12 void palette_index_to_rgb15(unsigned char index, struct rgb15* rgb);
13 void dump_mem(const char* msg, unsigned short base,
14 unsigned short offset, unsigned char* buf, int size);
15 void set_bgtile(int tile_id);
19 static unsigned char * bg_palette_tbl;
20 static unsigned char * spr_palette_tbl;
22 static unsigned char * name_tbl0;
23 static unsigned char * name_tbl1;
24 static unsigned char * name_tbl2;
25 static unsigned char * name_tbl3;
27 static unsigned char * attr_tbl0;
28 static unsigned char * attr_tbl1;
29 static unsigned char * attr_tbl2;
30 static unsigned char * attr_tbl3;
32 static unsigned char * pattern_tbl0;
33 static unsigned char * pattern_tbl1;
37 static int first_time = TRUE;
40 extern int debug_mode;
41 static void (*vram_log_level4)(unsigned short, unsigned char);
42 static void dump_vram_write (unsigned short addr, unsigned char data);
43 void d4_set(int on_off);
46 * VRAM get/set functions....
50 static unsigned char pattern_tbl_get(unsigned char bank, unsigned short offset) {
52 return pattern_tbl0[offset];
54 return pattern_tbl1[offset];
57 static unsigned char name_tbl_get(unsigned char bank, unsigned short offset) {
59 return name_tbl0[offset];
61 return name_tbl1[offset];
63 return name_tbl2[offset];
65 return name_tbl3[offset];
68 static void name_tbl_set(unsigned char bank, unsigned short offset, unsigned char data) {
70 name_tbl0[offset] = data;
72 name_tbl1[offset] = data;
74 name_tbl2[offset] = data;
76 name_tbl3[offset] = data;
80 static unsigned char attr_tbl_get(unsigned char bank, unsigned short offset) {
82 return attr_tbl0[offset];
84 return attr_tbl1[offset];
86 return attr_tbl2[offset];
88 return attr_tbl3[offset];
91 static void attr_tbl_set(unsigned char bank, unsigned short offset, unsigned char data) {
93 attr_tbl0[offset] = data;
95 attr_tbl1[offset] = data;
97 attr_tbl2[offset] = data;
99 attr_tbl3[offset] = data;
103 static unsigned char spr_palette_tbl_get(unsigned short offset) {
104 return spr_palette_tbl[offset];
107 static void spr_palette_tbl_set(unsigned short offset, unsigned char data) {
108 spr_palette_tbl[offset] = data;
111 static unsigned char bg_palette_tbl_get(unsigned short offset) {
112 return bg_palette_tbl[offset];
115 static void bg_palette_tbl_set(unsigned short offset, unsigned char data) {
116 bg_palette_tbl[offset] = data;
119 void vram_data_set(unsigned short addr, unsigned char data) {
123 #endif /* PPU_TEST */
125 vram_log_level4 (addr, data);
127 //mirror 0x4000 up addr.
128 addr &= PPU_ADDR_MASK;
130 if (addr < 2 * PATTERN_TBL_SIZE) {
131 //dprint("invalid vram write addr:%04x, data:%2x\n", addr, data);
132 //do nothing. pattern table is read only.
133 extern int critical_error;
134 dprint("invalid vram write!!!!\n");
135 critical_error = TRUE;
137 else if (addr >= PALETTE_START) {
138 // bg/sprite palette table.
139 if (addr & PALETTE_SPRITE_BIT)
140 spr_palette_tbl_set(addr & PALETTE_TBL_ADDR_MASK, data);
142 bg_palette_tbl_set(addr & PALETTE_TBL_ADDR_MASK, data);
146 // mask 0x3000 up addr.
147 addr &= NAME_ATTR_MASK;
148 if (addr < ATTR0_START) {
149 name_tbl_set(0, addr - NAME0_START, data);
151 else if (addr < NAME1_START) {
152 attr_tbl_set(0, addr - ATTR0_START, data);
154 else if (addr < ATTR1_START) {
155 name_tbl_set(1, addr - NAME1_START, data);
157 else if (addr < NAME2_START) {
158 attr_tbl_set(1, addr - ATTR1_START, data);
160 else if (addr < ATTR2_START) {
161 name_tbl_set(2, addr - NAME2_START, data);
163 else if (addr < NAME3_START) {
164 attr_tbl_set(2, addr - ATTR2_START, data);
166 else if (addr < ATTR3_START) {
167 name_tbl_set(3, addr - NAME3_START, data);
170 attr_tbl_set(3, addr - ATTR3_START, data);
175 unsigned char vram_data_get(unsigned short addr) {
177 addr &= PPU_ADDR_MASK;
179 if (addr < PATTERN_TBL_SIZE) {
180 return pattern_tbl_get(0, addr & PATTERN_ADDR_MASK);
182 if (addr < 2 * PATTERN_TBL_SIZE) {
183 return pattern_tbl_get(1, addr & PATTERN_ADDR_MASK);
185 else if (addr >= PALETTE_START) {
186 if (addr & PALETTE_SPRITE_BIT)
187 return spr_palette_tbl_get(addr & PALETTE_TBL_ADDR_MASK);
189 return bg_palette_tbl_get(addr & PALETTE_TBL_ADDR_MASK);
192 addr &= NAME_ATTR_MASK;
193 if (addr < ATTR0_START) {
194 return name_tbl_get(0, addr - NAME0_START);
196 else if (addr < NAME1_START) {
197 return attr_tbl_get(0, addr - ATTR0_START);
199 else if (addr < ATTR1_START) {
200 return name_tbl_get(1, addr - NAME1_START);
202 else if (addr < NAME2_START) {
203 return attr_tbl_get(1, addr - ATTR1_START);
205 else if (addr < ATTR2_START) {
206 return name_tbl_get(2, addr - NAME2_START);
208 else if (addr < NAME3_START) {
209 return attr_tbl_get(2, addr - ATTR2_START);
211 else if (addr < ATTR3_START) {
212 return name_tbl_get(3, addr - NAME3_START);
215 return attr_tbl_get(3, addr - ATTR3_START);
221 /* VRAM manipulation... */
227 static void test_ppu(void) {
229 unsigned char plt[32] = {
230 0x0f, 0x00, 0x10, 0x20,
231 0x0f, 0x06, 0x16, 0x26,
232 0x0f, 0x08, 0x18, 0x28,
233 0x0f, 0x0a, 0x1a, 0x2a,
235 0x0f, 0x00, 0x10, 0x20,
236 0x0f, 0x06, 0x16, 0x26,
237 0x0f, 0x08, 0x18, 0x28,
238 0x0f, 0x0a, 0x1a, 0x2a,
241 //bg character base addr set to 0x1000.
247 for (i = 0; i < 16; i++)
248 vram_data_set(0x3f00 + i, plt[i]);
249 for (i = 0; i < 16; i++)
250 vram_data_set(0x3f10 + i, plt[i + 16]);
253 for (i = 0; i < 960; i++)
254 vram_data_set(0x2000 + i, i %255);
259 for (i = 0; i < 64; i++)
260 vram_data_set(0x23c0 + i, i%16);
263 vram_data_set(0x2000 + 205, 'D');
264 vram_data_set(0x2000 + 206, 'e');
265 vram_data_set(0x2000 + 207, 'e');
266 vram_data_set(0x2000 + 208, '!');
267 vram_data_set(0x2000 + 209, '!');
268 //205 = palette gp2 00011011b
270 vram_data_set(0x23c0 + 11, 0x1b);
273 vram_data_set(0x2000 + 300, 1);
274 vram_data_set(0x2000 + 0, 0x65);
278 set_monocolor(FALSE);
281 for (i = 0; i < 960; i++)
286 struct sprite_attr sa;
291 set_sprite(30, 100, 'd', sa);
293 set_sprite(50, 100, 'd', sa);
295 set_sprite(70, 105, 'd', sa);
305 //void dump_vram(int type, int bank, unsigned short addr, int size);
307 dump_vram(VRAM_DUMP_TYPE_PTN, 0, 0, 0x100);
308 dump_vram(VRAM_DUMP_TYPE_NAME, 0, 0, 300);
309 dump_vram(VRAM_DUMP_TYPE_ATTR, 0, 0, 64);
310 dump_vram(VRAM_DUMP_TYPE_PLT, 0, 0, 16);
313 #endif /* PPU_TEST */
315 static int attr_index_to_gp(int tile_index) {
316 int tile_x, tile_y, gp_x, gp_y;
318 tile_x = tile_index % H_SCREEN_TILE_SIZE;
319 tile_y = tile_index / H_SCREEN_TILE_SIZE;
321 gp_x = tile_x / ATTR_GROUP_UNIT;
322 gp_y = tile_y / ATTR_GROUP_UNIT;
323 //dprint("tile_x:%d, y:%d, gp_x:%d, y:%d\n", tile_x, tile_y, gp_x, gp_y);
325 return gp_x + gp_y * 8;
328 void load_attribute(unsigned char bank, int tile_index, struct palette *plt) {
331 struct palette_unit pu;
333 unsigned short palette_addr;
338 gp_index = attr_index_to_gp(tile_index);
339 data = attr_tbl_get(bank, gp_index);
340 memcpy(&pu, &data, sizeof(pu));
342 tile_x = tile_index % H_SCREEN_TILE_SIZE;
343 tile_y = tile_index / H_SCREEN_TILE_SIZE;
344 in_x = tile_x % (ATTR_GROUP_UNIT);
345 in_y = tile_y % (ATTR_GROUP_UNIT);
348 palette_group = pu.bit01;
351 palette_group = pu.bit23;
356 palette_group = pu.bit45;
359 palette_group = pu.bit67;
363 dprint("tile_index: %d, gp_index: %d\n", tile_index, gp_index);
364 dprint("in_x: %d, in_y: %d\n", in_x, in_y);
365 dprint("pu bit01:%d, bit23:%d, bit45:%d, bit67:%d\n", pu.bit01, pu.bit23, pu.bit45, pu.bit67);
366 dprint("palette_gp: %d\n", palette_group);
369 /*load bg rgb palette color*/
370 palette_addr = palette_group * 4;
371 pi = bg_palette_tbl_get(palette_addr++);
372 palette_index_to_rgb15(pi, &plt->col[0]);
374 dprint("palette 0: index:%02d, %02x %02x %02x\n", pi,
375 colto8bit(plt->col[0].r), colto8bit(plt->col[0].g), colto8bit(plt->col[0].b));
378 pi = bg_palette_tbl_get(palette_addr++);
379 palette_index_to_rgb15(pi, &plt->col[1]);
381 dprint("palette 1: index:%02d, %02x %02x %02x\n", pi,
382 colto8bit(plt->col[1].r), colto8bit(plt->col[1].g), colto8bit(plt->col[1].b));
385 pi = bg_palette_tbl_get(palette_addr++);
386 palette_index_to_rgb15(pi, &plt->col[2]);
388 dprint("palette 2: index:%02d, %02x %02x %02x\n", pi,
389 colto8bit(plt->col[2].r), colto8bit(plt->col[2].g), colto8bit(plt->col[2].b));
392 pi = bg_palette_tbl_get(palette_addr);
393 palette_index_to_rgb15(pi, &plt->col[3]);
395 dprint("palette 3: index:%02d, %02x %02x %02x\n", pi,
396 colto8bit(plt->col[3].r), colto8bit(plt->col[3].g), colto8bit(plt->col[3].b));
401 void load_spr_attribute(struct sprite_attr sa, struct palette *plt) {
402 unsigned short palette_addr;
405 /*load bg rgb palette color*/
406 palette_addr = sa.palette * 4;
407 pi = bg_palette_tbl_get(palette_addr++);
408 palette_index_to_rgb15(pi, &plt->col[0]);
410 pi = bg_palette_tbl_get(palette_addr++);
411 palette_index_to_rgb15(pi, &plt->col[1]);
413 pi = bg_palette_tbl_get(palette_addr++);
414 palette_index_to_rgb15(pi, &plt->col[2]);
416 pi = bg_palette_tbl_get(palette_addr);
417 palette_index_to_rgb15(pi, &plt->col[3]);
421 * pattern index: 0 - 255
423 void load_pattern(unsigned char bank, unsigned char ptn_index, struct tile_2* pattern) {
428 //load character pattern
429 p = (unsigned char*)pattern;
430 addr = ptn_index * sizeof(struct tile_2);
431 for (i = 0; i < sizeof(struct tile_2); i++) {
432 *p = pattern_tbl_get(bank, addr);
438 int load_chr_rom(FILE* cartridge, int num_rom_bank) {
441 len = fread(pattern_tbl0, 1, PATTERN_TBL_SIZE, cartridge);
442 if (len != PATTERN_TBL_SIZE)
445 len = fread(pattern_tbl1, 1, PATTERN_TBL_SIZE, cartridge);
446 if (len != PATTERN_TBL_SIZE)
452 int vram_init(void) {
454 pattern_tbl0 = malloc(PATTERN_TBL_SIZE);
455 if (pattern_tbl0 == NULL)
458 pattern_tbl1 = malloc(PATTERN_TBL_SIZE);
459 if (pattern_tbl1 == NULL)
462 name_tbl0 = malloc(NAME_TBL_SIZE);
463 if (name_tbl0 == NULL)
466 name_tbl1 = malloc(NAME_TBL_SIZE);
467 if (name_tbl1 == NULL)
470 attr_tbl0 = malloc(ATTR_TBL_SIZE);
471 if (attr_tbl0 == NULL)
474 attr_tbl1 = malloc(ATTR_TBL_SIZE);
475 if (attr_tbl1 == NULL)
478 name_tbl2 = name_tbl0;
479 name_tbl3 = name_tbl1;
481 attr_tbl2 = attr_tbl0;
482 attr_tbl3 = attr_tbl1;
484 bg_palette_tbl = malloc(PALETTE_TBL_SIZE);
485 if (bg_palette_tbl == NULL)
488 spr_palette_tbl = malloc(PALETTE_TBL_SIZE);
489 if (spr_palette_tbl == NULL)
492 memset(pattern_tbl0, 0, PATTERN_TBL_SIZE);
493 memset(pattern_tbl1, 0, PATTERN_TBL_SIZE);
494 memset(name_tbl0, 0, NAME_TBL_SIZE);
495 memset(name_tbl1, 0, NAME_TBL_SIZE);
496 memset(attr_tbl0, 0, ATTR_TBL_SIZE);
497 memset(attr_tbl1, 0, ATTR_TBL_SIZE);
498 memset(bg_palette_tbl, 0, PALETTE_TBL_SIZE);
499 memset(spr_palette_tbl, 0, PALETTE_TBL_SIZE);
501 //d4_set(debug_mode);
507 void clean_vram(void) {
518 free(bg_palette_tbl);
519 free(spr_palette_tbl);
523 static void null_write (unsigned short addr, unsigned char data) {}
524 static void dump_vram_write (unsigned short addr, unsigned char data) {
526 dprint("vram_data_set addr:%04x, data:%2x\n", addr, data);
529 void d4_set(int on_off) {
531 vram_log_level4 = dump_vram_write;
534 vram_log_level4 = null_write;