comparison vdp.c @ 803:236a184bf6f0

Merge
author Michael Pavone <pavone@retrodev.com>
date Sun, 26 Jul 2015 16:51:03 -0700
parents 0565b2c1a034
children ac65086c031e
comparison
equal deleted inserted replaced
802:6811f601008f 803:236a184bf6f0
7 #include "blastem.h" 7 #include "blastem.h"
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <string.h> 9 #include <string.h>
10 #include "render.h" 10 #include "render.h"
11 11
12 #define NTSC_ACTIVE 225 12 #define NTSC_INACTIVE_START 224
13 #define PAL_ACTIVE 241 13 #define PAL_INACTIVE_START 240
14 #define BUF_BIT_PRIORITY 0x40 14 #define BUF_BIT_PRIORITY 0x40
15 #define MAP_BIT_PRIORITY 0x8000 15 #define MAP_BIT_PRIORITY 0x8000
16 #define MAP_BIT_H_FLIP 0x800 16 #define MAP_BIT_H_FLIP 0x800
17 #define MAP_BIT_V_FLIP 0x1000 17 #define MAP_BIT_V_FLIP 0x1000
18 18
20 #define SCROLL_BUFFER_MASK (SCROLL_BUFFER_SIZE-1) 20 #define SCROLL_BUFFER_MASK (SCROLL_BUFFER_SIZE-1)
21 #define SCROLL_BUFFER_DRAW (SCROLL_BUFFER_SIZE/2) 21 #define SCROLL_BUFFER_DRAW (SCROLL_BUFFER_SIZE/2)
22 22
23 #define MCLKS_SLOT_H40 16 23 #define MCLKS_SLOT_H40 16
24 #define MCLKS_SLOT_H32 20 24 #define MCLKS_SLOT_H32 20
25 #define VINT_CYCLE_H40 (21*MCLKS_SLOT_H40+332+9*MCLKS_SLOT_H40) //21 slots before HSYNC, 16 during, 10 after 25 #define VINT_SLOT_H40 4 //21 slots before HSYNC, 16 during, 10 after
26 #define VINT_CYCLE_H32 ((33+20+7)*MCLKS_SLOT_H32) //33 slots before HSYNC, 20 during, 7 after TODO: confirm final number 26 #define VINT_SLOT_H32 4 //old value was 23, but recent tests suggest the actual value is close to the H40 one
27 #define HSYNC_SLOT_H40 21 27 #define HSYNC_SLOT_H40 234
28 #define MCLK_WEIRD_END (HSYNC_SLOT_H40*MCLKS_SLOT_H40 + 332) 28 #define HSYNC_END_H40 (HSYNC_SLOT_H40+17)
29 #define SLOT_WEIRD_END (HSYNC_SLOT_H40+17)
30 #define HSYNC_END_H32 (33 * MCLKS_SLOT_H32) 29 #define HSYNC_END_H32 (33 * MCLKS_SLOT_H32)
31 #define HBLANK_CLEAR_H40 (MCLK_WEIRD_END+61*4) 30 #define HBLANK_START_H40 178 //should be 179 according to Nemesis, but 178 seems to fit slightly better with my test ROM results
32 #define HBLANK_CLEAR_H32 (HSYNC_END_H32 + 46*5) 31 #define HBLANK_END_H40 0 //should be 5.5 according to Nemesis, but 0 seems to fit better with my test ROM results
32 #define HBLANK_START_H32 233 //should be 147 according to Nemesis which is very different from my test ROM result
33 #define HBLANK_END_H32 0 //should be 5 according to Nemesis, but 0 seems to fit better with my test ROM results
34 #define LINE_CHANGE_H40 165
35 #define LINE_CHANGE_H32 132
36 #define VBLANK_START_H40 (LINE_CHANGE_H40+2)
37 #define VBLANK_START_H32 (LINE_CHANGE_H32+2)
33 #define FIFO_LATENCY 3 38 #define FIFO_LATENCY 3
34 39
35 int32_t color_map[1 << 12]; 40 int32_t color_map[1 << 12];
36 uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255}; 41 uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255};
37 42
43 {127, 0, 127} //Sprites 48 {127, 0, 127} //Sprites
44 }; 49 };
45 50
46 uint8_t color_map_init_done; 51 uint8_t color_map_init_done;
47 52
48 void init_vdp_context(vdp_context * context) 53 void init_vdp_context(vdp_context * context, uint8_t region_pal)
49 { 54 {
50 memset(context, 0, sizeof(*context)); 55 memset(context, 0, sizeof(*context));
51 context->vdpmem = malloc(VRAM_SIZE); 56 context->vdpmem = malloc(VRAM_SIZE);
52 memset(context->vdpmem, 0, VRAM_SIZE); 57 memset(context->vdpmem, 0, VRAM_SIZE);
53 /* 58 /*
55 if (headless) { 60 if (headless) {
56 context->oddbuf = context->framebuf = malloc(FRAMEBUF_ENTRIES * (32 / 8)); 61 context->oddbuf = context->framebuf = malloc(FRAMEBUF_ENTRIES * (32 / 8));
57 memset(context->framebuf, 0, FRAMEBUF_ENTRIES * (32 / 8)); 62 memset(context->framebuf, 0, FRAMEBUF_ENTRIES * (32 / 8));
58 context->evenbuf = malloc(FRAMEBUF_ENTRIES * (32 / 8)); 63 context->evenbuf = malloc(FRAMEBUF_ENTRIES * (32 / 8));
59 memset(context->evenbuf, 0, FRAMEBUF_ENTRIES * (32 / 8)); 64 memset(context->evenbuf, 0, FRAMEBUF_ENTRIES * (32 / 8));
60 context->b32 = 1;
61 } else { 65 } else {
62 render_alloc_surfaces(context); 66 render_alloc_surfaces(context);
63 context->b32 = render_depth() == 32;
64 } 67 }
65 context->framebuf = context->oddbuf; 68 context->framebuf = context->oddbuf;
66 context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); 69 context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
67 memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); 70 memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
68 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; 71 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE;
130 } 133 }
131 } 134 }
132 context->debugcolors[color] = render_map_color(r, g, b); 135 context->debugcolors[color] = render_map_color(r, g, b);
133 } 136 }
134 } 137 }
138 if (region_pal) {
139 context->flags2 |= FLAG2_REGION_PAL;
140 }
135 } 141 }
136 142
137 int is_refresh(vdp_context * context, uint32_t slot) 143 int is_refresh(vdp_context * context, uint32_t slot)
138 { 144 {
139 if (context->latched_mode & BIT_H40) { 145 if (context->regs[REG_MODE_4] & BIT_H40) {
140 return (slot == 37 || slot == 69 || slot == 102 || slot == 133 || slot == 165 || slot == 197 || slot >= 210); 146 return slot == 250 || slot == 26 || slot == 59 || slot == 90 || slot == 122 || slot == 154;
141 } else { 147 } else {
142 //TODO: Figure out which slots are refresh when display is off in 32-cell mode 148 //TODO: Figure out which slots are refresh when display is off in 32-cell mode
143 //These numbers are guesses based on H40 numbers 149 //These numbers are guesses based on H40 numbers
144 return (slot == 24 || slot == 56 || slot == 88 || slot == 120 || slot == 152); 150 return slot == 243 || slot == 19 || slot == 51 || slot == 83 || slot == 115;
145 //The numbers below are the refresh slots during active display 151 //The numbers below are the refresh slots during active display
146 //return (slot == 66 || slot == 98 || slot == 130 || slot == 162); 152 //return (slot == 29 || slot == 61 || slot == 93 || slot == 125);
147 } 153 }
148 } 154 }
149 155
150 void render_sprite_cells(vdp_context * context) 156 void render_sprite_cells(vdp_context * context)
151 { 157 {
201 current_index = link; 207 current_index = link;
202 count++; 208 count++;
203 } while (current_index != 0 && count < 80); 209 } while (current_index != 0 && count < 80);
204 } 210 }
205 211
206 void vdp_print_reg_explain(vdp_context * context)
207 {
208 char * hscroll[] = {"full", "7-line", "cell", "line"};
209 printf("**Mode Group**\n"
210 "00: %.2X | H-ints %s, Pal Select %d, HVC latch %s, Display gen %s\n"
211 "01: %.2X | Display %s, V-ints %s, Height: %d, Mode %d\n"
212 "0B: %.2X | E-ints %s, V-Scroll: %s, H-Scroll: %s\n"
213 "0C: %.2X | Width: %d, Shadow/Highlight: %s\n",
214 context->regs[REG_MODE_1], context->regs[REG_MODE_1] & BIT_HINT_EN ? "enabled" : "disabled", context->regs[REG_MODE_1] & BIT_PAL_SEL != 0,
215 context->regs[REG_MODE_1] & BIT_HVC_LATCH ? "enabled" : "disabled", context->regs[REG_MODE_1] & BIT_DISP_DIS ? "disabled" : "enabled",
216 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",
217 context->regs[REG_MODE_2] & BIT_PAL ? 30 : 28, context->regs[REG_MODE_2] & BIT_MODE_5 ? 5 : 4,
218 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",
219 hscroll[context->regs[REG_MODE_3] & 0x3],
220 context->regs[REG_MODE_4], context->regs[REG_MODE_4] & BIT_H40 ? 40 : 32, context->regs[REG_MODE_4] & BIT_HILIGHT ? "enabled" : "disabled");
221 printf("\n**Table Group**\n"
222 "02: %.2X | Scroll A Name Table: $%.4X\n"
223 "03: %.2X | Window Name Table: $%.4X\n"
224 "04: %.2X | Scroll B Name Table: $%.4X\n"
225 "05: %.2X | Sprite Attribute Table: $%.4X\n"
226 "0D: %.2X | HScroll Data Table: $%.4X\n",
227 context->regs[REG_SCROLL_A], (context->regs[REG_SCROLL_A] & 0x38) << 10,
228 context->regs[REG_WINDOW], (context->regs[REG_WINDOW] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x3C : 0x3E)) << 10,
229 context->regs[REG_SCROLL_B], (context->regs[REG_SCROLL_B] & 0x7) << 13,
230 context->regs[REG_SAT], (context->regs[REG_SAT] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x3E : 0x3F)) << 9,
231 context->regs[REG_HSCROLL], (context->regs[REG_HSCROLL] & 0x1F) << 10);
232 char * sizes[] = {"32", "64", "invalid", "128"};
233 printf("\n**Misc Group**\n"
234 "07: %.2X | Backdrop Color: $%X\n"
235 "0A: %.2X | H-Int Counter: %u\n"
236 "0F: %.2X | Auto-increment: $%X\n"
237 "10: %.2X | Scroll A/B Size: %sx%s\n",
238 context->regs[REG_BG_COLOR], context->regs[REG_BG_COLOR],
239 context->regs[REG_HINT], context->regs[REG_HINT],
240 context->regs[REG_AUTOINC], context->regs[REG_AUTOINC],
241 context->regs[REG_SCROLL], sizes[context->regs[REG_SCROLL] & 0x3], sizes[context->regs[REG_SCROLL] >> 4 & 0x3]);
242 printf("\n**Internal Group**\n"
243 "Address: %X\n"
244 "CD: %X\n"
245 "Pending: %s\n",
246 context->address, context->cd, (context->flags & FLAG_PENDING) ? "true" : "false");
247
248 //TODO: Window Group, DMA Group
249 }
250
251 void scan_sprite_table(uint32_t line, vdp_context * context)
252 {
253 if (context->sprite_index && context->slot_counter) {
254 line += 1;
255 line &= 0xFF;
256 uint16_t ymask, ymin;
257 uint8_t height_mult;
258 if (context->double_res) {
259 line *= 2;
260 if (context->framebuf != context->oddbuf) {
261 line++;
262 }
263 ymask = 0x3FF;
264 ymin = 256;
265 height_mult = 16;
266 } else {
267 ymask = 0x1FF;
268 ymin = 128;
269 height_mult = 8;
270 }
271 context->sprite_index &= 0x7F;
272 if (context->latched_mode & BIT_H40) {
273 if (context->sprite_index >= MAX_SPRITES_FRAME) {
274 context->sprite_index = 0;
275 return;
276 }
277 } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) {
278 context->sprite_index = 0;
279 return;
280 }
281 //TODO: Read from SAT cache rather than from VRAM
282 uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9;
283 uint16_t address = context->sprite_index * 8 + sat_address;
284 line += ymin;
285 uint16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & ymask;
286 uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult;
287 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
288 if (y <= line && line < (y + height)) {
289 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
290 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2];
291 context->sprite_info_list[context->slot_counter].index = context->sprite_index;
292 context->sprite_info_list[context->slot_counter].y = y-ymin;
293 }
294 context->sprite_index = context->vdpmem[address+3] & 0x7F;
295 if (context->sprite_index && context->slot_counter)
296 {
297 address = context->sprite_index * 8 + sat_address;
298 y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & ymask;
299 height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult;
300 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
301 if (y <= line && line < (y + height)) {
302 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
303 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2];
304 context->sprite_info_list[context->slot_counter].index = context->sprite_index;
305 context->sprite_info_list[context->slot_counter].y = y-ymin;
306 }
307 context->sprite_index = context->vdpmem[address+3] & 0x7F;
308 }
309 }
310 }
311
312 void read_sprite_x(uint32_t line, vdp_context * context)
313 {
314 if (context->cur_slot >= context->slot_counter) {
315 if (context->sprite_draws) {
316 line += 1;
317 line &= 0xFF;
318 //in tiles
319 uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1;
320 //in pixels
321 uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8;
322 if (context->double_res) {
323 line *= 2;
324 if (context->framebuf != context->oddbuf) {
325 line++;
326 }
327 height *= 2;
328 }
329 uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->cur_slot].index * 8 + 4;
330 uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1];
331 uint8_t pal_priority = (tileinfo >> 9) & 0x70;
332 uint8_t row;
333 if (tileinfo & MAP_BIT_V_FLIP) {
334 row = (context->sprite_info_list[context->cur_slot].y + height - 1) - line;
335 } else {
336 row = line-context->sprite_info_list[context->cur_slot].y;
337 }
338 uint16_t address;
339 if (context->double_res) {
340 address = ((tileinfo & 0x3FF) << 6) + row * 4;
341 } else {
342 address = ((tileinfo & 0x7FF) << 5) + row * 4;
343 }
344 int16_t x = ((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF;
345 if (x) {
346 context->flags |= FLAG_CAN_MASK;
347 } else if(context->flags & (FLAG_CAN_MASK | FLAG_DOT_OFLOW)) {
348 context->flags |= FLAG_MASKED;
349 }
350
351 context->flags &= ~FLAG_DOT_OFLOW;
352 int16_t i;
353 if (context->flags & FLAG_MASKED) {
354 for (i=0; i < width && context->sprite_draws; i++) {
355 --context->sprite_draws;
356 context->sprite_draw_list[context->sprite_draws].x_pos = -128;
357 }
358 } else {
359 x -= 128;
360 int16_t base_x = x;
361 int16_t dir;
362 if (tileinfo & MAP_BIT_H_FLIP) {
363 x += (width-1) * 8;
364 dir = -8;
365 } else {
366 dir = 8;
367 }
368 //printf("Sprite %d | x: %d, y: %d, width: %d, height: %d, pal_priority: %X, row: %d, tile addr: %X\n", context->sprite_info_list[context->cur_slot].index, x, context->sprite_info_list[context->cur_slot].y, width, height, pal_priority, row, address);
369 for (i=0; i < width && context->sprite_draws; i++, x += dir) {
370 --context->sprite_draws;
371 context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4;
372 context->sprite_draw_list[context->sprite_draws].x_pos = x;
373 context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority;
374 context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0;
375 }
376 }
377 if (i < width) {
378 context->flags |= FLAG_DOT_OFLOW;
379 }
380 context->cur_slot--;
381 } else {
382 context->flags |= FLAG_DOT_OFLOW;
383 }
384 }
385 }
386
387 void write_cram(vdp_context * context, uint16_t address, uint16_t value)
388 {
389 uint16_t addr = (address/2) & (CRAM_SIZE-1);
390 context->cram[addr] = value;
391 context->colors[addr] = color_map[value & 0xEEE];
392 context->colors[addr + CRAM_SIZE] = color_map[(value & 0xEEE) | FBUF_SHADOW];
393 context->colors[addr + CRAM_SIZE*2] = color_map[(value & 0xEEE) | FBUF_HILIGHT];
394 }
395
396 #define VRAM_READ 0 //0000 212 #define VRAM_READ 0 //0000
397 #define VRAM_WRITE 1 //0001 213 #define VRAM_WRITE 1 //0001
398 //2 would trigger register write 0010 214 //2 would trigger register write 0010
399 #define CRAM_WRITE 3 //0011 215 #define CRAM_WRITE 3 //0011
400 #define VSRAM_READ 4 //0100 216 #define VSRAM_READ 4 //0100
408 #define VRAM_READ8 0xC //1100 224 #define VRAM_READ8 0xC //1100
409 //D is a mystery 1101 225 //D is a mystery 1101
410 //E would trigger register write 1110 226 //E would trigger register write 1110
411 //F is a mystery 1111 227 //F is a mystery 1111
412 #define DMA_START 0x20 228 #define DMA_START 0x20
229
230 const char * cd_name(uint8_t cd)
231 {
232 switch (cd & 0xF)
233 {
234 case VRAM_READ:
235 return "VRAM read";
236 case VRAM_WRITE:
237 return "VRAM write";
238 case CRAM_WRITE:
239 return "CRAM write";
240 case VSRAM_READ:
241 return "VSRAM read";
242 case VSRAM_WRITE:
243 return "VSRAM write";
244 case VRAM_READ8:
245 return "VRAM read (undocumented 8-bit mode)";
246 default:
247 return "invalid";
248 }
249 }
250
251 void vdp_print_reg_explain(vdp_context * context)
252 {
253 char * hscroll[] = {"full", "7-line", "cell", "line"};
254 printf("**Mode Group**\n"
255 "00: %.2X | H-ints %s, Pal Select %d, HVC latch %s, Display gen %s\n"
256 "01: %.2X | Display %s, V-ints %s, Height: %d, Mode %d\n"
257 "0B: %.2X | E-ints %s, V-Scroll: %s, H-Scroll: %s\n"
258 "0C: %.2X | Width: %d, Shadow/Highlight: %s\n",
259 context->regs[REG_MODE_1], context->regs[REG_MODE_1] & BIT_HINT_EN ? "enabled" : "disabled", (context->regs[REG_MODE_1] & BIT_PAL_SEL) != 0,
260 context->regs[REG_MODE_1] & BIT_HVC_LATCH ? "enabled" : "disabled", context->regs[REG_MODE_1] & BIT_DISP_DIS ? "disabled" : "enabled",
261 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",
262 context->regs[REG_MODE_2] & BIT_PAL ? 30 : 28, context->regs[REG_MODE_2] & BIT_MODE_5 ? 5 : 4,
263 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",
264 hscroll[context->regs[REG_MODE_3] & 0x3],
265 context->regs[REG_MODE_4], context->regs[REG_MODE_4] & BIT_H40 ? 40 : 32, context->regs[REG_MODE_4] & BIT_HILIGHT ? "enabled" : "disabled");
266 printf("\n**Table Group**\n"
267 "02: %.2X | Scroll A Name Table: $%.4X\n"
268 "03: %.2X | Window Name Table: $%.4X\n"
269 "04: %.2X | Scroll B Name Table: $%.4X\n"
270 "05: %.2X | Sprite Attribute Table: $%.4X\n"
271 "0D: %.2X | HScroll Data Table: $%.4X\n",
272 context->regs[REG_SCROLL_A], (context->regs[REG_SCROLL_A] & 0x38) << 10,
273 context->regs[REG_WINDOW], (context->regs[REG_WINDOW] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x3C : 0x3E)) << 10,
274 context->regs[REG_SCROLL_B], (context->regs[REG_SCROLL_B] & 0x7) << 13,
275 context->regs[REG_SAT], (context->regs[REG_SAT] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x7E : 0x7F)) << 9,
276 context->regs[REG_HSCROLL], (context->regs[REG_HSCROLL] & 0x3F) << 10);
277 char * sizes[] = {"32", "64", "invalid", "128"};
278 printf("\n**Misc Group**\n"
279 "07: %.2X | Backdrop Color: $%X\n"
280 "0A: %.2X | H-Int Counter: %u\n"
281 "0F: %.2X | Auto-increment: $%X\n"
282 "10: %.2X | Scroll A/B Size: %sx%s\n",
283 context->regs[REG_BG_COLOR], context->regs[REG_BG_COLOR],
284 context->regs[REG_HINT], context->regs[REG_HINT],
285 context->regs[REG_AUTOINC], context->regs[REG_AUTOINC],
286 context->regs[REG_SCROLL], sizes[context->regs[REG_SCROLL] & 0x3], sizes[context->regs[REG_SCROLL] >> 4 & 0x3]);
287 char * src_types[] = {"68K", "68K", "Copy", "Fill"};
288 printf("\n**DMA Group**\n"
289 "13: %.2X |\n"
290 "14: %.2X | DMA Length: $%.4X words\n"
291 "15: %.2X |\n"
292 "16: %.2X |\n"
293 "17: %.2X | DMA Source Address: $%.6X, Type: %s\n",
294 context->regs[REG_DMALEN_L],
295 context->regs[REG_DMALEN_H], context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L],
296 context->regs[REG_DMASRC_L],
297 context->regs[REG_DMASRC_M],
298 context->regs[REG_DMASRC_H],
299 context->regs[REG_DMASRC_H] << 17 | context->regs[REG_DMASRC_M] << 9 | context->regs[REG_DMASRC_L] << 1,
300 src_types[context->regs[REG_DMASRC_H] >> 6 & 3]);
301 printf("\n**Internal Group**\n"
302 "Address: %X\n"
303 "CD: %X - %s\n"
304 "Pending: %s\n"
305 "VCounter: %d\n"
306 "HCounter: %d\n",
307 context->address, context->cd, cd_name(context->cd), (context->flags & FLAG_PENDING) ? "true" : "false",
308 context->vcounter, context->hslot*2);
309
310 //TODO: Window Group, DMA Group
311 }
312
313 void scan_sprite_table(uint32_t line, vdp_context * context)
314 {
315 if (context->sprite_index && context->slot_counter) {
316 line += 1;
317 line &= 0xFF;
318 uint16_t ymask, ymin;
319 uint8_t height_mult;
320 if (context->double_res) {
321 line *= 2;
322 if (context->framebuf != context->oddbuf) {
323 line++;
324 }
325 ymask = 0x3FF;
326 ymin = 256;
327 height_mult = 16;
328 } else {
329 ymask = 0x1FF;
330 ymin = 128;
331 height_mult = 8;
332 }
333 context->sprite_index &= 0x7F;
334 if (context->regs[REG_MODE_4] & BIT_H40) {
335 if (context->sprite_index >= MAX_SPRITES_FRAME) {
336 context->sprite_index = 0;
337 return;
338 }
339 } else if(context->sprite_index >= MAX_SPRITES_FRAME_H32) {
340 context->sprite_index = 0;
341 return;
342 }
343 //TODO: Read from SAT cache rather than from VRAM
344 uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9;
345 uint16_t address = context->sprite_index * 8 + sat_address;
346 line += ymin;
347 uint16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & ymask;
348 uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult;
349 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
350 if (y <= line && line < (y + height)) {
351 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
352 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2];
353 context->sprite_info_list[context->slot_counter].index = context->sprite_index;
354 context->sprite_info_list[context->slot_counter].y = y-ymin;
355 }
356 context->sprite_index = context->vdpmem[address+3] & 0x7F;
357 if (context->sprite_index && context->slot_counter)
358 {
359 address = context->sprite_index * 8 + sat_address;
360 y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & ymask;
361 height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult;
362 //printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
363 if (y <= line && line < (y + height)) {
364 //printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
365 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2];
366 context->sprite_info_list[context->slot_counter].index = context->sprite_index;
367 context->sprite_info_list[context->slot_counter].y = y-ymin;
368 }
369 context->sprite_index = context->vdpmem[address+3] & 0x7F;
370 }
371 }
372 }
373
374 void read_sprite_x(uint32_t line, vdp_context * context)
375 {
376 if (context->cur_slot >= context->slot_counter) {
377 if (context->sprite_draws) {
378 line += 1;
379 line &= 0xFF;
380 //in tiles
381 uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1;
382 //in pixels
383 uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8;
384 if (context->double_res) {
385 line *= 2;
386 if (context->framebuf != context->oddbuf) {
387 line++;
388 }
389 height *= 2;
390 }
391 uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->cur_slot].index * 8 + 4;
392 uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1];
393 uint8_t pal_priority = (tileinfo >> 9) & 0x70;
394 uint8_t row;
395 if (tileinfo & MAP_BIT_V_FLIP) {
396 row = (context->sprite_info_list[context->cur_slot].y + height - 1) - line;
397 } else {
398 row = line-context->sprite_info_list[context->cur_slot].y;
399 }
400 uint16_t address;
401 if (context->double_res) {
402 address = ((tileinfo & 0x3FF) << 6) + row * 4;
403 } else {
404 address = ((tileinfo & 0x7FF) << 5) + row * 4;
405 }
406 int16_t x = ((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF;
407 if (x) {
408 context->flags |= FLAG_CAN_MASK;
409 } else if(context->flags & (FLAG_CAN_MASK | FLAG_DOT_OFLOW)) {
410 context->flags |= FLAG_MASKED;
411 }
412
413 context->flags &= ~FLAG_DOT_OFLOW;
414 int16_t i;
415 if (context->flags & FLAG_MASKED) {
416 for (i=0; i < width && context->sprite_draws; i++) {
417 --context->sprite_draws;
418 context->sprite_draw_list[context->sprite_draws].x_pos = -128;
419 }
420 } else {
421 x -= 128;
422 int16_t base_x = x;
423 int16_t dir;
424 if (tileinfo & MAP_BIT_H_FLIP) {
425 x += (width-1) * 8;
426 dir = -8;
427 } else {
428 dir = 8;
429 }
430 //printf("Sprite %d | x: %d, y: %d, width: %d, height: %d, pal_priority: %X, row: %d, tile addr: %X\n", context->sprite_info_list[context->cur_slot].index, x, context->sprite_info_list[context->cur_slot].y, width, height, pal_priority, row, address);
431 for (i=0; i < width && context->sprite_draws; i++, x += dir) {
432 --context->sprite_draws;
433 context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4;
434 context->sprite_draw_list[context->sprite_draws].x_pos = x;
435 context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority;
436 context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0;
437 }
438 }
439 if (i < width) {
440 context->flags |= FLAG_DOT_OFLOW;
441 }
442 context->cur_slot--;
443 } else {
444 context->flags |= FLAG_DOT_OFLOW;
445 }
446 }
447 }
448
449 void write_cram(vdp_context * context, uint16_t address, uint16_t value)
450 {
451 uint16_t addr = (address/2) & (CRAM_SIZE-1);
452 context->cram[addr] = value;
453 context->colors[addr] = color_map[value & 0xEEE];
454 context->colors[addr + CRAM_SIZE] = color_map[(value & 0xEEE) | FBUF_SHADOW];
455 context->colors[addr + CRAM_SIZE*2] = color_map[(value & 0xEEE) | FBUF_HILIGHT];
456 }
413 457
414 void external_slot(vdp_context * context) 458 void external_slot(vdp_context * context)
415 { 459 {
416 fifo_entry * start = context->fifo + context->fifo_read; 460 fifo_entry * start = context->fifo + context->fifo_read;
417 /*if (context->flags2 & FLAG2_READ_PENDING) { 461 /*if (context->flags2 & FLAG2_READ_PENDING) {
439 write_cram(context, start->address, start->partial == 2 ? context->fifo[context->fifo_write].value : start->value); 483 write_cram(context, start->address, start->partial == 2 ? context->fifo[context->fifo_write].value : start->value);
440 break; 484 break;
441 } 485 }
442 case VSRAM_WRITE: 486 case VSRAM_WRITE:
443 if (((start->address/2) & 63) < VSRAM_SIZE) { 487 if (((start->address/2) & 63) < VSRAM_SIZE) {
444 //printf("VSRAM Write: %X to %X\n", start->value, context->address); 488 //printf("VSRAM Write: %X to %X @ vcounter: %d, hslot: %d, cycle: %d\n", start->value, context->address, context->vcounter, context->hslot, context->cycles);
445 context->vsram[(start->address/2) & 63] = start->partial == 2 ? context->fifo[context->fifo_write].value : start->value; 489 context->vsram[(start->address/2) & 63] = start->partial == 2 ? context->fifo[context->fifo_write].value : start->value;
446 } 490 }
447 491
448 break; 492 break;
449 } 493 }
470 //68K -> VDP 514 //68K -> VDP
471 case 0: 515 case 0:
472 case 0x40: 516 case 0x40:
473 if (!slot || !is_refresh(context, slot-1)) { 517 if (!slot || !is_refresh(context, slot-1)) {
474 cur = context->fifo + context->fifo_write; 518 cur = context->fifo + context->fifo_write;
475 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 519 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
476 cur->address = context->address; 520 cur->address = context->address;
477 cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); 521 cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]);
478 cur->cd = context->cd; 522 cur->cd = context->cd;
479 cur->partial = 0; 523 cur->partial = 0;
480 if (context->fifo_read < 0) { 524 if (context->fifo_read < 0) {
516 context->address += context->regs[REG_AUTOINC]; 560 context->address += context->regs[REG_AUTOINC];
517 uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1; 561 uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1;
518 context->regs[REG_DMALEN_H] = dma_len >> 8; 562 context->regs[REG_DMALEN_H] = dma_len >> 8;
519 context->regs[REG_DMALEN_L] = dma_len; 563 context->regs[REG_DMALEN_L] = dma_len;
520 if (!dma_len) { 564 if (!dma_len) {
521 //printf("DMA end at cycle %d\n", context->cycles); 565 //printf("DMA end at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", context->cycles, context->frame, context->vcounter, context->hslot);
522 context->flags &= ~FLAG_DMA_RUN; 566 context->flags &= ~FLAG_DMA_RUN;
523 context->cd &= 0xF; 567 context->cd &= 0xF;
524 } 568 }
525 } 569 }
526 } 570 }
565 bottom_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift; 609 bottom_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift;
566 } 610 }
567 if ((column >= left_col && column < right_col) || (line >= top_line && line < bottom_line)) { 611 if ((column >= left_col && column < right_col) || (line >= top_line && line < bottom_line)) {
568 uint16_t address = context->regs[REG_WINDOW] << 10; 612 uint16_t address = context->regs[REG_WINDOW] << 10;
569 uint16_t line_offset, offset, mask; 613 uint16_t line_offset, offset, mask;
570 if (context->latched_mode & BIT_H40) { 614 if (context->regs[REG_MODE_4] & BIT_H40) {
571 address &= 0xF000; 615 address &= 0xF000;
572 line_offset = (((line) >> vscroll_shift) * 64 * 2) & 0xFFF; 616 line_offset = (((line) >> vscroll_shift) * 64 * 2) & 0xFFF;
573 mask = 0x7F; 617 mask = 0x7F;
574 618
575 } else { 619 } else {
611 } 655 }
612 if (context->double_res) { 656 if (context->double_res) {
613 vscroll <<= 1; 657 vscroll <<= 1;
614 vscroll |= 1; 658 vscroll |= 1;
615 } 659 }
616 vscroll &= (context->vsram[(context->regs[REG_MODE_3] & BIT_VSCROLL ? (column-2)&63 : 0) + vsram_off] + line); 660 //TODO: Further research on vscroll latch behavior and the "first column bug"
661 if (!column) {
662 if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
663 if (context->regs[REG_MODE_4] & BIT_H40) {
664 //Based on observed behavior documented by Eke-Eke, I'm guessing the VDP
665 //ends up fetching the last value on the VSRAM bus in the H40 case
666 //getting the last latched value should be close enough for now
667 if (!vsram_off) {
668 context->vscroll_latch[0] = context->vscroll_latch[1];
669 }
670 } else {
671 //supposedly it's always forced to 0 in the H32 case
672 context->vscroll_latch[0] = context->vscroll_latch[1] = 0;
673 }
674 } else {
675 context->vscroll_latch[vsram_off] = context->vsram[vsram_off];
676 }
677 } else if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
678 context->vscroll_latch[vsram_off] = context->vsram[column - 2 + vsram_off];
679 }
680 vscroll &= context->vscroll_latch[vsram_off] + line;
617 context->v_offset = vscroll & v_offset_mask; 681 context->v_offset = vscroll & v_offset_mask;
618 //printf("%s | line %d, vsram: %d, vscroll: %d, v_offset: %d\n",(vsram_off ? "B" : "A"), line, context->vsram[context->regs[REG_MODE_3] & 0x4 ? column : 0], vscroll, context->v_offset); 682 //printf("%s | line %d, vsram: %d, vscroll: %d, v_offset: %d\n",(vsram_off ? "B" : "A"), line, context->vsram[context->regs[REG_MODE_3] & 0x4 ? column : 0], vscroll, context->v_offset);
619 vscroll >>= vscroll_shift; 683 vscroll >>= vscroll_shift;
620 uint16_t hscroll_mask; 684 uint16_t hscroll_mask;
621 uint16_t v_mul; 685 uint16_t v_mul;
720 { 784 {
721 if (line >= 240) { 785 if (line >= 240) {
722 return; 786 return;
723 } 787 }
724 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context); 788 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context);
725 uint16_t *dst; 789 uint32_t *dst;
726 uint32_t *dst32;
727 uint8_t *sprite_buf, *plane_a, *plane_b; 790 uint8_t *sprite_buf, *plane_a, *plane_b;
728 int plane_a_off, plane_b_off; 791 int plane_a_off, plane_b_off;
729 if (col) 792 if (col)
730 { 793 {
731 col-=2; 794 col-=2;
732 if (context->b32) { 795 dst = context->framebuf;
733 dst32 = context->framebuf; 796 dst += line * 320 + col * 8;
734 dst32 += line * 320 + col * 8; 797 if (context->debug < 2) {
735 } else { 798 sprite_buf = context->linebuf + col * 8;
736 dst = context->framebuf; 799 uint8_t a_src, src;
737 dst += line * 320 + col * 8; 800 if (context->flags & FLAG_WINDOW) {
738 } 801 plane_a_off = context->buf_a_off;
739 sprite_buf = context->linebuf + col * 8; 802 a_src = DBG_SRC_W;
740 uint8_t a_src, src; 803 } else {
741 if (context->flags & FLAG_WINDOW) { 804 plane_a_off = context->buf_a_off - (context->hscroll_a & 0xF);
742 plane_a_off = context->buf_a_off; 805 a_src = DBG_SRC_A;
743 a_src = DBG_SRC_W; 806 }
744 } else { 807 plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF);
745 plane_a_off = context->buf_a_off - (context->hscroll_a & 0xF); 808 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7));
746 a_src = DBG_SRC_A; 809
747 } 810 if (context->regs[REG_MODE_4] & BIT_HILIGHT) {
748 plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF); 811 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) {
749 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7)); 812 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK);
750 813 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK);
751 if (context->regs[REG_MODE_4] & BIT_HILIGHT) { 814 uint8_t pixel = context->regs[REG_BG_COLOR];
752 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) { 815 uint32_t *colors = context->colors;
753 uint8_t pixel; 816 src = DBG_SRC_BG;
754 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK); 817 if (*plane_b & 0xF) {
755 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK); 818 pixel = *plane_b;
756 uint32_t * colors = context->colors; 819 src = DBG_SRC_B;
757 src = 0; 820 }
758 pixel = context->regs[REG_BG_COLOR]; 821 uint8_t intensity = *plane_b & BUF_BIT_PRIORITY;
759 src = DBG_SRC_BG; 822 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
760 if (*plane_b & 0xF) { 823 pixel = *plane_a;
761 pixel = *plane_b; 824 src = DBG_SRC_A;
762 src = DBG_SRC_B; 825 }
763 } 826 intensity |= *plane_a & BUF_BIT_PRIORITY;
764 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { 827 if (*sprite_buf & 0xF && (*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
765 pixel = *plane_a; 828 if ((*sprite_buf & 0x3F) == 0x3E) {
766 src = DBG_SRC_A; 829 intensity += BUF_BIT_PRIORITY;
767 } 830 } else if ((*sprite_buf & 0x3F) == 0x3F) {
768 if (*sprite_buf & 0xF) { 831 intensity = 0;
769 uint8_t sprite_color = *sprite_buf & 0x3F; 832 } else {
770 if (sprite_color == 0x3E) { 833 pixel = *sprite_buf;
834 src = DBG_SRC_S;
835 if ((pixel & 0xF) == 0xE) {
836 intensity = BUF_BIT_PRIORITY;
837 } else {
838 intensity |= pixel & BUF_BIT_PRIORITY;
839 }
840 }
841 }
842 if (!intensity) {
843 src |= DBG_SHADOW;
844 colors += CRAM_SIZE;
845 } else if (intensity == BUF_BIT_PRIORITY*2) {
846 src |= DBG_HILIGHT;
771 colors += CRAM_SIZE*2; 847 colors += CRAM_SIZE*2;
772 src |= DBG_HILIGHT; 848 }
773 } else if (sprite_color == 0x3F) { 849
774 colors += CRAM_SIZE; 850 uint32_t outpixel;
775 src |= DBG_SHADOW; 851 if (context->debug) {
776 } else if ((*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { 852 outpixel = context->debugcolors[src];
853 } else {
854 outpixel = colors[pixel & 0x3F];
855 }
856 *(dst++) = outpixel;
857 }
858 } else {
859 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) {
860 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK);
861 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK);
862 uint8_t pixel = context->regs[REG_BG_COLOR];
863 src = DBG_SRC_BG;
864 if (*plane_b & 0xF) {
865 pixel = *plane_b;
866 src = DBG_SRC_B;
867 }
868 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
869 pixel = *plane_a;
870 src = DBG_SRC_A;
871 }
872 if (*sprite_buf & 0xF && (*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
777 pixel = *sprite_buf; 873 pixel = *sprite_buf;
778 src = DBG_SRC_S; 874 src = DBG_SRC_S;
779 if ((pixel & 0xF) == 0xE) {
780 src |= DBG_SHADOW;
781 colors += CRAM_SIZE;
782 }
783
784 } 875 }
785 } else if (!((*plane_a | *plane_b) & BUF_BIT_PRIORITY)) { 876 uint32_t outpixel;
786 colors += CRAM_SIZE; 877 if (context->debug) {
787 src |= DBG_SHADOW; 878 outpixel = context->debugcolors[src];
788 } 879 } else {
789 pixel &= 0x3F; 880 outpixel = context->colors[pixel & 0x3F];
790 uint32_t outpixel; 881 }
791 if (context->debug) {
792 outpixel = context->debugcolors[src];
793 } else {
794 outpixel = colors[pixel];
795 }
796 if (context->b32) {
797 *(dst32++) = outpixel;
798 } else {
799 *(dst++) = outpixel; 882 *(dst++) = outpixel;
800 } 883 }
801 //*dst = (context->cram[pixel & 0x3F] & 0xEEE) | ((pixel & BUF_BIT_PRIORITY) ? FBUF_BIT_PRIORITY : 0) | src; 884 }
802 } 885 } else if (context->debug == 2) {
803 } else { 886 if (col < 32) {
804 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) { 887 *(dst++) = context->colors[col * 2];
805 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK); 888 *(dst++) = context->colors[col * 2];
806 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK); 889 *(dst++) = context->colors[col * 2];
807 uint8_t pixel = context->regs[REG_BG_COLOR]; 890 *(dst++) = context->colors[col * 2];
808 src = DBG_SRC_BG; 891 *(dst++) = context->colors[col * 2 + 1];
809 if (*plane_b & 0xF) { 892 *(dst++) = context->colors[col * 2 + 1];
810 pixel = *plane_b; 893 *(dst++) = context->colors[col * 2 + 1];
811 src = DBG_SRC_B; 894 *(dst++) = context->colors[col * 2 + 1];
812 } 895 *(dst++) = context->colors[col * 2 + 2];
813 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { 896 *(dst++) = context->colors[col * 2 + 2];
814 pixel = *plane_a; 897 *(dst++) = context->colors[col * 2 + 2];
815 src = DBG_SRC_A; 898 *(dst++) = context->colors[col * 2 + 2];
816 } 899 *(dst++) = context->colors[col * 2 + 3];
817 if (*sprite_buf & 0xF && (*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) { 900 *(dst++) = context->colors[col * 2 + 3];
818 pixel = *sprite_buf; 901 *(dst++) = context->colors[col * 2 + 3];
819 src = DBG_SRC_S; 902 *(dst++) = context->colors[col * 2 + 3];
820 } 903 } else if (col == 32 || line >= 192) {
821 uint32_t outpixel; 904 for (int32_t i = 0; i < 16; i ++) {
822 if (context->debug) { 905 *(dst++) = 0;
823 outpixel = context->debugcolors[src]; 906 }
824 } else { 907 } else {
825 outpixel = context->colors[pixel & 0x3F]; 908 for (int32_t i = 0; i < 16; i ++) {
826 } 909 *(dst++) = context->colors[line / 3 + (col - 34) * 0x20];
827 if (context->b32) { 910 }
828 *(dst32++) = outpixel; 911 }
829 } else { 912 } else {
830 *(dst++) = outpixel; 913 uint32_t base = (context->debug - 3) * 0x200;
831 } 914 uint32_t cell = base + (line / 8) * (context->regs[REG_MODE_4] & BIT_H40 ? 40 : 32) + col;
915 uint32_t address = (cell * 32 + (line % 8) * 4) & 0xFFFF;
916 for (int32_t i = 0; i < 4; i ++) {
917 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] >> 4)];
918 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] & 0xF)];
919 address++;
920 }
921 cell++;
922 address = (cell * 32 + (line % 8) * 4) & 0xFFFF;
923 for (int32_t i = 0; i < 4; i ++) {
924 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] >> 4)];
925 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] & 0xF)];
926 address++;
832 } 927 }
833 } 928 }
834 } 929 }
835 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 930 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
836 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 931 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
891 { 986 {
892 uint16_t address; 987 uint16_t address;
893 uint32_t mask; 988 uint32_t mask;
894 switch(linecyc) 989 switch(linecyc)
895 { 990 {
991 case 165:
992 case 166:
993 external_slot(context);
994 break;
896 //sprite render to line buffer starts 995 //sprite render to line buffer starts
897 case 0: 996 case 167:
898 context->cur_slot = MAX_DRAWS-1; 997 case 168:
899 memset(context->linebuf, 0, LINEBUF_SIZE); 998 case 169:
900 case 1: 999 case 170:
901 case 2:
902 case 3:
903 if (line == 0xFF) { 1000 if (line == 0xFF) {
904 external_slot(context); 1001 external_slot(context);
905 } else { 1002 } else {
906 render_sprite_cells(context); 1003 render_sprite_cells(context);
907 } 1004 }
908 break; 1005 break;
909 //sprite attribute table scan starts 1006 //sprite attribute table scan starts
910 case 4: 1007 case 171:
911 render_sprite_cells( context); 1008 render_sprite_cells( context);
912 context->sprite_index = 0x80;
913 context->slot_counter = MAX_SPRITES_LINE;
914 scan_sprite_table(line, context); 1009 scan_sprite_table(line, context);
915 break; 1010 break;
916 case 5: 1011 case 172:
917 case 6: 1012 case 173:
918 case 7: 1013 case 174:
919 case 8: 1014 case 175:
920 case 9: 1015 case 176:
921 case 10: 1016 case 177:
922 case 11: 1017 case 178:
923 case 12: 1018 case 179:
924 case 13: 1019 case 180:
925 case 14: 1020 case 181:
926 case 15: 1021 case 182:
927 case 16: 1022 case 229:
928 case 17: 1023 case 230:
929 case 18: 1024 case 231:
930 case 19: 1025 case 232:
931 case 20: 1026 case 233:
932 //!HSYNC asserted 1027 //!HSYNC asserted
933 case 21: 1028 case 234:
934 case 22: 1029 case 235:
935 render_sprite_cells(context); 1030 render_sprite_cells(context);
936 scan_sprite_table(line, context); 1031 scan_sprite_table(line, context);
937 break; 1032 break;
938 case 23: 1033 case 236:
939 external_slot(context); 1034 external_slot(context);
940 break; 1035 break;
941 case 24: 1036 case 237:
942 case 25: 1037 case 238:
943 case 26: 1038 case 239:
944 case 27: 1039 case 240:
945 case 28: 1040 case 241:
946 case 29: 1041 case 242:
947 case 30: 1042 case 243:
948 case 31: 1043 case 244:
949 case 32: 1044 case 245:
950 case 33: 1045 case 246:
951 case 34: 1046 case 247:
952 render_sprite_cells(context); 1047 render_sprite_cells(context);
953 scan_sprite_table(line, context); 1048 scan_sprite_table(line, context);
954 break; 1049 break;
955 case 35: 1050 case 248:
956 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; 1051 address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
957 mask = 0; 1052 mask = 0;
958 if (context->regs[REG_MODE_3] & 0x2) { 1053 if (context->regs[REG_MODE_3] & 0x2) {
959 mask |= 0xF8; 1054 mask |= 0xF8;
960 } 1055 }
965 address += line * 4; 1060 address += line * 4;
966 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; 1061 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
967 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; 1062 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
968 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); 1063 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b);
969 break; 1064 break;
970 case 36: 1065 case 249:
971 //!HSYNC high 1066 //!HSYNC high
972 case 37: 1067 case 250:
973 case 38: 1068 case 251:
974 case 39: 1069 case 252:
975 render_sprite_cells(context); 1070 render_sprite_cells(context);
976 scan_sprite_table(line, context); 1071 scan_sprite_table(line, context);
977 break; 1072 break;
978 case 40: 1073 case 253:
979 read_map_scroll_a(0, line, context); 1074 read_map_scroll_a(0, line, context);
980 break; 1075 break;
981 case 41: 1076 case 254:
982 render_sprite_cells(context); 1077 render_sprite_cells(context);
983 scan_sprite_table(line, context); 1078 scan_sprite_table(line, context);
984 break; 1079 break;
985 case 42: 1080 case 255:
986 render_map_1(context); 1081 render_map_1(context);
987 scan_sprite_table(line, context);//Just a guess 1082 scan_sprite_table(line, context);//Just a guess
988 break; 1083 break;
989 case 43: 1084 case 0:
990 render_map_2(context); 1085 render_map_2(context);
991 scan_sprite_table(line, context);//Just a guess 1086 scan_sprite_table(line, context);//Just a guess
992 break; 1087 break;
993 case 44: 1088 case 1:
994 read_map_scroll_b(0, line, context); 1089 read_map_scroll_b(0, line, context);
995 break; 1090 break;
996 case 45: 1091 case 2:
997 render_sprite_cells(context); 1092 render_sprite_cells(context);
998 scan_sprite_table(line, context); 1093 scan_sprite_table(line, context);
999 break; 1094 break;
1000 case 46: 1095 case 3:
1001 render_map_3(context); 1096 render_map_3(context);
1002 scan_sprite_table(line, context);//Just a guess 1097 scan_sprite_table(line, context);//Just a guess
1003 break; 1098 break;
1004 case 47: 1099 case 4:
1005 render_map_output(line, 0, context); 1100 render_map_output(line, 0, context);
1006 scan_sprite_table(line, context);//Just a guess 1101 scan_sprite_table(line, context);//Just a guess
1007 //reverse context slot counter so it counts the number of sprite slots 1102 //reverse context slot counter so it counts the number of sprite slots
1008 //filled rather than the number of available slots 1103 //filled rather than the number of available slots
1009 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; 1104 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter;
1010 context->cur_slot = MAX_SPRITES_LINE-1; 1105 context->cur_slot = MAX_SPRITES_LINE-1;
1011 context->sprite_draws = MAX_DRAWS; 1106 context->sprite_draws = MAX_DRAWS;
1012 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); 1107 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
1013 break; 1108 break;
1014 COLUMN_RENDER_BLOCK(2, 48) 1109 COLUMN_RENDER_BLOCK(2, 5)
1015 COLUMN_RENDER_BLOCK(4, 56) 1110 COLUMN_RENDER_BLOCK(4, 13)
1016 COLUMN_RENDER_BLOCK(6, 64) 1111 COLUMN_RENDER_BLOCK(6, 21)
1017 COLUMN_RENDER_BLOCK_REFRESH(8, 72) 1112 COLUMN_RENDER_BLOCK_REFRESH(8, 29)
1018 COLUMN_RENDER_BLOCK(10, 80) 1113 COLUMN_RENDER_BLOCK(10, 37)
1019 COLUMN_RENDER_BLOCK(12, 88) 1114 COLUMN_RENDER_BLOCK(12, 45)
1020 COLUMN_RENDER_BLOCK(14, 96) 1115 COLUMN_RENDER_BLOCK(14, 53)
1021 COLUMN_RENDER_BLOCK_REFRESH(16, 104) 1116 COLUMN_RENDER_BLOCK_REFRESH(16, 61)
1022 COLUMN_RENDER_BLOCK(18, 112) 1117 COLUMN_RENDER_BLOCK(18, 69)
1023 COLUMN_RENDER_BLOCK(20, 120) 1118 COLUMN_RENDER_BLOCK(20, 77)
1024 COLUMN_RENDER_BLOCK(22, 128) 1119 COLUMN_RENDER_BLOCK(22, 85)
1025 COLUMN_RENDER_BLOCK_REFRESH(24, 136) 1120 COLUMN_RENDER_BLOCK_REFRESH(24, 93)
1026 COLUMN_RENDER_BLOCK(26, 144) 1121 COLUMN_RENDER_BLOCK(26, 101)
1027 COLUMN_RENDER_BLOCK(28, 152) 1122 COLUMN_RENDER_BLOCK(28, 109)
1028 COLUMN_RENDER_BLOCK(30, 160) 1123 COLUMN_RENDER_BLOCK(30, 117)
1029 COLUMN_RENDER_BLOCK_REFRESH(32, 168) 1124 COLUMN_RENDER_BLOCK_REFRESH(32, 125)
1030 COLUMN_RENDER_BLOCK(34, 176) 1125 COLUMN_RENDER_BLOCK(34, 133)
1031 COLUMN_RENDER_BLOCK(36, 184) 1126 COLUMN_RENDER_BLOCK(36, 141)
1032 COLUMN_RENDER_BLOCK(38, 192) 1127 COLUMN_RENDER_BLOCK(38, 149)
1033 COLUMN_RENDER_BLOCK_REFRESH(40, 200) 1128 COLUMN_RENDER_BLOCK_REFRESH(40, 157)
1034 case 208:
1035 case 209:
1036 external_slot(context);
1037 break;
1038 default:
1039 //leftovers from HSYNC clock change nonsense
1040 break;
1041 } 1129 }
1042 } 1130 }
1043 1131
1044 void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context) 1132 void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context)
1045 { 1133 {
1046 uint16_t address; 1134 uint16_t address;
1047 uint32_t mask; 1135 uint32_t mask;
1048 switch(linecyc) 1136 switch(linecyc)
1049 { 1137 {
1138 case 132:
1139 case 133:
1140 external_slot(context);
1141 break;
1050 //sprite render to line buffer starts 1142 //sprite render to line buffer starts
1051 case 0: 1143 case 134:
1052 context->cur_slot = MAX_DRAWS_H32-1; 1144 case 135:
1053 memset(context->linebuf, 0, LINEBUF_SIZE); 1145 case 136:
1054 case 1: 1146 case 137:
1055 case 2:
1056 case 3:
1057 if (line == 0xFF) { 1147 if (line == 0xFF) {
1058 external_slot(context); 1148 external_slot(context);
1059 } else { 1149 } else {
1060 render_sprite_cells(context); 1150 render_sprite_cells(context);
1061 } 1151 }
1062 break; 1152 break;
1063 //sprite attribute table scan starts 1153 //sprite attribute table scan starts
1064 case 4: 1154 case 138:
1065 render_sprite_cells( context); 1155 render_sprite_cells( context);
1066 context->sprite_index = 0x80;
1067 context->slot_counter = MAX_SPRITES_LINE_H32;
1068 scan_sprite_table(line, context); 1156 scan_sprite_table(line, context);
1069 break; 1157 break;
1070 case 5: 1158 case 139:
1071 case 6: 1159 case 140:
1072 case 7: 1160 case 141:
1073 case 8: 1161 case 142:
1074 case 9: 1162 case 143:
1075 case 10: 1163 case 144:
1076 case 11: 1164 case 145:
1077 case 12: 1165 case 146:
1078 case 13: 1166 case 147:
1079 render_sprite_cells(context); 1167 render_sprite_cells(context);
1080 scan_sprite_table(line, context); 1168 scan_sprite_table(line, context);
1081 case 14: 1169 case 233:
1082 external_slot(context); 1170 external_slot(context);
1083 break; 1171 break;
1084 case 15: 1172 case 234:
1085 case 16: 1173 case 235:
1086 case 17: 1174 case 236:
1087 case 18: 1175 case 237:
1088 case 19: 1176 case 238:
1089 //HSYNC start 1177 //HSYNC start
1090 case 20: 1178 case 239:
1091 case 21: 1179 case 240:
1092 case 22: 1180 case 241:
1093 case 23: 1181 case 242:
1094 case 24: 1182 case 243:
1095 case 25: 1183 case 244:
1096 case 26: 1184 case 245:
1097 render_sprite_cells(context); 1185 render_sprite_cells(context);
1098 scan_sprite_table(line, context); 1186 scan_sprite_table(line, context);
1099 break; 1187 break;
1100 case 27: 1188 case 246:
1101 external_slot(context); 1189 external_slot(context);
1102 break; 1190 break;
1103 case 28: 1191 case 247:
1104 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; 1192 address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
1105 mask = 0; 1193 mask = 0;
1106 if (context->regs[REG_MODE_3] & 0x2) { 1194 if (context->regs[REG_MODE_3] & 0x2) {
1107 mask |= 0xF8; 1195 mask |= 0xF8;
1108 } 1196 }
1113 address += line * 4; 1201 address += line * 4;
1114 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; 1202 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
1115 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; 1203 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
1116 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); 1204 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b);
1117 break; 1205 break;
1118 case 29: 1206 case 248:
1119 case 30: 1207 case 249:
1120 case 31: 1208 case 250:
1121 case 32: 1209 case 251:
1122 render_sprite_cells(context); 1210 render_sprite_cells(context);
1123 scan_sprite_table(line, context); 1211 scan_sprite_table(line, context);
1124 break; 1212 break;
1125 //!HSYNC high 1213 //!HSYNC high
1126 case 33: 1214 case 252:
1127 read_map_scroll_a(0, line, context); 1215 read_map_scroll_a(0, line, context);
1128 break; 1216 break;
1129 case 34: 1217 case 253:
1130 render_sprite_cells(context); 1218 render_sprite_cells(context);
1131 scan_sprite_table(line, context); 1219 scan_sprite_table(line, context);
1132 break; 1220 break;
1133 case 35: 1221 case 254:
1134 render_map_1(context); 1222 render_map_1(context);
1135 scan_sprite_table(line, context);//Just a guess 1223 scan_sprite_table(line, context);//Just a guess
1136 break; 1224 break;
1137 case 36: 1225 case 255:
1138 render_map_2(context); 1226 render_map_2(context);
1139 scan_sprite_table(line, context);//Just a guess 1227 scan_sprite_table(line, context);//Just a guess
1140 break; 1228 break;
1141 case 37: 1229 case 0:
1142 read_map_scroll_b(0, line, context); 1230 read_map_scroll_b(0, line, context);
1143 break; 1231 break;
1144 case 38: 1232 case 1:
1145 render_sprite_cells(context); 1233 render_sprite_cells(context);
1146 scan_sprite_table(line, context); 1234 scan_sprite_table(line, context);
1147 break; 1235 break;
1148 case 39: 1236 case 2:
1149 render_map_3(context); 1237 render_map_3(context);
1150 scan_sprite_table(line, context);//Just a guess 1238 scan_sprite_table(line, context);//Just a guess
1151 break; 1239 break;
1152 case 40: 1240 case 3:
1153 render_map_output(line, 0, context); 1241 render_map_output(line, 0, context);
1154 scan_sprite_table(line, context);//Just a guess 1242 scan_sprite_table(line, context);//Just a guess
1155 //reverse context slot counter so it counts the number of sprite slots 1243 //reverse context slot counter so it counts the number of sprite slots
1156 //filled rather than the number of available slots 1244 //filled rather than the number of available slots
1157 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; 1245 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter;
1158 context->cur_slot = MAX_SPRITES_LINE_H32-1; 1246 context->cur_slot = MAX_SPRITES_LINE_H32-1;
1159 context->sprite_draws = MAX_DRAWS_H32; 1247 context->sprite_draws = MAX_DRAWS_H32;
1160 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); 1248 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
1161 break; 1249 break;
1162 COLUMN_RENDER_BLOCK(2, 41) 1250 COLUMN_RENDER_BLOCK(2, 4)
1163 COLUMN_RENDER_BLOCK(4, 49) 1251 COLUMN_RENDER_BLOCK(4, 12)
1164 COLUMN_RENDER_BLOCK(6, 57) 1252 COLUMN_RENDER_BLOCK(6, 20)
1165 COLUMN_RENDER_BLOCK_REFRESH(8, 65) 1253 COLUMN_RENDER_BLOCK_REFRESH(8, 28)
1166 COLUMN_RENDER_BLOCK(10, 73) 1254 COLUMN_RENDER_BLOCK(10, 36)
1167 COLUMN_RENDER_BLOCK(12, 81) 1255 COLUMN_RENDER_BLOCK(12, 44)
1168 COLUMN_RENDER_BLOCK(14, 89) 1256 COLUMN_RENDER_BLOCK(14, 52)
1169 COLUMN_RENDER_BLOCK_REFRESH(16, 97) 1257 COLUMN_RENDER_BLOCK_REFRESH(16, 60)
1170 COLUMN_RENDER_BLOCK(18, 105) 1258 COLUMN_RENDER_BLOCK(18, 68)
1171 COLUMN_RENDER_BLOCK(20, 113) 1259 COLUMN_RENDER_BLOCK(20, 76)
1172 COLUMN_RENDER_BLOCK(22, 121) 1260 COLUMN_RENDER_BLOCK(22, 84)
1173 COLUMN_RENDER_BLOCK_REFRESH(24, 129) 1261 COLUMN_RENDER_BLOCK_REFRESH(24, 92)
1174 COLUMN_RENDER_BLOCK(26, 137) 1262 COLUMN_RENDER_BLOCK(26, 100)
1175 COLUMN_RENDER_BLOCK(28, 145) 1263 COLUMN_RENDER_BLOCK(28, 108)
1176 COLUMN_RENDER_BLOCK(30, 153) 1264 COLUMN_RENDER_BLOCK(30, 116)
1177 COLUMN_RENDER_BLOCK_REFRESH(32, 161) 1265 COLUMN_RENDER_BLOCK_REFRESH(32, 124)
1178 case 169:
1179 case 170:
1180 external_slot(context);
1181 break;
1182 } 1266 }
1183 } 1267 }
1184 1268
1185 void vdp_h40_line(uint32_t line, vdp_context * context) 1269 void vdp_h40_line(uint32_t line, vdp_context * context)
1186 { 1270 {
1187 context->cur_slot = MAX_DRAWS-1; 1271 context->cur_slot = MAX_DRAWS-1;
1188 memset(context->linebuf, 0, LINEBUF_SIZE); 1272 memset(context->linebuf, 0, LINEBUF_SIZE);
1189 if (line == 0xFF) { 1273 if (line == 0xFF) {
1274 external_slot(context);
1275 if (context->flags & FLAG_DMA_RUN) {
1276 run_dma_src(context, 0);
1277 }
1278 external_slot(context);
1279 if (context->flags & FLAG_DMA_RUN) {
1280 run_dma_src(context, 0);
1281 }
1190 external_slot(context); 1282 external_slot(context);
1191 if (context->flags & FLAG_DMA_RUN) { 1283 if (context->flags & FLAG_DMA_RUN) {
1192 run_dma_src(context, 0); 1284 run_dma_src(context, 0);
1193 } 1285 }
1194 external_slot(context); 1286 external_slot(context);
1238 } 1330 }
1239 read_sprite_x(line, context); 1331 read_sprite_x(line, context);
1240 1332
1241 read_sprite_x(line, context); 1333 read_sprite_x(line, context);
1242 } 1334 }
1243 external_slot(context); 1335
1244 if (context->flags & FLAG_DMA_RUN) {
1245 run_dma_src(context, 0);
1246 }
1247 external_slot(context);
1248 return; 1336 return;
1337 }
1338 external_slot(context);
1339 if (context->flags & FLAG_DMA_RUN) {
1340 run_dma_src(context, 0);
1341 }
1342 external_slot(context);
1343 if (context->flags & FLAG_DMA_RUN) {
1344 run_dma_src(context, 0);
1249 } 1345 }
1250 1346
1251 render_sprite_cells(context); 1347 render_sprite_cells(context);
1252 render_sprite_cells(context); 1348 render_sprite_cells(context);
1253 render_sprite_cells(context); 1349 render_sprite_cells(context);
1354 read_map_scroll_b(column, line, context); 1450 read_map_scroll_b(column, line, context);
1355 read_sprite_x(line, context); 1451 read_sprite_x(line, context);
1356 render_map_3(context); 1452 render_map_3(context);
1357 render_map_output(line, column, context); 1453 render_map_output(line, column, context);
1358 } 1454 }
1359 external_slot(context);
1360 if (context->flags & FLAG_DMA_RUN) {
1361 run_dma_src(context, 0);
1362 }
1363 external_slot(context);
1364 } 1455 }
1365 1456
1366 void latch_mode(vdp_context * context) 1457 void latch_mode(vdp_context * context)
1367 { 1458 {
1368 context->latched_mode = (context->regs[REG_MODE_4] & 0x81) | (context->regs[REG_MODE_2] & BIT_PAL); 1459 context->latched_mode = context->regs[REG_MODE_2] & BIT_PAL;
1369 } 1460 }
1370 1461
1371 void check_render_bg(vdp_context * context, int32_t line, uint32_t slot) 1462 void check_render_bg(vdp_context * context, int32_t line, uint32_t slot)
1372 { 1463 {
1373 if (line > 0) { 1464 int starti = -1;
1374 line -= 1; 1465 if (context->regs[REG_MODE_4] & BIT_H40) {
1375 int starti = -1; 1466 if (slot >= 12 && slot < 172) {
1376 if (context->latched_mode & BIT_H40) { 1467 uint32_t x = (slot-12)*2;
1377 if (slot >= 55 && slot < 210) { 1468 starti = line * 320 + x;
1378 uint32_t x = (slot-55)*2; 1469 }
1379 starti = line * 320 + x; 1470 } else {
1380 } else if (slot < 5) { 1471 if (slot >= 11 && slot < 139) {
1381 uint32_t x = (slot + 155)*2; 1472 uint32_t x = (slot-11)*2;
1382 starti = (line-1)*320 + x; 1473 starti = line * 320 + x;
1383 } 1474 }
1384 } else { 1475 }
1385 if (slot >= 48 && slot < 171) { 1476 if (starti >= 0) {
1386 uint32_t x = (slot-48)*2; 1477 uint32_t color = context->colors[context->regs[REG_BG_COLOR]];
1387 starti = line * 320 + x; 1478 uint32_t * start = context->framebuf;
1388 } else if (slot < 5) { 1479 start += starti;
1389 uint32_t x = (slot + 123)*2; 1480 for (int i = 0; i < 2; i++) {
1390 starti = (line-1)*320 + x; 1481 *(start++) = color;
1391 } 1482 }
1392 } 1483 }
1393 if (starti >= 0) { 1484 }
1394 if (context->b32) { 1485
1395 uint32_t color = context->colors[context->regs[REG_BG_COLOR]]; 1486 uint32_t const h40_hsync_cycles[] = {19, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 19};
1396 uint32_t * start = context->framebuf; 1487
1397 start += starti; 1488 void vdp_advance_line(vdp_context *context)
1398 for (int i = 0; i < 2; i++) { 1489 {
1399 *(start++) = color; 1490 context->vcounter++;
1400 } 1491 context->vcounter &= 0x1FF;
1401 } else { 1492 if (context->flags2 & FLAG2_REGION_PAL) {
1402 uint16_t color = context->colors[context->regs[REG_BG_COLOR]]; 1493 if (context->latched_mode & BIT_PAL) {
1403 uint16_t * start = context->framebuf; 1494 if (context->vcounter == 0x10B) {
1404 start += starti; 1495 context->vcounter = 0x1D2;
1405 for (int i = 0; i < 2; i++) { 1496 }
1406 *(start++) = color; 1497 } else if (context->vcounter == 0x103){
1407 } 1498 context->vcounter = 0x1CA;
1408 } 1499 }
1409 } 1500 } else if (!(context->latched_mode & BIT_PAL) && context->vcounter == 0xEB) {
1501 context->vcounter = 0x1E5;
1502 }
1503
1504 if (context->vcounter > (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
1505 context->hint_counter = context->regs[REG_HINT];
1506 } else if (context->hint_counter) {
1507 context->hint_counter--;
1508 } else {
1509 context->flags2 |= FLAG2_HINT_PENDING;
1510 context->pending_hint_start = context->cycles;
1511 context->hint_counter = context->regs[REG_HINT];
1410 } 1512 }
1411 } 1513 }
1412 1514
1413 void vdp_run_context(vdp_context * context, uint32_t target_cycles) 1515 void vdp_run_context(vdp_context * context, uint32_t target_cycles)
1414 { 1516 {
1415 while(context->cycles < target_cycles) 1517 while(context->cycles < target_cycles)
1416 { 1518 {
1417 context->flags &= ~FLAG_UNUSED_SLOT; 1519 context->flags &= ~FLAG_UNUSED_SLOT;
1418 uint32_t line = context->cycles / MCLKS_LINE; 1520 uint32_t line = context->vcounter;
1419 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 1521 uint32_t slot = context->hslot;
1420 if (!context->cycles) { 1522
1523 if (!line && !slot) {
1524 //TODO: Figure out when this actually happens
1421 latch_mode(context); 1525 latch_mode(context);
1422 } 1526 }
1423 uint32_t linecyc = context->cycles % MCLKS_LINE; 1527 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
1424 if (linecyc == 0) { 1528
1425 if (line <= 1 || line >= active_lines) { 1529 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40;
1426 context->hint_counter = context->regs[REG_HINT]; 1530 if (is_h40) {
1427 } else if (context->hint_counter) { 1531 if (slot == 167) {
1428 context->hint_counter--; 1532 context->cur_slot = MAX_DRAWS-1;
1533 memset(context->linebuf, 0, LINEBUF_SIZE);
1534 } else if (slot == 171) {
1535 context->sprite_index = 0x80;
1536 context->slot_counter = MAX_SPRITES_LINE;
1537 }
1538 } else {
1539 if (slot == 134) {
1540 context->cur_slot = MAX_DRAWS_H32-1;
1541 memset(context->linebuf, 0, LINEBUF_SIZE);
1542 } else if (slot == 138) {
1543 context->sprite_index = 0x80;
1544 context->slot_counter = MAX_SPRITES_LINE_H32;
1545 }
1546 }
1547 if(line == inactive_start) {
1548 uint32_t intslot = context->regs[REG_MODE_4] & BIT_H40 ? VINT_SLOT_H40 : VINT_SLOT_H32;
1549 if (slot == intslot) {
1550 context->flags2 |= FLAG2_VINT_PENDING;
1551 context->pending_vint_start = context->cycles;
1552 }
1553 }
1554 uint32_t inccycles;
1555 //line 0x1FF is basically active even though it's not displayed
1556 uint8_t active_slot = line < inactive_start || line == 0x1FF;
1557 if (is_h40) {
1558 if (slot < HSYNC_SLOT_H40 || slot >= HSYNC_END_H40) {
1559 inccycles = MCLKS_SLOT_H40;
1429 } else { 1560 } else {
1430 context->flags2 |= FLAG2_HINT_PENDING; 1561 inccycles = h40_hsync_cycles[slot-HSYNC_SLOT_H40];
1431 context->hint_counter = context->regs[REG_HINT]; 1562 }
1432 } 1563 //the first inactive line behaves as an active one for the first 4 slots
1433 } else if(line == active_lines) { 1564 if (line == inactive_start && slot > 166 && slot < 171) {
1434 uint32_t intcyc = context->latched_mode & BIT_H40 ? VINT_CYCLE_H40 : VINT_CYCLE_H32; 1565 active_slot = 1;
1435 if (linecyc == intcyc) {
1436 context->flags2 |= FLAG2_VINT_PENDING;
1437 }
1438 }
1439 uint32_t inccycles, slot;
1440 if (context->latched_mode & BIT_H40){
1441 if (linecyc < MCLKS_SLOT_H40*HSYNC_SLOT_H40) {
1442 slot = linecyc/MCLKS_SLOT_H40;
1443 inccycles = MCLKS_SLOT_H40;
1444 } else if(linecyc < MCLK_WEIRD_END) {
1445 switch(linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40))
1446 {
1447 case 0:
1448 inccycles = 19;
1449 slot = 0;
1450 break;
1451 case 19:
1452 slot = 1;
1453 inccycles = 20;
1454 break;
1455 case 39:
1456 slot = 2;
1457 inccycles = 20;
1458 break;
1459 case 59:
1460 slot = 3;
1461 inccycles = 20;
1462 break;
1463 case 79:
1464 slot = 4;
1465 inccycles = 18;
1466 break;
1467 case 97:
1468 slot = 5;
1469 inccycles = 20;
1470 break;
1471 case 117:
1472 slot = 6;
1473 inccycles = 20;
1474 break;
1475 case 137:
1476 slot = 7;
1477 inccycles = 20;
1478 break;
1479 case 157:
1480 slot = 8;
1481 inccycles = 18;
1482 break;
1483 case 175:
1484 slot = 9;
1485 inccycles = 20;
1486 break;
1487 case 195:
1488 slot = 10;
1489 inccycles = 20;
1490 break;
1491 case 215:
1492 slot = 11;
1493 inccycles = 20;
1494 break;
1495 case 235:
1496 slot = 12;
1497 inccycles = 18;
1498 break;
1499 case 253:
1500 slot = 13;
1501 inccycles = 20;
1502 break;
1503 case 273:
1504 slot = 14;
1505 inccycles = 20;
1506 break;
1507 case 293:
1508 slot = 15;
1509 inccycles = 20;
1510 break;
1511 case 313:
1512 slot = 16;
1513 inccycles = 19;
1514 break;
1515 default:
1516 fprintf(stderr, "cycles after weirdness %d\n", linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40));
1517 exit(1);
1518 }
1519 slot += HSYNC_SLOT_H40;
1520 } else {
1521 slot = (linecyc-MCLK_WEIRD_END)/MCLKS_SLOT_H40 + SLOT_WEIRD_END;
1522 inccycles = MCLKS_SLOT_H40;
1523 } 1566 }
1524 } else { 1567 } else {
1525 inccycles = MCLKS_SLOT_H32; 1568 inccycles = MCLKS_SLOT_H32;
1526 slot = linecyc/MCLKS_SLOT_H32; 1569 //the first inactive line behaves as an active one for the first 4 slots
1527 } 1570 if (line == inactive_start && slot > 166 && slot < 171) {
1528 if ((line < active_lines || (line == active_lines && linecyc < (context->latched_mode & BIT_H40 ? 64 : 80))) && context->regs[REG_MODE_2] & DISPLAY_ENABLE) { 1571 active_slot = 1;
1529 //first sort-of active line is treated as 255 internally 1572 }
1530 //it's used for gathering sprite info for line 1573 }
1531 line = (line - 1) & 0xFF; 1574 uint8_t inc_slot = 1;
1532 1575 if (context->regs[REG_MODE_2] & DISPLAY_ENABLE && active_slot) {
1533 //Convert to slot number 1576 //run VDP rendering for a slot or a line
1534 if (context->latched_mode & BIT_H40){ 1577 if (is_h40) {
1535 if (!slot && line != (active_lines-1) && (target_cycles - context->cycles) >= MCLKS_LINE) { 1578 if (slot == LINE_CHANGE_H40 && line < inactive_start && (target_cycles - context->cycles) >= MCLKS_LINE) {
1536 vdp_h40_line(line, context); 1579 vdp_h40_line(line, context);
1537 inccycles = MCLKS_LINE; 1580 inccycles = MCLKS_LINE;
1581 inc_slot = 0;
1538 } else { 1582 } else {
1539 vdp_h40(line, slot, context); 1583 vdp_h40(line, slot, context);
1540 } 1584 }
1541 } else { 1585 } else {
1542 vdp_h32(line, slot, context); 1586 vdp_h32(line, slot, context);
1543 } 1587 }
1544 } else { 1588 } else {
1545 if (!is_refresh(context, slot)) { 1589 if (!is_refresh(context, slot)) {
1546 external_slot(context); 1590 external_slot(context);
1547 } 1591 }
1548 if (line < active_lines) { 1592 if (line < inactive_start) {
1549 check_render_bg(context, line, slot); 1593 check_render_bg(context, line, slot);
1550 } 1594 }
1551 } 1595 }
1552 if (context->flags & FLAG_DMA_RUN && !is_refresh(context, slot)) { 1596 if (context->flags & FLAG_DMA_RUN && !is_refresh(context, slot)) {
1553 run_dma_src(context, slot); 1597 run_dma_src(context, slot);
1554 } 1598 }
1555 context->cycles += inccycles; 1599 context->cycles += inccycles;
1600 if (inc_slot) {
1601 context->hslot++;
1602 context->hslot &= 0xFF;
1603 if (is_h40) {
1604 if (context->hslot == LINE_CHANGE_H40) {
1605 vdp_advance_line(context);
1606 if (context->vcounter == (inactive_start + 8)) {
1607 context->frame++;
1608 }
1609 } else if (context->hslot == 183) {
1610 context->hslot = 229;
1611 }
1612 } else {
1613 if (context->hslot == LINE_CHANGE_H32) {
1614 vdp_advance_line(context);
1615 if (context->vcounter == (inactive_start + 8)) {
1616 context->frame++;
1617 }
1618 } else if (context->hslot == 148) {
1619 context->hslot = 233;
1620 }
1621 }
1622
1623 } else {
1624 vdp_advance_line(context);
1625 }
1556 } 1626 }
1557 } 1627 }
1558 1628
1559 uint32_t vdp_run_to_vblank(vdp_context * context) 1629 uint32_t vdp_run_to_vblank(vdp_context * context)
1560 { 1630 {
1561 uint32_t target_cycles = ((context->latched_mode & BIT_PAL) ? PAL_ACTIVE : NTSC_ACTIVE) * MCLKS_LINE; 1631 uint32_t target_cycles = ((context->latched_mode & BIT_PAL) ? PAL_INACTIVE_START : NTSC_INACTIVE_START) * MCLKS_LINE;
1562 vdp_run_context(context, target_cycles); 1632 vdp_run_context(context, target_cycles);
1563 return context->cycles; 1633 return context->cycles;
1564 } 1634 }
1565 1635
1566 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles) 1636 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles)
1568 for(;;) { 1638 for(;;) {
1569 uint32_t dmalen = (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]; 1639 uint32_t dmalen = (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L];
1570 if (!dmalen) { 1640 if (!dmalen) {
1571 dmalen = 0x10000; 1641 dmalen = 0x10000;
1572 } 1642 }
1573 uint32_t min_dma_complete = dmalen * (context->latched_mode & BIT_H40 ? 16 : 20); 1643 uint32_t min_dma_complete = dmalen * (context->regs[REG_MODE_4] & BIT_H40 ? 16 : 20);
1574 if ((context->regs[REG_DMASRC_H] & 0xC0) == 0xC0 || (context->cd & 0xF) == VRAM_WRITE) { 1644 if ((context->regs[REG_DMASRC_H] & 0xC0) == 0xC0 || (context->cd & 0xF) == VRAM_WRITE) {
1575 //DMA copies take twice as long to complete since they require a read and a write 1645 //DMA copies take twice as long to complete since they require a read and a write
1576 //DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word 1646 //DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word
1577 min_dma_complete *= 2; 1647 min_dma_complete *= 2;
1578 } 1648 }
1604 // 1674 //
1605 if((context->regs[REG_DMASRC_H] & 0xC0) != 0x80) { 1675 if((context->regs[REG_DMASRC_H] & 0xC0) != 0x80) {
1606 //DMA copy or 68K -> VDP, transfer starts immediately 1676 //DMA copy or 68K -> VDP, transfer starts immediately
1607 context->flags |= FLAG_DMA_RUN; 1677 context->flags |= FLAG_DMA_RUN;
1608 context->dma_cd = context->cd; 1678 context->dma_cd = context->cd;
1609 //printf("DMA start at cycle %d\n", context->cycles); 1679 //printf("DMA start (length: %X) at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L], context->cycles, context->frame, context->vcounter, context->hslot);
1610 if (!(context->regs[REG_DMASRC_H] & 0x80)) { 1680 if (!(context->regs[REG_DMASRC_H] & 0x80)) {
1611 //printf("DMA Address: %X, New CD: %X, Source: %X, Length: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_H] << 17) | (context->regs[REG_DMASRC_M] << 9) | (context->regs[REG_DMASRC_L] << 1), context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L]); 1681 //printf("DMA Address: %X, New CD: %X, Source: %X, Length: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_H] << 17) | (context->regs[REG_DMASRC_M] << 9) | (context->regs[REG_DMASRC_L] << 1), context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L]);
1612 return 1; 1682 return 1;
1613 } else { 1683 } else {
1614 //printf("DMA Copy Address: %X, New CD: %X, Source: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]); 1684 //printf("DMA Copy Address: %X, New CD: %X, Source: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]);
1627 context->hv_latch = vdp_hv_counter_read(context); 1697 context->hv_latch = vdp_hv_counter_read(context);
1628 } 1698 }
1629 if (reg == REG_BG_COLOR) { 1699 if (reg == REG_BG_COLOR) {
1630 value &= 0x3F; 1700 value &= 0x3F;
1631 } 1701 }
1702 /*if (reg == REG_MODE_4 && ((value ^ context->regs[reg]) & BIT_H40)) {
1703 printf("Mode changed from H%d to H%d @ %d, frame: %d\n", context->regs[reg] & BIT_H40 ? 40 : 32, value & BIT_H40 ? 40 : 32, context->cycles, context->frame);
1704 }*/
1632 context->regs[reg] = value; 1705 context->regs[reg] = value;
1633 if (reg == REG_MODE_4) { 1706 if (reg == REG_MODE_4) {
1634 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES); 1707 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES);
1635 if (!context->double_res) { 1708 if (!context->double_res) {
1636 context->framebuf = context->oddbuf; 1709 context->framebuf = context->oddbuf;
1637 } 1710 }
1638 } 1711 }
1639 context->cd &= 0x3C; 1712 context->cd &= 0x3C;
1640 } 1713 }
1641 } else { 1714 } else {
1642 context->flags |= FLAG_PENDING; 1715 context->flags |= FLAG_PENDING;
1643 context->address = (context->address &0xC000) | (value & 0x3FFF); 1716 context->address = (context->address &0xC000) | (value & 0x3FFF);
1659 }*/ 1732 }*/
1660 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 1733 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
1661 context->flags &= ~FLAG_DMA_RUN; 1734 context->flags &= ~FLAG_DMA_RUN;
1662 } 1735 }
1663 while (context->fifo_write == context->fifo_read) { 1736 while (context->fifo_write == context->fifo_read) {
1664 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); 1737 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1665 } 1738 }
1666 fifo_entry * cur = context->fifo + context->fifo_write; 1739 fifo_entry * cur = context->fifo + context->fifo_write;
1667 cur->cycle = context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 1740 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
1668 cur->address = context->address; 1741 cur->address = context->address;
1669 cur->value = value; 1742 cur->value = value;
1670 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 1743 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80 && (context->regs[REG_MODE_2] & BIT_DMA_ENABLE)) {
1671 context->flags |= FLAG_DMA_RUN; 1744 context->flags |= FLAG_DMA_RUN;
1672 } 1745 }
1673 cur->cd = context->cd; 1746 cur->cd = context->cd;
1674 cur->partial = 0; 1747 cur->partial = 0;
1675 if (context->fifo_read < 0) { 1748 if (context->fifo_read < 0) {
1707 context->flags2 &= ~FLAG2_SPRITE_COLLIDE; 1780 context->flags2 &= ~FLAG2_SPRITE_COLLIDE;
1708 } 1781 }
1709 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) { 1782 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) {
1710 value |= 0x10; 1783 value |= 0x10;
1711 } 1784 }
1712 uint32_t line= context->cycles / MCLKS_LINE; 1785 uint32_t line= context->vcounter;
1713 uint32_t linecyc = context->cycles % MCLKS_LINE; 1786 uint32_t slot = context->hslot;
1714 if (line >= (context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) { 1787 uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START);
1788 if (
1789 (
1790 line > inactive_start
1791 && line < 0x1FF
1792 )
1793 || (line == inactive_start
1794 && (
1795 slot >= (context->regs[REG_MODE_4] & BIT_H40 ? VBLANK_START_H40 : VBLANK_START_H32)
1796 || slot < (context->regs[REG_MODE_4] & BIT_H40 ? LINE_CHANGE_H40 : LINE_CHANGE_H32)
1797 )
1798 )
1799 || (line == 0x1FF
1800 && slot < (context->regs[REG_MODE_4] & BIT_H40 ? VBLANK_START_H40 : VBLANK_START_H32))
1801 && slot >= (context->regs[REG_MODE_4] & BIT_H40 ? LINE_CHANGE_H40 : LINE_CHANGE_H32)
1802 || !(context->regs[REG_MODE_2] & BIT_DISP_EN)
1803 ) {
1715 value |= 0x8; 1804 value |= 0x8;
1716 } 1805 }
1717 if (linecyc < (context->latched_mode & BIT_H40 ? HBLANK_CLEAR_H40 : HBLANK_CLEAR_H32)) { 1806 if (context->regs[REG_MODE_4] & BIT_H40) {
1718 value |= 0x4; 1807 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) {
1808 value |= 0x4;
1809 }
1810 } else {
1811 if (slot < HBLANK_END_H32 || slot > HBLANK_START_H32) {
1812 value |= 0x4;
1813 }
1719 } 1814 }
1720 if (context->flags & FLAG_DMA_RUN) { 1815 if (context->flags & FLAG_DMA_RUN) {
1721 value |= 0x2; 1816 value |= 0x2;
1722 } 1817 }
1723 if (context->latched_mode & BIT_PAL) {//Not sure about this, need to verify 1818 if (context->flags2 & FLAG2_REGION_PAL) {
1724 value |= 0x1; 1819 value |= 0x1;
1725 } 1820 }
1726 //printf("status read at cycle %d returned %X\n", context->cycles, value); 1821 //printf("status read at cycle %d returned %X\n", context->cycles, value);
1727 return value; 1822 return value;
1728 } 1823 }
1739 } 1834 }
1740 //Not sure if the FIFO should be drained before processing a read or not, but it would make sense 1835 //Not sure if the FIFO should be drained before processing a read or not, but it would make sense
1741 context->flags &= ~FLAG_UNUSED_SLOT; 1836 context->flags &= ~FLAG_UNUSED_SLOT;
1742 //context->flags2 |= FLAG2_READ_PENDING; 1837 //context->flags2 |= FLAG2_READ_PENDING;
1743 while (!(context->flags & FLAG_UNUSED_SLOT)) { 1838 while (!(context->flags & FLAG_UNUSED_SLOT)) {
1744 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); 1839 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1745 } 1840 }
1746 uint16_t value = 0; 1841 uint16_t value = 0;
1747 switch (context->cd & 0xF) 1842 switch (context->cd & 0xF)
1748 { 1843 {
1749 case VRAM_READ: 1844 case VRAM_READ:
1750 value = context->vdpmem[context->address & 0xFFFE] << 8; 1845 value = context->vdpmem[context->address & 0xFFFE] << 8;
1751 context->flags &= ~FLAG_UNUSED_SLOT; 1846 context->flags &= ~FLAG_UNUSED_SLOT;
1752 context->flags2 |= FLAG2_READ_PENDING; 1847 context->flags2 |= FLAG2_READ_PENDING;
1753 while (!(context->flags & FLAG_UNUSED_SLOT)) { 1848 while (!(context->flags & FLAG_UNUSED_SLOT)) {
1754 vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20)); 1849 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
1755 } 1850 }
1756 value |= context->vdpmem[context->address | 1]; 1851 value |= context->vdpmem[context->address | 1];
1757 break; 1852 break;
1758 case VRAM_READ8: 1853 case VRAM_READ8:
1759 value = context->vdpmem[context->address ^ 1]; 1854 value = context->vdpmem[context->address ^ 1];
1780 uint16_t vdp_hv_counter_read(vdp_context * context) 1875 uint16_t vdp_hv_counter_read(vdp_context * context)
1781 { 1876 {
1782 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) { 1877 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) {
1783 return context->hv_latch; 1878 return context->hv_latch;
1784 } 1879 }
1785 uint32_t line= context->cycles / MCLKS_LINE; 1880 uint32_t line= context->vcounter & 0xFF;
1786 if (!line) { 1881 uint32_t linecyc = context->hslot;
1787 line = 0xFF;
1788 } else {
1789 line--;
1790 if (line > 0xEA) {
1791 line = (line + 0xFA) & 0xFF;
1792 }
1793 }
1794 uint32_t linecyc = context->cycles % MCLKS_LINE;
1795 if (context->latched_mode & BIT_H40) {
1796 uint32_t slot;
1797 if (linecyc < MCLKS_SLOT_H40*HSYNC_SLOT_H40) {
1798 slot = linecyc/MCLKS_SLOT_H40;
1799 } else if(linecyc < MCLK_WEIRD_END) {
1800 switch(linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40))
1801 {
1802 case 0:
1803 slot = 0;
1804 break;
1805 case 19:
1806 slot = 1;
1807 break;
1808 case 39:
1809 slot = 2;
1810 break;
1811 case 59:
1812 slot = 2;
1813 break;
1814 case 79:
1815 slot = 3;
1816 break;
1817 case 97:
1818 slot = 4;
1819 break;
1820 case 117:
1821 slot = 5;
1822 break;
1823 case 137:
1824 slot = 6;
1825 break;
1826 case 157:
1827 slot = 7;
1828 break;
1829 case 175:
1830 slot = 8;
1831 break;
1832 case 195:
1833 slot = 9;
1834 break;
1835 case 215:
1836 slot = 11;
1837 break;
1838 case 235:
1839 slot = 12;
1840 break;
1841 case 253:
1842 slot = 13;
1843 break;
1844 case 273:
1845 slot = 14;
1846 break;
1847 case 293:
1848 slot = 15;
1849 break;
1850 case 313:
1851 slot = 16;
1852 break;
1853 default:
1854 fprintf(stderr, "cycles after weirdness %d\n", linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40));
1855 exit(1);
1856 }
1857 slot += HSYNC_SLOT_H40;
1858 } else {
1859 slot = (linecyc-MCLK_WEIRD_END)/MCLKS_SLOT_H40 + SLOT_WEIRD_END;
1860 }
1861 linecyc = slot * 2;
1862 if (linecyc >= 86) {
1863 linecyc -= 86;
1864 } else {
1865 linecyc += 334;
1866 }
1867 if (linecyc > 0x16C) {
1868 linecyc += 92;
1869 }
1870 } else {
1871 linecyc /= 10;
1872 if (linecyc >= 74) {
1873 linecyc -= 74;
1874 } else {
1875 linecyc += 268;
1876 }
1877 if (linecyc > 0x127) {
1878 linecyc += 170;
1879 }
1880 }
1881 linecyc &= 0xFF; 1882 linecyc &= 0xFF;
1882 if (context->double_res) { 1883 if (context->double_res) {
1883 line <<= 1; 1884 line <<= 1;
1884 if (line & 0x100) { 1885 if (line & 0x100) {
1885 line |= 1; 1886 line |= 1;
1895 } 1896 }
1896 1897
1897 void vdp_adjust_cycles(vdp_context * context, uint32_t deduction) 1898 void vdp_adjust_cycles(vdp_context * context, uint32_t deduction)
1898 { 1899 {
1899 context->cycles -= deduction; 1900 context->cycles -= deduction;
1901 if (context->pending_vint_start >= deduction) {
1902 context->pending_vint_start -= deduction;
1903 } else {
1904 context->pending_vint_start = 0;
1905 }
1906 if (context->pending_hint_start >= deduction) {
1907 context->pending_hint_start -= deduction;
1908 } else {
1909 context->pending_hint_start = 0;
1910 }
1900 if (context->fifo_read >= 0) { 1911 if (context->fifo_read >= 0) {
1901 int32_t idx = context->fifo_read; 1912 int32_t idx = context->fifo_read;
1902 do { 1913 do {
1903 if (context->fifo[idx].cycle >= deduction) { 1914 if (context->fifo[idx].cycle >= deduction) {
1904 context->fifo[idx].cycle -= deduction; 1915 context->fifo[idx].cycle -= deduction;
1908 idx = (idx+1) & (FIFO_SIZE-1); 1919 idx = (idx+1) & (FIFO_SIZE-1);
1909 } while(idx != context->fifo_write); 1920 } while(idx != context->fifo_write);
1910 } 1921 }
1911 } 1922 }
1912 1923
1924 uint32_t vdp_cycles_hslot_wrap_h40(vdp_context * context)
1925 {
1926 if (context->hslot < 183) {
1927 return MCLKS_LINE - context->hslot * MCLKS_SLOT_H40;
1928 } else if (context->hslot < HSYNC_END_H40) {
1929 uint32_t before_hsync = context->hslot < HSYNC_SLOT_H40 ? (HSYNC_SLOT_H40 - context->hslot) * MCLKS_SLOT_H40 : 0;
1930 uint32_t hsync = 0;
1931 for (int i = context->hslot <= HSYNC_SLOT_H40 ? 0 : context->hslot - HSYNC_SLOT_H40; i < sizeof(h40_hsync_cycles)/sizeof(uint32_t); i++)
1932 {
1933 hsync += h40_hsync_cycles[i];
1934 }
1935 uint32_t after_hsync = (256- HSYNC_END_H40) * MCLKS_SLOT_H40;
1936 return before_hsync + hsync + after_hsync;
1937 } else {
1938 return (256-context->hslot) * MCLKS_SLOT_H40;
1939 }
1940 }
1941
1942 uint32_t vdp_cycles_next_line(vdp_context * context)
1943 {
1944 if (context->regs[REG_MODE_4] & BIT_H40) {
1945 if (context->hslot < LINE_CHANGE_H40) {
1946 return (LINE_CHANGE_H40 - context->hslot) * MCLKS_SLOT_H40;
1947 } else {
1948 return vdp_cycles_hslot_wrap_h40(context) + LINE_CHANGE_H40 * MCLKS_SLOT_H40;
1949 }
1950 } else {
1951 if (context->hslot < LINE_CHANGE_H32) {
1952 return (LINE_CHANGE_H32 - context->hslot) * MCLKS_SLOT_H32;
1953 } else if (context->hslot < 148) {
1954 return MCLKS_LINE - (context->hslot - LINE_CHANGE_H32) * MCLKS_SLOT_H32;
1955 } else {
1956 return (256-context->hslot + LINE_CHANGE_H32) * MCLKS_SLOT_H32;
1957 }
1958 }
1959 }
1960
1961 uint32_t vdp_cycles_to_line(vdp_context * context, uint32_t target)
1962 {
1963 uint32_t jump_start, jump_dst;
1964 if (context->flags2 & FLAG2_REGION_PAL) {
1965 if (context->latched_mode & BIT_PAL) {
1966 jump_start = 0x10B;
1967 jump_dst = 0x1D2;
1968 } else {
1969 jump_start = 0x103;
1970 jump_dst = 0x1CA;
1971 }
1972 } else {
1973 if (context->latched_mode & BIT_PAL) {
1974 jump_start = 0;
1975 jump_dst = 0;
1976 } else {
1977 jump_start = 0xEB;
1978 jump_dst = 0x1E5;
1979 }
1980 }
1981 uint32_t lines;
1982 if (context->vcounter < target) {
1983 if (target < jump_start) {
1984 lines = target - context->vcounter;
1985 } else {
1986 lines = jump_start - context->vcounter + target - jump_dst;
1987 }
1988 } else {
1989 if (context->vcounter < jump_start) {
1990 lines = jump_start - context->vcounter + 512 - jump_dst;
1991 } else {
1992 lines = 512 - context->vcounter;
1993 }
1994 if (target < jump_start) {
1995 lines += target;
1996 } else {
1997 lines += jump_start + target - jump_dst;
1998 }
1999 }
2000 return MCLKS_LINE * (lines - 1) + vdp_cycles_next_line(context);
2001 }
2002
2003 uint32_t vdp_frame_end_line(vdp_context * context)
2004 {
2005 uint32_t frame_end;
2006 if (context->flags2 & FLAG2_REGION_PAL) {
2007 if (context->latched_mode & BIT_PAL) {
2008 frame_end = PAL_INACTIVE_START + 8;
2009 } else {
2010 frame_end = NTSC_INACTIVE_START + 8;
2011 }
2012 } else {
2013 if (context->latched_mode & BIT_PAL) {
2014 frame_end = 512;
2015 } else {
2016 frame_end = NTSC_INACTIVE_START + 8;
2017 }
2018 }
2019 return frame_end;
2020 }
2021
2022 uint32_t vdp_cycles_to_frame_end(vdp_context * context)
2023 {
2024 return context->cycles + vdp_cycles_to_line(context, vdp_frame_end_line(context));
2025 }
2026
1913 uint32_t vdp_next_hint(vdp_context * context) 2027 uint32_t vdp_next_hint(vdp_context * context)
1914 { 2028 {
1915 if (!(context->regs[REG_MODE_1] & BIT_HINT_EN)) { 2029 if (!(context->regs[REG_MODE_1] & BIT_HINT_EN)) {
1916 return 0xFFFFFFFF; 2030 return 0xFFFFFFFF;
1917 } 2031 }
1918 if (context->flags2 & FLAG2_HINT_PENDING) { 2032 if (context->flags2 & FLAG2_HINT_PENDING) {
1919 return context->cycles; 2033 return context->pending_hint_start;
1920 } 2034 }
1921 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 2035 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
1922 uint32_t line = context->cycles / MCLKS_LINE; 2036 uint32_t hint_line;
1923 if (line >= active_lines) { 2037 if (context->vcounter + context->hint_counter >= inactive_start) {
1924 return 0xFFFFFFFF; 2038 if (context->regs[REG_HINT] > inactive_start) {
1925 } 2039 return 0xFFFFFFFF;
1926 uint32_t linecyc = context->cycles % MCLKS_LINE; 2040 }
1927 uint32_t hcycle = context->cycles + context->hint_counter * MCLKS_LINE + MCLKS_LINE - linecyc; 2041 hint_line = context->regs[REG_HINT];
1928 if (!line) { 2042 } else {
1929 hcycle += MCLKS_LINE; 2043 hint_line = context->vcounter + context->hint_counter + 1;
1930 } 2044 }
1931 return hcycle; 2045
2046 return context->cycles + vdp_cycles_to_line(context, hint_line);
1932 } 2047 }
1933 2048
1934 uint32_t vdp_next_vint(vdp_context * context) 2049 uint32_t vdp_next_vint(vdp_context * context)
1935 { 2050 {
1936 if (!(context->regs[REG_MODE_2] & BIT_VINT_EN)) { 2051 if (!(context->regs[REG_MODE_2] & BIT_VINT_EN)) {
1937 return 0xFFFFFFFF; 2052 return 0xFFFFFFFF;
1938 } 2053 }
1939 if (context->flags2 & FLAG2_VINT_PENDING) { 2054 if (context->flags2 & FLAG2_VINT_PENDING) {
1940 return context->cycles; 2055 return context->pending_vint_start;
1941 } 2056 }
1942 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; 2057
1943 uint32_t vcycle = MCLKS_LINE * active_lines; 2058
1944 if (context->latched_mode & BIT_H40) { 2059 return vdp_next_vint_z80(context);
1945 vcycle += VINT_CYCLE_H40; 2060 }
2061
2062 uint32_t vdp_next_vint_z80(vdp_context * context)
2063 {
2064 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
2065 if (context->vcounter == inactive_start) {
2066 if (context->regs[REG_MODE_4] & BIT_H40) {
2067 if (context->hslot >= LINE_CHANGE_H40) {
2068 return context->cycles + vdp_cycles_hslot_wrap_h40(context) + VINT_SLOT_H40 * MCLKS_SLOT_H40;
2069 } else if (context->hslot <= VINT_SLOT_H40) {
2070 return context->cycles + (VINT_SLOT_H40 - context->hslot) * MCLKS_SLOT_H40;
2071 }
2072 } else {
2073 if (context->hslot >= LINE_CHANGE_H32) {
2074 if (context->hslot < 148) {
2075 return context->cycles + (VINT_SLOT_H32 + 148 - context->hslot + 256 - 233) * MCLKS_SLOT_H32;
2076 } else {
2077 return context->cycles + (VINT_SLOT_H32 + 256 - context->hslot) * MCLKS_SLOT_H32;
2078 }
2079 } else if (context->hslot <= VINT_SLOT_H32) {
2080 return context->cycles + (VINT_SLOT_H32 - context->hslot) * MCLKS_SLOT_H32;
2081 }
2082 }
2083 }
2084 int32_t cycles_to_vint = vdp_cycles_to_line(context, inactive_start);
2085 if (context->regs[REG_MODE_4] & BIT_H40) {
2086 cycles_to_vint += MCLKS_LINE - (LINE_CHANGE_H40 - VINT_SLOT_H40) * MCLKS_SLOT_H40;
1946 } else { 2087 } else {
1947 vcycle += VINT_CYCLE_H32; 2088 cycles_to_vint += (VINT_SLOT_H32 + 148 - LINE_CHANGE_H32 + 256 - 233) * MCLKS_SLOT_H32;
1948 } 2089 }
1949 if (vcycle < context->cycles) { 2090 return context->cycles + cycles_to_vint;
1950 return 0xFFFFFFFF;
1951 }
1952 return vcycle;
1953 }
1954
1955 uint32_t vdp_next_vint_z80(vdp_context * context)
1956 {
1957 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE;
1958 uint32_t vcycle = MCLKS_LINE * active_lines;
1959 if (context->latched_mode & BIT_H40) {
1960 vcycle += VINT_CYCLE_H40;
1961 } else {
1962 vcycle += VINT_CYCLE_H32;
1963 }
1964 return vcycle;
1965 } 2091 }
1966 2092
1967 void vdp_int_ack(vdp_context * context, uint16_t int_num) 2093 void vdp_int_ack(vdp_context * context, uint16_t int_num)
1968 { 2094 {
1969 if (int_num == 6) { 2095 if (int_num == 6) {