changeset 927:f2e4fdb0e663

Merge
author Michael Pavone <pavone@retrodev.com>
date Tue, 02 Feb 2016 22:24:49 -0800
parents b290343e5664 (diff) a3b08915624b (current diff)
children 8bd82aead087
files
diffstat 3 files changed, 215 insertions(+), 232 deletions(-) [+]
line wrap: on
line diff
--- a/analyze_olp.py	Mon Jan 25 09:37:27 2016 -0800
+++ b/analyze_olp.py	Tue Feb 02 22:24:49 2016 -0800
@@ -20,9 +20,16 @@
 	return not sample & mask
 
 def analyze_delays(chanmap, datafile):
-	m68k_clk = chanmap['M68K CLK']
+	if 'M68K_CLK' in chanmap:
+		m68k_clk = chanmap['M68K CLK']
+	elif 'CLK' in chanmap:
+		m68k_clk = chanmap['CLK']
 	m_as = chanmap['!AS']
+	ram_oe = chanmap['RAM !LOE/!RFSH']
+	ram_ce = chanmap['RAM !CE']
 	last = False
+	prev = False
+	prevRefresh = False
 	clks = 0
 	as_start = 0
 	for line in datafile.readlines():
@@ -36,10 +43,47 @@
 				if detect_rise(last, sample, m_as):
 					as_clks  = clks - as_start
 					if as_clks > 2:
-						print '!AS held for', as_clks, 'cycles starting (delay of ' + str(as_clks - 2) + ') at', as_start, 'and ending at', clks
+						if not (prev is False):
+							print '!AS held for', as_clks, 'cycles starting (delay of ' + str(as_clks - 2) + ') at', as_start, 'and ending at', clks, 'delta since last delay:', as_start - prev
+						else:
+							print '!AS held for', as_clks, 'cycles starting (delay of ' + str(as_clks - 2) + ') at', as_start, 'and ending at', clks
+						prev = as_start
 				elif detect_fall(last, sample, m_as):
 					as_start = clks
+				if detect_fall(last, sample, ram_oe) and detect_high( sample, ram_ce):
+					if prevRefresh is False:
+						print 'RAM refresh at ', clks
+					else:
+						print 'RAM refresh at', clks, 'delta since last:', clks-prevRefresh
+					prevRefresh = clks
 			last = sample
+			
+def analyze_refresh(chanmap, datafile):
+	if 'M68K_CLK' in chanmap:
+		m68k_clk = chanmap['M68K CLK']
+	elif 'CLK' in chanmap:
+		m68k_clk = chanmap['CLK']
+	ram_oe = chanmap['RAM !LOE/!RFSH']
+	ram_ce = chanmap['RAM !CE']
+	clks = 0
+	last = False
+	prevRefresh = False
+	for line in datafile.readlines():
+		line = line.strip()
+		if line and not line.startswith(';'):
+			sample,_,num = line.partition('@')
+			sample = int(sample, 16)
+			if not (last is False):
+				if detect_rise(last, sample, m68k_clk):
+					clks = clks + 1
+				if detect_fall(last, sample, ram_oe) and detect_high( sample, ram_ce):
+					if prevRefresh is False:
+						print 'RAM refresh at ', clks
+					else:
+						print 'RAM refresh at', clks, 'delta since last:', clks-prevRefresh
+					prevRefresh = clks
+			last = sample
+				
 
 def main(args):
 	if len(args) < 2:
@@ -49,12 +93,15 @@
 	channelfile = olpfile.open('channel.labels')
 	channels = [line.strip() for line in channelfile.readlines()]
 	channelfile.close()
+	print channels
 	chanmap = {}
 	for i in xrange(0, len(channels)):
 		chanmap[channels[i]] = i
 	datafile = olpfile.open('data.ols')
 	analyze_delays(chanmap, datafile)
-
+	datafile.close()
+	#datafile = olpfile.open('data.ols')
+	#analyze_refresh(chanmap, datafile)
 
 if __name__ == '__main__':
 	main(argv)
--- a/vdp.c	Mon Jan 25 09:37:27 2016 -0800
+++ b/vdp.c	Tue Feb 02 22:24:49 2016 -0800
@@ -24,7 +24,7 @@
 #define MCLKS_SLOT_H32  20
 #define VINT_SLOT_H40  4 //21 slots before HSYNC, 16 during, 10 after
 #define VINT_SLOT_H32  4  //old value was 23, but recent tests suggest the actual value is close to the H40 one
