// license:BSD-3-Clause // copyright-holders:David Haywood, Mirko Buffoni /* Happy Jackie (c) 1993 IGS. Video Slot machine game for amusement only. Driver by David Haywood and Mirko Buffoni */ /* Anno 199x Produttore IGS N.revisione CPU 1x Z0840006PSC (main) 2x D8255AC 1x unknown AMT001 1x unknown IGS002 1x UM3567 (sound) 1x oscillator 12.000MHz 1x oscillator 3.579645 ROMs 2x D27128A (1,3) 1x MBM27128 (2) 3x 27C010 (4,5,6) 1x D27512 (7sv) 1x MBM27C512 (v110) 1x unknown (DIP20 mil300)(jack3) 3x PEEL18CV8PC (read protected) 1x TIBPAL16L8 (read protected) Note 1x 36x2 edge connector 1x 10x2 edge connector (payout system) 1x trimmer (volume) 1x pushbutton 1x battery 5x 8x2 switches dip */ #include "emu.h" #include "cpu/z80/z80.h" #include "machine/i8255.h" #include "machine/timer.h" #include "sound/ym2413.h" #include "screen.h" #include "speaker.h" class jackie_state : public driver_device { public: jackie_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this,"maincpu") , m_gfxdecode(*this, "gfxdecode") , m_screen(*this, "screen") , m_palette(*this, "palette") , m_bg_scroll2(*this, "bg_scroll2") , m_bg_scroll(*this, "bg_scroll") , m_reel1_ram(*this, "reel1_ram") , m_reel2_ram(*this, "reel2_ram") , m_reel3_ram(*this, "reel3_ram") , m_fg_tile_ram(*this, "fg_tile_ram") , m_fg_color_ram(*this, "fg_color_ram") , m_led(*this, "led") , m_lamps(*this, "lamp%u", 1U) { } DECLARE_WRITE8_MEMBER(fg_tile_w); DECLARE_WRITE8_MEMBER(fg_color_w); DECLARE_WRITE8_MEMBER(bg_scroll_w); DECLARE_WRITE8_MEMBER(reel1_ram_w); DECLARE_WRITE8_MEMBER(reel2_ram_w); DECLARE_WRITE8_MEMBER(reel3_ram_w); DECLARE_WRITE8_MEMBER(unk_reg1_lo_w); DECLARE_WRITE8_MEMBER(unk_reg2_lo_w); DECLARE_WRITE8_MEMBER(unk_reg3_lo_w); DECLARE_WRITE8_MEMBER(unk_reg1_hi_w); DECLARE_WRITE8_MEMBER(unk_reg2_hi_w); DECLARE_WRITE8_MEMBER(unk_reg3_hi_w); DECLARE_WRITE8_MEMBER(nmi_and_coins_w); DECLARE_WRITE8_MEMBER(lamps_w); DECLARE_READ8_MEMBER(igs_irqack_r); DECLARE_WRITE8_MEMBER(igs_irqack_w); DECLARE_READ8_MEMBER(expram_r); void unk_reg_lo_w( int offset, uint8_t data, int reg ); void unk_reg_hi_w( int offset, uint8_t data, int reg ); void show_out(); DECLARE_CUSTOM_INPUT_MEMBER(hopper_r); TILE_GET_INFO_MEMBER(get_fg_tile_info); TILE_GET_INFO_MEMBER(get_reel1_tile_info); TILE_GET_INFO_MEMBER(get_reel2_tile_info); TILE_GET_INFO_MEMBER(get_reel3_tile_info); void init_jackie(); uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); TIMER_DEVICE_CALLBACK_MEMBER(irq); void jackie(machine_config &config); void jackie_io_map(address_map &map); void jackie_prg_map(address_map &map); protected: virtual void machine_start() override; virtual void machine_reset() override; virtual void video_start() override; required_device m_maincpu; required_device m_gfxdecode; required_device m_screen; required_device m_palette; required_shared_ptr m_bg_scroll2; required_shared_ptr m_bg_scroll; required_shared_ptr m_reel1_ram; required_shared_ptr m_reel2_ram; required_shared_ptr m_reel3_ram; required_shared_ptr m_fg_tile_ram; required_shared_ptr m_fg_color_ram; output_finder<> m_led; output_finder<6> m_lamps; int m_exp_bank; tilemap_t *m_fg_tilemap; tilemap_t *m_reel1_tilemap; tilemap_t *m_reel2_tilemap; tilemap_t *m_reel3_tilemap; int m_irq_enable; int m_nmi_enable; int m_bg_enable; int m_hopper; uint8_t m_out[3]; uint16_t m_unk_reg[3][5]; }; TILE_GET_INFO_MEMBER(jackie_state::get_fg_tile_info) { int code = m_fg_tile_ram[tile_index] | (m_fg_color_ram[tile_index] << 8); int tile = code & 0x1fff; SET_TILE_INFO_MEMBER(0, code, tile != 0x1fff ? ((code >> 12) & 0xe) + 1 : 0, 0); } WRITE8_MEMBER(jackie_state::fg_tile_w) { m_fg_tile_ram[offset] = data; m_fg_tilemap->mark_tile_dirty(offset); } WRITE8_MEMBER(jackie_state::fg_color_w) { m_fg_color_ram[offset] = data; m_fg_tilemap->mark_tile_dirty(offset); } WRITE8_MEMBER(jackie_state::bg_scroll_w) { m_bg_scroll[offset] = data; } WRITE8_MEMBER(jackie_state::reel1_ram_w) { m_reel1_ram[offset] = data; m_reel1_tilemap->mark_tile_dirty(offset); } TILE_GET_INFO_MEMBER(jackie_state::get_reel1_tile_info) { int code = m_reel1_ram[tile_index]; SET_TILE_INFO_MEMBER(1, code, 0, 0); } WRITE8_MEMBER(jackie_state::reel2_ram_w) { m_reel2_ram[offset] = data; m_reel2_tilemap->mark_tile_dirty(offset); } TILE_GET_INFO_MEMBER(jackie_state::get_reel2_tile_info) { int code = m_reel2_ram[tile_index]; SET_TILE_INFO_MEMBER(1, code, 0, 0); } WRITE8_MEMBER(jackie_state::reel3_ram_w) { m_reel3_ram[offset] = data; m_reel3_tilemap->mark_tile_dirty(offset); } TILE_GET_INFO_MEMBER(jackie_state::get_reel3_tile_info) { int code = m_reel3_ram[tile_index]; SET_TILE_INFO_MEMBER(1, code, 0, 0); } void jackie_state::video_start() { m_reel1_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(jackie_state::get_reel1_tile_info),this),TILEMAP_SCAN_ROWS,8,32, 64, 8); m_reel2_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(jackie_state::get_reel2_tile_info),this),TILEMAP_SCAN_ROWS,8,32, 64, 8); m_reel3_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(jackie_state::get_reel3_tile_info),this),TILEMAP_SCAN_ROWS,8,32, 64, 8); m_reel1_tilemap->set_scroll_cols(64); m_reel2_tilemap->set_scroll_cols(64); m_reel3_tilemap->set_scroll_cols(64); m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(jackie_state::get_fg_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); m_fg_tilemap->set_transparent_pen(0); } uint32_t jackie_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { int i,j; int startclipmin = 0; const rectangle &visarea = screen.visible_area(); bitmap.fill(m_palette->black_pen(), cliprect); for (i=0;i < 0x40;i++) { m_reel1_tilemap->set_scrolly(i, m_bg_scroll[i+0x000]); m_reel2_tilemap->set_scrolly(i, m_bg_scroll[i+0x040]); m_reel3_tilemap->set_scrolly(i, m_bg_scroll[i+0x080]); } for (j=0; j < 0x100-1; j++) { rectangle clip; int rowenable = m_bg_scroll2[j]; /* draw top of screen */ clip.set(visarea.min_x, visarea.max_x, startclipmin, startclipmin+1); if (rowenable==0) { m_reel1_tilemap->draw(screen, bitmap, clip, 0,0); } else if (rowenable==1) { m_reel2_tilemap->draw(screen, bitmap, clip, 0,0); } else if (rowenable==2) { m_reel3_tilemap->draw(screen, bitmap, clip, 0,0); } else if (rowenable==3) { } startclipmin+=1; } m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0); return 0; } void jackie_state::machine_start() { m_led.resolve(); m_lamps.resolve(); save_item(NAME(m_exp_bank)); // save_item(NAME(m_irq_enable)); //always 1? save_item(NAME(m_nmi_enable)); // save_item(NAME(m_bg_enable)); //always 1? save_item(NAME(m_hopper)); save_item(NAME(m_out)); save_item(NAME(m_unk_reg)); } void jackie_state::machine_reset() { m_irq_enable = 1; m_nmi_enable = 0; m_hopper = 0; m_bg_enable = 1; } void jackie_state::show_out() { #ifdef MAME_DEBUG // popmessage("%02x %02x %02x", m_out[0], m_out[1], m_out[2]); popmessage("520: %04x %04x %04x %04x %04x\n560: %04x %04x %04x %04x %04x\n5A0: %04x %04x %04x %04x %04x", m_unk_reg[0][0],m_unk_reg[0][1],m_unk_reg[0][2],m_unk_reg[0][3],m_unk_reg[0][4], m_unk_reg[1][0],m_unk_reg[1][1],m_unk_reg[1][2],m_unk_reg[1][3],m_unk_reg[1][4], m_unk_reg[2][0],m_unk_reg[2][1],m_unk_reg[2][2],m_unk_reg[2][3],m_unk_reg[2][4] ); #endif } void jackie_state::unk_reg_lo_w( int offset, uint8_t data, int reg ) { m_unk_reg[reg][offset] &= 0xff00; m_unk_reg[reg][offset] |= data; show_out(); } WRITE8_MEMBER(jackie_state::unk_reg1_lo_w){ unk_reg_lo_w( offset, data, 0 ); } WRITE8_MEMBER(jackie_state::unk_reg2_lo_w){ unk_reg_lo_w( offset, data, 1 ); } WRITE8_MEMBER(jackie_state::unk_reg3_lo_w){ unk_reg_lo_w( offset, data, 2 ); } void jackie_state::unk_reg_hi_w( int offset, uint8_t data, int reg ) { m_unk_reg[reg][offset] &= 0xff; m_unk_reg[reg][offset] |= data << 8; show_out(); } WRITE8_MEMBER(jackie_state::unk_reg1_hi_w){ unk_reg_hi_w( offset, data, 0 ); } WRITE8_MEMBER(jackie_state::unk_reg2_hi_w){ unk_reg_hi_w( offset, data, 1 ); } WRITE8_MEMBER(jackie_state::unk_reg3_hi_w){ unk_reg_hi_w( offset, data, 2 ); } WRITE8_MEMBER(jackie_state::nmi_and_coins_w) { machine().bookkeeping().coin_counter_w(0, data & 0x01); // coin_a machine().bookkeeping().coin_counter_w(1, data & 0x04); // coin_c machine().bookkeeping().coin_counter_w(2, data & 0x08); // key in machine().bookkeeping().coin_counter_w(3, data & 0x10); // coin m_out mech m_led = BIT(data, 5); // led for coin m_out / m_hopper active m_exp_bank = (data & 0x02) ? 1 : 0; // expram bank number m_nmi_enable = data & 0x80; // nmi enable? m_out[0] = data; show_out(); } WRITE8_MEMBER(jackie_state::lamps_w) { /* - Lbits - 7654 3210 ========= ---- --x- Hold1 lamp. --x- ---- Hold2 lamp. ---x ---- Hold3 lamp. ---- x--- Hold4 lamp. ---- -x-- Hold5 lamp. ---- ---x Start lamp. */ m_lamps[0] = BIT(data, 1); /* Lamp 1 - HOLD 1 */ m_lamps[1] = BIT(data, 5); /* Lamp 2 - HOLD 2 */ m_lamps[2] = BIT(data, 4); /* Lamp 3 - HOLD 3 */ m_lamps[3] = BIT(data, 3); /* Lamp 4 - HOLD 4 */ m_lamps[4] = BIT(data, 2); /* Lamp 5 - HOLD 5 */ m_lamps[5] = BIT(data, 0); /* Lamp 6 - START */ m_hopper = (~data)& 0x80; m_out[1] = data; show_out(); } READ8_MEMBER(jackie_state::igs_irqack_r) { m_irq_enable = 1; return 0; } WRITE8_MEMBER(jackie_state::igs_irqack_w) { // m_maincpu->set_input_line(0, CLEAR_LINE); m_out[2] = data; show_out(); } READ8_MEMBER(jackie_state::expram_r) { uint8_t *rom = memregion("gfx3")->base(); offset += m_exp_bank * 0x8000; // logerror("PC %06X: %04x = %02x\n",m_maincpu->pc(),offset,rom[offset]); return rom[offset]; } void jackie_state::jackie_prg_map(address_map &map) { map(0x0000, 0xefff).rom(); map(0xf000, 0xffff).ram().region("maincpu", 0xf000); } void jackie_state::jackie_io_map(address_map &map) { map(0x0520, 0x0524).w(this, FUNC(jackie_state::unk_reg1_lo_w)); map(0x0d20, 0x0d24).w(this, FUNC(jackie_state::unk_reg1_hi_w)); map(0x0560, 0x0564).w(this, FUNC(jackie_state::unk_reg2_lo_w)); map(0x0d60, 0x0d64).w(this, FUNC(jackie_state::unk_reg2_hi_w)); map(0x05a0, 0x05a4).w(this, FUNC(jackie_state::unk_reg3_lo_w)); map(0x0da0, 0x0da4).w(this, FUNC(jackie_state::unk_reg3_hi_w)); map(0x1000, 0x1107).ram().share("bg_scroll2"); map(0x2000, 0x27ff).ram().w(m_palette, FUNC(palette_device::write8)).share("palette"); map(0x2800, 0x2fff).ram().w(m_palette, FUNC(palette_device::write8_ext)).share("palette_ext"); map(0x4000, 0x4000).portr("DSW1"); /* DSW1 */ map(0x4001, 0x4001).portr("DSW2"); /* DSW2 */ map(0x4002, 0x4002).portr("DSW3"); /* DSW3 */ map(0x4003, 0x4003).portr("DSW4"); /* DSW4 */ map(0x4004, 0x4004).portr("DSW5"); /* DSW5 */ map(0x5080, 0x5083).rw("ppi1", FUNC(i8255_device::read), FUNC(i8255_device::write)); map(0x5090, 0x5093).rw("ppi2", FUNC(i8255_device::read), FUNC(i8255_device::write)); map(0x50a0, 0x50a0).portr("BUTTONS2"); map(0x50b0, 0x50b1).w("ymsnd", FUNC(ym2413_device::write)); map(0x50c0, 0x50c0).r(this, FUNC(jackie_state::igs_irqack_r)).w(this, FUNC(jackie_state::igs_irqack_w)); map(0x6000, 0x60ff).ram().w(this, FUNC(jackie_state::bg_scroll_w)).share("bg_scroll"); map(0x6800, 0x69ff).ram().w(this, FUNC(jackie_state::reel1_ram_w)).share("reel1_ram"); map(0x6a00, 0x6bff).ram().w(this, FUNC(jackie_state::reel2_ram_w)).share("reel2_ram"); map(0x6c00, 0x6dff).ram().w(this, FUNC(jackie_state::reel3_ram_w)).share("reel3_ram"); map(0x7000, 0x77ff).ram().w(this, FUNC(jackie_state::fg_tile_w)).share("fg_tile_ram"); map(0x7800, 0x7fff).ram().w(this, FUNC(jackie_state::fg_color_w)).share("fg_color_ram"); map(0x8000, 0xffff).r(this, FUNC(jackie_state::expram_r)); } CUSTOM_INPUT_MEMBER(jackie_state::hopper_r) { if (m_hopper) return !(m_screen->frame_number()%10); return machine().input().code_pressed(KEYCODE_H); } static INPUT_PORTS_START( jackie ) PORT_START("DSW1") PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SWA:8") PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPUNKNOWN( 0x02, 0x02 ) PORT_DIPUNKNOWN( 0x04, 0x04 ) PORT_DIPUNKNOWN( 0x08, 0x08 ) PORT_DIPUNKNOWN( 0x10, 0x10 ) PORT_DIPUNKNOWN( 0x20, 0x20 ) PORT_DIPUNKNOWN( 0x40, 0x40 ) PORT_DIPUNKNOWN( 0x80, 0x80 ) PORT_START("DSW2") PORT_DIPNAME( 0x0f, 0x07, "Main Game Chance" ) PORT_DIPLOCATION("SWB:8,7,6,5") PORT_DIPSETTING( 0x0f, "45%" ) PORT_DIPSETTING( 0x0e, "50%" ) PORT_DIPSETTING( 0x0d, "55%" ) PORT_DIPSETTING( 0x0c, "60%" ) PORT_DIPSETTING( 0x0b, "65%" ) PORT_DIPSETTING( 0x0a, "70%" ) PORT_DIPSETTING( 0x09, "75%" ) PORT_DIPSETTING( 0x08, "80%" ) PORT_DIPSETTING( 0x07, "83%" ) PORT_DIPSETTING( 0x06, "85%" ) PORT_DIPSETTING( 0x05, "88%" ) PORT_DIPSETTING( 0x04, "90%" ) PORT_DIPSETTING( 0x03, "92%" ) PORT_DIPSETTING( 0x02, "94%" ) PORT_DIPSETTING( 0x01, "96%" ) PORT_DIPSETTING( 0x00, "98%" ) PORT_DIPUNKNOWN( 0x10, 0x10 ) PORT_DIPNAME( 0x20, 0x00, "Double Up Rate" ) PORT_DIPLOCATION("SWB:3") PORT_DIPSETTING( 0x20, DEF_STR( Hard ) ) PORT_DIPSETTING( 0x00, DEF_STR( Easy ) ) PORT_DIPUNKNOWN( 0x40, 0x40 ) PORT_DIPUNKNOWN( 0x80, 0x80 ) PORT_START("DSW3") PORT_DIPUNKNOWN( 0x01, 0x01 ) PORT_DIPUNKNOWN( 0x02, 0x02 ) PORT_DIPUNKNOWN( 0x04, 0x04 ) PORT_DIPUNKNOWN( 0x08, 0x08 ) PORT_DIPUNKNOWN( 0x10, 0x10 ) PORT_DIPUNKNOWN( 0x20, 0x20 ) PORT_DIPNAME( 0xC0, 0x00, "Max Bet" ) PORT_DIPLOCATION("SWC:2,1") PORT_DIPSETTING( 0xC0, "1" ) PORT_DIPSETTING( 0x80, "8" ) PORT_DIPSETTING( 0x40, "16" ) PORT_DIPSETTING( 0x00, "32" ) PORT_START("DSW4") PORT_DIPUNKNOWN( 0x01, 0x01 ) PORT_DIPUNKNOWN( 0x02, 0x02 ) PORT_DIPUNKNOWN( 0x04, 0x04 ) PORT_DIPUNKNOWN( 0x08, 0x08 ) PORT_DIPUNKNOWN( 0x10, 0x10 ) PORT_DIPUNKNOWN( 0x20, 0x20 ) PORT_DIPUNKNOWN( 0x40, 0x40 ) PORT_DIPUNKNOWN( 0x80, 0x80 ) PORT_START("DSW5") PORT_DIPUNKNOWN( 0x01, 0x01 ) PORT_DIPUNKNOWN( 0x02, 0x02 ) PORT_DIPUNKNOWN( 0x04, 0x04 ) PORT_DIPUNKNOWN( 0x08, 0x08 ) PORT_DIPUNKNOWN( 0x10, 0x10 ) PORT_DIPUNKNOWN( 0x20, 0x20 ) PORT_DIPUNKNOWN( 0x40, 0x40 ) PORT_DIPUNKNOWN( 0x80, 0x80 ) PORT_START("SERVICE") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_9) PORT_NAME("Attendent") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(DEVICE_SELF,jackie_state,hopper_r, nullptr) PORT_NAME("HPSW") // hopper sensor PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_SERVICE_NO_TOGGLE( 0x20, IP_ACTIVE_LOW ) // test (press during boot) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_NAME("Statistics") PORT_START("COINS") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_NAME("Key In") PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_NAME("Clear") // pays out PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_T) PORT_NAME("Togglemode") // Used PORT_BIT( 0xC0, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_START("BUTTONS1") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_V) PORT_NAME("Stop") PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_START("BUTTONS2") // OK PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_D) PORT_NAME("Small / Right Hammer") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_A) PORT_NAME("Take/Left Hammer") PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_3) PORT_NAME("W-Up") PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_S) PORT_NAME("Big / Center Hammer") PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) INPUT_PORTS_END static const gfx_layout layout_8x8x6 = { 8, 8, RGN_FRAC(1, 3), 6, { RGN_FRAC(0,3)+8,RGN_FRAC(0,3)+0, RGN_FRAC(1,3)+8,RGN_FRAC(1,3)+0, RGN_FRAC(2,3)+8,RGN_FRAC(2,3)+0 }, { STEP8(0,1) }, { STEP8(0,2*8) }, 8*8*2 }; static const gfx_layout layout_8x32x6 = { 8, 32, RGN_FRAC(1, 3), 6, { RGN_FRAC(0,3)+8,RGN_FRAC(0,3)+0, RGN_FRAC(1,3)+8,RGN_FRAC(1,3)+0, RGN_FRAC(2,3)+8,RGN_FRAC(2,3)+0 }, { STEP8(0,1) }, { STEP32(0,2*8) }, 8*32*2 }; static GFXDECODE_START( gfx_jackie ) GFXDECODE_ENTRY( "gfx1", 0, layout_8x8x6, 0, 16 ) GFXDECODE_ENTRY( "gfx2", 0, layout_8x32x6, 0, 16 ) GFXDECODE_END void jackie_state::init_jackie() { uint8_t *rom = memregion("maincpu")->base(); for (int A = 0; A < 0xf000; A++) { rom[A] = rom[A] ^ 0x21; if (((A & 0x0080) == 0x0000) && ((A & 0x0008) == 0x0000)) rom[A] = rom[A] ^ 0x20; if ((A & 0x0282) == 0x0282) rom[A] ^= 0x01; if ((A & 0x0940) == 0x0940) rom[A] ^= 0x02; } memset(&rom[0xf000], 0, 0x1000); // Patch trap rom[0x7e86] = 0xc3; } TIMER_DEVICE_CALLBACK_MEMBER(jackie_state::irq) { int scanline = param; if((scanline % 32) != 0) return; if((scanline % 64) == 32 && m_irq_enable) m_maincpu->set_input_line(0, HOLD_LINE); else if ((scanline % 64) == 0 && m_nmi_enable) m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); } MACHINE_CONFIG_START(jackie_state::jackie) /* basic machine hardware */ MCFG_DEVICE_ADD("maincpu", Z80, XTAL(12'000'000) / 2) MCFG_DEVICE_PROGRAM_MAP(jackie_prg_map) MCFG_DEVICE_IO_MAP(jackie_io_map) MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", jackie_state, irq, "screen", 0, 1) MCFG_DEVICE_ADD("ppi1", I8255A, 0) // D8255AC MCFG_I8255_OUT_PORTA_CB(WRITE8(*this, jackie_state, nmi_and_coins_w)) MCFG_I8255_IN_PORTB_CB(IOPORT("SERVICE")) MCFG_I8255_IN_PORTC_CB(IOPORT("COINS")) MCFG_DEVICE_ADD("ppi2", I8255A, 0) // D8255AC MCFG_I8255_IN_PORTA_CB(IOPORT("BUTTONS1")) MCFG_I8255_OUT_PORTB_CB(WRITE8(*this, jackie_state, lamps_w)) /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(57) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) MCFG_SCREEN_SIZE(64*8, 32*8) MCFG_SCREEN_VISIBLE_AREA(0*8, 64*8-1, 0, 32*8-1) MCFG_SCREEN_UPDATE_DRIVER(jackie_state, screen_update) MCFG_SCREEN_PALETTE("palette") MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_jackie) MCFG_PALETTE_ADD("palette", 2048) MCFG_PALETTE_FORMAT(xBBBBBGGGGGRRRRR) /* sound hardware */ SPEAKER(config, "mono").front_center(); MCFG_DEVICE_ADD("ymsnd", YM2413, 3579545) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) MACHINE_CONFIG_END ROM_START( jackie ) ROM_REGION( 0x10000, "maincpu", 0 ) ROM_LOAD( "jackiev110.u23", 0x0000, 0x10000, CRC(1b78a619) SHA1(a6eb6b6e544efa55225f2e947483614afb6ece3b) ) ROM_REGION( 0x60000, "gfx1", 0 ) ROM_LOAD( "6.u6", 0x00000, 0x20000, CRC(d2ed60a9) SHA1(40e2280384aa5c9e72e87a3b9e673172ff695676) ) ROM_LOAD( "5.u5", 0x20000, 0x20000, CRC(dc01fe7c) SHA1(683834ce2f13a923c0467209b93fef693d9c3e38) ) ROM_LOAD( "4.u4", 0x40000, 0x20000, CRC(38a42dcd) SHA1(8cc08ff4143281d9022210d6577146d725df9044) ) ROM_REGION( 0x30000, "gfx2", 0 ) ROM_LOAD( "3.u3", 0x00000, 0x4000, CRC(c69e962b) SHA1(492427ad1ac959cdf22d23439e0eb5932b60ec88) ) ROM_LOAD( "2.u2", 0x10000, 0x4000, CRC(8900ffba) SHA1(065cf1810ec9738718e4c94613f726e85ba4314d) ) ROM_LOAD( "1.u1", 0x20000, 0x4000, CRC(071d20f0) SHA1(77c87486803dccaa63732ff959c223b1313820e3) ) ROM_REGION( 0x10000, "gfx3", 0 ) ROM_LOAD( "jackie7sv.u22", 0x0000, 0x10000, CRC(8b4eb6da) SHA1(480784917dfaf9a0343c1d56eb590b32bf5e94fd) ) ROM_REGION( 0x10000, "misc", 0 ) ROM_LOAD( "16l8.u31", 0x0000, 0x104, BAD_DUMP CRC(e9cd78fb) SHA1(557d3e7ef3b25c1338b24722cac91bca788c02b8) ) ROM_LOAD( "18cv8.u14", 0x0000, 0x155, BAD_DUMP CRC(996e8f59) SHA1(630d9b91f6e8eda781061e2a8ff6fb0fecaf034c) ) ROM_LOAD( "18cv8.u8", 0x0000, 0x155, BAD_DUMP CRC(996e8f59) SHA1(630d9b91f6e8eda781061e2a8ff6fb0fecaf034c) ) ROM_LOAD( "18cv8.u9", 0x0000, 0x155, BAD_DUMP CRC(996e8f59) SHA1(630d9b91f6e8eda781061e2a8ff6fb0fecaf034c) ) ROM_END GAME( 1993, jackie, 0, jackie, jackie, jackie_state, init_jackie, ROT0, "IGS", "Happy Jackie (v110U)", MACHINE_SUPPORTS_SAVE )