changeset 2118:c5d0edf1d7e7

Fix some null-pointer dereference crashes on a ROM that abuses V28/V30 mode switching
author Michael Pavone <pavone@retrodev.com>
date Sun, 06 Mar 2022 22:36:21 -0800
parents 03304d350339
children 5ec2f97365a2
files vdp.c
diffstat 1 files changed, 94 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/vdp.c	Sun Mar 06 22:30:47 2022 -0800
+++ b/vdp.c	Sun Mar 06 22:36:21 2022 -0800
@@ -527,7 +527,7 @@
 	       context->regs[REG_MODE_1], context->regs[REG_MODE_1] & BIT_HINT_EN ? "enabled" : "disabled", (context->regs[REG_MODE_1] & BIT_PAL_SEL) != 0,
 	           context->regs[REG_MODE_1] & BIT_HVC_LATCH ? "enabled" : "disabled", context->regs[REG_MODE_1] & BIT_DISP_DIS ? "disabled" : "enabled",
 	       context->regs[REG_MODE_2], context->regs[REG_MODE_2] & BIT_DISP_EN ? "enabled" : "disabled", context->regs[REG_MODE_2] & BIT_VINT_EN ? "enabled" : "disabled",
-	           context->regs[REG_MODE_2] & BIT_PAL ? 30 : 28, context->regs[REG_MODE_2] & BIT_MODE_5 ? 5 : 4, context->regs[REG_MODE_1] & BIT_128K_VRAM ? 128 : 64, 
+	           context->regs[REG_MODE_2] & BIT_PAL ? 30 : 28, context->regs[REG_MODE_2] & BIT_MODE_5 ? 5 : 4, context->regs[REG_MODE_1] & BIT_128K_VRAM ? 128 : 64,
 	       context->regs[REG_MODE_3], context->regs[REG_MODE_3] & BIT_EINT_EN ? "enabled" : "disabled", context->regs[REG_MODE_3] & BIT_VSCROLL ? "2 cell" : "full",
 	           hscroll[context->regs[REG_MODE_3] & 0x3],
 	       context->regs[REG_MODE_4], context->regs[REG_MODE_4] & BIT_H40 ? 40 : 32, context->regs[REG_MODE_4] & BIT_HILIGHT ? "enabled" : "disabled");
@@ -555,7 +555,7 @@
 			   context->regs[REG_STILE_BASE], (context->regs[REG_STILE_BASE] & 2) << 11,
 			   context->regs[REG_X_SCROLL], context->regs[REG_X_SCROLL],
 			   context->regs[REG_Y_SCROLL], context->regs[REG_Y_SCROLL]);
-			   
+
 	}
 	char * sizes[] = {"32", "64", "invalid", "128"};
 	printf("\n**Misc Group**\n"
@@ -592,11 +592,11 @@
 		   "VINT Pending: %s\n"
 		   "HINT Pending: %s\n"
 		   "Status: %X\n",
-	       context->address, context->cd, cd_name(context->cd), 
+	       context->address, context->cd, cd_name(context->cd),
 		   (context->flags & FLAG_PENDING) ? "word" : (context->flags2 & FLAG2_BYTE_PENDING) ? "byte" : "none",
 		   context->vcounter, context->hslot*2, (context->flags2 & FLAG2_VINT_PENDING) ? "true" : "false",
 		   (context->flags2 & FLAG2_HINT_PENDING) ? "true" : "false", vdp_control_port_read(context));
