[ memory ]
*/
-#include "memory.h"
+#include "./memory.h"
+#include "ppu.h"
#include "../datarec.h"
+#include "../ym2413.h"
#define EVENT_DMA_DONE 0
-void MEMORY::initialize()
+void FAMILYBASIC_MEMORY::initialize()
{
- memset(ram, 0, sizeof(ram));
-
- key_stat = emu->key_buffer();
- joy_stat = emu->joy_buffer();
+ key_stat = emu->get_key_buffer();
+ joy_stat = emu->get_joy_buffer();
// register event
register_vline_event(this);
}
-void MEMORY::load_rom_image(const _TCHAR *file_name)
+void FAMILYBASIC_MEMORY::load_rom_image(const _TCHAR *file_name)
{
FILEIO* fio = new FILEIO();
- bool file_open = false;
- if(fio->Fopen(emu->bios_path(file_name), FILEIO_READ_BINARY)) {
- file_open = true;
+ memset(save_ram, 0, sizeof(save_ram));
+
+ if(fio->Fopen(create_local_path(file_name), FILEIO_READ_BINARY)) {
// create save file name
_TCHAR tmp_file_name[_MAX_PATH];
- _tcscpy_s(tmp_file_name, _MAX_PATH, file_name);
+ my_tcscpy_s(tmp_file_name, _MAX_PATH, file_name);
_TCHAR *dot = _tcsstr(tmp_file_name, _T("."));
if(dot != NULL) dot[0] = _T('\0');
- _stprintf_s(save_file_name, _MAX_PATH, _T("%s.SAV"), tmp_file_name);
+ my_stprintf_s(save_file_name, _MAX_PATH, _T("%s.SAV"), tmp_file_name);
} else {
// for compatibility
- if(fio->Fopen(emu->bios_path(_T("BASIC.NES")), FILEIO_READ_BINARY)) {
- file_open = true;
- }
- _tcscpy_s(save_file_name, _MAX_PATH, _T("BACKUP.BIN"));
+ fio->Fopen(create_local_path(_T("BASIC.NES")), FILEIO_READ_BINARY);
+ my_tcscpy_s(save_file_name, _MAX_PATH, _T("BACKUP.BIN"));
}
- if(file_open) {
+ if(fio->IsOpened()) {
// read header
- fio->Fread(header, sizeof(header), 1);
- // read program rom (max 32kb)
- fio->Fread(rom, 0x4000, 1);
- memcpy(rom + 0x4000, rom, 0x4000);
- fio->Fread(rom + 0x4000, 0x4000, 1);
+ fio->Fread(&header, sizeof(header), 1);
+ // read program rom
+ rom_size = 0x2000 * header.num_8k_rom_banks();
+ for(uint32_t bit = 0x80000; bit != 0; bit >>= 1) {
+ if(rom_size & bit) {
+ if(rom_size & (bit - 1)) {
+ rom_size = (rom_size | (bit - 1)) + 1;
+ }
+ break;
+ }
+ }
+ rom = (uint8_t *)calloc(rom_size, 1);
+ fio->Fread(rom, 0x2000 * header.num_8k_rom_banks(), 1);
fio->Fclose();
} else {
- memset(header, 0, sizeof(header));
- memset(rom, 0xff, sizeof(rom));
+ memset(&header, 0, sizeof(header));
+ header.dummy = 2; // 32KB
+ rom_size = 0x2000 * header.num_8k_rom_banks();
+ rom = (uint8_t *)calloc(rom_size, 1);
+ memset(rom, 0xff, 0x2000 * header.num_8k_rom_banks());
}
- if(fio->Fopen(emu->bios_path(save_file_name), FILEIO_READ_BINARY)) {
+ if(fio->Fopen(create_local_path(save_file_name), FILEIO_READ_BINARY)) {
fio->Fread(save_ram, sizeof(save_ram), 1);
fio->Fclose();
- } else {
- memset(save_ram, 0, sizeof(save_ram));
}
delete fio;
- save_ram_crc32 = getcrc32(save_ram, sizeof(save_ram));
+ rom_mask = (rom_size / 0x2000) - 1;
+ save_ram_crc32 = get_crc32(save_ram, sizeof(save_ram));
}
-void MEMORY::save_backup()
+void FAMILYBASIC_MEMORY::save_backup()
{
- if(save_ram_crc32 != getcrc32(save_ram, sizeof(save_ram))) {
+ if(save_ram_crc32 != get_crc32(save_ram, sizeof(save_ram))) {
FILEIO* fio = new FILEIO();
- if(fio->Fopen(emu->bios_path(save_file_name), FILEIO_WRITE_BINARY)) {
+ if(fio->Fopen(create_local_path(save_file_name), FILEIO_WRITE_BINARY)) {
fio->Fwrite(save_ram, sizeof(save_ram), 1);
fio->Fclose();
}
}
}
-void MEMORY::release()
+void FAMILYBASIC_MEMORY::release()
{
+ if(rom != NULL) {
+ free(rom);
+ rom = NULL;
+ }
save_backup();
}
-void MEMORY::reset()
+void FAMILYBASIC_MEMORY::reset()
{
+ memset(ram, 0, sizeof(ram));
+
+ for(int i = 4; i < 8; i++) {
+ set_rom_bank(i, i);
+ }
+ bank_ptr[3] = save_ram;
+
dma_addr = 0x80;
frame_irq_enabled = 0xff;
kb_out = false;
kb_scan = 0;
+
+ mmc5_reset();
+ vrc7_reset();
}
-void MEMORY::write_data8(uint32 addr, uint32 data)
+void FAMILYBASIC_MEMORY::write_data8(uint32_t addr, uint32_t data)
{
addr &= 0xffff;
-
+
if(addr < 0x2000) {
ram[addr & 0x7ff] = data;
} else if(addr < 0x4000) {
} else if((data & 0x07) == 0x06) {
kb_out = !kb_out;
}
- // data recorder
- d_drec->write_signal(SIG_DATAREC_MIC, data, 2);
+ // data recorder (thanks MESS)
+ if((data & 0x07) == 0x07) {
+ d_drec->write_signal(SIG_DATAREC_MIC, 1, 1);
+ } else {
+ d_drec->write_signal(SIG_DATAREC_MIC, 0, 0);
+ }
} else if(addr < 0x4018) {
if(addr == 0x4017) {
frame_irq_enabled = data;
}
d_apu->write_data8(addr, data);
} else if(addr < 0x6000) {
- // mapper independent
+ if(header.mapper() == 5) {
+ mmc5_lo_write(addr, data);
+// } else if(header.mapper() == 85) {
+// vrc7_lo_write(addr, data);
+ }
} else if(addr < 0x8000) {
- save_ram[addr & 0x1fff] = data;
+ if(header.mapper() == 5) {
+ mmc5_save_write(addr, data);
+// } else if(header.mapper() == 85) {
+// vrc7_save_write(addr, data);
+ } else {
+ bank_ptr[3][addr & 0x1fff] = data;
+ }
} else {
- // mapper independent
+ if(header.mapper() == 5) {
+ mmc5_hi_write(addr, data);
+ } else if(header.mapper() == 85) {
+ vrc7_hi_write(addr, data);
+ }
}
}
-uint32 MEMORY::read_data8(uint32 addr)
+uint32_t FAMILYBASIC_MEMORY::read_data8(uint32_t addr)
{
addr &= 0xffff;
-
+
if(addr < 0x2000) {
return ram[addr & 0x7ff];
} else if(addr < 0x4000) {
} else if(addr == 0x4014) {
return dma_addr >> 8;
} else if(addr < 0x4016) {
- uint32 val = d_apu->read_data8(addr);
+ uint32_t val = d_apu->read_data8(addr);
if(addr == 0x4015 && !(frame_irq_enabled & 0xc0)) {
val |= 0x40;
}
return val;
} else if(addr == 0x4016) {
// joypad #1
- uint32 val = pad1_bits & 1;
+ uint32_t val = pad1_bits & 1;
pad1_bits >>= 1;
// data recorder
val |= d_drec->read_signal(0) ? 2 : 0;
return val;
} else if(addr == 0x4017) {
// joypad #2
- uint32 val = 0xfe | (pad2_bits & 1);
+ uint32_t val = 0xfe | (pad2_bits & 1);
pad2_bits >>= 1;
// keyboard
if(kb_out) {
}
return val;
} else if(addr < 0x6000) {
- // mapper independent
- return 0xff;
+ if(header.mapper() == 5) {
+ return mmc5_lo_read(addr);
+// } else if(header.mapper() == 85) {
+// return vrc7_lo_read(addr);
+ } else {
+ return 0xff;
+ }
} else if(addr < 0x8000) {
- return save_ram[addr & 0x1fff];
+// if(header.mapper() == 5) {
+// return mmc5_save_read(addr);
+// } else if(header.mapper() == 85) {
+// return vrc7_save_read(addr);
+// } else {
+ return bank_ptr[3][addr & 0x1fff];
+// }
+ } else if(addr < 0xa000) {
+ return bank_ptr[4][addr & 0x1fff];
+ } else if(addr < 0xc000) {
+ return bank_ptr[5][addr & 0x1fff];
+ } else if(addr < 0xe000) {
+ return bank_ptr[6][addr & 0x1fff];
} else {
- return rom[addr & 0x7fff];
+ return bank_ptr[7][addr & 0x1fff];
}
}
-void MEMORY::event_vline(int v, int clock)
+void FAMILYBASIC_MEMORY::event_vline(int v, int clock)
{
+ // 525 -> 262.5
+ if(v & 1) {
+ return;
+ }
+ v >>= 1;
+
// fram irq
if(v == 240 && !(frame_irq_enabled & 0xc0)) {
// pending
d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
}
+
+ // mapper irq
+ if(header.mapper() == 5) {
+ mmc5_hsync(v);
+ } else if(header.mapper() == 85) {
+ vrc7_hsync(v);
+ }
}
-void MEMORY::event_callback(int event_id, int err)
+void FAMILYBASIC_MEMORY::event_callback(int event_id, int err)
{
// dma done
d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
}
-#define STATE_VERSION 1
+void FAMILYBASIC_MEMORY::set_rom_bank(uint8_t bank, uint32_t bank_num)
+{
+ bank_ptr[bank] = rom + 0x2000 * (bank_num & rom_mask);
+ banks[bank] = bank_num;
+
+ // mmc5
+ mmc5_wram_bank[bank] = 8;
+}
+
+// mmc5
-void MEMORY::save_state(FILEIO* state_fio)
+void FAMILYBASIC_MEMORY::mmc5_reset()
{
- state_fio->FputUint32(STATE_VERSION);
- state_fio->FputInt32(this_device_id);
+ if(header.mapper() == 5) {
+ mmc5_set_wram_bank(3, 0);
+ set_rom_bank(4, header.num_8k_rom_banks() - 1);
+ set_rom_bank(5, header.num_8k_rom_banks() - 1);
+ set_rom_bank(6, header.num_8k_rom_banks() - 1);
+ set_rom_bank(7, header.num_8k_rom_banks() - 1);
+
+ for(int i = 0; i < 8; i++) {
+ mmc5_chr_reg[i][0] = i;
+ mmc5_chr_reg[i][1] = (i & 0x03) + 4;
+ }
+ mmc5_wram_protect0 = 0x02;
+ mmc5_wram_protect1 = 0x01;
+ mmc5_prg_size = 3;
+ mmc5_chr_size = 3;
+ mmc5_gfx_mode = 0;
+// mmc5_split_control = 0;
+// mmc5_split_bank = 0;
+ mmc5_irq_enabled = 0;
+ mmc5_irq_status = 0;
+ mmc5_irq_line = 0;
+ }
+}
+
+uint32_t FAMILYBASIC_MEMORY::mmc5_lo_read(uint32_t addr)
+{
+ uint8_t data = (uint8_t)(addr >> 8);
- state_fio->Fwrite(save_file_name, sizeof(save_file_name), 1);
- state_fio->Fwrite(header, sizeof(header), 1);
- state_fio->Fwrite(rom, sizeof(rom), 1);
- state_fio->Fwrite(ram, sizeof(ram), 1);
- state_fio->Fwrite(save_ram, sizeof(save_ram), 1);
- state_fio->FputUint32(save_ram_crc32);
- state_fio->FputUint16(dma_addr);
- state_fio->FputUint8(frame_irq_enabled);
- state_fio->FputBool(pad_strobe);
- state_fio->FputUint8(pad1_bits);
- state_fio->FputUint8(pad2_bits);
- state_fio->FputBool(kb_out);
- state_fio->FputUint8(kb_scan);
+ if(addr == 0x5204) {
+ data = mmc5_irq_status;
+ mmc5_irq_status &= ~0x80;
+ } else if(addr == 0x5205) {
+ data = (uint8_t)(((mmc5_value0 * mmc5_value1) & 0x00ff) >> 0);
+ } else if(addr == 0x5206) {
+ data = (uint8_t)(((mmc5_value0 * mmc5_value1) & 0xff00) >> 8);
+ } else if(addr >= 0x5c00 && addr < 0x6000) {
+ if(mmc5_gfx_mode == 2 || mmc5_gfx_mode == 3) {
+ data = (d_ppu->get_name_tables() + 0x800)[addr & 0x3ff];
+ }
+ }
+ return data;
+}
+
+void FAMILYBASIC_MEMORY::mmc5_lo_write(uint32_t addr, uint32_t data)
+{
+ switch(addr) {
+ case 0x5100:
+ mmc5_prg_size = data & 0x03;
+ break;
+ case 0x5101:
+ mmc5_chr_size = data & 0x03;
+ break;
+ case 0x5102:
+ mmc5_wram_protect0 = data & 0x03;
+ break;
+ case 0x5103:
+ mmc5_wram_protect1 = data & 0x03;
+ break;
+ case 0x5104:
+ mmc5_gfx_mode = data & 0x03;
+ break;
+ case 0x5105:
+ for(int i = 0; i < 4; i++) {
+ d_ppu->set_ppu_bank(8 + i, data & 0x03);
+ data >>= 2;
+ }
+ break;
+ case 0x5106:
+ for(int i = 0; i < 0x3c0; i++) {
+ (d_ppu->get_name_tables() + 0xc00)[i] = data;
+ }
+ break;
+ case 0x5107:
+ for(int i = 0x3c0; i < 0x400; i++) {
+ (d_ppu->get_name_tables() + 0xc00)[i] = 0x55 * (data & 3);
+ }
+ break;
+ case 0x5113:
+ mmc5_set_wram_bank(3, data & 0x07);
+ break;
+ case 0x5114:
+ case 0x5115:
+ case 0x5116:
+ case 0x5117:
+ mmc5_set_cpu_bank(addr & 0x07, data);
+ break;
+ case 0x5120:
+ case 0x5121:
+ case 0x5122:
+ case 0x5123:
+ case 0x5124:
+ case 0x5125:
+ case 0x5126:
+ case 0x5127:
+ mmc5_chr_reg[addr & 0x07][0] = data;
+ mmc5_set_ppu_bank(0);
+ break;
+ case 0x5128:
+ case 0x5129:
+ case 0x512a:
+ case 0x512b:
+ mmc5_chr_reg[(addr & 0x03) + 0][1] = data;
+ mmc5_chr_reg[(addr & 0x03) + 4][1] = data;
+ break;
+ case 0x5200:
+// mmc5_split_control = data;
+ break;
+ case 0x5201:
+// mmc5_split_scroll = data;
+ break;
+ case 0x5202:
+// mmc5_split_bank = data & 0x3f;
+ break;
+ case 0x5203:
+ mmc5_irq_line = data;
+ break;
+ case 0x5204:
+ mmc5_irq_enabled = data;
+ break;
+ case 0x5205:
+ mmc5_value0 = data;
+ break;
+ case 0x5206:
+ mmc5_value1 = data;
+ break;
+ default:
+ if(addr >= 0x5000 && addr <= 0x5015) {
+// d_mmc5->write_io8(addr, data);
+ } else if(addr >= 0x5c00 && addr <= 0x5fff) {
+ if(mmc5_gfx_mode != 3) {
+ (d_ppu->get_name_tables() + 0x800)[addr & 0x3ff] = data; //(mmc5_irq_status & 0) ? data : 0x40;
+ }
+ }
+ break;
+ }
}
-bool MEMORY::load_state(FILEIO* state_fio)
+//uint32_t FAMILYBASIC_MEMORY::mmc5_save_read(uint32_t addr)
+//{
+// return bank_ptr[3][addr & 0x1fff];
+//}
+
+void FAMILYBASIC_MEMORY::mmc5_save_write(uint32_t addr, uint32_t data)
{
- if(state_fio->FgetUint32() != STATE_VERSION) {
+ if(mmc5_wram_protect0 == 0x02 && mmc5_wram_protect1 == 0x01) {
+ if(mmc5_wram_bank[3] < 8) {
+ bank_ptr[3][addr & 0x1fff] = data;
+ }
+ }
+}
+
+void FAMILYBASIC_MEMORY::mmc5_hi_write(uint32_t addr, uint32_t data)
+{
+ if(mmc5_wram_protect0 == 0x02 && mmc5_wram_protect1 == 0x01) {
+ if(addr < 0xa000) {
+ if(mmc5_wram_bank[4] < 8) {
+ bank_ptr[4][addr & 0x1fff] = data;
+ }
+ } else if(addr < 0xc000) {
+ if(mmc5_wram_bank[5] < 8) {
+ bank_ptr[5][addr & 0x1fff] = data;
+ }
+ } else if(addr < 0xe000) {
+ if(mmc5_wram_bank[6] < 8) {
+ bank_ptr[6][addr & 0x1fff] = data;
+ }
+ } else {
+ if(mmc5_wram_bank[7] < 8) {
+ bank_ptr[7][addr & 0x1fff] = data;
+ }
+ }
+ }
+}
+
+void FAMILYBASIC_MEMORY::mmc5_hsync(int v)
+{
+ if(v <= 240) {
+ if(v == mmc5_irq_line) {
+ if(d_ppu->spr_enabled() && d_ppu->bg_enabled()) {
+ mmc5_irq_status |= 0x80;
+ }
+ }
+ if((mmc5_irq_status & 0x80) && (mmc5_irq_enabled & 0x80)) {
+ d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
+ }
+ } else {
+ mmc5_irq_status |= 0x40;
+ }
+}
+
+void FAMILYBASIC_MEMORY::mmc5_set_cpu_bank(uint8_t bank, uint32_t bank_num)
+{
+ if(bank_num & 0x80) {
+ if(mmc5_prg_size == 0) {
+ if(bank == 7) {
+ set_rom_bank(4, (bank_num & 0x7c) + 0);
+ set_rom_bank(5, (bank_num & 0x7c) + 1);
+ set_rom_bank(6, (bank_num & 0x7c) + 2);
+ set_rom_bank(7, (bank_num & 0x7c) + 3);
+ }
+ } else if(mmc5_prg_size == 1) {
+ if(bank == 5) {
+ set_rom_bank(4, (bank_num & 0x7e) + 0);
+ set_rom_bank(5, (bank_num & 0x7e) + 1);
+ } else if(bank == 7) {
+ set_rom_bank(6, (bank_num & 0x7e) + 0);
+ set_rom_bank(7, (bank_num & 0x7e) + 1);
+ }
+ } else if(mmc5_prg_size == 2) {
+ if(bank == 5) {
+ set_rom_bank(4, (bank_num & 0x7e) + 0);
+ set_rom_bank(5, (bank_num & 0x7e) + 1);
+ } else if(bank == 6) {
+ set_rom_bank(6, bank_num & 0x7f);
+ } else if(bank == 7) {
+ set_rom_bank(7, bank_num & 0x7f);
+ }
+ } else if(mmc5_prg_size == 3) {
+ if(bank == 4) {
+ set_rom_bank(4, bank_num & 0x7f);
+ } else if(bank == 5) {
+ set_rom_bank(5, bank_num & 0x7f);
+ } else if(bank == 6) {
+ set_rom_bank(6, bank_num & 0x7f);
+ } else if(bank == 7) {
+ set_rom_bank(7, bank_num & 0x7f);
+ }
+ }
+ } else {
+ if(mmc5_prg_size == 1) {
+ if(bank == 5) {
+ mmc5_set_wram_bank(4, (bank_num & 0x06)+0);
+ mmc5_set_wram_bank(5, (bank_num & 0x06)+1);
+ }
+ } else if(mmc5_prg_size == 2) {
+ if(bank == 5) {
+ mmc5_set_wram_bank(4, (bank_num & 0x06)+0);
+ mmc5_set_wram_bank(5, (bank_num & 0x06)+1);
+ } else if(bank == 6)
+ {
+ mmc5_set_wram_bank(6, bank_num & 0x07);
+ }
+ } else if(mmc5_prg_size == 3) {
+ if(bank == 4) {
+ mmc5_set_wram_bank(4, bank_num & 0x07);
+ } else if(bank == 5) {
+ mmc5_set_wram_bank(5, bank_num & 0x07);
+ } else if(bank == 6) {
+ mmc5_set_wram_bank(6, bank_num & 0x07);
+ }
+ }
+ }
+}
+
+void FAMILYBASIC_MEMORY::mmc5_set_wram_bank(uint8_t bank, uint32_t bank_num)
+{
+ if(bank_num < 8) {
+ bank_ptr[bank] = save_ram + 0x2000 * bank_num;
+ mmc5_wram_bank[bank] = bank_num;
+ } else {
+ set_rom_bank(bank, banks[bank]);
+ }
+}
+
+void FAMILYBASIC_MEMORY::mmc5_set_ppu_bank(uint8_t mode)
+{
+ if(mmc5_chr_size == 0) {
+ d_ppu->set_ppu_bank(0, mmc5_chr_reg[7][mode] * 8 + 0);
+ d_ppu->set_ppu_bank(1, mmc5_chr_reg[7][mode] * 8 + 1);
+ d_ppu->set_ppu_bank(2, mmc5_chr_reg[7][mode] * 8 + 2);
+ d_ppu->set_ppu_bank(3, mmc5_chr_reg[7][mode] * 8 + 3);
+ d_ppu->set_ppu_bank(4, mmc5_chr_reg[7][mode] * 8 + 4);
+ d_ppu->set_ppu_bank(5, mmc5_chr_reg[7][mode] * 8 + 5);
+ d_ppu->set_ppu_bank(6, mmc5_chr_reg[7][mode] * 8 + 6);
+ d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode] * 8 + 7);
+ } else if(mmc5_chr_size == 1) {
+ d_ppu->set_ppu_bank(0, mmc5_chr_reg[3][mode] * 4 + 0);
+ d_ppu->set_ppu_bank(1, mmc5_chr_reg[3][mode] * 4 + 1);
+ d_ppu->set_ppu_bank(2, mmc5_chr_reg[3][mode] * 4 + 2);
+ d_ppu->set_ppu_bank(3, mmc5_chr_reg[3][mode] * 4 + 3);
+ d_ppu->set_ppu_bank(4, mmc5_chr_reg[7][mode] * 4 + 0);
+ d_ppu->set_ppu_bank(5, mmc5_chr_reg[7][mode] * 4 + 1);
+ d_ppu->set_ppu_bank(6, mmc5_chr_reg[7][mode] * 4 + 2);
+ d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode] * 4 + 3);
+ } else if(mmc5_chr_size == 2) {
+ d_ppu->set_ppu_bank(0, mmc5_chr_reg[1][mode] * 2 + 0);
+ d_ppu->set_ppu_bank(1, mmc5_chr_reg[1][mode] * 2 + 1);
+ d_ppu->set_ppu_bank(2, mmc5_chr_reg[3][mode] * 2 + 0);
+ d_ppu->set_ppu_bank(3, mmc5_chr_reg[3][mode] * 2 + 1);
+ d_ppu->set_ppu_bank(4, mmc5_chr_reg[5][mode] * 2 + 0);
+ d_ppu->set_ppu_bank(5, mmc5_chr_reg[5][mode] * 2 + 1);
+ d_ppu->set_ppu_bank(6, mmc5_chr_reg[7][mode] * 2 + 0);
+ d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode] * 2 + 1);
+ } else {
+ d_ppu->set_ppu_bank(0, mmc5_chr_reg[0][mode]);
+ d_ppu->set_ppu_bank(1, mmc5_chr_reg[1][mode]);
+ d_ppu->set_ppu_bank(2, mmc5_chr_reg[2][mode]);
+ d_ppu->set_ppu_bank(3, mmc5_chr_reg[3][mode]);
+ d_ppu->set_ppu_bank(4, mmc5_chr_reg[4][mode]);
+ d_ppu->set_ppu_bank(5, mmc5_chr_reg[5][mode]);
+ d_ppu->set_ppu_bank(6, mmc5_chr_reg[6][mode]);
+ d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode]);
+ }
+}
+
+uint8_t FAMILYBASIC_MEMORY::mmc5_ppu_latch_render(uint8_t mode, uint32_t addr)
+{
+ uint8_t data = 0;
+
+ if(mmc5_gfx_mode == 1 && mode == 1) {
+ // ex gfx mode
+ uint32_t bank_num = ((d_ppu->get_name_tables() + 0x800)[addr] & 0x3f) << 2;
+ d_ppu->set_ppu_bank(0, bank_num + 0);
+ d_ppu->set_ppu_bank(1, bank_num + 1);
+ d_ppu->set_ppu_bank(2, bank_num + 2);
+ d_ppu->set_ppu_bank(3, bank_num + 3);
+ d_ppu->set_ppu_bank(4, bank_num + 0);
+ d_ppu->set_ppu_bank(5, bank_num + 1);
+ d_ppu->set_ppu_bank(6, bank_num + 2);
+ d_ppu->set_ppu_bank(7, bank_num + 3);
+ data = (((d_ppu->get_name_tables() + 0x800)[addr] & 0xc0) >> 4) | 0x01;
+ } else {
+ // normal
+ mmc5_set_ppu_bank(mode);
+ }
+ return data;
+}
+
+// vrc7
+
+void FAMILYBASIC_MEMORY::vrc7_reset()
+{
+ if(header.mapper() == 85) {
+ vrc7_irq_enabled = 0;
+ vrc7_irq_counter = 0;
+ vrc7_irq_latch = 0;
+ d_opll->write_signal(SIG_YM2413_MUTE, 0, 0);
+ set_rom_bank(4, 0);
+ set_rom_bank(5, 1);
+ set_rom_bank(6, header.num_8k_rom_banks() - 2);
+ set_rom_bank(7, header.num_8k_rom_banks() - 1);
+ } else {
+ d_opll->write_signal(SIG_YM2413_MUTE, 1, 1);
+ }
+}
+
+//uint32_t FAMILYBASIC_MEMORY::vrc7_lo_read(uint32_t addr)
+//{
+// return 0xff;
+//}
+
+//void FAMILYBASIC_MEMORY::vrc7_lo_write(uint32_t addr, uint32_t data)
+//{
+//}
+
+//uint32_t FAMILYBASIC_MEMORY::vrc7_save_read(uint32_t addr)
+//{
+// return bank_ptr[3][addr & 0x1fff];
+//}
+
+//void FAMILYBASIC_MEMORY::vrc7_save_write(uint32_t addr, uint32_t data)
+//{
+// bank_ptr[3][addr & 0x1fff] = data;
+//}
+
+void FAMILYBASIC_MEMORY::vrc7_hi_write(uint32_t addr, uint32_t data)
+{
+ switch(addr & 0xf038) {
+ case 0x8000:
+ set_rom_bank(4, data);
+ break;
+ case 0x8008:
+ case 0x8010:
+ set_rom_bank(5, data);
+ break;
+ case 0x9000:
+ set_rom_bank(6, data);
+ break;
+ case 0x9010:
+ case 0x9030:
+ d_opll->write_io8(addr >> 5, data);
+ break;
+ case 0xa000:
+ d_ppu->set_ppu_bank(0, data);
+ break;
+ case 0xa008:
+ case 0xa010:
+ d_ppu->set_ppu_bank(1, data);
+ break;
+ case 0xb000:
+ d_ppu->set_ppu_bank(2, data);
+ break;
+ case 0xb008:
+ case 0xb010:
+ d_ppu->set_ppu_bank(3, data);
+ break;
+ case 0xc000:
+ d_ppu->set_ppu_bank(4, data);
+ break;
+ case 0xc008:
+ case 0xc010:
+ d_ppu->set_ppu_bank(5, data);
+ break;
+ case 0xd000:
+ d_ppu->set_ppu_bank(6, data);
+ break;
+ case 0xd008:
+ case 0xd010:
+ d_ppu->set_ppu_bank(7, data);
+ break;
+ case 0xe000:
+ switch(data & 0x03) {
+ case 0x00:
+ d_ppu->set_mirroring(MIRROR_VERT);
+ break;
+ case 0x01:
+ d_ppu->set_mirroring(MIRROR_HORIZ);
+ break;
+ case 0x02:
+ d_ppu->set_mirroring(0, 0, 0, 0);
+ break;
+ case 0x03:
+ d_ppu->set_mirroring(1, 1, 1, 1);
+ break;
+ }
+ break;
+ case 0xe008:
+ case 0xe010:
+ vrc7_irq_latch = data;
+ break;
+ case 0xf000:
+ if(data & 0x02) {
+ vrc7_irq_counter = vrc7_irq_latch;
+ }
+ vrc7_irq_enabled = data & 0x03;
+ break;
+ case 0xf008:
+ case 0xf010:
+ vrc7_irq_enabled = (vrc7_irq_enabled & 0x01) * 3;
+ break;
+ }
+}
+
+void FAMILYBASIC_MEMORY::vrc7_hsync(int v)
+{
+ if(vrc7_irq_enabled & 0x02) {
+ if(vrc7_irq_counter == 0xff) {
+ d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
+ vrc7_irq_counter = vrc7_irq_latch;
+ } else {
+ vrc7_irq_counter++;
+ }
+ }
+}
+
+#define STATE_VERSION 2
+
+bool FAMILYBASIC_MEMORY::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
return false;
}
- if(state_fio->FgetInt32() != this_device_id) {
+ if(!state_fio->StateCheckInt32(this_device_id)) {
return false;
}
- state_fio->Fread(save_file_name, sizeof(save_file_name), 1);
- state_fio->Fread(header, sizeof(header), 1);
- state_fio->Fread(rom, sizeof(rom), 1);
- state_fio->Fread(ram, sizeof(ram), 1);
- state_fio->Fread(save_ram, sizeof(save_ram), 1);
- save_ram_crc32 = state_fio->FgetUint32();
- dma_addr = state_fio->FgetUint16();
- frame_irq_enabled = state_fio->FgetUint8();
- pad_strobe = state_fio->FgetBool();
- pad1_bits = state_fio->FgetUint8();
- pad2_bits = state_fio->FgetUint8();
- kb_out = state_fio->FgetBool();
- kb_scan = state_fio->FgetUint8();
+ state_fio->StateBuffer(save_file_name, sizeof(save_file_name), 1);
+ state_fio->StateBuffer(&header, sizeof(header), 1); // OK?
+ state_fio->StateUint32(rom_size);
+// state_fio->StateUint32(rom_mask);
+ if(loading) {
+ rom_mask = (rom_size / 0x2000) - 1;
+ if(rom != NULL) {
+ free(rom);
+ }
+ rom = (uint8_t *)malloc(rom_size);
+ }
+ state_fio->StateBuffer(rom, rom_size, 1);
+ state_fio->StateBuffer(ram, sizeof(ram), 1);
+ state_fio->StateBuffer(save_ram, sizeof(save_ram), 1);
+ state_fio->StateUint32(save_ram_crc32);
+ //state_fio->StateBuffer(banks, sizeof(banks), 1);
+ for(int i = 0; i < (sizeof(banks) / sizeof(uint32_t)); i++) {
+ state_fio->StateUint32(banks[i]);
+ }
+ state_fio->StateUint16(dma_addr);
+ state_fio->StateUint8(frame_irq_enabled);
+ //state_fio->StateBuffer(mmc5_wram_bank, sizeof(mmc5_wram_bank), 1);
+ for(int i = 0; i < (sizeof(mmc5_wram_bank) / sizeof(uint32_t)); i++) {
+ state_fio->StateUint32(mmc5_wram_bank[i]);
+ }
+ state_fio->StateBuffer(mmc5_chr_reg, sizeof(mmc5_chr_reg), 1);
+ state_fio->StateUint32(mmc5_value0);
+ state_fio->StateUint32(mmc5_value0);
+ state_fio->StateUint8(mmc5_wram_protect0);
+ state_fio->StateUint8(mmc5_wram_protect1);
+ state_fio->StateUint8(mmc5_prg_size);
+ state_fio->StateUint8(mmc5_chr_size);
+ state_fio->StateUint8(mmc5_gfx_mode);
+// state_fio->StateUint8(mmc5_split_control);
+// state_fio->StateUint8(mmc5_split_bank);
+ state_fio->StateUint8(mmc5_irq_enabled);
+ state_fio->StateUint8(mmc5_irq_status);
+ state_fio->StateUint32(mmc5_irq_line);
+ state_fio->StateUint8(vrc7_irq_enabled);
+ state_fio->StateUint8(vrc7_irq_counter);
+ state_fio->StateUint8(vrc7_irq_latch);
+ state_fio->StateBool(pad_strobe);
+ state_fio->StateUint8(pad1_bits);
+ state_fio->StateUint8(pad2_bits);
+ state_fio->StateBool(kb_out);
+ state_fio->StateUint8(kb_scan);
+
+ // post process
+ if(loading) {
+ if(header.mapper() == 5) {
+ for(int i = 3; i < 8; i++) {
+ mmc5_set_wram_bank(i, mmc5_wram_bank[i]);
+ }
+ } else {
+ for(int i = 4; i < 8; i++) {
+ set_rom_bank(i, banks[i]);
+ }
+ bank_ptr[3] = save_ram;
+ }
+ }
return true;
}
+