OSDN Git Service

sprite xfer ok
authorastoria-d <astoria-d@mail.goo.ne.jp>
Wed, 13 Mar 2013 03:20:46 +0000 (12:20 +0900)
committerastoria-d <astoria-d@mail.goo.ne.jp>
Wed, 13 Mar 2013 03:20:46 +0000 (12:20 +0900)
emulator/cpu.c
emulator/ppucore/dummy-driver2.c
emulator/ppucore/sprite.h [new file with mode: 0644]
emulator/ppucore/vram.c
emulator/ppucore/vram.h
emulator/ppucore/vscreen.c

index ad4dea9..80a0035 100644 (file)
@@ -88,6 +88,8 @@ void store_memory(unsigned short addr, unsigned char data) {
  * */
 unsigned short load_addr(unsigned short addr, int cycle) {
     unsigned char byte = load_memory(addr);
+
+    ///NES=little endian. lower byte first, higher byte second.
     if (cycle == 1)
         cpu_addr_buffer = byte;
     else
index 21540ed..9148f77 100644 (file)
@@ -9,6 +9,7 @@
 #include "tools.h"
 #include "vga.h"
 #include "vram.h"
+#include "sprite.h"
 
 static struct rgb15 *disp_data;
 void *vga_shm_get(void);
@@ -20,6 +21,7 @@ void set_vga_base(unsigned char* base);
 void vga_xfer(void);
 void dump_vram(int type, int bank, unsigned short addr, int size);
 void set_bgtile(int tile_id);
+void set_sprite(int x, int y, int tile_id, struct sprite_attr sa);
 
 struct timespec sleep_inteval = {0, 1000000 / VGA_REFRESH_RATE};
 
@@ -67,13 +69,12 @@ static void test_ppu(void) {
         spr_palette_tbl_set(i, plt[i + 16]);
 
     for (i = 0; i < 960; i++) 
-        name_tbl_set(0, i, 2);
+        name_tbl_set(0, i, 0);
 
     for (i = 0; i < 64; i++) 
         attr_tbl_set(0, i, 0);
 
     //name_tbl_set(0, 205, 2);
-    name_tbl_set(0, 300, 1);
     name_tbl_set(0, 205, 'D');
     name_tbl_set(0, 206, 'e');
     name_tbl_set(0, 207, 'e');
@@ -81,12 +82,27 @@ static void test_ppu(void) {
     name_tbl_set(0, 209, '!');
     //205 = palette gp2 01100101b
     //205 = 11
-    attr_tbl_set(0, 0, 0x65);
     attr_tbl_set(0, 11, 0x65);
 
+    //other test.
+    name_tbl_set(0, 300, 1);
+    attr_tbl_set(0, 0, 0x65);
+
     for (i = 0; i < 960; i++) 
         set_bgtile(i);
 
+    //sprite test
+    struct sprite_attr sa;
+    sa.palette = 2;
+    sa.priority = 1;
+    sa.flip_h = 0;
+    sa.flip_v = 0;
+    set_sprite(30, 100, 'd', sa);
+    sa.flip_h = 1;
+    set_sprite(50, 100, 'd', sa);
+    sa.flip_v = 1;
+    set_sprite(70, 105, 'd', sa);
+
     vga_xfer();
 
 //void dump_vram(int type, int bank, unsigned short addr, int size);
diff --git a/emulator/ppucore/sprite.h b/emulator/ppucore/sprite.h
new file mode 100644 (file)
index 0000000..1cbad24
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __sprite_h__
+#define __sprite_h__
+
+/*
+ * NES is little endian.
+ * low bit comes first.
+ * high bit follows.
+ * */
+struct sprite_attr {
+    unsigned int palette    :2;
+    unsigned int unused     :3;
+    unsigned int priority   :1;
+    unsigned int flip_h     :1;
+    unsigned int flip_v     :1;
+} __attribute__ ((packed));
+
+#endif /*__sprite_h__*/
+
index 922f43d..e06e456 100644 (file)
@@ -6,6 +6,7 @@
 #include "tools.h"
 #include "ppucore.h"
 #include "vram.h"
+#include "sprite.h"
 
 void palette_index_to_rgb15(unsigned char index, struct rgb15* rgb);
 void dump_mem(const char* msg, unsigned short base, 
@@ -222,12 +223,30 @@ void load_attribute(unsigned char bank, int tile_index, struct palette *plt) {
 
 }
 
+void load_spr_attribute(struct sprite_attr sa, struct palette *plt) {
+    unsigned short palette_addr;
+    unsigned char pi;
+
+    /*load bg rgb palette color*/
+    palette_addr = sa.palette * 4;
+    pi = bg_palette_tbl_get(palette_addr++);
+    palette_index_to_rgb15(pi, &plt->col[0]);
+
+    pi = bg_palette_tbl_get(palette_addr++);
+    palette_index_to_rgb15(pi, &plt->col[1]);
+
+    pi = bg_palette_tbl_get(palette_addr++);
+    palette_index_to_rgb15(pi, &plt->col[2]);
+
+    pi = bg_palette_tbl_get(palette_addr);
+    palette_index_to_rgb15(pi, &plt->col[3]);
+}
+
 /*
  * pattern index: 0 - 255
  * */
 void load_pattern(unsigned char bank, unsigned char ptn_index, struct tile_2* pattern) {
     int i;
-    unsigned char data;
     unsigned char *p;
     unsigned short addr;
 
@@ -235,8 +254,7 @@ void load_pattern(unsigned char bank, unsigned char ptn_index, struct tile_2* pa
     p = (unsigned char*)pattern;
     addr = ptn_index * sizeof(struct tile_2);
     for (i = 0; i < sizeof(struct tile_2); i++) {
-        data = pattern_tbl_get(bank, addr);
-        *p = data;
+        *p = pattern_tbl_get(bank, addr);
         p++;
         addr++;
     }
index ec43b46..5f5e02f 100644 (file)
@@ -24,6 +24,12 @@ void spr_ram_tbl_set(unsigned short addr, unsigned char data);
 int vram_init(void);
 void clean_vram(void);
 
+/*
+ * NES is little endian.
+ * low bit comes first.
+ * high bit follows.
+ *
+ * */
 struct tile_1_line{
     unsigned int dot0   :1;
     unsigned int dot1   :1;
index f67c910..36e5f0e 100644 (file)
@@ -6,9 +6,11 @@
 #include "vga.h"
 #include "ppucore.h"
 #include "vram.h"
+#include "sprite.h"
 
 void load_attribute(unsigned char bank, int tile_index, struct palette *plt);
 void load_pattern(unsigned char bank, unsigned char ptn_index, struct tile_2* pattern);
+void load_spr_attribute(struct sprite_attr sa, struct palette *plt);
 
 struct tile_rgb15_line {
     struct rgb15 d[8];
@@ -20,6 +22,36 @@ struct tile_rgb15 {
 
 static struct tile_rgb15 *vscreen;
 
+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;
+    struct tile_rgb15* tile;
+
+    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;
+    tile = vscreen + tile_id;
+
+    inner_x = x % TILE_DOT_SIZE;
+    inner_y = y % TILE_DOT_SIZE;
+    *col = tile->l[inner_y].d[inner_x];
+}
+
+void vscreenn_dot_set(int x, int y, struct rgb15 *col) {
+    int tile_id, tile_id_x, tile_id_y;
+    int inner_x, inner_y;
+    struct tile_rgb15* tile;
+
+    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;
+    tile = vscreen + tile_id;
+
+    inner_x = x % TILE_DOT_SIZE;
+    inner_y = y % TILE_DOT_SIZE;
+    tile->l[inner_y].d[inner_x] = *col;
+}
+
 
 void set_bgtile(int tile_id) {
     struct palette plt;
@@ -35,56 +67,75 @@ void set_bgtile(int tile_id) {
 
     set_data = vscreen + tile_id;
     for (i = 0; i < TILE_DOT_SIZE; i++) {
-        set_data->l[i].d[0] = plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot0];
-        set_data->l[i].d[1] = plt.col[ptn.b0.l[i].dot1 + ptn.b1.l[i].dot1];
-        set_data->l[i].d[2] = plt.col[ptn.b0.l[i].dot2 + ptn.b1.l[i].dot2];
-        set_data->l[i].d[3] = plt.col[ptn.b0.l[i].dot3 + ptn.b1.l[i].dot3];
-        set_data->l[i].d[4] = plt.col[ptn.b0.l[i].dot4 + ptn.b1.l[i].dot4];
-        set_data->l[i].d[5] = plt.col[ptn.b0.l[i].dot5 + ptn.b1.l[i].dot5];
-        set_data->l[i].d[6] = plt.col[ptn.b0.l[i].dot6 + ptn.b1.l[i].dot6];
-        set_data->l[i].d[7] = plt.col[ptn.b0.l[i].dot7 + ptn.b1.l[i].dot7];
+        //display shows left to right with high bit to low bit
+        set_data->l[i].d[7] = plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot0];
+        set_data->l[i].d[6] = plt.col[ptn.b0.l[i].dot1 + ptn.b1.l[i].dot1];
+        set_data->l[i].d[5] = plt.col[ptn.b0.l[i].dot2 + ptn.b1.l[i].dot2];
+        set_data->l[i].d[4] = plt.col[ptn.b0.l[i].dot3 + ptn.b1.l[i].dot3];
+        set_data->l[i].d[3] = plt.col[ptn.b0.l[i].dot4 + ptn.b1.l[i].dot4];
+        set_data->l[i].d[2] = plt.col[ptn.b0.l[i].dot5 + ptn.b1.l[i].dot5];
+        set_data->l[i].d[1] = plt.col[ptn.b0.l[i].dot6 + ptn.b1.l[i].dot6];
+        set_data->l[i].d[0] = plt.col[ptn.b0.l[i].dot7 + ptn.b1.l[i].dot7];
     }
 
 }
 
-void set_bg(void) {
-/*
+void set_sprite(int x, int y, int tile_id, struct sprite_attr sa) {
+    struct palette plt;
+    struct tile_2 ptn;
     int i;
-    //struct tile_rgb15* set_data = vscreen + tile_id;
-    unsigned char data;
-    unsigned char *p;
-    struct tile_2 pattern;
-    unsigned short addr;
-    //load name tbl
-    //name_tbl_get();
-
-    //load character pattern
-    p = (unsigned char*)&pattern;
-    addr = tile_id * sizeof(struct tile_2);
-    for (i = 0; i < sizeof(struct tile_2); i++) {
-        data = pattern_tbl_get(bg_bank, addr);
-        *p = data;
-        p++;
-    }
 
-    //load attribute.
-*/
-}
+    load_spr_attribute(sa, &plt);
 
-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;
-    struct tile_rgb15* tile;
-
-    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;
-    tile = vscreen + tile_id;
-
-    inner_x = x % TILE_DOT_SIZE;
-    inner_y = y % TILE_DOT_SIZE;
-    *col = tile->l[inner_y].d[inner_x];
+    load_pattern(0, tile_id, &ptn);
 
+    //display shows left to right with high bit to low bit
+    for (i = 0; i < TILE_DOT_SIZE; i++) {
+        if (sa.flip_h) {
+            if (sa.flip_v) {
+                vscreenn_dot_set(x + 0, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot0]);
+                vscreenn_dot_set(x + 1, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot1]);
+                vscreenn_dot_set(x + 2, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot2]);
+                vscreenn_dot_set(x + 3, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot3]);
+                vscreenn_dot_set(x + 4, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot4]);
+                vscreenn_dot_set(x + 5, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot5]);
+                vscreenn_dot_set(x + 6, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot6]);
+                vscreenn_dot_set(x + 7, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot7]);
+            }
+            else {
+                vscreenn_dot_set(x + 0, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot0]);
+                vscreenn_dot_set(x + 1, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot1]);
+                vscreenn_dot_set(x + 2, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot2]);
+                vscreenn_dot_set(x + 3, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot3]);
+                vscreenn_dot_set(x + 4, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot4]);
+                vscreenn_dot_set(x + 5, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot5]);
+                vscreenn_dot_set(x + 6, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot6]);
+                vscreenn_dot_set(x + 7, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot7]);
+            }
+        }
+        else {
+            if (sa.flip_v) {
+                vscreenn_dot_set(x + 7, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot0]);
+                vscreenn_dot_set(x + 6, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot1]);
+                vscreenn_dot_set(x + 5, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot2]);
+                vscreenn_dot_set(x + 4, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot3]);
+                vscreenn_dot_set(x + 3, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot4]);
+                vscreenn_dot_set(x + 2, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot5]);
+                vscreenn_dot_set(x + 1, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot6]);
+                vscreenn_dot_set(x + 0, y + 7 - i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot7]);
+            }
+            else {
+                vscreenn_dot_set(x + 7, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot0]);
+                vscreenn_dot_set(x + 6, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot1]);
+                vscreenn_dot_set(x + 5, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot2]);
+                vscreenn_dot_set(x + 4, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot3]);
+                vscreenn_dot_set(x + 3, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot4]);
+                vscreenn_dot_set(x + 2, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot5]);
+                vscreenn_dot_set(x + 1, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot6]);
+                vscreenn_dot_set(x + 0, y + i, &plt.col[ptn.b0.l[i].dot0 + ptn.b1.l[i].dot7]);
+            }
+        }
+    }
 }
 
 int vscreen_init(void) {