diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 43e84df01d0..7b7203800a6 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -3250,6 +3250,7 @@ files { MAME_DIR .. "src/mame/machine/pacplus.cpp", MAME_DIR .. "src/mame/machine/pacplus.h", MAME_DIR .. "src/mame/drivers/pengo.cpp", + MAME_DIR .. "src/mame/drivers/schick.cpp", } createMAMEProjects(_target, _subtarget, "pce") diff --git a/src/devices/machine/spg_renderer.cpp b/src/devices/machine/spg_renderer.cpp index fb728396de4..7e9b9e6380e 100644 --- a/src/devices/machine/spg_renderer.cpp +++ b/src/devices/machine/spg_renderer.cpp @@ -415,8 +415,9 @@ void spg_renderer_device::draw_page(bool read_from_csspace, bool has_extended_ti if (ctrl & 0x0040) // 'vertical compression feature' (later models only?) { - if (m_video_regs_1e != 0x0000) - popmessage("vertical compression mode with non-0 step amount %04x offset %04x step %04x\n", m_video_regs_1c, m_video_regs_1d, m_video_regs_1e); + // used by senspeed + //if (m_video_regs_1e != 0x0000) + // popmessage("vertical compression mode with non-0 step amount %04x offset %04x step %04x\n", m_video_regs_1c, m_video_regs_1d, m_video_regs_1e); logical_scanline = m_ycmp_table[scanline]; if (logical_scanline == 0xffffffff) diff --git a/src/mame/drivers/pengo.cpp b/src/mame/drivers/pengo.cpp index 618dd084a50..d5c2975a8c0 100644 --- a/src/mame/drivers/pengo.cpp +++ b/src/mame/drivers/pengo.cpp @@ -88,10 +88,8 @@ public: void pengoe(machine_config &config); void pengou(machine_config &config); void pengo(machine_config &config); - void schick(machine_config &config); void init_penta(); - void init_schick(); private: DECLARE_WRITE_LINE_MEMBER(coin_counter_1_w); @@ -100,17 +98,12 @@ private: DECLARE_WRITE_LINE_MEMBER(vblank_irq); void decode_penta(int end, int nodecend); - void decode_schick_extra(int size, uint8_t* rom); optional_shared_ptr m_decrypted_opcodes; optional_device m_latch; void decrypted_opcodes_map(address_map &map); - void schick_decrypted_opcodes_map(address_map &map); void jrpacmbl_map(address_map &map); void pengo_map(address_map &map); - void schick_map(address_map &map); - void schick_audio_map(address_map &map); - void schick_audio_io_map(address_map &map); }; @@ -200,45 +193,6 @@ void pengo_state::jrpacmbl_map(address_map &map) map(0x90c0, 0x90ff).portr("P1"); } -void pengo_state::schick_map(address_map &map) // everything needs to be verified, where's the sound latch? -{ - map(0x0000, 0x7fff).rom(); - map(0x8000, 0x83ff).ram().w(FUNC(pengo_state::pacman_videoram_w)).share("videoram"); - map(0x8400, 0x87ff).ram().w(FUNC(pengo_state::pacman_colorram_w)).share("colorram"); - map(0x8800, 0x8fef).ram().share("mainram"); - map(0x8ff0, 0x8fff).ram().share("spriteram"); - map(0x9000, 0x901f).nopw(); // leftover from pengo? - map(0x9020, 0x902f).writeonly().share("spriteram2"); - map(0x9000, 0x903f).portr("SW2"); - map(0x9040, 0x907f).portr("SW1"); - map(0x9040, 0x9047).w(m_latch, FUNC(ls259_device::write_d0)); - map(0x9070, 0x9070).w(m_watchdog, FUNC(watchdog_timer_device::reset_w)); - map(0x9080, 0x90bf).portr("IN1"); - map(0x90c0, 0x90ff).portr("IN0"); - map(0xe000, 0xffff).rom(); -} - -void pengo_state::schick_decrypted_opcodes_map(address_map &map) -{ - map(0x0000, 0xffff).rom().share("decrypted_opcodes"); - map(0x8800, 0x8fef).ram().share("mainram"); - map(0x8ff0, 0x8fff).ram().share("spriteram"); -} - -void pengo_state::schick_audio_map(address_map &map) -{ - map(0x0000, 0x1fff).rom(); - map(0x4000, 0x43ff).ram(); - map(0x6000, 0x6000).r("soundlatch", FUNC(generic_latch_8_device::read)); -} - -void pengo_state::schick_audio_io_map(address_map &map) -{ - map.global_mask(0xff); - map(0x00, 0x01).w("ay1", FUNC(ay8910_device::address_data_w)); - map(0x10, 0x11).w("ay2", FUNC(ay8910_device::address_data_w)); - map(0x80, 0x81).w("ay3", FUNC(ay8910_device::address_data_w)); -} /************************************* * @@ -335,48 +289,6 @@ static INPUT_PORTS_START( pengo ) INPUT_PORTS_END -static INPUT_PORTS_START( schick ) // TODO: check everything - PORT_START("IN0") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN2 ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN3 ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) - - PORT_START("IN1") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY PORT_COCKTAIL - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_COCKTAIL - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY PORT_COCKTAIL - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY PORT_COCKTAIL - PORT_SERVICE_NO_TOGGLE(0x10, IP_ACTIVE_LOW) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL - - PORT_START("SW1") - PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "SW1:1") - PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "SW1:2") - PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "SW1:3") - PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "SW1:4") - PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "SW1:5") - PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "SW1:6") - PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "SW1:7") - PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "SW1:8") - - PORT_START("SW2") - PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "SW2:1") - PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "SW2:2") - PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "SW2:3") - PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "SW2:4") - PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "SW2:5") - PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "SW2:6") - PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "SW2:7") - PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "SW2:8") -INPUT_PORTS_END - static INPUT_PORTS_START( jrpacmbl ) PORT_START("P1") @@ -544,52 +456,6 @@ void pengo_state::jrpacmbl(machine_config &config) MCFG_VIDEO_START_OVERRIDE(pengo_state,jrpacman) } -void pengo_state::schick(machine_config &config) // all dividers unknown -{ - /* basic machine hardware */ - Z80(config, m_maincpu, MASTER_CLOCK/6); - m_maincpu->set_addrmap(AS_PROGRAM, &pengo_state::schick_map); - m_maincpu->set_addrmap(AS_OPCODES, &pengo_state::schick_decrypted_opcodes_map); - - z80_device &audiocpu(Z80(config, "audiocpu", MASTER_CLOCK/6)); - audiocpu.set_addrmap(AS_PROGRAM, &pengo_state::schick_audio_map); - audiocpu.set_addrmap(AS_IO, &pengo_state::schick_audio_io_map); - - GENERIC_LATCH_8(config, "soundlatch"); - - WATCHDOG_TIMER(config, m_watchdog); - - LS259(config, m_latch); // 3I, TODO: identify bits' function. 0 is correct, 2, 6 and 7 seem to be set when switching from title screen to game screen, 1, 3, 4 and 5 seem to never be set during gameplay - m_latch->q_out_cb<0>().set(FUNC(pengo_state::irq_mask_w)); - m_latch->q_out_cb<1>().set_log("m_latch bit 1 set"); - m_latch->q_out_cb<2>().set(FUNC(pengo_state::pengo_palettebank_w)); - m_latch->q_out_cb<3>().set_log("m_latch bit 3 set"); - m_latch->q_out_cb<4>().set_log("m_latch bit 4 set"); - m_latch->q_out_cb<5>().set_log("m_latch bit 5 set"); - m_latch->q_out_cb<6>().set(FUNC(pengo_state::pengo_colortablebank_w)); - m_latch->q_out_cb<7>().set(FUNC(pengo_state::pengo_gfxbank_w)); - - /* video hardware */ - GFXDECODE(config, m_gfxdecode, m_palette, gfx_pengo); - PALETTE(config, m_palette, FUNC(pengo_state::pacman_palette), 128 * 4, 32); - - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); // to be verified - screen.set_raw(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART); - screen.set_screen_update(FUNC(pengo_state::screen_update_pacman)); - screen.set_palette(m_palette); - screen.screen_vblank().set(FUNC(pengo_state::vblank_irq)); - - MCFG_VIDEO_START_OVERRIDE(pengo_state, pengo) - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - - AY8910(config, "ay1", MASTER_CLOCK/12).add_route(ALL_OUTPUTS, "mono", 0.13); - - AY8910(config, "ay2", MASTER_CLOCK/12).add_route(ALL_OUTPUTS, "mono", 0.13); - - AY8910(config, "ay3", MASTER_CLOCK/12).add_route(ALL_OUTPUTS, "mono", 0.13); -} /************************************* * @@ -827,25 +693,6 @@ ROM_START( penta ) ROM_LOAD( "pr1636.ic70", 0x0100, 0x0100, CRC(77245b66) SHA1(0c4d0bee858b97632411c440bea6948a74759746) ) /* timing - not used */ ROM_END -// MH032288 PCB. LC ('lato componenti', components side in Italian) so maybe produced in Italy? -// A plastic block in a corner covers probably the main CPU and the decryption logic. -// Might fit better in a different driver once decrypted -ROM_START( schick ) - ROM_REGION( 0x10000, "maincpu", 0 ) - ROM_LOAD( "27c512.8d", 0x0000, 0x10000, CRC(38986329) SHA1(bfd62d6a49d25acc582e5f076833c3b22c1a7fd7) ) - - ROM_REGION( 0x8000, "audiocpu", 0 ) - ROM_LOAD( "27c256.7m", 0x0000, 0x8000, CRC(694dadca) SHA1(65d436d6c8ebf6a9b5af286122e7391973d463e0) ) // identical to bombjack, but 4x - - ROM_REGION( 0x10000, "gfx1", 0 ) - ROM_LOAD( "27c256.4e", 0x0000, 0x8000, CRC(edb4a243) SHA1(64f35b5142ffb3bfbd6a2899af9d1d719b83e2a1) ) - ROM_LOAD( "4.27c256.4f", 0x8000, 0x8000, CRC(f666a52a) SHA1(877e1112c9c9a39b55934f6a382ad35fc9bf6859) ) // only labeled ROM - - ROM_REGION( 0x0420, "proms", ROMREGION_ERASEFF ) - // currently not dumped, using the ones from Pengo for now - ROM_LOAD( "pr1633.ic78", 0x0000, 0x0020, BAD_DUMP CRC(3a5844ec) SHA1(680eab0e1204c9b74adc11588461651b474021bb) ) // color palette - ROM_LOAD( "pr1634.ic88", 0x0020, 0x0400, BAD_DUMP CRC(766b139b) SHA1(3fcd66610fcaee814953a115bf5e04788923181f) ) // color lookup -ROM_END ROM_START( jrpacmbl ) @@ -960,76 +807,6 @@ void pengo_state::init_penta() decode_penta(0x8000, 0x8000); } -void pengo_state::decode_schick_extra(int size, uint8_t* rom) -{ - // schick has an extra layer of encryption in addition to the penta encryption - for (int A = 0x0000; A < 0x8000; A++) - { - uint8_t srcdec = rom[A]; - - if (A & 0x100) - { - srcdec = bitswap<8>(srcdec^0x41, 7, 4, 5, 6, 3, 2, 1, 0); - } - else - { - srcdec = bitswap<8>(srcdec^0x51, 7, 6, 5, 0, 3, 2, 1, 4); - } - - - rom[A] = srcdec; - } - - for (int A = 0x8000; A < 0x10000; A++) // TODO: verify everything - { - uint8_t srcdec = rom[A]; - - // this layer of encryption only affects bits 0,4,6 ? - - if (rom == m_decrypted_opcodes) - { - if (A & 0x1000) // TODO: more conditions? - { - srcdec = bitswap<8>(srcdec ^ 0x40, 7, 0, 5, 6, 3, 2, 1, 4); - rom[A] = srcdec; - } - else - { - if (A & 0x100) - { - srcdec = bitswap<8>(srcdec ^ 0x40, 7, 4, 5, 0, 3, 2, 1, 6); - rom[A] = srcdec; - } - else - { - srcdec = bitswap<8>(srcdec ^ 0x41, 7, 0, 5, 6, 3, 2, 1, 4); - rom[A] = srcdec; - } - } - } - else - { - // // TODO: more conditions? - if (A & 0x10) - srcdec = bitswap<8>(srcdec ^ 0x11, 7, 0, 5, 6, 3, 2, 1, 4); - else - srcdec = bitswap<8>(srcdec ^ 0x51, 7, 4, 5, 0, 3, 2, 1, 6); - - rom[A] = srcdec; - } - } -} - -void pengo_state::init_schick() -{ - uint8_t *rom = memregion("maincpu")->base(); - - decode_penta(0x8000, 0x10000); - - decode_schick_extra(0x10000, rom); - decode_schick_extra(0x10000, m_decrypted_opcodes); -} - /************************************* * @@ -1046,4 +823,3 @@ GAME( 1982, pengo5, pengo, pengoe, pengo, pengo_state, empty_init, RO GAME( 1982, pengob, pengo, pengo, pengo, pengo_state, init_penta, ROT90, "bootleg", "Pengo (bootleg)", MACHINE_SUPPORTS_SAVE ) GAME( 1982, penta, pengo, pengo, pengo, pengo_state, init_penta, ROT90, "bootleg (Grinbee Shouji)", "Penta", MACHINE_SUPPORTS_SAVE ) // Grinbee Shouji was a subsidiary of Orca GAME( 1983, jrpacmbl, jrpacman, jrpacmbl, jrpacmbl, pengo_state, empty_init, ROT90, "bootleg", "Jr. Pac-Man (Pengo hardware)", MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) -GAME( 1988, schick, 0, schick, schick, pengo_state, init_schick, ROT90, "Microhard", "Super Chick", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // wrong colors due to missing PROMs, sound not hooked up, only basic controls verified, decryption could be incomplete (bad ROMs in test mode?) diff --git a/src/mame/drivers/schick.cpp b/src/mame/drivers/schick.cpp new file mode 100644 index 00000000000..2225908bb27 --- /dev/null +++ b/src/mame/drivers/schick.cpp @@ -0,0 +1,611 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood, Nicola Salmoria + +/* a strange hack of Pengo, seems to be built on top of the 'Penta' bootleg + its recycles encryption from there + adds an additional layer of encryption + has 4bpp tils instead of 2bpp, bombjack sound system + and possibly extra protection (conditional jumps to areas where there is no ROM data) + colours from undumped? proms (doesn't seem to be a palette RAM even with the extended 4bpp tiles) + + the changes are extensive enough to keep it here in its own driver +*/ + +#include "emu.h" + +#include "cpu/z80/z80.h" +#include "machine/74259.h" +#include "machine/gen_latch.h" +#include "machine/watchdog.h" +#include "sound/ay8910.h" +#include "emupal.h" +#include "tilemap.h" +#include "screen.h" +#include "speaker.h" +#include "video/resnet.h" + + +class schick_state : public driver_device +{ +public: + schick_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_decrypted_opcodes(*this, "decrypted_opcodes"), + m_latch(*this, "latch"), + m_watchdog(*this, "watchdog"), + m_spriteram(*this, "spriteram"), + m_spriteram2(*this, "spriteram2"), + m_videoram(*this, "videoram"), + m_colorram(*this, "colorram"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette"), + m_irq_mask(0) + {} + + void schick(machine_config &config); + + void init_schick(); + +private: + DECLARE_WRITE_LINE_MEMBER(coin_counter_1_w); + DECLARE_WRITE_LINE_MEMBER(coin_counter_2_w); + DECLARE_WRITE_LINE_MEMBER(irq_mask_w); + DECLARE_WRITE_LINE_MEMBER(vblank_irq); + + DECLARE_WRITE_LINE_MEMBER(schick_palettebank_w); + DECLARE_WRITE_LINE_MEMBER(schick_colortablebank_w); + DECLARE_WRITE_LINE_MEMBER(schick_gfxbank_w); + + TILEMAP_MAPPER_MEMBER(schick_scan_rows); + TILE_GET_INFO_MEMBER(schick_get_tile_info); + + void decode_penta(int end, int nodecend); + void decode_schick_extra(int size, uint8_t* rom); + + void schick_videoram_w(offs_t offset, uint8_t data); + void schick_colorram_w(offs_t offset, uint8_t data); + + required_device m_maincpu; + optional_shared_ptr m_decrypted_opcodes; + optional_device m_latch; + required_device m_watchdog; + optional_shared_ptr m_spriteram; + optional_shared_ptr m_spriteram2; + required_shared_ptr m_videoram; + optional_shared_ptr m_colorram; + required_device m_gfxdecode; + required_device m_palette; + + void schick_portmap(address_map &map); + void schick_decrypted_opcodes_map(address_map &map); + void schick_map(address_map &map); + void schick_audio_map(address_map &map); + void schick_audio_io_map(address_map &map); + + uint8_t m_irq_mask; + uint32_t screen_update_schick(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + DECLARE_VIDEO_START(schick); + + tilemap_t *m_bg_tilemap; + uint8_t m_charbank; + uint8_t m_spritebank; + uint8_t m_palettebank; + uint8_t m_colortablebank; + uint8_t m_flipscreen; + uint8_t m_bgpriority; + uint8_t m_inv_spr; + + uint8_t schick_hack_r() + { + return 0xff; + } + +}; + +#define MASTER_CLOCK (18432000) + +#define PIXEL_CLOCK (MASTER_CLOCK/3) + +/* H counts from 128->511, HBLANK starts at 128+16=144 and ends at 128+64+32+16=240 */ +#define HTOTAL (384) +#define HBEND (0) /*(96+16)*/ +#define HBSTART (288) /*(16)*/ + +#define VTOTAL (264) +#define VBEND (0) /*(16)*/ +#define VBSTART (224) /*(224+16)*/ + + +VIDEO_START_MEMBER(schick_state,schick) +{ + save_item(NAME(m_charbank)); + save_item(NAME(m_spritebank)); + save_item(NAME(m_palettebank)); + save_item(NAME(m_colortablebank)); + save_item(NAME(m_flipscreen)); + save_item(NAME(m_bgpriority)); + + m_charbank = 0; + m_spritebank = 0; + m_palettebank = 0; + m_colortablebank = 0; + m_flipscreen = 0; + m_bgpriority = 0; + m_inv_spr = 0; + + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(schick_state::schick_get_tile_info)), tilemap_mapper_delegate(*this, FUNC(schick_state::schick_scan_rows)), 8, 8, 36, 28); +} + +TILEMAP_MAPPER_MEMBER(schick_state::schick_scan_rows) +{ + int offs; + + row += 2; + col -= 2; + if (col & 0x20) + offs = row + ((col & 0x1f) << 5); + else + offs = col + (row << 5); + + return offs; +} + +TILE_GET_INFO_MEMBER(schick_state::schick_get_tile_info) +{ + int code = m_videoram[tile_index] | (m_charbank << 8); + int attr = (m_colorram[tile_index] & 0x1f) | (m_colortablebank << 5) | (m_palettebank << 6 ); + + attr &= 0xf; + + tileinfo.set(0,code,attr,0); +} + +void schick_state::schick_videoram_w(offs_t offset, uint8_t data) +{ + m_videoram[offset] = data; + m_bg_tilemap->mark_tile_dirty(offset ); +} + +void schick_state::schick_colorram_w(offs_t offset, uint8_t data) +{ + m_colorram[offset] = data; + m_bg_tilemap->mark_tile_dirty(offset ); +} + +WRITE_LINE_MEMBER(schick_state::schick_palettebank_w) +{ + m_palettebank = state; + m_bg_tilemap->mark_all_dirty(); +} + +WRITE_LINE_MEMBER(schick_state::schick_colortablebank_w) +{ + m_colortablebank = state; + m_bg_tilemap->mark_all_dirty(); +} + +WRITE_LINE_MEMBER(schick_state::schick_gfxbank_w) +{ + m_spritebank = state; + m_charbank = state; + m_bg_tilemap->mark_all_dirty(); +} + +WRITE_LINE_MEMBER(schick_state::coin_counter_1_w) +{ + machine().bookkeeping().coin_counter_w(0, state); +} + +WRITE_LINE_MEMBER(schick_state::coin_counter_2_w) +{ + machine().bookkeeping().coin_counter_w(1, state); +} + +WRITE_LINE_MEMBER(schick_state::irq_mask_w) +{ + m_irq_mask = state; +} + +uint32_t schick_state::screen_update_schick(screen_device& screen, bitmap_ind16& bitmap, const rectangle& cliprect) +{ + if (m_bgpriority != 0) + bitmap.fill(0, cliprect); + else + m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE, 0); + + if (m_spriteram != nullptr) + { + uint8_t* spriteram = m_spriteram; + uint8_t* spriteram_2 = m_spriteram2; + int offs; + + rectangle spriteclip(2 * 8, 34 * 8 - 1, 0 * 8, 28 * 8 - 1); + spriteclip &= cliprect; + + /* Draw the sprites. Note that it is important to draw them exactly in this */ + /* order, to have the correct priorities. */ + for (offs = m_spriteram.bytes() - 2; offs >= 0; offs -= 2) + { + int color; + int sx, sy; + uint8_t fx, fy; + + if (m_inv_spr) + { + sx = spriteram_2[offs + 1]; + sy = 240 - (spriteram_2[offs]); + } + else + { + sx = 272 - spriteram_2[offs + 1]; + sy = spriteram_2[offs] - 31; + } + + fx = (spriteram[offs] & 1) ^ m_inv_spr; + fy = (spriteram[offs] & 2) ^ ((m_inv_spr) << 1); + + color = (spriteram[offs + 1] & 0x1f) | (m_colortablebank << 5) | (m_palettebank << 6); + + m_gfxdecode->gfx(1)->transpen(bitmap, spriteclip, + (spriteram[offs] >> 2) | (m_spritebank << 6), + color, + fx, fy, + sx, sy, + 0); + + m_gfxdecode->gfx(1)->transpen(bitmap, spriteclip, + (spriteram[offs] >> 2) | (m_spritebank << 6), + color, + fx, fy, + sx - 256, sy, + 0); + } + } + + if (m_bgpriority != 0) + m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); + + return 0; +} + +void schick_state::schick_portmap(address_map &map) +{ + map.global_mask(0xff); +} + +void schick_state::schick_map(address_map &map) // everything needs to be verified, where's the sound latch? +{ + map(0x0000, 0x7fff).rom(); + map(0x8000, 0x83ff).ram().w(FUNC(schick_state::schick_videoram_w)).share("videoram"); + map(0x8400, 0x87ff).ram().w(FUNC(schick_state::schick_colorram_w)).share("colorram"); + map(0x8800, 0x8fef).ram().share("mainram"); + map(0x8ff0, 0x8fff).ram().share("spriteram"); + + map(0x8923, 0x8924).r(FUNC(schick_state::schick_hack_r)); // protection? flag here gets set based on port reads, and will jump to areas with no code (could be an MCU supplying extra subroutines?) + + map(0x9000, 0x901f).nopw(); // leftover from pengo? + map(0x9020, 0x902f).writeonly().share("spriteram2"); + map(0x9000, 0x903f).portr("SW2"); + map(0x9040, 0x907f).portr("SW1"); + map(0x9040, 0x9047).w(m_latch, FUNC(ls259_device::write_d0)); + map(0x9070, 0x9070).w(m_watchdog, FUNC(watchdog_timer_device::reset_w)); + map(0x9080, 0x90bf).portr("IN1"); + map(0x90c0, 0x90ff).portr("IN0"); + map(0xe000, 0xffff).rom(); +} + +void schick_state::schick_decrypted_opcodes_map(address_map &map) +{ + map(0x0000, 0xffff).rom().share("decrypted_opcodes"); + map(0x8800, 0x8fef).ram().share("mainram"); + map(0x8ff0, 0x8fff).ram().share("spriteram"); +} + +void schick_state::schick_audio_map(address_map &map) +{ + map(0x0000, 0x1fff).rom(); + map(0x4000, 0x43ff).ram(); + map(0x6000, 0x6000).r("soundlatch", FUNC(generic_latch_8_device::read)); +} + +void schick_state::schick_audio_io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x00, 0x01).w("ay1", FUNC(ay8910_device::address_data_w)); + map(0x10, 0x11).w("ay2", FUNC(ay8910_device::address_data_w)); + map(0x80, 0x81).w("ay3", FUNC(ay8910_device::address_data_w)); +} + +static INPUT_PORTS_START( schick ) // TODO: check everything + PORT_START("IN0") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN3 ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) + + PORT_START("IN1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY PORT_COCKTAIL + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_COCKTAIL + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY PORT_COCKTAIL + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY PORT_COCKTAIL + PORT_SERVICE_NO_TOGGLE(0x10, IP_ACTIVE_LOW) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL + + PORT_START("SW1") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "SW1:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "SW1:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "SW1:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "SW1:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "SW1:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "SW1:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "SW1:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "SW1:8") + + PORT_START("SW2") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "SW2:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "SW2:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "SW2:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "SW2:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "SW2:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "SW2:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "SW2:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "SW2:8") +INPUT_PORTS_END + + +static const gfx_layout tilelayout = +{ + 8,8, + RGN_FRAC(1,2), + 4, + { 0, 4, RGN_FRAC(1,2)+0, RGN_FRAC(1,2)+4 }, + { 8*8+0, 8*8+1, 8*8+2, 8*8+3, 0, 1, 2, 3 }, + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }, + 16*8 +}; + +static const gfx_layout spritelayout = +{ + 16,16, + RGN_FRAC(1,2), + 4, + { 0, 4, RGN_FRAC(1,2)+0, RGN_FRAC(1,2)+4 }, + { 8*8, 8*8+1, 8*8+2, 8*8+3, 16*8+0, 16*8+1, 16*8+2, 16*8+3, + 24*8+0, 24*8+1, 24*8+2, 24*8+3, 0, 1, 2, 3 }, + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, + 32*8, 33*8, 34*8, 35*8, 36*8, 37*8, 38*8, 39*8 }, + 64*8 +}; + + +static GFXDECODE_START( gfx_schick ) + GFXDECODE_ENTRY( "gfx1", 0x0000, tilelayout, 0, 128/4 ) + GFXDECODE_ENTRY( "gfx1", 0x0000, spritelayout, 0, 128/4 ) +GFXDECODE_END + +WRITE_LINE_MEMBER(schick_state::vblank_irq) +{ + if (state && m_irq_mask) + m_maincpu->set_input_line(0, HOLD_LINE); +} + +void schick_state::schick(machine_config &config) // all dividers unknown +{ + /* basic machine hardware */ + Z80(config, m_maincpu, MASTER_CLOCK/6); + m_maincpu->set_addrmap(AS_PROGRAM, &schick_state::schick_map); + m_maincpu->set_addrmap(AS_OPCODES, &schick_state::schick_decrypted_opcodes_map); + m_maincpu->set_addrmap(AS_IO, &schick_state::schick_portmap); + + z80_device &audiocpu(Z80(config, "audiocpu", MASTER_CLOCK/6)); + audiocpu.set_addrmap(AS_PROGRAM, &schick_state::schick_audio_map); + audiocpu.set_addrmap(AS_IO, &schick_state::schick_audio_io_map); + + GENERIC_LATCH_8(config, "soundlatch"); + + WATCHDOG_TIMER(config, m_watchdog); + + LS259(config, m_latch); // 3I, TODO: identify bits' function. 0 is correct, 2, 6 and 7 seem to be set when switching from title screen to game screen, 1, 3, 4 and 5 seem to never be set during gameplay + m_latch->q_out_cb<0>().set(FUNC(schick_state::irq_mask_w)); + m_latch->q_out_cb<1>().set_log("m_latch bit 1 set"); + m_latch->q_out_cb<2>().set(FUNC(schick_state::schick_palettebank_w)); + m_latch->q_out_cb<3>().set_log("m_latch bit 3 set"); + m_latch->q_out_cb<4>().set_log("m_latch bit 4 set"); + m_latch->q_out_cb<5>().set_log("m_latch bit 5 set"); + m_latch->q_out_cb<6>().set(FUNC(schick_state::schick_colortablebank_w)); + m_latch->q_out_cb<7>().set(FUNC(schick_state::schick_gfxbank_w)); + + /* video hardware */ + GFXDECODE(config, m_gfxdecode, m_palette, gfx_schick); + PALETTE(config, "palette").set_format(palette_device::xRGB_555, 0x8000); // unknown format, from missing PROMs? + + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); // to be verified + screen.set_raw(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART); + screen.set_screen_update(FUNC(schick_state::screen_update_schick)); + screen.set_palette(m_palette); + screen.screen_vblank().set(FUNC(schick_state::vblank_irq)); + + MCFG_VIDEO_START_OVERRIDE(schick_state, schick) + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + + AY8910(config, "ay1", MASTER_CLOCK/12).add_route(ALL_OUTPUTS, "mono", 0.13); + + AY8910(config, "ay2", MASTER_CLOCK/12).add_route(ALL_OUTPUTS, "mono", 0.13); + + AY8910(config, "ay3", MASTER_CLOCK/12).add_route(ALL_OUTPUTS, "mono", 0.13); +} + + + +// copied from schick.cpp, as also used here +void schick_state::decode_penta(int end, int nodecend) +{ +/* + the values vary, but the translation mask is always laid out like this: + + 0 1 2 3 4 5 6 7 8 9 a b c d e f + 0 A A B B A A B B C C D D C C D D + 1 A A B B A A B B C C D D C C D D + 2 E E F F E E F F G G H H G G H H + 3 E E F F E E F F G G H H G G H H + 4 A A B B A A B B C C D D C C D D + 5 A A B B A A B B C C D D C C D D + 6 E E F F E E F F G G H H G G H H + 7 E E F F E E F F G G H H G G H H + 8 H H G G H H G G F F E E F F E E + 9 H H G G H H G G F F E E F F E E + a D D C C D D C C B B A A B B A A + b D D C C D D C C B B A A B B A A + c H H G G H H G G F F E E F F E E + d H H G G H H G G F F E E F F E E + e D D C C D D C C B B A A B B A A + f D D C C D D C C B B A A B B A A + + (e.g. 0xc0 is XORed with H) + therefore in the following tables we only keep track of A, B, C, D, E, F, G and H. +*/ + static const uint8_t data_xortable[2][8] = + { + { 0xa0,0x82,0x28,0x0a,0x82,0xa0,0x0a,0x28 }, /* ...............0 */ + { 0x88,0x0a,0x82,0x00,0x88,0x0a,0x82,0x00 } /* ...............1 */ + }; + static const uint8_t opcode_xortable[8][8] = + { + { 0x02,0x08,0x2a,0x20,0x20,0x2a,0x08,0x02 }, /* ...0...0...0.... */ + { 0x88,0x88,0x00,0x00,0x88,0x88,0x00,0x00 }, /* ...0...0...1.... */ + { 0x88,0x0a,0x82,0x00,0xa0,0x22,0xaa,0x28 }, /* ...0...1...0.... */ + { 0x88,0x0a,0x82,0x00,0xa0,0x22,0xaa,0x28 }, /* ...0...1...1.... */ + { 0x2a,0x08,0x2a,0x08,0x8a,0xa8,0x8a,0xa8 }, /* ...1...0...0.... */ + { 0x2a,0x08,0x2a,0x08,0x8a,0xa8,0x8a,0xa8 }, /* ...1...0...1.... */ + { 0x88,0x0a,0x82,0x00,0xa0,0x22,0xaa,0x28 }, /* ...1...1...0.... */ + { 0x88,0x0a,0x82,0x00,0xa0,0x22,0xaa,0x28 } /* ...1...1...1.... */ + }; + + uint8_t *rom = memregion("maincpu")->base(); + + for (int A = 0x0000;A < end;A++) + { + uint8_t src = rom[A]; + + /* pick the translation table from bit 0 of the address */ + int i = A & 1; + + /* pick the offset in the table from bits 1, 3 and 5 of the source data */ + int j = ((src >> 1) & 1) + (((src >> 3) & 1) << 1) + (((src >> 5) & 1) << 2); + /* the bottom half of the translation table is the mirror image of the top */ + if (src & 0x80) j = 7 - j; + + /* decode the ROM data */ + rom[A] = src ^ data_xortable[i][j]; + + /* now decode the opcodes */ + /* pick the translation table from bits 4, 8 and 12 of the address */ + i = ((A >> 4) & 1) + (((A >> 8) & 1) << 1) + (((A >> 12) & 1) << 2); + m_decrypted_opcodes[A] = src ^ opcode_xortable[i][j]; + } + + for (int A = end; A < nodecend; A++) + { + m_decrypted_opcodes[A] = rom[A]; + } +} + +void schick_state::decode_schick_extra(int size, uint8_t* rom) +{ + // schick has an extra layer of encryption in addition to the penta encryption + for (int A = 0x0000; A < 0x8000; A++) + { + uint8_t srcdec = rom[A]; + + if (A & 0x100) + { + srcdec = bitswap<8>(srcdec^0x41, 7, 4, 5, 6, 3, 2, 1, 0); + } + else + { + srcdec = bitswap<8>(srcdec^0x51, 7, 6, 5, 0, 3, 2, 1, 4); + } + + + rom[A] = srcdec; + } + + for (int A = 0x8000; A < 0x10000; A++) // TODO: verify everything + { + uint8_t srcdec = rom[A]; + + // this layer of encryption only affects bits 0,4,6 ? + + if (rom == m_decrypted_opcodes) + { + if (A & 0x1000) // TODO: more conditions? + { + srcdec = bitswap<8>(srcdec ^ 0x40, 7, 0, 5, 6, 3, 2, 1, 4); + rom[A] = srcdec; + } + else + { + if (A & 0x100) + { + srcdec = bitswap<8>(srcdec ^ 0x40, 7, 4, 5, 0, 3, 2, 1, 6); + rom[A] = srcdec; + } + else + { + srcdec = bitswap<8>(srcdec ^ 0x41, 7, 0, 5, 6, 3, 2, 1, 4); + rom[A] = srcdec; + } + } + } + else + { + // // TODO: more conditions? + if (A & 0x10) + srcdec = bitswap<8>(srcdec ^ 0x11, 7, 0, 5, 6, 3, 2, 1, 4); + else + srcdec = bitswap<8>(srcdec ^ 0x51, 7, 4, 5, 0, 3, 2, 1, 6); + + rom[A] = srcdec; + } + } +} + +void schick_state::init_schick() +{ + uint8_t *rom = memregion("maincpu")->base(); + + decode_penta(0x8000, 0x10000); + + decode_schick_extra(0x10000, rom); + decode_schick_extra(0x10000, m_decrypted_opcodes); +} + + +// MH032288 PCB. LC ('lato componenti', components side in Italian) so maybe produced in Italy? +// A plastic block in a corner covers probably the main CPU and the decryption logic. +// Might fit better in a different driver once decrypted +ROM_START( schick ) + ROM_REGION( 0x10000, "maincpu", 0 ) + ROM_LOAD( "27c512.8d", 0x0000, 0x10000, CRC(38986329) SHA1(bfd62d6a49d25acc582e5f076833c3b22c1a7fd7) ) + + ROM_REGION( 0x8000, "audiocpu", 0 ) + ROM_LOAD( "27c256.7m", 0x0000, 0x8000, CRC(694dadca) SHA1(65d436d6c8ebf6a9b5af286122e7391973d463e0) ) // identical to bombjack, but 4x + + ROM_REGION( 0x10000, "gfx1", 0 ) + ROM_LOAD( "4.27c256.4f", 0x0000, 0x8000, CRC(f666a52a) SHA1(877e1112c9c9a39b55934f6a382ad35fc9bf6859) ) // only labeled ROM + ROM_LOAD( "27c256.4e", 0x8000, 0x8000, CRC(edb4a243) SHA1(64f35b5142ffb3bfbd6a2899af9d1d719b83e2a1) ) + + ROM_REGION( 0x0100, "proms", ROMREGION_ERASEFF ) + ROM_LOAD( "proms", 0x0000, 0x0100, NO_DUMP ) // color palette, unknown PROM size + arrangement +ROM_END + + +GAME( 1988, schick, 0, schick, schick, schick_state, init_schick, ROT90, "Microhard", "Super Chick", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // wrong colors due to missing PROMs, sound not hooked up, only basic controls verified, decryption could be incomplete (bad ROMs in test mode?) diff --git a/src/mame/drivers/spg2xx.cpp b/src/mame/drivers/spg2xx.cpp index 3d7d906e590..8f3ec3b6814 100644 --- a/src/mame/drivers/spg2xx.cpp +++ b/src/mame/drivers/spg2xx.cpp @@ -1663,7 +1663,7 @@ CONS( 2006, ablkickb, 0, 0, ablkickb, ablkickb, spg2xx_game_albkickb_ CONS( 2007, lxspidaj, 0, 0, spg2xx, lxspidaj, spg2xx_game_albkickb_state, init_ablkickb, "Lexibook", "Spider-Man Super TV Air Jet (Lexibook Junior, JG6000SP)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) -CONS( 2006, fordrace, 0, 0, fordrace, fordrace, spg2xx_game_fordrace_state, empty_init, "Excalibur Electronics", "Ford Racing", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2006, fordrace, 0, 0, fordrace, fordrace, spg2xx_game_fordrace_state, empty_init, "Excalibur Electronics", "Ford Racing", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) CONS( 2008, comil, 0, 0, comil, comil, spg2xx_game_comil_state, empty_init, "Character Options", "Who Wants to Be a Millionaire? (Character Options, Plug and Play, UK)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) @@ -1686,7 +1686,7 @@ CONS( 2009, gssytts, 0, 0, gssytts, guitarss, spg2xx_game_gssytts_s CONS( 2006, vtechtvssp, 0, 0, spg2xx, spg2xx, spg2xx_game_state, empty_init, "VTech", "TV Station (VTech, Spain)", MACHINE_NOT_WORKING ) CONS( 2006, vtechtvsgr, 0, 0, spg2xx, spg2xx, spg2xx_game_state, empty_init, "VTech", "TV Learning Station (VTech, Germany)", MACHINE_NOT_WORKING ) -CONS( 2008, senspeed, 0, 0, senspeed, senspeed, spg2xx_game_senspeed_state, empty_init, "Senario", "Speed Racer (Senario)", MACHINE_NOT_WORKING ) +CONS( 2008, senspeed, 0, 0, senspeed, senspeed, spg2xx_game_senspeed_state, empty_init, "Senario", "Speed Racer (Senario)", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) CONS( 200?, jjstrip, 0, 0, tvsprt10, jjstrip, spg2xx_game_state, empty_init, "Shiggles Inc.", "Club Jenna Presents: Jenna Jameson's Strip Poker", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS ) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 4a34fde6fdf..37323d8c9b5 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -32737,7 +32737,6 @@ pengo4 // 834-0386 (c) 1982 Sega pengo5 // 834-0386 (c) 1982 Sega pengob // bootleg penta // bootleg -schick // Microhard @source:pentagon.cpp pent1024 // @@ -35631,6 +35630,9 @@ sbuggera // (c) 1981 Game-A-Tron sc2 // sc2a // +@source:schick.cpp +schick // Microhard + @source:scm_500.cpp scm_500 //