-	printf("\nDebug Register: %X | Output disabled: %s, Force Layer: %d\n", context->test_port, 
+	printf("\nDebug Register: %X | Output disabled: %s, Force Layer: %d\n", context->test_port,
 		(context->test_port & TEST_BIT_DISABLE)  ? "true" : "false", context->test_port >> 7 & 3
 	);
 	//restore flags as calling vdp_control_port_read can change them
@@ -673,11 +673,11 @@
 	if (context->sprite_index < MAX_SPRITES_FRAME_H32) {
 		uint32_t line = context->vcounter;
 		line &= 0xFF;
-		
+
 		uint32_t sat_address = mode4_address_map[(context->regs[REG_SAT] << 7 & 0x3F00) + context->sprite_index];
 		uint32_t y = context->vdpmem[sat_address+1];
 		uint32_t size = (context->regs[REG_MODE_2] & BIT_SPRITE_SZ) ? 16 : 8;
-		
+
 		if (y == 0xd0) {
 			context->sprite_index = MAX_SPRITES_FRAME_H32;
 			return;
@@ -694,7 +694,7 @@
 			}
 			context->sprite_index++;
 		}
-		
+
 		if (context->sprite_index < MAX_SPRITES_FRAME_H32) {
 			y = context->vdpmem[sat_address];
 			if (y == 0xd0) {
@@ -714,7 +714,7 @@
 				context->sprite_index++;
 			}
 		}
-		
+
 	}
 }
 
@@ -824,9 +824,9 @@
 		value = (value << 1 & 0xE) | (value << 2 & 0xE0) | (value & 0xE00);
 	}
 	write_cram_internal(context, addr, value);
-	
+
 	if (context->output && context->hslot >= BG_START_SLOT && (
-		context->vcounter < context->inactive_start + context->border_bot 
+		context->vcounter < context->inactive_start + context->border_bot
 		|| context->vcounter > 0x200 - context->border_top
 	)) {
 		uint8_t bg_end_slot = BG_START_SLOT + (context->regs[REG_MODE_4] & BIT_H40) ? LINEBUF_SIZE/2 : (256+HORIZ_BORDER)/2;
@@ -984,14 +984,14 @@
 	} else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_COPY) {
 		if (context->flags & FLAG_READ_FETCHED) {
 			write_vram_byte(context, context->address ^ 1, context->prefetch);
-			
+
 			//Update DMA state
 			vdp_advance_dma(context);
-			
+
 			context->flags &= ~FLAG_READ_FETCHED;
 		} else {
 			context->prefetch = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1];
-			
+
 			context->flags |= FLAG_READ_FETCHED;
 		}
 	} else if (!(context->cd & 1) && !(context->flags & FLAG_READ_FETCHED)) {
@@ -1289,7 +1289,7 @@
 	if (context->col_1 & 0x400) {
 		vscroll = 7 - vscroll;
 	}
-	
+
 	uint32_t address = mode4_address_map[((context->col_1 & 0x1FF) * 32) + vscroll * 4];
 	context->fetch_tmp[0] = context->vdpmem[address];
 	context->fetch_tmp[1] = context->vdpmem[address+1];
@@ -1480,7 +1480,7 @@
 					}
 					break;
 				}
-				
+
 				*(dst++) = pixel;
 				*(debug_dst++) = src;
 			}
@@ -1554,7 +1554,7 @@
 				}
 				break;
 			}
-			
+
 			*(dst++) = SHADOW_OFFSET + pixel;
 			*(debug_dst++) = src;
 		}
@@ -1637,8 +1637,8 @@
 		col-=2;
 		dst = context->compositebuf + BORDER_LEFT + col * 8;
 		debug_dst = context->layer_debug_buf + BORDER_LEFT + col * 8;
-		
-		
+
+
 		uint8_t a_src, src;
 		uint8_t *buf_a;
 		int plane_a_mask;
@@ -1698,7 +1698,7 @@
 				int i;
 				i = 0;
 				uint8_t buf_off = context->buf_a_off - context->hscroll_a_fine + (16 - BORDER_LEFT);
-				//uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); 
+				//uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK);
 				for (; i < BORDER_LEFT; buf_off++, i++, dst++, debug_dst++)
 				{
 					*dst = context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK];
