OSDN Git Service

load bg and stripe update, temporary commit...
authorastoria-d <astoria-d@mail.goo.ne.jp>
Sat, 30 Mar 2013 02:53:54 +0000 (11:53 +0900)
committerastoria-d <astoria-d@mail.goo.ne.jp>
Sat, 30 Mar 2013 02:53:54 +0000 (11:53 +0900)
emulator/ppucore/ppucore.c
emulator/ppucore/vga_xfer.c
emulator/ppucore/vscreen.c

index f0eecca..c1ff6a8 100644 (file)
@@ -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 {
index ad40cca..493359b 100644 (file)
@@ -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;
index 4694c99..198fecc 100644 (file)
@@ -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)