-#define HSYNC_SLOT_H40  234
+#define HSYNC_SLOT_H40  228
 #define HSYNC_END_H40  (HSYNC_SLOT_H40+17)
 #define HSYNC_END_H32   (33 * MCLKS_SLOT_H32)
 #define HBLANK_START_H40 178 //should be 179 according to Nemesis, but 178 seems to fit slightly better with my test ROM results
@@ -514,7 +514,7 @@
 	}
 }
 
-void run_dma_src(vdp_context * context, uint32_t slot)
+void run_dma_src(vdp_context * context, int32_t slot)
 {
 	//TODO: Figure out what happens if CD bit 4 is not set in DMA copy mode
 	//TODO: Figure out what happens when CD:0-3 is not set to a write mode in DMA operations
@@ -528,7 +528,7 @@
 	//68K -> VDP
 	case 0:
 	case 0x40:
-		if (!slot || !is_refresh(context, slot-1)) {
+		if (slot == -1 || !is_refresh(context, slot-1)) {
 			cur = context->fifo + context->fifo_write;
 			cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
 			cur->address = context->address;
@@ -975,31 +975,31 @@
 }
 
 #define CHECK_ONLY if (context->cycles >= target_cycles) { return; }
-#define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY
+#define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY
 
 #define COLUMN_RENDER_BLOCK(column, startcyc) \
 	case startcyc:\
 		read_map_scroll_a(column, context->vcounter, context);\
 		CHECK_LIMIT\
-	case (startcyc+1):\
+	case ((startcyc+1)&0xFF):\
 		external_slot(context);\
 		CHECK_LIMIT\
-	case (startcyc+2):\
+	case ((startcyc+2)&0xFF):\
 		render_map_1(context);\
 		CHECK_LIMIT\
-	case (startcyc+3):\
+	case ((startcyc+3)&0xFF):\
 		render_map_2(context);\
 		CHECK_LIMIT\
-	case (startcyc+4):\
+	case ((startcyc+4)&0xFF):\
 		read_map_scroll_b(column, context->vcounter, context);\
 		CHECK_LIMIT\
-	case (startcyc+5):\
+	case ((startcyc+5)&0xFF):\
 		read_sprite_x(context->vcounter, context);\
 		CHECK_LIMIT\
-	case (startcyc+6):\
+	case ((startcyc+6)&0xFF):\
 		render_map_3(context);\
 		CHECK_LIMIT\
-	case (startcyc+7):\
+	case ((startcyc+7)&0xFF):\
 		render_map_output(context->vcounter, column, context);\
 		CHECK_LIMIT
 
@@ -1029,19 +1029,16 @@
 		CHECK_LIMIT\
 	case (startcyc+7):\
 		render_map_output(context->vcounter, column, context);\
-		if (column == 40 || (column == 32 && startcyc == 124)) {\
-			vdp_advance_line(context);\
-		}\
 		CHECK_LIMIT
 
 #define SPRITE_RENDER_H40(slot) \
 	case slot:\
 		render_sprite_cells( context);\
 		scan_sprite_table(context->vcounter, context);\
-		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); } \
+		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
 		if (slot == 182) {\
 			context->hslot = 229;\
-			context->cycles += slot_cycles;\
+			context->cycles += h40_hsync_cycles[0];\
 		} else {\
 			context->hslot++;\
 			if (slot >= HSYNC_SLOT_H40 && slot < HSYNC_END_H40) {\
@@ -1056,7 +1053,7 @@
 	case slot:\
 		render_sprite_cells( context);\
 		scan_sprite_table(context->vcounter, context);\
-		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); } \
+		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
 		if (slot == 147) {\
 			context->hslot = 233;\
 		} else {\
@@ -1075,55 +1072,21 @@
 	{
 	for (;;)
 	{
+	//sprite attribute table scan starts
 	case 165:
-		external_slot(context);
-		CHECK_LIMIT
-	case 166:
-		external_slot(context);
-		CHECK_LIMIT
-	//sprite render to line buffer starts
-	case 167:
-		context->cur_slot = MAX_DRAWS-1;
-		memset(context->linebuf, 0, LINEBUF_SIZE);
-		if (context->vcounter == 0x1FF) {
-			external_slot(context);
-		} else {
-			render_sprite_cells(context);
-		}
-		CHECK_LIMIT
-	case 168:
-		if (context->vcounter == 0x1FF) {
-			external_slot(context);
-		} else {
-			render_sprite_cells(context);
-		}
-		CHECK_LIMIT
-	case 169:
-		if (context->vcounter == 0x1FF) {
-			external_slot(context);
-		} else {
-			render_sprite_cells(context);
-		}
-		CHECK_LIMIT
-	case 170:
-		if (context->vcounter == 0x1FF) {
-			external_slot(context);
-		} else {
-			render_sprite_cells(context);
-			if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
-				context->hslot++;
-				context->cycles += slot_cycles;
-				return;
-			}
-		}
-		CHECK_LIMIT
-	//sprite attribute table scan starts
-	case 171:
 		context->sprite_index = 0x80;
 		context->slot_counter = MAX_SPRITES_LINE;
 		render_sprite_cells( context);
 		scan_sprite_table(context->vcounter, context);
 		CHECK_LIMIT
+	SPRITE_RENDER_H40(166)
+	SPRITE_RENDER_H40(167)
+	case 168:
+		external_slot(context);
+		CHECK_LIMIT
+	SPRITE_RENDER_H40(169)
+	SPRITE_RENDER_H40(170)
+	SPRITE_RENDER_H40(171)
 	SPRITE_RENDER_H40(172)
 	SPRITE_RENDER_H40(173)
 	SPRITE_RENDER_H40(174)
@@ -1134,13 +1097,13 @@
 	SPRITE_RENDER_H40(179)
 	SPRITE_RENDER_H40(180)
 	SPRITE_RENDER_H40(181)
+	//!HSYNC asserted
 	SPRITE_RENDER_H40(182)
 	SPRITE_RENDER_H40(229)
 	SPRITE_RENDER_H40(230)
 	SPRITE_RENDER_H40(231)
 	SPRITE_RENDER_H40(232)
 	SPRITE_RENDER_H40(233)
-	//!HSYNC asserted
 	SPRITE_RENDER_H40(234)
 	SPRITE_RENDER_H40(235)
 	SPRITE_RENDER_H40(236)
@@ -1149,13 +1112,7 @@
 	SPRITE_RENDER_H40(239)
 	SPRITE_RENDER_H40(240)
 	SPRITE_RENDER_H40(241)
-	SPRITE_RENDER_H40(242)
-	SPRITE_RENDER_H40(243)
-	SPRITE_RENDER_H40(244)
-	SPRITE_RENDER_H40(245)
-	SPRITE_RENDER_H40(246)
-	SPRITE_RENDER_H40(247)
-	case 248:
+	case 242:
 		address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
 		mask = 0;
 		if (context->regs[REG_MODE_3] & 0x2) {
@@ -1168,39 +1125,36 @@
 		context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
 		context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
 		//printf("%d: HScroll A: %d, HScroll B: %d\n", context->vcounter, context->hscroll_a, context->hscroll_b);
-		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); }
+		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); }
 		context->hslot++;
 		context->cycles += h40_hsync_cycles[14];
 		CHECK_ONLY
 	//!HSYNC high