@@ -1711,7 +1711,7 @@
 				int i;
 				i = 0;
 				uint8_t buf_off = context->buf_b_off - context->hscroll_b_fine + (16 - BORDER_LEFT);
-				//uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); 
+				//uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK);
 				for (; i < BORDER_LEFT; buf_off++, i++, dst++, debug_dst++)
 				{
 					*dst = context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK];
@@ -1745,14 +1745,14 @@
 		//vflip
 		vscroll = 7 - vscroll;
 	}
-	
+
 	uint32_t pixels = planar_to_chunky[context->fetch_tmp[0]] << 1;
 	pixels |=  planar_to_chunky[context->fetch_tmp[1]];
-	
+
 	uint32_t address = mode4_address_map[((context->col_1 & 0x1FF) * 32) + vscroll * 4 + 2];
 	pixels |= planar_to_chunky[context->vdpmem[address]] << 3;
 	pixels |= planar_to_chunky[context->vdpmem[address+1]] << 2;
-	
+
 	int i, i_inc, i_limit;
 	if (context->col_1 & 0x200) {
 		//hflip
@@ -1770,7 +1770,7 @@
 		*dst = (pixels >> i & 0xF) | pal_priority;
 	}
 	context->buf_a_off = (context->buf_a_off + 8) & 15;
-	
+
 	uint8_t *dst = context->compositebuf + col * 8 + BORDER_LEFT;
 	uint8_t *debug_dst = context->layer_debug_buf + col * 8 + BORDER_LEFT;
 	if (context->state == PREPARING) {
@@ -1779,7 +1779,7 @@
 		context->done_composite = dst + 8;
 		return;
 	}
-	
+
 	if (col || !(context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
 		uint8_t *sprite_src = context->linebuf + col * 8;
 		if (context->regs[REG_MODE_1] & BIT_SPRITE_8PX) {
@@ -1850,7 +1850,7 @@
 			line -= jump_end - jump_start;
 		}
 		uint32_t total_lines = (context->flags2 & FLAG2_REGION_PAL) ? 313 : 262;
-		
+
 		if (total_lines - line <= context->border_top) {
 			line -= total_lines - context->border_top;
 		} else {
@@ -1887,7 +1887,7 @@
 			}
 		}
 	}
-	
+
 	context->vcounter++;
 	if (context->vcounter == jump_start) {
 		context->vcounter = jump_end;
@@ -1974,7 +1974,7 @@
 				//
 				uint16_t entry = context->vdpmem[address] << 8 | context->vdpmem[address + 1];
 				uint8_t pal = entry >> 9 & 0x30;
-				
+
 				uint32_t *dst = fb + (row * pitch * 8 / sizeof(uint32_t)) + col * 8;
 				address = (entry & 0x7FF) * 32;
 				int y_diff = 4;
@@ -2013,11 +2013,11 @@
 		}
 		render_framebuffer_updated(context->debug_fb_indices[VDP_DEBUG_PLANE], 1024);
 	}
-	
+
 	if (context->enabled_debuggers & (1 << VDP_DEBUG_VRAM)) {
 		uint32_t pitch;
 		uint32_t *fb = render_get_framebuffer(context->debug_fb_indices[VDP_DEBUG_VRAM], &pitch);
-		
+
 		uint8_t pal = (context->debug_modes[VDP_DEBUG_VRAM] % 4) << 4;
 		for (int y = 0; y < 512; y++)
 		{
@@ -2039,13 +2039,13 @@
 				}
 			}
 		}
-		
+
 		render_framebuffer_updated(context->debug_fb_indices[VDP_DEBUG_VRAM], 1024);
 	}
