Mercurial > repos > blastem
comparison vdp.c @ 20:f664eeb55cb4
Mostly broken VDP core and savestate viewer
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 08 Dec 2012 02:00:54 -0800 |
parents | |
children | 72ce60cb1711 |
comparison
equal
deleted
inserted
replaced
19:4717146a7606 | 20:f664eeb55cb4 |
---|---|
1 #include "vdp.h" | |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 | |
5 #define MCLKS_LINE 3420 | |
6 #define NTSC_ACTIVE 225 | |
7 #define PAL_ACTIVE 241 | |
8 #define BUF_BIT_PRIORITY 0x40 | |
9 #define MAP_BIT_PRIORITY 0x8000 | |
10 #define MAP_BIT_H_FLIP 0x800 | |
11 #define MAP_BIT_V_FLIP 0x1000 | |
12 | |
13 #define BIT_PAL 0x8 | |
14 #define BIT_H40 0x1 | |
15 | |
16 void init_vdp_context(vdp_context * context) | |
17 { | |
18 memset(context, 0, sizeof(context)); | |
19 context->vdpmem = malloc(VRAM_SIZE); | |
20 context->framebuf = malloc(FRAMEBUF_SIZE); | |
21 context->linebuf = malloc(LINEBUF_SIZE + 48); | |
22 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; | |
23 context->tmp_buf_b = context->tmp_buf_a + 24; | |
24 } | |
25 | |
26 void render_sprite_cells(uint32_t linecyc, vdp_context * context) | |
27 { | |
28 if (linecyc < context->sprite_draws) { | |
29 sprite_draw * d = context->sprite_draw_list + linecyc; | |
30 uint16_t dir; | |
31 int16_t x; | |
32 if (d->h_flip) { | |
33 x = d->x_pos + 7; | |
34 dir = -1; | |
35 } else { | |
36 x = d->x_pos; | |
37 dir = 1; | |
38 } | |
39 for (uint16_t address = d->address; address < d->address+4; address++) { | |
40 if (x >= 0 && x < 320) { | |
41 context->linebuf[x] = (context->vdpmem[address] >> 4) | d->pal_priority; | |
42 } | |
43 x += dir; | |
44 if (x >= 0 && x < 320) { | |
45 context->linebuf[x] = (context->vdpmem[address] & 0xF) | d->pal_priority; | |
46 } | |
47 x += dir; | |
48 } | |
49 } | |
50 } | |
51 | |
52 void scan_sprite_table(uint32_t line, vdp_context * context) | |
53 { | |
54 if (context->sprite_index && context->slot_counter) { | |
55 line += 1; | |
56 line &= 0xFF; | |
57 line += 128; | |
58 context->sprite_index &= 0x7F; | |
59 //TODO: Read from SAT cache rather than from VRAM | |
60 uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; | |
61 uint16_t address = context->sprite_index * 8 + sat_address; | |
62 uint16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) - 128; | |
63 uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; | |
64 if (y >= line && (y + height) < line) { | |
65 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; | |
66 context->sprite_info_list[context->slot_counter].index = context->sprite_index; | |
67 context->sprite_info_list[context->slot_counter].y = y; | |
68 } | |
69 context->sprite_index = context->vdpmem[address+3] & 0x7F; | |
70 if (context->sprite_index && context->slot_counter) | |
71 { | |
72 address = context->sprite_index * 8 + sat_address; | |
73 y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) - 128; | |
74 height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; | |
75 if (y >= line && y < (line + height)) { | |
76 context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; | |
77 context->sprite_info_list[context->slot_counter].index = context->sprite_index; | |
78 context->sprite_info_list[context->slot_counter].y = y; | |
79 } | |
80 } | |
81 } | |
82 } | |
83 | |
84 void read_sprite_x(uint32_t line, vdp_context * context) | |
85 { | |
86 if (context->slot_counter && context->sprite_draws) { | |
87 context->slot_counter--; | |
88 uint8_t width = (context->sprite_info_list[context->slot_counter].size & 0x3) + 1; | |
89 uint8_t height = (((context->sprite_info_list[context->slot_counter].size >> 2) & 0x3) + 1) * 8; | |
90 uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->slot_counter].index * 8 + 4; | |
91 uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1]; | |
92 uint8_t pal_priority = (tileinfo >> 9) & 0x70; | |
93 uint8_t row; | |
94 if (tileinfo & MAP_BIT_V_FLIP) { | |
95 row = (context->sprite_info_list[context->slot_counter].y + height - 1) - line; | |
96 } else { | |
97 row = line-context->sprite_info_list[context->slot_counter].y; | |
98 } | |
99 uint16_t address = ((tileinfo & 0x7FF) << 5) + row * width * 4; | |
100 int16_t x = ((context->vdpmem[att_addr+ 6] & 0x3) << 8) | context->vdpmem[att_addr + 7]; | |
101 if (x) { | |
102 x -= 128; | |
103 for (;width && context->sprite_draws; --width, --context->sprite_draws, address += 4, x += 8) { | |
104 context->sprite_draw_list[context->sprite_draws].address = address; | |
105 context->sprite_draw_list[context->sprite_draws].x_pos = x; | |
106 context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority; | |
107 context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0; | |
108 } | |
109 } else { | |
110 //sprite masking enabled, no more sprites on this line | |
111 context->slot_counter = 0; | |
112 } | |
113 } | |
114 } | |
115 | |
116 void external_slot(vdp_context * context) | |
117 { | |
118 //TODO: Implement me | |
119 } | |
120 | |
121 void read_map_scroll(uint16_t column, uint32_t line, uint32_t scroll_reg, uint16_t hscroll_val, vdp_context * context) | |
122 { | |
123 uint16_t address = (context->regs[scroll_reg] & 0x38) << 10; | |
124 uint16_t vscroll; | |
125 switch(context->regs[REG_SCROLL] & 0x30) | |
126 { | |
127 case 0: | |
128 vscroll = 0xFF; | |
129 break; | |
130 case 0x10: | |
131 vscroll = 0x1FF; | |
132 break; | |
133 case 0x20: | |
134 //TODO: Verify this behavior | |
135 vscroll = 0; | |
136 break; | |
137 case 0x30: | |
138 vscroll = 0x3FF; | |
139 break; | |
140 } | |
141 vscroll &= (context->vsram[context->regs[REG_MODE_3] & 0x4 ? column : 0] + line); | |
142 context->v_offset = vscroll & 0x7; | |
143 vscroll /= 8; | |
144 uint16_t hscroll_mask; | |
145 uint16_t v_mul; | |
146 switch(context->regs[REG_SCROLL] & 0x3) | |
147 { | |
148 case 0: | |
149 hscroll_mask = 0xF8; | |
150 v_mul = 64; | |
151 break; | |
152 case 0x1: | |
153 hscroll_mask = 0x1F8; | |
154 v_mul = 128; | |
155 break; | |
156 case 0x2: | |
157 //TODO: Verify this behavior | |
158 hscroll_mask = 0; | |
159 v_mul = 0; | |
160 break; | |
161 case 0x3: | |
162 hscroll_mask = 0x3F8; | |
163 v_mul = 256; | |
164 break; | |
165 } | |
166 uint16_t hscroll = (hscroll_val + (column-1) * 8) & hscroll_mask; | |
167 uint16_t offset = address + ((vscroll * v_mul + hscroll/4) & 0x1FFF); | |
168 //printf("A | line: %d, col: %d, x: %d, hs_mask %X, v_mul: %d, scr reg: %X, tbl addr: %X\n", line, column, hscroll, hscroll_mask, v_mul, context->regs[REG_SCROLL], offset); | |
169 context->col_1 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1]; | |
170 hscroll = (hscroll_val + column * 8) & hscroll_mask; | |
171 offset = address + ((vscroll * v_mul + hscroll/4) & 0x1FFF); | |
172 context->col_2 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1]; | |
173 } | |
174 | |
175 void read_map_scroll_a(uint16_t column, uint32_t line, vdp_context * context) | |
176 { | |
177 read_map_scroll(column, line, REG_SCROLL_A, context->hscroll_a, context); | |
178 } | |
179 | |
180 void read_map_scroll_b(uint16_t column, uint32_t line, vdp_context * context) | |
181 { | |
182 read_map_scroll(column, line, REG_SCROLL_B, context->hscroll_b, context); | |
183 } | |
184 | |
185 void render_map(uint16_t col, uint8_t * tmp_buf, vdp_context * context) | |
186 { | |
187 uint16_t address = ((col & 0x3FF) << 5); | |
188 if (col & MAP_BIT_V_FLIP) { | |
189 address += 24 - 4 * context->v_offset; | |
190 } else { | |
191 address += 4 * context->v_offset; | |
192 } | |
193 uint16_t pal_priority = (col >> 9) & 0x70; | |
194 int32_t dir; | |
195 if (col & MAP_BIT_H_FLIP) { | |
196 tmp_buf += 7; | |
197 dir = -1; | |
198 } else { | |
199 dir = 1; | |
200 } | |
201 for (uint32_t i=0; i < 4; i++, address++) | |
202 { | |
203 *tmp_buf = pal_priority | (context->vdpmem[address] >> 4); | |
204 tmp_buf += dir; | |
205 *tmp_buf = pal_priority | (context->vdpmem[address] & 0xF); | |
206 tmp_buf += dir; | |
207 } | |
208 } | |
209 | |
210 void render_map_1(vdp_context * context) | |
211 { | |
212 render_map(context->col_1, context->tmp_buf_a+8, context); | |
213 } | |
214 | |
215 void render_map_2(vdp_context * context) | |
216 { | |
217 render_map(context->col_2, context->tmp_buf_a+16, context); | |
218 } | |
219 | |
220 void render_map_3(vdp_context * context) | |
221 { | |
222 render_map(context->col_1, context->tmp_buf_b+8, context); | |
223 } | |
224 | |
225 void render_map_output(uint32_t line, int32_t col, vdp_context * context) | |
226 { | |
227 if (line >= 240) { | |
228 return; | |
229 } | |
230 render_map(context->col_2, context->tmp_buf_b+16, context); | |
231 uint16_t *dst, *end; | |
232 uint8_t *sprite_buf, *plane_a, *plane_b; | |
233 if (col) | |
234 { | |
235 col-=2; | |
236 dst = context->framebuf + line * 320 + col * 8; | |
237 sprite_buf = context->linebuf + col * 8; | |
238 plane_a = context->tmp_buf_a + 8 - (context->hscroll_a & 0x7); | |
239 plane_b = context->tmp_buf_b + 8 - (context->hscroll_b & 0x7); | |
240 /*if (col == 40) | |
241 { | |
242 end = dst + 8; | |
243 } else {*/ | |
244 end = dst + 16; | |
245 //} | |
246 for (; dst < end; ++plane_a, ++plane_b, ++sprite_buf, ++dst) { | |
247 uint8_t pixel; | |
248 if (*sprite_buf & BUF_BIT_PRIORITY) { | |
249 pixel = *sprite_buf; | |
250 } else if (*plane_a & BUF_BIT_PRIORITY) { | |
251 pixel = *plane_a; | |
252 } else if (*plane_b & BUF_BIT_PRIORITY) { | |
253 pixel = *plane_b; | |
254 } else if (*sprite_buf & 0xF) { | |
255 pixel = *sprite_buf; | |
256 } else if (*plane_a & 0xF) { | |
257 pixel = *plane_a; | |
258 } else if (*plane_b & 0xF){ | |
259 pixel = *plane_b; | |
260 } else { | |
261 pixel = context->regs[REG_BG_COLOR] & 0x3F; | |
262 } | |
263 *dst = context->cram[pixel & 0x3F] | ((pixel & BUF_BIT_PRIORITY) ? 0x1000 : 0); | |
264 } | |
265 } else { | |
266 //dst = context->framebuf + line * 320; | |
267 //sprite_buf = context->linebuf + col * 8; | |
268 //plane_a = context->tmp_buf_a + 16 - (context->hscroll_a & 0x7); | |
269 //plane_b = context->tmp_buf_b + 16 - (context->hscroll_b & 0x7); | |
270 //end = dst + 8; | |
271 } | |
272 | |
273 uint16_t remaining = context->hscroll_a & 0x7; | |
274 memcpy(context->tmp_buf_a + 8 - remaining, context->tmp_buf_a + 24 - remaining, remaining); | |
275 remaining = context->hscroll_b & 0x7; | |
276 memcpy(context->tmp_buf_b + 8 - remaining, context->tmp_buf_a + 24 - remaining, remaining); | |
277 } | |
278 | |
279 #define COLUMN_RENDER_BLOCK(column, startcyc) \ | |
280 case startcyc:\ | |
281 read_map_scroll_a(column, line, context);\ | |
282 break;\ | |
283 case (startcyc+1):\ | |
284 external_slot(context);\ | |
285 break;\ | |
286 case (startcyc+2):\ | |
287 render_map_1(context);\ | |
288 break;\ | |
289 case (startcyc+3):\ | |
290 render_map_2(context);\ | |
291 break;\ | |
292 case (startcyc+4):\ | |
293 read_map_scroll_b(column, line, context);\ | |
294 break;\ | |
295 case (startcyc+5):\ | |
296 read_sprite_x(line, context);\ | |
297 break;\ | |
298 case (startcyc+6):\ | |
299 render_map_3(context);\ | |
300 break;\ | |
301 case (startcyc+7):\ | |
302 render_map_output(line, column, context);\ | |
303 break; | |
304 | |
305 #define COLUMN_RENDER_BLOCK_REFRESH(column, startcyc) \ | |
306 case startcyc:\ | |
307 read_map_scroll_a(column, line, context);\ | |
308 break;\ | |
309 case (startcyc+1):\ | |
310 break;\ | |
311 case (startcyc+2):\ | |
312 render_map_1(context);\ | |
313 break;\ | |
314 case (startcyc+3):\ | |
315 render_map_2(context);\ | |
316 break;\ | |
317 case (startcyc+4):\ | |
318 read_map_scroll_b(column, line, context);\ | |
319 break;\ | |
320 case (startcyc+5):\ | |
321 read_sprite_x(line, context);\ | |
322 break;\ | |
323 case (startcyc+6):\ | |
324 render_map_3(context);\ | |
325 break;\ | |
326 case (startcyc+7):\ | |
327 render_map_output(line, column, context);\ | |
328 break; | |
329 | |
330 void vdp_h40(uint32_t line, uint32_t linecyc, vdp_context * context) | |
331 { | |
332 uint16_t address; | |
333 uint32_t mask; | |
334 switch(linecyc) | |
335 { | |
336 //sprite render to line buffer starts | |
337 case 0: | |
338 memset(context->linebuf, 0, LINEBUF_SIZE); | |
339 render_sprite_cells(linecyc, context); | |
340 break; | |
341 case 1: | |
342 case 2: | |
343 case 3: | |
344 render_sprite_cells(linecyc, context); | |
345 break; | |
346 //sprite attribute table scan starts | |
347 case 4: | |
348 render_sprite_cells(linecyc, context); | |
349 context->sprite_index = 0x80; | |
350 context->slot_counter = MAX_SPRITES_LINE; | |
351 scan_sprite_table(line, context); | |
352 break; | |
353 case 5: | |
354 case 6: | |
355 case 7: | |
356 case 8: | |
357 case 9: | |
358 case 10: | |
359 case 11: | |
360 case 12: | |
361 case 13: | |
362 case 14: | |
363 case 15: | |
364 case 16: | |
365 case 17: | |
366 case 18: | |
367 case 19: | |
368 case 20: | |
369 //!HSYNC asserted | |
370 case 21: | |
371 case 22: | |
372 render_sprite_cells(linecyc, context); | |
373 scan_sprite_table(line, context); | |
374 break; | |
375 case 23: | |
376 external_slot(context); | |
377 break; | |
378 case 24: | |
379 case 25: | |
380 case 26: | |
381 case 27: | |
382 case 28: | |
383 case 29: | |
384 case 30: | |
385 case 31: | |
386 case 32: | |
387 case 33: | |
388 case 34: | |
389 render_sprite_cells(linecyc, context); | |
390 scan_sprite_table(line, context); | |
391 break; | |
392 case 35: | |
393 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; | |
394 mask = 0; | |
395 if (context->regs[REG_MODE_3] & 0x2) { | |
396 mask |= 0xF8; | |
397 } | |
398 if (context->regs[REG_MODE_3] & 0x1) { | |
399 mask |= 0x7; | |
400 } | |
401 line &= mask; | |
402 address += line * 4; | |
403 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; | |
404 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; | |
405 printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); | |
406 break; | |
407 case 36: | |
408 //!HSYNC high | |
409 case 37: | |
410 case 38: | |
411 case 39: | |
412 render_sprite_cells(linecyc, context); | |
413 scan_sprite_table(line, context); | |
414 break; | |
415 case 40: | |
416 read_map_scroll_a(0, line, context); | |
417 break; | |
418 case 41: | |
419 render_sprite_cells(linecyc, context); | |
420 scan_sprite_table(line, context); | |
421 break; | |
422 case 42: | |
423 render_map_1(context); | |
424 scan_sprite_table(line, context);//Just a guess | |
425 break; | |
426 case 43: | |
427 render_map_2(context); | |
428 scan_sprite_table(line, context);//Just a guess | |
429 break; | |
430 case 44: | |
431 read_map_scroll_b(0, line, context); | |
432 break; | |
433 case 45: | |
434 render_sprite_cells(linecyc, context); | |
435 scan_sprite_table(line, context); | |
436 break; | |
437 case 46: | |
438 render_map_3(context); | |
439 scan_sprite_table(line, context);//Just a guess | |
440 break; | |
441 case 47: | |
442 render_map_output(line, 0, context); | |
443 scan_sprite_table(line, context);//Just a guess | |
444 //reverse context slot counter so it counts the number of sprite slots | |
445 //filled rather than the number of available slots | |
446 context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; | |
447 context->sprite_draws = MAX_DRAWS; | |
448 break; | |
449 COLUMN_RENDER_BLOCK(2, 48) | |
450 COLUMN_RENDER_BLOCK(4, 56) | |
451 COLUMN_RENDER_BLOCK(6, 64) | |
452 COLUMN_RENDER_BLOCK_REFRESH(8, 72) | |
453 COLUMN_RENDER_BLOCK(10, 80) | |
454 COLUMN_RENDER_BLOCK(12, 88) | |
455 COLUMN_RENDER_BLOCK(14, 96) | |
456 COLUMN_RENDER_BLOCK_REFRESH(16, 104) | |
457 COLUMN_RENDER_BLOCK(18, 112) | |
458 COLUMN_RENDER_BLOCK(20, 120) | |
459 COLUMN_RENDER_BLOCK(22, 128) | |
460 COLUMN_RENDER_BLOCK_REFRESH(24, 136) | |
461 COLUMN_RENDER_BLOCK(26, 144) | |
462 COLUMN_RENDER_BLOCK(28, 152) | |
463 COLUMN_RENDER_BLOCK(30, 160) | |
464 COLUMN_RENDER_BLOCK_REFRESH(32, 168) | |
465 COLUMN_RENDER_BLOCK(34, 176) | |
466 COLUMN_RENDER_BLOCK(36, 184) | |
467 COLUMN_RENDER_BLOCK(38, 192) | |
468 COLUMN_RENDER_BLOCK_REFRESH(40, 200) | |
469 case 208: | |
470 context->sprite_draws = MAX_DRAWS - context->sprite_draws; | |
471 case 209: | |
472 external_slot(context); | |
473 break; | |
474 default: | |
475 //leftovers from HSYNC clock change nonsense | |
476 break; | |
477 } | |
478 } | |
479 | |
480 void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context) | |
481 { | |
482 switch(linecyc) | |
483 { | |
484 //sprite render to line buffer starts | |
485 case 0: | |
486 break; | |
487 case 1: | |
488 break; | |
489 case 2: | |
490 break; | |
491 case 3: | |
492 break; | |
493 case 4: | |
494 break; | |
495 case 5: | |
496 break; | |
497 case 6: | |
498 break; | |
499 case 7: | |
500 break; | |
501 case 8: | |
502 break; | |
503 case 9: | |
504 break; | |
505 case 10: | |
506 break; | |
507 case 11: | |
508 break; | |
509 case 12: | |
510 break; | |
511 case 13: | |
512 break; | |
513 case 14: | |
514 break; | |
515 case 15: | |
516 break; | |
517 case 16: | |
518 break; | |
519 case 17: | |
520 break; | |
521 case 18: | |
522 break; | |
523 case 19: | |
524 break; | |
525 case 20: | |
526 break; | |
527 case 21: | |
528 break; | |
529 case 22: | |
530 break; | |
531 case 23: | |
532 break; | |
533 case 24: | |
534 break; | |
535 case 25: | |
536 break; | |
537 case 26: | |
538 break; | |
539 case 27: | |
540 break; | |
541 case 28: | |
542 break; | |
543 case 29: | |
544 break; | |
545 case 30: | |
546 break; | |
547 case 31: | |
548 break; | |
549 case 32: | |
550 break; | |
551 case 33: | |
552 break; | |
553 case 34: | |
554 break; | |
555 case 35: | |
556 break; | |
557 case 36: | |
558 break; | |
559 case 37: | |
560 break; | |
561 case 38: | |
562 break; | |
563 case 39: | |
564 break; | |
565 case 40: | |
566 break; | |
567 case 41: | |
568 break; | |
569 case 42: | |
570 break; | |
571 case 43: | |
572 break; | |
573 case 44: | |
574 break; | |
575 case 45: | |
576 break; | |
577 case 46: | |
578 break; | |
579 case 47: | |
580 break; | |
581 case 48: | |
582 break; | |
583 case 49: | |
584 break; | |
585 case 50: | |
586 break; | |
587 case 51: | |
588 break; | |
589 case 52: | |
590 break; | |
591 case 53: | |
592 break; | |
593 case 54: | |
594 break; | |
595 case 55: | |
596 break; | |
597 case 56: | |
598 break; | |
599 case 57: | |
600 break; | |
601 case 58: | |
602 break; | |
603 case 59: | |
604 break; | |
605 case 60: | |
606 break; | |
607 case 61: | |
608 break; | |
609 case 62: | |
610 break; | |
611 case 63: | |
612 break; | |
613 case 64: | |
614 break; | |
615 case 65: | |
616 break; | |
617 case 66: | |
618 break; | |
619 case 67: | |
620 break; | |
621 case 68: | |
622 break; | |
623 case 69: | |
624 break; | |
625 case 70: | |
626 break; | |
627 case 71: | |
628 break; | |
629 case 72: | |
630 break; | |
631 case 73: | |
632 break; | |
633 case 74: | |
634 break; | |
635 case 75: | |
636 break; | |
637 case 76: | |
638 break; | |
639 case 77: | |
640 break; | |
641 case 78: | |
642 break; | |
643 case 79: | |
644 break; | |
645 case 80: | |
646 break; | |
647 case 81: | |
648 break; | |
649 case 82: | |
650 break; | |
651 case 83: | |
652 break; | |
653 case 84: | |
654 break; | |
655 case 85: | |
656 break; | |
657 case 86: | |
658 break; | |
659 case 87: | |
660 break; | |
661 case 88: | |
662 break; | |
663 case 89: | |
664 break; | |
665 case 90: | |
666 break; | |
667 case 91: | |
668 break; | |
669 case 92: | |
670 break; | |
671 case 93: | |
672 break; | |
673 case 94: | |
674 break; | |
675 case 95: | |
676 break; | |
677 case 96: | |
678 break; | |
679 case 97: | |
680 break; | |
681 case 98: | |
682 break; | |
683 case 99: | |
684 break; | |
685 case 100: | |
686 break; | |
687 case 101: | |
688 break; | |
689 case 102: | |
690 break; | |
691 case 103: | |
692 break; | |
693 case 104: | |
694 break; | |
695 case 105: | |
696 break; | |
697 case 106: | |
698 break; | |
699 case 107: | |
700 break; | |
701 case 108: | |
702 break; | |
703 case 109: | |
704 break; | |
705 case 110: | |
706 break; | |
707 case 111: | |
708 break; | |
709 case 112: | |
710 break; | |
711 case 113: | |
712 break; | |
713 case 114: | |
714 break; | |
715 case 115: | |
716 break; | |
717 case 116: | |
718 break; | |
719 case 117: | |
720 break; | |
721 case 118: | |
722 break; | |
723 case 119: | |
724 break; | |
725 case 120: | |
726 break; | |
727 case 121: | |
728 break; | |
729 case 122: | |
730 break; | |
731 case 123: | |
732 break; | |
733 case 124: | |
734 break; | |
735 case 125: | |
736 break; | |
737 case 126: | |
738 break; | |
739 case 127: | |
740 break; | |
741 case 128: | |
742 break; | |
743 case 129: | |
744 break; | |
745 case 130: | |
746 break; | |
747 case 131: | |
748 break; | |
749 case 132: | |
750 break; | |
751 case 133: | |
752 break; | |
753 case 134: | |
754 break; | |
755 case 135: | |
756 break; | |
757 case 136: | |
758 break; | |
759 case 137: | |
760 break; | |
761 case 138: | |
762 break; | |
763 case 139: | |
764 break; | |
765 case 140: | |
766 break; | |
767 case 141: | |
768 break; | |
769 case 142: | |
770 break; | |
771 case 143: | |
772 break; | |
773 case 144: | |
774 break; | |
775 case 145: | |
776 break; | |
777 case 146: | |
778 break; | |
779 case 147: | |
780 break; | |
781 case 148: | |
782 break; | |
783 case 149: | |
784 break; | |
785 case 150: | |
786 break; | |
787 case 151: | |
788 break; | |
789 case 152: | |
790 break; | |
791 case 153: | |
792 break; | |
793 case 154: | |
794 break; | |
795 case 155: | |
796 break; | |
797 case 156: | |
798 break; | |
799 case 157: | |
800 break; | |
801 case 158: | |
802 break; | |
803 case 159: | |
804 break; | |
805 case 160: | |
806 break; | |
807 case 161: | |
808 break; | |
809 case 162: | |
810 break; | |
811 case 163: | |
812 break; | |
813 case 164: | |
814 break; | |
815 case 165: | |
816 break; | |
817 case 166: | |
818 break; | |
819 case 167: | |
820 break; | |
821 case 168: | |
822 break; | |
823 case 169: | |
824 break; | |
825 case 170: | |
826 break; | |
827 case 171: | |
828 break; | |
829 } | |
830 } | |
831 void latch_mode(vdp_context * context) | |
832 { | |
833 context->latched_mode = (context->regs[REG_MODE_4] & 0x81) | (context->regs[REG_MODE_2] & BIT_PAL); | |
834 } | |
835 | |
836 void vdp_run_context(vdp_context * context, uint32_t target_cycles) | |
837 { | |
838 while(context->cycles < target_cycles) | |
839 { | |
840 uint32_t line = context->cycles / MCLKS_LINE; | |
841 uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; | |
842 if (line < active_lines) { | |
843 if (!line) { | |
844 latch_mode(context); | |
845 } | |
846 //first sort-of active line is treated as 255 internally | |
847 //it's used for gathering sprite info for line | |
848 line = (line - 1) & 0xFF; | |
849 uint32_t linecyc = context->cycles % MCLKS_LINE; | |
850 | |
851 //Convert to slot number | |
852 if (context->latched_mode & BIT_H40){ | |
853 //TODO: Deal with nasty clock switching during HBLANK | |
854 linecyc = linecyc/16; | |
855 context->cycles += 16; | |
856 vdp_h40(line, linecyc, context); | |
857 } else { | |
858 linecyc = linecyc/20; | |
859 context->cycles += 20; | |
860 vdp_h32(line, linecyc, context); | |
861 } | |
862 } else { | |
863 //TODO: Empty FIFO | |
864 } | |
865 } | |
866 } | |
867 | |
868 uint32_t vdp_run_to_vblank(vdp_context * context) | |
869 { | |
870 uint32_t target_cycles = ((context->latched_mode & BIT_PAL) ? PAL_ACTIVE : NTSC_ACTIVE) * MCLKS_LINE; | |
871 vdp_run_context(context, target_cycles); | |
872 return context->cycles; | |
873 } | |
874 | |
875 #define GST_VDP_REGS 0xFA | |
876 #define GST_VDP_MEM 0x12478 | |
877 | |
878 void vdp_load_savestate(vdp_context * context, FILE * state_file) | |
879 { | |
880 uint8_t tmp_buf[CRAM_SIZE*2]; | |
881 fseek(state_file, GST_VDP_REGS, SEEK_SET); | |
882 fread(context->regs, 1, VDP_REGS, state_file); | |
883 latch_mode(context); | |
884 fread(tmp_buf, 1, sizeof(tmp_buf), state_file); | |
885 for (int i = 0; i < CRAM_SIZE; i++) { | |
886 context->cram[i] = (tmp_buf[i*2+1] << 8) | tmp_buf[i*2]; | |
887 } | |
888 fread(tmp_buf, 2, VSRAM_SIZE, state_file); | |
889 for (int i = 0; i < VSRAM_SIZE; i++) { | |
890 context->vsram[i] = (tmp_buf[i*2] << 8) | tmp_buf[i*2+1]; | |
891 } | |
892 fseek(state_file, GST_VDP_MEM, SEEK_SET); | |
893 fread(context->vdpmem, 1, VRAM_SIZE, state_file); | |
894 } |