From 4c7a70b2192e75931a10e570f48bafcffd1f5c13 Mon Sep 17 00:00:00 2001 From: astoria-d Date: Wed, 13 Mar 2013 12:20:46 +0900 Subject: [PATCH] sprite xfer ok --- emulator/cpu.c | 2 + emulator/ppucore/dummy-driver2.c | 22 ++++++- emulator/ppucore/sprite.h | 18 ++++++ emulator/ppucore/vram.c | 24 ++++++- emulator/ppucore/vram.h | 6 ++ emulator/ppucore/vscreen.c | 135 +++++++++++++++++++++++++++------------ 6 files changed, 159 insertions(+), 48 deletions(-) create mode 100644 emulator/ppucore/sprite.h diff --git a/emulator/cpu.c b/emulator/cpu.c index ad4dea9..80a0035 100644 --- a/emulator/cpu.c +++ b/emulator/cpu.c @@ -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 diff --git a/emulator/ppucore/dummy-driver2.c b/emulator/ppucore/dummy-driver2.c index 21540ed..9148f77 100644 --- a/emulator/ppucore/dummy-driver2.c +++ b/emulator/ppucore/dummy-driver2.c @@ -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 index 0000000..1cbad24 --- /dev/null +++ b/emulator/ppucore/sprite.h @@ -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__*/ + diff --git a/emulator/ppucore/vram.c b/emulator/ppucore/vram.c index 922f43d..e06e456 100644 --- a/emulator/ppucore/vram.c +++ b/emulator/ppucore/vram.c @@ -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++; } diff --git a/emulator/ppucore/vram.h b/emulator/ppucore/vram.h index ec43b46..5f5e02f 100644 --- a/emulator/ppucore/vram.h +++ b/emulator/ppucore/vram.h @@ -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; diff --git a/emulator/ppucore/vscreen.c b/emulator/ppucore/vscreen.c index f67c910..36e5f0e 100644 --- a/emulator/ppucore/vscreen.c +++ b/emulator/ppucore/vscreen.c @@ -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) { -- 2.11.0