311 lines
5.9 KiB
C++
311 lines
5.9 KiB
C++
|
|
#ifdef _NES_MAPPER_CPP_
|
||
|
|
|
||
|
|
/////////////////////////////////////////////////////////////////////
|
||
|
|
// Mapper 20
|
||
|
|
void NES_mapper20::Reset()
|
||
|
|
{
|
||
|
|
// Init ExSound
|
||
|
|
parent_NES->apu->SelectExSound(4);
|
||
|
|
|
||
|
|
FILE* fp = NULL;
|
||
|
|
char fn[256];
|
||
|
|
|
||
|
|
GetModuleFileName(NULL, fn, 256);
|
||
|
|
int pt = strlen(fn);
|
||
|
|
while(fn[pt] != '\\') pt--;
|
||
|
|
fn[pt+1] = '\0';
|
||
|
|
strcat(fn, "DISKSYS.ROM");
|
||
|
|
|
||
|
|
if((fp = fopen(fn, "rb")) != NULL)
|
||
|
|
{
|
||
|
|
uint8 head1 = fgetc(fp);
|
||
|
|
uint8 head2 = fgetc(fp);
|
||
|
|
uint8 head3 = fgetc(fp);
|
||
|
|
if(head1 == 'N' && head2 == 'E' && head3 == 'S')
|
||
|
|
{
|
||
|
|
fseek(fp, 0x6010, SEEK_SET);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
fseek(fp, 0, SEEK_SET);
|
||
|
|
}
|
||
|
|
for(uint32 i = 0; i < 0x2000; i++)
|
||
|
|
{
|
||
|
|
bios[i] = fgetc(fp);
|
||
|
|
}
|
||
|
|
fclose(fp);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
throw "DISKSYS.ROM not found.";
|
||
|
|
}
|
||
|
|
|
||
|
|
// cancel license screen
|
||
|
|
//bios[0xfb0] = 0x00;
|
||
|
|
|
||
|
|
NES_6502::Context context;
|
||
|
|
parent_NES->cpu->GetContext(&context);
|
||
|
|
context.mem_page[3] = wram + 0x0000;
|
||
|
|
context.mem_page[4] = wram + 0x2000;
|
||
|
|
context.mem_page[5] = wram + 0x4000;
|
||
|
|
context.mem_page[6] = wram + 0x6000;
|
||
|
|
context.mem_page[7] = bios;
|
||
|
|
parent_NES->cpu->SetContext(&context);
|
||
|
|
|
||
|
|
// read FDS disk image
|
||
|
|
if(ROM_banks[0] == 'F' && ROM_banks[1] == 'D' && ROM_banks[2] == 'S')
|
||
|
|
{
|
||
|
|
for(uint32 i = 0; i < ROM_banks[4]; i++)
|
||
|
|
{
|
||
|
|
for(uint32 j = 0; j < 65500; j++)
|
||
|
|
{
|
||
|
|
disk[0x10000*i+j] = ROM_banks[16+65500*i+j];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
throw "Invalid DISK image.";
|
||
|
|
}
|
||
|
|
|
||
|
|
if(parent_NES->fds_id() == 0xc7525744) // Reflect World
|
||
|
|
{
|
||
|
|
parent_NES->frame_irq_disenabled = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
irq_enabled = 0;
|
||
|
|
irq_counter = 0;
|
||
|
|
irq_latch = 0;
|
||
|
|
irq_wait = 0;
|
||
|
|
|
||
|
|
access_flag = 0;
|
||
|
|
disk_enabled = 1;
|
||
|
|
head_position = 0;
|
||
|
|
write_skip = 0;
|
||
|
|
disk_status = 0;
|
||
|
|
write_reg = 0;
|
||
|
|
current_side = 1;
|
||
|
|
last_side = 1;
|
||
|
|
insert_wait = 180;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint8 NES_mapper20::MemoryReadLow(uint32 addr)
|
||
|
|
{
|
||
|
|
uint8 val = 0x00;
|
||
|
|
|
||
|
|
switch (addr)
|
||
|
|
{
|
||
|
|
case 0x4030:
|
||
|
|
{
|
||
|
|
val = disk_status;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 0x4031:
|
||
|
|
{
|
||
|
|
if((current_side != 0) && (current_side == last_side))
|
||
|
|
{
|
||
|
|
val = disk[(current_side-1)*0x10000+head_position];
|
||
|
|
if(write_reg & 0x01)
|
||
|
|
{
|
||
|
|
head_position += (head_position < 64999) ? 1 : 0;
|
||
|
|
irq_wait = 2;
|
||
|
|
}
|
||
|
|
access_flag = 1;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
val = 0xff;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 0x4032:
|
||
|
|
{
|
||
|
|
uint8 eject = ((current_side != 0) && (current_side == last_side)) ? 0 : 1;
|
||
|
|
val = 0x40;
|
||
|
|
val |= eject ? 1 : 0;
|
||
|
|
val |= eject ? 4 : 0;
|
||
|
|
val |= (!eject && (write_reg & 0x01) && !(write_reg & 0x02)) ? 0 : 2;
|
||
|
|
|
||
|
|
if(last_side != current_side)
|
||
|
|
{
|
||
|
|
// wait 2.0 sec for change disk
|
||
|
|
if(insert_wait > 120)
|
||
|
|
{
|
||
|
|
last_side = current_side;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 0x4033:
|
||
|
|
{
|
||
|
|
val = 0x80;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
{
|
||
|
|
val = parent_NES->apu->ExRead(addr);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return val;
|
||
|
|
}
|
||
|
|
|
||
|
|
void NES_mapper20::MemoryWriteLow(uint32 addr, uint8 data)
|
||
|
|
{
|
||
|
|
switch (addr)
|
||
|
|
{
|
||
|
|
case 0x4020:
|
||
|
|
{
|
||
|
|
irq_latch = (irq_latch & 0xFF00) | data;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 0x4021:
|
||
|
|
{
|
||
|
|
irq_latch = (irq_latch & 0x00FF) | ((uint32)data << 8);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 0x4022:
|
||
|
|
{
|
||
|
|
irq_counter = irq_latch;
|
||
|
|
irq_enabled = data & 0x03;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 0x4023:
|
||
|
|
{
|
||
|
|
disk_enabled = data & 0x01;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 0x4024:
|
||
|
|
{
|
||
|
|
if((current_side != 0) && (current_side == last_side))
|
||
|
|
{
|
||
|
|
if(disk_enabled && !(write_reg & 0x04) && head_position < 65000)
|
||
|
|
{
|
||
|
|
if(write_skip)
|
||
|
|
{
|
||
|
|
write_skip--;
|
||
|
|
}
|
||
|
|
else if(head_position >= 2)
|
||
|
|
{
|
||
|
|
disk[(current_side-1)*0x10000+head_position-2] = data;
|
||
|
|
access_flag = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 0x4025:
|
||
|
|
{
|
||
|
|
if(data & 0x08)
|
||
|
|
{
|
||
|
|
set_mirroring(NES_PPU::MIRROR_HORIZ);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
set_mirroring(NES_PPU::MIRROR_VERT);
|
||
|
|
}
|
||
|
|
if((current_side != 0) && (current_side == last_side))
|
||
|
|
{
|
||
|
|
if((write_reg & 0x40) && !(data & 0x10) && !(data & 0x40))
|
||
|
|
{
|
||
|
|
head_position = (head_position < 2) ? 0 : head_position - 2;
|
||
|
|
}
|
||
|
|
if(!(data & 0x04))
|
||
|
|
{
|
||
|
|
write_skip = 2;
|
||
|
|
}
|
||
|
|
if(data & 0x02)
|
||
|
|
{
|
||
|
|
head_position = 0;
|
||
|
|
irq_wait = 2;
|
||
|
|
}
|
||
|
|
if(data & 0x80)
|
||
|
|
{
|
||
|
|
irq_wait = 2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
write_reg = data;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
{
|
||
|
|
parent_NES->apu->ExWrite(addr, data);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void NES_mapper20::MemoryWriteSaveRAM(uint32 addr, uint8 data)
|
||
|
|
{
|
||
|
|
wram[addr - 0x6000] = data;
|
||
|
|
}
|
||
|
|
|
||
|
|
void NES_mapper20::MemoryWrite(uint32 addr, uint8 data)
|
||
|
|
{
|
||
|
|
if(addr < 0xE000)
|
||
|
|
{
|
||
|
|
wram[addr - 0x6000] = data;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void NES_mapper20::HSync(uint32 scanline)
|
||
|
|
{
|
||
|
|
disk_status &= 0xfc;
|
||
|
|
|
||
|
|
if(irq_enabled)
|
||
|
|
{
|
||
|
|
if(irq_counter < 113)
|
||
|
|
{
|
||
|
|
irq_enabled &= 0x01;
|
||
|
|
irq_counter = irq_latch;
|
||
|
|
disk_status |= 0x01;
|
||
|
|
parent_NES->cpu->DoIRQ();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
irq_counter -= 113;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if(irq_wait)
|
||
|
|
{
|
||
|
|
irq_wait--;
|
||
|
|
if(!irq_wait && (write_reg & 0x80))
|
||
|
|
{
|
||
|
|
disk_status |= 0x02;
|
||
|
|
parent_NES->cpu->DoIRQ();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void NES_mapper20::VSync()
|
||
|
|
{
|
||
|
|
// count MAX 3sec
|
||
|
|
insert_wait += (insert_wait < 180) ? 1 : 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void NES_mapper20::SNSS_fixup()
|
||
|
|
{
|
||
|
|
NES_6502::Context context;
|
||
|
|
parent_NES->cpu->GetContext(&context);
|
||
|
|
context.mem_page[3] = wram + 0x0000;
|
||
|
|
context.mem_page[4] = wram + 0x2000;
|
||
|
|
context.mem_page[5] = wram + 0x4000;
|
||
|
|
context.mem_page[6] = wram + 0x6000;
|
||
|
|
context.mem_page[7] = bios;
|
||
|
|
parent_NES->cpu->SetContext(&context);
|
||
|
|
}
|
||
|
|
/////////////////////////////////////////////////////////////////////
|
||
|
|
|
||
|
|
#endif
|