mirror of
https://github.com/holub/mame
synced 2025-04-16 13:34:55 +03:00
Major state refactoring of pc98 based HW (#8475)
First major step in splitting up machine classes in NEC PC98 family tree: * Splits up derivative HWs into own state machine and files (pc98ha.cpp, pc9821.cpp and pc9801_epson.cpp); * Adds a preliminary uPD4991a parallel RTC, used by pc98ha; * Fix -26, -86, -118 C-bus sound board dips or jumper settings; * Fix default sound card for pc9821 (-86) and pc9821ce2 / pc9821cx3 (-118); * Adds preliminary MAD Factory Otomichan-kai C-bus sound board; * Adds boilerplate code for C-bus installing board I/Os, avoiding the possible inconvenience of board(s) getting silently unmapped by other installed boards; * Major refactoring of HW dip switches readouts, using required_ioports instead of scattering things around in PPI hooks; * Extensive QA rundown, including research on missing features and undumped machines. pc9801.cpp: Don't passthrough mouse irq frequency when cycle setting is setup too, fixes jastrike mouse input on options menu. pc9801.cpp: Fix kanji RAM window LR readback, makes telenetm to properly display 8x16 chars on RS and derivative machines. pc8801.cpp: fixed OPNA RAM readback, allowing SWs to playback ADPCMs properly. New machines marked as NOT_WORKING ---------------------------------- PC-98LT [anonymous] PC-98HA "Handy98" [anonymous] PC-9821Nr15 (98NOTE Lavie) [flyingharuka] PC-9821Nr166 (98NOTE Lavie) [flyingharuka] PC-9821Nw150 (98NOTE Lavie) [flyingharuka] PC-9821Ra266 (98MATE R) [flyingharuka] PC-9821Cx3 (98MULTi CanBe) [flyingharuka] PC-9801VX [qazmko1029] PC-9801US [CoolMod]
This commit is contained in:
parent
c471fad8e0
commit
0e4ba6d49a
@ -10988,7 +10988,9 @@ ExtractDisk [02]"MAPディスク " -> "duel kawanakajima_02.d88"
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<software name="emeraldd">
|
||||
<!-- Displays Glodia transition then logo keeps scrolling left -->
|
||||
<!-- Same as Vain Dream? -->
|
||||
<software name="emeraldd" supported="no">
|
||||
<description>Emerald Dragon</description>
|
||||
<year>1989</year>
|
||||
<publisher>バショウハウス (Bashou House)</publisher>
|
||||
@ -23448,7 +23450,10 @@ ExtractDisk [03]"USER_DISK " -> "maha-kala_03.d88"
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<software name="valis2">
|
||||
<!-- boot OK -->
|
||||
<!-- Omake: press F5 during opening for music test, alternatively just boot disk G from drive 1 -->
|
||||
<!-- TODO: checkout if there are other hidden hotkeys like PC98 version -->
|
||||
<software name="valis2" supported="yes">
|
||||
<description>Mugen Senshi Valis II</description>
|
||||
<year>1989</year>
|
||||
<publisher>日本テレネット (Nihon Telenet)</publisher>
|
||||
@ -23686,12 +23691,12 @@ ExtractDisk [03]"USER_DISK " -> "maha-kala_03.d88"
|
||||
</software>
|
||||
|
||||
<software name="navitune">
|
||||
<description>Navitune</description>
|
||||
<description>Navitune - Dragon Koukaiki</description>
|
||||
<year>1989</year>
|
||||
<publisher>工画堂スタジオ (Kogado Studio)</publisher>
|
||||
<!-- PC8801mk2SR -->
|
||||
<info name="release" value="198911xx"/>
|
||||
<info name="alt_title" value="ナビチューン"/>
|
||||
<info name="alt_title" value="ナビチューン ドラゴン航海記"/>
|
||||
<!--combined image-->
|
||||
<!--rom name="navitune.d88" size="1662512" crc="b9540b35" sha1="8d937c8acfb62a12d24596114e7168db1087eaf0"/-->
|
||||
|
||||
@ -36112,7 +36117,9 @@ ExtractDisk [03]"Ulysses_Disk1 " -> "ulysses_v80_03.d88" (same as ulyssesa)
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<software name="vaindrea">
|
||||
<!-- Displays Glodia transition then logo keeps scrolling left with wrong colors -->
|
||||
<!-- Known to be related to write protect flag on System disk that must be ON (PC=0xB0A4) -->
|
||||
<software name="vaindrea" supported="no">
|
||||
<description>Vain Dream</description>
|
||||
<year>1991</year>
|
||||
<publisher>グローディア (Global Media)</publisher>
|
||||
|
513
hash/pc98.xml
513
hash/pc98.xml
File diff suppressed because it is too large
Load Diff
@ -4366,6 +4366,8 @@ if (BUSES["CBUS"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/bus/cbus/pc9801_26.cpp",
|
||||
MAME_DIR .. "src/devices/bus/cbus/pc9801_26.h",
|
||||
MAME_DIR .. "src/devices/bus/cbus/pc9801_55.cpp",
|
||||
MAME_DIR .. "src/devices/bus/cbus/pc9801_55.h",
|
||||
MAME_DIR .. "src/devices/bus/cbus/pc9801_86.cpp",
|
||||
MAME_DIR .. "src/devices/bus/cbus/pc9801_86.h",
|
||||
MAME_DIR .. "src/devices/bus/cbus/pc9801_118.cpp",
|
||||
|
@ -3448,6 +3448,18 @@ if (MACHINES["UPD1990A"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/upd4991a.h,MACHINES["UPD4991A"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["UPD4991A"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/upd4991a.cpp",
|
||||
MAME_DIR .. "src/devices/machine/upd4991a.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/upd4992.h,MACHINES["UPD4992"] = true
|
||||
|
@ -676,6 +676,7 @@ MACHINES["TSB12LV01A"] = true
|
||||
--MACHINES["TTL7474"] = true
|
||||
--MACHINES["UCB1200"] = true
|
||||
MACHINES["UPD1990A"] = true
|
||||
--MACHINES["UPD4991A"] = true
|
||||
MACHINES["UPD4992"] = true
|
||||
MACHINES["UPD4701"] = true
|
||||
MACHINES["UPD7001"] = true
|
||||
|
@ -729,6 +729,7 @@ MACHINES["TTL7474"] = true
|
||||
MACHINES["TUBE"] = true
|
||||
MACHINES["UCB1200"] = true
|
||||
MACHINES["UPD1990A"] = true
|
||||
MACHINES["UPD4991A"] = true
|
||||
--MACHINES["UPD4992"] = true
|
||||
MACHINES["UPD4701"] = true
|
||||
MACHINES["UPD7001"] = true
|
||||
@ -3123,6 +3124,12 @@ files {
|
||||
MAME_DIR .. "src/mame/machine/pc9801_cd.h",
|
||||
MAME_DIR .. "src/mame/machine/pc9801_memsw.cpp",
|
||||
MAME_DIR .. "src/mame/machine/pc9801_memsw.h",
|
||||
MAME_DIR .. "src/mame/drivers/pc98ha.cpp",
|
||||
MAME_DIR .. "src/mame/includes/pc98ha.h",
|
||||
MAME_DIR .. "src/mame/drivers/pc9801_epson.cpp",
|
||||
MAME_DIR .. "src/mame/includes/pc9801_epson.h",
|
||||
MAME_DIR .. "src/mame/drivers/pc9821.cpp",
|
||||
MAME_DIR .. "src/mame/includes/pc9821.h",
|
||||
MAME_DIR .. "src/mame/drivers/tk80bs.cpp",
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ WRITE_LINE_MEMBER( mpu_pc98_device::mpu_irq_out )
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(MPU_PC98, mpu_pc98_device, "mpu_pc98", "Roland MPU-401 MIDI Interface (CBUS)")
|
||||
DEFINE_DEVICE_TYPE(MPU_PC98, mpu_pc98_device, "mpu_pc98", "Roland MPU-401 MIDI Interface (C-bus)")
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device configuration
|
||||
|
@ -1,16 +1,24 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/***************************************************************************
|
||||
/**************************************************************************************************
|
||||
|
||||
NEC PC-9801-118 sound card
|
||||
NEC PC-9801-118 sound card "CanBe Sound 2"
|
||||
|
||||
YMF297 + some extra ports
|
||||
YMF297 + some extra ports, apparently derived from -86.
|
||||
Introduced around the same time as Windows 95 release, it has various compatibility issues
|
||||
under DOS (especially when PnP is enabled).
|
||||
Doesn't have a sound ROM, it also cannot be installed with an environment also sporting a -86.
|
||||
|
||||
TODO:
|
||||
- preliminary, presumably needs CS-4232 too, it's an extended clone of the already emulated AD1848 used on the Windows Sound System
|
||||
- Fix sound chip type (YMF297-F);
|
||||
- Add CS-4232 support, it's an extended clone of the already emulated AD1848 used on the
|
||||
Windows Sound System;
|
||||
- Understand what the obfuscated NEC "ANCHOR" and "MAZE" chips really are;
|
||||
- PnP interface (missing BIOS);
|
||||
- verify sound irq;
|
||||
- test if driver can be installed under Windows 95;
|
||||
|
||||
***************************************************************************/
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "bus/cbus/pc9801_118.h"
|
||||
@ -27,11 +35,11 @@
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(PC9801_118, pc9801_118_device, "pc9801_118", "pc9801_118")
|
||||
DEFINE_DEVICE_TYPE(PC9801_118, pc9801_118_device, "pc9801_118", "NEC PC-9801-118")
|
||||
|
||||
WRITE_LINE_MEMBER(pc9801_118_device::sound_irq)
|
||||
{
|
||||
/* TODO: seems to die very often */
|
||||
// TODO: sometimes misfired irq causes sound or even host hang
|
||||
m_bus->int_w<5>(state);
|
||||
}
|
||||
|
||||
@ -41,9 +49,15 @@ WRITE_LINE_MEMBER(pc9801_118_device::sound_irq)
|
||||
|
||||
void pc9801_118_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
// TODO: "ANCHOR" & "MAZE" custom NEC chips
|
||||
// sourced by 5D clock
|
||||
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
YM2608(config, m_opn3, XTAL_5B * 2 / 5); // actually YMF297-F, unknown clock / divider, more likely uses 5D clock
|
||||
|
||||
// actually YMF297-F (YMF288 + OPL3 compatible FM sources), unknown clock / divider
|
||||
// 5B is near both CS-4232 and this
|
||||
YM2608(config, m_opn3, XTAL_5B * 2 / 5);
|
||||
m_opn3->irq_handler().set(FUNC(pc9801_118_device::sound_irq));
|
||||
m_opn3->port_a_read_callback().set(FUNC(pc9801_118_device::opn_porta_r));
|
||||
//m_opn3->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
|
||||
@ -61,10 +75,48 @@ void pc9801_118_device::device_add_mconfig(machine_config &config)
|
||||
static INPUT_PORTS_START( pc9801_118 )
|
||||
PORT_INCLUDE( pc9801_joy_port )
|
||||
|
||||
PORT_START("OPN3_DSW")
|
||||
PORT_CONFNAME( 0x01, 0x00, "PC-9801-118: Port Base" )
|
||||
PORT_CONFSETTING( 0x00, "0x088" )
|
||||
PORT_CONFSETTING( 0x01, "0x188" )
|
||||
// 12 line Jumper settings @ 8F
|
||||
// documented at https://sammargh.github.io/pc98/ext_card_doc/9801-118.txt
|
||||
// TODO: understand how SW can read these
|
||||
PORT_START("OPN3_JP_8F")
|
||||
PORT_CONFNAME( 0x001, 0x000, "PC-9801-118: Enable Plug and Play" ) // [1]
|
||||
PORT_CONFSETTING( 0x000, DEF_STR( No ) )
|
||||
PORT_CONFSETTING( 0x001, DEF_STR( Yes ) )
|
||||
// "group" is basically a obnoxious machine ID
|
||||
// details are in the aforementioned link, in a nutshell should be:
|
||||
// Group 1: later CanBe (Cb onward)
|
||||
// Group 2: early CanBe (Ce, Ce2, Cs2), 9821 MATE A
|
||||
// Group 4: several ValueStar models
|
||||
// Group 5: 9821 MATE B, Notebooks, 9801 BX, some H98 models
|
||||
// Group 3: anything not covered above (link also mentions BX4 here?)
|
||||
// In practice this should really be tested on field ...
|
||||
PORT_CONFNAME( 0x406, 0x000, "PC-9801-118: PCM Group select") // [2, 3, 11]
|
||||
PORT_CONFSETTING( 0x000, "Groups 2, 3, 4, 5" ) // uses -118 PCM
|
||||
PORT_CONFSETTING( 0x404, "Group 3" ) // uses PCM host
|
||||
PORT_CONFSETTING( 0x002, "Group 1" ) // ?
|
||||
// all other settings "prohibited"
|
||||
PORT_CONFNAME( 0x008, 0x008, "PC-9801-118: unknown [4]" ) // [4] "prohibited", always ON
|
||||
PORT_CONFSETTING( 0x000, DEF_STR( Off ) )
|
||||
PORT_CONFSETTING( 0x008, DEF_STR( On ) )
|
||||
PORT_CONFNAME( 0x030, 0x000, "PC-9801-118: FM Interrupt setting" ) // [5,6]
|
||||
PORT_CONFSETTING( 0x000, "INT5 (IRQ12)" )
|
||||
PORT_CONFSETTING( 0x010, "INT6 (IRQ13)" )
|
||||
PORT_CONFSETTING( 0x020, "INT41 (IRQ10)" )
|
||||
PORT_CONFSETTING( 0x030, "INT0 (IRQ3)")
|
||||
PORT_CONFNAME( 0x040, 0x000, "PC-9801-118: DMA channel" ) // [7]
|
||||
PORT_CONFSETTING( 0x000, "1" )
|
||||
PORT_CONFSETTING( 0x040, "2" )
|
||||
PORT_CONFNAME( 0x180, 0x000, "PC-9801-118: PCM Interrupt setting" ) // [8,9]
|
||||
PORT_CONFSETTING( 0x000, "INT5 (IRQ12)" )
|
||||
PORT_CONFSETTING( 0x080, "INT1 (IRQ5)" )
|
||||
PORT_CONFSETTING( 0x100, "INT41 (IRQ10)" )
|
||||
PORT_CONFSETTING( 0x180, "INT0 (IRQ3)" )
|
||||
PORT_CONFNAME( 0x200, 0x000, "PC-9801-118: enable MIDI Interrupt" ) // [10]
|
||||
PORT_CONFSETTING( 0x000, DEF_STR( No ) )
|
||||
PORT_CONFSETTING( 0x200, DEF_STR( Yes ) ) // auto for PnP, INT41 for non-PnP
|
||||
PORT_CONFNAME( 0x800, 0x000, "PC-9801-118: unknown [12]" ) // [12] "prohibited", always OFF
|
||||
PORT_CONFSETTING( 0x000, DEF_STR( Off ) )
|
||||
PORT_CONFSETTING( 0x800, DEF_STR( On ) )
|
||||
INPUT_PORTS_END
|
||||
|
||||
ioport_constructor pc9801_118_device::device_input_ports() const
|
||||
@ -72,8 +124,14 @@ ioport_constructor pc9801_118_device::device_input_ports() const
|
||||
return INPUT_PORTS_NAME( pc9801_118 );
|
||||
}
|
||||
|
||||
// RAM
|
||||
ROM_START( pc9801_118 )
|
||||
ROM_REGION( 0x20000, "pnp_bios", ROMREGION_ERASE00 )
|
||||
// NB: either socket is exclusively populated, earlier models populates 1E while later populates 2E.
|
||||
// Most likely contains same data or slight revision bump.
|
||||
// μPD27c1024 socket
|
||||
ROM_LOAD( "118 e316.1e", 0x00000, 0x20000, NO_DUMP )
|
||||
// LH531024N socket at .2e (unreadable label)
|
||||
|
||||
ROM_REGION( 0x100000, "opn3", ROMREGION_ERASE00 )
|
||||
ROM_END
|
||||
|
||||
@ -111,11 +169,24 @@ void pc9801_118_device::device_validity_check(validity_checker &valid) const
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
u16 pc9801_118_device::read_io_base()
|
||||
{
|
||||
// hardwired on this board
|
||||
return 0x0188;
|
||||
}
|
||||
|
||||
void pc9801_118_device::device_start()
|
||||
{
|
||||
m_io_base = read_io_base();
|
||||
m_bus->install_io(0xa460, 0xa463, read8sm_delegate(*this, FUNC(pc9801_118_device::id_r)), write8sm_delegate(*this, FUNC(pc9801_118_device::ext_w)));
|
||||
|
||||
m_bus->install_io(
|
||||
m_io_base,
|
||||
m_io_base + 7,
|
||||
read8sm_delegate(*this, FUNC(pc9801_118_device::opn3_r)),
|
||||
write8sm_delegate(*this, FUNC(pc9801_118_device::opn3_w))
|
||||
);
|
||||
|
||||
save_item(NAME(m_ext_reg));
|
||||
}
|
||||
|
||||
@ -126,10 +197,8 @@ void pc9801_118_device::device_start()
|
||||
|
||||
void pc9801_118_device::device_reset()
|
||||
{
|
||||
uint16_t port_base = (ioport("OPN3_DSW")->read() & 1) << 8;
|
||||
m_bus->io_space().unmap_readwrite(0x0088, 0x008b, 0x100);
|
||||
m_bus->install_io(port_base + 0x0088, port_base + 0x008f, read8sm_delegate(*this, FUNC(pc9801_118_device::opn3_r)), write8sm_delegate(*this, FUNC(pc9801_118_device::opn3_w)));
|
||||
m_ext_reg = 1; // TODO: enabled or disabled?
|
||||
// TODO: is this enabled or disabled at boot?
|
||||
m_ext_reg = 1;
|
||||
}
|
||||
|
||||
|
||||
@ -140,7 +209,7 @@ void pc9801_118_device::device_reset()
|
||||
|
||||
uint8_t pc9801_118_device::opn3_r(offs_t offset)
|
||||
{
|
||||
if(((offset & 5) == 0) || m_ext_reg)
|
||||
if(((offset & 5) == 0) || m_ext_reg )
|
||||
return m_opn3->read(offset >> 1);
|
||||
else // odd
|
||||
{
|
||||
@ -152,7 +221,7 @@ uint8_t pc9801_118_device::opn3_r(offs_t offset)
|
||||
|
||||
void pc9801_118_device::opn3_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if(((offset & 5) == 0) || m_ext_reg)
|
||||
if( ((offset & 5) == 0) || m_ext_reg )
|
||||
m_opn3->write(offset >> 1,data);
|
||||
//else // odd
|
||||
// printf("PC9801-118: Write to undefined port [%02x] %02x\n",offset+0x188,data);
|
||||
@ -162,11 +231,13 @@ uint8_t pc9801_118_device::id_r(offs_t offset)
|
||||
{
|
||||
if(offset == 0)
|
||||
{
|
||||
printf("OPN3 EXT read ID [%02x]\n",offset);
|
||||
logerror("OPN3 EXT read ID [%02x]\n",offset);
|
||||
// TODO: confirm ID
|
||||
// by assumption we make this same as later CanBe releases, may or may not be right
|
||||
return 0x80 | (m_ext_reg & 1);
|
||||
}
|
||||
|
||||
printf("OPN3 EXT read unk [%02x]\n",offset);
|
||||
logerror("OPN3 EXT read unk [%02x]\n", offset);
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
@ -175,11 +246,10 @@ void pc9801_118_device::ext_w(offs_t offset, uint8_t data)
|
||||
if(offset == 0)
|
||||
{
|
||||
m_ext_reg = data & 1;
|
||||
/* TODO: apparently writing a 1 doubles the available channels (and presumably enables CS-4231 too) */
|
||||
if(data)
|
||||
printf("PC-9801-118: extended register %02x write\n",data);
|
||||
if(data & 2)
|
||||
logerror("%s: extended register %02x write\n", machine().describe_context(), data);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("OPN3 EXT write unk %02x -> [%02x]\n",data,offset);
|
||||
logerror("%s: EXT write unk %02x -> [%02x]\n", machine().describe_context(), data, offset);
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ public:
|
||||
// construction/destruction
|
||||
pc9801_118_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
static constexpr feature_type imperfect_features() { return feature::SOUND; }
|
||||
|
||||
uint8_t opn3_r(offs_t offset);
|
||||
void opn3_w(offs_t offset, uint8_t data);
|
||||
uint8_t id_r(offs_t offset);
|
||||
@ -42,6 +44,7 @@ protected:
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
virtual u16 read_io_base() override;
|
||||
|
||||
private:
|
||||
required_device<pc9801_slot_device> m_bus;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/***************************************************************************
|
||||
/**************************************************************************************************
|
||||
|
||||
NEC PC-9801-26 sound card
|
||||
|
||||
@ -8,8 +8,10 @@
|
||||
|
||||
TODO:
|
||||
- verify sound irq;
|
||||
- understand if dips can be read by SW;
|
||||
- configurable irq level needs a binding flush in C-bus handling;
|
||||
|
||||
***************************************************************************/
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "bus/cbus/pc9801_26.h"
|
||||
@ -23,11 +25,11 @@
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(PC9801_26, pc9801_26_device, "pc9801_26", "pc9801_26")
|
||||
DEFINE_DEVICE_TYPE(PC9801_26, pc9801_26_device, "pc9801_26", "NEC PC-9801-26")
|
||||
|
||||
WRITE_LINE_MEMBER(pc9801_26_device::sound_irq)
|
||||
{
|
||||
/* TODO: seems to die very often */
|
||||
// TODO: sometimes misfired irq causes sound or even host hang
|
||||
m_bus->int_w<5>(state);
|
||||
}
|
||||
|
||||
@ -77,10 +79,27 @@ const tiny_rom_entry *pc9801_26_device::device_rom_region() const
|
||||
static INPUT_PORTS_START( pc9801_26 )
|
||||
PORT_INCLUDE( pc9801_joy_port )
|
||||
|
||||
PORT_START("OPN_DSW")
|
||||
// On-board jumpers
|
||||
// TODO: any way to actually read these from HW?
|
||||
PORT_START("OPN_JP6A1_JP6A3")
|
||||
PORT_CONFNAME( 0x03, 0x02, "PC-9801-26: Interrupt level")
|
||||
PORT_CONFSETTING( 0x00, "IRQ 0" ) // 2-3, 2-3
|
||||
PORT_CONFSETTING( 0x01, "IRQ 4" ) // 2-3, 1-2
|
||||
PORT_CONFSETTING( 0x02, "IRQ 5" ) // 1-2, 1-2
|
||||
PORT_CONFSETTING( 0x03, "IRQ 6" ) // 1-2, 2-3
|
||||
|
||||
PORT_START("OPN_JP6A2")
|
||||
PORT_CONFNAME( 0x07, 0x01, "PC-9801-26: Sound ROM address")
|
||||
PORT_CONFSETTING( 0x00, "0xc8000" ) // 1-10
|
||||
PORT_CONFSETTING( 0x01, "0xcc000" ) // 2-9
|
||||
PORT_CONFSETTING( 0x02, "0xd0000" ) // 3-8
|
||||
PORT_CONFSETTING( 0x03, "0xd4000" ) // 4-7
|
||||
PORT_CONFSETTING( 0x04, "Disable ROM") // 5-6
|
||||
|
||||
PORT_START("OPN_JP6A4")
|
||||
PORT_CONFNAME( 0x01, 0x01, "PC-9801-26: Port Base" )
|
||||
PORT_CONFSETTING( 0x00, "0x088" )
|
||||
PORT_CONFSETTING( 0x01, "0x188" )
|
||||
PORT_CONFSETTING( 0x00, "0x088" ) // 1-4
|
||||
PORT_CONFSETTING( 0x01, "0x188" ) // 2-3
|
||||
INPUT_PORTS_END
|
||||
|
||||
ioport_constructor pc9801_26_device::device_input_ports() const
|
||||
@ -97,9 +116,9 @@ ioport_constructor pc9801_26_device::device_input_ports() const
|
||||
//-------------------------------------------------
|
||||
|
||||
pc9801_26_device::pc9801_26_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pc9801_snd_device(mconfig, PC9801_26, tag, owner, clock),
|
||||
m_bus(*this, DEVICE_SELF_OWNER),
|
||||
m_opn(*this, "opn")
|
||||
: pc9801_snd_device(mconfig, PC9801_26, tag, owner, clock)
|
||||
, m_bus(*this, DEVICE_SELF_OWNER)
|
||||
, m_opn(*this, "opn")
|
||||
{
|
||||
}
|
||||
|
||||
@ -117,10 +136,15 @@ void pc9801_26_device::device_validity_check(validity_checker &valid) const
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
u16 pc9801_26_device::read_io_base()
|
||||
{
|
||||
return ((ioport("OPN_JP6A4")->read() & 1) << 8) + 0x0088;
|
||||
}
|
||||
|
||||
void pc9801_26_device::device_start()
|
||||
{
|
||||
m_bus->program_space().install_rom(0xcc000,0xcffff,memregion(this->subtag("sound_bios").c_str())->base());
|
||||
m_rom_base = 0;
|
||||
m_io_base = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -130,10 +154,48 @@ void pc9801_26_device::device_start()
|
||||
|
||||
void pc9801_26_device::device_reset()
|
||||
{
|
||||
uint16_t port_base = (ioport("OPN_DSW")->read() & 1) << 8;
|
||||
// install the ROM to the physical program space
|
||||
u8 rom_setting = ioport("OPN_JP6A2")->read() & 7;
|
||||
static const u32 rom_addresses[8] = { 0xc8000, 0xcc000, 0xd0000, 0xd4000, 0, 0, 0, 0 };
|
||||
u32 current_rom = rom_addresses[rom_setting & 7];
|
||||
memory_region *rom_region = memregion(this->subtag("sound_bios").c_str());
|
||||
const u32 rom_size = rom_region->bytes() - 1;
|
||||
|
||||
m_bus->io_space().unmap_readwrite(0x0088, 0x008b, 0x100);
|
||||
m_bus->install_io(port_base + 0x0088, port_base + 0x008b, read8sm_delegate(*this, FUNC(pc9801_26_device::opn_r)), write8sm_delegate(*this, FUNC(pc9801_26_device::opn_w)));
|
||||
if (m_rom_base == 0)
|
||||
m_rom_base = current_rom;
|
||||
|
||||
if (m_rom_base != 0)
|
||||
{
|
||||
logerror("%s: uninstall ROM at %08x-%08x\n", machine().describe_context(), m_rom_base, m_rom_base + rom_size);
|
||||
m_bus->program_space().unmap_readwrite(m_rom_base, m_rom_base + rom_size);
|
||||
}
|
||||
if (current_rom != 0)
|
||||
{
|
||||
logerror("%s: install ROM at %08x-%08x\n", machine().describe_context(), current_rom, current_rom + rom_size);
|
||||
m_bus->program_space().unmap_readwrite(current_rom, current_rom + rom_size);
|
||||
m_bus->program_space().install_rom(
|
||||
current_rom,
|
||||
current_rom + rom_size,
|
||||
rom_region->base()
|
||||
);
|
||||
}
|
||||
m_rom_base = current_rom;
|
||||
|
||||
// install I/O ports
|
||||
u16 current_io = read_io_base();
|
||||
m_bus->flush_install_io(
|
||||
this->tag(),
|
||||
m_io_base,
|
||||
current_io,
|
||||
3,
|
||||
read8sm_delegate(*this, FUNC(pc9801_26_device::opn_r)),
|
||||
write8sm_delegate(*this, FUNC(pc9801_26_device::opn_w))
|
||||
);
|
||||
m_io_base = current_io;
|
||||
|
||||
// install IRQ line
|
||||
// static const u8 irq_levels[4] = {0, 4, 5, 6};
|
||||
// m_irq_level = irq_levels[ioport("OPN_JP6A1_JP6A3")->read() & 3];
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// copyright-holders:Angelo Salese
|
||||
/***************************************************************************
|
||||
|
||||
Template for skeleton device
|
||||
NEC PC-9801-26 sound card
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -39,12 +39,14 @@ protected:
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
virtual u16 read_io_base() override;
|
||||
|
||||
private:
|
||||
required_device<pc9801_slot_device> m_bus;
|
||||
required_device<ym2203_device> m_opn;
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(sound_irq);
|
||||
u32 m_rom_base;
|
||||
};
|
||||
|
||||
|
||||
|
253
src/devices/bus/cbus/pc9801_55.cpp
Normal file
253
src/devices/bus/cbus/pc9801_55.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
NEC PC-9801-55/-55U/-55L
|
||||
|
||||
SCSI interface, running on WD33C93A
|
||||
|
||||
TODO:
|
||||
- Is PC-9801-55 also running on this except with WD33C93 instead?
|
||||
Will see once we obtain a dump of that;
|
||||
- DIP is never taken (definitely lies at vector 0x2c -> PC=0xdc01e);
|
||||
- DRQ
|
||||
- All roms seems to be misdumped (too generous sizes), is it intentional?
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "bus/cbus/pc9801_55.h"
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(PC9801_55U, pc9801_55u_device, "pc9801_55u", "NEC PC-9801-55U")
|
||||
DEFINE_DEVICE_TYPE(PC9801_55L, pc9801_55l_device, "pc9801_55l", "NEC PC-9801-55L")
|
||||
|
||||
ROM_START( pc9801_55u )
|
||||
ROM_REGION16_LE( 0x10000, "scsi_bios", ROMREGION_ERASEFF )
|
||||
// JNC2B_00.BIN BADADDR ---xxxxxxxxxxxx
|
||||
// JNC3B_00.BIN BADADDR ---xxxxxxxxxxxx
|
||||
ROM_LOAD16_BYTE( "jnc2b_00.bin", 0x000000, 0x008000, CRC(ddace1b7) SHA1(614569be28a90bd385cf8abc193e629e568125b7) )
|
||||
ROM_LOAD16_BYTE( "jnc3b_00.bin", 0x000001, 0x008000, CRC(b8a8a49e) SHA1(7781dab492df889148e070a7da7ead207e18ed04) )
|
||||
ROM_END
|
||||
|
||||
const tiny_rom_entry *pc9801_55u_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( pc9801_55u );
|
||||
}
|
||||
|
||||
ROM_START( pc9801_55l )
|
||||
ROM_REGION16_LE( 0x10000, "scsi_bios", ROMREGION_ERASEFF )
|
||||
// ETA1B_00.BIN BADADDR ---xxxxxxxxxxxx
|
||||
// ETA3B_00.BIN BADADDR ---xxxxxxxxxxxx
|
||||
ROM_LOAD16_BYTE( "eta1b_00.bin", 0x000000, 0x008000, CRC(300ff6c1) SHA1(6cdee535b77535fe6c4dda4427aeb803fcdea0b8) )
|
||||
ROM_LOAD16_BYTE( "eta3b_00.bin", 0x000001, 0x008000, CRC(44477512) SHA1(182bb45ba0da7a4f9113e268e04ffca8403cf164) )
|
||||
ROM_END
|
||||
|
||||
const tiny_rom_entry *pc9801_55l_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( pc9801_55l );
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device configuration
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER(pc9801_55_device::scsi_irq_w)
|
||||
{
|
||||
// TODO: should be INT3, but BIOS configures as INT0 somewhere (unhandled dip reading?)
|
||||
m_bus->int_w<0>(state);
|
||||
}
|
||||
|
||||
void pc9801_55_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
NSCSI_BUS(config, m_scsi_bus);
|
||||
// TODO: currently returning default_scsi_devices, checkout if true for PC-98
|
||||
NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "scsi:7").option_set("wdc", WD33C93A).machine_config(
|
||||
[this](device_t *device)
|
||||
{
|
||||
wd33c9x_base_device &adapter = downcast<wd33c9x_base_device &>(*device);
|
||||
|
||||
// TODO: unknown clock
|
||||
adapter.set_clock(10'000'000);
|
||||
adapter.irq_cb().set(*this, FUNC(pc9801_55_device::scsi_irq_w));
|
||||
// TODO: DRQ on C-bus
|
||||
//adapter.drq_cb().set(*this, FUNC(pc9801_55_device::scsi_drq));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START( pc9801_55 )
|
||||
PORT_START("SCSI_DSW1")
|
||||
PORT_DIPNAME( 0x07, 0x07, "PC-9801-55: SCSI board ID") PORT_DIPLOCATION("SCSI_SW1:!1,!2,!3")
|
||||
PORT_DIPSETTING( 0x00, "0" )
|
||||
PORT_DIPSETTING( 0x01, "1" )
|
||||
PORT_DIPSETTING( 0x02, "2" )
|
||||
PORT_DIPSETTING( 0x03, "3" )
|
||||
PORT_DIPSETTING( 0x04, "4" )
|
||||
PORT_DIPSETTING( 0x05, "5" )
|
||||
PORT_DIPSETTING( 0x06, "6" )
|
||||
PORT_DIPSETTING( 0x07, "7" )
|
||||
PORT_DIPNAME( 0x38, 0x18, "PC-9801-55: Interrupt level") PORT_DIPLOCATION("SCSI_SW1:!4,!5,!6")
|
||||
PORT_DIPSETTING( 0x00, "INT0" )
|
||||
PORT_DIPSETTING( 0x08, "INT1" )
|
||||
PORT_DIPSETTING( 0x10, "INT2" )
|
||||
PORT_DIPSETTING( 0x18, "INT3" )
|
||||
PORT_DIPSETTING( 0x20, "INT5" )
|
||||
PORT_DIPSETTING( 0x28, "INT6" )
|
||||
PORT_DIPSETTING( 0x30, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x38, DEF_STR( Unknown ) )
|
||||
PORT_DIPNAME( 0xc0, 0x00, "PC-9801-55: DMA channel") PORT_DIPLOCATION("SCSI_SW1:!7,!8")
|
||||
PORT_DIPSETTING( 0x00, "0" )
|
||||
PORT_DIPSETTING( 0x40, "1 (prohibited)" )
|
||||
PORT_DIPSETTING( 0x80, "2" )
|
||||
PORT_DIPSETTING( 0xc0, "3" )
|
||||
|
||||
PORT_START("SCSI_DSW2")
|
||||
// TODO: understand all valid possible settings of this
|
||||
PORT_DIPNAME( 0x7f, 0x66, "PC-9801-55: machine ID and ROM base address") PORT_DIPLOCATION("SCSI_SW2:!1,!2,!3,!4,!5,!6,!7")
|
||||
PORT_DIPSETTING( 0x66, "i386, 0xdc000-0xddfff")
|
||||
// ...
|
||||
PORT_DIPNAME( 0x80, 0x80, "PC-9801-55: ROM accessibility at Power-On") PORT_DIPLOCATION("SCSI_SW2:!8")
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( Yes ))
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( No ))
|
||||
|
||||
PORT_START("SCSI_JP")
|
||||
// SW3 and SW4 Jumper settings
|
||||
PORT_CONFNAME( 0x03, 0x00, "PC-9801-55: I/O base address")
|
||||
PORT_CONFSETTING( 0x00, "0xcc0") // 01-02 01 02
|
||||
PORT_CONFSETTING( 0x01, "0xcd0")
|
||||
PORT_CONFSETTING( 0x02, "0xce0")
|
||||
PORT_CONFSETTING( 0x03, "0xcf0")
|
||||
INPUT_PORTS_END
|
||||
|
||||
ioport_constructor pc9801_55_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( pc9801_55 );
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// pc9801_55u_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
pc9801_55_device::pc9801_55_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_bus(*this, DEVICE_SELF_OWNER)
|
||||
, m_scsi_bus(*this, "scsi")
|
||||
, m_wdc(*this, "scsi:7:wdc")
|
||||
{
|
||||
}
|
||||
|
||||
pc9801_55u_device::pc9801_55u_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pc9801_55_device(mconfig, PC9801_55U, tag, owner, clock)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
pc9801_55l_device::pc9801_55l_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pc9801_55_device(mconfig, PC9801_55L, tag, owner, clock)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_validity_check - perform validity checks
|
||||
// on this device
|
||||
//-------------------------------------------------
|
||||
|
||||
void pc9801_55_device::device_validity_check(validity_checker &valid) const
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void pc9801_55_device::device_start()
|
||||
{
|
||||
m_bus->program_space().install_rom(
|
||||
0xdc000,
|
||||
0xddfff,
|
||||
memregion(this->subtag("scsi_bios").c_str())->base()
|
||||
);
|
||||
|
||||
// TODO: docs hints that this has mirrors at 0xcd*, 0xce*, 0xcf*
|
||||
m_bus->install_io(
|
||||
0xcc0,
|
||||
0xcc5,
|
||||
read8sm_delegate(*this, FUNC(pc9801_55_device::comms_r)),
|
||||
write8sm_delegate(*this, FUNC(pc9801_55_device::comms_w))
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void pc9801_55_device::device_reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// READ/WRITE HANDLERS
|
||||
//**************************************************************************
|
||||
|
||||
u8 pc9801_55_device::comms_r(offs_t offset)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
{
|
||||
offs_t addr = offset >> 1;
|
||||
if (addr & 2)
|
||||
{
|
||||
logerror("%s: Read to status port [%02x]\n", machine().describe_context(), offset + 0xcc0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_wdc->indir_r(addr);
|
||||
}
|
||||
// odd
|
||||
|
||||
logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + 0xcc0);
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void pc9801_55_device::comms_w(offs_t offset, u8 data)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
{
|
||||
offs_t addr = offset >> 1;
|
||||
if (addr & 2)
|
||||
{
|
||||
logerror("%s: Write to command port [%02x] %02x\n", machine().describe_context(), offset + 0xcc0, data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_wdc->indir_w(addr, data);
|
||||
return;
|
||||
}
|
||||
|
||||
// odd
|
||||
logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + 0xcc0, data);
|
||||
}
|
80
src/devices/bus/cbus/pc9801_55.h
Normal file
80
src/devices/bus/cbus/pc9801_55.h
Normal file
@ -0,0 +1,80 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/***************************************************************************
|
||||
|
||||
NEC PC-9801-55/-55U/-55L
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_BUS_CBUS_PC9801_55_H
|
||||
#define MAME_BUS_CBUS_PC9801_55_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bus/cbus/pc9801_cbus.h"
|
||||
#include "bus/nscsi/devices.h"
|
||||
#include "machine/nscsi_bus.h"
|
||||
#include "machine/wd33c9x.h"
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> pc9801_118_device
|
||||
|
||||
class pc9801_55_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
//pc9801_55_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
pc9801_55_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
static constexpr feature_type unemulated_features() { return feature::DISK; }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(scsi_irq_w);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_validity_check(validity_checker &valid) const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
// optional information overrides
|
||||
// virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
|
||||
private:
|
||||
required_device<pc9801_slot_device> m_bus;
|
||||
required_device<nscsi_bus_device> m_scsi_bus;
|
||||
required_device<wd33c9x_base_device> m_wdc;
|
||||
|
||||
u8 comms_r(offs_t offset);
|
||||
void comms_w(offs_t offset, u8 data);
|
||||
};
|
||||
|
||||
class pc9801_55u_device : public pc9801_55_device
|
||||
{
|
||||
public:
|
||||
pc9801_55u_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
private:
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
|
||||
};
|
||||
|
||||
class pc9801_55l_device : public pc9801_55_device
|
||||
{
|
||||
public:
|
||||
pc9801_55l_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
private:
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
|
||||
};
|
||||
|
||||
// device type definition
|
||||
//DECLARE_DEVICE_TYPE(PC9801_55, pc9801_55_device)
|
||||
DECLARE_DEVICE_TYPE(PC9801_55U, pc9801_55u_device)
|
||||
DECLARE_DEVICE_TYPE(PC9801_55L, pc9801_55l_device)
|
||||
|
||||
#endif // MAME_BUS_CBUS_PC9801_55_H
|
@ -1,25 +1,35 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/***************************************************************************
|
||||
/**************************************************************************************************
|
||||
|
||||
NEC PC-9801-86 sound card
|
||||
NEC PC-9801-SpeakBoard sound card
|
||||
Mad Factory Otomi-chan Kai sound card
|
||||
|
||||
Similar to PC-9801-26, this one has YM2608 instead of YM2203 and an
|
||||
additional DAC port
|
||||
|
||||
SpeakBoard sound card seems to be derived design from -86, with an additional
|
||||
OPNA mapped at 0x58*
|
||||
|
||||
Otomi-chan Kai is a doujinshi sound card based off SpeakBoard design.
|
||||
It uses YM3438 OPL2C mapped at 0x78*, and anything that uses the nax.exe sound driver
|
||||
expects this to be installed as default (cfr. datsumj).
|
||||
To fallback to a regular -26/-86 board user needs to add parameter switches "-2" or "-3"
|
||||
respectively, cfr. "nax -?" for additional details.
|
||||
|
||||
TODO:
|
||||
- Test all pcm modes
|
||||
- Make volume work
|
||||
- Recording
|
||||
- Test all pcm modes;
|
||||
- Make volume work;
|
||||
- Recording;
|
||||
- SpeakBoard: no idea about software that uses this, also board shows a single YM2608B?
|
||||
"-86 only supports ADPCM instead of PCM, while SpeakBoard has OPNA + 256 Kbit RAM"
|
||||
Sounds like a sound core flaw since OPNA requires a rom region in any case;
|
||||
"-86 only supports ADPCM instead of PCM, while SpeakBoard has OPNA + 256 Kbit RAM";
|
||||
- Otomi-chan Kai: find a manual (マニュアル), it's mentioned with nax usage.
|
||||
Very low-res scan of the PCB sports a 4-bit dip-sw bank at very least;
|
||||
- Otomi-chan Kai: unknown ID port readback;
|
||||
- verify sound irq;
|
||||
|
||||
***************************************************************************/
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "bus/cbus/pc9801_86.h"
|
||||
@ -32,15 +42,22 @@
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(PC9801_86, pc9801_86_device, "pc9801_86", "pc9801_86")
|
||||
DEFINE_DEVICE_TYPE(PC9801_86, pc9801_86_device, "pc9801_86", "NEC PC-9801-86")
|
||||
|
||||
WRITE_LINE_MEMBER(pc9801_86_device::sound_irq)
|
||||
{
|
||||
m_fmirq = state ? true : false;
|
||||
/* TODO: seems to die very often */
|
||||
// TODO: sometimes misfired irq causes sound or even host hang
|
||||
m_bus->int_w<5>(state || (m_pcmirq ? ASSERT_LINE : CLEAR_LINE));
|
||||
}
|
||||
|
||||
// only for derived designs?
|
||||
void pc9801_86_device::opna_map(address_map &map)
|
||||
{
|
||||
// TODO: confirm it really is ROMless
|
||||
// TODO: confirm size
|
||||
map(0x000000, 0x1fffff).ram();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device configuration
|
||||
@ -60,6 +77,8 @@ void pc9801_86_device::pc9801_86_config(machine_config &config)
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
YM2608(config, m_opna, 7.987_MHz_XTAL); // actually YM2608B
|
||||
// shouldn't have one
|
||||
// m_opna->set_addrmap(0, &pc9801_86_device::opna_map);
|
||||
m_opna->irq_handler().set(FUNC(pc9801_86_device::sound_irq));
|
||||
m_opna->port_a_read_callback().set(FUNC(pc9801_86_device::opn_porta_r));
|
||||
//m_opna->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
|
||||
@ -79,6 +98,16 @@ void pc9801_86_device::device_add_mconfig(machine_config &config)
|
||||
pc9801_86_config(config);
|
||||
}
|
||||
|
||||
// helper for derived devices to account for the different master OPNA sound mixing
|
||||
void pc9801_86_device::opna_reset_routes_config(machine_config &config)
|
||||
{
|
||||
m_opna->reset_routes();
|
||||
m_opna->add_route(0, "lspeaker", 0.50);
|
||||
m_opna->add_route(0, "rspeaker", 0.50);
|
||||
m_opna->add_route(1, "lspeaker", 0.50);
|
||||
m_opna->add_route(2, "rspeaker", 0.50);
|
||||
}
|
||||
|
||||
// to load a different bios for slots:
|
||||
// -cbusX pc9801_86,bios=N
|
||||
ROM_START( pc9801_86 )
|
||||
@ -87,13 +116,12 @@ ROM_START( pc9801_86 )
|
||||
// we currently mark bios names based off where they originally belonged to, lacking of a better info
|
||||
// supposedly these are -86 roms according to eikanwa2 sound card detection,
|
||||
// loading a -26 rom in a -86 environment causes an hang there.
|
||||
// TODO: several later machines (i.e. CanBe) really has an internal -86 with sound BIOS data coming directly from the machine ROM
|
||||
// it also sports different ID mapping at $a460
|
||||
ROM_SYSTEM_BIOS( 0, "86rx", "nec86rx" )
|
||||
ROMX_LOAD( "sound_rx.rom", 0x0000, 0x4000, BAD_DUMP CRC(fe9f57f2) SHA1(d5dbc4fea3b8367024d363f5351baecd6adcd8ef), ROM_BIOS(0) )
|
||||
ROM_SYSTEM_BIOS( 1, "86mu", "nec86mu" )
|
||||
ROM_SYSTEM_BIOS( 1, "86mu", "epson86mu" )
|
||||
ROMX_LOAD( "sound_486mu.rom", 0x0000, 0x4000, BAD_DUMP CRC(6cdfa793) SHA1(4b8250f9b9db66548b79f961d61010558d6d6e1c), ROM_BIOS(1) )
|
||||
|
||||
// RAM
|
||||
ROM_REGION( 0x100000, "opna", ROMREGION_ERASE00 )
|
||||
ROM_END
|
||||
|
||||
const tiny_rom_entry *pc9801_86_device::device_rom_region() const
|
||||
@ -109,10 +137,32 @@ const tiny_rom_entry *pc9801_86_device::device_rom_region() const
|
||||
static INPUT_PORTS_START( pc9801_86 )
|
||||
PORT_INCLUDE( pc9801_joy_port )
|
||||
|
||||
// Single 8-bit DSW bank
|
||||
// TODO: how HW really reads these?
|
||||
PORT_START("OPNA_DSW")
|
||||
PORT_CONFNAME( 0x01, 0x01, "PC-9801-86: Port Base" )
|
||||
PORT_CONFSETTING( 0x00, "0x088" )
|
||||
PORT_CONFSETTING( 0x01, "0x188" )
|
||||
PORT_DIPNAME( 0x01, 0x00, "PC-9801-86: Port Base" ) PORT_DIPLOCATION("OPNA_SW:!1")
|
||||
PORT_DIPSETTING( 0x00, "0x188" )
|
||||
PORT_DIPSETTING( 0x01, "0x288" )
|
||||
PORT_DIPNAME( 0x02, 0x00, "PC-9801-86: Enable sound ROM") PORT_DIPLOCATION("OPNA_SW:!2")
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) // hardwired at 0xcc000
|
||||
PORT_DIPSETTING( 0x02, DEF_STR( No ) )
|
||||
PORT_DIPNAME( 0x0c, 0x00, "PC-9801-86: Interrupt level") PORT_DIPLOCATION("OPNA_SW:!3,!4")
|
||||
PORT_DIPSETTING( 0x0c, "IRQ 0" )
|
||||
PORT_DIPSETTING( 0x08, "IRQ 4" )
|
||||
PORT_DIPSETTING( 0x00, "IRQ 5" )
|
||||
PORT_DIPSETTING( 0x04, "IRQ 6" )
|
||||
PORT_DIPNAME( 0x10, 0x00, "PC-9801-86: Interrupt enable") PORT_DIPLOCATION("OPNA_SW:!5")
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
|
||||
PORT_DIPSETTING( 0x10, DEF_STR( No ) )
|
||||
PORT_DIPNAME( 0xe0, 0x80, "PC-9801-86: ID number") PORT_DIPLOCATION("OPNA_SW:!6,!7,!8")
|
||||
PORT_DIPSETTING( 0x00, "0" )
|
||||
PORT_DIPSETTING( 0x20, "1" )
|
||||
PORT_DIPSETTING( 0x40, "2" )
|
||||
PORT_DIPSETTING( 0x60, "3" )
|
||||
PORT_DIPSETTING( 0x80, "4" )
|
||||
PORT_DIPSETTING( 0xa0, "5" )
|
||||
PORT_DIPSETTING( 0xc0, "6" )
|
||||
PORT_DIPSETTING( 0xe0, "7" )
|
||||
INPUT_PORTS_END
|
||||
|
||||
ioport_constructor pc9801_86_device::device_input_ports() const
|
||||
@ -129,12 +179,12 @@ ioport_constructor pc9801_86_device::device_input_ports() const
|
||||
//-------------------------------------------------
|
||||
|
||||
pc9801_86_device::pc9801_86_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pc9801_snd_device(mconfig, type, tag, owner, clock),
|
||||
m_bus(*this, DEVICE_SELF_OWNER),
|
||||
m_opna(*this, "opna"),
|
||||
m_ldac(*this, "ldac"),
|
||||
m_rdac(*this, "rdac"),
|
||||
m_queue(QUEUE_SIZE)
|
||||
: pc9801_snd_device(mconfig, type, tag, owner, clock)
|
||||
, m_bus(*this, DEVICE_SELF_OWNER)
|
||||
, m_opna(*this, "opna")
|
||||
, m_ldac(*this, "ldac")
|
||||
, m_rdac(*this, "rdac")
|
||||
, m_queue(QUEUE_SIZE)
|
||||
{
|
||||
}
|
||||
|
||||
@ -154,6 +204,11 @@ void pc9801_86_device::device_validity_check(validity_checker &valid) const
|
||||
{
|
||||
}
|
||||
|
||||
u16 pc9801_86_device::read_io_base()
|
||||
{
|
||||
return ((ioport("OPNA_DSW")->read() & 1) << 8) + 0x188;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
@ -161,12 +216,19 @@ void pc9801_86_device::device_validity_check(validity_checker &valid) const
|
||||
|
||||
void pc9801_86_device::device_start()
|
||||
{
|
||||
m_bus->program_space().install_rom(0xcc000,0xcffff,memregion(this->subtag("sound_bios").c_str())->base());
|
||||
// TODO: uninstall option from dip
|
||||
m_bus->program_space().install_rom(
|
||||
0xcc000,
|
||||
0xcffff,
|
||||
memregion(this->subtag("sound_bios").c_str())->base()
|
||||
);
|
||||
m_bus->install_io(0xa460, 0xa463, read8smo_delegate(*this, FUNC(pc9801_86_device::id_r)), write8smo_delegate(*this, FUNC(pc9801_86_device::mask_w)));
|
||||
m_bus->install_io(0xa464, 0xa46f, read8sm_delegate(*this, FUNC(pc9801_86_device::pcm_r)), write8sm_delegate(*this, FUNC(pc9801_86_device::pcm_w)));
|
||||
m_bus->install_io(0xa66c, 0xa66f, read8sm_delegate(*this, [this](offs_t o){ return o == 2 ? m_pcm_mute : 0xff; }, "pc9801_86_mute_r"),
|
||||
write8sm_delegate(*this, [this](offs_t o, u8 d){ if(o == 2) m_pcm_mute = d; }, "pc9801_86_mute_w"));
|
||||
|
||||
m_io_base = 0;
|
||||
|
||||
m_dac_timer = timer_alloc();
|
||||
save_item(NAME(m_count));
|
||||
save_item(NAME(m_queue));
|
||||
@ -180,9 +242,16 @@ void pc9801_86_device::device_start()
|
||||
|
||||
void pc9801_86_device::device_reset()
|
||||
{
|
||||
uint16_t port_base = (ioport("OPNA_DSW")->read() & 1) << 8;
|
||||
m_bus->io_space().unmap_readwrite(0x0088, 0x008f, 0x100);
|
||||
m_bus->install_io(port_base + 0x0088, port_base + 0x008f, read8sm_delegate(*this, FUNC(pc9801_86_device::opna_r)), write8sm_delegate(*this, FUNC(pc9801_86_device::opna_w)));
|
||||
u16 current_io = read_io_base();
|
||||
m_bus->flush_install_io(
|
||||
this->tag(),
|
||||
m_io_base,
|
||||
current_io,
|
||||
7,
|
||||
read8sm_delegate(*this, FUNC(pc9801_86_device::opna_r)),
|
||||
write8sm_delegate(*this, FUNC(pc9801_86_device::opna_w))
|
||||
);
|
||||
m_io_base = current_io;
|
||||
|
||||
m_mask = 0;
|
||||
m_head = m_tail = m_count = 0;
|
||||
@ -200,36 +269,40 @@ void pc9801_86_device::device_reset()
|
||||
//**************************************************************************
|
||||
|
||||
|
||||
uint8_t pc9801_86_device::opna_r(offs_t offset)
|
||||
u8 pc9801_86_device::opna_r(offs_t offset)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
return m_opna->read(offset >> 1);
|
||||
else // odd
|
||||
{
|
||||
logerror("PC9801-86: Read to undefined port [%02x]\n",offset+0x188);
|
||||
logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + m_io_base);
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void pc9801_86_device::opna_w(offs_t offset, uint8_t data)
|
||||
void pc9801_86_device::opna_w(offs_t offset, u8 data)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
m_opna->write(offset >> 1,data);
|
||||
else // odd
|
||||
logerror("PC9801-86: Write to undefined port [%02x] %02x\n",offset+0x188,data);
|
||||
logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + m_io_base, data);
|
||||
}
|
||||
|
||||
uint8_t pc9801_86_device::id_r()
|
||||
u8 pc9801_86_device::id_r()
|
||||
{
|
||||
return 0x40 | m_mask;
|
||||
// either a -86 or 9821 MATE A uses this id (built-in)
|
||||
const u8 id_port = ((ioport("OPNA_DSW")->read() & 1) << 4) | 0x40;
|
||||
return id_port | m_mask;
|
||||
}
|
||||
|
||||
void pc9801_86_device::mask_w(uint8_t data)
|
||||
void pc9801_86_device::mask_w(u8 data)
|
||||
{
|
||||
m_mask = data & 1;
|
||||
// TODO: bit 1 totally cuts off OPNA output
|
||||
logerror("%s: OPNA mask setting %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
|
||||
uint8_t pc9801_86_device::pcm_r(offs_t offset)
|
||||
u8 pc9801_86_device::pcm_r(offs_t offset)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
{
|
||||
@ -251,7 +324,7 @@ uint8_t pc9801_86_device::pcm_r(offs_t offset)
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void pc9801_86_device::pcm_w(offs_t offset, uint8_t data)
|
||||
void pc9801_86_device::pcm_w(offs_t offset, u8 data)
|
||||
{
|
||||
const u32 rate = (25.4_MHz_XTAL).value() / 16;
|
||||
const int divs[8] = {36, 48, 72, 96, 144, 192, 288, 384};
|
||||
@ -301,9 +374,9 @@ int pc9801_86_device::queue_count()
|
||||
return m_count;
|
||||
}
|
||||
|
||||
uint8_t pc9801_86_device::queue_pop()
|
||||
u8 pc9801_86_device::queue_pop()
|
||||
{
|
||||
uint8_t ret = m_queue[m_tail++];
|
||||
u8 ret = m_queue[m_tail++];
|
||||
m_tail %= QUEUE_SIZE;
|
||||
m_count = (m_count - 1) % QUEUE_SIZE; // dangel resets the fifo after filling it completely so maybe it expects an underflow
|
||||
return ret;
|
||||
@ -356,7 +429,9 @@ void pc9801_86_device::device_timer(emu_timer& timer, device_timer_id id, int pa
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
//
|
||||
// SpeakBoard device section
|
||||
//
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device, "pc9801_spb", "NEC PC9801 SpeakBoard")
|
||||
@ -365,11 +440,6 @@ ROM_START( pc9801_spb )
|
||||
ROM_REGION( 0x4000, "sound_bios", ROMREGION_ERASEFF )
|
||||
ROM_LOAD16_BYTE( "spb lh5764 ic21_pink.bin", 0x0001, 0x2000, CRC(5bcefa1f) SHA1(ae88e45d411bf5de1cb42689b12b6fca0146c586) )
|
||||
ROM_LOAD16_BYTE( "spb lh5764 ic22_green.bin", 0x0000, 0x2000, CRC(a7925ced) SHA1(3def9ee386ab6c31436888261bded042cd64a0eb) )
|
||||
|
||||
// RAM
|
||||
ROM_REGION( 0x100000, "opna", ROMREGION_ERASE00 )
|
||||
|
||||
ROM_REGION( 0x100000, "opna_slave", ROMREGION_ERASE00 )
|
||||
ROM_END
|
||||
|
||||
const tiny_rom_entry *pc9801_speakboard_device::device_rom_region() const
|
||||
@ -377,32 +447,21 @@ const tiny_rom_entry *pc9801_speakboard_device::device_rom_region() const
|
||||
return ROM_NAME( pc9801_spb );
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// pc9801_speakboard_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
pc9801_speakboard_device::pc9801_speakboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pc9801_86_device(mconfig, PC9801_SPEAKBOARD, tag, owner, clock),
|
||||
m_opna_slave(*this, "opna_slave")
|
||||
: pc9801_86_device(mconfig, PC9801_SPEAKBOARD, tag, owner, clock)
|
||||
, m_opna_slave(*this, "opna_slave")
|
||||
{
|
||||
}
|
||||
|
||||
void pc9801_speakboard_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
pc9801_86_config(config);
|
||||
|
||||
m_opna->reset_routes();
|
||||
m_opna->add_route(0, "lspeaker", 0.50);
|
||||
m_opna->add_route(0, "rspeaker", 0.50);
|
||||
m_opna->add_route(1, "lspeaker", 0.50);
|
||||
m_opna->add_route(2, "rspeaker", 0.50);
|
||||
opna_reset_routes_config(config);
|
||||
// TODO: confirm RAM mapping configuration (shared? not present on either chip? misc?)
|
||||
m_opna->set_addrmap(0, &pc9801_speakboard_device::opna_map);
|
||||
|
||||
YM2608(config, m_opna_slave, 7.987_MHz_XTAL);
|
||||
m_opna_slave->set_addrmap(0, &pc9801_speakboard_device::opna_map);
|
||||
m_opna_slave->add_route(0, "lspeaker", 0.50);
|
||||
m_opna_slave->add_route(0, "rspeaker", 0.50);
|
||||
m_opna_slave->add_route(1, "lspeaker", 0.50);
|
||||
@ -421,22 +480,96 @@ void pc9801_speakboard_device::device_reset()
|
||||
pc9801_86_device::device_reset();
|
||||
}
|
||||
|
||||
uint8_t pc9801_speakboard_device::opna_slave_r(offs_t offset)
|
||||
u8 pc9801_speakboard_device::opna_slave_r(offs_t offset)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
return m_opna_slave->read(offset >> 1);
|
||||
else // odd
|
||||
{
|
||||
logerror("PC9801-SPB: Read to undefined port [%02x]\n",offset+0x588);
|
||||
logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + 0x588);
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void pc9801_speakboard_device::opna_slave_w(offs_t offset, uint8_t data)
|
||||
void pc9801_speakboard_device::opna_slave_w(offs_t offset, u8 data)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
m_opna_slave->write(offset >> 1,data);
|
||||
else // odd
|
||||
logerror("PC9801-SPB: Write to undefined port [%02x] %02x\n",offset+0x588,data);
|
||||
logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + 0x588, data);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
//
|
||||
// Otomi-chan Kai device section
|
||||
//
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(OTOMICHAN_KAI, otomichan_kai_device, "pc98_otomichan_kai", "MAD Factory Otomi-chan Kai") // 音美(おとみ)ちゃん改
|
||||
|
||||
otomichan_kai_device::otomichan_kai_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: pc9801_86_device(mconfig, OTOMICHAN_KAI, tag, owner, clock)
|
||||
, m_opn2c(*this, "opn2c")
|
||||
{
|
||||
}
|
||||
|
||||
ROM_START( pc98_otomichan_kai )
|
||||
ROM_REGION( 0x4000, "sound_bios", ROMREGION_ERASEFF )
|
||||
// TODO: "compatible" with SpeakBoard, does it even uses a ROM altogether? low-res PCB pic doesn't help at all.
|
||||
ROM_LOAD16_BYTE( "spb lh5764 ic21_pink.bin", 0x0001, 0x2000, BAD_DUMP CRC(5bcefa1f) SHA1(ae88e45d411bf5de1cb42689b12b6fca0146c586) )
|
||||
ROM_LOAD16_BYTE( "spb lh5764 ic22_green.bin", 0x0000, 0x2000, BAD_DUMP CRC(a7925ced) SHA1(3def9ee386ab6c31436888261bded042cd64a0eb) )
|
||||
ROM_END
|
||||
|
||||
const tiny_rom_entry *otomichan_kai_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( pc98_otomichan_kai );
|
||||
}
|
||||
|
||||
void otomichan_kai_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
pc9801_86_config(config);
|
||||
opna_reset_routes_config(config);
|
||||
// TODO: confirm if this has OPNA RAM
|
||||
m_opna->set_addrmap(0, &otomichan_kai_device::opna_map);
|
||||
|
||||
YM3438(config, m_opn2c, 7.987_MHz_XTAL);
|
||||
m_opn2c->add_route(0, "lspeaker", 0.50);
|
||||
m_opn2c->add_route(1, "rspeaker", 0.50);
|
||||
}
|
||||
|
||||
u8 otomichan_kai_device::id_r()
|
||||
{
|
||||
// no ID, unconfirmed if it has mask
|
||||
return 0xf0 | m_mask;
|
||||
}
|
||||
|
||||
void otomichan_kai_device::device_start()
|
||||
{
|
||||
pc9801_86_device::device_start();
|
||||
|
||||
m_bus->install_io(0x0788, 0x078f, read8sm_delegate(*this, FUNC(otomichan_kai_device::opn2c_r)), write8sm_delegate(*this, FUNC(otomichan_kai_device::opn2c_w)));
|
||||
}
|
||||
|
||||
void otomichan_kai_device::device_reset()
|
||||
{
|
||||
pc9801_86_device::device_reset();
|
||||
}
|
||||
|
||||
u8 otomichan_kai_device::opn2c_r(offs_t offset)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
return m_opn2c->read(offset >> 1);
|
||||
else // odd
|
||||
{
|
||||
logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + 0x788);
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void otomichan_kai_device::opn2c_w(offs_t offset, u8 data)
|
||||
{
|
||||
if((offset & 1) == 0)
|
||||
m_opn2c->write(offset >> 1, data);
|
||||
else // odd
|
||||
logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + 0x788, data);
|
||||
}
|
||||
|
@ -29,13 +29,6 @@ public:
|
||||
pc9801_86_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
pc9801_86_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
uint8_t opna_r(offs_t offset);
|
||||
void opna_w(offs_t offset, uint8_t data);
|
||||
uint8_t id_r();
|
||||
void mask_w(uint8_t data);
|
||||
uint8_t pcm_r(offs_t offset);
|
||||
void pcm_w(offs_t offset, uint8_t data);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(sound_irq);
|
||||
|
||||
protected:
|
||||
@ -45,25 +38,37 @@ protected:
|
||||
virtual void device_reset() override;
|
||||
// optional information overrides
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
void opna_reset_routes_config(machine_config &config);
|
||||
virtual ioport_constructor device_input_ports() const 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;
|
||||
void pc9801_86_config(machine_config &config);
|
||||
virtual u16 read_io_base() override;
|
||||
|
||||
required_device<pc9801_slot_device> m_bus;
|
||||
required_device<ym2608_device> m_opna;
|
||||
|
||||
void opna_map(address_map &map);
|
||||
|
||||
u8 opna_r(offs_t offset);
|
||||
void opna_w(offs_t offset, u8 data);
|
||||
virtual u8 id_r();
|
||||
void mask_w(u8 data);
|
||||
u8 pcm_r(offs_t offset);
|
||||
void pcm_w(offs_t offset, u8 data);
|
||||
|
||||
u8 m_mask;
|
||||
|
||||
private:
|
||||
int queue_count();
|
||||
uint8_t queue_pop();
|
||||
u8 queue_pop();
|
||||
|
||||
|
||||
uint8_t m_mask, m_pcm_mode, m_vol[7], m_pcm_ctrl, m_pcm_mute;
|
||||
u8 m_pcm_mode, m_vol[7], m_pcm_ctrl, m_pcm_mute;
|
||||
uint16_t m_head, m_tail, m_count, m_irq_rate;
|
||||
bool m_pcmirq, m_fmirq, m_pcm_clk, m_init;
|
||||
required_device<dac_word_interface> m_ldac;
|
||||
required_device<dac_word_interface> m_rdac;
|
||||
std::vector<uint8_t> m_queue;
|
||||
std::vector<u8> m_queue;
|
||||
emu_timer *m_dac_timer;
|
||||
};
|
||||
|
||||
@ -73,8 +78,10 @@ public:
|
||||
// construction/destruction
|
||||
pc9801_speakboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
uint8_t opna_slave_r(offs_t offset);
|
||||
void opna_slave_w(offs_t offset, uint8_t data);
|
||||
static constexpr feature_type imperfect_features() { return feature::SOUND; }
|
||||
|
||||
u8 opna_slave_r(offs_t offset);
|
||||
void opna_slave_w(offs_t offset, u8 data);
|
||||
|
||||
protected:
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
@ -86,13 +93,33 @@ private:
|
||||
required_device<ym2608_device> m_opna_slave;
|
||||
};
|
||||
|
||||
class otomichan_kai_device : public pc9801_86_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
otomichan_kai_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
static constexpr feature_type imperfect_features() { return feature::SOUND; }
|
||||
|
||||
u8 opn2c_r(offs_t offset);
|
||||
void opn2c_w(offs_t offset, u8 data);
|
||||
|
||||
protected:
|
||||
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;
|
||||
|
||||
private:
|
||||
required_device<ym3438_device> m_opn2c;
|
||||
|
||||
virtual u8 id_r() override;
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(PC9801_86, pc9801_86_device)
|
||||
DECLARE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device)
|
||||
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(OTOMICHAN_KAI, otomichan_kai_device)
|
||||
|
||||
|
||||
#endif // MAME_BUS_CBUS_PC9801_86_H
|
||||
|
@ -1,6 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/***************************************************************************
|
||||
/**************************************************************************************************
|
||||
|
||||
System Sacom AMD-98 (AmuseMent boarD)
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
- PIT control;
|
||||
- PCM section;
|
||||
|
||||
=============================================================================
|
||||
===================================================================================================
|
||||
|
||||
- Known games with AMD-98 support
|
||||
Brown's Run (System Sacom)
|
||||
@ -25,7 +25,7 @@
|
||||
Relics (Bothtec)
|
||||
Thexder (Game Arts)
|
||||
|
||||
***************************************************************************/
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "bus/cbus/pc9801_amd98.h"
|
||||
@ -37,7 +37,7 @@
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device, "pc9801_amd98", "pc9801_amd98")
|
||||
DEFINE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device, "pc9801_amd98", "System Sacom AMD-98")
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device configuration
|
||||
@ -101,11 +101,11 @@ ioport_constructor pc9801_amd98_device::device_input_ports() const
|
||||
//-------------------------------------------------
|
||||
|
||||
pc9801_amd98_device::pc9801_amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, PC9801_AMD98, tag, owner, clock),
|
||||
m_bus(*this, DEVICE_SELF_OWNER),
|
||||
m_ay1(*this, "ay1"),
|
||||
m_ay2(*this, "ay2"),
|
||||
m_ay3(*this, "ay3")
|
||||
: device_t(mconfig, PC9801_AMD98, tag, owner, clock)
|
||||
, m_bus(*this, DEVICE_SELF_OWNER)
|
||||
, m_ay1(*this, "ay1")
|
||||
, m_ay2(*this, "ay2")
|
||||
, m_ay3(*this, "ay3")
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// copyright-holders:Angelo Salese
|
||||
/***************************************************************************
|
||||
|
||||
NEC PC-9801-118
|
||||
System Sacom AMD-98 (AmuseMent boarD)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -14,12 +14,11 @@
|
||||
#include "bus/cbus/pc9801_cbus.h"
|
||||
#include "sound/ay8910.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> pc9801_118_device
|
||||
// ======================> pc9801_amd98_device
|
||||
|
||||
class pc9801_amd98_device : public device_t
|
||||
{
|
||||
@ -54,12 +53,7 @@ private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // MAME_BUS_CBUS_PC9801_118_H
|
||||
#endif // MAME_BUS_CBUS_PC9801_AMD98_H
|
||||
|
@ -1,15 +1,23 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/**********************************************************************
|
||||
/**************************************************************************************************
|
||||
|
||||
C-bus slot interface for PC-98xx family
|
||||
|
||||
a.k.a. NEC version of the ISA bus.
|
||||
C-bus -> Card Bus
|
||||
|
||||
TODO:
|
||||
- stub interface, checkout what actually belongs here.
|
||||
Speculation is that C-bus has ROM / RAM slots always in the 0xc0000-0xdffff region,
|
||||
and some opacity can be added if true.
|
||||
- move pc9801_cbus_devices declaration from pc9801 driver in here;
|
||||
- 8-bit I/O smearing should be handled here;
|
||||
- INT# should be handled here too;
|
||||
- Best way to inform user when it tries to install incompatible boards?
|
||||
- Support for PCI bridging on later machines (cfr. pc9801cx3);
|
||||
|
||||
**********************************************************************/
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "pc9801_cbus.h"
|
||||
@ -123,3 +131,35 @@ template void pc9801_slot_device::install_io<read8_delegate, write8_delegate
|
||||
template void pc9801_slot_device::install_io<read8s_delegate, write8s_delegate >(offs_t start, offs_t end, read8s_delegate rhandler, write8s_delegate whandler);
|
||||
template void pc9801_slot_device::install_io<read8sm_delegate, write8sm_delegate >(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler);
|
||||
template void pc9801_slot_device::install_io<read8smo_delegate, write8smo_delegate>(offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler);
|
||||
|
||||
// boilerplate code for boards that has configurable I/O with either Jumpers or Dip-Switches
|
||||
// NB: client must have a mechanism to remember what port has been used before and after calling this,
|
||||
// in order to avoid "last instantiated wins" issues with overlapping board full configs.
|
||||
void pc9801_slot_device::flush_install_io(const char *client_tag, u16 old_io, u16 new_io, u16 size, read8sm_delegate rhandler, write8sm_delegate whandler)
|
||||
{
|
||||
// initialize if client have this unmapped (such as first boot)
|
||||
// device_start fns cannot read input ports ...
|
||||
if (old_io == 0)
|
||||
old_io = new_io;
|
||||
|
||||
logerror("%s: %s uninstall I/O at %04x-%04x\n",
|
||||
this->tag(),
|
||||
client_tag,
|
||||
old_io,
|
||||
old_io + size
|
||||
);
|
||||
this->io_space().unmap_readwrite(old_io, old_io + size);
|
||||
|
||||
logerror("%s: %s install I/O at %04x-%04x\n",
|
||||
this->tag(),
|
||||
client_tag,
|
||||
new_io,
|
||||
new_io + size
|
||||
);
|
||||
this->install_io(
|
||||
new_io,
|
||||
new_io + size,
|
||||
rhandler,
|
||||
whandler
|
||||
);
|
||||
}
|
||||
|
@ -113,6 +113,8 @@ public:
|
||||
template<int I> void int_w(bool state) { m_int_callback[I](state); }
|
||||
template<typename R, typename W> void install_io(offs_t start, offs_t end, R rhandler, W whandler);
|
||||
|
||||
void flush_install_io(const char *client_tag, u16 old_io, u16 new_io, u16 size, read8sm_delegate rhandler, write8sm_delegate whandler);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
@ -3,21 +3,19 @@
|
||||
/***************************************************************************
|
||||
|
||||
NEC PC-9801
|
||||
common functions for CBUS sound boards -26, -86, -118
|
||||
common functions for C-bus sound boards -26, -86, -118
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "pc9801_snd.h"
|
||||
|
||||
//DEFINE_DEVICE_TYPE(PC9801_SND, pc9801_snd_device, "pc9801_snd", "PC9801 CBUS Sound")
|
||||
|
||||
pc9801_snd_device::pc9801_snd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t pc9801_snd_device::opn_porta_r()
|
||||
u8 pc9801_snd_device::opn_porta_r()
|
||||
{
|
||||
if(m_joy_sel & 0x80)
|
||||
return ioport(m_joy_sel & 0x40 ? "PA2" : "PA1")->read();
|
||||
@ -25,7 +23,7 @@ uint8_t pc9801_snd_device::opn_porta_r()
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void pc9801_snd_device::opn_portb_w(uint8_t data) { m_joy_sel = data; }
|
||||
void pc9801_snd_device::opn_portb_w(u8 data) { m_joy_sel = data; }
|
||||
|
||||
INPUT_PORTS_START(pc9801_joy_port)
|
||||
PORT_START("PA1")
|
||||
|
@ -18,11 +18,13 @@ public:
|
||||
pc9801_snd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
uint8_t opn_porta_r();
|
||||
void opn_portb_w(uint8_t data);
|
||||
u8 opn_porta_r();
|
||||
void opn_portb_w(u8 data);
|
||||
u16 m_io_base;
|
||||
virtual u16 read_io_base() = 0;
|
||||
|
||||
private:
|
||||
uint8_t m_joy_sel;
|
||||
u8 m_joy_sel;
|
||||
};
|
||||
|
||||
//DECLARE_DEVICE_TYPE(PC9801_SND, pc9801_snd_device)
|
||||
|
140
src/devices/machine/upd4991a.cpp
Normal file
140
src/devices/machine/upd4991a.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
NEC uPD4991/uPD4991a parallel RTC
|
||||
|
||||
uPD4991 should be very similar but with "30% more power consumption" (cit.)
|
||||
|
||||
TODO:
|
||||
- bare minimum to make PC98HA happy;
|
||||
- set clock regs;
|
||||
- alarm & timer pulse;
|
||||
- AM/PM hour mode;
|
||||
- leap year;
|
||||
- busy flag;
|
||||
- adjust/clock stop/clock wait mechanisms;
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/upd4991a.h"
|
||||
|
||||
|
||||
//*************************************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//*************************************************************************************************
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(UPD4991A, upd4991a_device, "upd4991a", "NEC uPD4991a parallel RTC")
|
||||
|
||||
|
||||
//*************************************************************************************************
|
||||
// LIVE DEVICE
|
||||
//*************************************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// upd4991a_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
upd4991a_device::upd4991a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, UPD4991A, tag, owner, clock)
|
||||
, device_rtc_interface(mconfig, *this)
|
||||
, m_timer_clock(nullptr)
|
||||
{
|
||||
std::fill(std::begin(m_rtc_regs), std::end(m_rtc_regs), 0);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_validity_check - perform validity checks
|
||||
// on this device
|
||||
//-------------------------------------------------
|
||||
|
||||
void upd4991a_device::device_validity_check(validity_checker &valid) const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void upd4991a_device::device_start()
|
||||
{
|
||||
m_timer_clock = timer_alloc(TIMER_CLOCK);
|
||||
m_timer_clock->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
|
||||
|
||||
save_item(NAME(m_address));
|
||||
}
|
||||
|
||||
|
||||
void upd4991a_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_CLOCK:
|
||||
advance_seconds();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rtc_clock_updated -
|
||||
//-------------------------------------------------
|
||||
|
||||
void upd4991a_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
|
||||
{
|
||||
/*
|
||||
[0-1]
|
||||
xxxx xxxx seconds
|
||||
[2-3]
|
||||
xxxx xxxx minutes
|
||||
[4-5]
|
||||
xxxx xxxx hour
|
||||
[6-7]
|
||||
---- xxxx date digit (weekday?)
|
||||
xxxx ---- 1 day digit
|
||||
[8-9]
|
||||
---- xxxx 10 day digit
|
||||
xxxx ---- 1 month digit
|
||||
[a-b]
|
||||
---- xxxx 10 month digit
|
||||
xxxx ---- 1 year digit
|
||||
[c-d]
|
||||
---- xxxx 10 year digit
|
||||
xxxx ---- control register 1 (write only)
|
||||
[e-f]
|
||||
---- xxxx control register 2 (read/write)
|
||||
xxxx ---- mode register (write only)
|
||||
*/
|
||||
m_rtc_regs[0] = convert_to_bcd(second);
|
||||
m_rtc_regs[1] = convert_to_bcd(minute);
|
||||
m_rtc_regs[2] = convert_to_bcd(hour);
|
||||
const u8 bcd_day = convert_to_bcd(day);
|
||||
const u8 bcd_month = convert_to_bcd(month);
|
||||
const u8 bcd_year = convert_to_bcd(year);
|
||||
m_rtc_regs[3] = (day_of_week-1) | ((bcd_day & 0x0f) << 4);
|
||||
m_rtc_regs[4] = ((bcd_day & 0xf0) >> 4) | ((bcd_month & 0x0f) << 4);
|
||||
m_rtc_regs[5] = ((bcd_month & 0xf0) >> 4) | ((bcd_year & 0x0f) << 4);
|
||||
m_rtc_regs[6] = ((bcd_year & 0xf0) >> 4);
|
||||
}
|
||||
|
||||
//*************************************************************************************************
|
||||
// READ/WRITE HANDLERS
|
||||
//*************************************************************************************************
|
||||
|
||||
u8 upd4991a_device::data_r(offs_t offset)
|
||||
{
|
||||
return m_rtc_regs[m_address >> 1] >> ((m_address & 1) ? 4 : 0);
|
||||
}
|
||||
|
||||
void upd4991a_device::data_w(offs_t offset, u8 data)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void upd4991a_device::address_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_address = data & 0xf;
|
||||
}
|
59
src/devices/machine/upd4991a.h
Normal file
59
src/devices/machine/upd4991a.h
Normal file
@ -0,0 +1,59 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Angelo Salese
|
||||
/***************************************************************************
|
||||
|
||||
uPD4991a RTC
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_MACHINE_UPD4991A_H
|
||||
#define MAME_MACHINE_UPD4991A_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dirtc.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> upd4991a_device
|
||||
|
||||
class upd4991a_device : public device_t, public device_rtc_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
upd4991a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
// I/O operations
|
||||
void address_w(offs_t offset, u8 data);
|
||||
u8 data_r(offs_t offset);
|
||||
void data_w(offs_t offset, u8 data);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_validity_check(validity_checker &valid) const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
TIMER_CLOCK
|
||||
//TIMER_TP,
|
||||
//TIMER_DATA_OUT,
|
||||
//TIMER_TEST_MODE
|
||||
};
|
||||
|
||||
emu_timer *m_timer_clock;
|
||||
u8 m_rtc_regs[8];
|
||||
u8 m_address;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(UPD4991A, upd4991a_device)
|
||||
|
||||
#endif // MAME_MACHINE_UPD4991A_H
|
@ -1082,7 +1082,7 @@ void neogeo_base_state::memcard_w(offs_t offset, uint16_t data, uint16_t mem_mas
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
if (m_memcard->present())
|
||||
m_memcard->write(offset, data);
|
||||
m_memcard->write(offset, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,24 +1,31 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/*************************************************************************************************************************************
|
||||
/**************************************************************************************************
|
||||
|
||||
PC-8801 (c) 1981 NEC
|
||||
|
||||
driver by Angelo Salese, original MESS PC-88SR driver by ???
|
||||
|
||||
TODO:
|
||||
- implement proper i8214 routing, also add irq latch mechanism;
|
||||
- Fix up Floppy Terminal Count 0 / 1 writes properly, Castle Excellent (and presumably other games) is very picky about it.
|
||||
|
||||
- add differences between various models;
|
||||
- implement proper upd3301 / i8257 support;
|
||||
- fix "jumps" in mouse support pointer (noticeable in Balance of Power);
|
||||
- implement proper i8214 routing, and add irq latch mechanism;
|
||||
- Fix up Floppy Terminal Count 0 / 1 writes properly, Castle Excellent (and presumably other
|
||||
games) is very picky about it.
|
||||
- implement proper upd3301 / i8257 text support (currently hacked around);
|
||||
- Add limits for extend work RAM;
|
||||
- What happens to the palette contents when the analog/digital palette mode changes?
|
||||
- waitstates;
|
||||
- dipswitches needs to be controlled;
|
||||
- below notes states that plain PC-8801 doesn't have a disk CPU, but the BIOS clearly checks the floppy ports. Wrong info?
|
||||
- clean-ups, banking and video in particular (i.e. hook-ups with memory region should go away and device models should be used instead)
|
||||
- clean-ups:
|
||||
- better state machine isolation of features between various models (currently pretty cheaty);
|
||||
- refactor memory banking to use address maps;
|
||||
- video;
|
||||
- double check dipswitches;
|
||||
- move PC80S31K to device, needed by PC-6601SR, PC-88VA, (vanilla & optional) PC-9801.
|
||||
Also notice that there are common points with SPC-1000 and TF-20 FDDs;
|
||||
- backport/merge what is portable to PC-8001;
|
||||
- implement bus slot mechanism for NEC boards ("PC-8800-**"), HAL PCG-8100 & GSX8800,
|
||||
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;
|
||||
@ -334,6 +341,8 @@ void pc8801_state::draw_bitmap_3bpp(bitmap_ind16 &bitmap,const rectangle &clipre
|
||||
if(cliprect.contains(x+xi, y+0))
|
||||
bitmap.pix(y+0, x+xi) = m_palette->pen(pen & 7);
|
||||
|
||||
// TODO: real HW seems to actually just output to either even or odd line when in 3bpp mode
|
||||
// investigate which is right
|
||||
if(cliprect.contains(x+xi, y+1))
|
||||
bitmap.pix(y+1, x+xi) = m_palette->pen(pen & 7);
|
||||
}
|
||||
@ -1170,6 +1179,8 @@ void pc8801_state::pc8801_palram_w(offs_t offset, uint8_t data)
|
||||
m_palram[offset].g = data & 4 ? 7 : 0;
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
@ -1294,6 +1305,7 @@ void pc8801_state::pc8801_dmac_mode_w(uint8_t data)
|
||||
m_dmac_mode = data;
|
||||
m_dmac_ff = 0;
|
||||
|
||||
// Valis II sets 0x20
|
||||
if(data != 0xe4 && data != 0xa0 && data != 0xc4 && data != 0x80 && data != 0x00)
|
||||
printf("%02x DMAC mode\n",data);
|
||||
}
|
||||
@ -1333,10 +1345,13 @@ void pc8801_state::pc8801_alu_ctrl2_w(uint8_t data)
|
||||
m_alu_ctrl2 = data;
|
||||
}
|
||||
|
||||
// TODO: Implement PCG-8100 as a bus option
|
||||
// It's an HAL Laboratory custom board with PCG (maps to chars $80-$ff),
|
||||
// dual AY-3-891x & PIT, I/O $b0-$b2 is the I/O ID for it?
|
||||
// Find a supported SW (only HAL seems to support it) & investigate
|
||||
void pc8801_state::pc8801_pcg8100_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if(data)
|
||||
printf("Write to PCG-8100 %02x %02x\n",offset,data);
|
||||
logerror("%s: Possible write to PCG-8100 %02x %02x\n", machine().describe_context(), offset, data);
|
||||
}
|
||||
|
||||
void pc8801_state::pc8801_txt_cmt_ctrl_w(uint8_t data)
|
||||
@ -1615,7 +1630,8 @@ void pc8801_state::pc8801fdc_mem(address_map &map)
|
||||
|
||||
TIMER_CALLBACK_MEMBER(pc8801_state::pc8801fd_upd765_tc_to_zero)
|
||||
{
|
||||
//printf("0\n");
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -1629,10 +1645,13 @@ uint8_t pc8801_state::upd765_tc_r()
|
||||
{
|
||||
//printf("%04x 1\n",m_fdccpu->pc());
|
||||
|
||||
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));
|
||||
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
|
||||
}
|
||||
|
||||
@ -1662,6 +1681,13 @@ void pc8801_state::pc8801fdc_io(address_map &map)
|
||||
map(0xfc, 0xff).rw("d8255_slave", FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
}
|
||||
|
||||
void pc8801_state::opna_map(address_map &map)
|
||||
{
|
||||
// TODO: confirm it really is ROMless
|
||||
// TODO: confirm size
|
||||
map(0x000000, 0x1fffff).ram();
|
||||
}
|
||||
|
||||
/* Input Ports */
|
||||
|
||||
/* 2008-05 FP:
|
||||
@ -2378,17 +2404,27 @@ void pc8801_state::pc8801(machine_config &config)
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "mono").front_center();
|
||||
m_cassette->add_route(ALL_OUTPUTS, "mono", 0.05);
|
||||
|
||||
// TODO: sound irqs goes different routes when both boards are installed
|
||||
YM2203(config, m_opn, MASTER_CLOCK);
|
||||
m_opn->irq_handler().set(FUNC(pc8801_state::pc8801_sound_irq));
|
||||
m_opn->port_a_read_callback().set(FUNC(pc8801_state::opn_porta_r));
|
||||
m_opn->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
|
||||
m_opn->add_route(ALL_OUTPUTS, "mono", 1.00);
|
||||
// TODO: handtune mixing
|
||||
m_opn->add_route(0, "mono", 0.25);
|
||||
m_opn->add_route(1, "mono", 0.25);
|
||||
m_opn->add_route(2, "mono", 0.25);
|
||||
m_opn->add_route(3, "mono", 0.25);
|
||||
|
||||
YM2608(config, m_opna, MASTER_CLOCK*2);
|
||||
m_opna->set_addrmap(0, &pc8801_state::opna_map);
|
||||
m_opna->irq_handler().set(FUNC(pc8801_state::pc8801_sound_irq));
|
||||
m_opna->port_a_read_callback().set(FUNC(pc8801_state::opn_porta_r));
|
||||
m_opna->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
|
||||
m_opna->add_route(ALL_OUTPUTS, "mono", 1.00);
|
||||
// TODO: handtune mixing
|
||||
m_opna->add_route(0, "mono", 0.25);
|
||||
m_opna->add_route(1, "mono", 0.25);
|
||||
m_opna->add_route(2, "mono", 0.25);
|
||||
|
||||
BEEP(config, m_beeper, 2400).add_route(ALL_OUTPUTS, "mono", 0.10);
|
||||
|
||||
@ -2413,15 +2449,7 @@ void pc8801_state::pc8801mc(machine_config &config)
|
||||
MCFG_MACHINE_RESET_OVERRIDE(pc8801_state, pc8801_cdrom )
|
||||
}
|
||||
|
||||
|
||||
/* TODO: clean this up */
|
||||
#define PC8801_MEM_LOAD \
|
||||
ROM_REGION( 0x100000, "opna", ROMREGION_ERASE00 )
|
||||
|
||||
|
||||
ROM_START( pc8801 )
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.2
|
||||
ROM_LOAD( "n80.rom", 0x0000, 0x8000, CRC(5cb8b584) SHA1(063609dd518c124a4fc9ba35d1bae35771666a34) )
|
||||
|
||||
@ -2442,8 +2470,6 @@ ROM_END
|
||||
/* The dump only included "maincpu". Other roms arbitrariely taken from PC-8801 & PC-8801 MkIISR (there should be
|
||||
at least 1 Kanji ROM). */
|
||||
ROM_START( pc8801mk2 )
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.4
|
||||
ROM_LOAD( "m2_n80.rom", 0x0000, 0x8000, CRC(91d84b1a) SHA1(d8a1abb0df75936b3fc9d226ccdb664a9070ffb1) )
|
||||
|
||||
@ -2462,8 +2488,6 @@ ROM_START( pc8801mk2 )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pc8801mk2sr )
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.5
|
||||
ROM_LOAD( "mk2sr_n80.rom", 0x0000, 0x8000, CRC(27e1857d) SHA1(5b922ed9de07d2a729bdf1da7b57c50ddf08809a) )
|
||||
|
||||
@ -2490,8 +2514,6 @@ ROM_START( pc8801mk2sr )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pc8801mk2fr )
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.5
|
||||
ROM_LOAD( "m2fr_n80.rom", 0x0000, 0x8000, CRC(27e1857d) SHA1(5b922ed9de07d2a729bdf1da7b57c50ddf08809a) )
|
||||
|
||||
@ -2517,8 +2539,6 @@ ROM_START( pc8801mk2fr )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pc8801mk2mr )
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8
|
||||
ROM_LOAD( "m2mr_n80.rom", 0x0000, 0x8000, CRC(f074b515) SHA1(ebe9cf4cf57f1602c887f609a728267f8d953dce) )
|
||||
|
||||
@ -2545,8 +2565,6 @@ ROM_START( pc8801mk2mr )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pc8801mh )
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8, but different BIOS code?
|
||||
ROM_LOAD( "mh_n80.rom", 0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
|
||||
|
||||
@ -2573,8 +2591,6 @@ ROM_START( pc8801mh )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pc8801fa )
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8, but different BIOS code?
|
||||
ROM_LOAD( "fa_n80.rom", 0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
|
||||
|
||||
@ -2601,8 +2617,6 @@ ROM_START( pc8801fa )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pc8801ma ) // newer floppy BIOS and Jisyo (dictionary) ROM
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8, but different BIOS code?
|
||||
ROM_LOAD( "ma_n80.rom", 0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
|
||||
|
||||
@ -2633,8 +2647,6 @@ ROM_START( pc8801ma ) // newer floppy BIOS and Jisyo (dictionary) ROM
|
||||
ROM_END
|
||||
|
||||
ROM_START( pc8801ma2 )
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8
|
||||
ROM_LOAD( "ma2_n80.rom", 0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
|
||||
|
||||
@ -2664,8 +2676,6 @@ ROM_START( pc8801ma2 )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pc8801mc )
|
||||
PC8801_MEM_LOAD
|
||||
|
||||
ROM_REGION( 0x08000, "n80rom", ROMREGION_ERASEFF ) // 1.8
|
||||
ROM_LOAD( "mc_n80.rom", 0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
490
src/mame/drivers/pc9801_epson.cpp
Normal file
490
src/mame/drivers/pc9801_epson.cpp
Normal file
@ -0,0 +1,490 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese,Carl
|
||||
/**************************************************************************************************
|
||||
|
||||
Epson PC98[01] class machine
|
||||
|
||||
TODO (PC-386M):
|
||||
- Incomplete shadow IPL banking, we currently never bankswitch to the other ROM bank
|
||||
(which barely contains program code);
|
||||
- "ERR:VR" at POST (GFX VRAM)
|
||||
Sub-routine that throws this is at PC=0xfd9bc. Notice that you can actually skip this
|
||||
with eip=0x1bf in debugger and make the system to actually checkout memory installed.
|
||||
(Shorthand: "bp fd9bc,eip=0x1bf")
|
||||
- POST throws non-fatal "ERR:PA" (page fault, "Protected Address"?) after checking memory
|
||||
installed. Non-fatal as in POST will checkout bootable devices afterward.
|
||||
|
||||
TODO: (PC-486SE/PC-486MU):
|
||||
- Verify ROM bankswitch;
|
||||
On PC-486SE sets up what is normally IPL bankswitch at PC=0xf5115, successive opcode
|
||||
is a jmp 0xf8000, pretty unlikely it delays bankswitch so assume it reloads
|
||||
the same bank.
|
||||
- Remove IDE regression hack at I/O $74e;
|
||||
- Regressed with a ERR:RA (conventional memory!?) when moving driver to
|
||||
stand-alone file;
|
||||
- Eventually errors with a ERR:VR (GFX VRAM);
|
||||
|
||||
Notes:
|
||||
- A detailed list of Epson PC98s can be seen from here:
|
||||
http://www.pc-9800.net/db_epson/index.htm
|
||||
|
||||
- Being these knockoffs means that there isn't 100% compatibility with all SWs.
|
||||
Additionally NEC introduced the so called "EPSON Protect" / "EPSON check" (エプソンチェック)
|
||||
starting with MS-DOS 3.3 onward, which checks the presence of NEC / Microsoft copyright
|
||||
string at E800:0DD8 and refuses to boot if not satisfied.
|
||||
cfr. https://github.com/joncampbell123/dosbox-x/issues/682
|
||||
Epson offcially provided PC "Software Installation Program" (SIP) floppy disks
|
||||
(the "epinstal*" in SW list?) that counteracts with the protection check.
|
||||
There's alternatively a freeware user released "Dispell!" program tool that can be used for
|
||||
the same purpose, which also works for 32-bit DOS/V machines.
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/pc9801_epson.h"
|
||||
|
||||
template <unsigned which> void pc98_epson_state::shadow_ipl_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
// TODO: shadow register 0x6a may actually be write deprotect
|
||||
COMBINE_DATA(&m_shadow_ipl[which][offset]);
|
||||
}
|
||||
|
||||
/**************************************************************************************************
|
||||
|
||||
Control port for Epson shadow IPL
|
||||
|
||||
If any of these isn't right system throws "ERR:BR" at boot (BIOS loader error).
|
||||
Executes some code in text VRAM area (PC=$a006e), trying to setup a writeable RAM bank
|
||||
to IPL window area.
|
||||
|
||||
**************************************************************************************************/
|
||||
void pc98_epson_state::epson_ipl_bank_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_shadow_ipl_bank = data;
|
||||
switch(m_shadow_ipl_bank)
|
||||
{
|
||||
case 0x2a:
|
||||
m_ipl->set_bank(2);
|
||||
break;
|
||||
case 0xe6:
|
||||
m_ipl->set_bank(0);
|
||||
break;
|
||||
default:
|
||||
// TODO: at least 0xa6 used, what for?
|
||||
logerror("%s: unknown Epson shadow IPL bank setting set %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// overrides original PC98 $43c-$43f ports
|
||||
void pc98_epson_state::epson_itf_bank_w(offs_t offset, u8 data)
|
||||
{
|
||||
// $43f
|
||||
if (offset == 1)
|
||||
{
|
||||
switch(data)
|
||||
{
|
||||
case 0x40: m_itf_bank_enable = false; break;
|
||||
case 0x42: m_itf_bank_enable = true; break;
|
||||
default:
|
||||
logerror("%s: unknown ITF enable setting %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// $43d
|
||||
if (offset == 0)
|
||||
{
|
||||
switch(data)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x02:
|
||||
if (m_itf_bank_enable == true)
|
||||
m_ipl->set_bank((data & 2) >> 1);
|
||||
break;
|
||||
default:
|
||||
// TODO: 0x10 - 0x12 setting, which should be same as NEC PC98
|
||||
// (i.e. reversed compared to above)
|
||||
logerror("%s: unknown ITF bank setting %02x\n", machine().describe_context(), data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pc98_epson_state::epson_a20_w(offs_t offset, u8 data)
|
||||
{
|
||||
// pc386m PC=0xfd9b3
|
||||
// if this isn't mapped then POST throws "ERR:RA" (conventional memory -> "Real Address"?)
|
||||
m_gate_a20 = data & 1;
|
||||
m_maincpu->set_input_line(INPUT_LINE_A20, m_gate_a20 ? ASSERT_LINE : CLEAR_LINE);
|
||||
logerror("%s: Epson gate a20 %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
|
||||
void pc98_epson_state::epson_vram_bank_w(offs_t offset, u8 data)
|
||||
{
|
||||
// m_vram_bank = (data & 1) ^ 1;
|
||||
// accessed in the same routine that actually throws ERR:VR
|
||||
logerror("%s: Epson $c06 write %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
|
||||
void pc98_epson_state::pc386m_map(address_map &map)
|
||||
{
|
||||
pc9801rs_map(map);
|
||||
// TODO: is shadow RAM physically mapped here?
|
||||
// map(0xd0000, 0xd**ff).ram();
|
||||
}
|
||||
|
||||
void pc98_epson_state::pc486se_map(address_map &map)
|
||||
{
|
||||
pc386m_map(map);
|
||||
map(0x000e8000, 0x000fffff).m(m_ipl, FUNC(address_map_bank_device::amap16));
|
||||
map(0xffee8000, 0xffefffff).m(m_ipl, FUNC(address_map_bank_device::amap16));
|
||||
map(0xfffe8000, 0xffffffff).m(m_ipl, FUNC(address_map_bank_device::amap16));
|
||||
}
|
||||
|
||||
void pc98_epson_state::pc386m_io(address_map &map)
|
||||
{
|
||||
pc9801rs_io(map);
|
||||
// map(0x0c03, 0x0c03).r Epson CPU mode, 'R' for Real mode, 'P' for Protected mode (lolwut)
|
||||
map(0x0c05, 0x0c05).w(FUNC(pc98_epson_state::epson_a20_w));
|
||||
map(0x0c06, 0x0c06).w(FUNC(pc98_epson_state::epson_vram_bank_w));
|
||||
map(0x0c07, 0x0c07).w(FUNC(pc98_epson_state::epson_ipl_bank_w));
|
||||
// map(0x0c13, 0x0c13).r Epson <unknown> readback
|
||||
// map(0x0c14, 0x0c14).r Epson <unknown> readback
|
||||
}
|
||||
|
||||
void pc98_epson_state::pc486se_io(address_map &map)
|
||||
{
|
||||
pc386m_io(map);
|
||||
|
||||
map(0x0082, 0x0082).lr8(NAME([]() -> u8 { return 0x00; }));
|
||||
|
||||
map(0x043c, 0x043f).w(FUNC(pc98_epson_state::epson_itf_bank_w)).umask16(0xff00);
|
||||
|
||||
map(0x0c42, 0x0c43).lr16(NAME([]() -> u16 { return 0x0000; }));
|
||||
|
||||
// map(0x0640, 0x064f).rw(FUNC(pc9801_state::ide_cs0_r), FUNC(pc9801_state::ide_cs0_w));
|
||||
// map(0x0740, 0x074f).rw(FUNC(pc9801_state::ide_cs1_r), FUNC(pc9801_state::ide_cs1_w));
|
||||
// HACK: avoid POST moaning for misconfigured HDDs (!?)
|
||||
map(0x074e, 0x074e).lr8(NAME([]() -> u8 { return 0xff; }));
|
||||
|
||||
// (R) bit 0: expected to go off at PC=0xf8c52 (pc486se)
|
||||
// (W) commands for?
|
||||
map(0x0c09, 0x0c09).lr8(NAME([]() -> u8 { return 0x00; }));
|
||||
map(0x0c0b, 0x0c0b).lr8(NAME([]() -> u8 { return 0x00; }));
|
||||
}
|
||||
|
||||
void pc98_epson_state::pc386m_ipl_bank(address_map &map)
|
||||
{
|
||||
map(0x00000, 0x17fff).rom().region("ipl", 0x00000).w(FUNC(pc98_epson_state::shadow_ipl_w<0>));
|
||||
map(0x18000, 0x2ffff).rom().region("ipl", 0x18000).w(FUNC(pc98_epson_state::shadow_ipl_w<1>));
|
||||
map(0x30000, 0x47fff).ram().share("shadow_ipl_0");
|
||||
map(0x48000, 0x5ffff).ram().share("shadow_ipl_1");
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START( pc386m )
|
||||
// in tracer bullet fashion we intentionally separated all dips/mouse switches
|
||||
// since there's no real need to actually INPUT_PORTS_EXTERN here:
|
||||
// - mouse should really be a device interface anyway;
|
||||
// - dips may really diverge from NEC specs or even be unmapped (needs verification).
|
||||
// In both cases those needs a major cleanup, haven't yet found actual documentation for these specifically.
|
||||
// Notice that Epson eventually inherited SDIP chip as well.
|
||||
PORT_START("DSW1")
|
||||
PORT_DIPNAME( 0x01, 0x01, "Monitor Type" )
|
||||
PORT_DIPSETTING( 0x00, "Normal Display (15KHz)" )
|
||||
PORT_DIPSETTING( 0x01, "Hi-Res Display (24KHz)" )
|
||||
PORT_DIPNAME( 0x02, 0x00, "DSW1" )
|
||||
PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x04, 0x04, "Display Type" )
|
||||
PORT_DIPSETTING( 0x04, "RGB" )
|
||||
PORT_DIPSETTING( 0x00, "Plasma" )
|
||||
PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x10, 0x00, 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, 0x00, "Graphic Function" )
|
||||
PORT_DIPSETTING( 0x80, "Basic (8 Colors)" )
|
||||
PORT_DIPSETTING( 0x00, "Expanded (16/4096 Colors)" )
|
||||
|
||||
PORT_START("DSW2")
|
||||
PORT_DIPNAME( 0x01, 0x00, "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, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x10, 0x00, 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, "GDC clock" )
|
||||
PORT_DIPSETTING( 0x80, "2.5 MHz" )
|
||||
PORT_DIPSETTING( 0x00, "5 MHz" )
|
||||
|
||||
PORT_START("DSW3")
|
||||
PORT_DIPNAME( 0x01, 0x01, "FDD Fix Mode" )
|
||||
PORT_DIPSETTING( 0x00, "Auto-Detection" )
|
||||
PORT_DIPSETTING( 0x01, "Fixed" )
|
||||
PORT_DIPNAME( 0x02, 0x02, "FDD Density Select" )
|
||||
PORT_DIPSETTING( 0x00, "2DD" )
|
||||
PORT_DIPSETTING( 0x02, "2HD" )
|
||||
PORT_DIPNAME( 0x04, 0x04, "DSW3" )
|
||||
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, "Conventional RAM size" )
|
||||
PORT_DIPSETTING( 0x40, "640 KB" )
|
||||
PORT_DIPSETTING( 0x00, "512 KB" )
|
||||
PORT_DIPNAME( 0x80, 0x00, "CPU Type" )
|
||||
PORT_DIPSETTING( 0x80, "V30" )
|
||||
PORT_DIPSETTING( 0x00, "I386" )
|
||||
|
||||
PORT_START("MOUSE_X")
|
||||
PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(30) PORT_KEYDELTA(30)
|
||||
|
||||
PORT_START("MOUSE_Y")
|
||||
PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(30) PORT_KEYDELTA(30)
|
||||
|
||||
PORT_START("MOUSE_B")
|
||||
PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_NAME("Mouse Right Button")
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_NAME("Mouse Middle Button")
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Mouse Left Button")
|
||||
|
||||
PORT_START("ROM_LOAD")
|
||||
PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_CONFNAME( 0x04, 0x04, "Load IDE BIOS" )
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Yes ) )
|
||||
PORT_CONFSETTING( 0x04, DEF_STR( No ) )
|
||||
INPUT_PORTS_END
|
||||
|
||||
MACHINE_START_MEMBER(pc98_epson_state, pc98_epson)
|
||||
{
|
||||
MACHINE_START_CALL_MEMBER(pc9801rs);
|
||||
}
|
||||
|
||||
MACHINE_RESET_MEMBER(pc98_epson_state, pc98_epson)
|
||||
{
|
||||
MACHINE_RESET_CALL_MEMBER(pc9801rs);
|
||||
m_ipl->set_bank(0);
|
||||
}
|
||||
|
||||
void pc98_epson_state::pc386m(machine_config &config)
|
||||
{
|
||||
pc9801rs(config);
|
||||
I386SX(config.replace(), m_maincpu, 16000000); // i386SX 16MHz, switchable to 10/6 MHz
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &pc98_epson_state::pc386m_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &pc98_epson_state::pc386m_io);
|
||||
m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb));
|
||||
|
||||
m_ipl->set_addrmap(AS_PROGRAM, &pc98_epson_state::pc386m_ipl_bank);
|
||||
// TODO: 19 or 20 address lines?
|
||||
// 20 may be used in case that mixed up ROM & shadow IPL loads are actually possible
|
||||
// (which sounds pretty possible)
|
||||
m_ipl->set_options(ENDIANNESS_LITTLE, 16, 19, 0x18000);
|
||||
|
||||
MCFG_MACHINE_START_OVERRIDE(pc98_epson_state, pc98_epson)
|
||||
MCFG_MACHINE_RESET_OVERRIDE(pc98_epson_state, pc98_epson)
|
||||
|
||||
// RAM: 640KB + 14.6MB max
|
||||
// 2 3.5 floppy drives
|
||||
// ...
|
||||
}
|
||||
|
||||
void pc98_epson_state::pc486se(machine_config &config)
|
||||
{
|
||||
pc386m(config);
|
||||
const XTAL xtal = XTAL(25'000'000);
|
||||
I486(config.replace(), m_maincpu, xtal); // i486SX, switchable to 10/5 MHz, supports overdrive
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &pc98_epson_state::pc486se_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &pc98_epson_state::pc486se_io);
|
||||
m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb));
|
||||
|
||||
pit_clock_config(config, xtal/8); // unknown, passes "ERR:TM" test
|
||||
|
||||
// RAM: 1.6 MB (!) + 17.6 max
|
||||
// "dedicated internal memory slot x 1"
|
||||
// "dedicated video board" slot
|
||||
}
|
||||
|
||||
void pc98_epson_state::pc486mu(machine_config &config)
|
||||
{
|
||||
pc386m(config);
|
||||
const XTAL xtal = XTAL(33'000'000);
|
||||
I486(config.replace(), m_maincpu, xtal); // i486SX, switchable to I386DX 10MHz/5MHz, Pentium ODP compatible
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &pc98_epson_state::pc486se_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &pc98_epson_state::pc386m_io);
|
||||
m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb));
|
||||
|
||||
pit_clock_config(config, xtal/8); // unknown, passes "ERR:TM" test
|
||||
|
||||
// CL-GD5428
|
||||
// RAM: 5.6 + 61.6MB max
|
||||
// 2 x 3.5 floppy drives
|
||||
}
|
||||
|
||||
|
||||
// backported from pc98, of course both aren't 100% identical to the NEC counterpart
|
||||
#define LOAD_IDE_ROM \
|
||||
ROM_REGION( 0x4000, "ide", ROMREGION_ERASEVAL(0xcb) ) \
|
||||
ROM_LOAD( "epson_ide_bios.rom", 0x0000, 0x2000, NO_DUMP ) \
|
||||
ROM_IGNORE( 0x2000 ) \
|
||||
ROM_IGNORE( 0x2000 ) \
|
||||
ROM_IGNORE( 0x2000 )
|
||||
|
||||
#define LOAD_KANJI_ROMS \
|
||||
ROM_REGION( 0x80000, "raw_kanji", ROMREGION_ERASEFF ) \
|
||||
ROM_LOAD16_BYTE( "24256c-x01.bin", 0x00000, 0x4000, BAD_DUMP CRC(28ec1375) SHA1(9d8e98e703ce0f483df17c79f7e841c5c5cd1692) ) \
|
||||
ROM_CONTINUE( 0x20000, 0x4000 ) \
|
||||
ROM_LOAD16_BYTE( "24256c-x02.bin", 0x00001, 0x4000, BAD_DUMP CRC(90985158) SHA1(78fb106131a3f4eb054e87e00fe4f41193416d65) ) \
|
||||
ROM_CONTINUE( 0x20001, 0x4000 ) \
|
||||
ROM_LOAD16_BYTE( "24256c-x03.bin", 0x40000, 0x4000, BAD_DUMP CRC(d4893543) SHA1(eb8c1bee0f694e1e0c145a24152222d4e444e86f) ) \
|
||||
ROM_CONTINUE( 0x60000, 0x4000 ) \
|
||||
ROM_LOAD16_BYTE( "24256c-x04.bin", 0x40001, 0x4000, BAD_DUMP CRC(5dec0fc2) SHA1(41000da14d0805ed0801b31eb60623552e50e41c) ) \
|
||||
ROM_CONTINUE( 0x60001, 0x4000 ) \
|
||||
ROM_REGION( 0x100000, "kanji", ROMREGION_ERASEFF ) \
|
||||
ROM_REGION( 0x80000, "new_chargen", ROMREGION_ERASEFF )
|
||||
|
||||
/*
|
||||
Epson PC-386M
|
||||
|
||||
i386SX-16 @ 16
|
||||
1MB
|
||||
3.5"2DD/2HDx2
|
||||
CBus: 3slots
|
||||
*/
|
||||
|
||||
ROM_START( pc386m )
|
||||
ROM_REGION16_LE( 0x30000, "ipl", ROMREGION_ERASEFF )
|
||||
// bank 0: definitely wants this ROM mapping otherwise POST throws "ERR:R0" (BIOS checksum)
|
||||
ROM_LOAD( "cwma-a02.bin", 0x10000, 0x08000, CRC(d2c357a4) SHA1(819c9a1fc92124a8d6a85339c74651add7efaf92) )
|
||||
ROM_CONTINUE( 0x00000, 0x10000 )
|
||||
ROM_CONTINUE( 0x28000, 0x08000 ) // bank 1, unconfirmed
|
||||
|
||||
ROM_REGION( 0x80000, "chargen", 0 )
|
||||
ROM_LOAD( "font_486mu.rom", 0x0000, 0x46800, BAD_DUMP CRC(456d9fc7) SHA1(78ba9960f135372825ab7244b5e4e73a810002ff))
|
||||
|
||||
LOAD_KANJI_ROMS
|
||||
LOAD_IDE_ROM
|
||||
ROM_END
|
||||
|
||||
/*
|
||||
Epson PC-486SE
|
||||
|
||||
i486SX @ 25 MHz
|
||||
1.6 MB of conventional memory (???)
|
||||
17.6 MB
|
||||
CBus: 2slots
|
||||
*/
|
||||
|
||||
ROM_START( pc486se )
|
||||
ROM_REGION16_LE( 0x20000, "biosrom", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "1699ma_cw99-a03.bin", 0x00000, 0x20000, CRC(f03df711) SHA1(88614746e01c7d3cff9f3b8ce0a598830a77d1dc) )
|
||||
|
||||
ROM_REGION16_LE( 0x30000, "ipl", ROMREGION_ERASEFF )
|
||||
// this is quite convoluted
|
||||
ROM_COPY( "biosrom", 0x08000, 0x00000, 0x08000 )
|
||||
ROM_COPY( "biosrom", 0x00000, 0x10000, 0x08000 )
|
||||
ROM_COPY( "biosrom", 0x10000, 0x08000, 0x08000 )
|
||||
// ROM_FILL( 0x18000, 0x08000, 0x90) // untested by BIOS
|
||||
ROM_COPY( "biosrom", 0x10000, 0x20000, 0x08000 )
|
||||
ROM_COPY( "biosrom", 0x18000, 0x28000, 0x08000 )
|
||||
|
||||
ROM_REGION( 0x80000, "chargen", 0 )
|
||||
ROM_LOAD( "font_486mu.rom", 0x0000, 0x46800, BAD_DUMP CRC(456d9fc7) SHA1(78ba9960f135372825ab7244b5e4e73a810002ff))
|
||||
|
||||
LOAD_KANJI_ROMS
|
||||
LOAD_IDE_ROM
|
||||
ROM_END
|
||||
|
||||
/*
|
||||
Epson PC-486MU
|
||||
i486SX-33 @ 33
|
||||
8MB RAM
|
||||
3.5'2DD/2HDx2, 2xCD-ROM
|
||||
CBus: 3 slots
|
||||
*/
|
||||
|
||||
ROM_START( pc486mu )
|
||||
ROM_REGION16_LE( 0x20000, "biosrom", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "pc-486mu_hn27c1024.bin", 0x00000, 0x20000, CRC(113268e1) SHA1(2a630abc825b2808f9f8fb65c6cb1fb7e7f6c710))
|
||||
// ROM_LOAD( "bios_486mu.rom", 0x00000, 0x18000, BAD_DUMP CRC(57b5d701) SHA1(15029800842e93e07615b0fd91fb9f2bfe3e3c24))
|
||||
|
||||
ROM_REGION16_LE( 0x30000, "ipl", ROMREGION_ERASEFF )
|
||||
// backported from pc486se
|
||||
ROM_COPY( "biosrom", 0x08000, 0x00000, 0x08000 )
|
||||
ROM_COPY( "biosrom", 0x00000, 0x10000, 0x08000 )
|
||||
ROM_COPY( "biosrom", 0x10000, 0x08000, 0x08000 )
|
||||
// ROM_FILL( 0x18000, 0x08000, 0x90) // untested by BIOS
|
||||
ROM_COPY( "biosrom", 0x10000, 0x20000, 0x08000 )
|
||||
ROM_COPY( "biosrom", 0x18000, 0x28000, 0x08000 )
|
||||
|
||||
|
||||
ROM_REGION( 0x80000, "chargen", 0 )
|
||||
ROM_LOAD( "font_486mu.rom", 0x0000, 0x46800, BAD_DUMP CRC(456d9fc7) SHA1(78ba9960f135372825ab7244b5e4e73a810002ff))
|
||||
|
||||
LOAD_KANJI_ROMS
|
||||
LOAD_IDE_ROM
|
||||
ROM_END
|
||||
|
||||
// Epson PC98 desktop line
|
||||
|
||||
// PC-286 (i286, first model released in Oct 1987)
|
||||
// PC-286U (same as above except running on V30)
|
||||
// PC-286C "PC Club" (same as PC-286?)
|
||||
// ...
|
||||
|
||||
// PC-386 (i386)
|
||||
COMP( 1990, pc386m, 0, 0, pc386m, pc386m, pc98_epson_state, init_pc9801_kanji, "Epson", "PC-386M", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
|
||||
|
||||
// PC-486 (i486SX/DX)
|
||||
COMP( 1994, pc486mu, 0, 0, pc486se, pc386m, pc98_epson_state, init_pc9801_kanji, "Epson", "PC-486MU", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
|
||||
COMP( 1993, pc486se, pc486mu, 0, pc486se, pc386m, pc98_epson_state, init_pc9801_kanji, "Epson", "PC-486SE", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND )
|
||||
// PRO-486 (first actual version with i486dx? Supports High-reso)
|
||||
// PC-486P/Win (same as a PC-486P but with Windows 3.0a + MS-DOS 3.3 HDD pre-installed?)
|
||||
|
||||
// PC-586 (Pentium/Pentium ODP compatibles)
|
||||
// ...
|
||||
|
||||
// Epson PC98 L[aptop] line
|
||||
// PC-286B (80C286)
|
||||
// PC-286L* (V30 or 80C286)
|
||||
// ...
|
||||
|
||||
// PC-386BL* (i386sx)
|
||||
// PC-386LS* (just bigger version of above?)
|
||||
// ...
|
||||
|
||||
// Epson PC98 NOTE[book] line
|
||||
// PC-*86N* (runs on correlated CPU as above)
|
||||
// PC-486PT ("P[or]T[able]" SL enhanced i486, wallet-like dimensions, supports light pen, runs under "PenDOS")
|
||||
// ...
|
1418
src/mame/drivers/pc9821.cpp
Normal file
1418
src/mame/drivers/pc9821.cpp
Normal file
File diff suppressed because it is too large
Load Diff
526
src/mame/drivers/pc98ha.cpp
Normal file
526
src/mame/drivers/pc98ha.cpp
Normal file
@ -0,0 +1,526 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/**************************************************************************************************
|
||||
|
||||
PC98LT/HA class machine "Handy98" aka 1st Gen LCD PC98
|
||||
|
||||
TODO:
|
||||
- pc98lt: remove timer hack:
|
||||
- definitely incorrect given the erratic cursor blinking in N88BASIC;
|
||||
- identify LCDC used here, reg 2 is clearly H display (0x4f+1)*8=640
|
||||
- merge from base pc98 class (WIP);
|
||||
- when idle for some time buzzer farts until a key is pressed (?);
|
||||
- add NVRAM saving:
|
||||
- pinpoint NVRAM init switch source:
|
||||
- first port C read (pc98lt: i/o 0x35, PC=0xf841f) tests for bit 7,
|
||||
which initializes battery backup if on, but port C is in output mode there.
|
||||
Somehow obf irq is on at boot if battery failed?
|
||||
- power handling;
|
||||
- pc98ha specifics:
|
||||
- RTC is upd4991a (partially done), it's parallel instead of serial and incompatible with
|
||||
everything else ugh;
|
||||
- EMS fails at boot, it's never ever really checked;
|
||||
- MSDOS cannot detect EMS properly, is there a flag somewhere?
|
||||
- JEIDA memory card interface;
|
||||
- optional docking station (for floppy device only or can mount other stuff too?);
|
||||
|
||||
**************************************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/pc98ha.h"
|
||||
|
||||
void pc98lt_state::lt_palette(palette_device &palette) const
|
||||
{
|
||||
palette.set_pen_color(0, 160, 168, 160);
|
||||
palette.set_pen_color(1, 48, 56, 16);
|
||||
}
|
||||
|
||||
uint32_t pc98lt_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect )
|
||||
{
|
||||
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
for (int x = cliprect.min_x; x <= cliprect.max_x; x += 16)
|
||||
{
|
||||
u16 pen = bitswap<16>(m_gvram[(y*640+x)/16], 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);
|
||||
|
||||
for (int xi = 0; xi < 16; xi++)
|
||||
{
|
||||
u8 dot = (pen >> xi) & 1;
|
||||
bitmap.pix(y, x+xi) = m_palette->pen(dot);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power Status Register
|
||||
*
|
||||
* x--- ---- docking station connected (HA only?)
|
||||
* -x-- ---- AC power supply connected
|
||||
* ---x ---- alarm enabled
|
||||
* ---- x--- unknown
|
||||
* ---- -x-- Lithium battery low (HA only?)
|
||||
* ---- --x- battery low
|
||||
* ---- ---x power off
|
||||
*/
|
||||
u8 pc98lt_state::power_status_r()
|
||||
{
|
||||
return 0x80;
|
||||
}
|
||||
|
||||
void pc98lt_state::power_control_w(offs_t offset, u8 data)
|
||||
{
|
||||
// TODO: happens pretty often, supposed to halt the system and wake up on arbitrary event?
|
||||
if (BIT(data, 2))
|
||||
logerror("%s: power_control_w standby signal ON\n", machine().describe_context());
|
||||
|
||||
// pc98lt: go to prompt (type "command" in main menu) and execute "poweroff.com"
|
||||
if (BIT(data, 0))
|
||||
logerror("%s: power_control_w power off signal ON\n", machine().describe_context());
|
||||
|
||||
// pc98ha bit 1: flips between 0->1 on system boot failure, in tandem with standby mode held
|
||||
if (data & ~0x07)
|
||||
logerror("%s: power_control_w unknown signal sent %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
|
||||
// TODO: intentionally repeated from base pc98 until I understand what's going on here.
|
||||
// (supposedly should be same from base pc98 minus the V50 integrations and whatever the "docking station" really adds up)
|
||||
u8 pc98lt_state::floppy_mode_r(offs_t offset)
|
||||
{
|
||||
// floppy "mode" identifies drive capabilities, if 2dd/2hd exclusive or mixed type.
|
||||
// and to my understanding it doesn't really read from write reg ...
|
||||
return (m_floppy_mode & 3) | 0x08;
|
||||
}
|
||||
|
||||
void pc98lt_state::floppy_mode_w(offs_t offset, u8 data)
|
||||
{
|
||||
// bit 1: selects between 2hd and 2dd, not unlike base PC98
|
||||
m_floppy_mode = data & 3;
|
||||
m_fdc->subdevice<floppy_connector>("0")->get_device()->set_rpm(data & 0x02 ? 360 : 300);
|
||||
m_fdc->subdevice<floppy_connector>("1")->get_device()->set_rpm(data & 0x02 ? 360 : 300);
|
||||
|
||||
m_fdc->set_rate(data & 0x02 ? 500000 : 250000);
|
||||
}
|
||||
|
||||
u8 pc98lt_state::fdc_ctrl_r(offs_t offset)
|
||||
{
|
||||
// TODO: doesn't work as intended, bit 4 is supposedly if the drive has a disk in or not according to documentation.
|
||||
int ret = (m_fdc->subdevice<floppy_connector>("0")->get_device()->ready_r()) ? 0x10 : 0;
|
||||
ret |= (m_fdc->subdevice<floppy_connector>("1")->get_device()->ready_r()) ? 0x10 : 0;
|
||||
return ret | 0x64;
|
||||
}
|
||||
|
||||
void pc98lt_state::fdc_ctrl_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_fdc->reset_w(BIT(data, 7));
|
||||
|
||||
m_fdc_ctrl = data;
|
||||
if(data & 0x40)
|
||||
{
|
||||
m_fdc->set_ready_line_connected(0);
|
||||
m_fdc->ready_w(0);
|
||||
}
|
||||
else
|
||||
m_fdc->set_ready_line_connected(1);
|
||||
|
||||
m_fdc->subdevice<floppy_connector>("0")->get_device()->mon_w(data & 8 ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_fdc->subdevice<floppy_connector>("1")->get_device()->mon_w(data & 8 ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
void pc98lt_state::lt_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x00000, 0x5ffff).ram(); // 384 KB
|
||||
map(0x60000, 0x9ffff).noprw();
|
||||
|
||||
// no TVRAM
|
||||
map(0xa8000, 0xaffff).ram().share("gvram");
|
||||
// 0xb0000-0xbffff unmapped GVRAM or mirror, check me
|
||||
map(0xc0000, 0xcffff).unmaprw(); // EMS area, not present here but checked
|
||||
map(0xd0000, 0xd3fff).bankrw("bram_bank");
|
||||
map(0xd4000, 0xd7fff).bankr("dict_bank");
|
||||
map(0xd8000, 0xdbfff).bankr("kanji_bank");
|
||||
map(0xe0000, 0xeffff).bankr("romdrv_bank");
|
||||
map(0xf0000, 0xfffff).rom().region("ipl", 0);
|
||||
}
|
||||
|
||||
void pc98lt_state::lt_io(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
// map(0x0000, 0x001f) // PIC (bit 3 ON slave / master), V50 internal / <undefined>
|
||||
map(0x0020, 0x002f).w(FUNC(pc98lt_state::rtc_w)).umask16(0x00ff);
|
||||
map(0x0030, 0x0037).rw(m_ppi_sys, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0xff00); //i8251 RS232c / i8255 system port
|
||||
map(0x0040, 0x0047).rw(m_ppi_prn, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff);
|
||||
map(0x0040, 0x0047).rw(m_keyb, FUNC(pc9801_kbd_device::rx_r), FUNC(pc9801_kbd_device::tx_w)).umask16(0xff00); //i8255 printer port / i8251 keyboard
|
||||
// map(0x0070, 0x007f) // PIT, V50 internal
|
||||
|
||||
// floppy actually requires a docking station on PC98HA, density should be 2dd given the mapping
|
||||
map(0x00be, 0x00be).rw(FUNC(pc98lt_state::floppy_mode_r), FUNC(pc98lt_state::floppy_mode_w));
|
||||
map(0x00c8, 0x00cb).m(m_fdc, FUNC(upd765a_device::map)).umask16(0x00ff);
|
||||
map(0x00cc, 0x00cc).rw(FUNC(pc98lt_state::fdc_ctrl_r), FUNC(pc98lt_state::fdc_ctrl_w));
|
||||
|
||||
// map(0x00e0, 0x00ef) // uPD71071, V50 internal
|
||||
|
||||
// map(0x0810, 0x0810) // <unknown device data>, LCDC?
|
||||
// map(0x0812, 0x0812) // <unknown device address> & 0xf
|
||||
|
||||
map(0x0c10, 0x0c10).lrw8(
|
||||
NAME([this] () { return (m_bram_bank_reg & (m_bram_banks - 1)) | 0x40; }),
|
||||
NAME([this] (u8 data) { m_bram_bank_reg = data & (m_bram_banks - 1); m_bram_bank->set_entry(m_bram_bank_reg); })
|
||||
);
|
||||
// map(0x0f8e, 0x0f8e) // card slot status 1 (undefined on pc98lt?)
|
||||
// map(0x4810, 0x4810) // ?
|
||||
map(0x4c10, 0x4c10).lrw8(
|
||||
NAME([this] () { return (m_dict_bank_reg & 0x3f) | 0x40; }),
|
||||
NAME([this] (u8 data) { m_dict_bank_reg = data & 0x3f; m_dict_bank->set_entry(m_dict_bank_reg); })
|
||||
);
|
||||
// map(0x5e8e, 0x5e8e) // card slot status 2
|
||||
// map(0x6e8e, 0x6e8e) // modem control 1
|
||||
// map(0x7e8e, 0x7e8e) // modem control 2
|
||||
map(0x8810, 0x8810).rw(FUNC(pc98lt_state::power_status_r), FUNC(pc98lt_state::power_control_w));
|
||||
map(0x8c10, 0x8c10).lw8(NAME([this] (u8 data) { m_kanji_bank->set_entry(data & 0x0f); }));
|
||||
// map(0xc810, 0xc810) // ?
|
||||
map(0xcc10, 0xcc10).lrw8(
|
||||
NAME([this] () { return (m_romdrv_bank_reg & 0xf) | 0x40; }),
|
||||
NAME([this] (u8 data) { m_romdrv_bank_reg = data & 0xf; m_romdrv_bank->set_entry(m_romdrv_bank_reg); })
|
||||
);
|
||||
}
|
||||
|
||||
/************************************
|
||||
*
|
||||
* 98HA specifics
|
||||
*
|
||||
***********************************/
|
||||
|
||||
void pc98ha_state::ext_view_bank_w(offs_t offset, u8 data)
|
||||
{
|
||||
if (m_ext_view_sel == 0x81)
|
||||
m_ramdrv_bank->set_entry(data & 0x7f);
|
||||
else
|
||||
logerror("External view SEL bank set %02x (view=%02x)\n", data, m_ext_view_sel);
|
||||
}
|
||||
|
||||
void pc98ha_state::ext_view_sel_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_ext_view_sel = data;
|
||||
// either bit 7 ON or writing 0x80 to this port disables the external view.
|
||||
if (data & 0x80)
|
||||
m_ext_view.select(data & 0x3);
|
||||
if (data != 0x81)
|
||||
logerror("External view SEL line set %02x\n", data);
|
||||
}
|
||||
|
||||
void pc98ha_state::ems_bank_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_ems_banks[offset]->set_entry(data & 0x7f);
|
||||
}
|
||||
|
||||
u8 pc98ha_state::memcard_status_1_r(offs_t offset)
|
||||
{
|
||||
// TODO: identify exact type
|
||||
// 0x0e: memory card present
|
||||
// bit 3 is checked at boot, PC=f82a5
|
||||
// mask 0xf0 is checked at PC=f8956 then periodically polled at PC=0xfd110
|
||||
// NeoGeo uses v3
|
||||
return 0x04;
|
||||
}
|
||||
|
||||
u8 pc98ha_state::memcard_status_2_r(offs_t offset)
|
||||
{
|
||||
// 0x46: memory card present
|
||||
return 0x40;
|
||||
}
|
||||
|
||||
void pc98ha_state::ha_map(address_map &map)
|
||||
{
|
||||
lt_map(map);
|
||||
map(0x00000, 0x9ffff).ram(); // 640 KB
|
||||
|
||||
map(0xc0000, 0xc3fff).bankrw("ems_bank1");
|
||||
map(0xc4000, 0xc7fff).bankrw("ems_bank2");
|
||||
map(0xc8000, 0xcbfff).bankrw("ems_bank3");
|
||||
map(0xcc000, 0xcffff).bankrw("ems_bank4");
|
||||
map(0xdc000, 0xdffff).view(m_ext_view);
|
||||
m_ext_view[0](0xdc000, 0xdffff).unmaprw(); // unknown, accessed on MSDOS boot
|
||||
m_ext_view[1](0xdc000, 0xdffff).bankrw("ramdrv_bank");
|
||||
m_ext_view[2](0xdc000, 0xdffff).unmaprw(); // JEIDA memory card
|
||||
m_ext_view[3](0xdc000, 0xdffff).unmaprw();
|
||||
}
|
||||
|
||||
void pc98ha_state::ha_io(address_map &map)
|
||||
{
|
||||
lt_io(map);
|
||||
map(0x0020, 0x002f).unmaprw();
|
||||
map(0x0022, 0x0022).w(m_rtc_pio, FUNC(upd4991a_device::address_w));
|
||||
map(0x0023, 0x0023).rw(m_rtc_pio, FUNC(upd4991a_device::data_r), FUNC(upd4991a_device::data_w));
|
||||
map(0x08e0, 0x08e7).w(FUNC(pc98ha_state::ems_bank_w)).umask16(0xff00);
|
||||
map(0x0e8e, 0x0e8e).w(FUNC(pc98ha_state::ext_view_bank_w));
|
||||
map(0x0f8e, 0x0f8e).r(FUNC(pc98ha_state::memcard_status_1_r));
|
||||
map(0x1e8e, 0x1e8e).w(FUNC(pc98ha_state::ext_view_sel_w));
|
||||
map(0x5f8e, 0x5f8e).r(FUNC(pc98ha_state::memcard_status_2_r));
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START( pc98lt )
|
||||
PORT_START("SYSB")
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER(RTC_TAG, upd1990a_device, data_out_r)
|
||||
PORT_DIPNAME( 0x02, 0x00, "SYSB" )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x10, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x10, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x20, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x20, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x40, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x40, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x80, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( On ) )
|
||||
|
||||
PORT_START("SYSC")
|
||||
PORT_DIPNAME( 0x01, 0x00, "SYSC" )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x10, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x10, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x20, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x20, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x40, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x40, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x80, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( On ) )
|
||||
|
||||
PORT_START("PRNB")
|
||||
PORT_DIPNAME( 0x01, 0x00, "PRNB" ) // checked on boot
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // CPUT LT/HA switch
|
||||
PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unknown ) ) // checked on boot
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x10, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x10, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x20, 0x00, DEF_STR( Unknown ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x20, DEF_STR( On ) )
|
||||
PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(pc98lt_state, system_type_r)
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START( pc98ha )
|
||||
PORT_INCLUDE( pc98lt )
|
||||
|
||||
PORT_MODIFY("SYSB")
|
||||
PORT_DIPNAME( 0x01, 0x00, "<rtc empty signal>" )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
||||
|
||||
PORT_MODIFY("PRNB")
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
INPUT_PORTS_END
|
||||
|
||||
// debug
|
||||
static const gfx_layout gfx_16x16x1 =
|
||||
{
|
||||
16,16,
|
||||
RGN_FRAC(1,1),
|
||||
1,
|
||||
{ 0 },
|
||||
{ STEP16(0,1) },
|
||||
{ STEP16(0,16) },
|
||||
16*16
|
||||
};
|
||||
|
||||
static GFXDECODE_START( gfx_pc98lt )
|
||||
GFXDECODE_ENTRY( "kanji", 0x00000, gfx_8x8x1, 0x000, 0x01 )
|
||||
GFXDECODE_ENTRY( "kanji", 0x00000, gfx_16x16x1, 0x000, 0x01 )
|
||||
GFXDECODE_END
|
||||
|
||||
void pc98lt_state::machine_start()
|
||||
{
|
||||
// TODO: make this and NVRAM saving to co-exist
|
||||
// we have a 16-bit host bus with a banked NVRAM window that also has different sizes depending on the model,
|
||||
// may consider to encapsulate instead.
|
||||
const u32 bram_size = memregion("backup")->bytes() / 2;
|
||||
uint16_t *bram = (uint16_t *)memregion("backup")->base();
|
||||
m_bram_banks = (bram_size * 2) / 0x4000;
|
||||
m_bram_ptr = make_unique_clear<uint16_t[]>(bram_size);
|
||||
|
||||
for (int i = 0; i < bram_size; i++)
|
||||
m_bram_ptr[i] = bram[i];
|
||||
|
||||
m_kanji_bank->configure_entries( 0, 0x10, memregion("kanji")->base(), 0x4000);
|
||||
m_bram_bank->configure_entries( 0, m_bram_banks, m_bram_ptr.get(), 0x4000);
|
||||
m_romdrv_bank->configure_entries( 0, 0x10, memregion("romdrv")->base(), 0x10000);
|
||||
m_dict_bank->configure_entries( 0, 0x40, memregion("dict")->base(), 0x4000);
|
||||
|
||||
if (m_rtc != nullptr)
|
||||
{
|
||||
m_rtc->cs_w(1);
|
||||
m_rtc->oe_w(1);
|
||||
}
|
||||
m_sys_type = 0xc0 >> 6;
|
||||
|
||||
save_item(NAME(m_bram_bank_reg));
|
||||
save_item(NAME(m_romdrv_bank_reg));
|
||||
save_item(NAME(m_dict_bank_reg));
|
||||
save_pointer(NAME(m_bram_ptr), bram_size);
|
||||
}
|
||||
|
||||
void pc98ha_state::machine_start()
|
||||
{
|
||||
pc98lt_state::machine_start();
|
||||
const u32 ems_banks = 0x80;
|
||||
const u32 ems_size = (ems_banks * 0x4000) / 2;
|
||||
|
||||
m_ramdrv_bank->configure_entries(0, 0x80, memregion("ramdrv")->base(), 0x4000);
|
||||
|
||||
m_ems_ram = make_unique_clear<uint16_t[]>(ems_size);
|
||||
for (int i = 0; i < 4; i++)
|
||||
m_ems_banks[i]->configure_entries(0, ems_banks, m_ems_ram.get(), 0x4000);
|
||||
|
||||
save_item(NAME(m_ext_view_sel));
|
||||
save_pointer(NAME(m_ems_ram), ems_size);
|
||||
}
|
||||
|
||||
static void pc9801_floppies(device_slot_interface &device)
|
||||
{
|
||||
// device.option_add("525dd", FLOPPY_525_DD);
|
||||
device.option_add("525hd", FLOPPY_525_HD);
|
||||
// device.option_add("35hd", FLOPPY_35_HD);
|
||||
}
|
||||
|
||||
void pc98lt_state::lt_config(machine_config &config)
|
||||
{
|
||||
const XTAL xtal = XTAL(8'000'000);
|
||||
V50(config, m_maincpu, xtal); // µPD70216
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &pc98lt_state::lt_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &pc98lt_state::lt_io);
|
||||
// TODO: jumps off the weeds if divided by / 4 after timer check, DMA issue?
|
||||
// m_maincpu->set_tclk(xtal / 4);
|
||||
m_maincpu->set_tclk(xtal / 100);
|
||||
// m_maincpu->tout2_cb().set_inputline(m_maincpu, INPUT_LINE_IRQ2);
|
||||
// m_pit->out_handler<0>().set(m_pic1, FUNC(pic8259_device::ir0_w));
|
||||
// m_pit->out_handler<2>().set(m_sio, FUNC(i8251_device::write_txc));
|
||||
// m_pit->out_handler<2>().append(m_sio, FUNC(i8251_device::write_rxc));
|
||||
|
||||
// m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb));
|
||||
|
||||
PC9801_KBD(config, m_keyb, 53);
|
||||
m_keyb->irq_wr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ1);
|
||||
|
||||
I8255(config, m_ppi_sys, 0);
|
||||
// PC98LT/HA has no dips, port A acts as a RAM storage
|
||||
m_ppi_sys->in_pa_callback().set(m_ppi_sys, FUNC(i8255_device::pa_r));
|
||||
m_ppi_sys->in_pb_callback().set_ioport("SYSB");
|
||||
// m_ppi_sys->in_pc_callback().set_constant(0xa0); // 0x80 cpu triple fault reset flag?
|
||||
m_ppi_sys->out_pc_callback().set(FUNC(pc98lt_state::ppi_sys_beep_portc_w));
|
||||
|
||||
I8255(config, m_ppi_prn, 0);
|
||||
m_ppi_prn->in_pb_callback().set_ioport("PRNB");
|
||||
|
||||
UPD1990A(config, m_rtc);
|
||||
|
||||
UPD765A(config, m_fdc, 8'000'000, false, true);
|
||||
m_fdc->intrq_wr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ6);
|
||||
m_fdc->drq_wr_callback().set(m_maincpu, FUNC(v50_device::dreq_w<2>)).invert();
|
||||
// m_fdc->drq_wr_callback().set(m_maincpu, FUNC(v50_device::dreq_w<3>)).invert(); // 2dd
|
||||
FLOPPY_CONNECTOR(config, "upd765:0", pc9801_floppies, "525hd", pc9801_state::floppy_formats);
|
||||
FLOPPY_CONNECTOR(config, "upd765:1", pc9801_floppies, "525hd", pc9801_state::floppy_formats);
|
||||
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_LCD);
|
||||
// TODO: copied verbatim from base PC98, verify clock et al.
|
||||
m_screen->set_raw(21.0526_MHz_XTAL, 848, 0, 640, 440, 0, 400);
|
||||
m_screen->set_screen_update(FUNC(pc98lt_state::screen_update));
|
||||
// m_screen->screen_vblank().set(FUNC(pc9801_state::vrtc_irq));
|
||||
|
||||
PALETTE(config, m_palette, FUNC(pc98lt_state::lt_palette), 2);
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, m_palette, gfx_pc98lt);
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
BEEP(config, m_beeper, 2400).add_route(ALL_OUTPUTS, "mono", 0.05);
|
||||
}
|
||||
|
||||
void pc98ha_state::ha_config(machine_config &config)
|
||||
{
|
||||
lt_config(config);
|
||||
const XTAL xtal = XTAL(10'000'000);
|
||||
V50(config.replace(), m_maincpu, xtal);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &pc98ha_state::ha_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &pc98ha_state::ha_io);
|
||||
m_maincpu->set_tclk(xtal / 4);
|
||||
// m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb));
|
||||
|
||||
config.device_remove("rtc");
|
||||
UPD4991A(config, m_rtc_pio, 32'768);
|
||||
}
|
||||
|
||||
// all ROMs in both sets needs at least chip renaming, and I haven't seen a single PCB pic from the net.
|
||||
// dict.rom and ramdrv.bin definitely won't fit an even ROM size regardless,
|
||||
// also backup.bin may not be factory default.
|
||||
|
||||
ROM_START( pc98lt )
|
||||
ROM_REGION16_LE( 0x10000, "ipl", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "ipl.rom", 0x000000, 0x010000, BAD_DUMP CRC(b6a6a382) SHA1(3f1767cccc1ae02b3e48f6ee327d3ef4fad05750) )
|
||||
|
||||
ROM_REGION( 0x40000, "kanji", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "kanji.rom", 0x000000, 0x040000, BAD_DUMP CRC(26a81aa2) SHA1(bf12e40c608ef6ef1ac38f6b0b3ca79260a50cef) )
|
||||
|
||||
ROM_REGION16_LE( 0x10000, "backup", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "backup.bin", 0x000000, 0x010000, BAD_DUMP CRC(56d7ca00) SHA1(d17942e166f98af1d484e497e97d31da515973f7) )
|
||||
|
||||
ROM_REGION( 0x100000, "dict", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "dict.rom", 0x000000, 0x080000, BAD_DUMP CRC(421278ee) SHA1(f6066fc5085de521395ce1a8bb040536c1454c7e) )
|
||||
|
||||
ROM_REGION( 0x100000, "romdrv", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "romdrv.rom", 0x000000, 0x080000, BAD_DUMP CRC(282ff6eb) SHA1(f4833e49dd9089ec40f5e86a713e08cd8c598578) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pc98ha )
|
||||
ROM_REGION16_LE( 0x10000, "ipl", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "ipl.rom", 0x000000, 0x010000, BAD_DUMP CRC(2f552bb9) SHA1(7f53bf95181d65b2f9942285da669d92c61247a3) )
|
||||
|
||||
ROM_REGION( 0x40000, "kanji", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "kanji.rom", 0x000000, 0x040000, BAD_DUMP CRC(4be5ff2f) SHA1(261d28419a2ddebe3177a282952806d7bb036b40) )
|
||||
|
||||
ROM_REGION16_LE( 0x40000, "backup", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "backup.bin", 0x000000, 0x040000, BAD_DUMP CRC(3c5b2a99) SHA1(f8e2f5a4c7601d4e81d5e9c83621107ed3f5a29a) )
|
||||
|
||||
ROM_REGION( 0x100000, "dict", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "dict.rom", 0x000000, 0x0c0000, BAD_DUMP CRC(6dc8493c) SHA1(3e04cdc3403a814969b6590cd78e239e72677fe5) )
|
||||
|
||||
ROM_REGION( 0x100000, "romdrv", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "romdrv.rom", 0x000000, 0x100000, BAD_DUMP CRC(2f59127f) SHA1(932cb970c2b22408f7895dbf9df6dbc47f8e055b) )
|
||||
|
||||
// $00 filled with odd size
|
||||
ROM_REGION( 0x200000, "ramdrv", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "ramdrv.bin", 0x000000, 0x160000, BAD_DUMP CRC(f2cec994) SHA1(c986ad6d8f810ac0a9657c1af26b6fec712d56ed) )
|
||||
ROM_END
|
||||
|
||||
COMP( 1989, pc98lt, 0, 0, lt_config, pc98lt, pc98lt_state, empty_init, "NEC", "PC-98LT", MACHINE_NOT_WORKING )
|
||||
COMP( 1990, pc98ha, 0, 0, ha_config, pc98ha, pc98ha_state, empty_init, "NEC", "PC-98HA (Handy98)", MACHINE_NOT_WORKING )
|
@ -253,6 +253,7 @@ private:
|
||||
void fdc_8255_c_w(uint8_t data);
|
||||
uint8_t opn_porta_r();
|
||||
uint8_t opn_portb_r();
|
||||
void opna_map(address_map &map);
|
||||
IRQ_CALLBACK_MEMBER(pc8801_irq_callback);
|
||||
DECLARE_WRITE_LINE_MEMBER(pc8801_sound_irq);
|
||||
};
|
||||
|
@ -1,5 +1,11 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese,Carl
|
||||
/******************************************
|
||||
*
|
||||
* NEC PC-9801
|
||||
*
|
||||
******************************************/
|
||||
|
||||
#ifndef MAME_INCLUDES_PC9801_H
|
||||
#define MAME_INCLUDES_PC9801_H
|
||||
|
||||
@ -9,6 +15,7 @@
|
||||
#include "cpu/i86/i286.h"
|
||||
#include "cpu/i86/i86.h"
|
||||
#include "cpu/nec/nec.h"
|
||||
#include "cpu/nec/v5x.h"
|
||||
|
||||
#include "imagedev/floppy.h"
|
||||
#include "machine/am9517a.h"
|
||||
@ -17,12 +24,13 @@
|
||||
#include "machine/i8251.h"
|
||||
#include "machine/i8255.h"
|
||||
#include "machine/output_latch.h"
|
||||
#include "machine/pc9801_memsw.h"
|
||||
#include "machine/pic8259.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "machine/ram.h"
|
||||
#include "machine/timer.h"
|
||||
#include "machine/upd1990a.h"
|
||||
#include "machine/pc9801_memsw.h"
|
||||
#include "machine/upd4991a.h"
|
||||
#include "machine/upd765.h"
|
||||
|
||||
#include "bus/scsi/pc9801_sasi.h"
|
||||
@ -37,6 +45,7 @@
|
||||
#include "video/upd7220.h"
|
||||
|
||||
#include "bus/cbus/pc9801_26.h"
|
||||
#include "bus/cbus/pc9801_55.h"
|
||||
#include "bus/cbus/pc9801_86.h"
|
||||
#include "bus/cbus/pc9801_118.h"
|
||||
#include "bus/cbus/pc9801_amd98.h"
|
||||
@ -61,8 +70,7 @@
|
||||
#include "formats/dip_dsk.h"
|
||||
#include "formats/nfd_dsk.h"
|
||||
|
||||
|
||||
#define UPD1990A_TAG "upd1990a"
|
||||
#define RTC_TAG "rtc"
|
||||
#define UPD8251_TAG "upd8251"
|
||||
#define SASIBUS_TAG "sasi"
|
||||
|
||||
@ -77,156 +85,136 @@
|
||||
#define ANALOG_256_MODE (0x20 >> 1)
|
||||
#define GDC_IS_5MHz (0x84 >> 1)
|
||||
|
||||
class pc9801_state : public driver_device
|
||||
class pc98_base_state : public driver_device
|
||||
{
|
||||
public:
|
||||
pc9801_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_dmac(*this, "i8237"),
|
||||
m_pit8253(*this, "pit8253"),
|
||||
m_pic1(*this, "pic8259_master"),
|
||||
m_pic2(*this, "pic8259_slave"),
|
||||
m_ppi_sys(*this, "ppi8255_sys"),
|
||||
m_ppi_prn(*this, "ppi8255_prn"),
|
||||
m_fdc_2hd(*this, "upd765_2hd"),
|
||||
m_fdc_2dd(*this, "upd765_2dd"),
|
||||
m_rtc(*this, UPD1990A_TAG),
|
||||
m_memsw(*this, "memsw"),
|
||||
m_keyb(*this, "keyb"),
|
||||
m_sio(*this, UPD8251_TAG),
|
||||
m_hgdc1(*this, "upd7220_chr"),
|
||||
m_hgdc2(*this, "upd7220_btm"),
|
||||
m_sasibus(*this, SASIBUS_TAG),
|
||||
m_sasi_data_out(*this, "sasi_data_out"),
|
||||
m_sasi_data_in(*this, "sasi_data_in"),
|
||||
m_sasi_ctrl_in(*this, "sasi_ctrl_in"),
|
||||
m_ide(*this, "ide%u", 1U),
|
||||
m_video_ram_1(*this, "video_ram_1"),
|
||||
m_video_ram_2(*this, "video_ram_2"),
|
||||
m_ext_gvram(*this, "ext_gvram"),
|
||||
m_beeper(*this, "beeper"),
|
||||
m_dac(*this, "dac"),
|
||||
m_ram(*this, RAM_TAG),
|
||||
m_ipl(*this, "ipl_bank"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_palette(*this, "palette"),
|
||||
m_screen(*this, "screen")
|
||||
pc98_base_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_gfxdecode(*this, "gfxdecode")
|
||||
, m_palette(*this, "palette")
|
||||
, m_screen(*this, "screen")
|
||||
, m_keyb(*this, "keyb")
|
||||
, m_rtc(*this, RTC_TAG)
|
||||
, m_ppi_sys(*this, "ppi_sys")
|
||||
, m_ppi_prn(*this, "ppi_prn")
|
||||
, m_beeper(*this, "beeper")
|
||||
{
|
||||
}
|
||||
|
||||
DECLARE_CUSTOM_INPUT_MEMBER(system_type_r);
|
||||
|
||||
protected:
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<pc9801_kbd_device> m_keyb;
|
||||
optional_device<upd1990a_device> m_rtc;
|
||||
required_device<i8255_device> m_ppi_sys;
|
||||
required_device<i8255_device> m_ppi_prn;
|
||||
optional_device<beep_device> m_beeper;
|
||||
|
||||
void rtc_w(uint8_t data);
|
||||
void ppi_sys_beep_portc_w(uint8_t data);
|
||||
|
||||
static void floppy_formats(format_registration &fr);
|
||||
|
||||
u8 m_sys_type;
|
||||
};
|
||||
|
||||
class pc9801_state : public pc98_base_state
|
||||
{
|
||||
public:
|
||||
pc9801_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc98_base_state(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_ipl(*this, "ipl_bank")
|
||||
, m_dmac(*this, "i8237")
|
||||
, m_pit(*this, "pit")
|
||||
, m_dsw1(*this, "DSW1")
|
||||
, m_dsw2(*this, "DSW2")
|
||||
, m_ppi_mouse(*this, "ppi_mouse")
|
||||
, m_fdc_2hd(*this, "upd765_2hd")
|
||||
, m_fdc_2dd(*this, "upd765_2dd")
|
||||
, m_ram(*this, RAM_TAG)
|
||||
, m_hgdc(*this, "hgdc%d", 1)
|
||||
, m_video_ram(*this, "video_ram_%d", 1)
|
||||
, m_cbus(*this, "cbus%d", 0)
|
||||
, m_pic1(*this, "pic8259_master")
|
||||
, m_pic2(*this, "pic8259_slave")
|
||||
, m_memsw(*this, "memsw")
|
||||
, m_sio(*this, UPD8251_TAG)
|
||||
, m_sasibus(*this, SASIBUS_TAG)
|
||||
, m_sasi_data_out(*this, "sasi_data_out")
|
||||
, m_sasi_data_in(*this, "sasi_data_in")
|
||||
, m_sasi_ctrl_in(*this, "sasi_ctrl_in")
|
||||
{
|
||||
}
|
||||
|
||||
void pc9801(machine_config &config);
|
||||
|
||||
void pc9801vm(machine_config &config);
|
||||
|
||||
void pc9801ux(machine_config &config);
|
||||
void pc9801rs(machine_config &config);
|
||||
|
||||
void pc9801bx2(machine_config &config);
|
||||
|
||||
void pc9821(machine_config &config);
|
||||
void pc9821as(machine_config &config);
|
||||
void pc9821ap2(machine_config &config);
|
||||
void pc9821xa16(machine_config &config);
|
||||
void pc9821ra20(machine_config &config);
|
||||
void pc9821ra333(machine_config &config);
|
||||
void pc9821v20(machine_config &config);
|
||||
|
||||
void pc386m(machine_config &config);
|
||||
void pc486mu(machine_config &config);
|
||||
void pc486se(machine_config &config);
|
||||
|
||||
DECLARE_CUSTOM_INPUT_MEMBER(system_type_r);
|
||||
void init_pc9801_kanji();
|
||||
void init_pc9801vm_kanji();
|
||||
|
||||
// Device declarations
|
||||
protected:
|
||||
virtual void video_start() override;
|
||||
required_device<cpu_device> m_maincpu;
|
||||
optional_device<address_map_bank_device> m_ipl;
|
||||
required_device<am9517a_device> m_dmac;
|
||||
required_device<pit8253_device> m_pit;
|
||||
required_ioport m_dsw1;
|
||||
required_ioport m_dsw2;
|
||||
required_device<i8255_device> m_ppi_mouse;
|
||||
// TODO: should really be one FDC
|
||||
// (I/O $90-$93 is a "simplified" version)
|
||||
required_device<upd765a_device> m_fdc_2hd;
|
||||
optional_device<upd765a_device> m_fdc_2dd;
|
||||
optional_device<ram_device> m_ram;
|
||||
required_device_array<upd7220_device, 2> m_hgdc;
|
||||
required_shared_ptr_array<uint16_t, 2> m_video_ram;
|
||||
required_device_array<pc9801_slot_device, 2> m_cbus;
|
||||
required_device<pic8259_device> m_pic1;
|
||||
required_device<pic8259_device> m_pic2;
|
||||
private:
|
||||
required_device<pc9801_memsw_device> m_memsw;
|
||||
required_device<i8251_device> m_sio;
|
||||
optional_device<scsi_port_device> m_sasibus;
|
||||
optional_device<output_latch_device> m_sasi_data_out;
|
||||
optional_device<input_buffer_device> m_sasi_data_in;
|
||||
optional_device<input_buffer_device> m_sasi_ctrl_in;
|
||||
|
||||
// Infrastructure declaration
|
||||
protected:
|
||||
DECLARE_MACHINE_START(pc9801_common);
|
||||
DECLARE_MACHINE_RESET(pc9801_common);
|
||||
|
||||
void pc9801_keyboard(machine_config &config);
|
||||
void pc9801_mouse(machine_config &config);
|
||||
void pc9801_cbus(machine_config &config);
|
||||
void pc9801_sasi(machine_config &config);
|
||||
void pc9801_ide(machine_config &config);
|
||||
void pc9801_common(machine_config &config);
|
||||
void pc9801_pit_clock(machine_config &config, const XTAL clock);
|
||||
void config_floppy_525hd(machine_config &config);
|
||||
void config_floppy_35hd(machine_config &config);
|
||||
|
||||
private:
|
||||
static void cdrom_headphones(device_t *device);
|
||||
void pit_clock_config(machine_config &config, const XTAL clock);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<am9517a_device> m_dmac;
|
||||
required_device<pit8253_device> m_pit8253;
|
||||
required_device<pic8259_device> m_pic1;
|
||||
required_device<pic8259_device> m_pic2;
|
||||
required_device<i8255_device> m_ppi_sys;
|
||||
required_device<i8255_device> m_ppi_prn;
|
||||
required_device<upd765a_device> m_fdc_2hd;
|
||||
optional_device<upd765a_device> m_fdc_2dd;
|
||||
required_device<upd1990a_device> m_rtc;
|
||||
required_device<pc9801_memsw_device> m_memsw;
|
||||
required_device<pc9801_kbd_device> m_keyb;
|
||||
required_device<i8251_device> m_sio;
|
||||
required_device<upd7220_device> m_hgdc1;
|
||||
required_device<upd7220_device> m_hgdc2;
|
||||
optional_device<scsi_port_device> m_sasibus;
|
||||
optional_device<output_latch_device> m_sasi_data_out;
|
||||
optional_device<input_buffer_device> m_sasi_data_in;
|
||||
optional_device<input_buffer_device> m_sasi_ctrl_in;
|
||||
optional_device_array<ata_interface_device, 2> m_ide;
|
||||
required_shared_ptr<uint16_t> m_video_ram_1;
|
||||
required_shared_ptr<uint16_t> m_video_ram_2;
|
||||
optional_shared_ptr<uint32_t> m_ext_gvram;
|
||||
optional_device<beep_device> m_beeper;
|
||||
// optional_device<dac_1bit_device> m_dac;
|
||||
optional_device<speaker_sound_device> m_dac;
|
||||
optional_device<ram_device> m_ram;
|
||||
optional_device<address_map_bank_device> m_ipl;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<screen_device> m_screen;
|
||||
void pc9801_common_io(address_map &map);
|
||||
void ipl_bank(address_map &map);
|
||||
|
||||
void rtc_w(uint8_t data);
|
||||
void dmapg4_w(offs_t offset, uint8_t data);
|
||||
void dmapg8_w(offs_t offset, uint8_t data);
|
||||
void nmi_ctrl_w(offs_t offset, uint8_t data);
|
||||
void vrtc_clear_w(uint8_t data);
|
||||
void pc9801_video_ff_w(uint8_t data);
|
||||
uint8_t txt_scrl_r(offs_t offset);
|
||||
void txt_scrl_w(offs_t offset, uint8_t data);
|
||||
uint8_t grcg_r(offs_t offset);
|
||||
void grcg_w(offs_t offset, uint8_t data);
|
||||
void egc_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint8_t pc9801_a0_r(offs_t offset);
|
||||
void pc9801_a0_w(offs_t offset, uint8_t data);
|
||||
uint8_t fdc_2hd_ctrl_r();
|
||||
void fdc_2hd_ctrl_w(uint8_t data);
|
||||
uint8_t fdc_2dd_ctrl_r();
|
||||
void fdc_2dd_ctrl_w(uint8_t data);
|
||||
uint16_t tvram_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void tvram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint8_t gvram_r(offs_t offset);
|
||||
void gvram_w(offs_t offset, uint8_t data);
|
||||
void pc9801rs_mouse_freq_w(offs_t offset, uint8_t data);
|
||||
uint16_t grcg_gvram_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void grcg_gvram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t grcg_gvram0_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void grcg_gvram0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
u8 unk_r(offs_t offset);
|
||||
uint8_t f0_r(offs_t offset);
|
||||
|
||||
uint16_t pc9821_grcg_gvram_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void pc9821_grcg_gvram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t pc9821_grcg_gvram0_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void pc9821_grcg_gvram0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint8_t m_nmi_ff;
|
||||
|
||||
uint16_t upd7220_grcg_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void upd7220_grcg_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
virtual u8 ppi_prn_portb_r();
|
||||
|
||||
uint8_t ide_ctrl_r();
|
||||
void ide_ctrl_w(uint8_t data);
|
||||
uint16_t ide_cs0_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void ide_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t ide_cs1_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void ide_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
private:
|
||||
void pc9801_io(address_map &map);
|
||||
void pc9801_map(address_map &map);
|
||||
|
||||
void nmi_ctrl_w(offs_t offset, uint8_t data);
|
||||
|
||||
u8 ppi_sys_portb_r();
|
||||
|
||||
void sasi_data_w(uint8_t data);
|
||||
uint8_t sasi_data_r();
|
||||
@ -235,84 +223,46 @@ private:
|
||||
uint8_t sasi_status_r();
|
||||
void sasi_ctrl_w(uint8_t data);
|
||||
|
||||
uint8_t pc9801rs_knjram_r(offs_t offset);
|
||||
void pc9801rs_knjram_w(offs_t offset, uint8_t data);
|
||||
void pc9801rs_bank_w(offs_t offset, uint8_t data);
|
||||
uint8_t f0_r(offs_t offset);
|
||||
|
||||
uint8_t a20_ctrl_r(offs_t offset);
|
||||
void a20_ctrl_w(offs_t offset, uint8_t data);
|
||||
uint8_t fdc_mode_ctrl_r();
|
||||
void fdc_mode_ctrl_w(uint8_t data);
|
||||
// uint8_t pc9801rs_2dd_r();
|
||||
// void pc9801rs_2dd_w(uint8_t data);
|
||||
void pc9801rs_video_ff_w(offs_t offset, uint8_t data);
|
||||
void pc9801rs_a0_w(offs_t offset, uint8_t data);
|
||||
void pc9821_video_ff_w(offs_t offset, uint8_t data);
|
||||
uint8_t pc9821_a0_r(offs_t offset);
|
||||
void pc9821_a0_w(offs_t offset, uint8_t data);
|
||||
uint8_t access_ctrl_r(offs_t offset);
|
||||
void access_ctrl_w(offs_t offset, uint8_t data);
|
||||
uint8_t midi_r();
|
||||
// uint8_t winram_r();
|
||||
// void winram_w(uint8_t data);
|
||||
|
||||
DECLARE_MACHINE_START(pc9801f);
|
||||
DECLARE_MACHINE_RESET(pc9801f);
|
||||
|
||||
// PIC
|
||||
protected:
|
||||
uint8_t pic_r(offs_t offset);
|
||||
void pic_w(offs_t offset, uint8_t data);
|
||||
|
||||
uint8_t sdip_0_r(offs_t offset);
|
||||
uint8_t sdip_1_r(offs_t offset);
|
||||
uint8_t sdip_2_r(offs_t offset);
|
||||
uint8_t sdip_3_r(offs_t offset);
|
||||
uint8_t sdip_4_r(offs_t offset);
|
||||
uint8_t sdip_5_r(offs_t offset);
|
||||
uint8_t sdip_6_r(offs_t offset);
|
||||
uint8_t sdip_7_r(offs_t offset);
|
||||
uint8_t sdip_8_r(offs_t offset);
|
||||
uint8_t sdip_9_r(offs_t offset);
|
||||
uint8_t sdip_a_r(offs_t offset);
|
||||
uint8_t sdip_b_r(offs_t offset);
|
||||
|
||||
void sdip_0_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_1_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_2_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_3_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_4_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_5_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_6_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_7_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_8_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_9_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_a_w(offs_t offset, uint8_t data) ;
|
||||
void sdip_b_w(offs_t offset, uint8_t data) ;
|
||||
|
||||
uint8_t as_unkdev_data_r(offs_t offset);
|
||||
void as_unkdev_data_w(offs_t offset, uint8_t data);
|
||||
void as_unkdev_addr_w(offs_t offset, uint8_t data);
|
||||
|
||||
uint8_t window_bank_r(offs_t offset);
|
||||
void window_bank_w(offs_t offset, uint8_t data);
|
||||
uint16_t timestamp_r(offs_t offset);
|
||||
uint8_t ext2_video_ff_r();
|
||||
void ext2_video_ff_w(uint8_t data);
|
||||
|
||||
static void floppy_formats(format_registration &fr);
|
||||
UPD7220_DISPLAY_PIXELS_MEMBER( hgdc_display_pixels );
|
||||
UPD7220_DRAW_TEXT_LINE_MEMBER( hgdc_draw_text );
|
||||
|
||||
DECLARE_MACHINE_START(pc9801_common);
|
||||
DECLARE_MACHINE_START(pc9801f);
|
||||
DECLARE_MACHINE_START(pc9801rs);
|
||||
DECLARE_MACHINE_START(pc9801bx2);
|
||||
DECLARE_MACHINE_START(pc9821);
|
||||
DECLARE_MACHINE_START(pc9821ap2);
|
||||
DECLARE_MACHINE_RESET(pc9801_common);
|
||||
DECLARE_MACHINE_RESET(pc9801f);
|
||||
DECLARE_MACHINE_RESET(pc9801rs);
|
||||
DECLARE_MACHINE_RESET(pc9821);
|
||||
|
||||
void pc9801_palette(palette_device &palette) const;
|
||||
DECLARE_WRITE_LINE_MEMBER(vrtc_irq);
|
||||
private:
|
||||
uint8_t get_slave_ack(offs_t offset);
|
||||
|
||||
// FDC
|
||||
protected:
|
||||
uint8_t fdc_2hd_ctrl_r();
|
||||
void fdc_2hd_ctrl_w(uint8_t data);
|
||||
|
||||
u8 m_fdc_2hd_ctrl;
|
||||
|
||||
bool fdc_drive_ready_r(upd765a_device *fdc);
|
||||
private:
|
||||
DECLARE_WRITE_LINE_MEMBER(fdc_2dd_irq);
|
||||
|
||||
uint8_t fdc_2dd_ctrl_r();
|
||||
void fdc_2dd_ctrl_w(uint8_t data);
|
||||
|
||||
u8 m_fdc_2dd_ctrl;
|
||||
|
||||
// DMA
|
||||
protected:
|
||||
uint8_t m_dma_offset[4];
|
||||
uint8_t m_dma_autoinc[4];
|
||||
int m_dack;
|
||||
|
||||
private:
|
||||
void dmapg4_w(offs_t offset, uint8_t data);
|
||||
|
||||
inline void set_dma_channel(int channel, int state);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(dma_hrq_changed);
|
||||
DECLARE_WRITE_LINE_MEMBER(tc_w);
|
||||
uint8_t dma_read_byte(offs_t offset);
|
||||
@ -321,71 +271,73 @@ private:
|
||||
DECLARE_WRITE_LINE_MEMBER(dack1_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(dack2_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(dack3_w);
|
||||
void ppi_sys_beep_portc_w(uint8_t data);
|
||||
void ppi_sys_dac_portc_w(uint8_t data);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(fdc_2dd_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(pc9801rs_fdc_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(pc9801rs_fdc_drq);
|
||||
|
||||
uint8_t ppi_mouse_porta_r();
|
||||
void ppi_mouse_porta_w(uint8_t data);
|
||||
void ppi_mouse_portb_w(uint8_t data);
|
||||
void ppi_mouse_portc_w(uint8_t data);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER( mouse_irq_cb );
|
||||
uint8_t unk_r();
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
uint32_t a20_286(bool state);
|
||||
|
||||
void ipl_bank(address_map &map);
|
||||
void pc9801_common_io(address_map &map);
|
||||
void pc9801_io(address_map &map);
|
||||
void pc9801_map(address_map &map);
|
||||
void pc9801rs_io(address_map &map);
|
||||
void pc9801rs_map(address_map &map);
|
||||
void pc9801ux_io(address_map &map);
|
||||
void pc9801ux_map(address_map &map);
|
||||
void pc9821_io(address_map &map);
|
||||
void pc9821_map(address_map &map);
|
||||
void pc9821as_io(address_map &map);
|
||||
// Video
|
||||
protected:
|
||||
void upd7220_1_map(address_map &map);
|
||||
void upd7220_2_map(address_map &map);
|
||||
void upd7220_grcg_2_map(address_map &map);
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_VBIRQ
|
||||
};
|
||||
UPD7220_DISPLAY_PIXELS_MEMBER( hgdc_display_pixels );
|
||||
|
||||
virtual void video_start() override;
|
||||
void pc9801_palette(palette_device &palette) const;
|
||||
|
||||
inline void set_dma_channel(int channel, int state);
|
||||
uint8_t *m_char_rom;
|
||||
uint8_t *m_kanji_rom;
|
||||
|
||||
uint8_t m_dma_offset[4];
|
||||
uint8_t m_dma_autoinc[4];
|
||||
int m_dack;
|
||||
struct {
|
||||
uint8_t mode;
|
||||
uint8_t tile[4], tile_index;
|
||||
}m_grcg;
|
||||
|
||||
uint8_t m_video_ff[8],m_gfx_ff;
|
||||
enum
|
||||
{
|
||||
TIMER_VBIRQ,
|
||||
TIMER_FDC_TRIGGER
|
||||
};
|
||||
|
||||
uint16_t tvram_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void tvram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint8_t gvram_r(offs_t offset);
|
||||
void gvram_w(offs_t offset, uint8_t data);
|
||||
uint8_t grcg_r(offs_t offset);
|
||||
void grcg_w(offs_t offset, uint8_t data);
|
||||
|
||||
void pc9801_video_ff_w(uint8_t data);
|
||||
|
||||
uint16_t m_font_addr;
|
||||
uint16_t m_font_lr;
|
||||
uint8_t m_video_ff[8];
|
||||
// TODO: move to derived state
|
||||
uint8_t m_ex_video_ff[128];
|
||||
u8 m_vram_bank;
|
||||
u8 m_vram_disp;
|
||||
|
||||
private:
|
||||
UPD7220_DRAW_TEXT_LINE_MEMBER( hgdc_draw_text );
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(vrtc_irq);
|
||||
void vrtc_clear_w(uint8_t data);
|
||||
uint8_t txt_scrl_r(offs_t offset);
|
||||
void txt_scrl_w(offs_t offset, uint8_t data);
|
||||
|
||||
// TODO: make this virtual
|
||||
// (necessary for H98 high-reso mode, PC9821-E02, SVGA binds)
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
uint8_t m_font_line;
|
||||
std::unique_ptr<uint16_t[]> m_tvram;
|
||||
uint8_t m_gfx_ff;
|
||||
uint8_t m_txt_scroll_reg[8];
|
||||
uint8_t m_pal_clut[4];
|
||||
|
||||
std::unique_ptr<uint16_t[]> m_tvram;
|
||||
|
||||
uint16_t m_font_addr;
|
||||
uint8_t m_font_line;
|
||||
uint16_t m_font_lr;
|
||||
|
||||
uint8_t m_fdc_2dd_ctrl,m_fdc_2hd_ctrl;
|
||||
uint8_t m_nmi_ff;
|
||||
|
||||
uint8_t m_vram_bank;
|
||||
uint8_t m_vram_disp;
|
||||
|
||||
// SASI
|
||||
uint8_t m_sasi_data;
|
||||
int m_sasi_data_enable;
|
||||
uint8_t m_sasi_ctrl;
|
||||
|
||||
// Mouse
|
||||
protected:
|
||||
struct{
|
||||
uint8_t control;
|
||||
uint8_t lx, ly;
|
||||
@ -395,41 +347,130 @@ private:
|
||||
uint8_t freq_index;
|
||||
}m_mouse;
|
||||
|
||||
uint8_t m_ide_sel;
|
||||
private:
|
||||
u8 ppi_mouse_porta_r();
|
||||
void ppi_mouse_porta_w(uint8_t data);
|
||||
void ppi_mouse_portb_w(uint8_t data);
|
||||
void ppi_mouse_portc_w(uint8_t data);
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER( mouse_irq_cb );
|
||||
};
|
||||
|
||||
/**********************************************************
|
||||
*
|
||||
* VM class
|
||||
*
|
||||
**********************************************************/
|
||||
|
||||
class pc9801vm_state : public pc9801_state
|
||||
{
|
||||
public:
|
||||
pc9801vm_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9801_state(mconfig, type, tag)
|
||||
, m_dsw3(*this, "DSW3")
|
||||
, m_ide(*this, "ide%u", 1U)
|
||||
, m_dac1bit(*this, "dac1bit")
|
||||
{
|
||||
}
|
||||
|
||||
void pc9801vm(machine_config &config);
|
||||
|
||||
void pc9801ux(machine_config &config);
|
||||
void pc9801vx(machine_config &config);
|
||||
void pc9801rs(machine_config &config);
|
||||
|
||||
void init_pc9801vm_kanji();
|
||||
|
||||
protected:
|
||||
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
void pc9801rs_io(address_map &map);
|
||||
void pc9801rs_map(address_map &map);
|
||||
|
||||
uint16_t grcg_gvram_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void grcg_gvram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t grcg_gvram0_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void grcg_gvram0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
uint16_t upd7220_grcg_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void upd7220_grcg_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
void upd7220_grcg_2_map(address_map &map);
|
||||
|
||||
void pc9801_ide(machine_config &config);
|
||||
static void cdrom_headphones(device_t *device);
|
||||
|
||||
void pc9801rs_video_ff_w(offs_t offset, uint8_t data);
|
||||
void pc9801rs_a0_w(offs_t offset, uint8_t data);
|
||||
|
||||
uint8_t ide_ctrl_r();
|
||||
void ide_ctrl_w(uint8_t data);
|
||||
uint16_t ide_cs0_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void ide_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t ide_cs1_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void ide_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
void dmapg8_w(offs_t offset, uint8_t data);
|
||||
|
||||
uint16_t timestamp_r(offs_t offset);
|
||||
|
||||
void ppi_sys_dac_portc_w(uint8_t data);
|
||||
virtual u8 ppi_prn_portb_r() override;
|
||||
|
||||
DECLARE_MACHINE_START(pc9801rs);
|
||||
DECLARE_MACHINE_RESET(pc9801rs);
|
||||
|
||||
u8 m_gate_a20;
|
||||
u8 m_dma_access_ctrl;
|
||||
u8 m_ide_sel;
|
||||
|
||||
// starting from PC9801VF/U buzzer is substituted with a DAC1BIT
|
||||
bool m_dac_disable;
|
||||
bool m_dac1bit_disable;
|
||||
|
||||
/* PC9801RS specific, move to specific state */
|
||||
uint8_t m_gate_a20; //A20 line
|
||||
uint8_t m_access_ctrl; // DMA related
|
||||
uint8_t m_fdc_ctrl;
|
||||
uint8_t m_ex_video_ff[128];
|
||||
required_ioport m_dsw3;
|
||||
private:
|
||||
optional_device_array<ata_interface_device, 2> m_ide;
|
||||
// optional_device<dac_1bit_device> m_dac1bit;
|
||||
required_device<speaker_sound_device> m_dac1bit;
|
||||
|
||||
void pc9801ux_io(address_map &map);
|
||||
void pc9801ux_map(address_map &map);
|
||||
|
||||
uint32_t a20_286(bool state);
|
||||
|
||||
uint8_t pc9801rs_knjram_r(offs_t offset);
|
||||
void pc9801rs_knjram_w(offs_t offset, uint8_t data);
|
||||
void pc9801rs_bank_w(offs_t offset, uint8_t data);
|
||||
uint8_t midi_r();
|
||||
|
||||
// 286-based machines except for PC98XA
|
||||
u8 dma_access_ctrl_r(offs_t offset);
|
||||
void dma_access_ctrl_w(offs_t offset, u8 data);
|
||||
|
||||
uint8_t a20_ctrl_r(offs_t offset);
|
||||
void a20_ctrl_w(offs_t offset, uint8_t data);
|
||||
|
||||
template <unsigned port> u8 fdc_2hd_2dd_ctrl_r();
|
||||
template <unsigned port> void fdc_2hd_2dd_ctrl_w(u8 data);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
|
||||
|
||||
emu_timer *m_fdc_timer;
|
||||
|
||||
u8 m_fdc_mode;
|
||||
u8 fdc_mode_r();
|
||||
void fdc_mode_w(u8 data);
|
||||
void fdc_set_density_mode(bool is_2hd);
|
||||
|
||||
protected:
|
||||
struct {
|
||||
uint8_t pal_entry;
|
||||
uint8_t r[16],g[16],b[16];
|
||||
}m_analog16;
|
||||
struct {
|
||||
uint8_t pal_entry;
|
||||
uint8_t r[0x100],g[0x100],b[0x100];
|
||||
uint16_t bank[2];
|
||||
}m_analog256;
|
||||
struct {
|
||||
uint8_t mode;
|
||||
uint8_t tile[4], tile_index;
|
||||
}m_grcg;
|
||||
|
||||
void egc_blit_w(uint32_t offset, uint16_t data, uint16_t mem_mask);
|
||||
uint16_t egc_blit_r(uint32_t offset, uint16_t mem_mask);
|
||||
|
||||
|
||||
/* PC9821 specific */
|
||||
uint8_t m_sdip[24], m_sdip_bank;
|
||||
uint8_t m_unkdev0468[0x100], m_unkdev0468_addr;
|
||||
uint8_t m_pc9821_window_bank;
|
||||
uint8_t m_ext2_ff;
|
||||
uint8_t m_sys_type;
|
||||
|
||||
private:
|
||||
// EGC, PC9801VX onward
|
||||
struct {
|
||||
uint16_t regs[8];
|
||||
uint16_t pat[4];
|
||||
@ -440,13 +481,76 @@ private:
|
||||
bool init;
|
||||
} m_egc;
|
||||
|
||||
uint16_t m_pc9821_256vram_bank;
|
||||
protected:
|
||||
void egc_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
private:
|
||||
void egc_blit_w(uint32_t offset, uint16_t data, uint16_t mem_mask);
|
||||
uint16_t egc_blit_r(uint32_t offset, uint16_t mem_mask);
|
||||
|
||||
uint8_t m_sdip_read(uint16_t port, uint8_t sdip_offset);
|
||||
void m_sdip_write(uint16_t port, uint8_t sdip_offset,uint8_t data);
|
||||
uint16_t egc_do_partial_op(int plane, uint16_t src, uint16_t pat, uint16_t dst) const;
|
||||
uint16_t egc_shift(int plane, uint16_t val);
|
||||
uint16_t egc_color_pat(int plane) const;
|
||||
|
||||
protected:
|
||||
u8 mouse_freq_r(offs_t offset);
|
||||
void mouse_freq_w(offs_t offset, u8 data);
|
||||
|
||||
u8 ppi_mouse_portb_r();
|
||||
u8 ppi_mouse_portc_r();
|
||||
};
|
||||
|
||||
class pc9801us_state : public pc9801vm_state
|
||||
{
|
||||
public:
|
||||
pc9801us_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9801vm_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
void pc9801us(machine_config &config);
|
||||
|
||||
protected:
|
||||
void pc9801us_io(address_map &map);
|
||||
|
||||
DECLARE_MACHINE_START(pc9801us);
|
||||
|
||||
|
||||
// SDIP, PC9801DA onward
|
||||
protected:
|
||||
u8 m_sdip[24];
|
||||
private:
|
||||
u8 m_sdip_bank;
|
||||
template<unsigned port> u8 sdip_r(offs_t offset);
|
||||
template<unsigned port> void sdip_w(offs_t offset, u8 data);
|
||||
void sdip_bank_w(offs_t offset, u8 data);
|
||||
};
|
||||
|
||||
/**********************************************************
|
||||
*
|
||||
* BX class ("98Fellow")
|
||||
*
|
||||
**********************************************************/
|
||||
|
||||
class pc9801bx_state : public pc9801us_state
|
||||
{
|
||||
public:
|
||||
pc9801bx_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9801us_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void pc9801bx2(machine_config &config);
|
||||
|
||||
protected:
|
||||
void pc9801bx2_io(address_map &map);
|
||||
void pc9801bx2_map(address_map &map);
|
||||
|
||||
DECLARE_MACHINE_START(pc9801bx2);
|
||||
DECLARE_MACHINE_RESET(pc9801bx2);
|
||||
|
||||
private:
|
||||
u8 i486_cpu_mode_r(offs_t offset);
|
||||
u8 gdc_31kHz_r(offs_t offset);
|
||||
void gdc_31kHz_w(offs_t offset, u8 data);
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_PC9801_H
|
||||
|
58
src/mame/includes/pc9801_epson.h
Normal file
58
src/mame/includes/pc9801_epson.h
Normal file
@ -0,0 +1,58 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese,Carl
|
||||
/******************************************
|
||||
*
|
||||
* Epson PC98 clones
|
||||
*
|
||||
******************************************/
|
||||
|
||||
#ifndef MAME_INCLUDES_PC9801_EPSON_H
|
||||
#define MAME_INCLUDES_PC9801_EPSON_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "includes/pc9801.h"
|
||||
|
||||
class pc98_epson_state : public pc9801vm_state
|
||||
{
|
||||
public:
|
||||
pc98_epson_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9801vm_state(mconfig, type, tag)
|
||||
, m_shadow_ipl(*this, "shadow_ipl_%u", 0)
|
||||
{
|
||||
}
|
||||
|
||||
void pc386m(machine_config &config);
|
||||
void pc486mu(machine_config &config);
|
||||
void pc486se(machine_config &config);
|
||||
|
||||
protected:
|
||||
void pc386m_ipl_bank(address_map &map);
|
||||
|
||||
void pc386m_io(address_map &map);
|
||||
void pc386m_map(address_map &map);
|
||||
void pc486se_io(address_map &map);
|
||||
void pc486se_map(address_map &map);
|
||||
|
||||
// virtual void machine_start() override;
|
||||
// virtual void machine_reset() override;
|
||||
|
||||
DECLARE_MACHINE_START(pc98_epson);
|
||||
DECLARE_MACHINE_RESET(pc98_epson);
|
||||
|
||||
private:
|
||||
void epson_ipl_bank_w(offs_t offset, u8 data);
|
||||
void epson_itf_bank_w(offs_t offset, u8 data);
|
||||
void epson_a20_w(offs_t offset, u8 data);
|
||||
void epson_vram_bank_w(offs_t offset, u8 data);
|
||||
|
||||
required_shared_ptr_array<uint16_t, 2> m_shadow_ipl;
|
||||
|
||||
template <unsigned which> void shadow_ipl_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
u8 m_shadow_ipl_bank;
|
||||
bool m_itf_bank_enable;
|
||||
// u8 m_itf_bank;
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_PC9801_EPSON_H
|
193
src/mame/includes/pc9821.h
Normal file
193
src/mame/includes/pc9821.h
Normal file
@ -0,0 +1,193 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese,Carl
|
||||
/******************************************
|
||||
*
|
||||
* NEC PC-9821
|
||||
*
|
||||
******************************************/
|
||||
|
||||
#ifndef MAME_INCLUDES_PC9821_H
|
||||
#define MAME_INCLUDES_PC9821_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "includes/pc9801.h"
|
||||
|
||||
class pc9821_state : public pc9801bx_state
|
||||
{
|
||||
public:
|
||||
pc9821_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9801bx_state(mconfig, type, tag)
|
||||
, m_ext_gvram(*this, "ext_gvram")
|
||||
{
|
||||
}
|
||||
|
||||
void pc9821(machine_config &config);
|
||||
|
||||
protected:
|
||||
void pc9821_io(address_map &map);
|
||||
void pc9821_map(address_map &map);
|
||||
|
||||
DECLARE_MACHINE_START(pc9821);
|
||||
DECLARE_MACHINE_RESET(pc9821);
|
||||
private:
|
||||
required_shared_ptr<uint32_t> m_ext_gvram;
|
||||
|
||||
uint16_t pc9821_grcg_gvram_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void pc9821_grcg_gvram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t pc9821_grcg_gvram0_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void pc9821_grcg_gvram0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void pc9821_video_ff_w(offs_t offset, uint8_t data);
|
||||
uint8_t pc9821_a0_r(offs_t offset);
|
||||
void pc9821_a0_w(offs_t offset, uint8_t data);
|
||||
uint8_t window_bank_r(offs_t offset);
|
||||
void window_bank_w(offs_t offset, uint8_t data);
|
||||
uint8_t ext2_video_ff_r();
|
||||
void ext2_video_ff_w(uint8_t data);
|
||||
|
||||
uint8_t m_pc9821_window_bank;
|
||||
uint8_t m_ext2_ff;
|
||||
|
||||
struct {
|
||||
uint8_t pal_entry;
|
||||
uint8_t r[0x100],g[0x100],b[0x100];
|
||||
uint16_t bank[2];
|
||||
}m_analog256;
|
||||
|
||||
void pc9821_egc_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
|
||||
UPD7220_DISPLAY_PIXELS_MEMBER( pegc_display_pixels );
|
||||
};
|
||||
|
||||
// MATE A
|
||||
|
||||
class pc9821_mate_a_state : public pc9821_state
|
||||
{
|
||||
public:
|
||||
pc9821_mate_a_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9821_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void pc9821as(machine_config &config);
|
||||
void pc9821ap2(machine_config &config);
|
||||
|
||||
protected:
|
||||
void pc9821as_io(address_map &map);
|
||||
|
||||
private:
|
||||
DECLARE_MACHINE_START(pc9821ap2);
|
||||
|
||||
// Ap, As, Ae only
|
||||
u8 ext_sdip_data_r(offs_t offset);
|
||||
void ext_sdip_data_w(offs_t offset, u8 data);
|
||||
void ext_sdip_address_w(offs_t offset, u8 data);
|
||||
void ext_sdip_access_w(offs_t offset, u8 data);
|
||||
|
||||
uint8_t m_ext_sdip[0x100], m_ext_sdip_addr;
|
||||
};
|
||||
|
||||
// CanBe
|
||||
|
||||
class pc9821_canbe_state : public pc9821_state
|
||||
{
|
||||
public:
|
||||
pc9821_canbe_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9821_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void pc9821ce2(machine_config &config);
|
||||
void pc9821cx3(machine_config &config);
|
||||
|
||||
protected:
|
||||
void pc9821cx3_map(address_map &map);
|
||||
void pc9821cx3_io(address_map &map);
|
||||
|
||||
private:
|
||||
void remote_addr_w(offs_t offset, u8 data);
|
||||
u8 remote_data_r(offs_t offset);
|
||||
void remote_data_w(offs_t offset, u8 data);
|
||||
|
||||
DECLARE_MACHINE_START(pc9821_canbe);
|
||||
|
||||
struct {
|
||||
u8 index;
|
||||
}m_remote;
|
||||
};
|
||||
|
||||
// class pc9821_cereb_state : public pc9821_canbe_state
|
||||
|
||||
// Mate B
|
||||
|
||||
// class pc9821_mate_b_state : public pc9821_state
|
||||
|
||||
// Mate X (NB: should be subclass of Mate B)
|
||||
|
||||
class pc9821_mate_x_state : public pc9821_state
|
||||
{
|
||||
public:
|
||||
pc9821_mate_x_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9821_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void pc9821xa16(machine_config &config);
|
||||
void pc9821xs(machine_config &config);
|
||||
};
|
||||
|
||||
// Mate R
|
||||
|
||||
class pc9821_mate_r_state : public pc9821_mate_x_state
|
||||
{
|
||||
public:
|
||||
pc9821_mate_r_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9821_mate_x_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void pc9821ra20(machine_config &config);
|
||||
void pc9821ra266(machine_config &config);
|
||||
void pc9821ra333(machine_config &config);
|
||||
};
|
||||
|
||||
class pc9821_valuestar_state : public pc9821_mate_x_state
|
||||
{
|
||||
public:
|
||||
pc9821_valuestar_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9821_mate_x_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void pc9821v13(machine_config &config);
|
||||
void pc9821v20(machine_config &config);
|
||||
};
|
||||
|
||||
// 9821NOTE
|
||||
|
||||
class pc9821_note_state : public pc9821_state
|
||||
{
|
||||
public:
|
||||
pc9821_note_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9821_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void pc9821ne(machine_config &config);
|
||||
};
|
||||
|
||||
class pc9821_note_lavie_state : public pc9821_note_state
|
||||
{
|
||||
public:
|
||||
pc9821_note_lavie_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc9821_note_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void pc9821nr15(machine_config &config);
|
||||
void pc9821nr166(machine_config &config);
|
||||
void pc9821nw150(machine_config &config);
|
||||
};
|
||||
|
||||
|
||||
#endif // MAME_INCLUDES_PC9821_H
|
104
src/mame/includes/pc98ha.h
Normal file
104
src/mame/includes/pc98ha.h
Normal file
@ -0,0 +1,104 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Angelo Salese
|
||||
/******************************************
|
||||
*
|
||||
* NEC "Handy98" 1st gen portables
|
||||
*
|
||||
******************************************/
|
||||
|
||||
#ifndef MAME_INCLUDES_PC98HA_H
|
||||
#define MAME_INCLUDES_PC98HA_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "includes/pc9801.h"
|
||||
|
||||
class pc98lt_state : public pc98_base_state
|
||||
{
|
||||
public:
|
||||
pc98lt_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc98_base_state(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_fdc(*this, "upd765")
|
||||
, m_gvram(*this, "gvram")
|
||||
, m_bram_bank(*this, "bram_bank")
|
||||
, m_dict_bank(*this, "dict_bank")
|
||||
, m_kanji_bank(*this, "kanji_bank")
|
||||
, m_romdrv_bank(*this, "romdrv_bank")
|
||||
{
|
||||
}
|
||||
|
||||
void lt_config(machine_config &config);
|
||||
|
||||
protected:
|
||||
void lt_map(address_map &map);
|
||||
void lt_io(address_map &map);
|
||||
|
||||
required_device<v50_device> m_maincpu;
|
||||
|
||||
virtual void machine_start() override;
|
||||
// virtual void machine_reset() override;
|
||||
private:
|
||||
required_device<upd765a_device> m_fdc;
|
||||
required_shared_ptr<uint16_t> m_gvram;
|
||||
std::unique_ptr<uint16_t[]> m_bram_ptr;
|
||||
required_memory_bank m_bram_bank;
|
||||
required_memory_bank m_dict_bank;
|
||||
required_memory_bank m_kanji_bank;
|
||||
required_memory_bank m_romdrv_bank;
|
||||
|
||||
void lt_palette(palette_device &palette) const;
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
u8 power_status_r();
|
||||
void power_control_w(offs_t offset, u8 data);
|
||||
u8 floppy_mode_r(offs_t offset);
|
||||
void floppy_mode_w(offs_t offset, u8 data);
|
||||
u8 fdc_ctrl_r(offs_t offset);
|
||||
void fdc_ctrl_w(offs_t offset, u8 data);
|
||||
|
||||
u8 m_romdrv_bank_reg;
|
||||
u8 m_bram_banks;
|
||||
u8 m_bram_bank_reg;
|
||||
u8 m_dict_bank_reg;
|
||||
|
||||
u8 m_floppy_mode;
|
||||
u8 m_fdc_ctrl;
|
||||
};
|
||||
|
||||
class pc98ha_state : public pc98lt_state
|
||||
{
|
||||
public:
|
||||
pc98ha_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: pc98lt_state(mconfig, type, tag)
|
||||
, m_ems_banks(*this, "ems_bank%u", 1U)
|
||||
, m_ext_view(*this, "ext_io")
|
||||
, m_ramdrv_bank(*this, "ramdrv_bank")
|
||||
, m_rtc_pio(*this, "prtc")
|
||||
{
|
||||
}
|
||||
|
||||
void ha_config(machine_config &config);
|
||||
|
||||
protected:
|
||||
void ha_map(address_map &map);
|
||||
void ha_io(address_map &map);
|
||||
|
||||
virtual void machine_start() override;
|
||||
private:
|
||||
required_memory_bank_array<4> m_ems_banks;
|
||||
memory_view m_ext_view;
|
||||
required_memory_bank m_ramdrv_bank;
|
||||
required_device<upd4991a_device> m_rtc_pio;
|
||||
|
||||
std::unique_ptr<uint16_t[]> m_ems_ram;
|
||||
|
||||
void ext_view_bank_w(offs_t offset, u8 data);
|
||||
void ext_view_sel_w(offs_t offset, u8 data);
|
||||
void ems_bank_w(offs_t offset, u8 data);
|
||||
u8 memcard_status_1_r(offs_t offset);
|
||||
u8 memcard_status_2_r(offs_t offset);
|
||||
u8 m_ext_view_sel;
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_PC9801_EPSON_H
|
@ -33849,28 +33849,43 @@ pc8801mk2sr //
|
||||
pc88va //
|
||||
pc88va2 //
|
||||
|
||||
@source:pc98ha.cpp
|
||||
pc98lt // 1989
|
||||
pc98ha // 1990
|
||||
|
||||
@source:pc9801.cpp
|
||||
pc386m //
|
||||
pc486mu //
|
||||
pc486se // 1993
|
||||
pc9801bx2 // 1993
|
||||
pc9801f // 1983
|
||||
pc9801rs // 1989
|
||||
pc9801rx // 1988
|
||||
pc9801us // 1992
|
||||
pc9801ux // 1987
|
||||
pc9801vm // 1985
|
||||
pc9801vm11 //
|
||||
pc9821 //
|
||||
pc9821ap2 //
|
||||
pc9821as //
|
||||
pc9821ce2 //
|
||||
pc9821ne //
|
||||
pc9821ra20 //
|
||||
pc9821ra333 //
|
||||
pc9821v13 //
|
||||
pc9821v20 //
|
||||
pc9821xa16 //
|
||||
pc9821xs //
|
||||
pc9801vm11 // 1985
|
||||
pc9801vx // 1986
|
||||
|
||||
@source:pc9801_epson.cpp
|
||||
pc386m // 1990
|
||||
pc486se // 1993
|
||||
pc486mu // 1994
|
||||
|
||||
@source:pc9821.cpp
|
||||
pc9821 // 1992
|
||||
pc9821ap2 // 1993
|
||||
pc9821as // 1993
|
||||
pc9821ce2 // 1994
|
||||
pc9821cx3 // 1995
|
||||
pc9821ne // 1994
|
||||
pc9821nr15 // 1996
|
||||
pc9821nr166 // 1997
|
||||
pc9821nw150 // 1997
|
||||
pc9821ra20 // 1996
|
||||
pc9821ra266 // 1997
|
||||
pc9821ra333 // 1998
|
||||
pc9821v13 // 1998
|
||||
pc9821v20 // 1998
|
||||
pc9821xa16 // 1996
|
||||
pc9821xs // 1994
|
||||
|
||||
@source:pcat_dyn.cpp
|
||||
toursol // (c) 1995 Dynamo
|
||||
|
@ -30,8 +30,10 @@ uint32_t pc9801_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap
|
||||
bitmap.fill(m_palette->black_pen(), cliprect);
|
||||
|
||||
/* graphics */
|
||||
m_hgdc2->screen_update(screen, bitmap, cliprect);
|
||||
m_hgdc1->screen_update(screen, bitmap, cliprect);
|
||||
if(m_video_ff[DISPLAY_REG] != 0)
|
||||
m_hgdc[1]->screen_update(screen, bitmap, cliprect);
|
||||
m_hgdc[0]->screen_update(screen, bitmap, cliprect);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -46,39 +48,21 @@ UPD7220_DISPLAY_PIXELS_MEMBER( pc9801_state::hgdc_display_pixels )
|
||||
{
|
||||
rgb_t const *const palette = m_palette->palette()->entry_list_raw();
|
||||
|
||||
if(m_video_ff[DISPLAY_REG] == 0) //screen is off
|
||||
return;
|
||||
|
||||
uint8_t colors16_mode = (m_ex_video_ff[ANALOG_16_MODE]) ? 16 : 8;
|
||||
|
||||
if(m_ex_video_ff[ANALOG_256_MODE])
|
||||
for(int xi=0;xi<16;xi++)
|
||||
{
|
||||
uint8_t *ext_gvram = (uint8_t *)m_ext_gvram.target();
|
||||
for(int xi=0;xi<16;xi++)
|
||||
{
|
||||
int res_x = x + xi;
|
||||
int res_y = y;
|
||||
int res_x = x + xi;
|
||||
int res_y = y;
|
||||
|
||||
uint8_t pen = ext_gvram[(address)*16+xi+(m_vram_disp*0x40000)];
|
||||
uint8_t pen;
|
||||
|
||||
bitmap.pix(res_y, res_x) = palette[pen + 0x20];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int xi=0;xi<16;xi++)
|
||||
{
|
||||
int res_x = x + xi;
|
||||
int res_y = y;
|
||||
|
||||
uint8_t pen;
|
||||
pen = ((m_video_ram_2[((address & 0x3fff) + (0x4000) + ((m_vram_disp*0x20000)>>1))] >> xi) & 1) ? 1 : 0;
|
||||
pen|= ((m_video_ram_2[((address & 0x3fff) + (0x8000) + ((m_vram_disp*0x20000)>>1))] >> xi) & 1) ? 2 : 0;
|
||||
pen|= ((m_video_ram_2[((address & 0x3fff) + (0xc000) + ((m_vram_disp*0x20000)>>1))] >> xi) & 1) ? 4 : 0;
|
||||
if(m_ex_video_ff[ANALOG_16_MODE])
|
||||
pen|= ((m_video_ram_2[((address & 0x3fff) + (0) + ((m_vram_disp*0x20000)>>1))] >> xi) & 1) ? 8 : 0;
|
||||
bitmap.pix(res_y, res_x) = palette[pen + colors16_mode];
|
||||
}
|
||||
pen = ((m_video_ram[1][((address & 0x3fff) + (0x4000) + ((m_vram_disp*0x20000)>>1))] >> xi) & 1) ? 1 : 0;
|
||||
pen|= ((m_video_ram[1][((address & 0x3fff) + (0x8000) + ((m_vram_disp*0x20000)>>1))] >> xi) & 1) ? 2 : 0;
|
||||
pen|= ((m_video_ram[1][((address & 0x3fff) + (0xc000) + ((m_vram_disp*0x20000)>>1))] >> xi) & 1) ? 4 : 0;
|
||||
if(m_ex_video_ff[ANALOG_16_MODE])
|
||||
pen|= ((m_video_ram[1][((address & 0x3fff) + (0) + ((m_vram_disp*0x20000)>>1))] >> xi) & 1) ? 8 : 0;
|
||||
bitmap.pix(res_y, res_x) = palette[pen + colors16_mode];
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,8 +91,8 @@ UPD7220_DRAW_TEXT_LINE_MEMBER( pc9801_state::hgdc_draw_text )
|
||||
uint8_t kanji_sel = 0;
|
||||
uint8_t kanji_lr = 0;
|
||||
|
||||
uint16_t tile = m_video_ram_1[tile_addr & 0xfff] & 0xff;
|
||||
uint8_t knj_tile = m_video_ram_1[tile_addr & 0xfff] >> 8;
|
||||
uint16_t tile = m_video_ram[0][tile_addr & 0xfff] & 0xff;
|
||||
uint8_t knj_tile = m_video_ram[0][tile_addr & 0xfff] >> 8;
|
||||
if(knj_tile)
|
||||
{
|
||||
/* Note: bit 7 doesn't really count, if a kanji is enabled then the successive tile is always the second part of it.
|
||||
@ -135,7 +119,7 @@ UPD7220_DRAW_TEXT_LINE_MEMBER( pc9801_state::hgdc_draw_text )
|
||||
{
|
||||
/* Rori Rori Rolling definitely uses different colors for brake stop PCG elements,
|
||||
assume that all attributes are recalculated on different strips */
|
||||
uint8_t attr = (m_video_ram_1[((tile_addr+kanji_lr) & 0xfff) | 0x1000] & 0xff);
|
||||
uint8_t attr = (m_video_ram[0][((tile_addr+kanji_lr) & 0xfff) | 0x1000] & 0xff);
|
||||
|
||||
uint8_t secret = (attr & 1) ^ 1;
|
||||
uint8_t blink = attr & 2;
|
||||
@ -310,7 +294,7 @@ uint8_t pc9801_state::pc9801_a0_r(offs_t offset)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x02:
|
||||
return m_hgdc2->read((offset & 2) >> 1);
|
||||
return m_hgdc[1]->read((offset & 2) >> 1);
|
||||
/* TODO: double check these two */
|
||||
case 0x04:
|
||||
return m_vram_disp & 1;
|
||||
@ -355,7 +339,7 @@ void pc9801_state::pc9801_a0_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x02:
|
||||
m_hgdc2->write((offset & 2) >> 1,data);
|
||||
m_hgdc[1]->write((offset & 2) >> 1,data);
|
||||
return;
|
||||
case 0x04:
|
||||
m_vram_disp = data & 1;
|
||||
@ -452,7 +436,7 @@ void pc9801_state::tvram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
else if(m_video_ff[MEMSW_REG] && ACCESSING_BITS_0_7)
|
||||
m_memsw->write(offset & 0x0f, data & 0xff);
|
||||
|
||||
COMBINE_DATA(&m_video_ram_1[offset]); //TODO: check me
|
||||
COMBINE_DATA(&m_video_ram[0][offset]); //TODO: check me
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
@ -464,15 +448,15 @@ void pc9801_state::tvram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
/* +0x8000 is trusted (bank 0 is actually used by 16 colors mode) */
|
||||
uint8_t pc9801_state::gvram_r(offs_t offset)
|
||||
{
|
||||
return bitswap<8>(m_video_ram_2[(offset>>1)+0x04000+m_vram_bank*0x10000] >> ((offset & 1) << 3),0,1,2,3,4,5,6,7);
|
||||
return bitswap<8>(m_video_ram[1][(offset>>1)+0x04000+m_vram_bank*0x10000] >> ((offset & 1) << 3),0,1,2,3,4,5,6,7);
|
||||
}
|
||||
|
||||
void pc9801_state::gvram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
uint16_t ram = m_video_ram_2[(offset>>1)+0x04000+m_vram_bank*0x10000];
|
||||
uint16_t ram = m_video_ram[1][(offset>>1)+0x04000+m_vram_bank*0x10000];
|
||||
int mask = (offset & 1) << 3;
|
||||
data = bitswap<8>(data,0,1,2,3,4,5,6,7);
|
||||
m_video_ram_2[(offset>>1)+0x04000+m_vram_bank*0x10000] = (ram & (0xff00 >> mask)) | (data << mask);
|
||||
m_video_ram[1][(offset>>1)+0x04000+m_vram_bank*0x10000] = (ram & (0xff00 >> mask)) | (data << mask);
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
@ -481,12 +465,12 @@ void pc9801_state::gvram_w(offs_t offset, uint8_t data)
|
||||
*
|
||||
************************************************/
|
||||
|
||||
uint16_t pc9801_state::upd7220_grcg_r(offs_t offset, uint16_t mem_mask)
|
||||
uint16_t pc9801vm_state::upd7220_grcg_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t res = 0;
|
||||
|
||||
if(!(m_grcg.mode & 0x80) || machine().side_effects_disabled())
|
||||
res = m_video_ram_2[offset];
|
||||
res = m_video_ram[1][offset];
|
||||
else if(m_ex_video_ff[2])
|
||||
res = egc_blit_r(offset, mem_mask);
|
||||
else if(!(m_grcg.mode & 0x40))
|
||||
@ -499,7 +483,7 @@ uint16_t pc9801_state::upd7220_grcg_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
if((m_grcg.mode & (1 << i)) == 0)
|
||||
{
|
||||
res |= m_video_ram_2[offset | (((i + 1) & 3) * 0x4000)] ^ (m_grcg.tile[i] | m_grcg.tile[i] << 8);
|
||||
res |= m_video_ram[1][offset | (((i + 1) & 3) * 0x4000)] ^ (m_grcg.tile[i] | m_grcg.tile[i] << 8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -509,16 +493,16 @@ uint16_t pc9801_state::upd7220_grcg_r(offs_t offset, uint16_t mem_mask)
|
||||
return res;
|
||||
}
|
||||
|
||||
void pc9801_state::upd7220_grcg_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
void pc9801vm_state::upd7220_grcg_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
if(!(m_grcg.mode & 0x80))
|
||||
COMBINE_DATA(&m_video_ram_2[offset]);
|
||||
COMBINE_DATA(&m_video_ram[1][offset]);
|
||||
else if(m_ex_video_ff[2])
|
||||
egc_blit_w(offset, data, mem_mask);
|
||||
else
|
||||
{
|
||||
int i;
|
||||
uint8_t *vram = (uint8_t *)m_video_ram_2.target();
|
||||
uint8_t *vram = (uint8_t *)m_video_ram[1].target();
|
||||
offset = (offset << 1) & 0x27fff;
|
||||
|
||||
if(m_grcg.mode & 0x40) // RMW
|
||||
@ -563,7 +547,7 @@ void pc9801_state::upd7220_grcg_w(offs_t offset, uint16_t data, uint16_t mem_mas
|
||||
*
|
||||
************************************************/
|
||||
|
||||
uint16_t pc9801_state::egc_color_pat(int plane) const
|
||||
uint16_t pc9801vm_state::egc_color_pat(int plane) const
|
||||
{
|
||||
uint8_t color = 0;
|
||||
switch((m_egc.regs[1] >> 13) & 3)
|
||||
@ -582,7 +566,7 @@ uint16_t pc9801_state::egc_color_pat(int plane) const
|
||||
return BIT(color, plane) ? 0xffff : 0;
|
||||
}
|
||||
|
||||
uint16_t pc9801_state::egc_shift(int plane, uint16_t val)
|
||||
uint16_t pc9801vm_state::egc_shift(int plane, uint16_t val)
|
||||
{
|
||||
int src_off = m_egc.regs[6] & 0xf, dst_off = (m_egc.regs[6] >> 4) & 0xf;
|
||||
int left = src_off - dst_off, right = dst_off - src_off;
|
||||
@ -616,7 +600,7 @@ uint16_t pc9801_state::egc_shift(int plane, uint16_t val)
|
||||
return out;
|
||||
}
|
||||
|
||||
uint16_t pc9801_state::egc_do_partial_op(int plane, uint16_t src, uint16_t pat, uint16_t dst) const
|
||||
uint16_t pc9801vm_state::egc_do_partial_op(int plane, uint16_t src, uint16_t pat, uint16_t dst) const
|
||||
{
|
||||
uint16_t out = 0;
|
||||
|
||||
@ -631,7 +615,7 @@ uint16_t pc9801_state::egc_do_partial_op(int plane, uint16_t src, uint16_t pat,
|
||||
return out;
|
||||
}
|
||||
|
||||
void pc9801_state::egc_blit_w(uint32_t offset, uint16_t data, uint16_t mem_mask)
|
||||
void pc9801vm_state::egc_blit_w(uint32_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t mask = m_egc.regs[4] & mem_mask, out = 0;
|
||||
bool dir = !(m_egc.regs[6] & 0x1000);
|
||||
@ -684,7 +668,7 @@ void pc9801_state::egc_blit_w(uint32_t offset, uint16_t data, uint16_t mem_mask)
|
||||
src = egc_shift(i, data);
|
||||
|
||||
if((m_egc.regs[2] & 0x300) == 0x200)
|
||||
pat = m_video_ram_2[offset + (((i + 1) & 3) * 0x4000)];
|
||||
pat = m_video_ram[1][offset + (((i + 1) & 3) * 0x4000)];
|
||||
|
||||
switch((m_egc.regs[2] >> 11) & 3)
|
||||
{
|
||||
@ -692,7 +676,7 @@ void pc9801_state::egc_blit_w(uint32_t offset, uint16_t data, uint16_t mem_mask)
|
||||
out = data;
|
||||
break;
|
||||
case 1:
|
||||
out = egc_do_partial_op(i, src, pat, m_video_ram_2[offset + (((i + 1) & 3) * 0x4000)]);
|
||||
out = egc_do_partial_op(i, src, pat, m_video_ram[1][offset + (((i + 1) & 3) * 0x4000)]);
|
||||
break;
|
||||
case 2:
|
||||
out = pat;
|
||||
@ -702,8 +686,8 @@ void pc9801_state::egc_blit_w(uint32_t offset, uint16_t data, uint16_t mem_mask)
|
||||
return;
|
||||
}
|
||||
|
||||
m_video_ram_2[offset + (((i + 1) & 3) * 0x4000)] &= ~mask;
|
||||
m_video_ram_2[offset + (((i + 1) & 3) * 0x4000)] |= out & mask;
|
||||
m_video_ram[1][offset + (((i + 1) & 3) * 0x4000)] &= ~mask;
|
||||
m_video_ram[1][offset + (((i + 1) & 3) * 0x4000)] |= out & mask;
|
||||
}
|
||||
}
|
||||
if(mem_mask != 0xffff)
|
||||
@ -731,15 +715,15 @@ void pc9801_state::egc_blit_w(uint32_t offset, uint16_t data, uint16_t mem_mask)
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t pc9801_state::egc_blit_r(uint32_t offset, uint16_t mem_mask)
|
||||
uint16_t pc9801vm_state::egc_blit_r(uint32_t offset, uint16_t mem_mask)
|
||||
{
|
||||
uint32_t plane_off = offset & 0x13fff;
|
||||
if((m_egc.regs[2] & 0x300) == 0x100)
|
||||
{
|
||||
m_egc.pat[0] = m_video_ram_2[plane_off + 0x4000];
|
||||
m_egc.pat[1] = m_video_ram_2[plane_off + (0x4000 * 2)];
|
||||
m_egc.pat[2] = m_video_ram_2[plane_off + (0x4000 * 3)];
|
||||
m_egc.pat[3] = m_video_ram_2[plane_off];
|
||||
m_egc.pat[0] = m_video_ram[1][plane_off + 0x4000];
|
||||
m_egc.pat[1] = m_video_ram[1][plane_off + (0x4000 * 2)];
|
||||
m_egc.pat[2] = m_video_ram[1][plane_off + (0x4000 * 3)];
|
||||
m_egc.pat[3] = m_video_ram[1][plane_off];
|
||||
}
|
||||
//TODO: this needs another look
|
||||
/*if(m_egc.first && !m_egc.init)
|
||||
@ -750,17 +734,17 @@ uint16_t pc9801_state::egc_blit_r(uint32_t offset, uint16_t mem_mask)
|
||||
}*/
|
||||
m_egc.init = true;
|
||||
for(int i = 0; i < 4; i++)
|
||||
m_egc.src[i] = egc_shift(i, m_video_ram_2[plane_off + (((i + 1) & 3) * 0x4000)]);
|
||||
m_egc.src[i] = egc_shift(i, m_video_ram[1][plane_off + (((i + 1) & 3) * 0x4000)]);
|
||||
|
||||
if(BIT(m_egc.regs[2], 13))
|
||||
{
|
||||
uint16_t ret;
|
||||
// docs say vram is compared to the foreground color register but 4a2 13-14 must be 2
|
||||
// guess that the other values probably work too
|
||||
ret = ~(egc_color_pat(0) ^ m_video_ram_2[plane_off + 0x4000]);
|
||||
ret &= ~(egc_color_pat(1) ^ m_video_ram_2[plane_off + (0x4000 * 2)]);
|
||||
ret &= ~(egc_color_pat(2) ^ m_video_ram_2[plane_off + (0x4000 * 3)]);
|
||||
ret &= ~(egc_color_pat(3) ^ m_video_ram_2[plane_off]);
|
||||
ret = ~(egc_color_pat(0) ^ m_video_ram[1][plane_off + 0x4000]);
|
||||
ret &= ~(egc_color_pat(1) ^ m_video_ram[1][plane_off + (0x4000 * 2)]);
|
||||
ret &= ~(egc_color_pat(2) ^ m_video_ram[1][plane_off + (0x4000 * 3)]);
|
||||
ret &= ~(egc_color_pat(3) ^ m_video_ram[1][plane_off]);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user