summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/unichamp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/unichamp.cpp')
-rw-r--r--src/mame/drivers/unichamp.cpp295
1 files changed, 0 insertions, 295 deletions
diff --git a/src/mame/drivers/unichamp.cpp b/src/mame/drivers/unichamp.cpp
deleted file mode 100644
index 55579643f12..00000000000
--- a/src/mame/drivers/unichamp.cpp
+++ /dev/null
@@ -1,295 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:David Viens
-/************************************************************************
- * Unisonic Champion 2711 (late 1977 based on part dates)
- *
- * Driver from plgDavid (David Viens)
- *
- * Thanks to Sylvain De Chantal (Sly D.C.) for the 2 test units,
- * carts and FAQ: http://www.ccjvq.com/slydc/index/faq/2711
- *
- * Thanks to Paul Robson for the GIC font rom.
- * (http://worstconsole.blogspot.ca/2012/12/the-worstconsoleever.html)
- * Note a spare dead GIC has been given to Lord Nightmare and should be sent for decap!
- *
- * The Unisonc Champion is the only known GI "Gimini Mid-Range 8950 Programmable Game Set"
- * to ever reach the market, and only in limited quantities (aprox 500 units ever built)
- *
- * Architecture:
- * Master IC : AY-3-8800-1 Graphics Interface (A.K.A. GIC, 40 pin)
- * Slave IC : CP1610 CPU (40 pin, same as in the Intellivision)
- * EXEC ROM : 9501-01009 (40 pin) at 0x0800 (factory mapped)
- *
- * The GIC generates the CPU Clock, the video signals and the audio.
- * The CPU does NOT access the GIC directly.
- * One way CPU->GIC 'communication' takes place through 256 bytes of shared RAM
- * (using two 4x256 TMS4043NL-2 (2112-1) Static Rams at U3 and U4)
- *
- * In this design the GIC only allows the CPU to use the BUS (and shared RAM)
- * a fraction of the frame time. (4.33ms for each 16.69ms, or 26% of the time)
- * (the real ratio of clocks is 7752/29868 )
- *
- * Boot: When the GIC let go of !RESET_OUT the EXEC Rom pushes 0x800 onto
- * the bus for the CPU to fetch and place in R7 to start execution.
- * This first CPU slice only last 3ms, then the GIC sets the CPU's BUSRQ low,
- * stalling it for 12.36ms, then sets it high for 4.33ms etc...
- * 59.95 times a second - NTSC
- ************************************************************************/
-
-#include "emu.h"
-
-#include "cpu/cp1610/cp1610.h"
-#include "video/gic.h"
-
-#include "bus/generic/slot.h"
-#include "bus/generic/carts.h"
-
-#include "emupal.h"
-#include "screen.h"
-#include "softlist.h"
-#include "speaker.h"
-
-
-class unichamp_state : public driver_device
-{
-public:
- unichamp_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_gic(*this, "gic"),
- m_cart(*this, "cartslot"),
- m_ctrls(*this, "CTRLS")
- { }
-
- void unichamp(machine_config &config);
-
- void init_unichamp();
-
-protected:
- virtual void machine_start() override;
- virtual void machine_reset() override;
-
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
-private:
- required_device<cp1610_cpu_device> m_maincpu;
- required_device<gic_device> m_gic;
- required_device<generic_slot_device> m_cart;
-
- required_ioport m_ctrls;
-
- uint8_t m_ram[256];
-
- void unichamp_palette(palette_device &palette) const;
-
- DECLARE_READ8_MEMBER(bext_r);
-
- DECLARE_READ8_MEMBER(unichamp_gicram_r);
- DECLARE_WRITE8_MEMBER(unichamp_gicram_w);
-
- DECLARE_READ16_MEMBER(unichamp_trapl_r);
- DECLARE_WRITE16_MEMBER(unichamp_trapl_w);
-
- DECLARE_READ16_MEMBER(read_ff);
-
- uint32_t screen_update_unichamp(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
-
- void unichamp_mem(address_map &map);
-};
-
-void unichamp_state::unichamp_palette(palette_device &palette) const
-{
- /*
- palette.set_pen_color(GIC_BLACK, rgb_t(0x00, 0x00, 0x00));
- palette.set_pen_color(GIC_RED, rgb_t(0xae, 0x49, 0x41));//(from box shot)
- palette.set_pen_color(GIC_GREEN, rgb_t(0x62, 0x95, 0x88));//(from box shot)
- palette.set_pen_color(GIC_WHITE, rgb_t(0xff, 0xff, 0xff));
- */
-
- //using from intv.c instead as suggested by RB
- palette.set_pen_color(GIC_BLACK, rgb_t(0x00, 0x00, 0x00));
- palette.set_pen_color(GIC_RED, rgb_t(0xff, 0x3d, 0x10));
- //palette.set_pen_color(GIC_GREEN, rgb_t(0x38, 0x6b, 0x3f)); //intv's DARK GREEN
- palette.set_pen_color(GIC_GREEN, rgb_t(0x00, 0xa7, 0x56)); //intv's GREEN
- palette.set_pen_color(GIC_WHITE, rgb_t(0xff, 0xfc, 0xff));
-}
-
-
-void unichamp_state::unichamp_mem(address_map &map)
-{
- map.global_mask(0x1FFF); //B13/B14/B15 are grounded!
- map(0x0000, 0x00FF).rw(FUNC(unichamp_state::unichamp_gicram_r), FUNC(unichamp_state::unichamp_gicram_w)).umask16(0x00ff);
- map(0x0100, 0x07FF).rw(FUNC(unichamp_state::unichamp_trapl_r), FUNC(unichamp_state::unichamp_trapl_w));
- map(0x0800, 0x0FFF).rom().region("maincpu", 0); // Carts and EXE ROM, 10-bits wide
-}
-
-
-static INPUT_PORTS_START( unichamp )
- PORT_START( "CTRLS" )
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')// P1 YES (EBCA0)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N')// P1 NO (EBCA1)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A')// P2 YES (EBCA2)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S')// P2 NO (EBCA3)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
-INPUT_PORTS_END
-
-
-void unichamp_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- //TODO should we add an explicit Reset button in there just like the controller?
-}
-
-
-READ8_MEMBER(unichamp_state::bext_r)
-{
- //The BEXT instruction pushes a user-defined nibble out on the four EBCA pins (EBCA0 to EBCA3)
- //and reads the ECBI input pin for HIGH or LOW signal to know whether or not to branch
-
- //The unisonic control system couldnt be simpler in design.
- //Each of the two player controllers has three buttons:
- //one tying !RESET(GIC pin 21) to ground when closed - resetting the WHOLE system.
- //a YES button (connecting EBCA0 to EBCI for Player1 and EBC2 to EBCI for Player2)
- //a NO button (connecting EBCA1 to EBCI for Player1 and EBC3 to EBCI for Player2)
-
- //The CPU outputs a MASK of whatever it needs and checks the result.
- //EG: Any player can choose if one or two players are going to play the game for instance
-
- uint8_t port = ioport("CTRLS")->read() & 0x0F; ////only lower nibble
-
- //We need to return logical high or low on the EBCI pin
- return (port & offset)>0?1:0;
-}
-
-
-void unichamp_state::init_unichamp()
-{
-}
-
-READ16_MEMBER(unichamp_state::read_ff)
-{
- return 0xffff;
-}
-
-void unichamp_state::machine_start()
-{
- if (m_cart->exists()){
- //flip endians in more "this surely exists in MAME" way?
- //NOTE The unichamp roms have the same endianness as intv on disk and in memory
- uint8_t*ptr = m_cart->get_rom_base();
- size_t size = m_cart->get_rom_size();
- for(size_t i=0;i<size;i+=2){
- uint8_t TEMP = ptr[i];
- ptr[i] = ptr[i+1];
- ptr[i+1] = TEMP;
- }
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x1000, 0x17ff,
- read16s_delegate(*m_cart, FUNC(generic_slot_device::read16_rom)));
- } else
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x1000, 0x17ff,
- read16_delegate(*this, FUNC(unichamp_state::read_ff)));
-}
-
-/* Set Reset and INTR/INTRM Vector */
-void unichamp_state::machine_reset()
-{
- /*
- the intv driver did not explain this but from the CP1600 manual:
- When MSYNC* goes inactive (high), the bus control signals issue lAB,
- and the CPU inputs from the bus into the PC the starting address of the main program.
- Note that the initialization address can be defined by the user at any desired bus address or
- can be the default address resulting from the logical state of the non-driven bus
- */
-
- //The Unisonic EXEC ROM chip (9501-01009) is self mapped at 0x0800
- //The cart ROMS are self mapped to 0x1000
- //upon boot the EXEC ROM puts 0x0800 on the bus for the CPU to use as first INT vector
-
- m_maincpu->set_input_line_vector(CP1610_RESET, 0x0800); // CP1610
- m_maincpu->set_input_line_vector(CP1610_INT_INTRM, 0x0804); // CP1610 - not used anyway
- m_maincpu->set_input_line_vector(CP1610_INT_INTR, 0x0804); // CP1610 - not used anyway
-
- /* Set initial PC */
- m_maincpu->set_state_int(cp1610_cpu_device::CP1610_R7, 0x0800);
-
- memset(m_ram, 0, sizeof(m_ram));
-}
-
-uint32_t unichamp_state::screen_update_unichamp(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- return m_gic->screen_update(screen, bitmap, cliprect);
-}
-
-READ8_MEMBER( unichamp_state::unichamp_gicram_r )
-{
- return m_ram[offset];
-}
-
-WRITE8_MEMBER( unichamp_state::unichamp_gicram_w )
-{
- m_ram[offset] = data;
-}
-
-READ16_MEMBER( unichamp_state::unichamp_trapl_r )
-{
- logerror("trapl_r(%x)\n",offset);
- return (int)0;
-}
-
-WRITE16_MEMBER( unichamp_state::unichamp_trapl_w )
-{
- logerror("trapl_w(%x) = %x\n",offset,data);
-}
-
-void unichamp_state::unichamp(machine_config &config)
-{
- /* basic machine hardware */
-
- //The CPU is really clocked this way:
- //CP1610(config, m_maincpu, XTAL(3'579'545)/4);
- //But since it is only running 7752/29868 th's of the time...
- //TODO find a more accurate method? (the emulation will be the same though)
- CP1610(config, m_maincpu, (7752.0/29868.0)*XTAL(3'579'545)/4);
- m_maincpu->set_addrmap(AS_PROGRAM, &unichamp_state::unichamp_mem);
- m_maincpu->bext().set(FUNC(unichamp_state::bext_r));
-
- config.set_maximum_quantum(attotime::from_hz(60));
-
- /* video hardware */
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_raw(XTAL(3'579'545),
- gic_device::LINE_CLOCKS, gic_device::START_ACTIVE_SCAN, gic_device::END_ACTIVE_SCAN,
- gic_device::LINES, gic_device::START_Y, gic_device::START_Y + gic_device::SCREEN_HEIGHT);
- screen.set_screen_update(FUNC(unichamp_state::screen_update_unichamp));
- screen.set_palette("palette");
-
- PALETTE(config, "palette", FUNC(unichamp_state::unichamp_palette), 4);
-
- /* sound hardware */
- SPEAKER(config, "mono").front_center();
- GIC(config, m_gic, XTAL(3'579'545));
- m_gic->set_screen("screen");
- m_gic->ram_callback().set(FUNC(unichamp_state::unichamp_gicram_r));
- m_gic->add_route(ALL_OUTPUTS, "mono", 0.40);
-
- /* cartridge */
- GENERIC_CARTSLOT(config, m_cart, generic_linear_slot, "unichamp_cart", "bin,rom");
- SOFTWARE_LIST(config, "cart_list").set_original("unichamp");
-}
-
-ROM_START(unichamp)
- ROM_REGION(0x1000,"maincpu", ROMREGION_ERASEFF)
-
- ROM_LOAD16_WORD( "9501-01009.u2", 0, 0x1000, CRC(49a0bd8f) SHA1(f4d126d3462ad351da4b75d76c75942d5a6f27ef))
-
- //these below are for local tests. you can use them in softlist or -cart
- //ROM_LOAD16_WORD( "pac-02.bin", 0x1000<<1, 0x1000, CRC(fe3213be) SHA1(5b9c407fe86865f3454d4be824a7f2bf53478f73))
- //ROM_LOAD16_WORD( "pac-03.bin", 0x1000<<1, 0x1000, CRC(f81f04bd) SHA1(82e2a0fda1787d5835c457ee5745b0db0cebe079))
- //ROM_LOAD16_WORD( "pac-04.bin", 0x1000<<1, 0x1000, CRC(cac09841) SHA1(bc9db83f26ed0810938156db6b104b4576754225))
- //ROM_LOAD16_WORD( "pac-05.bin", 0x1000<<1, 0x1000, CRC(d54a6090) SHA1(e85593096f43dcf14b08fd2c9fda277008a8df8b))
-ROM_END
-
-
-CONS( 1977, unichamp, 0, 0, unichamp, unichamp, unichamp_state, init_unichamp, "Unisonic", "Champion 2711", 0/*MACHINE_IMPERFECT_GRAPHICS*/ )