move schick out of pengo driver + misc promotions (#6842)

* moved schick.cpp out of pengo driver, too many small modifications to the hardware make it messy to keep there  (nw)

also promoted some sunplus games I've decided work well enough to promote (nw)

* (nw)

* (nw)
This commit is contained in:
David Haywood 2020-06-19 19:58:05 +01:00 committed by GitHub
parent e13544c5a2
commit 489d1882b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 620 additions and 229 deletions

View File

@ -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")

View File

@ -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)

View File

@ -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<uint8_t> m_decrypted_opcodes;
optional_device<ls259_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?)

611
src/mame/drivers/schick.cpp Normal file
View File

@ -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<cpu_device> m_maincpu;
optional_shared_ptr<uint8_t> m_decrypted_opcodes;
optional_device<ls259_device> m_latch;
required_device<watchdog_timer_device> m_watchdog;
optional_shared_ptr<uint8_t> m_spriteram;
optional_shared_ptr<uint8_t> m_spriteram2;
required_shared_ptr<uint8_t> m_videoram;
optional_shared_ptr<uint8_t> m_colorram;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_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?)

View File

@ -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 )

View File

@ -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 //