summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/mame/sunelectronics/blockch.cpp188
1 files changed, 121 insertions, 67 deletions
diff --git a/src/mame/sunelectronics/blockch.cpp b/src/mame/sunelectronics/blockch.cpp
index 4e370781f43..5b473d8be32 100644
--- a/src/mame/sunelectronics/blockch.cpp
+++ b/src/mame/sunelectronics/blockch.cpp
@@ -18,14 +18,17 @@ TV Game 8080 hardware is pretty much the same, but on a completely different
cheaper looking PCB. It has 13 switches instead of 15.
TODO:
-- missing paddle position read (or maybe ball vs paddle collision detection)
-- interrupts are wrong, it looks like it expects IN.2 0x40 to be low for a while before the 2nd irq
-- is mirror(0x08) on the PPIs correct? it reads from 0x1c what may be paddle related too
+- Is blockch really Block Challenger, or an older game on the same hardware?
+ The flyer has more bricks, and has the score panel at the bottom. Although
+ the PCB was purchased as Sun Electronics Block Challenger.
+- paddle/ball sprite drawing is guessed
- video timing is wrong
-- identify remaining switches
- the flyer photo shows a green screen, assumed to be an overlay on a B&W CRT
+- identify remaining switches
+- cocktail mode
- sound emulation
-- verify tvgm8080 title, the only reference is from the instruction card which said: TV.GAME -8080-
+- verify tvgm8080 title, the only reference is from the instruction card which
+ said: TV.GAME -8080-
******************************************************************************/
@@ -33,6 +36,7 @@ TODO:
#include "cpu/i8085/i8085.h"
#include "machine/i8255.h"
+#include "machine/timer.h"
#include "screen.h"
@@ -53,39 +57,41 @@ public:
m_inputs(*this, "IN.%u", 0)
{ }
- // machine configs
void blockch(machine_config &config);
protected:
virtual void machine_start() override;
private:
- // devices/pointers
required_device<cpu_device> m_maincpu;
required_device_array<i8255_device, 2> m_ppi;
required_device<screen_device> m_screen;
required_shared_ptr<u8> m_vram;
- required_ioport_array<4> m_inputs;
+ required_ioport_array<5> m_inputs;
void main_map(address_map &map);
void io_map(address_map &map);
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- DECLARE_WRITE_LINE_MEMBER(vblank_irq);
+ TIMER_DEVICE_CALLBACK_MEMBER(scanline);
void ppi0_c_w(u8 data);
void ppi1_a_w(u8 data);
void ppi1_b_w(u8 data);
void ppi1_c_w(u8 data);
- int m_ball_x = 0;
- int m_ball_y = 0;
+ u8 m_sound = 0;
+ u8 m_ball_x = 0;
+ u8 m_ball_y = 0;
+ u8 m_vctrl = 0;
};
void blockch_state::machine_start()
{
+ save_item(NAME(m_sound));
save_item(NAME(m_ball_x));
save_item(NAME(m_ball_y));
+ save_item(NAME(m_vctrl));
}
@@ -96,6 +102,8 @@ void blockch_state::machine_start()
u32 blockch_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
+ bitmap.fill(0, cliprect);
+
// 96x64 background
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
@@ -108,7 +116,8 @@ u32 blockch_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, co
}
// draw ball sprite
- int bx = 0x200 - m_ball_x - 2;
+ int bx = (m_vctrl << 8 & 0x100) | m_ball_x;
+ bx = 0x200 - bx - 2;
int by = 0x100 - m_ball_y;
for (int y = by; y < (by + 4); y++)
@@ -117,13 +126,20 @@ u32 blockch_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, co
bitmap.pix(y, x) = rgb_t::white();
// draw paddle
- // TODO: preliminary
- int py = m_inputs[3]->read();
- int px[2] = { 186, 46 };
+ int num_p = (m_inputs[3]->read() & 1) ? 1 : 2;
+ int py = m_inputs[4]->read();
+ int px[2] = { 44, 184 };
+ int plen = (m_vctrl & 4) ? 16 : 32;
- for (int y = py; y < (py + 20); y++)
- for (int i = 0; i < 2; i++)
- for (int x = px[i]; x < (px[i] + 2); x++)
+ if (m_sound & 0x80)
+ {
+ py = 0;
+ plen = 256;
+ }
+
+ for (int y = py; y < (py + plen); y++)
+ for (int i = 0; i < num_p; i++)
+ for (int x = px[i]; x < (px[i] + 4); x++)
if (cliprect.contains(x, y))
bitmap.pix(y, x) = rgb_t::white();
@@ -136,14 +152,24 @@ u32 blockch_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, co
I/O
******************************************************************************/
-WRITE_LINE_MEMBER(blockch_state::vblank_irq)
+TIMER_DEVICE_CALLBACK_MEMBER(blockch_state::scanline)
{
- m_maincpu->set_input_line(0, HOLD_LINE);
+ int scanline = param;
+
+ // vblank irq
+ if (scanline == 248)
+ m_maincpu->set_input_line(0, HOLD_LINE);
+
+ // unknown irq
+ if (scanline == 32)
+ m_maincpu->set_input_line(0, HOLD_LINE);
}
void blockch_state::ppi0_c_w(u8 data)
{
- // sound?
+ // sound/lamps?
+ // d7 also appears to be for hiding the paddles
+ m_sound = data;
}
void blockch_state::ppi1_a_w(u8 data)
@@ -153,12 +179,16 @@ void blockch_state::ppi1_a_w(u8 data)
void blockch_state::ppi1_b_w(u8 data)
{
- m_ball_x = (m_ball_x & 0xf00) | data;
+ m_ball_x = data;
}
void blockch_state::ppi1_c_w(u8 data)
{
- m_ball_x = (m_ball_x & 0xff) | (data << 8 & 0xf00);
+ // d0: ball x hi
+ // d1: flip screen
+ // d2: shorter paddles
+ // d3: unused?
+ m_vctrl = data;
}
@@ -176,8 +206,10 @@ void blockch_state::main_map(address_map &map)
void blockch_state::io_map(address_map &map)
{
- map(0x10, 0x13).mirror(0x08).rw(m_ppi[0], FUNC(i8255_device::read), FUNC(i8255_device::write));
- map(0x14, 0x17).mirror(0x08).rw(m_ppi[1], FUNC(i8255_device::read), FUNC(i8255_device::write));
+ map(0x10, 0x13).rw(m_ppi[0], FUNC(i8255_device::read), FUNC(i8255_device::write));
+ map(0x14, 0x17).rw(m_ppi[1], FUNC(i8255_device::read), FUNC(i8255_device::write));
+ map(0x18, 0x18).portr("IN.4");
+ map(0x1c, 0x1c).portr("IN.3");
}
@@ -193,58 +225,79 @@ static INPUT_PORTS_START( blockch )
PORT_DIPSETTING( 0x01, "5" )
PORT_DIPSETTING( 0x02, "7" )
PORT_DIPSETTING( 0x03, "9")
- PORT_DIPNAME( 0x04, 0x00, "Unknown 0_04" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x04, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, "Unknown 0_04" )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x08, 0x08, DEF_STR( Coinage ) )
PORT_DIPSETTING( 0x08, DEF_STR( 1C_1C ) )
PORT_DIPSETTING( 0x00, DEF_STR( 1C_2C ) )
- PORT_DIPNAME( 0x10, 0x00, "Unknown 0_10" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x10, DEF_STR( On ) )
- PORT_DIPNAME( 0x20, 0x00, "Unknown 0_20" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x20, DEF_STR( On ) )
- PORT_DIPNAME( 0x40, 0x00, "Unknown 0_40" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x40, DEF_STR( On ) )
- PORT_DIPNAME( 0x80, 0x00, "Unknown 0_80" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x80, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, "Unknown 0_10" )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, "Unknown 0_20" )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, "Unknown 0_40" )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, "Unknown 0_80" )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_START("IN.1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 )
- PORT_DIPNAME( 0x10, 0x00, "Unknown 1_10" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x10, DEF_STR( On ) )
- PORT_DIPNAME( 0x20, 0x00, "Barriers" )
+ PORT_DIPNAME( 0x10, 0x10, "Unknown 1_10" )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, "Barriers" )
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
- PORT_DIPNAME( 0x40, 0x00, "Unknown 1_40" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x40, DEF_STR( On ) )
- PORT_DIPNAME( 0x80, 0x00, "Unknown 1_80" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x80, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, "Unknown 1_40" )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, "Unknown 1_80" )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_START("IN.2")
PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_DIPNAME( 0x10, 0x10, "Unknown 2_10" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x10, DEF_STR( On ) )
- PORT_DIPNAME( 0x20, 0x00, "Unknown 2_20" ) // collision related?
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x20, DEF_STR( On ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) ) // game won't boot
+ PORT_DIPNAME( 0x20, 0x00, "Unknown 2_20" )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) // paddle collision problem
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
- PORT_DIPNAME( 0x80, 0x00, "Unknown 2_80" )
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x80, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Cabinet ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Upright ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) )
PORT_START("IN.3")
- PORT_BIT( 0xff, 0x00, IPT_PADDLE ) PORT_SENSITIVITY(40) PORT_KEYDELTA(10) PORT_CENTERDELTA(0)
+ PORT_DIPNAME( 0x01, 0x01, "Paddles" )
+ PORT_DIPSETTING( 0x01, "1" )
+ PORT_DIPSETTING( 0x00, "2" )
+ PORT_BIT( 0x7e, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_DIPNAME( 0x80, 0x80, "Unknown 3_80" )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_START("IN.4")
+ PORT_BIT( 0xff, 0x00, IPT_PADDLE ) PORT_SENSITIVITY(40) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_MINMAX(0x00, 0xf0)
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( tvgm8080 )
+ PORT_INCLUDE( blockch )
+
+ PORT_MODIFY("IN.1")
+ PORT_DIPNAME( 0x40, 0x40, "Oil" )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_MODIFY("IN.3")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
@@ -255,11 +308,13 @@ INPUT_PORTS_END
void blockch_state::blockch(machine_config &config)
{
- /* basic machine hardware */
+ // basic machine hardware
I8080A(config, m_maincpu, 18_MHz_XTAL/9);
m_maincpu->set_addrmap(AS_PROGRAM, &blockch_state::main_map);
m_maincpu->set_addrmap(AS_IO, &blockch_state::io_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(blockch_state::scanline), "screen", 0, 1);
+
I8255(config, m_ppi[0]); // 0x92: A & B = input, C = output
m_ppi[0]->in_pa_callback().set_ioport("IN.0");
m_ppi[0]->in_pb_callback().set_ioport("IN.1");
@@ -271,18 +326,17 @@ void blockch_state::blockch(machine_config &config)
m_ppi[1]->out_pc_callback().set(FUNC(blockch_state::ppi1_c_w));
m_ppi[1]->in_pc_callback().set_ioport("IN.2");
- /* video hardware */
+ // video hardware
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(60);
m_screen->set_size(512, 256);
- m_screen->set_visarea(0, 384-1, 0, 256-1);
+ m_screen->set_visarea(4, 384-12-1, 4, 248-1);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500));
m_screen->set_screen_update(FUNC(blockch_state::screen_update));
- m_screen->screen_vblank().set(FUNC(blockch_state::vblank_irq));
config.set_default_layout(layout_blockch);
- /* sound hardware */
+ // sound hardware
// TODO: discrete?
}
@@ -316,6 +370,6 @@ ROM_END
Drivers
******************************************************************************/
-// YEAR NAME PARENT MACHINE INPUT CLASS INIT SCREEN COMPANY, FULLNAME, FLAGS
-GAME( 1978, blockch, 0, blockch, blockch, blockch_state, empty_init, ROT270, "Sun Electronics / Gifu Tokki", "G.T. Block Challenger", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_COCKTAIL )
-GAME( 1978, tvgm8080, blockch, blockch, blockch, blockch_state, empty_init, ROT270, "bootleg?", "TV Game 8080", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_COCKTAIL )
+// YEAR NAME PARENT MACHINE INPUT CLASS INIT SCREEN COMPANY, FULLNAME, FLAGS
+GAME( 1978, blockch, 0, blockch, blockch, blockch_state, empty_init, ROT270, "Sun Electronics / Gifu Tokki", "G.T. Block Challenger", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_COCKTAIL )
+GAME( 1978, tvgm8080, blockch, blockch, tvgm8080, blockch_state, empty_init, ROT270, "bootleg?", "TV Game 8080", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_COCKTAIL )