summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/vcs/scharger.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/vcs/scharger.c')
-rw-r--r--src/devices/bus/vcs/scharger.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/src/devices/bus/vcs/scharger.c b/src/devices/bus/vcs/scharger.c
new file mode 100644
index 00000000000..a3d90391ce9
--- /dev/null
+++ b/src/devices/bus/vcs/scharger.c
@@ -0,0 +1,214 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/***************************************************************************
+
+ Atari 2600 cart Starpath Supercharger (Cart + Tape drive!)
+
+
+
+ From kevtris notes ( http://blog.kevtris.org/blogfiles/Atari%202600%20Mappers.txt ):
+
+
+ - Control register [0x1ff8]
+
+ 7 0
+ ---------
+ 1FF8: DDDB BBWE
+
+ D: write delay (see below)
+ B: bankswitching mode (see below)
+ W: RAM write enable (1 = enabled, 0 = disabled)
+ E: ROM power enable (0 = enabled, 1 = turn off ROM)
+
+ - Audio input register [0x1ff9]
+
+ 7 0
+ ---------
+ 1FF9: 0000 000A
+
+ A: Supercharger audio data. 0 = low input, 1 = high input.
+
+
+***************************************************************************/
+
+
+#include "emu.h"
+#include "scharger.h"
+#include "sound/wave.h"
+#include "formats/a26_cas.h"
+
+const device_type A26_ROM_SUPERCHARGER = &device_creator<a26_rom_ss_device>;
+
+
+a26_rom_ss_device::a26_rom_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : a26_rom_f6_device(mconfig, A26_ROM_SUPERCHARGER, "Atari 2600 ROM Cart Supercharger", tag, owner, clock, "a2600_ss", __FILE__),
+ m_cassette(*this, "cassette")
+{
+}
+
+//-------------------------------------------------
+// mapper specific start/reset
+//-------------------------------------------------
+
+void a26_rom_ss_device::device_start()
+{
+ m_maincpu = machine().device<cpu_device>("maincpu");
+
+ save_item(NAME(m_base_banks));
+ save_item(NAME(m_reg));
+ save_item(NAME(m_write_delay));
+ save_item(NAME(m_ram_write_enabled));
+ save_item(NAME(m_rom_enabled));
+ save_item(NAME(m_byte_started));
+ save_item(NAME(m_last_address));
+ save_item(NAME(m_diff_adjust));
+}
+
+void a26_rom_ss_device::device_reset()
+{
+ // banks = 0, 1, 2 are 2K chunk of RAM (of the available 6K), banks = 3 is ROM!
+ m_base_banks[0] = 2;
+ m_base_banks[1] = 3;
+ m_ram_write_enabled = 0;
+ m_byte_started = 0;
+ m_reg = 0;
+ m_write_delay = 0;
+ m_rom_enabled = 1;
+ m_last_address = 0;
+ m_diff_adjust = 0;
+}
+
+
+static MACHINE_CONFIG_FRAGMENT( a26_ss )
+ MCFG_CASSETTE_ADD("cassette")
+ MCFG_CASSETTE_FORMATS(a26_cassette_formats)
+ MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED)
+ MCFG_CASSETTE_INTERFACE("a2600_cass")
+
+// MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
+// MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+MACHINE_CONFIG_END
+
+machine_config_constructor a26_rom_ss_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( a26_ss );
+}
+
+inline UINT8 a26_rom_ss_device::read_byte(UINT32 offset)
+{
+ if (offset < 0x800)
+ return m_ram[(offset & 0x7ff) + (m_base_banks[0] * 0x800)];
+ else if (m_base_banks[1] != 3)
+ return m_ram[(offset & 0x7ff) + (m_base_banks[1] * 0x800)];
+ else if (m_rom_enabled)
+ return m_rom[offset & 0x7ff];
+ else
+ return 0xff;
+}
+
+READ8_MEMBER(a26_rom_ss_device::read_rom)
+{
+ if (space.debugger_access())
+ return read_byte(offset);
+
+ // Bankswitch
+ if (offset == 0xff8)
+ {
+ //logerror("%04X: Access to control register data = %02X\n", m_maincpu->pc(), m_modeSS_byte);
+ m_write_delay = m_reg >> 5;
+ m_ram_write_enabled = BIT(m_reg, 1);
+ m_rom_enabled = !BIT(m_reg, 0);
+
+ // compensate time spent in this access to avoid spurious RAM write
+ m_byte_started -= 5;
+
+ // handle bankswitch
+ switch (m_reg & 0x1c)
+ {
+ case 0x00:
+ m_base_banks[0] = 2;
+ m_base_banks[1] = 3;
+ break;
+ case 0x04:
+ m_base_banks[0] = 0;
+ m_base_banks[1] = 3;
+ break;
+ case 0x08:
+ m_base_banks[0] = 2;
+ m_base_banks[1] = 0;
+ break;
+ case 0x0c:
+ m_base_banks[0] = 0;
+ m_base_banks[1] = 2;
+ break;
+ case 0x10:
+ m_base_banks[0] = 2;
+ m_base_banks[1] = 3;
+ break;
+ case 0x14:
+ m_base_banks[0] = 1;
+ m_base_banks[1] = 3;
+ break;
+ case 0x18:
+ m_base_banks[0] = 2;
+ m_base_banks[1] = 1;
+ break;
+ case 0x1c:
+ m_base_banks[0] = 1;
+ m_base_banks[1] = 2;
+ break;
+ }
+
+ return read_byte(offset);
+ }
+ // Cassette port read
+ else if (offset == 0xff9)
+ {
+ //logerror("%04X: Cassette port read, tap_val = %f\n", m_maincpu->pc(), tap_val);
+ double tap_val = m_cassette->input();
+
+ // compensate time spent in this access to avoid spurious RAM write
+ m_byte_started -= 5;
+
+ if (tap_val < 0)
+ return 0x00;
+ else
+ return 0x01;
+ }
+ // Possible RAM write
+ else
+ {
+ if (m_ram_write_enabled)
+ {
+ /* Check for dummy read from same address */
+ if (m_last_address == offset)
+ m_diff_adjust++;
+
+ int diff = m_maincpu->total_cycles() - m_byte_started;
+ //logerror("%04X: offset = %04X, %d\n", m_maincpu->pc(), offset, diff);
+
+ if (diff - m_diff_adjust == 5)
+ {
+ //logerror("%04X: RAM write offset = %04X, data = %02X\n", m_maincpu->pc(), offset, m_modeSS_byte );
+ if (offset < 0x800)
+ m_ram[(offset & 0x7ff) + (m_base_banks[0] * 0x800)] = m_reg;
+ else if (m_base_banks[1] != 3)
+ m_ram[(offset & 0x7ff) + (m_base_banks[1] * 0x800)] = m_reg;
+ }
+ else if (offset < 0x0100)
+ {
+ m_reg = offset;
+ m_byte_started = m_maincpu->total_cycles();
+ m_diff_adjust = 0;
+ }
+ }
+ else if (offset < 0x0100)
+ {
+ m_reg = offset;
+ m_byte_started = m_maincpu->total_cycles();
+ m_diff_adjust = 0;
+ }
+ m_last_address = offset;
+ return read_byte(offset);
+ }
+}