Skip to content

Commit 92f4376

Browse files
committed
[code] Add hardware cursor support for no-DMA frame drawing
1 parent a337cf9 commit 92f4376

File tree

1 file changed

+56
-3
lines changed

1 file changed

+56
-3
lines changed

core/lcd.c

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,57 @@ static inline void lcd_crsr_update(void) {
8787
}
8888
}
8989

90+
static inline uint8_t lcd_crsr_pixel(uint32_t crsrOffset) {
91+
return lcd.crsrImageBytes[crsrOffset >> 2] >> ((~crsrOffset & 3) * 2) & 3;
92+
}
93+
94+
static void lcd_drawcrsr(void *output, uint32_t rowWidth, lcd_crsr_state_t *crsrRegs, bool crsrIsLarge, uint32_t size) {
95+
uint32_t crsrSize = (crsrIsLarge + 1) * 32;
96+
uint32_t crsrClipX = crsrRegs->crsrClip & 0xFF;
97+
uint32_t crsrClipY = crsrRegs->crsrClip >> 8;
98+
if ((crsrClipX | crsrClipY) >= crsrSize) {
99+
return;
100+
}
101+
uint32_t crsrCol = crsrRegs->crsrXY & 0xFFFF;
102+
if (crsrCol >= rowWidth) {
103+
return;
104+
}
105+
uint32_t crsrWidth = crsrSize - crsrClipX;
106+
if (crsrWidth > rowWidth - crsrCol) {
107+
crsrWidth = rowWidth - crsrCol;
108+
}
109+
uint32_t crsrHeight = crsrSize - crsrClipY;
110+
uint32_t crsrRow = crsrRegs->crsrXY >> 16;
111+
uint32_t crsrRowOffset = ((crsrRegs->crsrImage * crsrSize + crsrClipY) * crsrSize + crsrClipX) & 0xFFF;
112+
uint32_t *out = output;
113+
uint32_t outRowOffset = crsrRow * rowWidth + crsrCol;
114+
uint32_t crsrPalette[4] = {
115+
lcd_rgb888out(lcd_bgr888swap(lcd.crsrPalette0, 0xFF)),
116+
lcd_rgb888out(lcd_bgr888swap(lcd.crsrPalette1, 0xFF)),
117+
0x000000,
118+
0xFFFFFF
119+
};
120+
do {
121+
if (outRowOffset >= size) {
122+
return;
123+
}
124+
uint32_t i = crsrWidth;
125+
if (i > size - outRowOffset) {
126+
i = size - outRowOffset;
127+
}
128+
uint32_t crsrOffset = crsrRowOffset;
129+
uint32_t *outPtr = out + outRowOffset;
130+
do {
131+
uint8_t pixel = lcd_crsr_pixel(crsrOffset);
132+
*outPtr = (pixel & 2 ? *outPtr : 0) ^ crsrPalette[pixel];
133+
crsrOffset++;
134+
outPtr++;
135+
} while (--i);
136+
crsrRowOffset += crsrSize;
137+
outRowOffset += rowWidth;
138+
} while (--crsrHeight);
139+
}
140+
90141
void emu_set_lcd_callback(bool (*callback)(void*), void *data) {
91142
lcd.gui_callback = callback;
92143
lcd.gui_callback_data = data;
@@ -106,6 +157,9 @@ void emu_lcd_drawframe(void *output) {
106157
memcpy(output, panel.display, sizeof(panel.display));
107158
} else if (lcd.control & 1 << 11) {
108159
emu_lcd_drawmem(output, lcd.data, lcd.data_end, lcd.control, LCD_SIZE);
160+
if (unlikely(lcd.crsrControl)) {
161+
lcd_drawcrsr(output, lcd.CPL, &lcd.crsrRegs[1], lcd.crsrConfig & 1, LCD_SIZE);
162+
}
109163
}
110164
}
111165

@@ -226,8 +280,7 @@ static uint32_t lcd_process_pixel(uint32_t ticks, uint16_t bgr565) {
226280
assert(lcd.curCol < lcd.CPL);
227281
uint32_t crsrColOffset = lcd.curCol - lcd.curCrsrCol;
228282
if (unlikely(crsrColOffset < lcd.curCrsrWidth)) {
229-
uint32_t crsrOffset = lcd.curCrsrOffset + crsrColOffset;
230-
uint8_t crsrPixel = lcd.crsrImageBytes[crsrOffset >> 2] >> ((~crsrOffset & 3) * 2) & 3;
283+
uint8_t crsrPixel = lcd_crsr_pixel(lcd.curCrsrOffset + crsrColOffset);
231284
bgr565 = (crsrPixel & 2 ? bgr565 : 0) ^ lcd.crsrPalette[crsrPixel];
232285
}
233286
panel.clock_pixel(bgr565);
@@ -490,7 +543,7 @@ static uint8_t lcd_read(const uint16_t pio, bool peek) {
490543
if (index >= 0x800) { return lcd.crsrImageBytes[index - 0x800]; }
491544
} else if (index < 0xE00) {
492545
if (!peek) {
493-
cpu.cycles--;
546+
sched_rewind_cpu(1); /* safely handle underflow */
494547
}
495548
if (index == 0xC00) { return lcd.crsrControl | (lcd.crsrRegs[0].crsrImage << 4); }
496549
if (index == 0xC04) { return lcd.crsrConfig; }

0 commit comments

Comments
 (0)