-	SPRITE_RENDER_H40(249)
-	SPRITE_RENDER_H40(250)
-	SPRITE_RENDER_H40(251)
-	SPRITE_RENDER_H40(252)
-	case 253:
+	SPRITE_RENDER_H40(243)
+	SPRITE_RENDER_H40(244)
+	SPRITE_RENDER_H40(245)
+	SPRITE_RENDER_H40(246)
+	case 247:
 		read_map_scroll_a(0, context->vcounter, context);
 		CHECK_LIMIT
-	SPRITE_RENDER_H40(254)
-	case 255:
+	SPRITE_RENDER_H40(248)
+	case 249:
 		render_map_1(context);
 		scan_sprite_table(context->vcounter, context);//Just a guess
-		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); }
-		context->hslot = 0;
-		context->cycles += slot_cycles;
-		CHECK_ONLY
-	case 0:
+		CHECK_LIMIT
+	case 250:
 		render_map_2(context);
 		scan_sprite_table(context->vcounter, context);//Just a guess
 		CHECK_LIMIT
-	case 1:
+	case 251:
 		read_map_scroll_b(0, context->vcounter, context);
 		CHECK_LIMIT
-	SPRITE_RENDER_H40(2)
-	case 3:
+	SPRITE_RENDER_H40(252)
+	case 253:
 		render_map_3(context);
 		scan_sprite_table(context->vcounter, context);//Just a guess
 		CHECK_LIMIT
