From: astoria-d Date: Sat, 30 Mar 2013 02:53:54 +0000 (+0900) Subject: load bg and stripe update, temporary commit... X-Git-Tag: motonesemu-0.1.2~12 X-Git-Url: http://git.osdn.net/view?p=motonesemu%2Fmotonesemu.git;a=commitdiff_plain;h=169da1943e285365ae09fd746c86c5242d6c690c load bg and stripe update, temporary commit... --- diff --git a/emulator/ppucore/ppucore.c b/emulator/ppucore/ppucore.c index f0eecca..c1ff6a8 100644 --- a/emulator/ppucore/ppucore.c +++ b/emulator/ppucore/ppucore.c @@ -134,18 +134,18 @@ static void *ppucore_loop(void* arg) { for (scanline = 0; scanline < SCAN_LINE; scanline++) { if (ctrl_reg2.show_sprite) { //sprite in the back - load_sprite(FALSE, scanline); + load_sprite_old(FALSE, scanline); } if (ctrl_reg2.show_bg/**/) { //back ground image is pre-loaded. load 1 line ahead of drawline. if (scanline == 0) - load_background(scanline); + load_background_old(scanline); if (scanline < SCAN_LINE - 1) load_background(scanline + 8); } if (ctrl_reg2.show_sprite) { //foreground sprite - load_sprite(TRUE, scanline); + load_sprite_old(TRUE, scanline); } vga_xfer(scanline); } @@ -202,20 +202,20 @@ static int clock_ppu(void) { if (ctrl_reg2.show_sprite) { //sprite in the back - load_sprite(FALSE, scanline); + load_sprite_old(FALSE, scanline); } if (ctrl_reg2.show_bg/**/) { //back ground image is pre-loaded. load 1 line ahead of drawline. if (scanline == 0) - load_background(scanline); + load_background_old(scanline); if (scanline < SCAN_LINE - 1) - load_background(scanline + 8); + load_background_old(scanline + 8); } if (ctrl_reg2.show_sprite) { //foreground sprite - load_sprite(TRUE, scanline); + load_sprite_old(TRUE, scanline); } - vga_xfer(scanline); + vga_xfer_old(scanline); } } else { diff --git a/emulator/ppucore/vga_xfer.c b/emulator/ppucore/vga_xfer.c index ad40cca..493359b 100644 --- a/emulator/ppucore/vga_xfer.c +++ b/emulator/ppucore/vga_xfer.c @@ -4,6 +4,7 @@ #include "ppucore.h" void vscreenn_dot_get(int x, int y, struct rgb15 *col); +struct rgb15 *get_vscreen_head(void); #define VSCREEN_WIDTH (H_SCREEN_TILE_SIZE * TILE_DOT_SIZE) #define VSCREEN_HEIGHT (V_SCREEN_TILE_SIZE * TILE_DOT_SIZE) @@ -51,7 +52,7 @@ static int vga_y; static int vscrn_y, vscrn_y_old; static struct rgb15 *vga_col; -void vga_xfer(int scanline) { +void vga_xfer_old(int scanline) { int vscrn_x, vscrn_x_old; int vga_x; struct rgb15 *col_old; @@ -95,6 +96,58 @@ void vga_xfer(int scanline) { } } +static struct rgb15 *vs_col, *vs_head; +static struct rgb15 *vga_col; + +void vga_posinit(void) { + vs_head = (struct rgb15 *)get_vscreen_head(); +} + +void vga_xfer(int vs_x, int vs_y) { + int vga_x, vga_y, vga_x_next; + struct rgb15 *vga_col_next; + + //dprint("vga_xfer x:%d, y:%d\n", vs_x, vs_y); + //x direction scale is 640/256. + //y direction scale is 480/240 + + if (vs_x == 0) { + int tile_id, tile_id_y; + int inner_y; + + tile_id_y = vs_y / TILE_DOT_SIZE; + tile_id = tile_id_y * H_SCREEN_TILE_SIZE; + inner_y = vs_y % TILE_DOT_SIZE; + + vs_col = vs_head + tile_id * TILE_DOT_SIZE * TILE_DOT_SIZE + inner_y * TILE_DOT_SIZE; + + vga_y = vs_y * VGA_HEIGHT / VSCREEN_HEIGHT; + vga_col = vga_base + vga_y * VGA_WIDTH; + } + else { + if (vs_x % TILE_DOT_SIZE) { + vs_col++; + } + else { + vs_col += (TILE_DOT_SIZE - 1) * TILE_DOT_SIZE + 1; + } + } + + vga_x = vs_x * VGA_WIDTH / VSCREEN_WIDTH; + vga_x_next = (vs_x + 1) * VGA_WIDTH / VSCREEN_WIDTH; + vga_col_next = vga_col + vga_x_next - vga_x; + + //copy color in vscreen to vga buffer. + while ( vga_col != vga_col_next) { + *vga_col = *vs_col; + //double the copy of the next dot below as well + //since y direction scale is just x2. + *(vga_col + VGA_WIDTH) = *vs_col; + vga_col++; + } + +} + int vga_xfer_init(void) { emp_red = FALSE; emp_green = FALSE; diff --git a/emulator/ppucore/vscreen.c b/emulator/ppucore/vscreen.c index 4694c99..198fecc 100644 --- a/emulator/ppucore/vscreen.c +++ b/emulator/ppucore/vscreen.c @@ -27,6 +27,11 @@ struct tile_rgb15 { struct tile_rgb15_line l[8]; }; +struct sprite_buf_reg { + struct palette plt; + struct tile_2 ptn; +}; + static struct tile_rgb15 *vscreen; static unsigned char bg_pattern_bank; @@ -34,6 +39,13 @@ static unsigned char spr_pattern_bank; static unsigned short bg_name_tbl_base; static unsigned char bg_attr_tbl_bank; + +#define SPRITE_PREFETCH_CNT 64 +static struct ppu_sprite_reg sprite_temp_buf [SPRITE_PREFETCH_CNT]; +static struct sprite_buf_reg sprite_buf [SPRITE_PREFETCH_CNT]; +static int sprite_hit_cnt; + + void vscreenn_dot_get(int x, int y, struct rgb15 *col) { int tile_id, tile_id_x, tile_id_y; int inner_x, inner_y; @@ -122,7 +134,7 @@ void set_bgtile(int tile_id) { } -int load_background(int scanline) { +int load_background_old(int scanline) { int i, start, end; //load tile must be executed every 8 scanlines only. @@ -137,6 +149,49 @@ int load_background(int scanline) { return TRUE; } +static struct palette plt; +static struct tile_2 ptn; +static struct tile_rgb15* set_data; +int load_background(int x, int y) { + //dprint("load bg x:%d, y:%d...\n", x, y); + + int inner_x, inner_y; + + + //tile loading happens every 8 dots only. + if (x % TILE_DOT_SIZE == 0) { + int tile_id, tile_id_x, tile_id_y; + unsigned char name_index; + + tile_id_x = x / TILE_DOT_SIZE; + tile_id_y = y / TILE_DOT_SIZE; + tile_id = tile_id_x + tile_id_y * H_SCREEN_TILE_SIZE; + + //dprint("load tile.\n"); + load_attribute(bg_attr_tbl_bank, tile_id, &plt); + name_index = vram_data_get(bg_name_tbl_base + tile_id); + load_pattern(bg_pattern_bank, name_index, &ptn); + set_data = vscreen + tile_id; + } + + + inner_x = x % TILE_DOT_SIZE; + inner_y = y % TILE_DOT_SIZE; + + int pi = pal_index(&ptn, inner_y, inner_x); + if (pi) { + //dprint("%d, %d, colind:%d\n", j, i, pi); + set_data->l[inner_y].d[7 - inner_x] = plt.col[pi]; + } + else { + //transparent bg color is read from sprite 0x10 color. + pi = vram_data_get(TRANSPARENT_PALETTE_ADDR); + palette_index_to_rgb15(pi, &set_data->l[inner_y].d[7 - inner_x]); + } + + return TRUE; +} + void set_sprite(int x, int y, int tile_id, struct sprite_attr sa) { struct palette plt; @@ -184,7 +239,7 @@ void set_sprite(int x, int y, int tile_id, struct sprite_attr sa) { } } -int load_sprite(int foreground, int scanline) { +int load_sprite_old(int foreground, int scanline) { int i; struct sprite_attr sa; unsigned char x, y, tile, tmp; @@ -214,6 +269,104 @@ int load_sprite(int foreground, int scanline) { return TRUE; } +//prefetch sprite step 1. +//load sprite temp buffer. +int sprite_prefetch1(int srch_line) { + int i; + unsigned char tmp; + + sprite_hit_cnt = 0; + for (i = 0; i < SPRITE_CNT; i++) { + int spr_y; + spr_y = spr_ram_tbl_get(4 * i); + if (srch_line < spr_y || srch_line > spr_y + TILE_DOT_SIZE) + continue; + + if (sprite_hit_cnt < SPRITE_PREFETCH_CNT) { + sprite_temp_buf[sprite_hit_cnt].y = spr_y; + sprite_temp_buf[sprite_hit_cnt].index = spr_ram_tbl_get(4 * i + 1); + tmp = spr_ram_tbl_get(4 * i + 2); + memcpy(&sprite_temp_buf[sprite_hit_cnt].sa, &tmp, sizeof(struct sprite_attr)); + sprite_temp_buf[sprite_hit_cnt].x = spr_ram_tbl_get(4 * i + 3); + } +/* + dprint("sprite prefetch hit. #%d, index:%d, srch y:%d, spr y:%d, spr x:%d\n", + i, sprite_temp_buf[sprite_hit_cnt].index, srch_line, spr_y, + sprite_temp_buf[sprite_hit_cnt].x); +*/ + sprite_hit_cnt++; + } + return sprite_hit_cnt; +} + +//prefetch sprite step 2. +//load sprite pattern and palette. +int sprite_prefetch2(int srch_line) { + int i; + int spr_buf_bottom; + + spr_buf_bottom = sprite_hit_cnt > SPRITE_PREFETCH_CNT ? SPRITE_PREFETCH_CNT : sprite_hit_cnt; + for (i = 0; i < spr_buf_bottom; i++) { + load_spr_attribute(sprite_temp_buf[i].sa, &sprite_buf[i].plt); + load_pattern(spr_pattern_bank, sprite_temp_buf[i].index, &sprite_buf[i].ptn); + } + return 0; +} + +int load_sprite(int foreground, int x, int y) { + int i; + int spr_buf_bottom; + int pi; + + //sprite priority: + //draw lowest priority first, + //high priority late. highest priority comes top. + //seek for the topmost sprite on this spot (x, y) + spr_buf_bottom = sprite_hit_cnt > SPRITE_PREFETCH_CNT ? SPRITE_PREFETCH_CNT : sprite_hit_cnt; + for (i = 0; i < spr_buf_bottom; i++) { + if (sprite_temp_buf[i].x <= x && x < sprite_temp_buf[i].x + TILE_DOT_SIZE) { + int x_in, y_in; + int draw_x_in, draw_y_in; + + if (sprite_temp_buf[i].sa.priority != foreground) + continue; + + x_in = x % TILE_DOT_SIZE; + y_in = y % TILE_DOT_SIZE; + if (sprite_temp_buf[i].sa.flip_h) { + draw_x_in = x_in; + if (sprite_temp_buf[i].sa.flip_v) { + draw_y_in = 7 - y_in; + } + else { + draw_y_in = y_in; + } + } + else { + draw_x_in = 7 - x_in; + if (sprite_temp_buf[i].sa.flip_v) { + draw_y_in = 7 - y_in; + } + else { + draw_y_in = y_in; + } + } + + pi = pal_index(&sprite_buf[i].ptn, draw_y_in, draw_x_in); + if (pi) { + //dprint("spr#%d, dot set x:%d, y:%d\n", sprite_temp_buf[i].index, x, y); + vscreenn_dot_set(x, y, &sprite_buf[i].plt.col[pi]); + if (sprite_temp_buf[i].index == 0) { + sprite0_hit_set(); + } + return TRUE; + } + } + } + + return FALSE; +} + void set_bg_pattern_bank(unsigned char bank) { bg_pattern_bank = bank; @@ -240,12 +393,18 @@ void set_bg_name_tbl_base(unsigned char sw) { bg_attr_tbl_bank = sw; } +struct rgb15 *get_vscreen_head(void) { + return (struct rgb15 *)vscreen; +} + int vscreen_init(void) { bg_pattern_bank = 0; spr_pattern_bank = 0; bg_name_tbl_base = NAME0_START; bg_attr_tbl_bank = 0; + sprite_hit_cnt = 0; + vscreen = (struct tile_rgb15 *) malloc( sizeof (struct tile_rgb15) * VIRT_SCREEN_TILE_SIZE * VIRT_SCREEN_TILE_SIZE); if (vscreen == NULL)