-	
+
 	if (context->enabled_debuggers & (1 << VDP_DEBUG_CRAM)) {
 		uint32_t starting_line = 512 - 32*4;
-		uint32_t *line = context->debug_fbs[VDP_DEBUG_CRAM] 
+		uint32_t *line = context->debug_fbs[VDP_DEBUG_CRAM]
 			+ context->debug_fb_pitch[VDP_DEBUG_CRAM]  * starting_line / sizeof(uint32_t);
 		if (context->regs[REG_MODE_2] & BIT_MODE_5) {
 			for (int pal = 0; pal < 4; pal ++)
@@ -2102,7 +2102,7 @@
 	if (context->enabled_debuggers & (1 << VDP_DEBUG_COMPOSITE)) {
 		render_framebuffer_updated(context->debug_fb_indices[VDP_DEBUG_COMPOSITE], LINEBUF_SIZE);
 		context->debug_fbs[VDP_DEBUG_COMPOSITE] = render_get_framebuffer(context->debug_fb_indices[VDP_DEBUG_COMPOSITE], &context->debug_fb_pitch[VDP_DEBUG_COMPOSITE]);
-	}		
+	}
 }
 
 void vdp_force_update_framebuffer(vdp_context *context)
@@ -2111,7 +2111,7 @@
 		return;
 	}
 	uint16_t lines_max = context->inactive_start + context->border_bot + context->border_top;
-			
+
 	uint16_t to_fill = lines_max - context->output_lines;
 	memset(
 		((char *)context->fb) + context->output_pitch * context->output_lines,
@@ -2131,8 +2131,8 @@
 	if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
 		//vcounter increment occurs much later in Mode 4
 		output_line++;
-	} 
-	
+	}
+
 	if (context->output_lines >= lines_max || (!context->pushed_frame && output_line == context->inactive_start + context->border_top)) {
 		//we've either filled up a full frame or we're at the bottom of screen in the current defined mode + border crop
 		if (!headless) {
@@ -2150,7 +2150,7 @@
 		context->frame++;
 		context->output_lines = 0;
 	}
-	
+
 	if (output_line < context->inactive_start + context->border_bot) {
 		if (context->output_lines) {
 			output_line = context->output_lines++;//context->border_top + context->vcounter;
@@ -2184,7 +2184,7 @@
 	{
 		context->output[i] = 0xFFFF00FF;
 	}
-#endif	
+#endif
 	if (context->output && (context->regs[REG_MODE_4] & BIT_H40)) {
 		context->h40_lines++;
 	}
@@ -2241,7 +2241,7 @@
 				int i;
 				i = 0;
 				uint8_t buf_off = context->buf_a_off - context->hscroll_a_fine;
-				//uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); 
+				//uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK);
 				for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
 				{
 					*dst = context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK] & 0x3F;
@@ -2253,7 +2253,7 @@
 				int i;
 				i = 0;
 				uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF);
-				//uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); 
+				//uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK);
 				for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
 				{
 					*dst = context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK] & 0x3F;
@@ -2286,7 +2286,7 @@
 			*(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\
 		}\
 	}
-	
+
 #define OUTPUT_PIXEL_H40(slot) if (slot <= (BG_START_SLOT + LINEBUF_SIZE/2)) {\
 		uint8_t *src = context->compositebuf + (slot - BG_START_SLOT) *2;\
 		uint32_t *dst = context->output + (slot - BG_START_SLOT) *2;\
@@ -2303,7 +2303,7 @@
 			}\
 		}\
 	}
-	
+
 #define OUTPUT_PIXEL_H32(slot) if (slot <= (BG_START_SLOT + (256+HORIZ_BORDER)/2)) {\
 		uint8_t *src = context->compositebuf + (slot - BG_START_SLOT) *2;\
 		uint32_t *dst = context->output + (slot - BG_START_SLOT) *2;\
@@ -2320,7 +2320,7 @@
 			}\
 		}\
 	}
-	
+
 //BG_START_SLOT => dst = 0, src = border
 //BG_START_SLOT + 13/2=6, dst = 6, src = border + comp + 13
 #define OUTPUT_PIXEL_MODE4(slot) if ((slot) >= BG_START_SLOT) {\
