mirror of
https://github.com/holub/mame
synced 2025-06-05 20:33:45 +03:00
blockch: add paddle position read
This commit is contained in:
parent
cd6d4cbb78
commit
b3c21ce2e4
@ -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 )
|
||||
|
Loading…
Reference in New Issue
Block a user