summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes/disksys.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nes/disksys.cpp')
-rw-r--r--src/devices/bus/nes/disksys.cpp132
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)