-	case 4:
+	case 254:
 		if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
 			context->flags2 |= FLAG2_VINT_PENDING;
 			context->pending_vint_start = context->cycles;
@@ -1214,26 +1168,53 @@
 		context->sprite_draws = MAX_DRAWS;
 		context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
 		CHECK_LIMIT
-	COLUMN_RENDER_BLOCK(2, 5)
-	COLUMN_RENDER_BLOCK(4, 13)
-	COLUMN_RENDER_BLOCK(6, 21)
-	COLUMN_RENDER_BLOCK_REFRESH(8, 29)
-	COLUMN_RENDER_BLOCK(10, 37)
-	COLUMN_RENDER_BLOCK(12, 45)
-	COLUMN_RENDER_BLOCK(14, 53)
-	COLUMN_RENDER_BLOCK_REFRESH(16, 61)
-	COLUMN_RENDER_BLOCK(18, 69)
-	COLUMN_RENDER_BLOCK(20, 77)
-	COLUMN_RENDER_BLOCK(22, 85)
-	COLUMN_RENDER_BLOCK_REFRESH(24, 93)
-	COLUMN_RENDER_BLOCK(26, 101)
-	COLUMN_RENDER_BLOCK(28, 109)
-	COLUMN_RENDER_BLOCK(30, 117)
-	COLUMN_RENDER_BLOCK_REFRESH(32, 125)
-	COLUMN_RENDER_BLOCK(34, 133)
-	COLUMN_RENDER_BLOCK(36, 141)
-	COLUMN_RENDER_BLOCK(38, 149)
-	COLUMN_RENDER_BLOCK_REFRESH(40, 157)
+	COLUMN_RENDER_BLOCK(2, 255)
+	COLUMN_RENDER_BLOCK(4, 7)
+	COLUMN_RENDER_BLOCK(6, 15)
+	COLUMN_RENDER_BLOCK_REFRESH(8, 23)
+	COLUMN_RENDER_BLOCK(10, 31)
+	COLUMN_RENDER_BLOCK(12, 39)
+	COLUMN_RENDER_BLOCK(14, 47)
+	COLUMN_RENDER_BLOCK_REFRESH(16, 55)
+	COLUMN_RENDER_BLOCK(18, 63)
+	COLUMN_RENDER_BLOCK(20, 71)
+	COLUMN_RENDER_BLOCK(22, 79)
+	COLUMN_RENDER_BLOCK_REFRESH(24, 87)
+	COLUMN_RENDER_BLOCK(26, 95)
+	COLUMN_RENDER_BLOCK(28, 103)
+	COLUMN_RENDER_BLOCK(30, 111)
+	COLUMN_RENDER_BLOCK_REFRESH(32, 119)
+	COLUMN_RENDER_BLOCK(34, 127)
+	COLUMN_RENDER_BLOCK(36, 135)
+	COLUMN_RENDER_BLOCK(38, 143)
+	COLUMN_RENDER_BLOCK_REFRESH(40, 151)
+	case 159:
+		external_slot(context);
+		CHECK_LIMIT
+	case 160:
+		external_slot(context);
+		CHECK_LIMIT
+	//sprite render to line buffer starts
+	case 161:
+		context->cur_slot = MAX_DRAWS-1;
+		memset(context->linebuf, 0, LINEBUF_SIZE);
+		render_sprite_cells(context);
+		CHECK_LIMIT
+	case 162:
+		render_sprite_cells(context);
+		CHECK_LIMIT
+	case 163:
+		render_sprite_cells(context);
+		CHECK_LIMIT
+	case 164:
+		render_sprite_cells(context);
+		vdp_advance_line(context);
+		if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
+			context->hslot++;
+			context->cycles += slot_cycles;
+			return;
+		}
+		CHECK_LIMIT
 	}
 	default:
 		context->hslot++;
