summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author wilbertpol <wilbertpol@users.noreply.github.com>2020-09-23 13:58:19 +0200
committer GitHub <noreply@github.com>2020-09-23 07:58:19 -0400
commitf773d1b6564f12dd782f7009ec00281c955a9b06 (patch)
tree6561cc13f6fce5b181966efd334e77e2fa1fc978 /src
parent33a5e3ea4b2158f05fb5ea2655757e9cb7d57152 (diff)
wswan/wscolor: Add boot rom support (#7277)
* wswan: Add boot rom. [Wilbert Pol] * wswan: merge drivers/wswan.cpp, includes/wswan.h, and machine/wswan.cpp (nw) * wswan: fix background color selection in wsc mode (nw) * wswan: add defaults for the internal eeproms (nw) * wswan: add some documentation; rename a few methods (nw)
Diffstat (limited to 'src')
-rw-r--r--src/mame/drivers/wswan.cpp784
-rw-r--r--src/mame/includes/wswan.h120
-rw-r--r--src/mame/machine/wswan.cpp664
-rw-r--r--src/mame/video/wswan.cpp9
-rw-r--r--src/mame/video/wswan.h23
5 files changed, 749 insertions, 851 deletions
diff --git a/src/mame/drivers/wswan.cpp b/src/mame/drivers/wswan.cpp
index af411c7fb78..0fd49940a3c 100644
--- a/src/mame/drivers/wswan.cpp
+++ b/src/mame/drivers/wswan.cpp
@@ -12,85 +12,214 @@
Based on the WStech documentation by Judge and Dox.
+ Usage:
+ Keep START button pressed during startup (or reset) to enter the internal
+ configuration menu.
+
Known issues/TODOs:
- - Get the V30MZ core into MAME, still need to remove some nec specific
- instructions and fix the flags handling of the div/mul instructions.
- Add support for noise sound
- Add support for voice sound
- Add support for enveloped sound
- Perform video DMA at proper timing.
- - Add sound DMA.
- - Setup some reasonable values in the internal EEPROM area?
- Add (real/proper) RTC support.
- - Look into timing issues like in Puzzle Bobble. VBlank interrupt lasts very long
- which causes sprites to be disabled until about 10%-40% of drawing the screen.
- The real unit seems to display things fine, need a real unit + real cart to
- verify.
- - Is background color setting really ok?
- - Get a dump of the internal BIOSes.
- Swan Crystal can handle up to 512Mbit ROMs??????
-
+ - SRAM sizes should be in kbit instead of kbytes(?). This raises a few
+ interesting issues:
+ - mirror of smaller <64KBYTE/512kbit sram sizes
+ - banking when using 1M or 2M sram sizes
+ - The units likely came with the name "WONDERSWAN" configured in the
+ internal EEPOM
***************************************************************************/
#include "emu.h"
-#include "includes/wswan.h"
-
+#include "cpu/v30mz/v30mz.h"
+#include "machine/nvram.h"
+#include "audio/wswan.h"
+#include "video/wswan.h"
+#include "bus/wswan/slot.h"
+#include "bus/wswan/rom.h"
+#include "emupal.h"
+#include "render.h"
#include "screen.h"
#include "softlist.h"
#include "speaker.h"
#include "wswan.lh"
-void wswan_state::wswan_mem(address_map &map)
+class wswan_state : public driver_device
+{
+public:
+ wswan_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_vdp(*this, "vdp"),
+ m_sound(*this, "custom"),
+ m_cart(*this, "cartslot"),
+ m_region_maincpu(*this, "maincpu"),
+ m_cursx(*this, "CURSX"),
+ m_cursy(*this, "CURSY"),
+ m_buttons(*this, "BUTTONS")
+ { }
+
+ void wswan(machine_config &config);
+
+protected:
+ // Interrupt flags
+ static const u8 WSWAN_IFLAG_STX = 0x01;
+ static const u8 WSWAN_IFLAG_KEY = 0x02;
+ static const u8 WSWAN_IFLAG_RTC = 0x04;
+ static const u8 WSWAN_IFLAG_SRX = 0x08;
+ static const u8 WSWAN_IFLAG_LCMP = 0x10;
+ static const u8 WSWAN_IFLAG_VBLTMR = 0x20;
+ static const u8 WSWAN_IFLAG_VBL = 0x40;
+ static const u8 WSWAN_IFLAG_HBLTMR = 0x80;
+
+ // Interrupts
+ static const u8 WSWAN_INT_STX = 0;
+ static const u8 WSWAN_INT_KEY = 1;
+ static const u8 WSWAN_INT_RTC = 2;
+ static const u8 WSWAN_INT_SRX = 3;
+ static const u8 WSWAN_INT_LCMP = 4;
+ static const u8 WSWAN_INT_VBLTMR = 5;
+ static const u8 WSWAN_INT_VBL = 6;
+ static const u8 WSWAN_INT_HBLTMR = 7;
+
+ static const u32 INTERNAL_EEPROM_SIZE = 1024; // 16kbit on WSC
+ static const u32 INTERNAL_EEPROM_SIZE_WS = 64; // 1kbit on WS
+
+ enum enum_system { TYPE_WSWAN=0, TYPE_WSC };
+
+ struct sound_dma_t
+ {
+ u32 source; // Source address
+ u16 size; // Size
+ u8 enable; // Enabled
+ };
+
+ required_device<cpu_device> m_maincpu;
+ required_device<wswan_video_device> m_vdp;
+ required_device<wswan_sound_device> m_sound;
+ required_device<ws_cart_slot_device> m_cart;
+
+ u8 m_ws_portram[256];
+ u8 m_internal_eeprom[INTERNAL_EEPROM_SIZE * 2];
+ u8 m_system_type;
+ sound_dma_t m_sound_dma;
+ u8 m_bios_disabled;
+ u8 m_rotate;
+
+ required_memory_region m_region_maincpu;
+ required_ioport m_cursx;
+ required_ioport m_cursy;
+ required_ioport m_buttons;
+
+ u8 bios_r(offs_t offset);
+ u8 port_r(offs_t offset);
+ void port_w(offs_t offset, u8 data);
+
+ void set_irq_line(int irq);
+ void dma_sound_cb();
+ void common_start();
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+ void palette(palette_device &palette) const;
+
+ void io_map(address_map &map);
+ void mem_map(address_map &map);
+ void snd_map(address_map &map);
+
+ void register_save();
+ void handle_irqs();
+ void clear_irq_line(int irq);
+ virtual u16 get_internal_eeprom_address();
+};
+
+class wscolor_state : public wswan_state
+{
+public:
+ using wswan_state::wswan_state;
+ void wscolor(machine_config &config);
+
+protected:
+ virtual void machine_start() override;
+ void mem_map(address_map &map);
+ void palette(palette_device &palette) const;
+ virtual u16 get_internal_eeprom_address() override;
+};
+
+static const uint8_t ws_portram_init[256] =
+{
+ 0x00, 0x00, 0x00/*?*/, 0xbb, 0x00, 0x00, 0x00, 0x26, 0xfe, 0xde, 0xf9, 0xfb, 0xdb, 0xd7, 0x7f, 0xf5,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x99, 0xfd, 0xb7, 0xdf,
+ 0x30, 0x57, 0x75, 0x76, 0x15, 0x73, 0x70/*77?*/, 0x77, 0x20, 0x75, 0x50, 0x36, 0x70, 0x67, 0x50, 0x77,
+ 0x57, 0x54, 0x75, 0x77, 0x75, 0x17, 0x37, 0x73, 0x50, 0x57, 0x60, 0x77, 0x70, 0x77, 0x10, 0x73,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x87, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xdb, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x83, 0x00,
+ 0x2f, 0x3f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+ 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1
+};
+
+void wswan_state::mem_map(address_map &map)
{
map(0x00000, 0x03fff).rw(m_vdp, FUNC(wswan_video_device::vram_r), FUNC(wswan_video_device::vram_w)); // 16kb RAM / 4 colour tiles
map(0x04000, 0x0ffff).noprw(); // nothing
- //map(0x10000, 0xeffff) // cart range, setup at machine_start
map(0xf0000, 0xfffff).r(FUNC(wswan_state::bios_r));
}
-void wscolor_state::wscolor_mem(address_map &map)
+
+void wscolor_state::mem_map(address_map &map)
{
- map(0x00000, 0x0ffff).rw("vdp", FUNC(wswan_video_device::vram_r), FUNC(wswan_video_device::vram_w)); // 16kb RAM / 4 colour tiles, 16 colour tiles + palettes
- //map(0x10000, 0xeffff) // cart range, setup at machine_start
+ map(0x00000, 0x0ffff).rw(m_vdp, FUNC(wswan_video_device::vram_r), FUNC(wswan_video_device::vram_w)); // 16kb RAM / 4 colour tiles, 16 colour tiles + palettes
map(0xf0000, 0xfffff).r(FUNC(wscolor_state::bios_r));
}
-void wswan_state::wswan_io(address_map &map)
+
+void wswan_state::io_map(address_map &map)
{
map(0x00, 0xff).rw(FUNC(wswan_state::port_r), FUNC(wswan_state::port_w)); // I/O ports
}
-void wswan_state::wswan_snd(address_map &map)
+
+void wswan_state::snd_map(address_map &map)
{
map(0x00000, 0x03fff).r(m_vdp, FUNC(wswan_video_device::vram_r));
}
+
static INPUT_PORTS_START( wswan )
PORT_START("CURSX")
- PORT_BIT( 0x1, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("X1 - Up")
- PORT_BIT( 0x4, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("X3 - Down")
PORT_BIT( 0x8, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_NAME("X4 - Left")
+ PORT_BIT( 0x4, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_NAME("X3 - Down")
PORT_BIT( 0x2, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_NAME("X2 - Right")
+ PORT_BIT( 0x1, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_NAME("X1 - Up")
PORT_START("BUTTONS")
- PORT_BIT( 0x2, IP_ACTIVE_HIGH, IPT_START1 ) PORT_NAME("Start")
- PORT_BIT( 0x4, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Button A")
PORT_BIT( 0x8, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Button B")
+ PORT_BIT( 0x4, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Button A")
+ PORT_BIT( 0x2, IP_ACTIVE_HIGH, IPT_START1 ) PORT_NAME("Start")
PORT_START("CURSY")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Y1 - Up") PORT_CODE(KEYCODE_W)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Y3 - Down") PORT_CODE(KEYCODE_S)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Y4 - Left") PORT_CODE(KEYCODE_A)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Y3 - Down") PORT_CODE(KEYCODE_S)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Y2 - Right") PORT_CODE(KEYCODE_D)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Y1 - Up") PORT_CODE(KEYCODE_W)
INPUT_PORTS_END
static GFXDECODE_START( gfx_wswan )
GFXDECODE_END
+
/* WonderSwan can display 16 shades of grey */
-void wswan_state::wswan_palette(palette_device &palette) const
+void wswan_state::palette(palette_device &palette) const
{
for (int i = 0; i < 16; i++)
{
@@ -99,7 +228,8 @@ void wswan_state::wswan_palette(palette_device &palette) const
}
}
-void wscolor_state::wscolor_palette(palette_device &palette) const
+
+void wscolor_state::palette(palette_device &palette) const
{
for (int i = 0; i < 4096; i++)
{
@@ -110,6 +240,7 @@ void wscolor_state::wscolor_palette(palette_device &palette) const
}
}
+
static void wswan_cart(device_slot_interface &device)
{
device.option_add_internal("ws_rom", WS_ROM_STD);
@@ -117,16 +248,17 @@ static void wswan_cart(device_slot_interface &device)
device.option_add_internal("ws_eeprom", WS_ROM_EEPROM);
}
+
void wswan_state::wswan(machine_config &config)
{
- /* Basic machine hardware */
+ // Basic machine hardware
V30MZ(config, m_maincpu, 3.072_MHz_XTAL);
- m_maincpu->set_addrmap(AS_PROGRAM, &wswan_state::wswan_mem);
- m_maincpu->set_addrmap(AS_IO, &wswan_state::wswan_io);
+ m_maincpu->set_addrmap(AS_PROGRAM, &wswan_state::mem_map);
+ m_maincpu->set_addrmap(AS_IO, &wswan_state::io_map);
WSWAN_VIDEO(config, m_vdp, 0);
m_vdp->set_screen("screen");
- m_vdp->set_vdp_type(VDP_TYPE_WSWAN);
+ m_vdp->set_vdp_type(wswan_video_device::VDP_TYPE_WSWAN);
m_vdp->set_irq_callback(FUNC(wswan_state::set_irq_line));
m_vdp->set_dmasnd_callback(FUNC(wswan_state::dma_sound_cb));
@@ -136,68 +268,622 @@ void wswan_state::wswan(machine_config &config)
screen.set_screen_update("vdp", FUNC(wswan_video_device::screen_update));
// screen.set_size(WSWAN_X_PIXELS, WSWAN_Y_PIXELS);
// screen.set_visarea(0*8, WSWAN_X_PIXELS - 1, 0, WSWAN_Y_PIXELS - 1);
- screen.set_raw(3.072_MHz_XTAL, 256, 0, WSWAN_X_PIXELS, 159, 0, WSWAN_Y_PIXELS);
+ screen.set_raw(3.072_MHz_XTAL, 256, 0, wswan_video_device::WSWAN_X_PIXELS, 159, 0, wswan_video_device::WSWAN_Y_PIXELS);
screen.set_palette("palette");
config.set_default_layout(layout_wswan);
config.set_maximum_quantum(attotime::from_hz(60));
- NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1);
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
GFXDECODE(config, "gfxdecode", "palette", gfx_wswan);
- PALETTE(config, "palette", FUNC(wswan_state::wswan_palette), 16);
+ PALETTE(config, "palette", FUNC(wswan_state::palette), 16);
- /* sound hardware */
+ // sound hardware
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
WSWAN_SND(config, m_sound, 3.072_MHz_XTAL);
- m_sound->set_addrmap(0, &wswan_state::wswan_snd);
+ m_sound->set_addrmap(0, &wswan_state::snd_map);
m_sound->add_route(0, "lspeaker", 0.50);
m_sound->add_route(1, "rspeaker", 0.50);
- /* cartridge */
+ // cartridge
WS_CART_SLOT(config, m_cart, 3.072_MHz_XTAL / 8, wswan_cart, nullptr);
- /* software lists */
+ // software lists
SOFTWARE_LIST(config, "cart_list").set_original("wswan");
SOFTWARE_LIST(config, "wsc_list").set_compatible("wscolor");
SOFTWARE_LIST(config, "pc2_list").set_compatible("pockchalv2");
}
+
void wscolor_state::wscolor(machine_config &config)
{
wswan(config);
- m_maincpu->set_addrmap(AS_PROGRAM, &wscolor_state::wscolor_mem);
+ m_maincpu->set_addrmap(AS_PROGRAM, &wscolor_state::mem_map);
- m_vdp->set_vdp_type(VDP_TYPE_WSC);
+ m_vdp->set_vdp_type(wswan_video_device::VDP_TYPE_WSC);
auto &palette(*subdevice<palette_device>("palette"));
palette.set_entries(4096);
- palette.set_init(FUNC(wscolor_state::wscolor_palette));
+ palette.set_init(FUNC(wscolor_state::palette));
- /* software lists */
+ // software lists
config.device_remove("wsc_list");
SOFTWARE_LIST(config.replace(), "cart_list").set_original("wscolor");
SOFTWARE_LIST(config, "ws_list").set_compatible("wswan");
}
+
+void wswan_state::handle_irqs()
+{
+ if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_HBLTMR)
+ {
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_HBLTMR); // V30MZ
+ }
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBL)
+ {
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBL); // V30MZ
+ }
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBLTMR)
+ {
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBLTMR); // V30MZ
+ }
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_LCMP)
+ {
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_LCMP); // V30MZ
+ }
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_SRX)
+ {
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_SRX); // V30MZ
+ }
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_RTC)
+ {
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_RTC); // V30MZ
+ }
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_KEY)
+ {
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_KEY); // V30MZ
+ }
+ else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_STX)
+ {
+ m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_STX); // V30MZ
+ }
+ else
+ {
+ m_maincpu->set_input_line(0, CLEAR_LINE);
+ }
+}
+
+
+void wswan_state::set_irq_line(int irq)
+{
+ if (m_ws_portram[0xb2] & irq)
+ {
+ m_ws_portram[0xb6] |= irq;
+ handle_irqs();
+ }
+}
+
+
+void wswan_state::dma_sound_cb()
+{
+ if ((m_sound_dma.enable & 0x88) == 0x80)
+ {
+ address_space &space = m_maincpu->space(AS_PROGRAM);
+ /* TODO: Output sound DMA byte */
+ port_w(0x89, space.read_byte(m_sound_dma.source));
+ m_sound_dma.size--;
+ m_sound_dma.source = (m_sound_dma.source + 1) & 0x0fffff;
+ if (m_sound_dma.size == 0)
+ {
+ m_sound_dma.enable &= 0x7f;
+ }
+ }
+}
+
+
+void wswan_state::clear_irq_line(int irq)
+{
+ m_ws_portram[0xb6] &= ~irq;
+ handle_irqs();
+}
+
+
+void wswan_state::register_save()
+{
+ save_item(NAME(m_ws_portram));
+ save_item(NAME(m_internal_eeprom));
+ save_item(NAME(m_bios_disabled));
+ save_item(NAME(m_rotate));
+
+ save_item(NAME(m_sound_dma.source));
+ save_item(NAME(m_sound_dma.size));
+ save_item(NAME(m_sound_dma.enable));
+
+ if (m_cart->exists())
+ m_cart->save_nvram();
+}
+
+
+void wswan_state::common_start()
+{
+ register_save();
+
+ if (m_cart->exists())
+ {
+ // ROM
+ m_maincpu->space(AS_PROGRAM).install_read_handler(0x20000, 0x2ffff, read8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::read_rom20)));
+ m_maincpu->space(AS_PROGRAM).install_read_handler(0x30000, 0x3ffff, read8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::read_rom30)));
+ m_maincpu->space(AS_PROGRAM).install_read_handler(0x40000, 0xeffff, read8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::read_rom40)));
+
+ // SRAM
+ if (m_cart->get_type() == WS_SRAM)
+ {
+ m_maincpu->space(AS_PROGRAM).install_read_handler(0x10000, 0x1ffff, read8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::read_ram)));
+ m_maincpu->space(AS_PROGRAM).install_write_handler(0x10000, 0x1ffff, write8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::write_ram)));
+ }
+ }
+}
+
+
+void wswan_state::machine_start()
+{
+ common_start();
+ subdevice<nvram_device>("nvram")->set_base(m_internal_eeprom, INTERNAL_EEPROM_SIZE_WS * 2);
+ m_system_type = TYPE_WSWAN;
+}
+
+
+void wscolor_state::machine_start()
+{
+ common_start();
+ subdevice<nvram_device>("nvram")->set_base(m_internal_eeprom, INTERNAL_EEPROM_SIZE * 2);
+ m_system_type = TYPE_WSC;
+}
+
+
+void wswan_state::machine_reset()
+{
+ m_bios_disabled = 0;
+
+ if (m_cart->exists())
+ m_rotate = m_cart->get_is_rotated();
+ else
+ m_rotate = 0;
+
+ /* Intialize ports */
+ memcpy(m_ws_portram, ws_portram_init, 256);
+
+ render_target *target = machine().render().first_target();
+ target->set_view(m_rotate);
+
+ /* Initialize sound DMA */
+ memset(&m_sound_dma, 0, sizeof(m_sound_dma));
+}
+
+
+u8 wswan_state::bios_r(offs_t offset)
+{
+ if (!m_bios_disabled)
+ return m_region_maincpu->base()[offset & (m_region_maincpu->bytes() - 1)];
+ else
+ return m_cart->read_rom40(offset + 0xb0000);
+}
+
+
+u8 wswan_state::port_r(offs_t offset)
+{
+ u8 value = m_ws_portram[offset];
+
+ if (offset != 2)
+ logerror("PC=%X: port read %02X\n", m_maincpu->pc(), offset);
+
+ if (offset < 0x40 || (offset >= 0xa1 && offset < 0xb0))
+ return m_vdp->reg_r(offset);
+
+ switch (offset)
+ {
+ case 0x4a: // Sound DMA source address (low)
+ value = m_sound_dma.source & 0xff;
+ break;
+ case 0x4b: // Sound DMA source address (high)
+ value = (m_sound_dma.source >> 8) & 0xff;
+ break;
+ case 0x4c: // Sound DMA source memory segment
+ value = (m_sound_dma.source >> 16) & 0xff;
+ break;
+ case 0x4e: // Sound DMA transfer size (low)
+ value = m_sound_dma.size & 0xff;
+ break;
+ case 0x4f: // Sound DMA transfer size (high)
+ value = (m_sound_dma.size >> 8) & 0xff;
+ break;
+ case 0x52: // Sound DMA start/stop
+ value = m_sound_dma.enable;
+ break;
+ case 0x60:
+ value = m_vdp->reg_r(offset);
+ break;
+ case 0xa0: // Hardware type
+ // Bit 0 - Disable/enable Bios
+ // Bit 1 - Determine mono/color
+ // Bit 2 - Unknown, used to determine color/crystal
+ // Bit 3 - Unknown
+ // Bit 7 - Checked during start up, expects bit 7 set
+ value = value & ~ 0x02;
+ if (m_system_type == TYPE_WSC)
+ value |= 2;
+ value |= 0x80;
+ break;
+ case 0xb5: // Read controls
+ // Bit 0-3 - Current state of input lines (read-only)
+ // Bit 4-6 - Select line of inputs to read
+ // 001 - Read Y cursors
+ // 010 - Read X cursors
+ // 100 - Read START,A,B buttons
+ // Bit 7 - Unknown
+ value = value & 0xf0;
+ switch (value)
+ {
+ case 0x10: // Read Y cursors: Y1 - Y2 - Y3 - Y4
+ {
+ u8 input = m_cursy->read();
+ if (m_rotate) // reorient controls if the console is rotated
+ {
+ if (input & 0x01) value |= 0x02;
+ if (input & 0x02) value |= 0x04;
+ if (input & 0x04) value |= 0x08;
+ if (input & 0x08) value |= 0x01;
+ }
+ else
+ value = value | input;
+ }
+ break;
+ case 0x20: // Read X cursors: X1 - X2 - X3 - X4
+ {
+ u8 input = m_cursx->read();
+ if (m_rotate) // reorient controls if the console is rotated
+ {
+ if (input & 0x01) value |= 0x02;
+ if (input & 0x02) value |= 0x04;
+ if (input & 0x04) value |= 0x08;
+ if (input & 0x08) value |= 0x01;
+ }
+ else
+ value = value | input;
+ }
+ break;
+ case 0x40: // Read buttons: START - A - B
+ value = value | m_buttons->read();
+ break;
+ }
+ break;
+ case 0xc0:
+ case 0xc1:
+ case 0xc2:
+ case 0xc3:
+ case 0xc4: // Cartridge EEPROM data
+ case 0xc5: // Cartridge EEPROM data
+ case 0xc6:
+ case 0xc7:
+ case 0xc8:
+ case 0xc9:
+ case 0xca:
+ case 0xcb: // RTC data
+ case 0xcc:
+ case 0xcd:
+ case 0xce:
+ case 0xcf:
+ value = m_cart->read_io(offset & 0x0f);
+ break;
+ }
+
+ return value;
+}
+
+
+void wswan_state::port_w(offs_t offset, u8 data)
+{
+ address_space &mem = m_maincpu->space(AS_PROGRAM);
+ logerror("PC=%X: port write %02X <- %02X\n", m_maincpu->pc(), offset, data);
+
+ if (offset < 0x40 || (offset >= 0xa1 && offset < 0xb0))
+ {
+ m_vdp->reg_w(offset, data);
+ return;
+ }
+
+ switch (offset)
+ {
+ case 0x40: // DMA source address (low)
+ case 0x41: // DMA source address (high)
+ case 0x42: // DMA source bank
+ case 0x43: // DMA destination bank
+ case 0x44: // DMA destination address (low)
+ case 0x45: // DMA destination address (high)
+ case 0x46: // Size of copied data (low)
+ case 0x47: // Size of copied data (high)
+ break;
+ case 0x48: // DMA control
+ // Bit 0-6 - Unknown
+ // Bit 7 - DMA stop/start
+ if (data & 0x80)
+ {
+ u32 src, dst;
+ u16 length;
+
+ src = m_ws_portram[0x40] + (m_ws_portram[0x41] << 8) + (m_ws_portram[0x42] << 16);
+ dst = m_ws_portram[0x44] + (m_ws_portram[0x45] << 8) + (m_ws_portram[0x43] << 16);
+ length = m_ws_portram[0x46] + (m_ws_portram[0x47] << 8);
+ for ( ; length > 0; length--)
+ {
+ mem.write_byte(dst, mem.read_byte(src));
+ src++;
+ dst++;
+ }
+#ifdef MAME_DEBUG
+ logerror("DMA src:%X dst:%X length:%d\n", src, dst, length);
+#endif
+ m_ws_portram[0x40] = src & 0xff;
+ m_ws_portram[0x41] = (src >> 8) & 0xff;
+ m_ws_portram[0x44] = dst & 0xff;
+ m_ws_portram[0x45] = (dst >> 8) & 0xff;
+ m_ws_portram[0x46] = length & 0xff;
+ m_ws_portram[0x47] = (length >> 8) & 0xff;
+ data &= 0x7f;
+ }
+ break;
+ case 0x4a: // Sound DMA source address (low)
+ m_sound_dma.source = (m_sound_dma.source & 0x0fff00) | data;
+ break;
+ case 0x4b: // Sound DMA source address (high)
+ m_sound_dma.source = (m_sound_dma.source & 0x0f00ff) | (data << 8);
+ break;
+ case 0x4c: // Sound DMA source memory segment
+ // Bit 0-3 - Sound DMA source address segment
+ // Bit 4-7 - Unknown
+ m_sound_dma.source = (m_sound_dma.source & 0xffff) | ((data & 0x0f) << 16);
+ break;
+ case 0x4d: // Unknown
+ break;
+ case 0x4e: // Sound DMA transfer size (low)
+ m_sound_dma.size = (m_sound_dma.size & 0xff00) | data;
+ break;
+ case 0x4f: // Sound DMA transfer size (high)
+ m_sound_dma.size = (m_sound_dma.size & 0xff) | (data << 8);
+ break;
+ case 0x50: // Unknown
+ case 0x51: // Unknown
+ break;
+ case 0x52: // Sound DMA start/stop
+ // Bit 0-6 - Unknown
+ // Bit 7 - Sound DMA stop/start
+ m_sound_dma.enable = data;
+ break;
+ case 0x60:
+ m_vdp->reg_w(offset, data);
+ break;
+ case 0x80: // Audio 1 freq (lo)
+ case 0x81: // Audio 1 freq (hi)
+ case 0x82: // Audio 2 freq (lo)
+ case 0x83: // Audio 2 freq (hi)
+ case 0x84: // Audio 3 freq (lo)
+ case 0x85: // Audio 3 freq (hi)
+ case 0x86: // Audio 4 freq (lo)
+ case 0x87: // Audio 4 freq (hi)
+ case 0x88: // Audio 1 volume
+ // Bit 0-3 - Right volume audio channel 1
+ // Bit 4-7 - Left volume audio channel 1
+ case 0x89: // Audio 2 volume
+ // Bit 0-3 - Right volume audio channel 2
+ // Bit 4-7 - Left volume audio channel 2
+ case 0x8a: // Audio 3 volume
+ // Bit 0-3 - Right volume audio channel 3
+ // Bit 4-7 - Left volume audio channel 3
+ case 0x8b: // Audio 4 volume
+ // Bit 0-3 - Right volume audio channel 4
+ // Bit 4-7 - Left volume audio channel 4
+ case 0x8c: // Sweep step
+ case 0x8d: // Sweep time
+ case 0x8e: // Noise control
+ // Bit 0-2 - Noise generator type
+ // Bit 3 - Reset
+ // Bit 4 - Enable
+ // Bit 5-7 - Unknown
+ case 0x8f: // Sample location
+ // Bit 0-7 - Sample address location 0 00xxxxxx xx000000
+ case 0x90: // Audio control
+ // Bit 0 - Audio 1 enable
+ // Bit 1 - Audio 2 enable
+ // Bit 2 - Audio 3 enable
+ // Bit 3 - Audio 4 enable
+ // Bit 4 - Unknown
+ // Bit 5 - Audio 2 voice mode enable
+ // Bit 6 - Audio 3 sweep mode enable
+ // Bit 7 - Audio 4 noise mode enable
+ case 0x91: // Audio output
+ // Bit 0 - Mono select
+ // Bit 1-2 - Output volume
+ // Bit 3 - External stereo
+ // Bit 4-6 - Unknown
+ // Bit 7 - External speaker (Read-only, set by hardware)
+ case 0x92: // Noise counter shift register (lo)
+ case 0x93: // Noise counter shift register (hi)
+ // Bit 0-6 - Noise counter shift register bit 8-14
+ // bit 7 - Unknown
+ case 0x94: // Master volume
+ // Bit 0-3 - Master volume
+ // Bit 4-7 - Unknown
+ m_sound->port_w(offset, data);
+ break;
+ case 0x9E: // WSC volume setting (0, 1, 2, 3)
+ break;
+ case 0xa0: // Hardware type/system control
+ // Bit 0 - Enable cartridge slot and/or disable bios
+ // Bit 1 - Hardware type: 0 = WS, 1 = WSC
+ // Bit 2 - Unknown, written during boot
+ // Bit 3 - Unknown, written during boot
+ // Bit 4-6 - Unknown
+ // Bit 7 - Unknown, read during boot
+ if ((data & 0x01) && !m_bios_disabled)
+ m_bios_disabled = 1;
+ break;
+
+ case 0xb0: // Interrupt base vector
+ break;
+ case 0xb1: // Communication byte
+ break;
+ case 0xb2: // Interrupt enable
+ // Bit 0 - Serial transmit interrupt enable
+ // Bit 1 - Key press interrupt enable
+ // Bit 2 - RTC alarm interrupt enable
+ // Bit 3 - Serial receive interrupt enable
+ // Bit 4 - Drawing line detection interrupt enable
+ // Bit 5 - VBlank timer interrupt enable
+ // Bit 6 - VBlank interrupt enable
+ // Bit 7 - HBlank timer interrupt enable
+ break;
+ case 0xb3: // serial communication control
+ // Bit 0 - Receive complete
+ // Bit 1 - Error
+ // Bit 2 - Send complete
+ // Bit 3-4 - Unknown
+ // Bit 5 - Send data interrupt generation
+ // Bit 6 - Connection speed: 0 = 9600 bps, 1 = 38400 bps
+ // Bit 7 - Receive data interrupt generation
+ m_ws_portram[0xb1] = 0xff;
+ if (data & 0x80)
+ {
+ // m_ws_portram[0xb1] = 0x00;
+ data |= 0x04;
+ }
+ if (data & 0x20)
+ {
+ // data |= 0x01;
+ }
+ break;
+ case 0xb5: // Read controls
+ // Bit 0-3 - Current state of input lines (read-only)
+ // Bit 4-6 - Select line of inputs to read
+ // 001 - Read Y cursors
+ // 010 - Read X cursors
+ // 100 - Read START,A,B buttons
+ // Bit 7 - Unknown
+ break;
+ case 0xb6: // Interrupt acknowledge
+ // Bit 0 - Serial transmit interrupt acknowledge
+ // Bit 1 - Key press interrupt acknowledge
+ // Bit 2 - RTC alarm interrupt acknowledge
+ // Bit 3 - Serial receive interrupt acknowledge
+ // Bit 4 - Drawing line detection interrupt acknowledge
+ // Bit 5 - VBlank timer interrupt acknowledge
+ // Bit 6 - VBlank interrupt acknowledge
+ // Bit 7 - HBlank timer interrupt acknowledge
+ clear_irq_line(data);
+ data = m_ws_portram[0xb6];
+ break;
+ case 0xba: // Internal EEPROM data (low)
+ case 0xbb: // Internal EEPROM data (high)
+ break;
+ case 0xbc: // Internal EEPROM address (low)
+ // (WS) Bit 0-5 = Internal EEPROM address
+ // (WSC) Bit 0-7 - Internal EEPROM address bit 1-8
+ case 0xbd: // Internal EEPROM address (high)
+ // (WSC) Bit 0 - Internal EEPROM address bit 9(?)
+ // Bit 1-7 - Unknown
+ break;
+ case 0xbe: // Internal EEPROM command/status
+ // Bit 0 - Read complete (read only)
+ // Bit 1 - Write complete (read only)
+ // Bit 2-3 - Unknown
+ // Bit 4 - Read
+ // Bit 5 - Write
+ // Bit 6 - Protect
+ // Bit 7 - Initialize
+ if (data & 0x20)
+ {
+ u16 addr = get_internal_eeprom_address();
+ m_internal_eeprom[addr] = m_ws_portram[0xba];
+ m_internal_eeprom[addr + 1] = m_ws_portram[0xbb];
+ data |= 0x02;
+ }
+ else if ( data & 0x10 )
+ {
+ u16 addr = get_internal_eeprom_address();
+ m_ws_portram[0xba] = m_internal_eeprom[addr];
+ m_ws_portram[0xbb] = m_internal_eeprom[addr + 1];
+ data |= 0x01;
+ }
+ else
+ {
+ logerror( "Unsupported internal EEPROM command: %X\n", data );
+ }
+ break;
+ case 0xc0: // ROM bank $40000-$fffff
+ case 0xc1: // SRAM bank
+ case 0xc2: // ROM bank $20000-$2ffff
+ case 0xc3: // ROM bank $30000-$3ffff
+ case 0xc4:
+ case 0xc5:
+ case 0xc6: // EEPROM address / command
+ case 0xc7: // EEPROM address / command
+ case 0xc8: // EEPROM command
+ case 0xc9:
+ case 0xca: // RTC command
+ case 0xcb: // RTC data
+ case 0xcc:
+ case 0xcd:
+ case 0xce:
+ case 0xcf:
+ m_cart->write_io(offset & 0x0f, data);
+ break;
+ default:
+ logerror( "Write to unsupported port: %X - %X\n", offset, data );
+ break;
+ }
+
+ // Update the port value
+ m_ws_portram[offset] = data;
+}
+
+
+u16 wswan_state::get_internal_eeprom_address() {
+ return (m_ws_portram[0xbc] & 0x3f) << 1;
+}
+
+
+u16 wscolor_state::get_internal_eeprom_address() {
+ return (((m_ws_portram[0xbd] << 8) | m_ws_portram[0xbc]) & 0x1FF) << 1;
+}
+
/***************************************************************************
Game driver(s)
***************************************************************************/
-ROM_START( wswan )
- ROM_REGION( 0x100000, "maincpu", ROMREGION_ERASEFF )
-// ROM_LOAD( "ws_bios.bin", 0x0000, 0x0001, NO_DUMP )
+ROM_START(wswan)
+ ROM_REGION(0x1000, "maincpu", 0)
+ ROM_LOAD("boot.rom", 0x0000, 0x1000, CRC(7f35f890) SHA1(4015bcacea76bb0b5bbdb13c5358f7e1abb986a1))
+
+ ROM_REGION(0x80, "nvram", 0)
+ // Need a dump from an original new unit
+ // Empty file containing just the name 'WONDERSAN'
+ ROM_LOAD("internal_eeprom.ws", 0x00, 0x80, BAD_DUMP CRC(b1dff316) SHA1(7b76c3d59c9add9501f95e8bfc34427773fcbd28))
ROM_END
-ROM_START( wscolor )
- ROM_REGION( 0x100000, "maincpu", ROMREGION_ERASEFF )
-// ROM_LOAD( "wsc_bios.bin", 0x0000, 0x0001, NO_DUMP )
+ROM_START(wscolor)
+ ROM_REGION(0x2000, "maincpu", 0)
+ ROM_LOAD("boot.rom", 0x0000, 0x2000, CRC(cb06d9c3) SHA1(c5ad0b8af45d762662a69f50b64161b9c8919efb))
+
+ ROM_REGION(0x800, "nvram", 0)
+ // Need a dump from an original new unit
+ // Empty file containing just the name 'WONDERSAN'
+ ROM_LOAD("internal_eeprom.wsc", 0x000, 0x800, BAD_DUMP CRC(9e29725c) SHA1(a903c2cb5f4bb94b67326ff87a2d91605dceffff))
ROM_END
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME
diff --git a/src/mame/includes/wswan.h b/src/mame/includes/wswan.h
deleted file mode 100644
index 2657e33e3c3..00000000000
--- a/src/mame/includes/wswan.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/*****************************************************************************
- *
- * includes/wswan.h
- *
- ****************************************************************************/
-#ifndef MAME_INCLUDES_WSWAN_H
-#define MAME_INCLUDES_WSWAN_H
-
-#pragma once
-
-#define WSWAN_TYPE_MONO 0
-#define WSWAN_TYPE_COLOR 1
-
-#define INTERNAL_EEPROM_SIZE 1024
-
-#include "cpu/v30mz/v30mz.h"
-#include "machine/nvram.h"
-#include "audio/wswan.h"
-#include "video/wswan.h"
-#include "bus/wswan/slot.h"
-#include "bus/wswan/rom.h"
-#include "emupal.h"
-
-
-class wswan_state : public driver_device
-{
-public:
- wswan_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_vdp(*this, "vdp"),
- m_sound(*this, "custom"),
- m_cart(*this, "cartslot"),
- m_cursx(*this, "CURSX"),
- m_cursy(*this, "CURSY"),
- m_buttons(*this, "BUTTONS")
- { }
-
- void wswan(machine_config &config);
-
-protected:
- /* Interrupt flags */
- static const uint8_t WSWAN_IFLAG_STX = 0x01;
- static const uint8_t WSWAN_IFLAG_KEY = 0x02;
- static const uint8_t WSWAN_IFLAG_RTC = 0x04;
- static const uint8_t WSWAN_IFLAG_SRX = 0x08;
- static const uint8_t WSWAN_IFLAG_LCMP = 0x10;
- static const uint8_t WSWAN_IFLAG_VBLTMR = 0x20;
- static const uint8_t WSWAN_IFLAG_VBL = 0x40;
- static const uint8_t WSWAN_IFLAG_HBLTMR = 0x80;
-
- /* Interrupts */
- static const uint8_t WSWAN_INT_STX = 0;
- static const uint8_t WSWAN_INT_KEY = 1;
- static const uint8_t WSWAN_INT_RTC = 2;
- static const uint8_t WSWAN_INT_SRX = 3;
- static const uint8_t WSWAN_INT_LCMP = 4;
- static const uint8_t WSWAN_INT_VBLTMR = 5;
- static const uint8_t WSWAN_INT_VBL = 6;
- static const uint8_t WSWAN_INT_HBLTMR = 7;
-
- struct SoundDMA
- {
- uint32_t source; /* Source address */
- uint16_t size; /* Size */
- uint8_t enable; /* Enabled */
- };
-
- required_device<cpu_device> m_maincpu;
- required_device<wswan_video_device> m_vdp;
- required_device<wswan_sound_device> m_sound;
- required_device<ws_cart_slot_device> m_cart;
-
- uint8_t m_ws_portram[256];
- uint8_t m_internal_eeprom[INTERNAL_EEPROM_SIZE];
- uint8_t m_system_type;
- SoundDMA m_sound_dma;
- std::unique_ptr<uint8_t[]> m_ws_bios_bank;
- uint8_t m_bios_disabled;
- uint8_t m_rotate;
-
- required_ioport m_cursx;
- required_ioport m_cursy;
- required_ioport m_buttons;
-
- uint8_t bios_r(offs_t offset);
- uint8_t port_r(offs_t offset);
- void port_w(offs_t offset, uint8_t data);
-
- void set_irq_line(int irq);
- void dma_sound_cb();
- void common_start();
- virtual void machine_start() override;
- virtual void machine_reset() override;
- void wswan_palette(palette_device &palette) const;
-
- void wswan_io(address_map &map);
- void wswan_mem(address_map &map);
- void wswan_snd(address_map &map);
-
- void register_save();
- void handle_irqs();
- void clear_irq_line(int irq);
-};
-
-class wscolor_state : public wswan_state
-{
-public:
- using wswan_state::wswan_state;
- void wscolor(machine_config &config);
-
-protected:
- virtual void machine_start() override;
- void wscolor_mem(address_map &map);
- void wscolor_palette(palette_device &palette) const;
-};
-
-#endif // MAME_INCLUDES_WSWAN_H
diff --git a/src/mame/machine/wswan.cpp b/src/mame/machine/wswan.cpp
deleted file mode 100644
index c8a942e1a6e..00000000000
--- a/src/mame/machine/wswan.cpp
+++ /dev/null
@@ -1,664 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Anthony Kruize,Wilbert Pol
-/***************************************************************************
-
- wswan.c
-
- Machine file to handle emulation of the Bandai WonderSwan.
-
- Anthony Kruize
- Wilbert Pol
-
-TODO:
- SRAM sizes should be in kbit instead of kbytes(?). This raises a few
- interesting issues:
- - mirror of smaller <64KBYTE/512kbit sram sizes
- - banking when using 1M or 2M sram sizes
-
-***************************************************************************/
-
-#include "emu.h"
-#include "includes/wswan.h"
-#include "render.h"
-
-#define INTERNAL_EEPROM_SIZE 1024
-
-enum enum_system { TYPE_WSWAN=0, TYPE_WSC };
-
-
-static const uint8_t ws_portram_init[256] =
-{
- 0x00, 0x00, 0x00/*?*/, 0xbb, 0x00, 0x00, 0x00, 0x26, 0xfe, 0xde, 0xf9, 0xfb, 0xdb, 0xd7, 0x7f, 0xf5,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x99, 0xfd, 0xb7, 0xdf,
- 0x30, 0x57, 0x75, 0x76, 0x15, 0x73, 0x70/*77?*/, 0x77, 0x20, 0x75, 0x50, 0x36, 0x70, 0x67, 0x50, 0x77,
- 0x57, 0x54, 0x75, 0x77, 0x75, 0x17, 0x37, 0x73, 0x50, 0x57, 0x60, 0x77, 0x70, 0x77, 0x10, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
- 0x87, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xdb, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x83, 0x00,
- 0x2f, 0x3f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
- 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
- 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
- 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1
-};
-
-/*
- Some fake bios code to initialize some registers and set up some things on the wonderswan.
- The code from f:ffe0 which gets copied to 0:0400 is taken from a wonderswan crystal's initial
- memory settings. Lacking real bios dumps we will use this....
-
- The setting of SP to 2000h is what's needed to get Wonderswan Colloseum to boot.
-
- f000:ffc0
- FC cld
- BC 00 20 mov sp,2000h
- 68 00 00 push 0000h
- 07 pop es
- 68 00 F0 push F000h
- 1F pop ds
- BF 00 04 mov di,0400h
- BE E0 FF mov si,FFE0h
- B9 10 00 mov cx,0010h
- F3 A4 rep movsb
- B0 2F mov al,2Fh
- E6 C0 out al,C0h
- EA 00 04 00 00 jmp 0000:0400
-
- f000:ffe0
- E4 A0 in al, A0h
- 0C 01 or al,01h
- E6 A0 out al,A0h
- EA 00 00 FF FF jmp FFFFh:0000h
-
-*/
-static const uint8_t ws_fake_bios_code[] = {
- 0xfc, 0xbc, 0x00, 0x20, 0x68, 0x00, 0x00, 0x07, 0x68, 0x00, 0xf0, 0x1f, 0xbf, 0x00, 0x04, 0xbe,
- 0xe0, 0xff, 0xb9, 0x10, 0x00, 0xf3, 0xa4, 0xb0, 0x2f, 0xe6, 0xc0, 0xea, 0x00, 0x04, 0x00, 0x00,
- 0xe4, 0xa0, 0x0c, 0x01, 0xe6, 0xa0, 0xea, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xea, 0xc0, 0xff, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-void wswan_state::handle_irqs()
-{
- if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_HBLTMR)
- {
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_HBLTMR); // V30MZ
- }
- else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBL)
- {
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBL); // V30MZ
- }
- else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_VBLTMR)
- {
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_VBLTMR); // V30MZ
- }
- else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_LCMP)
- {
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_LCMP); // V30MZ
- }
- else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_SRX)
- {
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_SRX); // V30MZ
- }
- else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_RTC)
- {
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_RTC); // V30MZ
- }
- else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_KEY)
- {
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_KEY); // V30MZ
- }
- else if (m_ws_portram[0xb2] & m_ws_portram[0xb6] & WSWAN_IFLAG_STX)
- {
- m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_ws_portram[0xb0] + WSWAN_INT_STX); // V30MZ
- }
- else
- {
- m_maincpu->set_input_line(0, CLEAR_LINE);
- }
-}
-
-void wswan_state::set_irq_line(int irq)
-{
- if (m_ws_portram[0xb2] & irq)
- {
- m_ws_portram[0xb6] |= irq;
- handle_irqs();
- }
-}
-
-void wswan_state::dma_sound_cb()
-{
- if ((m_sound_dma.enable & 0x88) == 0x80)
- {
- address_space &space = m_maincpu->space(AS_PROGRAM);
- /* TODO: Output sound DMA byte */
- port_w(0x89, space.read_byte(m_sound_dma.source));
- m_sound_dma.size--;
- m_sound_dma.source = (m_sound_dma.source + 1) & 0x0fffff;
- if (m_sound_dma.size == 0)
- {
- m_sound_dma.enable &= 0x7F;
- }
- }
-}
-
-void wswan_state::clear_irq_line(int irq)
-{
- m_ws_portram[0xb6] &= ~irq;
- handle_irqs();
-}
-
-void wswan_state::register_save()
-{
- save_item(NAME(m_ws_portram));
- save_item(NAME(m_internal_eeprom));
- save_item(NAME(m_bios_disabled));
- save_item(NAME(m_rotate));
-
- save_item(NAME(m_sound_dma.source));
- save_item(NAME(m_sound_dma.size));
- save_item(NAME(m_sound_dma.enable));
-
- if (m_cart->exists())
- m_cart->save_nvram();
-}
-
-void wswan_state::common_start()
-{
- m_ws_bios_bank = std::make_unique<uint8_t[]>(0x10000);
- memcpy(m_ws_bios_bank.get() + 0xffc0, ws_fake_bios_code, 0x40);
-
- register_save();
-
- subdevice<nvram_device>("nvram")->set_base(m_internal_eeprom, INTERNAL_EEPROM_SIZE);
-
- if (m_cart->exists())
- {
- // ROM
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x20000, 0x2ffff, read8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::read_rom20)));
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x30000, 0x3ffff, read8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::read_rom30)));
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x40000, 0xeffff, read8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::read_rom40)));
-
- // SRAM
- if (m_cart->get_type() == WS_SRAM)
- {
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x10000, 0x1ffff, read8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::read_ram)));
- m_maincpu->space(AS_PROGRAM).install_write_handler(0x10000, 0x1ffff, write8sm_delegate(*m_cart, FUNC(ws_cart_slot_device::write_ram)));
- }
- }
-}
-
-void wswan_state::machine_start()
-{
- common_start();
- m_system_type = TYPE_WSWAN;
-}
-
-void wscolor_state::machine_start()
-{
- common_start();
- m_system_type = TYPE_WSC;
-}
-
-void wswan_state::machine_reset()
-{
- m_bios_disabled = 0;
-
- if (m_cart->exists())
- m_rotate = m_cart->get_is_rotated();
- else
- m_rotate = 0;
-
- /* Intialize ports */
- memcpy(m_ws_portram, ws_portram_init, 256);
-
- render_target *target = machine().render().first_target();
- target->set_view(m_rotate);
-
- /* Initialize sound DMA */
- memset(&m_sound_dma, 0, sizeof(m_sound_dma));
-}
-
-uint8_t wswan_state::bios_r(offs_t offset)
-{
- if (!m_bios_disabled)
- return m_ws_bios_bank[offset];
- else
- return m_cart->read_rom40(offset + 0xb0000);
-}
-
-uint8_t wswan_state::port_r(offs_t offset)
-{
- uint8_t value = m_ws_portram[offset];
-
- if (offset != 2)
- logerror("PC=%X: port read %02X\n", m_maincpu->pc(), offset);
-
- if (offset < 0x40 || (offset >= 0xa1 && offset < 0xb0))
- return m_vdp->reg_r(offset);
-
- switch (offset)
- {
- case 0x4a: // Sound DMA source address (low)
- value = m_sound_dma.source & 0xff;
- break;
- case 0x4b: // Sound DMA source address (high)
- value = (m_sound_dma.source >> 8) & 0xff;
- break;
- case 0x4c: // Sound DMA source memory segment
- value = (m_sound_dma.source >> 16) & 0xff;
- break;
- case 0x4e: // Sound DMA transfer size (low)
- value = m_sound_dma.size & 0xff;
- break;
- case 0x4f: // Sound DMA transfer size (high)
- value = (m_sound_dma.size >> 8) & 0xff;
- break;
- case 0x52: // Sound DMA start/stop
- value = m_sound_dma.enable;
- break;
- case 0x60:
- value = m_vdp->reg_r(offset);
- break;
- case 0xa0: // Hardware type
- // Bit 0 - Disable/enable Bios
- // Bit 1 - Determine mono/color
- // Bit 2 - Determine color/crystal
- value = value & ~ 0x02;
- if (m_system_type == TYPE_WSC)
- value |= 2;
- break;
- case 0xc0:
- case 0xc1:
- case 0xc2:
- case 0xc3:
- case 0xc4: // EEPROM data
- case 0xc5: // EEPROM data
- case 0xc6:
- case 0xc7:
- case 0xc8:
- case 0xc9:
- case 0xca:
- case 0xcb: // RTC data
- case 0xcc:
- case 0xcd:
- case 0xce:
- case 0xcf:
- value = m_cart->read_io(offset & 0x0f);
- break;
- }
-
- return value;
-}
-
-void wswan_state::port_w(offs_t offset, uint8_t data)
-{
- address_space &mem = m_maincpu->space(AS_PROGRAM);
- uint8_t input;
- logerror("PC=%X: port write %02X <- %02X\n", m_maincpu->pc(), offset, data);
-
- if (offset < 0x40 || (offset >= 0xa1 && offset < 0xb0))
- {
- m_vdp->reg_w(offset, data);
- return;
- }
-
- switch (offset)
- {
- case 0x40: /* DMA source address (low)
- Bit 0-7 - DMA source address bit 0-7
- */
- case 0x41: /* DMA source address (high)
- Bit 0-7 - DMA source address bit 8-15
- */
- case 0x42: /* DMA source bank
- Bit 0-7 - DMA source bank number
- */
- case 0x43: /* DMA destination bank
- Bit 0-7 - DMA destination bank number
- */
- case 0x44: /* DMA destination address (low)
- Bit 0-7 - DMA destination address bit 0-7
- */
- case 0x45: /* DMA destination address (high)
- Bit 0-7 - DMA destination address bit 8-15
- */
- case 0x46: /* Size of copied data (low)
- Bit 0-7 - DMA size bit 0-7
- */
- case 0x47: /* Size of copied data (high)
- Bit 0-7 - DMA size bit 8-15
- */
- break;
- case 0x48: /* DMA control
- Bit 0-6 - Unknown
- Bit 7 - DMA stop/start
- */
- if (data & 0x80)
- {
- uint32_t src, dst;
- uint16_t length;
-
- src = m_ws_portram[0x40] + (m_ws_portram[0x41] << 8) + (m_ws_portram[0x42] << 16);
- dst = m_ws_portram[0x44] + (m_ws_portram[0x45] << 8) + (m_ws_portram[0x43] << 16);
- length = m_ws_portram[0x46] + (m_ws_portram[0x47] << 8);
- for ( ; length > 0; length--)
- {
- mem.write_byte(dst, mem.read_byte(src));
- src++;
- dst++;
- }
-#ifdef MAME_DEBUG
- logerror("DMA src:%X dst:%X length:%d\n", src, dst, length);
-#endif
- m_ws_portram[0x40] = src & 0xff;
- m_ws_portram[0x41] = (src >> 8) & 0xff;
- m_ws_portram[0x44] = dst & 0xff;
- m_ws_portram[0x45] = (dst >> 8) & 0xff;
- m_ws_portram[0x46] = length & 0xff;
- m_ws_portram[0x47] = (length >> 8) & 0xff;
- data &= 0x7f;
- }
- break;
- case 0x4a: /* Sound DMA source address (low)
- Bit 0-7 - Sound DMA source address bit 0-7
- */
- m_sound_dma.source = (m_sound_dma.source & 0x0fff00) | data;
- break;
- case 0x4b: /* Sound DMA source address (high)
- Bit 0-7 - Sound DMA source address bit 8-15
- */
- m_sound_dma.source = (m_sound_dma.source & 0x0f00ff) | (data << 8);
- break;
- case 0x4c: /* Sound DMA source memory segment
- Bit 0-3 - Sound DMA source address segment
- Bit 4-7 - Unknown
- */
- m_sound_dma.source = (m_sound_dma.source & 0xffff) | ((data & 0x0f) << 16);
- break;
- case 0x4d: /* Unknown */
- break;
- case 0x4e: /* Sound DMA transfer size (low)
- Bit 0-7 - Sound DMA transfer size bit 0-7
- */
- m_sound_dma.size = (m_sound_dma.size & 0xff00) | data;
- break;
- case 0x4f: /* Sound DMA transfer size (high)
- Bit 0-7 - Sound DMA transfer size bit 8-15
- */
- m_sound_dma.size = (m_sound_dma.size & 0xff) | (data << 8);
- break;
- case 0x50: /* Unknown */
- case 0x51: /* Unknown */
- break;
- case 0x52: /* Sound DMA start/stop
- Bit 0-6 - Unknown
- Bit 7 - Sound DMA stop/start
- */
- m_sound_dma.enable = data;
- break;
- case 0x60:
- m_vdp->reg_w(offset, data);
- break;
- case 0x80: /* Audio 1 freq (lo)
- Bit 0-7 - Audio channel 1 frequency bit 0-7
- */
- case 0x81: /* Audio 1 freq (hi)
- Bit 0-7 - Audio channel 1 frequency bit 8-15
- */
- case 0x82: /* Audio 2 freq (lo)
- Bit 0-7 - Audio channel 2 frequency bit 0-7
- */
- case 0x83: /* Audio 2 freq (hi)
- Bit 0-7 - Audio channel 2 frequency bit 8-15
- */
- case 0x84: /* Audio 3 freq (lo)
- Bit 0-7 - Audio channel 3 frequency bit 0-7
- */
- case 0x85: /* Audio 3 freq (hi)
- Bit 0-7 - Audio channel 3 frequency bit 8-15
- */
- case 0x86: /* Audio 4 freq (lo)
- Bit 0-7 - Audio channel 4 frequency bit 0-7
- */
- case 0x87: /* Audio 4 freq (hi)
- Bit 0-7 - Audio channel 4 frequency bit 8-15
- */
- case 0x88: /* Audio 1 volume
- Bit 0-3 - Right volume audio channel 1
- Bit 4-7 - Left volume audio channel 1
- */
- case 0x89: /* Audio 2 volume
- Bit 0-3 - Right volume audio channel 2
- Bit 4-7 - Left volume audio channel 2
- */
- case 0x8a: /* Audio 3 volume
- Bit 0-3 - Right volume audio channel 3
- Bit 4-7 - Left volume audio channel 3
- */
- case 0x8b: /* Audio 4 volume
- Bit 0-3 - Right volume audio channel 4
- Bit 4-7 - Left volume audio channel 4
- */
- case 0x8c: /* Sweep step
- Bit 0-7 - Sweep step
- */
- case 0x8d: /* Sweep time
- Bit 0-7 - Sweep time
- */
- case 0x8e: /* Noise control
- Bit 0-2 - Noise generator type
- Bit 3 - Reset
- Bit 4 - Enable
- Bit 5-7 - Unknown
- */
- case 0x8f: /* Sample location
- Bit 0-7 - Sample address location 0 00xxxxxx xx000000
- */
- case 0x90: /* Audio control
- Bit 0 - Audio 1 enable
- Bit 1 - Audio 2 enable
- Bit 2 - Audio 3 enable
- Bit 3 - Audio 4 enable
- Bit 4 - Unknown
- Bit 5 - Audio 2 voice mode enable
- Bit 6 - Audio 3 sweep mode enable
- Bit 7 - Audio 4 noise mode enable
- */
- case 0x91: /* Audio output
- Bit 0 - Mono select
- Bit 1-2 - Output volume
- Bit 3 - External stereo
- Bit 4-6 - Unknown
- Bit 7 - External speaker (Read-only, set by hardware)
- */
- case 0x92: /* Noise counter shift register (lo)
- Bit 0-7 - Noise counter shift register bit 0-7
- */
- case 0x93: /* Noise counter shift register (hi)
- Bit 0-6 - Noise counter shift register bit 8-14
- bit 7 - Unknown
- */
- case 0x94: /* Master volume
- Bit 0-3 - Master volume
- Bit 4-7 - Unknown
- */
- m_sound->port_w(offset, data);
- break;
- case 0xa0: /* Hardware type - this is probably read only
- Bit 0 - Enable cartridge slot and/or disable bios
- Bit 1 - Hardware type: 0 = WS, 1 = WSC
- Bit 2-7 - Unknown
- */
- if ((data & 0x01) && !m_bios_disabled)
- m_bios_disabled = 1;
- break;
-
- case 0xb0: /* Interrupt base vector
- Bit 0-7 - Interrupt base vector
- */
- break;
- case 0xb1: /* Communication byte
- Bit 0-7 - Communication byte
- */
- break;
- case 0xb2: /* Interrupt enable
- Bit 0 - Serial transmit interrupt enable
- Bit 1 - Key press interrupt enable
- Bit 2 - RTC alarm interrupt enable
- Bit 3 - Serial receive interrupt enable
- Bit 4 - Drawing line detection interrupt enable
- Bit 5 - VBlank timer interrupt enable
- Bit 6 - VBlank interrupt enable
- Bit 7 - HBlank timer interrupt enable
- */
- break;
- case 0xb3: /* serial communication control
- Bit 0 - Receive complete
- Bit 1 - Error
- Bit 2 - Send complete
- Bit 3-4 - Unknown
- Bit 5 - Send data interrupt generation
- Bit 6 - Connection speed: 0 = 9600 bps, 1 = 38400 bps
- bit 7 - Receive data interrupt generation
- */
- // data |= 0x02;
- m_ws_portram[0xb1] = 0xff;
- if (data & 0x80)
- {
- // m_ws_portram[0xb1] = 0x00;
- data |= 0x04;
- }
- if (data & 0x20)
- {
- // data |= 0x01;
- }
- break;
- case 0xb5: /* Read controls
- Bit 0-3 - Current state of input lines (read-only)
- Bit 4-6 - Select line of inputs to read
- 001 - Read Y cursors
- 010 - Read X cursors
- 100 - Read START,A,B buttons
- Bit 7 - Unknown
- */
- data = data & 0xf0;
- switch (data)
- {
- case 0x10: /* Read Y cursors: Y1 - Y2 - Y3 - Y4 */
- input = m_cursy->read();
- if (m_rotate) // reorient controls if the console is rotated
- {
- if (input & 0x01) data |= 0x02;
- if (input & 0x02) data |= 0x04;
- if (input & 0x04) data |= 0x08;
- if (input & 0x08) data |= 0x01;
- }
- else
- data = data | input;
- break;
- case 0x20: /* Read X cursors: X1 - X2 - X3 - X4 */
- input = m_cursx->read();
- if (m_rotate) // reorient controls if the console is rotated
- {
- if (input & 0x01) data |= 0x02;
- if (input & 0x02) data |= 0x04;
- if (input & 0x04) data |= 0x08;
- if (input & 0x08) data |= 0x01;
- }
- else
- data = data | input;
- break;
- case 0x40: /* Read buttons: START - A - B */
- data = data | m_buttons->read();
- break;
- }
- break;
- case 0xb6: /* Interrupt acknowledge
- Bit 0 - Serial transmit interrupt acknowledge
- Bit 1 - Key press interrupt acknowledge
- Bit 2 - RTC alarm interrupt acknowledge
- Bit 3 - Serial receive interrupt acknowledge
- Bit 4 - Drawing line detection interrupt acknowledge
- Bit 5 - VBlank timer interrupt acknowledge
- Bit 6 - VBlank interrupt acknowledge
- Bit 7 - HBlank timer interrupt acknowledge
- */
- clear_irq_line(data);
- data = m_ws_portram[0xb6];
- break;
- case 0xba: /* Internal EEPROM data (low)
- Bit 0-7 - Internal EEPROM data transfer bit 0-7
- */
- case 0xbb: /* Internal EEPROM data (high)
- Bit 0-7 - Internal EEPROM data transfer bit 8-15
- */
- break;
- case 0xbc: /* Internal EEPROM address (low)
- Bit 0-7 - Internal EEPROM address bit 1-8
- */
- case 0xbd: /* Internal EEPROM address (high)
- Bit 0 - Internal EEPROM address bit 9(?)
- Bit 1-7 - Unknown
- Only 1KByte internal EEPROM??
- */
- break;
- case 0xbe: /* Internal EEPROM command
- Bit 0 - Read complete (read only)
- Bit 1 - Write complete (read only)
- Bit 2-3 - Unknown
- Bit 4 - Read
- Bit 5 - Write
- Bit 6 - Protect
- Bit 7 - Initialize
- */
- if (data & 0x20)
- {
- uint16_t addr = ( ( ( m_ws_portram[0xbd] << 8 ) | m_ws_portram[0xbc] ) << 1 ) & 0x1FF;
- m_internal_eeprom[ addr ] = m_ws_portram[0xba];
- m_internal_eeprom[ addr + 1 ] = m_ws_portram[0xbb];
- data |= 0x02;
- }
- else if ( data & 0x10 )
- {
- uint16_t addr = ( ( ( m_ws_portram[0xbd] << 8 ) | m_ws_portram[0xbc] ) << 1 ) & 0x1FF;
- m_ws_portram[0xba] = m_internal_eeprom[ addr ];
- m_ws_portram[0xbb] = m_internal_eeprom[ addr + 1];
- data |= 0x01;
- }
- else
- {
- logerror( "Unsupported internal EEPROM command: %X\n", data );
- }
- break;
- case 0xc0: // ROM bank $40000-$fffff
- case 0xc1: // SRAM bank
- case 0xc2: // ROM bank $20000-$2ffff
- case 0xc3: // ROM bank $30000-$3ffff
- case 0xc4:
- case 0xc5:
- case 0xc6: // EEPROM address / command
- case 0xc7: // EEPROM address / command
- case 0xc8: // EEPROM command
- case 0xc9:
- case 0xca: // RTC command
- case 0xcb: // RTC data
- case 0xcc:
- case 0xcd:
- case 0xce:
- case 0xcf:
- m_cart->write_io(offset & 0x0f, data);
- break;
- default:
- logerror( "Write to unsupported port: %X - %X\n", offset, data );
- break;
- }
-
- /* Update the port value */
- m_ws_portram[offset] = data;
-}
diff --git a/src/mame/video/wswan.cpp b/src/mame/video/wswan.cpp
index 258925e2058..a6866091546 100644
--- a/src/mame/video/wswan.cpp
+++ b/src/mame/video/wswan.cpp
@@ -9,7 +9,8 @@
TODO:
- remove the redundant parts of m_regs
- - split the Color VDP from the Mono VDP?
+ - split the Color VDP from the Mono VDP
+ - Add support for WSC high/low contrast (register 14, bit 1)
***************************************************************************/
@@ -804,8 +805,7 @@ void wswan_video_device::refresh_scanline()
rectangle rec(0, WSWAN_X_PIXELS, m_current_line, m_current_line);
if (m_lcd_control)
{
- /* Not sure if these background color checks and settings are correct */
- if (m_color_mode && m_colors_16)
+ if (m_color_mode)
m_bitmap.fill(m_pal[m_bg_control >> 4][m_bg_control & 0x0f], rec);
else
m_bitmap.fill(m_main_palette[m_bg_control & 0x07], rec);
@@ -1007,7 +1007,8 @@ void wswan_video_device::reg_w(offs_t offset, uint8_t data)
break;
case 0x14: // LCD control
// Bit 0 - LCD enable
- // Bit 1-7 - Unknown
+ // Bit 1 - WSC only, brightness low/high
+ // Bit 2-7 - Unknown
m_lcd_control = data;
break;
case 0x15: // LCD icons
diff --git a/src/mame/video/wswan.h b/src/mame/video/wswan.h
index a7df4401e77..0ca4b6d3c1d 100644
--- a/src/mame/video/wswan.h
+++ b/src/mame/video/wswan.h
@@ -16,20 +16,6 @@
#pragma once
-
-enum
-{
- VDP_TYPE_WSWAN = 0,
- VDP_TYPE_WSC
-};
-
-#define WSWAN_X_PIXELS (28*8)
-#define WSWAN_Y_PIXELS (18*8)
-
-
-#define WSWAN_VIDEO_IRQ_CB_MEMBER(_name) void _name(int irq)
-#define WSWAN_VIDEO_DMASND_CB_MEMBER(_name) void _name()
-
class wswan_video_device : public device_t, public device_video_interface
{
public:
@@ -51,6 +37,15 @@ public:
uint8_t reg_r(offs_t offset);
void reg_w(offs_t offset, uint8_t data);
+ enum
+ {
+ VDP_TYPE_WSWAN = 0,
+ VDP_TYPE_WSC
+ };
+
+ static const u16 WSWAN_X_PIXELS = (28*8);
+ static const u16 WSWAN_Y_PIXELS = (18*8);
+
protected:
// device-level overrides
virtual void device_start() override;