mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
atari/toobin.cpp, atari/triplhnt.cpp, atari/tunhunt.cpp. atari/videopin.cpp: consolidated drivers in single files
This commit is contained in:
parent
2f30101bbd
commit
ab56f7de85
@ -1,5 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Aaron Giles
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Atari Toobin' hardware
|
||||
@ -23,16 +24,330 @@
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "toobin.h"
|
||||
|
||||
#include "atarijsa.h"
|
||||
#include "atarimo.h"
|
||||
|
||||
#include "cpu/m68000/m68010.h"
|
||||
#include "machine/eeprompar.h"
|
||||
#include "machine/watchdog.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
|
||||
static constexpr XTAL MASTER_CLOCK = 32_MHz_XTAL;
|
||||
#include "tilemap.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class toobin_state : public driver_device
|
||||
{
|
||||
public:
|
||||
toobin_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_screen(*this, "screen"),
|
||||
m_jsa(*this, "jsa"),
|
||||
m_playfield_tilemap(*this, "playfield"),
|
||||
m_alpha_tilemap(*this, "alpha"),
|
||||
m_mob(*this, "mob"),
|
||||
m_palette(*this, "palette"),
|
||||
m_paletteram(*this, "paletteram"),
|
||||
m_interrupt_scan(*this, "interrupt_scan"),
|
||||
m_xscroll(*this, "xscroll"),
|
||||
m_yscroll(*this, "yscroll")
|
||||
{ }
|
||||
|
||||
void toobin(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<atari_jsa_i_device> m_jsa;
|
||||
required_device<tilemap_device> m_playfield_tilemap;
|
||||
required_device<tilemap_device> m_alpha_tilemap;
|
||||
required_device<atari_motion_objects_device> m_mob;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
required_shared_ptr<uint16_t> m_paletteram;
|
||||
required_shared_ptr<uint16_t> m_interrupt_scan;
|
||||
required_shared_ptr<uint16_t> m_xscroll;
|
||||
required_shared_ptr<uint16_t> m_yscroll;
|
||||
|
||||
double m_brightness = 0;
|
||||
bitmap_ind16 m_pfbitmap;
|
||||
|
||||
emu_timer *m_scanline_interrupt_timer = nullptr;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(scanline_interrupt);
|
||||
void scanline_int_ack_w(uint16_t data);
|
||||
|
||||
void interrupt_scan_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void paletteram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void intensity_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void xscroll_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void yscroll_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void slip_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_alpha_tile_info);
|
||||
TILE_GET_INFO_MEMBER(get_playfield_tile_info);
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void main_map(address_map &map);
|
||||
|
||||
static const atari_motion_objects_config s_mob_config;
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Tilemap callbacks
|
||||
*
|
||||
*************************************/
|
||||
|
||||
TILE_GET_INFO_MEMBER(toobin_state::get_alpha_tile_info)
|
||||
{
|
||||
uint16_t const data = m_alpha_tilemap->basemem_read(tile_index);
|
||||
int const code = data & 0x3ff;
|
||||
int const color = (data >> 12) & 0x0f;
|
||||
tileinfo.set(2, code, color, (data >> 10) & 1);
|
||||
}
|
||||
|
||||
|
||||
TILE_GET_INFO_MEMBER(toobin_state::get_playfield_tile_info)
|
||||
{
|
||||
uint32_t const data = m_playfield_tilemap->basemem_read(tile_index);
|
||||
int const code = data & 0x3fff;
|
||||
int const color = (data >> 16) & 0x0f;
|
||||
tileinfo.set(0, code, color, TILE_FLIPYX(data >> 14));
|
||||
tileinfo.category = (data >> 20) & 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Video system start
|
||||
*
|
||||
*************************************/
|
||||
|
||||
const atari_motion_objects_config toobin_state::s_mob_config =
|
||||
{
|
||||
1, // index to which gfx system
|
||||
1, // number of motion object banks
|
||||
1, // are the entries linked?
|
||||
0, // are the entries split?
|
||||
0, // render in reverse order?
|
||||
1, // render in swapped X/Y order?
|
||||
0, // does the neighbor bit affect the next object?
|
||||
1024, // pixels per SLIP entry (0 for no-slip)
|
||||
0, // pixel offset for SLIPs
|
||||
0, // maximum number of links to visit/scanline (0=all)
|
||||
|
||||
0x100, // base palette entry
|
||||
0x100, // maximum number of colors
|
||||
0, // transparent pen index
|
||||
|
||||
{{ 0,0,0x00ff,0 }}, // mask for the link
|
||||
{{ 0,0x3fff,0,0 }}, // mask for the code index
|
||||
{{ 0,0,0,0x000f }}, // mask for the color
|
||||
{{ 0,0,0,0xffc0 }}, // mask for the X position
|
||||
{{ 0x7fc0,0,0,0 }}, // mask for the Y position
|
||||
{{ 0x0007,0,0,0 }}, // mask for the width, in tiles
|
||||
{{ 0x0038,0,0,0 }}, // mask for the height, in tiles
|
||||
{{ 0,0x4000,0,0 }}, // mask for the horizontal flip
|
||||
{{ 0,0x8000,0,0 }}, // mask for the vertical flip
|
||||
{{ 0 }}, // mask for the priority
|
||||
{{ 0 }}, // mask for the neighbor
|
||||
{{ 0x8000,0,0,0 }}, // mask for absolute coordinates
|
||||
|
||||
{{ 0 }}, // mask for the special value
|
||||
0 // resulting value to indicate "special"
|
||||
};
|
||||
|
||||
void toobin_state::video_start()
|
||||
{
|
||||
// allocate a playfield bitmap for rendering
|
||||
m_screen->register_screen_bitmap(m_pfbitmap);
|
||||
|
||||
save_item(NAME(m_brightness));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Palette RAM write handler
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void toobin_state::paletteram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_paletteram[offset]);
|
||||
uint16_t newword = m_paletteram[offset];
|
||||
|
||||
{
|
||||
int red = (((newword >> 10) & 31) * 224) >> 5;
|
||||
int green = (((newword >> 5) & 31) * 224) >> 5;
|
||||
int blue = ((newword & 31) * 224) >> 5;
|
||||
|
||||
if (red) red += 38;
|
||||
if (green) green += 38;
|
||||
if (blue) blue += 38;
|
||||
|
||||
m_palette->set_pen_color(offset & 0x3ff, rgb_t(red, green, blue));
|
||||
if (!(newword & 0x8000))
|
||||
m_palette->set_pen_contrast(offset & 0x3ff, m_brightness);
|
||||
else
|
||||
m_palette->set_pen_contrast(offset & 0x3ff, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void toobin_state::intensity_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
m_brightness = (double)(~data & 0x1f) / 31.0;
|
||||
|
||||
for (int i = 0; i < 0x400; i++)
|
||||
if (!BIT(m_paletteram[i], 15))
|
||||
m_palette->set_pen_contrast(i, m_brightness);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* X/Y scroll handlers
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void toobin_state::xscroll_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t const oldscroll = *m_xscroll;
|
||||
uint16_t newscroll = oldscroll;
|
||||
COMBINE_DATA(&newscroll);
|
||||
|
||||
// if anything has changed, force a partial update
|
||||
if (newscroll != oldscroll)
|
||||
m_screen->update_partial(m_screen->vpos());
|
||||
|
||||
// update the playfield scrolling - hscroll is clocked on the following scanline
|
||||
m_playfield_tilemap->set_scrollx(0, newscroll >> 6);
|
||||
m_mob->set_xscroll(newscroll >> 6);
|
||||
|
||||
// update the data
|
||||
*m_xscroll = newscroll;
|
||||
}
|
||||
|
||||
|
||||
void toobin_state::yscroll_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t const oldscroll = *m_yscroll;
|
||||
uint16_t newscroll = oldscroll;
|
||||
COMBINE_DATA(&newscroll);
|
||||
|
||||
// if anything has changed, force a partial update
|
||||
if (newscroll != oldscroll)
|
||||
m_screen->update_partial(m_screen->vpos());
|
||||
|
||||
// if bit 4 is zero, the scroll value is clocked in right away
|
||||
m_playfield_tilemap->set_scrolly(0, newscroll >> 6);
|
||||
m_mob->set_yscroll((newscroll >> 6) & 0x1ff);
|
||||
|
||||
// update the data
|
||||
*m_yscroll = newscroll;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* X/Y scroll handlers
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void toobin_state::slip_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t const oldslip = m_mob->slipram(offset);
|
||||
uint16_t newslip = oldslip;
|
||||
COMBINE_DATA(&newslip);
|
||||
|
||||
// if the SLIP is changing, force a partial update first
|
||||
if (oldslip != newslip)
|
||||
m_screen->update_partial(m_screen->vpos());
|
||||
|
||||
// update the data
|
||||
m_mob->slipram(offset) = newslip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Main refresh
|
||||
*
|
||||
*************************************/
|
||||
|
||||
uint32_t toobin_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
// start drawing
|
||||
m_mob->draw_async(cliprect);
|
||||
|
||||
// draw the playfield
|
||||
bitmap_ind8 &priority_bitmap = screen.priority();
|
||||
priority_bitmap.fill(0, cliprect);
|
||||
m_playfield_tilemap->draw(screen, m_pfbitmap, cliprect, 0, 0);
|
||||
m_playfield_tilemap->draw(screen, m_pfbitmap, cliprect, 1, 1);
|
||||
m_playfield_tilemap->draw(screen, m_pfbitmap, cliprect, 2, 2);
|
||||
m_playfield_tilemap->draw(screen, m_pfbitmap, cliprect, 3, 3);
|
||||
|
||||
// draw and merge the MO
|
||||
bitmap_ind16 &mobitmap = m_mob->bitmap();
|
||||
pen_t const *const palette = m_palette->pens();
|
||||
for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
|
||||
{
|
||||
uint32_t *const dest = &bitmap.pix(y);
|
||||
uint16_t const *const mo = &mobitmap.pix(y);
|
||||
uint16_t const *const pf = &m_pfbitmap.pix(y);
|
||||
uint8_t const *const pri = &priority_bitmap.pix(y);
|
||||
for (int x = cliprect.left(); x <= cliprect.right(); x++)
|
||||
{
|
||||
uint16_t pix = pf[x];
|
||||
if (mo[x] != 0xffff)
|
||||
{
|
||||
/* not verified: logic is all controlled in a PAL
|
||||
|
||||
factors: LBPRI1-0, LBPIX3, ANPIX1-0, PFPIX3, PFPRI1-0,
|
||||
(~LBPIX3 & ~LBPIX2 & ~LBPIX1 & ~LBPIX0)
|
||||
*/
|
||||
|
||||
// only draw if not high priority PF
|
||||
if (!pri[x] || !(pix & 8))
|
||||
pix = mo[x];
|
||||
}
|
||||
dest[x] = palette[pix];
|
||||
}
|
||||
}
|
||||
|
||||
// add the alpha on top
|
||||
m_alpha_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
|
||||
/*************************************
|
||||
*
|
||||
@ -61,11 +376,11 @@ void toobin_state::machine_start()
|
||||
|
||||
void toobin_state::interrupt_scan_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
int oldword = m_interrupt_scan[offset];
|
||||
int const oldword = m_interrupt_scan[offset];
|
||||
int newword = oldword;
|
||||
COMBINE_DATA(&newword);
|
||||
|
||||
/* if something changed, update the word in memory */
|
||||
// if something changed, update the word in memory
|
||||
if (oldword != newword)
|
||||
{
|
||||
m_interrupt_scan[offset] = newword;
|
||||
@ -86,7 +401,7 @@ void toobin_state::scanline_int_ack_w(uint16_t data)
|
||||
*
|
||||
*************************************/
|
||||
|
||||
/* full address map decoded from schematics */
|
||||
// full address map decoded from schematics
|
||||
void toobin_state::main_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0xc7ffff);
|
||||
@ -94,18 +409,18 @@ void toobin_state::main_map(address_map &map)
|
||||
map(0xc00000, 0xc07fff).ram().w(m_playfield_tilemap, FUNC(tilemap_device::write16)).share("playfield");
|
||||
map(0xc08000, 0xc097ff).mirror(0x046000).ram().w(m_alpha_tilemap, FUNC(tilemap_device::write16)).share("alpha");
|
||||
map(0xc09800, 0xc09fff).mirror(0x046000).ram().share("mob");
|
||||
map(0xc10000, 0xc107ff).mirror(0x047800).ram().w(FUNC(toobin_state::paletteram_w)).share("paletteram");
|
||||
map(0x826000, 0x826001).mirror(0x4500fe).nopr(); /* who knows? read at controls time */
|
||||
map(0xc10000, 0xc107ff).mirror(0x047800).ram().w(FUNC(toobin_state::paletteram_w)).share(m_paletteram);
|
||||
map(0x826000, 0x826001).mirror(0x4500fe).nopr(); // who knows? read at controls time
|
||||
map(0x828000, 0x828001).mirror(0x4500fe).w("watchdog", FUNC(watchdog_timer_device::reset16_w));
|
||||
map(0x828101, 0x828101).mirror(0x4500fe).w(m_jsa, FUNC(atari_jsa_i_device::main_command_w));
|
||||
map(0x828300, 0x828301).mirror(0x45003e).w(FUNC(toobin_state::intensity_w));
|
||||
map(0x828340, 0x828341).mirror(0x45003e).w(FUNC(toobin_state::interrupt_scan_w)).share("interrupt_scan");
|
||||
map(0x828340, 0x828341).mirror(0x45003e).w(FUNC(toobin_state::interrupt_scan_w)).share(m_interrupt_scan);
|
||||
map(0x828380, 0x828381).mirror(0x45003e).ram().w(FUNC(toobin_state::slip_w)).share("mob:slip");
|
||||
map(0x8283c0, 0x8283c1).mirror(0x45003e).w(FUNC(toobin_state::scanline_int_ack_w));
|
||||
map(0x828400, 0x828401).mirror(0x4500fe).w(m_jsa, FUNC(atari_jsa_i_device::sound_reset_w));
|
||||
map(0x828500, 0x828501).mirror(0x4500fe).w("eeprom", FUNC(eeprom_parallel_28xx_device::unlock_write16));
|
||||
map(0x828600, 0x828601).mirror(0x4500fe).w(FUNC(toobin_state::xscroll_w)).share("xscroll");
|
||||
map(0x828700, 0x828701).mirror(0x4500fe).w(FUNC(toobin_state::yscroll_w)).share("yscroll");
|
||||
map(0x828600, 0x828601).mirror(0x4500fe).w(FUNC(toobin_state::xscroll_w)).share(m_xscroll);
|
||||
map(0x828700, 0x828701).mirror(0x4500fe).w(FUNC(toobin_state::yscroll_w)).share(m_yscroll);
|
||||
map(0x828800, 0x828801).mirror(0x4507fe).portr("FF8800");
|
||||
map(0x829000, 0x829001).mirror(0x4507fe).portr("FF9000");
|
||||
map(0x829801, 0x829801).mirror(0x4507fe).r(m_jsa, FUNC(atari_jsa_i_device::main_response_r));
|
||||
@ -205,8 +520,10 @@ GFXDECODE_END
|
||||
|
||||
void toobin_state::toobin(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
m68010_device &maincpu(M68010(config, m_maincpu, MASTER_CLOCK/4));
|
||||
static constexpr XTAL MASTER_CLOCK = 32_MHz_XTAL;
|
||||
|
||||
// basic machine hardware
|
||||
m68010_device &maincpu(M68010(config, m_maincpu, MASTER_CLOCK / 4));
|
||||
maincpu.set_addrmap(AS_PROGRAM, &toobin_state::main_map);
|
||||
maincpu.disable_interrupt_mixer();
|
||||
|
||||
@ -214,22 +531,22 @@ void toobin_state::toobin(machine_config &config)
|
||||
|
||||
WATCHDOG_TIMER(config, "watchdog").set_vblank_count(m_screen, 8);
|
||||
|
||||
/* video hardware */
|
||||
TILEMAP(config, m_playfield_tilemap, m_gfxdecode, 4, 8,8, TILEMAP_SCAN_ROWS, 128,64).set_info_callback(FUNC(toobin_state::get_playfield_tile_info));
|
||||
TILEMAP(config, m_alpha_tilemap, m_gfxdecode, 2, 8,8, TILEMAP_SCAN_ROWS, 64,48, 0).set_info_callback(FUNC(toobin_state::get_alpha_tile_info));
|
||||
// video hardware
|
||||
TILEMAP(config, m_playfield_tilemap, m_gfxdecode, 4, 8, 8, TILEMAP_SCAN_ROWS, 128, 64).set_info_callback(FUNC(toobin_state::get_playfield_tile_info));
|
||||
TILEMAP(config, m_alpha_tilemap, m_gfxdecode, 2, 8, 8, TILEMAP_SCAN_ROWS, 64, 48, 0).set_info_callback(FUNC(toobin_state::get_alpha_tile_info));
|
||||
|
||||
ATARI_MOTION_OBJECTS(config, m_mob, 0, m_screen, toobin_state::s_mob_config);
|
||||
m_mob->set_gfxdecode(m_gfxdecode);
|
||||
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||
m_screen->set_video_attributes(VIDEO_UPDATE_BEFORE_VBLANK);
|
||||
m_screen->set_raw(MASTER_CLOCK/2, 640, 0, 512, 416, 0, 384);
|
||||
m_screen->set_raw(MASTER_CLOCK / 2, 640, 0, 512, 416, 0, 384);
|
||||
m_screen->set_screen_update(FUNC(toobin_state::screen_update));
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, m_palette, gfx_toobin);
|
||||
PALETTE(config, m_palette).set_entries(1024);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
|
||||
@ -250,7 +567,7 @@ void toobin_state::toobin(machine_config &config)
|
||||
*************************************/
|
||||
|
||||
ROM_START( toobin )
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) /* 8*64k for 68000 code */
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) // 68000 code
|
||||
ROM_LOAD16_BYTE( "3133-1j.061", 0x000000, 0x010000, CRC(79a92d02) SHA1(72eebb96a3963f94558bb204e0afe08f2b4c1864) )
|
||||
ROM_LOAD16_BYTE( "3137-1f.061", 0x000001, 0x010000, CRC(e389ef60) SHA1(24861fe5eb49de852987993a905fefe4dd43b204) )
|
||||
ROM_LOAD16_BYTE( "3134-2j.061", 0x020000, 0x010000, CRC(3dbe9a48) SHA1(37fe2534fed5708a63995e53ea0cb1d2d23fc1b9) )
|
||||
@ -260,7 +577,7 @@ ROM_START( toobin )
|
||||
ROM_LOAD16_BYTE( "1136-5j.061", 0x060000, 0x010000, CRC(5ae3eeac) SHA1(583b6c3f61e8ad4d98449205fedecf3e21ee993c) )
|
||||
ROM_LOAD16_BYTE( "1140-5f.061", 0x060001, 0x010000, CRC(dacbbd94) SHA1(0e3a93f439ff9f3dd57ee13604be02e9c74c8eec) )
|
||||
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) /* 64k for 6502 code */
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) // 6502 code
|
||||
ROM_LOAD( "1141-2k.061", 0x00000, 0x10000, CRC(c0dcce1a) SHA1(285c13f08020cf5827eca2afcc2fa8a3a0a073e0) )
|
||||
|
||||
ROM_REGION( 0x080000, "gfx1", 0 )
|
||||
@ -305,7 +622,7 @@ ROM_END
|
||||
|
||||
|
||||
ROM_START( toobine )
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) /* 8*64k for 68000 code */
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) // 68000 code
|
||||
ROM_LOAD16_BYTE( "3733-1j.061", 0x000000, 0x010000, CRC(286c7fad) SHA1(1f06168327bdc356f1bc4cf9a951f914932c491a) )
|
||||
ROM_LOAD16_BYTE( "3737-1f.061", 0x000001, 0x010000, CRC(965c161d) SHA1(30d959a945cb7dc7f00ad4ca9db027a377024030) )
|
||||
ROM_LOAD16_BYTE( "3134-2j.061", 0x020000, 0x010000, CRC(3dbe9a48) SHA1(37fe2534fed5708a63995e53ea0cb1d2d23fc1b9) )
|
||||
@ -315,7 +632,7 @@ ROM_START( toobine )
|
||||
ROM_LOAD16_BYTE( "1136-5j.061", 0x060000, 0x010000, CRC(5ae3eeac) SHA1(583b6c3f61e8ad4d98449205fedecf3e21ee993c) )
|
||||
ROM_LOAD16_BYTE( "1140-5f.061", 0x060001, 0x010000, CRC(dacbbd94) SHA1(0e3a93f439ff9f3dd57ee13604be02e9c74c8eec) )
|
||||
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) /* 64k for 6502 code */
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) // 6502 code
|
||||
ROM_LOAD( "1141-2k.061", 0x00000, 0x10000, CRC(c0dcce1a) SHA1(285c13f08020cf5827eca2afcc2fa8a3a0a073e0) )
|
||||
|
||||
ROM_REGION( 0x080000, "gfx1", 0 )
|
||||
@ -360,7 +677,7 @@ ROM_END
|
||||
|
||||
|
||||
ROM_START( toobing )
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) /* 8*64k for 68000 code */
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) // 68000 code
|
||||
ROM_LOAD16_BYTE( "3233-1j.061", 0x000000, 0x010000, CRC(b04eb760) SHA1(760525b4f72fad47cfc457e14db70ade30a9ddac) )
|
||||
ROM_LOAD16_BYTE( "3237-1f.061", 0x000001, 0x010000, CRC(4e41a470) SHA1(3a4c9b0d93cf4cff80978c0568bb9ef9eeb878dd) )
|
||||
ROM_LOAD16_BYTE( "3234-2j.061", 0x020000, 0x010000, CRC(8c60f1b4) SHA1(0ff3f4fede83410d73027b6e7445e83044e4b21e) )
|
||||
@ -370,7 +687,7 @@ ROM_START( toobing )
|
||||
ROM_LOAD16_BYTE( "1136-5j.061", 0x060000, 0x010000, CRC(5ae3eeac) SHA1(583b6c3f61e8ad4d98449205fedecf3e21ee993c) )
|
||||
ROM_LOAD16_BYTE( "1140-5f.061", 0x060001, 0x010000, CRC(dacbbd94) SHA1(0e3a93f439ff9f3dd57ee13604be02e9c74c8eec) )
|
||||
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) /* 64k for 6502 code */
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) // 6502 code
|
||||
ROM_LOAD( "1141-2k.061", 0x00000, 0x10000, CRC(c0dcce1a) SHA1(285c13f08020cf5827eca2afcc2fa8a3a0a073e0) )
|
||||
|
||||
ROM_REGION( 0x080000, "gfx1", 0 )
|
||||
@ -415,7 +732,7 @@ ROM_END
|
||||
|
||||
|
||||
ROM_START( toobin2e )
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) /* 8*64k for 68000 code */
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) // 68000 code
|
||||
ROM_LOAD16_BYTE( "2733-1j.061", 0x000000, 0x010000, CRC(a6334cf7) SHA1(39e540619c24af65bda44160a5bdaebf3600b64b) )
|
||||
ROM_LOAD16_BYTE( "2737-1f.061", 0x000001, 0x010000, CRC(9a52dd20) SHA1(a370ae3e4c7af55ea61b57a203a900f2be3ce6b9) )
|
||||
ROM_LOAD16_BYTE( "2134-2j.061", 0x020000, 0x010000, CRC(2b8164c8) SHA1(aeeaff9df9fda23b295b59efadf52160f084d256) )
|
||||
@ -425,7 +742,7 @@ ROM_START( toobin2e )
|
||||
ROM_LOAD16_BYTE( "1136-5j.061", 0x060000, 0x010000, CRC(5ae3eeac) SHA1(583b6c3f61e8ad4d98449205fedecf3e21ee993c) )
|
||||
ROM_LOAD16_BYTE( "1140-5f.061", 0x060001, 0x010000, CRC(dacbbd94) SHA1(0e3a93f439ff9f3dd57ee13604be02e9c74c8eec) )
|
||||
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) /* 64k for 6502 code */
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) // 6502 code
|
||||
ROM_LOAD( "1141-2k.061", 0x00000, 0x10000, CRC(c0dcce1a) SHA1(285c13f08020cf5827eca2afcc2fa8a3a0a073e0) )
|
||||
|
||||
ROM_REGION( 0x080000, "gfx1", 0 )
|
||||
@ -470,7 +787,7 @@ ROM_END
|
||||
|
||||
|
||||
ROM_START( toobin2 )
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) /* 8*64k for 68000 code */
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) // 68000 code
|
||||
ROM_LOAD16_BYTE( "2133-1j.061", 0x000000, 0x010000, CRC(2c3382e4) SHA1(39919e9b5b586b630e0581adabfe25d83b2bfaef) )
|
||||
ROM_LOAD16_BYTE( "2137-1f.061", 0x000001, 0x010000, CRC(891c74b1) SHA1(2f39d0e4934ccf48bb5fc0737f34fc5a65cfd903) )
|
||||
ROM_LOAD16_BYTE( "2134-2j.061", 0x020000, 0x010000, CRC(2b8164c8) SHA1(aeeaff9df9fda23b295b59efadf52160f084d256) )
|
||||
@ -480,7 +797,7 @@ ROM_START( toobin2 )
|
||||
ROM_LOAD16_BYTE( "1136-5j.061", 0x060000, 0x010000, CRC(5ae3eeac) SHA1(583b6c3f61e8ad4d98449205fedecf3e21ee993c) )
|
||||
ROM_LOAD16_BYTE( "1140-5f.061", 0x060001, 0x010000, CRC(dacbbd94) SHA1(0e3a93f439ff9f3dd57ee13604be02e9c74c8eec) )
|
||||
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) /* 64k for 6502 code */
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) // 6502 code
|
||||
ROM_LOAD( "1141-2k.061", 0x00000, 0x10000, CRC(c0dcce1a) SHA1(285c13f08020cf5827eca2afcc2fa8a3a0a073e0) )
|
||||
|
||||
ROM_REGION( 0x080000, "gfx1", 0 )
|
||||
@ -525,7 +842,7 @@ ROM_END
|
||||
|
||||
|
||||
ROM_START( toobin1 )
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) /* 8*64k for 68000 code */
|
||||
ROM_REGION( 0x80000, "maincpu", 0 ) // 68000 code
|
||||
ROM_LOAD16_BYTE( "1133-1j.061", 0x000000, 0x010000, CRC(caeb5d1b) SHA1(8036871a04b5206fd383ac0fd9a9d3218128088b) )
|
||||
ROM_LOAD16_BYTE( "1137-1f.061", 0x000001, 0x010000, CRC(9713d9d3) SHA1(55791150312de201bdd330bfd4cbb132cb3959e4) )
|
||||
ROM_LOAD16_BYTE( "1134-2j.061", 0x020000, 0x010000, CRC(119f5d7b) SHA1(edd0b1ab29bb9c15c3b80037635c3b6d5fb434dc) )
|
||||
@ -535,7 +852,7 @@ ROM_START( toobin1 )
|
||||
ROM_LOAD16_BYTE( "1136-5j.061", 0x060000, 0x010000, CRC(5ae3eeac) SHA1(583b6c3f61e8ad4d98449205fedecf3e21ee993c) )
|
||||
ROM_LOAD16_BYTE( "1140-5f.061", 0x060001, 0x010000, CRC(dacbbd94) SHA1(0e3a93f439ff9f3dd57ee13604be02e9c74c8eec) )
|
||||
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) /* 64k for 6502 code */
|
||||
ROM_REGION( 0x10000, "jsa:cpu", 0 ) // 6502 code
|
||||
ROM_LOAD( "1141-2k.061", 0x00000, 0x10000, CRC(c0dcce1a) SHA1(285c13f08020cf5827eca2afcc2fa8a3a0a073e0) )
|
||||
|
||||
ROM_REGION( 0x080000, "gfx1", 0 )
|
||||
@ -578,6 +895,8 @@ ROM_START( toobin1 )
|
||||
ROM_LOAD( "1142-20h.061", 0x000000, 0x004000, CRC(a6ab551f) SHA1(6a11e16f3965416c81737efcb81e751484ba5ace) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
@ -585,9 +904,9 @@ ROM_END
|
||||
*
|
||||
*************************************/
|
||||
|
||||
GAME( 1988, toobin, 0, toobin, toobin, toobin_state, empty_init, ROT270, "Atari Games", "Toobin' (rev 3)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1988, toobin, 0, toobin, toobin, toobin_state, empty_init, ROT270, "Atari Games", "Toobin' (rev 3)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1988, toobine, toobin, toobin, toobin, toobin_state, empty_init, ROT270, "Atari Games", "Toobin' (Europe, rev 3)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1988, toobing, toobin, toobin, toobin, toobin_state, empty_init, ROT270, "Atari Games", "Toobin' (German, rev 3)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1988, toobin2, toobin, toobin, toobin, toobin_state, empty_init, ROT270, "Atari Games", "Toobin' (rev 2)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1988, toobin2, toobin, toobin, toobin, toobin_state, empty_init, ROT270, "Atari Games", "Toobin' (rev 2)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1988, toobin2e, toobin, toobin, toobin, toobin_state, empty_init, ROT270, "Atari Games", "Toobin' (Europe, rev 2)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1988, toobin1, toobin, toobin, toobin, toobin_state, empty_init, ROT270, "Atari Games", "Toobin' (rev 1)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1988, toobin1, toobin, toobin, toobin, toobin_state, empty_init, ROT270, "Atari Games", "Toobin' (rev 1)", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -1,83 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Aaron Giles
|
||||
/*************************************************************************
|
||||
|
||||
Atari Toobin' hardware
|
||||
|
||||
*************************************************************************/
|
||||
#ifndef MAME_ATARI_TOOBIN_H
|
||||
#define MAME_ATARI_TOOBIN_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "atarijsa.h"
|
||||
#include "atarimo.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
class toobin_state : public driver_device
|
||||
{
|
||||
public:
|
||||
toobin_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_screen(*this, "screen"),
|
||||
m_jsa(*this, "jsa"),
|
||||
m_playfield_tilemap(*this, "playfield"),
|
||||
m_alpha_tilemap(*this, "alpha"),
|
||||
m_mob(*this, "mob"),
|
||||
m_palette(*this, "palette"),
|
||||
m_paletteram(*this, "paletteram"),
|
||||
m_interrupt_scan(*this, "interrupt_scan"),
|
||||
m_xscroll(*this, "xscroll"),
|
||||
m_yscroll(*this, "yscroll")
|
||||
{ }
|
||||
|
||||
void toobin(machine_config &config);
|
||||
|
||||
private:
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(scanline_interrupt);
|
||||
void scanline_int_ack_w(uint16_t data);
|
||||
|
||||
void interrupt_scan_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void paletteram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void intensity_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void xscroll_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void yscroll_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void slip_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_alpha_tile_info);
|
||||
TILE_GET_INFO_MEMBER(get_playfield_tile_info);
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void main_map(address_map &map);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<atari_jsa_i_device> m_jsa;
|
||||
required_device<tilemap_device> m_playfield_tilemap;
|
||||
required_device<tilemap_device> m_alpha_tilemap;
|
||||
required_device<atari_motion_objects_device> m_mob;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
required_shared_ptr<uint16_t> m_paletteram;
|
||||
required_shared_ptr<uint16_t> m_interrupt_scan;
|
||||
required_shared_ptr<uint16_t> m_xscroll;
|
||||
required_shared_ptr<uint16_t> m_yscroll;
|
||||
|
||||
double m_brightness = 0;
|
||||
bitmap_ind16 m_pfbitmap;
|
||||
|
||||
emu_timer *m_scanline_interrupt_timer = nullptr;
|
||||
|
||||
static const atari_motion_objects_config s_mob_config;
|
||||
};
|
||||
|
||||
#endif // MAME_ATARI_TOOBIN_H
|
@ -1,250 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Aaron Giles
|
||||
/***************************************************************************
|
||||
|
||||
Atari Toobin' hardware
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "toobin.h"
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Tilemap callbacks
|
||||
*
|
||||
*************************************/
|
||||
|
||||
TILE_GET_INFO_MEMBER(toobin_state::get_alpha_tile_info)
|
||||
{
|
||||
uint16_t data = m_alpha_tilemap->basemem_read(tile_index);
|
||||
int code = data & 0x3ff;
|
||||
int color = (data >> 12) & 0x0f;
|
||||
tileinfo.set(2, code, color, (data >> 10) & 1);
|
||||
}
|
||||
|
||||
|
||||
TILE_GET_INFO_MEMBER(toobin_state::get_playfield_tile_info)
|
||||
{
|
||||
uint32_t data = m_playfield_tilemap->basemem_read(tile_index);
|
||||
int code = data & 0x3fff;
|
||||
int color = (data >> 16) & 0x0f;
|
||||
tileinfo.set(0, code, color, TILE_FLIPYX(data >> 14));
|
||||
tileinfo.category = (data >> 20) & 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Video system start
|
||||
*
|
||||
*************************************/
|
||||
|
||||
const atari_motion_objects_config toobin_state::s_mob_config =
|
||||
{
|
||||
1, /* index to which gfx system */
|
||||
1, /* number of motion object banks */
|
||||
1, /* are the entries linked? */
|
||||
0, /* are the entries split? */
|
||||
0, /* render in reverse order? */
|
||||
1, /* render in swapped X/Y order? */
|
||||
0, /* does the neighbor bit affect the next object? */
|
||||
1024, /* pixels per SLIP entry (0 for no-slip) */
|
||||
0, /* pixel offset for SLIPs */
|
||||
0, /* maximum number of links to visit/scanline (0=all) */
|
||||
|
||||
0x100, /* base palette entry */
|
||||
0x100, /* maximum number of colors */
|
||||
0, /* transparent pen index */
|
||||
|
||||
{{ 0,0,0x00ff,0 }}, /* mask for the link */
|
||||
{{ 0,0x3fff,0,0 }}, /* mask for the code index */
|
||||
{{ 0,0,0,0x000f }}, /* mask for the color */
|
||||
{{ 0,0,0,0xffc0 }}, /* mask for the X position */
|
||||
{{ 0x7fc0,0,0,0 }}, /* mask for the Y position */
|
||||
{{ 0x0007,0,0,0 }}, /* mask for the width, in tiles*/
|
||||
{{ 0x0038,0,0,0 }}, /* mask for the height, in tiles */
|
||||
{{ 0,0x4000,0,0 }}, /* mask for the horizontal flip */
|
||||
{{ 0,0x8000,0,0 }}, /* mask for the vertical flip */
|
||||
{{ 0 }}, /* mask for the priority */
|
||||
{{ 0 }}, /* mask for the neighbor */
|
||||
{{ 0x8000,0,0,0 }}, /* mask for absolute coordinates */
|
||||
|
||||
{{ 0 }}, /* mask for the special value */
|
||||
0 /* resulting value to indicate "special" */
|
||||
};
|
||||
|
||||
void toobin_state::video_start()
|
||||
{
|
||||
/* allocate a playfield bitmap for rendering */
|
||||
m_screen->register_screen_bitmap(m_pfbitmap);
|
||||
|
||||
save_item(NAME(m_brightness));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Palette RAM write handler
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void toobin_state::paletteram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_paletteram[offset]);
|
||||
uint16_t newword = m_paletteram[offset];
|
||||
|
||||
{
|
||||
int red = (((newword >> 10) & 31) * 224) >> 5;
|
||||
int green = (((newword >> 5) & 31) * 224) >> 5;
|
||||
int blue = (((newword ) & 31) * 224) >> 5;
|
||||
|
||||
if (red) red += 38;
|
||||
if (green) green += 38;
|
||||
if (blue) blue += 38;
|
||||
|
||||
m_palette->set_pen_color(offset & 0x3ff, rgb_t(red, green, blue));
|
||||
if (!(newword & 0x8000))
|
||||
m_palette->set_pen_contrast(offset & 0x3ff, m_brightness);
|
||||
else
|
||||
m_palette->set_pen_contrast(offset & 0x3ff, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void toobin_state::intensity_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
{
|
||||
m_brightness = (double)(~data & 0x1f) / 31.0;
|
||||
|
||||
for (int i = 0; i < 0x400; i++)
|
||||
if (!BIT(m_paletteram[i], 15))
|
||||
m_palette->set_pen_contrast(i, m_brightness);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* X/Y scroll handlers
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void toobin_state::xscroll_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t oldscroll = *m_xscroll;
|
||||
uint16_t newscroll = oldscroll;
|
||||
COMBINE_DATA(&newscroll);
|
||||
|
||||
/* if anything has changed, force a partial update */
|
||||
if (newscroll != oldscroll)
|
||||
m_screen->update_partial(m_screen->vpos());
|
||||
|
||||
/* update the playfield scrolling - hscroll is clocked on the following scanline */
|
||||
m_playfield_tilemap->set_scrollx(0, newscroll >> 6);
|
||||
m_mob->set_xscroll(newscroll >> 6);
|
||||
|
||||
/* update the data */
|
||||
*m_xscroll = newscroll;
|
||||
}
|
||||
|
||||
|
||||
void toobin_state::yscroll_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t oldscroll = *m_yscroll;
|
||||
uint16_t newscroll = oldscroll;
|
||||
COMBINE_DATA(&newscroll);
|
||||
|
||||
/* if anything has changed, force a partial update */
|
||||
if (newscroll != oldscroll)
|
||||
m_screen->update_partial(m_screen->vpos());
|
||||
|
||||
/* if bit 4 is zero, the scroll value is clocked in right away */
|
||||
m_playfield_tilemap->set_scrolly(0, newscroll >> 6);
|
||||
m_mob->set_yscroll((newscroll >> 6) & 0x1ff);
|
||||
|
||||
/* update the data */
|
||||
*m_yscroll = newscroll;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* X/Y scroll handlers
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void toobin_state::slip_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t oldslip = m_mob->slipram(offset);
|
||||
uint16_t newslip = oldslip;
|
||||
COMBINE_DATA(&newslip);
|
||||
|
||||
/* if the SLIP is changing, force a partial update first */
|
||||
if (oldslip != newslip)
|
||||
m_screen->update_partial(m_screen->vpos());
|
||||
|
||||
/* update the data */
|
||||
m_mob->slipram(offset) = newslip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Main refresh
|
||||
*
|
||||
*************************************/
|
||||
|
||||
uint32_t toobin_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
// start drawing
|
||||
m_mob->draw_async(cliprect);
|
||||
|
||||
/* draw the playfield */
|
||||
bitmap_ind8 &priority_bitmap = screen.priority();
|
||||
priority_bitmap.fill(0, cliprect);
|
||||
m_playfield_tilemap->draw(screen, m_pfbitmap, cliprect, 0, 0);
|
||||
m_playfield_tilemap->draw(screen, m_pfbitmap, cliprect, 1, 1);
|
||||
m_playfield_tilemap->draw(screen, m_pfbitmap, cliprect, 2, 2);
|
||||
m_playfield_tilemap->draw(screen, m_pfbitmap, cliprect, 3, 3);
|
||||
|
||||
/* draw and merge the MO */
|
||||
bitmap_ind16 &mobitmap = m_mob->bitmap();
|
||||
pen_t const *const palette = m_palette->pens();
|
||||
for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
|
||||
{
|
||||
uint32_t *const dest = &bitmap.pix(y);
|
||||
uint16_t const *const mo = &mobitmap.pix(y);
|
||||
uint16_t const *const pf = &m_pfbitmap.pix(y);
|
||||
uint8_t const *const pri = &priority_bitmap.pix(y);
|
||||
for (int x = cliprect.left(); x <= cliprect.right(); x++)
|
||||
{
|
||||
uint16_t pix = pf[x];
|
||||
if (mo[x] != 0xffff)
|
||||
{
|
||||
/* not verified: logic is all controlled in a PAL
|
||||
|
||||
factors: LBPRI1-0, LBPIX3, ANPIX1-0, PFPIX3, PFPRI1-0,
|
||||
(~LBPIX3 & ~LBPIX2 & ~LBPIX1 & ~LBPIX0)
|
||||
*/
|
||||
|
||||
/* only draw if not high priority PF */
|
||||
if (!pri[x] || !(pix & 8))
|
||||
pix = mo[x];
|
||||
}
|
||||
dest[x] = palette[pix];
|
||||
}
|
||||
}
|
||||
|
||||
/* add the alpha on top */
|
||||
m_alpha_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
return 0;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Stefan Jokisch
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Atari Triple Hunt Driver
|
||||
@ -9,12 +10,213 @@ Atari Triple Hunt Driver
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "triplhnt.h"
|
||||
|
||||
#include "triplhnt_a.h"
|
||||
|
||||
#include "cpu/m6800/m6800.h"
|
||||
#include "machine/74259.h"
|
||||
#include "machine/nvram.h"
|
||||
#include "machine/watchdog.h"
|
||||
#include "sound/discrete.h"
|
||||
#include "sound/samples.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class triplhnt_state : public driver_device
|
||||
{
|
||||
public:
|
||||
triplhnt_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_latch(*this, "latch"),
|
||||
m_watchdog(*this, "watchdog"),
|
||||
m_discrete(*this, "discrete"),
|
||||
m_samples(*this, "samples"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_screen(*this, "screen"),
|
||||
m_palette(*this, "palette"),
|
||||
m_playfield_ram(*this, "playfield_ram"),
|
||||
m_vpos_ram(*this, "vpos_ram"),
|
||||
m_hpos_ram(*this, "hpos_ram"),
|
||||
m_orga_ram(*this, "orga_ram"),
|
||||
m_code_ram(*this, "code_ram"),
|
||||
m_0c09(*this, "0C09"),
|
||||
m_0c0b(*this, "0C0B"),
|
||||
m_vblank(*this, "VBLANK"),
|
||||
m_stick(*this, "STICK%c", 'X'),
|
||||
m_lamp(*this, "lamp0")
|
||||
{ }
|
||||
|
||||
void triplhnt(machine_config &config);
|
||||
|
||||
void init_triplhnt();
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<f9334_device> m_latch;
|
||||
required_device<watchdog_timer_device> m_watchdog;
|
||||
required_device<discrete_sound_device> m_discrete;
|
||||
required_device<samples_device> m_samples;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
required_shared_ptr<uint8_t> m_playfield_ram;
|
||||
required_shared_ptr<uint8_t> m_vpos_ram;
|
||||
required_shared_ptr<uint8_t> m_hpos_ram;
|
||||
required_shared_ptr<uint8_t> m_orga_ram;
|
||||
required_shared_ptr<uint8_t> m_code_ram;
|
||||
required_ioport m_0c09;
|
||||
required_ioport m_0c0b;
|
||||
required_ioport m_vblank;
|
||||
required_ioport_array<2> m_stick;
|
||||
output_finder<> m_lamp;
|
||||
|
||||
uint8_t m_cmos[16]{};
|
||||
uint8_t m_da_latch = 0;
|
||||
uint8_t m_cmos_latch = 0;
|
||||
uint8_t m_hit_code = 0;
|
||||
uint8_t m_sprite_zoom = 0;
|
||||
uint8_t m_sprite_bank = 0;
|
||||
bitmap_ind16 m_helper;
|
||||
emu_timer *m_hit_timer = nullptr;
|
||||
tilemap_t* m_bg_tilemap = nullptr;
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(coin_lockout_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(tape_control_w);
|
||||
|
||||
uint8_t cmos_r(offs_t offset);
|
||||
uint8_t input_port_4_r();
|
||||
uint8_t misc_r(offs_t offset);
|
||||
uint8_t da_latch_r(offs_t offset);
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_tile_info);
|
||||
void palette(palette_device &palette) const;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
TIMER_CALLBACK_MEMBER(set_collision);
|
||||
|
||||
void program_map(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
|
||||
TILE_GET_INFO_MEMBER(triplhnt_state::get_tile_info)
|
||||
{
|
||||
int const code = m_playfield_ram[tile_index] & 0x3f;
|
||||
|
||||
tileinfo.set(2, code, code == 0x3f ? 1 : 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void triplhnt_state::video_start()
|
||||
{
|
||||
m_screen->register_screen_bitmap(m_helper);
|
||||
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(triplhnt_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 16);
|
||||
|
||||
m_hit_timer = timer_alloc(FUNC(triplhnt_state::set_collision), this);
|
||||
|
||||
save_item(NAME(m_cmos));
|
||||
save_item(NAME(m_da_latch));
|
||||
save_item(NAME(m_cmos_latch));
|
||||
save_item(NAME(m_hit_code));
|
||||
save_item(NAME(m_sprite_zoom));
|
||||
save_item(NAME(m_sprite_bank));
|
||||
}
|
||||
|
||||
|
||||
void triplhnt_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int hit_line = 999;
|
||||
int hit_code = 999;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
rectangle rect;
|
||||
|
||||
int const j = (m_orga_ram[i] & 15) ^ 15;
|
||||
|
||||
// software sorts sprites by x and stores order in orga RAM
|
||||
|
||||
int hpos = m_hpos_ram[j] ^ 255;
|
||||
int vpos = m_vpos_ram[j] ^ 255;
|
||||
int code = m_code_ram[j] ^ 255;
|
||||
|
||||
if (hpos == 255)
|
||||
continue;
|
||||
|
||||
// sprite placement might be wrong
|
||||
|
||||
if (m_sprite_zoom)
|
||||
{
|
||||
rect.set(hpos - 16, hpos - 16 + 63, 196 - vpos, 196 - vpos + 63);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.set(hpos - 16, hpos - 16 + 31, 224 - vpos, 224 - vpos + 31);
|
||||
}
|
||||
|
||||
// render sprite to auxiliary bitmap
|
||||
|
||||
m_gfxdecode->gfx(m_sprite_zoom)->opaque(m_helper, cliprect,
|
||||
2 * code + m_sprite_bank, 0, code & 8, 0,
|
||||
rect.left(), rect.top());
|
||||
|
||||
rect &= cliprect;
|
||||
|
||||
// check for collisions and copy sprite
|
||||
for (int x = rect.left(); x <= rect.right(); x++)
|
||||
{
|
||||
for (int y = rect.top(); y <= rect.bottom(); y++)
|
||||
{
|
||||
pen_t const a = m_helper.pix(y, x);
|
||||
pen_t const b = bitmap.pix(y, x);
|
||||
|
||||
if (a == 2 && b == 7)
|
||||
{
|
||||
hit_code = j;
|
||||
hit_line = y;
|
||||
}
|
||||
|
||||
if (a != 1)
|
||||
bitmap.pix(y, x) = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hit_line != 999 && hit_code != 999)
|
||||
m_hit_timer->adjust(m_screen->time_until_pos(hit_line), hit_code);
|
||||
}
|
||||
|
||||
|
||||
uint32_t triplhnt_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_bg_tilemap->mark_all_dirty();
|
||||
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
|
||||
draw_sprites(bitmap, cliprect);
|
||||
|
||||
m_discrete->write(TRIPLHNT_BEAR_ROAR_DATA, m_playfield_ram[0xfa] & 15);
|
||||
m_discrete->write(TRIPLHNT_SHOT_DATA, m_playfield_ram[0xfc] & 15);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
|
||||
void triplhnt_state::init_triplhnt()
|
||||
{
|
||||
@ -39,16 +241,16 @@ WRITE_LINE_MEMBER(triplhnt_state::coin_lockout_w)
|
||||
|
||||
WRITE_LINE_MEMBER(triplhnt_state::tape_control_w)
|
||||
{
|
||||
bool is_witch_hunt = ioport("0C09")->read() == 0x40;
|
||||
bool bit = !state;
|
||||
bool const is_witch_hunt = m_0c09->read() == 0x40;
|
||||
bool const bit = !state;
|
||||
|
||||
/* if we're not playing the sample yet, start it */
|
||||
// if we're not playing the sample yet, start it
|
||||
if (!m_samples->playing(0))
|
||||
m_samples->start(0, 0, true);
|
||||
if (!m_samples->playing(1))
|
||||
m_samples->start(1, 1, true);
|
||||
|
||||
/* bit 6 turns cassette on/off */
|
||||
// bit 6 turns cassette on/off
|
||||
m_samples->pause(0, is_witch_hunt || bit);
|
||||
m_samples->pause(1, !is_witch_hunt || bit);
|
||||
}
|
||||
@ -65,25 +267,25 @@ uint8_t triplhnt_state::cmos_r(offs_t offset)
|
||||
uint8_t triplhnt_state::input_port_4_r()
|
||||
{
|
||||
m_watchdog->watchdog_reset();
|
||||
return ioport("0C0B")->read();
|
||||
return m_0c0b->read();
|
||||
}
|
||||
|
||||
|
||||
uint8_t triplhnt_state::misc_r(offs_t offset)
|
||||
{
|
||||
m_latch->write_a0(offset);
|
||||
return ioport("VBLANK")->read() | m_hit_code;
|
||||
return m_vblank->read() | m_hit_code;
|
||||
}
|
||||
|
||||
|
||||
uint8_t triplhnt_state::da_latch_r(offs_t offset)
|
||||
{
|
||||
int cross_x = ioport("STICKX")->read();
|
||||
int cross_y = ioport("STICKY")->read();
|
||||
int const cross_x = m_stick[0]->read();
|
||||
int const cross_y = m_stick[1]->read();
|
||||
|
||||
m_da_latch = offset;
|
||||
|
||||
/* the following is a slight simplification */
|
||||
// the following is a slight simplification
|
||||
|
||||
return (offset & 1) ? cross_x : cross_y;
|
||||
}
|
||||
@ -97,15 +299,15 @@ void triplhnt_state::machine_start()
|
||||
}
|
||||
|
||||
|
||||
void triplhnt_state::triplhnt_map(address_map &map)
|
||||
void triplhnt_state::program_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0x7fff);
|
||||
map(0x0000, 0x00ff).ram().mirror(0x300);
|
||||
map(0x0400, 0x04ff).writeonly().share("playfield_ram");
|
||||
map(0x0800, 0x080f).writeonly().share("vpos_ram");
|
||||
map(0x0810, 0x081f).writeonly().share("hpos_ram");
|
||||
map(0x0820, 0x082f).writeonly().share("orga_ram");
|
||||
map(0x0830, 0x083f).writeonly().share("code_ram");
|
||||
map(0x0400, 0x04ff).writeonly().share(m_playfield_ram);
|
||||
map(0x0800, 0x080f).writeonly().share(m_vpos_ram);
|
||||
map(0x0810, 0x081f).writeonly().share(m_hpos_ram);
|
||||
map(0x0820, 0x082f).writeonly().share(m_orga_ram);
|
||||
map(0x0830, 0x083f).writeonly().share(m_code_ram);
|
||||
map(0x0c00, 0x0c00).portr("0C00");
|
||||
map(0x0c08, 0x0c08).portr("0C08");
|
||||
map(0x0c09, 0x0c09).portr("0C09");
|
||||
@ -116,44 +318,44 @@ void triplhnt_state::triplhnt_map(address_map &map)
|
||||
map(0x0c30, 0x0c3f).r(FUNC(triplhnt_state::misc_r)).w(m_latch, FUNC(f9334_device::write_a0));
|
||||
map(0x0c40, 0x0c40).portr("0C40");
|
||||
map(0x0c48, 0x0c48).portr("0C48");
|
||||
map(0x7000, 0x7fff).rom(); /* program */
|
||||
map(0x7000, 0x7fff).rom();
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( triplhnt )
|
||||
PORT_START("0C00") /* 0C00 */
|
||||
PORT_START("0C00")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_COIN1 )
|
||||
|
||||
PORT_START("0C08") /* 0C08 */
|
||||
PORT_START("0C08")
|
||||
PORT_DIPNAME( 0xc0, 0x00, "Play Time" )
|
||||
PORT_DIPSETTING( 0x00, "32 seconds / 16 raccoons" )
|
||||
PORT_DIPSETTING( 0x40, "64 seconds / 32 raccoons" )
|
||||
PORT_DIPSETTING( 0x80, "96 seconds / 48 raccoons" )
|
||||
PORT_DIPSETTING( 0xc0, "128 seconds / 64 raccoons" )
|
||||
|
||||
PORT_START("0C09") /* 0C09 */
|
||||
PORT_START("0C09")
|
||||
PORT_DIPNAME( 0xc0, 0x40, "Game Select" )
|
||||
PORT_DIPSETTING( 0x00, "Hit the Bear" )
|
||||
PORT_DIPSETTING( 0x40, "Witch Hunt" )
|
||||
PORT_DIPSETTING( 0xc0, "Raccoon Hunt" )
|
||||
|
||||
PORT_START("0C0A") /* 0C0A */
|
||||
PORT_START("0C0A")
|
||||
PORT_DIPNAME( 0xc0, 0x00, DEF_STR( Coinage ))
|
||||
PORT_DIPSETTING( 0x40, DEF_STR( 2C_1C ))
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ))
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( 1C_2C ))
|
||||
|
||||
PORT_START("0C0B") /* 0C0B */
|
||||
PORT_START("0C0B")
|
||||
PORT_DIPNAME( 0x80, 0x00, "Extended Play" )
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( Off ))
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ))
|
||||
|
||||
PORT_START("0C40") /* 0C40 */
|
||||
PORT_START("0C40")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_TILT )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_COIN2 )
|
||||
|
||||
PORT_START("0C48") /* 0C48 */
|
||||
PORT_START("0C48")
|
||||
// default to service enabled to make users calibrate gun
|
||||
// PORT_SERVICE( 0x40, IP_ACTIVE_LOW )
|
||||
PORT_DIPNAME( 0x40, 0x00, DEF_STR( Service_Mode )) PORT_TOGGLE PORT_CODE(KEYCODE_F2)
|
||||
@ -170,31 +372,31 @@ static INPUT_PORTS_START( triplhnt )
|
||||
PORT_START("STICKY")
|
||||
PORT_BIT( 0xfc, 0x78, IPT_AD_STICK_Y ) PORT_MINMAX(0x00,0xec) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15)
|
||||
|
||||
PORT_START("BEAR") /* 10 */
|
||||
PORT_START("BEAR") // 10
|
||||
PORT_ADJUSTER( 35, "Bear Roar Frequency" )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
static const gfx_layout triplhnt_small_sprite_layout =
|
||||
{
|
||||
32, 32, /* width, height */
|
||||
16, /* total */
|
||||
2, /* planes */
|
||||
/* plane offsets */
|
||||
32, 32, // width, height
|
||||
16, // total
|
||||
2, // planes
|
||||
// plane offsets
|
||||
{ 0x0000, 0x4000 },
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
||||
},
|
||||
{
|
||||
0x000, 0x020, 0x040, 0x060, 0x080, 0x0A0, 0x0C0, 0x0E0,
|
||||
0x100, 0x120, 0x140, 0x160, 0x180, 0x1A0, 0x1C0, 0x1E0,
|
||||
0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
|
||||
0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0
|
||||
0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0,
|
||||
0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0,
|
||||
0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0,
|
||||
0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0
|
||||
},
|
||||
0x400 /* increment */
|
||||
0x400 // increment
|
||||
};
|
||||
|
||||
|
||||
@ -202,31 +404,31 @@ static const uint32_t triplhnt_large_sprite_layout_xoffset[64] =
|
||||
{
|
||||
0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
|
||||
0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07,
|
||||
0x08, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B,
|
||||
0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F,
|
||||
0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
|
||||
0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f,
|
||||
0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13,
|
||||
0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17,
|
||||
0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
|
||||
0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F
|
||||
0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b,
|
||||
0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f
|
||||
};
|
||||
|
||||
static const uint32_t triplhnt_large_sprite_layout_yoffset[64] =
|
||||
{
|
||||
0x000, 0x000, 0x020, 0x020, 0x040, 0x040, 0x060, 0x060,
|
||||
0x080, 0x080, 0x0A0, 0x0A0, 0x0C0, 0x0C0, 0x0E0, 0x0E0,
|
||||
0x080, 0x080, 0x0a0, 0x0a0, 0x0c0, 0x0c0, 0x0e0, 0x0e0,
|
||||
0x100, 0x100, 0x120, 0x120, 0x140, 0x140, 0x160, 0x160,
|
||||
0x180, 0x180, 0x1A0, 0x1A0, 0x1C0, 0x1C0, 0x1E0, 0x1E0,
|
||||
0x180, 0x180, 0x1a0, 0x1a0, 0x1c0, 0x1c0, 0x1e0, 0x1e0,
|
||||
0x200, 0x200, 0x220, 0x220, 0x240, 0x240, 0x260, 0x260,
|
||||
0x280, 0x280, 0x2A0, 0x2A0, 0x2C0, 0x2C0, 0x2E0, 0x2E0,
|
||||
0x280, 0x280, 0x2a0, 0x2a0, 0x2c0, 0x2c0, 0x2e0, 0x2e0,
|
||||
0x300, 0x300, 0x320, 0x320, 0x340, 0x340, 0x360, 0x360,
|
||||
0x380, 0x380, 0x3A0, 0x3A0, 0x3C0, 0x3C0, 0x3E0, 0x3E0
|
||||
0x380, 0x380, 0x3a0, 0x3a0, 0x3c0, 0x3c0, 0x3e0, 0x3e0
|
||||
};
|
||||
|
||||
static const gfx_layout triplhnt_large_sprite_layout =
|
||||
{
|
||||
64, 64, /* width, height */
|
||||
16, /* total */
|
||||
2, /* planes */
|
||||
64, 64, // width, height
|
||||
16, // total
|
||||
2, // planes
|
||||
{ 0x0000, 0x4000 },
|
||||
EXTENDED_XOFFS,
|
||||
EXTENDED_YOFFS,
|
||||
@ -238,10 +440,10 @@ static const gfx_layout triplhnt_large_sprite_layout =
|
||||
|
||||
static const gfx_layout triplhnt_tile_layout =
|
||||
{
|
||||
16, 16, /* width, height */
|
||||
64, /* total */
|
||||
1, /* planes */
|
||||
{ 0 }, /* plane offsets */
|
||||
16, 16, // width, height
|
||||
64, // total
|
||||
1, // planes
|
||||
{ 0 }, // plane offsets
|
||||
{
|
||||
0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7
|
||||
},
|
||||
@ -249,18 +451,18 @@ static const gfx_layout triplhnt_tile_layout =
|
||||
0x00, 0x00, 0x08, 0x08, 0x10, 0x10, 0x18, 0x18,
|
||||
0x20, 0x20, 0x28, 0x28, 0x30, 0x30, 0x38, 0x38
|
||||
},
|
||||
0x40 /* increment */
|
||||
0x40 // increment
|
||||
};
|
||||
|
||||
|
||||
static GFXDECODE_START( gfx_triplhnt )
|
||||
GFXDECODE_ENTRY( "gfx1", 0, triplhnt_small_sprite_layout, 0, 1 )
|
||||
GFXDECODE_ENTRY( "gfx1", 0, triplhnt_large_sprite_layout, 0, 1 )
|
||||
GFXDECODE_ENTRY( "gfx2", 0, triplhnt_tile_layout, 4, 2 )
|
||||
GFXDECODE_ENTRY( "sprites", 0, triplhnt_small_sprite_layout, 0, 1 )
|
||||
GFXDECODE_ENTRY( "sprites", 0, triplhnt_large_sprite_layout, 0, 1 )
|
||||
GFXDECODE_ENTRY( "tiles", 0, triplhnt_tile_layout, 4, 2 )
|
||||
GFXDECODE_END
|
||||
|
||||
|
||||
void triplhnt_state::triplhnt_palette(palette_device &palette) const
|
||||
void triplhnt_state::palette(palette_device &palette) const
|
||||
{
|
||||
palette.set_pen_color(0, rgb_t(0xaf, 0xaf, 0xaf)); // sprites
|
||||
palette.set_pen_color(1, rgb_t(0x00, 0x00, 0x00));
|
||||
@ -275,9 +477,9 @@ void triplhnt_state::triplhnt_palette(palette_device &palette) const
|
||||
|
||||
void triplhnt_state::triplhnt(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
M6800(config, m_maincpu, 800000);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &triplhnt_state::triplhnt_map);
|
||||
// basic machine hardware
|
||||
M6800(config, m_maincpu, 800'000);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &triplhnt_state::program_map);
|
||||
m_maincpu->set_vblank_int("screen", FUNC(triplhnt_state::irq0_line_hold));
|
||||
|
||||
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // battery-backed 74C89 at J5
|
||||
@ -296,7 +498,7 @@ void triplhnt_state::triplhnt(machine_config &config)
|
||||
|
||||
WATCHDOG_TIMER(config, m_watchdog);
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_size(256, 262);
|
||||
@ -305,13 +507,13 @@ void triplhnt_state::triplhnt(machine_config &config)
|
||||
screen.set_palette(m_palette);
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, m_palette, gfx_triplhnt);
|
||||
PALETTE(config, m_palette, FUNC(triplhnt_state::triplhnt_palette), 8);
|
||||
PALETTE(config, m_palette, FUNC(triplhnt_state::palette), 8);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
SAMPLES(config, m_samples);
|
||||
m_samples->set_channels(2); /* 2 channels */
|
||||
m_samples->set_channels(2);
|
||||
m_samples->set_samples_names(triplhnt_sample_names);
|
||||
m_samples->add_route(ALL_OUTPUTS, "mono", 0.20);
|
||||
|
||||
@ -331,14 +533,16 @@ ROM_START( triplhnt )
|
||||
ROM_LOAD_NIB_HIGH( "8401.c1", 0x7C00, 0x400, CRC(7461b05e) SHA1(16573ae655c306a38ff0f29a3c3285d636907f38) )
|
||||
ROM_LOAD_NIB_LOW ( "8405.c2", 0x7C00, 0x400, CRC(ba370b97) SHA1(5d799ce6ae56c315ff0abedea7ad9204bacc266b) )
|
||||
|
||||
ROM_REGION( 0x1000, "gfx1", 0 ) /* sprites */
|
||||
ROM_REGION( 0x1000, "sprites", 0 )
|
||||
ROM_LOAD( "8423.n1", 0x0000, 0x800, CRC(9937d0da) SHA1(abb906c2d9869b09be5172cc7639bb9cda38831b) )
|
||||
ROM_LOAD( "8422.r1", 0x0800, 0x800, CRC(803621dd) SHA1(ffbd7f87a86477e5eb94f12fc20a837128a02442) )
|
||||
|
||||
ROM_REGION( 0x200, "gfx2", 0 ) /* tiles */
|
||||
ROM_REGION( 0x200, "tiles", 0 )
|
||||
ROM_LOAD_NIB_HIGH( "8409.l3", 0x0000, 0x200, CRC(ec304172) SHA1(ccbf7e117fef7fa4288e3bf68f1a150b3a492ce6) )
|
||||
ROM_LOAD_NIB_LOW ( "8410.m3", 0x0000, 0x200, CRC(f75a1b08) SHA1(81b4733194462cd4cef7f4221ecb7abd1556b871) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
GAME( 1977, triplhnt, 0, triplhnt, triplhnt, triplhnt_state, init_triplhnt, 0, "Atari", "Triple Hunt", MACHINE_REQUIRES_ARTWORK | MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -1,108 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Stefan Jokisch
|
||||
/*************************************************************************
|
||||
|
||||
Atari Triple Hunt hardware
|
||||
|
||||
*************************************************************************/
|
||||
#ifndef MAME_ATARI_TRIPLHNT_H
|
||||
#define MAME_ATARI_TRIPLHNT_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "machine/74259.h"
|
||||
#include "machine/watchdog.h"
|
||||
#include "sound/discrete.h"
|
||||
#include "sound/samples.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
|
||||
/* Discrete Sound Input Nodes */
|
||||
#define TRIPLHNT_BEAR_ROAR_DATA NODE_01
|
||||
#define TRIPLHNT_BEAR_EN NODE_02
|
||||
#define TRIPLHNT_SHOT_DATA NODE_03
|
||||
#define TRIPLHNT_SCREECH_EN NODE_04
|
||||
#define TRIPLHNT_LAMP_EN NODE_05
|
||||
|
||||
|
||||
class triplhnt_state : public driver_device
|
||||
{
|
||||
public:
|
||||
triplhnt_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_latch(*this, "latch"),
|
||||
m_watchdog(*this, "watchdog"),
|
||||
m_discrete(*this, "discrete"),
|
||||
m_samples(*this, "samples"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_screen(*this, "screen"),
|
||||
m_palette(*this, "palette"),
|
||||
m_playfield_ram(*this, "playfield_ram"),
|
||||
m_vpos_ram(*this, "vpos_ram"),
|
||||
m_hpos_ram(*this, "hpos_ram"),
|
||||
m_orga_ram(*this, "orga_ram"),
|
||||
m_code_ram(*this, "code_ram"),
|
||||
m_lamp(*this, "lamp0")
|
||||
{ }
|
||||
|
||||
void triplhnt(machine_config &config);
|
||||
|
||||
void init_triplhnt();
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
DECLARE_WRITE_LINE_MEMBER(coin_lockout_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(tape_control_w);
|
||||
|
||||
uint8_t cmos_r(offs_t offset);
|
||||
uint8_t input_port_4_r();
|
||||
uint8_t misc_r(offs_t offset);
|
||||
uint8_t da_latch_r(offs_t offset);
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_tile_info);
|
||||
void triplhnt_palette(palette_device &palette) const;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
TIMER_CALLBACK_MEMBER(set_collision);
|
||||
|
||||
void triplhnt_map(address_map &map);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<f9334_device> m_latch;
|
||||
required_device<watchdog_timer_device> m_watchdog;
|
||||
required_device<discrete_sound_device> m_discrete;
|
||||
required_device<samples_device> m_samples;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
required_shared_ptr<uint8_t> m_playfield_ram;
|
||||
required_shared_ptr<uint8_t> m_vpos_ram;
|
||||
required_shared_ptr<uint8_t> m_hpos_ram;
|
||||
required_shared_ptr<uint8_t> m_orga_ram;
|
||||
required_shared_ptr<uint8_t> m_code_ram;
|
||||
output_finder<> m_lamp;
|
||||
|
||||
uint8_t m_cmos[16]{};
|
||||
uint8_t m_da_latch = 0;
|
||||
uint8_t m_cmos_latch = 0;
|
||||
uint8_t m_hit_code = 0;
|
||||
int m_sprite_zoom = 0;
|
||||
int m_sprite_bank = 0;
|
||||
bitmap_ind16 m_helper;
|
||||
emu_timer *m_hit_timer = nullptr;
|
||||
tilemap_t* m_bg_tilemap = nullptr;
|
||||
};
|
||||
|
||||
/*----------- defined in audio/triplhnt.cpp -----------*/
|
||||
DISCRETE_SOUND_EXTERN( triplhnt_discrete );
|
||||
extern const char *const triplhnt_sample_names[];
|
||||
|
||||
#endif // MAME_ATARI_TRIPLHNT_H
|
@ -1,12 +1,15 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Derrick Renaud
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
audio\triplhnt.cpp
|
||||
atari\triplhnt_a.cpp
|
||||
|
||||
*************************************************************************/
|
||||
#include "emu.h"
|
||||
#include "triplhnt.h"
|
||||
|
||||
#include "triplhnt_a.h"
|
||||
|
||||
#include "sound/discrete.h"
|
||||
|
||||
|
||||
|
22
src/mame/atari/triplhnt_a.h
Normal file
22
src/mame/atari/triplhnt_a.h
Normal file
@ -0,0 +1,22 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Derrick Renaud
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Triple Hunt Audio
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "sound/discrete.h"
|
||||
|
||||
// discrete sound input nodes
|
||||
|
||||
#define TRIPLHNT_BEAR_ROAR_DATA NODE_01
|
||||
#define TRIPLHNT_BEAR_EN NODE_02
|
||||
#define TRIPLHNT_SHOT_DATA NODE_03
|
||||
#define TRIPLHNT_SCREECH_EN NODE_04
|
||||
#define TRIPLHNT_LAMP_EN NODE_05
|
||||
|
||||
|
||||
DISCRETE_SOUND_EXTERN( triplhnt_discrete );
|
||||
extern const char *const triplhnt_sample_names[];
|
@ -1,113 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Stefan Jokisch
|
||||
/***************************************************************************
|
||||
|
||||
Atari Triple Hunt video emulation
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "triplhnt.h"
|
||||
|
||||
|
||||
TILE_GET_INFO_MEMBER(triplhnt_state::get_tile_info)
|
||||
{
|
||||
int code = m_playfield_ram[tile_index] & 0x3f;
|
||||
|
||||
tileinfo.set(2, code, code == 0x3f ? 1 : 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void triplhnt_state::video_start()
|
||||
{
|
||||
m_screen->register_screen_bitmap(m_helper);
|
||||
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(triplhnt_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 16);
|
||||
|
||||
m_hit_timer = timer_alloc(FUNC(triplhnt_state::set_collision), this);
|
||||
|
||||
save_item(NAME(m_cmos));
|
||||
save_item(NAME(m_da_latch));
|
||||
save_item(NAME(m_cmos_latch));
|
||||
save_item(NAME(m_hit_code));
|
||||
save_item(NAME(m_sprite_zoom));
|
||||
save_item(NAME(m_sprite_bank));
|
||||
}
|
||||
|
||||
|
||||
void triplhnt_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int hit_line = 999;
|
||||
int hit_code = 999;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
rectangle rect;
|
||||
|
||||
int j = (m_orga_ram[i] & 15) ^ 15;
|
||||
|
||||
/* software sorts sprites by x and stores order in orga RAM */
|
||||
|
||||
int hpos = m_hpos_ram[j] ^ 255;
|
||||
int vpos = m_vpos_ram[j] ^ 255;
|
||||
int code = m_code_ram[j] ^ 255;
|
||||
|
||||
if (hpos == 255)
|
||||
continue;
|
||||
|
||||
/* sprite placement might be wrong */
|
||||
|
||||
if (m_sprite_zoom)
|
||||
{
|
||||
rect.set(hpos - 16, hpos - 16 + 63, 196 - vpos, 196 - vpos + 63);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.set(hpos - 16, hpos - 16 + 31, 224 - vpos, 224 - vpos + 31);
|
||||
}
|
||||
|
||||
/* render sprite to auxiliary bitmap */
|
||||
|
||||
m_gfxdecode->gfx(m_sprite_zoom)->opaque(m_helper,cliprect,
|
||||
2 * code + m_sprite_bank, 0, code & 8, 0,
|
||||
rect.left(), rect.top());
|
||||
|
||||
rect &= cliprect;
|
||||
|
||||
/* check for collisions and copy sprite */
|
||||
for (int x = rect.left(); x <= rect.right(); x++)
|
||||
{
|
||||
for (int y = rect.top(); y <= rect.bottom(); y++)
|
||||
{
|
||||
pen_t const a = m_helper.pix(y, x);
|
||||
pen_t const b = bitmap.pix(y, x);
|
||||
|
||||
if (a == 2 && b == 7)
|
||||
{
|
||||
hit_code = j;
|
||||
hit_line = y;
|
||||
}
|
||||
|
||||
if (a != 1)
|
||||
bitmap.pix(y, x) = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hit_line != 999 && hit_code != 999)
|
||||
m_hit_timer->adjust(m_screen->time_until_pos(hit_line), hit_code);
|
||||
}
|
||||
|
||||
|
||||
uint32_t triplhnt_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_bg_tilemap->mark_all_dirty();
|
||||
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
|
||||
draw_sprites(bitmap, cliprect);
|
||||
|
||||
m_discrete->write(TRIPLHNT_BEAR_ROAR_DATA, m_playfield_ram[0xfa] & 15);
|
||||
m_discrete->write(TRIPLHNT_SHOT_DATA, m_playfield_ram[0xfc] & 15);
|
||||
return 0;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Phil Stroffolino, David Haywood
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Atari Tunnel Hunt hardware
|
||||
@ -26,8 +27,8 @@
|
||||
|
||||
Colors:
|
||||
- Hues are hardcoded. There doesn't appear to be any logical way to
|
||||
map the color proms so that the correct colors appear.
|
||||
See last page of schematics for details. Are color proms bad?
|
||||
map the color PROMs so that the correct colors appear.
|
||||
See last page of schematics for details. Are color PROMs bad?
|
||||
(shouldn't be, both sets were the same)
|
||||
|
||||
Shell Objects:
|
||||
@ -46,13 +47,462 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "tunhunt.h"
|
||||
|
||||
#include "cpu/m6502/m6502.h"
|
||||
#include "machine/rescap.h"
|
||||
#include "sound/pokey.h"
|
||||
#include "speaker.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class tunhunt_state : public driver_device
|
||||
{
|
||||
public:
|
||||
tunhunt_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_screen(*this, "screen"),
|
||||
m_palette(*this, "palette"),
|
||||
m_workram(*this, "workram"),
|
||||
m_videoram(*this, "videoram"),
|
||||
m_spriteram(*this, "spriteram"),
|
||||
m_paletteram(*this, "paletteram"),
|
||||
m_in0(*this, "IN0"),
|
||||
m_dsw(*this, "DSW"),
|
||||
m_led(*this, "led0")
|
||||
{ }
|
||||
|
||||
void tunhunt(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override { m_led.resolve(); }
|
||||
virtual void machine_reset() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
required_shared_ptr<uint8_t> m_workram;
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_shared_ptr<uint8_t> m_paletteram;
|
||||
required_ioport m_in0;
|
||||
required_ioport m_dsw;
|
||||
output_finder<> m_led;
|
||||
|
||||
uint8_t m_control = 0;
|
||||
tilemap_t *m_fg_tilemap = nullptr;
|
||||
bitmap_ind16 m_tmpbitmap;
|
||||
|
||||
uint8_t m_mobsc0 = 0;
|
||||
uint8_t m_mobsc1 = 0;
|
||||
uint8_t m_lineh[13]{};
|
||||
uint8_t m_shl0st = 0;
|
||||
uint8_t m_shl1st = 0;
|
||||
uint8_t m_vstrlo = 0;
|
||||
uint8_t m_linesh = 0;
|
||||
uint8_t m_shl0pc = 0;
|
||||
uint8_t m_shl1pc = 0;
|
||||
uint8_t m_linec[13]{};
|
||||
uint8_t m_shl0v = 0;
|
||||
uint8_t m_shl1v = 0;
|
||||
uint8_t m_mobjh = 0;
|
||||
uint8_t m_linev[13]{};
|
||||
uint8_t m_shl0vs = 0;
|
||||
uint8_t m_shl1vs = 0;
|
||||
uint8_t m_mobvs = 0;
|
||||
uint8_t m_linevs[13]{};
|
||||
uint8_t m_shel0h = 0;
|
||||
uint8_t m_mobst = 0;
|
||||
uint8_t m_shel1h = 0;
|
||||
uint8_t m_mobjv = 0;
|
||||
|
||||
void control_w(uint8_t data);
|
||||
uint8_t button_r(offs_t offset);
|
||||
void videoram_w(offs_t offset, uint8_t data);
|
||||
template <uint16_t Mask> uint8_t dsw2_r();
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_fg_tile_info);
|
||||
|
||||
void palette(palette_device &palette) const;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void set_pens();
|
||||
void draw_motion_object(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void draw_box(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void draw_shell(bitmap_ind16 &bitmap, const rectangle &cliprect, int picture_code, int hposition, int vstart, int vstop, int vstretch, int hstretch);
|
||||
void main_map(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void tunhunt_state::videoram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_videoram[offset] = data;
|
||||
m_fg_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(tunhunt_state::get_fg_tile_info)
|
||||
{
|
||||
int const attr = m_videoram[tile_index];
|
||||
int const code = attr & 0x3f;
|
||||
int const color = attr >> 6;
|
||||
int const flags = color ? TILE_FORCE_LAYER0 : 0;
|
||||
|
||||
tileinfo.set(0, code, color, flags);
|
||||
}
|
||||
|
||||
void tunhunt_state::video_start()
|
||||
{
|
||||
/*
|
||||
Motion Object RAM contains 64 lines of run-length encoded data.
|
||||
We keep track of dirty lines and cache the expanded bitmap.
|
||||
With max RLE expansion, bitmap size is 256x64.
|
||||
*/
|
||||
|
||||
m_tmpbitmap.allocate(256, 64, m_screen->format());
|
||||
|
||||
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tunhunt_state::get_fg_tile_info)), TILEMAP_SCAN_COLS, 8, 8, 8, 32);
|
||||
|
||||
m_fg_tilemap->set_transparent_pen(0);
|
||||
m_fg_tilemap->set_scrollx(0, 64);
|
||||
|
||||
save_item(NAME(m_control));
|
||||
save_item(NAME(m_mobsc0));
|
||||
save_item(NAME(m_mobsc1));
|
||||
save_item(NAME(m_lineh));
|
||||
save_item(NAME(m_shl0st));
|
||||
save_item(NAME(m_shl1st));
|
||||
save_item(NAME(m_vstrlo));
|
||||
save_item(NAME(m_linesh));
|
||||
save_item(NAME(m_shl0pc));
|
||||
save_item(NAME(m_shl1pc));
|
||||
save_item(NAME(m_linec));
|
||||
save_item(NAME(m_shl0v));
|
||||
save_item(NAME(m_shl1v));
|
||||
save_item(NAME(m_mobjh));
|
||||
save_item(NAME(m_linev));
|
||||
save_item(NAME(m_shl0vs));
|
||||
save_item(NAME(m_shl1vs));
|
||||
save_item(NAME(m_mobvs));
|
||||
save_item(NAME(m_linevs));
|
||||
save_item(NAME(m_shel0h));
|
||||
save_item(NAME(m_mobst));
|
||||
save_item(NAME(m_shel1h));
|
||||
save_item(NAME(m_mobjv));
|
||||
}
|
||||
|
||||
void tunhunt_state::palette(palette_device &palette) const
|
||||
{
|
||||
/* Tunnel Hunt uses a combination of color PROMs and palette RAM to specify a 16 color
|
||||
* palette. Here, we manage only the mappings for alphanumeric characters and SHELL
|
||||
* graphics, which are unpacked ahead of time and drawn using MAME's drawgfx primitives.
|
||||
*/
|
||||
|
||||
// motion objects/box
|
||||
for (int i = 0; i < 0x10; i++)
|
||||
palette.set_pen_indirect(i, i);
|
||||
|
||||
/* AlphaNumerics (1bpp)
|
||||
* 2 bits of hilite select from 4 different background colors
|
||||
* Foreground color is always pen#4
|
||||
* Background color is mapped as follows:
|
||||
*/
|
||||
|
||||
// alpha hilite#0
|
||||
palette.set_pen_indirect(0x10, 0x0); // background color#0 (transparent)
|
||||
palette.set_pen_indirect(0x11, 0x4); // foreground color
|
||||
|
||||
// alpha hilite#1
|
||||
palette.set_pen_indirect(0x12, 0x5); // background color#1
|
||||
palette.set_pen_indirect(0x13, 0x4); // foreground color
|
||||
|
||||
// alpha hilite#2
|
||||
palette.set_pen_indirect(0x14, 0x6); // background color#2
|
||||
palette.set_pen_indirect(0x15, 0x4); // foreground color
|
||||
|
||||
// alpha hilite#3
|
||||
palette.set_pen_indirect(0x16, 0xf); // background color#3
|
||||
palette.set_pen_indirect(0x17, 0x4); // foreground color
|
||||
|
||||
/* shell graphics; these are either 1bpp (2 banks) or 2bpp. It isn't clear which.
|
||||
* In any event, the following pens are associated with the shell graphics:
|
||||
*/
|
||||
palette.set_pen_indirect(0x18, 0);
|
||||
palette.set_pen_indirect(0x19, 4);//1;
|
||||
}
|
||||
|
||||
/*
|
||||
Color Array RAM Assignments:
|
||||
Location
|
||||
0 Blanking, border
|
||||
1 Mot Obj (10) (D), Shell (01)
|
||||
2 Mot Obj (01) (G), Shell (10)
|
||||
3 Mot Obj (00) (W)
|
||||
4 Alpha & Shell (11) - shields
|
||||
5 Hilight 1
|
||||
6 Hilight 2
|
||||
8-E Lines (as normal) background
|
||||
F Hilight 3
|
||||
*/
|
||||
void tunhunt_state::set_pens()
|
||||
{
|
||||
/*
|
||||
The actual contents of the color PROMs (unused by this driver)
|
||||
are as follows:
|
||||
|
||||
D11 "blue/green"
|
||||
0000: 00 00 8b 0b fb 0f ff 0b
|
||||
00 00 0f 0f fb f0 f0 ff
|
||||
|
||||
C11 "red"
|
||||
0020: 00 f0 f0 f0 b0 b0 00 f0
|
||||
00 f0 f0 00 b0 00 f0 f0
|
||||
*/
|
||||
//const uint8_t *color_prom = memregion("proms")->base();
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
int color = m_paletteram[i];
|
||||
int const shade = 0xf^(color>>4);
|
||||
int red, green, blue;
|
||||
|
||||
color &= 0xf; // hue select
|
||||
switch (color)
|
||||
{
|
||||
default:
|
||||
case 0x0: red = 0xff; green = 0xff; blue = 0xff; break; // white
|
||||
case 0x1: red = 0xff; green = 0x00; blue = 0xff; break; // purple
|
||||
case 0x2: red = 0x00; green = 0x00; blue = 0xff; break; // blue
|
||||
case 0x3: red = 0x00; green = 0xff; blue = 0xff; break; // cyan
|
||||
case 0x4: red = 0x00; green = 0xff; blue = 0x00; break; // green
|
||||
case 0x5: red = 0xff; green = 0xff; blue = 0x00; break; // yellow
|
||||
case 0x6: red = 0xff; green = 0x00; blue = 0x00; break; // red
|
||||
case 0x7: red = 0x00; green = 0x00; blue = 0x00; break; // black?
|
||||
|
||||
case 0x8: red = 0xff; green = 0x7f; blue = 0x00; break; // orange
|
||||
case 0x9: red = 0x7f; green = 0xff; blue = 0x00; break; // ?
|
||||
case 0xa: red = 0x00; green = 0xff; blue = 0x7f; break; // ?
|
||||
case 0xb: red = 0x00; green = 0x7f; blue = 0xff; break; // ?
|
||||
case 0xc: red = 0xff; green = 0x00; blue = 0x7f; break; // ?
|
||||
case 0xd: red = 0x7f; green = 0x00; blue = 0xff; break; // ?
|
||||
case 0xe: red = 0xff; green = 0xaa; blue = 0xaa; break; // ?
|
||||
case 0xf: red = 0xaa; green = 0xaa; blue = 0xff; break; // ?
|
||||
}
|
||||
|
||||
// combine color components with shade value (0..0xf)
|
||||
#define APPLY_SHADE( C,S ) ((C*S)/0xf)
|
||||
red = APPLY_SHADE(red, shade);
|
||||
green = APPLY_SHADE(green, shade);
|
||||
blue = APPLY_SHADE(blue, shade);
|
||||
|
||||
m_palette->set_indirect_color(i, rgb_t(red, green, blue));
|
||||
}
|
||||
}
|
||||
|
||||
void tunhunt_state::draw_motion_object(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
/*
|
||||
* VSTRLO 0x1202
|
||||
* normally 0x02 (gameplay, attract1)
|
||||
* in attract2 (with "Tunnel Hunt" graphic), decrements from 0x2f down to 0x01
|
||||
* goes to 0x01 for some enemy shots
|
||||
*
|
||||
* MOBSC0 0x1080
|
||||
* MOBSC1 0x1081
|
||||
* always 0x00?
|
||||
*/
|
||||
|
||||
bitmap_ind16 &tmpbitmap = m_tmpbitmap;
|
||||
//int skip = m_mobst;
|
||||
const int x0 = 255 - m_mobjv;
|
||||
const int y0 = 255 - m_mobjh;
|
||||
|
||||
for (int line = 0; line < 64; line++)
|
||||
{
|
||||
int x = 0;
|
||||
const uint8_t *const source = &m_spriteram[line * 0x10];
|
||||
for (int span = 0; span < 0x10; span++)
|
||||
{
|
||||
const int span_data = source[span];
|
||||
if (span_data == 0xff) break;
|
||||
const int color = ((span_data >> 6) & 0x3) ^ 0x3;
|
||||
int count = (span_data & 0x1f) + 1;
|
||||
while (count-- && x < 256)
|
||||
tmpbitmap.pix(line, x++) = color;
|
||||
}
|
||||
while (x < 256)
|
||||
tmpbitmap.pix(line, x++) = 0;
|
||||
}
|
||||
|
||||
int scaley;
|
||||
switch (m_vstrlo)
|
||||
{
|
||||
case 0x01:
|
||||
scaley = (1 << 16) * 0.33; // seems correct
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
scaley = (1 << 16) * 0.50; // seems correct
|
||||
break;
|
||||
|
||||
default:
|
||||
scaley = (1 << 16) * m_vstrlo / 4; // ???
|
||||
break;
|
||||
}
|
||||
const int scalex = 1 << 16;
|
||||
|
||||
copyrozbitmap_trans(
|
||||
bitmap, cliprect, tmpbitmap,
|
||||
-x0 * scalex, // startx
|
||||
-y0 * scaley, // starty
|
||||
scalex, // incxx
|
||||
0, 0, // incxy, incyx
|
||||
scaley, // incyy
|
||||
false, // no wraparound
|
||||
0);
|
||||
}
|
||||
|
||||
void tunhunt_state::draw_box(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
/*
|
||||
This is unnecessarily slow, but the box priorities aren't completely understood,
|
||||
yet. Once understood, this function should be converted to use bitmap_fill with
|
||||
rectangular chunks instead of BITMAP_ADDR.
|
||||
|
||||
Tunnels:
|
||||
1080: 00 00 00 01 e7 18 ae 51 94 6b 88 77 83 7c 80 7f x0
|
||||
1480: 00 f0 17 00 22 22 5b 5b 75 75 81 81 86 86 89 89 y0
|
||||
1400: 00 00 97 ff f1 f1 b8 b8 9e 9e 92 92 8d 8d 8a 8a y1
|
||||
1280: 07 03 00 07 07 0c 0c 0d 0d 0e 0e 08 08 09 09 0a palette select
|
||||
|
||||
Color Bars:
|
||||
1080: 00 00 00 01 00 20 40 60 80 a0 c0 e0 01 2a 50 7a x0
|
||||
1480: 00 f0 00 00 40 40 40 40 40 40 40 40 00 00 00 00 y0
|
||||
1400: 00 00 00 ff ff ff ff ff ff ff ff ff 40 40 40 40 y1
|
||||
1280: 07 03 00 01 07 06 04 05 02 07 03 00 09 0a 0b 0c palette select
|
||||
->hue 06 02 ff 60 06 05 03 04 01 06 02 ff d2 00 c2 ff
|
||||
*/
|
||||
|
||||
for (int y = 0; y < 256; y++)
|
||||
{
|
||||
if (0xff - y >= cliprect.top() && 0xff - y <= cliprect.bottom())
|
||||
for (int x = 0; x < 256; x++)
|
||||
{
|
||||
int color = 0;
|
||||
int z = 0;
|
||||
for (int span = 0; span < 13; span++)
|
||||
{
|
||||
int const x0 = m_lineh[span];
|
||||
int const y0 = m_linevs[span];
|
||||
int const y1 = m_linev[span];
|
||||
|
||||
if (y >= y0 && y <= y1 && x >= x0 && x0 >= z)
|
||||
{
|
||||
color = m_linec[span] & 0xf;
|
||||
z = x0; // give priority to rightmost spans
|
||||
}
|
||||
}
|
||||
if (x >= cliprect.left() && x <= cliprect.right())
|
||||
bitmap.pix(0xff - y, x) = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "shell" graphics are 16x16 pixel tiles used for player shots and targeting cursor
|
||||
void tunhunt_state::draw_shell(bitmap_ind16 &bitmap,
|
||||
const rectangle &cliprect,
|
||||
int picture_code,
|
||||
int hposition,
|
||||
int vstart,
|
||||
int vstop,
|
||||
int vstretch,
|
||||
int hstretch )
|
||||
{
|
||||
if (hstretch)
|
||||
{
|
||||
for (int sx = 0; sx < 256; sx += 16)
|
||||
{
|
||||
for (int sy = 0; sy < 256; sy += 16)
|
||||
{
|
||||
m_gfxdecode->gfx(1)->transpen(bitmap, cliprect,
|
||||
picture_code,
|
||||
0, // color
|
||||
0, 0, // flip
|
||||
sx, sy, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
/*
|
||||
vstretch is normally 0x01
|
||||
|
||||
targeting cursor:
|
||||
hposition = 0x78
|
||||
vstart = 0x90
|
||||
vstop = 0x80
|
||||
|
||||
during grid test:
|
||||
vstretch = 0xff
|
||||
hposition = 0xff
|
||||
vstart = 0xff
|
||||
vstop = 0x00
|
||||
|
||||
*/
|
||||
|
||||
m_gfxdecode->gfx(1)->transpen(bitmap, cliprect,
|
||||
picture_code,
|
||||
0, // color
|
||||
0, 0, // flip
|
||||
255 - hposition - 16, vstart - 32, 0);
|
||||
}
|
||||
|
||||
uint32_t tunhunt_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
set_pens();
|
||||
|
||||
draw_box(bitmap, cliprect);
|
||||
|
||||
draw_motion_object(bitmap, cliprect);
|
||||
|
||||
draw_shell(bitmap, cliprect,
|
||||
m_shl0pc, // picture code
|
||||
m_shel0h, // hposition
|
||||
m_shl0v, // vstart
|
||||
m_shl0vs, // vstop
|
||||
m_shl0st, // vstretch
|
||||
m_control & 0x08); // hstretch
|
||||
|
||||
draw_shell(bitmap, cliprect,
|
||||
m_shl1pc, // picture code
|
||||
m_shel1h, // hposition
|
||||
m_shl1v, // vstart
|
||||
m_shl1vs, // vstop
|
||||
m_shl1st, // vstretch
|
||||
m_control & 0x10); // hstretch
|
||||
|
||||
rectangle cr = cliprect;
|
||||
if (cr.min_x < 192)
|
||||
cr.min_x = 192;
|
||||
|
||||
m_fg_tilemap->draw(screen, bitmap, cr, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
|
||||
/*************************************
|
||||
*
|
||||
@ -75,7 +525,7 @@ void tunhunt_state::control_w(uint8_t data)
|
||||
m_control = data;
|
||||
machine().bookkeeping().coin_counter_w(0, BIT(data, 0));
|
||||
machine().bookkeeping().coin_counter_w(1, BIT(data, 1));
|
||||
m_led = BIT(data , 6); /* start */
|
||||
m_led = BIT(data , 6); // start
|
||||
}
|
||||
|
||||
|
||||
@ -88,40 +538,18 @@ void tunhunt_state::control_w(uint8_t data)
|
||||
|
||||
uint8_t tunhunt_state::button_r(offs_t offset)
|
||||
{
|
||||
int data = ioport("IN0")->read();
|
||||
return ((data>>offset)&1)?0x00:0x80;
|
||||
int const data = m_in0->read();
|
||||
return ((data >> offset) & 1) ? 0x00 : 0x80;
|
||||
}
|
||||
|
||||
|
||||
uint8_t tunhunt_state::dsw2_0r()
|
||||
template <uint16_t Mask>
|
||||
uint8_t tunhunt_state::dsw2_r()
|
||||
{
|
||||
return (ioport("DSW")->read()&0x0100)?0x80:0x00;
|
||||
return (m_dsw->read()& Mask) ? 0x80 : 0x00;
|
||||
}
|
||||
|
||||
|
||||
uint8_t tunhunt_state::dsw2_1r()
|
||||
{
|
||||
return (ioport("DSW")->read()&0x0200)?0x80:0x00;
|
||||
}
|
||||
|
||||
|
||||
uint8_t tunhunt_state::dsw2_2r()
|
||||
{
|
||||
return (ioport("DSW")->read()&0x0400)?0x80:0x00;
|
||||
}
|
||||
|
||||
|
||||
uint8_t tunhunt_state::dsw2_3r()
|
||||
{
|
||||
return (ioport("DSW")->read()&0x0800)?0x80:0x00;
|
||||
}
|
||||
|
||||
|
||||
uint8_t tunhunt_state::dsw2_4r()
|
||||
{
|
||||
return (ioport("DSW")->read()&0x1000)?0x80:0x00;
|
||||
}
|
||||
|
||||
void tunhunt_state::machine_reset()
|
||||
{
|
||||
m_mobsc0 = 0;
|
||||
@ -159,7 +587,7 @@ void tunhunt_state::machine_reset()
|
||||
void tunhunt_state::main_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0x7fff);
|
||||
map(0x0000, 0x03ff).ram().share("workram"); /* Work RAM */
|
||||
map(0x0000, 0x03ff).ram().share(m_workram);
|
||||
|
||||
map(0x1080, 0x1080).lw8(NAME([this](uint8_t data) { m_mobsc0 = data; })); // SCAN ROM START FOR MOBJ (unused?)
|
||||
map(0x1081, 0x1081).lw8(NAME([this](uint8_t data) { m_mobsc1 = data; })); // (unused?)
|
||||
@ -179,18 +607,18 @@ void tunhunt_state::main_map(address_map &map)
|
||||
map(0x1481, 0x1481).lw8(NAME([this](uint8_t data) { m_shl1vs = data; }));
|
||||
map(0x1482, 0x1482).lw8(NAME([this](uint8_t data) { m_mobvs = data; })); // V STOP OF MOTION OBJECT (NORMAL SCREEN)
|
||||
map(0x1483, 0x148f).lw8(NAME([this](offs_t offset, uint8_t data) { m_linevs[offset] = data; })); // LINES VERT STOP
|
||||
map(0x1600, 0x160f).writeonly().share("paletteram"); // COLRAM (D7-D4 SHADE; D3-D0 COLOR)
|
||||
map(0x1600, 0x160f).writeonly().share(m_paletteram); // COLRAM (D7-D4 SHADE; D3-D0 COLOR)
|
||||
map(0x1800, 0x1800).lw8(NAME([this](uint8_t data) { m_shel0h = data; })); // SHELL H POSITON (NORMAL SCREEN)
|
||||
map(0x1802, 0x1802).lw8(NAME([this](uint8_t data) { m_mobst = data; })); // STARTING LINE FOR RAM SCAN ON MOBJ
|
||||
map(0x1a00, 0x1a00).lw8(NAME([this](uint8_t data) { m_shel1h = data; }));
|
||||
map(0x1c00, 0x1c00).lw8(NAME([this](uint8_t data) { m_mobjv = data; })); // V POSITION (SCREEN ON SIDE)
|
||||
map(0x1e00, 0x1eff).w(FUNC(tunhunt_state::videoram_w)).share("videoram"); /* ALPHA */
|
||||
map(0x1e00, 0x1eff).w(FUNC(tunhunt_state::videoram_w)).share(m_videoram); // ALPHA
|
||||
|
||||
map(0x2000, 0x2000).nopw(); /* watchdog */
|
||||
map(0x2000, 0x2000).nopw(); // watchdog
|
||||
map(0x2000, 0x2007).r(FUNC(tunhunt_state::button_r));
|
||||
map(0x2400, 0x2400).nopw(); /* INT ACK */
|
||||
map(0x2400, 0x2400).nopw(); // INT ACK
|
||||
map(0x2800, 0x2800).w(FUNC(tunhunt_state::control_w));
|
||||
map(0x2c00, 0x2fff).writeonly().share("spriteram");
|
||||
map(0x2c00, 0x2fff).writeonly().share(m_spriteram);
|
||||
|
||||
map(0x3000, 0x300f).rw("pokey1", FUNC(pokey_device::read), FUNC(pokey_device::write));
|
||||
map(0x4000, 0x400f).rw("pokey2", FUNC(pokey_device::read), FUNC(pokey_device::write));
|
||||
@ -283,29 +711,29 @@ static const gfx_layout alpha_layout =
|
||||
static const gfx_layout obj_layout =
|
||||
{
|
||||
16,16,
|
||||
8, /* number of objects */
|
||||
1, /* number of bitplanes */
|
||||
{ 4 }, /* plane offsets */
|
||||
8, // number of objects
|
||||
1, // number of bitplanes
|
||||
{ 4 }, // plane offsets
|
||||
{
|
||||
0x00+0,0x00+1,0x00+2,0x00+3,
|
||||
0x08+0,0x08+1,0x08+2,0x08+3,
|
||||
0x10+0,0x10+1,0x10+2,0x10+3,
|
||||
0x18+0,0x18+1,0x18+2,0x18+3
|
||||
}, /* x offsets */
|
||||
}, // x offsets
|
||||
{
|
||||
0x0*0x20, 0x1*0x20, 0x2*0x20, 0x3*0x20,
|
||||
0x4*0x20, 0x5*0x20, 0x6*0x20, 0x7*0x20,
|
||||
0x8*0x20, 0x9*0x20, 0xa*0x20, 0xb*0x20,
|
||||
0xc*0x20, 0xd*0x20, 0xe*0x20, 0xf*0x20
|
||||
}, /* y offsets */
|
||||
}, // y offsets
|
||||
0x200
|
||||
};
|
||||
|
||||
|
||||
static GFXDECODE_START( gfx_tunhunt )
|
||||
GFXDECODE_ENTRY( "gfx1", 0x000, alpha_layout, 0x10, 4 )
|
||||
GFXDECODE_ENTRY( "gfx2", 0x200, obj_layout, 0x18, 1 )
|
||||
GFXDECODE_ENTRY( "gfx2", 0x000, obj_layout, 0x18, 1 ) /* second bank, or second bitplane? */
|
||||
GFXDECODE_ENTRY( "chars", 0x000, alpha_layout, 0x10, 4 )
|
||||
GFXDECODE_ENTRY( "sprites", 0x200, obj_layout, 0x18, 1 )
|
||||
GFXDECODE_ENTRY( "sprites", 0x000, obj_layout, 0x18, 1 ) // second bank, or second bitplane?
|
||||
GFXDECODE_END
|
||||
|
||||
|
||||
@ -317,39 +745,39 @@ GFXDECODE_END
|
||||
|
||||
void tunhunt_state::tunhunt(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
M6502(config, m_maincpu, 12.096_MHz_XTAL/6); /* ??? */
|
||||
// basic machine hardware
|
||||
M6502(config, m_maincpu, 12.096_MHz_XTAL / 6); // ???
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &tunhunt_state::main_map);
|
||||
m_maincpu->set_periodic_int(FUNC(tunhunt_state::irq0_line_hold), attotime::from_hz(4*60)); /* 48V, 112V, 176V, 240V */
|
||||
m_maincpu->set_periodic_int(FUNC(tunhunt_state::irq0_line_hold), attotime::from_hz(4*60)); // 48V, 112V, 176V, 240V
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||
m_screen->set_refresh_hz(60);
|
||||
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
|
||||
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // not accurate
|
||||
m_screen->set_size(256, 256-16);
|
||||
m_screen->set_visarea(0, 255, 0, 255-16);
|
||||
m_screen->set_screen_update(FUNC(tunhunt_state::screen_update));
|
||||
m_screen->set_palette(m_palette);
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, m_palette, gfx_tunhunt);
|
||||
PALETTE(config, m_palette, FUNC(tunhunt_state::tunhunt_palette), 0x1a, 16);
|
||||
PALETTE(config, m_palette, FUNC(tunhunt_state::palette), 0x1a, 16);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
pokey_device &pokey1(POKEY(config, "pokey1", 12.096_MHz_XTAL/10));
|
||||
pokey_device &pokey1(POKEY(config, "pokey1", 12.096_MHz_XTAL / 10));
|
||||
pokey1.allpot_r().set_ioport("DSW");
|
||||
pokey1.set_output_rc(RES_K(1), CAP_U(0.047), 5.0);
|
||||
pokey1.add_route(ALL_OUTPUTS, "mono", 0.50);
|
||||
|
||||
pokey_device &pokey2(POKEY(config, "pokey2", 12.096_MHz_XTAL/10));
|
||||
pokey_device &pokey2(POKEY(config, "pokey2", 12.096_MHz_XTAL / 10));
|
||||
pokey2.pot_r<0>().set_ioport("IN1");
|
||||
pokey2.pot_r<1>().set_ioport("IN2");
|
||||
pokey2.pot_r<2>().set(FUNC(tunhunt_state::dsw2_0r));
|
||||
pokey2.pot_r<3>().set(FUNC(tunhunt_state::dsw2_1r));
|
||||
pokey2.pot_r<4>().set(FUNC(tunhunt_state::dsw2_2r));
|
||||
pokey2.pot_r<5>().set(FUNC(tunhunt_state::dsw2_3r));
|
||||
pokey2.pot_r<6>().set(FUNC(tunhunt_state::dsw2_4r));
|
||||
pokey2.pot_r<2>().set(FUNC(tunhunt_state::dsw2_r<0x100>));
|
||||
pokey2.pot_r<3>().set(FUNC(tunhunt_state::dsw2_r<0x200>));
|
||||
pokey2.pot_r<4>().set(FUNC(tunhunt_state::dsw2_r<0x400>));
|
||||
pokey2.pot_r<5>().set(FUNC(tunhunt_state::dsw2_r<0x800>));
|
||||
pokey2.pot_r<6>().set(FUNC(tunhunt_state::dsw2_r<0x1000>));
|
||||
pokey2.set_output_rc(RES_K(1), CAP_U(0.047), 5.0);
|
||||
pokey2.add_route(ALL_OUTPUTS, "mono", 0.50);
|
||||
}
|
||||
@ -392,44 +820,45 @@ ROM_START( tunhunt )
|
||||
ROM_LOAD( "005.ef1", 0x7000, 0x800, CRC(e17badf0) SHA1(6afbf517486340fe54b01fa26258877b2a8fc510) )
|
||||
ROM_LOAD( "006.d1", 0x7800, 0x800, CRC(c3ae8519) SHA1(2b2e49065bc38429894ef29a29ffc60f96e64840) )
|
||||
|
||||
ROM_REGION( 0x400, "gfx1", 0 ) /* alphanumeric characters */
|
||||
ROM_REGION( 0x400, "chars", 0 )
|
||||
ROM_LOAD( "019.c10", 0x000, 0x400, CRC(d6fd45a9) SHA1(c86ea3790c29c554199af8ad6f3d563dcb7723c7) )
|
||||
|
||||
ROM_REGION( 0x400, "gfx2", 0 ) /* "SHELL" objects (16x16 pixel sprites) */
|
||||
ROM_REGION( 0x400, "sprites", 0 ) // "SHELL" objects (16x16 pixel sprites)
|
||||
ROM_LOAD( "016.a8", 0x000, 0x200, CRC(830e6c34) SHA1(37a5eeb722dd80c4224c7f622b0edabb3ac1ca19) )
|
||||
ROM_LOAD( "017.b8", 0x200, 0x200, CRC(5bef8b5a) SHA1(bfd9c592a34ed4861a6ad76ef10ea0d9b76a92b2) )
|
||||
|
||||
ROM_REGION( 0x540, "proms", 0 )
|
||||
ROM_LOAD( "013.d11", 0x000, 0x020, CRC(66f1f5eb) SHA1(bcf5348ae328cf943d2bf6e38df727c0c4c466b7) ) /* hue: BBBBGGGG? */
|
||||
ROM_LOAD( "014.c11", 0x020, 0x020, CRC(662444b2) SHA1(2e510c1d9b7e34a3045048a46045e61fabaf918e) ) /* hue: RRRR----? */
|
||||
ROM_LOAD( "015.n4", 0x040, 0x100, CRC(00e224a0) SHA1(1a384ef488791c62566c91b18d6a1fb4a5def2ba) ) /* timing? */
|
||||
ROM_LOAD( "018.h9", 0x140, 0x400, CRC(6547c208) SHA1(f19c334f9b4a1cfcbc913c0920688db2730dded0) ) /* color lookup table? */
|
||||
ROM_LOAD( "013.d11", 0x000, 0x020, CRC(66f1f5eb) SHA1(bcf5348ae328cf943d2bf6e38df727c0c4c466b7) ) // hue: BBBBGGGG?
|
||||
ROM_LOAD( "014.c11", 0x020, 0x020, CRC(662444b2) SHA1(2e510c1d9b7e34a3045048a46045e61fabaf918e) ) // hue: RRRR----?
|
||||
ROM_LOAD( "015.n4", 0x040, 0x100, CRC(00e224a0) SHA1(1a384ef488791c62566c91b18d6a1fb4a5def2ba) ) // timing?
|
||||
ROM_LOAD( "018.h9", 0x140, 0x400, CRC(6547c208) SHA1(f19c334f9b4a1cfcbc913c0920688db2730dded0) ) // color lookup table?
|
||||
ROM_END
|
||||
|
||||
ROM_START( tunhuntc )
|
||||
ROM_REGION( 0x10000, "maincpu", 0 )
|
||||
ROM_LOAD( "001.lm1", 0x5000, 0x800, CRC(2601a3a4) SHA1(939bafc54576fdaccf688b49cc9d201b03feec3a) )
|
||||
ROM_LOAD( "002.k1", 0x5800, 0x800, CRC(29bbf3df) SHA1(4a0ec4cfab362a976d3962b347f687db45095cfd) )
|
||||
ROM_LOAD( "003.j1", 0x6000, 0x800, CRC(360c0f47) SHA1(8e3d815836504c7651812e0e26423b0c7045621c) ) /* bad crc? fails self-test */
|
||||
/* 0xcaa6bb2a: alternate prom (re)dumped by Al also fails, they simply modified the rom without fixing the checksum routine? */
|
||||
ROM_LOAD( "003.j1", 0x6000, 0x800, CRC(360c0f47) SHA1(8e3d815836504c7651812e0e26423b0c7045621c) ) // bad CRC? fails self-test
|
||||
// 0xcaa6bb2a: alternate PROM (re)dumped by Al also fails, they simply modified the ROM without fixing the checksum routine?
|
||||
ROM_LOAD( "004.fh1", 0x6800, 0x800, CRC(4d6c920e) SHA1(2ef274356f4b8a0170a267cd6a3758b2bda693b5) )
|
||||
ROM_LOAD( "005.ef1", 0x7000, 0x800, CRC(e17badf0) SHA1(6afbf517486340fe54b01fa26258877b2a8fc510) )
|
||||
ROM_LOAD( "006.d1", 0x7800, 0x800, CRC(c3ae8519) SHA1(2b2e49065bc38429894ef29a29ffc60f96e64840) )
|
||||
|
||||
ROM_REGION( 0x400, "gfx1", 0 ) /* alphanumeric characters */
|
||||
ROM_REGION( 0x400, "chars", 0 )
|
||||
ROM_LOAD( "019.c10", 0x000, 0x400, CRC(d6fd45a9) SHA1(c86ea3790c29c554199af8ad6f3d563dcb7723c7) )
|
||||
|
||||
ROM_REGION( 0x400, "gfx2", 0 ) /* "SHELL" objects (16x16 pixel sprites) */
|
||||
ROM_REGION( 0x400, "sprites", 0 ) // "SHELL" objects (16x16 pixel sprites)
|
||||
ROM_LOAD( "016.a8", 0x000, 0x200, CRC(830e6c34) SHA1(37a5eeb722dd80c4224c7f622b0edabb3ac1ca19) )
|
||||
ROM_LOAD( "017.b8", 0x200, 0x200, CRC(5bef8b5a) SHA1(bfd9c592a34ed4861a6ad76ef10ea0d9b76a92b2) )
|
||||
|
||||
ROM_REGION( 0x540, "proms", 0 )
|
||||
ROM_LOAD( "013.d11", 0x000, 0x020, CRC(66f1f5eb) SHA1(bcf5348ae328cf943d2bf6e38df727c0c4c466b7) ) /* hue: BBBBGGGG? */
|
||||
ROM_LOAD( "014.c11", 0x020, 0x020, CRC(662444b2) SHA1(2e510c1d9b7e34a3045048a46045e61fabaf918e) ) /* hue: RRRR----? */
|
||||
ROM_LOAD( "015.n4", 0x040, 0x100, CRC(00e224a0) SHA1(1a384ef488791c62566c91b18d6a1fb4a5def2ba) ) /* timing? */
|
||||
ROM_LOAD( "018.h9", 0x140, 0x400, CRC(6547c208) SHA1(f19c334f9b4a1cfcbc913c0920688db2730dded0) ) /* color lookup table? */
|
||||
ROM_LOAD( "013.d11", 0x000, 0x020, CRC(66f1f5eb) SHA1(bcf5348ae328cf943d2bf6e38df727c0c4c466b7) ) // hue: BBBBGGGG?
|
||||
ROM_LOAD( "014.c11", 0x020, 0x020, CRC(662444b2) SHA1(2e510c1d9b7e34a3045048a46045e61fabaf918e) ) // hue: RRRR----?
|
||||
ROM_LOAD( "015.n4", 0x040, 0x100, CRC(00e224a0) SHA1(1a384ef488791c62566c91b18d6a1fb4a5def2ba) ) // timing?
|
||||
ROM_LOAD( "018.h9", 0x140, 0x400, CRC(6547c208) SHA1(f19c334f9b4a1cfcbc913c0920688db2730dded0) ) // color lookup table?
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/*************************************
|
||||
@ -438,6 +867,5 @@ ROM_END
|
||||
*
|
||||
*************************************/
|
||||
|
||||
/* rom parent machine inp state init */
|
||||
GAME( 1979,tunhunt, 0, tunhunt, tunhunt, tunhunt_state, empty_init, ORIENTATION_SWAP_XY, "Atari", "Tunnel Hunt", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1979,tunhunt, 0, tunhunt, tunhunt, tunhunt_state, empty_init, ORIENTATION_SWAP_XY, "Atari", "Tunnel Hunt", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1981,tunhuntc, tunhunt, tunhunt, tunhunt, tunhunt_state, empty_init, ORIENTATION_SWAP_XY, "Atari (Centuri license)", "Tunnel Hunt (Centuri)", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -1,94 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Phil Stroffolino, David Haywood
|
||||
#ifndef MAME_ATARI_TUNHUNT_H
|
||||
#define MAME_ATARI_TUNHUNT_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
class tunhunt_state : public driver_device
|
||||
{
|
||||
public:
|
||||
tunhunt_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_screen(*this, "screen"),
|
||||
m_palette(*this, "palette"),
|
||||
m_workram(*this, "workram"),
|
||||
m_videoram(*this, "videoram"),
|
||||
m_spriteram(*this, "spriteram"),
|
||||
m_generic_paletteram_8(*this, "paletteram"),
|
||||
m_led(*this, "led0")
|
||||
{ }
|
||||
|
||||
void tunhunt(machine_config &config);
|
||||
|
||||
private:
|
||||
void control_w(uint8_t data);
|
||||
uint8_t button_r(offs_t offset);
|
||||
void videoram_w(offs_t offset, uint8_t data);
|
||||
uint8_t dsw2_0r();
|
||||
uint8_t dsw2_1r();
|
||||
uint8_t dsw2_2r();
|
||||
uint8_t dsw2_3r();
|
||||
uint8_t dsw2_4r();
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_fg_tile_info);
|
||||
|
||||
virtual void machine_start() override { m_led.resolve(); }
|
||||
virtual void video_start() override;
|
||||
void tunhunt_palette(palette_device &palette) const;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void set_pens();
|
||||
void draw_motion_object(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void draw_box(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void draw_shell(bitmap_ind16 &bitmap, const rectangle &cliprect, int picture_code,
|
||||
int hposition,int vstart,int vstop,int vstretch,int hstretch);
|
||||
void main_map(address_map &map);
|
||||
virtual void machine_reset() override;
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
required_shared_ptr<uint8_t> m_workram;
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_shared_ptr<uint8_t> m_generic_paletteram_8;
|
||||
output_finder<> m_led;
|
||||
|
||||
uint8_t m_control = 0;
|
||||
tilemap_t *m_fg_tilemap = nullptr;
|
||||
bitmap_ind16 m_tmpbitmap;
|
||||
|
||||
uint8_t m_mobsc0 = 0;
|
||||
uint8_t m_mobsc1 = 0;
|
||||
uint8_t m_lineh[13]{};
|
||||
uint8_t m_shl0st = 0;
|
||||
uint8_t m_shl1st = 0;
|
||||
uint8_t m_vstrlo = 0;
|
||||
uint8_t m_linesh = 0;
|
||||
uint8_t m_shl0pc = 0;
|
||||
uint8_t m_shl1pc = 0;
|
||||
uint8_t m_linec[13]{};
|
||||
uint8_t m_shl0v = 0;
|
||||
uint8_t m_shl1v = 0;
|
||||
uint8_t m_mobjh = 0;
|
||||
uint8_t m_linev[13]{};
|
||||
uint8_t m_shl0vs = 0;
|
||||
uint8_t m_shl1vs = 0;
|
||||
uint8_t m_mobvs = 0;
|
||||
uint8_t m_linevs[13]{};
|
||||
uint8_t m_shel0h = 0;
|
||||
uint8_t m_mobst = 0;
|
||||
uint8_t m_shel1h = 0;
|
||||
uint8_t m_mobjv = 0;
|
||||
};
|
||||
|
||||
#endif // MAME_ATARI_TUNHUNT_H
|
@ -1,374 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Phil Stroffolino, David Haywood
|
||||
/*************************************************************************
|
||||
|
||||
Atari Tunnel Hunt hardware
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "tunhunt.h"
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void tunhunt_state::videoram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_videoram[offset] = data;
|
||||
m_fg_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(tunhunt_state::get_fg_tile_info)
|
||||
{
|
||||
int attr = m_videoram[tile_index];
|
||||
int code = attr & 0x3f;
|
||||
int color = attr >> 6;
|
||||
int flags = color ? TILE_FORCE_LAYER0 : 0;
|
||||
|
||||
tileinfo.set(0, code, color, flags);
|
||||
}
|
||||
|
||||
void tunhunt_state::video_start()
|
||||
{
|
||||
/*
|
||||
Motion Object RAM contains 64 lines of run-length encoded data.
|
||||
We keep track of dirty lines and cache the expanded bitmap.
|
||||
With max RLE expansion, bitmap size is 256x64.
|
||||
*/
|
||||
|
||||
m_tmpbitmap.allocate(256, 64, m_screen->format());
|
||||
|
||||
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tunhunt_state::get_fg_tile_info)), TILEMAP_SCAN_COLS, 8, 8, 8, 32);
|
||||
|
||||
m_fg_tilemap->set_transparent_pen(0);
|
||||
m_fg_tilemap->set_scrollx(0, 64);
|
||||
|
||||
save_item(NAME(m_control));
|
||||
save_item(NAME(m_mobsc0));
|
||||
save_item(NAME(m_mobsc1));
|
||||
save_item(NAME(m_lineh));
|
||||
save_item(NAME(m_shl0st));
|
||||
save_item(NAME(m_shl1st));
|
||||
save_item(NAME(m_vstrlo));
|
||||
save_item(NAME(m_linesh));
|
||||
save_item(NAME(m_shl0pc));
|
||||
save_item(NAME(m_shl1pc));
|
||||
save_item(NAME(m_linec));
|
||||
save_item(NAME(m_shl0v));
|
||||
save_item(NAME(m_shl1v));
|
||||
save_item(NAME(m_mobjh));
|
||||
save_item(NAME(m_linev));
|
||||
save_item(NAME(m_shl0vs));
|
||||
save_item(NAME(m_shl1vs));
|
||||
save_item(NAME(m_mobvs));
|
||||
save_item(NAME(m_linevs));
|
||||
save_item(NAME(m_shel0h));
|
||||
save_item(NAME(m_mobst));
|
||||
save_item(NAME(m_shel1h));
|
||||
save_item(NAME(m_mobjv));
|
||||
}
|
||||
|
||||
void tunhunt_state::tunhunt_palette(palette_device &palette) const
|
||||
{
|
||||
/* Tunnel Hunt uses a combination of color proms and palette RAM to specify a 16 color
|
||||
* palette. Here, we manage only the mappings for alphanumeric characters and SHELL
|
||||
* graphics, which are unpacked ahead of time and drawn using MAME's drawgfx primitives.
|
||||
*/
|
||||
|
||||
/* motion objects/box */
|
||||
for (int i = 0; i < 0x10; i++)
|
||||
palette.set_pen_indirect(i, i);
|
||||
|
||||
/* AlphaNumerics (1bpp)
|
||||
* 2 bits of hilite select from 4 different background colors
|
||||
* Foreground color is always pen#4
|
||||
* Background color is mapped as follows:
|
||||
*/
|
||||
|
||||
/* alpha hilite#0 */
|
||||
palette.set_pen_indirect(0x10, 0x0); // background color#0 (transparent)
|
||||
palette.set_pen_indirect(0x11, 0x4); // foreground color
|
||||
|
||||
/* alpha hilite#1 */
|
||||
palette.set_pen_indirect(0x12, 0x5); // background color#1
|
||||
palette.set_pen_indirect(0x13, 0x4); // foreground color
|
||||
|
||||
/* alpha hilite#2 */
|
||||
palette.set_pen_indirect(0x14, 0x6); // background color#2
|
||||
palette.set_pen_indirect(0x15, 0x4); // foreground color
|
||||
|
||||
/* alpha hilite#3 */
|
||||
palette.set_pen_indirect(0x16, 0xf); // background color#3
|
||||
palette.set_pen_indirect(0x17, 0x4); // foreground color
|
||||
|
||||
/* shell graphics; these are either 1bpp (2 banks) or 2bpp. It isn't clear which.
|
||||
* In any event, the following pens are associated with the shell graphics:
|
||||
*/
|
||||
palette.set_pen_indirect(0x18, 0);
|
||||
palette.set_pen_indirect(0x19, 4);//1;
|
||||
}
|
||||
|
||||
/*
|
||||
Color Array Ram Assignments:
|
||||
Location
|
||||
0 Blanking, border
|
||||
1 Mot Obj (10) (D), Shell (01)
|
||||
2 Mot Obj (01) (G), Shell (10)
|
||||
3 Mot Obj (00) (W)
|
||||
4 Alpha & Shell (11) - shields
|
||||
5 Hilight 1
|
||||
6 Hilight 2
|
||||
8-E Lines (as normal) background
|
||||
F Hilight 3
|
||||
*/
|
||||
void tunhunt_state::set_pens()
|
||||
{
|
||||
/*
|
||||
The actual contents of the color proms (unused by this driver)
|
||||
are as follows:
|
||||
|
||||
D11 "blue/green"
|
||||
0000: 00 00 8b 0b fb 0f ff 0b
|
||||
00 00 0f 0f fb f0 f0 ff
|
||||
|
||||
C11 "red"
|
||||
0020: 00 f0 f0 f0 b0 b0 00 f0
|
||||
00 f0 f0 00 b0 00 f0 f0
|
||||
*/
|
||||
//const uint8_t *color_prom = memregion( "proms" )->base();
|
||||
int color;
|
||||
int shade;
|
||||
int red,green,blue;
|
||||
|
||||
for( int i=0; i<16; i++ )
|
||||
{
|
||||
color = m_generic_paletteram_8[i];
|
||||
shade = 0xf^(color>>4);
|
||||
|
||||
color &= 0xf; /* hue select */
|
||||
switch( color )
|
||||
{
|
||||
default:
|
||||
case 0x0: red = 0xff; green = 0xff; blue = 0xff; break; /* white */
|
||||
case 0x1: red = 0xff; green = 0x00; blue = 0xff; break; /* purple */
|
||||
case 0x2: red = 0x00; green = 0x00; blue = 0xff; break; /* blue */
|
||||
case 0x3: red = 0x00; green = 0xff; blue = 0xff; break; /* cyan */
|
||||
case 0x4: red = 0x00; green = 0xff; blue = 0x00; break; /* green */
|
||||
case 0x5: red = 0xff; green = 0xff; blue = 0x00; break; /* yellow */
|
||||
case 0x6: red = 0xff; green = 0x00; blue = 0x00; break; /* red */
|
||||
case 0x7: red = 0x00; green = 0x00; blue = 0x00; break; /* black? */
|
||||
|
||||
case 0x8: red = 0xff; green = 0x7f; blue = 0x00; break; /* orange */
|
||||
case 0x9: red = 0x7f; green = 0xff; blue = 0x00; break; /* ? */
|
||||
case 0xa: red = 0x00; green = 0xff; blue = 0x7f; break; /* ? */
|
||||
case 0xb: red = 0x00; green = 0x7f; blue = 0xff; break; /* ? */
|
||||
case 0xc: red = 0xff; green = 0x00; blue = 0x7f; break; /* ? */
|
||||
case 0xd: red = 0x7f; green = 0x00; blue = 0xff; break; /* ? */
|
||||
case 0xe: red = 0xff; green = 0xaa; blue = 0xaa; break; /* ? */
|
||||
case 0xf: red = 0xaa; green = 0xaa; blue = 0xff; break; /* ? */
|
||||
}
|
||||
|
||||
/* combine color components with shade value (0..0xf) */
|
||||
#define APPLY_SHADE( C,S ) ((C*S)/0xf)
|
||||
red = APPLY_SHADE(red,shade);
|
||||
green = APPLY_SHADE(green,shade);
|
||||
blue = APPLY_SHADE(blue,shade);
|
||||
|
||||
m_palette->set_indirect_color( i,rgb_t(red,green,blue) );
|
||||
}
|
||||
}
|
||||
|
||||
void tunhunt_state::draw_motion_object(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
/*
|
||||
* VSTRLO 0x1202
|
||||
* normally 0x02 (gameplay, attract1)
|
||||
* in attract2 (with "Tunnel Hunt" graphic), decrements from 0x2f down to 0x01
|
||||
* goes to 0x01 for some enemy shots
|
||||
*
|
||||
* MOBSC0 0x1080
|
||||
* MOBSC1 0x1081
|
||||
* always 0x00?
|
||||
*/
|
||||
|
||||
bitmap_ind16 &tmpbitmap = m_tmpbitmap;
|
||||
//int skip = m_mobst;
|
||||
const int x0 = 255 - m_mobjv;
|
||||
const int y0 = 255 - m_mobjh;
|
||||
|
||||
for (int line = 0; line < 64; line++)
|
||||
{
|
||||
int x = 0;
|
||||
const uint8_t *const source = &m_spriteram[line * 0x10];
|
||||
for (int span = 0; span < 0x10; span++)
|
||||
{
|
||||
const int span_data = source[span];
|
||||
if (span_data == 0xff) break;
|
||||
const int color = ((span_data >> 6) & 0x3) ^ 0x3;
|
||||
int count = (span_data & 0x1f) + 1;
|
||||
while (count-- && x < 256)
|
||||
tmpbitmap.pix(line, x++) = color;
|
||||
}
|
||||
while (x < 256)
|
||||
tmpbitmap.pix(line, x++) = 0;
|
||||
}
|
||||
|
||||
int scaley;
|
||||
switch (m_vstrlo)
|
||||
{
|
||||
case 0x01:
|
||||
scaley = (1 << 16) * 0.33; // seems correct
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
scaley = (1 << 16) * 0.50; // seems correct
|
||||
break;
|
||||
|
||||
default:
|
||||
scaley = (1 << 16) * m_vstrlo / 4; // ???
|
||||
break;
|
||||
}
|
||||
const int scalex = 1 << 16;
|
||||
|
||||
copyrozbitmap_trans(
|
||||
bitmap, cliprect, tmpbitmap,
|
||||
-x0 * scalex, // startx
|
||||
-y0 * scaley, // starty
|
||||
scalex, // incxx
|
||||
0, 0, // incxy, incyx
|
||||
scaley, // incyy
|
||||
false, // no wraparound
|
||||
0);
|
||||
}
|
||||
|
||||
void tunhunt_state::draw_box(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
/*
|
||||
This is unnecessarily slow, but the box priorities aren't completely understood,
|
||||
yet. Once understood, this function should be converted to use bitmap_fill with
|
||||
rectangular chunks instead of BITMAP_ADDR.
|
||||
|
||||
Tunnels:
|
||||
1080: 00 00 00 01 e7 18 ae 51 94 6b 88 77 83 7c 80 7f x0
|
||||
1480: 00 f0 17 00 22 22 5b 5b 75 75 81 81 86 86 89 89 y0
|
||||
1400: 00 00 97 ff f1 f1 b8 b8 9e 9e 92 92 8d 8d 8a 8a y1
|
||||
1280: 07 03 00 07 07 0c 0c 0d 0d 0e 0e 08 08 09 09 0a palette select
|
||||
|
||||
Color Bars:
|
||||
1080: 00 00 00 01 00 20 40 60 80 a0 c0 e0 01 2a 50 7a x0
|
||||
1480: 00 f0 00 00 40 40 40 40 40 40 40 40 00 00 00 00 y0
|
||||
1400: 00 00 00 ff ff ff ff ff ff ff ff ff 40 40 40 40 y1
|
||||
1280: 07 03 00 01 07 06 04 05 02 07 03 00 09 0a 0b 0c palette select
|
||||
->hue 06 02 ff 60 06 05 03 04 01 06 02 ff d2 00 c2 ff
|
||||
*/
|
||||
int span,x,y;
|
||||
int color;
|
||||
// rectangle bbox;
|
||||
int z;
|
||||
int x0,y0,y1;
|
||||
|
||||
for( y=0; y<256; y++ )
|
||||
{
|
||||
if (0xff-y >= cliprect.top() && 0xff-y <= cliprect.bottom())
|
||||
for( x=0; x<256; x++ )
|
||||
{
|
||||
color = 0;
|
||||
z = 0;
|
||||
for( span=0; span<13; span++ )
|
||||
{
|
||||
x0 = m_lineh[span];
|
||||
y0 = m_linevs[span];
|
||||
y1 = m_linev[span];
|
||||
|
||||
if( y>=y0 && y<=y1 && x>=x0 && x0>=z )
|
||||
{
|
||||
color = m_linec[span]&0xf;
|
||||
z = x0; /* give priority to rightmost spans */
|
||||
}
|
||||
}
|
||||
if (x >= cliprect.left() && x <= cliprect.right())
|
||||
bitmap.pix(0xff-y, x) = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* "shell" graphics are 16x16 pixel tiles used for player shots and targeting cursor */
|
||||
void tunhunt_state::draw_shell(bitmap_ind16 &bitmap,
|
||||
const rectangle &cliprect,
|
||||
int picture_code,
|
||||
int hposition,
|
||||
int vstart,
|
||||
int vstop,
|
||||
int vstretch,
|
||||
int hstretch )
|
||||
{
|
||||
if( hstretch )
|
||||
{
|
||||
int sx,sy;
|
||||
for( sx=0; sx<256; sx+=16 )
|
||||
{
|
||||
for( sy=0; sy<256; sy+=16 )
|
||||
{
|
||||
m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
|
||||
picture_code,
|
||||
0, /* color */
|
||||
0,0, /* flip */
|
||||
sx,sy,0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
/*
|
||||
vstretch is normally 0x01
|
||||
|
||||
targeting cursor:
|
||||
hposition = 0x78
|
||||
vstart = 0x90
|
||||
vstop = 0x80
|
||||
|
||||
during grid test:
|
||||
vstretch = 0xff
|
||||
hposition = 0xff
|
||||
vstart = 0xff
|
||||
vstop = 0x00
|
||||
|
||||
*/
|
||||
|
||||
m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
|
||||
picture_code,
|
||||
0, /* color */
|
||||
0,0, /* flip */
|
||||
255-hposition-16,vstart-32,0 );
|
||||
}
|
||||
|
||||
uint32_t tunhunt_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
set_pens();
|
||||
|
||||
draw_box(bitmap, cliprect);
|
||||
|
||||
draw_motion_object(bitmap, cliprect);
|
||||
|
||||
draw_shell(bitmap, cliprect,
|
||||
m_shl0pc, /* picture code */
|
||||
m_shel0h, /* hposition */
|
||||
m_shl0v, /* vstart */
|
||||
m_shl0vs, /* vstop */
|
||||
m_shl0st, /* vstretch */
|
||||
m_control&0x08 ); /* hstretch */
|
||||
|
||||
draw_shell(bitmap, cliprect,
|
||||
m_shl1pc, /* picture code */
|
||||
m_shel1h, /* hposition */
|
||||
m_shl1v, /* vstart */
|
||||
m_shl1vs, /* vstop */
|
||||
m_shl1st, /* vstretch */
|
||||
m_control&0x10 ); /* hstretch */
|
||||
|
||||
rectangle cr = cliprect;
|
||||
if( cr.min_x < 192 )
|
||||
cr.min_x = 192;
|
||||
|
||||
m_fg_tilemap->draw(screen, bitmap, cr, 0, 0);
|
||||
return 0;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Sebastien Monassa
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
Atari Video Pinball driver
|
||||
@ -18,19 +19,177 @@
|
||||
*************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "videopin.h"
|
||||
|
||||
#include "videopin_a.h"
|
||||
|
||||
#include "cpu/m6502/m6502.h"
|
||||
#include "machine/watchdog.h"
|
||||
#include "sound/discrete.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
#include "videopin.lh"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class videopin_state : public driver_device
|
||||
{
|
||||
public:
|
||||
videopin_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_discrete(*this, "discrete"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_screen(*this, "screen"),
|
||||
m_palette(*this, "palette"),
|
||||
m_video_ram(*this, "video_ram"),
|
||||
m_in(*this, "IN%u", 1U),
|
||||
m_leds(*this, "LED%02u", 1U)
|
||||
{ }
|
||||
|
||||
void videopin(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<discrete_device> m_discrete;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
required_shared_ptr<uint8_t> m_video_ram;
|
||||
required_ioport_array<2> m_in;
|
||||
output_finder<32> m_leds;
|
||||
|
||||
attotime m_time_pushed;
|
||||
attotime m_time_released;
|
||||
uint8_t m_prev = 0;
|
||||
uint8_t m_mask = 0;
|
||||
uint8_t m_ball_x = 0;
|
||||
uint8_t m_ball_y = 0;
|
||||
tilemap_t *m_bg_tilemap = nullptr;
|
||||
emu_timer *m_interrupt_timer = nullptr;
|
||||
|
||||
void main_map(address_map &map);
|
||||
|
||||
uint8_t misc_r();
|
||||
void led_w(uint8_t data);
|
||||
void ball_w(uint8_t data);
|
||||
void video_ram_w(offs_t offset, uint8_t data);
|
||||
void out1_w(uint8_t data);
|
||||
void out2_w(uint8_t data);
|
||||
void note_dvsr_w(uint8_t data);
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(get_memory_offset);
|
||||
TILE_GET_INFO_MEMBER(get_tile_info);
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
TIMER_CALLBACK_MEMBER(interrupt_callback);
|
||||
void update_plunger();
|
||||
double calc_plunger_pos();
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(videopin_state::get_memory_offset)
|
||||
{
|
||||
return num_rows * ((col + 16) % 48) + row;
|
||||
}
|
||||
|
||||
|
||||
TILE_GET_INFO_MEMBER(videopin_state::get_tile_info)
|
||||
{
|
||||
uint8_t const code = m_video_ram[tile_index];
|
||||
|
||||
tileinfo.set(0, code, 0, (code & 0x40) ? TILE_FLIPY : 0);
|
||||
}
|
||||
|
||||
|
||||
void videopin_state::video_start()
|
||||
{
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(videopin_state::get_tile_info)), tilemap_mapper_delegate(*this, FUNC(videopin_state::get_memory_offset)), 8, 8, 48, 32);
|
||||
|
||||
save_item(NAME(m_ball_x));
|
||||
save_item(NAME(m_ball_y));
|
||||
}
|
||||
|
||||
|
||||
uint32_t videopin_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_bg_tilemap->set_scrollx(0, -8); // account for delayed loading of shift reg C6
|
||||
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
|
||||
for (int row = 0; row < 32; row++)
|
||||
{
|
||||
for (int col = 0; col < 48; col++)
|
||||
{
|
||||
uint32_t const offset = m_bg_tilemap->memory_index(col, row);
|
||||
|
||||
if (m_video_ram[offset] & 0x80) // ball bit found
|
||||
{
|
||||
int x = 8 * col;
|
||||
int y = 8 * row;
|
||||
|
||||
x += 4; // account for delayed loading of flip-flop C4
|
||||
|
||||
rectangle rect(x, x + 15, y, y + 15);
|
||||
rect &= cliprect;
|
||||
|
||||
x -= m_ball_x;
|
||||
y -= m_ball_y;
|
||||
|
||||
// ball placement is still 0.5 pixels off but don't tell anyone
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
m_gfxdecode->gfx(1)->transpen(bitmap, rect,
|
||||
0, 0,
|
||||
0, 0,
|
||||
x + 16 * i,
|
||||
y + 16 * j, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // keep things simple and ignore the rest
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void videopin_state::ball_w(uint8_t data)
|
||||
{
|
||||
m_ball_x = data & 15;
|
||||
m_ball_y = data >> 4;
|
||||
}
|
||||
|
||||
|
||||
void videopin_state::video_ram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_video_ram[offset] = data;
|
||||
m_bg_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
|
||||
void videopin_state::update_plunger()
|
||||
{
|
||||
uint8_t val = ioport("IN2")->read();
|
||||
uint8_t const val = m_in[1]->read();
|
||||
|
||||
if (m_prev != val)
|
||||
{
|
||||
@ -82,7 +241,7 @@ void videopin_state::machine_reset()
|
||||
{
|
||||
m_interrupt_timer->adjust(m_screen->time_until_pos(32), 32);
|
||||
|
||||
/* both output latches are cleared on reset */
|
||||
// both output latches are cleared on reset
|
||||
|
||||
out1_w(0);
|
||||
out2_w(0);
|
||||
@ -108,15 +267,15 @@ uint8_t videopin_state::misc_r()
|
||||
// signals received. This results in the MPU displaying the
|
||||
// ball being shot onto the playfield at a certain speed.
|
||||
|
||||
uint8_t val = ioport("IN1")->read();
|
||||
uint8_t val = m_in[0]->read();
|
||||
|
||||
if (plunger >= 0.000 && plunger <= 0.001)
|
||||
{
|
||||
val &= ~1; /* PLUNGER1 */
|
||||
val &= ~1; // PLUNGER1
|
||||
}
|
||||
if (plunger >= 0.006 && plunger <= 0.007)
|
||||
{
|
||||
val &= ~2; /* PLUNGER2 */
|
||||
val &= ~2; // PLUNGER2
|
||||
}
|
||||
|
||||
return val;
|
||||
@ -140,7 +299,7 @@ void videopin_state::led_w(uint8_t data)
|
||||
};
|
||||
|
||||
// anode from 32V,64V,128V
|
||||
int a = m_screen->vpos() >> 5 & 7;
|
||||
int const a = m_screen->vpos() >> 5 & 7;
|
||||
|
||||
for (int c = 0; c < 4; c++)
|
||||
m_leds[matrix[a][c] - 1] = BIT(data, c);
|
||||
@ -151,14 +310,14 @@ void videopin_state::led_w(uint8_t data)
|
||||
|
||||
void videopin_state::out1_w(uint8_t data)
|
||||
{
|
||||
/* D0 => OCTAVE0 */
|
||||
/* D1 => OCTACE1 */
|
||||
/* D2 => OCTAVE2 */
|
||||
/* D3 => LOCKOUT */
|
||||
/* D4 => NMIMASK */
|
||||
/* D5 => NOT USED */
|
||||
/* D6 => NOT USED */
|
||||
/* D7 => NOT USED */
|
||||
// D0 => OCTAVE0
|
||||
// D1 => OCTACE1
|
||||
// D2 => OCTAVE2
|
||||
// D3 => LOCKOUT
|
||||
// D4 => NMIMASK
|
||||
// D5 => NOT USED
|
||||
// D6 => NOT USED
|
||||
// D7 => NOT USED
|
||||
|
||||
m_mask = ~data & 0x10;
|
||||
|
||||
@ -167,21 +326,21 @@ void videopin_state::out1_w(uint8_t data)
|
||||
|
||||
machine().bookkeeping().coin_lockout_global_w(~data & 0x08);
|
||||
|
||||
/* Convert octave data to divide value and write to sound */
|
||||
// Convert octave data to divide value and write to sound
|
||||
m_discrete->write(VIDEOPIN_OCTAVE_DATA, (0x01 << (~data & 0x07)) & 0xfe);
|
||||
}
|
||||
|
||||
|
||||
void videopin_state::out2_w(uint8_t data)
|
||||
{
|
||||
/* D0 => VOL0 */
|
||||
/* D1 => VOL1 */
|
||||
/* D2 => VOL2 */
|
||||
/* D3 => NOT USED */
|
||||
/* D4 => COIN CNTR */
|
||||
/* D5 => BONG */
|
||||
/* D6 => BELL */
|
||||
/* D7 => ATTRACT */
|
||||
// D0 => VOL0
|
||||
// D1 => VOL1
|
||||
// D2 => VOL2
|
||||
// D3 => NOT USED
|
||||
// D4 => COIN CNTR
|
||||
// D5 => BONG
|
||||
// D6 => BELL
|
||||
// D7 => ATTRACT
|
||||
|
||||
machine().bookkeeping().coin_counter_w(0, data & 0x10);
|
||||
|
||||
@ -194,7 +353,7 @@ void videopin_state::out2_w(uint8_t data)
|
||||
|
||||
void videopin_state::note_dvsr_w(uint8_t data)
|
||||
{
|
||||
/* note data */
|
||||
// note data
|
||||
m_discrete->write(VIDEOPIN_NOTE_DATA, ~data &0xff);
|
||||
}
|
||||
|
||||
@ -208,7 +367,7 @@ void videopin_state::note_dvsr_w(uint8_t data)
|
||||
void videopin_state::main_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x01ff).ram();
|
||||
map(0x0200, 0x07ff).ram().w(FUNC(videopin_state::video_ram_w)).share("video_ram");
|
||||
map(0x0200, 0x07ff).ram().w(FUNC(videopin_state::video_ram_w)).share(m_video_ram);
|
||||
map(0x0800, 0x0800).r(FUNC(videopin_state::misc_r)).w(FUNC(videopin_state::note_dvsr_w));
|
||||
map(0x0801, 0x0801).w(FUNC(videopin_state::led_w));
|
||||
map(0x0802, 0x0802).w("watchdog", FUNC(watchdog_timer_device::reset_w));
|
||||
@ -229,7 +388,7 @@ void videopin_state::main_map(address_map &map)
|
||||
*************************************/
|
||||
|
||||
static INPUT_PORTS_START( videopin )
|
||||
PORT_START("IN0") /* IN0 */
|
||||
PORT_START("IN0") // IN0
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Left Flipper") PORT_CODE(KEYCODE_LCONTROL)
|
||||
@ -239,7 +398,7 @@ static INPUT_PORTS_START( videopin )
|
||||
PORT_SERVICE( 0x40, IP_ACTIVE_LOW )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
|
||||
PORT_START("DSW") /* IN1 */
|
||||
PORT_START("DSW") // IN1
|
||||
PORT_DIPNAME( 0xc0, 0x80, DEF_STR( Coinage ) ) PORT_DIPLOCATION("DSW:8,7")
|
||||
PORT_DIPSETTING( 0xc0, DEF_STR( 2C_1C ) )
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( 1C_1C ) )
|
||||
@ -263,9 +422,9 @@ static INPUT_PORTS_START( videopin )
|
||||
PORT_DIPSETTING( 0x00, "180000 (3 balls) / 300000 (5 balls)" )
|
||||
PORT_DIPSETTING( 0x01, "210000 (3 balls) / 350000 (5 balls)" )
|
||||
|
||||
PORT_START("IN1") /* IN2 */
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) /* PLUNGER 1 */
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_CUSTOM ) /* PLUNGER 2 */
|
||||
PORT_START("IN1") // IN2
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) // PLUNGER 1
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_CUSTOM ) // PLUNGER 2
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
@ -298,22 +457,6 @@ INPUT_PORTS_END
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static const gfx_layout tile_layout =
|
||||
{
|
||||
8, 8,
|
||||
64,
|
||||
1,
|
||||
{ 0 },
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7
|
||||
},
|
||||
{
|
||||
0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
|
||||
},
|
||||
0x40
|
||||
};
|
||||
|
||||
|
||||
static const gfx_layout ball_layout =
|
||||
{
|
||||
16, 16,
|
||||
@ -334,8 +477,8 @@ static const gfx_layout ball_layout =
|
||||
|
||||
|
||||
static GFXDECODE_START( gfx_videopin )
|
||||
GFXDECODE_ENTRY( "gfx1", 0x0000, tile_layout, 0, 1 )
|
||||
GFXDECODE_ENTRY( "gfx2", 0x0000, ball_layout, 0, 1 )
|
||||
GFXDECODE_ENTRY( "tiles", 0x0000, gfx_8x8x1, 0, 1 )
|
||||
GFXDECODE_ENTRY( "ball", 0x0000, ball_layout, 0, 1 )
|
||||
GFXDECODE_END
|
||||
|
||||
|
||||
@ -348,13 +491,13 @@ GFXDECODE_END
|
||||
|
||||
void videopin_state::videopin(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
M6502(config, m_maincpu, 12096000 / 16);
|
||||
// basic machine hardware
|
||||
M6502(config, m_maincpu, 12'096'000 / 16);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &videopin_state::main_map);
|
||||
|
||||
WATCHDOG_TIMER(config, "watchdog");
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||
m_screen->set_refresh_hz(60);
|
||||
m_screen->set_size(304, 263);
|
||||
@ -366,7 +509,7 @@ void videopin_state::videopin(machine_config &config)
|
||||
|
||||
PALETTE(config, m_palette, palette_device::MONOCHROME);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
DISCRETE(config, m_discrete, videopin_discrete).add_route(ALL_OUTPUTS, "mono", 1.0);
|
||||
@ -403,15 +546,15 @@ ROM_START( videopin )
|
||||
ROM_LOAD_NIB_HIGH( "34241-01.f0", 0x3c00, 0x0400, CRC(5bfb83da) SHA1(9f392b0d4a972b6ae15ec12913a7e66761f4175d) )
|
||||
ROM_RELOAD( 0xfc00, 0x0400 )
|
||||
|
||||
ROM_REGION( 0x0200, "gfx1", 0 ) /* tiles */
|
||||
ROM_REGION( 0x0200, "tiles", 0 )
|
||||
ROM_LOAD_NIB_LOW ( "34259-01.d5", 0x0000, 0x0200, CRC(6cd98c06) SHA1(48bf077b7abbd2f529a19bdf85700b93014f39f9) )
|
||||
ROM_LOAD_NIB_HIGH( "34258-01.c5", 0x0000, 0x0200, CRC(91a5f117) SHA1(03ac6b0b3da0ed5faf1ba6695d16918d12ceeff5) )
|
||||
|
||||
ROM_REGION( 0x0020, "gfx2", 0 ) /* ball */
|
||||
ROM_REGION( 0x0020, "ball", 0 )
|
||||
ROM_LOAD( "34257-01.m1", 0x0000, 0x0020, CRC(50245866) SHA1(b0692bc8d44f127f6e7182a1ce75a785e22ac5b9) )
|
||||
|
||||
ROM_REGION( 0x0100, "proms", 0 )
|
||||
ROM_LOAD( "9402-01.h4", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) ) /* sync */
|
||||
ROM_REGION( 0x0100, "sync_prom", 0 )
|
||||
ROM_LOAD( "9402-01.h4", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) )
|
||||
ROM_END
|
||||
|
||||
// This is an even later revision (marked -02) with 4 EPROMs (4096x8 according to manual, while 2048x8 in reality)
|
||||
@ -423,15 +566,15 @@ ROM_START( videopina )
|
||||
ROM_LOAD( "034256-01.k2", 0x3800, 0x0800, CRC(9f24428c) SHA1(df35225afebb4cc18a593ec665e94f677b3606ee) )
|
||||
ROM_COPY( "maincpu" , 0x3c00, 0xfc00, 0x400 )
|
||||
|
||||
ROM_REGION( 0x0200, "gfx1", 0 ) // tiles
|
||||
ROM_REGION( 0x0200, "tiles", 0 )
|
||||
ROM_LOAD_NIB_LOW ( "34259-01.d5", 0x0000, 0x0200, CRC(6cd98c06) SHA1(48bf077b7abbd2f529a19bdf85700b93014f39f9) )
|
||||
ROM_LOAD_NIB_HIGH( "34258-01.c5", 0x0000, 0x0200, CRC(91a5f117) SHA1(03ac6b0b3da0ed5faf1ba6695d16918d12ceeff5) )
|
||||
|
||||
ROM_REGION( 0x0020, "gfx2", 0 ) // ball
|
||||
ROM_REGION( 0x0020, "ball", 0 )
|
||||
ROM_LOAD( "34257-01.m1", 0x0000, 0x0020, CRC(50245866) SHA1(b0692bc8d44f127f6e7182a1ce75a785e22ac5b9) )
|
||||
|
||||
ROM_REGION( 0x0100, "proms", 0 )
|
||||
ROM_LOAD( "9402-01.h4", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) ) // sync
|
||||
ROM_REGION( 0x0100, "sync_prom", 0 )
|
||||
ROM_LOAD( "9402-01.h4", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( solarwar )
|
||||
@ -455,17 +598,19 @@ ROM_START( solarwar )
|
||||
ROM_LOAD_NIB_HIGH( "36158-02.f0", 0x3c00, 0x0400, CRC(2606b87e) SHA1(ea72e36837eccf29cd5c82fe9a6a018a1a94730c) )
|
||||
ROM_RELOAD( 0xfc00, 0x0400 )
|
||||
|
||||
ROM_REGION( 0x0200, "gfx1", 0 ) /* tiles */
|
||||
ROM_REGION( 0x0200, "tiles", 0 )
|
||||
ROM_LOAD_NIB_LOW ( "34259-01.d5", 0x0000, 0x0200, CRC(6cd98c06) SHA1(48bf077b7abbd2f529a19bdf85700b93014f39f9) )
|
||||
ROM_LOAD_NIB_HIGH( "34258-01.c5", 0x0000, 0x0200, CRC(91a5f117) SHA1(03ac6b0b3da0ed5faf1ba6695d16918d12ceeff5) )
|
||||
|
||||
ROM_REGION( 0x0020, "gfx2", 0 ) /* ball */
|
||||
ROM_REGION( 0x0020, "ball", 0 )
|
||||
ROM_LOAD( "34257-01.m1", 0x0000, 0x0020, CRC(50245866) SHA1(b0692bc8d44f127f6e7182a1ce75a785e22ac5b9) )
|
||||
|
||||
ROM_REGION( 0x0100, "proms", 0 )
|
||||
ROM_LOAD( "9402-01.h4", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) ) /* sync */
|
||||
ROM_REGION( 0x0100, "sync_prom", 0 )
|
||||
ROM_LOAD( "9402-01.h4", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
@ -474,5 +619,5 @@ ROM_END
|
||||
*************************************/
|
||||
|
||||
GAMEL( 1979, videopin, 0, videopin, videopin, videopin_state, empty_init, ROT270, "Atari", "Video Pinball (16 PROMs version)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK, layout_videopin )
|
||||
GAMEL( 1979, videopina, videopin, videopin, videopin, videopin_state, empty_init, ROT270, "Atari", "Video Pinball (4 ROMs version)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK, layout_videopin )
|
||||
GAMEL( 1979, solarwar, 0, videopin, solarwar, videopin_state, empty_init, ROT270, "Atari", "Solar War", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK, layout_videopin )
|
||||
GAMEL( 1979, videopina, videopin, videopin, videopin, videopin_state, empty_init, ROT270, "Atari", "Video Pinball (4 ROMs version)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK, layout_videopin )
|
||||
GAMEL( 1979, solarwar, 0, videopin, solarwar, videopin_state, empty_init, ROT270, "Atari", "Solar War", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK, layout_videopin )
|
||||
|
@ -1,90 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Sebastien Monassa
|
||||
/*************************************************************************
|
||||
|
||||
Atari Video Pinball hardware
|
||||
|
||||
*************************************************************************/
|
||||
#ifndef MAME_ATARI_VIDEOPIN_H
|
||||
#define MAME_ATARI_VIDEOPIN_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sound/discrete.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
/* Discrete Sound Input Nodes */
|
||||
#define VIDEOPIN_OCTAVE_DATA NODE_01
|
||||
#define VIDEOPIN_NOTE_DATA NODE_02
|
||||
#define VIDEOPIN_BELL_EN NODE_03
|
||||
#define VIDEOPIN_BONG_EN NODE_04
|
||||
#define VIDEOPIN_ATTRACT_EN NODE_05
|
||||
#define VIDEOPIN_VOL_DATA NODE_06
|
||||
|
||||
|
||||
class videopin_state : public driver_device
|
||||
{
|
||||
public:
|
||||
videopin_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_discrete(*this, "discrete"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_screen(*this, "screen"),
|
||||
m_palette(*this, "palette"),
|
||||
m_video_ram(*this, "video_ram"),
|
||||
m_leds(*this, "LED%02u", 1U)
|
||||
{ }
|
||||
|
||||
void videopin(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
void main_map(address_map &map);
|
||||
|
||||
uint8_t misc_r();
|
||||
void led_w(uint8_t data);
|
||||
void ball_w(uint8_t data);
|
||||
void video_ram_w(offs_t offset, uint8_t data);
|
||||
void out1_w(uint8_t data);
|
||||
void out2_w(uint8_t data);
|
||||
void note_dvsr_w(uint8_t data);
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(get_memory_offset);
|
||||
TILE_GET_INFO_MEMBER(get_tile_info);
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
TIMER_CALLBACK_MEMBER(interrupt_callback);
|
||||
void update_plunger();
|
||||
double calc_plunger_pos();
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<discrete_device> m_discrete;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
required_shared_ptr<uint8_t> m_video_ram;
|
||||
output_finder<32> m_leds;
|
||||
|
||||
attotime m_time_pushed;
|
||||
attotime m_time_released;
|
||||
uint8_t m_prev = 0;
|
||||
uint8_t m_mask = 0;
|
||||
int m_ball_x = 0;
|
||||
int m_ball_y = 0;
|
||||
tilemap_t* m_bg_tilemap = nullptr;
|
||||
emu_timer *m_interrupt_timer = nullptr;
|
||||
};
|
||||
|
||||
/*----------- defined in audio/videopin.c -----------*/
|
||||
DISCRETE_SOUND_EXTERN( videopin_discrete );
|
||||
|
||||
#endif // MAME_ATARI_VIDEOPIN_H
|
@ -1,14 +1,14 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Derrick Renaud
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
audio\videopin.c
|
||||
atari\videopin_a.cpp
|
||||
|
||||
*************************************************************************/
|
||||
#include "emu.h"
|
||||
#include "videopin.h"
|
||||
#include "sound/discrete.h"
|
||||
|
||||
#include "videopin_a.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* videopin Sound System Analog emulation */
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
DISCRETE_SOUND_START(videopin_discrete)
|
||||
/************************************************/
|
||||
/* videopin Effects Relataive Gain Table */
|
||||
/* videopin Effects Relative Gain Table */
|
||||
/* */
|
||||
/* Effect V-ampIn Gain ratio Relative */
|
||||
/* Vol0 3.8 10/(10+50) 1000.0 */
|
||||
@ -83,11 +83,11 @@ DISCRETE_SOUND_START(videopin_discrete)
|
||||
|
||||
/************************************************/
|
||||
/* Bell is Hsync/16 with an R/C decay amplitude */
|
||||
/* the 1uF cap is rapidally charged when BELL */
|
||||
/* is enabled, then dischaged through the 1M */
|
||||
/* the 1uF cap is rapidly charged when BELL */
|
||||
/* is enabled, then discharged through the 1M */
|
||||
/* resistor when disabled. */
|
||||
/* We use 180 phase because of inverter Q17, */
|
||||
/* but it rally has no effect on sound. */
|
||||
/* but it really has no effect on sound. */
|
||||
/************************************************/
|
||||
DISCRETE_RCDISC2(NODE_30, VIDEOPIN_BELL_EN, 740.2, 1, 0, 1e6, 1e-6)
|
||||
DISCRETE_SQUAREWFIX(VIDEOPIN_BELL_SND, VIDEOPIN_BELL_EN, 15750.0/16.0, NODE_30, 50.0, 0, 180.0)
|
||||
|
22
src/mame/atari/videopin_a.h
Normal file
22
src/mame/atari/videopin_a.h
Normal file
@ -0,0 +1,22 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Derrick Renaud
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Video Pinball Audio
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "sound/discrete.h"
|
||||
|
||||
// discrete sound input nodes
|
||||
|
||||
#define VIDEOPIN_OCTAVE_DATA NODE_01
|
||||
#define VIDEOPIN_NOTE_DATA NODE_02
|
||||
#define VIDEOPIN_BELL_EN NODE_03
|
||||
#define VIDEOPIN_BONG_EN NODE_04
|
||||
#define VIDEOPIN_ATTRACT_EN NODE_05
|
||||
#define VIDEOPIN_VOL_DATA NODE_06
|
||||
|
||||
|
||||
DISCRETE_SOUND_EXTERN( videopin_discrete );
|
@ -1,103 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Sebastien Monassa
|
||||
/*************************************************************************
|
||||
|
||||
Atari Video Pinball video emulation
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "videopin.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(videopin_state::get_memory_offset)
|
||||
{
|
||||
return num_rows * ((col + 16) % 48) + row;
|
||||
}
|
||||
|
||||
|
||||
TILE_GET_INFO_MEMBER(videopin_state::get_tile_info)
|
||||
{
|
||||
uint8_t code = m_video_ram[tile_index];
|
||||
|
||||
tileinfo.set(0, code, 0, (code & 0x40) ? TILE_FLIPY : 0);
|
||||
}
|
||||
|
||||
|
||||
void videopin_state::video_start()
|
||||
{
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(videopin_state::get_tile_info)), tilemap_mapper_delegate(*this, FUNC(videopin_state::get_memory_offset)), 8, 8, 48, 32);
|
||||
|
||||
save_item(NAME(m_ball_x));
|
||||
save_item(NAME(m_ball_y));
|
||||
}
|
||||
|
||||
|
||||
uint32_t videopin_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int col;
|
||||
int row;
|
||||
|
||||
m_bg_tilemap->set_scrollx(0, -8); /* account for delayed loading of shift reg C6 */
|
||||
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
|
||||
for (row = 0; row < 32; row++)
|
||||
{
|
||||
for (col = 0; col < 48; col++)
|
||||
{
|
||||
uint32_t offset = m_bg_tilemap->memory_index(col, row);
|
||||
|
||||
if (m_video_ram[offset] & 0x80) /* ball bit found */
|
||||
{
|
||||
int x = 8 * col;
|
||||
int y = 8 * row;
|
||||
|
||||
int i;
|
||||
int j;
|
||||
|
||||
x += 4; /* account for delayed loading of flip-flop C4 */
|
||||
|
||||
rectangle rect(x, x + 15, y, y + 15);
|
||||
rect &= cliprect;
|
||||
|
||||
x -= m_ball_x;
|
||||
y -= m_ball_y;
|
||||
|
||||
/* ball placement is still 0.5 pixels off but don't tell anyone */
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
m_gfxdecode->gfx(1)->transpen(bitmap,rect,
|
||||
0, 0,
|
||||
0, 0,
|
||||
x + 16 * i,
|
||||
y + 16 * j, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* keep things simple and ignore the rest */
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void videopin_state::ball_w(uint8_t data)
|
||||
{
|
||||
m_ball_x = data & 15;
|
||||
m_ball_y = data >> 4;
|
||||
}
|
||||
|
||||
|
||||
void videopin_state::video_ram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_video_ram[offset] = data;
|
||||
m_bg_tilemap->mark_tile_dirty(offset);
|
||||
}
|
@ -82,6 +82,10 @@ Versions known to exist but not dumped:
|
||||
PCBs were shown running (and could be played) at a Cave fan show known as Cave Festival 2006. There are
|
||||
videos of the game being played floating around the internet and on YouTube. AKA DDP-CV or DDP BLUE ROM
|
||||
|
||||
NOTE: Easter egg in Fereron SOS / Dangun Feveron:
|
||||
Insert a coin and with the joystick move: Down, Up, Right, Left, Up, Down, Left, Right
|
||||
If you did the above right, you'll hear a MEOW sound. Start the game and your ship is now a cat!
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
Loading…
Reference in New Issue
Block a user