@@ -2414,7 +2414,7 @@
 		OUTPUT_PIXEL((startcyc+7)&0xFF)\
 		render_map_output(context->vcounter, column, context);\
 		CHECK_LIMIT
-		
+
 #define COLUMN_RENDER_BLOCK_MODE4(column, startcyc) \
 	case startcyc:\
 		OUTPUT_PIXEL_MODE4(startcyc)\
@@ -2436,7 +2436,7 @@
 		OUTPUT_PIXEL_MODE4((startcyc+3)&0xFF)\
 		render_map_mode4(context->vcounter, column, context);\
 		CHECK_LIMIT
-		
+
 #define CHECK_LIMIT_HSYNC(slot) \
 	if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
 	if (slot >= HSYNC_SLOT_H40 && slot < HSYNC_END_H40) {\
@@ -2523,7 +2523,7 @@
 		}\
 		context->cycles += slot_cycles;\
 		CHECK_ONLY
-		
+
 #define MODE4_CHECK_SLOT_LINE(slot) \
 		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
 		if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\
@@ -2547,7 +2547,7 @@
 		CHECK_ONLY
 
 #define CALC_SLOT(slot, increment) ((slot+increment) > 147 && (slot+increment) < 233 ? (slot+increment-148+233): (slot+increment))
-		
+
 #define SPRITE_RENDER_H32_MODE4(slot) \
 	case slot:\
 		OUTPUT_PIXEL_MODE4(slot)\
@@ -2582,7 +2582,7 @@
 	uint32_t const slot_cycles = MCLKS_SLOT_H40;
 	uint8_t bgindex = context->regs[REG_BG_COLOR] & 0x3F;
 	uint8_t test_layer = context->test_port >> 7 & 3;
-	
+
 	//165
 	if (!(context->regs[REG_MODE_3] & BIT_VSCROLL)) {
 		//TODO: Develop some tests on hardware to see when vscroll latch actually happens for full plane mode
@@ -2614,21 +2614,24 @@
 		context->buf_b_off + 8,
 		context->col_2
 	);
+
 	//Do palette lookup for end of previous line
 	uint8_t *src = context->compositebuf + (LINE_CHANGE_H40 - BG_START_SLOT) *2;
 	uint32_t *dst = context->output + (LINE_CHANGE_H40 - BG_START_SLOT) *2;
