OSDN Git Service

show sprite developed.
[motonesemu/motonesemu.git] / emulator / ppucore / vram.c
index cc1bc12..634d75c 100644 (file)
@@ -1,30 +1,22 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <time.h>
 
 #include "tools.h"
 #include "ppucore.h"
 #include "vram.h"
+#include "sprite.h"
 
-void palette_index_to_rgb15(int bank, unsigned char index, struct rgb15* rgb);
-
-#define PATTERN_TBL_SIZE    0x1000
-#define NAME_TBL_SIZE       V_SCREEN_TILE_SIZE * H_SCREEN_TILE_SIZE
-#define ATTR_TBL_SIZE       (VIRT_SCREEN_TILE_SIZE * VIRT_SCREEN_TILE_SIZE \
-                            / ATTR_GROUP_UNIT / ATTR_UNIT_PER_BYTE)
-#define PALETTE_TBL_SIZE    16
-#define SPRITE_RAM_SIZE     0xff
-
-#define PATTERN_ADDR_MASK       (PATTERN_TBL_SIZE - 1)
-#define NAME_TBL_ADDR_MASK      (NAME_TBL_SIZE - 1)
-#define ATTR_TBL_ADDR_MASK      (ATTR_TBL_SIZE - 1)
-#define PALETTE_TBL_ADDR_MASK   (PALETTE_TBL_SIZE - 1)
-#define SPR_RAM_ADDR_MASK       (SPRITE_RAM_SIZE - 1)
+void palette_index_to_rgb15(unsigned char index, struct rgb15* rgb);
+void dump_mem(const char* msg, unsigned short base, 
+        unsigned short offset, unsigned char* buf, int size);
+void set_bgtile(int tile_id);
 
 /*vram definition*/
-static unsigned char * sprite_ram;
 
-static unsigned char * img_palette_tbl;
+static unsigned char * bg_palette_tbl;
 static unsigned char * spr_palette_tbl;
 
 static unsigned char * name_tbl0;
@@ -40,150 +32,396 @@ static unsigned char * attr_tbl3;
 static unsigned char * pattern_tbl0;
 static unsigned char * pattern_tbl1;
 
+//#define PPU_TEST
+#ifdef PPU_TEST
+static int first_time = TRUE;
+#endif /* PPU_TEST */
+
+extern int debug_mode;
+static void (*vram_log_level4)(unsigned short, unsigned char);
+static void dump_vram_write (unsigned short addr, unsigned char data);
+void d4_set(int on_off);
+
 /*
  * VRAM get/set functions....
  *
  * */
 
