From 96e24fc56bb9cd0b15aa8d0ce17c4915ae2b2043 Mon Sep 17 00:00:00 2001 From: Olivier Galibert Date: Fri, 1 Jul 2022 17:44:25 +0200 Subject: There is only one Sega --- scripts/src/machine.lua | 22 + src/devices/machine/segacrp2_device.cpp | 451 +++ src/devices/machine/segacrp2_device.h | 126 + src/devices/machine/segacrpt_device.cpp | 1055 +++++++ src/devices/machine/segacrpt_device.h | 279 ++ src/mame/igs/goldstar.cpp | 5 +- src/mame/kiwako/jongkyo.cpp | 3 +- src/mame/mame.lst | 22 +- src/mame/mess.flt | 22 +- src/mame/nichibut/cclimber.h | 3 +- src/mame/nichibut/jangou.cpp | 3 +- src/mame/pacman/pengo.cpp | 3 +- src/mame/sanritsu/appoooh.cpp | 3 +- src/mame/sega/angelkds.cpp | 3 +- src/mame/sega/calorie.cpp | 2 +- src/mame/sega/dc-ctrl.cpp | 164 + src/mame/sega/dc-ctrl.h | 97 + src/mame/sega/dc.cpp | 668 ++++ src/mame/sega/dc.h | 287 ++ src/mame/sega/dc_g2if.cpp | 538 ++++ src/mame/sega/dc_g2if.h | 106 + src/mame/sega/dccons.cpp | 667 ++++ src/mame/sega/dccons.h | 60 + src/mame/sega/dccons_m.cpp | 225 ++ src/mame/sega/maple-dc.cpp | 302 ++ src/mame/sega/maple-dc.h | 84 + src/mame/sega/mapledev.cpp | 63 + src/mame/sega/mapledev.h | 46 + src/mame/sega/mdconsole.cpp | 1205 ++++++++ src/mame/sega/mdconsole.h | 109 + src/mame/sega/megacd.cpp | 1939 ++++++++++++ src/mame/sega/megacd.h | 229 ++ src/mame/sega/megadriv.cpp | 1108 +++++++ src/mame/sega/megadriv.h | 151 + src/mame/sega/megadriv_rad.cpp | 692 +++++ src/mame/sega/megadriv_rad.h | 107 + src/mame/sega/megadriv_sunplus_hybrid.cpp | 171 + src/mame/sega/megadriv_vt_hybrid.cpp | 168 + src/mame/sega/mie.cpp | 374 +++ src/mame/sega/mie.h | 142 + src/mame/sega/naomig1.cpp | 241 ++ src/mame/sega/naomig1.h | 79 + src/mame/sega/powervr2.cpp | 4117 +++++++++++++++++++++++++ src/mame/sega/powervr2.h | 581 ++++ src/mame/sega/sega_beena.cpp | 198 ++ src/mame/sega/sega_sawatte.cpp | 250 ++ src/mame/sega/segae.cpp | 2 +- src/mame/sega/segag80r.cpp | 3 +- src/mame/sega/segapico.cpp | 638 ++++ src/mame/sega/segapm.cpp | 89 + src/mame/sega/segas16a.cpp | 2 +- src/mame/sega/sg1000.cpp | 706 +++++ src/mame/sega/sg1000.h | 124 + src/mame/sega/sg1000a.cpp | 3 +- src/mame/sega/suprloco.cpp | 3 +- src/mame/sega/svmu.cpp | 416 +++ src/mame/sega/system1.cpp | 3 +- src/mame/sega/system1.h | 3 +- src/mame/sega/turbo.cpp | 3 +- src/mame/sega/zaxxon.cpp | 3 +- src/mame/segacons/dccons.cpp | 667 ---- src/mame/segacons/dccons.h | 60 - src/mame/segacons/dccons_m.cpp | 225 -- src/mame/segacons/mdconsole.cpp | 1205 -------- src/mame/segacons/mdconsole.h | 109 - src/mame/segacons/megacd.cpp | 1939 ------------ src/mame/segacons/megacd.h | 229 -- src/mame/segacons/megadriv_rad.cpp | 692 ----- src/mame/segacons/megadriv_rad.h | 107 - src/mame/segacons/megadriv_sunplus_hybrid.cpp | 171 - src/mame/segacons/megadriv_vt_hybrid.cpp | 168 - src/mame/segacons/sega_beena.cpp | 198 -- src/mame/segacons/sega_sawatte.cpp | 250 -- src/mame/segacons/segapico.cpp | 638 ---- src/mame/segacons/segapm.cpp | 89 - src/mame/segacons/sg1000.cpp | 706 ----- src/mame/segacons/sg1000.h | 124 - src/mame/segacons/svmu.cpp | 416 --- src/mame/shared/dc-ctrl.cpp | 164 - src/mame/shared/dc-ctrl.h | 97 - src/mame/shared/dc.cpp | 668 ---- src/mame/shared/dc.h | 287 -- src/mame/shared/dc_g2if.cpp | 538 ---- src/mame/shared/dc_g2if.h | 106 - src/mame/shared/maple-dc.cpp | 302 -- src/mame/shared/maple-dc.h | 84 - src/mame/shared/mapledev.cpp | 63 - src/mame/shared/mapledev.h | 46 - src/mame/shared/megadriv.cpp | 1108 ------- src/mame/shared/megadriv.h | 151 - src/mame/shared/mie.cpp | 374 --- src/mame/shared/mie.h | 142 - src/mame/shared/naomig1.cpp | 241 -- src/mame/shared/naomig1.h | 79 - src/mame/shared/powervr2.cpp | 4117 ------------------------- src/mame/shared/powervr2.h | 581 ---- src/mame/shared/segacrp2_device.cpp | 451 --- src/mame/shared/segacrp2_device.h | 126 - src/mame/shared/segacrpt_device.cpp | 1055 ------- src/mame/shared/segacrpt_device.h | 279 -- src/mame/tehkan/pbaction.cpp | 3 +- src/mame/tehkan/senjyo.cpp | 3 +- 102 files changed, 19117 insertions(+), 19109 deletions(-) create mode 100644 src/devices/machine/segacrp2_device.cpp create mode 100644 src/devices/machine/segacrp2_device.h create mode 100644 src/devices/machine/segacrpt_device.cpp create mode 100644 src/devices/machine/segacrpt_device.h create mode 100644 src/mame/sega/dc-ctrl.cpp create mode 100644 src/mame/sega/dc-ctrl.h create mode 100644 src/mame/sega/dc.cpp create mode 100644 src/mame/sega/dc.h create mode 100644 src/mame/sega/dc_g2if.cpp create mode 100644 src/mame/sega/dc_g2if.h create mode 100644 src/mame/sega/dccons.cpp create mode 100644 src/mame/sega/dccons.h create mode 100644 src/mame/sega/dccons_m.cpp create mode 100644 src/mame/sega/maple-dc.cpp create mode 100644 src/mame/sega/maple-dc.h create mode 100644 src/mame/sega/mapledev.cpp create mode 100644 src/mame/sega/mapledev.h create mode 100644 src/mame/sega/mdconsole.cpp create mode 100644 src/mame/sega/mdconsole.h create mode 100644 src/mame/sega/megacd.cpp create mode 100644 src/mame/sega/megacd.h create mode 100644 src/mame/sega/megadriv.cpp create mode 100644 src/mame/sega/megadriv.h create mode 100644 src/mame/sega/megadriv_rad.cpp create mode 100644 src/mame/sega/megadriv_rad.h create mode 100644 src/mame/sega/megadriv_sunplus_hybrid.cpp create mode 100644 src/mame/sega/megadriv_vt_hybrid.cpp create mode 100644 src/mame/sega/mie.cpp create mode 100644 src/mame/sega/mie.h create mode 100644 src/mame/sega/naomig1.cpp create mode 100644 src/mame/sega/naomig1.h create mode 100644 src/mame/sega/powervr2.cpp create mode 100644 src/mame/sega/powervr2.h create mode 100644 src/mame/sega/sega_beena.cpp create mode 100644 src/mame/sega/sega_sawatte.cpp create mode 100644 src/mame/sega/segapico.cpp create mode 100644 src/mame/sega/segapm.cpp create mode 100644 src/mame/sega/sg1000.cpp create mode 100644 src/mame/sega/sg1000.h create mode 100644 src/mame/sega/svmu.cpp delete mode 100644 src/mame/segacons/dccons.cpp delete mode 100644 src/mame/segacons/dccons.h delete mode 100644 src/mame/segacons/dccons_m.cpp delete mode 100644 src/mame/segacons/mdconsole.cpp delete mode 100644 src/mame/segacons/mdconsole.h delete mode 100644 src/mame/segacons/megacd.cpp delete mode 100644 src/mame/segacons/megacd.h delete mode 100644 src/mame/segacons/megadriv_rad.cpp delete mode 100644 src/mame/segacons/megadriv_rad.h delete mode 100644 src/mame/segacons/megadriv_sunplus_hybrid.cpp delete mode 100644 src/mame/segacons/megadriv_vt_hybrid.cpp delete mode 100644 src/mame/segacons/sega_beena.cpp delete mode 100644 src/mame/segacons/sega_sawatte.cpp delete mode 100644 src/mame/segacons/segapico.cpp delete mode 100644 src/mame/segacons/segapm.cpp delete mode 100644 src/mame/segacons/sg1000.cpp delete mode 100644 src/mame/segacons/sg1000.h delete mode 100644 src/mame/segacons/svmu.cpp delete mode 100644 src/mame/shared/dc-ctrl.cpp delete mode 100644 src/mame/shared/dc-ctrl.h delete mode 100644 src/mame/shared/dc.cpp delete mode 100644 src/mame/shared/dc.h delete mode 100644 src/mame/shared/dc_g2if.cpp delete mode 100644 src/mame/shared/dc_g2if.h delete mode 100644 src/mame/shared/maple-dc.cpp delete mode 100644 src/mame/shared/maple-dc.h delete mode 100644 src/mame/shared/mapledev.cpp delete mode 100644 src/mame/shared/mapledev.h delete mode 100644 src/mame/shared/megadriv.cpp delete mode 100644 src/mame/shared/megadriv.h delete mode 100644 src/mame/shared/mie.cpp delete mode 100644 src/mame/shared/mie.h delete mode 100644 src/mame/shared/naomig1.cpp delete mode 100644 src/mame/shared/naomig1.h delete mode 100644 src/mame/shared/powervr2.cpp delete mode 100644 src/mame/shared/powervr2.h delete mode 100644 src/mame/shared/segacrp2_device.cpp delete mode 100644 src/mame/shared/segacrp2_device.h delete mode 100644 src/mame/shared/segacrpt_device.cpp delete mode 100644 src/mame/shared/segacrpt_device.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 71e446ec7ca..88c49accc82 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -5062,3 +5062,25 @@ if (MACHINES["SAA7191"]~=null) then MAME_DIR .. "src/devices/machine/saa7191.h", } end + +--------------------------------------------------- +-- +--@src/devices/machine/segacrpt_device.h,MACHINES["SEGACRPT"] = true +--------------------------------------------------- +if (MACHINES["SEGACRPT"]~=null) then + files { + MAME_DIR .. "src/devices/machine/segacrpt_device.cpp", + MAME_DIR .. "src/devices/machine/segacrpt_device.h", + } +end + +--------------------------------------------------- +-- +--@src/devices/machine/segacrp2_device.h,MACHINES["SEGACRP2"] = true +--------------------------------------------------- +if (MACHINES["SEGACRP2"]~=null) then + files { + MAME_DIR .. "src/devices/machine/segacrp2_device.cpp", + MAME_DIR .. "src/devices/machine/segacrp2_device.h", + } +end diff --git a/src/devices/machine/segacrp2_device.cpp b/src/devices/machine/segacrp2_device.cpp new file mode 100644 index 00000000000..1a2676bd631 --- /dev/null +++ b/src/devices/machine/segacrp2_device.cpp @@ -0,0 +1,451 @@ +// license:BSD-3-Clause +// copyright-holders:Nicola Salmoria, David Haywood +/****************************************************************************** + + Sega encryption emulation by Nicola Salmoria + + + This encryption is an evolution of the one implemented in segacrpt.cpp. + It works on more data and address bits but apart from that it's essentially + the same. + + The encryption affects D0, D2, D4, and D6, and depends on M1, A0, A3, A6, A9, + A12, and A14. + + The encryption consists of a permutation of the four data bits, which can also + be inverted. Therefore there are 4! * 2^4 = 384 different possible encryptions. + + An interesting peculiarity is that four games in the list below use an almost + identical key, just offset by one or more bytes. This leads to believe that + keys were generated using a PRNG like in other Sega encryptions (MC8123 etc.) + and the CPU part# used to skip the first N bytes. + + + List of encrypted games currently known: + + CPU Part # Game Comments + 315-5136 New Lucky 8 Lines (set 7, W-4, encrypted) + 315-5162 4D Warriors & used I'm Sorry for k.p.a. + Rafflesia & + Wonder Boy (set 4) + 315-5176 Wonder Boy (system 2 hardware, set 2) + 315-5177 Astro Flash & + Wonder Boy (set 1) + 315-5178 Wonder Boy (set 2) unencrypted version available + 315-5179 Robo-Wrestle 2001 + 317-5000 Fantasy Zone (Sound CPU) same key as 315-5177 + + The following games seem to use the same algorithm as the above ones, but + using a key which almost doesn't change + + 317-0004 Calorie Kun unencrypted bootleg available + 317-0005 Space Position + 317-0006 Gardia (set 1) + 317-0007 Gardia (set 2) + +******************************************************************************/ + +#include "emu.h" +#include "segacrp2_device.h" + + +static void decode(uint8_t *rom, uint8_t *decrypted, const uint8_t xor_table[128], const int swap_table[128]) +{ + static const uint8_t swaptable[24][4] = { + { 6,4,2,0 }, { 4,6,2,0 }, { 2,4,6,0 }, { 0,4,2,6 }, + { 6,2,4,0 }, { 6,0,2,4 }, { 6,4,0,2 }, { 2,6,4,0 }, + { 4,2,6,0 }, { 4,6,0,2 }, { 6,0,4,2 }, { 0,6,4,2 }, + { 4,0,6,2 }, { 0,4,6,2 }, { 6,2,0,4 }, { 2,6,0,4 }, + { 0,6,2,4 }, { 2,0,6,4 }, { 0,2,6,4 }, { 4,2,0,6 }, + { 2,4,0,6 }, { 4,0,2,6 }, { 2,0,4,6 }, { 0,2,4,6 } }; + + for (int a = 0x0000; a < 0x8000; a++) + { + const uint8_t *tbl; + + const uint8_t src = rom[a]; + + // pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address + const int row = bitswap<6>(a, 14, 12, 9, 6, 3, 0); + + // decode the opcodes + tbl = swaptable[swap_table[2 * row]]; + decrypted[a] = bitswap<8>(src, 7, tbl[0], 5, tbl[1], 3, tbl[2], 1, tbl[3]) ^ xor_table[2 * row]; + + // decode the data + tbl = swaptable[swap_table[2 * row + 1]]; + rom[a] = bitswap<8>(src, 7, tbl[0], 5, tbl[1], 3, tbl[2], 1, tbl[3]) ^ xor_table[2 * row + 1]; + } +} + + +DEFINE_DEVICE_TYPE(NEC_315_5136, nec_315_5136_device, "nec_315_5136", "Nec 315-5136") +DEFINE_DEVICE_TYPE(SEGA_315_5179, sega_315_5179_device, "sega_315_5179", "Sega 315-5179") +DEFINE_DEVICE_TYPE(SEGA_315_5178, sega_315_5178_device, "sega_315_5178", "Sega 315-5178") +DEFINE_DEVICE_TYPE(SEGA_315_5177, sega_315_5177_device, "sega_315_5177", "Sega 315-5177") // also seen as 317-5000 +DEFINE_DEVICE_TYPE(SEGA_315_5176, sega_315_5176_device, "sega_315_5176", "Sega 315-5176") +DEFINE_DEVICE_TYPE(SEGA_315_5162, sega_315_5162_device, "sega_315_5162", "Sega 315-5162") + +DEFINE_DEVICE_TYPE(SEGA_317_0004, sega_317_0004_device, "sega_317_0004", "Sega 317-0004") +DEFINE_DEVICE_TYPE(SEGA_317_0005, sega_317_0005_device, "sega_317_0005", "Sega 317-0005") +DEFINE_DEVICE_TYPE(SEGA_317_0006, sega_317_0006_device, "sega_317_0006", "Sega 317-0006") +DEFINE_DEVICE_TYPE(SEGA_317_0007, sega_317_0007_device, "sega_317_0007", "Sega 317-0007") + + +segacrp2_z80_device::segacrp2_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + z80_device(mconfig, type, tag, owner, clock), + m_decrypted(*this, finder_base::DUMMY_TAG) +{ +} + +void segacrp2_z80_device::device_start() +{ + z80_device::device_start(); + decrypt(); +} + +nec_315_5136_device::nec_315_5136_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, NEC_315_5136, tag, owner, clock) +{ +} + +void nec_315_5136_device::decrypt() +{ + // 315-5136 + static const uint8_t xor_table[128] = { + 0x00,0x40, 0x10,0x50, 0x04,0x44, 0x14,0x54, 0x01,0x41, 0x11,0x51, 0x05,0x45, 0x15,0x55, + 0x00,0x40, 0x10,0x50, 0x04,0x44, 0x14,0x54, 0x01,0x41, 0x11,0x51, 0x05,0x45, 0x15,0x55, + 0x00,0x40, 0x10,0x50, 0x04,0x44, 0x14,0x54, 0x01,0x41, 0x11,0x51, 0x05,0x45, 0x15,0x55, + 0x00,0x40, 0x10,0x50, 0x04,0x44, 0x14,0x54, 0x01,0x41, 0x11,0x51, 0x05,0x45, 0x15,0x55, + + 0x50,0x10, 0x44,0x04, 0x54,0x14, 0x41,0x01, 0x51,0x11, 0x45,0x05, 0x55,0x15, 0x40,0x00, + 0x50,0x10, 0x44,0x04, 0x54,0x14, 0x41,0x01, 0x51,0x11, 0x45,0x05, 0x55,0x15, 0x40,0x00, + 0x50,0x10, 0x44,0x04, 0x54,0x14, 0x41,0x01, 0x51,0x11, 0x45,0x05, 0x55,0x15, 0x40,0x00, + 0x50,0x10, 0x44,0x04, 0x54,0x14, 0x41,0x01, 0x51,0x11, 0x45,0x05, 0x55,0x15, 0x40,0x00 }; + + static const int swap_table[128] = { + 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, + 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02, + 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x03, + 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04 }; + + decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); +} + + +sega_315_5177_device::sega_315_5177_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, SEGA_315_5177, tag, owner, clock) +{ +} + +void sega_315_5177_device::decrypt() +{ + // 315-5177 + static const uint8_t xor_table[128] = { + 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, + 0x05,0x55,0x50,0x14,0x41,0x45,0x00,0x50,0x54,0x11,0x45,0x40, + 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, + 0x05,0x55,0x50,0x14,0x41,0x45,0x00,0x50,0x54,0x11,0x45,0x40, + 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, + 0x05,0x55,0x50,0x14, + + 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, + 0x05,0x55,0x50,0x14,0x41,0x45,0x00,0x50,0x54,0x11,0x45,0x40, + 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, + 0x05,0x55,0x50,0x14,0x41,0x45,0x00,0x50,0x54,0x11,0x45,0x40, + 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, + 0x05,0x55,0x50,0x14 }; + + static const int swap_table[128] = { + 0,0,0,0, + 1,1,1,1,1, + 2,2,2,2,2, + 3,3,3,3, + 4,4,4,4,4, + 5,5,5,5,5, + 6,6,6,6,6, + 7,7,7,7,7, + 8,8,8,8, + 9,9,9,9,9, + 10,10,10,10,10, + 11,11,11,11,11, + 12,12,12,12,12, + 13,13, + + 8,8,8,8, + 9,9,9,9,9, + 10,10,10,10,10, + 11,11,11,11, + 12,12,12,12,12, + 13,13,13,13,13, + 14,14,14,14,14, + 15,15,15,15,15, + 16,16,16,16, + 17,17,17,17,17, + 18,18,18,18,18, + 19,19,19,19,19, + 20,20,20,20,20, + 21,21 }; + decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); +} + + +sega_315_5176_device::sega_315_5176_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, SEGA_315_5176, tag, owner, clock) +{ +} + +void sega_315_5176_device::decrypt() +{ + static const uint8_t xor_table[128] = { + 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, + 0x41, 0x05, 0x55, 0x10, 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, + 0x45, 0x00, 0x50, 0x14, 0x41, 0x05, 0x55, 0x10, 0x44, 0x01, 0x51, 0x15, + 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, 0x41, 0x05, 0x55, 0x10, + 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, + 0x41, 0x05, 0x55, 0x10, + + 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, + 0x41, 0x05, 0x55, 0x10, 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, + 0x45, 0x00, 0x50, 0x14, 0x41, 0x05, 0x55, 0x10, 0x44, 0x01, 0x51, 0x15, + 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, 0x41, 0x05, 0x55, 0x10, + 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, + 0x41, 0x05, 0x55, 0x10 }; + + static const int swap_table[128] = { + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, + + 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14 }; + + decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); +} + + +sega_315_5162_device::sega_315_5162_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, SEGA_315_5162, tag, owner, clock) +{ +} + +void sega_315_5162_device::decrypt() +{ + // 315-5162 + static const uint8_t xor_table[128] = { + 0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, + 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, + 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, + 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, + 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, + 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, + 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, + 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, + 0x00 }; + + static const int swap_table[128] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 12 }; + + decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); +} + + + +sega_315_5178_device::sega_315_5178_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, SEGA_315_5178, tag, owner, clock) +{ +} + +void sega_315_5178_device::decrypt() +{ // 315-5178 + static const uint8_t xor_table[128] = { + 0x00,0x55,0x45,0x05,0x11,0x41,0x01,0x14,0x44,0x50,0x10, + 0x00,0x55,0x15,0x05,0x51,0x41,0x01,0x14,0x44,0x04,0x10, + 0x40,0x55,0x15,0x05,0x51,0x11, + 0x01,0x54,0x44,0x04,0x10,0x40,0x00,0x15,0x45,0x51,0x11, + 0x01,0x54,0x14,0x04,0x50,0x40,0x00,0x15,0x45,0x05,0x11, + 0x41,0x54,0x14,0x04,0x50,0x10, + 0x00,0x55,0x45,0x05,0x11,0x41,0x01,0x14, + + 0x00,0x55,0x45,0x05,0x11,0x41,0x01,0x14,0x44,0x50,0x10, + 0x00,0x55,0x15,0x05,0x51,0x41,0x01,0x14,0x44,0x04,0x10, + 0x40,0x55,0x15,0x05,0x51,0x11, + 0x01,0x54,0x44,0x04,0x10,0x40,0x00,0x15,0x45,0x51,0x11, + 0x01,0x54,0x14,0x04,0x50,0x40,0x00,0x15,0x45,0x05,0x11, + 0x41,0x54,0x14,0x04,0x50,0x10, + 0x00,0x55,0x45,0x05,0x11,0x41,0x01,0x14 }; + + static const int swap_table[128] = { + 2, + 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7, + 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, + 5, 7, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, + 4, 6, 0, 2, 4, 6, 0, 2, 4, 6, + 8, + 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, + 6, 0, 2, 4, 6, 0, 2, + + 10, + 11,13,15, 9,11,13,15, 9,11,13,15, + 8,10,12,14, 8,10,12,14, 8,10,12, + 13,15, 9,11,13,15, 9,11,13,15, 9,11, + 12,14, 8,10,12,14, 8,10,12,14, + 16, + 9,11,13,15, 9,11,13,15, 9,11,13, + 14, 8,10,12,14, 8,10 }; + + decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); +} + + +sega_315_5179_device::sega_315_5179_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, SEGA_315_5179, tag, owner, clock) +{ +} + +void sega_315_5179_device::decrypt() +{ // 315-5179 + static const uint8_t xor_table[128] = { + 0x00,0x45,0x41,0x14,0x10,0x55,0x51,0x01,0x04,0x40,0x45,0x11,0x14,0x50, + 0x00,0x05,0x41,0x44,0x10,0x15,0x51,0x54,0x04, + 0x00,0x45,0x41,0x14,0x10,0x55,0x05,0x01,0x44,0x40,0x15,0x11,0x54,0x50, + 0x00,0x05,0x41,0x44,0x10,0x15,0x51,0x01,0x04, + 0x40,0x45,0x11,0x14,0x50,0x55,0x05,0x01,0x44,0x40,0x15,0x11,0x54,0x04, + 0x00,0x45,0x41,0x14,0x50, + 0x00,0x05,0x41,0x44,0x10,0x15,0x51,0x54,0x04, + 0x00,0x45,0x41,0x14,0x50,0x55,0x05,0x01,0x44,0x40,0x15,0x11,0x54,0x50, + 0x00,0x05,0x41,0x44,0x10,0x55,0x51,0x01,0x04, + 0x40,0x45,0x11,0x14,0x50,0x55,0x05,0x01,0x44,0x40,0x15,0x51,0x54,0x04, + 0x00,0x45,0x41,0x14,0x10,0x55,0x51,0x01,0x04, + 0x40,0x45,0x11,0x54,0x50,0x00,0x05,0x41 }; + + static const int swap_table[128] = { + 8, 9,11,13,15, 0, 2, 4, 6, + 8, 9,11,13,15, 1, 2, 4, 6, + 8, 9,11,13,15, 1, 2, 4, 6, + 8, 9,11,13,15, 1, 2, 4, 6, + 8,10,11,13,15, 1, 2, 4, 6, + 8,10,11,13,15, 1, 2, 4, 6, + 8,10,11,13,15, 1, 3, 4, 6, + 8, + 7, 1, 2, 4, 6, 0, 1, 3, 5, + 7, 1, 2, 4, 6, 0, 1, 3, 5, + 7, 1, 2, 4, 6, 0, 2, 3, 5, + 7, 1, 2, 4, 6, 0, 2, 3, 5, + 7, 1, 2, 4, 6, 0, 2, 3, 5, + 7, 1, 3, 4, 6, 0, 2, 3, 5, + 7, 1, 3, 4, 6, 0, 2, 4, 5, + 7 }; + + decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); +} + + +/****************************************************************************** + + These games (all 317-000x CPUs) use the same algorithm, but the key doesn't + change much - just a shift in the table. + +******************************************************************************/ + +static void sega_decode_317(uint8_t *rom, uint8_t *decrypted, int shift) +{ + static const uint8_t xor_table[128 + 3] = { + 0x04,0x54,0x44,0x14,0x15,0x15,0x51,0x41,0x41,0x14,0x10,0x50,0x15,0x55,0x54,0x05, + 0x04,0x41,0x51,0x01,0x05,0x10,0x55,0x51,0x05,0x05,0x54,0x11,0x45,0x05,0x04,0x14, + 0x10,0x55,0x01,0x41,0x51,0x05,0x55,0x04,0x45,0x41,0x55,0x14,0x45,0x10,0x04,0x45, + 0x55,0x50,0x40,0x00,0x11,0x45,0x15,0x00,0x01,0x00,0x40,0x00,0x01,0x45,0x11,0x00, + 0x45,0x00,0x44,0x54,0x40,0x04,0x05,0x15,0x15,0x10,0x15,0x04,0x01,0x05,0x50,0x11, + 0x00,0x44,0x44,0x04,0x04,0x01,0x50,0x05,0x51,0x00,0x45,0x44,0x50,0x15,0x54,0x40, + 0x41,0x45,0x40,0x10,0x14,0x15,0x40,0x51,0x50,0x50,0x45,0x00,0x10,0x15,0x05,0x51, + 0x50,0x44,0x01,0x15,0x40,0x04,0x01,0x44,0x50,0x44,0x50,0x50,0x50,0x10,0x44,0x04, + 0x40,0x04,0x10 }; + + static const int swap_table[128 + 3] = { + 7, 7,12, 1,18,11, 8,23,21,17, 0,23,22, 0,21,15, + 13,19,21,20,20,12,13,10,20, 0,14,18, 6,18, 3, 5, + 5,20,20,13, 8, 0,20,18, 4,14, 8, 5,17, 6,22,10, + 0,21, 0, 1, 6,11,17, 9,17, 3, 9,21, 0, 4,16, 1, + 13,17,21, 5, 3, 7, 2,16,18,13, 6,19,11,23, 3,20, + 3, 2,18,10,18,23,19,23, 3,15, 0,10, 5,12, 0, 0, + 11,22, 8,14, 8, 6, 1,15, 7,11, 2,17,10,15, 8,21, + 10, 0, 2, 6, 1, 1, 3, 1,12,18,16, 5, 0,15,17,15, + 10,20, 1 }; + + decode(rom, decrypted, xor_table + shift, swap_table + shift); +} + + +sega_317_0004_device::sega_317_0004_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, SEGA_317_0004, tag, owner, clock) +{ +} + +void sega_317_0004_device::decrypt() +{ // 317-0004 + sega_decode_317(memregion(tag())->base(), m_decrypted, 0); +} + + +sega_317_0005_device::sega_317_0005_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, SEGA_317_0005, tag, owner, clock) +{ +} + +void sega_317_0005_device::decrypt() +{ // 317-0005 + sega_decode_317(memregion(tag())->base(), m_decrypted, 1); +} + + +sega_317_0006_device::sega_317_0006_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, SEGA_317_0006, tag, owner, clock) +{ +} + +void sega_317_0006_device::decrypt() +{ // 317-0006 + sega_decode_317(memregion(tag())->base(), m_decrypted, 2); +} + + +sega_317_0007_device::sega_317_0007_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + segacrp2_z80_device(mconfig, SEGA_317_0007, tag, owner, clock) +{ +} + +void sega_317_0007_device::decrypt() +{ // 317-0006 + sega_decode_317(memregion(tag())->base(), m_decrypted, 3); +} diff --git a/src/devices/machine/segacrp2_device.h b/src/devices/machine/segacrp2_device.h new file mode 100644 index 00000000000..a64f3fa5fe0 --- /dev/null +++ b/src/devices/machine/segacrp2_device.h @@ -0,0 +1,126 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +#ifndef MAME_MACHINE_SEGACRP2_DEVICE_H +#define MAME_MACHINE_SEGACRP2_DEVICE_H + +#pragma once + + +#include "cpu/z80/z80.h" + +// base class +class segacrp2_z80_device : public z80_device +{ +public: + template void set_decrypted_tag(T &&decrypted_tag) { m_decrypted.set_tag(std::forward(decrypted_tag)); } + +protected: + segacrp2_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void decrypt() = 0; + + required_shared_ptr m_decrypted; +}; + + + +// actual encrypted CPUs +class nec_315_5136_device : public segacrp2_z80_device +{ +public: + nec_315_5136_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5179_device : public segacrp2_z80_device +{ +public: + sega_315_5179_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + +class sega_315_5178_device : public segacrp2_z80_device +{ +public: + sega_315_5178_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5177_device : public segacrp2_z80_device +{ +public: + sega_315_5177_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5176_device : public segacrp2_z80_device +{ +public: + sega_315_5176_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5162_device : public segacrp2_z80_device +{ +public: + sega_315_5162_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_317_0004_device : public segacrp2_z80_device +{ +public: + sega_317_0004_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + +class sega_317_0005_device : public segacrp2_z80_device +{ +public: + sega_317_0005_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + +class sega_317_0006_device : public segacrp2_z80_device +{ +public: + sega_317_0006_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_317_0007_device : public segacrp2_z80_device +{ +public: + sega_317_0007_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + +DECLARE_DEVICE_TYPE(NEC_315_5136, nec_315_5136_device) +DECLARE_DEVICE_TYPE(SEGA_315_5179, sega_315_5179_device) +DECLARE_DEVICE_TYPE(SEGA_315_5178, sega_315_5178_device) +DECLARE_DEVICE_TYPE(SEGA_315_5177, sega_315_5177_device) +DECLARE_DEVICE_TYPE(SEGA_315_5176, sega_315_5176_device) +DECLARE_DEVICE_TYPE(SEGA_315_5162, sega_315_5162_device) + +DECLARE_DEVICE_TYPE(SEGA_317_0004, sega_317_0004_device) +DECLARE_DEVICE_TYPE(SEGA_317_0005, sega_317_0005_device) +DECLARE_DEVICE_TYPE(SEGA_317_0006, sega_317_0006_device) +DECLARE_DEVICE_TYPE(SEGA_317_0007, sega_317_0007_device) + + +#endif // MAME_MACHINE_SEGACRP2_DEVICE_H diff --git a/src/devices/machine/segacrpt_device.cpp b/src/devices/machine/segacrpt_device.cpp new file mode 100644 index 00000000000..2ba57904e60 --- /dev/null +++ b/src/devices/machine/segacrpt_device.cpp @@ -0,0 +1,1055 @@ +// license:BSD-3-Clause +// copyright-holders:Nicola Salmoria, David Haywood +/****************************************************************************** + + Sega encryption emulation by Nicola Salmoria + + + Several Sega Z80 games have program ROMs encrypted using a common algorithm + (but with a different key). + The hardware used to implement this encryption is either a custom CPU, or an + epoxy block which probably contains a standard Z80 + PALs. + + The encryption affects D3, D5, and D7, and depends on M1, A0, A4, A8 and A12. + D0, D1, D2, D4 and D6 are always unaffected. + + The encryption consists of a permutation of the three bits, which can also be + inverted. Therefore there are 3! * 2^3 = 48 different possible encryptions. + + For simplicity, the decryption is implemented using conversion tables. + We need 32 of these tables, one for every possible combination of M1, A0, A4, + A8 and A12. However, all the games currently known are full of repetitions + and only use 6 different tables, the only exceptions being Pengo, Yamato and + Spatter which have 7 (but one of them is the identity: { 0x00, 0x08, 0x20, 0x28 } ). + This is most likely a limitation of the hardware. + Some of the early games are even weaker: of the 6 different tables, they use + 3 for opcodes and 3 for data, and always coupled in the same way. + + In all games currently known, only bytes in the memory range 0x0000-0x7fff + (A15 = 0) are encrypted. My guess is that this was done to allow games to + copy code to RAM (in the memory range 0x8000-0xffff) and execute it from + there without the CPU trying to decrypt it and messing everything up. + However Zaxxon has RAM at 0x6000, and the CPU doesn't seem to interfere with + it; but it doesn't execute code from there, so it's possible that the CPU is + encrypting the data while writing it and decrypting it while reading (that + would seem kind of strange though). Video and sprite RAM and memory mapped + ports are all placed above 0x8000. + + Given its strict limitations, this encryption is reasonably easy to break, + and very vulnerable to known plaintext attacks. + + + + Ninja Princess: + + there is a (bootleg?) board which has a standard Z80 + 2 bipolar PROMs + instead of the custom CPU. The encryption table is different from the + original Ninja Princess; it is actually the same as Flicky. + + The first PROM is 32x8 and contains the number (0..5) of the table to + use depending on M1, A0, A4, A8, A12: + + 00: 11 00 33 22 00 44 44 00 11 33 33 22 44 44 44 22 + 10: 11 55 55 33 44 22 55 22 11 33 55 33 44 44 11 22 + + The second PROM is 256x4 and contains the 6 different XOR tables: + + A D B C C B D A + 00: 09 09 0A 0A 0A 0A 09 09 + 08: 0E 08 0B 0D 0D 0B 08 0E + 10: 0A 0C 0A 0C 0C 0A 0C 0A + 18: 0B 0E 0E 0B 0B 0E 0E 0B + 20: 0C 0C 0F 0F 0F 0F 0C 0C + 28: 08 0D 0B 0E 0E 0B 0D 08 + [the remaining bytes are all 0F] + bit 3 is not used. + bits 0-2 is the XOR code inverted (0 = 0xa8, 1 = 0xa0 ... 6 = 0x08 7 = 0x00) + + Here is a diagram showing how it works: + + data to XOR + decode value + A --- + D7 --------------- 0| | + D3 --------------- 1| | + D5 --------------- 2| P |D + A --- D | R |0 ---|>--- D3 + M1 --- 0| P |0 --- 3| O |1 ---|>--- D5 + A0 --- 1| R |1 --- 4| M |2 ---|>--- D7 + A4 --- 2| O |2 --- 5| 2 |3 --- + A8 --- 3| M |3 --- 6| | + A12 --- 4| 1 |4 --- 7| | + --- --- + + + My Hero: + + the bootleg does the decryption using a single 256x4 PROM, mapped in the + obvious way: + + data to XOR + decode value + A --- + D3 --- 0| | + D5 --- 1| |D + D7 --- 2| P |0 --- D3 + A0 --- 3| R |1 --- D5 + A4 --- 4| O |2 --- D7 + A8 --- 5| M |3 --- + A12 --- 6| | + M1 --- 7| | + --- + + + + List of encrypted games currently known: + + CPU Part # Game Comments + 315-5010 Pengo unencrypted version available + 315-5013 Super Zaxxon used Zaxxon for known plaintext attack + 315-5014 Buck Rogers / Zoom 909 unencrypted version available + 315-5015 Super Locomotive + 315-5018 Yamato + ???-???? Top Roller same key as Yamato + 315-5028 Sindbad Mystery + 315-5030 Up'n Down unencrypted version available + ???-???? M120 Razzmatazz same key as Up'n Down + 315-5033 Regulus unencrypted version available + 315-5041 M140 Mister Viking + 315-5048 SWAT used Bull Fight for k.p.a. + 315-5051 Flicky & + Ninja Princess (bootleg) + 315-5061 Future Spy + 315-5064 Water Match used Mister Viking for k.p.a. + 315-5065 Bull Fight + 315-5069 Star Force game by Tehkan; same key as Super Locomotive + ???-???? Spatter same encryption scheme is used by the Falcon 03155096 CPU (Z80) + 315-5084 Jongkyo TABLE INCOMPLETE game by Kiwako; also has a simple bitswap on top + 315-5093 Pitfall II + 315-5098 Ninja Princess unencrypted version available; same key as Up'n Down + 315-5102 Sega Ninja unencrypted version available + 315-5110 I'm Sorry used My Hero for k.p.a. + 315-5114 Champion Pro Wrestling same key as Regulus + 315-5115 TeddyBoy Blues + 315-5128 Pinball Action game by Tehkan; also has a simple bitswap on top + 315-5132 My Hero + 315-5135 Heavy Metal & + Wonder Boy (set 1a & 3; bootlegs?) + + + Some text found in the ROMs: + + Buck Rogers SECULITY BY MASATOSHI,MIZUNAGA + Super Locomotive SEGA FUKUMURA MIZUNAGA + Yamato SECULITY BY M,MIZUNAGA + Regulus SECULITY BY SYUICHI,KATAGI + Up'n Down 19/SEP 1983 MASATOSHI,MIZUNAGA + Mister Viking SECURITY BY S.KATAGI CONTROL CHIP M140 + SWAT SECURITY BY S.KATAGI + Flicky SECURITY BY S.KATAGI + Water Match PROGRAMED BY KAWAHARA&NAKAGAWA + Star Force STAR FORCE TEHKAN. SECURITY BY SEGA ENTERPRISESE + +******************************************************************************/ + +#include "emu.h" +#include "segacrpt_device.h" + + +#if 0 +static void lfkp(int mask) +{ + int A; + uint8_t *RAM = machine.root_device().memregion("maincpu")->base(); + + + for (A = 0x0000;A < 0x8000-14;A++) + { + static const char text[] = "INSERT COIN"; + int i; + + + if ( (RAM[A+0] & mask) == (0x21 & mask) && /* LD HL,$xxxx */ + (RAM[A+3] & mask) == (0x11 & mask) && /* LD DE,$xxxx */ + (RAM[A+6] & mask) == (0x01 & mask)) /* LD BC,$xxxx */ + { + if ( (RAM[A+ 9] & mask) == (0x36 & mask) && /* LD (HL),$xx */ + (RAM[A+11] & mask) == (0xed & mask) && + (RAM[A+12] & mask) == (0xb0 & mask)) /* LDIR */ + logerror("%04x: hl de bc (hl),xx ldir\n",A); + + if ( (RAM[A+ 9] & mask) == (0x77 & mask) && /* LD (HL),A */ + (RAM[A+10] & mask) == (0xed & mask) && + (RAM[A+11] & mask) == (0xb0 & mask)) /* LDIR */ + logerror("%04x: hl de bc (hl),a ldir\n",A); + + if ( (RAM[A+ 9] & mask) == (0xed & mask) && + (RAM[A+10] & mask) == (0xb0 & mask)) /* LDIR */ + logerror("%04x: hl de bc ldir\n",A); + } + + /* the following can also be PUSH IX, PUSH IY - need better checking */ + if ( (RAM[A+0] & mask) == (0xf5 & mask) && /* PUSH AF */ + (RAM[A+1] & mask) == (0xc5 & mask) && /* PUSH BC */ + (RAM[A+2] & mask) == (0xd5 & mask) && /* PUSH DE */ + (RAM[A+3] & mask) == (0xe5 & mask)) /* PUSH HL */ + logerror("%04x: push af bc de hl\n",A); + + if ( (RAM[A+0] & mask) == (0xe1 & mask) && /* POP HL */ + (RAM[A+1] & mask) == (0xd1 & mask) && /* POP DE */ + (RAM[A+2] & mask) == (0xc1 & mask) && /* POP BC */ + (RAM[A+3] & mask) == (0xf1 & mask)) /* POP AF */ + logerror("%04x: pop hl de bc af\n",A); + + for (i = 0;i < strlen(text);i++) + if ((RAM[A+i] & mask) != (text[i] & mask)) break; + if (i == strlen(text)) + logerror("%04x: INSERT COIN\n",A); + } +} + +static void look_for_known_plaintext(void) +{ + lfkp(0x57); +} +#endif + +static void decode(uint8_t *data, uint8_t *opcodes, int size, const uint8_t convtable[32][4], int bank_count, int bank_size) +{ + for (int A = 0x0000;A < size + bank_count*bank_size;A++) + { + int xorval = 0; + + uint8_t src = data[A]; + int adr; + if(A < size || !bank_count) + adr = A; + else + adr = size + ((A - size) % bank_size); + + /* pick the translation table from bits 0, 4, 8 and 12 of the address */ + int row = (adr & 1) + (((adr >> 4) & 1) << 1) + (((adr >> 8) & 1) << 2) + (((adr >> 12) & 1) << 3); + + /* pick the offset in the table from bits 3 and 5 of the source data */ + int col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1); + /* the bottom half of the translation table is the mirror image of the top */ + if (src & 0x80) + { + col = 3 - col; + xorval = 0xa8; + } + + /* decode the opcodes */ + opcodes[A] = (src & ~0xa8) | (convtable[2*row][col] ^ xorval); + + /* decode the data */ + data[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xorval); + + if (convtable[2*row][col] == 0xff) /* table incomplete! (for development) */ + opcodes[A] = 0xee; + if (convtable[2*row+1][col] == 0xff) /* table incomplete! (for development) */ + data[A] = 0xee; + } +} + + + + +DEFINE_DEVICE_TYPE(SEGA_315_5132, sega_315_5132_device, "sega_315_5132", "Sega 315-5132") +DEFINE_DEVICE_TYPE(SEGA_315_5155, sega_315_5155_device, "sega_315_5155", "Sega 315-5155") +DEFINE_DEVICE_TYPE(SEGA_315_5110, sega_315_5110_device, "sega_315_5110", "Sega 315-5110") +DEFINE_DEVICE_TYPE(SEGA_315_5135, sega_315_5135_device, "sega_315_5135", "Sega 315-5135") +DEFINE_DEVICE_TYPE(SEGA_315_5051, sega_315_5051_device, "sega_315_5051", "Sega 315-5051") +DEFINE_DEVICE_TYPE(SEGA_315_5098, sega_315_5098_device, "sega_315_5098", "Sega 315-5098") // also 315-5030 ? +DEFINE_DEVICE_TYPE(SEGA_315_5102, sega_315_5102_device, "sega_315_5102", "Sega 315-5102") +DEFINE_DEVICE_TYPE(SEGA_315_5065, sega_315_5065_device, "sega_315_5065", "Sega 315-5065") +DEFINE_DEVICE_TYPE(SEGA_315_5064, sega_315_5064_device, "sega_315_5064", "Sega 315-5064") +DEFINE_DEVICE_TYPE(SEGA_315_5033, sega_315_5033_device, "sega_315_5033", "Sega 315-5033") +DEFINE_DEVICE_TYPE(SEGA_315_5041, sega_315_5041_device, "sega_315_5041", "Sega 315-5041") +DEFINE_DEVICE_TYPE(SEGA_315_5048, sega_315_5048_device, "sega_315_5048", "Sega 315-5048") +DEFINE_DEVICE_TYPE(SEGA_315_5093, sega_315_5093_device, "sega_315_5093", "Sega 315-5093") +DEFINE_DEVICE_TYPE(SEGA_315_5099, sega_315_5099_device, "sega_315_5099", "Sega 315-5099") +DEFINE_DEVICE_TYPE(SEGA_315_5015, sega_315_5015_device, "sega_315_5015", "Sega 315-5015") +DEFINE_DEVICE_TYPE(SEGA_315_5133, sega_315_5133_device, "sega_315_5133", "Sega 315-5133") // exactly the same as Sega 315-5048? +DEFINE_DEVICE_TYPE(SEGA_315_5061, sega_315_5061_device, "sega_315_5061", "Sega 315-5061") +DEFINE_DEVICE_TYPE(SEGA_315_5028, sega_315_5028_device, "sega_315_5028", "Sega 315-5028") +DEFINE_DEVICE_TYPE(SEGA_315_5084, sega_315_5084_device, "sega_315_5084", "Sega 315-5084") +DEFINE_DEVICE_TYPE(SEGA_315_5013, sega_315_5013_device, "sega_315_5013", "Sega 315-5013") +DEFINE_DEVICE_TYPE(SEGA_315_5014, sega_315_5014_device, "sega_315_5014", "Sega 315-5014") +DEFINE_DEVICE_TYPE(SEGA_315_5018, sega_315_5018_device, "sega_315_5018", "Sega 315-5018") +DEFINE_DEVICE_TYPE(SEGA_315_5010, sega_315_5010_device, "sega_315_5010", "Sega 315-5010") +DEFINE_DEVICE_TYPE(SEGA_315_SPAT, sega_315_spat_device, "sega_315_spat", "Sega 315-5xxx (Spatter)") // unknown part number +DEFINE_DEVICE_TYPE(SEGA_315_5128, sega_315_5128_device, "sega_315_5128", "Sega 315-5128") + + + + +segacrpt_z80_device::segacrpt_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + z80_device(mconfig, type, tag, owner, clock), + m_decrypted_ptr(nullptr), + m_region_ptr(nullptr), + m_decode_size(0x8000), + m_numbanks(0), + m_banksize(0), + m_decryption_done(false) +{ +} + +void segacrpt_z80_device::device_start() +{ + z80_device::device_start(); +} + +void segacrpt_z80_device::device_reset() +{ + // decrypt on reset, makes sure DRIVER_INIT stuff happens first (for myherok) + // actual CPU would be decrypting in realtime anyway + if (m_decrypted_ptr == nullptr) + { + m_decrypted_ptr = (uint8_t*)memshare(m_decrypted_tag)->ptr(); + } + + if (m_region_ptr == nullptr) + { + m_region_ptr = (uint8_t*)memregion(tag())->base(); + } + + if (m_decryption_done == false) + { + decrypt(); + m_decryption_done = true; + } + z80_device::device_reset(); +} + +void segacrpt_z80_device::set_region_p(uint8_t* ptr) +{ + m_region_ptr = ptr; +} + +void segacrpt_z80_device::set_decrypted_p(uint8_t* ptr) +{ + m_decrypted_ptr = ptr; +} + + + + +sega_315_5132_device::sega_315_5132_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5132, tag, owner, clock) {} +void sega_315_5132_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...0 */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...1 */ + { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */ + { 0x20,0x00,0xa0,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...0 */ + { 0x80,0xa0,0x88,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...1 */ + { 0x80,0xa0,0x88,0xa8 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...0 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ + { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + + +sega_315_5155_device::sega_315_5155_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5155, tag, owner, clock) {} +void sega_315_5155_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x20,0x28,0x00,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...0...0...0 */ + { 0x20,0x28,0x00,0x08 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ + { 0x20,0x28,0x00,0x08 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */ + { 0x80,0x00,0xa0,0x20 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...0 */ + { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...1 */ + { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...1 */ + { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...1 */ + { 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + + +sega_315_5110_device::sega_315_5110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5110, tag, owner, clock) {} +void sega_315_5110_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0x08,0x80,0x00 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...0...0 */ + { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...1 */ + { 0x88,0x08,0xa8,0x28 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...1...0 */ + { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ + { 0x00,0x20,0x80,0xa0 }, { 0x08,0x00,0x88,0x80 }, /* ...0...1...0...0 */ + { 0x00,0x20,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...0...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ + { 0x88,0x08,0x80,0x00 }, { 0x08,0x00,0x88,0x80 }, /* ...1...0...0...0 */ + { 0x08,0x00,0x88,0x80 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...0...1 */ + { 0x08,0x28,0x00,0x20 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...1 */ + { 0x08,0x28,0x00,0x20 }, { 0x08,0x00,0x88,0x80 }, /* ...1...1...0...0 */ + { 0x08,0x28,0x00,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 }, /* ...1...1...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + +sega_315_5135_device::sega_315_5135_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5135, tag, owner, clock) {} +void sega_315_5135_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...1...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */ + { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ + { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */ + { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...0 */ + { 0xa0,0x20,0xa8,0x28 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...1...0...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...1...0 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + + +sega_315_5051_device::sega_315_5051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5051, tag, owner, clock) {} +void sega_315_5051_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x08,0x88,0x00,0x80 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ + { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0x20,0x00 }, /* ...0...0...1...0 */ + { 0x28,0x08,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ + { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...1...0...0 */ + { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ + { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...0...1...1...0 */ + { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ + { 0x08,0x88,0x00,0x80 }, { 0xa8,0x88,0x28,0x08 }, /* ...1...0...0...0 */ + { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...1 */ + { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */ + { 0xa8,0x88,0x28,0x08 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...1 */ + { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...0 */ + { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...1 */ + { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...1...1...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x88,0x80,0x08,0x00 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + +sega_315_5098_device::sega_315_5098_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5098, tag, owner, clock) {} +void sega_315_5098_device::decrypt() +{ + // also 315-5030 ? + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x08,0x88,0x00,0x80 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...0...0...0 */ + { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...1...0...0 */ + { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */ + { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...0...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + + +sega_315_5102_device::sega_315_5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5102, tag, owner, clock) {} +void sega_315_5102_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...1 */ + { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...0...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...1...1 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ + { 0xa0,0xa8,0x80,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...0...1 */ + { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */ + { 0xa8,0xa0,0x28,0x20 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...1...0 */ + { 0xa8,0xa0,0x28,0x20 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + +sega_315_5065_device::sega_315_5065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5065, tag, owner, clock) {} +void sega_315_5065_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0xa0,0xa8,0x20,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...0...0...0...0 */ + { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...0...0...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...0...1...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...1...1...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...0...1 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ + { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...1 */ + { 0x08,0x28,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ + { 0x08,0x28,0x00,0x20 }, { 0x88,0x08,0xa8,0x28 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + +sega_315_5064_device::sega_315_5064_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5064, tag, owner, clock) {} +void sega_315_5064_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...0...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...0...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...1 */ + { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...0 */ + { 0x08,0x88,0x00,0x80 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...1 */ + { 0xa8,0x28,0x88,0x08 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...1...0 */ + { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...1...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...0...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...0 */ + { 0xa8,0x28,0x88,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...1...0 */ + { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + +sega_315_5033_device::sega_315_5033_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5033, tag, owner, clock) {} +void sega_315_5033_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...1...0 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */ + { 0x80,0xa0,0x00,0x20 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */ + { 0x80,0xa0,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...0 */ + { 0x80,0xa0,0x00,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + +sega_315_5041_device::sega_315_5041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5041, tag, owner, clock) {} +void sega_315_5041_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */ + { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...1...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...1...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + +sega_315_5048_device::sega_315_5048_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5048, tag, owner, clock) {} +sega_315_5048_device::sega_315_5048_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, type, tag, owner, clock) {} +void sega_315_5048_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */ + { 0xa0,0xa8,0x80,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ + { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...0 */ + { 0xa0,0x20,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */ + { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...0 */ + { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...1...0...1 */ + { 0xa0,0xa8,0x80,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...1...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + +sega_315_5093_device::sega_315_5093_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5093, tag, owner, clock) {} +void sega_315_5093_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ + { 0x08,0x88,0x28,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...0...0...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...1...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...1...0...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...1...0...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...1...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + +sega_315_5099_device::sega_315_5099_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5099, tag, owner, clock) {} +void sega_315_5099_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0xa0,0xa8,0x20,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...0...0...0...0 */ + { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...0...0...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...0...1...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...1...1...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...0...1 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ + { 0x28,0xa8,0x20,0xa0 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ + { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ + { 0x88,0x08,0xa8,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...1 */ + { 0x08,0x28,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ + { 0x08,0x28,0x00,0x20 }, { 0x88,0x08,0xa8,0x28 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + + +sega_315_spat_device::sega_315_spat_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_SPAT, tag, owner, clock) {} +void sega_315_spat_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0x08,0x80,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...0...0...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ + { 0x00,0x08,0x20,0x28 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0x80,0x88,0x00,0x08 }, /* ...0...1...0...1 */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0x80,0x88,0x00,0x08 }, /* ...1...0...0...0 */ + { 0x80,0x88,0x00,0x08 }, { 0x00,0x08,0x20,0x28 }, /* ...1...0...0...1 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...0 */ + { 0x00,0x08,0x20,0x28 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */ + { 0x80,0x88,0x00,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ + { 0x80,0xa0,0x88,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...1...1...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + +sega_315_5015_device::sega_315_5015_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5015, tag, owner, clock) {} +void sega_315_5015_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...0 */ + { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...0...0 */ + { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...0...1 */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...0 */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...0...1 */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ + { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...1...1 */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */ + { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ + { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ + }; + + /* decrypt program ROMs */ + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + +sega_315_5133_device::sega_315_5133_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : sega_315_5048_device(mconfig, SEGA_315_5133, tag, owner, clock) {} +// == sega_315_5048_device + + +sega_315_5014_device::sega_315_5014_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5014, tag, owner, clock) {} +void sega_315_5014_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...0...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ + { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...0...0 */ + { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...0 */ + { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ + { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...1 */ + { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */ + }; + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + +sega_315_5013_device::sega_315_5013_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5013, tag, owner, clock) {} +void sega_315_5013_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...0...0 */ + { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ + { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */ + { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ + { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...1...1...0 */ + { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ + { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...1...0 */ + { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...0...1...1 */ + { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...0...0 */ + { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...0...1 */ + { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + +sega_315_5061_device::sega_315_5061_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5061, tag, owner, clock) {} +void sega_315_5061_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...0...0...0...0 */ + { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...0...0...1 */ + { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...0...1...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...0...1...1 */ + { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0xa8,0xa0 }, /* ...0...1...0...0 */ + { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ + { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...1...1 */ + { 0x88,0x80,0xa8,0xa0 }, { 0x28,0x08,0x20,0x00 }, /* ...1...0...0...0 */ + { 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...1 */ + { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 }, /* ...1...0...1...0 */ + { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...1...1 */ + { 0x88,0x80,0xa8,0xa0 }, { 0x88,0x80,0xa8,0xa0 }, /* ...1...1...0...0 */ + { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */ + { 0x80,0x00,0xa0,0x20 }, { 0x28,0x08,0x20,0x00 }, /* ...1...1...1...0 */ + { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + +sega_315_5018_device::sega_315_5018_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5018, tag, owner, clock) {} +void sega_315_5018_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...0 */ + { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...0...1...1 */ + { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...0...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...0...1 */ + { 0x20,0xa0,0x28,0xa8 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...1...1...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */ + { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...0...0...0 */ + { 0x20,0xa0,0x28,0xa8 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ + { 0xa0,0x20,0x80,0x00 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...1 */ + { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...0 */ + { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...1 */ + { 0xa0,0x20,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...1...1...0 */ + { 0x20,0xa0,0x28,0xa8 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); + +} + + +sega_315_5010_device::sega_315_5010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5010, tag, owner, clock) {} +void sega_315_5010_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0xa0,0x80,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...0 */ + { 0x08,0x28,0x88,0xa8 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ + { 0x08,0x00,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0x08,0x00,0x88,0x80 }, /* ...0...1...0...1 */ + { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */ + { 0xa0,0x80,0x20,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...0...1...1...1 */ + { 0x88,0x80,0x08,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...0 */ + { 0x88,0x80,0x08,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...1...0...0...1 */ + { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, /* ...1...0...1...0 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...1 */ + { 0x08,0x00,0x88,0x80 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ + { 0x00,0x08,0x20,0x28 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */ + { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, /* ...1...1...1...0 */ + { 0x08,0x00,0x88,0x80 }, { 0xa0,0x80,0x20,0x00 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + + + +sega_315_5128_device::sega_315_5128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5128, tag, owner, clock) {} +void sega_315_5128_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0xa8,0xa0,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...0 */ + { 0x28,0x08,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...1 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...0 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */ + { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...0...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ + { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...0 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...1 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...1 */ + { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ + { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...0...0 */ + { 0x28,0x20,0xa8,0xa0 }, { 0xa8,0x28,0xa0,0x20 }, /* ...1...1...0...1 */ + { 0xa0,0x80,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ + { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0x28,0xa0,0x20 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + +sega_315_5028_device::sega_315_5028_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5028, tag, owner, clock) {} +void sega_315_5028_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...0...1 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...1...1 */ + { 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 }, /* ...0...1...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...0 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...1...0...1...0 */ + { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...1...0...1...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ + { 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...1 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ + { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 } /* ...1...1...1...1 */ + }; + + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} + + +sega_315_5084_device::sega_315_5084_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5084, tag, owner, clock) {} +void sega_315_5084_device::decrypt() +{ + static const uint8_t convtable[32][4] = + { + /* opcode data address */ + /* A B C D A B C D */ + { 0x28,0x08,0xa8,0x88 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...0...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x80,0x88,0xa0,0xa8 }, /* ...0...0...1...1 */ + { 0x08,0x88,0x00,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...0 */ + { 0x88,0xa8,0x80,0xa0 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ + { 0x20,0xa0,0x00,0x80 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...1...1...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...1...1 */ + { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...1 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...0...1...0 */ + { 0xa0,0xa8,0x20,0x28 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...1...1 */ + { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...0 */ + { 0x08,0x88,0x00,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...1...0...1 */ + { 0x28,0x08,0xa8,0x88 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...1...0 */ + { 0x80,0x88,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 } /* ...1...1...1...1 */ + }; + decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); +} diff --git a/src/devices/machine/segacrpt_device.h b/src/devices/machine/segacrpt_device.h new file mode 100644 index 00000000000..63b50bde2d0 --- /dev/null +++ b/src/devices/machine/segacrpt_device.h @@ -0,0 +1,279 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#ifndef MAME_MACHINE_SEGACRYPT_DEVICE_H +#define MAME_MACHINE_SEGACRYPT_DEVICE_H + +#pragma once + +#include "cpu/z80/z80.h" + + +// base class +class segacrpt_z80_device : public z80_device +{ +public: + void set_decrypted_tag(const char* decrypted_tag) { m_decrypted_tag = decrypted_tag; } + void set_size(int size) { m_decode_size = size; } + void set_numbanks(int numbanks) { m_numbanks = numbanks; } + void set_banksize(int banksize) { m_banksize = banksize; } + + void set_decrypted_p(uint8_t* ptr); + void set_region_p(uint8_t* ptr); + +protected: + segacrpt_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + virtual void decrypt() = 0; + + const char* m_decrypted_tag = nullptr; + uint8_t* m_decrypted_ptr; + uint8_t* m_region_ptr; + int m_decode_size; + int m_numbanks; + int m_banksize; + +private: + bool m_decryption_done; +}; + + +// actual encrypted CPUs +class sega_315_5132_device : public segacrpt_z80_device +{ +public: + sega_315_5132_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5155_device : public segacrpt_z80_device +{ +public: + sega_315_5155_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5110_device : public segacrpt_z80_device +{ +public: + sega_315_5110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5135_device : public segacrpt_z80_device +{ +public: + sega_315_5135_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5051_device : public segacrpt_z80_device +{ +public: + sega_315_5051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5098_device : public segacrpt_z80_device +{ +public: + sega_315_5098_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5102_device : public segacrpt_z80_device +{ +public: + sega_315_5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5065_device : public segacrpt_z80_device +{ +public: + sega_315_5065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + +class sega_315_5064_device : public segacrpt_z80_device +{ +public: + sega_315_5064_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + +class sega_315_5033_device : public segacrpt_z80_device +{ +public: + sega_315_5033_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5041_device : public segacrpt_z80_device +{ +public: + sega_315_5041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5048_device : public segacrpt_z80_device +{ +public: + sega_315_5048_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); + sega_315_5048_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void decrypt() override; +}; + +class sega_315_5093_device : public segacrpt_z80_device +{ +public: + sega_315_5093_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5099_device : public segacrpt_z80_device +{ +public: + sega_315_5099_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_spat_device : public segacrpt_z80_device +{ +public: + sega_315_spat_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5015_device : public segacrpt_z80_device +{ +public: + sega_315_5015_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + +class sega_315_5133_device : public sega_315_5048_device +{ +public: + sega_315_5133_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +}; + +class sega_315_5014_device : public segacrpt_z80_device +{ +public: + sega_315_5014_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5013_device : public segacrpt_z80_device +{ +public: + sega_315_5013_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5061_device : public segacrpt_z80_device +{ +public: + sega_315_5061_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + + +class sega_315_5018_device : public segacrpt_z80_device +{ +public: + sega_315_5018_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5010_device : public segacrpt_z80_device +{ +public: + sega_315_5010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + + +class sega_315_5128_device : public segacrpt_z80_device +{ +public: + sega_315_5128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5028_device : public segacrpt_z80_device +{ +public: + sega_315_5028_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + +class sega_315_5084_device : public segacrpt_z80_device +{ +public: + sega_315_5084_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); +protected: + virtual void decrypt() override; +}; + + +DECLARE_DEVICE_TYPE(SEGA_315_5132, sega_315_5132_device) +DECLARE_DEVICE_TYPE(SEGA_315_5155, sega_315_5155_device) +DECLARE_DEVICE_TYPE(SEGA_315_5110, sega_315_5110_device) +DECLARE_DEVICE_TYPE(SEGA_315_5135, sega_315_5135_device) +DECLARE_DEVICE_TYPE(SEGA_315_5051, sega_315_5051_device) +DECLARE_DEVICE_TYPE(SEGA_315_5098, sega_315_5098_device) +DECLARE_DEVICE_TYPE(SEGA_315_5102, sega_315_5102_device) +DECLARE_DEVICE_TYPE(SEGA_315_5065, sega_315_5065_device) +DECLARE_DEVICE_TYPE(SEGA_315_5064, sega_315_5064_device) +DECLARE_DEVICE_TYPE(SEGA_315_5033, sega_315_5033_device) +DECLARE_DEVICE_TYPE(SEGA_315_5041, sega_315_5041_device) +DECLARE_DEVICE_TYPE(SEGA_315_5048, sega_315_5048_device) +DECLARE_DEVICE_TYPE(SEGA_315_5093, sega_315_5093_device) +DECLARE_DEVICE_TYPE(SEGA_315_5099, sega_315_5099_device) +DECLARE_DEVICE_TYPE(SEGA_315_SPAT, sega_315_spat_device) +DECLARE_DEVICE_TYPE(SEGA_315_5015, sega_315_5015_device) +DECLARE_DEVICE_TYPE(SEGA_315_5133, sega_315_5133_device) +DECLARE_DEVICE_TYPE(SEGA_315_5014, sega_315_5014_device) +DECLARE_DEVICE_TYPE(SEGA_315_5013, sega_315_5013_device) +DECLARE_DEVICE_TYPE(SEGA_315_5061, sega_315_5061_device) +DECLARE_DEVICE_TYPE(SEGA_315_5018, sega_315_5018_device) +DECLARE_DEVICE_TYPE(SEGA_315_5010, sega_315_5010_device) +DECLARE_DEVICE_TYPE(SEGA_315_5128, sega_315_5128_device) +DECLARE_DEVICE_TYPE(SEGA_315_5028, sega_315_5028_device) +DECLARE_DEVICE_TYPE(SEGA_315_5084, sega_315_5084_device) + + +#endif // MAME_MACHINE_SEGACRYPT_DEVICE_H diff --git a/src/mame/igs/goldstar.cpp b/src/mame/igs/goldstar.cpp index 872c4dc3b67..9f48e1ba650 100644 --- a/src/mame/igs/goldstar.cpp +++ b/src/mame/igs/goldstar.cpp @@ -215,12 +215,11 @@ #include "emu.h" #include "goldstar.h" -#include "segacrp2_device.h" -#include "segacrpt_device.h" - #include "cpu/z80/z80.h" #include "cpu/mcs51/mcs51.h" #include "machine/nvram.h" +#include "machine/segacrp2_device.h" +#include "machine/segacrpt_device.h" #include "sound/ay8910.h" #include "sound/okim6295.h" #include "sound/sn76496.h" diff --git a/src/mame/kiwako/jongkyo.cpp b/src/mame/kiwako/jongkyo.cpp index 57b947b0d18..25901e3c1fc 100644 --- a/src/mame/kiwako/jongkyo.cpp +++ b/src/mame/kiwako/jongkyo.cpp @@ -28,8 +28,7 @@ #include "emu.h" -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "cpu/z80/z80.h" #include "sound/ay8910.h" diff --git a/src/mame/mame.lst b/src/mame/mame.lst index baee015ffa0..3506e4855e8 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -11933,7 +11933,7 @@ waidrive // 2005.01 WaiWai Drive xtrmhnt2 // 2006.09 Extreme Hunting 2 Tournament Edition xtrmhunt // 2004.09 Extreme Hunting -@source:segacons/dccons.cpp +@source:sega/dccons.cpp dc // 1999 Sega Dreamcast (USA) dcdev // 1998 Sega HKT-0120 Sega Dreamcast Development Box dceu // 1999 Sega Dreamcast (Europe) @@ -23053,7 +23053,7 @@ mechattu1 // A8002 'MA' (c) 1989 a51site4 // ?? (c) 1998 a51site4a // Sept.11,1998 (c) 1998 -@source:segacons/mdconsole.cpp +@source:sega/mdconsole.cpp 32x // 1994 Sega 32X (USA) 32x_mcd // 1995 Sega Mega-CD (Europe w/32X addon) 32x_mcdj // 1994 Sega Mega-CD (Japan w/32X addon) @@ -23100,7 +23100,7 @@ ssf2mdb // MegaDrive-based hack topshoot // (c) 1995 Sun Mixing twinktmb // MegaDrive-based hack -@source:segacons/megadriv_rad.cpp +@source:sega/megadriv_rad.cpp rad_sf2 // (c)2004 Radica rad_sf2p // (c)2004 Radica rad_gen1 // (c)2004 Radica @@ -23115,10 +23115,10 @@ msi_sf2 dgunl3227 ra145 -@source:segacons/megadriv_sunplus_hybrid.cpp +@source:sega/megadriv_sunplus_hybrid.cpp reactmd -@source:segacons/megadriv_vt_hybrid.cpp +@source:sega/megadriv_vt_hybrid.cpp sarc110 sarc110a @@ -37779,10 +37779,10 @@ wg3dhfe // (c) 1996 Atari Games @source:skeleton/seattlecmp.cpp scp300f // Seattle SCP-300F -@source:segacons/sega_beena.cpp +@source:sega/sega_beena.cpp beena // -@source:segacons/sega_sawatte.cpp +@source:sega/sega_sawatte.cpp sawatte // @source:sega/segaatom.cpp @@ -37949,13 +37949,13 @@ toutrunj1 // 1987 (FD1094) toutrunj1d // bootleg toutrunjd // bootleg -@source:segacons/segapico.cpp +@source:sega/segapico.cpp copera // 1993 Sega / Yamaha pico // 1994 Sega Pico (Europe) picoj // 1993 Sega Pico (Japan) picou // 1994 Sega Pico (USA) -@source:segacons/segapm.cpp +@source:sega/segapm.cpp segapm // 1996 Sega Picture Magic (32x type hardware) @source:sega/segas16a.cpp @@ -38869,7 +38869,7 @@ sfkick // (c) 1988 Haesung/HJ Corp sfkicka // (c) 198? Haesung spinkick // (c) 1988 Haesung/Seojin -@source:segacons/sg1000.cpp +@source:sega/sg1000.cpp omv1000 // Tsukuda Original Othello Multivision FG-1000 omv2000 // Tsukuda Original Othello Multivision FG-2000 sc3000 // Sega SC-3000 (Japan) @@ -40547,7 +40547,7 @@ svisionp // svisions // tvlinkp // -@source:segacons/svmu.cpp +@source:sega/svmu.cpp svmu // 1998 Sega Visual Memory Unit @source:namco/sweetland.cpp diff --git a/src/mame/mess.flt b/src/mame/mess.flt index 18aae54476e..75418b7471e 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -674,17 +674,17 @@ sanyo/phc25.cpp saturn/st17xx.cpp sega/saturn.cpp sega/sms.cpp -segacons/dccons.cpp -segacons/mdconsole.cpp -segacons/megadriv_rad.cpp -segacons/megadriv_sunplus_hybrid.cpp -segacons/megadriv_vt_hybrid.cpp -segacons/sega_beena.cpp -segacons/sega_sawatte.cpp -segacons/segapico.cpp -segacons/segapm.cpp -segacons/sg1000.cpp -segacons/svmu.cpp +sega/dccons.cpp +sega/mdconsole.cpp +sega/megadriv_rad.cpp +sega/megadriv_sunplus_hybrid.cpp +sega/megadriv_vt_hybrid.cpp +sega/sega_beena.cpp +sega/sega_sawatte.cpp +sega/segapico.cpp +sega/segapm.cpp +sega/sg1000.cpp +sega/svmu.cpp sequential/prophet600.cpp sfrj/galaxy.cpp sfrj/galeb.cpp diff --git a/src/mame/nichibut/cclimber.h b/src/mame/nichibut/cclimber.h index 5cc7cd3721c..91c88100c49 100644 --- a/src/mame/nichibut/cclimber.h +++ b/src/mame/nichibut/cclimber.h @@ -5,8 +5,7 @@ #pragma once -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "machine/74259.h" #include "machine/gen_latch.h" diff --git a/src/mame/nichibut/jangou.cpp b/src/mame/nichibut/jangou.cpp index 2b473e5947c..46ef242d6d7 100644 --- a/src/mame/nichibut/jangou.cpp +++ b/src/mame/nichibut/jangou.cpp @@ -27,8 +27,7 @@ $c088-$c095 player tiles #include "emu.h" -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "cpu/m6800/m6800.h" #include "cpu/z80/z80.h" #include "machine/gen_latch.h" diff --git a/src/mame/pacman/pengo.cpp b/src/mame/pacman/pengo.cpp index 05283372185..fdf27ed3a3a 100644 --- a/src/mame/pacman/pengo.cpp +++ b/src/mame/pacman/pengo.cpp @@ -66,8 +66,7 @@ #include "emu.h" #include "pacman.h" -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "cpu/z80/z80.h" #include "machine/74259.h" #include "machine/gen_latch.h" diff --git a/src/mame/sanritsu/appoooh.cpp b/src/mame/sanritsu/appoooh.cpp index 751bb7b2f64..06dd27b12f4 100644 --- a/src/mame/sanritsu/appoooh.cpp +++ b/src/mame/sanritsu/appoooh.cpp @@ -165,8 +165,7 @@ Language #include "emu.h" -#include "segacrp2_device.h" - +#include "machine/segacrp2_device.h" #include "cpu/z80/z80.h" #include "sound/msm5205.h" #include "sound/sn76496.h" diff --git a/src/mame/sega/angelkds.cpp b/src/mame/sega/angelkds.cpp index 943bc7f3ef1..8e1571658af 100644 --- a/src/mame/sega/angelkds.cpp +++ b/src/mame/sega/angelkds.cpp @@ -128,9 +128,8 @@ Dumped by Chackn #include "emu.h" -#include "segacrp2_device.h" - #include "cpu/z80/z80.h" +#include "machine/segacrp2_device.h" #include "machine/i8255.h" #include "sound/ymopn.h" diff --git a/src/mame/sega/calorie.cpp b/src/mame/sega/calorie.cpp index d4f57ec7708..734defb6bce 100644 --- a/src/mame/sega/calorie.cpp +++ b/src/mame/sega/calorie.cpp @@ -82,7 +82,7 @@ Notes: #include "emu.h" #include "cpu/z80/z80.h" #include "machine/gen_latch.h" -#include "segacrp2_device.h" +#include "machine/segacrp2_device.h" #include "sound/ay8910.h" #include "emupal.h" #include "screen.h" diff --git a/src/mame/sega/dc-ctrl.cpp b/src/mame/sega/dc-ctrl.cpp new file mode 100644 index 00000000000..fe2925fcf0b --- /dev/null +++ b/src/mame/sega/dc-ctrl.cpp @@ -0,0 +1,164 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +#include "emu.h" +#include "dc-ctrl.h" + +/******************************* + * + * Common abstract class + * + ******************************/ + +dc_common_device::dc_common_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + maple_device(mconfig, type, tag, owner, clock) + , port(*this, {finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG}) +{ +} + +void dc_common_device::device_start() +{ + maple_device::device_start(); +} + +void dc_common_device::maple_w(const uint32_t *data, uint32_t in_size) +{ + switch(data[0] & 0xff) { + case 0x01: // Device request + reply_start(5, 0x20, 29); + fixed_status(reply_buffer+1); + reply_ready_with_delay(); + break; + + case 0x02: // All status request + reply_start(6, 0x20, 49); + fixed_status(reply_buffer+1); + free_status(reply_buffer+29); + reply_ready_with_delay(); + break; + + case 0x03: // reset - we're stateless where it matters + reply_start(7, 0x20, 0); + reply_ready_with_delay(); + break; + + case 0x09: // get condition + if(1 || (in_size >= 2 && data[1] == 0x01000000)) { + reply_start(8, 0x20, 4); + read(reply_buffer+1); + reply_ready_with_delay(); + } + break; + } +} + +/******************************* + * + * Dreamcast Controller + * + ******************************/ + +DEFINE_DEVICE_TYPE(DC_CONTROLLER, dc_controller_device, "dcctrl", "Dreamcast Controller") + +dc_controller_device::dc_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + dc_common_device(mconfig, DC_CONTROLLER, tag, owner, clock) +{ + model = "Dreamcast Controller"; + license = "Produced By or Under License From SEGA ENTERPRISES,LTD."; + versions = "Version 1.000,1998/05/11,315-6215-AB ,Analog Module: The 4th Edition. 05/08"; + id = 0x01000000; // Controller + electric_current = 0x01f401ae; // max 50mA, standby 43mA + region = 0x00ff; +} + +void dc_controller_device::fixed_status(uint32_t *dest) +{ + dest[0] = id; + dest[1] = + ((port[2] != nullptr) ? 0x0100 : 0) | + ((port[3] != nullptr) ? 0x0200 : 0) | + ((port[4] != nullptr) ? 0x0400 : 0) | + ((port[5] != nullptr) ? 0x0800 : 0) | + ((port[6] != nullptr) ? 0x1000 : 0) | + ((port[7] != nullptr) ? 0x2000 : 0) | + ((port[0] ? port[0]->active() : 0) << 24) | + ((port[1] ? port[1]->active() : 0) << 16); // 1st function - controller + dest[2] = 0; // No 2nd function + dest[3] = 0; // No 3rd function + dest[4] = region; // Every region, no expansion + copy_with_spaces(((uint8_t *)dest) + 18, model, 30); + copy_with_spaces(((uint8_t *)dest) + 48, license, 60); + dest[27] = electric_current; +} + +void dc_controller_device::free_status(uint32_t *dest) +{ + copy_with_spaces((uint8_t *)dest, versions, 80); +} + +void dc_controller_device::read(uint32_t *dest) +{ + dest[0] = id; // Controller + dest[1] = + (port[0] ? port[0]->read() : 0xff) | + ((port[1] ? port[1]->read() : 0xff) << 8) | + ((port[2] ? port[2]->read() : 0) << 16) | + ((port[3] ? port[3]->read() : 0) << 24); + dest[2] = + (port[4] ? port[4]->read() : 0x80) | + ((port[5] ? port[5]->read() : 0x80) << 8) | + ((port[6] ? port[6]->read() : 0x80) << 16) | + ((port[7] ? port[7]->read() : 0x80) << 24); +} + +/******************************* + * + * Dreamcast Keyboard + * + ******************************/ + +DEFINE_DEVICE_TYPE(DC_KEYBOARD, dc_keyboard_device, "dckb", "Dreamcast Keyboard") + +dc_keyboard_device::dc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + dc_common_device(mconfig, DC_KEYBOARD, tag, owner, clock) +{ + model = "92key Keyboard for JPN"; + license = "Produced By or Under License From SEGA ENTERPRISES,LTD."; + versions = "Version 1.000,1998/06/12,315-6215-AD ,Key Scan Module: The 1st Edition. 05/20"; + id = 0x40000000; // Keyboard + electric_current = 0x0190015e; // max 40mA, standby 35mA + region = 0x0002; // Japan region, no expansion +} + +void dc_keyboard_device::fixed_status(uint32_t *dest) +{ + dest[0] = id; // Keyboard + dest[1] = 0x00201000; // 1st function + dest[2] = 0x00000008; // No 2nd function (doc returns 8 here tho?) + dest[3] = 0x00000000; // No 3rd function + dest[4] = region; + copy_with_spaces(((uint8_t *)dest) + 18, model, 30); + copy_with_spaces(((uint8_t *)dest) + 48, license, 60); + dest[27] = electric_current; +} + +void dc_keyboard_device::free_status(uint32_t *dest) +{ + copy_with_spaces((uint8_t *)dest, versions, 80); +} + +void dc_keyboard_device::read(uint32_t *dest) +{ + dest[0] = id; + // key code + dest[1] = + (port[0] ? port[0]->read() : 0) | + ((port[1] ? port[1]->read() : 0) << 8) | + ((port[2] ? port[2]->read() : 0) << 16) | + ((port[3] ? port[3]->read() : 0) << 24); + dest[2] = + (port[4] ? port[4]->read() : 0) | + ((port[5] ? port[5]->read() : 0) << 8) | + ((port[6] ? port[6]->read() : 0) << 16) | + ((port[7] ? port[7]->read() : 0) << 24); +} + diff --git a/src/mame/sega/dc-ctrl.h b/src/mame/sega/dc-ctrl.h new file mode 100644 index 00000000000..4fd4cd65131 --- /dev/null +++ b/src/mame/sega/dc-ctrl.h @@ -0,0 +1,97 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +#ifndef MAME_MACHINE_DC_CTRL_H +#define MAME_MACHINE_DC_CTRL_H + +#pragma once + +#include "mapledev.h" + + +class dc_common_device : public maple_device +{ +public: + // construction/destruction + dc_common_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + template + void set_port_tag(T &&port_tag) { port[Which].set_tag(std::forward(port_tag)); } + template + void set_port_tags(T &&first_tag, U &&... other_tags) + { + set_port_tag(std::forward(first_tag)); + set_port_tags(std::forward(other_tags)...); + } + + // TODO: we probably don't need these setters + void set_model(const char *new_id) { model = new_id; } + void set_license(const char *new_license) { license = new_license; } + void set_versions(const char *new_versions) { versions = new_versions; } + + void maple_w(const uint32_t *data, uint32_t in_size) override; + +protected: + template void set_port_tags() { } + + // device-level overrides + virtual void device_start() override; + + const char *model = nullptr, *license = nullptr, *versions = nullptr; + uint32_t id = 0; + uint32_t electric_current = 0; + uint32_t region = 0; + + optional_ioport_array<8> port; + + virtual void fixed_status(uint32_t *dest) = 0; + virtual void free_status(uint32_t *dest) = 0; + virtual void read(uint32_t *dest) = 0; +}; + +class dc_controller_device : public dc_common_device +{ +public: + // construction/destruction + template + dc_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&host_tag, int host_port) + : dc_controller_device(mconfig, tag, owner, clock) + { + host.set_tag(std::forward(host_tag)); + set_host_port(host_port); + } + + dc_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +private: + void fixed_status(uint32_t *dest) override; + void free_status(uint32_t *dest) override; + void read(uint32_t *dest) override; +}; + + +class dc_keyboard_device : public dc_common_device +{ +public: + // construction/destruction + template + dc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&host_tag, int host_port) + : dc_keyboard_device(mconfig, tag, owner, clock) + { + host.set_tag(std::forward(host_tag)); + set_host_port(host_port); + } + + dc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +//protected: + +private: + void fixed_status(uint32_t *dest) override; + void free_status(uint32_t *dest) override; + void read(uint32_t *dest) override; +}; + +DECLARE_DEVICE_TYPE(DC_CONTROLLER, dc_controller_device) +DECLARE_DEVICE_TYPE(DC_KEYBOARD, dc_keyboard_device) + +#endif // MAME_MACHINE_DC_CTRL_H diff --git a/src/mame/sega/dc.cpp b/src/mame/sega/dc.cpp new file mode 100644 index 00000000000..9e97c847294 --- /dev/null +++ b/src/mame/sega/dc.cpp @@ -0,0 +1,668 @@ +// license:LGPL-2.1+ +// copyright-holders: Samuele Zannoli, R. Belmont, ElSemi, David Haywood, Angelo Salese, Olivier Galibert, MetalliC +/* + + dc.cpp - Sega Dreamcast hardware + + Misc interfacing to common DC buses over the various clients. + +*/ + +#include "emu.h" +#include "dc.h" + +#include "mie.h" + +#include "cpu/sh/sh4.h" +#include "cpu/arm7/arm7core.h" + +//#include "debugger.h" + +#define DEBUG_REGISTERS (1) + +#if DEBUG_REGISTERS + +#define DEBUG_SYSCTRL (0) +#define DEBUG_AICA_DMA (0) + +#if DEBUG_SYSCTRL +static const char *const sysctrl_names[] = +{ + "CH2 DMA dest", + "CH2 DMA length", + "CH2 DMA start", + "5f680c", + "Sort DMA start link table addr", + "Sort DMA link base addr", + "Sort DMA link address bit width", + "Sort DMA link address shift control", + "Sort DMA start", + "5f6824", "5f6828", "5f682c", "5f6830", + "5f6834", "5f6838", "5f683c", + "DBREQ # signal mask control", + "BAVL # signal wait count", + "DMA priority count", + "CH2 DMA max burst length", + "5f6850", "5f6854", "5f6858", "5f685c", + "5f6860", "5f6864", "5f6868", "5f686c", + "5f6870", "5f6874", "5f6878", "5f687c", + "TA FIFO remaining", + "TA texture memory bus select 0", + "TA texture memory bus select 1", + "FIFO status", + "System reset", "5f6894", "5f6898", + "System bus version", + "SH4 root bus split enable", + "5f68a4", "5f68a8", "5f68ac", + "5f68b0", "5f68b4", "5f68b8", "5f68bc", + "5f68c0", "5f68c4", "5f68c8", "5f68cc", + "5f68d0", "5f68d4", "5f68d8", "5f68dc", + "5f68e0", "5f68e4", "5f68e8", "5f68ec", + "5f68f0", "5f68f4", "5f68f8", "5f68fc", + "Normal IRQ status", + "External IRQ status", + "Error IRQ status", "5f690c", + "Level 2 normal IRQ mask", + "Level 2 external IRQ mask", + "Level 2 error IRQ mask", "5f691c", + "Level 4 normal IRQ mask", + "Level 4 external IRQ mask", + "Level 4 error IRQ mask", "5f692c", + "Level 6 normal IRQ mask", + "Level 6 external IRQ mask", + "Level 6 error IRQ mask", "5f693c", + "Normal IRQ PVR-DMA startup mask", + "External IRQ PVR-DMA startup mask", + "5f6948", "5f694c", + "Normal IRQ G2-DMA startup mask", + "External IRQ G2-DMA startup mask" +}; +#endif + +#endif + +void dc_state::generic_dma(uint32_t main_adr, void *dma_ptr, uint32_t length, uint32_t size, bool to_mainram) +{ + sh4_ddt_dma ddt; + if(to_mainram) + ddt.destination = main_adr; + else + ddt.source = main_adr; + ddt.buffer = dma_ptr; + ddt.length = length; + ddt.size = size; + ddt.direction = to_mainram; + ddt.channel = 0; + ddt.mode = -1; + m_maincpu->sh4_dma_ddt(&ddt); +} + +void dc_state::g2_dma_end_w(offs_t channel, u8 state) +{ + dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_AICA << channel; + dc_update_interrupt_status(); +} + +void dc_state::g2_dma_error_ia_w(offs_t channel, u8 state) +{ + dc_sysctrl_regs[SB_ISTERR] |= 0x8000 << channel; + dc_update_interrupt_status(); +} + +void dc_state::g2_dma_error_ov_w(offs_t channel, u8 state) +{ + dc_sysctrl_regs[SB_ISTERR] |= 0x80000 << channel; + dc_update_interrupt_status(); +} + +void dc_state::g1_irq(uint8_t data) +{ + switch(data) { + case naomi_g1_device::DMA_GDROM_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_GDROM; + break; + } + dc_update_interrupt_status(); +} + +void dc_state::pvr_irq(uint8_t data) +{ + switch(data) { + case powervr2_device::EOXFER_YUV_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_YUV; + break; + + case powervr2_device::EOXFER_OPLST_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_OPLST; + break; + + case powervr2_device::EOXFER_OPMV_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_OPMV; + break; + + case powervr2_device::EOXFER_TRLST_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_TRLST; + break; + + case powervr2_device::EOXFER_TRMV_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_TRMV; + break; + + case powervr2_device::EOXFER_PTLST_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_PTLST; + break; + + case powervr2_device::VBL_IN_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_VBL_IN; + break; + + case powervr2_device::VBL_OUT_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_VBL_OUT; + break; + + case powervr2_device::HBL_IN_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_HBL_IN; + break; + + case powervr2_device::EOR_VIDEO_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_VIDEO; + break; + + case powervr2_device::EOR_TSP_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_TSP; + break; + + case powervr2_device::EOR_ISP_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_ISP; + break; + + case powervr2_device::DMA_PVR_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_PVR; + break; + + case powervr2_device::ERR_ISP_LIMIT_IRQ: + dc_sysctrl_regs[SB_ISTERR] |= IST_ERR_ISP_LIMIT; + break; + + case powervr2_device::ERR_PVRIF_ILL_ADDR_IRQ: + dc_sysctrl_regs[SB_ISTERR] |= IST_ERR_PVRIF_ILL_ADDR; + break; + } + dc_update_interrupt_status(); +} + +void dc_state::maple_irq(uint8_t data) +{ + switch(data) { + case maple_dc_device::DMA_MAPLE_IRQ: + dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_MAPLE; + break; + } + dc_update_interrupt_status(); +} + +TIMER_CALLBACK_MEMBER(dc_state::ch2_dma_irq) +{ + dc_sysctrl_regs[SB_C2DLEN] = 0; + dc_sysctrl_regs[SB_C2DST] = 0; + dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_CH2; + dc_update_interrupt_status(); +} + +// register decode helpers + +// this accepts only 32-bit accesses +int dc_state::decode_reg32_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift) +{ + int reg = offset * 2; + + *shift = 0; + + // non 32-bit accesses have not yet been seen here, we need to know when they are + if ((mem_mask != 0xffffffff00000000U) && (mem_mask != 0x00000000ffffffffU)) + { + osd_printf_verbose("%s:Wrong mask!\n", machine().describe_context()); + //machine().debug_break(); + } + + if (mem_mask == 0xffffffff00000000U) + { + reg++; + *shift = 32; + } + + return reg; +} + +// this accepts only 32 and 16 bit accesses +int dc_state::decode_reg3216_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift) +{ + int reg = offset * 2; + + *shift = 0; + + // non 16&32-bit accesses have not yet been seen here, we need to know when they are + if ((mem_mask != 0x0000ffff00000000U) && (mem_mask != 0x000000000000ffffU) && + (mem_mask != 0xffffffff00000000U) && (mem_mask != 0x00000000ffffffffU)) + { + osd_printf_verbose("%s:Wrong mask!\n", machine().describe_context()); + //machine().debug_break(); + } + + if (ACCESSING_BITS_32_47) + { + reg++; + *shift = 32; + } + + return reg; +} + +int dc_state::dc_compute_interrupt_level() +{ + uint32_t ln,lx,le; + + ln=dc_sysctrl_regs[SB_ISTNRM] & dc_sysctrl_regs[SB_IML6NRM]; + lx=dc_sysctrl_regs[SB_ISTEXT] & dc_sysctrl_regs[SB_IML6EXT]; + le=dc_sysctrl_regs[SB_ISTERR] & dc_sysctrl_regs[SB_IML6ERR]; + if (ln | lx | le) + { + return 6; + } + + ln=dc_sysctrl_regs[SB_ISTNRM] & dc_sysctrl_regs[SB_IML4NRM]; + lx=dc_sysctrl_regs[SB_ISTEXT] & dc_sysctrl_regs[SB_IML4EXT]; + le=dc_sysctrl_regs[SB_ISTERR] & dc_sysctrl_regs[SB_IML4ERR]; + if (ln | lx | le) + { + return 4; + } + + ln=dc_sysctrl_regs[SB_ISTNRM] & dc_sysctrl_regs[SB_IML2NRM]; + lx=dc_sysctrl_regs[SB_ISTEXT] & dc_sysctrl_regs[SB_IML2EXT]; + le=dc_sysctrl_regs[SB_ISTERR] & dc_sysctrl_regs[SB_IML2ERR]; + if (ln | lx | le) + { + return 2; + } + + return 0; +} + +void dc_state::dc_update_interrupt_status() +{ + int level; + + if (dc_sysctrl_regs[SB_ISTERR]) + { + dc_sysctrl_regs[SB_ISTNRM] |= IST_ERROR; + } + else + { + dc_sysctrl_regs[SB_ISTNRM] &= ~IST_ERROR; + } + + if (dc_sysctrl_regs[SB_ISTEXT]) + { + dc_sysctrl_regs[SB_ISTNRM] |= IST_G1G2EXTSTAT; + } + else + { + dc_sysctrl_regs[SB_ISTNRM] &= ~IST_G1G2EXTSTAT; + } + + level=dc_compute_interrupt_level(); + m_maincpu->sh4_set_irln_input(15-level); + + /* Wave DMA HW trigger */ + m_g2if->hw_irq_trigger_hs( + dc_sysctrl_regs[SB_G2DTNRM] & dc_sysctrl_regs[SB_ISTNRM], + dc_sysctrl_regs[SB_G2DTEXT] & dc_sysctrl_regs[SB_ISTEXT] + ); + + /* PVR-DMA HW trigger */ + if(m_powervr2->m_pvr_dma.flag && ((m_powervr2->m_pvr_dma.sel & 1) == 1)) + { + if((dc_sysctrl_regs[SB_PDTNRM] & dc_sysctrl_regs[SB_ISTNRM]) || (dc_sysctrl_regs[SB_PDTEXT] & dc_sysctrl_regs[SB_ISTEXT])) + { + address_space &space = m_maincpu->space(AS_PROGRAM); + + logerror("PVR-DMA HW trigger\n"); + m_powervr2->pvr_dma_execute(space); + } + } +} + +// TODO: convert SYSCTRL to device I/F (NAOMI2 needs two of these) +uint64_t dc_state::dc_sysctrl_r(offs_t offset, uint64_t mem_mask) +{ + int reg; + uint64_t shift; + + reg = decode_reg32_64(offset, mem_mask, &shift); + + #if DEBUG_SYSCTRL + if ((reg != 0x40) && (reg != 0x41) && (reg != 0x42) && (reg != 0x23) && (reg > 2)) // filter out IRQ status reads + { + osd_printf_verbose("SYSCTRL: [%08x] read %x @ %x (reg %x: %s), mask %x (PC=%x)\n", 0x5f6800+reg*4, dc_sysctrl_regs[reg], offset, reg, sysctrl_names[reg], mem_mask, m_maincpu->pc()); + } + #endif + + return (uint64_t)dc_sysctrl_regs[reg] << shift; +} + +void dc_state::dc_sysctrl_w(offs_t offset, uint64_t data, uint64_t mem_mask) +{ + int reg; + uint64_t shift; + uint32_t old,dat; + uint32_t address; + struct sh4_ddt_dma ddtdata; + + reg = decode_reg32_64(offset, mem_mask, &shift); + dat = (uint32_t)(data >> shift); + old = dc_sysctrl_regs[reg]; + dc_sysctrl_regs[reg] = dat; // 5f6800+off*4=dat + switch (reg) + { + case SB_C2DST: + if(((old & 1) == 0) && (dat & 1)) // 0 -> 1 + { + address=(dc_sysctrl_regs[SB_C2DSTAT] & 0x03ffffe0) | 0x10000000; + if(dc_sysctrl_regs[SB_C2DSTAT] & 0x1f) + printf("C2DSTAT just used to reserved bits %02x\n",dc_sysctrl_regs[SB_C2DSTAT] & 0x1f); + + ddtdata.destination=address; + /* 0 rounding size = 16 Mbytes */ + if(dc_sysctrl_regs[SB_C2DLEN] == 0) + ddtdata.length = 0x1000000; + else + ddtdata.length = dc_sysctrl_regs[SB_C2DLEN]; + ddtdata.size=1; + ddtdata.direction=0; + ddtdata.channel=2; + ddtdata.mode=25; //011001 + m_maincpu->sh4_dma_ddt(&ddtdata); + #if DEBUG_SYSCTRL + if ((address >= 0x11000000) && (address <= 0x11FFFFFF)) + if (dc_sysctrl_regs[SB_LMMODE0]) + printf("SYSCTRL: Ch2 direct display lists dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); // 1 + else + osd_printf_verbose("SYSCTRL: Ch2 direct textures dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); // 0 + else if ((address >= 0x13000000) && (address <= 0x13FFFFFF)) + if (dc_sysctrl_regs[SB_LMMODE1]) + printf("SYSCTRL: Ch2 direct display lists dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); // 1 + else + osd_printf_verbose("SYSCTRL: Ch2 direct textures dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); // 0 + else if ((address >= 0x10800000) && (address <= 0x10ffffff)) + printf("SYSCTRL: Ch2 YUV dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); + else if ((address >= 0x10000000) && (address <= 0x107fffff)) + osd_printf_verbose("SYSCTRL: Ch2 TA Display List dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); + else + osd_printf_verbose("SYSCTRL: Ch2 unknown dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); + #endif + + if ((!(address & 0x01000000))) + dc_sysctrl_regs[SB_C2DSTAT]=address; + else //direct texture path + dc_sysctrl_regs[SB_C2DSTAT]=address+ddtdata.length; + + /* TODO: timing is a guess */ + m_ch2_dma_irq_timer->adjust(m_maincpu->cycles_to_attotime(ddtdata.length/4)); + } + break; + + case SB_ISTNRM: + dc_sysctrl_regs[SB_ISTNRM] = old & ~(dat | 0xC0000000); // bits 31,30 ro + dc_update_interrupt_status(); + break; + + case SB_ISTEXT: + dc_sysctrl_regs[SB_ISTEXT] = old; + dc_update_interrupt_status(); + break; + + case SB_ISTERR: + dc_sysctrl_regs[SB_ISTERR] = old & ~dat; + dc_update_interrupt_status(); + break; + case SB_SDST: + if(dat & 1) + { + // TODO: Sort-DMA routine goes here + printf("Sort-DMA irq\n"); + + dc_sysctrl_regs[SB_SDST] = 0; + dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_SORT; + dc_update_interrupt_status(); + } + break; + } + + #if DEBUG_SYSCTRL + if ((reg != 0x40) && (reg != 0x42) && (reg > 2)) // filter out IRQ acks and ch2 dma + { + osd_printf_verbose("SYSCTRL: write %x to %x (reg %x), mask %x\n", data>>shift, offset, reg, /*sysctrl_names[reg],*/ mem_mask); + } + #endif +} + +uint64_t dc_state::dc_gdrom_r(offs_t offset, uint64_t mem_mask) +{ + uint32_t off; + + if ((int)~mem_mask & 1) + { + off=(offset << 1) | 1; + } + else + { + off=offset << 1; + } + + if (off*4 == 0x4c) + return -1; + if (off*4 == 8) + return 0; + + return 0; +} + +void dc_state::dc_gdrom_w(offs_t offset, uint64_t data, uint64_t mem_mask) +{ + uint32_t dat,off; + + if ((int)~mem_mask & 1) + { + dat=(uint32_t)(data >> 32); + off=(offset << 1) | 1; + } + else + { + dat=(uint32_t)data; + off=offset << 1; + } + + osd_printf_verbose("GDROM: [%08x=%x]write %x to %x, mask %x\n", 0x5f7000+off*4, dat, data, offset, mem_mask); +} + +int dc_state::decode_reg_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift) +{ + int reg = offset * 2; + + *shift = 0; + + // non 32-bit accesses have not yet been seen here, we need to know when they are + if ((mem_mask != 0xffffffff00000000U) && (mem_mask != 0x00000000ffffffffU)) + { + /*assume to return the lower 32-bits ONLY*/ + return reg & 0xffffffff; + } + + if (mem_mask == 0xffffffff00000000U) + { + reg++; + *shift = 32; + } + + return reg; +} + +uint64_t dc_state::dc_modem_r(offs_t offset, uint64_t mem_mask) +{ + int reg; + uint64_t shift; + + reg = decode_reg32_64(offset, mem_mask, &shift); + + // from ElSemi: this makes Atomiswave do it's "verbose boot" with a Sammy logo and diagnostics instead of just running the cart. + // our PVR emulation is apparently not good enough for that to work yet though. + if (reg == 0x280/4) + { + return 0xffffffffffffffffU; + } + + osd_printf_verbose("MODEM: Unmapped read %08x\n", 0x600000+reg*4); + return 0; +} + +void dc_state::dc_modem_w(offs_t offset, uint64_t data, uint64_t mem_mask) +{ + int reg; + uint64_t shift; + uint32_t dat; + + reg = decode_reg32_64(offset, mem_mask, &shift); + dat = (uint32_t)(data >> shift); + osd_printf_verbose("MODEM: [%08x=%x] write %x to %x, mask %x\n", 0x600000+reg*4, dat, data, offset, mem_mask); +} + +void dc_state::machine_start() +{ + // dccons doesn't have a specific g1 device yet + if(m_naomig1) + m_naomig1->set_dma_cb(naomi_g1_device::dma_cb(&dc_state::generic_dma, this)); + + m_maincpu->sh2drc_set_options(SH2DRC_STRICT_VERIFY | SH2DRC_STRICT_PCREL); + // TODO: repeated in dccons.cpp init_dc (NAOMI also uses double RAM) + m_maincpu->sh2drc_add_fastram(0x0c000000, 0x0cffffff, false, dc_ram); + + // save states + save_pointer(NAME(dc_sysctrl_regs), 0x200/4); + + m_ch2_dma_irq_timer = timer_alloc(FUNC(dc_state::ch2_dma_irq), this); +} + +void dc_state::machine_reset() +{ + /* halt the ARM7 */ + m_armrst = 1; + m_soundcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + + memset(dc_sysctrl_regs, 0, sizeof(dc_sysctrl_regs)); + + dc_sysctrl_regs[SB_SBREV] = 0x0b; + + m_ch2_dma_irq_timer->adjust(attotime::never); +} + +uint32_t dc_state::dc_aica_reg_r(offs_t offset, uint32_t mem_mask) +{ +// osd_printf_verbose("AICA REG: [%08x] read %x, mask %x\n", 0x700000+reg*4, (uint64_t)offset, mem_mask); + + if(offset == 0x2c00/4) + return m_armrst; + + return m_aica->read(offset*2); +} + +void dc_state::dc_aica_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + if (offset == (0x2c00/4)) + { + if(ACCESSING_BITS_0_7) + { + m_armrst = data & 1; + + if (data & 1) + { + /* halt the ARM7 */ + m_soundcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + } + else + { + /* it's alive ! */ + m_soundcpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + } + } + } + + m_aica->write(offset*2, data, 0xffff); + +// osd_printf_verbose("AICA REG: [%08x=%x] write %x to %x, mask %x\n", 0x700000+reg*4, data, offset, mem_mask); +} + +uint32_t dc_state::dc_arm_aica_r(offs_t offset) +{ + return m_aica->read(offset*2) & 0xffff; +} + +void dc_state::dc_arm_aica_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + m_aica->write(offset*2, data, mem_mask&0xffff); +} + +uint16_t dc_state::soundram_r(offs_t offset) +{ + return dc_sound_ram[offset]; +} + +void dc_state::soundram_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&dc_sound_ram[offset]); +} + +WRITE_LINE_MEMBER(dc_state::aica_irq) +{ + m_soundcpu->set_input_line(ARM7_FIRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); +} + +WRITE_LINE_MEMBER(dc_state::sh4_aica_irq) +{ + if(state) + dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_AICA; + else + dc_sysctrl_regs[SB_ISTEXT] &= ~IST_EXT_AICA; + + dc_update_interrupt_status(); +} + +WRITE_LINE_MEMBER(dc_state::external_irq) +{ + if (state) + dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_EXTERNAL; + else + dc_sysctrl_regs[SB_ISTEXT] &= ~IST_EXT_EXTERNAL; + + dc_update_interrupt_status(); +} + +MACHINE_RESET_MEMBER(dc_state,dc_console) +{ + dc_state::machine_reset(); + m_maincpu->sh2drc_set_options(SH2DRC_STRICT_VERIFY | SH2DRC_STRICT_PCREL); +} + +TIMER_DEVICE_CALLBACK_MEMBER(dc_state::dc_scanline) +{ + m_powervr2->pvr_scanline_timer(param); +} + +void dc_state::system_bus_config(machine_config &config, const char *cpu_tag) +{ + DC_G2IF(config, m_g2if, XTAL(25'000'000)); + m_g2if->set_host_space(cpu_tag, AS_PROGRAM); + m_g2if->int_cb().set(FUNC(dc_state::g2_dma_end_w)); + m_g2if->error_ia_cb().set(FUNC(dc_state::g2_dma_error_ia_w)); + m_g2if->error_ov_cb().set(FUNC(dc_state::g2_dma_error_ov_w)); +} diff --git a/src/mame/sega/dc.h b/src/mame/sega/dc.h new file mode 100644 index 00000000000..cf2eb344f42 --- /dev/null +++ b/src/mame/sega/dc.h @@ -0,0 +1,287 @@ +// license:LGPL-2.1+ +// copyright-holders:Angelo Salese, Olivier Galibert, David Haywood, Samuele Zannoli, R. Belmont, ElSemi + +#ifndef MAME_INCLUDES_DC_H +#define MAME_INCLUDES_DC_H + +#pragma once + +#include "dc_g2if.h" +#include "maple-dc.h" +#include "naomig1.h" +#include "powervr2.h" + +#include "cpu/arm7/arm7.h" +#include "cpu/arm7/arm7core.h" +#include "cpu/sh/sh4.h" +#include "machine/timer.h" +#include "sound/aica.h" + +class dc_state : public driver_device +{ +public: + dc_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , dc_framebuffer_ram(*this, "frameram") + , dc_texture_ram(*this, "dc_texture_ram") + , dc_sound_ram(*this, "dc_sound_ram") + , dc_ram(*this, "dc_ram") + , m_maincpu(*this, "maincpu") + , m_soundcpu(*this, "soundcpu") + , m_powervr2(*this, "powervr2") + , m_maple(*this, "maple_dc") + , m_naomig1(*this, "rom_board") + , m_g2if(*this, "sb_g2if") + , m_aica(*this, "aica") + { } + + required_shared_ptr dc_framebuffer_ram; // '32-bit access area' + required_shared_ptr dc_texture_ram; // '64-bit access area' + + required_shared_ptr dc_sound_ram; + required_shared_ptr dc_ram; + + /* machine related */ + uint32_t dc_sysctrl_regs[0x200/4]{}; + uint8_t m_armrst = 0U; + emu_timer *m_ch2_dma_irq_timer = nullptr; + + virtual void machine_start() override; + virtual void machine_reset() override; + void g2_dma_end_w(offs_t channel, u8 state); + void g2_dma_error_ia_w(offs_t channel, u8 state); + void g2_dma_error_ov_w(offs_t channel, u8 state); + TIMER_CALLBACK_MEMBER(ch2_dma_irq); + uint32_t dc_aica_reg_r(offs_t offset, uint32_t mem_mask = ~0); + void dc_aica_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t dc_arm_aica_r(offs_t offset); + void dc_arm_aica_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + inline int decode_reg32_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift); + inline int decode_reg3216_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift); + int dc_compute_interrupt_level(); + void dc_update_interrupt_status(); + inline int decode_reg_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift); + uint64_t dc_sysctrl_r(offs_t offset, uint64_t mem_mask = ~0); + void dc_sysctrl_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); + uint64_t dc_gdrom_r(offs_t offset, uint64_t mem_mask = ~0); + void dc_gdrom_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); + uint64_t dc_modem_r(offs_t offset, uint64_t mem_mask = ~0); + void dc_modem_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); + void g1_irq(uint8_t data); + void pvr_irq(uint8_t data); + void maple_irq(uint8_t data); + uint16_t soundram_r(offs_t offset); + void soundram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + DECLARE_WRITE_LINE_MEMBER(aica_irq); + DECLARE_WRITE_LINE_MEMBER(sh4_aica_irq); + DECLARE_WRITE_LINE_MEMBER(external_irq); + + + required_device m_maincpu; + required_device m_soundcpu; + required_device m_powervr2; + required_device m_maple; + optional_device m_naomig1; + required_device m_g2if; + required_device m_aica; + + void generic_dma(uint32_t main_adr, void *dma_ptr, uint32_t length, uint32_t size, bool to_mainram); + TIMER_DEVICE_CALLBACK_MEMBER(dc_scanline); + DECLARE_MACHINE_RESET(dc_console); + + void naomi_aw_base(machine_config &config); + void aica_map(address_map &map); + void dc_audio_map(address_map &map); + +protected: + void system_bus_config(machine_config &config, const char *cpu_tag); +}; + +/*--------- Ch2-DMA Control Registers ----------*/ +#define SB_C2DSTAT ((0x005f6800-0x005f6800)/4) +#define SB_C2DLEN ((0x005f6804-0x005f6800)/4) +#define SB_C2DST ((0x005f6808-0x005f6800)/4) +/*-------- Sort-DMA Control Registers ----------*/ +#define SB_SDSTAW ((0x005f6810-0x005f6800)/4) +#define SB_SDBAAW ((0x005f6814-0x005f6800)/4) +#define SB_SDWLT ((0x005f6818-0x005f6800)/4) +#define SB_SDLAS ((0x005f681c-0x005f6800)/4) +#define SB_SDST ((0x005f6820-0x005f6800)/4) +/*-- DDT I/F Block & System Control Registers --*/ +#define SB_DBREQM ((0x005f6840-0x005f6800)/4) +#define SB_BAVLWC ((0x005f6844-0x005f6800)/4) +#define SB_C2DPRYC ((0x005f6848-0x005f6800)/4) +#define SB_C2DMAXL ((0x005f684c-0x005f6800)/4) +#define SB_TFREM ((0x005f6880-0x005f6800)/4) +#define SB_LMMODE0 ((0x005f6884-0x005f6800)/4) +#define SB_LMMODE1 ((0x005f6888-0x005f6800)/4) +#define SB_FFST ((0x005f688c-0x005f6800)/4) +#define SB_SFRES ((0x005f6890-0x005f6800)/4) +#define SB_SBREV ((0x005f689c-0x005f6800)/4) +#define SB_RBSPLT ((0x005f68a0-0x005f6800)/4) +/*-------- Interrupt Control Registers ---------*/ +#define SB_ISTNRM ((0x005f6900-0x005f6800)/4) +#define SB_ISTEXT ((0x005f6904-0x005f6800)/4) +#define SB_ISTERR ((0x005f6908-0x005f6800)/4) +#define SB_IML2NRM ((0x005f6910-0x005f6800)/4) +#define SB_IML2EXT ((0x005f6914-0x005f6800)/4) +#define SB_IML2ERR ((0x005f6918-0x005f6800)/4) +#define SB_IML4NRM ((0x005f6920-0x005f6800)/4) +#define SB_IML4EXT ((0x005f6924-0x005f6800)/4) +#define SB_IML4ERR ((0x005f6928-0x005f6800)/4) +#define SB_IML6NRM ((0x005f6930-0x005f6800)/4) +#define SB_IML6EXT ((0x005f6934-0x005f6800)/4) +#define SB_IML6ERR ((0x005f6938-0x005f6800)/4) +#define SB_PDTNRM ((0x005f6940-0x005f6800)/4) +#define SB_PDTEXT ((0x005f6944-0x005f6800)/4) +#define SB_G2DTNRM ((0x005f6950-0x005f6800)/4) +#define SB_G2DTEXT ((0x005f6954-0x005f6800)/4) + + +/*-------- Maple-DMA Control Registers ---------*/ +#define SB_MDSTAR ((0x005f6c04-0x005f6c00)/4) +#define SB_MDTSEL ((0x005f6c10-0x005f6c00)/4) +#define SB_MDEN ((0x005f6c14-0x005f6c00)/4) +#define SB_MDST ((0x005f6c18-0x005f6c00)/4) +/*---- Maple I/F Block HW Control Registers ----*/ +#define SB_MSYS ((0x005f6c80-0x005f6c00)/4) +#define SB_MST ((0x005f6c84-0x005f6c00)/4) +#define SB_MSHTCL ((0x005f6c88-0x005f6c00)/4) +#define SB_MDAPRO ((0x005f6c8c-0x005f6c00)/4) +#define SB_MMSEL ((0x005f6ce8-0x005f6c00)/4) +/*-------- Maple-DMA Debug Registers -----------*/ +#define SB_MTXDAD ((0x005f6cf4-0x005f6c00)/4) +#define SB_MRXDAD ((0x005f6cf8-0x005f6c00)/4) +#define SB_MRXDBD ((0x005f6cfc-0x005f6c00)/4) + +/*--------- GD-DMA Control Registers -----------*/ +#define SB_GDSTAR ((0x005f7404-0x005f7400)/4) +#define SB_GDLEN ((0x005f7408-0x005f7400)/4) +#define SB_GDDIR ((0x005f740c-0x005f7400)/4) +#define SB_GDEN ((0x005f7414-0x005f7400)/4) +#define SB_GDST ((0x005f7418-0x005f7400)/4) +/*----- G1 I/F Block HW Control Registers ------*/ +#define SB_G1RRC ((0x005f7480-0x005f7400)/4) +#define SB_G1RWC ((0x005f7484-0x005f7400)/4) +#define SB_G1FRC ((0x005f7488-0x005f7400)/4) +#define SB_G1FWC ((0x005f748c-0x005f7400)/4) +#define SB_G1CRC ((0x005f7490-0x005f7400)/4) +#define SB_G1CWC ((0x005f7494-0x005f7400)/4) +#define SB_G1GDRC ((0x005f74a0-0x005f7400)/4) +#define SB_G1GDWC ((0x005f74a4-0x005f7400)/4) +#define SB_G1SYSM ((0x005f74b0-0x005f7400)/4) +#define SB_G1CRDYC ((0x005f74b4-0x005f7400)/4) +#define SB_GDAPRO ((0x005f74b8-0x005f7400)/4) + +/*-------- BIOS security Registers ---------*/ +#define SB_SECUR_EADR ((0x005f74e4-0x005f7400)/4) +#define SB_SECUR_STATE ((0x005f74ec-0x005f7400)/4) +/*---------- GD-DMA Debug Registers ------------*/ +#define SB_GDSTARD ((0x005f74f4-0x005f7400)/4) +#define SB_GDLEND ((0x005f74f8-0x005f7400)/4) + +/*-------- Wave DMA Control Registers ----------*/ +#define SB_ADSTAG ((0x005f7800-0x005f7800)/4) +#define SB_ADSTAR ((0x005f7804-0x005f7800)/4) +#define SB_ADLEN ((0x005f7808-0x005f7800)/4) +#define SB_ADDIR ((0x005f780c-0x005f7800)/4) +#define SB_ADTSEL ((0x005f7810-0x005f7800)/4) +#define SB_ADTRG SB_ADTSEL +#define SB_ADEN ((0x005f7814-0x005f7800)/4) +#define SB_ADST ((0x005f7818-0x005f7800)/4) +#define SB_ADSUSP ((0x005f781c-0x005f7800)/4) + +/*----- External 1 DMA Control Registers -------*/ +#define SB_E1STAG ((0x005f7820-0x005f7800)/4) +#define SB_E1STAR ((0x005f7824-0x005f7800)/4) +#define SB_E1LEN ((0x005f7828-0x005f7800)/4) +#define SB_E1DIR ((0x005f782c-0x005f7800)/4) +#define SB_E1TSEL ((0x005f7830-0x005f7800)/4) +#define SB_E1TRG SB_E1TSEL +#define SB_E1EN ((0x005f7834-0x005f7800)/4) +#define SB_E1ST ((0x005f7838-0x005f7800)/4) +#define SB_E1SUSP ((0x005f783c-0x005f7800)/4) + +/*----- External 2 DMA Control Registers -------*/ +#define SB_E2STAG ((0x005f7840-0x005f7800)/4) +#define SB_E2STAR ((0x005f7844-0x005f7800)/4) +#define SB_E2LEN ((0x005f7848-0x005f7800)/4) +#define SB_E2DIR ((0x005f784c-0x005f7800)/4) +#define SB_E2TSEL ((0x005f7850-0x005f7800)/4) +#define SB_E2TRG SB_E2TSEL +#define SB_E2EN ((0x005f7854-0x005f7800)/4) +#define SB_E2ST ((0x005f7858-0x005f7800)/4) +#define SB_E2SUSP ((0x005f785c-0x005f7800)/4) + +/*------- Debug DMA Control Registers ----------*/ +#define SB_DDSTAG ((0x005f7860-0x005f7800)/4) +#define SB_DDSTAR ((0x005f7864-0x005f7800)/4) +#define SB_DDLEN ((0x005f7868-0x005f7800)/4) +#define SB_DDDIR ((0x005f786c-0x005f7800)/4) +#define SB_DDTSEL ((0x005f7870-0x005f7800)/4) +#define SB_DDTRG SB_DDTSEL +#define SB_DDEN ((0x005f7874-0x005f7800)/4) +#define SB_DDST ((0x005f7878-0x005f7800)/4) +#define SB_DDSUSP ((0x005f787c-0x005f7800)/4) +/*----- G2 I/F Block HW Control Registers ------*/ +#define SB_G2ID ((0x005f7880-0x005f7800)/4) +#define SB_G2DSTO ((0x005f7890-0x005f7800)/4) +#define SB_G2TRTO ((0x005f7894-0x005f7800)/4) +#define SB_G2MDMTO ((0x005f7898-0x005f7800)/4) +#define SB_G2MDMW ((0x005f789c-0x005f7800)/4) +#define SB_G2APRO ((0x005f78bc-0x005f7800)/4) + +/*---------- G2 DMA Debug Registers ------------*/ +#define SB_ADSTAGD ((0x005f78c0-0x005f7800)/4) +#define SB_ADSTARD ((0x005f78c4-0x005f7800)/4) +#define SB_ADLEND ((0x005f78c8-0x005f7800)/4) +#define SB_E1STAGD ((0x005f78d0-0x005f7800)/4) +#define SB_E1STARD ((0x005f78d4-0x005f7800)/4) +#define SB_E1LEND ((0x005f78d8-0x005f7800)/4) +#define SB_E2STAGD ((0x005f78e0-0x005f7800)/4) +#define SB_E2STARD ((0x005f78e4-0x005f7800)/4) +#define SB_E2LEND ((0x005f78e8-0x005f7800)/4) +#define SB_DDSTAGD ((0x005f78f0-0x005f7800)/4) +#define SB_DDSTARD ((0x005f78f4-0x005f7800)/4) +#define SB_DDLEND ((0x005f78f8-0x005f7800)/4) + +#define RTC1 ((0x00710000-0x00710000)/4) +#define RTC2 ((0x00710004-0x00710000)/4) +#define RTC3 ((0x00710008-0x00710000)/4) + + +/* ------------- normal interrupts ------------- */ +#define IST_EOR_VIDEO 0x00000001 +#define IST_EOR_ISP 0x00000002 +#define IST_EOR_TSP 0x00000004 +#define IST_VBL_IN 0x00000008 +#define IST_VBL_OUT 0x00000010 +#define IST_HBL_IN 0x00000020 +#define IST_EOXFER_YUV 0x00000040 +#define IST_EOXFER_OPLST 0x00000080 +#define IST_EOXFER_OPMV 0x00000100 +#define IST_EOXFER_TRLST 0x00000200 +#define IST_EOXFER_TRMV 0x00000400 +#define IST_DMA_PVR 0x00000800 +#define IST_DMA_MAPLE 0x00001000 +#define IST_DMA_MAPLEVB 0x00002000 +#define IST_DMA_GDROM 0x00004000 +#define IST_DMA_AICA 0x00008000 +#define IST_DMA_EXT1 0x00010000 +#define IST_DMA_EXT2 0x00020000 +#define IST_DMA_DEV 0x00040000 +#define IST_DMA_CH2 0x00080000 +#define IST_DMA_SORT 0x00100000 +#define IST_EOXFER_PTLST 0x00200000 +#define IST_G1G2EXTSTAT 0x40000000 +#define IST_ERROR 0x80000000 +/* ------------ external interrupts ------------ */ +#define IST_EXT_EXTERNAL 0x00000008 +#define IST_EXT_MODEM 0x00000004 +#define IST_EXT_AICA 0x00000002 +#define IST_EXT_GDROM 0x00000001 +/* -------------- error interrupts ------------- */ +#define IST_ERR_ISP_LIMIT 0x00000004 +#define IST_ERR_PVRIF_ILL_ADDR 0x00000040 + +#endif // MAME_INCLUDES_DC_H diff --git a/src/mame/sega/dc_g2if.cpp b/src/mame/sega/dc_g2if.cpp new file mode 100644 index 00000000000..9929a2844fc --- /dev/null +++ b/src/mame/sega/dc_g2if.cpp @@ -0,0 +1,538 @@ +// license:LGPL-2.1+ +// copyright-holders:Angelo Salese +/************************************************************************************************** + + Sega Dreamcast G2 System Bus I/F + + TODO: + - Single-step instead of transfering in one go; + - Abort DMA if suspend mode is triggered; + - Time Out mechanism thru DS# & TR# signals; + - External pin enable in trigger select; + - Create a pure abstract interface shared with PVR-DMA I/F + (one channel, different max size, simpler tsel, no suspend, + different security code & area protection); + - DMA starts should send DDT requests and being notified back to use this i/f implementation + anyway. Exact purpose is unknown, maybe it's for granting use of the bus? + +**************************************************************************************************/ + +#include "emu.h" +#include "dc_g2if.h" + +#define LOG_WARN (1U << 1) +#define LOG_DMA (1U << 2) // log DMA starts with CPU triggers (.tsel bit 1 == 0) +#define LOG_HWTRIG (1U << 3) // log DMA starts with HW triggers (.tsel bit 1 == 1) +#define LOG_DMAEND (1U << 4) // log DMA event ends +#define LOG_ILLEGAL (1U << 5) // log illegal/malformed addresses + +#define VERBOSE (LOG_WARN | LOG_DMA | LOG_HWTRIG | LOG_DMAEND | LOG_ILLEGAL) +//#define LOG_OUTPUT_STREAM std::cout +#include "logmacro.h" + +#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) +#define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__) +#define LOGHWTRIG(...) LOGMASKED(LOG_HWTRIG, __VA_ARGS__) +#define LOGDMAEND(...) LOGMASKED(LOG_DMAEND, __VA_ARGS__) +#define LOGILLEGAL(...) LOGMASKED(LOG_ILLEGAL, __VA_ARGS__) + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + + +// device type definition +DEFINE_DEVICE_TYPE(DC_G2IF, dc_g2if_device, "dc_g2if", "Sega Dreamcast G2 I/F System Bus") + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + + +//------------------------------------------------- +// dc_g2if_device - constructor +//------------------------------------------------- + + +dc_g2if_device::dc_g2if_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, DC_G2IF, tag, owner, clock) + , m_host_space(*this, finder_base::DUMMY_TAG, -1) + , m_int_w(*this) + , m_error_ia_w(*this) + , m_error_ov_w(*this) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + + +void dc_g2if_device::device_start() +{ + for (int i = 0; i < 4; i++) + { + m_dma[i].end_timer = timer_alloc(FUNC(dc_g2if_device::dma_end_tick), this); + } + + m_int_w.resolve(); + m_error_ia_w.resolve(); + m_error_ov_w.resolve(); + + save_item(STRUCT_MEMBER(m_dma, g2_addr)); + save_item(STRUCT_MEMBER(m_dma, root_addr)); + save_item(STRUCT_MEMBER(m_dma, len)); + save_item(STRUCT_MEMBER(m_dma, size)); + save_item(STRUCT_MEMBER(m_dma, mode)); + save_item(STRUCT_MEMBER(m_dma, dir)); + save_item(STRUCT_MEMBER(m_dma, enable)); + save_item(STRUCT_MEMBER(m_dma, in_progress)); + save_item(STRUCT_MEMBER(m_dma, start)); + save_item(STRUCT_MEMBER(m_dma, tsel)); + save_item(STRUCT_MEMBER(m_dma, hw_trigger)); + save_item(NAME(m_g2apro.top_addr)); + save_item(NAME(m_g2apro.bottom_addr)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + + +void dc_g2if_device::device_reset() +{ + for (int ch = 0; ch < 4; ch ++) + { + m_dma[ch].g2_addr = 0; + m_dma[ch].root_addr = 0; + m_dma[ch].len = 0; + m_dma[ch].size = 0; + m_dma[ch].mode = false; + m_dma[ch].dir = false; + m_dma[ch].enable = false; + m_dma[ch].in_progress = false; + m_dma[ch].start = false; + m_dma[ch].tsel = 0; + m_dma[ch].hw_trigger = false; + m_dma[ch].end_timer->adjust(attotime::never); + } +} + +TIMER_CALLBACK_MEMBER(dc_g2if_device::dma_end_tick) +{ + u8 channel = (u8)(param >> 1); + bool dma_result = (param & 1); + m_dma[channel].in_progress = false; + m_dma[channel].start = false; + LOGDMAEND("DMA%d %s\n", channel, dma_result ? "normal end" : "overflow error"); + + if (dma_result) + m_int_w(channel, 1); + else + m_error_ov_w(channel, 1); +} + + +//************************************************************************** +// READ/WRITE HANDLERS +//************************************************************************** + +template void dc_g2if_device::channel_map(address_map &map) +{ + map(0x00, 0x03).rw(FUNC(dc_g2if_device::stag_r), FUNC(dc_g2if_device::stag_w)); + map(0x04, 0x07).rw(FUNC(dc_g2if_device::star_r), FUNC(dc_g2if_device::star_w)); + map(0x08, 0x0b).rw(FUNC(dc_g2if_device::len_r), FUNC(dc_g2if_device::len_w)); + map(0x0c, 0x0f).rw(FUNC(dc_g2if_device::dir_r), FUNC(dc_g2if_device::dir_w)); + map(0x10, 0x13).rw(FUNC(dc_g2if_device::tsel_r), FUNC(dc_g2if_device::tsel_w)); + map(0x14, 0x17).rw(FUNC(dc_g2if_device::en_r), FUNC(dc_g2if_device::en_w)); + map(0x18, 0x1b).rw(FUNC(dc_g2if_device::st_r), FUNC(dc_g2if_device::st_w)); + map(0x1c, 0x1f).rw(FUNC(dc_g2if_device::susp_r), FUNC(dc_g2if_device::susp_w)); +} + +// Instantiate channel maps +template void dc_g2if_device::channel_map<0>(address_map &map); +template void dc_g2if_device::channel_map<1>(address_map &map); +template void dc_g2if_device::channel_map<2>(address_map &map); +template void dc_g2if_device::channel_map<3>(address_map &map); + +void dc_g2if_device::amap(address_map &map) +{ + // 0x5f7800-ff + // SB_AD* + map(0x00, 0x1f).m(FUNC(dc_g2if_device::channel_map<0>)); + // SB_E1* + map(0x20, 0x3f).m(FUNC(dc_g2if_device::channel_map<1>)); + // SB_E2* + map(0x40, 0x5f).m(FUNC(dc_g2if_device::channel_map<2>)); + // SB_DD* + map(0x60, 0x7f).m(FUNC(dc_g2if_device::channel_map<3>)); + + map(0x80, 0x83).r(FUNC(dc_g2if_device::g2id_r)); + +// map(0x90, 0x93).rw SB_G2DSTO #DS timeout +// map(0x94, 0x97).rw SB_G2TRTO #TR timeout +// map(0x98, 0x9b).rw SB_G2MDMTO modem wait timeout +// map(0x9c, 0x9f).rw SB_G2MDMW modem wait time + + map(0xbc, 0xbf).w(FUNC(dc_g2if_device::g2apro_w)); + +// map(0xc0, 0xcb).r SB_AD*D live register reads (STAG, STAR, LEN) +// map(0xd0, 0xdb).r SB_E1*D live register reads +// map(0xe0, 0xeb).r SB_E2*D live register reads +// map(0xf0, 0xfb).r SB_DD*D live register reads +} + +template u32 dc_g2if_device::stag_r() +{ + return m_dma[Channel].g2_addr; +} + +// SB_**STAG +// G2 bus start address +template void dc_g2if_device::stag_w(offs_t offset, u32 data, u32 mem_mask) +{ + COMBINE_DATA(&m_dma[Channel].g2_addr); + + if (!g2_address_check(m_dma[Channel].g2_addr)) + { + LOGILLEGAL("%s: G2 illegal Address trap %08x (%08x)\n", machine().describe_context(), data, mem_mask); + m_error_ia_w(Channel, 1); + } +} + +template u32 dc_g2if_device::star_r() +{ + return m_dma[Channel].root_addr; +} + +// SB_**STAR +// root bus (SH4) start address +template void dc_g2if_device::star_w(offs_t offset, u32 data, u32 mem_mask) +{ + COMBINE_DATA(&m_dma[Channel].root_addr); + + if (!root_address_check(m_dma[Channel].root_addr)) + { + LOGILLEGAL("%s: root illegal Address trap %08x (%08x)\n", machine().describe_context(), data, mem_mask); + m_error_ia_w(Channel, 1); + } +} + +template u32 dc_g2if_device::len_r() +{ + return m_dma[Channel].len; +} + +/* + * SB_**LEN + * x--- ---- ---- ---- ---- ---- ---- ---- DMA transfer mode + * (0) Restart + * (1) End (enable register clears to '0') + * ---- ---x xxxx xxxx xxxx xxxx xxx- ---- DMA transfer length + * (all buses?) + */ +template void dc_g2if_device::len_w(offs_t offset, u32 data, u32 mem_mask) +{ + COMBINE_DATA(&m_dma[Channel].len); + // log an attempt if any of the reserved bits 30-25 and 4-0 are set + if (m_dma[Channel].len & 0x7fe0001f) + LOGWARN("%s: DMA%d LEN setup %08x (mask=%08x)!\n", machine().describe_context(), data, mem_mask); +// m_dma[Channel].size = m_dma[Channel].len & 0x7fffffff; + m_dma[Channel].size = m_dma[Channel].len & 0x001fffe0; + m_dma[Channel].mode = bool(BIT(m_dma[Channel].len, 31)); +} + +// TODO: following regs are supposedly single byte, but HW still accesses them as dword, is it a liability? + +template u32 dc_g2if_device::dir_r() +{ + return m_dma[Channel].dir; +} + +/* + * SB_**DIR (transfer direction) + * ---x (0) root -> G2 device RAM + * (1) root <- G2 device RAM + */ +template void dc_g2if_device::dir_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_7) + m_dma[Channel].dir = bool(BIT(data, 0)); +} + +template u32 dc_g2if_device::tsel_r() +{ + return m_dma[Channel].tsel; +} + +/* + * SB_**TSEL (trigger select) + * -x-- SUSPend enable + * --x- (0) CPU trigger (along with st_w '1'), + * (1) HW trigger (with external pin/irq mechanism) + * ---x External pin enable + */ +template void dc_g2if_device::tsel_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_7) + { + m_dma[Channel].tsel = data & 7; + m_dma[Channel].hw_trigger = bool(BIT(m_dma[Channel].tsel, 1)); + } +} + + +template u32 dc_g2if_device::en_r() +{ + return m_dma[Channel].enable; +} + +/* + * SB_**EN + * ---x DMA enable + * (0) mask + * (1) enabled + * Note: DMA transfer is aborted if this is written with a 0. + */ +template void dc_g2if_device::en_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_7) + { + m_dma[Channel].enable = bool(BIT(data, 0)); + // TODO: suppresses an in-progress DMA if this is disabled + } +} + +template u32 dc_g2if_device::st_r() +{ + return m_dma[Channel].in_progress & 1; +} + +/* + * SB_**ST + * ---x DMA start/status + * (r) (0) DMA isn't running (1) DMA is in-progress + * (w) (1) starts a DMA (if hw_trigger is '0') + */ +template void dc_g2if_device::st_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_7) + { + if (m_dma[Channel].start == true) + { + LOGWARN("%s: DMA%d attempt to start an in-flight\n", machine().describe_context(), Channel); + return; + } + + m_dma[Channel].start = bool(BIT(data, 0)); + + if (m_dma[Channel].enable && m_dma[Channel].start && m_dma[Channel].hw_trigger == false) + { + LOGDMA("%s: DMA%d root=%08x g2=%08x dir=G2%sroot (%d)\n size=%08x (len=%08x) mode=DMA %s\n", + machine().describe_context(), Channel, + m_dma[Channel].root_addr, m_dma[Channel].g2_addr, m_dma[Channel].dir ? "->" : "<-", + m_dma[Channel].dir, + m_dma[Channel].size, m_dma[Channel].len, m_dma[Channel].mode ? "end" : "restart" + ); + dma_execute(Channel); + } + } +} + +// --x- ---- (r/o) DMA request input state (from external bus?) +// ---x ---- (r/o) DMA suspend/stop status (active low) +// ---- ---x (w) DMA suspend request +template u32 dc_g2if_device::susp_r() +{ + return (m_dma[Channel].in_progress == false) << 4; +} + +template void dc_g2if_device::susp_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (ACCESSING_BITS_0_7) + { + // TODO: unemulated suspend mode + if (data & 1) + { + LOGWARN("%s: DMA%d suspend write %08x %08x\n", + machine().describe_context(), + Channel, data, mem_mask + ); + // ... + } + } +} + +//************************************************************************** +// Misc. registers +//************************************************************************** + +// SB_G2ID +// 0001 ---- Holly v1.0 +// ---- 0011 G2 version +u32 dc_g2if_device::g2id_r() +{ + LOGWARN("%s: read ID\n", machine().describe_context()); + return 0x12; +} + +// SB_G2APRO +// xxxx xxxx xxxx xxxx ---- ---- ---- ---- Unlock register (must be == 0x4659) +// ---- ---- ---- ---- -xxx xxxx ---- ---- Top range (start address) +// ---- ---- ---- ---- ---- ---- -xxx xxxx Bottom range (end address) +// all channels follows this ruleset +void dc_g2if_device::g2apro_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (mem_mask != 0xffffffff) + { + LOGWARN("%s: g2apro_w attempt to write %08x with a non-dword (mem_mask=%08x)\n", machine().describe_context(), data, mem_mask); + return; + } + const u16 security_code = data >> 16; + + if (security_code != 0x4659) + { + LOGWARN("%s: g2apro_w attempt to write %08x without satisfying security code condition\n", machine().describe_context(), data); + return; + } + + const u16 top_range = (data & 0x7f00) >> 8; + const u16 bottom_range = (data & 0x7f); + + m_g2apro.top_addr = (top_range << 20) | 0x08000000; + m_g2apro.bottom_addr = (bottom_range << 20) | 0x080fffff; + + LOGILLEGAL("%s: g2apro_w set top=%08x bottom=%08x (%08x)\n", + machine().describe_context(), + m_g2apro.top_addr, m_g2apro.bottom_addr, data + ); +} + +//************************************************************************** +// DMA implementation +//************************************************************************** + +inline bool dc_g2if_device::root_address_check(u32 offset) +{ + const u8 area = (offset >> 26) & 7; + // root iA is generated by accessing outside System RAM or texture/framebuffer RAM + return area == 1 || area == 3; +} + +inline bool dc_g2if_device::g2_address_check(u32 offset) +{ + const u8 area = (offset >> 26) & 7; + // g2 iA is generated by accessing outside: + // - area == 0 for AD/E1/E2 buses + // - area == 5 for DD + return area == 0 || area == 5; +} + +inline bool dc_g2if_device::root_overflow_check(u32 offset, u8 channel) +{ + bool result = offset >= m_g2apro.top_addr && offset <= m_g2apro.bottom_addr; + if (result == false) + LOGILLEGAL("DMA%d overflow abort root=%08x\n", channel, offset); + + return result; +} + +void dc_g2if_device::dma_execute(u8 channel) +{ + u32 src, dst, index, transfer_size; + dst = m_dma[channel].g2_addr; + src = m_dma[channel].root_addr; + + // Punt if attempts to go beyond the allocated buses + // TODO: should require two extra cycles for fetching addresses first + if (!root_address_check(src) || !g2_address_check(dst)) + { + LOGILLEGAL("%s: DMA%d illegal address attempt root=%08x g2=%08x\n", + machine().describe_context(), + channel, src, dst + ); + m_dma[channel].in_progress = false; + m_dma[channel].start = false; + m_dma[channel].enable = false; + m_error_ia_w(channel, 1); + return; + } + + index = 0; + + transfer_size = m_dma[channel].size; + /* 0 rounding size = 32 Mbytes */ + if (transfer_size == 0) { transfer_size = 0x200000; } + + if (m_dma[channel].dir == 1) + std::swap(src, dst); + + // notify that a DMA is in progress + // ofc this should rather transfer one word at a time, + // we currently don't do that for performance reasons ... + m_dma[channel].in_progress = true; + + bool dma_result = true; + + for (; index < transfer_size; index += 2) + { + // assert that root address is inside the g2apro range + if (!root_overflow_check(m_dma[channel].dir ? dst : src, channel)) + { + dma_result = false; + break; + } + // TODO: raise debug signals if SB_G2DSTO / SB_G2TRTO aren't respected + // Shouldn't matter for AICA RAM, + // it does in loopchk g2 test 0304 when it tries to write to + // expansion bus (where nothing lies on stock DC) + m_host_space->write_word(dst, m_host_space->read_word(src)); + src += 2; + dst += 2; + } + + // update the params + // Note: if you trigger an instant DMA IRQ trigger, sfz3ugd doesn't play any BGM. + // G2 bus is 16 bits @ 25 MHz according to Fig. 2-1 + // TODO: reported limit output for AICA DMA is set at 11.3MB/s while the others at 24.0/26.0 + // bus contention ftw ... + const attotime dma_time = attotime::from_ticks(index / 2, clock()); + + m_dma[channel].g2_addr = dst; + m_dma[channel].root_addr = src; + // TODO: how len copes with updates? + m_dma[channel].len = 0; + // clear mask flag if the DMA transfer mode is in End mode + // (Restart mode leaves this set to true) + if (m_dma[channel].mode == true) + m_dma[channel].enable = false; + + m_dma[channel].end_timer->adjust(dma_time, (channel << 1) | (dma_result ? 1 : 0)); +} + +/* + * normal_ist: SB_G2DTNRM & SB_ISTNRM + * (triggers a DMA if selected irq in former gets triggered) + * ext_ist: SB_G2DTEXT & SB_ISTEXT + * (triggers a DMA if external pin is triggered) + */ +void dc_g2if_device::hw_irq_trigger_hs(u32 normal_ist, u32 ext_ist) +{ + // TODO: is latter requiring .tsel bit 0 == 1? + bool hw_ist_enable = normal_ist || ext_ist; + + if (hw_ist_enable == false) + return; + + for (int ch = 0; ch < 4; ch++) + { + if (m_dma[ch].hw_trigger & m_dma[ch].enable) + { + LOGHWTRIG("HW trigger channel %d (ISTNRM=%08x ISTEXT=%08x)\n", ch, normal_ist, ext_ist); + dma_execute(ch); + } + } +} diff --git a/src/mame/sega/dc_g2if.h b/src/mame/sega/dc_g2if.h new file mode 100644 index 00000000000..c598307b441 --- /dev/null +++ b/src/mame/sega/dc_g2if.h @@ -0,0 +1,106 @@ +// license:LGPL-2.1+ +// copyright-holders:Angelo Salese +/************************************************************************************************** + + Sega Dreamcast G2 System Bus I/F + +**************************************************************************************************/ + +#ifndef MAME_MACHINE_DC_G2IF_H +#define MAME_MACHINE_DC_G2IF_H + +#pragma once + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class dc_g2if_device : public device_t +{ +public: + // construction/destruction + dc_g2if_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template void set_host_space(T &&tag, int index) { m_host_space.set_tag(std::forward(tag), index); } + auto int_cb() { return m_int_w.bind(); } + auto error_ia_cb() { return m_error_ia_w.bind(); } + auto error_ov_cb() { return m_error_ov_w.bind(); } + + void amap(address_map &map); + + void hw_irq_trigger_hs(u32 normal_ist, u32 ext_ist); + +protected: + // device-level overrides + //virtual void device_validity_check(validity_checker &valid) const override; + //virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + + TIMER_CALLBACK_MEMBER(dma_end_tick); + +private: + required_address_space m_host_space; + devcb_write8 m_int_w; + devcb_write8 m_error_ia_w; + devcb_write8 m_error_ov_w; + + struct { + u32 g2_addr; + u32 root_addr; + u32 len; + u32 size; + bool mode; + bool dir; + bool enable; + bool in_progress; + bool start; + u8 tsel; + bool hw_trigger; + emu_timer *end_timer; + } m_dma[4]; + + struct { + u32 bottom_addr; + u32 top_addr; + } m_g2apro; + + template void channel_map(address_map &map); + + template u32 stag_r(); + template void stag_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + template u32 star_r(); + template void star_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + template u32 len_r(); + template void len_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + template u32 dir_r(); + template void dir_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + template u32 tsel_r(); + template void tsel_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + template u32 en_r(); + template void en_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + template u32 st_r(); + template void st_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + template u32 susp_r(); + template void susp_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + void dma_execute(u8 channel); + bool root_address_check(u32 offset); + bool g2_address_check(u32 offset); + bool root_overflow_check(u32 offset, u8 channel); + + u32 g2id_r(); + void g2apro_w(offs_t offset, u32 data, u32 mem_mask = ~0); +}; + + +// device type definition +DECLARE_DEVICE_TYPE(DC_G2IF, dc_g2if_device) + +#endif // MAME_MACHINE_DC_G2IF_H diff --git a/src/mame/sega/dccons.cpp b/src/mame/sega/dccons.cpp new file mode 100644 index 00000000000..3535c08dd09 --- /dev/null +++ b/src/mame/sega/dccons.cpp @@ -0,0 +1,667 @@ +// 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 "dccons.h" + +#include "dc-ctrl.h" + +#include "bus/ata/gdrom.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 "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 ) diff --git a/src/mame/sega/dccons.h b/src/mame/sega/dccons.h new file mode 100644 index 00000000000..1bad460cd38 --- /dev/null +++ b/src/mame/sega/dccons.h @@ -0,0 +1,60 @@ +// license:LGPL-2.1+ +// copyright-holders:Angelo Salese, R. Belmont +#ifndef MAME_SEGACONS_DCCONS_H +#define MAME_SEGACONS_DCCONS_H + +#pragma once + +#include "dc.h" + +#include "bus/ata/ataintf.h" +#include "imagedev/chd_cd.h" +#include "machine/intelfsh.h" + +class dc_cons_state : public dc_state +{ +public: + dc_cons_state(const machine_config &mconfig, device_type type, const char *tag) + : dc_state(mconfig, type, tag) + , m_ata(*this, "ata") + , m_dcflash(*this, "dcflash") + , atapi_xfercomplete(0) + { } + + required_device m_ata; + required_device m_dcflash; + + void init_dc(); + void init_tream(); + + uint64_t dc_pdtra_r(); + void dc_pdtra_w(uint64_t data); + DECLARE_WRITE_LINE_MEMBER(aica_irq); + DECLARE_WRITE_LINE_MEMBER(sh4_aica_irq); + DECLARE_WRITE_LINE_MEMBER(ata_interrupt); + + TIMER_CALLBACK_MEMBER( atapi_xfer_end ); + + void dreamcast_atapi_init(); + uint32_t dc_mess_g1_ctrl_r(offs_t offset); + void dc_mess_g1_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint8_t dc_flash_r(offs_t offset); + void dc_flash_w(offs_t offset, uint8_t data); + + static void gdrom_config(device_t *device); + void dc_base(machine_config &config); + void dc(machine_config &config); + void dc_fish(machine_config &config); + void aica_map(address_map &map); + void dc_audio_map(address_map &map); + void dc_map(address_map &map); + void dc_port(address_map &map); +private: + uint32_t g1bus_regs[0x100/4]{}; // DC-only + + uint64_t PDTRA = 0U, PCTRA = 0U; + emu_timer *atapi_timer = nullptr; + int atapi_xferlen = 0, atapi_xferbase = 0, atapi_xfercomplete; +}; + +#endif // MAME_SEGACONS_DCCONS_H diff --git a/src/mame/sega/dccons_m.cpp b/src/mame/sega/dccons_m.cpp new file mode 100644 index 00000000000..a69834a46e3 --- /dev/null +++ b/src/mame/sega/dccons_m.cpp @@ -0,0 +1,225 @@ +// license:LGPL-2.1+ +// copyright-holders:Angelo Salese, R. Belmont +/* + + dc.c - Sega Dreamcast hardware + + DC home console hardware overrides (GD-ROM drive etc) + + TODO: + - Convert to actual G1 I/F; + - gdrom_alt_status is identical to normal status except that "but it does not clear DMA status information when it is accessed"; + - Verify unimplemented behaviours via tests; + + Old notes, consultation only: + c230048 - 5 is written, want 6 + c0d9d9e - where bad happens, from routine @ c0da260 + + c0d9d8e - R0 on return is the value to put in + + cfffee0 - stack location when bad happens + +*/ + +#include "emu.h" +#include "dccons.h" + +#include "cdrom.h" +//#include "debugger.h" +#include "cpu/sh/sh4.h" +#include "sound/aica.h" + +// TODO: fine grain this value +#define ATAPI_CYCLES_PER_SECTOR (5000) + +#define LOG_WARN (1U << 1) +#define LOG_XFER (1U << 2) // log ATAPI transfers + +#define VERBOSE (LOG_WARN) +//#define LOG_OUTPUT_STREAM std::cout +#include "logmacro.h" + +#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) +#define LOGXFER(...) LOGMASKED(LOG_XFER, __VA_ARGS__) + +WRITE_LINE_MEMBER(dc_cons_state::ata_interrupt) +{ + if (state) + dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_GDROM; + else + dc_sysctrl_regs[SB_ISTEXT] &= ~IST_EXT_GDROM; + + dc_update_interrupt_status(); +} + +TIMER_CALLBACK_MEMBER(dc_cons_state::atapi_xfer_end ) +{ + uint8_t sector_buffer[ 4096 ]; + + atapi_timer->adjust(attotime::never); + + LOGXFER("atapi_xfer_end atapi_xferlen = %d\n", atapi_xferlen ); + + m_ata->write_dmack(1); + atapi_xfercomplete = 0; + + // TODO: dispatch transfers one step at a time instead of the full block + while (atapi_xferlen > 0 ) + { + struct sh4_ddt_dma ddtdata; + + // get a sector from the SCSI device + for (int i = 0; i < 2048 / 2; i++) + { + int d = m_ata->read_dma(); + sector_buffer[ i*2 ] = d & 0xff; + sector_buffer[ (i*2)+1 ] = d >> 8; + } + + atapi_xferlen -= 2048; + atapi_xfercomplete += 2048; + + // perform the DMA + ddtdata.destination = atapi_xferbase; // destination address + ddtdata.length = 2048 / 4; + ddtdata.size = 4; + ddtdata.buffer = sector_buffer; + ddtdata.direction = 1; // 0 source to buffer, 1 buffer to destination + ddtdata.channel = 0; + ddtdata.mode = -1; // copy from/to buffer + LOGXFER("G1 I/F ATAPI: DMA one sector to %x, %x remaining\n", + atapi_xferbase, atapi_xferlen + ); + m_maincpu->sh4_dma_ddt(&ddtdata); + + atapi_xferbase += 2048; + } + + m_ata->write_dmack(0); + + g1bus_regs[SB_GDST] = 0; + dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_GDROM; + dc_update_interrupt_status(); +} + +void dc_cons_state::dreamcast_atapi_init() +{ + atapi_timer = timer_alloc(FUNC(dc_cons_state::atapi_xfer_end), this); + atapi_timer->adjust(attotime::never); + save_item(NAME(atapi_xferlen)); + save_item(NAME(atapi_xferbase)); +} + +/* + + GDROM regsters: + + 5f7018: alternate status/device control + 5f7080: data + 5f7084: error/features + 5f7088: interrupt reason/sector count + 5f708c: sector number + 5f7090: byte control low + 5f7094: byte control high + 5f7098: drive select + 5f709c: status/command + +c002910 - ATAPI packet writes +c002796 - aux status read after that +c000776 - DMA triggered to c008000 + +*/ + +uint32_t dc_cons_state::dc_mess_g1_ctrl_r(offs_t offset) +{ + switch(offset) + { + case SB_GDSTARD: + // TODO: one of the Hello Kitty (identify which) reads there + logerror("G1CTRL: GDSTARD %08x\n", atapi_xferbase); + //machine().debug_break(); + return atapi_xferbase; + case SB_GDST: + break; + case SB_GDLEND: + //machine().debug_break(); + return atapi_xfercomplete; + case SB_SECUR_EADR: // always read 0xFF on hardware + return 0x000000ff; + case SB_SECUR_STATE: // state of BIOS checksum security system (R/O): + // 3 - check passed OK, G1 ATA (5F70xx) registers area accessible + // 2 - check failed, G1 ATA area blocked (read FFFFFFFFh) + // 0 - check in progress, BIOS data summed, G1 ATA area blocked (read FFFFFFFFh) + return 3; + default: + LOGWARN("G1CTRL: Unmapped read %08x\n", 0x5f7400 + offset * 4); + //machine().debug_break(); + break; + } + return g1bus_regs[offset]; +} + +void dc_cons_state::dc_mess_g1_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + g1bus_regs[offset] = data; // 5f7400+reg*4=dat +// osd_printf_verbose("G1CTRL: [%08x=%x] write %x to %x, mask %x\n", 0x5f7400+reg*4, dat, data, offset, mem_mask); + switch (offset) + { + case SB_GDST: + if (data & 1 && g1bus_regs[SB_GDEN] == 1) // 0 -> 1 + { + if (g1bus_regs[SB_GDDIR] == 0) + { + // TODO: write to GD-ROM, shouldn't happen unless "special" condition occurs + // (implies a debug/development device?) + LOGWARN("%s: G1 I/F illegal direction transfer\n", machine().describe_context()); + return; + } + + atapi_xferbase = g1bus_regs[SB_GDSTAR]; + //atapi_timer->adjust(m_maincpu->cycles_to_attotime((ATAPI_CYCLES_PER_SECTOR * (atapi_xferlen/2048)))); + /* 12x * 75 Hz = 0,00(1) secs per sector */ + /* TODO: make DMA to be single step */ + atapi_timer->adjust(attotime::from_usec(1111*atapi_xferlen/2048)); +// atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80; + } + break; + + case SB_GDLEN: + atapi_xferlen = data; + break; + +/* + The following register is involved in BIOS checksum protection system. + current understanding of its functioning based on several hardware tests: + + after power on security system is in state 0 (check in progress): + - access to G1 ATA register area (5F70XX) is blocked, ie GD-ROM in Dreamcast or cartridge/DIMM in arcade systems is not accessible; + - *any* data readed via G1 data bus (i.e. BIOS) is summed internally by chipset; + - write to SB_SECUR_EADR register set last address of checksummed area; + + then read address will match SB_SECUR_EADR - calculated summ compared with some hardcoded value + if values match - security system becomes in state 3 (check OK): + - G1 ATA registers area unlocked; + - can be switched back to state 0 by write to SB_SECUR_EADR register, Dreamcast BIOS write 42FEh before jump into Mil-CD executables + + if values doesn't match - security system switch to state 2 (check fail): + - G1 ATA locked + - can be switched to state 0 by write to SB_SECUR_EADR register, however passing valid data block through security system set it back to state 2 + - the only exit from this state - power off/on or reset; + + current state can be read from SB_SECUR_STATE register + actual checksum algorithm is unknown, but its supposed to be simple and weak, + known few modded BIOSes which succesfully passes this CRC check, because of good luck + + all described above works the same way in all HOLLY/CLX2-based systems - Dreamcast, Naomi 1/2, Atomiswave, SystemSP +*/ + case SB_SECUR_EADR: + if (data==0 || data==0x001fffff || data==0x42fe) + { + // atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80; + logerror("%s: Unlocking GD-ROM %x\n", machine().describe_context(), data); + } + break; + } +} diff --git a/src/mame/sega/maple-dc.cpp b/src/mame/sega/maple-dc.cpp new file mode 100644 index 00000000000..47e44386efd --- /dev/null +++ b/src/mame/sega/maple-dc.cpp @@ -0,0 +1,302 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +#include "emu.h" +#include "maple-dc.h" +#include "mie.h" + +DEFINE_DEVICE_TYPE(MAPLE_DC, maple_dc_device, "maple_dc", "Dreamcast Maple Bus") + +void maple_dc_device::amap(address_map &map) +{ + map(0x04, 0x07).rw(FUNC(maple_dc_device::sb_mdstar_r), FUNC(maple_dc_device::sb_mdstar_w)); + map(0x10, 0x13).rw(FUNC(maple_dc_device::sb_mdtsel_r), FUNC(maple_dc_device::sb_mdtsel_w)); + map(0x14, 0x17).rw(FUNC(maple_dc_device::sb_mden_r), FUNC(maple_dc_device::sb_mden_w)); + map(0x18, 0x1b).rw(FUNC(maple_dc_device::sb_mdst_r), FUNC(maple_dc_device::sb_mdst_w)); + map(0x80, 0x83).rw(FUNC(maple_dc_device::sb_msys_r), FUNC(maple_dc_device::sb_msys_w)); + map(0x8c, 0x8f).w(FUNC(maple_dc_device::sb_mdapro_w)); +} + +maple_dc_device::maple_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, MAPLE_DC, tag, owner, clock), + cpu(*this, finder_base::DUMMY_TAG), + irq_cb(*this) +{ + // Do not move that in device_start or there will be a race + // condition with the maple devices call to register_port. + memset(devices, 0, sizeof(devices)); +} + +void maple_dc_device::register_port(int port, maple_device *device) +{ + if(devices[port]) + fatalerror("maple_dc_device: duplicate registration on port %d\n", port); + + devices[port] = device; +} + +void maple_dc_device::device_start() +{ + logerror("maple_dc_device started\n"); + timer = timer_alloc(FUNC(maple_dc_device::dma_timer_tick), this); + irq_cb.resolve_safe(); + + mdstar = 0; + + save_item(NAME(mdstar)); + save_item(NAME(mden)); + save_item(NAME(mdst)); + save_item(NAME(msys)); + save_item(NAME(mdtsel)); + save_item(NAME(dma_state)); + save_item(NAME(dma_adr)); + save_item(NAME(dma_port)); + save_item(NAME(dma_dest)); + save_item(NAME(dma_endflag)); +} + +void maple_dc_device::device_reset() +{ + mden = 0; + mdst = 0; + msys = 0; + mdtsel = 0; + dma_state = DMA_IDLE; + dma_adr = 0; + dma_port = 0; + dma_dest = 0; + dma_endflag = false; +} + +TIMER_CALLBACK_MEMBER(maple_dc_device::dma_timer_tick) +{ + switch(dma_state) { + case DMA_WAIT_REPLY: + dma_state = DMA_TIMEOUT; + dma_step(); + break; + + case DMA_WAIT_NOP: + dma_state = DMA_SEND; + dma_step(); + break; + + case DMA_DONE: + dma_state = DMA_IDLE; + mdst = 0; + irq_cb(DMA_MAPLE_IRQ); + break; + + default: + logerror("MAPLE: Unexpected timer callback trigger\n"); + break; + } +} + +void maple_dc_device::dma_step() +{ + for(;;) { + switch(dma_state) { + case DMA_SEND: { + sh4_ddt_dma ddtdata; + uint32_t header[2]; + uint32_t data[512]; + ddtdata.source = dma_adr; // source address + ddtdata.length = 2; // words to transfer + ddtdata.size = 4; // bytes per word + ddtdata.buffer = header; // destination buffer + ddtdata.direction = 0; // 0 source to buffer, 1 buffer to source + ddtdata.channel = 0; + ddtdata.mode = -1; // copy from/to buffer + cpu->sh4_dma_ddt(&ddtdata); + dma_adr += 8; + + dma_endflag = header[0] & 0x80000000; + dma_port = (header[0] >> 16) & 3; + uint32_t pattern = (header[0] >> 8) & 7; + uint32_t length = (header[0] & 255) + 1; + dma_dest = header[1]; + + ddtdata.source = dma_adr; // source address + ddtdata.length = length; // words to transfer + ddtdata.size = 4; // bytes per word + ddtdata.buffer = data; // destination buffer + ddtdata.direction = 0; // 0 source to buffer, 1 buffer to source + ddtdata.channel = 0; + ddtdata.mode = -1; // copy from/to buffer + cpu->sh4_dma_ddt(&ddtdata); + dma_adr += length*4; + + switch(pattern) { + case 0: // start + if(devices[dma_port]) + devices[dma_port]->maple_w(data, length); + else { + // Avoid spending time on that specific timeout + dma_state = DMA_TIMEOUT; + break; + } + dma_state = DMA_WAIT_REPLY; + + // the MIE seems too slow for the correct timeout + // it's rather strange though + // timer->adjust(attotime::from_nsec(40000 + 20*(msys>>16))); // The 40us represent the sending and reception time + timer->adjust(attotime::from_msec(5)); + break; + case 2: // sdckb occupy permission (light gun protocol) + logerror("MAPLE: sdckb occupy permission\n"); + break; + case 3: // reset + if(devices[dma_port]) + devices[dma_port]->maple_reset(); + break; + case 4: // sdckb occupy cancel + logerror("MAPLE: sdckb occupy cancel\n"); + break; + case 7: // nop + logerror("MAPLE: nop\n"); + dma_state = DMA_WAIT_NOP; + break; + } + if(dma_state == DMA_SEND && dma_endflag) + dma_state = DMA_DONE; + break; + } + + case DMA_WAIT_REPLY: + return; + + case DMA_WAIT_NOP: + return; + + case DMA_TIMEOUT: { + sh4_ddt_dma ddtdata; + uint32_t data = 0xffffffff; + ddtdata.destination = dma_dest; // destination address + ddtdata.length = 1; // words to transfer + ddtdata.size = 4; // bytes per word + ddtdata.buffer = &data; // destination buffer + ddtdata.direction = 1; // 0 source to buffer, 1 buffer to source + ddtdata.channel = 0; + ddtdata.mode = -1; // copy from/to buffer + cpu->sh4_dma_ddt(&ddtdata); + dma_state = dma_endflag ? DMA_DONE : DMA_SEND; + break; + } + + case DMA_GOT_REPLY: { + timer->adjust(attotime::never); + + sh4_ddt_dma ddtdata; + uint32_t data[512]; + uint32_t length = 0; + bool partial = false; + if(devices[dma_port]) + devices[dma_port]->maple_r(data, length, partial); + else + fatalerror("MAPLE: reading from unconnected device on port %d\n", dma_port); + + if(length) { + ddtdata.destination = dma_dest; // destination address + ddtdata.length = length; // words to transfer + ddtdata.size = 4; // bytes per word + ddtdata.buffer = data; // destination buffer + ddtdata.direction = 1; // 0 source to buffer, 1 buffer to source + ddtdata.channel = 0; + ddtdata.mode = -1; // copy from/to buffer + cpu->sh4_dma_ddt(&ddtdata); + dma_dest += length*4; + } + + if(partial) + dma_state = DMA_WAIT_REPLY; + else + dma_state = dma_endflag ? DMA_DONE : DMA_SEND; + break; + } + case DMA_DONE: + timer->adjust(attotime::from_usec(200)); + return; + } + } +} + +void maple_dc_device::end_of_reply() +{ + if(dma_state == DMA_WAIT_REPLY) { + dma_state = DMA_GOT_REPLY; + dma_step(); + } else + logerror("MAPLE: Unexpected end of reply\n"); +} + +void maple_dc_device::maple_hw_trigger() +{ + if(mdtsel & 1) // HW trigger + { + dma_adr = mdstar; + dma_state = DMA_SEND; + dma_step(); + } +} + +uint32_t maple_dc_device::sb_mdstar_r() +{ + return mdstar; +} + +void maple_dc_device::sb_mdstar_w(uint32_t data) +{ + mdstar = data & ~31; +} + +uint32_t maple_dc_device::sb_mden_r() +{ + return mden; +} + +void maple_dc_device::sb_mden_w(uint32_t data) +{ + mden = data & 1; +} + +uint32_t maple_dc_device::sb_mdtsel_r() +{ + return mdtsel; +} + +void maple_dc_device::sb_mdtsel_w(uint32_t data) +{ + mdtsel = data & 1; +} + +uint32_t maple_dc_device::sb_mdst_r() +{ + return dma_state != DMA_IDLE ? 1 : 0; +} + +void maple_dc_device::sb_mdst_w(uint32_t data) +{ + uint32_t old = mdst; + mdst = data & 1; + + if(!old && data && (mden & 1) && mdtsel == 0) { + dma_adr = mdstar; + dma_state = DMA_SEND; + dma_step(); + } +} + +uint32_t maple_dc_device::sb_msys_r() +{ + return msys; +} + +void maple_dc_device::sb_msys_w(uint32_t data) +{ + msys = data; +} + +void maple_dc_device::sb_mdapro_w(uint32_t data) +{ +} diff --git a/src/mame/sega/maple-dc.h b/src/mame/sega/maple-dc.h new file mode 100644 index 00000000000..45d2efbbec1 --- /dev/null +++ b/src/mame/sega/maple-dc.h @@ -0,0 +1,84 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +#ifndef MAME_MACHINE_MAPLE_DC_H +#define MAME_MACHINE_MAPLE_DC_H + +#pragma once + +#include "cpu/sh/sh4.h" + +class maple_device; + +class maple_dc_device : public device_t +{ +public: + enum { + DMA_MAPLE_IRQ + }; + + template + maple_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag) + : maple_dc_device(mconfig, tag, owner, clock) + { + set_maincpu_tag(std::forward(cpu_tag)); + } + + maple_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template void set_maincpu_tag(T &&cpu_tag) { cpu.set_tag(std::forward(cpu_tag)); } + auto irq_callback() { return irq_cb.bind(); } + + uint32_t sb_mdstar_r(); // 5f6c04 + void sb_mdstar_w(uint32_t data); + uint32_t sb_mdtsel_r(); // 5f6c10 + void sb_mdtsel_w(uint32_t data); + uint32_t sb_mden_r(); // 5f6c14 + void sb_mden_w(uint32_t data); + uint32_t sb_mdst_r(); // 5f6c18 + void sb_mdst_w(uint32_t data); + uint32_t sb_msys_r(); // 5f6c80 + void sb_msys_w(uint32_t data); + void sb_mdapro_w(uint32_t data); // 5f6c8c + + void amap(address_map &map); + + void end_of_reply(); + void register_port(int port, maple_device *device); + void maple_hw_trigger(); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + TIMER_CALLBACK_MEMBER(dma_timer_tick); + +private: + enum { + DMA_IDLE, + DMA_DONE, + DMA_SEND, + DMA_WAIT_NOP, + DMA_WAIT_RESET, + DMA_WAIT_REPLY, + DMA_GOT_REPLY, + DMA_TIMEOUT + }; + + maple_device *devices[4]; + + required_device cpu; + emu_timer *timer; + + uint32_t mdstar, mden, mdst, msys; + uint32_t mdtsel; + + uint32_t dma_state, dma_adr, dma_port, dma_dest; + bool dma_endflag; + devcb_write8 irq_cb; + + void dma_step(); +}; + +DECLARE_DEVICE_TYPE(MAPLE_DC, maple_dc_device) + +#endif // MAME_MACHINE_MAPLE_DC_H diff --git a/src/mame/sega/mapledev.cpp b/src/mame/sega/mapledev.cpp new file mode 100644 index 00000000000..ee4340ee56f --- /dev/null +++ b/src/mame/sega/mapledev.cpp @@ -0,0 +1,63 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +#include "emu.h" +#include "mapledev.h" + +maple_device::maple_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) +, host(*this, finder_base::DUMMY_TAG) +{ + host_port = 0; +} + + +void maple_device::device_start() +{ + host->register_port(host_port, this); + + timer = timer_alloc(FUNC(maple_device::reply_ready), this); + + save_item(NAME(reply_buffer)); + save_item(NAME(reply_size)); + save_item(NAME(reply_partial)); +} + +void maple_device::maple_reset() +{ + device_reset(); +} + +void maple_device::reply_ready_with_delay() +{ + // Arbitrary delay to avoid instant replies + // Makes the maple dma code easier to write + // There's usually something z80 in there after all, so it even makes sense + timer->adjust(attotime::from_usec(100)); +} + +TIMER_CALLBACK_MEMBER(maple_device::reply_ready) +{ + host->end_of_reply(); +} + +void maple_device::copy_with_spaces(uint8_t *dest, const char *source, int len) +{ + int i; + for(i=0; i host; + int host_port = 0; + +private: + emu_timer *timer = nullptr; +}; + +#endif // MAME_MACHINE_MAPLEDEV_H diff --git a/src/mame/sega/mdconsole.cpp b/src/mame/sega/mdconsole.cpp new file mode 100644 index 00000000000..0021f421f11 --- /dev/null +++ b/src/mame/sega/mdconsole.cpp @@ -0,0 +1,1205 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#include "emu.h" +#include "mdconsole.h" + +#include "bus/generic/carts.h" +#include "bus/generic/slot.h" +#include "imagedev/chd_cd.h" +#include "sound/sn76496.h" + +#include "softlist.h" + +#include "formats/imageutl.h" + + +/************************************* + * + * Input handlers + * + *************************************/ + +/* These overwrite the MAME ones in DRIVER_INIT */ +/* They're needed to give the users the choice between different controllers */ +uint8_t md_cons_state::mess_md_io_read_data_port(offs_t offset) +{ + int portnum = offset; + + uint8_t retdata; + int controller; + uint8_t helper_6b = (m_megadrive_io_ctrl_regs[portnum] & 0x3f) | 0xc0; // bits 6 & 7 always come from megadrive_io_data_regs + uint8_t helper_3b = (m_megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from megadrive_io_data_regs + + switch (portnum) + { + case 0: + controller = (m_io_ctrlr->read() & 0x0f); + break; + + case 1: + controller = (m_io_ctrlr->read() & 0xf0); + break; + + default: + controller = 0; + break; + } + + /* Are we using a 6 buttons Joypad? */ + if (controller) + { + if (m_megadrive_io_data_regs[portnum] & 0x40) + { + if (m_io_stage[portnum] == 2) + { + /* here we read B, C & the additional buttons */ + retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | + ((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0x30) | + ((m_io_pad6b[1][portnum] ? m_io_pad6b[1][portnum]->read() : 0) & 0x0f)) & ~helper_6b); + } + else + { + /* here we read B, C & the directional buttons */ + retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | + (((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0x3f) & ~helper_6b); + } + } + else + { + if (m_io_stage[portnum] == 1) + { + /* here we read ((Start & A) >> 2) | 0x00 */ + retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | + ((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0xc0) >> 2) & ~helper_6b); + } + else if (m_io_stage[portnum]==2) + { + /* here we read ((Start & A) >> 2) | 0x0f */ + retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | + (((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0xc0) >> 2) | 0x0f) & ~helper_6b); + } + else + { + /* here we read ((Start & A) >> 2) | Up and Down */ + retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | + (((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0xc0) >> 2) | + ((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0x03)) & ~helper_6b); + } + } + + // osd_printf_debug("read io data port stage %d port %d %02x\n",mess_io_stage[portnum],portnum,retdata); + + retdata |= (retdata << 8); + } + /* Otherwise it's a 3 buttons Joypad */ + else + { + uint8_t svp_test = 0; + if (m_cart) + svp_test = m_cart->read_test(); + + // handle test input for SVP test + if (portnum == 0 && svp_test) + { + retdata = (m_megadrive_io_data_regs[0] & 0xc0); + } + else if (m_megadrive_io_data_regs[portnum] & 0x40) + { + /* here we read B, C & the directional buttons */ + retdata = (m_megadrive_io_data_regs[portnum] & helper_3b) | + ((((m_io_pad3b[portnum] ? m_io_pad3b[portnum]->read() : 0) & 0x3f) | 0x40) & ~helper_3b); + } + else + { + /* here we read ((Start & A) >> 2) | Up and Down */ + retdata = (m_megadrive_io_data_regs[portnum] & helper_3b) | + (((((m_io_pad3b[portnum] ? m_io_pad3b[portnum]->read() : 0) & 0xc0) >> 2) | + ((m_io_pad3b[portnum] ? m_io_pad3b[portnum]->read() : 0) & 0x03) | 0x40) & ~helper_3b); + } + } + + return retdata; +} + + +void md_cons_state::mess_md_io_write_data_port(offs_t offset, uint16_t data) +{ + int portnum = offset; + int controller; + + switch (portnum) + { + case 0: + controller = (m_io_ctrlr->read() & 0x0f); + break; + + case 1: + controller = (m_io_ctrlr->read() & 0xf0); + break; + + default: + controller = 0; + break; + } + + if (controller) + { + if (m_megadrive_io_ctrl_regs[portnum] & 0x40) + { + if (((m_megadrive_io_data_regs[portnum] & 0x40) == 0x00) && ((data & 0x40) == 0x40)) + { + m_io_stage[portnum]++; + m_io_timeout[portnum]->adjust(m_maincpu->cycles_to_attotime(8192)); + } + + } + } + m_megadrive_io_data_regs[portnum] = data; + //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); +} + + +/************************************* + * + * Input ports + * + *************************************/ + + +static INPUT_PORTS_START( md_base ) + PORT_START("PAD1_3B") /* Joypad 1 (3 button + start) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) + + PORT_START("PAD2_3B") /* Joypad 2 (3 button + start) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) + + PORT_START("PAD1_6B") /* Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + + PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 Z") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 Y") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 X") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("P1 Mode") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) + + PORT_START("PAD2_6B") /* Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + + PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 Z") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 Y") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 X") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("P2 Mode") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) + + PORT_START("RESET") /* Buttons on Genesis Console */ + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Reset Button") PORT_IMPULSE(1) // reset, resets 68k (and..?) +INPUT_PORTS_END + +static INPUT_PORTS_START( md ) + PORT_INCLUDE( md_base ) + + PORT_START("CTRLSEL") /* Controller selection */ + PORT_CONFNAME( 0x0f, 0x00, "Player 1 Controller" ) + PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) + PORT_CONFSETTING( 0x01, "Joystick 6 Buttons" ) +// PORT_CONFSETTING( 0x02, "Sega Mouse" ) +/* there exists both a 2 buttons version of the Mouse (Jpn ver, to be used with RPGs, it + can aslo be used as trackball) and a 3 buttons version (US ver, no trackball feats.) */ +// PORT_CONFSETTING( 0x03, "Sega Menacer" ) +// PORT_CONFSETTING( 0x04, "Konami Justifier" ) +// PORT_CONFSETTING( 0x05, "Team Player (Sega Multitap)" ) +// PORT_CONFSETTING( 0x06, "4-Play (EA Multitap)" ) +// PORT_CONFSETTING( 0x07, "J-Cart" ) + PORT_CONFNAME( 0xf0, 0x00, "Player 2 Controller" ) + PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) + PORT_CONFSETTING( 0x10, "Joystick 6 Buttons" ) +INPUT_PORTS_END + +static INPUT_PORTS_START( megajet ) + PORT_INCLUDE( md_base ) + + PORT_START("CTRLSEL") /* Fixed controller setting for Player 1 */ + PORT_CONFNAME( 0x0f, 0x01, "Player 1 Controller" ) // Fixed + PORT_CONFSETTING( 0x01, "Joystick 6 Buttons" ) + PORT_CONFNAME( 0xf0, 0x00, "Player 2 Controller" ) + PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) + PORT_CONFSETTING( 0x10, "Joystick 6 Buttons" ) +INPUT_PORTS_END + +static INPUT_PORTS_START( gen_nomd ) + PORT_INCLUDE( megajet ) + + PORT_MODIFY("RESET") /* No reset button */ + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED ) +INPUT_PORTS_END + + +/************************************* + * + * Machine driver + * + *************************************/ + +void md_cons_state::machine_start() +{ + static const char *const pad6names[2][4] = { + { "PAD1_6B", "PAD2_6B", "UNUSED", "UNUSED" }, + { "EXTRA1", "EXTRA2", "UNUSED", "UNUSED" } + }; + static const char *const pad3names[4] = { "PAD1_3B", "PAD2_3B", "UNUSED", "UNUSED" }; + + m_io_ctrlr = ioport("CTRLSEL"); + + for (int i = 0; i < 4; i++) + { + m_io_pad3b[i] = ioport(pad3names[i]); + m_io_pad6b[0][i] = ioport(pad6names[0][i]); + m_io_pad6b[1][i] = ioport(pad6names[1][i]); + } + + // setup timers for 6 button pads + for (int i = 0; i < 3; i++) + m_io_timeout[i] = timer_alloc(FUNC(md_base_state::io_timeout_timer_callback), this); + + m_vdp->stop_timers(); + + if (m_cart) + m_cart->save_nvram(); + + if (m_z80snd) + m_genz80.z80_run_timer = timer_alloc(FUNC(md_base_state::megadriv_z80_run_state), this); +} + +void md_cons_state::install_cartslot() +{ + if (m_cart) + { + // for now m_cartslot is only in MD and not 32x and SegaCD + m_maincpu->space(AS_PROGRAM).install_read_handler(0x000000, 0x7fffff, read16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::read))); + m_maincpu->space(AS_PROGRAM).install_write_handler(0x000000, 0x7fffff, write16s_delegate(*m_cart, FUNC(base_md_cart_slot_device::write))); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa13000, 0xa130ff, read16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::read_a13)), write16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::write_a13))); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa15000, 0xa150ff, read16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::read_a15)), write16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::write_a15))); +// m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14000, 0xa14003, write16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::write_tmss_bank))); + } +} + +uint16_t md_cons_state::tmss_r(offs_t offset) +{ + if (offset < 0x4000 / 2) + return m_tmss[offset]; + + return 0xffff; +} + +void md_cons_state::tmss_swap_w(uint16_t data) +{ + if (data & 0x0001) + { + install_cartslot(); + m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14100, 0xa14101, write16smo_delegate(*this, FUNC(md_cons_state::tmss_swap_w))); + } + else + { + install_tmss(); + } +} + + +void md_cons_state::install_tmss() +{ + m_maincpu->space(AS_PROGRAM).unmap_readwrite(0x000000, 0x7fffff); + m_maincpu->space(AS_PROGRAM).install_read_handler(0x000000, 0x7fffff, read16sm_delegate(*this, FUNC(md_cons_state::tmss_r))); + + m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14100, 0xa14101, write16smo_delegate(*this, FUNC(md_cons_state::tmss_swap_w))); + +} + + +void md_cons_slot_state::machine_start() +{ + md_cons_state::machine_start(); + + // the SVP introduces some kind of DMA 'lag', which we have to compensate for, this is obvious even on gfx DMAd from ROM (the Speedometer) + if (m_cart && (m_cart->get_type() == SEGA_SVP)) + m_vdp->set_dma_delay(2); + + if (m_tmss) + { + install_tmss(); + } + else + { + install_cartslot(); + } +} + +void md_cons_state::machine_reset() +{ + md_base_state::machine_reset(); + + // if the system has a 32x, pause the extra CPUs until they are actually turned on + if (m_32x) + m_32x->pause_cpu(); +} + +void md_cons_cd_state::machine_start() +{ + md_cons_state::machine_start(); + + // the segaCD introduces some kind of DMA 'lag', which we have to compensate for, + // at least when reading wordram? we might need to check what mode we're in the DMA... + m_vdp->set_dma_delay(2); +} + +// same as screen_eof_megadriv but with addition of 32x and SegaCD/MegaCD pieces +WRITE_LINE_MEMBER(md_cons_state::screen_vblank_console) +{ + if (m_io_reset.read_safe(0) & 0x01) + m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); + + // rising edge + if (state) + { + if (!m_vdp->m_use_alt_timing) + { + bool mode3 = (m_vdp->get_imode() == 3); + m_vdp->vdp_handle_eof(); + m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); + + if (m_32x) + m_32x->screen_eof(mode3); + + if (m_segacd) + m_segacd->update_total_scanlines(mode3); + } + } +} + +void md_cons_state::dcat16_megadriv_base(machine_config &config) +{ + md_ntsc(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::dcat16_megadriv_map); +} + +void md_cons_slot_state::ms_megadriv(machine_config &config) +{ + md_ntsc(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); + SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); +} + +void md_cons_slot_state::ms_megadpal(machine_config &config) +{ + md_pal(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); + SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); +} + +void md_cons_slot_state::ms_megadriv2(machine_config &config) +{ + md2_ntsc(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); + SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); +} + +void md_cons_slot_state::genesis_tmss(machine_config &config) +{ + ms_megadriv(config); + subdevice("cart_list")->set_filter("TMSS"); +} + +void md_cons_state::dcat16_megadriv(machine_config &config) +{ + dcat16_megadriv_base(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + +// has SD card slot instead? +// MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); +// SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); +} + +/************************************* + * + * ROM definition(s) + * + *************************************/ + + +/* we don't use the bios rom (it's not needed and only provides security on early models) */ + +ROM_START(genesis) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START(megadriv) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START(megadrij) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START(genesis_tmss) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) + + ROM_REGION16_BE(0x4000, "tmss", ROMREGION_ERASEFF) + ROM_LOAD( "tmss_usa.bin", 0x0000, 0x4000, CRC(5f5e64eb) SHA1(453fca4e1db6fae4a10657c4451bccbb71955628) ) +ROM_END + +ROM_START(dcat16) + ROM_REGION(0x800000, "maincpu", ROMREGION_ERASEFF) + ROM_LOAD16_WORD_SWAP( "mg6025.u1", 0x0000, 0x800000, CRC(5453d673) SHA1(b9f8d849cbed81fe73525229f4897ccaeeb7a833) ) + + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START(megajet) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START(gen_nomd) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +/************************************* + * + * Driver initialization + * + *************************************/ + +void md_cons_state::init_mess_md_common() +{ + m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_cons_state::mess_md_io_read_data_port)); + m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_cons_state::mess_md_io_write_data_port)); +} + +void md_cons_state::init_genesis() +{ + init_megadriv(); + init_mess_md_common(); + + if (m_32x) + { + m_32x->set_32x_pal(false); + m_32x->set_framerate(60); + m_32x->set_total_scanlines(262); + } + if (m_segacd) + { + m_segacd->set_framerate(60); + m_segacd->set_total_scanlines(262); + } + + m_version_hi_nibble = 0x80; // Export NTSC + if (!m_segacd) + m_version_hi_nibble |= 0x20; +} + +void md_cons_state::init_md_eur() +{ + init_megadrie(); + init_mess_md_common(); + + if (m_32x) + { + m_32x->set_32x_pal(true); + m_32x->set_framerate(50); + m_32x->set_total_scanlines(313); + } + if (m_segacd) + { + m_segacd->set_framerate(50); + m_segacd->set_total_scanlines(313); + } + + m_version_hi_nibble = 0xc0; // Export PAL + if (!m_segacd) + m_version_hi_nibble |= 0x20; +} + +void md_cons_state::init_md_jpn() +{ + init_megadrij(); + init_mess_md_common(); + + if (m_32x) + { + m_32x->set_32x_pal(false); + m_32x->set_framerate(60); + m_32x->set_total_scanlines(262); + } + if (m_segacd) + { + m_segacd->set_framerate(60); + m_segacd->set_total_scanlines(262); + } + + m_version_hi_nibble = 0x00; // JPN NTSC + if (!m_segacd) + m_version_hi_nibble |= 0x20; +} + +/****************************************** 32X emulation ****************************************/ + +DEVICE_IMAGE_LOAD_MEMBER( md_cons_state::_32x_cart ) +{ + uint32_t length; + std::vector temp_copy; + uint16_t *ROM16; + uint32_t *ROM32; + int i; + + if (!image.loaded_through_softlist()) + { + length = image.length(); + temp_copy.resize(length); + image.fread(&temp_copy[0], length); + } + else + { + length = image.get_software_region_length("rom"); + temp_copy.resize(length); + memcpy(&temp_copy[0], image.get_software_region("rom"), length); + } + + /* Copy the cart image in the locations the driver expects */ + // Notice that, by using pick_integer, we are sure the code works on both LE and BE machines + ROM16 = (uint16_t *) memregion("gamecart")->base(); + for (i = 0; i < length; i += 2) + ROM16[i / 2] = pick_integer_be(&temp_copy[0], i, 2); + + ROM32 = (uint32_t *) memregion("gamecart_sh2")->base(); + for (i = 0; i < length; i += 4) + ROM32[i / 4] = pick_integer_be(&temp_copy[0], i, 4); + + ROM16 = (uint16_t *) memregion("maincpu")->base(); + for (i = 0x00; i < length; i += 2) + ROM16[i / 2] = pick_integer_be(&temp_copy[0], i, 2); + + return image_init_result::PASS; +} + + +void md_cons_state::_32x_scanline_callback(int x, uint32_t priority, uint32_t &lineptr) +{ + if (m_32x) + m_32x->render_videobuffer_to_screenbuffer(x, priority, lineptr); +} + +void md_cons_state::_32x_interrupt_callback(int scanline, int irq6) +{ + if (m_32x) + m_32x->interrupt_cb(scanline, irq6); +} + +void md_cons_state::_32x_scanline_helper_callback(int scanline) +{ + if (m_32x) + m_32x->render_videobuffer_to_screenbuffer_helper(scanline); +} + +void md_cons_state::genesis_32x(machine_config &config) +{ + md_ntsc(config); + + m_vdp->set_md_32x_scanline(FUNC(md_cons_state::_32x_scanline_callback)); + m_vdp->set_md_32x_scanline_helper(FUNC(md_cons_state::_32x_scanline_helper_callback)); + m_vdp->set_md_32x_interrupt(FUNC(md_cons_state::_32x_interrupt_callback)); + m_vdp->reset_routes(); + m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.50)/2); + m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.50)/2); + + SEGA_32X_NTSC(config, m_32x, (MASTER_CLOCK_NTSC * 3) / 7, m_maincpu, m_scan_timer); + m_32x->set_screen("megadriv"); + m_32x->add_route(0, "lspeaker", 1.00); + m_32x->add_route(1, "rspeaker", 1.00); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + // we need to remove and re-add the YM because the balance is different + // due to MAME having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!) + m_ymsnd->reset_routes(); + m_ymsnd->add_route(0, "lspeaker", (0.50)/2); + m_ymsnd->add_route(1, "rspeaker", (0.50)/2); + + generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin")); + cartslot.set_must_be_loaded(true); + cartslot.set_device_load(FUNC(md_cons_state::_32x_cart)); + + SOFTWARE_LIST(config, "cart_list").set_original("32x").set_filter("NTSC-U"); +} + + +void md_cons_state::mdj_32x(machine_config &config) +{ + md_ntsc(config); + + m_vdp->set_md_32x_scanline(FUNC(md_cons_state::_32x_scanline_callback)); + m_vdp->set_md_32x_scanline_helper(FUNC(md_cons_state::_32x_scanline_helper_callback)); + m_vdp->set_md_32x_interrupt(FUNC(md_cons_state::_32x_interrupt_callback)); + m_vdp->reset_routes(); + m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.50)/2); + m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.50)/2); + + SEGA_32X_NTSC(config, m_32x, (MASTER_CLOCK_NTSC * 3) / 7, m_maincpu, m_scan_timer); + m_32x->set_screen("megadriv"); + m_32x->add_route(0, "lspeaker", 1.00); + m_32x->add_route(1, "rspeaker", 1.00); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + // we need to remove and re-add the sound system because the balance is different + // due to MAME having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!) + m_ymsnd->reset_routes(); + m_ymsnd->add_route(0, "lspeaker", (0.50)/2); + m_ymsnd->add_route(1, "rspeaker", (0.50)/2); + + generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin")); + cartslot.set_must_be_loaded(true); + cartslot.set_device_load(FUNC(md_cons_state::_32x_cart)); + + SOFTWARE_LIST(config, "cart_list").set_original("32x").set_filter("NTSC-J"); +} + + +void md_cons_state::md_32x(machine_config &config) +{ + md_pal(config); + + m_vdp->set_md_32x_scanline(FUNC(md_cons_state::_32x_scanline_callback)); + m_vdp->set_md_32x_scanline_helper(FUNC(md_cons_state::_32x_scanline_helper_callback)); + m_vdp->set_md_32x_interrupt(FUNC(md_cons_state::_32x_interrupt_callback)); + m_vdp->reset_routes(); + m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.50)/2); + m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.50)/2); + + SEGA_32X_PAL(config, m_32x, (MASTER_CLOCK_PAL * 3) / 7, m_maincpu, m_scan_timer); + m_32x->set_screen("megadriv"); + m_32x->add_route(0, "lspeaker", 1.00); + m_32x->add_route(1, "rspeaker", 1.00); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + // we need to remove and re-add the sound system because the balance is different + // due to MAME having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!) + m_ymsnd->reset_routes(); + m_ymsnd->add_route(0, "lspeaker", (0.50)/2); + m_ymsnd->add_route(1, "rspeaker", (0.50)/2); + + generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin")); + cartslot.set_must_be_loaded(true); + cartslot.set_device_load(FUNC(md_cons_state::_32x_cart)); + + SOFTWARE_LIST(config, "cart_list").set_original("32x").set_filter("PAL"); +} + + + +#define _32X_ROMS \ + ROM_REGION16_BE( 0x400000, "gamecart", ROMREGION_ERASE00 ) /* 68000 Code */ \ + ROM_REGION32_BE( 0x400000, "gamecart_sh2", ROMREGION_ERASE00 ) /* Copy for the SH2 */ \ + ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ \ + ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) \ + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) \ + /* temp, rom should only be visible here when one of the regs is set, tempo needs it */ \ + ROM_COPY( "32x_68k_bios", 0x0, 0x0, 0x100) \ + ROM_REGION32_BE( 0x400000, "master", 0 ) /* SH2 Code */ \ + ROM_SYSTEM_BIOS( 0, "retail", "Mars Version 1.0 (retail)" ) \ + ROMX_LOAD( "32x_m_bios.bin", 0x000000, 0x000800, CRC(dd9c46b8) SHA1(1e5b0b2441a4979b6966d942b20cc76c413b8c5e), ROM_BIOS(0) ) \ + ROM_SYSTEM_BIOS( 1, "sdk", "Mars Version 1.0 (early sdk)" ) \ + ROMX_LOAD( "32x_m_bios_sdk.bin", 0x000000, 0x000800, BAD_DUMP CRC(c7102c53) SHA1(ed73a47f186b373b8eff765f84ef26c3d9ef6cb0), ROM_BIOS(1) ) \ + ROM_REGION32_BE( 0x400000, "slave", 0 ) /* SH2 Code */ \ + ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) + +ROM_START( 32x ) + _32X_ROMS +ROM_END + +ROM_START( 32xe ) + _32X_ROMS +ROM_END + +ROM_START( 32xj ) + _32X_ROMS +ROM_END + + +/****************************************** SegaCD emulation ****************************************/ + +void md_cons_cd_state::genesis_scd(machine_config &config) +{ + md_ntsc(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + SEGA_SEGACD_US(config, m_segacd, 0); + m_segacd->set_palette("gen_vdp:gfx_palette"); + m_segacd->set_hostcpu(m_maincpu); + m_segacd->set_screen("megadriv"); + + config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + + CDROM(config, "cdrom").set_interface("scd_cdrom"); + + SOFTWARE_LIST(config, "cd_list").set_original("segacd"); +} + +void md_cons_cd_state::genesis2_scd(machine_config &config) +{ + md2_ntsc(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + SEGA_SEGACD_US(config, m_segacd, 0); + m_segacd->set_palette("gen_vdp:gfx_palette"); + m_segacd->set_hostcpu(m_maincpu); + m_segacd->set_screen("megadriv"); + + config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + + CDROM(config, "cdrom").set_interface("scd_cdrom"); + + SOFTWARE_LIST(config, "cd_list").set_original("segacd"); +} + +void md_cons_cd_state::md_scd(machine_config &config) +{ + md_pal(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + SEGA_SEGACD_EUROPE(config, m_segacd, 0); + m_segacd->set_palette("gen_vdp:gfx_palette"); + m_segacd->set_hostcpu(m_maincpu); + m_segacd->set_screen("megadriv"); + + config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + + CDROM(config, "cdrom").set_interface("scd_cdrom"); + + SOFTWARE_LIST(config, "cd_list").set_original("megacd"); +} + +void md_cons_cd_state::md2_scd(machine_config &config) +{ + md2_pal(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + SEGA_SEGACD_EUROPE(config, m_segacd, 0); + m_segacd->set_palette("gen_vdp:gfx_palette"); + m_segacd->set_hostcpu(m_maincpu); + m_segacd->set_screen("megadriv"); + + config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + + CDROM(config, "cdrom").set_interface("scd_cdrom"); + + SOFTWARE_LIST(config, "cd_list").set_original("megacd"); +} + +void md_cons_cd_state::mdj_scd(machine_config &config) +{ + md_ntsc(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + SEGA_SEGACD_JAPAN(config, m_segacd, 0); + m_segacd->set_palette("gen_vdp:gfx_palette"); + m_segacd->set_hostcpu(m_maincpu); + m_segacd->set_screen("megadriv"); + + config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + + CDROM(config, "cdrom").set_interface("scd_cdrom"); + + SOFTWARE_LIST(config, "cd_list").set_original("megacdj"); +} + +void md_cons_cd_state::md2j_scd(machine_config &config) +{ + md2_ntsc(config); + + subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + SEGA_SEGACD_JAPAN(config, m_segacd, 0); + m_segacd->set_palette("gen_vdp:gfx_palette"); + m_segacd->set_hostcpu(m_maincpu); + m_segacd->set_screen("megadriv"); + + config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + + CDROM(config, "cdrom").set_interface("scd_cdrom"); + + SOFTWARE_LIST(config, "cd_list").set_original("megacdj"); +} + +/******************SEGA CD + 32X****************************/ + +void md_cons_cd_state::genesis_32x_scd(machine_config &config) +{ + genesis_32x(config); + + SEGA_SEGACD_US(config, m_segacd, 0); + m_segacd->set_palette("gen_vdp:gfx_palette"); + m_segacd->set_hostcpu(m_maincpu); + m_segacd->set_screen("megadriv"); + + config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + + CDROM(config, "cdrom").set_interface("scd_cdrom"); + + config.device_remove("cartslot"); + GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_state::_32x_cart)); + + //config.m_perfect_cpu_quantum = subtag("32x_master_sh2"); + SOFTWARE_LIST(config, "cd_list").set_original("segacd"); +} + +void md_cons_cd_state::md_32x_scd(machine_config &config) +{ + md_32x(config); + + SEGA_SEGACD_EUROPE(config, m_segacd, 0); + m_segacd->set_palette("gen_vdp:gfx_palette"); + m_segacd->set_hostcpu(m_maincpu); + m_segacd->set_screen("megadriv"); + + config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + + CDROM(config, "cdrom").set_interface("scd_cdrom"); + + config.device_remove("cartslot"); + GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_state::_32x_cart)); + + //config.m_perfect_cpu_quantum = subtag("32x_master_sh2"); + SOFTWARE_LIST(config, "cd_list").set_original("megacd"); +} + +void md_cons_cd_state::mdj_32x_scd(machine_config &config) +{ + mdj_32x(config); + + SEGA_SEGACD_JAPAN(config, m_segacd, 0); + m_segacd->set_palette("gen_vdp:gfx_palette"); + m_segacd->set_hostcpu(m_maincpu); + m_segacd->set_screen("megadriv"); + + config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + + CDROM(config, "cdrom").set_interface("scd_cdrom"); + + config.device_remove("cartslot"); + GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_state::_32x_cart)); + + //config.m_perfect_cpu_quantum = subtag("32x_master_sh2"); + SOFTWARE_LIST(config, "cd_list").set_original("megacdj"); +} + +/* We need proper names for most of these BIOS ROMs! */ +ROM_START( segacd ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v1.10 confirmed dump by dead_screem */ + ROM_LOAD( "mpr-15045b.bin", 0x000000, 0x020000, CRC(c6d10268) SHA1(f4f315adcef9b8feb0364c21ab7f0eaf5457f3ed) ) +ROM_END + +ROM_START( megacd ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v1.00, confirmed good dump */ + ROM_LOAD( "megacd_model1_bios_1_00_e.bin", 0x000000, 0x020000, CRC(529ac15a) SHA1(f891e0ea651e2232af0c5c4cb46a0cae2ee8f356) ) +ROM_END + +ROM_START( megacdj ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_DEFAULT_BIOS("v100g") // this seems the only revision where the cursor in CD menu works, allowing to boot games + /* Confirmed by ElBarto */ + ROM_SYSTEM_BIOS(0, "v100s", "v1.00S") + ROMX_LOAD( "mpr-14088h.bin", 0x000000, 0x020000, CRC(3773d5aa) SHA1(bbf729a1aaa1667b783749299e1ad932aaf5f253), ROM_BIOS(0) | ROM_GROUPWORD | ROM_REVERSE) + /* Confirmed by ElBarto */ + ROM_SYSTEM_BIOS(1, "v100g", "v1.00G") + ROMX_LOAD( "epr-14088b.bin", 0x000000, 0x020000, CRC(69ed6ccd) SHA1(27d11c3836506f01ee81cd142c0cd8b51abebbd2), ROM_BIOS(1) | ROM_GROUPWORD | ROM_REVERSE) + /* Confirmed by ElBarto */ + ROM_SYSTEM_BIOS(2, "v100l", "v1.00L") + ROMX_LOAD( "mpr-14088c.bin", 0x000000, 0x020000, CRC(03134289) SHA1(d60cb5a53f26d6b13e354bc149217587f2301718), ROM_BIOS(2) | ROM_GROUPWORD | ROM_REVERSE) + /* Confirmed by ElBarto */ + ROM_SYSTEM_BIOS(3, "v100o", "v1.00O") + ROMX_LOAD( "epr-14088d.bin", 0x000000, 0x020000, CRC(dfa95ee9) SHA1(e13666c76fa0a2e94e2f651b26b0fd625bf55f07), ROM_BIOS(3) | ROM_GROUPWORD | ROM_REVERSE) + ROM_SYSTEM_BIOS(4, "v100p", "v1.00P") // CRC: e2e70bc8 when byteswapped + ROMX_LOAD( "epr-14088e.bin", 0x000000, 0x020000, CRC(9d2da8f2) SHA1(4846f448160059a7da0215a5df12ca160f26dd69), ROM_BIOS(4) ) + // EEPROM had no SEGA's label, might be 14088(no rev) or 14088A + ROM_SYSTEM_BIOS(5, "v100c", "v1.00C") // CRC: c3b60c13 when byteswapped + ROMX_LOAD( "100c.bin", 0x000000, 0x020000, CRC(41af44c4) SHA1(f30d109d1c2f7c9feaf38600c65834261db73d1f), ROM_BIOS(5) ) + ROM_SYSTEM_BIOS(6, "v111", "v1.11") // CRC: e0a6179b when byteswapped + ROMX_LOAD( "mpr-14837.bin", 0x000000, 0x020000, CRC(4be18ff6) SHA1(204758d5a64c24e96e1a9fe6bd82e1878fef7ade), ROM_BIOS(6) ) +ROM_END + +/* Asia bios, when run in USA region will show : +ERROR! +THIS IS A PAL-COMPATIBLE MEGA CD +FOR EXCLUSIVE USE IN SOUTHEAST ASIA. + +Confirmed by Jakovasaur +*/ +ROM_START( megacda ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_LOAD( "epr-14536h.bin", 0x000000, 0x020000, CRC(550f30bb) SHA1(e4193c6ae44c3cea002707d2a88f1fbcced664de)) +ROM_END + +ROM_START( segacd2 ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v211x", "Model 2 v2.11X") + ROMX_LOAD( "mpr-15764-t.bin", 0x000000, 0x020000, CRC(2e49d72c) SHA1(328a3228c29fba244b9db2055adc1ec4f7a87e6b), ROM_BIOS(0) ) + ROM_SYSTEM_BIOS(1, "v200", "Model 2 v2.00") /* verified dump */ + ROMX_LOAD( "us_scd2_930314.bin", 0x000000, 0x020000, CRC(8af65f58) SHA1(5a8c4b91d3034c1448aac4b5dc9a6484fce51636), ROM_BIOS(1) ) + /* this is reportedly a bad dump, it has many differences from the verified dump and does not boot in Kega */ + /* ROMX_LOAD( "segacd_model2_bios_2_00_u.bin", 0x000000, 0x020000, CRC(340b4be4) SHA1(bd3ee0c8ab732468748bf98953603ce772612704), ROM_BIOS(1) ) */ + ROM_SYSTEM_BIOS(2, "v200w", "Model 2 v2.00W") + ROMX_LOAD( "segacd_model2_bios_2_00w_u.bin", 0x000000, 0x020000, CRC(9f6f6276) SHA1(5adb6c3af218c60868e6b723ec47e36bbdf5e6f0), ROM_BIOS(2) ) +ROM_END + +/* v2.00, v2.00w confirmed good dumps by ElBarto */ +/* v2.11x confirmed good dump by TwistedTom */ +ROM_START( megacd2 ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v211x", "v2.11X") // MK-4102A-50 Sony pcb + ROMX_LOAD( "mpr-15811-t.bin", 0x000000, 0x020000, CRC(391a80d2) SHA1(aa4bb1803b06714fbc04d8a209161876796dd511), ROM_BIOS(0) | ROM_GROUPWORD | ROM_REVERSE ) + ROM_SYSTEM_BIOS(1, "v200w", "v2.00W") // MK-4102-50 Funai pcb + ROMX_LOAD( "mpr-15512a.bin", 0x000000, 0x020000, CRC(53f1757c) SHA1(67bf3970ca5a05fd5ce3d6c446789c5d971b98a4), ROM_BIOS(1) | ROM_GROUPWORD | ROM_REVERSE ) + ROM_SYSTEM_BIOS(2, "v200", "v2.00") // ? + ROMX_LOAD( "mpr-15512.bin", 0x000000, 0x020000, CRC(cb76f114) SHA1(939f173cadc41e996a3c34498da1bf55e7e18ff8), ROM_BIOS(2) | ROM_GROUPWORD | ROM_REVERSE ) +ROM_END + +/* Confirmed good dump by ElBarto */ +ROM_START( megacd2j ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v200c", "v2.00C") + ROMX_LOAD( "mpr-15398.bin", 0x000000, 0x020000, CRC(1e4344e6) SHA1(4d1251a6973d932e734ae5e8c6b9b55eb40e4143), ROM_BIOS(0) | ROM_GROUPWORD | ROM_REVERSE ) +ROM_END + +ROM_START( aiwamcd ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v2.11 */ + ROM_LOAD( "mpr-15768-t.bin", 0x000000, 0x020000, CRC(8052c7a0) SHA1(219d284dcf63ce366a4dc6d1ff767a0d2eea283d) ) +ROM_END + +ROM_START( laseract ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v104", "v1.04") + ROMX_LOAD( "laseractive_bios_1_04_u.bin", 0x000000, 0x020000, CRC(50cd3d23) SHA1(aa811861f8874775075bd3f53008c8aaf59b07db), ROM_BIOS(0) ) + ROM_SYSTEM_BIOS(1, "v102", "v1.02") + ROMX_LOAD( "laseractive_bios_1_02_u.bin", 0x000000, 0x020000, CRC(3b10cf41) SHA1(8af162223bb12fc19b414f126022910372790103), ROM_BIOS(1) ) +ROM_END + +ROM_START( laseractj ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + ROM_SYSTEM_BIOS(0, "v105", "v1.05") + ROMX_LOAD( "mega-ld 1.05 bios.bin", 0x000000, 0x020000, CRC(474aaa44) SHA1(b3b1d880e288b6dc79eec0ff1b0480c229ec141d), ROM_BIOS(0) ) + ROM_SYSTEM_BIOS(1, "v102", "v1.02") + ROMX_LOAD( "laseractive_bios_1_02_j.bin", 0x000000, 0x020000, CRC(00eedb3a) SHA1(26237b333db4a4c6770297fa5e655ea95840d5d9), ROM_BIOS(1) ) +ROM_END + +ROM_START( xeye ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v2.00 (US), confirmed good with a chip dump */ + ROM_LOAD( "g304.bin", 0x000000, 0x020000, CRC(290f8e33) SHA1(651f14d5a5e0ecb974a60c0f43b1d2006323fb09) ) +ROM_END + +ROM_START( wmega ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v1.00 (Japan NTSC) Sega BIOS, chip-dumped */ + ROM_LOAD( "g301.bin", 0x000000, 0x020000, CRC(d21fe71d) SHA1(3fc9358072f74bd24e3e297ea11b2bf15a7af891) ) +ROM_END + +ROM_START( wmegam2 ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v2.00 */ + ROM_LOAD( "wondermega_m2_bios_2_00_j.bin", 0x000000, 0x020000, CRC(2b19972f) SHA1(b3f32e409bd5508c89ed8be33d41a58d791d0e5d) ) +ROM_END + +ROM_START( cdx ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v2.21X */ + ROM_LOAD( "segacdx_bios_2_21_u.bin", 0x000000, 0x020000, CRC(d48c44b5) SHA1(2b125c0545afa089b617f2558e686ea723bdc06e) ) +ROM_END + +ROM_START( multmega ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + /* v2.21X */ + ROM_LOAD( "opr-16140.bin", 0x000000, 0x020000, CRC(aacb851e) SHA1(75548ac9aaa6e81224499f9a1403b2b42433f5b7) ) + /* the below was marked "confirmed good dump", but 0x72 and 0x73 are 0xFF, indicating a bad dump made from memory */ + /* ROM_LOAD( "multimega_bios_2_21_e.bin", 0x000000, 0x020000, CRC(34d3cce1) SHA1(73fc9c014ad803e9e7d8076b3642a8a5224b3e51) ) */ +ROM_END + +/* some games use the 32x and SegaCD together to give better quality FMV */ +ROM_START( 32x_scd ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + + ROM_REGION16_BE( 0x400000, "gamecart", 0 ) /* 68000 Code */ + ROM_LOAD( "mpr-15764-t.bin", 0x000000, 0x020000, CRC(2e49d72c) SHA1(328a3228c29fba244b9db2055adc1ec4f7a87e6b) ) + + ROM_REGION32_BE( 0x400000, "gamecart_sh2", 0 ) /* Copy for the SH2 */ + ROM_COPY( "gamecart", 0x000000, 0x0, 0x400000) + + ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ + ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) + + ROM_REGION32_BE( 0x400000, "master", 0 ) /* SH2 Code */ + ROM_LOAD( "32x_m_bios.bin", 0x000000, 0x000800, CRC(dd9c46b8) SHA1(1e5b0b2441a4979b6966d942b20cc76c413b8c5e) ) + + ROM_REGION32_BE( 0x400000, "slave", 0 ) /* SH2 Code */ + ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) +ROM_END + +ROM_START( 32x_mcd ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + + ROM_REGION16_BE( 0x400000, "gamecart", 0 ) /* 68000 Code */ + ROM_LOAD( "megacd_model1_bios_1_00_e.bin", 0x000000, 0x020000, CRC(529ac15a) SHA1(f891e0ea651e2232af0c5c4cb46a0cae2ee8f356) ) + + ROM_REGION32_BE( 0x400000, "gamecart_sh2", 0 ) /* Copy for the SH2 */ + ROM_COPY( "gamecart", 0x000000, 0x0, 0x400000) + + ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ + ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) + + ROM_REGION32_BE( 0x400000, "master", 0 ) /* SH2 Code */ + ROM_LOAD( "32x_m_bios.bin", 0x000000, 0x000800, CRC(dd9c46b8) SHA1(1e5b0b2441a4979b6966d942b20cc76c413b8c5e) ) + + ROM_REGION32_BE( 0x400000, "slave", 0 ) /* SH2 Code */ + ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) +ROM_END + +ROM_START( 32x_mcdj ) + ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) + + ROM_REGION16_BE( 0x400000, "gamecart", 0 ) /* 68000 Code */ + ROM_DEFAULT_BIOS("v100g") // this seems the only revision where the cursor in CD menu works, allowing to boot games + /* Confirmed by ElBarto */ + ROM_SYSTEM_BIOS(0, "v100s", "v1.00S") + ROMX_LOAD( "mpr-14088h.bin", 0x000000, 0x020000, CRC(3773d5aa) SHA1(bbf729a1aaa1667b783749299e1ad932aaf5f253), ROM_BIOS(0) | ROM_GROUPWORD | ROM_REVERSE) + /* Confirmed by ElBarto */ + ROM_SYSTEM_BIOS(1, "v100g", "v1.00G") + ROMX_LOAD( "epr-14088b.bin", 0x000000, 0x020000, CRC(69ed6ccd) SHA1(27d11c3836506f01ee81cd142c0cd8b51abebbd2), ROM_BIOS(1) | ROM_GROUPWORD | ROM_REVERSE) + /* Confirmed by ElBarto */ + ROM_SYSTEM_BIOS(2, "v100l", "v1.00L") + ROMX_LOAD( "mpr-14088c.bin", 0x000000, 0x020000, CRC(03134289) SHA1(d60cb5a53f26d6b13e354bc149217587f2301718), ROM_BIOS(2) | ROM_GROUPWORD | ROM_REVERSE) + /* Confirmed by ElBarto */ + ROM_SYSTEM_BIOS(3, "v100o", "v1.00O") + ROMX_LOAD( "epr-14088d.bin", 0x000000, 0x020000, CRC(dfa95ee9) SHA1(e13666c76fa0a2e94e2f651b26b0fd625bf55f07), ROM_BIOS(3) | ROM_GROUPWORD | ROM_REVERSE) + ROM_SYSTEM_BIOS(4, "v100p", "v1.00P") // CRC: e2e70bc8 when byteswapped + ROMX_LOAD( "epr-14088e.bin", 0x000000, 0x020000, CRC(9d2da8f2) SHA1(4846f448160059a7da0215a5df12ca160f26dd69), ROM_BIOS(4) ) + + ROM_REGION32_BE( 0x400000, "gamecart_sh2", 0 ) /* Copy for the SH2 */ + ROM_COPY( "gamecart", 0x000000, 0x0, 0x400000) + + ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ + ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) + + ROM_REGION32_BE( 0x400000, "master", 0 ) /* SH2 Code */ + ROM_LOAD( "32x_m_bios.bin", 0x000000, 0x000800, CRC(dd9c46b8) SHA1(1e5b0b2441a4979b6966d942b20cc76c413b8c5e) ) + + ROM_REGION32_BE( 0x400000, "slave", 0 ) /* SH2 Code */ + ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) +ROM_END + + + +/*************************************************************************** + + Game driver(s) + +***************************************************************************/ + +/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */ +CONS( 1989, genesis, 0, 0, ms_megadriv, md, md_cons_slot_state, init_genesis, "Sega", "Genesis (USA, NTSC)", MACHINE_SUPPORTS_SAVE ) +CONS( 1990, megadriv, genesis, 0, ms_megadpal, md, md_cons_slot_state, init_md_eur, "Sega", "Mega Drive (Europe, PAL)", MACHINE_SUPPORTS_SAVE ) +CONS( 1988, megadrij, genesis, 0, ms_megadriv, md, md_cons_slot_state, init_md_jpn, "Sega", "Mega Drive (Japan, NTSC)", MACHINE_SUPPORTS_SAVE ) + +// 1990+ models had the TMSS security chip, leave this as a clone, it reduces compatibility and nothing more. +CONS( 1990, genesis_tmss, genesis, 0, genesis_tmss, md, md_cons_slot_state, init_genesis, "Sega", "Genesis (USA, NTSC, with TMSS chip)", MACHINE_SUPPORTS_SAVE ) + +// the 32X plugged in the cart slot, games plugged into the 32x. Maybe it should be handled as an expansion device? +CONS( 1994, 32x, 0, 0, genesis_32x, md, md_cons_state, init_genesis, "Sega", "Genesis with 32X (USA, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1994, 32xe, 32x, 0, md_32x, md, md_cons_state, init_md_eur, "Sega", "Mega Drive with 32X (Europe, PAL)", MACHINE_NOT_WORKING ) +CONS( 1994, 32xj, 32x, 0, mdj_32x, md, md_cons_state, init_md_jpn, "Sega", "Mega Drive with 32X (Japan, NTSC)", MACHINE_NOT_WORKING ) + +// the SegaCD plugged into the expansion port.. +CONS( 1992, segacd, 0, 0, genesis_scd, md, md_cons_cd_state, init_genesis, "Sega", "Sega CD (USA, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1993, megacd, segacd, 0, md_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Mega-CD (Europe, PAL)", MACHINE_NOT_WORKING ) +CONS( 1991, megacdj, segacd, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "Sega", "Mega-CD (Japan, NTSC)", MACHINE_NOT_WORKING ) // this bios doesn't work with our ram interleave needed by a few games?! +CONS( 1991, megacda, segacd, 0, md_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Mega-CD (Asia, PAL)", MACHINE_NOT_WORKING ) +CONS( 1993, segacd2, 0, 0, genesis_scd, md, md_cons_cd_state, init_genesis, "Sega", "Sega CD 2 (USA, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1993, megacd2, segacd2, 0, md_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Mega-CD 2 (Europe, PAL)", MACHINE_NOT_WORKING ) +CONS( 1993, megacd2j, segacd2, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "Sega", "Mega-CD 2 (Japan, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1994, aiwamcd, segacd2, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "AIWA", "Mega-CD CSD-G1M (Japan, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1993, xeye, 0, 0, genesis2_scd, md, md_cons_cd_state, init_genesis, "JVC", "X'eye (USA, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1992, wmega, xeye, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "Sega", "Wondermega (Japan, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1993, wmegam2, xeye, 0, md2j_scd, md, md_cons_cd_state, init_md_jpn, "Victor", "Wondermega M2 (Japan, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1994, cdx, 0, 0, genesis2_scd, md, md_cons_cd_state, init_genesis, "Sega", "CDX (USA, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1994, multmega, cdx, 0, md2_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Multi-Mega (Europe, PAL)", MACHINE_NOT_WORKING ) + +//32X plugged in the cart slot + SegaCD plugged into the expansion port.. +CONS( 1994, 32x_scd, 0, 0, genesis_32x_scd, md, md_cons_cd_state, init_genesis, "Sega", "Sega CD with 32X (USA, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1995, 32x_mcd, 32x_scd, 0, md_32x_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Mega-CD with 32X (Europe, PAL)", MACHINE_NOT_WORKING ) +CONS( 1994, 32x_mcdj, 32x_scd, 0, mdj_32x_scd, md, md_cons_cd_state, init_md_jpn, "Sega", "Mega-CD with 32X (Japan, NTSC)", MACHINE_NOT_WORKING ) + +// handheld hardware +CONS( 1995, gen_nomd, 0, 0, ms_megadriv2, gen_nomd, md_cons_slot_state, init_genesis, "Sega", "Genesis Nomad (USA Genesis handheld)", MACHINE_SUPPORTS_SAVE ) + +// handheld without LCD +CONS( 1993, megajet, gen_nomd, 0, ms_megadriv2, megajet, md_cons_slot_state, init_md_jpn, "Sega", "Mega Jet (Japan Mega Drive handheld)", MACHINE_SUPPORTS_SAVE ) + +// LaserActive (Laserdisc Player(ex: CLD-A100) with 'Control Pack' Addon slot) +// Mega Drive Pack(PAC-S1)/Genesis Pack(PAC-S10) plugged into the Control Pack slot, for plays Mega Drive/Genesis Cartridge, Mega-CD/Sega CD, Mega-LD stuffs +CONS( 1993, laseract, 0, 0, genesis_scd, md, md_cons_cd_state, init_genesis, "Pioneer / Sega","LaserActive with Genesis Pack PAC-S10 (USA, NTSC)", MACHINE_NOT_WORKING ) +CONS( 1993, laseractj, laseract, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "Pioneer / Sega","LaserActive with Mega Drive Pack PAC-S1 (Japan, NTSC)", MACHINE_NOT_WORKING ) +//TODO: it has also PC Engine Pack(PAC-N1)/TG16 Pack(PAC-N10) for plays PC Engine/TG16 Cartridge, (Super/Arcade) CD-ROM2/TurboGrafx-CD, LD-ROM2 stuffs, but not emulated. + +/* clone hardware - not sure if this hardware is running some kind of emulator, or enhanced MD clone, or just custom banking */ +CONS( 200?, dcat16, 0, 0, dcat16_megadriv, md, md_cons_slot_state, init_genesis, "Firecore", "D-CAT16 (Mega Drive handheld)", MACHINE_NOT_WORKING ) diff --git a/src/mame/sega/mdconsole.h b/src/mame/sega/mdconsole.h new file mode 100644 index 00000000000..1290be529d5 --- /dev/null +++ b/src/mame/sega/mdconsole.h @@ -0,0 +1,109 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +#ifndef MAME_SEGACONS_MDCONSOLE_H +#define MAME_SEGACONS_MDCONSOLE_H + +#pragma once + +#include "megadriv.h" + +#include "mega32x.h" +#include "megacd.h" + +#include "bus/megadrive/md_slot.h" +#include "bus/megadrive/md_carts.h" + + +class md_cons_state : public md_base_state +{ +public: + md_cons_state(const machine_config &mconfig, device_type type, const char *tag) : + md_base_state(mconfig, type, tag), + m_32x(*this,"sega32x"), + m_segacd(*this,"segacd"), + m_cart(*this, "mdslot"), + m_tmss(*this, "tmss") + { } + + ioport_port *m_io_ctrlr = nullptr; + ioport_port *m_io_pad3b[4]{}; + ioport_port *m_io_pad6b[2][4]{}; + + optional_device m_32x; + optional_device m_segacd; + optional_device m_cart; + optional_region_ptr m_tmss; + + void init_mess_md_common(); + void init_genesis(); + void init_md_eur(); + void init_md_jpn(); + + uint8_t mess_md_io_read_data_port(offs_t offset); + void mess_md_io_write_data_port(offs_t offset, uint16_t data); + + DECLARE_WRITE_LINE_MEMBER(screen_vblank_console); + + DECLARE_DEVICE_IMAGE_LOAD_MEMBER( _32x_cart ); + + void _32x_scanline_callback(int x, uint32_t priority, uint32_t &lineptr); + void _32x_interrupt_callback(int scanline, int irq6); + void _32x_scanline_helper_callback(int scanline); + + void install_cartslot(); + void install_tmss(); + uint16_t tmss_r(offs_t offset); + void tmss_swap_w(uint16_t data); + void dcat16_megadriv_base(machine_config &config); + void dcat16_megadriv(machine_config &config); + + void md_32x(machine_config &config); + void genesis_32x(machine_config &config); + void mdj_32x(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; +}; + +class md_cons_slot_state : public md_cons_state +{ +public: + md_cons_slot_state(const machine_config &mconfig, device_type type, const char *tag) : + md_cons_state(mconfig, type, tag) + { } + + void ms_megadpal(machine_config &config); + void ms_megadriv(machine_config &config); + void ms_megadriv2(machine_config &config); + + void genesis_tmss(machine_config &config); + + +protected: + virtual void machine_start() override; +}; + +class md_cons_cd_state : public md_cons_state +{ +public: + md_cons_cd_state(const machine_config &mconfig, device_type type, const char *tag) : + md_cons_state(mconfig, type, tag) + { } + + void genesis_scd(machine_config &config); + void genesis2_scd(machine_config &config); + void md_scd(machine_config &config); + void md2_scd(machine_config &config); + void mdj_scd(machine_config &config); + + void mdj_32x_scd(machine_config &config); + void md2j_scd(machine_config &config); + void genesis_32x_scd(machine_config &config); + void md_32x_scd(machine_config &config); + +protected: + virtual void machine_start() override; +}; + +#endif // MAME_SEGACONS_MDCONSOLE_H diff --git a/src/mame/sega/megacd.cpp b/src/mame/sega/megacd.cpp new file mode 100644 index 00000000000..6f7bc7d82f6 --- /dev/null +++ b/src/mame/sega/megacd.cpp @@ -0,0 +1,1939 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +#include "emu.h" +#include "megacd.h" +#include "machine/nvram.h" +#include "video/315_5313.h" +#include "megacd.lh" + + +#define SEGACD_CLOCK 12500000 + +#define RAM_MODE_2MEG (0) +#define RAM_MODE_1MEG (2) + +#define DMA_PCM (0x0400) +#define DMA_PRG (0x0500) +#define DMA_WRAM (0x0700) + +#define SEGACD_IRQ3_TIMER_SPEED (attotime::from_nsec(m_irq3_timer_reg*30720)) + + +DEFINE_DEVICE_TYPE(SEGA_SEGACD_US, sega_segacd_us_device, "segacd_us", "Sega Sega CD (US)") +DEFINE_DEVICE_TYPE(SEGA_SEGACD_JAPAN, sega_segacd_japan_device, "segacd_japan", "Sega Mega-CD (Japan)") +DEFINE_DEVICE_TYPE(SEGA_SEGACD_EUROPE, sega_segacd_europe_device, "segacd_europe", "Sega Mega-CD (PAL)") + + +/* Callback when the genesis enters interrupt code */ +IRQ_CALLBACK_MEMBER(sega_segacd_device::segacd_sub_int_callback) +{ + if (irqline==2) + { + // clear this bit + m_a12000_halt_reset_reg &= ~0x0100; + m_scdcpu->set_input_line(2, CLEAR_LINE); + } + + return (0x60+irqline*4)/4; // vector address +} + + +TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::irq3_timer_callback ) +{ + if (m_lc89510_temp->get_segacd_irq_mask() & 0x08) + m_scdcpu->set_input_line(3, HOLD_LINE); + + m_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED); +} + +// GFX conversion +TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::stamp_timer_callback ) +{ + //printf("stamp_timer_callback\n"); + + if (m_lc89510_temp->get_segacd_irq_mask() & 0x02) + m_scdcpu->set_input_line(1, HOLD_LINE); + + segacd_conversion_active = 0; + + // this ends up as 0 after processing (soniccd bonus stage) + segacd_imagebuffer_vdot_size = 0; +} + + +void sega_segacd_device::segacd_map(address_map &map) +{ + map(0x000000, 0x07ffff).ram().share("prgram"); + map(0x080000, 0x0bffff).rw(FUNC(sega_segacd_device::segacd_sub_dataram_part1_r), FUNC(sega_segacd_device::segacd_sub_dataram_part1_w)).share("dataram"); + map(0x0c0000, 0x0dffff).rw(FUNC(sega_segacd_device::segacd_sub_dataram_part2_r), FUNC(sega_segacd_device::segacd_sub_dataram_part2_w)); //.share("dataram2"); + + map(0xfe0000, 0xfe3fff).rw(FUNC(sega_segacd_device::backupram_r), FUNC(sega_segacd_device::backupram_w)).umask16(0x00ff); // backup RAM, odd bytes only! + + map(0xff0000, 0xff3fff).m(m_rfsnd, FUNC(rf5c164_device::rf5c164_map)).umask16(0x00ff); // PCM, RF5C164 + + map(0xff8000, 0xff8001).rw(FUNC(sega_segacd_device::segacd_sub_led_ready_r), FUNC(sega_segacd_device::segacd_sub_led_ready_w)); + map(0xff8002, 0xff8003).rw(FUNC(sega_segacd_device::segacd_sub_memory_mode_r), FUNC(sega_segacd_device::segacd_sub_memory_mode_w)); + + map(0xff8004, 0xff8005).rw("tempcdc", FUNC(lc89510_temp_device::segacd_cdc_mode_address_r), FUNC(lc89510_temp_device::segacd_cdc_mode_address_w)); + map(0xff8006, 0xff8007).rw("tempcdc", FUNC(lc89510_temp_device::segacd_cdc_data_r), FUNC(lc89510_temp_device::segacd_cdc_data_w)); + map(0xff8008, 0xff8009).r("tempcdc", FUNC(lc89510_temp_device::cdc_data_sub_r)); + map(0xff800a, 0xff800b).rw(FUNC(sega_segacd_device::segacd_dmaaddr_r), FUNC(sega_segacd_device::segacd_dmaaddr_w)); // DMA Address (not CDC, used in conjunction with) + map(0xff800c, 0xff800d).rw(FUNC(sega_segacd_device::segacd_stopwatch_timer_r), FUNC(sega_segacd_device::segacd_stopwatch_timer_w));// Stopwatch timer + map(0xff800e, 0xff800f).rw(FUNC(sega_segacd_device::segacd_comms_flags_r), FUNC(sega_segacd_device::segacd_comms_flags_subcpu_w)); + map(0xff8010, 0xff801f).rw(FUNC(sega_segacd_device::segacd_comms_sub_part1_r), FUNC(sega_segacd_device::segacd_comms_sub_part1_w)); + map(0xff8020, 0xff802f).rw(FUNC(sega_segacd_device::segacd_comms_sub_part2_r), FUNC(sega_segacd_device::segacd_comms_sub_part2_w)); + map(0xff8030, 0xff8031).rw(FUNC(sega_segacd_device::segacd_irq3timer_r), FUNC(sega_segacd_device::segacd_irq3timer_w)); // Timer W/INT3 + map(0xff8032, 0xff8033).rw("tempcdc", FUNC(lc89510_temp_device::segacd_irq_mask_r), FUNC(lc89510_temp_device::segacd_irq_mask_w)); + map(0xff8034, 0xff8035).rw("tempcdc", FUNC(lc89510_temp_device::segacd_cdfader_r), FUNC(lc89510_temp_device::segacd_cdfader_w)); // CD Fader + map(0xff8036, 0xff8037).rw("tempcdc", FUNC(lc89510_temp_device::segacd_cdd_ctrl_r), FUNC(lc89510_temp_device::segacd_cdd_ctrl_w)); + map(0xff8038, 0xff8041).r("tempcdc", FUNC(lc89510_temp_device::segacd_cdd_rx_r)); + map(0xff8042, 0xff804b).w("tempcdc", FUNC(lc89510_temp_device::segacd_cdd_tx_w)); + map(0xff804d, 0xff804d).rw(FUNC(sega_segacd_device::font_color_r), FUNC(sega_segacd_device::font_color_w)); + map(0xff804e, 0xff804f).ram().share("font_bits"); + map(0xff8050, 0xff8057).r(FUNC(sega_segacd_device::font_converted_r)); + map(0xff8058, 0xff8059).rw(FUNC(sega_segacd_device::segacd_stampsize_r), FUNC(sega_segacd_device::segacd_stampsize_w)); // Stamp size + map(0xff805a, 0xff805b).rw(FUNC(sega_segacd_device::segacd_stampmap_base_address_r), FUNC(sega_segacd_device::segacd_stampmap_base_address_w)); // Stamp map base address + map(0xff805c, 0xff805d).rw(FUNC(sega_segacd_device::segacd_imagebuffer_vcell_size_r), FUNC(sega_segacd_device::segacd_imagebuffer_vcell_size_w));// Image buffer V cell size + map(0xff805e, 0xff805f).rw(FUNC(sega_segacd_device::segacd_imagebuffer_start_address_r), FUNC(sega_segacd_device::segacd_imagebuffer_start_address_w)); // Image buffer start address + map(0xff8060, 0xff8061).rw(FUNC(sega_segacd_device::segacd_imagebuffer_offset_r), FUNC(sega_segacd_device::segacd_imagebuffer_offset_w)); + map(0xff8062, 0xff8063).rw(FUNC(sega_segacd_device::segacd_imagebuffer_hdot_size_r), FUNC(sega_segacd_device::segacd_imagebuffer_hdot_size_w)); // Image buffer H dot size + map(0xff8064, 0xff8065).rw(FUNC(sega_segacd_device::segacd_imagebuffer_vdot_size_r), FUNC(sega_segacd_device::segacd_imagebuffer_vdot_size_w)); // Image buffer V dot size + map(0xff8066, 0xff8067).w(FUNC(sega_segacd_device::segacd_trace_vector_base_address_w));// Trace vector base address +// map(0xff8068, 0xff8069) // Subcode address + +// map(0xff8100, 0xff817f) // Subcode buffer area +// map(0xff8180, 0xff81ff) // mirror of subcode buffer area + +} + +void sega_segacd_device::segacd_pcm_map(address_map &map) +{ + map.unmap_value_high(); + map(0x0000, 0xffff).ram(); +} + + +// the tiles in RAM are 8x8 tiles +// they are referenced in the cell look-up map as either 16x16 or 32x32 tiles (made of 4 / 16 8x8 tiles) + +#define SEGACD_BYTES_PER_TILE16 (128) +#define SEGACD_BYTES_PER_TILE32 (512) + +#define SEGACD_NUM_TILES16 (0x40000/SEGACD_BYTES_PER_TILE16) +#define SEGACD_NUM_TILES32 (0x40000/SEGACD_BYTES_PER_TILE32) + +#define _16x16_SEQUENCE_1 { STEP8(0, 4), STEP8(512, 4) }, +#define _16x16_SEQUENCE_1_FLIP { STEP8(512+28, -4), STEP8(28, -4) }, + +#define _16x16_SEQUENCE_2 { STEP16(0, 32) }, +#define _16x16_SEQUENCE_2_FLIP { STEP16(15*32, -32) }, + + +#define _16x16_START \ +{ \ + 16,16, \ + SEGACD_NUM_TILES16, \ + 4, \ + { STEP4(0,1) }, +#define _16x16_END \ + 8*128 \ +}; +#define _32x32_START \ +{ \ + 32,32, \ + SEGACD_NUM_TILES32, \ + 4, \ + { STEP4(0,1) }, + +#define _32x32_END \ + 8*512 \ +}; + +#define _32x32_SEQUENCE_1 { STEP8(0, 4), STEP8(1024, 4), STEP8(2048, 4), STEP8(3072, 4) }, +#define _32x32_SEQUENCE_1_FLIP { STEP8(3072+28, -4), STEP8(2048+28, -4), STEP8(1024+28, -4), STEP8(28, -4) }, + +#define _32x32_SEQUENCE_2 { STEP32(0, 32) }, +#define _32x32_SEQUENCE_2_FLIP { STEP32(31*32, -32) }, + + +/* 16x16 decodes */ +static const gfx_layout sega_16x16_r00_f0_layout = +_16x16_START + _16x16_SEQUENCE_1 + _16x16_SEQUENCE_2 +_16x16_END + +static const gfx_layout sega_16x16_r01_f0_layout = +_16x16_START + _16x16_SEQUENCE_2 + _16x16_SEQUENCE_1_FLIP +_16x16_END + +static const gfx_layout sega_16x16_r10_f0_layout = +_16x16_START + _16x16_SEQUENCE_1_FLIP + _16x16_SEQUENCE_2_FLIP +_16x16_END + +static const gfx_layout sega_16x16_r11_f0_layout = +_16x16_START + _16x16_SEQUENCE_2_FLIP + _16x16_SEQUENCE_1 +_16x16_END + +static const gfx_layout sega_16x16_r00_f1_layout = +_16x16_START + _16x16_SEQUENCE_1_FLIP + _16x16_SEQUENCE_2 +_16x16_END + +static const gfx_layout sega_16x16_r01_f1_layout = +_16x16_START + _16x16_SEQUENCE_2 + _16x16_SEQUENCE_1 +_16x16_END + +static const gfx_layout sega_16x16_r10_f1_layout = +_16x16_START + _16x16_SEQUENCE_1 + _16x16_SEQUENCE_2_FLIP +_16x16_END + +static const gfx_layout sega_16x16_r11_f1_layout = +_16x16_START + _16x16_SEQUENCE_2_FLIP + _16x16_SEQUENCE_1_FLIP +_16x16_END + +/* 32x32 decodes */ +static const gfx_layout sega_32x32_r00_f0_layout = +_32x32_START + _32x32_SEQUENCE_1 + _32x32_SEQUENCE_2 +_32x32_END + +static const gfx_layout sega_32x32_r01_f0_layout = +_32x32_START + _32x32_SEQUENCE_2 + _32x32_SEQUENCE_1_FLIP +_32x32_END + +static const gfx_layout sega_32x32_r10_f0_layout = +_32x32_START + _32x32_SEQUENCE_1_FLIP + _32x32_SEQUENCE_2_FLIP +_32x32_END + +static const gfx_layout sega_32x32_r11_f0_layout = +_32x32_START + _32x32_SEQUENCE_2_FLIP + _32x32_SEQUENCE_1 +_32x32_END + +static const gfx_layout sega_32x32_r00_f1_layout = +_32x32_START + _32x32_SEQUENCE_1_FLIP + _32x32_SEQUENCE_2 +_32x32_END + +static const gfx_layout sega_32x32_r01_f1_layout = +_32x32_START + _32x32_SEQUENCE_2 + _32x32_SEQUENCE_1 +_32x32_END + +static const gfx_layout sega_32x32_r10_f1_layout = +_32x32_START + _32x32_SEQUENCE_1 + _32x32_SEQUENCE_2_FLIP +_32x32_END + +static const gfx_layout sega_32x32_r11_f1_layout = +_32x32_START + _32x32_SEQUENCE_2_FLIP + _32x32_SEQUENCE_1_FLIP +_32x32_END + +static GFXDECODE_START( gfx_segacd ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r00_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r01_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r10_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r11_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r00_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r11_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r10_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r01_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r00_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r01_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r10_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r11_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r00_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r11_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r10_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) + GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r01_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) +GFXDECODE_END + + +void sega_segacd_device::device_add_mconfig(machine_config &config) +{ + M68000(config, m_scdcpu, SEGACD_CLOCK); /* 12.5 MHz */ + m_scdcpu->set_addrmap(AS_PROGRAM, &sega_segacd_device::segacd_map); + m_scdcpu->set_irq_acknowledge_callback(FUNC(sega_segacd_device::segacd_sub_int_callback)); + + LC89510(config, "cdc", 0); // cd controller + + // temporary until things are cleaned up + LC89510_TEMP(config, m_lc89510_temp, 0); // cd controller + m_lc89510_temp->set_cdc_do_dma_callback(FUNC(sega_segacd_device::SegaCD_CDC_Do_DMA)); // hack + m_lc89510_temp->set_cdrom_tag("^cdrom"); + m_lc89510_temp->set_68k_tag(m_scdcpu); + + TIMER(config, m_stopwatch_timer).configure_generic(nullptr); //stopwatch timer + TIMER(config, m_stamp_timer).configure_generic(FUNC(sega_segacd_device::stamp_timer_callback)); + TIMER(config, m_irq3_timer).configure_generic(FUNC(sega_segacd_device::irq3_timer_callback)); + TIMER(config, m_dma_timer).configure_generic(FUNC(sega_segacd_device::dma_timer_callback)); + + config.set_default_layout(layout_megacd); + + RF5C164(config, m_rfsnd, SEGACD_CLOCK); // or Sega 315-5476A + m_rfsnd->add_route( 0, ":lspeaker", 0.50 ); + m_rfsnd->add_route( 1, ":rspeaker", 0.50 ); + m_rfsnd->set_addrmap(0, &sega_segacd_device::segacd_pcm_map); + + NVRAM(config, "backupram", nvram_device::DEFAULT_ALL_0); +} + + +sega_segacd_device::sega_segacd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , device_gfx_interface(mconfig, *this, gfx_segacd) + , device_video_interface(mconfig, *this, false) + , m_scdcpu(*this, "segacd_68k") + , m_hostcpu(*this, finder_base::DUMMY_TAG) + , m_rfsnd(*this, "rfsnd") + , m_lc89510_temp(*this, "tempcdc") + , m_stopwatch_timer(*this, "sw_timer") + , m_stamp_timer(*this, "stamp_timer") + , m_irq3_timer(*this, "irq3_timer") + , m_dma_timer(*this, "dma_timer") + , m_prgram(*this, "prgram") + , m_dataram(*this, "dataram") + , m_font_bits(*this, "font_bits") + , m_red_led(*this, "red_led") + , m_green_led(*this, "green_led") +{ +} + +sega_segacd_us_device::sega_segacd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sega_segacd_device(mconfig, SEGA_SEGACD_US, tag, owner, clock) +{ +} + +sega_segacd_japan_device::sega_segacd_japan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sega_segacd_device(mconfig, SEGA_SEGACD_JAPAN, tag, owner, clock) +{ +} + +sega_segacd_europe_device::sega_segacd_europe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sega_segacd_device(mconfig, SEGA_SEGACD_EUROPE, tag, owner, clock) +{ +} + + +inline void sega_segacd_device::write_pixel(uint8_t pix, int pixeloffset) +{ + int shift = 12-(4*(pixeloffset&0x3)); + uint16_t datamask = (0x000f) << shift; + + int offset = pixeloffset>>3; + if (pixeloffset&4) offset++; + + offset &=0x1ffff; + + switch (segacd_memory_priority_mode) + { + case 0x00: // normal write, just write the data + m_dataram[offset] = m_dataram[offset] &~ datamask; + m_dataram[offset] |= pix << shift; + break; + + case 0x01: // underwrite, only write if the existing data is 0 + if ((m_dataram[offset]&datamask) == 0x0000) + { + m_dataram[offset] = m_dataram[offset] &~ datamask; + m_dataram[offset] |= pix << shift; + } + break; + + case 0x02: // overwrite, only write non-zero data + if (pix) + { + m_dataram[offset] = m_dataram[offset] &~ datamask; + m_dataram[offset] |= pix << shift; + } + break; + + default: + case 0x03: + pix = machine().rand() & 0x000f; + m_dataram[offset] = m_dataram[offset] &~ datamask; + m_dataram[offset] |= pix << shift; + break; + + } +} + +// 1meg / 2meg swap is interleaved swap, not half/half of the ram? +// Wily Beamish and Citizen X appear to rely on this +// however, it breaks the megacdj bios (megacd2j still works!) +// (maybe that's a timing issue instead?) +uint16_t sega_segacd_device::segacd_1meg_mode_word_read(offs_t offset) +{ + offset *= 2; + + if ((offset&0x20000)) + offset +=1; + + offset &=0x1ffff; + + return m_dataram[offset]; +} + + +void sega_segacd_device::segacd_1meg_mode_word_write(offs_t offset, uint16_t data, uint16_t mem_mask, int use_pm) +{ + offset *= 2; + + if ((offset&0x20000)) + offset +=1; + + offset &=0x1ffff; + + if (use_pm) + { + // priority mode can apply when writing with the double up buffer mode + // Jaguar XJ220 relies on this + switch (segacd_memory_priority_mode) + { + case 0x00: // normal write, just write the data + COMBINE_DATA(&m_dataram[offset]); + break; + + case 0x01: // underwrite, only write if the existing data is 0 + if (ACCESSING_BITS_8_15) + { + if ((m_dataram[offset]&0xf000) == 0x0000) m_dataram[offset] |= (data)&0xf000; + if ((m_dataram[offset]&0x0f00) == 0x0000) m_dataram[offset] |= (data)&0x0f00; + } + if (ACCESSING_BITS_0_7) + { + if ((m_dataram[offset]&0x00f0) == 0x0000) m_dataram[offset] |= (data)&0x00f0; + if ((m_dataram[offset]&0x000f) == 0x0000) m_dataram[offset] |= (data)&0x000f; + } + break; + + case 0x02: // overwrite, only write non-zero data + if (ACCESSING_BITS_8_15) + { + if ((data)&0xf000) m_dataram[offset] = (m_dataram[offset] & 0x0fff) | ((data)&0xf000); + if ((data)&0x0f00) m_dataram[offset] = (m_dataram[offset] & 0xf0ff) | ((data)&0x0f00); + } + if (ACCESSING_BITS_0_7) + { + if ((data)&0x00f0) m_dataram[offset] = (m_dataram[offset] & 0xff0f) | ((data)&0x00f0); + if ((data)&0x000f) m_dataram[offset] = (m_dataram[offset] & 0xfff0) | ((data)&0x000f); + } + break; + + default: + case 0x03: // invalid? + COMBINE_DATA(&m_dataram[offset]); + break; + + } + } + else + { + COMBINE_DATA(&m_dataram[offset]); + } +} + + + + +void sega_segacd_device::scd_a12000_halt_reset_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + uint16_t old_halt = m_a12000_halt_reset_reg; + + COMBINE_DATA(&m_a12000_halt_reset_reg); + + if (ACCESSING_BITS_0_7) + { + // reset line + if (m_a12000_halt_reset_reg & 0x0001) + { + m_scdcpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + if (!(old_halt&0x0001)) printf("clear reset slave\n"); + } + else + { + m_scdcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + if ((old_halt&0x0001)) printf("assert reset slave\n"); + } + + // request BUS + if (m_a12000_halt_reset_reg & 0x0002) + { + m_scdcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); + if (!(old_halt&0x0002)) printf("halt slave\n"); + } + else + { + m_scdcpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); + if ((old_halt&0x0002)) printf("resume slave\n"); + } + } + + if (ACCESSING_BITS_8_15) + { + // from master CPU + if (m_a12000_halt_reset_reg & 0x0100 && m_lc89510_temp->get_segacd_irq_mask() & 0x04) + m_scdcpu->set_input_line(2, HOLD_LINE); + + if (m_a12000_halt_reset_reg & 0x8000) + { + // not writable.. but can read irq mask here? + //printf("m_a12000_halt_reset_reg & 0x8000 set\n"); // irq2 mask? + } + + + } +} + +uint16_t sega_segacd_device::scd_a12000_halt_reset_r() +{ + return m_a12000_halt_reset_reg; +} + + +/******************************************************************************** + MEMORY MODE CONTROL + - main / sub sides differ! +********************************************************************************/ + +// +// we might need a delay on the segacd_maincpu_has_ram_access registers, as they actually indicate requests being made +// so probably don't change instantly... +// + + +uint16_t sega_segacd_device::scd_a12002_memory_mode_r() +{ + int temp = scd_rammode; + int temp2 = 0; + + temp2 |= (scd_mode_dmna_ret_flags>>(temp*4))&0x7; + + return (segacd_ram_writeprotect_bits << 8) | + (segacd_4meg_prgbank << 6) | + temp2; + +} + + +/* I'm still not 100% clear how this works, the sources I have are a bit vague, + it might still be incorrect in both modes + + for a simple way to swap blocks of ram between cpus this is stupidly convoluted + + */ + +// DMNA = Decleration Mainram No Access (bit 0) +// RET = Return access (bit 1) + + +void sega_segacd_device::scd_a12002_memory_mode_w_8_15(u8 data) +{ + if (data & 0xff00) + { + printf("write protect bits set %02x\n", data); + } + + segacd_ram_writeprotect_bits = data; +} + + +void sega_segacd_device::scd_a12002_memory_mode_w_0_7(u8 data) +{ + //printf("scd_a12002_memory_mode_w_0_7 %04x\n",data); + + segacd_4meg_prgbank = (data&0x00c0)>>6; + + if (scd_rammode&0x2) + { // ==0x2 (1 meg mode) + if (!(data&2)) // check DMNA bit + { + scd_mode_dmna_ret_flags |= 0x2200; + } + } + else // == 0x0 (2 meg mode) + { + if (data&2) // check DMNA bit + { + scd_rammode = 1; + } + } +} + + +void sega_segacd_device::scd_a12002_memory_mode_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_8_15) + scd_a12002_memory_mode_w_8_15(data>>8); + + if (ACCESSING_BITS_0_7) + scd_a12002_memory_mode_w_0_7(data&0xff); +} + + + + +uint16_t sega_segacd_device::segacd_sub_memory_mode_r() +{ + int temp = scd_rammode; + int temp2 = 0; + + temp2 |= (scd_mode_dmna_ret_flags>>(temp*4))&0x7; + + return (segacd_ram_writeprotect_bits << 8) | + (segacd_memory_priority_mode << 3) | + temp2; +} + + +void sega_segacd_device::segacd_sub_memory_mode_w_8_15(u8 data) +{ + /* setting write protect bits from sub-cpu has no effect? */ +} + + + +void sega_segacd_device::segacd_sub_memory_mode_w_0_7(u8 data) +{ + segacd_memory_priority_mode = (data&0x0018)>>3; + + // If the mode bit is 0 then we're requesting a change to + // 2Meg mode? + + //printf("segacd_sub_memory_mode_w_0_7 %04x\n",data); + + if (!(data&4)) // check ram mode bit + { // == 0x0 - 2 meg mode + scd_mode_dmna_ret_flags &= 0xddff; + + if (data&1) // check RET + { + // If RET is set and the Mode bit in the write is set to 2M then we want to change to 2M mode + // If we're already in 2M mode it has no effect + scd_rammode = 0; + + } + else + { + // == 0x4 - 1 meg mode + + int temp = scd_rammode; + if (temp&2) // check ram mode + { // == 0x2 - 1 meg mode + scd_mode_dmna_ret_flags &= 0xffde; + scd_rammode = temp &1; + } + } + } + else + { // == 0x4 - 1 meg mode + data &=1; + int temp = data; + int scd_rammode_old = scd_rammode; + data |=2; + + temp ^= scd_rammode_old; + scd_rammode = data; + + if (scd_rammode_old & 2) + { // == 0x2 - already in 1 meg mode + if (temp & 1) // ret bit + { + scd_mode_dmna_ret_flags &= 0xddff; + } + } + else + { // == 0x0 - currently in 2 meg mode + scd_mode_dmna_ret_flags &= 0xddff; + } + } +} + +void sega_segacd_device::segacd_sub_memory_mode_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + //printf("segacd_sub_memory_mode_w %04x %04x\n", data, mem_mask); + + + if (ACCESSING_BITS_8_15) + segacd_sub_memory_mode_w_8_15(data>>8); + + if (ACCESSING_BITS_0_7) + segacd_sub_memory_mode_w_0_7(data&0xff); +} + + +/******************************************************************************** + END MEMORY MODE CONTROL +********************************************************************************/ + +/******************************************************************************** + COMMUNICATION FLAGS + - main / sub sides differ in which bits are write only +********************************************************************************/ + + +uint16_t sega_segacd_device::segacd_comms_flags_r() +{ + return segacd_comms_flags; +} + +void sega_segacd_device::segacd_comms_flags_subcpu_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_8_15) // Dragon's Lair + { + segacd_comms_flags = (segacd_comms_flags & 0xff00) | ((data >> 8) & 0x00ff); + } + + // flashback needs low bits to take priority in word writes + if (ACCESSING_BITS_0_7) + { + segacd_comms_flags = (segacd_comms_flags & 0xff00) | (data & 0x00ff); + } +} + +void sega_segacd_device::segacd_comms_flags_maincpu_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_8_15) + { + segacd_comms_flags = (segacd_comms_flags & 0x00ff) | (data & 0xff00); + } + + // flashback needs low bits to take priority in word writes + if (ACCESSING_BITS_0_7) + { + segacd_comms_flags = (segacd_comms_flags & 0x00ff) | ((data << 8) & 0xff00); + } +} + +uint16_t sega_segacd_device::scd_4m_prgbank_ram_r(offs_t offset) +{ + uint32_t realoffset = ((segacd_4meg_prgbank * 0x20000)/2) + offset; + return m_prgram[realoffset]; + +} + +void sega_segacd_device::scd_4m_prgbank_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + uint32_t realoffset = ((segacd_4meg_prgbank * 0x20000)/2) + offset; + + // todo: + // check for write protection? (or does that only apply to writes on the SubCPU side? + + COMBINE_DATA(&m_prgram[realoffset]); + +} + + + +uint16_t sega_segacd_device::segacd_comms_main_part1_r(offs_t offset) +{ + return segacd_comms_part1[offset]; +} + +void sega_segacd_device::segacd_comms_main_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&segacd_comms_part1[offset]); +} + +uint16_t sega_segacd_device::segacd_comms_main_part2_r(offs_t offset) +{ + return segacd_comms_part2[offset]; +} + +void sega_segacd_device::segacd_comms_main_part2_w(uint16_t data) +{ + printf("Sega CD main CPU attempting to write to read only comms regs\n"); +} + + +uint16_t sega_segacd_device::segacd_comms_sub_part1_r(offs_t offset) +{ + return segacd_comms_part1[offset]; +} + +void sega_segacd_device::segacd_comms_sub_part1_w(uint16_t data) +{ + printf("Sega CD sub CPU attempting to write to read only comms regs\n"); +} + +uint16_t sega_segacd_device::segacd_comms_sub_part2_r(offs_t offset) +{ + return segacd_comms_part2[offset]; +} + +void sega_segacd_device::segacd_comms_sub_part2_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&segacd_comms_part2[offset]); +} + + +uint16_t sega_segacd_device::segacd_main_dataram_part1_r(offs_t offset) +{ + if ((scd_rammode&2)==RAM_MODE_2MEG) + { + // is this correct? + if (!(scd_rammode&1)) + { + //printf("segacd_main_dataram_part1_r in mode 0 %08x %04x\n", offset*2, m_dataram[offset]); + + return m_dataram[offset]; + + } + else + { + //printf("Illegal: segacd_main_dataram_part1_r in mode 0 without permission\n"); + return 0xffff; + } + + } + else if ((scd_rammode&2)==RAM_MODE_1MEG) + { + if (offset<0x20000/2) + { + // wordram accees + //printf("Unsupported: segacd_main_dataram_part1_r (word RAM) in mode 1\n"); + + // ret bit set by sub cpu determines which half of WorkRAM we have access to? + if (scd_rammode&1) + { + return segacd_1meg_mode_word_read(offset+0x20000/2); + } + else + { + return segacd_1meg_mode_word_read(offset+0x00000/2); + } + + } + else + { + // converts data stored in bitmap format (in dataram) to be read out as tiles (for dma->vram purposes) + // used by Heart of the Alien + + if(offset<0x30000/2) /* 0x20000 - 0x2ffff */ // 512x256 bitmap. tiles + offset = bitswap<24>(offset,23,22,21,20,19,18,17,16,15,8,7,6,5,4,3,2,1,14,13,12,11,10,9,0); + else if(offset<0x38000/2) /* 0x30000 - 0x37fff */ // 512x128 bitmap. tiles + offset = bitswap<24>(offset,23,22,21,20,19,18,17,16,15,14,7,6,5,4,3,2,1,13,12,11,10,9,8,0); + else if(offset<0x3c000/2) /* 0x38000 - 0x3bfff */ // 512x64 bitmap. tiles + offset = bitswap<24>(offset,23,22,21,20,19,18,17,16,15,14,13,6,5,4,3,2,1,12,11,10,9,8,7,0); + else /* 0x3c000 - 0x3dfff and 0x3e000 - 0x3ffff */ // 512x32 bitmap (x2) -> tiles + offset = bitswap<24>(offset,23,22,21,20,19,18,17,16,15,14,13,12,5,4,3,2,1,11,10,9,8,7,6,0); + + offset &=0xffff; + // HOTA cares about this + if (!(scd_rammode&1)) + { + return segacd_1meg_mode_word_read(offset+0x00000/2); + } + else + { + return segacd_1meg_mode_word_read(offset+0x20000/2); + } + } + } + + return 0x0000; +} + +void sega_segacd_device::segacd_main_dataram_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if ((scd_rammode&2)==RAM_MODE_2MEG) + { + // is this correct? + if (!(scd_rammode&1)) + { + COMBINE_DATA(&m_dataram[offset]); + segacd_mark_tiles_dirty(offset); + } + else + { + //printf("Illegal: segacd_main_dataram_part1_w in mode 0 without permission\n"); + } + + } + else if ((scd_rammode&2)==RAM_MODE_1MEG) + { + if (offset<0x20000/2) + { + //printf("Unsupported: segacd_main_dataram_part1_w (word RAM) in mode 1\n"); + // wordram accees + + // ret bit set by sub cpu determines which half of WorkRAM we have access to? + if (scd_rammode&1) + { + segacd_1meg_mode_word_write(offset+0x20000/2, data, mem_mask, 0); + } + else + { + segacd_1meg_mode_word_write(offset+0x00000/2, data, mem_mask, 0); + } + } + else + { + // printf("Unsupported: segacd_main_dataram_part1_w (Cell rearranged RAM) in mode 1 (illega?)\n"); // is this legal?? + } + } +} + +uint16_t sega_segacd_device::scd_hint_vector_r(offs_t offset) +{ +// printf("read HINT offset %d\n", offset); + + switch (offset&1) + { + case 0x00: + //return 0x00ff; // doesn't make much sense.. + return 0xffff; + case 0x01: + return segacd_hint_register; + } + + return 0; + +} + +uint16_t sega_segacd_device::scd_a12006_hint_register_r() +{ + return segacd_hint_register; +} + +void sega_segacd_device::scd_a12006_hint_register_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&segacd_hint_register); +} + + +void sega_segacd_device::segacd_mark_tiles_dirty(int offset) +{ + gfx(0)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); + gfx(1)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); + gfx(2)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); + gfx(3)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); + gfx(4)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); + gfx(5)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); + gfx(6)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); + gfx(7)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); + + gfx(8)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); + gfx(9)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); + gfx(10)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); + gfx(11)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); + gfx(12)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); + gfx(13)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); + gfx(14)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); + gfx(15)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); +} + + +// mame specific.. map registers to which tilemap cache we use +int sega_segacd_device::segacd_get_active_stampmap_tilemap(void) +{ + return (segacd_stampsize & 0x6)>>1; +} + + + +void sega_segacd_device::SCD_GET_TILE_INFO_16x16_1x1( int& tile_region, int& tileno, int tile_index ) +{ + tile_region = 0; // 16x16 tiles + int tile_base = (segacd_stampmap_base_address & 0xff80) * 4; + + int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; + tileno = tiledat & 0x07ff; + int xflip = tiledat & 0x8000; + int roll = (tiledat & 0x6000)>>13; + + if (xflip) tile_region += 4; + tile_region+=roll; +} + +void sega_segacd_device::SCD_GET_TILE_INFO_32x32_1x1( int& tile_region, int& tileno, int tile_index ) +{ + tile_region = 8; // 32x32 tiles + int tile_base = (segacd_stampmap_base_address & 0xffe0) * 4; + + int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; + tileno = (tiledat & 0x07fc)>>2; + int xflip = tiledat & 0x8000; + int roll = (tiledat & 0x6000)>>13; + + if (xflip) tile_region += 4; + tile_region+=roll; +} + + +void sega_segacd_device::SCD_GET_TILE_INFO_16x16_16x16( int& tile_region, int& tileno, int tile_index ) +{ + tile_region = 0; // 16x16 tiles + int tile_base = (0x8000) * 4; // fixed address in this mode + + int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; + tileno = tiledat & 0x07ff; + int xflip = tiledat & 0x8000; + int roll = (tiledat & 0x6000)>>13; + + if (xflip) tile_region += 4; + tile_region+=roll; +} + + +void sega_segacd_device::SCD_GET_TILE_INFO_32x32_16x16( int& tile_region, int& tileno, int tile_index ) +{ + tile_region = 8; // 32x32 tiles + int tile_base = (segacd_stampmap_base_address & 0xe000) * 4; + + int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; + tileno = (tiledat & 0x07fc)>>2; + int xflip = tiledat & 0x8000; + int roll = (tiledat & 0x6000)>>13; + + if (xflip) tile_region += 4; + tile_region+=roll; +} + +/* Tilemap callbacks (we don't actually use the tilemaps due to the excessive overhead */ + + + +TILE_GET_INFO_MEMBER( sega_segacd_device::get_stampmap_16x16_1x1_tile_info ) +{ + int tile_region, tileno; + SCD_GET_TILE_INFO_16x16_1x1(tile_region,tileno,(int)tile_index); + tileinfo.set(tile_region, tileno, 0, 0); +} + +TILE_GET_INFO_MEMBER( sega_segacd_device::get_stampmap_32x32_1x1_tile_info ) +{ + int tile_region, tileno; + SCD_GET_TILE_INFO_32x32_1x1(tile_region,tileno,(int)tile_index); + tileinfo.set(tile_region, tileno, 0, 0); +} + + +TILE_GET_INFO_MEMBER( sega_segacd_device::get_stampmap_16x16_16x16_tile_info ) +{ + int tile_region, tileno; + SCD_GET_TILE_INFO_16x16_16x16(tile_region,tileno,(int)tile_index); + tileinfo.set(tile_region, tileno, 0, 0); +} + +TILE_GET_INFO_MEMBER( sega_segacd_device::get_stampmap_32x32_16x16_tile_info ) +{ + int tile_region, tileno; + SCD_GET_TILE_INFO_32x32_16x16(tile_region,tileno,(int)tile_index); + tileinfo.set(tile_region, tileno, 0, 0); +} + +// non-tilemap functions to get a pixel from a 'tilemap' based on the above, but looking up each pixel, as to avoid the heavy cache bitmap + +inline uint8_t sega_segacd_device::get_stampmap_16x16_1x1_tile_info_pixel(int xpos, int ypos) +{ + const int tilesize = 4; // 0xf pixels + const int tilemapsize = 0x0f; + + int wraparound = segacd_stampsize&1; + + int xtile = xpos >> tilesize; + int ytile = ypos >> tilesize; + + if (wraparound) + { + // wrap... + xtile &= tilemapsize; + ytile &= tilemapsize; + } + else + { + if (xtile>tilemapsize) return 0; + if (xtile<0) return 0; + + if (ytile>tilemapsize) return 0; + if (ytile<0) return 0; + } + + int tile_index = (ytile * (tilemapsize+1)) + xtile; + + int tile_region, tileno; + SCD_GET_TILE_INFO_16x16_1x1(tile_region,tileno,(int)tile_index); + + tileno %= gfx(tile_region)->elements(); + + if (tileno==0) return 0x00; + + const uint8_t* srcdata = gfx(tile_region)->get_data(tileno); + return srcdata[((ypos&((1<> tilesize; + int ytile = ypos >> tilesize; + + if (wraparound) + { + // wrap... + xtile &= tilemapsize; + ytile &= tilemapsize; + } + else + { + if (xtile>tilemapsize) return 0; + if (xtile<0) return 0; + + if (ytile>tilemapsize) return 0; + if (ytile<0) return 0; + } + + int tile_index = (ytile * (tilemapsize+1)) + xtile; + + int tile_region, tileno; + SCD_GET_TILE_INFO_32x32_1x1(tile_region,tileno,(int)tile_index); + + tileno %= gfx(tile_region)->elements(); + + if (tileno==0) return 0x00; // does this apply in this mode? + + const uint8_t* srcdata = gfx(tile_region)->get_data(tileno); + return srcdata[((ypos&((1<> tilesize; + int ytile = ypos >> tilesize; + + if (wraparound) + { + // wrap... + xtile &= tilemapsize; + ytile &= tilemapsize; + } + else + { + if (xtile>tilemapsize) return 0; + if (xtile<0) return 0; + + if (ytile>tilemapsize) return 0; + if (ytile<0) return 0; + } + + int tile_index = (ytile * (tilemapsize+1)) + xtile; + + int tile_region, tileno; + SCD_GET_TILE_INFO_16x16_16x16(tile_region,tileno,(int)tile_index); + + tileno %= gfx(tile_region)->elements(); + + if (tileno==0) return 0x00; // does this apply in this mode + + const uint8_t* srcdata = gfx(tile_region)->get_data(tileno); + return srcdata[((ypos&((1<> tilesize; + int ytile = ypos >> tilesize; + + if (wraparound) + { + // wrap... + xtile &= tilemapsize; + ytile &= tilemapsize; + } + else + { + if (xtile>tilemapsize) return 0; + if (xtile<0) return 0; + + if (ytile>tilemapsize) return 0; + if (ytile<0) return 0; + } + + int tile_index = (ytile * (tilemapsize+1)) + xtile; + + int tile_region, tileno; + SCD_GET_TILE_INFO_32x32_16x16(tile_region,tileno,(int)tile_index); + + tileno %= gfx(tile_region)->elements(); + + if (tileno==0) return 0x00; + + const uint8_t* srcdata = gfx(tile_region)->get_data(tileno); + return srcdata[((ypos&((1<reset(); + else + printf("Stopwatch timer %04x\n",data); +} + +uint16_t sega_segacd_device::segacd_stopwatch_timer_r() +{ + int32_t result = (m_stopwatch_timer->time_elapsed() * ATTOSECONDS_TO_HZ(ATTOSECONDS_IN_USEC(30.72))).as_double(); + + return result & 0xfff; +} + + + + + + + +uint16_t sega_segacd_device::segacd_sub_led_ready_r(offs_t offset, uint16_t mem_mask) +{ + uint16_t retdata = 0x0000; + + if (ACCESSING_BITS_0_7) + { + retdata |= segacd_ready; + } + + if (ACCESSING_BITS_8_15) + { + retdata |= segacd_redled << 8; + retdata |= segacd_greenled << 9; + } + + return retdata; +} + +void sega_segacd_device::segacd_sub_led_ready_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_0_7) + { + if ((data&0x01) == 0x00) + { + // reset CD unit + } + } + + if (ACCESSING_BITS_8_15) + { + segacd_redled = (data >> 8)&1; + segacd_greenled = (data >> 9)&1; + + m_red_led = segacd_redled ^ 1; + m_green_led = segacd_greenled ^ 1; + } +} + + + +uint16_t sega_segacd_device::segacd_sub_dataram_part1_r(offs_t offset) +{ + if ((scd_rammode&2)==RAM_MODE_2MEG) + { + // is this correct? + if (scd_rammode&1) + return m_dataram[offset]; + else + { + //printf("Illegal: segacd_sub_dataram_part1_r in mode 0 without permission\n"); + return 0x0000; + } + } + else if ((scd_rammode&2)==RAM_MODE_1MEG) + { +// printf("Unsupported: segacd_sub_dataram_part1_r in mode 1 (Word RAM Expander - 1 Byte Per Pixel)\n"); + uint16_t data; + + if (scd_rammode&1) + { + data = segacd_1meg_mode_word_read(offset/2+0x00000/2); + } + else + { + data = segacd_1meg_mode_word_read(offset/2+0x20000/2); + } + + if (offset&1) + { + return ((data & 0x00f0) << 4) | ((data & 0x000f) << 0); + } + else + { + return ((data & 0xf000) >> 4) | ((data & 0x0f00) >> 8); + } + + + } + + return 0x0000; +} + +void sega_segacd_device::segacd_sub_dataram_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if ((scd_rammode&2)==RAM_MODE_2MEG) + { + // is this correct? + if (scd_rammode&1) + { + COMBINE_DATA(&m_dataram[offset]); + segacd_mark_tiles_dirty(offset); + } + else + { + //printf("Illegal: segacd_sub_dataram_part1_w in mode 0 without permission\n"); + } + } + else if ((scd_rammode&2)==RAM_MODE_1MEG) + { + //if (mem_mask==0xffff) + // printf("Unsupported: segacd_sub_dataram_part1_w in mode 1 (Word RAM Expander - 1 Byte Per Pixel) %04x %04x\n", data, mem_mask); + + data = (data & 0x000f) | (data & 0x0f00)>>4; + mem_mask = (mem_mask & 0x000f) | (mem_mask & 0x0f00)>>4; + +// data = ((data & 0x00f0) >>4) | (data & 0xf000)>>8; +// mem_mask = ((mem_mask & 0x00f0)>>4) | ((mem_mask & 0xf000)>>8); + + + if (!(offset&1)) + { + data <<=8; + mem_mask <<=8; + } + + if (scd_rammode&1) + { + segacd_1meg_mode_word_write(offset/2+0x00000/2, data , mem_mask, 1); + } + else + { + segacd_1meg_mode_word_write(offset/2+0x20000/2, data, mem_mask, 1); + } + + // printf("Unsupported: segacd_sub_dataram_part1_w in mode 1 (Word RAM Expander - 1 Byte Per Pixel) %04x\n", data); + } +} + +uint16_t sega_segacd_device::segacd_sub_dataram_part2_r(offs_t offset) +{ + if ((scd_rammode&2)==RAM_MODE_2MEG) + { + //printf("ILLEGAL segacd_sub_dataram_part2_r in mode 0\n"); // not mapped to anything in mode 0 + return 0x0000; + } + else if ((scd_rammode&2)==RAM_MODE_1MEG) + { + //printf("Unsupported: segacd_sub_dataram_part2_r in mode 1 (Word RAM)\n"); + // ret bit set by sub cpu determines which half of WorkRAM we have access to? + if (scd_rammode&1) + { + return segacd_1meg_mode_word_read(offset+0x00000/2); + } + else + { + return segacd_1meg_mode_word_read(offset+0x20000/2); + } + + } + + return 0x0000; +} + +void sega_segacd_device::segacd_sub_dataram_part2_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if ((scd_rammode&2)==RAM_MODE_2MEG) + { + printf("ILLEGAL segacd_sub_dataram_part2_w in mode 0\n"); // not mapped to anything in mode 0 + } + else if ((scd_rammode&2)==RAM_MODE_1MEG) + { + //printf("Unsupported: segacd_sub_dataram_part2_w in mode 1 (Word RAM)\n"); + // ret bit set by sub cpu determines which half of WorkRAM we have access to? + if (scd_rammode&1) + { + segacd_1meg_mode_word_write(offset+0x00000/2, data, mem_mask, 0); + } + else + { + segacd_1meg_mode_word_write(offset+0x20000/2, data, mem_mask, 0); + } + + } +} + + + +uint16_t sega_segacd_device::segacd_stampsize_r() +{ + uint16_t retdata = 0x0000; + + retdata |= segacd_conversion_active<<15; + + retdata |= segacd_stampsize & 0x7; + + return retdata; + +} + +void sega_segacd_device::segacd_stampsize_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + //printf("segacd_stampsize_w %04x %04x\n",data, mem_mask); + if (ACCESSING_BITS_0_7) + { + segacd_stampsize = data & 0x07; + //if (data & 0xf8) + // printf(" unused bits (LSB) set in stampsize!\n"); + + //if (data&1) printf(" Repeat On\n"); + //else printf(" Repeat Off\n"); + + //if (data&2) printf(" 32x32 dots\n"); + //else printf(" 16x16 dots\n"); + + //if (data&4) printf(" 16x16 screens\n"); + //else printf(" 1x1 screen\n"); + } + + if (ACCESSING_BITS_8_15) + { + //if (data&0xff00) printf(" unused bits (MSB) set in stampsize!\n"); + } +} + +// these functions won't cope if +// +// the lower 3 bits of segacd_imagebuffer_hdot_size are set + +// this really needs to be doing it's own lookups rather than depending on the inefficient MAME cache.. +inline uint8_t sega_segacd_device::read_pixel_from_stampmap(bitmap_ind16* srcbitmap, int x, int y) +{ +/* + if (!srcbitmap) + { + return machine().rand(); + } + + if (x >= srcbitmap->width) return 0; + if (y >= srcbitmap->height) return 0; + + uint16_t* cacheptr = &srcbitmap->pix(y, x); + + return cacheptr[0] & 0xf; +*/ + + switch (segacd_get_active_stampmap_tilemap()&3) + { + case 0x00: return get_stampmap_16x16_1x1_tile_info_pixel( x, y ); + case 0x01: return get_stampmap_32x32_1x1_tile_info_pixel( x, y ); + case 0x02: return get_stampmap_16x16_16x16_tile_info_pixel( x, y ); + case 0x03: return get_stampmap_32x32_16x16_tile_info_pixel( x, y ); + } + + return 0; +} + + + + + +// this triggers the conversion operation, which will cause an IRQ1 when finished +void sega_segacd_device::segacd_trace_vector_base_address_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if ((scd_rammode&2)==RAM_MODE_1MEG) + { + printf("ILLEGAL: segacd_trace_vector_base_address_w %04x %04x in mode 1!\n",data,mem_mask); + } + + //printf("segacd_trace_vector_base_address_w %04x %04x\n",data,mem_mask); + + { + int base = (data & 0xfffe) * 4; + + //printf("actual base = %06x\n", base + 0x80000); + + // nasty nasty nasty + //segacd_mark_stampmaps_dirty(); + + segacd_conversion_active = 1; + + // todo: proper time calculation + m_stamp_timer->adjust(attotime::from_nsec(30000)); + + + + int line; + //bitmap_ind16 *srcbitmap = segacd_stampmap[segacd_get_active_stampmap_tilemap(->pixmap()]); + bitmap_ind16 *srcbitmap = nullptr; + uint32_t bufferstart = ((segacd_imagebuffer_start_address&0xfff8)*2)<<3; + + for (line=0;line>1]; + tilemapyoffs = m_dataram[(currbase+0x2)>>1]; + deltax = m_dataram[(currbase+0x4)>>1]; // x-zoom + deltay = m_dataram[(currbase+0x6)>>1]; // rotation + + //printf("%06x: %04x (%d) %04x (%d) %04x %04x\n", currbase, tilemapxoffs, tilemapxoffs>>3, tilemapyoffs, tilemapyoffs>>3, deltax, deltay); + + int xbase = tilemapxoffs * 256; + int ybase = tilemapyoffs * 256; + int count; + + for (count=0;count<(segacd_imagebuffer_hdot_size);count++) + { + //int i; + uint8_t pix = 0x0; + + pix = read_pixel_from_stampmap(srcbitmap, xbase>>(3+8), ybase>>(3+8)); + + xbase += deltax; + ybase += deltay; + + // clamp to 24-bits, seems to be required for all the intro effects to work + xbase &= 0xffffff; + ybase &= 0xffffff; + + int countx = count + (segacd_imagebuffer_offset&0x7); + + uint32_t offset; + + offset = bufferstart+((((segacd_imagebuffer_vcell_size+1)*0x10)*(countx>>3))<<3); + + offset+= ((line*2)<<3); + offset+=(segacd_imagebuffer_offset&0x38)<<1; + + offset+=countx & 0x7; + + write_pixel( pix, offset ); + + segacd_mark_tiles_dirty(offset>>3); + segacd_mark_tiles_dirty((offset>>3)+1); + + } + + } + } + +} + +// actually just the low 8 bits? +uint16_t sega_segacd_device::segacd_imagebuffer_vdot_size_r() +{ + return segacd_imagebuffer_vdot_size; +} + +void sega_segacd_device::segacd_imagebuffer_vdot_size_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + //printf("segacd_imagebuffer_vdot_size_w %04x %04x\n",data,mem_mask); + COMBINE_DATA(&segacd_imagebuffer_vdot_size); +} + + +// basically the 'tilemap' base address, for the 16x16 / 32x32 source tiles +uint16_t sega_segacd_device::segacd_stampmap_base_address_r() +{ + // different bits are valid in different modes, but I'm guessing the register + // always returns all the bits set, even if they're not used? + return segacd_stampmap_base_address; + +} + +void sega_segacd_device::segacd_stampmap_base_address_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ // WORD ACCESS + + // low 3 bitsa aren't used, are they stored? + COMBINE_DATA(&segacd_stampmap_base_address); +} + +// destination for 'rendering' the section of the tilemap(stampmap) requested +uint16_t sega_segacd_device::segacd_imagebuffer_start_address_r() +{ + return segacd_imagebuffer_start_address; +} + +void sega_segacd_device::segacd_imagebuffer_start_address_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&segacd_imagebuffer_start_address); + + //int base = (segacd_imagebuffer_start_address & 0xfffe) * 4; + //printf("segacd_imagebuffer_start_address_w %04x %04x (actual base = %06x)\n", data, segacd_imagebuffer_start_address, base); +} + +uint16_t sega_segacd_device::segacd_imagebuffer_offset_r() +{ + return segacd_imagebuffer_offset; +} + +void sega_segacd_device::segacd_imagebuffer_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&segacd_imagebuffer_offset); +// printf("segacd_imagebuffer_offset_w %04x\n", segacd_imagebuffer_offset); +} + +uint16_t sega_segacd_device::segacd_imagebuffer_vcell_size_r() +{ + return segacd_imagebuffer_vcell_size; +} + +void sega_segacd_device::segacd_imagebuffer_vcell_size_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&segacd_imagebuffer_vcell_size); +} + + +uint16_t sega_segacd_device::segacd_imagebuffer_hdot_size_r() +{ + return segacd_imagebuffer_hdot_size; +} + +void sega_segacd_device::segacd_imagebuffer_hdot_size_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&segacd_imagebuffer_hdot_size); +} + + + +uint16_t sega_segacd_device::segacd_irq3timer_r() +{ + return m_irq3_timer_reg; // always returns value written, not current counter! +} + + +void sega_segacd_device::segacd_irq3timer_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_0_7) + { + m_irq3_timer_reg = data & 0xff; + + // time = reg * 30.72 us + + if (m_irq3_timer_reg) + m_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED); + else + m_irq3_timer->adjust(attotime::never); + + //printf("segacd_irq3timer_w %02x\n", segacd_m_irq3_timer_reg); + } +} + + +uint8_t sega_segacd_device::backupram_r(offs_t offset) +{ + return m_backupram[offset]; +} + +void sega_segacd_device::backupram_w(offs_t offset, uint8_t data) +{ + m_backupram[offset] = data; +} + +uint8_t sega_segacd_device::font_color_r() +{ + return m_font_color; +} + +void sega_segacd_device::font_color_w(uint8_t data) +{ + m_font_color = data; +} + +uint16_t sega_segacd_device::font_converted_r(offs_t offset) +{ + int scbg = (m_font_color & 0x0f); + int scfg = (m_font_color & 0xf0)>>4; + uint16_t retdata = 0; + int bit; + + for (bit=0;bit<4;bit++) + { + if (*m_font_bits&((0x1000>>offset*4)<space(AS_PROGRAM); + + m_backupram.resize(0x2000); + subdevice("backupram")->set_base(&m_backupram[0], 0x2000); + + segacd_4meg_prgbank = 0; + + m_red_led.resolve(); + m_green_led.resolve(); + + space.unmap_readwrite (0x020000,0x3fffff); + + space.install_read_handler (0x0020000, 0x003ffff, read16sm_delegate(*this, FUNC(sega_segacd_device::scd_4m_prgbank_ram_r)) ); + space.install_write_handler (0x0020000, 0x003ffff, write16s_delegate(*this, FUNC(sega_segacd_device::scd_4m_prgbank_ram_w)) ); + + + space.install_read_handler(0x200000, 0x23ffff, read16sm_delegate(*this, FUNC(sega_segacd_device::segacd_main_dataram_part1_r))); // RAM shared with sub + space.install_write_handler(0x200000, 0x23ffff, write16s_delegate(*this, FUNC(sega_segacd_device::segacd_main_dataram_part1_w))); // RAM shared with sub + space.install_read_handler(0xa12000, 0xa12001, read16smo_delegate(*this, FUNC(sega_segacd_device::scd_a12000_halt_reset_r))); // sub-cpu control + space.install_write_handler(0xa12000, 0xa12001, write16s_delegate(*this, FUNC(sega_segacd_device::scd_a12000_halt_reset_w))); // sub-cpu control + space.install_read_handler(0xa12002, 0xa12003, read16smo_delegate(*this, FUNC(sega_segacd_device::scd_a12002_memory_mode_r))); // memory mode / write protect + space.install_write_handler(0xa12002, 0xa12003, write16s_delegate(*this, FUNC(sega_segacd_device::scd_a12002_memory_mode_w))); // memory mode / write protect + //space.install_readwrite_handler(0xa12004, 0xa12005, read16_delegate(*this, FUNC(sega_segacd_device::segacd_cdc_mode_address_r)), write16_delegate(*this, FUNC(sega_segacd_device::segacd_cdc_mode_address_w))); + space.install_read_handler(0xa12006, 0xa12007, read16smo_delegate(*this, FUNC(sega_segacd_device::scd_a12006_hint_register_r))); // where HINT points on main CPU + space.install_write_handler(0xa12006, 0xa12007, write16s_delegate(*this, FUNC(sega_segacd_device::scd_a12006_hint_register_w))); // where HINT points on main CPU + //space.install_read_handler (0xa12008, 0xa12009, read16_delegate(*this, FUNC(sega_segacd_device::cdc_data_main_r))); + + + space.install_readwrite_handler(0xa1200c, 0xa1200d, read16smo_delegate(*this, FUNC(sega_segacd_device::segacd_stopwatch_timer_r)), write16smo_delegate(*this, FUNC(sega_segacd_device::segacd_stopwatch_timer_w))); // starblad + + space.install_read_handler(0xa1200e, 0xa1200f, read16smo_delegate(*this, FUNC(sega_segacd_device::segacd_comms_flags_r))); // communication flags block + space.install_write_handler(0xa1200e, 0xa1200f, write16s_delegate(*this, FUNC(sega_segacd_device::segacd_comms_flags_maincpu_w))); // communication flags block + + space.install_read_handler(0xa12010, 0xa1201f, read16sm_delegate(*this, FUNC(sega_segacd_device::segacd_comms_main_part1_r))); + space.install_write_handler(0xa12010, 0xa1201f, write16s_delegate(*this, FUNC(sega_segacd_device::segacd_comms_main_part1_w))); + space.install_read_handler(0xa12020, 0xa1202f, read16sm_delegate(*this, FUNC(sega_segacd_device::segacd_comms_main_part2_r))); + space.install_write_handler(0xa12020, 0xa1202f, write16smo_delegate(*this, FUNC(sega_segacd_device::segacd_comms_main_part2_w))); + + + + space.install_read_handler (0x0000070, 0x0000073, read16sm_delegate(*this, FUNC(sega_segacd_device::scd_hint_vector_r)) ); + + segacd_stampmap[0] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(sega_segacd_device::get_stampmap_16x16_1x1_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 16); + segacd_stampmap[1] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(sega_segacd_device::get_stampmap_32x32_1x1_tile_info)), TILEMAP_SCAN_ROWS, 32, 32, 8, 8); + segacd_stampmap[2] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(sega_segacd_device::get_stampmap_16x16_16x16_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 256, 256); // 128kb! + segacd_stampmap[3] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(sega_segacd_device::get_stampmap_32x32_16x16_tile_info)), TILEMAP_SCAN_ROWS, 32, 32, 128, 128); // 32kb! + + // todo register save state stuff +} + +uint16_t sega_segacd_device::segacd_dmaaddr_r() +{ + return m_dmaaddr; +} + +void sega_segacd_device::segacd_dmaaddr_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_dmaaddr); +} + +void sega_segacd_device::device_reset() +{ + m_scdcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + m_scdcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); + + segacd_hint_register = 0xffff; // -1 + + m_a12000_halt_reset_reg = 0x0000; + + scd_rammode = 0; + scd_mode_dmna_ret_flags = 0x5421; + + m_lc89510_temp->reset_cd(); + m_dmaaddr = 0; + m_dma_timer->adjust(attotime::zero); + + m_total_scanlines = 262; + + // HACK!!!! timegal, anettfut, roadaven/rbfx end up with the SubCPU waiting in a loop for *something* + // overclocking the CPU, even at the point where the game is hung, allows them to continue and boot + // I'm not sure what the source of this timing problem is, it's not using IRQ3 or StopWatch at the + // time. Changing the CDHock timer to 50hz from 75hz also stops the hang, but then the video is + // too slow and has bad sound. -- Investigate! + // Update: removed, otherwise megacdj and megacd2j will black screen with no cdrom inserted. + //m_scdcpu->set_clock_scale(1.5000f); + + + // initialize some stuff on reset + + segacd_ram_writeprotect_bits = 0; + segacd_4meg_prgbank = 0; + segacd_memory_priority_mode = 0; + segacd_stampsize = 0; + + segacd_imagebuffer_vdot_size = 0; + segacd_imagebuffer_vcell_size = 0; + segacd_imagebuffer_hdot_size = 0; + + segacd_conversion_active = 0; + segacd_stampmap_base_address = 0; + segacd_imagebuffer_start_address = 0; + segacd_imagebuffer_offset = 0; + + segacd_comms_flags = 0x0000; + + segacd_redled = 0; + segacd_greenled = 0; + segacd_ready = 1; // actually set 100ms after startup? + m_irq3_timer_reg = 0; + + m_stamp_timer->adjust(attotime::never); + m_irq3_timer->adjust(attotime::never); + +} + + +// todo: tidy up +TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::dma_timer_callback ) +{ + // todo: accurate timing of this! + + #define RATE 256 + m_lc89510_temp->CDC_Do_DMA(RATE); + + // timed reset of flags + scd_mode_dmna_ret_flags |= 0x0021; + + m_dma_timer->adjust(attotime::from_hz(get_framerate()) / double(m_total_scanlines)); + +} + +// todo: tidy up, too many CDC internals here +void sega_segacd_device::SegaCD_CDC_Do_DMA(int &dmacount, uint8_t *CDC_BUFFER, uint16_t &dma_addrc, uint16_t &destination ) +{ + int length = dmacount; + uint16_t *dest; + int srcoffset = 0; + int dstoffset = 0; + + bool PCM_DMA = false; + + if (destination==DMA_PCM) + { + dstoffset = (m_dmaaddr & 0x03FF) << 2; + PCM_DMA = true; + } + else + { + dstoffset = (m_dmaaddr & 0xFFFF) << 3; + } + + + while (dmacount--) + { + uint16_t data = (CDC_BUFFER[dma_addrc+srcoffset]<<8) | CDC_BUFFER[dma_addrc+srcoffset+1]; + + if (destination==DMA_PRG) + { + dest = m_prgram; + } + else if (destination==DMA_WRAM) + { + dest = m_dataram; + } + else if (destination==DMA_PCM) + { + dest = nullptr;//fatalerror("PCM RAM DMA unimplemented!\n"); + } + else + { + fatalerror("Unknown DMA Destination!!\n"); + } + + if (PCM_DMA) + { + m_rfsnd->rf5c68_mem_w(dstoffset & 0xfff, data >> 8); + m_rfsnd->rf5c68_mem_w((dstoffset+1) & 0xfff, data); + // printf("PCM_DMA writing %04x %04x\n",0xff2000+(dstoffset*2), data); + } + else + { + if (dest) + { + if (destination==DMA_WRAM) + { + if ((scd_rammode&2)==RAM_MODE_2MEG) + { + dstoffset &= 0x3ffff; + + dest[dstoffset/2] = data; + + segacd_mark_tiles_dirty(dstoffset/2); + } + else + { + dstoffset &= 0x1ffff; + + if (!(scd_rammode & 1)) + { + segacd_1meg_mode_word_write((dstoffset+0x20000)/2, data, 0xffff, 0); + } + else + { + segacd_1meg_mode_word_write((dstoffset+0x00000)/2, data, 0xffff, 0); + } + } + + } + else + { + // main ram + dest[dstoffset/2] = data; + } + + } + } + + srcoffset += 2; + dstoffset += 2; + } + + + if (PCM_DMA) + { + m_dmaaddr += length >> 1; + } + else + { + m_dmaaddr += length >> 2; + } +} diff --git a/src/mame/sega/megacd.h b/src/mame/sega/megacd.h new file mode 100644 index 00000000000..13bcb2579da --- /dev/null +++ b/src/mame/sega/megacd.h @@ -0,0 +1,229 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +/* Sega CD / Mega CD */ +#ifndef MAME_MACHINE_MEGACD_H +#define MAME_MACHINE_MEGACD_H + +#pragma once + +#include "cpu/m68000/m68000.h" +#include "machine/lc89510.h" +#include "megacdcd.h" +#include "sound/rf5c68.h" +#include "screen.h" +#include "tilemap.h" + +class sega_segacd_device : public device_t, public device_gfx_interface, public device_video_interface +{ +public: + template void set_hostcpu(T &&tag) { m_hostcpu.set_tag(std::forward(tag)); } + + // set some variables at start, depending on region (shall be moved to a device interface?) + void set_framerate(int rate) { m_framerate = rate; } + void set_total_scanlines(int total) { m_base_total_scanlines = total; } // this gets set at start only + void update_total_scanlines(bool mode3) { m_total_scanlines = mode3 ? (m_base_total_scanlines * 2) : m_base_total_scanlines; } // this gets set at each EOF + double get_framerate() { return has_screen() ? screen().frame_period().as_hz() : double(m_framerate); } + + uint16_t segacd_dmaaddr_r(); + void segacd_dmaaddr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + void scd_a12000_halt_reset_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t scd_a12000_halt_reset_r(); + uint16_t scd_a12002_memory_mode_r(); + void scd_a12002_memory_mode_w_8_15(u8 data); + void scd_a12002_memory_mode_w_0_7(u8 data); + void scd_a12002_memory_mode_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_sub_memory_mode_r(); + void segacd_sub_memory_mode_w_8_15(u8 data); + void segacd_sub_memory_mode_w_0_7(u8 data); + void segacd_sub_memory_mode_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + uint16_t segacd_comms_flags_r(); + void segacd_comms_flags_subcpu_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void segacd_comms_flags_maincpu_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t scd_4m_prgbank_ram_r(offs_t offset); + void scd_4m_prgbank_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_comms_main_part1_r(offs_t offset); + void segacd_comms_main_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_comms_main_part2_r(offs_t offset); + void segacd_comms_main_part2_w(uint16_t data); + uint16_t segacd_comms_sub_part1_r(offs_t offset); + void segacd_comms_sub_part1_w(uint16_t data); + uint16_t segacd_comms_sub_part2_r(offs_t offset); + void segacd_comms_sub_part2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + + + uint16_t segacd_main_dataram_part1_r(offs_t offset); + void segacd_main_dataram_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + uint16_t scd_hint_vector_r(offs_t offset); + uint16_t scd_a12006_hint_register_r(); + void scd_a12006_hint_register_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + + void segacd_stopwatch_timer_w(uint16_t data); + uint16_t segacd_stopwatch_timer_r(); + uint16_t segacd_sub_led_ready_r(offs_t offset, uint16_t mem_mask = ~0); + void segacd_sub_led_ready_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_sub_dataram_part1_r(offs_t offset); + void segacd_sub_dataram_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_sub_dataram_part2_r(offs_t offset); + void segacd_sub_dataram_part2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + + uint16_t segacd_stampsize_r(); + void segacd_stampsize_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + TILE_GET_INFO_MEMBER( get_stampmap_16x16_1x1_tile_info ); + TILE_GET_INFO_MEMBER( get_stampmap_32x32_1x1_tile_info ); + TILE_GET_INFO_MEMBER( get_stampmap_16x16_16x16_tile_info ); + TILE_GET_INFO_MEMBER( get_stampmap_32x32_16x16_tile_info ); + + void segacd_trace_vector_base_address_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_imagebuffer_vdot_size_r(); + void segacd_imagebuffer_vdot_size_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_stampmap_base_address_r(); + void segacd_stampmap_base_address_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_imagebuffer_start_address_r(); + void segacd_imagebuffer_start_address_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_imagebuffer_offset_r(); + void segacd_imagebuffer_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_imagebuffer_vcell_size_r(); + void segacd_imagebuffer_vcell_size_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_imagebuffer_hdot_size_r(); + void segacd_imagebuffer_hdot_size_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t segacd_irq3timer_r(); + void segacd_irq3timer_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint8_t backupram_r(offs_t offset); + void backupram_w(offs_t offset, uint8_t data); + uint8_t font_color_r(); + void font_color_w(uint8_t data); + uint16_t font_converted_r(offs_t offset); + + void segacd_map(address_map &map); + void segacd_pcm_map(address_map &map); +protected: + sega_segacd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + + required_device m_scdcpu; + required_device m_hostcpu; + required_device m_rfsnd; + required_device m_lc89510_temp; + required_device m_stopwatch_timer; + required_device m_stamp_timer; + required_device m_irq3_timer; + required_device m_dma_timer; + //required_device m_hock_timer; + + required_shared_ptr m_prgram; + required_shared_ptr m_dataram; + required_shared_ptr m_font_bits; + + output_finder<> m_red_led; + output_finder<> m_green_led; + + // can't use a memshare because it's 8-bit RAM in a 16-bit address space + std::vector m_backupram; + + uint8_t m_font_color = 0; + + uint16_t scd_rammode = 0; + uint32_t scd_mode_dmna_ret_flags = 0; + + tilemap_t *segacd_stampmap[4]{}; + + + uint8_t segacd_ram_writeprotect_bits = 0; + int segacd_4meg_prgbank = 0; // which bank the MainCPU can see of the SubCPU PrgRAM + int segacd_memory_priority_mode = 0; + int segacd_stampsize = 0; + + uint16_t segacd_hint_register = 0; + uint16_t segacd_imagebuffer_vdot_size = 0; + uint16_t segacd_imagebuffer_vcell_size = 0; + uint16_t segacd_imagebuffer_hdot_size = 0; + + int segacd_conversion_active = 0; + uint16_t segacd_stampmap_base_address = 0; + uint16_t segacd_imagebuffer_start_address = 0; + uint16_t segacd_imagebuffer_offset = 0; + + + uint16_t segacd_comms_flags = 0; + uint16_t segacd_comms_part1[0x8]{}; + uint16_t segacd_comms_part2[0x8]{}; + + int segacd_redled = 0; + int segacd_greenled = 0; + int segacd_ready = 1; // actually set 100ms after startup? + uint8_t m_irq3_timer_reg = 0; + + + inline void write_pixel(uint8_t pix, int pixeloffset); + uint16_t segacd_1meg_mode_word_read(offs_t offset); + void segacd_1meg_mode_word_write(offs_t offset, uint16_t data, uint16_t mem_mask, int use_pm); + + uint16_t m_dmaaddr = 0; + + uint16_t m_a12000_halt_reset_reg = 0; + + int m_framerate = 0; + int m_base_total_scanlines = 0; + int m_total_scanlines = 0; + + void segacd_mark_tiles_dirty(int offset); + int segacd_get_active_stampmap_tilemap(void); + + void SCD_GET_TILE_INFO_16x16_1x1( int& tile_region, int& tileno, int tile_index ); + void SCD_GET_TILE_INFO_32x32_1x1( int& tile_region, int& tileno, int tile_index ); + void SCD_GET_TILE_INFO_16x16_16x16( int& tile_region, int& tileno, int tile_index ); + void SCD_GET_TILE_INFO_32x32_16x16( int& tile_region, int& tileno, int tile_index ); + + uint8_t get_stampmap_16x16_1x1_tile_info_pixel(int xpos, int ypos); + uint8_t get_stampmap_32x32_1x1_tile_info_pixel(int xpos, int ypos); + uint8_t get_stampmap_16x16_16x16_tile_info_pixel(int xpos, int ypos); + uint8_t get_stampmap_32x32_16x16_tile_info_pixel(int xpos, int ypos); + + uint8_t read_pixel_from_stampmap(bitmap_ind16* srcbitmap, int x, int y); + + virtual void device_start() override; + virtual void device_reset() override; + + TIMER_DEVICE_CALLBACK_MEMBER( dma_timer_callback ); + IRQ_CALLBACK_MEMBER(segacd_sub_int_callback); + + TIMER_DEVICE_CALLBACK_MEMBER( irq3_timer_callback ); + TIMER_DEVICE_CALLBACK_MEMBER( stamp_timer_callback ); + + void SegaCD_CDC_Do_DMA( int &dmacount, uint8_t *CDC_BUFFER, uint16_t &dma_addrc, uint16_t &destination ); +}; + + +class sega_segacd_us_device : public sega_segacd_device +{ +public: + sega_segacd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +class sega_segacd_japan_device : public sega_segacd_device +{ +public: + sega_segacd_japan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +class sega_segacd_europe_device : public sega_segacd_device +{ +public: + sega_segacd_europe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + + +DECLARE_DEVICE_TYPE(SEGA_SEGACD_US, sega_segacd_us_device) +DECLARE_DEVICE_TYPE(SEGA_SEGACD_JAPAN, sega_segacd_japan_device) +DECLARE_DEVICE_TYPE(SEGA_SEGACD_EUROPE, sega_segacd_europe_device) + +#endif // MAME_MACHINE_MEGACD_H diff --git a/src/mame/sega/megadriv.cpp b/src/mame/sega/megadriv.cpp new file mode 100644 index 00000000000..80a238bf9b9 --- /dev/null +++ b/src/mame/sega/megadriv.cpp @@ -0,0 +1,1108 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +/* + +Megadrive / Genesis support + +this could probably do with a complete rewrite at this point to take into +account all new information discovered since this was created, it's looking +rather old now. + + + +Cleanup / Rewrite notes: + + + +Known Non-Issues (confirmed on Real Genesis) + Castlevania - Bloodlines (U) [!] - Pause text is missing on upside down level + Blood Shot (E) (M4) [!] - corrupt texture in level 1 is correct... + + + +*/ + + +#include "emu.h" +#include "megadriv.h" +#include "speaker.h" + +#define LOG_AUDIOBANK (1U << 1) // z80 to 68k space window access at $8000-$ffff +#define LOG_AUDIOBUS (1U << 2) // z80 bus grants +#define LOG_AUDIORESET (1U << 3) // z80 reset line + +#define VERBOSE (0) + +#include "logmacro.h" + +#define LOGAUDIOBANK(...) LOGMASKED(LOG_AUDIOBANK, __VA_ARGS__) +#define LOGAUDIOBUS(...) LOGMASKED(LOG_AUDIOBUS, __VA_ARGS__) +#define LOGAUDIORESET(...) LOGMASKED(LOG_AUDIORESET, __VA_ARGS__) + + +void md_base_state::megadriv_z80_bank_w(uint16_t data) +{ + // TODO: menghu crashes here + // Tries to setup a bank of 0xff0000 from z80 side (PC=1131) after you talk with the cashier twice. + // Without a guard over it game will trash 68k memory causing a crash, works on real HW with everdrive + // so not coming from a cart copy protection. + // Update: it breaks cfodder BGM on character select at least, therefore we current don't guard against it + // Apparently reading 68k RAM from z80 is not recommended by Sega, so *writing* isn't possible lacking bus grant? + m_genz80.z80_bank_addr = ((m_genz80.z80_bank_addr >> 1) | (data << 23)) & 0xff8000; +} + +void md_base_state::megadriv_68k_z80_bank_write(uint16_t data) +{ + megadriv_z80_bank_w(data & 0x01); +} + +void md_base_state::megadriv_z80_z80_bank_w(uint8_t data) +{ + LOGAUDIOBANK("%s: port $6000 write 0x%02x ", machine().describe_context(), data); + megadriv_z80_bank_w(data & 0x01); + LOGAUDIOBANK("Current bank %08x\n", m_genz80.z80_bank_addr); +} + +uint8_t md_base_state::megadriv_68k_YM2612_read(offs_t offset, uint8_t mem_mask) +{ + //osd_printf_debug("megadriv_68k_YM2612_read %02x %04x\n",offset,mem_mask); + if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) + { + return m_ymsnd->read(offset); + } + else + { + LOG("%s: 68000 attempting to access YM2612 (read) without bus\n", machine().describe_context()); + return 0; + } + + // never executed + //return -1; +} + + +void md_base_state::megadriv_68k_YM2612_write(offs_t offset, uint8_t data, uint8_t mem_mask) +{ + //osd_printf_debug("megadriv_68k_YM2612_write %02x %04x %04x\n",offset,data,mem_mask); + if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) + { + m_ymsnd->write(offset, data); + } + else + { + LOG("%s: 68000 attempting to access YM2612 (write) without bus\n", machine().describe_context()); + } +} + +// this is used by 6 button pads and gets installed in machine_start for drivers requiring it +TIMER_CALLBACK_MEMBER(md_base_state::io_timeout_timer_callback) +{ + m_io_stage[(int)param] = -1; +} + + +/* + + A10001h = A0 Version register + + A10003h = 7F Data register for port A + A10005h = 7F Data register for port B + A10007h = 7F Data register for port C + + A10009h = 00 Ctrl register for port A + A1000Bh = 00 Ctrl register for port B + A1000Dh = 00 Ctrl register for port C + + A1000Fh = FF TxData register for port A + A10011h = 00 RxData register for port A + A10013h = 00 S-Ctrl register for port A + + A10015h = FF TxData register for port B + A10017h = 00 RxData register for port B + A10019h = 00 S-Ctrl register for port B + + A1001Bh = FF TxData register for port C + A1001Dh = 00 RxData register for port C + A1001Fh = 00 S-Ctrl register for port C + + + + + Bit 7 - (Not connected) + Bit 6 - TH + Bit 5 - TL + Bit 4 - TR + Bit 3 - RIGHT + Bit 2 - LEFT + Bit 1 - DOWN + Bit 0 - UP + + +*/ + +INPUT_PORTS_START( md_common ) + PORT_START("PAD1") /* Joypad 1 (3 button + start) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") // b + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") // c + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") // a + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 START") // start + + PORT_START("PAD2") /* Joypad 2 (3 button + start) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") // b + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") // c + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") // a + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 START") // start +INPUT_PORTS_END + + +INPUT_PORTS_START( megadriv ) + PORT_INCLUDE( md_common ) + + PORT_START("RESET") /* Buttons on Genesis Console */ + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Reset Button") PORT_IMPULSE(1) // reset, resets 68k (and..?) +INPUT_PORTS_END + +INPUT_PORTS_START( megadri6 ) + PORT_INCLUDE( megadriv ) + + PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("P1 Z") // z + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 Y") // y + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 X") // x + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(1) PORT_NAME("P1 MODE") // mode + + PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("P2 Z") // z + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 Y") // y + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 X") // x + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(2) PORT_NAME("P2 MODE") // mode +INPUT_PORTS_END + +void md_base_state::megadrive_reset_io() +{ + int i; + + m_megadrive_io_data_regs[0] = 0x7f; + m_megadrive_io_data_regs[1] = 0x7f; + m_megadrive_io_data_regs[2] = 0x7f; + m_megadrive_io_ctrl_regs[0] = 0x00; + m_megadrive_io_ctrl_regs[1] = 0x00; + m_megadrive_io_ctrl_regs[2] = 0x00; + m_megadrive_io_tx_regs[0] = 0xff; + m_megadrive_io_tx_regs[1] = 0xff; + m_megadrive_io_tx_regs[2] = 0xff; + + for (i=0; i<3; i++) + { + m_io_stage[i] = -1; + } +} + +/************* 6 buttons version **************************/ +uint8_t md_base_state::megadrive_io_read_data_port_6button(offs_t offset) +{ + int portnum = offset; + uint8_t retdata, helper = (m_megadrive_io_ctrl_regs[portnum] & 0x3f) | 0xc0; // bits 6 & 7 always come from m_megadrive_io_data_regs + + if (m_megadrive_io_data_regs[portnum] & 0x40) + { + if (m_io_stage[portnum] == 2) + { + /* here we read B, C & the additional buttons */ + retdata = (m_megadrive_io_data_regs[portnum] & helper) | + ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x30) | + ((m_io_pad_6b[portnum] ? m_io_pad_6b[portnum]->read() : 0) & 0x0f)) & ~helper); + } + else + { + /* here we read B, C & the directional buttons */ + retdata = (m_megadrive_io_data_regs[portnum] & helper) | + (((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x3f) & ~helper); + } + } + else + { + if (m_io_stage[portnum] == 1) + { + /* here we read ((Start & A) >> 2) | 0x00 */ + retdata = (m_megadrive_io_data_regs[portnum] & helper) | + ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) & ~helper); + } + else if (m_io_stage[portnum]==2) + { + /* here we read ((Start & A) >> 2) | 0x0f */ + retdata = (m_megadrive_io_data_regs[portnum] & helper) | + (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | 0x0f) & ~helper); + } + else + { + /* here we read ((Start & A) >> 2) | Up and Down */ + retdata = (m_megadrive_io_data_regs[portnum] & helper) | + (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | + ((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x03)) & ~helper); + } + } + +// osd_printf_debug("read io data port stage %d port %d %02x\n",m_io_stage[portnum],portnum,retdata); + + return retdata | (retdata << 8); +} + + +/************* 3 buttons version **************************/ +uint8_t md_base_state::megadrive_io_read_data_port_3button(offs_t offset) +{ + int portnum = offset; + uint8_t retdata, helper = (m_megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from m_megadrive_io_data_regs + + if (m_megadrive_io_data_regs[portnum] & 0x40) + { + /* here we read B, C & the directional buttons */ + retdata = (m_megadrive_io_data_regs[portnum] & helper) | + ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x3f) | 0x40) & ~helper); + } + else + { + /* here we read ((Start & A) >> 2) | Up and Down */ + retdata = (m_megadrive_io_data_regs[portnum] & helper) | + (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | + ((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x03) | 0x40) & ~helper); + } + + return retdata; +} + +uint8_t md_base_state::megadrive_io_read_ctrl_port(int portnum) +{ + uint8_t retdata; + retdata = m_megadrive_io_ctrl_regs[portnum]; + //osd_printf_debug("read io ctrl port %d %02x\n",portnum,retdata); + + return retdata | (retdata << 8); +} + +uint8_t md_base_state::megadrive_io_read_tx_port(int portnum) +{ + uint8_t retdata; + retdata = m_megadrive_io_tx_regs[portnum]; + return retdata | (retdata << 8); +} + +uint8_t md_base_state::megadrive_io_read_rx_port(int portnum) +{ + return 0x00; +} + +uint8_t md_base_state::megadrive_io_read_sctrl_port(int portnum) +{ + return 0x00; +} + + +uint16_t md_base_state::megadriv_68k_io_read(offs_t offset) +{ + uint8_t retdata; + + retdata = 0; + /* Charles MacDonald ( http://cgfm2.emuviews.com/ ) + D7 : Console is 1= Export (USA, Europe, etc.) 0= Domestic (Japan) + D6 : Video type is 1= PAL, 0= NTSC + D5 : Sega CD unit is 1= not present, 0= connected. + D4 : Unused (always returns zero) + D3 : Bit 3 of version number + D2 : Bit 2 of version number + D1 : Bit 1 of version number + D0 : Bit 0 of version number + */ + + //return (machine().rand()&0x0f0f)|0xf0f0;//0x0000; + switch (offset) + { + case 0: + LOG("%06x read version register\n", m_maincpu->pc()); + // Version number contained in bits 3-0 + // TODO: non-TMSS BIOSes must return 0 here + retdata = m_version_hi_nibble | 0x01; + break; + + /* Joystick Port Registers */ + + case 0x1: + case 0x2: + case 0x3: + retdata = m_megadrive_io_read_data_port_ptr(offset-1); + break; + + case 0x4: + case 0x5: + case 0x6: + retdata = megadrive_io_read_ctrl_port(offset-4); + break; + + /* Serial I/O Registers */ + + case 0x7: retdata = megadrive_io_read_tx_port(0); break; + case 0x8: retdata = megadrive_io_read_rx_port(0); break; + case 0x9: retdata = megadrive_io_read_sctrl_port(0); break; + + case 0xa: retdata = megadrive_io_read_tx_port(1); break; + case 0xb: retdata = megadrive_io_read_rx_port(1); break; + case 0xc: retdata = megadrive_io_read_sctrl_port(1); break; + + case 0xd: retdata = megadrive_io_read_tx_port(2); break; + case 0xe: retdata = megadrive_io_read_rx_port(2); break; + case 0xf: retdata = megadrive_io_read_sctrl_port(2); break; + + } + + return retdata | (retdata << 8); +} + + +void md_base_state::megadrive_io_write_data_port_3button(offs_t offset, uint16_t data) +{ + int portnum = offset; + m_megadrive_io_data_regs[portnum] = data; + //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); + +} + + +/****************************** 6 buttons version*****************************/ + +void md_base_state::megadrive_io_write_data_port_6button(offs_t offset, uint16_t data) +{ + int portnum = offset; + if (m_megadrive_io_ctrl_regs[portnum]&0x40) + { + if (((m_megadrive_io_data_regs[portnum]&0x40)==0x00) && ((data&0x40) == 0x40)) + { + m_io_stage[portnum]++; + m_io_timeout[portnum]->adjust(m_maincpu->cycles_to_attotime(8192), portnum); + } + + } + + m_megadrive_io_data_regs[portnum] = data; + //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); + +} + + +/*************************** 3 buttons version ****************************/ + +void md_base_state::megadrive_io_write_ctrl_port(int portnum, uint16_t data) +{ + m_megadrive_io_ctrl_regs[portnum] = data; +// osd_printf_debug("Setting IO Control Register #%d data %04x\n",portnum,data); +} + +void md_base_state::megadrive_io_write_tx_port(int portnum, uint16_t data) +{ + m_megadrive_io_tx_regs[portnum] = data; +} + +void md_base_state::megadrive_io_write_rx_port(int portnum, uint16_t data) +{ +} + +void md_base_state::megadrive_io_write_sctrl_port(int portnum, uint16_t data) +{ +} + + +void md_base_state::megadriv_68k_io_write(offs_t offset, uint16_t data, uint16_t mem_mask) +{ +// osd_printf_debug("IO Write #%02x data %04x mem_mask %04x\n",offset,data,mem_mask); + + + switch (offset) + { + case 0x0: + osd_printf_debug("Write to Version Register?!\n"); + break; + + /* Joypad Port Registers */ + + case 0x1: + case 0x2: + case 0x3: + m_megadrive_io_write_data_port_ptr(offset-1,data); + break; + + case 0x4: + case 0x5: + case 0x6: + megadrive_io_write_ctrl_port(offset-4,data); + break; + + /* Serial I/O Registers */ + + case 0x7: megadrive_io_write_tx_port(0,data); break; + case 0x8: megadrive_io_write_rx_port(0,data); break; + case 0x9: megadrive_io_write_sctrl_port(0,data); break; + + case 0xa: megadrive_io_write_tx_port(1,data); break; + case 0xb: megadrive_io_write_rx_port(1,data); break; + case 0xc: megadrive_io_write_sctrl_port(1,data); break; + + case 0xd: megadrive_io_write_tx_port(2,data); break; + case 0xe: megadrive_io_write_rx_port(2,data); break; + case 0xf: megadrive_io_write_sctrl_port(2,data); break; + } +} + + + +void md_base_state::megadriv_map(address_map &map) +{ + map(0x000000, 0x3fffff).rom(); + /* (0x000000 - 0x3fffff) == GAME ROM (4Meg Max, Some games have special banking too) */ + + map(0xa00000, 0xa01fff).rw(FUNC(md_base_state::megadriv_68k_read_z80_ram), FUNC(md_base_state::megadriv_68k_write_z80_ram)); + map(0xa02000, 0xa03fff).w(FUNC(md_base_state::megadriv_68k_write_z80_ram)); + map(0xa04000, 0xa04003).rw(FUNC(md_base_state::megadriv_68k_YM2612_read), FUNC(md_base_state::megadriv_68k_YM2612_write)); + + map(0xa06000, 0xa06001).w(FUNC(md_base_state::megadriv_68k_z80_bank_write)); + + map(0xa10000, 0xa1001f).rw(FUNC(md_base_state::megadriv_68k_io_read), FUNC(md_base_state::megadriv_68k_io_write)); + + map(0xa11100, 0xa11101).rw(FUNC(md_base_state::megadriv_68k_check_z80_bus), FUNC(md_base_state::megadriv_68k_req_z80_bus)); + map(0xa11200, 0xa11201).w(FUNC(md_base_state::megadriv_68k_req_z80_reset)); + + map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); + map(0xd00000, 0xd0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); // the earth defend + map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram"); +// map(0xff0000, 0xffffff).readonly(); + /* 0xe00000 - 0xffffff) == MAIN RAM (64kb, Mirrored, most games use ff0000 - ffffff) */ +} + + +void md_base_state::dcat16_megadriv_map(address_map &map) +{ + megadriv_map(map); + map(0x000000, 0x7fffff).rom(); +} + + +/* z80 sounds/sub CPU */ + + +uint16_t md_base_state::megadriv_68k_read_z80_ram(offs_t offset, uint16_t mem_mask) +{ + //osd_printf_debug("read z80 ram %04x\n",mem_mask); + + if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) + { + return m_genz80.z80_prgram[(offset<<1)^1] | (m_genz80.z80_prgram[(offset<<1)]<<8); + } + else + { + LOG("%06x: 68000 attempting to access Z80 (read) address space without bus\n", m_maincpu->pc()); + return machine().rand(); + } +} + +void md_base_state::megadriv_68k_write_z80_ram(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) + { + if (!ACCESSING_BITS_0_7) // byte (MSB) access + { + m_genz80.z80_prgram[(offset<<1)] = (data & 0xff00) >> 8; + } + else if (!ACCESSING_BITS_8_15) + { + m_genz80.z80_prgram[(offset<<1)^1] = (data & 0x00ff); + } + else + { + // for WORD access only the MSB is used, LSB is ignored + m_genz80.z80_prgram[(offset<<1)] = (data & 0xff00) >> 8; + } + } + else + { + LOG("%06x: 68000 attempting to access Z80 (write) address space without bus\n", m_maincpu->pc()); + } +} + +/* + * ddragon, beast, superoff, and timekill have buggy sound programs. + * They request the bus, then have a loop which waits for the bus + * to be unavailable, checking for a 0 value due to bad coding. The real hardware + * appears to return bits of the next instruction in the unused bits, thus meaning + * the value is never zero. Time Killers is the most fussy, and doesn't like the + * read_next_instruction function from system16, so I just return a random value + * in the unused bits + */ +uint16_t md_base_state::megadriv_68k_check_z80_bus(offs_t offset, uint16_t mem_mask) +{ + uint16_t retvalue; + + + uint16_t nextvalue = machine().rand(); //read_next_instruction(space)&0xff00; + + + /* Check if the 68k has the z80 bus */ + if (!ACCESSING_BITS_0_7) // byte (MSB) access + { + if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = nextvalue | 0x0100; + else retvalue = (nextvalue & 0xfeff); + + LOGAUDIOBUS("%06x: 68000 check z80 Bus (byte MSB access) returning %04x mask %04x\n", m_maincpu->pc(),retvalue, mem_mask); + return retvalue; + + } + else if (!ACCESSING_BITS_8_15) // is this valid? + { + LOGAUDIOBUS("%06x: 68000 check z80 Bus (byte LSB access) %04x\n", m_maincpu->pc(), mem_mask); + if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = 0x0001; + else retvalue = 0x0000; + + return retvalue; + } + else + { + LOGAUDIOBUS("%06x: 68000 check z80 Bus (word access) %04x\n", m_maincpu->pc(),mem_mask); + if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = nextvalue | 0x0100; + else retvalue = (nextvalue & 0xfeff); + + // osd_printf_debug("%06x: 68000 check z80 Bus (word access) %04x %04x\n", m_maincpu->pc(),mem_mask, retvalue); + return retvalue; + } +} + + +TIMER_CALLBACK_MEMBER(md_base_state::megadriv_z80_run_state) +{ + /* Is the z80 RESET line pulled? */ + // TODO: Z80 /RESET + if (m_genz80.z80_is_reset) + { + m_z80snd->reset(); + m_z80snd->suspend(SUSPEND_REASON_HALT, 1); + m_ymsnd->reset(); + } + else + { + /* Check if z80 has the bus */ + // TODO: Z80 /BUSREQ + if (m_genz80.z80_has_bus) + m_z80snd->resume(SUSPEND_REASON_HALT); + else + m_z80snd->suspend(SUSPEND_REASON_HALT, 1); + } +} + + +void md_base_state::megadriv_68k_req_z80_bus(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + /* Request the Z80 bus, allows 68k to read/write Z80 address space */ + if (!ACCESSING_BITS_0_7) // byte access + { + if (data & 0x0100) + { + LOGAUDIOBUS("%06x: 68000 request z80 Bus (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_has_bus = 0; + } + else + { + LOGAUDIOBUS("%06x: 68000 return z80 Bus (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_has_bus = 1; + } + } + else if (!ACCESSING_BITS_8_15) // is this valid? + { + if (data & 0x0001) + { + LOGAUDIOBUS("%06x: 68000 request z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_has_bus = 0; + } + else + { + LOGAUDIOBUS("%06x: 68000 return z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_has_bus = 1; + } + } + else // word access + { + if (data & 0x0100) + { + LOGAUDIOBUS("%06x: 68000 request z80 Bus (word access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_has_bus = 0; + } + else + { + LOGAUDIOBUS("%06x: 68000 return z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_has_bus = 1; + } + } + + /* If the z80 is running, sync the z80 execution state */ + if (!m_genz80.z80_is_reset) + m_genz80.z80_run_timer->adjust(attotime::zero); +} + +void md_base_state::megadriv_68k_req_z80_reset(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (!ACCESSING_BITS_0_7) // byte access + { + if (data & 0x0100) + { + LOGAUDIORESET("%06x: 68000 clear z80 reset (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_is_reset = 0; + } + else + { + LOGAUDIORESET("%06x: 68000 start z80 reset (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_is_reset = 1; + } + } + else if (!ACCESSING_BITS_8_15) // is this valid? + { + if (data & 0x0001) + { + LOGAUDIORESET("%06x: 68000 clear z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_is_reset = 0; + } + else + { + LOGAUDIORESET("%06x: 68000 start z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_is_reset = 1; + } + } + else // word access + { + if (data & 0x0100) + { + LOGAUDIORESET("%06x: 68000 clear z80 reset (word access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_is_reset = 0; + } + else + { + LOGAUDIORESET("%06x: 68000 start z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); + m_genz80.z80_is_reset = 1; + } + } + m_genz80.z80_run_timer->adjust(attotime::zero); +} + + +// just directly access the 68k space, this makes it easier to deal with +// add-on hardware which changes the cpu mapping like the 32x and SegaCD. +// - we might need to add exceptions for example, z80 reading / writing the +// z80 area of the 68k if games misbehave +uint8_t md_base_state::z80_read_68k_banked_data(offs_t offset) +{ + address_space &space68k = m_maincpu->space(); + uint8_t ret = space68k.read_byte(m_genz80.z80_bank_addr+offset); + return ret; +} + +void md_base_state::z80_write_68k_banked_data(offs_t offset, uint8_t data) +{ + address_space &space68k = m_maincpu->space(); + space68k.write_byte(m_genz80.z80_bank_addr+offset,data); +} + +void md_base_state::megadriv_z80_vdp_write(offs_t offset, uint8_t data) +{ + switch (offset) + { + case 0x11: + case 0x13: + case 0x15: + case 0x17: + // accessed by either segapsg_device or sn76496_device + m_vdp->vdp_w(offset >> 1, data, 0x00ff); + break; + + default: + osd_printf_debug("unhandled z80 vdp write %02x %02x\n",offset,data); + } +} + + +uint8_t md_base_state::megadriv_z80_vdp_read(offs_t offset) +{ + u8 ret = 0; + u8 shift = ((~offset & 1) << 3); + switch (offset & ~1) + { + case 0x04: // ctrl_port_r + case 0x06: + case 0x08: // H/V counter + case 0x0a: + case 0x0c: + case 0x0e: + ret = m_vdp->vdp_r(offset >> 1, 0xff << shift) >> shift; + break; + + default: + if (!machine().side_effects_disabled()) + osd_printf_debug("unhandled z80 vdp read %02x\n",offset); + ret = machine().rand(); + break; + } + return ret; +} + +uint8_t md_base_state::megadriv_z80_unmapped_read() +{ + return 0xff; +} + +void md_base_state::megadriv_z80_map(address_map &map) +{ + map(0x0000, 0x1fff).bankrw("bank1").mirror(0x2000); // RAM can be accessed by the 68k + map(0x4000, 0x4003).rw(m_ymsnd, FUNC(ym_generic_device::read), FUNC(ym_generic_device::write)); + + map(0x6000, 0x6000).w(FUNC(md_base_state::megadriv_z80_z80_bank_w)); + map(0x6001, 0x6001).w(FUNC(md_base_state::megadriv_z80_z80_bank_w)); // wacky races uses this address + + map(0x6100, 0x7eff).r(FUNC(md_base_state::megadriv_z80_unmapped_read)); + + map(0x7f00, 0x7fff).rw(FUNC(md_base_state::megadriv_z80_vdp_read), FUNC(md_base_state::megadriv_z80_vdp_write)); + + map(0x8000, 0xffff).rw(FUNC(md_base_state::z80_read_68k_banked_data), FUNC(md_base_state::z80_write_68k_banked_data)); // The Z80 can read the 68k address space this way +} + +void md_base_state::megadriv_z80_io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x00, 0xff).noprw(); +} + +uint32_t md_base_state::screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + /* Copy our screen buffer here */ + for (int y = cliprect.min_y; y <= cliprect.max_y; y++) + { + uint32_t *const desty = &bitmap.pix(y, 0); + uint32_t const *srcy; + + if (!m_vdp->m_use_alt_timing) + srcy = &m_vdp->m_render_bitmap->pix(y, 0); + else + srcy = m_vdp->m_render_line.get(); + + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) + { + desty[x] = srcy[x]; + } + } + + return 0; +} + + + +/*****************************************************************************************/ + +void md_base_state::video_start() +{ + // nothing? +} + +void md_base_state::machine_start() +{ + m_io_pad_3b[0] = ioport("PAD1"); + m_io_pad_3b[1] = ioport("PAD2"); + m_io_pad_3b[2] = ioport("IN0"); + m_io_pad_3b[3] = ioport("UNK"); + + save_item(NAME(m_io_stage)); + save_item(NAME(m_megadrive_io_data_regs)); + save_item(NAME(m_megadrive_io_ctrl_regs)); + save_item(NAME(m_megadrive_io_tx_regs)); + + if (m_z80snd) + m_genz80.z80_run_timer = timer_alloc(FUNC(md_base_state::megadriv_z80_run_state), this); +} + +void md_base_state::machine_reset() +{ + /* default state of z80 = reset, with bus */ + osd_printf_debug("Resetting Megadrive / Genesis\n"); + + if (m_z80snd) + { + m_genz80.z80_is_reset = 1; + m_genz80.z80_has_bus = 1; + m_genz80.z80_bank_addr = 0; + m_vdp->set_scanline_counter(-1); + m_genz80.z80_run_timer->adjust(attotime::zero); + } + + megadrive_reset_io(); + + if (!m_vdp->m_use_alt_timing) + { + m_vdp->m_megadriv_scanline_timer = m_scan_timer; + m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); + } + + if (m_megadrive_ram) + memset(m_megadrive_ram, 0x00, 0x10000); + + m_vdp->device_reset_old(); +} + +void md_base_state::megadriv_stop_scanline_timer() +{ + if (!m_vdp->m_use_alt_timing) + m_vdp->m_megadriv_scanline_timer->reset(); +} + + + +// this comes from the VDP on lines 240 (on) 241 (off) and is connected to the z80 irq 0 +WRITE_LINE_MEMBER(md_base_state::vdp_sndirqline_callback_genesis_z80) +{ + if (m_z80snd) + { + if (state == ASSERT_LINE) + { + if ((m_genz80.z80_has_bus == 1) && (m_genz80.z80_is_reset == 0)) + m_z80snd->set_input_line(0, HOLD_LINE); + } + else if (state == CLEAR_LINE) + { + m_z80snd->set_input_line(0, CLEAR_LINE); + } + } +} + +// this comes from the vdp, and is connected to 68k irq level 6 (main vbl interrupt) +WRITE_LINE_MEMBER(md_base_state::vdp_lv6irqline_callback_genesis_68k) +{ + if (state == ASSERT_LINE) + m_maincpu->set_input_line(6, HOLD_LINE); + else + m_maincpu->set_input_line(6, CLEAR_LINE); +} + +// this comes from the vdp, and is connected to 68k irq level 4 (raster interrupt) +WRITE_LINE_MEMBER(md_base_state::vdp_lv4irqline_callback_genesis_68k) +{ + if (state == ASSERT_LINE) + m_maincpu->set_input_line(4, HOLD_LINE); + else + m_maincpu->set_input_line(4, CLEAR_LINE); +} + +/* Callback when the 68k takes an IRQ */ +IRQ_CALLBACK_MEMBER(md_base_state::genesis_int_callback) +{ + if (irqline==4) + { + m_vdp->vdp_clear_irq4_pending(); + } + + if (irqline==6) + { + m_vdp->vdp_clear_irq6_pending(); + } + + return (0x60+irqline*4)/4; // vector address +} + +void md_base_state::megadriv_timers(machine_config &config) +{ + TIMER(config, m_scan_timer).configure_generic("gen_vdp", FUNC(sega315_5313_device::megadriv_scanline_timer_callback)); +} + + +void md_base_state::md_ntsc(machine_config &config) +{ + M68000(config, m_maincpu, MASTER_CLOCK_NTSC / 7); /* 7.67 MHz */ + m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_map); + m_maincpu->set_irq_acknowledge_callback(FUNC(md_base_state::genesis_int_callback)); + + /* IRQs are handled via the timers */ + + Z80(config, m_z80snd, MASTER_CLOCK_NTSC / 15); /* 3.58 MHz */ + m_z80snd->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_z80_map); + m_z80snd->set_addrmap(AS_IO, &md_base_state::megadriv_z80_io_map); + /* IRQ handled via the timers */ + + megadriv_timers(config); + + SEGA315_5313(config, m_vdp, MASTER_CLOCK_NTSC, m_maincpu); + m_vdp->set_is_pal(false); + m_vdp->snd_irq().set(FUNC(md_base_state::vdp_sndirqline_callback_genesis_z80)); + m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k)); + m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k)); + m_vdp->set_screen("megadriv"); + m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50); + m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 10.0 / 262.0 / 342.0); // same as SMS? +// m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 8.0 / 262.0 / 427.0); // or 427 Htotal? + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. + m_screen->set_size(64*8, 620); + m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); + m_screen->set_screen_update(FUNC(md_base_state::screen_update_megadriv)); /* Copies a bitmap */ + m_screen->screen_vblank().set(FUNC(md_base_state::screen_vblank_megadriv)); /* Used to Sync the timing */ + + /* sound hardware */ + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + YM2612(config, m_ymsnd, MASTER_CLOCK_NTSC/7); /* 7.67 MHz */ + m_ymsnd->add_route(0, "lspeaker", 0.50); + m_ymsnd->add_route(1, "rspeaker", 0.50); +} + +void md_base_state::md2_ntsc(machine_config &config) +{ + md_ntsc(config); + + // Internalized YM3438 in VDP ASIC + YM3438(config.replace(), m_ymsnd, MASTER_CLOCK_NTSC/7); /* 7.67 MHz */ + m_ymsnd->add_route(0, "lspeaker", 0.50); + m_ymsnd->add_route(1, "rspeaker", 0.50); +} + +/************ PAL hardware has a different master clock *************/ + +void md_base_state::md_pal(machine_config &config) +{ + M68000(config, m_maincpu, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ + m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_map); + m_maincpu->set_irq_acknowledge_callback(FUNC(md_base_state::genesis_int_callback)); + /* IRQs are handled via the timers */ + + Z80(config, m_z80snd, MASTER_CLOCK_PAL / 15); /* 3.58 MHz */ + m_z80snd->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_z80_map); + m_z80snd->set_addrmap(AS_IO, &md_base_state::megadriv_z80_io_map); + /* IRQ handled via the timers */ + + megadriv_timers(config); + + SEGA315_5313(config, m_vdp, MASTER_CLOCK_PAL, m_maincpu); + m_vdp->set_is_pal(true); + m_vdp->snd_irq().set(FUNC(md_base_state::vdp_sndirqline_callback_genesis_z80)); + m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k)); + m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k)); + m_vdp->set_screen("megadriv"); + m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50); + m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 10.0 / 313.0 / 342.0); // same as SMS? +// m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 8.0 / 313.0 / 423.0); // or 423 Htotal? + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. + m_screen->set_size(64*8, 620); + m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); + m_screen->set_screen_update(FUNC(md_base_state::screen_update_megadriv)); /* Copies a bitmap */ + m_screen->screen_vblank().set(FUNC(md_base_state::screen_vblank_megadriv)); /* Used to Sync the timing */ + + /* sound hardware */ + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + YM2612(config, m_ymsnd, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ + m_ymsnd->add_route(0, "lspeaker", 0.50); + m_ymsnd->add_route(1, "rspeaker", 0.50); +} + +void md_base_state::md2_pal(machine_config &config) +{ + md_pal(config); + + // Internalized YM3438 in VDP ASIC + YM3438(config.replace(), m_ymsnd, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ + m_ymsnd->add_route(0, "lspeaker", 0.50); + m_ymsnd->add_route(1, "rspeaker", 0.50); +} + + +void md_base_state::megadriv_tas_callback(offs_t offset, uint8_t data) +{ + // writeback not allowed +} + +void md_base_state::megadriv_init_common() +{ + /* Look to see if this system has the standard Sound Z80 */ + if (m_z80snd) + { + m_genz80.z80_prgram = std::make_unique(0x2000); + membank("bank1")->set_base(m_genz80.z80_prgram.get()); + save_item(NAME(m_genz80.z80_is_reset)); + save_item(NAME(m_genz80.z80_has_bus)); + save_item(NAME(m_genz80.z80_bank_addr)); + save_pointer(NAME(m_genz80.z80_prgram), 0x2000); + } + + m_maincpu->set_tas_write_callback(*this, FUNC(md_base_state::megadriv_tas_callback)); + + m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_3button)); + m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_3button)); +} + +void md_base_state::init_megadriv() +{ + megadriv_init_common(); + + // todo: move this to the device interface? + m_vdp->set_use_cram(1); + m_vdp->set_vdp_pal(false); + m_vdp->set_framerate(60); + m_vdp->set_total_scanlines(262); + + m_version_hi_nibble = 0xa0; // Export NTSC no-SCD +} + +void md_base_state::init_megadrij() +{ + megadriv_init_common(); + + // todo: move this to the device interface? + m_vdp->set_use_cram(1); + m_vdp->set_vdp_pal(false); + m_vdp->set_framerate(60); + m_vdp->set_total_scanlines(262); + + m_version_hi_nibble = 0x20; // JPN NTSC no-SCD +} + +void md_base_state::init_megadrie() +{ + megadriv_init_common(); + + // todo: move this to the device interface? + m_vdp->set_use_cram(1); + m_vdp->set_vdp_pal(true); + m_vdp->set_framerate(50); + m_vdp->set_total_scanlines(313); + + m_version_hi_nibble = 0xe0; // Export PAL no-SCD +} + +WRITE_LINE_MEMBER(md_base_state::screen_vblank_megadriv) +{ + if (m_io_reset.read_safe(0) & 0x01) + m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); + + // rising edge + if (state) + { + if (!m_vdp->m_use_alt_timing) + { + m_vdp->vdp_handle_eof(); + m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); + } + } +} diff --git a/src/mame/sega/megadriv.h b/src/mame/sega/megadriv.h new file mode 100644 index 00000000000..eb95bc8eedc --- /dev/null +++ b/src/mame/sega/megadriv.h @@ -0,0 +1,151 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +#ifndef MAME_SHARED_MEGADRIV_H +#define MAME_SHARED_MEGADRIV_H + +#pragma once + +#include "cpu/m68000/m68000.h" +#include "cpu/z80/z80.h" +#include "sound/sn76496.h" +#include "sound/ymopn.h" +#include "video/315_5313.h" + +#define MASTER_CLOCK_NTSC 53693175 +#define MASTER_CLOCK_PAL 53203424 + +#define MD_CPU_REGION_SIZE 0x800000 + + +/*----------- defined in machine/megadriv.cpp -----------*/ + +INPUT_PORTS_EXTERN( md_common ); +INPUT_PORTS_EXTERN( megadriv ); +INPUT_PORTS_EXTERN( megadri6 ); +INPUT_PORTS_EXTERN( ssf2mdb ); +INPUT_PORTS_EXTERN( mk3mdb ); + + +class md_base_state : public driver_device +{ +public: + md_base_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this,"maincpu"), + m_z80snd(*this,"genesis_snd_z80"), + m_ymsnd(*this,"ymsnd"), + m_scan_timer(*this, "md_scan_timer"), + m_vdp(*this,"gen_vdp"), + m_megadrive_ram(*this,"megadrive_ram"), + m_screen(*this,"megadriv"), + m_io_reset(*this, "RESET"), + m_megadrive_io_read_data_port_ptr(*this), + m_megadrive_io_write_data_port_ptr(*this) + { } + + required_device m_maincpu; + optional_device m_z80snd; + optional_device m_ymsnd; + optional_device m_scan_timer; + required_device m_vdp; + optional_shared_ptr m_megadrive_ram; + optional_device m_screen; + + optional_ioport m_io_reset; + ioport_port *m_io_pad_3b[4]; + ioport_port *m_io_pad_6b[4]; + + struct genesis_z80_vars + { + int z80_is_reset = 0; + int z80_has_bus = 0; + uint32_t z80_bank_addr = 0; + std::unique_ptr z80_prgram; + emu_timer *z80_run_timer = nullptr; + }; + + genesis_z80_vars m_genz80; + int m_version_hi_nibble; + + void init_megadrie(); + void init_megadriv(); + void init_megadrij(); + + uint8_t megadriv_68k_YM2612_read(offs_t offset, uint8_t mem_mask = ~0); + void megadriv_68k_YM2612_write(offs_t offset, uint8_t data, uint8_t mem_mask = ~0); + IRQ_CALLBACK_MEMBER(genesis_int_callback); + void megadriv_init_common(); + + void megadriv_z80_bank_w(uint16_t data); + void megadriv_68k_z80_bank_write(uint16_t data); + void megadriv_z80_z80_bank_w(uint8_t data); + uint16_t megadriv_68k_io_read(offs_t offset); + void megadriv_68k_io_write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t megadriv_68k_read_z80_ram(offs_t offset, uint16_t mem_mask = ~0); + void megadriv_68k_write_z80_ram(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t megadriv_68k_check_z80_bus(offs_t offset, uint16_t mem_mask = ~0); + void megadriv_68k_req_z80_bus(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + void megadriv_68k_req_z80_reset(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint8_t z80_read_68k_banked_data(offs_t offset); + void z80_write_68k_banked_data(offs_t offset, uint8_t data); + void megadriv_z80_vdp_write(offs_t offset, uint8_t data); + uint8_t megadriv_z80_vdp_read(offs_t offset); + uint8_t megadriv_z80_unmapped_read(); + TIMER_CALLBACK_MEMBER(megadriv_z80_run_state); + + /* Megadrive / Genesis has 3 I/O ports */ + emu_timer *m_io_timeout[3]; + int m_io_stage[3]; + uint8_t m_megadrive_io_data_regs[3]; + uint8_t m_megadrive_io_ctrl_regs[3]; + uint8_t m_megadrive_io_tx_regs[3]; + read8sm_delegate m_megadrive_io_read_data_port_ptr; + write16sm_delegate m_megadrive_io_write_data_port_ptr; + + WRITE_LINE_MEMBER(vdp_sndirqline_callback_genesis_z80); + WRITE_LINE_MEMBER(vdp_lv6irqline_callback_genesis_68k); + WRITE_LINE_MEMBER(vdp_lv4irqline_callback_genesis_68k); + + TIMER_CALLBACK_MEMBER( io_timeout_timer_callback ); + void megadrive_reset_io(); + uint8_t megadrive_io_read_data_port_6button(offs_t offset); + uint8_t megadrive_io_read_data_port_3button(offs_t offset); + uint8_t megadrive_io_read_ctrl_port(int portnum); + uint8_t megadrive_io_read_tx_port(int portnum); + uint8_t megadrive_io_read_rx_port(int portnum); + uint8_t megadrive_io_read_sctrl_port(int portnum); + + void megadrive_io_write_data_port_3button(offs_t offset, uint16_t data); + void megadrive_io_write_data_port_6button(offs_t offset, uint16_t data); + void megadrive_io_write_ctrl_port(int portnum, uint16_t data); + void megadrive_io_write_tx_port(int portnum, uint16_t data); + void megadrive_io_write_rx_port(int portnum, uint16_t data); + void megadrive_io_write_sctrl_port(int portnum, uint16_t data); + + void megadriv_stop_scanline_timer(); + + uint32_t screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(screen_vblank_megadriv); + + void megadriv_tas_callback(offs_t offset, uint8_t data); + + void megadriv_timers(machine_config &config); + void md_ntsc(machine_config &config); + void md2_ntsc(machine_config &config); + void md_pal(machine_config &config); + void md2_pal(machine_config &config); + void md_bootleg(machine_config &config); + + void dcat16_megadriv_base(machine_config &config); + void dcat16_megadriv_map(address_map &map); + void megadriv_map(address_map &map); + void megadriv_z80_io_map(address_map &map); + void megadriv_z80_map(address_map &map); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; +}; + +#endif // MAME_SHARED_MEGADRIV_H diff --git a/src/mame/sega/megadriv_rad.cpp b/src/mame/sega/megadriv_rad.cpp new file mode 100644 index 00000000000..42e14b90572 --- /dev/null +++ b/src/mame/sega/megadriv_rad.cpp @@ -0,0 +1,692 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +/* + Radica 'Mega Drive' and 'Genesis' clones + these were mini battery operated "TV Game" consoles with wired in controller and no cartslot + fully licensed by Sega + + reproduction 'System on a Chip' hardware, not perfect, flaws will need emulating eventually. + + not dumped + + Genesis Volume 2 + Genesis SF2 / GnG (PAL one is locked to PAL) + + Outrun 2019 (probably identical ROM to MD version, just custom controller) + + more? + +*/ + +#include "emu.h" +#include "megadriv.h" +#include "megadriv_rad.h" + +// todo, use actual MD map, easier once maps are part of base class. +void megadriv_radica_state::megadriv_base_map(address_map &map) +{ + map(0x000000, 0x3fffff).r(FUNC(megadriv_radica_state::read)); /* Cartridge Program Rom */ + map(0xa00000, 0xa01fff).rw(FUNC(megadriv_radica_state::megadriv_68k_read_z80_ram), FUNC(megadriv_radica_state::megadriv_68k_write_z80_ram)); + map(0xa02000, 0xa03fff).w(FUNC(megadriv_radica_state::megadriv_68k_write_z80_ram)); + map(0xa04000, 0xa04003).rw(FUNC(megadriv_radica_state::megadriv_68k_YM2612_read), FUNC(megadriv_radica_state::megadriv_68k_YM2612_write)); + map(0xa06000, 0xa06001).w(FUNC(megadriv_radica_state::megadriv_68k_z80_bank_write)); + map(0xa10000, 0xa1001f).rw(FUNC(megadriv_radica_state::megadriv_68k_io_read), FUNC(megadriv_radica_state::megadriv_68k_io_write)); + map(0xa11100, 0xa11101).rw(FUNC(megadriv_radica_state::megadriv_68k_check_z80_bus), FUNC(megadriv_radica_state::megadriv_68k_req_z80_bus)); + map(0xa11200, 0xa11201).w(FUNC(megadriv_radica_state::megadriv_68k_req_z80_reset)); + map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); + map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram"); +} + +void megadriv_radica_state::megadriv_radica_map(address_map &map) +{ + megadriv_base_map(map); + map(0xa13000, 0xa130ff).r(FUNC(megadriv_radica_state::read_a13)); +} + +uint16_t megadriv_dgunl_state::read_a16300(offs_t offset, uint16_t mem_mask) +{ + return 0x5a5a; +} + +uint16_t megadriv_dgunl_state::read_a16302(offs_t offset, uint16_t mem_mask) +{ + return m_a1630a; +} + +void megadriv_dgunl_state::write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + m_a1630a = data; + m_bank = (data & 0x07) * 8; +} + + +void megadriv_ra145_state::write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + // the banking must know how big each game is to get the base location, as it only writes a game number?! + // it must also know to skip the unused copy of Golden Axe + // there must be a table somewhere, or, if this is actually an emulation based system, it must be scanning + // for headers somehow? + + m_a1630a = data; + + switch (data & 0xff) + { + + + // 0x0000000 = Block of unknown data/code + // 0x0040000 = 145 in 1 menu + // (includes unused Columns, Fatal Labyrinth, Blockout, Flicky, Shove It, Space Invaders 90 as part of menu data) + case 0x00: m_bank = 0x02c0000; break;// = Fantasia 00 + case 0x01: m_bank = 0x0340000; break;// = Fire Shark 01 + case 0x02: m_bank = 0x03c0000; break;// = James Bond 007 - The Duel 02 (BAD ROM) + case 0x03: m_bank = 0x0440000; break;// = Sunset Riders 03 + case 0x04: m_bank = 0x04c0000; break;// = Robocop 3 04 + case 0x05: m_bank = 0x0540000; break;// = Hokuto no Ken 05 (BAD ROM) + case 0x06: m_bank = 0x05c0000; break;// = Alien 3 06 + case 0x07: m_bank = 0x0640000; break;// = Batman 07 (BAD ROM) + case 0x08: m_bank = 0x06c0000; break;// = Cat 08 + case 0x09: m_bank = 0x0740000; break;// = DJ Boy 09 + case 0x0a: m_bank = 0x07c0000; break;// = Rambo 3 0a (BAD ROM) + case 0x0b: m_bank = 0x0840000; break;// = Wardner 0b + case 0x0c: m_bank = 0x08c0000; break;// = Paperboy 0c + case 0x0d: m_bank = 0x0940000; break;// = Streets of Rage 0d + case 0x0e: m_bank = 0x09c0000; break;// = Tiny Toon Adventures 0e + case 0x0f: m_bank = 0x0a40000; break;// = Super Battleship 0f + case 0x10: m_bank = 0x0ac0000; break;// = Burning Force 10 + case 0x11: m_bank = 0x0b40000; break;// = Cadash 11 + case 0x12: m_bank = 0x0bc0000; break;// = Caesars Palace 12 + case 0x13: m_bank = 0x0c40000; break;// = chase HQ 2 13 + case 0x14: m_bank = 0x0cc0000; break;// = Wonderboy 3 14 + case 0x15: m_bank = 0x0d40000; break;// = Fighting Master 15 + case 0x16: m_bank = 0x0dc0000; break;// = The Flintstones 16 + case 0x17: m_bank = 0x0e40000; break;// = Ariel the Little Mermaid 17 + case 0x18: m_bank = 0x0ec0000; break;// = Hellfire 18 + case 0x19: m_bank = 0x0f40000; break;// = Arrow Flash 19 + case 0x1a: m_bank = 0x0fc0000; break;// = Shove It 1a + case 0x1b: m_bank = 0x1040000; break;// = Donkey Kong 99 1b + case 0x1c: m_bank = 0x1240000; break;// = Turtles Tournament 1c + case 0x1d: m_bank = 0x1440000; break;// = Thunder Force 2 1d (This is meant to be Revenge of Shinobi according to the menu, but incorrect game was in the ROM) + case 0x1e: m_bank = 0x14c0000; break;// = Wings of Wor 1e + case 0x1f: m_bank = 0x1540000; break;// = Wrestle War 1f + case 0x20: m_bank = 0x15c0000; break;// = Afterburner 2 20 + case 0x21: m_bank = 0x1640000; break;// = Altered Beast 21 + case 0x22: m_bank = 0x16c0000; break;// = Captain Planet 22 + case 0x23: m_bank = 0x1740000; break;// = Bimimi Run 23 + case 0x24: m_bank = 0x17c0000; break;// = Osomatsu 24 + case 0x25: m_bank = 0x1840000; break;// = Castle of Illusion 25 + case 0x26: m_bank = 0x18c0000; break;// = Crackdown 26 + case 0x27: m_bank = 0x1940000; break;// = Crossfire 27 + case 0x28: m_bank = 0x19c0000; break;// = Curse 28 + case 0x29: m_bank = 0x1a40000; break;// = Dangerous Seed 29 + case 0x2a: m_bank = 0x1ac0000; break;// = Dark Castle 2a + case 0x2b: m_bank = 0x1b40000; break;// = Darwin 2b + case 0x2c: m_bank = 0x1bc0000; break;// = Thunder Force 2 (duplicate?) 2c + case 0x2d: m_bank = 0x1c40000; break;// = Dynamite Duke 2d + case 0x2e: m_bank = 0x1cc0000; break;// = EA Hockey 2e + case 0x2f: m_bank = 0x1d40000; break;// = Elemenal Master 2f + case 0x30: m_bank = 0x1dc0000; break;// = Super Thunder Blade 30 + case 0x31: m_bank = 0x1e40000; break;// = Target Earth 31 + case 0x32: m_bank = 0x1ec0000; break;// = Rastan Saga 2 32 + case 0x33: m_bank = 0x1f40000; break;// = Ghostbusters 33 + case 0x34: m_bank = 0x1fc0000; break;// = Mahjong cop 34 + case 0x35: m_bank = 0x2040000; break;// = High School Soccer 35 + case 0x36: m_bank = 0x20c0000; break;// = Insector X 36 + case 0x37: m_bank = 0x2140000; break;// = Pheilos 37 + case 0x38: m_bank = 0x21c0000; break;// = Runark 38 + case 0x39: m_bank = 0x2240000; break;// = Saint Sword 39 + case 0x3a: m_bank = 0x22c0000; break;// = Shadow Dancer 3a + case 0x3b: m_bank = 0x2340000; break;// = Shiten Myooh 3b + case 0x3c: m_bank = 0x23c0000; break;// = Wani Wani World 3c + case 0x3d: m_bank = 0x2440000; break;// = Street Mmart 3d + case 0x3e: m_bank = 0x24c0000; break;// = Toki 3e + case 0x3f: m_bank = 0x2540000; break;// = Trouble Shooter 3f + case 0x40: m_bank = 0x25c0000; break;// = Truxton 40 + case 0x41: m_bank = 0x2640000; break;// = James Pond 2 41 + case 0x42: m_bank = 0x26c0000; break;// = Twin Hawk 42 + case 0x43: m_bank = 0x2740000; break;// = Syd of Valis 43 + case 0x44: m_bank = 0x27c0000; break;// = Zoom 44 + case 0x45: m_bank = 0x2840000; break;// = Streets of Rage 2 45 + case 0x46: m_bank = 0x2a40000; break;// = Sonic & Knuckles 46 + case 0x47: m_bank = 0x2c40000; break;// = Comix Zone 47 + case 0x48: m_bank = 0x2e40000; break;// = Rolling Thunder 2 48 + case 0x49: m_bank = 0x2f40000; break;// = Bubble & Squeek 49 + case 0x4a: m_bank = 0x2fc0000; break;// = Alex Kidd 4a + case 0x4b: m_bank = 0x3040000; break;// = Super Mario 2 4b + case 0x4c: m_bank = 0x3240000; break;// = NBA All Star 4c + case 0x4d: m_bank = 0x3340000; break;// = Bio Hazard Battle 4d + case 0x4e: m_bank = 0x3440000; break;// = Prince of Persia 4e + case 0x4f: m_bank = 0x3540000; break;// = Champions World Soccer 4f + case 0x50: m_bank = 0x3640000; break;// = Lotus 2 50 + case 0x51: m_bank = 0x3740000; break;// = Grandia 51 + case 0x52: m_bank = 0x37c0000; break;// = World Cup Soccer 52 + case 0x53: m_bank = 0x3840000; break;// = Ultimate Mortal Kombat 3 53 + case 0x54: m_bank = 0x3c40000; break;// = Street Fighter II (hacked MSI version) 54 + case 0x55: m_bank = 0x3f40000; break;// = Verytex 55 + case 0x56: m_bank = 0x3fc0000; break;// = Space Invaders 90 56 + + //This 32MBytes of the ROM has its own unused '666666 in 1 menu' and only references games + //within this block; it was probably released as a standalone using this 32Mbytes of ROM + // 0x4000000 = Block of unknown data/code + // 0x4040000 = 666666 in 1 menu + // (includes unused Columns, Fatal Labyrinth, Blockout, Flicky, Shove It, Space Invaders 90 as part of menu data) + // 0x42c0000 - Golden Axe -- (not used by 145-in-1 menu, no assigned number either?!) + case 0x57: m_bank = 0x4340000; break;// - Mega Bomberman 57 + case 0x58: m_bank = 0x4440000; break;// - Dragon The Bruce Lee Story 58 + case 0x59: m_bank = 0x4640000; break;// - Twinkle Tale 59 + case 0x5a: m_bank = 0x4740000; break;// - Jewel Master 5a + case 0x5b: m_bank = 0x47c0000; break;// - Pacmania 5b + case 0x5c: m_bank = 0x4840000; break;// - X-Men 2 5c + case 0x5d: m_bank = 0x4a40000; break;// - Top Gear 2 5d + case 0x5e: m_bank = 0x4b40000; break;// - Brian Lara Cricket 5e + case 0x5f: m_bank = 0x4c40000; break;// - Garfield 5f + case 0x60: m_bank = 0x4e40000; break;// - Raiden Trad 60 + case 0x61: m_bank = 0x4f40000; break;// - James Pond 61 + case 0x62: m_bank = 0x4fc0000; break;// - Mega Panel 62 + case 0x63: m_bank = 0x5040000; break;// - James Pond 3 63 + case 0x64: m_bank = 0x5240000; break;// - Contra Hardcorps 64 + case 0x65: m_bank = 0x5440000; break;// - International Superstar Soccer Deluxe 65 + case 0x66: m_bank = 0x5640000; break;// - Double Dragon 3 (with Trainer) 66 + case 0x67: m_bank = 0x5740000; break;// - Micro Machines 67 + case 0x68: m_bank = 0x57c0000; break;// - Hard Drivin' 68 + case 0x69: m_bank = 0x5840000; break;// - Dragon Ball Z 69 + case 0x6a: m_bank = 0x5a40000; break;// - F1 World Championship Edition 6a + case 0x6b: m_bank = 0x5c40000; break;// - Megaman / Rockman -- (6b, but unused? probably due to save feature?) + case 0x6c: m_bank = 0x5e40000; break;// - Operation Vapor Trail 6c + case 0x6d: m_bank = 0x5f40000; break;// - Roadblasters 6d + case 0x6e: m_bank = 0x5fc0000; break;// - Super Volleyball 6e + + //The final 32MBytes of the ROM has its own unused '888888 in 1 menu' and only references games + //within this block; it was probably released as a standalone using this 32Mbytes of ROM + // 0x6000000 = Block of unknown data/code + // 0x6040000 = 888888 in 1 menu + // (includes unused Columns, Fatal Labyrinth, Blockout, Flicky, Shove It, Space Invaders 90 as part of menu data) + case 0x6f: m_bank = 0x62c0000; break;// - Last Battle 6f + case 0x70: m_bank = 0x6340000; break;// - Shinobi III 70 + case 0x71: m_bank = 0x6440000; break;// - Mickey Mania 71 + case 0x72: m_bank = 0x6640000; break;// - Snow Bros 72 + case 0x73: m_bank = 0x6740000; break;// - Space Harrier II 73 + case 0x74: m_bank = 0x67c0000; break;// - Volfied 74 + case 0x75: m_bank = 0x6840000; break;// - Goofy's Hysterical History Tour 75 + case 0x76: m_bank = 0x6940000; break;// - Mighty Max 76 + case 0x77: m_bank = 0x6a40000; break;// - Mr Nutz 77 + case 0x78: m_bank = 0x6b40000; break;// - Sonic 2 78 + case 0x79: m_bank = 0x6c40000; break;// - Ecco Jr. 79 + case 0x7a: m_bank = 0x6d40000; break;// - Desert Demolition 7a + case 0x7b: m_bank = 0x6e40000; break;// - Midnight Resistance 7b + case 0x7c: m_bank = 0x6f40000; break;// - Spiderman vs The Kingpin 7c + case 0x7d: m_bank = 0x6fc0000; break;// - Trampoline Terror 7d + case 0x7e: m_bank = 0x7040000; break;// - MUSHA 7e + case 0x7f: m_bank = 0x70c0000; break;// - Sonic 7f + case 0x80: m_bank = 0x7140000; break;// - Thunder Force III 80 + case 0x81: m_bank = 0x71c0000; break;// - Golden Axe (again) 81 + // 0x7240000; break;// - Controller Test Menu -- (unused) + // 0x7340000; break;// - Controller Test Menu (again) -- (unused) + case 0x82: m_bank = 0x7440000; break;// - Wacky Worlds 82 (writes 93, incorrectly swapped in menu with Wacky Worlds) + case 0x83: m_bank = 0x7540000; break;// - Bonkers 83 + case 0x84: m_bank = 0x7640000; break;// - Alisia Dragoon 84 + case 0x85: m_bank = 0x7740000; break;// - Super Hang On 85 + case 0x86: m_bank = 0x77c0000; break;// - Dragon's Eye Shanghai 3 86 + case 0x87: m_bank = 0x7840000; break;// - Jimmy White's Whirlwind Snooker 87 + case 0x88: m_bank = 0x78c0000; break;// - Home Alone 2 88 + case 0x89: m_bank = 0x7940000; break;// - Xenon 2 (with trainer) 89 + case 0x8a: m_bank = 0x79c0000; break;// - Hit the Ice 8a + case 0x8b: m_bank = 0x7a40000; break;// - Tale Spin 8b + case 0x8c: m_bank = 0x7ac0000; break;// - Puyo Puyo 8c + case 0x8d: m_bank = 0x7b40000; break;// - Rampart (with trainer) 8d + case 0x8e: m_bank = 0x7bc0000; break;// - Crue Ball 8e + case 0x8f: m_bank = 0x7c40000; break;// - Marble Madness 8f + case 0x90: m_bank = 0x7cc0000; break;// - Patlabor 90 + case 0x91: m_bank = 0x7d40000; break;// - The Aquatic Games 91 + case 0x92: m_bank = 0x7dc0000; break;// - King Salmon 92 + case 0x93: m_bank = 0x7e40000; break;// - Fun n Games 93 (writes 82, incorrectly swapped in menu with Fun n Games) + case 0x94: m_bank = 0x7f40000; break;// - Gynoug 94 + case 0x95: m_bank = 0x7fc0000; break;// - Ms. Pac-Man 95 + default: m_bank = 0x0040000; break; + } + + m_bank = m_bank / 0x10000; +} + + +void megadriv_dgunl_state::megadriv_dgunl_map(address_map &map) +{ + megadriv_base_map(map); + + map(0xa16300, 0xa16301).r(FUNC(megadriv_dgunl_state::read_a16300)); + map(0xa16302, 0xa16303).r(FUNC(megadriv_dgunl_state::read_a16302)); + + map(0xa1630a, 0xa1630b).w(FUNC(megadriv_dgunl_state::write_a1630a)); +} + +uint16_t megadriv_radica_state::read(offs_t offset) +{ + return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (m_romsize - 1))/2]; +} + +uint16_t megadriv_radica_state::read_a13(offs_t offset) +{ + if (offset < 0x80) + m_bank = offset & 0x3f; + + // low bit gets set when selecting cannon fodder or mega lo mania in the rad_ssoc set, pointing to the wrong area, but rad_gen1 needs it for the menu + // as they're standalones it could just be different logic + if (m_bank != 0x3f) + m_bank &= 0x3e; + + return 0; +} + +// controller is wired directly into unit, no controller slots +static INPUT_PORTS_START( megadriv_radica_3button ) + PORT_INCLUDE( md_common ) + + PORT_MODIFY("PAD1") + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 ) + + PORT_MODIFY("PAD2") + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START2 ) +INPUT_PORTS_END + +// the 6-in-1 and Sonic Gold units really only have a single wired controller, and no way to connect a 2nd one, despite having some 2 player games! +static INPUT_PORTS_START( megadriv_radica_3button_1player ) + PORT_INCLUDE( megadriv_radica_3button ) + + PORT_MODIFY("PAD2") + PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + +static INPUT_PORTS_START( megadriv_radica_6button ) + PORT_INCLUDE( megadriv_radica_3button ) + + PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("IN0") + PORT_START("UNK") +INPUT_PORTS_END + +static INPUT_PORTS_START( megadriv_msi_6button ) + PORT_INCLUDE( megadriv_radica_3button ) + + PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("EXTRA2") // no 2nd pad + PORT_BIT( 0x000f, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_MODIFY("PAD2") // no 2nd pad + PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("IN0") + PORT_START("UNK") +INPUT_PORTS_END + +static INPUT_PORTS_START( megadriv_dgunl_1player ) + PORT_INCLUDE( megadriv_radica_3button ) + + PORT_MODIFY("PAD1") // the unit only has 2 buttons, A and C, strings are changed to remove references to C, even if behavior in Pac-Mania still exists and differs between them + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED ) // disable 'C' + //PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNUSED ) // disable 'A' + + PORT_MODIFY("PAD2") + PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + +void megadriv_radica_6button_state::machine_start() +{ + md_base_state::machine_start(); + m_vdp->stop_timers(); + + m_io_pad_6b[0] = ioport("EXTRA1"); + m_io_pad_6b[1] = ioport("EXTRA2"); + m_io_pad_6b[2] = ioport("IN0"); + m_io_pad_6b[3] = ioport("UNK"); + + // setup timers for 6 button pads + for (int i = 0; i < 3; i++) + m_io_timeout[i] = timer_alloc(FUNC(md_base_state::io_timeout_timer_callback), this); + + save_item(NAME(m_bank)); +} + +void megadriv_radica_3button_state::machine_start() +{ + md_base_state::machine_start(); + m_vdp->stop_timers(); + save_item(NAME(m_bank)); +} + + +void megadriv_dgunl_state::machine_start() +{ + megadriv_radica_3button_state::machine_start(); + m_a1630a = 0; + save_item(NAME(m_a1630a)); +} + +void megadriv_ra145_state::machine_start() +{ + md_base_state::machine_start(); + m_vdp->stop_timers(); + + m_io_pad_6b[0] = ioport("EXTRA1"); + m_io_pad_6b[1] = ioport("EXTRA2"); + m_io_pad_6b[2] = ioport("IN0"); + m_io_pad_6b[3] = ioport("UNK"); + + // setup timers for 6 button pads + for (int i = 0; i < 3; i++) + m_io_timeout[i] = timer_alloc(FUNC(md_base_state::io_timeout_timer_callback), this); + + m_a1630a = 0; + save_item(NAME(m_a1630a)); + save_item(NAME(m_bank)); +} + +void megadriv_ra145_state::machine_reset() +{ + m_bank = 4; + md_base_state::machine_reset(); +} + + +void megadriv_radica_3button_state::machine_reset() +{ + m_bank = 0; + md_base_state::machine_reset(); +} + +void megadriv_radica_3button_state::megadriv_radica_3button_ntsc(machine_config &config) +{ + md_ntsc(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); +} + +void megadriv_radica_3button_state::megadriv_radica_3button_pal(machine_config &config) +{ + md_pal(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); +} + +void megadriv_radica_6button_state::megadriv_radica_6button_pal(machine_config &config) +{ + md_pal(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); +} + +void megadriv_radica_6button_state::megadriv_radica_6button_ntsc(machine_config &config) +{ + md_ntsc(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); +} + +void megadriv_dgunl_state::megadriv_dgunl_ntsc(machine_config &config) +{ + md_ntsc(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_dgunl_state::megadriv_dgunl_map); +} + +ROM_START( rad_sf2 ) + ROM_REGION( 0x400000, "maincpu", 0 ) + ROM_LOAD16_WORD_SWAP( "radica_megadrive_streetfighter2_usa.bin", 0x000000, 0x400000, CRC(a4426df8) SHA1(091f2a95ebd091141de5bcb83562c6087708cb32) ) +ROM_END + +ROM_START( rad_sf2p ) + ROM_REGION( 0x400000, "maincpu", 0 ) + ROM_LOAD16_WORD_SWAP( "radica_megadrive_streetfighter2_uk.bin", 0x000000, 0x400000, CRC(868afb44) SHA1(f4339e36272c18b1d49aa4095127ed18e0961df6) ) +ROM_END + +ROM_START( rad_gen1 ) + ROM_REGION( 0x400000, "maincpu", 0 ) + ROM_LOAD16_WORD_SWAP( "radica_megadrive_vol1_blue_usa.bin", 0x000000, 0x400000, CRC(3b4c8438) SHA1(5ed9c053f9ebc8d4bf571d57e562cf347585d158) ) +ROM_END + +ROM_START( rad_md1 ) + ROM_REGION( 0x400000, "maincpu", 0 ) + ROM_LOAD16_WORD_SWAP( "radica_megadrive_vol1_blue_europe.bin", 0x000000, 0x400000, CRC(85867db1) SHA1(ddc596e2e68dc872bc0679a2de7a295b4c6d6b8e) ) +ROM_END + +ROM_START( rad_gen2 ) + ROM_REGION( 0x400000, "maincpu", 0 ) + ROM_LOAD16_WORD_SWAP( "radica_genesis_vol2_red_usa.bin", 0x000000, 0x400000, CRC(7c1a0f0e) SHA1(a6441f75a4cd48f1563aeafdfbdde00202d4067c) ) +ROM_END + +ROM_START( rad_md2 ) + ROM_REGION( 0x400000, "maincpu", 0 ) + ROM_LOAD16_WORD_SWAP( "radica_megadrive_vol2_red_uk.bin", 0x000000, 0x400000, CRC(b68fd025) SHA1(b8f9c505653d6dd2b62840f078f828360faf8abc) ) +ROM_END + +ROM_START( rad_ssoc ) + ROM_REGION( 0x400000, "maincpu", 0 ) + ROM_LOAD( "radica_sensiblesoccer_uk.bin", 0x000000, 0x400000, CRC(b8745ab3) SHA1(0ab3f26e5ffd288e5a3a5db676951b9095299eb0) ) // should be byteswapped? +ROM_END + +ROM_START( rad_sonic ) + ROM_REGION( 0x400000, "maincpu", 0 ) + ROM_LOAD16_WORD_SWAP( "radica_supersonicgold_usa.bin", 0x000000, 0x400000, CRC(853c9140) SHA1(cf70a9cdd3be4d8d1b6195698db3a941f4908791) ) +ROM_END + +ROM_START( rad_sonicp ) + ROM_REGION( 0x400000, "maincpu", 0 ) + ROM_LOAD16_WORD_SWAP( "radica_supersonicgold_uk.bin", 0x000000, 0x400000, CRC(ed774018) SHA1(cc2f7183e128c947463e3a43a0184b835ea16db8) ) +ROM_END + +// once byteswapped this matches "outrun 2019 (usa) (beta).bin megadriv:outr2019up Out Run 2019 (USA, Prototype)" +// this was dumped from a PAL/UK unit, so maybe that 'beta' is really an alt Euro release, or was simply dumped from one of these Radica units and mislabeled? +ROM_START( rad_orun ) + ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASEFF ) + ROM_LOAD16_WORD_SWAP( "outrun.bin", 0x000000, 0x100000, CRC(4fd6d653) SHA1(57f0e4550ff883e4bb7857caef2c893c21f80b42) ) +ROM_END + +ROM_START( msi_sf2 ) + ROM_REGION( 0x400000, "maincpu", 0 ) + // The first part of the ROM seems to be a boot ROM for the enhanced MD clone menus, even if it does nothing here + // and is probably leftover from one of the multigame systems, hacked to only launch one game. We should emulate it... + // .. but the game ROM starts at 0xc8000 so we can cheat for now + ROM_LOAD16_WORD_SWAP( "29lv320.bin", 0x000000, 0xc8000, CRC(465b12f0) SHA1(7a058f6feb4f08f56ae0f7369c2ca9a9fe2ed40e) ) + ROM_CONTINUE(0x00000,0x338000) +ROM_END + +ROM_START( dgunl3227 ) + ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASE00 ) + // populated in init function + + ROM_REGION( 0x400000, "rom", 0 ) + ROM_LOAD16_WORD_SWAP( "myarcadepacman_s99jl032hbt1_9991227e_as_s29jl032h55tai01.bin", 0x000000, 0x400000, CRC(ecead966) SHA1(971e8da6eb720f670f4148c7e07922e4f24eb609) ) +ROM_END + + + +ROM_START( ra145 ) + /* + Data for the following games is corrupt (ranges approximate, based on areas of inconsistent readout) + + 3c0000 - 43ffff - James Bond 007 - The Duel (400171 - 41c600 is corrupt) + 4c0000 - 53ffff - Robocop 3 (507bd4 - 50ad43 is corrupt) + 540000 - 5bffff - Hokuto no Ken (540006 - 55fff2 is corrupt) + 640000 - 6bffff - Batman (640042 - 65ffaf is corrupt) + 7c0000 - 7fffff - Rambo 3 (7e031a - 7fffb9 is corrupt) + + Unfortunately as many of the games in this unit have been hacked, or are using pirate versions of the games + from the mid 90s (in a few cases, complete with trainers) that seem to have dropped out of circulation it + is not possible to repair the data in dump from the damaged unit. + + The unit also includes a duplicate copy of Thunder Force II instead of Revenge of Shinobi, this however + is not a dump issue, nor is Wacky Worlds being swapped with Fun and Games in the menu + */ + + ROM_REGION( 0x8000000, "maincpu", ROMREGION_ERASE00 ) + ROM_LOAD16_WORD_SWAP( "ra145.bin", 0x000000, 0x8000000, BAD_DUMP CRC(30583950) SHA1(855eae232e3830a505f9bc1a26edb3a7d15ce4d1) ) +ROM_END + + + + +void megadriv_radica_6button_state::init_megadriv_radica_6button_pal() +{ + init_megadrie(); + // 6 button game, so overwrite 3 button io handlers + m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); + m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); +} + +void megadriv_radica_6button_state::init_megadriv_radica_6button_ntsc() +{ + init_megadriv(); + // 6 button game, so overwrite 3 button io handlers + m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); + m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); +} + +void megadriv_dgunl_state::init_dgunl3227() +{ + uint8_t* rom = memregion("rom")->base(); + uint8_t* dst = memregion("maincpu")->base(); + size_t len = memregion("rom")->bytes(); + + std::vector buffer(len); + + for (int i = 0; i < len; i++) + buffer[i] = rom[i ^ 3]; + + std::copy(buffer.begin(), buffer.end(), &rom[0]); + + int baseaddr, size, dstaddr; + //baseaddr = 0x200000; size = 0x40000; // unknown data (unused menu data maybe?) + //baseaddr = 0x240000; size = 0x20000; // 'sample' program with UWOL header later too (lower part of menu program) + //baseaddr = 0x260000; size = 0x20000; // pirate version of Columns with Sega text removed + //baseaddr = 0x280000; size = 0x20000; // Fatal Labyrinth + //baseaddr = 0x2a0000; size = 0x20000; // pirate version of Block Out with EA logo and text removed + //baseaddr = 0x2c0000; size = 0x20000; // Flicky + //baseaddr = 0x2e0000; size = 0x20000; // Shove It + //baseaddr = 0x300000; size = 0x40000; // pirate version of Space Invaders 90 with Taito logos and copyright removed (also upper part of menu program - has extra header + bits of code for '202 in 1' menu which has been hacked to run the 3-in-1 menu) + + // the following 3 games are available to select from the menu on this system + //baseaddr = 0x340000; size = 0x40000; // Pac-Attack / Pac-Panic (used by this unit) + //baseaddr = 0x380000; size = 0x40000; // Pac-Mania (used by this unit) + //baseaddr = 0x3c0000; size = 0x40000; // Pac-Man (used by this unit) (2nd copy of header about halfway through?) + + // copy 1st part of menu code + baseaddr = 0x240000; + size = 0x020000; + dstaddr = 0x000000; + for (int i = 0; i < size; i++) + { + dst[i + dstaddr] = rom[baseaddr + i]; + } + + // copy 2nd part of menu code + baseaddr = 0x300000; + size = 0x040000; + dstaddr = 0x0c0000; + for (int i = 0; i < size; i++) + { + dst[i + dstaddr] = rom[baseaddr + i]; + } + + // copy pac-panic to first bank + baseaddr = 0x340000; + size = 0x040000; + dstaddr = 0x100000; + for (int i = 0; i < size; i++) + { + dst[i + dstaddr] = rom[baseaddr + i]; + } + + // copy pac-mania to 2nd bank + baseaddr = 0x380000; + size = 0x040000; + dstaddr = 0x180000; + for (int i = 0; i < size; i++) + { + dst[i + dstaddr] = rom[baseaddr + i]; + } + + // copy pac-man to 3nd bank + baseaddr = 0x3c0000; + size = 0x040000; + dstaddr = 0x200000; + for (int i = 0; i < size; i++) + { + dst[i + dstaddr] = rom[baseaddr + i]; + } + + // other data isn't copied because it's never referenced, therefore we don't know how it gets accessed + + init_megadriv(); +} + +void megadriv_ra145_state::init_ra145() +{ + m_romsize = 0x8000000; + init_megadriv(); + // 6 button game, so overwrite 3 button io handlers + m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); + m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); +} + +// US versions show 'Genesis' on the menu, show a www.radicagames.com splash screen, and use NTSC versions of the ROMs, sometimes region locked +// EU versions show 'Mega Drive' on the menu, show a www.radicagames.com splash screen, and use PAL versions of the ROMs, sometimes region locked +// UK versions show "Mega Drive' on the menu, show a www.radicauk.com splash screen, and use PAL versions of the ROMs, sometimes region locked + + +CONS( 2004, rad_gen1, 0, 0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadriv, "Radica / Sega", "Genesis Collection Volume 1 (Radica, Arcade Legends) (USA)", 0) +CONS( 2004, rad_md1, rad_gen1, 0, megadriv_radica_3button_pal, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie, "Radica / Sega", "Mega Drive Collection Volume 1 (Radica, Arcade Legends) (Europe)", 0) +// A UK version exists, showing the Radica UK boot screen + +CONS( 2004, rad_gen2, 0, 0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadriv, "Radica / Sega", "Genesis Collection Volume 2 (Radica, Arcade Legends) (USA)", 0) +CONS( 2004, rad_md2, rad_gen2, 0, megadriv_radica_3button_pal, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie, "Radica / Sega", "Mega Drive Collection Volume 2 (Radica, Arcade Legends) (UK)", 0) +// is there a Europe version with Radica Games boot screen and Mega Drive text? + +// box calls this Volume 3 +CONS( 2004, rad_sonic, 0, 0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadriv, "Radica / Sega", "Super Sonic Gold (Radica Plug & Play) (USA)", 0) +CONS( 2004, rad_sonicp,rad_sonic,0, megadriv_radica_3button_pal, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie, "Radica / Sega", "Super Sonic Gold (Radica Plug & Play) (UK)", 0) +// is there a Europe version with Radica Games boot screen and Mega Drive text? + +CONS( 2004, rad_sf2, 0, 0, megadriv_radica_6button_ntsc, megadriv_radica_6button, megadriv_radica_6button_state, init_megadriv_radica_6button_ntsc,"Radica / Capcom / Sega", "Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (USA)", 0) +CONS( 2004, rad_sf2p, rad_sf2, 0, megadriv_radica_6button_pal, megadriv_radica_6button, megadriv_radica_6button_state, init_megadriv_radica_6button_pal, "Radica / Capcom / Sega", "Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (UK)", 0) +// is there a Europe version with Radica Games boot screen and Mega Drive text? + +// still branded as Arcade Legends even if none of these were ever arcade games, European exclusive +CONS( 2004, rad_ssoc, 0, 0, megadriv_radica_3button_pal, megadriv_radica_3button, megadriv_radica_3button_state, init_megadrie, "Radica / Sensible Software / Sega", "Sensible Soccer plus [Cannon Fodder, Mega lo Mania] (Radica, Arcade Legends) (UK)", 0) +// is there a Europe version with Radica Games boot screen and Mega Drive text? + +// not region locked, no Radica logos, uncertain if other regions would differ +CONS( 2004, rad_orun, 0, 0, megadriv_radica_3button_pal, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie, "Radica / Sega", "Out Run 2019 (Radica Plug & Play, UK)", 0) + +// From a European unit but NTSC? - code is hacked from original USA Genesis game with region check still intact? (does the clone hardware always identify as such? or does the bypassed boot code skip the check?) +// TODO: move out of here eventually once the enhanced MD part is emulated rather than bypassed (it's probably the same as the 145-in-1 multigame unit, but modified to only include this single game) +CONS( 2018, msi_sf2, 0, 0, megadriv_radica_6button_ntsc, megadriv_msi_6button, megadriv_radica_6button_state, init_megadriv_radica_6button_ntsc, "MSI / Capcom / Sega", "Street Fighter II: Special Champion Edition (MSI Plug & Play) (Europe)", 0) + +// Are these (dgunl3227, ra145) actually emulation based? there is a block of 0x40000 bytes at the start of the ROM that doesn't +// appear to be used, very similar in both units. Banking also seems entirely illogical unless something else is managing it. +// The menu code in both seems to have the same origin, containing a bunch of unused pirate versions of MD games. +// The version of SF2 in the 'ra145' unit is the same as the one in the MSI unit above, and expects region to report US even +// when some of the units run at PAL speed? +// It is also confirmed from real hardware videos that these units do not have the usual sprite limits (so masking effect on Sonic title screen fails) + +// this is the only 'Pocket Player' unit to use Genesis on a Chip tech, the others are NES on a chip. +// some versions of this unit have an additional "Add Credits with 'A' or 'B'" screen after you select Pac-Man, this version does not. +CONS( 2018, dgunl3227, 0, 0, megadriv_dgunl_ntsc, megadriv_dgunl_1player, megadriv_dgunl_state, init_dgunl3227, "dreamGEAR", "My Arcade Pac-Man Pocket Player (DGUNL-3227)", 0 ) + +CONS( 2018, ra145, 0, 0, megadriv_dgunl_ntsc, megadriv_msi_6button, megadriv_ra145_state, init_ra145, "", "Retro Arcade 16 Bits Classic Edition Mini TV Game Console - 145 Classic Games - TV Arcade Plug and Play (Mega Drive bootlegs)", MACHINE_NOT_WORKING ) + diff --git a/src/mame/sega/megadriv_rad.h b/src/mame/sega/megadriv_rad.h new file mode 100644 index 00000000000..cc3bbde3316 --- /dev/null +++ b/src/mame/sega/megadriv_rad.h @@ -0,0 +1,107 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#ifndef MAME_INCLUDES_MEGADRIV_RAD_H +#define MAME_INCLUDES_MEGADRIV_RAD_H + +class megadriv_radica_state : public md_base_state +{ +public: + megadriv_radica_state(const machine_config &mconfig, device_type type, const char *tag) + : md_base_state(mconfig, type, tag), + m_bank(0), + m_romsize(0x400000), + m_rom(*this, "maincpu") + {} + + + uint16_t read(offs_t offset); + uint16_t read_a13(offs_t offset); + + void megadriv_radica_map(address_map &map); + +protected: + void megadriv_base_map(address_map &map); + int m_bank; + int m_romsize; + +private: + required_region_ptr m_rom; +}; + +class megadriv_radica_3button_state : public megadriv_radica_state +{ +public: + megadriv_radica_3button_state(const machine_config& mconfig, device_type type, const char* tag) + : megadriv_radica_state(mconfig, type, tag) + {} +public: + void megadriv_radica_3button_ntsc(machine_config &config); + void megadriv_radica_3button_pal(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; +}; + +class megadriv_radica_6button_state : public megadriv_radica_3button_state +{ +public: + void megadriv_radica_6button_ntsc(machine_config &config); + void megadriv_radica_6button_pal(machine_config &config); + + void init_megadriv_radica_6button_pal(); + void init_megadriv_radica_6button_ntsc(); + +public: + megadriv_radica_6button_state(const machine_config& mconfig, device_type type, const char* tag) + : megadriv_radica_3button_state(mconfig, type, tag) + {} + virtual void machine_start() override; +}; + +class megadriv_dgunl_state : public megadriv_radica_3button_state +{ +public: + megadriv_dgunl_state(const machine_config& mconfig, device_type type, const char* tag) + : megadriv_radica_3button_state(mconfig, type, tag) + {} +public: + void megadriv_dgunl_ntsc(machine_config &config); + + void init_dgunl3227(); + +protected: + virtual void machine_start() override; + uint16_t m_a1630a = 0; + +private: + uint16_t read_a16300(offs_t offset, uint16_t mem_mask); + uint16_t read_a16302(offs_t offset, uint16_t mem_mask); + virtual void write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask); + + void megadriv_dgunl_map(address_map &map); +}; + +class megadriv_ra145_state : public megadriv_dgunl_state +{ +public: + megadriv_ra145_state(const machine_config& mconfig, device_type type, const char* tag) + : megadriv_dgunl_state(mconfig, type, tag) + {} + + void init_ra145(); + +public: + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + virtual void write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask) override; +}; + + + +#endif // MAME_INCLUDES_MEGADRIV_RAD_H diff --git a/src/mame/sega/megadriv_sunplus_hybrid.cpp b/src/mame/sega/megadriv_sunplus_hybrid.cpp new file mode 100644 index 00000000000..678d84863da --- /dev/null +++ b/src/mame/sega/megadriv_sunplus_hybrid.cpp @@ -0,0 +1,171 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +/* + This is an enhanced 'Mega Drive / Genesis on a Chip' combined with a SunPlus SPG2xx system for the 'Bonus Games' menu + + It can take MegaDrive cartridges + + The MD side of things doesn't work as it needs enhanced chipset emulation? + + TODO: + hook up the SunPlus side again (see spg2xx_zone.cpp for hookup) + +*/ + +#include "emu.h" +#include "megadriv.h" + +class megadriv_sunplus_state : public md_base_state +{ +public: + megadriv_sunplus_state(const machine_config &mconfig, device_type type, const char *tag) + // Mega Drive part + : md_base_state(mconfig, type, tag), + m_md_is_running(true), + m_bank(0), + m_rom(*this, "maincpu") + {} + + // Mega Drive part + uint16_t read(offs_t offset); + void megadriv_sunplus_pal(machine_config &config); + void megadriv_sunplus_map(address_map &map); + + void init_reactmd(); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + bool m_md_is_running; + + // Mega Drive part + int m_bank; + required_region_ptr m_rom; + uint32_t screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(screen_vblank_hybrid); + +}; + + +// todo, use actual MD map, easier once maps are part of base class. +void megadriv_sunplus_state::megadriv_sunplus_map(address_map &map) +{ + map(0x000000, 0x3fffff).r(FUNC(megadriv_sunplus_state::read)); /* Cartridge Program Rom */ + map(0xa00000, 0xa01fff).rw(FUNC(megadriv_sunplus_state::megadriv_68k_read_z80_ram), FUNC(megadriv_sunplus_state::megadriv_68k_write_z80_ram)); + map(0xa02000, 0xa03fff).w(FUNC(megadriv_sunplus_state::megadriv_68k_write_z80_ram)); + map(0xa04000, 0xa04003).rw(FUNC(megadriv_sunplus_state::megadriv_68k_YM2612_read), FUNC(megadriv_sunplus_state::megadriv_68k_YM2612_write)); + map(0xa06000, 0xa06001).w(FUNC(megadriv_sunplus_state::megadriv_68k_z80_bank_write)); + map(0xa10000, 0xa1001f).rw(FUNC(megadriv_sunplus_state::megadriv_68k_io_read), FUNC(megadriv_sunplus_state::megadriv_68k_io_write)); + map(0xa11100, 0xa11101).rw(FUNC(megadriv_sunplus_state::megadriv_68k_check_z80_bus), FUNC(megadriv_sunplus_state::megadriv_68k_req_z80_bus)); + map(0xa11200, 0xa11201).w(FUNC(megadriv_sunplus_state::megadriv_68k_req_z80_reset)); + map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); + map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram"); +} + +uint16_t megadriv_sunplus_state::read(offs_t offset) +{ + return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (0x400000 - 1))/2]; +} + + +// controller is wired directly into unit, no controller slots +static INPUT_PORTS_START( megadriv_sunplus ) + PORT_INCLUDE( md_common ) + + PORT_MODIFY("PAD1") + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 ) + //PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_MODIFY("PAD2") + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START2 ) + //PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + + +void megadriv_sunplus_state::machine_start() +{ + logerror("megadriv_sunplus_state::machine_start\n"); + md_base_state::machine_start(); + + m_vdp->stop_timers(); + save_item(NAME(m_bank)); +} + +void megadriv_sunplus_state::machine_reset() +{ + logerror("megadriv_sunplus_state::machine_reset\n"); + md_base_state::machine_reset(); +} + +uint32_t megadriv_sunplus_state::screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + if (m_md_is_running) + { + /* Copies a bitmap */ + return screen_update_megadriv(screen, bitmap, cliprect); + } + + return 0; +} + +WRITE_LINE_MEMBER(megadriv_sunplus_state::screen_vblank_hybrid) +{ + if (m_md_is_running) + { + /* Used to Sync the timing */ + md_base_state::screen_vblank_megadriv(state); + } +} + + +void megadriv_sunplus_state::megadriv_sunplus_pal(machine_config &config) +{ + md_pal(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_sunplus_state::megadriv_sunplus_map); + + m_screen->set_screen_update(FUNC(megadriv_sunplus_state::screen_update_hybrid)); + m_screen->screen_vblank().set(FUNC(megadriv_sunplus_state::screen_vblank_hybrid)); +} + + +void megadriv_sunplus_state::init_reactmd() +{ + uint16_t *ROM = (uint16_t*)memregion("sunplus")->base(); + int size = memregion("sunplus")->bytes(); + + for (int i = 0; i < size/2; i++) + { + ROM[i] = bitswap<16>(ROM[i], 15, 13, 14, 12, 7, 6, 5, 4, + 11, 10, 9, 8, 3, 1, 2, 0); + + ROM[i] = ROM[i] ^ 0xa5a5; + } + + init_megadrie(); +} + + +ROM_START( reactmd ) + ROM_REGION( 0x2000000, "maincpu", ROMREGION_ERASE00 ) // this contains the MD games and main boot menu + ROM_LOAD16_WORD_SWAP( "reactormd.bin", 0x0000, 0x2000000, CRC(fe9664a4) SHA1(d475b524f576c9d1d90aed20c7467cc652396baf) ) + + ROM_REGION( 0x4000000, "sunplus", ROMREGION_ERASE00 ) // this contains the SunPlus games + ROM_LOAD16_WORD_SWAP( "reactor_md_sunplus-full.bin", 0x0000, 0x4000000, CRC(843aa58c) SHA1(07cdc6d4aa0057939c145ece01a9aca73c7f1f2b) ) + ROM_IGNORE(0x4000000) // the 2nd half of the ROM can't be accessed by the PCB (address line tied low) (contains garbage? data) +ROM_END + + +// Two systems in one unit - Genesis on a Chip and SunPlus, only the SunPlus part is currently emulated. Genesis on a chip is a very poor implementation with many issues on real hardware. +// This should actually boot to a menu on the MD side, with the SunPlus only being enabled if selected from that menu. MD side menu runs in some enhanced / custom MD mode though. +// Badminton hangs, as it does in the 49-in-1 above +CONS( 2009, reactmd, 0, 0, megadriv_sunplus_pal, megadriv_sunplus, megadriv_sunplus_state, init_reactmd, "AtGames / Sega / Waixing", "Reactor MD (PAL)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) + diff --git a/src/mame/sega/megadriv_vt_hybrid.cpp b/src/mame/sega/megadriv_vt_hybrid.cpp new file mode 100644 index 00000000000..0644fb1ab3a --- /dev/null +++ b/src/mame/sega/megadriv_vt_hybrid.cpp @@ -0,0 +1,168 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +/* + This is an enhanced 'Mega Drive / Genesis on a Chip' combined with a VT02/VT03 system for the 'Bonus Games' menu + + The menu for the MD side of things doesn't work as it needs enhanced chipset emulation? + at the moment it just boots the game in the lowest ROM bank (Flicky) + + TODO: + hook up the VT side again + +*/ + +#include "emu.h" +#include "megadriv.h" + +namespace { + +class megadriv_vt0203_state : public md_base_state +{ +public: + megadriv_vt0203_state(const machine_config &mconfig, device_type type, const char *tag) + // Mega Drive part + : md_base_state(mconfig, type, tag), + m_md_is_running(true), + m_bank(0), + m_rom(*this, "maincpu") + {} + + // Mega Drive part + uint16_t read(offs_t offset); + void megadriv_vt0203_pal(machine_config &config); + void megadriv_vt0203_map(address_map &map); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + bool m_md_is_running; + + // Mega Drive part + int m_bank; + required_region_ptr m_rom; + uint32_t screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(screen_vblank_hybrid); + +}; + + +// todo, use actual MD map, easier once maps are part of base class. +void megadriv_vt0203_state::megadriv_vt0203_map(address_map &map) +{ + map(0x000000, 0x3fffff).r(FUNC(megadriv_vt0203_state::read)); /* Cartridge Program Rom */ + map(0xa00000, 0xa01fff).rw(FUNC(megadriv_vt0203_state::megadriv_68k_read_z80_ram), FUNC(megadriv_vt0203_state::megadriv_68k_write_z80_ram)); + map(0xa02000, 0xa03fff).w(FUNC(megadriv_vt0203_state::megadriv_68k_write_z80_ram)); + map(0xa04000, 0xa04003).rw(FUNC(megadriv_vt0203_state::megadriv_68k_YM2612_read), FUNC(megadriv_vt0203_state::megadriv_68k_YM2612_write)); + map(0xa06000, 0xa06001).w(FUNC(megadriv_vt0203_state::megadriv_68k_z80_bank_write)); + map(0xa10000, 0xa1001f).rw(FUNC(megadriv_vt0203_state::megadriv_68k_io_read), FUNC(megadriv_vt0203_state::megadriv_68k_io_write)); + map(0xa11100, 0xa11101).rw(FUNC(megadriv_vt0203_state::megadriv_68k_check_z80_bus), FUNC(megadriv_vt0203_state::megadriv_68k_req_z80_bus)); + map(0xa11200, 0xa11201).w(FUNC(megadriv_vt0203_state::megadriv_68k_req_z80_reset)); + map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); + map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram"); +} + +uint16_t megadriv_vt0203_state::read(offs_t offset) +{ + return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (0x400000 - 1))/2]; +} + + +// controller is wired directly into unit, no controller slots +static INPUT_PORTS_START( megadriv_vt0203 ) + PORT_INCLUDE( md_common ) + + PORT_MODIFY("PAD1") +#if 0 + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 ) +#else + PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) +#endif + + PORT_MODIFY("PAD2") +#if 0 + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START2 ) +##else + PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) +#endif +INPUT_PORTS_END + + +void megadriv_vt0203_state::machine_start() +{ + logerror("megadriv_vt0203_state::machine_start\n"); + md_base_state::machine_start(); + + m_vdp->stop_timers(); + save_item(NAME(m_bank)); +} + +void megadriv_vt0203_state::machine_reset() +{ + logerror("megadriv_vt0203_state::machine_reset\n"); + md_base_state::machine_reset(); +} + +uint32_t megadriv_vt0203_state::screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + if (m_md_is_running) + { + /* Copies a bitmap */ + return screen_update_megadriv(screen, bitmap, cliprect); + } + + return 0; +} + +WRITE_LINE_MEMBER(megadriv_vt0203_state::screen_vblank_hybrid) +{ + if (m_md_is_running) + { + /* Used to Sync the timing */ + md_base_state::screen_vblank_megadriv(state); + } +} + + +void megadriv_vt0203_state::megadriv_vt0203_pal(machine_config &config) +{ + md_pal(config); + m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_vt0203_state::megadriv_vt0203_map); + + m_screen->set_screen_update(FUNC(megadriv_vt0203_state::screen_update_hybrid)); + m_screen->screen_vblank().set(FUNC(megadriv_vt0203_state::screen_vblank_hybrid)); + + // TODO: add the VT part, this might require refactoring of the VT stuff as the SoC currently contains the screen + // but instead we'll need to use a shared screen that is reconfigured depending on which part is enabled +} + +} // anonymous namespace + + +ROM_START( sarc110 ) + ROM_REGION( 0x1000000, "maincpu", 0 ) // Mega Drive part + ROM_LOAD16_WORD_SWAP( "superarcade.bin", 0x000000, 0x1000000, CRC(be732867) SHA1(3857b2fbddd6a548c81caf64122e47a0df079be5) ) + + ROM_REGION( 0x400000, "mainrom", 0 ) // VT02/03 part + ROM_LOAD( "ic1.prg", 0x00000, 0x400000, CRC(de76f71f) SHA1(ff6b37a76c6463af7ae901918fc008b4a2863951) ) +ROM_END + +ROM_START( sarc110a ) + ROM_REGION( 0x1000000, "maincpu", 0 ) // Mega Drive part + ROM_LOAD16_WORD_SWAP( "superarcade.bin", 0x000000, 0x1000000, CRC(be732867) SHA1(3857b2fbddd6a548c81caf64122e47a0df079be5) ) + + ROM_REGION( 0x400000, "mainrom", 0 ) // VT02/03 part + ROM_LOAD( "ic1_ver2.prg", 0x00000, 0x400000, CRC(b97a0dc7) SHA1(bace32d73184df914113de5336e29a7a6f4c03fa) ) +ROM_END + + +CONS( 200?, sarc110, 0, 0, megadriv_vt0203_pal, megadriv_vt0203, megadriv_vt0203_state, init_megadrie, "", "Super Arcade 101-in-1 (set 1)", MACHINE_NOT_WORKING) +CONS( 200?, sarc110a,sarc110, 0, megadriv_vt0203_pal, megadriv_vt0203, megadriv_vt0203_state, init_megadrie, "", "Super Arcade 101-in-1 (set 2)", MACHINE_NOT_WORKING) diff --git a/src/mame/sega/mie.cpp b/src/mame/sega/mie.cpp new file mode 100644 index 00000000000..77639bd5ea8 --- /dev/null +++ b/src/mame/sega/mie.cpp @@ -0,0 +1,374 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +#include "emu.h" +#include "mie.h" +#include "maple-dc.h" + +// MIE aka Sega 315-6146, MAPLE-JVS bridge Z80-based MCU +// +// Todos: +// - ports 00-0f is identical to Sega 315-5338A/315-5649 I/O ICs +// (used in Sega H1, Model 2, etc). devicefication needed. +// +// - ports 10-15 and 20-25 is standard 8250/16xxx UARTs. +// +// - ports a0-af - external I/O 1, in JVS I/Os connected to NEC uPD71053 counter/timer +// +// - ports c0-cf - external I/O 2, not used +// in JVS I/Os can be connected to (unpopulated) 315-5296 I/O IC, if enabled by DIP switch +// +// - both memory and I/O address spaces can be directly accessed by host system (used in Hikaru) +// +// - Speed is all wrong + + +DEFINE_DEVICE_TYPE(MIE, mie_device, "mie", "Sega 315-6146 MIE") +DEFINE_DEVICE_TYPE(MIE_JVS, mie_jvs_device, "mie_jvs", "JVS (MIE)") + +void mie_device::mie_map(address_map &map) +{ + map(0x0000, 0x07ff).rom(); + map(0x0800, 0x6fff).r(FUNC(mie_device::read_ff)); + map(0x7000, 0x7002).rw(FUNC(mie_device::control_r), FUNC(mie_device::control_w)).mirror(0x07c0); + map(0x7003, 0x7003).rw(FUNC(mie_device::lreg_r), FUNC(mie_device::lreg_w)).mirror(0x07c0); + map(0x7004, 0x7023).rw(FUNC(mie_device::tbuf_r), FUNC(mie_device::tbuf_w)).mirror(0x07c0); + map(0x7024, 0x703f).r(FUNC(mie_device::read_00)).mirror(0x07c0); + map(0x7800, 0x7fff).r(FUNC(mie_device::read_78xx)); + map(0x8000, 0xffff).ram(); +} + +void mie_device::mie_port(address_map &map) +{ + map.global_mask(0xff); + map(0x00, 0x07).rw(FUNC(mie_device::gpio_r), FUNC(mie_device::gpio_w)); + map(0x08, 0x08).rw(FUNC(mie_device::gpiodir_r), FUNC(mie_device::gpiodir_w)); + map(0x0f, 0x0f).rw(FUNC(mie_device::adc_r), FUNC(mie_device::adc_w)); + map(0x10, 0x10).rw(FUNC(mie_device::jvs_r), FUNC(mie_device::jvs_w)); // ports 1x and 2x is standard UARTs, TODO handle it properly + map(0x12, 0x12).w(FUNC(mie_device::jvs_dest_w)); + map(0x13, 0x13).w(FUNC(mie_device::jvs_lcr_w)); + map(0x15, 0x15).r(FUNC(mie_device::jvs_status_r)); + map(0x30, 0x30).rw(FUNC(mie_device::irq_enable_r), FUNC(mie_device::irq_enable_w)); + map(0x50, 0x50).rw(FUNC(mie_device::maple_irqlevel_r), FUNC(mie_device::maple_irqlevel_w)); + map(0x70, 0x70).rw(FUNC(mie_device::irq_pending_r), FUNC(mie_device::irq_pending_w)); + map(0x90, 0x90).w(FUNC(mie_device::jvs_control_w)); + map(0x91, 0x91).r(FUNC(mie_device::jvs_sense_r)); +} + +ROM_START( mie ) + ROM_REGION( 0x800, "mie", 0 ) + ROM_LOAD( "315-6146.bin", 0x000, 0x800, CRC(9b197e35) SHA1(864d14d58732dd4e2ee538ccc71fa8df7013ba06)) +ROM_END + +const tiny_rom_entry *mie_device::device_rom_region() const +{ + return ROM_NAME(mie); +} + +void mie_device::device_add_mconfig(machine_config &config) +{ + Z80(config, cpu, DERIVED_CLOCK(1,1)); + cpu->set_addrmap(AS_PROGRAM, &mie_device::mie_map); + cpu->set_addrmap(AS_IO, &mie_device::mie_port); + cpu->set_irq_acknowledge_callback(FUNC(mie_device::irq_callback)); +} + +mie_jvs_device::mie_jvs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : jvs_host(mconfig, MIE_JVS, tag, owner, clock) +{ +} + +mie_device::mie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : maple_device(mconfig, MIE, tag, owner, clock) + , cpu(*this, "mie") + , jvs(*this, finder_base::DUMMY_TAG) + , gpio_port(*this, {finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG}) +{ +} + +void mie_device::device_start() +{ + maple_device::device_start(); + timer = timer_alloc(FUNC(mie_device::update_irq_reply), this); + + save_item(NAME(gpiodir)); + save_item(NAME(gpio_val)); + save_item(NAME(irq_enable)); + save_item(NAME(irq_pending)); + save_item(NAME(maple_irqlevel)); + + // patch out MIE RAM test + // TODO: figure out why SH4 code doesn't wait long enough for internal firmware's RAM test completed in the case of reset + uint32_t *rom = (uint32_t*)memregion("mie")->base(); + rom[0x144/4] = 0x0001d8c3; +} + +void mie_device::device_reset() +{ + lreg = 0; + control = 0; + jvs_control = 0; + jvs_dest = 0; + jvs_rpos = 0; + memset(gpio_val, 0, sizeof(gpio_val)); + gpiodir = 0xff; + maple_irqlevel = 0xff; + irq_enable = irq_pending = 0; + cpu->reset(); + timer->adjust(attotime::never); + memset(tbuf, 0, sizeof(tbuf)); +} + +uint8_t mie_device::control_r(offs_t offset) +{ + return control >> (8*offset); +} + +void mie_device::control_w(offs_t offset, uint8_t data) +{ + uint32_t prev_control = control; + int shift = offset*8; + control = (control & ~(255 << shift)) | (data << shift); + + if((!(prev_control & CTRL_TXB) && (control & CTRL_TXB)) || + (!(prev_control & CTRL_CTXB) && (control & CTRL_CTXB))) { + control &= ~(CTRL_TFB|CTRL_RXB|CTRL_RFB|CTRL_BFOV|CTRL_EMP); + reply_size = lreg+1; + if(reply_size > TBUF_SIZE) + reply_size = TBUF_SIZE; + memcpy(reply_buffer, tbuf, reply_size*4); + reply_partial = !(control & CTRL_ENDP); + + timer->adjust(attotime::from_usec(20)); + } +} + +TIMER_CALLBACK_MEMBER(mie_device::update_irq_reply) +{ + if(control & CTRL_RXB) { + control &= ~CTRL_RXB; + control |= CTRL_RFB; + raise_irq(maple_irqlevel); + } + if(control & (CTRL_TXB|CTRL_CTXB)) { + reply_ready(0); + lreg -= reply_size; + if(reply_partial) { + control &= ~CTRL_CTXB; + control |= CTRL_EMP; + } else { + control &= ~(CTRL_TXB|CTRL_CTXB); + control |= CTRL_TFB|CTRL_EMP; + } + } + if(control & CTRL_HRES) { + raise_irq(maple_irqlevel); + } +} + +void mie_device::maple_w(const uint32_t *data, uint32_t in_size) +{ + memcpy(tbuf, data, in_size*4); + lreg = in_size-1; + // currently not known how/then CTRL_HRES is cleared after reset, lets clear it at packet receive + control &= ~(CTRL_HRES|CTRL_TXB|CTRL_TFB|CTRL_RFB|CTRL_BFOV); + control |= CTRL_RXB; + + timer->adjust(attotime::from_usec(20)); +} + +uint8_t mie_device::read_ff() +{ + return 0xff; +} + +uint8_t mie_device::read_00() +{ + return 0x00; +} + +uint8_t mie_device::read_78xx(offs_t offset) +{ + // Internal rom tests (7800) & 80 and jumps to 8010 if non-zero + // What we return is what a memdump sees on a naomi2 board + return offset & 4 ? 0xff : 0x00; +} + +uint8_t mie_device::gpio_r(offs_t offset) +{ + if(gpiodir & (1 << offset)) + return gpio_port[offset] ? gpio_port[offset]->read() : 0xff; + else + return gpio_val[offset]; +} + +void mie_device::gpio_w(offs_t offset, uint8_t data) +{ + gpio_val[offset] = data; + if(!(gpiodir & (1 << offset)) && gpio_port[offset]) + gpio_port[offset]->write(data, 0xff); +} + +uint8_t mie_device::gpiodir_r() +{ + return gpiodir; +} + +void mie_device::gpiodir_w(uint8_t data) +{ + gpiodir = data; +} + +uint8_t mie_device::adc_r() +{ + return 0; +} + +void mie_device::adc_w(uint8_t data) +{ +} + +uint8_t mie_device::irq_enable_r() +{ + return irq_enable; +} + +void mie_device::irq_enable_w(uint8_t data) +{ + irq_enable = data; + recalc_irq(); +} + +uint8_t mie_device::maple_irqlevel_r() +{ + return maple_irqlevel; +} + +void mie_device::maple_irqlevel_w(uint8_t data) +{ + maple_irqlevel = data; +} + +uint8_t mie_device::irq_pending_r() +{ + return irq_pending; +} + +void mie_device::irq_pending_w(uint8_t data) +{ + irq_pending = data; + recalc_irq(); +} + +void mie_device::recalc_irq() +{ + cpu->set_input_line(0, irq_enable & irq_pending & 0x7f ? ASSERT_LINE : CLEAR_LINE); +} + +IRQ_CALLBACK_MEMBER(mie_device::irq_callback) +{ + if(!(irq_enable & irq_pending & 0x7f)) + throw emu_fatalerror("MIE irq callback called with enable=%02x, pending=%02x", irq_enable, irq_pending); + + int level = -1; + for(level = 0; level < 7; level++) + if((irq_enable & irq_pending) & (1 << level)) + break; + + irq_pending &= ~(1 << level); + recalc_irq(); + return 0xf2+2*level; +} + +void mie_device::raise_irq(int level) +{ + if(level>=0 && level<7) { + irq_pending |= 1<> 2] >> (8*(offset & 3)); +} + +void mie_device::tbuf_w(offs_t offset, uint8_t data) +{ + int shift = (offset & 3)*8; + tbuf[offset >> 2] = (tbuf[offset >> 2] & ~(255 << shift)) | (data << shift); +} + +uint8_t mie_device::lreg_r() +{ + return lreg; +} + +void mie_device::lreg_w(uint8_t data) +{ + lreg = data; +} + +uint8_t mie_device::jvs_r() +{ + if(jvs_lcr & 0x80) + return 0; + + const uint8_t *buf; + uint32_t size; + jvs->get_encoded_reply(buf, size); + if(jvs_rpos >= size) + return 0; + return buf[jvs_rpos++]; +} + +void mie_device::jvs_w(uint8_t data) +{ + if(jvs_lcr & 0x80) + return; + + jvs->push(data); +} + +void mie_device::jvs_dest_w(uint8_t data) +{ + jvs_dest = data; +} + +uint8_t mie_device::jvs_status_r() +{ + // 01 = ready for reading + // 20 = ready for writing + // 40 = sending done + const uint8_t *buf; + uint32_t size; + jvs->get_encoded_reply(buf, size); + return 0x60 | (jvs_rpos < size ? 1 : 0); +} + +void mie_device::jvs_control_w(uint8_t data) +{ + if((jvs_control & 1) && !(data & 1)) { + jvs->commit_encoded(); + jvs_rpos = 0; + } + jvs_control = data; +} + +void mie_device::jvs_lcr_w(uint8_t data) +{ + jvs_lcr = data; +} + +uint8_t mie_device::jvs_sense_r() +{ + return 0x8c | (jvs->get_address_set_line() ? 2 : 0) | (jvs->get_presence_line() ? 0 : 1); +} + +void mie_device::maple_reset() +{ + control &= ~(CTRL_RXB|CTRL_TXB|CTRL_TFB|CTRL_RFB|CTRL_BFOV); + control |= CTRL_HRES; + + timer->adjust(attotime::from_usec(20)); +} diff --git a/src/mame/sega/mie.h b/src/mame/sega/mie.h new file mode 100644 index 00000000000..57792269ec0 --- /dev/null +++ b/src/mame/sega/mie.h @@ -0,0 +1,142 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +#ifndef MAME_MACHINE_MIE_H +#define MAME_MACHINE_MIE_H + +#pragma once + +#include "mapledev.h" + +#include "cpu/z80/z80.h" +#include "machine/eepromser.h" +#include "machine/jvshost.h" + + +class mie_jvs_device; + +// ======================> mie_device + +class mie_device : public maple_device +{ +public: + template + mie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&host_tag, int host_port, U &&jvs_tag) + : mie_device(mconfig, tag, owner, clock) + { + host.set_tag(std::forward(host_tag)); + set_host_port(host_port); + jvs.set_tag(std::forward(jvs_tag)); + } + + mie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template + void set_gpio_name(T &&gpio_port_tag) { gpio_port[Which].set_tag(std::forward(gpio_port_tag)); } + template + void set_gpio_names(T &&first_tag, U &&... other_tags) + { + set_gpio_name(std::forward(first_tag)); + set_gpio_names(std::forward(other_tags)...); + } + + uint8_t control_r(offs_t offset); + void control_w(offs_t offset, uint8_t data); + uint8_t lreg_r(); + void lreg_w(uint8_t data); + uint8_t tbuf_r(offs_t offset); + void tbuf_w(offs_t offset, uint8_t data); + uint8_t gpio_r(offs_t offset); + void gpio_w(offs_t offset, uint8_t data); + uint8_t gpiodir_r(); + void gpiodir_w(uint8_t data); + uint8_t adc_r(); + void adc_w(uint8_t data); + + uint8_t irq_enable_r(); + void irq_enable_w(uint8_t data); + uint8_t maple_irqlevel_r(); + void maple_irqlevel_w(uint8_t data); + uint8_t irq_pending_r(); + void irq_pending_w(uint8_t data); + + uint8_t jvs_r(); + void jvs_w(uint8_t data); + void jvs_dest_w(uint8_t data); + uint8_t jvs_status_r(); + void jvs_control_w(uint8_t data); + uint8_t jvs_sense_r(); + void jvs_lcr_w(uint8_t data); + + uint8_t read_ff(); + uint8_t read_00(); + uint8_t read_78xx(offs_t offset); + + void maple_w(const uint32_t *data, uint32_t in_size) override; + virtual void maple_reset() override; + + void mie_map(address_map &map); + void mie_port(address_map &map); + +protected: + template void set_gpio_names() { } + + // device-level overrides + 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; + + TIMER_CALLBACK_MEMBER(update_irq_reply); + +private: + enum { TBUF_SIZE = 8 }; + + enum { + CTRL_TXB = 0x000001, // Start transmit + CTRL_CTXB = 0x000002, // Continue transmit flag (when doing multipart) + CTRL_ENDP = 0x000004, // Add an end pattern + CTRL_EMP = 0x000100, // Empty flag + CTRL_PERR = 0x000200, // Parity error + CTRL_BFOV = 0x000800, // Set when overflow, cleared to 0 when starting send/receive + CTRL_RXB = 0x001000, // Receiving + CTRL_RFB = 0x002000, // Receive done + CTRL_TFB = 0x004000, // Transmit done + CTRL_HRES = 0x008000 // Reset pattern received + }; + + // internal state + required_device cpu; + emu_timer *timer = nullptr; + required_device jvs; + optional_ioport_array<8> gpio_port; + + uint32_t tbuf[TBUF_SIZE]{}; + uint32_t control = 0, lreg = 0, jvs_rpos = 0; + uint8_t gpiodir = 0, gpio_val[8]{}; + uint8_t irq_enable = 0, irq_pending = 0, maple_irqlevel = 0; + uint8_t jvs_control = 0, jvs_dest = 0; + uint8_t jvs_lcr = 0; + + void raise_irq(int level); + void recalc_irq(); + IRQ_CALLBACK_MEMBER(irq_callback); +}; + +// Trampoline class, required for device discovery +class mie_jvs_device : public jvs_host +{ +public: + friend class mie_device; + + // construction/destruction + mie_jvs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + + +// device type definition +DECLARE_DEVICE_TYPE(MIE, mie_device) +DECLARE_DEVICE_TYPE(MIE_JVS, mie_jvs_device) + +#endif // MAME_MACHINE_MIE_H diff --git a/src/mame/sega/naomig1.cpp b/src/mame/sega/naomig1.cpp new file mode 100644 index 00000000000..059339e08ed --- /dev/null +++ b/src/mame/sega/naomig1.cpp @@ -0,0 +1,241 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +#include "emu.h" +#include "naomig1.h" + +void naomi_g1_device::amap(address_map &map) +{ + map(0x04, 0x07).rw(FUNC(naomi_g1_device::sb_gdstar_r), FUNC(naomi_g1_device::sb_gdstar_w)); + map(0x08, 0x0b).rw(FUNC(naomi_g1_device::sb_gdlen_r), FUNC(naomi_g1_device::sb_gdlen_w)); + map(0x0c, 0x0f).rw(FUNC(naomi_g1_device::sb_gddir_r), FUNC(naomi_g1_device::sb_gddir_w)); + map(0x14, 0x17).rw(FUNC(naomi_g1_device::sb_gden_r), FUNC(naomi_g1_device::sb_gden_w)); + map(0x18, 0x1b).rw(FUNC(naomi_g1_device::sb_gdst_r), FUNC(naomi_g1_device::sb_gdst_w)); + map(0x80, 0x83).w(FUNC(naomi_g1_device::sb_g1rrc_w)); + map(0x84, 0x87).w(FUNC(naomi_g1_device::sb_g1rwc_w)); + map(0x88, 0x8b).w(FUNC(naomi_g1_device::sb_g1frc_w)); + map(0x8c, 0x8f).w(FUNC(naomi_g1_device::sb_g1fwc_w)); + map(0x90, 0x93).w(FUNC(naomi_g1_device::sb_g1crc_w)); + map(0x94, 0x97).w(FUNC(naomi_g1_device::sb_g1cwc_w)); + map(0xa0, 0xa3).w(FUNC(naomi_g1_device::sb_g1gdrc_w)); + map(0xa4, 0xa7).w(FUNC(naomi_g1_device::sb_g1gdwc_w)); + map(0xb0, 0xb3).r(FUNC(naomi_g1_device::sb_g1sysm_r)); + map(0xb4, 0xb7).w(FUNC(naomi_g1_device::sb_g1crdyc_w)); + map(0xb8, 0xbb).w(FUNC(naomi_g1_device::sb_gdapro_w)); + map(0xf4, 0xf7).r(FUNC(naomi_g1_device::sb_gdstard_r)); + map(0xf8, 0xfb).r(FUNC(naomi_g1_device::sb_gdlend_r)); +} + +naomi_g1_device::naomi_g1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , irq_cb(*this) + , ext_irq_cb(*this) + , reset_out_cb(*this) +{ +} + +void naomi_g1_device::device_start() +{ + timer = timer_alloc(FUNC(naomi_g1_device::trigger_gdrom_irq), this); + irq_cb.resolve_safe(); + ext_irq_cb.resolve_safe(); + reset_out_cb.resolve_safe(); + + save_item(NAME(gdstar)); + save_item(NAME(gdlen)); + save_item(NAME(gddir)); + save_item(NAME(gden)); + save_item(NAME(gdst)); +} + +void naomi_g1_device::device_reset() +{ + gdstar = 0; + gdlen = 0; + gddir = 0; + gden = 0; + gdst = 0; + set_ext_irq(CLEAR_LINE); +} + +TIMER_CALLBACK_MEMBER(naomi_g1_device::trigger_gdrom_irq) +{ + if(!gdst) + return; + gdst = 0; + irq_cb(DMA_GDROM_IRQ); +} + +uint32_t naomi_g1_device::sb_gdstar_r() +{ + return gdstar; +} + +void naomi_g1_device::sb_gdstar_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&gdstar); + logerror("G1: gdstar_w %08x @ %08x\n", data, mem_mask); +} + +uint32_t naomi_g1_device::sb_gdlen_r() +{ + return gdlen; +} + +void naomi_g1_device::sb_gdlen_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&gdlen); + logerror("G1: gdlen_w %08x @ %08x\n", data, mem_mask); +} + +uint32_t naomi_g1_device::sb_gddir_r() +{ + return gddir; +} + +void naomi_g1_device::sb_gddir_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&gddir); + gddir &= 1; + logerror("G1: gddir_w %08x @ %08x\n", data, mem_mask); +} + +uint32_t naomi_g1_device::sb_gden_r() +{ + return gden; +} + +void naomi_g1_device::sb_gden_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&gden); + gden &= 1; + logerror("G1: gden_w %08x @ %08x\n", data, mem_mask); +} + +uint32_t naomi_g1_device::sb_gdst_r() +{ + return gdst; +} + +void naomi_g1_device::sb_gdst_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + uint32_t old = gdst; + COMBINE_DATA(&gdst); + gdst &= 1; + logerror("G1: gdst_w %08x @ %08x\n", data, mem_mask); + if(!old && gdst && gden) { + // DMA starts + + uint32_t adr = gdstar; + uint32_t len = gdlen; + + // Deunan says round up to 32, doc says complete with zeroes. + // Virtua Tennis requires one of the two to boot + // We'll go with DK for now. + // + // In any case, low bit is ignored + len = (len + 30) & ~30; + + bool to_mainram = true; + while(len) { + uint8_t *base; + uint32_t limit = len; + dma_get_position(base, limit, to_mainram); + + if(!limit) + break; + uint32_t tlen = limit > len ? len : limit; + dma(base, adr, tlen, to_mainram); + adr += tlen; + len -= tlen; + dma_advance(tlen); + } + + while(len && to_mainram) { + unsigned char zero[32]; + memset(zero, 0, sizeof(zero)); + uint32_t tlen = len > 32 ? 32 : len; + dma(zero, adr, tlen, to_mainram); + adr += tlen; + len -= tlen; + } + + /* 12x * 75 Hz = 0,00(1) secs per sector */ + /* TODO: make DMA to be single step */ + timer->adjust(attotime::from_usec(1111*(gdlen/2048))); + } +} + +void naomi_g1_device::sb_g1rrc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: g1rrc_w %08x @ %08x\n", data, mem_mask); +} + +void naomi_g1_device::sb_g1rwc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: g1rwc_w %08x @ %08x\n", data, mem_mask); +} + +void naomi_g1_device::sb_g1crc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: g1crc_w %08x @ %08x\n", data, mem_mask); +} + +void naomi_g1_device::sb_g1cwc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: g1cwc_w %08x @ %08x\n", data, mem_mask); +} + +void naomi_g1_device::sb_g1frc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: g1frc_w %08x @ %08x\n", data, mem_mask); +} + +void naomi_g1_device::sb_g1fwc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: g1fwc_w %08x @ %08x\n", data, mem_mask); +} + +void naomi_g1_device::sb_g1gdrc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: g1gdrc_w %08x @ %08x\n", data, mem_mask); +} + +void naomi_g1_device::sb_g1gdwc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: g1gdwc_w %08x @ %08x\n", data, mem_mask); +} + +uint32_t naomi_g1_device::sb_g1sysm_r(offs_t offset, uint32_t mem_mask) +{ + logerror("G1: g1sysm_r @ %08x\n", mem_mask); + return 0; +} + +void naomi_g1_device::sb_g1crdyc_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: g1crdyc_w %08x @ %08x\n", data, mem_mask); +} + +void naomi_g1_device::sb_gdapro_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + logerror("G1: gdapro_w %08x @ %08x\n", data, mem_mask); +} + +uint32_t naomi_g1_device::sb_gdstard_r(offs_t offset, uint32_t mem_mask) +{ + logerror("G1: gdstard_r @ %08x\n", mem_mask); + return 0; +} + +uint32_t naomi_g1_device::sb_gdlend_r(offs_t offset, uint32_t mem_mask) +{ + logerror("G1: gdlend_r @ %08x\n", mem_mask); + return 0; +} + +void naomi_g1_device::dma(void *dma_ptr, uint32_t main_adr, uint32_t size, bool to_mainram) +{ + if(!_dma_cb.isnull()) + _dma_cb(main_adr, dma_ptr, size >> 5, 32, to_mainram); +} diff --git a/src/mame/sega/naomig1.h b/src/mame/sega/naomig1.h new file mode 100644 index 00000000000..924c3712aa5 --- /dev/null +++ b/src/mame/sega/naomig1.h @@ -0,0 +1,79 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +#ifndef MAME_MACHINE_NAOMIG1_H +#define MAME_MACHINE_NAOMIG1_H + +#pragma once + +#include "cpu/sh/sh4.h" + +class naomi_g1_device : public device_t +{ +public: + enum { + DMA_GDROM_IRQ + }; + + typedef delegate dma_cb; + + auto irq_callback() { return irq_cb.bind(); } + auto ext_irq_callback() { return ext_irq_cb.bind(); } + auto reset_out_callback() { return reset_out_cb.bind(); } + void set_dma_cb(dma_cb cb) { _dma_cb = cb; } + + void amap(address_map &map); // for range 0x005f7400-0x005f74ff + virtual void submap(address_map &map) = 0; // for range 0x005f7000-0x005f70ff + + uint32_t sb_gdstar_r(); // 5f7404 + void sb_gdstar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7404 + uint32_t sb_gdlen_r(); // 5f7408 + void sb_gdlen_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7408 + uint32_t sb_gddir_r(); // 5f740c + void sb_gddir_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f740c + uint32_t sb_gden_r(); // 5f7414 + void sb_gden_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7414 + uint32_t sb_gdst_r(); // 5f7418 + void sb_gdst_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7418 + + void sb_g1rrc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7480 + void sb_g1rwc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7484 + void sb_g1frc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7488 + void sb_g1fwc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f748c + void sb_g1crc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7490 + void sb_g1cwc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7494 + void sb_g1gdrc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f74a0 + void sb_g1gdwc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f74a4 + uint32_t sb_g1sysm_r(offs_t offset, uint32_t mem_mask = ~0); // 5f74b0 + void sb_g1crdyc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f74b4 + void sb_gdapro_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f74b8 + + uint32_t sb_gdstard_r(offs_t offset, uint32_t mem_mask = ~0); // 5f74f4 + uint32_t sb_gdlend_r(offs_t offset, uint32_t mem_mask = ~0); // 5f74f8 + +protected: + naomi_g1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + virtual void dma_get_position(uint8_t *&base, uint32_t &limit, bool to_maincpu) = 0; + virtual void dma_advance(uint32_t size) = 0; + + void set_ext_irq(int state) { ext_irq_cb(state); } + void set_reset_out() { reset_out_cb(ASSERT_LINE); } + + TIMER_CALLBACK_MEMBER(trigger_gdrom_irq); + +private: + uint32_t gdstar, gdlen, gddir, gden, gdst; + + emu_timer *timer; + devcb_write8 irq_cb; + devcb_write_line ext_irq_cb; + devcb_write_line reset_out_cb; + dma_cb _dma_cb; + + void dma(void *dma_ptr, uint32_t main_adr, uint32_t size, bool to_mainram); +}; + +#endif // MAME_MACHINE_NAOMIG1_H diff --git a/src/mame/sega/powervr2.cpp b/src/mame/sega/powervr2.cpp new file mode 100644 index 00000000000..476965b84f4 --- /dev/null +++ b/src/mame/sega/powervr2.cpp @@ -0,0 +1,4117 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/* + Dreamcast video emulation + + TODO: + - Needs break-down into sub-devices, as a generic rule of thumb + TA is Holly/CLX implementation specific while CORE is ISP/TSP only. + This will be particularly useful for PVR PMX implementations + (atvtrack.cpp and aristmk6.cpp); + - Remove dc_state readbacks from here; + - Better abstraction of timers; + +*/ + +#include "emu.h" +#include "powervr2.h" +#include "dc.h" + +#include "cpu/sh/sh4.h" +#include "video/rgbutil.h" +#include "rendutil.h" + +#define LOG_WARN (1U << 1) // Show warnings +#define LOG_TA_CMD (1U << 2) // Show TA CORE commands +#define LOG_TA_FIFO (1U << 3) // Show TA FIFO polygon entries +#define LOG_TA_TILE (1U << 4) // Show TA tile entries +#define LOG_PVR_DMA (1U << 5) // Show PVR-DMA access +#define LOG_IRQ (1U << 6) // Show irq triggers + +#define VERBOSE (LOG_WARN | LOG_PVR_DMA) + +#include "logmacro.h" + +#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) +#define LOGTACMD(...) LOGMASKED(LOG_TA_CMD, __VA_ARGS__) +#define LOGTAFIFO(...) LOGMASKED(LOG_TA_FIFO, __VA_ARGS__) +#define LOGTATILE(...) LOGMASKED(LOG_TA_TILE, __VA_ARGS__) +#define LOGPVRDMA(...) LOGMASKED(LOG_PVR_DMA, __VA_ARGS__) +#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__) + +#define LIVE_YUV_VIEW 0 + + +DEFINE_DEVICE_TYPE(POWERVR2, powervr2_device, "powervr2", "PowerVR 2") + +void powervr2_device::ta_map(address_map &map) +{ + map(0x0000, 0x0003).r(FUNC(powervr2_device::id_r)); + map(0x0004, 0x0007).r(FUNC(powervr2_device::revision_r)); + map(0x0008, 0x000b).rw(FUNC(powervr2_device::softreset_r), FUNC(powervr2_device::softreset_w)); + map(0x0014, 0x0017).w(FUNC(powervr2_device::startrender_w)); +// 18 = test select + map(0x0020, 0x0023).rw(FUNC(powervr2_device::param_base_r), FUNC(powervr2_device::param_base_w)); + map(0x002c, 0x002f).rw(FUNC(powervr2_device::region_base_r), FUNC(powervr2_device::region_base_w)); +// 30 = span sort cfg + map(0x0040, 0x0043).rw(FUNC(powervr2_device::vo_border_col_r), FUNC(powervr2_device::vo_border_col_w)); + map(0x0044, 0x0047).rw(FUNC(powervr2_device::fb_r_ctrl_r), FUNC(powervr2_device::fb_r_ctrl_w)); + map(0x0048, 0x004b).rw(FUNC(powervr2_device::fb_w_ctrl_r), FUNC(powervr2_device::fb_w_ctrl_w)); + map(0x004c, 0x004f).rw(FUNC(powervr2_device::fb_w_linestride_r), FUNC(powervr2_device::fb_w_linestride_w)); + map(0x0050, 0x0053).rw(FUNC(powervr2_device::fb_r_sof1_r), FUNC(powervr2_device::fb_r_sof1_w)); + map(0x0054, 0x0057).rw(FUNC(powervr2_device::fb_r_sof2_r), FUNC(powervr2_device::fb_r_sof2_w)); + map(0x005c, 0x005f).rw(FUNC(powervr2_device::fb_r_size_r), FUNC(powervr2_device::fb_r_size_w)); + map(0x0060, 0x0063).rw(FUNC(powervr2_device::fb_w_sof1_r), FUNC(powervr2_device::fb_w_sof1_w)); + map(0x0064, 0x0067).rw(FUNC(powervr2_device::fb_w_sof2_r), FUNC(powervr2_device::fb_w_sof2_w)); + map(0x0068, 0x006b).rw(FUNC(powervr2_device::fb_x_clip_r), FUNC(powervr2_device::fb_x_clip_w)); + map(0x006c, 0x006f).rw(FUNC(powervr2_device::fb_y_clip_r), FUNC(powervr2_device::fb_y_clip_w)); +// 74 = fpu_shad_scale +// 78 = fpu_cull_val + map(0x007c, 0x007f).rw(FUNC(powervr2_device::fpu_param_cfg_r), FUNC(powervr2_device::fpu_param_cfg_w)); +// 80 = half_offset +// 84 = fpu_perp_val +// 88 = isp_backgnd_d + map(0x008c, 0x008f).rw(FUNC(powervr2_device::isp_backgnd_t_r), FUNC(powervr2_device::isp_backgnd_t_w)); +// 98 = isp_feed_cfg +// a0 = sdram_refresh +// a4 = sdram_arb_cfg +// a8 = sdram_cfg +// b0 = fog_col_ram +// b4 = fog_col_vert +// b8 = fog_density +// bc = fog_clamp_max +// c0 = fog_clamp_min +// c4 = spg_trigger_pos + map(0x00c8, 0x00cb).rw(FUNC(powervr2_device::spg_hblank_int_r), FUNC(powervr2_device::spg_hblank_int_w)); + map(0x00cc, 0x00cf).rw(FUNC(powervr2_device::spg_vblank_int_r), FUNC(powervr2_device::spg_vblank_int_w)); + map(0x00d0, 0x00d3).rw(FUNC(powervr2_device::spg_control_r), FUNC(powervr2_device::spg_control_w)); + map(0x00d4, 0x00d7).rw(FUNC(powervr2_device::spg_hblank_r), FUNC(powervr2_device::spg_hblank_w)); + map(0x00d8, 0x00db).rw(FUNC(powervr2_device::spg_load_r), FUNC(powervr2_device::spg_load_w)); + map(0x00dc, 0x00df).rw(FUNC(powervr2_device::spg_vblank_r), FUNC(powervr2_device::spg_vblank_w)); + map(0x00e0, 0x00e3).rw(FUNC(powervr2_device::spg_width_r), FUNC(powervr2_device::spg_width_w)); + map(0x00e4, 0x00e7).rw(FUNC(powervr2_device::text_control_r), FUNC(powervr2_device::text_control_w)); + map(0x00e8, 0x00eb).rw(FUNC(powervr2_device::vo_control_r), FUNC(powervr2_device::vo_control_w)); + map(0x00ec, 0x00ef).rw(FUNC(powervr2_device::vo_startx_r), FUNC(powervr2_device::vo_startx_w)); + map(0x00f0, 0x00f3).rw(FUNC(powervr2_device::vo_starty_r), FUNC(powervr2_device::vo_starty_w)); +// f4 = scaler_ctl + map(0x0108, 0x010b).rw(FUNC(powervr2_device::pal_ram_ctrl_r), FUNC(powervr2_device::pal_ram_ctrl_w)); + map(0x010c, 0x010f).r(FUNC(powervr2_device::spg_status_r)); +// 110 = fb_burstctrl +// 118 = y_coeff +// 11c = pt_alpha_ref + + map(0x0124, 0x0127).rw(FUNC(powervr2_device::ta_ol_base_r), FUNC(powervr2_device::ta_ol_base_w)); + map(0x0128, 0x012b).rw(FUNC(powervr2_device::ta_isp_base_r), FUNC(powervr2_device::ta_isp_base_w)); + map(0x012c, 0x012f).rw(FUNC(powervr2_device::ta_ol_limit_r), FUNC(powervr2_device::ta_ol_limit_w)); + map(0x0130, 0x0133).rw(FUNC(powervr2_device::ta_isp_limit_r), FUNC(powervr2_device::ta_isp_limit_w)); + map(0x0134, 0x0137).r(FUNC(powervr2_device::ta_next_opb_r)); + map(0x0138, 0x013b).r(FUNC(powervr2_device::ta_itp_current_r)); +// 13c = ta_glob_tile_clip + map(0x0140, 0x0143).rw(FUNC(powervr2_device::ta_alloc_ctrl_r), FUNC(powervr2_device::ta_alloc_ctrl_w)); + map(0x0144, 0x0147).rw(FUNC(powervr2_device::ta_list_init_r), FUNC(powervr2_device::ta_list_init_w)); + map(0x0148, 0x014b).rw(FUNC(powervr2_device::ta_yuv_tex_base_r), FUNC(powervr2_device::ta_yuv_tex_base_w)); + map(0x014c, 0x014f).rw(FUNC(powervr2_device::ta_yuv_tex_ctrl_r), FUNC(powervr2_device::ta_yuv_tex_ctrl_w)); + map(0x0150, 0x0153).r(FUNC(powervr2_device::ta_yuv_tex_cnt_r)); + map(0x0160, 0x0163).w(FUNC(powervr2_device::ta_list_cont_w)); + map(0x0164, 0x0167).rw(FUNC(powervr2_device::ta_next_opb_init_r), FUNC(powervr2_device::ta_next_opb_init_w)); + + map(0x0200, 0x03ff).rw(FUNC(powervr2_device::fog_table_r), FUNC(powervr2_device::fog_table_w)); + map(0x1000, 0x1fff).rw(FUNC(powervr2_device::palette_r), FUNC(powervr2_device::palette_w)); +} + +void powervr2_device::pd_dma_map(address_map &map) +{ + map(0x00, 0x03).rw(FUNC(powervr2_device::sb_pdstap_r), FUNC(powervr2_device::sb_pdstap_w)); + map(0x04, 0x07).rw(FUNC(powervr2_device::sb_pdstar_r), FUNC(powervr2_device::sb_pdstar_w)); + map(0x08, 0x0b).rw(FUNC(powervr2_device::sb_pdlen_r), FUNC(powervr2_device::sb_pdlen_w)); + map(0x0c, 0x0f).rw(FUNC(powervr2_device::sb_pddir_r), FUNC(powervr2_device::sb_pddir_w)); + map(0x10, 0x13).rw(FUNC(powervr2_device::sb_pdtsel_r), FUNC(powervr2_device::sb_pdtsel_w)); + map(0x14, 0x17).rw(FUNC(powervr2_device::sb_pden_r), FUNC(powervr2_device::sb_pden_w)); + map(0x18, 0x1b).rw(FUNC(powervr2_device::sb_pdst_r), FUNC(powervr2_device::sb_pdst_w)); + map(0x80, 0x83).rw(FUNC(powervr2_device::sb_pdapro_r), FUNC(powervr2_device::sb_pdapro_w)); +} + +const int powervr2_device::pvr_parconfseq[] = {1,2,3,2,3,4,5,6,5,6,7,8,9,10,11,12,13,14,13,14,15,16,17,16,17,0,0,0,0,0,18,19,20,19,20,21,22,23,22,23}; +const int powervr2_device::pvr_wordsvertex[24] = {8,8,8,8,8,16,16,8,8,8, 8, 8,8,8,8,8,16,16, 8,16,16,8,16,16}; +const int powervr2_device::pvr_wordspolygon[24] = {8,8,8,8,8, 8, 8,8,8,8,16,16,8,8,8,8, 8, 8,16,16,16,8, 8, 8}; + +inline int32_t powervr2_device::clamp(int32_t in, int32_t min, int32_t max) +{ + if(in < min) return min; + if(in > max) return max; + return in; +} + +// Perform a standard bilinear filter across four pixels +inline uint32_t powervr2_device::bilinear_filter(uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, float u, float v) +{ + const uint32_t ui = (u * 256.0f); + const uint32_t vi = (v * 256.0f); + return rgbaint_t::bilinear_filter(c0, c1, c3, c2, ui, vi); +} + +// Multiply with alpha value in bits 31-24 +inline uint32_t powervr2_device::bla(uint32_t c, uint32_t a) +{ + a = a >> 24; + return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00); +} + +// Multiply with 1-alpha value in bits 31-24 +inline uint32_t powervr2_device::blia(uint32_t c, uint32_t a) +{ + a = 0x100 - (a >> 24); + return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00); +} + +// Per-component multiply with color value +inline uint32_t powervr2_device::blc(uint32_t c1, uint32_t c2) +{ + uint32_t cr = + (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) >> 8) | + (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0xff000000) >> 16); + c1 >>= 16; + c2 >>= 16; + cr |= + (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) << 8) | + (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0xff000000)); + return cr; +} + +// Per-component multiply with 1-color value +inline uint32_t powervr2_device::blic(uint32_t c1, uint32_t c2) +{ + uint32_t cr = + (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) >> 8) | + (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0xff000000) >> 16); + c1 >>= 16; + c2 >>= 16; + cr |= + (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) << 8) | + (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0xff000000)); + return cr; +} + +// Add two colors with saturation +inline uint32_t powervr2_device::bls(uint32_t c1, uint32_t c2) +{ + uint32_t cr1, cr2; + cr1 = (c1 & 0x00ff00ff) + (c2 & 0x00ff00ff); + if(cr1 & 0x0000ff00) + cr1 = (cr1 & 0xffff00ff) | 0x000000ff; + if(cr1 & 0xff000000) + cr1 = (cr1 & 0x00ffffff) | 0x00ff0000; + + cr2 = ((c1 >> 8) & 0x00ff00ff) + ((c2 >> 8) & 0x00ff00ff); + if(cr2 & 0x0000ff00) + cr2 = (cr2 & 0xffff00ff) | 0x000000ff; + if(cr2 & 0xff000000) + cr2 = (cr2 & 0x00ffffff) | 0x00ff0000; + return cr1|(cr2 << 8); +} + +/* + * Add two colors with saturation, not including the alpha channel + * The only difference between this function and bls is that bls does not + * ignore alpha. The alpha will be cleared to zero by this instruction + */ +inline uint32_t powervr2_device::bls24(uint32_t c1, uint32_t c2) +{ + uint32_t cr1, cr2; + cr1 = (c1 & 0x00ff00ff) + (c2 & 0x00ff00ff); + if(cr1 & 0x0000ff00) + cr1 = (cr1 & 0xffff00ff) | 0x000000ff; + if(cr1 & 0xff000000) + cr1 = (cr1 & 0x00ffffff) | 0x00ff0000; + + cr2 = ((c1 >> 8) & 0x000000ff) + ((c2 >> 8) & 0x000000ff); + if(cr2 & 0x0000ff00) + cr2 = (cr2 & 0xffff00ff) | 0x000000ff; + return cr1|(cr2 << 8); +} + +inline uint32_t powervr2_device::float_argb_to_packed_argb(float argb[4]) { + int argb_int[4] = { + (int)(argb[0] * 256.0f), + (int)(argb[1] * 256.0f), + (int)(argb[2] * 256.0f), + (int)(argb[3] * 256.0f) + }; + + // clamp to [0, 255] + int idx; + for (idx = 0; idx < 4; idx++) { + if (argb_int[idx] < 0) + argb_int[idx] = 0; + else if (argb_int[idx] > 255) + argb_int[idx] = 255; + } + + return (argb_int[0] << 24) | (argb_int[1] << 16) | + (argb_int[2] << 8) | argb_int[3]; +} + +inline void powervr2_device::packed_argb_to_float_argb(float dst[4], uint32_t in) { + dst[0] = (in >> 24) / 256.0f; + dst[1] = ((in >> 16) & 0xff) / 256.0f; + dst[2] = ((in >> 8) & 0xff) / 256.0f; + dst[3] = (in & 0xff) / 256.0f; +} + +// All 64 blending modes, 3 top bits are source mode, 3 bottom bits are destination mode +uint32_t powervr2_device::bl00(uint32_t s, uint32_t d) { return 0; } +uint32_t powervr2_device::bl01(uint32_t s, uint32_t d) { return d; } +uint32_t powervr2_device::bl02(uint32_t s, uint32_t d) { return blc(d, s); } +uint32_t powervr2_device::bl03(uint32_t s, uint32_t d) { return blic(d, s); } +uint32_t powervr2_device::bl04(uint32_t s, uint32_t d) { return bla(d, s); } +uint32_t powervr2_device::bl05(uint32_t s, uint32_t d) { return blia(d, s); } +uint32_t powervr2_device::bl06(uint32_t s, uint32_t d) { return bla(d, d); } +uint32_t powervr2_device::bl07(uint32_t s, uint32_t d) { return blia(d, d); } +uint32_t powervr2_device::bl10(uint32_t s, uint32_t d) { return s; } +uint32_t powervr2_device::bl11(uint32_t s, uint32_t d) { return bls(s, d); } +uint32_t powervr2_device::bl12(uint32_t s, uint32_t d) { return bls(s, blc(s, d)); } +uint32_t powervr2_device::bl13(uint32_t s, uint32_t d) { return bls(s, blic(s, d)); } +uint32_t powervr2_device::bl14(uint32_t s, uint32_t d) { return bls(s, bla(d, s)); } +uint32_t powervr2_device::bl15(uint32_t s, uint32_t d) { return bls(s, blia(d, s)); } +uint32_t powervr2_device::bl16(uint32_t s, uint32_t d) { return bls(s, bla(d, d)); } +uint32_t powervr2_device::bl17(uint32_t s, uint32_t d) { return bls(s, blia(d, d)); } +uint32_t powervr2_device::bl20(uint32_t s, uint32_t d) { return blc(d, s); } +uint32_t powervr2_device::bl21(uint32_t s, uint32_t d) { return bls(blc(d, s), d); } +uint32_t powervr2_device::bl22(uint32_t s, uint32_t d) { return bls(blc(d, s), blc(s, d)); } +uint32_t powervr2_device::bl23(uint32_t s, uint32_t d) { return bls(blc(d, s), blic(s, d)); } +uint32_t powervr2_device::bl24(uint32_t s, uint32_t d) { return bls(blc(d, s), bla(d, s)); } +uint32_t powervr2_device::bl25(uint32_t s, uint32_t d) { return bls(blc(d, s), blia(d, s)); } +uint32_t powervr2_device::bl26(uint32_t s, uint32_t d) { return bls(blc(d, s), bla(d, d)); } +uint32_t powervr2_device::bl27(uint32_t s, uint32_t d) { return bls(blc(d, s), blia(d, d)); } +uint32_t powervr2_device::bl30(uint32_t s, uint32_t d) { return blic(d, s); } +uint32_t powervr2_device::bl31(uint32_t s, uint32_t d) { return bls(blic(d, s), d); } +uint32_t powervr2_device::bl32(uint32_t s, uint32_t d) { return bls(blic(d, s), blc(s, d)); } +uint32_t powervr2_device::bl33(uint32_t s, uint32_t d) { return bls(blic(d, s), blic(s, d)); } +uint32_t powervr2_device::bl34(uint32_t s, uint32_t d) { return bls(blic(d, s), bla(d, s)); } +uint32_t powervr2_device::bl35(uint32_t s, uint32_t d) { return bls(blic(d, s), blia(d, s)); } +uint32_t powervr2_device::bl36(uint32_t s, uint32_t d) { return bls(blic(d, s), bla(d, d)); } +uint32_t powervr2_device::bl37(uint32_t s, uint32_t d) { return bls(blic(d, s), blia(d, d)); } +uint32_t powervr2_device::bl40(uint32_t s, uint32_t d) { return bla(s, s); } +uint32_t powervr2_device::bl41(uint32_t s, uint32_t d) { return bls(bla(s, s), d); } +uint32_t powervr2_device::bl42(uint32_t s, uint32_t d) { return bls(bla(s, s), blc(s, d)); } +uint32_t powervr2_device::bl43(uint32_t s, uint32_t d) { return bls(bla(s, s), blic(s, d)); } +uint32_t powervr2_device::bl44(uint32_t s, uint32_t d) { return bls(bla(s, s), bla(d, s)); } +uint32_t powervr2_device::bl45(uint32_t s, uint32_t d) { return bls(bla(s, s), blia(d, s)); } +uint32_t powervr2_device::bl46(uint32_t s, uint32_t d) { return bls(bla(s, s), bla(d, d)); } +uint32_t powervr2_device::bl47(uint32_t s, uint32_t d) { return bls(bla(s, s), blia(d, d)); } +uint32_t powervr2_device::bl50(uint32_t s, uint32_t d) { return blia(s, s); } +uint32_t powervr2_device::bl51(uint32_t s, uint32_t d) { return bls(blia(s, s), d); } +uint32_t powervr2_device::bl52(uint32_t s, uint32_t d) { return bls(blia(s, s), blc(s, d)); } +uint32_t powervr2_device::bl53(uint32_t s, uint32_t d) { return bls(blia(s, s), blic(s, d)); } +uint32_t powervr2_device::bl54(uint32_t s, uint32_t d) { return bls(blia(s, s), bla(d, s)); } +uint32_t powervr2_device::bl55(uint32_t s, uint32_t d) { return bls(blia(s, s), blia(d, s)); } +uint32_t powervr2_device::bl56(uint32_t s, uint32_t d) { return bls(blia(s, s), bla(d, d)); } +uint32_t powervr2_device::bl57(uint32_t s, uint32_t d) { return bls(blia(s, s), blia(d, d)); } +uint32_t powervr2_device::bl60(uint32_t s, uint32_t d) { return bla(s, d); } +uint32_t powervr2_device::bl61(uint32_t s, uint32_t d) { return bls(bla(s, d), d); } +uint32_t powervr2_device::bl62(uint32_t s, uint32_t d) { return bls(bla(s, d), blc(s, d)); } +uint32_t powervr2_device::bl63(uint32_t s, uint32_t d) { return bls(bla(s, d), blic(s, d)); } +uint32_t powervr2_device::bl64(uint32_t s, uint32_t d) { return bls(bla(s, d), bla(d, s)); } +uint32_t powervr2_device::bl65(uint32_t s, uint32_t d) { return bls(bla(s, d), blia(d, s)); } +uint32_t powervr2_device::bl66(uint32_t s, uint32_t d) { return bls(bla(s, d), bla(d, d)); } +uint32_t powervr2_device::bl67(uint32_t s, uint32_t d) { return bls(bla(s, d), blia(d, d)); } +uint32_t powervr2_device::bl70(uint32_t s, uint32_t d) { return blia(s, d); } +uint32_t powervr2_device::bl71(uint32_t s, uint32_t d) { return bls(blia(s, d), d); } +uint32_t powervr2_device::bl72(uint32_t s, uint32_t d) { return bls(blia(s, d), blc(s, d)); } +uint32_t powervr2_device::bl73(uint32_t s, uint32_t d) { return bls(blia(s, d), blic(s, d)); } +uint32_t powervr2_device::bl74(uint32_t s, uint32_t d) { return bls(blia(s, d), bla(d, s)); } +uint32_t powervr2_device::bl75(uint32_t s, uint32_t d) { return bls(blia(s, d), blia(d, s)); } +uint32_t powervr2_device::bl76(uint32_t s, uint32_t d) { return bls(blia(s, d), bla(d, d)); } +uint32_t powervr2_device::bl77(uint32_t s, uint32_t d) { return bls(blia(s, d), blia(d, d)); } + +uint32_t (*const powervr2_device::blend_functions[64])(uint32_t s, uint32_t d) = { + bl00, bl01, bl02, bl03, bl04, bl05, bl06, bl07, + bl10, bl11, bl12, bl13, bl14, bl15, bl16, bl17, + bl20, bl21, bl22, bl23, bl24, bl25, bl26, bl27, + bl30, bl31, bl32, bl33, bl34, bl35, bl36, bl37, + bl40, bl41, bl42, bl43, bl44, bl45, bl46, bl47, + bl50, bl51, bl52, bl53, bl54, bl55, bl56, bl57, + bl60, bl61, bl62, bl63, bl64, bl65, bl66, bl67, + bl70, bl71, bl72, bl73, bl74, bl75, bl76, bl77, +}; + +inline uint32_t powervr2_device::cv_1555(uint16_t c) +{ + return + (c & 0x8000 ? 0xff000000 : 0) | + ((c << 9) & 0x00f80000) | ((c << 4) & 0x00070000) | + ((c << 6) & 0x0000f800) | ((c << 1) & 0x00000700) | + ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007); +} + +inline uint32_t powervr2_device::cv_1555z(uint16_t c) +{ + return + (c & 0x8000 ? 0xff000000 : 0) | + ((c << 9) & 0x00f80000) | + ((c << 6) & 0x0000f800) | + ((c << 3) & 0x000000f8); +} + +inline uint32_t powervr2_device::cv_565(uint16_t c) +{ + return + 0xff000000 | + ((c << 8) & 0x00f80000) | ((c << 3) & 0x00070000) | + ((c << 5) & 0x0000fc00) | ((c >> 1) & 0x00000300) | + ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007); +} + +inline uint32_t powervr2_device::cv_565z(uint16_t c) +{ + return + 0xff000000 | + ((c << 8) & 0x00f80000) | + ((c << 5) & 0x0000fc00) | + ((c << 3) & 0x000000f8); +} + +inline uint32_t powervr2_device::cv_4444(uint16_t c) +{ + return + ((c << 16) & 0xf0000000) | ((c << 12) & 0x0f000000) | + ((c << 12) & 0x00f00000) | ((c << 8) & 0x000f0000) | + ((c << 8) & 0x0000f000) | ((c << 4) & 0x00000f00) | + ((c << 4) & 0x000000f0) | ((c ) & 0x0000000f); +} + +inline uint32_t powervr2_device::cv_4444z(uint16_t c) +{ + return + ((c << 16) & 0xf0000000) | + ((c << 12) & 0x00f00000) | + ((c << 8) & 0x0000f000) | + ((c << 4) & 0x000000f0); +} + +inline uint32_t powervr2_device::cv_yuv(uint16_t c1, uint16_t c2, int x) +{ + int u = 11*((c1 & 0xff) - 128); + int v = 11*((c2 & 0xff) - 128); + int y = (x & 1 ? c2 : c1) >> 8; + int r = y + v/8; + int g = y - u/32 - v/16; + int b = y + (3*u)/16; + r = r < 0 ? 0 : r > 255 ? 255 : r; + g = g < 0 ? 0 : g > 255 ? 255 : g; + b = b < 0 ? 0 : b > 255 ? 255 : b; + return 0xff000000 | (r << 16) | (g << 8) | b; +} + +int powervr2_device::uv_wrap(float uv, int size) +{ + int iuv = (int)uv; + return iuv & (size - 1); +} +int powervr2_device::uv_flip(float uv, int size) +{ + int iuv = (int)uv; + return ((iuv & size) ? ~iuv : iuv) & (size - 1); +} +int powervr2_device::uv_clamp(float uv, int size) +{ + int iuv = (int)uv; + return (iuv > 0) ? (iuv < size) ? iuv : (size - 1) : 0; +} + +uint32_t powervr2_device::tex_r_yuv_n(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + (t->stride*yt + (xt & ~1))*2; + uint16_t c1 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp)); + uint16_t c2 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp+2)); + return cv_yuv(c1, c2, xt); +} + +uint32_t powervr2_device::tex_r_yuv_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + (dilated1[t->cd][xt & ~1] + dilated0[t->cd][yt]) * 2; + uint16_t c1 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp)); + uint16_t c2 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp+4)); + return cv_yuv(c1, c2, xt); +} + +#if 0 +uint32_t powervr2_device::tex_r_yuv_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; + uint16_t c1 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp)); + uint16_t c2 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp+4)); + return cv_yuv(c1, c2, xt); +} +#endif + +uint32_t powervr2_device::tex_r_1555_n(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + (t->stride*yt + xt) * 2; + return cv_1555z(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); +} + +uint32_t powervr2_device::tex_r_1555_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt]) * 2; + return cv_1555(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); +} + +uint32_t powervr2_device::tex_r_1555_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; + return cv_1555(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); +} + +uint32_t powervr2_device::tex_r_565_n(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + (t->stride*yt + xt) * 2; + return cv_565z(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); +} + +uint32_t powervr2_device::tex_r_565_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt]) * 2; + return cv_565(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); +} + +uint32_t powervr2_device::tex_r_565_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; + return cv_565(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); +} + +uint32_t powervr2_device::tex_r_4444_n(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + (t->stride*yt + xt) * 2; + return cv_4444z(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); +} + +uint32_t powervr2_device::tex_r_4444_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt]) * 2; + return cv_4444(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); +} + +uint32_t powervr2_device::tex_r_4444_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; + return cv_4444(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); +} + +uint32_t powervr2_device::tex_r_p4_1555_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; + int addrp = t->address + (off >> 1); + int c = ((reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; + return cv_1555(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p4_1555_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; + return cv_1555(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p4_565_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; + int addrp = t->address + (off >> 1); + int c = ((reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; + return cv_565(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p4_565_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; + return cv_565(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p4_4444_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; + int addrp = t->address + (off >> 1); + int c = ((reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; + return cv_4444(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p4_4444_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; + return cv_4444(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p4_8888_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; + int addrp = t->address + (off >> 1); + int c = ((reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; + return palette[t->palbase + c]; +} + +uint32_t powervr2_device::tex_r_p4_8888_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; + return palette[t->palbase + c]; +} + +uint32_t powervr2_device::tex_r_p8_1555_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; + return cv_1555(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p8_1555_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; + return cv_1555(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p8_565_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; + return cv_565(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p8_565_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; + return cv_565(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p8_4444_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; + return cv_4444(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p8_4444_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; + return cv_4444(palette[t->palbase + c]); +} + +uint32_t powervr2_device::tex_r_p8_8888_tw(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; + return palette[t->palbase + c]; +} + +uint32_t powervr2_device::tex_r_p8_8888_vq(texinfo *t, float x, float y) +{ + int xt = t->u_func(x, t->sizex); + int yt = t->v_func(y, t->sizey); + int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; + int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; + int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; + return palette[t->palbase + c]; +} + + +uint32_t powervr2_device::tex_r_default(texinfo *t, float x, float y) +{ + return ((int)x ^ (int)y) & 4 ? 0xffffff00 : 0xff0000ff; +} + +void powervr2_device::tex_get_info(texinfo *t) +{ + int miptype = 0; + + t->textured = texture; + t->address = textureaddress; + t->pf = pixelformat; + t->palette = 0; + t->mode = (vqcompressed<<1); + + // scanorder is ignored for palettized textures (palettized textures are ALWAYS twiddled) + // (the same bits are used for palette select instead) + if ((t->pf == 5) || (t->pf == 6)) + { + t->palette = paletteselector; + } + else + { + t->mode |= scanorder; + } + + /* When scan order is 1 (non-twiddled) mipmap is ignored */ + t->mipmapped = t->mode & 1 ? 0 : mipmapped; + + // Mipmapped textures are always square, ignore v size + if (t->mipmapped) + { + t->sizes = (texturesizes & 0x38) | ((texturesizes & 0x38) >> 3); + } + else + { + t->sizes = texturesizes; + } + + t->sizex = 1 << (3+((t->sizes >> 3) & 7)); + t->sizey = 1 << (3+(t->sizes & 7)); + + + /* Stride select is used only in the non-twiddled case */ + t->stride = (t->mode & 1) && strideselect ? (text_control & 0x1f) << 5 : t->sizex; + + t->blend_mode = blend_mode; + t->filter_mode = filtermode; + + t->u_func = (clampuv & 2) ? &powervr2_device::uv_clamp : ((flipuv & 2) ? &powervr2_device::uv_flip : &powervr2_device::uv_wrap); + t->v_func = (clampuv & 1) ? &powervr2_device::uv_clamp : ((flipuv & 1) ? &powervr2_device::uv_flip : &powervr2_device::uv_wrap); + + t->r = &powervr2_device::tex_r_default; + t->cd = dilatechose[t->sizes]; + t->palbase = 0; + t->vqbase = t->address; + t->blend = ignoretexalpha ? bl10 : blend_functions[t->blend_mode]; + + t->coltype = coltype; + t->tsinstruction = tsinstruction; + +// fprintf(stderr, "tex %d %d %d %d\n", t->pf, t->mode, pal_ram_ctrl, t->mipmapped); + if(!t->textured) + { + t->r = nullptr; + } + else + { + switch(t->pf) { + case 0: // 1555 + switch(t->mode) { + case 0: t->r = &powervr2_device::tex_r_1555_tw; miptype = 2; break; + case 1: t->r = &powervr2_device::tex_r_1555_n; miptype = 2; break; + case 2: + case 3: t->r = &powervr2_device::tex_r_1555_vq; miptype = 3; t->address += 0x800; break; + + default: + // + break; + } + break; + + case 1: // 565 + switch(t->mode) { + case 0: t->r = &powervr2_device::tex_r_565_tw; miptype = 2; break; + case 1: t->r = &powervr2_device::tex_r_565_n; miptype = 2; break; + case 2: + case 3: t->r = &powervr2_device::tex_r_565_vq; miptype = 3; t->address += 0x800; break; + + default: + // + break; + } + break; + + case 2: // 4444 + switch(t->mode) { + case 0: t->r = &powervr2_device::tex_r_4444_tw; miptype = 2; break; + case 1: t->r = &powervr2_device::tex_r_4444_n; miptype = 2; break; + case 2: + case 3: t->r = &powervr2_device::tex_r_4444_vq; miptype = 3; t->address += 0x800; break; + + default: + // + break; + } + break; + + case 3: // yuv422 + switch(t->mode) { + case 0: t->r = &powervr2_device::tex_r_yuv_tw; miptype = -1; break; + case 1: t->r = &powervr2_device::tex_r_yuv_n; miptype = -1; break; + //default: t->r = &powervr2_device::tex_r_yuv_vq; miptype = -1; break; + } + break; + + case 4: // bumpmap + break; + + case 5: // 4bpp palette + t->palbase = (t->palette & 0x3f) << 4; + switch(t->mode) { + case 0: case 1: + miptype = 0; + + switch(pal_ram_ctrl) { + case 0: t->r = &powervr2_device::tex_r_p4_1555_tw; break; + case 1: t->r = &powervr2_device::tex_r_p4_565_tw; break; + case 2: t->r = &powervr2_device::tex_r_p4_4444_tw; break; + case 3: t->r = &powervr2_device::tex_r_p4_8888_tw; break; + } + break; + case 2: case 3: + miptype = 3; // ? + switch(pal_ram_ctrl) { + case 0: t->r = &powervr2_device::tex_r_p4_1555_vq; t->address += 0x800; break; + case 1: t->r = &powervr2_device::tex_r_p4_565_vq; t->address += 0x800; break; + case 2: t->r = &powervr2_device::tex_r_p4_4444_vq; t->address += 0x800; break; + case 3: t->r = &powervr2_device::tex_r_p4_8888_vq; t->address += 0x800; break; + } + break; + + default: + // + break; + } + break; + + case 6: // 8bpp palette + t->palbase = (t->palette & 0x30) << 4; + switch(t->mode) { + case 0: case 1: + miptype = 1; + + switch(pal_ram_ctrl) { + case 0: t->r = &powervr2_device::tex_r_p8_1555_tw; break; + case 1: t->r = &powervr2_device::tex_r_p8_565_tw; break; + case 2: t->r = &powervr2_device::tex_r_p8_4444_tw; break; + case 3: t->r = &powervr2_device::tex_r_p8_8888_tw; break; + } + break; + case 2: case 3: + miptype = 3; // ? + switch(pal_ram_ctrl) { + case 0: t->r = &powervr2_device::tex_r_p8_1555_vq; t->address += 0x800; break; + case 1: t->r = &powervr2_device::tex_r_p8_565_vq; t->address += 0x800; break; + case 2: t->r = &powervr2_device::tex_r_p8_4444_vq; t->address += 0x800; break; + case 3: t->r = &powervr2_device::tex_r_p8_8888_vq; t->address += 0x800; break; + } + break; + + default: + // + break; + } + break; + + case 9: // reserved + break; + } + } + + if (t->mipmapped) + { + // full offset tables for reference, + // we don't do mipmapping, so don't use anything < 8x8 + // first table is half-bytes + + // 4BPP palette textures + // Texture size _4-bit_ offset value for starting address + // 1x1 0x00003 + // 2x2 0x00004 + // 4x4 0x00008 + // 8x8 0x00018 + // 16x16 0x00058 + // 32x32 0x00158 + // 64x64 0x00558 + // 128x128 0x01558 + // 256x256 0x05558 + // 512x512 0x15558 + // 1024x1024 0x55558 + + // 8BPP palette textures + // Texture size Byte offset value for starting address + // 1x1 0x00003 + // 2x2 0x00004 + // 4x4 0x00008 + // 8x8 0x00018 + // 16x16 0x00058 + // 32x32 0x00158 + // 64x64 0x00558 + // 128x128 0x01558 + // 256x256 0x05558 + // 512x512 0x15558 + // 1024x1024 0x55558 + + // Non-palette textures + // Texture size Byte offset value for starting address + // 1x1 0x00006 + // 2x2 0x00008 + // 4x4 0x00010 + // 8x8 0x00030 + // 16x16 0x000B0 + // 32x32 0x002B0 + // 64x64 0x00AB0 + // 128x128 0x02AB0 + // 256x256 0x0AAB0 + // 512x512 0x2AAB0 + // 1024x1024 0xAAAB0 + + // VQ textures + // Texture size Byte offset value for starting address + // 1x1 0x00000 + // 2x2 0x00001 + // 4x4 0x00002 + // 8x8 0x00006 + // 16x16 0x00016 + // 32x32 0x00056 + // 64x64 0x00156 + // 128x128 0x00556 + // 256x256 0x01556 + // 512x512 0x05556 + // 1024x1024 0x15556 + + static const int mipmap_4_8_offset[8] = { 0x00018, 0x00058, 0x00158, 0x00558, 0x01558, 0x05558, 0x15558, 0x55558 }; // 4bpp (4bit offset) / 8bpp (8bit offset) + static const int mipmap_np_offset[8] = { 0x00030, 0x000B0, 0x002B0, 0x00AB0, 0x02AB0, 0x0AAB0, 0x2AAB0, 0xAAAB0 }; // nonpalette textures + static const int mipmap_vq_offset[8] = { 0x00006, 0x00016, 0x00056, 0x00156, 0x00556, 0x01556, 0x05556, 0x15556 }; // vq textures + + switch (miptype) + { + case 0: // 4bpp + //printf("4bpp\n"); + t->address += mipmap_4_8_offset[(t->sizes)&7]>>1; + break; + + case 1: // 8bpp + //printf("8bpp\n"); + t->address += mipmap_4_8_offset[(t->sizes)&7]; + break; + + case 2: // nonpalette + //printf("np\n"); + t->address += mipmap_np_offset[(t->sizes)&7]; + break; + + case 3: // vq + //printf("vq\n"); + t->address += mipmap_vq_offset[(t->sizes)&7]; + break; + } + } + +} + +uint32_t powervr2_device::id_r() +{ + return 0x17fd11db; +} + +uint32_t powervr2_device::revision_r() +{ + return 0x00000011; +} + +uint32_t powervr2_device::softreset_r() +{ + return softreset; +} + +void powervr2_device::softreset_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&softreset); + if (softreset & 1) { + LOGTACMD("TA soft reset\n"); + listtype_used=0; + } + if (softreset & 2) { + LOGTACMD("Core Pipeline soft reset\n"); + + if (start_render_received == 1) { + for (int a=0;a < NUM_BUFFERS;a++) + if (grab[a].busy == 1) + grab[a].busy = 0; + + start_render_received = 0; + } + } + if (softreset & 4) { + LOGTACMD("sdram I/F soft reset\n"); + } +} + +void powervr2_device::startrender_w(address_space &space, uint32_t data) +{ + dc_state *state = machine().driver_data(); + g_profiler.start(PROFILER_USER1); + + LOGTACMD("Start render, region=%08x, params=%08x\n", region_base, param_base); + + // select buffer to draw using param_base + for (int a=0;a < NUM_BUFFERS;a++) { + if ((grab[a].ispbase == param_base) && (grab[a].valid == 1) && (grab[a].busy == 0)) { + grab[a].busy = 1; + renderselect = a; + start_render_received=1; + + + grab[a].fbwsof1 = fb_w_sof1; + grab[a].fbwsof2 = fb_w_sof2; + + rectangle clip(0, 1023, 0, 1023); + + // we've got a request to draw, so, draw to the accumulation buffer! + // this should really be done for each tile! + render_to_accumulation_buffer(*fake_accumulationbuffer_bitmap,clip); + + /* copy the tiles to the framebuffer (really the rendering should be in this loop too) */ + int sizera = fpu_param_cfg & 0x200000 ? 6 : 5; + int offsetra=region_base; + + //printf("base is %08x\n", offsetra); + + // sanity + int sanitycount = 0; + for (;;) { + uint32_t st[6]; + + st[0]=space.read_dword((0x05000000+offsetra)); + st[1]=space.read_dword((0x05000004+offsetra)); // Opaque List Pointer + st[2]=space.read_dword((0x05000008+offsetra)); // Opaque Modifier Volume List Pointer + st[3]=space.read_dword((0x0500000c+offsetra)); // Translucent List Pointer + st[4]=space.read_dword((0x05000010+offsetra)); // Translucent Modifier Volume List Pointer + + if (sizera == 6) { + st[5] = space.read_dword((0x05000014+offsetra)); // Punch Through List Pointer + offsetra+=0x18; + } else { + st[5] = 0; + offsetra+=0x14; + } + + { + int x = ((st[0]&0x000000fc)>>2)*32; + int y = ((st[0]&0x00003f00)>>8)*32; + //printf("tiledata %08x %d %d - %08x %08x %08x %08x %08x\n",st[0],x,y,st[1],st[2],st[3],st[4],st[5]); + + // should render to the accumulation buffer here using pointers we filled in when processing the data + // sent to the TA. HOWEVER, we don't process the TA data and create the real format object lists, so + // instead just use these co-ordinates to copy data from our fake full-screnen accumnulation buffer into + // the framebuffer + + pvr_accumulationbuffer_to_framebuffer(space, x,y); + } + + if (st[0] & 0x80000000) + break; + + sanitycount++; + // prevent infinite loop if asked to process invalid data + //if(sanitycount>2000) + // break; + } + + /* Fire ISP irq after a set amount of time */ + // TODO: exact timing of this + // hacky end of render delay for Capcom games, otherwise they works at ~1/10 speed. + // 500k is definitely too slow for them: it fires the isp/tsp completion at + // vbl-in and expect that it completes after some time that vbl-out kicks in, + // in order to have enough time to execute logic stuff in the meantime. +// const u64 isp_completion = sanitycount * 25 + 500000; + const u64 isp_completion = sanitycount * 25 + 2000000; + LOGIRQ("[%d] ISP end of render start %d in %d cycles\n", + screen().frame_number(), screen().vpos(), isp_completion + ); + endofrender_timer_isp->adjust(state->m_maincpu->cycles_to_attotime(isp_completion)); + break; + } + } +} + + +uint32_t powervr2_device::param_base_r() +{ + return param_base; +} + +void powervr2_device::param_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(¶m_base); +} + +uint32_t powervr2_device::region_base_r() +{ + return region_base; +} + +void powervr2_device::region_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(®ion_base); +} + +uint32_t powervr2_device::vo_border_col_r() +{ + return vo_border_col; +} + +void powervr2_device::vo_border_col_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&vo_border_col); +} + +uint32_t powervr2_device::fb_r_ctrl_r() +{ + return fb_r_ctrl; +} + +void powervr2_device::fb_r_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_r_ctrl); +} + +uint32_t powervr2_device::fb_w_ctrl_r() +{ + return fb_w_ctrl; +} + +void powervr2_device::fb_w_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_w_ctrl); +} + +uint32_t powervr2_device::fb_w_linestride_r() +{ + return fb_w_linestride; +} + +void powervr2_device::fb_w_linestride_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_w_linestride); +} + +uint32_t powervr2_device::fb_r_sof1_r() +{ + return fb_r_sof1; +} + +void powervr2_device::fb_r_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_r_sof1); +} + +uint32_t powervr2_device::fb_r_sof2_r() +{ + return fb_r_sof2; +} + +void powervr2_device::fb_r_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_r_sof2); +} + +uint32_t powervr2_device::fb_r_size_r() +{ + return fb_r_size; +} + +void powervr2_device::fb_r_size_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_r_size); +} + +uint32_t powervr2_device::fb_w_sof1_r() +{ + return fb_w_sof1; +} + +void powervr2_device::fb_w_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_w_sof1); +} + +uint32_t powervr2_device::fb_w_sof2_r() +{ + return fb_w_sof2; +} + +void powervr2_device::fb_w_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_w_sof2); +} + +uint32_t powervr2_device::fb_x_clip_r() +{ + return fb_x_clip; +} + +void powervr2_device::fb_x_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_x_clip); +} + +uint32_t powervr2_device::fb_y_clip_r() +{ + return fb_y_clip; +} + +void powervr2_device::fb_y_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fb_y_clip); +} + +uint32_t powervr2_device::fpu_param_cfg_r() +{ + return fpu_param_cfg; +} + +void powervr2_device::fpu_param_cfg_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&fpu_param_cfg); +} + +uint32_t powervr2_device::isp_backgnd_t_r() +{ + return isp_backgnd_t; +} + +void powervr2_device::isp_backgnd_t_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&isp_backgnd_t); +} + +uint32_t powervr2_device::spg_hblank_int_r() +{ + return spg_hblank_int; +} + +void powervr2_device::spg_hblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&spg_hblank_int); + // TODO: timer adjust +} + +uint32_t powervr2_device::spg_vblank_int_r() +{ + return spg_vblank_int; +} + +void powervr2_device::spg_vblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&spg_vblank_int); + + /* clear pending irqs and modify them with the updated ones */ +// vbin_timer->adjust(attotime::never); +// vbout_timer->adjust(attotime::never); + +// vbin_timer->adjust(screen().time_until_pos(spg_vblank_int & 0x3ff)); +// vbout_timer->adjust(screen().time_until_pos((spg_vblank_int >> 16) & 0x3ff)); +} + +uint32_t powervr2_device::spg_control_r() +{ + return spg_control; +} + +void powervr2_device::spg_control_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&spg_control); + update_screen_format(); + + if((spg_control & 0xc0) == 0xc0) + popmessage("SPG undocumented pixel clock mode 11, contact MAME/MESSdev"); + + if((spg_control & 0xd0) == 0x10) + popmessage("SPG enabled VGA mode with interlace, contact MAME/MESSdev"); +} + +uint32_t powervr2_device::spg_hblank_r() +{ + return spg_hblank; +} + +void powervr2_device::spg_hblank_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&spg_hblank); + update_screen_format(); +} + +uint32_t powervr2_device::spg_load_r() +{ + return spg_load; +} + +void powervr2_device::spg_load_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&spg_load); + update_screen_format(); +} + +uint32_t powervr2_device::spg_vblank_r() +{ + return spg_vblank; +} + +void powervr2_device::spg_vblank_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&spg_vblank); + update_screen_format(); +} + +uint32_t powervr2_device::spg_width_r() +{ + return spg_width; +} + +void powervr2_device::spg_width_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&spg_width); + update_screen_format(); +} + +uint32_t powervr2_device::text_control_r() +{ + return text_control; +} + +void powervr2_device::text_control_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&text_control); +} + +uint32_t powervr2_device::vo_control_r() +{ + return vo_control; +} + +void powervr2_device::vo_control_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&vo_control); +} + +uint32_t powervr2_device::vo_startx_r() +{ + return vo_startx; +} + +void powervr2_device::vo_startx_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&vo_startx); + update_screen_format(); +} + +uint32_t powervr2_device::vo_starty_r() +{ + return vo_starty; +} + +void powervr2_device::vo_starty_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&vo_starty); + update_screen_format(); +} + +uint32_t powervr2_device::pal_ram_ctrl_r() +{ + return pal_ram_ctrl; +} + +void powervr2_device::pal_ram_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&pal_ram_ctrl); +} + +uint32_t powervr2_device::spg_status_r() +{ + uint32_t fieldnum = (screen().frame_number() & 1) ? 1 : 0; + int32_t spg_hbstart = spg_hblank & 0x3ff; + int32_t spg_hbend = (spg_hblank >> 16) & 0x3ff; + int32_t spg_vbstart = spg_vblank & 0x3ff; + int32_t spg_vbend = (spg_vblank >> 16) & 0x3ff; + + uint32_t vsync = ((screen().vpos() >= spg_vbstart) || (screen().vpos() < spg_vbend)) ? 0 : 1; + uint32_t hsync = ((screen().hpos() >= spg_hbstart) || (screen().hpos() < spg_hbend)) ? 0 : 1; + // FIXME: following is just a wild guess + uint32_t blank = ((screen().vpos() >= spg_vbstart) || (screen().vpos() < spg_vbend) || + (screen().hpos() >= spg_hbstart) || (screen().hpos() < spg_hbend)) ? 0 : 1; + if(vo_control & 4) { blank^=1; } + if(vo_control & 2) { vsync^=1; } + if(vo_control & 1) { hsync^=1; } + + return (vsync << 13) | (hsync << 12) | (blank << 11) | (fieldnum << 10) | (screen().vpos() & 0x3ff); +} + + +uint32_t powervr2_device::ta_ol_base_r() +{ + return ta_ol_base; +} + +void powervr2_device::ta_ol_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&ta_ol_base); +} + +uint32_t powervr2_device::ta_isp_base_r() +{ + return ta_isp_base; +} + +void powervr2_device::ta_isp_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&ta_isp_base); +} + +uint32_t powervr2_device::ta_ol_limit_r() +{ + return ta_ol_limit; +} + +void powervr2_device::ta_ol_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&ta_ol_limit); +} + +uint32_t powervr2_device::ta_isp_limit_r() +{ + return ta_isp_limit; +} + +void powervr2_device::ta_isp_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&ta_isp_limit); +} + +uint32_t powervr2_device::ta_next_opb_r() +{ + return ta_next_opb; +} + +uint32_t powervr2_device::ta_itp_current_r() +{ + return ta_itp_current; +} + +uint32_t powervr2_device::ta_alloc_ctrl_r() +{ + return ta_alloc_ctrl; +} + +void powervr2_device::ta_alloc_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&ta_alloc_ctrl); +} + +uint32_t powervr2_device::ta_list_init_r() +{ + return 0; //bit 31 always return 0, a probable left-over in Crazy Taxi reads this and discards the read (?) +} + +void powervr2_device::ta_list_init_w(uint32_t data) +{ + if(data & 0x80000000) { + tafifo_pos=0; + tafifo_mask=7; + tafifo_vertexwords=8; + tafifo_listtype= DISPLAY_LIST_NONE; + + LOGTACMD("list init ol=(%08x, %08x) isp=(%08x, %08x), alloc=%08x obp=%08x\n", + ta_ol_base, ta_ol_limit, + ta_isp_base, ta_isp_limit, + ta_alloc_ctrl, + ta_next_opb_init + ); + + ta_next_opb = ta_next_opb_init; + ta_itp_current = ta_isp_base; + alloc_ctrl_OPB_Mode = ta_alloc_ctrl & 0x100000; // 0 up 1 down + alloc_ctrl_PT_OPB = (4 << ((ta_alloc_ctrl >> 16) & 3)) & 0x38; // number of 32 bit words (0,8,16,32) + alloc_ctrl_TM_OPB = (4 << ((ta_alloc_ctrl >> 12) & 3)) & 0x38; + alloc_ctrl_T_OPB = (4 << ((ta_alloc_ctrl >> 8) & 3)) & 0x38; + alloc_ctrl_OM_OPB = (4 << ((ta_alloc_ctrl >> 4) & 3)) & 0x38; + alloc_ctrl_O_OPB = (4 << ((ta_alloc_ctrl >> 0) & 3)) & 0x38; + listtype_used |= (1+4); + // use ta_isp_base and select buffer for grab data + grabsel = -1; + // try to find already used buffer but not busy + for (int a=0;a < NUM_BUFFERS;a++) + if ((grab[a].ispbase == ta_isp_base) && (grab[a].busy == 0) && (grab[a].valid == 1)) { + grabsel=a; + break; + } + + // try a buffer not used yet + if (grabsel < 0) + for (int a=0;a < NUM_BUFFERS;a++) + if (grab[a].valid == 0) { + grabsel=a; + break; + } + + // find a non busy buffer starting from the last one used + if (grabsel < 0) + for (int a=0;a < 3;a++) + if (grab[(grabsellast+1+a) & 3].busy == 0) { + grabsel=a; + break; + } + + if (grabsel < 0) + throw emu_fatalerror("powervr2_device::ta_list_init_w: TA grabber error B!"); + grabsellast=grabsel; + grab[grabsel].ispbase=ta_isp_base; + grab[grabsel].busy=0; + grab[grabsel].valid=1; + grab[grabsel].verts_size=0; + for (int group = 0; group < DISPLAY_LIST_COUNT; group++) { + grab[grabsel].groups[group].strips_size=0; + } + + g_profiler.stop(); + } +} + + +uint32_t powervr2_device::ta_yuv_tex_base_r() +{ + return ta_yuv_tex_base; +} + +void powervr2_device::ta_yuv_tex_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&ta_yuv_tex_base); + + // Writes causes a reset in YUV FIFO pipeline + ta_yuv_index = 0; + ta_yuv_u_ptr = 0; + ta_yuv_v_ptr = 0; +} + +uint32_t powervr2_device::ta_yuv_tex_ctrl_r() +{ + return ta_yuv_tex_ctrl; +} + +void powervr2_device::ta_yuv_tex_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&ta_yuv_tex_ctrl); + + ta_yuv_v_size = (((ta_yuv_tex_ctrl >> 8) & 0x3f) + 1) * 16; + ta_yuv_u_size = ((ta_yuv_tex_ctrl & 0x3f) + 1) * 16; + + if (ta_yuv_tex_ctrl & 0x01010000) + throw emu_fatalerror("YUV422 mode selected %08x", ta_yuv_tex_ctrl); +} + +// TODO: unemulated YUV macroblock live count, nothing seems to use it? +uint32_t powervr2_device::ta_yuv_tex_cnt_r() +{ + if (!machine().side_effects_disabled()) + LOGWARN("%s yuv_tex_cnt read!", machine().describe_context()); + return ta_yuv_tex_cnt; +} + +void powervr2_device::ta_list_cont_w(uint32_t data) +{ + if(data & 0x80000000) { + tafifo_listtype= DISPLAY_LIST_NONE; // no list being received + listtype_used |= (1+4); + } +} + +uint32_t powervr2_device::ta_next_opb_init_r() +{ + return ta_next_opb_init; +} + +void powervr2_device::ta_next_opb_init_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&ta_next_opb_init); +} + + +uint32_t powervr2_device::fog_table_r(offs_t offset) +{ + return fog_table[offset]; +} + +void powervr2_device::fog_table_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(fog_table+offset); +} + +uint32_t powervr2_device::palette_r(offs_t offset) +{ + return palette[offset]; +} + +void powervr2_device::palette_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(palette+offset); +} + +void powervr2_device::update_screen_format() +{ + /* 00=VGA 01=NTSC 10=PAL, 11=illegal/undocumented */ + const int spg_clks[4] = { 26944080, 13458568, 13462800, 26944080 }; + int32_t spg_hsize = spg_load & 0x3ff; + int32_t spg_vsize = (spg_load >> 16) & 0x3ff; + int32_t spg_hbstart = spg_hblank & 0x3ff; + int32_t spg_hbend = (spg_hblank >> 16) & 0x3ff; + int32_t spg_vbstart = spg_vblank & 0x3ff; + int32_t spg_vbend = (spg_vblank >> 16) & 0x3ff; + //int32_t vo_horz_start_pos = vo_startx & 0x3ff; + //int32_t vo_vert_start_pos_f1 = vo_starty & 0x3ff; + int pclk = spg_clks[(spg_control >> 6) & 3] * (((spg_control & 0x10) >> 4)+1); + + attoseconds_t refresh = HZ_TO_ATTOSECONDS(pclk) * spg_hsize * spg_vsize; + + rectangle visarea = screen().visible_area(); + + visarea.min_x = spg_hbend; + visarea.max_x = spg_hbstart - 1; + visarea.min_y = spg_vbend; + visarea.max_y = spg_vbstart - 1; + + // Sanitize + if(visarea.max_x >= spg_hsize) + visarea.max_x = spg_hsize-1; + if(visarea.max_y >= spg_vsize) + visarea.max_y = spg_vsize-1; + if(visarea.min_x > visarea.max_x) + visarea.min_x = visarea.max_x; + if(visarea.min_y > visarea.max_y) + visarea.min_y = visarea.max_y; + + screen().configure(spg_hsize, spg_vsize, visarea, refresh ); +} + + +uint32_t powervr2_device::sb_pdstap_r() +{ + return sb_pdstap; +} + +void powervr2_device::sb_pdstap_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&sb_pdstap); + m_pvr_dma.pvr_addr = sb_pdstap; +} + +uint32_t powervr2_device::sb_pdstar_r() +{ + return sb_pdstar; +} + +void powervr2_device::sb_pdstar_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&sb_pdstar); + m_pvr_dma.sys_addr = sb_pdstar; +} + +uint32_t powervr2_device::sb_pdlen_r() +{ + return sb_pdlen; +} + +void powervr2_device::sb_pdlen_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&sb_pdlen); + m_pvr_dma.size = sb_pdlen; +} + +uint32_t powervr2_device::sb_pddir_r() +{ + return sb_pddir; +} + +void powervr2_device::sb_pddir_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&sb_pddir); + m_pvr_dma.dir = sb_pddir; +} + +uint32_t powervr2_device::sb_pdtsel_r() +{ + return sb_pdtsel; +} + +void powervr2_device::sb_pdtsel_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&sb_pdtsel); + m_pvr_dma.sel = sb_pdtsel & 1; +} + +uint32_t powervr2_device::sb_pden_r() +{ + return sb_pden; +} + +void powervr2_device::sb_pden_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&sb_pden); + m_pvr_dma.flag = sb_pden & 1; +} + +uint32_t powervr2_device::sb_pdst_r() +{ + return sb_pdst; +} + +void powervr2_device::sb_pdst_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&sb_pdst); + + uint32_t old = m_pvr_dma.start & 1; + m_pvr_dma.start = sb_pdst & 1; + + // 0 -> 1 transition starts the DMA + if(((old & 1) == 0) && m_pvr_dma.flag && m_pvr_dma.start && ((m_pvr_dma.sel & 1) == 0)) + pvr_dma_execute(space); +} + +uint32_t powervr2_device::sb_pdapro_r() +{ + return sb_pdapro; +} + +void powervr2_device::sb_pdapro_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&sb_pdapro); +} + + +TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_list_irq) +{ + LOGIRQ("[%d] EOXFER OPLST %d\n", screen().frame_number(), screen().vpos()); + + irq_cb(EOXFER_OPLST_IRQ); +} + +TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_modifier_volume_list_irq) +{ + LOGIRQ("[%d] EOXFER OPMV %d\n", screen().frame_number(), screen().vpos()); + + irq_cb(EOXFER_OPMV_IRQ); +} + +TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_list_irq) +{ + LOGIRQ("[%d] EOXFER TRLST %d\n", screen().frame_number(), screen().vpos()); + + irq_cb(EOXFER_TRLST_IRQ); +} + +TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_modifier_volume_list_irq) +{ + LOGIRQ("[%d] EOXFER TRMV %d\n", screen().frame_number(), screen().vpos()); + + irq_cb(EOXFER_TRMV_IRQ); +} + +TIMER_CALLBACK_MEMBER(powervr2_device::transfer_punch_through_list_irq) +{ + LOGIRQ("[%d] EOXFER PTLST %d\n", screen().frame_number(), screen().vpos()); + + irq_cb(EOXFER_PTLST_IRQ); +} + +void powervr2_device::process_ta_fifo() +{ + /* first byte in the buffer is the Parameter Control Word + + pppp pppp gggg gggg oooo oooo oooo oooo + + p = para control + g = group control + o = object control + + */ + + receiveddata *rd = &grab[grabsel]; + + // Para Control + paracontrol=(tafifo_buff[0] >> 24) & 0xff; + // 0 end of list + // 1 user tile clip + // 2 object list set + // 3 reserved + // 4 polygon/modifier volume + // 5 sprite + // 6 reserved + // 7 vertex + paratype=(paracontrol >> 5) & 7; + endofstrip=(paracontrol >> 4) & 1; + listtype=(paracontrol >> 0) & 7; + if ((paratype >= 4) && (paratype <= 6)) + { + global_paratype = paratype; + // Group Control + groupcontrol=(tafifo_buff[0] >> 16) & 0xff; + groupen=(groupcontrol >> 7) & 1; + striplen=(groupcontrol >> 2) & 3; + userclip=(groupcontrol >> 0) & 3; + // Obj Control + objcontrol=(tafifo_buff[0] >> 0) & 0xffff; + shadow=(objcontrol >> 7) & 1; + volume=(objcontrol >> 6) & 1; + coltype=(objcontrol >> 4) & 3; + texture=(objcontrol >> 3) & 1; + offset_color_enable=texture ? (objcontrol >> 2) & 1 : 0; + gouraud=(objcontrol >> 1) & 1; + uv16bit=(objcontrol >> 0) & 1; + } + + // check if we need 8 words more + if (tafifo_mask == 7) + { + parameterconfig = pvr_parameterconfig[objcontrol & 0x3d]; + // decide number of words per vertex + if (paratype == 7) + { + if ((global_paratype == 5) || + (tafifo_listtype == DISPLAY_LIST_OPAQUE_MOD) || + (tafifo_listtype == DISPLAY_LIST_TRANS_MOD)) + { + tafifo_vertexwords = 16; + } + if (tafifo_vertexwords == 16) + { + tafifo_mask = 15; + tafifo_pos = 8; + return; + } + } + // decide number of words when not a vertex + tafifo_vertexwords=pvr_wordsvertex[parameterconfig]; + if ((paratype == 4) && ((listtype != 1) && (listtype != 3))) + if (pvr_wordspolygon[parameterconfig] == 16) + { + tafifo_mask = 15; + tafifo_pos = 8; + return; + } + } + bool have_16_byte_header = tafifo_mask != 7; + tafifo_mask = 7; + + // now we heve all the needed words + + /* + * load per-polygon colors if color type is 2 or 3 or parameter type is + * 5 (quad). For color types 0 and 1, color is determined entirely on a + * per-vertex basis. + */ + if (paratype == 4) + { + switch (coltype) { + case 2: + if (offset_color_enable) { + memcpy(poly_base_color, tafifo_buff + 8, 4 * sizeof(float)); + memcpy(poly_offs_color, tafifo_buff + 12, 4 * sizeof(float)); + } else { + memcpy(poly_base_color, tafifo_buff + 4, 4 * sizeof(float)); + memset(poly_offs_color, 0, sizeof(poly_offs_color)); + } + memcpy(poly_last_mode_2_base_color, poly_base_color, sizeof(poly_last_mode_2_base_color)); + break; + case 3: + memcpy(poly_base_color, poly_last_mode_2_base_color, sizeof(poly_base_color)); + memset(poly_offs_color, 0, sizeof(poly_offs_color)); + break; + default: + memset(poly_base_color, 0, sizeof(poly_base_color)); + memset(poly_offs_color, 0, sizeof(poly_offs_color)); + break; + } + } else if (paratype == 5) { + packed_argb_to_float_argb(poly_base_color, tafifo_buff[4]); + if (offset_color_enable) { + packed_argb_to_float_argb(poly_offs_color, tafifo_buff[5]); + } else { + memset(poly_offs_color, 0, sizeof(poly_offs_color)); + } + } + + // here we should generate the data for the various tiles + // for now, just interpret their meaning + if (paratype == 0) + { + LOGTATILE("Para Type 0 End of List\n"); + + /* Process transfer FIFO done irqs here */ + //printf("%d %d\n",tafifo_listtype,screen().vpos()); + // FIXME: timing of these + switch (tafifo_listtype) + { + case DISPLAY_LIST_OPAQUE: + opaque_irq_timer->adjust(attotime::from_usec(100)); + break; + case DISPLAY_LIST_OPAQUE_MOD: + opaque_modifier_volume_irq_timer->adjust(attotime::from_usec(100)); + break; + case DISPLAY_LIST_TRANS: + translucent_irq_timer->adjust(attotime::from_usec(100)); + break; + case DISPLAY_LIST_TRANS_MOD: + translucent_modifier_volume_irq_timer->adjust(attotime::from_usec(100)); + break; + case DISPLAY_LIST_PUNCH_THROUGH: + punch_through_irq_timer->adjust(attotime::from_usec(100)); + break; + } + tafifo_listtype = DISPLAY_LIST_NONE; // no list being received + listtype_used |= (2+8); + } + else if (paratype == 1) + { + LOGTATILE("Para Type 1 User Tile Clip\n"); + LOGTATILE(" (%d , %d)-(%d , %d)\n", tafifo_buff[4], tafifo_buff[5], tafifo_buff[6], tafifo_buff[7]); + } + else if (paratype == 2) + { + LOGTATILE("Para Type 2 Object List Set at %08x\n", tafifo_buff[1]); + LOGTATILE(" (%d , %d)-(%d , %d)\n", tafifo_buff[4], tafifo_buff[5], tafifo_buff[6], tafifo_buff[7]); + } + else if (paratype == 3) + { + LOGWARN("Para Type %x Unknown!\n", tafifo_buff[0]); + } + else + { // global parameter or vertex parameter + LOGTATILE("Para Type %d", paratype); + if (paratype == 7) + LOGTATILE(" End of Strip %d", endofstrip); + if (listtype_used & 3) + LOGTATILE(" List Type %d", listtype); + LOGTATILE("\n"); + + // set type of list currently being received + if ((paratype == 4) || (paratype == 5) || (paratype == 6)) + { + if (tafifo_listtype < 0) + { + tafifo_listtype = listtype; + } + } + listtype_used = listtype_used ^ (listtype_used & 3); + + if ((paratype == 4) || (paratype == 5)) + { // quad or polygon + depthcomparemode=(tafifo_buff[1] >> 29) & 7; + cullingmode=(tafifo_buff[1] >> 27) & 3; + zwritedisable=(tafifo_buff[1] >> 26) & 1; + cachebypass=(tafifo_buff[1] >> 21) & 1; + dcalcctrl=(tafifo_buff[1] >> 20) & 1; + volumeinstruction=(tafifo_buff[1] >> 29) & 7; + + //textureusize=1 << (3+((tafifo_buff[2] >> 3) & 7)); + //texturevsize=1 << (3+(tafifo_buff[2] & 7)); + texturesizes=tafifo_buff[2] & 0x3f; + blend_mode = tafifo_buff[2] >> 26; + srcselect=(tafifo_buff[2] >> 25) & 1; + dstselect=(tafifo_buff[2] >> 24) & 1; + fogcontrol=(tafifo_buff[2] >> 22) & 3; + colorclamp=(tafifo_buff[2] >> 21) & 1; + use_alpha = (tafifo_buff[2] >> 20) & 1; + ignoretexalpha=(tafifo_buff[2] >> 19) & 1; + flipuv=(tafifo_buff[2] >> 17) & 3; + clampuv=(tafifo_buff[2] >> 15) & 3; + filtermode=(tafifo_buff[2] >> 13) & 3; + sstexture=(tafifo_buff[2] >> 12) & 1; + mmdadjust=(tafifo_buff[2] >> 8) & 1; + tsinstruction=(tafifo_buff[2] >> 6) & 3; + if (texture == 1) + { + textureaddress=(tafifo_buff[3] & 0x1FFFFF) << 3; + scanorder=(tafifo_buff[3] >> 26) & 1; + pixelformat=(tafifo_buff[3] >> 27) & 7; + mipmapped=(tafifo_buff[3] >> 31) & 1; + vqcompressed=(tafifo_buff[3] >> 30) & 1; + strideselect=(tafifo_buff[3] >> 25) & 1; + paletteselector=(tafifo_buff[3] >> 21) & 0x3F; + + LOGTATILE(" Texture at %08x format %d\n", (tafifo_buff[3] & 0x1FFFFF) << 3, pixelformat); + } + if (use_alpha == 0) + { + // Alpha value in base/offset color is to be treated as 1.0/0xFF. + poly_base_color[0] = 1.0; + if (offset_color_enable) + poly_offs_color[0] = 1.0; + } + if (paratype == 4) + { + LOGTATILE(" %s\n", + ((tafifo_listtype == DISPLAY_LIST_OPAQUE_MOD) || + (tafifo_listtype == DISPLAY_LIST_TRANS_MOD)) ? "Modifier Volume" : "Polygon" + ); + } + if (paratype == 5) + { // quad + LOGTATILE(" Sprite\n"); + } + } + + if (paratype == 7) + { // vertex + if (tafifo_listtype < 0 || tafifo_listtype >= DISPLAY_LIST_COUNT) { + LOGWARN("unrecognized list type %d\n", tafifo_listtype); + return; + } + struct poly_group *grp = rd->groups + tafifo_listtype; + if ((tafifo_listtype == DISPLAY_LIST_OPAQUE_MOD) || + (tafifo_listtype == DISPLAY_LIST_TRANS_MOD)) + { + LOGTATILE(" Vertex modifier volume"); + LOGTATILE(" A(%f,%f,%f) B(%f,%f,%f) C(%f,%f,%f)\n", + u2f(tafifo_buff[1]), u2f(tafifo_buff[2]), u2f(tafifo_buff[3]), + u2f(tafifo_buff[4]), u2f(tafifo_buff[5]), u2f(tafifo_buff[6]), + u2f(tafifo_buff[7]), u2f(tafifo_buff[8]), u2f(tafifo_buff[9]) + ); + } + else if (global_paratype == 5) + { + LOGTATILE(" Vertex sprite"); + LOGTATILE(" A(%f,%f,%f) B(%f,%f,%f) C(%f,%f,%f) D(%f,%f,)\n", + u2f(tafifo_buff[1]), u2f(tafifo_buff[2]), u2f(tafifo_buff[3]), + u2f(tafifo_buff[4]), u2f(tafifo_buff[5]), u2f(tafifo_buff[6]), + u2f(tafifo_buff[7]), u2f(tafifo_buff[8]), u2f(tafifo_buff[9]), + u2f(tafifo_buff[10]), u2f(tafifo_buff[11]) + ); + + if (rd->verts_size <= (MAX_VERTS - 6) && grp->strips_size < MAX_STRIPS) + { + vert * const tv = &rd->verts[rd->verts_size]; + tv[0].x = u2f(tafifo_buff[0x1]); + tv[0].y = u2f(tafifo_buff[0x2]); + tv[0].w = u2f(tafifo_buff[0x3]); + tv[1].x = u2f(tafifo_buff[0x4]); + tv[1].y = u2f(tafifo_buff[0x5]); + tv[1].w = u2f(tafifo_buff[0x6]); + tv[3].x = u2f(tafifo_buff[0x7]); + tv[3].y = u2f(tafifo_buff[0x8]); + tv[3].w = u2f(tafifo_buff[0x9]); + tv[2].x = u2f(tafifo_buff[0xa]); + tv[2].y = u2f(tafifo_buff[0xb]); + tv[2].w = tv[0].w+tv[3].w-tv[1].w; + + if (texture == 1) + { + tv[0].u = u2f(tafifo_buff[0xd] & 0xffff0000); + tv[0].v = u2f(tafifo_buff[0xd] << 16); + tv[1].u = u2f(tafifo_buff[0xe] & 0xffff0000); + tv[1].v = u2f(tafifo_buff[0xe] << 16); + tv[3].u = u2f(tafifo_buff[0xf] & 0xffff0000); + tv[3].v = u2f(tafifo_buff[0xf] << 16); + tv[2].u = tv[0].u+tv[3].u-tv[1].u; + tv[2].v = tv[0].v+tv[3].v-tv[1].v; + } + + for (int idx = 0; idx < 4; idx++) + { + memcpy(tv[idx].b, poly_base_color, sizeof(tv[idx].b)); + memcpy(tv[idx].o, poly_offs_color, sizeof(tv[idx].o)); + } + + strip * const ts = &grp->strips[grp->strips_size++]; + tex_get_info(&ts->ti); + ts->svert = rd->verts_size; + ts->evert = rd->verts_size + 3; + + rd->verts_size += 4; + } + } + else if (global_paratype == 4) + { + LOGTATILE(" Vertex polygon"); + LOGTATILE(" V(%f,%f,%f) T(%f,%f)\n", + u2f(tafifo_buff[1]), u2f(tafifo_buff[2]), u2f(tafifo_buff[3]), + u2f(tafifo_buff[4]), u2f(tafifo_buff[5]) + ); + + if (rd->verts_size <= (MAX_VERTS - 6)) + { + float vert_offset_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + float vert_base_color[4]; + + float base_intensity, offs_intensity; + + switch (coltype) { + case 0: + // packed color + packed_argb_to_float_argb(vert_base_color, tafifo_buff[6]); + break; + case 1: + // floating-point color + if (have_16_byte_header) { + memcpy(vert_base_color, tafifo_buff + 8, + sizeof(vert_base_color)); + memcpy(vert_offset_color, tafifo_buff + 12, + sizeof(vert_offset_color)); + } else { + memcpy(vert_base_color, tafifo_buff + 4, + sizeof(vert_base_color)); + } + break; + case 2: + case 3: + /* + * base/offset color were previously + * specified on a per-polygon basis. + * To get the per-vertex base and + * offset colors, they are scaled by + * per-vertex scalar values. + */ + memcpy(&base_intensity, tafifo_buff + 6, sizeof(base_intensity)); + memcpy(&offs_intensity, tafifo_buff + 7, sizeof(offs_intensity)); + vert_base_color[0] = poly_base_color[0] * base_intensity; + vert_base_color[1] = poly_base_color[1] * base_intensity; + vert_base_color[2] = poly_base_color[2] * base_intensity; + vert_base_color[3] = poly_base_color[3] * base_intensity; + if (offset_color_enable) { + vert_offset_color[0] = poly_offs_color[0] * offs_intensity; + vert_offset_color[1] = poly_offs_color[1] * offs_intensity; + vert_offset_color[2] = poly_offs_color[2] * offs_intensity; + vert_offset_color[3] = poly_offs_color[3] * offs_intensity; + } + break; + default: + // This will never actually happen, coltype is 2-bits. + logerror("line %d of %s - coltype is %d\n", coltype); + memset(vert_base_color, 0, sizeof(vert_base_color)); + } + + /* add a vertex to our list */ + /* this is used for 3d stuff, ie most of the graphics (see guilty gear, confidential mission, maze of the kings etc.) */ + /* -- this is also wildly inaccurate! */ + vert *tv = &rd->verts[rd->verts_size]; + + tv->x=u2f(tafifo_buff[1]); + tv->y=u2f(tafifo_buff[2]); + tv->w=u2f(tafifo_buff[3]); + tv->u=u2f(tafifo_buff[4]); + tv->v=u2f(tafifo_buff[5]); + memcpy(tv->b, vert_base_color, sizeof(tv->b)); + memcpy(tv->o, vert_offset_color, sizeof(tv->o)); + + if(grp->strips_size < MAX_STRIPS && + ((!grp->strips_size) || + grp->strips[grp->strips_size-1].evert != -1)) + { + strip *ts = &grp->strips[grp->strips_size++]; + tex_get_info(&ts->ti); + ts->svert = rd->verts_size; + ts->evert = -1; + } + if(endofstrip) + grp->strips[grp->strips_size-1].evert = rd->verts_size; + rd->verts_size++; + } + } + } + } +} + +void powervr2_device::ta_fifo_poly_w(offs_t offset, uint64_t data, uint64_t mem_mask) +{ + if (mem_mask == 0xffffffffffffffffU) // 64 bit + { + tafifo_buff[tafifo_pos]=(uint32_t)data; + tafifo_buff[tafifo_pos+1]=(uint32_t)(data >> 32); + LOGTAFIFO("ta_fifo_poly_w: write64 %08x = %x -> %08x %08x\n", + 0x10000000 + offset * 8, + data, + tafifo_buff[tafifo_pos], + tafifo_buff[tafifo_pos + 1] + ); + tafifo_pos += 2; + } + else + { + LOGWARN("ta_fifo_poly_w: Unmapped write64 %08x = %x mask %x\n", 0x10000000+offset*8, data, mem_mask); + } + + tafifo_pos &= tafifo_mask; + + // if the command is complete, process it + if (tafifo_pos == 0) + process_ta_fifo(); + +} + +TIMER_CALLBACK_MEMBER(powervr2_device::yuv_convert_end) +{ + irq_cb(EOXFER_YUV_IRQ); + yuv_timer_end->adjust(attotime::never); +} + +void powervr2_device::ta_fifo_yuv_w(uint8_t data) +{ + dc_state *state = machine().driver_data(); + + yuv_fifo[ta_yuv_index] = data; + ta_yuv_index++; + + if(ta_yuv_index == 0x180) + { +#if LIVE_YUV_VIEW + popmessage("YUV fifo write base=%08x ctrl=%08x (%dx%d)", + ta_yuv_tex_base, ta_yuv_tex_ctrl, + ta_yuv_u_size, ta_yuv_v_size + ); +#endif + + ta_yuv_index = 0; + for(int y = 0; y < 16; y++) + { + for(int x = 0; x < 16; x+=2) + { + int dst_addr; + int u, v, y0, y1; + + dst_addr = ta_yuv_tex_base; + dst_addr+= (ta_yuv_u_ptr + x) * 2; + // pitch is given by U size (320 for luptype, 512 for ss2005/kurucham) + dst_addr+= ((ta_yuv_v_ptr + y) * ta_yuv_u_size * 2); + + u = yuv_fifo[0x00+(x>>1)+((y>>1)*8)]; + v = yuv_fifo[0x40+(x>>1)+((y>>1)*8)]; + y0 = yuv_fifo[0x80+((x&8) ? 0x40 : 0x00)+((y&8) ? 0x80 : 0x00)+(x&6)+((y&7)*8)]; + y1 = yuv_fifo[0x80+((x&8) ? 0x40 : 0x00)+((y&8) ? 0x80 : 0x00)+(x&6)+((y&7)*8)+1]; + + *(uint8_t *)((reinterpret_cast(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr)) = u; + *(uint8_t *)((reinterpret_cast(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr+1)) = y0; + *(uint8_t *)((reinterpret_cast(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr+2)) = v; + *(uint8_t *)((reinterpret_cast(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr+3)) = y1; + } + } + + ta_yuv_u_ptr += 16; + if(ta_yuv_u_ptr == ta_yuv_u_size) + { + ta_yuv_u_ptr = 0; + ta_yuv_v_ptr += 16; + if(ta_yuv_v_ptr == ta_yuv_v_size) + { + ta_yuv_v_ptr = 0; + // TODO: actual timings + yuv_timer_end->adjust(state->m_maincpu->cycles_to_attotime((ta_yuv_u_size/16)*(ta_yuv_v_size/16)*0x180)); + } + } + } +} + +// SB_LMMODE0 +void powervr2_device::ta_texture_directpath0_w(offs_t offset, uint64_t data, uint64_t mem_mask) +{ + // That's not in the pvr control address space, it's in g2's + // int mode = pvrctrl_regs[SB_LMMODE0]&1; + int mode = 0; + if (mode&1) + { + printf("ta_texture_directpath0_w 32-bit access!\n"); + COMBINE_DATA(&dc_framebuffer_ram[offset]); + } + else + { + COMBINE_DATA(&dc_texture_ram[offset]); + } +} + +// SB_LMMODE1 +void powervr2_device::ta_texture_directpath1_w(offs_t offset, uint64_t data, uint64_t mem_mask) +{ + // That's not in the pvr control address space, it's in g2's + // int mode = pvrctrl_regs[SB_LMMODE1]&1; + int mode = 0; + if (mode&1) + { + printf("ta_texture_directpath1_w 32-bit access!\n"); + COMBINE_DATA(&dc_framebuffer_ram[offset]); + } + else + { + COMBINE_DATA(&dc_texture_ram[offset]); + } +} + +/* test video start */ +uint32_t powervr2_device::dilate0(uint32_t value,int bits) // dilate first "bits" bits in "value" +{ + uint32_t x,m1,m2,m3; + int a; + + x = value; + for (a=0;a < bits;a++) + { + m2 = 1 << (a << 1); + m1 = m2 - 1; + m3 = (~m1) << 1; + x = (x & m1) + (x & m2) + ((x & m3) << 1); + } + return x; +} + +uint32_t powervr2_device::dilate1(uint32_t value,int bits) // dilate first "bits" bits in "value" +{ + uint32_t x,m1,m2,m3; + int a; + + x = value; + for (a=0;a < bits;a++) + { + m2 = 1 << (a << 1); + m1 = m2 - 1; + m3 = (~m1) << 1; + x = (x & m1) + ((x & m2) << 1) + ((x & m3) << 1); + } + return x; +} + +void powervr2_device::computedilated() +{ + int a,b; + + for (b=0;b <= 14;b++) + for (a=0;a < 1024;a++) { + dilated0[b][a]=dilate0(a,b); + dilated1[b][a]=dilate1(a,b); + } + for (b=0;b <= 7;b++) + for (a=0;a <= 7;a++) + dilatechose[(b << 3) + a]=3+(a < b ? a : b); +} + +inline uint32_t powervr2_device::sample_nontextured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color) +{ + return bls24(base_color, offset_color) | (base_color & 0xff000000); +} + +template +inline uint32_t powervr2_device::sample_textured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color) +{ + uint32_t tmp; + uint32_t c = (this->*(ti->r))(ti, u, v); + if (bilinear) + { + uint32_t c1 = (this->*(ti->r))(ti, u+1.0f, v); + uint32_t c2 = (this->*(ti->r))(ti, u+1.0f, v+1.0f); + uint32_t c3 = (this->*(ti->r))(ti, u, v+1.0f); + c = bilinear_filter(c, c1, c2, c3, u, v); + } + + switch (tsinst) { + case 0: + // decal + c = bls24(c, offset_color) | (c & 0xff000000); + break; + case 1: + // modulate + tmp = blc(c, base_color); + tmp = bls24(tmp, offset_color); + tmp |= c & 0xff000000; + c = tmp; + break; + case 2: + // decal with alpha + tmp = bls24(bla(c, c), blia(base_color, c)); + c = bls24(tmp, offset_color) | (base_color & 0xff000000); + break; + case 3: + // modulate with alpha + tmp = blc(c, base_color); + tmp = bls24(tmp, offset_color); + tmp |= (((c >> 24) * (base_color >> 24)) >> 8) << 24; + c = tmp; + break; + } + return c; +} + +template +inline void powervr2_device::render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, float xl, float xr, float ul, float ur, float vl, float vr, float wl, float wr, float const bl_in[4], float const br_in[4], float const offl_in[4], float const offr_in[4]) +{ + int idx; + int xxl, xxr; + float dx, ddx, dudx, dvdx, dwdx; + uint32_t *tdata; + float *wbufline; + + float bl[4], offl[4]; + + if(xr < 0 || xl >= 640) + return; + + xxl = round(xl); + xxr = round(xr); + + if(xxl == xxr) + return; + + memcpy(bl, bl_in, sizeof(bl)); + memcpy(offl, offl_in, sizeof(offl)); + + dx = xr-xl; + float dx_recip = 1.0f / dx; + + dudx = (ur-ul) * dx_recip; + dvdx = (vr-vl) * dx_recip; + dwdx = (wr-wl) * dx_recip; + + float dbdx[4] = { + (br_in[0] - bl[0]) * dx_recip, + (br_in[1] - bl[1]) * dx_recip, + (br_in[2] - bl[2]) * dx_recip, + (br_in[3] - bl[3]) * dx_recip + }; + + float dodx[4] = { + (offr_in[0] - offl[0]) * dx_recip, + (offr_in[1] - offl[1]) * dx_recip, + (offr_in[2] - offl[2]) * dx_recip, + (offr_in[3] - offl[3]) * dx_recip + }; + + if(xxl < 0) + xxl = 0; + if(xxr > 640) + xxr = 640; + + // Target the pixel center + ddx = xxl + 0.5f - xl; + ul += ddx*dudx; + vl += ddx*dvdx; + wl += ddx*dwdx; + for (idx = 0; idx < 4; idx++) { + bl[idx] += ddx * dbdx[idx]; + offl[idx] += ddx * dodx[idx]; + } + + tdata = &bitmap.pix(y, xxl); + wbufline = &wbuffer[y][xxl]; + + while(xxl < xxr) { + if((wl >= *wbufline)) { + uint32_t c; + float u = ul/wl; + float v = vl/wl; + uint32_t offset_color = float_argb_to_packed_argb(offl); + uint32_t base_color = float_argb_to_packed_argb(bl); + c = (this->*sample_fn)(ti, u, v, offset_color, base_color); + if (group_no == DISPLAY_LIST_OPAQUE) { + *tdata = c; + *wbufline = wl; + } else { + if(c & 0xff000000) { + *wbufline = wl; + *tdata = ti->blend(c, *tdata); + } + } + } + wbufline++; + tdata++; + + ul += dudx; + vl += dvdx; + wl += dwdx; + for (idx = 0; idx < 4; idx++) { + bl[idx] += dbdx[idx]; + offl[idx] += dodx[idx]; + } + xxl ++; + } +} + +template +inline void powervr2_device::render_span(bitmap_rgb32 &bitmap, texinfo *ti, + float y0, float y1, + float xl, float xr, + float ul, float ur, + float vl, float vr, + float wl, float wr, + float const bl_in[4], float const br_in[4], + float const offl_in[4], float const offr_in[4], + float dxldy, float dxrdy, + float duldy, float durdy, + float dvldy, float dvrdy, + float dwldy, float dwrdy, + float const dbldy[4], float const dbrdy[4], + float const doldy[4], float const dordy[4]) +{ + int idx; + float dy; + int yy0, yy1; + + if(y1 <= 0) + return; + if(y1 > 480) + y1 = 480; + + float bl[4], br[4], offl[4], offr[4]; + memcpy(bl, bl_in, sizeof(bl)); + memcpy(br, br_in, sizeof(br)); + memcpy(offl, offl_in, sizeof(offl)); + memcpy(offr, offr_in, sizeof(offr)); + + if(y0 < 0) { + xl += -dxldy*y0; + xr += -dxrdy*y0; + ul += -duldy*y0; + ur += -durdy*y0; + vl += -dvldy*y0; + vr += -dvrdy*y0; + wl += -dwldy*y0; + wr += -dwrdy*y0; + + for (idx = 0; idx < 4; idx++) { + bl[idx] += -dbldy[idx] * y0; + br[idx] += -dbrdy[idx] * y0; + offl[idx] += -doldy[idx] * y0; + offr[idx] += -dordy[idx] * y0; + } + y0 = 0; + } + + yy0 = round(y0); + yy1 = round(y1); + + if((yy0 < 0 && y0 > 0) || (yy1 < 0 && y1 > 0)) //temp handling of int32 overflow, needed by hotd2/totd + return; + + dy = yy0+0.5f-y0; + + if(0) + fprintf(stderr, "%f %f %f %f -> %f %f | %f %f -> %f %f\n", + (double) y0, + (double) dy, (double) dxldy, (double) dxrdy, (double) (dy*dxldy), (double) (dy*dxrdy), + (double) xl, (double) xr, (double) (xl + dy*dxldy), (double) (xr + dy*dxrdy)); + xl += dy*dxldy; + xr += dy*dxrdy; + ul += dy*duldy; + ur += dy*durdy; + vl += dy*dvldy; + vr += dy*dvrdy; + wl += dy*dwldy; + wr += dy*dwrdy; + for (idx = 0; idx < 4; idx++) { + bl[idx] += dy * dbldy[idx]; + br[idx] += dy * dbrdy[idx]; + offl[idx] += dy * doldy[idx]; + offr[idx] += dy * dordy[idx]; + } + + while(yy0 < yy1) { + render_hline(bitmap, ti, yy0, xl, xr, ul, ur, vl, vr, wl, wr, bl, br, offl, offr); + + xl += dxldy; + xr += dxrdy; + ul += duldy; + ur += durdy; + vl += dvldy; + vr += dvrdy; + wl += dwldy; + wr += dwrdy; + for (idx = 0; idx < 4; idx++) { + bl[idx] += dbldy[idx]; + br[idx] += dbrdy[idx]; + offl[idx] += doldy[idx]; + offr[idx] += dordy[idx]; + } + + yy0 ++; + } +} + +void powervr2_device::sort_vertices(const vert *v, int *i0, int *i1, int *i2) +{ + float miny, maxy; + int imin, imax, imid; + miny = maxy = v[0].y; + imin = imax = 0; + + if(miny > v[1].y) { + miny = v[1].y; + imin = 1; + } else if(maxy < v[1].y) { + maxy = v[1].y; + imax = 1; + } + + if(miny > v[2].y) { + miny = v[2].y; + imin = 2; + } else if(maxy < v[2].y) { + maxy = v[2].y; + imax = 2; + } + + imid = (imin == 0 || imax == 0) ? (imin == 1 || imax == 1) ? 2 : 1 : 0; + + *i0 = imin; + *i1 = imid; + *i2 = imax; +} + + +template +inline void powervr2_device::render_tri_sorted(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v0, const vert *v1, const vert *v2) +{ + float dy01, dy02, dy12; + + float dx01dy, dx02dy, dx12dy, du01dy, du02dy, du12dy, dv01dy, dv02dy, dv12dy, dw01dy, dw02dy, dw12dy; + + if(v0->y >= 480 || v2->y < 0) + return; + + float db01[4] = { + v1->b[0] - v0->b[0], + v1->b[1] - v0->b[1], + v1->b[2] - v0->b[2], + v1->b[3] - v0->b[3] + }; + + float db02[4] = { + v2->b[0] - v0->b[0], + v2->b[1] - v0->b[1], + v2->b[2] - v0->b[2], + v2->b[3] - v0->b[3] + }; + + float db12[4] = { + v2->b[0] - v1->b[0], + v2->b[1] - v1->b[1], + v2->b[2] - v1->b[2], + v2->b[3] - v1->b[3] + }; + + float do01[4] = { + v1->o[0] - v0->o[0], + v1->o[1] - v0->o[1], + v1->o[2] - v0->o[2], + v1->o[3] - v0->o[3] + }; + + float do02[4] = { + v2->o[0] - v0->o[0], + v2->o[1] - v0->o[1], + v2->o[2] - v0->o[2], + v2->o[3] - v0->o[3] + }; + + float do12[4] = { + v2->o[0] - v1->o[0], + v2->o[1] - v1->o[1], + v2->o[2] - v1->o[2], + v2->o[3] - v1->o[3] + }; + + dy01 = v1->y - v0->y; + dy02 = v2->y - v0->y; + dy12 = v2->y - v1->y; + + float db01dy[4] = { + dy01 ? db01[0]/dy01 : 0, + dy01 ? db01[1]/dy01 : 0, + dy01 ? db01[2]/dy01 : 0, + dy01 ? db01[3]/dy01 : 0 + }; + + float db02dy[4] = { + dy01 ? db02[0]/dy02 : 0, + dy01 ? db02[1]/dy02 : 0, + dy01 ? db02[2]/dy02 : 0, + dy01 ? db02[3]/dy02 : 0 + }; + + float db12dy[4] = { + dy01 ? db12[0]/dy12 : 0, + dy01 ? db12[1]/dy12 : 0, + dy01 ? db12[2]/dy12 : 0, + dy01 ? db12[3]/dy12 : 0 + }; + + float do01dy[4] = { + dy01 ? do01[0]/dy01 : 0, + dy01 ? do01[1]/dy01 : 0, + dy01 ? do01[2]/dy01 : 0, + dy01 ? do01[3]/dy01 : 0 + }; + + float do02dy[4] = { + dy01 ? do02[0]/dy02 : 0, + dy01 ? do02[1]/dy02 : 0, + dy01 ? do02[2]/dy02 : 0, + dy01 ? do02[3]/dy02 : 0 + }; + + float do12dy[4] = { + dy01 ? do12[0]/dy12 : 0, + dy01 ? do12[1]/dy12 : 0, + dy01 ? do12[2]/dy12 : 0, + dy01 ? do12[3]/dy12 : 0 + }; + + dx01dy = dy01 ? (v1->x-v0->x)/dy01 : 0; + dx02dy = dy02 ? (v2->x-v0->x)/dy02 : 0; + dx12dy = dy12 ? (v2->x-v1->x)/dy12 : 0; + + du01dy = dy01 ? (v1->u-v0->u)/dy01 : 0; + du02dy = dy02 ? (v2->u-v0->u)/dy02 : 0; + du12dy = dy12 ? (v2->u-v1->u)/dy12 : 0; + + dv01dy = dy01 ? (v1->v-v0->v)/dy01 : 0; + dv02dy = dy02 ? (v2->v-v0->v)/dy02 : 0; + dv12dy = dy12 ? (v2->v-v1->v)/dy12 : 0; + + dw01dy = dy01 ? (v1->w-v0->w)/dy01 : 0; + dw02dy = dy02 ? (v2->w-v0->w)/dy02 : 0; + dw12dy = dy12 ? (v2->w-v1->w)/dy12 : 0; + + if(!dy01) { + if(!dy12) + return; + + if(v1->x > v0->x) + render_span(bitmap, ti, v1->y, v2->y, v0->x, v1->x, v0->u, v1->u, v0->v, v1->v, v0->w, v1->w, v0->b, v1->b, v0->o, v1->o, dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy, db02dy, db12dy, do02dy, do12dy); + else + render_span(bitmap, ti, v1->y, v2->y, v1->x, v0->x, v1->u, v0->u, v1->v, v0->v, v1->w, v0->w, v1->b, v0->b, v1->o, v0->o, dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy, db12dy, db02dy, do12dy, do02dy); + + } else if(!dy12) { + if(v2->x > v1->x) + render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy, db01dy, db02dy, do01dy, do02dy); + else + render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy, db02dy, db01dy, do02dy, do01dy); + + } else { + float idk_b[4] = { + v0->b[0] + db02dy[0] * dy01, + v0->b[1] + db02dy[1] * dy01, + v0->b[2] + db02dy[2] * dy01, + v0->b[3] + db02dy[3] * dy01 + }; + float idk_o[4] = { + v0->o[0] + do02dy[0] * dy01, + v0->o[1] + do02dy[1] * dy01, + v0->o[2] + do02dy[2] * dy01, + v0->o[3] + do02dy[3] * dy01 + }; + if(dx01dy < dx02dy) { + render_span(bitmap, ti, v0->y, v1->y, + v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, + dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy, db01dy, db02dy, do01dy, do02dy); + render_span(bitmap, ti, v1->y, v2->y, + v1->x, v0->x + dx02dy*dy01, v1->u, v0->u + du02dy*dy01, v1->v, v0->v + dv02dy*dy01, v1->w, v0->w + dw02dy*dy01, v1->b, idk_b, v1->o, idk_o, + dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy, db12dy, db02dy, do12dy, do02dy); + } else { + render_span(bitmap, ti, v0->y, v1->y, + v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, + dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy, db02dy, db01dy, do02dy, do01dy); + render_span(bitmap, ti, v1->y, v2->y, + v0->x + dx02dy*dy01, v1->x, v0->u + du02dy*dy01, v1->u, v0->v + dv02dy*dy01, v1->v, v0->w + dw02dy*dy01, v1->w, idk_b, v1->b, idk_o, v1->o, + dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy, db02dy, db12dy, do02dy, do12dy); + } + } +} + +template +void powervr2_device::render_tri(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v) +{ + int i0, i1, i2; + + sort_vertices(v, &i0, &i1, &i2); + + bool textured = ti->textured; + if (textured) { + bool bilinear = (debug_dip_status & 1) && + (ti->filter_mode >= TEX_FILTER_BILINEAR); + if (bilinear) { + switch (ti->tsinstruction) { + case 0: + render_tri_sorted<&powervr2_device::sample_textured<0,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + break; + case 1: + render_tri_sorted<&powervr2_device::sample_textured<1,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + break; + case 2: + render_tri_sorted<&powervr2_device::sample_textured<2,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + break; + case 3: + render_tri_sorted<&powervr2_device::sample_textured<3,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + break; + default: + /* + * This should be impossible because tsinstruction was previously + * AND'd with 3 + */ + logerror("%s - tsinstruction is 0x%08x\n", (unsigned)ti->tsinstruction); + render_tri_sorted<&powervr2_device::sample_nontextured, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + } + } else { + switch (ti->tsinstruction) { + case 0: + render_tri_sorted<&powervr2_device::sample_textured<0,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + break; + case 1: + render_tri_sorted<&powervr2_device::sample_textured<1,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + break; + case 2: + render_tri_sorted<&powervr2_device::sample_textured<2,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + break; + case 3: + render_tri_sorted<&powervr2_device::sample_textured<3,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + break; + default: + /* + * This should be impossible because tsinstruction was previously + * AND'd with 3 + */ + logerror("%s - tsinstruction is 0x%08x\n", (unsigned)ti->tsinstruction); + render_tri_sorted<&powervr2_device::sample_nontextured, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + } + } + } else { + render_tri_sorted<&powervr2_device::sample_nontextured, group_no>(bitmap, ti, v+i0, v+i1, v+i2); + } +} + +template +void powervr2_device::render_group_to_accumulation_buffer(bitmap_rgb32 &bitmap,const rectangle &cliprect) +{ +#if 0 + int stride; + uint16_t *bmpaddr16; + uint32_t k; +#endif + + + if (renderselect < 0) + return; + + //printf("drawtest!\n"); + + int rs=renderselect; + + struct poly_group *grp = grab[rs].groups + group_no; + + int ns=grp->strips_size; + + for (int cs=0;cs < ns;cs++) + { + strip *ts = &grp->strips[cs]; + int sv = ts->svert; + int ev = ts->evert; + int i; + if(ev == -1) + continue; + + for(i=sv; i <= ev; i++) + { + vert *tv = grab[rs].verts + i; + tv->u = tv->u * ts->ti.sizex * tv->w; + tv->v = tv->v * ts->ti.sizey * tv->w; + } + + for(i=sv; i <= ev-2; i++) + { + if (!(debug_dip_status&0x2)) + render_tri(bitmap, &ts->ti, grab[rs].verts + i); + + } + } +} + +void powervr2_device::render_to_accumulation_buffer(bitmap_rgb32 &bitmap, const rectangle &cliprect) { + if (renderselect < 0) + return; + + memset(wbuffer, 0x00, sizeof(wbuffer)); + + dc_state *state = machine().driver_data(); + address_space &space = state->m_maincpu->space(AS_PROGRAM); + + // TODO: read ISP/TSP command from isp_background_t instead of assuming Gourad-shaded + // full-screen polygon. + uint32_t c=space.read_dword(0x05000000+(param_base&0xf00000)+((isp_backgnd_t&0xfffff8)>>1)+(3+3)*4); + bitmap.fill(c, cliprect); + + // TODO: modifier volumes + render_group_to_accumulation_buffer(bitmap, cliprect); + render_group_to_accumulation_buffer(bitmap, cliprect); + render_group_to_accumulation_buffer(bitmap, cliprect); + + grab[renderselect].busy=0; +} + +// copies the accumulation buffer into the framebuffer, converting to the specified format +// not accurate, ignores field stuff and just uses SOF1 for now +// also ignores scale effects (can scale accumulation buffer to half size with filtering etc.) +// also can specify dither etc. +// basically, just a crude implementation! + +/* 0555KRGB = 0 */ +void powervr2_device::fb_convert_0555krgb_to_555rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000f800) >> 11)) << 5) | + ((((data & 0x00f80000) >> 19)) << 10); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_0555krgb_to_565rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000f800) >> 11)) << 5) | + ((((data & 0x00f80000) >> 19)) << 11); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_0555krgb_to_888rgb24(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xf8f8f8); + + space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); + space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); + space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); + } + } +} + +void powervr2_device::fb_convert_0555krgb_to_888rgb32(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xf8f8f8); + + space.write_dword(realwriteoffs+xcnt*4, newdat); + } + } +} + +/* 0565RGB = 1 */ +void powervr2_device::fb_convert_0565rgb_to_555rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000fc00) >> 10)) << 5) | + ((((data & 0x00f80000) >> 19)) << 10); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_0565rgb_to_565rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000fc00) >> 10)) << 5) | + ((((data & 0x00f80000) >> 19)) << 11); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_0565rgb_to_888rgb24(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xf8fcf8); + + space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); + space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); + space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); + } + } +} + +void powervr2_device::fb_convert_0565rgb_to_888rgb32(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xf8fcf8); + + space.write_dword(realwriteoffs+xcnt*4, newdat); + } + } +} + +/* 1555ARGB = 3 */ +void powervr2_device::fb_convert_1555argb_to_555rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000f800) >> 11)) << 5) | + ((((data & 0x00f80000) >> 19)) << 10); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_1555argb_to_565rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000f800) >> 11)) << 5) | + ((((data & 0x00f80000) >> 19)) << 11); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_1555argb_to_888rgb24(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xf8f8f8); + + space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); + space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); + space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); + } + } +} + +void powervr2_device::fb_convert_1555argb_to_888rgb32(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xf8f8f8); + + space.write_dword(realwriteoffs+xcnt*4, newdat); + } + } +} + +/* 888RGB = 4 */ +void powervr2_device::fb_convert_888rgb_to_555rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000f800) >> 11)) << 5) | + ((((data & 0x00f80000) >> 16)) << 10); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_888rgb_to_565rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000fc00) >> 11)) << 5) | + ((((data & 0x00f80000) >> 16)) << 11); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_888rgb_to_888rgb24(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xffffff); + + space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); + space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); + space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); + } + } +} + +void powervr2_device::fb_convert_888rgb_to_888rgb32(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xffffff); + + space.write_dword(realwriteoffs+xcnt*4, newdat); + } + } +} + + +/* 8888ARGB = 6 */ +void powervr2_device::fb_convert_8888argb_to_555rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000f800) >> 11)) << 5) | + ((((data & 0x00f80000) >> 16)) << 10); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_8888argb_to_565rgb(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | + ((((data & 0x0000fc00) >> 11)) << 5) | + ((((data & 0x00f80000) >> 16)) << 11); + + space.write_word(realwriteoffs+xcnt*2, newdat); + } + } +} + +void powervr2_device::fb_convert_8888argb_to_888rgb24(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xffffff); + + space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); + space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); + space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); + } + } +} + +void powervr2_device::fb_convert_8888argb_to_888rgb32(address_space &space, int x,int y) +{ + for (int ycnt=0;ycnt<32;ycnt++) + { + uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); + + for (int xcnt=0;xcnt<32;xcnt++) + { + // data starts in 8888 format, downsample it + uint32_t data = src[xcnt]; + uint32_t newdat = (data & 0xffffff); + + space.write_dword(realwriteoffs+xcnt*4, newdat); + } + } +} + + +/* + +0x0 0555 KRGB 16 bit (default) Bit 15 is the value of fb_kval 7. +0x1 565 RGB 16 bit +0x2 4444 ARGB 16 bit +0x3 1555 ARGB 16 bit The alpha value is determined by comparison with the value of fb_alpha_threshold. +0x4 888 RGB 24 bit packed +0x5 0888 KRGB 32 bit K is the value of fk_kval. +0x6 8888 ARGB 32 bit +0x7 Setting prohibited. + +*/ + +void powervr2_device::pvr_accumulationbuffer_to_framebuffer(address_space &space, int x,int y) +{ + // the accumulation buffer is always 8888 + // + // the standard format for the framebuffer appears to be 565 + // yes, this means colour data is lost in the conversion + + uint8_t packmode = fb_w_ctrl & 0x7; + uint8_t unpackmode = (fb_r_ctrl & 0x0000000c) >>2; // aka fb_depth + +// popmessage("%02x %02x",packmode,unpackmode); + + switch (packmode) + { + // used by ringout + case 0x00: //0555 KRGB + { + switch(unpackmode) + { + case 0x00: fb_convert_0555krgb_to_555rgb(space,x,y); break; + case 0x01: fb_convert_0555krgb_to_565rgb(space,x,y); break; + case 0x02: fb_convert_0555krgb_to_888rgb24(space,x,y); break; + case 0x03: fb_convert_0555krgb_to_888rgb32(space,x,y); break; + } + } + break; + + // used by cleoftp + case 0x01: //565 RGB 16 bit + { + switch(unpackmode) + { + case 0x00: fb_convert_0565rgb_to_555rgb(space,x,y); break; + case 0x01: fb_convert_0565rgb_to_565rgb(space,x,y); break; + case 0x02: fb_convert_0565rgb_to_888rgb24(space,x,y); break; + case 0x03: fb_convert_0565rgb_to_888rgb32(space,x,y); break; + } + } + break; + + case 0x02: + printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (4444 ARGB)\n",x,y,packmode); + break; + + case 0x03: // 1555 ARGB 16 bit + { + switch(unpackmode) + { + case 0x00: fb_convert_1555argb_to_555rgb(space,x,y); break; + case 0x01: fb_convert_1555argb_to_565rgb(space,x,y); break; + case 0x02: fb_convert_1555argb_to_888rgb24(space,x,y); break; + case 0x03: fb_convert_1555argb_to_888rgb32(space,x,y); break; + } + } + break; + + // used by Suchie3 + case 0x04: // 888 RGB 24-bit + { + switch(unpackmode) + { + case 0x00: fb_convert_888rgb_to_555rgb(space,x,y); break; + case 0x01: fb_convert_888rgb_to_565rgb(space,x,y); break; + case 0x02: fb_convert_888rgb_to_888rgb24(space,x,y); break; + case 0x03: fb_convert_888rgb_to_888rgb32(space,x,y); break; + } + } + break; + + case 0x05: // 0888 KRGB 32 bit + { + switch(unpackmode) + { + case 0x00: fb_convert_8888argb_to_555rgb(space,x,y); break; + case 0x01: fb_convert_8888argb_to_565rgb(space,x,y); break; + case 0x02: fb_convert_8888argb_to_888rgb24(space,x,y); break; + case 0x03: fb_convert_8888argb_to_888rgb32(space,x,y); break; + } + } + break; + + case 0x06: // 8888 ARGB 32 bit + { + switch(unpackmode) + { + case 0x00: fb_convert_8888argb_to_555rgb(space,x,y); break; + case 0x01: fb_convert_8888argb_to_565rgb(space,x,y); break; + case 0x02: fb_convert_8888argb_to_888rgb24(space,x,y); break; + case 0x03: fb_convert_8888argb_to_888rgb32(space,x,y); break; + } + } + break; + + case 0x07: + throw emu_fatalerror("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (Reserved! Don't Use!)\n",x,y,packmode); + break; + } +} + +void powervr2_device::pvr_drawframebuffer(bitmap_rgb32 &bitmap,const rectangle &cliprect) +{ + int dy,xi; + uint8_t interlace_on = ((spg_control & 0x10) >> 4); + int32_t ystart_f1 = (vo_starty & 0x3ff) << interlace_on; + //int32_t ystart_f2 = (vo_starty >> 16) & 0x3ff; + int32_t hstart = (vo_startx & 0x3ff); +// rectangle fbclip; + + uint8_t unpackmode = (fb_r_ctrl & 0x0000000c) >>2; // aka fb_depth + uint8_t enable = (fb_r_ctrl & 0x00000001); + + // ?? + if (!enable) return; + + // only for rgb565 framebuffer + xi=((fb_r_size & 0x3ff)+1) << 1; + dy=((fb_r_size >> 10) & 0x3ff)+1; + + dy++; + dy*=2; // probably depends on interlace mode, fields etc... + +// popmessage("%d %d %d %d %d",ystart_f1,ystart_f2,interlace_on,spg_vblank & 0x3ff,(spg_vblank >> 16) & 0x3ff); + +#if 0 + fbclip.min_x = hstart; + fbclip.min_y = ystart_f1; + fbclip.max_x = hstart + (xi << ((vo_control & 0x100) >> 8)); + fbclip.max_y = ystart_f1 + dy; + + popmessage("%d %d %d %d",fbclip.min_x,fbclip.min_y,fbclip.max_x,fbclip.max_y); +#endif + + switch (unpackmode) + { + case 0x00: // 0555 RGB 16-bit, Cleo Fortune Plus + // should upsample back to 8-bit output using fb_concat + for (int y=0;y <= dy;y++) + { + uint32_t addrp = fb_r_sof1+y*xi*2; + if(vo_control & 0x100) + { + for (int x=0;x < xi;x++) + { + int res_x = x*2+0 + hstart; + int res_y = y + ystart_f1; + + uint32_t *fbaddr=&bitmap.pix(res_y, res_x); + uint32_t c=*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); + + uint32_t b = (c & 0x001f) << 3; + uint32_t g = (c & 0x03e0) >> 2; + uint32_t r = (c & 0x7c00) >> 7; + + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + + res_x = x*2+1 + hstart; + + fbaddr=&bitmap.pix(res_y, res_x); + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + addrp+=2; + } + } + else + { + for (int x=0;x < xi;x++) + { + int res_x = x + hstart; + int res_y = y + ystart_f1; + + uint32_t *fbaddr=&bitmap.pix(res_y, res_x); + uint32_t c=*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); + + uint32_t b = (c & 0x001f) << 3; + uint32_t g = (c & 0x03e0) >> 2; + uint32_t r = (c & 0x7c00) >> 7; + + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + addrp+=2; + } + } + } + break; + + case 0x01: // 0565 RGB 16-bit + // should upsample back to 8-bit output using fb_concat + for (int y=0;y <= dy;y++) + { + uint32_t addrp = fb_r_sof1+y*xi*2; + if(vo_control & 0x100) + { + for (int x=0;x < xi;x++) + { + int res_x = x*2+0 + hstart; + int res_y = y + ystart_f1; + uint32_t *fbaddr=&bitmap.pix(res_y, res_x); + uint32_t c=*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); + + uint32_t b = (c & 0x001f) << 3; + uint32_t g = (c & 0x07e0) >> 3; + uint32_t r = (c & 0xf800) >> 8; + + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + + res_x = x*2+1 + hstart; + //res_y = y + ystart_f1; + fbaddr=&bitmap.pix(res_y, res_x); + + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + + addrp+=2; + } + } + else + { + for (int x=0;x < xi;x++) + { + int res_x = x + hstart; + int res_y = y + ystart_f1; + uint32_t *fbaddr=&bitmap.pix(res_y, res_x); + uint32_t c=*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); + + uint32_t b = (c & 0x001f) << 3; + uint32_t g = (c & 0x07e0) >> 3; + uint32_t r = (c & 0xf800) >> 8; + + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + addrp+=2; + } + } + } + break; + + case 0x02: ; // 888 RGB 24-bit - suchie3, Soul Calibur + for (int y=0;y <= dy;y++) + { + uint32_t addrp = fb_r_sof1+y*xi*2; + + if(vo_control & 0x100) + { + for (int x=0;x < xi;x++) + { + int res_x = x*2+0 + hstart; + int res_y = y + ystart_f1; + + uint32_t *fbaddr=&bitmap.pix(res_y, res_x); + + uint32_t b =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp)); + + uint32_t g =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+1)); + + uint32_t r =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+2)); + + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + + res_x = x*2+1 + hstart; + + fbaddr=&bitmap.pix(res_y, res_x); + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + + addrp+=3; + } + } + else + { + for (int x=0;x < xi;x++) + { + int res_x = x + hstart; + int res_y = y + ystart_f1; + uint32_t *fbaddr=&bitmap.pix(res_y, res_x); + + uint32_t b =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp)); + + uint32_t g =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+1)); + + uint32_t r =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+2)); + + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + + addrp+=3; + } + } + } + break; + + case 0x03: // 0888 ARGB 32-bit + for (int y=0;y <= dy;y++) + { + uint32_t addrp = fb_r_sof1+y*xi*2; + + if(vo_control & 0x100) + { + for (int x=0;x < xi;x++) + { + int res_x = x*2+0 + hstart; + int res_y = y + ystart_f1; + + uint32_t *fbaddr=&bitmap.pix(res_y, res_x); + uint32_t c =*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 2)); + + uint32_t b = (c & 0x0000ff) >> 0; + uint32_t g = (c & 0x00ff00) >> 8; + uint32_t r = (c & 0xff0000) >> 16; + + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + + res_x = x*2+1 + hstart; + + fbaddr=&bitmap.pix(res_y, res_x); + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + + addrp+=4; + } + } + else + { + for (int x=0;x < xi;x++) + { + int res_x = x + hstart; + int res_y = y + ystart_f1; + uint32_t *fbaddr=&bitmap.pix(res_y, res_x); + uint32_t c =*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 2)); + + uint32_t b = (c & 0x0000ff) >> 0; + uint32_t g = (c & 0x00ff00) >> 8; + uint32_t r = (c & 0xff0000) >> 16; + + if (cliprect.contains(res_x, res_y)) + *fbaddr = b | (g<<8) | (r<<16); + + addrp+=4; + } + } + } + break; + } +} + +/* test video end */ + +void powervr2_device::pvr_build_parameterconfig() +{ + int a,b,c,d,e,p; + + for (a = 0;a <= 63;a++) + pvr_parameterconfig[a] = -1; + p=0; + // volume,col_type,texture,offset,16bit_uv + for (a = 0;a <= 1;a++) + for (b = 0;b <= 3;b++) + for (c = 0;c <= 1;c++) + if (c == 0) + { + for (d = 0;d <= 1;d++) + for (e = 0;e <= 1;e++) + pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p]; + p++; + } + else + for (d = 0;d <= 1;d++) + for (e = 0;e <= 1;e++) + { + pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p]; + p++; + } + for (a = 1;a <= 63;a++) + if (pvr_parameterconfig[a] < 0) + pvr_parameterconfig[a] = pvr_parameterconfig[a-1]; +} + +// TODO: these two are currently unused +TIMER_CALLBACK_MEMBER(powervr2_device::vbin) +{ + LOGIRQ("[%d] VBL IN %d\n", screen().frame_number(), screen().vpos()); + LOGIRQ(" VII %d VOI %d VI %d VO %d VS %d\n", + spg_vblank_int & 0x3ff, (spg_vblank_int >> 16) & 0x3ff, + spg_vblank & 0x3ff, (spg_vblank >> 16) & 0x3ff, (spg_load >> 16) & 0x3ff + ); + + irq_cb(VBL_IN_IRQ); + +// vbin_timer->adjust(screen().time_until_pos(spg_vblank_int & 0x3ff)); +} + +TIMER_CALLBACK_MEMBER(powervr2_device::vbout) +{ + LOGIRQ("[%d] VBL OUT %d\n", screen().frame_number(), screen().vpos()); + + irq_cb(VBL_OUT_IRQ); + +// vbout_timer->adjust(screen().time_until_pos((spg_vblank_int >> 16) & 0x3ff)); +} + +TIMER_CALLBACK_MEMBER(powervr2_device::hbin) +{ + if(spg_hblank_int & 0x1000) + { + if(scanline == next_y) + { + LOGIRQ("[%d] HBL IN %d - (%08x)\n", + screen().frame_number(), screen().vpos(), scanline, spg_hblank_int + ); + irq_cb(HBL_IN_IRQ); + next_y += spg_hblank_int & 0x3ff; + } + } + else if((scanline == (spg_hblank_int & 0x3ff)) || (spg_hblank_int & 0x2000)) + { + LOGIRQ("[%d] HBL IN %d - (%08x)\n", + screen().frame_number(), screen().vpos(), scanline, spg_hblank_int + ); + irq_cb(HBL_IN_IRQ); + } + + scanline++; + + if(scanline >= ((spg_load >> 16) & 0x3ff)) + { + scanline = 0; + next_y = spg_hblank_int & 0x3ff; + } + + hbin_timer->adjust(screen().time_until_pos(scanline, ((spg_hblank_int >> 16) & 0x3ff)-1)); +} + +// TODO: these two aren't really called atm +TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_video) +{ + LOGIRQ("[%d] VIDEO END %d\n", screen().frame_number(), screen().vpos()); +// endofrender_timer_video->adjust(attotime::never); +} + +TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_tsp) +{ + LOGIRQ("[%d] TSP END %d\n", screen().frame_number(), screen().vpos()); + +// endofrender_timer_tsp->adjust(attotime::never); +// endofrender_timer_video->adjust(attotime::from_usec(500) ); +} + +TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_isp) +{ + irq_cb(EOR_ISP_IRQ); // ISP end of render + irq_cb(EOR_TSP_IRQ); // TSP end of render + irq_cb(EOR_VIDEO_IRQ); // VIDEO end of render + + LOGIRQ("[%d] ISP END %d\n", screen().frame_number(), screen().vpos()); + + endofrender_timer_isp->adjust(attotime::never); +// endofrender_timer_tsp->adjust(attotime::from_usec(500) ); +} + +uint32_t powervr2_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + /****************** + MAME note + ******************* + + The video update function should NOT be generating interrupts, setting timers or doing _anything_ the game might be able to detect + as it will be called at different times depending on frameskip etc. + + Rendering should happen when the hardware requests it, to the framebuffer(s) + + Everything else should depend on timers. + + ******************/ + +// static int useframebuffer=1; +// const rectangle &visarea = screen.visible_area(); + + // copy our fake framebuffer bitmap (where things have been rendered) to the screen +#if 0 + for (int y = visarea->min_y ; y <= visarea->max_y ; y++) + { + for (int x = visarea->min_x ; x <= visarea->max_x ; x++) + { + uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y, x); + uint32_t *const dst = &bitmap.pix(y, x); + dst[0] = src[0]; + } + } +#endif + + //FIXME: additional Chroma bit + bitmap.fill(rgb_t(0xff, (vo_border_col >> 16) & 0xff, + (vo_border_col >> 8 ) & 0xff, + (vo_border_col ) & 0xff), cliprect); + + if(!(vo_control & 8)) + pvr_drawframebuffer(bitmap, cliprect); + + // update this here so we only do string lookup once per frame + debug_dip_status = m_mamedebug->read(); + + return 0; +} + +TIMER_CALLBACK_MEMBER(powervr2_device::pvr_dma_irq) +{ + LOGIRQ("[%d] PVR DMA %d\n", screen().frame_number(), screen().vpos()); + + m_pvr_dma.start = sb_pdst = 0; + irq_cb(DMA_PVR_IRQ); +} + +/* used so far by usagiym and sprtjam */ +// TODO: very inaccurate +void powervr2_device::pvr_dma_execute(address_space &space) +{ + dc_state *state = machine().driver_data(); + uint32_t src,dst,size; + dst = m_pvr_dma.pvr_addr; + src = m_pvr_dma.sys_addr; + size = 0; + + LOGPVRDMA("PVR-DMA start\n"); + LOGPVRDMA("%08x %08x %08x\n",m_pvr_dma.pvr_addr, m_pvr_dma.sys_addr, m_pvr_dma.size); + LOGPVRDMA("src %s dst %08x\n",m_pvr_dma.dir ? "->" : "<-",m_pvr_dma.sel); + + /* Throw illegal address set */ + // TODO: unimplemented for now, checkable from DCLP +#if 0 + if((m_pvr_dma.sys_addr & 0x1c000000) != 0x0c000000) + { + irq_cb(ERR_PVRIF_ILL_ADDR_IRQ); + m_pvr_dma.start = sb_pdst = 0; + printf("Illegal PVR DMA set\n"); + return; + } +#endif + + /* 0 rounding size = 16 Mbytes */ + if(m_pvr_dma.size == 0) { m_pvr_dma.size = 0x100000; } + + if(m_pvr_dma.dir == 0) + { + for(;size < m_pvr_dma.size; size+=4) + { + space.write_dword(dst,space.read_dword(src)); + src+=4; + dst+=4; + } + } + else + { + for(;size < m_pvr_dma.size; size+=4) + { + space.write_dword(src,space.read_dword(dst)); + src+=4; + dst+=4; + } + } + + /* Note: do not update the params, since this DMA type doesn't support it. */ + // TODO: accurate timing + dma_irq_timer->adjust(state->m_maincpu->cycles_to_attotime(m_pvr_dma.size/4)); +} + +INPUT_PORTS_START( powervr2 ) + PORT_START("PVR_DEBUG") + PORT_CONFNAME( 0x01, 0x00, "Bilinear Filtering" ) + PORT_CONFSETTING( 0x00, DEF_STR( No ) ) + PORT_CONFSETTING( 0x01, DEF_STR( Yes ) ) + PORT_CONFNAME( 0x02, 0x00, "Disable Render Calls" ) + PORT_CONFSETTING( 0x00, DEF_STR( No ) ) + PORT_CONFSETTING( 0x02, DEF_STR( Yes ) ) +INPUT_PORTS_END + +ioport_constructor powervr2_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( powervr2 ); +} + +powervr2_device::powervr2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, POWERVR2, tag, owner, clock) + , device_video_interface(mconfig, *this) + , irq_cb(*this) + , m_mamedebug(*this, "PVR_DEBUG") +{ +} + +void powervr2_device::device_start() +{ + irq_cb.resolve_safe(); + + grab = std::make_unique(NUM_BUFFERS); + + pvr_build_parameterconfig(); + + computedilated(); + +// vbout_timer = timer_alloc(FUNC(powervr2_device::vbout), this); +// vbin_timer = timer_alloc(FUNC(powervr2_device::vbin), this); + hbin_timer = timer_alloc(FUNC(powervr2_device::hbin), this); + yuv_timer_end = timer_alloc(FUNC(powervr2_device::yuv_convert_end), this); + + endofrender_timer_isp = timer_alloc(FUNC(powervr2_device::endofrender_isp), this); + endofrender_timer_tsp = timer_alloc(FUNC(powervr2_device::endofrender_tsp), this); + endofrender_timer_video = timer_alloc(FUNC(powervr2_device::endofrender_video), this); + + opaque_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_opaque_list_irq), this); + opaque_modifier_volume_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_opaque_modifier_volume_list_irq), this); + translucent_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_translucent_list_irq), this); + translucent_modifier_volume_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_translucent_modifier_volume_list_irq), this); + punch_through_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_punch_through_list_irq), this); + dma_irq_timer = timer_alloc(FUNC(powervr2_device::pvr_dma_irq), this); + + fake_accumulationbuffer_bitmap = std::make_unique(2048,2048); + + softreset = 0; + param_base = 0; + region_base = 0; + vo_border_col = 0; + fb_r_ctrl = 0; + fb_w_ctrl = 0; + fb_w_linestride = 0; + fb_r_sof1 = 0; + fb_r_sof2 = 0; + fb_r_size = 0; + fb_w_sof1 = 0; + fb_w_sof2 = 0; + fb_x_clip = 0; + fb_y_clip = 0; + fpu_param_cfg = 0; + isp_backgnd_t = 0; + spg_hblank_int = 0; + spg_vblank_int = 0; + spg_hblank = 0; + spg_load = 0; + spg_vblank = 0; + spg_width = 0; + spg_control = 0; + vo_control = 0; + vo_startx = 0; + vo_starty = 0; + text_control = 0; + pal_ram_ctrl = 0; + ta_ol_base = 0; + ta_ol_limit = 0; + ta_isp_base = 0; + ta_isp_limit = 0; + ta_next_opb = 0; + ta_itp_current = 0; + ta_alloc_ctrl = 0; + ta_next_opb_init = 0; + ta_yuv_tex_base = 0; + ta_yuv_tex_ctrl = 0; + ta_yuv_tex_cnt = 0; + memset(fog_table, 0, sizeof(fog_table)); + memset(palette, 0, sizeof(palette)); + memset(&m_pvr_dma, 0x00, sizeof(m_pvr_dma)); + + sb_pdstap = 0; + sb_pdstar = 0; + sb_pdlen = 0; + sb_pddir = 0; + sb_pdtsel = 0; + sb_pden = 0; + sb_pdst = 0; + sb_pdapro = 0; + + save_item(NAME(softreset)); + save_item(NAME(param_base)); + save_item(NAME(region_base)); + save_item(NAME(vo_border_col)); + save_item(NAME(fb_r_ctrl)); + save_item(NAME(fb_w_ctrl)); + save_item(NAME(fb_w_linestride)); + save_item(NAME(fb_r_sof1)); + save_item(NAME(fb_r_sof2)); + save_item(NAME(fb_r_size)); + save_item(NAME(fb_w_sof1)); + save_item(NAME(fb_w_sof2)); + save_item(NAME(fb_x_clip)); + save_item(NAME(fb_y_clip)); + save_item(NAME(fpu_param_cfg)); + save_item(NAME(isp_backgnd_t)); + save_item(NAME(spg_hblank_int)); + save_item(NAME(spg_vblank_int)); + save_item(NAME(spg_hblank)); + save_item(NAME(spg_load)); + save_item(NAME(spg_vblank)); + save_item(NAME(spg_width)); + save_item(NAME(vo_control)); + save_item(NAME(vo_startx)); + save_item(NAME(vo_starty)); + save_item(NAME(text_control)); + save_item(NAME(pal_ram_ctrl)); + save_item(NAME(ta_ol_base)); + save_item(NAME(ta_ol_limit)); + save_item(NAME(ta_isp_base)); + save_item(NAME(ta_isp_limit)); + save_item(NAME(ta_next_opb)); + save_item(NAME(ta_itp_current)); + save_item(NAME(ta_alloc_ctrl)); + save_item(NAME(ta_next_opb_init)); + save_item(NAME(ta_yuv_tex_base)); + save_item(NAME(ta_yuv_tex_ctrl)); + save_item(NAME(ta_yuv_tex_cnt)); + save_pointer(NAME(fog_table), 0x80); + save_pointer(NAME(palette), 0x400); + + save_item(NAME(sb_pdstap)); + save_item(NAME(sb_pdstar)); + save_item(NAME(sb_pdlen)); + save_item(NAME(sb_pddir)); + save_item(NAME(sb_pdtsel)); + save_item(NAME(sb_pden)); + save_item(NAME(sb_pdst)); + save_item(NAME(sb_pdapro)); + + save_item(NAME(m_pvr_dma.pvr_addr)); + save_item(NAME(m_pvr_dma.sys_addr)); + save_item(NAME(m_pvr_dma.size)); + save_item(NAME(m_pvr_dma.sel)); + save_item(NAME(m_pvr_dma.dir)); + save_item(NAME(m_pvr_dma.flag)); + save_item(NAME(m_pvr_dma.start)); + save_item(NAME(debug_dip_status)); + save_pointer(NAME(tafifo_buff),32); + save_item(NAME(scanline)); + save_item(NAME(next_y)); +} + +void powervr2_device::device_reset() +{ + softreset = 0x00000007; + vo_control = 0x00000108; + vo_startx = 0x0000009d; + vo_starty = 0x00150015; + spg_hblank = 0x007e0345; + spg_load = 0x01060359; + spg_vblank = 0x01500104; + spg_hblank_int = 0x031d0000; + spg_vblank_int = 0x01500104; + + tafifo_pos = 0; + tafifo_mask = 7; + tafifo_vertexwords = 8; + tafifo_listtype = DISPLAY_LIST_NONE; + start_render_received = 0; + renderselect = -1; + grabsel = 0; + +// vbout_timer->adjust(screen().time_until_pos((spg_vblank_int >> 16) & 0x3ff)); +// vbin_timer->adjust(screen().time_until_pos(spg_vblank_int & 0x3ff)); + hbin_timer->adjust(screen().time_until_pos(0, ((spg_hblank_int >> 16) & 0x3ff)-1)); + + scanline = 0; + next_y = 0; + + endofrender_timer_isp->adjust(attotime::never); + endofrender_timer_tsp->adjust(attotime::never); + endofrender_timer_video->adjust(attotime::never); + yuv_timer_end->adjust(attotime::never); + + dc_state *state = machine().driver_data(); + dc_texture_ram = state->dc_texture_ram.target(); + dc_framebuffer_ram = state->dc_framebuffer_ram.target(); +} + +/* called by TIMER_ADD_PERIODIC, in driver sections (controlled by SPG, that's a PVR sub-device) */ +void powervr2_device::pvr_scanline_timer(int vpos) +{ + int vbin_line = spg_vblank_int & 0x3ff; + int vbout_line = (spg_vblank_int >> 16) & 0x3ff; + uint8_t interlace_on = ((spg_control & 0x10) >> 4); + dc_state *state = machine().driver_data(); + + vbin_line <<= interlace_on; + vbout_line <<= interlace_on; + + if(vbin_line-(1+interlace_on) == vpos) + state->m_maple->maple_hw_trigger(); + + if(vbin_line == vpos) + { + LOGIRQ("[%d] VBL IN %d\n", screen().frame_number(), screen().vpos()); + LOGIRQ(" VII %d VOI %d VI %d VO %d VS %d\n", + spg_vblank_int & 0x3ff, (spg_vblank_int >> 16) & 0x3ff, + spg_vblank & 0x3ff, (spg_vblank >> 16) & 0x3ff, (spg_load >> 16) & 0x3ff + ); + irq_cb(VBL_IN_IRQ); + } + + if(vbout_line == vpos) + { + LOGIRQ("[%d] VBL OUT %d\n", screen().frame_number(), screen().vpos()); + irq_cb(VBL_OUT_IRQ); + } +} diff --git a/src/mame/sega/powervr2.h b/src/mame/sega/powervr2.h new file mode 100644 index 00000000000..a5457206c03 --- /dev/null +++ b/src/mame/sega/powervr2.h @@ -0,0 +1,581 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +#ifndef MAME_VIDEO_POWERVR2_H +#define MAME_VIDEO_POWERVR2_H + +#pragma once + +class powervr2_device : public device_t, + public device_video_interface +{ +public: + powervr2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + auto irq_callback() { return irq_cb.bind(); } + static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } + + enum { NUM_BUFFERS = 4 }; + enum { + EOXFER_YUV_IRQ, + EOXFER_OPLST_IRQ, + EOXFER_OPMV_IRQ, + EOXFER_TRLST_IRQ, + EOXFER_TRMV_IRQ, + EOXFER_PTLST_IRQ, + VBL_IN_IRQ, + VBL_OUT_IRQ, + HBL_IN_IRQ, + EOR_VIDEO_IRQ, + EOR_TSP_IRQ, + EOR_ISP_IRQ, + DMA_PVR_IRQ, + ERR_ISP_LIMIT_IRQ, + ERR_PVRIF_ILL_ADDR_IRQ + }; + + void ta_map(address_map &map); + void pd_dma_map(address_map &map); + + struct { + uint32_t pvr_addr; + uint32_t sys_addr; + uint32_t size; + uint8_t sel; + uint8_t dir; + uint8_t flag; + uint8_t start; + } m_pvr_dma; + + static const int pvr_parconfseq[]; + static const int pvr_wordsvertex[24]; + static const int pvr_wordspolygon[24]; + int pvr_parameterconfig[128]; + uint32_t dilated0[15][1024]; + uint32_t dilated1[15][1024]; + int dilatechose[64]; + float wbuffer[480][640]; + + + // the real accumulation buffer is a 32x32x8bpp buffer into which tiles get rendered before they get copied to the framebuffer + // our implementation is not currently tile based, and thus the accumulation buffer is screen sized + std::unique_ptr fake_accumulationbuffer_bitmap; + + /* + * Per-polygon base and offset colors. These are scaled by per-vertex + * weights. + * + * These are only used if the colortype in the polygon header is 2 + * or 3. If it is 0 or 1, then each vertex's base and offset colors are + * specified completely independently of one another in the per-vertex + * parameters. + * + * The base color is combined with the texture sample (if any) according + * to one of four fixed functions. The offset color is then added to + * the combined texture sample and base color with the exception of + * alpha. + * + * poly_offs_color is not always used. Not specifying a poly_offs_color + * is equivalent to using a poly_offs_color of 0. + * + * poly_last_mode_2_base_color is used to hold the last base color + * specified using color type 2. Color type 3 will always use the last + * base color specified using color type 2. + */ + float poly_base_color[4], poly_offs_color[4], + poly_last_mode_2_base_color[4]; + + struct texinfo + { + uint32_t address = 0, vqbase = 0; + + uint32_t tsinstruction = 0; + + int textured = 0, sizex = 0, sizey = 0, stride = 0, sizes = 0, pf = 0, palette = 0, mode = 0, mipmapped = 0, blend_mode = 0, filter_mode = 0; + int coltype = 0; + + uint32_t (powervr2_device::*r)(texinfo *t, float x, float y) = nullptr; + uint32_t (*blend)(uint32_t s, uint32_t d) = nullptr; + int (*u_func)(float uv, int size) = nullptr; + int (*v_func)(float uv, int size) = nullptr; + int palbase = 0, cd = 0; + }; + + struct vert + { + float x = 0, y = 0, w = 0, u = 0, v = 0; + + // base and offset colors + float b[4] = { 0, 0, 0, 0 }, o[4] = { 0, 0, 0, 0 }; + }; + + struct strip + { + int svert = 0, evert = 0; + texinfo ti; + }; + + static const unsigned MAX_VERTS = 65536; + static const unsigned MAX_STRIPS = 65536; + + /* + * There are five polygon lists: + * + * Opaque + * Punch-through polygon + * Opaque/punch-through modifier volume + * Translucent + * Translucent modifier volume + * + * They are rendered in that order. List indices are are three bits, so + * technically there are 8 polygon lists, but only the first 5 are valid. + */ + enum { + DISPLAY_LIST_OPAQUE, + DISPLAY_LIST_OPAQUE_MOD, + DISPLAY_LIST_TRANS, + DISPLAY_LIST_TRANS_MOD, + DISPLAY_LIST_PUNCH_THROUGH, + DISPLAY_LIST_LAST, + + DISPLAY_LIST_COUNT, + + DISPLAY_LIST_NONE = -1 + }; + + struct poly_group { + strip strips[MAX_STRIPS]; + int strips_size = 0; + }; + + struct receiveddata { + vert verts[MAX_VERTS]; + struct poly_group groups[DISPLAY_LIST_COUNT]; + uint32_t ispbase = 0; + uint32_t fbwsof1 = 0; + uint32_t fbwsof2 = 0; + int busy = 0; + int valid = 0; + int verts_size = 0; + }; + + enum { + TEX_FILTER_NEAREST = 0, + TEX_FILTER_BILINEAR, + TEX_FILTER_TRILINEAR_A, + TEX_FILTER_TRILINEAR_B + }; + + int tafifo_pos, tafifo_mask, tafifo_vertexwords, tafifo_listtype; + int start_render_received; + int renderselect; + int listtype_used; + int alloc_ctrl_OPB_Mode, alloc_ctrl_PT_OPB, alloc_ctrl_TM_OPB, alloc_ctrl_T_OPB, alloc_ctrl_OM_OPB, alloc_ctrl_O_OPB; + std::unique_ptr grab; + int grabsel; + int grabsellast; + uint32_t paracontrol,paratype,endofstrip,listtype,global_paratype,parameterconfig; + uint32_t groupcontrol,groupen,striplen,userclip; + uint32_t objcontrol,shadow,volume,coltype,texture,offset_color_enable,gouraud,uv16bit; + uint32_t texturesizes,textureaddress,scanorder,pixelformat; + uint32_t blend_mode, srcselect,dstselect,fogcontrol,colorclamp, use_alpha; + uint32_t ignoretexalpha,flipuv,clampuv,filtermode,sstexture,mmdadjust,tsinstruction; + uint32_t depthcomparemode,cullingmode,zwritedisable,cachebypass,dcalcctrl,volumeinstruction,mipmapped,vqcompressed,strideselect,paletteselector; + + uint64_t *dc_texture_ram; + uint64_t *dc_framebuffer_ram; + + uint64_t *pvr2_texture_ram; + uint64_t *pvr2_framebuffer_ram; + + uint32_t debug_dip_status; + emu_timer *vbout_timer; + emu_timer *vbin_timer; + emu_timer *hbin_timer; + emu_timer *endofrender_timer_isp; + emu_timer *endofrender_timer_tsp; + emu_timer *endofrender_timer_video; + emu_timer *yuv_timer_end; + uint32_t tafifo_buff[32]; + int scanline; + int next_y; + + uint32_t id_r(); + uint32_t revision_r(); + uint32_t softreset_r(); + void softreset_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + void startrender_w(address_space &space, uint32_t data); + uint32_t param_base_r(); + void param_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t region_base_r(); + void region_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t vo_border_col_r(); + void vo_border_col_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_r_ctrl_r(); + void fb_r_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_w_ctrl_r(); + void fb_w_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_w_linestride_r(); + void fb_w_linestride_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_r_sof1_r(); + void fb_r_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_r_sof2_r(); + void fb_r_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_r_size_r(); + void fb_r_size_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_w_sof1_r(); + void fb_w_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_w_sof2_r(); + void fb_w_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_x_clip_r(); + void fb_x_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fb_y_clip_r(); + void fb_y_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t fpu_param_cfg_r(); + void fpu_param_cfg_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t isp_backgnd_t_r(); + void isp_backgnd_t_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t spg_hblank_int_r(); + void spg_hblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t spg_vblank_int_r(); + void spg_vblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t spg_control_r(); + void spg_control_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t spg_hblank_r(); + void spg_hblank_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t spg_load_r(); + void spg_load_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t spg_vblank_r(); + void spg_vblank_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t spg_width_r(); + void spg_width_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t text_control_r(); + void text_control_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t vo_control_r(); + void vo_control_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t vo_startx_r(); + void vo_startx_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t vo_starty_r(); + void vo_starty_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t pal_ram_ctrl_r(); + void pal_ram_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t spg_status_r(); + + uint32_t ta_ol_base_r(); + void ta_ol_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t ta_isp_base_r(); + void ta_isp_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t ta_ol_limit_r(); + void ta_ol_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t ta_isp_limit_r(); + void ta_isp_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t ta_next_opb_r(); + uint32_t ta_itp_current_r(); + uint32_t ta_alloc_ctrl_r(); + void ta_alloc_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t ta_list_init_r(); + void ta_list_init_w(uint32_t data); + uint32_t ta_yuv_tex_base_r(); + void ta_yuv_tex_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t ta_yuv_tex_ctrl_r(); + void ta_yuv_tex_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t ta_yuv_tex_cnt_r(); + void ta_list_cont_w(uint32_t data); + uint32_t ta_next_opb_init_r(); + void ta_next_opb_init_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + + + uint32_t fog_table_r(offs_t offset); + void fog_table_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t palette_r(offs_t offset); + void palette_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + + uint32_t sb_pdstap_r(); + void sb_pdstap_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t sb_pdstar_r(); + void sb_pdstar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t sb_pdlen_r(); + void sb_pdlen_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t sb_pddir_r(); + void sb_pddir_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t sb_pdtsel_r(); + void sb_pdtsel_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t sb_pden_r(); + void sb_pden_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t sb_pdst_r(); + void sb_pdst_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t sb_pdapro_r(); + void sb_pdapro_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + + uint32_t pvr2_ta_r(offs_t offset); + + void ta_fifo_poly_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); + void ta_fifo_yuv_w(uint8_t data); + void ta_texture_directpath0_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); + void ta_texture_directpath1_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); + + TIMER_CALLBACK_MEMBER(vbin); + TIMER_CALLBACK_MEMBER(vbout); + TIMER_CALLBACK_MEMBER(hbin); + TIMER_CALLBACK_MEMBER(yuv_convert_end); + TIMER_CALLBACK_MEMBER(endofrender_video); + TIMER_CALLBACK_MEMBER(endofrender_tsp); + TIMER_CALLBACK_MEMBER(endofrender_isp); + TIMER_CALLBACK_MEMBER(transfer_opaque_list_irq); + TIMER_CALLBACK_MEMBER(transfer_opaque_modifier_volume_list_irq); + TIMER_CALLBACK_MEMBER(transfer_translucent_list_irq); + TIMER_CALLBACK_MEMBER(transfer_translucent_modifier_volume_list_irq); + TIMER_CALLBACK_MEMBER(transfer_punch_through_list_irq); + TIMER_CALLBACK_MEMBER(pvr_dma_irq); + + void pvr_dma_execute(address_space &space); + void pvr_scanline_timer(int vpos); + uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + + typedef uint32_t(powervr2_device::*pix_sample_fn)(texinfo*,float,float,uint32_t,uint32_t); + + inline uint32_t sample_nontextured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color); + + template + inline uint32_t sample_textured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + ioport_constructor device_input_ports() const override; + +private: + devcb_write8 irq_cb; + required_ioport m_mamedebug; + + // Core registers + uint32_t softreset; + uint32_t param_base, region_base; + uint32_t vo_border_col; + uint32_t fb_r_ctrl, fb_w_ctrl, fb_w_linestride, fb_r_sof1, fb_r_sof2, fb_r_size, fb_w_sof1, fb_w_sof2, fb_x_clip, fb_y_clip; + uint32_t fpu_param_cfg; + uint32_t isp_backgnd_t; + uint32_t spg_hblank_int, spg_vblank_int, spg_control, spg_hblank, spg_load, spg_vblank, spg_width; + uint32_t vo_control, vo_startx, vo_starty; + uint32_t text_control; + uint32_t pal_ram_ctrl; + + // TA registers + uint32_t ta_ol_base, ta_ol_limit, ta_isp_base, ta_isp_limit; + uint32_t ta_next_opb, ta_itp_current, ta_alloc_ctrl, ta_next_opb_init; + uint32_t ta_yuv_tex_base, ta_yuv_tex_ctrl, ta_yuv_tex_cnt; + uint32_t ta_yuv_index; + int ta_yuv_u_ptr, ta_yuv_v_ptr; + int ta_yuv_u_size, ta_yuv_v_size; + uint8_t yuv_fifo[384]; + + // Other registers + uint32_t fog_table[0x80]; + uint32_t palette[0x400]; + + // PD DMA registers + uint32_t sb_pdstap, sb_pdstar, sb_pdlen, sb_pddir, sb_pdtsel, sb_pden, sb_pdst, sb_pdapro; + + // Timer callbacks + emu_timer *opaque_irq_timer = nullptr; + emu_timer *opaque_modifier_volume_irq_timer = nullptr; + emu_timer *translucent_irq_timer = nullptr; + emu_timer *translucent_modifier_volume_irq_timer = nullptr; + emu_timer *punch_through_irq_timer = nullptr; + emu_timer *dma_irq_timer = nullptr; + + static uint32_t (*const blend_functions[64])(uint32_t s, uint32_t d); + + static int uv_wrap(float uv, int size); + static int uv_flip(float uv, int size); + static int uv_clamp(float uv, int size); + + static inline uint32_t float_argb_to_packed_argb(float argb[4]); + static inline void packed_argb_to_float_argb(float dst[4], uint32_t in); + + static inline int32_t clamp(int32_t in, int32_t min, int32_t max); + static inline uint32_t bilinear_filter(uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, float u, float v); + static inline uint32_t bla(uint32_t c, uint32_t a); + static inline uint32_t blia(uint32_t c, uint32_t a); + static inline uint32_t blc(uint32_t c1, uint32_t c2); + static inline uint32_t blic(uint32_t c1, uint32_t c2); + static inline uint32_t bls(uint32_t c1, uint32_t c2); + static inline uint32_t bls24(uint32_t c1, uint32_t c2); + + static uint32_t bl00(uint32_t s, uint32_t d); + static uint32_t bl01(uint32_t s, uint32_t d); + static uint32_t bl02(uint32_t s, uint32_t d); + static uint32_t bl03(uint32_t s, uint32_t d); + static uint32_t bl04(uint32_t s, uint32_t d); + static uint32_t bl05(uint32_t s, uint32_t d); + static uint32_t bl06(uint32_t s, uint32_t d); + static uint32_t bl07(uint32_t s, uint32_t d); + static uint32_t bl10(uint32_t s, uint32_t d); + static uint32_t bl11(uint32_t s, uint32_t d); + static uint32_t bl12(uint32_t s, uint32_t d); + static uint32_t bl13(uint32_t s, uint32_t d); + static uint32_t bl14(uint32_t s, uint32_t d); + static uint32_t bl15(uint32_t s, uint32_t d); + static uint32_t bl16(uint32_t s, uint32_t d); + static uint32_t bl17(uint32_t s, uint32_t d); + static uint32_t bl20(uint32_t s, uint32_t d); + static uint32_t bl21(uint32_t s, uint32_t d); + static uint32_t bl22(uint32_t s, uint32_t d); + static uint32_t bl23(uint32_t s, uint32_t d); + static uint32_t bl24(uint32_t s, uint32_t d); + static uint32_t bl25(uint32_t s, uint32_t d); + static uint32_t bl26(uint32_t s, uint32_t d); + static uint32_t bl27(uint32_t s, uint32_t d); + static uint32_t bl30(uint32_t s, uint32_t d); + static uint32_t bl31(uint32_t s, uint32_t d); + static uint32_t bl32(uint32_t s, uint32_t d); + static uint32_t bl33(uint32_t s, uint32_t d); + static uint32_t bl34(uint32_t s, uint32_t d); + static uint32_t bl35(uint32_t s, uint32_t d); + static uint32_t bl36(uint32_t s, uint32_t d); + static uint32_t bl37(uint32_t s, uint32_t d); + static uint32_t bl40(uint32_t s, uint32_t d); + static uint32_t bl41(uint32_t s, uint32_t d); + static uint32_t bl42(uint32_t s, uint32_t d); + static uint32_t bl43(uint32_t s, uint32_t d); + static uint32_t bl44(uint32_t s, uint32_t d); + static uint32_t bl45(uint32_t s, uint32_t d); + static uint32_t bl46(uint32_t s, uint32_t d); + static uint32_t bl47(uint32_t s, uint32_t d); + static uint32_t bl50(uint32_t s, uint32_t d); + static uint32_t bl51(uint32_t s, uint32_t d); + static uint32_t bl52(uint32_t s, uint32_t d); + static uint32_t bl53(uint32_t s, uint32_t d); + static uint32_t bl54(uint32_t s, uint32_t d); + static uint32_t bl55(uint32_t s, uint32_t d); + static uint32_t bl56(uint32_t s, uint32_t d); + static uint32_t bl57(uint32_t s, uint32_t d); + static uint32_t bl60(uint32_t s, uint32_t d); + static uint32_t bl61(uint32_t s, uint32_t d); + static uint32_t bl62(uint32_t s, uint32_t d); + static uint32_t bl63(uint32_t s, uint32_t d); + static uint32_t bl64(uint32_t s, uint32_t d); + static uint32_t bl65(uint32_t s, uint32_t d); + static uint32_t bl66(uint32_t s, uint32_t d); + static uint32_t bl67(uint32_t s, uint32_t d); + static uint32_t bl70(uint32_t s, uint32_t d); + static uint32_t bl71(uint32_t s, uint32_t d); + static uint32_t bl72(uint32_t s, uint32_t d); + static uint32_t bl73(uint32_t s, uint32_t d); + static uint32_t bl74(uint32_t s, uint32_t d); + static uint32_t bl75(uint32_t s, uint32_t d); + static uint32_t bl76(uint32_t s, uint32_t d); + static uint32_t bl77(uint32_t s, uint32_t d); + static inline uint32_t cv_1555(uint16_t c); + static inline uint32_t cv_1555z(uint16_t c); + static inline uint32_t cv_565(uint16_t c); + static inline uint32_t cv_565z(uint16_t c); + static inline uint32_t cv_4444(uint16_t c); + static inline uint32_t cv_4444z(uint16_t c); + static inline uint32_t cv_yuv(uint16_t c1, uint16_t c2, int x); + uint32_t tex_r_yuv_n(texinfo *t, float x, float y); + uint32_t tex_r_yuv_tw(texinfo *t, float x, float y); +// uint32_t tex_r_yuv_vq(texinfo *t, float x, float y); + uint32_t tex_r_1555_n(texinfo *t, float x, float y); + uint32_t tex_r_1555_tw(texinfo *t, float x, float y); + uint32_t tex_r_1555_vq(texinfo *t, float x, float y); + uint32_t tex_r_565_n(texinfo *t, float x, float y); + uint32_t tex_r_565_tw(texinfo *t, float x, float y); + uint32_t tex_r_565_vq(texinfo *t, float x, float y); + uint32_t tex_r_4444_n(texinfo *t, float x, float y); + uint32_t tex_r_4444_tw(texinfo *t, float x, float y); + uint32_t tex_r_4444_vq(texinfo *t, float x, float y); + uint32_t tex_r_p4_1555_tw(texinfo *t, float x, float y); + uint32_t tex_r_p4_1555_vq(texinfo *t, float x, float y); + uint32_t tex_r_p4_565_tw(texinfo *t, float x, float y); + uint32_t tex_r_p4_565_vq(texinfo *t, float x, float y); + uint32_t tex_r_p4_4444_tw(texinfo *t, float x, float y); + uint32_t tex_r_p4_4444_vq(texinfo *t, float x, float y); + uint32_t tex_r_p4_8888_tw(texinfo *t, float x, float y); + uint32_t tex_r_p4_8888_vq(texinfo *t, float x, float y); + uint32_t tex_r_p8_1555_tw(texinfo *t, float x, float y); + uint32_t tex_r_p8_1555_vq(texinfo *t, float x, float y); + uint32_t tex_r_p8_565_tw(texinfo *t, float x, float y); + uint32_t tex_r_p8_565_vq(texinfo *t, float x, float y); + uint32_t tex_r_p8_4444_tw(texinfo *t, float x, float y); + uint32_t tex_r_p8_4444_vq(texinfo *t, float x, float y); + uint32_t tex_r_p8_8888_tw(texinfo *t, float x, float y); + uint32_t tex_r_p8_8888_vq(texinfo *t, float x, float y); + + uint32_t tex_r_default(texinfo *t, float x, float y); + void tex_get_info(texinfo *t); + + template + inline void render_hline(bitmap_rgb32 &bitmap, texinfo *ti, + int y, float xl, float xr, + float ul, float ur, float vl, float vr, + float wl, float wr, + float const bl[4], float const br[4], + float const offl[4], float const offr[4]); + + template + inline void render_span(bitmap_rgb32 &bitmap, texinfo *ti, + float y0, float y1, + float xl, float xr, + float ul, float ur, + float vl, float vr, + float wl, float wr, + float const bl[4], float const br[4], + float const offl[4], float const offr[4], + float dxldy, float dxrdy, + float duldy, float durdy, + float dvldy, float dvrdy, + float dwldy, float dwrdy, + float const dbldy[4], float const dbrdy[4], + float const doldy[4], float const dordy[4]); + + template + inline void render_tri_sorted(bitmap_rgb32 &bitmap, texinfo *ti, + const vert *v0, + const vert *v1, const vert *v2); + + template + void render_tri(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v); + + template + void render_group_to_accumulation_buffer(bitmap_rgb32 &bitmap, const rectangle &cliprect); + + void sort_vertices(const vert *v, int *i0, int *i1, int *i2); + void render_to_accumulation_buffer(bitmap_rgb32 &bitmap, const rectangle &cliprect); + void pvr_accumulationbuffer_to_framebuffer(address_space &space, int x, int y); + void pvr_drawframebuffer(bitmap_rgb32 &bitmap,const rectangle &cliprect); + static uint32_t dilate0(uint32_t value,int bits); + static uint32_t dilate1(uint32_t value,int bits); + void computedilated(); + void pvr_build_parameterconfig(); + void process_ta_fifo(); + void update_screen_format(); + + void fb_convert_0555krgb_to_555rgb(address_space &space, int x, int y); + void fb_convert_0555krgb_to_565rgb(address_space &space, int x, int y); + void fb_convert_0555krgb_to_888rgb24(address_space &space, int x, int y); + void fb_convert_0555krgb_to_888rgb32(address_space &space, int x, int y); + + void fb_convert_0565rgb_to_555rgb(address_space &space, int x, int y); + void fb_convert_0565rgb_to_565rgb(address_space &space, int x, int y); + void fb_convert_0565rgb_to_888rgb24(address_space &space, int x, int y); + void fb_convert_0565rgb_to_888rgb32(address_space &space, int x, int y); + + void fb_convert_1555argb_to_555rgb(address_space &space, int x, int y); + void fb_convert_1555argb_to_565rgb(address_space &space, int x, int y); + void fb_convert_1555argb_to_888rgb24(address_space &space, int x, int y); + void fb_convert_1555argb_to_888rgb32(address_space &space, int x, int y); + + void fb_convert_888rgb_to_555rgb(address_space &space, int x, int y); + void fb_convert_888rgb_to_565rgb(address_space &space, int x, int y); + void fb_convert_888rgb_to_888rgb24(address_space &space, int x, int y); + void fb_convert_888rgb_to_888rgb32(address_space &space, int x, int y); + + void fb_convert_8888argb_to_555rgb(address_space &space, int x, int y); + void fb_convert_8888argb_to_565rgb(address_space &space, int x, int y); + void fb_convert_8888argb_to_888rgb24(address_space &space, int x, int y); + void fb_convert_8888argb_to_888rgb32(address_space &space, int x, int y); + +}; + +DECLARE_DEVICE_TYPE(POWERVR2, powervr2_device) + +#endif // MAME_VIDEO_POWERVR2_H diff --git a/src/mame/sega/sega_beena.cpp b/src/mame/sega/sega_beena.cpp new file mode 100644 index 00000000000..02cef4abd52 --- /dev/null +++ b/src/mame/sega/sega_beena.cpp @@ -0,0 +1,198 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/****************************************************************************** + + Sega Beena + + apbeena.cpp + + Skeleton driver for the Sega Advanced Pico BEENA + + H/W is custom Sega SoC with ARM7TDMI core at 81 MHz. + + TODO: + Everything! + Needs the internal BIOS dumped. + Component list / PCB diagram + + Cartridge ROM has 'edinburgh' in the header, maybe a system codename? + ROM is also full of OGG files containing the string 'Encoded with Speex speex-1.0.4' + as well as .mid files for music. + + Cartridges pinout: + + Glob down, PCB cut corner at upper right + Top row of pins A25 on left to A1 on right. + Bottom row of pins B25 on left to B1 on right. + + A1 /CE (tied high with resistor) + A2 D11 + A3 D3 + A4 D10 + A5 D2 + A6 D9 + A7 D1 + A8 D8 + A9 D0 + A10 /OE + A11 N/C + A12 A0 + A13 A1 + A14 A2 + A15 A3 + A16 A4 + A17 A5 + A18 A6 + A19 A7 + A20 A17 + A21 A18 + A22 N/C + A23 VCC + A24 N/C + A25 GND + + B1 N/C + B2 D4 + B3 D12 + B4 D5 + B5 D13 + B6 D6 + B7 D14 + B8 D7 + B9 D15 + B10 A16 + B11 A15 + B12 A14 + B13 A13 + B14 A12 + B15 A11 + B16 A10 + B17 A9 + B18 A8 + B19 A19 + B20 A20 + B21 N/C + B22 A21 + B23 VCC + B24 N/C + B25 GND + +*******************************************************************************/ + +#include "emu.h" + +#include "bus/generic/slot.h" +#include "bus/generic/carts.h" +#include "cpu/arm7/arm7.h" + +#include "softlist_dev.h" +#include "speaker.h" +#include "screen.h" + + +class sega_beena_state : public driver_device +{ +public: + sega_beena_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "arm7") + , m_cart(*this, "cartslot") + , m_cart_region(nullptr) + , m_bank(*this, "cartbank") + { } + + void sega_beena(machine_config &config); + +private: + virtual void machine_start() override; + virtual void machine_reset() override; + + uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + + DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load); + + void beena_arm7_map(address_map &map); + + required_device m_maincpu; + optional_device m_cart; + memory_region *m_cart_region; + optional_memory_bank m_bank; +}; + +void sega_beena_state::beena_arm7_map(address_map &map) +{ + map(0x00000000, 0x000001ff).rom().bankr("cartbank"); + map(0x80000000, 0x807fffff).rom().bankr("cartbank"); +} + +void sega_beena_state::machine_start() +{ + // if there's a cart, override the standard mapping + if (m_cart && m_cart->exists()) + { + std::string region_tag; + m_cart_region = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); + + m_bank->configure_entries(0, (m_cart_region->bytes() + 0x7fffff) / 0x800000, m_cart_region->base(), 0x800000); + } + else + m_bank->configure_entries(0, 1, memregion("bios")->base(), 0x800000); + + m_bank->set_entry(0); +} + +void sega_beena_state::machine_reset() +{ +} + +DEVICE_IMAGE_LOAD_MEMBER(sega_beena_state::cart_load) +{ + uint32_t size = m_cart->common_get_size("rom"); + + m_cart->rom_alloc(size, GENERIC_ROM16_WIDTH, ENDIANNESS_LITTLE); + m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom"); + + + return image_init_result::PASS; +} + +static INPUT_PORTS_START( sega_beena ) +INPUT_PORTS_END + + +uint32_t sega_beena_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + return 0; +} + +void sega_beena_state::sega_beena(machine_config &config) +{ + ARM7_BE(config, m_maincpu, 81'000'000); + m_maincpu->set_addrmap(AS_PROGRAM, &sega_beena_state::beena_arm7_map); + + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); + screen.set_size(640, 480); + screen.set_visarea(0, 640-1, 0, 480-1); + screen.set_screen_update(FUNC(sega_beena_state::screen_update)); + + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "sega_beena_cart"); + m_cart->set_width(GENERIC_ROM16_WIDTH); + m_cart->set_device_load(FUNC(sega_beena_state::cart_load)); + m_cart->set_must_be_loaded(true); + + SOFTWARE_LIST(config, "cart_list").set_original("sega_beena_cart"); +} + +ROM_START( beena ) + ROM_REGION32_BE( 0x80000, "bios", 0 ) // SoC internal BIOS + ROM_LOAD16_WORD_SWAP( "beenabios.bin", 0x000000, 0x080000, NO_DUMP ) +ROM_END + + +// year, name, parent, compat, machine, input, class, init, company, fullname, flags +CONS( 2009, beena, 0, 0, sega_beena, sega_beena, sega_beena_state, empty_init, "Sega", "Advanced Pico BEENA", MACHINE_IS_SKELETON ) diff --git a/src/mame/sega/sega_sawatte.cpp b/src/mame/sega/sega_sawatte.cpp new file mode 100644 index 00000000000..9e6cde13b8c --- /dev/null +++ b/src/mame/sega/sega_sawatte.cpp @@ -0,0 +1,250 @@ +// license:BSD-3-Clause +// copyright-holders:AJR + +/* Sega Sawatte / S-Pico + +a sound-only Pico type system (one of the boards even says S-PICO) + +CPU is unknown (MCU with internal ROM?) cartridge dumps contain 6502 code +and have been tested as working using a flash cart. + + +images supplied by Team Europe + +http://mamedev.emulab.it/haze/reference/sawatte/cartridge_pcb_front.jpg +http://mamedev.emulab.it/haze/reference/sawatte/cartridge_pcb_back.jpg + +http://mamedev.emulab.it/haze/reference/sawatte/PCB_Front.jpg +http://mamedev.emulab.it/haze/reference/sawatte/PCB_Back.jpg + +http://mamedev.emulab.it/haze/reference/sawatte/Console_Front.JPG +http://mamedev.emulab.it/haze/reference/sawatte/Console_Back.JPG + +http://mamedev.emulab.it/haze/reference/sawatte/cartridge_example.jpg + +*/ + +#include "emu.h" +#include "bus/generic/carts.h" +#include "bus/generic/slot.h" +#include "cpu/m6502/m6502.h" +#include "softlist_dev.h" + + +class sawatte_state : public driver_device +{ +public: + sawatte_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_cartslot(*this, "cartslot") + , m_soundram(*this, "soundram") + , m_irq3_timer(nullptr) + , m_irq4_timer(nullptr) + , m_data_bank(0) + , m_prog_bank(0) + , m_irq_status(0) + , m_irq_mask(0) + { } + + void sawatte(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + TIMER_CALLBACK_MEMBER(irq3_timer); + TIMER_CALLBACK_MEMBER(irq4_timer); + + void bank08_w(u8 data); + void bank09_w(u8 data); + void bank0a_w(u8 data); + u8 irq_status_r(); + void irq_mask_w(u8 data); + void irq3_timer_w(u8 data); + void irq4_timer_w(u8 data); + u8 fixed_r(offs_t offset); + u8 data_bank_r(offs_t offset); + u8 prog_bank_r(offs_t offset); + + void mem_map(address_map &map); + + required_device m_maincpu; + required_device m_cartslot; + required_shared_ptr m_soundram; + + emu_timer *m_irq3_timer; + emu_timer *m_irq4_timer; + + u16 m_data_bank; + u8 m_prog_bank; + u8 m_irq_status; + u8 m_irq_mask; +}; + +void sawatte_state::machine_start() +{ + m_irq3_timer = timer_alloc(FUNC(sawatte_state::irq3_timer), this); + m_irq4_timer = timer_alloc(FUNC(sawatte_state::irq4_timer), this); + + save_item(NAME(m_data_bank)); + save_item(NAME(m_prog_bank)); + save_item(NAME(m_irq_status)); + save_item(NAME(m_irq_mask)); +} + +void sawatte_state::machine_reset() +{ + m_data_bank = 0; + m_prog_bank = 0; + + m_irq_status = 0; + m_irq_mask = 0; + m_maincpu->set_input_line(m6502_device::IRQ_LINE, CLEAR_LINE); + + m_irq3_timer->adjust(attotime::never); + m_irq4_timer->adjust(attotime::never); +} + +TIMER_CALLBACK_MEMBER(sawatte_state::irq3_timer) +{ + if (BIT(m_irq_mask, 3)) + { + m_irq_status |= 0x08; + m_maincpu->set_input_line(m6502_device::IRQ_LINE, ASSERT_LINE); + } +} + +TIMER_CALLBACK_MEMBER(sawatte_state::irq4_timer) +{ + if (BIT(m_irq_mask, 4)) + { + m_irq_status |= 0x10; + m_maincpu->set_input_line(m6502_device::IRQ_LINE, ASSERT_LINE); + } +} + + +void sawatte_state::bank08_w(u8 data) +{ + m_data_bank = (m_data_bank & 0xff00) | data; +} + +void sawatte_state::bank09_w(u8 data) +{ + m_data_bank = u16(data) << 8 | (m_data_bank & 0x00ff); +} + +void sawatte_state::bank0a_w(u8 data) +{ + m_prog_bank = data; +} + +u8 sawatte_state::irq_status_r() +{ + return m_irq_status; +} + +void sawatte_state::irq_mask_w(u8 data) +{ + m_irq_mask = data; + if (m_irq_status != 0) + { + m_irq_status &= data; + if (m_irq_status == 0) + m_maincpu->set_input_line(m6502_device::IRQ_LINE, CLEAR_LINE); + } +} + +void sawatte_state::irq3_timer_w(u8 data) +{ + if (data == 0) + m_irq3_timer->adjust(attotime::never); + else + { + attotime period = attotime::from_hz(10'000); // probably incorrect + m_irq3_timer->adjust(period, 0, period); + } +} + +void sawatte_state::irq4_timer_w(u8 data) +{ + if (!BIT(data, 0)) + m_irq4_timer->adjust(attotime::never); + else + { + attotime period = attotime::from_hz(8'000); // probably incorrect + m_irq4_timer->adjust(period, 0, period); + } +} + +u8 sawatte_state::fixed_r(offs_t offset) +{ + return m_cartslot->read_rom(offset + 0x200); +} + +u8 sawatte_state::data_bank_r(offs_t offset) +{ + return m_cartslot->read_rom(offset | offs_t(m_data_bank) << 11); +} + +u8 sawatte_state::prog_bank_r(offs_t offset) +{ + return m_cartslot->read_rom(offset | offs_t(m_prog_bank) << 12); +} + + +void sawatte_state::mem_map(address_map &map) +{ + map.global_mask(0x1fff); + map(0x0000, 0x0000).nopr(); + map(0x0008, 0x0008).w(FUNC(sawatte_state::bank08_w)); + map(0x0009, 0x0009).w(FUNC(sawatte_state::bank09_w)); + map(0x000a, 0x000a).w(FUNC(sawatte_state::bank0a_w)); + map(0x0011, 0x0011).portr("IN1"); + map(0x0012, 0x0012).portr("IN2"); + map(0x0016, 0x0016).nopr(); + map(0x0017, 0x0017).r(FUNC(sawatte_state::irq_status_r)); + map(0x0020, 0x0020).nopw(); // matrix scanning? + map(0x0022, 0x0022).nopw(); // matrix scanning? + map(0x0026, 0x0026).w(FUNC(sawatte_state::irq3_timer_w)); + map(0x0027, 0x0027).w(FUNC(sawatte_state::irq_mask_w)); + map(0x002f, 0x002f).w(FUNC(sawatte_state::irq4_timer_w)); + map(0x0060, 0x007f).ram(); + map(0x0080, 0x009f).ram().share("soundram"); + map(0x00a0, 0x01ff).ram(); // might not all exist + map(0x0200, 0x07ff).r(FUNC(sawatte_state::fixed_r)); + map(0x0800, 0x0fff).r(FUNC(sawatte_state::data_bank_r)); + map(0x1000, 0x1fff).r(FUNC(sawatte_state::prog_bank_r)); +} + + +static INPUT_PORTS_START( sawatte ) + PORT_START("IN1") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON2) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON3) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_BUTTON4) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON5) + + PORT_START("IN2") + PORT_BIT(0x1f, IP_ACTIVE_HIGH, IPT_UNKNOWN) // matrix inputs? + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON6) +INPUT_PORTS_END + + +void sawatte_state::sawatte(machine_config &config) +{ + M6502(config, m_maincpu, 4'000'000); // could be some stock SoC, type and clock unknown + m_maincpu->set_addrmap(AS_PROGRAM, &sawatte_state::mem_map); + + GENERIC_CARTSLOT(config, m_cartslot, generic_plain_slot, "sawatte_cart"); + SOFTWARE_LIST(config, "cart_list").set_original("sawatte"); +} + +ROM_START( sawatte ) +ROM_END + + +CONS( 1996?, sawatte, 0, 0, sawatte, sawatte, sawatte_state, empty_init, "Sega", "Sawatte", MACHINE_IS_SKELETON ) diff --git a/src/mame/sega/segae.cpp b/src/mame/sega/segae.cpp index 2be20a5cc9f..abe3d0d6c32 100644 --- a/src/mame/sega/segae.cpp +++ b/src/mame/sega/segae.cpp @@ -301,7 +301,7 @@ GND 8A 8B GND #include "machine/adc0804.h" #include "machine/i8255.h" #include "machine/rescap.h" -#include "segacrp2_device.h" +#include "machine/segacrp2_device.h" #include "machine/upd4701.h" #include "video/315_5124.h" #include "speaker.h" diff --git a/src/mame/sega/segag80r.cpp b/src/mame/sega/segag80r.cpp index bb542d23a8d..13a2197bbbc 100644 --- a/src/mame/sega/segag80r.cpp +++ b/src/mame/sega/segag80r.cpp @@ -110,8 +110,7 @@ #include "segag80r.h" #include "segag80_m.h" -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "cpu/z80/z80.h" #include "machine/i8255.h" #include "speaker.h" diff --git a/src/mame/sega/segapico.cpp b/src/mame/sega/segapico.cpp new file mode 100644 index 00000000000..5b13193333a --- /dev/null +++ b/src/mame/sega/segapico.cpp @@ -0,0 +1,638 @@ +// license:BSD-3-Clause +// copyright-holders:Emmanuel Vadot + +/****************************************** PICO emulation ****************************************/ + +/* todo, make this more independent of the Genesis emulation, it's really only the same CPU + VDP + and doesn't need to be connected to the Genesis at all. + + sound is the 315-5641 / D77591, should be compatible with the 7759? but probably wants us to maintain + an external buffer of at least 0x40 bytes and feed it on a timer in sync with the timer in the chip? + + currently no way to select (or display) the story book area of the games? (will require layout and + external artwork) + +*/ + + +/* + +Pico mainboard (PAL version) + ++---+ +-------------------------------------------------------------------------+ +| | | +-+ | +| | | +--+ |B| +-+ | +| | | |A3| +-+ | | | +| +------------------------------+ +--+ |C| +-| +| | | | | +| GCMK-C2X +-+ | --> PEN +| +-----+ +--+ +-| +| | | |A3| +--------+ | +| | A1 | +--+ | | +---------+ | +| SEGA | | | A2 | |HM53861J | | +| 1994 837-10846 +-----+ | | | | | +| IAC MAIN PAL +--------+ +---------+ | +| MADE IN JAPAN +----+ | +| VA0 +----------+ |XTAL| +--+ +| | SEGA | +---------+ | | | <-- VCC IN +| | 315-5640 | |MC68HC000| |53.2| +--+ +| | 9434 W51 | |FN8-A | +----+ |00 | +----------+ | +| | | | | | | +----+ | SEGA | | +| | | | 2B89N | | | | 315-5313A| | +| | | |S0AH9425A| | A4 | | F1001 | +--| +| +----------+ +---------+ | | | | | | +| | | |9428 LAGG | | --> VIDEO OUT +| | | | | | | +| +----+ +----------+ +--| +| | +| +----------------------------+ | +| ||||||CARTRIDGE CONNECTOR||||| | +| +----------------------------+ | +| | ++------------------------------------------------------------------------------------------------------------+ + +A1 = SEGA / 315-5641 / D77591 / 9442CA010 +A2 = SEGA / 315-5769 U13 / 9451MD020 +A3 = BA10324AF +A4 = MALAYSIA 9336 / 651632DFP-15 / 0000988S +B = 4K16 / HC00 +C = MB3514 / 9325 M36 + + +315-5640 - touchpad controller? +315-5313A - VDP +315-5641 - PCM chip + + +*/ + +/* + Pico Implementation By ElBarto (Emmanuel Vadot, elbarto@megadrive.org) + Still missing the PCM custom chip + Some game will not boot due to this + + Pico Info from Notaz (http://notaz.gp2x.de/docs/picodoc.txt) + + addr acc description +-------+-----+------------ +800001 byte Version register. + ?vv? ????, where v can be: + 00 - hardware is for Japan + 01 - European version + 10 - USA version + 11 - ? +800003 byte Buttons, 0 for pressed, 1 for released: + bit 0: UP (white) + bit 1: DOWN (orange) + bit 2: LEFT (blue) + bit 3: RIGHT (green) + bit 4: red button + bit 5: unused? + bit 6: unused? + bit 7: pen button +800005 byte Most significant byte of pen x coordinate. +800007 byte Least significant byte of pen x coordinate. +800009 byte Most significant byte of pen y coordinate. +80000b byte Least significant byte of pen y coordinate. +80000d byte Page register. One bit means one uncovered page sensor. + 00 - storyware closed + 01, 03, 07, 0f, 1f, 3f - pages 1-6 + either page 5 or page 6 is often unused. +800010 word PCM data register. + r/w read returns free bytes left in PCM FIFO buffer + writes write data to buffer. +800012 word PCM control register. + r/w For writes, it has following possible meanings: + ?p?? ???? ???? ?rrr + p - set to enable playback? + r - sample rate / PCM data type? + 0: 8kHz 4bit ADPCM? + 1-7: 16kHz variants? + For reads, if bit 15 is cleared, it means PCM is 'busy' or + something like that, as games sometimes wait for it to become 1. +800019 byte Games write 'S' +80001b byte Games write 'E' +80001d byte Games write 'G' +80001f byte Games write 'A' + +*/ + +#include "emu.h" +#include "mdconsole.h" +#include "sound/315-5641.h" +#include "bus/megadrive/rom.h" +#include "softlist.h" + + +namespace { + +#define PICO_PENX 1 +#define PICO_PENY 2 + +class pico_base_state : public md_cons_state +{ +public: + pico_base_state(const machine_config &mconfig, device_type type, const char *tag) : + md_cons_state(mconfig, type, tag), + m_sega_315_5641_pcm(*this, "315_5641"), + m_io_page(*this, "PAGE"), + m_io_pad(*this, "PAD"), + m_io_penx(*this, "PENX"), + m_io_peny(*this, "PENY") + { } + + void init_pico(); + void init_picou(); + void init_picoj(); + +protected: + optional_device m_sega_315_5641_pcm; + + required_ioport m_io_page; + required_ioport m_io_pad; + required_ioport m_io_penx; + required_ioport m_io_peny; + + uint8_t m_page_register; + + uint16_t pico_read_penpos(int pen); + uint16_t pico_68k_io_read(offs_t offset); + void pico_68k_io_write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + DECLARE_WRITE_LINE_MEMBER(sound_cause_irq); + + void pico_mem(address_map &map); +}; + +class pico_state : public pico_base_state +{ +public: + pico_state(const machine_config &mconfig, device_type type, const char *tag) : + pico_base_state(mconfig, type, tag), + m_picocart(*this, "picoslot") + { } + + void pico(machine_config &config); + void picopal(machine_config &config); + +private: + required_device m_picocart; + DECLARE_MACHINE_START(pico); +}; + + + +uint16_t pico_base_state::pico_read_penpos(int pen) +{ + uint16_t penpos = 0; + + switch (pen) + { + case PICO_PENX: + penpos = m_io_penx->read(); + penpos |= 0x6; + penpos = penpos * 320 / 255; + penpos += 0x3d; + break; + case PICO_PENY: + penpos = m_io_peny->read(); + penpos |= 0x6; + penpos = penpos * 251 / 255; + penpos += 0x1fc; + break; + } + + return penpos; +} + +uint16_t pico_base_state::pico_68k_io_read(offs_t offset) +{ + uint8_t retdata = 0; + + switch (offset) + { + case 0: /* Version register ?XX?????? where XX is 00 for japan, 01 for europe and 10 for USA*/ + retdata = m_version_hi_nibble; + break; + case 1: + retdata = m_io_pad->read(); + break; + + /* + Still notes from notaz for the pen : + + The pen can be used to 'draw' either on the drawing pad or on the storyware + itself. Both storyware and drawing pad are mapped on single virtual plane, where + coordinates range: + + x: 0x03c - 0x17c + y: 0x1fc - 0x2f7 (drawing pad) + 0x2f8 - 0x3f3 (storyware) + */ + case 2: + retdata = pico_read_penpos(PICO_PENX) >> 8; + break; + case 3: + retdata = pico_read_penpos(PICO_PENX) & 0x00ff; + break; + case 4: + retdata = pico_read_penpos(PICO_PENY) >> 8; + break; + case 5: + retdata = pico_read_penpos(PICO_PENY) & 0x00ff; + break; + case 6: + /* Page register : + 00 - storyware closed + 01, 03, 07, 0f, 1f, 3f - pages 1-6 + either page 5 or page 6 is often unused. + */ + { + uint8_t tmp = m_io_page->read(); + if (tmp == 2 && m_page_register != 0x3f) + { + m_page_register <<= 1; + m_page_register |= 1; + } + if (tmp == 1 && m_page_register != 0x00) + m_page_register >>= 1; + retdata = m_page_register; + break; + } + + + + case 8: // toy story 2 checks this for 0x3f (is that 'empty'?) + /* Returns free bytes left in the PCM FIFO buffer */ + retdata = m_sega_315_5641_pcm->get_fifo_space(); + break; + case 9: + /* + For reads, if bit 15 is cleared, it means PCM is 'busy' or + something like that, as games sometimes wait for it to become 1. + */ + // return (m_upd7759->busy_r()^1) << 15; + // The BUSY bit stays 1 as long as some PCM sound is playing. + // SMPS drivers check 800012 [byte] and clear the "prevent music PCM" byte when the READY bit gets set. + // If this is done incorrectly, the voices in Sonic Gameworld (J) are muted by the music's PCM drums. + return m_sega_315_5641_pcm->busy_r() << 15; + + + case 7: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + logerror("pico_68k_io_read %d\n", offset); + + } + + return retdata | retdata << 8; +} + + +WRITE_LINE_MEMBER(pico_base_state::sound_cause_irq) +{ +// printf("sound irq\n"); + /* sega_315_5641_pcm callback */ + m_maincpu->set_input_line(3, HOLD_LINE); +} + +void pico_base_state::pico_68k_io_write(offs_t offset, uint16_t data, uint16_t mem_mask) +{ +// printf("pico_68k_io_write %04x %04x %04x\n", offset*2, data, mem_mask); + + switch (offset) + { + case 0x10/2: + if (mem_mask & 0xFF00) + m_sega_315_5641_pcm->port_w((data >> 8) & 0xFF); + if (mem_mask & 0x00FF) + m_sega_315_5641_pcm->port_w((data >> 0) & 0xFF); + break; + case 0x12/2: // guess + // Note about uPD7759 lines: + // reset line: 1 - normal, 1->0 - reset chip, 0 - playback disabled + // start line: 0->1 - start playback + if (mem_mask & 0xFF00) + { + // I assume that: + // value 8000 resets the FIFO? (always used with low reset line) + // value 0800 maps to the uPD7759's reset line (0 = reset, 1 = normal) + // value 4000 maps to the uPD7759's start line (0->1 = start) + m_sega_315_5641_pcm->fifo_reset_w(BIT(data, 15)); + m_sega_315_5641_pcm->reset_w(BIT(data, 11)); + m_sega_315_5641_pcm->start_w(BIT(data, 14)); + } + + + /*m_sega_315_5641_pcm->reset_w(0); + m_sega_315_5641_pcm->start_w(0); + m_sega_315_5641_pcm->reset_w(1); + m_sega_315_5641_pcm->start_w(1); + + if (ACCESSING_BITS_0_7) m_sega_315_5641_pcm->port_w(space,0,data&0xff); + if (ACCESSING_BITS_8_15) m_sega_315_5641_pcm->port_w(space,0,(data>>8)&0xff);*/ + + break; + } +} + +void pico_base_state::pico_mem(address_map &map) +{ + map(0x000000, 0x3fffff).rom(); + map(0x800000, 0x80001f).rw(FUNC(pico_base_state::pico_68k_io_read), FUNC(pico_base_state::pico_68k_io_write)); + map(0xc00000, 0xc0001f).rw("gen_vdp", FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); + map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000); +} + + +static INPUT_PORTS_START( pico ) + PORT_START("PAD") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("Red Button") + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("Pen Button") + + PORT_START("PAGE") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("Increment Page") + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("Decrement Page") + + PORT_START("PENX") + PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_NAME("PEN X") + + PORT_START("PENY") + PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0,255 ) PORT_PLAYER(1) PORT_NAME("PEN Y") +INPUT_PORTS_END + + +static void pico_cart(device_slot_interface &device) +{ + device.option_add_internal("rom", MD_STD_ROM); + device.option_add_internal("rom_sram", MD_ROM_SRAM); // not sure these are needed... + device.option_add_internal("rom_sramsafe", MD_ROM_SRAM); // not sure these are needed... +} + +MACHINE_START_MEMBER(pico_state,pico) +{ + m_maincpu->space(AS_PROGRAM).install_read_handler(0x000000, 0x7fffff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read))); + m_maincpu->space(AS_PROGRAM).install_write_handler(0x000000, 0x7fffff, write16s_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write))); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa13000, 0xa130ff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read_a13)), write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_a13))); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa15000, 0xa150ff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read_a15)), write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_a15))); + m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14000, 0xa14003, write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_tmss_bank))); + + m_vdp->stop_timers(); +} + +void pico_state::pico(machine_config &config) +{ + md_ntsc(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &pico_state::pico_mem); + + config.device_remove("genesis_snd_z80"); + config.device_remove("ymsnd"); + + MCFG_MACHINE_START_OVERRIDE( pico_state, pico ) + + PICO_CART_SLOT(config, m_picocart, pico_cart, nullptr).set_must_be_loaded(true); + SOFTWARE_LIST(config, "cart_list").set_original("pico"); + + SEGA_315_5641_PCM(config, m_sega_315_5641_pcm, upd7759_device::STANDARD_CLOCK*2); + m_sega_315_5641_pcm->fifo_cb().set(FUNC(pico_state::sound_cause_irq)); + m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "lspeaker", 0.16); + m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "rspeaker", 0.16); +} + +void pico_state::picopal(machine_config &config) +{ + md_pal(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &pico_state::pico_mem); + + config.device_remove("genesis_snd_z80"); + config.device_remove("ymsnd"); + + MCFG_MACHINE_START_OVERRIDE( pico_state, pico ) + + PICO_CART_SLOT(config, m_picocart, pico_cart, nullptr).set_must_be_loaded(true); + SOFTWARE_LIST(config, "cart_list").set_original("pico"); + + SEGA_315_5641_PCM(config, m_sega_315_5641_pcm, upd7759_device::STANDARD_CLOCK*2); + m_sega_315_5641_pcm->fifo_cb().set(FUNC(pico_state::sound_cause_irq)); + m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "lspeaker", 0.16); + m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "rspeaker", 0.16); +} + + + +ROM_START( pico ) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START( picou ) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +ROM_START( picoj ) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + + +void pico_base_state::init_pico() +{ + init_megadrie(); + init_mess_md_common(); + + m_version_hi_nibble = 0x60; // Export PAL +} + +void pico_base_state::init_picou() +{ + init_megadriv(); + init_mess_md_common(); + + m_version_hi_nibble = 0x40; // Export NTSC +} + +void pico_base_state::init_picoj() +{ + init_megadrij(); + init_mess_md_common(); + + m_version_hi_nibble = 0x00; // JPN NTSC +} + + +/* + +This looks a lot like a Pico with extra sound hardware... + YMZ263B is the basis of a Sound Blaster Clone + YMF262-M is the OPL3 + +YAMAHA - MIXT BOOK PLAYER COPERA +MMG-1 + + + +-------------+ + | | + |------+ | + | | | + MIDI OUT <-- | | + | | | + |------+ | + | | +------------------------------------------------------------------------------------------------------+ + |------+ | | +--+ | + | | | | |YM| | + MIDI IN <-- | | | |7 | | + | | | | |12| +---------+ | + |------+ +--+ | +------+ |8B| | YAMAHA | | + | |||| | | +--+ | YMZ263B | | + +---------||--+ | +--------+ | | | + || | |YM7 128B| +---------+ +---+ | + || | +--------+ |YMF| | + +---------||----------+ |262| | + | || |-M | | + | || +---+ | + | || | + | || SEGA | + |------+ || 1993 837-9845 COPERA | + | | || MADE IN JAPAN +--| + | | || VA0 | --> PEN + CONTROL <-- | || | | + | | || +--| + | | || | + | | || | + |------+ || +----+ | + | || |XTAL| +------------+ | + | || | | | OKI JAPAN | +----+ + | || +----------+ |53.6| | M54C864-80 | | | + | |||| | SEGA | |93 | +------------+ | | + | +--+ | 315-5639 | | Mhz| | | + | | U11| +----+ +-------------+ | E | + | |9341PD025 | | | | X | + |--+ +----------+ | SEGA | | T | + MIC <-- | +----+ +----+ | 315-5313A | | E | + | | |TC51| |TC51| | FC1001 | | N | + |--+ |832A| |832A| | 9331 AASG | | D | + | |FL-1| |FL-1| | | | E | + | |0 | |0 | | | | D | + | | | | | | | | | + |--+ +----+ +----+ +-------------+ | | + +-- | | C | + | |--+ | O | +S-AUDIO <-| | +-----------+ +-------+ | N | + | |--+ | SEGA | | SEGA | +-----------+ | N | + +-- | | 315-5640 | |315-564| | 3D4 UA | | E | + |--+ | 9333 W26 | |1 | |HD68HC000CP| | C | + | | | |D77591 | |8 | | T | + |--+ | | +-------+ | | | O | + S-VIDEO <-- | | | | | | R | + |--+ | | | | | | + | +-----------+ | JAPAN| | | + | +-----------+ | | + |--+ | | + VCC --> | +----------------------------------------------+ | | + |--+ | CARTRIDGE | +----+ + | | CONNECTOR | | + | +----------------------------------------------+ | + +-----------------------------------------------------------------------------------------------------------------------------------+ + +*/ + + + +class copera_state : public pico_base_state +{ +public: + copera_state(const machine_config &mconfig, device_type type, const char *tag) : + pico_base_state(mconfig, type, tag), + m_picocart(*this, "coperaslot") + { } + + void copera(machine_config &config); + void copera_mem(address_map &map); + +private: + required_device m_picocart; + DECLARE_MACHINE_START(copera); +}; + + + +void copera_state::copera_mem(address_map &map) +{ + map(0x000000, 0x3fffff).rom(); + + map(0x800000, 0x80001f).rw(FUNC(copera_state::pico_68k_io_read), FUNC(copera_state::pico_68k_io_write)); + + map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); + + map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000); +} + + + +static void copera_cart(device_slot_interface &device) +{ + device.option_add_internal("rom", MD_STD_ROM); + device.option_add_internal("rom_sram", MD_ROM_SRAM); // not sure these are needed... + device.option_add_internal("rom_sramsafe", MD_ROM_SRAM); // not sure these are needed... +} + +MACHINE_START_MEMBER(copera_state,copera) +{ + m_maincpu->space(AS_PROGRAM).install_read_handler(0x000000, 0x7fffff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read))); + m_maincpu->space(AS_PROGRAM).install_write_handler(0x000000, 0x7fffff, write16s_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write))); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa13000, 0xa130ff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read_a13)), write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_a13))); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa15000, 0xa150ff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read_a15)), write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_a15))); + m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14000, 0xa14003, write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_tmss_bank))); + + m_sega_315_5641_pcm->reset_w(0); + m_sega_315_5641_pcm->start_w(0); + m_sega_315_5641_pcm->reset_w(1); + m_sega_315_5641_pcm->start_w(1); + +} + +void copera_state::copera(machine_config &config) +{ + md_ntsc(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &copera_state::copera_mem); + + config.device_remove("genesis_snd_z80"); + config.device_remove("ymsnd"); + + MCFG_MACHINE_START_OVERRIDE( copera_state, copera ) + + COPERA_CART_SLOT(config, m_picocart, copera_cart, nullptr).set_must_be_loaded(true); + SOFTWARE_LIST(config, "cart_list").set_original("copera"); + + SEGA_315_5641_PCM(config, m_sega_315_5641_pcm, upd7759_device::STANDARD_CLOCK); + m_sega_315_5641_pcm->fifo_cb().set(FUNC(copera_state::sound_cause_irq)); + m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "lspeaker", 0.16); + m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "rspeaker", 0.16); +} + + + +ROM_START( copera ) + ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) + ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) +ROM_END + +} // anonymous namespace + + +CONS( 1994, pico, 0, 0, picopal, pico, pico_state, init_pico, "Sega", "Pico (Europe, PAL)", MACHINE_NOT_WORKING) +CONS( 1994, picou, pico, 0, pico, pico, pico_state, init_picou, "Sega", "Pico (USA, NTSC)", MACHINE_NOT_WORKING) +CONS( 1993, picoj, pico, 0, pico, pico, pico_state, init_picoj, "Sega", "Pico (Japan, NTSC)", MACHINE_NOT_WORKING) + +CONS( 1993, copera, 0, 0, copera, pico, copera_state, init_picoj, "Yamaha / Sega", "Yamaha Mixt Book Player Copera", MACHINE_NOT_WORKING) diff --git a/src/mame/sega/segapm.cpp b/src/mame/sega/segapm.cpp new file mode 100644 index 00000000000..494aedcd64e --- /dev/null +++ b/src/mame/sega/segapm.cpp @@ -0,0 +1,89 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +/* Sega Picture Magic (codename JANUS) */ +// http://segaretro.org/Sega_Picture_Magic + +// this uses a Sega 32X PCB (not in a 32X case) attached to a stripped down 68k based board rather than a full Genesis / Megadrive +// it is likely the internal SH2 bios roms differ + + +#include "emu.h" +#include "cpu/m68000/m68000.h" +#include "emupal.h" +#include "screen.h" + + +class segapm_state : public driver_device +{ +public: + segapm_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu") + { } + + void segapm(machine_config &config); + +private: + virtual void video_start() override; + uint32_t screen_update_segapm(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + required_device m_maincpu; + void segapm_map(address_map &map); +}; + + +void segapm_state::video_start() +{ +} + +uint32_t segapm_state::screen_update_segapm(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + return 0; +} + + + +void segapm_state::segapm_map(address_map &map) +{ + map(0x000000, 0x07ffff).rom(); + + // A15100 + + map(0xe00000, 0xe7ffff).ram(); + +} + +static INPUT_PORTS_START( segapm ) +INPUT_PORTS_END + + + + +void segapm_state::segapm(machine_config &config) +{ + M68000(config, m_maincpu, 8000000); // ?? + m_maincpu->set_addrmap(AS_PROGRAM, &segapm_state::segapm_map); + + // + 2 sh2s on 32x board + + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); + screen.set_size(32*8, 32*8); + screen.set_visarea(0*8, 32*8-1, 2*8, 30*8-1); + screen.set_screen_update(FUNC(segapm_state::screen_update_segapm)); + screen.set_palette("palette"); + + PALETTE(config, "palette").set_format(palette_device::xRGB_555, 0x200); +} + + + +ROM_START( segapm ) // was more than one cartridge available? if so softlist them? + ROM_REGION( 0x80000, "maincpu", 0 ) /* 68000 Code */ + ROM_LOAD( "picture magic boot cart.bin", 0x00000, 0x80000, CRC(c9ab4e60) SHA1(9c4d4ab3e59c8acde86049a1ba3787aa03b549a3) ) // internal header is GOUSEI HENSYUU + + // todo, sh2 bios roms etc. +ROM_END + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +CONS( 1996, segapm, 0, 0, segapm, segapm, segapm_state, empty_init, "Sega", "Picture Magic", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) diff --git a/src/mame/sega/segas16a.cpp b/src/mame/sega/segas16a.cpp index a75393e9566..6c348bcd930 100644 --- a/src/mame/sega/segas16a.cpp +++ b/src/mame/sega/segas16a.cpp @@ -153,7 +153,7 @@ Tetris - - - - EPR12169 EPR12170 - #include "fd1089.h" #include "fd1094.h" #include "machine/nvram.h" -#include "segacrp2_device.h" +#include "machine/segacrp2_device.h" #include "sound/dac.h" #include "speaker.h" diff --git a/src/mame/sega/sg1000.cpp b/src/mame/sega/sg1000.cpp new file mode 100644 index 00000000000..a3004543a98 --- /dev/null +++ b/src/mame/sega/sg1000.cpp @@ -0,0 +1,706 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder +/* + +Sega SG-1000 + +PCB Layout +---------- + +171-5078 (C) SEGA 1983 +171-5046 REV. A (C) SEGA 1983 + +|---------------------------| |----------------------------| +| SW1 CN2 | |------|---------------| | SW2 CN4 | +| |---| CN3 |---| | +| CN1 CN5 | +| | +| 10.738635MHz |------------------------------| 7805 | +| |---| |------------------------------| | +| | | CN6 | +| | 9 | | +| | 9 | LS32 | +| | 1 | |---------| | +| | 8 | | TMM2009 | LS139 | +| | A | |---------| |------------------| | +| | | | Z80 | | +| |---| |------------------| | +| | +| | +| MB8118 MB8118 MB8118 MB8118 SN76489A SW3 | +| MB8118 MB8118 MB8118 MB8118 LS257 LS257 | +|---------------------------------------------------------------------------------------| + +Notes: + All IC's shown. + + Z80 - NEC D780C-1 / Zilog Z8400A (REV.A) Z80A CPU @ 3.579545 + TMS9918A- Texas Instruments TMS9918ANL Video Display Processor @ 10.738635MHz + MB8118 - Fujitsu MB8118-12 16K x 1 Dynamic RAM + TMM2009 - Toshiba TMM2009P-A / TMM2009P-B (REV.A) + SN76489A- Texas Instruments SN76489AN Digital Complex Sound Generator @ 3.579545 + CN1 - player 1 joystick connector + CN2 - RF video connector + CN3 - keyboard connector + CN4 - power connector (+9VDC) + CN5 - player 2 joystick connector + CN6 - cartridge connector + SW1 - TV channel select switch + SW2 - power switch + SW3 - hold switch + +*/ + +/* + + TODO: + + - SC-3000 return instruction referenced by R when reading ports 60-7f,e0-ff + - connect PSG /READY signal to Z80 WAIT + - accurate video timing + - SH-400 racing controller + - SF-7000 serial comms + +*/ + + +#include "emu.h" +#include "sg1000.h" +#include "bus/rs232/rs232.h" +#include "softlist_dev.h" +#include "speaker.h" + + +/*************************************************************************** + READ/WRITE HANDLERS +***************************************************************************/ + +// TODO: not sure if the OMV bios actually detects the presence of a cart, +// or if the cart data simply overwrites the internal bios... +// for the moment let assume the latter! +uint8_t sg1000_state::omv_r(offs_t offset) +{ + if (m_cart && m_cart->exists()) + return m_cart->read_cart(offset); + else + return m_rom->base()[offset]; +} + +void sg1000_state::omv_w(offs_t offset, uint8_t data) +{ + if (m_cart && m_cart->exists()) + m_cart->write_cart(offset, data); +} + +uint8_t sg1000_state::peripheral_r(offs_t offset) +{ + bool joy_ports_disabled = m_sgexpslot->is_readable(offset); + + if (joy_ports_disabled) + { + return m_sgexpslot->read(offset); + } + else + { + if (offset & 0x01) + return m_pb7->read(); + else + return m_pa7->read(); + } +} + +void sg1000_state::peripheral_w(offs_t offset, uint8_t data) +{ + bool joy_ports_disabled = m_sgexpslot->is_writeable(offset); + + if (joy_ports_disabled) + { + m_sgexpslot->write(offset, data); + } +} + +/*------------------------------------------------- + ADDRESS_MAP( sg1000_map ) +-------------------------------------------------*/ + +void sg1000_state::sg1000_map(address_map &map) +{ + map(0x0000, 0xbfff).rw(m_cart, FUNC(sega8_cart_slot_device::read_cart), FUNC(sega8_cart_slot_device::write_cart)); + map(0xc000, 0xc3ff).mirror(0x3c00).ram(); +} + +/*------------------------------------------------- + ADDRESS_MAP( sg1000_io_map ) +-------------------------------------------------*/ + +void sg1000_state::sg1000_io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x40, 0x40).mirror(0x3f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); + map(0x80, 0x81).mirror(0x3e).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); + map(0xdc, 0xdf).rw(FUNC(sg1000_state::peripheral_r), FUNC(sg1000_state::peripheral_w)); +} + +/*------------------------------------------------- + ADDRESS_MAP( omv_map ) +-------------------------------------------------*/ + +void sg1000_state::omv_map(address_map &map) +{ + map(0x0000, 0xbfff).rw(FUNC(sg1000_state::omv_r), FUNC(sg1000_state::omv_w)); + map(0xc000, 0xc7ff).mirror(0x3800).ram(); +} + +/*------------------------------------------------- + ADDRESS_MAP( omv_io_map ) +-------------------------------------------------*/ + +void sg1000_state::omv_io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x40, 0x40).mirror(0x3f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); + map(0x80, 0x81).mirror(0x3e).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); + map(0xc0, 0xc0).mirror(0x38).portr("C0"); + map(0xc1, 0xc1).mirror(0x38).portr("C1"); + map(0xc2, 0xc2).mirror(0x38).portr("C2"); + map(0xc3, 0xc3).mirror(0x38).portr("C3"); + map(0xc4, 0xc4).mirror(0x3a).portr("C4"); + map(0xc5, 0xc5).mirror(0x3a).portr("C5"); +} + +/*------------------------------------------------- + ADDRESS_MAP( sc3000_map ) +-------------------------------------------------*/ + +void sg1000_state::sc3000_map(address_map &map) +{ + map(0x0000, 0xbfff).rw(CARTSLOT_TAG, FUNC(sega8_cart_slot_device::read_cart), FUNC(sega8_cart_slot_device::write_cart)); + map(0xc000, 0xc7ff).mirror(0x3800).ram(); +} + +/*------------------------------------------------- + ADDRESS_MAP( sc3000_io_map ) +-------------------------------------------------*/ + +void sg1000_state::sc3000_io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x00, 0xff).rw(CARTSLOT_TAG, FUNC(sega8_cart_slot_device::read_io), FUNC(sega8_cart_slot_device::write_io)); + map(0x7f, 0x7f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); + map(0xbe, 0xbf).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); + map(0xdc, 0xdf).rw(FUNC(sg1000_state::peripheral_r), FUNC(sg1000_state::peripheral_w)); +} + +/* This is how the I/O ports are really mapped, but MAME does not support overlapping ranges +void sg1000_state::sc3000_io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x00, 0x00).mirror(0xdf).rw(UPD9255_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write)); + map(0x00, 0x00).mirror(0x7f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); + map(0x00, 0x01).mirror(0xae).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); + map(0x60, 0x60).mirror(0x9f).r(FUNC(sg1000_state::sc3000_r_r)); +} +*/ + +/*------------------------------------------------- + ADDRESS_MAP( sf7000_map ) +-------------------------------------------------*/ + +void sf7000_state::sf7000_map(address_map &map) +{ + map(0x0000, 0x3fff).bankr("bank1").bankw("bank2"); + map(0x4000, 0xffff).ram(); +} + +/*------------------------------------------------- + ADDRESS_MAP( sf7000_io_map ) +-------------------------------------------------*/ + +void sf7000_state::sf7000_io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x7f, 0x7f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); + map(0xbe, 0xbf).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); + map(0xdc, 0xdf).rw(FUNC(sf7000_state::peripheral_r), FUNC(sf7000_state::peripheral_w)); + map(0xe0, 0xe1).m(m_fdc, FUNC(upd765a_device::map)); + map(0xe4, 0xe7).rw(UPD9255_1_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write)); + map(0xe8, 0xe9).rw(UPD8251_TAG, FUNC(i8251_device::read), FUNC(i8251_device::write)); +} + +/*************************************************************************** + INPUT PORTS +***************************************************************************/ + +/*------------------------------------------------- + INPUT_CHANGED_MEMBER( trigger_nmi ) +-------------------------------------------------*/ + +INPUT_CHANGED_MEMBER( sg1000_state::trigger_nmi ) +{ + m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE); +} + +/*------------------------------------------------- + INPUT_PORTS( sg1000 ) +-------------------------------------------------*/ + +static INPUT_PORTS_START( sg1000_joy ) + PORT_START("PA7") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) + + PORT_START("PB7") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + +static INPUT_PORTS_START( sg1000 ) + PORT_INCLUDE( sg1000_joy ) + + PORT_START("NMI") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("PAUSE") PORT_CODE(KEYCODE_P) PORT_CHANGED_MEMBER(DEVICE_SELF, sg1000_state, trigger_nmi, 0) +INPUT_PORTS_END + +/*------------------------------------------------- + INPUT_PORTS( omv ) +-------------------------------------------------*/ + +static INPUT_PORTS_START( omv1000 ) + PORT_START("C0") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') + PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("C1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("9 #") PORT_CODE(KEYCODE_9) PORT_CHAR('9') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("0 *") PORT_CODE(KEYCODE_0) PORT_CHAR('0') + PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("C2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E') + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F') + PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("C3") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G') + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H') + PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("C4") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("S-1") + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("S-2") + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) + + // The OMV FG-1000 has no 2nd joystick + // http://www.famitsu.com/image/29819/pEllnbNQfCJ58skZ25uB511N6eSFfAu6.jpg + PORT_START("C5") + PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + +static INPUT_PORTS_START( omv2000 ) + PORT_INCLUDE( omv1000 ) + + PORT_MODIFY("C5") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_END + +/*------------------------------------------------- + INPUT_PORTS( sc3000 ) +-------------------------------------------------*/ + +static INPUT_PORTS_START( sc3000 ) + PORT_INCLUDE( sg1000_joy ) + + // keyboard keys are added by the embedded sk1100 device + + PORT_START("NMI") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F10) PORT_CHANGED_MEMBER(DEVICE_SELF, sg1000_state, trigger_nmi, 0) +INPUT_PORTS_END + +/*------------------------------------------------- + INPUT_PORTS( sf7000 ) +-------------------------------------------------*/ + +static INPUT_PORTS_START( sf7000 ) + PORT_INCLUDE( sc3000 ) + + PORT_START("BAUD") + PORT_CONFNAME( 0x07, 0x05, "Baud rate") + PORT_CONFSETTING( 0x00, "9600 baud" ) + PORT_CONFSETTING( 0x01, "4800 baud" ) + PORT_CONFSETTING( 0x02, "2400 baud" ) + PORT_CONFSETTING( 0x03, "1200 baud" ) + PORT_CONFSETTING( 0x04, "600 baud" ) + PORT_CONFSETTING( 0x05, "300 baud" ) +INPUT_PORTS_END + +/*************************************************************************** + DEVICE CONFIGURATION +***************************************************************************/ + +/*------------------------------------------------- + I8255 INTERFACE +-------------------------------------------------*/ + +WRITE_LINE_MEMBER( sf7000_state::write_centronics_busy ) +{ + m_centronics_busy = state; +} + +uint8_t sf7000_state::ppi_pa_r() +{ + /* + Signal Description + + PA0 INT from FDC + PA1 BUSY from Centronics printer + PA2 INDEX from FDD + PA3 + PA4 + PA5 + PA6 + PA7 + */ + + uint8_t data = 0; + + data |= m_fdc->get_irq() ? 0x01 : 0x00; + data |= m_centronics_busy << 1; + data |= m_floppy0->idx_r() << 2; + + return data; +} + +void sf7000_state::ppi_pc_w(uint8_t data) +{ + /* + Signal Description + + PC0 /INUSE signal to FDD + PC1 /MOTOR ON signal to FDD + PC2 TC signal to FDC + PC3 RESET signal to FDC + PC4 not connected + PC5 not connected + PC6 /ROM SEL (switch between IPL ROM and RAM) + PC7 /STROBE to Centronics printer + */ + + if (!BIT(data, 0)) + m_fdc->set_floppy(m_floppy0); + else + m_fdc->set_floppy(nullptr); + + /* floppy motor */ + m_floppy0->mon_w(BIT(data, 1)); + + /* FDC terminal count */ + m_fdc->tc_w(BIT(data, 2)); + + /* FDC reset */ + if (BIT(data, 3)) + { + m_fdc->reset(); + } + + /* ROM selection */ + membank("bank1")->set_entry(BIT(data, 6)); + + /* printer strobe */ + m_centronics->write_strobe(BIT(data, 7)); +} + +/*------------------------------------------------- + upd765_interface sf7000_upd765_interface +-------------------------------------------------*/ + +void sf7000_state::floppy_formats(format_registration &fr) +{ + fr.add_mfm_containers(); + fr.add(FLOPPY_SF7000_FORMAT); +} + +/*------------------------------------------------- + floppy_interface sf7000_floppy_interface +-------------------------------------------------*/ + +static void sf7000_floppies(device_slot_interface &device) +{ + device.option_add("3ssdd", FLOPPY_3_SSDD); +} + +/*------------------------------------------------- + MACHINE_START( sg1000 ) +-------------------------------------------------*/ + +void sg1000_state::machine_start() +{ + if (m_cart->get_type() == SEGA8_DAHJEE_TYPEA || m_cart->get_type() == SEGA8_DAHJEE_TYPEB) + { + m_maincpu->space(AS_PROGRAM).install_read_handler(0xc000, 0xffff, read8sm_delegate(*m_cart, FUNC(sega8_cart_slot_device::read_ram))); + m_maincpu->space(AS_PROGRAM).install_write_handler(0xc000, 0xffff, write8sm_delegate(*m_cart, FUNC(sega8_cart_slot_device::write_ram))); + } + + if (m_cart) + m_cart->save_ram(); +} + +/*------------------------------------------------- + MACHINE_START( sc3000 ) +-------------------------------------------------*/ + +void sc3000_state::machine_start() +{ + if (m_cart && m_cart->exists() && (m_cart->get_type() == SEGA8_BASIC_L3 || m_cart->get_type() == SEGA8_MUSIC_EDITOR + || m_cart->get_type() == SEGA8_DAHJEE_TYPEA || m_cart->get_type() == SEGA8_DAHJEE_TYPEB + || m_cart->get_type() == SEGA8_MULTICART || m_cart->get_type() == SEGA8_MEGACART)) + { + m_maincpu->space(AS_PROGRAM).install_read_handler(0xc000, 0xffff, read8sm_delegate(*m_cart, FUNC(sega8_cart_slot_device::read_ram))); + m_maincpu->space(AS_PROGRAM).install_write_handler(0xc000, 0xffff, write8sm_delegate(*m_cart, FUNC(sega8_cart_slot_device::write_ram))); + } + + if (m_cart) + m_cart->save_ram(); +} + + +/*------------------------------------------------- + MACHINE_START( sf7000 ) +-------------------------------------------------*/ + +void sf7000_state::machine_start() +{ + sc3000_state::machine_start(); + + save_item(NAME(m_centronics_busy)); + + /* configure memory banking */ + membank("bank1")->configure_entry(0, m_rom->base()); + membank("bank1")->configure_entry(1, m_ram->pointer()); + membank("bank2")->configure_entry(0, m_ram->pointer()); +} + +void sf7000_state::machine_reset() +{ + membank("bank1")->set_entry(0); + membank("bank2")->set_entry(0); +} + +/*************************************************************************** + MACHINE DRIVERS +***************************************************************************/ + +/*------------------------------------------------- + machine_config( sg1000 ) +-------------------------------------------------*/ + +void sg1000_state::sg1000(machine_config &config) +{ + /* basic machine hardware */ + Z80(config, m_maincpu, XTAL(10'738'635)/3); + m_maincpu->set_addrmap(AS_PROGRAM, &sg1000_state::sg1000_map); + m_maincpu->set_addrmap(AS_IO, &sg1000_state::sg1000_io_map); + + /* video hardware */ + tms9918a_device &vdp(TMS9918A(config, TMS9918A_TAG, XTAL(10'738'635))); + vdp.set_screen("screen"); + vdp.set_vram_size(0x4000); + vdp.int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + SCREEN(config, "screen", SCREEN_TYPE_RASTER); + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + + SN76489A(config, SN76489AN_TAG, XTAL(10'738'635)/3).add_route(ALL_OUTPUTS, "mono", 1.00); + + /* expansion slot */ + SG1000_EXPANSION_SLOT(config, m_sgexpslot, sg1000_expansion_devices, nullptr, false); + + /* cartridge */ + SG1000_CART_SLOT(config, CARTSLOT_TAG, sg1000_cart, nullptr).set_must_be_loaded(true); + + /* software lists */ + SOFTWARE_LIST(config, "cart_list").set_original("sg1000"); + + /* internal ram */ + RAM(config, m_ram).set_default_size("1K"); +} + +/*------------------------------------------------- + machine_config( omv ) +-------------------------------------------------*/ + +void sg1000_state::omv(machine_config &config) +{ + sg1000(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &sg1000_state::omv_map); + m_maincpu->set_addrmap(AS_IO, &sg1000_state::omv_io_map); + + OMV_CART_SLOT(config.replace(), CARTSLOT_TAG, sg1000_cart, nullptr); + + m_ram->set_default_size("2K"); +} + +/*------------------------------------------------- + machine_config( sc3000 ) +-------------------------------------------------*/ + +void sc3000_state::sc3000(machine_config &config) +{ + /* basic machine hardware */ + Z80(config, m_maincpu, XTAL(10'738'635)/3); // LH0080A + m_maincpu->set_addrmap(AS_PROGRAM, &sc3000_state::sc3000_map); + m_maincpu->set_addrmap(AS_IO, &sc3000_state::sc3000_io_map); + + /* video hardware */ + tms9918a_device &vdp(TMS9918A(config, TMS9918A_TAG, XTAL(10'738'635))); + vdp.set_screen("screen"); + vdp.set_vram_size(0x4000); + vdp.int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + SCREEN(config, "screen", SCREEN_TYPE_RASTER); + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + + SN76489A(config, SN76489AN_TAG, XTAL(10'738'635)/3).add_route(ALL_OUTPUTS, "mono", 1.00); + + /* sc3000 has all sk1100 features built-in, so add it as a fixed slot */ + SG1000_EXPANSION_SLOT(config, m_sgexpslot, sg1000_expansion_devices, "sk1100", true); + + /* cartridge */ + SC3000_CART_SLOT(config, CARTSLOT_TAG, sg1000_cart, nullptr).set_must_be_loaded(true); + + /* software lists */ + SOFTWARE_LIST(config, "cart_list").set_original("sg1000"); + /* the sk1100 device will add sc3000 cart and cass lists */ + + /* internal ram */ + RAM(config, m_ram).set_default_size("2K"); +} + +/*------------------------------------------------- + machine_config( sf7000 ) +-------------------------------------------------*/ + +void sf7000_state::sf7000(machine_config &config) +{ + /* basic machine hardware */ + Z80(config, m_maincpu, XTAL(10'738'635)/3); + m_maincpu->set_addrmap(AS_PROGRAM, &sf7000_state::sf7000_map); + m_maincpu->set_addrmap(AS_IO, &sf7000_state::sf7000_io_map); + + /* video hardware */ + tms9918a_device &vdp(TMS9918A(config, TMS9918A_TAG, XTAL(10'738'635))); + vdp.set_screen("screen"); + vdp.set_vram_size(0x4000); + vdp.int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + SCREEN(config, "screen", SCREEN_TYPE_RASTER); + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + + SN76489A(config, SN76489AN_TAG, XTAL(10'738'635)/3).add_route(ALL_OUTPUTS, "mono", 1.00); + + /* devices */ + i8255_device &ppi(I8255(config, UPD9255_1_TAG)); + ppi.in_pa_callback().set(FUNC(sf7000_state::ppi_pa_r)); + ppi.out_pb_callback().set("cent_data_out", FUNC(output_latch_device::write)); + ppi.out_pc_callback().set(FUNC(sf7000_state::ppi_pc_w)); + + i8251_device &upd8251(I8251(config, UPD8251_TAG, 0)); + upd8251.txd_handler().set(RS232_TAG, FUNC(rs232_port_device::write_txd)); + upd8251.dtr_handler().set(RS232_TAG, FUNC(rs232_port_device::write_dtr)); + upd8251.rts_handler().set(RS232_TAG, FUNC(rs232_port_device::write_rts)); + + rs232_port_device &rs232(RS232_PORT(config, RS232_TAG, default_rs232_devices, nullptr)); + rs232.rxd_handler().set(UPD8251_TAG, FUNC(i8251_device::write_rxd)); + rs232.dsr_handler().set(UPD8251_TAG, FUNC(i8251_device::write_dsr)); + + UPD765A(config, m_fdc, 8'000'000, false, false); + FLOPPY_CONNECTOR(config, UPD765_TAG ":0", sf7000_floppies, "3ssdd", sf7000_state::floppy_formats); + + CENTRONICS(config, m_centronics, centronics_devices, "printer"); + + output_latch_device ¢_data_out(OUTPUT_LATCH(config, "cent_data_out")); + m_centronics->set_output_latch(cent_data_out); + + /* sf7000 (sc3000) has all sk1100 features built-in, so add it as a fixed slot */ + SG1000_EXPANSION_SLOT(config, m_sgexpslot, sg1000_expansion_devices, "sk1100", true); + + /* software lists */ + SOFTWARE_LIST(config, "flop_list").set_original("sf7000"); + + /* internal ram */ + RAM(config, m_ram).set_default_size("64K"); +} + +/*************************************************************************** + ROMS +***************************************************************************/ + +ROM_START( sg1000 ) + ROM_REGION( 0x10000, Z80_TAG, ROMREGION_ERASE00 ) +ROM_END + +#define rom_sg1000m2 rom_sg1000 + +#define rom_sc3000 rom_sg1000 + +#define rom_sc3000h rom_sg1000 + +ROM_START( sf7000 ) + ROM_REGION( 0x10000, Z80_TAG, ROMREGION_ERASE00 ) + ROM_LOAD( "ipl.rom", 0x0000, 0x2000, CRC(d76810b8) SHA1(77339a6db2593aadc638bed77b8e9bed5d9d87e3) ) +ROM_END + +ROM_START( omv1000 ) + ROM_REGION( 0x10000, Z80_TAG, ROMREGION_ERASE00 ) + ROM_LOAD( "omvbios.bin", 0x0000, 0x4000, BAD_DUMP CRC(c5a67b95) SHA1(6d7c64dd60dee4a33061d3d3a7c2ed190d895cdb) ) // The BIOS comes from a Multivision FG-2000. It is still unknown if the FG-1000 BIOS differs +ROM_END + +ROM_START( omv2000 ) + ROM_REGION( 0x10000, Z80_TAG, ROMREGION_ERASE00 ) + ROM_LOAD( "omvbios.bin", 0x0000, 0x4000, CRC(c5a67b95) SHA1(6d7c64dd60dee4a33061d3d3a7c2ed190d895cdb) ) +ROM_END + +/*************************************************************************** + SYSTEM DRIVERS +***************************************************************************/ + +/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ +CONS( 1983, sg1000, 0, 0, sg1000, sg1000, sg1000_state, empty_init, "Sega", "SG-1000", MACHINE_SUPPORTS_SAVE ) +CONS( 1984, sg1000m2, sg1000, 0, sc3000, sc3000, sc3000_state, empty_init, "Sega", "SG-1000 II", MACHINE_SUPPORTS_SAVE ) +COMP( 1983, sc3000, 0, sg1000, sc3000, sc3000, sc3000_state, empty_init, "Sega", "SC-3000", MACHINE_SUPPORTS_SAVE ) +COMP( 1983, sc3000h, sc3000, 0, sc3000, sc3000, sc3000_state, empty_init, "Sega", "SC-3000H", MACHINE_SUPPORTS_SAVE ) +COMP( 1983, sf7000, sc3000, 0, sf7000, sf7000, sf7000_state, empty_init, "Sega", "SC-3000/Super Control Station SF-7000", MACHINE_SUPPORTS_SAVE ) +CONS( 1984, omv1000, sg1000, 0, omv, omv1000, sg1000_state, empty_init, "Tsukuda Original", "Othello Multivision FG-1000", MACHINE_SUPPORTS_SAVE ) +CONS( 1984, omv2000, sg1000, 0, omv, omv2000, sg1000_state, empty_init, "Tsukuda Original", "Othello Multivision FG-2000", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/sega/sg1000.h b/src/mame/sega/sg1000.h new file mode 100644 index 00000000000..11e1a6ab851 --- /dev/null +++ b/src/mame/sega/sg1000.h @@ -0,0 +1,124 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder + +#ifndef MAME_INCLUDES_SG1000_H +#define MAME_INCLUDES_SG1000_H + +#include "cpu/z80/z80.h" +#include "formats/sf7000_dsk.h" +#include "imagedev/floppy.h" +#include "imagedev/printer.h" +#include "bus/centronics/ctronics.h" +#include "machine/i8255.h" +#include "machine/i8251.h" +#include "machine/ram.h" +#include "bus/sega8/sega8_slot.h" +#include "bus/sg1000_exp/sg1000exp.h" +#include "machine/upd765.h" +#include "sound/sn76496.h" +#include "video/tms9928a.h" +#include "crsshair.h" + +#define SCREEN_TAG "screen" +#define Z80_TAG "z80" +#define SN76489AN_TAG "sn76489an" +#define UPD765_TAG "upd765" +#define UPD8251_TAG "upd8251" +#define UPD9255_TAG "upd9255" +#define UPD9255_1_TAG "upd9255_1" // "upd9255_0" is being used by sk1100 device +#define CENTRONICS_TAG "centronics" +#define TMS9918A_TAG "tms9918a" +#define RS232_TAG "rs232" +#define CARTSLOT_TAG "slot" +#define EXPSLOT_TAG "sgexp" + + + +class sg1000_state : public driver_device +{ +public: + sg1000_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag), + m_maincpu(*this, Z80_TAG), + m_ram(*this, RAM_TAG), + m_rom(*this, Z80_TAG), + m_cart(*this, CARTSLOT_TAG), + m_sgexpslot(*this, EXPSLOT_TAG), + m_pa7(*this, "PA7"), + m_pb7(*this, "PB7") + { } + + void sg1000(machine_config &config); + void omv(machine_config &config); + + DECLARE_INPUT_CHANGED_MEMBER( trigger_nmi ); + +protected: + required_device m_maincpu; + required_device m_ram; + required_memory_region m_rom; + optional_device m_cart; + optional_device m_sgexpslot; + optional_ioport m_pa7; + optional_ioport m_pb7; + + virtual void machine_start() override; + + uint8_t peripheral_r(offs_t offset); + void peripheral_w(offs_t offset, uint8_t data); + + uint8_t omv_r(offs_t offset); + void omv_w(offs_t offset, uint8_t data); + + void omv_io_map(address_map &map); + void omv_map(address_map &map); + void sc3000_io_map(address_map &map); + void sc3000_map(address_map &map); + void sg1000_io_map(address_map &map); + void sg1000_map(address_map &map); +}; + +class sc3000_state : public sg1000_state +{ +public: + sc3000_state(const machine_config &mconfig, device_type type, const char *tag) + : sg1000_state(mconfig, type, tag) + { } + + void sc3000(machine_config &config); + +protected: + virtual void machine_start() override; +}; + +class sf7000_state : public sc3000_state +{ +public: + sf7000_state(const machine_config &mconfig, device_type type, const char *tag) + : sc3000_state(mconfig, type, tag), + m_fdc(*this, UPD765_TAG), + m_centronics(*this, CENTRONICS_TAG), + m_floppy0(*this, UPD765_TAG ":0:3ssdd") + { } + + void sf7000(machine_config &config); + +private: + required_device m_fdc; + required_device m_centronics; + required_device m_floppy0; + + virtual void machine_start() override; + virtual void machine_reset() override; + + int m_centronics_busy = 0; + DECLARE_WRITE_LINE_MEMBER( write_centronics_busy ); + uint8_t ppi_pa_r(); + void ppi_pc_w(uint8_t data); + + static void floppy_formats(format_registration &fr); + void sf7000_io_map(address_map &map); + void sf7000_map(address_map &map); +}; + +#endif diff --git a/src/mame/sega/sg1000a.cpp b/src/mame/sega/sg1000a.cpp index 2480d61567d..9f98d03f096 100644 --- a/src/mame/sega/sg1000a.cpp +++ b/src/mame/sega/sg1000a.cpp @@ -271,12 +271,11 @@ End #include "emu.h" -#include "segacrpt_device.h" - #include "cpu/z80/z80.h" #include "sound/sn76496.h" #include "video/tms9928a.h" #include "machine/i8255.h" +#include "machine/segacrpt_device.h" #include "speaker.h" diff --git a/src/mame/sega/suprloco.cpp b/src/mame/sega/suprloco.cpp index fa16728f4e9..162409dbc67 100644 --- a/src/mame/sega/suprloco.cpp +++ b/src/mame/sega/suprloco.cpp @@ -24,8 +24,7 @@ Sega PCB 834-5137 #include "emu.h" #include "suprloco.h" -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "cpu/z80/z80.h" #include "machine/i8255.h" #include "sound/sn76496.h" diff --git a/src/mame/sega/svmu.cpp b/src/mame/sega/svmu.cpp new file mode 100644 index 00000000000..61cc0a204de --- /dev/null +++ b/src/mame/sega/svmu.cpp @@ -0,0 +1,416 @@ +// license:BSD-3-Clause +// copyright-holders:Sandro Ronco +/*************************************************************************** + + Sega Visual Memory Unit + + driver by Sandro Ronco + + TODO: + - add more bios versions + - serial + +****************************************************************************/ + +#include "emu.h" +#include "cpu/lc8670/lc8670.h" +#include "imagedev/snapquik.h" +#include "machine/intelfsh.h" +#include "sound/spkrdev.h" +#include "emupal.h" +#include "screen.h" +#include "softlist_dev.h" +#include "speaker.h" + +#include "svmu.lh" + + +#define PIXEL_SIZE 7 +#define PIXEL_DISTANCE 1 + +class svmu_state : public driver_device +{ +public: + svmu_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_flash(*this, "flash") + , m_speaker(*this, "speaker") + , m_bios(*this, "bios") + , m_battery(*this, "BATTERY") + , m_file_icon(*this, "file_icon") + , m_game_icon(*this, "game_icon") + , m_clock_icon(*this, "clock_icon") + , m_flash_icon(*this, "flash_icon") + { } + + void svmu(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + LC8670_LCD_UPDATE(svmu_lcd_update); + void svmu_palette(palette_device &palette) const; + void page_w(uint8_t data); + uint8_t prog_r(offs_t offset); + void prog_w(offs_t offset, uint8_t data); + uint8_t p1_r(); + void p1_w(uint8_t data); + uint8_t p7_r(); + DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb); + + void svmu_io_mem(address_map &map); + void svmu_mem(address_map &map); + + required_device m_maincpu; + required_device m_flash; + required_device m_speaker; + required_region_ptr m_bios; + required_ioport m_battery; + output_finder<> m_file_icon; + output_finder<> m_game_icon; + output_finder<> m_clock_icon; + output_finder<> m_flash_icon; + + uint8_t m_page; +}; + + +void svmu_state::page_w(uint8_t data) +{ + m_page = data & 0x03; +} + +uint8_t svmu_state::prog_r(offs_t offset) +{ + if (m_page == 1) + return m_flash->read(offset); + else if (m_page == 2) + return m_flash->read(0x10000 + offset); + else + return m_bios[offset]; +} + +void svmu_state::prog_w(offs_t offset, uint8_t data) +{ + if (m_page == 1) + m_flash->write(offset, data); + else if (m_page == 2) + m_flash->write(0x10000 + offset, data); +} + +/* + Port 1 + + x--- ---- PWM output + -x-- ---- BUZ + --x- ---- SCK1 + ---x ---- SB1 + ---- x--- SO1 + ---- -x-- SCK0 + ---- --x- SB0 + ---- ---x SO0 + +*/ + +uint8_t svmu_state::p1_r() +{ + return 0; +} + +void svmu_state::p1_w(uint8_t data) +{ + m_speaker->level_w(BIT(data, 7)); +} + + +/* + Port 7 + + ---- x--- ID1 + ---- -x-- ID0 + ---- --x- battery low voltage + ---- ---x 5V detection +*/ + +uint8_t svmu_state::p7_r() +{ + return (m_battery->read()<<1); +} + + +void svmu_state::svmu_mem(address_map &map) +{ + map(0x0000, 0xffff).rw(FUNC(svmu_state::prog_r), FUNC(svmu_state::prog_w)); +} + +void svmu_state::svmu_io_mem(address_map &map) +{ + map(LC8670_PORT1, LC8670_PORT1).rw(FUNC(svmu_state::p1_r), FUNC(svmu_state::p1_w)); + map(LC8670_PORT3, LC8670_PORT3).portr("P3"); + map(LC8670_PORT7, LC8670_PORT7).r(FUNC(svmu_state::p7_r)); +} + +/* Input ports */ +static INPUT_PORTS_START( svmu ) + PORT_START( "P3" ) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_NAME("Up") + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_NAME("Down") + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_NAME("Left") + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_NAME("Right") + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Button A") + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("Button B") + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("MODE") PORT_CODE( KEYCODE_M ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("SLEEP") PORT_CODE( KEYCODE_S ) + PORT_START("BATTERY") + PORT_CONFNAME( 0x01, 0x01, "Battery" ) + PORT_CONFSETTING( 0x01, "Good" ) + PORT_CONFSETTING( 0x00, "Poor" ) +INPUT_PORTS_END + +void svmu_state::machine_start() +{ + m_file_icon.resolve(); + m_game_icon.resolve(); + m_clock_icon.resolve(); + m_flash_icon.resolve(); +} + +void svmu_state::machine_reset() +{ + m_page = 0; +} + +void svmu_state::svmu_palette(palette_device &palette) const +{ + palette.set_pen_color(0, rgb_t(138, 146, 148)); + palette.set_pen_color(1, rgb_t(92, 83, 88)); +} + +LC8670_LCD_UPDATE(svmu_state::svmu_lcd_update) +{ + if (lcd_enabled) + { + for (int y=0; y<32; y++) + for (int x=0; x<6; x++) + { + int gfx = vram[y*6 + x]; + + for (int b = 0; b < 8; b++) + bitmap.plot_box((x*8 + b) * (PIXEL_SIZE + PIXEL_DISTANCE), y * (PIXEL_SIZE + PIXEL_DISTANCE), PIXEL_SIZE, PIXEL_SIZE, BIT(gfx,7-b)); + } + } + else + { + bitmap.fill(0, cliprect); + } + + m_file_icon = lcd_enabled ? BIT(vram[0xc1],6) : 0; + m_game_icon = lcd_enabled ? BIT(vram[0xc2],4) : 0; + m_clock_icon = lcd_enabled ? BIT(vram[0xc3],2) : 0; + m_flash_icon = lcd_enabled ? BIT(vram[0xc4],0) : 0; + + return 0; +} + + +inline void vmufat_write_byte(uint8_t* flash, uint8_t block, offs_t offset, uint8_t data) +{ + flash[(block * 512) + offset] = data; +} + +inline void vmufat_write_word(uint8_t* flash, uint8_t block, offs_t offset, uint16_t data) +{ + // 16-bit data are stored in little endian + flash[(block * 512) + offset + 0] = data & 0xff; + flash[(block * 512) + offset + 1] = (data>>8) & 0xff; +} + +QUICKLOAD_LOAD_MEMBER(svmu_state::quickload_cb) +{ + uint32_t size = image.length(); + uint8_t *flash = m_flash->base(); + + image.fread(flash, size); + + // verify if image is already a valid VMUFAT file system + bool valid_vmufat = true; + if (size == 0x20000) + { + for (int i=0; i<0x10; i++) + if (flash[255 * 512 + i] != 0x55) + { + valid_vmufat = false; + break; + } + } + else + { + valid_vmufat = false; + } + + if (!valid_vmufat) + { + // more info about the VMUFAT here: http://mc.pp.se/dc/vms/flashmem.html + + //-------------------------------- Formatting -------------------------------- + memset(flash + 241*512, 0, 15*512); // clears the last 15 blocks that contain file system information + + for (int i=0; i<0x10; i++) + vmufat_write_byte(flash, 255, i, 0x55); // first 16 bytes should be 0x55 to indicate a properly formatted card + + vmufat_write_byte(flash, 255, 0x10, 0x00); // custom VMS colour (1 = use custom colours, 0 = standard colour) + vmufat_write_byte(flash, 255, 0x11, 0x00); // VMS colour blue component + vmufat_write_byte(flash, 255, 0x12, 0x00); // VMS colour green component + vmufat_write_byte(flash, 255, 0x13, 0x00); // VMS colour red component + vmufat_write_byte(flash, 255, 0x14, 0x00); // VMS colour alpha component + vmufat_write_byte(flash, 255, 0x30, 0x19); // Century (BCD) + vmufat_write_byte(flash, 255, 0x31, 0x99); // Year (BCD) + vmufat_write_byte(flash, 255, 0x32, 0x01); // Month (BCD) + vmufat_write_byte(flash, 255, 0x33, 0x01); // Day (BCD) + vmufat_write_byte(flash, 255, 0x34, 0x00); // Hour (BCD) + vmufat_write_byte(flash, 255, 0x35, 0x00); // Minute (BCD) + vmufat_write_byte(flash, 255, 0x36, 0x00); // Second (BCD) + vmufat_write_byte(flash, 255, 0x37, 0x00); // Day of week (0 = Monday, 6 = Sunday) + vmufat_write_word(flash, 255, 0x44, 0x00ff); // location of Root + vmufat_write_word(flash, 255, 0x46, 0x00fe); // location of FAT (254) + vmufat_write_word(flash, 255, 0x48, 0x0001); // size of FAT in blocks (1) + vmufat_write_word(flash, 255, 0x4a, 0x00fd); // location of Directory (253) + vmufat_write_word(flash, 255, 0x4c, 0x000d); // size of Directory in blocks (13) + vmufat_write_word(flash, 255, 0x4e, 0x0000); // icon shape for this VMS (0-123) + vmufat_write_word(flash, 255, 0x50, 0x00c8); // number of user blocks (200) + + for (int i=0; i<256; i++) + vmufat_write_word(flash, 254, i<<1, 0xfffc); // marks all blocks as unallocated + + for (int i=253; i>241; --i) + vmufat_write_word(flash, 254, i<<1, i - 1); // marsk all Directory blocks as allocate + + vmufat_write_word(flash, 254, 0x1e2, 0xfffa); // marks last Directory block + vmufat_write_word(flash, 254, 0x1fc, 0xfffa); // marks FAT block as allocated + vmufat_write_word(flash, 254, 0x1fe, 0xfffa); // marks Root block as allocated + + //-------------------------------- Create the vms file -------------------------------- + int vms_blocks = (size / 512) + (size & 0x1ff ? 1 : 0); // number of blocks required for store the vms file + + for (int i=0; iset_addrmap(AS_PROGRAM, &svmu_state::svmu_mem); + m_maincpu->set_addrmap(AS_IO, &svmu_state::svmu_io_mem); + + /* specific LC8670 configurations */ + m_maincpu->set_clock_sources(XTAL(32'768), 600000, XTAL(6'000'000)); // tolerance range of the RC oscillator is 600kHz to 1200kHz + m_maincpu->bank_cb().set(FUNC(svmu_state::page_w)); + m_maincpu->set_lcd_update_cb(FUNC(svmu_state::svmu_lcd_update)); + + /* video hardware */ + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // not accurate + screen.set_size(48 * (PIXEL_SIZE + PIXEL_DISTANCE), 32 * (PIXEL_SIZE + PIXEL_DISTANCE)); + screen.set_visarea(0, 48*(PIXEL_SIZE + PIXEL_DISTANCE) - 1, 0, 32*(PIXEL_SIZE + PIXEL_DISTANCE) - 1); + screen.set_screen_update("maincpu", FUNC(lc8670_cpu_device::screen_update)); + screen.set_palette("palette"); + + config.set_default_layout(layout_svmu); + PALETTE(config, "palette", FUNC(svmu_state::svmu_palette), 2); + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50); + + /* devices */ + ATMEL_29C010(config, m_flash); + + quickload_image_device &quickload(QUICKLOAD(config, "quickload", "vms,bin")); + quickload.set_load_callback(FUNC(svmu_state::quickload_cb)); + quickload.set_interface("svmu_quik"); + + /* Software lists */ + SOFTWARE_LIST(config, "quik_list").set_original("svmu"); +} + + +/* ROM definition */ +ROM_START( svmu ) + // some ROMs come from the Sega Katana SDK and are scrambled, a simple way to restore them is to remove the first 4 bytes and xor the whole file for the xor key. + + ROM_REGION(0x10000, "bios", 0) + ROM_DEFAULT_BIOS("en1005b") + + // Version 1.005,1999/04/28,315-6124-07,SEGA Visual Memory System BIOS Produced by Sue + ROM_SYSTEM_BIOS(0, "en1005a", "VMS English BIOS (1.005 1999/04/28)") + ROMX_LOAD("en1005-19990428-315-6124-07.bin", 0x0000, 0x10000, CRC(dfd77f4e) SHA1(4a7bfd1b8eb599d87883312df0bb48e0edd13034), ROM_BIOS(0)) // extracted with trojan + + // Version 1.005,1999/10/26,315-6208-05,SEGA Visual Memory System BIOS Produced by Sue + ROM_SYSTEM_BIOS(1, "en1005b", "VMS English BIOS (1.005 1999/10/26)") + ROMX_LOAD("en1005-19991026-315-6208-05.bin", 0x0000, 0x10000, CRC(c825003a) SHA1(6242320d705c156f8369969d6caa8c737f01e4f3), ROM_BIOS(1)) // extracted with trojan + + // Version 1.001,1998/05/28,315-6124-02,SEGA Visual Memory System BIOS Produced by Sue + ROM_SYSTEM_BIOS(2, "jp1001", "VMS Japanese BIOS (1.001 1998/05/28)") + ROMX_LOAD("jp1001-19980528-315-6124-02.bin", 0x0000, 0x10000, CRC(e6339f4a) SHA1(688b2e1ff8c60bde6e8b07a2d2695cdacc07bd0c), ROM_BIOS(2)) + + // Version 1.002,1998/06/04,315-6124-03,SEGA Visual Memory System BIOS Produced by Sue + ROM_SYSTEM_BIOS(3, "jp1002", "VMS Japanese BIOS (1.002 1998/06/04)") + ROMX_LOAD("jp1002-19980604-315-6124-03.bin", 0x0000, 0x10000, CRC(6c020d48) SHA1(9ee7c87d7b033235e0b315a0b421e70deb547c7a), ROM_BIOS(3)) + + // Version 1.004,1998/09/30,315-6208-01,SEGA Visual Memory System BIOS Produced by Sue + ROM_SYSTEM_BIOS(4, "jp1004", "VMS Japanese BIOS (1.004, 1998/09/30)") + ROMX_LOAD("jp1004-19980930-315-6208-01.bin", 0x0000, 0x10000, CRC(8e0f867a) SHA1(dc2fa2963138a1049a43f7f36439ad0a416ee8b4), ROM_BIOS(4)) // from Sega Katana SDK (original file: fbios.sbf, CRC: c7c77b3c, xor key: 0x37) + + // Version 1.005,1998/12/09,315-6124-05,SEGA Visual Memory System BIOS Produced by Sue + ROM_SYSTEM_BIOS(5, "jp1005a", "VMS Japanese BIOS (1.005 1998/12/09)") + ROMX_LOAD("jp1005-19981209-315-6124-05.bin", 0x0000, 0x10000, CRC(47623324) SHA1(fca1aceff8a2f8c6826f3a865f4d5ef88dfd9ed1), ROM_BIOS(5)) + + // Version 1.005,1999/10/26,315-6208-04,SEGA Visual Memory System BIOS Produced by Sue + ROM_SYSTEM_BIOS(6, "jp1005b", "VMS Japanese BIOS (1.005 1999/10/26)") + ROMX_LOAD("jp1005-19991026-315-6208-04.bin", 0x0000, 0x10000, CRC(6cab02c2) SHA1(6cc2fbf4a67770988922117c300d006aa20899ac), ROM_BIOS(6)) // extracted with trojan + + // Version 1.004,1998/09/30,315-6208-01,SEGA Visual Memory System BIOS Produced by Sue + ROM_SYSTEM_BIOS(7, "dev1004", "VMS Japanese Development BIOS (1.004 1998/09/30)") // automatically boot the first game found in the flash + ROMX_LOAD( "jp1004-19980930-315-6208-01-dev.bin", 0x0000, 0x10000, CRC(395e25f2) SHA1(37dea034322b5b80b35b2de784298d32c71ba7a3), ROM_BIOS(7)) // from Sega Katana SDK (original file: qbios.sbf, CRC: eed5524c, xor key: 0x43) +ROM_END + + +/* Driver */ + +/* YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS */ +COMP( 1998, svmu, 0, 0, svmu, svmu, svmu_state, empty_init, "Sega", "Visual Memory Unit", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) diff --git a/src/mame/sega/system1.cpp b/src/mame/sega/system1.cpp index 78faadbfa1c..b996734243f 100644 --- a/src/mame/sega/system1.cpp +++ b/src/mame/sega/system1.cpp @@ -306,8 +306,7 @@ seem to have access to. #include "emu.h" #include "system1.h" -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "cpu/z80/mc8123.h" #include "sound/sn76496.h" diff --git a/src/mame/sega/system1.h b/src/mame/sega/system1.h index 8f4de2cfca7..8c73c21de14 100644 --- a/src/mame/sega/system1.h +++ b/src/mame/sega/system1.h @@ -10,7 +10,8 @@ #include "machine/z80pio.h" #include "machine/gen_latch.h" #include "machine/i8255.h" -#include "segacrp2_device.h" +#include "machine/segacrpt_device.h" +#include "machine/segacrp2_device.h" #include "machine/timer.h" #include "emupal.h" #include "screen.h" diff --git a/src/mame/sega/turbo.cpp b/src/mame/sega/turbo.cpp index a910d04423c..6c7cf360ddd 100644 --- a/src/mame/sega/turbo.cpp +++ b/src/mame/sega/turbo.cpp @@ -149,8 +149,7 @@ #include "emu.h" #include "turbo.h" -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "machine/74259.h" #include "machine/i8279.h" diff --git a/src/mame/sega/zaxxon.cpp b/src/mame/sega/zaxxon.cpp index 02538231aa7..fd1ad7164ad 100644 --- a/src/mame/sega/zaxxon.cpp +++ b/src/mame/sega/zaxxon.cpp @@ -257,9 +257,8 @@ #include "zaxxon.h" #include "segausb.h" -#include "segacrpt_device.h" - #include "cpu/z80/z80.h" +#include "machine/segacrpt_device.h" #include "machine/gen_latch.h" #include "machine/i8255.h" #include "sound/samples.h" diff --git a/src/mame/segacons/dccons.cpp b/src/mame/segacons/dccons.cpp deleted file mode 100644 index 3535c08dd09..00000000000 --- a/src/mame/segacons/dccons.cpp +++ /dev/null @@ -1,667 +0,0 @@ -// 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 "dccons.h" - -#include "dc-ctrl.h" - -#include "bus/ata/gdrom.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 "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 ) diff --git a/src/mame/segacons/dccons.h b/src/mame/segacons/dccons.h deleted file mode 100644 index 1bad460cd38..00000000000 --- a/src/mame/segacons/dccons.h +++ /dev/null @@ -1,60 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Angelo Salese, R. Belmont -#ifndef MAME_SEGACONS_DCCONS_H -#define MAME_SEGACONS_DCCONS_H - -#pragma once - -#include "dc.h" - -#include "bus/ata/ataintf.h" -#include "imagedev/chd_cd.h" -#include "machine/intelfsh.h" - -class dc_cons_state : public dc_state -{ -public: - dc_cons_state(const machine_config &mconfig, device_type type, const char *tag) - : dc_state(mconfig, type, tag) - , m_ata(*this, "ata") - , m_dcflash(*this, "dcflash") - , atapi_xfercomplete(0) - { } - - required_device m_ata; - required_device m_dcflash; - - void init_dc(); - void init_tream(); - - uint64_t dc_pdtra_r(); - void dc_pdtra_w(uint64_t data); - DECLARE_WRITE_LINE_MEMBER(aica_irq); - DECLARE_WRITE_LINE_MEMBER(sh4_aica_irq); - DECLARE_WRITE_LINE_MEMBER(ata_interrupt); - - TIMER_CALLBACK_MEMBER( atapi_xfer_end ); - - void dreamcast_atapi_init(); - uint32_t dc_mess_g1_ctrl_r(offs_t offset); - void dc_mess_g1_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint8_t dc_flash_r(offs_t offset); - void dc_flash_w(offs_t offset, uint8_t data); - - static void gdrom_config(device_t *device); - void dc_base(machine_config &config); - void dc(machine_config &config); - void dc_fish(machine_config &config); - void aica_map(address_map &map); - void dc_audio_map(address_map &map); - void dc_map(address_map &map); - void dc_port(address_map &map); -private: - uint32_t g1bus_regs[0x100/4]{}; // DC-only - - uint64_t PDTRA = 0U, PCTRA = 0U; - emu_timer *atapi_timer = nullptr; - int atapi_xferlen = 0, atapi_xferbase = 0, atapi_xfercomplete; -}; - -#endif // MAME_SEGACONS_DCCONS_H diff --git a/src/mame/segacons/dccons_m.cpp b/src/mame/segacons/dccons_m.cpp deleted file mode 100644 index a69834a46e3..00000000000 --- a/src/mame/segacons/dccons_m.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Angelo Salese, R. Belmont -/* - - dc.c - Sega Dreamcast hardware - - DC home console hardware overrides (GD-ROM drive etc) - - TODO: - - Convert to actual G1 I/F; - - gdrom_alt_status is identical to normal status except that "but it does not clear DMA status information when it is accessed"; - - Verify unimplemented behaviours via tests; - - Old notes, consultation only: - c230048 - 5 is written, want 6 - c0d9d9e - where bad happens, from routine @ c0da260 - - c0d9d8e - R0 on return is the value to put in - - cfffee0 - stack location when bad happens - -*/ - -#include "emu.h" -#include "dccons.h" - -#include "cdrom.h" -//#include "debugger.h" -#include "cpu/sh/sh4.h" -#include "sound/aica.h" - -// TODO: fine grain this value -#define ATAPI_CYCLES_PER_SECTOR (5000) - -#define LOG_WARN (1U << 1) -#define LOG_XFER (1U << 2) // log ATAPI transfers - -#define VERBOSE (LOG_WARN) -//#define LOG_OUTPUT_STREAM std::cout -#include "logmacro.h" - -#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) -#define LOGXFER(...) LOGMASKED(LOG_XFER, __VA_ARGS__) - -WRITE_LINE_MEMBER(dc_cons_state::ata_interrupt) -{ - if (state) - dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_GDROM; - else - dc_sysctrl_regs[SB_ISTEXT] &= ~IST_EXT_GDROM; - - dc_update_interrupt_status(); -} - -TIMER_CALLBACK_MEMBER(dc_cons_state::atapi_xfer_end ) -{ - uint8_t sector_buffer[ 4096 ]; - - atapi_timer->adjust(attotime::never); - - LOGXFER("atapi_xfer_end atapi_xferlen = %d\n", atapi_xferlen ); - - m_ata->write_dmack(1); - atapi_xfercomplete = 0; - - // TODO: dispatch transfers one step at a time instead of the full block - while (atapi_xferlen > 0 ) - { - struct sh4_ddt_dma ddtdata; - - // get a sector from the SCSI device - for (int i = 0; i < 2048 / 2; i++) - { - int d = m_ata->read_dma(); - sector_buffer[ i*2 ] = d & 0xff; - sector_buffer[ (i*2)+1 ] = d >> 8; - } - - atapi_xferlen -= 2048; - atapi_xfercomplete += 2048; - - // perform the DMA - ddtdata.destination = atapi_xferbase; // destination address - ddtdata.length = 2048 / 4; - ddtdata.size = 4; - ddtdata.buffer = sector_buffer; - ddtdata.direction = 1; // 0 source to buffer, 1 buffer to destination - ddtdata.channel = 0; - ddtdata.mode = -1; // copy from/to buffer - LOGXFER("G1 I/F ATAPI: DMA one sector to %x, %x remaining\n", - atapi_xferbase, atapi_xferlen - ); - m_maincpu->sh4_dma_ddt(&ddtdata); - - atapi_xferbase += 2048; - } - - m_ata->write_dmack(0); - - g1bus_regs[SB_GDST] = 0; - dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_GDROM; - dc_update_interrupt_status(); -} - -void dc_cons_state::dreamcast_atapi_init() -{ - atapi_timer = timer_alloc(FUNC(dc_cons_state::atapi_xfer_end), this); - atapi_timer->adjust(attotime::never); - save_item(NAME(atapi_xferlen)); - save_item(NAME(atapi_xferbase)); -} - -/* - - GDROM regsters: - - 5f7018: alternate status/device control - 5f7080: data - 5f7084: error/features - 5f7088: interrupt reason/sector count - 5f708c: sector number - 5f7090: byte control low - 5f7094: byte control high - 5f7098: drive select - 5f709c: status/command - -c002910 - ATAPI packet writes -c002796 - aux status read after that -c000776 - DMA triggered to c008000 - -*/ - -uint32_t dc_cons_state::dc_mess_g1_ctrl_r(offs_t offset) -{ - switch(offset) - { - case SB_GDSTARD: - // TODO: one of the Hello Kitty (identify which) reads there - logerror("G1CTRL: GDSTARD %08x\n", atapi_xferbase); - //machine().debug_break(); - return atapi_xferbase; - case SB_GDST: - break; - case SB_GDLEND: - //machine().debug_break(); - return atapi_xfercomplete; - case SB_SECUR_EADR: // always read 0xFF on hardware - return 0x000000ff; - case SB_SECUR_STATE: // state of BIOS checksum security system (R/O): - // 3 - check passed OK, G1 ATA (5F70xx) registers area accessible - // 2 - check failed, G1 ATA area blocked (read FFFFFFFFh) - // 0 - check in progress, BIOS data summed, G1 ATA area blocked (read FFFFFFFFh) - return 3; - default: - LOGWARN("G1CTRL: Unmapped read %08x\n", 0x5f7400 + offset * 4); - //machine().debug_break(); - break; - } - return g1bus_regs[offset]; -} - -void dc_cons_state::dc_mess_g1_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - g1bus_regs[offset] = data; // 5f7400+reg*4=dat -// osd_printf_verbose("G1CTRL: [%08x=%x] write %x to %x, mask %x\n", 0x5f7400+reg*4, dat, data, offset, mem_mask); - switch (offset) - { - case SB_GDST: - if (data & 1 && g1bus_regs[SB_GDEN] == 1) // 0 -> 1 - { - if (g1bus_regs[SB_GDDIR] == 0) - { - // TODO: write to GD-ROM, shouldn't happen unless "special" condition occurs - // (implies a debug/development device?) - LOGWARN("%s: G1 I/F illegal direction transfer\n", machine().describe_context()); - return; - } - - atapi_xferbase = g1bus_regs[SB_GDSTAR]; - //atapi_timer->adjust(m_maincpu->cycles_to_attotime((ATAPI_CYCLES_PER_SECTOR * (atapi_xferlen/2048)))); - /* 12x * 75 Hz = 0,00(1) secs per sector */ - /* TODO: make DMA to be single step */ - atapi_timer->adjust(attotime::from_usec(1111*atapi_xferlen/2048)); -// atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80; - } - break; - - case SB_GDLEN: - atapi_xferlen = data; - break; - -/* - The following register is involved in BIOS checksum protection system. - current understanding of its functioning based on several hardware tests: - - after power on security system is in state 0 (check in progress): - - access to G1 ATA register area (5F70XX) is blocked, ie GD-ROM in Dreamcast or cartridge/DIMM in arcade systems is not accessible; - - *any* data readed via G1 data bus (i.e. BIOS) is summed internally by chipset; - - write to SB_SECUR_EADR register set last address of checksummed area; - - then read address will match SB_SECUR_EADR - calculated summ compared with some hardcoded value - if values match - security system becomes in state 3 (check OK): - - G1 ATA registers area unlocked; - - can be switched back to state 0 by write to SB_SECUR_EADR register, Dreamcast BIOS write 42FEh before jump into Mil-CD executables - - if values doesn't match - security system switch to state 2 (check fail): - - G1 ATA locked - - can be switched to state 0 by write to SB_SECUR_EADR register, however passing valid data block through security system set it back to state 2 - - the only exit from this state - power off/on or reset; - - current state can be read from SB_SECUR_STATE register - actual checksum algorithm is unknown, but its supposed to be simple and weak, - known few modded BIOSes which succesfully passes this CRC check, because of good luck - - all described above works the same way in all HOLLY/CLX2-based systems - Dreamcast, Naomi 1/2, Atomiswave, SystemSP -*/ - case SB_SECUR_EADR: - if (data==0 || data==0x001fffff || data==0x42fe) - { - // atapi_regs[ATAPI_REG_SAMTAG] = GDROM_PAUSE_STATE | 0x80; - logerror("%s: Unlocking GD-ROM %x\n", machine().describe_context(), data); - } - break; - } -} diff --git a/src/mame/segacons/mdconsole.cpp b/src/mame/segacons/mdconsole.cpp deleted file mode 100644 index 0021f421f11..00000000000 --- a/src/mame/segacons/mdconsole.cpp +++ /dev/null @@ -1,1205 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood - -#include "emu.h" -#include "mdconsole.h" - -#include "bus/generic/carts.h" -#include "bus/generic/slot.h" -#include "imagedev/chd_cd.h" -#include "sound/sn76496.h" - -#include "softlist.h" - -#include "formats/imageutl.h" - - -/************************************* - * - * Input handlers - * - *************************************/ - -/* These overwrite the MAME ones in DRIVER_INIT */ -/* They're needed to give the users the choice between different controllers */ -uint8_t md_cons_state::mess_md_io_read_data_port(offs_t offset) -{ - int portnum = offset; - - uint8_t retdata; - int controller; - uint8_t helper_6b = (m_megadrive_io_ctrl_regs[portnum] & 0x3f) | 0xc0; // bits 6 & 7 always come from megadrive_io_data_regs - uint8_t helper_3b = (m_megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from megadrive_io_data_regs - - switch (portnum) - { - case 0: - controller = (m_io_ctrlr->read() & 0x0f); - break; - - case 1: - controller = (m_io_ctrlr->read() & 0xf0); - break; - - default: - controller = 0; - break; - } - - /* Are we using a 6 buttons Joypad? */ - if (controller) - { - if (m_megadrive_io_data_regs[portnum] & 0x40) - { - if (m_io_stage[portnum] == 2) - { - /* here we read B, C & the additional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - ((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0x30) | - ((m_io_pad6b[1][portnum] ? m_io_pad6b[1][portnum]->read() : 0) & 0x0f)) & ~helper_6b); - } - else - { - /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - (((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0x3f) & ~helper_6b); - } - } - else - { - if (m_io_stage[portnum] == 1) - { - /* here we read ((Start & A) >> 2) | 0x00 */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - ((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0xc0) >> 2) & ~helper_6b); - } - else if (m_io_stage[portnum]==2) - { - /* here we read ((Start & A) >> 2) | 0x0f */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - (((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0xc0) >> 2) | 0x0f) & ~helper_6b); - } - else - { - /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - (((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0xc0) >> 2) | - ((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0x03)) & ~helper_6b); - } - } - - // osd_printf_debug("read io data port stage %d port %d %02x\n",mess_io_stage[portnum],portnum,retdata); - - retdata |= (retdata << 8); - } - /* Otherwise it's a 3 buttons Joypad */ - else - { - uint8_t svp_test = 0; - if (m_cart) - svp_test = m_cart->read_test(); - - // handle test input for SVP test - if (portnum == 0 && svp_test) - { - retdata = (m_megadrive_io_data_regs[0] & 0xc0); - } - else if (m_megadrive_io_data_regs[portnum] & 0x40) - { - /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_3b) | - ((((m_io_pad3b[portnum] ? m_io_pad3b[portnum]->read() : 0) & 0x3f) | 0x40) & ~helper_3b); - } - else - { - /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_3b) | - (((((m_io_pad3b[portnum] ? m_io_pad3b[portnum]->read() : 0) & 0xc0) >> 2) | - ((m_io_pad3b[portnum] ? m_io_pad3b[portnum]->read() : 0) & 0x03) | 0x40) & ~helper_3b); - } - } - - return retdata; -} - - -void md_cons_state::mess_md_io_write_data_port(offs_t offset, uint16_t data) -{ - int portnum = offset; - int controller; - - switch (portnum) - { - case 0: - controller = (m_io_ctrlr->read() & 0x0f); - break; - - case 1: - controller = (m_io_ctrlr->read() & 0xf0); - break; - - default: - controller = 0; - break; - } - - if (controller) - { - if (m_megadrive_io_ctrl_regs[portnum] & 0x40) - { - if (((m_megadrive_io_data_regs[portnum] & 0x40) == 0x00) && ((data & 0x40) == 0x40)) - { - m_io_stage[portnum]++; - m_io_timeout[portnum]->adjust(m_maincpu->cycles_to_attotime(8192)); - } - - } - } - m_megadrive_io_data_regs[portnum] = data; - //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); -} - - -/************************************* - * - * Input ports - * - *************************************/ - - -static INPUT_PORTS_START( md_base ) - PORT_START("PAD1_3B") /* Joypad 1 (3 button + start) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - - PORT_START("PAD2_3B") /* Joypad 2 (3 button + start) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - - PORT_START("PAD1_6B") /* Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - - PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 Z") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 Y") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 X") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("P1 Mode") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - - PORT_START("PAD2_6B") /* Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - - PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 Z") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 Y") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 X") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("P2 Mode") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - - PORT_START("RESET") /* Buttons on Genesis Console */ - PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Reset Button") PORT_IMPULSE(1) // reset, resets 68k (and..?) -INPUT_PORTS_END - -static INPUT_PORTS_START( md ) - PORT_INCLUDE( md_base ) - - PORT_START("CTRLSEL") /* Controller selection */ - PORT_CONFNAME( 0x0f, 0x00, "Player 1 Controller" ) - PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) - PORT_CONFSETTING( 0x01, "Joystick 6 Buttons" ) -// PORT_CONFSETTING( 0x02, "Sega Mouse" ) -/* there exists both a 2 buttons version of the Mouse (Jpn ver, to be used with RPGs, it - can aslo be used as trackball) and a 3 buttons version (US ver, no trackball feats.) */ -// PORT_CONFSETTING( 0x03, "Sega Menacer" ) -// PORT_CONFSETTING( 0x04, "Konami Justifier" ) -// PORT_CONFSETTING( 0x05, "Team Player (Sega Multitap)" ) -// PORT_CONFSETTING( 0x06, "4-Play (EA Multitap)" ) -// PORT_CONFSETTING( 0x07, "J-Cart" ) - PORT_CONFNAME( 0xf0, 0x00, "Player 2 Controller" ) - PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) - PORT_CONFSETTING( 0x10, "Joystick 6 Buttons" ) -INPUT_PORTS_END - -static INPUT_PORTS_START( megajet ) - PORT_INCLUDE( md_base ) - - PORT_START("CTRLSEL") /* Fixed controller setting for Player 1 */ - PORT_CONFNAME( 0x0f, 0x01, "Player 1 Controller" ) // Fixed - PORT_CONFSETTING( 0x01, "Joystick 6 Buttons" ) - PORT_CONFNAME( 0xf0, 0x00, "Player 2 Controller" ) - PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) - PORT_CONFSETTING( 0x10, "Joystick 6 Buttons" ) -INPUT_PORTS_END - -static INPUT_PORTS_START( gen_nomd ) - PORT_INCLUDE( megajet ) - - PORT_MODIFY("RESET") /* No reset button */ - PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED ) -INPUT_PORTS_END - - -/************************************* - * - * Machine driver - * - *************************************/ - -void md_cons_state::machine_start() -{ - static const char *const pad6names[2][4] = { - { "PAD1_6B", "PAD2_6B", "UNUSED", "UNUSED" }, - { "EXTRA1", "EXTRA2", "UNUSED", "UNUSED" } - }; - static const char *const pad3names[4] = { "PAD1_3B", "PAD2_3B", "UNUSED", "UNUSED" }; - - m_io_ctrlr = ioport("CTRLSEL"); - - for (int i = 0; i < 4; i++) - { - m_io_pad3b[i] = ioport(pad3names[i]); - m_io_pad6b[0][i] = ioport(pad6names[0][i]); - m_io_pad6b[1][i] = ioport(pad6names[1][i]); - } - - // setup timers for 6 button pads - for (int i = 0; i < 3; i++) - m_io_timeout[i] = timer_alloc(FUNC(md_base_state::io_timeout_timer_callback), this); - - m_vdp->stop_timers(); - - if (m_cart) - m_cart->save_nvram(); - - if (m_z80snd) - m_genz80.z80_run_timer = timer_alloc(FUNC(md_base_state::megadriv_z80_run_state), this); -} - -void md_cons_state::install_cartslot() -{ - if (m_cart) - { - // for now m_cartslot is only in MD and not 32x and SegaCD - m_maincpu->space(AS_PROGRAM).install_read_handler(0x000000, 0x7fffff, read16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::read))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0x000000, 0x7fffff, write16s_delegate(*m_cart, FUNC(base_md_cart_slot_device::write))); - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa13000, 0xa130ff, read16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::read_a13)), write16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::write_a13))); - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa15000, 0xa150ff, read16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::read_a15)), write16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::write_a15))); -// m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14000, 0xa14003, write16sm_delegate(*m_cart, FUNC(base_md_cart_slot_device::write_tmss_bank))); - } -} - -uint16_t md_cons_state::tmss_r(offs_t offset) -{ - if (offset < 0x4000 / 2) - return m_tmss[offset]; - - return 0xffff; -} - -void md_cons_state::tmss_swap_w(uint16_t data) -{ - if (data & 0x0001) - { - install_cartslot(); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14100, 0xa14101, write16smo_delegate(*this, FUNC(md_cons_state::tmss_swap_w))); - } - else - { - install_tmss(); - } -} - - -void md_cons_state::install_tmss() -{ - m_maincpu->space(AS_PROGRAM).unmap_readwrite(0x000000, 0x7fffff); - m_maincpu->space(AS_PROGRAM).install_read_handler(0x000000, 0x7fffff, read16sm_delegate(*this, FUNC(md_cons_state::tmss_r))); - - m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14100, 0xa14101, write16smo_delegate(*this, FUNC(md_cons_state::tmss_swap_w))); - -} - - -void md_cons_slot_state::machine_start() -{ - md_cons_state::machine_start(); - - // the SVP introduces some kind of DMA 'lag', which we have to compensate for, this is obvious even on gfx DMAd from ROM (the Speedometer) - if (m_cart && (m_cart->get_type() == SEGA_SVP)) - m_vdp->set_dma_delay(2); - - if (m_tmss) - { - install_tmss(); - } - else - { - install_cartslot(); - } -} - -void md_cons_state::machine_reset() -{ - md_base_state::machine_reset(); - - // if the system has a 32x, pause the extra CPUs until they are actually turned on - if (m_32x) - m_32x->pause_cpu(); -} - -void md_cons_cd_state::machine_start() -{ - md_cons_state::machine_start(); - - // the segaCD introduces some kind of DMA 'lag', which we have to compensate for, - // at least when reading wordram? we might need to check what mode we're in the DMA... - m_vdp->set_dma_delay(2); -} - -// same as screen_eof_megadriv but with addition of 32x and SegaCD/MegaCD pieces -WRITE_LINE_MEMBER(md_cons_state::screen_vblank_console) -{ - if (m_io_reset.read_safe(0) & 0x01) - m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); - - // rising edge - if (state) - { - if (!m_vdp->m_use_alt_timing) - { - bool mode3 = (m_vdp->get_imode() == 3); - m_vdp->vdp_handle_eof(); - m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); - - if (m_32x) - m_32x->screen_eof(mode3); - - if (m_segacd) - m_segacd->update_total_scanlines(mode3); - } - } -} - -void md_cons_state::dcat16_megadriv_base(machine_config &config) -{ - md_ntsc(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::dcat16_megadriv_map); -} - -void md_cons_slot_state::ms_megadriv(machine_config &config) -{ - md_ntsc(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); - SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); -} - -void md_cons_slot_state::ms_megadpal(machine_config &config) -{ - md_pal(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); - SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); -} - -void md_cons_slot_state::ms_megadriv2(machine_config &config) -{ - md2_ntsc(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); - SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); -} - -void md_cons_slot_state::genesis_tmss(machine_config &config) -{ - ms_megadriv(config); - subdevice("cart_list")->set_filter("TMSS"); -} - -void md_cons_state::dcat16_megadriv(machine_config &config) -{ - dcat16_megadriv_base(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - -// has SD card slot instead? -// MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); -// SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); -} - -/************************************* - * - * ROM definition(s) - * - *************************************/ - - -/* we don't use the bios rom (it's not needed and only provides security on early models) */ - -ROM_START(genesis) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - -ROM_START(megadriv) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - -ROM_START(megadrij) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - -ROM_START(genesis_tmss) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) - - ROM_REGION16_BE(0x4000, "tmss", ROMREGION_ERASEFF) - ROM_LOAD( "tmss_usa.bin", 0x0000, 0x4000, CRC(5f5e64eb) SHA1(453fca4e1db6fae4a10657c4451bccbb71955628) ) -ROM_END - -ROM_START(dcat16) - ROM_REGION(0x800000, "maincpu", ROMREGION_ERASEFF) - ROM_LOAD16_WORD_SWAP( "mg6025.u1", 0x0000, 0x800000, CRC(5453d673) SHA1(b9f8d849cbed81fe73525229f4897ccaeeb7a833) ) - - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - -ROM_START(megajet) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - -ROM_START(gen_nomd) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - -/************************************* - * - * Driver initialization - * - *************************************/ - -void md_cons_state::init_mess_md_common() -{ - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_cons_state::mess_md_io_read_data_port)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_cons_state::mess_md_io_write_data_port)); -} - -void md_cons_state::init_genesis() -{ - init_megadriv(); - init_mess_md_common(); - - if (m_32x) - { - m_32x->set_32x_pal(false); - m_32x->set_framerate(60); - m_32x->set_total_scanlines(262); - } - if (m_segacd) - { - m_segacd->set_framerate(60); - m_segacd->set_total_scanlines(262); - } - - m_version_hi_nibble = 0x80; // Export NTSC - if (!m_segacd) - m_version_hi_nibble |= 0x20; -} - -void md_cons_state::init_md_eur() -{ - init_megadrie(); - init_mess_md_common(); - - if (m_32x) - { - m_32x->set_32x_pal(true); - m_32x->set_framerate(50); - m_32x->set_total_scanlines(313); - } - if (m_segacd) - { - m_segacd->set_framerate(50); - m_segacd->set_total_scanlines(313); - } - - m_version_hi_nibble = 0xc0; // Export PAL - if (!m_segacd) - m_version_hi_nibble |= 0x20; -} - -void md_cons_state::init_md_jpn() -{ - init_megadrij(); - init_mess_md_common(); - - if (m_32x) - { - m_32x->set_32x_pal(false); - m_32x->set_framerate(60); - m_32x->set_total_scanlines(262); - } - if (m_segacd) - { - m_segacd->set_framerate(60); - m_segacd->set_total_scanlines(262); - } - - m_version_hi_nibble = 0x00; // JPN NTSC - if (!m_segacd) - m_version_hi_nibble |= 0x20; -} - -/****************************************** 32X emulation ****************************************/ - -DEVICE_IMAGE_LOAD_MEMBER( md_cons_state::_32x_cart ) -{ - uint32_t length; - std::vector temp_copy; - uint16_t *ROM16; - uint32_t *ROM32; - int i; - - if (!image.loaded_through_softlist()) - { - length = image.length(); - temp_copy.resize(length); - image.fread(&temp_copy[0], length); - } - else - { - length = image.get_software_region_length("rom"); - temp_copy.resize(length); - memcpy(&temp_copy[0], image.get_software_region("rom"), length); - } - - /* Copy the cart image in the locations the driver expects */ - // Notice that, by using pick_integer, we are sure the code works on both LE and BE machines - ROM16 = (uint16_t *) memregion("gamecart")->base(); - for (i = 0; i < length; i += 2) - ROM16[i / 2] = pick_integer_be(&temp_copy[0], i, 2); - - ROM32 = (uint32_t *) memregion("gamecart_sh2")->base(); - for (i = 0; i < length; i += 4) - ROM32[i / 4] = pick_integer_be(&temp_copy[0], i, 4); - - ROM16 = (uint16_t *) memregion("maincpu")->base(); - for (i = 0x00; i < length; i += 2) - ROM16[i / 2] = pick_integer_be(&temp_copy[0], i, 2); - - return image_init_result::PASS; -} - - -void md_cons_state::_32x_scanline_callback(int x, uint32_t priority, uint32_t &lineptr) -{ - if (m_32x) - m_32x->render_videobuffer_to_screenbuffer(x, priority, lineptr); -} - -void md_cons_state::_32x_interrupt_callback(int scanline, int irq6) -{ - if (m_32x) - m_32x->interrupt_cb(scanline, irq6); -} - -void md_cons_state::_32x_scanline_helper_callback(int scanline) -{ - if (m_32x) - m_32x->render_videobuffer_to_screenbuffer_helper(scanline); -} - -void md_cons_state::genesis_32x(machine_config &config) -{ - md_ntsc(config); - - m_vdp->set_md_32x_scanline(FUNC(md_cons_state::_32x_scanline_callback)); - m_vdp->set_md_32x_scanline_helper(FUNC(md_cons_state::_32x_scanline_helper_callback)); - m_vdp->set_md_32x_interrupt(FUNC(md_cons_state::_32x_interrupt_callback)); - m_vdp->reset_routes(); - m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.50)/2); - m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.50)/2); - - SEGA_32X_NTSC(config, m_32x, (MASTER_CLOCK_NTSC * 3) / 7, m_maincpu, m_scan_timer); - m_32x->set_screen("megadriv"); - m_32x->add_route(0, "lspeaker", 1.00); - m_32x->add_route(1, "rspeaker", 1.00); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - // we need to remove and re-add the YM because the balance is different - // due to MAME having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!) - m_ymsnd->reset_routes(); - m_ymsnd->add_route(0, "lspeaker", (0.50)/2); - m_ymsnd->add_route(1, "rspeaker", (0.50)/2); - - generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin")); - cartslot.set_must_be_loaded(true); - cartslot.set_device_load(FUNC(md_cons_state::_32x_cart)); - - SOFTWARE_LIST(config, "cart_list").set_original("32x").set_filter("NTSC-U"); -} - - -void md_cons_state::mdj_32x(machine_config &config) -{ - md_ntsc(config); - - m_vdp->set_md_32x_scanline(FUNC(md_cons_state::_32x_scanline_callback)); - m_vdp->set_md_32x_scanline_helper(FUNC(md_cons_state::_32x_scanline_helper_callback)); - m_vdp->set_md_32x_interrupt(FUNC(md_cons_state::_32x_interrupt_callback)); - m_vdp->reset_routes(); - m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.50)/2); - m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.50)/2); - - SEGA_32X_NTSC(config, m_32x, (MASTER_CLOCK_NTSC * 3) / 7, m_maincpu, m_scan_timer); - m_32x->set_screen("megadriv"); - m_32x->add_route(0, "lspeaker", 1.00); - m_32x->add_route(1, "rspeaker", 1.00); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - // we need to remove and re-add the sound system because the balance is different - // due to MAME having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!) - m_ymsnd->reset_routes(); - m_ymsnd->add_route(0, "lspeaker", (0.50)/2); - m_ymsnd->add_route(1, "rspeaker", (0.50)/2); - - generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin")); - cartslot.set_must_be_loaded(true); - cartslot.set_device_load(FUNC(md_cons_state::_32x_cart)); - - SOFTWARE_LIST(config, "cart_list").set_original("32x").set_filter("NTSC-J"); -} - - -void md_cons_state::md_32x(machine_config &config) -{ - md_pal(config); - - m_vdp->set_md_32x_scanline(FUNC(md_cons_state::_32x_scanline_callback)); - m_vdp->set_md_32x_scanline_helper(FUNC(md_cons_state::_32x_scanline_helper_callback)); - m_vdp->set_md_32x_interrupt(FUNC(md_cons_state::_32x_interrupt_callback)); - m_vdp->reset_routes(); - m_vdp->add_route(ALL_OUTPUTS, "lspeaker", (0.50)/2); - m_vdp->add_route(ALL_OUTPUTS, "rspeaker", (0.50)/2); - - SEGA_32X_PAL(config, m_32x, (MASTER_CLOCK_PAL * 3) / 7, m_maincpu, m_scan_timer); - m_32x->set_screen("megadriv"); - m_32x->add_route(0, "lspeaker", 1.00); - m_32x->add_route(1, "rspeaker", 1.00); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - // we need to remove and re-add the sound system because the balance is different - // due to MAME having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!) - m_ymsnd->reset_routes(); - m_ymsnd->add_route(0, "lspeaker", (0.50)/2); - m_ymsnd->add_route(1, "rspeaker", (0.50)/2); - - generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin")); - cartslot.set_must_be_loaded(true); - cartslot.set_device_load(FUNC(md_cons_state::_32x_cart)); - - SOFTWARE_LIST(config, "cart_list").set_original("32x").set_filter("PAL"); -} - - - -#define _32X_ROMS \ - ROM_REGION16_BE( 0x400000, "gamecart", ROMREGION_ERASE00 ) /* 68000 Code */ \ - ROM_REGION32_BE( 0x400000, "gamecart_sh2", ROMREGION_ERASE00 ) /* Copy for the SH2 */ \ - ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ \ - ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) \ - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) \ - /* temp, rom should only be visible here when one of the regs is set, tempo needs it */ \ - ROM_COPY( "32x_68k_bios", 0x0, 0x0, 0x100) \ - ROM_REGION32_BE( 0x400000, "master", 0 ) /* SH2 Code */ \ - ROM_SYSTEM_BIOS( 0, "retail", "Mars Version 1.0 (retail)" ) \ - ROMX_LOAD( "32x_m_bios.bin", 0x000000, 0x000800, CRC(dd9c46b8) SHA1(1e5b0b2441a4979b6966d942b20cc76c413b8c5e), ROM_BIOS(0) ) \ - ROM_SYSTEM_BIOS( 1, "sdk", "Mars Version 1.0 (early sdk)" ) \ - ROMX_LOAD( "32x_m_bios_sdk.bin", 0x000000, 0x000800, BAD_DUMP CRC(c7102c53) SHA1(ed73a47f186b373b8eff765f84ef26c3d9ef6cb0), ROM_BIOS(1) ) \ - ROM_REGION32_BE( 0x400000, "slave", 0 ) /* SH2 Code */ \ - ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) - -ROM_START( 32x ) - _32X_ROMS -ROM_END - -ROM_START( 32xe ) - _32X_ROMS -ROM_END - -ROM_START( 32xj ) - _32X_ROMS -ROM_END - - -/****************************************** SegaCD emulation ****************************************/ - -void md_cons_cd_state::genesis_scd(machine_config &config) -{ - md_ntsc(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - SEGA_SEGACD_US(config, m_segacd, 0); - m_segacd->set_palette("gen_vdp:gfx_palette"); - m_segacd->set_hostcpu(m_maincpu); - m_segacd->set_screen("megadriv"); - - config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu - - CDROM(config, "cdrom").set_interface("scd_cdrom"); - - SOFTWARE_LIST(config, "cd_list").set_original("segacd"); -} - -void md_cons_cd_state::genesis2_scd(machine_config &config) -{ - md2_ntsc(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - SEGA_SEGACD_US(config, m_segacd, 0); - m_segacd->set_palette("gen_vdp:gfx_palette"); - m_segacd->set_hostcpu(m_maincpu); - m_segacd->set_screen("megadriv"); - - config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu - - CDROM(config, "cdrom").set_interface("scd_cdrom"); - - SOFTWARE_LIST(config, "cd_list").set_original("segacd"); -} - -void md_cons_cd_state::md_scd(machine_config &config) -{ - md_pal(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - SEGA_SEGACD_EUROPE(config, m_segacd, 0); - m_segacd->set_palette("gen_vdp:gfx_palette"); - m_segacd->set_hostcpu(m_maincpu); - m_segacd->set_screen("megadriv"); - - config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu - - CDROM(config, "cdrom").set_interface("scd_cdrom"); - - SOFTWARE_LIST(config, "cd_list").set_original("megacd"); -} - -void md_cons_cd_state::md2_scd(machine_config &config) -{ - md2_pal(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - SEGA_SEGACD_EUROPE(config, m_segacd, 0); - m_segacd->set_palette("gen_vdp:gfx_palette"); - m_segacd->set_hostcpu(m_maincpu); - m_segacd->set_screen("megadriv"); - - config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu - - CDROM(config, "cdrom").set_interface("scd_cdrom"); - - SOFTWARE_LIST(config, "cd_list").set_original("megacd"); -} - -void md_cons_cd_state::mdj_scd(machine_config &config) -{ - md_ntsc(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - SEGA_SEGACD_JAPAN(config, m_segacd, 0); - m_segacd->set_palette("gen_vdp:gfx_palette"); - m_segacd->set_hostcpu(m_maincpu); - m_segacd->set_screen("megadriv"); - - config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu - - CDROM(config, "cdrom").set_interface("scd_cdrom"); - - SOFTWARE_LIST(config, "cd_list").set_original("megacdj"); -} - -void md_cons_cd_state::md2j_scd(machine_config &config) -{ - md2_ntsc(config); - - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); - - SEGA_SEGACD_JAPAN(config, m_segacd, 0); - m_segacd->set_palette("gen_vdp:gfx_palette"); - m_segacd->set_hostcpu(m_maincpu); - m_segacd->set_screen("megadriv"); - - config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu - - CDROM(config, "cdrom").set_interface("scd_cdrom"); - - SOFTWARE_LIST(config, "cd_list").set_original("megacdj"); -} - -/******************SEGA CD + 32X****************************/ - -void md_cons_cd_state::genesis_32x_scd(machine_config &config) -{ - genesis_32x(config); - - SEGA_SEGACD_US(config, m_segacd, 0); - m_segacd->set_palette("gen_vdp:gfx_palette"); - m_segacd->set_hostcpu(m_maincpu); - m_segacd->set_screen("megadriv"); - - config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu - - CDROM(config, "cdrom").set_interface("scd_cdrom"); - - config.device_remove("cartslot"); - GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_state::_32x_cart)); - - //config.m_perfect_cpu_quantum = subtag("32x_master_sh2"); - SOFTWARE_LIST(config, "cd_list").set_original("segacd"); -} - -void md_cons_cd_state::md_32x_scd(machine_config &config) -{ - md_32x(config); - - SEGA_SEGACD_EUROPE(config, m_segacd, 0); - m_segacd->set_palette("gen_vdp:gfx_palette"); - m_segacd->set_hostcpu(m_maincpu); - m_segacd->set_screen("megadriv"); - - config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu - - CDROM(config, "cdrom").set_interface("scd_cdrom"); - - config.device_remove("cartslot"); - GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_state::_32x_cart)); - - //config.m_perfect_cpu_quantum = subtag("32x_master_sh2"); - SOFTWARE_LIST(config, "cd_list").set_original("megacd"); -} - -void md_cons_cd_state::mdj_32x_scd(machine_config &config) -{ - mdj_32x(config); - - SEGA_SEGACD_JAPAN(config, m_segacd, 0); - m_segacd->set_palette("gen_vdp:gfx_palette"); - m_segacd->set_hostcpu(m_maincpu); - m_segacd->set_screen("megadriv"); - - config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu - - CDROM(config, "cdrom").set_interface("scd_cdrom"); - - config.device_remove("cartslot"); - GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_state::_32x_cart)); - - //config.m_perfect_cpu_quantum = subtag("32x_master_sh2"); - SOFTWARE_LIST(config, "cd_list").set_original("megacdj"); -} - -/* We need proper names for most of these BIOS ROMs! */ -ROM_START( segacd ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - /* v1.10 confirmed dump by dead_screem */ - ROM_LOAD( "mpr-15045b.bin", 0x000000, 0x020000, CRC(c6d10268) SHA1(f4f315adcef9b8feb0364c21ab7f0eaf5457f3ed) ) -ROM_END - -ROM_START( megacd ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - /* v1.00, confirmed good dump */ - ROM_LOAD( "megacd_model1_bios_1_00_e.bin", 0x000000, 0x020000, CRC(529ac15a) SHA1(f891e0ea651e2232af0c5c4cb46a0cae2ee8f356) ) -ROM_END - -ROM_START( megacdj ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - ROM_DEFAULT_BIOS("v100g") // this seems the only revision where the cursor in CD menu works, allowing to boot games - /* Confirmed by ElBarto */ - ROM_SYSTEM_BIOS(0, "v100s", "v1.00S") - ROMX_LOAD( "mpr-14088h.bin", 0x000000, 0x020000, CRC(3773d5aa) SHA1(bbf729a1aaa1667b783749299e1ad932aaf5f253), ROM_BIOS(0) | ROM_GROUPWORD | ROM_REVERSE) - /* Confirmed by ElBarto */ - ROM_SYSTEM_BIOS(1, "v100g", "v1.00G") - ROMX_LOAD( "epr-14088b.bin", 0x000000, 0x020000, CRC(69ed6ccd) SHA1(27d11c3836506f01ee81cd142c0cd8b51abebbd2), ROM_BIOS(1) | ROM_GROUPWORD | ROM_REVERSE) - /* Confirmed by ElBarto */ - ROM_SYSTEM_BIOS(2, "v100l", "v1.00L") - ROMX_LOAD( "mpr-14088c.bin", 0x000000, 0x020000, CRC(03134289) SHA1(d60cb5a53f26d6b13e354bc149217587f2301718), ROM_BIOS(2) | ROM_GROUPWORD | ROM_REVERSE) - /* Confirmed by ElBarto */ - ROM_SYSTEM_BIOS(3, "v100o", "v1.00O") - ROMX_LOAD( "epr-14088d.bin", 0x000000, 0x020000, CRC(dfa95ee9) SHA1(e13666c76fa0a2e94e2f651b26b0fd625bf55f07), ROM_BIOS(3) | ROM_GROUPWORD | ROM_REVERSE) - ROM_SYSTEM_BIOS(4, "v100p", "v1.00P") // CRC: e2e70bc8 when byteswapped - ROMX_LOAD( "epr-14088e.bin", 0x000000, 0x020000, CRC(9d2da8f2) SHA1(4846f448160059a7da0215a5df12ca160f26dd69), ROM_BIOS(4) ) - // EEPROM had no SEGA's label, might be 14088(no rev) or 14088A - ROM_SYSTEM_BIOS(5, "v100c", "v1.00C") // CRC: c3b60c13 when byteswapped - ROMX_LOAD( "100c.bin", 0x000000, 0x020000, CRC(41af44c4) SHA1(f30d109d1c2f7c9feaf38600c65834261db73d1f), ROM_BIOS(5) ) - ROM_SYSTEM_BIOS(6, "v111", "v1.11") // CRC: e0a6179b when byteswapped - ROMX_LOAD( "mpr-14837.bin", 0x000000, 0x020000, CRC(4be18ff6) SHA1(204758d5a64c24e96e1a9fe6bd82e1878fef7ade), ROM_BIOS(6) ) -ROM_END - -/* Asia bios, when run in USA region will show : -ERROR! -THIS IS A PAL-COMPATIBLE MEGA CD -FOR EXCLUSIVE USE IN SOUTHEAST ASIA. - -Confirmed by Jakovasaur -*/ -ROM_START( megacda ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - ROM_LOAD( "epr-14536h.bin", 0x000000, 0x020000, CRC(550f30bb) SHA1(e4193c6ae44c3cea002707d2a88f1fbcced664de)) -ROM_END - -ROM_START( segacd2 ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - ROM_SYSTEM_BIOS(0, "v211x", "Model 2 v2.11X") - ROMX_LOAD( "mpr-15764-t.bin", 0x000000, 0x020000, CRC(2e49d72c) SHA1(328a3228c29fba244b9db2055adc1ec4f7a87e6b), ROM_BIOS(0) ) - ROM_SYSTEM_BIOS(1, "v200", "Model 2 v2.00") /* verified dump */ - ROMX_LOAD( "us_scd2_930314.bin", 0x000000, 0x020000, CRC(8af65f58) SHA1(5a8c4b91d3034c1448aac4b5dc9a6484fce51636), ROM_BIOS(1) ) - /* this is reportedly a bad dump, it has many differences from the verified dump and does not boot in Kega */ - /* ROMX_LOAD( "segacd_model2_bios_2_00_u.bin", 0x000000, 0x020000, CRC(340b4be4) SHA1(bd3ee0c8ab732468748bf98953603ce772612704), ROM_BIOS(1) ) */ - ROM_SYSTEM_BIOS(2, "v200w", "Model 2 v2.00W") - ROMX_LOAD( "segacd_model2_bios_2_00w_u.bin", 0x000000, 0x020000, CRC(9f6f6276) SHA1(5adb6c3af218c60868e6b723ec47e36bbdf5e6f0), ROM_BIOS(2) ) -ROM_END - -/* v2.00, v2.00w confirmed good dumps by ElBarto */ -/* v2.11x confirmed good dump by TwistedTom */ -ROM_START( megacd2 ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - ROM_SYSTEM_BIOS(0, "v211x", "v2.11X") // MK-4102A-50 Sony pcb - ROMX_LOAD( "mpr-15811-t.bin", 0x000000, 0x020000, CRC(391a80d2) SHA1(aa4bb1803b06714fbc04d8a209161876796dd511), ROM_BIOS(0) | ROM_GROUPWORD | ROM_REVERSE ) - ROM_SYSTEM_BIOS(1, "v200w", "v2.00W") // MK-4102-50 Funai pcb - ROMX_LOAD( "mpr-15512a.bin", 0x000000, 0x020000, CRC(53f1757c) SHA1(67bf3970ca5a05fd5ce3d6c446789c5d971b98a4), ROM_BIOS(1) | ROM_GROUPWORD | ROM_REVERSE ) - ROM_SYSTEM_BIOS(2, "v200", "v2.00") // ? - ROMX_LOAD( "mpr-15512.bin", 0x000000, 0x020000, CRC(cb76f114) SHA1(939f173cadc41e996a3c34498da1bf55e7e18ff8), ROM_BIOS(2) | ROM_GROUPWORD | ROM_REVERSE ) -ROM_END - -/* Confirmed good dump by ElBarto */ -ROM_START( megacd2j ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - ROM_SYSTEM_BIOS(0, "v200c", "v2.00C") - ROMX_LOAD( "mpr-15398.bin", 0x000000, 0x020000, CRC(1e4344e6) SHA1(4d1251a6973d932e734ae5e8c6b9b55eb40e4143), ROM_BIOS(0) | ROM_GROUPWORD | ROM_REVERSE ) -ROM_END - -ROM_START( aiwamcd ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - /* v2.11 */ - ROM_LOAD( "mpr-15768-t.bin", 0x000000, 0x020000, CRC(8052c7a0) SHA1(219d284dcf63ce366a4dc6d1ff767a0d2eea283d) ) -ROM_END - -ROM_START( laseract ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - ROM_SYSTEM_BIOS(0, "v104", "v1.04") - ROMX_LOAD( "laseractive_bios_1_04_u.bin", 0x000000, 0x020000, CRC(50cd3d23) SHA1(aa811861f8874775075bd3f53008c8aaf59b07db), ROM_BIOS(0) ) - ROM_SYSTEM_BIOS(1, "v102", "v1.02") - ROMX_LOAD( "laseractive_bios_1_02_u.bin", 0x000000, 0x020000, CRC(3b10cf41) SHA1(8af162223bb12fc19b414f126022910372790103), ROM_BIOS(1) ) -ROM_END - -ROM_START( laseractj ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - ROM_SYSTEM_BIOS(0, "v105", "v1.05") - ROMX_LOAD( "mega-ld 1.05 bios.bin", 0x000000, 0x020000, CRC(474aaa44) SHA1(b3b1d880e288b6dc79eec0ff1b0480c229ec141d), ROM_BIOS(0) ) - ROM_SYSTEM_BIOS(1, "v102", "v1.02") - ROMX_LOAD( "laseractive_bios_1_02_j.bin", 0x000000, 0x020000, CRC(00eedb3a) SHA1(26237b333db4a4c6770297fa5e655ea95840d5d9), ROM_BIOS(1) ) -ROM_END - -ROM_START( xeye ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - /* v2.00 (US), confirmed good with a chip dump */ - ROM_LOAD( "g304.bin", 0x000000, 0x020000, CRC(290f8e33) SHA1(651f14d5a5e0ecb974a60c0f43b1d2006323fb09) ) -ROM_END - -ROM_START( wmega ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - /* v1.00 (Japan NTSC) Sega BIOS, chip-dumped */ - ROM_LOAD( "g301.bin", 0x000000, 0x020000, CRC(d21fe71d) SHA1(3fc9358072f74bd24e3e297ea11b2bf15a7af891) ) -ROM_END - -ROM_START( wmegam2 ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - /* v2.00 */ - ROM_LOAD( "wondermega_m2_bios_2_00_j.bin", 0x000000, 0x020000, CRC(2b19972f) SHA1(b3f32e409bd5508c89ed8be33d41a58d791d0e5d) ) -ROM_END - -ROM_START( cdx ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - /* v2.21X */ - ROM_LOAD( "segacdx_bios_2_21_u.bin", 0x000000, 0x020000, CRC(d48c44b5) SHA1(2b125c0545afa089b617f2558e686ea723bdc06e) ) -ROM_END - -ROM_START( multmega ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - /* v2.21X */ - ROM_LOAD( "opr-16140.bin", 0x000000, 0x020000, CRC(aacb851e) SHA1(75548ac9aaa6e81224499f9a1403b2b42433f5b7) ) - /* the below was marked "confirmed good dump", but 0x72 and 0x73 are 0xFF, indicating a bad dump made from memory */ - /* ROM_LOAD( "multimega_bios_2_21_e.bin", 0x000000, 0x020000, CRC(34d3cce1) SHA1(73fc9c014ad803e9e7d8076b3642a8a5224b3e51) ) */ -ROM_END - -/* some games use the 32x and SegaCD together to give better quality FMV */ -ROM_START( 32x_scd ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - - ROM_REGION16_BE( 0x400000, "gamecart", 0 ) /* 68000 Code */ - ROM_LOAD( "mpr-15764-t.bin", 0x000000, 0x020000, CRC(2e49d72c) SHA1(328a3228c29fba244b9db2055adc1ec4f7a87e6b) ) - - ROM_REGION32_BE( 0x400000, "gamecart_sh2", 0 ) /* Copy for the SH2 */ - ROM_COPY( "gamecart", 0x000000, 0x0, 0x400000) - - ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ - ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) - - ROM_REGION32_BE( 0x400000, "master", 0 ) /* SH2 Code */ - ROM_LOAD( "32x_m_bios.bin", 0x000000, 0x000800, CRC(dd9c46b8) SHA1(1e5b0b2441a4979b6966d942b20cc76c413b8c5e) ) - - ROM_REGION32_BE( 0x400000, "slave", 0 ) /* SH2 Code */ - ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) -ROM_END - -ROM_START( 32x_mcd ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - - ROM_REGION16_BE( 0x400000, "gamecart", 0 ) /* 68000 Code */ - ROM_LOAD( "megacd_model1_bios_1_00_e.bin", 0x000000, 0x020000, CRC(529ac15a) SHA1(f891e0ea651e2232af0c5c4cb46a0cae2ee8f356) ) - - ROM_REGION32_BE( 0x400000, "gamecart_sh2", 0 ) /* Copy for the SH2 */ - ROM_COPY( "gamecart", 0x000000, 0x0, 0x400000) - - ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ - ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) - - ROM_REGION32_BE( 0x400000, "master", 0 ) /* SH2 Code */ - ROM_LOAD( "32x_m_bios.bin", 0x000000, 0x000800, CRC(dd9c46b8) SHA1(1e5b0b2441a4979b6966d942b20cc76c413b8c5e) ) - - ROM_REGION32_BE( 0x400000, "slave", 0 ) /* SH2 Code */ - ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) -ROM_END - -ROM_START( 32x_mcdj ) - ROM_REGION16_BE( 0x400000, "maincpu", ROMREGION_ERASE00 ) - - ROM_REGION16_BE( 0x400000, "gamecart", 0 ) /* 68000 Code */ - ROM_DEFAULT_BIOS("v100g") // this seems the only revision where the cursor in CD menu works, allowing to boot games - /* Confirmed by ElBarto */ - ROM_SYSTEM_BIOS(0, "v100s", "v1.00S") - ROMX_LOAD( "mpr-14088h.bin", 0x000000, 0x020000, CRC(3773d5aa) SHA1(bbf729a1aaa1667b783749299e1ad932aaf5f253), ROM_BIOS(0) | ROM_GROUPWORD | ROM_REVERSE) - /* Confirmed by ElBarto */ - ROM_SYSTEM_BIOS(1, "v100g", "v1.00G") - ROMX_LOAD( "epr-14088b.bin", 0x000000, 0x020000, CRC(69ed6ccd) SHA1(27d11c3836506f01ee81cd142c0cd8b51abebbd2), ROM_BIOS(1) | ROM_GROUPWORD | ROM_REVERSE) - /* Confirmed by ElBarto */ - ROM_SYSTEM_BIOS(2, "v100l", "v1.00L") - ROMX_LOAD( "mpr-14088c.bin", 0x000000, 0x020000, CRC(03134289) SHA1(d60cb5a53f26d6b13e354bc149217587f2301718), ROM_BIOS(2) | ROM_GROUPWORD | ROM_REVERSE) - /* Confirmed by ElBarto */ - ROM_SYSTEM_BIOS(3, "v100o", "v1.00O") - ROMX_LOAD( "epr-14088d.bin", 0x000000, 0x020000, CRC(dfa95ee9) SHA1(e13666c76fa0a2e94e2f651b26b0fd625bf55f07), ROM_BIOS(3) | ROM_GROUPWORD | ROM_REVERSE) - ROM_SYSTEM_BIOS(4, "v100p", "v1.00P") // CRC: e2e70bc8 when byteswapped - ROMX_LOAD( "epr-14088e.bin", 0x000000, 0x020000, CRC(9d2da8f2) SHA1(4846f448160059a7da0215a5df12ca160f26dd69), ROM_BIOS(4) ) - - ROM_REGION32_BE( 0x400000, "gamecart_sh2", 0 ) /* Copy for the SH2 */ - ROM_COPY( "gamecart", 0x000000, 0x0, 0x400000) - - ROM_REGION16_BE( 0x400000, "32x_68k_bios", 0 ) /* 68000 Code */ - ROM_LOAD( "32x_g_bios.bin", 0x000000, 0x000100, CRC(5c12eae8) SHA1(dbebd76a448447cb6e524ac3cb0fd19fc065d944) ) - - ROM_REGION32_BE( 0x400000, "master", 0 ) /* SH2 Code */ - ROM_LOAD( "32x_m_bios.bin", 0x000000, 0x000800, CRC(dd9c46b8) SHA1(1e5b0b2441a4979b6966d942b20cc76c413b8c5e) ) - - ROM_REGION32_BE( 0x400000, "slave", 0 ) /* SH2 Code */ - ROM_LOAD( "32x_s_bios.bin", 0x000000, 0x000400, CRC(bfda1fe5) SHA1(4103668c1bbd66c5e24558e73d4f3f92061a109a) ) -ROM_END - - - -/*************************************************************************** - - Game driver(s) - -***************************************************************************/ - -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */ -CONS( 1989, genesis, 0, 0, ms_megadriv, md, md_cons_slot_state, init_genesis, "Sega", "Genesis (USA, NTSC)", MACHINE_SUPPORTS_SAVE ) -CONS( 1990, megadriv, genesis, 0, ms_megadpal, md, md_cons_slot_state, init_md_eur, "Sega", "Mega Drive (Europe, PAL)", MACHINE_SUPPORTS_SAVE ) -CONS( 1988, megadrij, genesis, 0, ms_megadriv, md, md_cons_slot_state, init_md_jpn, "Sega", "Mega Drive (Japan, NTSC)", MACHINE_SUPPORTS_SAVE ) - -// 1990+ models had the TMSS security chip, leave this as a clone, it reduces compatibility and nothing more. -CONS( 1990, genesis_tmss, genesis, 0, genesis_tmss, md, md_cons_slot_state, init_genesis, "Sega", "Genesis (USA, NTSC, with TMSS chip)", MACHINE_SUPPORTS_SAVE ) - -// the 32X plugged in the cart slot, games plugged into the 32x. Maybe it should be handled as an expansion device? -CONS( 1994, 32x, 0, 0, genesis_32x, md, md_cons_state, init_genesis, "Sega", "Genesis with 32X (USA, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1994, 32xe, 32x, 0, md_32x, md, md_cons_state, init_md_eur, "Sega", "Mega Drive with 32X (Europe, PAL)", MACHINE_NOT_WORKING ) -CONS( 1994, 32xj, 32x, 0, mdj_32x, md, md_cons_state, init_md_jpn, "Sega", "Mega Drive with 32X (Japan, NTSC)", MACHINE_NOT_WORKING ) - -// the SegaCD plugged into the expansion port.. -CONS( 1992, segacd, 0, 0, genesis_scd, md, md_cons_cd_state, init_genesis, "Sega", "Sega CD (USA, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1993, megacd, segacd, 0, md_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Mega-CD (Europe, PAL)", MACHINE_NOT_WORKING ) -CONS( 1991, megacdj, segacd, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "Sega", "Mega-CD (Japan, NTSC)", MACHINE_NOT_WORKING ) // this bios doesn't work with our ram interleave needed by a few games?! -CONS( 1991, megacda, segacd, 0, md_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Mega-CD (Asia, PAL)", MACHINE_NOT_WORKING ) -CONS( 1993, segacd2, 0, 0, genesis_scd, md, md_cons_cd_state, init_genesis, "Sega", "Sega CD 2 (USA, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1993, megacd2, segacd2, 0, md_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Mega-CD 2 (Europe, PAL)", MACHINE_NOT_WORKING ) -CONS( 1993, megacd2j, segacd2, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "Sega", "Mega-CD 2 (Japan, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1994, aiwamcd, segacd2, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "AIWA", "Mega-CD CSD-G1M (Japan, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1993, xeye, 0, 0, genesis2_scd, md, md_cons_cd_state, init_genesis, "JVC", "X'eye (USA, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1992, wmega, xeye, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "Sega", "Wondermega (Japan, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1993, wmegam2, xeye, 0, md2j_scd, md, md_cons_cd_state, init_md_jpn, "Victor", "Wondermega M2 (Japan, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1994, cdx, 0, 0, genesis2_scd, md, md_cons_cd_state, init_genesis, "Sega", "CDX (USA, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1994, multmega, cdx, 0, md2_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Multi-Mega (Europe, PAL)", MACHINE_NOT_WORKING ) - -//32X plugged in the cart slot + SegaCD plugged into the expansion port.. -CONS( 1994, 32x_scd, 0, 0, genesis_32x_scd, md, md_cons_cd_state, init_genesis, "Sega", "Sega CD with 32X (USA, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1995, 32x_mcd, 32x_scd, 0, md_32x_scd, md, md_cons_cd_state, init_md_eur, "Sega", "Mega-CD with 32X (Europe, PAL)", MACHINE_NOT_WORKING ) -CONS( 1994, 32x_mcdj, 32x_scd, 0, mdj_32x_scd, md, md_cons_cd_state, init_md_jpn, "Sega", "Mega-CD with 32X (Japan, NTSC)", MACHINE_NOT_WORKING ) - -// handheld hardware -CONS( 1995, gen_nomd, 0, 0, ms_megadriv2, gen_nomd, md_cons_slot_state, init_genesis, "Sega", "Genesis Nomad (USA Genesis handheld)", MACHINE_SUPPORTS_SAVE ) - -// handheld without LCD -CONS( 1993, megajet, gen_nomd, 0, ms_megadriv2, megajet, md_cons_slot_state, init_md_jpn, "Sega", "Mega Jet (Japan Mega Drive handheld)", MACHINE_SUPPORTS_SAVE ) - -// LaserActive (Laserdisc Player(ex: CLD-A100) with 'Control Pack' Addon slot) -// Mega Drive Pack(PAC-S1)/Genesis Pack(PAC-S10) plugged into the Control Pack slot, for plays Mega Drive/Genesis Cartridge, Mega-CD/Sega CD, Mega-LD stuffs -CONS( 1993, laseract, 0, 0, genesis_scd, md, md_cons_cd_state, init_genesis, "Pioneer / Sega","LaserActive with Genesis Pack PAC-S10 (USA, NTSC)", MACHINE_NOT_WORKING ) -CONS( 1993, laseractj, laseract, 0, mdj_scd, md, md_cons_cd_state, init_md_jpn, "Pioneer / Sega","LaserActive with Mega Drive Pack PAC-S1 (Japan, NTSC)", MACHINE_NOT_WORKING ) -//TODO: it has also PC Engine Pack(PAC-N1)/TG16 Pack(PAC-N10) for plays PC Engine/TG16 Cartridge, (Super/Arcade) CD-ROM2/TurboGrafx-CD, LD-ROM2 stuffs, but not emulated. - -/* clone hardware - not sure if this hardware is running some kind of emulator, or enhanced MD clone, or just custom banking */ -CONS( 200?, dcat16, 0, 0, dcat16_megadriv, md, md_cons_slot_state, init_genesis, "Firecore", "D-CAT16 (Mega Drive handheld)", MACHINE_NOT_WORKING ) diff --git a/src/mame/segacons/mdconsole.h b/src/mame/segacons/mdconsole.h deleted file mode 100644 index 1290be529d5..00000000000 --- a/src/mame/segacons/mdconsole.h +++ /dev/null @@ -1,109 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -#ifndef MAME_SEGACONS_MDCONSOLE_H -#define MAME_SEGACONS_MDCONSOLE_H - -#pragma once - -#include "megadriv.h" - -#include "mega32x.h" -#include "megacd.h" - -#include "bus/megadrive/md_slot.h" -#include "bus/megadrive/md_carts.h" - - -class md_cons_state : public md_base_state -{ -public: - md_cons_state(const machine_config &mconfig, device_type type, const char *tag) : - md_base_state(mconfig, type, tag), - m_32x(*this,"sega32x"), - m_segacd(*this,"segacd"), - m_cart(*this, "mdslot"), - m_tmss(*this, "tmss") - { } - - ioport_port *m_io_ctrlr = nullptr; - ioport_port *m_io_pad3b[4]{}; - ioport_port *m_io_pad6b[2][4]{}; - - optional_device m_32x; - optional_device m_segacd; - optional_device m_cart; - optional_region_ptr m_tmss; - - void init_mess_md_common(); - void init_genesis(); - void init_md_eur(); - void init_md_jpn(); - - uint8_t mess_md_io_read_data_port(offs_t offset); - void mess_md_io_write_data_port(offs_t offset, uint16_t data); - - DECLARE_WRITE_LINE_MEMBER(screen_vblank_console); - - DECLARE_DEVICE_IMAGE_LOAD_MEMBER( _32x_cart ); - - void _32x_scanline_callback(int x, uint32_t priority, uint32_t &lineptr); - void _32x_interrupt_callback(int scanline, int irq6); - void _32x_scanline_helper_callback(int scanline); - - void install_cartslot(); - void install_tmss(); - uint16_t tmss_r(offs_t offset); - void tmss_swap_w(uint16_t data); - void dcat16_megadriv_base(machine_config &config); - void dcat16_megadriv(machine_config &config); - - void md_32x(machine_config &config); - void genesis_32x(machine_config &config); - void mdj_32x(machine_config &config); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; -}; - -class md_cons_slot_state : public md_cons_state -{ -public: - md_cons_slot_state(const machine_config &mconfig, device_type type, const char *tag) : - md_cons_state(mconfig, type, tag) - { } - - void ms_megadpal(machine_config &config); - void ms_megadriv(machine_config &config); - void ms_megadriv2(machine_config &config); - - void genesis_tmss(machine_config &config); - - -protected: - virtual void machine_start() override; -}; - -class md_cons_cd_state : public md_cons_state -{ -public: - md_cons_cd_state(const machine_config &mconfig, device_type type, const char *tag) : - md_cons_state(mconfig, type, tag) - { } - - void genesis_scd(machine_config &config); - void genesis2_scd(machine_config &config); - void md_scd(machine_config &config); - void md2_scd(machine_config &config); - void mdj_scd(machine_config &config); - - void mdj_32x_scd(machine_config &config); - void md2j_scd(machine_config &config); - void genesis_32x_scd(machine_config &config); - void md_32x_scd(machine_config &config); - -protected: - virtual void machine_start() override; -}; - -#endif // MAME_SEGACONS_MDCONSOLE_H diff --git a/src/mame/segacons/megacd.cpp b/src/mame/segacons/megacd.cpp deleted file mode 100644 index 6f7bc7d82f6..00000000000 --- a/src/mame/segacons/megacd.cpp +++ /dev/null @@ -1,1939 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -#include "emu.h" -#include "megacd.h" -#include "machine/nvram.h" -#include "video/315_5313.h" -#include "megacd.lh" - - -#define SEGACD_CLOCK 12500000 - -#define RAM_MODE_2MEG (0) -#define RAM_MODE_1MEG (2) - -#define DMA_PCM (0x0400) -#define DMA_PRG (0x0500) -#define DMA_WRAM (0x0700) - -#define SEGACD_IRQ3_TIMER_SPEED (attotime::from_nsec(m_irq3_timer_reg*30720)) - - -DEFINE_DEVICE_TYPE(SEGA_SEGACD_US, sega_segacd_us_device, "segacd_us", "Sega Sega CD (US)") -DEFINE_DEVICE_TYPE(SEGA_SEGACD_JAPAN, sega_segacd_japan_device, "segacd_japan", "Sega Mega-CD (Japan)") -DEFINE_DEVICE_TYPE(SEGA_SEGACD_EUROPE, sega_segacd_europe_device, "segacd_europe", "Sega Mega-CD (PAL)") - - -/* Callback when the genesis enters interrupt code */ -IRQ_CALLBACK_MEMBER(sega_segacd_device::segacd_sub_int_callback) -{ - if (irqline==2) - { - // clear this bit - m_a12000_halt_reset_reg &= ~0x0100; - m_scdcpu->set_input_line(2, CLEAR_LINE); - } - - return (0x60+irqline*4)/4; // vector address -} - - -TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::irq3_timer_callback ) -{ - if (m_lc89510_temp->get_segacd_irq_mask() & 0x08) - m_scdcpu->set_input_line(3, HOLD_LINE); - - m_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED); -} - -// GFX conversion -TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::stamp_timer_callback ) -{ - //printf("stamp_timer_callback\n"); - - if (m_lc89510_temp->get_segacd_irq_mask() & 0x02) - m_scdcpu->set_input_line(1, HOLD_LINE); - - segacd_conversion_active = 0; - - // this ends up as 0 after processing (soniccd bonus stage) - segacd_imagebuffer_vdot_size = 0; -} - - -void sega_segacd_device::segacd_map(address_map &map) -{ - map(0x000000, 0x07ffff).ram().share("prgram"); - map(0x080000, 0x0bffff).rw(FUNC(sega_segacd_device::segacd_sub_dataram_part1_r), FUNC(sega_segacd_device::segacd_sub_dataram_part1_w)).share("dataram"); - map(0x0c0000, 0x0dffff).rw(FUNC(sega_segacd_device::segacd_sub_dataram_part2_r), FUNC(sega_segacd_device::segacd_sub_dataram_part2_w)); //.share("dataram2"); - - map(0xfe0000, 0xfe3fff).rw(FUNC(sega_segacd_device::backupram_r), FUNC(sega_segacd_device::backupram_w)).umask16(0x00ff); // backup RAM, odd bytes only! - - map(0xff0000, 0xff3fff).m(m_rfsnd, FUNC(rf5c164_device::rf5c164_map)).umask16(0x00ff); // PCM, RF5C164 - - map(0xff8000, 0xff8001).rw(FUNC(sega_segacd_device::segacd_sub_led_ready_r), FUNC(sega_segacd_device::segacd_sub_led_ready_w)); - map(0xff8002, 0xff8003).rw(FUNC(sega_segacd_device::segacd_sub_memory_mode_r), FUNC(sega_segacd_device::segacd_sub_memory_mode_w)); - - map(0xff8004, 0xff8005).rw("tempcdc", FUNC(lc89510_temp_device::segacd_cdc_mode_address_r), FUNC(lc89510_temp_device::segacd_cdc_mode_address_w)); - map(0xff8006, 0xff8007).rw("tempcdc", FUNC(lc89510_temp_device::segacd_cdc_data_r), FUNC(lc89510_temp_device::segacd_cdc_data_w)); - map(0xff8008, 0xff8009).r("tempcdc", FUNC(lc89510_temp_device::cdc_data_sub_r)); - map(0xff800a, 0xff800b).rw(FUNC(sega_segacd_device::segacd_dmaaddr_r), FUNC(sega_segacd_device::segacd_dmaaddr_w)); // DMA Address (not CDC, used in conjunction with) - map(0xff800c, 0xff800d).rw(FUNC(sega_segacd_device::segacd_stopwatch_timer_r), FUNC(sega_segacd_device::segacd_stopwatch_timer_w));// Stopwatch timer - map(0xff800e, 0xff800f).rw(FUNC(sega_segacd_device::segacd_comms_flags_r), FUNC(sega_segacd_device::segacd_comms_flags_subcpu_w)); - map(0xff8010, 0xff801f).rw(FUNC(sega_segacd_device::segacd_comms_sub_part1_r), FUNC(sega_segacd_device::segacd_comms_sub_part1_w)); - map(0xff8020, 0xff802f).rw(FUNC(sega_segacd_device::segacd_comms_sub_part2_r), FUNC(sega_segacd_device::segacd_comms_sub_part2_w)); - map(0xff8030, 0xff8031).rw(FUNC(sega_segacd_device::segacd_irq3timer_r), FUNC(sega_segacd_device::segacd_irq3timer_w)); // Timer W/INT3 - map(0xff8032, 0xff8033).rw("tempcdc", FUNC(lc89510_temp_device::segacd_irq_mask_r), FUNC(lc89510_temp_device::segacd_irq_mask_w)); - map(0xff8034, 0xff8035).rw("tempcdc", FUNC(lc89510_temp_device::segacd_cdfader_r), FUNC(lc89510_temp_device::segacd_cdfader_w)); // CD Fader - map(0xff8036, 0xff8037).rw("tempcdc", FUNC(lc89510_temp_device::segacd_cdd_ctrl_r), FUNC(lc89510_temp_device::segacd_cdd_ctrl_w)); - map(0xff8038, 0xff8041).r("tempcdc", FUNC(lc89510_temp_device::segacd_cdd_rx_r)); - map(0xff8042, 0xff804b).w("tempcdc", FUNC(lc89510_temp_device::segacd_cdd_tx_w)); - map(0xff804d, 0xff804d).rw(FUNC(sega_segacd_device::font_color_r), FUNC(sega_segacd_device::font_color_w)); - map(0xff804e, 0xff804f).ram().share("font_bits"); - map(0xff8050, 0xff8057).r(FUNC(sega_segacd_device::font_converted_r)); - map(0xff8058, 0xff8059).rw(FUNC(sega_segacd_device::segacd_stampsize_r), FUNC(sega_segacd_device::segacd_stampsize_w)); // Stamp size - map(0xff805a, 0xff805b).rw(FUNC(sega_segacd_device::segacd_stampmap_base_address_r), FUNC(sega_segacd_device::segacd_stampmap_base_address_w)); // Stamp map base address - map(0xff805c, 0xff805d).rw(FUNC(sega_segacd_device::segacd_imagebuffer_vcell_size_r), FUNC(sega_segacd_device::segacd_imagebuffer_vcell_size_w));// Image buffer V cell size - map(0xff805e, 0xff805f).rw(FUNC(sega_segacd_device::segacd_imagebuffer_start_address_r), FUNC(sega_segacd_device::segacd_imagebuffer_start_address_w)); // Image buffer start address - map(0xff8060, 0xff8061).rw(FUNC(sega_segacd_device::segacd_imagebuffer_offset_r), FUNC(sega_segacd_device::segacd_imagebuffer_offset_w)); - map(0xff8062, 0xff8063).rw(FUNC(sega_segacd_device::segacd_imagebuffer_hdot_size_r), FUNC(sega_segacd_device::segacd_imagebuffer_hdot_size_w)); // Image buffer H dot size - map(0xff8064, 0xff8065).rw(FUNC(sega_segacd_device::segacd_imagebuffer_vdot_size_r), FUNC(sega_segacd_device::segacd_imagebuffer_vdot_size_w)); // Image buffer V dot size - map(0xff8066, 0xff8067).w(FUNC(sega_segacd_device::segacd_trace_vector_base_address_w));// Trace vector base address -// map(0xff8068, 0xff8069) // Subcode address - -// map(0xff8100, 0xff817f) // Subcode buffer area -// map(0xff8180, 0xff81ff) // mirror of subcode buffer area - -} - -void sega_segacd_device::segacd_pcm_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0xffff).ram(); -} - - -// the tiles in RAM are 8x8 tiles -// they are referenced in the cell look-up map as either 16x16 or 32x32 tiles (made of 4 / 16 8x8 tiles) - -#define SEGACD_BYTES_PER_TILE16 (128) -#define SEGACD_BYTES_PER_TILE32 (512) - -#define SEGACD_NUM_TILES16 (0x40000/SEGACD_BYTES_PER_TILE16) -#define SEGACD_NUM_TILES32 (0x40000/SEGACD_BYTES_PER_TILE32) - -#define _16x16_SEQUENCE_1 { STEP8(0, 4), STEP8(512, 4) }, -#define _16x16_SEQUENCE_1_FLIP { STEP8(512+28, -4), STEP8(28, -4) }, - -#define _16x16_SEQUENCE_2 { STEP16(0, 32) }, -#define _16x16_SEQUENCE_2_FLIP { STEP16(15*32, -32) }, - - -#define _16x16_START \ -{ \ - 16,16, \ - SEGACD_NUM_TILES16, \ - 4, \ - { STEP4(0,1) }, -#define _16x16_END \ - 8*128 \ -}; -#define _32x32_START \ -{ \ - 32,32, \ - SEGACD_NUM_TILES32, \ - 4, \ - { STEP4(0,1) }, - -#define _32x32_END \ - 8*512 \ -}; - -#define _32x32_SEQUENCE_1 { STEP8(0, 4), STEP8(1024, 4), STEP8(2048, 4), STEP8(3072, 4) }, -#define _32x32_SEQUENCE_1_FLIP { STEP8(3072+28, -4), STEP8(2048+28, -4), STEP8(1024+28, -4), STEP8(28, -4) }, - -#define _32x32_SEQUENCE_2 { STEP32(0, 32) }, -#define _32x32_SEQUENCE_2_FLIP { STEP32(31*32, -32) }, - - -/* 16x16 decodes */ -static const gfx_layout sega_16x16_r00_f0_layout = -_16x16_START - _16x16_SEQUENCE_1 - _16x16_SEQUENCE_2 -_16x16_END - -static const gfx_layout sega_16x16_r01_f0_layout = -_16x16_START - _16x16_SEQUENCE_2 - _16x16_SEQUENCE_1_FLIP -_16x16_END - -static const gfx_layout sega_16x16_r10_f0_layout = -_16x16_START - _16x16_SEQUENCE_1_FLIP - _16x16_SEQUENCE_2_FLIP -_16x16_END - -static const gfx_layout sega_16x16_r11_f0_layout = -_16x16_START - _16x16_SEQUENCE_2_FLIP - _16x16_SEQUENCE_1 -_16x16_END - -static const gfx_layout sega_16x16_r00_f1_layout = -_16x16_START - _16x16_SEQUENCE_1_FLIP - _16x16_SEQUENCE_2 -_16x16_END - -static const gfx_layout sega_16x16_r01_f1_layout = -_16x16_START - _16x16_SEQUENCE_2 - _16x16_SEQUENCE_1 -_16x16_END - -static const gfx_layout sega_16x16_r10_f1_layout = -_16x16_START - _16x16_SEQUENCE_1 - _16x16_SEQUENCE_2_FLIP -_16x16_END - -static const gfx_layout sega_16x16_r11_f1_layout = -_16x16_START - _16x16_SEQUENCE_2_FLIP - _16x16_SEQUENCE_1_FLIP -_16x16_END - -/* 32x32 decodes */ -static const gfx_layout sega_32x32_r00_f0_layout = -_32x32_START - _32x32_SEQUENCE_1 - _32x32_SEQUENCE_2 -_32x32_END - -static const gfx_layout sega_32x32_r01_f0_layout = -_32x32_START - _32x32_SEQUENCE_2 - _32x32_SEQUENCE_1_FLIP -_32x32_END - -static const gfx_layout sega_32x32_r10_f0_layout = -_32x32_START - _32x32_SEQUENCE_1_FLIP - _32x32_SEQUENCE_2_FLIP -_32x32_END - -static const gfx_layout sega_32x32_r11_f0_layout = -_32x32_START - _32x32_SEQUENCE_2_FLIP - _32x32_SEQUENCE_1 -_32x32_END - -static const gfx_layout sega_32x32_r00_f1_layout = -_32x32_START - _32x32_SEQUENCE_1_FLIP - _32x32_SEQUENCE_2 -_32x32_END - -static const gfx_layout sega_32x32_r01_f1_layout = -_32x32_START - _32x32_SEQUENCE_2 - _32x32_SEQUENCE_1 -_32x32_END - -static const gfx_layout sega_32x32_r10_f1_layout = -_32x32_START - _32x32_SEQUENCE_1 - _32x32_SEQUENCE_2_FLIP -_32x32_END - -static const gfx_layout sega_32x32_r11_f1_layout = -_32x32_START - _32x32_SEQUENCE_2_FLIP - _32x32_SEQUENCE_1_FLIP -_32x32_END - -static GFXDECODE_START( gfx_segacd ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r00_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r01_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r10_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r11_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r00_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r11_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r10_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r01_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r00_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r01_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r10_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r11_f0_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r00_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r11_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r10_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) - GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r01_f1_layout, 0, (sega315_5313_device::PALETTE_PER_FRAME) / 16 ) -GFXDECODE_END - - -void sega_segacd_device::device_add_mconfig(machine_config &config) -{ - M68000(config, m_scdcpu, SEGACD_CLOCK); /* 12.5 MHz */ - m_scdcpu->set_addrmap(AS_PROGRAM, &sega_segacd_device::segacd_map); - m_scdcpu->set_irq_acknowledge_callback(FUNC(sega_segacd_device::segacd_sub_int_callback)); - - LC89510(config, "cdc", 0); // cd controller - - // temporary until things are cleaned up - LC89510_TEMP(config, m_lc89510_temp, 0); // cd controller - m_lc89510_temp->set_cdc_do_dma_callback(FUNC(sega_segacd_device::SegaCD_CDC_Do_DMA)); // hack - m_lc89510_temp->set_cdrom_tag("^cdrom"); - m_lc89510_temp->set_68k_tag(m_scdcpu); - - TIMER(config, m_stopwatch_timer).configure_generic(nullptr); //stopwatch timer - TIMER(config, m_stamp_timer).configure_generic(FUNC(sega_segacd_device::stamp_timer_callback)); - TIMER(config, m_irq3_timer).configure_generic(FUNC(sega_segacd_device::irq3_timer_callback)); - TIMER(config, m_dma_timer).configure_generic(FUNC(sega_segacd_device::dma_timer_callback)); - - config.set_default_layout(layout_megacd); - - RF5C164(config, m_rfsnd, SEGACD_CLOCK); // or Sega 315-5476A - m_rfsnd->add_route( 0, ":lspeaker", 0.50 ); - m_rfsnd->add_route( 1, ":rspeaker", 0.50 ); - m_rfsnd->set_addrmap(0, &sega_segacd_device::segacd_pcm_map); - - NVRAM(config, "backupram", nvram_device::DEFAULT_ALL_0); -} - - -sega_segacd_device::sega_segacd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) - , device_gfx_interface(mconfig, *this, gfx_segacd) - , device_video_interface(mconfig, *this, false) - , m_scdcpu(*this, "segacd_68k") - , m_hostcpu(*this, finder_base::DUMMY_TAG) - , m_rfsnd(*this, "rfsnd") - , m_lc89510_temp(*this, "tempcdc") - , m_stopwatch_timer(*this, "sw_timer") - , m_stamp_timer(*this, "stamp_timer") - , m_irq3_timer(*this, "irq3_timer") - , m_dma_timer(*this, "dma_timer") - , m_prgram(*this, "prgram") - , m_dataram(*this, "dataram") - , m_font_bits(*this, "font_bits") - , m_red_led(*this, "red_led") - , m_green_led(*this, "green_led") -{ -} - -sega_segacd_us_device::sega_segacd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sega_segacd_device(mconfig, SEGA_SEGACD_US, tag, owner, clock) -{ -} - -sega_segacd_japan_device::sega_segacd_japan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sega_segacd_device(mconfig, SEGA_SEGACD_JAPAN, tag, owner, clock) -{ -} - -sega_segacd_europe_device::sega_segacd_europe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sega_segacd_device(mconfig, SEGA_SEGACD_EUROPE, tag, owner, clock) -{ -} - - -inline void sega_segacd_device::write_pixel(uint8_t pix, int pixeloffset) -{ - int shift = 12-(4*(pixeloffset&0x3)); - uint16_t datamask = (0x000f) << shift; - - int offset = pixeloffset>>3; - if (pixeloffset&4) offset++; - - offset &=0x1ffff; - - switch (segacd_memory_priority_mode) - { - case 0x00: // normal write, just write the data - m_dataram[offset] = m_dataram[offset] &~ datamask; - m_dataram[offset] |= pix << shift; - break; - - case 0x01: // underwrite, only write if the existing data is 0 - if ((m_dataram[offset]&datamask) == 0x0000) - { - m_dataram[offset] = m_dataram[offset] &~ datamask; - m_dataram[offset] |= pix << shift; - } - break; - - case 0x02: // overwrite, only write non-zero data - if (pix) - { - m_dataram[offset] = m_dataram[offset] &~ datamask; - m_dataram[offset] |= pix << shift; - } - break; - - default: - case 0x03: - pix = machine().rand() & 0x000f; - m_dataram[offset] = m_dataram[offset] &~ datamask; - m_dataram[offset] |= pix << shift; - break; - - } -} - -// 1meg / 2meg swap is interleaved swap, not half/half of the ram? -// Wily Beamish and Citizen X appear to rely on this -// however, it breaks the megacdj bios (megacd2j still works!) -// (maybe that's a timing issue instead?) -uint16_t sega_segacd_device::segacd_1meg_mode_word_read(offs_t offset) -{ - offset *= 2; - - if ((offset&0x20000)) - offset +=1; - - offset &=0x1ffff; - - return m_dataram[offset]; -} - - -void sega_segacd_device::segacd_1meg_mode_word_write(offs_t offset, uint16_t data, uint16_t mem_mask, int use_pm) -{ - offset *= 2; - - if ((offset&0x20000)) - offset +=1; - - offset &=0x1ffff; - - if (use_pm) - { - // priority mode can apply when writing with the double up buffer mode - // Jaguar XJ220 relies on this - switch (segacd_memory_priority_mode) - { - case 0x00: // normal write, just write the data - COMBINE_DATA(&m_dataram[offset]); - break; - - case 0x01: // underwrite, only write if the existing data is 0 - if (ACCESSING_BITS_8_15) - { - if ((m_dataram[offset]&0xf000) == 0x0000) m_dataram[offset] |= (data)&0xf000; - if ((m_dataram[offset]&0x0f00) == 0x0000) m_dataram[offset] |= (data)&0x0f00; - } - if (ACCESSING_BITS_0_7) - { - if ((m_dataram[offset]&0x00f0) == 0x0000) m_dataram[offset] |= (data)&0x00f0; - if ((m_dataram[offset]&0x000f) == 0x0000) m_dataram[offset] |= (data)&0x000f; - } - break; - - case 0x02: // overwrite, only write non-zero data - if (ACCESSING_BITS_8_15) - { - if ((data)&0xf000) m_dataram[offset] = (m_dataram[offset] & 0x0fff) | ((data)&0xf000); - if ((data)&0x0f00) m_dataram[offset] = (m_dataram[offset] & 0xf0ff) | ((data)&0x0f00); - } - if (ACCESSING_BITS_0_7) - { - if ((data)&0x00f0) m_dataram[offset] = (m_dataram[offset] & 0xff0f) | ((data)&0x00f0); - if ((data)&0x000f) m_dataram[offset] = (m_dataram[offset] & 0xfff0) | ((data)&0x000f); - } - break; - - default: - case 0x03: // invalid? - COMBINE_DATA(&m_dataram[offset]); - break; - - } - } - else - { - COMBINE_DATA(&m_dataram[offset]); - } -} - - - - -void sega_segacd_device::scd_a12000_halt_reset_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - uint16_t old_halt = m_a12000_halt_reset_reg; - - COMBINE_DATA(&m_a12000_halt_reset_reg); - - if (ACCESSING_BITS_0_7) - { - // reset line - if (m_a12000_halt_reset_reg & 0x0001) - { - m_scdcpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - if (!(old_halt&0x0001)) printf("clear reset slave\n"); - } - else - { - m_scdcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - if ((old_halt&0x0001)) printf("assert reset slave\n"); - } - - // request BUS - if (m_a12000_halt_reset_reg & 0x0002) - { - m_scdcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - if (!(old_halt&0x0002)) printf("halt slave\n"); - } - else - { - m_scdcpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); - if ((old_halt&0x0002)) printf("resume slave\n"); - } - } - - if (ACCESSING_BITS_8_15) - { - // from master CPU - if (m_a12000_halt_reset_reg & 0x0100 && m_lc89510_temp->get_segacd_irq_mask() & 0x04) - m_scdcpu->set_input_line(2, HOLD_LINE); - - if (m_a12000_halt_reset_reg & 0x8000) - { - // not writable.. but can read irq mask here? - //printf("m_a12000_halt_reset_reg & 0x8000 set\n"); // irq2 mask? - } - - - } -} - -uint16_t sega_segacd_device::scd_a12000_halt_reset_r() -{ - return m_a12000_halt_reset_reg; -} - - -/******************************************************************************** - MEMORY MODE CONTROL - - main / sub sides differ! -********************************************************************************/ - -// -// we might need a delay on the segacd_maincpu_has_ram_access registers, as they actually indicate requests being made -// so probably don't change instantly... -// - - -uint16_t sega_segacd_device::scd_a12002_memory_mode_r() -{ - int temp = scd_rammode; - int temp2 = 0; - - temp2 |= (scd_mode_dmna_ret_flags>>(temp*4))&0x7; - - return (segacd_ram_writeprotect_bits << 8) | - (segacd_4meg_prgbank << 6) | - temp2; - -} - - -/* I'm still not 100% clear how this works, the sources I have are a bit vague, - it might still be incorrect in both modes - - for a simple way to swap blocks of ram between cpus this is stupidly convoluted - - */ - -// DMNA = Decleration Mainram No Access (bit 0) -// RET = Return access (bit 1) - - -void sega_segacd_device::scd_a12002_memory_mode_w_8_15(u8 data) -{ - if (data & 0xff00) - { - printf("write protect bits set %02x\n", data); - } - - segacd_ram_writeprotect_bits = data; -} - - -void sega_segacd_device::scd_a12002_memory_mode_w_0_7(u8 data) -{ - //printf("scd_a12002_memory_mode_w_0_7 %04x\n",data); - - segacd_4meg_prgbank = (data&0x00c0)>>6; - - if (scd_rammode&0x2) - { // ==0x2 (1 meg mode) - if (!(data&2)) // check DMNA bit - { - scd_mode_dmna_ret_flags |= 0x2200; - } - } - else // == 0x0 (2 meg mode) - { - if (data&2) // check DMNA bit - { - scd_rammode = 1; - } - } -} - - -void sega_segacd_device::scd_a12002_memory_mode_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if (ACCESSING_BITS_8_15) - scd_a12002_memory_mode_w_8_15(data>>8); - - if (ACCESSING_BITS_0_7) - scd_a12002_memory_mode_w_0_7(data&0xff); -} - - - - -uint16_t sega_segacd_device::segacd_sub_memory_mode_r() -{ - int temp = scd_rammode; - int temp2 = 0; - - temp2 |= (scd_mode_dmna_ret_flags>>(temp*4))&0x7; - - return (segacd_ram_writeprotect_bits << 8) | - (segacd_memory_priority_mode << 3) | - temp2; -} - - -void sega_segacd_device::segacd_sub_memory_mode_w_8_15(u8 data) -{ - /* setting write protect bits from sub-cpu has no effect? */ -} - - - -void sega_segacd_device::segacd_sub_memory_mode_w_0_7(u8 data) -{ - segacd_memory_priority_mode = (data&0x0018)>>3; - - // If the mode bit is 0 then we're requesting a change to - // 2Meg mode? - - //printf("segacd_sub_memory_mode_w_0_7 %04x\n",data); - - if (!(data&4)) // check ram mode bit - { // == 0x0 - 2 meg mode - scd_mode_dmna_ret_flags &= 0xddff; - - if (data&1) // check RET - { - // If RET is set and the Mode bit in the write is set to 2M then we want to change to 2M mode - // If we're already in 2M mode it has no effect - scd_rammode = 0; - - } - else - { - // == 0x4 - 1 meg mode - - int temp = scd_rammode; - if (temp&2) // check ram mode - { // == 0x2 - 1 meg mode - scd_mode_dmna_ret_flags &= 0xffde; - scd_rammode = temp &1; - } - } - } - else - { // == 0x4 - 1 meg mode - data &=1; - int temp = data; - int scd_rammode_old = scd_rammode; - data |=2; - - temp ^= scd_rammode_old; - scd_rammode = data; - - if (scd_rammode_old & 2) - { // == 0x2 - already in 1 meg mode - if (temp & 1) // ret bit - { - scd_mode_dmna_ret_flags &= 0xddff; - } - } - else - { // == 0x0 - currently in 2 meg mode - scd_mode_dmna_ret_flags &= 0xddff; - } - } -} - -void sega_segacd_device::segacd_sub_memory_mode_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - //printf("segacd_sub_memory_mode_w %04x %04x\n", data, mem_mask); - - - if (ACCESSING_BITS_8_15) - segacd_sub_memory_mode_w_8_15(data>>8); - - if (ACCESSING_BITS_0_7) - segacd_sub_memory_mode_w_0_7(data&0xff); -} - - -/******************************************************************************** - END MEMORY MODE CONTROL -********************************************************************************/ - -/******************************************************************************** - COMMUNICATION FLAGS - - main / sub sides differ in which bits are write only -********************************************************************************/ - - -uint16_t sega_segacd_device::segacd_comms_flags_r() -{ - return segacd_comms_flags; -} - -void sega_segacd_device::segacd_comms_flags_subcpu_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if (ACCESSING_BITS_8_15) // Dragon's Lair - { - segacd_comms_flags = (segacd_comms_flags & 0xff00) | ((data >> 8) & 0x00ff); - } - - // flashback needs low bits to take priority in word writes - if (ACCESSING_BITS_0_7) - { - segacd_comms_flags = (segacd_comms_flags & 0xff00) | (data & 0x00ff); - } -} - -void sega_segacd_device::segacd_comms_flags_maincpu_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if (ACCESSING_BITS_8_15) - { - segacd_comms_flags = (segacd_comms_flags & 0x00ff) | (data & 0xff00); - } - - // flashback needs low bits to take priority in word writes - if (ACCESSING_BITS_0_7) - { - segacd_comms_flags = (segacd_comms_flags & 0x00ff) | ((data << 8) & 0xff00); - } -} - -uint16_t sega_segacd_device::scd_4m_prgbank_ram_r(offs_t offset) -{ - uint32_t realoffset = ((segacd_4meg_prgbank * 0x20000)/2) + offset; - return m_prgram[realoffset]; - -} - -void sega_segacd_device::scd_4m_prgbank_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - uint32_t realoffset = ((segacd_4meg_prgbank * 0x20000)/2) + offset; - - // todo: - // check for write protection? (or does that only apply to writes on the SubCPU side? - - COMBINE_DATA(&m_prgram[realoffset]); - -} - - - -uint16_t sega_segacd_device::segacd_comms_main_part1_r(offs_t offset) -{ - return segacd_comms_part1[offset]; -} - -void sega_segacd_device::segacd_comms_main_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&segacd_comms_part1[offset]); -} - -uint16_t sega_segacd_device::segacd_comms_main_part2_r(offs_t offset) -{ - return segacd_comms_part2[offset]; -} - -void sega_segacd_device::segacd_comms_main_part2_w(uint16_t data) -{ - printf("Sega CD main CPU attempting to write to read only comms regs\n"); -} - - -uint16_t sega_segacd_device::segacd_comms_sub_part1_r(offs_t offset) -{ - return segacd_comms_part1[offset]; -} - -void sega_segacd_device::segacd_comms_sub_part1_w(uint16_t data) -{ - printf("Sega CD sub CPU attempting to write to read only comms regs\n"); -} - -uint16_t sega_segacd_device::segacd_comms_sub_part2_r(offs_t offset) -{ - return segacd_comms_part2[offset]; -} - -void sega_segacd_device::segacd_comms_sub_part2_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&segacd_comms_part2[offset]); -} - - -uint16_t sega_segacd_device::segacd_main_dataram_part1_r(offs_t offset) -{ - if ((scd_rammode&2)==RAM_MODE_2MEG) - { - // is this correct? - if (!(scd_rammode&1)) - { - //printf("segacd_main_dataram_part1_r in mode 0 %08x %04x\n", offset*2, m_dataram[offset]); - - return m_dataram[offset]; - - } - else - { - //printf("Illegal: segacd_main_dataram_part1_r in mode 0 without permission\n"); - return 0xffff; - } - - } - else if ((scd_rammode&2)==RAM_MODE_1MEG) - { - if (offset<0x20000/2) - { - // wordram accees - //printf("Unsupported: segacd_main_dataram_part1_r (word RAM) in mode 1\n"); - - // ret bit set by sub cpu determines which half of WorkRAM we have access to? - if (scd_rammode&1) - { - return segacd_1meg_mode_word_read(offset+0x20000/2); - } - else - { - return segacd_1meg_mode_word_read(offset+0x00000/2); - } - - } - else - { - // converts data stored in bitmap format (in dataram) to be read out as tiles (for dma->vram purposes) - // used by Heart of the Alien - - if(offset<0x30000/2) /* 0x20000 - 0x2ffff */ // 512x256 bitmap. tiles - offset = bitswap<24>(offset,23,22,21,20,19,18,17,16,15,8,7,6,5,4,3,2,1,14,13,12,11,10,9,0); - else if(offset<0x38000/2) /* 0x30000 - 0x37fff */ // 512x128 bitmap. tiles - offset = bitswap<24>(offset,23,22,21,20,19,18,17,16,15,14,7,6,5,4,3,2,1,13,12,11,10,9,8,0); - else if(offset<0x3c000/2) /* 0x38000 - 0x3bfff */ // 512x64 bitmap. tiles - offset = bitswap<24>(offset,23,22,21,20,19,18,17,16,15,14,13,6,5,4,3,2,1,12,11,10,9,8,7,0); - else /* 0x3c000 - 0x3dfff and 0x3e000 - 0x3ffff */ // 512x32 bitmap (x2) -> tiles - offset = bitswap<24>(offset,23,22,21,20,19,18,17,16,15,14,13,12,5,4,3,2,1,11,10,9,8,7,6,0); - - offset &=0xffff; - // HOTA cares about this - if (!(scd_rammode&1)) - { - return segacd_1meg_mode_word_read(offset+0x00000/2); - } - else - { - return segacd_1meg_mode_word_read(offset+0x20000/2); - } - } - } - - return 0x0000; -} - -void sega_segacd_device::segacd_main_dataram_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if ((scd_rammode&2)==RAM_MODE_2MEG) - { - // is this correct? - if (!(scd_rammode&1)) - { - COMBINE_DATA(&m_dataram[offset]); - segacd_mark_tiles_dirty(offset); - } - else - { - //printf("Illegal: segacd_main_dataram_part1_w in mode 0 without permission\n"); - } - - } - else if ((scd_rammode&2)==RAM_MODE_1MEG) - { - if (offset<0x20000/2) - { - //printf("Unsupported: segacd_main_dataram_part1_w (word RAM) in mode 1\n"); - // wordram accees - - // ret bit set by sub cpu determines which half of WorkRAM we have access to? - if (scd_rammode&1) - { - segacd_1meg_mode_word_write(offset+0x20000/2, data, mem_mask, 0); - } - else - { - segacd_1meg_mode_word_write(offset+0x00000/2, data, mem_mask, 0); - } - } - else - { - // printf("Unsupported: segacd_main_dataram_part1_w (Cell rearranged RAM) in mode 1 (illega?)\n"); // is this legal?? - } - } -} - -uint16_t sega_segacd_device::scd_hint_vector_r(offs_t offset) -{ -// printf("read HINT offset %d\n", offset); - - switch (offset&1) - { - case 0x00: - //return 0x00ff; // doesn't make much sense.. - return 0xffff; - case 0x01: - return segacd_hint_register; - } - - return 0; - -} - -uint16_t sega_segacd_device::scd_a12006_hint_register_r() -{ - return segacd_hint_register; -} - -void sega_segacd_device::scd_a12006_hint_register_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&segacd_hint_register); -} - - -void sega_segacd_device::segacd_mark_tiles_dirty(int offset) -{ - gfx(0)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); - gfx(1)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); - gfx(2)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); - gfx(3)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); - gfx(4)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); - gfx(5)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); - gfx(6)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); - gfx(7)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); - - gfx(8)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); - gfx(9)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); - gfx(10)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); - gfx(11)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); - gfx(12)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); - gfx(13)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); - gfx(14)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); - gfx(15)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); -} - - -// mame specific.. map registers to which tilemap cache we use -int sega_segacd_device::segacd_get_active_stampmap_tilemap(void) -{ - return (segacd_stampsize & 0x6)>>1; -} - - - -void sega_segacd_device::SCD_GET_TILE_INFO_16x16_1x1( int& tile_region, int& tileno, int tile_index ) -{ - tile_region = 0; // 16x16 tiles - int tile_base = (segacd_stampmap_base_address & 0xff80) * 4; - - int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; - tileno = tiledat & 0x07ff; - int xflip = tiledat & 0x8000; - int roll = (tiledat & 0x6000)>>13; - - if (xflip) tile_region += 4; - tile_region+=roll; -} - -void sega_segacd_device::SCD_GET_TILE_INFO_32x32_1x1( int& tile_region, int& tileno, int tile_index ) -{ - tile_region = 8; // 32x32 tiles - int tile_base = (segacd_stampmap_base_address & 0xffe0) * 4; - - int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; - tileno = (tiledat & 0x07fc)>>2; - int xflip = tiledat & 0x8000; - int roll = (tiledat & 0x6000)>>13; - - if (xflip) tile_region += 4; - tile_region+=roll; -} - - -void sega_segacd_device::SCD_GET_TILE_INFO_16x16_16x16( int& tile_region, int& tileno, int tile_index ) -{ - tile_region = 0; // 16x16 tiles - int tile_base = (0x8000) * 4; // fixed address in this mode - - int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; - tileno = tiledat & 0x07ff; - int xflip = tiledat & 0x8000; - int roll = (tiledat & 0x6000)>>13; - - if (xflip) tile_region += 4; - tile_region+=roll; -} - - -void sega_segacd_device::SCD_GET_TILE_INFO_32x32_16x16( int& tile_region, int& tileno, int tile_index ) -{ - tile_region = 8; // 32x32 tiles - int tile_base = (segacd_stampmap_base_address & 0xe000) * 4; - - int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; - tileno = (tiledat & 0x07fc)>>2; - int xflip = tiledat & 0x8000; - int roll = (tiledat & 0x6000)>>13; - - if (xflip) tile_region += 4; - tile_region+=roll; -} - -/* Tilemap callbacks (we don't actually use the tilemaps due to the excessive overhead */ - - - -TILE_GET_INFO_MEMBER( sega_segacd_device::get_stampmap_16x16_1x1_tile_info ) -{ - int tile_region, tileno; - SCD_GET_TILE_INFO_16x16_1x1(tile_region,tileno,(int)tile_index); - tileinfo.set(tile_region, tileno, 0, 0); -} - -TILE_GET_INFO_MEMBER( sega_segacd_device::get_stampmap_32x32_1x1_tile_info ) -{ - int tile_region, tileno; - SCD_GET_TILE_INFO_32x32_1x1(tile_region,tileno,(int)tile_index); - tileinfo.set(tile_region, tileno, 0, 0); -} - - -TILE_GET_INFO_MEMBER( sega_segacd_device::get_stampmap_16x16_16x16_tile_info ) -{ - int tile_region, tileno; - SCD_GET_TILE_INFO_16x16_16x16(tile_region,tileno,(int)tile_index); - tileinfo.set(tile_region, tileno, 0, 0); -} - -TILE_GET_INFO_MEMBER( sega_segacd_device::get_stampmap_32x32_16x16_tile_info ) -{ - int tile_region, tileno; - SCD_GET_TILE_INFO_32x32_16x16(tile_region,tileno,(int)tile_index); - tileinfo.set(tile_region, tileno, 0, 0); -} - -// non-tilemap functions to get a pixel from a 'tilemap' based on the above, but looking up each pixel, as to avoid the heavy cache bitmap - -inline uint8_t sega_segacd_device::get_stampmap_16x16_1x1_tile_info_pixel(int xpos, int ypos) -{ - const int tilesize = 4; // 0xf pixels - const int tilemapsize = 0x0f; - - int wraparound = segacd_stampsize&1; - - int xtile = xpos >> tilesize; - int ytile = ypos >> tilesize; - - if (wraparound) - { - // wrap... - xtile &= tilemapsize; - ytile &= tilemapsize; - } - else - { - if (xtile>tilemapsize) return 0; - if (xtile<0) return 0; - - if (ytile>tilemapsize) return 0; - if (ytile<0) return 0; - } - - int tile_index = (ytile * (tilemapsize+1)) + xtile; - - int tile_region, tileno; - SCD_GET_TILE_INFO_16x16_1x1(tile_region,tileno,(int)tile_index); - - tileno %= gfx(tile_region)->elements(); - - if (tileno==0) return 0x00; - - const uint8_t* srcdata = gfx(tile_region)->get_data(tileno); - return srcdata[((ypos&((1<> tilesize; - int ytile = ypos >> tilesize; - - if (wraparound) - { - // wrap... - xtile &= tilemapsize; - ytile &= tilemapsize; - } - else - { - if (xtile>tilemapsize) return 0; - if (xtile<0) return 0; - - if (ytile>tilemapsize) return 0; - if (ytile<0) return 0; - } - - int tile_index = (ytile * (tilemapsize+1)) + xtile; - - int tile_region, tileno; - SCD_GET_TILE_INFO_32x32_1x1(tile_region,tileno,(int)tile_index); - - tileno %= gfx(tile_region)->elements(); - - if (tileno==0) return 0x00; // does this apply in this mode? - - const uint8_t* srcdata = gfx(tile_region)->get_data(tileno); - return srcdata[((ypos&((1<> tilesize; - int ytile = ypos >> tilesize; - - if (wraparound) - { - // wrap... - xtile &= tilemapsize; - ytile &= tilemapsize; - } - else - { - if (xtile>tilemapsize) return 0; - if (xtile<0) return 0; - - if (ytile>tilemapsize) return 0; - if (ytile<0) return 0; - } - - int tile_index = (ytile * (tilemapsize+1)) + xtile; - - int tile_region, tileno; - SCD_GET_TILE_INFO_16x16_16x16(tile_region,tileno,(int)tile_index); - - tileno %= gfx(tile_region)->elements(); - - if (tileno==0) return 0x00; // does this apply in this mode - - const uint8_t* srcdata = gfx(tile_region)->get_data(tileno); - return srcdata[((ypos&((1<> tilesize; - int ytile = ypos >> tilesize; - - if (wraparound) - { - // wrap... - xtile &= tilemapsize; - ytile &= tilemapsize; - } - else - { - if (xtile>tilemapsize) return 0; - if (xtile<0) return 0; - - if (ytile>tilemapsize) return 0; - if (ytile<0) return 0; - } - - int tile_index = (ytile * (tilemapsize+1)) + xtile; - - int tile_region, tileno; - SCD_GET_TILE_INFO_32x32_16x16(tile_region,tileno,(int)tile_index); - - tileno %= gfx(tile_region)->elements(); - - if (tileno==0) return 0x00; - - const uint8_t* srcdata = gfx(tile_region)->get_data(tileno); - return srcdata[((ypos&((1<reset(); - else - printf("Stopwatch timer %04x\n",data); -} - -uint16_t sega_segacd_device::segacd_stopwatch_timer_r() -{ - int32_t result = (m_stopwatch_timer->time_elapsed() * ATTOSECONDS_TO_HZ(ATTOSECONDS_IN_USEC(30.72))).as_double(); - - return result & 0xfff; -} - - - - - - - -uint16_t sega_segacd_device::segacd_sub_led_ready_r(offs_t offset, uint16_t mem_mask) -{ - uint16_t retdata = 0x0000; - - if (ACCESSING_BITS_0_7) - { - retdata |= segacd_ready; - } - - if (ACCESSING_BITS_8_15) - { - retdata |= segacd_redled << 8; - retdata |= segacd_greenled << 9; - } - - return retdata; -} - -void sega_segacd_device::segacd_sub_led_ready_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if (ACCESSING_BITS_0_7) - { - if ((data&0x01) == 0x00) - { - // reset CD unit - } - } - - if (ACCESSING_BITS_8_15) - { - segacd_redled = (data >> 8)&1; - segacd_greenled = (data >> 9)&1; - - m_red_led = segacd_redled ^ 1; - m_green_led = segacd_greenled ^ 1; - } -} - - - -uint16_t sega_segacd_device::segacd_sub_dataram_part1_r(offs_t offset) -{ - if ((scd_rammode&2)==RAM_MODE_2MEG) - { - // is this correct? - if (scd_rammode&1) - return m_dataram[offset]; - else - { - //printf("Illegal: segacd_sub_dataram_part1_r in mode 0 without permission\n"); - return 0x0000; - } - } - else if ((scd_rammode&2)==RAM_MODE_1MEG) - { -// printf("Unsupported: segacd_sub_dataram_part1_r in mode 1 (Word RAM Expander - 1 Byte Per Pixel)\n"); - uint16_t data; - - if (scd_rammode&1) - { - data = segacd_1meg_mode_word_read(offset/2+0x00000/2); - } - else - { - data = segacd_1meg_mode_word_read(offset/2+0x20000/2); - } - - if (offset&1) - { - return ((data & 0x00f0) << 4) | ((data & 0x000f) << 0); - } - else - { - return ((data & 0xf000) >> 4) | ((data & 0x0f00) >> 8); - } - - - } - - return 0x0000; -} - -void sega_segacd_device::segacd_sub_dataram_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if ((scd_rammode&2)==RAM_MODE_2MEG) - { - // is this correct? - if (scd_rammode&1) - { - COMBINE_DATA(&m_dataram[offset]); - segacd_mark_tiles_dirty(offset); - } - else - { - //printf("Illegal: segacd_sub_dataram_part1_w in mode 0 without permission\n"); - } - } - else if ((scd_rammode&2)==RAM_MODE_1MEG) - { - //if (mem_mask==0xffff) - // printf("Unsupported: segacd_sub_dataram_part1_w in mode 1 (Word RAM Expander - 1 Byte Per Pixel) %04x %04x\n", data, mem_mask); - - data = (data & 0x000f) | (data & 0x0f00)>>4; - mem_mask = (mem_mask & 0x000f) | (mem_mask & 0x0f00)>>4; - -// data = ((data & 0x00f0) >>4) | (data & 0xf000)>>8; -// mem_mask = ((mem_mask & 0x00f0)>>4) | ((mem_mask & 0xf000)>>8); - - - if (!(offset&1)) - { - data <<=8; - mem_mask <<=8; - } - - if (scd_rammode&1) - { - segacd_1meg_mode_word_write(offset/2+0x00000/2, data , mem_mask, 1); - } - else - { - segacd_1meg_mode_word_write(offset/2+0x20000/2, data, mem_mask, 1); - } - - // printf("Unsupported: segacd_sub_dataram_part1_w in mode 1 (Word RAM Expander - 1 Byte Per Pixel) %04x\n", data); - } -} - -uint16_t sega_segacd_device::segacd_sub_dataram_part2_r(offs_t offset) -{ - if ((scd_rammode&2)==RAM_MODE_2MEG) - { - //printf("ILLEGAL segacd_sub_dataram_part2_r in mode 0\n"); // not mapped to anything in mode 0 - return 0x0000; - } - else if ((scd_rammode&2)==RAM_MODE_1MEG) - { - //printf("Unsupported: segacd_sub_dataram_part2_r in mode 1 (Word RAM)\n"); - // ret bit set by sub cpu determines which half of WorkRAM we have access to? - if (scd_rammode&1) - { - return segacd_1meg_mode_word_read(offset+0x00000/2); - } - else - { - return segacd_1meg_mode_word_read(offset+0x20000/2); - } - - } - - return 0x0000; -} - -void sega_segacd_device::segacd_sub_dataram_part2_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if ((scd_rammode&2)==RAM_MODE_2MEG) - { - printf("ILLEGAL segacd_sub_dataram_part2_w in mode 0\n"); // not mapped to anything in mode 0 - } - else if ((scd_rammode&2)==RAM_MODE_1MEG) - { - //printf("Unsupported: segacd_sub_dataram_part2_w in mode 1 (Word RAM)\n"); - // ret bit set by sub cpu determines which half of WorkRAM we have access to? - if (scd_rammode&1) - { - segacd_1meg_mode_word_write(offset+0x00000/2, data, mem_mask, 0); - } - else - { - segacd_1meg_mode_word_write(offset+0x20000/2, data, mem_mask, 0); - } - - } -} - - - -uint16_t sega_segacd_device::segacd_stampsize_r() -{ - uint16_t retdata = 0x0000; - - retdata |= segacd_conversion_active<<15; - - retdata |= segacd_stampsize & 0x7; - - return retdata; - -} - -void sega_segacd_device::segacd_stampsize_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - //printf("segacd_stampsize_w %04x %04x\n",data, mem_mask); - if (ACCESSING_BITS_0_7) - { - segacd_stampsize = data & 0x07; - //if (data & 0xf8) - // printf(" unused bits (LSB) set in stampsize!\n"); - - //if (data&1) printf(" Repeat On\n"); - //else printf(" Repeat Off\n"); - - //if (data&2) printf(" 32x32 dots\n"); - //else printf(" 16x16 dots\n"); - - //if (data&4) printf(" 16x16 screens\n"); - //else printf(" 1x1 screen\n"); - } - - if (ACCESSING_BITS_8_15) - { - //if (data&0xff00) printf(" unused bits (MSB) set in stampsize!\n"); - } -} - -// these functions won't cope if -// -// the lower 3 bits of segacd_imagebuffer_hdot_size are set - -// this really needs to be doing it's own lookups rather than depending on the inefficient MAME cache.. -inline uint8_t sega_segacd_device::read_pixel_from_stampmap(bitmap_ind16* srcbitmap, int x, int y) -{ -/* - if (!srcbitmap) - { - return machine().rand(); - } - - if (x >= srcbitmap->width) return 0; - if (y >= srcbitmap->height) return 0; - - uint16_t* cacheptr = &srcbitmap->pix(y, x); - - return cacheptr[0] & 0xf; -*/ - - switch (segacd_get_active_stampmap_tilemap()&3) - { - case 0x00: return get_stampmap_16x16_1x1_tile_info_pixel( x, y ); - case 0x01: return get_stampmap_32x32_1x1_tile_info_pixel( x, y ); - case 0x02: return get_stampmap_16x16_16x16_tile_info_pixel( x, y ); - case 0x03: return get_stampmap_32x32_16x16_tile_info_pixel( x, y ); - } - - return 0; -} - - - - - -// this triggers the conversion operation, which will cause an IRQ1 when finished -void sega_segacd_device::segacd_trace_vector_base_address_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if ((scd_rammode&2)==RAM_MODE_1MEG) - { - printf("ILLEGAL: segacd_trace_vector_base_address_w %04x %04x in mode 1!\n",data,mem_mask); - } - - //printf("segacd_trace_vector_base_address_w %04x %04x\n",data,mem_mask); - - { - int base = (data & 0xfffe) * 4; - - //printf("actual base = %06x\n", base + 0x80000); - - // nasty nasty nasty - //segacd_mark_stampmaps_dirty(); - - segacd_conversion_active = 1; - - // todo: proper time calculation - m_stamp_timer->adjust(attotime::from_nsec(30000)); - - - - int line; - //bitmap_ind16 *srcbitmap = segacd_stampmap[segacd_get_active_stampmap_tilemap(->pixmap()]); - bitmap_ind16 *srcbitmap = nullptr; - uint32_t bufferstart = ((segacd_imagebuffer_start_address&0xfff8)*2)<<3; - - for (line=0;line>1]; - tilemapyoffs = m_dataram[(currbase+0x2)>>1]; - deltax = m_dataram[(currbase+0x4)>>1]; // x-zoom - deltay = m_dataram[(currbase+0x6)>>1]; // rotation - - //printf("%06x: %04x (%d) %04x (%d) %04x %04x\n", currbase, tilemapxoffs, tilemapxoffs>>3, tilemapyoffs, tilemapyoffs>>3, deltax, deltay); - - int xbase = tilemapxoffs * 256; - int ybase = tilemapyoffs * 256; - int count; - - for (count=0;count<(segacd_imagebuffer_hdot_size);count++) - { - //int i; - uint8_t pix = 0x0; - - pix = read_pixel_from_stampmap(srcbitmap, xbase>>(3+8), ybase>>(3+8)); - - xbase += deltax; - ybase += deltay; - - // clamp to 24-bits, seems to be required for all the intro effects to work - xbase &= 0xffffff; - ybase &= 0xffffff; - - int countx = count + (segacd_imagebuffer_offset&0x7); - - uint32_t offset; - - offset = bufferstart+((((segacd_imagebuffer_vcell_size+1)*0x10)*(countx>>3))<<3); - - offset+= ((line*2)<<3); - offset+=(segacd_imagebuffer_offset&0x38)<<1; - - offset+=countx & 0x7; - - write_pixel( pix, offset ); - - segacd_mark_tiles_dirty(offset>>3); - segacd_mark_tiles_dirty((offset>>3)+1); - - } - - } - } - -} - -// actually just the low 8 bits? -uint16_t sega_segacd_device::segacd_imagebuffer_vdot_size_r() -{ - return segacd_imagebuffer_vdot_size; -} - -void sega_segacd_device::segacd_imagebuffer_vdot_size_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - //printf("segacd_imagebuffer_vdot_size_w %04x %04x\n",data,mem_mask); - COMBINE_DATA(&segacd_imagebuffer_vdot_size); -} - - -// basically the 'tilemap' base address, for the 16x16 / 32x32 source tiles -uint16_t sega_segacd_device::segacd_stampmap_base_address_r() -{ - // different bits are valid in different modes, but I'm guessing the register - // always returns all the bits set, even if they're not used? - return segacd_stampmap_base_address; - -} - -void sega_segacd_device::segacd_stampmap_base_address_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ // WORD ACCESS - - // low 3 bitsa aren't used, are they stored? - COMBINE_DATA(&segacd_stampmap_base_address); -} - -// destination for 'rendering' the section of the tilemap(stampmap) requested -uint16_t sega_segacd_device::segacd_imagebuffer_start_address_r() -{ - return segacd_imagebuffer_start_address; -} - -void sega_segacd_device::segacd_imagebuffer_start_address_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&segacd_imagebuffer_start_address); - - //int base = (segacd_imagebuffer_start_address & 0xfffe) * 4; - //printf("segacd_imagebuffer_start_address_w %04x %04x (actual base = %06x)\n", data, segacd_imagebuffer_start_address, base); -} - -uint16_t sega_segacd_device::segacd_imagebuffer_offset_r() -{ - return segacd_imagebuffer_offset; -} - -void sega_segacd_device::segacd_imagebuffer_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&segacd_imagebuffer_offset); -// printf("segacd_imagebuffer_offset_w %04x\n", segacd_imagebuffer_offset); -} - -uint16_t sega_segacd_device::segacd_imagebuffer_vcell_size_r() -{ - return segacd_imagebuffer_vcell_size; -} - -void sega_segacd_device::segacd_imagebuffer_vcell_size_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&segacd_imagebuffer_vcell_size); -} - - -uint16_t sega_segacd_device::segacd_imagebuffer_hdot_size_r() -{ - return segacd_imagebuffer_hdot_size; -} - -void sega_segacd_device::segacd_imagebuffer_hdot_size_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&segacd_imagebuffer_hdot_size); -} - - - -uint16_t sega_segacd_device::segacd_irq3timer_r() -{ - return m_irq3_timer_reg; // always returns value written, not current counter! -} - - -void sega_segacd_device::segacd_irq3timer_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if (ACCESSING_BITS_0_7) - { - m_irq3_timer_reg = data & 0xff; - - // time = reg * 30.72 us - - if (m_irq3_timer_reg) - m_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED); - else - m_irq3_timer->adjust(attotime::never); - - //printf("segacd_irq3timer_w %02x\n", segacd_m_irq3_timer_reg); - } -} - - -uint8_t sega_segacd_device::backupram_r(offs_t offset) -{ - return m_backupram[offset]; -} - -void sega_segacd_device::backupram_w(offs_t offset, uint8_t data) -{ - m_backupram[offset] = data; -} - -uint8_t sega_segacd_device::font_color_r() -{ - return m_font_color; -} - -void sega_segacd_device::font_color_w(uint8_t data) -{ - m_font_color = data; -} - -uint16_t sega_segacd_device::font_converted_r(offs_t offset) -{ - int scbg = (m_font_color & 0x0f); - int scfg = (m_font_color & 0xf0)>>4; - uint16_t retdata = 0; - int bit; - - for (bit=0;bit<4;bit++) - { - if (*m_font_bits&((0x1000>>offset*4)<space(AS_PROGRAM); - - m_backupram.resize(0x2000); - subdevice("backupram")->set_base(&m_backupram[0], 0x2000); - - segacd_4meg_prgbank = 0; - - m_red_led.resolve(); - m_green_led.resolve(); - - space.unmap_readwrite (0x020000,0x3fffff); - - space.install_read_handler (0x0020000, 0x003ffff, read16sm_delegate(*this, FUNC(sega_segacd_device::scd_4m_prgbank_ram_r)) ); - space.install_write_handler (0x0020000, 0x003ffff, write16s_delegate(*this, FUNC(sega_segacd_device::scd_4m_prgbank_ram_w)) ); - - - space.install_read_handler(0x200000, 0x23ffff, read16sm_delegate(*this, FUNC(sega_segacd_device::segacd_main_dataram_part1_r))); // RAM shared with sub - space.install_write_handler(0x200000, 0x23ffff, write16s_delegate(*this, FUNC(sega_segacd_device::segacd_main_dataram_part1_w))); // RAM shared with sub - space.install_read_handler(0xa12000, 0xa12001, read16smo_delegate(*this, FUNC(sega_segacd_device::scd_a12000_halt_reset_r))); // sub-cpu control - space.install_write_handler(0xa12000, 0xa12001, write16s_delegate(*this, FUNC(sega_segacd_device::scd_a12000_halt_reset_w))); // sub-cpu control - space.install_read_handler(0xa12002, 0xa12003, read16smo_delegate(*this, FUNC(sega_segacd_device::scd_a12002_memory_mode_r))); // memory mode / write protect - space.install_write_handler(0xa12002, 0xa12003, write16s_delegate(*this, FUNC(sega_segacd_device::scd_a12002_memory_mode_w))); // memory mode / write protect - //space.install_readwrite_handler(0xa12004, 0xa12005, read16_delegate(*this, FUNC(sega_segacd_device::segacd_cdc_mode_address_r)), write16_delegate(*this, FUNC(sega_segacd_device::segacd_cdc_mode_address_w))); - space.install_read_handler(0xa12006, 0xa12007, read16smo_delegate(*this, FUNC(sega_segacd_device::scd_a12006_hint_register_r))); // where HINT points on main CPU - space.install_write_handler(0xa12006, 0xa12007, write16s_delegate(*this, FUNC(sega_segacd_device::scd_a12006_hint_register_w))); // where HINT points on main CPU - //space.install_read_handler (0xa12008, 0xa12009, read16_delegate(*this, FUNC(sega_segacd_device::cdc_data_main_r))); - - - space.install_readwrite_handler(0xa1200c, 0xa1200d, read16smo_delegate(*this, FUNC(sega_segacd_device::segacd_stopwatch_timer_r)), write16smo_delegate(*this, FUNC(sega_segacd_device::segacd_stopwatch_timer_w))); // starblad - - space.install_read_handler(0xa1200e, 0xa1200f, read16smo_delegate(*this, FUNC(sega_segacd_device::segacd_comms_flags_r))); // communication flags block - space.install_write_handler(0xa1200e, 0xa1200f, write16s_delegate(*this, FUNC(sega_segacd_device::segacd_comms_flags_maincpu_w))); // communication flags block - - space.install_read_handler(0xa12010, 0xa1201f, read16sm_delegate(*this, FUNC(sega_segacd_device::segacd_comms_main_part1_r))); - space.install_write_handler(0xa12010, 0xa1201f, write16s_delegate(*this, FUNC(sega_segacd_device::segacd_comms_main_part1_w))); - space.install_read_handler(0xa12020, 0xa1202f, read16sm_delegate(*this, FUNC(sega_segacd_device::segacd_comms_main_part2_r))); - space.install_write_handler(0xa12020, 0xa1202f, write16smo_delegate(*this, FUNC(sega_segacd_device::segacd_comms_main_part2_w))); - - - - space.install_read_handler (0x0000070, 0x0000073, read16sm_delegate(*this, FUNC(sega_segacd_device::scd_hint_vector_r)) ); - - segacd_stampmap[0] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(sega_segacd_device::get_stampmap_16x16_1x1_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 16); - segacd_stampmap[1] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(sega_segacd_device::get_stampmap_32x32_1x1_tile_info)), TILEMAP_SCAN_ROWS, 32, 32, 8, 8); - segacd_stampmap[2] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(sega_segacd_device::get_stampmap_16x16_16x16_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 256, 256); // 128kb! - segacd_stampmap[3] = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(sega_segacd_device::get_stampmap_32x32_16x16_tile_info)), TILEMAP_SCAN_ROWS, 32, 32, 128, 128); // 32kb! - - // todo register save state stuff -} - -uint16_t sega_segacd_device::segacd_dmaaddr_r() -{ - return m_dmaaddr; -} - -void sega_segacd_device::segacd_dmaaddr_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&m_dmaaddr); -} - -void sega_segacd_device::device_reset() -{ - m_scdcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - m_scdcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - - segacd_hint_register = 0xffff; // -1 - - m_a12000_halt_reset_reg = 0x0000; - - scd_rammode = 0; - scd_mode_dmna_ret_flags = 0x5421; - - m_lc89510_temp->reset_cd(); - m_dmaaddr = 0; - m_dma_timer->adjust(attotime::zero); - - m_total_scanlines = 262; - - // HACK!!!! timegal, anettfut, roadaven/rbfx end up with the SubCPU waiting in a loop for *something* - // overclocking the CPU, even at the point where the game is hung, allows them to continue and boot - // I'm not sure what the source of this timing problem is, it's not using IRQ3 or StopWatch at the - // time. Changing the CDHock timer to 50hz from 75hz also stops the hang, but then the video is - // too slow and has bad sound. -- Investigate! - // Update: removed, otherwise megacdj and megacd2j will black screen with no cdrom inserted. - //m_scdcpu->set_clock_scale(1.5000f); - - - // initialize some stuff on reset - - segacd_ram_writeprotect_bits = 0; - segacd_4meg_prgbank = 0; - segacd_memory_priority_mode = 0; - segacd_stampsize = 0; - - segacd_imagebuffer_vdot_size = 0; - segacd_imagebuffer_vcell_size = 0; - segacd_imagebuffer_hdot_size = 0; - - segacd_conversion_active = 0; - segacd_stampmap_base_address = 0; - segacd_imagebuffer_start_address = 0; - segacd_imagebuffer_offset = 0; - - segacd_comms_flags = 0x0000; - - segacd_redled = 0; - segacd_greenled = 0; - segacd_ready = 1; // actually set 100ms after startup? - m_irq3_timer_reg = 0; - - m_stamp_timer->adjust(attotime::never); - m_irq3_timer->adjust(attotime::never); - -} - - -// todo: tidy up -TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::dma_timer_callback ) -{ - // todo: accurate timing of this! - - #define RATE 256 - m_lc89510_temp->CDC_Do_DMA(RATE); - - // timed reset of flags - scd_mode_dmna_ret_flags |= 0x0021; - - m_dma_timer->adjust(attotime::from_hz(get_framerate()) / double(m_total_scanlines)); - -} - -// todo: tidy up, too many CDC internals here -void sega_segacd_device::SegaCD_CDC_Do_DMA(int &dmacount, uint8_t *CDC_BUFFER, uint16_t &dma_addrc, uint16_t &destination ) -{ - int length = dmacount; - uint16_t *dest; - int srcoffset = 0; - int dstoffset = 0; - - bool PCM_DMA = false; - - if (destination==DMA_PCM) - { - dstoffset = (m_dmaaddr & 0x03FF) << 2; - PCM_DMA = true; - } - else - { - dstoffset = (m_dmaaddr & 0xFFFF) << 3; - } - - - while (dmacount--) - { - uint16_t data = (CDC_BUFFER[dma_addrc+srcoffset]<<8) | CDC_BUFFER[dma_addrc+srcoffset+1]; - - if (destination==DMA_PRG) - { - dest = m_prgram; - } - else if (destination==DMA_WRAM) - { - dest = m_dataram; - } - else if (destination==DMA_PCM) - { - dest = nullptr;//fatalerror("PCM RAM DMA unimplemented!\n"); - } - else - { - fatalerror("Unknown DMA Destination!!\n"); - } - - if (PCM_DMA) - { - m_rfsnd->rf5c68_mem_w(dstoffset & 0xfff, data >> 8); - m_rfsnd->rf5c68_mem_w((dstoffset+1) & 0xfff, data); - // printf("PCM_DMA writing %04x %04x\n",0xff2000+(dstoffset*2), data); - } - else - { - if (dest) - { - if (destination==DMA_WRAM) - { - if ((scd_rammode&2)==RAM_MODE_2MEG) - { - dstoffset &= 0x3ffff; - - dest[dstoffset/2] = data; - - segacd_mark_tiles_dirty(dstoffset/2); - } - else - { - dstoffset &= 0x1ffff; - - if (!(scd_rammode & 1)) - { - segacd_1meg_mode_word_write((dstoffset+0x20000)/2, data, 0xffff, 0); - } - else - { - segacd_1meg_mode_word_write((dstoffset+0x00000)/2, data, 0xffff, 0); - } - } - - } - else - { - // main ram - dest[dstoffset/2] = data; - } - - } - } - - srcoffset += 2; - dstoffset += 2; - } - - - if (PCM_DMA) - { - m_dmaaddr += length >> 1; - } - else - { - m_dmaaddr += length >> 2; - } -} diff --git a/src/mame/segacons/megacd.h b/src/mame/segacons/megacd.h deleted file mode 100644 index 13bcb2579da..00000000000 --- a/src/mame/segacons/megacd.h +++ /dev/null @@ -1,229 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/* Sega CD / Mega CD */ -#ifndef MAME_MACHINE_MEGACD_H -#define MAME_MACHINE_MEGACD_H - -#pragma once - -#include "cpu/m68000/m68000.h" -#include "machine/lc89510.h" -#include "megacdcd.h" -#include "sound/rf5c68.h" -#include "screen.h" -#include "tilemap.h" - -class sega_segacd_device : public device_t, public device_gfx_interface, public device_video_interface -{ -public: - template void set_hostcpu(T &&tag) { m_hostcpu.set_tag(std::forward(tag)); } - - // set some variables at start, depending on region (shall be moved to a device interface?) - void set_framerate(int rate) { m_framerate = rate; } - void set_total_scanlines(int total) { m_base_total_scanlines = total; } // this gets set at start only - void update_total_scanlines(bool mode3) { m_total_scanlines = mode3 ? (m_base_total_scanlines * 2) : m_base_total_scanlines; } // this gets set at each EOF - double get_framerate() { return has_screen() ? screen().frame_period().as_hz() : double(m_framerate); } - - uint16_t segacd_dmaaddr_r(); - void segacd_dmaaddr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - - void scd_a12000_halt_reset_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t scd_a12000_halt_reset_r(); - uint16_t scd_a12002_memory_mode_r(); - void scd_a12002_memory_mode_w_8_15(u8 data); - void scd_a12002_memory_mode_w_0_7(u8 data); - void scd_a12002_memory_mode_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_sub_memory_mode_r(); - void segacd_sub_memory_mode_w_8_15(u8 data); - void segacd_sub_memory_mode_w_0_7(u8 data); - void segacd_sub_memory_mode_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - - uint16_t segacd_comms_flags_r(); - void segacd_comms_flags_subcpu_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - void segacd_comms_flags_maincpu_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t scd_4m_prgbank_ram_r(offs_t offset); - void scd_4m_prgbank_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_comms_main_part1_r(offs_t offset); - void segacd_comms_main_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_comms_main_part2_r(offs_t offset); - void segacd_comms_main_part2_w(uint16_t data); - uint16_t segacd_comms_sub_part1_r(offs_t offset); - void segacd_comms_sub_part1_w(uint16_t data); - uint16_t segacd_comms_sub_part2_r(offs_t offset); - void segacd_comms_sub_part2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - - - - uint16_t segacd_main_dataram_part1_r(offs_t offset); - void segacd_main_dataram_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - - uint16_t scd_hint_vector_r(offs_t offset); - uint16_t scd_a12006_hint_register_r(); - void scd_a12006_hint_register_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - - - void segacd_stopwatch_timer_w(uint16_t data); - uint16_t segacd_stopwatch_timer_r(); - uint16_t segacd_sub_led_ready_r(offs_t offset, uint16_t mem_mask = ~0); - void segacd_sub_led_ready_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_sub_dataram_part1_r(offs_t offset); - void segacd_sub_dataram_part1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_sub_dataram_part2_r(offs_t offset); - void segacd_sub_dataram_part2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - - - uint16_t segacd_stampsize_r(); - void segacd_stampsize_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - - TILE_GET_INFO_MEMBER( get_stampmap_16x16_1x1_tile_info ); - TILE_GET_INFO_MEMBER( get_stampmap_32x32_1x1_tile_info ); - TILE_GET_INFO_MEMBER( get_stampmap_16x16_16x16_tile_info ); - TILE_GET_INFO_MEMBER( get_stampmap_32x32_16x16_tile_info ); - - void segacd_trace_vector_base_address_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_imagebuffer_vdot_size_r(); - void segacd_imagebuffer_vdot_size_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_stampmap_base_address_r(); - void segacd_stampmap_base_address_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_imagebuffer_start_address_r(); - void segacd_imagebuffer_start_address_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_imagebuffer_offset_r(); - void segacd_imagebuffer_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_imagebuffer_vcell_size_r(); - void segacd_imagebuffer_vcell_size_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_imagebuffer_hdot_size_r(); - void segacd_imagebuffer_hdot_size_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t segacd_irq3timer_r(); - void segacd_irq3timer_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint8_t backupram_r(offs_t offset); - void backupram_w(offs_t offset, uint8_t data); - uint8_t font_color_r(); - void font_color_w(uint8_t data); - uint16_t font_converted_r(offs_t offset); - - void segacd_map(address_map &map); - void segacd_pcm_map(address_map &map); -protected: - sega_segacd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - // optional information overrides - virtual void device_add_mconfig(machine_config &config) override; - - required_device m_scdcpu; - required_device m_hostcpu; - required_device m_rfsnd; - required_device m_lc89510_temp; - required_device m_stopwatch_timer; - required_device m_stamp_timer; - required_device m_irq3_timer; - required_device m_dma_timer; - //required_device m_hock_timer; - - required_shared_ptr m_prgram; - required_shared_ptr m_dataram; - required_shared_ptr m_font_bits; - - output_finder<> m_red_led; - output_finder<> m_green_led; - - // can't use a memshare because it's 8-bit RAM in a 16-bit address space - std::vector m_backupram; - - uint8_t m_font_color = 0; - - uint16_t scd_rammode = 0; - uint32_t scd_mode_dmna_ret_flags = 0; - - tilemap_t *segacd_stampmap[4]{}; - - - uint8_t segacd_ram_writeprotect_bits = 0; - int segacd_4meg_prgbank = 0; // which bank the MainCPU can see of the SubCPU PrgRAM - int segacd_memory_priority_mode = 0; - int segacd_stampsize = 0; - - uint16_t segacd_hint_register = 0; - uint16_t segacd_imagebuffer_vdot_size = 0; - uint16_t segacd_imagebuffer_vcell_size = 0; - uint16_t segacd_imagebuffer_hdot_size = 0; - - int segacd_conversion_active = 0; - uint16_t segacd_stampmap_base_address = 0; - uint16_t segacd_imagebuffer_start_address = 0; - uint16_t segacd_imagebuffer_offset = 0; - - - uint16_t segacd_comms_flags = 0; - uint16_t segacd_comms_part1[0x8]{}; - uint16_t segacd_comms_part2[0x8]{}; - - int segacd_redled = 0; - int segacd_greenled = 0; - int segacd_ready = 1; // actually set 100ms after startup? - uint8_t m_irq3_timer_reg = 0; - - - inline void write_pixel(uint8_t pix, int pixeloffset); - uint16_t segacd_1meg_mode_word_read(offs_t offset); - void segacd_1meg_mode_word_write(offs_t offset, uint16_t data, uint16_t mem_mask, int use_pm); - - uint16_t m_dmaaddr = 0; - - uint16_t m_a12000_halt_reset_reg = 0; - - int m_framerate = 0; - int m_base_total_scanlines = 0; - int m_total_scanlines = 0; - - void segacd_mark_tiles_dirty(int offset); - int segacd_get_active_stampmap_tilemap(void); - - void SCD_GET_TILE_INFO_16x16_1x1( int& tile_region, int& tileno, int tile_index ); - void SCD_GET_TILE_INFO_32x32_1x1( int& tile_region, int& tileno, int tile_index ); - void SCD_GET_TILE_INFO_16x16_16x16( int& tile_region, int& tileno, int tile_index ); - void SCD_GET_TILE_INFO_32x32_16x16( int& tile_region, int& tileno, int tile_index ); - - uint8_t get_stampmap_16x16_1x1_tile_info_pixel(int xpos, int ypos); - uint8_t get_stampmap_32x32_1x1_tile_info_pixel(int xpos, int ypos); - uint8_t get_stampmap_16x16_16x16_tile_info_pixel(int xpos, int ypos); - uint8_t get_stampmap_32x32_16x16_tile_info_pixel(int xpos, int ypos); - - uint8_t read_pixel_from_stampmap(bitmap_ind16* srcbitmap, int x, int y); - - virtual void device_start() override; - virtual void device_reset() override; - - TIMER_DEVICE_CALLBACK_MEMBER( dma_timer_callback ); - IRQ_CALLBACK_MEMBER(segacd_sub_int_callback); - - TIMER_DEVICE_CALLBACK_MEMBER( irq3_timer_callback ); - TIMER_DEVICE_CALLBACK_MEMBER( stamp_timer_callback ); - - void SegaCD_CDC_Do_DMA( int &dmacount, uint8_t *CDC_BUFFER, uint16_t &dma_addrc, uint16_t &destination ); -}; - - -class sega_segacd_us_device : public sega_segacd_device -{ -public: - sega_segacd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - -class sega_segacd_japan_device : public sega_segacd_device -{ -public: - sega_segacd_japan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - -class sega_segacd_europe_device : public sega_segacd_device -{ -public: - sega_segacd_europe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - - -DECLARE_DEVICE_TYPE(SEGA_SEGACD_US, sega_segacd_us_device) -DECLARE_DEVICE_TYPE(SEGA_SEGACD_JAPAN, sega_segacd_japan_device) -DECLARE_DEVICE_TYPE(SEGA_SEGACD_EUROPE, sega_segacd_europe_device) - -#endif // MAME_MACHINE_MEGACD_H diff --git a/src/mame/segacons/megadriv_rad.cpp b/src/mame/segacons/megadriv_rad.cpp deleted file mode 100644 index 42e14b90572..00000000000 --- a/src/mame/segacons/megadriv_rad.cpp +++ /dev/null @@ -1,692 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood - -/* - Radica 'Mega Drive' and 'Genesis' clones - these were mini battery operated "TV Game" consoles with wired in controller and no cartslot - fully licensed by Sega - - reproduction 'System on a Chip' hardware, not perfect, flaws will need emulating eventually. - - not dumped - - Genesis Volume 2 - Genesis SF2 / GnG (PAL one is locked to PAL) - - Outrun 2019 (probably identical ROM to MD version, just custom controller) - - more? - -*/ - -#include "emu.h" -#include "megadriv.h" -#include "megadriv_rad.h" - -// todo, use actual MD map, easier once maps are part of base class. -void megadriv_radica_state::megadriv_base_map(address_map &map) -{ - map(0x000000, 0x3fffff).r(FUNC(megadriv_radica_state::read)); /* Cartridge Program Rom */ - map(0xa00000, 0xa01fff).rw(FUNC(megadriv_radica_state::megadriv_68k_read_z80_ram), FUNC(megadriv_radica_state::megadriv_68k_write_z80_ram)); - map(0xa02000, 0xa03fff).w(FUNC(megadriv_radica_state::megadriv_68k_write_z80_ram)); - map(0xa04000, 0xa04003).rw(FUNC(megadriv_radica_state::megadriv_68k_YM2612_read), FUNC(megadriv_radica_state::megadriv_68k_YM2612_write)); - map(0xa06000, 0xa06001).w(FUNC(megadriv_radica_state::megadriv_68k_z80_bank_write)); - map(0xa10000, 0xa1001f).rw(FUNC(megadriv_radica_state::megadriv_68k_io_read), FUNC(megadriv_radica_state::megadriv_68k_io_write)); - map(0xa11100, 0xa11101).rw(FUNC(megadriv_radica_state::megadriv_68k_check_z80_bus), FUNC(megadriv_radica_state::megadriv_68k_req_z80_bus)); - map(0xa11200, 0xa11201).w(FUNC(megadriv_radica_state::megadriv_68k_req_z80_reset)); - map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); - map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram"); -} - -void megadriv_radica_state::megadriv_radica_map(address_map &map) -{ - megadriv_base_map(map); - map(0xa13000, 0xa130ff).r(FUNC(megadriv_radica_state::read_a13)); -} - -uint16_t megadriv_dgunl_state::read_a16300(offs_t offset, uint16_t mem_mask) -{ - return 0x5a5a; -} - -uint16_t megadriv_dgunl_state::read_a16302(offs_t offset, uint16_t mem_mask) -{ - return m_a1630a; -} - -void megadriv_dgunl_state::write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - m_a1630a = data; - m_bank = (data & 0x07) * 8; -} - - -void megadriv_ra145_state::write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - // the banking must know how big each game is to get the base location, as it only writes a game number?! - // it must also know to skip the unused copy of Golden Axe - // there must be a table somewhere, or, if this is actually an emulation based system, it must be scanning - // for headers somehow? - - m_a1630a = data; - - switch (data & 0xff) - { - - - // 0x0000000 = Block of unknown data/code - // 0x0040000 = 145 in 1 menu - // (includes unused Columns, Fatal Labyrinth, Blockout, Flicky, Shove It, Space Invaders 90 as part of menu data) - case 0x00: m_bank = 0x02c0000; break;// = Fantasia 00 - case 0x01: m_bank = 0x0340000; break;// = Fire Shark 01 - case 0x02: m_bank = 0x03c0000; break;// = James Bond 007 - The Duel 02 (BAD ROM) - case 0x03: m_bank = 0x0440000; break;// = Sunset Riders 03 - case 0x04: m_bank = 0x04c0000; break;// = Robocop 3 04 - case 0x05: m_bank = 0x0540000; break;// = Hokuto no Ken 05 (BAD ROM) - case 0x06: m_bank = 0x05c0000; break;// = Alien 3 06 - case 0x07: m_bank = 0x0640000; break;// = Batman 07 (BAD ROM) - case 0x08: m_bank = 0x06c0000; break;// = Cat 08 - case 0x09: m_bank = 0x0740000; break;// = DJ Boy 09 - case 0x0a: m_bank = 0x07c0000; break;// = Rambo 3 0a (BAD ROM) - case 0x0b: m_bank = 0x0840000; break;// = Wardner 0b - case 0x0c: m_bank = 0x08c0000; break;// = Paperboy 0c - case 0x0d: m_bank = 0x0940000; break;// = Streets of Rage 0d - case 0x0e: m_bank = 0x09c0000; break;// = Tiny Toon Adventures 0e - case 0x0f: m_bank = 0x0a40000; break;// = Super Battleship 0f - case 0x10: m_bank = 0x0ac0000; break;// = Burning Force 10 - case 0x11: m_bank = 0x0b40000; break;// = Cadash 11 - case 0x12: m_bank = 0x0bc0000; break;// = Caesars Palace 12 - case 0x13: m_bank = 0x0c40000; break;// = chase HQ 2 13 - case 0x14: m_bank = 0x0cc0000; break;// = Wonderboy 3 14 - case 0x15: m_bank = 0x0d40000; break;// = Fighting Master 15 - case 0x16: m_bank = 0x0dc0000; break;// = The Flintstones 16 - case 0x17: m_bank = 0x0e40000; break;// = Ariel the Little Mermaid 17 - case 0x18: m_bank = 0x0ec0000; break;// = Hellfire 18 - case 0x19: m_bank = 0x0f40000; break;// = Arrow Flash 19 - case 0x1a: m_bank = 0x0fc0000; break;// = Shove It 1a - case 0x1b: m_bank = 0x1040000; break;// = Donkey Kong 99 1b - case 0x1c: m_bank = 0x1240000; break;// = Turtles Tournament 1c - case 0x1d: m_bank = 0x1440000; break;// = Thunder Force 2 1d (This is meant to be Revenge of Shinobi according to the menu, but incorrect game was in the ROM) - case 0x1e: m_bank = 0x14c0000; break;// = Wings of Wor 1e - case 0x1f: m_bank = 0x1540000; break;// = Wrestle War 1f - case 0x20: m_bank = 0x15c0000; break;// = Afterburner 2 20 - case 0x21: m_bank = 0x1640000; break;// = Altered Beast 21 - case 0x22: m_bank = 0x16c0000; break;// = Captain Planet 22 - case 0x23: m_bank = 0x1740000; break;// = Bimimi Run 23 - case 0x24: m_bank = 0x17c0000; break;// = Osomatsu 24 - case 0x25: m_bank = 0x1840000; break;// = Castle of Illusion 25 - case 0x26: m_bank = 0x18c0000; break;// = Crackdown 26 - case 0x27: m_bank = 0x1940000; break;// = Crossfire 27 - case 0x28: m_bank = 0x19c0000; break;// = Curse 28 - case 0x29: m_bank = 0x1a40000; break;// = Dangerous Seed 29 - case 0x2a: m_bank = 0x1ac0000; break;// = Dark Castle 2a - case 0x2b: m_bank = 0x1b40000; break;// = Darwin 2b - case 0x2c: m_bank = 0x1bc0000; break;// = Thunder Force 2 (duplicate?) 2c - case 0x2d: m_bank = 0x1c40000; break;// = Dynamite Duke 2d - case 0x2e: m_bank = 0x1cc0000; break;// = EA Hockey 2e - case 0x2f: m_bank = 0x1d40000; break;// = Elemenal Master 2f - case 0x30: m_bank = 0x1dc0000; break;// = Super Thunder Blade 30 - case 0x31: m_bank = 0x1e40000; break;// = Target Earth 31 - case 0x32: m_bank = 0x1ec0000; break;// = Rastan Saga 2 32 - case 0x33: m_bank = 0x1f40000; break;// = Ghostbusters 33 - case 0x34: m_bank = 0x1fc0000; break;// = Mahjong cop 34 - case 0x35: m_bank = 0x2040000; break;// = High School Soccer 35 - case 0x36: m_bank = 0x20c0000; break;// = Insector X 36 - case 0x37: m_bank = 0x2140000; break;// = Pheilos 37 - case 0x38: m_bank = 0x21c0000; break;// = Runark 38 - case 0x39: m_bank = 0x2240000; break;// = Saint Sword 39 - case 0x3a: m_bank = 0x22c0000; break;// = Shadow Dancer 3a - case 0x3b: m_bank = 0x2340000; break;// = Shiten Myooh 3b - case 0x3c: m_bank = 0x23c0000; break;// = Wani Wani World 3c - case 0x3d: m_bank = 0x2440000; break;// = Street Mmart 3d - case 0x3e: m_bank = 0x24c0000; break;// = Toki 3e - case 0x3f: m_bank = 0x2540000; break;// = Trouble Shooter 3f - case 0x40: m_bank = 0x25c0000; break;// = Truxton 40 - case 0x41: m_bank = 0x2640000; break;// = James Pond 2 41 - case 0x42: m_bank = 0x26c0000; break;// = Twin Hawk 42 - case 0x43: m_bank = 0x2740000; break;// = Syd of Valis 43 - case 0x44: m_bank = 0x27c0000; break;// = Zoom 44 - case 0x45: m_bank = 0x2840000; break;// = Streets of Rage 2 45 - case 0x46: m_bank = 0x2a40000; break;// = Sonic & Knuckles 46 - case 0x47: m_bank = 0x2c40000; break;// = Comix Zone 47 - case 0x48: m_bank = 0x2e40000; break;// = Rolling Thunder 2 48 - case 0x49: m_bank = 0x2f40000; break;// = Bubble & Squeek 49 - case 0x4a: m_bank = 0x2fc0000; break;// = Alex Kidd 4a - case 0x4b: m_bank = 0x3040000; break;// = Super Mario 2 4b - case 0x4c: m_bank = 0x3240000; break;// = NBA All Star 4c - case 0x4d: m_bank = 0x3340000; break;// = Bio Hazard Battle 4d - case 0x4e: m_bank = 0x3440000; break;// = Prince of Persia 4e - case 0x4f: m_bank = 0x3540000; break;// = Champions World Soccer 4f - case 0x50: m_bank = 0x3640000; break;// = Lotus 2 50 - case 0x51: m_bank = 0x3740000; break;// = Grandia 51 - case 0x52: m_bank = 0x37c0000; break;// = World Cup Soccer 52 - case 0x53: m_bank = 0x3840000; break;// = Ultimate Mortal Kombat 3 53 - case 0x54: m_bank = 0x3c40000; break;// = Street Fighter II (hacked MSI version) 54 - case 0x55: m_bank = 0x3f40000; break;// = Verytex 55 - case 0x56: m_bank = 0x3fc0000; break;// = Space Invaders 90 56 - - //This 32MBytes of the ROM has its own unused '666666 in 1 menu' and only references games - //within this block; it was probably released as a standalone using this 32Mbytes of ROM - // 0x4000000 = Block of unknown data/code - // 0x4040000 = 666666 in 1 menu - // (includes unused Columns, Fatal Labyrinth, Blockout, Flicky, Shove It, Space Invaders 90 as part of menu data) - // 0x42c0000 - Golden Axe -- (not used by 145-in-1 menu, no assigned number either?!) - case 0x57: m_bank = 0x4340000; break;// - Mega Bomberman 57 - case 0x58: m_bank = 0x4440000; break;// - Dragon The Bruce Lee Story 58 - case 0x59: m_bank = 0x4640000; break;// - Twinkle Tale 59 - case 0x5a: m_bank = 0x4740000; break;// - Jewel Master 5a - case 0x5b: m_bank = 0x47c0000; break;// - Pacmania 5b - case 0x5c: m_bank = 0x4840000; break;// - X-Men 2 5c - case 0x5d: m_bank = 0x4a40000; break;// - Top Gear 2 5d - case 0x5e: m_bank = 0x4b40000; break;// - Brian Lara Cricket 5e - case 0x5f: m_bank = 0x4c40000; break;// - Garfield 5f - case 0x60: m_bank = 0x4e40000; break;// - Raiden Trad 60 - case 0x61: m_bank = 0x4f40000; break;// - James Pond 61 - case 0x62: m_bank = 0x4fc0000; break;// - Mega Panel 62 - case 0x63: m_bank = 0x5040000; break;// - James Pond 3 63 - case 0x64: m_bank = 0x5240000; break;// - Contra Hardcorps 64 - case 0x65: m_bank = 0x5440000; break;// - International Superstar Soccer Deluxe 65 - case 0x66: m_bank = 0x5640000; break;// - Double Dragon 3 (with Trainer) 66 - case 0x67: m_bank = 0x5740000; break;// - Micro Machines 67 - case 0x68: m_bank = 0x57c0000; break;// - Hard Drivin' 68 - case 0x69: m_bank = 0x5840000; break;// - Dragon Ball Z 69 - case 0x6a: m_bank = 0x5a40000; break;// - F1 World Championship Edition 6a - case 0x6b: m_bank = 0x5c40000; break;// - Megaman / Rockman -- (6b, but unused? probably due to save feature?) - case 0x6c: m_bank = 0x5e40000; break;// - Operation Vapor Trail 6c - case 0x6d: m_bank = 0x5f40000; break;// - Roadblasters 6d - case 0x6e: m_bank = 0x5fc0000; break;// - Super Volleyball 6e - - //The final 32MBytes of the ROM has its own unused '888888 in 1 menu' and only references games - //within this block; it was probably released as a standalone using this 32Mbytes of ROM - // 0x6000000 = Block of unknown data/code - // 0x6040000 = 888888 in 1 menu - // (includes unused Columns, Fatal Labyrinth, Blockout, Flicky, Shove It, Space Invaders 90 as part of menu data) - case 0x6f: m_bank = 0x62c0000; break;// - Last Battle 6f - case 0x70: m_bank = 0x6340000; break;// - Shinobi III 70 - case 0x71: m_bank = 0x6440000; break;// - Mickey Mania 71 - case 0x72: m_bank = 0x6640000; break;// - Snow Bros 72 - case 0x73: m_bank = 0x6740000; break;// - Space Harrier II 73 - case 0x74: m_bank = 0x67c0000; break;// - Volfied 74 - case 0x75: m_bank = 0x6840000; break;// - Goofy's Hysterical History Tour 75 - case 0x76: m_bank = 0x6940000; break;// - Mighty Max 76 - case 0x77: m_bank = 0x6a40000; break;// - Mr Nutz 77 - case 0x78: m_bank = 0x6b40000; break;// - Sonic 2 78 - case 0x79: m_bank = 0x6c40000; break;// - Ecco Jr. 79 - case 0x7a: m_bank = 0x6d40000; break;// - Desert Demolition 7a - case 0x7b: m_bank = 0x6e40000; break;// - Midnight Resistance 7b - case 0x7c: m_bank = 0x6f40000; break;// - Spiderman vs The Kingpin 7c - case 0x7d: m_bank = 0x6fc0000; break;// - Trampoline Terror 7d - case 0x7e: m_bank = 0x7040000; break;// - MUSHA 7e - case 0x7f: m_bank = 0x70c0000; break;// - Sonic 7f - case 0x80: m_bank = 0x7140000; break;// - Thunder Force III 80 - case 0x81: m_bank = 0x71c0000; break;// - Golden Axe (again) 81 - // 0x7240000; break;// - Controller Test Menu -- (unused) - // 0x7340000; break;// - Controller Test Menu (again) -- (unused) - case 0x82: m_bank = 0x7440000; break;// - Wacky Worlds 82 (writes 93, incorrectly swapped in menu with Wacky Worlds) - case 0x83: m_bank = 0x7540000; break;// - Bonkers 83 - case 0x84: m_bank = 0x7640000; break;// - Alisia Dragoon 84 - case 0x85: m_bank = 0x7740000; break;// - Super Hang On 85 - case 0x86: m_bank = 0x77c0000; break;// - Dragon's Eye Shanghai 3 86 - case 0x87: m_bank = 0x7840000; break;// - Jimmy White's Whirlwind Snooker 87 - case 0x88: m_bank = 0x78c0000; break;// - Home Alone 2 88 - case 0x89: m_bank = 0x7940000; break;// - Xenon 2 (with trainer) 89 - case 0x8a: m_bank = 0x79c0000; break;// - Hit the Ice 8a - case 0x8b: m_bank = 0x7a40000; break;// - Tale Spin 8b - case 0x8c: m_bank = 0x7ac0000; break;// - Puyo Puyo 8c - case 0x8d: m_bank = 0x7b40000; break;// - Rampart (with trainer) 8d - case 0x8e: m_bank = 0x7bc0000; break;// - Crue Ball 8e - case 0x8f: m_bank = 0x7c40000; break;// - Marble Madness 8f - case 0x90: m_bank = 0x7cc0000; break;// - Patlabor 90 - case 0x91: m_bank = 0x7d40000; break;// - The Aquatic Games 91 - case 0x92: m_bank = 0x7dc0000; break;// - King Salmon 92 - case 0x93: m_bank = 0x7e40000; break;// - Fun n Games 93 (writes 82, incorrectly swapped in menu with Fun n Games) - case 0x94: m_bank = 0x7f40000; break;// - Gynoug 94 - case 0x95: m_bank = 0x7fc0000; break;// - Ms. Pac-Man 95 - default: m_bank = 0x0040000; break; - } - - m_bank = m_bank / 0x10000; -} - - -void megadriv_dgunl_state::megadriv_dgunl_map(address_map &map) -{ - megadriv_base_map(map); - - map(0xa16300, 0xa16301).r(FUNC(megadriv_dgunl_state::read_a16300)); - map(0xa16302, 0xa16303).r(FUNC(megadriv_dgunl_state::read_a16302)); - - map(0xa1630a, 0xa1630b).w(FUNC(megadriv_dgunl_state::write_a1630a)); -} - -uint16_t megadriv_radica_state::read(offs_t offset) -{ - return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (m_romsize - 1))/2]; -} - -uint16_t megadriv_radica_state::read_a13(offs_t offset) -{ - if (offset < 0x80) - m_bank = offset & 0x3f; - - // low bit gets set when selecting cannon fodder or mega lo mania in the rad_ssoc set, pointing to the wrong area, but rad_gen1 needs it for the menu - // as they're standalones it could just be different logic - if (m_bank != 0x3f) - m_bank &= 0x3e; - - return 0; -} - -// controller is wired directly into unit, no controller slots -static INPUT_PORTS_START( megadriv_radica_3button ) - PORT_INCLUDE( md_common ) - - PORT_MODIFY("PAD1") - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 ) - - PORT_MODIFY("PAD2") - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START2 ) -INPUT_PORTS_END - -// the 6-in-1 and Sonic Gold units really only have a single wired controller, and no way to connect a 2nd one, despite having some 2 player games! -static INPUT_PORTS_START( megadriv_radica_3button_1player ) - PORT_INCLUDE( megadriv_radica_3button ) - - PORT_MODIFY("PAD2") - PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) -INPUT_PORTS_END - -static INPUT_PORTS_START( megadriv_radica_6button ) - PORT_INCLUDE( megadriv_radica_3button ) - - PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IN0") - PORT_START("UNK") -INPUT_PORTS_END - -static INPUT_PORTS_START( megadriv_msi_6button ) - PORT_INCLUDE( megadriv_radica_3button ) - - PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("EXTRA2") // no 2nd pad - PORT_BIT( 0x000f, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_MODIFY("PAD2") // no 2nd pad - PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("IN0") - PORT_START("UNK") -INPUT_PORTS_END - -static INPUT_PORTS_START( megadriv_dgunl_1player ) - PORT_INCLUDE( megadriv_radica_3button ) - - PORT_MODIFY("PAD1") // the unit only has 2 buttons, A and C, strings are changed to remove references to C, even if behavior in Pac-Mania still exists and differs between them - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED ) // disable 'C' - //PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNUSED ) // disable 'A' - - PORT_MODIFY("PAD2") - PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) -INPUT_PORTS_END - -void megadriv_radica_6button_state::machine_start() -{ - md_base_state::machine_start(); - m_vdp->stop_timers(); - - m_io_pad_6b[0] = ioport("EXTRA1"); - m_io_pad_6b[1] = ioport("EXTRA2"); - m_io_pad_6b[2] = ioport("IN0"); - m_io_pad_6b[3] = ioport("UNK"); - - // setup timers for 6 button pads - for (int i = 0; i < 3; i++) - m_io_timeout[i] = timer_alloc(FUNC(md_base_state::io_timeout_timer_callback), this); - - save_item(NAME(m_bank)); -} - -void megadriv_radica_3button_state::machine_start() -{ - md_base_state::machine_start(); - m_vdp->stop_timers(); - save_item(NAME(m_bank)); -} - - -void megadriv_dgunl_state::machine_start() -{ - megadriv_radica_3button_state::machine_start(); - m_a1630a = 0; - save_item(NAME(m_a1630a)); -} - -void megadriv_ra145_state::machine_start() -{ - md_base_state::machine_start(); - m_vdp->stop_timers(); - - m_io_pad_6b[0] = ioport("EXTRA1"); - m_io_pad_6b[1] = ioport("EXTRA2"); - m_io_pad_6b[2] = ioport("IN0"); - m_io_pad_6b[3] = ioport("UNK"); - - // setup timers for 6 button pads - for (int i = 0; i < 3; i++) - m_io_timeout[i] = timer_alloc(FUNC(md_base_state::io_timeout_timer_callback), this); - - m_a1630a = 0; - save_item(NAME(m_a1630a)); - save_item(NAME(m_bank)); -} - -void megadriv_ra145_state::machine_reset() -{ - m_bank = 4; - md_base_state::machine_reset(); -} - - -void megadriv_radica_3button_state::machine_reset() -{ - m_bank = 0; - md_base_state::machine_reset(); -} - -void megadriv_radica_3button_state::megadriv_radica_3button_ntsc(machine_config &config) -{ - md_ntsc(config); - m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); -} - -void megadriv_radica_3button_state::megadriv_radica_3button_pal(machine_config &config) -{ - md_pal(config); - m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); -} - -void megadriv_radica_6button_state::megadriv_radica_6button_pal(machine_config &config) -{ - md_pal(config); - m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); -} - -void megadriv_radica_6button_state::megadriv_radica_6button_ntsc(machine_config &config) -{ - md_ntsc(config); - m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map); -} - -void megadriv_dgunl_state::megadriv_dgunl_ntsc(machine_config &config) -{ - md_ntsc(config); - m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_dgunl_state::megadriv_dgunl_map); -} - -ROM_START( rad_sf2 ) - ROM_REGION( 0x400000, "maincpu", 0 ) - ROM_LOAD16_WORD_SWAP( "radica_megadrive_streetfighter2_usa.bin", 0x000000, 0x400000, CRC(a4426df8) SHA1(091f2a95ebd091141de5bcb83562c6087708cb32) ) -ROM_END - -ROM_START( rad_sf2p ) - ROM_REGION( 0x400000, "maincpu", 0 ) - ROM_LOAD16_WORD_SWAP( "radica_megadrive_streetfighter2_uk.bin", 0x000000, 0x400000, CRC(868afb44) SHA1(f4339e36272c18b1d49aa4095127ed18e0961df6) ) -ROM_END - -ROM_START( rad_gen1 ) - ROM_REGION( 0x400000, "maincpu", 0 ) - ROM_LOAD16_WORD_SWAP( "radica_megadrive_vol1_blue_usa.bin", 0x000000, 0x400000, CRC(3b4c8438) SHA1(5ed9c053f9ebc8d4bf571d57e562cf347585d158) ) -ROM_END - -ROM_START( rad_md1 ) - ROM_REGION( 0x400000, "maincpu", 0 ) - ROM_LOAD16_WORD_SWAP( "radica_megadrive_vol1_blue_europe.bin", 0x000000, 0x400000, CRC(85867db1) SHA1(ddc596e2e68dc872bc0679a2de7a295b4c6d6b8e) ) -ROM_END - -ROM_START( rad_gen2 ) - ROM_REGION( 0x400000, "maincpu", 0 ) - ROM_LOAD16_WORD_SWAP( "radica_genesis_vol2_red_usa.bin", 0x000000, 0x400000, CRC(7c1a0f0e) SHA1(a6441f75a4cd48f1563aeafdfbdde00202d4067c) ) -ROM_END - -ROM_START( rad_md2 ) - ROM_REGION( 0x400000, "maincpu", 0 ) - ROM_LOAD16_WORD_SWAP( "radica_megadrive_vol2_red_uk.bin", 0x000000, 0x400000, CRC(b68fd025) SHA1(b8f9c505653d6dd2b62840f078f828360faf8abc) ) -ROM_END - -ROM_START( rad_ssoc ) - ROM_REGION( 0x400000, "maincpu", 0 ) - ROM_LOAD( "radica_sensiblesoccer_uk.bin", 0x000000, 0x400000, CRC(b8745ab3) SHA1(0ab3f26e5ffd288e5a3a5db676951b9095299eb0) ) // should be byteswapped? -ROM_END - -ROM_START( rad_sonic ) - ROM_REGION( 0x400000, "maincpu", 0 ) - ROM_LOAD16_WORD_SWAP( "radica_supersonicgold_usa.bin", 0x000000, 0x400000, CRC(853c9140) SHA1(cf70a9cdd3be4d8d1b6195698db3a941f4908791) ) -ROM_END - -ROM_START( rad_sonicp ) - ROM_REGION( 0x400000, "maincpu", 0 ) - ROM_LOAD16_WORD_SWAP( "radica_supersonicgold_uk.bin", 0x000000, 0x400000, CRC(ed774018) SHA1(cc2f7183e128c947463e3a43a0184b835ea16db8) ) -ROM_END - -// once byteswapped this matches "outrun 2019 (usa) (beta).bin megadriv:outr2019up Out Run 2019 (USA, Prototype)" -// this was dumped from a PAL/UK unit, so maybe that 'beta' is really an alt Euro release, or was simply dumped from one of these Radica units and mislabeled? -ROM_START( rad_orun ) - ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASEFF ) - ROM_LOAD16_WORD_SWAP( "outrun.bin", 0x000000, 0x100000, CRC(4fd6d653) SHA1(57f0e4550ff883e4bb7857caef2c893c21f80b42) ) -ROM_END - -ROM_START( msi_sf2 ) - ROM_REGION( 0x400000, "maincpu", 0 ) - // The first part of the ROM seems to be a boot ROM for the enhanced MD clone menus, even if it does nothing here - // and is probably leftover from one of the multigame systems, hacked to only launch one game. We should emulate it... - // .. but the game ROM starts at 0xc8000 so we can cheat for now - ROM_LOAD16_WORD_SWAP( "29lv320.bin", 0x000000, 0xc8000, CRC(465b12f0) SHA1(7a058f6feb4f08f56ae0f7369c2ca9a9fe2ed40e) ) - ROM_CONTINUE(0x00000,0x338000) -ROM_END - -ROM_START( dgunl3227 ) - ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASE00 ) - // populated in init function - - ROM_REGION( 0x400000, "rom", 0 ) - ROM_LOAD16_WORD_SWAP( "myarcadepacman_s99jl032hbt1_9991227e_as_s29jl032h55tai01.bin", 0x000000, 0x400000, CRC(ecead966) SHA1(971e8da6eb720f670f4148c7e07922e4f24eb609) ) -ROM_END - - - -ROM_START( ra145 ) - /* - Data for the following games is corrupt (ranges approximate, based on areas of inconsistent readout) - - 3c0000 - 43ffff - James Bond 007 - The Duel (400171 - 41c600 is corrupt) - 4c0000 - 53ffff - Robocop 3 (507bd4 - 50ad43 is corrupt) - 540000 - 5bffff - Hokuto no Ken (540006 - 55fff2 is corrupt) - 640000 - 6bffff - Batman (640042 - 65ffaf is corrupt) - 7c0000 - 7fffff - Rambo 3 (7e031a - 7fffb9 is corrupt) - - Unfortunately as many of the games in this unit have been hacked, or are using pirate versions of the games - from the mid 90s (in a few cases, complete with trainers) that seem to have dropped out of circulation it - is not possible to repair the data in dump from the damaged unit. - - The unit also includes a duplicate copy of Thunder Force II instead of Revenge of Shinobi, this however - is not a dump issue, nor is Wacky Worlds being swapped with Fun and Games in the menu - */ - - ROM_REGION( 0x8000000, "maincpu", ROMREGION_ERASE00 ) - ROM_LOAD16_WORD_SWAP( "ra145.bin", 0x000000, 0x8000000, BAD_DUMP CRC(30583950) SHA1(855eae232e3830a505f9bc1a26edb3a7d15ce4d1) ) -ROM_END - - - - -void megadriv_radica_6button_state::init_megadriv_radica_6button_pal() -{ - init_megadrie(); - // 6 button game, so overwrite 3 button io handlers - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); -} - -void megadriv_radica_6button_state::init_megadriv_radica_6button_ntsc() -{ - init_megadriv(); - // 6 button game, so overwrite 3 button io handlers - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); -} - -void megadriv_dgunl_state::init_dgunl3227() -{ - uint8_t* rom = memregion("rom")->base(); - uint8_t* dst = memregion("maincpu")->base(); - size_t len = memregion("rom")->bytes(); - - std::vector buffer(len); - - for (int i = 0; i < len; i++) - buffer[i] = rom[i ^ 3]; - - std::copy(buffer.begin(), buffer.end(), &rom[0]); - - int baseaddr, size, dstaddr; - //baseaddr = 0x200000; size = 0x40000; // unknown data (unused menu data maybe?) - //baseaddr = 0x240000; size = 0x20000; // 'sample' program with UWOL header later too (lower part of menu program) - //baseaddr = 0x260000; size = 0x20000; // pirate version of Columns with Sega text removed - //baseaddr = 0x280000; size = 0x20000; // Fatal Labyrinth - //baseaddr = 0x2a0000; size = 0x20000; // pirate version of Block Out with EA logo and text removed - //baseaddr = 0x2c0000; size = 0x20000; // Flicky - //baseaddr = 0x2e0000; size = 0x20000; // Shove It - //baseaddr = 0x300000; size = 0x40000; // pirate version of Space Invaders 90 with Taito logos and copyright removed (also upper part of menu program - has extra header + bits of code for '202 in 1' menu which has been hacked to run the 3-in-1 menu) - - // the following 3 games are available to select from the menu on this system - //baseaddr = 0x340000; size = 0x40000; // Pac-Attack / Pac-Panic (used by this unit) - //baseaddr = 0x380000; size = 0x40000; // Pac-Mania (used by this unit) - //baseaddr = 0x3c0000; size = 0x40000; // Pac-Man (used by this unit) (2nd copy of header about halfway through?) - - // copy 1st part of menu code - baseaddr = 0x240000; - size = 0x020000; - dstaddr = 0x000000; - for (int i = 0; i < size; i++) - { - dst[i + dstaddr] = rom[baseaddr + i]; - } - - // copy 2nd part of menu code - baseaddr = 0x300000; - size = 0x040000; - dstaddr = 0x0c0000; - for (int i = 0; i < size; i++) - { - dst[i + dstaddr] = rom[baseaddr + i]; - } - - // copy pac-panic to first bank - baseaddr = 0x340000; - size = 0x040000; - dstaddr = 0x100000; - for (int i = 0; i < size; i++) - { - dst[i + dstaddr] = rom[baseaddr + i]; - } - - // copy pac-mania to 2nd bank - baseaddr = 0x380000; - size = 0x040000; - dstaddr = 0x180000; - for (int i = 0; i < size; i++) - { - dst[i + dstaddr] = rom[baseaddr + i]; - } - - // copy pac-man to 3nd bank - baseaddr = 0x3c0000; - size = 0x040000; - dstaddr = 0x200000; - for (int i = 0; i < size; i++) - { - dst[i + dstaddr] = rom[baseaddr + i]; - } - - // other data isn't copied because it's never referenced, therefore we don't know how it gets accessed - - init_megadriv(); -} - -void megadriv_ra145_state::init_ra145() -{ - m_romsize = 0x8000000; - init_megadriv(); - // 6 button game, so overwrite 3 button io handlers - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); -} - -// US versions show 'Genesis' on the menu, show a www.radicagames.com splash screen, and use NTSC versions of the ROMs, sometimes region locked -// EU versions show 'Mega Drive' on the menu, show a www.radicagames.com splash screen, and use PAL versions of the ROMs, sometimes region locked -// UK versions show "Mega Drive' on the menu, show a www.radicauk.com splash screen, and use PAL versions of the ROMs, sometimes region locked - - -CONS( 2004, rad_gen1, 0, 0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadriv, "Radica / Sega", "Genesis Collection Volume 1 (Radica, Arcade Legends) (USA)", 0) -CONS( 2004, rad_md1, rad_gen1, 0, megadriv_radica_3button_pal, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie, "Radica / Sega", "Mega Drive Collection Volume 1 (Radica, Arcade Legends) (Europe)", 0) -// A UK version exists, showing the Radica UK boot screen - -CONS( 2004, rad_gen2, 0, 0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadriv, "Radica / Sega", "Genesis Collection Volume 2 (Radica, Arcade Legends) (USA)", 0) -CONS( 2004, rad_md2, rad_gen2, 0, megadriv_radica_3button_pal, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie, "Radica / Sega", "Mega Drive Collection Volume 2 (Radica, Arcade Legends) (UK)", 0) -// is there a Europe version with Radica Games boot screen and Mega Drive text? - -// box calls this Volume 3 -CONS( 2004, rad_sonic, 0, 0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadriv, "Radica / Sega", "Super Sonic Gold (Radica Plug & Play) (USA)", 0) -CONS( 2004, rad_sonicp,rad_sonic,0, megadriv_radica_3button_pal, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie, "Radica / Sega", "Super Sonic Gold (Radica Plug & Play) (UK)", 0) -// is there a Europe version with Radica Games boot screen and Mega Drive text? - -CONS( 2004, rad_sf2, 0, 0, megadriv_radica_6button_ntsc, megadriv_radica_6button, megadriv_radica_6button_state, init_megadriv_radica_6button_ntsc,"Radica / Capcom / Sega", "Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (USA)", 0) -CONS( 2004, rad_sf2p, rad_sf2, 0, megadriv_radica_6button_pal, megadriv_radica_6button, megadriv_radica_6button_state, init_megadriv_radica_6button_pal, "Radica / Capcom / Sega", "Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (UK)", 0) -// is there a Europe version with Radica Games boot screen and Mega Drive text? - -// still branded as Arcade Legends even if none of these were ever arcade games, European exclusive -CONS( 2004, rad_ssoc, 0, 0, megadriv_radica_3button_pal, megadriv_radica_3button, megadriv_radica_3button_state, init_megadrie, "Radica / Sensible Software / Sega", "Sensible Soccer plus [Cannon Fodder, Mega lo Mania] (Radica, Arcade Legends) (UK)", 0) -// is there a Europe version with Radica Games boot screen and Mega Drive text? - -// not region locked, no Radica logos, uncertain if other regions would differ -CONS( 2004, rad_orun, 0, 0, megadriv_radica_3button_pal, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie, "Radica / Sega", "Out Run 2019 (Radica Plug & Play, UK)", 0) - -// From a European unit but NTSC? - code is hacked from original USA Genesis game with region check still intact? (does the clone hardware always identify as such? or does the bypassed boot code skip the check?) -// TODO: move out of here eventually once the enhanced MD part is emulated rather than bypassed (it's probably the same as the 145-in-1 multigame unit, but modified to only include this single game) -CONS( 2018, msi_sf2, 0, 0, megadriv_radica_6button_ntsc, megadriv_msi_6button, megadriv_radica_6button_state, init_megadriv_radica_6button_ntsc, "MSI / Capcom / Sega", "Street Fighter II: Special Champion Edition (MSI Plug & Play) (Europe)", 0) - -// Are these (dgunl3227, ra145) actually emulation based? there is a block of 0x40000 bytes at the start of the ROM that doesn't -// appear to be used, very similar in both units. Banking also seems entirely illogical unless something else is managing it. -// The menu code in both seems to have the same origin, containing a bunch of unused pirate versions of MD games. -// The version of SF2 in the 'ra145' unit is the same as the one in the MSI unit above, and expects region to report US even -// when some of the units run at PAL speed? -// It is also confirmed from real hardware videos that these units do not have the usual sprite limits (so masking effect on Sonic title screen fails) - -// this is the only 'Pocket Player' unit to use Genesis on a Chip tech, the others are NES on a chip. -// some versions of this unit have an additional "Add Credits with 'A' or 'B'" screen after you select Pac-Man, this version does not. -CONS( 2018, dgunl3227, 0, 0, megadriv_dgunl_ntsc, megadriv_dgunl_1player, megadriv_dgunl_state, init_dgunl3227, "dreamGEAR", "My Arcade Pac-Man Pocket Player (DGUNL-3227)", 0 ) - -CONS( 2018, ra145, 0, 0, megadriv_dgunl_ntsc, megadriv_msi_6button, megadriv_ra145_state, init_ra145, "", "Retro Arcade 16 Bits Classic Edition Mini TV Game Console - 145 Classic Games - TV Arcade Plug and Play (Mega Drive bootlegs)", MACHINE_NOT_WORKING ) - diff --git a/src/mame/segacons/megadriv_rad.h b/src/mame/segacons/megadriv_rad.h deleted file mode 100644 index cc3bbde3316..00000000000 --- a/src/mame/segacons/megadriv_rad.h +++ /dev/null @@ -1,107 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood - -#ifndef MAME_INCLUDES_MEGADRIV_RAD_H -#define MAME_INCLUDES_MEGADRIV_RAD_H - -class megadriv_radica_state : public md_base_state -{ -public: - megadriv_radica_state(const machine_config &mconfig, device_type type, const char *tag) - : md_base_state(mconfig, type, tag), - m_bank(0), - m_romsize(0x400000), - m_rom(*this, "maincpu") - {} - - - uint16_t read(offs_t offset); - uint16_t read_a13(offs_t offset); - - void megadriv_radica_map(address_map &map); - -protected: - void megadriv_base_map(address_map &map); - int m_bank; - int m_romsize; - -private: - required_region_ptr m_rom; -}; - -class megadriv_radica_3button_state : public megadriv_radica_state -{ -public: - megadriv_radica_3button_state(const machine_config& mconfig, device_type type, const char* tag) - : megadriv_radica_state(mconfig, type, tag) - {} -public: - void megadriv_radica_3button_ntsc(machine_config &config); - void megadriv_radica_3button_pal(machine_config &config); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; -}; - -class megadriv_radica_6button_state : public megadriv_radica_3button_state -{ -public: - void megadriv_radica_6button_ntsc(machine_config &config); - void megadriv_radica_6button_pal(machine_config &config); - - void init_megadriv_radica_6button_pal(); - void init_megadriv_radica_6button_ntsc(); - -public: - megadriv_radica_6button_state(const machine_config& mconfig, device_type type, const char* tag) - : megadriv_radica_3button_state(mconfig, type, tag) - {} - virtual void machine_start() override; -}; - -class megadriv_dgunl_state : public megadriv_radica_3button_state -{ -public: - megadriv_dgunl_state(const machine_config& mconfig, device_type type, const char* tag) - : megadriv_radica_3button_state(mconfig, type, tag) - {} -public: - void megadriv_dgunl_ntsc(machine_config &config); - - void init_dgunl3227(); - -protected: - virtual void machine_start() override; - uint16_t m_a1630a = 0; - -private: - uint16_t read_a16300(offs_t offset, uint16_t mem_mask); - uint16_t read_a16302(offs_t offset, uint16_t mem_mask); - virtual void write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask); - - void megadriv_dgunl_map(address_map &map); -}; - -class megadriv_ra145_state : public megadriv_dgunl_state -{ -public: - megadriv_ra145_state(const machine_config& mconfig, device_type type, const char* tag) - : megadriv_dgunl_state(mconfig, type, tag) - {} - - void init_ra145(); - -public: - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - -private: - virtual void write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask) override; -}; - - - -#endif // MAME_INCLUDES_MEGADRIV_RAD_H diff --git a/src/mame/segacons/megadriv_sunplus_hybrid.cpp b/src/mame/segacons/megadriv_sunplus_hybrid.cpp deleted file mode 100644 index 678d84863da..00000000000 --- a/src/mame/segacons/megadriv_sunplus_hybrid.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood - -/* - This is an enhanced 'Mega Drive / Genesis on a Chip' combined with a SunPlus SPG2xx system for the 'Bonus Games' menu - - It can take MegaDrive cartridges - - The MD side of things doesn't work as it needs enhanced chipset emulation? - - TODO: - hook up the SunPlus side again (see spg2xx_zone.cpp for hookup) - -*/ - -#include "emu.h" -#include "megadriv.h" - -class megadriv_sunplus_state : public md_base_state -{ -public: - megadriv_sunplus_state(const machine_config &mconfig, device_type type, const char *tag) - // Mega Drive part - : md_base_state(mconfig, type, tag), - m_md_is_running(true), - m_bank(0), - m_rom(*this, "maincpu") - {} - - // Mega Drive part - uint16_t read(offs_t offset); - void megadriv_sunplus_pal(machine_config &config); - void megadriv_sunplus_map(address_map &map); - - void init_reactmd(); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - -private: - bool m_md_is_running; - - // Mega Drive part - int m_bank; - required_region_ptr m_rom; - uint32_t screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(screen_vblank_hybrid); - -}; - - -// todo, use actual MD map, easier once maps are part of base class. -void megadriv_sunplus_state::megadriv_sunplus_map(address_map &map) -{ - map(0x000000, 0x3fffff).r(FUNC(megadriv_sunplus_state::read)); /* Cartridge Program Rom */ - map(0xa00000, 0xa01fff).rw(FUNC(megadriv_sunplus_state::megadriv_68k_read_z80_ram), FUNC(megadriv_sunplus_state::megadriv_68k_write_z80_ram)); - map(0xa02000, 0xa03fff).w(FUNC(megadriv_sunplus_state::megadriv_68k_write_z80_ram)); - map(0xa04000, 0xa04003).rw(FUNC(megadriv_sunplus_state::megadriv_68k_YM2612_read), FUNC(megadriv_sunplus_state::megadriv_68k_YM2612_write)); - map(0xa06000, 0xa06001).w(FUNC(megadriv_sunplus_state::megadriv_68k_z80_bank_write)); - map(0xa10000, 0xa1001f).rw(FUNC(megadriv_sunplus_state::megadriv_68k_io_read), FUNC(megadriv_sunplus_state::megadriv_68k_io_write)); - map(0xa11100, 0xa11101).rw(FUNC(megadriv_sunplus_state::megadriv_68k_check_z80_bus), FUNC(megadriv_sunplus_state::megadriv_68k_req_z80_bus)); - map(0xa11200, 0xa11201).w(FUNC(megadriv_sunplus_state::megadriv_68k_req_z80_reset)); - map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); - map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram"); -} - -uint16_t megadriv_sunplus_state::read(offs_t offset) -{ - return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (0x400000 - 1))/2]; -} - - -// controller is wired directly into unit, no controller slots -static INPUT_PORTS_START( megadriv_sunplus ) - PORT_INCLUDE( md_common ) - - PORT_MODIFY("PAD1") - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 ) - //PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_MODIFY("PAD2") - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START2 ) - //PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) -INPUT_PORTS_END - - -void megadriv_sunplus_state::machine_start() -{ - logerror("megadriv_sunplus_state::machine_start\n"); - md_base_state::machine_start(); - - m_vdp->stop_timers(); - save_item(NAME(m_bank)); -} - -void megadriv_sunplus_state::machine_reset() -{ - logerror("megadriv_sunplus_state::machine_reset\n"); - md_base_state::machine_reset(); -} - -uint32_t megadriv_sunplus_state::screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - if (m_md_is_running) - { - /* Copies a bitmap */ - return screen_update_megadriv(screen, bitmap, cliprect); - } - - return 0; -} - -WRITE_LINE_MEMBER(megadriv_sunplus_state::screen_vblank_hybrid) -{ - if (m_md_is_running) - { - /* Used to Sync the timing */ - md_base_state::screen_vblank_megadriv(state); - } -} - - -void megadriv_sunplus_state::megadriv_sunplus_pal(machine_config &config) -{ - md_pal(config); - m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_sunplus_state::megadriv_sunplus_map); - - m_screen->set_screen_update(FUNC(megadriv_sunplus_state::screen_update_hybrid)); - m_screen->screen_vblank().set(FUNC(megadriv_sunplus_state::screen_vblank_hybrid)); -} - - -void megadriv_sunplus_state::init_reactmd() -{ - uint16_t *ROM = (uint16_t*)memregion("sunplus")->base(); - int size = memregion("sunplus")->bytes(); - - for (int i = 0; i < size/2; i++) - { - ROM[i] = bitswap<16>(ROM[i], 15, 13, 14, 12, 7, 6, 5, 4, - 11, 10, 9, 8, 3, 1, 2, 0); - - ROM[i] = ROM[i] ^ 0xa5a5; - } - - init_megadrie(); -} - - -ROM_START( reactmd ) - ROM_REGION( 0x2000000, "maincpu", ROMREGION_ERASE00 ) // this contains the MD games and main boot menu - ROM_LOAD16_WORD_SWAP( "reactormd.bin", 0x0000, 0x2000000, CRC(fe9664a4) SHA1(d475b524f576c9d1d90aed20c7467cc652396baf) ) - - ROM_REGION( 0x4000000, "sunplus", ROMREGION_ERASE00 ) // this contains the SunPlus games - ROM_LOAD16_WORD_SWAP( "reactor_md_sunplus-full.bin", 0x0000, 0x4000000, CRC(843aa58c) SHA1(07cdc6d4aa0057939c145ece01a9aca73c7f1f2b) ) - ROM_IGNORE(0x4000000) // the 2nd half of the ROM can't be accessed by the PCB (address line tied low) (contains garbage? data) -ROM_END - - -// Two systems in one unit - Genesis on a Chip and SunPlus, only the SunPlus part is currently emulated. Genesis on a chip is a very poor implementation with many issues on real hardware. -// This should actually boot to a menu on the MD side, with the SunPlus only being enabled if selected from that menu. MD side menu runs in some enhanced / custom MD mode though. -// Badminton hangs, as it does in the 49-in-1 above -CONS( 2009, reactmd, 0, 0, megadriv_sunplus_pal, megadriv_sunplus, megadriv_sunplus_state, init_reactmd, "AtGames / Sega / Waixing", "Reactor MD (PAL)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) - diff --git a/src/mame/segacons/megadriv_vt_hybrid.cpp b/src/mame/segacons/megadriv_vt_hybrid.cpp deleted file mode 100644 index 0644fb1ab3a..00000000000 --- a/src/mame/segacons/megadriv_vt_hybrid.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood - -/* - This is an enhanced 'Mega Drive / Genesis on a Chip' combined with a VT02/VT03 system for the 'Bonus Games' menu - - The menu for the MD side of things doesn't work as it needs enhanced chipset emulation? - at the moment it just boots the game in the lowest ROM bank (Flicky) - - TODO: - hook up the VT side again - -*/ - -#include "emu.h" -#include "megadriv.h" - -namespace { - -class megadriv_vt0203_state : public md_base_state -{ -public: - megadriv_vt0203_state(const machine_config &mconfig, device_type type, const char *tag) - // Mega Drive part - : md_base_state(mconfig, type, tag), - m_md_is_running(true), - m_bank(0), - m_rom(*this, "maincpu") - {} - - // Mega Drive part - uint16_t read(offs_t offset); - void megadriv_vt0203_pal(machine_config &config); - void megadriv_vt0203_map(address_map &map); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - -private: - bool m_md_is_running; - - // Mega Drive part - int m_bank; - required_region_ptr m_rom; - uint32_t screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(screen_vblank_hybrid); - -}; - - -// todo, use actual MD map, easier once maps are part of base class. -void megadriv_vt0203_state::megadriv_vt0203_map(address_map &map) -{ - map(0x000000, 0x3fffff).r(FUNC(megadriv_vt0203_state::read)); /* Cartridge Program Rom */ - map(0xa00000, 0xa01fff).rw(FUNC(megadriv_vt0203_state::megadriv_68k_read_z80_ram), FUNC(megadriv_vt0203_state::megadriv_68k_write_z80_ram)); - map(0xa02000, 0xa03fff).w(FUNC(megadriv_vt0203_state::megadriv_68k_write_z80_ram)); - map(0xa04000, 0xa04003).rw(FUNC(megadriv_vt0203_state::megadriv_68k_YM2612_read), FUNC(megadriv_vt0203_state::megadriv_68k_YM2612_write)); - map(0xa06000, 0xa06001).w(FUNC(megadriv_vt0203_state::megadriv_68k_z80_bank_write)); - map(0xa10000, 0xa1001f).rw(FUNC(megadriv_vt0203_state::megadriv_68k_io_read), FUNC(megadriv_vt0203_state::megadriv_68k_io_write)); - map(0xa11100, 0xa11101).rw(FUNC(megadriv_vt0203_state::megadriv_68k_check_z80_bus), FUNC(megadriv_vt0203_state::megadriv_68k_req_z80_bus)); - map(0xa11200, 0xa11201).w(FUNC(megadriv_vt0203_state::megadriv_68k_req_z80_reset)); - map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); - map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram"); -} - -uint16_t megadriv_vt0203_state::read(offs_t offset) -{ - return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (0x400000 - 1))/2]; -} - - -// controller is wired directly into unit, no controller slots -static INPUT_PORTS_START( megadriv_vt0203 ) - PORT_INCLUDE( md_common ) - - PORT_MODIFY("PAD1") -#if 0 - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 ) -#else - PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) -#endif - - PORT_MODIFY("PAD2") -#if 0 - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START2 ) -##else - PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED ) -#endif -INPUT_PORTS_END - - -void megadriv_vt0203_state::machine_start() -{ - logerror("megadriv_vt0203_state::machine_start\n"); - md_base_state::machine_start(); - - m_vdp->stop_timers(); - save_item(NAME(m_bank)); -} - -void megadriv_vt0203_state::machine_reset() -{ - logerror("megadriv_vt0203_state::machine_reset\n"); - md_base_state::machine_reset(); -} - -uint32_t megadriv_vt0203_state::screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - if (m_md_is_running) - { - /* Copies a bitmap */ - return screen_update_megadriv(screen, bitmap, cliprect); - } - - return 0; -} - -WRITE_LINE_MEMBER(megadriv_vt0203_state::screen_vblank_hybrid) -{ - if (m_md_is_running) - { - /* Used to Sync the timing */ - md_base_state::screen_vblank_megadriv(state); - } -} - - -void megadriv_vt0203_state::megadriv_vt0203_pal(machine_config &config) -{ - md_pal(config); - m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_vt0203_state::megadriv_vt0203_map); - - m_screen->set_screen_update(FUNC(megadriv_vt0203_state::screen_update_hybrid)); - m_screen->screen_vblank().set(FUNC(megadriv_vt0203_state::screen_vblank_hybrid)); - - // TODO: add the VT part, this might require refactoring of the VT stuff as the SoC currently contains the screen - // but instead we'll need to use a shared screen that is reconfigured depending on which part is enabled -} - -} // anonymous namespace - - -ROM_START( sarc110 ) - ROM_REGION( 0x1000000, "maincpu", 0 ) // Mega Drive part - ROM_LOAD16_WORD_SWAP( "superarcade.bin", 0x000000, 0x1000000, CRC(be732867) SHA1(3857b2fbddd6a548c81caf64122e47a0df079be5) ) - - ROM_REGION( 0x400000, "mainrom", 0 ) // VT02/03 part - ROM_LOAD( "ic1.prg", 0x00000, 0x400000, CRC(de76f71f) SHA1(ff6b37a76c6463af7ae901918fc008b4a2863951) ) -ROM_END - -ROM_START( sarc110a ) - ROM_REGION( 0x1000000, "maincpu", 0 ) // Mega Drive part - ROM_LOAD16_WORD_SWAP( "superarcade.bin", 0x000000, 0x1000000, CRC(be732867) SHA1(3857b2fbddd6a548c81caf64122e47a0df079be5) ) - - ROM_REGION( 0x400000, "mainrom", 0 ) // VT02/03 part - ROM_LOAD( "ic1_ver2.prg", 0x00000, 0x400000, CRC(b97a0dc7) SHA1(bace32d73184df914113de5336e29a7a6f4c03fa) ) -ROM_END - - -CONS( 200?, sarc110, 0, 0, megadriv_vt0203_pal, megadriv_vt0203, megadriv_vt0203_state, init_megadrie, "", "Super Arcade 101-in-1 (set 1)", MACHINE_NOT_WORKING) -CONS( 200?, sarc110a,sarc110, 0, megadriv_vt0203_pal, megadriv_vt0203, megadriv_vt0203_state, init_megadrie, "", "Super Arcade 101-in-1 (set 2)", MACHINE_NOT_WORKING) diff --git a/src/mame/segacons/sega_beena.cpp b/src/mame/segacons/sega_beena.cpp deleted file mode 100644 index 02cef4abd52..00000000000 --- a/src/mame/segacons/sega_beena.cpp +++ /dev/null @@ -1,198 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/****************************************************************************** - - Sega Beena - - apbeena.cpp - - Skeleton driver for the Sega Advanced Pico BEENA - - H/W is custom Sega SoC with ARM7TDMI core at 81 MHz. - - TODO: - Everything! - Needs the internal BIOS dumped. - Component list / PCB diagram - - Cartridge ROM has 'edinburgh' in the header, maybe a system codename? - ROM is also full of OGG files containing the string 'Encoded with Speex speex-1.0.4' - as well as .mid files for music. - - Cartridges pinout: - - Glob down, PCB cut corner at upper right - Top row of pins A25 on left to A1 on right. - Bottom row of pins B25 on left to B1 on right. - - A1 /CE (tied high with resistor) - A2 D11 - A3 D3 - A4 D10 - A5 D2 - A6 D9 - A7 D1 - A8 D8 - A9 D0 - A10 /OE - A11 N/C - A12 A0 - A13 A1 - A14 A2 - A15 A3 - A16 A4 - A17 A5 - A18 A6 - A19 A7 - A20 A17 - A21 A18 - A22 N/C - A23 VCC - A24 N/C - A25 GND - - B1 N/C - B2 D4 - B3 D12 - B4 D5 - B5 D13 - B6 D6 - B7 D14 - B8 D7 - B9 D15 - B10 A16 - B11 A15 - B12 A14 - B13 A13 - B14 A12 - B15 A11 - B16 A10 - B17 A9 - B18 A8 - B19 A19 - B20 A20 - B21 N/C - B22 A21 - B23 VCC - B24 N/C - B25 GND - -*******************************************************************************/ - -#include "emu.h" - -#include "bus/generic/slot.h" -#include "bus/generic/carts.h" -#include "cpu/arm7/arm7.h" - -#include "softlist_dev.h" -#include "speaker.h" -#include "screen.h" - - -class sega_beena_state : public driver_device -{ -public: - sega_beena_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "arm7") - , m_cart(*this, "cartslot") - , m_cart_region(nullptr) - , m_bank(*this, "cartbank") - { } - - void sega_beena(machine_config &config); - -private: - virtual void machine_start() override; - virtual void machine_reset() override; - - uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load); - - void beena_arm7_map(address_map &map); - - required_device m_maincpu; - optional_device m_cart; - memory_region *m_cart_region; - optional_memory_bank m_bank; -}; - -void sega_beena_state::beena_arm7_map(address_map &map) -{ - map(0x00000000, 0x000001ff).rom().bankr("cartbank"); - map(0x80000000, 0x807fffff).rom().bankr("cartbank"); -} - -void sega_beena_state::machine_start() -{ - // if there's a cart, override the standard mapping - if (m_cart && m_cart->exists()) - { - std::string region_tag; - m_cart_region = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); - - m_bank->configure_entries(0, (m_cart_region->bytes() + 0x7fffff) / 0x800000, m_cart_region->base(), 0x800000); - } - else - m_bank->configure_entries(0, 1, memregion("bios")->base(), 0x800000); - - m_bank->set_entry(0); -} - -void sega_beena_state::machine_reset() -{ -} - -DEVICE_IMAGE_LOAD_MEMBER(sega_beena_state::cart_load) -{ - uint32_t size = m_cart->common_get_size("rom"); - - m_cart->rom_alloc(size, GENERIC_ROM16_WIDTH, ENDIANNESS_LITTLE); - m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom"); - - - return image_init_result::PASS; -} - -static INPUT_PORTS_START( sega_beena ) -INPUT_PORTS_END - - -uint32_t sega_beena_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - return 0; -} - -void sega_beena_state::sega_beena(machine_config &config) -{ - ARM7_BE(config, m_maincpu, 81'000'000); - m_maincpu->set_addrmap(AS_PROGRAM, &sega_beena_state::beena_arm7_map); - - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); - screen.set_size(640, 480); - screen.set_visarea(0, 640-1, 0, 480-1); - screen.set_screen_update(FUNC(sega_beena_state::screen_update)); - - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "sega_beena_cart"); - m_cart->set_width(GENERIC_ROM16_WIDTH); - m_cart->set_device_load(FUNC(sega_beena_state::cart_load)); - m_cart->set_must_be_loaded(true); - - SOFTWARE_LIST(config, "cart_list").set_original("sega_beena_cart"); -} - -ROM_START( beena ) - ROM_REGION32_BE( 0x80000, "bios", 0 ) // SoC internal BIOS - ROM_LOAD16_WORD_SWAP( "beenabios.bin", 0x000000, 0x080000, NO_DUMP ) -ROM_END - - -// year, name, parent, compat, machine, input, class, init, company, fullname, flags -CONS( 2009, beena, 0, 0, sega_beena, sega_beena, sega_beena_state, empty_init, "Sega", "Advanced Pico BEENA", MACHINE_IS_SKELETON ) diff --git a/src/mame/segacons/sega_sawatte.cpp b/src/mame/segacons/sega_sawatte.cpp deleted file mode 100644 index 9e6cde13b8c..00000000000 --- a/src/mame/segacons/sega_sawatte.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:AJR - -/* Sega Sawatte / S-Pico - -a sound-only Pico type system (one of the boards even says S-PICO) - -CPU is unknown (MCU with internal ROM?) cartridge dumps contain 6502 code -and have been tested as working using a flash cart. - - -images supplied by Team Europe - -http://mamedev.emulab.it/haze/reference/sawatte/cartridge_pcb_front.jpg -http://mamedev.emulab.it/haze/reference/sawatte/cartridge_pcb_back.jpg - -http://mamedev.emulab.it/haze/reference/sawatte/PCB_Front.jpg -http://mamedev.emulab.it/haze/reference/sawatte/PCB_Back.jpg - -http://mamedev.emulab.it/haze/reference/sawatte/Console_Front.JPG -http://mamedev.emulab.it/haze/reference/sawatte/Console_Back.JPG - -http://mamedev.emulab.it/haze/reference/sawatte/cartridge_example.jpg - -*/ - -#include "emu.h" -#include "bus/generic/carts.h" -#include "bus/generic/slot.h" -#include "cpu/m6502/m6502.h" -#include "softlist_dev.h" - - -class sawatte_state : public driver_device -{ -public: - sawatte_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_cartslot(*this, "cartslot") - , m_soundram(*this, "soundram") - , m_irq3_timer(nullptr) - , m_irq4_timer(nullptr) - , m_data_bank(0) - , m_prog_bank(0) - , m_irq_status(0) - , m_irq_mask(0) - { } - - void sawatte(machine_config &config); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - -private: - TIMER_CALLBACK_MEMBER(irq3_timer); - TIMER_CALLBACK_MEMBER(irq4_timer); - - void bank08_w(u8 data); - void bank09_w(u8 data); - void bank0a_w(u8 data); - u8 irq_status_r(); - void irq_mask_w(u8 data); - void irq3_timer_w(u8 data); - void irq4_timer_w(u8 data); - u8 fixed_r(offs_t offset); - u8 data_bank_r(offs_t offset); - u8 prog_bank_r(offs_t offset); - - void mem_map(address_map &map); - - required_device m_maincpu; - required_device m_cartslot; - required_shared_ptr m_soundram; - - emu_timer *m_irq3_timer; - emu_timer *m_irq4_timer; - - u16 m_data_bank; - u8 m_prog_bank; - u8 m_irq_status; - u8 m_irq_mask; -}; - -void sawatte_state::machine_start() -{ - m_irq3_timer = timer_alloc(FUNC(sawatte_state::irq3_timer), this); - m_irq4_timer = timer_alloc(FUNC(sawatte_state::irq4_timer), this); - - save_item(NAME(m_data_bank)); - save_item(NAME(m_prog_bank)); - save_item(NAME(m_irq_status)); - save_item(NAME(m_irq_mask)); -} - -void sawatte_state::machine_reset() -{ - m_data_bank = 0; - m_prog_bank = 0; - - m_irq_status = 0; - m_irq_mask = 0; - m_maincpu->set_input_line(m6502_device::IRQ_LINE, CLEAR_LINE); - - m_irq3_timer->adjust(attotime::never); - m_irq4_timer->adjust(attotime::never); -} - -TIMER_CALLBACK_MEMBER(sawatte_state::irq3_timer) -{ - if (BIT(m_irq_mask, 3)) - { - m_irq_status |= 0x08; - m_maincpu->set_input_line(m6502_device::IRQ_LINE, ASSERT_LINE); - } -} - -TIMER_CALLBACK_MEMBER(sawatte_state::irq4_timer) -{ - if (BIT(m_irq_mask, 4)) - { - m_irq_status |= 0x10; - m_maincpu->set_input_line(m6502_device::IRQ_LINE, ASSERT_LINE); - } -} - - -void sawatte_state::bank08_w(u8 data) -{ - m_data_bank = (m_data_bank & 0xff00) | data; -} - -void sawatte_state::bank09_w(u8 data) -{ - m_data_bank = u16(data) << 8 | (m_data_bank & 0x00ff); -} - -void sawatte_state::bank0a_w(u8 data) -{ - m_prog_bank = data; -} - -u8 sawatte_state::irq_status_r() -{ - return m_irq_status; -} - -void sawatte_state::irq_mask_w(u8 data) -{ - m_irq_mask = data; - if (m_irq_status != 0) - { - m_irq_status &= data; - if (m_irq_status == 0) - m_maincpu->set_input_line(m6502_device::IRQ_LINE, CLEAR_LINE); - } -} - -void sawatte_state::irq3_timer_w(u8 data) -{ - if (data == 0) - m_irq3_timer->adjust(attotime::never); - else - { - attotime period = attotime::from_hz(10'000); // probably incorrect - m_irq3_timer->adjust(period, 0, period); - } -} - -void sawatte_state::irq4_timer_w(u8 data) -{ - if (!BIT(data, 0)) - m_irq4_timer->adjust(attotime::never); - else - { - attotime period = attotime::from_hz(8'000); // probably incorrect - m_irq4_timer->adjust(period, 0, period); - } -} - -u8 sawatte_state::fixed_r(offs_t offset) -{ - return m_cartslot->read_rom(offset + 0x200); -} - -u8 sawatte_state::data_bank_r(offs_t offset) -{ - return m_cartslot->read_rom(offset | offs_t(m_data_bank) << 11); -} - -u8 sawatte_state::prog_bank_r(offs_t offset) -{ - return m_cartslot->read_rom(offset | offs_t(m_prog_bank) << 12); -} - - -void sawatte_state::mem_map(address_map &map) -{ - map.global_mask(0x1fff); - map(0x0000, 0x0000).nopr(); - map(0x0008, 0x0008).w(FUNC(sawatte_state::bank08_w)); - map(0x0009, 0x0009).w(FUNC(sawatte_state::bank09_w)); - map(0x000a, 0x000a).w(FUNC(sawatte_state::bank0a_w)); - map(0x0011, 0x0011).portr("IN1"); - map(0x0012, 0x0012).portr("IN2"); - map(0x0016, 0x0016).nopr(); - map(0x0017, 0x0017).r(FUNC(sawatte_state::irq_status_r)); - map(0x0020, 0x0020).nopw(); // matrix scanning? - map(0x0022, 0x0022).nopw(); // matrix scanning? - map(0x0026, 0x0026).w(FUNC(sawatte_state::irq3_timer_w)); - map(0x0027, 0x0027).w(FUNC(sawatte_state::irq_mask_w)); - map(0x002f, 0x002f).w(FUNC(sawatte_state::irq4_timer_w)); - map(0x0060, 0x007f).ram(); - map(0x0080, 0x009f).ram().share("soundram"); - map(0x00a0, 0x01ff).ram(); // might not all exist - map(0x0200, 0x07ff).r(FUNC(sawatte_state::fixed_r)); - map(0x0800, 0x0fff).r(FUNC(sawatte_state::data_bank_r)); - map(0x1000, 0x1fff).r(FUNC(sawatte_state::prog_bank_r)); -} - - -static INPUT_PORTS_START( sawatte ) - PORT_START("IN1") - PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) - PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON2) - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON3) - PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_BUTTON4) - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON5) - - PORT_START("IN2") - PORT_BIT(0x1f, IP_ACTIVE_HIGH, IPT_UNKNOWN) // matrix inputs? - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON6) -INPUT_PORTS_END - - -void sawatte_state::sawatte(machine_config &config) -{ - M6502(config, m_maincpu, 4'000'000); // could be some stock SoC, type and clock unknown - m_maincpu->set_addrmap(AS_PROGRAM, &sawatte_state::mem_map); - - GENERIC_CARTSLOT(config, m_cartslot, generic_plain_slot, "sawatte_cart"); - SOFTWARE_LIST(config, "cart_list").set_original("sawatte"); -} - -ROM_START( sawatte ) -ROM_END - - -CONS( 1996?, sawatte, 0, 0, sawatte, sawatte, sawatte_state, empty_init, "Sega", "Sawatte", MACHINE_IS_SKELETON ) diff --git a/src/mame/segacons/segapico.cpp b/src/mame/segacons/segapico.cpp deleted file mode 100644 index 5b13193333a..00000000000 --- a/src/mame/segacons/segapico.cpp +++ /dev/null @@ -1,638 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Emmanuel Vadot - -/****************************************** PICO emulation ****************************************/ - -/* todo, make this more independent of the Genesis emulation, it's really only the same CPU + VDP - and doesn't need to be connected to the Genesis at all. - - sound is the 315-5641 / D77591, should be compatible with the 7759? but probably wants us to maintain - an external buffer of at least 0x40 bytes and feed it on a timer in sync with the timer in the chip? - - currently no way to select (or display) the story book area of the games? (will require layout and - external artwork) - -*/ - - -/* - -Pico mainboard (PAL version) - -+---+ +-------------------------------------------------------------------------+ -| | | +-+ | -| | | +--+ |B| +-+ | -| | | |A3| +-+ | | | -| +------------------------------+ +--+ |C| +-| -| | | | | -| GCMK-C2X +-+ | --> PEN -| +-----+ +--+ +-| -| | | |A3| +--------+ | -| | A1 | +--+ | | +---------+ | -| SEGA | | | A2 | |HM53861J | | -| 1994 837-10846 +-----+ | | | | | -| IAC MAIN PAL +--------+ +---------+ | -| MADE IN JAPAN +----+ | -| VA0 +----------+ |XTAL| +--+ -| | SEGA | +---------+ | | | <-- VCC IN -| | 315-5640 | |MC68HC000| |53.2| +--+ -| | 9434 W51 | |FN8-A | +----+ |00 | +----------+ | -| | | | | | | +----+ | SEGA | | -| | | | 2B89N | | | | 315-5313A| | -| | | |S0AH9425A| | A4 | | F1001 | +--| -| +----------+ +---------+ | | | | | | -| | | |9428 LAGG | | --> VIDEO OUT -| | | | | | | -| +----+ +----------+ +--| -| | -| +----------------------------+ | -| ||||||CARTRIDGE CONNECTOR||||| | -| +----------------------------+ | -| | -+------------------------------------------------------------------------------------------------------------+ - -A1 = SEGA / 315-5641 / D77591 / 9442CA010 -A2 = SEGA / 315-5769 U13 / 9451MD020 -A3 = BA10324AF -A4 = MALAYSIA 9336 / 651632DFP-15 / 0000988S -B = 4K16 / HC00 -C = MB3514 / 9325 M36 - - -315-5640 - touchpad controller? -315-5313A - VDP -315-5641 - PCM chip - - -*/ - -/* - Pico Implementation By ElBarto (Emmanuel Vadot, elbarto@megadrive.org) - Still missing the PCM custom chip - Some game will not boot due to this - - Pico Info from Notaz (http://notaz.gp2x.de/docs/picodoc.txt) - - addr acc description --------+-----+------------ -800001 byte Version register. - ?vv? ????, where v can be: - 00 - hardware is for Japan - 01 - European version - 10 - USA version - 11 - ? -800003 byte Buttons, 0 for pressed, 1 for released: - bit 0: UP (white) - bit 1: DOWN (orange) - bit 2: LEFT (blue) - bit 3: RIGHT (green) - bit 4: red button - bit 5: unused? - bit 6: unused? - bit 7: pen button -800005 byte Most significant byte of pen x coordinate. -800007 byte Least significant byte of pen x coordinate. -800009 byte Most significant byte of pen y coordinate. -80000b byte Least significant byte of pen y coordinate. -80000d byte Page register. One bit means one uncovered page sensor. - 00 - storyware closed - 01, 03, 07, 0f, 1f, 3f - pages 1-6 - either page 5 or page 6 is often unused. -800010 word PCM data register. - r/w read returns free bytes left in PCM FIFO buffer - writes write data to buffer. -800012 word PCM control register. - r/w For writes, it has following possible meanings: - ?p?? ???? ???? ?rrr - p - set to enable playback? - r - sample rate / PCM data type? - 0: 8kHz 4bit ADPCM? - 1-7: 16kHz variants? - For reads, if bit 15 is cleared, it means PCM is 'busy' or - something like that, as games sometimes wait for it to become 1. -800019 byte Games write 'S' -80001b byte Games write 'E' -80001d byte Games write 'G' -80001f byte Games write 'A' - -*/ - -#include "emu.h" -#include "mdconsole.h" -#include "sound/315-5641.h" -#include "bus/megadrive/rom.h" -#include "softlist.h" - - -namespace { - -#define PICO_PENX 1 -#define PICO_PENY 2 - -class pico_base_state : public md_cons_state -{ -public: - pico_base_state(const machine_config &mconfig, device_type type, const char *tag) : - md_cons_state(mconfig, type, tag), - m_sega_315_5641_pcm(*this, "315_5641"), - m_io_page(*this, "PAGE"), - m_io_pad(*this, "PAD"), - m_io_penx(*this, "PENX"), - m_io_peny(*this, "PENY") - { } - - void init_pico(); - void init_picou(); - void init_picoj(); - -protected: - optional_device m_sega_315_5641_pcm; - - required_ioport m_io_page; - required_ioport m_io_pad; - required_ioport m_io_penx; - required_ioport m_io_peny; - - uint8_t m_page_register; - - uint16_t pico_read_penpos(int pen); - uint16_t pico_68k_io_read(offs_t offset); - void pico_68k_io_write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - DECLARE_WRITE_LINE_MEMBER(sound_cause_irq); - - void pico_mem(address_map &map); -}; - -class pico_state : public pico_base_state -{ -public: - pico_state(const machine_config &mconfig, device_type type, const char *tag) : - pico_base_state(mconfig, type, tag), - m_picocart(*this, "picoslot") - { } - - void pico(machine_config &config); - void picopal(machine_config &config); - -private: - required_device m_picocart; - DECLARE_MACHINE_START(pico); -}; - - - -uint16_t pico_base_state::pico_read_penpos(int pen) -{ - uint16_t penpos = 0; - - switch (pen) - { - case PICO_PENX: - penpos = m_io_penx->read(); - penpos |= 0x6; - penpos = penpos * 320 / 255; - penpos += 0x3d; - break; - case PICO_PENY: - penpos = m_io_peny->read(); - penpos |= 0x6; - penpos = penpos * 251 / 255; - penpos += 0x1fc; - break; - } - - return penpos; -} - -uint16_t pico_base_state::pico_68k_io_read(offs_t offset) -{ - uint8_t retdata = 0; - - switch (offset) - { - case 0: /* Version register ?XX?????? where XX is 00 for japan, 01 for europe and 10 for USA*/ - retdata = m_version_hi_nibble; - break; - case 1: - retdata = m_io_pad->read(); - break; - - /* - Still notes from notaz for the pen : - - The pen can be used to 'draw' either on the drawing pad or on the storyware - itself. Both storyware and drawing pad are mapped on single virtual plane, where - coordinates range: - - x: 0x03c - 0x17c - y: 0x1fc - 0x2f7 (drawing pad) - 0x2f8 - 0x3f3 (storyware) - */ - case 2: - retdata = pico_read_penpos(PICO_PENX) >> 8; - break; - case 3: - retdata = pico_read_penpos(PICO_PENX) & 0x00ff; - break; - case 4: - retdata = pico_read_penpos(PICO_PENY) >> 8; - break; - case 5: - retdata = pico_read_penpos(PICO_PENY) & 0x00ff; - break; - case 6: - /* Page register : - 00 - storyware closed - 01, 03, 07, 0f, 1f, 3f - pages 1-6 - either page 5 or page 6 is often unused. - */ - { - uint8_t tmp = m_io_page->read(); - if (tmp == 2 && m_page_register != 0x3f) - { - m_page_register <<= 1; - m_page_register |= 1; - } - if (tmp == 1 && m_page_register != 0x00) - m_page_register >>= 1; - retdata = m_page_register; - break; - } - - - - case 8: // toy story 2 checks this for 0x3f (is that 'empty'?) - /* Returns free bytes left in the PCM FIFO buffer */ - retdata = m_sega_315_5641_pcm->get_fifo_space(); - break; - case 9: - /* - For reads, if bit 15 is cleared, it means PCM is 'busy' or - something like that, as games sometimes wait for it to become 1. - */ - // return (m_upd7759->busy_r()^1) << 15; - // The BUSY bit stays 1 as long as some PCM sound is playing. - // SMPS drivers check 800012 [byte] and clear the "prevent music PCM" byte when the READY bit gets set. - // If this is done incorrectly, the voices in Sonic Gameworld (J) are muted by the music's PCM drums. - return m_sega_315_5641_pcm->busy_r() << 15; - - - case 7: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - logerror("pico_68k_io_read %d\n", offset); - - } - - return retdata | retdata << 8; -} - - -WRITE_LINE_MEMBER(pico_base_state::sound_cause_irq) -{ -// printf("sound irq\n"); - /* sega_315_5641_pcm callback */ - m_maincpu->set_input_line(3, HOLD_LINE); -} - -void pico_base_state::pico_68k_io_write(offs_t offset, uint16_t data, uint16_t mem_mask) -{ -// printf("pico_68k_io_write %04x %04x %04x\n", offset*2, data, mem_mask); - - switch (offset) - { - case 0x10/2: - if (mem_mask & 0xFF00) - m_sega_315_5641_pcm->port_w((data >> 8) & 0xFF); - if (mem_mask & 0x00FF) - m_sega_315_5641_pcm->port_w((data >> 0) & 0xFF); - break; - case 0x12/2: // guess - // Note about uPD7759 lines: - // reset line: 1 - normal, 1->0 - reset chip, 0 - playback disabled - // start line: 0->1 - start playback - if (mem_mask & 0xFF00) - { - // I assume that: - // value 8000 resets the FIFO? (always used with low reset line) - // value 0800 maps to the uPD7759's reset line (0 = reset, 1 = normal) - // value 4000 maps to the uPD7759's start line (0->1 = start) - m_sega_315_5641_pcm->fifo_reset_w(BIT(data, 15)); - m_sega_315_5641_pcm->reset_w(BIT(data, 11)); - m_sega_315_5641_pcm->start_w(BIT(data, 14)); - } - - - /*m_sega_315_5641_pcm->reset_w(0); - m_sega_315_5641_pcm->start_w(0); - m_sega_315_5641_pcm->reset_w(1); - m_sega_315_5641_pcm->start_w(1); - - if (ACCESSING_BITS_0_7) m_sega_315_5641_pcm->port_w(space,0,data&0xff); - if (ACCESSING_BITS_8_15) m_sega_315_5641_pcm->port_w(space,0,(data>>8)&0xff);*/ - - break; - } -} - -void pico_base_state::pico_mem(address_map &map) -{ - map(0x000000, 0x3fffff).rom(); - map(0x800000, 0x80001f).rw(FUNC(pico_base_state::pico_68k_io_read), FUNC(pico_base_state::pico_68k_io_write)); - map(0xc00000, 0xc0001f).rw("gen_vdp", FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); - map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000); -} - - -static INPUT_PORTS_START( pico ) - PORT_START("PAD") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("Red Button") - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("Pen Button") - - PORT_START("PAGE") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("Increment Page") - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("Decrement Page") - - PORT_START("PENX") - PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_NAME("PEN X") - - PORT_START("PENY") - PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0,255 ) PORT_PLAYER(1) PORT_NAME("PEN Y") -INPUT_PORTS_END - - -static void pico_cart(device_slot_interface &device) -{ - device.option_add_internal("rom", MD_STD_ROM); - device.option_add_internal("rom_sram", MD_ROM_SRAM); // not sure these are needed... - device.option_add_internal("rom_sramsafe", MD_ROM_SRAM); // not sure these are needed... -} - -MACHINE_START_MEMBER(pico_state,pico) -{ - m_maincpu->space(AS_PROGRAM).install_read_handler(0x000000, 0x7fffff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0x000000, 0x7fffff, write16s_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write))); - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa13000, 0xa130ff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read_a13)), write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_a13))); - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa15000, 0xa150ff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read_a15)), write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_a15))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14000, 0xa14003, write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_tmss_bank))); - - m_vdp->stop_timers(); -} - -void pico_state::pico(machine_config &config) -{ - md_ntsc(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &pico_state::pico_mem); - - config.device_remove("genesis_snd_z80"); - config.device_remove("ymsnd"); - - MCFG_MACHINE_START_OVERRIDE( pico_state, pico ) - - PICO_CART_SLOT(config, m_picocart, pico_cart, nullptr).set_must_be_loaded(true); - SOFTWARE_LIST(config, "cart_list").set_original("pico"); - - SEGA_315_5641_PCM(config, m_sega_315_5641_pcm, upd7759_device::STANDARD_CLOCK*2); - m_sega_315_5641_pcm->fifo_cb().set(FUNC(pico_state::sound_cause_irq)); - m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "lspeaker", 0.16); - m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "rspeaker", 0.16); -} - -void pico_state::picopal(machine_config &config) -{ - md_pal(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &pico_state::pico_mem); - - config.device_remove("genesis_snd_z80"); - config.device_remove("ymsnd"); - - MCFG_MACHINE_START_OVERRIDE( pico_state, pico ) - - PICO_CART_SLOT(config, m_picocart, pico_cart, nullptr).set_must_be_loaded(true); - SOFTWARE_LIST(config, "cart_list").set_original("pico"); - - SEGA_315_5641_PCM(config, m_sega_315_5641_pcm, upd7759_device::STANDARD_CLOCK*2); - m_sega_315_5641_pcm->fifo_cb().set(FUNC(pico_state::sound_cause_irq)); - m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "lspeaker", 0.16); - m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "rspeaker", 0.16); -} - - - -ROM_START( pico ) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - -ROM_START( picou ) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - -ROM_START( picoj ) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - - -void pico_base_state::init_pico() -{ - init_megadrie(); - init_mess_md_common(); - - m_version_hi_nibble = 0x60; // Export PAL -} - -void pico_base_state::init_picou() -{ - init_megadriv(); - init_mess_md_common(); - - m_version_hi_nibble = 0x40; // Export NTSC -} - -void pico_base_state::init_picoj() -{ - init_megadrij(); - init_mess_md_common(); - - m_version_hi_nibble = 0x00; // JPN NTSC -} - - -/* - -This looks a lot like a Pico with extra sound hardware... - YMZ263B is the basis of a Sound Blaster Clone - YMF262-M is the OPL3 - -YAMAHA - MIXT BOOK PLAYER COPERA -MMG-1 - - - +-------------+ - | | - |------+ | - | | | - MIDI OUT <-- | | - | | | - |------+ | - | | +------------------------------------------------------------------------------------------------------+ - |------+ | | +--+ | - | | | | |YM| | - MIDI IN <-- | | | |7 | | - | | | | |12| +---------+ | - |------+ +--+ | +------+ |8B| | YAMAHA | | - | |||| | | +--+ | YMZ263B | | - +---------||--+ | +--------+ | | | - || | |YM7 128B| +---------+ +---+ | - || | +--------+ |YMF| | - +---------||----------+ |262| | - | || |-M | | - | || +---+ | - | || | - | || SEGA | - |------+ || 1993 837-9845 COPERA | - | | || MADE IN JAPAN +--| - | | || VA0 | --> PEN - CONTROL <-- | || | | - | | || +--| - | | || | - | | || | - |------+ || +----+ | - | || |XTAL| +------------+ | - | || | | | OKI JAPAN | +----+ - | || +----------+ |53.6| | M54C864-80 | | | - | |||| | SEGA | |93 | +------------+ | | - | +--+ | 315-5639 | | Mhz| | | - | | U11| +----+ +-------------+ | E | - | |9341PD025 | | | | X | - |--+ +----------+ | SEGA | | T | - MIC <-- | +----+ +----+ | 315-5313A | | E | - | | |TC51| |TC51| | FC1001 | | N | - |--+ |832A| |832A| | 9331 AASG | | D | - | |FL-1| |FL-1| | | | E | - | |0 | |0 | | | | D | - | | | | | | | | | - |--+ +----+ +----+ +-------------+ | | - +-- | | C | - | |--+ | O | -S-AUDIO <-| | +-----------+ +-------+ | N | - | |--+ | SEGA | | SEGA | +-----------+ | N | - +-- | | 315-5640 | |315-564| | 3D4 UA | | E | - |--+ | 9333 W26 | |1 | |HD68HC000CP| | C | - | | | |D77591 | |8 | | T | - |--+ | | +-------+ | | | O | - S-VIDEO <-- | | | | | | R | - |--+ | | | | | | - | +-----------+ | JAPAN| | | - | +-----------+ | | - |--+ | | - VCC --> | +----------------------------------------------+ | | - |--+ | CARTRIDGE | +----+ - | | CONNECTOR | | - | +----------------------------------------------+ | - +-----------------------------------------------------------------------------------------------------------------------------------+ - -*/ - - - -class copera_state : public pico_base_state -{ -public: - copera_state(const machine_config &mconfig, device_type type, const char *tag) : - pico_base_state(mconfig, type, tag), - m_picocart(*this, "coperaslot") - { } - - void copera(machine_config &config); - void copera_mem(address_map &map); - -private: - required_device m_picocart; - DECLARE_MACHINE_START(copera); -}; - - - -void copera_state::copera_mem(address_map &map) -{ - map(0x000000, 0x3fffff).rom(); - - map(0x800000, 0x80001f).rw(FUNC(copera_state::pico_68k_io_read), FUNC(copera_state::pico_68k_io_write)); - - map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); - - map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000); -} - - - -static void copera_cart(device_slot_interface &device) -{ - device.option_add_internal("rom", MD_STD_ROM); - device.option_add_internal("rom_sram", MD_ROM_SRAM); // not sure these are needed... - device.option_add_internal("rom_sramsafe", MD_ROM_SRAM); // not sure these are needed... -} - -MACHINE_START_MEMBER(copera_state,copera) -{ - m_maincpu->space(AS_PROGRAM).install_read_handler(0x000000, 0x7fffff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0x000000, 0x7fffff, write16s_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write))); - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa13000, 0xa130ff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read_a13)), write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_a13))); - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa15000, 0xa150ff, read16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::read_a15)), write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_a15))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xa14000, 0xa14003, write16sm_delegate(*m_picocart, FUNC(base_md_cart_slot_device::write_tmss_bank))); - - m_sega_315_5641_pcm->reset_w(0); - m_sega_315_5641_pcm->start_w(0); - m_sega_315_5641_pcm->reset_w(1); - m_sega_315_5641_pcm->start_w(1); - -} - -void copera_state::copera(machine_config &config) -{ - md_ntsc(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &copera_state::copera_mem); - - config.device_remove("genesis_snd_z80"); - config.device_remove("ymsnd"); - - MCFG_MACHINE_START_OVERRIDE( copera_state, copera ) - - COPERA_CART_SLOT(config, m_picocart, copera_cart, nullptr).set_must_be_loaded(true); - SOFTWARE_LIST(config, "cart_list").set_original("copera"); - - SEGA_315_5641_PCM(config, m_sega_315_5641_pcm, upd7759_device::STANDARD_CLOCK); - m_sega_315_5641_pcm->fifo_cb().set(FUNC(copera_state::sound_cause_irq)); - m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "lspeaker", 0.16); - m_sega_315_5641_pcm->add_route(ALL_OUTPUTS, "rspeaker", 0.16); -} - - - -ROM_START( copera ) - ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) - ROM_REGION( 0x10000, "soundcpu", ROMREGION_ERASEFF) -ROM_END - -} // anonymous namespace - - -CONS( 1994, pico, 0, 0, picopal, pico, pico_state, init_pico, "Sega", "Pico (Europe, PAL)", MACHINE_NOT_WORKING) -CONS( 1994, picou, pico, 0, pico, pico, pico_state, init_picou, "Sega", "Pico (USA, NTSC)", MACHINE_NOT_WORKING) -CONS( 1993, picoj, pico, 0, pico, pico, pico_state, init_picoj, "Sega", "Pico (Japan, NTSC)", MACHINE_NOT_WORKING) - -CONS( 1993, copera, 0, 0, copera, pico, copera_state, init_picoj, "Yamaha / Sega", "Yamaha Mixt Book Player Copera", MACHINE_NOT_WORKING) diff --git a/src/mame/segacons/segapm.cpp b/src/mame/segacons/segapm.cpp deleted file mode 100644 index 494aedcd64e..00000000000 --- a/src/mame/segacons/segapm.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/* Sega Picture Magic (codename JANUS) */ -// http://segaretro.org/Sega_Picture_Magic - -// this uses a Sega 32X PCB (not in a 32X case) attached to a stripped down 68k based board rather than a full Genesis / Megadrive -// it is likely the internal SH2 bios roms differ - - -#include "emu.h" -#include "cpu/m68000/m68000.h" -#include "emupal.h" -#include "screen.h" - - -class segapm_state : public driver_device -{ -public: - segapm_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu") - { } - - void segapm(machine_config &config); - -private: - virtual void video_start() override; - uint32_t screen_update_segapm(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - required_device m_maincpu; - void segapm_map(address_map &map); -}; - - -void segapm_state::video_start() -{ -} - -uint32_t segapm_state::screen_update_segapm(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - return 0; -} - - - -void segapm_state::segapm_map(address_map &map) -{ - map(0x000000, 0x07ffff).rom(); - - // A15100 - - map(0xe00000, 0xe7ffff).ram(); - -} - -static INPUT_PORTS_START( segapm ) -INPUT_PORTS_END - - - - -void segapm_state::segapm(machine_config &config) -{ - M68000(config, m_maincpu, 8000000); // ?? - m_maincpu->set_addrmap(AS_PROGRAM, &segapm_state::segapm_map); - - // + 2 sh2s on 32x board - - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); - screen.set_size(32*8, 32*8); - screen.set_visarea(0*8, 32*8-1, 2*8, 30*8-1); - screen.set_screen_update(FUNC(segapm_state::screen_update_segapm)); - screen.set_palette("palette"); - - PALETTE(config, "palette").set_format(palette_device::xRGB_555, 0x200); -} - - - -ROM_START( segapm ) // was more than one cartridge available? if so softlist them? - ROM_REGION( 0x80000, "maincpu", 0 ) /* 68000 Code */ - ROM_LOAD( "picture magic boot cart.bin", 0x00000, 0x80000, CRC(c9ab4e60) SHA1(9c4d4ab3e59c8acde86049a1ba3787aa03b549a3) ) // internal header is GOUSEI HENSYUU - - // todo, sh2 bios roms etc. -ROM_END - -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -CONS( 1996, segapm, 0, 0, segapm, segapm, segapm_state, empty_init, "Sega", "Picture Magic", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) diff --git a/src/mame/segacons/sg1000.cpp b/src/mame/segacons/sg1000.cpp deleted file mode 100644 index a3004543a98..00000000000 --- a/src/mame/segacons/sg1000.cpp +++ /dev/null @@ -1,706 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Curt Coder -/* - -Sega SG-1000 - -PCB Layout ----------- - -171-5078 (C) SEGA 1983 -171-5046 REV. A (C) SEGA 1983 - -|---------------------------| |----------------------------| -| SW1 CN2 | |------|---------------| | SW2 CN4 | -| |---| CN3 |---| | -| CN1 CN5 | -| | -| 10.738635MHz |------------------------------| 7805 | -| |---| |------------------------------| | -| | | CN6 | -| | 9 | | -| | 9 | LS32 | -| | 1 | |---------| | -| | 8 | | TMM2009 | LS139 | -| | A | |---------| |------------------| | -| | | | Z80 | | -| |---| |------------------| | -| | -| | -| MB8118 MB8118 MB8118 MB8118 SN76489A SW3 | -| MB8118 MB8118 MB8118 MB8118 LS257 LS257 | -|---------------------------------------------------------------------------------------| - -Notes: - All IC's shown. - - Z80 - NEC D780C-1 / Zilog Z8400A (REV.A) Z80A CPU @ 3.579545 - TMS9918A- Texas Instruments TMS9918ANL Video Display Processor @ 10.738635MHz - MB8118 - Fujitsu MB8118-12 16K x 1 Dynamic RAM - TMM2009 - Toshiba TMM2009P-A / TMM2009P-B (REV.A) - SN76489A- Texas Instruments SN76489AN Digital Complex Sound Generator @ 3.579545 - CN1 - player 1 joystick connector - CN2 - RF video connector - CN3 - keyboard connector - CN4 - power connector (+9VDC) - CN5 - player 2 joystick connector - CN6 - cartridge connector - SW1 - TV channel select switch - SW2 - power switch - SW3 - hold switch - -*/ - -/* - - TODO: - - - SC-3000 return instruction referenced by R when reading ports 60-7f,e0-ff - - connect PSG /READY signal to Z80 WAIT - - accurate video timing - - SH-400 racing controller - - SF-7000 serial comms - -*/ - - -#include "emu.h" -#include "sg1000.h" -#include "bus/rs232/rs232.h" -#include "softlist_dev.h" -#include "speaker.h" - - -/*************************************************************************** - READ/WRITE HANDLERS -***************************************************************************/ - -// TODO: not sure if the OMV bios actually detects the presence of a cart, -// or if the cart data simply overwrites the internal bios... -// for the moment let assume the latter! -uint8_t sg1000_state::omv_r(offs_t offset) -{ - if (m_cart && m_cart->exists()) - return m_cart->read_cart(offset); - else - return m_rom->base()[offset]; -} - -void sg1000_state::omv_w(offs_t offset, uint8_t data) -{ - if (m_cart && m_cart->exists()) - m_cart->write_cart(offset, data); -} - -uint8_t sg1000_state::peripheral_r(offs_t offset) -{ - bool joy_ports_disabled = m_sgexpslot->is_readable(offset); - - if (joy_ports_disabled) - { - return m_sgexpslot->read(offset); - } - else - { - if (offset & 0x01) - return m_pb7->read(); - else - return m_pa7->read(); - } -} - -void sg1000_state::peripheral_w(offs_t offset, uint8_t data) -{ - bool joy_ports_disabled = m_sgexpslot->is_writeable(offset); - - if (joy_ports_disabled) - { - m_sgexpslot->write(offset, data); - } -} - -/*------------------------------------------------- - ADDRESS_MAP( sg1000_map ) --------------------------------------------------*/ - -void sg1000_state::sg1000_map(address_map &map) -{ - map(0x0000, 0xbfff).rw(m_cart, FUNC(sega8_cart_slot_device::read_cart), FUNC(sega8_cart_slot_device::write_cart)); - map(0xc000, 0xc3ff).mirror(0x3c00).ram(); -} - -/*------------------------------------------------- - ADDRESS_MAP( sg1000_io_map ) --------------------------------------------------*/ - -void sg1000_state::sg1000_io_map(address_map &map) -{ - map.global_mask(0xff); - map(0x40, 0x40).mirror(0x3f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); - map(0x80, 0x81).mirror(0x3e).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); - map(0xdc, 0xdf).rw(FUNC(sg1000_state::peripheral_r), FUNC(sg1000_state::peripheral_w)); -} - -/*------------------------------------------------- - ADDRESS_MAP( omv_map ) --------------------------------------------------*/ - -void sg1000_state::omv_map(address_map &map) -{ - map(0x0000, 0xbfff).rw(FUNC(sg1000_state::omv_r), FUNC(sg1000_state::omv_w)); - map(0xc000, 0xc7ff).mirror(0x3800).ram(); -} - -/*------------------------------------------------- - ADDRESS_MAP( omv_io_map ) --------------------------------------------------*/ - -void sg1000_state::omv_io_map(address_map &map) -{ - map.global_mask(0xff); - map(0x40, 0x40).mirror(0x3f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); - map(0x80, 0x81).mirror(0x3e).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); - map(0xc0, 0xc0).mirror(0x38).portr("C0"); - map(0xc1, 0xc1).mirror(0x38).portr("C1"); - map(0xc2, 0xc2).mirror(0x38).portr("C2"); - map(0xc3, 0xc3).mirror(0x38).portr("C3"); - map(0xc4, 0xc4).mirror(0x3a).portr("C4"); - map(0xc5, 0xc5).mirror(0x3a).portr("C5"); -} - -/*------------------------------------------------- - ADDRESS_MAP( sc3000_map ) --------------------------------------------------*/ - -void sg1000_state::sc3000_map(address_map &map) -{ - map(0x0000, 0xbfff).rw(CARTSLOT_TAG, FUNC(sega8_cart_slot_device::read_cart), FUNC(sega8_cart_slot_device::write_cart)); - map(0xc000, 0xc7ff).mirror(0x3800).ram(); -} - -/*------------------------------------------------- - ADDRESS_MAP( sc3000_io_map ) --------------------------------------------------*/ - -void sg1000_state::sc3000_io_map(address_map &map) -{ - map.global_mask(0xff); - map(0x00, 0xff).rw(CARTSLOT_TAG, FUNC(sega8_cart_slot_device::read_io), FUNC(sega8_cart_slot_device::write_io)); - map(0x7f, 0x7f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); - map(0xbe, 0xbf).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); - map(0xdc, 0xdf).rw(FUNC(sg1000_state::peripheral_r), FUNC(sg1000_state::peripheral_w)); -} - -/* This is how the I/O ports are really mapped, but MAME does not support overlapping ranges -void sg1000_state::sc3000_io_map(address_map &map) -{ - map.global_mask(0xff); - map(0x00, 0x00).mirror(0xdf).rw(UPD9255_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write)); - map(0x00, 0x00).mirror(0x7f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); - map(0x00, 0x01).mirror(0xae).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); - map(0x60, 0x60).mirror(0x9f).r(FUNC(sg1000_state::sc3000_r_r)); -} -*/ - -/*------------------------------------------------- - ADDRESS_MAP( sf7000_map ) --------------------------------------------------*/ - -void sf7000_state::sf7000_map(address_map &map) -{ - map(0x0000, 0x3fff).bankr("bank1").bankw("bank2"); - map(0x4000, 0xffff).ram(); -} - -/*------------------------------------------------- - ADDRESS_MAP( sf7000_io_map ) --------------------------------------------------*/ - -void sf7000_state::sf7000_io_map(address_map &map) -{ - map.global_mask(0xff); - map(0x7f, 0x7f).w(SN76489AN_TAG, FUNC(sn76489a_device::write)); - map(0xbe, 0xbf).rw(TMS9918A_TAG, FUNC(tms9918a_device::read), FUNC(tms9918a_device::write)); - map(0xdc, 0xdf).rw(FUNC(sf7000_state::peripheral_r), FUNC(sf7000_state::peripheral_w)); - map(0xe0, 0xe1).m(m_fdc, FUNC(upd765a_device::map)); - map(0xe4, 0xe7).rw(UPD9255_1_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write)); - map(0xe8, 0xe9).rw(UPD8251_TAG, FUNC(i8251_device::read), FUNC(i8251_device::write)); -} - -/*************************************************************************** - INPUT PORTS -***************************************************************************/ - -/*------------------------------------------------- - INPUT_CHANGED_MEMBER( trigger_nmi ) --------------------------------------------------*/ - -INPUT_CHANGED_MEMBER( sg1000_state::trigger_nmi ) -{ - m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE); -} - -/*------------------------------------------------- - INPUT_PORTS( sg1000 ) --------------------------------------------------*/ - -static INPUT_PORTS_START( sg1000_joy ) - PORT_START("PA7") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) - - PORT_START("PB7") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) - PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) -INPUT_PORTS_END - -static INPUT_PORTS_START( sg1000 ) - PORT_INCLUDE( sg1000_joy ) - - PORT_START("NMI") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("PAUSE") PORT_CODE(KEYCODE_P) PORT_CHANGED_MEMBER(DEVICE_SELF, sg1000_state, trigger_nmi, 0) -INPUT_PORTS_END - -/*------------------------------------------------- - INPUT_PORTS( omv ) --------------------------------------------------*/ - -static INPUT_PORTS_START( omv1000 ) - PORT_START("C0") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') - PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("C1") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("9 #") PORT_CODE(KEYCODE_9) PORT_CHAR('9') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("0 *") PORT_CODE(KEYCODE_0) PORT_CHAR('0') - PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("C2") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E') - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F') - PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("C3") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G') - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H') - PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED ) - - PORT_START("C4") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("S-1") - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("S-2") - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) - - // The OMV FG-1000 has no 2nd joystick - // http://www.famitsu.com/image/29819/pEllnbNQfCJ58skZ25uB511N6eSFfAu6.jpg - PORT_START("C5") - PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) -INPUT_PORTS_END - -static INPUT_PORTS_START( omv2000 ) - PORT_INCLUDE( omv1000 ) - - PORT_MODIFY("C5") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) - PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) -INPUT_PORTS_END - -/*------------------------------------------------- - INPUT_PORTS( sc3000 ) --------------------------------------------------*/ - -static INPUT_PORTS_START( sc3000 ) - PORT_INCLUDE( sg1000_joy ) - - // keyboard keys are added by the embedded sk1100 device - - PORT_START("NMI") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F10) PORT_CHANGED_MEMBER(DEVICE_SELF, sg1000_state, trigger_nmi, 0) -INPUT_PORTS_END - -/*------------------------------------------------- - INPUT_PORTS( sf7000 ) --------------------------------------------------*/ - -static INPUT_PORTS_START( sf7000 ) - PORT_INCLUDE( sc3000 ) - - PORT_START("BAUD") - PORT_CONFNAME( 0x07, 0x05, "Baud rate") - PORT_CONFSETTING( 0x00, "9600 baud" ) - PORT_CONFSETTING( 0x01, "4800 baud" ) - PORT_CONFSETTING( 0x02, "2400 baud" ) - PORT_CONFSETTING( 0x03, "1200 baud" ) - PORT_CONFSETTING( 0x04, "600 baud" ) - PORT_CONFSETTING( 0x05, "300 baud" ) -INPUT_PORTS_END - -/*************************************************************************** - DEVICE CONFIGURATION -***************************************************************************/ - -/*------------------------------------------------- - I8255 INTERFACE --------------------------------------------------*/ - -WRITE_LINE_MEMBER( sf7000_state::write_centronics_busy ) -{ - m_centronics_busy = state; -} - -uint8_t sf7000_state::ppi_pa_r() -{ - /* - Signal Description - - PA0 INT from FDC - PA1 BUSY from Centronics printer - PA2 INDEX from FDD - PA3 - PA4 - PA5 - PA6 - PA7 - */ - - uint8_t data = 0; - - data |= m_fdc->get_irq() ? 0x01 : 0x00; - data |= m_centronics_busy << 1; - data |= m_floppy0->idx_r() << 2; - - return data; -} - -void sf7000_state::ppi_pc_w(uint8_t data) -{ - /* - Signal Description - - PC0 /INUSE signal to FDD - PC1 /MOTOR ON signal to FDD - PC2 TC signal to FDC - PC3 RESET signal to FDC - PC4 not connected - PC5 not connected - PC6 /ROM SEL (switch between IPL ROM and RAM) - PC7 /STROBE to Centronics printer - */ - - if (!BIT(data, 0)) - m_fdc->set_floppy(m_floppy0); - else - m_fdc->set_floppy(nullptr); - - /* floppy motor */ - m_floppy0->mon_w(BIT(data, 1)); - - /* FDC terminal count */ - m_fdc->tc_w(BIT(data, 2)); - - /* FDC reset */ - if (BIT(data, 3)) - { - m_fdc->reset(); - } - - /* ROM selection */ - membank("bank1")->set_entry(BIT(data, 6)); - - /* printer strobe */ - m_centronics->write_strobe(BIT(data, 7)); -} - -/*------------------------------------------------- - upd765_interface sf7000_upd765_interface --------------------------------------------------*/ - -void sf7000_state::floppy_formats(format_registration &fr) -{ - fr.add_mfm_containers(); - fr.add(FLOPPY_SF7000_FORMAT); -} - -/*------------------------------------------------- - floppy_interface sf7000_floppy_interface --------------------------------------------------*/ - -static void sf7000_floppies(device_slot_interface &device) -{ - device.option_add("3ssdd", FLOPPY_3_SSDD); -} - -/*------------------------------------------------- - MACHINE_START( sg1000 ) --------------------------------------------------*/ - -void sg1000_state::machine_start() -{ - if (m_cart->get_type() == SEGA8_DAHJEE_TYPEA || m_cart->get_type() == SEGA8_DAHJEE_TYPEB) - { - m_maincpu->space(AS_PROGRAM).install_read_handler(0xc000, 0xffff, read8sm_delegate(*m_cart, FUNC(sega8_cart_slot_device::read_ram))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xc000, 0xffff, write8sm_delegate(*m_cart, FUNC(sega8_cart_slot_device::write_ram))); - } - - if (m_cart) - m_cart->save_ram(); -} - -/*------------------------------------------------- - MACHINE_START( sc3000 ) --------------------------------------------------*/ - -void sc3000_state::machine_start() -{ - if (m_cart && m_cart->exists() && (m_cart->get_type() == SEGA8_BASIC_L3 || m_cart->get_type() == SEGA8_MUSIC_EDITOR - || m_cart->get_type() == SEGA8_DAHJEE_TYPEA || m_cart->get_type() == SEGA8_DAHJEE_TYPEB - || m_cart->get_type() == SEGA8_MULTICART || m_cart->get_type() == SEGA8_MEGACART)) - { - m_maincpu->space(AS_PROGRAM).install_read_handler(0xc000, 0xffff, read8sm_delegate(*m_cart, FUNC(sega8_cart_slot_device::read_ram))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xc000, 0xffff, write8sm_delegate(*m_cart, FUNC(sega8_cart_slot_device::write_ram))); - } - - if (m_cart) - m_cart->save_ram(); -} - - -/*------------------------------------------------- - MACHINE_START( sf7000 ) --------------------------------------------------*/ - -void sf7000_state::machine_start() -{ - sc3000_state::machine_start(); - - save_item(NAME(m_centronics_busy)); - - /* configure memory banking */ - membank("bank1")->configure_entry(0, m_rom->base()); - membank("bank1")->configure_entry(1, m_ram->pointer()); - membank("bank2")->configure_entry(0, m_ram->pointer()); -} - -void sf7000_state::machine_reset() -{ - membank("bank1")->set_entry(0); - membank("bank2")->set_entry(0); -} - -/*************************************************************************** - MACHINE DRIVERS -***************************************************************************/ - -/*------------------------------------------------- - machine_config( sg1000 ) --------------------------------------------------*/ - -void sg1000_state::sg1000(machine_config &config) -{ - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(10'738'635)/3); - m_maincpu->set_addrmap(AS_PROGRAM, &sg1000_state::sg1000_map); - m_maincpu->set_addrmap(AS_IO, &sg1000_state::sg1000_io_map); - - /* video hardware */ - tms9918a_device &vdp(TMS9918A(config, TMS9918A_TAG, XTAL(10'738'635))); - vdp.set_screen("screen"); - vdp.set_vram_size(0x4000); - vdp.int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - SCREEN(config, "screen", SCREEN_TYPE_RASTER); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - - SN76489A(config, SN76489AN_TAG, XTAL(10'738'635)/3).add_route(ALL_OUTPUTS, "mono", 1.00); - - /* expansion slot */ - SG1000_EXPANSION_SLOT(config, m_sgexpslot, sg1000_expansion_devices, nullptr, false); - - /* cartridge */ - SG1000_CART_SLOT(config, CARTSLOT_TAG, sg1000_cart, nullptr).set_must_be_loaded(true); - - /* software lists */ - SOFTWARE_LIST(config, "cart_list").set_original("sg1000"); - - /* internal ram */ - RAM(config, m_ram).set_default_size("1K"); -} - -/*------------------------------------------------- - machine_config( omv ) --------------------------------------------------*/ - -void sg1000_state::omv(machine_config &config) -{ - sg1000(config); - - m_maincpu->set_addrmap(AS_PROGRAM, &sg1000_state::omv_map); - m_maincpu->set_addrmap(AS_IO, &sg1000_state::omv_io_map); - - OMV_CART_SLOT(config.replace(), CARTSLOT_TAG, sg1000_cart, nullptr); - - m_ram->set_default_size("2K"); -} - -/*------------------------------------------------- - machine_config( sc3000 ) --------------------------------------------------*/ - -void sc3000_state::sc3000(machine_config &config) -{ - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(10'738'635)/3); // LH0080A - m_maincpu->set_addrmap(AS_PROGRAM, &sc3000_state::sc3000_map); - m_maincpu->set_addrmap(AS_IO, &sc3000_state::sc3000_io_map); - - /* video hardware */ - tms9918a_device &vdp(TMS9918A(config, TMS9918A_TAG, XTAL(10'738'635))); - vdp.set_screen("screen"); - vdp.set_vram_size(0x4000); - vdp.int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - SCREEN(config, "screen", SCREEN_TYPE_RASTER); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - - SN76489A(config, SN76489AN_TAG, XTAL(10'738'635)/3).add_route(ALL_OUTPUTS, "mono", 1.00); - - /* sc3000 has all sk1100 features built-in, so add it as a fixed slot */ - SG1000_EXPANSION_SLOT(config, m_sgexpslot, sg1000_expansion_devices, "sk1100", true); - - /* cartridge */ - SC3000_CART_SLOT(config, CARTSLOT_TAG, sg1000_cart, nullptr).set_must_be_loaded(true); - - /* software lists */ - SOFTWARE_LIST(config, "cart_list").set_original("sg1000"); - /* the sk1100 device will add sc3000 cart and cass lists */ - - /* internal ram */ - RAM(config, m_ram).set_default_size("2K"); -} - -/*------------------------------------------------- - machine_config( sf7000 ) --------------------------------------------------*/ - -void sf7000_state::sf7000(machine_config &config) -{ - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(10'738'635)/3); - m_maincpu->set_addrmap(AS_PROGRAM, &sf7000_state::sf7000_map); - m_maincpu->set_addrmap(AS_IO, &sf7000_state::sf7000_io_map); - - /* video hardware */ - tms9918a_device &vdp(TMS9918A(config, TMS9918A_TAG, XTAL(10'738'635))); - vdp.set_screen("screen"); - vdp.set_vram_size(0x4000); - vdp.int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); - SCREEN(config, "screen", SCREEN_TYPE_RASTER); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - - SN76489A(config, SN76489AN_TAG, XTAL(10'738'635)/3).add_route(ALL_OUTPUTS, "mono", 1.00); - - /* devices */ - i8255_device &ppi(I8255(config, UPD9255_1_TAG)); - ppi.in_pa_callback().set(FUNC(sf7000_state::ppi_pa_r)); - ppi.out_pb_callback().set("cent_data_out", FUNC(output_latch_device::write)); - ppi.out_pc_callback().set(FUNC(sf7000_state::ppi_pc_w)); - - i8251_device &upd8251(I8251(config, UPD8251_TAG, 0)); - upd8251.txd_handler().set(RS232_TAG, FUNC(rs232_port_device::write_txd)); - upd8251.dtr_handler().set(RS232_TAG, FUNC(rs232_port_device::write_dtr)); - upd8251.rts_handler().set(RS232_TAG, FUNC(rs232_port_device::write_rts)); - - rs232_port_device &rs232(RS232_PORT(config, RS232_TAG, default_rs232_devices, nullptr)); - rs232.rxd_handler().set(UPD8251_TAG, FUNC(i8251_device::write_rxd)); - rs232.dsr_handler().set(UPD8251_TAG, FUNC(i8251_device::write_dsr)); - - UPD765A(config, m_fdc, 8'000'000, false, false); - FLOPPY_CONNECTOR(config, UPD765_TAG ":0", sf7000_floppies, "3ssdd", sf7000_state::floppy_formats); - - CENTRONICS(config, m_centronics, centronics_devices, "printer"); - - output_latch_device ¢_data_out(OUTPUT_LATCH(config, "cent_data_out")); - m_centronics->set_output_latch(cent_data_out); - - /* sf7000 (sc3000) has all sk1100 features built-in, so add it as a fixed slot */ - SG1000_EXPANSION_SLOT(config, m_sgexpslot, sg1000_expansion_devices, "sk1100", true); - - /* software lists */ - SOFTWARE_LIST(config, "flop_list").set_original("sf7000"); - - /* internal ram */ - RAM(config, m_ram).set_default_size("64K"); -} - -/*************************************************************************** - ROMS -***************************************************************************/ - -ROM_START( sg1000 ) - ROM_REGION( 0x10000, Z80_TAG, ROMREGION_ERASE00 ) -ROM_END - -#define rom_sg1000m2 rom_sg1000 - -#define rom_sc3000 rom_sg1000 - -#define rom_sc3000h rom_sg1000 - -ROM_START( sf7000 ) - ROM_REGION( 0x10000, Z80_TAG, ROMREGION_ERASE00 ) - ROM_LOAD( "ipl.rom", 0x0000, 0x2000, CRC(d76810b8) SHA1(77339a6db2593aadc638bed77b8e9bed5d9d87e3) ) -ROM_END - -ROM_START( omv1000 ) - ROM_REGION( 0x10000, Z80_TAG, ROMREGION_ERASE00 ) - ROM_LOAD( "omvbios.bin", 0x0000, 0x4000, BAD_DUMP CRC(c5a67b95) SHA1(6d7c64dd60dee4a33061d3d3a7c2ed190d895cdb) ) // The BIOS comes from a Multivision FG-2000. It is still unknown if the FG-1000 BIOS differs -ROM_END - -ROM_START( omv2000 ) - ROM_REGION( 0x10000, Z80_TAG, ROMREGION_ERASE00 ) - ROM_LOAD( "omvbios.bin", 0x0000, 0x4000, CRC(c5a67b95) SHA1(6d7c64dd60dee4a33061d3d3a7c2ed190d895cdb) ) -ROM_END - -/*************************************************************************** - SYSTEM DRIVERS -***************************************************************************/ - -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ -CONS( 1983, sg1000, 0, 0, sg1000, sg1000, sg1000_state, empty_init, "Sega", "SG-1000", MACHINE_SUPPORTS_SAVE ) -CONS( 1984, sg1000m2, sg1000, 0, sc3000, sc3000, sc3000_state, empty_init, "Sega", "SG-1000 II", MACHINE_SUPPORTS_SAVE ) -COMP( 1983, sc3000, 0, sg1000, sc3000, sc3000, sc3000_state, empty_init, "Sega", "SC-3000", MACHINE_SUPPORTS_SAVE ) -COMP( 1983, sc3000h, sc3000, 0, sc3000, sc3000, sc3000_state, empty_init, "Sega", "SC-3000H", MACHINE_SUPPORTS_SAVE ) -COMP( 1983, sf7000, sc3000, 0, sf7000, sf7000, sf7000_state, empty_init, "Sega", "SC-3000/Super Control Station SF-7000", MACHINE_SUPPORTS_SAVE ) -CONS( 1984, omv1000, sg1000, 0, omv, omv1000, sg1000_state, empty_init, "Tsukuda Original", "Othello Multivision FG-1000", MACHINE_SUPPORTS_SAVE ) -CONS( 1984, omv2000, sg1000, 0, omv, omv2000, sg1000_state, empty_init, "Tsukuda Original", "Othello Multivision FG-2000", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/segacons/sg1000.h b/src/mame/segacons/sg1000.h deleted file mode 100644 index 11e1a6ab851..00000000000 --- a/src/mame/segacons/sg1000.h +++ /dev/null @@ -1,124 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Curt Coder - -#ifndef MAME_INCLUDES_SG1000_H -#define MAME_INCLUDES_SG1000_H - -#include "cpu/z80/z80.h" -#include "formats/sf7000_dsk.h" -#include "imagedev/floppy.h" -#include "imagedev/printer.h" -#include "bus/centronics/ctronics.h" -#include "machine/i8255.h" -#include "machine/i8251.h" -#include "machine/ram.h" -#include "bus/sega8/sega8_slot.h" -#include "bus/sg1000_exp/sg1000exp.h" -#include "machine/upd765.h" -#include "sound/sn76496.h" -#include "video/tms9928a.h" -#include "crsshair.h" - -#define SCREEN_TAG "screen" -#define Z80_TAG "z80" -#define SN76489AN_TAG "sn76489an" -#define UPD765_TAG "upd765" -#define UPD8251_TAG "upd8251" -#define UPD9255_TAG "upd9255" -#define UPD9255_1_TAG "upd9255_1" // "upd9255_0" is being used by sk1100 device -#define CENTRONICS_TAG "centronics" -#define TMS9918A_TAG "tms9918a" -#define RS232_TAG "rs232" -#define CARTSLOT_TAG "slot" -#define EXPSLOT_TAG "sgexp" - - - -class sg1000_state : public driver_device -{ -public: - sg1000_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_maincpu(*this, Z80_TAG), - m_ram(*this, RAM_TAG), - m_rom(*this, Z80_TAG), - m_cart(*this, CARTSLOT_TAG), - m_sgexpslot(*this, EXPSLOT_TAG), - m_pa7(*this, "PA7"), - m_pb7(*this, "PB7") - { } - - void sg1000(machine_config &config); - void omv(machine_config &config); - - DECLARE_INPUT_CHANGED_MEMBER( trigger_nmi ); - -protected: - required_device m_maincpu; - required_device m_ram; - required_memory_region m_rom; - optional_device m_cart; - optional_device m_sgexpslot; - optional_ioport m_pa7; - optional_ioport m_pb7; - - virtual void machine_start() override; - - uint8_t peripheral_r(offs_t offset); - void peripheral_w(offs_t offset, uint8_t data); - - uint8_t omv_r(offs_t offset); - void omv_w(offs_t offset, uint8_t data); - - void omv_io_map(address_map &map); - void omv_map(address_map &map); - void sc3000_io_map(address_map &map); - void sc3000_map(address_map &map); - void sg1000_io_map(address_map &map); - void sg1000_map(address_map &map); -}; - -class sc3000_state : public sg1000_state -{ -public: - sc3000_state(const machine_config &mconfig, device_type type, const char *tag) - : sg1000_state(mconfig, type, tag) - { } - - void sc3000(machine_config &config); - -protected: - virtual void machine_start() override; -}; - -class sf7000_state : public sc3000_state -{ -public: - sf7000_state(const machine_config &mconfig, device_type type, const char *tag) - : sc3000_state(mconfig, type, tag), - m_fdc(*this, UPD765_TAG), - m_centronics(*this, CENTRONICS_TAG), - m_floppy0(*this, UPD765_TAG ":0:3ssdd") - { } - - void sf7000(machine_config &config); - -private: - required_device m_fdc; - required_device m_centronics; - required_device m_floppy0; - - virtual void machine_start() override; - virtual void machine_reset() override; - - int m_centronics_busy = 0; - DECLARE_WRITE_LINE_MEMBER( write_centronics_busy ); - uint8_t ppi_pa_r(); - void ppi_pc_w(uint8_t data); - - static void floppy_formats(format_registration &fr); - void sf7000_io_map(address_map &map); - void sf7000_map(address_map &map); -}; - -#endif diff --git a/src/mame/segacons/svmu.cpp b/src/mame/segacons/svmu.cpp deleted file mode 100644 index 61cc0a204de..00000000000 --- a/src/mame/segacons/svmu.cpp +++ /dev/null @@ -1,416 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Sandro Ronco -/*************************************************************************** - - Sega Visual Memory Unit - - driver by Sandro Ronco - - TODO: - - add more bios versions - - serial - -****************************************************************************/ - -#include "emu.h" -#include "cpu/lc8670/lc8670.h" -#include "imagedev/snapquik.h" -#include "machine/intelfsh.h" -#include "sound/spkrdev.h" -#include "emupal.h" -#include "screen.h" -#include "softlist_dev.h" -#include "speaker.h" - -#include "svmu.lh" - - -#define PIXEL_SIZE 7 -#define PIXEL_DISTANCE 1 - -class svmu_state : public driver_device -{ -public: - svmu_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_flash(*this, "flash") - , m_speaker(*this, "speaker") - , m_bios(*this, "bios") - , m_battery(*this, "BATTERY") - , m_file_icon(*this, "file_icon") - , m_game_icon(*this, "game_icon") - , m_clock_icon(*this, "clock_icon") - , m_flash_icon(*this, "flash_icon") - { } - - void svmu(machine_config &config); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - -private: - LC8670_LCD_UPDATE(svmu_lcd_update); - void svmu_palette(palette_device &palette) const; - void page_w(uint8_t data); - uint8_t prog_r(offs_t offset); - void prog_w(offs_t offset, uint8_t data); - uint8_t p1_r(); - void p1_w(uint8_t data); - uint8_t p7_r(); - DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb); - - void svmu_io_mem(address_map &map); - void svmu_mem(address_map &map); - - required_device m_maincpu; - required_device m_flash; - required_device m_speaker; - required_region_ptr m_bios; - required_ioport m_battery; - output_finder<> m_file_icon; - output_finder<> m_game_icon; - output_finder<> m_clock_icon; - output_finder<> m_flash_icon; - - uint8_t m_page; -}; - - -void svmu_state::page_w(uint8_t data) -{ - m_page = data & 0x03; -} - -uint8_t svmu_state::prog_r(offs_t offset) -{ - if (m_page == 1) - return m_flash->read(offset); - else if (m_page == 2) - return m_flash->read(0x10000 + offset); - else - return m_bios[offset]; -} - -void svmu_state::prog_w(offs_t offset, uint8_t data) -{ - if (m_page == 1) - m_flash->write(offset, data); - else if (m_page == 2) - m_flash->write(0x10000 + offset, data); -} - -/* - Port 1 - - x--- ---- PWM output - -x-- ---- BUZ - --x- ---- SCK1 - ---x ---- SB1 - ---- x--- SO1 - ---- -x-- SCK0 - ---- --x- SB0 - ---- ---x SO0 - -*/ - -uint8_t svmu_state::p1_r() -{ - return 0; -} - -void svmu_state::p1_w(uint8_t data) -{ - m_speaker->level_w(BIT(data, 7)); -} - - -/* - Port 7 - - ---- x--- ID1 - ---- -x-- ID0 - ---- --x- battery low voltage - ---- ---x 5V detection -*/ - -uint8_t svmu_state::p7_r() -{ - return (m_battery->read()<<1); -} - - -void svmu_state::svmu_mem(address_map &map) -{ - map(0x0000, 0xffff).rw(FUNC(svmu_state::prog_r), FUNC(svmu_state::prog_w)); -} - -void svmu_state::svmu_io_mem(address_map &map) -{ - map(LC8670_PORT1, LC8670_PORT1).rw(FUNC(svmu_state::p1_r), FUNC(svmu_state::p1_w)); - map(LC8670_PORT3, LC8670_PORT3).portr("P3"); - map(LC8670_PORT7, LC8670_PORT7).r(FUNC(svmu_state::p7_r)); -} - -/* Input ports */ -static INPUT_PORTS_START( svmu ) - PORT_START( "P3" ) - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_NAME("Up") - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_NAME("Down") - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_NAME("Left") - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_NAME("Right") - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Button A") - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("Button B") - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("MODE") PORT_CODE( KEYCODE_M ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("SLEEP") PORT_CODE( KEYCODE_S ) - PORT_START("BATTERY") - PORT_CONFNAME( 0x01, 0x01, "Battery" ) - PORT_CONFSETTING( 0x01, "Good" ) - PORT_CONFSETTING( 0x00, "Poor" ) -INPUT_PORTS_END - -void svmu_state::machine_start() -{ - m_file_icon.resolve(); - m_game_icon.resolve(); - m_clock_icon.resolve(); - m_flash_icon.resolve(); -} - -void svmu_state::machine_reset() -{ - m_page = 0; -} - -void svmu_state::svmu_palette(palette_device &palette) const -{ - palette.set_pen_color(0, rgb_t(138, 146, 148)); - palette.set_pen_color(1, rgb_t(92, 83, 88)); -} - -LC8670_LCD_UPDATE(svmu_state::svmu_lcd_update) -{ - if (lcd_enabled) - { - for (int y=0; y<32; y++) - for (int x=0; x<6; x++) - { - int gfx = vram[y*6 + x]; - - for (int b = 0; b < 8; b++) - bitmap.plot_box((x*8 + b) * (PIXEL_SIZE + PIXEL_DISTANCE), y * (PIXEL_SIZE + PIXEL_DISTANCE), PIXEL_SIZE, PIXEL_SIZE, BIT(gfx,7-b)); - } - } - else - { - bitmap.fill(0, cliprect); - } - - m_file_icon = lcd_enabled ? BIT(vram[0xc1],6) : 0; - m_game_icon = lcd_enabled ? BIT(vram[0xc2],4) : 0; - m_clock_icon = lcd_enabled ? BIT(vram[0xc3],2) : 0; - m_flash_icon = lcd_enabled ? BIT(vram[0xc4],0) : 0; - - return 0; -} - - -inline void vmufat_write_byte(uint8_t* flash, uint8_t block, offs_t offset, uint8_t data) -{ - flash[(block * 512) + offset] = data; -} - -inline void vmufat_write_word(uint8_t* flash, uint8_t block, offs_t offset, uint16_t data) -{ - // 16-bit data are stored in little endian - flash[(block * 512) + offset + 0] = data & 0xff; - flash[(block * 512) + offset + 1] = (data>>8) & 0xff; -} - -QUICKLOAD_LOAD_MEMBER(svmu_state::quickload_cb) -{ - uint32_t size = image.length(); - uint8_t *flash = m_flash->base(); - - image.fread(flash, size); - - // verify if image is already a valid VMUFAT file system - bool valid_vmufat = true; - if (size == 0x20000) - { - for (int i=0; i<0x10; i++) - if (flash[255 * 512 + i] != 0x55) - { - valid_vmufat = false; - break; - } - } - else - { - valid_vmufat = false; - } - - if (!valid_vmufat) - { - // more info about the VMUFAT here: http://mc.pp.se/dc/vms/flashmem.html - - //-------------------------------- Formatting -------------------------------- - memset(flash + 241*512, 0, 15*512); // clears the last 15 blocks that contain file system information - - for (int i=0; i<0x10; i++) - vmufat_write_byte(flash, 255, i, 0x55); // first 16 bytes should be 0x55 to indicate a properly formatted card - - vmufat_write_byte(flash, 255, 0x10, 0x00); // custom VMS colour (1 = use custom colours, 0 = standard colour) - vmufat_write_byte(flash, 255, 0x11, 0x00); // VMS colour blue component - vmufat_write_byte(flash, 255, 0x12, 0x00); // VMS colour green component - vmufat_write_byte(flash, 255, 0x13, 0x00); // VMS colour red component - vmufat_write_byte(flash, 255, 0x14, 0x00); // VMS colour alpha component - vmufat_write_byte(flash, 255, 0x30, 0x19); // Century (BCD) - vmufat_write_byte(flash, 255, 0x31, 0x99); // Year (BCD) - vmufat_write_byte(flash, 255, 0x32, 0x01); // Month (BCD) - vmufat_write_byte(flash, 255, 0x33, 0x01); // Day (BCD) - vmufat_write_byte(flash, 255, 0x34, 0x00); // Hour (BCD) - vmufat_write_byte(flash, 255, 0x35, 0x00); // Minute (BCD) - vmufat_write_byte(flash, 255, 0x36, 0x00); // Second (BCD) - vmufat_write_byte(flash, 255, 0x37, 0x00); // Day of week (0 = Monday, 6 = Sunday) - vmufat_write_word(flash, 255, 0x44, 0x00ff); // location of Root - vmufat_write_word(flash, 255, 0x46, 0x00fe); // location of FAT (254) - vmufat_write_word(flash, 255, 0x48, 0x0001); // size of FAT in blocks (1) - vmufat_write_word(flash, 255, 0x4a, 0x00fd); // location of Directory (253) - vmufat_write_word(flash, 255, 0x4c, 0x000d); // size of Directory in blocks (13) - vmufat_write_word(flash, 255, 0x4e, 0x0000); // icon shape for this VMS (0-123) - vmufat_write_word(flash, 255, 0x50, 0x00c8); // number of user blocks (200) - - for (int i=0; i<256; i++) - vmufat_write_word(flash, 254, i<<1, 0xfffc); // marks all blocks as unallocated - - for (int i=253; i>241; --i) - vmufat_write_word(flash, 254, i<<1, i - 1); // marsk all Directory blocks as allocate - - vmufat_write_word(flash, 254, 0x1e2, 0xfffa); // marks last Directory block - vmufat_write_word(flash, 254, 0x1fc, 0xfffa); // marks FAT block as allocated - vmufat_write_word(flash, 254, 0x1fe, 0xfffa); // marks Root block as allocated - - //-------------------------------- Create the vms file -------------------------------- - int vms_blocks = (size / 512) + (size & 0x1ff ? 1 : 0); // number of blocks required for store the vms file - - for (int i=0; iset_addrmap(AS_PROGRAM, &svmu_state::svmu_mem); - m_maincpu->set_addrmap(AS_IO, &svmu_state::svmu_io_mem); - - /* specific LC8670 configurations */ - m_maincpu->set_clock_sources(XTAL(32'768), 600000, XTAL(6'000'000)); // tolerance range of the RC oscillator is 600kHz to 1200kHz - m_maincpu->bank_cb().set(FUNC(svmu_state::page_w)); - m_maincpu->set_lcd_update_cb(FUNC(svmu_state::svmu_lcd_update)); - - /* video hardware */ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // not accurate - screen.set_size(48 * (PIXEL_SIZE + PIXEL_DISTANCE), 32 * (PIXEL_SIZE + PIXEL_DISTANCE)); - screen.set_visarea(0, 48*(PIXEL_SIZE + PIXEL_DISTANCE) - 1, 0, 32*(PIXEL_SIZE + PIXEL_DISTANCE) - 1); - screen.set_screen_update("maincpu", FUNC(lc8670_cpu_device::screen_update)); - screen.set_palette("palette"); - - config.set_default_layout(layout_svmu); - PALETTE(config, "palette", FUNC(svmu_state::svmu_palette), 2); - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50); - - /* devices */ - ATMEL_29C010(config, m_flash); - - quickload_image_device &quickload(QUICKLOAD(config, "quickload", "vms,bin")); - quickload.set_load_callback(FUNC(svmu_state::quickload_cb)); - quickload.set_interface("svmu_quik"); - - /* Software lists */ - SOFTWARE_LIST(config, "quik_list").set_original("svmu"); -} - - -/* ROM definition */ -ROM_START( svmu ) - // some ROMs come from the Sega Katana SDK and are scrambled, a simple way to restore them is to remove the first 4 bytes and xor the whole file for the xor key. - - ROM_REGION(0x10000, "bios", 0) - ROM_DEFAULT_BIOS("en1005b") - - // Version 1.005,1999/04/28,315-6124-07,SEGA Visual Memory System BIOS Produced by Sue - ROM_SYSTEM_BIOS(0, "en1005a", "VMS English BIOS (1.005 1999/04/28)") - ROMX_LOAD("en1005-19990428-315-6124-07.bin", 0x0000, 0x10000, CRC(dfd77f4e) SHA1(4a7bfd1b8eb599d87883312df0bb48e0edd13034), ROM_BIOS(0)) // extracted with trojan - - // Version 1.005,1999/10/26,315-6208-05,SEGA Visual Memory System BIOS Produced by Sue - ROM_SYSTEM_BIOS(1, "en1005b", "VMS English BIOS (1.005 1999/10/26)") - ROMX_LOAD("en1005-19991026-315-6208-05.bin", 0x0000, 0x10000, CRC(c825003a) SHA1(6242320d705c156f8369969d6caa8c737f01e4f3), ROM_BIOS(1)) // extracted with trojan - - // Version 1.001,1998/05/28,315-6124-02,SEGA Visual Memory System BIOS Produced by Sue - ROM_SYSTEM_BIOS(2, "jp1001", "VMS Japanese BIOS (1.001 1998/05/28)") - ROMX_LOAD("jp1001-19980528-315-6124-02.bin", 0x0000, 0x10000, CRC(e6339f4a) SHA1(688b2e1ff8c60bde6e8b07a2d2695cdacc07bd0c), ROM_BIOS(2)) - - // Version 1.002,1998/06/04,315-6124-03,SEGA Visual Memory System BIOS Produced by Sue - ROM_SYSTEM_BIOS(3, "jp1002", "VMS Japanese BIOS (1.002 1998/06/04)") - ROMX_LOAD("jp1002-19980604-315-6124-03.bin", 0x0000, 0x10000, CRC(6c020d48) SHA1(9ee7c87d7b033235e0b315a0b421e70deb547c7a), ROM_BIOS(3)) - - // Version 1.004,1998/09/30,315-6208-01,SEGA Visual Memory System BIOS Produced by Sue - ROM_SYSTEM_BIOS(4, "jp1004", "VMS Japanese BIOS (1.004, 1998/09/30)") - ROMX_LOAD("jp1004-19980930-315-6208-01.bin", 0x0000, 0x10000, CRC(8e0f867a) SHA1(dc2fa2963138a1049a43f7f36439ad0a416ee8b4), ROM_BIOS(4)) // from Sega Katana SDK (original file: fbios.sbf, CRC: c7c77b3c, xor key: 0x37) - - // Version 1.005,1998/12/09,315-6124-05,SEGA Visual Memory System BIOS Produced by Sue - ROM_SYSTEM_BIOS(5, "jp1005a", "VMS Japanese BIOS (1.005 1998/12/09)") - ROMX_LOAD("jp1005-19981209-315-6124-05.bin", 0x0000, 0x10000, CRC(47623324) SHA1(fca1aceff8a2f8c6826f3a865f4d5ef88dfd9ed1), ROM_BIOS(5)) - - // Version 1.005,1999/10/26,315-6208-04,SEGA Visual Memory System BIOS Produced by Sue - ROM_SYSTEM_BIOS(6, "jp1005b", "VMS Japanese BIOS (1.005 1999/10/26)") - ROMX_LOAD("jp1005-19991026-315-6208-04.bin", 0x0000, 0x10000, CRC(6cab02c2) SHA1(6cc2fbf4a67770988922117c300d006aa20899ac), ROM_BIOS(6)) // extracted with trojan - - // Version 1.004,1998/09/30,315-6208-01,SEGA Visual Memory System BIOS Produced by Sue - ROM_SYSTEM_BIOS(7, "dev1004", "VMS Japanese Development BIOS (1.004 1998/09/30)") // automatically boot the first game found in the flash - ROMX_LOAD( "jp1004-19980930-315-6208-01-dev.bin", 0x0000, 0x10000, CRC(395e25f2) SHA1(37dea034322b5b80b35b2de784298d32c71ba7a3), ROM_BIOS(7)) // from Sega Katana SDK (original file: qbios.sbf, CRC: eed5524c, xor key: 0x43) -ROM_END - - -/* Driver */ - -/* YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS */ -COMP( 1998, svmu, 0, 0, svmu, svmu, svmu_state, empty_init, "Sega", "Visual Memory Unit", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) diff --git a/src/mame/shared/dc-ctrl.cpp b/src/mame/shared/dc-ctrl.cpp deleted file mode 100644 index fe2925fcf0b..00000000000 --- a/src/mame/shared/dc-ctrl.cpp +++ /dev/null @@ -1,164 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert -#include "emu.h" -#include "dc-ctrl.h" - -/******************************* - * - * Common abstract class - * - ******************************/ - -dc_common_device::dc_common_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - maple_device(mconfig, type, tag, owner, clock) - , port(*this, {finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG}) -{ -} - -void dc_common_device::device_start() -{ - maple_device::device_start(); -} - -void dc_common_device::maple_w(const uint32_t *data, uint32_t in_size) -{ - switch(data[0] & 0xff) { - case 0x01: // Device request - reply_start(5, 0x20, 29); - fixed_status(reply_buffer+1); - reply_ready_with_delay(); - break; - - case 0x02: // All status request - reply_start(6, 0x20, 49); - fixed_status(reply_buffer+1); - free_status(reply_buffer+29); - reply_ready_with_delay(); - break; - - case 0x03: // reset - we're stateless where it matters - reply_start(7, 0x20, 0); - reply_ready_with_delay(); - break; - - case 0x09: // get condition - if(1 || (in_size >= 2 && data[1] == 0x01000000)) { - reply_start(8, 0x20, 4); - read(reply_buffer+1); - reply_ready_with_delay(); - } - break; - } -} - -/******************************* - * - * Dreamcast Controller - * - ******************************/ - -DEFINE_DEVICE_TYPE(DC_CONTROLLER, dc_controller_device, "dcctrl", "Dreamcast Controller") - -dc_controller_device::dc_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dc_common_device(mconfig, DC_CONTROLLER, tag, owner, clock) -{ - model = "Dreamcast Controller"; - license = "Produced By or Under License From SEGA ENTERPRISES,LTD."; - versions = "Version 1.000,1998/05/11,315-6215-AB ,Analog Module: The 4th Edition. 05/08"; - id = 0x01000000; // Controller - electric_current = 0x01f401ae; // max 50mA, standby 43mA - region = 0x00ff; -} - -void dc_controller_device::fixed_status(uint32_t *dest) -{ - dest[0] = id; - dest[1] = - ((port[2] != nullptr) ? 0x0100 : 0) | - ((port[3] != nullptr) ? 0x0200 : 0) | - ((port[4] != nullptr) ? 0x0400 : 0) | - ((port[5] != nullptr) ? 0x0800 : 0) | - ((port[6] != nullptr) ? 0x1000 : 0) | - ((port[7] != nullptr) ? 0x2000 : 0) | - ((port[0] ? port[0]->active() : 0) << 24) | - ((port[1] ? port[1]->active() : 0) << 16); // 1st function - controller - dest[2] = 0; // No 2nd function - dest[3] = 0; // No 3rd function - dest[4] = region; // Every region, no expansion - copy_with_spaces(((uint8_t *)dest) + 18, model, 30); - copy_with_spaces(((uint8_t *)dest) + 48, license, 60); - dest[27] = electric_current; -} - -void dc_controller_device::free_status(uint32_t *dest) -{ - copy_with_spaces((uint8_t *)dest, versions, 80); -} - -void dc_controller_device::read(uint32_t *dest) -{ - dest[0] = id; // Controller - dest[1] = - (port[0] ? port[0]->read() : 0xff) | - ((port[1] ? port[1]->read() : 0xff) << 8) | - ((port[2] ? port[2]->read() : 0) << 16) | - ((port[3] ? port[3]->read() : 0) << 24); - dest[2] = - (port[4] ? port[4]->read() : 0x80) | - ((port[5] ? port[5]->read() : 0x80) << 8) | - ((port[6] ? port[6]->read() : 0x80) << 16) | - ((port[7] ? port[7]->read() : 0x80) << 24); -} - -/******************************* - * - * Dreamcast Keyboard - * - ******************************/ - -DEFINE_DEVICE_TYPE(DC_KEYBOARD, dc_keyboard_device, "dckb", "Dreamcast Keyboard") - -dc_keyboard_device::dc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dc_common_device(mconfig, DC_KEYBOARD, tag, owner, clock) -{ - model = "92key Keyboard for JPN"; - license = "Produced By or Under License From SEGA ENTERPRISES,LTD."; - versions = "Version 1.000,1998/06/12,315-6215-AD ,Key Scan Module: The 1st Edition. 05/20"; - id = 0x40000000; // Keyboard - electric_current = 0x0190015e; // max 40mA, standby 35mA - region = 0x0002; // Japan region, no expansion -} - -void dc_keyboard_device::fixed_status(uint32_t *dest) -{ - dest[0] = id; // Keyboard - dest[1] = 0x00201000; // 1st function - dest[2] = 0x00000008; // No 2nd function (doc returns 8 here tho?) - dest[3] = 0x00000000; // No 3rd function - dest[4] = region; - copy_with_spaces(((uint8_t *)dest) + 18, model, 30); - copy_with_spaces(((uint8_t *)dest) + 48, license, 60); - dest[27] = electric_current; -} - -void dc_keyboard_device::free_status(uint32_t *dest) -{ - copy_with_spaces((uint8_t *)dest, versions, 80); -} - -void dc_keyboard_device::read(uint32_t *dest) -{ - dest[0] = id; - // key code - dest[1] = - (port[0] ? port[0]->read() : 0) | - ((port[1] ? port[1]->read() : 0) << 8) | - ((port[2] ? port[2]->read() : 0) << 16) | - ((port[3] ? port[3]->read() : 0) << 24); - dest[2] = - (port[4] ? port[4]->read() : 0) | - ((port[5] ? port[5]->read() : 0) << 8) | - ((port[6] ? port[6]->read() : 0) << 16) | - ((port[7] ? port[7]->read() : 0) << 24); -} - diff --git a/src/mame/shared/dc-ctrl.h b/src/mame/shared/dc-ctrl.h deleted file mode 100644 index 4fd4cd65131..00000000000 --- a/src/mame/shared/dc-ctrl.h +++ /dev/null @@ -1,97 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert -#ifndef MAME_MACHINE_DC_CTRL_H -#define MAME_MACHINE_DC_CTRL_H - -#pragma once - -#include "mapledev.h" - - -class dc_common_device : public maple_device -{ -public: - // construction/destruction - dc_common_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - template - void set_port_tag(T &&port_tag) { port[Which].set_tag(std::forward(port_tag)); } - template - void set_port_tags(T &&first_tag, U &&... other_tags) - { - set_port_tag(std::forward(first_tag)); - set_port_tags(std::forward(other_tags)...); - } - - // TODO: we probably don't need these setters - void set_model(const char *new_id) { model = new_id; } - void set_license(const char *new_license) { license = new_license; } - void set_versions(const char *new_versions) { versions = new_versions; } - - void maple_w(const uint32_t *data, uint32_t in_size) override; - -protected: - template void set_port_tags() { } - - // device-level overrides - virtual void device_start() override; - - const char *model = nullptr, *license = nullptr, *versions = nullptr; - uint32_t id = 0; - uint32_t electric_current = 0; - uint32_t region = 0; - - optional_ioport_array<8> port; - - virtual void fixed_status(uint32_t *dest) = 0; - virtual void free_status(uint32_t *dest) = 0; - virtual void read(uint32_t *dest) = 0; -}; - -class dc_controller_device : public dc_common_device -{ -public: - // construction/destruction - template - dc_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&host_tag, int host_port) - : dc_controller_device(mconfig, tag, owner, clock) - { - host.set_tag(std::forward(host_tag)); - set_host_port(host_port); - } - - dc_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -private: - void fixed_status(uint32_t *dest) override; - void free_status(uint32_t *dest) override; - void read(uint32_t *dest) override; -}; - - -class dc_keyboard_device : public dc_common_device -{ -public: - // construction/destruction - template - dc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&host_tag, int host_port) - : dc_keyboard_device(mconfig, tag, owner, clock) - { - host.set_tag(std::forward(host_tag)); - set_host_port(host_port); - } - - dc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -//protected: - -private: - void fixed_status(uint32_t *dest) override; - void free_status(uint32_t *dest) override; - void read(uint32_t *dest) override; -}; - -DECLARE_DEVICE_TYPE(DC_CONTROLLER, dc_controller_device) -DECLARE_DEVICE_TYPE(DC_KEYBOARD, dc_keyboard_device) - -#endif // MAME_MACHINE_DC_CTRL_H diff --git a/src/mame/shared/dc.cpp b/src/mame/shared/dc.cpp deleted file mode 100644 index 9e97c847294..00000000000 --- a/src/mame/shared/dc.cpp +++ /dev/null @@ -1,668 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders: Samuele Zannoli, R. Belmont, ElSemi, David Haywood, Angelo Salese, Olivier Galibert, MetalliC -/* - - dc.cpp - Sega Dreamcast hardware - - Misc interfacing to common DC buses over the various clients. - -*/ - -#include "emu.h" -#include "dc.h" - -#include "mie.h" - -#include "cpu/sh/sh4.h" -#include "cpu/arm7/arm7core.h" - -//#include "debugger.h" - -#define DEBUG_REGISTERS (1) - -#if DEBUG_REGISTERS - -#define DEBUG_SYSCTRL (0) -#define DEBUG_AICA_DMA (0) - -#if DEBUG_SYSCTRL -static const char *const sysctrl_names[] = -{ - "CH2 DMA dest", - "CH2 DMA length", - "CH2 DMA start", - "5f680c", - "Sort DMA start link table addr", - "Sort DMA link base addr", - "Sort DMA link address bit width", - "Sort DMA link address shift control", - "Sort DMA start", - "5f6824", "5f6828", "5f682c", "5f6830", - "5f6834", "5f6838", "5f683c", - "DBREQ # signal mask control", - "BAVL # signal wait count", - "DMA priority count", - "CH2 DMA max burst length", - "5f6850", "5f6854", "5f6858", "5f685c", - "5f6860", "5f6864", "5f6868", "5f686c", - "5f6870", "5f6874", "5f6878", "5f687c", - "TA FIFO remaining", - "TA texture memory bus select 0", - "TA texture memory bus select 1", - "FIFO status", - "System reset", "5f6894", "5f6898", - "System bus version", - "SH4 root bus split enable", - "5f68a4", "5f68a8", "5f68ac", - "5f68b0", "5f68b4", "5f68b8", "5f68bc", - "5f68c0", "5f68c4", "5f68c8", "5f68cc", - "5f68d0", "5f68d4", "5f68d8", "5f68dc", - "5f68e0", "5f68e4", "5f68e8", "5f68ec", - "5f68f0", "5f68f4", "5f68f8", "5f68fc", - "Normal IRQ status", - "External IRQ status", - "Error IRQ status", "5f690c", - "Level 2 normal IRQ mask", - "Level 2 external IRQ mask", - "Level 2 error IRQ mask", "5f691c", - "Level 4 normal IRQ mask", - "Level 4 external IRQ mask", - "Level 4 error IRQ mask", "5f692c", - "Level 6 normal IRQ mask", - "Level 6 external IRQ mask", - "Level 6 error IRQ mask", "5f693c", - "Normal IRQ PVR-DMA startup mask", - "External IRQ PVR-DMA startup mask", - "5f6948", "5f694c", - "Normal IRQ G2-DMA startup mask", - "External IRQ G2-DMA startup mask" -}; -#endif - -#endif - -void dc_state::generic_dma(uint32_t main_adr, void *dma_ptr, uint32_t length, uint32_t size, bool to_mainram) -{ - sh4_ddt_dma ddt; - if(to_mainram) - ddt.destination = main_adr; - else - ddt.source = main_adr; - ddt.buffer = dma_ptr; - ddt.length = length; - ddt.size = size; - ddt.direction = to_mainram; - ddt.channel = 0; - ddt.mode = -1; - m_maincpu->sh4_dma_ddt(&ddt); -} - -void dc_state::g2_dma_end_w(offs_t channel, u8 state) -{ - dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_AICA << channel; - dc_update_interrupt_status(); -} - -void dc_state::g2_dma_error_ia_w(offs_t channel, u8 state) -{ - dc_sysctrl_regs[SB_ISTERR] |= 0x8000 << channel; - dc_update_interrupt_status(); -} - -void dc_state::g2_dma_error_ov_w(offs_t channel, u8 state) -{ - dc_sysctrl_regs[SB_ISTERR] |= 0x80000 << channel; - dc_update_interrupt_status(); -} - -void dc_state::g1_irq(uint8_t data) -{ - switch(data) { - case naomi_g1_device::DMA_GDROM_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_GDROM; - break; - } - dc_update_interrupt_status(); -} - -void dc_state::pvr_irq(uint8_t data) -{ - switch(data) { - case powervr2_device::EOXFER_YUV_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_YUV; - break; - - case powervr2_device::EOXFER_OPLST_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_OPLST; - break; - - case powervr2_device::EOXFER_OPMV_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_OPMV; - break; - - case powervr2_device::EOXFER_TRLST_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_TRLST; - break; - - case powervr2_device::EOXFER_TRMV_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_TRMV; - break; - - case powervr2_device::EOXFER_PTLST_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_PTLST; - break; - - case powervr2_device::VBL_IN_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_VBL_IN; - break; - - case powervr2_device::VBL_OUT_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_VBL_OUT; - break; - - case powervr2_device::HBL_IN_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_HBL_IN; - break; - - case powervr2_device::EOR_VIDEO_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_VIDEO; - break; - - case powervr2_device::EOR_TSP_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_TSP; - break; - - case powervr2_device::EOR_ISP_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_ISP; - break; - - case powervr2_device::DMA_PVR_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_PVR; - break; - - case powervr2_device::ERR_ISP_LIMIT_IRQ: - dc_sysctrl_regs[SB_ISTERR] |= IST_ERR_ISP_LIMIT; - break; - - case powervr2_device::ERR_PVRIF_ILL_ADDR_IRQ: - dc_sysctrl_regs[SB_ISTERR] |= IST_ERR_PVRIF_ILL_ADDR; - break; - } - dc_update_interrupt_status(); -} - -void dc_state::maple_irq(uint8_t data) -{ - switch(data) { - case maple_dc_device::DMA_MAPLE_IRQ: - dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_MAPLE; - break; - } - dc_update_interrupt_status(); -} - -TIMER_CALLBACK_MEMBER(dc_state::ch2_dma_irq) -{ - dc_sysctrl_regs[SB_C2DLEN] = 0; - dc_sysctrl_regs[SB_C2DST] = 0; - dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_CH2; - dc_update_interrupt_status(); -} - -// register decode helpers - -// this accepts only 32-bit accesses -int dc_state::decode_reg32_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift) -{ - int reg = offset * 2; - - *shift = 0; - - // non 32-bit accesses have not yet been seen here, we need to know when they are - if ((mem_mask != 0xffffffff00000000U) && (mem_mask != 0x00000000ffffffffU)) - { - osd_printf_verbose("%s:Wrong mask!\n", machine().describe_context()); - //machine().debug_break(); - } - - if (mem_mask == 0xffffffff00000000U) - { - reg++; - *shift = 32; - } - - return reg; -} - -// this accepts only 32 and 16 bit accesses -int dc_state::decode_reg3216_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift) -{ - int reg = offset * 2; - - *shift = 0; - - // non 16&32-bit accesses have not yet been seen here, we need to know when they are - if ((mem_mask != 0x0000ffff00000000U) && (mem_mask != 0x000000000000ffffU) && - (mem_mask != 0xffffffff00000000U) && (mem_mask != 0x00000000ffffffffU)) - { - osd_printf_verbose("%s:Wrong mask!\n", machine().describe_context()); - //machine().debug_break(); - } - - if (ACCESSING_BITS_32_47) - { - reg++; - *shift = 32; - } - - return reg; -} - -int dc_state::dc_compute_interrupt_level() -{ - uint32_t ln,lx,le; - - ln=dc_sysctrl_regs[SB_ISTNRM] & dc_sysctrl_regs[SB_IML6NRM]; - lx=dc_sysctrl_regs[SB_ISTEXT] & dc_sysctrl_regs[SB_IML6EXT]; - le=dc_sysctrl_regs[SB_ISTERR] & dc_sysctrl_regs[SB_IML6ERR]; - if (ln | lx | le) - { - return 6; - } - - ln=dc_sysctrl_regs[SB_ISTNRM] & dc_sysctrl_regs[SB_IML4NRM]; - lx=dc_sysctrl_regs[SB_ISTEXT] & dc_sysctrl_regs[SB_IML4EXT]; - le=dc_sysctrl_regs[SB_ISTERR] & dc_sysctrl_regs[SB_IML4ERR]; - if (ln | lx | le) - { - return 4; - } - - ln=dc_sysctrl_regs[SB_ISTNRM] & dc_sysctrl_regs[SB_IML2NRM]; - lx=dc_sysctrl_regs[SB_ISTEXT] & dc_sysctrl_regs[SB_IML2EXT]; - le=dc_sysctrl_regs[SB_ISTERR] & dc_sysctrl_regs[SB_IML2ERR]; - if (ln | lx | le) - { - return 2; - } - - return 0; -} - -void dc_state::dc_update_interrupt_status() -{ - int level; - - if (dc_sysctrl_regs[SB_ISTERR]) - { - dc_sysctrl_regs[SB_ISTNRM] |= IST_ERROR; - } - else - { - dc_sysctrl_regs[SB_ISTNRM] &= ~IST_ERROR; - } - - if (dc_sysctrl_regs[SB_ISTEXT]) - { - dc_sysctrl_regs[SB_ISTNRM] |= IST_G1G2EXTSTAT; - } - else - { - dc_sysctrl_regs[SB_ISTNRM] &= ~IST_G1G2EXTSTAT; - } - - level=dc_compute_interrupt_level(); - m_maincpu->sh4_set_irln_input(15-level); - - /* Wave DMA HW trigger */ - m_g2if->hw_irq_trigger_hs( - dc_sysctrl_regs[SB_G2DTNRM] & dc_sysctrl_regs[SB_ISTNRM], - dc_sysctrl_regs[SB_G2DTEXT] & dc_sysctrl_regs[SB_ISTEXT] - ); - - /* PVR-DMA HW trigger */ - if(m_powervr2->m_pvr_dma.flag && ((m_powervr2->m_pvr_dma.sel & 1) == 1)) - { - if((dc_sysctrl_regs[SB_PDTNRM] & dc_sysctrl_regs[SB_ISTNRM]) || (dc_sysctrl_regs[SB_PDTEXT] & dc_sysctrl_regs[SB_ISTEXT])) - { - address_space &space = m_maincpu->space(AS_PROGRAM); - - logerror("PVR-DMA HW trigger\n"); - m_powervr2->pvr_dma_execute(space); - } - } -} - -// TODO: convert SYSCTRL to device I/F (NAOMI2 needs two of these) -uint64_t dc_state::dc_sysctrl_r(offs_t offset, uint64_t mem_mask) -{ - int reg; - uint64_t shift; - - reg = decode_reg32_64(offset, mem_mask, &shift); - - #if DEBUG_SYSCTRL - if ((reg != 0x40) && (reg != 0x41) && (reg != 0x42) && (reg != 0x23) && (reg > 2)) // filter out IRQ status reads - { - osd_printf_verbose("SYSCTRL: [%08x] read %x @ %x (reg %x: %s), mask %x (PC=%x)\n", 0x5f6800+reg*4, dc_sysctrl_regs[reg], offset, reg, sysctrl_names[reg], mem_mask, m_maincpu->pc()); - } - #endif - - return (uint64_t)dc_sysctrl_regs[reg] << shift; -} - -void dc_state::dc_sysctrl_w(offs_t offset, uint64_t data, uint64_t mem_mask) -{ - int reg; - uint64_t shift; - uint32_t old,dat; - uint32_t address; - struct sh4_ddt_dma ddtdata; - - reg = decode_reg32_64(offset, mem_mask, &shift); - dat = (uint32_t)(data >> shift); - old = dc_sysctrl_regs[reg]; - dc_sysctrl_regs[reg] = dat; // 5f6800+off*4=dat - switch (reg) - { - case SB_C2DST: - if(((old & 1) == 0) && (dat & 1)) // 0 -> 1 - { - address=(dc_sysctrl_regs[SB_C2DSTAT] & 0x03ffffe0) | 0x10000000; - if(dc_sysctrl_regs[SB_C2DSTAT] & 0x1f) - printf("C2DSTAT just used to reserved bits %02x\n",dc_sysctrl_regs[SB_C2DSTAT] & 0x1f); - - ddtdata.destination=address; - /* 0 rounding size = 16 Mbytes */ - if(dc_sysctrl_regs[SB_C2DLEN] == 0) - ddtdata.length = 0x1000000; - else - ddtdata.length = dc_sysctrl_regs[SB_C2DLEN]; - ddtdata.size=1; - ddtdata.direction=0; - ddtdata.channel=2; - ddtdata.mode=25; //011001 - m_maincpu->sh4_dma_ddt(&ddtdata); - #if DEBUG_SYSCTRL - if ((address >= 0x11000000) && (address <= 0x11FFFFFF)) - if (dc_sysctrl_regs[SB_LMMODE0]) - printf("SYSCTRL: Ch2 direct display lists dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); // 1 - else - osd_printf_verbose("SYSCTRL: Ch2 direct textures dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); // 0 - else if ((address >= 0x13000000) && (address <= 0x13FFFFFF)) - if (dc_sysctrl_regs[SB_LMMODE1]) - printf("SYSCTRL: Ch2 direct display lists dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); // 1 - else - osd_printf_verbose("SYSCTRL: Ch2 direct textures dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); // 0 - else if ((address >= 0x10800000) && (address <= 0x10ffffff)) - printf("SYSCTRL: Ch2 YUV dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); - else if ((address >= 0x10000000) && (address <= 0x107fffff)) - osd_printf_verbose("SYSCTRL: Ch2 TA Display List dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); - else - osd_printf_verbose("SYSCTRL: Ch2 unknown dma %x from %08x to %08x (lmmode0=%d lmmode1=%d)\n", dc_sysctrl_regs[SB_C2DLEN], ddtdata.source-ddtdata.length, dc_sysctrl_regs[SB_C2DSTAT],dc_sysctrl_regs[SB_LMMODE0],dc_sysctrl_regs[SB_LMMODE1]); - #endif - - if ((!(address & 0x01000000))) - dc_sysctrl_regs[SB_C2DSTAT]=address; - else //direct texture path - dc_sysctrl_regs[SB_C2DSTAT]=address+ddtdata.length; - - /* TODO: timing is a guess */ - m_ch2_dma_irq_timer->adjust(m_maincpu->cycles_to_attotime(ddtdata.length/4)); - } - break; - - case SB_ISTNRM: - dc_sysctrl_regs[SB_ISTNRM] = old & ~(dat | 0xC0000000); // bits 31,30 ro - dc_update_interrupt_status(); - break; - - case SB_ISTEXT: - dc_sysctrl_regs[SB_ISTEXT] = old; - dc_update_interrupt_status(); - break; - - case SB_ISTERR: - dc_sysctrl_regs[SB_ISTERR] = old & ~dat; - dc_update_interrupt_status(); - break; - case SB_SDST: - if(dat & 1) - { - // TODO: Sort-DMA routine goes here - printf("Sort-DMA irq\n"); - - dc_sysctrl_regs[SB_SDST] = 0; - dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_SORT; - dc_update_interrupt_status(); - } - break; - } - - #if DEBUG_SYSCTRL - if ((reg != 0x40) && (reg != 0x42) && (reg > 2)) // filter out IRQ acks and ch2 dma - { - osd_printf_verbose("SYSCTRL: write %x to %x (reg %x), mask %x\n", data>>shift, offset, reg, /*sysctrl_names[reg],*/ mem_mask); - } - #endif -} - -uint64_t dc_state::dc_gdrom_r(offs_t offset, uint64_t mem_mask) -{ - uint32_t off; - - if ((int)~mem_mask & 1) - { - off=(offset << 1) | 1; - } - else - { - off=offset << 1; - } - - if (off*4 == 0x4c) - return -1; - if (off*4 == 8) - return 0; - - return 0; -} - -void dc_state::dc_gdrom_w(offs_t offset, uint64_t data, uint64_t mem_mask) -{ - uint32_t dat,off; - - if ((int)~mem_mask & 1) - { - dat=(uint32_t)(data >> 32); - off=(offset << 1) | 1; - } - else - { - dat=(uint32_t)data; - off=offset << 1; - } - - osd_printf_verbose("GDROM: [%08x=%x]write %x to %x, mask %x\n", 0x5f7000+off*4, dat, data, offset, mem_mask); -} - -int dc_state::decode_reg_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift) -{ - int reg = offset * 2; - - *shift = 0; - - // non 32-bit accesses have not yet been seen here, we need to know when they are - if ((mem_mask != 0xffffffff00000000U) && (mem_mask != 0x00000000ffffffffU)) - { - /*assume to return the lower 32-bits ONLY*/ - return reg & 0xffffffff; - } - - if (mem_mask == 0xffffffff00000000U) - { - reg++; - *shift = 32; - } - - return reg; -} - -uint64_t dc_state::dc_modem_r(offs_t offset, uint64_t mem_mask) -{ - int reg; - uint64_t shift; - - reg = decode_reg32_64(offset, mem_mask, &shift); - - // from ElSemi: this makes Atomiswave do it's "verbose boot" with a Sammy logo and diagnostics instead of just running the cart. - // our PVR emulation is apparently not good enough for that to work yet though. - if (reg == 0x280/4) - { - return 0xffffffffffffffffU; - } - - osd_printf_verbose("MODEM: Unmapped read %08x\n", 0x600000+reg*4); - return 0; -} - -void dc_state::dc_modem_w(offs_t offset, uint64_t data, uint64_t mem_mask) -{ - int reg; - uint64_t shift; - uint32_t dat; - - reg = decode_reg32_64(offset, mem_mask, &shift); - dat = (uint32_t)(data >> shift); - osd_printf_verbose("MODEM: [%08x=%x] write %x to %x, mask %x\n", 0x600000+reg*4, dat, data, offset, mem_mask); -} - -void dc_state::machine_start() -{ - // dccons doesn't have a specific g1 device yet - if(m_naomig1) - m_naomig1->set_dma_cb(naomi_g1_device::dma_cb(&dc_state::generic_dma, this)); - - m_maincpu->sh2drc_set_options(SH2DRC_STRICT_VERIFY | SH2DRC_STRICT_PCREL); - // TODO: repeated in dccons.cpp init_dc (NAOMI also uses double RAM) - m_maincpu->sh2drc_add_fastram(0x0c000000, 0x0cffffff, false, dc_ram); - - // save states - save_pointer(NAME(dc_sysctrl_regs), 0x200/4); - - m_ch2_dma_irq_timer = timer_alloc(FUNC(dc_state::ch2_dma_irq), this); -} - -void dc_state::machine_reset() -{ - /* halt the ARM7 */ - m_armrst = 1; - m_soundcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - - memset(dc_sysctrl_regs, 0, sizeof(dc_sysctrl_regs)); - - dc_sysctrl_regs[SB_SBREV] = 0x0b; - - m_ch2_dma_irq_timer->adjust(attotime::never); -} - -uint32_t dc_state::dc_aica_reg_r(offs_t offset, uint32_t mem_mask) -{ -// osd_printf_verbose("AICA REG: [%08x] read %x, mask %x\n", 0x700000+reg*4, (uint64_t)offset, mem_mask); - - if(offset == 0x2c00/4) - return m_armrst; - - return m_aica->read(offset*2); -} - -void dc_state::dc_aica_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - if (offset == (0x2c00/4)) - { - if(ACCESSING_BITS_0_7) - { - m_armrst = data & 1; - - if (data & 1) - { - /* halt the ARM7 */ - m_soundcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - } - else - { - /* it's alive ! */ - m_soundcpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - } - } - } - - m_aica->write(offset*2, data, 0xffff); - -// osd_printf_verbose("AICA REG: [%08x=%x] write %x to %x, mask %x\n", 0x700000+reg*4, data, offset, mem_mask); -} - -uint32_t dc_state::dc_arm_aica_r(offs_t offset) -{ - return m_aica->read(offset*2) & 0xffff; -} - -void dc_state::dc_arm_aica_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - m_aica->write(offset*2, data, mem_mask&0xffff); -} - -uint16_t dc_state::soundram_r(offs_t offset) -{ - return dc_sound_ram[offset]; -} - -void dc_state::soundram_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - COMBINE_DATA(&dc_sound_ram[offset]); -} - -WRITE_LINE_MEMBER(dc_state::aica_irq) -{ - m_soundcpu->set_input_line(ARM7_FIRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); -} - -WRITE_LINE_MEMBER(dc_state::sh4_aica_irq) -{ - if(state) - dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_AICA; - else - dc_sysctrl_regs[SB_ISTEXT] &= ~IST_EXT_AICA; - - dc_update_interrupt_status(); -} - -WRITE_LINE_MEMBER(dc_state::external_irq) -{ - if (state) - dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_EXTERNAL; - else - dc_sysctrl_regs[SB_ISTEXT] &= ~IST_EXT_EXTERNAL; - - dc_update_interrupt_status(); -} - -MACHINE_RESET_MEMBER(dc_state,dc_console) -{ - dc_state::machine_reset(); - m_maincpu->sh2drc_set_options(SH2DRC_STRICT_VERIFY | SH2DRC_STRICT_PCREL); -} - -TIMER_DEVICE_CALLBACK_MEMBER(dc_state::dc_scanline) -{ - m_powervr2->pvr_scanline_timer(param); -} - -void dc_state::system_bus_config(machine_config &config, const char *cpu_tag) -{ - DC_G2IF(config, m_g2if, XTAL(25'000'000)); - m_g2if->set_host_space(cpu_tag, AS_PROGRAM); - m_g2if->int_cb().set(FUNC(dc_state::g2_dma_end_w)); - m_g2if->error_ia_cb().set(FUNC(dc_state::g2_dma_error_ia_w)); - m_g2if->error_ov_cb().set(FUNC(dc_state::g2_dma_error_ov_w)); -} diff --git a/src/mame/shared/dc.h b/src/mame/shared/dc.h deleted file mode 100644 index cf2eb344f42..00000000000 --- a/src/mame/shared/dc.h +++ /dev/null @@ -1,287 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Angelo Salese, Olivier Galibert, David Haywood, Samuele Zannoli, R. Belmont, ElSemi - -#ifndef MAME_INCLUDES_DC_H -#define MAME_INCLUDES_DC_H - -#pragma once - -#include "dc_g2if.h" -#include "maple-dc.h" -#include "naomig1.h" -#include "powervr2.h" - -#include "cpu/arm7/arm7.h" -#include "cpu/arm7/arm7core.h" -#include "cpu/sh/sh4.h" -#include "machine/timer.h" -#include "sound/aica.h" - -class dc_state : public driver_device -{ -public: - dc_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , dc_framebuffer_ram(*this, "frameram") - , dc_texture_ram(*this, "dc_texture_ram") - , dc_sound_ram(*this, "dc_sound_ram") - , dc_ram(*this, "dc_ram") - , m_maincpu(*this, "maincpu") - , m_soundcpu(*this, "soundcpu") - , m_powervr2(*this, "powervr2") - , m_maple(*this, "maple_dc") - , m_naomig1(*this, "rom_board") - , m_g2if(*this, "sb_g2if") - , m_aica(*this, "aica") - { } - - required_shared_ptr dc_framebuffer_ram; // '32-bit access area' - required_shared_ptr dc_texture_ram; // '64-bit access area' - - required_shared_ptr dc_sound_ram; - required_shared_ptr dc_ram; - - /* machine related */ - uint32_t dc_sysctrl_regs[0x200/4]{}; - uint8_t m_armrst = 0U; - emu_timer *m_ch2_dma_irq_timer = nullptr; - - virtual void machine_start() override; - virtual void machine_reset() override; - void g2_dma_end_w(offs_t channel, u8 state); - void g2_dma_error_ia_w(offs_t channel, u8 state); - void g2_dma_error_ov_w(offs_t channel, u8 state); - TIMER_CALLBACK_MEMBER(ch2_dma_irq); - uint32_t dc_aica_reg_r(offs_t offset, uint32_t mem_mask = ~0); - void dc_aica_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t dc_arm_aica_r(offs_t offset); - void dc_arm_aica_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - inline int decode_reg32_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift); - inline int decode_reg3216_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift); - int dc_compute_interrupt_level(); - void dc_update_interrupt_status(); - inline int decode_reg_64(uint32_t offset, uint64_t mem_mask, uint64_t *shift); - uint64_t dc_sysctrl_r(offs_t offset, uint64_t mem_mask = ~0); - void dc_sysctrl_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); - uint64_t dc_gdrom_r(offs_t offset, uint64_t mem_mask = ~0); - void dc_gdrom_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); - uint64_t dc_modem_r(offs_t offset, uint64_t mem_mask = ~0); - void dc_modem_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); - void g1_irq(uint8_t data); - void pvr_irq(uint8_t data); - void maple_irq(uint8_t data); - uint16_t soundram_r(offs_t offset); - void soundram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - DECLARE_WRITE_LINE_MEMBER(aica_irq); - DECLARE_WRITE_LINE_MEMBER(sh4_aica_irq); - DECLARE_WRITE_LINE_MEMBER(external_irq); - - - required_device m_maincpu; - required_device m_soundcpu; - required_device m_powervr2; - required_device m_maple; - optional_device m_naomig1; - required_device m_g2if; - required_device m_aica; - - void generic_dma(uint32_t main_adr, void *dma_ptr, uint32_t length, uint32_t size, bool to_mainram); - TIMER_DEVICE_CALLBACK_MEMBER(dc_scanline); - DECLARE_MACHINE_RESET(dc_console); - - void naomi_aw_base(machine_config &config); - void aica_map(address_map &map); - void dc_audio_map(address_map &map); - -protected: - void system_bus_config(machine_config &config, const char *cpu_tag); -}; - -/*--------- Ch2-DMA Control Registers ----------*/ -#define SB_C2DSTAT ((0x005f6800-0x005f6800)/4) -#define SB_C2DLEN ((0x005f6804-0x005f6800)/4) -#define SB_C2DST ((0x005f6808-0x005f6800)/4) -/*-------- Sort-DMA Control Registers ----------*/ -#define SB_SDSTAW ((0x005f6810-0x005f6800)/4) -#define SB_SDBAAW ((0x005f6814-0x005f6800)/4) -#define SB_SDWLT ((0x005f6818-0x005f6800)/4) -#define SB_SDLAS ((0x005f681c-0x005f6800)/4) -#define SB_SDST ((0x005f6820-0x005f6800)/4) -/*-- DDT I/F Block & System Control Registers --*/ -#define SB_DBREQM ((0x005f6840-0x005f6800)/4) -#define SB_BAVLWC ((0x005f6844-0x005f6800)/4) -#define SB_C2DPRYC ((0x005f6848-0x005f6800)/4) -#define SB_C2DMAXL ((0x005f684c-0x005f6800)/4) -#define SB_TFREM ((0x005f6880-0x005f6800)/4) -#define SB_LMMODE0 ((0x005f6884-0x005f6800)/4) -#define SB_LMMODE1 ((0x005f6888-0x005f6800)/4) -#define SB_FFST ((0x005f688c-0x005f6800)/4) -#define SB_SFRES ((0x005f6890-0x005f6800)/4) -#define SB_SBREV ((0x005f689c-0x005f6800)/4) -#define SB_RBSPLT ((0x005f68a0-0x005f6800)/4) -/*-------- Interrupt Control Registers ---------*/ -#define SB_ISTNRM ((0x005f6900-0x005f6800)/4) -#define SB_ISTEXT ((0x005f6904-0x005f6800)/4) -#define SB_ISTERR ((0x005f6908-0x005f6800)/4) -#define SB_IML2NRM ((0x005f6910-0x005f6800)/4) -#define SB_IML2EXT ((0x005f6914-0x005f6800)/4) -#define SB_IML2ERR ((0x005f6918-0x005f6800)/4) -#define SB_IML4NRM ((0x005f6920-0x005f6800)/4) -#define SB_IML4EXT ((0x005f6924-0x005f6800)/4) -#define SB_IML4ERR ((0x005f6928-0x005f6800)/4) -#define SB_IML6NRM ((0x005f6930-0x005f6800)/4) -#define SB_IML6EXT ((0x005f6934-0x005f6800)/4) -#define SB_IML6ERR ((0x005f6938-0x005f6800)/4) -#define SB_PDTNRM ((0x005f6940-0x005f6800)/4) -#define SB_PDTEXT ((0x005f6944-0x005f6800)/4) -#define SB_G2DTNRM ((0x005f6950-0x005f6800)/4) -#define SB_G2DTEXT ((0x005f6954-0x005f6800)/4) - - -/*-------- Maple-DMA Control Registers ---------*/ -#define SB_MDSTAR ((0x005f6c04-0x005f6c00)/4) -#define SB_MDTSEL ((0x005f6c10-0x005f6c00)/4) -#define SB_MDEN ((0x005f6c14-0x005f6c00)/4) -#define SB_MDST ((0x005f6c18-0x005f6c00)/4) -/*---- Maple I/F Block HW Control Registers ----*/ -#define SB_MSYS ((0x005f6c80-0x005f6c00)/4) -#define SB_MST ((0x005f6c84-0x005f6c00)/4) -#define SB_MSHTCL ((0x005f6c88-0x005f6c00)/4) -#define SB_MDAPRO ((0x005f6c8c-0x005f6c00)/4) -#define SB_MMSEL ((0x005f6ce8-0x005f6c00)/4) -/*-------- Maple-DMA Debug Registers -----------*/ -#define SB_MTXDAD ((0x005f6cf4-0x005f6c00)/4) -#define SB_MRXDAD ((0x005f6cf8-0x005f6c00)/4) -#define SB_MRXDBD ((0x005f6cfc-0x005f6c00)/4) - -/*--------- GD-DMA Control Registers -----------*/ -#define SB_GDSTAR ((0x005f7404-0x005f7400)/4) -#define SB_GDLEN ((0x005f7408-0x005f7400)/4) -#define SB_GDDIR ((0x005f740c-0x005f7400)/4) -#define SB_GDEN ((0x005f7414-0x005f7400)/4) -#define SB_GDST ((0x005f7418-0x005f7400)/4) -/*----- G1 I/F Block HW Control Registers ------*/ -#define SB_G1RRC ((0x005f7480-0x005f7400)/4) -#define SB_G1RWC ((0x005f7484-0x005f7400)/4) -#define SB_G1FRC ((0x005f7488-0x005f7400)/4) -#define SB_G1FWC ((0x005f748c-0x005f7400)/4) -#define SB_G1CRC ((0x005f7490-0x005f7400)/4) -#define SB_G1CWC ((0x005f7494-0x005f7400)/4) -#define SB_G1GDRC ((0x005f74a0-0x005f7400)/4) -#define SB_G1GDWC ((0x005f74a4-0x005f7400)/4) -#define SB_G1SYSM ((0x005f74b0-0x005f7400)/4) -#define SB_G1CRDYC ((0x005f74b4-0x005f7400)/4) -#define SB_GDAPRO ((0x005f74b8-0x005f7400)/4) - -/*-------- BIOS security Registers ---------*/ -#define SB_SECUR_EADR ((0x005f74e4-0x005f7400)/4) -#define SB_SECUR_STATE ((0x005f74ec-0x005f7400)/4) -/*---------- GD-DMA Debug Registers ------------*/ -#define SB_GDSTARD ((0x005f74f4-0x005f7400)/4) -#define SB_GDLEND ((0x005f74f8-0x005f7400)/4) - -/*-------- Wave DMA Control Registers ----------*/ -#define SB_ADSTAG ((0x005f7800-0x005f7800)/4) -#define SB_ADSTAR ((0x005f7804-0x005f7800)/4) -#define SB_ADLEN ((0x005f7808-0x005f7800)/4) -#define SB_ADDIR ((0x005f780c-0x005f7800)/4) -#define SB_ADTSEL ((0x005f7810-0x005f7800)/4) -#define SB_ADTRG SB_ADTSEL -#define SB_ADEN ((0x005f7814-0x005f7800)/4) -#define SB_ADST ((0x005f7818-0x005f7800)/4) -#define SB_ADSUSP ((0x005f781c-0x005f7800)/4) - -/*----- External 1 DMA Control Registers -------*/ -#define SB_E1STAG ((0x005f7820-0x005f7800)/4) -#define SB_E1STAR ((0x005f7824-0x005f7800)/4) -#define SB_E1LEN ((0x005f7828-0x005f7800)/4) -#define SB_E1DIR ((0x005f782c-0x005f7800)/4) -#define SB_E1TSEL ((0x005f7830-0x005f7800)/4) -#define SB_E1TRG SB_E1TSEL -#define SB_E1EN ((0x005f7834-0x005f7800)/4) -#define SB_E1ST ((0x005f7838-0x005f7800)/4) -#define SB_E1SUSP ((0x005f783c-0x005f7800)/4) - -/*----- External 2 DMA Control Registers -------*/ -#define SB_E2STAG ((0x005f7840-0x005f7800)/4) -#define SB_E2STAR ((0x005f7844-0x005f7800)/4) -#define SB_E2LEN ((0x005f7848-0x005f7800)/4) -#define SB_E2DIR ((0x005f784c-0x005f7800)/4) -#define SB_E2TSEL ((0x005f7850-0x005f7800)/4) -#define SB_E2TRG SB_E2TSEL -#define SB_E2EN ((0x005f7854-0x005f7800)/4) -#define SB_E2ST ((0x005f7858-0x005f7800)/4) -#define SB_E2SUSP ((0x005f785c-0x005f7800)/4) - -/*------- Debug DMA Control Registers ----------*/ -#define SB_DDSTAG ((0x005f7860-0x005f7800)/4) -#define SB_DDSTAR ((0x005f7864-0x005f7800)/4) -#define SB_DDLEN ((0x005f7868-0x005f7800)/4) -#define SB_DDDIR ((0x005f786c-0x005f7800)/4) -#define SB_DDTSEL ((0x005f7870-0x005f7800)/4) -#define SB_DDTRG SB_DDTSEL -#define SB_DDEN ((0x005f7874-0x005f7800)/4) -#define SB_DDST ((0x005f7878-0x005f7800)/4) -#define SB_DDSUSP ((0x005f787c-0x005f7800)/4) -/*----- G2 I/F Block HW Control Registers ------*/ -#define SB_G2ID ((0x005f7880-0x005f7800)/4) -#define SB_G2DSTO ((0x005f7890-0x005f7800)/4) -#define SB_G2TRTO ((0x005f7894-0x005f7800)/4) -#define SB_G2MDMTO ((0x005f7898-0x005f7800)/4) -#define SB_G2MDMW ((0x005f789c-0x005f7800)/4) -#define SB_G2APRO ((0x005f78bc-0x005f7800)/4) - -/*---------- G2 DMA Debug Registers ------------*/ -#define SB_ADSTAGD ((0x005f78c0-0x005f7800)/4) -#define SB_ADSTARD ((0x005f78c4-0x005f7800)/4) -#define SB_ADLEND ((0x005f78c8-0x005f7800)/4) -#define SB_E1STAGD ((0x005f78d0-0x005f7800)/4) -#define SB_E1STARD ((0x005f78d4-0x005f7800)/4) -#define SB_E1LEND ((0x005f78d8-0x005f7800)/4) -#define SB_E2STAGD ((0x005f78e0-0x005f7800)/4) -#define SB_E2STARD ((0x005f78e4-0x005f7800)/4) -#define SB_E2LEND ((0x005f78e8-0x005f7800)/4) -#define SB_DDSTAGD ((0x005f78f0-0x005f7800)/4) -#define SB_DDSTARD ((0x005f78f4-0x005f7800)/4) -#define SB_DDLEND ((0x005f78f8-0x005f7800)/4) - -#define RTC1 ((0x00710000-0x00710000)/4) -#define RTC2 ((0x00710004-0x00710000)/4) -#define RTC3 ((0x00710008-0x00710000)/4) - - -/* ------------- normal interrupts ------------- */ -#define IST_EOR_VIDEO 0x00000001 -#define IST_EOR_ISP 0x00000002 -#define IST_EOR_TSP 0x00000004 -#define IST_VBL_IN 0x00000008 -#define IST_VBL_OUT 0x00000010 -#define IST_HBL_IN 0x00000020 -#define IST_EOXFER_YUV 0x00000040 -#define IST_EOXFER_OPLST 0x00000080 -#define IST_EOXFER_OPMV 0x00000100 -#define IST_EOXFER_TRLST 0x00000200 -#define IST_EOXFER_TRMV 0x00000400 -#define IST_DMA_PVR 0x00000800 -#define IST_DMA_MAPLE 0x00001000 -#define IST_DMA_MAPLEVB 0x00002000 -#define IST_DMA_GDROM 0x00004000 -#define IST_DMA_AICA 0x00008000 -#define IST_DMA_EXT1 0x00010000 -#define IST_DMA_EXT2 0x00020000 -#define IST_DMA_DEV 0x00040000 -#define IST_DMA_CH2 0x00080000 -#define IST_DMA_SORT 0x00100000 -#define IST_EOXFER_PTLST 0x00200000 -#define IST_G1G2EXTSTAT 0x40000000 -#define IST_ERROR 0x80000000 -/* ------------ external interrupts ------------ */ -#define IST_EXT_EXTERNAL 0x00000008 -#define IST_EXT_MODEM 0x00000004 -#define IST_EXT_AICA 0x00000002 -#define IST_EXT_GDROM 0x00000001 -/* -------------- error interrupts ------------- */ -#define IST_ERR_ISP_LIMIT 0x00000004 -#define IST_ERR_PVRIF_ILL_ADDR 0x00000040 - -#endif // MAME_INCLUDES_DC_H diff --git a/src/mame/shared/dc_g2if.cpp b/src/mame/shared/dc_g2if.cpp deleted file mode 100644 index 9929a2844fc..00000000000 --- a/src/mame/shared/dc_g2if.cpp +++ /dev/null @@ -1,538 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Angelo Salese -/************************************************************************************************** - - Sega Dreamcast G2 System Bus I/F - - TODO: - - Single-step instead of transfering in one go; - - Abort DMA if suspend mode is triggered; - - Time Out mechanism thru DS# & TR# signals; - - External pin enable in trigger select; - - Create a pure abstract interface shared with PVR-DMA I/F - (one channel, different max size, simpler tsel, no suspend, - different security code & area protection); - - DMA starts should send DDT requests and being notified back to use this i/f implementation - anyway. Exact purpose is unknown, maybe it's for granting use of the bus? - -**************************************************************************************************/ - -#include "emu.h" -#include "dc_g2if.h" - -#define LOG_WARN (1U << 1) -#define LOG_DMA (1U << 2) // log DMA starts with CPU triggers (.tsel bit 1 == 0) -#define LOG_HWTRIG (1U << 3) // log DMA starts with HW triggers (.tsel bit 1 == 1) -#define LOG_DMAEND (1U << 4) // log DMA event ends -#define LOG_ILLEGAL (1U << 5) // log illegal/malformed addresses - -#define VERBOSE (LOG_WARN | LOG_DMA | LOG_HWTRIG | LOG_DMAEND | LOG_ILLEGAL) -//#define LOG_OUTPUT_STREAM std::cout -#include "logmacro.h" - -#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) -#define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__) -#define LOGHWTRIG(...) LOGMASKED(LOG_HWTRIG, __VA_ARGS__) -#define LOGDMAEND(...) LOGMASKED(LOG_DMAEND, __VA_ARGS__) -#define LOGILLEGAL(...) LOGMASKED(LOG_ILLEGAL, __VA_ARGS__) - -//************************************************************************** -// GLOBAL VARIABLES -//************************************************************************** - - -// device type definition -DEFINE_DEVICE_TYPE(DC_G2IF, dc_g2if_device, "dc_g2if", "Sega Dreamcast G2 I/F System Bus") - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - - -//------------------------------------------------- -// dc_g2if_device - constructor -//------------------------------------------------- - - -dc_g2if_device::dc_g2if_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, DC_G2IF, tag, owner, clock) - , m_host_space(*this, finder_base::DUMMY_TAG, -1) - , m_int_w(*this) - , m_error_ia_w(*this) - , m_error_ov_w(*this) -{ -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - - -void dc_g2if_device::device_start() -{ - for (int i = 0; i < 4; i++) - { - m_dma[i].end_timer = timer_alloc(FUNC(dc_g2if_device::dma_end_tick), this); - } - - m_int_w.resolve(); - m_error_ia_w.resolve(); - m_error_ov_w.resolve(); - - save_item(STRUCT_MEMBER(m_dma, g2_addr)); - save_item(STRUCT_MEMBER(m_dma, root_addr)); - save_item(STRUCT_MEMBER(m_dma, len)); - save_item(STRUCT_MEMBER(m_dma, size)); - save_item(STRUCT_MEMBER(m_dma, mode)); - save_item(STRUCT_MEMBER(m_dma, dir)); - save_item(STRUCT_MEMBER(m_dma, enable)); - save_item(STRUCT_MEMBER(m_dma, in_progress)); - save_item(STRUCT_MEMBER(m_dma, start)); - save_item(STRUCT_MEMBER(m_dma, tsel)); - save_item(STRUCT_MEMBER(m_dma, hw_trigger)); - save_item(NAME(m_g2apro.top_addr)); - save_item(NAME(m_g2apro.bottom_addr)); -} - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - - -void dc_g2if_device::device_reset() -{ - for (int ch = 0; ch < 4; ch ++) - { - m_dma[ch].g2_addr = 0; - m_dma[ch].root_addr = 0; - m_dma[ch].len = 0; - m_dma[ch].size = 0; - m_dma[ch].mode = false; - m_dma[ch].dir = false; - m_dma[ch].enable = false; - m_dma[ch].in_progress = false; - m_dma[ch].start = false; - m_dma[ch].tsel = 0; - m_dma[ch].hw_trigger = false; - m_dma[ch].end_timer->adjust(attotime::never); - } -} - -TIMER_CALLBACK_MEMBER(dc_g2if_device::dma_end_tick) -{ - u8 channel = (u8)(param >> 1); - bool dma_result = (param & 1); - m_dma[channel].in_progress = false; - m_dma[channel].start = false; - LOGDMAEND("DMA%d %s\n", channel, dma_result ? "normal end" : "overflow error"); - - if (dma_result) - m_int_w(channel, 1); - else - m_error_ov_w(channel, 1); -} - - -//************************************************************************** -// READ/WRITE HANDLERS -//************************************************************************** - -template void dc_g2if_device::channel_map(address_map &map) -{ - map(0x00, 0x03).rw(FUNC(dc_g2if_device::stag_r), FUNC(dc_g2if_device::stag_w)); - map(0x04, 0x07).rw(FUNC(dc_g2if_device::star_r), FUNC(dc_g2if_device::star_w)); - map(0x08, 0x0b).rw(FUNC(dc_g2if_device::len_r), FUNC(dc_g2if_device::len_w)); - map(0x0c, 0x0f).rw(FUNC(dc_g2if_device::dir_r), FUNC(dc_g2if_device::dir_w)); - map(0x10, 0x13).rw(FUNC(dc_g2if_device::tsel_r), FUNC(dc_g2if_device::tsel_w)); - map(0x14, 0x17).rw(FUNC(dc_g2if_device::en_r), FUNC(dc_g2if_device::en_w)); - map(0x18, 0x1b).rw(FUNC(dc_g2if_device::st_r), FUNC(dc_g2if_device::st_w)); - map(0x1c, 0x1f).rw(FUNC(dc_g2if_device::susp_r), FUNC(dc_g2if_device::susp_w)); -} - -// Instantiate channel maps -template void dc_g2if_device::channel_map<0>(address_map &map); -template void dc_g2if_device::channel_map<1>(address_map &map); -template void dc_g2if_device::channel_map<2>(address_map &map); -template void dc_g2if_device::channel_map<3>(address_map &map); - -void dc_g2if_device::amap(address_map &map) -{ - // 0x5f7800-ff - // SB_AD* - map(0x00, 0x1f).m(FUNC(dc_g2if_device::channel_map<0>)); - // SB_E1* - map(0x20, 0x3f).m(FUNC(dc_g2if_device::channel_map<1>)); - // SB_E2* - map(0x40, 0x5f).m(FUNC(dc_g2if_device::channel_map<2>)); - // SB_DD* - map(0x60, 0x7f).m(FUNC(dc_g2if_device::channel_map<3>)); - - map(0x80, 0x83).r(FUNC(dc_g2if_device::g2id_r)); - -// map(0x90, 0x93).rw SB_G2DSTO #DS timeout -// map(0x94, 0x97).rw SB_G2TRTO #TR timeout -// map(0x98, 0x9b).rw SB_G2MDMTO modem wait timeout -// map(0x9c, 0x9f).rw SB_G2MDMW modem wait time - - map(0xbc, 0xbf).w(FUNC(dc_g2if_device::g2apro_w)); - -// map(0xc0, 0xcb).r SB_AD*D live register reads (STAG, STAR, LEN) -// map(0xd0, 0xdb).r SB_E1*D live register reads -// map(0xe0, 0xeb).r SB_E2*D live register reads -// map(0xf0, 0xfb).r SB_DD*D live register reads -} - -template u32 dc_g2if_device::stag_r() -{ - return m_dma[Channel].g2_addr; -} - -// SB_**STAG -// G2 bus start address -template void dc_g2if_device::stag_w(offs_t offset, u32 data, u32 mem_mask) -{ - COMBINE_DATA(&m_dma[Channel].g2_addr); - - if (!g2_address_check(m_dma[Channel].g2_addr)) - { - LOGILLEGAL("%s: G2 illegal Address trap %08x (%08x)\n", machine().describe_context(), data, mem_mask); - m_error_ia_w(Channel, 1); - } -} - -template u32 dc_g2if_device::star_r() -{ - return m_dma[Channel].root_addr; -} - -// SB_**STAR -// root bus (SH4) start address -template void dc_g2if_device::star_w(offs_t offset, u32 data, u32 mem_mask) -{ - COMBINE_DATA(&m_dma[Channel].root_addr); - - if (!root_address_check(m_dma[Channel].root_addr)) - { - LOGILLEGAL("%s: root illegal Address trap %08x (%08x)\n", machine().describe_context(), data, mem_mask); - m_error_ia_w(Channel, 1); - } -} - -template u32 dc_g2if_device::len_r() -{ - return m_dma[Channel].len; -} - -/* - * SB_**LEN - * x--- ---- ---- ---- ---- ---- ---- ---- DMA transfer mode - * (0) Restart - * (1) End (enable register clears to '0') - * ---- ---x xxxx xxxx xxxx xxxx xxx- ---- DMA transfer length - * (all buses?) - */ -template void dc_g2if_device::len_w(offs_t offset, u32 data, u32 mem_mask) -{ - COMBINE_DATA(&m_dma[Channel].len); - // log an attempt if any of the reserved bits 30-25 and 4-0 are set - if (m_dma[Channel].len & 0x7fe0001f) - LOGWARN("%s: DMA%d LEN setup %08x (mask=%08x)!\n", machine().describe_context(), data, mem_mask); -// m_dma[Channel].size = m_dma[Channel].len & 0x7fffffff; - m_dma[Channel].size = m_dma[Channel].len & 0x001fffe0; - m_dma[Channel].mode = bool(BIT(m_dma[Channel].len, 31)); -} - -// TODO: following regs are supposedly single byte, but HW still accesses them as dword, is it a liability? - -template u32 dc_g2if_device::dir_r() -{ - return m_dma[Channel].dir; -} - -/* - * SB_**DIR (transfer direction) - * ---x (0) root -> G2 device RAM - * (1) root <- G2 device RAM - */ -template void dc_g2if_device::dir_w(offs_t offset, u32 data, u32 mem_mask) -{ - if (ACCESSING_BITS_0_7) - m_dma[Channel].dir = bool(BIT(data, 0)); -} - -template u32 dc_g2if_device::tsel_r() -{ - return m_dma[Channel].tsel; -} - -/* - * SB_**TSEL (trigger select) - * -x-- SUSPend enable - * --x- (0) CPU trigger (along with st_w '1'), - * (1) HW trigger (with external pin/irq mechanism) - * ---x External pin enable - */ -template void dc_g2if_device::tsel_w(offs_t offset, u32 data, u32 mem_mask) -{ - if (ACCESSING_BITS_0_7) - { - m_dma[Channel].tsel = data & 7; - m_dma[Channel].hw_trigger = bool(BIT(m_dma[Channel].tsel, 1)); - } -} - - -template u32 dc_g2if_device::en_r() -{ - return m_dma[Channel].enable; -} - -/* - * SB_**EN - * ---x DMA enable - * (0) mask - * (1) enabled - * Note: DMA transfer is aborted if this is written with a 0. - */ -template void dc_g2if_device::en_w(offs_t offset, u32 data, u32 mem_mask) -{ - if (ACCESSING_BITS_0_7) - { - m_dma[Channel].enable = bool(BIT(data, 0)); - // TODO: suppresses an in-progress DMA if this is disabled - } -} - -template u32 dc_g2if_device::st_r() -{ - return m_dma[Channel].in_progress & 1; -} - -/* - * SB_**ST - * ---x DMA start/status - * (r) (0) DMA isn't running (1) DMA is in-progress - * (w) (1) starts a DMA (if hw_trigger is '0') - */ -template void dc_g2if_device::st_w(offs_t offset, u32 data, u32 mem_mask) -{ - if (ACCESSING_BITS_0_7) - { - if (m_dma[Channel].start == true) - { - LOGWARN("%s: DMA%d attempt to start an in-flight\n", machine().describe_context(), Channel); - return; - } - - m_dma[Channel].start = bool(BIT(data, 0)); - - if (m_dma[Channel].enable && m_dma[Channel].start && m_dma[Channel].hw_trigger == false) - { - LOGDMA("%s: DMA%d root=%08x g2=%08x dir=G2%sroot (%d)\n size=%08x (len=%08x) mode=DMA %s\n", - machine().describe_context(), Channel, - m_dma[Channel].root_addr, m_dma[Channel].g2_addr, m_dma[Channel].dir ? "->" : "<-", - m_dma[Channel].dir, - m_dma[Channel].size, m_dma[Channel].len, m_dma[Channel].mode ? "end" : "restart" - ); - dma_execute(Channel); - } - } -} - -// --x- ---- (r/o) DMA request input state (from external bus?) -// ---x ---- (r/o) DMA suspend/stop status (active low) -// ---- ---x (w) DMA suspend request -template u32 dc_g2if_device::susp_r() -{ - return (m_dma[Channel].in_progress == false) << 4; -} - -template void dc_g2if_device::susp_w(offs_t offset, u32 data, u32 mem_mask) -{ - if (ACCESSING_BITS_0_7) - { - // TODO: unemulated suspend mode - if (data & 1) - { - LOGWARN("%s: DMA%d suspend write %08x %08x\n", - machine().describe_context(), - Channel, data, mem_mask - ); - // ... - } - } -} - -//************************************************************************** -// Misc. registers -//************************************************************************** - -// SB_G2ID -// 0001 ---- Holly v1.0 -// ---- 0011 G2 version -u32 dc_g2if_device::g2id_r() -{ - LOGWARN("%s: read ID\n", machine().describe_context()); - return 0x12; -} - -// SB_G2APRO -// xxxx xxxx xxxx xxxx ---- ---- ---- ---- Unlock register (must be == 0x4659) -// ---- ---- ---- ---- -xxx xxxx ---- ---- Top range (start address) -// ---- ---- ---- ---- ---- ---- -xxx xxxx Bottom range (end address) -// all channels follows this ruleset -void dc_g2if_device::g2apro_w(offs_t offset, u32 data, u32 mem_mask) -{ - if (mem_mask != 0xffffffff) - { - LOGWARN("%s: g2apro_w attempt to write %08x with a non-dword (mem_mask=%08x)\n", machine().describe_context(), data, mem_mask); - return; - } - const u16 security_code = data >> 16; - - if (security_code != 0x4659) - { - LOGWARN("%s: g2apro_w attempt to write %08x without satisfying security code condition\n", machine().describe_context(), data); - return; - } - - const u16 top_range = (data & 0x7f00) >> 8; - const u16 bottom_range = (data & 0x7f); - - m_g2apro.top_addr = (top_range << 20) | 0x08000000; - m_g2apro.bottom_addr = (bottom_range << 20) | 0x080fffff; - - LOGILLEGAL("%s: g2apro_w set top=%08x bottom=%08x (%08x)\n", - machine().describe_context(), - m_g2apro.top_addr, m_g2apro.bottom_addr, data - ); -} - -//************************************************************************** -// DMA implementation -//************************************************************************** - -inline bool dc_g2if_device::root_address_check(u32 offset) -{ - const u8 area = (offset >> 26) & 7; - // root iA is generated by accessing outside System RAM or texture/framebuffer RAM - return area == 1 || area == 3; -} - -inline bool dc_g2if_device::g2_address_check(u32 offset) -{ - const u8 area = (offset >> 26) & 7; - // g2 iA is generated by accessing outside: - // - area == 0 for AD/E1/E2 buses - // - area == 5 for DD - return area == 0 || area == 5; -} - -inline bool dc_g2if_device::root_overflow_check(u32 offset, u8 channel) -{ - bool result = offset >= m_g2apro.top_addr && offset <= m_g2apro.bottom_addr; - if (result == false) - LOGILLEGAL("DMA%d overflow abort root=%08x\n", channel, offset); - - return result; -} - -void dc_g2if_device::dma_execute(u8 channel) -{ - u32 src, dst, index, transfer_size; - dst = m_dma[channel].g2_addr; - src = m_dma[channel].root_addr; - - // Punt if attempts to go beyond the allocated buses - // TODO: should require two extra cycles for fetching addresses first - if (!root_address_check(src) || !g2_address_check(dst)) - { - LOGILLEGAL("%s: DMA%d illegal address attempt root=%08x g2=%08x\n", - machine().describe_context(), - channel, src, dst - ); - m_dma[channel].in_progress = false; - m_dma[channel].start = false; - m_dma[channel].enable = false; - m_error_ia_w(channel, 1); - return; - } - - index = 0; - - transfer_size = m_dma[channel].size; - /* 0 rounding size = 32 Mbytes */ - if (transfer_size == 0) { transfer_size = 0x200000; } - - if (m_dma[channel].dir == 1) - std::swap(src, dst); - - // notify that a DMA is in progress - // ofc this should rather transfer one word at a time, - // we currently don't do that for performance reasons ... - m_dma[channel].in_progress = true; - - bool dma_result = true; - - for (; index < transfer_size; index += 2) - { - // assert that root address is inside the g2apro range - if (!root_overflow_check(m_dma[channel].dir ? dst : src, channel)) - { - dma_result = false; - break; - } - // TODO: raise debug signals if SB_G2DSTO / SB_G2TRTO aren't respected - // Shouldn't matter for AICA RAM, - // it does in loopchk g2 test 0304 when it tries to write to - // expansion bus (where nothing lies on stock DC) - m_host_space->write_word(dst, m_host_space->read_word(src)); - src += 2; - dst += 2; - } - - // update the params - // Note: if you trigger an instant DMA IRQ trigger, sfz3ugd doesn't play any BGM. - // G2 bus is 16 bits @ 25 MHz according to Fig. 2-1 - // TODO: reported limit output for AICA DMA is set at 11.3MB/s while the others at 24.0/26.0 - // bus contention ftw ... - const attotime dma_time = attotime::from_ticks(index / 2, clock()); - - m_dma[channel].g2_addr = dst; - m_dma[channel].root_addr = src; - // TODO: how len copes with updates? - m_dma[channel].len = 0; - // clear mask flag if the DMA transfer mode is in End mode - // (Restart mode leaves this set to true) - if (m_dma[channel].mode == true) - m_dma[channel].enable = false; - - m_dma[channel].end_timer->adjust(dma_time, (channel << 1) | (dma_result ? 1 : 0)); -} - -/* - * normal_ist: SB_G2DTNRM & SB_ISTNRM - * (triggers a DMA if selected irq in former gets triggered) - * ext_ist: SB_G2DTEXT & SB_ISTEXT - * (triggers a DMA if external pin is triggered) - */ -void dc_g2if_device::hw_irq_trigger_hs(u32 normal_ist, u32 ext_ist) -{ - // TODO: is latter requiring .tsel bit 0 == 1? - bool hw_ist_enable = normal_ist || ext_ist; - - if (hw_ist_enable == false) - return; - - for (int ch = 0; ch < 4; ch++) - { - if (m_dma[ch].hw_trigger & m_dma[ch].enable) - { - LOGHWTRIG("HW trigger channel %d (ISTNRM=%08x ISTEXT=%08x)\n", ch, normal_ist, ext_ist); - dma_execute(ch); - } - } -} diff --git a/src/mame/shared/dc_g2if.h b/src/mame/shared/dc_g2if.h deleted file mode 100644 index c598307b441..00000000000 --- a/src/mame/shared/dc_g2if.h +++ /dev/null @@ -1,106 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Angelo Salese -/************************************************************************************************** - - Sega Dreamcast G2 System Bus I/F - -**************************************************************************************************/ - -#ifndef MAME_MACHINE_DC_G2IF_H -#define MAME_MACHINE_DC_G2IF_H - -#pragma once - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -class dc_g2if_device : public device_t -{ -public: - // construction/destruction - dc_g2if_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - template void set_host_space(T &&tag, int index) { m_host_space.set_tag(std::forward(tag), index); } - auto int_cb() { return m_int_w.bind(); } - auto error_ia_cb() { return m_error_ia_w.bind(); } - auto error_ov_cb() { return m_error_ov_w.bind(); } - - void amap(address_map &map); - - void hw_irq_trigger_hs(u32 normal_ist, u32 ext_ist); - -protected: - // device-level overrides - //virtual void device_validity_check(validity_checker &valid) const override; - //virtual void device_add_mconfig(machine_config &config) override; - virtual void device_start() override; - virtual void device_reset() override; - - TIMER_CALLBACK_MEMBER(dma_end_tick); - -private: - required_address_space m_host_space; - devcb_write8 m_int_w; - devcb_write8 m_error_ia_w; - devcb_write8 m_error_ov_w; - - struct { - u32 g2_addr; - u32 root_addr; - u32 len; - u32 size; - bool mode; - bool dir; - bool enable; - bool in_progress; - bool start; - u8 tsel; - bool hw_trigger; - emu_timer *end_timer; - } m_dma[4]; - - struct { - u32 bottom_addr; - u32 top_addr; - } m_g2apro; - - template void channel_map(address_map &map); - - template u32 stag_r(); - template void stag_w(offs_t offset, u32 data, u32 mem_mask = ~0); - - template u32 star_r(); - template void star_w(offs_t offset, u32 data, u32 mem_mask = ~0); - - template u32 len_r(); - template void len_w(offs_t offset, u32 data, u32 mem_mask = ~0); - - template u32 dir_r(); - template void dir_w(offs_t offset, u32 data, u32 mem_mask = ~0); - - template u32 tsel_r(); - template void tsel_w(offs_t offset, u32 data, u32 mem_mask = ~0); - - template u32 en_r(); - template void en_w(offs_t offset, u32 data, u32 mem_mask = ~0); - - template u32 st_r(); - template void st_w(offs_t offset, u32 data, u32 mem_mask = ~0); - - template u32 susp_r(); - template void susp_w(offs_t offset, u32 data, u32 mem_mask = ~0); - - void dma_execute(u8 channel); - bool root_address_check(u32 offset); - bool g2_address_check(u32 offset); - bool root_overflow_check(u32 offset, u8 channel); - - u32 g2id_r(); - void g2apro_w(offs_t offset, u32 data, u32 mem_mask = ~0); -}; - - -// device type definition -DECLARE_DEVICE_TYPE(DC_G2IF, dc_g2if_device) - -#endif // MAME_MACHINE_DC_G2IF_H diff --git a/src/mame/shared/maple-dc.cpp b/src/mame/shared/maple-dc.cpp deleted file mode 100644 index 47e44386efd..00000000000 --- a/src/mame/shared/maple-dc.cpp +++ /dev/null @@ -1,302 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert - -#include "emu.h" -#include "maple-dc.h" -#include "mie.h" - -DEFINE_DEVICE_TYPE(MAPLE_DC, maple_dc_device, "maple_dc", "Dreamcast Maple Bus") - -void maple_dc_device::amap(address_map &map) -{ - map(0x04, 0x07).rw(FUNC(maple_dc_device::sb_mdstar_r), FUNC(maple_dc_device::sb_mdstar_w)); - map(0x10, 0x13).rw(FUNC(maple_dc_device::sb_mdtsel_r), FUNC(maple_dc_device::sb_mdtsel_w)); - map(0x14, 0x17).rw(FUNC(maple_dc_device::sb_mden_r), FUNC(maple_dc_device::sb_mden_w)); - map(0x18, 0x1b).rw(FUNC(maple_dc_device::sb_mdst_r), FUNC(maple_dc_device::sb_mdst_w)); - map(0x80, 0x83).rw(FUNC(maple_dc_device::sb_msys_r), FUNC(maple_dc_device::sb_msys_w)); - map(0x8c, 0x8f).w(FUNC(maple_dc_device::sb_mdapro_w)); -} - -maple_dc_device::maple_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, MAPLE_DC, tag, owner, clock), - cpu(*this, finder_base::DUMMY_TAG), - irq_cb(*this) -{ - // Do not move that in device_start or there will be a race - // condition with the maple devices call to register_port. - memset(devices, 0, sizeof(devices)); -} - -void maple_dc_device::register_port(int port, maple_device *device) -{ - if(devices[port]) - fatalerror("maple_dc_device: duplicate registration on port %d\n", port); - - devices[port] = device; -} - -void maple_dc_device::device_start() -{ - logerror("maple_dc_device started\n"); - timer = timer_alloc(FUNC(maple_dc_device::dma_timer_tick), this); - irq_cb.resolve_safe(); - - mdstar = 0; - - save_item(NAME(mdstar)); - save_item(NAME(mden)); - save_item(NAME(mdst)); - save_item(NAME(msys)); - save_item(NAME(mdtsel)); - save_item(NAME(dma_state)); - save_item(NAME(dma_adr)); - save_item(NAME(dma_port)); - save_item(NAME(dma_dest)); - save_item(NAME(dma_endflag)); -} - -void maple_dc_device::device_reset() -{ - mden = 0; - mdst = 0; - msys = 0; - mdtsel = 0; - dma_state = DMA_IDLE; - dma_adr = 0; - dma_port = 0; - dma_dest = 0; - dma_endflag = false; -} - -TIMER_CALLBACK_MEMBER(maple_dc_device::dma_timer_tick) -{ - switch(dma_state) { - case DMA_WAIT_REPLY: - dma_state = DMA_TIMEOUT; - dma_step(); - break; - - case DMA_WAIT_NOP: - dma_state = DMA_SEND; - dma_step(); - break; - - case DMA_DONE: - dma_state = DMA_IDLE; - mdst = 0; - irq_cb(DMA_MAPLE_IRQ); - break; - - default: - logerror("MAPLE: Unexpected timer callback trigger\n"); - break; - } -} - -void maple_dc_device::dma_step() -{ - for(;;) { - switch(dma_state) { - case DMA_SEND: { - sh4_ddt_dma ddtdata; - uint32_t header[2]; - uint32_t data[512]; - ddtdata.source = dma_adr; // source address - ddtdata.length = 2; // words to transfer - ddtdata.size = 4; // bytes per word - ddtdata.buffer = header; // destination buffer - ddtdata.direction = 0; // 0 source to buffer, 1 buffer to source - ddtdata.channel = 0; - ddtdata.mode = -1; // copy from/to buffer - cpu->sh4_dma_ddt(&ddtdata); - dma_adr += 8; - - dma_endflag = header[0] & 0x80000000; - dma_port = (header[0] >> 16) & 3; - uint32_t pattern = (header[0] >> 8) & 7; - uint32_t length = (header[0] & 255) + 1; - dma_dest = header[1]; - - ddtdata.source = dma_adr; // source address - ddtdata.length = length; // words to transfer - ddtdata.size = 4; // bytes per word - ddtdata.buffer = data; // destination buffer - ddtdata.direction = 0; // 0 source to buffer, 1 buffer to source - ddtdata.channel = 0; - ddtdata.mode = -1; // copy from/to buffer - cpu->sh4_dma_ddt(&ddtdata); - dma_adr += length*4; - - switch(pattern) { - case 0: // start - if(devices[dma_port]) - devices[dma_port]->maple_w(data, length); - else { - // Avoid spending time on that specific timeout - dma_state = DMA_TIMEOUT; - break; - } - dma_state = DMA_WAIT_REPLY; - - // the MIE seems too slow for the correct timeout - // it's rather strange though - // timer->adjust(attotime::from_nsec(40000 + 20*(msys>>16))); // The 40us represent the sending and reception time - timer->adjust(attotime::from_msec(5)); - break; - case 2: // sdckb occupy permission (light gun protocol) - logerror("MAPLE: sdckb occupy permission\n"); - break; - case 3: // reset - if(devices[dma_port]) - devices[dma_port]->maple_reset(); - break; - case 4: // sdckb occupy cancel - logerror("MAPLE: sdckb occupy cancel\n"); - break; - case 7: // nop - logerror("MAPLE: nop\n"); - dma_state = DMA_WAIT_NOP; - break; - } - if(dma_state == DMA_SEND && dma_endflag) - dma_state = DMA_DONE; - break; - } - - case DMA_WAIT_REPLY: - return; - - case DMA_WAIT_NOP: - return; - - case DMA_TIMEOUT: { - sh4_ddt_dma ddtdata; - uint32_t data = 0xffffffff; - ddtdata.destination = dma_dest; // destination address - ddtdata.length = 1; // words to transfer - ddtdata.size = 4; // bytes per word - ddtdata.buffer = &data; // destination buffer - ddtdata.direction = 1; // 0 source to buffer, 1 buffer to source - ddtdata.channel = 0; - ddtdata.mode = -1; // copy from/to buffer - cpu->sh4_dma_ddt(&ddtdata); - dma_state = dma_endflag ? DMA_DONE : DMA_SEND; - break; - } - - case DMA_GOT_REPLY: { - timer->adjust(attotime::never); - - sh4_ddt_dma ddtdata; - uint32_t data[512]; - uint32_t length = 0; - bool partial = false; - if(devices[dma_port]) - devices[dma_port]->maple_r(data, length, partial); - else - fatalerror("MAPLE: reading from unconnected device on port %d\n", dma_port); - - if(length) { - ddtdata.destination = dma_dest; // destination address - ddtdata.length = length; // words to transfer - ddtdata.size = 4; // bytes per word - ddtdata.buffer = data; // destination buffer - ddtdata.direction = 1; // 0 source to buffer, 1 buffer to source - ddtdata.channel = 0; - ddtdata.mode = -1; // copy from/to buffer - cpu->sh4_dma_ddt(&ddtdata); - dma_dest += length*4; - } - - if(partial) - dma_state = DMA_WAIT_REPLY; - else - dma_state = dma_endflag ? DMA_DONE : DMA_SEND; - break; - } - case DMA_DONE: - timer->adjust(attotime::from_usec(200)); - return; - } - } -} - -void maple_dc_device::end_of_reply() -{ - if(dma_state == DMA_WAIT_REPLY) { - dma_state = DMA_GOT_REPLY; - dma_step(); - } else - logerror("MAPLE: Unexpected end of reply\n"); -} - -void maple_dc_device::maple_hw_trigger() -{ - if(mdtsel & 1) // HW trigger - { - dma_adr = mdstar; - dma_state = DMA_SEND; - dma_step(); - } -} - -uint32_t maple_dc_device::sb_mdstar_r() -{ - return mdstar; -} - -void maple_dc_device::sb_mdstar_w(uint32_t data) -{ - mdstar = data & ~31; -} - -uint32_t maple_dc_device::sb_mden_r() -{ - return mden; -} - -void maple_dc_device::sb_mden_w(uint32_t data) -{ - mden = data & 1; -} - -uint32_t maple_dc_device::sb_mdtsel_r() -{ - return mdtsel; -} - -void maple_dc_device::sb_mdtsel_w(uint32_t data) -{ - mdtsel = data & 1; -} - -uint32_t maple_dc_device::sb_mdst_r() -{ - return dma_state != DMA_IDLE ? 1 : 0; -} - -void maple_dc_device::sb_mdst_w(uint32_t data) -{ - uint32_t old = mdst; - mdst = data & 1; - - if(!old && data && (mden & 1) && mdtsel == 0) { - dma_adr = mdstar; - dma_state = DMA_SEND; - dma_step(); - } -} - -uint32_t maple_dc_device::sb_msys_r() -{ - return msys; -} - -void maple_dc_device::sb_msys_w(uint32_t data) -{ - msys = data; -} - -void maple_dc_device::sb_mdapro_w(uint32_t data) -{ -} diff --git a/src/mame/shared/maple-dc.h b/src/mame/shared/maple-dc.h deleted file mode 100644 index 45d2efbbec1..00000000000 --- a/src/mame/shared/maple-dc.h +++ /dev/null @@ -1,84 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert -#ifndef MAME_MACHINE_MAPLE_DC_H -#define MAME_MACHINE_MAPLE_DC_H - -#pragma once - -#include "cpu/sh/sh4.h" - -class maple_device; - -class maple_dc_device : public device_t -{ -public: - enum { - DMA_MAPLE_IRQ - }; - - template - maple_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag) - : maple_dc_device(mconfig, tag, owner, clock) - { - set_maincpu_tag(std::forward(cpu_tag)); - } - - maple_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - template void set_maincpu_tag(T &&cpu_tag) { cpu.set_tag(std::forward(cpu_tag)); } - auto irq_callback() { return irq_cb.bind(); } - - uint32_t sb_mdstar_r(); // 5f6c04 - void sb_mdstar_w(uint32_t data); - uint32_t sb_mdtsel_r(); // 5f6c10 - void sb_mdtsel_w(uint32_t data); - uint32_t sb_mden_r(); // 5f6c14 - void sb_mden_w(uint32_t data); - uint32_t sb_mdst_r(); // 5f6c18 - void sb_mdst_w(uint32_t data); - uint32_t sb_msys_r(); // 5f6c80 - void sb_msys_w(uint32_t data); - void sb_mdapro_w(uint32_t data); // 5f6c8c - - void amap(address_map &map); - - void end_of_reply(); - void register_port(int port, maple_device *device); - void maple_hw_trigger(); - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - TIMER_CALLBACK_MEMBER(dma_timer_tick); - -private: - enum { - DMA_IDLE, - DMA_DONE, - DMA_SEND, - DMA_WAIT_NOP, - DMA_WAIT_RESET, - DMA_WAIT_REPLY, - DMA_GOT_REPLY, - DMA_TIMEOUT - }; - - maple_device *devices[4]; - - required_device cpu; - emu_timer *timer; - - uint32_t mdstar, mden, mdst, msys; - uint32_t mdtsel; - - uint32_t dma_state, dma_adr, dma_port, dma_dest; - bool dma_endflag; - devcb_write8 irq_cb; - - void dma_step(); -}; - -DECLARE_DEVICE_TYPE(MAPLE_DC, maple_dc_device) - -#endif // MAME_MACHINE_MAPLE_DC_H diff --git a/src/mame/shared/mapledev.cpp b/src/mame/shared/mapledev.cpp deleted file mode 100644 index ee4340ee56f..00000000000 --- a/src/mame/shared/mapledev.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert -#include "emu.h" -#include "mapledev.h" - -maple_device::maple_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) -, host(*this, finder_base::DUMMY_TAG) -{ - host_port = 0; -} - - -void maple_device::device_start() -{ - host->register_port(host_port, this); - - timer = timer_alloc(FUNC(maple_device::reply_ready), this); - - save_item(NAME(reply_buffer)); - save_item(NAME(reply_size)); - save_item(NAME(reply_partial)); -} - -void maple_device::maple_reset() -{ - device_reset(); -} - -void maple_device::reply_ready_with_delay() -{ - // Arbitrary delay to avoid instant replies - // Makes the maple dma code easier to write - // There's usually something z80 in there after all, so it even makes sense - timer->adjust(attotime::from_usec(100)); -} - -TIMER_CALLBACK_MEMBER(maple_device::reply_ready) -{ - host->end_of_reply(); -} - -void maple_device::copy_with_spaces(uint8_t *dest, const char *source, int len) -{ - int i; - for(i=0; i host; - int host_port = 0; - -private: - emu_timer *timer = nullptr; -}; - -#endif // MAME_MACHINE_MAPLEDEV_H diff --git a/src/mame/shared/megadriv.cpp b/src/mame/shared/megadriv.cpp deleted file mode 100644 index 80a238bf9b9..00000000000 --- a/src/mame/shared/megadriv.cpp +++ /dev/null @@ -1,1108 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/* - -Megadrive / Genesis support - -this could probably do with a complete rewrite at this point to take into -account all new information discovered since this was created, it's looking -rather old now. - - - -Cleanup / Rewrite notes: - - - -Known Non-Issues (confirmed on Real Genesis) - Castlevania - Bloodlines (U) [!] - Pause text is missing on upside down level - Blood Shot (E) (M4) [!] - corrupt texture in level 1 is correct... - - - -*/ - - -#include "emu.h" -#include "megadriv.h" -#include "speaker.h" - -#define LOG_AUDIOBANK (1U << 1) // z80 to 68k space window access at $8000-$ffff -#define LOG_AUDIOBUS (1U << 2) // z80 bus grants -#define LOG_AUDIORESET (1U << 3) // z80 reset line - -#define VERBOSE (0) - -#include "logmacro.h" - -#define LOGAUDIOBANK(...) LOGMASKED(LOG_AUDIOBANK, __VA_ARGS__) -#define LOGAUDIOBUS(...) LOGMASKED(LOG_AUDIOBUS, __VA_ARGS__) -#define LOGAUDIORESET(...) LOGMASKED(LOG_AUDIORESET, __VA_ARGS__) - - -void md_base_state::megadriv_z80_bank_w(uint16_t data) -{ - // TODO: menghu crashes here - // Tries to setup a bank of 0xff0000 from z80 side (PC=1131) after you talk with the cashier twice. - // Without a guard over it game will trash 68k memory causing a crash, works on real HW with everdrive - // so not coming from a cart copy protection. - // Update: it breaks cfodder BGM on character select at least, therefore we current don't guard against it - // Apparently reading 68k RAM from z80 is not recommended by Sega, so *writing* isn't possible lacking bus grant? - m_genz80.z80_bank_addr = ((m_genz80.z80_bank_addr >> 1) | (data << 23)) & 0xff8000; -} - -void md_base_state::megadriv_68k_z80_bank_write(uint16_t data) -{ - megadriv_z80_bank_w(data & 0x01); -} - -void md_base_state::megadriv_z80_z80_bank_w(uint8_t data) -{ - LOGAUDIOBANK("%s: port $6000 write 0x%02x ", machine().describe_context(), data); - megadriv_z80_bank_w(data & 0x01); - LOGAUDIOBANK("Current bank %08x\n", m_genz80.z80_bank_addr); -} - -uint8_t md_base_state::megadriv_68k_YM2612_read(offs_t offset, uint8_t mem_mask) -{ - //osd_printf_debug("megadriv_68k_YM2612_read %02x %04x\n",offset,mem_mask); - if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) - { - return m_ymsnd->read(offset); - } - else - { - LOG("%s: 68000 attempting to access YM2612 (read) without bus\n", machine().describe_context()); - return 0; - } - - // never executed - //return -1; -} - - -void md_base_state::megadriv_68k_YM2612_write(offs_t offset, uint8_t data, uint8_t mem_mask) -{ - //osd_printf_debug("megadriv_68k_YM2612_write %02x %04x %04x\n",offset,data,mem_mask); - if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) - { - m_ymsnd->write(offset, data); - } - else - { - LOG("%s: 68000 attempting to access YM2612 (write) without bus\n", machine().describe_context()); - } -} - -// this is used by 6 button pads and gets installed in machine_start for drivers requiring it -TIMER_CALLBACK_MEMBER(md_base_state::io_timeout_timer_callback) -{ - m_io_stage[(int)param] = -1; -} - - -/* - - A10001h = A0 Version register - - A10003h = 7F Data register for port A - A10005h = 7F Data register for port B - A10007h = 7F Data register for port C - - A10009h = 00 Ctrl register for port A - A1000Bh = 00 Ctrl register for port B - A1000Dh = 00 Ctrl register for port C - - A1000Fh = FF TxData register for port A - A10011h = 00 RxData register for port A - A10013h = 00 S-Ctrl register for port A - - A10015h = FF TxData register for port B - A10017h = 00 RxData register for port B - A10019h = 00 S-Ctrl register for port B - - A1001Bh = FF TxData register for port C - A1001Dh = 00 RxData register for port C - A1001Fh = 00 S-Ctrl register for port C - - - - - Bit 7 - (Not connected) - Bit 6 - TH - Bit 5 - TL - Bit 4 - TR - Bit 3 - RIGHT - Bit 2 - LEFT - Bit 1 - DOWN - Bit 0 - UP - - -*/ - -INPUT_PORTS_START( md_common ) - PORT_START("PAD1") /* Joypad 1 (3 button + start) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") // b - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") // c - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") // a - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 START") // start - - PORT_START("PAD2") /* Joypad 2 (3 button + start) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") // b - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") // c - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") // a - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 START") // start -INPUT_PORTS_END - - -INPUT_PORTS_START( megadriv ) - PORT_INCLUDE( md_common ) - - PORT_START("RESET") /* Buttons on Genesis Console */ - PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Reset Button") PORT_IMPULSE(1) // reset, resets 68k (and..?) -INPUT_PORTS_END - -INPUT_PORTS_START( megadri6 ) - PORT_INCLUDE( megadriv ) - - PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("P1 Z") // z - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 Y") // y - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 X") // x - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(1) PORT_NAME("P1 MODE") // mode - - PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("P2 Z") // z - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 Y") // y - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 X") // x - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(2) PORT_NAME("P2 MODE") // mode -INPUT_PORTS_END - -void md_base_state::megadrive_reset_io() -{ - int i; - - m_megadrive_io_data_regs[0] = 0x7f; - m_megadrive_io_data_regs[1] = 0x7f; - m_megadrive_io_data_regs[2] = 0x7f; - m_megadrive_io_ctrl_regs[0] = 0x00; - m_megadrive_io_ctrl_regs[1] = 0x00; - m_megadrive_io_ctrl_regs[2] = 0x00; - m_megadrive_io_tx_regs[0] = 0xff; - m_megadrive_io_tx_regs[1] = 0xff; - m_megadrive_io_tx_regs[2] = 0xff; - - for (i=0; i<3; i++) - { - m_io_stage[i] = -1; - } -} - -/************* 6 buttons version **************************/ -uint8_t md_base_state::megadrive_io_read_data_port_6button(offs_t offset) -{ - int portnum = offset; - uint8_t retdata, helper = (m_megadrive_io_ctrl_regs[portnum] & 0x3f) | 0xc0; // bits 6 & 7 always come from m_megadrive_io_data_regs - - if (m_megadrive_io_data_regs[portnum] & 0x40) - { - if (m_io_stage[portnum] == 2) - { - /* here we read B, C & the additional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x30) | - ((m_io_pad_6b[portnum] ? m_io_pad_6b[portnum]->read() : 0) & 0x0f)) & ~helper); - } - else - { - /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - (((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x3f) & ~helper); - } - } - else - { - if (m_io_stage[portnum] == 1) - { - /* here we read ((Start & A) >> 2) | 0x00 */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) & ~helper); - } - else if (m_io_stage[portnum]==2) - { - /* here we read ((Start & A) >> 2) | 0x0f */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | 0x0f) & ~helper); - } - else - { - /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | - ((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x03)) & ~helper); - } - } - -// osd_printf_debug("read io data port stage %d port %d %02x\n",m_io_stage[portnum],portnum,retdata); - - return retdata | (retdata << 8); -} - - -/************* 3 buttons version **************************/ -uint8_t md_base_state::megadrive_io_read_data_port_3button(offs_t offset) -{ - int portnum = offset; - uint8_t retdata, helper = (m_megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from m_megadrive_io_data_regs - - if (m_megadrive_io_data_regs[portnum] & 0x40) - { - /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x3f) | 0x40) & ~helper); - } - else - { - /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | - (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | - ((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x03) | 0x40) & ~helper); - } - - return retdata; -} - -uint8_t md_base_state::megadrive_io_read_ctrl_port(int portnum) -{ - uint8_t retdata; - retdata = m_megadrive_io_ctrl_regs[portnum]; - //osd_printf_debug("read io ctrl port %d %02x\n",portnum,retdata); - - return retdata | (retdata << 8); -} - -uint8_t md_base_state::megadrive_io_read_tx_port(int portnum) -{ - uint8_t retdata; - retdata = m_megadrive_io_tx_regs[portnum]; - return retdata | (retdata << 8); -} - -uint8_t md_base_state::megadrive_io_read_rx_port(int portnum) -{ - return 0x00; -} - -uint8_t md_base_state::megadrive_io_read_sctrl_port(int portnum) -{ - return 0x00; -} - - -uint16_t md_base_state::megadriv_68k_io_read(offs_t offset) -{ - uint8_t retdata; - - retdata = 0; - /* Charles MacDonald ( http://cgfm2.emuviews.com/ ) - D7 : Console is 1= Export (USA, Europe, etc.) 0= Domestic (Japan) - D6 : Video type is 1= PAL, 0= NTSC - D5 : Sega CD unit is 1= not present, 0= connected. - D4 : Unused (always returns zero) - D3 : Bit 3 of version number - D2 : Bit 2 of version number - D1 : Bit 1 of version number - D0 : Bit 0 of version number - */ - - //return (machine().rand()&0x0f0f)|0xf0f0;//0x0000; - switch (offset) - { - case 0: - LOG("%06x read version register\n", m_maincpu->pc()); - // Version number contained in bits 3-0 - // TODO: non-TMSS BIOSes must return 0 here - retdata = m_version_hi_nibble | 0x01; - break; - - /* Joystick Port Registers */ - - case 0x1: - case 0x2: - case 0x3: - retdata = m_megadrive_io_read_data_port_ptr(offset-1); - break; - - case 0x4: - case 0x5: - case 0x6: - retdata = megadrive_io_read_ctrl_port(offset-4); - break; - - /* Serial I/O Registers */ - - case 0x7: retdata = megadrive_io_read_tx_port(0); break; - case 0x8: retdata = megadrive_io_read_rx_port(0); break; - case 0x9: retdata = megadrive_io_read_sctrl_port(0); break; - - case 0xa: retdata = megadrive_io_read_tx_port(1); break; - case 0xb: retdata = megadrive_io_read_rx_port(1); break; - case 0xc: retdata = megadrive_io_read_sctrl_port(1); break; - - case 0xd: retdata = megadrive_io_read_tx_port(2); break; - case 0xe: retdata = megadrive_io_read_rx_port(2); break; - case 0xf: retdata = megadrive_io_read_sctrl_port(2); break; - - } - - return retdata | (retdata << 8); -} - - -void md_base_state::megadrive_io_write_data_port_3button(offs_t offset, uint16_t data) -{ - int portnum = offset; - m_megadrive_io_data_regs[portnum] = data; - //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); - -} - - -/****************************** 6 buttons version*****************************/ - -void md_base_state::megadrive_io_write_data_port_6button(offs_t offset, uint16_t data) -{ - int portnum = offset; - if (m_megadrive_io_ctrl_regs[portnum]&0x40) - { - if (((m_megadrive_io_data_regs[portnum]&0x40)==0x00) && ((data&0x40) == 0x40)) - { - m_io_stage[portnum]++; - m_io_timeout[portnum]->adjust(m_maincpu->cycles_to_attotime(8192), portnum); - } - - } - - m_megadrive_io_data_regs[portnum] = data; - //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); - -} - - -/*************************** 3 buttons version ****************************/ - -void md_base_state::megadrive_io_write_ctrl_port(int portnum, uint16_t data) -{ - m_megadrive_io_ctrl_regs[portnum] = data; -// osd_printf_debug("Setting IO Control Register #%d data %04x\n",portnum,data); -} - -void md_base_state::megadrive_io_write_tx_port(int portnum, uint16_t data) -{ - m_megadrive_io_tx_regs[portnum] = data; -} - -void md_base_state::megadrive_io_write_rx_port(int portnum, uint16_t data) -{ -} - -void md_base_state::megadrive_io_write_sctrl_port(int portnum, uint16_t data) -{ -} - - -void md_base_state::megadriv_68k_io_write(offs_t offset, uint16_t data, uint16_t mem_mask) -{ -// osd_printf_debug("IO Write #%02x data %04x mem_mask %04x\n",offset,data,mem_mask); - - - switch (offset) - { - case 0x0: - osd_printf_debug("Write to Version Register?!\n"); - break; - - /* Joypad Port Registers */ - - case 0x1: - case 0x2: - case 0x3: - m_megadrive_io_write_data_port_ptr(offset-1,data); - break; - - case 0x4: - case 0x5: - case 0x6: - megadrive_io_write_ctrl_port(offset-4,data); - break; - - /* Serial I/O Registers */ - - case 0x7: megadrive_io_write_tx_port(0,data); break; - case 0x8: megadrive_io_write_rx_port(0,data); break; - case 0x9: megadrive_io_write_sctrl_port(0,data); break; - - case 0xa: megadrive_io_write_tx_port(1,data); break; - case 0xb: megadrive_io_write_rx_port(1,data); break; - case 0xc: megadrive_io_write_sctrl_port(1,data); break; - - case 0xd: megadrive_io_write_tx_port(2,data); break; - case 0xe: megadrive_io_write_rx_port(2,data); break; - case 0xf: megadrive_io_write_sctrl_port(2,data); break; - } -} - - - -void md_base_state::megadriv_map(address_map &map) -{ - map(0x000000, 0x3fffff).rom(); - /* (0x000000 - 0x3fffff) == GAME ROM (4Meg Max, Some games have special banking too) */ - - map(0xa00000, 0xa01fff).rw(FUNC(md_base_state::megadriv_68k_read_z80_ram), FUNC(md_base_state::megadriv_68k_write_z80_ram)); - map(0xa02000, 0xa03fff).w(FUNC(md_base_state::megadriv_68k_write_z80_ram)); - map(0xa04000, 0xa04003).rw(FUNC(md_base_state::megadriv_68k_YM2612_read), FUNC(md_base_state::megadriv_68k_YM2612_write)); - - map(0xa06000, 0xa06001).w(FUNC(md_base_state::megadriv_68k_z80_bank_write)); - - map(0xa10000, 0xa1001f).rw(FUNC(md_base_state::megadriv_68k_io_read), FUNC(md_base_state::megadriv_68k_io_write)); - - map(0xa11100, 0xa11101).rw(FUNC(md_base_state::megadriv_68k_check_z80_bus), FUNC(md_base_state::megadriv_68k_req_z80_bus)); - map(0xa11200, 0xa11201).w(FUNC(md_base_state::megadriv_68k_req_z80_reset)); - - map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); - map(0xd00000, 0xd0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w)); // the earth defend - map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram"); -// map(0xff0000, 0xffffff).readonly(); - /* 0xe00000 - 0xffffff) == MAIN RAM (64kb, Mirrored, most games use ff0000 - ffffff) */ -} - - -void md_base_state::dcat16_megadriv_map(address_map &map) -{ - megadriv_map(map); - map(0x000000, 0x7fffff).rom(); -} - - -/* z80 sounds/sub CPU */ - - -uint16_t md_base_state::megadriv_68k_read_z80_ram(offs_t offset, uint16_t mem_mask) -{ - //osd_printf_debug("read z80 ram %04x\n",mem_mask); - - if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) - { - return m_genz80.z80_prgram[(offset<<1)^1] | (m_genz80.z80_prgram[(offset<<1)]<<8); - } - else - { - LOG("%06x: 68000 attempting to access Z80 (read) address space without bus\n", m_maincpu->pc()); - return machine().rand(); - } -} - -void md_base_state::megadriv_68k_write_z80_ram(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if ((m_genz80.z80_has_bus == 0) && (m_genz80.z80_is_reset == 0)) - { - if (!ACCESSING_BITS_0_7) // byte (MSB) access - { - m_genz80.z80_prgram[(offset<<1)] = (data & 0xff00) >> 8; - } - else if (!ACCESSING_BITS_8_15) - { - m_genz80.z80_prgram[(offset<<1)^1] = (data & 0x00ff); - } - else - { - // for WORD access only the MSB is used, LSB is ignored - m_genz80.z80_prgram[(offset<<1)] = (data & 0xff00) >> 8; - } - } - else - { - LOG("%06x: 68000 attempting to access Z80 (write) address space without bus\n", m_maincpu->pc()); - } -} - -/* - * ddragon, beast, superoff, and timekill have buggy sound programs. - * They request the bus, then have a loop which waits for the bus - * to be unavailable, checking for a 0 value due to bad coding. The real hardware - * appears to return bits of the next instruction in the unused bits, thus meaning - * the value is never zero. Time Killers is the most fussy, and doesn't like the - * read_next_instruction function from system16, so I just return a random value - * in the unused bits - */ -uint16_t md_base_state::megadriv_68k_check_z80_bus(offs_t offset, uint16_t mem_mask) -{ - uint16_t retvalue; - - - uint16_t nextvalue = machine().rand(); //read_next_instruction(space)&0xff00; - - - /* Check if the 68k has the z80 bus */ - if (!ACCESSING_BITS_0_7) // byte (MSB) access - { - if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = nextvalue | 0x0100; - else retvalue = (nextvalue & 0xfeff); - - LOGAUDIOBUS("%06x: 68000 check z80 Bus (byte MSB access) returning %04x mask %04x\n", m_maincpu->pc(),retvalue, mem_mask); - return retvalue; - - } - else if (!ACCESSING_BITS_8_15) // is this valid? - { - LOGAUDIOBUS("%06x: 68000 check z80 Bus (byte LSB access) %04x\n", m_maincpu->pc(), mem_mask); - if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = 0x0001; - else retvalue = 0x0000; - - return retvalue; - } - else - { - LOGAUDIOBUS("%06x: 68000 check z80 Bus (word access) %04x\n", m_maincpu->pc(),mem_mask); - if (m_genz80.z80_has_bus || m_genz80.z80_is_reset) retvalue = nextvalue | 0x0100; - else retvalue = (nextvalue & 0xfeff); - - // osd_printf_debug("%06x: 68000 check z80 Bus (word access) %04x %04x\n", m_maincpu->pc(),mem_mask, retvalue); - return retvalue; - } -} - - -TIMER_CALLBACK_MEMBER(md_base_state::megadriv_z80_run_state) -{ - /* Is the z80 RESET line pulled? */ - // TODO: Z80 /RESET - if (m_genz80.z80_is_reset) - { - m_z80snd->reset(); - m_z80snd->suspend(SUSPEND_REASON_HALT, 1); - m_ymsnd->reset(); - } - else - { - /* Check if z80 has the bus */ - // TODO: Z80 /BUSREQ - if (m_genz80.z80_has_bus) - m_z80snd->resume(SUSPEND_REASON_HALT); - else - m_z80snd->suspend(SUSPEND_REASON_HALT, 1); - } -} - - -void md_base_state::megadriv_68k_req_z80_bus(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - /* Request the Z80 bus, allows 68k to read/write Z80 address space */ - if (!ACCESSING_BITS_0_7) // byte access - { - if (data & 0x0100) - { - LOGAUDIOBUS("%06x: 68000 request z80 Bus (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_has_bus = 0; - } - else - { - LOGAUDIOBUS("%06x: 68000 return z80 Bus (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_has_bus = 1; - } - } - else if (!ACCESSING_BITS_8_15) // is this valid? - { - if (data & 0x0001) - { - LOGAUDIOBUS("%06x: 68000 request z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_has_bus = 0; - } - else - { - LOGAUDIOBUS("%06x: 68000 return z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_has_bus = 1; - } - } - else // word access - { - if (data & 0x0100) - { - LOGAUDIOBUS("%06x: 68000 request z80 Bus (word access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_has_bus = 0; - } - else - { - LOGAUDIOBUS("%06x: 68000 return z80 Bus (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_has_bus = 1; - } - } - - /* If the z80 is running, sync the z80 execution state */ - if (!m_genz80.z80_is_reset) - m_genz80.z80_run_timer->adjust(attotime::zero); -} - -void md_base_state::megadriv_68k_req_z80_reset(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if (!ACCESSING_BITS_0_7) // byte access - { - if (data & 0x0100) - { - LOGAUDIORESET("%06x: 68000 clear z80 reset (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_is_reset = 0; - } - else - { - LOGAUDIORESET("%06x: 68000 start z80 reset (byte MSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_is_reset = 1; - } - } - else if (!ACCESSING_BITS_8_15) // is this valid? - { - if (data & 0x0001) - { - LOGAUDIORESET("%06x: 68000 clear z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_is_reset = 0; - } - else - { - LOGAUDIORESET("%06x: 68000 start z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_is_reset = 1; - } - } - else // word access - { - if (data & 0x0100) - { - LOGAUDIORESET("%06x: 68000 clear z80 reset (word access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_is_reset = 0; - } - else - { - LOGAUDIORESET("%06x: 68000 start z80 reset (byte LSB access) %04x %04x\n", m_maincpu->pc(),data,mem_mask); - m_genz80.z80_is_reset = 1; - } - } - m_genz80.z80_run_timer->adjust(attotime::zero); -} - - -// just directly access the 68k space, this makes it easier to deal with -// add-on hardware which changes the cpu mapping like the 32x and SegaCD. -// - we might need to add exceptions for example, z80 reading / writing the -// z80 area of the 68k if games misbehave -uint8_t md_base_state::z80_read_68k_banked_data(offs_t offset) -{ - address_space &space68k = m_maincpu->space(); - uint8_t ret = space68k.read_byte(m_genz80.z80_bank_addr+offset); - return ret; -} - -void md_base_state::z80_write_68k_banked_data(offs_t offset, uint8_t data) -{ - address_space &space68k = m_maincpu->space(); - space68k.write_byte(m_genz80.z80_bank_addr+offset,data); -} - -void md_base_state::megadriv_z80_vdp_write(offs_t offset, uint8_t data) -{ - switch (offset) - { - case 0x11: - case 0x13: - case 0x15: - case 0x17: - // accessed by either segapsg_device or sn76496_device - m_vdp->vdp_w(offset >> 1, data, 0x00ff); - break; - - default: - osd_printf_debug("unhandled z80 vdp write %02x %02x\n",offset,data); - } -} - - -uint8_t md_base_state::megadriv_z80_vdp_read(offs_t offset) -{ - u8 ret = 0; - u8 shift = ((~offset & 1) << 3); - switch (offset & ~1) - { - case 0x04: // ctrl_port_r - case 0x06: - case 0x08: // H/V counter - case 0x0a: - case 0x0c: - case 0x0e: - ret = m_vdp->vdp_r(offset >> 1, 0xff << shift) >> shift; - break; - - default: - if (!machine().side_effects_disabled()) - osd_printf_debug("unhandled z80 vdp read %02x\n",offset); - ret = machine().rand(); - break; - } - return ret; -} - -uint8_t md_base_state::megadriv_z80_unmapped_read() -{ - return 0xff; -} - -void md_base_state::megadriv_z80_map(address_map &map) -{ - map(0x0000, 0x1fff).bankrw("bank1").mirror(0x2000); // RAM can be accessed by the 68k - map(0x4000, 0x4003).rw(m_ymsnd, FUNC(ym_generic_device::read), FUNC(ym_generic_device::write)); - - map(0x6000, 0x6000).w(FUNC(md_base_state::megadriv_z80_z80_bank_w)); - map(0x6001, 0x6001).w(FUNC(md_base_state::megadriv_z80_z80_bank_w)); // wacky races uses this address - - map(0x6100, 0x7eff).r(FUNC(md_base_state::megadriv_z80_unmapped_read)); - - map(0x7f00, 0x7fff).rw(FUNC(md_base_state::megadriv_z80_vdp_read), FUNC(md_base_state::megadriv_z80_vdp_write)); - - map(0x8000, 0xffff).rw(FUNC(md_base_state::z80_read_68k_banked_data), FUNC(md_base_state::z80_write_68k_banked_data)); // The Z80 can read the 68k address space this way -} - -void md_base_state::megadriv_z80_io_map(address_map &map) -{ - map.global_mask(0xff); - map(0x00, 0xff).noprw(); -} - -uint32_t md_base_state::screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - /* Copy our screen buffer here */ - for (int y = cliprect.min_y; y <= cliprect.max_y; y++) - { - uint32_t *const desty = &bitmap.pix(y, 0); - uint32_t const *srcy; - - if (!m_vdp->m_use_alt_timing) - srcy = &m_vdp->m_render_bitmap->pix(y, 0); - else - srcy = m_vdp->m_render_line.get(); - - for (int x = cliprect.min_x; x <= cliprect.max_x; x++) - { - desty[x] = srcy[x]; - } - } - - return 0; -} - - - -/*****************************************************************************************/ - -void md_base_state::video_start() -{ - // nothing? -} - -void md_base_state::machine_start() -{ - m_io_pad_3b[0] = ioport("PAD1"); - m_io_pad_3b[1] = ioport("PAD2"); - m_io_pad_3b[2] = ioport("IN0"); - m_io_pad_3b[3] = ioport("UNK"); - - save_item(NAME(m_io_stage)); - save_item(NAME(m_megadrive_io_data_regs)); - save_item(NAME(m_megadrive_io_ctrl_regs)); - save_item(NAME(m_megadrive_io_tx_regs)); - - if (m_z80snd) - m_genz80.z80_run_timer = timer_alloc(FUNC(md_base_state::megadriv_z80_run_state), this); -} - -void md_base_state::machine_reset() -{ - /* default state of z80 = reset, with bus */ - osd_printf_debug("Resetting Megadrive / Genesis\n"); - - if (m_z80snd) - { - m_genz80.z80_is_reset = 1; - m_genz80.z80_has_bus = 1; - m_genz80.z80_bank_addr = 0; - m_vdp->set_scanline_counter(-1); - m_genz80.z80_run_timer->adjust(attotime::zero); - } - - megadrive_reset_io(); - - if (!m_vdp->m_use_alt_timing) - { - m_vdp->m_megadriv_scanline_timer = m_scan_timer; - m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); - } - - if (m_megadrive_ram) - memset(m_megadrive_ram, 0x00, 0x10000); - - m_vdp->device_reset_old(); -} - -void md_base_state::megadriv_stop_scanline_timer() -{ - if (!m_vdp->m_use_alt_timing) - m_vdp->m_megadriv_scanline_timer->reset(); -} - - - -// this comes from the VDP on lines 240 (on) 241 (off) and is connected to the z80 irq 0 -WRITE_LINE_MEMBER(md_base_state::vdp_sndirqline_callback_genesis_z80) -{ - if (m_z80snd) - { - if (state == ASSERT_LINE) - { - if ((m_genz80.z80_has_bus == 1) && (m_genz80.z80_is_reset == 0)) - m_z80snd->set_input_line(0, HOLD_LINE); - } - else if (state == CLEAR_LINE) - { - m_z80snd->set_input_line(0, CLEAR_LINE); - } - } -} - -// this comes from the vdp, and is connected to 68k irq level 6 (main vbl interrupt) -WRITE_LINE_MEMBER(md_base_state::vdp_lv6irqline_callback_genesis_68k) -{ - if (state == ASSERT_LINE) - m_maincpu->set_input_line(6, HOLD_LINE); - else - m_maincpu->set_input_line(6, CLEAR_LINE); -} - -// this comes from the vdp, and is connected to 68k irq level 4 (raster interrupt) -WRITE_LINE_MEMBER(md_base_state::vdp_lv4irqline_callback_genesis_68k) -{ - if (state == ASSERT_LINE) - m_maincpu->set_input_line(4, HOLD_LINE); - else - m_maincpu->set_input_line(4, CLEAR_LINE); -} - -/* Callback when the 68k takes an IRQ */ -IRQ_CALLBACK_MEMBER(md_base_state::genesis_int_callback) -{ - if (irqline==4) - { - m_vdp->vdp_clear_irq4_pending(); - } - - if (irqline==6) - { - m_vdp->vdp_clear_irq6_pending(); - } - - return (0x60+irqline*4)/4; // vector address -} - -void md_base_state::megadriv_timers(machine_config &config) -{ - TIMER(config, m_scan_timer).configure_generic("gen_vdp", FUNC(sega315_5313_device::megadriv_scanline_timer_callback)); -} - - -void md_base_state::md_ntsc(machine_config &config) -{ - M68000(config, m_maincpu, MASTER_CLOCK_NTSC / 7); /* 7.67 MHz */ - m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_map); - m_maincpu->set_irq_acknowledge_callback(FUNC(md_base_state::genesis_int_callback)); - - /* IRQs are handled via the timers */ - - Z80(config, m_z80snd, MASTER_CLOCK_NTSC / 15); /* 3.58 MHz */ - m_z80snd->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_z80_map); - m_z80snd->set_addrmap(AS_IO, &md_base_state::megadriv_z80_io_map); - /* IRQ handled via the timers */ - - megadriv_timers(config); - - SEGA315_5313(config, m_vdp, MASTER_CLOCK_NTSC, m_maincpu); - m_vdp->set_is_pal(false); - m_vdp->snd_irq().set(FUNC(md_base_state::vdp_sndirqline_callback_genesis_z80)); - m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k)); - m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k)); - m_vdp->set_screen("megadriv"); - m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50); - m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50); - - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 10.0 / 262.0 / 342.0); // same as SMS? -// m_screen->set_refresh_hz(double(MASTER_CLOCK_NTSC) / 8.0 / 262.0 / 427.0); // or 427 Htotal? - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. - m_screen->set_size(64*8, 620); - m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); - m_screen->set_screen_update(FUNC(md_base_state::screen_update_megadriv)); /* Copies a bitmap */ - m_screen->screen_vblank().set(FUNC(md_base_state::screen_vblank_megadriv)); /* Used to Sync the timing */ - - /* sound hardware */ - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - YM2612(config, m_ymsnd, MASTER_CLOCK_NTSC/7); /* 7.67 MHz */ - m_ymsnd->add_route(0, "lspeaker", 0.50); - m_ymsnd->add_route(1, "rspeaker", 0.50); -} - -void md_base_state::md2_ntsc(machine_config &config) -{ - md_ntsc(config); - - // Internalized YM3438 in VDP ASIC - YM3438(config.replace(), m_ymsnd, MASTER_CLOCK_NTSC/7); /* 7.67 MHz */ - m_ymsnd->add_route(0, "lspeaker", 0.50); - m_ymsnd->add_route(1, "rspeaker", 0.50); -} - -/************ PAL hardware has a different master clock *************/ - -void md_base_state::md_pal(machine_config &config) -{ - M68000(config, m_maincpu, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ - m_maincpu->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_map); - m_maincpu->set_irq_acknowledge_callback(FUNC(md_base_state::genesis_int_callback)); - /* IRQs are handled via the timers */ - - Z80(config, m_z80snd, MASTER_CLOCK_PAL / 15); /* 3.58 MHz */ - m_z80snd->set_addrmap(AS_PROGRAM, &md_base_state::megadriv_z80_map); - m_z80snd->set_addrmap(AS_IO, &md_base_state::megadriv_z80_io_map); - /* IRQ handled via the timers */ - - megadriv_timers(config); - - SEGA315_5313(config, m_vdp, MASTER_CLOCK_PAL, m_maincpu); - m_vdp->set_is_pal(true); - m_vdp->snd_irq().set(FUNC(md_base_state::vdp_sndirqline_callback_genesis_z80)); - m_vdp->lv6_irq().set(FUNC(md_base_state::vdp_lv6irqline_callback_genesis_68k)); - m_vdp->lv4_irq().set(FUNC(md_base_state::vdp_lv4irqline_callback_genesis_68k)); - m_vdp->set_screen("megadriv"); - m_vdp->add_route(ALL_OUTPUTS, "lspeaker", 0.50); - m_vdp->add_route(ALL_OUTPUTS, "rspeaker", 0.50); - - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 10.0 / 313.0 / 342.0); // same as SMS? -// m_screen->set_refresh_hz(double(MASTER_CLOCK_PAL) / 8.0 / 313.0 / 423.0); // or 423 Htotal? - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); // Vblank handled manually. - m_screen->set_size(64*8, 620); - m_screen->set_visarea(0, 32*8-1, 0, 28*8-1); - m_screen->set_screen_update(FUNC(md_base_state::screen_update_megadriv)); /* Copies a bitmap */ - m_screen->screen_vblank().set(FUNC(md_base_state::screen_vblank_megadriv)); /* Used to Sync the timing */ - - /* sound hardware */ - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - YM2612(config, m_ymsnd, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ - m_ymsnd->add_route(0, "lspeaker", 0.50); - m_ymsnd->add_route(1, "rspeaker", 0.50); -} - -void md_base_state::md2_pal(machine_config &config) -{ - md_pal(config); - - // Internalized YM3438 in VDP ASIC - YM3438(config.replace(), m_ymsnd, MASTER_CLOCK_PAL / 7); /* 7.67 MHz */ - m_ymsnd->add_route(0, "lspeaker", 0.50); - m_ymsnd->add_route(1, "rspeaker", 0.50); -} - - -void md_base_state::megadriv_tas_callback(offs_t offset, uint8_t data) -{ - // writeback not allowed -} - -void md_base_state::megadriv_init_common() -{ - /* Look to see if this system has the standard Sound Z80 */ - if (m_z80snd) - { - m_genz80.z80_prgram = std::make_unique(0x2000); - membank("bank1")->set_base(m_genz80.z80_prgram.get()); - save_item(NAME(m_genz80.z80_is_reset)); - save_item(NAME(m_genz80.z80_has_bus)); - save_item(NAME(m_genz80.z80_bank_addr)); - save_pointer(NAME(m_genz80.z80_prgram), 0x2000); - } - - m_maincpu->set_tas_write_callback(*this, FUNC(md_base_state::megadriv_tas_callback)); - - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_3button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_3button)); -} - -void md_base_state::init_megadriv() -{ - megadriv_init_common(); - - // todo: move this to the device interface? - m_vdp->set_use_cram(1); - m_vdp->set_vdp_pal(false); - m_vdp->set_framerate(60); - m_vdp->set_total_scanlines(262); - - m_version_hi_nibble = 0xa0; // Export NTSC no-SCD -} - -void md_base_state::init_megadrij() -{ - megadriv_init_common(); - - // todo: move this to the device interface? - m_vdp->set_use_cram(1); - m_vdp->set_vdp_pal(false); - m_vdp->set_framerate(60); - m_vdp->set_total_scanlines(262); - - m_version_hi_nibble = 0x20; // JPN NTSC no-SCD -} - -void md_base_state::init_megadrie() -{ - megadriv_init_common(); - - // todo: move this to the device interface? - m_vdp->set_use_cram(1); - m_vdp->set_vdp_pal(true); - m_vdp->set_framerate(50); - m_vdp->set_total_scanlines(313); - - m_version_hi_nibble = 0xe0; // Export PAL no-SCD -} - -WRITE_LINE_MEMBER(md_base_state::screen_vblank_megadriv) -{ - if (m_io_reset.read_safe(0) & 0x01) - m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); - - // rising edge - if (state) - { - if (!m_vdp->m_use_alt_timing) - { - m_vdp->vdp_handle_eof(); - m_vdp->m_megadriv_scanline_timer->adjust(attotime::zero); - } - } -} diff --git a/src/mame/shared/megadriv.h b/src/mame/shared/megadriv.h deleted file mode 100644 index eb95bc8eedc..00000000000 --- a/src/mame/shared/megadriv.h +++ /dev/null @@ -1,151 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -#ifndef MAME_SHARED_MEGADRIV_H -#define MAME_SHARED_MEGADRIV_H - -#pragma once - -#include "cpu/m68000/m68000.h" -#include "cpu/z80/z80.h" -#include "sound/sn76496.h" -#include "sound/ymopn.h" -#include "video/315_5313.h" - -#define MASTER_CLOCK_NTSC 53693175 -#define MASTER_CLOCK_PAL 53203424 - -#define MD_CPU_REGION_SIZE 0x800000 - - -/*----------- defined in machine/megadriv.cpp -----------*/ - -INPUT_PORTS_EXTERN( md_common ); -INPUT_PORTS_EXTERN( megadriv ); -INPUT_PORTS_EXTERN( megadri6 ); -INPUT_PORTS_EXTERN( ssf2mdb ); -INPUT_PORTS_EXTERN( mk3mdb ); - - -class md_base_state : public driver_device -{ -public: - md_base_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_maincpu(*this,"maincpu"), - m_z80snd(*this,"genesis_snd_z80"), - m_ymsnd(*this,"ymsnd"), - m_scan_timer(*this, "md_scan_timer"), - m_vdp(*this,"gen_vdp"), - m_megadrive_ram(*this,"megadrive_ram"), - m_screen(*this,"megadriv"), - m_io_reset(*this, "RESET"), - m_megadrive_io_read_data_port_ptr(*this), - m_megadrive_io_write_data_port_ptr(*this) - { } - - required_device m_maincpu; - optional_device m_z80snd; - optional_device m_ymsnd; - optional_device m_scan_timer; - required_device m_vdp; - optional_shared_ptr m_megadrive_ram; - optional_device m_screen; - - optional_ioport m_io_reset; - ioport_port *m_io_pad_3b[4]; - ioport_port *m_io_pad_6b[4]; - - struct genesis_z80_vars - { - int z80_is_reset = 0; - int z80_has_bus = 0; - uint32_t z80_bank_addr = 0; - std::unique_ptr z80_prgram; - emu_timer *z80_run_timer = nullptr; - }; - - genesis_z80_vars m_genz80; - int m_version_hi_nibble; - - void init_megadrie(); - void init_megadriv(); - void init_megadrij(); - - uint8_t megadriv_68k_YM2612_read(offs_t offset, uint8_t mem_mask = ~0); - void megadriv_68k_YM2612_write(offs_t offset, uint8_t data, uint8_t mem_mask = ~0); - IRQ_CALLBACK_MEMBER(genesis_int_callback); - void megadriv_init_common(); - - void megadriv_z80_bank_w(uint16_t data); - void megadriv_68k_z80_bank_write(uint16_t data); - void megadriv_z80_z80_bank_w(uint8_t data); - uint16_t megadriv_68k_io_read(offs_t offset); - void megadriv_68k_io_write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t megadriv_68k_read_z80_ram(offs_t offset, uint16_t mem_mask = ~0); - void megadriv_68k_write_z80_ram(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t megadriv_68k_check_z80_bus(offs_t offset, uint16_t mem_mask = ~0); - void megadriv_68k_req_z80_bus(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - void megadriv_68k_req_z80_reset(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint8_t z80_read_68k_banked_data(offs_t offset); - void z80_write_68k_banked_data(offs_t offset, uint8_t data); - void megadriv_z80_vdp_write(offs_t offset, uint8_t data); - uint8_t megadriv_z80_vdp_read(offs_t offset); - uint8_t megadriv_z80_unmapped_read(); - TIMER_CALLBACK_MEMBER(megadriv_z80_run_state); - - /* Megadrive / Genesis has 3 I/O ports */ - emu_timer *m_io_timeout[3]; - int m_io_stage[3]; - uint8_t m_megadrive_io_data_regs[3]; - uint8_t m_megadrive_io_ctrl_regs[3]; - uint8_t m_megadrive_io_tx_regs[3]; - read8sm_delegate m_megadrive_io_read_data_port_ptr; - write16sm_delegate m_megadrive_io_write_data_port_ptr; - - WRITE_LINE_MEMBER(vdp_sndirqline_callback_genesis_z80); - WRITE_LINE_MEMBER(vdp_lv6irqline_callback_genesis_68k); - WRITE_LINE_MEMBER(vdp_lv4irqline_callback_genesis_68k); - - TIMER_CALLBACK_MEMBER( io_timeout_timer_callback ); - void megadrive_reset_io(); - uint8_t megadrive_io_read_data_port_6button(offs_t offset); - uint8_t megadrive_io_read_data_port_3button(offs_t offset); - uint8_t megadrive_io_read_ctrl_port(int portnum); - uint8_t megadrive_io_read_tx_port(int portnum); - uint8_t megadrive_io_read_rx_port(int portnum); - uint8_t megadrive_io_read_sctrl_port(int portnum); - - void megadrive_io_write_data_port_3button(offs_t offset, uint16_t data); - void megadrive_io_write_data_port_6button(offs_t offset, uint16_t data); - void megadrive_io_write_ctrl_port(int portnum, uint16_t data); - void megadrive_io_write_tx_port(int portnum, uint16_t data); - void megadrive_io_write_rx_port(int portnum, uint16_t data); - void megadrive_io_write_sctrl_port(int portnum, uint16_t data); - - void megadriv_stop_scanline_timer(); - - uint32_t screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(screen_vblank_megadriv); - - void megadriv_tas_callback(offs_t offset, uint8_t data); - - void megadriv_timers(machine_config &config); - void md_ntsc(machine_config &config); - void md2_ntsc(machine_config &config); - void md_pal(machine_config &config); - void md2_pal(machine_config &config); - void md_bootleg(machine_config &config); - - void dcat16_megadriv_base(machine_config &config); - void dcat16_megadriv_map(address_map &map); - void megadriv_map(address_map &map); - void megadriv_z80_io_map(address_map &map); - void megadriv_z80_map(address_map &map); - -protected: - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; -}; - -#endif // MAME_SHARED_MEGADRIV_H diff --git a/src/mame/shared/mie.cpp b/src/mame/shared/mie.cpp deleted file mode 100644 index 77639bd5ea8..00000000000 --- a/src/mame/shared/mie.cpp +++ /dev/null @@ -1,374 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert - -#include "emu.h" -#include "mie.h" -#include "maple-dc.h" - -// MIE aka Sega 315-6146, MAPLE-JVS bridge Z80-based MCU -// -// Todos: -// - ports 00-0f is identical to Sega 315-5338A/315-5649 I/O ICs -// (used in Sega H1, Model 2, etc). devicefication needed. -// -// - ports 10-15 and 20-25 is standard 8250/16xxx UARTs. -// -// - ports a0-af - external I/O 1, in JVS I/Os connected to NEC uPD71053 counter/timer -// -// - ports c0-cf - external I/O 2, not used -// in JVS I/Os can be connected to (unpopulated) 315-5296 I/O IC, if enabled by DIP switch -// -// - both memory and I/O address spaces can be directly accessed by host system (used in Hikaru) -// -// - Speed is all wrong - - -DEFINE_DEVICE_TYPE(MIE, mie_device, "mie", "Sega 315-6146 MIE") -DEFINE_DEVICE_TYPE(MIE_JVS, mie_jvs_device, "mie_jvs", "JVS (MIE)") - -void mie_device::mie_map(address_map &map) -{ - map(0x0000, 0x07ff).rom(); - map(0x0800, 0x6fff).r(FUNC(mie_device::read_ff)); - map(0x7000, 0x7002).rw(FUNC(mie_device::control_r), FUNC(mie_device::control_w)).mirror(0x07c0); - map(0x7003, 0x7003).rw(FUNC(mie_device::lreg_r), FUNC(mie_device::lreg_w)).mirror(0x07c0); - map(0x7004, 0x7023).rw(FUNC(mie_device::tbuf_r), FUNC(mie_device::tbuf_w)).mirror(0x07c0); - map(0x7024, 0x703f).r(FUNC(mie_device::read_00)).mirror(0x07c0); - map(0x7800, 0x7fff).r(FUNC(mie_device::read_78xx)); - map(0x8000, 0xffff).ram(); -} - -void mie_device::mie_port(address_map &map) -{ - map.global_mask(0xff); - map(0x00, 0x07).rw(FUNC(mie_device::gpio_r), FUNC(mie_device::gpio_w)); - map(0x08, 0x08).rw(FUNC(mie_device::gpiodir_r), FUNC(mie_device::gpiodir_w)); - map(0x0f, 0x0f).rw(FUNC(mie_device::adc_r), FUNC(mie_device::adc_w)); - map(0x10, 0x10).rw(FUNC(mie_device::jvs_r), FUNC(mie_device::jvs_w)); // ports 1x and 2x is standard UARTs, TODO handle it properly - map(0x12, 0x12).w(FUNC(mie_device::jvs_dest_w)); - map(0x13, 0x13).w(FUNC(mie_device::jvs_lcr_w)); - map(0x15, 0x15).r(FUNC(mie_device::jvs_status_r)); - map(0x30, 0x30).rw(FUNC(mie_device::irq_enable_r), FUNC(mie_device::irq_enable_w)); - map(0x50, 0x50).rw(FUNC(mie_device::maple_irqlevel_r), FUNC(mie_device::maple_irqlevel_w)); - map(0x70, 0x70).rw(FUNC(mie_device::irq_pending_r), FUNC(mie_device::irq_pending_w)); - map(0x90, 0x90).w(FUNC(mie_device::jvs_control_w)); - map(0x91, 0x91).r(FUNC(mie_device::jvs_sense_r)); -} - -ROM_START( mie ) - ROM_REGION( 0x800, "mie", 0 ) - ROM_LOAD( "315-6146.bin", 0x000, 0x800, CRC(9b197e35) SHA1(864d14d58732dd4e2ee538ccc71fa8df7013ba06)) -ROM_END - -const tiny_rom_entry *mie_device::device_rom_region() const -{ - return ROM_NAME(mie); -} - -void mie_device::device_add_mconfig(machine_config &config) -{ - Z80(config, cpu, DERIVED_CLOCK(1,1)); - cpu->set_addrmap(AS_PROGRAM, &mie_device::mie_map); - cpu->set_addrmap(AS_IO, &mie_device::mie_port); - cpu->set_irq_acknowledge_callback(FUNC(mie_device::irq_callback)); -} - -mie_jvs_device::mie_jvs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : jvs_host(mconfig, MIE_JVS, tag, owner, clock) -{ -} - -mie_device::mie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : maple_device(mconfig, MIE, tag, owner, clock) - , cpu(*this, "mie") - , jvs(*this, finder_base::DUMMY_TAG) - , gpio_port(*this, {finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG}) -{ -} - -void mie_device::device_start() -{ - maple_device::device_start(); - timer = timer_alloc(FUNC(mie_device::update_irq_reply), this); - - save_item(NAME(gpiodir)); - save_item(NAME(gpio_val)); - save_item(NAME(irq_enable)); - save_item(NAME(irq_pending)); - save_item(NAME(maple_irqlevel)); - - // patch out MIE RAM test - // TODO: figure out why SH4 code doesn't wait long enough for internal firmware's RAM test completed in the case of reset - uint32_t *rom = (uint32_t*)memregion("mie")->base(); - rom[0x144/4] = 0x0001d8c3; -} - -void mie_device::device_reset() -{ - lreg = 0; - control = 0; - jvs_control = 0; - jvs_dest = 0; - jvs_rpos = 0; - memset(gpio_val, 0, sizeof(gpio_val)); - gpiodir = 0xff; - maple_irqlevel = 0xff; - irq_enable = irq_pending = 0; - cpu->reset(); - timer->adjust(attotime::never); - memset(tbuf, 0, sizeof(tbuf)); -} - -uint8_t mie_device::control_r(offs_t offset) -{ - return control >> (8*offset); -} - -void mie_device::control_w(offs_t offset, uint8_t data) -{ - uint32_t prev_control = control; - int shift = offset*8; - control = (control & ~(255 << shift)) | (data << shift); - - if((!(prev_control & CTRL_TXB) && (control & CTRL_TXB)) || - (!(prev_control & CTRL_CTXB) && (control & CTRL_CTXB))) { - control &= ~(CTRL_TFB|CTRL_RXB|CTRL_RFB|CTRL_BFOV|CTRL_EMP); - reply_size = lreg+1; - if(reply_size > TBUF_SIZE) - reply_size = TBUF_SIZE; - memcpy(reply_buffer, tbuf, reply_size*4); - reply_partial = !(control & CTRL_ENDP); - - timer->adjust(attotime::from_usec(20)); - } -} - -TIMER_CALLBACK_MEMBER(mie_device::update_irq_reply) -{ - if(control & CTRL_RXB) { - control &= ~CTRL_RXB; - control |= CTRL_RFB; - raise_irq(maple_irqlevel); - } - if(control & (CTRL_TXB|CTRL_CTXB)) { - reply_ready(0); - lreg -= reply_size; - if(reply_partial) { - control &= ~CTRL_CTXB; - control |= CTRL_EMP; - } else { - control &= ~(CTRL_TXB|CTRL_CTXB); - control |= CTRL_TFB|CTRL_EMP; - } - } - if(control & CTRL_HRES) { - raise_irq(maple_irqlevel); - } -} - -void mie_device::maple_w(const uint32_t *data, uint32_t in_size) -{ - memcpy(tbuf, data, in_size*4); - lreg = in_size-1; - // currently not known how/then CTRL_HRES is cleared after reset, lets clear it at packet receive - control &= ~(CTRL_HRES|CTRL_TXB|CTRL_TFB|CTRL_RFB|CTRL_BFOV); - control |= CTRL_RXB; - - timer->adjust(attotime::from_usec(20)); -} - -uint8_t mie_device::read_ff() -{ - return 0xff; -} - -uint8_t mie_device::read_00() -{ - return 0x00; -} - -uint8_t mie_device::read_78xx(offs_t offset) -{ - // Internal rom tests (7800) & 80 and jumps to 8010 if non-zero - // What we return is what a memdump sees on a naomi2 board - return offset & 4 ? 0xff : 0x00; -} - -uint8_t mie_device::gpio_r(offs_t offset) -{ - if(gpiodir & (1 << offset)) - return gpio_port[offset] ? gpio_port[offset]->read() : 0xff; - else - return gpio_val[offset]; -} - -void mie_device::gpio_w(offs_t offset, uint8_t data) -{ - gpio_val[offset] = data; - if(!(gpiodir & (1 << offset)) && gpio_port[offset]) - gpio_port[offset]->write(data, 0xff); -} - -uint8_t mie_device::gpiodir_r() -{ - return gpiodir; -} - -void mie_device::gpiodir_w(uint8_t data) -{ - gpiodir = data; -} - -uint8_t mie_device::adc_r() -{ - return 0; -} - -void mie_device::adc_w(uint8_t data) -{ -} - -uint8_t mie_device::irq_enable_r() -{ - return irq_enable; -} - -void mie_device::irq_enable_w(uint8_t data) -{ - irq_enable = data; - recalc_irq(); -} - -uint8_t mie_device::maple_irqlevel_r() -{ - return maple_irqlevel; -} - -void mie_device::maple_irqlevel_w(uint8_t data) -{ - maple_irqlevel = data; -} - -uint8_t mie_device::irq_pending_r() -{ - return irq_pending; -} - -void mie_device::irq_pending_w(uint8_t data) -{ - irq_pending = data; - recalc_irq(); -} - -void mie_device::recalc_irq() -{ - cpu->set_input_line(0, irq_enable & irq_pending & 0x7f ? ASSERT_LINE : CLEAR_LINE); -} - -IRQ_CALLBACK_MEMBER(mie_device::irq_callback) -{ - if(!(irq_enable & irq_pending & 0x7f)) - throw emu_fatalerror("MIE irq callback called with enable=%02x, pending=%02x", irq_enable, irq_pending); - - int level = -1; - for(level = 0; level < 7; level++) - if((irq_enable & irq_pending) & (1 << level)) - break; - - irq_pending &= ~(1 << level); - recalc_irq(); - return 0xf2+2*level; -} - -void mie_device::raise_irq(int level) -{ - if(level>=0 && level<7) { - irq_pending |= 1<> 2] >> (8*(offset & 3)); -} - -void mie_device::tbuf_w(offs_t offset, uint8_t data) -{ - int shift = (offset & 3)*8; - tbuf[offset >> 2] = (tbuf[offset >> 2] & ~(255 << shift)) | (data << shift); -} - -uint8_t mie_device::lreg_r() -{ - return lreg; -} - -void mie_device::lreg_w(uint8_t data) -{ - lreg = data; -} - -uint8_t mie_device::jvs_r() -{ - if(jvs_lcr & 0x80) - return 0; - - const uint8_t *buf; - uint32_t size; - jvs->get_encoded_reply(buf, size); - if(jvs_rpos >= size) - return 0; - return buf[jvs_rpos++]; -} - -void mie_device::jvs_w(uint8_t data) -{ - if(jvs_lcr & 0x80) - return; - - jvs->push(data); -} - -void mie_device::jvs_dest_w(uint8_t data) -{ - jvs_dest = data; -} - -uint8_t mie_device::jvs_status_r() -{ - // 01 = ready for reading - // 20 = ready for writing - // 40 = sending done - const uint8_t *buf; - uint32_t size; - jvs->get_encoded_reply(buf, size); - return 0x60 | (jvs_rpos < size ? 1 : 0); -} - -void mie_device::jvs_control_w(uint8_t data) -{ - if((jvs_control & 1) && !(data & 1)) { - jvs->commit_encoded(); - jvs_rpos = 0; - } - jvs_control = data; -} - -void mie_device::jvs_lcr_w(uint8_t data) -{ - jvs_lcr = data; -} - -uint8_t mie_device::jvs_sense_r() -{ - return 0x8c | (jvs->get_address_set_line() ? 2 : 0) | (jvs->get_presence_line() ? 0 : 1); -} - -void mie_device::maple_reset() -{ - control &= ~(CTRL_RXB|CTRL_TXB|CTRL_TFB|CTRL_RFB|CTRL_BFOV); - control |= CTRL_HRES; - - timer->adjust(attotime::from_usec(20)); -} diff --git a/src/mame/shared/mie.h b/src/mame/shared/mie.h deleted file mode 100644 index 57792269ec0..00000000000 --- a/src/mame/shared/mie.h +++ /dev/null @@ -1,142 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert -#ifndef MAME_MACHINE_MIE_H -#define MAME_MACHINE_MIE_H - -#pragma once - -#include "mapledev.h" - -#include "cpu/z80/z80.h" -#include "machine/eepromser.h" -#include "machine/jvshost.h" - - -class mie_jvs_device; - -// ======================> mie_device - -class mie_device : public maple_device -{ -public: - template - mie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&host_tag, int host_port, U &&jvs_tag) - : mie_device(mconfig, tag, owner, clock) - { - host.set_tag(std::forward(host_tag)); - set_host_port(host_port); - jvs.set_tag(std::forward(jvs_tag)); - } - - mie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - template - void set_gpio_name(T &&gpio_port_tag) { gpio_port[Which].set_tag(std::forward(gpio_port_tag)); } - template - void set_gpio_names(T &&first_tag, U &&... other_tags) - { - set_gpio_name(std::forward(first_tag)); - set_gpio_names(std::forward(other_tags)...); - } - - uint8_t control_r(offs_t offset); - void control_w(offs_t offset, uint8_t data); - uint8_t lreg_r(); - void lreg_w(uint8_t data); - uint8_t tbuf_r(offs_t offset); - void tbuf_w(offs_t offset, uint8_t data); - uint8_t gpio_r(offs_t offset); - void gpio_w(offs_t offset, uint8_t data); - uint8_t gpiodir_r(); - void gpiodir_w(uint8_t data); - uint8_t adc_r(); - void adc_w(uint8_t data); - - uint8_t irq_enable_r(); - void irq_enable_w(uint8_t data); - uint8_t maple_irqlevel_r(); - void maple_irqlevel_w(uint8_t data); - uint8_t irq_pending_r(); - void irq_pending_w(uint8_t data); - - uint8_t jvs_r(); - void jvs_w(uint8_t data); - void jvs_dest_w(uint8_t data); - uint8_t jvs_status_r(); - void jvs_control_w(uint8_t data); - uint8_t jvs_sense_r(); - void jvs_lcr_w(uint8_t data); - - uint8_t read_ff(); - uint8_t read_00(); - uint8_t read_78xx(offs_t offset); - - void maple_w(const uint32_t *data, uint32_t in_size) override; - virtual void maple_reset() override; - - void mie_map(address_map &map); - void mie_port(address_map &map); - -protected: - template void set_gpio_names() { } - - // device-level overrides - 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; - - TIMER_CALLBACK_MEMBER(update_irq_reply); - -private: - enum { TBUF_SIZE = 8 }; - - enum { - CTRL_TXB = 0x000001, // Start transmit - CTRL_CTXB = 0x000002, // Continue transmit flag (when doing multipart) - CTRL_ENDP = 0x000004, // Add an end pattern - CTRL_EMP = 0x000100, // Empty flag - CTRL_PERR = 0x000200, // Parity error - CTRL_BFOV = 0x000800, // Set when overflow, cleared to 0 when starting send/receive - CTRL_RXB = 0x001000, // Receiving - CTRL_RFB = 0x002000, // Receive done - CTRL_TFB = 0x004000, // Transmit done - CTRL_HRES = 0x008000 // Reset pattern received - }; - - // internal state - required_device cpu; - emu_timer *timer = nullptr; - required_device jvs; - optional_ioport_array<8> gpio_port; - - uint32_t tbuf[TBUF_SIZE]{}; - uint32_t control = 0, lreg = 0, jvs_rpos = 0; - uint8_t gpiodir = 0, gpio_val[8]{}; - uint8_t irq_enable = 0, irq_pending = 0, maple_irqlevel = 0; - uint8_t jvs_control = 0, jvs_dest = 0; - uint8_t jvs_lcr = 0; - - void raise_irq(int level); - void recalc_irq(); - IRQ_CALLBACK_MEMBER(irq_callback); -}; - -// Trampoline class, required for device discovery -class mie_jvs_device : public jvs_host -{ -public: - friend class mie_device; - - // construction/destruction - mie_jvs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - - -// device type definition -DECLARE_DEVICE_TYPE(MIE, mie_device) -DECLARE_DEVICE_TYPE(MIE_JVS, mie_jvs_device) - -#endif // MAME_MACHINE_MIE_H diff --git a/src/mame/shared/naomig1.cpp b/src/mame/shared/naomig1.cpp deleted file mode 100644 index 059339e08ed..00000000000 --- a/src/mame/shared/naomig1.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert - -#include "emu.h" -#include "naomig1.h" - -void naomi_g1_device::amap(address_map &map) -{ - map(0x04, 0x07).rw(FUNC(naomi_g1_device::sb_gdstar_r), FUNC(naomi_g1_device::sb_gdstar_w)); - map(0x08, 0x0b).rw(FUNC(naomi_g1_device::sb_gdlen_r), FUNC(naomi_g1_device::sb_gdlen_w)); - map(0x0c, 0x0f).rw(FUNC(naomi_g1_device::sb_gddir_r), FUNC(naomi_g1_device::sb_gddir_w)); - map(0x14, 0x17).rw(FUNC(naomi_g1_device::sb_gden_r), FUNC(naomi_g1_device::sb_gden_w)); - map(0x18, 0x1b).rw(FUNC(naomi_g1_device::sb_gdst_r), FUNC(naomi_g1_device::sb_gdst_w)); - map(0x80, 0x83).w(FUNC(naomi_g1_device::sb_g1rrc_w)); - map(0x84, 0x87).w(FUNC(naomi_g1_device::sb_g1rwc_w)); - map(0x88, 0x8b).w(FUNC(naomi_g1_device::sb_g1frc_w)); - map(0x8c, 0x8f).w(FUNC(naomi_g1_device::sb_g1fwc_w)); - map(0x90, 0x93).w(FUNC(naomi_g1_device::sb_g1crc_w)); - map(0x94, 0x97).w(FUNC(naomi_g1_device::sb_g1cwc_w)); - map(0xa0, 0xa3).w(FUNC(naomi_g1_device::sb_g1gdrc_w)); - map(0xa4, 0xa7).w(FUNC(naomi_g1_device::sb_g1gdwc_w)); - map(0xb0, 0xb3).r(FUNC(naomi_g1_device::sb_g1sysm_r)); - map(0xb4, 0xb7).w(FUNC(naomi_g1_device::sb_g1crdyc_w)); - map(0xb8, 0xbb).w(FUNC(naomi_g1_device::sb_gdapro_w)); - map(0xf4, 0xf7).r(FUNC(naomi_g1_device::sb_gdstard_r)); - map(0xf8, 0xfb).r(FUNC(naomi_g1_device::sb_gdlend_r)); -} - -naomi_g1_device::naomi_g1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) - , irq_cb(*this) - , ext_irq_cb(*this) - , reset_out_cb(*this) -{ -} - -void naomi_g1_device::device_start() -{ - timer = timer_alloc(FUNC(naomi_g1_device::trigger_gdrom_irq), this); - irq_cb.resolve_safe(); - ext_irq_cb.resolve_safe(); - reset_out_cb.resolve_safe(); - - save_item(NAME(gdstar)); - save_item(NAME(gdlen)); - save_item(NAME(gddir)); - save_item(NAME(gden)); - save_item(NAME(gdst)); -} - -void naomi_g1_device::device_reset() -{ - gdstar = 0; - gdlen = 0; - gddir = 0; - gden = 0; - gdst = 0; - set_ext_irq(CLEAR_LINE); -} - -TIMER_CALLBACK_MEMBER(naomi_g1_device::trigger_gdrom_irq) -{ - if(!gdst) - return; - gdst = 0; - irq_cb(DMA_GDROM_IRQ); -} - -uint32_t naomi_g1_device::sb_gdstar_r() -{ - return gdstar; -} - -void naomi_g1_device::sb_gdstar_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&gdstar); - logerror("G1: gdstar_w %08x @ %08x\n", data, mem_mask); -} - -uint32_t naomi_g1_device::sb_gdlen_r() -{ - return gdlen; -} - -void naomi_g1_device::sb_gdlen_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&gdlen); - logerror("G1: gdlen_w %08x @ %08x\n", data, mem_mask); -} - -uint32_t naomi_g1_device::sb_gddir_r() -{ - return gddir; -} - -void naomi_g1_device::sb_gddir_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&gddir); - gddir &= 1; - logerror("G1: gddir_w %08x @ %08x\n", data, mem_mask); -} - -uint32_t naomi_g1_device::sb_gden_r() -{ - return gden; -} - -void naomi_g1_device::sb_gden_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&gden); - gden &= 1; - logerror("G1: gden_w %08x @ %08x\n", data, mem_mask); -} - -uint32_t naomi_g1_device::sb_gdst_r() -{ - return gdst; -} - -void naomi_g1_device::sb_gdst_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - uint32_t old = gdst; - COMBINE_DATA(&gdst); - gdst &= 1; - logerror("G1: gdst_w %08x @ %08x\n", data, mem_mask); - if(!old && gdst && gden) { - // DMA starts - - uint32_t adr = gdstar; - uint32_t len = gdlen; - - // Deunan says round up to 32, doc says complete with zeroes. - // Virtua Tennis requires one of the two to boot - // We'll go with DK for now. - // - // In any case, low bit is ignored - len = (len + 30) & ~30; - - bool to_mainram = true; - while(len) { - uint8_t *base; - uint32_t limit = len; - dma_get_position(base, limit, to_mainram); - - if(!limit) - break; - uint32_t tlen = limit > len ? len : limit; - dma(base, adr, tlen, to_mainram); - adr += tlen; - len -= tlen; - dma_advance(tlen); - } - - while(len && to_mainram) { - unsigned char zero[32]; - memset(zero, 0, sizeof(zero)); - uint32_t tlen = len > 32 ? 32 : len; - dma(zero, adr, tlen, to_mainram); - adr += tlen; - len -= tlen; - } - - /* 12x * 75 Hz = 0,00(1) secs per sector */ - /* TODO: make DMA to be single step */ - timer->adjust(attotime::from_usec(1111*(gdlen/2048))); - } -} - -void naomi_g1_device::sb_g1rrc_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: g1rrc_w %08x @ %08x\n", data, mem_mask); -} - -void naomi_g1_device::sb_g1rwc_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: g1rwc_w %08x @ %08x\n", data, mem_mask); -} - -void naomi_g1_device::sb_g1crc_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: g1crc_w %08x @ %08x\n", data, mem_mask); -} - -void naomi_g1_device::sb_g1cwc_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: g1cwc_w %08x @ %08x\n", data, mem_mask); -} - -void naomi_g1_device::sb_g1frc_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: g1frc_w %08x @ %08x\n", data, mem_mask); -} - -void naomi_g1_device::sb_g1fwc_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: g1fwc_w %08x @ %08x\n", data, mem_mask); -} - -void naomi_g1_device::sb_g1gdrc_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: g1gdrc_w %08x @ %08x\n", data, mem_mask); -} - -void naomi_g1_device::sb_g1gdwc_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: g1gdwc_w %08x @ %08x\n", data, mem_mask); -} - -uint32_t naomi_g1_device::sb_g1sysm_r(offs_t offset, uint32_t mem_mask) -{ - logerror("G1: g1sysm_r @ %08x\n", mem_mask); - return 0; -} - -void naomi_g1_device::sb_g1crdyc_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: g1crdyc_w %08x @ %08x\n", data, mem_mask); -} - -void naomi_g1_device::sb_gdapro_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - logerror("G1: gdapro_w %08x @ %08x\n", data, mem_mask); -} - -uint32_t naomi_g1_device::sb_gdstard_r(offs_t offset, uint32_t mem_mask) -{ - logerror("G1: gdstard_r @ %08x\n", mem_mask); - return 0; -} - -uint32_t naomi_g1_device::sb_gdlend_r(offs_t offset, uint32_t mem_mask) -{ - logerror("G1: gdlend_r @ %08x\n", mem_mask); - return 0; -} - -void naomi_g1_device::dma(void *dma_ptr, uint32_t main_adr, uint32_t size, bool to_mainram) -{ - if(!_dma_cb.isnull()) - _dma_cb(main_adr, dma_ptr, size >> 5, 32, to_mainram); -} diff --git a/src/mame/shared/naomig1.h b/src/mame/shared/naomig1.h deleted file mode 100644 index 924c3712aa5..00000000000 --- a/src/mame/shared/naomig1.h +++ /dev/null @@ -1,79 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert -#ifndef MAME_MACHINE_NAOMIG1_H -#define MAME_MACHINE_NAOMIG1_H - -#pragma once - -#include "cpu/sh/sh4.h" - -class naomi_g1_device : public device_t -{ -public: - enum { - DMA_GDROM_IRQ - }; - - typedef delegate dma_cb; - - auto irq_callback() { return irq_cb.bind(); } - auto ext_irq_callback() { return ext_irq_cb.bind(); } - auto reset_out_callback() { return reset_out_cb.bind(); } - void set_dma_cb(dma_cb cb) { _dma_cb = cb; } - - void amap(address_map &map); // for range 0x005f7400-0x005f74ff - virtual void submap(address_map &map) = 0; // for range 0x005f7000-0x005f70ff - - uint32_t sb_gdstar_r(); // 5f7404 - void sb_gdstar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7404 - uint32_t sb_gdlen_r(); // 5f7408 - void sb_gdlen_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7408 - uint32_t sb_gddir_r(); // 5f740c - void sb_gddir_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f740c - uint32_t sb_gden_r(); // 5f7414 - void sb_gden_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7414 - uint32_t sb_gdst_r(); // 5f7418 - void sb_gdst_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7418 - - void sb_g1rrc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7480 - void sb_g1rwc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7484 - void sb_g1frc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7488 - void sb_g1fwc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f748c - void sb_g1crc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7490 - void sb_g1cwc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f7494 - void sb_g1gdrc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f74a0 - void sb_g1gdwc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f74a4 - uint32_t sb_g1sysm_r(offs_t offset, uint32_t mem_mask = ~0); // 5f74b0 - void sb_g1crdyc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f74b4 - void sb_gdapro_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); // 5f74b8 - - uint32_t sb_gdstard_r(offs_t offset, uint32_t mem_mask = ~0); // 5f74f4 - uint32_t sb_gdlend_r(offs_t offset, uint32_t mem_mask = ~0); // 5f74f8 - -protected: - naomi_g1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_reset() override; - - virtual void dma_get_position(uint8_t *&base, uint32_t &limit, bool to_maincpu) = 0; - virtual void dma_advance(uint32_t size) = 0; - - void set_ext_irq(int state) { ext_irq_cb(state); } - void set_reset_out() { reset_out_cb(ASSERT_LINE); } - - TIMER_CALLBACK_MEMBER(trigger_gdrom_irq); - -private: - uint32_t gdstar, gdlen, gddir, gden, gdst; - - emu_timer *timer; - devcb_write8 irq_cb; - devcb_write_line ext_irq_cb; - devcb_write_line reset_out_cb; - dma_cb _dma_cb; - - void dma(void *dma_ptr, uint32_t main_adr, uint32_t size, bool to_mainram); -}; - -#endif // MAME_MACHINE_NAOMIG1_H diff --git a/src/mame/shared/powervr2.cpp b/src/mame/shared/powervr2.cpp deleted file mode 100644 index 476965b84f4..00000000000 --- a/src/mame/shared/powervr2.cpp +++ /dev/null @@ -1,4117 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert -/* - Dreamcast video emulation - - TODO: - - Needs break-down into sub-devices, as a generic rule of thumb - TA is Holly/CLX implementation specific while CORE is ISP/TSP only. - This will be particularly useful for PVR PMX implementations - (atvtrack.cpp and aristmk6.cpp); - - Remove dc_state readbacks from here; - - Better abstraction of timers; - -*/ - -#include "emu.h" -#include "powervr2.h" -#include "dc.h" - -#include "cpu/sh/sh4.h" -#include "video/rgbutil.h" -#include "rendutil.h" - -#define LOG_WARN (1U << 1) // Show warnings -#define LOG_TA_CMD (1U << 2) // Show TA CORE commands -#define LOG_TA_FIFO (1U << 3) // Show TA FIFO polygon entries -#define LOG_TA_TILE (1U << 4) // Show TA tile entries -#define LOG_PVR_DMA (1U << 5) // Show PVR-DMA access -#define LOG_IRQ (1U << 6) // Show irq triggers - -#define VERBOSE (LOG_WARN | LOG_PVR_DMA) - -#include "logmacro.h" - -#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) -#define LOGTACMD(...) LOGMASKED(LOG_TA_CMD, __VA_ARGS__) -#define LOGTAFIFO(...) LOGMASKED(LOG_TA_FIFO, __VA_ARGS__) -#define LOGTATILE(...) LOGMASKED(LOG_TA_TILE, __VA_ARGS__) -#define LOGPVRDMA(...) LOGMASKED(LOG_PVR_DMA, __VA_ARGS__) -#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__) - -#define LIVE_YUV_VIEW 0 - - -DEFINE_DEVICE_TYPE(POWERVR2, powervr2_device, "powervr2", "PowerVR 2") - -void powervr2_device::ta_map(address_map &map) -{ - map(0x0000, 0x0003).r(FUNC(powervr2_device::id_r)); - map(0x0004, 0x0007).r(FUNC(powervr2_device::revision_r)); - map(0x0008, 0x000b).rw(FUNC(powervr2_device::softreset_r), FUNC(powervr2_device::softreset_w)); - map(0x0014, 0x0017).w(FUNC(powervr2_device::startrender_w)); -// 18 = test select - map(0x0020, 0x0023).rw(FUNC(powervr2_device::param_base_r), FUNC(powervr2_device::param_base_w)); - map(0x002c, 0x002f).rw(FUNC(powervr2_device::region_base_r), FUNC(powervr2_device::region_base_w)); -// 30 = span sort cfg - map(0x0040, 0x0043).rw(FUNC(powervr2_device::vo_border_col_r), FUNC(powervr2_device::vo_border_col_w)); - map(0x0044, 0x0047).rw(FUNC(powervr2_device::fb_r_ctrl_r), FUNC(powervr2_device::fb_r_ctrl_w)); - map(0x0048, 0x004b).rw(FUNC(powervr2_device::fb_w_ctrl_r), FUNC(powervr2_device::fb_w_ctrl_w)); - map(0x004c, 0x004f).rw(FUNC(powervr2_device::fb_w_linestride_r), FUNC(powervr2_device::fb_w_linestride_w)); - map(0x0050, 0x0053).rw(FUNC(powervr2_device::fb_r_sof1_r), FUNC(powervr2_device::fb_r_sof1_w)); - map(0x0054, 0x0057).rw(FUNC(powervr2_device::fb_r_sof2_r), FUNC(powervr2_device::fb_r_sof2_w)); - map(0x005c, 0x005f).rw(FUNC(powervr2_device::fb_r_size_r), FUNC(powervr2_device::fb_r_size_w)); - map(0x0060, 0x0063).rw(FUNC(powervr2_device::fb_w_sof1_r), FUNC(powervr2_device::fb_w_sof1_w)); - map(0x0064, 0x0067).rw(FUNC(powervr2_device::fb_w_sof2_r), FUNC(powervr2_device::fb_w_sof2_w)); - map(0x0068, 0x006b).rw(FUNC(powervr2_device::fb_x_clip_r), FUNC(powervr2_device::fb_x_clip_w)); - map(0x006c, 0x006f).rw(FUNC(powervr2_device::fb_y_clip_r), FUNC(powervr2_device::fb_y_clip_w)); -// 74 = fpu_shad_scale -// 78 = fpu_cull_val - map(0x007c, 0x007f).rw(FUNC(powervr2_device::fpu_param_cfg_r), FUNC(powervr2_device::fpu_param_cfg_w)); -// 80 = half_offset -// 84 = fpu_perp_val -// 88 = isp_backgnd_d - map(0x008c, 0x008f).rw(FUNC(powervr2_device::isp_backgnd_t_r), FUNC(powervr2_device::isp_backgnd_t_w)); -// 98 = isp_feed_cfg -// a0 = sdram_refresh -// a4 = sdram_arb_cfg -// a8 = sdram_cfg -// b0 = fog_col_ram -// b4 = fog_col_vert -// b8 = fog_density -// bc = fog_clamp_max -// c0 = fog_clamp_min -// c4 = spg_trigger_pos - map(0x00c8, 0x00cb).rw(FUNC(powervr2_device::spg_hblank_int_r), FUNC(powervr2_device::spg_hblank_int_w)); - map(0x00cc, 0x00cf).rw(FUNC(powervr2_device::spg_vblank_int_r), FUNC(powervr2_device::spg_vblank_int_w)); - map(0x00d0, 0x00d3).rw(FUNC(powervr2_device::spg_control_r), FUNC(powervr2_device::spg_control_w)); - map(0x00d4, 0x00d7).rw(FUNC(powervr2_device::spg_hblank_r), FUNC(powervr2_device::spg_hblank_w)); - map(0x00d8, 0x00db).rw(FUNC(powervr2_device::spg_load_r), FUNC(powervr2_device::spg_load_w)); - map(0x00dc, 0x00df).rw(FUNC(powervr2_device::spg_vblank_r), FUNC(powervr2_device::spg_vblank_w)); - map(0x00e0, 0x00e3).rw(FUNC(powervr2_device::spg_width_r), FUNC(powervr2_device::spg_width_w)); - map(0x00e4, 0x00e7).rw(FUNC(powervr2_device::text_control_r), FUNC(powervr2_device::text_control_w)); - map(0x00e8, 0x00eb).rw(FUNC(powervr2_device::vo_control_r), FUNC(powervr2_device::vo_control_w)); - map(0x00ec, 0x00ef).rw(FUNC(powervr2_device::vo_startx_r), FUNC(powervr2_device::vo_startx_w)); - map(0x00f0, 0x00f3).rw(FUNC(powervr2_device::vo_starty_r), FUNC(powervr2_device::vo_starty_w)); -// f4 = scaler_ctl - map(0x0108, 0x010b).rw(FUNC(powervr2_device::pal_ram_ctrl_r), FUNC(powervr2_device::pal_ram_ctrl_w)); - map(0x010c, 0x010f).r(FUNC(powervr2_device::spg_status_r)); -// 110 = fb_burstctrl -// 118 = y_coeff -// 11c = pt_alpha_ref - - map(0x0124, 0x0127).rw(FUNC(powervr2_device::ta_ol_base_r), FUNC(powervr2_device::ta_ol_base_w)); - map(0x0128, 0x012b).rw(FUNC(powervr2_device::ta_isp_base_r), FUNC(powervr2_device::ta_isp_base_w)); - map(0x012c, 0x012f).rw(FUNC(powervr2_device::ta_ol_limit_r), FUNC(powervr2_device::ta_ol_limit_w)); - map(0x0130, 0x0133).rw(FUNC(powervr2_device::ta_isp_limit_r), FUNC(powervr2_device::ta_isp_limit_w)); - map(0x0134, 0x0137).r(FUNC(powervr2_device::ta_next_opb_r)); - map(0x0138, 0x013b).r(FUNC(powervr2_device::ta_itp_current_r)); -// 13c = ta_glob_tile_clip - map(0x0140, 0x0143).rw(FUNC(powervr2_device::ta_alloc_ctrl_r), FUNC(powervr2_device::ta_alloc_ctrl_w)); - map(0x0144, 0x0147).rw(FUNC(powervr2_device::ta_list_init_r), FUNC(powervr2_device::ta_list_init_w)); - map(0x0148, 0x014b).rw(FUNC(powervr2_device::ta_yuv_tex_base_r), FUNC(powervr2_device::ta_yuv_tex_base_w)); - map(0x014c, 0x014f).rw(FUNC(powervr2_device::ta_yuv_tex_ctrl_r), FUNC(powervr2_device::ta_yuv_tex_ctrl_w)); - map(0x0150, 0x0153).r(FUNC(powervr2_device::ta_yuv_tex_cnt_r)); - map(0x0160, 0x0163).w(FUNC(powervr2_device::ta_list_cont_w)); - map(0x0164, 0x0167).rw(FUNC(powervr2_device::ta_next_opb_init_r), FUNC(powervr2_device::ta_next_opb_init_w)); - - map(0x0200, 0x03ff).rw(FUNC(powervr2_device::fog_table_r), FUNC(powervr2_device::fog_table_w)); - map(0x1000, 0x1fff).rw(FUNC(powervr2_device::palette_r), FUNC(powervr2_device::palette_w)); -} - -void powervr2_device::pd_dma_map(address_map &map) -{ - map(0x00, 0x03).rw(FUNC(powervr2_device::sb_pdstap_r), FUNC(powervr2_device::sb_pdstap_w)); - map(0x04, 0x07).rw(FUNC(powervr2_device::sb_pdstar_r), FUNC(powervr2_device::sb_pdstar_w)); - map(0x08, 0x0b).rw(FUNC(powervr2_device::sb_pdlen_r), FUNC(powervr2_device::sb_pdlen_w)); - map(0x0c, 0x0f).rw(FUNC(powervr2_device::sb_pddir_r), FUNC(powervr2_device::sb_pddir_w)); - map(0x10, 0x13).rw(FUNC(powervr2_device::sb_pdtsel_r), FUNC(powervr2_device::sb_pdtsel_w)); - map(0x14, 0x17).rw(FUNC(powervr2_device::sb_pden_r), FUNC(powervr2_device::sb_pden_w)); - map(0x18, 0x1b).rw(FUNC(powervr2_device::sb_pdst_r), FUNC(powervr2_device::sb_pdst_w)); - map(0x80, 0x83).rw(FUNC(powervr2_device::sb_pdapro_r), FUNC(powervr2_device::sb_pdapro_w)); -} - -const int powervr2_device::pvr_parconfseq[] = {1,2,3,2,3,4,5,6,5,6,7,8,9,10,11,12,13,14,13,14,15,16,17,16,17,0,0,0,0,0,18,19,20,19,20,21,22,23,22,23}; -const int powervr2_device::pvr_wordsvertex[24] = {8,8,8,8,8,16,16,8,8,8, 8, 8,8,8,8,8,16,16, 8,16,16,8,16,16}; -const int powervr2_device::pvr_wordspolygon[24] = {8,8,8,8,8, 8, 8,8,8,8,16,16,8,8,8,8, 8, 8,16,16,16,8, 8, 8}; - -inline int32_t powervr2_device::clamp(int32_t in, int32_t min, int32_t max) -{ - if(in < min) return min; - if(in > max) return max; - return in; -} - -// Perform a standard bilinear filter across four pixels -inline uint32_t powervr2_device::bilinear_filter(uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, float u, float v) -{ - const uint32_t ui = (u * 256.0f); - const uint32_t vi = (v * 256.0f); - return rgbaint_t::bilinear_filter(c0, c1, c3, c2, ui, vi); -} - -// Multiply with alpha value in bits 31-24 -inline uint32_t powervr2_device::bla(uint32_t c, uint32_t a) -{ - a = a >> 24; - return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00); -} - -// Multiply with 1-alpha value in bits 31-24 -inline uint32_t powervr2_device::blia(uint32_t c, uint32_t a) -{ - a = 0x100 - (a >> 24); - return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00); -} - -// Per-component multiply with color value -inline uint32_t powervr2_device::blc(uint32_t c1, uint32_t c2) -{ - uint32_t cr = - (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) >> 8) | - (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0xff000000) >> 16); - c1 >>= 16; - c2 >>= 16; - cr |= - (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) << 8) | - (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0xff000000)); - return cr; -} - -// Per-component multiply with 1-color value -inline uint32_t powervr2_device::blic(uint32_t c1, uint32_t c2) -{ - uint32_t cr = - (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) >> 8) | - (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0xff000000) >> 16); - c1 >>= 16; - c2 >>= 16; - cr |= - (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) << 8) | - (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0xff000000)); - return cr; -} - -// Add two colors with saturation -inline uint32_t powervr2_device::bls(uint32_t c1, uint32_t c2) -{ - uint32_t cr1, cr2; - cr1 = (c1 & 0x00ff00ff) + (c2 & 0x00ff00ff); - if(cr1 & 0x0000ff00) - cr1 = (cr1 & 0xffff00ff) | 0x000000ff; - if(cr1 & 0xff000000) - cr1 = (cr1 & 0x00ffffff) | 0x00ff0000; - - cr2 = ((c1 >> 8) & 0x00ff00ff) + ((c2 >> 8) & 0x00ff00ff); - if(cr2 & 0x0000ff00) - cr2 = (cr2 & 0xffff00ff) | 0x000000ff; - if(cr2 & 0xff000000) - cr2 = (cr2 & 0x00ffffff) | 0x00ff0000; - return cr1|(cr2 << 8); -} - -/* - * Add two colors with saturation, not including the alpha channel - * The only difference between this function and bls is that bls does not - * ignore alpha. The alpha will be cleared to zero by this instruction - */ -inline uint32_t powervr2_device::bls24(uint32_t c1, uint32_t c2) -{ - uint32_t cr1, cr2; - cr1 = (c1 & 0x00ff00ff) + (c2 & 0x00ff00ff); - if(cr1 & 0x0000ff00) - cr1 = (cr1 & 0xffff00ff) | 0x000000ff; - if(cr1 & 0xff000000) - cr1 = (cr1 & 0x00ffffff) | 0x00ff0000; - - cr2 = ((c1 >> 8) & 0x000000ff) + ((c2 >> 8) & 0x000000ff); - if(cr2 & 0x0000ff00) - cr2 = (cr2 & 0xffff00ff) | 0x000000ff; - return cr1|(cr2 << 8); -} - -inline uint32_t powervr2_device::float_argb_to_packed_argb(float argb[4]) { - int argb_int[4] = { - (int)(argb[0] * 256.0f), - (int)(argb[1] * 256.0f), - (int)(argb[2] * 256.0f), - (int)(argb[3] * 256.0f) - }; - - // clamp to [0, 255] - int idx; - for (idx = 0; idx < 4; idx++) { - if (argb_int[idx] < 0) - argb_int[idx] = 0; - else if (argb_int[idx] > 255) - argb_int[idx] = 255; - } - - return (argb_int[0] << 24) | (argb_int[1] << 16) | - (argb_int[2] << 8) | argb_int[3]; -} - -inline void powervr2_device::packed_argb_to_float_argb(float dst[4], uint32_t in) { - dst[0] = (in >> 24) / 256.0f; - dst[1] = ((in >> 16) & 0xff) / 256.0f; - dst[2] = ((in >> 8) & 0xff) / 256.0f; - dst[3] = (in & 0xff) / 256.0f; -} - -// All 64 blending modes, 3 top bits are source mode, 3 bottom bits are destination mode -uint32_t powervr2_device::bl00(uint32_t s, uint32_t d) { return 0; } -uint32_t powervr2_device::bl01(uint32_t s, uint32_t d) { return d; } -uint32_t powervr2_device::bl02(uint32_t s, uint32_t d) { return blc(d, s); } -uint32_t powervr2_device::bl03(uint32_t s, uint32_t d) { return blic(d, s); } -uint32_t powervr2_device::bl04(uint32_t s, uint32_t d) { return bla(d, s); } -uint32_t powervr2_device::bl05(uint32_t s, uint32_t d) { return blia(d, s); } -uint32_t powervr2_device::bl06(uint32_t s, uint32_t d) { return bla(d, d); } -uint32_t powervr2_device::bl07(uint32_t s, uint32_t d) { return blia(d, d); } -uint32_t powervr2_device::bl10(uint32_t s, uint32_t d) { return s; } -uint32_t powervr2_device::bl11(uint32_t s, uint32_t d) { return bls(s, d); } -uint32_t powervr2_device::bl12(uint32_t s, uint32_t d) { return bls(s, blc(s, d)); } -uint32_t powervr2_device::bl13(uint32_t s, uint32_t d) { return bls(s, blic(s, d)); } -uint32_t powervr2_device::bl14(uint32_t s, uint32_t d) { return bls(s, bla(d, s)); } -uint32_t powervr2_device::bl15(uint32_t s, uint32_t d) { return bls(s, blia(d, s)); } -uint32_t powervr2_device::bl16(uint32_t s, uint32_t d) { return bls(s, bla(d, d)); } -uint32_t powervr2_device::bl17(uint32_t s, uint32_t d) { return bls(s, blia(d, d)); } -uint32_t powervr2_device::bl20(uint32_t s, uint32_t d) { return blc(d, s); } -uint32_t powervr2_device::bl21(uint32_t s, uint32_t d) { return bls(blc(d, s), d); } -uint32_t powervr2_device::bl22(uint32_t s, uint32_t d) { return bls(blc(d, s), blc(s, d)); } -uint32_t powervr2_device::bl23(uint32_t s, uint32_t d) { return bls(blc(d, s), blic(s, d)); } -uint32_t powervr2_device::bl24(uint32_t s, uint32_t d) { return bls(blc(d, s), bla(d, s)); } -uint32_t powervr2_device::bl25(uint32_t s, uint32_t d) { return bls(blc(d, s), blia(d, s)); } -uint32_t powervr2_device::bl26(uint32_t s, uint32_t d) { return bls(blc(d, s), bla(d, d)); } -uint32_t powervr2_device::bl27(uint32_t s, uint32_t d) { return bls(blc(d, s), blia(d, d)); } -uint32_t powervr2_device::bl30(uint32_t s, uint32_t d) { return blic(d, s); } -uint32_t powervr2_device::bl31(uint32_t s, uint32_t d) { return bls(blic(d, s), d); } -uint32_t powervr2_device::bl32(uint32_t s, uint32_t d) { return bls(blic(d, s), blc(s, d)); } -uint32_t powervr2_device::bl33(uint32_t s, uint32_t d) { return bls(blic(d, s), blic(s, d)); } -uint32_t powervr2_device::bl34(uint32_t s, uint32_t d) { return bls(blic(d, s), bla(d, s)); } -uint32_t powervr2_device::bl35(uint32_t s, uint32_t d) { return bls(blic(d, s), blia(d, s)); } -uint32_t powervr2_device::bl36(uint32_t s, uint32_t d) { return bls(blic(d, s), bla(d, d)); } -uint32_t powervr2_device::bl37(uint32_t s, uint32_t d) { return bls(blic(d, s), blia(d, d)); } -uint32_t powervr2_device::bl40(uint32_t s, uint32_t d) { return bla(s, s); } -uint32_t powervr2_device::bl41(uint32_t s, uint32_t d) { return bls(bla(s, s), d); } -uint32_t powervr2_device::bl42(uint32_t s, uint32_t d) { return bls(bla(s, s), blc(s, d)); } -uint32_t powervr2_device::bl43(uint32_t s, uint32_t d) { return bls(bla(s, s), blic(s, d)); } -uint32_t powervr2_device::bl44(uint32_t s, uint32_t d) { return bls(bla(s, s), bla(d, s)); } -uint32_t powervr2_device::bl45(uint32_t s, uint32_t d) { return bls(bla(s, s), blia(d, s)); } -uint32_t powervr2_device::bl46(uint32_t s, uint32_t d) { return bls(bla(s, s), bla(d, d)); } -uint32_t powervr2_device::bl47(uint32_t s, uint32_t d) { return bls(bla(s, s), blia(d, d)); } -uint32_t powervr2_device::bl50(uint32_t s, uint32_t d) { return blia(s, s); } -uint32_t powervr2_device::bl51(uint32_t s, uint32_t d) { return bls(blia(s, s), d); } -uint32_t powervr2_device::bl52(uint32_t s, uint32_t d) { return bls(blia(s, s), blc(s, d)); } -uint32_t powervr2_device::bl53(uint32_t s, uint32_t d) { return bls(blia(s, s), blic(s, d)); } -uint32_t powervr2_device::bl54(uint32_t s, uint32_t d) { return bls(blia(s, s), bla(d, s)); } -uint32_t powervr2_device::bl55(uint32_t s, uint32_t d) { return bls(blia(s, s), blia(d, s)); } -uint32_t powervr2_device::bl56(uint32_t s, uint32_t d) { return bls(blia(s, s), bla(d, d)); } -uint32_t powervr2_device::bl57(uint32_t s, uint32_t d) { return bls(blia(s, s), blia(d, d)); } -uint32_t powervr2_device::bl60(uint32_t s, uint32_t d) { return bla(s, d); } -uint32_t powervr2_device::bl61(uint32_t s, uint32_t d) { return bls(bla(s, d), d); } -uint32_t powervr2_device::bl62(uint32_t s, uint32_t d) { return bls(bla(s, d), blc(s, d)); } -uint32_t powervr2_device::bl63(uint32_t s, uint32_t d) { return bls(bla(s, d), blic(s, d)); } -uint32_t powervr2_device::bl64(uint32_t s, uint32_t d) { return bls(bla(s, d), bla(d, s)); } -uint32_t powervr2_device::bl65(uint32_t s, uint32_t d) { return bls(bla(s, d), blia(d, s)); } -uint32_t powervr2_device::bl66(uint32_t s, uint32_t d) { return bls(bla(s, d), bla(d, d)); } -uint32_t powervr2_device::bl67(uint32_t s, uint32_t d) { return bls(bla(s, d), blia(d, d)); } -uint32_t powervr2_device::bl70(uint32_t s, uint32_t d) { return blia(s, d); } -uint32_t powervr2_device::bl71(uint32_t s, uint32_t d) { return bls(blia(s, d), d); } -uint32_t powervr2_device::bl72(uint32_t s, uint32_t d) { return bls(blia(s, d), blc(s, d)); } -uint32_t powervr2_device::bl73(uint32_t s, uint32_t d) { return bls(blia(s, d), blic(s, d)); } -uint32_t powervr2_device::bl74(uint32_t s, uint32_t d) { return bls(blia(s, d), bla(d, s)); } -uint32_t powervr2_device::bl75(uint32_t s, uint32_t d) { return bls(blia(s, d), blia(d, s)); } -uint32_t powervr2_device::bl76(uint32_t s, uint32_t d) { return bls(blia(s, d), bla(d, d)); } -uint32_t powervr2_device::bl77(uint32_t s, uint32_t d) { return bls(blia(s, d), blia(d, d)); } - -uint32_t (*const powervr2_device::blend_functions[64])(uint32_t s, uint32_t d) = { - bl00, bl01, bl02, bl03, bl04, bl05, bl06, bl07, - bl10, bl11, bl12, bl13, bl14, bl15, bl16, bl17, - bl20, bl21, bl22, bl23, bl24, bl25, bl26, bl27, - bl30, bl31, bl32, bl33, bl34, bl35, bl36, bl37, - bl40, bl41, bl42, bl43, bl44, bl45, bl46, bl47, - bl50, bl51, bl52, bl53, bl54, bl55, bl56, bl57, - bl60, bl61, bl62, bl63, bl64, bl65, bl66, bl67, - bl70, bl71, bl72, bl73, bl74, bl75, bl76, bl77, -}; - -inline uint32_t powervr2_device::cv_1555(uint16_t c) -{ - return - (c & 0x8000 ? 0xff000000 : 0) | - ((c << 9) & 0x00f80000) | ((c << 4) & 0x00070000) | - ((c << 6) & 0x0000f800) | ((c << 1) & 0x00000700) | - ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007); -} - -inline uint32_t powervr2_device::cv_1555z(uint16_t c) -{ - return - (c & 0x8000 ? 0xff000000 : 0) | - ((c << 9) & 0x00f80000) | - ((c << 6) & 0x0000f800) | - ((c << 3) & 0x000000f8); -} - -inline uint32_t powervr2_device::cv_565(uint16_t c) -{ - return - 0xff000000 | - ((c << 8) & 0x00f80000) | ((c << 3) & 0x00070000) | - ((c << 5) & 0x0000fc00) | ((c >> 1) & 0x00000300) | - ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007); -} - -inline uint32_t powervr2_device::cv_565z(uint16_t c) -{ - return - 0xff000000 | - ((c << 8) & 0x00f80000) | - ((c << 5) & 0x0000fc00) | - ((c << 3) & 0x000000f8); -} - -inline uint32_t powervr2_device::cv_4444(uint16_t c) -{ - return - ((c << 16) & 0xf0000000) | ((c << 12) & 0x0f000000) | - ((c << 12) & 0x00f00000) | ((c << 8) & 0x000f0000) | - ((c << 8) & 0x0000f000) | ((c << 4) & 0x00000f00) | - ((c << 4) & 0x000000f0) | ((c ) & 0x0000000f); -} - -inline uint32_t powervr2_device::cv_4444z(uint16_t c) -{ - return - ((c << 16) & 0xf0000000) | - ((c << 12) & 0x00f00000) | - ((c << 8) & 0x0000f000) | - ((c << 4) & 0x000000f0); -} - -inline uint32_t powervr2_device::cv_yuv(uint16_t c1, uint16_t c2, int x) -{ - int u = 11*((c1 & 0xff) - 128); - int v = 11*((c2 & 0xff) - 128); - int y = (x & 1 ? c2 : c1) >> 8; - int r = y + v/8; - int g = y - u/32 - v/16; - int b = y + (3*u)/16; - r = r < 0 ? 0 : r > 255 ? 255 : r; - g = g < 0 ? 0 : g > 255 ? 255 : g; - b = b < 0 ? 0 : b > 255 ? 255 : b; - return 0xff000000 | (r << 16) | (g << 8) | b; -} - -int powervr2_device::uv_wrap(float uv, int size) -{ - int iuv = (int)uv; - return iuv & (size - 1); -} -int powervr2_device::uv_flip(float uv, int size) -{ - int iuv = (int)uv; - return ((iuv & size) ? ~iuv : iuv) & (size - 1); -} -int powervr2_device::uv_clamp(float uv, int size) -{ - int iuv = (int)uv; - return (iuv > 0) ? (iuv < size) ? iuv : (size - 1) : 0; -} - -uint32_t powervr2_device::tex_r_yuv_n(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + (t->stride*yt + (xt & ~1))*2; - uint16_t c1 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp)); - uint16_t c2 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp+2)); - return cv_yuv(c1, c2, xt); -} - -uint32_t powervr2_device::tex_r_yuv_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + (dilated1[t->cd][xt & ~1] + dilated0[t->cd][yt]) * 2; - uint16_t c1 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp)); - uint16_t c2 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp+4)); - return cv_yuv(c1, c2, xt); -} - -#if 0 -uint32_t powervr2_device::tex_r_yuv_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; - uint16_t c1 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp)); - uint16_t c2 = *(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp+4)); - return cv_yuv(c1, c2, xt); -} -#endif - -uint32_t powervr2_device::tex_r_1555_n(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + (t->stride*yt + xt) * 2; - return cv_1555z(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); -} - -uint32_t powervr2_device::tex_r_1555_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt]) * 2; - return cv_1555(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); -} - -uint32_t powervr2_device::tex_r_1555_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; - return cv_1555(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); -} - -uint32_t powervr2_device::tex_r_565_n(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + (t->stride*yt + xt) * 2; - return cv_565z(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); -} - -uint32_t powervr2_device::tex_r_565_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt]) * 2; - return cv_565(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); -} - -uint32_t powervr2_device::tex_r_565_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; - return cv_565(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); -} - -uint32_t powervr2_device::tex_r_4444_n(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + (t->stride*yt + xt) * 2; - return cv_4444z(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); -} - -uint32_t powervr2_device::tex_r_4444_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt]) * 2; - return cv_4444(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); -} - -uint32_t powervr2_device::tex_r_4444_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; - return cv_4444(*(uint16_t *)((reinterpret_cast(dc_texture_ram)) + WORD_XOR_LE(addrp))); -} - -uint32_t powervr2_device::tex_r_p4_1555_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; - int addrp = t->address + (off >> 1); - int c = ((reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; - return cv_1555(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p4_1555_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; - return cv_1555(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p4_565_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; - int addrp = t->address + (off >> 1); - int c = ((reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; - return cv_565(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p4_565_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; - return cv_565(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p4_4444_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; - int addrp = t->address + (off >> 1); - int c = ((reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; - return cv_4444(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p4_4444_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; - return cv_4444(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p4_8888_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; - int addrp = t->address + (off >> 1); - int c = ((reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; - return palette[t->palbase + c]; -} - -uint32_t powervr2_device::tex_r_p4_8888_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; - return palette[t->palbase + c]; -} - -uint32_t powervr2_device::tex_r_p8_1555_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; - return cv_1555(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p8_1555_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; - return cv_1555(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p8_565_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; - return cv_565(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p8_565_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; - return cv_565(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p8_4444_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; - return cv_4444(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p8_4444_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; - return cv_4444(palette[t->palbase + c]); -} - -uint32_t powervr2_device::tex_r_p8_8888_tw(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; - return palette[t->palbase + c]; -} - -uint32_t powervr2_device::tex_r_p8_8888_vq(texinfo *t, float x, float y) -{ - int xt = t->u_func(x, t->sizex); - int yt = t->v_func(y, t->sizey); - int idx = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; - int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; - int c = (reinterpret_cast(dc_texture_ram))[BYTE_XOR_LE(addrp)]; - return palette[t->palbase + c]; -} - - -uint32_t powervr2_device::tex_r_default(texinfo *t, float x, float y) -{ - return ((int)x ^ (int)y) & 4 ? 0xffffff00 : 0xff0000ff; -} - -void powervr2_device::tex_get_info(texinfo *t) -{ - int miptype = 0; - - t->textured = texture; - t->address = textureaddress; - t->pf = pixelformat; - t->palette = 0; - t->mode = (vqcompressed<<1); - - // scanorder is ignored for palettized textures (palettized textures are ALWAYS twiddled) - // (the same bits are used for palette select instead) - if ((t->pf == 5) || (t->pf == 6)) - { - t->palette = paletteselector; - } - else - { - t->mode |= scanorder; - } - - /* When scan order is 1 (non-twiddled) mipmap is ignored */ - t->mipmapped = t->mode & 1 ? 0 : mipmapped; - - // Mipmapped textures are always square, ignore v size - if (t->mipmapped) - { - t->sizes = (texturesizes & 0x38) | ((texturesizes & 0x38) >> 3); - } - else - { - t->sizes = texturesizes; - } - - t->sizex = 1 << (3+((t->sizes >> 3) & 7)); - t->sizey = 1 << (3+(t->sizes & 7)); - - - /* Stride select is used only in the non-twiddled case */ - t->stride = (t->mode & 1) && strideselect ? (text_control & 0x1f) << 5 : t->sizex; - - t->blend_mode = blend_mode; - t->filter_mode = filtermode; - - t->u_func = (clampuv & 2) ? &powervr2_device::uv_clamp : ((flipuv & 2) ? &powervr2_device::uv_flip : &powervr2_device::uv_wrap); - t->v_func = (clampuv & 1) ? &powervr2_device::uv_clamp : ((flipuv & 1) ? &powervr2_device::uv_flip : &powervr2_device::uv_wrap); - - t->r = &powervr2_device::tex_r_default; - t->cd = dilatechose[t->sizes]; - t->palbase = 0; - t->vqbase = t->address; - t->blend = ignoretexalpha ? bl10 : blend_functions[t->blend_mode]; - - t->coltype = coltype; - t->tsinstruction = tsinstruction; - -// fprintf(stderr, "tex %d %d %d %d\n", t->pf, t->mode, pal_ram_ctrl, t->mipmapped); - if(!t->textured) - { - t->r = nullptr; - } - else - { - switch(t->pf) { - case 0: // 1555 - switch(t->mode) { - case 0: t->r = &powervr2_device::tex_r_1555_tw; miptype = 2; break; - case 1: t->r = &powervr2_device::tex_r_1555_n; miptype = 2; break; - case 2: - case 3: t->r = &powervr2_device::tex_r_1555_vq; miptype = 3; t->address += 0x800; break; - - default: - // - break; - } - break; - - case 1: // 565 - switch(t->mode) { - case 0: t->r = &powervr2_device::tex_r_565_tw; miptype = 2; break; - case 1: t->r = &powervr2_device::tex_r_565_n; miptype = 2; break; - case 2: - case 3: t->r = &powervr2_device::tex_r_565_vq; miptype = 3; t->address += 0x800; break; - - default: - // - break; - } - break; - - case 2: // 4444 - switch(t->mode) { - case 0: t->r = &powervr2_device::tex_r_4444_tw; miptype = 2; break; - case 1: t->r = &powervr2_device::tex_r_4444_n; miptype = 2; break; - case 2: - case 3: t->r = &powervr2_device::tex_r_4444_vq; miptype = 3; t->address += 0x800; break; - - default: - // - break; - } - break; - - case 3: // yuv422 - switch(t->mode) { - case 0: t->r = &powervr2_device::tex_r_yuv_tw; miptype = -1; break; - case 1: t->r = &powervr2_device::tex_r_yuv_n; miptype = -1; break; - //default: t->r = &powervr2_device::tex_r_yuv_vq; miptype = -1; break; - } - break; - - case 4: // bumpmap - break; - - case 5: // 4bpp palette - t->palbase = (t->palette & 0x3f) << 4; - switch(t->mode) { - case 0: case 1: - miptype = 0; - - switch(pal_ram_ctrl) { - case 0: t->r = &powervr2_device::tex_r_p4_1555_tw; break; - case 1: t->r = &powervr2_device::tex_r_p4_565_tw; break; - case 2: t->r = &powervr2_device::tex_r_p4_4444_tw; break; - case 3: t->r = &powervr2_device::tex_r_p4_8888_tw; break; - } - break; - case 2: case 3: - miptype = 3; // ? - switch(pal_ram_ctrl) { - case 0: t->r = &powervr2_device::tex_r_p4_1555_vq; t->address += 0x800; break; - case 1: t->r = &powervr2_device::tex_r_p4_565_vq; t->address += 0x800; break; - case 2: t->r = &powervr2_device::tex_r_p4_4444_vq; t->address += 0x800; break; - case 3: t->r = &powervr2_device::tex_r_p4_8888_vq; t->address += 0x800; break; - } - break; - - default: - // - break; - } - break; - - case 6: // 8bpp palette - t->palbase = (t->palette & 0x30) << 4; - switch(t->mode) { - case 0: case 1: - miptype = 1; - - switch(pal_ram_ctrl) { - case 0: t->r = &powervr2_device::tex_r_p8_1555_tw; break; - case 1: t->r = &powervr2_device::tex_r_p8_565_tw; break; - case 2: t->r = &powervr2_device::tex_r_p8_4444_tw; break; - case 3: t->r = &powervr2_device::tex_r_p8_8888_tw; break; - } - break; - case 2: case 3: - miptype = 3; // ? - switch(pal_ram_ctrl) { - case 0: t->r = &powervr2_device::tex_r_p8_1555_vq; t->address += 0x800; break; - case 1: t->r = &powervr2_device::tex_r_p8_565_vq; t->address += 0x800; break; - case 2: t->r = &powervr2_device::tex_r_p8_4444_vq; t->address += 0x800; break; - case 3: t->r = &powervr2_device::tex_r_p8_8888_vq; t->address += 0x800; break; - } - break; - - default: - // - break; - } - break; - - case 9: // reserved - break; - } - } - - if (t->mipmapped) - { - // full offset tables for reference, - // we don't do mipmapping, so don't use anything < 8x8 - // first table is half-bytes - - // 4BPP palette textures - // Texture size _4-bit_ offset value for starting address - // 1x1 0x00003 - // 2x2 0x00004 - // 4x4 0x00008 - // 8x8 0x00018 - // 16x16 0x00058 - // 32x32 0x00158 - // 64x64 0x00558 - // 128x128 0x01558 - // 256x256 0x05558 - // 512x512 0x15558 - // 1024x1024 0x55558 - - // 8BPP palette textures - // Texture size Byte offset value for starting address - // 1x1 0x00003 - // 2x2 0x00004 - // 4x4 0x00008 - // 8x8 0x00018 - // 16x16 0x00058 - // 32x32 0x00158 - // 64x64 0x00558 - // 128x128 0x01558 - // 256x256 0x05558 - // 512x512 0x15558 - // 1024x1024 0x55558 - - // Non-palette textures - // Texture size Byte offset value for starting address - // 1x1 0x00006 - // 2x2 0x00008 - // 4x4 0x00010 - // 8x8 0x00030 - // 16x16 0x000B0 - // 32x32 0x002B0 - // 64x64 0x00AB0 - // 128x128 0x02AB0 - // 256x256 0x0AAB0 - // 512x512 0x2AAB0 - // 1024x1024 0xAAAB0 - - // VQ textures - // Texture size Byte offset value for starting address - // 1x1 0x00000 - // 2x2 0x00001 - // 4x4 0x00002 - // 8x8 0x00006 - // 16x16 0x00016 - // 32x32 0x00056 - // 64x64 0x00156 - // 128x128 0x00556 - // 256x256 0x01556 - // 512x512 0x05556 - // 1024x1024 0x15556 - - static const int mipmap_4_8_offset[8] = { 0x00018, 0x00058, 0x00158, 0x00558, 0x01558, 0x05558, 0x15558, 0x55558 }; // 4bpp (4bit offset) / 8bpp (8bit offset) - static const int mipmap_np_offset[8] = { 0x00030, 0x000B0, 0x002B0, 0x00AB0, 0x02AB0, 0x0AAB0, 0x2AAB0, 0xAAAB0 }; // nonpalette textures - static const int mipmap_vq_offset[8] = { 0x00006, 0x00016, 0x00056, 0x00156, 0x00556, 0x01556, 0x05556, 0x15556 }; // vq textures - - switch (miptype) - { - case 0: // 4bpp - //printf("4bpp\n"); - t->address += mipmap_4_8_offset[(t->sizes)&7]>>1; - break; - - case 1: // 8bpp - //printf("8bpp\n"); - t->address += mipmap_4_8_offset[(t->sizes)&7]; - break; - - case 2: // nonpalette - //printf("np\n"); - t->address += mipmap_np_offset[(t->sizes)&7]; - break; - - case 3: // vq - //printf("vq\n"); - t->address += mipmap_vq_offset[(t->sizes)&7]; - break; - } - } - -} - -uint32_t powervr2_device::id_r() -{ - return 0x17fd11db; -} - -uint32_t powervr2_device::revision_r() -{ - return 0x00000011; -} - -uint32_t powervr2_device::softreset_r() -{ - return softreset; -} - -void powervr2_device::softreset_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&softreset); - if (softreset & 1) { - LOGTACMD("TA soft reset\n"); - listtype_used=0; - } - if (softreset & 2) { - LOGTACMD("Core Pipeline soft reset\n"); - - if (start_render_received == 1) { - for (int a=0;a < NUM_BUFFERS;a++) - if (grab[a].busy == 1) - grab[a].busy = 0; - - start_render_received = 0; - } - } - if (softreset & 4) { - LOGTACMD("sdram I/F soft reset\n"); - } -} - -void powervr2_device::startrender_w(address_space &space, uint32_t data) -{ - dc_state *state = machine().driver_data(); - g_profiler.start(PROFILER_USER1); - - LOGTACMD("Start render, region=%08x, params=%08x\n", region_base, param_base); - - // select buffer to draw using param_base - for (int a=0;a < NUM_BUFFERS;a++) { - if ((grab[a].ispbase == param_base) && (grab[a].valid == 1) && (grab[a].busy == 0)) { - grab[a].busy = 1; - renderselect = a; - start_render_received=1; - - - grab[a].fbwsof1 = fb_w_sof1; - grab[a].fbwsof2 = fb_w_sof2; - - rectangle clip(0, 1023, 0, 1023); - - // we've got a request to draw, so, draw to the accumulation buffer! - // this should really be done for each tile! - render_to_accumulation_buffer(*fake_accumulationbuffer_bitmap,clip); - - /* copy the tiles to the framebuffer (really the rendering should be in this loop too) */ - int sizera = fpu_param_cfg & 0x200000 ? 6 : 5; - int offsetra=region_base; - - //printf("base is %08x\n", offsetra); - - // sanity - int sanitycount = 0; - for (;;) { - uint32_t st[6]; - - st[0]=space.read_dword((0x05000000+offsetra)); - st[1]=space.read_dword((0x05000004+offsetra)); // Opaque List Pointer - st[2]=space.read_dword((0x05000008+offsetra)); // Opaque Modifier Volume List Pointer - st[3]=space.read_dword((0x0500000c+offsetra)); // Translucent List Pointer - st[4]=space.read_dword((0x05000010+offsetra)); // Translucent Modifier Volume List Pointer - - if (sizera == 6) { - st[5] = space.read_dword((0x05000014+offsetra)); // Punch Through List Pointer - offsetra+=0x18; - } else { - st[5] = 0; - offsetra+=0x14; - } - - { - int x = ((st[0]&0x000000fc)>>2)*32; - int y = ((st[0]&0x00003f00)>>8)*32; - //printf("tiledata %08x %d %d - %08x %08x %08x %08x %08x\n",st[0],x,y,st[1],st[2],st[3],st[4],st[5]); - - // should render to the accumulation buffer here using pointers we filled in when processing the data - // sent to the TA. HOWEVER, we don't process the TA data and create the real format object lists, so - // instead just use these co-ordinates to copy data from our fake full-screnen accumnulation buffer into - // the framebuffer - - pvr_accumulationbuffer_to_framebuffer(space, x,y); - } - - if (st[0] & 0x80000000) - break; - - sanitycount++; - // prevent infinite loop if asked to process invalid data - //if(sanitycount>2000) - // break; - } - - /* Fire ISP irq after a set amount of time */ - // TODO: exact timing of this - // hacky end of render delay for Capcom games, otherwise they works at ~1/10 speed. - // 500k is definitely too slow for them: it fires the isp/tsp completion at - // vbl-in and expect that it completes after some time that vbl-out kicks in, - // in order to have enough time to execute logic stuff in the meantime. -// const u64 isp_completion = sanitycount * 25 + 500000; - const u64 isp_completion = sanitycount * 25 + 2000000; - LOGIRQ("[%d] ISP end of render start %d in %d cycles\n", - screen().frame_number(), screen().vpos(), isp_completion - ); - endofrender_timer_isp->adjust(state->m_maincpu->cycles_to_attotime(isp_completion)); - break; - } - } -} - - -uint32_t powervr2_device::param_base_r() -{ - return param_base; -} - -void powervr2_device::param_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(¶m_base); -} - -uint32_t powervr2_device::region_base_r() -{ - return region_base; -} - -void powervr2_device::region_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(®ion_base); -} - -uint32_t powervr2_device::vo_border_col_r() -{ - return vo_border_col; -} - -void powervr2_device::vo_border_col_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&vo_border_col); -} - -uint32_t powervr2_device::fb_r_ctrl_r() -{ - return fb_r_ctrl; -} - -void powervr2_device::fb_r_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_r_ctrl); -} - -uint32_t powervr2_device::fb_w_ctrl_r() -{ - return fb_w_ctrl; -} - -void powervr2_device::fb_w_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_w_ctrl); -} - -uint32_t powervr2_device::fb_w_linestride_r() -{ - return fb_w_linestride; -} - -void powervr2_device::fb_w_linestride_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_w_linestride); -} - -uint32_t powervr2_device::fb_r_sof1_r() -{ - return fb_r_sof1; -} - -void powervr2_device::fb_r_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_r_sof1); -} - -uint32_t powervr2_device::fb_r_sof2_r() -{ - return fb_r_sof2; -} - -void powervr2_device::fb_r_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_r_sof2); -} - -uint32_t powervr2_device::fb_r_size_r() -{ - return fb_r_size; -} - -void powervr2_device::fb_r_size_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_r_size); -} - -uint32_t powervr2_device::fb_w_sof1_r() -{ - return fb_w_sof1; -} - -void powervr2_device::fb_w_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_w_sof1); -} - -uint32_t powervr2_device::fb_w_sof2_r() -{ - return fb_w_sof2; -} - -void powervr2_device::fb_w_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_w_sof2); -} - -uint32_t powervr2_device::fb_x_clip_r() -{ - return fb_x_clip; -} - -void powervr2_device::fb_x_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_x_clip); -} - -uint32_t powervr2_device::fb_y_clip_r() -{ - return fb_y_clip; -} - -void powervr2_device::fb_y_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fb_y_clip); -} - -uint32_t powervr2_device::fpu_param_cfg_r() -{ - return fpu_param_cfg; -} - -void powervr2_device::fpu_param_cfg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&fpu_param_cfg); -} - -uint32_t powervr2_device::isp_backgnd_t_r() -{ - return isp_backgnd_t; -} - -void powervr2_device::isp_backgnd_t_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&isp_backgnd_t); -} - -uint32_t powervr2_device::spg_hblank_int_r() -{ - return spg_hblank_int; -} - -void powervr2_device::spg_hblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&spg_hblank_int); - // TODO: timer adjust -} - -uint32_t powervr2_device::spg_vblank_int_r() -{ - return spg_vblank_int; -} - -void powervr2_device::spg_vblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&spg_vblank_int); - - /* clear pending irqs and modify them with the updated ones */ -// vbin_timer->adjust(attotime::never); -// vbout_timer->adjust(attotime::never); - -// vbin_timer->adjust(screen().time_until_pos(spg_vblank_int & 0x3ff)); -// vbout_timer->adjust(screen().time_until_pos((spg_vblank_int >> 16) & 0x3ff)); -} - -uint32_t powervr2_device::spg_control_r() -{ - return spg_control; -} - -void powervr2_device::spg_control_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&spg_control); - update_screen_format(); - - if((spg_control & 0xc0) == 0xc0) - popmessage("SPG undocumented pixel clock mode 11, contact MAME/MESSdev"); - - if((spg_control & 0xd0) == 0x10) - popmessage("SPG enabled VGA mode with interlace, contact MAME/MESSdev"); -} - -uint32_t powervr2_device::spg_hblank_r() -{ - return spg_hblank; -} - -void powervr2_device::spg_hblank_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&spg_hblank); - update_screen_format(); -} - -uint32_t powervr2_device::spg_load_r() -{ - return spg_load; -} - -void powervr2_device::spg_load_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&spg_load); - update_screen_format(); -} - -uint32_t powervr2_device::spg_vblank_r() -{ - return spg_vblank; -} - -void powervr2_device::spg_vblank_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&spg_vblank); - update_screen_format(); -} - -uint32_t powervr2_device::spg_width_r() -{ - return spg_width; -} - -void powervr2_device::spg_width_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&spg_width); - update_screen_format(); -} - -uint32_t powervr2_device::text_control_r() -{ - return text_control; -} - -void powervr2_device::text_control_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&text_control); -} - -uint32_t powervr2_device::vo_control_r() -{ - return vo_control; -} - -void powervr2_device::vo_control_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&vo_control); -} - -uint32_t powervr2_device::vo_startx_r() -{ - return vo_startx; -} - -void powervr2_device::vo_startx_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&vo_startx); - update_screen_format(); -} - -uint32_t powervr2_device::vo_starty_r() -{ - return vo_starty; -} - -void powervr2_device::vo_starty_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&vo_starty); - update_screen_format(); -} - -uint32_t powervr2_device::pal_ram_ctrl_r() -{ - return pal_ram_ctrl; -} - -void powervr2_device::pal_ram_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&pal_ram_ctrl); -} - -uint32_t powervr2_device::spg_status_r() -{ - uint32_t fieldnum = (screen().frame_number() & 1) ? 1 : 0; - int32_t spg_hbstart = spg_hblank & 0x3ff; - int32_t spg_hbend = (spg_hblank >> 16) & 0x3ff; - int32_t spg_vbstart = spg_vblank & 0x3ff; - int32_t spg_vbend = (spg_vblank >> 16) & 0x3ff; - - uint32_t vsync = ((screen().vpos() >= spg_vbstart) || (screen().vpos() < spg_vbend)) ? 0 : 1; - uint32_t hsync = ((screen().hpos() >= spg_hbstart) || (screen().hpos() < spg_hbend)) ? 0 : 1; - // FIXME: following is just a wild guess - uint32_t blank = ((screen().vpos() >= spg_vbstart) || (screen().vpos() < spg_vbend) || - (screen().hpos() >= spg_hbstart) || (screen().hpos() < spg_hbend)) ? 0 : 1; - if(vo_control & 4) { blank^=1; } - if(vo_control & 2) { vsync^=1; } - if(vo_control & 1) { hsync^=1; } - - return (vsync << 13) | (hsync << 12) | (blank << 11) | (fieldnum << 10) | (screen().vpos() & 0x3ff); -} - - -uint32_t powervr2_device::ta_ol_base_r() -{ - return ta_ol_base; -} - -void powervr2_device::ta_ol_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&ta_ol_base); -} - -uint32_t powervr2_device::ta_isp_base_r() -{ - return ta_isp_base; -} - -void powervr2_device::ta_isp_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&ta_isp_base); -} - -uint32_t powervr2_device::ta_ol_limit_r() -{ - return ta_ol_limit; -} - -void powervr2_device::ta_ol_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&ta_ol_limit); -} - -uint32_t powervr2_device::ta_isp_limit_r() -{ - return ta_isp_limit; -} - -void powervr2_device::ta_isp_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&ta_isp_limit); -} - -uint32_t powervr2_device::ta_next_opb_r() -{ - return ta_next_opb; -} - -uint32_t powervr2_device::ta_itp_current_r() -{ - return ta_itp_current; -} - -uint32_t powervr2_device::ta_alloc_ctrl_r() -{ - return ta_alloc_ctrl; -} - -void powervr2_device::ta_alloc_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&ta_alloc_ctrl); -} - -uint32_t powervr2_device::ta_list_init_r() -{ - return 0; //bit 31 always return 0, a probable left-over in Crazy Taxi reads this and discards the read (?) -} - -void powervr2_device::ta_list_init_w(uint32_t data) -{ - if(data & 0x80000000) { - tafifo_pos=0; - tafifo_mask=7; - tafifo_vertexwords=8; - tafifo_listtype= DISPLAY_LIST_NONE; - - LOGTACMD("list init ol=(%08x, %08x) isp=(%08x, %08x), alloc=%08x obp=%08x\n", - ta_ol_base, ta_ol_limit, - ta_isp_base, ta_isp_limit, - ta_alloc_ctrl, - ta_next_opb_init - ); - - ta_next_opb = ta_next_opb_init; - ta_itp_current = ta_isp_base; - alloc_ctrl_OPB_Mode = ta_alloc_ctrl & 0x100000; // 0 up 1 down - alloc_ctrl_PT_OPB = (4 << ((ta_alloc_ctrl >> 16) & 3)) & 0x38; // number of 32 bit words (0,8,16,32) - alloc_ctrl_TM_OPB = (4 << ((ta_alloc_ctrl >> 12) & 3)) & 0x38; - alloc_ctrl_T_OPB = (4 << ((ta_alloc_ctrl >> 8) & 3)) & 0x38; - alloc_ctrl_OM_OPB = (4 << ((ta_alloc_ctrl >> 4) & 3)) & 0x38; - alloc_ctrl_O_OPB = (4 << ((ta_alloc_ctrl >> 0) & 3)) & 0x38; - listtype_used |= (1+4); - // use ta_isp_base and select buffer for grab data - grabsel = -1; - // try to find already used buffer but not busy - for (int a=0;a < NUM_BUFFERS;a++) - if ((grab[a].ispbase == ta_isp_base) && (grab[a].busy == 0) && (grab[a].valid == 1)) { - grabsel=a; - break; - } - - // try a buffer not used yet - if (grabsel < 0) - for (int a=0;a < NUM_BUFFERS;a++) - if (grab[a].valid == 0) { - grabsel=a; - break; - } - - // find a non busy buffer starting from the last one used - if (grabsel < 0) - for (int a=0;a < 3;a++) - if (grab[(grabsellast+1+a) & 3].busy == 0) { - grabsel=a; - break; - } - - if (grabsel < 0) - throw emu_fatalerror("powervr2_device::ta_list_init_w: TA grabber error B!"); - grabsellast=grabsel; - grab[grabsel].ispbase=ta_isp_base; - grab[grabsel].busy=0; - grab[grabsel].valid=1; - grab[grabsel].verts_size=0; - for (int group = 0; group < DISPLAY_LIST_COUNT; group++) { - grab[grabsel].groups[group].strips_size=0; - } - - g_profiler.stop(); - } -} - - -uint32_t powervr2_device::ta_yuv_tex_base_r() -{ - return ta_yuv_tex_base; -} - -void powervr2_device::ta_yuv_tex_base_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&ta_yuv_tex_base); - - // Writes causes a reset in YUV FIFO pipeline - ta_yuv_index = 0; - ta_yuv_u_ptr = 0; - ta_yuv_v_ptr = 0; -} - -uint32_t powervr2_device::ta_yuv_tex_ctrl_r() -{ - return ta_yuv_tex_ctrl; -} - -void powervr2_device::ta_yuv_tex_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&ta_yuv_tex_ctrl); - - ta_yuv_v_size = (((ta_yuv_tex_ctrl >> 8) & 0x3f) + 1) * 16; - ta_yuv_u_size = ((ta_yuv_tex_ctrl & 0x3f) + 1) * 16; - - if (ta_yuv_tex_ctrl & 0x01010000) - throw emu_fatalerror("YUV422 mode selected %08x", ta_yuv_tex_ctrl); -} - -// TODO: unemulated YUV macroblock live count, nothing seems to use it? -uint32_t powervr2_device::ta_yuv_tex_cnt_r() -{ - if (!machine().side_effects_disabled()) - LOGWARN("%s yuv_tex_cnt read!", machine().describe_context()); - return ta_yuv_tex_cnt; -} - -void powervr2_device::ta_list_cont_w(uint32_t data) -{ - if(data & 0x80000000) { - tafifo_listtype= DISPLAY_LIST_NONE; // no list being received - listtype_used |= (1+4); - } -} - -uint32_t powervr2_device::ta_next_opb_init_r() -{ - return ta_next_opb_init; -} - -void powervr2_device::ta_next_opb_init_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&ta_next_opb_init); -} - - -uint32_t powervr2_device::fog_table_r(offs_t offset) -{ - return fog_table[offset]; -} - -void powervr2_device::fog_table_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(fog_table+offset); -} - -uint32_t powervr2_device::palette_r(offs_t offset) -{ - return palette[offset]; -} - -void powervr2_device::palette_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(palette+offset); -} - -void powervr2_device::update_screen_format() -{ - /* 00=VGA 01=NTSC 10=PAL, 11=illegal/undocumented */ - const int spg_clks[4] = { 26944080, 13458568, 13462800, 26944080 }; - int32_t spg_hsize = spg_load & 0x3ff; - int32_t spg_vsize = (spg_load >> 16) & 0x3ff; - int32_t spg_hbstart = spg_hblank & 0x3ff; - int32_t spg_hbend = (spg_hblank >> 16) & 0x3ff; - int32_t spg_vbstart = spg_vblank & 0x3ff; - int32_t spg_vbend = (spg_vblank >> 16) & 0x3ff; - //int32_t vo_horz_start_pos = vo_startx & 0x3ff; - //int32_t vo_vert_start_pos_f1 = vo_starty & 0x3ff; - int pclk = spg_clks[(spg_control >> 6) & 3] * (((spg_control & 0x10) >> 4)+1); - - attoseconds_t refresh = HZ_TO_ATTOSECONDS(pclk) * spg_hsize * spg_vsize; - - rectangle visarea = screen().visible_area(); - - visarea.min_x = spg_hbend; - visarea.max_x = spg_hbstart - 1; - visarea.min_y = spg_vbend; - visarea.max_y = spg_vbstart - 1; - - // Sanitize - if(visarea.max_x >= spg_hsize) - visarea.max_x = spg_hsize-1; - if(visarea.max_y >= spg_vsize) - visarea.max_y = spg_vsize-1; - if(visarea.min_x > visarea.max_x) - visarea.min_x = visarea.max_x; - if(visarea.min_y > visarea.max_y) - visarea.min_y = visarea.max_y; - - screen().configure(spg_hsize, spg_vsize, visarea, refresh ); -} - - -uint32_t powervr2_device::sb_pdstap_r() -{ - return sb_pdstap; -} - -void powervr2_device::sb_pdstap_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&sb_pdstap); - m_pvr_dma.pvr_addr = sb_pdstap; -} - -uint32_t powervr2_device::sb_pdstar_r() -{ - return sb_pdstar; -} - -void powervr2_device::sb_pdstar_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&sb_pdstar); - m_pvr_dma.sys_addr = sb_pdstar; -} - -uint32_t powervr2_device::sb_pdlen_r() -{ - return sb_pdlen; -} - -void powervr2_device::sb_pdlen_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&sb_pdlen); - m_pvr_dma.size = sb_pdlen; -} - -uint32_t powervr2_device::sb_pddir_r() -{ - return sb_pddir; -} - -void powervr2_device::sb_pddir_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&sb_pddir); - m_pvr_dma.dir = sb_pddir; -} - -uint32_t powervr2_device::sb_pdtsel_r() -{ - return sb_pdtsel; -} - -void powervr2_device::sb_pdtsel_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&sb_pdtsel); - m_pvr_dma.sel = sb_pdtsel & 1; -} - -uint32_t powervr2_device::sb_pden_r() -{ - return sb_pden; -} - -void powervr2_device::sb_pden_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&sb_pden); - m_pvr_dma.flag = sb_pden & 1; -} - -uint32_t powervr2_device::sb_pdst_r() -{ - return sb_pdst; -} - -void powervr2_device::sb_pdst_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&sb_pdst); - - uint32_t old = m_pvr_dma.start & 1; - m_pvr_dma.start = sb_pdst & 1; - - // 0 -> 1 transition starts the DMA - if(((old & 1) == 0) && m_pvr_dma.flag && m_pvr_dma.start && ((m_pvr_dma.sel & 1) == 0)) - pvr_dma_execute(space); -} - -uint32_t powervr2_device::sb_pdapro_r() -{ - return sb_pdapro; -} - -void powervr2_device::sb_pdapro_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&sb_pdapro); -} - - -TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_list_irq) -{ - LOGIRQ("[%d] EOXFER OPLST %d\n", screen().frame_number(), screen().vpos()); - - irq_cb(EOXFER_OPLST_IRQ); -} - -TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_modifier_volume_list_irq) -{ - LOGIRQ("[%d] EOXFER OPMV %d\n", screen().frame_number(), screen().vpos()); - - irq_cb(EOXFER_OPMV_IRQ); -} - -TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_list_irq) -{ - LOGIRQ("[%d] EOXFER TRLST %d\n", screen().frame_number(), screen().vpos()); - - irq_cb(EOXFER_TRLST_IRQ); -} - -TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_modifier_volume_list_irq) -{ - LOGIRQ("[%d] EOXFER TRMV %d\n", screen().frame_number(), screen().vpos()); - - irq_cb(EOXFER_TRMV_IRQ); -} - -TIMER_CALLBACK_MEMBER(powervr2_device::transfer_punch_through_list_irq) -{ - LOGIRQ("[%d] EOXFER PTLST %d\n", screen().frame_number(), screen().vpos()); - - irq_cb(EOXFER_PTLST_IRQ); -} - -void powervr2_device::process_ta_fifo() -{ - /* first byte in the buffer is the Parameter Control Word - - pppp pppp gggg gggg oooo oooo oooo oooo - - p = para control - g = group control - o = object control - - */ - - receiveddata *rd = &grab[grabsel]; - - // Para Control - paracontrol=(tafifo_buff[0] >> 24) & 0xff; - // 0 end of list - // 1 user tile clip - // 2 object list set - // 3 reserved - // 4 polygon/modifier volume - // 5 sprite - // 6 reserved - // 7 vertex - paratype=(paracontrol >> 5) & 7; - endofstrip=(paracontrol >> 4) & 1; - listtype=(paracontrol >> 0) & 7; - if ((paratype >= 4) && (paratype <= 6)) - { - global_paratype = paratype; - // Group Control - groupcontrol=(tafifo_buff[0] >> 16) & 0xff; - groupen=(groupcontrol >> 7) & 1; - striplen=(groupcontrol >> 2) & 3; - userclip=(groupcontrol >> 0) & 3; - // Obj Control - objcontrol=(tafifo_buff[0] >> 0) & 0xffff; - shadow=(objcontrol >> 7) & 1; - volume=(objcontrol >> 6) & 1; - coltype=(objcontrol >> 4) & 3; - texture=(objcontrol >> 3) & 1; - offset_color_enable=texture ? (objcontrol >> 2) & 1 : 0; - gouraud=(objcontrol >> 1) & 1; - uv16bit=(objcontrol >> 0) & 1; - } - - // check if we need 8 words more - if (tafifo_mask == 7) - { - parameterconfig = pvr_parameterconfig[objcontrol & 0x3d]; - // decide number of words per vertex - if (paratype == 7) - { - if ((global_paratype == 5) || - (tafifo_listtype == DISPLAY_LIST_OPAQUE_MOD) || - (tafifo_listtype == DISPLAY_LIST_TRANS_MOD)) - { - tafifo_vertexwords = 16; - } - if (tafifo_vertexwords == 16) - { - tafifo_mask = 15; - tafifo_pos = 8; - return; - } - } - // decide number of words when not a vertex - tafifo_vertexwords=pvr_wordsvertex[parameterconfig]; - if ((paratype == 4) && ((listtype != 1) && (listtype != 3))) - if (pvr_wordspolygon[parameterconfig] == 16) - { - tafifo_mask = 15; - tafifo_pos = 8; - return; - } - } - bool have_16_byte_header = tafifo_mask != 7; - tafifo_mask = 7; - - // now we heve all the needed words - - /* - * load per-polygon colors if color type is 2 or 3 or parameter type is - * 5 (quad). For color types 0 and 1, color is determined entirely on a - * per-vertex basis. - */ - if (paratype == 4) - { - switch (coltype) { - case 2: - if (offset_color_enable) { - memcpy(poly_base_color, tafifo_buff + 8, 4 * sizeof(float)); - memcpy(poly_offs_color, tafifo_buff + 12, 4 * sizeof(float)); - } else { - memcpy(poly_base_color, tafifo_buff + 4, 4 * sizeof(float)); - memset(poly_offs_color, 0, sizeof(poly_offs_color)); - } - memcpy(poly_last_mode_2_base_color, poly_base_color, sizeof(poly_last_mode_2_base_color)); - break; - case 3: - memcpy(poly_base_color, poly_last_mode_2_base_color, sizeof(poly_base_color)); - memset(poly_offs_color, 0, sizeof(poly_offs_color)); - break; - default: - memset(poly_base_color, 0, sizeof(poly_base_color)); - memset(poly_offs_color, 0, sizeof(poly_offs_color)); - break; - } - } else if (paratype == 5) { - packed_argb_to_float_argb(poly_base_color, tafifo_buff[4]); - if (offset_color_enable) { - packed_argb_to_float_argb(poly_offs_color, tafifo_buff[5]); - } else { - memset(poly_offs_color, 0, sizeof(poly_offs_color)); - } - } - - // here we should generate the data for the various tiles - // for now, just interpret their meaning - if (paratype == 0) - { - LOGTATILE("Para Type 0 End of List\n"); - - /* Process transfer FIFO done irqs here */ - //printf("%d %d\n",tafifo_listtype,screen().vpos()); - // FIXME: timing of these - switch (tafifo_listtype) - { - case DISPLAY_LIST_OPAQUE: - opaque_irq_timer->adjust(attotime::from_usec(100)); - break; - case DISPLAY_LIST_OPAQUE_MOD: - opaque_modifier_volume_irq_timer->adjust(attotime::from_usec(100)); - break; - case DISPLAY_LIST_TRANS: - translucent_irq_timer->adjust(attotime::from_usec(100)); - break; - case DISPLAY_LIST_TRANS_MOD: - translucent_modifier_volume_irq_timer->adjust(attotime::from_usec(100)); - break; - case DISPLAY_LIST_PUNCH_THROUGH: - punch_through_irq_timer->adjust(attotime::from_usec(100)); - break; - } - tafifo_listtype = DISPLAY_LIST_NONE; // no list being received - listtype_used |= (2+8); - } - else if (paratype == 1) - { - LOGTATILE("Para Type 1 User Tile Clip\n"); - LOGTATILE(" (%d , %d)-(%d , %d)\n", tafifo_buff[4], tafifo_buff[5], tafifo_buff[6], tafifo_buff[7]); - } - else if (paratype == 2) - { - LOGTATILE("Para Type 2 Object List Set at %08x\n", tafifo_buff[1]); - LOGTATILE(" (%d , %d)-(%d , %d)\n", tafifo_buff[4], tafifo_buff[5], tafifo_buff[6], tafifo_buff[7]); - } - else if (paratype == 3) - { - LOGWARN("Para Type %x Unknown!\n", tafifo_buff[0]); - } - else - { // global parameter or vertex parameter - LOGTATILE("Para Type %d", paratype); - if (paratype == 7) - LOGTATILE(" End of Strip %d", endofstrip); - if (listtype_used & 3) - LOGTATILE(" List Type %d", listtype); - LOGTATILE("\n"); - - // set type of list currently being received - if ((paratype == 4) || (paratype == 5) || (paratype == 6)) - { - if (tafifo_listtype < 0) - { - tafifo_listtype = listtype; - } - } - listtype_used = listtype_used ^ (listtype_used & 3); - - if ((paratype == 4) || (paratype == 5)) - { // quad or polygon - depthcomparemode=(tafifo_buff[1] >> 29) & 7; - cullingmode=(tafifo_buff[1] >> 27) & 3; - zwritedisable=(tafifo_buff[1] >> 26) & 1; - cachebypass=(tafifo_buff[1] >> 21) & 1; - dcalcctrl=(tafifo_buff[1] >> 20) & 1; - volumeinstruction=(tafifo_buff[1] >> 29) & 7; - - //textureusize=1 << (3+((tafifo_buff[2] >> 3) & 7)); - //texturevsize=1 << (3+(tafifo_buff[2] & 7)); - texturesizes=tafifo_buff[2] & 0x3f; - blend_mode = tafifo_buff[2] >> 26; - srcselect=(tafifo_buff[2] >> 25) & 1; - dstselect=(tafifo_buff[2] >> 24) & 1; - fogcontrol=(tafifo_buff[2] >> 22) & 3; - colorclamp=(tafifo_buff[2] >> 21) & 1; - use_alpha = (tafifo_buff[2] >> 20) & 1; - ignoretexalpha=(tafifo_buff[2] >> 19) & 1; - flipuv=(tafifo_buff[2] >> 17) & 3; - clampuv=(tafifo_buff[2] >> 15) & 3; - filtermode=(tafifo_buff[2] >> 13) & 3; - sstexture=(tafifo_buff[2] >> 12) & 1; - mmdadjust=(tafifo_buff[2] >> 8) & 1; - tsinstruction=(tafifo_buff[2] >> 6) & 3; - if (texture == 1) - { - textureaddress=(tafifo_buff[3] & 0x1FFFFF) << 3; - scanorder=(tafifo_buff[3] >> 26) & 1; - pixelformat=(tafifo_buff[3] >> 27) & 7; - mipmapped=(tafifo_buff[3] >> 31) & 1; - vqcompressed=(tafifo_buff[3] >> 30) & 1; - strideselect=(tafifo_buff[3] >> 25) & 1; - paletteselector=(tafifo_buff[3] >> 21) & 0x3F; - - LOGTATILE(" Texture at %08x format %d\n", (tafifo_buff[3] & 0x1FFFFF) << 3, pixelformat); - } - if (use_alpha == 0) - { - // Alpha value in base/offset color is to be treated as 1.0/0xFF. - poly_base_color[0] = 1.0; - if (offset_color_enable) - poly_offs_color[0] = 1.0; - } - if (paratype == 4) - { - LOGTATILE(" %s\n", - ((tafifo_listtype == DISPLAY_LIST_OPAQUE_MOD) || - (tafifo_listtype == DISPLAY_LIST_TRANS_MOD)) ? "Modifier Volume" : "Polygon" - ); - } - if (paratype == 5) - { // quad - LOGTATILE(" Sprite\n"); - } - } - - if (paratype == 7) - { // vertex - if (tafifo_listtype < 0 || tafifo_listtype >= DISPLAY_LIST_COUNT) { - LOGWARN("unrecognized list type %d\n", tafifo_listtype); - return; - } - struct poly_group *grp = rd->groups + tafifo_listtype; - if ((tafifo_listtype == DISPLAY_LIST_OPAQUE_MOD) || - (tafifo_listtype == DISPLAY_LIST_TRANS_MOD)) - { - LOGTATILE(" Vertex modifier volume"); - LOGTATILE(" A(%f,%f,%f) B(%f,%f,%f) C(%f,%f,%f)\n", - u2f(tafifo_buff[1]), u2f(tafifo_buff[2]), u2f(tafifo_buff[3]), - u2f(tafifo_buff[4]), u2f(tafifo_buff[5]), u2f(tafifo_buff[6]), - u2f(tafifo_buff[7]), u2f(tafifo_buff[8]), u2f(tafifo_buff[9]) - ); - } - else if (global_paratype == 5) - { - LOGTATILE(" Vertex sprite"); - LOGTATILE(" A(%f,%f,%f) B(%f,%f,%f) C(%f,%f,%f) D(%f,%f,)\n", - u2f(tafifo_buff[1]), u2f(tafifo_buff[2]), u2f(tafifo_buff[3]), - u2f(tafifo_buff[4]), u2f(tafifo_buff[5]), u2f(tafifo_buff[6]), - u2f(tafifo_buff[7]), u2f(tafifo_buff[8]), u2f(tafifo_buff[9]), - u2f(tafifo_buff[10]), u2f(tafifo_buff[11]) - ); - - if (rd->verts_size <= (MAX_VERTS - 6) && grp->strips_size < MAX_STRIPS) - { - vert * const tv = &rd->verts[rd->verts_size]; - tv[0].x = u2f(tafifo_buff[0x1]); - tv[0].y = u2f(tafifo_buff[0x2]); - tv[0].w = u2f(tafifo_buff[0x3]); - tv[1].x = u2f(tafifo_buff[0x4]); - tv[1].y = u2f(tafifo_buff[0x5]); - tv[1].w = u2f(tafifo_buff[0x6]); - tv[3].x = u2f(tafifo_buff[0x7]); - tv[3].y = u2f(tafifo_buff[0x8]); - tv[3].w = u2f(tafifo_buff[0x9]); - tv[2].x = u2f(tafifo_buff[0xa]); - tv[2].y = u2f(tafifo_buff[0xb]); - tv[2].w = tv[0].w+tv[3].w-tv[1].w; - - if (texture == 1) - { - tv[0].u = u2f(tafifo_buff[0xd] & 0xffff0000); - tv[0].v = u2f(tafifo_buff[0xd] << 16); - tv[1].u = u2f(tafifo_buff[0xe] & 0xffff0000); - tv[1].v = u2f(tafifo_buff[0xe] << 16); - tv[3].u = u2f(tafifo_buff[0xf] & 0xffff0000); - tv[3].v = u2f(tafifo_buff[0xf] << 16); - tv[2].u = tv[0].u+tv[3].u-tv[1].u; - tv[2].v = tv[0].v+tv[3].v-tv[1].v; - } - - for (int idx = 0; idx < 4; idx++) - { - memcpy(tv[idx].b, poly_base_color, sizeof(tv[idx].b)); - memcpy(tv[idx].o, poly_offs_color, sizeof(tv[idx].o)); - } - - strip * const ts = &grp->strips[grp->strips_size++]; - tex_get_info(&ts->ti); - ts->svert = rd->verts_size; - ts->evert = rd->verts_size + 3; - - rd->verts_size += 4; - } - } - else if (global_paratype == 4) - { - LOGTATILE(" Vertex polygon"); - LOGTATILE(" V(%f,%f,%f) T(%f,%f)\n", - u2f(tafifo_buff[1]), u2f(tafifo_buff[2]), u2f(tafifo_buff[3]), - u2f(tafifo_buff[4]), u2f(tafifo_buff[5]) - ); - - if (rd->verts_size <= (MAX_VERTS - 6)) - { - float vert_offset_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - float vert_base_color[4]; - - float base_intensity, offs_intensity; - - switch (coltype) { - case 0: - // packed color - packed_argb_to_float_argb(vert_base_color, tafifo_buff[6]); - break; - case 1: - // floating-point color - if (have_16_byte_header) { - memcpy(vert_base_color, tafifo_buff + 8, - sizeof(vert_base_color)); - memcpy(vert_offset_color, tafifo_buff + 12, - sizeof(vert_offset_color)); - } else { - memcpy(vert_base_color, tafifo_buff + 4, - sizeof(vert_base_color)); - } - break; - case 2: - case 3: - /* - * base/offset color were previously - * specified on a per-polygon basis. - * To get the per-vertex base and - * offset colors, they are scaled by - * per-vertex scalar values. - */ - memcpy(&base_intensity, tafifo_buff + 6, sizeof(base_intensity)); - memcpy(&offs_intensity, tafifo_buff + 7, sizeof(offs_intensity)); - vert_base_color[0] = poly_base_color[0] * base_intensity; - vert_base_color[1] = poly_base_color[1] * base_intensity; - vert_base_color[2] = poly_base_color[2] * base_intensity; - vert_base_color[3] = poly_base_color[3] * base_intensity; - if (offset_color_enable) { - vert_offset_color[0] = poly_offs_color[0] * offs_intensity; - vert_offset_color[1] = poly_offs_color[1] * offs_intensity; - vert_offset_color[2] = poly_offs_color[2] * offs_intensity; - vert_offset_color[3] = poly_offs_color[3] * offs_intensity; - } - break; - default: - // This will never actually happen, coltype is 2-bits. - logerror("line %d of %s - coltype is %d\n", coltype); - memset(vert_base_color, 0, sizeof(vert_base_color)); - } - - /* add a vertex to our list */ - /* this is used for 3d stuff, ie most of the graphics (see guilty gear, confidential mission, maze of the kings etc.) */ - /* -- this is also wildly inaccurate! */ - vert *tv = &rd->verts[rd->verts_size]; - - tv->x=u2f(tafifo_buff[1]); - tv->y=u2f(tafifo_buff[2]); - tv->w=u2f(tafifo_buff[3]); - tv->u=u2f(tafifo_buff[4]); - tv->v=u2f(tafifo_buff[5]); - memcpy(tv->b, vert_base_color, sizeof(tv->b)); - memcpy(tv->o, vert_offset_color, sizeof(tv->o)); - - if(grp->strips_size < MAX_STRIPS && - ((!grp->strips_size) || - grp->strips[grp->strips_size-1].evert != -1)) - { - strip *ts = &grp->strips[grp->strips_size++]; - tex_get_info(&ts->ti); - ts->svert = rd->verts_size; - ts->evert = -1; - } - if(endofstrip) - grp->strips[grp->strips_size-1].evert = rd->verts_size; - rd->verts_size++; - } - } - } - } -} - -void powervr2_device::ta_fifo_poly_w(offs_t offset, uint64_t data, uint64_t mem_mask) -{ - if (mem_mask == 0xffffffffffffffffU) // 64 bit - { - tafifo_buff[tafifo_pos]=(uint32_t)data; - tafifo_buff[tafifo_pos+1]=(uint32_t)(data >> 32); - LOGTAFIFO("ta_fifo_poly_w: write64 %08x = %x -> %08x %08x\n", - 0x10000000 + offset * 8, - data, - tafifo_buff[tafifo_pos], - tafifo_buff[tafifo_pos + 1] - ); - tafifo_pos += 2; - } - else - { - LOGWARN("ta_fifo_poly_w: Unmapped write64 %08x = %x mask %x\n", 0x10000000+offset*8, data, mem_mask); - } - - tafifo_pos &= tafifo_mask; - - // if the command is complete, process it - if (tafifo_pos == 0) - process_ta_fifo(); - -} - -TIMER_CALLBACK_MEMBER(powervr2_device::yuv_convert_end) -{ - irq_cb(EOXFER_YUV_IRQ); - yuv_timer_end->adjust(attotime::never); -} - -void powervr2_device::ta_fifo_yuv_w(uint8_t data) -{ - dc_state *state = machine().driver_data(); - - yuv_fifo[ta_yuv_index] = data; - ta_yuv_index++; - - if(ta_yuv_index == 0x180) - { -#if LIVE_YUV_VIEW - popmessage("YUV fifo write base=%08x ctrl=%08x (%dx%d)", - ta_yuv_tex_base, ta_yuv_tex_ctrl, - ta_yuv_u_size, ta_yuv_v_size - ); -#endif - - ta_yuv_index = 0; - for(int y = 0; y < 16; y++) - { - for(int x = 0; x < 16; x+=2) - { - int dst_addr; - int u, v, y0, y1; - - dst_addr = ta_yuv_tex_base; - dst_addr+= (ta_yuv_u_ptr + x) * 2; - // pitch is given by U size (320 for luptype, 512 for ss2005/kurucham) - dst_addr+= ((ta_yuv_v_ptr + y) * ta_yuv_u_size * 2); - - u = yuv_fifo[0x00+(x>>1)+((y>>1)*8)]; - v = yuv_fifo[0x40+(x>>1)+((y>>1)*8)]; - y0 = yuv_fifo[0x80+((x&8) ? 0x40 : 0x00)+((y&8) ? 0x80 : 0x00)+(x&6)+((y&7)*8)]; - y1 = yuv_fifo[0x80+((x&8) ? 0x40 : 0x00)+((y&8) ? 0x80 : 0x00)+(x&6)+((y&7)*8)+1]; - - *(uint8_t *)((reinterpret_cast(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr)) = u; - *(uint8_t *)((reinterpret_cast(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr+1)) = y0; - *(uint8_t *)((reinterpret_cast(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr+2)) = v; - *(uint8_t *)((reinterpret_cast(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr+3)) = y1; - } - } - - ta_yuv_u_ptr += 16; - if(ta_yuv_u_ptr == ta_yuv_u_size) - { - ta_yuv_u_ptr = 0; - ta_yuv_v_ptr += 16; - if(ta_yuv_v_ptr == ta_yuv_v_size) - { - ta_yuv_v_ptr = 0; - // TODO: actual timings - yuv_timer_end->adjust(state->m_maincpu->cycles_to_attotime((ta_yuv_u_size/16)*(ta_yuv_v_size/16)*0x180)); - } - } - } -} - -// SB_LMMODE0 -void powervr2_device::ta_texture_directpath0_w(offs_t offset, uint64_t data, uint64_t mem_mask) -{ - // That's not in the pvr control address space, it's in g2's - // int mode = pvrctrl_regs[SB_LMMODE0]&1; - int mode = 0; - if (mode&1) - { - printf("ta_texture_directpath0_w 32-bit access!\n"); - COMBINE_DATA(&dc_framebuffer_ram[offset]); - } - else - { - COMBINE_DATA(&dc_texture_ram[offset]); - } -} - -// SB_LMMODE1 -void powervr2_device::ta_texture_directpath1_w(offs_t offset, uint64_t data, uint64_t mem_mask) -{ - // That's not in the pvr control address space, it's in g2's - // int mode = pvrctrl_regs[SB_LMMODE1]&1; - int mode = 0; - if (mode&1) - { - printf("ta_texture_directpath1_w 32-bit access!\n"); - COMBINE_DATA(&dc_framebuffer_ram[offset]); - } - else - { - COMBINE_DATA(&dc_texture_ram[offset]); - } -} - -/* test video start */ -uint32_t powervr2_device::dilate0(uint32_t value,int bits) // dilate first "bits" bits in "value" -{ - uint32_t x,m1,m2,m3; - int a; - - x = value; - for (a=0;a < bits;a++) - { - m2 = 1 << (a << 1); - m1 = m2 - 1; - m3 = (~m1) << 1; - x = (x & m1) + (x & m2) + ((x & m3) << 1); - } - return x; -} - -uint32_t powervr2_device::dilate1(uint32_t value,int bits) // dilate first "bits" bits in "value" -{ - uint32_t x,m1,m2,m3; - int a; - - x = value; - for (a=0;a < bits;a++) - { - m2 = 1 << (a << 1); - m1 = m2 - 1; - m3 = (~m1) << 1; - x = (x & m1) + ((x & m2) << 1) + ((x & m3) << 1); - } - return x; -} - -void powervr2_device::computedilated() -{ - int a,b; - - for (b=0;b <= 14;b++) - for (a=0;a < 1024;a++) { - dilated0[b][a]=dilate0(a,b); - dilated1[b][a]=dilate1(a,b); - } - for (b=0;b <= 7;b++) - for (a=0;a <= 7;a++) - dilatechose[(b << 3) + a]=3+(a < b ? a : b); -} - -inline uint32_t powervr2_device::sample_nontextured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color) -{ - return bls24(base_color, offset_color) | (base_color & 0xff000000); -} - -template -inline uint32_t powervr2_device::sample_textured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color) -{ - uint32_t tmp; - uint32_t c = (this->*(ti->r))(ti, u, v); - if (bilinear) - { - uint32_t c1 = (this->*(ti->r))(ti, u+1.0f, v); - uint32_t c2 = (this->*(ti->r))(ti, u+1.0f, v+1.0f); - uint32_t c3 = (this->*(ti->r))(ti, u, v+1.0f); - c = bilinear_filter(c, c1, c2, c3, u, v); - } - - switch (tsinst) { - case 0: - // decal - c = bls24(c, offset_color) | (c & 0xff000000); - break; - case 1: - // modulate - tmp = blc(c, base_color); - tmp = bls24(tmp, offset_color); - tmp |= c & 0xff000000; - c = tmp; - break; - case 2: - // decal with alpha - tmp = bls24(bla(c, c), blia(base_color, c)); - c = bls24(tmp, offset_color) | (base_color & 0xff000000); - break; - case 3: - // modulate with alpha - tmp = blc(c, base_color); - tmp = bls24(tmp, offset_color); - tmp |= (((c >> 24) * (base_color >> 24)) >> 8) << 24; - c = tmp; - break; - } - return c; -} - -template -inline void powervr2_device::render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, float xl, float xr, float ul, float ur, float vl, float vr, float wl, float wr, float const bl_in[4], float const br_in[4], float const offl_in[4], float const offr_in[4]) -{ - int idx; - int xxl, xxr; - float dx, ddx, dudx, dvdx, dwdx; - uint32_t *tdata; - float *wbufline; - - float bl[4], offl[4]; - - if(xr < 0 || xl >= 640) - return; - - xxl = round(xl); - xxr = round(xr); - - if(xxl == xxr) - return; - - memcpy(bl, bl_in, sizeof(bl)); - memcpy(offl, offl_in, sizeof(offl)); - - dx = xr-xl; - float dx_recip = 1.0f / dx; - - dudx = (ur-ul) * dx_recip; - dvdx = (vr-vl) * dx_recip; - dwdx = (wr-wl) * dx_recip; - - float dbdx[4] = { - (br_in[0] - bl[0]) * dx_recip, - (br_in[1] - bl[1]) * dx_recip, - (br_in[2] - bl[2]) * dx_recip, - (br_in[3] - bl[3]) * dx_recip - }; - - float dodx[4] = { - (offr_in[0] - offl[0]) * dx_recip, - (offr_in[1] - offl[1]) * dx_recip, - (offr_in[2] - offl[2]) * dx_recip, - (offr_in[3] - offl[3]) * dx_recip - }; - - if(xxl < 0) - xxl = 0; - if(xxr > 640) - xxr = 640; - - // Target the pixel center - ddx = xxl + 0.5f - xl; - ul += ddx*dudx; - vl += ddx*dvdx; - wl += ddx*dwdx; - for (idx = 0; idx < 4; idx++) { - bl[idx] += ddx * dbdx[idx]; - offl[idx] += ddx * dodx[idx]; - } - - tdata = &bitmap.pix(y, xxl); - wbufline = &wbuffer[y][xxl]; - - while(xxl < xxr) { - if((wl >= *wbufline)) { - uint32_t c; - float u = ul/wl; - float v = vl/wl; - uint32_t offset_color = float_argb_to_packed_argb(offl); - uint32_t base_color = float_argb_to_packed_argb(bl); - c = (this->*sample_fn)(ti, u, v, offset_color, base_color); - if (group_no == DISPLAY_LIST_OPAQUE) { - *tdata = c; - *wbufline = wl; - } else { - if(c & 0xff000000) { - *wbufline = wl; - *tdata = ti->blend(c, *tdata); - } - } - } - wbufline++; - tdata++; - - ul += dudx; - vl += dvdx; - wl += dwdx; - for (idx = 0; idx < 4; idx++) { - bl[idx] += dbdx[idx]; - offl[idx] += dodx[idx]; - } - xxl ++; - } -} - -template -inline void powervr2_device::render_span(bitmap_rgb32 &bitmap, texinfo *ti, - float y0, float y1, - float xl, float xr, - float ul, float ur, - float vl, float vr, - float wl, float wr, - float const bl_in[4], float const br_in[4], - float const offl_in[4], float const offr_in[4], - float dxldy, float dxrdy, - float duldy, float durdy, - float dvldy, float dvrdy, - float dwldy, float dwrdy, - float const dbldy[4], float const dbrdy[4], - float const doldy[4], float const dordy[4]) -{ - int idx; - float dy; - int yy0, yy1; - - if(y1 <= 0) - return; - if(y1 > 480) - y1 = 480; - - float bl[4], br[4], offl[4], offr[4]; - memcpy(bl, bl_in, sizeof(bl)); - memcpy(br, br_in, sizeof(br)); - memcpy(offl, offl_in, sizeof(offl)); - memcpy(offr, offr_in, sizeof(offr)); - - if(y0 < 0) { - xl += -dxldy*y0; - xr += -dxrdy*y0; - ul += -duldy*y0; - ur += -durdy*y0; - vl += -dvldy*y0; - vr += -dvrdy*y0; - wl += -dwldy*y0; - wr += -dwrdy*y0; - - for (idx = 0; idx < 4; idx++) { - bl[idx] += -dbldy[idx] * y0; - br[idx] += -dbrdy[idx] * y0; - offl[idx] += -doldy[idx] * y0; - offr[idx] += -dordy[idx] * y0; - } - y0 = 0; - } - - yy0 = round(y0); - yy1 = round(y1); - - if((yy0 < 0 && y0 > 0) || (yy1 < 0 && y1 > 0)) //temp handling of int32 overflow, needed by hotd2/totd - return; - - dy = yy0+0.5f-y0; - - if(0) - fprintf(stderr, "%f %f %f %f -> %f %f | %f %f -> %f %f\n", - (double) y0, - (double) dy, (double) dxldy, (double) dxrdy, (double) (dy*dxldy), (double) (dy*dxrdy), - (double) xl, (double) xr, (double) (xl + dy*dxldy), (double) (xr + dy*dxrdy)); - xl += dy*dxldy; - xr += dy*dxrdy; - ul += dy*duldy; - ur += dy*durdy; - vl += dy*dvldy; - vr += dy*dvrdy; - wl += dy*dwldy; - wr += dy*dwrdy; - for (idx = 0; idx < 4; idx++) { - bl[idx] += dy * dbldy[idx]; - br[idx] += dy * dbrdy[idx]; - offl[idx] += dy * doldy[idx]; - offr[idx] += dy * dordy[idx]; - } - - while(yy0 < yy1) { - render_hline(bitmap, ti, yy0, xl, xr, ul, ur, vl, vr, wl, wr, bl, br, offl, offr); - - xl += dxldy; - xr += dxrdy; - ul += duldy; - ur += durdy; - vl += dvldy; - vr += dvrdy; - wl += dwldy; - wr += dwrdy; - for (idx = 0; idx < 4; idx++) { - bl[idx] += dbldy[idx]; - br[idx] += dbrdy[idx]; - offl[idx] += doldy[idx]; - offr[idx] += dordy[idx]; - } - - yy0 ++; - } -} - -void powervr2_device::sort_vertices(const vert *v, int *i0, int *i1, int *i2) -{ - float miny, maxy; - int imin, imax, imid; - miny = maxy = v[0].y; - imin = imax = 0; - - if(miny > v[1].y) { - miny = v[1].y; - imin = 1; - } else if(maxy < v[1].y) { - maxy = v[1].y; - imax = 1; - } - - if(miny > v[2].y) { - miny = v[2].y; - imin = 2; - } else if(maxy < v[2].y) { - maxy = v[2].y; - imax = 2; - } - - imid = (imin == 0 || imax == 0) ? (imin == 1 || imax == 1) ? 2 : 1 : 0; - - *i0 = imin; - *i1 = imid; - *i2 = imax; -} - - -template -inline void powervr2_device::render_tri_sorted(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v0, const vert *v1, const vert *v2) -{ - float dy01, dy02, dy12; - - float dx01dy, dx02dy, dx12dy, du01dy, du02dy, du12dy, dv01dy, dv02dy, dv12dy, dw01dy, dw02dy, dw12dy; - - if(v0->y >= 480 || v2->y < 0) - return; - - float db01[4] = { - v1->b[0] - v0->b[0], - v1->b[1] - v0->b[1], - v1->b[2] - v0->b[2], - v1->b[3] - v0->b[3] - }; - - float db02[4] = { - v2->b[0] - v0->b[0], - v2->b[1] - v0->b[1], - v2->b[2] - v0->b[2], - v2->b[3] - v0->b[3] - }; - - float db12[4] = { - v2->b[0] - v1->b[0], - v2->b[1] - v1->b[1], - v2->b[2] - v1->b[2], - v2->b[3] - v1->b[3] - }; - - float do01[4] = { - v1->o[0] - v0->o[0], - v1->o[1] - v0->o[1], - v1->o[2] - v0->o[2], - v1->o[3] - v0->o[3] - }; - - float do02[4] = { - v2->o[0] - v0->o[0], - v2->o[1] - v0->o[1], - v2->o[2] - v0->o[2], - v2->o[3] - v0->o[3] - }; - - float do12[4] = { - v2->o[0] - v1->o[0], - v2->o[1] - v1->o[1], - v2->o[2] - v1->o[2], - v2->o[3] - v1->o[3] - }; - - dy01 = v1->y - v0->y; - dy02 = v2->y - v0->y; - dy12 = v2->y - v1->y; - - float db01dy[4] = { - dy01 ? db01[0]/dy01 : 0, - dy01 ? db01[1]/dy01 : 0, - dy01 ? db01[2]/dy01 : 0, - dy01 ? db01[3]/dy01 : 0 - }; - - float db02dy[4] = { - dy01 ? db02[0]/dy02 : 0, - dy01 ? db02[1]/dy02 : 0, - dy01 ? db02[2]/dy02 : 0, - dy01 ? db02[3]/dy02 : 0 - }; - - float db12dy[4] = { - dy01 ? db12[0]/dy12 : 0, - dy01 ? db12[1]/dy12 : 0, - dy01 ? db12[2]/dy12 : 0, - dy01 ? db12[3]/dy12 : 0 - }; - - float do01dy[4] = { - dy01 ? do01[0]/dy01 : 0, - dy01 ? do01[1]/dy01 : 0, - dy01 ? do01[2]/dy01 : 0, - dy01 ? do01[3]/dy01 : 0 - }; - - float do02dy[4] = { - dy01 ? do02[0]/dy02 : 0, - dy01 ? do02[1]/dy02 : 0, - dy01 ? do02[2]/dy02 : 0, - dy01 ? do02[3]/dy02 : 0 - }; - - float do12dy[4] = { - dy01 ? do12[0]/dy12 : 0, - dy01 ? do12[1]/dy12 : 0, - dy01 ? do12[2]/dy12 : 0, - dy01 ? do12[3]/dy12 : 0 - }; - - dx01dy = dy01 ? (v1->x-v0->x)/dy01 : 0; - dx02dy = dy02 ? (v2->x-v0->x)/dy02 : 0; - dx12dy = dy12 ? (v2->x-v1->x)/dy12 : 0; - - du01dy = dy01 ? (v1->u-v0->u)/dy01 : 0; - du02dy = dy02 ? (v2->u-v0->u)/dy02 : 0; - du12dy = dy12 ? (v2->u-v1->u)/dy12 : 0; - - dv01dy = dy01 ? (v1->v-v0->v)/dy01 : 0; - dv02dy = dy02 ? (v2->v-v0->v)/dy02 : 0; - dv12dy = dy12 ? (v2->v-v1->v)/dy12 : 0; - - dw01dy = dy01 ? (v1->w-v0->w)/dy01 : 0; - dw02dy = dy02 ? (v2->w-v0->w)/dy02 : 0; - dw12dy = dy12 ? (v2->w-v1->w)/dy12 : 0; - - if(!dy01) { - if(!dy12) - return; - - if(v1->x > v0->x) - render_span(bitmap, ti, v1->y, v2->y, v0->x, v1->x, v0->u, v1->u, v0->v, v1->v, v0->w, v1->w, v0->b, v1->b, v0->o, v1->o, dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy, db02dy, db12dy, do02dy, do12dy); - else - render_span(bitmap, ti, v1->y, v2->y, v1->x, v0->x, v1->u, v0->u, v1->v, v0->v, v1->w, v0->w, v1->b, v0->b, v1->o, v0->o, dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy, db12dy, db02dy, do12dy, do02dy); - - } else if(!dy12) { - if(v2->x > v1->x) - render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy, db01dy, db02dy, do01dy, do02dy); - else - render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy, db02dy, db01dy, do02dy, do01dy); - - } else { - float idk_b[4] = { - v0->b[0] + db02dy[0] * dy01, - v0->b[1] + db02dy[1] * dy01, - v0->b[2] + db02dy[2] * dy01, - v0->b[3] + db02dy[3] * dy01 - }; - float idk_o[4] = { - v0->o[0] + do02dy[0] * dy01, - v0->o[1] + do02dy[1] * dy01, - v0->o[2] + do02dy[2] * dy01, - v0->o[3] + do02dy[3] * dy01 - }; - if(dx01dy < dx02dy) { - render_span(bitmap, ti, v0->y, v1->y, - v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, - dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy, db01dy, db02dy, do01dy, do02dy); - render_span(bitmap, ti, v1->y, v2->y, - v1->x, v0->x + dx02dy*dy01, v1->u, v0->u + du02dy*dy01, v1->v, v0->v + dv02dy*dy01, v1->w, v0->w + dw02dy*dy01, v1->b, idk_b, v1->o, idk_o, - dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy, db12dy, db02dy, do12dy, do02dy); - } else { - render_span(bitmap, ti, v0->y, v1->y, - v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, - dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy, db02dy, db01dy, do02dy, do01dy); - render_span(bitmap, ti, v1->y, v2->y, - v0->x + dx02dy*dy01, v1->x, v0->u + du02dy*dy01, v1->u, v0->v + dv02dy*dy01, v1->v, v0->w + dw02dy*dy01, v1->w, idk_b, v1->b, idk_o, v1->o, - dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy, db02dy, db12dy, do02dy, do12dy); - } - } -} - -template -void powervr2_device::render_tri(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v) -{ - int i0, i1, i2; - - sort_vertices(v, &i0, &i1, &i2); - - bool textured = ti->textured; - if (textured) { - bool bilinear = (debug_dip_status & 1) && - (ti->filter_mode >= TEX_FILTER_BILINEAR); - if (bilinear) { - switch (ti->tsinstruction) { - case 0: - render_tri_sorted<&powervr2_device::sample_textured<0,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - break; - case 1: - render_tri_sorted<&powervr2_device::sample_textured<1,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - break; - case 2: - render_tri_sorted<&powervr2_device::sample_textured<2,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - break; - case 3: - render_tri_sorted<&powervr2_device::sample_textured<3,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - break; - default: - /* - * This should be impossible because tsinstruction was previously - * AND'd with 3 - */ - logerror("%s - tsinstruction is 0x%08x\n", (unsigned)ti->tsinstruction); - render_tri_sorted<&powervr2_device::sample_nontextured, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - } - } else { - switch (ti->tsinstruction) { - case 0: - render_tri_sorted<&powervr2_device::sample_textured<0,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - break; - case 1: - render_tri_sorted<&powervr2_device::sample_textured<1,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - break; - case 2: - render_tri_sorted<&powervr2_device::sample_textured<2,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - break; - case 3: - render_tri_sorted<&powervr2_device::sample_textured<3,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - break; - default: - /* - * This should be impossible because tsinstruction was previously - * AND'd with 3 - */ - logerror("%s - tsinstruction is 0x%08x\n", (unsigned)ti->tsinstruction); - render_tri_sorted<&powervr2_device::sample_nontextured, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - } - } - } else { - render_tri_sorted<&powervr2_device::sample_nontextured, group_no>(bitmap, ti, v+i0, v+i1, v+i2); - } -} - -template -void powervr2_device::render_group_to_accumulation_buffer(bitmap_rgb32 &bitmap,const rectangle &cliprect) -{ -#if 0 - int stride; - uint16_t *bmpaddr16; - uint32_t k; -#endif - - - if (renderselect < 0) - return; - - //printf("drawtest!\n"); - - int rs=renderselect; - - struct poly_group *grp = grab[rs].groups + group_no; - - int ns=grp->strips_size; - - for (int cs=0;cs < ns;cs++) - { - strip *ts = &grp->strips[cs]; - int sv = ts->svert; - int ev = ts->evert; - int i; - if(ev == -1) - continue; - - for(i=sv; i <= ev; i++) - { - vert *tv = grab[rs].verts + i; - tv->u = tv->u * ts->ti.sizex * tv->w; - tv->v = tv->v * ts->ti.sizey * tv->w; - } - - for(i=sv; i <= ev-2; i++) - { - if (!(debug_dip_status&0x2)) - render_tri(bitmap, &ts->ti, grab[rs].verts + i); - - } - } -} - -void powervr2_device::render_to_accumulation_buffer(bitmap_rgb32 &bitmap, const rectangle &cliprect) { - if (renderselect < 0) - return; - - memset(wbuffer, 0x00, sizeof(wbuffer)); - - dc_state *state = machine().driver_data(); - address_space &space = state->m_maincpu->space(AS_PROGRAM); - - // TODO: read ISP/TSP command from isp_background_t instead of assuming Gourad-shaded - // full-screen polygon. - uint32_t c=space.read_dword(0x05000000+(param_base&0xf00000)+((isp_backgnd_t&0xfffff8)>>1)+(3+3)*4); - bitmap.fill(c, cliprect); - - // TODO: modifier volumes - render_group_to_accumulation_buffer(bitmap, cliprect); - render_group_to_accumulation_buffer(bitmap, cliprect); - render_group_to_accumulation_buffer(bitmap, cliprect); - - grab[renderselect].busy=0; -} - -// copies the accumulation buffer into the framebuffer, converting to the specified format -// not accurate, ignores field stuff and just uses SOF1 for now -// also ignores scale effects (can scale accumulation buffer to half size with filtering etc.) -// also can specify dither etc. -// basically, just a crude implementation! - -/* 0555KRGB = 0 */ -void powervr2_device::fb_convert_0555krgb_to_555rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000f800) >> 11)) << 5) | - ((((data & 0x00f80000) >> 19)) << 10); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_0555krgb_to_565rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000f800) >> 11)) << 5) | - ((((data & 0x00f80000) >> 19)) << 11); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_0555krgb_to_888rgb24(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xf8f8f8); - - space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); - space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); - space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); - } - } -} - -void powervr2_device::fb_convert_0555krgb_to_888rgb32(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xf8f8f8); - - space.write_dword(realwriteoffs+xcnt*4, newdat); - } - } -} - -/* 0565RGB = 1 */ -void powervr2_device::fb_convert_0565rgb_to_555rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000fc00) >> 10)) << 5) | - ((((data & 0x00f80000) >> 19)) << 10); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_0565rgb_to_565rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000fc00) >> 10)) << 5) | - ((((data & 0x00f80000) >> 19)) << 11); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_0565rgb_to_888rgb24(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xf8fcf8); - - space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); - space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); - space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); - } - } -} - -void powervr2_device::fb_convert_0565rgb_to_888rgb32(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xf8fcf8); - - space.write_dword(realwriteoffs+xcnt*4, newdat); - } - } -} - -/* 1555ARGB = 3 */ -void powervr2_device::fb_convert_1555argb_to_555rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000f800) >> 11)) << 5) | - ((((data & 0x00f80000) >> 19)) << 10); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_1555argb_to_565rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000f800) >> 11)) << 5) | - ((((data & 0x00f80000) >> 19)) << 11); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_1555argb_to_888rgb24(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xf8f8f8); - - space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); - space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); - space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); - } - } -} - -void powervr2_device::fb_convert_1555argb_to_888rgb32(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xf8f8f8); - - space.write_dword(realwriteoffs+xcnt*4, newdat); - } - } -} - -/* 888RGB = 4 */ -void powervr2_device::fb_convert_888rgb_to_555rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000f800) >> 11)) << 5) | - ((((data & 0x00f80000) >> 16)) << 10); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_888rgb_to_565rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000fc00) >> 11)) << 5) | - ((((data & 0x00f80000) >> 16)) << 11); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_888rgb_to_888rgb24(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xffffff); - - space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); - space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); - space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); - } - } -} - -void powervr2_device::fb_convert_888rgb_to_888rgb32(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xffffff); - - space.write_dword(realwriteoffs+xcnt*4, newdat); - } - } -} - - -/* 8888ARGB = 6 */ -void powervr2_device::fb_convert_8888argb_to_555rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000f800) >> 11)) << 5) | - ((((data & 0x00f80000) >> 16)) << 10); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_8888argb_to_565rgb(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) | - ((((data & 0x0000fc00) >> 11)) << 5) | - ((((data & 0x00f80000) >> 16)) << 11); - - space.write_word(realwriteoffs+xcnt*2, newdat); - } - } -} - -void powervr2_device::fb_convert_8888argb_to_888rgb24(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xffffff); - - space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0); - space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8); - space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16); - } - } -} - -void powervr2_device::fb_convert_8888argb_to_888rgb32(address_space &space, int x,int y) -{ - for (int ycnt=0;ycnt<32;ycnt++) - { - uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4); - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x); - - for (int xcnt=0;xcnt<32;xcnt++) - { - // data starts in 8888 format, downsample it - uint32_t data = src[xcnt]; - uint32_t newdat = (data & 0xffffff); - - space.write_dword(realwriteoffs+xcnt*4, newdat); - } - } -} - - -/* - -0x0 0555 KRGB 16 bit (default) Bit 15 is the value of fb_kval 7. -0x1 565 RGB 16 bit -0x2 4444 ARGB 16 bit -0x3 1555 ARGB 16 bit The alpha value is determined by comparison with the value of fb_alpha_threshold. -0x4 888 RGB 24 bit packed -0x5 0888 KRGB 32 bit K is the value of fk_kval. -0x6 8888 ARGB 32 bit -0x7 Setting prohibited. - -*/ - -void powervr2_device::pvr_accumulationbuffer_to_framebuffer(address_space &space, int x,int y) -{ - // the accumulation buffer is always 8888 - // - // the standard format for the framebuffer appears to be 565 - // yes, this means colour data is lost in the conversion - - uint8_t packmode = fb_w_ctrl & 0x7; - uint8_t unpackmode = (fb_r_ctrl & 0x0000000c) >>2; // aka fb_depth - -// popmessage("%02x %02x",packmode,unpackmode); - - switch (packmode) - { - // used by ringout - case 0x00: //0555 KRGB - { - switch(unpackmode) - { - case 0x00: fb_convert_0555krgb_to_555rgb(space,x,y); break; - case 0x01: fb_convert_0555krgb_to_565rgb(space,x,y); break; - case 0x02: fb_convert_0555krgb_to_888rgb24(space,x,y); break; - case 0x03: fb_convert_0555krgb_to_888rgb32(space,x,y); break; - } - } - break; - - // used by cleoftp - case 0x01: //565 RGB 16 bit - { - switch(unpackmode) - { - case 0x00: fb_convert_0565rgb_to_555rgb(space,x,y); break; - case 0x01: fb_convert_0565rgb_to_565rgb(space,x,y); break; - case 0x02: fb_convert_0565rgb_to_888rgb24(space,x,y); break; - case 0x03: fb_convert_0565rgb_to_888rgb32(space,x,y); break; - } - } - break; - - case 0x02: - printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (4444 ARGB)\n",x,y,packmode); - break; - - case 0x03: // 1555 ARGB 16 bit - { - switch(unpackmode) - { - case 0x00: fb_convert_1555argb_to_555rgb(space,x,y); break; - case 0x01: fb_convert_1555argb_to_565rgb(space,x,y); break; - case 0x02: fb_convert_1555argb_to_888rgb24(space,x,y); break; - case 0x03: fb_convert_1555argb_to_888rgb32(space,x,y); break; - } - } - break; - - // used by Suchie3 - case 0x04: // 888 RGB 24-bit - { - switch(unpackmode) - { - case 0x00: fb_convert_888rgb_to_555rgb(space,x,y); break; - case 0x01: fb_convert_888rgb_to_565rgb(space,x,y); break; - case 0x02: fb_convert_888rgb_to_888rgb24(space,x,y); break; - case 0x03: fb_convert_888rgb_to_888rgb32(space,x,y); break; - } - } - break; - - case 0x05: // 0888 KRGB 32 bit - { - switch(unpackmode) - { - case 0x00: fb_convert_8888argb_to_555rgb(space,x,y); break; - case 0x01: fb_convert_8888argb_to_565rgb(space,x,y); break; - case 0x02: fb_convert_8888argb_to_888rgb24(space,x,y); break; - case 0x03: fb_convert_8888argb_to_888rgb32(space,x,y); break; - } - } - break; - - case 0x06: // 8888 ARGB 32 bit - { - switch(unpackmode) - { - case 0x00: fb_convert_8888argb_to_555rgb(space,x,y); break; - case 0x01: fb_convert_8888argb_to_565rgb(space,x,y); break; - case 0x02: fb_convert_8888argb_to_888rgb24(space,x,y); break; - case 0x03: fb_convert_8888argb_to_888rgb32(space,x,y); break; - } - } - break; - - case 0x07: - throw emu_fatalerror("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (Reserved! Don't Use!)\n",x,y,packmode); - break; - } -} - -void powervr2_device::pvr_drawframebuffer(bitmap_rgb32 &bitmap,const rectangle &cliprect) -{ - int dy,xi; - uint8_t interlace_on = ((spg_control & 0x10) >> 4); - int32_t ystart_f1 = (vo_starty & 0x3ff) << interlace_on; - //int32_t ystart_f2 = (vo_starty >> 16) & 0x3ff; - int32_t hstart = (vo_startx & 0x3ff); -// rectangle fbclip; - - uint8_t unpackmode = (fb_r_ctrl & 0x0000000c) >>2; // aka fb_depth - uint8_t enable = (fb_r_ctrl & 0x00000001); - - // ?? - if (!enable) return; - - // only for rgb565 framebuffer - xi=((fb_r_size & 0x3ff)+1) << 1; - dy=((fb_r_size >> 10) & 0x3ff)+1; - - dy++; - dy*=2; // probably depends on interlace mode, fields etc... - -// popmessage("%d %d %d %d %d",ystart_f1,ystart_f2,interlace_on,spg_vblank & 0x3ff,(spg_vblank >> 16) & 0x3ff); - -#if 0 - fbclip.min_x = hstart; - fbclip.min_y = ystart_f1; - fbclip.max_x = hstart + (xi << ((vo_control & 0x100) >> 8)); - fbclip.max_y = ystart_f1 + dy; - - popmessage("%d %d %d %d",fbclip.min_x,fbclip.min_y,fbclip.max_x,fbclip.max_y); -#endif - - switch (unpackmode) - { - case 0x00: // 0555 RGB 16-bit, Cleo Fortune Plus - // should upsample back to 8-bit output using fb_concat - for (int y=0;y <= dy;y++) - { - uint32_t addrp = fb_r_sof1+y*xi*2; - if(vo_control & 0x100) - { - for (int x=0;x < xi;x++) - { - int res_x = x*2+0 + hstart; - int res_y = y + ystart_f1; - - uint32_t *fbaddr=&bitmap.pix(res_y, res_x); - uint32_t c=*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); - - uint32_t b = (c & 0x001f) << 3; - uint32_t g = (c & 0x03e0) >> 2; - uint32_t r = (c & 0x7c00) >> 7; - - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - - res_x = x*2+1 + hstart; - - fbaddr=&bitmap.pix(res_y, res_x); - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - addrp+=2; - } - } - else - { - for (int x=0;x < xi;x++) - { - int res_x = x + hstart; - int res_y = y + ystart_f1; - - uint32_t *fbaddr=&bitmap.pix(res_y, res_x); - uint32_t c=*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); - - uint32_t b = (c & 0x001f) << 3; - uint32_t g = (c & 0x03e0) >> 2; - uint32_t r = (c & 0x7c00) >> 7; - - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - addrp+=2; - } - } - } - break; - - case 0x01: // 0565 RGB 16-bit - // should upsample back to 8-bit output using fb_concat - for (int y=0;y <= dy;y++) - { - uint32_t addrp = fb_r_sof1+y*xi*2; - if(vo_control & 0x100) - { - for (int x=0;x < xi;x++) - { - int res_x = x*2+0 + hstart; - int res_y = y + ystart_f1; - uint32_t *fbaddr=&bitmap.pix(res_y, res_x); - uint32_t c=*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); - - uint32_t b = (c & 0x001f) << 3; - uint32_t g = (c & 0x07e0) >> 3; - uint32_t r = (c & 0xf800) >> 8; - - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - - res_x = x*2+1 + hstart; - //res_y = y + ystart_f1; - fbaddr=&bitmap.pix(res_y, res_x); - - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - - addrp+=2; - } - } - else - { - for (int x=0;x < xi;x++) - { - int res_x = x + hstart; - int res_y = y + ystart_f1; - uint32_t *fbaddr=&bitmap.pix(res_y, res_x); - uint32_t c=*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); - - uint32_t b = (c & 0x001f) << 3; - uint32_t g = (c & 0x07e0) >> 3; - uint32_t r = (c & 0xf800) >> 8; - - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - addrp+=2; - } - } - } - break; - - case 0x02: ; // 888 RGB 24-bit - suchie3, Soul Calibur - for (int y=0;y <= dy;y++) - { - uint32_t addrp = fb_r_sof1+y*xi*2; - - if(vo_control & 0x100) - { - for (int x=0;x < xi;x++) - { - int res_x = x*2+0 + hstart; - int res_y = y + ystart_f1; - - uint32_t *fbaddr=&bitmap.pix(res_y, res_x); - - uint32_t b =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp)); - - uint32_t g =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+1)); - - uint32_t r =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+2)); - - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - - res_x = x*2+1 + hstart; - - fbaddr=&bitmap.pix(res_y, res_x); - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - - addrp+=3; - } - } - else - { - for (int x=0;x < xi;x++) - { - int res_x = x + hstart; - int res_y = y + ystart_f1; - uint32_t *fbaddr=&bitmap.pix(res_y, res_x); - - uint32_t b =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp)); - - uint32_t g =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+1)); - - uint32_t r =*(uint8_t *)((reinterpret_cast(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+2)); - - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - - addrp+=3; - } - } - } - break; - - case 0x03: // 0888 ARGB 32-bit - for (int y=0;y <= dy;y++) - { - uint32_t addrp = fb_r_sof1+y*xi*2; - - if(vo_control & 0x100) - { - for (int x=0;x < xi;x++) - { - int res_x = x*2+0 + hstart; - int res_y = y + ystart_f1; - - uint32_t *fbaddr=&bitmap.pix(res_y, res_x); - uint32_t c =*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 2)); - - uint32_t b = (c & 0x0000ff) >> 0; - uint32_t g = (c & 0x00ff00) >> 8; - uint32_t r = (c & 0xff0000) >> 16; - - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - - res_x = x*2+1 + hstart; - - fbaddr=&bitmap.pix(res_y, res_x); - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - - addrp+=4; - } - } - else - { - for (int x=0;x < xi;x++) - { - int res_x = x + hstart; - int res_y = y + ystart_f1; - uint32_t *fbaddr=&bitmap.pix(res_y, res_x); - uint32_t c =*((reinterpret_cast(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 2)); - - uint32_t b = (c & 0x0000ff) >> 0; - uint32_t g = (c & 0x00ff00) >> 8; - uint32_t r = (c & 0xff0000) >> 16; - - if (cliprect.contains(res_x, res_y)) - *fbaddr = b | (g<<8) | (r<<16); - - addrp+=4; - } - } - } - break; - } -} - -/* test video end */ - -void powervr2_device::pvr_build_parameterconfig() -{ - int a,b,c,d,e,p; - - for (a = 0;a <= 63;a++) - pvr_parameterconfig[a] = -1; - p=0; - // volume,col_type,texture,offset,16bit_uv - for (a = 0;a <= 1;a++) - for (b = 0;b <= 3;b++) - for (c = 0;c <= 1;c++) - if (c == 0) - { - for (d = 0;d <= 1;d++) - for (e = 0;e <= 1;e++) - pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p]; - p++; - } - else - for (d = 0;d <= 1;d++) - for (e = 0;e <= 1;e++) - { - pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p]; - p++; - } - for (a = 1;a <= 63;a++) - if (pvr_parameterconfig[a] < 0) - pvr_parameterconfig[a] = pvr_parameterconfig[a-1]; -} - -// TODO: these two are currently unused -TIMER_CALLBACK_MEMBER(powervr2_device::vbin) -{ - LOGIRQ("[%d] VBL IN %d\n", screen().frame_number(), screen().vpos()); - LOGIRQ(" VII %d VOI %d VI %d VO %d VS %d\n", - spg_vblank_int & 0x3ff, (spg_vblank_int >> 16) & 0x3ff, - spg_vblank & 0x3ff, (spg_vblank >> 16) & 0x3ff, (spg_load >> 16) & 0x3ff - ); - - irq_cb(VBL_IN_IRQ); - -// vbin_timer->adjust(screen().time_until_pos(spg_vblank_int & 0x3ff)); -} - -TIMER_CALLBACK_MEMBER(powervr2_device::vbout) -{ - LOGIRQ("[%d] VBL OUT %d\n", screen().frame_number(), screen().vpos()); - - irq_cb(VBL_OUT_IRQ); - -// vbout_timer->adjust(screen().time_until_pos((spg_vblank_int >> 16) & 0x3ff)); -} - -TIMER_CALLBACK_MEMBER(powervr2_device::hbin) -{ - if(spg_hblank_int & 0x1000) - { - if(scanline == next_y) - { - LOGIRQ("[%d] HBL IN %d - (%08x)\n", - screen().frame_number(), screen().vpos(), scanline, spg_hblank_int - ); - irq_cb(HBL_IN_IRQ); - next_y += spg_hblank_int & 0x3ff; - } - } - else if((scanline == (spg_hblank_int & 0x3ff)) || (spg_hblank_int & 0x2000)) - { - LOGIRQ("[%d] HBL IN %d - (%08x)\n", - screen().frame_number(), screen().vpos(), scanline, spg_hblank_int - ); - irq_cb(HBL_IN_IRQ); - } - - scanline++; - - if(scanline >= ((spg_load >> 16) & 0x3ff)) - { - scanline = 0; - next_y = spg_hblank_int & 0x3ff; - } - - hbin_timer->adjust(screen().time_until_pos(scanline, ((spg_hblank_int >> 16) & 0x3ff)-1)); -} - -// TODO: these two aren't really called atm -TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_video) -{ - LOGIRQ("[%d] VIDEO END %d\n", screen().frame_number(), screen().vpos()); -// endofrender_timer_video->adjust(attotime::never); -} - -TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_tsp) -{ - LOGIRQ("[%d] TSP END %d\n", screen().frame_number(), screen().vpos()); - -// endofrender_timer_tsp->adjust(attotime::never); -// endofrender_timer_video->adjust(attotime::from_usec(500) ); -} - -TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_isp) -{ - irq_cb(EOR_ISP_IRQ); // ISP end of render - irq_cb(EOR_TSP_IRQ); // TSP end of render - irq_cb(EOR_VIDEO_IRQ); // VIDEO end of render - - LOGIRQ("[%d] ISP END %d\n", screen().frame_number(), screen().vpos()); - - endofrender_timer_isp->adjust(attotime::never); -// endofrender_timer_tsp->adjust(attotime::from_usec(500) ); -} - -uint32_t powervr2_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - /****************** - MAME note - ******************* - - The video update function should NOT be generating interrupts, setting timers or doing _anything_ the game might be able to detect - as it will be called at different times depending on frameskip etc. - - Rendering should happen when the hardware requests it, to the framebuffer(s) - - Everything else should depend on timers. - - ******************/ - -// static int useframebuffer=1; -// const rectangle &visarea = screen.visible_area(); - - // copy our fake framebuffer bitmap (where things have been rendered) to the screen -#if 0 - for (int y = visarea->min_y ; y <= visarea->max_y ; y++) - { - for (int x = visarea->min_x ; x <= visarea->max_x ; x++) - { - uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y, x); - uint32_t *const dst = &bitmap.pix(y, x); - dst[0] = src[0]; - } - } -#endif - - //FIXME: additional Chroma bit - bitmap.fill(rgb_t(0xff, (vo_border_col >> 16) & 0xff, - (vo_border_col >> 8 ) & 0xff, - (vo_border_col ) & 0xff), cliprect); - - if(!(vo_control & 8)) - pvr_drawframebuffer(bitmap, cliprect); - - // update this here so we only do string lookup once per frame - debug_dip_status = m_mamedebug->read(); - - return 0; -} - -TIMER_CALLBACK_MEMBER(powervr2_device::pvr_dma_irq) -{ - LOGIRQ("[%d] PVR DMA %d\n", screen().frame_number(), screen().vpos()); - - m_pvr_dma.start = sb_pdst = 0; - irq_cb(DMA_PVR_IRQ); -} - -/* used so far by usagiym and sprtjam */ -// TODO: very inaccurate -void powervr2_device::pvr_dma_execute(address_space &space) -{ - dc_state *state = machine().driver_data(); - uint32_t src,dst,size; - dst = m_pvr_dma.pvr_addr; - src = m_pvr_dma.sys_addr; - size = 0; - - LOGPVRDMA("PVR-DMA start\n"); - LOGPVRDMA("%08x %08x %08x\n",m_pvr_dma.pvr_addr, m_pvr_dma.sys_addr, m_pvr_dma.size); - LOGPVRDMA("src %s dst %08x\n",m_pvr_dma.dir ? "->" : "<-",m_pvr_dma.sel); - - /* Throw illegal address set */ - // TODO: unimplemented for now, checkable from DCLP -#if 0 - if((m_pvr_dma.sys_addr & 0x1c000000) != 0x0c000000) - { - irq_cb(ERR_PVRIF_ILL_ADDR_IRQ); - m_pvr_dma.start = sb_pdst = 0; - printf("Illegal PVR DMA set\n"); - return; - } -#endif - - /* 0 rounding size = 16 Mbytes */ - if(m_pvr_dma.size == 0) { m_pvr_dma.size = 0x100000; } - - if(m_pvr_dma.dir == 0) - { - for(;size < m_pvr_dma.size; size+=4) - { - space.write_dword(dst,space.read_dword(src)); - src+=4; - dst+=4; - } - } - else - { - for(;size < m_pvr_dma.size; size+=4) - { - space.write_dword(src,space.read_dword(dst)); - src+=4; - dst+=4; - } - } - - /* Note: do not update the params, since this DMA type doesn't support it. */ - // TODO: accurate timing - dma_irq_timer->adjust(state->m_maincpu->cycles_to_attotime(m_pvr_dma.size/4)); -} - -INPUT_PORTS_START( powervr2 ) - PORT_START("PVR_DEBUG") - PORT_CONFNAME( 0x01, 0x00, "Bilinear Filtering" ) - PORT_CONFSETTING( 0x00, DEF_STR( No ) ) - PORT_CONFSETTING( 0x01, DEF_STR( Yes ) ) - PORT_CONFNAME( 0x02, 0x00, "Disable Render Calls" ) - PORT_CONFSETTING( 0x00, DEF_STR( No ) ) - PORT_CONFSETTING( 0x02, DEF_STR( Yes ) ) -INPUT_PORTS_END - -ioport_constructor powervr2_device::device_input_ports() const -{ - return INPUT_PORTS_NAME( powervr2 ); -} - -powervr2_device::powervr2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, POWERVR2, tag, owner, clock) - , device_video_interface(mconfig, *this) - , irq_cb(*this) - , m_mamedebug(*this, "PVR_DEBUG") -{ -} - -void powervr2_device::device_start() -{ - irq_cb.resolve_safe(); - - grab = std::make_unique(NUM_BUFFERS); - - pvr_build_parameterconfig(); - - computedilated(); - -// vbout_timer = timer_alloc(FUNC(powervr2_device::vbout), this); -// vbin_timer = timer_alloc(FUNC(powervr2_device::vbin), this); - hbin_timer = timer_alloc(FUNC(powervr2_device::hbin), this); - yuv_timer_end = timer_alloc(FUNC(powervr2_device::yuv_convert_end), this); - - endofrender_timer_isp = timer_alloc(FUNC(powervr2_device::endofrender_isp), this); - endofrender_timer_tsp = timer_alloc(FUNC(powervr2_device::endofrender_tsp), this); - endofrender_timer_video = timer_alloc(FUNC(powervr2_device::endofrender_video), this); - - opaque_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_opaque_list_irq), this); - opaque_modifier_volume_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_opaque_modifier_volume_list_irq), this); - translucent_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_translucent_list_irq), this); - translucent_modifier_volume_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_translucent_modifier_volume_list_irq), this); - punch_through_irq_timer = timer_alloc(FUNC(powervr2_device::transfer_punch_through_list_irq), this); - dma_irq_timer = timer_alloc(FUNC(powervr2_device::pvr_dma_irq), this); - - fake_accumulationbuffer_bitmap = std::make_unique(2048,2048); - - softreset = 0; - param_base = 0; - region_base = 0; - vo_border_col = 0; - fb_r_ctrl = 0; - fb_w_ctrl = 0; - fb_w_linestride = 0; - fb_r_sof1 = 0; - fb_r_sof2 = 0; - fb_r_size = 0; - fb_w_sof1 = 0; - fb_w_sof2 = 0; - fb_x_clip = 0; - fb_y_clip = 0; - fpu_param_cfg = 0; - isp_backgnd_t = 0; - spg_hblank_int = 0; - spg_vblank_int = 0; - spg_hblank = 0; - spg_load = 0; - spg_vblank = 0; - spg_width = 0; - spg_control = 0; - vo_control = 0; - vo_startx = 0; - vo_starty = 0; - text_control = 0; - pal_ram_ctrl = 0; - ta_ol_base = 0; - ta_ol_limit = 0; - ta_isp_base = 0; - ta_isp_limit = 0; - ta_next_opb = 0; - ta_itp_current = 0; - ta_alloc_ctrl = 0; - ta_next_opb_init = 0; - ta_yuv_tex_base = 0; - ta_yuv_tex_ctrl = 0; - ta_yuv_tex_cnt = 0; - memset(fog_table, 0, sizeof(fog_table)); - memset(palette, 0, sizeof(palette)); - memset(&m_pvr_dma, 0x00, sizeof(m_pvr_dma)); - - sb_pdstap = 0; - sb_pdstar = 0; - sb_pdlen = 0; - sb_pddir = 0; - sb_pdtsel = 0; - sb_pden = 0; - sb_pdst = 0; - sb_pdapro = 0; - - save_item(NAME(softreset)); - save_item(NAME(param_base)); - save_item(NAME(region_base)); - save_item(NAME(vo_border_col)); - save_item(NAME(fb_r_ctrl)); - save_item(NAME(fb_w_ctrl)); - save_item(NAME(fb_w_linestride)); - save_item(NAME(fb_r_sof1)); - save_item(NAME(fb_r_sof2)); - save_item(NAME(fb_r_size)); - save_item(NAME(fb_w_sof1)); - save_item(NAME(fb_w_sof2)); - save_item(NAME(fb_x_clip)); - save_item(NAME(fb_y_clip)); - save_item(NAME(fpu_param_cfg)); - save_item(NAME(isp_backgnd_t)); - save_item(NAME(spg_hblank_int)); - save_item(NAME(spg_vblank_int)); - save_item(NAME(spg_hblank)); - save_item(NAME(spg_load)); - save_item(NAME(spg_vblank)); - save_item(NAME(spg_width)); - save_item(NAME(vo_control)); - save_item(NAME(vo_startx)); - save_item(NAME(vo_starty)); - save_item(NAME(text_control)); - save_item(NAME(pal_ram_ctrl)); - save_item(NAME(ta_ol_base)); - save_item(NAME(ta_ol_limit)); - save_item(NAME(ta_isp_base)); - save_item(NAME(ta_isp_limit)); - save_item(NAME(ta_next_opb)); - save_item(NAME(ta_itp_current)); - save_item(NAME(ta_alloc_ctrl)); - save_item(NAME(ta_next_opb_init)); - save_item(NAME(ta_yuv_tex_base)); - save_item(NAME(ta_yuv_tex_ctrl)); - save_item(NAME(ta_yuv_tex_cnt)); - save_pointer(NAME(fog_table), 0x80); - save_pointer(NAME(palette), 0x400); - - save_item(NAME(sb_pdstap)); - save_item(NAME(sb_pdstar)); - save_item(NAME(sb_pdlen)); - save_item(NAME(sb_pddir)); - save_item(NAME(sb_pdtsel)); - save_item(NAME(sb_pden)); - save_item(NAME(sb_pdst)); - save_item(NAME(sb_pdapro)); - - save_item(NAME(m_pvr_dma.pvr_addr)); - save_item(NAME(m_pvr_dma.sys_addr)); - save_item(NAME(m_pvr_dma.size)); - save_item(NAME(m_pvr_dma.sel)); - save_item(NAME(m_pvr_dma.dir)); - save_item(NAME(m_pvr_dma.flag)); - save_item(NAME(m_pvr_dma.start)); - save_item(NAME(debug_dip_status)); - save_pointer(NAME(tafifo_buff),32); - save_item(NAME(scanline)); - save_item(NAME(next_y)); -} - -void powervr2_device::device_reset() -{ - softreset = 0x00000007; - vo_control = 0x00000108; - vo_startx = 0x0000009d; - vo_starty = 0x00150015; - spg_hblank = 0x007e0345; - spg_load = 0x01060359; - spg_vblank = 0x01500104; - spg_hblank_int = 0x031d0000; - spg_vblank_int = 0x01500104; - - tafifo_pos = 0; - tafifo_mask = 7; - tafifo_vertexwords = 8; - tafifo_listtype = DISPLAY_LIST_NONE; - start_render_received = 0; - renderselect = -1; - grabsel = 0; - -// vbout_timer->adjust(screen().time_until_pos((spg_vblank_int >> 16) & 0x3ff)); -// vbin_timer->adjust(screen().time_until_pos(spg_vblank_int & 0x3ff)); - hbin_timer->adjust(screen().time_until_pos(0, ((spg_hblank_int >> 16) & 0x3ff)-1)); - - scanline = 0; - next_y = 0; - - endofrender_timer_isp->adjust(attotime::never); - endofrender_timer_tsp->adjust(attotime::never); - endofrender_timer_video->adjust(attotime::never); - yuv_timer_end->adjust(attotime::never); - - dc_state *state = machine().driver_data(); - dc_texture_ram = state->dc_texture_ram.target(); - dc_framebuffer_ram = state->dc_framebuffer_ram.target(); -} - -/* called by TIMER_ADD_PERIODIC, in driver sections (controlled by SPG, that's a PVR sub-device) */ -void powervr2_device::pvr_scanline_timer(int vpos) -{ - int vbin_line = spg_vblank_int & 0x3ff; - int vbout_line = (spg_vblank_int >> 16) & 0x3ff; - uint8_t interlace_on = ((spg_control & 0x10) >> 4); - dc_state *state = machine().driver_data(); - - vbin_line <<= interlace_on; - vbout_line <<= interlace_on; - - if(vbin_line-(1+interlace_on) == vpos) - state->m_maple->maple_hw_trigger(); - - if(vbin_line == vpos) - { - LOGIRQ("[%d] VBL IN %d\n", screen().frame_number(), screen().vpos()); - LOGIRQ(" VII %d VOI %d VI %d VO %d VS %d\n", - spg_vblank_int & 0x3ff, (spg_vblank_int >> 16) & 0x3ff, - spg_vblank & 0x3ff, (spg_vblank >> 16) & 0x3ff, (spg_load >> 16) & 0x3ff - ); - irq_cb(VBL_IN_IRQ); - } - - if(vbout_line == vpos) - { - LOGIRQ("[%d] VBL OUT %d\n", screen().frame_number(), screen().vpos()); - irq_cb(VBL_OUT_IRQ); - } -} diff --git a/src/mame/shared/powervr2.h b/src/mame/shared/powervr2.h deleted file mode 100644 index a5457206c03..00000000000 --- a/src/mame/shared/powervr2.h +++ /dev/null @@ -1,581 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert -#ifndef MAME_VIDEO_POWERVR2_H -#define MAME_VIDEO_POWERVR2_H - -#pragma once - -class powervr2_device : public device_t, - public device_video_interface -{ -public: - powervr2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - auto irq_callback() { return irq_cb.bind(); } - static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } - - enum { NUM_BUFFERS = 4 }; - enum { - EOXFER_YUV_IRQ, - EOXFER_OPLST_IRQ, - EOXFER_OPMV_IRQ, - EOXFER_TRLST_IRQ, - EOXFER_TRMV_IRQ, - EOXFER_PTLST_IRQ, - VBL_IN_IRQ, - VBL_OUT_IRQ, - HBL_IN_IRQ, - EOR_VIDEO_IRQ, - EOR_TSP_IRQ, - EOR_ISP_IRQ, - DMA_PVR_IRQ, - ERR_ISP_LIMIT_IRQ, - ERR_PVRIF_ILL_ADDR_IRQ - }; - - void ta_map(address_map &map); - void pd_dma_map(address_map &map); - - struct { - uint32_t pvr_addr; - uint32_t sys_addr; - uint32_t size; - uint8_t sel; - uint8_t dir; - uint8_t flag; - uint8_t start; - } m_pvr_dma; - - static const int pvr_parconfseq[]; - static const int pvr_wordsvertex[24]; - static const int pvr_wordspolygon[24]; - int pvr_parameterconfig[128]; - uint32_t dilated0[15][1024]; - uint32_t dilated1[15][1024]; - int dilatechose[64]; - float wbuffer[480][640]; - - - // the real accumulation buffer is a 32x32x8bpp buffer into which tiles get rendered before they get copied to the framebuffer - // our implementation is not currently tile based, and thus the accumulation buffer is screen sized - std::unique_ptr fake_accumulationbuffer_bitmap; - - /* - * Per-polygon base and offset colors. These are scaled by per-vertex - * weights. - * - * These are only used if the colortype in the polygon header is 2 - * or 3. If it is 0 or 1, then each vertex's base and offset colors are - * specified completely independently of one another in the per-vertex - * parameters. - * - * The base color is combined with the texture sample (if any) according - * to one of four fixed functions. The offset color is then added to - * the combined texture sample and base color with the exception of - * alpha. - * - * poly_offs_color is not always used. Not specifying a poly_offs_color - * is equivalent to using a poly_offs_color of 0. - * - * poly_last_mode_2_base_color is used to hold the last base color - * specified using color type 2. Color type 3 will always use the last - * base color specified using color type 2. - */ - float poly_base_color[4], poly_offs_color[4], - poly_last_mode_2_base_color[4]; - - struct texinfo - { - uint32_t address = 0, vqbase = 0; - - uint32_t tsinstruction = 0; - - int textured = 0, sizex = 0, sizey = 0, stride = 0, sizes = 0, pf = 0, palette = 0, mode = 0, mipmapped = 0, blend_mode = 0, filter_mode = 0; - int coltype = 0; - - uint32_t (powervr2_device::*r)(texinfo *t, float x, float y) = nullptr; - uint32_t (*blend)(uint32_t s, uint32_t d) = nullptr; - int (*u_func)(float uv, int size) = nullptr; - int (*v_func)(float uv, int size) = nullptr; - int palbase = 0, cd = 0; - }; - - struct vert - { - float x = 0, y = 0, w = 0, u = 0, v = 0; - - // base and offset colors - float b[4] = { 0, 0, 0, 0 }, o[4] = { 0, 0, 0, 0 }; - }; - - struct strip - { - int svert = 0, evert = 0; - texinfo ti; - }; - - static const unsigned MAX_VERTS = 65536; - static const unsigned MAX_STRIPS = 65536; - - /* - * There are five polygon lists: - * - * Opaque - * Punch-through polygon - * Opaque/punch-through modifier volume - * Translucent - * Translucent modifier volume - * - * They are rendered in that order. List indices are are three bits, so - * technically there are 8 polygon lists, but only the first 5 are valid. - */ - enum { - DISPLAY_LIST_OPAQUE, - DISPLAY_LIST_OPAQUE_MOD, - DISPLAY_LIST_TRANS, - DISPLAY_LIST_TRANS_MOD, - DISPLAY_LIST_PUNCH_THROUGH, - DISPLAY_LIST_LAST, - - DISPLAY_LIST_COUNT, - - DISPLAY_LIST_NONE = -1 - }; - - struct poly_group { - strip strips[MAX_STRIPS]; - int strips_size = 0; - }; - - struct receiveddata { - vert verts[MAX_VERTS]; - struct poly_group groups[DISPLAY_LIST_COUNT]; - uint32_t ispbase = 0; - uint32_t fbwsof1 = 0; - uint32_t fbwsof2 = 0; - int busy = 0; - int valid = 0; - int verts_size = 0; - }; - - enum { - TEX_FILTER_NEAREST = 0, - TEX_FILTER_BILINEAR, - TEX_FILTER_TRILINEAR_A, - TEX_FILTER_TRILINEAR_B - }; - - int tafifo_pos, tafifo_mask, tafifo_vertexwords, tafifo_listtype; - int start_render_received; - int renderselect; - int listtype_used; - int alloc_ctrl_OPB_Mode, alloc_ctrl_PT_OPB, alloc_ctrl_TM_OPB, alloc_ctrl_T_OPB, alloc_ctrl_OM_OPB, alloc_ctrl_O_OPB; - std::unique_ptr grab; - int grabsel; - int grabsellast; - uint32_t paracontrol,paratype,endofstrip,listtype,global_paratype,parameterconfig; - uint32_t groupcontrol,groupen,striplen,userclip; - uint32_t objcontrol,shadow,volume,coltype,texture,offset_color_enable,gouraud,uv16bit; - uint32_t texturesizes,textureaddress,scanorder,pixelformat; - uint32_t blend_mode, srcselect,dstselect,fogcontrol,colorclamp, use_alpha; - uint32_t ignoretexalpha,flipuv,clampuv,filtermode,sstexture,mmdadjust,tsinstruction; - uint32_t depthcomparemode,cullingmode,zwritedisable,cachebypass,dcalcctrl,volumeinstruction,mipmapped,vqcompressed,strideselect,paletteselector; - - uint64_t *dc_texture_ram; - uint64_t *dc_framebuffer_ram; - - uint64_t *pvr2_texture_ram; - uint64_t *pvr2_framebuffer_ram; - - uint32_t debug_dip_status; - emu_timer *vbout_timer; - emu_timer *vbin_timer; - emu_timer *hbin_timer; - emu_timer *endofrender_timer_isp; - emu_timer *endofrender_timer_tsp; - emu_timer *endofrender_timer_video; - emu_timer *yuv_timer_end; - uint32_t tafifo_buff[32]; - int scanline; - int next_y; - - uint32_t id_r(); - uint32_t revision_r(); - uint32_t softreset_r(); - void softreset_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - void startrender_w(address_space &space, uint32_t data); - uint32_t param_base_r(); - void param_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t region_base_r(); - void region_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t vo_border_col_r(); - void vo_border_col_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_r_ctrl_r(); - void fb_r_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_w_ctrl_r(); - void fb_w_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_w_linestride_r(); - void fb_w_linestride_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_r_sof1_r(); - void fb_r_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_r_sof2_r(); - void fb_r_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_r_size_r(); - void fb_r_size_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_w_sof1_r(); - void fb_w_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_w_sof2_r(); - void fb_w_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_x_clip_r(); - void fb_x_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fb_y_clip_r(); - void fb_y_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t fpu_param_cfg_r(); - void fpu_param_cfg_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t isp_backgnd_t_r(); - void isp_backgnd_t_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t spg_hblank_int_r(); - void spg_hblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t spg_vblank_int_r(); - void spg_vblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t spg_control_r(); - void spg_control_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t spg_hblank_r(); - void spg_hblank_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t spg_load_r(); - void spg_load_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t spg_vblank_r(); - void spg_vblank_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t spg_width_r(); - void spg_width_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t text_control_r(); - void text_control_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t vo_control_r(); - void vo_control_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t vo_startx_r(); - void vo_startx_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t vo_starty_r(); - void vo_starty_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t pal_ram_ctrl_r(); - void pal_ram_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t spg_status_r(); - - uint32_t ta_ol_base_r(); - void ta_ol_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t ta_isp_base_r(); - void ta_isp_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t ta_ol_limit_r(); - void ta_ol_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t ta_isp_limit_r(); - void ta_isp_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t ta_next_opb_r(); - uint32_t ta_itp_current_r(); - uint32_t ta_alloc_ctrl_r(); - void ta_alloc_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t ta_list_init_r(); - void ta_list_init_w(uint32_t data); - uint32_t ta_yuv_tex_base_r(); - void ta_yuv_tex_base_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t ta_yuv_tex_ctrl_r(); - void ta_yuv_tex_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t ta_yuv_tex_cnt_r(); - void ta_list_cont_w(uint32_t data); - uint32_t ta_next_opb_init_r(); - void ta_next_opb_init_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - - - uint32_t fog_table_r(offs_t offset); - void fog_table_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t palette_r(offs_t offset); - void palette_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - - uint32_t sb_pdstap_r(); - void sb_pdstap_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t sb_pdstar_r(); - void sb_pdstar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t sb_pdlen_r(); - void sb_pdlen_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t sb_pddir_r(); - void sb_pddir_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t sb_pdtsel_r(); - void sb_pdtsel_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t sb_pden_r(); - void sb_pden_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t sb_pdst_r(); - void sb_pdst_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - uint32_t sb_pdapro_r(); - void sb_pdapro_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - - uint32_t pvr2_ta_r(offs_t offset); - - void ta_fifo_poly_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); - void ta_fifo_yuv_w(uint8_t data); - void ta_texture_directpath0_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); - void ta_texture_directpath1_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); - - TIMER_CALLBACK_MEMBER(vbin); - TIMER_CALLBACK_MEMBER(vbout); - TIMER_CALLBACK_MEMBER(hbin); - TIMER_CALLBACK_MEMBER(yuv_convert_end); - TIMER_CALLBACK_MEMBER(endofrender_video); - TIMER_CALLBACK_MEMBER(endofrender_tsp); - TIMER_CALLBACK_MEMBER(endofrender_isp); - TIMER_CALLBACK_MEMBER(transfer_opaque_list_irq); - TIMER_CALLBACK_MEMBER(transfer_opaque_modifier_volume_list_irq); - TIMER_CALLBACK_MEMBER(transfer_translucent_list_irq); - TIMER_CALLBACK_MEMBER(transfer_translucent_modifier_volume_list_irq); - TIMER_CALLBACK_MEMBER(transfer_punch_through_list_irq); - TIMER_CALLBACK_MEMBER(pvr_dma_irq); - - void pvr_dma_execute(address_space &space); - void pvr_scanline_timer(int vpos); - uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - typedef uint32_t(powervr2_device::*pix_sample_fn)(texinfo*,float,float,uint32_t,uint32_t); - - inline uint32_t sample_nontextured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color); - - template - inline uint32_t sample_textured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color); - -protected: - virtual void device_start() override; - virtual void device_reset() override; - ioport_constructor device_input_ports() const override; - -private: - devcb_write8 irq_cb; - required_ioport m_mamedebug; - - // Core registers - uint32_t softreset; - uint32_t param_base, region_base; - uint32_t vo_border_col; - uint32_t fb_r_ctrl, fb_w_ctrl, fb_w_linestride, fb_r_sof1, fb_r_sof2, fb_r_size, fb_w_sof1, fb_w_sof2, fb_x_clip, fb_y_clip; - uint32_t fpu_param_cfg; - uint32_t isp_backgnd_t; - uint32_t spg_hblank_int, spg_vblank_int, spg_control, spg_hblank, spg_load, spg_vblank, spg_width; - uint32_t vo_control, vo_startx, vo_starty; - uint32_t text_control; - uint32_t pal_ram_ctrl; - - // TA registers - uint32_t ta_ol_base, ta_ol_limit, ta_isp_base, ta_isp_limit; - uint32_t ta_next_opb, ta_itp_current, ta_alloc_ctrl, ta_next_opb_init; - uint32_t ta_yuv_tex_base, ta_yuv_tex_ctrl, ta_yuv_tex_cnt; - uint32_t ta_yuv_index; - int ta_yuv_u_ptr, ta_yuv_v_ptr; - int ta_yuv_u_size, ta_yuv_v_size; - uint8_t yuv_fifo[384]; - - // Other registers - uint32_t fog_table[0x80]; - uint32_t palette[0x400]; - - // PD DMA registers - uint32_t sb_pdstap, sb_pdstar, sb_pdlen, sb_pddir, sb_pdtsel, sb_pden, sb_pdst, sb_pdapro; - - // Timer callbacks - emu_timer *opaque_irq_timer = nullptr; - emu_timer *opaque_modifier_volume_irq_timer = nullptr; - emu_timer *translucent_irq_timer = nullptr; - emu_timer *translucent_modifier_volume_irq_timer = nullptr; - emu_timer *punch_through_irq_timer = nullptr; - emu_timer *dma_irq_timer = nullptr; - - static uint32_t (*const blend_functions[64])(uint32_t s, uint32_t d); - - static int uv_wrap(float uv, int size); - static int uv_flip(float uv, int size); - static int uv_clamp(float uv, int size); - - static inline uint32_t float_argb_to_packed_argb(float argb[4]); - static inline void packed_argb_to_float_argb(float dst[4], uint32_t in); - - static inline int32_t clamp(int32_t in, int32_t min, int32_t max); - static inline uint32_t bilinear_filter(uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, float u, float v); - static inline uint32_t bla(uint32_t c, uint32_t a); - static inline uint32_t blia(uint32_t c, uint32_t a); - static inline uint32_t blc(uint32_t c1, uint32_t c2); - static inline uint32_t blic(uint32_t c1, uint32_t c2); - static inline uint32_t bls(uint32_t c1, uint32_t c2); - static inline uint32_t bls24(uint32_t c1, uint32_t c2); - - static uint32_t bl00(uint32_t s, uint32_t d); - static uint32_t bl01(uint32_t s, uint32_t d); - static uint32_t bl02(uint32_t s, uint32_t d); - static uint32_t bl03(uint32_t s, uint32_t d); - static uint32_t bl04(uint32_t s, uint32_t d); - static uint32_t bl05(uint32_t s, uint32_t d); - static uint32_t bl06(uint32_t s, uint32_t d); - static uint32_t bl07(uint32_t s, uint32_t d); - static uint32_t bl10(uint32_t s, uint32_t d); - static uint32_t bl11(uint32_t s, uint32_t d); - static uint32_t bl12(uint32_t s, uint32_t d); - static uint32_t bl13(uint32_t s, uint32_t d); - static uint32_t bl14(uint32_t s, uint32_t d); - static uint32_t bl15(uint32_t s, uint32_t d); - static uint32_t bl16(uint32_t s, uint32_t d); - static uint32_t bl17(uint32_t s, uint32_t d); - static uint32_t bl20(uint32_t s, uint32_t d); - static uint32_t bl21(uint32_t s, uint32_t d); - static uint32_t bl22(uint32_t s, uint32_t d); - static uint32_t bl23(uint32_t s, uint32_t d); - static uint32_t bl24(uint32_t s, uint32_t d); - static uint32_t bl25(uint32_t s, uint32_t d); - static uint32_t bl26(uint32_t s, uint32_t d); - static uint32_t bl27(uint32_t s, uint32_t d); - static uint32_t bl30(uint32_t s, uint32_t d); - static uint32_t bl31(uint32_t s, uint32_t d); - static uint32_t bl32(uint32_t s, uint32_t d); - static uint32_t bl33(uint32_t s, uint32_t d); - static uint32_t bl34(uint32_t s, uint32_t d); - static uint32_t bl35(uint32_t s, uint32_t d); - static uint32_t bl36(uint32_t s, uint32_t d); - static uint32_t bl37(uint32_t s, uint32_t d); - static uint32_t bl40(uint32_t s, uint32_t d); - static uint32_t bl41(uint32_t s, uint32_t d); - static uint32_t bl42(uint32_t s, uint32_t d); - static uint32_t bl43(uint32_t s, uint32_t d); - static uint32_t bl44(uint32_t s, uint32_t d); - static uint32_t bl45(uint32_t s, uint32_t d); - static uint32_t bl46(uint32_t s, uint32_t d); - static uint32_t bl47(uint32_t s, uint32_t d); - static uint32_t bl50(uint32_t s, uint32_t d); - static uint32_t bl51(uint32_t s, uint32_t d); - static uint32_t bl52(uint32_t s, uint32_t d); - static uint32_t bl53(uint32_t s, uint32_t d); - static uint32_t bl54(uint32_t s, uint32_t d); - static uint32_t bl55(uint32_t s, uint32_t d); - static uint32_t bl56(uint32_t s, uint32_t d); - static uint32_t bl57(uint32_t s, uint32_t d); - static uint32_t bl60(uint32_t s, uint32_t d); - static uint32_t bl61(uint32_t s, uint32_t d); - static uint32_t bl62(uint32_t s, uint32_t d); - static uint32_t bl63(uint32_t s, uint32_t d); - static uint32_t bl64(uint32_t s, uint32_t d); - static uint32_t bl65(uint32_t s, uint32_t d); - static uint32_t bl66(uint32_t s, uint32_t d); - static uint32_t bl67(uint32_t s, uint32_t d); - static uint32_t bl70(uint32_t s, uint32_t d); - static uint32_t bl71(uint32_t s, uint32_t d); - static uint32_t bl72(uint32_t s, uint32_t d); - static uint32_t bl73(uint32_t s, uint32_t d); - static uint32_t bl74(uint32_t s, uint32_t d); - static uint32_t bl75(uint32_t s, uint32_t d); - static uint32_t bl76(uint32_t s, uint32_t d); - static uint32_t bl77(uint32_t s, uint32_t d); - static inline uint32_t cv_1555(uint16_t c); - static inline uint32_t cv_1555z(uint16_t c); - static inline uint32_t cv_565(uint16_t c); - static inline uint32_t cv_565z(uint16_t c); - static inline uint32_t cv_4444(uint16_t c); - static inline uint32_t cv_4444z(uint16_t c); - static inline uint32_t cv_yuv(uint16_t c1, uint16_t c2, int x); - uint32_t tex_r_yuv_n(texinfo *t, float x, float y); - uint32_t tex_r_yuv_tw(texinfo *t, float x, float y); -// uint32_t tex_r_yuv_vq(texinfo *t, float x, float y); - uint32_t tex_r_1555_n(texinfo *t, float x, float y); - uint32_t tex_r_1555_tw(texinfo *t, float x, float y); - uint32_t tex_r_1555_vq(texinfo *t, float x, float y); - uint32_t tex_r_565_n(texinfo *t, float x, float y); - uint32_t tex_r_565_tw(texinfo *t, float x, float y); - uint32_t tex_r_565_vq(texinfo *t, float x, float y); - uint32_t tex_r_4444_n(texinfo *t, float x, float y); - uint32_t tex_r_4444_tw(texinfo *t, float x, float y); - uint32_t tex_r_4444_vq(texinfo *t, float x, float y); - uint32_t tex_r_p4_1555_tw(texinfo *t, float x, float y); - uint32_t tex_r_p4_1555_vq(texinfo *t, float x, float y); - uint32_t tex_r_p4_565_tw(texinfo *t, float x, float y); - uint32_t tex_r_p4_565_vq(texinfo *t, float x, float y); - uint32_t tex_r_p4_4444_tw(texinfo *t, float x, float y); - uint32_t tex_r_p4_4444_vq(texinfo *t, float x, float y); - uint32_t tex_r_p4_8888_tw(texinfo *t, float x, float y); - uint32_t tex_r_p4_8888_vq(texinfo *t, float x, float y); - uint32_t tex_r_p8_1555_tw(texinfo *t, float x, float y); - uint32_t tex_r_p8_1555_vq(texinfo *t, float x, float y); - uint32_t tex_r_p8_565_tw(texinfo *t, float x, float y); - uint32_t tex_r_p8_565_vq(texinfo *t, float x, float y); - uint32_t tex_r_p8_4444_tw(texinfo *t, float x, float y); - uint32_t tex_r_p8_4444_vq(texinfo *t, float x, float y); - uint32_t tex_r_p8_8888_tw(texinfo *t, float x, float y); - uint32_t tex_r_p8_8888_vq(texinfo *t, float x, float y); - - uint32_t tex_r_default(texinfo *t, float x, float y); - void tex_get_info(texinfo *t); - - template - inline void render_hline(bitmap_rgb32 &bitmap, texinfo *ti, - int y, float xl, float xr, - float ul, float ur, float vl, float vr, - float wl, float wr, - float const bl[4], float const br[4], - float const offl[4], float const offr[4]); - - template - inline void render_span(bitmap_rgb32 &bitmap, texinfo *ti, - float y0, float y1, - float xl, float xr, - float ul, float ur, - float vl, float vr, - float wl, float wr, - float const bl[4], float const br[4], - float const offl[4], float const offr[4], - float dxldy, float dxrdy, - float duldy, float durdy, - float dvldy, float dvrdy, - float dwldy, float dwrdy, - float const dbldy[4], float const dbrdy[4], - float const doldy[4], float const dordy[4]); - - template - inline void render_tri_sorted(bitmap_rgb32 &bitmap, texinfo *ti, - const vert *v0, - const vert *v1, const vert *v2); - - template - void render_tri(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v); - - template - void render_group_to_accumulation_buffer(bitmap_rgb32 &bitmap, const rectangle &cliprect); - - void sort_vertices(const vert *v, int *i0, int *i1, int *i2); - void render_to_accumulation_buffer(bitmap_rgb32 &bitmap, const rectangle &cliprect); - void pvr_accumulationbuffer_to_framebuffer(address_space &space, int x, int y); - void pvr_drawframebuffer(bitmap_rgb32 &bitmap,const rectangle &cliprect); - static uint32_t dilate0(uint32_t value,int bits); - static uint32_t dilate1(uint32_t value,int bits); - void computedilated(); - void pvr_build_parameterconfig(); - void process_ta_fifo(); - void update_screen_format(); - - void fb_convert_0555krgb_to_555rgb(address_space &space, int x, int y); - void fb_convert_0555krgb_to_565rgb(address_space &space, int x, int y); - void fb_convert_0555krgb_to_888rgb24(address_space &space, int x, int y); - void fb_convert_0555krgb_to_888rgb32(address_space &space, int x, int y); - - void fb_convert_0565rgb_to_555rgb(address_space &space, int x, int y); - void fb_convert_0565rgb_to_565rgb(address_space &space, int x, int y); - void fb_convert_0565rgb_to_888rgb24(address_space &space, int x, int y); - void fb_convert_0565rgb_to_888rgb32(address_space &space, int x, int y); - - void fb_convert_1555argb_to_555rgb(address_space &space, int x, int y); - void fb_convert_1555argb_to_565rgb(address_space &space, int x, int y); - void fb_convert_1555argb_to_888rgb24(address_space &space, int x, int y); - void fb_convert_1555argb_to_888rgb32(address_space &space, int x, int y); - - void fb_convert_888rgb_to_555rgb(address_space &space, int x, int y); - void fb_convert_888rgb_to_565rgb(address_space &space, int x, int y); - void fb_convert_888rgb_to_888rgb24(address_space &space, int x, int y); - void fb_convert_888rgb_to_888rgb32(address_space &space, int x, int y); - - void fb_convert_8888argb_to_555rgb(address_space &space, int x, int y); - void fb_convert_8888argb_to_565rgb(address_space &space, int x, int y); - void fb_convert_8888argb_to_888rgb24(address_space &space, int x, int y); - void fb_convert_8888argb_to_888rgb32(address_space &space, int x, int y); - -}; - -DECLARE_DEVICE_TYPE(POWERVR2, powervr2_device) - -#endif // MAME_VIDEO_POWERVR2_H diff --git a/src/mame/shared/segacrp2_device.cpp b/src/mame/shared/segacrp2_device.cpp deleted file mode 100644 index 1a2676bd631..00000000000 --- a/src/mame/shared/segacrp2_device.cpp +++ /dev/null @@ -1,451 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nicola Salmoria, David Haywood -/****************************************************************************** - - Sega encryption emulation by Nicola Salmoria - - - This encryption is an evolution of the one implemented in segacrpt.cpp. - It works on more data and address bits but apart from that it's essentially - the same. - - The encryption affects D0, D2, D4, and D6, and depends on M1, A0, A3, A6, A9, - A12, and A14. - - The encryption consists of a permutation of the four data bits, which can also - be inverted. Therefore there are 4! * 2^4 = 384 different possible encryptions. - - An interesting peculiarity is that four games in the list below use an almost - identical key, just offset by one or more bytes. This leads to believe that - keys were generated using a PRNG like in other Sega encryptions (MC8123 etc.) - and the CPU part# used to skip the first N bytes. - - - List of encrypted games currently known: - - CPU Part # Game Comments - 315-5136 New Lucky 8 Lines (set 7, W-4, encrypted) - 315-5162 4D Warriors & used I'm Sorry for k.p.a. - Rafflesia & - Wonder Boy (set 4) - 315-5176 Wonder Boy (system 2 hardware, set 2) - 315-5177 Astro Flash & - Wonder Boy (set 1) - 315-5178 Wonder Boy (set 2) unencrypted version available - 315-5179 Robo-Wrestle 2001 - 317-5000 Fantasy Zone (Sound CPU) same key as 315-5177 - - The following games seem to use the same algorithm as the above ones, but - using a key which almost doesn't change - - 317-0004 Calorie Kun unencrypted bootleg available - 317-0005 Space Position - 317-0006 Gardia (set 1) - 317-0007 Gardia (set 2) - -******************************************************************************/ - -#include "emu.h" -#include "segacrp2_device.h" - - -static void decode(uint8_t *rom, uint8_t *decrypted, const uint8_t xor_table[128], const int swap_table[128]) -{ - static const uint8_t swaptable[24][4] = { - { 6,4,2,0 }, { 4,6,2,0 }, { 2,4,6,0 }, { 0,4,2,6 }, - { 6,2,4,0 }, { 6,0,2,4 }, { 6,4,0,2 }, { 2,6,4,0 }, - { 4,2,6,0 }, { 4,6,0,2 }, { 6,0,4,2 }, { 0,6,4,2 }, - { 4,0,6,2 }, { 0,4,6,2 }, { 6,2,0,4 }, { 2,6,0,4 }, - { 0,6,2,4 }, { 2,0,6,4 }, { 0,2,6,4 }, { 4,2,0,6 }, - { 2,4,0,6 }, { 4,0,2,6 }, { 2,0,4,6 }, { 0,2,4,6 } }; - - for (int a = 0x0000; a < 0x8000; a++) - { - const uint8_t *tbl; - - const uint8_t src = rom[a]; - - // pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address - const int row = bitswap<6>(a, 14, 12, 9, 6, 3, 0); - - // decode the opcodes - tbl = swaptable[swap_table[2 * row]]; - decrypted[a] = bitswap<8>(src, 7, tbl[0], 5, tbl[1], 3, tbl[2], 1, tbl[3]) ^ xor_table[2 * row]; - - // decode the data - tbl = swaptable[swap_table[2 * row + 1]]; - rom[a] = bitswap<8>(src, 7, tbl[0], 5, tbl[1], 3, tbl[2], 1, tbl[3]) ^ xor_table[2 * row + 1]; - } -} - - -DEFINE_DEVICE_TYPE(NEC_315_5136, nec_315_5136_device, "nec_315_5136", "Nec 315-5136") -DEFINE_DEVICE_TYPE(SEGA_315_5179, sega_315_5179_device, "sega_315_5179", "Sega 315-5179") -DEFINE_DEVICE_TYPE(SEGA_315_5178, sega_315_5178_device, "sega_315_5178", "Sega 315-5178") -DEFINE_DEVICE_TYPE(SEGA_315_5177, sega_315_5177_device, "sega_315_5177", "Sega 315-5177") // also seen as 317-5000 -DEFINE_DEVICE_TYPE(SEGA_315_5176, sega_315_5176_device, "sega_315_5176", "Sega 315-5176") -DEFINE_DEVICE_TYPE(SEGA_315_5162, sega_315_5162_device, "sega_315_5162", "Sega 315-5162") - -DEFINE_DEVICE_TYPE(SEGA_317_0004, sega_317_0004_device, "sega_317_0004", "Sega 317-0004") -DEFINE_DEVICE_TYPE(SEGA_317_0005, sega_317_0005_device, "sega_317_0005", "Sega 317-0005") -DEFINE_DEVICE_TYPE(SEGA_317_0006, sega_317_0006_device, "sega_317_0006", "Sega 317-0006") -DEFINE_DEVICE_TYPE(SEGA_317_0007, sega_317_0007_device, "sega_317_0007", "Sega 317-0007") - - -segacrp2_z80_device::segacrp2_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - z80_device(mconfig, type, tag, owner, clock), - m_decrypted(*this, finder_base::DUMMY_TAG) -{ -} - -void segacrp2_z80_device::device_start() -{ - z80_device::device_start(); - decrypt(); -} - -nec_315_5136_device::nec_315_5136_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, NEC_315_5136, tag, owner, clock) -{ -} - -void nec_315_5136_device::decrypt() -{ - // 315-5136 - static const uint8_t xor_table[128] = { - 0x00,0x40, 0x10,0x50, 0x04,0x44, 0x14,0x54, 0x01,0x41, 0x11,0x51, 0x05,0x45, 0x15,0x55, - 0x00,0x40, 0x10,0x50, 0x04,0x44, 0x14,0x54, 0x01,0x41, 0x11,0x51, 0x05,0x45, 0x15,0x55, - 0x00,0x40, 0x10,0x50, 0x04,0x44, 0x14,0x54, 0x01,0x41, 0x11,0x51, 0x05,0x45, 0x15,0x55, - 0x00,0x40, 0x10,0x50, 0x04,0x44, 0x14,0x54, 0x01,0x41, 0x11,0x51, 0x05,0x45, 0x15,0x55, - - 0x50,0x10, 0x44,0x04, 0x54,0x14, 0x41,0x01, 0x51,0x11, 0x45,0x05, 0x55,0x15, 0x40,0x00, - 0x50,0x10, 0x44,0x04, 0x54,0x14, 0x41,0x01, 0x51,0x11, 0x45,0x05, 0x55,0x15, 0x40,0x00, - 0x50,0x10, 0x44,0x04, 0x54,0x14, 0x41,0x01, 0x51,0x11, 0x45,0x05, 0x55,0x15, 0x40,0x00, - 0x50,0x10, 0x44,0x04, 0x54,0x14, 0x41,0x01, 0x51,0x11, 0x45,0x05, 0x55,0x15, 0x40,0x00 }; - - static const int swap_table[128] = { - 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, - 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, - 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, - 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, - 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, - 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, - 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, - 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02, - 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x03, - 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04 }; - - decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); -} - - -sega_315_5177_device::sega_315_5177_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, SEGA_315_5177, tag, owner, clock) -{ -} - -void sega_315_5177_device::decrypt() -{ - // 315-5177 - static const uint8_t xor_table[128] = { - 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, - 0x05,0x55,0x50,0x14,0x41,0x45,0x00,0x50,0x54,0x11,0x45,0x40, - 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, - 0x05,0x55,0x50,0x14,0x41,0x45,0x00,0x50,0x54,0x11,0x45,0x40, - 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, - 0x05,0x55,0x50,0x14, - - 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, - 0x05,0x55,0x50,0x14,0x41,0x45,0x00,0x50,0x54,0x11,0x45,0x40, - 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, - 0x05,0x55,0x50,0x14,0x41,0x45,0x00,0x50,0x54,0x11,0x45,0x40, - 0x04,0x54,0x51,0x15,0x40,0x44,0x01,0x51,0x55,0x10,0x44,0x41, - 0x05,0x55,0x50,0x14 }; - - static const int swap_table[128] = { - 0,0,0,0, - 1,1,1,1,1, - 2,2,2,2,2, - 3,3,3,3, - 4,4,4,4,4, - 5,5,5,5,5, - 6,6,6,6,6, - 7,7,7,7,7, - 8,8,8,8, - 9,9,9,9,9, - 10,10,10,10,10, - 11,11,11,11,11, - 12,12,12,12,12, - 13,13, - - 8,8,8,8, - 9,9,9,9,9, - 10,10,10,10,10, - 11,11,11,11, - 12,12,12,12,12, - 13,13,13,13,13, - 14,14,14,14,14, - 15,15,15,15,15, - 16,16,16,16, - 17,17,17,17,17, - 18,18,18,18,18, - 19,19,19,19,19, - 20,20,20,20,20, - 21,21 }; - decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); -} - - -sega_315_5176_device::sega_315_5176_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, SEGA_315_5176, tag, owner, clock) -{ -} - -void sega_315_5176_device::decrypt() -{ - static const uint8_t xor_table[128] = { - 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, - 0x41, 0x05, 0x55, 0x10, 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, - 0x45, 0x00, 0x50, 0x14, 0x41, 0x05, 0x55, 0x10, 0x44, 0x01, 0x51, 0x15, - 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, 0x41, 0x05, 0x55, 0x10, - 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, - 0x41, 0x05, 0x55, 0x10, - - 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, - 0x41, 0x05, 0x55, 0x10, 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, - 0x45, 0x00, 0x50, 0x14, 0x41, 0x05, 0x55, 0x10, 0x44, 0x01, 0x51, 0x15, - 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, 0x41, 0x05, 0x55, 0x10, - 0x44, 0x01, 0x51, 0x15, 0x40, 0x04, 0x54, 0x11, 0x45, 0x00, 0x50, 0x14, - 0x41, 0x05, 0x55, 0x10 }; - - static const int swap_table[128] = { - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, - - 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14 }; - - decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); -} - - -sega_315_5162_device::sega_315_5162_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, SEGA_315_5162, tag, owner, clock) -{ -} - -void sega_315_5162_device::decrypt() -{ - // 315-5162 - static const uint8_t xor_table[128] = { - 0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, - 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, - 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, - 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, - 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, - 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, - 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, - 0x00,0x40,0x10,0x50,0x04,0x44,0x14,0x54,0x01,0x41,0x11,0x51,0x05,0x45,0x15,0x55, - 0x00 }; - - static const int swap_table[128] = { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, - 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, - 12 }; - - decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); -} - - - -sega_315_5178_device::sega_315_5178_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, SEGA_315_5178, tag, owner, clock) -{ -} - -void sega_315_5178_device::decrypt() -{ // 315-5178 - static const uint8_t xor_table[128] = { - 0x00,0x55,0x45,0x05,0x11,0x41,0x01,0x14,0x44,0x50,0x10, - 0x00,0x55,0x15,0x05,0x51,0x41,0x01,0x14,0x44,0x04,0x10, - 0x40,0x55,0x15,0x05,0x51,0x11, - 0x01,0x54,0x44,0x04,0x10,0x40,0x00,0x15,0x45,0x51,0x11, - 0x01,0x54,0x14,0x04,0x50,0x40,0x00,0x15,0x45,0x05,0x11, - 0x41,0x54,0x14,0x04,0x50,0x10, - 0x00,0x55,0x45,0x05,0x11,0x41,0x01,0x14, - - 0x00,0x55,0x45,0x05,0x11,0x41,0x01,0x14,0x44,0x50,0x10, - 0x00,0x55,0x15,0x05,0x51,0x41,0x01,0x14,0x44,0x04,0x10, - 0x40,0x55,0x15,0x05,0x51,0x11, - 0x01,0x54,0x44,0x04,0x10,0x40,0x00,0x15,0x45,0x51,0x11, - 0x01,0x54,0x14,0x04,0x50,0x40,0x00,0x15,0x45,0x05,0x11, - 0x41,0x54,0x14,0x04,0x50,0x10, - 0x00,0x55,0x45,0x05,0x11,0x41,0x01,0x14 }; - - static const int swap_table[128] = { - 2, - 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7, - 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, - 5, 7, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, - 4, 6, 0, 2, 4, 6, 0, 2, 4, 6, - 8, - 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, - 6, 0, 2, 4, 6, 0, 2, - - 10, - 11,13,15, 9,11,13,15, 9,11,13,15, - 8,10,12,14, 8,10,12,14, 8,10,12, - 13,15, 9,11,13,15, 9,11,13,15, 9,11, - 12,14, 8,10,12,14, 8,10,12,14, - 16, - 9,11,13,15, 9,11,13,15, 9,11,13, - 14, 8,10,12,14, 8,10 }; - - decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); -} - - -sega_315_5179_device::sega_315_5179_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, SEGA_315_5179, tag, owner, clock) -{ -} - -void sega_315_5179_device::decrypt() -{ // 315-5179 - static const uint8_t xor_table[128] = { - 0x00,0x45,0x41,0x14,0x10,0x55,0x51,0x01,0x04,0x40,0x45,0x11,0x14,0x50, - 0x00,0x05,0x41,0x44,0x10,0x15,0x51,0x54,0x04, - 0x00,0x45,0x41,0x14,0x10,0x55,0x05,0x01,0x44,0x40,0x15,0x11,0x54,0x50, - 0x00,0x05,0x41,0x44,0x10,0x15,0x51,0x01,0x04, - 0x40,0x45,0x11,0x14,0x50,0x55,0x05,0x01,0x44,0x40,0x15,0x11,0x54,0x04, - 0x00,0x45,0x41,0x14,0x50, - 0x00,0x05,0x41,0x44,0x10,0x15,0x51,0x54,0x04, - 0x00,0x45,0x41,0x14,0x50,0x55,0x05,0x01,0x44,0x40,0x15,0x11,0x54,0x50, - 0x00,0x05,0x41,0x44,0x10,0x55,0x51,0x01,0x04, - 0x40,0x45,0x11,0x14,0x50,0x55,0x05,0x01,0x44,0x40,0x15,0x51,0x54,0x04, - 0x00,0x45,0x41,0x14,0x10,0x55,0x51,0x01,0x04, - 0x40,0x45,0x11,0x54,0x50,0x00,0x05,0x41 }; - - static const int swap_table[128] = { - 8, 9,11,13,15, 0, 2, 4, 6, - 8, 9,11,13,15, 1, 2, 4, 6, - 8, 9,11,13,15, 1, 2, 4, 6, - 8, 9,11,13,15, 1, 2, 4, 6, - 8,10,11,13,15, 1, 2, 4, 6, - 8,10,11,13,15, 1, 2, 4, 6, - 8,10,11,13,15, 1, 3, 4, 6, - 8, - 7, 1, 2, 4, 6, 0, 1, 3, 5, - 7, 1, 2, 4, 6, 0, 1, 3, 5, - 7, 1, 2, 4, 6, 0, 2, 3, 5, - 7, 1, 2, 4, 6, 0, 2, 3, 5, - 7, 1, 2, 4, 6, 0, 2, 3, 5, - 7, 1, 3, 4, 6, 0, 2, 3, 5, - 7, 1, 3, 4, 6, 0, 2, 4, 5, - 7 }; - - decode(memregion(tag())->base(), m_decrypted, xor_table, swap_table); -} - - -/****************************************************************************** - - These games (all 317-000x CPUs) use the same algorithm, but the key doesn't - change much - just a shift in the table. - -******************************************************************************/ - -static void sega_decode_317(uint8_t *rom, uint8_t *decrypted, int shift) -{ - static const uint8_t xor_table[128 + 3] = { - 0x04,0x54,0x44,0x14,0x15,0x15,0x51,0x41,0x41,0x14,0x10,0x50,0x15,0x55,0x54,0x05, - 0x04,0x41,0x51,0x01,0x05,0x10,0x55,0x51,0x05,0x05,0x54,0x11,0x45,0x05,0x04,0x14, - 0x10,0x55,0x01,0x41,0x51,0x05,0x55,0x04,0x45,0x41,0x55,0x14,0x45,0x10,0x04,0x45, - 0x55,0x50,0x40,0x00,0x11,0x45,0x15,0x00,0x01,0x00,0x40,0x00,0x01,0x45,0x11,0x00, - 0x45,0x00,0x44,0x54,0x40,0x04,0x05,0x15,0x15,0x10,0x15,0x04,0x01,0x05,0x50,0x11, - 0x00,0x44,0x44,0x04,0x04,0x01,0x50,0x05,0x51,0x00,0x45,0x44,0x50,0x15,0x54,0x40, - 0x41,0x45,0x40,0x10,0x14,0x15,0x40,0x51,0x50,0x50,0x45,0x00,0x10,0x15,0x05,0x51, - 0x50,0x44,0x01,0x15,0x40,0x04,0x01,0x44,0x50,0x44,0x50,0x50,0x50,0x10,0x44,0x04, - 0x40,0x04,0x10 }; - - static const int swap_table[128 + 3] = { - 7, 7,12, 1,18,11, 8,23,21,17, 0,23,22, 0,21,15, - 13,19,21,20,20,12,13,10,20, 0,14,18, 6,18, 3, 5, - 5,20,20,13, 8, 0,20,18, 4,14, 8, 5,17, 6,22,10, - 0,21, 0, 1, 6,11,17, 9,17, 3, 9,21, 0, 4,16, 1, - 13,17,21, 5, 3, 7, 2,16,18,13, 6,19,11,23, 3,20, - 3, 2,18,10,18,23,19,23, 3,15, 0,10, 5,12, 0, 0, - 11,22, 8,14, 8, 6, 1,15, 7,11, 2,17,10,15, 8,21, - 10, 0, 2, 6, 1, 1, 3, 1,12,18,16, 5, 0,15,17,15, - 10,20, 1 }; - - decode(rom, decrypted, xor_table + shift, swap_table + shift); -} - - -sega_317_0004_device::sega_317_0004_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, SEGA_317_0004, tag, owner, clock) -{ -} - -void sega_317_0004_device::decrypt() -{ // 317-0004 - sega_decode_317(memregion(tag())->base(), m_decrypted, 0); -} - - -sega_317_0005_device::sega_317_0005_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, SEGA_317_0005, tag, owner, clock) -{ -} - -void sega_317_0005_device::decrypt() -{ // 317-0005 - sega_decode_317(memregion(tag())->base(), m_decrypted, 1); -} - - -sega_317_0006_device::sega_317_0006_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, SEGA_317_0006, tag, owner, clock) -{ -} - -void sega_317_0006_device::decrypt() -{ // 317-0006 - sega_decode_317(memregion(tag())->base(), m_decrypted, 2); -} - - -sega_317_0007_device::sega_317_0007_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - segacrp2_z80_device(mconfig, SEGA_317_0007, tag, owner, clock) -{ -} - -void sega_317_0007_device::decrypt() -{ // 317-0006 - sega_decode_317(memregion(tag())->base(), m_decrypted, 3); -} diff --git a/src/mame/shared/segacrp2_device.h b/src/mame/shared/segacrp2_device.h deleted file mode 100644 index a64f3fa5fe0..00000000000 --- a/src/mame/shared/segacrp2_device.h +++ /dev/null @@ -1,126 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -#ifndef MAME_MACHINE_SEGACRP2_DEVICE_H -#define MAME_MACHINE_SEGACRP2_DEVICE_H - -#pragma once - - -#include "cpu/z80/z80.h" - -// base class -class segacrp2_z80_device : public z80_device -{ -public: - template void set_decrypted_tag(T &&decrypted_tag) { m_decrypted.set_tag(std::forward(decrypted_tag)); } - -protected: - segacrp2_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void decrypt() = 0; - - required_shared_ptr m_decrypted; -}; - - - -// actual encrypted CPUs -class nec_315_5136_device : public segacrp2_z80_device -{ -public: - nec_315_5136_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5179_device : public segacrp2_z80_device -{ -public: - sega_315_5179_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - -class sega_315_5178_device : public segacrp2_z80_device -{ -public: - sega_315_5178_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5177_device : public segacrp2_z80_device -{ -public: - sega_315_5177_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5176_device : public segacrp2_z80_device -{ -public: - sega_315_5176_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5162_device : public segacrp2_z80_device -{ -public: - sega_315_5162_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_317_0004_device : public segacrp2_z80_device -{ -public: - sega_317_0004_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - -class sega_317_0005_device : public segacrp2_z80_device -{ -public: - sega_317_0005_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - -class sega_317_0006_device : public segacrp2_z80_device -{ -public: - sega_317_0006_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_317_0007_device : public segacrp2_z80_device -{ -public: - sega_317_0007_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - -DECLARE_DEVICE_TYPE(NEC_315_5136, nec_315_5136_device) -DECLARE_DEVICE_TYPE(SEGA_315_5179, sega_315_5179_device) -DECLARE_DEVICE_TYPE(SEGA_315_5178, sega_315_5178_device) -DECLARE_DEVICE_TYPE(SEGA_315_5177, sega_315_5177_device) -DECLARE_DEVICE_TYPE(SEGA_315_5176, sega_315_5176_device) -DECLARE_DEVICE_TYPE(SEGA_315_5162, sega_315_5162_device) - -DECLARE_DEVICE_TYPE(SEGA_317_0004, sega_317_0004_device) -DECLARE_DEVICE_TYPE(SEGA_317_0005, sega_317_0005_device) -DECLARE_DEVICE_TYPE(SEGA_317_0006, sega_317_0006_device) -DECLARE_DEVICE_TYPE(SEGA_317_0007, sega_317_0007_device) - - -#endif // MAME_MACHINE_SEGACRP2_DEVICE_H diff --git a/src/mame/shared/segacrpt_device.cpp b/src/mame/shared/segacrpt_device.cpp deleted file mode 100644 index 2ba57904e60..00000000000 --- a/src/mame/shared/segacrpt_device.cpp +++ /dev/null @@ -1,1055 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nicola Salmoria, David Haywood -/****************************************************************************** - - Sega encryption emulation by Nicola Salmoria - - - Several Sega Z80 games have program ROMs encrypted using a common algorithm - (but with a different key). - The hardware used to implement this encryption is either a custom CPU, or an - epoxy block which probably contains a standard Z80 + PALs. - - The encryption affects D3, D5, and D7, and depends on M1, A0, A4, A8 and A12. - D0, D1, D2, D4 and D6 are always unaffected. - - The encryption consists of a permutation of the three bits, which can also be - inverted. Therefore there are 3! * 2^3 = 48 different possible encryptions. - - For simplicity, the decryption is implemented using conversion tables. - We need 32 of these tables, one for every possible combination of M1, A0, A4, - A8 and A12. However, all the games currently known are full of repetitions - and only use 6 different tables, the only exceptions being Pengo, Yamato and - Spatter which have 7 (but one of them is the identity: { 0x00, 0x08, 0x20, 0x28 } ). - This is most likely a limitation of the hardware. - Some of the early games are even weaker: of the 6 different tables, they use - 3 for opcodes and 3 for data, and always coupled in the same way. - - In all games currently known, only bytes in the memory range 0x0000-0x7fff - (A15 = 0) are encrypted. My guess is that this was done to allow games to - copy code to RAM (in the memory range 0x8000-0xffff) and execute it from - there without the CPU trying to decrypt it and messing everything up. - However Zaxxon has RAM at 0x6000, and the CPU doesn't seem to interfere with - it; but it doesn't execute code from there, so it's possible that the CPU is - encrypting the data while writing it and decrypting it while reading (that - would seem kind of strange though). Video and sprite RAM and memory mapped - ports are all placed above 0x8000. - - Given its strict limitations, this encryption is reasonably easy to break, - and very vulnerable to known plaintext attacks. - - - - Ninja Princess: - - there is a (bootleg?) board which has a standard Z80 + 2 bipolar PROMs - instead of the custom CPU. The encryption table is different from the - original Ninja Princess; it is actually the same as Flicky. - - The first PROM is 32x8 and contains the number (0..5) of the table to - use depending on M1, A0, A4, A8, A12: - - 00: 11 00 33 22 00 44 44 00 11 33 33 22 44 44 44 22 - 10: 11 55 55 33 44 22 55 22 11 33 55 33 44 44 11 22 - - The second PROM is 256x4 and contains the 6 different XOR tables: - - A D B C C B D A - 00: 09 09 0A 0A 0A 0A 09 09 - 08: 0E 08 0B 0D 0D 0B 08 0E - 10: 0A 0C 0A 0C 0C 0A 0C 0A - 18: 0B 0E 0E 0B 0B 0E 0E 0B - 20: 0C 0C 0F 0F 0F 0F 0C 0C - 28: 08 0D 0B 0E 0E 0B 0D 08 - [the remaining bytes are all 0F] - bit 3 is not used. - bits 0-2 is the XOR code inverted (0 = 0xa8, 1 = 0xa0 ... 6 = 0x08 7 = 0x00) - - Here is a diagram showing how it works: - - data to XOR - decode value - A --- - D7 --------------- 0| | - D3 --------------- 1| | - D5 --------------- 2| P |D - A --- D | R |0 ---|>--- D3 - M1 --- 0| P |0 --- 3| O |1 ---|>--- D5 - A0 --- 1| R |1 --- 4| M |2 ---|>--- D7 - A4 --- 2| O |2 --- 5| 2 |3 --- - A8 --- 3| M |3 --- 6| | - A12 --- 4| 1 |4 --- 7| | - --- --- - - - My Hero: - - the bootleg does the decryption using a single 256x4 PROM, mapped in the - obvious way: - - data to XOR - decode value - A --- - D3 --- 0| | - D5 --- 1| |D - D7 --- 2| P |0 --- D3 - A0 --- 3| R |1 --- D5 - A4 --- 4| O |2 --- D7 - A8 --- 5| M |3 --- - A12 --- 6| | - M1 --- 7| | - --- - - - - List of encrypted games currently known: - - CPU Part # Game Comments - 315-5010 Pengo unencrypted version available - 315-5013 Super Zaxxon used Zaxxon for known plaintext attack - 315-5014 Buck Rogers / Zoom 909 unencrypted version available - 315-5015 Super Locomotive - 315-5018 Yamato - ???-???? Top Roller same key as Yamato - 315-5028 Sindbad Mystery - 315-5030 Up'n Down unencrypted version available - ???-???? M120 Razzmatazz same key as Up'n Down - 315-5033 Regulus unencrypted version available - 315-5041 M140 Mister Viking - 315-5048 SWAT used Bull Fight for k.p.a. - 315-5051 Flicky & - Ninja Princess (bootleg) - 315-5061 Future Spy - 315-5064 Water Match used Mister Viking for k.p.a. - 315-5065 Bull Fight - 315-5069 Star Force game by Tehkan; same key as Super Locomotive - ???-???? Spatter same encryption scheme is used by the Falcon 03155096 CPU (Z80) - 315-5084 Jongkyo TABLE INCOMPLETE game by Kiwako; also has a simple bitswap on top - 315-5093 Pitfall II - 315-5098 Ninja Princess unencrypted version available; same key as Up'n Down - 315-5102 Sega Ninja unencrypted version available - 315-5110 I'm Sorry used My Hero for k.p.a. - 315-5114 Champion Pro Wrestling same key as Regulus - 315-5115 TeddyBoy Blues - 315-5128 Pinball Action game by Tehkan; also has a simple bitswap on top - 315-5132 My Hero - 315-5135 Heavy Metal & - Wonder Boy (set 1a & 3; bootlegs?) - - - Some text found in the ROMs: - - Buck Rogers SECULITY BY MASATOSHI,MIZUNAGA - Super Locomotive SEGA FUKUMURA MIZUNAGA - Yamato SECULITY BY M,MIZUNAGA - Regulus SECULITY BY SYUICHI,KATAGI - Up'n Down 19/SEP 1983 MASATOSHI,MIZUNAGA - Mister Viking SECURITY BY S.KATAGI CONTROL CHIP M140 - SWAT SECURITY BY S.KATAGI - Flicky SECURITY BY S.KATAGI - Water Match PROGRAMED BY KAWAHARA&NAKAGAWA - Star Force STAR FORCE TEHKAN. SECURITY BY SEGA ENTERPRISESE - -******************************************************************************/ - -#include "emu.h" -#include "segacrpt_device.h" - - -#if 0 -static void lfkp(int mask) -{ - int A; - uint8_t *RAM = machine.root_device().memregion("maincpu")->base(); - - - for (A = 0x0000;A < 0x8000-14;A++) - { - static const char text[] = "INSERT COIN"; - int i; - - - if ( (RAM[A+0] & mask) == (0x21 & mask) && /* LD HL,$xxxx */ - (RAM[A+3] & mask) == (0x11 & mask) && /* LD DE,$xxxx */ - (RAM[A+6] & mask) == (0x01 & mask)) /* LD BC,$xxxx */ - { - if ( (RAM[A+ 9] & mask) == (0x36 & mask) && /* LD (HL),$xx */ - (RAM[A+11] & mask) == (0xed & mask) && - (RAM[A+12] & mask) == (0xb0 & mask)) /* LDIR */ - logerror("%04x: hl de bc (hl),xx ldir\n",A); - - if ( (RAM[A+ 9] & mask) == (0x77 & mask) && /* LD (HL),A */ - (RAM[A+10] & mask) == (0xed & mask) && - (RAM[A+11] & mask) == (0xb0 & mask)) /* LDIR */ - logerror("%04x: hl de bc (hl),a ldir\n",A); - - if ( (RAM[A+ 9] & mask) == (0xed & mask) && - (RAM[A+10] & mask) == (0xb0 & mask)) /* LDIR */ - logerror("%04x: hl de bc ldir\n",A); - } - - /* the following can also be PUSH IX, PUSH IY - need better checking */ - if ( (RAM[A+0] & mask) == (0xf5 & mask) && /* PUSH AF */ - (RAM[A+1] & mask) == (0xc5 & mask) && /* PUSH BC */ - (RAM[A+2] & mask) == (0xd5 & mask) && /* PUSH DE */ - (RAM[A+3] & mask) == (0xe5 & mask)) /* PUSH HL */ - logerror("%04x: push af bc de hl\n",A); - - if ( (RAM[A+0] & mask) == (0xe1 & mask) && /* POP HL */ - (RAM[A+1] & mask) == (0xd1 & mask) && /* POP DE */ - (RAM[A+2] & mask) == (0xc1 & mask) && /* POP BC */ - (RAM[A+3] & mask) == (0xf1 & mask)) /* POP AF */ - logerror("%04x: pop hl de bc af\n",A); - - for (i = 0;i < strlen(text);i++) - if ((RAM[A+i] & mask) != (text[i] & mask)) break; - if (i == strlen(text)) - logerror("%04x: INSERT COIN\n",A); - } -} - -static void look_for_known_plaintext(void) -{ - lfkp(0x57); -} -#endif - -static void decode(uint8_t *data, uint8_t *opcodes, int size, const uint8_t convtable[32][4], int bank_count, int bank_size) -{ - for (int A = 0x0000;A < size + bank_count*bank_size;A++) - { - int xorval = 0; - - uint8_t src = data[A]; - int adr; - if(A < size || !bank_count) - adr = A; - else - adr = size + ((A - size) % bank_size); - - /* pick the translation table from bits 0, 4, 8 and 12 of the address */ - int row = (adr & 1) + (((adr >> 4) & 1) << 1) + (((adr >> 8) & 1) << 2) + (((adr >> 12) & 1) << 3); - - /* pick the offset in the table from bits 3 and 5 of the source data */ - int col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1); - /* the bottom half of the translation table is the mirror image of the top */ - if (src & 0x80) - { - col = 3 - col; - xorval = 0xa8; - } - - /* decode the opcodes */ - opcodes[A] = (src & ~0xa8) | (convtable[2*row][col] ^ xorval); - - /* decode the data */ - data[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xorval); - - if (convtable[2*row][col] == 0xff) /* table incomplete! (for development) */ - opcodes[A] = 0xee; - if (convtable[2*row+1][col] == 0xff) /* table incomplete! (for development) */ - data[A] = 0xee; - } -} - - - - -DEFINE_DEVICE_TYPE(SEGA_315_5132, sega_315_5132_device, "sega_315_5132", "Sega 315-5132") -DEFINE_DEVICE_TYPE(SEGA_315_5155, sega_315_5155_device, "sega_315_5155", "Sega 315-5155") -DEFINE_DEVICE_TYPE(SEGA_315_5110, sega_315_5110_device, "sega_315_5110", "Sega 315-5110") -DEFINE_DEVICE_TYPE(SEGA_315_5135, sega_315_5135_device, "sega_315_5135", "Sega 315-5135") -DEFINE_DEVICE_TYPE(SEGA_315_5051, sega_315_5051_device, "sega_315_5051", "Sega 315-5051") -DEFINE_DEVICE_TYPE(SEGA_315_5098, sega_315_5098_device, "sega_315_5098", "Sega 315-5098") // also 315-5030 ? -DEFINE_DEVICE_TYPE(SEGA_315_5102, sega_315_5102_device, "sega_315_5102", "Sega 315-5102") -DEFINE_DEVICE_TYPE(SEGA_315_5065, sega_315_5065_device, "sega_315_5065", "Sega 315-5065") -DEFINE_DEVICE_TYPE(SEGA_315_5064, sega_315_5064_device, "sega_315_5064", "Sega 315-5064") -DEFINE_DEVICE_TYPE(SEGA_315_5033, sega_315_5033_device, "sega_315_5033", "Sega 315-5033") -DEFINE_DEVICE_TYPE(SEGA_315_5041, sega_315_5041_device, "sega_315_5041", "Sega 315-5041") -DEFINE_DEVICE_TYPE(SEGA_315_5048, sega_315_5048_device, "sega_315_5048", "Sega 315-5048") -DEFINE_DEVICE_TYPE(SEGA_315_5093, sega_315_5093_device, "sega_315_5093", "Sega 315-5093") -DEFINE_DEVICE_TYPE(SEGA_315_5099, sega_315_5099_device, "sega_315_5099", "Sega 315-5099") -DEFINE_DEVICE_TYPE(SEGA_315_5015, sega_315_5015_device, "sega_315_5015", "Sega 315-5015") -DEFINE_DEVICE_TYPE(SEGA_315_5133, sega_315_5133_device, "sega_315_5133", "Sega 315-5133") // exactly the same as Sega 315-5048? -DEFINE_DEVICE_TYPE(SEGA_315_5061, sega_315_5061_device, "sega_315_5061", "Sega 315-5061") -DEFINE_DEVICE_TYPE(SEGA_315_5028, sega_315_5028_device, "sega_315_5028", "Sega 315-5028") -DEFINE_DEVICE_TYPE(SEGA_315_5084, sega_315_5084_device, "sega_315_5084", "Sega 315-5084") -DEFINE_DEVICE_TYPE(SEGA_315_5013, sega_315_5013_device, "sega_315_5013", "Sega 315-5013") -DEFINE_DEVICE_TYPE(SEGA_315_5014, sega_315_5014_device, "sega_315_5014", "Sega 315-5014") -DEFINE_DEVICE_TYPE(SEGA_315_5018, sega_315_5018_device, "sega_315_5018", "Sega 315-5018") -DEFINE_DEVICE_TYPE(SEGA_315_5010, sega_315_5010_device, "sega_315_5010", "Sega 315-5010") -DEFINE_DEVICE_TYPE(SEGA_315_SPAT, sega_315_spat_device, "sega_315_spat", "Sega 315-5xxx (Spatter)") // unknown part number -DEFINE_DEVICE_TYPE(SEGA_315_5128, sega_315_5128_device, "sega_315_5128", "Sega 315-5128") - - - - -segacrpt_z80_device::segacrpt_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - z80_device(mconfig, type, tag, owner, clock), - m_decrypted_ptr(nullptr), - m_region_ptr(nullptr), - m_decode_size(0x8000), - m_numbanks(0), - m_banksize(0), - m_decryption_done(false) -{ -} - -void segacrpt_z80_device::device_start() -{ - z80_device::device_start(); -} - -void segacrpt_z80_device::device_reset() -{ - // decrypt on reset, makes sure DRIVER_INIT stuff happens first (for myherok) - // actual CPU would be decrypting in realtime anyway - if (m_decrypted_ptr == nullptr) - { - m_decrypted_ptr = (uint8_t*)memshare(m_decrypted_tag)->ptr(); - } - - if (m_region_ptr == nullptr) - { - m_region_ptr = (uint8_t*)memregion(tag())->base(); - } - - if (m_decryption_done == false) - { - decrypt(); - m_decryption_done = true; - } - z80_device::device_reset(); -} - -void segacrpt_z80_device::set_region_p(uint8_t* ptr) -{ - m_region_ptr = ptr; -} - -void segacrpt_z80_device::set_decrypted_p(uint8_t* ptr) -{ - m_decrypted_ptr = ptr; -} - - - - -sega_315_5132_device::sega_315_5132_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5132, tag, owner, clock) {} -void sega_315_5132_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...0 */ - { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...1 */ - { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ - { 0x08,0x88,0x00,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...1...1 */ - { 0x20,0x00,0xa0,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */ - { 0x20,0x00,0xa0,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */ - { 0x08,0x88,0x00,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...0 */ - { 0x80,0xa0,0x88,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...1 */ - { 0x80,0xa0,0x88,0xa8 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...0 */ - { 0xa8,0xa0,0x88,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */ - { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ - { 0x88,0x80,0x08,0x00 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */ - { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ - { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - - -sega_315_5155_device::sega_315_5155_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5155, tag, owner, clock) {} -void sega_315_5155_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x20,0x28,0x00,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...0...0...0 */ - { 0x20,0x28,0x00,0x08 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...1 */ - { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */ - { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ - { 0x20,0x28,0x00,0x08 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */ - { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...0...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */ - { 0x80,0x00,0xa0,0x20 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...0 */ - { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...1 */ - { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ - { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...1 */ - { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ - { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...1 */ - { 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */ - { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - - -sega_315_5110_device::sega_315_5110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5110, tag, owner, clock) {} -void sega_315_5110_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x88,0x08,0x80,0x00 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...0...0 */ - { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...1 */ - { 0x88,0x08,0xa8,0x28 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...1...0 */ - { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ - { 0x00,0x20,0x80,0xa0 }, { 0x08,0x00,0x88,0x80 }, /* ...0...1...0...0 */ - { 0x00,0x20,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...0...1 */ - { 0x20,0x28,0xa0,0xa8 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...0 */ - { 0x20,0x28,0xa0,0xa8 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ - { 0x88,0x08,0x80,0x00 }, { 0x08,0x00,0x88,0x80 }, /* ...1...0...0...0 */ - { 0x08,0x00,0x88,0x80 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...0...1 */ - { 0x08,0x28,0x00,0x20 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ - { 0x88,0x08,0x80,0x00 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...1 */ - { 0x08,0x28,0x00,0x20 }, { 0x08,0x00,0x88,0x80 }, /* ...1...1...0...0 */ - { 0x08,0x28,0x00,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...1 */ - { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 }, /* ...1...1...1...0 */ - { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - -sega_315_5135_device::sega_315_5135_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5135, tag, owner, clock) {} -void sega_315_5135_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...1...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ - { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...0 */ - { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */ - { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ - { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */ - { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...0 */ - { 0xa0,0x20,0xa8,0x28 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...1...0...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...1...0 */ - { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - - -sega_315_5051_device::sega_315_5051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5051, tag, owner, clock) {} -void sega_315_5051_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x08,0x88,0x00,0x80 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ - { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0x20,0x00 }, /* ...0...0...1...0 */ - { 0x28,0x08,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ - { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...1...0...0 */ - { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ - { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...0...1...1...0 */ - { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ - { 0x08,0x88,0x00,0x80 }, { 0xa8,0x88,0x28,0x08 }, /* ...1...0...0...0 */ - { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...1 */ - { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */ - { 0xa8,0x88,0x28,0x08 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...1 */ - { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...0 */ - { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...1 */ - { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...1...1...1...0 */ - { 0x08,0x88,0x00,0x80 }, { 0x88,0x80,0x08,0x00 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - -sega_315_5098_device::sega_315_5098_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5098, tag, owner, clock) {} -void sega_315_5098_device::decrypt() -{ - // also 315-5030 ? - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x08,0x88,0x00,0x80 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...0...0...0 */ - { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ - { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...1 */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...1...0...0 */ - { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...0...1 */ - { 0x88,0x80,0x08,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */ - { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...0...0 */ - { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...1 */ - { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ - { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - - -sega_315_5102_device::sega_315_5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5102, tag, owner, clock) {} -void sega_315_5102_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...1 */ - { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...0...1...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...1...1 */ - { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...1 */ - { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...1...1 */ - { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ - { 0xa0,0xa8,0x80,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...0...1 */ - { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */ - { 0xa8,0xa0,0x28,0x20 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...1 */ - { 0x28,0x08,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */ - { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...1 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...1...0 */ - { 0xa8,0xa0,0x28,0x20 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - -sega_315_5065_device::sega_315_5065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5065, tag, owner, clock) {} -void sega_315_5065_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0xa0,0xa8,0x20,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...0...0...0...0 */ - { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...0...0...0...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...0...1...0 */ - { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...0 */ - { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...1...1...0 */ - { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ - { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */ - { 0x88,0x08,0xa8,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...0...1 */ - { 0x28,0xa8,0x20,0xa0 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ - { 0x28,0xa8,0x20,0xa0 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ - { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ - { 0x88,0x08,0xa8,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...1 */ - { 0x08,0x28,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ - { 0x08,0x28,0x00,0x20 }, { 0x88,0x08,0xa8,0x28 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - -sega_315_5064_device::sega_315_5064_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5064, tag, owner, clock) {} -void sega_315_5064_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...0...0 */ - { 0x08,0x88,0x00,0x80 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ - { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...0...1...0 */ - { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...1 */ - { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...0 */ - { 0x08,0x88,0x00,0x80 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...1 */ - { 0xa8,0x28,0x88,0x08 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...1...0 */ - { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...1...1 */ - { 0x20,0x28,0xa0,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...0...1 */ - { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...0 */ - { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...1...1 */ - { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...0 */ - { 0xa8,0x28,0x88,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ - { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...1...0 */ - { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - -sega_315_5033_device::sega_315_5033_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5033, tag, owner, clock) {} -void sega_315_5033_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ - { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */ - { 0x88,0x80,0x08,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */ - { 0x88,0x08,0x80,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...1 */ - { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ - { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ - { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...1...0 */ - { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */ - { 0x80,0xa0,0x00,0x20 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */ - { 0x80,0xa0,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...0 */ - { 0x80,0xa0,0x00,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...0...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ - { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - -sega_315_5041_device::sega_315_5041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5041, tag, owner, clock) {} -void sega_315_5041_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ - { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ - { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...0 */ - { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ - { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ - { 0x88,0x80,0x08,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ - { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */ - { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ - { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */ - { 0xa0,0x80,0x20,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...0 */ - { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...1...1 */ - { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ - { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...1...0 */ - { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - -sega_315_5048_device::sega_315_5048_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5048, tag, owner, clock) {} -sega_315_5048_device::sega_315_5048_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, type, tag, owner, clock) {} -void sega_315_5048_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x88,0x08,0x80,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...0 */ - { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ - { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */ - { 0xa0,0xa8,0x80,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ - { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ - { 0xa0,0x80,0x20,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...0 */ - { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...1 */ - { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...0 */ - { 0xa0,0x20,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */ - { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...0 */ - { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...1 */ - { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...1...0...1 */ - { 0xa0,0xa8,0x80,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...1...0 */ - { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - -sega_315_5093_device::sega_315_5093_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5093, tag, owner, clock) {} -void sega_315_5093_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ - { 0x08,0x88,0x28,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...0...0...0...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */ - { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...1...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...0 */ - { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...0 */ - { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...1 */ - { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...0 */ - { 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ - { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...1...0...1...1 */ - { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...1...0...0 */ - { 0x80,0x88,0xa0,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...1...0...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */ - { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - -sega_315_5099_device::sega_315_5099_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5099, tag, owner, clock) {} -void sega_315_5099_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0xa0,0xa8,0x20,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...0...0...0...0 */ - { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...0...0...0...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...0...1...0 */ - { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...0 */ - { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...1...1...0 */ - { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ - { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */ - { 0x88,0x08,0xa8,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...0...1 */ - { 0x28,0xa8,0x20,0xa0 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ - { 0x28,0xa8,0x20,0xa0 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ - { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ - { 0x88,0x08,0xa8,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...1 */ - { 0x08,0x28,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ - { 0x08,0x28,0x00,0x20 }, { 0x88,0x08,0xa8,0x28 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - - -sega_315_spat_device::sega_315_spat_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_SPAT, tag, owner, clock) {} -void sega_315_spat_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x88,0x08,0x80,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...0...0...0...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */ - { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...0 */ - { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ - { 0x00,0x08,0x20,0x28 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...0 */ - { 0xa0,0x80,0x20,0x00 }, { 0x80,0x88,0x00,0x08 }, /* ...0...1...0...1 */ - { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */ - { 0x88,0x08,0x80,0x00 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0x80,0x88,0x00,0x08 }, /* ...1...0...0...0 */ - { 0x80,0x88,0x00,0x08 }, { 0x00,0x08,0x20,0x28 }, /* ...1...0...0...1 */ - { 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...0 */ - { 0x00,0x08,0x20,0x28 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */ - { 0x80,0x88,0x00,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ - { 0x80,0xa0,0x88,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ - { 0xa0,0x80,0x20,0x00 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...1...1...0 */ - { 0x28,0x20,0xa8,0xa0 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - -sega_315_5015_device::sega_315_5015_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5015, tag, owner, clock) {} -void sega_315_5015_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...0 */ - { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...1 */ - { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ - { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ - { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...0...0 */ - { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...0...1 */ - { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ - { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...0 */ - { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...0...1 */ - { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ - { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...1...1 */ - { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...0...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */ - { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ - { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ - }; - - /* decrypt program ROMs */ - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - -sega_315_5133_device::sega_315_5133_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : sega_315_5048_device(mconfig, SEGA_315_5133, tag, owner, clock) {} -// == sega_315_5048_device - - -sega_315_5014_device::sega_315_5014_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5014, tag, owner, clock) {} -void sega_315_5014_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...0...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ - { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...0...0 */ - { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...0 */ - { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ - { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...1 */ - { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...1...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...1...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */ - }; - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - -sega_315_5013_device::sega_315_5013_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5013, tag, owner, clock) {} -void sega_315_5013_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...0...0 */ - { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ - { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...0...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */ - { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ - { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...1...1...0 */ - { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ - { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...1...0 */ - { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...0...1...1 */ - { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...0...0 */ - { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...0...1 */ - { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - -sega_315_5061_device::sega_315_5061_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5061, tag, owner, clock) {} -void sega_315_5061_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...0...0...0...0 */ - { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...0...0...1 */ - { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...0...1...0 */ - { 0xa0,0x80,0x20,0x00 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...0...1...1 */ - { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0xa8,0xa0 }, /* ...0...1...0...0 */ - { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ - { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...1...0 */ - { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...1...1 */ - { 0x88,0x80,0xa8,0xa0 }, { 0x28,0x08,0x20,0x00 }, /* ...1...0...0...0 */ - { 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...1 */ - { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 }, /* ...1...0...1...0 */ - { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...1...1 */ - { 0x88,0x80,0xa8,0xa0 }, { 0x88,0x80,0xa8,0xa0 }, /* ...1...1...0...0 */ - { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */ - { 0x80,0x00,0xa0,0x20 }, { 0x28,0x08,0x20,0x00 }, /* ...1...1...1...0 */ - { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - -sega_315_5018_device::sega_315_5018_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5018, tag, owner, clock) {} -void sega_315_5018_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...0 */ - { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...0...1...1 */ - { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...0...1...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...0...1 */ - { 0x20,0xa0,0x28,0xa8 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...1...1...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */ - { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...0...0...0 */ - { 0x20,0xa0,0x28,0xa8 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ - { 0xa0,0x20,0x80,0x00 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...0 */ - { 0x28,0x20,0xa8,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...1 */ - { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...0 */ - { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...1 */ - { 0xa0,0x20,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...1...1...0 */ - { 0x20,0xa0,0x28,0xa8 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); - -} - - -sega_315_5010_device::sega_315_5010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5010, tag, owner, clock) {} -void sega_315_5010_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0xa0,0x80,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...1 */ - { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...0 */ - { 0x08,0x28,0x88,0xa8 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ - { 0x08,0x00,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */ - { 0xa0,0x80,0x20,0x00 }, { 0x08,0x00,0x88,0x80 }, /* ...0...1...0...1 */ - { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */ - { 0xa0,0x80,0x20,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...0...1...1...1 */ - { 0x88,0x80,0x08,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...0 */ - { 0x88,0x80,0x08,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...1...0...0...1 */ - { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, /* ...1...0...1...0 */ - { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...1 */ - { 0x08,0x00,0x88,0x80 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ - { 0x00,0x08,0x20,0x28 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */ - { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, /* ...1...1...1...0 */ - { 0x08,0x00,0x88,0x80 }, { 0xa0,0x80,0x20,0x00 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - - - -sega_315_5128_device::sega_315_5128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5128, tag, owner, clock) {} -void sega_315_5128_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0xa8,0xa0,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...0 */ - { 0x28,0x08,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...1 */ - { 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...0 */ - { 0x28,0x08,0xa8,0x88 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */ - { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...0...0 */ - { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ - { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...0 */ - { 0xa8,0xa0,0x88,0x80 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...1 */ - { 0xa8,0xa0,0x88,0x80 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...0 */ - { 0x28,0x20,0xa8,0xa0 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...1 */ - { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ - { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...0...0 */ - { 0x28,0x20,0xa8,0xa0 }, { 0xa8,0x28,0xa0,0x20 }, /* ...1...1...0...1 */ - { 0xa0,0x80,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ - { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0x28,0xa0,0x20 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - -sega_315_5028_device::sega_315_5028_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5028, tag, owner, clock) {} -void sega_315_5028_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ - { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...0...1 */ - { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...1...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...1...1 */ - { 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 }, /* ...0...1...0...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ - { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...0 */ - { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */ - { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...1...0...1...0 */ - { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...1...0...1...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ - { 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...1 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ - { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 } /* ...1...1...1...1 */ - }; - - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} - - -sega_315_5084_device::sega_315_5084_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5084, tag, owner, clock) {} -void sega_315_5084_device::decrypt() -{ - static const uint8_t convtable[32][4] = - { - /* opcode data address */ - /* A B C D A B C D */ - { 0x28,0x08,0xa8,0x88 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...0 */ - { 0x80,0x88,0xa0,0xa8 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...0...1...0 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x80,0x88,0xa0,0xa8 }, /* ...0...0...1...1 */ - { 0x08,0x88,0x00,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...0 */ - { 0x88,0xa8,0x80,0xa0 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ - { 0x20,0xa0,0x00,0x80 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...1...1...0 */ - { 0x08,0x88,0x00,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...1...1 */ - { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */ - { 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...1 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...0...1...0 */ - { 0xa0,0xa8,0x20,0x28 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...1...1 */ - { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...0 */ - { 0x08,0x88,0x00,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...1...0...1 */ - { 0x28,0x08,0xa8,0x88 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...1...0 */ - { 0x80,0x88,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 } /* ...1...1...1...1 */ - }; - decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize); -} diff --git a/src/mame/shared/segacrpt_device.h b/src/mame/shared/segacrpt_device.h deleted file mode 100644 index 63b50bde2d0..00000000000 --- a/src/mame/shared/segacrpt_device.h +++ /dev/null @@ -1,279 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood - -#ifndef MAME_MACHINE_SEGACRYPT_DEVICE_H -#define MAME_MACHINE_SEGACRYPT_DEVICE_H - -#pragma once - -#include "cpu/z80/z80.h" - - -// base class -class segacrpt_z80_device : public z80_device -{ -public: - void set_decrypted_tag(const char* decrypted_tag) { m_decrypted_tag = decrypted_tag; } - void set_size(int size) { m_decode_size = size; } - void set_numbanks(int numbanks) { m_numbanks = numbanks; } - void set_banksize(int banksize) { m_banksize = banksize; } - - void set_decrypted_p(uint8_t* ptr); - void set_region_p(uint8_t* ptr); - -protected: - segacrpt_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_reset() override; - virtual void decrypt() = 0; - - const char* m_decrypted_tag = nullptr; - uint8_t* m_decrypted_ptr; - uint8_t* m_region_ptr; - int m_decode_size; - int m_numbanks; - int m_banksize; - -private: - bool m_decryption_done; -}; - - -// actual encrypted CPUs -class sega_315_5132_device : public segacrpt_z80_device -{ -public: - sega_315_5132_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5155_device : public segacrpt_z80_device -{ -public: - sega_315_5155_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5110_device : public segacrpt_z80_device -{ -public: - sega_315_5110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5135_device : public segacrpt_z80_device -{ -public: - sega_315_5135_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5051_device : public segacrpt_z80_device -{ -public: - sega_315_5051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5098_device : public segacrpt_z80_device -{ -public: - sega_315_5098_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5102_device : public segacrpt_z80_device -{ -public: - sega_315_5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5065_device : public segacrpt_z80_device -{ -public: - sega_315_5065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - -class sega_315_5064_device : public segacrpt_z80_device -{ -public: - sega_315_5064_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - -class sega_315_5033_device : public segacrpt_z80_device -{ -public: - sega_315_5033_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5041_device : public segacrpt_z80_device -{ -public: - sega_315_5041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5048_device : public segacrpt_z80_device -{ -public: - sega_315_5048_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); - sega_315_5048_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - -protected: - virtual void decrypt() override; -}; - -class sega_315_5093_device : public segacrpt_z80_device -{ -public: - sega_315_5093_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5099_device : public segacrpt_z80_device -{ -public: - sega_315_5099_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_spat_device : public segacrpt_z80_device -{ -public: - sega_315_spat_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5015_device : public segacrpt_z80_device -{ -public: - sega_315_5015_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - -class sega_315_5133_device : public sega_315_5048_device -{ -public: - sega_315_5133_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -}; - -class sega_315_5014_device : public segacrpt_z80_device -{ -public: - sega_315_5014_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5013_device : public segacrpt_z80_device -{ -public: - sega_315_5013_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5061_device : public segacrpt_z80_device -{ -public: - sega_315_5061_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - - -class sega_315_5018_device : public segacrpt_z80_device -{ -public: - sega_315_5018_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5010_device : public segacrpt_z80_device -{ -public: - sega_315_5010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - - -class sega_315_5128_device : public segacrpt_z80_device -{ -public: - sega_315_5128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5028_device : public segacrpt_z80_device -{ -public: - sega_315_5028_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - -class sega_315_5084_device : public segacrpt_z80_device -{ -public: - sega_315_5084_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t); -protected: - virtual void decrypt() override; -}; - - -DECLARE_DEVICE_TYPE(SEGA_315_5132, sega_315_5132_device) -DECLARE_DEVICE_TYPE(SEGA_315_5155, sega_315_5155_device) -DECLARE_DEVICE_TYPE(SEGA_315_5110, sega_315_5110_device) -DECLARE_DEVICE_TYPE(SEGA_315_5135, sega_315_5135_device) -DECLARE_DEVICE_TYPE(SEGA_315_5051, sega_315_5051_device) -DECLARE_DEVICE_TYPE(SEGA_315_5098, sega_315_5098_device) -DECLARE_DEVICE_TYPE(SEGA_315_5102, sega_315_5102_device) -DECLARE_DEVICE_TYPE(SEGA_315_5065, sega_315_5065_device) -DECLARE_DEVICE_TYPE(SEGA_315_5064, sega_315_5064_device) -DECLARE_DEVICE_TYPE(SEGA_315_5033, sega_315_5033_device) -DECLARE_DEVICE_TYPE(SEGA_315_5041, sega_315_5041_device) -DECLARE_DEVICE_TYPE(SEGA_315_5048, sega_315_5048_device) -DECLARE_DEVICE_TYPE(SEGA_315_5093, sega_315_5093_device) -DECLARE_DEVICE_TYPE(SEGA_315_5099, sega_315_5099_device) -DECLARE_DEVICE_TYPE(SEGA_315_SPAT, sega_315_spat_device) -DECLARE_DEVICE_TYPE(SEGA_315_5015, sega_315_5015_device) -DECLARE_DEVICE_TYPE(SEGA_315_5133, sega_315_5133_device) -DECLARE_DEVICE_TYPE(SEGA_315_5014, sega_315_5014_device) -DECLARE_DEVICE_TYPE(SEGA_315_5013, sega_315_5013_device) -DECLARE_DEVICE_TYPE(SEGA_315_5061, sega_315_5061_device) -DECLARE_DEVICE_TYPE(SEGA_315_5018, sega_315_5018_device) -DECLARE_DEVICE_TYPE(SEGA_315_5010, sega_315_5010_device) -DECLARE_DEVICE_TYPE(SEGA_315_5128, sega_315_5128_device) -DECLARE_DEVICE_TYPE(SEGA_315_5028, sega_315_5028_device) -DECLARE_DEVICE_TYPE(SEGA_315_5084, sega_315_5084_device) - - -#endif // MAME_MACHINE_SEGACRYPT_DEVICE_H diff --git a/src/mame/tehkan/pbaction.cpp b/src/mame/tehkan/pbaction.cpp index 5484fa963ab..1039c46369a 100644 --- a/src/mame/tehkan/pbaction.cpp +++ b/src/mame/tehkan/pbaction.cpp @@ -97,8 +97,7 @@ Stephh's notes (based on the game Z80 code and some tests) : #include "emu.h" #include "pbaction.h" -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "machine/74259.h" #include "sound/ay8910.h" #include "screen.h" diff --git a/src/mame/tehkan/senjyo.cpp b/src/mame/tehkan/senjyo.cpp index c8854f5742a..784929b32b9 100644 --- a/src/mame/tehkan/senjyo.cpp +++ b/src/mame/tehkan/senjyo.cpp @@ -80,8 +80,7 @@ I/O read/write #include "emu.h" #include "senjyo.h" -#include "segacrpt_device.h" - +#include "machine/segacrpt_device.h" #include "cpu/z80/z80.h" #include "sound/sn76496.h" -- cgit v1.2.3