-	if (test_layer) {
-		for (int i = 0; i < LINEBUF_SIZE - (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++)
-		{
-			*(dst++) = context->colors[*(src++)];
-		}
-	} else {
-		for (int i = 0; i < LINEBUF_SIZE - (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++)
-		{
-			if (*src & 0x3F) {
+	if (context->output) {
+		if (test_layer) {
+			for (int i = 0; i < LINEBUF_SIZE - (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++)
+			{
 				*(dst++) = context->colors[*(src++)];
-			} else {
-				*(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];
+			}
+		} else {
+			for (int i = 0; i < LINEBUF_SIZE - (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++)
+			{
+				if (*src & 0x3F) {
+					*(dst++) = context->colors[*(src++)];
+				} else {
+					*(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];
+				}
 			}
 		}
 	}
@@ -2752,6 +2755,9 @@
 	context->cycles += MCLKS_LINE;
 	vdp_advance_line(context);
 	src = context->compositebuf;
+	if (!context->output) {
+		return;
+	}
 	dst = context->output;
 	if (test_layer) {
 		for (int i = 0; i < (LINE_CHANGE_H40 - BG_START_SLOT) * 2; i++)
@@ -2792,6 +2798,11 @@
 				vdp_h40_line(context);
 			}
 			CHECK_ONLY
+			if (!context->output) {
+				//This shouldn't happen normally, but it can theoretically
+				//happen when doing border busting
+				context->output = dummy_buffer;
+			}
 		}
 		OUTPUT_PIXEL(165)
 		if (!(context->regs[REG_MODE_3] & BIT_VSCROLL)) {
@@ -3405,7 +3416,7 @@
 	uint8_t buf_clear_slot, index_reset_slot, bg_end_slot, vint_slot, line_change, jump_start, jump_dest, latch_slot;
 	uint8_t index_reset_value, max_draws, max_sprites;
 	uint16_t vint_line, active_line;
-	
+
 	if (mode_5) {
 		if (is_h40) {
 			latch_slot = 165;
@@ -3465,9 +3476,9 @@
 	} else {
 		dst = NULL;
 	}
-		
+
 	uint8_t test_layer = context->test_port >> 7 & 3;
-	
+
 	while(context->cycles < target_cycles)
 	{
 		check_switch_inactive(context, is_h40);
@@ -3478,7 +3489,7 @@
 			advance_output_line(context);
 			dst = NULL;
 		}
-		//this will need some tweaking to properly interact with 128K mode, 
+		//this will need some tweaking to properly interact with 128K mode,
 		//but this should be good enough for now
 		context->serial_address += 1024;
 		if (test_layer) {
@@ -3501,7 +3512,7 @@
 				break;
 			}
 		}
-		
+
 		if (context->hslot == buf_clear_slot) {
 			if (mode_5) {
 				context->cur_slot = max_draws;
@@ -3515,7 +3526,7 @@
 			context->slot_counter = mode_5 ? 0 : max_sprites;
 		} else if (context->hslot == latch_slot) {
 			//it seems unlikely to me that vscroll actually gets latched when the display is off
-			//but it's the only straightforward way to reconcile what I'm seeing between Skitchin 
+			//but it's the only straightforward way to reconcile what I'm seeing between Skitchin
 			//(which seems to expect vscroll to be latched early) and the intro of Gunstar Heroes
 			//(which disables the display and ends up with garbage if vscroll is latched during that period)
 			//without it. Some more tests are definitely needed
@@ -3527,7 +3538,7 @@
 		} else if (context->vcounter == context->inactive_start && context->hslot == 1 && (context->regs[REG_MODE_4] & BIT_INTERLACE)) {
 			context->flags2 ^= FLAG2_EVEN_FIELD;
 		}
-		
+
 		if (dst) {
 			uint8_t bg_index;
 			uint32_t bg_color;
@@ -3568,7 +3579,7 @@
 				*(dst++) = bg_color;
 				*(debug_dst++) = DBG_SRC_BG;
 			}
-			
+
 			if (context->hslot == (bg_end_slot-1)) {
 				if (context->done_composite) {
 					uint8_t pixel = context->compositebuf[dst-context->output];
@@ -3586,14 +3597,14 @@
 				}
 			}
 		}
-		
+
 		if (!is_refresh(context, context->hslot)) {
 			external_slot(context);
 			if (context->flags & FLAG_DMA_RUN && !is_refresh(context, context->hslot)) {
 				run_dma_src(context, context->hslot);
 			}
 		}
-		
+
 		if (is_h40) {
 			if (context->hslot >= HSYNC_SLOT_H40 && context->hslot < HSYNC_END_H40) {
 				context->cycles += h40_hsync_cycles[context->hslot - HSYNC_SLOT_H40];
@@ -3625,7 +3636,7 @@
 	while(context->cycles < target_cycles)
 	{
 		check_switch_inactive(context, is_h40);
-		
+
 		if (is_active(context)) {
 			if (mode_5) {
 				if (is_h40) {
@@ -3671,7 +3682,7 @@
 		}
 		uint32_t min_dma_complete = dmalen * (context->regs[REG_MODE_4] & BIT_H40 ? 16 : 20);
 		if (
-			(context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_COPY 
+			(context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_COPY
 			|| (((context->cd & 0xF) == VRAM_WRITE) && !(context->regs[REG_MODE_2] & BIT_128K_VRAM))) {
 			//DMA copies take twice as long to complete since they require a read and a write
 			//DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word
@@ -3724,7 +3735,7 @@
 		hv = context->hv_latch & 0xFF;
 	}
 	hv |= get_ext_vcounter(context);
-	
+
 	return hv;
 }
 
@@ -3732,7 +3743,7 @@
 {
 	context->flags &= ~FLAG_PENDING;
 	context->address = context->address_latch;
-	//It seems like the DMA enable bit doesn't so much enable DMA so much 
+	//It seems like the DMA enable bit doesn't so much enable DMA so much
 	//as it enables changing CD5 from control port writes
 	if (context->regs[REG_MODE_2] & BIT_DMA_ENABLE) {
 		context->cd = context->cd_latch;
@@ -4048,7 +4059,7 @@
 	}
 	context->flags &= ~FLAG_READ_FETCHED;
 	context->flags2 &= ~FLAG2_BYTE_PENDING;
-		
+
 	context->cd = VRAM_READ8;
 	return context->prefetch;
 }
@@ -4266,7 +4277,7 @@
 						if (context->hslot < 183) {
 							cycles += (183 - context->hslot) * MCLKS_SLOT_H40;
 						}
-						
+
 						if (context->hslot < HSYNC_SLOT_H40) {
 							cycles += (HSYNC_SLOT_H40 - (context->hslot >= 229 ? context->hslot : 229)) * MCLKS_SLOT_H40;
 						}
@@ -4276,7 +4287,7 @@
 						}
 						cycles += (256 - (context->hslot > HSYNC_END_H40 ? context->hslot : HSYNC_END_H40)) * MCLKS_SLOT_H40;
 					}
-					
+
 					cycles += (VINT_SLOT_H40 - (context->hslot >= LINE_CHANGE_H40 ? 0 : context->hslot)) * MCLKS_SLOT_H40;
 					return cycles;
 				}
@@ -4331,7 +4342,7 @@
 	//CPU interrupt acknowledge is only used in Mode 5
 	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
 		//Apparently the VDP interrupt controller is not very smart
-		//Instead of paying attention to what interrupt is being acknowledged it just 
+		//Instead of paying attention to what interrupt is being acknowledged it just
 		//clears the pending flag for whatever interrupt it is currently asserted
 		//which may be different from the interrupt it was asserting when the 68k
 		//started the interrupt process. The window for this is narrow and depends
@@ -4421,7 +4432,7 @@
 		save_int16(buf, info->y);
 	}
 	save_buffer8(buf, context->linebuf, LINEBUF_SIZE);
-	
+
 	save_int32(buf, context->cycles);
 	save_int32(buf, context->pending_vint_start);
 	save_int32(buf, context->pending_hint_start);
@@ -4517,12 +4528,12 @@
 				draw->h_flip = load_int8(buf);
 				draw->width = 1;
 				draw->height = 8;
-				
+
 				if (last && last->width < 4 && last->h_flip == draw->h_flip && last->pal_priority == draw->pal_priority) {
 					int adjust_x = draw->x_pos + draw->h_flip ? -8 : 8;
 					int height = draw->address - last->address /4;
 					if (last->x_pos == adjust_x && (
-						(last->width > 1 && height == last->height) || 
+						(last->width > 1 && height == last->height) ||
 						(last->width == 1 && (height == 8 || height == 16 || height == 24 || height == 32))
 					)) {
 						//current draw appears to be part of the same sprite as the last one, combine it
@@ -4557,7 +4568,7 @@
 		info->y = load_int16(buf);
 	}
 	load_buffer8(buf, context->linebuf, LINEBUF_SIZE);
-	
+
 	context->cycles = load_int32(buf);
 	context->pending_vint_start = load_int32(buf);
 	context->pending_hint_start = load_int32(buf);
@@ -4682,7 +4693,7 @@
 		address = load_int8(buffer);
 		break;
 	}
-	
+
 	switch (event)
 	{
 	case EVENT_VDP_REG: {