// license: BSD-3-Clause // copyright-holders: Zsolt Vasvari, Dirk Best /*************************************************************************** Ambush © 1983 Tecfri PCB connector pinout +5V 1 A GND +5V 2 B GND +12V Coin Counter 3 C +12V Coin Counter 1P Button 1 4 D 1P Up 1P Button 2 5 E 1P Down 2P Button 1 6 F 1P Left 2P Button 2 7 G 1P Right 2P Start 8 H 2P Up 1P Start 9 I 2P Down Coin 2 10 J 2P Left Coin 1 11 K 2P Right Blue 12 L Counter Red 13 M Counter Green 14 N Counter Sync 15 O Speaker Right +12V 16 P Speaker Left Speaker- 17 Q +5V Video GND 18 R +5V The bootlegs are running on a kind of extended hardware. It has double the amount of work RAM, an updated graphics system to accommodate the bootlegged games and the AY8912s were changed to AY8910s. TODO: - Verify actual Z80 and AY891x clock speeds from PCB (XTAL confirmed) - VBlank IRQ ACK - Verify screen raw parameters - Identify the changes in the 'hacked' set and why they were made - Is 'b' really a second color PROM? - Figure out what the additional PROMs do (and dump the missing ones) - Unknown dkong3abl dip switch: Coinage related? ***************************************************************************/ #include "emu.h" #include "cpu/z80/z80.h" #include "machine/74259.h" #include "machine/watchdog.h" #include "sound/ay8910.h" #include "screen.h" #include "speaker.h" //************************************************************************** // TYPE DEFINITIONS //************************************************************************** class ambush_state : public driver_device { public: ambush_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_gfxdecode(*this, "gfxdecode"), m_outlatch(*this, "outlatch%u", 1), m_video_ram(*this, "video_ram"), m_sprite_ram(*this, "sprite_ram"), m_attribute_ram(*this, "attribute_ram"), m_scroll_ram(*this, "scroll_ram"), m_char_tilemap(nullptr), m_color_bank(0) { } DECLARE_PALETTE_INIT(ambush); DECLARE_PALETTE_INIT(mario); DECLARE_PALETTE_INIT(dkong3); uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_bootleg(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); TILE_GET_INFO_MEMBER(ambush_char_tile_info); TILE_GET_INFO_MEMBER(mariobl_char_tile_info); TILE_GET_INFO_MEMBER(dkong3abl_char_tile_info); DECLARE_WRITE_LINE_MEMBER(flip_screen_w); DECLARE_WRITE8_MEMBER(scroll_ram_w); DECLARE_WRITE_LINE_MEMBER(color_bank_1_w); DECLARE_WRITE_LINE_MEMBER(color_bank_2_w); DECLARE_MACHINE_START(ambush); DECLARE_MACHINE_START(mariobl); DECLARE_MACHINE_START(dkong3abl); DECLARE_WRITE_LINE_MEMBER(coin_counter_1_w); DECLARE_WRITE_LINE_MEMBER(coin_counter_2_w); DECLARE_WRITE8_MEMBER(output_latches_w); void mariobl(machine_config &config); void ambush(machine_config &config); void dkong3abl(machine_config &config); void bootleg_map(address_map &map); void main_map(address_map &map); void main_portmap(address_map &map); private: void register_save_states(); required_device m_gfxdecode; optional_device_array m_outlatch; required_shared_ptr m_video_ram; required_shared_ptr m_sprite_ram; required_shared_ptr m_attribute_ram; required_shared_ptr m_scroll_ram; tilemap_t *m_char_tilemap; uint8_t m_color_bank; }; //************************************************************************** // ADDRESS MAPS //************************************************************************** void ambush_state::main_map(address_map &map) { map(0x0000, 0x7fff).rom(); map(0x8000, 0x87ff).ram(); map(0xa000, 0xa000).r("watchdog", FUNC(watchdog_timer_device::reset_r)); map(0xc000, 0xc07f).ram(); map(0xc080, 0xc09f).ram().w(this, FUNC(ambush_state::scroll_ram_w)).share("scroll_ram"); // 1 byte for each column map(0xc0a0, 0xc0ff).ram(); map(0xc100, 0xc1ff).ram().share("attribute_ram"); // 1 line corresponds to 4 in the video ram map(0xc200, 0xc3ff).ram().share("sprite_ram"); map(0xc400, 0xc7ff).ram().share("video_ram"); map(0xc800, 0xc800).portr("sw1"); map(0xcc00, 0xcc07).w(this, FUNC(ambush_state::output_latches_w)); } void ambush_state::main_portmap(address_map &map) { map.global_mask(0xff); map(0x00, 0x00).rw("ay1", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)); map(0x01, 0x01).w("ay1", FUNC(ay8910_device::data_w)); map(0x80, 0x80).rw("ay2", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)); map(0x81, 0x81).w("ay2", FUNC(ay8910_device::data_w)); } void ambush_state::bootleg_map(address_map &map) { map(0x0000, 0x5fff).rom(); map(0x6000, 0x6fff).ram(); map(0x7000, 0x77ff).ram(); map(0x7000, 0x71ff).share("sprite_ram"); map(0x7200, 0x72ff).share("attribute_ram"); map(0x7380, 0x739f).share("scroll_ram"); // not used on bootlegs? map(0x7400, 0x77ff).share("video_ram"); map(0x8000, 0x9fff).rom(); map(0xa000, 0xa000).r("watchdog", FUNC(watchdog_timer_device::reset_r)); map(0xa100, 0xa100).portr("sw1"); map(0xa200, 0xa207).w("outlatch", FUNC(ls259_device::write_d0)); map(0xb000, 0xbfff).rom(); map(0xe000, 0xffff).rom(); } //************************************************************************** // INPUTS //************************************************************************** static INPUT_PORTS_START( ambush ) PORT_START("buttons") PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_COCKTAIL PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_COCKTAIL PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_START2) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_START1) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_COIN2) PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_COIN1) PORT_START("joystick") 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_JOYSTICK_UP) PORT_8WAY PORT_COCKTAIL PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_COCKTAIL PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_COCKTAIL PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_COCKTAIL PORT_START("sw1") PORT_DIPNAME(0x03, 0x00, DEF_STR( Lives )) PORT_DIPLOCATION("SW1:1,2") PORT_DIPSETTING( 0x00, "3") PORT_DIPSETTING( 0x01, "4") PORT_DIPSETTING( 0x02, "5") PORT_DIPSETTING( 0x03, "6") PORT_DIPNAME(0x1c, 0x00, DEF_STR( Coinage )) PORT_DIPLOCATION("SW1:3,4,5") PORT_DIPSETTING( 0x10, DEF_STR( 2C_1C )) PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C )) PORT_DIPSETTING( 0x14, DEF_STR( 2C_3C )) PORT_DIPSETTING( 0x04, DEF_STR( 1C_2C )) PORT_DIPSETTING( 0x18, DEF_STR( 2C_5C )) PORT_DIPSETTING( 0x08, DEF_STR( 1C_3C )) PORT_DIPSETTING( 0x0c, DEF_STR( 1C_4C )) PORT_DIPSETTING( 0x1c, "Service Mode/Free Play") PORT_DIPNAME(0x20, 0x00, DEF_STR( Difficulty )) PORT_DIPLOCATION("SW1:6") PORT_DIPSETTING( 0x00, DEF_STR( Easy )) PORT_DIPSETTING( 0x20, DEF_STR( Hard )) PORT_DIPNAME(0x40, 0x40, DEF_STR( Bonus_Life )) PORT_DIPLOCATION("SW1:7") PORT_DIPSETTING( 0x40, "80000") PORT_DIPSETTING( 0x00, "120000") PORT_DIPNAME(0x80, 0x80, DEF_STR( Cabinet )) PORT_DIPLOCATION("SW1:8") PORT_DIPSETTING( 0x80, DEF_STR( Upright )) PORT_DIPSETTING( 0x00, DEF_STR( Cocktail )) INPUT_PORTS_END static INPUT_PORTS_START( ambusht ) PORT_INCLUDE(ambush) PORT_MODIFY("sw1") PORT_DIPNAME(0x04, 0x04, DEF_STR( Allow_Continue )) PORT_DIPLOCATION("SW1:3") PORT_DIPSETTING( 0x00, DEF_STR( No )) PORT_DIPSETTING( 0x04, DEF_STR( Yes )) PORT_DIPNAME(0x08, 0x00, "Service Mode/Free Play") PORT_DIPLOCATION("SW1:4") PORT_DIPSETTING( 0x00, DEF_STR( Off )) PORT_DIPSETTING( 0x08, DEF_STR( On )) PORT_DIPNAME(0x10, 0x00, DEF_STR( Coinage )) PORT_DIPLOCATION("SW1:5") PORT_DIPSETTING( 0x00, "A 1 Coin/1 Credit B 1 Coin/2 Credits") PORT_DIPSETTING( 0x10, "A 2 Coins/3 Credits B 1 Coin/3 Credits") INPUT_PORTS_END static INPUT_PORTS_START( mariobl ) PORT_INCLUDE(ambush) PORT_MODIFY("buttons") PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_SERVICE) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) PORT_MODIFY("joystick") PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_PLAYER(1) PORT_2WAY PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(1) PORT_2WAY PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(2) PORT_2WAY PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_PLAYER(2) PORT_2WAY PORT_BIT(0x33, IP_ACTIVE_LOW, IPT_UNUSED) PORT_MODIFY("sw1") PORT_DIPNAME(0x1c, 0x00, DEF_STR( Coinage )) PORT_DIPLOCATION("SW1:3,4,5") PORT_DIPSETTING( 0x08, DEF_STR( 3C_1C )) PORT_DIPSETTING( 0x10, DEF_STR( 2C_1C )) PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C )) PORT_DIPSETTING( 0x18, DEF_STR( 1C_2C )) PORT_DIPSETTING( 0x04, DEF_STR( 1C_3C )) PORT_DIPSETTING( 0x0c, DEF_STR( 1C_4C )) PORT_DIPSETTING( 0x14, DEF_STR( 1C_5C )) PORT_DIPSETTING( 0x1c, DEF_STR( 1C_6C )) PORT_DIPNAME(0x20, 0x20, "2 Players Game") PORT_DIPLOCATION("SW1:6") PORT_DIPSETTING( 0x00, "1 Credit") PORT_DIPSETTING( 0x20, "2 Credits") PORT_DIPNAME(0xc0, 0x00, DEF_STR( Bonus_Life )) PORT_DIPLOCATION("SW1:7,8") PORT_DIPSETTING( 0x00, "20k 50k 30k+") PORT_DIPSETTING( 0x40, "30k 60k 30k+") PORT_DIPSETTING( 0x80, "40k 70k 30k+") PORT_DIPSETTING( 0xc0, DEF_STR( None )) INPUT_PORTS_END static INPUT_PORTS_START( dkong3abl ) PORT_INCLUDE(ambush) PORT_MO
#include "UnitTest++/Config.h"
#include "UnitTest++/UnitTestPP.h"

