@@ -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+
90141void 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