NES: Fixed FDS BIOS loading to match the README and give a proper error
This commit is contained in:
parent
73cb29e2c9
commit
21940f2d56
@ -34,7 +34,7 @@
|
||||
#define FDS_CLOCK (NES_CPU_CLOCK_NTSC / 2)
|
||||
#define SEEK_TIME 100 // 150
|
||||
#define CLEAR_IRQ() irq.seek_counter = irq.transfer_done = irq.timer_fired = 0; nes6502_irq_clear();
|
||||
#define TIMER_RELOAD() irq.timer_counter = (fds->regs[1] << 8) | fds->regs[0];
|
||||
#define TIMER_RELOAD() irq.timer_counter = (fds.regs[1] << 8) | fds.regs[0];
|
||||
|
||||
#define REG2_IRQ_REPEAT (1 << 0)
|
||||
#define REG2_IRQ_ENABLED (1 << 1)
|
||||
@ -80,18 +80,18 @@ struct
|
||||
bool transfer_done;
|
||||
} irq;
|
||||
|
||||
static fds_t *fds;
|
||||
static fds_t fds;
|
||||
|
||||
|
||||
static void fds_cpu_timer(int cycles)
|
||||
{
|
||||
if (irq.timer_counter > 0 && (fds->regs[2] & REG2_IRQ_ENABLED))
|
||||
if (irq.timer_counter > 0 && (fds.regs[2] & REG2_IRQ_ENABLED))
|
||||
{
|
||||
irq.timer_counter -= cycles;
|
||||
if (irq.timer_counter <= 0)
|
||||
{
|
||||
if (!(fds->regs[2] & REG2_IRQ_REPEAT))
|
||||
fds->regs[2] &= ~REG2_IRQ_ENABLED;
|
||||
if (!(fds.regs[2] & REG2_IRQ_REPEAT))
|
||||
fds.regs[2] &= ~REG2_IRQ_ENABLED;
|
||||
|
||||
TIMER_RELOAD();
|
||||
nes6502_irq();
|
||||
@ -105,7 +105,7 @@ static void fds_cpu_timer(int cycles)
|
||||
irq.seek_counter -= cycles;
|
||||
if (irq.seek_counter <= 0)
|
||||
{
|
||||
if (fds->regs[5] & REG5_USE_INTERRUPT)
|
||||
if (fds.regs[5] & REG5_USE_INTERRUPT)
|
||||
{
|
||||
nes6502_irq();
|
||||
}
|
||||
@ -133,13 +133,13 @@ static uint8 fds_read(uint32 address)
|
||||
return ret;
|
||||
|
||||
case 0x4031: // Read data register
|
||||
if (fds->regs[5] & 0x04)
|
||||
if (fds.regs[5] & 0x04)
|
||||
{
|
||||
CLEAR_IRQ();
|
||||
irq.seek_counter = SEEK_TIME;
|
||||
|
||||
if (fds->block_pos < fds->block_size)
|
||||
return fds->block_ptr[fds->block_pos++];
|
||||
if (fds.block_pos < fds.block_size)
|
||||
return fds.block_ptr[fds.block_pos++];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@ -147,7 +147,7 @@ static uint8 fds_read(uint32 address)
|
||||
|
||||
case 0x4032: // Disk drive status register
|
||||
// wprotect|/ready|/inserted
|
||||
if (!(fds->regs[5] & 1) || (fds->regs[5] & 2))
|
||||
if (!(fds.regs[5] & 1) || (fds.regs[5] & 2))
|
||||
return 0b110;
|
||||
return 0b100;
|
||||
|
||||
@ -191,42 +191,42 @@ static void fds_write(uint32 address, uint8 value)
|
||||
// Transfer Reset
|
||||
if (value & 0x02)
|
||||
{
|
||||
fds->block_type = BLOCK_INIT;
|
||||
fds->block_ptr = &fds->disk[0][0];
|
||||
fds->block_filesize = 0;
|
||||
fds->block_size = 0;
|
||||
fds->block_pos = 0;
|
||||
fds.block_type = BLOCK_INIT;
|
||||
fds.block_ptr = &fds.disk[0][0];
|
||||
fds.block_filesize = 0;
|
||||
fds.block_size = 0;
|
||||
fds.block_pos = 0;
|
||||
}
|
||||
|
||||
// New transfer
|
||||
if (value & 0x40 && ~(fds->regs[5]) & 0x40)
|
||||
if (value & 0x40 && ~(fds.regs[5]) & 0x40)
|
||||
{
|
||||
fds->block_ptr = fds->block_ptr + fds->block_pos;
|
||||
fds->block_pos = 0;
|
||||
fds.block_ptr = fds.block_ptr + fds.block_pos;
|
||||
fds.block_pos = 0;
|
||||
|
||||
switch (fds->block_type + 1)
|
||||
switch (fds.block_type + 1)
|
||||
{
|
||||
case BLOCK_VOLUME:
|
||||
fds->block_type = BLOCK_VOLUME;
|
||||
fds->block_size = 0x38;
|
||||
fds.block_type = BLOCK_VOLUME;
|
||||
fds.block_size = 0x38;
|
||||
break;
|
||||
case BLOCK_FILECOUNT:
|
||||
fds->block_type = BLOCK_FILECOUNT;
|
||||
fds->block_size = 0x02;
|
||||
fds.block_type = BLOCK_FILECOUNT;
|
||||
fds.block_size = 0x02;
|
||||
break;
|
||||
case BLOCK_FILEHEADER:
|
||||
case BLOCK_NEXT:
|
||||
fds->block_type = BLOCK_FILEHEADER;
|
||||
fds->block_size = 0x10;
|
||||
fds->block_filesize = (fds->block_ptr[13]) | (fds->block_ptr[14]) << 8;
|
||||
fds.block_type = BLOCK_FILEHEADER;
|
||||
fds.block_size = 0x10;
|
||||
fds.block_filesize = (fds.block_ptr[13]) | (fds.block_ptr[14]) << 8;
|
||||
break;
|
||||
case BLOCK_FILEDATA:
|
||||
fds->block_type = BLOCK_FILEDATA;
|
||||
fds->block_size = 0x01 + fds->block_filesize;
|
||||
fds.block_type = BLOCK_FILEDATA;
|
||||
fds.block_size = 0x01 + fds.block_filesize;
|
||||
break;
|
||||
}
|
||||
|
||||
MESSAGE_INFO("Block type %d with size %d bytes\n", fds->block_type, fds->block_size);
|
||||
MESSAGE_INFO("Block type %d with size %d bytes\n", fds.block_type, fds.block_size);
|
||||
}
|
||||
|
||||
// Turn on motor
|
||||
@ -236,7 +236,7 @@ static void fds_write(uint32 address, uint8 value)
|
||||
}
|
||||
|
||||
// Update mirroring
|
||||
if ((value & REG5_MIRRORING) != (fds->regs[5] & REG5_MIRRORING) || fds->regs[5] == 0)
|
||||
if ((value & REG5_MIRRORING) != (fds.regs[5] & REG5_MIRRORING) || fds.regs[5] == 0)
|
||||
{
|
||||
ppu_setmirroring((value & REG5_MIRRORING) ? PPU_MIRROR_HORI : PPU_MIRROR_VERT);
|
||||
}
|
||||
@ -244,7 +244,7 @@ static void fds_write(uint32 address, uint8 value)
|
||||
break;
|
||||
}
|
||||
|
||||
fds->regs[address & 7] = value;
|
||||
fds.regs[address & 7] = value;
|
||||
}
|
||||
|
||||
static uint8 fds_sound_read(uint32 address)
|
||||
@ -281,40 +281,28 @@ static void fds_setstate(void *state)
|
||||
|
||||
void fds_init(rom_t *cart)
|
||||
{
|
||||
if (!fds)
|
||||
{
|
||||
fds = calloc(1, sizeof(fds_t));
|
||||
|
||||
// I'm not sure yet where we should load the bios
|
||||
// so it shall be hardcoded here while I work on
|
||||
// the actual hardware emulation...
|
||||
FILE *fp = fopen("/sd/roms/fds/disksys.rom", "rb");
|
||||
fread(cart->prg_rom, 0x2000, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
uint8 *disk_ptr = cart->data_ptr;
|
||||
|
||||
if (memcmp(disk_ptr, FDS_HEAD_MAGIC, 4) == 0)
|
||||
{
|
||||
fds->sides = ((fdsheader_t *)disk_ptr)->sides;
|
||||
fds.sides = ((fdsheader_t *)disk_ptr)->sides;
|
||||
disk_ptr += 16;
|
||||
MESSAGE_INFO("FDS header present. Sides = %d\n", fds->sides);
|
||||
MESSAGE_INFO("FDS header present. Sides = %d\n", fds.sides);
|
||||
}
|
||||
else
|
||||
{
|
||||
fds->sides = cart->data_len / 65500;
|
||||
MESSAGE_INFO("FDS header absent. Sides = %d\n", fds->sides);
|
||||
fds.sides = cart->data_len / 65500;
|
||||
MESSAGE_INFO("FDS header absent. Sides = %d\n", fds.sides);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (i < fds->sides || cart->data_len > i * 65500)
|
||||
fds->disk[i] = disk_ptr + (i * 65500);
|
||||
if (i < fds.sides || cart->data_len > i * 65500)
|
||||
fds.disk[i] = disk_ptr + (i * 65500);
|
||||
else
|
||||
fds->disk[i] = NULL;
|
||||
fds.disk[i] = NULL;
|
||||
}
|
||||
fds->block_ptr = &fds->disk[0][0];
|
||||
fds.block_ptr = &fds.disk[0][0];
|
||||
|
||||
mmc_bankprg(32, 0x6000, 0, PRG_RAM); // PRG-RAM 0x6000-0xDFFF
|
||||
mmc_bankprg(8, 0xE000, 0, PRG_ROM); // BIOS 0xE000-0xFFFF
|
||||
|
||||
@ -135,17 +135,25 @@ void nes_setcompathacks(void)
|
||||
}
|
||||
|
||||
/* insert a cart into the NES */
|
||||
rom_t *nes_insertcart(const char *filename)
|
||||
int nes_insertcart(const char *filename, const char *biosfile)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
/* rom file */
|
||||
nes.cart = rom_loadfile(filename);
|
||||
if (NULL == nes.cart)
|
||||
{
|
||||
status = -1;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
/* mapper */
|
||||
nes.mapper = mmc_init(nes.cart);
|
||||
if (NULL == nes.mapper)
|
||||
{
|
||||
status = -2;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
/* if we're using VRAM, let the PPU know */
|
||||
nes.ppu->vram_present = (nes.cart->chr_rom == NULL);
|
||||
@ -184,21 +192,42 @@ rom_t *nes_insertcart(const char *filename)
|
||||
nes.overscan = 8;
|
||||
}
|
||||
|
||||
/* Load BIOS file if required (currently only for Famicom Disk System) */
|
||||
if (nes.cart->flags & ROM_FLAG_FDS_DISK)
|
||||
{
|
||||
if (biosfile == NULL)
|
||||
{
|
||||
// TO DO: Try biosfile = dirname(filename) / disksys.rom
|
||||
status = -3;
|
||||
goto _fail;
|
||||
}
|
||||
FILE *fp = fopen(biosfile, "rb");
|
||||
if (!fp || !fread(nes.cart->prg_rom, ROM_PRG_BANK_SIZE, nes.cart->prg_rom_banks, fp))
|
||||
{
|
||||
MESSAGE_ERROR("NES: BIOS file load failed from '%s'.\n", biosfile);
|
||||
status = -3;
|
||||
fclose(fp);
|
||||
goto _fail;
|
||||
}
|
||||
fclose(fp);
|
||||
MESSAGE_INFO("NES: BIOS file loaded from '%s'.\n", biosfile);
|
||||
}
|
||||
|
||||
nes_setcompathacks();
|
||||
|
||||
nes_reset(true);
|
||||
|
||||
return nes.cart;
|
||||
return status;
|
||||
|
||||
_fail:
|
||||
nes_shutdown();
|
||||
return NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* insert a disk into the FDS */
|
||||
rom_t *nes_insertdisk(const char *filename)
|
||||
int nes_insertdisk(const char *filename, const char *biosfile)
|
||||
{
|
||||
return NULL;
|
||||
return nes_insertcart(filename, biosfile);
|
||||
}
|
||||
|
||||
/* Reset NES hardware */
|
||||
|
||||
@ -123,8 +123,8 @@ typedef struct
|
||||
nes_t *nes_getptr(void);
|
||||
nes_t *nes_init(nes_type_t system, int sample_rate, bool stereo);
|
||||
void nes_shutdown(void);
|
||||
rom_t *nes_insertcart(const char *filename);
|
||||
rom_t *nes_insertdisk(const char *filename);
|
||||
int nes_insertcart(const char *filename, const char *biosfile);
|
||||
int nes_insertdisk(const char *filename, const char *biosfile);
|
||||
void nes_settimer(nes_timer_t *func, long period);
|
||||
void nes_emulate(bool draw);
|
||||
void nes_reset(bool hard_reset);
|
||||
|
||||
@ -107,6 +107,8 @@ rom_t *rom_loadmem(uint8 *data, size_t size)
|
||||
rom.flags = header->rom_type;
|
||||
rom.mapper_number = header->rom_type >> 4;
|
||||
|
||||
MESSAGE_INFO("ROM: CRC32: %08X\n", rom.checksum);
|
||||
|
||||
if (header->reserved2 == 0)
|
||||
{
|
||||
// https://wiki.nesdev.com/w/index.php/INES
|
||||
@ -186,7 +188,6 @@ rom_t *rom_loadmem(uint8 *data, size_t size)
|
||||
rom.chr_rom = rom.prg_rom + (rom.prg_rom_banks * ROM_PRG_BANK_SIZE);
|
||||
}
|
||||
|
||||
MESSAGE_INFO("ROM: CRC32: %08X\n", rom.checksum);
|
||||
MESSAGE_INFO("ROM: Mapper: %d, PRG:%dK, CHR:%dK, Flags: %c%c%c%c\n",
|
||||
rom.mapper_number,
|
||||
rom.prg_rom_banks * 8, rom.chr_rom_banks * 8,
|
||||
@ -202,25 +203,26 @@ rom_t *rom_loadmem(uint8 *data, size_t size)
|
||||
{
|
||||
MESSAGE_INFO("ROM: Found FDS file of size %d.\n", size);
|
||||
|
||||
rom.flags = ROM_FLAG_FDS_DISK|ROM_FLAG_BATTERY;
|
||||
rom.prg_ram_banks = 4;
|
||||
rom.chr_ram_banks = 1;
|
||||
rom.prg_rom_banks = 1;
|
||||
|
||||
rom.prg_ram = malloc(0x8000 + 0x2000);
|
||||
rom.chr_ram = malloc(0x2000);
|
||||
rom.prg_rom = rom.prg_ram + 0x8000;
|
||||
|
||||
if (!rom.prg_ram || !rom.chr_ram)
|
||||
{
|
||||
MESSAGE_ERROR("ROM: Memory allocation failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rom.checksum = crc32_le(0, rom.data_ptr, rom.data_len);
|
||||
rom.mapper_number = 20;
|
||||
|
||||
MESSAGE_INFO("ROM: CRC32: %08X\n", rom.checksum);
|
||||
|
||||
rom.prg_ram = malloc((rom.prg_ram_banks + rom.prg_rom_banks) * ROM_PRG_BANK_SIZE);
|
||||
rom.chr_ram = malloc(rom.chr_ram_banks * ROM_CHR_BANK_SIZE);
|
||||
// We do it this way because only rom.prg_ram is freed in rom_free
|
||||
rom.prg_rom = rom.prg_ram + (rom.prg_ram_banks * ROM_PRG_BANK_SIZE);
|
||||
|
||||
if (!rom.prg_ram || !rom.chr_ram || !rom.prg_rom)
|
||||
{
|
||||
MESSAGE_ERROR("ROM: Memory allocation failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(rom.filename, "filename.fds", PATH_MAX);
|
||||
return &rom;
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#define ROM_FLAG_BATTERY 0x02
|
||||
#define ROM_FLAG_VERTICAL 0x01
|
||||
#define ROM_FLAG_FREE_DATA 0x100
|
||||
#define ROM_FLAG_FDS_DISK 0x200
|
||||
|
||||
#define ROM_PRG_BANK_SIZE 0x2000
|
||||
#define ROM_CHR_BANK_SIZE 0x2000
|
||||
|
||||
@ -107,7 +107,7 @@ int nofrendo_run(const char *filename, const char *savefile)
|
||||
{
|
||||
nes_t *nes = nes_getptr();
|
||||
|
||||
if (!nes_insertcart(filename))
|
||||
if (nes_insertcart(filename, NULL) < 0)
|
||||
{
|
||||
MESSAGE_ERROR("Failed to insert NES cart.\n");
|
||||
return -2;
|
||||
|
||||
@ -257,10 +257,15 @@ void app_main(void)
|
||||
RG_PANIC("Init failed.");
|
||||
}
|
||||
|
||||
if (!nes_insertcart(app->romPath))
|
||||
{
|
||||
int ret = nes_insertcart(app->romPath, "/sd/bios/fds_bios.bin");
|
||||
if (ret == -1)
|
||||
RG_PANIC("ROM load failed.");
|
||||
else if (ret == -2)
|
||||
RG_PANIC("Unsupported mapper.");
|
||||
else if (ret == -3)
|
||||
RG_PANIC("BIOS file required.");
|
||||
else if (ret < 0)
|
||||
RG_PANIC("Unsupported ROM.");
|
||||
}
|
||||
|
||||
app->refreshRate = nes->refresh_rate;
|
||||
nes->blit_func = osd_blitscreen;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user