@@ -1251,84 +1232,42 @@
 	{
 	for (;;)
 	{
+	//sprite attribute table scan starts
 	case 132:
-		external_slot(context);
-		CHECK_LIMIT
-	case 133:
-		external_slot(context);
-		CHECK_LIMIT
-	//sprite render to line buffer starts
-	case 134:
-		context->cur_slot = MAX_DRAWS_H32-1;
-		memset(context->linebuf, 0, LINEBUF_SIZE);
-		if (context->vcounter == 0x1FF) {
-			external_slot(context);
-		} else {
-			render_sprite_cells(context);
-		}
-		CHECK_LIMIT
-	case 135:
-		if (context->vcounter == 0x1FF) {
-			external_slot(context);
-		} else {
-			render_sprite_cells(context);
-		}
-		CHECK_LIMIT
-	case 136:
-		if (context->vcounter == 0x1FF) {
-			external_slot(context);
-		} else {
-			render_sprite_cells(context);
-		}
-		CHECK_LIMIT
-	case 137:
-		if (context->vcounter == 0x1FF) {
-			external_slot(context);
-		} else {
-			render_sprite_cells(context);
-			if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
-				context->hslot++;
-				context->cycles += slot_cycles;
-				return;
-			}
-		}
-		CHECK_LIMIT
-	//sprite attribute table scan starts
-	case 138:
 		context->sprite_index = 0x80;
 		context->slot_counter = MAX_SPRITES_LINE_H32;
 		render_sprite_cells( context);
 		scan_sprite_table(context->vcounter, context);
 		CHECK_LIMIT
+	SPRITE_RENDER_H32(133)
+	SPRITE_RENDER_H32(134)
+	SPRITE_RENDER_H32(135)
+	SPRITE_RENDER_H32(136)
+	SPRITE_RENDER_H32(137)
+	SPRITE_RENDER_H32(138)
 	SPRITE_RENDER_H32(139)
 	SPRITE_RENDER_H32(140)
 	SPRITE_RENDER_H32(141)
-	SPRITE_RENDER_H32(142)
+	case 142:
+		external_slot(context);
+		CHECK_LIMIT
 	SPRITE_RENDER_H32(143)
 	SPRITE_RENDER_H32(144)
 	SPRITE_RENDER_H32(145)
 	SPRITE_RENDER_H32(146)
 	SPRITE_RENDER_H32(147)
-	case 233:
-		external_slot(context);
-		CHECK_LIMIT
+	//HSYNC start
+	SPRITE_RENDER_H32(233)
 	SPRITE_RENDER_H32(234)
 	SPRITE_RENDER_H32(235)
 	SPRITE_RENDER_H32(236)
 	SPRITE_RENDER_H32(237)
 	SPRITE_RENDER_H32(238)
-	//HSYNC start
 	SPRITE_RENDER_H32(239)
-	SPRITE_RENDER_H32(240)
-	SPRITE_RENDER_H32(241)
-	SPRITE_RENDER_H32(242)
-	SPRITE_RENDER_H32(243)
-	SPRITE_RENDER_H32(244)
-	SPRITE_RENDER_H32(245)
-	case 246:
+	case 240:
 		external_slot(context);
 		CHECK_LIMIT
-	case 247:
+	case 241:
 		address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
 		mask = 0;
 		if (context->regs[REG_MODE_3] & 0x2) {
@@ -1342,38 +1281,35 @@
 		context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
 		//printf("%d: HScroll A: %d, HScroll B: %d\n", context->vcounter, context->hscroll_a, context->hscroll_b);
 		CHECK_LIMIT
-	SPRITE_RENDER_H32(248)
-	SPRITE_RENDER_H32(249)
-	SPRITE_RENDER_H32(250)
-	SPRITE_RENDER_H32(251)
+	SPRITE_RENDER_H32(242)
+	SPRITE_RENDER_H32(243)
+	SPRITE_RENDER_H32(244)
+	SPRITE_RENDER_H32(245)
 	//!HSYNC high
-	case 252:
+	case 246:
 		read_map_scroll_a(0, context->vcounter, context);
 		CHECK_LIMIT
-	SPRITE_RENDER_H32(253)
-	case 254:
+	SPRITE_RENDER_H32(247)
+	case 248:
 		render_map_1(context);
 		scan_sprite_table(context->vcounter, context);//Just a guess
 		CHECK_LIMIT
-	case 255:
+	case 249:
 		render_map_2(context);
 		scan_sprite_table(context->vcounter, context);//Just a guess
-		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); }
-		context->cycles += slot_cycles;
-		context->hslot = 0;
-		CHECK_ONLY
-	case 0:
+		CHECK_LIMIT
+	case 250:
 		read_map_scroll_b(0, context->vcounter, context);
 		CHECK_LIMIT
