// license:LGPL-2.1+ // copyright-holders:Angelo Salese, R. Belmont /* dccons.cpp - Sega Dreamcast driver by R. Belmont & Angelo Salese SH-4 @ 200 MHz ARM7DI @ 2.8223 MHz (no T or M extensions) PowerVR 3D video AICA audio GD-ROM drive (modified ATAPI interface) NTSC/N NTSC/I PAL/N PAL/I VGA (x/240) (x/480) (x/240) (x/480) (640x480) VTOTAL 262 524 312 624 524 HTOTAL 857 857 863 863 857 PCLKs = 26917135 (NTSC 480 @ 59.94), 26944080 (VGA 480 @ 60.0), 13458568 (NTSC 240 @ 59.94), 25925600 (PAL 480 @ 50.00), 13462800 (PAL 240 @ 50.00) TODO: - RTC error always pops up at start-up, no flash plus bug with ticks (needs rewrite) - cfr. naomi.cpp header for general DC notes; - https://github.com/flyinghead/flycast/blob/master/docs/Notable%20game%20bugs.md For a comprehensive list of issues to be verified; - Fix Check-GD disk usability, cfr. notes in dc.xml; - G1 i/f for GD-ROM needs to be converted in device class and hunted for unsupported features; - VMU; - Modem; Old TODO (to be rechecked and moved in XML notes): - Inputs doesn't work most of the time; - Candy Stripe: fills the log with "ATAPI_FEATURES_FLAG_OVL not supported", black screen - Carrier: Jaleco logo uses YUV, but y size is halved? - Close To: Hangs at FMV - F355 Challenge: black screen after Sega logo; - Gundam - Side Story 0079: currently hangs at Bandai logo (regression) - Idol Janshi wo Tsukucchaou: pixel aspect is way wrong (stretched and offsetted horizontally) - Power Stone: hangs at Capcom logo; - Sega GT: no cursor on main menu; - Tetris 4D: hangs at BPS FMV (bp 0C0B0C4E) Notes: - 0x1a002 of flash ROM returns the region type (0x30=Japan, 0x31=USA, 0x32=Europe). Amusingly, if the value on a non-jp console is different than these ones, the system shows a black swirl (and nothing boots). */ #include "emu.h" #include "includes/dccons.h" #include "cpu/arm7/arm7.h" #include "cpu/arm7/arm7core.h" #include "cpu/sh/sh4.h" #include "imagedev/chd_cd.h" #include "machine/aicartc.h" #include "machine/dc-ctrl.h" #include "machine/gdrom.h" //#include "emupal.h" #include "screen.h" #include "speaker.h" #include "softlist.h" #define CPU_CLOCK (200000000) // cfr. sh4.cpp m_mmuhack #define DC_MMU_HACK_MODE (1) void dc_cons_state::init_dc() { m_maincpu->sh2drc_set_options(SH2DRC_STRICT_VERIFY | SH2DRC_STRICT_PCREL); m_maincpu->sh2drc_add_fastram(0x00000000, 0x001fffff, true, memregion("maincpu")->base()); m_maincpu->sh2drc_add_fastram(0x0c000000, 0x0cffffff, false, dc_ram); dreamcast_atapi_init(); } void dc_cons_state::init_tream() { // Modchip connected to BIOS ROM chip changes 4 bytes (actually bits) as shown below, which allow to boot any region games. u8 *rom = (u8 *)memregion("maincpu")->base(); rom[0x503] |= 0x40; rom[0x50f] |= 0x40; rom[0x523] |= 0x40; rom[0x531] |= 0x40; init_dc(); } uint64_t dc_cons_state::dc_pdtra_r() { uint64_t out = PCTRA<<32; out |= PDTRA & ~0x0303; // if both bits are inputs if (!(PCTRA & 0x5)) { out |= 0x03; } // one's input one's output, always pull up both bits if (((PCTRA & 5) == 1) || ((PCTRA & 5) == 4)) { if (PDTRA & 3) { out |= 0x03; } } // cable setting, (0) VGA, (2) TV RGB (3) TV VBS/Y + S/C. // Note: several games doesn't like VGA setting, // default to composite for max possible compatibility // (i.e. Idol Janshi wo Tsukucchaou, Airforce Delta) // TODO: identify via script out |= ioport("SCREEN_TYPE")->read() << 8; return out; } void dc_cons_state::dc_pdtra_w(uint64_t data) { PCTRA = (data>>16) & 0xffff; PDTRA = (data & 0xffff); } uint8_t dc_cons_state::dc_flash_r(offs_t offset) { return m_dcflash->read(offset+0x20000); } void dc_cons_state::dc_flash_w(offs_t offset, uint8_t data) { m_dcflash->write(offset+0x20000,data); } void dc_cons_state::dc_map(address_map &map) { map(0x00000000, 0x001fffff).rom().nopw(); // BIOS map(0x00200000, 0x0021ffff).rw(FUNC(dc_cons_state::dc_flash_r), FUNC(dc_cons_state::dc_flash_w)); map(0x005f6800, 0x005f69ff).rw(FUNC(dc_cons_state::dc_sysctrl_r), FUNC(dc_cons_state::dc_sysctrl_w)); map(0x005f6c00, 0x005f6cff).m(m_maple, FUNC(maple_dc_device::amap)); map(0x005f7000, 0x005f701f).rw(m_ata, FUNC(ata_interface_device::cs1_r), FUNC(ata_interface_device::cs1_w)).umask64(0x0000ffff0000ffff); map(0x005f7080, 0x005f709f).rw(m_ata, FUNC(ata_interface_device::cs0_r), FUNC(ata_interface_device::cs0_w)).umask64(0x0000ffff0000ffff); map(0x005f7400, 0x005f74ff).rw(FUNC(dc_cons_state::dc_mess_g1_ctrl_r), FUNC(dc_cons_state::dc_mess_g1_ctrl_w)); map(0x005f7800, 0x005f78ff).m(m_g2if, FUNC(dc_g2if_device::amap)); map(0x005f7c00, 0x005f7cff).m(m_powervr2, FUNC(powervr2_device::pd_dma_map)); map(0x005f8000, 0x005f9fff).m(m_powervr2, FUNC(powervr2_device::ta_map)); map(0x00600000, 0x006007ff).rw(FUNC(dc_cons_state::dc_modem_r), FUNC(dc_cons_state::dc_modem_w)); map(0x00700000, 0x00707fff).rw(FUNC(dc_cons_state::dc_aica_reg_r), FUNC(dc_cons_state::dc_aica_reg_w)); map(0x00710000, 0x0071000f).mirror(0x02000000).rw("aicartc", FUNC(aicartc_device::read), FUNC(aicartc_device::write)).umask64(0x0000ffff0000ffff); map(0x00800000, 0x009fffff).mirror(0x02000000).rw(FUNC(dc_cons_state::soundram_r), FUNC(dc_cons_state::soundram_w)); // map(0x01000000, 0x01ffffff) G2 Ext Device #1 // map(0x02700000, 0x02707fff) AICA reg mirror // map(0x02800000, 0x02ffffff) AICA wave mem mirror (loopchk g2 bus DMA test) // map(0x03000000, 0x03ffffff) G2 Ext Device #2 /* Area 1 */ map(0x04000000, 0x04ffffff).ram().share("dc_texture_ram"); // texture memory 64 bit access map(0x05000000, 0x05ffffff).ram().share("frameram"); // apparently this actually accesses the same memory as the 64-bit texture memory access, but in a different format, keep it apart for now /* Area 3 */ map(0x0c000000, 0x0cffffff).ram().share("dc_ram"); map(0x0d000000, 0x0dffffff).ram().share("dc_ram");// extra ram on Naomi (mirror on DC) map(0x0e000000, 0x0effffff).ram().share("dc_ram");// mirror map(0x0f000000, 0x0fffffff).ram().share("dc_ram");// mirror /* Area 4 */ map(0x10000000, 0x107fffff).w(m_powervr2, FUNC(powervr2_device::ta_fifo_poly_w)); map(0x10800000, 0x10ffffff).w(m_powervr2, FUNC(powervr2_device::ta_fifo_yuv_w)); map(0x11000000, 0x117fffff).w(m_powervr2, FUNC(powervr2_device::ta_texture_directpath0_w)).mirror(0x00800000); // access to texture / framebuffer memory (either 32-bit or 64-bit area depending on SB_LMMODE0 register - cannot be written directly, only through dma / store queue map(0x12000000, 0x127fffff).w(m_powervr2, FUNC(powervr2_device::ta_fifo_poly_w)); map(0x12800000, 0x12ffffff).w(m_powervr2, FUNC(powervr2_device::ta_fifo_yuv_w)); map(0x13000000, 0x137fffff).w(m_powervr2, FUNC(powervr2_device::ta_texture_directpath1_w)).mirror(0x00800000); // access to texture / framebuffer memory (either 32-bit or 64-bit area depending on SB_LMMODE1 register - cannot be written directly, only through dma / store queue // map(0x14000000, 0x17ffffff) G2 Ext Device #3 map(0x8c000000, 0x8cffffff).ram().share("dc_ram"); // another RAM mirror map(0xa0000000, 0xa01fffff).rom().region("maincpu", 0); map(0xf4000000, 0xf4003fff).noprw(); // SH-4 operand cache address array } void dc_cons_state::dc_port(address_map &map) { map(0x00000000, 0x00000007).rw(FUNC(dc_cons_state::dc_pdtra_r), FUNC(dc_cons_state::dc_pdtra_w)); } void dc_cons_state::dc_audio_map(address_map &map) { map.unmap_value_high(); map(0x00000000, 0x001fffff).rw(FUNC(dc_cons_state::soundram_r), FUNC(dc_cons_state::soundram_w)); /* shared with SH-4 */ map(0x00800000, 0x00807fff).rw(FUNC(dc_cons_state::dc_arm_aica_r), FUNC(dc_cons_state::dc_arm_aica_w)); } void dc_cons_state::aica_map(address_map &map) { map.unmap_value_high(); map(0x000000, 0x1fffff).ram().share("dc_sound_ram"); } static INPUT_PORTS_START( dc ) PORT_START("P1:0") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 RIGHT") PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 LEFT") PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 DOWN") PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 UP") PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) PORT_NAME("P1 START") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P1 C") PORT_START("P1:1") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 2nd directional pad PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P1 D") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 X") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 Y") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P1 Z") PORT_START("P1:A0") PORT_BIT( 0xff, 0x00, IPT_PEDAL2 ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_NAME("P1 R") PORT_PLAYER(1) PORT_START("P1:A1") PORT_BIT( 0xff, 0x00, IPT_PEDAL ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_NAME("P1 L") PORT_PLAYER(1) PORT_START("P1:A2") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_PLAYER(1) PORT_START("P1:A3") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_PLAYER(1) //A4 - A5, second analog stick, unused on DC PORT_START("P2:0") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 RIGHT") PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 LEFT") PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 DOWN") PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 UP") PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START2 ) PORT_NAME("P2 START") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P2 C") PORT_START("P2:1") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 2nd directional pad PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P1 D") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 X") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 Y") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P1 Z") PORT_START("P2:A0") PORT_BIT( 0xff, 0x00, IPT_PEDAL2 ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_NAME("P2 R") PORT_PLAYER(2) PORT_START("P2:A1") PORT_BIT( 0xff, 0x00, IPT_PEDAL ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_NAME("P2 L") PORT_PLAYER(2) PORT_START("P2:A2") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_PLAYER(2) PORT_START("P2:A3") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_PLAYER(2) //A4 - A5, second analog stick, unused on DC PORT_START("P3:0") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3) PORT_NAME("P3 RIGHT") PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3) PORT_NAME("P3 LEFT") PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3) PORT_NAME("P3 DOWN") PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3) PORT_NAME("P3 UP") PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START3 ) PORT_NAME("P3 START") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3) PORT_NAME("P3 A") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3) PORT_NAME("P3 B") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P3 C") PORT_START("P3:1") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 2nd directional pad PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P3 D") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3) PORT_NAME("P3 X") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(3) PORT_NAME("P3 Y") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P3 Z") PORT_START("P3:A0") PORT_BIT( 0xff, 0x00, IPT_PEDAL2 ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_NAME("P3 R") PORT_PLAYER(3) PORT_START("P3:A1") PORT_BIT( 0xff, 0x00, IPT_PEDAL ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_NAME("P3 L") PORT_PLAYER(3) PORT_START("P3:A2") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_PLAYER(3) PORT_START("P3:A3") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_PLAYER(3) //A4 - A5, second analog stick, unused on DC PORT_START("P4:0") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4) PORT_NAME("P4 RIGHT") PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4) PORT_NAME("P4 LEFT") PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4) PORT_NAME("P4 DOWN") PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(4) PORT_NAME("P4 UP") PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START4 ) PORT_NAME("P4 START") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4) PORT_NAME("P4 A") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4) PORT_NAME("P4 B") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P4 C") PORT_START("P4:1") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 2nd directional pad PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P3 D") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(4) PORT_NAME("P4 X") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(4) PORT_NAME("P4 Y") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) //PORT_NAME("P3 Z") PORT_START("P4:A0") PORT_BIT( 0xff, 0x00, IPT_PEDAL2 ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_NAME("P4 R") PORT_PLAYER(4) PORT_START("P4:A1") PORT_BIT( 0xff, 0x00, IPT_PEDAL ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_NAME("P4 L") PORT_PLAYER(4) PORT_START("P4:A2") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_PLAYER(4) PORT_START("P4:A3") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(10) PORT_CENTERDELTA(10) PORT_PLAYER(4) //A4 - A5, second analog stick, unused on DC PORT_START("SCREEN_TYPE") PORT_CONFNAME( 0x03, 0x03, "Screen Connection Type" ) PORT_CONFSETTING( 0x00, "VGA" ) PORT_CONFSETTING( 0x02, "Composite" ) PORT_CONFSETTING( 0x03, "S-Video" ) INPUT_PORTS_END static INPUT_PORTS_START( dcfish ) PORT_START("P1:0") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) PORT_NAME("CONFIG") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("SCREEN_TYPE") PORT_CONFNAME( 0x03, 0x03, "Screen Connection Type" ) PORT_CONFSETTING( 0x00, "VGA" ) PORT_CONFSETTING( 0x02, "Composite" ) PORT_CONFSETTING( 0x03, "S-Video" ) INPUT_PORTS_END void dc_cons_state::gdrom_config(device_t *device) { cdda_device *cdda = device->subdevice("cdda"); cdda->add_route(0, "^^aica", 0.4); cdda->add_route(1, "^^aica", 0.4); } void dc_cons_state::dc_base(machine_config &config) { /* basic machine hardware */ SH4LE(config, m_maincpu, CPU_CLOCK); m_maincpu->set_md(0, 1); m_maincpu->set_md(1, 0); m_maincpu->set_md(2, 1); m_maincpu->set_md(3, 0); m_maincpu->set_md(4, 0); m_maincpu->set_md(5, 1); m_maincpu->set_md(6, 0); m_maincpu->set_md(7, 1); m_maincpu->set_md(8, 0); m_maincpu->set_sh4_clock(CPU_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &dc_cons_state::dc_map); m_maincpu->set_addrmap(AS_IO, &dc_cons_state::dc_port); m_maincpu->set_mmu_hacktype(DC_MMU_HACK_MODE); TIMER(config, "scantimer").configure_scanline(FUNC(dc_state::dc_scanline), "screen", 0, 1); system_bus_config(config, "maincpu"); ARM7(config, m_soundcpu, ((XTAL(33'868'800)*2)/3)/8); // AICA bus clock is 2/3rds * 33.8688. ARM7 gets 1 bus cycle out of each 8. m_soundcpu->set_addrmap(AS_PROGRAM, &dc_cons_state::dc_audio_map); MCFG_MACHINE_RESET_OVERRIDE(dc_cons_state,dc_console ) FUJITSU_29LV002TC(config, "dcflash"); MAPLE_DC(config, m_maple, 0, m_maincpu); m_maple->irq_callback().set(FUNC(dc_state::maple_irq)); /* video hardware */ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); // TODO: find exact pclk source screen.set_raw(13458568*2, 857, 0, 640, 524, 0, 480); screen.set_screen_update("powervr2", FUNC(powervr2_device::screen_update)); POWERVR2(config, m_powervr2, 0); m_powervr2->irq_callback().set(FUNC(dc_state::pvr_irq)); SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); AICA(config, m_aica, (XTAL(33'868'800)*2)/3); // 67.7376MHz(2*33.8688MHz), div 3 for audio block m_aica->irq().set(FUNC(dc_state::aica_irq)); m_aica->main_irq().set(FUNC(dc_state::sh4_aica_irq)); m_aica->set_addrmap(0, &dc_cons_state::aica_map); m_aica->add_route(0, "lspeaker", 0.4); m_aica->add_route(1, "rspeaker", 0.4); AICARTC(config, "aicartc", XTAL(32'768)); ATA_INTERFACE(config, m_ata, 0); m_ata->irq_handler().set(FUNC(dc_cons_state::ata_interrupt)); ata_slot_device &ata_0(*subdevice("ata:0")); ata_0.option_add("gdrom", GDROM); ata_0.set_option_machine_config("gdrom", gdrom_config); ata_0.set_default_option("gdrom"); } void dc_cons_state::dc(machine_config &config) { dc_base(config); dc_controller_device &dcctrl0(DC_CONTROLLER(config, "dcctrl0", 0, m_maple, 0)); dcctrl0.set_port_tags("P1:0", "P1:1", "P1:A0", "P1:A1", "P1:A2", "P1:A3", "P1:A4", "P1:A5"); dc_controller_device &dcctrl1(DC_CONTROLLER(config, "dcctrl1", 0, m_maple, 1)); dcctrl1.set_port_tags("P2:0", "P2:1", "P2:A0", "P2:A1", "P2:A2", "P2:A3", "P2:A4", "P2:A5"); dc_controller_device &dcctrl2(DC_CONTROLLER(config, "dcctrl2", 0, m_maple, 2)); dcctrl2.set_port_tags("P3:0", "P3:1", "P3:A0", "P3:A1", "P3:A2", "P3:A3", "P3:A4", "P3:A5"); dc_controller_device &dcctrl3(DC_CONTROLLER(config, "dcctrl3", 0, m_maple, 3)); dcctrl3.set_port_tags("P4:0", "P4:1", "P4:A0", "P4:A1", "P4:A2", "P4:A3", "P4:A4", "P4:A5"); SOFTWARE_LIST(config, "cd_list").set_original("dc"); } void dc_cons_state::dc_fish(machine_config &config) { dc_base(config); dc_controller_device &dcctrl0(DC_CONTROLLER(config, "dcctrl0", 0, m_maple, 0)); dcctrl0.set_port_tag<0>("P1:0"); } #define ROM_LOAD_BIOS(bios,name,offset,length,hash) \ ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_BIOS(bios)) // known undumped or private BIOS revisions: // "MPR-21068 SEGA JAPAN / 9850 D" from VA0 837-13392-02 (171-7782B) NTSC-J unit // KABUTO Ver.1.011 CRC 34DA5C88 from pre-release US unit (private) // MPR-21933 (5v/VA0) confirmed match MPR-21931 (3.3v/VA1) - v1.01d // actual mask rom labels may have -X1 or -X2 added depending on chip manufacturer, contents is the same #define DREAMCAST_COMMON_BIOS \ ROM_REGION(0x200000, "maincpu", 0) \ ROM_SYSTEM_BIOS(0, "101d", "v1.01d (World)") \ ROM_LOAD_BIOS(0, "mpr-21931.ic501", 0x000000, 0x200000, CRC(89f2b1a1) SHA1(8951d1bb219ab2ff8583033d2119c899cc81f18c) ) \ ROM_SYSTEM_BIOS(1, "1022", "v1.022 (World)") \ ROM_LOAD_BIOS(1, "mpr-23588.ic501", 0x000000, 0x200000, CRC(786168f9) SHA1(ba8bbb90fdb29525f24f17055dc2c7b2d7674437) ) \ ROM_SYSTEM_BIOS(2, "101c", "v1.01c (World)") \ ROM_LOAD_BIOS(2, "mpr-21871.ic501", 0x000000, 0x200000, CRC(2f551bc5) SHA1(1ede8d5be49116a4c6f3fe0961175469537a0434) ) \ ROM_SYSTEM_BIOS(3, "101dch", "v1.01d (Chinese hack)") \ ROM_LOAD_BIOS(3, "dc101d_ch.bin", 0x000000, 0x200000, CRC(a2564fad) SHA1(edc5d3d70a93c935703d26119b37731fd317d2bf) ) // ^^^ dc101d_ch.bin ^^^ is selfmade Chinese translation, doesn't work on real hardware, does it must be here at all ? /* note: Dreamcast Flash ROMs actually 256KB MBM29F002TC (5v/VA0) or MBM29LV002TC (3.3v/VA1) devices, only 2nd 128KB half is used, A17 pin tied to VCC sector SA5 (1A000 - 1BFFF) is read-only, contain information written during manufacture or repair, fully generated by software tool (except predefined list of creators) struct factory_sector { struct factory_record { // everything 'char' below is decimal numbers in ASCII, unless noted else char machine_code1; // '0' - Dreamcast, 0xFF - dev.box char machine_code2; // '0' - Dreamcast, 0xFF - dev.box char country_code; // 0 - Japan, 1 - America, 2 - Europe char language; // 0 - Japanese, 1 - English, etc char broadcast_format; // 0 - NTSC, 1 - PAL, 2 - PAL-M, 3 - PAL-N char machine_name[32]; // ASCII text 'Dreamcast', trail is 0x20 filled char tool_number[4]; // software tool # char tool_version[2]; // software tool version char tool_type[2]; // software tool type: 0 - for MP(mass production?), 1 - for Repair, 2 - for PP char year[4]; char month[2]; char day[2]; char hour[2]; char min[2]; char serial_number[8]; char factory_code[4]; char total_number[16]; uint8_t sum; // byte sum of above struct { uint8_t sum_inv; // ~(UID byte sum) uint8_t sum; // UID byte sum uint8_t id[6]; // UID } machine_id; uint8_t machine_type; // FF - Dreamcast uint8_t machine_version;// FF - VA0, FE - VA1, FD - VA2, NOTE: present in 1st factory record only, in 2nd always FF uint8_t unused[0x40] // FF filled } factory_records[2]; // 2 copies uint8_t unused_0[0x36]; // FF filled uint8_t unk_version; // not clear if hardware or bios version, A0 - VA0, 9F - VA1, 9E - VA2 uint8_t unused_1[9]; // FF filled char staff_roll[0xca0]; // list of creators uint8_t unused_2[0x420]; // FF filled uint8_t random[0xdc0]; // output of RNG {static u32 seed; seed=(seed*0x83d+0x2439)&0x7fff; return (u16)(seed+0xc000);}, where initial seed value is serial_number[7] & 0xf }; Besides factory sector, each new Dreamcast have "Flash Partition 2" header in SA6 (@1C000) followed by "CID" record: struct cid_record { uint16_t record_type; // 0, can be 0-4 struct cid_data { uint8_t date[4]; // BCD YYYY/MM/DD char t_inferior_code[4]; // '0'-filled in all dumps we have char repair_voucher_no[8]; // '0'-filled in all dumps we have uint8_t serial_no[8]; uint8_t factory_code; uint8_t order_no[5]; } cid[2]; uint16_t crc16; }; */ ROM_START(dc) DREAMCAST_COMMON_BIOS ROM_REGION64_LE(0x040000, "dcflash", ROMREGION_ERASEFF) ROM_LOAD( "dcus_ntsc.bin", 0x020000, 0x020000, CRC(4136c25b) SHA1(1efa00ab9d8357a9f91e5be931a3efd6236f2b79) ) // dumped from VA2.4 mobo with 1.022 BIOS ROM_END ROM_START( dceu ) DREAMCAST_COMMON_BIOS ROM_REGION64_LE(0x040000, "dcflash", ROMREGION_ERASEFF) ROM_LOAD( "dceu_pal.bin", 0x020000, 0x020000, CRC(7a102d05) SHA1(13e444e613dffe0a8bce073a01efa9a1d4626ba7) ) // VA1 ROM_LOAD( "dceu_pala.bin", 0x020000, 0x020000, CRC(2e8dfa07) SHA1(ca5fd977bbf8f48c28c1027a023b038123d57d39) ) // from VA1 with 1.01d BIOS ROM_END ROM_START( dcjp ) DREAMCAST_COMMON_BIOS ROM_SYSTEM_BIOS(4, "1004", "v1.004 (Japan)") // oldest known mass production version, supports Japan region only ROM_LOAD_BIOS(4, "mpr-21068.ic501", 0x000000, 0x200000, CRC(5454841f) SHA1(1ea132c0fbbf07ef76789eadc07908045c089bd6) ) ROM_REGION64_LE(0x040000, "dcflash", ROMREGION_ERASEFF) ROM_LOAD( "dcjp_ntsc.bin", 0x020000, 0x020000, CRC(306023ab) SHA1(5fb66adb6d1b54a552fe9c2bb736e4c6960e447d) ) // from refurbished VA0 with 1.004 BIOS ROM_END // unauthorised portable modification ROM_START( dctream ) ROM_REGION(0x200000, "maincpu", 0) // uses regular mpr-21931 BIOS chip, have region-free mod-chip installed, see driver init. ROM_LOAD( "mpr-21931.ic501", 0x000000, 0x200000, CRC(89f2b1a1) SHA1(8951d1bb219ab2ff8583033d2119c899cc81f18c) ) ROM_REGION64_LE(0x040000, "dcflash", ROMREGION_ERASEFF) ROM_LOAD( "dc_flash.bin", 0x020000, 0x020000, CRC(9d5515c4) SHA1(78a86fd4e8b58fc9d3535eef6591178f1b97ecf9) ) // VA1 NTSC-US ROM_END // normally, with DIP switch 4 off, HKT-0100/0110/0120 AKA "Katana Set 5.xx", will be booted from flash ROM IC507 (first 2 dumps below) // otherwise it boots from EPROM which contain system checker software (last 2 dumps) ROM_START( dcdev ) ROM_REGION(0x200000, "maincpu", 0) ROM_SYSTEM_BIOS(0, "1011", "Katana Set5 v1.011 (World)") // BOOT flash rom update from Katana SDK R9-R11, WinCE SDK v2.1 ROM_LOAD_BIOS(0, "set5v1.011.ic507", 0x000000, 0x200000, CRC(2186e0e5) SHA1(6bd18fb83f8fdb56f1941e079580e5dd672a6dad) ) ROM_SYSTEM_BIOS(1, "1001", "Katana Set5 v1.001 (Japan)") // BOOT flash rom update from Katana SDK 1.42J and WinCE SDK v1.0 ROM_LOAD_BIOS(1, "set5v1.001.ic507", 0x000000, 0x200000, CRC(5702d38f) SHA1(ea7a3ae1de73683008dd795c252941a4fc81b42e) ) ROM_SYSTEM_BIOS(2, "0976", "Katana Set5 v0.976 (Japan)") // BOOT flash rom update from Katana SDK 1.20J ROM_LOAD_BIOS(2, "set5v0.976.ic507", 0x000000, 0x200000, CRC(dcb2e86f) SHA1(c88b4b6704811e3a428ee225727e4f7df467a3b5) ) // 27C160 EPROM (DIP42) IC??? labeled // SET5 7676 // V0.71 98/11/13 ROM_SYSTEM_BIOS(3, "071", "Katana Set5 Checker v0.71") ROM_LOAD_BIOS(3, "set5v0.71.bin", 0x000000, 0x200000, CRC(52d01969) SHA1(28aec4a01419d2d2a664c540bef30ea289ca0644) ) // SET5 FC52 // V0.41 98/08/27 ROM_SYSTEM_BIOS(4, "041", "Katana Set5 Checker v0.41") ROM_LOAD_BIOS(4, "set5v0.41.bin", 0x000000, 0x200000, CRC(485877bd) SHA1(dc1af1f1248ffa87d57bc5ef2ea41aac95ecfc5e) ) ROM_REGION64_LE(0x040000, "dcflash", ROMREGION_ERASEFF) // Dev.Boxes have empty (FF filled) flash ROM ROM_END /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */ CONS( 1999, dc, dcjp, 0, dc, dc, dc_cons_state, init_dc, "Sega", "Dreamcast (USA, NTSC)", MACHINE_NOT_WORKING ) CONS( 1998, dcjp, 0, 0, dc, dc, dc_cons_state, init_dc, "Sega", "Dreamcast (Japan, NTSC)", MACHINE_NOT_WORKING ) CONS( 1999, dceu, dcjp, 0, dc, dc, dc_cons_state, init_dc, "Sega", "Dreamcast (Europe, PAL)", MACHINE_NOT_WORKING ) CONS( 200?, dctream, dcjp, 0, dc, dc, dc_cons_state, init_tream,"", "Treamcast", MACHINE_NOT_WORKING ) CONS( 1998, dcdev, 0, 0, dc, dc, dc_cons_state, init_dc, "Sega", "HKT-0120 Sega Dreamcast Development Box", MACHINE_NOT_WORKING ) /* Fish Life - interactive aquarium simulator Consists of HKS-0300 main unit and HKS-0100 LCD with touch screen HKS-0300 Fish Life 670-14239A (c) 2000 Sega components: Dreamcast VA1 motherboard GD-ROM drive PSU 173-8100B / 837-14049 IC BD SW FL backplate with up/down/left/right/A/B/Start buttons 171-8097B / 837-14046 IC BD FL main components: 315-6211-AB - Dreamcast game controller IC 315-6182 - Dreamcast microphone controller IC connectors HKS-0100 touch screen wired to SH-4's SCIF serial port. Communication is one-way, touch packet format is: 0100000T 00xxxxxx 00XXXXXX 00yyyyyy 00YYYYYY 00--zzzz 00------ T: 1 - touch, 0 - release x: X value low bits X: X value high bits y: Y value low bits Y: Y value high bits z: unused X/Y values range seems 3000x2294 HKS-0200 software GD-ROMs: HDR-0093 673-01613 Fish Life Red Sea Playful Edition *HDR-0094 673-01672 Fish Life Amazon Playful Edition HDR-0095 673-01??? Fish Life Episode 1 Basic Edition HDR-0096 673-01??? Fish Life Episode 2 Basic Edition HDR-0097 673-01??? Fish Life Episode 3 Basic Edition MSD-0001 ???-????? Fish Life Red Sea & Amazon PDP Ver. * denotes these games are archived. Machines high likely based on Fish Life: タッチであそぼ! / Play with a touch! (2001) - touch screen cabinet for McDonald's Japan https://www.famitsu.com/game/news/2001/09/13/103,1000362656,1276,0,0.html タッチでポン! / Pong by touch! (2001) - sushi ordering system https://web.archive.org/web/20180421214402/sega.jp/fb/creators/vol_13/1.html notes: Some sources claims Playful and Basic editions hardware is not the same, has to be verified. Press down+B for Test Mode */ ROM_START( dcfish ) ROM_REGION64_LE(0x200000, "maincpu", 0) ROM_LOAD( "mpr-21931.ic501", 0x000000, 0x200000, CRC(89f2b1a1) SHA1(8951d1bb219ab2ff8583033d2119c899cc81f18c) ) // regular v1.0d 3.3v BIOS // similar Dreamcast flashes, machine_name was changed to "Fish Life", machine_code2 is 0xff (verified by software) ROM_REGION64_LE(0x040000, "dcflash", ROMREGION_ERASEFF) ROM_LOAD( "fish_flash.bin", 0x020000, 0x020000, CRC(f7f36b7b) SHA1(f49d18de85c519c16d5447ca8ae39b62d1b8e483) ) // VA1 NTSC-JP DISK_REGION( "ata:0:gdrom" ) DISK_IMAGE_READONLY( "fish_life_amazon", 0, SHA1(2cbba727b219bbbeddf551d0f3e80c5f8ecbe21f) ) // HDR-0094 ROM_END /* YEAR NAME PARENT MACHINE INPUT CLASS INIT ROT COMPANY FULLNAME */ GAME( 2000, dcfish, 0, dc_fish, dcfish,dc_cons_state, init_dc, ROT0, "Sega", "Fish Life Amazon Playful Edition (Japan)", MACHINE_NOT_WORKING )