#include "UnitTest++/ReportAssert.h"
#include "UnitTest++/ReportAssertImpl.h"
#include "UnitTest++/AssertException.h"

#include "RecordingReporter.h"
#include <csetjmp>

using namespace UnitTest;

namespace {

TEST(CanSetAssertExpected)
{
	Detail::ExpectAssert(true);
	CHECK(Detail::AssertExpected());

	Detail::ExpectAssert(false);
	CHECK(!Detail::AssertExpected());
}

#ifndef UNITTEST_NO_EXCEPTIONS

TEST(ReportAssertThrowsAssertException)
{
    bool caught = false;

    try
    {
		TestResults testResults;
		TestDetails testDetails("", "", "", 0);
        Detail::ReportAssertEx(&testResults, &testDetails, "", "", 0);
    }
    catch(AssertException const&)
    {
        caught = true;
    }

    CHECK(true == caught);
}

TEST(ReportAssertClearsExpectAssertFlag)
{
	RecordingReporter reporter;
	TestResults testResults(&reporter);
	TestDetails testDetails("", "", "", 0);

	try
	{
		Detail::ExpectAssert(true);
		Detail::ReportAssertEx(&testResults, &testDetails, "", "", 0);
	}
	catch(AssertException const&)
	{
	}

	CHECK(Detail::AssertExpected() == false);
	CHECK_EQUAL(0, reporter.testFailedCount);
}

TEST(ReportAssertWritesFailureToResultsAndDetailsWhenAssertIsNotExpected)
{
    const int lineNumber = 12345;
    const char* description = "description";
    const char* filename = "filename";

	RecordingReporter reporter;
	TestResults testResults(&reporter);
	TestDetails testDetails("", "", "", 0);

    try
    {
        Detail::ReportAssertEx(&testResults, &testDetails, description, filename, lineNumber);
    }
    catch(AssertException const&)
    {
    }

	CHECK_EQUAL(description, reporter.lastFailedMessage);
	CHECK_EQUAL(filename, reporter.lastFailedFile);
	CHECK_EQUAL(lineNumber, reporter.lastFailedLine);
}

TEST(ReportAssertReportsNoErrorsWhenAssertIsExpected)
{
	Detail::ExpectAssert(true);

	RecordingReporter reporter;
	TestResults testResults(&reporter);
	TestDetails testDetails("", "", "", 0);

	try
	{
		Detail::ReportAssertEx(&testResults, &testDetails, "", "", 0);
	}
	catch(AssertException const&)
	{
	}

	CHECK_EQUAL(0, reporter.testFailedCount);
}

TEST(CheckAssertMacroSetsAssertExpectationToFalseAfterRunning)
{
	Detail::ExpectAssert(true);
	CHECK_ASSERT(ReportAssert("", "", 0));
	CHECK(!Detail::AssertExpected());
	Detail::ExpectAssert(false);
}

#else

TEST(SetAssertJumpTargetReturnsFalseWhenSettingJumpTarget)
{
	CHECK(UNITTEST_SET_ASSERT_JUMP_TARGET() == false);
}

TEST(JumpToAssertJumpTarget_JumpsToSetPoint_ReturnsTrue)
{
	const volatile bool taken = !!UNITTEST_SET_ASSERT_JUMP_TARGET();

	volatile bool set = false;
	if (taken == false)
	{
		UNITTEST_JUMP_TO_ASSERT_JUMP_TARGET();
		set = true;
	}

	CHECK(set == false);
}

#endif

}
AVE ) GAME( 1983, ambushh, ambush, ambush, ambusht, ambush_state, 0, ROT0, "Tecfri", "Ambush (hack?)", MACHINE_SUPPORTS_SAVE ) GAME( 1983, ambushj, ambush, ambush, ambush, ambush_state, 0, ROT0, "Tecfri (Nippon Amuse license)", "Ambush (Japan)", MACHINE_SUPPORTS_SAVE ) GAME( 1983, ambushv, ambush, ambush, ambush, ambush_state, 0, ROT0, "Tecfri (Volt Electronics license)", "Ambush (Volt Electronics)", MACHINE_SUPPORTS_SAVE ) GAME( 1983, mariobl, mario, mariobl, mariobl, ambush_state, 0, ROT180, "bootleg", "Mario Bros. (bootleg on Ambush Hardware)", MACHINE_SUPPORTS_SAVE ) GAME( 1983, dkong3abl, dkong3, dkong3abl, dkong3abl, ambush_state, 0, ROT90, "bootleg", "Donkey Kong 3 (bootleg on Ambush hardware)", MACHINE_SUPPORTS_SAVE )