summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
author Robbbert <Robbbert@users.noreply.github.com>2021-09-28 19:48:10 +1000
committer Robbbert <Robbbert@users.noreply.github.com>2021-09-28 19:48:10 +1000
commit9c9b2f30bb67deefbfd869138e66d24bf277ebf1 (patch)
treee80413b96c44804155c20fc973b90f8939a8b1e9 /src
parent925646674ca492fcf01b3866085eb4cc734ee6fe (diff)
parent6b1057f205525c2de070b7002f91e063d5f6d074 (diff)
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/a2bus/a2sd.cpp2
-rw-r--r--src/devices/bus/a2bus/laser128.cpp32
-rw-r--r--src/devices/bus/a2bus/laser128.h16
-rw-r--r--src/devices/bus/nes/batlab.cpp4
-rw-r--r--src/devices/bus/nes/bootleg.cpp83
-rw-r--r--src/devices/bus/nes/bootleg.h27
-rw-r--r--src/devices/bus/nes/event.h6
-rw-r--r--src/devices/bus/nes/mmc1.cpp110
-rw-r--r--src/devices/bus/nes/mmc1.h32
-rw-r--r--src/devices/bus/nes/mmc3.cpp3
-rw-r--r--src/devices/bus/nes/mmc3_clones.cpp295
-rw-r--r--src/devices/bus/nes/mmc3_clones.h23
-rw-r--r--src/devices/bus/nes/multigame.cpp248
-rw-r--r--src/devices/bus/nes/multigame.h76
-rw-r--r--src/devices/bus/nes/nes_carts.cpp6
-rw-r--r--src/devices/bus/nes/nes_ines.hxx37
-rw-r--r--src/devices/bus/nes/nes_pcb.hxx24
-rw-r--r--src/devices/bus/nes/nes_slot.cpp1
-rw-r--r--src/devices/bus/nes/nes_slot.h17
-rw-r--r--src/devices/bus/nes/pirate.cpp4
-rw-r--r--src/devices/bus/ti99/gromport/cartridges.cpp24
-rw-r--r--src/devices/cpu/tms32082/dis_mp.cpp16
-rw-r--r--src/devices/cpu/tms32082/mp_ops.cpp213
-rw-r--r--src/devices/cpu/tms32082/tms32082.cpp147
-rw-r--r--src/devices/cpu/tms32082/tms32082.h3
-rw-r--r--src/devices/cpu/tx0/tx0.cpp256
-rw-r--r--src/devices/cpu/tx0/tx0.h23
-rw-r--r--src/devices/cpu/tx0/tx0dasm.cpp86
-rw-r--r--src/devices/cpu/tx0/tx0dasm.h13
-rw-r--r--src/devices/machine/8042kbdc.h2
-rw-r--r--src/devices/machine/clock.cpp3
-rw-r--r--src/devices/machine/smpc.cpp24
-rw-r--r--src/devices/machine/stvcd.cpp66
-rw-r--r--src/devices/sound/ics2115.cpp2
-rw-r--r--src/devices/video/upd3301.cpp537
-rw-r--r--src/devices/video/upd3301.h31
-rw-r--r--src/emu/validity.cpp8
-rw-r--r--src/frontend/mame/infoxml.cpp194
-rw-r--r--src/frontend/mame/ui/viewgfx.cpp2
-rw-r--r--src/lib/formats/rpk.cpp84
-rw-r--r--src/lib/formats/rpk.h28
-rw-r--r--src/lib/util/delegate.cpp129
-rw-r--r--src/mame/arcade.flt5
-rw-r--r--src/mame/drivers/4enraya.cpp4
-rw-r--r--src/mame/drivers/acesp.cpp4
-rw-r--r--src/mame/drivers/agat.cpp8
-rw-r--r--src/mame/drivers/ampoker2.cpp6
-rw-r--r--src/mame/drivers/apple2.cpp8
-rw-r--r--src/mame/drivers/apple2e.cpp214
-rw-r--r--src/mame/drivers/apple2gs.cpp2
-rw-r--r--src/mame/drivers/atarig42.cpp6
-rw-r--r--src/mame/drivers/barni.cpp16
-rw-r--r--src/mame/drivers/conchess.cpp16
-rw-r--r--src/mame/drivers/cybstorm.cpp4
-rw-r--r--src/mame/drivers/fidel_eag68k.cpp2
-rw-r--r--src/mame/drivers/konamigx.cpp31
-rw-r--r--src/mame/drivers/konmedal020.cpp2
-rw-r--r--src/mame/drivers/mpu4.cpp4
-rw-r--r--src/mame/drivers/naomi.cpp2
-rw-r--r--src/mame/drivers/olyboss.cpp7
-rw-r--r--src/mame/drivers/pc8001.cpp535
-rw-r--r--src/mame/drivers/pc8801.cpp278
-rw-r--r--src/mame/drivers/pc88va.cpp2
-rw-r--r--src/mame/drivers/rollext.cpp671
-rw-r--r--src/mame/drivers/saturn.cpp116
-rw-r--r--src/mame/drivers/segac2.cpp6
-rw-r--r--src/mame/drivers/spg2xx_jakks.cpp2
-rw-r--r--src/mame/drivers/tasc.cpp4
-rw-r--r--src/mame/drivers/tx0.cpp37
-rw-r--r--src/mame/includes/pc8001.h147
-rw-r--r--src/mame/includes/pc8801.h37
-rw-r--r--src/mame/includes/tx0.h1
-rw-r--r--src/mame/layout/ace_sp_dmd.lay2
-rw-r--r--src/mame/machine/ace_sp_reelctrl.cpp4
-rw-r--r--src/mame/machine/nes.cpp1
-rw-r--r--src/mame/machine/pc80s31k.cpp460
-rw-r--r--src/mame/machine/pc80s31k.h86
-rw-r--r--src/mame/mame.lst8
-rw-r--r--src/mame/video/apple2.cpp60
-rw-r--r--src/mame/video/apple2.h1
-rw-r--r--src/mame/video/kikikai.cpp57
-rw-r--r--src/mame/video/sknsspr.cpp2
-rw-r--r--src/osd/modules/debugger/debuggdbstub.cpp2
-rw-r--r--src/osd/modules/debugger/qt/debuggerview.cpp4
-rw-r--r--src/osd/modules/debugger/win/debugviewinfo.cpp4
-rw-r--r--src/tools/unidasm.cpp1
86 files changed, 3956 insertions, 1850 deletions
diff --git a/src/devices/bus/a2bus/a2sd.cpp b/src/devices/bus/a2bus/a2sd.cpp
index 7a5208e473f..3f9bd439bc6 100644
--- a/src/devices/bus/a2bus/a2sd.cpp
+++ b/src/devices/bus/a2bus/a2sd.cpp
@@ -9,7 +9,7 @@
AppleIISD has a Xilinx FPGA which implements a minimally hardware
assisted SPI interface, and the SD card is thus driven in SPI
- mode rather than SD.
+ mode rather than SD.
The SPI controller is fixed to SPI Mode 3 only.
(shift on falling CLK edges, shift-then-latch).
diff --git a/src/devices/bus/a2bus/laser128.cpp b/src/devices/bus/a2bus/laser128.cpp
index e0c7626aa93..bf0319751db 100644
--- a/src/devices/bus/a2bus/laser128.cpp
+++ b/src/devices/bus/a2bus/laser128.cpp
@@ -23,6 +23,7 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(A2BUS_LASER128, a2bus_laser128_device, "a2laser128", "VTech Laser 128 Internal Device")
+DEFINE_DEVICE_TYPE(A2BUS_LASER128_ORIG, a2bus_laser128_orig_device, "a2laser128o", "VTech Laser 128 Internal Device (original hardware)")
/***************************************************************************
FUNCTION PROTOTYPES
@@ -52,6 +53,11 @@ a2bus_laser128_device::a2bus_laser128_device(const machine_config &mconfig, cons
{
}
+a2bus_laser128_orig_device::a2bus_laser128_orig_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_laser128_device(mconfig, A2BUS_LASER128_ORIG, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -142,3 +148,29 @@ bool a2bus_laser128_device::take_c800()
return false;
}
}
+
+uint8_t a2bus_laser128_orig_device::read_c800(uint16_t offset)
+{
+ switch (slotno())
+ {
+ case 1:
+ return m_rom[(offset & 0x7ff) + 0x4800];
+
+ case 2:
+ return m_rom[(offset & 0x7ff) + 0x5800];
+
+ case 5:
+ return m_rom[(offset & 0x7ff) + 0x5000];
+
+ case 6:
+ return m_rom[(offset & 0x7ff) + 0x6800];
+
+ case 7:
+ if (offset < 0x400)
+ return m_slot7_ram[offset];
+ else
+ return m_rom[(offset & 0x3ff) + 0x6000 + m_slot7_bank];
+ }
+
+ return 0xff;
+}
diff --git a/src/devices/bus/a2bus/laser128.h b/src/devices/bus/a2bus/laser128.h
index a71f88e0c3d..3ea016ad983 100644
--- a/src/devices/bus/a2bus/laser128.h
+++ b/src/devices/bus/a2bus/laser128.h
@@ -42,13 +42,25 @@ protected:
virtual void write_c800(uint16_t offset, uint8_t data) override;
virtual bool take_c800() override;
-private:
uint8_t *m_rom;
uint8_t m_slot7_ram[0x800];
- int m_slot7_bank, m_slot7_ram_bank;
+ int m_slot7_bank;
+
+private:
+ int m_slot7_ram_bank;
+};
+
+class a2bus_laser128_orig_device: public a2bus_laser128_device
+{
+public:
+ a2bus_laser128_orig_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual uint8_t read_c800(uint16_t offset) override;
};
// device type definition
DECLARE_DEVICE_TYPE(A2BUS_LASER128, a2bus_laser128_device)
+DECLARE_DEVICE_TYPE(A2BUS_LASER128_ORIG, a2bus_laser128_orig_device)
#endif // MAME_BUS_A2BUS_LASER128_H
diff --git a/src/devices/bus/nes/batlab.cpp b/src/devices/bus/nes/batlab.cpp
index cc39fb95466..7f11696134d 100644
--- a/src/devices/bus/nes/batlab.cpp
+++ b/src/devices/bus/nes/batlab.cpp
@@ -188,7 +188,7 @@ u8 nes_batmap_srrx_device::read_dpcm()
u8 nes_batmap_srrx_device::read_l(offs_t offset)
{
-// LOG_MMC(("batmap_srrx read_l, offset: %04x", offset));
+// LOG_MMC(("batmap_srrx read_l, offset: %04x", offset));
offset += 0x100;
switch (offset & 0x1800)
@@ -204,7 +204,7 @@ u8 nes_batmap_srrx_device::read_l(offs_t offset)
u8 nes_batmap_srrx_device::read_m(offs_t offset)
{
-// LOG_MMC(("batmap_srrx read_m, offset: %04x", offset));
+// LOG_MMC(("batmap_srrx read_m, offset: %04x", offset));
return m_prg[(m_reg * 0x2000 + offset) & (m_prg_size - 1)];
}
diff --git a/src/devices/bus/nes/bootleg.cpp b/src/devices/bus/nes/bootleg.cpp
index 4382bf7ec43..842b932869f 100644
--- a/src/devices/bus/nes/bootleg.cpp
+++ b/src/devices/bus/nes/bootleg.cpp
@@ -53,6 +53,7 @@ DEFINE_DEVICE_TYPE(NES_SMB2JB, nes_smb2jb_device, "nes_smb2jb", "N
DEFINE_DEVICE_TYPE(NES_N32_4IN1, nes_n32_4in1_device, "nes_n32_4in1", "NES Cart N-32 4 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_0353, nes_0353_device, "nes_0353", "NES Cart 0353 PCB")
DEFINE_DEVICE_TYPE(NES_09034A, nes_09034a_device, "nes_09034a", "NES Cart 09-034A PCB")
+DEFINE_DEVICE_TYPE(NES_L001, nes_l001_device, "nes_l001", "NES Cart L-001 PCB")
DEFINE_DEVICE_TYPE(NES_BATMANFS, nes_batmanfs_device, "nes_batmanfs", "NES Cart Batman Pirate PCB")
DEFINE_DEVICE_TYPE(NES_PALTHENA, nes_palthena_device, "nes_palthena", "NES Cart Palthena no Kagami Pirate PCB")
DEFINE_DEVICE_TYPE(NES_TOBIDASE, nes_tobidase_device, "nes_tobidase", "NES Cart Tobidase Daisakusen Pirate PCB")
@@ -144,6 +145,11 @@ nes_09034a_device::nes_09034a_device(const machine_config &mconfig, const char *
{
}
+nes_l001_device::nes_l001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_L001, tag, owner, clock), m_irq_count(0), irq_timer(nullptr)
+{
+}
+
nes_batmanfs_device::nes_batmanfs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BATMANFS, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
{
@@ -499,6 +505,23 @@ void nes_09034a_device::pcb_reset()
m_reg = 0;
}
+void nes_l001_device::device_start()
+{
+ common_start();
+ irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_irq_count));
+}
+
+void nes_l001_device::pcb_reset()
+{
+ prg32((m_prg_chunks >> 1) - 1);
+ chr8(0, CHRROM);
+
+ m_irq_count = 0;
+}
+
void nes_palthena_device::device_start()
{
common_start();
@@ -1550,6 +1573,64 @@ u8 nes_09034a_device::read_m(offs_t offset)
/*-------------------------------------------------
+ Board L-001
+
+ Games: Sangokushi III (Sangokushi II bootleg)
+
+ This board has swappable 8K PRG banks at 0x8000, 0xa000,
+ and 0xc000, while 0xe000 is fixed to the final bank.
+ CHRROM and CIRAM are also swappable in 1K banks.
+ The board has a 16-bit IRQ counter with the enable bit
+ acting as the MSB. The enhanced audio of the original
+ Namco 163 board is not retained.
+
+ NES 2.0: mapper 330
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_l001_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (id == TIMER_IRQ)
+ {
+ if (BIT(m_irq_count, 15))
+ {
+ if (++m_irq_count == 0)
+ set_irq_line(ASSERT_LINE);
+ }
+ }
+}
+
+void nes_l001_device::write_h(offs_t offset, u8 data)
+{
+ LOG_MMC(("l-001 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6400)
+ {
+ case 0x0000:
+ case 0x2000:
+ chr1_x((offset >> 11) & 0x07, data, CHRROM);
+ break;
+ case 0x0400:
+ m_irq_count = (m_irq_count & 0xff00) | data;
+ break;
+ case 0x2400:
+ m_irq_count = (m_irq_count & 0x00ff) | data << 8;
+ set_irq_line(CLEAR_LINE);
+ break;
+ case 0x4000:
+ set_nt_page((offset >> 11) & 0x03, CIRAM, data & 1, 1);
+ break;
+ case 0x6000:
+ if (offset < 0x7800)
+ prg8_x((offset >> 11) & 0x03, data & 0x1f);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
BTL-BATMANFS
Games: Batman "Fine Studio" pirate
@@ -2207,7 +2288,7 @@ void nes_shuiguan_device::write_h(offs_t offset, uint8_t data)
{
case 0x00: m_irq_count = (m_irq_count & 0xf0) | ((data & 0x0f) << 0); break;
case 0x04: m_irq_count = (m_irq_count & 0x0f) | ((data & 0x0f) << 4); break;
- case 0x08: m_irq_enable= data; break;
+ case 0x08: m_irq_enable = data; break;
case 0x0c: break;
}
break;
diff --git a/src/devices/bus/nes/bootleg.h b/src/devices/bus/nes/bootleg.h
index 7eeaaaf2ff9..081173d3e2e 100644
--- a/src/devices/bus/nes/bootleg.h
+++ b/src/devices/bus/nes/bootleg.h
@@ -320,6 +320,31 @@ private:
};
+// ======================> nes_l001_device
+
+class nes_l001_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_l001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+private:
+ u16 m_irq_count;
+
+ static const device_timer_id TIMER_IRQ = 0;
+ emu_timer *irq_timer;
+};
+
+
// ======================> nes_batmanfs_device
class nes_batmanfs_device : public nes_nrom_device
@@ -327,6 +352,7 @@ class nes_batmanfs_device : public nes_nrom_device
public:
// construction/destruction
nes_batmanfs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
@@ -751,6 +777,7 @@ DECLARE_DEVICE_TYPE(NES_SMB2JB, nes_smb2jb_device)
DECLARE_DEVICE_TYPE(NES_N32_4IN1, nes_n32_4in1_device)
DECLARE_DEVICE_TYPE(NES_0353, nes_0353_device)
DECLARE_DEVICE_TYPE(NES_09034A, nes_09034a_device)
+DECLARE_DEVICE_TYPE(NES_L001, nes_l001_device)
DECLARE_DEVICE_TYPE(NES_BATMANFS, nes_batmanfs_device)
DECLARE_DEVICE_TYPE(NES_PALTHENA, nes_palthena_device)
DECLARE_DEVICE_TYPE(NES_TOBIDASE, nes_tobidase_device)
diff --git a/src/devices/bus/nes/event.h b/src/devices/bus/nes/event.h
index b4b67614b50..c1ba24d179d 100644
--- a/src/devices/bus/nes/event.h
+++ b/src/devices/bus/nes/event.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
-#ifndef MAEM_BUS_NES_EVENT_H
-#define MAEM_BUS_NES_EVENT_H
+#ifndef MAME_BUS_NES_EVENT_H
+#define MAME_BUS_NES_EVENT_H
#pragma once
@@ -46,4 +46,4 @@ protected:
// device type definition
DECLARE_DEVICE_TYPE(NES_EVENT, nes_event_device)
-#endif // MAEM_BUS_NES_EVENT_H
+#endif // MAME_BUS_NES_EVENT_H
diff --git a/src/devices/bus/nes/mmc1.cpp b/src/devices/bus/nes/mmc1.cpp
index cb752cb0754..8c8e7bc31bd 100644
--- a/src/devices/bus/nes/mmc1.cpp
+++ b/src/devices/bus/nes/mmc1.cpp
@@ -16,6 +16,9 @@
TODO:
- Combine 2 versions of set_prg in SxROM base class. This means dealing with
variant boards SNROM, SUROM, etc which repurpose bits in the MMC1 regs.
+ - Determine if "MMC1" marked chips, the earliest version, ignores WRAM
+ enable/disable bit like its first revision, MMC1A. Also determine if MMC1C
+ really exists. It's described by kevtris, but it's not in BootGod's DB.
***********************************************************************************************************/
@@ -36,10 +39,8 @@
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_SXROM, nes_sxrom_device, "nes_sxrom", "NES Cart SxROM (MMC-1) PCB")
-DEFINE_DEVICE_TYPE(NES_SOROM, nes_sorom_device, "nes_sorom", "NES Cart SOROM (MMC-1) PCB")
-DEFINE_DEVICE_TYPE(NES_SXROM_A, nes_sxrom_a_device, "nes_sxrom_a", "NES Cart SxROM (MMC-1A) PCB")
-DEFINE_DEVICE_TYPE(NES_SOROM_A, nes_sorom_a_device, "nes_sorom_a", "NES Cart SOROM (MMC-1A) PCB")
+DEFINE_DEVICE_TYPE(NES_SXROM, nes_sxrom_device, "nes_sxrom", "NES Cart SxROM (MMC-1) PCB")
+DEFINE_DEVICE_TYPE(NES_SOROM, nes_sorom_device, "nes_sorom", "NES Cart SOROM (MMC-1) PCB")
@@ -58,16 +59,6 @@ nes_sorom_device::nes_sorom_device(const machine_config &mconfig, const char *ta
{
}
-nes_sxrom_a_device::nes_sxrom_a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_sxrom_device(mconfig, NES_SXROM_A, tag, owner, clock)
-{
-}
-
-nes_sorom_a_device::nes_sorom_a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_sxrom_device(mconfig, NES_SOROM_A, tag, owner, clock)
-{
-}
-
void nes_sxrom_device::device_start()
@@ -86,7 +77,8 @@ void nes_sxrom_device::pcb_reset()
m_latch = 0;
m_count = 0;
m_reg[0] = 0x0f;
- m_reg[1] = m_reg[2] = m_reg[3] = 0;
+ m_reg[1] = m_reg[2] = 0;
+ m_reg[3] = m_mmc1_type == mmc1_type::MMC1C ? 0x10 : 0x00; // WRAM disabled by default on MMC1C
m_reg_write_enable = 1;
set_nt_mirroring(PPU_MIRROR_HORZ);
@@ -94,35 +86,6 @@ void nes_sxrom_device::pcb_reset()
set_prg();
}
-void nes_sorom_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_latch = 0;
- m_count = 0;
- m_reg[0] = 0x0f;
- m_reg[1] = m_reg[2] = m_reg[3] = 0;
- m_reg_write_enable = 1;
-
- set_nt_mirroring(PPU_MIRROR_HORZ);
- set_chr();
- set_prg();
-}
-
-void nes_sorom_a_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_latch = 0;
- m_count = 0;
- m_reg[0] = 0x0f;
- m_reg[1] = m_reg[2] = m_reg[3] = 0;
- m_reg_write_enable = 1;
-
- set_nt_mirroring(PPU_MIRROR_HORZ);
- set_chr();
- set_prg();
-}
@@ -295,7 +258,7 @@ void nes_sxrom_device::write_m(offs_t offset, uint8_t data)
uint8_t bank = (m_reg[1] >> 2) & 3;
LOG_MMC(("sxrom write_m, offset: %04x, data: %02x\n", offset, data));
- if (!BIT(m_reg[3], 4)) // WRAM enabled
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
if (!m_battery.empty())
m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)] = data;
@@ -309,7 +272,7 @@ uint8_t nes_sxrom_device::read_m(offs_t offset)
uint8_t bank = (m_reg[1] >> 2) & 3;
LOG_MMC(("sxrom read_m, offset: %04x\n", offset));
- if (!BIT(m_reg[3], 4)) // WRAM enabled
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
if (!m_battery.empty())
return m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)];
@@ -317,7 +280,7 @@ uint8_t nes_sxrom_device::read_m(offs_t offset)
return m_prgram[((bank * 0x2000) + offset) & (m_prgram.size() - 1)];
}
- return get_open_bus(); // open bus
+ return get_open_bus();
}
// SOROM has two RAM banks, the first is not battery backed up, the second is.
@@ -326,7 +289,7 @@ void nes_sorom_device::write_m(offs_t offset, uint8_t data)
uint8_t type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
LOG_MMC(("sorom write_m, offset: %04x, data: %02x\n", offset, data));
- if (!BIT(m_reg[3], 4)) // WRAM enabled
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
if (type)
m_battery[offset & (m_battery.size() - 1)] = data;
@@ -340,7 +303,7 @@ uint8_t nes_sorom_device::read_m(offs_t offset)
uint8_t type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
LOG_MMC(("sorom read_m, offset: %04x\n", offset));
- if (!BIT(m_reg[3], 4)) // WRAM enabled
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
if (type)
return m_battery[offset & (m_battery.size() - 1)];
@@ -348,52 +311,5 @@ uint8_t nes_sorom_device::read_m(offs_t offset)
return m_prgram[offset & (m_prgram.size() - 1)];
}
- return get_open_bus(); // open bus
-}
-
-// MMC1A boards have no wram enable/disable bit
-void nes_sxrom_a_device::write_m(offs_t offset, uint8_t data)
-{
- uint8_t bank = (m_reg[1] >> 2) & 3;
- LOG_MMC(("sxrom_a write_m, offset: %04x, data: %02x\n", offset, data));
-
- if (!m_battery.empty())
- m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)] = data;
- if (!m_prgram.empty())
- m_prgram[((bank * 0x2000) + offset) & (m_prgram.size() - 1)] = data;
-}
-
-uint8_t nes_sxrom_a_device::read_m(offs_t offset)
-{
- uint8_t bank = (m_reg[1] >> 2) & 3;
- LOG_MMC(("sxrom_a read_m, offset: %04x\n", offset));
-
- if (!m_battery.empty())
- return m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)];
- if (!m_prgram.empty())
- return m_prgram[((bank * 0x2000) + offset) & (m_prgram.size() - 1)];
-
- return get_open_bus(); // open bus
-}
-
-void nes_sorom_a_device::write_m(offs_t offset, uint8_t data)
-{
- uint8_t type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
- LOG_MMC(("sorom_a write_m, offset: %04x, data: %02x\n", offset, data));
-
- if (type)
- m_battery[offset & (m_battery.size() - 1)] = data;
- else
- m_prgram[offset & (m_prgram.size() - 1)] = data;
-}
-
-uint8_t nes_sorom_a_device::read_m(offs_t offset)
-{
- uint8_t type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
- LOG_MMC(("sorom_a read_m, offset: %04x\n", offset));
-
- if (type)
- return m_battery[offset & (m_battery.size() - 1)];
- else
- return m_prgram[offset & (m_prgram.size() - 1)];
+ return get_open_bus();
}
diff --git a/src/devices/bus/nes/mmc1.h b/src/devices/bus/nes/mmc1.h
index bc2198c33aa..dbf234f734f 100644
--- a/src/devices/bus/nes/mmc1.h
+++ b/src/devices/bus/nes/mmc1.h
@@ -34,7 +34,7 @@ protected:
void set_prg(int prg_base, int prg_mask);
void set_chr(int chr_base, int chr_mask);
virtual void set_prg();
-// virtual void set_prg() { set_prg(0x00, 0x0f); }
+// virtual void set_prg() { set_prg(0x00, 0x0f); }
virtual void set_chr() { set_chr(0x00, 0x1f); }
uint8_t m_reg[4];
@@ -51,37 +51,11 @@ public:
virtual uint8_t read_m(offs_t offset) override;
virtual void write_m(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-};
-
-class nes_sxrom_a_device : public nes_sxrom_device
-{
-public:
- // construction/destruction
- nes_sxrom_a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
-};
-
-class nes_sorom_a_device : public nes_sxrom_device
-{
-public:
- // construction/destruction
- nes_sorom_a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
};
// device type definition
-DECLARE_DEVICE_TYPE(NES_SXROM, nes_sxrom_device)
-DECLARE_DEVICE_TYPE(NES_SOROM, nes_sorom_device)
-DECLARE_DEVICE_TYPE(NES_SXROM_A, nes_sxrom_a_device)
-DECLARE_DEVICE_TYPE(NES_SOROM_A, nes_sorom_a_device)
+DECLARE_DEVICE_TYPE(NES_SXROM, nes_sxrom_device)
+DECLARE_DEVICE_TYPE(NES_SOROM, nes_sorom_device)
#endif // MAME_BUS_NES_MMC1_H
diff --git a/src/devices/bus/nes/mmc3.cpp b/src/devices/bus/nes/mmc3.cpp
index d6f7f37dc4a..dfc57f59b71 100644
--- a/src/devices/bus/nes/mmc3.cpp
+++ b/src/devices/bus/nes/mmc3.cpp
@@ -283,7 +283,8 @@ void nes_txrom_device::txrom_write(offs_t offset, uint8_t data)
break;
case 0x2000:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ if (m_mirroring != PPU_MIRROR_4SCREEN)
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
case 0x2001:
diff --git a/src/devices/bus/nes/mmc3_clones.cpp b/src/devices/bus/nes/mmc3_clones.cpp
index 322d35bdacd..82e3d0abfaf 100644
--- a/src/devices/bus/nes/mmc3_clones.cpp
+++ b/src/devices/bus/nes/mmc3_clones.cpp
@@ -50,7 +50,7 @@ DEFINE_DEVICE_TYPE(NES_SF3, nes_sf3_device, "nes_sf3",
DEFINE_DEVICE_TYPE(NES_GOUDER, nes_gouder_device, "nes_gouder", "NES Cart Gouder PCB")
DEFINE_DEVICE_TYPE(NES_SA9602B, nes_sa9602b_device, "nes_sa9602b", "NES Cart SA-9602B PCB")
DEFINE_DEVICE_TYPE(NES_SACHEN_SHERO, nes_sachen_shero_device, "nes_shero", "NES Cart Street Hero PCB")
-//DEFINE_DEVICE_TYPE(NES_A9746, nes_a9746_device, "nes_bmc_a9746", "NES Cart A-9746 PCB")
+DEFINE_DEVICE_TYPE(NES_A9746, nes_a9746_device, "nes_bmc_a9746", "NES Cart A-9746 PCB")
DEFINE_DEVICE_TYPE(NES_A88S1, nes_a88s1_device, "nes_a88s1", "NES Cart BMC A88S-1 PCB")
DEFINE_DEVICE_TYPE(NES_FCGJ8IN1, nes_fcgj8in1_device, "nes_fcgj8in1", "NES Cart BMC FC Genjin 8 in 1 PCB")
@@ -83,6 +83,29 @@ DEFINE_DEVICE_TYPE(NES_PJOY84, nes_pjoy84_device, "nes_pjoy84",
DEFINE_DEVICE_TYPE(NES_COOLBOY, nes_coolboy_device, "nes_coolboy", "NES Cart CoolBoy PCB")
+INPUT_PORTS_START( sachen_shero )
+ PORT_START("JUMPER")
+ PORT_CONFNAME( 0x80, 0x00, "Title Screen" )
+ PORT_CONFSETTING( 0x00, "Street Heroes" )
+ PORT_CONFSETTING( 0x80, u8"\u4f8d\u9b42 (Shìhún)" ) // 侍魂
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_sachen_shero_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( sachen_shero );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
nes_nitra_device::nes_nitra_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_txrom_device(mconfig, NES_NITRA, tag, owner, clock)
{
@@ -203,15 +226,17 @@ nes_sa9602b_device::nes_sa9602b_device(const machine_config &mconfig, const char
{
}
-nes_sachen_shero_device::nes_sachen_shero_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_SACHEN_SHERO, tag, owner, clock), m_reg(0)
+nes_sachen_shero_device::nes_sachen_shero_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_SACHEN_SHERO, tag, owner, clock)
+ , m_jumper(*this, "JUMPER")
+ , m_reg(0)
{
}
-//nes_a9746_device::nes_a9746_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-// : nes_txrom_device(mconfig, NES_A9746, tag, owner, clock)
-//{
-//}
+nes_a9746_device::nes_a9746_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : nes_txrom_device(mconfig, NES_A9746, tag, owner, clock)
+{
+}
nes_a88s1_device::nes_a88s1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_A88S1, tag, owner, clock)
@@ -278,8 +303,8 @@ nes_bmc_8in1_device::nes_bmc_8in1_device(const machine_config &mconfig, const ch
{
}
-nes_bmc_15in1_device::nes_bmc_15in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_BMC_15IN1, tag, owner, clock)
+nes_bmc_15in1_device::nes_bmc_15in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_15IN1, tag, owner, clock), m_jumper(0)
{
}
@@ -533,7 +558,23 @@ void nes_sachen_shero_device::pcb_reset()
m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
m_reg = 0;
- mmc3_common_initialize(0xff, 0x1ff, 0);
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_a9746_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_a9746_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg[0] = 0;
+ m_reg[1] = 0;
+ m_reg[2] = 0;
+ mmc3_common_initialize(0x7f, 0xff, 0);
}
void nes_a88s1_device::device_start()
@@ -657,10 +698,7 @@ void nes_bmc_8in1_device::pcb_reset()
void nes_bmc_15in1_device::pcb_reset()
{
m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
mmc3_common_initialize(0x1f, 0xff, 0);
- m_prg_base = 0x10; // this board has a diff prg_base
- set_prg(m_prg_base, m_prg_mask);
}
void nes_bmc_sbig7_device::pcb_reset()
@@ -1874,22 +1912,21 @@ void nes_sa9602b_device::write_h(offs_t offset, uint8_t data)
Sachen boards used for Street Heroes
- in MESS: Very Preliminary support
+ NES 2.0: mapper 262
- -------------------------------------------------*/
+ In MAME: Supported.
+ -------------------------------------------------*/
-void nes_sachen_shero_device::chr_cb( int start, int bank, int source )
+void nes_sachen_shero_device::chr_cb(int start, int bank, int source)
{
- int shift = start < 2 ? 5 :
- start < 4 ? 6 :
- start < 6 ? 8 : 7;
+ static constexpr u8 shift[4] = {5, 6, 8, 7};
+
if (!BIT(m_reg, 6))
- chr1_x(start, ((m_reg << shift) & 0x100) | bank, source);
+ chr1_x(start, ((m_reg << shift[start >> 1]) & 0x100) | bank, source);
}
-
-void nes_sachen_shero_device::write_l(offs_t offset, uint8_t data)
+void nes_sachen_shero_device::write_l(offs_t offset, u8 data)
{
LOG_MMC(("shero write_l, offset: %04x, data: %02x\n", offset, data));
offset += 0x4100;
@@ -1904,16 +1941,90 @@ void nes_sachen_shero_device::write_l(offs_t offset, uint8_t data)
}
}
-uint8_t nes_sachen_shero_device::read_l(offs_t offset)
+u8 nes_sachen_shero_device::read_l(offs_t offset)
{
LOG_MMC(("shero read_l, offset: %04x\n", offset));
offset += 0x4100;
if (offset == 0x4100)
+ return m_jumper->read();
+ else
+ return get_open_bus();
+}
+
+/*-------------------------------------------------
+
+ UNL-A9746
+
+ Games: Toy Story, Super 1997 4 in 1 (NT-8029)
+
+ MMC3 clone
+
+ iNES: mapper 219
+
+ Preliminary emulation based on Cah4e3's code
+
+ -------------------------------------------------*/
+
+void nes_a9746_device::update_banks(uint8_t value)
+{
+ uint8_t bank = bitswap<8>(value & 0x3c,7,6,0,1,2,3,4,5);
+
+ switch (m_reg[0])
{
- // DSW read!
+ case 0x26: prg8_89(bank); break;
+ case 0x25: prg8_ab(bank); break;
+ case 0x24: prg8_cd(bank); break;
+ case 0x23: prg8_ef(bank); break;
+ }
+
+ switch (m_reg[1])
+ {
+ case 0x08: case 0x0a: case 0x0c: case 0x0e:
+ case 0x10: case 0x12: case 0x14: case 0x16:
+ case 0x18: case 0x1a: case 0x1c: case 0x1e:
+ m_reg[2] = (value << 4);
+ break;
+ case 0x09: chr1_0(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x0b: chr1_1(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
+ case 0x0d: chr1_2(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x0f: chr1_3(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
+ case 0x11: chr1_4(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x15: chr1_5(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x19: chr1_6(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x1d: chr1_7(m_reg[2] | (value >> 1), m_chr_source); break;
+ }
+}
+
+void nes_a9746_device::write_h(offs_t offset, uint8_t data)
+{
+ LOG_MMC(("unl_a9746 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6003)
+ {
+ case 0x0000:
+ m_reg[1] = data;
+ m_reg[0] = 0;
+ break;
+ case 0x0001:
+ update_banks(data);
+ break;
+ case 0x0002:
+ m_reg[0] = data;
+ m_reg[1] = 0;
+ break;
+
+ case 0x0003:
+ case 0x2000:
+ case 0x2001:
+ case 0x2002:
+ case 0x2003:
+ break;
+
+ default:
+ txrom_write(offset, data);
+ break;
}
- return get_open_bus(); // open bus
}
@@ -1924,16 +2035,16 @@ uint8_t nes_sachen_shero_device::read_l(offs_t offset)
-------------------------------------------------*/
- /*-------------------------------------------------
+/*-------------------------------------------------
- Board BMC-FK23C
+ Board BMC-FK23C
- MMC3 clone
+ MMC3 clone
- In MESS: partially supported (still to sort initial banking
- for many games)
+ In MAME: partially supported (still to sort initial banking
+ for many games)
- -------------------------------------------------*/
+ -------------------------------------------------*/
#if 0
// alt version...
@@ -2235,30 +2346,32 @@ void nes_bmc_8in1_device::write_h(offs_t offset, u8 data)
/*-------------------------------------------------
- BMC-15IN1
+ BMC-15IN1 (PCB JC-016-2?)
- Unknown Bootleg Multigame Board
Games: 3 in 1, 15 in 1
- iNES: mapper 205, MMC3 clone
+ MMC3 clone with banking for multigame menu.
- In MESS: Supported.
+ iNES: mapper 205
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_15in1_device::write_m(offs_t offset, uint8_t data)
+void nes_bmc_15in1_device::write_m(offs_t offset, u8 data)
{
LOG_MMC(("bmc_15in1 write_m, offset: %04x, data: %02x\n", offset, data));
- if (offset & 0x0800)
- {
- m_prg_base = (data & 0x03) << 4;
- m_prg_mask = (data & 0x02) ? 0x0f : 0x1f;
- m_chr_base = (data & 0x03) << 7;
- m_chr_mask = (data & 0x02) ? 0x7f : 0xff;
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
- }
+ if (data & 1)
+ data |= m_jumper; // TODO: add jumper settings, m_jumper is 0 for now
+
+ m_prg_base = (data & 0x03) << 4;
+ m_prg_mask = 0x1f >> BIT(data, 1);
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = m_prg_base << 3;
+ m_chr_mask = 0xff >> BIT(data, 1);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
/*-------------------------------------------------
@@ -3052,95 +3165,3 @@ void nes_coolboy_device::write_m(offs_t offset, uint8_t data)
set_chr(m_chr_source, m_chr_base, m_chr_mask);
set_prg(m_prg_base, m_prg_mask);
}
-
-#ifdef UNUSED_FUNCTION
-/*-------------------------------------------------
-
- UNL-A9746
-
-
- MMC3 clone
-
-
- Preliminary emulation based on Cah4e3's code
- No dump is available (yet) for this.
-
- -------------------------------------------------*/
-
-void nes_a9746_device::device_start()
-{
- mmc3_start();
- save_item(NAME(m_reg));
-}
-
-void nes_a9746_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_reg[0] = 0;
- m_reg[1] = 0;
- m_reg[2] = 0;
- mmc3_common_initialize(0x7f, 0xff, 0);
-}
-
-void nes_a9746_device::update_banks(uint8_t value)
-{
- uint8_t bank = bitswap<8>(value & 0x3c,7,6,0,1,2,3,4,5);
-
- switch (m_reg[0])
- {
- case 0x26: prg8_89(bank); break;
- case 0x25: prg8_ab(bank); break;
- case 0x24: prg8_cd(bank); break;
- case 0x23: prg8_ef(bank); break;
- }
-
- switch (m_reg[1])
- {
- case 0x08: case 0x0a: case 0x0c: case 0x0e:
- case 0x10: case 0x12: case 0x14: case 0x16:
- case 0x18: case 0x1a: case 0x1c: case 0x1e:
- m_reg[2] = (value << 4);
- break;
- case 0x09: chr1_0(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x0b: chr1_1(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
- case 0x0d: chr1_2(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x0f: chr1_3(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
- case 0x11: chr1_4(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x15: chr1_5(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x19: chr1_6(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x1d: chr1_7(m_reg[2] | (value >> 1), m_chr_source); break;
- }
-}
-
-void nes_a9746_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("unl_a9746 write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x6003)
- {
- case 0x0000:
- m_reg[1] = data;
- m_reg[0] = 0;
- break;
- case 0x0001:
- update_banks(data);
- break;
- case 0x0002:
- m_reg[0] = data;
- m_reg[1] = 0;
- break;
-
- case 0x0003:
- case 0x2000:
- case 0x2001:
- case 0x2002:
- case 0x2003:
- break;
-
- default:
- txrom_write(offset, data);
- break;
- }
-}
-#endif
diff --git a/src/devices/bus/nes/mmc3_clones.h b/src/devices/bus/nes/mmc3_clones.h
index 201c82efca7..08822d6a7f2 100644
--- a/src/devices/bus/nes/mmc3_clones.h
+++ b/src/devices/bus/nes/mmc3_clones.h
@@ -412,23 +412,24 @@ class nes_sachen_shero_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_sachen_shero_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_sachen_shero_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_l(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
virtual void chr_cb(int start, int bank, int source) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
+ virtual ioport_constructor device_input_ports() const override;
virtual void device_start() override;
private:
- uint8_t m_reg;
+ required_ioport m_jumper;
+ u8 m_reg;
};
-#ifdef UNUSED_FUNCTION
// ======================> nes_a9746_device
class nes_a9746_device : public nes_txrom_device
@@ -439,7 +440,7 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void pcb_reset();
+ virtual void pcb_reset() override;
protected:
// device-level overrides
@@ -449,7 +450,6 @@ private:
void update_banks(uint8_t value);
uint8_t m_reg[3];
};
-#endif
// ======================> nes_a88s1_device
@@ -651,12 +651,15 @@ class nes_bmc_15in1_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_bmc_15in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_15in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// device-level overrides
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
+
+private:
+ u8 m_jumper;
};
@@ -1018,9 +1021,7 @@ DECLARE_DEVICE_TYPE(NES_SF3, nes_sf3_device)
DECLARE_DEVICE_TYPE(NES_GOUDER, nes_gouder_device)
DECLARE_DEVICE_TYPE(NES_SA9602B, nes_sa9602b_device)
DECLARE_DEVICE_TYPE(NES_SACHEN_SHERO, nes_sachen_shero_device)
-#ifdef UNUSED_FUNCTION
DECLARE_DEVICE_TYPE(NES_A9746, nes_a9746_device)
-#endif
DECLARE_DEVICE_TYPE(NES_A88S1, nes_a88s1_device)
DECLARE_DEVICE_TYPE(NES_FCGJ8IN1, nes_fcgj8in1_device)
diff --git a/src/devices/bus/nes/multigame.cpp b/src/devices/bus/nes/multigame.cpp
index 58679f5ea1e..71793333747 100644
--- a/src/devices/bus/nes/multigame.cpp
+++ b/src/devices/bus/nes/multigame.cpp
@@ -66,7 +66,8 @@ DEFINE_DEVICE_TYPE(NES_BMC_HIK300, nes_bmc_hik300_device, "nes_bmc_hik30
DEFINE_DEVICE_TYPE(NES_BMC_S700, nes_bmc_s700_device, "nes_bmc_s700", "NES Cart BMC Super 700 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_BALL11, nes_bmc_ball11_device, "nes_bmc_ball11", "NES Cart BMC Ball 11 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_22GAMES, nes_bmc_22games_device, "nes_bmc_22games", "NES Cart BMC 22 Games PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_64Y2K, nes_bmc_64y2k_device, "nes_bmc_64y2k", "NES Cart BMC 64 in 1 Y2K PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_64Y2K, nes_bmc_64y2k_device, "nes_bmc_64y2k", "NES Cart BMC Y2K 64 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_420Y2K, nes_bmc_420y2k_device, "nes_bmc_420y2k", "NES Cart BMC Y2K 420 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_12IN1, nes_bmc_12in1_device, "nes_bmc_12in1", "NES Cart BMC 12 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_20IN1, nes_bmc_20in1_device, "nes_bmc_20in1", "NES Cart BMC 20 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_21IN1, nes_bmc_21in1_device, "nes_bmc_21in1", "NES Cart BMC 21 in 1 PCB")
@@ -305,6 +306,11 @@ nes_bmc_64y2k_device::nes_bmc_64y2k_device(const machine_config &mconfig, const
{
}
+nes_bmc_420y2k_device::nes_bmc_420y2k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_420Y2K, tag, owner, clock), m_latch(0), m_reg(0)
+{
+}
+
nes_bmc_12in1_device::nes_bmc_12in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_BMC_12IN1, tag, owner, clock)
{
@@ -340,8 +346,18 @@ nes_bmc_64in1_device::nes_bmc_64in1_device(const machine_config &mconfig, const
{
}
-nes_bmc_70in1_device::nes_bmc_70in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_70IN1, tag, owner, clock), m_mode(0)
+nes_bmc_70in1_device::nes_bmc_70in1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_jumper(type == NES_BMC_70IN1 ? 0x0d : 0x06)
+{
+}
+
+nes_bmc_70in1_device::nes_bmc_70in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_70in1_device(mconfig, NES_BMC_70IN1, tag, owner, clock)
+{
+}
+
+nes_bmc_800in1_device::nes_bmc_800in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_70in1_device(mconfig, NES_BMC_800IN1, tag, owner, clock)
{
}
@@ -365,11 +381,6 @@ nes_bmc_500in1_device::nes_bmc_500in1_device(const machine_config &mconfig, cons
{
}
-nes_bmc_800in1_device::nes_bmc_800in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_800IN1, tag, owner, clock), m_mode(0)
-{
-}
-
nes_bmc_1200in1_device::nes_bmc_1200in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_BMC_1200IN1, tag, owner, clock), m_vram_protect(0)
{
@@ -819,6 +830,23 @@ void nes_bmc_64y2k_device::pcb_reset()
set_nt_mirroring(PPU_MIRROR_VERT);
}
+void nes_bmc_420y2k_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_latch));
+ save_item(NAME(m_reg));
+}
+
+void nes_bmc_420y2k_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(7);
+ chr8(0, CHRRAM);
+
+ m_latch = 0;
+ m_reg = 0;
+}
+
void nes_bmc_12in1_device::device_start()
{
common_start();
@@ -878,18 +906,16 @@ void nes_bmc_64in1_device::pcb_reset()
void nes_bmc_70in1_device::device_start()
{
common_start();
- save_item(NAME(m_reg));
- save_item(NAME(m_mode));
+ save_item(NAME(m_latch));
}
void nes_bmc_70in1_device::pcb_reset()
{
- prg16_89ab(m_prg_chunks - 1);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, CHRROM);
- m_reg[0] = 0;
- m_reg[1] = 0;
- m_mode = 0;
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ chr8(0, m_chr_source);
+
+ m_latch[0] = m_latch[1] = 0;
+ update_banks();
}
void nes_bmc_72in1_device::device_start()
@@ -919,24 +945,6 @@ void nes_bmc_150in1_device::pcb_reset()
chr8(0, CHRROM);
}
-void nes_bmc_800in1_device::device_start()
-{
- common_start();
- save_item(NAME(m_reg));
- save_item(NAME(m_mode));
-}
-
-void nes_bmc_800in1_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(m_prg_chunks - 1);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
- m_reg[0] = 0;
- m_reg[1] = 0;
- m_mode = 0;
-}
-
void nes_bmc_1200in1_device::device_start()
{
common_start();
@@ -2243,6 +2251,48 @@ void nes_bmc_64y2k_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
+ Board BMC-TELETUBBIES
+ (name assigned by BootGod who said the board has
+ no markings, a glop top, and an 8K VRAM chip)
+
+ Games: Y2K 420 in 1
+
+ iNES: mapper 237
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_420y2k_device::write_h(offs_t offset, u8 data)
+{
+ LOG_MMC(("bmc_420y2k write_h, offset: %04x, data: %02x\n", offset, data));
+
+ if (BIT(m_latch, 1)) // lock bit
+ m_reg = (m_reg & ~0x07) | (data & 0x07);
+ else
+ {
+ m_latch = offset;
+ m_reg = data;
+ }
+
+ u8 bank = BIT(m_latch, 2) << 5 | (m_reg & 0x1f);
+ u8 mode = BIT(m_reg, 6);
+ prg16_89ab(bank & ~mode); // strangely for UNROM games it DOESN'T ignore the NROM mode bit
+ prg16_cdef(bank | (BIT(m_reg, 7) ? mode : 0x07));
+
+ set_nt_mirroring(BIT(m_reg, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+}
+
+u8 nes_bmc_420y2k_device::read_h(offs_t offset)
+{
+ LOG_MMC(("bmc_420y2k read_h, offset: %04x\n", offset));
+ // latch bit 0 is only used to determine the menu, and the behavior of
+ // this cart seems hardwired to OR $02 (ORing $00-$03 allows four menus)
+ return hi_access_rom(offset | (m_latch & 1) << 1);
+}
+
+/*-------------------------------------------------
+
BMC-12IN1
Unknown Bootleg Multigame Board
@@ -2432,56 +2482,86 @@ void nes_bmc_64in1_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
- BMC-70IN1
+ BMC-70IN1 (FIXME: according to NesDev the boards for this
+ and BMC-800IN1 are Realtec 8031 and 8155. Which is which?)
- Unknown Bootleg Multigame Board
- Games:
+ Games: 35 in 1, 68 in 1, 70 in 1
- iNES: mapper
+ iNES: mapper 236
- This is same hardware as BMC-800IN1 below, but this
- cart has CHR and slightly diff bankswitch.
- DSW not emulated yet.
+ This is the same hardware as BMC-800IN1 below, but
+ these carts have CHRROM and lack the extended PRG
+ bank switching. Solder pads/jumpers not emulated yet.
- In MESS: Preliminary Supported.
+ In MAME: Supported.
+
+ TODO: Determine if Excitebike on 68 in 1 is actually
+ bugged on the real cartridge. It sets mirroring bit
+ to horizontal when it should be vertical.
-------------------------------------------------*/
-void nes_bmc_70in1_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_70in1_device::update_banks()
{
- LOG_MMC(("bmc70in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ update_prg(m_latch[1] & 0x07);
+ chr8(m_latch[0] & 0x07, CHRROM);
+}
- if (offset < 0x4000)
+void nes_bmc_70in1_device::update_prg(u8 bank)
+{
+ if (BIT(m_latch[1], 5)) // NROM mode
{
- set_nt_mirroring(BIT(offset, 5) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
- chr8(offset & 7, CHRROM);
+ u8 mode = !BIT(m_latch[1], 4);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
}
- else
+ else // UNROM mode
{
- switch (offset & 0x30)
- {
- case 0x00: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x7; break;
- case 0x10: m_mode = 0x1; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x7; break;
- case 0x20: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x6); m_reg[1] = m_reg[0] | 0x1; break;
- case 0x30: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x0; break;
- }
- prg16_89ab(m_reg[0]);
- prg16_cdef(m_reg[1]);
+ prg16_89ab(bank);
+ prg16_cdef(bank | 0x07);
}
}
+void nes_bmc_70in1_device::write_h(offs_t offset, u8 data)
+{
+ LOG_MMC(("bmc70in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ m_latch[BIT(offset, 14)] = offset;
+ update_banks();
+ set_nt_mirroring(BIT(m_latch[0], 5) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
+}
+
uint8_t nes_bmc_70in1_device::read_h(offs_t offset)
{
LOG_MMC(("bmc70in1 read_h, offset: %04x\n", offset));
- if (m_mode)
- offset = (offset & 0x7ff0) | m_mode;
+ if ((m_latch[1] & 0x30) == 0x10)
+ offset = (offset & ~0x0f) | m_jumper; // TODO: make jumper selectable
return hi_access_rom(offset);
}
/*-------------------------------------------------
+ BMC-800IN1
+
+ Games: 800 in 1
+
+ iNES: mapper 236
+
+ This is the same hardware as BMC-70IN1, but this
+ cart supports larger PRG and has unbanked CHRRAM.
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_800in1_device::update_banks()
+{
+ update_prg((m_latch[0] & 0x07) << 3 | (m_latch[1] & 0x07));
+}
+
+/*-------------------------------------------------
+
BMC-72IN1, BMC-110IN1
Unknown Bootleg Multigame Board
@@ -2609,56 +2689,6 @@ void nes_bmc_500in1_device::write_h(offs_t offset, u8 data)
/*-------------------------------------------------
- BMC-800IN1
-
- Unknown Bootleg Multigame Board
- Games:
-
- iNES: mapper
-
- DSW not emulated yet.
-
- In MESS: Preliminary Supported.
-
- -------------------------------------------------*/
-
-void nes_bmc_800in1_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("bmc800in1 write_h, offset: %04x, data: %02x\n", offset, data));
-
- if (offset < 0x4000)
- {
- set_nt_mirroring(BIT(offset, 5) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
-
- m_reg[0] = (m_reg[0]) | ((offset << 3) & 0x38);
- m_reg[1] = (m_reg[1]) | ((offset << 3) & 0x38);
- }
- else
- {
- switch (offset & 0x30)
- {
- case 0x00: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x7; break;
- case 0x10: m_mode = 0x1; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x7; break;
- case 0x20: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x6); m_reg[1] = m_reg[0] | 0x1; break;
- case 0x30: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x0; break;
- }
- }
- prg16_89ab(m_reg[0]);
- prg16_cdef(m_reg[1]);
-}
-
-uint8_t nes_bmc_800in1_device::read_h(offs_t offset)
-{
- LOG_MMC(("bmc800in1 read_h, offset: %04x\n", offset));
-
- if (m_mode)
- offset = (offset & 0x7ff0) | m_mode;
-
- return hi_access_rom(offset);
-}
-
-/*-------------------------------------------------
-
BMC-1200IN1
Unknown Bootleg Multigame Board
diff --git a/src/devices/bus/nes/multigame.h b/src/devices/bus/nes/multigame.h
index fe4a780691c..6dfbed4ee7e 100644
--- a/src/devices/bus/nes/multigame.h
+++ b/src/devices/bus/nes/multigame.h
@@ -672,6 +672,28 @@ private:
};
+// ======================> nes_bmc_420y2k_device
+
+class nes_bmc_420y2k_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_420y2k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+private:
+ u8 m_latch, m_reg;
+};
+
+
// ======================> nes_bmc_12in1_device
class nes_bmc_12in1_device : public nes_nrom_device
@@ -790,20 +812,40 @@ class nes_bmc_70in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_70in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_70in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
+ // construction/destruction
+ nes_bmc_70in1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
// device-level overrides
virtual void device_start() override;
+ virtual void update_banks();
+ void update_prg(u8 bank);
+
+ u8 m_latch[2];
+
private:
- uint8_t m_mode;
- uint8_t m_reg[2];
+ u8 m_jumper;
+};
+
+
+// ======================> nes_bmc_800in1_device
+
+class nes_bmc_800in1_device : public nes_bmc_70in1_device
+{
+public:
+ // construction/destruction
+ nes_bmc_800in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void update_banks() override;
};
@@ -877,29 +919,6 @@ public:
};
-// ======================> nes_bmc_800in1_device
-
-class nes_bmc_800in1_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_bmc_800in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- uint8_t m_mode;
- uint8_t m_reg[2];
-};
-
-
// ======================> nes_bmc_1200in1_device
class nes_bmc_1200in1_device : public nes_nrom_device
@@ -1144,6 +1163,7 @@ DECLARE_DEVICE_TYPE(NES_BMC_S700, nes_bmc_s700_device)
DECLARE_DEVICE_TYPE(NES_BMC_BALL11, nes_bmc_ball11_device)
DECLARE_DEVICE_TYPE(NES_BMC_22GAMES, nes_bmc_22games_device)
DECLARE_DEVICE_TYPE(NES_BMC_64Y2K, nes_bmc_64y2k_device)
+DECLARE_DEVICE_TYPE(NES_BMC_420Y2K, nes_bmc_420y2k_device)
DECLARE_DEVICE_TYPE(NES_BMC_12IN1, nes_bmc_12in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_20IN1, nes_bmc_20in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_21IN1, nes_bmc_21in1_device)
diff --git a/src/devices/bus/nes/nes_carts.cpp b/src/devices/bus/nes/nes_carts.cpp
index 7dea84ea444..8237cb0bca0 100644
--- a/src/devices/bus/nes/nes_carts.cpp
+++ b/src/devices/bus/nes/nes_carts.cpp
@@ -101,8 +101,6 @@ void nes_cart(device_slot_interface &device)
// SxROM
device.option_add_internal("sxrom", NES_SXROM);
device.option_add_internal("sorom", NES_SOROM);
- device.option_add_internal("sxrom_a", NES_SXROM_A); // in MMC1-A PRG RAM is always enabled
- device.option_add_internal("sorom_a", NES_SOROM_A); // in MMC1-A PRG RAM is always enabled
// TxROM
device.option_add_internal("txrom", NES_TXROM);
// HKROM
@@ -313,6 +311,7 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("yung08", NES_YUNG08);
device.option_add_internal("btl_0353", NES_0353); // used by Lucky (Roger) Rabbit FDS conversion
device.option_add_internal("09034a", NES_09034A);
+ device.option_add_internal("l001", NES_L001);
device.option_add_internal("batmanfs", NES_BATMANFS);
device.option_add_internal("palthena", NES_PALTHENA); // used by Palthena no Kagami FDS conversion
device.option_add_internal("tobidase", NES_TOBIDASE); // mapper 120
@@ -356,6 +355,7 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("gouder", NES_GOUDER);
device.option_add_internal("sa9602b", NES_SA9602B);
device.option_add_internal("unl_shero", NES_SACHEN_SHERO);
+ device.option_add_internal("a9746", NES_A9746); // mapper 219
// misc multigame cart boards
device.option_add_internal("benshieng", NES_BENSHIENG);
device.option_add_internal("action52", NES_ACTION52);
@@ -401,6 +401,7 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("bmc_ball11", NES_BMC_BALL11);
device.option_add_internal("bmc_22games", NES_BMC_22GAMES);
device.option_add_internal("bmc_64y2k", NES_BMC_64Y2K);
+ device.option_add_internal("bmc_420y2k", NES_BMC_420Y2K);
device.option_add_internal("bmc_12in1", NES_BMC_12IN1);
device.option_add_internal("bmc_20in1", NES_BMC_20IN1);
device.option_add_internal("bmc_21in1", NES_BMC_21IN1);
@@ -471,7 +472,6 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("konami_qtai", NES_NROM); // [mentioned in FCEUMM source - we need more info] - UNSUPPORTED
device.option_add_internal("unl_3d_block", NES_NROM); // [mentioned in FCEUMM source - we need more info] - UNSUPPORTED
device.option_add_internal("unl_c_n22m", NES_NROM); // [mentioned in FCEUMM source - we need more info] - UNSUPPORTED
- device.option_add_internal("a9746", NES_NROM); // mapper 219 - UNSUPPORTED (no dump available);
// legacy boards for FFE copier mappers (are there images available to fix/improve emulation?)
device.option_add_internal("ffe3", NES_FFE3);
device.option_add_internal("ffe4", NES_FFE4);
diff --git a/src/devices/bus/nes/nes_ines.hxx b/src/devices/bus/nes/nes_ines.hxx
index 74e3360f742..6f31c9abbe0 100644
--- a/src/devices/bus/nes/nes_ines.hxx
+++ b/src/devices/bus/nes/nes_ines.hxx
@@ -188,7 +188,7 @@ static const nes_mmc mmc_list[] =
{ 152, DIS_74X161X161X32 },
{ 153, BANDAI_LZ93 },
{ 154, NAMCOT_34X3 },
- { 155, STD_SXROM_A }, // diff compared to MMC1 concern WRAM
+ { 155, STD_SXROM }, // same as mapper 1 but forces the use of MMC1A
{ 156, OPENCORP_DAOU306 },
{ 157, BANDAI_DATACH }, // Datach Reader games -> must go in the Datach subslot
{ 158, TENGEN_800037 },
@@ -252,7 +252,7 @@ static const nes_mmc mmc_list[] =
{ 216, RCM_GS2015 },
{ 217, BMC_500IN1 },
{ 218, NOCASH_NOCHR },
- // 219 UNL-A9746 (according to Cah4e3's code, no dump available (yet)
+ { 219, UNL_A9746 },
// 220 Unused - reserved for emulator debugging
{ 221, UNL_N625092 },
{ 222, BTL_DRAGONNINJA },
@@ -269,8 +269,8 @@ static const nes_mmc mmc_list[] =
{ 233, BMC_42IN1RESET },
{ 234, AVE_MAXI15 },
{ 235, BMC_GOLD150 }, // 235 Golden Game x-in-1 - Unsupported
- // 236 Game 800-in-1 - Unsupported, Realtec boards 8031 and 8155
- // 237 Teletubbies 420-in-1 multicart. Dump available?
+ { 236, BMC_70IN1 },
+ { 237, BMC_TELETUBBIES },
{ 238, UNL_603_5052 },
// 239 Unused
{ 240, CNE_SHLZ },
@@ -365,7 +365,7 @@ static const nes_mmc mmc_list[] =
// 327 BMC-10-24-C-A1 6-in-1
{ 328, UNL_RT01 }, // test cart (Russia)
{ 329, UNL_EDU2K },
- // 330 Sangokushi II - Haou no Tairiku hack - N163 bootleg
+ { 330, BTL_L001 }, // Sangokushi II bootleg (retitled part III)
{ 331, BMC_12IN1 },
{ 332, BMC_WS },
{ 333, BMC_8IN1 },
@@ -651,10 +651,8 @@ void nes_cart_slot_device::call_load_ines()
// handle submappers
if (submapper)
{
- // 001: MMC1
- if (mapper == 1 && submapper == 3)
- pcb_id = STD_SXROM_A;
- else if (mapper == 1 && submapper == 5)
+ // 001: MMC1 (other submappers are deprecated)
+ if (mapper == 1 && submapper == 5)
logerror("Unimplemented NES 2.0 submapper: SEROM/SHROM/SH1ROM.\n");
// 002, 003, 007: UxROM, CNROM, AxROM
else if (mapper == 2 && submapper == 2)
@@ -780,6 +778,11 @@ void nes_cart_slot_device::call_load_ines()
}
break;
+ case STD_SXROM:
+ if (mapper == 155)
+ m_cart->set_mmc1_type(device_nes_cart_interface::mmc1_type::MMC1A);
+ break;
+
case NOCASH_NOCHR:
// this mapper uses mirroring flags differently
m_cart->set_four_screen_vram(false);
@@ -903,6 +906,11 @@ void nes_cart_slot_device::call_load_ines()
m_pcb_id = UNL_8237A;
break;
+ case BMC_70IN1:
+ if (vrom_size == 0)
+ m_pcb_id = BMC_800IN1;
+ break;
+
case RCM_GS2004:
if (prg_size >= 0x50000)
m_pcb_id = RCM_GS2013;
@@ -1155,10 +1163,8 @@ const char * nes_cart_slot_device::get_default_card_ines(get_default_card_softwa
// handle submappers
if (submapper)
{
- // 001: MMC1
- if (mapper == 1 && submapper == 3)
- pcb_id = STD_SXROM_A;
- else if (mapper == 1 && submapper == 5)
+ // 001: MMC1 (other submappers are deprecated)
+ if (mapper == 1 && submapper == 5)
logerror("Unimplemented NES 2.0 submapper: SEROM/SHROM/SH1ROM.\n");
// 021, 023, 025: VRC4 / VRC2
else if (mapper == 21 || mapper == 23 || mapper == 25)
@@ -1241,6 +1247,11 @@ const char * nes_cart_slot_device::get_default_card_ines(get_default_card_softwa
pcb_id = UNL_8237A;
break;
+ case BMC_70IN1: // Mapper 236 is used for 2 diff boards
+ if (ROM[5] == 0)
+ pcb_id = BMC_800IN1;
+ break;
+
case RCM_GS2004: // Mapper 283 is used for 2 diff boards
if (ROM[4] >= 20)
pcb_id = RCM_GS2013;
diff --git a/src/devices/bus/nes/nes_pcb.hxx b/src/devices/bus/nes/nes_pcb.hxx
index 410fb6197f1..799f17a15b6 100644
--- a/src/devices/bus/nes/nes_pcb.hxx
+++ b/src/devices/bus/nes/nes_pcb.hxx
@@ -32,8 +32,6 @@ static const nes_pcb pcb_list[] =
{ "un1rom", STD_UN1ROM },
{ "sxrom", STD_SXROM },
{ "sorom", STD_SOROM },
- { "sxrom_a", STD_SXROM_A },
- { "sorom_a", STD_SOROM_A },
{ "txrom", STD_TXROM },
{ "hkrom", STD_HKROM },
{ "tqrom", STD_TQROM },
@@ -216,6 +214,7 @@ static const nes_pcb pcb_list[] =
{ "yung08", BTL_YUNG08 },
{ "btl_0353", BTL_0353 },
{ "09034a", BTL_09034A },
+ { "l001", BTL_L001 },
{ "batmanfs", BTL_BATMANFS },
{ "palthena", BTL_PALTHENA },
{ "tobidase", BTL_TOBIDASE }, // mapper 120
@@ -279,6 +278,7 @@ static const nes_pcb pcb_list[] =
{ "bmc_ball11", BMC_BALLGAMES_11IN1 },
{ "bmc_22games", BMC_22GAMES },
{ "bmc_64y2k", BMC_64IN1NR },
+ { "bmc_420y2k", BMC_TELETUBBIES },
{ "bmc_12in1", BMC_12IN1 },
{ "bmc_20in1", BMC_20IN1 },
{ "bmc_21in1", BMC_21IN1 },
@@ -339,6 +339,7 @@ static const nes_pcb pcb_list[] =
{ "tek90", JYCOMPANY_A },
{ "sa9602b", SACHEN_SA9602B },
{ "unl_shero", SACHEN_SHERO },
+ { "a9746", UNL_A9746 },
{ "mmalee2", UNL_MMALEE },
{ "unl_2708", UNL_2708 },
{ "unl_dh08", UNL_DH08 },
@@ -376,7 +377,6 @@ static const nes_pcb pcb_list[] =
{ "onebus", UNSUPPORTED_BOARD },
{ "coolboy", UNSUPPORTED_BOARD },
{ "btl_900218", UNSUPPORTED_BOARD }, // pirate The Lord of King, to be emulated soon
- { "a9746", UNSUPPORTED_BOARD },
{ "pec586", UNSUPPORTED_BOARD },
{ "unl_drgnfgt", UNSUPPORTED_BOARD }, // Dragon Fighter by Flying Star
{ "test", TEST_BOARD },
@@ -627,6 +627,24 @@ void nes_cart_slot_device::call_load_pcb()
// osd_printf_error("VRC-6, pin9: A%d, pin10: A%d\n", nes_cart_get_line(get_feature("vrc6-pin9"), nes_cart_get_line(get_feature("vrc6-pin10"));
}
+ if (m_pcb_id == STD_SXROM || m_pcb_id == STD_SOROM)
+ {
+ if (get_feature("mmc1_type") != nullptr)
+ {
+ using mmc1_type = device_nes_cart_interface::mmc1_type;
+
+ const char *type = get_feature("mmc1_type");
+ if (!strcmp(type, "MMC1"))
+ m_cart->set_mmc1_type(mmc1_type::MMC1);
+ else if (!strcmp(type, "MMC1A"))
+ m_cart->set_mmc1_type(mmc1_type::MMC1A);
+ else if (!strncmp(type, "MMC1B", 5)) // common prefix of several variants
+ m_cart->set_mmc1_type(mmc1_type::MMC1B);
+ else if (!strcmp(type, "MMC1C"))
+ m_cart->set_mmc1_type(mmc1_type::MMC1C);
+ }
+ }
+
if (m_pcb_id == STD_HKROM || m_pcb_id == TAITO_X1_017)
mapper_sram_size = m_cart->get_mapper_sram_size();
diff --git a/src/devices/bus/nes/nes_slot.cpp b/src/devices/bus/nes/nes_slot.cpp
index ebaf5ea0406..fef76b520d0 100644
--- a/src/devices/bus/nes/nes_slot.cpp
+++ b/src/devices/bus/nes/nes_slot.cpp
@@ -122,6 +122,7 @@ device_nes_cart_interface::device_nes_cart_interface(const machine_config &mconf
, m_misc_rom_size(0)
, m_ce_mask(0)
, m_ce_state(0)
+ , m_mmc1_type(mmc1_type::MMC1B)
, m_vrc_ls_prg_a(0)
, m_vrc_ls_prg_b(0)
, m_vrc_ls_chr(0)
diff --git a/src/devices/bus/nes/nes_slot.h b/src/devices/bus/nes/nes_slot.h
index f634c7c1dc7..fc4459c458a 100644
--- a/src/devices/bus/nes/nes_slot.h
+++ b/src/devices/bus/nes/nes_slot.h
@@ -23,11 +23,10 @@ enum
STD_CNROM, STD_CPROM,
STD_EXROM, STD_FXROM, STD_GXROM,
STD_HKROM, STD_PXROM,
- STD_SXROM, STD_TXROM, STD_TXSROM,
- STD_TKROM, STD_TQROM,
+ STD_SXROM, STD_SOROM,
+ STD_TXROM, STD_TXSROM, STD_TKROM, STD_TQROM,
STD_UXROM, STD_UN1ROM, UXROM_CC,
HVC_FAMBASIC, NES_QJ, PAL_ZZ, STD_EVENT,
- STD_SXROM_A, STD_SOROM, STD_SOROM_A,
STD_DISKSYS,
STD_NROM368,//homebrew extension of NROM!
// Discrete components boards (by various manufacturer)
@@ -87,7 +86,7 @@ enum
TXC_MJBLOCK, TXC_STRIKEW, TXC_TW,
// Multigame Carts
BMC_64IN1NR, BMC_190IN1, BMC_A65AS, BMC_A88S1, BMC_F15,
- BMC_GN45, BMC_HIK8IN1, BMC_S24IN1SC03, BMC_T262,
+ BMC_GN45, BMC_HIK8IN1, BMC_S24IN1SC03, BMC_T262, BMC_TELETUBBIES,
BMC_WS, BMC_SUPERBIG_7IN1, BMC_SUPERHIK_4IN1, BMC_BALLGAMES_11IN1,
BMC_MARIOPARTY_7IN1, BMC_GOLD_7IN1, BMC_SUPER_700IN1, BMC_FAMILY_4646,
BMC_36IN1, BMC_21IN1, BMC_150IN1, BMC_35IN1, BMC_64IN1,
@@ -116,9 +115,9 @@ enum
UNL_43272, UNL_TF1201, UNL_CITYFIGHT, UNL_NINJARYU, UNL_EH8813A, UNL_RT01,
// Bootleg boards
BTL_0353, BTL_09034A, BTL_AISENSHINICOL, BTL_BATMANFS,
- BTL_CONTRAJ, BTL_DRAGONNINJA, BTL_MARIOBABY, BTL_PALTHENA,
- BTL_PIKACHUY2K, BTL_SBROS11, BTL_SMB2JA, BTL_SMB2JB,
- BTL_SMB3, BTL_SHUIGUAN, BTL_TOBIDASE, BTL_YUNG08,
+ BTL_CONTRAJ, BTL_DRAGONNINJA, BTL_L001, BTL_MARIOBABY,
+ BTL_PALTHENA, BTL_PIKACHUY2K, BTL_SBROS11, BTL_SHUIGUAN,
+ BTL_SMB2JA, BTL_SMB2JB, BTL_SMB3, BTL_TOBIDASE, BTL_YUNG08,
// Shenzhen Jncota
JNCOTA_KT1001,
// Kaiser
@@ -176,6 +175,8 @@ enum
class device_nes_cart_interface : public device_interface
{
public:
+ enum class mmc1_type : u8 { MMC1, MMC1A, MMC1B, MMC1C };
+
// construction/destruction
virtual ~device_nes_cart_interface();
@@ -214,6 +215,7 @@ public:
void set_trainer(bool val) { m_has_trainer = val; }
void set_ce(int mask, int state) { m_ce_mask = mask; m_ce_state = state; }
+ void set_mmc1_type(mmc1_type val) { m_mmc1_type = val; }
void set_vrc_lines(int PRG_A, int PRG_B, int CHR) { m_vrc_ls_prg_a = PRG_A; m_vrc_ls_prg_b = PRG_B; m_vrc_ls_chr = CHR; }
void set_n163_vol(int vol) { m_n163_vol = vol; }
void set_x1_005_alt(bool val) { m_x1_005_alt_mirroring = val; }
@@ -284,6 +286,7 @@ protected:
int m_ce_mask;
int m_ce_state;
+ mmc1_type m_mmc1_type;
int m_vrc_ls_prg_a;
int m_vrc_ls_prg_b;
int m_vrc_ls_chr;
diff --git a/src/devices/bus/nes/pirate.cpp b/src/devices/bus/nes/pirate.cpp
index c6a68d48b98..fdc48fdc66b 100644
--- a/src/devices/bus/nes/pirate.cpp
+++ b/src/devices/bus/nes/pirate.cpp
@@ -36,8 +36,8 @@
DEFINE_DEVICE_TYPE(NES_AGCI_50282, nes_agci_device, "nes_agci50282", "NES Cart AGCI 50282 PCB")
DEFINE_DEVICE_TYPE(NES_DREAMTECH01, nes_dreamtech_device, "nes_dreamtech", "NES Cart Dreamtech01 PCB")
-DEFINE_DEVICE_TYPE(NES_FUKUTAKE, nes_fukutake_device, "nes_futuremedia", "NES Cart Fukutake Study Box PCB")
-DEFINE_DEVICE_TYPE(NES_FUTUREMEDIA, nes_futuremedia_device, "nes_fukutake", "NES Cart FutureMedia PCB")
+DEFINE_DEVICE_TYPE(NES_FUKUTAKE, nes_fukutake_device, "nes_fukutake", "NES Cart Fukutake Study Box PCB")
+DEFINE_DEVICE_TYPE(NES_FUTUREMEDIA, nes_futuremedia_device, "nes_futuremedia", "NES Cart FutureMedia PCB")
DEFINE_DEVICE_TYPE(NES_MAGSERIES, nes_magseries_device, "nes_magseries", "NES Cart Magical Series PCB")
DEFINE_DEVICE_TYPE(NES_DAOU306, nes_daou306_device, "nes_daou306", "NES Cart Daou 306 PCB")
DEFINE_DEVICE_TYPE(NES_CC21, nes_cc21_device, "nes_cc21", "NES Cart CC-21 PCB")
diff --git a/src/devices/bus/ti99/gromport/cartridges.cpp b/src/devices/bus/ti99/gromport/cartridges.cpp
index 7a9ccb95a6d..b4c3655a7e5 100644
--- a/src/devices/bus/ti99/gromport/cartridges.cpp
+++ b/src/devices/bus/ti99/gromport/cartridges.cpp
@@ -62,18 +62,18 @@ enum
static char const *const pcbdefs[] =
{
- "standard", // PCB_STANDARD
- "paged12k", // PCB_PAGED12K
- "paged", // PCB_PAGED16K
- "minimem", // PCB_MINIMEM
- "super", // PCB_SUPER
- "mbx", // PCB_MBX
- "paged379i", // PCB_PAGED379I
- "paged378", // PCB_PAGED378
- "paged377", // PCB_PAGED377
- "pagedcru", // PCB_PAGEDCRU
- "gromemu", // PCB_GROMEMU
- "paged7", // PCB_PAGED7
+ "standard", // PCB_STANDARD
+ "paged12k", // PCB_PAGED12K
+ "paged", // PCB_PAGED16K
+ "minimem", // PCB_MINIMEM
+ "super", // PCB_SUPER
+ "mbx", // PCB_MBX
+ "paged379i", // PCB_PAGED379I
+ "paged378", // PCB_PAGED378
+ "paged377", // PCB_PAGED377
+ "pagedcru", // PCB_PAGEDCRU
+ "gromemu", // PCB_GROMEMU
+ "paged7", // PCB_PAGED7
nullptr
};
diff --git a/src/devices/cpu/tms32082/dis_mp.cpp b/src/devices/cpu/tms32082/dis_mp.cpp
index be0f9d92074..b194dd0e4d4 100644
--- a/src/devices/cpu/tms32082/dis_mp.cpp
+++ b/src/devices/cpu/tms32082/dis_mp.cpp
@@ -325,14 +325,14 @@ offs_t tms32082_mp_disassembler::disassemble(std::ostream &stream, offs_t pc, co
case 0x0c: util::stream_format(*output, "brcr R%d", src1); break;
case 0x0d: util::stream_format(*output, "brcr %s", get_creg_name(imm32)); break;
- case 0x10: util::stream_format(*output, "shift%s.dz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
- case 0x12: util::stream_format(*output, "shift%s.dm %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
- case 0x14: util::stream_format(*output, "shift%s.ds %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
- case 0x16: util::stream_format(*output, "shift%s.ez %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
- case 0x18: util::stream_format(*output, "shift%s.em %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
- case 0x1a: util::stream_format(*output, "shift%s.es %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
- case 0x1c: util::stream_format(*output, "shift%s.iz %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
- case 0x1e: util::stream_format(*output, "shift%s.im %d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x10: util::stream_format(*output, "shift%s.dz R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x12: util::stream_format(*output, "shift%s.dm R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x14: util::stream_format(*output, "shift%s.ds R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x16: util::stream_format(*output, "shift%s.ez R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x18: util::stream_format(*output, "shift%s.em R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x1a: util::stream_format(*output, "shift%s.es R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x1c: util::stream_format(*output, "shift%s.iz R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
+ case 0x1e: util::stream_format(*output, "shift%s.im R%d, %d, R%d, R%d", (op & (1 << 10)) ? "r" : "l", rotate, endmask, rs, rd); break;
case 0x22: util::stream_format(*output, "and R%d, R%d, R%d", src1, rs, rd); break;
case 0x23: util::stream_format(*output, "and 0x%08X, R%d, R%d", imm32, rs, rd); break;
diff --git a/src/devices/cpu/tms32082/mp_ops.cpp b/src/devices/cpu/tms32082/mp_ops.cpp
index cbae99b9d81..867a5ecf54b 100644
--- a/src/devices/cpu/tms32082/mp_ops.cpp
+++ b/src/devices/cpu/tms32082/mp_ops.cpp
@@ -24,18 +24,6 @@
#define ROTATE_L(x, r) ((x << r) | (x >> (32-r)))
#define ROTATE_R(x, r) ((x >> r) | (x << (32-r)))
-#define CMP_OVERFLOW32(r, s, d) ((((d) ^ (s)) & ((d) ^ (r)) & 0x80000000) ? 1 : 0)
-#define CMP_OVERFLOW16(r, s, d) ((((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? 1 : 0)
-#define CMP_OVERFLOW8(r, s, d) ((((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? 1 : 0)
-#define CARRY32(x) (((x) & (((uint64_t)1) << 32)) ? 1 : 0)
-#define CARRY16(x) (((x) & 0x10000) ? 1 : 0)
-#define CARRY8(x) (((x) & 0x100) ? 1 : 0)
-#define SIGN32(x) (((x) & 0x80000000) ? 1 : 0)
-#define SIGN16(x) (((x) & 0x8000) ? 1 : 0)
-#define SIGN8(x) (((x) & 0x80) ? 1 : 0)
-
-#define SIGN_EXTEND(x, r) ((x) | (((x) & (0x80000000 >> r)) ? ((int32_t)(0x80000000) >> r) : 0))
-
bool tms32082_mp_device::test_condition(int condition, uint32_t value)
@@ -72,63 +60,64 @@ bool tms32082_mp_device::test_condition(int condition, uint32_t value)
uint32_t tms32082_mp_device::calculate_cmp(uint32_t src1, uint32_t src2)
{
- uint16_t src1_16 = (uint16_t)(src1);
- uint8_t src1_8 = (uint8_t)(src1);
- uint16_t src2_16 = (uint16_t)(src2);
- uint8_t src2_8 = (uint8_t)(src2);
-
- uint64_t res32 = (uint64_t)src1 - (uint64_t)src2;
- int z32 = (res32 == 0) ? 1 : 0;
- int n32 = SIGN32(res32);
- int v32 = CMP_OVERFLOW32(res32, src2, src1);
- int c32 = CARRY32(res32);
-
- uint32_t res16 = (uint32_t)src1_16 - (uint32_t)src2_16;
- int z16 = (res16 == 0) ? 1 : 0;
- int n16 = SIGN16(res16);
- int v16 = CMP_OVERFLOW16(res16, src2_16, src1_16);
- int c16 = CARRY16(res16);
-
- uint16_t res8 = (uint16_t)src1_8 - (uint16_t)src2_8;
- int z8 = (res8 == 0) ? 1 : 0;
- int n8 = SIGN8(res8);
- int v8 = CMP_OVERFLOW8(res8, src2_8, src1_8);
- int c8 = CARRY8(res8);
+ int32_t a32 = (uint32_t)(src1);
+ int16_t a16 = (uint16_t)(src1);
+ int8_t a8 = (uint8_t)(src1);
+ int32_t b32 = (uint32_t)(src2);
+ int16_t b16 = (uint16_t)(src2);
+ int8_t b8 = (uint8_t)(src2);
+
+ int32_t res32 = a32 - b32;
+ int16_t res16 = a16 - b16;
+ int8_t res8 = a8 - b8;
+
+ int z32 = res32 == 0;
+ int n32 = ((res32) & 0x80000000) ? 1 : 0;
+ int v32 = ((((a32) ^ (b32)) & ((a32) ^ (res32))) & 0x80000000) ? 1 : 0;
+ int c32 = (!((uint32_t)a32 < (uint32_t)b32)) ? 1 : 0;
+ int z16 = res16 == 0;
+ int n16 = ((res16) & 0x8000) ? 1 : 0;
+ int v16 = ((((a16) ^ (b16)) & ((a16) ^ (res16))) & 0x8000) ? 1 : 0;
+ int c16 = (!((uint16_t)a16 < (uint16_t)b16)) ? 1 : 0;
+ int z8 = res8 == 0;
+ int n8 = ((res8) & 0x80) ? 1 : 0;
+ int v8 = ((((a8) ^ (b8)) & ((a8) ^ (res8))) & 0x80) ? 1 : 0;
+ int c8 = (!((uint8_t)a8 < (uint8_t)b8)) ? 1 : 0;
uint32_t flags = 0;
// 32-bits (bits 20-29)
- flags |= ((~c32) & 1) << 29; // higher than or same (C)
- flags |= ((c32) & 1) << 28; // lower than (~C)
- flags |= ((c32|z32) & 1) << 27; // lower than or same (~C|Z)
- flags |= ((~c32&~z32) & 1) << 26; // higher than (C&~Z)
- flags |= (((n32&v32)|(~n32&~v32)) & 1) << 25; // greater than or equal (N&V)|(~N&~V)
- flags |= (((n32&~v32)|(~n32&v32)) & 1) << 24; // less than (N&~V)|(~N&V)
- flags |= (((n32&~v32)|(~n32&v32)|(z32)) & 1) << 23; // less than or equal (N&~V)|(~N&V)|Z
- flags |= (((n32&v32&~z32)|(~n32&~v32&~z32)) & 1) << 22; // greater than (N&V&~Z)|(~N&~V&~Z)
- flags |= ((~z32) & 1) << 21; // not equal (~Z)
- flags |= ((z32) & 1) << 20; // equal (Z)
+ flags |= ((c32) & 1) << 29; // higher than or same (C)
+ flags |= ((~c32) & 1) << 28; // lower than (~C)
+ flags |= ((~c32 | z32) & 1) << 27; // lower than or same (~C|Z)
+ flags |= ((c32 & ~z32) & 1) << 26; // higher than (C&~Z)
+ flags |= (((n32 & v32) | (~n32 & ~v32)) & 1) << 25; // greater than or equal (N&V)|(~N&~V)
+ flags |= (((n32 & ~v32) | (~n32 & v32)) & 1) << 24; // less than (N&~V)|(~N&V)
+ flags |= (((n32 & ~v32) | (~n32 & v32) | (z32)) & 1) << 23; // less than or equal (N&~V)|(~N&V)|Z
+ flags |= (((n32 & v32 & ~z32) | (~n32 & ~v32 & ~z32)) & 1) << 22; // greater than (N&V&~Z)|(~N&~V&~Z)
+ flags |= ((~z32) & 1) << 21; // not equal (~Z)
+ flags |= ((z32) & 1) << 20; // equal (Z)
// 16-bits (bits 10-19)
- flags |= ((~c16) & 1) << 19; // higher than or same (C)
- flags |= ((c16) & 1) << 18; // lower than (~C)
- flags |= ((c16|z16) & 1) << 17; // lower than or same (~C|Z)
- flags |= ((~c16&~z16) & 1) << 16; // higher than (C&~Z)
- flags |= (((n16&v16)|(~n16&~v16)) & 1) << 15; // greater than or equal (N&V)|(~N&~V)
- flags |= (((n16&~v16)|(~n16&v16)) & 1) << 14; // less than (N&~V)|(~N&V)
- flags |= (((n16&~v16)|(~n16&v16)|(z16)) & 1) << 13; // less than or equal (N&~V)|(~N&V)|Z
- flags |= (((n16&v16&~z16)|(~n16&~v16&~z16)) & 1) << 12; // greater than (N&V&~Z)|(~N&~V&~Z)
- flags |= ((~z16) & 1) << 11; // not equal (~Z)
- flags |= ((z16) & 1) << 10; // equal (Z)
+ flags |= ((c16) & 1) << 19; // higher than or same (C)
+ flags |= ((~c16) & 1) << 18; // lower than (~C)
+ flags |= ((~c16 | z16) & 1) << 17; // lower than or same (~C|Z)
+ flags |= ((c16 & ~z16) & 1) << 16; // higher than (C&~Z)
+ flags |= (((n16 & v16) | (~n16 & ~v16)) & 1) << 15; // greater than or equal (N&V)|(~N&~V)
+ flags |= (((n16 & ~v16) | (~n16 & v16)) & 1) << 14; // less than (N&~V)|(~N&V)
+ flags |= (((n16 & ~v16) | (~n16 & v16) | (z16)) & 1) << 13; // less than or equal (N&~V)|(~N&V)|Z
+ flags |= (((n16 & v16 & ~z16) | (~n16 & ~v16 & ~z16)) & 1) << 12; // greater than (N&V&~Z)|(~N&~V&~Z)
+ flags |= ((~z16) & 1) << 11; // not equal (~Z)
+ flags |= ((z16) & 1) << 10; // equal (Z)
// 8-bits (bits 0-9)
- flags |= ((~c8) & 1) << 9; // higher than or same (C)
- flags |= ((c8) & 1) << 8; // lower than (~C)
- flags |= ((c8|z8) & 1) << 7; // lower than or same (~C|Z)
- flags |= ((~c8&~z8) & 1) << 6; // higher than (C&~Z)
- flags |= (((n8&v8)|(~n8&~v8)) & 1) << 5; // greater than or equal (N&V)|(~N&~V)
- flags |= (((n8&~v8)|(~n8&v8)) & 1) << 4; // less than (N&~V)|(~N&V)
- flags |= (((n8&~v8)|(~n8&v8)|(z8)) & 1) << 3; // less than or equal (N&~V)|(~N&V)|Z
- flags |= (((n8&v8&~z8)|(~n8&~v8&~z8)) & 1) << 2; // greater than (N&V&~Z)|(~N&~V&~Z)
- flags |= ((~z8) & 1) << 1; // not equal (~Z)
- flags |= ((z8) & 1) << 0; // equal (Z)
+ flags |= ((c8) & 1) << 9; // higher than or same (C)
+ flags |= ((~c8) & 1) << 8; // lower than (~C)
+ flags |= ((~c8 | z8) & 1) << 7; // lower than or same (~C|Z)
+ flags |= ((c8 & ~z8) & 1) << 6; // higher than (C&~Z)
+ flags |= (((n8 & v8) | (~n8 & ~v8)) & 1) << 5; // greater than or equal (N&V)|(~N&~V)
+ flags |= (((n8 & ~v8) | (~n8 & v8)) & 1) << 4; // less than (N&~V)|(~N&V)
+ flags |= (((n8 & ~v8) | (~n8 & v8) | (z8)) & 1) << 3; // less than or equal (N&~V)|(~N&V)|Z
+ flags |= (((n8 & v8 & ~z8) | (~n8 & ~v8 & ~z8)) & 1) << 2; // greater than (N&V&~Z)|(~N&~V&~Z)
+ flags |= ((~z8) & 1) << 1; // not equal (~Z)
+ flags |= ((z8) & 1) << 0; // equal (Z)
return flags;
}
@@ -287,7 +276,9 @@ void tms32082_mp_device::execute_short_imm()
if (r) // right
{
res = ROTATE_R(source, rot) & compmask;
- res = SIGN_EXTEND(res, rot);
+ // sign extend
+ if (res & (1 << (end - 1)))
+ res |= 0xffffffff << end;
}
else // left
{
@@ -312,8 +303,7 @@ void tms32082_mp_device::execute_short_imm()
uint32_t endmask = SHIFT_MASK[end ? end : 32];
if (inv) endmask = ~endmask;
- int shift = r ? 32-rot : rot;
- uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32];
+ uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot];
uint32_t compmask = endmask & shiftmask;
uint32_t res;
@@ -373,15 +363,16 @@ void tms32082_mp_device::execute_short_imm()
uint32_t endmask = SHIFT_MASK[end ? end : 32];
if (inv) endmask = ~endmask;
- int shift = r ? 32-rot : rot;
- uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32];
+ uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot];
uint32_t compmask = endmask & shiftmask;
uint32_t res;
if (r) // right
{
res = ROTATE_R(source, rot) & compmask;
- res = SIGN_EXTEND(res, rot);
+ // sign extend
+ if (res & (1 << (31 - rot)))
+ res |= 0xffffffff << (31 - rot);
}
else // left
{
@@ -885,16 +876,15 @@ void tms32082_mp_device::execute_reg_long_imm()
{
int r = (m_ir & (1 << 10));
int inv = (m_ir & (1 << 11));
- int rot = m_reg[OP_ROTATE()];
+ int rot = m_reg[OP_ROTATE()] & 0x1f;
int end = OP_ENDMASK();
uint32_t source = m_reg[OP_RS()];
int rd = OP_RD();
- uint32_t endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1];
+ uint32_t endmask = end ? SHIFT_MASK[end] : 0xffffffff;
if (inv) endmask = ~endmask;
- int shift = r ? 32-rot : rot;
- uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32];
+ uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot];
uint32_t compmask = endmask & shiftmask;
uint32_t res;
@@ -916,23 +906,24 @@ void tms32082_mp_device::execute_reg_long_imm()
{
int r = (m_ir & (1 << 10));
int inv = (m_ir & (1 << 11));
- int rot = m_reg[OP_ROTATE()];
+ int rot = m_reg[OP_ROTATE()] & 0x1f;
int end = OP_ENDMASK();
uint32_t source = m_reg[OP_RS()];
int rd = OP_RD();
- uint32_t endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1];
+ uint32_t endmask = SHIFT_MASK[end ? end : 32];
if (inv) endmask = ~endmask;
- int shift = r ? 32-rot : rot;
- uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32];
+ uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot];
uint32_t compmask = endmask & shiftmask;
uint32_t res;
if (r) // right
{
res = ROTATE_R(source, rot) & compmask;
- res = SIGN_EXTEND(res, rot);
+ // sign extend
+ if (res & (1 << (31 - rot)))
+ res |= 0xffffffff << (31 - rot);
}
else // left
{
@@ -948,16 +939,15 @@ void tms32082_mp_device::execute_reg_long_imm()
{
int r = (m_ir & (1 << 10));
int inv = (m_ir & (1 << 11));
- int rot = m_reg[OP_ROTATE()];
+ int rot = m_reg[OP_ROTATE()] & 0x1f;
int end = OP_ENDMASK();
uint32_t source = m_reg[OP_RS()];
int rd = OP_RD();
- uint32_t endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1];
+ uint32_t endmask = end ? SHIFT_MASK[end] : 0xffffffff;
if (inv) endmask = ~endmask;
- int shift = r ? 32-rot : rot;
- uint32_t shiftmask = SHIFT_MASK[shift ? shift : 32];
+ uint32_t shiftmask = SHIFT_MASK[r ? 32 - rot : rot];
uint32_t compmask = endmask & ~shiftmask;
uint32_t res;
@@ -1301,29 +1291,30 @@ void tms32082_mp_device::execute_reg_long_imm()
int ls_bit1 = m_ir & (1 << 10);
int ls_bit2 = m_ir & (1 << 6);
int rd = OP_RS();
- int src1 OP_SRC1();
+ int src1 = OP_SRC1();
double source = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[src1 >> 1]) : (double)u2f(m_reg[src1]));
+ double source2 = pd ? u2d(m_fpair[rd >> 1]) : (double)(u2f(m_reg[rd]));
+
+ // parallel load/store op
+ if (!(ls_bit1 == 0 && ls_bit2 == 0))
+ {
+ vector_loadstore();
+ }
if (rd)
{
if (pd)
{
- double res = source * u2d(m_fpair[rd >> 1]);
+ double res = source * source2;
m_fpair[rd >> 1] = d2u(res);
}
else
{
- float res = (float)(source) * u2f(m_reg[rd]);
+ float res = (float)(source * source2);
m_reg[rd] = f2u(res);
}
}
-
- // parallel load/store op
- if (!(ls_bit1 == 0 && ls_bit2 == 0))
- {
- vector_loadstore();
- }
break;
}
@@ -1342,6 +1333,12 @@ void tms32082_mp_device::execute_reg_long_imm()
double source = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[rs1 >> 1]) : (double)u2f(m_reg[rs1]));
+ // parallel load/store op
+ if (!(ls_bit1 == 0 && ls_bit2 == 0))
+ {
+ vector_loadstore();
+ }
+
if (rd)
{
// destination register
@@ -1369,12 +1366,6 @@ void tms32082_mp_device::execute_reg_long_imm()
m_facc[acc] = source;
}
-
- // parallel load/store op
- if (!(ls_bit1 == 0 && ls_bit2 == 0))
- {
- vector_loadstore();
- }
break;
}
@@ -1390,7 +1381,7 @@ void tms32082_mp_device::execute_reg_long_imm()
int ls_bit2 = m_ir & (1 << 6);
int rd = OP_RD();
- float src1 = u2f(m_reg[OP_SRC1()]);
+ float src1 = has_imm ? u2f(imm32) : u2f(m_reg[OP_SRC1()]);
float src2 = u2f(m_reg[OP_RS()]);
float res = (src1 * src2) + (z ? 0.0f : m_facc[acc]);
@@ -1412,7 +1403,7 @@ void tms32082_mp_device::execute_reg_long_imm()
else
m_reg[rd] = f2u((float)res);
}
- else
+ else if (pd)
{
// write to accumulator
m_facc[acc] = (double)res;
@@ -1433,7 +1424,7 @@ void tms32082_mp_device::execute_reg_long_imm()
int ls_bit2 = m_ir & (1 << 6);
int rd = OP_RD();
- float src1 = u2f(m_reg[OP_SRC1()]);
+ float src1 = has_imm ? u2f(imm32) : u2f(m_reg[OP_SRC1()]);
float src2 = u2f(m_reg[OP_RS()]);
float res = (z ? 0.0f : m_facc[acc]) - (src1 * src2);
@@ -1455,7 +1446,7 @@ void tms32082_mp_device::execute_reg_long_imm()
else
m_reg[rd] = f2u((float)res);
}
- else
+ else if (pd)
{
// write to accumulator
m_facc[acc] = (double)res;
@@ -1501,7 +1492,7 @@ void tms32082_mp_device::execute_reg_long_imm()
}
case 0x11: // DP - SP -> DP
{
- double s1 = u2d(m_fpair[src1 >> 1]);
+ double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]);
float s2 = u2f(m_reg[rs]);
uint64_t res = d2u(s1 + (double) s2);
m_fpair[rd >> 1] = res;
@@ -1509,7 +1500,7 @@ void tms32082_mp_device::execute_reg_long_imm()
}
case 0x15: // DP - DP -> DP
{
- double s1 = u2d(m_fpair[src1 >> 1]);
+ double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]);
double s2 = u2d(m_fpair[rs >> 1]);
uint64_t res = d2u((double)(s1 + s2));
m_fpair[rd >> 1] = res;
@@ -1559,7 +1550,7 @@ void tms32082_mp_device::execute_reg_long_imm()
}
case 0x11: // DP - SP -> DP
{
- double s1 = u2d(m_fpair[src1 >> 1]);
+ double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]);
float s2 = u2f(m_reg[rs]);
uint64_t res = d2u(s1 - (double) s2);
m_fpair[rd >> 1] = res;
@@ -1567,7 +1558,7 @@ void tms32082_mp_device::execute_reg_long_imm()
}
case 0x15: // DP - DP -> DP
{
- double s1 = u2d(m_fpair[src1 >> 1]);
+ double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]);
double s2 = u2d(m_fpair[rs >> 1]);
uint64_t res = d2u((double)(s1 - s2));
m_fpair[rd >> 1] = res;
@@ -1617,7 +1608,7 @@ void tms32082_mp_device::execute_reg_long_imm()
}
case 0x11: // DP x SP -> DP
{
- double s1 = u2d(m_fpair[src1 >> 1]);
+ double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]);
float s2 = u2f(m_reg[rs]);
uint64_t res = d2u(s1 * (double) s2);
m_fpair[rd >> 1] = res;
@@ -1625,7 +1616,7 @@ void tms32082_mp_device::execute_reg_long_imm()
}
case 0x15: // DP x DP -> DP
{
- double s1 = u2d(m_fpair[src1 >> 1]);
+ double s1 = has_imm ? u2f(imm32) : u2d(m_fpair[src1 >> 1]);
double s2 = u2d(m_fpair[rs >> 1]);
uint64_t res = d2u(s1 * s2);
m_fpair[rd >> 1] = res;
@@ -1694,7 +1685,7 @@ void tms32082_mp_device::execute_reg_long_imm()
s = has_imm ? (double)(u2f(imm32)) : (double)u2f(m_reg[src1]);
break;
case 1:
- s = u2d(m_fpair[src1 >> 1]);
+ s = has_imm ? (double)(u2f(imm32)) : u2d(m_fpair[src1 >> 1]);
break;
case 2:
s = has_imm ? (double)((int32_t)(imm32)) : (double)(int32_t)(m_reg[src1]);
@@ -1794,9 +1785,9 @@ void tms32082_mp_device::execute_reg_long_imm()
for (int i=0; i < 32; i++)
{
- if (source & (1 << (31-i)))
+ if (source & (1 << i))
{
- bit = i;
+ bit = 31 - i;
break;
}
}
diff --git a/src/devices/cpu/tms32082/tms32082.cpp b/src/devices/cpu/tms32082/tms32082.cpp
index 25dc0af52ac..330627829da 100644
--- a/src/devices/cpu/tms32082/tms32082.cpp
+++ b/src/devices/cpu/tms32082/tms32082.cpp
@@ -72,40 +72,37 @@ std::unique_ptr<util::disasm_interface> tms32082_mp_device::create_disassembler(
}
-uint32_t tms32082_mp_device::mp_param_r(offs_t offset, uint32_t mem_mask)
+void tms32082_mp_device::tc_command_execute(int channel, uint32_t entrypoint)
{
- //printf("mp_param_w: %08X, %08X\n", offset, mem_mask);
- return m_param_ram[offset];
-}
+ [[maybe_unused]] static const char* CHANNEL_NAME[16] = {
+ "XPT15", "XPT14", "XPT13", "XPT12", "XPT11", "XPT10", "XPT9", "XPT8",
+ "XPT7", "XPT6", "XPT5", "XPT4", "XPT3", "XPT2", "XPT1", "MP"
+ };
-void tms32082_mp_device::mp_param_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- //printf("mp_param_w: %08X, %08X, %08X\n", offset, data, mem_mask);
+ uint32_t address = entrypoint;
- COMBINE_DATA(&m_param_ram[offset]);
+ uint32_t next_entry = m_program.read_dword(address + 0);
+ uint32_t pt_options = m_program.read_dword(address + 4);
- if (offset == 0x3f)
+ if ((pt_options & 0x00100000) == 0)
{
- // initiate Transfer Controller operation
- // TODO: move TC functionality to separate device
- uint32_t address = data;
+ // long-form transfer
- uint32_t next_entry = m_program.read_dword(address + 0);
- uint32_t pt_options = m_program.read_dword(address + 4);
uint32_t src_addr = m_program.read_dword(address + 8);
uint32_t dst_addr = m_program.read_dword(address + 12);
uint32_t src_b_count = m_program.read_word(address + 16);
uint32_t src_a_count = m_program.read_word(address + 18);
- uint32_t dst_b_count = m_program.read_word(address + 20);
- uint32_t dst_a_count = m_program.read_word(address + 22);
+ // uint32_t dst_b_count = m_program.read_word(address + 20);
+ // uint32_t dst_a_count = m_program.read_word(address + 22);
uint32_t src_c_count = m_program.read_dword(address + 24);
- uint32_t dst_c_count = m_program.read_dword(address + 28);
+ // uint32_t dst_c_count = m_program.read_dword(address + 28);
uint32_t src_b_pitch = m_program.read_dword(address + 32);
uint32_t dst_b_pitch = m_program.read_dword(address + 36);
uint32_t src_c_pitch = m_program.read_dword(address + 40);
uint32_t dst_c_pitch = m_program.read_dword(address + 44);
- printf("TC operation:\n");
+ /*
+ printf("TC operation (long form) %s:\n", CHANNEL_NAME[channel]);
printf(" Next entry: %08X\n", next_entry);
printf(" PT options: %08X\n", pt_options);
printf(" SRC addr: %08X\n", src_addr);
@@ -118,6 +115,7 @@ void tms32082_mp_device::mp_param_w(offs_t offset, uint32_t data, uint32_t mem_m
printf(" DST B pitch: %08X\n", dst_b_pitch);
printf(" SRC C pitch: %08X\n", src_c_pitch);
printf(" DST C pitch: %08X\n", dst_c_pitch);
+ */
if (pt_options != 0x80000000)
fatalerror("TC transfer, options = %08X\n", pt_options);
@@ -145,6 +143,57 @@ void tms32082_mp_device::mp_param_w(offs_t offset, uint32_t data, uint32_t mem_m
}
}
}
+ else
+ {
+ // short-form transfer
+
+ bool stop = false;
+
+ do
+ {
+
+ // uint32_t src_addr = m_program.read_dword(address + 8);
+ // uint32_t dst_addr = m_program.read_dword(address + 12);
+
+ // int count = pt_options & 0xffff;
+ stop = (pt_options & 0x80000000) ? true : false;
+
+ /*
+ printf("TC operation (short form) %s [%08X]:\n", CHANNEL_NAME[channel], address);
+ printf(" Next entry: %08X\n", next_entry);
+ printf(" PT options: %08X\n", pt_options);
+ printf(" Byte count: %08X\n", count);
+ printf(" SRC addr: %08X\n", src_addr);
+ printf(" DST addr: %08X\n", dst_addr);
+ */
+
+ address = next_entry;
+ if (!stop)
+ {
+ next_entry = m_program.read_dword(address);
+ pt_options = m_program.read_dword(address + 4);
+ }
+ } while (!stop);
+ }
+}
+
+
+uint32_t tms32082_mp_device::mp_param_r(offs_t offset, uint32_t mem_mask)
+{
+ //printf("mp_param_w: %08X, %08X\n", offset, mem_mask);
+ return m_param_ram[offset];
+}
+
+void tms32082_mp_device::mp_param_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ //printf("mp_param_w: %08X, %08X, %08X\n", offset, data, mem_mask);
+
+ COMBINE_DATA(&m_param_ram[offset]);
+
+ if (offset >= 0x30 && offset <= 0x3f)
+ {
+ tc_command_execute(offset - 0x30, data);
+ }
}
@@ -255,48 +304,32 @@ void tms32082_mp_device::device_reset()
m_intpen = 0;
m_ie = 0;
+
+ m_pp_status = 0xf0000; // start with all PPs halted
}
void tms32082_mp_device::processor_command(uint32_t command)
{
- printf("MP CMND %08X: ", command);
+ // unhalt PPs
+ if (command & 0x20000000)
+ {
+ if (command & 0x00000001)
+ m_pp_status &= ~0x10000;
+ if (command & 0x00000002)
+ m_pp_status &= ~0x20000;
+ }
- if (command & 0x80000000)
- printf("Reset ");
+ // halt PPs
if (command & 0x40000000)
- printf("Halt ");
- if (command & 0x20000000)
- printf("Unhalt ");
- if (command & 0x10000000)
- printf("ICR ");
- if (command & 0x08000000)
- printf("DCR ");
- if (command & 0x00004000)
- printf("Task ");
- if (command & 0x00002000)
- printf("Msg ");
-
- printf("to: ");
-
- if (command & 0x00000400)
- printf("VC ");
- if (command & 0x00000200)
- printf("TC ");
- if (command & 0x00000100)
- printf("MP ");
- if (command & 0x00000008)
- printf("PP3 ");
- if (command & 0x00000004)
- printf("PP2 ");
- if (command & 0x00000002)
- printf("PP1 ");
- if (command & 0x00000001)
- printf("PP0 ");
+ {
+ if (command & 0x00000001)
+ m_pp_status |= 0x10000;
+ if (command & 0x00000002)
+ m_pp_status |= 0x20000;
+ }
if (!m_cmd_callback.isnull())
m_cmd_callback(space(AS_PROGRAM), command);
-
- printf("\n");
}
uint32_t tms32082_mp_device::read_creg(int reg)
@@ -309,6 +342,11 @@ uint32_t tms32082_mp_device::read_creg(int reg)
case 0x1: // EIP
return m_eip;
+ case 0x2: // CONFIG
+ // Type = 0010: 2 Parallel Processors
+ // Release = 0011: Production release silicon
+ return (0x2 << 12) | (0x3 << 4);
+
case 0x4: // INTPEN
return m_intpen;
@@ -316,7 +354,7 @@ uint32_t tms32082_mp_device::read_creg(int reg)
return m_ie;
case 0xa: // PPERROR
- return 0xe0000;
+ return m_pp_status;
case 0xe: // TCOUNT
return m_tcount;
@@ -331,7 +369,7 @@ uint32_t tms32082_mp_device::read_creg(int reg)
return m_outp;
default:
- printf("read_creg(): %08X\n", reg);
+ //printf("read_creg(): %08X\n", reg);
break;
}
return 0;
@@ -361,7 +399,6 @@ void tms32082_mp_device::write_creg(int reg, uint32_t data)
case 0x6: // IE
m_ie = data;
- printf("IE = %08X\n", data);
break;
case 0xe: // TCOUNT
@@ -381,7 +418,7 @@ void tms32082_mp_device::write_creg(int reg, uint32_t data)
break;
default:
- printf("write_creg(): %08X, %08X\n", reg, data);
+ //printf("write_creg(): %08X, %08X\n", reg, data);
break;
}
}
diff --git a/src/devices/cpu/tms32082/tms32082.h b/src/devices/cpu/tms32082/tms32082.h
index a3e3135b568..415ce95d564 100644
--- a/src/devices/cpu/tms32082/tms32082.h
+++ b/src/devices/cpu/tms32082/tms32082.h
@@ -134,6 +134,8 @@ protected:
write32mo_delegate m_cmd_callback;
+ uint32_t m_pp_status;
+
void check_interrupts();
void processor_command(uint32_t command);
uint32_t fetch();
@@ -146,6 +148,7 @@ protected:
bool test_condition(int condition, uint32_t value);
uint32_t calculate_cmp(uint32_t src1, uint32_t src2);
void vector_loadstore();
+ void tc_command_execute(int channel, uint32_t entrypoint);
};
diff --git a/src/devices/cpu/tx0/tx0.cpp b/src/devices/cpu/tx0/tx0.cpp
index 51bc1ba6c6b..0b669c48dca 100644
--- a/src/devices/cpu/tx0/tx0.cpp
+++ b/src/devices/cpu/tx0/tx0.cpp
@@ -42,8 +42,9 @@
#define INCREMENT_PC_8KW (PC = (PC+1) & ADDRESS_MASK_8KW)
-DEFINE_DEVICE_TYPE(TX0_8KW, tx0_8kw_device, "tx0_8kw_cpu", "MIT Lincoln Laboratory TX-0 8KW")
-DEFINE_DEVICE_TYPE(TX0_64KW, tx0_64kw_device, "tx0_64kw_cpu", "MIT Lincoln Laboratory TX-0 64KW")
+DEFINE_DEVICE_TYPE(TX0_8KW, tx0_8kw_device, "tx0_8kw_cpu", "MIT Lincoln Laboratory TX-0 8KW (new)")
+DEFINE_DEVICE_TYPE(TX0_8KW_OLD, tx0_8kwo_device, "tx0_8kwo_cpu", "MIT Lincoln Laboratory TX-0 8KW (old)")
+DEFINE_DEVICE_TYPE(TX0_64KW, tx0_64kw_device, "tx0_64kw_cpu", "MIT Lincoln Laboratory TX-0 64KW")
tx0_device::tx0_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int addr_bits, int address_mask, int ir_mask)
@@ -66,8 +67,18 @@ tx0_device::tx0_device(const machine_config &mconfig, device_type type, const ch
m_program_config.m_is_octal = true;
}
+tx0_8kw_device::tx0_8kw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : tx0_device(mconfig, type, tag, owner, clock, 13, ADDRESS_MASK_8KW, 037)
+{
+}
+
tx0_8kw_device::tx0_8kw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : tx0_device(mconfig, TX0_8KW, tag, owner, clock, 13, ADDRESS_MASK_8KW, 037)
+ : tx0_8kw_device(mconfig, TX0_8KW, tag, owner, clock)
+{
+}
+
+tx0_8kwo_device::tx0_8kwo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : tx0_8kw_device(mconfig, TX0_8KW_OLD, tag, owner, clock)
{
}
@@ -583,6 +594,221 @@ void tx0_64kw_device::execute_instruction_64kw()
/* (1.2) TBR = Store the contents of the TBR in the MBR. */
MBR |= m_tbr;
+ if ((MAR & 0000003) == 2 && ((MAR & 0000600) >> 7) == 1)
+ /* LMB and MBL used simultaneously interchange LR and MBR */
+ std::swap(LR, MBR);
+ else if ((MAR & 0000003) == 2)
+ /* (1.3) LMB = Store the contents of the LR in the MBR. */
+ MBR = LR;
+ else if (((MAR & 0000600) >> 7) == 1)
+ /* (1.3) MLR = Store the contents of the MBR (memory buffer
+ register) in the live reg. */
+ LR = MBR;
+
+ if (((MAR & 0000600) >> 7) == 2)
+ /* (1.4) SHR = Shift the AC right one place, i.e. multiply the AC
+ by 2^-1 */
+ AC >>= 1;
+
+ if (((MAR & 0000600) >> 7) == 3)
+ /* (1.4) CYR = Cycle the AC right one digital position (AC(17) will
+ become AC(0)) */
+ AC = (AC >> 1) | ((AC & 1) << 17);
+
+ if (MAR & 0000020)
+ /* (1.4) PAD = Partial add AC to MBR, that is, for every digital
+ position of the MBR that contains a one, complement the digit
+ in the corresponding digital position of the AC. This is also
+ called a half add. */
+ AC ^= MBR;
+
+ if (MAR & 0000010)
+ { /* (1.7) CRY = Partial add the 18 digits of the AC to the
+ corresponding 18 digits of the carry.
+
+ To determine what the 18 digits of the carry are, use the
+ following rule:
+
+ "Grouping the AC and MBR digits into pairs and proceeding from
+ right to left, assign the carry digit of the next pair to a one
+ if in the present pair MBR = 1 and AC = 0 or if in the present
+ pair AC = 1 and carry 1.
+
+ (Note: the 0th digit pair determines the 17th pair's carry
+ digit)" */
+ AC ^= MBR;
+
+ AC = AC + MBR;
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+ }
+
+ if (((MAR & 0030000) >> 12) == 3)
+ /* (1.8) Hlt = Halt the computer */
+ m_run = 0;
+
+ break;
+ }
+ }
+}
+
+/* execute one instruction */
+void tx0_8kwo_device::execute_instruction_8kw()
+{
+ if (! m_cycle)
+ {
+ m_cycle = 1; /* most frequent case */
+ switch (IR)
+ {
+ case 0: /* STOre */
+ case 4: /* Store LR */
+ case 8: /* ADD */
+ case 12: /* Load LR */
+ break;
+
+ case 16: /* TRansfer on Negative */
+ if (AC & 0400000)
+ {
+ PC = MAR & 0017777;
+ m_cycle = 0; /* instruction only takes one cycle if branch
+ is taken */
+ }
+ break;
+
+ case 20: /* TRAnsfer */
+ PC = MAR & 0017777;
+ m_cycle = 0; /* instruction only takes one cycle if branch
+ is taken */
+ break;
+
+ case 24: /* OPeRate */
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ if (IR & 004)
+ /* (0.8) CLL = Clear the left nine digital positions of the AC */
+ AC &= 0000777;
+
+ if (IR & 002)
+ /* (0.8) CLR = Clear the right nine digital positions of the AC */
+ AC &= 0777000;
+
+ if (((IR & 001) == 01) && ((MAR & 010000) == 000000))
+ {
+ /* (0.8) IOS In-Out Stop = Stop machine so that an In-Out command
+ (specified by digits 6 7 8 of MAR) may be executed */
+ /* ((MAR & 0007000) >> 9) is device ID */
+ /* 7: */
+ /* (0.8) P7H = Punch holes 1-6 in flexo tape specified by AC
+ digital positions 2, 5, 8, 11, 14, and 17. Also punches a 7th
+ hole on tape. */
+ /* 6: */
+ /* (0.8) P6H = Same as P7H but no seventh hole */
+ /* 4: */
+ /* (0.8) PNT = Print one flexowriter character specified by AC
+ digits 2, 5, 8, 11, 14, and 17. */
+ /* 1: */
+ /* (0.8) R1C = Read one line of flexo tape so that tape positions
+ 1, 2, 3, 4, 5, and 6 will be put in the AC digital positions 0,
+ 3, 6, 9, 12 and 15. */
+ /* 3: */
+ /* (0.8) R3C = Read one line of flexo tape into AC digits 0, 3, 6,
+ 9, 12 and 15. Then cycle the AC one digital position; read the
+ next line on tape into AC digits 0, 3, 6, 9, 12 and 15, cycle
+ the AC right one digital position and read the third and last
+ line into AC digits 0, 3, 6, 9, 12 and 15. (This command is
+ equal to a triple CYR-R1C.) */
+ /* 2: */
+ /* (0.8) DIS = Intensify a point on the scope with x and y
+ coordinates where x is specified by AC digits 0-8 with digit 0
+ being used as the sign and y is specified by AC digits 9-17
+ with digit 9 being used as the sign for y. The complement
+ system is in effect when the signs are negative. */
+ /* (5 is undefined) */
+ int index = (MAR & 0007000) >> 9;
+
+ m_ios = 0;
+ call_io_handler(index);
+ m_ioh = 1;
+ }
+
+ if (((IR & 001) == 00) && ((MAR & 010000) == 010000))
+ { /* (IOS) EX0 through EX7 = operate user's EXternal equipment. */
+ switch ((MAR & 0007000) >> 9)
+ {
+ /* ... */
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ m_cycle = 0; /* always true */
+ switch (IR)
+ {
+ case 0: /* STOre */
+ tx0_write(MAR, (MBR = AC));
+ break;
+
+ case 4: /* Store LR */
+ tx0_write(MAR, (MBR = LR));
+ break;
+
+ case 8: /* ADD */
+ MBR = tx0_read(MAR);
+
+ AC = AC + MBR;
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+
+ break;
+
+ case 12: /* Load LR */
+ LR = MBR = tx0_read(MAR);
+ break;
+
+ case 16: /* TRansfer on Negative */
+ case 20: /* TRAnsfer */
+ break;
+
+ case 24: /* OPeRate */
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ MBR = 0;
+
+ if ((MAR & 0000104) == 0000100)
+ /* (1.1) PEN = Read the light pen flip-flops 1 and 2 into AC(0) and
+ AC(1). */
+ /*...*/{ }
+
+ if ((MAR & 0000104) == 0000004)
+ /* (1.1) TAC = Insert a one in each digital position of the AC
+ wherever there is a one in the corresponding digital position
+ of the TAC. */
+ AC |= m_tac;
+
+ if ((MAR & 0000003) == 1)
+ /* (1.2) AMB = Store the contents of the AC in the MBR. */
+ MBR = AC;
+
+ if (MAR & 0000040)
+ /* (1.2) COM = Complement every digit in the accumulator */
+ AC ^= 0777777;
+
+ if ((MAR & 0000003) == 3)
+ /* (1.2) TBR = Store the contents of the TBR in the MBR. */
+ MBR |= m_tbr;
+
+ uint32_t tmp = MBR;
+
if ((MAR & 0000003) == 2)
/* (1.3) LMB = Store the contents of the LR in the MBR. */
MBR = LR;
@@ -590,7 +816,15 @@ void tx0_64kw_device::execute_instruction_64kw()
if (((MAR & 0000600) >> 7) == 1)
/* (1.3) MLR = Store the contents of the MBR (memory buffer
register) in the live reg. */
- LR = MBR;
+ LR = tmp;
+
+ if ((MAR & 0000704) == 0000104)
+ /* (1.3) ORL = Inclusive or MBR into LR. */
+ LR |= tmp;
+
+ if ((MAR & 0000704) == 0000304)
+ /* (1.3) ANL = And MBR into LR. */
+ LR &= tmp;
if (((MAR & 0000600) >> 7) == 2)
/* (1.4) SHR = Shift the AC right one place, i.e. multiply the AC
@@ -629,7 +863,7 @@ void tx0_64kw_device::execute_instruction_64kw()
AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
}
- if (((MAR & 0030000) >> 12) == 3)
+ if (((IR & 001) == 01) && ((MAR & 017000) == 010000))
/* (1.8) Hlt = Halt the computer */
m_run = 0;
@@ -969,11 +1203,8 @@ void tx0_8kw_device::execute_instruction_8kw()
}
if (((! (MAR & 0000400)) && (MAR & 0000200)) && ((! (MAR & 0000004)) && (MAR & 0000002)))
- { /* LMB and MBL used simultaneously interchange LR and MBR */
- int tmp = MBR;
- MBR = LR;
- LR = tmp;
- }
+ /* LMB and MBL used simultaneously interchange LR and MBR */
+ std::swap(LR, MBR);
else if ((! (MAR & 0000400)) && (MAR & 0000200))
/* (1.4) MBL = Transfer MBR contents to LR */
LR = MBR;
@@ -1073,6 +1304,11 @@ std::unique_ptr<util::disasm_interface> tx0_8kw_device::create_disassembler()
return std::make_unique<tx0_8kw_disassembler>();
}
+std::unique_ptr<util::disasm_interface> tx0_8kwo_device::create_disassembler()
+{
+ return std::make_unique<tx0_8kwo_disassembler>();
+}
+
std::unique_ptr<util::disasm_interface> tx0_64kw_device::create_disassembler()
{
return std::make_unique<tx0_64kw_disassembler>();
diff --git a/src/devices/cpu/tx0/tx0.h b/src/devices/cpu/tx0/tx0.h
index 51c729bd743..8c57c08e8f7 100644
--- a/src/devices/cpu/tx0/tx0.h
+++ b/src/devices/cpu/tx0/tx0.h
@@ -133,11 +133,27 @@ public:
tx0_8kw_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
protected:
+ tx0_8kw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
virtual void execute_run() override;
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
private:
- void execute_instruction_8kw();
+ virtual void execute_instruction_8kw();
+};
+
+
+class tx0_8kwo_device : public tx0_8kw_device
+{
+public:
+ // construction/destruction
+ tx0_8kwo_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
+
+protected:
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+private:
+ virtual void execute_instruction_8kw() override;
};
@@ -156,7 +172,8 @@ private:
};
-DECLARE_DEVICE_TYPE(TX0_64KW, tx0_64kw_device)
-DECLARE_DEVICE_TYPE(TX0_8KW, tx0_8kw_device)
+DECLARE_DEVICE_TYPE(TX0_64KW, tx0_64kw_device)
+DECLARE_DEVICE_TYPE(TX0_8KW_OLD, tx0_8kwo_device)
+DECLARE_DEVICE_TYPE(TX0_8KW, tx0_8kw_device)
#endif // MAME_CPU_TX0_TX0_H
diff --git a/src/devices/cpu/tx0/tx0dasm.cpp b/src/devices/cpu/tx0/tx0dasm.cpp
index a810f280b47..1c6ca3e5d7c 100644
--- a/src/devices/cpu/tx0/tx0dasm.cpp
+++ b/src/devices/cpu/tx0/tx0dasm.cpp
@@ -38,7 +38,7 @@
1.4 | 600020 (PAD) Partial add (exclusive or) MBR to AC
1.4 | 600400 (SHR) Shift AC right once
1.4 | 600600 (CYR) Cycle AC right once
- 1.7 | 600010 (CRY) Add carry digits to AC (according to LR)
+ 1.7 | 600010 (CRY) Add carry digits to AC (according to MBR)
1.8 | 603000 (HLT) Halt computer
ANL and ORL were added in the first half of 1959 (M-5001-6).
@@ -72,7 +72,7 @@
1.6 | 600400 (SHR) Shift AC right once
1.6 | 600600 (CYR) Cycle AC right once
1.6 | 607000 (SPF) Set PFR from MBR
- 1.7 | 600010 (CRY) Add carry digits to AC (according to LR)
+ 1.7 | 600010 (CRY) Add carry digits to AC (according to MBR)
1.8 | 600001 (MBX) Transfer MBR to XR
1.8 | 603000 (HLT) Halt computer
@@ -119,7 +119,15 @@ offs_t tx0_64kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
// Addressable instructions (only 3 in this version)
util::stream_format(stream, "%s %06o", s_addressable_insts[(inst & 0600000) >> 13], inst & 0177777);
}
- else switch (inst)
+ else
+ dasm_opr(stream, inst);
+
+ return 1 | SUPPORTED;
+}
+
+void tx0_64kw_disassembler::dasm_opr(std::ostream &stream, u32 inst)
+{
+switch (inst)
{
case 0600012:
stream << "cry";
@@ -245,6 +253,10 @@ offs_t tx0_64kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "clc";
break;
+ case 0740062:
+ stream << "lcc";
+ break;
+
case 0740200:
stream << "cal";
break;
@@ -276,6 +288,46 @@ offs_t tx0_64kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
util::stream_format(stream, "opr %o", inst & 0177777);
break;
}
+}
+
+offs_t tx0_8kwo_disassembler::disassemble(std::ostream &stream, offs_t pc, const tx0_8kwo_disassembler::data_buffer &opcodes, const tx0_8kwo_disassembler::data_buffer &params)
+{
+ u32 inst = opcodes.r32(pc) & 0777777;
+
+ if (inst < 0600000)
+ {
+ // Addressable instructions (only 6 in this version)
+ if ((inst & 060000) != 0)
+ util::stream_format(stream, "%06o", inst);
+ else
+ util::stream_format(stream, "%s %05o", s_addressable_insts[(inst & 0700000) >> 13], inst & 017777);
+ }
+ else switch (inst)
+ {
+ case 0600105:
+ stream << "orl";
+ break;
+
+ case 0600125:
+ stream << "ora";
+ break;
+
+ case 0600305:
+ stream << "anl";
+ break;
+
+ case 0600325:
+ stream << "ana";
+ break;
+
+ case 0610000: case 0611000: case 0612000: case 0613000: case 0614000: case 0615000: case 0616000: case 0617000:
+ util::stream_format(stream, "ex%d", BIT(inst, 9, 3));
+ break;
+
+ default:
+ dasm_opr(stream, inst);
+ break;
+ }
return 1 | SUPPORTED;
}
@@ -309,10 +361,10 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
}
else
{
- if ((inst & 037000) == 02000)
+ if ((inst & 0137020) == 0102020)
{
stream << "tbr";
- if ((inst & 0100757) == 0)
+ if ((inst & 000757) == 0)
return 1 | SUPPORTED;
stream << 'U';
}
@@ -642,6 +694,10 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "alo";
break;
+ case 040227:
+ stream << "anl 20"; // no consistent mnemonic used in program macros
+ break;
+
case 040230:
stream << "all";
break;
@@ -662,6 +718,10 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "anlUcom";
break;
+ case 040250:
+ stream << "alrUamz";
+ break;
+
case 040260:
stream << "alc";
break;
@@ -694,6 +754,10 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "clc";
break;
+ case 0100041:
+ stream << "clcUxro";
+ break;
+
case 0100062:
stream << "lcc";
break;
@@ -718,6 +782,18 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "cal";
break;
+ case 0100201:
+ stream << "calUxro";
+ break;
+
+ case 0100212:
+ stream << "lalUlro";
+ break;
+
+ case 0100222:
+ stream << "lacUlro";
+ break;
+
case 0100240:
stream << "calUcom";
break;
diff --git a/src/devices/cpu/tx0/tx0dasm.h b/src/devices/cpu/tx0/tx0dasm.h
index ff9b82e3a5e..0ede659b70e 100644
--- a/src/devices/cpu/tx0/tx0dasm.h
+++ b/src/devices/cpu/tx0/tx0dasm.h
@@ -12,8 +12,20 @@ public:
tx0_64kw_disassembler() = default;
virtual ~tx0_64kw_disassembler() = default;
+protected:
virtual u32 opcode_alignment() const override;
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+
+ void dasm_opr(std::ostream &stream, u32 inst);
+};
+
+class tx0_8kwo_disassembler : public tx0_64kw_disassembler
+{
+public:
+ tx0_8kwo_disassembler() = default;
+
+protected:
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
};
class tx0_8kw_disassembler : public util::disasm_interface
@@ -22,6 +34,7 @@ public:
tx0_8kw_disassembler() = default;
virtual ~tx0_8kw_disassembler() = default;
+protected:
virtual u32 opcode_alignment() const override;
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
};
diff --git a/src/devices/machine/8042kbdc.h b/src/devices/machine/8042kbdc.h
index affee6f6c7a..d28c17c9cf8 100644
--- a/src/devices/machine/8042kbdc.h
+++ b/src/devices/machine/8042kbdc.h
@@ -114,7 +114,7 @@ private:
optional_ioport m_mousebtn_port;
kbdc8042_type_t m_keybtype;
- kbdc8042_interrupt_type_t m_interrupttype;
+ kbdc8042_interrupt_type_t m_interrupttype;
devcb_write_line m_system_reset_cb;
devcb_write_line m_gate_a20_cb;
diff --git a/src/devices/machine/clock.cpp b/src/devices/machine/clock.cpp
index 803e3d3a55f..4bd89fe791a 100644
--- a/src/devices/machine/clock.cpp
+++ b/src/devices/machine/clock.cpp
@@ -12,9 +12,6 @@ pulse width (active time) can be set directly with set_pulse_width.
Output signal at machine start is right after falling edge.
-TODO:
-- add one-shot trigger? eg. monostable 555
-
*/
#include "emu.h"
diff --git a/src/devices/machine/smpc.cpp b/src/devices/machine/smpc.cpp
index bff704cdcb3..4f2e9ca8295 100644
--- a/src/devices/machine/smpc.cpp
+++ b/src/devices/machine/smpc.cpp
@@ -594,11 +594,17 @@ void smpc_hle_device::device_timer(emu_timer &timer, device_timer_id id, int par
// ...
m_command_in_progress = false;
m_oreg[31] = m_comreg;
- sf_ack(true); //clear hand-shake flag (TODO: diagnostic wants this to have bit 3 high)
+ // TODO: diagnostic also wants this to have bit 3 high
+ sf_ack(true); //set hand-shake flag
return;
-// case 0x0a: // NETLINKON
-// case 0x0b: // NETLINKOFF
+ case 0x0a: // NETLINKON
+ // TODO: understand where NetLink actually lies and implement delegation accordingly
+ // (is it really an SH1 device like suggested by the space access or it overlays on CS2 bus?)
+ popmessage("%s: NetLink enabled", this->tag());
+ [[fallthrough]];
+ case 0x0b: // NETLINKOFF
+ break;
case 0x0d: // SYSRES
// send a 1 -> 0 to device reset lines
@@ -614,10 +620,6 @@ void smpc_hle_device::device_timer(emu_timer &timer, device_timer_id id, int par
case 0x0f: // CKCHG320
m_dotsel(m_comreg & 1);
- // send a NMI to Master SH2 if enabled
- if(m_NMI_reset == false)
- master_sh2_nmi();
-
// assert Slave SH2 line
m_sshres(1);
// clear PLL system halt
@@ -625,6 +627,12 @@ void smpc_hle_device::device_timer(emu_timer &timer, device_timer_id id, int par
// setup the new dot select
m_cur_dotsel = (m_comreg & 1) ^ 1;
+
+ // send a NMI to Master SH2 if enabled
+ // it is unconditionally requested:
+ // bigichig, capgen1, capgen4 and capgen5 triggers a SLEEP opcode from BIOS call and expects this to wake them up.
+ //if(m_NMI_reset == false)
+ master_sh2_nmi();
break;
case 0x10: // INTBACK
@@ -659,7 +667,7 @@ void smpc_hle_device::device_timer(emu_timer &timer, device_timer_id id, int par
break;
default:
- logerror("%s unemulated %02x command\n",this->tag(),m_comreg);
+ logerror("%s: unemulated %02x command\n",this->tag(),m_comreg);
return;
}
diff --git a/src/devices/machine/stvcd.cpp b/src/devices/machine/stvcd.cpp
index 88af2d7e0cf..9e62335f448 100644
--- a/src/devices/machine/stvcd.cpp
+++ b/src/devices/machine/stvcd.cpp
@@ -135,6 +135,10 @@ void stvcd_device::io_regs(address_map &map)
map(0x9001c, 0x9001f).mirror(0x08000).rw(FUNC(stvcd_device::cr2_r), FUNC(stvcd_device::cr2_w)).umask32(0xffffffff);
map(0x90020, 0x90023).mirror(0x08000).rw(FUNC(stvcd_device::cr3_r), FUNC(stvcd_device::cr3_w)).umask32(0xffffffff);
map(0x90024, 0x90027).mirror(0x08000).rw(FUNC(stvcd_device::cr4_r), FUNC(stvcd_device::cr4_w)).umask32(0xffffffff);
+
+ // NetLink access
+ // dragndrm expects this value, most likely for status
+ map(0x8502a, 0x8502a).lr8(NAME([] () -> u8 { return 0x11; }));
}
u32 stvcd_device::datatrns_r(offs_t offset, uint32_t mem_mask)
@@ -221,14 +225,14 @@ inline u32 stvcd_device::dataxfer_long_r()
transpart->size -= xferdnum;
transpart->numblks -= xfersectnum;
- /* TODO: is this correct? */
+ // TODO: is this correct?
xfertype32 = XFERTYPE32_INVALID;
}
}
break;
default:
- osd_printf_error("CD: unhandled 32-bit transfer type\n");
+ osd_printf_error("CD: unhandled 32-bit transfer type %d\n", (int)xfertype32);
break;
}
@@ -269,7 +273,7 @@ inline void stvcd_device::dataxfer_long_w(u32 data)
break;
default:
- printf("CD: unhandled 32-bit transfer type write\n");
+ printf("CD: unhandled 32-bit transfer type write %d\n", (int)xfertype32);
break;
}
}
@@ -462,7 +466,9 @@ void stvcd_device::stvcd_w(offs_t offset, uint32_t data, uint32_t mem_mask)
*/
int stvcd_device::get_timing_command(void)
{
- /* TODO: calculate timings based off command params */
+ // TODO: calculate timings based off command params
+ // given the CMOK returns it looks like SH2 expects way slower responses
+ // (loops for 0x7xx times at most, max number of iterations is 0x240000)
return 16667;
}
@@ -769,7 +775,7 @@ void stvcd_device::cmd_play_disc()
}
else
{
- /* TODO: Waku Waku 7 sets up track 0, that basically doesn't make any sense. Just skip it for now. */
+ // FIXME: Waku Waku 7 sets up track 0, that basically doesn't make any sense. Just skip it for now.
popmessage("Warning: track mode == 0, contact MAMEdev");
cr_standard_return(cd_stat);
hirqreg |= (CMOK);
@@ -814,9 +820,12 @@ void stvcd_device::cmd_play_disc()
else
{
/* resume from a pause state */
- /* TODO: Galaxy Fight calls 10ff ffff ffff ffff, but then it calls 0x04->0x02->0x06->0x11->0x04->0x02->0x06 command sequence
- (and current implementation nukes start/end FAD addresses at 0x04). I'm sure that this doesn't work like this, but there could
- be countless possible combinations ... */
+ // FIXME: verify implementation with Galaxy Fight
+ // it calls 10ff ffff ffff ffff, but then it follows up with
+ // 0x04->0x02->0x06->0x11->0x04->0x02->0x06 command sequence
+ // (and current implementation nukes start/end FAD addresses at 0x04).
+ // I'm sure that this doesn't work like this, but there could
+ // be countless possible combinations ...
if(fadstoplay == 0)
{
cd_curfad = cdrom_get_track_start(cdrom, cur_track-1);
@@ -1130,7 +1139,8 @@ void stvcd_device::cmd_get_filter_mode()
void stvcd_device::cmd_set_filter_connection()
{
// Set Filter Connection
- /* TODO: maybe condition false is cr3 low? */
+ // FIXME: verify usage of cr3 LSB
+ // (false condition?)
uint8_t fnum = (cr3>>8)&0xff;
LOG("%s:CD: Set Filter Connection %x => mode %x parm %04x\n", machine().describe_context(), fnum, cr1 & 0xf, cr2);
@@ -1181,7 +1191,7 @@ void stvcd_device::cmd_reset_selector()
}
/* reset false filter output conditions */
- /* TODO: check these two. */
+ /// TODO: verify default value for these two
if(cr1 & 0x80)
{
for(i=0;i<MAX_FILTERS;i++)
@@ -1396,8 +1406,9 @@ void stvcd_device::cmd_get_sector_data()
if (bufnum >= MAX_FILTERS)
{
+ // TODO: find actual SW that does this
+ // (may conceal a bigger issue)
osd_printf_error("CD: invalid buffer number\n");
- /* TODO: why this is happening? */
cr_standard_return(CD_STAT_REJECT);
hirqreg |= (CMOK|EHST);
return;
@@ -1439,14 +1450,15 @@ void stvcd_device::cmd_delete_sector_data()
if (bufnum >= MAX_FILTERS)
{
+ // TODO: mustn't happen
osd_printf_error("CD: invalid buffer number\n");
- /* TODO: why this is happening? */
cr_standard_return(CD_STAT_REJECT);
hirqreg |= (CMOK|EHST);
return;
}
- /* TODO: Phantasy Star 2 throws this one. */
+ // pstarcol PS2 does this
+ // TODO: verify if implementation is correct
if (partitions[bufnum].numblks == 0)
{
osd_printf_error("CD: buffer is already empty\n");
@@ -1459,10 +1471,15 @@ void stvcd_device::cmd_delete_sector_data()
for (i = sectofs; i < (sectofs + sectnum); i++)
{
- partitions[bufnum].size -= partitions[bufnum].blocks[i]->size;
- cd_free_block(partitions[bufnum].blocks[i]);
- partitions[bufnum].blocks[i] = (blockT *)nullptr;
- partitions[bufnum].bnum[i] = 0xff;
+ // pstarcol PS2 tries to delete partial partitions,
+ // need to guard against it (otherwise it would crash after first attract cycle)
+ if (partitions[bufnum].size > 0)
+ {
+ partitions[bufnum].size -= partitions[bufnum].blocks[i]->size;
+ cd_free_block(partitions[bufnum].blocks[i]);
+ partitions[bufnum].blocks[i] = (blockT *)nullptr;
+ partitions[bufnum].bnum[i] = 0xff;
+ }
}
cd_defragblocks(&partitions[bufnum]);
@@ -1492,14 +1509,15 @@ void stvcd_device::cmd_get_and_delete_sector_data()
if (bufnum >= MAX_FILTERS)
{
+ // TODO: mustn't happen
osd_printf_error("CD: invalid buffer number\n");
- /* TODO: why this is happening? */
cr_standard_return(CD_STAT_REJECT);
hirqreg |= (CMOK|EHST);
return;
}
/* Yoshimoto Mahjong uses the REJECT status to verify when the data is ready. */
+ // TODO: verify again if it's really REJECT or something else
if (partitions[bufnum].numblks < sectnum)
{
osd_printf_error("CD: buffer is not full %08x %08x\n",partitions[bufnum].numblks,sectnum);
@@ -1708,7 +1726,11 @@ void stvcd_device::cmd_get_target_file_info()
cr3 = 0;
cr4 = 0;
- printf("%08x %08x\n",curdir[temp].firstfad,curdir[temp].length);
+ // TODO: chaossd and sengblad does this
+ // (iso9660 parsing doesn't read beyond the first sector)
+ if (curdir[temp].firstfad == 0 || curdir[temp].length == 0)
+ throw emu_fatalerror("File ID not found in XFERTYPE_FILEINFO_1");
+// printf("%08x %08x\n",curdir[temp].firstfad,curdir[temp].length);
// first 4 bytes = FAD
finfbuf[0] = (curdir[temp].firstfad>>24)&0xff;
finfbuf[1] = (curdir[temp].firstfad>>16)&0xff;
@@ -1724,6 +1746,7 @@ void stvcd_device::cmd_get_target_file_info()
finfbuf[10] = temp;
finfbuf[11] = curdir[temp].flags;
+
xfertype = XFERTYPE_FILEINFO_1;
xfercount = 0;
}
@@ -1988,8 +2011,9 @@ TIMER_DEVICE_CALLBACK_MEMBER( stvcd_device::stv_sector_cb )
else
m_sector_timer->adjust(attotime::from_hz(75*cd_speed)); // 75 / 150 sectors / second = 150 / 300kBytes/second
- /* TODO: doesn't boot if a disk isn't in? */
- /* TODO: Check out when this really happens. (Daytona USA original version definitely wants it to be on).*/
+ // TODO: Saturn refuses to boot with this if a disk isn't in and condition is applied!?
+ // TODO: Check out actual timing of SCDQ acquisition.
+ // (Daytona USA original version definitely wants it to be on).
//if(((cd_stat & 0x0f00) != CD_STAT_NODISC) && ((cd_stat & 0x0f00) != CD_STAT_OPEN))
hirqreg |= SCDQ;
diff --git a/src/devices/sound/ics2115.cpp b/src/devices/sound/ics2115.cpp
index d97ca8dea9a..0afc0787ed0 100644
--- a/src/devices/sound/ics2115.cpp
+++ b/src/devices/sound/ics2115.cpp
@@ -434,7 +434,7 @@ int ics2115_device::fill_output(ics2115_voice& voice, std::vector<write_stream_v
{
constexpr int RAMP_SHIFT = 6;
const u32 volacc = (voice.vol.acc >> 14) & 0xfff;
- const u16 vlefti = volacc - m_panlaw[255 - voice.vol.pan]; // left index from acc - pan law
+ const u16 vlefti = volacc - m_panlaw[255 - voice.vol.pan]; // left index from acc - pan law
const u16 vrighti = volacc - m_panlaw[voice.vol.pan]; // right index from acc - pan law
//check negative values so no cracks, is it a hardware feature ?
const u16 vleft = vlefti > 0 ? (m_volume[vlefti] * voice.state.ramp >> RAMP_SHIFT) : 0;
diff --git a/src/devices/video/upd3301.cpp b/src/devices/video/upd3301.cpp
index 9da9f70af7c..ed57a55d760 100644
--- a/src/devices/video/upd3301.cpp
+++ b/src/devices/video/upd3301.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Curt Coder
+// copyright-holders:Curt Coder, Angelo Salese
/**********************************************************************
NEC uPD3301 Programmable CRT Controller emulation
@@ -10,12 +10,20 @@
TODO:
- - attributes
- - N interrupt
+ - pinpoint how much of pc8001/pc8801 drawing functions should actually be inherited
+ here;
+ - N interrupt (special control character)
- light pen
- reset counters
- proper DMA timing (now the whole screen is transferred at the end of the frame,
accurate timing requires CCLK timer which kills performance)
+ - DMA burst mode;
+ - cleanup: variable namings should be more verbose
+ (i.e. not be a single letter like m_y, m_z, m_b ...);
+ - sorcerml (pc8801) has buggy DMA burst mode, causing an underrun (hence a status U interrupt);
+ - jettermi (pc8801) expects to colorize its underlying 400 b&w mode by masking with the
+ text color attributes here;
+ - xak2 (pc8801) throws text garbage on legacy renderer (verify);
*/
@@ -77,33 +85,35 @@ DEFINE_DEVICE_TYPE(UPD3301, upd3301_device, "upd3301", "NEC uPD3301")
// upd3301_device - constructor
//-------------------------------------------------
-upd3301_device::upd3301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, UPD3301, tag, owner, clock),
- device_video_interface(mconfig, *this),
- m_write_int(*this),
- m_write_drq(*this),
- m_write_hrtc(*this),
- m_write_vrtc(*this),
- m_display_cb(*this),
- m_width(0),
- m_status(0),
- m_param_count(0),
- m_data_fifo_pos(0),
- m_attr_fifo_pos(0),
- m_input_fifo(0),
- m_me(0),
- m_h(80),
- m_l(20),
- m_r(10),
- m_v(6),
- m_z(32),
- m_attr_blink(0),
- m_attr_frame(0),
- m_cm(0),
- m_cx(0),
- m_cy(0),
- m_cursor_blink(0),
- m_cursor_frame(0)
+upd3301_device::upd3301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, UPD3301, tag, owner, clock)
+ , device_video_interface(mconfig, *this)
+ , m_write_int(*this)
+ , m_write_drq(*this)
+ , m_write_hrtc(*this)
+ , m_write_vrtc(*this)
+ , m_write_rvv(*this)
+ , m_display_cb(*this)
+ , m_attr_fetch_cb(*this)
+ , m_width(0)
+ , m_status(0)
+ , m_param_count(0)
+ , m_data_fifo_pos(0)
+ , m_attr_fifo_pos(0)
+ , m_input_fifo(0)
+ , m_me(0)
+ , m_h(80)
+ , m_l(20)
+ , m_r(10)
+ , m_v(6)
+ , m_z(32)
+ , m_attr_blink(0)
+ , m_attr_frame(0)
+ , m_cm(0)
+ , m_cx(0)
+ , m_cy(0)
+ , m_cursor_blink(0)
+ , m_cursor_frame(0)
{
}
@@ -120,7 +130,9 @@ void upd3301_device::device_start()
m_write_int.resolve_safe();
m_write_hrtc.resolve_safe();
m_write_vrtc.resolve_safe();
+ m_write_rvv.resolve();
m_display_cb.resolve();
+ m_attr_fetch_cb.resolve();
// allocate timers
m_hrtc_timer = timer_alloc(TIMER_HRTC);
@@ -148,9 +160,7 @@ void upd3301_device::device_start()
save_item(NAME(m_r));
save_item(NAME(m_v));
save_item(NAME(m_z));
- save_item(NAME(m_at1));
- save_item(NAME(m_at0));
- save_item(NAME(m_sc));
+ save_item(NAME(m_gfx_mode));
save_item(NAME(m_attr));
save_item(NAME(m_attr_blink));
save_item(NAME(m_attr_frame));
@@ -161,6 +171,7 @@ void upd3301_device::device_start()
save_item(NAME(m_cursor_frame));
save_item(NAME(m_data_fifo));
save_item(NAME(m_attr_fifo));
+ save_item(NAME(m_reverse_display));
}
@@ -173,6 +184,10 @@ void upd3301_device::device_reset()
set_interrupt(0);
set_drq(0);
+ m_cm = 0;
+ m_b = 48;
+ m_reverse_display = false;
+
recompute_parameters();
}
@@ -191,40 +206,68 @@ void upd3301_device::device_clock_changed()
// device_timer - handle timer events
//-------------------------------------------------
+// this snipped was inside screen_update fn
+// bad idea: it causes all sort of desync glitches when emulation unthrottles
+// TODO: verify if FIFO clear-out happens on vblank-in or -out
+inline void upd3301_device::reset_fifo_vrtc()
+{
+ m_y = 0;
+ m_data_fifo_pos = 0;
+ m_attr_fifo_pos = 0;
+
+ m_cursor_frame++;
+
+ if (m_cursor_frame == m_b)
+ {
+ m_cursor_frame = 0;
+ m_cursor_blink = !m_cursor_blink;
+ }
+
+ m_attr_frame++;
+ if (m_attr_frame == (m_b << 1))
+ {
+ m_attr_frame = 0;
+ m_attr_blink = !m_attr_blink;
+ }
+}
+
void upd3301_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
- case TIMER_HRTC:
- LOG("UPD3301 HRTC: %u\n", param);
+ case TIMER_HRTC:
+ LOG("UPD3301 HRTC: %u\n", param);
- m_write_hrtc(param);
- m_hrtc = param;
+ m_write_hrtc(param);
+ m_hrtc = param;
- update_hrtc_timer(param);
- break;
+ update_hrtc_timer(param);
+ break;
- case TIMER_VRTC:
- LOG("UPD3301 VRTC: %u\n", param);
+ case TIMER_VRTC:
+ LOG("UPD3301 VRTC: %u\n", param);
- m_write_vrtc(param);
- m_vrtc = param;
+ m_write_vrtc(param);
+ m_vrtc = param;
- update_vrtc_timer(param);
- if(!(m_status & STATUS_VE))
- break;
+ update_vrtc_timer(param);
+ if(!(m_status & STATUS_VE))
+ break;
- if (param && !m_me)
- {
- m_status |= STATUS_E;
- set_interrupt(1);
- }
- else if(!param)
- set_drq(1);
- break;
+ if(!param)
+ reset_fifo_vrtc();
+
+ if (param && !m_me)
+ {
+ m_status |= STATUS_E;
+ set_interrupt(1);
+ }
+ else if(!param)
+ set_drq(1);
+ break;
- case TIMER_DRQ:
- break;
+ case TIMER_DRQ:
+ break;
}
}
@@ -239,13 +282,16 @@ uint8_t upd3301_device::read(offs_t offset)
switch (offset & 0x01)
{
- case 0: // data
- break;
+ case 0: // data
+ // TODO: light pen
+ if (!machine().side_effects_disabled())
+ popmessage("light pen reading");
+ break;
- case 1: // status
- data = m_status;
- m_status &= ~(STATUS_LP | STATUS_E |STATUS_N | STATUS_U);
- break;
+ case 1: // status
+ data = m_status;
+ m_status &= ~(STATUS_LP | STATUS_E |STATUS_N | STATUS_U);
+ break;
}
return data;
@@ -260,135 +306,185 @@ void upd3301_device::write(offs_t offset, uint8_t data)
{
switch (offset & 0x01)
{
- case 0: // data
- switch (m_mode)
- {
- case MODE_RESET:
- switch (m_param_count)
+ case 0: // data
+ switch (m_mode)
{
- case 0:
- m_dma_mode = BIT(data, 7);
- m_h = (data & 0x7f) + 2;
- LOG("UPD3301 DMA Mode: %s\n", m_dma_mode ? "character" : "burst");
- LOG("UPD3301 H: %u\n", m_h);
+ case MODE_RESET:
+ switch (m_param_count)
+ {
+ case 0:
+ m_dma_mode = BIT(data, 7);
+ // number of characters per line -2
+ // TODO: doesn't seem to like anything beyond 80
+ m_h = (data & 0x7f) + 2;
+ if (m_h > 80)
+ popmessage("Illegal width set %d", m_h);
+ LOG("UPD3301 DMA Mode: %s\n", m_dma_mode ? "character" : "burst");
+ LOG("UPD3301 H: %u\n", m_h);
+ break;
+
+ case 1:
+ // cursor/attribute blink rate
+ m_b = ((data >> 6) + 1) * 16;
+ // number of lines displayed -1
+ // (or in other words, tilemap y size)
+ m_l = (data & 0x3f) + 1;
+ LOG("UPD3301 B: %u\n", m_b);
+ LOG("UPD3301 L: %u\n", m_l);
+ break;
+
+ case 2:
+ // skip line (pseudo-interlace?)
+ m_s = BIT(data, 7);
+ if (m_s)
+ popmessage("skip line enable");
+ // cursor mode
+ // (00) not blinking underline cursor
+ // (01) blinking underline cursor
+ // (10) not blinking solid cursor
+ // (11) blinking solid cursor
+ // NB: there must be at least 14 lines per char to make underline valid
+ m_c = (data >> 5) & 0x03;
+ if (m_c != 3)
+ popmessage("cursor mode %02x", m_c);
+ // Number of lines per character -1
+ m_r = (data & 0x1f) + 1;
+ LOG("UPD3301 S: %u\n", m_s);
+ LOG("UPD3301 C: %u\n", m_c);
+ LOG("UPD3301 R: %u\n", m_r);
+ break;
+
+ case 3:
+ // vblank lines -1 (1 to 8)
+ m_v = (data >> 5) + 1;
+ // hblank width -2 (6 to 33)
+ m_z = (data & 0x1f) + 2;
+ LOG("UPD3301 V: %u\n", m_v);
+ LOG("UPD3301 Z: %u\n", m_z);
+ recompute_parameters();
+ break;
+
+ case 4:
+ // AT|SC
+ // (00|0) transparent b&w with special control character
+ // (00|1) no attributes, no special control
+ // (01|0) transparent color
+ // (10|0) non-transparent b&w, special control
+ // (10|1) non-transparent b&w, no special control
+ // any other setting are invalid
+ //m_at1 = BIT(data, 7);
+ //m_at0 = BIT(data, 6);
+ //m_sc = BIT(data, 5);
+ m_gfx_mode = (data & 0xe0) >> 5;
+ if (m_gfx_mode & 0x5)
+ popmessage("attr mode %02x", m_gfx_mode);
+ // Max number of attributes per line -1
+ // can't be higher than 20
+ m_attr = std::min((data & 0x1f) + 1, 20);
+ LOG("UPD3301 AT1: %u AT0: %u SC: %u\n", BIT(data, 7), BIT(data, 6), BIT(data, 5));
+ LOG("UPD3301 ATTR: %u\n", m_attr);
+
+ m_mode = MODE_NONE;
+ break;
+ }
+
+ m_param_count++;
break;
- case 1:
- m_b = ((data >> 6) + 1) * 16;
- m_l = (data & 0x3f) + 1;
- LOG("UPD3301 B: %u\n", m_b);
- LOG("UPD3301 L: %u\n", m_l);
- break;
+ case MODE_LOAD_CURSOR_POSITION:
+ switch (m_param_count)
+ {
+ case 0:
+ m_cx = data & 0x7f;
+ LOG("UPD3301 CX: %u\n", m_cx);
+ break;
- case 2:
- m_s = BIT(data, 7);
- m_c = (data >> 4) & 0x03;
- m_r = (data & 0x1f) + 1;
- LOG("UPD3301 S: %u\n", m_s);
- LOG("UPD3301 C: %u\n", m_c);
- LOG("UPD3301 R: %u\n", m_r);
- break;
+ case 1:
+ m_cy = data & 0x3f;
+ LOG("UPD3301 CY: %u\n", m_cy);
- case 3:
- m_v = (data >> 5) + 1;
- m_z = (data & 0x1f) + 2;
- LOG("UPD3301 V: %u\n", m_v);
- LOG("UPD3301 Z: %u\n", m_z);
- recompute_parameters();
- break;
+ m_mode = MODE_NONE;
+ break;
+ }
- case 4:
- m_at1 = BIT(data, 7);
- m_at0 = BIT(data, 6);
- m_sc = BIT(data, 5);
- m_attr = (data & 0x1f) + 1;
- LOG("UPD3301 AT1: %u\n", m_at1);
- LOG("UPD3301 AT0: %u\n", m_at0);
- LOG("UPD3301 SC: %u\n", m_sc);
- LOG("UPD3301 ATTR: %u\n", m_attr);
-
- m_mode = MODE_NONE;
+ m_param_count++;
break;
- }
- m_param_count++;
+ default:
+ LOG("UPD3301 Invalid Parameter Byte %02x!\n", data);
+ }
break;
- case MODE_LOAD_CURSOR_POSITION:
- switch (m_param_count)
+ case 1: // command
+ m_mode = MODE_NONE;
+ m_param_count = 0;
+
+ switch (data & 0xe0)
{
- case 0:
- m_cx = data & 0x7f;
- LOG("UPD3301 CX: %u\n", m_cx);
+ case COMMAND_RESET:
+ LOG("UPD3301 Reset\n");
+ m_mode = MODE_RESET;
+ // TODO: this also disables external display such as Graphic VRAM in PC-8801
+ set_display(0);
+ set_interrupt(0);
break;
- case 1:
- m_cy = data & 0x3f;
- LOG("UPD3301 CY: %u\n", m_cy);
-
- m_mode = MODE_NONE;
+ case COMMAND_START_DISPLAY:
+ {
+ LOG("UPD3301 Start Display\n");
+ bool new_rvv = bool(BIT(data, 0));
+ // misscmd (pc8001) enables this
+ if (m_reverse_display != new_rvv)
+ {
+ m_reverse_display = new_rvv;
+ if (!m_write_rvv.isnull())
+ m_write_rvv(m_reverse_display);
+ else if (m_reverse_display == true)
+ logerror("%s: reverse display enabled (warning)\n", machine().describe_context());
+ }
+ set_display(1);
+ reset_counters();
break;
}
- m_param_count++;
- break;
-
- default:
- LOG("UPD3301 Invalid Parameter Byte %02x!\n", data);
- }
- break;
-
- case 1: // command
- m_mode = MODE_NONE;
- m_param_count = 0;
-
- switch (data & 0xe0)
- {
- case COMMAND_RESET:
- LOG("UPD3301 Reset\n");
- m_mode = MODE_RESET;
- set_display(0);
- set_interrupt(0);
- break;
-
- case COMMAND_START_DISPLAY:
- LOG("UPD3301 Start Display\n");
- set_display(1);
- reset_counters();
- break;
-
- case COMMAND_SET_INTERRUPT_MASK:
- LOG("UPD3301 Set Interrupt Mask\n");
- m_me = BIT(data, 0);
- m_mn = BIT(data, 1);
- LOG("UPD3301 ME: %u\n", m_me);
- LOG("UPD3301 MN: %u\n", m_mn);
- break;
+ case COMMAND_SET_INTERRUPT_MASK:
+ LOG("UPD3301 Set Interrupt Mask\n");
+ // vblank irq mask
+ m_me = BIT(data, 0);
+ // special control character irq mask
+ m_mn = BIT(data, 1);
+ // TODO: writing a negated bit 0 makes status bit 7 to be held high?
+ LOG("UPD3301 ME: %u\n", m_me);
+ LOG("UPD3301 MN: %u\n", m_mn);
+ break;
- case COMMAND_READ_LIGHT_PEN:
- LOG("UPD3301 Read Light Pen\n");
- m_mode = MODE_READ_LIGHT_PEN;
- break;
+ case COMMAND_READ_LIGHT_PEN:
+ LOG("UPD3301 Read Light Pen\n");
+ // TODO: similar to cursor parameters except on read
+ // (plus an HR to bit 7 param [0])
+ m_mode = MODE_READ_LIGHT_PEN;
+ break;
- case COMMAND_LOAD_CURSOR_POSITION:
- LOG("UPD3301 Load Cursor Position\n");
- m_mode = MODE_LOAD_CURSOR_POSITION;
- m_cm = BIT(data, 0);
- LOG("UPD3301 CM: %u\n", m_cm);
- break;
+ case COMMAND_LOAD_CURSOR_POSITION:
+ LOG("UPD3301 Load Cursor Position\n");
+ m_mode = MODE_LOAD_CURSOR_POSITION;
+ // (1) show cursor (0) disable cursor
+ m_cm = BIT(data, 0);
+ LOG("UPD3301 CM: %u\n", m_cm);
+ break;
- case COMMAND_RESET_INTERRUPT:
- LOG("UPD3301 Reset Interrupt\n");
- set_interrupt(0);
- break;
+ case COMMAND_RESET_INTERRUPT:
+ LOG("UPD3301 Reset Interrupt\n");
+ set_interrupt(0);
+ break;
- case COMMAND_RESET_COUNTERS:
- LOG("UPD3301 Reset Counters\n");
- m_mode = MODE_RESET_COUNTERS;
- reset_counters();
+ case COMMAND_RESET_COUNTERS:
+ LOG("UPD3301 Reset Counters\n");
+ m_mode = MODE_RESET_COUNTERS;
+ reset_counters();
+ break;
+ }
break;
- }
- break;
}
}
@@ -406,17 +502,23 @@ void upd3301_device::dack_w(uint8_t data)
if (m_data_fifo_pos < m_h)
{
- m_data_fifo[m_data_fifo_pos][m_input_fifo] = data;
+ m_data_fifo[m_input_fifo][m_data_fifo_pos] = data;
m_data_fifo_pos++;
}
else
{
- m_attr_fifo[m_attr_fifo_pos][m_input_fifo] = data;
+ m_attr_fifo[m_input_fifo][m_attr_fifo_pos] = data;
m_attr_fifo_pos++;
}
if ((m_data_fifo_pos == m_h) && (m_attr_fifo_pos == (m_attr << 1)))
{
+ const u8 attr_max_size = 80;
+ // first attribute start is always overwritten with a 0
+ m_attr_fifo[m_input_fifo][0] = 0;
+ // last parameter always extends up to the end of the row
+ // (7narabe (pc8001) fills last row value with white when exausting available slots)
+ m_attr_fifo[m_input_fifo][40] = attr_max_size;
m_input_fifo = !m_input_fifo;
m_data_fifo_pos = 0;
@@ -466,23 +568,70 @@ int upd3301_device::vrtc_r()
// draw_scanline -
//-------------------------------------------------
+UPD3301_FETCH_ATTRIBUTE( upd3301_device::default_attr_fetch )
+{
+ const u8 attr_max_size = 80;
+ std::array<u16, attr_max_size> attr_extend_info;
+
+ // TODO: uPD3301 may actually fetch in LIFO order
+ for (int ex = 0; ex < attr_fifo_size; ex+=2)
+ {
+ u8 attr_start = std::min(attr_row[ex], attr_max_size);
+ u8 attr_value = attr_row[ex+1];
+ u8 attr_end = std::min(attr_row[ex+2], attr_max_size);
+ // if the target is == 0 then just consider max size instead
+ // (starfire (pc8001) wants this otherwise will black screen on gameplay)
+ if (attr_end == 0)
+ attr_end = attr_max_size;
+
+ //printf("%04x %d %d [%02x]\n", ex, attr_start, attr_end, attr_value);
+
+ for (int i = attr_start; i < attr_end; i++)
+ attr_extend_info[i] = attr_value;
+
+ if (attr_end == attr_max_size)
+ break;
+ }
+
+ return attr_extend_info;
+}
+
void upd3301_device::draw_scanline()
{
+ // Olympia Boss never bothers in writing a correct attribute table for rows on resident OS,
+ // it just extends the full attribute RAM with a start: 0 end: 0xff value: 0.
+ // According to doc notes anything beyond width 80 is puked by the CRTC, therefore we clamp.
+ const u8 attr_max_size = 80;
+ const std::array<u8, 41> attr_fifo = m_attr_fifo[!m_input_fifo];
+
+ // expose attribute handling to our client
+ // PC-8801 schematics definitely shows extra TTL connections for handling its "8 to 16-bit" attribute conversion.
+ // It also practically needs to read the attribute mapping for various extra side-effects such as colorized 400 line 1bpp
+ // cfr. "その他 / other" section at http://mydocuments.g2.xrea.com/html/p8/vraminfo.html
+ std::array<u16, attr_max_size> extend_attr = m_attr_fetch_cb(attr_fifo, m_gfx_mode, m_y, m_attr << 1, m_h);
+
for (int lc = 0; lc < m_r; lc++)
{
+ bool is_lowestline = lc == m_r - 1;
for (int sx = 0; sx < m_h; sx++)
{
int y = m_y + lc;
- uint8_t cc = m_data_fifo[sx][!m_input_fifo];
- int hlgt = 0; // TODO
- int rvv = 0; // TODO
- int vsp = 0; // TODO
- int sl0 = 0; // TODO
- int sl12 = 0; // TODO
+ uint8_t cc = m_data_fifo[!m_input_fifo][sx];
int csr = m_cm && m_cursor_blink && ((y / m_r) == m_cy) && (sx == m_cx);
- int gpa = 0; // TODO
- m_display_cb(m_bitmap, y, sx, cc, lc, hlgt, rvv, vsp, sl0, sl12, csr, gpa);
+ // datasheet mentions these but I find zero unambiguous information for PC-8001/PC-8801, i.e.:
+ // - "highlight" should be attribute blinking?
+ // - is "gpa" actually NEC-ese for attr bus?
+ // - is sl0 / sl12 NEC names for upper/lower line?
+// int hlgt = 0;
+// int rvv = 0;
+// int vsp = 0;
+// int sl0 = 0;
+// int sl12 = 0;
+// int gpa = 0;
+
+// m_display_cb(m_bitmap, y, sx, cc, lc, hlgt, rvv, vsp, sl0, sl12, csr, gpa);
+ m_display_cb(m_bitmap, y, sx, cc, lc, csr, m_attr_blink, extend_attr[sx], m_gfx_mode, is_lowestline);
}
}
@@ -496,33 +645,13 @@ void upd3301_device::draw_scanline()
uint32_t upd3301_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- if (m_status & STATUS_VE)
- {
- m_y = 0;
- m_data_fifo_pos = 0;
- m_attr_fifo_pos = 0;
+ bitmap.fill(rgb_t(0x00,0x00,0x00), cliprect);
- m_cursor_frame++;
+ if (!(m_status & STATUS_VE))
+ return 0;
- if (m_cursor_frame == m_b)
- {
- m_cursor_frame = 0;
- m_cursor_blink = !m_cursor_blink;
- }
-
- m_attr_frame++;
+ copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
- if (m_attr_frame == (m_b << 1))
- {
- m_attr_frame = 0;
- m_attr_blink = !m_attr_blink;
- }
- copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
- }
- else
- {
- bitmap.fill(rgb_t(0x00,0x00,0x00), cliprect);
- }
return 0;
}
diff --git a/src/devices/video/upd3301.h b/src/devices/video/upd3301.h
index 281c17a9980..7532dc61c5b 100644
--- a/src/devices/video/upd3301.h
+++ b/src/devices/video/upd3301.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Curt Coder
+// copyright-holders:Curt Coder, Angelo Salese
/**********************************************************************
NEC uPD3301 Programmable CRT Controller emulation
@@ -40,8 +40,10 @@
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
-#define UPD3301_DRAW_CHARACTER_MEMBER(_name) void _name(bitmap_rgb32 &bitmap, int y, int sx, uint8_t cc, uint8_t lc, int hlgt, int rvv, int vsp, int sl0, int sl12, int csr, int gpa)
+//#define UPD3301_DRAW_CHARACTER_MEMBER(_name) void _name(bitmap_rgb32 &bitmap, int y, int sx, uint8_t cc, uint8_t lc, int hlgt, int rvv, int vsp, int sl0, int sl12, int csr, int gpa)
+#define UPD3301_DRAW_CHARACTER_MEMBER(_name) void _name(bitmap_rgb32 &bitmap, int y, int sx, uint8_t cc, uint8_t lc, int csr, bool attr_blink_on, u16 attr, u8 gfx_mode, bool is_lowestline)
+#define UPD3301_FETCH_ATTRIBUTE(_name) std::array<u16, 80> _name(const std::array<u8, 41> attr_row, u8 gfx_mode, int y, u8 attr_fifo_size, u8 row_size)
//**************************************************************************
// TYPE DEFINITIONS
@@ -54,18 +56,24 @@ class upd3301_device : public device_t,
public device_video_interface
{
public:
- typedef device_delegate<void (bitmap_rgb32 &bitmap, int y, int sx, uint8_t cc, uint8_t lc, int hlgt, int rvv, int vsp, int sl0, int sl12, int csr, int gpa)> draw_character_delegate;
+// typedef device_delegate<void (bitmap_rgb32 &bitmap, int y, int sx, uint8_t cc, uint8_t lc, int hlgt, int rvv, int vsp, int sl0, int sl12, int csr, int gpa)> draw_character_delegate;
+ typedef device_delegate<void (bitmap_rgb32 &bitmap, int y, int sx, uint8_t cc, uint8_t lc, int csr, bool attr_blink_on, u16 attr, u8 gfx_mode, bool is_lowerline)> draw_character_delegate;
+ typedef device_delegate<std::array<u16, 80> (const std::array<u8, 41> attr_row, u8 gfx_mode, int y, u8 attr_fifo_size, u8 row_size)> fetch_attribute_delegate;
// construction/destruction
upd3301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void set_character_width(int value) { m_width = value; }
template <typename... T> void set_display_callback(T &&... args) { m_display_cb.set(std::forward<T>(args)...); }
+ template <typename... T> void set_attribute_fetch_callback(T &&... args) { m_attr_fetch_cb.set(std::forward<T>(args)...); }
+
+ UPD3301_FETCH_ATTRIBUTE( default_attr_fetch );
auto drq_wr_callback() { return m_write_drq.bind(); }
auto int_wr_callback() { return m_write_int.bind(); }
auto hrtc_wr_callback() { return m_write_hrtc.bind(); }
auto vrtc_wr_callback() { return m_write_vrtc.bind(); }
+ auto rvv_wr_callback() { return m_write_rvv.bind(); }
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
@@ -100,13 +108,16 @@ private:
void recompute_parameters();
void draw_scanline();
+ inline void reset_fifo_vrtc();
devcb_write_line m_write_int;
devcb_write_line m_write_drq;
devcb_write_line m_write_hrtc;
devcb_write_line m_write_vrtc;
+ devcb_write_line m_write_rvv;
draw_character_delegate m_display_cb;
+ fetch_attribute_delegate m_attr_fetch_cb;
int m_width;
// screen drawing
@@ -121,8 +132,8 @@ private:
int m_param_count; // parameter count
// FIFOs
- uint8_t m_data_fifo[80][2]; // row data FIFO
- uint8_t m_attr_fifo[40][2]; // attribute FIFO
+ u8 m_data_fifo[2][80]; // row data FIFO
+ std::array<std::array<u8, 40+1>, 2> m_attr_fifo; // attribute FIFO (+1 for extending to end of row)
int m_data_fifo_pos; // row data FIFO position
int m_attr_fifo_pos; // attribute FIFO position
int m_input_fifo; // which FIFO is in input mode
@@ -143,9 +154,10 @@ private:
int m_z; // horizontal blanking width
// attributes
- int m_at1; //
- int m_at0; //
- int m_sc; //
+// int m_at1; //
+// int m_at0; //
+// int m_sc; //
+ u8 m_gfx_mode; // AT1 + AT0 + SC
int m_attr; // attributes per row
int m_attr_blink; // attribute blink
int m_attr_frame; // attribute blink frame counter
@@ -157,6 +169,9 @@ private:
int m_cursor_blink; // cursor blink
int m_cursor_frame; // cursor blink frame counter
+ // misc
+ bool m_reverse_display;
+
// timers
emu_timer *m_hrtc_timer;
emu_timer *m_vrtc_timer;
diff --git a/src/emu/validity.cpp b/src/emu/validity.cpp
index 31a89b5ce1a..590f4faccac 100644
--- a/src/emu/validity.cpp
+++ b/src/emu/validity.cpp
@@ -47,10 +47,12 @@ using test_delegate = delegate<char (void const *&)>;
// type
//-------------------------------------------------
+#if !defined(_LIBCPP_VERSION) || (_LIBCPP_VERSION >= 7000)
test_delegate make_diamond_class_delegate(char (diamond_inheritance::*func)(void const *&), diamond_inheritance *obj)
{
return test_delegate(func, obj);
}
+#endif // !defined(_LIBCPP_VERSION) || (_LIBCPP_VERSION >= 7000)
//-------------------------------------------------
@@ -1391,6 +1393,7 @@ void validate_delegates_mfp()
if (&o != addr)
osd_printf_error("Error testing delegate this pointer adjustment for virtual member function through base class pointer %p -> %p (expected %p)\n", static_cast<void const *>(static_cast<base_b *>(&o)), addr, static_cast<void const *>(&o));
+#if !defined(_LIBCPP_VERSION) || (_LIBCPP_VERSION >= 7000)
// test creating delegates for a forward-declared class
cb1 = make_diamond_class_delegate(&diamond_inheritance::get_derived_a, &d);
cb2 = make_diamond_class_delegate(&diamond_inheritance::get_derived_b, &d);
@@ -1409,8 +1412,8 @@ void validate_delegates_mfp()
if (static_cast<virtual_derived_b *>(&d) != addr)
osd_printf_error("Error testing delegate this pointer adjustment for incomplete class %p -> %p (expected %p)\n", static_cast<void const *>(&d), addr, static_cast<void const *>(static_cast<virtual_derived_b *>(&d)));
+#if defined(_MSC_VER) && !defined(__clang__)
// test MSVC extension allowing casting member pointer types across virtual inheritance relationships
-#if defined(_MSC_VER)
cb1 = make_diamond_class_delegate(&diamond_inheritance::get_base, &d);
addr = nullptr;
@@ -1419,7 +1422,8 @@ void validate_delegates_mfp()
osd_printf_error("Error testing delegate non-virtual member function dispatch for incomplete class\n");
if (static_cast<virtual_base *>(&d) != addr)
osd_printf_error("Error testing delegate this pointer adjustment for incomplete class %p -> %p (expected %p)\n", static_cast<void const *>(&d), addr, static_cast<void const *>(static_cast<virtual_base *>(&d)));
-#endif // defined(_MSC_VER)
+#endif // defined(_MSC_VER) && !defined(__clang__)
+#endif // !defined(_LIBCPP_VERSION) || (_LIBCPP_VERSION >= 7000)
}
diff --git a/src/frontend/mame/infoxml.cpp b/src/frontend/mame/infoxml.cpp
index 44c4aac98d6..99faf0cbd68 100644
--- a/src/frontend/mame/infoxml.cpp
+++ b/src/frontend/mame/infoxml.cpp
@@ -52,6 +52,51 @@ public:
bool operator()(const std::add_pointer_t<device_type> &lhs, const std::add_pointer_t<device_type> &rhs) const;
};
+
+class device_filter
+{
+public:
+ device_filter(const std::function<bool(const char *shortname, bool &done)> &callback)
+ : m_callback(callback)
+ , m_done(false)
+ {
+ }
+
+ // methods
+ bool filter(const char *shortname);
+
+ // accessors
+ bool done() const { return m_done; }
+
+private:
+ const std::function<bool(const char *shortname, bool &done)> & m_callback;
+ bool m_done;
+};
+
+
+class filtered_driver_enumerator
+{
+public:
+ filtered_driver_enumerator(driver_enumerator &drivlist, device_filter &devfilter)
+ : m_drivlist(drivlist)
+ , m_devfilter(devfilter)
+ , m_done(false)
+ {
+ }
+
+ // methods
+ std::vector<std::reference_wrapper<const game_driver>> next(int count);
+
+ // accessors
+ bool done() const { return m_done || m_devfilter.done(); }
+
+private:
+ driver_enumerator & m_drivlist;
+ device_filter & m_devfilter;
+ bool m_done;
+};
+
+
typedef std::set<std::add_pointer_t<device_type>, device_type_compare> device_type_set;
std::string normalize_string(const char *string);
@@ -386,16 +431,22 @@ void info_xml_creator::output(std::ostream &out, const std::function<bool(const
{
struct prepared_info
{
+ prepared_info() = default;
+ prepared_info(const prepared_info &) = delete;
+ prepared_info(prepared_info &&) = default;
+ prepared_info &operator=(const prepared_info &) = delete;
+
std::string m_xml_snippet;
device_type_set m_dev_set;
};
// prepare a driver enumerator and the queue
driver_enumerator drivlist(m_lookup_options);
- bool drivlist_done = false;
- bool filter_done = false;
+ device_filter devfilter(filter);
+ filtered_driver_enumerator filtered_drivlist(drivlist, devfilter);
bool header_outputted = false;
+ // essentially a local method to emit the header if necessary
auto output_header_if_necessary = [this, &header_outputted](std::ostream &out)
{
if (!header_outputted)
@@ -406,79 +457,97 @@ void info_xml_creator::output(std::ostream &out, const std::function<bool(const
};
// only keep a device set when we're asked to track it
- std::unique_ptr<device_type_set> devfilter;
+ std::optional<device_type_set> devset;
if (include_devices && filter)
- devfilter = std::make_unique<device_type_set>();
+ devset.emplace();
+
+ // prepare a queue of tasks - this is a FIFO queue because of the
+ // need to be deterministic
+ std::queue<std::future<prepared_info>> tasks;
- // prepare a queue of futures
- std::queue<std::future<prepared_info>> queue;
+ // while we want to be deterministic, asynchronous task scheduling is not; so we want to
+ // track the amount of active tasks so that we can keep on spawning tasks even if we're
+ // waiting on the task in the front of the queue
+ std::atomic<unsigned int> active_task_count = 0;
+ unsigned int maximum_active_task_count = std::thread::hardware_concurrency() + 10;
+ unsigned int maximum_outstanding_task_count = maximum_active_task_count + 20;
- // try enumerating drivers and outputting them
- while (!queue.empty() || (!drivlist_done && !filter_done))
+ // loop until we're done enumerating drivers, and until there are no outstanding tasks
+ while (!filtered_drivlist.done() || !tasks.empty())
{
- // try populating the queue
- while (queue.size() < 20 && !drivlist_done && !filter_done)
+ // loop until there are as many outstanding tasks as possible (we want to separately cap outstanding
+ // tasks and active tasks)
+ while (!filtered_drivlist.done()
+ && active_task_count < maximum_active_task_count
+ && tasks.size() < maximum_outstanding_task_count)
{
- if (!drivlist.next())
- {
- // at this point we are done enumerating through drivlist and it is no
- // longer safe to call next(), so record that we're done
- drivlist_done = true;
- }
- else if (!filter || filter(drivlist.driver().name, filter_done))
+ // we want to launch a task; grab a packet of drivers to process
+ std::vector<std::reference_wrapper<const game_driver>> drivers = filtered_drivlist.next(20);
+ if (drivers.empty())
+ break;
+
+ // do the dirty work asychronously
+ auto task_proc = [&drivlist, drivers{ std::move(drivers) }, include_devices, &active_task_count]
{
- const game_driver &driver(drivlist.driver());
- std::future<prepared_info> future_pi = std::async(std::launch::async, [&drivlist, &driver, &devfilter]
- {
- prepared_info result;
- std::ostringstream stream;
-
- output_one(stream, drivlist, driver, devfilter ? &result.m_dev_set : nullptr);
- result.m_xml_snippet = stream.str();
- return result;
- });
- queue.push(std::move(future_pi));
- }
+ prepared_info result;
+ std::ostringstream stream;
+
+ // output each of the drivers
+ for (const game_driver &driver : drivers)
+ output_one(stream, drivlist, driver, include_devices ? &result.m_dev_set : nullptr);
+
+ // capture the XML snippet
+ result.m_xml_snippet = stream.str();
+
+ // we're done with the task; decrement the counter and return
+ active_task_count--;
+ return result;
+ };
+
+ // add this task to the queue
+ active_task_count++;
+ tasks.emplace(std::async(std::launch::async, std::move(task_proc)));
}
- // now that we have the queue populated, try grabbing one (assuming that it is not empty)
- if (!queue.empty())
+ // we've put as many outstanding tasks out as we can; are there any tasks outstanding?
+ if (!tasks.empty())
{
- // wait for the future to complete and get the info
- prepared_info pi = queue.front().get();
- queue.pop();
+ // wait for the task at the front of the queue to complete and get the info, in the
+ // spirit of determinism
+ prepared_info pi = tasks.front().get();
+ tasks.pop();
- // emit the XML
+ // emit whatever XML we accumulated in the task
output_header_if_necessary(out);
out << pi.m_xml_snippet;
- // merge devices into devfilter, if appropriate
- if (devfilter)
+ // merge devices into devset, if appropriate
+ if (devset)
{
for (const auto &x : pi.m_dev_set)
- devfilter->insert(x);
+ devset->insert(x);
}
}
}
// iterate through the device types if not everything matches a driver
- if (devfilter && !filter_done)
+ if (devset && !devfilter.done())
{
for (device_type type : registered_device_types)
{
- if (!filter || filter(type.shortname(), filter_done))
- devfilter->insert(&type);
+ if (devfilter.filter(type.shortname()))
+ devset->insert(&type);
- if (filter_done)
+ if (devfilter.done())
break;
}
}
// output devices (both devices with roms and slot devices)
- if (include_devices && (!devfilter || !devfilter->empty()))
+ if (include_devices && (!devset || !devset->empty()))
{
output_header_if_necessary(out);
- output_devices(out, m_lookup_options, devfilter.get());
+ output_devices(out, m_lookup_options, devset ? &*devset : nullptr);
}
if (header_outputted)
@@ -523,6 +592,43 @@ std::string normalize_string(const char *string)
//-------------------------------------------------
+// device_filter::filter - apply the filter, if
+// present
+//-------------------------------------------------
+
+bool device_filter::filter(const char *shortname)
+{
+ return !m_done && (!m_callback || m_callback(shortname, m_done));
+}
+
+
+//-------------------------------------------------
+// filtered_driver_enumerator::next - take a number
+// of game_drivers, while applying filters
+//-------------------------------------------------
+
+std::vector<std::reference_wrapper<const game_driver>> filtered_driver_enumerator::next(int count)
+{
+ std::vector<std::reference_wrapper<const game_driver>> results;
+ while (!done() && results.size() < count)
+ {
+ if (!m_drivlist.next())
+ {
+ // at this point we are done enumerating through drivlist and it is no
+ // longer safe to call next(), so record that we're done
+ m_done = true;
+ }
+ else if (m_devfilter.filter(m_drivlist.driver().name))
+ {
+ const game_driver &driver(m_drivlist.driver());
+ results.push_back(driver);
+ }
+ }
+ return results;
+}
+
+
+//-------------------------------------------------
// output_header - print the XML DTD and open
// the root element
//-------------------------------------------------
diff --git a/src/frontend/mame/ui/viewgfx.cpp b/src/frontend/mame/ui/viewgfx.cpp
index 1c263fed451..b10a62aee13 100644
--- a/src/frontend/mame/ui/viewgfx.cpp
+++ b/src/frontend/mame/ui/viewgfx.cpp
@@ -96,7 +96,7 @@ struct ui_gfx_state
int yoffs; // current Y offset
int zoom; // zoom factor, either x or 1/x
bool zoom_frac; // zoom via reciprocal fractions
- bool auto_zoom; // auto-zoom toggle
+ bool auto_zoom; // auto-zoom toggle
uint8_t rotate; // current rotation (orientation) value
uint32_t flags; // render flags
} tilemap;
diff --git a/src/lib/formats/rpk.cpp b/src/lib/formats/rpk.cpp
index a5b146d74aa..6171b6a4cb0 100644
--- a/src/lib/formats/rpk.cpp
+++ b/src/lib/formats/rpk.cpp
@@ -2,48 +2,48 @@
// copyright-holders:Michael Zapf
/***************************************************************************
- rpk.cpp
+ rpk.cpp
- RPK format support
+ RPK format support
- A RPK file ("rompack") contains a collection of dump files and a layout
- file that defines the kind of circuit board (PCB) used in the cartridge
- and the mapping of dumps to sockets on the board.
+ A RPK file ("rompack") contains a collection of dump files and a layout
+ file that defines the kind of circuit board (PCB) used in the cartridge
+ and the mapping of dumps to sockets on the board.
Example:
- <?xml version="1.0" encoding="utf-8"?>
- <romset>
- <resources>
- <rom id="gromimage" file="ed-assmg.bin" />
- </resources>
- <configuration>
- <pcb type="standard">
- <socket id="grom_socket" uses="gromimage"/>
- </pcb>
- </configuration>
- </romset>
+ <?xml version="1.0" encoding="utf-8"?>
+ <romset>
+ <resources>
+ <rom id="gromimage" file="ed-assmg.bin" />
+ </resources>
+ <configuration>
+ <pcb type="standard">
+ <socket id="grom_socket" uses="gromimage"/>
+ </pcb>
+ </configuration>
+ </romset>
DTD:
- <!ELEMENT romset (resources, configuration)>
- <!ELEMENT resources (rom|ram)+>
- <!ELEMENT rom EMPTY>
- <!ELEMENT ram EMPTY>
- <!ELEMENT configuration (pcb)>
- <!ELEMENT pcb (socket)+>
- <!ELEMENT socket EMPTY>
- <!ATTLIST romset version CDATA #IMPLIED>
- <!ATTLIST rom id ID #REQUIRED
- <!ATTLIST rom file CDATA #REQUIRED>
- <!ATTLIST rom crc CDATA #IMPLIED>
- <!ATTLIST rom sha1 CDATA #IMPLIED>
- <!ATTLIST ram id ID #REQUIRED>
- <!ATTLIST ram type (volatile|persistent) #IMPLIED>
- <!ATTLIST ram store (internal|external) #IMPLIED>
- <!ATTLIST ram file CDATA #IMPLIED>
- <!ATTLIST ram length CDATA #REQUIRED>
- <!ATTLIST pcb type CDATA #REQUIRED>
- <!ATTLIST socket id ID #REQUIRED>
- <!ATTLIST socket uses IDREF #REQUIRED>
+ <!ELEMENT romset (resources, configuration)>
+ <!ELEMENT resources (rom|ram)+>
+ <!ELEMENT rom EMPTY>
+ <!ELEMENT ram EMPTY>
+ <!ELEMENT configuration (pcb)>
+ <!ELEMENT pcb (socket)+>
+ <!ELEMENT socket EMPTY>
+ <!ATTLIST romset version CDATA #IMPLIED>
+ <!ATTLIST rom id ID #REQUIRED
+ <!ATTLIST rom file CDATA #REQUIRED>
+ <!ATTLIST rom crc CDATA #IMPLIED>
+ <!ATTLIST rom sha1 CDATA #IMPLIED>
+ <!ATTLIST ram id ID #REQUIRED>
+ <!ATTLIST ram type (volatile|persistent) #IMPLIED>
+ <!ATTLIST ram store (internal|external) #IMPLIED>
+ <!ATTLIST ram file CDATA #IMPLIED>
+ <!ATTLIST ram length CDATA #REQUIRED>
+ <!ATTLIST pcb type CDATA #REQUIRED>
+ <!ATTLIST socket id ID #REQUIRED>
+ <!ATTLIST socket uses IDREF #REQUIRED>
***************************************************************************/
@@ -55,7 +55,7 @@ namespace
{
/***************************************************************************
- TYPE DEFINITIONS
+ TYPE DEFINITIONS
***************************************************************************/
class rpk_category_impl : public std::error_category
@@ -67,7 +67,7 @@ public:
/***************************************************************************
- GLOBAL VARIABLES
+ GLOBAL VARIABLES
***************************************************************************/
rpk_category_impl const f_rpk_category_instance;
@@ -75,7 +75,7 @@ rpk_category_impl const f_rpk_category_instance;
/***************************************************************************
- RPK READER
+ RPK READER
***************************************************************************/
//-------------------------------------------------
@@ -220,7 +220,7 @@ std::error_condition rpk_reader::read(std::unique_ptr<util::random_read> &&strea
/***************************************************************************
- RPK FILE
+ RPK FILE
***************************************************************************/
//-------------------------------------------------
@@ -347,7 +347,7 @@ std::error_condition rpk_file::add_ram_socket(std::string &&id, const util::xml:
/***************************************************************************
- RPK SOCKET
+ RPK SOCKET
***************************************************************************/
//-------------------------------------------------
@@ -416,7 +416,7 @@ std::error_condition rpk_socket::read_file(std::vector<std::uint8_t> &result) co
/***************************************************************************
- RPK EXCEPTION HANDLING
+ RPK EXCEPTION HANDLING
***************************************************************************/
//-------------------------------------------------
diff --git a/src/lib/formats/rpk.h b/src/lib/formats/rpk.h
index 55b6f0a4839..f6e6360c21c 100644
--- a/src/lib/formats/rpk.h
+++ b/src/lib/formats/rpk.h
@@ -2,9 +2,9 @@
// copyright-holders:Michael Zapf
/***************************************************************************
- rpk.h
+ rpk.h
- RPK format support
+ RPK format support
***************************************************************************/
@@ -22,7 +22,7 @@
/***************************************************************************
- TYPE DEFINITIONS
+ TYPE DEFINITIONS
***************************************************************************/
class rpk_reader;
@@ -57,12 +57,12 @@ public:
std::error_condition read_file(std::vector<std::uint8_t> &result) const;
private:
- rpk_file & m_rpk;
- std::string m_id;
- socket_type m_type;
- std::string m_filename;
- std::optional<util::hash_collection> m_hashes;
- std::uint32_t m_length;
+ rpk_file & m_rpk;
+ std::string m_id;
+ socket_type m_type;
+ std::string m_filename;
+ std::optional<util::hash_collection> m_hashes;
+ std::uint32_t m_length;
};
@@ -87,9 +87,9 @@ public:
const std::list<rpk_socket> &sockets() const { return m_sockets; }
private:
- util::archive_file::ptr m_zipfile;
- int m_pcb_type;
- std::list<rpk_socket> m_sockets;
+ util::archive_file::ptr m_zipfile;
+ int m_pcb_type;
+ std::list<rpk_socket> m_sockets;
// accesors
util::archive_file &zipfile() { return *m_zipfile; }
@@ -127,8 +127,8 @@ public:
std::error_condition read(std::unique_ptr<util::random_read> &&stream, rpk_file::ptr &result) const;
private:
- char const *const * m_pcb_types;
- bool m_supports_ram;
+ char const *const * m_pcb_types;
+ bool m_supports_ram;
};
diff --git a/src/lib/util/delegate.cpp b/src/lib/util/delegate.cpp
index 6f73c925da1..eff36ba6192 100644
--- a/src/lib/util/delegate.cpp
+++ b/src/lib/util/delegate.cpp
@@ -148,39 +148,76 @@ delegate_generic_function delegate_mfp_msvc::adjust_this_pointer(delegate_generi
std::uint8_t const *func = reinterpret_cast<std::uint8_t const *>(m_function);
while (true)
{
+ // Assumes Windows calling convention, and doesn't consider that
+ // the "this" pointer could be in RDX if RCX is a pointer to
+ // space for an oversize scalar result. Since the result area
+ // is uninitialised on entry, you won't see something that looks
+ // like a vtable dispatch through RCX in this case - it won't
+ // behave badly, it just won't bypass virtual call thunks in the
+ // rare situations where the return type is an oversize scalar.
if (0xe9 == func[0])
{
// relative jump with 32-bit displacement (typically a resolved PLT entry)
LOG("Found relative jump at %p ", func);
func += 5 + *reinterpret_cast<std::int32_t const *>(func + 1);
LOG("redirecting to %p\n", func);
+ continue;
}
- else if ((0x48 == func[0]) && (0x8b == func[1]) && (0x01 == func[2]) && (0xff == func[3]) && ((0x20 == func[4]) || (0x60 == func[4]) || (0xa0 == func[4])))
+ else if ((0x48 == func[0]) && (0x8b == func[1]) && (0x01 == func[2]))
{
- // virtual function call thunk - mov rax,QWORD PTR [rcx] ; jmp QWORD PTR [rax+...]
- // Assumes Windows calling convention, and doesn't consider
- // that the "this" pointer could be in RDX if RCX is a
- // pointer to space for an oversize scalar result. Since
- // the result area is uninitialised on entry, you won't see
- // something that looks like a vtable dispatch through RCX
- // in this case - it won't behave badly, it just won't
- // bypass virtual call thunks in the rare situations where
- // the return type is an oversize scalar.
- LOG("Found virtual member function thunk at %p ", func);
- std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
- if (0x20 == func[4]) // no displacement
- func = *reinterpret_cast<std::uint8_t const *const *>(vptr);
- else if (0x60 == func[4]) // 8-bit displacement
- func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int8_t const *>(func + 5));
- else // 32-bit displacement
- func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int32_t const *>(func + 5));
- LOG("redirecting to %p\n", func);
- }
- else
- {
- // not something we can easily bypass
- break;
+ if ((0xff == func[3]) && ((0x20 == func[4]) || (0x60 == func[4]) || (0xa0 == func[4])))
+ {
+ // MSVC virtual function call thunk - mov rax,QWORD PTR [rcx] ; jmp QWORD PTR [rax+...]
+ LOG("Found virtual member function thunk at %p ", func);
+ std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
+ if (0x20 == func[4]) // no displacement
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr);
+ else if (0x60 == func[4]) // 8-bit displacement
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int8_t const *>(func + 5));
+ else // 32-bit displacement
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int32_t const *>(func + 5));
+ LOG("redirecting to %p\n", func);
+ continue;
+ }
+ else if ((0x48 == func[3]) && (0x8b == func[4]))
+ {
+ // clang virtual function call thunk - mov rax,QWORD PTR [rcx] ; mov rax,QWORD PTR [rax+...] ; jmp rax
+ if ((0x40 == func[5]) && (0x48 == func[7]) && (0xff == func[8]) && (0xe0 == func[9]))
+ {
+ // 8-bit displacement
+ LOG("Found virtual member function thunk at %p ", func);
+ std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int8_t const *>(func + 6));
+ LOG("redirecting to %p\n", func);
+ continue;
+ }
+ else if ((0x80 == func[5]) && (0x48 == func[10]) && (0xff == func[11]) && (0xe0 == func[12]))
+ {
+ // 32-bit displacement
+ LOG("Found virtual member function thunk at %p ", func);
+ std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int32_t const *>(func + 6));
+ LOG("redirecting to %p\n", func);
+ continue;
+ }
+ }
}
+
+ // clang uses unoptimised thunks if optimisation is disabled
+ // Without optimisation, clang produces thunks like:
+ // 50 push rax
+ // 48 89 0c 24 mov QWORD PTR [rsp],rcx
+ // 48 8b 0c 24 mov rcx,QWORD PTR [rsp]
+ // 48 8b 01 mov rax,QWORD PTR [rcx]
+ // 48 8b 80 xx xx xx xx mov rax,QWORD PTR [rax+...]
+ // 41 5a pop r10
+ // 48 ff e0 jmp rax
+ // Trying to decode these thunks likely isn't worth the effort.
+ // Chasing performance in unoptimised builds isn't very useful,
+ // and the format of these thinks may be fragile.
+
+ // not something we can easily bypass
+ break;
}
return reinterpret_cast<delegate_generic_function>(std::uintptr_t(func));
#elif defined(__aarch64__) || defined(_M_ARM64)
@@ -190,7 +227,19 @@ delegate_generic_function delegate_mfp_msvc::adjust_this_pointer(delegate_generi
// Assumes little Endian mode. Instructions are always stored
// in little Endian format on AArch64, so if big Endian mode is
// to be supported, the values need to be swapped.
- if ((0xf9400010 == func[0]) && (0xf9400210 == (func[1] & 0xffc003ff)) && (0xd61f0200 == func[2]))
+ if ((0x90000010 == (func[0] & 0x9f00001f)) && (0x91000210 == (func[1] & 0xffc003ff)) && (0xd61f0200 == func[2]))
+ {
+ // page-relative jump with +/-4GB reach - adrp xip0,... ; add xip0,xip0,#... ; br xip0
+ LOG("Found page-relative jump at %p ", func);
+ std::int64_t const page =
+ (std::uint64_t(func[0] & 0x60000000) >> 17) |
+ (std::uint64_t(func[0] & 0x00ffffe0) << 9) |
+ ((func[0] & 0x00800000) ? (~std::uint64_t(0) << 33) : 0);
+ std::uint32_t const offset = (func[1] & 0x003ffc00) >> 10;
+ func = reinterpret_cast<std::uint32_t const *>(((std::uintptr_t(func) + page) & (~std::uintptr_t(0) << 12)) + offset);
+ LOG("redirecting to %p\n", func);
+ }
+ else if ((0xf9400010 == func[0]) && (0xf9400210 == (func[1] & 0xffc003ff)) && (0xd61f0200 == func[2]))
{
// virtual function call thunk - ldr xip0,[x0] ; ldr xip0,[x0,#...] ; br xip0
LOG("Found virtual member function thunk at %p ", func);
@@ -203,6 +252,36 @@ delegate_generic_function delegate_mfp_msvc::adjust_this_pointer(delegate_generi
// not something we can easily bypass
break;
}
+
+ // clang uses horribly sub-optimal thunks for AArch64
+ // Without optimisation, clang produces thunks like:
+ // d10143ff sub sp,sp,#80
+ // f90027e7 str x7,[sp,#72]
+ // f90023e6 str x6,[sp,#64]
+ // f9001fe5 str x5,[sp,#56]
+ // f9001be4 str x4,[sp,#48]
+ // f90017e3 str x3,[sp,#40]
+ // f90013e2 str x2,[sp,#32]
+ // f9000fe1 str x1,[sp,#24]
+ // f90007e0 str x0,[sp,#8]
+ // f94007e0 ldr x0,[sp,#8]
+ // f9400009 ldr x9,[x0]
+ // f9400129 ldr x9,[x9,#...]
+ // 910143ff add sp,sp,#80
+ // d61f0120 br x9
+ // With optimisation, clang produces thunks like:
+ // d10103ff sub sp,sp,#64
+ // a9008be1 stp x1,x2,[sp,#8]
+ // a90193e3 stp x3,x4,[sp,#24]
+ // a9029be5 stp x5,x6,[sp,#40]
+ // f9001fe7 str x7,[sp,#56]
+ // f9400009 ldr x9,[x0]
+ // f9400129 ldr x9,[x9,#...]
+ // 910103ff add sp,sp,#64
+ // d61f0120 br x9
+ // It's more effort than it's worth to try decoding these
+ // thunks.
+
}
return reinterpret_cast<delegate_generic_function>(std::uintptr_t(func));
#else
diff --git a/src/mame/arcade.flt b/src/mame/arcade.flt
index fff6fef6a4e..131ce9e3c07 100644
--- a/src/mame/arcade.flt
+++ b/src/mame/arcade.flt
@@ -1524,10 +1524,11 @@ zwackery.cpp
-ng_mv2f
-ng_mv4f
//saturn.cpp
+-hisaturn
-saturn
--saturnjp
-saturneu
+-saturnjp
+-saturnkr
-vsaturn
--hisaturn
//vectrex.cpp
-vectrex
diff --git a/src/mame/drivers/4enraya.cpp b/src/mame/drivers/4enraya.cpp
index ffd8224a931..1cfeb83af07 100644
--- a/src/mame/drivers/4enraya.cpp
+++ b/src/mame/drivers/4enraya.cpp
@@ -677,10 +677,10 @@ ROM_END
TourVision was a Spanish developer, PCB had TourVision stickers, but this kind of machine was illegal in Spain, so made for the French market instead
- Ariège Amusements was the exclusive distributor of TourVision products until 1991, Paradise Automatique was a spin-off of this distributor
+ Ariège Amusements was the exclusive distributor of TourVision products until 1991, Paradise Automatique was a spin-off of this distributor
and was legally created in 1992 to import/export food vending machines, video games and audiovisual appliances and continued to work with
TourVision.
-
+
A version of this exists (on newer hardware?) with the title 'Lucky Gum' or 'Luck Gum' however the supported game shows no title screen so the title
is unknown.
*/
diff --git a/src/mame/drivers/acesp.cpp b/src/mame/drivers/acesp.cpp
index 1f39b35d536..9ad8f15365b 100644
--- a/src/mame/drivers/acesp.cpp
+++ b/src/mame/drivers/acesp.cpp
@@ -116,8 +116,8 @@ void ace_sp_state::ace_sp_map(address_map &map)
// 0x33 - lamp stb
// 0x34 - shift stb
// 0x35 - shift clk
- map(0x36, 0x36).ram().rw(FUNC(ace_sp_state::serial_r), FUNC(ace_sp_state::serial_w)); // 0x36 - sio
-
+ map(0x36, 0x36).ram().rw(FUNC(ace_sp_state::serial_r), FUNC(ace_sp_state::serial_w)); // 0x36 - sio
+
// 0x37 - watchdog?
map(0x0038, 0x003b).rw("pia0", FUNC(pia6821_device::read), FUNC(pia6821_device::write));
/* 0x3c */
diff --git a/src/mame/drivers/agat.cpp b/src/mame/drivers/agat.cpp
index 4f7b20828b4..56d5f7b95f7 100644
--- a/src/mame/drivers/agat.cpp
+++ b/src/mame/drivers/agat.cpp
@@ -586,19 +586,19 @@ uint8_t agat_base_state::controller_strobe_r()
void agat_base_state::controller_strobe_w(uint8_t data)
{
// 555 monostable one-shot timers; a running timer cannot be restarted
- if (machine().time().as_double() >= m_joystick_x1_time)
+ if (machine().time().as_double() >= m_joystick_x1_time)
{
m_joystick_x1_time = machine().time().as_double() + m_x_calibration * m_joy1x->read();
}
- if (machine().time().as_double() >= m_joystick_y1_time)
+ if (machine().time().as_double() >= m_joystick_y1_time)
{
m_joystick_y1_time = machine().time().as_double() + m_y_calibration * m_joy1y->read();
}
- if (machine().time().as_double() >= m_joystick_x2_time)
+ if (machine().time().as_double() >= m_joystick_x2_time)
{
m_joystick_x2_time = machine().time().as_double() + m_x_calibration * m_joy2x->read();
}
- if (machine().time().as_double() >= m_joystick_y2_time)
+ if (machine().time().as_double() >= m_joystick_y2_time)
{
m_joystick_y2_time = machine().time().as_double() + m_y_calibration * m_joy2y->read();
}
diff --git a/src/mame/drivers/ampoker2.cpp b/src/mame/drivers/ampoker2.cpp
index 17aa59aee8c..349f6f95ad7 100644
--- a/src/mame/drivers/ampoker2.cpp
+++ b/src/mame/drivers/ampoker2.cpp
@@ -1323,7 +1323,7 @@ ROM_END
*/
ROM_START( ampkr2jsp )
- ROM_REGION( 0x10000, "maincpu", 0 ) // The set is marked as "3A".
+ ROM_REGION( 0x10000, "maincpu", 0 ) // The set is marked as "3A".
ROM_LOAD( "u6", 0x0000, 0x10000, CRC(183b67a6) SHA1(8d5b1ce401e8783641c666a5b190a1f052f2dfca) )
ROM_REGION( 0x4000, "gfx1", 0 )
@@ -1335,7 +1335,7 @@ ROM_START( ampkr2jsp )
ROM_END
ROM_START( ampkr2jspa )
- ROM_REGION( 0x10000, "maincpu", 0 ) // The set is marked as "zarate".
+ ROM_REGION( 0x10000, "maincpu", 0 ) // The set is marked as "zarate".
ROM_LOAD( "u6", 0x0000, 0x10000, CRC(35aa7c52) SHA1(8aa422b1b86d0366fe4736d97470fc330335ae78) )
ROM_REGION( 0x4000, "gfx1", 0 )
@@ -1346,7 +1346,7 @@ ROM_START( ampkr2jspa )
ROM_END
ROM_START( ampkr2jspb )
- ROM_REGION( 0x10000, "maincpu", 0 ) // The set is marked as "novomatic".
+ ROM_REGION( 0x10000, "maincpu", 0 ) // The set is marked as "novomatic".
ROM_LOAD( "u6", 0x0000, 0x10000, CRC(e2f5ff56) SHA1(ab793a4f15673d6d4447024172f6fa6c61719fe7) )
ROM_REGION( 0x4000, "gfx1", 0 )
diff --git a/src/mame/drivers/apple2.cpp b/src/mame/drivers/apple2.cpp
index d43eb3fa842..6020af74499 100644
--- a/src/mame/drivers/apple2.cpp
+++ b/src/mame/drivers/apple2.cpp
@@ -678,19 +678,19 @@ u8 apple2_state::controller_strobe_r()
void apple2_state::controller_strobe_w(u8 data)
{
// 558 monostable one-shot timers; a running timer cannot be restarted
- if (machine().time().as_double() >= m_joystick_x1_time)
+ if (machine().time().as_double() >= m_joystick_x1_time)
{
m_joystick_x1_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl0_r();
}
- if (machine().time().as_double() >= m_joystick_y1_time)
+ if (machine().time().as_double() >= m_joystick_y1_time)
{
m_joystick_y1_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl1_r();
}
- if (machine().time().as_double() >= m_joystick_x2_time)
+ if (machine().time().as_double() >= m_joystick_x2_time)
{
m_joystick_x2_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl2_r();
}
- if (machine().time().as_double() >= m_joystick_y2_time)
+ if (machine().time().as_double() >= m_joystick_y2_time)
{
m_joystick_y2_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl3_r();
}
diff --git a/src/mame/drivers/apple2e.cpp b/src/mame/drivers/apple2e.cpp
index ed169af47b9..c9e2ece12e7 100644
--- a/src/mame/drivers/apple2e.cpp
+++ b/src/mame/drivers/apple2e.cpp
@@ -232,9 +232,9 @@ MIG RAM page 2 $CE02 is the speaker/slot bitfield and $CE03 is the paddle/accele
#define CNXX_UNCLAIMED -1
#define CNXX_INTROM -2
-#define IRQ_SLOT 0
-#define IRQ_VBL 1
-#define IRQ_MOUSEXY 2
+static constexpr int IRQ_SLOT = 0;
+static constexpr int IRQ_VBL = 1;
+static constexpr int IRQ_MOUSEXY = 2;
class apple2e_state : public driver_device
{
@@ -286,12 +286,14 @@ public:
m_ds1315(*this, "nsc")
{
m_accel_laser = false;
+ m_has_laser_mouse = false;
m_isiic = false;
m_isiicplus = false;
m_iscec = false;
m_iscecm = false;
m_iscec2000 = false;
m_spectrum_text = false;
+ m_inverse_text = false;
m_pal = false;
#if IICP_NEW_IWM
m_cur_floppy = nullptr;
@@ -377,6 +379,7 @@ public:
void auxram4000_w(offs_t offset, u8 data);
u8 c000_r(offs_t offset);
void c000_w(offs_t offset, u8 data);
+ u8 c000_laser_r(offs_t offset);
void c000_laser_w(offs_t offset, u8 data);
u8 c000_iic_r(offs_t offset);
void c000_iic_w(offs_t offset, u8 data);
@@ -413,6 +416,8 @@ public:
void lc_w(offs_t offset, u8 data);
u8 lc_romswitch_r(offs_t offset);
void lc_romswitch_w(offs_t offset, u8 data);
+ u8 laser_mouse_r(offs_t offset);
+ void laser_mouse_w(offs_t offset, u8 data);
DECLARE_WRITE_LINE_MEMBER(a2bus_irq_w);
DECLARE_WRITE_LINE_MEMBER(a2bus_nmi_w);
DECLARE_WRITE_LINE_MEMBER(a2bus_inh_w);
@@ -425,9 +430,10 @@ public:
u8 nsc_backing_r(offs_t offset);
void apple2cp(machine_config &config);
- void laser128ex2(machine_config &config);
void spectred(machine_config &config);
void laser128(machine_config &config);
+ void laser128o(machine_config &config);
+ void laser128ex2(machine_config &config);
void apple2c_iwm(machine_config &config);
void apple2c_mem(machine_config &config);
void cec(machine_config &config);
@@ -456,6 +462,7 @@ public:
void r2000bank_map(address_map &map);
void r4000bank_map(address_map &map);
void spectred_keyb_map(address_map &map);
+ void init_laser128();
void init_128ex();
void init_spect();
void init_pal();
@@ -495,7 +502,7 @@ private:
bool m_mockingboard4c;
bool m_intc8rom;
- bool m_isiic, m_isiicplus, m_iscec, m_iscecm, m_iscec2000, m_spectrum_text, m_pal;
+ bool m_isiic, m_isiicplus, m_iscec, m_iscecm, m_iscec2000, m_spectrum_text, m_inverse_text, m_pal;
u8 m_migram[0x800];
u16 m_migpage;
@@ -504,6 +511,7 @@ private:
bool m_accel_present;
bool m_accel_temp_slowdown;
bool m_accel_laser;
+ bool m_has_laser_mouse;
int m_accel_stage;
u32 m_accel_speed;
u8 m_accel_slotspk, m_accel_gameio;
@@ -1233,6 +1241,7 @@ void apple2e_state::machine_reset()
void apple2e_state::init_128ex()
{
m_accel_laser = true;
+ m_has_laser_mouse = true;
}
void apple2e_state::init_spect()
@@ -1240,6 +1249,12 @@ void apple2e_state::init_spect()
m_spectrum_text = true;
}
+void apple2e_state::init_laser128()
+{
+ m_inverse_text = true;
+ m_has_laser_mouse = true;
+}
+
void apple2e_state::init_pal()
{
m_pal = true;
@@ -1274,7 +1289,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(apple2e_state::apple2_interrupt)
{
int scanline = param;
- if (m_isiic)
+ if ((m_isiic) || (m_has_laser_mouse))
{
update_iic_mouse();
}
@@ -1337,7 +1352,19 @@ u32 apple2e_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, co
{
m_video->hgr_update(screen, bitmap, cliprect, 0, 159);
}
- m_video->text_update(screen, bitmap, cliprect, 160, 191);
+
+ if (m_spectrum_text)
+ {
+ m_video->text_update_spectrum(screen, bitmap, cliprect, 160, 191);
+ }
+ else if (m_inverse_text)
+ {
+ m_video->text_update_inverse(screen, bitmap, cliprect, 160, 191);
+ }
+ else
+ {
+ m_video->text_update(screen, bitmap, cliprect, 160, 191);
+ }
}
else
{
@@ -1385,6 +1412,10 @@ u32 apple2e_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, co
{
m_video->text_update_spectrum(screen, bitmap, cliprect, 0, 191);
}
+ else if (m_inverse_text)
+ {
+ m_video->text_update_inverse(screen, bitmap, cliprect, 0, 191);
+ }
else
{
m_video->text_update(screen, bitmap, cliprect, 0, 191);
@@ -2068,6 +2099,25 @@ u8 apple2e_state::c000_r(offs_t offset)
return read_floatingbus();
}
+u8 apple2e_state::c000_laser_r(offs_t offset)
+{
+ u8 uFloatingBus7 = read_floatingbus() & 0x7f;
+
+ switch (offset)
+ {
+ case 0x63: // read mouse button
+ return (m_mouseb->read() ? 0 : 0x80) | uFloatingBus7;
+
+ case 0x66: // read mouse xdir
+ return (m_x1 ? 0x80 : 0) | uFloatingBus7;
+
+ case 0x67: // read mouse ydir
+ return (m_y1 ? 0x80 : 0) | uFloatingBus7;
+ }
+
+ return c000_r(offset);
+}
+
void apple2e_state::c000_laser_w(offs_t offset, u8 data)
{
if ((m_accel_laser) && (offset == 0x74))
@@ -2095,6 +2145,11 @@ void apple2e_state::c000_laser_w(offs_t offset, u8 data)
}
else
{
+ if ((offset & 0xf0) == 0x70)
+ {
+ lower_irq(IRQ_VBL);
+ }
+
c000_w(offset, data);
}
}
@@ -2660,6 +2715,75 @@ void apple2e_state::update_iic_mouse()
}
}
+u8 apple2e_state::laser_mouse_r(offs_t offset)
+{
+ u8 uFloatingBus7 = read_floatingbus() & 0x7f;
+
+ switch (offset)
+ {
+ case 0x8: // read X0Edge
+ return (m_x0edge ? 0x80 : 0x00) | uFloatingBus7;
+
+ case 0x9: // read Y0Edge
+ return (m_y0edge ? 0x80 : 0x00) | uFloatingBus7;
+
+ case 0xa: // read XYMask
+ return (m_xy ? 0x80 : 0x00) | uFloatingBus7;
+
+ case 0xb: // read VBL mask
+ return (m_vblmask ? 0x80 : 0x00) | uFloatingBus7;
+
+ case 0xc: // mouse X1 IRQ status
+ return (m_xirq ? 0x80 : 0) | uFloatingBus7;
+
+ case 0xd: // mouse Y1 IRQ status
+ return (m_yirq ? 0x80 : 0) | uFloatingBus7;
+
+ case 0xe: // VBL interrupt status
+ return ((m_irqmask & IRQ_VBL) ? 0x80 : 0) | uFloatingBus7;
+ }
+
+ return 0xff;
+}
+
+void apple2e_state::laser_mouse_w(offs_t offset, u8 data)
+{
+ // these are the same as the //c mouse registers, but with bit 4 of the
+ // address inverted, pretty much.
+ switch (offset)
+ {
+ case 0x0: // RisX0Edge
+ m_x0edge = false; break;
+
+ case 0x1: // FalX0Edge
+ m_x0edge = true; break;
+
+ case 0x2: // RisY0Edge
+ m_y0edge = false; break;
+
+ case 0x3: // FalY0Edge
+ m_y0edge = true; break;
+
+ case 0x4: // DisXY
+ m_xy = false; break;
+
+ case 0x5: // EnbXY
+ m_xy = true; break;
+
+ case 0x6: // DisVBL
+ lower_irq(IRQ_VBL);
+ m_vblmask = false; break;
+
+ case 0x7: // EnVBL
+ m_vblmask = true; break;
+
+ case 0xf: // clear XY interrupt
+ lower_irq(IRQ_MOUSEXY);
+ m_xirq = m_yirq = false;
+ break;
+ }
+}
+
u8 apple2e_state::c080_r(offs_t offset)
{
if(!machine().side_effects_disabled())
@@ -3333,10 +3457,11 @@ void apple2e_state::laser128_map(address_map &map)
map(0x0800, 0x1fff).m(m_0800bank, FUNC(address_map_bank_device::amap8));
map(0x2000, 0x3fff).m(m_2000bank, FUNC(address_map_bank_device::amap8));
map(0x4000, 0xbfff).m(m_4000bank, FUNC(address_map_bank_device::amap8));
- map(0xc000, 0xc07f).rw(FUNC(apple2e_state::c000_r), FUNC(apple2e_state::c000_laser_w));
+ map(0xc000, 0xc07f).rw(FUNC(apple2e_state::c000_laser_r), FUNC(apple2e_state::c000_laser_w));
map(0xc080, 0xc0ff).rw(FUNC(apple2e_state::c080_r), FUNC(apple2e_state::c080_w));
map(0xc098, 0xc09b).rw(m_acia1, FUNC(mos6551_device::read), FUNC(mos6551_device::write));
map(0xc0a8, 0xc0ab).rw(m_acia2, FUNC(mos6551_device::read), FUNC(mos6551_device::write));
+ map(0xc0c0, 0xc0cf).rw(FUNC(apple2e_state::laser_mouse_r), FUNC(apple2e_state::laser_mouse_w));
map(0xc0d0, 0xc0d3).rw(FUNC(apple2e_state::memexp_r), FUNC(apple2e_state::memexp_w));
map(0xc0e0, 0xc0ef).rw(m_laserudc, FUNC(applefdc_base_device::read), FUNC(applefdc_base_device::write));
map(0xc100, 0xc2ff).m(m_c100bank, FUNC(address_map_bank_device::amap8));
@@ -4148,6 +4273,15 @@ INPUT_PORTS_END
static INPUT_PORTS_START( laser128 )
PORT_INCLUDE( apple2e_common )
PORT_INCLUDE( apple2_sysconfig_no_accel )
+
+ PORT_START(MOUSE_BUTTON_TAG) /* Mouse - button */
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Button") PORT_CODE(MOUSECODE_BUTTON1)
+
+ PORT_START(MOUSE_XAXIS_TAG) /* Mouse - X AXIS */
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(20) PORT_KEYDELTA(0) PORT_PLAYER(1)
+
+ PORT_START(MOUSE_YAXIS_TAG) /* Mouse - Y AXIS */
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(20) PORT_KEYDELTA(0) PORT_PLAYER(1)
INPUT_PORTS_END
static INPUT_PORTS_START( apple2cp )
@@ -5153,6 +5287,31 @@ void apple2e_state::laser128(machine_config &config)
m_ram->set_default_size("128K").set_extra_options("128K, 384K, 640K, 896K, 1152K");
}
+void apple2e_state::laser128o(machine_config &config)
+{
+ apple2c(config);
+ M65C02(config.replace(), m_maincpu, 1021800);
+ m_maincpu->set_addrmap(AS_PROGRAM, &apple2e_state::laser128_map);
+
+ LEGACY_APPLEFDC(config, m_laserudc, &fdc_interface);
+ FLOPPY_APPLE(config, FLOPPY_0, &floppy_interface, 15, 16);
+ FLOPPY_APPLE(config, FLOPPY_1, &floppy_interface, 15, 16);
+
+ config.device_remove("sl4");
+ config.device_remove("sl6");
+
+ A2BUS_LASER128_ORIG(config, "sl1", A2BUS_7M_CLOCK).set_onboard(m_a2bus);
+ A2BUS_LASER128_ORIG(config, "sl2", A2BUS_7M_CLOCK).set_onboard(m_a2bus);
+ A2BUS_LASER128_ORIG(config, "sl3", A2BUS_7M_CLOCK).set_onboard(m_a2bus);
+ A2BUS_LASER128_ORIG(config, "sl4", A2BUS_7M_CLOCK).set_onboard(m_a2bus);
+ A2BUS_SLOT(config, "sl5", m_a2bus, apple2_cards, nullptr);
+ A2BUS_LASER128_ORIG(config, "sl6", A2BUS_7M_CLOCK).set_onboard(m_a2bus);
+ A2BUS_SLOT(config, "sl7", m_a2bus, apple2_cards, nullptr);
+
+ // original Laser 128 doesn't have the Slinky memory expansion
+ m_ram->set_default_size("128K").set_extra_options("128K");
+}
+
void apple2e_state::laser128ex2(machine_config &config)
{
apple2c(config);
@@ -5404,11 +5563,41 @@ ROM_END
ROM_START(laser128)
ROM_REGION(0x2000,"gfx1",0)
- ROM_LOAD ( "341-0265-a.chr", 0x0000, 0x1000, BAD_DUMP CRC(2651014d) SHA1(b2b5d87f52693817fc747df087a4aa1ddcdb1f10)) // need to dump real laser rom
- ROM_LOAD ( "341-0265-a.chr", 0x1000, 0x1000, BAD_DUMP CRC(2651014d) SHA1(b2b5d87f52693817fc747df087a4aa1ddcdb1f10)) // need to dump real laser rom
+ ROM_LOAD( "laser 128 video rom vt27-0706-0.bin", 0x000000, 0x002000, CRC(7884cc0f) SHA1(693a0a66191465825b8f7b5e746b463f3000e9cc) )
ROM_REGION(0x10000,"maincpu",0)
- ROM_LOAD("laser128.256", 0x0000, 0x8000, CRC(39e59ed3) SHA1(cbd2f45c923725bfd57f8548e65cc80b13bc18da))
+ ROM_SYSTEM_BIOS(0, "871222", "v4.3")
+ ROMX_LOAD( "laser 128 v4.3 871222.bin", 0x000000, 0x008000, CRC(e091af13) SHA1(3232f7036a68b996fd4126d5e19e855c4d5c64df), ROM_BIOS(0) )
+
+ ROM_SYSTEM_BIOS(1, "870917", "v4.2")
+ ROMX_LOAD( "laser 128 v4.2 870917.bin", 0x000000, 0x008000, CRC(39e59ed3) SHA1(cbd2f45c923725bfd57f8548e65cc80b13bc18da), ROM_BIOS(1) )
+
+ ROM_SYSTEM_BIOS(2, "870724", "v4.1")
+ ROMX_LOAD( "laser 128 v4.1 870724.bin", 0x000000, 0x008000, CRC(ce087911) SHA1(f6dba711f0d727f1d13b0256f10ba62bde6d7f5b), ROM_BIOS(2) )
+
+ ROM_REGION( 0x800, "keyboard", ROMREGION_ERASE00 )
+ ROM_LOAD( "342-0132-c.e12", 0x000, 0x800, BAD_DUMP CRC(e47045f4) SHA1(12a2e718f5f4acd69b6c33a45a4a940b1440a481) ) // need to dump real laser rom
+ROM_END
+
+ROM_START(laser128o)
+ ROM_REGION(0x2000,"gfx1",0)
+ ROM_LOAD( "laser 128 video rom vt27-0706-0.bin", 0x000000, 0x002000, CRC(7884cc0f) SHA1(693a0a66191465825b8f7b5e746b463f3000e9cc) )
+
+ ROM_REGION(0x10000,"maincpu",0)
+ ROM_SYSTEM_BIOS(0, "871212", "v3.3")
+ ROMX_LOAD( "laser 128 v3.3 871212.bin", 0x000000, 0x008000, CRC(3f5deffe) SHA1(4e7195b941c51ba83d5ef16e1f78e3f62bccd8cd), ROM_BIOS(0) )
+
+ ROM_SYSTEM_BIOS(1, "870320", "v3.0")
+ ROMX_LOAD( "laser 128 v3.0 870320.bin", 0x000000, 0x008000, CRC(145d39ff) SHA1(087e992548c2e9849d4262a0eb505548f846c7f5), ROM_BIOS(1) )
+
+ ROM_SYSTEM_BIOS(2, "870203", "v2.9")
+ ROMX_LOAD( "laser 128 v2.9 870203.bin", 0x000000, 0x008000, CRC(7e12fe93) SHA1(d7be7ba05725111354e4bdbaaef620a2a8ea65f7), ROM_BIOS(2) )
+
+ ROM_SYSTEM_BIOS(3, "860915", "860915")
+ ROMX_LOAD( "laser 128 860915.bin", 0x000000, 0x008000, CRC(8d1a181d) SHA1(8fae95776c3d8a581c621cd258e118b8dfdb0cfd), ROM_BIOS(3) )
+
+ ROM_SYSTEM_BIOS(4, "860801", "860801")
+ ROMX_LOAD( "laser 128 860801.bin", 0x000000, 0x008000, CRC(a88c2fcf) SHA1(ec163bb6e7e07cb256e0ed0f8d148cf85313e9f9), ROM_BIOS(4) )
ROM_REGION( 0x800, "keyboard", ROMREGION_ERASE00 )
ROM_LOAD( "342-0132-c.e12", 0x000, 0x800, BAD_DUMP CRC(e47045f4) SHA1(12a2e718f5f4acd69b6c33a45a4a940b1440a481) ) // need to dump real laser rom
@@ -5605,7 +5794,8 @@ COMP( 1984, apple2c, 0, apple2, apple2c, apple2c, apple2e_state,
COMP( 1985?,spectred, apple2e, 0, spectred, apple2e, apple2e_state, init_spect, "Scopus/Spectrum", "Spectrum ED" , MACHINE_SUPPORTS_SAVE )
COMP( 1986, tk3000, apple2c, 0, tk3000, apple2e, apple2e_state, empty_init, "Microdigital", "TK3000//e" , MACHINE_SUPPORTS_SAVE )
COMP( 1989, prav8c, apple2e, 0, apple2e, apple2e, apple2e_state, empty_init, "Pravetz", "Pravetz 8C", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
-COMP( 1987, laser128, apple2c, 0, laser128, laser128, apple2e_state, empty_init, "Video Technology", "Laser 128 (version 4.2)", MACHINE_SUPPORTS_SAVE )
+COMP( 1987, laser128, apple2c, 0, laser128, laser128, apple2e_state, init_laser128, "Video Technology", "Laser 128", MACHINE_SUPPORTS_SAVE )
+COMP( 1987, laser128o, apple2c, 0, laser128o, laser128, apple2e_state, init_laser128, "Video Technology", "Laser 128 (original hardware)", MACHINE_SUPPORTS_SAVE )
COMP( 1988, las128ex, apple2c, 0, laser128, laser128, apple2e_state, init_128ex, "Video Technology", "Laser 128ex (version 4.5)", MACHINE_SUPPORTS_SAVE )
COMP( 1988, las128e2, apple2c, 0, laser128ex2, laser128, apple2e_state, init_128ex, "Video Technology", "Laser 128ex2 (version 6.1)", MACHINE_SUPPORTS_SAVE )
COMP( 1985, apple2c0, apple2c, 0, apple2c_iwm, apple2c, apple2e_state, empty_init, "Apple Computer", "Apple //c (UniDisk 3.5)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/apple2gs.cpp b/src/mame/drivers/apple2gs.cpp
index e01bc172779..7df85e9c9cb 100644
--- a/src/mame/drivers/apple2gs.cpp
+++ b/src/mame/drivers/apple2gs.cpp
@@ -1543,7 +1543,7 @@ void apple2gs_state::machine_reset()
m_ramrd = false;
m_ramwrt = false;
m_ioudis = true;
- m_newvideo = 0x01; // verified on ROM03 hardware
+ m_newvideo = 0x01; // verified on ROM03 hardware
m_clock_frame = 0;
m_mouse_x = 0x00;
m_mouse_y = 0x00;
diff --git a/src/mame/drivers/atarig42.cpp b/src/mame/drivers/atarig42.cpp
index 0fd418de9c8..2a17942f426 100644
--- a/src/mame/drivers/atarig42.cpp
+++ b/src/mame/drivers/atarig42.cpp
@@ -375,7 +375,7 @@ INPUT_PORTS_END
INPUT_PORTS_START( dangerex )
- PORT_START("IN0") /* e00000 */
+ PORT_START("IN0") /* e00000 */
PORT_BIT( 0x000f, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_CUSTOM ) // Toggle 0 - D4
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_CUSTOM ) // Toggle 1 - D5
@@ -798,7 +798,7 @@ ROM_END
ROM_START( dangerex )
- ROM_REGION( 0x80004, "maincpu", 0 ) /* 68000 code */
+ ROM_REGION( 0x80004, "maincpu", 0 ) /* 68000 code */
ROM_LOAD16_BYTE( "dx8d-0h.8d", 0x00000, 0x20000, CRC(4957b65d) SHA1(de9f187b6496cf96d29c4b1b29887abc2bdf9bf0) )
ROM_LOAD16_BYTE( "dx8c-0l.8c", 0x00001, 0x20000, CRC(aedcb497) SHA1(7e201b7db5c0ff661f782566a6b17299d514c77a) )
ROM_LOAD16_BYTE( "dx9d-1h.9d", 0x40000, 0x20000, CRC(2eb943e2) SHA1(87dbf11720e2938bf5755b13231fc668ab3e0e05) )
@@ -849,7 +849,7 @@ ROM_START( dangerex )
ROM_REGION( 0x800, "eeprom", 0 )
ROM_LOAD( "dx-eeprom.5c", 0x0000, 0x800, CRC(d14e813d) SHA1(b206ce85f7a87986d401d34eafa188b5bffae08c) )
- ROM_REGION( 0x0600, "proms", 0 ) /* microcode for growth renderer */
+ ROM_REGION( 0x0600, "proms", 0 ) /* microcode for growth renderer */
ROM_LOAD( "092-1001.20p", 0x0000, 0x0200, NO_DUMP )
ROM_LOAD( "092-1002.22p", 0x0200, 0x0200, NO_DUMP )
ROM_LOAD( "092-1003.21p", 0x0400, 0x0200, NO_DUMP )
diff --git a/src/mame/drivers/barni.cpp b/src/mame/drivers/barni.cpp
index d47eec28897..766c226382b 100644
--- a/src/mame/drivers/barni.cpp
+++ b/src/mame/drivers/barni.cpp
@@ -218,21 +218,21 @@ void barni_state::barni(machine_config &config)
config.set_default_layout(layout_barni);
PIA6821(config, m_pia1, 0);
-// m_pia1->writepa_handler().set(FUNC(barni_state::pia1_pa_w));
-// m_pia1->writepb_handler().set(FUNC(barni_state::pia1_pb_w));
-// m_pia1->readpa_handler().set(FUNC(barni_state::pia1_pa_r));
+// m_pia1->writepa_handler().set(FUNC(barni_state::pia1_pa_w));
+// m_pia1->writepb_handler().set(FUNC(barni_state::pia1_pb_w));
+// m_pia1->readpa_handler().set(FUNC(barni_state::pia1_pa_r));
PIA6821(config, m_pia2, 0);
-// m_pia2->writepa_handler().set(FUNC(barni_state::pia2_pa_w));
-// m_pia2->writepb_handler().set(FUNC(barni_state::pia2_pb_w));
-// m_pia2->readpa_handler().set(FUNC(barni_state::pia2_pa_r));
+// m_pia2->writepa_handler().set(FUNC(barni_state::pia2_pa_w));
+// m_pia2->writepb_handler().set(FUNC(barni_state::pia2_pb_w));
+// m_pia2->readpa_handler().set(FUNC(barni_state::pia2_pa_r));
MOS6522(config, m_via, 4'000'000 / 4); // to check
m_via->irq_handler().set_inputline(m_maincpu, M6809_IRQ_LINE);
m_via->writepa_handler().set(FUNC(barni_state::via_pa_w));
m_via->writepb_handler().set(FUNC(barni_state::via_pb_w));
-// m_via->ca2_handler().set(FUNC(barni_state::via_ca2_w));
-// m_via->cb2_handler().set(FUNC(barni_state::via_cb2_w));
+// m_via->ca2_handler().set(FUNC(barni_state::via_ca2_w));
+// m_via->cb2_handler().set(FUNC(barni_state::via_cb2_w));
// SOUND BOARD
M6802(config, m_audiocpu, 4000000); // guess - crystal value not shown
diff --git a/src/mame/drivers/conchess.cpp b/src/mame/drivers/conchess.cpp
index 19ae4c19d74..e2bea9699dc 100644
--- a/src/mame/drivers/conchess.cpp
+++ b/src/mame/drivers/conchess.cpp
@@ -228,7 +228,7 @@ void conchess_state::concstd(machine_config &config)
M6502(config, m_maincpu, 4_MHz_XTAL/2);
m_maincpu->set_addrmap(AS_PROGRAM, &conchess_state::main_map);
- const attotime irq_period = attotime::from_hz(4_MHz_XTAL/2 / 0x1000);
+ const attotime irq_period = attotime::from_hz(4_MHz_XTAL / 0x2000);
m_maincpu->set_periodic_int(FUNC(conchess_state::irq0_line_assert), irq_period);
SENSORBOARD(config, m_board).set_type(sensorboard_device::MAGNETS);
@@ -244,7 +244,7 @@ void conchess_state::concstd(machine_config &config)
/* sound hardware */
SPEAKER(config, "mono").front_center();
- BEEP(config, m_beeper, 4_MHz_XTAL/2 / 0x200);
+ BEEP(config, m_beeper, 4_MHz_XTAL / 0x400);
m_beeper->add_route(ALL_OUTPUTS, "mono", 0.25);
}
@@ -256,13 +256,13 @@ void conchess_state::concply5(machine_config &config)
R65C02(config.replace(), m_maincpu, 11_MHz_XTAL/2);
m_maincpu->set_addrmap(AS_PROGRAM, &conchess_state::main_map);
- const attotime irq_period = attotime::from_hz(11_MHz_XTAL/2 / 0x2000);
+ const attotime irq_period = attotime::from_hz(11_MHz_XTAL / 0x4000);
m_maincpu->set_periodic_int(FUNC(conchess_state::irq0_line_assert), irq_period);
SOFTWARE_LIST(config.replace(), "cart_list").set_original("conchess_plymate");
/* sound hardware */
- BEEP(config.replace(), m_beeper, 11_MHz_XTAL/2 / 0x400);
+ BEEP(config.replace(), m_beeper, 11_MHz_XTAL / 0x800);
m_beeper->add_route(ALL_OUTPUTS, "mono", 0.25);
}
@@ -274,11 +274,11 @@ void conchess_state::concply8(machine_config &config)
R65C02(config.replace(), m_maincpu, 16_MHz_XTAL/2);
m_maincpu->set_addrmap(AS_PROGRAM, &conchess_state::main_map);
- const attotime irq_period = attotime::from_hz(16_MHz_XTAL/2 / 0x2000);
+ const attotime irq_period = attotime::from_hz(16_MHz_XTAL / 0x4000);
m_maincpu->set_periodic_int(FUNC(conchess_state::irq0_line_assert), irq_period);
/* sound hardware */
- BEEP(config.replace(), m_beeper, 16_MHz_XTAL/2 / 0x800);
+ BEEP(config.replace(), m_beeper, 16_MHz_XTAL / 0x1000);
m_beeper->add_route(ALL_OUTPUTS, "mono", 0.25);
}
@@ -290,13 +290,13 @@ void conchess_state::concplyv(machine_config &config)
M65C02(config.replace(), m_maincpu, 12.288_MHz_XTAL/2);
m_maincpu->set_addrmap(AS_PROGRAM, &conchess_state::main_map);
- const attotime irq_period = attotime::from_hz(12.288_MHz_XTAL/2 / 0x2000);
+ const attotime irq_period = attotime::from_hz(12.288_MHz_XTAL / 0x4000);
m_maincpu->set_periodic_int(FUNC(conchess_state::irq0_line_assert), irq_period);
SOFTWARE_LIST(config.replace(), "cart_list").set_original("conchess_victoria");
/* sound hardware */
- BEEP(config.replace(), m_beeper, 12.288_MHz_XTAL/2 / 0x800);
+ BEEP(config.replace(), m_beeper, 12.288_MHz_XTAL / 0x1000);
m_beeper->add_route(ALL_OUTPUTS, "mono", 0.25);
}
diff --git a/src/mame/drivers/cybstorm.cpp b/src/mame/drivers/cybstorm.cpp
index 216fbad30b6..dbd7318286c 100644
--- a/src/mame/drivers/cybstorm.cpp
+++ b/src/mame/drivers/cybstorm.cpp
@@ -12,8 +12,8 @@
Known bugs:
* STAIN effect not 100% correct
- Possible bugs:
- * Tilemap offsets shifted by 1 pixel?
+ Possible bugs:
+ * Tilemap offsets shifted by 1 pixel?
***************************************************************************/
diff --git a/src/mame/drivers/fidel_eag68k.cpp b/src/mame/drivers/fidel_eag68k.cpp
index 380d3d6a8bc..4ce43644894 100644
--- a/src/mame/drivers/fidel_eag68k.cpp
+++ b/src/mame/drivers/fidel_eag68k.cpp
@@ -472,7 +472,7 @@ void eagv5_state::main_map(address_map &map)
void eagv5_state::sub_map(address_map &map)
{
map(0x000000, 0x00ffff).rom();
- map(0x000001, 0x000001).mirror(0x00fffe).w(m_sublatch, FUNC(generic_latch_8_device::write));
+ map(0x000000, 0x000001).mirror(0x00fffe).w(m_sublatch, FUNC(generic_latch_8_device::write)).umask16(0x00ff);
map(0x044000, 0x047fff).ram();
map(0x140000, 0x140000).r(FUNC(eagv5_state::sub_ack_r));
map(0x140001, 0x140001).r(m_mainlatch, FUNC(generic_latch_8_device::read));
diff --git a/src/mame/drivers/konamigx.cpp b/src/mame/drivers/konamigx.cpp
index c3b31babc6c..e5c659bc1df 100644
--- a/src/mame/drivers/konamigx.cpp
+++ b/src/mame/drivers/konamigx.cpp
@@ -2578,6 +2578,35 @@ ROM_START( winspike )
ROM_LOAD( "705a22.9g", 0x000000, 4*1024*1024, CRC(1a9246f6) SHA1(a40ff43310d035f7b88c4e397a4ee75151578c17) )
ROM_END
+/* Winning Spike - Version AAA (Asia) */
+ROM_START( winspikea )
+ /* main program */
+ ROM_REGION( 0x800000, "maincpu", 0 )
+ GX_BIOS
+ ROM_LOAD32_WORD_SWAP( "705aaa02.31b", 0x200002, 512*1024, CRC(43d1bad9) SHA1(e7c9c50270112e027f88d05e664c35abedc6b2e2) )
+ ROM_LOAD32_WORD_SWAP( "705aaa03.27b", 0x200000, 512*1024, CRC(2af78cca) SHA1(9f6fa586cd4cd0a3e863d67d1bc1d67d35e21ca8) )
+
+ /* sound program */
+ ROM_REGION( 0x40000, "soundcpu", 0 )
+ ROM_LOAD16_BYTE("705a08.9c", 0x000000, 128*1024, CRC(0d531639) SHA1(14a72925f75528e7b4d6b701b2b51f4557f031f0) )
+ ROM_LOAD16_BYTE("705a09.7c", 0x000001, 128*1024, CRC(24e58845) SHA1(a01caced5bad9d98a3f33d72ca5eb9096c45e4ba) )
+
+ ROM_REGION( 0x800000, "k056832", ROMREGION_ERASE00 )
+ ROM_LOAD16_BYTE( "705a19.17h", 0x000000, 0x100000, CRC(bab84b30) SHA1(8522a0dc5e37524f51d632e9d975e949a14c0dc3) )
+ ROM_LOAD16_BYTE( "705a18.22h", 0x000001, 0x100000, CRC(eb97fb5f) SHA1(13de0ad060fd6f1312fa10edde1fef6481e8df64) )
+
+ /* sprites */
+ ROM_REGION( 0x1000000, "k055673", ROMREGION_ERASE00 )
+ ROM_LOAD64_WORD( "705a17.25g", 0x000000, 0x400000, CRC(971d2812) SHA1(ee0819faf6f6c8420d5d3742cb39dfb76b9ce7a4) )
+ ROM_LOAD64_WORD( "705a13.28g", 0x000002, 0x400000, CRC(3b62584b) SHA1(69718f47ff1e8d65a11972af1ed5068db175f625) )
+ ROM_LOAD64_WORD( "705a11.30g", 0x000004, 0x400000, CRC(68542ce9) SHA1(a4294da1d1026e3a9d070575e5855935389a705f) )
+ ROM_LOAD64_WORD( "705a10.33g", 0x000006, 0x400000, CRC(fc4dc78b) SHA1(520cdcf9ca20ec1c84be734e06e183e7a871090b) )
+
+ /* sound data */
+ ROM_REGION( 0x400000, "k054539", 0 )
+ ROM_LOAD( "705a22.9g", 0x000000, 4*1024*1024, CRC(1a9246f6) SHA1(a40ff43310d035f7b88c4e397a4ee75151578c17) )
+ROM_END
+
/*
Winning Spike (Version JAA)
@@ -3893,6 +3922,7 @@ static const GXGameInfoT gameDefs[] =
{ "salmndr2", 7, 6, BPP66 },
{ "salmndr2a", 7, 6, BPP66 },
{ "winspike", 8, 7, BPP4 },
+ { "winspikea", 8, 7, BPP4 },
{ "winspikej", 8, 7, BPP4 },
{ "soccerss", 7, 0, BPP4 },
{ "soccerssu", 7, 0, BPP4 },
@@ -4067,6 +4097,7 @@ GAME( 1996, salmndr2a, salmndr2, salmndr2, gokuparo, konamigx_state, init_k
// bad sprite colours, part of tilemap gets blanked out when a game starts (might be more protection)
GAME( 1997, winspike, konamigx, winspike, common, konamigx_state, init_konamigx, ROT0, "Konami", "Winning Spike (ver EAA)", MACHINE_UNEMULATED_PROTECTION | MACHINE_IMPERFECT_GRAPHICS )
+GAME( 1997, winspikea, winspike, winspike, common, konamigx_state, init_konamigx, ROT0, "Konami", "Winning Spike (ver AAA)", MACHINE_UNEMULATED_PROTECTION | MACHINE_IMPERFECT_GRAPHICS )
GAME( 1997, winspikej, winspike, winspike, common, konamigx_state, init_konamigx, ROT0, "Konami", "Winning Spike (ver JAA)", MACHINE_UNEMULATED_PROTECTION | MACHINE_IMPERFECT_GRAPHICS )
/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/mame/drivers/konmedal020.cpp b/src/mame/drivers/konmedal020.cpp
index 41346454bf6..d44dcddaa18 100644
--- a/src/mame/drivers/konmedal020.cpp
+++ b/src/mame/drivers/konmedal020.cpp
@@ -121,4 +121,4 @@ ROM_END
} // Anonymous namespace
-GAME( 1997, gs471, 0, gs471, gs471, konmedal020_state, empty_init, ROT0, "Konami", "Unknown medal game GS471", MACHINE_NOT_WORKING )
+GAME( 1997, gs471, 0, gs471, gs471, konmedal020_state, empty_init, ROT0, "Konami", "unknown medal game GS471", MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/mpu4.cpp b/src/mame/drivers/mpu4.cpp
index acb4be7a6ff..bae54af37e7 100644
--- a/src/mame/drivers/mpu4.cpp
+++ b/src/mame/drivers/mpu4.cpp
@@ -1517,7 +1517,7 @@ ROM_END
BARCREST SAMPLED SOUND
_________________________
- | · |
+ | · |
| · |
| · |
| · |_____________
@@ -1543,7 +1543,7 @@ Just one different byte between the three "Escalera y Tobogan" sets, at address
1268: 0xF4
1269: 0xF5
1270: 0xF6
-May be the game serial number hard-encoded on the EPROM?
+May be the game serial number hard-encoded on the EPROM?
*/
ROM_START( m4esctbg )
ROM_REGION( 0x20000, "maincpu", 0 )
diff --git a/src/mame/drivers/naomi.cpp b/src/mame/drivers/naomi.cpp
index e7b4d49ddb4..bf6d54e3fd0 100644
--- a/src/mame/drivers/naomi.cpp
+++ b/src/mame/drivers/naomi.cpp
@@ -5115,7 +5115,7 @@ ROM_START( mushikk )
NAOMI_DEFAULT_EEPROM
ROM_REGION( 0x4000000, "rom_board", ROMREGION_ERASEFF )
- ROM_LOAD( "epr-24265.ic11", 0x0000000, 0x0400000, CRC(dccb210b) SHA1(35891f97bec251083b2c927e926d73685d750a4d) )
+ ROM_LOAD( "epr-24265.ic11", 0x0000000, 0x0400000, CRC(dccb210b) SHA1(35891f97bec251083b2c927e926d73685d750a4d) )
ROM_LOAD32_WORD( "opr-24266.ic17s", 0x1000000, 0x0800000, CRC(293e5350) SHA1(7107d3378fe3a73e868bc03e0572b19e91152a3b) )
ROM_LOAD32_WORD( "opr-24267.ic18", 0x1000002, 0x0800000, CRC(80798f9a) SHA1(a843a052dce254f9a5a7b7024f21e4e6f8621666) )
ROM_LOAD32_WORD( "opr-24268.ic19s", 0x2000000, 0x0800000, CRC(b512c772) SHA1(f45084f2e242e07e47c25eeeed44624274a95a7e) )
diff --git a/src/mame/drivers/olyboss.cpp b/src/mame/drivers/olyboss.cpp
index df710367f37..b711c8a0ac6 100644
--- a/src/mame/drivers/olyboss.cpp
+++ b/src/mame/drivers/olyboss.cpp
@@ -172,7 +172,7 @@ void olyboss_state::olyboss_io(address_map &map)
{
map.global_mask(0xff);
map.unmap_value_high();
- map(0x0, 0x8).rw(m_dma, FUNC(i8257_device::read), FUNC(i8257_device::write));
+ map(0x00, 0x08).rw(m_dma, FUNC(i8257_device::read), FUNC(i8257_device::write));
map(0x10, 0x11).m(m_fdc, FUNC(upd765a_device::map));
//map(0x20, 0x20) //beeper?
map(0x30, 0x30).rw(m_uic, FUNC(am9519_device::data_r), FUNC(am9519_device::data_w));
@@ -269,8 +269,8 @@ UPD3301_DRAW_CHARACTER_MEMBER( olyboss_state::olyboss_display_pixels )
for (int i = 0; i < 8; i++)
{
- int color = BIT(data, 7) ^ rvv;
- bitmap.pix(y, (sx * 8) + i) = color?0xffffff:0;
+ int color = BIT(data, 7);
+ bitmap.pix(y, (sx * 8) + i) = color ? 0xffffff : 0;
data <<= 1;
}
}
@@ -458,6 +458,7 @@ void olyboss_state::olybossd(machine_config &config)
UPD3301(config, m_crtc, XTAL(14'318'181));
m_crtc->set_character_width(8);
m_crtc->set_display_callback(FUNC(olyboss_state::olyboss_display_pixels));
+ m_crtc->set_attribute_fetch_callback(m_crtc, FUNC(upd3301_device::default_attr_fetch));
m_crtc->drq_wr_callback().set(m_dma, FUNC(i8257_device::dreq2_w));
m_crtc->int_wr_callback().set(m_uic, FUNC(am9519_device::ireq0_w)).invert();
m_crtc->set_screen(SCREEN_TAG);
diff --git a/src/mame/drivers/pc8001.cpp b/src/mame/drivers/pc8001.cpp
index f34f2cd00ad..9e790f900b4 100644
--- a/src/mame/drivers/pc8001.cpp
+++ b/src/mame/drivers/pc8001.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Curt Coder
+// copyright-holders:Curt Coder, Angelo Salese
/*
http://www2.odn.ne.jp/~haf09260/Pc80/EnrPc.htm
@@ -12,14 +12,28 @@
TODO:
- - uPD3301 attributes
- - PCG1000
- - Intel 8251
- - cassette
- - floppy
- - PC-8011
- - PC-8021
- - PC-8031
+ - uPD3301 attributes;
+ - PCG-1000;
+ - Intel 8251;
+ - cassette;
+ - dip-switches;
+ - PC-8011 (expansion unit)
+ - PC-8021;
+ - PC-8031 (mini disk unit, in progress)
+ - pc8001mk2sr: verify how much needs to be ported from pc8801.cpp code
+ (Has 3 bitplane GVRAM like PC-8801 V1 mode);
+ - waitstates & DMA penalty (some games are suspciously fast);
+ - buzzer has pretty ugly aliasing in places;
+
+ Notes:
+ - pc8001 v1.01 / v1.02 sports a buggy readout of the expansion ROM at PC=17a1:
+ It expects an header read of 0x41-0x42 at offset $6000-6001, but second read at
+ PC=0x17aa is just a comparison to $6000 == 0x42, which is impossible at that point
+ unless external aid is given. This has been fixed in v1.10;
+ - Color Magical (pc8001gp:flop5 option 7) transfers two 8 color screens at
+ even/odd frame intervals, effectively boosting the number of available colors to 27.
+ This trick is kinda flickery even on real HW, no wonder it looks ugly in MAME,
+ can it be improved?
*/
@@ -28,6 +42,150 @@
#include "screen.h"
#include "speaker.h"
+WRITE_LINE_MEMBER( pc8001_base_state::crtc_reverse_w )
+{
+ // rvv acts as a global flip for reverse attribute meaning
+ // (does not act on underlying palette)
+ // TODO: what happens if RVV changes mid-frame?
+ // I suspect monitor resync more likely than rasters.
+ m_screen_reverse = state;
+}
+
+UPD3301_FETCH_ATTRIBUTE( pc8001_base_state::attr_fetch )
+{
+ const u8 attr_max_size = 80;
+ const bool is_color_mode = gfx_mode == 0x2;
+ std::array<u16, attr_max_size> attr_extend_info = m_crtc->default_attr_fetch(attr_row, gfx_mode, y, attr_fifo_size, row_size);
+
+ // further extend the attributes if we are in color mode
+ if (is_color_mode)
+ {
+ // TODO: defaults
+ // flgworld (pc8001) gameplay sets up:
+ // - 0x00 0x00 0x02 0x88 on playfield
+ // \- (wanting the default from the first defined color)
+ // - 0x00 0x00 0x00 0x48 0x12 0x88 for first row
+ // \- (Expecting "FLAG WORLD" wording to be red while the "P"s in green wtf)
+ // undermon (pc8001) instruction screen sets up:
+ // - 0x00 0x00 0x06 0xb8
+ // \- (expecting blue fill up to 0x06)
+ u8 attr_color = 0xe8;
+ u8 attr_decoration = 0x00;
+
+ for (int ex = 0; ex < row_size; ex++)
+ {
+ u16 cur_attr = attr_extend_info[ex];
+ if (BIT(cur_attr, 3))
+ attr_color = cur_attr;
+ else
+ attr_decoration = cur_attr;
+ attr_extend_info[ex] = (attr_color << 8) | attr_decoration;
+ }
+ }
+
+ return attr_extend_info;
+}
+
+UPD3301_DRAW_CHARACTER_MEMBER( pc8001_base_state::draw_text )
+{
+ // punt if we are in width 40 (discarded on this end)
+ if (sx % 2 && !m_width80)
+ return;
+
+ const bool is_color_mode = gfx_mode == 0x2;
+ u8 tile;
+ const u8 tile_width = m_width80 ? 8 : 16;
+ const u8 dot_width = (m_width80 ^ 1) + 1;
+ const u8 y_double = m_screen_is_24KHz ? 2 : 1;
+ const u8 y_height = y_double * 8;
+
+ bool semigfx_tile, reverse, attr_blink, secret;
+ bool upperline, lowerline;
+ u8 color;
+
+ if (is_color_mode)
+ {
+ color = (attr & 0xe000) >> 13;
+ semigfx_tile = bool(BIT(attr, 12));
+ // bit 7 is used by 2001spc and many others, no effect?
+ }
+ else
+ {
+ color = 7;
+ semigfx_tile = bool(BIT(attr, 7));
+ }
+
+ lowerline = bool(BIT(attr, 5));
+ upperline = bool(BIT(attr, 4));
+ reverse = bool(BIT(attr, 2));
+ attr_blink = bool(BIT(attr, 1));
+ secret = bool(BIT(attr, 0));
+
+ if (semigfx_tile)
+ tile = cc;
+ else
+ {
+ if (lc > y_height - 1)
+ tile = 0;
+ else
+ tile = m_cgrom->base()[(cc << 3) | (lc >> (y_double-1))];
+ }
+
+ // secret blacks out every tile connections,
+ // has lower priority over blinking and other attribute decorations
+ if (secret)
+ tile = 0;
+
+ if (csr)
+ tile ^= 0xff;
+ else if (attr_blink_on && attr_blink)
+ tile = 0;
+
+ // upper/lower line aren't affected by secret and blinking, only reverse
+ // TODO: should downshift chars by one
+ if (lc == 0 && upperline)
+ tile = 0xff;
+
+ if (is_lowestline && lowerline)
+ tile = 0xff;
+
+ if (reverse ^ m_screen_reverse)
+ tile ^= 0xff;
+
+// if (m_width80)
+ {
+ u8 pen;
+
+ for (int xi = 0; xi < tile_width; xi += dot_width)
+ {
+ int res_x = (sx * 8) + xi;
+ if (semigfx_tile)
+ {
+ u8 mask = (xi & (4 << (dot_width - 1))) ? 0x10 : 0x01;
+ mask <<= (lc & (0x3 << y_double)) >> y_double;
+ pen = tile & mask;
+ }
+ else
+ {
+ pen = tile;
+ pen = (pen >> (7 - (xi >> (dot_width - 1)))) & 1;
+ }
+
+ for (int di = 0; di < dot_width; di++)
+ bitmap.pix(y, res_x + di) = m_crtc_palette->pen(pen ? color : 0);
+ }
+ }
+}
+
+uint32_t pc8001_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ bitmap.fill(0, cliprect);
+ // TODO: superimposing
+ // TODO: merging with previous frame for Color Magical (is it driver area?)
+ m_crtc->screen_update(screen, bitmap, cliprect);
+ return 0;
+}
+
/* Read/Write Handlers */
void pc8001_state::port10_w(uint8_t data)
@@ -57,7 +215,7 @@ void pc8001_state::port10_w(uint8_t data)
m_cent_data_out->write(data);
}
-void pc8001_state::port30_w(uint8_t data)
+void pc8001_base_state::port30_w(uint8_t data)
{
/*
@@ -80,8 +238,7 @@ void pc8001_state::port30_w(uint8_t data)
/* color mode */
m_color = BIT(data, 1);
- /* cassette motor */
- m_cassette->change_state(BIT(data,3) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
+ m_cassette->change_state(BIT(data, 3) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
}
void pc8001mk2_state::port31_w(uint8_t data)
@@ -100,6 +257,7 @@ void pc8001mk2_state::port31_w(uint8_t data)
7 background color
*/
+ membank("bank2")->set_entry(data & 1);
}
WRITE_LINE_MEMBER( pc8001_state::write_centronics_busy )
@@ -129,12 +287,13 @@ uint8_t pc8001_state::port40_r()
*/
- uint8_t data = 0x08;
+ uint8_t data = 0x00;
data |= m_centronics_busy;
data |= m_centronics_ack << 1;
data |= m_rtc->data_out_r() << 4;
data |= m_crtc->vrtc_r() << 5;
+ // TODO: enable line from pc80s31k (bit 3, active_low)
return data;
}
@@ -158,15 +317,15 @@ void pc8001_state::port40_w(uint8_t data)
m_centronics->write_strobe(BIT(data, 0));
- m_rtc->clk_w(BIT(data, 2));
m_rtc->stb_w(BIT(data, 1));
+ m_rtc->clk_w(BIT(data, 2));
m_beep->set_state(BIT(data, 5));
}
/* Memory Maps */
-void pc8001_state::pc8001_mem(address_map &map)
+void pc8001_state::pc8001_map(address_map &map)
{
map(0x0000, 0x5fff).bankrw("bank1");
map(0x6000, 0x7fff).bankrw("bank2");
@@ -217,10 +376,10 @@ void pc8001_state::pc8001_io(address_map &map)
// map(0xe6, 0xe6).w(FUNC(pc8001_state::irq_mask_w));
// map(0xe7, 0xe7).w(FUNC(pc8001_state::pc8012_memory_mode_w));
// map(0xe8, 0xfb) unused
- map(0xfc, 0xff).rw(I8255A_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write));
+ map(0xfc, 0xff).m(m_pc80s31, FUNC(pc80s31_device::host_map));
}
-void pc8001mk2_state::pc8001mk2_mem(address_map &map)
+void pc8001mk2_state::pc8001mk2_map(address_map &map)
{
map(0x0000, 0x5fff).bankrw("bank1");
map(0x6000, 0x7fff).bankrw("bank2");
@@ -231,8 +390,8 @@ void pc8001mk2_state::pc8001mk2_mem(address_map &map)
void pc8001mk2_state::pc8001mk2_io(address_map &map)
{
pc8001_io(map);
- map(0x30, 0x30).w(FUNC(pc8001mk2_state::port30_w));
- map(0x31, 0x31).w(FUNC(pc8001mk2_state::port31_w));
+ map(0x30, 0x30).portr("DSW1").w(FUNC(pc8001mk2_state::port30_w));
+ map(0x31, 0x31).portr("DSW2").w(FUNC(pc8001mk2_state::port31_w));
// map(0x5c, 0x5c).w(FUNC(pc8001mk2_state::gram_on_w));
// map(0x5f, 0x5f).w(FUNC(pc8001mk2_state::gram_off_w));
// map(0xe8, 0xe8) kanji_address_lo_w, kanji_data_lo_r
@@ -250,6 +409,40 @@ void pc8001mk2_state::pc8001mk2_io(address_map &map)
// map(0xfb, 0xfb) DMA type 5 inch FDC data register
}
+void pc8001mk2sr_state::port33_w(u8 data)
+{
+ // TODO: needs progressive flush
+#ifdef UNUSED_FUNCTION
+ if (data & 0x80)
+ {
+ membank("bank1")->set_entry(2);
+ membank("bank2")->set_entry(2 | (m_n80sr_bank & 1));
+ }
+ else
+ {
+ membank("bank1")->set_entry(0);
+ membank("bank2")->set_entry(0);
+ }
+#endif
+}
+
+u8 pc8001mk2sr_state::port71_r()
+{
+ return m_n80sr_bank;
+}
+
+void pc8001mk2sr_state::port71_w(u8 data)
+{
+ m_n80sr_bank = data;
+}
+
+void pc8001mk2sr_state::pc8001mk2sr_io(address_map &map)
+{
+ pc8001mk2_io(map);
+ map(0x33, 0x33).w(FUNC(pc8001mk2sr_state::port33_w));
+ map(0x71, 0x71).rw(FUNC(pc8001mk2sr_state::port71_r), FUNC(pc8001mk2sr_state::port71_w));
+}
+
/* Input Ports */
static INPUT_PORTS_START( pc8001 )
@@ -353,60 +546,84 @@ static INPUT_PORTS_START( pc8001 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ESC) PORT_CHAR(27)
- PORT_START("DSW1")
+// PORT_START("DSW1")
INPUT_PORTS_END
-/* uPD3301 Interface */
-
-static const rgb_t PALETTE_PC8001[] =
-{
- rgb_t::black(),
- rgb_t(0x00, 0x00, 0xff),
- rgb_t(0xff, 0x00, 0x00),
- rgb_t(0xff, 0x00, 0xff),
- rgb_t(0x00, 0xff, 0x00),
- rgb_t(0x00, 0xff, 0xff),
- rgb_t(0xff, 0xff, 0x00),
- rgb_t::white()
-};
-
-UPD3301_DRAW_CHARACTER_MEMBER( pc8001_state::pc8001_display_pixels )
-{
- uint8_t data = m_char_rom->base()[(cc << 3) | lc];
-
- if (lc >= 8) return;
- if (csr) data = 0xff;
-
- if (m_width80)
- {
- for (int i = 0; i < 8; i++)
- {
- int color = BIT(data, 7) ^ rvv;
+static INPUT_PORTS_START( pc8001mk2 )
+ PORT_INCLUDE( pc8001 )
- bitmap.pix(y, (sx * 8) + i) = PALETTE_PC8001[color ? 7 : 0];
-
- data <<= 1;
- }
- }
- else
- {
- if (sx % 2) return;
-
- for (int i = 0; i < 8; i++)
- {
- int color = BIT(data, 7) ^ rvv;
-
- bitmap.pix(y, (sx/2 * 16) + (i * 2)) = PALETTE_PC8001[color ? 7 : 0];
- bitmap.pix(y, (sx/2 * 16) + (i * 2) + 1) = PALETTE_PC8001[color ? 7 : 0];
+ PORT_START("DSW1")
+ PORT_DIPNAME( 0x01, 0x00, "Boot Mode" )
+ PORT_DIPSETTING( 0x00, "N-BASIC" )
+ PORT_DIPSETTING( 0x01, "N80-BASIC" )
+ PORT_DIPNAME( 0x02, 0x02, "DSW1" )
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x01, 0x01, "DSW2" )
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+INPUT_PORTS_END
- data <<= 1;
- }
- }
-}
+static INPUT_PORTS_START( pc8001mk2sr )
+ PORT_INCLUDE( pc8001mk2 )
+
+ PORT_MODIFY("DSW1")
+ // This is really a tri-state dip on front panel
+ // BIOS just expects bit 1 to be off for SR mode
+ PORT_DIPNAME( 0x03, 0x02, "Boot Mode" )
+ PORT_DIPSETTING( 0x00, "N80SR-BASIC (duplicate)")
+ PORT_DIPSETTING( 0x01, "N80SR-BASIC" )
+ PORT_DIPSETTING( 0x02, "N-BASIC" )
+ PORT_DIPSETTING( 0x03, "N80-BASIC" )
+ PORT_DIPNAME( 0x04, 0x04, "DSW1" )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+INPUT_PORTS_END
/* 8257 Interface */
-WRITE_LINE_MEMBER( pc8001_state::hrq_w )
+WRITE_LINE_MEMBER( pc8001_base_state::hrq_w )
{
/* HACK - this should be connected to the BUSREQ line of Z80 */
m_maincpu->set_input_line(INPUT_LINE_HALT, state);
@@ -415,7 +632,7 @@ WRITE_LINE_MEMBER( pc8001_state::hrq_w )
m_dma->hlda_w(state);
}
-uint8_t pc8001_state::dma_mem_r(offs_t offset)
+uint8_t pc8001_base_state::dma_mem_r(offs_t offset)
{
address_space &program = m_maincpu->space(AS_PROGRAM);
@@ -424,6 +641,14 @@ uint8_t pc8001_state::dma_mem_r(offs_t offset)
/* Machine Initialization */
+void pc8001_base_state::machine_start()
+{
+ save_item(NAME(m_width80));
+ save_item(NAME(m_color));
+ save_item(NAME(m_screen_reverse));
+ save_item(NAME(m_screen_is_24KHz));
+}
+
void pc8001_state::machine_start()
{
address_space &program = m_maincpu->space(AS_PROGRAM);
@@ -441,6 +666,7 @@ void pc8001_state::machine_start()
membank("bank1")->configure_entry(1, m_rom->base());
program.install_read_bank(0x0000, 0x5fff, membank("bank1"));
program.unmap_write(0x0000, 0x5fff);
+ membank("bank2")->configure_entry(1, m_rom->base() + 0x6000);
switch (m_ram->size())
{
@@ -464,55 +690,81 @@ void pc8001_state::machine_start()
program.install_readwrite_bank(0x0000, 0x5fff, membank("bank1"));
program.install_readwrite_bank(0x6000, 0xbfff, membank("bank2"));
program.install_readwrite_bank(0x8000, 0xffff, membank("bank3"));
- membank("bank2")->set_entry(0);
+// membank("bank2")->set_entry(0);
break;
}
+ // PC8001 is 15KHz only
+ set_screen_frequency(false);
+}
+
+void pc8001_state::machine_reset()
+{
membank("bank1")->set_entry(1);
+ membank("bank2")->set_entry(1);
membank("bank3")->set_entry(0);
+}
- /* register for state saving */
- save_item(NAME(m_width80));
- save_item(NAME(m_color));
+void pc8001mk2sr_state::machine_start()
+{
+ pc8001_state::machine_start();
+
+ membank("bank1")->configure_entry(2, m_n80sr_rom->base());
+ membank("bank2")->configure_entry(2, m_n80sr_rom->base() + 0x6000);
+ membank("bank2")->configure_entry(3, m_n80sr_rom->base() + 0x8000);
+
+ save_item(NAME(m_n80sr_bank));
+}
+
+void pc8001mk2sr_state::machine_reset()
+{
+ pc8001_state::machine_reset();
+
+ //membank("bank1")->set_entry(2);
+ //membank("bank2")->set_entry(2);
}
/* Machine Drivers */
void pc8001_state::pc8001(machine_config &config)
{
+ constexpr XTAL MASTER_CLOCK = XTAL(4'000'000);
+ constexpr XTAL VIDEO_CLOCK = XTAL(14'318'181);
+
/* basic machine hardware */
- Z80(config, m_maincpu, XTAL(4'000'000));
- m_maincpu->set_addrmap(AS_PROGRAM, &pc8001_state::pc8001_mem);
+ Z80(config, m_maincpu, MASTER_CLOCK);
+ m_maincpu->set_addrmap(AS_PROGRAM, &pc8001_state::pc8001_map);
m_maincpu->set_addrmap(AS_IO, &pc8001_state::pc8001_io);
+ PC80S31(config, m_pc80s31, MASTER_CLOCK);
+ config.set_perfect_quantum(m_maincpu);
+ config.set_perfect_quantum("pc80s31:fdc_cpu");
+
/* video hardware */
- screen_device &screen(SCREEN(config, SCREEN_TAG, SCREEN_TYPE_RASTER));
- screen.set_refresh_hz(60);
- screen.set_screen_update(UPD3301_TAG, FUNC(upd3301_device::screen_update));
- screen.set_size(640, 220);
- screen.set_visarea(0, 640-1, 0, 200-1);
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(VIDEO_CLOCK, 896, 0, 640, 260, 0, 200);
+ m_screen->set_screen_update(FUNC(pc8001_state::screen_update));
+// m_screen->set_palette(m_crtc_palette);
- /* sound hardware */
- SPEAKER(config, "mono").front_center();
- BEEP(config, m_beep, 2000).add_route(ALL_OUTPUTS, "mono", 0.25);
+ PALETTE(config, m_crtc_palette, palette_device::BRG_3BIT);
- /* devices */
- I8251(config, I8251_TAG, 0);
-
- I8255A(config, I8255A_TAG, 0);
+ UPD3301(config, m_crtc, VIDEO_CLOCK);
+ m_crtc->set_character_width(8);
+ m_crtc->set_display_callback(FUNC(pc8001_state::draw_text));
+ m_crtc->set_attribute_fetch_callback(FUNC(pc8001_state::attr_fetch));
+ m_crtc->drq_wr_callback().set(m_dma, FUNC(i8257_device::dreq2_w));
+ m_crtc->rvv_wr_callback().set(FUNC(pc8001_state::crtc_reverse_w));
+ m_crtc->set_screen(m_screen);
- I8257(config, m_dma, XTAL(4'000'000));
+ I8257(config, m_dma, MASTER_CLOCK);
m_dma->out_hrq_cb().set(FUNC(pc8001_state::hrq_w));
m_dma->in_memr_cb().set(FUNC(pc8001_state::dma_mem_r));
m_dma->out_iow_cb<2>().set(m_crtc, FUNC(upd3301_device::dack_w));
- UPD1990A(config, m_rtc);
+ /* devices */
+ I8251(config, I8251_TAG, 0);
- UPD3301(config, m_crtc, XTAL(14'318'181));
- m_crtc->set_character_width(8);
- m_crtc->set_display_callback(FUNC(pc8001_state::pc8001_display_pixels));
- m_crtc->drq_wr_callback().set(m_dma, FUNC(i8257_device::dreq2_w));
- m_crtc->set_screen(SCREEN_TAG);
+ UPD1990A(config, m_rtc);
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->ack_handler().set(FUNC(pc8001_state::write_centronics_ack));
@@ -526,84 +778,91 @@ void pc8001_state::pc8001(machine_config &config)
m_cassette->add_route(ALL_OUTPUTS, "mono", 0.05);
RAM(config, RAM_TAG).set_default_size("16K").set_extra_options("32K,64K");
-}
-
-void pc8001mk2_state::pc8001mk2(machine_config &config)
-{
- /* basic machine hardware */
- Z80(config, m_maincpu, XTAL(4'000'000));
- m_maincpu->set_addrmap(AS_PROGRAM, &pc8001mk2_state::pc8001mk2_mem);
- m_maincpu->set_addrmap(AS_IO, &pc8001mk2_state::pc8001mk2_io);
- /* video hardware */
- screen_device &screen(SCREEN(config, SCREEN_TAG, SCREEN_TYPE_RASTER));
- screen.set_refresh_hz(60);
- screen.set_screen_update(UPD3301_TAG, FUNC(upd3301_device::screen_update));
- screen.set_size(640, 220);
- screen.set_visarea(0, 640-1, 0, 200-1);
+ SOFTWARE_LIST(config, "disk_n_list").set_original("pc8001_flop");
/* sound hardware */
SPEAKER(config, "mono").front_center();
- BEEP(config, m_beep, 2000).add_route(ALL_OUTPUTS, "mono", 0.25);
-
- /* devices */
- I8251(config, I8251_TAG, 0);
-
- I8255A(config, I8255A_TAG, 0);
+ // TODO: unknown clock, is it really a beeper?
+ BEEP(config, m_beep, 2400).add_route(ALL_OUTPUTS, "mono", 0.25);
+}
- I8257(config, m_dma, XTAL(4'000'000));
- m_dma->out_hrq_cb().set(FUNC(pc8001_state::hrq_w));
- m_dma->in_memr_cb().set(FUNC(pc8001_state::dma_mem_r));
- m_dma->out_iow_cb<2>().set(m_crtc, FUNC(upd3301_device::dack_w));
+void pc8001mk2_state::pc8001mk2(machine_config &config)
+{
+ pc8001(config);
+ m_maincpu->set_addrmap(AS_PROGRAM, &pc8001mk2_state::pc8001mk2_map);
+ m_maincpu->set_addrmap(AS_IO, &pc8001mk2_state::pc8001mk2_io);
- UPD1990A(config, m_rtc);
+ // TODO: video HW has extra GVRAM setup
- UPD3301(config, m_crtc, XTAL(14'318'181));
- m_crtc->set_character_width(8);
- m_crtc->set_display_callback(FUNC(pc8001_state::pc8001_display_pixels));
- m_crtc->drq_wr_callback().set(m_dma, FUNC(i8257_device::dreq2_w));
- m_crtc->set_screen(SCREEN_TAG);
+ RAM(config.replace(), RAM_TAG).set_default_size("64K");
- CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ SOFTWARE_LIST(config, "disk_n80_list").set_original("pc8001mk2_flop");
+}
- OUTPUT_LATCH(config, m_cent_data_out);
- m_centronics->set_output_latch(*m_cent_data_out);
+void pc8001mk2sr_state::pc8001mk2sr(machine_config &config)
+{
+ pc8001mk2(config);
+ m_maincpu->set_addrmap(AS_IO, &pc8001mk2sr_state::pc8001mk2sr_io);
- CASSETTE(config, m_cassette);
- m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
- m_cassette->add_route(ALL_OUTPUTS, "mono", 0.05);
+ // TODO: mods for SR mode support
- RAM(config, RAM_TAG).set_default_size("64K");
+ SOFTWARE_LIST(config, "disk_n80sr_list").set_original("pc8001mk2sr_flop");
}
/* ROMs */
ROM_START( pc8001 )
- ROM_REGION( 0x6000, Z80_TAG, 0 )
+ ROM_REGION( 0x8000, Z80_TAG, ROMREGION_ERASEFF )
+ // PCB pictures shows divided by 3 ROMs (and 4th socket unpopulated)
ROM_SYSTEM_BIOS( 0, "v101", "N-BASIC v1.01" )
- ROMX_LOAD( "n80v101.rom", 0x00000, 0x6000, CRC(a2cc9f22) SHA1(6d2d838de7fea20ddf6601660d0525d5b17bf8a3), ROM_BIOS(0) )
+ ROMX_LOAD( "n80v101.rom", 0x00000, 0x6000, BAD_DUMP CRC(a2cc9f22) SHA1(6d2d838de7fea20ddf6601660d0525d5b17bf8a3), ROM_BIOS(0) )
ROM_SYSTEM_BIOS( 1, "v102", "N-BASIC v1.02" )
- ROMX_LOAD( "n80v102.rom", 0x00000, 0x6000, CRC(ed01ca3f) SHA1(b34a98941499d5baf79e7c0e5578b81dbede4a58), ROM_BIOS(1) )
+ ROMX_LOAD( "n80v102.rom", 0x00000, 0x6000, BAD_DUMP CRC(ed01ca3f) SHA1(b34a98941499d5baf79e7c0e5578b81dbede4a58), ROM_BIOS(1) )
ROM_SYSTEM_BIOS( 2, "v110", "N-BASIC v1.10" )
- ROMX_LOAD( "n80v110.rom", 0x00000, 0x6000, CRC(1e02d93f) SHA1(4603cdb7a3833e7feb257b29d8052c872369e713), ROM_BIOS(2) )
+ ROMX_LOAD( "n80v110.rom", 0x00000, 0x6000, BAD_DUMP CRC(1e02d93f) SHA1(4603cdb7a3833e7feb257b29d8052c872369e713), ROM_BIOS(2) )
- ROM_REGION( 0x800, UPD3301_TAG, 0)
+ ROM_REGION( 0x800, CGROM_TAG, 0)
ROM_LOAD( "font.rom", 0x000, 0x800, CRC(56653188) SHA1(84b90f69671d4b72e8f219e1fe7cd667e976cf7f) )
ROM_END
ROM_START( pc8001mk2 )
ROM_REGION( 0x8000, Z80_TAG, 0 )
- ROM_LOAD( "n80_2.rom", 0x00000, 0x8000, CRC(03cce7b6) SHA1(c12d34e42021110930fed45a8af98db52136f1fb) )
+ // N-BASIC v1.3
+ // N80-BASIC v1.0
+ ROM_LOAD( "n80_2.rom", 0x0000, 0x8000, CRC(03cce7b6) SHA1(c12d34e42021110930fed45a8af98db52136f1fb) )
- ROM_REGION( 0x800, UPD3301_TAG, 0)
+ ROM_REGION( 0x800, CGROM_TAG, 0)
ROM_LOAD( "font.rom", 0x0000, 0x0800, CRC(56653188) SHA1(84b90f69671d4b72e8f219e1fe7cd667e976cf7f) )
ROM_REGION( 0x20000, "kanji", 0)
ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
ROM_END
+ROM_START( pc8001mk2sr )
+ ROM_REGION( 0x8000, Z80_TAG, 0 )
+ // N-BASIC v1.6
+ // N80-BASIC v1.2
+ ROM_LOAD( "n80_2sr.rom", 0x0000, 0x8000, CRC(dcb71282) SHA1(e8db5dc5eae11da14e48656d324874e59f2e3844) )
+
+ ROM_REGION (0x10000, N80SR_ROM_TAG, ROMREGION_ERASEFF )
+ // N80SR-BASIC v1.0
+ ROM_LOAD( "n80_3.rom", 0x0000, 0xa000, BAD_DUMP CRC(d99ef247) SHA1(9bfa5009d703cd31caa734d932d2a847d74cbfa6) )
+
+ ROM_REGION( 0x2000, CGROM_TAG, 0)
+ ROM_LOAD( "font80sr.rom", 0x000000, 0x001000, CRC(784c0b17) SHA1(565dc8e5e46b1633cb434d12b4d8b3a662546b33) )
+ ROM_LOAD( "fonthira.rom", 0x001000, 0x000800, CRC(fe7059d5) SHA1(10c5f85adcce540cbd0a11352e2c38a84c989a26) )
+ ROM_LOAD( "fontkata.rom", 0x001800, 0x000800, CRC(56653188) SHA1(84b90f69671d4b72e8f219e1fe7cd667e976cf7f) )
+
+ ROM_REGION( 0x20000, "kanji", 0)
+ ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
+ROM_END
+
/* System Drivers */
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
-COMP( 1979, pc8001, 0, 0, pc8001, pc8001, pc8001_state, empty_init, "NEC", "PC-8001", MACHINE_NOT_WORKING )
-COMP( 1983, pc8001mk2, pc8001, 0, pc8001mk2, pc8001, pc8001mk2_state, empty_init, "NEC", "PC-8001mkII", MACHINE_NOT_WORKING )
+// 1978?, pc8001g, Wirewrapped prototype version
+COMP( 1979, pc8001, 0, 0, pc8001, pc8001, pc8001_state, empty_init, "NEC", "PC-8001", MACHINE_NOT_WORKING )
+// 1981 pc8001a, US version of PC-8001 with Greek alphabet instead of Kana
+COMP( 1983, pc8001mk2, pc8001, 0, pc8001mk2, pc8001mk2, pc8001mk2_state, empty_init, "NEC", "PC-8001mkII", MACHINE_NOT_WORKING )
+COMP( 1985, pc8001mk2sr, pc8001, 0, pc8001mk2sr, pc8001mk2sr, pc8001mk2sr_state, empty_init, "NEC", "PC-8001mkIISR", MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/pc8801.cpp b/src/mame/drivers/pc8801.cpp
index a50c1d6317f..2e975032af3 100644
--- a/src/mame/drivers/pc8801.cpp
+++ b/src/mame/drivers/pc8801.cpp
@@ -25,29 +25,17 @@
probably others (does bus have an actual codename or just "PC-8801 bus"?);
- below notes states that plain PC-8801 doesn't have a disk CPU, but the BIOS clearly checks
the floppy ports. Wrong info or check for external board anyway?
- - fix "jumps" in mouse support pointer (noticeable in Balance of Power);
-
- per-game specific TODO:
- - 100yen Soft 8 Revival Special: tight loop with vblank bit, but vblank irq takes too much time to execute its code;
- - 177: gameplay is too fast (parent pc8801 only);
- - 1942: missing sound, enables a masked irq;
- - Acro Jet: hangs waiting for an irq (floppy issue);
- - Arcus: doesn't surpass Wolf Team logo;
- - Advanced Fantasian: garbage during gameplay (floppy?)
- - American Success: reads the light pen?
- - Attacker: resets after a bunch of animation frames;
- - Balance of Power: uses the SIO port for something ...
+ - fix "jumps" in PC-8872 mouse pointer (noticeable in balpower);
+
+ per-game specific TODO (move to XML):
- Belloncho Shintai Kensa: hangs
- Bishoujo Baseball Gakuen: checks ym2608 after intro screen;
- The Black Onyx: writes a katakana msg: "sono kata ha koko ni orimasen" then doesn't show up anything. (Needs user disk?)
- - Boukenshatachi: dies after the intro.
- Campaign Ban Daisenryaku 2: Hangs at title screen?
- - Carigraph: inputs doesn't work?
- Can Can Bunny: bitmap artifacts on intro, caused by a fancy usage of the attribute vram;
- Can Can Bunny: no sound (regression);
- Can Can Bunny Superior: black screen during the intro
- Chou Bishoujo Densetsu CROQUIS: accesses ports 0xa0-0xa3 and 0xc2-0xc3
- - Combat: mono gfx mode enabled, but I don't see any noticeable quirk?
- Cranston Manor (actually N88-Basic demo): no sound
- Datenshi Kyouko: gfx garbage on the right edge?
- Final Crisis: sound stuck with OPNA?
@@ -56,10 +44,7 @@
- Gaudi - Barcelona no Kaze: fails PCM loading
- GeGeGe no Kitarou: title screen text/bitmap contrast is pretty ugly (BTANB?);
- Grobda: palette is ugly (parent pc8801 only);
- - Makaimura: after losing a life the game doesn't work properly anymore, copy protection?
- Music Collection Vol. 2 - Final Fantasy Tokushuu: sound irq dies pretty soon
- - N-BASIC: cursor doesn't show up;
- - The Return of Ishtar: z80 exception after entering the name.
- Star Cruiser: bad kanji data?
- Star Cruiser: reads at i/o 0x8e?
- Wanderers from Ys: user data disk looks screwed? It loads with everything as maximum as per now ...
@@ -120,11 +105,6 @@
- Fruit Panic
- FSD Sample Ongaku Shuu Vol. 1-7
- Gaia no Kiba (Disk I/O error at 150)
- - Gaiflame
- - Gambler Jiko Chuushin ha
- - Gambler Jiko Chuushin ha 2
- - Gambler Jiko Chuushin ha 3
- - Gambler Jiko Chuushin ha 3 (demo)
- Gambler Jiko Chuushin ha Mahjong Puzzle Collection
- Gambler Jiko Chuushin ha Mahjong Puzzle Collection (demo)
* Game Music Library
@@ -142,14 +122,12 @@
* MakaiMura (attempts to r/w the sio ports, but it's clearly crashed)
* Mugen Senshi Valis (at Telenet logo, it also appears to have a nasty copy protection when taking a specific item (untested))
- Mr. Pro Yakyuu
- - Panorama Toh
- PC-8034 (app)
- PC-8037SR (app)
- P1 (app)
- Pattern Editor 88 (app)
- Super Shunbo II (app) (Load error)
- Super TII (app)
- * The Return of Ishtar
- Tobira wo Akete (random crashes in parent pc8801 only)
list of games that doesn't like i8214_irq_level == 5 in sound irq
@@ -360,6 +338,8 @@ void pc8801_state::draw_bitmap_3bpp(bitmap_ind16 &bitmap,const rectangle &clipre
void pc8801_state::draw_bitmap_1bpp(bitmap_ind16 &bitmap,const rectangle &cliprect)
{
+ // TODO: jettermi really masks the color attribute from 3301
+ // (we currently draw it in b&w, should be colorized)
uint32_t count = 0;
uint8_t color = (m_gfx_ctrl & 1) ? 7 & ((m_layer_mask ^ 0xe) >> 1) : 7;
uint8_t is_cursor = 0;
@@ -803,9 +783,7 @@ uint8_t pc8801_state::pc8801_mem_r(offs_t offset)
window_offset = (offset & 0x3ff) + (m_window_offset_bank << 8);
- if(((window_offset & 0xf000) == 0xf000) && (m_misc_ctrl & 0x10))
- printf("Read from 0xf000 - 0xffff window offset\n"); //accessed by Castle Excellent, no noticeable quirk
-
+ // castlex and imenes accesses this
if(((window_offset & 0xf000) == 0xf000) && (m_misc_ctrl & 0x10))
return pc8801_high_wram_r(window_offset & 0xfff);
@@ -864,9 +842,9 @@ void pc8801_state::pc8801_mem_w(offs_t offset, uint8_t data)
window_offset = (offset & 0x3ff) + (m_window_offset_bank << 8);
- if(((window_offset & 0xf000) == 0xf000) && (m_misc_ctrl & 0x10))
- printf("Write to 0xf000 - 0xffff window offset\n"); //accessed by Castle Excellent, no noticeable quirk
-
+ // castlex and imenes accesses this
+ // TODO: high TVRAM even
+ // (uPD3301 reads from this instead of the regular work RAM)
if(((window_offset & 0xf000) == 0xf000) && (m_misc_ctrl & 0x10))
pc8801_high_wram_w(window_offset & 0xfff,data);
else
@@ -1117,6 +1095,20 @@ void pc8801_state::pc8801_window_bank_inc_w(uint8_t data)
m_window_offset_bank&=0xff;
}
+/*
+ * I/O Port $32 (R/W)
+ *
+ * x--- ---- sound irq mask (0) irq enabled (1) irq masked
+ * -x-- ---- Graphic VRAM access mode (0) independent access mode (1) ALU mode
+ * --x- ---- analog (1) / digital (0) palette select
+ * ---x ---- high speed RAM select (for TVRAM) (1) main RAM bank (0) dedicated Text RAM
+ * ---- xx-- Screen output mode
+ * ---- 00-- TV / video mode
+ * ---- 01-- None (as in disabling the screen entirely?)
+ * ---- 10-- Analog RGB mode
+ * ---- 11-- Optional mode
+ * ---- --xx internal EROM selection
+ */
uint8_t pc8801_state::pc8801_misc_ctrl_r()
{
return m_misc_ctrl;
@@ -1124,11 +1116,6 @@ uint8_t pc8801_state::pc8801_misc_ctrl_r()
void pc8801_state::pc8801_misc_ctrl_w(uint8_t data)
{
- /*
- x--- ---- sound irq mask, active low
- --x- ---- analog (1) / digital (0) palette select
- */
-
m_misc_ctrl = data;
#if USE_PROPER_I8214
@@ -1182,6 +1169,7 @@ void pc8801_state::pc8801_palram_w(offs_t offset, uint8_t data)
// TODO: What happens to the palette contents when the analog/digital palette mode changes?
// Preserve content? Translation? Undefined?
m_palette->set_pen_color(offset, pal3bit(m_palram[offset].r), pal3bit(m_palram[offset].g), pal3bit(m_palram[offset].b));
+ // TODO: at least analog mode can do rasters
}
void pc8801_state::pc8801_layer_masking_w(uint8_t data)
@@ -1472,7 +1460,7 @@ uint8_t pc8801_state::pc8801_sound_board_r(offs_t offset)
void pc8801_state::pc8801_sound_board_w(offs_t offset, uint8_t data)
{
if(m_has_opna)
- m_opna->write(offset,data);
+ m_opna->write(offset, data);
else if((offset & 2) == 0)
m_opn->write(offset, data);
}
@@ -1590,95 +1578,7 @@ void pc8801_state::pc8801_io(address_map &map)
// map(0xf3, 0xf3).noprw(); /* DMA floppy (unknown) */
// map(0xf4, 0xf7).noprw(); /* DMA 5'floppy (may be not released) */
// map(0xf8, 0xfb).noprw(); /* DMA 8'floppy (unknown) */
- map(0xfc, 0xff).rw("d8255_master", FUNC(i8255_device::read), FUNC(i8255_device::write));
-}
-
-uint8_t pc8801_state::cpu_8255_c_r()
-{
-// machine().scheduler().synchronize(); // force resync
-
- return m_i8255_1_pc >> 4;
-}
-
-void pc8801_state::cpu_8255_c_w(uint8_t data)
-{
-// machine().scheduler().synchronize(); // force resync
-
- m_i8255_0_pc = data;
-}
-
-
-uint8_t pc8801_state::fdc_8255_c_r()
-{
-// machine().scheduler().synchronize(); // force resync
-
- return m_i8255_0_pc >> 4;
-}
-
-void pc8801_state::fdc_8255_c_w(uint8_t data)
-{
-// machine().scheduler().synchronize(); // force resync
-
- m_i8255_1_pc = data;
-}
-
-void pc8801_state::pc8801fdc_mem(address_map &map)
-{
- map(0x0000, 0x1fff).rom();
- map(0x4000, 0x7fff).ram();
-}
-
-TIMER_CALLBACK_MEMBER(pc8801_state::pc8801fd_upd765_tc_to_zero)
-{
- // TODO: holein1 explictly reads TC port at PC=504e followed by an HALT opcode, failing to boot
- // is this gonna unbreak HALT state too?
- m_fdc->tc_w(false);
-}
-
-void pc8801_state::upd765_mc_w(uint8_t data)
-{
- m_fdd[0]->get_device()->mon_w(!(data & 1));
- m_fdd[1]->get_device()->mon_w(!(data & 2));
-}
-
-uint8_t pc8801_state::upd765_tc_r()
-{
- //printf("%04x 1\n",m_fdccpu->pc());
-
- if (!machine().side_effects_disabled())
- {
- m_fdc->tc_w(true);
- //TODO: I'm not convinced that this works correctly with current hook-up ... 1000 usec is needed by Aploon, a bigger value breaks Alpha.
- //OTOH, 50 seems more than enough for the new upd...
- machine().scheduler().timer_set(attotime::from_usec(50), timer_expired_delegate(FUNC(pc8801_state::pc8801fd_upd765_tc_to_zero),this));
- }
- return 0xff; // value is meaningless
-}
-
-void pc8801_state::fdc_irq_vector_w(uint8_t data)
-{
- popmessage("Write to FDC IRQ vector I/O %02x, contact MESSdev\n",data);
- m_fdc_irq_opcode = data;
-}
-
-void pc8801_state::fdc_drive_mode_w(uint8_t data)
-{
- logerror("FDC drive mode %02x\n", data);
- m_fdd[0]->get_device()->set_rpm(data & 0x01 ? 360 : 300);
- m_fdd[1]->get_device()->set_rpm(data & 0x02 ? 360 : 300);
-
- m_fdc->set_rate(data & 0x20 ? 500000 : 250000);
-}
-
-void pc8801_state::pc8801fdc_io(address_map &map)
-{
- map.global_mask(0xff);
- map(0xf0, 0xf0).w(FUNC(pc8801_state::fdc_irq_vector_w)); // Interrupt Opcode Port
- map(0xf4, 0xf4).w(FUNC(pc8801_state::fdc_drive_mode_w)); // Drive mode, 2d, 2dd, 2hd
- map(0xf7, 0xf7).nopw(); // printer port output
- map(0xf8, 0xf8).rw(FUNC(pc8801_state::upd765_tc_r), FUNC(pc8801_state::upd765_mc_w)); // (R) Terminal Count Port (W) Motor Control Port
- map(0xfa, 0xfb).m(m_fdc, FUNC(upd765a_device::map));
- map(0xfc, 0xff).rw("d8255_slave", FUNC(i8255_device::read), FUNC(i8255_device::write));
+ map(0xfc, 0xff).m(m_pc80s31, FUNC(pc80s31_device::host_map));
}
void pc8801_state::opna_map(address_map &map)
@@ -2005,12 +1905,6 @@ static GFXDECODE_START( gfx_pc8801 )
GFXDECODE_ENTRY( "kanji", 0, kanji_layout, 0, 8 )
GFXDECODE_END
-/* Floppy Configuration */
-
-static void pc88_floppies(device_slot_interface &device)
-{
- device.option_add("525hd", FLOPPY_525_HD);
-}
#if 0
/* Cassette Configuration */
@@ -2164,10 +2058,6 @@ INTERRUPT_GEN_MEMBER(pc8801_state::pc8801_vrtc_irq)
void pc8801_state::machine_start()
{
- m_fdd[0]->get_device()->set_rpm(300);
- m_fdd[1]->get_device()->set_rpm(300);
- m_fdc->set_rate(250000);
-
m_rtc->cs_w(1);
m_rtc->oe_w(1);
@@ -2203,11 +2093,8 @@ void pc8801_state::machine_reset()
// pc8801_dynamic_res_change(machine());
- m_fdc_irq_opcode = 0; //TODO: copied from PC-88VA, could be wrong here ... should be 0x7f ld a,a in the latter case
m_mouse.phase = 0;
- m_fdccpu->set_input_line_vector(0, 0); // Z80
-
{
m_txt_color = 2;
}
@@ -2277,7 +2164,8 @@ MACHINE_RESET_MEMBER(pc8801_state,pc8801_clock_speed)
m_clock_setting = ioport("CFG")->read() & 0x80;
m_maincpu->set_unscaled_clock(m_clock_setting ? XTAL(4'000'000) : XTAL(8'000'000));
- m_fdccpu->set_unscaled_clock(m_clock_setting ? XTAL(4'000'000) : XTAL(8'000'000)); // correct?
+ // TODO: FDC board shouldn't be connected to the clock setting, verify
+// m_fdccpu->set_unscaled_clock(m_clock_setting ? XTAL(4'000'000) : XTAL(8'000'000));
m_baudrate_val = 0;
}
@@ -2348,28 +2236,11 @@ void pc8801_state::pc8801(machine_config &config)
m_maincpu->set_vblank_int("screen", FUNC(pc8801_state::pc8801_vrtc_irq));
m_maincpu->set_irq_acknowledge_callback(FUNC(pc8801_state::pc8801_irq_callback));
- /* sub CPU(5 inch floppy drive) */
- Z80(config, m_fdccpu, MASTER_CLOCK); /* 4 MHz */
- m_fdccpu->set_addrmap(AS_PROGRAM, &pc8801_state::pc8801fdc_mem);
- m_fdccpu->set_addrmap(AS_IO, &pc8801_state::pc8801fdc_io);
-
- //config.set_maximum_quantum(attotime::from_hz(300000));
+ PC80S31(config, m_pc80s31, MASTER_CLOCK);
config.set_perfect_quantum(m_maincpu);
+ config.set_perfect_quantum("pc80s31:fdc_cpu");
- i8255_device &d8255_master(I8255(config, "d8255_master"));
- d8255_master.in_pa_callback().set("d8255_slave", FUNC(i8255_device::pb_r));
- d8255_master.in_pb_callback().set("d8255_slave", FUNC(i8255_device::pa_r));
- d8255_master.in_pc_callback().set(FUNC(pc8801_state::cpu_8255_c_r));
- d8255_master.out_pc_callback().set(FUNC(pc8801_state::cpu_8255_c_w));
-
- i8255_device &d8255_slave(I8255(config, "d8255_slave"));
- d8255_slave.in_pa_callback().set("d8255_master", FUNC(i8255_device::pb_r));
- d8255_slave.in_pb_callback().set("d8255_master", FUNC(i8255_device::pa_r));
- d8255_slave.in_pc_callback().set(FUNC(pc8801_state::fdc_8255_c_r));
- d8255_slave.out_pc_callback().set(FUNC(pc8801_state::fdc_8255_c_w));
-
- UPD765A(config, m_fdc, 8'000'000, true, true);
- m_fdc->intrq_wr_callback().set_inputline(m_fdccpu, INPUT_LINE_IRQ0);
+// config.set_maximum_quantum(attotime::from_hz(MASTER_CLOCK/1024));
#if USE_PROPER_I8214
I8214(config, I8214_TAG, MASTER_CLOCK);
@@ -2386,9 +2257,8 @@ void pc8801_state::pc8801(machine_config &config)
i8251.txd_handler().set(FUNC(pc8801_state::txdata_callback));
i8251.rts_handler().set(FUNC(pc8801_state::rxrdy_w));
- FLOPPY_CONNECTOR(config, "upd765:0", pc88_floppies, "525hd", floppy_image_device::default_mfm_floppy_formats);
- FLOPPY_CONNECTOR(config, "upd765:1", pc88_floppies, "525hd", floppy_image_device::default_mfm_floppy_formats);
- SOFTWARE_LIST(config, "disk_list").set_original("pc8801_flop");
+ SOFTWARE_LIST(config, "disk_n88_list").set_original("pc8801_flop");
+ SOFTWARE_LIST(config, "disk_n_list").set_original("pc8001_flop");
/* video hardware */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
@@ -2431,21 +2301,27 @@ void pc8801_state::pc8801(machine_config &config)
TIMER(config, "rtc_timer").configure_periodic(FUNC(pc8801_state::pc8801_rtc_irq), attotime::from_hz(600));
}
-void pc8801_state::pc8801fh(machine_config &config)
+void pc8801_state::pc8801mk2mr(machine_config &config)
{
pc8801(config);
+ PC80S31K(config.replace(), m_pc80s31, MASTER_CLOCK);
+}
+
+void pc8801_state::pc8801fh(machine_config &config)
+{
+ pc8801mk2mr(config);
MCFG_MACHINE_RESET_OVERRIDE(pc8801_state, pc8801_clock_speed )
}
void pc8801_state::pc8801ma(machine_config &config)
{
- pc8801(config);
+ pc8801fh(config);
MCFG_MACHINE_RESET_OVERRIDE(pc8801_state, pc8801_dic )
}
void pc8801_state::pc8801mc(machine_config &config)
{
- pc8801(config);
+ pc8801ma(config);
MCFG_MACHINE_RESET_OVERRIDE(pc8801_state, pc8801_cdrom )
}
@@ -2457,9 +2333,6 @@ ROM_START( pc8801 )
ROM_LOAD( "n88.rom", 0x0000, 0x8000, CRC(ffd68be0) SHA1(3518193b8207bdebf22c1380c2db8c554baff329) )
ROM_LOAD( "n88_0.rom", 0x8000, 0x2000, CRC(61984bab) SHA1(d1ae642aed4f0584eeb81ff50180db694e5101d4) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "disk.rom", 0x0000, 0x0800, CRC(2158d307) SHA1(bb7103a0818850a039c67ff666a31ce49a8d516f) )
-
ROM_REGION( 0x40000, "kanji", ROMREGION_ERASEFF)
ROM_LOAD_OPTIONAL( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
@@ -2477,9 +2350,6 @@ ROM_START( pc8801mk2 )
ROM_LOAD( "m2_n88.rom", 0x0000, 0x8000, CRC(f35169eb) SHA1(ef1f067f819781d9fb2713836d195866f0f81501) )
ROM_LOAD( "m2_n88_0.rom", 0x8000, 0x2000, CRC(5eb7a8d0) SHA1(95a70af83b0637a5a0f05e31fb0452bb2cb68055) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "disk.rom", 0x0000, 0x0800, CRC(2158d307) SHA1(bb7103a0818850a039c67ff666a31ce49a8d516f) )
-
ROM_REGION( 0x40000, "kanji", ROMREGION_ERASEFF)
ROM_LOAD_OPTIONAL( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
@@ -2498,13 +2368,6 @@ ROM_START( pc8801mk2sr )
ROM_LOAD( "n88_2.rom", 0xc000, 0x2000, CRC(af2b6efa) SHA1(b7c8bcea219b77d9cc3ee0efafe343cc307425d1) )
ROM_LOAD( "n88_3.rom", 0xe000, 0x2000, CRC(7713c519) SHA1(efce0b51cab9f0da6cf68507757f1245a2867a72) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "disk.rom", 0x0000, 0x0800, CRC(2158d307) SHA1(bb7103a0818850a039c67ff666a31ce49a8d516f) )
-
- /* No idea of the proper size: it has never been dumped */
- ROM_REGION( 0x2000, "audiocpu", 0)
- ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
-
ROM_REGION( 0x40000, "kanji", 0)
ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
ROM_LOAD( "kanji2.rom", 0x20000, 0x20000, CRC(154803cc) SHA1(7e6591cd465cbb35d6d3446c5a83b46d30fafe95) ) // it should not be here
@@ -2524,13 +2387,6 @@ ROM_START( pc8801mk2fr )
ROM_LOAD( "m2fr_n88_2.rom", 0xc000, 0x2000, CRC(98c3a7b2) SHA1(fc4980762d3caa56964d0ae583424756f511d186) )
ROM_LOAD( "m2fr_n88_3.rom", 0xe000, 0x2000, CRC(0ca08abd) SHA1(a5a42d0b7caa84c3bc6e337c9f37874d82f9c14b) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "m2fr_disk.rom", 0x0000, 0x0800, CRC(2163b304) SHA1(80da2dee49d4307f00895a129a5cfeff00cf5321) )
-
- /* No idea of the proper size: it has never been dumped */
- ROM_REGION( 0x2000, "audiocpu", 0)
- ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
-
ROM_REGION( 0x40000, "kanji", 0)
ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
@@ -2549,13 +2405,6 @@ ROM_START( pc8801mk2mr )
ROM_LOAD( "m2mr_n88_2.rom", 0xc000, 0x2000, CRC(11176e0b) SHA1(f13f14f3d62df61498a23f7eb624e1a646caea45) )
ROM_LOAD( "m2mr_n88_3.rom", 0xe000, 0x2000, CRC(0ca08abd) SHA1(a5a42d0b7caa84c3bc6e337c9f37874d82f9c14b) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "m2mr_disk.rom", 0x0000, 0x2000, CRC(2447516b) SHA1(1492116f15c426f9796dc2bb6fcccf2656c0ca75) )
-
- /* No idea of the proper size: it has never been dumped */
- ROM_REGION( 0x2000, "audiocpu", 0)
- ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
-
ROM_REGION( 0x40000, "kanji", 0)
ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
ROM_LOAD( "m2mr_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
@@ -2575,13 +2424,6 @@ ROM_START( pc8801mh )
ROM_LOAD( "mh_n88_2.rom", 0xc000, 0x2000, CRC(6aa6b6d8) SHA1(2a077ab444a4fd1470cafb06fd3a0f45420c39cc) )
ROM_LOAD( "mh_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "mh_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004) )
-
- /* No idea of the proper size: it has never been dumped */
- ROM_REGION( 0x2000, "audiocpu", 0)
- ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
-
ROM_REGION( 0x40000, "kanji", 0)
ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
ROM_LOAD( "mh_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
@@ -2601,13 +2443,6 @@ ROM_START( pc8801fa )
ROM_LOAD( "fa_n88_2.rom", 0xc000, 0x2000, CRC(6aee9a4e) SHA1(e94278682ef9e9bbb82201f72c50382748dcea2a) )
ROM_LOAD( "fa_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "fa_disk.rom", 0x0000, 0x0800, CRC(2163b304) SHA1(80da2dee49d4307f00895a129a5cfeff00cf5321) )
-
- /* No idea of the proper size: it has never been dumped */
- ROM_REGION( 0x2000, "audiocpu", 0)
- ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
-
ROM_REGION( 0x40000, "kanji", 0 )
ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
ROM_LOAD( "fa_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
@@ -2627,13 +2462,6 @@ ROM_START( pc8801ma ) // newer floppy BIOS and Jisyo (dictionary) ROM
ROM_LOAD( "ma_n88_2.rom", 0xc000, 0x2000, CRC(6aee9a4e) SHA1(e94278682ef9e9bbb82201f72c50382748dcea2a) )
ROM_LOAD( "ma_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "ma_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004) )
-
- /* No idea of the proper size: it has never been dumped */
- ROM_REGION( 0x2000, "audiocpu", 0)
- ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
-
ROM_REGION( 0x40000, "kanji", 0 )
ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
ROM_LOAD( "ma_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
@@ -2657,13 +2485,6 @@ ROM_START( pc8801ma2 )
ROM_LOAD( "ma2_n88_2.rom", 0xc000, 0x2000, CRC(1d6277b6) SHA1(dd9c3e50169b75bb707ef648f20d352e6a8bcfe4) )
ROM_LOAD( "ma2_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "ma2_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004) )
-
- /* No idea of the proper size: it has never been dumped */
- ROM_REGION( 0x2000, "audiocpu", 0)
- ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
-
ROM_REGION( 0x40000, "kanji", 0)
ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
ROM_LOAD( "ma2_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
@@ -2686,16 +2507,9 @@ ROM_START( pc8801mc )
ROM_LOAD( "mc_n88_2.rom", 0xc000, 0x2000, CRC(1d6277b6) SHA1(dd9c3e50169b75bb707ef648f20d352e6a8bcfe4) )
ROM_LOAD( "mc_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
- ROM_REGION( 0x10000, "fdccpu", 0)
- ROM_LOAD( "mc_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004) )
-
ROM_REGION( 0x10000, "cdrom", 0 )
ROM_LOAD( "cdbios.rom", 0x0000, 0x10000, CRC(5c230221) SHA1(6394a8a23f44ea35fcfc3e974cf940bc8f84d62a) )
- /* No idea of the proper size: it has never been dumped */
- ROM_REGION( 0x2000, "audiocpu", 0)
- ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
-
ROM_REGION( 0x40000, "kanji", 0 )
ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
ROM_LOAD( "mc_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
@@ -2716,15 +2530,15 @@ COMP( 1983, pc8801mk2, pc8801, 0, pc8801, pc88sr, pc8801_state, empt
COMP( 1985, pc8801mk2sr, pc8801, 0, pc8801, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801mkIISR", MACHINE_NOT_WORKING )
//COMP( 1985, pc8801mk2tr, pc8801, 0, pc8801, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801mkIITR", MACHINE_NOT_WORKING )
COMP( 1985, pc8801mk2fr, pc8801, 0, pc8801, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801mkIIFR", MACHINE_NOT_WORKING )
-COMP( 1985, pc8801mk2mr, pc8801, 0, pc8801, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801mkIIMR", MACHINE_NOT_WORKING )
+COMP( 1985, pc8801mk2mr, pc8801, 0, pc8801mk2mr, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801mkIIMR", MACHINE_NOT_WORKING )
-//COMP( 1986, pc8801fh, 0, 0, pc8801, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801FH", MACHINE_NOT_WORKING )
+//COMP( 1986, pc8801fh, 0, 0, pc8801mk2fr, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801FH", MACHINE_NOT_WORKING )
COMP( 1986, pc8801mh, pc8801, 0, pc8801fh, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801MH", MACHINE_NOT_WORKING )
COMP( 1987, pc8801fa, pc8801, 0, pc8801fh, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801FA", MACHINE_NOT_WORKING )
COMP( 1987, pc8801ma, pc8801, 0, pc8801ma, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801MA", MACHINE_NOT_WORKING )
-//COMP( 1988, pc8801fe, pc8801, 0, pc8801, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801FE", MACHINE_NOT_WORKING )
+//COMP( 1988, pc8801fe, pc8801, 0, pc8801fa, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801FE", MACHINE_NOT_WORKING )
COMP( 1988, pc8801ma2, pc8801, 0, pc8801ma, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801MA2", MACHINE_NOT_WORKING )
-//COMP( 1989, pc8801fe2, pc8801, 0, pc8801, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801FE2", MACHINE_NOT_WORKING )
+//COMP( 1989, pc8801fe2, pc8801, 0, pc8801fa, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801FE2", MACHINE_NOT_WORKING )
COMP( 1989, pc8801mc, pc8801, 0, pc8801mc, pc88sr, pc8801_state, empty_init, "NEC", "PC-8801MC", MACHINE_NOT_WORKING )
//COMP( 1989, pc98do, 0, 0, pc88va, pc88sr, pc8801_state, empty_init, "NEC", "PC-98DO", MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/pc88va.cpp b/src/mame/drivers/pc88va.cpp
index 7e6bc817e80..7e2dbb70afa 100644
--- a/src/mame/drivers/pc88va.cpp
+++ b/src/mame/drivers/pc88va.cpp
@@ -13,7 +13,7 @@
- What exact kind of garbage happens if you try to enable both direct and palette color
modes to a graphic layer?
- unemulated upd71071 demand mode;
- - What is exactly supposed to be a "bus slot"?
+ - What is exactly supposed to be a "bus slot"? Does it have an official name?
- fdc "intelligent mode" has 0x7f as irq vector ... 0x7f is ld a,a and it IS NOT correctly
hooked up by the current z80 core
- PC-88VA stock version has two bogus opcodes. One is at 0xf0b15, another at 0xf0b31.
diff --git a/src/mame/drivers/rollext.cpp b/src/mame/drivers/rollext.cpp
index adb2c2d9aca..be7d9cb13c4 100644
--- a/src/mame/drivers/rollext.cpp
+++ b/src/mame/drivers/rollext.cpp
@@ -63,214 +63,339 @@
ROM [0xc0050000] 0x10000 floats copied to [0x40180000]
+ ROM [0xff800000 - 0xff80171f] sound data headers, 32 bytes each
+ Word 0: sound data pointer (offset from 0xff800000)
+ Word 1: uncompressed length?
+ Word 2: ?
+ Word 3: same as word 1?
+ Word 4: ?
+ Word 5: ?
+ Word 6: ?
+ Word 7: 0
+
+ ROM [0xff801720 -> ] compressed audio data
+
+ [0x0000100c] bitmask of active sound channels (max 16 channels?)
+ [0x00001018 -> ] sound channel data, 64 bytes each
+ +0x00: sound data pointer in ROM
+ +0x04: 0
+ +0x08: uncompressed length
+ +0x0c: uncompressed length
+ +0x10: 0?
+ +0x14: 0 - sample rate?
+ +0x18: 0?
+ +0x1c: sample rate? (halfword)
+ +0x1e: ?? (halfword)
+ +0x20: ?
+ +0x24: ?
+ +0x28: ?
+ +0x2c: ?
+ +0x30: ?
+ +0x34: ?
+ +0x36: ? (halfword)
+ +0x38: ?
+ +0x3c: ?
+
+
Texture ROM decode:
{ic45} {ic47} {ic58} {ic60}
[2,0][0,0] [2,1][0,1] [3,0][1,0] [3,1][1,1]
+
+
+ TODO:
+
+ - TMS320C82 parallel processors are not emulated
+ * PP0 transfers polygon data from a software FIFO to the graphics processor. This is currently HLE'd.
+ * PP1 most likely does sound mixing. This is currently not emulated.
+ - Alpha blending (probably based on palette index like on gaelco3d)
+ - Minor Z-buffer issues
+ - Wrong textures in a few places (could be a CPU core bug)
+ - Networking
+
*/
#include "emu.h"
#include "cpu/tms32082/tms32082.h"
#include "video/poly.h"
+#include "video/rgbutil.h"
+#include "machine/eepromser.h"
#include "screen.h"
+#define BILINEAR 1
+
struct rollext_polydata
{
- uint32_t tex_bottom;
- uint32_t tex_left;
+ uint32_t tex_origin_y;
+ uint32_t tex_origin_x;
uint32_t pal;
+ float uoz_dx;
+ float uoz_dy;
+ float voz_dx;
+ float voz_dy;
+ float ooz_dx;
+ float ooz_dy;
+ float baseu;
+ float basev;
+ float basez;
+ uint32_t zmul;
};
class rollext_renderer : public poly_manager<float, rollext_polydata, 4>
{
+ friend class rollext_state;
+
public:
rollext_renderer(screen_device &screen)
: poly_manager<float, rollext_polydata, 4>(screen.machine())
{
- m_fb = std::make_unique<bitmap_rgb32>(1024, 1024);
+ m_fb[0] = std::make_unique<bitmap_rgb32>(1024, 1024);
+ m_fb[1] = std::make_unique<bitmap_rgb32>(1024, 1024);
+
+ m_zb = std::make_unique<bitmap_ind32>(1024, 1024);
+
+
+ m_palette = std::make_unique<rgb_t[]>(32768);
+ m_texture_mask = std::make_unique<uint8_t[]>(2048 * 16384);
+
+ m_fb_current = 0;
}
+ template<bool UseZ>
void render_texture_scan(int32_t scanline, const extent_t &extent, const rollext_polydata &extradata, int threadid);
- void set_texture_ram(uint8_t* texture_ram);
- void set_palette_ram(uint16_t* palette_ram);
+ void set_texture_ram(uint8_t* texture_ram) { m_texture_ram = texture_ram; }
void process_display_list(screen_device &screen, uint32_t* dispram);
+ void palette_write(int index, uint16_t data);
+ void texture_mask_write(int index, uint8_t data);
+
void clear_fb();
void display(bitmap_rgb32 *bitmap, const rectangle &cliprect);
private:
- std::unique_ptr<bitmap_rgb32> m_fb;
+ std::unique_ptr<bitmap_rgb32> m_fb[2];
+ std::unique_ptr<rgb_t[]> m_palette;
+ std::unique_ptr<uint8_t[]> m_texture_mask;
+
+ std::unique_ptr<bitmap_ind32> m_zb;
+
+ int m_fb_current;
uint8_t *m_texture_ram;
- uint16_t *m_palette_ram;
};
-void rollext_renderer::set_texture_ram(uint8_t* texture_ram)
+template<bool UseZ>
+void rollext_renderer::render_texture_scan(int32_t scanline, const extent_t &extent, const rollext_polydata &extradata, int threadid)
{
- m_texture_ram = texture_ram;
-}
+ uint32_t *fb = &m_fb[m_fb_current]->pix(scanline);
+ uint32_t* const zb = &m_zb->pix(scanline);
-void rollext_renderer::set_palette_ram(uint16_t* palette_ram)
-{
- m_palette_ram = palette_ram;
-}
+ uint32_t tex_origin_y = extradata.tex_origin_y;
+ uint32_t tex_origin_x = extradata.tex_origin_x;
-void rollext_renderer::render_texture_scan(int32_t scanline, const extent_t &extent, const rollext_polydata &extradata, int threadid)
-{
- float u = extent.param[0].start;
- float v = extent.param[1].start;
- float du = extent.param[0].dpdx;
- float dv = extent.param[1].dpdx;
+ float baseu = extradata.baseu;
+ float basev = extradata.basev;
+ float basez = extradata.basez;
+ float uoz_dx = extradata.uoz_dx;
+ float uoz_dy = extradata.uoz_dy;
+ float voz_dx = extradata.voz_dx;
+ float voz_dy = extradata.voz_dy;
+ float ooz_dx = extradata.ooz_dx;
+ float ooz_dy = extradata.ooz_dy;
- uint32_t *fb = &m_fb->pix(scanline);
+ uint32_t zmul = extradata.zmul;
- uint32_t texbot = extradata.tex_bottom;
- uint32_t texleft = extradata.tex_left;
+ int palnum = extradata.pal << 8;
- int palnum = extradata.pal;
+ float uoz = baseu + (uoz_dx * (extent.startx - 256)) + (-uoz_dy * (scanline - 192));
+ float voz = basev + (voz_dx * (extent.startx - 256)) + (-voz_dy * (scanline - 192));
+ float ooz = basez + (ooz_dx * (extent.startx - 256)) + (-ooz_dy * (scanline - 192));
for (int x = extent.startx; x < extent.stopx; x++)
{
- int iu = (int)(u * 29.0f);
- int iv = (int)(v * 29.0f);
+ float z = recip_approx(ooz);
+ uint32_t zbufval = (int)(z * zmul);
+
+ if (zbufval <= zb[x] || !UseZ)
+ {
+ float u = uoz * z;
+ float v = voz * z;
- uint8_t p = m_texture_ram[((texbot - iv) * 2048) + texleft + iu];
+ int tx = tex_origin_x + (int)(u);
+ int ty = tex_origin_y + (int)(v);
- uint16_t texel = m_palette_ram[(palnum * 256) + BYTE_XOR_BE(p)];
- int r = ((texel >> 10) & 0x1f) << 3;
- int g = ((texel >> 5) & 0x1f) << 3;
- int b = (texel & 0x1f) << 3;
- fb[x] = 0xff000000 | (r << 16) | (g << 8) | b;
+#if BILINEAR
+ float intu, intv;
- u += du;
- v += dv;
+ int fracu = modff(u, &intu) * 255.0f;
+ int fracv = modff(v, &intv) * 255.0f;
+
+ uint32_t mask00 = m_texture_mask[((ty & 0x3fff) * 2048) + (tx & 0x7ff)];
+ uint32_t mask01 = m_texture_mask[((ty & 0x3fff) * 2048) + ((tx+1) & 0x7ff)];
+ uint32_t mask10 = m_texture_mask[(((ty+1) & 0x3fff) * 2048) + (tx & 0x7ff)];
+ uint32_t mask11 = m_texture_mask[(((ty+1) & 0x3fff) * 2048) + ((tx+1) & 0x7ff)];
+ const uint32_t mask_level = rgbaint_t::bilinear_filter(mask00, mask01, mask10, mask11, fracu, fracv);
+
+ if (mask_level < 0xff)
+ {
+ uint32_t tex00 = m_palette[palnum + BYTE_XOR_BE(m_texture_ram[((ty) & 0x3fff) * 2048 + ((tx) & 0x7ff)])];
+ uint32_t tex01 = m_palette[palnum + BYTE_XOR_BE(m_texture_ram[((ty) & 0x3fff) * 2048 + ((tx + 1) & 0x7ff)])];
+ uint32_t tex10 = m_palette[palnum + BYTE_XOR_BE(m_texture_ram[((ty + 1) & 0x3fff) * 2048 + ((tx) & 0x7ff)])];
+ uint32_t tex11 = m_palette[palnum + BYTE_XOR_BE(m_texture_ram[((ty + 1) & 0x3fff) * 2048 + ((tx + 1) & 0x7ff)])];
+
+ const uint32_t texsam = rgbaint_t::bilinear_filter(tex00, tex01, tex10, tex11, fracu, fracv);
+
+ rgbaint_t texel_color(texsam);
+ rgbaint_t fb_color(fb[x]);
+ texel_color.blend(fb_color, 255-mask_level);
+
+ fb[x] = texel_color.to_rgba_clamp();
+ if (UseZ)
+ zb[x] = zbufval;
+ }
+#else
+ uint8_t mask = m_texture_mask[((ty & 0x3fff) * 2048) + (tx & 0x7ff)];
+ if (mask == 0)
+ {
+ uint8_t pen = m_texture_ram[((ty & 0x3fff) * 2048) + (tx & 0x7ff)];
+ uint32_t texel = m_palette[palnum + BYTE_XOR_BE(pen)];
+ fb[x] = texel;
+ if (UseZ)
+ zb[x] = zbufval;
+ }
+#endif
+ }
+
+ uoz += uoz_dx;
+ voz += voz_dx;
+ ooz += ooz_dx;
}
}
void rollext_renderer::process_display_list(screen_device &screen, uint32_t* disp_ram)
{
- const rectangle& visarea = screen.visible_area();
-
- render_delegate rd = render_delegate(&rollext_renderer::render_texture_scan, this);
+ rectangle visarea = rectangle(0, 511, 0, 383);
int num = disp_ram[0xffffc/4];
for (int i=0; i < num; i++)
{
- int ii = i * 0x60;
-
- vertex_t vert[4];
+ int ii = i * 0x18;
- //int x[4];
- //int y[4];
+ vertex_t vert[5];
// Poly data:
- // Word 0: xxxxxxxx -------- -------- -------- Command? 0xFC for quads
- // -------- -------- xxxxxxxx -------- Palette?
- // -------- -------- -------- xxxxxxxx Number of verts? (4 for quads)
-
- // Word 1: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Vertex 1 X
-
+ // Word 0: x------- -------- -------- -------- ?
+ // -x------ -------- -------- -------- ? set to 1 for polygons, 0 on command 0x9c (viewport setup command?)
+ // --x----- -------- -------- -------- ? set to 1 for no perspective
+ // ---x---- -------- -------- -------- ? always 1?
+ // ----x--- -------- -------- -------- ? always 1?
+ // -----x-- -------- -------- -------- the PP transfer code checks for 1
+ // ------x- -------- -------- -------- always 0?
+ // -------x -------- -------- -------- Texture page
+ // -------- -------- -xxxxxxx -------- Palette
+ // -------- -------- -------- -----xxx Number of verts (3,4,5 used)
+ // Word 1: (float) Vertex 1 X
// Word 2: xxxxxxxx xxxxx--- -------- -------- Texture Origin Bottom
// -------- -----xxx xxxxxxxx -------- Texture Origin Left
+ // Word 3: (float) Vertex 1 Y
+ // Word 4: xxxxxxxx xxxxxxxx xxxxxxxx x------- Z buffer multiplier (int)
+ // Word 5: (float) Vertex 2 X
+ // Word 6: (float) U/Z per X pixel increment
+ // Word 7: (float) Vertex 2 Y
+ // Word 8: (float) U/Z per Y pixel increment
+ // Word 9: (float) Vertex 3 X
+ // Word 10: (float) 1/Z per X pixel increment
+ // Word 11: (float) Vertex 3 Y
+ // Word 12: (float) 1/Z per Y pixel increment
+ // Word 13: (float) Vertex 4 X (if quad)
+ // Word 14: (float) V/Z per X pixel increment
+ // Word 15: (float) Vertex 4 Y (if quad)
+ // Word 16: (float) V/Z per Y pixel increment
+ // Word 17: (float) Vertex 5 X (if 5 verts)
+ // Word 18: (float) Base U coordinate
+ // Word 19: (float) Vertex 5 Y (if 5 verts)
+ // Word 20: (float) Base Z coordinate
+ // Word 21: (float) Unused? PP code checks for 0 (validity check?)
+ // Word 22: (float) Base V coordinate
+ // Word 23: (float) ? Seems to be a copy of the last X coordinate
+
+ for (int j=0; j < 5; j++)
+ {
+ float fx = u2f(disp_ram[ii + (j * 4) + 1]);
+ float fy = u2f(disp_ram[ii + (j * 4) + 3]);
- // Word 3: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Vertex 1 Y
-
- // Word 4: -------- -------- xxxxxxxx xxxxxxxx ?
-
- // Word 5: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Vertex 2 X
-
- // Word 6: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Unknown float
-
- // Word 7: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Vertex 2 Y
-
- // Word 8: -------- -------- -------- -------- ?
-
- // Word 9: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Vertex 3 X
-
- // Word 10: -------- -------- -------- -------- ?
-
- // Word 11: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Vertex 3 Y
-
- // Word 12: -------- -------- -------- -------- ?
-
- // Word 13: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Vertex 4 X
-
- // Word 14: -------- -------- -------- -------- ?
-
- // Word 15: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Vertex 4 Y
-
- // Word 16: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Unknown float
-
- // Word 17: -------- -------- -------- -------- ?
-
- // Word 18: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Unknown float
-
- // Word 19: -------- -------- -------- -------- ?
-
- // Word 20: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Unknown float
-
- // Word 21: -------- -------- -------- -------- ?
-
- // Word 22: xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Unknown float
+ vert[j].x = (int)(fx + 256.0f);
+ vert[j].y = (int)(-fy + 192.0f);
+ }
- // Word 23: -------- -------- -------- -------- ?
+ rollext_polydata& extra = object_data().next();
- for (int j=0; j < 4; j++)
- {
- uint32_t ix = disp_ram[(ii + (j*0x10) + 0x4) / 4];
- uint32_t iy = disp_ram[(ii + (j*0x10) + 0xc) / 4];
+ extra.tex_origin_y = (disp_ram[ii + 2] >> 19) & 0x1fff;
+ extra.tex_origin_x = (disp_ram[ii + 2] >> 8) & 0x7ff;
+ extra.pal = (disp_ram[ii + 0] >> 8) & 0x7f;
- vert[j].x = (int)((u2f(ix) / 2.0f) + 256.0f);
- vert[j].y = (int)((u2f(iy) / 2.0f) + 192.0f);
- }
+ extra.tex_origin_y |= (disp_ram[ii + 0] & 0x01000000) ? 0x2000 : 0;
- vert[0].p[0] = 0.0f; vert[0].p[1] = 1.0f;
- vert[1].p[0] = 0.0f; vert[1].p[1] = 0.0f;
- vert[2].p[0] = 1.0f; vert[2].p[1] = 0.0f;
- vert[3].p[0] = 1.0f; vert[3].p[1] = 1.0f;
+ extra.uoz_dx = u2f(disp_ram[ii + 6]);
+ extra.uoz_dy = u2f(disp_ram[ii + 8]);
+ extra.voz_dx = u2f(disp_ram[ii + 14]);
+ extra.voz_dy = u2f(disp_ram[ii + 16]);
+ extra.ooz_dx = u2f(disp_ram[ii + 10]);
+ extra.ooz_dy = u2f(disp_ram[ii + 12]);
+ extra.baseu = u2f(disp_ram[ii + 18]);
+ extra.basev = u2f(disp_ram[ii + 22]);
+ extra.basez = u2f(disp_ram[ii + 20]);
- rollext_polydata &extra = object_data().next();
+ extra.zmul = (uint32_t)(disp_ram[ii + 4]) >> 7;
- extra.tex_bottom = (disp_ram[(ii + 8) / 4] >> 19) & 0x1fff;
- extra.tex_left = (disp_ram[(ii + 8) / 4] >> 8) & 0x7ff;
- extra.pal = (disp_ram[(ii + 0) / 4] >> 8) & 0x1f;
+ int num_verts = (disp_ram[ii + 0] & 0x7);
-#if 0
- printf("P%d\n", i);
- for (int j=0; j < 6; j++)
+ if (disp_ram[ii + 0] & 0x40000000)
{
- printf(" %08X %08X %08X %08X", disp_ram[(ii + (j*0x10) + 0) / 4], disp_ram[(ii + (j*0x10) + 4) / 4], disp_ram[(ii + (j*0x10) + 8) / 4], disp_ram[(ii + (j*0x10) + 12) / 4]);
- printf(" %f %f %f %f\n", u2f(disp_ram[(ii + (j*0x10) + 0) / 4]), u2f(disp_ram[(ii + (j*0x10) + 4) / 4]), u2f(disp_ram[(ii + (j*0x10) + 8) / 4]), u2f(disp_ram[(ii + (j*0x10) + 12) / 4]));
+ if (num_verts == 4)
+ render_polygon<4, 0>(visarea, render_delegate(&rollext_renderer::render_texture_scan<true>, this), vert);
+ else if (num_verts == 3)
+ render_triangle<0>(visarea, render_delegate(&rollext_renderer::render_texture_scan<true>, this), vert[0], vert[1], vert[2]);
+ else if (num_verts == 5)
+ render_polygon<5, 0>(visarea, render_delegate(&rollext_renderer::render_texture_scan<true>, this), vert);
}
-#endif
-
- render_triangle<4>(visarea, rd, vert[0], vert[1], vert[2]);
- render_triangle<4>(visarea, rd, vert[0], vert[2], vert[3]);
}
-
- wait();
}
void rollext_renderer::clear_fb()
{
- rectangle visarea;
- visarea.min_x = 0;
- visarea.max_x = 511;
- visarea.min_y = 0;
- visarea.max_y = 383;
+ rectangle visarea(0, 511, 0, 383);
+
+ m_zb->fill(0xffffffff, visarea);
+ m_fb[m_fb_current]->fill(0xff000000, visarea);
+}
+
+void rollext_renderer::palette_write(int index, uint16_t data)
+{
+ m_palette[index] = rgb_t(0xff, pal5bit(data >> 10), pal5bit(data >> 5), pal5bit(data));
+}
- m_fb->fill(0xff000000, visarea);
+void rollext_renderer::texture_mask_write(int index, uint8_t data)
+{
+ int x = index & 0xff;
+ int y = index >> 8;
+ // expand to bytes for easier access
+ for (auto j = 0; j < 8; j++)
+ {
+ m_texture_mask[(y * 2048) + (x * 8) + j] = (data & (1 << j)) ? 0xff : 0x00;
+ }
}
void rollext_renderer::display(bitmap_rgb32 *bitmap, const rectangle &cliprect)
{
- copybitmap_trans(*bitmap, *m_fb, 0, 0, 0, 0, cliprect, 0);
+ wait();
+ copybitmap_trans(*bitmap, *m_fb[m_fb_current], 0, 0, 0, 0, cliprect, 0);
}
@@ -283,10 +408,12 @@ public:
rollext_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
- m_palette_ram(*this, "palette_ram"),
- m_texture_mask(*this, "texture_mask"),
m_disp_ram(*this, "disp_ram"),
- m_screen(*this, "screen")
+ m_screen(*this, "screen"),
+ m_in(*this, "INPUTS%u", 1U),
+ m_analog(*this, "ANALOG%u", 1U),
+ m_eeprom_in(*this, "EEPROMIN"),
+ m_eeprom_out(*this, "EEPROMOUT")
{
}
@@ -296,20 +423,35 @@ public:
private:
required_device<tms32082_mp_device> m_maincpu;
- required_shared_ptr<uint32_t> m_palette_ram;
- required_shared_ptr<uint32_t> m_texture_mask;
required_shared_ptr<uint32_t> m_disp_ram;
required_device<screen_device> m_screen;
- uint32_t a0000000_r(offs_t offset);
- void a0000000_w(uint32_t data);
+ uint32_t a0000000_r(offs_t offset, uint32_t mem_mask = ~0);
+ void a0000000_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
uint32_t b0000000_r(offs_t offset);
+ void palette_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ void texture_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
void cmd_callback(address_space &space, uint32_t data);
+ uint32_t fifo_ptr_r(offs_t offset, uint32_t mem_mask = ~0);
+ void fifo_ptr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
std::unique_ptr<uint8_t[]> m_texture;
std::unique_ptr<rollext_renderer> m_renderer;
+ uint32_t m_fifo_ptr;
+
+ uint8_t m_adc_reg;
+ uint8_t m_adc_input;
+ uint8_t m_adc_readbit;
+
+ required_ioport_array<3> m_in;
+ required_ioport_array<1> m_analog;
+ required_ioport m_eeprom_in;
+ required_ioport m_eeprom_out;
+
INTERRUPT_GEN_MEMBER(vblank_interrupt);
virtual void machine_start() override;
virtual void machine_reset() override;
@@ -347,72 +489,84 @@ void rollext_state::video_start()
m_renderer = std::make_unique<rollext_renderer>(*m_screen);
m_renderer->set_texture_ram(m_texture.get());
- m_renderer->set_palette_ram((uint16_t*)&m_palette_ram[0]);
}
uint32_t rollext_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
-#if 0
- uint16_t *pal = (uint16_t*)&m_palette_ram[0];
-
- int palnum = 31;
- // 24,25,31 for basic font
- // 29 = trees
-
- int ii=0;
- for (int j=0; j < 384; j++)
- {
- uint32_t *fb = &bitmap.pix(j);
- for (int i=0; i < 512; i++)
- {
- uint8_t p = m_texture[ii++];
-
- uint16_t rgb = pal[(palnum * 256) + BYTE_XOR_BE(p)];
- int r = ((rgb >> 10) & 0x1f) << 3;
- int g = ((rgb >> 5) & 0x1f) << 3;
- int b = (rgb & 0x1f) << 3;
-
- fb[i] = 0xff000000 | (r << 16) | (g << 8) | b;
- }
- ii += 1536;
- }
-#endif
-
m_renderer->display(&bitmap, cliprect);
-
- //m_renderer->clear_fb();
-
- //m_disp_ram[0xffffc/4] = 0;
-
-
return 0;
}
-uint32_t rollext_state::a0000000_r(offs_t offset)
+uint32_t rollext_state::a0000000_r(offs_t offset, uint32_t mem_mask)
{
switch (offset)
{
- case 0: // ??
+ case 0: // inputs
{
- uint32_t data = 0x20200;
+ uint32_t data = 0;
- //data |= ioport("INPUTS1")->read();
- //data |= 0xfff7fff7;
+ if (ACCESSING_BITS_16_23)
+ {
+ // -------- ---x---- -------- -------- ADC channel 0
+ // -------- --x----- -------- -------- ADC channel 1?
+ // -------- -x------ -------- -------- ADC channel 2?
+ // -------- x------- -------- -------- ADC channel 3?
+
+ data |= (m_adc_readbit & 1) ? 0x100000 : 0;
+
+ data |= m_in[0]->read() << 16;
+ }
+ if (ACCESSING_BITS_8_15)
+ {
+ data |= 0x200; // 0 causes inf loop
+ data |= m_eeprom_in->read() << 8;
+ }
+ if (ACCESSING_BITS_0_7)
+ {
+ data |= m_in[1]->read();
+ }
return data;
}
case 1:
- return 0xffffffff;
+ uint32_t data = 0;
+ data |= m_in[2]->read();
+ return data;
}
return 0xffffffff;
}
-void rollext_state::a0000000_w(uint32_t data)
+void rollext_state::a0000000_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- // FPGA interface?
+ if (offset == 0)
+ {
+ if (ACCESSING_BITS_8_15)
+ {
+ m_eeprom_out->write(data >> 8, 0xff);
+ }
+ }
+ else if (offset == 1)
+ {
+ if (ACCESSING_BITS_16_23)
+ {
+ uint8_t newdata = data >> 16;
+ if ((newdata & 0x20) == 0 && (m_adc_reg & 0x20) != 0)
+ {
+ m_adc_input = m_analog[0]->read();
+ }
+
+ if (newdata & 0x10)
+ {
+ m_adc_readbit = (m_adc_input >> 7) & 1;
+ m_adc_input <<= 1;
+ }
+
+ m_adc_reg = newdata;
+ }
+ }
}
uint32_t rollext_state::b0000000_r(offs_t offset)
@@ -425,7 +579,7 @@ uint32_t rollext_state::b0000000_r(offs_t offset)
return 0;
}
- return 0;
+ return 0xffffffff;
}
void rollext_state::cmd_callback(address_space &space, uint32_t data)
@@ -440,64 +594,11 @@ void rollext_state::cmd_callback(address_space &space, uint32_t data)
// simulate PP behavior for now...
space.write_dword(0x00000084, 3);
- uint32_t num = space.read_dword(0x90);
-
- int consume_num = num;
- if (consume_num > 32)
- consume_num = 32;
-
- printf("PP num %d\n", num);
- printf("0x00000084 = %08X\n", space.read_dword(0x84));
-
-
- uint32_t ra = 0x1000280;
-
- /*
- printf("FIFO push:\n");
-
- for (int i=0; i < consume_num; i++)
- {
- printf("Entry %d:\n", i);
- for (int k=0; k < 6; k++)
- {
- for (int l=0; l < 4; l++)
- {
- uint32_t dd = m_program->read_dword(ra);
- ra += 4;
-
- printf("%08X(%f) ", dd, u2f(dd));
- }
- printf("\n");
- }
- printf("\n");
- }
- */
-
- ra = 0x1000280;
-
- int oldnum = space.read_dword(0x600ffffc);
- uint32_t rb = 0x60000000 + (oldnum * 0x60);
-
- for (int i=0; i < consume_num; i++)
- {
- for (int k=0; k < 24; k++)
- {
- uint32_t dd = space.read_dword(ra);
- ra += 4;
-
- space.write_dword(rb, dd);
- rb += 4;
- }
- }
- space.write_dword(0x600ffffc, oldnum+consume_num);
+ m_renderer->m_fb_current ^= 1;
+ m_renderer->clear_fb();
m_renderer->process_display_list(*m_screen, m_disp_ram);
-
- space.write_dword(0x600ffffc, 0);
-
- space.write_dword(0x00000090, 0);
- space.write_dword(0x00000094, 0);
-
+ m_maincpu->space().write_dword(0x600ffffc, 0);
}
}
// PP1
@@ -511,14 +612,48 @@ void rollext_state::cmd_callback(address_space &space, uint32_t data)
}
}
+void rollext_state::palette_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ if (ACCESSING_BITS_16_31)
+ {
+ m_renderer->palette_write((offset * 2) + 1, data >> 16);
+ }
+ if (ACCESSING_BITS_0_15)
+ {
+ m_renderer->palette_write(offset * 2, data & 0xffff);
+ }
+}
+
+void rollext_state::texture_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ if (ACCESSING_BITS_24_31)
+ {
+ m_renderer->texture_mask_write((offset * 4) + 1, data >> 24);
+ }
+ if (ACCESSING_BITS_16_23)
+ {
+ m_renderer->texture_mask_write((offset * 4) + 0, data >> 16);
+ }
+ if (ACCESSING_BITS_8_15)
+ {
+ m_renderer->texture_mask_write((offset * 4) + 3, data >> 8);
+ }
+ if (ACCESSING_BITS_0_7)
+ {
+ m_renderer->texture_mask_write((offset * 4) + 2, data & 0xff);
+ }
+}
+
+
+
// Master Processor memory map
void rollext_state::memmap(address_map &map)
{
map(0x40000000, 0x40ffffff).ram().share("main_ram");
map(0x60000000, 0x600fffff).ram().share("disp_ram");
- map(0x80000000, 0x8000ffff).ram().share("palette_ram");
- map(0x90000000, 0x9007ffff).ram().share("texture_mask");
+ map(0x80000000, 0x8000ffff).w(FUNC(rollext_state::palette_w));
+ map(0x90000000, 0x9007ffff).w(FUNC(rollext_state::texture_mask_w));
map(0xa0000000, 0xa00000ff).rw(FUNC(rollext_state::a0000000_r), FUNC(rollext_state::a0000000_w));
map(0xb0000000, 0xb0000007).r(FUNC(rollext_state::b0000000_r));
map(0xc0000000, 0xc03fffff).rom().region("rom1", 0);
@@ -527,20 +662,87 @@ void rollext_state::memmap(address_map &map)
static INPUT_PORTS_START(rollext)
-
PORT_START("INPUTS1")
- PORT_BIT( 0xfff7fff7, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_SERVICE_NO_TOGGLE( 0x00080008, IP_ACTIVE_LOW) /* Test Button */
-
+ PORT_SERVICE_NO_TOGGLE(0x8, IP_ACTIVE_LOW) // test button
+ PORT_BIT(0x4, IP_ACTIVE_LOW, IPT_VOLUME_DOWN)
+ PORT_BIT(0x2, IP_ACTIVE_LOW, IPT_SERVICE1)
+ PORT_BIT(0x1, IP_ACTIVE_LOW, IPT_VOLUME_UP)
+
+ PORT_START("INPUTS2")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_START)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("View Change")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("Right Brake")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("Left Brake")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Left Smash")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("Right Smash")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("INPUTS3")
+ PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_COIN1)
+
+ PORT_START("EEPROMIN")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, do_read)
+
+ PORT_START("EEPROMOUT")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_OUTPUT) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, clk_write)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OUTPUT) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, cs_write)
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OUTPUT) PORT_WRITE_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, di_write)
+
+ PORT_START("ANALOG1")
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(35) PORT_KEYDELTA(5) PORT_NAME("Seat Tilt")
INPUT_PORTS_END
+uint32_t rollext_state::fifo_ptr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_fifo_ptr;
+}
+
+void rollext_state::fifo_ptr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ m_fifo_ptr = data;
+ if (m_fifo_ptr > 0)
+ {
+ // simulate PP behavior for now...
+ uint32_t num = m_fifo_ptr;
+
+ int consume_num = num;
+ if (consume_num > 32)
+ consume_num = 32;
+
+ uint32_t ra = 0x1000280;
+
+ int oldnum = m_maincpu->space().read_dword(0x600ffffc);
+ uint32_t rb = 0x60000000 + (oldnum * 0x60);
+
+ for (int i = 0; i < consume_num; i++)
+ {
+ for (int k = 0; k < 24; k++)
+ {
+ uint32_t dd = m_maincpu->space().read_dword(ra);
+ ra += 4;
+
+ m_maincpu->space().write_dword(rb, dd);
+ rb += 4;
+ }
+ }
+ m_maincpu->space().write_dword(0x600ffffc, oldnum + consume_num);
+ m_maincpu->space().write_dword(0x00000090, 0);
+ }
+}
+
+
+
void rollext_state::machine_reset()
{
}
void rollext_state::machine_start()
{
+ // hook to fifo pointer for simulating PP0
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x90, 0x93, read32s_delegate(*this, FUNC(rollext_state::fifo_ptr_r)), write32s_delegate(*this, FUNC(rollext_state::fifo_ptr_w)));
}
@@ -548,8 +750,7 @@ void rollext_state::rollext(machine_config &config)
{
TMS32082_MP(config, m_maincpu, 60000000);
m_maincpu->set_addrmap(AS_PROGRAM, &rollext_state::memmap);
- //m_maincpu->set_vblank_int("screen", FUNC(rollext_state::vblank_interrupt));
- m_maincpu->set_periodic_int(FUNC(rollext_state::irq1_line_assert), attotime::from_hz(60));
+ m_maincpu->set_vblank_int("screen", FUNC(rollext_state::vblank_interrupt));
//m_maincpu->set_periodic_int(FUNC(rollext_state::irq3_line_assert), attotime::from_hz(500));
tms32082_pp_device &pp0(TMS32082_PP(config, "pp0", 60000000));
@@ -557,6 +758,8 @@ void rollext_state::rollext(machine_config &config)
config.set_maximum_quantum(attotime::from_hz(100));
+ EEPROM_93C66_16BIT(config, "eeprom");
+
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0));
diff --git a/src/mame/drivers/saturn.cpp b/src/mame/drivers/saturn.cpp
index 94a6309610c..3e1b93d9c51 100644
--- a/src/mame/drivers/saturn.cpp
+++ b/src/mame/drivers/saturn.cpp
@@ -463,26 +463,50 @@ public:
void saturnjp(machine_config &config);
void saturneu(machine_config &config);
void saturnus(machine_config &config);
+ void saturnkr(machine_config &config);
- void init_saturnus();
- void init_saturneu();
- void init_saturnjp();
+ template <bool is_pal> void init_saturn();
DECLARE_INPUT_CHANGED_MEMBER(tray_open);
DECLARE_INPUT_CHANGED_MEMBER(tray_close);
private:
-
DECLARE_MACHINE_START(saturn);
DECLARE_MACHINE_RESET(saturn);
+ // SMPC region codes, hardwired via jumper setting.
+ // - Given the scheme bit 3 should determine if the region is PAL or NTSC.
+ // - 0 and F are "prohibited", others are "Sega reserved".
+ // - Documentation states that 2 is "TAIWAN" and 6 is "KOREA",
+ // but games on latter definitely wants 2 rather than 6.
+ // We currently swap, former actual slot needs to be confirmed.
+ enum {
+ REGION_NTSC_0 = 0,
+ REGION_NTSC_JAPAN,
+// REGION_NTSC_TAIWAN,
+ REGION_NTSC_KOREA,
+ REGION_NTSC_3,
+ REGION_NTSC_USA, // & Canada, Mexico
+ REGION_NTSC_BRAZIL,
+// REGION_NTSC_KOREA,
+ REGION_NTSC_TAIWAN, // & Philippines
+ REGION_NTSC_7,
+ REGION_PAL_8,
+ REGION_PAL_9,
+ REGION_PAL_ASIA, // China, Middle East, East Asia not covered above
+ REGION_PAL_B,
+ REGION_PAL_EUROPE, // Australia, South Africa
+ REGION_PAL_AMERICA, // Non-NTSC Central/South America
+ REGION_PAL_E,
+ REGION_PAL_F
+ };
+
uint8_t saturn_cart_type_r();
uint32_t abus_dummy_r(offs_t offset);
uint32_t saturn_null_ram_r();
void saturn_null_ram_w(uint32_t data);
- void saturn_init_driver(int rgn);
uint8_t saturn_pdr1_direct_r();
uint8_t saturn_pdr2_direct_r();
void saturn_pdr1_direct_w(uint8_t data);
@@ -548,7 +572,7 @@ void sat_console_state::saturn_mem(address_map &map)
map(0x05f80000, 0x05fbffff).rw(FUNC(sat_console_state::saturn_vdp2_regs_r), FUNC(sat_console_state::saturn_vdp2_regs_w));
map(0x05fe0000, 0x05fe00cf).m(m_scu, FUNC(sega_scu_device::regs_map)); //rw(FUNC(sat_console_state::saturn_scu_r), FUNC(sat_console_state::saturn_scu_w));
map(0x06000000, 0x060fffff).ram().mirror(0x21f00000).share("workram_h");
- map(0x45000000, 0x46ffffff).nopw();
+ map(0x40000000, 0x46ffffff).nopw(); // associative purge page
map(0x60000000, 0x600003ff).nopw(); // cache address array
map(0xc0000000, 0xc0000fff).ram(); // cache data array, Dragon Ball Z sprites relies on this
}
@@ -884,7 +908,7 @@ void sat_console_state::saturnus(machine_config &config)
SATURN_CART_SLOT(config, "exp", saturn_cart, nullptr);
SOFTWARE_LIST(config, "cart_list").set_original("sat_cart");
- m_smpc_hle->set_region_code(4);
+ m_smpc_hle->set_region_code(REGION_NTSC_USA);
}
void sat_console_state::saturneu(machine_config &config)
@@ -897,7 +921,7 @@ void sat_console_state::saturneu(machine_config &config)
SATURN_CART_SLOT(config, "exp", saturn_cart, nullptr);
SOFTWARE_LIST(config, "cart_list").set_original("sat_cart");
- m_smpc_hle->set_region_code(12);
+ m_smpc_hle->set_region_code(REGION_PAL_EUROPE);
}
void sat_console_state::saturnjp(machine_config &config)
@@ -910,13 +934,27 @@ void sat_console_state::saturnjp(machine_config &config)
SATURN_CART_SLOT(config, "exp", saturn_cart, nullptr);
SOFTWARE_LIST(config, "cart_list").set_original("sat_cart");
- m_smpc_hle->set_region_code(1);
+ m_smpc_hle->set_region_code(REGION_NTSC_JAPAN);
+}
+
+void sat_console_state::saturnkr(machine_config &config)
+{
+ saturn(config);
+ SATURN_CDB(config, "saturn_cdb", 16000000);
+
+ SOFTWARE_LIST(config, "cd_list").set_original("saturn").set_filter("NTSC-K");
+
+ SATURN_CART_SLOT(config, "exp", saturn_cart, nullptr);
+ SOFTWARE_LIST(config, "cart_list").set_original("sat_cart");
+
+ m_smpc_hle->set_region_code(REGION_NTSC_KOREA);
}
-void sat_console_state::saturn_init_driver(int rgn)
+template <bool is_pal> void sat_console_state::init_saturn()
{
- m_vdp2.pal = (rgn == 12) ? 1 : 0;
+ // TODO: setter for (missing) VDP2 device
+ m_vdp2.pal = is_pal;
// set compatible options
m_maincpu->sh2drc_set_options(SH2DRC_STRICT_VERIFY|SH2DRC_STRICT_PCREL);
@@ -939,25 +977,8 @@ void sat_console_state::saturn_init_driver(int rgn)
m_backupram = make_unique_clear<uint8_t[]>(0x8000);
}
-void sat_console_state::init_saturnus()
-{
- saturn_init_driver(4);
-}
-
-void sat_console_state::init_saturneu()
-{
- saturn_init_driver(12);
-}
-
-void sat_console_state::init_saturnjp()
-{
- saturn_init_driver(1);
-}
-
-
-/* Japanese Saturn */
-ROM_START(saturnjp)
- ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF ) /* SH2 code */
+ROM_START( saturnjp )
+ ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF )
ROM_SYSTEM_BIOS(0, "101", "Japan v1.01 (941228)")
ROMX_LOAD("sega_101.bin", 0x00000000, 0x00080000, CRC(224b752c) SHA1(df94c5b4d47eb3cc404d88b33a8fda237eaf4720), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "1003", "Japan v1.003 (941012)")
@@ -966,9 +987,8 @@ ROM_START(saturnjp)
ROMX_LOAD("sega_100.bin", 0x00000000, 0x00080000, CRC(2aba43c2) SHA1(2b8cb4f87580683eb4d760e4ed210813d667f0a2), ROM_BIOS(2))
ROM_END
-/* Overseas Saturn */
-ROM_START(saturn)
- ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF ) /* SH2 code */
+ROM_START( saturn )
+ ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF )
ROM_SYSTEM_BIOS(0, "101a", "Overseas v1.01a (941115)")
/* Confirmed by ElBarto */
ROMX_LOAD("mpr-17933.bin", 0x00000000, 0x00080000, CRC(4afcf0fa) SHA1(faa8ea183a6d7bbe5d4e03bb1332519800d3fbc3), ROM_BIOS(0))
@@ -976,8 +996,8 @@ ROM_START(saturn)
ROMX_LOAD("sega_100a.bin", 0x00000000, 0x00080000, CRC(f90f0089) SHA1(3bb41feb82838ab9a35601ac666de5aacfd17a58), ROM_BIOS(1))
ROM_END
-ROM_START(saturneu)
- ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF ) /* SH2 code */
+ROM_START( saturneu )
+ ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF )
ROM_SYSTEM_BIOS(0, "101a", "Overseas v1.01a (941115)")
/* Confirmed by ElBarto */
ROMX_LOAD("mpr-17933.bin", 0x00000000, 0x00080000, CRC(4afcf0fa) SHA1(faa8ea183a6d7bbe5d4e03bb1332519800d3fbc3), ROM_BIOS(0))
@@ -985,13 +1005,20 @@ ROM_START(saturneu)
ROMX_LOAD("sega_100a.bin", 0x00000000, 0x00080000, CRC(f90f0089) SHA1(3bb41feb82838ab9a35601ac666de5aacfd17a58), ROM_BIOS(1))
ROM_END
-ROM_START(vsaturn)
- ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF ) /* SH2 code */
+ROM_START( saturnkr )
+ ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF )
+ // undumped, uses Japanese VA1 motherboard with v1.02a BIOS rev,
+ // with extra checks for region jumpers that disables Japanese language if setting matches '2' (no Korea option tho)
+ ROM_LOAD("sega_101.bin", 0x00000000, 0x00080000, BAD_DUMP CRC(224b752c) SHA1(df94c5b4d47eb3cc404d88b33a8fda237eaf4720) )
+ROM_END
+
+ROM_START( vsaturn )
+ ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF )
ROM_LOAD("vsaturn.bin", 0x00000000, 0x00080000, CRC(e4d61811) SHA1(4154e11959f3d5639b11d7902b3a393a99fb5776))
ROM_END
-ROM_START(hisaturn)
- ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF ) /* SH2 code */
+ROM_START( hisaturn )
+ ROM_REGION32_BE( 0x80000, "bios", ROMREGION_ERASEFF )
ROM_SYSTEM_BIOS(0, "102", "v1.02 (950519)")
ROMX_LOAD("mpr-18100.bin", 0x000000, 0x080000, CRC(3408dbf4) SHA1(8a22710e09ce75f39625894366cafe503ed1942d), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "101", "v1.01 (950130)")
@@ -999,8 +1026,9 @@ ROM_START(hisaturn)
ROM_END
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
-CONS( 1994, saturn, 0, 0, saturnus, saturn, sat_console_state, init_saturnus, "Sega", "Saturn (USA)", MACHINE_NOT_WORKING )
-CONS( 1994, saturnjp, saturn, 0, saturnjp, saturn, sat_console_state, init_saturnjp, "Sega", "Saturn (Japan)", MACHINE_NOT_WORKING )
-CONS( 1994, saturneu, saturn, 0, saturneu, saturn, sat_console_state, init_saturneu, "Sega", "Saturn (PAL)", MACHINE_NOT_WORKING )
-CONS( 1995, vsaturn, saturn, 0, saturnjp, saturn, sat_console_state, init_saturnjp, "JVC", "V-Saturn", MACHINE_NOT_WORKING )
-CONS( 1995, hisaturn, saturn, 0, saturnjp, saturn, sat_console_state, init_saturnjp, "Hitachi", "HiSaturn", MACHINE_NOT_WORKING )
+CONS( 1994, saturn, 0, 0, saturnus, saturn, sat_console_state, init_saturn<false>, "Sega", "Saturn (USA)", MACHINE_NOT_WORKING )
+CONS( 1994, saturnjp, saturn, 0, saturnjp, saturn, sat_console_state, init_saturn<false>, "Sega", "Saturn (Japan)", MACHINE_NOT_WORKING )
+CONS( 1994, saturneu, saturn, 0, saturneu, saturn, sat_console_state, init_saturn<true>, "Sega", "Saturn (PAL)", MACHINE_NOT_WORKING )
+CONS( 1995, saturnkr, saturn, 0, saturnkr, saturn, sat_console_state, init_saturn<false>, "Samsung", "Saturn (Korea)", MACHINE_NOT_WORKING )
+CONS( 1995, vsaturn, saturn, 0, saturnjp, saturn, sat_console_state, init_saturn<false>, "JVC", "V-Saturn", MACHINE_NOT_WORKING )
+CONS( 1995, hisaturn, saturn, 0, saturnjp, saturn, sat_console_state, init_saturn<false>, "Hitachi", "HiSaturn", MACHINE_NOT_WORKING )
diff --git a/src/mame/drivers/segac2.cpp b/src/mame/drivers/segac2.cpp
index 1be460ff039..112a4571dea 100644
--- a/src/mame/drivers/segac2.cpp
+++ b/src/mame/drivers/segac2.cpp
@@ -674,11 +674,11 @@ void pclub_state::print_club_camera_w(uint16_t data)
void segac2_state::segac_map(address_map &map)
{
map(0x000000, 0x1fffff).rom();
- map(0x800001, 0x800001).mirror(0x13fdfe).rw(FUNC(segac2_state::prot_r), FUNC(segac2_state::prot_w));
- map(0x800201, 0x800201).mirror(0x13fdfe).w(FUNC(segac2_state::control_w));
+ map(0x800000, 0x800001).mirror(0x13fdfe).rw(FUNC(segac2_state::prot_r), FUNC(segac2_state::prot_w)).umask16(0x00ff);
+ map(0x800200, 0x800201).mirror(0x13fdfe).w(FUNC(segac2_state::control_w)).umask16(0x00ff);
map(0x840000, 0x84001f).mirror(0x13fee0).rw("io", FUNC(sega_315_5296_device::read), FUNC(sega_315_5296_device::write)).umask16(0x00ff);
map(0x840100, 0x840107).mirror(0x13fef8).rw(m_ymsnd, FUNC(ym3438_device::read), FUNC(ym3438_device::write)).umask16(0x00ff);
- map(0x880101, 0x880101).mirror(0x13fefe).w(FUNC(segac2_state::counter_timer_w));
+ map(0x880100, 0x880101).mirror(0x13fefe).w(FUNC(segac2_state::counter_timer_w)).umask16(0x00ff);
map(0x8c0000, 0x8c0fff).mirror(0x13f000).rw(FUNC(segac2_state::palette_r), FUNC(segac2_state::palette_w)).share("paletteram");
map(0xc00000, 0xc0001f).mirror(0x18ff00).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w));
map(0xe00000, 0xe0ffff).mirror(0x1f0000).ram().share("nvram");
diff --git a/src/mame/drivers/spg2xx_jakks.cpp b/src/mame/drivers/spg2xx_jakks.cpp
index da3125d5e32..7deed4f8473 100644
--- a/src/mame/drivers/spg2xx_jakks.cpp
+++ b/src/mame/drivers/spg2xx_jakks.cpp
@@ -216,7 +216,7 @@ CONS( 2004, jak_mpacw,0, 0, jakks_mpac, jak_mpac, jakks_state, empty_init, "JA
// This was available in 2 different case styles, initially an underwater / jellyfish themed one, then later
// reissued in a 'SpongeBob head' style case reminiscent of the undumpable 2003 SpongeBob plug and play but
// with 2 buttons in the top left corner instead of 1
-//
+//
// The software on both versions of Jellyfish Dodge is believed to be the same, the build date can be seen in
// the 'hidden' test mode.
//
diff --git a/src/mame/drivers/tasc.cpp b/src/mame/drivers/tasc.cpp
index 13a0c1ec7c2..e795f1cd1f5 100644
--- a/src/mame/drivers/tasc.cpp
+++ b/src/mame/drivers/tasc.cpp
@@ -6,7 +6,7 @@ Tasc ChessSystem
Commonly known as Tasc R30, it's basically a dedicated ChessMachine.
The King chess engines are also compatible with Tasc's The ChessMachine software
-on PC, however the prototype Gideon 2.1(internally: Rebel 2.01) is not.
+on PC, however the prototype Gideon 3.1(internally: 2.1, Rebel 2.01) is not.
WARNING: Don't configure more than 512KB RAM for R30 The King 2.50, it will still
be playable but will actually use less than 512KB RAM and become weaker.
@@ -378,4 +378,4 @@ ROM_END
CONS( 1995, tascr30, 0, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.50)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_TIMING | MACHINE_CLICKABLE_ARTWORK )
CONS( 1993, tascr30a, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.20)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_TIMING | MACHINE_CLICKABLE_ARTWORK )
CONS( 1993, tascr30b, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (The King 2.23, TM version)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_TIMING | MACHINE_CLICKABLE_ARTWORK ) // competed in several chesscomputer tournaments
-CONS( 1993, tascr30g, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (Gideon 2.1, prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_TIMING | MACHINE_CLICKABLE_ARTWORK ) // made in 1993, later released in 2012
+CONS( 1993, tascr30g, tascr30, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30 (Gideon 3.1, prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_TIMING | MACHINE_CLICKABLE_ARTWORK ) // made in 1993, later released in 2012
diff --git a/src/mame/drivers/tx0.cpp b/src/mame/drivers/tx0.cpp
index fcbf223a12e..101992c4b9a 100644
--- a/src/mame/drivers/tx0.cpp
+++ b/src/mame/drivers/tx0.cpp
@@ -1612,6 +1612,31 @@ void tx0_state::tx0_64kw(machine_config &config)
SOFTWARE_LIST(config, "ptp_list").set_original("tx0_ptp").set_filter("64,OLDCODE");
}
+void tx0_state::tx0_8kwo(machine_config &config)
+{
+ tx0_64kw(config);
+
+ /* basic machine hardware */
+ /* TX0 CPU @ approx. 167 kHz (no master clock, but the memory cycle time is
+ approximately 6usec) */
+ TX0_8KW_OLD(config.replace(), m_maincpu, 166667);
+ m_maincpu->cpy().set(FUNC(tx0_state::tx0_io_cpy));
+ m_maincpu->r1l().set(FUNC(tx0_state::tx0_io_r1l));
+ m_maincpu->dis().set(FUNC(tx0_state::tx0_io_dis));
+ m_maincpu->r3l().set(FUNC(tx0_state::tx0_io_r3l));
+ m_maincpu->prt().set(FUNC(tx0_state::tx0_io_prt));
+ m_maincpu->rsv().set_nop();
+ m_maincpu->p6h().set(FUNC(tx0_state::tx0_io_p6h));
+ m_maincpu->p7h().set(FUNC(tx0_state::tx0_io_p7h));
+ m_maincpu->sel().set(FUNC(tx0_state::tx0_sel));
+ m_maincpu->res().set(FUNC(tx0_state::tx0_io_reset_callback));
+ m_maincpu->set_addrmap(AS_PROGRAM, &tx0_state::tx0_8kw_map);
+ /* dummy interrupt: handles input */
+ m_maincpu->set_vblank_int("screen", FUNC(tx0_state::tx0_interrupt));
+
+ SOFTWARE_LIST(config.replace(), "ptp_list").set_original("tx0_ptp").set_filter("8,OLDCODE");
+}
+
void tx0_state::tx0_8kw(machine_config &config)
{
tx0_64kw(config);
@@ -1642,6 +1667,11 @@ ROM_START(tx0_64kw)
/* space filled with our font */
ROM_END
+ROM_START(tx0_8kwo)
+ ROM_REGION(tx0_fontdata_size, "gfx1", ROMREGION_ERASEFF)
+ /* space filled with our font */
+ROM_END
+
ROM_START(tx0_8kw)
ROM_REGION(tx0_fontdata_size, "gfx1", ROMREGION_ERASEFF)
/* space filled with our font */
@@ -1653,6 +1683,7 @@ ROM_END
***************************************************************************/
-// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
-COMP( 1956, tx0_64kw, 0, 0, tx0_64kw, tx0, tx0_state, init_tx0, "MIT", "TX-0 original demonstrator (64 kWords of RAM)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)
-COMP( 1962, tx0_8kw, tx0_64kw, 0, tx0_8kw, tx0, tx0_state, init_tx0, "MIT", "TX-0 upgraded system (8 kWords of RAM)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)
+// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
+COMP( 1956, tx0_64kw, tx0_8kw, 0, tx0_64kw, tx0, tx0_state, init_tx0, "MIT", "TX-0 original demonstrator (64 kWords of RAM)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)
+COMP( 1959, tx0_8kwo, tx0_8kw, 0, tx0_8kwo, tx0, tx0_state, init_tx0, "MIT", "TX-0 upgraded system (8 kWords of RAM, old order code)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)
+COMP( 1962, tx0_8kw, 0, 0, tx0_8kw, tx0, tx0_state, init_tx0, "MIT", "TX-0 upgraded system (8 kWords of RAM, new order code)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)
diff --git a/src/mame/includes/pc8001.h b/src/mame/includes/pc8001.h
index 12002ed8dcd..d2c4ed50e8f 100644
--- a/src/mame/includes/pc8001.h
+++ b/src/mame/includes/pc8001.h
@@ -1,11 +1,11 @@
// license:BSD-3-Clause
-// copyright-holders:Curt Coder
+// copyright-holders:Curt Coder, Angelo Salese
+
#pragma once
#ifndef MAME_INCLUDES_PC8001_H
#define MAME_INCLUDES_PC8001_H
-
#include "cpu/z80/z80.h"
#include "imagedev/cassette.h"
#include "machine/buffer.h"
@@ -15,86 +15,151 @@
#include "machine/i8251.h"
#include "machine/ram.h"
#include "machine/upd1990a.h"
+#include "machine/pc80s31k.h"
#include "sound/beep.h"
#include "video/upd3301.h"
+#include "emupal.h"
+#include "screen.h"
#define Z80_TAG "z80"
+#define N80SR_ROM_TAG "n80sr_rom"
#define I8251_TAG "i8251"
-#define I8255A_TAG "i8255"
#define I8257_TAG "i8257"
#define UPD1990A_TAG "upd1990a"
#define UPD3301_TAG "upd3301"
+#define CGROM_TAG "cgrom"
#define CENTRONICS_TAG "centronics"
-#define SCREEN_TAG "screen"
-class pc8001_state : public driver_device
+class pc8001_base_state : public driver_device
{
public:
- pc8001_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag),
- m_maincpu(*this, Z80_TAG),
- m_rtc(*this, UPD1990A_TAG),
- m_dma(*this, I8257_TAG),
- m_crtc(*this, UPD3301_TAG),
- m_cassette(*this, "cassette"),
- m_centronics(*this, CENTRONICS_TAG),
- m_cent_data_out(*this, "cent_data_out"),
- m_beep(*this, "beeper"),
- m_ram(*this, RAM_TAG),
- m_rom(*this, Z80_TAG),
- m_char_rom(*this, UPD3301_TAG)
- { }
+ pc8001_base_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag)
+ , m_maincpu(*this, Z80_TAG)
+ , m_crtc(*this, UPD3301_TAG)
+ , m_crtc_palette(*this, "crtc_palette")
+ , m_dma(*this, I8257_TAG)
+ , m_cassette(*this, "cassette")
+ , m_cgrom(*this, CGROM_TAG)
+ {}
+protected:
required_device<cpu_device> m_maincpu;
- required_device<upd1990a_device> m_rtc;
- required_device<i8257_device> m_dma;
required_device<upd3301_device> m_crtc;
+ required_device<palette_device> m_crtc_palette;
+ required_device<i8257_device> m_dma;
required_device<cassette_image_device> m_cassette;
- required_device<centronics_device> m_centronics;
- required_device<output_latch_device> m_cent_data_out;
- required_device<beep_device> m_beep;
- required_device<ram_device> m_ram;
- required_memory_region m_rom;
- required_memory_region m_char_rom;
+ required_memory_region m_cgrom;
+ void port30_w(u8 data);
virtual void machine_start() override;
+ void set_screen_frequency(bool is_24KHz) { m_screen_is_24KHz = is_24KHz; };
- void port10_w(uint8_t data);
- void port30_w(uint8_t data);
- uint8_t port40_r();
- void port40_w(uint8_t data);
+ DECLARE_WRITE_LINE_MEMBER( crtc_reverse_w );
+ UPD3301_DRAW_CHARACTER_MEMBER( draw_text );
+ UPD3301_FETCH_ATTRIBUTE( attr_fetch );
DECLARE_WRITE_LINE_MEMBER( hrq_w );
uint8_t dma_mem_r(offs_t offset);
+private:
+ bool m_screen_reverse;
+ bool m_screen_is_24KHz;
+
/* video state */
int m_width80;
int m_color;
+};
+
+class pc8001_state : public pc8001_base_state
+{
+public:
+ pc8001_state(const machine_config &mconfig, device_type type, const char *tag)
+ : pc8001_base_state(mconfig, type, tag)
+ , m_pc80s31(*this, "pc80s31")
+ , m_rtc(*this, UPD1990A_TAG)
+ , m_screen(*this, "screen")
+ , m_centronics(*this, CENTRONICS_TAG)
+ , m_cent_data_out(*this, "cent_data_out")
+ , m_beep(*this, "beeper")
+ , m_ram(*this, RAM_TAG)
+ , m_rom(*this, Z80_TAG)
+ { }
+
+ void pc8001(machine_config &config);
+
+protected:
+ void pc8001_io(address_map &map);
+ void pc8001_map(address_map &map);
+
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ required_device<pc80s31_device> m_pc80s31;
+ required_device<upd1990a_device> m_rtc;
+ required_device<screen_device> m_screen;
+ required_device<centronics_device> m_centronics;
+ required_device<output_latch_device> m_cent_data_out;
+ required_device<beep_device> m_beep;
+ required_device<ram_device> m_ram;
+ required_memory_region m_rom;
+
+private:
+ void port10_w(uint8_t data);
+ uint8_t port40_r();
+ void port40_w(uint8_t data);
int m_centronics_busy;
int m_centronics_ack;
DECLARE_WRITE_LINE_MEMBER(write_centronics_busy);
DECLARE_WRITE_LINE_MEMBER(write_centronics_ack);
- UPD3301_DRAW_CHARACTER_MEMBER( pc8001_display_pixels );
- void pc8001(machine_config &config);
- void pc8001_io(address_map &map);
- void pc8001_mem(address_map &map);
};
class pc8001mk2_state : public pc8001_state
{
public:
pc8001mk2_state(const machine_config &mconfig, device_type type, const char *tag)
- : pc8001_state(mconfig, type, tag),
- m_kanji_rom(*this, "kanji")
+ : pc8001_state(mconfig, type, tag)
+ , m_kanji_rom(*this, "kanji")
+ , m_dsw(*this, "DSW%d", 1U)
{ }
- required_memory_region m_kanji_rom;
-
- void port31_w(uint8_t data);
void pc8001mk2(machine_config &config);
+
+protected:
void pc8001mk2_io(address_map &map);
- void pc8001mk2_mem(address_map &map);
+ void pc8001mk2_map(address_map &map);
+
+ required_memory_region m_kanji_rom;
+ required_ioport_array<2> m_dsw;
+private:
+ void port31_w(uint8_t data);
+};
+
+class pc8001mk2sr_state : public pc8001mk2_state
+{
+public:
+ pc8001mk2sr_state(const machine_config &mconfig, device_type type, const char *tag)
+ : pc8001mk2_state(mconfig, type, tag)
+ , m_n80sr_rom(*this, N80SR_ROM_TAG)
+ { }
+
+ void pc8001mk2sr(machine_config &config);
+
+private:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+ void pc8001mk2sr_io(address_map &map);
+
+ required_memory_region m_n80sr_rom;
+
+ void port33_w(u8 data);
+ u8 port71_r();
+ void port71_w(u8 data);
+
+ u8 m_n80sr_bank;
};
#endif
diff --git a/src/mame/includes/pc8801.h b/src/mame/includes/pc8801.h
index 5365f1d6094..5b76aeb2945 100644
--- a/src/mame/includes/pc8801.h
+++ b/src/mame/includes/pc8801.h
@@ -5,12 +5,12 @@
PC-8801 (c) 1981 NEC
********************************************************************************************/
+
#ifndef MAME_INCLUDES_PC8801_H
#define MAME_INCLUDES_PC8801_H
#pragma once
-
#include "cpu/z80/z80.h"
#include "bus/centronics/ctronics.h"
#include "imagedev/cassette.h"
@@ -20,7 +20,7 @@
#include "machine/i8255.h"
#include "machine/timer.h"
#include "machine/upd1990a.h"
-#include "machine/upd765.h"
+#include "machine/pc80s31k.h"
#include "sound/beep.h"
#include "sound/ymopn.h"
#include "emupal.h"
@@ -41,9 +41,7 @@ public:
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_screen(*this, "screen")
- , m_fdccpu(*this, "fdccpu")
- , m_fdc(*this, "upd765")
- , m_fdd(*this, "upd765:%u", 0U)
+ , m_pc80s31(*this, "pc80s31")
, m_pic(*this, I8214_TAG)
, m_rtc(*this, UPD1990A_TAG)
, m_cassette(*this, "cassette")
@@ -53,16 +51,28 @@ public:
, m_palette(*this, "palette")
{ }
- void pc8801mc(machine_config &config);
- void pc8801fh(machine_config &config);
void pc8801(machine_config &config);
+ void pc8801mk2mr(machine_config &config);
+ void pc8801fh(machine_config &config);
void pc8801ma(machine_config &config);
+ void pc8801mc(machine_config &config);
protected:
virtual void video_start() override;
virtual void machine_start() override;
virtual void machine_reset() override;
+ required_device<cpu_device> m_maincpu;
+ required_device<screen_device> m_screen;
+ required_device<pc80s31_device> m_pc80s31;
+ optional_device<i8214_device> m_pic;
+ required_device<upd1990a_device> m_rtc;
+ required_device<cassette_image_device> m_cassette;
+ required_device<beep_device> m_beeper;
+ required_device<ym2608_device> m_opna;
+ required_device<ym2203_device> m_opn;
+ required_device<palette_device> m_palette;
+
private:
struct crtc_t
{
@@ -78,19 +88,6 @@ private:
attotime time;
};
- required_device<cpu_device> m_maincpu;
- required_device<screen_device> m_screen;
- required_device<cpu_device> m_fdccpu;
- required_device<upd765a_device> m_fdc;
- required_device_array<floppy_connector, 2> m_fdd;
- optional_device<i8214_device> m_pic;
- required_device<upd1990a_device> m_rtc;
- required_device<cassette_image_device> m_cassette;
- required_device<beep_device> m_beeper;
- required_device<ym2608_device> m_opna;
- required_device<ym2203_device> m_opn;
- required_device<palette_device> m_palette;
-
std::unique_ptr<uint8_t[]> m_work_ram;
std::unique_ptr<uint8_t[]> m_hi_work_ram;
std::unique_ptr<uint8_t[]> m_ext_work_ram;
diff --git a/src/mame/includes/tx0.h b/src/mame/includes/tx0.h
index 37eb320b803..76b12820c7d 100644
--- a/src/mame/includes/tx0.h
+++ b/src/mame/includes/tx0.h
@@ -145,6 +145,7 @@ public:
{ }
void tx0_64kw(machine_config &config);
+ void tx0_8kwo(machine_config &config);
void tx0_8kw(machine_config &config);
void init_tx0();
diff --git a/src/mame/layout/ace_sp_dmd.lay b/src/mame/layout/ace_sp_dmd.lay
index e00e8abeabd..d3876c787e2 100644
--- a/src/mame/layout/ace_sp_dmd.lay
+++ b/src/mame/layout/ace_sp_dmd.lay
@@ -14,7 +14,7 @@ license:CC0
<color state="0" red="0.125" green="0.125" blue="0.125" />
</disk>
</element>
-
+
<group name="dmd">
<repeat count="24">
<param name="s" start="0" increment="64" />
diff --git a/src/mame/machine/ace_sp_reelctrl.cpp b/src/mame/machine/ace_sp_reelctrl.cpp
index b4fd316b235..dbec9211045 100644
--- a/src/mame/machine/ace_sp_reelctrl.cpp
+++ b/src/mame/machine/ace_sp_reelctrl.cpp
@@ -42,7 +42,7 @@ void ace_sp_reelctrl_base_device::device_add_mconfig(machine_config &config)
}
ROM_START( ace_sp_reelctrl )
- ROM_REGION16_BE( 0x0800, "mcu", 0 )
+ ROM_REGION16_BE( 0x0800, "mcu", 0 )
ROM_LOAD( "ace reel mcu v9 _space_.bin", 0, 0x0800, CRC(d7b91fe0) SHA1(44f78da8138caf4f79f1e8e9a2abe53d79c0fe79) ) // MC68705P3 internal ROM
ROM_END
@@ -52,7 +52,7 @@ const tiny_rom_entry *ace_sp_reelctrl_device::device_rom_region() const
}
ROM_START( ace_sp_reelctrl_pcp )
- ROM_REGION16_BE( 0x0800, "mcu", 0 )
+ ROM_REGION16_BE( 0x0800, "mcu", 0 )
ROM_LOAD( "pcp reel mcu fcr 1 _space_.bin", 0, 0x0800, CRC(1c8019bf) SHA1(d1d6ea68d9aace4a4ea0de212f17426bccfe5856) ) // MC68705P3 internal ROM
ROM_END
diff --git a/src/mame/machine/nes.cpp b/src/mame/machine/nes.cpp
index 29831ada9a8..2f4e29e5323 100644
--- a/src/mame/machine/nes.cpp
+++ b/src/mame/machine/nes.cpp
@@ -80,6 +80,7 @@ void nes_state::machine_start()
BMC_800IN1,
BMC_8157,
BMC_GOLD150,
+ BMC_TELETUBBIES,
BMC_VT5201,
BTL_PALTHENA,
CAMERICA_ALADDIN,
diff --git a/src/mame/machine/pc80s31k.cpp b/src/mame/machine/pc80s31k.cpp
new file mode 100644
index 00000000000..eb05acb8cfd
--- /dev/null
+++ b/src/mame/machine/pc80s31k.cpp
@@ -0,0 +1,460 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese, Olivier Galibert
+/**************************************************************************************************
+
+ NEC PC-80S31(K) Mini Disk Unit
+
+ Z80 + μPD765 + PPI that connects in cross with an host PPI
+
+ "Mini" as compared to the PC-8881 8-inch floppy I/F
+
+ Design is decidedly derived from Epson TF-20 and friends,
+ cfr. devices/bus/epson_sio/tf20.cpp
+
+ TODO:
+ - What's PC-80S32? Is it the 88VA version or a different beast?
+ - PC=0x7dd reads from FDC bit 3 in ST3 (twosid_r fn),
+ expecting a bit 3 high for all the PC8001 games otherwise keeps looping and eventually dies.
+ Are those incorrectly identified as 2DD? Hacked to work for now;
+ - set_input_line_vector fn doesn't work properly when issued from a device_reset,
+ we currently just implement the irq_callback instead;
+ - Bus option;
+ - Cascade mode, i.e. the CN2 connector used to accept a second disk unit for drive 2 & 3;
+ - pc80s31k: verify that irq vector write (I/O port $f0) belongs here or just
+ whatever PC88VA uses.
+ - printer interface (used for debugging? 4-bit serial?)
+ - Pinpoint what host I/O ports $f6, $f7 truly are
+ (direct FDC access from this device or a different beast? cfr. play6lim with pc8001mk2)
+ - filemst tries to access undocumented I/O port $09 at PC=5000:
+ \- If that's 0 then it tries to read a vector at [0x8000];
+ \- It then tries to read at memory [0xc0ff], set the value read in [0xf012];
+ \- Expects that ROM [0x0000] is not equal to 0xc3;
+ Bottom line: Is it trying to access some custom HW?
+
+===================================================================================================
+
+PCB (PC-80S31K)
+
+===================================================================================================
+
+ |--------------------------------------|
+ | P1 P2 P3 X1 |
+ | |
+ | CN2 |
+ | B6102C022 |
+ | FD1 FD2 (**) |
+ | | | |
+ | CN1 ------- D765AC D2364EC (*)|
+ | (*)|
+ | D8255AC-2 B6101C017 D780C-1 |
+ | |
+ |--------------------------------------|
+
+ PCB is marked PC-80S31KFDC NEC-14T
+ P1, P2, P3 are power supplies (+5V, +12V, -5V for P1, lacks -5V for the other two)
+ μPD2364EC is at position IC13, it's a 8192 size ROM. (***)
+ (*) are μPD41416C
+ (**) marked as JP, unpopulated x 3;
+ μPB6101/2 are bipolar TTL gate arrays, presumably
+ Cannot read marking of X1 (8 MHz?)
+
+ (***) Given this, we guess that PC80S31 is the 2D version while the 'K
+ variant is the 2D/2DD/2HD version.
+
+===================================================================================================
+
+Command Protocol
+
+===================================================================================================
+
+Command & parameters are normally communicated from Host via port B
+(read on port A on FDC side)
+An RPi implementation can be seen at https://github.com/MinatsuT/RPi_PC-80S31
+
+[0x00] Initialize
+[0x01] Write to disk
+ %1 number of sectors
+ %2 drive number
+ %3 track number
+ %4 sector number +1
+[0x02] Read from disk
+ %1 number of sectors
+ %2 drive number
+ %3 track number
+ %4 sector number +1
+[0x03] Send data to host
+[0x04] Copy data in-place
+ %1 number of sectors
+ %2 source drive
+ %3 source track
+ %4 source sector number +1
+ %5 destination drive
+ %6 destination track
+ %7 destination sector number +1
+[0x05] Format
+ %1 drive number
+[0x06] Send result status to Host
+ x--- ---- I/O complete
+ -x-- ---- has unread buffer
+ ---- ---x error occurred
+[0x07] Drive status
+[0x0b] Send memory data
+%1-%2 address start
+%3-%4 length
+[0x11] Fast write to disk
+ %1 number of sectors
+ %2 drive number
+ %3 track number
+ %4 sector number +1
+[0x12] Fast send data
+ (picks up number of sector etc. from previous issued commands?)
+[0x14] Device status
+ x--- ---- ESIG: error
+ -x-- ---- WPDR: write protected
+ --x- ---- RDY: ready
+ ---x ---- TRK0: track 0
+ ---- x--- DSDR: double sided drive
+ ---- -x-- HDDR: head
+ ---- --xx DS1, DS2: drive select
+ (same as 765 ST3?)
+[0x17] Mode change
+ %1 ---- xxxx mode select
+
+FDC normally puts ST0-1-2 to RAM buffers $7f0d-f, CHRN data in $7f10-13
+
+===================================================================================================
+
+Port C
+Used as a communication protocol flags
+
+===================================================================================================
+
+ Host side
+ (swap 4-bit nibbles and r/w direction for FDC side, all bits are active high):
+ x--- ---- (w) ATN AtenTioN:
+ host sends a command to FDC, interrupts current one
+ (looks unconnected the other way around?)
+ -x-- ---- (w) DAC DAta aCcepted:
+ host just picked up data from FDC
+ --x- ---- (w) RFD Ready For Data:
+ host requests data from FDC
+ ---x ---- (w) DAV DAta Valid:
+ host outputs data to port B
+ ---- -x-- (r) DAC DAta aCcepted:
+ FDC has accepted data from port B
+ ---- --x- (r) RFD Ready For Data:
+ FDC requests data from host
+ ---- ---x (r) DAV DAta Valid:
+ FDC has output data to port A
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "pc80s31k.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+
+// device type definition
+DEFINE_DEVICE_TYPE(PC80S31, pc80s31_device, "pc80s31", "NEC PC-80S31 Mini Disk Unit I/F")
+DEFINE_DEVICE_TYPE(PC80S31K, pc80s31k_device, "pc80s31k", "NEC PC-80S31K Mini Disk Unit I/F")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+
+//-------------------------------------------------
+// pc80s31_device - constructor
+//-------------------------------------------------
+
+
+pc80s31_device::pc80s31_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0U)
+ , m_fdc_cpu(*this, "fdc_cpu")
+ , m_fdc_rom(*this, "fdc_rom")
+ , m_ppi_host(*this, "ppi_host")
+ , m_ppi_fdc(*this, "ppi_fdc")
+ , m_latch(*this, "latch_%u", 0U)
+{
+}
+
+
+pc80s31_device::pc80s31_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc80s31_device(mconfig, PC80S31, tag, owner, clock)
+{
+
+}
+
+ROM_START( pc80s31 )
+ // TODO: exact identification of these
+ ROM_REGION( 0x2000, "fdc_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "disk", "disk BIOS" )
+ ROMX_LOAD( "disk.rom", 0x0000, 0x0800, CRC(2158d307) SHA1(bb7103a0818850a039c67ff666a31ce49a8d516f), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "mk2fr", "mkIIFR disk BIOS" )
+ ROMX_LOAD( "mk2fr_disk.rom", 0x0000, 0x0800, CRC(2163b304) SHA1(80da2dee49d4307f00895a129a5cfeff00cf5321), ROM_BIOS(1) )
+
+ ROM_FILL( 0x7df, 1, 0x00 )
+ ROM_FILL( 0x7e0, 1, 0x00 )
+ROM_END
+
+const tiny_rom_entry *pc80s31_device::device_rom_region() const
+{
+ return ROM_NAME( pc80s31 );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific machine
+// configuration addiitons
+//-------------------------------------------------
+
+void pc80s31_device::host_map(address_map &map)
+{
+ map(0, 3).rw(m_ppi_host, FUNC(i8255_device::read), FUNC(i8255_device::write));
+}
+
+void pc80s31_device::fdc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).rom().region("fdc_rom", 0);
+ map(0x4000, 0x7fff).ram();
+}
+
+void pc80s31_device::fdc_io(address_map &map)
+{
+ map.unmap_value_high();
+ map.global_mask(0xff);
+// map(0x09, 0x09).r accessed by filemst (pc8801), cfr. notes
+
+// map(0xf0, 0xf0).w(FUNC(pc8801_state::fdc_irq_vector_w)); // Interrupt Opcode Port
+// map(0xf4, 0xf4).w(FUNC(pc8801_state::fdc_drive_mode_w)); // Drive mode, 2d, 2dd, 2hd
+// map(0xf6, 0xf6).nopw(); // printer related
+ map(0xf7, 0xf7).nopw(); // printer port output
+ map(0xf8, 0xf8).rw(FUNC(pc80s31_device::terminal_count_r), FUNC(pc80s31_device::motor_control_w));
+ map(0xfa, 0xfb).m(m_fdc, FUNC(upd765a_device::map));
+ map(0xfc, 0xff).rw(m_ppi_fdc, FUNC(i8255_device::read), FUNC(i8255_device::write));
+}
+
+static void pc88_floppies(device_slot_interface &device)
+{
+ // TODO: definitely not correct for base device
+ device.option_add("525hd", FLOPPY_525_HD);
+}
+
+IRQ_CALLBACK_MEMBER(pc80s31_device::irq_cb)
+{
+ return m_irq_vector;
+}
+
+void pc80s31_device::device_add_mconfig(machine_config &config)
+{
+ constexpr XTAL fdc_xtal = XTAL(4'000'000);
+ Z80(config, m_fdc_cpu, fdc_xtal);
+ m_fdc_cpu->set_addrmap(AS_PROGRAM, &pc80s31_device::fdc_map);
+ m_fdc_cpu->set_addrmap(AS_IO, &pc80s31_device::fdc_io);
+ m_fdc_cpu->set_irq_acknowledge_callback(FUNC(pc80s31_device::irq_cb));
+
+ UPD765A(config, m_fdc, XTAL(4'000'000), true, true);
+ m_fdc->intrq_wr_callback().set_inputline(m_fdc_cpu, INPUT_LINE_IRQ0);
+
+ for (auto &floppy : m_floppy)
+ {
+ FLOPPY_CONNECTOR(config, floppy, pc88_floppies, "525hd", floppy_image_device::default_mfm_floppy_formats);
+ floppy->enable_sound(true);
+ }
+
+ for (auto &latch : m_latch)
+ GENERIC_LATCH_8(config, latch);
+
+ I8255A(config, m_ppi_host);
+ m_ppi_host->in_pa_callback().set(FUNC(pc80s31_device::latch_r<0>));
+ m_ppi_host->out_pa_callback().set(FUNC(pc80s31_device::latch_w<1>));
+ m_ppi_host->in_pb_callback().set(FUNC(pc80s31_device::latch_r<2>));
+ m_ppi_host->out_pb_callback().set(FUNC(pc80s31_device::latch_w<3>));
+ m_ppi_host->in_pc_callback().set(FUNC(pc80s31_device::latch_r<4>));
+ m_ppi_host->out_pc_callback().set(FUNC(pc80s31_device::latch_w<5>));
+
+ // 8255AC-2
+ I8255A(config, m_ppi_fdc);
+ m_ppi_fdc->in_pa_callback().set(FUNC(pc80s31_device::latch_r<3>));
+ m_ppi_fdc->out_pa_callback().set(FUNC(pc80s31_device::latch_w<2>));
+ m_ppi_fdc->in_pb_callback().set(FUNC(pc80s31_device::latch_r<1>));
+ m_ppi_fdc->out_pb_callback().set(FUNC(pc80s31_device::latch_w<0>));
+ m_ppi_fdc->in_pc_callback().set(FUNC(pc80s31_device::latch_r<5>));
+ m_ppi_fdc->out_pc_callback().set(FUNC(pc80s31_device::latch_w<4>));
+}
+
+//-------------------------------------------------
+// device_timer - device-specific timers
+//-------------------------------------------------
+
+void pc80s31_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ assert(id == 0);
+
+ m_fdc->tc_w(false);
+
+ // several games tries to scan invalid IDs from their structures, if this hits then
+ // it's possibly an attempt to scan a missing sector from the floppy structure.
+ // cfr. acrojet: the third read data command issued tries to access a CHRN of (0, 0, 16, 256)
+ // and checks at PC=500B if any of these status flags are satisfied:
+ // ST0 & 0xdf
+ // ST1 & 0xff
+ // ST2 & 0x73
+ // Data doesn't matter, it also seems to have some activity to the printer port
+ // (debugging left on?)
+ if ((u8)m_fdc_cpu->state_int(Z80_HALT) == 1)
+ {
+ logerror("%s: attempt to trigger TC while in HALT state (read ID copy protection warning)\n", machine().describe_context());
+// throw emu_fatalerror("copy protection hit");
+ }
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pc80s31_device::device_start()
+{
+ m_tc_zero_timer = timer_alloc(0);
+
+ save_item(NAME(m_irq_vector));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+
+void pc80s31_device::device_reset()
+{
+ m_floppy[0]->get_device()->set_rpm(300);
+ m_floppy[1]->get_device()->set_rpm(300);
+ m_fdc->set_rate(250000);
+
+ // TODO: doesn't seem to work for devices?
+ m_fdc_cpu->set_input_line_vector(0, 0);
+ m_irq_vector = 0;
+
+ m_tc_zero_timer->adjust(attotime::never);
+}
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+// Comms are simple dual port connected in cross fashion.
+// Even at "perfect" interleave tho we need to mailbox the connections.
+// - barbatus will hang at Artec logo the first time around (works if you soft reset);
+template <unsigned N> u8 pc80s31_device::latch_r()
+{
+ const int port_mask = N & 4 ? 0x0f : 0xff;
+// machine().scheduler().synchronize();
+ return m_latch[N]->read() & port_mask;
+}
+
+template <unsigned N> void pc80s31_device::latch_w(u8 data)
+{
+ const int lower_nibble = N & 4;
+// machine().scheduler().synchronize();
+ if (lower_nibble)
+ {
+ LOG("%s: %s port C write %02x (ATN=%d DAC=%d RFD=%d DAV=%d)\n"
+ , N & 1 ? "host" : "fdc"
+ , machine().describe_context()
+ , data
+ , BIT(data, 7)
+ , BIT(data, 6)
+ , BIT(data, 5)
+ , BIT(data, 4)
+ );
+ }
+ return m_latch[N]->write(data >> lower_nibble);
+}
+
+u8 pc80s31_device::terminal_count_r(address_space &space)
+{
+ if (!machine().side_effects_disabled())
+ {
+ m_fdc->tc_w(true);
+ // TODO: accurate time of this going off
+ m_tc_zero_timer->reset();
+ m_tc_zero_timer->adjust(attotime::from_usec(50));
+ }
+ // value is meaningless (never readback)
+ // TODO: verify this being 0xff or open bus
+ return space.unmap();
+}
+
+void pc80s31_device::motor_control_w(uint8_t data)
+{
+ // FIXME: on pc80s31k device (particularly on later releases) this stays always on
+ // babylon: just spins indefinitely at PC=6d8 (using the internal routines),
+ // waiting for DAV or ATN being on. Never hits the port until a flag is issued.
+ // prajator: on idle times it spins at PC=7060, waiting for ATN and keep issuing a 0xff here.
+ // valis2: calls PC=7009 subroutine for idle, waits for ATN on.
+ // It eventually writes a 0 here, not before an extremely long time
+ // (~10000 frames!)
+ m_floppy[0]->get_device()->mon_w(!(data & 1));
+ m_floppy[1]->get_device()->mon_w(!(data & 2));
+
+ // TODO: according to docs a value of 0x07 enables precompensation to tracks 0-19, 0xf enables it on 20-39
+}
+
+//**************************************************************************
+//
+// PC80S31K device overrides
+//
+//**************************************************************************
+
+pc80s31k_device::pc80s31k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc80s31_device(mconfig, PC80S31K, tag, owner, clock)
+{
+
+}
+
+ROM_START( pc80s31k )
+ // TODO: exact identification of these
+ ROM_REGION( 0x2000, "fdc_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "ma", "MA disk BIOS")
+ ROMX_LOAD( "ma_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "mk2mr", "mkIIMR disk BIOS" )
+ ROMX_LOAD( "m2mr_disk.rom", 0x0000, 0x2000, CRC(2447516b) SHA1(1492116f15c426f9796dc2bb6fcccf2656c0ca75), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 2, "mh", "MH disk BIOS" )
+ ROMX_LOAD( "mh_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004), ROM_BIOS(2) )
+ // TODO: this may belong to PC-80S32
+ ROM_SYSTEM_BIOS( 3, "88va", "PC88VA disk BIOS")
+ ROMX_LOAD( "vasubsys.rom", 0x0000, 0x2000, CRC(08962850) SHA1(a9375aa480f85e1422a0e1385acb0ea170c5c2e0), ROM_BIOS(3) )
+ROM_END
+
+const tiny_rom_entry *pc80s31k_device::device_rom_region() const
+{
+ return ROM_NAME( pc80s31k );
+}
+
+void pc80s31k_device::drive_mode_w(uint8_t data)
+{
+ // TODO: fix implementation
+ // anything that isn't a 2D doesn't really set proper parameters in here
+ logerror("FDC drive mode %02x\n", data);
+ m_floppy[0]->get_device()->set_rpm(BIT(data, 0) ? 360 : 300);
+ m_floppy[1]->get_device()->set_rpm(BIT(data, 1) ? 360 : 300);
+
+ m_fdc->set_rate(BIT(data, 5) ? 500000 : 250000);
+}
+
+void pc80s31k_device::fdc_io(address_map &map)
+{
+ pc80s31_device::fdc_io(map);
+
+ map(0xf0, 0xf0).lw8(NAME([this] (u8 data) { m_irq_vector = data; }));
+ map(0xf4, 0xf4).w(FUNC(pc80s31k_device::drive_mode_w));
+}
diff --git a/src/mame/machine/pc80s31k.h b/src/mame/machine/pc80s31k.h
new file mode 100644
index 00000000000..b21d2845daf
--- /dev/null
+++ b/src/mame/machine/pc80s31k.h
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/***************************************************************************
+
+NEC PC-80S31K
+
+***************************************************************************/
+
+#ifndef MAME_MACHINE_PC80S31K_H
+#define MAME_MACHINE_PC80S31K_H
+
+#pragma once
+
+#include "cpu/z80/z80.h"
+#include "imagedev/floppy.h"
+#include "machine/gen_latch.h"
+#include "machine/i8255.h"
+#include "machine/upd765.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class pc80s31_device : public device_t
+{
+public:
+ // construction/destruction
+ pc80s31_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void host_map(address_map &map);
+
+protected:
+ pc80s31_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ //virtual void device_validity_check(validity_checker &valid) const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+ virtual void fdc_io(address_map &map);
+
+ required_device<upd765a_device> m_fdc;
+ required_device_array<floppy_connector, 2> m_floppy;
+ u8 m_irq_vector;
+
+private:
+ required_device<z80_device> m_fdc_cpu;
+ required_memory_region m_fdc_rom;
+ required_device<i8255_device> m_ppi_host;
+ required_device<i8255_device> m_ppi_fdc;
+ required_device_array<generic_latch_8_device, 6> m_latch;
+
+ void fdc_map(address_map &map);
+
+ template <unsigned N> u8 latch_r();
+ template <unsigned N> void latch_w(u8 data);
+
+ u8 terminal_count_r(address_space &space);
+ void motor_control_w(u8 data);
+
+ emu_timer *m_tc_zero_timer;
+
+ IRQ_CALLBACK_MEMBER(irq_cb);
+};
+
+class pc80s31k_device : public pc80s31_device
+{
+public:
+ pc80s31k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void fdc_io(address_map &map) override;
+
+private:
+ void drive_mode_w(u8 data);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(PC80S31, pc80s31_device)
+DECLARE_DEVICE_TYPE(PC80S31K, pc80s31k_device)
+
+#endif // MAME_MACHINE_PC80S31K_H
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index a3ebb528f54..501fba57489 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -19380,6 +19380,7 @@ vsnetscreb // 1996.?? GX627 (Europe)
vsnetscrj // 1996.12 GX627 (Japan)
vsnetscru // 1996.?? GX627 (US)
winspike // 1997.?? GX705 (Europe)
+winspikea // 1997.?? GX705 (Asia)
winspikej // 1997.07 GX705 (Japan)
@source:konamim2.cpp
@@ -33855,8 +33856,9 @@ pc6001sr //
pc6601 //
@source:pc8001.cpp
-pc8001 //
-pc8001mk2 //
+pc8001 // 1979
+pc8001mk2 // 1983
+pc8001mk2sr // 1985
@source:pc8401a.cpp
pc8401a // roms needed
@@ -36970,6 +36972,7 @@ hisaturn // Hitachi HiSaturn
saturn // 1995 Sega Saturn (USA)
saturneu // 1995 Sega Saturn (Europe)
saturnjp // 1994 Sega Saturn (Japan)
+saturnkr // 1995 Samsung Saturn (Korea)
vsaturn // JVC V-Saturn
@source:sauro.cpp
@@ -41735,6 +41738,7 @@ twinsed2 // (c) 1994 Electronic Devices
@source:tx0.cpp
tx0_64kw // April 1956 MIT TX-0 (64kw RAM)
+tx0_8kwo // 1959 MIT TX-0 (8kw RAM)
tx0_8kw // 1962 MIT TX-0 (8kw RAM)
@source:tx1.cpp
diff --git a/src/mame/video/apple2.cpp b/src/mame/video/apple2.cpp
index 91babf1809a..683002f8bb9 100644
--- a/src/mame/video/apple2.cpp
+++ b/src/mame/video/apple2.cpp
@@ -786,6 +786,66 @@ void a2_video_device::text_update(screen_device &screen, bitmap_ind16 &bitmap, c
}
}
+void a2_video_device::text_update_inverse(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
+{
+ uint8_t const *const aux_page = m_aux_ptr ? m_aux_ptr : m_ram_ptr;
+
+ uint32_t const start_address = m_page2 ? 0x800 : 0x400;
+
+ beginrow = (std::max)(beginrow, cliprect.top() - (cliprect.top() % 8));
+ endrow = (std::min)(endrow, cliprect.bottom() - (cliprect.bottom() % 8) + 7);
+
+ const int startrow = (beginrow / 8) * 8;
+ const int stoprow = ((endrow / 8) + 1) * 8;
+ const int startcol = (cliprect.left() / 14);
+ const int stopcol = ((cliprect.right() / 14) + 1);
+
+ //printf("TXT: row %d startcol %d stopcol %d left %d right %d\n", beginrow, startcol, stopcol, cliprect.left(), cliprect.right());
+
+ int fg = 0;
+ int bg = 0;
+ switch (m_sysconfig & 0x03)
+ {
+ case 0: case 4: bg = WHITE; break;
+ case 1: bg = WHITE; break;
+ case 2: bg = GREEN; break;
+ case 3: bg = ORANGE; break;
+ }
+
+ for (int row = startrow; row < stoprow; row += 8)
+ {
+ if (m_80col)
+ {
+ for (int col = startcol; col < stopcol; col++)
+ {
+ /* calculate address */
+ uint32_t const address = start_address + ((((row/8) & 0x07) << 7) | (((row/8) & 0x18) * 5 + col));
+
+ plot_text_character(bitmap, col * 14, row, 1, aux_page[address],
+ fg, bg);
+ plot_text_character(bitmap, col * 14 + 7, row, 1, m_ram_ptr[address],
+ fg, bg);
+ }
+ }
+ else
+ {
+ for (int col = startcol; col < stopcol; col++)
+ {
+ /* calculate address */
+ uint32_t const address = start_address + ((((row/8) & 0x07) << 7) | (((row/8) & 0x18) * 5 + col));
+ if (((m_sysconfig & 7) == 4) && (m_dhires))
+ {
+ u8 tmp = aux_page[address];
+ fg = tmp>>4;
+ bg = tmp & 0xf;
+ }
+
+ plot_text_character(bitmap, col * 14, row, 2, m_ram_ptr[address], fg, bg);
+ }
+ }
+ }
+}
+
void a2_video_device::text_update_orig(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
{
int row, col;
diff --git a/src/mame/video/apple2.h b/src/mame/video/apple2.h
index f03fd6a596a..70af5a1d986 100644
--- a/src/mame/video/apple2.h
+++ b/src/mame/video/apple2.h
@@ -51,6 +51,7 @@ public:
DECLARE_WRITE_LINE_MEMBER(an2_w);
void text_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
+ void text_update_inverse(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
void text_update_ultr(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
void text_update_orig(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
void text_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow);
diff --git a/src/mame/video/kikikai.cpp b/src/mame/video/kikikai.cpp
index 9105d1f23b8..6e3f96011e7 100644
--- a/src/mame/video/kikikai.cpp
+++ b/src/mame/video/kikikai.cpp
@@ -18,74 +18,63 @@ void kikikai_state::main_bankswitch_w(uint8_t data)
uint32_t kikikai_state::screen_update_kicknrun(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
- int offs;
- int sx, sy, xc, yc;
- int gfx_num, gfx_attr, gfx_offs;
-
-
- /* Bubble Bobble doesn't have a real video RAM. All graphics (characters */
- /* and sprites) are stored in the same memory region, and information on */
- /* the background character columns is stored inthe area dd00-dd3f */
+ // Similar to bublbobl.cpp, Video hardware generates sprites only.
bitmap.fill(255, cliprect);
- sx = 0;
+ int sx = 0;
- /* the score display seems to be outside of the main objectram. */
- for (offs = 0x1500; offs < 0x2000; offs += 4)
+ // the score display seems to be outside of the main objectram
+ for (int offs = 0x1500; offs < 0x2000; offs += 4)
{
- int height;
-
if (offs >= 0x1800 && offs < 0x1980)
continue;
if (offs >= 0x19c0)
continue;
- /* skip empty sprites */
- /* this is dword aligned so the uint32_t * cast shouldn't give problems */
- /* on any architecture */
+ // skip empty sprites
+ // this is dword aligned so the uint32_t * cast shouldn't give problems on any architecture
if (*(uint32_t *)(&m_mainram[offs]) == 0)
continue;
- gfx_num = m_mainram[offs + 1];
- gfx_attr = m_mainram[offs + 3];
+ const int gfx_num = m_mainram[offs + 1];
+ const int gfx_attr = m_mainram[offs + 3];
- if (!BIT(gfx_num, 7)) /* 16x16 sprites */
+ int gfx_offs, height;
+ if (!BIT(gfx_num, 7)) // 16x16 sprites
{
gfx_offs = ((gfx_num & 0x1f) * 0x80) + ((gfx_num & 0x60) >> 1) + 12;
height = 2;
}
- else /* tilemaps (each sprite is a 16x256 column) */
+ else // tilemaps (each sprite is a 16x256 column)
{
gfx_offs = ((gfx_num & 0x3f) * 0x80);
height = 32;
}
- if ((gfx_num & 0xc0) == 0xc0) /* next column */
+ if ((gfx_num & 0xc0) == 0xc0) // next column
sx += 16;
else
{
sx = m_mainram[offs + 2];
//if (gfx_attr & 0x40) sx -= 256;
}
- sy = 256 - height * 8 - (m_mainram[offs + 0]);
+ const int sy = 256 - height * 8 - (m_mainram[offs + 0]);
- for (xc = 0; xc < 2; xc++)
+ for (int xc = 0; xc < 2; xc++)
{
- for (yc = 0; yc < height; yc++)
+ for (int yc = 0; yc < height; yc++)
{
- int goffs, code, color, flipx, flipy, x, y;
-
- goffs = gfx_offs + xc * 0x40 + yc * 0x02;
- code = m_mainram[goffs] + ((m_mainram[goffs + 1] & 0x07) << 8)
+ const int goffs = gfx_offs + xc * 0x40 + yc * 0x02;
+ const int code = m_mainram[goffs] + ((m_mainram[goffs + 1] & 0x07) << 8)
+ ((m_mainram[goffs + 1] & 0x80) << 4) + (m_charbank << 12);
- color = ((m_mainram[goffs + 1] & 0x38) >> 3) + ((gfx_attr & 0x02) << 2);
- flipx = m_mainram[goffs + 1] & 0x40;
- flipy = 0;
+ const int color = ((m_mainram[goffs + 1] & 0x38) >> 3) + ((gfx_attr & 0x02) << 2);
+ const int flipx = m_mainram[goffs + 1] & 0x40;
+ const int flipy = 0;
- //x = sx + xc * 8;
- x = (sx + xc * 8) & 0xff;
- y = (sy + yc * 8) & 0xff;
+ //const int x = sx + xc * 8;
+ const int x = (sx + xc * 8) & 0xff;
+ const int y = (sy + yc * 8) & 0xff;
m_gfxdecode->gfx(0)->transpen(bitmap,cliprect,
code,
diff --git a/src/mame/video/sknsspr.cpp b/src/mame/video/sknsspr.cpp
index 518e2a4bfb5..d474ff0d8da 100644
--- a/src/mame/video/sknsspr.cpp
+++ b/src/mame/video/sknsspr.cpp
@@ -156,7 +156,7 @@ void sknsspr_device::skns_sprite_kludge(int x, int y)
while(ys < sy && yd >= clip.min_y)
#define z_draw_pixel() \
- u8 val = src[(xs >> 16) & 0x3f]; \
+ u8 val = src[(xs >> 16) & 0x3f]; \
if(val) \
bitmap.pix(yd>>16, xd>>16) = val + colour;
diff --git a/src/osd/modules/debugger/debuggdbstub.cpp b/src/osd/modules/debugger/debuggdbstub.cpp
index 55f09087f35..9f26fb2c778 100644
--- a/src/osd/modules/debugger/debuggdbstub.cpp
+++ b/src/osd/modules/debugger/debuggdbstub.cpp
@@ -421,7 +421,7 @@ class debug_gdbstub : public osd_module, public debug_module
public:
debug_gdbstub()
: osd_module(OSD_DEBUG_PROVIDER, "gdbstub"), debug_module(),
- m_readbuf_state(PACKET_START),
+ m_readbuf_state(PACKET_START),
m_machine(nullptr),
m_maincpu(nullptr),
m_state(nullptr),
diff --git a/src/osd/modules/debugger/qt/debuggerview.cpp b/src/osd/modules/debugger/qt/debuggerview.cpp
index 263fcfe1e73..a1c8bcf2aec 100644
--- a/src/osd/modules/debugger/qt/debuggerview.cpp
+++ b/src/osd/modules/debugger/qt/debuggerview.cpp
@@ -331,8 +331,8 @@ void DebuggerView::copyVisibleSlot()
for (uint32_t col = 0; col < visarea.x; ++col)
text += wchar_t(viewdata[col].byte);
std::string::size_type const nonblank = text.find_last_not_of("\t\n\v\r ");
- if ((nonblank != std::string::npos) && (nonblank >= start))
- text.resize(nonblank + 1);
+ if (nonblank != std::string::npos)
+ text.resize((std::max)(start, nonblank + 1));
text += "\n";
}
diff --git a/src/osd/modules/debugger/win/debugviewinfo.cpp b/src/osd/modules/debugger/win/debugviewinfo.cpp
index d6e94c1ba3e..6965d032dfa 100644
--- a/src/osd/modules/debugger/win/debugviewinfo.cpp
+++ b/src/osd/modules/debugger/win/debugviewinfo.cpp
@@ -320,8 +320,8 @@ void debugview_info::handle_context_menu(unsigned command)
for (uint32_t col = 0; col < visarea.x; ++col)
text += wchar_t(viewdata[col].byte);
std::wstring::size_type const nonblank = text.find_last_not_of(L"\t\n\v\r ");
- if ((nonblank != std::wstring::npos) && (nonblank >= start))
- text.resize(nonblank + 1);
+ if (nonblank != std::wstring::npos)
+ text.resize((std::max)(start, nonblank + 1));
text += L"\r\n";
}
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index dca4793aeac..dd8457f1e41 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -596,6 +596,7 @@ static const dasm_table_entry dasm_table[] =
{ "tp0320", be, 0, []() -> util::disasm_interface * { return new tp0320_disassembler; } },
{ "tx0_64kw", be, -2, []() -> util::disasm_interface * { return new tx0_64kw_disassembler; } },
{ "tx0_8kw", be, -2, []() -> util::disasm_interface * { return new tx0_8kw_disassembler; } },
+ { "tx0_8kwo", be, -2, []() -> util::disasm_interface * { return new tx0_8kwo_disassembler; } },
{ "ucom4", le, 0, []() -> util::disasm_interface * { return new ucom4_disassembler; } },
{ "unsp10", be, -1, []() -> util::disasm_interface * { return new unsp_disassembler; } },
{ "unsp12", be, -1, []() -> util::disasm_interface * { return new unsp_12_disassembler; } },