-	case 1:
+	case 251:
 		render_sprite_cells(context);
 		scan_sprite_table(context->vcounter, context);
 		CHECK_LIMIT
-	case 2:
+	case 252:
 		render_map_3(context);
 		scan_sprite_table(context->vcounter, context);//Just a guess
 		CHECK_LIMIT
-	case 3:
+	case 253:
 		render_map_output(context->vcounter, 0, context);
 		scan_sprite_table(context->vcounter, context);//Just a guess
 		//reverse context slot counter so it counts the number of sprite slots
@@ -1383,22 +1319,49 @@
 		context->sprite_draws = MAX_DRAWS_H32;
 		context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
 		CHECK_LIMIT
-	COLUMN_RENDER_BLOCK(2, 4)
-	COLUMN_RENDER_BLOCK(4, 12)
-	COLUMN_RENDER_BLOCK(6, 20)
-	COLUMN_RENDER_BLOCK_REFRESH(8, 28)
-	COLUMN_RENDER_BLOCK(10, 36)
-	COLUMN_RENDER_BLOCK(12, 44)
-	COLUMN_RENDER_BLOCK(14, 52)
-	COLUMN_RENDER_BLOCK_REFRESH(16, 60)
-	COLUMN_RENDER_BLOCK(18, 68)
-	COLUMN_RENDER_BLOCK(20, 76)
-	COLUMN_RENDER_BLOCK(22, 84)
-	COLUMN_RENDER_BLOCK_REFRESH(24, 92)
-	COLUMN_RENDER_BLOCK(26, 100)
-	COLUMN_RENDER_BLOCK(28, 108)
-	COLUMN_RENDER_BLOCK(30, 116)
-	COLUMN_RENDER_BLOCK_REFRESH(32, 124)
+	COLUMN_RENDER_BLOCK(2, 254)
+	COLUMN_RENDER_BLOCK(4, 6)
+	COLUMN_RENDER_BLOCK(6, 14)
+	COLUMN_RENDER_BLOCK_REFRESH(8, 22)
+	COLUMN_RENDER_BLOCK(10, 30)
+	COLUMN_RENDER_BLOCK(12, 38)
+	COLUMN_RENDER_BLOCK(14, 46)
+	COLUMN_RENDER_BLOCK_REFRESH(16, 54)
+	COLUMN_RENDER_BLOCK(18, 62)
+	COLUMN_RENDER_BLOCK(20, 70)
+	COLUMN_RENDER_BLOCK(22, 78)
+	COLUMN_RENDER_BLOCK_REFRESH(24, 86)
+	COLUMN_RENDER_BLOCK(26, 94)
+	COLUMN_RENDER_BLOCK(28, 102)
+	COLUMN_RENDER_BLOCK(30, 110)
+	COLUMN_RENDER_BLOCK_REFRESH(32, 118)
+	case 126:
+		external_slot(context);
+		CHECK_LIMIT
+	case 127:
+		external_slot(context);
+		CHECK_LIMIT
+	//sprite render to line buffer starts
+	case 128:
+		context->cur_slot = MAX_DRAWS_H32-1;
+		memset(context->linebuf, 0, LINEBUF_SIZE);
+		render_sprite_cells(context);
+		CHECK_LIMIT
+	case 129:
+		render_sprite_cells(context);
+		CHECK_LIMIT
+	case 130:
+		render_sprite_cells(context);
+		CHECK_LIMIT
+	case 131:
+		render_sprite_cells(context);
+		vdp_advance_line(context);
+		if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
+			context->hslot++;
+			context->cycles += slot_cycles;
+			return;
+		}
+		CHECK_LIMIT
 	}
 	default:
 		context->hslot++;
@@ -1444,19 +1407,6 @@
 		//line 0x1FF is basically active even though it's not displayed
 		uint8_t active_slot = context->vcounter < inactive_start || context->vcounter == 0x1FF;
 		uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40;
