diff options
Diffstat (limited to 'src/devices/bus/nes/disksys.cpp')
-rw-r--r-- | src/devices/bus/nes/disksys.cpp | 132 |
1 files changed, 90 insertions, 42 deletions
diff --git a/src/devices/bus/nes/disksys.cpp b/src/devices/bus/nes/disksys.cpp index 71101492822..9512ef036e8 100644 --- a/src/devices/bus/nes/disksys.cpp +++ b/src/devices/bus/nes/disksys.cpp @@ -9,12 +9,10 @@ Here we emulate the RAM expansion + Disk Drive which form the Famicom Disk System. - Based on info from NESDev wiki ( http://wiki.nesdev.com/w/index.php/Family_Computer_Disk_System ) + Based on info from NESDev wiki ( https://www.nesdev.org/wiki/Family_Computer_Disk_System ) TODO: - convert floppy drive + fds format to modern code! - - add sound bits - - stop IRQ from using HOLD_LINE ***********************************************************************************************************/ @@ -23,14 +21,14 @@ #include "disksys.h" #include "imagedev/flopdrv.h" #include "formats/nes_dsk.h" +#include "speaker.h" #ifdef NES_PCB_DEBUG - #define VERBOSE 1 +#define VERBOSE (LOG_GENERAL) #else - #define VERBOSE 0 +#define VERBOSE (0) #endif - -#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0) +#include "logmacro.h" //----------------------------------------------- @@ -53,15 +51,20 @@ static const floppy_interface nes_floppy_interface = void nes_disksys_device::device_add_mconfig(machine_config &config) { - LEGACY_FLOPPY(config, FLOPPY_0, 0, &nes_floppy_interface); + LEGACY_FLOPPY(config, m_disk, 0, &nes_floppy_interface); + + SPEAKER(config, "addon").front_center(); // connected to motherboard + + RP2C33_SOUND(config, m_sound, XTAL(21'477'272)/12); // clock driven from motherboard? + m_sound->add_route(0, "addon", 0.2); } ROM_START( disksys ) ROM_REGION(0x2000, "drive", 0) - ROM_SYSTEM_BIOS( 0, "2c33a-01a", "Famicom Disk System Bios") + ROM_SYSTEM_BIOS( 0, "2c33a-01a", "Famicom Disk System BIOS") ROMX_LOAD( "rp2c33a-01a.bin", 0x0000, 0x2000, CRC(5e607dcf) SHA1(57fe1bdee955bb48d357e463ccbf129496930b62), ROM_BIOS(0)) // newer, Nintendo logo has no shadow - ROM_SYSTEM_BIOS( 1, "2c33-01", "Famicom Disk System Bios, older") + ROM_SYSTEM_BIOS( 1, "2c33-01", "Famicom Disk System BIOS, older") ROMX_LOAD( "rp2c33-01.bin", 0x0000, 0x2000, CRC(1c7ae5d5) SHA1(af5af53f66982e749643fdf8b2acbb7d4d3ed229), ROM_BIOS(1)) // older, Nintendo logo has shadow ROM_END @@ -101,9 +104,11 @@ nes_disksys_device::nes_disksys_device(const machine_config &mconfig, const char : nes_nrom_device(mconfig, NES_DISKSYS, tag, owner, clock) , m_2c33_rom(*this, "drive") , m_fds_data(nullptr) - , m_disk(*this, FLOPPY_0) + , m_disk(*this, "floppy0") + , m_sound(*this, "rp2c33snd") , irq_timer(nullptr) - , m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), m_irq_transfer(0), m_fds_motor_on(0), m_fds_door_closed(0), m_fds_current_side(0), m_fds_head_position(0), m_fds_status0(0), m_read_mode(0), m_drive_ready(0) + , m_irq_count(0), m_irq_count_latch(0), m_irq_enable(false), m_irq_repeat(false), m_irq_transfer(false), m_disk_reg_enable(false), m_sound_en(false) + , m_fds_motor_on(0), m_fds_door_closed(0), m_fds_current_side(0), m_fds_head_position(0), m_fds_status0(0), m_read_mode(0), m_drive_ready(0) , m_fds_sides(0), m_fds_last_side(0), m_fds_count(0) { } @@ -116,7 +121,7 @@ void nes_disksys_device::device_start() m_disk->floppy_install_load_proc(nes_disksys_device::load_proc); m_disk->floppy_install_unload_proc(nes_disksys_device::unload_proc); - irq_timer = timer_alloc(TIMER_IRQ); + irq_timer = timer_alloc(FUNC(nes_disksys_device::irq_timer_tick), this); irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); save_item(NAME(m_fds_motor_on)); @@ -127,9 +132,12 @@ void nes_disksys_device::device_start() save_item(NAME(m_read_mode)); save_item(NAME(m_drive_ready)); save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_repeat)); save_item(NAME(m_irq_transfer)); save_item(NAME(m_irq_count)); save_item(NAME(m_irq_count_latch)); + save_item(NAME(m_disk_reg_enable)); + save_item(NAME(m_sound_en)); save_item(NAME(m_fds_last_side)); save_item(NAME(m_fds_count)); @@ -151,8 +159,11 @@ void nes_disksys_device::pcb_reset() m_drive_ready = 0; m_irq_count = 0; m_irq_count_latch = 0; - m_irq_enable = 0; - m_irq_transfer = 0; + m_irq_enable = false; + m_irq_repeat = false; + m_irq_transfer = false; + m_disk_reg_enable = false; + m_sound_en = false; m_fds_count = 0; m_fds_last_side = 0; @@ -175,7 +186,7 @@ void nes_disksys_device::pcb_reset() void nes_disksys_device::write_h(offs_t offset, uint8_t data) { - LOG_MMC(("Famicom Disk System write_h, offset %04x, data: %02x\n", offset, data)); + LOG("Famicom Disk System write_h, offset %04x, data: %02x\n", offset, data); if (offset < 0x6000) m_prgram[offset + 0x2000] = data; @@ -183,7 +194,7 @@ void nes_disksys_device::write_h(offs_t offset, uint8_t data) uint8_t nes_disksys_device::read_h(offs_t offset) { - LOG_MMC(("Famicom Disk System read_h, offset: %04x\n", offset)); + LOG("Famicom Disk System read_h, offset: %04x\n", offset); if (offset < 0x6000) return m_prgram[offset + 0x2000]; @@ -193,29 +204,35 @@ uint8_t nes_disksys_device::read_h(offs_t offset) void nes_disksys_device::write_m(offs_t offset, uint8_t data) { - LOG_MMC(("Famicom Disk System write_m, offset: %04x, data: %02x\n", offset, data)); + LOG("Famicom Disk System write_m, offset: %04x, data: %02x\n", offset, data); m_prgram[offset] = data; } uint8_t nes_disksys_device::read_m(offs_t offset) { - LOG_MMC(("Famicom Disk System read_m, offset: %04x\n", offset)); + LOG("Famicom Disk System read_m, offset: %04x\n", offset); return m_prgram[offset]; } -void nes_disksys_device::hblank_irq(int scanline, int vblank, int blanked) +void nes_disksys_device::hblank_irq(int scanline, bool vblank, bool blanked) { + // FIXME: This looks like a gross hack that ties the disk byte transfer IRQ to the PPU. Seriously? if (m_irq_transfer) - hold_irq_line(); + { + set_irq_line(ASSERT_LINE); + m_fds_status0 |= 0x02; + } } void nes_disksys_device::write_ex(offs_t offset, uint8_t data) { - LOG_MMC(("Famicom Disk System write_ex, offset: %04x, data: %02x\n", offset, data)); + LOG("Famicom Disk System write_ex, offset: %04x, data: %02x\n", offset, data); if (offset >= 0x20 && offset < 0x60) { // wavetable + if (m_sound_en) + m_sound->wave_w(offset - 0x20, data); } switch (offset) @@ -227,18 +244,35 @@ void nes_disksys_device::write_ex(offs_t offset, uint8_t data) m_irq_count_latch = (m_irq_count_latch & 0x00ff) | (data << 8); break; case 0x02: - m_irq_count = m_irq_count_latch; - m_irq_enable = BIT(data, 1); + if (m_disk_reg_enable) + { + m_irq_repeat = BIT(data, 0); + m_irq_enable = BIT(data, 1); + if (m_irq_enable) + m_irq_count = m_irq_count_latch; + else + set_irq_line(CLEAR_LINE); + } break; case 0x03: // bit0 - Enable disk I/O registers // bit1 - Enable sound I/O registers + m_disk_reg_enable = BIT(data, 0); + if (!m_disk_reg_enable) + { + m_irq_enable = 0; + set_irq_line(CLEAR_LINE); + } + m_sound_en = BIT(data, 1); break; case 0x04: // write data out to disk // TEST! if (m_fds_data && m_fds_current_side && !m_read_mode) m_fds_data[(m_fds_current_side - 1) * 65500 + m_fds_head_position++] = data; + // clear the byte transfer flag + m_fds_status0 &= ~0x02; + set_irq_line(CLEAR_LINE); break; case 0x05: // $4025 - FDS Control @@ -260,7 +294,11 @@ void nes_disksys_device::write_ex(offs_t offset, uint8_t data) m_fds_head_position -= 2; // ??? is this some sort of compensation?? m_read_mode = BIT(data, 2); - set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + if (BIT(data, 3)) + m_fds_status0 |= 0x08; + else + m_fds_status0 &= ~0x08; + set_nt_mirroring(BIT(m_fds_status0, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); m_drive_ready = data & 0x40; m_irq_transfer = BIT(data, 7); break; @@ -277,18 +315,22 @@ void nes_disksys_device::write_ex(offs_t offset, uint8_t data) case 0x68: // $4088 - Mod table write case 0x69: // $4089 - Wave write / master volume case 0x6a: // $408a - Envelope speed + if (m_sound_en) + m_sound->write(offset - 0x60, data); break; } } uint8_t nes_disksys_device::read_ex(offs_t offset) { - LOG_MMC(("Famicom Disk System read_ex, offset: %04x\n", offset)); - uint8_t ret; + LOG("Famicom Disk System read_ex, offset: %04x\n", offset); + uint8_t ret = 0x00; if (offset >= 0x20 && offset < 0x60) { // wavetable + if (m_sound_en) + ret = m_sound->wave_r(offset - 0x20); } switch (offset) @@ -299,12 +341,14 @@ uint8_t nes_disksys_device::read_ex(offs_t offset) // bit1 - Byte transfer flag (Set to 1 every time 8 bits have been transferred between // the RAM adaptor & disk drive through $4024/$4031; Reset to 0 when $4024, // $4031, or $4030 has been serviced) + // bit3 = Nametable mirroring flag (0: Vertical, 1: Horizontal) // bit4 - CRC control (0: CRC passed; 1: CRC error) // bit6 - End of Head (1 when disk head is on the most inner track) // bit7 - Disk Data Read/Write Enable (1 when disk is readable/writable) ret = m_fds_status0 | 0x80; - // clear the disk IRQ detect flag - m_fds_status0 &= ~0x01; + // clear the disk IRQ detect and byte transfer flags + m_fds_status0 &= ~0x03; + set_irq_line(CLEAR_LINE); break; case 0x11: // $4031 - data latch @@ -323,6 +367,9 @@ uint8_t nes_disksys_device::read_ex(offs_t offset) } else ret = 0; + // clear the byte transfer flag + m_fds_status0 &= ~0x02; + set_irq_line(CLEAR_LINE); break; case 0x12: // $4032 - disk status 1: @@ -351,6 +398,9 @@ uint8_t nes_disksys_device::read_ex(offs_t offset) break; case 0x70: // $4090 - Volume gain - write through $4080 case 0x72: // $4092 - Mod gain - read through $4084 + if (m_sound_en) + ret = m_sound->read(offset - 0x60); + break; default: ret = 0x00; break; @@ -360,23 +410,22 @@ uint8_t nes_disksys_device::read_ex(offs_t offset) } //------------------------------------------------- -// device_timer - handler timer events +// irq_timer_tick - handle IRQ timer //------------------------------------------------- -void nes_disksys_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nes_disksys_device::irq_timer_tick) { - if (id == TIMER_IRQ) + if (m_irq_enable) { - if (m_irq_enable && m_irq_count) - { + if (m_irq_count) m_irq_count--; - if (!m_irq_count) - { - hold_irq_line(); + else + { + set_irq_line(ASSERT_LINE); + m_irq_count = m_irq_count_latch; + if (!m_irq_repeat) m_irq_enable = 0; - m_fds_status0 |= 0x01; - m_irq_count_latch = 0; // used in Kaettekita Mario Bros - } + m_fds_status0 |= 0x01; } } } @@ -393,7 +442,7 @@ void nes_disksys_device::disk_flip_side() if (m_fds_current_side == 0) popmessage("No disk inserted."); else - popmessage("Disk set to side %d", m_fds_current_side); + popmessage("Disk set to side %c", m_fds_current_side+0x40); } @@ -416,7 +465,6 @@ void nes_disksys_device::load_disk(device_image_interface &image) // if there is an header, skip it image.fseek(header, SEEK_SET); image.fread(m_fds_data.get(), 65500 * m_fds_sides); - return; } void nes_disksys_device::unload_disk(device_image_interface &image) |