# HG changeset patch # User Mike Pavone # Date 1354960854 28800 # Node ID f664eeb55cb495879c9109ac68ba9ce55377bb25 # Parent 4717146a7606329561d03a7dfad92e703f3007bb Mostly broken VDP core and savestate viewer diff -r 4717146a7606 -r f664eeb55cb4 Makefile --- a/Makefile Tue Dec 04 19:25:54 2012 -0800 +++ b/Makefile Sat Dec 08 02:00:54 2012 -0800 @@ -1,5 +1,6 @@ +LIBS=sdl -all : dis trans +all : dis trans stateview dis : dis.o 68kinst.o $(CC) -o dis dis.o 68kinst.o @@ -7,6 +8,9 @@ trans : trans.o 68kinst.o gen_x86.o m68k_to_x86.o runtime.o mem.o $(CC) -o trans trans.o 68kinst.o gen_x86.o m68k_to_x86.o runtime.o mem.o +stateview : stateview.o vdp.o render_sdl.o + $(CC) -o stateview stateview.o vdp.o render_sdl.o `pkg-config --libs $(LIBS)` + test_x86 : test_x86.o gen_x86.o $(CC) -o test_x86 test_x86.o gen_x86.o @@ -17,10 +21,10 @@ $(CC) -c -o $@ $< %.o : %.c - $(CC) -ggdb -std=gnu99 -c -o $@ $< + $(CC) -ggdb -std=gnu99 `pkg-config --cflags-only-I $(LIBS)` -c -o $@ $< %.bin : %.s68 vasmm68k_mot -Fbin -m68000 -spaces -o $@ $< clean : - rm -rf dis trans test_x86 gen_fib *.o + rm -rf dis trans stateview test_x86 gen_fib *.o diff -r 4717146a7606 -r f664eeb55cb4 dis.c --- a/dis.c Tue Dec 04 19:25:54 2012 -0800 +++ b/dis.c Sat Dec 08 02:00:54 2012 -0800 @@ -20,7 +20,7 @@ { *cur = (*cur >> 8) | (*cur << 8); } - for(cur = filebuf; (cur - filebuf) < (filesize/2); ) + for(cur = filebuf + 0x100; (cur - filebuf) < (filesize/2); ) { //printf("cur: %p: %x\n", cur, *cur); unsigned short * start = cur; diff -r 4717146a7606 -r f664eeb55cb4 fib.s68 --- a/fib.s68 Tue Dec 04 19:25:54 2012 -0800 +++ b/fib.s68 Sat Dec 08 02:00:54 2012 -0800 @@ -1,6 +1,6 @@ dc.l $0, start start: - moveq #10, d0 + moveq #36, d0 bsr fib illegal fib: diff -r 4717146a7606 -r f664eeb55cb4 render.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/render.h Sat Dec 08 02:00:54 2012 -0800 @@ -0,0 +1,10 @@ +#ifndef RENDER_SDL_H_ +#define RENDER_SDL_H_ + +#include "vdp.h" +void render_init(); +void render_context(vdp_context * context); +void render_wait_quit(); + +#endif //RENDER_SDL_H_ + diff -r 4717146a7606 -r f664eeb55cb4 render_sdl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/render_sdl.c Sat Dec 08 02:00:54 2012 -0800 @@ -0,0 +1,102 @@ +#include +#include +#include +#include "render.h" + +SDL_Surface *screen; + +void render_init() +{ + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + screen = SDL_SetVideoMode(320, 240, 32, SDL_SWSURFACE | SDL_ANYFORMAT); + if (!screen) { + fprintf(stderr, "Unable to get SDL surface: %s\n", SDL_GetError()); + exit(1); + } + if (screen->format->BytesPerPixel < 2) { + fprintf(stderr, "BlastEm requires at least a 16-bit surface, SDL returned a %d-bit surface\n", screen->format->BytesPerPixel * 8); + exit(1); + } +} + +void render_context(vdp_context * context) +{ + uint8_t *buf_8; + uint16_t *buf_16; + uint32_t *buf_32; + uint8_t b,g,r; + if (SDL_MUSTLOCK(screen)) { + if (SDL_LockSurface(screen) < 0) { + return; + } + } + switch (screen->format->BytesPerPixel) { + case 2: + buf_16 = (uint16_t *)screen->pixels; + for (int y = 0; y < 240; y++, buf_16 += (screen->pitch/2 - 320)) { + for (int x = 0; x < 320; x++, buf_16++) { + uint16_t gen_color = context->framebuf[y * 320 + x]; + b = ((gen_color >> 8) & 0xE) * 18; + g = ((gen_color >> 4) & 0xE) * 18; + r = (gen_color& 0xE) * 18; + *buf_16 = SDL_MapRGB(screen->format, r, g, b); + } + } + break; + case 3: + buf_8 = (uint8_t *)screen->pixels; + for (int y = 0; y < 240; y++, buf_8 += (screen->pitch - 320)) { + for (int x = 0; x < 320; x++, buf_8 += 3) { + uint16_t gen_color = context->framebuf[y * 320 + x]; + b = ((gen_color >> 8) & 0xE) * 18; + g = ((gen_color >> 4) & 0xE) * 18; + r = (gen_color& 0xE) * 18; + *(buf_8+screen->format->Rshift/8) = r; + *(buf_8+screen->format->Gshift/8) = g; + *(buf_8+screen->format->Bshift/8) = b; + } + } + break; + case 4: + buf_32 = (uint32_t *)screen->pixels; + for (int y = 0; y < 224; y++, buf_32 += (screen->pitch/4 - 320)) { + for (int x = 0; x < 320; x++, buf_32++) { + uint16_t gen_color = context->framebuf[y * 320 + x]; + b = ((gen_color >> 8) & 0xE) * 18; + g = ((gen_color >> 4) & 0xE) * 18; + r = (gen_color& 0xE) * 18; + *buf_32 = SDL_MapRGB(screen->format, r, g, b); + } + } + for (int y = 224; y < 240; y++, buf_32 += (screen->pitch/4 - 320)) { + for (int x = 0; x < 320; x++, buf_32++) { + uint16_t gen_color = context->cram[x/10 + ((y-224)/8)*32]; + b = ((gen_color >> 8) & 0xE) * 18; + g = ((gen_color >> 4) & 0xE) * 18; + r = (gen_color& 0xE) * 18; + *buf_32 = SDL_MapRGB(screen->format, r, g, b); + } + } + break; + } + if ( SDL_MUSTLOCK(screen) ) { + SDL_UnlockSurface(screen); + } + SDL_UpdateRect(screen, 0, 0, 320, 240); +} + +void render_wait_quit() +{ + SDL_Event event; + while(SDL_WaitEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + return; + } + } +} + diff -r 4717146a7606 -r f664eeb55cb4 stateview.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stateview.c Sat Dec 08 02:00:54 2012 -0800 @@ -0,0 +1,25 @@ +#include +#include +#include "vdp.h" +#include "render.h" + +int main(int argc, char ** argv) +{ + if (argc < 2) { + fprintf(stderr, "Usage: stateview FILENAME\n"); + exit(1); + } + FILE * state_file = fopen(argv[1], "rb"); + if (!state_file) { + fprintf(stderr, "Failed to open %s\n", argv[1]); + exit(1); + } + vdp_context context; + init_vdp_context(&context); + vdp_load_savestate(&context, state_file); + vdp_run_to_vblank(&context); + render_init(); + render_context(&context); + render_wait_quit(); + return 0; +} diff -r 4717146a7606 -r f664eeb55cb4 vdp.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vdp.c Sat Dec 08 02:00:54 2012 -0800 @@ -0,0 +1,894 @@ +#include "vdp.h" +#include +#include + +#define MCLKS_LINE 3420 +#define NTSC_ACTIVE 225 +#define PAL_ACTIVE 241 +#define BUF_BIT_PRIORITY 0x40 +#define MAP_BIT_PRIORITY 0x8000 +#define MAP_BIT_H_FLIP 0x800 +#define MAP_BIT_V_FLIP 0x1000 + +#define BIT_PAL 0x8 +#define BIT_H40 0x1 + +void init_vdp_context(vdp_context * context) +{ + memset(context, 0, sizeof(context)); + context->vdpmem = malloc(VRAM_SIZE); + context->framebuf = malloc(FRAMEBUF_SIZE); + context->linebuf = malloc(LINEBUF_SIZE + 48); + context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; + context->tmp_buf_b = context->tmp_buf_a + 24; +} + +void render_sprite_cells(uint32_t linecyc, vdp_context * context) +{ + if (linecyc < context->sprite_draws) { + sprite_draw * d = context->sprite_draw_list + linecyc; + uint16_t dir; + int16_t x; + if (d->h_flip) { + x = d->x_pos + 7; + dir = -1; + } else { + x = d->x_pos; + dir = 1; + } + for (uint16_t address = d->address; address < d->address+4; address++) { + if (x >= 0 && x < 320) { + context->linebuf[x] = (context->vdpmem[address] >> 4) | d->pal_priority; + } + x += dir; + if (x >= 0 && x < 320) { + context->linebuf[x] = (context->vdpmem[address] & 0xF) | d->pal_priority; + } + x += dir; + } + } +} + +void scan_sprite_table(uint32_t line, vdp_context * context) +{ + if (context->sprite_index && context->slot_counter) { + line += 1; + line &= 0xFF; + line += 128; + context->sprite_index &= 0x7F; + //TODO: Read from SAT cache rather than from VRAM + uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9; + uint16_t address = context->sprite_index * 8 + sat_address; + uint16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) - 128; + uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; + if (y >= line && (y + height) < line) { + context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; + context->sprite_info_list[context->slot_counter].index = context->sprite_index; + context->sprite_info_list[context->slot_counter].y = y; + } + context->sprite_index = context->vdpmem[address+3] & 0x7F; + if (context->sprite_index && context->slot_counter) + { + address = context->sprite_index * 8 + sat_address; + y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) - 128; + height = ((context->vdpmem[address+2] & 0x3) + 1) * 8; + if (y >= line && y < (line + height)) { + context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2]; + context->sprite_info_list[context->slot_counter].index = context->sprite_index; + context->sprite_info_list[context->slot_counter].y = y; + } + } + } +} + +void read_sprite_x(uint32_t line, vdp_context * context) +{ + if (context->slot_counter && context->sprite_draws) { + context->slot_counter--; + uint8_t width = (context->sprite_info_list[context->slot_counter].size & 0x3) + 1; + uint8_t height = (((context->sprite_info_list[context->slot_counter].size >> 2) & 0x3) + 1) * 8; + uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->slot_counter].index * 8 + 4; + uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1]; + uint8_t pal_priority = (tileinfo >> 9) & 0x70; + uint8_t row; + if (tileinfo & MAP_BIT_V_FLIP) { + row = (context->sprite_info_list[context->slot_counter].y + height - 1) - line; + } else { + row = line-context->sprite_info_list[context->slot_counter].y; + } + uint16_t address = ((tileinfo & 0x7FF) << 5) + row * width * 4; + int16_t x = ((context->vdpmem[att_addr+ 6] & 0x3) << 8) | context->vdpmem[att_addr + 7]; + if (x) { + x -= 128; + for (;width && context->sprite_draws; --width, --context->sprite_draws, address += 4, x += 8) { + context->sprite_draw_list[context->sprite_draws].address = address; + context->sprite_draw_list[context->sprite_draws].x_pos = x; + context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority; + context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0; + } + } else { + //sprite masking enabled, no more sprites on this line + context->slot_counter = 0; + } + } +} + +void external_slot(vdp_context * context) +{ + //TODO: Implement me +} + +void read_map_scroll(uint16_t column, uint32_t line, uint32_t scroll_reg, uint16_t hscroll_val, vdp_context * context) +{ + uint16_t address = (context->regs[scroll_reg] & 0x38) << 10; + uint16_t vscroll; + switch(context->regs[REG_SCROLL] & 0x30) + { + case 0: + vscroll = 0xFF; + break; + case 0x10: + vscroll = 0x1FF; + break; + case 0x20: + //TODO: Verify this behavior + vscroll = 0; + break; + case 0x30: + vscroll = 0x3FF; + break; + } + vscroll &= (context->vsram[context->regs[REG_MODE_3] & 0x4 ? column : 0] + line); + context->v_offset = vscroll & 0x7; + vscroll /= 8; + uint16_t hscroll_mask; + uint16_t v_mul; + switch(context->regs[REG_SCROLL] & 0x3) + { + case 0: + hscroll_mask = 0xF8; + v_mul = 64; + break; + case 0x1: + hscroll_mask = 0x1F8; + v_mul = 128; + break; + case 0x2: + //TODO: Verify this behavior + hscroll_mask = 0; + v_mul = 0; + break; + case 0x3: + hscroll_mask = 0x3F8; + v_mul = 256; + break; + } + uint16_t hscroll = (hscroll_val + (column-1) * 8) & hscroll_mask; + uint16_t offset = address + ((vscroll * v_mul + hscroll/4) & 0x1FFF); + //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); + context->col_1 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1]; + hscroll = (hscroll_val + column * 8) & hscroll_mask; + offset = address + ((vscroll * v_mul + hscroll/4) & 0x1FFF); + context->col_2 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1]; +} + +void read_map_scroll_a(uint16_t column, uint32_t line, vdp_context * context) +{ + read_map_scroll(column, line, REG_SCROLL_A, context->hscroll_a, context); +} + +void read_map_scroll_b(uint16_t column, uint32_t line, vdp_context * context) +{ + read_map_scroll(column, line, REG_SCROLL_B, context->hscroll_b, context); +} + +void render_map(uint16_t col, uint8_t * tmp_buf, vdp_context * context) +{ + uint16_t address = ((col & 0x3FF) << 5); + if (col & MAP_BIT_V_FLIP) { + address += 24 - 4 * context->v_offset; + } else { + address += 4 * context->v_offset; + } + uint16_t pal_priority = (col >> 9) & 0x70; + int32_t dir; + if (col & MAP_BIT_H_FLIP) { + tmp_buf += 7; + dir = -1; + } else { + dir = 1; + } + for (uint32_t i=0; i < 4; i++, address++) + { + *tmp_buf = pal_priority | (context->vdpmem[address] >> 4); + tmp_buf += dir; + *tmp_buf = pal_priority | (context->vdpmem[address] & 0xF); + tmp_buf += dir; + } +} + +void render_map_1(vdp_context * context) +{ + render_map(context->col_1, context->tmp_buf_a+8, context); +} + +void render_map_2(vdp_context * context) +{ + render_map(context->col_2, context->tmp_buf_a+16, context); +} + +void render_map_3(vdp_context * context) +{ + render_map(context->col_1, context->tmp_buf_b+8, context); +} + +void render_map_output(uint32_t line, int32_t col, vdp_context * context) +{ + if (line >= 240) { + return; + } + render_map(context->col_2, context->tmp_buf_b+16, context); + uint16_t *dst, *end; + uint8_t *sprite_buf, *plane_a, *plane_b; + if (col) + { + col-=2; + dst = context->framebuf + line * 320 + col * 8; + sprite_buf = context->linebuf + col * 8; + plane_a = context->tmp_buf_a + 8 - (context->hscroll_a & 0x7); + plane_b = context->tmp_buf_b + 8 - (context->hscroll_b & 0x7); + /*if (col == 40) + { + end = dst + 8; + } else {*/ + end = dst + 16; + //} + for (; dst < end; ++plane_a, ++plane_b, ++sprite_buf, ++dst) { + uint8_t pixel; + if (*sprite_buf & BUF_BIT_PRIORITY) { + pixel = *sprite_buf; + } else if (*plane_a & BUF_BIT_PRIORITY) { + pixel = *plane_a; + } else if (*plane_b & BUF_BIT_PRIORITY) { + pixel = *plane_b; + } else if (*sprite_buf & 0xF) { + pixel = *sprite_buf; + } else if (*plane_a & 0xF) { + pixel = *plane_a; + } else if (*plane_b & 0xF){ + pixel = *plane_b; + } else { + pixel = context->regs[REG_BG_COLOR] & 0x3F; + } + *dst = context->cram[pixel & 0x3F] | ((pixel & BUF_BIT_PRIORITY) ? 0x1000 : 0); + } + } else { + //dst = context->framebuf + line * 320; + //sprite_buf = context->linebuf + col * 8; + //plane_a = context->tmp_buf_a + 16 - (context->hscroll_a & 0x7); + //plane_b = context->tmp_buf_b + 16 - (context->hscroll_b & 0x7); + //end = dst + 8; + } + + uint16_t remaining = context->hscroll_a & 0x7; + memcpy(context->tmp_buf_a + 8 - remaining, context->tmp_buf_a + 24 - remaining, remaining); + remaining = context->hscroll_b & 0x7; + memcpy(context->tmp_buf_b + 8 - remaining, context->tmp_buf_a + 24 - remaining, remaining); +} + +#define COLUMN_RENDER_BLOCK(column, startcyc) \ + case startcyc:\ + read_map_scroll_a(column, line, context);\ + break;\ + case (startcyc+1):\ + external_slot(context);\ + break;\ + case (startcyc+2):\ + render_map_1(context);\ + break;\ + case (startcyc+3):\ + render_map_2(context);\ + break;\ + case (startcyc+4):\ + read_map_scroll_b(column, line, context);\ + break;\ + case (startcyc+5):\ + read_sprite_x(line, context);\ + break;\ + case (startcyc+6):\ + render_map_3(context);\ + break;\ + case (startcyc+7):\ + render_map_output(line, column, context);\ + break; + +#define COLUMN_RENDER_BLOCK_REFRESH(column, startcyc) \ + case startcyc:\ + read_map_scroll_a(column, line, context);\ + break;\ + case (startcyc+1):\ + break;\ + case (startcyc+2):\ + render_map_1(context);\ + break;\ + case (startcyc+3):\ + render_map_2(context);\ + break;\ + case (startcyc+4):\ + read_map_scroll_b(column, line, context);\ + break;\ + case (startcyc+5):\ + read_sprite_x(line, context);\ + break;\ + case (startcyc+6):\ + render_map_3(context);\ + break;\ + case (startcyc+7):\ + render_map_output(line, column, context);\ + break; + +void vdp_h40(uint32_t line, uint32_t linecyc, vdp_context * context) +{ + uint16_t address; + uint32_t mask; + switch(linecyc) + { + //sprite render to line buffer starts + case 0: + memset(context->linebuf, 0, LINEBUF_SIZE); + render_sprite_cells(linecyc, context); + break; + case 1: + case 2: + case 3: + render_sprite_cells(linecyc, context); + break; + //sprite attribute table scan starts + case 4: + render_sprite_cells(linecyc, context); + context->sprite_index = 0x80; + context->slot_counter = MAX_SPRITES_LINE; + scan_sprite_table(line, context); + break; + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + //!HSYNC asserted + case 21: + case 22: + render_sprite_cells(linecyc, context); + scan_sprite_table(line, context); + break; + case 23: + external_slot(context); + break; + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + render_sprite_cells(linecyc, context); + scan_sprite_table(line, context); + break; + case 35: + address = (context->regs[REG_HSCROLL] & 0x3F) << 10; + mask = 0; + if (context->regs[REG_MODE_3] & 0x2) { + mask |= 0xF8; + } + if (context->regs[REG_MODE_3] & 0x1) { + mask |= 0x7; + } + line &= mask; + address += line * 4; + context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; + context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; + printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); + break; + case 36: + //!HSYNC high + case 37: + case 38: + case 39: + render_sprite_cells(linecyc, context); + scan_sprite_table(line, context); + break; + case 40: + read_map_scroll_a(0, line, context); + break; + case 41: + render_sprite_cells(linecyc, context); + scan_sprite_table(line, context); + break; + case 42: + render_map_1(context); + scan_sprite_table(line, context);//Just a guess + break; + case 43: + render_map_2(context); + scan_sprite_table(line, context);//Just a guess + break; + case 44: + read_map_scroll_b(0, line, context); + break; + case 45: + render_sprite_cells(linecyc, context); + scan_sprite_table(line, context); + break; + case 46: + render_map_3(context); + scan_sprite_table(line, context);//Just a guess + break; + case 47: + render_map_output(line, 0, context); + scan_sprite_table(line, context);//Just a guess + //reverse context slot counter so it counts the number of sprite slots + //filled rather than the number of available slots + context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; + context->sprite_draws = MAX_DRAWS; + break; + COLUMN_RENDER_BLOCK(2, 48) + COLUMN_RENDER_BLOCK(4, 56) + COLUMN_RENDER_BLOCK(6, 64) + COLUMN_RENDER_BLOCK_REFRESH(8, 72) + COLUMN_RENDER_BLOCK(10, 80) + COLUMN_RENDER_BLOCK(12, 88) + COLUMN_RENDER_BLOCK(14, 96) + COLUMN_RENDER_BLOCK_REFRESH(16, 104) + COLUMN_RENDER_BLOCK(18, 112) + COLUMN_RENDER_BLOCK(20, 120) + COLUMN_RENDER_BLOCK(22, 128) + COLUMN_RENDER_BLOCK_REFRESH(24, 136) + COLUMN_RENDER_BLOCK(26, 144) + COLUMN_RENDER_BLOCK(28, 152) + COLUMN_RENDER_BLOCK(30, 160) + COLUMN_RENDER_BLOCK_REFRESH(32, 168) + COLUMN_RENDER_BLOCK(34, 176) + COLUMN_RENDER_BLOCK(36, 184) + COLUMN_RENDER_BLOCK(38, 192) + COLUMN_RENDER_BLOCK_REFRESH(40, 200) + case 208: + context->sprite_draws = MAX_DRAWS - context->sprite_draws; + case 209: + external_slot(context); + break; + default: + //leftovers from HSYNC clock change nonsense + break; + } +} + +void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context) +{ + switch(linecyc) + { + //sprite render to line buffer starts + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 10: + break; + case 11: + break; + case 12: + break; + case 13: + break; + case 14: + break; + case 15: + break; + case 16: + break; + case 17: + break; + case 18: + break; + case 19: + break; + case 20: + break; + case 21: + break; + case 22: + break; + case 23: + break; + case 24: + break; + case 25: + break; + case 26: + break; + case 27: + break; + case 28: + break; + case 29: + break; + case 30: + break; + case 31: + break; + case 32: + break; + case 33: + break; + case 34: + break; + case 35: + break; + case 36: + break; + case 37: + break; + case 38: + break; + case 39: + break; + case 40: + break; + case 41: + break; + case 42: + break; + case 43: + break; + case 44: + break; + case 45: + break; + case 46: + break; + case 47: + break; + case 48: + break; + case 49: + break; + case 50: + break; + case 51: + break; + case 52: + break; + case 53: + break; + case 54: + break; + case 55: + break; + case 56: + break; + case 57: + break; + case 58: + break; + case 59: + break; + case 60: + break; + case 61: + break; + case 62: + break; + case 63: + break; + case 64: + break; + case 65: + break; + case 66: + break; + case 67: + break; + case 68: + break; + case 69: + break; + case 70: + break; + case 71: + break; + case 72: + break; + case 73: + break; + case 74: + break; + case 75: + break; + case 76: + break; + case 77: + break; + case 78: + break; + case 79: + break; + case 80: + break; + case 81: + break; + case 82: + break; + case 83: + break; + case 84: + break; + case 85: + break; + case 86: + break; + case 87: + break; + case 88: + break; + case 89: + break; + case 90: + break; + case 91: + break; + case 92: + break; + case 93: + break; + case 94: + break; + case 95: + break; + case 96: + break; + case 97: + break; + case 98: + break; + case 99: + break; + case 100: + break; + case 101: + break; + case 102: + break; + case 103: + break; + case 104: + break; + case 105: + break; + case 106: + break; + case 107: + break; + case 108: + break; + case 109: + break; + case 110: + break; + case 111: + break; + case 112: + break; + case 113: + break; + case 114: + break; + case 115: + break; + case 116: + break; + case 117: + break; + case 118: + break; + case 119: + break; + case 120: + break; + case 121: + break; + case 122: + break; + case 123: + break; + case 124: + break; + case 125: + break; + case 126: + break; + case 127: + break; + case 128: + break; + case 129: + break; + case 130: + break; + case 131: + break; + case 132: + break; + case 133: + break; + case 134: + break; + case 135: + break; + case 136: + break; + case 137: + break; + case 138: + break; + case 139: + break; + case 140: + break; + case 141: + break; + case 142: + break; + case 143: + break; + case 144: + break; + case 145: + break; + case 146: + break; + case 147: + break; + case 148: + break; + case 149: + break; + case 150: + break; + case 151: + break; + case 152: + break; + case 153: + break; + case 154: + break; + case 155: + break; + case 156: + break; + case 157: + break; + case 158: + break; + case 159: + break; + case 160: + break; + case 161: + break; + case 162: + break; + case 163: + break; + case 164: + break; + case 165: + break; + case 166: + break; + case 167: + break; + case 168: + break; + case 169: + break; + case 170: + break; + case 171: + break; + } +} +void latch_mode(vdp_context * context) +{ + context->latched_mode = (context->regs[REG_MODE_4] & 0x81) | (context->regs[REG_MODE_2] & BIT_PAL); +} + +void vdp_run_context(vdp_context * context, uint32_t target_cycles) +{ + while(context->cycles < target_cycles) + { + uint32_t line = context->cycles / MCLKS_LINE; + uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE; + if (line < active_lines) { + if (!line) { + latch_mode(context); + } + //first sort-of active line is treated as 255 internally + //it's used for gathering sprite info for line + line = (line - 1) & 0xFF; + uint32_t linecyc = context->cycles % MCLKS_LINE; + + //Convert to slot number + if (context->latched_mode & BIT_H40){ + //TODO: Deal with nasty clock switching during HBLANK + linecyc = linecyc/16; + context->cycles += 16; + vdp_h40(line, linecyc, context); + } else { + linecyc = linecyc/20; + context->cycles += 20; + vdp_h32(line, linecyc, context); + } + } else { + //TODO: Empty FIFO + } + } +} + +uint32_t vdp_run_to_vblank(vdp_context * context) +{ + uint32_t target_cycles = ((context->latched_mode & BIT_PAL) ? PAL_ACTIVE : NTSC_ACTIVE) * MCLKS_LINE; + vdp_run_context(context, target_cycles); + return context->cycles; +} + +#define GST_VDP_REGS 0xFA +#define GST_VDP_MEM 0x12478 + +void vdp_load_savestate(vdp_context * context, FILE * state_file) +{ + uint8_t tmp_buf[CRAM_SIZE*2]; + fseek(state_file, GST_VDP_REGS, SEEK_SET); + fread(context->regs, 1, VDP_REGS, state_file); + latch_mode(context); + fread(tmp_buf, 1, sizeof(tmp_buf), state_file); + for (int i = 0; i < CRAM_SIZE; i++) { + context->cram[i] = (tmp_buf[i*2+1] << 8) | tmp_buf[i*2]; + } + fread(tmp_buf, 2, VSRAM_SIZE, state_file); + for (int i = 0; i < VSRAM_SIZE; i++) { + context->vsram[i] = (tmp_buf[i*2] << 8) | tmp_buf[i*2+1]; + } + fseek(state_file, GST_VDP_MEM, SEEK_SET); + fread(context->vdpmem, 1, VRAM_SIZE, state_file); +} diff -r 4717146a7606 -r f664eeb55cb4 vdp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vdp.h Sat Dec 08 02:00:54 2012 -0800 @@ -0,0 +1,80 @@ +#ifndef VDP_H_ +#define VDP_H_ + +#include +#include + +#define VDP_REGS 24 +#define CRAM_SIZE 64 +#define VSRAM_SIZE 40 +#define VRAM_SIZE (64*1024) +#define LINEBUF_SIZE 320 +#define FRAMEBUF_ENTRIES 320*224 +#define FRAMEBUF_SIZE (FRAMEBUF_ENTRIES*sizeof(uint16_t)) +#define MAX_DRAWS 40 +#define MAX_SPRITES_LINE 20 + +enum { + REG_MODE_1=0, + REG_MODE_2, + REG_SCROLL_A, + REG_WINDOW, + REG_SCROLL_B, + REG_SAT, + REG_BG_COLOR, + REG_HINT=0xA, + REG_MODE_3, + REG_MODE_4, + REG_HSCROLL, + REG_AUTOINC=0xF, + REG_SCROLL, + REG_WINDOW_H, + REG_WINDOW_V +} vdp_regs; + +typedef struct { + uint16_t address; + int16_t x_pos; + uint8_t pal_priority; + uint8_t h_flip; +} sprite_draw; + +typedef struct { + uint8_t size; + uint8_t index; + int16_t y; +} sprite_info; + +typedef struct { + //cycle count in MCLKs + uint32_t cycles; + uint8_t *vdpmem; + //stores 2-bit palette + 4-bit palette index + priority for current sprite line + uint8_t *linebuf; + //stores 12-bit color + shadow/highlight bits + uint16_t *framebuf; + uint16_t cram[CRAM_SIZE]; + uint16_t vsram[VSRAM_SIZE]; + uint8_t latched_mode; + uint16_t hscroll_a; + uint16_t hscroll_b; + uint8_t sprite_index; + uint8_t sprite_draws; + uint8_t slot_counter; + uint8_t regs[VDP_REGS]; + sprite_draw sprite_draw_list[MAX_DRAWS]; + sprite_info sprite_info_list[MAX_SPRITES_LINE]; + uint16_t col_1; + uint16_t col_2; + uint8_t v_offset; + uint8_t *tmp_buf_a; + uint8_t *tmp_buf_b; +} vdp_context; + +void init_vdp_context(vdp_context * context); +void vdp_run_context(vdp_context * context, uint32_t target_cycles); +//runs from current cycle count to VBLANK for the current mode, returns ending cycle count +uint32_t vdp_run_to_vblank(vdp_context * context); +void vdp_load_savestate(vdp_context * context, FILE * state_file); + +#endif //VDP_H_