2 Nintendo Family BASIC Emulator 'eFamilyBASIC'
5 Author : Takeda.Toshiya
13 #include "../datarec.h"
14 #include "../ym2413.h"
16 namespace FAMILYBASIC {
18 #define EVENT_DMA_DONE 0
20 void MEMORY::initialize()
22 key_stat = emu->get_key_buffer();
23 joy_stat = emu->get_joy_buffer();
26 register_vline_event(this);
29 void MEMORY::load_rom_image(const _TCHAR *file_name)
31 FILEIO* fio = new FILEIO();
33 memset(save_ram, 0, sizeof(save_ram));
35 if(fio->Fopen(create_local_path(file_name), FILEIO_READ_BINARY)) {
36 // create save file name
37 _TCHAR tmp_file_name[_MAX_PATH];
38 my_tcscpy_s(tmp_file_name, _MAX_PATH, file_name);
39 _TCHAR *dot = _tcsstr(tmp_file_name, _T("."));
40 if(dot != NULL) dot[0] = _T('\0');
41 my_stprintf_s(save_file_name, _MAX_PATH, _T("%s.SAV"), tmp_file_name);
44 fio->Fopen(create_local_path(_T("BASIC.NES")), FILEIO_READ_BINARY);
45 my_tcscpy_s(save_file_name, _MAX_PATH, _T("BACKUP.BIN"));
49 fio->Fread(&header, sizeof(header), 1);
51 rom_size = 0x2000 * header.num_8k_rom_banks();
52 for(uint32_t bit = 0x80000; bit != 0; bit >>= 1) {
54 if(rom_size & (bit - 1)) {
55 rom_size = (rom_size | (bit - 1)) + 1;
60 rom = (uint8_t *)calloc(rom_size, 1);
61 fio->Fread(rom, 0x2000 * header.num_8k_rom_banks(), 1);
64 memset(&header, 0, sizeof(header));
65 header.dummy = 2; // 32KB
66 rom_size = 0x2000 * header.num_8k_rom_banks();
67 rom = (uint8_t *)calloc(rom_size, 1);
68 memset(rom, 0xff, 0x2000 * header.num_8k_rom_banks());
70 if(fio->Fopen(create_local_path(save_file_name), FILEIO_READ_BINARY)) {
71 fio->Fread(save_ram, sizeof(save_ram), 1);
76 rom_mask = (rom_size / 0x2000) - 1;
77 save_ram_crc32 = get_crc32(save_ram, sizeof(save_ram));
80 void MEMORY::save_backup()
82 if(save_ram_crc32 != get_crc32(save_ram, sizeof(save_ram))) {
83 FILEIO* fio = new FILEIO();
84 if(fio->Fopen(create_local_path(save_file_name), FILEIO_WRITE_BINARY)) {
85 fio->Fwrite(save_ram, sizeof(save_ram), 1);
92 void MEMORY::release()
103 memset(ram, 0, sizeof(ram));
105 for(int i = 4; i < 8; i++) {
108 bank_ptr[3] = save_ram;
111 frame_irq_enabled = 0xff;
114 pad1_bits = pad2_bits = 0xff;
123 void MEMORY::write_data8(uint32_t addr, uint32_t data)
128 ram[addr & 0x7ff] = data;
129 } else if(addr < 0x4000) {
130 d_ppu->write_data8(addr, data);
131 } else if(addr == 0x4014) {
133 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
134 register_event_by_clock(this, EVENT_DMA_DONE, 514, false, NULL);
136 dma_addr = data << 8;
137 for(int i = 0; i < 256; i++) {
138 spr_ram[i] = read_data8(dma_addr | i);
140 } else if(addr == 0x4016) {
143 } else if(pad_strobe) {
147 if(joy_stat[0] & 0x10) pad1_bits |= 0x01; // A
148 if(joy_stat[0] & 0x20) pad1_bits |= 0x02; // B
149 if(joy_stat[0] & 0x40) pad1_bits |= 0x04; // SEL
150 if(joy_stat[0] & 0x80) pad1_bits |= 0x08; // START
151 if(joy_stat[0] & 0x01) pad1_bits |= 0x10; // UP
152 if(joy_stat[0] & 0x02) pad1_bits |= 0x20; // DOWN
153 if(joy_stat[0] & 0x04) pad1_bits |= 0x40; // LEFT
154 if(joy_stat[0] & 0x08) pad1_bits |= 0x80; // RIGHT
157 if(joy_stat[1] & 0x10) pad2_bits |= 0x01; // A
158 if(joy_stat[1] & 0x20) pad2_bits |= 0x02; // B
159 if(joy_stat[1] & 0x01) pad2_bits |= 0x10; // UP
160 if(joy_stat[1] & 0x02) pad2_bits |= 0x20; // DOWN
161 if(joy_stat[1] & 0x04) pad2_bits |= 0x40; // LEFT
162 if(joy_stat[1] & 0x08) pad2_bits |= 0x80; // RIGHT
165 if((data & 0x07) == 0x04) {
170 } else if((data & 0x07) == 0x05) {
173 } else if((data & 0x07) == 0x06) {
176 // data recorder (thanks MESS)
177 if((data & 0x07) == 0x07) {
178 d_drec->write_signal(SIG_DATAREC_MIC, 1, 1);
180 d_drec->write_signal(SIG_DATAREC_MIC, 0, 0);
182 } else if(addr < 0x4018) {
184 frame_irq_enabled = data;
186 d_apu->write_data8(addr, data);
187 } else if(addr < 0x6000) {
188 if(header.mapper() == 5) {
189 mmc5_lo_write(addr, data);
190 // } else if(header.mapper() == 85) {
191 // vrc7_lo_write(addr, data);
193 } else if(addr < 0x8000) {
194 if(header.mapper() == 5) {
195 mmc5_save_write(addr, data);
196 // } else if(header.mapper() == 85) {
197 // vrc7_save_write(addr, data);
199 bank_ptr[3][addr & 0x1fff] = data;
202 if(header.mapper() == 5) {
203 mmc5_hi_write(addr, data);
204 } else if(header.mapper() == 85) {
205 vrc7_hi_write(addr, data);
210 uint32_t MEMORY::read_data8(uint32_t addr)
215 return ram[addr & 0x7ff];
216 } else if(addr < 0x4000) {
217 return d_ppu->read_data8(addr);
218 } else if(addr == 0x4014) {
219 return dma_addr >> 8;
220 } else if(addr < 0x4016) {
221 uint32_t val = d_apu->read_data8(addr);
222 if(addr == 0x4015 && !(frame_irq_enabled & 0xc0)) {
226 } else if(addr == 0x4016) {
228 uint32_t val = pad1_bits & 1;
231 val |= d_drec->read_signal(0) ? 2 : 0;
233 val |= key_stat[0x7b] ? 4 : 0; // F12
235 } else if(addr == 0x4017) {
237 uint32_t val = 0xfe | (pad2_bits & 1);
243 if(key_stat[0x77]) val &= ~0x02; // F8
244 if(key_stat[0x0d]) val &= ~0x04; // RETURN
245 if(key_stat[0xdb]) val &= ~0x08; // [
246 if(key_stat[0xdd]) val &= ~0x10; // ]
249 if(key_stat[0x76]) val &= ~0x02; // F7
250 if(key_stat[0xc0]) val &= ~0x04; // @
251 if(key_stat[0xba]) val &= ~0x08; // :
252 if(key_stat[0xbb]) val &= ~0x10; // ;
255 if(key_stat[0x75]) val &= ~0x02; // F6
256 if(key_stat[0x4f]) val &= ~0x04; // O
257 if(key_stat[0x4c]) val &= ~0x08; // L
258 if(key_stat[0x4b]) val &= ~0x10; // K
261 if(key_stat[0x74]) val &= ~0x02; // F5
262 if(key_stat[0x49]) val &= ~0x04; // I
263 if(key_stat[0x55]) val &= ~0x08; // U
264 if(key_stat[0x4a]) val &= ~0x10; // J
267 if(key_stat[0x73]) val &= ~0x02; // F4
268 if(key_stat[0x59]) val &= ~0x04; // Y
269 if(key_stat[0x47]) val &= ~0x08; // G
270 if(key_stat[0x48]) val &= ~0x10; // H
273 if(key_stat[0x72]) val &= ~0x02; // F3
274 if(key_stat[0x54]) val &= ~0x04; // T
275 if(key_stat[0x52]) val &= ~0x08; // R
276 if(key_stat[0x44]) val &= ~0x10; // D
279 if(key_stat[0x71]) val &= ~0x02; // F2
280 if(key_stat[0x57]) val &= ~0x04; // W
281 if(key_stat[0x53]) val &= ~0x08; // S
282 if(key_stat[0x41]) val &= ~0x10; // A
285 if(key_stat[0x70]) val &= ~0x02; // F1
286 if(key_stat[0x1b]) val &= ~0x04; // ESC
287 if(key_stat[0x51]) val &= ~0x08; // Q
288 if(key_stat[0x11]) val &= ~0x10; // CTRL
291 if(key_stat[0x24]) val &= ~0x02; // CLS
292 if(key_stat[0x26]) val &= ~0x04; // UP
293 if(key_stat[0x27]) val &= ~0x08; // RIGHT
294 if(key_stat[0x25]) val &= ~0x10; // LEFT
300 if(key_stat[0x15]) val &= ~0x02; // KANA
301 // if(key_stat[0x10]) val &= ~0x04; // RSHIFT
302 if(key_stat[0xdc]) val &= ~0x08; // '\\'
303 if(key_stat[0x23]) val &= ~0x10; // STOP
306 if(key_stat[0xe2]) val &= ~0x02; // _
307 if(key_stat[0xbf]) val &= ~0x04; // /
308 if(key_stat[0xbd]) val &= ~0x08; // -
309 if(key_stat[0xde]) val &= ~0x10; // ^
312 if(key_stat[0xbe]) val &= ~0x02; // .
313 if(key_stat[0xbc]) val &= ~0x04; // ,
314 if(key_stat[0x50]) val &= ~0x08; // P
315 if(key_stat[0x30]) val &= ~0x10; // 0
318 if(key_stat[0x4d]) val &= ~0x02; // M
319 if(key_stat[0x4e]) val &= ~0x04; // N
320 if(key_stat[0x39]) val &= ~0x08; // 9
321 if(key_stat[0x38]) val &= ~0x10; // 8
324 if(key_stat[0x42]) val &= ~0x02; // B
325 if(key_stat[0x56]) val &= ~0x04; // V
326 if(key_stat[0x37]) val &= ~0x08; // 7
327 if(key_stat[0x36]) val &= ~0x10; // 6
330 if(key_stat[0x46]) val &= ~0x02; // F
331 if(key_stat[0x43]) val &= ~0x04; // C
332 if(key_stat[0x35]) val &= ~0x08; // 5
333 if(key_stat[0x34]) val &= ~0x10; // 4
336 if(key_stat[0x58]) val &= ~0x02; // X
337 if(key_stat[0x5a]) val &= ~0x04; // Z
338 if(key_stat[0x45]) val &= ~0x08; // E
339 if(key_stat[0x33]) val &= ~0x10; // 3
342 if(key_stat[0x10]) val &= ~0x02; // LSHIFT
343 if(key_stat[0x12]) val &= ~0x04; // GRAPH
344 if(key_stat[0x31]) val &= ~0x08; // 1
345 if(key_stat[0x32]) val &= ~0x10; // 2
348 if(key_stat[0x28]) val &= ~0x02; // DOWN
349 if(key_stat[0x20]) val &= ~0x04; // SPACE
350 if(key_stat[0x2e]) val &= ~0x08; // DEL
351 if(key_stat[0x2d]) val &= ~0x10; // INS
356 } else if(addr < 0x6000) {
357 if(header.mapper() == 5) {
358 return mmc5_lo_read(addr);
359 // } else if(header.mapper() == 85) {
360 // return vrc7_lo_read(addr);
364 } else if(addr < 0x8000) {
365 // if(header.mapper() == 5) {
366 // return mmc5_save_read(addr);
367 // } else if(header.mapper() == 85) {
368 // return vrc7_save_read(addr);
370 return bank_ptr[3][addr & 0x1fff];
372 } else if(addr < 0xa000) {
373 return bank_ptr[4][addr & 0x1fff];
374 } else if(addr < 0xc000) {
375 return bank_ptr[5][addr & 0x1fff];
376 } else if(addr < 0xe000) {
377 return bank_ptr[6][addr & 0x1fff];
379 return bank_ptr[7][addr & 0x1fff];
383 void MEMORY::event_vline(int v, int clock)
392 if(v == 240 && !(frame_irq_enabled & 0xc0)) {
394 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
398 if(header.mapper() == 5) {
400 } else if(header.mapper() == 85) {
405 void MEMORY::event_callback(int event_id, int err)
408 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
411 void MEMORY::set_rom_bank(uint8_t bank, uint32_t bank_num)
413 bank_ptr[bank] = rom + 0x2000 * (bank_num & rom_mask);
414 banks[bank] = bank_num;
417 mmc5_wram_bank[bank] = 8;
422 void MEMORY::mmc5_reset()
424 if(header.mapper() == 5) {
425 mmc5_set_wram_bank(3, 0);
426 set_rom_bank(4, header.num_8k_rom_banks() - 1);
427 set_rom_bank(5, header.num_8k_rom_banks() - 1);
428 set_rom_bank(6, header.num_8k_rom_banks() - 1);
429 set_rom_bank(7, header.num_8k_rom_banks() - 1);
431 for(int i = 0; i < 8; i++) {
432 mmc5_chr_reg[i][0] = i;
433 mmc5_chr_reg[i][1] = (i & 0x03) + 4;
435 mmc5_wram_protect0 = 0x02;
436 mmc5_wram_protect1 = 0x01;
440 // mmc5_split_control = 0;
441 // mmc5_split_bank = 0;
442 mmc5_irq_enabled = 0;
448 uint32_t MEMORY::mmc5_lo_read(uint32_t addr)
450 uint8_t data = (uint8_t)(addr >> 8);
453 data = mmc5_irq_status;
454 mmc5_irq_status &= ~0x80;
455 } else if(addr == 0x5205) {
456 data = (uint8_t)(((mmc5_value0 * mmc5_value1) & 0x00ff) >> 0);
457 } else if(addr == 0x5206) {
458 data = (uint8_t)(((mmc5_value0 * mmc5_value1) & 0xff00) >> 8);
459 } else if(addr >= 0x5c00 && addr < 0x6000) {
460 if(mmc5_gfx_mode == 2 || mmc5_gfx_mode == 3) {
461 data = (d_ppu->get_name_tables() + 0x800)[addr & 0x3ff];
467 void MEMORY::mmc5_lo_write(uint32_t addr, uint32_t data)
471 mmc5_prg_size = data & 0x03;
474 mmc5_chr_size = data & 0x03;
477 mmc5_wram_protect0 = data & 0x03;
480 mmc5_wram_protect1 = data & 0x03;
483 mmc5_gfx_mode = data & 0x03;
486 for(int i = 0; i < 4; i++) {
487 d_ppu->set_ppu_bank(8 + i, data & 0x03);
492 for(int i = 0; i < 0x3c0; i++) {
493 (d_ppu->get_name_tables() + 0xc00)[i] = data;
497 for(int i = 0x3c0; i < 0x400; i++) {
498 (d_ppu->get_name_tables() + 0xc00)[i] = 0x55 * (data & 3);
502 mmc5_set_wram_bank(3, data & 0x07);
508 mmc5_set_cpu_bank(addr & 0x07, data);
518 mmc5_chr_reg[addr & 0x07][0] = data;
519 mmc5_set_ppu_bank(0);
525 mmc5_chr_reg[(addr & 0x03) + 0][1] = data;
526 mmc5_chr_reg[(addr & 0x03) + 4][1] = data;
529 // mmc5_split_control = data;
532 // mmc5_split_scroll = data;
535 // mmc5_split_bank = data & 0x3f;
538 mmc5_irq_line = data;
541 mmc5_irq_enabled = data;
550 if(addr >= 0x5000 && addr <= 0x5015) {
551 // d_mmc5->write_io8(addr, data);
552 } else if(addr >= 0x5c00 && addr <= 0x5fff) {
553 if(mmc5_gfx_mode != 3) {
554 (d_ppu->get_name_tables() + 0x800)[addr & 0x3ff] = data; //(mmc5_irq_status & 0) ? data : 0x40;
561 //uint32_t MEMORY::mmc5_save_read(uint32_t addr)
563 // return bank_ptr[3][addr & 0x1fff];
566 void MEMORY::mmc5_save_write(uint32_t addr, uint32_t data)
568 if(mmc5_wram_protect0 == 0x02 && mmc5_wram_protect1 == 0x01) {
569 if(mmc5_wram_bank[3] < 8) {
570 bank_ptr[3][addr & 0x1fff] = data;
575 void MEMORY::mmc5_hi_write(uint32_t addr, uint32_t data)
577 if(mmc5_wram_protect0 == 0x02 && mmc5_wram_protect1 == 0x01) {
579 if(mmc5_wram_bank[4] < 8) {
580 bank_ptr[4][addr & 0x1fff] = data;
582 } else if(addr < 0xc000) {
583 if(mmc5_wram_bank[5] < 8) {
584 bank_ptr[5][addr & 0x1fff] = data;
586 } else if(addr < 0xe000) {
587 if(mmc5_wram_bank[6] < 8) {
588 bank_ptr[6][addr & 0x1fff] = data;
591 if(mmc5_wram_bank[7] < 8) {
592 bank_ptr[7][addr & 0x1fff] = data;
598 void MEMORY::mmc5_hsync(int v)
601 if(v == mmc5_irq_line) {
602 if(d_ppu->spr_enabled() && d_ppu->bg_enabled()) {
603 mmc5_irq_status |= 0x80;
606 if((mmc5_irq_status & 0x80) && (mmc5_irq_enabled & 0x80)) {
607 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
610 mmc5_irq_status |= 0x40;
614 void MEMORY::mmc5_set_cpu_bank(uint8_t bank, uint32_t bank_num)
616 if(bank_num & 0x80) {
617 if(mmc5_prg_size == 0) {
619 set_rom_bank(4, (bank_num & 0x7c) + 0);
620 set_rom_bank(5, (bank_num & 0x7c) + 1);
621 set_rom_bank(6, (bank_num & 0x7c) + 2);
622 set_rom_bank(7, (bank_num & 0x7c) + 3);
624 } else if(mmc5_prg_size == 1) {
626 set_rom_bank(4, (bank_num & 0x7e) + 0);
627 set_rom_bank(5, (bank_num & 0x7e) + 1);
628 } else if(bank == 7) {
629 set_rom_bank(6, (bank_num & 0x7e) + 0);
630 set_rom_bank(7, (bank_num & 0x7e) + 1);
632 } else if(mmc5_prg_size == 2) {
634 set_rom_bank(4, (bank_num & 0x7e) + 0);
635 set_rom_bank(5, (bank_num & 0x7e) + 1);
636 } else if(bank == 6) {
637 set_rom_bank(6, bank_num & 0x7f);
638 } else if(bank == 7) {
639 set_rom_bank(7, bank_num & 0x7f);
641 } else if(mmc5_prg_size == 3) {
643 set_rom_bank(4, bank_num & 0x7f);
644 } else if(bank == 5) {
645 set_rom_bank(5, bank_num & 0x7f);
646 } else if(bank == 6) {
647 set_rom_bank(6, bank_num & 0x7f);
648 } else if(bank == 7) {
649 set_rom_bank(7, bank_num & 0x7f);
653 if(mmc5_prg_size == 1) {
655 mmc5_set_wram_bank(4, (bank_num & 0x06)+0);
656 mmc5_set_wram_bank(5, (bank_num & 0x06)+1);
658 } else if(mmc5_prg_size == 2) {
660 mmc5_set_wram_bank(4, (bank_num & 0x06)+0);
661 mmc5_set_wram_bank(5, (bank_num & 0x06)+1);
664 mmc5_set_wram_bank(6, bank_num & 0x07);
666 } else if(mmc5_prg_size == 3) {
668 mmc5_set_wram_bank(4, bank_num & 0x07);
669 } else if(bank == 5) {
670 mmc5_set_wram_bank(5, bank_num & 0x07);
671 } else if(bank == 6) {
672 mmc5_set_wram_bank(6, bank_num & 0x07);
678 void MEMORY::mmc5_set_wram_bank(uint8_t bank, uint32_t bank_num)
681 bank_ptr[bank] = save_ram + 0x2000 * bank_num;
682 mmc5_wram_bank[bank] = bank_num;
684 set_rom_bank(bank, banks[bank]);
688 void MEMORY::mmc5_set_ppu_bank(uint8_t mode)
690 if(mmc5_chr_size == 0) {
691 d_ppu->set_ppu_bank(0, mmc5_chr_reg[7][mode] * 8 + 0);
692 d_ppu->set_ppu_bank(1, mmc5_chr_reg[7][mode] * 8 + 1);
693 d_ppu->set_ppu_bank(2, mmc5_chr_reg[7][mode] * 8 + 2);
694 d_ppu->set_ppu_bank(3, mmc5_chr_reg[7][mode] * 8 + 3);
695 d_ppu->set_ppu_bank(4, mmc5_chr_reg[7][mode] * 8 + 4);
696 d_ppu->set_ppu_bank(5, mmc5_chr_reg[7][mode] * 8 + 5);
697 d_ppu->set_ppu_bank(6, mmc5_chr_reg[7][mode] * 8 + 6);
698 d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode] * 8 + 7);
699 } else if(mmc5_chr_size == 1) {
700 d_ppu->set_ppu_bank(0, mmc5_chr_reg[3][mode] * 4 + 0);
701 d_ppu->set_ppu_bank(1, mmc5_chr_reg[3][mode] * 4 + 1);
702 d_ppu->set_ppu_bank(2, mmc5_chr_reg[3][mode] * 4 + 2);
703 d_ppu->set_ppu_bank(3, mmc5_chr_reg[3][mode] * 4 + 3);
704 d_ppu->set_ppu_bank(4, mmc5_chr_reg[7][mode] * 4 + 0);
705 d_ppu->set_ppu_bank(5, mmc5_chr_reg[7][mode] * 4 + 1);
706 d_ppu->set_ppu_bank(6, mmc5_chr_reg[7][mode] * 4 + 2);
707 d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode] * 4 + 3);
708 } else if(mmc5_chr_size == 2) {
709 d_ppu->set_ppu_bank(0, mmc5_chr_reg[1][mode] * 2 + 0);
710 d_ppu->set_ppu_bank(1, mmc5_chr_reg[1][mode] * 2 + 1);
711 d_ppu->set_ppu_bank(2, mmc5_chr_reg[3][mode] * 2 + 0);
712 d_ppu->set_ppu_bank(3, mmc5_chr_reg[3][mode] * 2 + 1);
713 d_ppu->set_ppu_bank(4, mmc5_chr_reg[5][mode] * 2 + 0);
714 d_ppu->set_ppu_bank(5, mmc5_chr_reg[5][mode] * 2 + 1);
715 d_ppu->set_ppu_bank(6, mmc5_chr_reg[7][mode] * 2 + 0);
716 d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode] * 2 + 1);
718 d_ppu->set_ppu_bank(0, mmc5_chr_reg[0][mode]);
719 d_ppu->set_ppu_bank(1, mmc5_chr_reg[1][mode]);
720 d_ppu->set_ppu_bank(2, mmc5_chr_reg[2][mode]);
721 d_ppu->set_ppu_bank(3, mmc5_chr_reg[3][mode]);
722 d_ppu->set_ppu_bank(4, mmc5_chr_reg[4][mode]);
723 d_ppu->set_ppu_bank(5, mmc5_chr_reg[5][mode]);
724 d_ppu->set_ppu_bank(6, mmc5_chr_reg[6][mode]);
725 d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode]);
729 uint8_t MEMORY::mmc5_ppu_latch_render(uint8_t mode, uint32_t addr)
733 if(mmc5_gfx_mode == 1 && mode == 1) {
735 uint32_t bank_num = ((d_ppu->get_name_tables() + 0x800)[addr] & 0x3f) << 2;
736 d_ppu->set_ppu_bank(0, bank_num + 0);
737 d_ppu->set_ppu_bank(1, bank_num + 1);
738 d_ppu->set_ppu_bank(2, bank_num + 2);
739 d_ppu->set_ppu_bank(3, bank_num + 3);
740 d_ppu->set_ppu_bank(4, bank_num + 0);
741 d_ppu->set_ppu_bank(5, bank_num + 1);
742 d_ppu->set_ppu_bank(6, bank_num + 2);
743 d_ppu->set_ppu_bank(7, bank_num + 3);
744 data = (((d_ppu->get_name_tables() + 0x800)[addr] & 0xc0) >> 4) | 0x01;
747 mmc5_set_ppu_bank(mode);
754 void MEMORY::vrc7_reset()
756 if(header.mapper() == 85) {
757 vrc7_irq_enabled = 0;
758 vrc7_irq_counter = 0;
760 d_opll->write_signal(SIG_YM2413_MUTE, 0, 0);
763 set_rom_bank(6, header.num_8k_rom_banks() - 2);
764 set_rom_bank(7, header.num_8k_rom_banks() - 1);
766 d_opll->write_signal(SIG_YM2413_MUTE, 1, 1);
770 //uint32_t MEMORY::vrc7_lo_read(uint32_t addr)
775 //void MEMORY::vrc7_lo_write(uint32_t addr, uint32_t data)
779 //uint32_t MEMORY::vrc7_save_read(uint32_t addr)
781 // return bank_ptr[3][addr & 0x1fff];
784 //void MEMORY::vrc7_save_write(uint32_t addr, uint32_t data)
786 // bank_ptr[3][addr & 0x1fff] = data;
789 void MEMORY::vrc7_hi_write(uint32_t addr, uint32_t data)
791 switch(addr & 0xf038) {
793 set_rom_bank(4, data);
797 set_rom_bank(5, data);
800 set_rom_bank(6, data);
804 d_opll->write_io8(addr >> 5, data);
807 d_ppu->set_ppu_bank(0, data);
811 d_ppu->set_ppu_bank(1, data);
814 d_ppu->set_ppu_bank(2, data);
818 d_ppu->set_ppu_bank(3, data);
821 d_ppu->set_ppu_bank(4, data);
825 d_ppu->set_ppu_bank(5, data);
828 d_ppu->set_ppu_bank(6, data);
832 d_ppu->set_ppu_bank(7, data);
835 switch(data & 0x03) {
837 d_ppu->set_mirroring(MIRROR_VERT);
840 d_ppu->set_mirroring(MIRROR_HORIZ);
843 d_ppu->set_mirroring(0, 0, 0, 0);
846 d_ppu->set_mirroring(1, 1, 1, 1);
852 vrc7_irq_latch = data;
856 vrc7_irq_counter = vrc7_irq_latch;
858 vrc7_irq_enabled = data & 0x03;
862 vrc7_irq_enabled = (vrc7_irq_enabled & 0x01) * 3;
867 void MEMORY::vrc7_hsync(int v)
869 if(vrc7_irq_enabled & 0x02) {
870 if(vrc7_irq_counter == 0xff) {
871 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
872 vrc7_irq_counter = vrc7_irq_latch;
879 #define STATE_VERSION 2
881 bool MEMORY::process_state(FILEIO* state_fio, bool loading)
883 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
886 if(!state_fio->StateCheckInt32(this_device_id)) {
889 state_fio->StateBuffer(save_file_name, sizeof(save_file_name), 1);
890 state_fio->StateBuffer(&header, sizeof(header), 1); // OK?
891 state_fio->StateUint32(rom_size);
892 // state_fio->StateUint32(rom_mask);
894 rom_mask = (rom_size / 0x2000) - 1;
898 rom = (uint8_t *)malloc(rom_size);
900 state_fio->StateBuffer(rom, rom_size, 1);
901 state_fio->StateBuffer(ram, sizeof(ram), 1);
902 state_fio->StateBuffer(save_ram, sizeof(save_ram), 1);
903 state_fio->StateUint32(save_ram_crc32);
904 //state_fio->StateBuffer(banks, sizeof(banks), 1);
905 for(int i = 0; i < (sizeof(banks) / sizeof(uint32_t)); i++) {
906 state_fio->StateUint32(banks[i]);
908 state_fio->StateUint16(dma_addr);
909 state_fio->StateUint8(frame_irq_enabled);
910 //state_fio->StateBuffer(mmc5_wram_bank, sizeof(mmc5_wram_bank), 1);
911 for(int i = 0; i < (sizeof(mmc5_wram_bank) / sizeof(uint32_t)); i++) {
912 state_fio->StateUint32(mmc5_wram_bank[i]);
914 state_fio->StateBuffer(mmc5_chr_reg, sizeof(mmc5_chr_reg), 1);
915 state_fio->StateUint32(mmc5_value0);
916 state_fio->StateUint32(mmc5_value0);
917 state_fio->StateUint8(mmc5_wram_protect0);
918 state_fio->StateUint8(mmc5_wram_protect1);
919 state_fio->StateUint8(mmc5_prg_size);
920 state_fio->StateUint8(mmc5_chr_size);
921 state_fio->StateUint8(mmc5_gfx_mode);
922 // state_fio->StateUint8(mmc5_split_control);
923 // state_fio->StateUint8(mmc5_split_bank);
924 state_fio->StateUint8(mmc5_irq_enabled);
925 state_fio->StateUint8(mmc5_irq_status);
926 state_fio->StateUint32(mmc5_irq_line);
927 state_fio->StateUint8(vrc7_irq_enabled);
928 state_fio->StateUint8(vrc7_irq_counter);
929 state_fio->StateUint8(vrc7_irq_latch);
930 state_fio->StateBool(pad_strobe);
931 state_fio->StateUint8(pad1_bits);
932 state_fio->StateUint8(pad2_bits);
933 state_fio->StateBool(kb_out);
934 state_fio->StateUint8(kb_scan);
938 if(header.mapper() == 5) {
939 for(int i = 3; i < 8; i++) {
940 mmc5_set_wram_bank(i, mmc5_wram_bank[i]);
943 for(int i = 4; i < 8; i++) {
944 set_rom_bank(i, banks[i]);
946 bank_ptr[3] = save_ram;