// license:BSD-3-Clause // copyright-holders: Phil Stroffolino /* DJ Boy (c)1989 Kaneko Hardware has many similarities to Air Buster. Self Test has two parts: 1) color test : press button#3 to advance past color pattern 2) i/o and sound test: use buttons 1,2,3 to select and play sound/music - CPU0 manages sprites, which are also used to display text irq (0x10) - timing/watchdog irq (0x30) - processes sprites nmi: wakes up this CPU - CPU1 manages the protection device, coin counters, palette, and tilemap(s) nmi: resets this CPU irq: game update - CPU2 manages sound chips irq: update music nmi: handle sound command - The "BEAST" protection device has access to DIP switches and player inputs. It also counts coins and attempts to manage counters and lockouts much like "MERMAID" (hvyunit), but fails to update corresponding outputs due to a bug. PCB Layout ---------- BS |----------------------------------------------| | 6264 BS15 6116 | | BS-101 6116 | | BS-005 780C-2 | | BS-004 DSW1 DSW2 | | 6264 IO-JAMMA| | 16MHz PAL1|----------| | | 12MHz | BEAST | J| | |----------| A| | BS-003 * M| | 6116 BS-203 6295 YM2203 M| | BS-000 YM3014 A| | |-------| 6295 324 4558 | | BS-001 |KANEKO | 780C-2 324 | | |PANDORA| VOL JP| | BS-002 | | BS-100 PAL2 324 | | |-------| 6264 VOL CN1| | BS07 4464 4464 BS19 BS-200 LA4460 | | 4464 4464 PAL3 D780C-2 LA4460 | |----------------------------------------------| Notes: D780C-2 - Z80 CPU. Clock 6.000MHz [12/2] (for all 3 Z80 CPUs) BEAST - OKI MSM80C51F microcontroller with internal ROM. Clock 6.000MHz on pins 18 & 19 chip is stamped 'KANEKO Beast (C)Intel '80 (C)KANEKO 1988' YM2203 - Yamaha YM2203, clock 3.000MHz [12/4] 6295 - OKI M6295, clock 1.500MHz [12/8]. Sample rate (Hz) = 12000000 / 8 / 165 PANDORA - Custom Kaneko graphics generator chip stamped 'PX79C480FP-3 PANDORA-CHIP' (QFP160) 4464 - 64k x4 DRAM (DIP18) 6116 - 2k x8 SRAM (DIP24) 6264 - 8k x8 SRAM (DIP28) VSync - 57.5Hz HSync - 15.68kHz JP - 3 pin jumper to set mono/stereo sound output CN1 - 4 pin connector for speakers when jumper is set for stereo sound output PAL1 - PAL16L8 stamped 'BS-501' PAL2 - PAL16L8 stamped 'BS-502' PAL3 - PAL16L8 stamped 'BS-500' IO-JAMMA- Custom Kaneko ceramic I/O input resistor pack stamped 'I/O JAMMA MC-8282837' LA4460 - Sanyo 12W Power Amplifier (SIL10) * - Unpopulated DIP32 position ROMs - BS15.6Y 27C512 EPROM (DIP28) \ There is an alt. set of labels used for these ROMs with an 'S' BS07.1B 27C512 EPROM (DIP28) | added to the name (i.e. 'BS15S'), but the actual ROM contents is identical BS19.4B 27C1001 EPROM (DIP32) / to the regular set (both sets dumped / verified) BS-000.1H 4M mask ROM (DIP32) {sprite} BS-001.1F 4M mask ROM (DIP32) {sprite} BS-002.1D 4M mask ROM (DIP32) {sprite} BS-003.1K 4M mask ROM (DIP32) {sprite} BS-004.1S 4M mask ROM (DIP32) {tile} BS-005.1U 4M mask ROM (DIP32) {tile} BS-100.4D 1M mask ROM (DIP28) {Z80} BS-101.6W 1M mask ROM (DIP28) {Z80 data} BS-200.8C 1M mask ROM (DIP28) {Z80} BS-203.5J 2M mask ROM (DIP32) {OKI-M6295 samples} DIPs - SW1 |--------------------------------------------| | 1 2 3 4 5 6 7 8 | |--------------------------------------------| |SCREEN NORMAL OFF | | FLIP ON | |--------------------------------------------| |GAME NORMAL OFF | |MODE TEST ON | |--------------------------------------------| |COIN1 1C/1P OFF OFF | | 1C/2P ON OFF | | 2C/1P OFF ON | | 2C/3P ON ON | | | |COIN2 1C/1P OFF OFF| | 1C/2P ON OFF| | 2C/1P OFF ON | | 2C/3P ON ON | |--------------------------------------------| |SW1 & SW4 NOT USED ALWAYS OFF | |--------------------------------------------| SW2 |--------------------------------------------| | 1 2 3 4 5 6 7 8 | |--------------------------------------------| |DIFFICULTY | |NORMAL OFF OFF | |EASY ON OFF | |HARD OFF ON | |HARDEST ON ON | |--------------------------------------------| |BONUS | |10,30,50,70,90 OFF OFF | |10,20,30,40,50, | |60,70,80,90 ON OFF | |20,50 OFF ON | |NONE ON ON | |--------------------------------------------| |LIVES 5 OFF OFF | | 3 ON OFF | | 7 OFF ON | | 9 ON ON | |--------------------------------------------| |DEMO sound YES OFF | | NO ON | |--------------------------------------------| |SPEAKER STEREO OFF| |OUTPUT MONO ON| |--------------------------------------------| */ #include "emu.h" #include "kan_pand.h" #include "cpu/mcs51/i80c51.h" #include "cpu/z80/z80.h" #include "machine/gen_latch.h" #include "machine/timer.h" #include "sound/okim6295.h" #include "sound/ymopn.h" #include "emupal.h" #include "screen.h" #include "speaker.h" #include "tilemap.h" namespace { class djboy_state : public driver_device { public: djboy_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") , m_subcpu(*this, "subcpu") , m_soundcpu(*this, "soundcpu") , m_beast(*this, "beast") , m_pandora(*this, "pandora") , m_gfxdecode(*this, "gfxdecode") , m_palette(*this, "palette") , m_soundlatch(*this, "soundlatch") , m_sublatch(*this, "sublatch") , m_beastlatch(*this, "beastlatch") , m_videoram(*this, "videoram") , m_mainbank(*this, "main_bank%u", 0U) , m_subbank(*this, "sub_bank") , m_soundbank(*this, "sound_bank") , m_port_in(*this, "IN%u", 0) , m_port_dsw(*this, "DSW%u", 1) { } void djboy(machine_config &config); void init_djboy(); void init_djboyj(); protected: virtual void machine_start() override ATTR_COLD; virtual void machine_reset() override ATTR_COLD; virtual void video_start() override ATTR_COLD; private: //static constexpr unsigned PROT_OUTPUT_BUFFER_SIZE = 8; u8 beast_status_r(); void trigger_nmi_on_maincpu(u8 data); void maincpu_bankswitch_w(u8 data); void subcpu_bankswitch_w(u8 data); void coin_count_w(u8 data); void soundcpu_bankswitch_w(u8 data); u8 beast_p0_r(); void beast_p0_w(u8 data); u8 beast_p1_r(); void beast_p1_w(u8 data); u8 beast_p2_r(); void beast_p2_w(u8 data); u8 beast_p3_r(); void beast_p3_w(u8 data); void scrollx_w(u8 data); void scrolly_w(u8 data); void videoram_w(offs_t offset, u8 data); TILE_GET_INFO_MEMBER(get_bg_tile_info); u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void screen_vblank(int state); TIMER_DEVICE_CALLBACK_MEMBER(scanline); void maincpu_am(address_map &map) ATTR_COLD; void maincpu_port_am(address_map &map) ATTR_COLD; void subcpu_am(address_map &map) ATTR_COLD; void subcpu_port_am(address_map &map) ATTR_COLD; void soundcpu_am(address_map &map) ATTR_COLD; void soundcpu_port_am(address_map &map) ATTR_COLD; // devices required_device m_maincpu; required_device m_subcpu; required_device m_soundcpu; required_device m_beast; required_device m_pandora; required_device m_gfxdecode; required_device m_palette; required_device m_soundlatch; required_device m_sublatch; required_device m_beastlatch; // memory pointers required_shared_ptr m_videoram; // ROM banking required_memory_bank_array<2> m_mainbank; required_memory_bank m_subbank; required_memory_bank m_soundbank; required_ioport_array<3> m_port_in; required_ioport_array<2> m_port_dsw; u8 m_bankxor = 0; // video-related tilemap_t *m_background = nullptr; u8 m_videoreg = 0; u8 m_scrollx = 0; u8 m_scrolly = 0; // Kaneko BEAST state u8 m_beast_p[4]{}; }; void djboy_state::scrollx_w(u8 data) { m_scrollx = data; } void djboy_state::scrolly_w(u8 data) { m_scrolly = data; } TILE_GET_INFO_MEMBER(djboy_state::get_bg_tile_info) { u8 const attr = m_videoram[tile_index + 0x800]; u32 code = m_videoram[tile_index] + ((attr & 0xf) << 8); u32 const color = attr >> 4; if (BIT(color, 3)) code |= 0x1000; tileinfo.set(0, code, color, 0); // no flip } void djboy_state::videoram_w(offs_t offset, u8 data) { m_videoram[offset] = data; m_background->mark_tile_dirty(offset & 0x7ff); } void djboy_state::video_start() { m_background = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(djboy_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); } u32 djboy_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { int const scrollx = m_scrollx | ((m_videoreg & 0xc0) << 2); m_background->set_scrollx(0, scrollx - 0x391); int const scrolly = m_scrolly | ((m_videoreg & 0x20) << 3); m_background->set_scrolly(0, scrolly); m_background->draw(screen, bitmap, cliprect, 0, 0); m_pandora->update(bitmap, cliprect); return 0; } void djboy_state::screen_vblank(int state) { // rising edge if (state) { m_pandora->eof(); } } // KANEKO BEAST state u8 djboy_state::beast_status_r() { return (m_sublatch->pending_r() ? 0x0 : 0x4) | (m_beastlatch->pending_r() ? 0x8 : 0x0); } /******************************************************************************/ void djboy_state::trigger_nmi_on_maincpu(u8 data) { m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); } void djboy_state::maincpu_bankswitch_w(u8 data) { data ^= m_bankxor; m_mainbank[0]->set_entry(data); m_mainbank[1]->set_entry(0); // unsure if / how this area is banked } /******************************************************************************/ /** * xx------ msb scrollx * --x----- msb scrolly * ---x---- screen flip * ----xxxx bank */ void djboy_state::subcpu_bankswitch_w(u8 data) { m_videoreg = data; if ((data & 0xc) != 4) m_subbank->set_entry((data & 0xf)); } void djboy_state::coin_count_w(u8 data) { machine().bookkeeping().coin_counter_w(0, BIT(data, 0)); machine().bookkeeping().coin_counter_w(1, BIT(data, 1)); } /******************************************************************************/ void djboy_state::soundcpu_bankswitch_w(u8 data) { m_soundbank->set_entry(data); // shall we check data<0x07? } /******************************************************************************/ void djboy_state::maincpu_am(address_map &map) { map(0x0000, 0x7fff).rom(); map(0x8000, 0xafff).bankr(m_mainbank[1]); map(0xb000, 0xbfff).rw(m_pandora, FUNC(kaneko_pandora_device::spriteram_r), FUNC(kaneko_pandora_device::spriteram_w)); map(0xc000, 0xdfff).bankr(m_mainbank[0]); map(0xe000, 0xffff).ram().share("main_sub"); } void djboy_state::maincpu_port_am(address_map &map) { map.global_mask(0xff); map(0x00, 0x00).w(FUNC(djboy_state::maincpu_bankswitch_w)); } /******************************************************************************/ void djboy_state::subcpu_am(address_map &map) { map(0x0000, 0x7fff).rom(); map(0x8000, 0xbfff).bankr(m_subbank); map(0xc000, 0xcfff).ram().w(FUNC(djboy_state::videoram_w)).share(m_videoram); map(0xd000, 0xd3ff).ram().w(m_palette, FUNC(palette_device::write8)).share("palette"); map(0xd400, 0xd8ff).ram(); map(0xe000, 0xffff).ram().share("main_sub"); } void djboy_state::subcpu_port_am(address_map &map) { map.global_mask(0xff); map(0x00, 0x00).w(FUNC(djboy_state::subcpu_bankswitch_w)); map(0x02, 0x02).w(m_soundlatch, FUNC(generic_latch_8_device::write)); map(0x04, 0x04).r(m_sublatch, FUNC(generic_latch_8_device::read)).w(m_beastlatch, FUNC(generic_latch_8_device::write)); map(0x06, 0x06).w(FUNC(djboy_state::scrolly_w)); map(0x08, 0x08).w(FUNC(djboy_state::scrollx_w)); map(0x0a, 0x0a).w(FUNC(djboy_state::trigger_nmi_on_maincpu)); map(0x0c, 0x0c).r(FUNC(djboy_state::beast_status_r)); map(0x0e, 0x0e).w(FUNC(djboy_state::coin_count_w)); } /******************************************************************************/ void djboy_state::soundcpu_am(address_map &map) { map(0x0000, 0x7fff).rom(); map(0x8000, 0xbfff).bankr(m_soundbank); map(0xc000, 0xdfff).ram(); } void djboy_state::soundcpu_port_am(address_map &map) { map.global_mask(0xff); map(0x00, 0x00).w(FUNC(djboy_state::soundcpu_bankswitch_w)); map(0x02, 0x03).rw("ymsnd", FUNC(ym2203_device::read), FUNC(ym2203_device::write)); map(0x04, 0x04).r(m_soundlatch, FUNC(generic_latch_8_device::read)); map(0x06, 0x06).rw("oki_l", FUNC(okim6295_device::read), FUNC(okim6295_device::write)); map(0x07, 0x07).rw("oki_r", FUNC(okim6295_device::read), FUNC(okim6295_device::write)); } /******************************************************************************/ u8 djboy_state::beast_p0_r() { // ? return 0; } void djboy_state::beast_p0_w(u8 data) { if (!BIT(m_beast_p[0], 1) && BIT(data, 1)) { m_sublatch->write(m_beast_p[1]); } if (BIT(~data, 0)) m_beastlatch->acknowledge_w(); m_beast_p[0] = data; } u8 djboy_state::beast_p1_r() { if (BIT(~m_beast_p[0], 0)) return m_beastlatch->read(); else return 0; // ? } void djboy_state::beast_p1_w(u8 data) { m_beast_p[1] = data; } u8 djboy_state::beast_p2_r() { switch ((m_beast_p[0] >> 2) & 3) { case 0: return m_port_in[1]->read(); case 1: return m_port_in[2]->read(); case 2: return m_port_in[0]->read(); default: return 0xff; } } void djboy_state::beast_p2_w(u8 data) { m_beast_p[2] = data; } u8 djboy_state::beast_p3_r() { u8 dsw = 0; u8 const dsw1 = ~m_port_dsw[0]->read(); u8 const dsw2 = ~m_port_dsw[1]->read(); switch ((m_beast_p[0] >> 5) & 3) { case 0: dsw = (BIT(dsw2, 4) << 3) | (BIT(dsw2, 0) << 2) | (BIT(dsw1, 4) << 1) | BIT(dsw1, 0); break; case 1: dsw = (BIT(dsw2, 5) << 3) | (BIT(dsw2, 1) << 2) | (BIT(dsw1, 5) << 1) | BIT(dsw1, 1); break; case 2: dsw = (BIT(dsw2, 6) << 3) | (BIT(dsw2, 2) << 2) | (BIT(dsw1, 6) << 1) | BIT(dsw1, 2); break; case 3: dsw = (BIT(dsw2, 7) << 3) | (BIT(dsw2, 3) << 2) | (BIT(dsw1, 7) << 1) | BIT(dsw1, 3); break; } return (dsw << 4) | (m_beastlatch->pending_r() ? 0x0 : 0x4) | (m_sublatch->pending_r() ? 0x8 : 0x0); } void djboy_state::beast_p3_w(u8 data) { m_beast_p[3] = data; m_subcpu->set_input_line(INPUT_LINE_RESET, BIT(data, 1) ? CLEAR_LINE : ASSERT_LINE); } // Program / data maps are defined in the 8051 core /******************************************************************************/ static INPUT_PORTS_START( djboy ) PORT_START("IN0") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) // labeled "TEST" in self test PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_TILT ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_START("IN1") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) // punch PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) // kick PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) // jump PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_START("IN2") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_START("DSW1") PORT_DIPNAME( 0x01, 0x00, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:1") // Manual states "CAUTION !! .... Don't use ." PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x01, DEF_STR( On ) ) PORT_DIPNAME( 0x02, 0x00, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW1:2") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x02, DEF_STR( On ) ) PORT_SERVICE_DIPLOC( 0x04, IP_ACTIVE_HIGH, "SW1:3" ) // PORT_DIPNAME( 0x04, 0x00, DEF_STR( Service_Mode ) ) PORT_DIPLOCATION("SW1:3") // PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // PORT_DIPSETTING( 0x04, DEF_STR( On ) ) PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:4") PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x08, DEF_STR( On ) ) PORT_DIPNAME( 0x30, 0x00, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:5,6") PORT_DIPSETTING( 0x20, DEF_STR( 2C_1C ) ) PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) PORT_DIPSETTING( 0x30, DEF_STR( 2C_3C ) ) PORT_DIPSETTING( 0x10, DEF_STR( 1C_2C ) ) PORT_DIPNAME( 0xc0, 0x00, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:7,8") PORT_DIPSETTING( 0x80, DEF_STR( 2C_1C ) ) PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) PORT_DIPSETTING( 0xc0, DEF_STR( 2C_3C ) ) PORT_DIPSETTING( 0x40, DEF_STR( 1C_2C ) ) PORT_START("DSW2") PORT_DIPNAME( 0x03, 0x00, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW2:1,2") PORT_DIPSETTING( 0x01, DEF_STR( Easy ) ) PORT_DIPSETTING( 0x00, DEF_STR( Normal ) ) PORT_DIPSETTING( 0x02, DEF_STR( Hard ) ) PORT_DIPSETTING( 0x03, DEF_STR( Hardest ) ) PORT_DIPNAME( 0x0c, 0x00, "Bonus Levels (in thousands)" ) PORT_DIPLOCATION("SW2:3,4") PORT_DIPSETTING( 0x00, "10,30,50,70,90" ) PORT_DIPSETTING( 0x04, "10,20,30,40,50,60,70,80,90" ) PORT_DIPSETTING( 0x08, "20,50" ) PORT_DIPSETTING( 0x0c, DEF_STR( None ) ) PORT_DIPNAME( 0x30, 0x00, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW2:5,6") PORT_DIPSETTING( 0x10, "3" ) PORT_DIPSETTING( 0x00, "5" ) PORT_DIPSETTING( 0x20, "7" ) PORT_DIPSETTING( 0x30, "9" ) PORT_DIPNAME( 0x40, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:7") PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x80, 0x80, "Stereo Sound" ) PORT_DIPLOCATION("SW2:8") PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) INPUT_PORTS_END static GFXDECODE_START( gfx_djboy ) GFXDECODE_ENTRY( "bgtiles", 0, gfx_8x8x4_row_2x2_group_packed_msb, 0x000, 16 ) GFXDECODE_END static GFXDECODE_START( gfx_djboy_spr ) GFXDECODE_ENTRY( "sprites", 0, gfx_8x8x4_row_2x2_group_packed_msb, 0x100, 16 ) GFXDECODE_END /******************************************************************************/ // Main Z80 uses IM2 TIMER_DEVICE_CALLBACK_MEMBER(djboy_state::scanline) { int const scanline = param; if (scanline == 240) // vblank-out irq m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xfd); // Z80 // Pandora "sprite end dma" irq? TODO: timing is clearly off, attract mode relies on this if (scanline == 64) m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xff); // Z80 } void djboy_state::machine_start() { u8 *main = memregion("maincpu")->base(); u8 *sub = memregion("subcpu")->base(); u8 *sound = memregion("soundcpu")->base(); m_mainbank[0]->configure_entries(0, 32, &main[0x00000], 0x2000); m_subbank->configure_entries(0, 4, &sub[0x00000], 0x4000); // TODO: Mirrored? m_subbank->configure_entries(8, 8, &sub[0x10000], 0x4000); m_soundbank->configure_entries(0, 8, &sound[0x00000], 0x4000); m_mainbank[1]->configure_entry(0, &main[0x08000]); // unsure if / how this area is banked save_item(NAME(m_videoreg)); save_item(NAME(m_scrollx)); save_item(NAME(m_scrolly)); // Kaneko BEAST save_item(NAME(m_beast_p)); } void djboy_state::machine_reset() { m_videoreg = 0; m_scrollx = 0; m_scrolly = 0; } void djboy_state::djboy(machine_config &config) { Z80(config, m_maincpu, 12_MHz_XTAL / 2); // 6.000MHz, verified m_maincpu->set_addrmap(AS_PROGRAM, &djboy_state::maincpu_am); m_maincpu->set_addrmap(AS_IO, &djboy_state::maincpu_port_am); TIMER(config, "scantimer").configure_scanline(FUNC(djboy_state::scanline), "screen", 0, 1); Z80(config, m_subcpu, 12_MHz_XTAL / 2); // 6.000MHz, verified m_subcpu->set_addrmap(AS_PROGRAM, &djboy_state::subcpu_am); m_subcpu->set_addrmap(AS_IO, &djboy_state::subcpu_port_am); m_subcpu->set_vblank_int("screen", FUNC(djboy_state::irq0_line_hold)); Z80(config, m_soundcpu, 12_MHz_XTAL / 2); // 6.000MHz, verified m_soundcpu->set_addrmap(AS_PROGRAM, &djboy_state::soundcpu_am); m_soundcpu->set_addrmap(AS_IO, &djboy_state::soundcpu_port_am); I80C51(config, m_beast, 12_MHz_XTAL / 2); // 6.000MHz, verified m_beast->port_in_cb<0>().set(FUNC(djboy_state::beast_p0_r)); m_beast->port_out_cb<0>().set(FUNC(djboy_state::beast_p0_w)); m_beast->port_in_cb<1>().set(FUNC(djboy_state::beast_p1_r)); m_beast->port_out_cb<1>().set(FUNC(djboy_state::beast_p1_w)); m_beast->port_in_cb<2>().set(FUNC(djboy_state::beast_p2_r)); m_beast->port_out_cb<2>().set(FUNC(djboy_state::beast_p2_w)); m_beast->port_in_cb<3>().set(FUNC(djboy_state::beast_p3_r)); m_beast->port_out_cb<3>().set(FUNC(djboy_state::beast_p3_w)); config.set_maximum_quantum(attotime::from_hz(6000)); GENERIC_LATCH_8(config, m_sublatch); GENERIC_LATCH_8(config, m_beastlatch); m_beastlatch->data_pending_callback().set_inputline(m_beast, INPUT_LINE_IRQ0); m_beastlatch->set_separate_acknowledge(true); screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); screen.set_refresh_hz(57.5); screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); screen.set_size(256, 256); screen.set_visarea(0, 256-1, 16, 256-16-1); screen.set_screen_update(FUNC(djboy_state::screen_update)); screen.screen_vblank().set(FUNC(djboy_state::screen_vblank)); screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_djboy); PALETTE(config, m_palette).set_format(palette_device::xRGB_444, 0x200); m_palette->set_endianness(ENDIANNESS_BIG); KANEKO_PANDORA(config, m_pandora, 0, m_palette, gfx_djboy_spr); SPEAKER(config, "speaker", 2).front(); GENERIC_LATCH_8(config, m_soundlatch); m_soundlatch->data_pending_callback().set_inputline(m_soundcpu, INPUT_LINE_NMI); ym2203_device &ymsnd(YM2203(config, "ymsnd", 12_MHz_XTAL / 4)); // 3.000MHz, verified ymsnd.irq_handler().set_inputline(m_soundcpu, INPUT_LINE_IRQ0); ymsnd.add_route(ALL_OUTPUTS, "speaker", 0.40, 0); ymsnd.add_route(ALL_OUTPUTS, "speaker", 0.40, 1); okim6295_device &oki_l(OKIM6295(config, "oki_l", 12_MHz_XTAL / 8, okim6295_device::PIN7_LOW)); // 1.500MHz, verified oki_l.set_device_rom_tag("oki"); oki_l.add_route(ALL_OUTPUTS, "speaker", 0.50, 0); okim6295_device &oki_r(OKIM6295(config, "oki_r", 12_MHz_XTAL / 8, okim6295_device::PIN7_LOW)); // 1.500MHz, verified oki_r.set_device_rom_tag("oki"); oki_r.add_route(ALL_OUTPUTS, "speaker", 0.50, 1); } ROM_START( djboy ) ROM_REGION( 0x40000, "maincpu", 0 ) ROM_LOAD( "djboy.4b", 0x00000, 0x20000, CRC(354531ec) SHA1(4722376601ca2d8fb79622fef35ab5b5b084555d) ) // verified on 2 PCBs, neither PCB had a label on the ROM ROM_LOAD( "bs100.4d", 0x20000, 0x20000, CRC(081e8af8) SHA1(3589dab1cf31b109a40370b4db1f31785023e2ed) ) ROM_REGION( 0x30000, "subcpu", 0 ) ROM_LOAD( "djboy.5y", 0x00000, 0x10000, CRC(91eb189a) SHA1(a6a2662369cd6c851ae45a49654f6150fa8cf42e) ) // mask ROM without label ROM_LOAD( "bs101.6w", 0x10000, 0x20000, CRC(a7c85577) SHA1(8296b96d5f69f6c730b7ed77fa8c93496b33529c) ) ROM_REGION( 0x20000, "soundcpu", 0 ) ROM_LOAD( "bs200.8c", 0x00000, 0x20000, CRC(f6c19e51) SHA1(82193f71122df07cce0a7f057a87b89eb2d587a1) ) ROM_REGION( 0x1000, "beast", 0 ) // MSM80C51F microcontroller ROM_LOAD( "beast.9s", 0x00000, 0x1000, CRC(ebe0f5f3) SHA1(6081343c9b4510c4c16b71f6340266a1f76170ac) ) // Internal ROM image ROM_REGION( 0x200000, "sprites", 0 ) ROM_LOAD( "bs000.1h", 0x000000, 0x80000, CRC(be4bf805) SHA1(a73c564575fe89d26225ca8ec2d98b6ac319ac18) ) ROM_LOAD( "bs001.1f", 0x080000, 0x80000, CRC(fdf36e6b) SHA1(a8762458dfd5201304247c113ceb85e96e33d423) ) ROM_LOAD( "bs002.1d", 0x100000, 0x80000, CRC(c52fee7f) SHA1(bd33117f7a57899fd4ec0a77413107edd9c44629) ) ROM_LOAD( "bs003.1k", 0x180000, 0x80000, CRC(ed89acb4) SHA1(611af362606b73cd2cf501678b463db52dcf69c4) ) ROM_LOAD( "bs06.1b", 0x1f0000, 0x10000, CRC(22c8aa08) SHA1(5521c9d73b4ee82a2de1992d6edc7ef62788ad72) ) // replaces last 0x200 tiles - verified correct for the World set ROM_REGION( 0x100000, "bgtiles", 0 ) ROM_LOAD( "bs004.1s", 0x000000, 0x80000, CRC(2f1392c3) SHA1(1bc3030b3612766a02133eef0b4d20013c0495a4) ) ROM_LOAD( "bs005.1u", 0x080000, 0x80000, CRC(46b400c4) SHA1(35f4823364bbff1fc935994498d462bbd3bc6044) ) ROM_REGION( 0x40000, "oki", 0 ) ROM_LOAD( "bs203.5j", 0x000000, 0x40000, CRC(805341fb) SHA1(fb94e400e2283aaa806814d5a39d6196457dc822) ) ROM_END ROM_START( djboyu ) ROM_REGION( 0x40000, "maincpu", 0 ) ROM_LOAD( "bs64.4b", 0x00000, 0x20000, CRC(b77aacc7) SHA1(78100d4695738a702f13807526eb1bcac759cce3) ) ROM_LOAD( "bs100.4d", 0x20000, 0x20000, CRC(081e8af8) SHA1(3589dab1cf31b109a40370b4db1f31785023e2ed) ) ROM_REGION( 0x30000, "subcpu", 0 ) ROM_LOAD( "bs65.5y", 0x00000, 0x10000, CRC(0f1456eb) SHA1(62ed48c0d71c1fabbb3f6ada60381f57f692cef8) ) ROM_LOAD( "bs101.6w", 0x10000, 0x20000, CRC(a7c85577) SHA1(8296b96d5f69f6c730b7ed77fa8c93496b33529c) ) ROM_REGION( 0x20000, "soundcpu", 0 ) ROM_LOAD( "bs200.8c", 0x00000, 0x20000, CRC(f6c19e51) SHA1(82193f71122df07cce0a7f057a87b89eb2d587a1) ) ROM_REGION( 0x1000, "beast", 0 ) // MSM80C51F microcontroller ROM_LOAD( "beast.9s", 0x00000, 0x1000, CRC(ebe0f5f3) SHA1(6081343c9b4510c4c16b71f6340266a1f76170ac) ) // Internal ROM image ROM_REGION( 0x200000, "sprites", 0 ) ROM_LOAD( "bs000.1h", 0x000000, 0x80000, CRC(be4bf805) SHA1(a73c564575fe89d26225ca8ec2d98b6ac319ac18) ) ROM_LOAD( "bs001.1f", 0x080000, 0x80000, CRC(fdf36e6b) SHA1(a8762458dfd5201304247c113ceb85e96e33d423) ) ROM_LOAD( "bs002.1d", 0x100000, 0x80000, CRC(c52fee7f) SHA1(bd33117f7a57899fd4ec0a77413107edd9c44629) ) ROM_LOAD( "bs003.1k", 0x180000, 0x80000, CRC(ed89acb4) SHA1(611af362606b73cd2cf501678b463db52dcf69c4) ) ROM_LOAD( "bs07s.1b", 0x1f0000, 0x10000, CRC(d9b7a220) SHA1(ba3b528d50650c209c986268bb29b42ff1276eb2) ) // replaces last 0x200 tiles - found labeled as both BS07 and BS07S, same data - verified ROM_REGION( 0x100000, "bgtiles", 0 ) ROM_LOAD( "bs004.1s", 0x000000, 0x80000, CRC(2f1392c3) SHA1(1bc3030b3612766a02133eef0b4d20013c0495a4) ) ROM_LOAD( "bs005.1u", 0x080000, 0x80000, CRC(46b400c4) SHA1(35f4823364bbff1fc935994498d462bbd3bc6044) ) ROM_REGION( 0x40000, "oki", 0 ) ROM_LOAD( "bs203.5j", 0x000000, 0x40000, CRC(805341fb) SHA1(fb94e400e2283aaa806814d5a39d6196457dc822) ) ROM_END ROM_START( djboyua ) ROM_REGION( 0x40000, "maincpu", 0 ) ROM_LOAD( "bs19s.4b", 0x00000, 0x20000, CRC(17ce9f6c) SHA1(a0c1832b05dc46991e8949067ca0278f5498835f) ) // found labeled as both BS19 and BS19S, same data - verified ROM_LOAD( "bs100.4d", 0x20000, 0x20000, CRC(081e8af8) SHA1(3589dab1cf31b109a40370b4db1f31785023e2ed) ) ROM_REGION( 0x30000, "subcpu", 0 ) ROM_LOAD( "bs15s.5y", 0x00000, 0x10000, CRC(e6f966b2) SHA1(f9df16035a8b09d87eb70315b216892e25d99b03) ) // found labeled as both BS15 and BS15S, same data - verified ROM_LOAD( "bs101.6w", 0x10000, 0x20000, CRC(a7c85577) SHA1(8296b96d5f69f6c730b7ed77fa8c93496b33529c) ) ROM_REGION( 0x20000, "soundcpu", 0 ) ROM_LOAD( "bs200.8c", 0x00000, 0x20000, CRC(f6c19e51) SHA1(82193f71122df07cce0a7f057a87b89eb2d587a1) ) ROM_REGION( 0x1000, "beast", 0 ) // MSM80C51F microcontroller ROM_LOAD( "beast.9s", 0x00000, 0x1000, CRC(ebe0f5f3) SHA1(6081343c9b4510c4c16b71f6340266a1f76170ac) ) // Internal ROM image ROM_REGION( 0x200000, "sprites", 0 ) ROM_LOAD( "bs000.1h", 0x000000, 0x80000, CRC(be4bf805) SHA1(a73c564575fe89d26225ca8ec2d98b6ac319ac18) ) ROM_LOAD( "bs001.1f", 0x080000, 0x80000, CRC(fdf36e6b) SHA1(a8762458dfd5201304247c113ceb85e96e33d423) ) ROM_LOAD( "bs002.1d", 0x100000, 0x80000, CRC(c52fee7f) SHA1(bd33117f7a57899fd4ec0a77413107edd9c44629) ) ROM_LOAD( "bs003.1k", 0x180000, 0x80000, CRC(ed89acb4) SHA1(611af362606b73cd2cf501678b463db52dcf69c4) ) ROM_LOAD( "bs07s.1b", 0x1f0000, 0x10000, CRC(d9b7a220) SHA1(ba3b528d50650c209c986268bb29b42ff1276eb2) ) // replaces last 0x200 tiles - found labeled as both BS07 and BS07S, same data - verified ROM_REGION( 0x100000, "bgtiles", 0 ) ROM_LOAD( "bs004.1s", 0x000000, 0x80000, CRC(2f1392c3) SHA1(1bc3030b3612766a02133eef0b4d20013c0495a4) ) ROM_LOAD( "bs005.1u", 0x080000, 0x80000, CRC(46b400c4) SHA1(35f4823364bbff1fc935994498d462bbd3bc6044) ) ROM_REGION( 0x40000, "oki", 0 ) ROM_LOAD( "bs203.5j", 0x000000, 0x40000, CRC(805341fb) SHA1(fb94e400e2283aaa806814d5a39d6196457dc822) ) ROM_END ROM_START( djboyj ) ROM_REGION( 0x40000, "maincpu", 0 ) ROM_LOAD( "bs12.4b", 0x00000, 0x20000, CRC(0971523e) SHA1(f90cd02cedf8632f4b651de7ea75dc8c0e682f6e) ) ROM_LOAD( "bs100.4d", 0x20000, 0x20000, CRC(081e8af8) SHA1(3589dab1cf31b109a40370b4db1f31785023e2ed) ) ROM_REGION( 0x30000, "subcpu", 0 ) ROM_LOAD( "bs13.5y", 0x00000, 0x10000, CRC(5c3f2f96) SHA1(bb7ee028a2d8d3c76a78a29fba60bcc36e9399f5) ) ROM_LOAD( "bs101.6w", 0x10000, 0x20000, CRC(a7c85577) SHA1(8296b96d5f69f6c730b7ed77fa8c93496b33529c) ) ROM_REGION( 0x20000, "soundcpu", 0 ) ROM_LOAD( "bs200.8c", 0x00000, 0x20000, CRC(f6c19e51) SHA1(82193f71122df07cce0a7f057a87b89eb2d587a1) ) ROM_REGION( 0x1000, "beast", 0 ) // MSM80C51F microcontroller ROM_LOAD( "beast.9s", 0x00000, 0x1000, CRC(ebe0f5f3) SHA1(6081343c9b4510c4c16b71f6340266a1f76170ac) ) // Internal ROM image ROM_REGION( 0x200000, "sprites", 0 ) ROM_LOAD( "bs000.1h", 0x000000, 0x80000, CRC(be4bf805) SHA1(a73c564575fe89d26225ca8ec2d98b6ac319ac18) ) ROM_LOAD( "bs001.1f", 0x080000, 0x80000, CRC(fdf36e6b) SHA1(a8762458dfd5201304247c113ceb85e96e33d423) ) ROM_LOAD( "bs002.1d", 0x100000, 0x80000, CRC(c52fee7f) SHA1(bd33117f7a57899fd4ec0a77413107edd9c44629) ) ROM_LOAD( "bs003.1k", 0x180000, 0x80000, CRC(ed89acb4) SHA1(611af362606b73cd2cf501678b463db52dcf69c4) ) ROM_LOAD( "bs06.1b", 0x1f0000, 0x10000, CRC(22c8aa08) SHA1(5521c9d73b4ee82a2de1992d6edc7ef62788ad72) ) // replaces last 0x200 tiles ROM_REGION( 0x100000, "bgtiles", 0 ) ROM_LOAD( "bs004.1s", 0x000000, 0x80000, CRC(2f1392c3) SHA1(1bc3030b3612766a02133eef0b4d20013c0495a4) ) ROM_LOAD( "bs005.1u", 0x080000, 0x80000, CRC(46b400c4) SHA1(35f4823364bbff1fc935994498d462bbd3bc6044) ) ROM_REGION( 0x40000, "oki", 0 ) ROM_LOAD( "bs-204.5j", 0x000000, 0x40000, CRC(510244f0) SHA1(afb502d46d268ad9cd209ae1da72c50e4e785626) ) ROM_END ROM_START( djboyja ) ROM_REGION( 0x40000, "maincpu", 0 ) ROM_LOAD( "djboyja.4b", 0x00000, 0x20000, CRC(f7ac20ca) SHA1(1bf66bfaa6d98f4cff50bc4d15cebfb7f4b09ae5) ) // mask ROM without label ROM_LOAD( "bs100.4d", 0x20000, 0x20000, CRC(081e8af8) SHA1(3589dab1cf31b109a40370b4db1f31785023e2ed) ) ROM_REGION( 0x30000, "subcpu", 0 ) ROM_LOAD( "bs13.5y", 0x00000, 0x10000, CRC(5c3f2f96) SHA1(bb7ee028a2d8d3c76a78a29fba60bcc36e9399f5) ) ROM_LOAD( "bs101.6w", 0x10000, 0x20000, CRC(a7c85577) SHA1(8296b96d5f69f6c730b7ed77fa8c93496b33529c) ) ROM_REGION( 0x20000, "soundcpu", 0 ) ROM_LOAD( "bs200.8c", 0x00000, 0x20000, CRC(f6c19e51) SHA1(82193f71122df07cce0a7f057a87b89eb2d587a1) ) ROM_REGION( 0x1000, "beast", 0 ) // MSM80C51F microcontroller ROM_LOAD( "beast.9s", 0x00000, 0x1000, CRC(ebe0f5f3) SHA1(6081343c9b4510c4c16b71f6340266a1f76170ac) ) // Internal ROM image ROM_REGION( 0x200000, "sprites", 0 ) ROM_LOAD( "bs000.1h", 0x000000, 0x80000, CRC(be4bf805) SHA1(a73c564575fe89d26225ca8ec2d98b6ac319ac18) ) ROM_LOAD( "bs001.1f", 0x080000, 0x80000, CRC(fdf36e6b) SHA1(a8762458dfd5201304247c113ceb85e96e33d423) ) ROM_LOAD( "bs002.1d", 0x100000, 0x80000, CRC(c52fee7f) SHA1(bd33117f7a57899fd4ec0a77413107edd9c44629) ) ROM_LOAD( "bs003.1k", 0x180000, 0x80000, CRC(ed89acb4) SHA1(611af362606b73cd2cf501678b463db52dcf69c4) ) ROM_LOAD( "bs06.1b", 0x1f0000, 0x10000, CRC(22c8aa08) SHA1(5521c9d73b4ee82a2de1992d6edc7ef62788ad72) ) // replaces last 0x200 tiles ROM_REGION( 0x100000, "bgtiles", 0 ) ROM_LOAD( "bs004.1s", 0x000000, 0x80000, CRC(2f1392c3) SHA1(1bc3030b3612766a02133eef0b4d20013c0495a4) ) ROM_LOAD( "bs005.1u", 0x080000, 0x80000, CRC(46b400c4) SHA1(35f4823364bbff1fc935994498d462bbd3bc6044) ) ROM_REGION( 0x40000, "oki", 0 ) ROM_LOAD( "bs24_l.5j", 0x000000, 0x20000, CRC(b0e0a452) SHA1(ff2d7ea750d43b1a05c55ad01296866af9aea444) ) // same data as bs-204.5j but split in halves ROM_LOAD( "bs24_h.5l", 0x020000, 0x20000, CRC(d24988ad) SHA1(22c2b9823e5320cf4e659d3e3b54991617b1e6b1) ) ROM_END void djboy_state::init_djboy() { m_bankxor = 0x00; } void djboy_state::init_djboyj() { m_bankxor = 0x1f; } } // anonymous namespace // YEAR, NAME, PARENT, MACHINE, INPUT, STATE, INIT, MNTR, COMPANY, FULLNAME, FLAGS GAME( 1989, djboy, 0, djboy, djboy, djboy_state, init_djboy, ROT0, "Kaneko", "DJ Boy (World)", MACHINE_SUPPORTS_SAVE ) GAME( 1990, djboyu, djboy, djboy, djboy, djboy_state, init_djboy, ROT0, "Kaneko (American Sammy license)", "DJ Boy (US, set 1)", MACHINE_SUPPORTS_SAVE ) // Sammy & Williams logos in FG ROM GAME( 1990, djboyua, djboy, djboy, djboy, djboy_state, init_djboy, ROT0, "Kaneko (American Sammy license)", "DJ Boy (US, set 2)", MACHINE_SUPPORTS_SAVE ) // Sammy & Williams logos in FG ROM GAME( 1989, djboyj, djboy, djboy, djboy, djboy_state, init_djboyj, ROT0, "Kaneko (Sega license)", "DJ Boy (Japan, set 1)", MACHINE_SUPPORTS_SAVE ) // Sega logo in FG ROM GAME( 1989, djboyja, djboy, djboy, djboy, djboy_state, init_djboyj, ROT0, "Kaneko (Sega license)", "DJ Boy (Japan, set 2)", MACHINE_SUPPORTS_SAVE ) // Sega logo in FG ROM