-		if (context->vcounter == inactive_start) {
-			if (is_h40) {
-				//the first inactive line behaves as an active one for the first 4 slots
-				if (context->hslot > LINE_CHANGE_H40 && context->hslot < 171) {
-					active_slot = 1;
-				}
-			} else {
-				//the first inactive line behaves as an active one for the first few slots
-				if (context->hslot > LINE_CHANGE_H32 && context->hslot < 138) {
-					active_slot = 1;
-				}
-			}
-		}
 		if (context->regs[REG_MODE_2] & DISPLAY_ENABLE && active_slot) {
 			if (is_h40) {
 				vdp_h40(context, target_cycles);
@@ -1465,18 +1415,18 @@
 			}
 		} else {
 			if (is_h40) {
-				if (context->hslot == 167) {
+				if (context->hslot == 161) {
 					context->cur_slot = MAX_DRAWS-1;
 					memset(context->linebuf, 0, LINEBUF_SIZE);
-				} else if (context->hslot == 171) {
+				} else if (context->hslot == 165) {
 					context->sprite_index = 0x80;
 					context->slot_counter = MAX_SPRITES_LINE;
 				}
 			} else {
-				if (context->hslot == 134) {
+				if (context->hslot == 128) {
 					context->cur_slot = MAX_DRAWS_H32-1;
 					memset(context->linebuf, 0, LINEBUF_SIZE);
-				} else if (context->hslot == 138) {
+				} else if (context->hslot == 132) {
 					context->sprite_index = 0x80;
 					context->slot_counter = MAX_SPRITES_LINE_H32;
 				}
@@ -1490,7 +1440,9 @@
 			}
 			uint32_t inccycles;
 			if (is_h40) {
-				if (context->hslot < HSYNC_SLOT_H40 || context->hslot >= HSYNC_END_H40) {
+				if (context->hslot == 182) {
+					inccycles = h40_hsync_cycles[0];
+				} else if (context->hslot < HSYNC_SLOT_H40 || context->hslot >= HSYNC_END_H40) {
 					inccycles = MCLKS_SLOT_H40;
 				} else {
 					inccycles = h40_hsync_cycles[context->hslot-HSYNC_SLOT_H40];
@@ -1509,7 +1461,6 @@
 			}
 			context->cycles += inccycles;
 			context->hslot++;
-			context->hslot &= 0xFF;
 			if (is_h40) {
 				if (context->hslot == LINE_CHANGE_H40) {
 					vdp_advance_line(context);
@@ -1692,22 +1643,7 @@
 	uint32_t line= context->vcounter;
 	uint32_t slot = context->hslot;
 	uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START);
-	if (
-		(
-			line > inactive_start
-			&& line < 0x1FF
-		)
-		|| (line == inactive_start
-			&& (
-				slot >= (context->regs[REG_MODE_4] & BIT_H40 ? VBLANK_START_H40 : VBLANK_START_H32)
-				|| slot < (context->regs[REG_MODE_4] & BIT_H40 ? LINE_CHANGE_H40 : LINE_CHANGE_H32)
-			)
-		)
-		|| (line == 0x1FF
-			&& slot < (context->regs[REG_MODE_4] & BIT_H40 ? VBLANK_START_H40 : VBLANK_START_H32))
-			&& slot >= (context->regs[REG_MODE_4] & BIT_H40 ? LINE_CHANGE_H40 : LINE_CHANGE_H32)
-		|| !(context->regs[REG_MODE_2] & BIT_DISP_EN)
-	) {
+	if ((line >= inactive_start && line < 0x1FF) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) {
 		value |= 0x8;
 	}
 	if (context->regs[REG_MODE_4] & BIT_H40) {
--- a/vdp.h	Mon Jan 25 09:37:27 2016 -0800
+++ b/vdp.h	Tue Feb 02 22:24:49 2016 -0800
@@ -148,9 +148,9 @@
 	uint16_t    vscroll_latch[2];
 	uint32_t    frame;
 	uint16_t    vcounter;
-	uint16_t    hslot; //hcounter/2
 	uint16_t    hscroll_a;
 	uint16_t    hscroll_b;
+	uint8_t     hslot; //hcounter/2
 	uint8_t     latched_mode;
 	uint8_t	    sprite_index;
 	uint8_t     sprite_draws;