-unsigned char pattern_tbl_get(unsigned char bank, unsigned short addr) {
-    addr = addr & PATTERN_ADDR_MASK;
+static unsigned char pattern_tbl_get(unsigned char bank, unsigned short offset) {
     if (bank == 0)
-        return pattern_tbl0[addr];
+        return pattern_tbl0[offset];
     else
-        return pattern_tbl1[addr];
+        return pattern_tbl1[offset];
 }
 
-unsigned char name_tbl_get(unsigned char bank, unsigned short addr) {
-    addr = addr & NAME_TBL_ADDR_MASK;
+static unsigned char name_tbl_get(unsigned char bank, unsigned short offset) {
     if (bank == 0)
-        return name_tbl0[addr];
+        return name_tbl0[offset];
     else if (bank == 1)
-        return name_tbl1[addr];
+        return name_tbl1[offset];
     else if (bank == 2)
-        return name_tbl2[addr];
+        return name_tbl2[offset];
     else
-        return name_tbl3[addr];
+        return name_tbl3[offset];
 }
 
-void name_tbl_set(unsigned char bank, unsigned short addr, unsigned char data) {
-    addr = addr & NAME_TBL_ADDR_MASK;
+static void name_tbl_set(unsigned char bank, unsigned short offset, unsigned char data) {
     if (bank == 0)
-        name_tbl0[addr] = data;
+        name_tbl0[offset] = data;
     else if (bank == 1)
-        name_tbl1[addr] = data;
+        name_tbl1[offset] = data;
     else if (bank == 2)
-        name_tbl2[addr] = data;
+        name_tbl2[offset] = data;
     else
-        name_tbl3[addr] = data;
+        name_tbl3[offset] = data;
 }
 
 
-unsigned char attr_tbl_get(unsigned char bank, unsigned short addr) {
-    addr = addr & ATTR_TBL_ADDR_MASK;
+static unsigned char attr_tbl_get(unsigned char bank, unsigned short offset) {
     if (bank == 0)
-        return attr_tbl0[addr];
+        return attr_tbl0[offset];
     else if (bank == 1)
-        return attr_tbl1[addr];
+        return attr_tbl1[offset];
     else if (bank == 2)
-        return attr_tbl2[addr];
+        return attr_tbl2[offset];
     else
-        return attr_tbl3[addr];
+        return attr_tbl3[offset];
 }
 
-void attr_tbl_set(unsigned char bank, unsigned short addr, unsigned char data) {
-    addr = addr & ATTR_TBL_ADDR_MASK;
+static void attr_tbl_set(unsigned char bank, unsigned short offset, unsigned char data) {
     if (bank == 0)
-        attr_tbl0[addr] = data;
+        attr_tbl0[offset] = data;
     else if (bank == 1)
-        attr_tbl1[addr] = data;
+        attr_tbl1[offset] = data;
     else if (bank == 2)
-        attr_tbl2[addr] = data;
+        attr_tbl2[offset] = data;
     else
-        attr_tbl3[addr] = data;
+        attr_tbl3[offset] = data;
 }
 
 
-unsigned char spr_palette_tbl_get(unsigned short addr) {
-    addr = addr & PALETTE_TBL_ADDR_MASK;
-    return spr_palette_tbl[addr];
+static unsigned char spr_palette_tbl_get(unsigned short offset) {
+    return spr_palette_tbl[offset];
 }
 
-void spr_palette_tbl_set(unsigned short addr, unsigned char data) {
-    addr = addr & PALETTE_TBL_ADDR_MASK;
-    spr_palette_tbl[addr] = data;
+static void spr_palette_tbl_set(unsigned short offset, unsigned char data) {
+    spr_palette_tbl[offset] = data;
 }
 
-unsigned char img_palette_tbl_get(unsigned short addr) {
-    addr = addr & PALETTE_TBL_ADDR_MASK;
-    return img_palette_tbl[addr];
+static unsigned char bg_palette_tbl_get(unsigned short offset) {
+    return bg_palette_tbl[offset];
 }
 
-void img_palette_tbl_set(unsigned short addr, unsigned char data) {
-    addr = addr & PALETTE_TBL_ADDR_MASK;
-    img_palette_tbl[addr] = data;
+static void bg_palette_tbl_set(unsigned short offset, unsigned char data) {
+    bg_palette_tbl[offset] = data;
 }
 
+void vram_data_set(unsigned short addr, unsigned char data) {
+#ifdef PPU_TEST
+    if (!first_time)
+        return;
+#endif /* PPU_TEST */
 
-unsigned char spr_ram_tbl_get(unsigned short addr) {
-    addr = addr & SPR_RAM_ADDR_MASK;
-    return sprite_ram[addr];
+    vram_log_level4 (addr, data);
+
+    //mirror 0x4000 up addr.
+    addr &= PPU_ADDR_MASK;
+
+    if (addr < 2 * PATTERN_TBL_SIZE) {
+        //dprint("invalid vram write addr:%04x, data:%2x\n", addr, data);
+        //do nothing. pattern table is read only.
+        extern int critical_error;
+        dprint("invalid vram write!!!!\n");
+        critical_error = TRUE;
+    }
+    else if (addr >= PALETTE_START) {
+        // bg/sprite palette table.
+        if (addr & PALETTE_SPRITE_BIT)
+            spr_palette_tbl_set(addr & PALETTE_TBL_ADDR_MASK, data);
+        else 
+            bg_palette_tbl_set(addr & PALETTE_TBL_ADDR_MASK, data);
+    }
+    else {
+        // name/attr table.
+        // mask 0x3000 up addr.
+        addr &= NAME_ATTR_MASK;
+        if (addr < ATTR0_START) {
+            name_tbl_set(0, addr - NAME0_START, data);
+        }
+        else if (addr < NAME1_START) {
+            attr_tbl_set(0, addr - ATTR0_START, data);
+        }
+        else if (addr < ATTR1_START) {
+            name_tbl_set(1, addr - NAME1_START, data);
+        }
+        else if (addr < NAME2_START) {
+            attr_tbl_set(1, addr - ATTR1_START, data);
+        }
+        else if (addr < ATTR2_START) {
+            name_tbl_set(2, addr - NAME2_START, data);
+        }
+        else if (addr < NAME3_START) {
+            attr_tbl_set(2, addr - ATTR2_START, data);
+        }
+        else if (addr < ATTR3_START) {
+            name_tbl_set(3, addr - NAME3_START, data);
+        }
+        else {
+            attr_tbl_set(3, addr - ATTR3_START, data);
+        }
+    }
 }
 
-void spr_ram_tbl_set(unsigned short addr, unsigned char data) {
-    addr = addr & SPR_RAM_ADDR_MASK;
-    sprite_ram[addr] = data;
+unsigned char vram_data_get(unsigned short addr) {
+
+    addr &= PPU_ADDR_MASK;
+
+    if (addr < PATTERN_TBL_SIZE) {
+        return pattern_tbl_get(0, addr & PATTERN_ADDR_MASK);
+    }
+    if (addr < 2 * PATTERN_TBL_SIZE) {
+        return pattern_tbl_get(1, addr & PATTERN_ADDR_MASK);
+    }
+    else if (addr >= PALETTE_START) {
+        if (addr & PALETTE_SPRITE_BIT)
+            return spr_palette_tbl_get(addr & PALETTE_TBL_ADDR_MASK);
+        else 
+            return bg_palette_tbl_get(addr & PALETTE_TBL_ADDR_MASK);
+    }
+    else {
+        addr &= NAME_ATTR_MASK;
+        if (addr < ATTR0_START) {
+            return name_tbl_get(0, addr - NAME0_START);
+        }
+        else if (addr < NAME1_START) {
+            return attr_tbl_get(0, addr - ATTR0_START);
+        }
+        else if (addr < ATTR1_START) {
+            return name_tbl_get(1, addr - NAME1_START);
+        }
+        else if (addr < NAME2_START) {
+            return attr_tbl_get(1, addr - ATTR1_START);
+        }
+        else if (addr < ATTR2_START) {
+            return name_tbl_get(2, addr - NAME2_START);
+        }
+        else if (addr < NAME3_START) {
+            return attr_tbl_get(2, addr - ATTR2_START);
+        }
+        else if (addr < ATTR3_START) {
+            return name_tbl_get(3, addr - NAME3_START);
+        }
+        else {
+            return attr_tbl_get(3, addr - ATTR3_START);
+        }
+    }
+    return 0;
 }
 
 /* VRAM manipulation... */
 
+#ifdef PPU_TEST
+/*
+ * ppu test function
+ * */
+static void test_ppu(void) {
+    int i;
+    unsigned char plt[32] = {
+            0x0f, 0x00, 0x10, 0x20,
+            0x0f, 0x06, 0x16, 0x26,
+            0x0f, 0x08, 0x18, 0x28,
+            0x0f, 0x0a, 0x1a, 0x2a,
+
+            0x0f, 0x00, 0x10, 0x20,
+            0x0f, 0x06, 0x16, 0x26,
+            0x0f, 0x08, 0x18, 0x28,
+            0x0f, 0x0a, 0x1a, 0x2a,
+    };
+
+    //bg character base addr set to 0x1000.
+    ppu_ctrl1_set(0x00);
+
+/*
+*/
+    //palette tbl
+    for (i = 0; i < 16; i++)
+        vram_data_set(0x3f00 + i, plt[i]);
+    for (i = 0; i < 16; i++)
+        vram_data_set(0x3f10 + i, plt[i + 16]);
+
+    //name tbl
+    for (i = 0; i < 960; i++) 
+        vram_data_set(0x2000 + i, i %255);
+
+/*
+*/
+    //attr tbl
+    for (i = 0; i < 64; i++) 
+        vram_data_set(0x23c0 + i, i%16);
+
+    /*
+    vram_data_set(0x2000 + 205, 'D');
+    vram_data_set(0x2000 + 206, 'e');
+    vram_data_set(0x2000 + 207, 'e');
+    vram_data_set(0x2000 + 208, '!');
+    vram_data_set(0x2000 + 209, '!');
+    //205 = palette gp2 00011011b 
+    //205 = 11
+    vram_data_set(0x23c0 + 11, 0x1b);
+
+    //other test.
+    vram_data_set(0x2000 + 300, 1);
+    vram_data_set(0x2000 + 0, 0x65);
+*/
+
+    /*
+    set_monocolor(FALSE);
+     * */
+
+    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);
+     * */
+
+    //bg&sprite show
+    ppu_ctrl2_set(0x18);
+
+    /*
+    vga_xfer();
+*/
+
+//void dump_vram(int type, int bank, unsigned short addr, int size);
+/*
+    dump_vram(VRAM_DUMP_TYPE_PTN, 0, 0, 0x100);
+    dump_vram(VRAM_DUMP_TYPE_NAME, 0, 0, 300);
+    dump_vram(VRAM_DUMP_TYPE_ATTR, 0, 0, 64);
+    dump_vram(VRAM_DUMP_TYPE_PLT, 0, 0, 16);
+*/
+}
+#endif /* PPU_TEST */
+
+static int attr_index_to_gp(int tile_index) {
+    int tile_x, tile_y, gp_x, gp_y;
+
+    tile_x = tile_index % H_SCREEN_TILE_SIZE;
+    tile_y = tile_index / H_SCREEN_TILE_SIZE;
+
+    gp_x = tile_x / ATTR_GROUP_UNIT;
+    gp_y = tile_y / ATTR_GROUP_UNIT;
+    //dprint("tile_x:%d, y:%d, gp_x:%d, y:%d\n", tile_x, tile_y, gp_x, gp_y);
+
+    return gp_x + gp_y * 8;
+}
+
 void load_attribute(unsigned char bank, int tile_index, struct palette *plt) {
     int gp_index;
-    int unit_index;
     unsigned char data;
     struct palette_unit pu;
     int palette_group;
     unsigned short palette_addr;
     unsigned char pi;
+    int tile_x, tile_y;
+    int in_x, in_y;
 
-    gp_index = tile_index / ATTR_GROUP_UNIT / ATTR_UNIT_PER_BYTE;
-    unit_index = tile_index / ATTR_GROUP_UNIT;
+    gp_index = attr_index_to_gp(tile_index);
     data = attr_tbl_get(bank, gp_index);
-    pu = *(struct palette_unit*)&data;
-
-    switch(unit_index) {
-        case 0:
+    memcpy(&pu, &data, sizeof(pu));
+
+    tile_x = tile_index % H_SCREEN_TILE_SIZE;
+    tile_y = tile_index / H_SCREEN_TILE_SIZE;
+    in_x = tile_x % (ATTR_GROUP_UNIT);
+    in_y = tile_y % (ATTR_GROUP_UNIT);
+    if (in_y < 2) {
+        if (in_x < 2) {
             palette_group = pu.bit01;
-            break;
-        case 1:
+        }
+        else {
             palette_group = pu.bit23;
-            break;
-        case 2:
+        }
+    }
+    else {
+        if (in_x < 2) {
             palette_group = pu.bit45;
-            break;
-        default:
+        }
+        else {
             palette_group = pu.bit67;
-            break;
+        }
     }
+    /*
+    dprint("tile_index: %d, gp_index: %d\n", tile_index, gp_index);
+    dprint("in_x: %d, in_y: %d\n", in_x, in_y);
+    dprint("pu bit01:%d, bit23:%d, bit45:%d, bit67:%d\n", pu.bit01, pu.bit23, pu.bit45, pu.bit67);
+    dprint("palette_gp: %d\n", palette_group);
+    */
 
     /*load bg rgb palette color*/
     palette_addr = palette_group * 4;
-    pi = img_palette_tbl_get(palette_addr++);
-    palette_index_to_rgb15(0, pi, &plt->col[0]);
-    pi = img_palette_tbl_get(palette_addr++);
-    palette_index_to_rgb15(0, pi, &plt->col[1]);
-    pi = img_palette_tbl_get(palette_addr++);
-    palette_index_to_rgb15(0, pi, &plt->col[2]);
-    pi = img_palette_tbl_get(palette_addr);
-    palette_index_to_rgb15(0, pi, &plt->col[3]);
+    pi = bg_palette_tbl_get(palette_addr++);
+    palette_index_to_rgb15(pi, &plt->col[0]);
+    /*
+    dprint("palette 0: index:%02d, %02x %02x %02x\n", pi, 
+            colto8bit(plt->col[0].r), colto8bit(plt->col[0].g), colto8bit(plt->col[0].b));
+            */
+
+    pi = bg_palette_tbl_get(palette_addr++);
+    palette_index_to_rgb15(pi, &plt->col[1]);
+    /*
+    dprint("palette 1: index:%02d, %02x %02x %02x\n", pi, 
+            colto8bit(plt->col[1].r), colto8bit(plt->col[1].g), colto8bit(plt->col[1].b));
+            */
+
+    pi = bg_palette_tbl_get(palette_addr++);
+    palette_index_to_rgb15(pi, &plt->col[2]);
+    /*
+    dprint("palette 2: index:%02d, %02x %02x %02x\n", pi, 
+            colto8bit(plt->col[2].r), colto8bit(plt->col[2].g), colto8bit(plt->col[2].b));
+            */
+
+    pi = bg_palette_tbl_get(palette_addr);
+    palette_index_to_rgb15(pi, &plt->col[3]);
+    /*
+    dprint("palette 3: index:%02d, %02x %02x %02x\n", pi, 
+            colto8bit(plt->col[3].r), colto8bit(plt->col[3].g), colto8bit(plt->col[3].b));
+            */
 
 }
 
+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;
 
@@ -191,13 +429,12 @@ 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++;
     }
 }
 
-
 int load_chr_rom(FILE* cartridge, int num_rom_bank) {
     int len;
 
@@ -213,12 +450,6 @@ int load_chr_rom(FILE* cartridge, int num_rom_bank) {
 }
 
 int vram_init(void) {
-    name_tbl2 = NULL;
-    name_tbl3 = NULL;
-
-    attr_tbl2 = NULL;
-    attr_tbl3 = NULL;
-    
 
     pattern_tbl0 = malloc(PATTERN_TBL_SIZE);
     if (pattern_tbl0 == NULL)
@@ -228,10 +459,6 @@ int vram_init(void) {
     if (pattern_tbl1 == NULL)
         return FALSE;
 
-    sprite_ram = malloc(SPRITE_RAM_SIZE);
-    if (sprite_ram == NULL)
-        return FALSE;
-
     name_tbl0 = malloc(NAME_TBL_SIZE);
     if (name_tbl0 == NULL)
         return FALSE;
@@ -248,14 +475,31 @@ int vram_init(void) {
     if (attr_tbl1 == NULL)
         return FALSE;
 
-    img_palette_tbl = malloc(PALETTE_TBL_SIZE);
-    if (img_palette_tbl == NULL)
+    name_tbl2 = name_tbl0;
+    name_tbl3 = name_tbl1;
+
+    attr_tbl2 = attr_tbl0;
+    attr_tbl3 = attr_tbl1;
+    
+    bg_palette_tbl = malloc(PALETTE_TBL_SIZE);
+    if (bg_palette_tbl == NULL)
         return FALSE;
 
     spr_palette_tbl = malloc(PALETTE_TBL_SIZE);
     if (spr_palette_tbl == NULL)
         return FALSE;
 
+    memset(pattern_tbl0, 0, PATTERN_TBL_SIZE);
+    memset(pattern_tbl1, 0, PATTERN_TBL_SIZE);
+    memset(name_tbl0, 0, NAME_TBL_SIZE);
+    memset(name_tbl1, 0, NAME_TBL_SIZE);
+    memset(attr_tbl0, 0, ATTR_TBL_SIZE);
+    memset(attr_tbl1, 0, ATTR_TBL_SIZE);
+    memset(bg_palette_tbl, 0, PALETTE_TBL_SIZE);
+    memset(spr_palette_tbl, 0, PALETTE_TBL_SIZE);
+
+    d4_set(debug_mode);
+
     return TRUE;
 }
 
@@ -264,17 +508,28 @@ void clean_vram(void) {
     free(pattern_tbl0);
     free(pattern_tbl1);
 
-    free(sprite_ram);
-
     free(name_tbl0);
     free(name_tbl1);
 
     free(attr_tbl0);
     free(attr_tbl1);
 
-    free(img_palette_tbl);
+    free(bg_palette_tbl);
     free(spr_palette_tbl);
 
 }
 
+static void null_write (unsigned short addr, unsigned char data) {}
+static void dump_vram_write (unsigned short addr, unsigned char data) {
+    dprint("                                  ");
+    dprint("vram_data_set addr:%04x, data:%2x\n", addr, data);
+}
 
+void d4_set(int on_off) {
+    if (on_off) {
+        vram_log_level4 = dump_vram_write;
+    }
+    else {
+        vram_log_level4 = null_write;
+    }
+}