- pacman/pacman.cpp: redumped PROMs for mspacmane and pacmanmr [IZ8DWF]

- rare/btoads.cpp: consolidated driver in single file
This commit is contained in:
Ivan Vangelista 2024-06-12 18:44:33 +02:00
parent ba3d767ecc
commit 4fd79b3fc0
6 changed files with 640 additions and 696 deletions

View File

@ -5573,11 +5573,11 @@ ROM_START( pacmanmr ) // PCB is marked "PAC/M" on component side
ROM_REGION( 0x0120, "proms", 0 )
ROM_LOAD( "pacm.8h", 0x0000, 0x0020, CRC(2c3cc909) SHA1(32d68d4cfdf9f3e7351353428d268c763e809c63) )
ROM_LOAD( "pacm.4a", 0x0020, 0x0100, CRC(4c8e83a4) SHA1(e522cbc6c14bc481f2e97f1a7224c66bb283f553) )
ROM_LOAD( "pacm.4a", 0x0020, 0x0100, CRC(3eb3a8e4) SHA1(19097b5f60d1030f8b82d9f1d3a241f93e5c75d6) )
ROM_REGION( 0x0200, "namco", 0 ) // Sound PROMs
ROM_LOAD( "pacm.1m", 0x0000, 0x0100, CRC(4e8b3b74) SHA1(aa427aa45373e9a1e6a1155b4bc7bbd97f74f3d8) )
ROM_LOAD( "pacm.3m", 0x0100, 0x0100, CRC(05197026) SHA1(9b71fb175331bbc12e43441ecfad75b633e2f953) ) // Timing - not used
ROM_LOAD( "pacm.1m", 0x0000, 0x0100, CRC(3cb61034) SHA1(2f24b88839aee107a0ac1064f8bc4853933f5205) )
ROM_LOAD( "pacm.3m", 0x0100, 0x0100, CRC(77245b66) SHA1(0c4d0bee858b97632411c440bea6948a74759746) ) // Timing - not used
ROM_END
// this bootleg on Pacman hardware has half as many tiles as the original and some gfx / animations
@ -6432,11 +6432,11 @@ ROM_START( mspacmane )
ROM_REGION( 0x0120, "proms", 0 )
ROM_LOAD( "8h", 0x0000, 0x0020, CRC(2c3cc909) SHA1(32d68d4cfdf9f3e7351353428d268c763e809c63) )
ROM_LOAD( "4a", 0x0020, 0x0100, CRC(4c8e83a4) SHA1(e522cbc6c14bc481f2e97f1a7224c66bb283f553) )
ROM_LOAD( "4a", 0x0020, 0x0100, CRC(3eb3a8e4) SHA1(19097b5f60d1030f8b82d9f1d3a241f93e5c75d6) )
ROM_REGION( 0x0200, "namco", 0 ) // Sound PROMs
ROM_LOAD( "1m", 0x0000, 0x0100, CRC(7b1f9b71) SHA1(5ef72bbdfb72db3eb1175fed652a761938eeb6cd) )
ROM_LOAD( "3m", 0x0100, 0x0100, CRC(05197026) SHA1(9b71fb175331bbc12e43441ecfad75b633e2f953) ) // Timing - not used
ROM_LOAD( "1m", 0x0000, 0x0100, CRC(0922b031) SHA1(1eb9e1f8e6b027ca80a0ee0b391d4e904e9ea49b) )
ROM_LOAD( "3m", 0x0100, 0x0100, CRC(77245b66) SHA1(0c4d0bee858b97632411c440bea6948a74759746) ) // Timing - not used
ROM_END
ROM_START( mspacmane2 ) // G-GA-2 + G-GB-2 PCBs

View File

@ -1515,6 +1515,7 @@ ROM_START( pleiadce )
ROM_LOAD( "7611-5.26", 0x0100, 0x0100, CRC(7a1bcb1e) SHA1(bdfab316ea26e2063879e7aa78b6ae2b55eb95c8) ) // palette high bits
ROM_END
// TIM-8001 + TIM-8002 PCBs. Sound section seems more similar to Phoenix (MM6221AA instead of TMS3615, etc)
ROM_START( pleiadsgmp )
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "ic45", 0x0000, 0x0800, CRC(6a6dcabf) SHA1(cec3669674feb1ea86248d181f83f60a6affe68d) )

View File

@ -485,7 +485,7 @@ inline int pleiads_sound_device::tone4(int samplerate)
/*****************************************************************************
* Noise comes from a shift register (4006) hooked up just like in Phoenix.
* Difference: the clock frequecy is toggled between two values only by
* Difference: the clock frequency is toggled between two values only by
* bit 4 of latch A. The output of the first shift register can be zapped(?)
* by some control line (IC87 in Pop Flamer: not yet implemented)
*****************************************************************************/

View File

@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
// copyright-holders: Aaron Giles
/*************************************************************************
BattleToads
@ -9,15 +10,608 @@
**************************************************************************/
#include "emu.h"
#include "btoads.h"
#include "cpu/tms34010/tms34010.h"
#include "cpu/z80/z80.h"
#include "machine/nvram.h"
#include "sound/bsmt2000.h"
#include "video/tlc34076.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#define CPU_CLOCK XTAL(64'000'000)
#define VIDEO_CLOCK XTAL(20'000'000)
#define SOUND_CLOCK XTAL(24'000'000)
namespace {
class btoads_state : public driver_device
{
public:
btoads_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_vram_fg(*this, "vram_fg%u", 0U, 0x200000U, ENDIANNESS_LITTLE),
m_vram_fg_data(*this, "vram_fg_data"),
m_vram_bg(*this, "vram_bg%u", 0U, 0x400000U, ENDIANNESS_LITTLE),
m_sprite_scale(*this, "sprite_scale"),
m_sprite_control(*this, "sprite_control"),
m_maincpu(*this, "maincpu"),
m_audiocpu(*this, "audiocpu"),
m_bsmt(*this, "bsmt"),
m_tlc34076(*this, "tlc34076"),
m_screen(*this, "screen") { }
int main_to_sound_r();
int sound_to_main_r();
void btoads(machine_config &config);
protected:
// driver_device overrides
virtual void machine_start() override;
virtual void video_start() override;
private:
// shared pointers
memory_share_array_creator<uint8_t, 2> m_vram_fg;
required_shared_ptr<uint32_t> m_vram_fg_data;
memory_share_array_creator<uint16_t, 2> m_vram_bg;
required_shared_ptr<uint32_t> m_sprite_scale;
required_shared_ptr<uint32_t> m_sprite_control;
// devices
required_device<tms34020_device> m_maincpu;
required_device<z80_device> m_audiocpu;
required_device<bsmt2000_device> m_bsmt;
required_device<tlc34076_device> m_tlc34076;
required_device<screen_device> m_screen;
// state
uint8_t m_main_to_sound_data = 0;
uint8_t m_main_to_sound_ready = 0;
uint8_t m_sound_to_main_data = 0;
uint8_t m_sound_to_main_ready = 0;
uint8_t m_sound_int_state = 0;
uint8_t *m_vram_fg_draw = nullptr;
uint8_t *m_vram_fg_display = nullptr;
int32_t m_xscroll[2]{};
int32_t m_yscroll[2]{};
uint8_t m_screen_control = 0;
uint16_t m_sprite_source_offs = 0;
uint8_t *m_sprite_dest_base = nullptr;
uint16_t m_sprite_dest_offs = 0;
uint16_t m_misc_control = 0;
[[maybe_unused]] int m_xcount = 0;
std::unique_ptr<uint8_t[]> m_nvram_data;
emu_timer *m_delayed_sound_timer;
emu_timer *m_audio_sync_timer;
void nvram_w(offs_t offset, uint8_t data);
uint8_t nvram_r(offs_t offset);
void main_sound_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t main_sound_r();
void sound_data_w(uint8_t data);
uint8_t sound_data_r();
uint8_t sound_ready_to_send_r();
uint8_t sound_data_ready_r();
void sound_int_state_w(uint8_t data);
uint8_t bsmt_ready_r();
void bsmt2000_port_w(offs_t offset, uint8_t data);
TIMER_CALLBACK_MEMBER(delayed_sound);
TIMER_CALLBACK_MEMBER(audio_sync) { }
void misc_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void display_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
template <uint8_t Which> void scroll_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
template <uint8_t Which> void vram_bg_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
template <uint8_t Which> uint16_t vram_bg_r(offs_t offset);
void vram_fg_display_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void vram_fg_draw_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t vram_fg_display_r(offs_t offset);
uint16_t vram_fg_draw_r(offs_t offset);
void render_sprite_row(uint16_t *sprite_source, uint32_t address);
TMS340X0_TO_SHIFTREG_CB_MEMBER(to_shiftreg);
TMS340X0_FROM_SHIFTREG_CB_MEMBER(from_shiftreg);
TMS340X0_SCANLINE_RGB32_CB_MEMBER(scanline_update);
void main_map(address_map &map);
void sound_io_map(address_map &map);
void sound_map(address_map &map);
};
#define BT_DEBUG 0
/*************************************
*
* Video system start
*
*************************************/
void btoads_state::video_start()
{
// initialize the swapped pointers
m_vram_fg_draw = m_vram_fg[0];
m_vram_fg_display = m_vram_fg[1];
save_item(NAME(m_xscroll));
save_item(NAME(m_yscroll));
save_item(NAME(m_screen_control));
save_item(NAME(m_sprite_source_offs));
save_item(NAME(m_sprite_dest_offs));
save_item(NAME(m_misc_control));
}
/*************************************
*
* Control registers
*
*************************************/
void btoads_state::misc_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_misc_control);
// bit 3 controls sound reset line
m_audiocpu->set_input_line(INPUT_LINE_RESET, (m_misc_control & 8) ? CLEAR_LINE : ASSERT_LINE);
}
void btoads_state::display_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (ACCESSING_BITS_8_15)
{
// allow multiple changes during display
int const scanline = m_screen->vpos();
if (scanline > 0)
m_screen->update_partial(scanline - 1);
// bit 15 controls which page is rendered and which page is displayed
if (data & 0x8000)
{
m_vram_fg_draw = m_vram_fg[1];
m_vram_fg_display = m_vram_fg[0];
}
else
{
m_vram_fg_draw = m_vram_fg[0];
m_vram_fg_display = m_vram_fg[1];
}
// stash the remaining data for later
m_screen_control = data >> 8;
}
}
/*************************************
*
* Scroll registers
*
*************************************/
template <uint8_t Which>
void btoads_state::scroll_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
// allow multiple changes during display
// m_screen->update_now();
m_screen->update_partial(m_screen->vpos());
// upper bits are Y scroll, lower bits are X scroll
if (ACCESSING_BITS_8_15)
m_yscroll[Which] = data >> 8;
if (ACCESSING_BITS_0_7)
m_xscroll[Which] = data & 0xff;
}
/*************************************
*
* Background video RAM
*
*************************************/
template <uint8_t Which>
void btoads_state::vram_bg_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_vram_bg[Which][offset & 0x3fcff]);
}
template <uint8_t Which>
uint16_t btoads_state::vram_bg_r(offs_t offset)
{
return m_vram_bg[Which][offset & 0x3fcff];
}
/*************************************
*
* Foreground video RAM
*
*************************************/
void btoads_state::vram_fg_display_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (ACCESSING_BITS_0_7)
m_vram_fg_display[offset] = data;
}
void btoads_state::vram_fg_draw_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (ACCESSING_BITS_0_7)
m_vram_fg_draw[offset] = data;
}
uint16_t btoads_state::vram_fg_display_r(offs_t offset)
{
return m_vram_fg_display[offset];
}
uint16_t btoads_state::vram_fg_draw_r(offs_t offset)
{
return m_vram_fg_draw[offset];
}
/*************************************
*
* Sprite rendering
*
*************************************/
void btoads_state::render_sprite_row(uint16_t *sprite_source, uint32_t address)
{
int const flipxor = ((*m_sprite_control >> 10) & 1) ? 0xffff : 0x0000;
int const width = (~*m_sprite_control & 0x1ff) + 2;
int const color = (~*m_sprite_control >> 8) & 0xf0;
int srcoffs = m_sprite_source_offs << 8;
int const srcend = srcoffs + (width << 8);
int const srcstep = 0x100 - (m_sprite_scale[0] & 0xffff);
int const dststep = 0x100 - (m_sprite_scale[4] & 0xffff);
int dstoffs = m_sprite_dest_offs << 8;
if (!(m_misc_control & 0x10))
{
// non-shadow case
for ( ; srcoffs < srcend; srcoffs += srcstep, dstoffs += dststep)
{
uint16_t src = sprite_source[(srcoffs >> 10) & 0x1ff];
if (src)
{
src = (src >> (((srcoffs ^ flipxor) >> 6) & 0x0c)) & 0x0f;
if (src)
m_sprite_dest_base[(dstoffs >> 8) & 0x1ff] = src | color;
}
}
}
else
{
// shadow case
for ( ; srcoffs < srcend; srcoffs += srcstep, dstoffs += dststep)
{
uint16_t src = sprite_source[(srcoffs >> 10) & 0x1ff];
if (src)
{
src = (src >> (((srcoffs ^ flipxor) >> 6) & 0x0c)) & 0x0f;
if (src)
m_sprite_dest_base[(dstoffs >> 8) & 0x1ff] = color;
}
}
}
m_sprite_source_offs += width;
m_sprite_dest_offs = dstoffs >> 8;
}
/*************************************
*
* Shift register read/write
*
*************************************/
TMS340X0_TO_SHIFTREG_CB_MEMBER(btoads_state::to_shiftreg)
{
address &= ~0x40000000;
if (address >= 0xa0000000 && address <= 0xa3ffffff)
{
// reads from this first region are usual shift register reads
memcpy(shiftreg, &m_vram_fg_display[(address & 0x3fffff) >> 4], 0x200);
}
else if (address >= 0xa4000000 && address <= 0xa7ffffff)
{
// reads from this region set the sprite destination address
m_sprite_dest_base = &m_vram_fg_draw[(address & 0x3fc000) >> 4];
m_sprite_dest_offs = (address & 0x003fff) >> 5;
}
else if (address >= 0xa8000000 && address <= 0xabffffff)
{
// reads from this region set the sprite source address
const u32 *src = &m_vram_fg_data[(address & 0x7fc000) >> 5];
u16 *dest = shiftreg;
for (unsigned int i = 0; i != 0x100; i++)
{
*dest++ = *src;
*dest++ = *src >> 16;
src++;
}
m_sprite_source_offs = (address & 0x003fff) >> 3;
}
else
logerror("%s: to_shiftreg(%08X)\n", machine().describe_context(), address);
}
TMS340X0_FROM_SHIFTREG_CB_MEMBER(btoads_state::from_shiftreg)
{
address &= ~0x40000000;
if (address >= 0xa0000000 && address <= 0xa3ffffff)
{
// writes to this first region are usual shift register writes
memcpy(&m_vram_fg_display[(address & 0x3fc000) >> 4], shiftreg, 0x200);
}
else if (address >= 0xa4000000 && address <= 0xa7ffffff)
{
// writes to this region are ignored for our purposes
}
else if (address >= 0xa8000000 && address <= 0xabffffff)
{
// writes to this region copy standard data
const u16 *src = shiftreg;
u32 *dest = &m_vram_fg_data[(address & 0x7fc000) >> 5];
for (unsigned int i = 0; i != 0x100; i++)
{
*dest++ = src[0] | (src[1] << 16);
src += 2;
}
}
else if (address >= 0xac000000 && address <= 0xafffffff)
{
// writes to this region render the current sprite data
render_sprite_row(shiftreg, address);
}
else
logerror("%s: from_shiftreg(%08X)\n", machine().describe_context(), address);
}
/*************************************
*
* Main refresh
*
*************************************/
TMS340X0_SCANLINE_RGB32_CB_MEMBER(btoads_state::scanline_update)
{
uint32_t const fulladdr = ((params->rowaddr << 16) | params->coladdr) >> 4;
uint16_t *bg0_base = &m_vram_bg[0][(fulladdr + (m_yscroll[0] << 10)) & 0x3fc00];
uint16_t *bg1_base = &m_vram_bg[1][(fulladdr + (m_yscroll[1] << 10)) & 0x3fc00];
uint8_t *spr_base = &m_vram_fg_display[fulladdr & 0x3fc00];
uint32_t *const dst = &bitmap.pix(scanline);
const pen_t *pens = m_tlc34076->pens();
int coladdr = fulladdr & 0x3ff;
// for each scanline, switch off the render mode
switch (m_screen_control & 3)
{
// mode 0: used in ship level, snake boss, title screen (free play)
/* priority is:
1. Sprite pixels with high bit clear
2. BG1 pixels with the high bit set
3. Sprites
4. BG1
5. BG0
*/
case 0:
for (int x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
{
uint8_t const sprpix = spr_base[coladdr & 0xff];
if (sprpix && !(sprpix & 0x80))
{
dst[x + 0] = pens[sprpix];
dst[x + 1] = pens[sprpix];
}
else
{
uint16_t const bg0pix = bg0_base[(coladdr + m_xscroll[0]) & 0xff];
uint16_t const bg1pix = bg1_base[(coladdr + m_xscroll[1]) & 0xff];
if (bg1pix & 0x80)
dst[x + 0] = pens[bg1pix & 0xff];
else if (sprpix)
dst[x + 0] = pens[sprpix];
else if (bg1pix & 0xff)
dst[x + 0] = pens[bg1pix & 0xff];
else
dst[x + 0] = pens[bg0pix & 0xff];
if (bg1pix & 0x8000)
dst[x + 1] = pens[bg1pix >> 8];
else if (sprpix)
dst[x + 1] = pens[sprpix];
else if (bg1pix >> 8)
dst[x + 1] = pens[bg1pix >> 8];
else
dst[x + 1] = pens[bg0pix >> 8];
}
}
break;
// mode 1: used in snow level, title screen (free play), top part of rolling ball level
/* priority is:
1. Sprite pixels with high bit clear
2. BG0
3. BG1 pixels with high bit set
4. Sprites
5. BG1
*/
case 1:
for (int x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
{
uint8_t const sprpix = spr_base[coladdr & 0xff];
if (sprpix && !(sprpix & 0x80))
{
dst[x + 0] = pens[sprpix];
dst[x + 1] = pens[sprpix];
}
else
{
uint16_t const bg0pix = bg0_base[(coladdr + m_xscroll[0]) & 0xff];
uint16_t const bg1pix = bg1_base[(coladdr + m_xscroll[1]) & 0xff];
if (bg0pix & 0xff)
dst[x + 0] = pens[bg0pix & 0xff];
else if (bg1pix & 0x80)
dst[x + 0] = pens[bg1pix & 0xff];
else if (sprpix)
dst[x + 0] = pens[sprpix];
else
dst[x + 0] = pens[bg1pix & 0xff];
if (bg0pix >> 8)
dst[x + 1] = pens[bg0pix >> 8];
else if (bg1pix & 0x8000)
dst[x + 1] = pens[bg1pix >> 8];
else if (sprpix)
dst[x + 1] = pens[sprpix];
else
dst[x + 1] = pens[bg1pix >> 8];
}
}
break;
// mode 2: used in EOA screen, jetpack level, first level, high score screen
/* priority is:
1. Sprites
2. BG1
3. BG0
*/
case 2:
for (int x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
{
uint8_t const sprpix = spr_base[coladdr & 0xff];
if (sprpix)
{
dst[x + 0] = pens[sprpix];
dst[x + 1] = pens[sprpix];
}
else
{
uint16_t const bg0pix = bg0_base[(coladdr + m_xscroll[0]) & 0xff];
uint16_t const bg1pix = bg1_base[(coladdr + m_xscroll[1]) & 0xff];
if (bg1pix & 0xff)
dst[x + 0] = pens[bg1pix & 0xff];
else
dst[x + 0] = pens[bg0pix & 0xff];
if (bg1pix >> 8)
dst[x + 1] = pens[bg1pix >> 8];
else
dst[x + 1] = pens[bg0pix >> 8];
}
}
break;
// mode 3: used in toilet level, toad intros, bottom of rolling ball level
/* priority is:
1. BG1 pixels with the high bit set
2. Sprite pixels with the high bit set
3. BG1
4. Sprites
5. BG0
*/
case 3:
for (int x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
{
uint16_t const bg0pix = bg0_base[(coladdr + m_xscroll[0]) & 0xff];
uint16_t const bg1pix = bg1_base[(coladdr + m_xscroll[1]) & 0xff];
uint8_t const sprpix = spr_base[coladdr & 0xff];
if (bg1pix & 0x80)
dst[x + 0] = pens[bg1pix & 0xff];
else if (sprpix & 0x80)
dst[x + 0] = pens[sprpix];
else if (bg1pix & 0xff)
dst[x + 0] = pens[bg1pix & 0xff];
else if (sprpix)
dst[x + 0] = pens[sprpix];
else
dst[x + 0] = pens[bg0pix & 0xff];
if (bg1pix & 0x8000)
dst[x + 1] = pens[bg1pix >> 8];
else if (sprpix & 0x80)
dst[x + 1] = pens[sprpix];
else if (bg1pix >> 8)
dst[x + 1] = pens[bg1pix >> 8];
else if (sprpix)
dst[x + 1] = pens[sprpix];
else
dst[x + 1] = pens[bg0pix >> 8];
}
break;
}
// debugging - dump the screen contents to a file
#if BT_DEBUG
popmessage("screen_control = %02X", m_screen_control & 0x7f);
if (machine().input().code_pressed(KEYCODE_X))
{
char name[10];
FILE *f;
while (machine().input().code_pressed(KEYCODE_X)) { }
sprintf(name, "disp%d.log", m_xcount++);
f = fopen(name, "w");
fprintf(f, "screen_control = %04X\n\n", m_screen_control << 8);
for (int i = 0; i < 3; i++)
{
uint16_t *base = (i == 0) ? (uint16_t *)m_vram_fg_display : (i == 1) ? m_vram_bg0 : m_vram_bg1;
int xscr = (i == 0) ? 0 : (i == 1) ? m_xscroll[0] : m_xscroll[1];
int yscr = (i == 0) ? 0 : (i == 1) ? m_yscroll[0] : m_yscroll[1];
for (int y = 0; y < 224; y++)
{
uint32_t offs = ((y + yscr) & 0xff) * TOWORD(0x4000);
for (int x = 0; x < 256; x++)
{
uint16_t pix = base[offs + ((x + xscr) & 0xff)];
fprintf(f, "%02X%02X", pix & 0xff, pix >> 8);
if (x % 16 == 15) fprintf(f, " ");
}
fprintf(f, "\n");
}
fprintf(f, "\n\n");
}
fclose(f);
}
logerror("---VBLANK---\n");
#endif
}
/*************************************
@ -149,11 +743,11 @@ uint8_t btoads_state::sound_data_ready_r()
void btoads_state::sound_int_state_w(uint8_t data)
{
/* top bit controls BSMT2000 reset */
// top bit controls BSMT2000 reset
if (!(m_sound_int_state & 0x80) && (data & 0x80))
m_bsmt->reset();
/* also clears interrupts */
// also clears interrupts
m_audiocpu->set_input_line(0, CLEAR_LINE);
m_sound_int_state = data;
}
@ -195,23 +789,23 @@ void btoads_state::main_map(address_map &map)
map(0x20000180, 0x200001ff).portr("UNK");
map(0x20000200, 0x2000027f).portr("SPECIAL");
map(0x20000280, 0x200002ff).portr("SW1");
map(0x20000000, 0x200000ff).writeonly().share("sprite_scale");
map(0x20000100, 0x2000017f).writeonly().share("sprite_control");
map(0x20000000, 0x200000ff).writeonly().share(m_sprite_scale);
map(0x20000100, 0x2000017f).writeonly().share(m_sprite_control);
map(0x20000180, 0x200001ff).w(FUNC(btoads_state::display_control_w));
map(0x20000200, 0x2000027f).w(FUNC(btoads_state::scroll0_w));
map(0x20000280, 0x200002ff).w(FUNC(btoads_state::scroll1_w));
map(0x20000200, 0x2000027f).w(FUNC(btoads_state::scroll_w<0>));
map(0x20000280, 0x200002ff).w(FUNC(btoads_state::scroll_w<1>));
map(0x20000300, 0x2000037f).rw(m_tlc34076, FUNC(tlc34076_device::read), FUNC(tlc34076_device::write)).umask32(0x000000ff);
map(0x20000380, 0x200003ff).rw(FUNC(btoads_state::main_sound_r), FUNC(btoads_state::main_sound_w));
map(0x20000400, 0x2000047f).w(FUNC(btoads_state::misc_control_w));
map(0x40000000, 0x4000001f).nopw(); /* watchdog? */
map(0x40000000, 0x4000001f).nopw(); // watchdog?
map(0x60000000, 0x6003ffff).rw(FUNC(btoads_state::nvram_r), FUNC(btoads_state::nvram_w)).umask32(0x000000ff);
map(0xa0000000, 0xa03fffff).rw(FUNC(btoads_state::vram_fg_display_r), FUNC(btoads_state::vram_fg_display_w));
map(0xa4000000, 0xa43fffff).rw(FUNC(btoads_state::vram_fg_draw_r), FUNC(btoads_state::vram_fg_draw_w));
map(0xa8000000, 0xa87fffff).ram().share("vram_fg_data");
map(0xa8800000, 0xa8ffffff).nopw();
map(0xb0000000, 0xb03fffff).rw(FUNC(btoads_state::vram_bg0_r), FUNC(btoads_state::vram_bg0_w));
map(0xb4000000, 0xb43fffff).rw(FUNC(btoads_state::vram_bg1_r), FUNC(btoads_state::vram_bg1_w));
map(0xfc000000, 0xffffffff).rom().region("user1", 0);
map(0xb0000000, 0xb03fffff).rw(FUNC(btoads_state::vram_bg_r<0>), FUNC(btoads_state::vram_bg_w<0>));
map(0xb4000000, 0xb43fffff).rw(FUNC(btoads_state::vram_bg_r<1>), FUNC(btoads_state::vram_bg_w<1>));
map(0xfc000000, 0xffffffff).rom().region("maincpu", 0);
}
@ -324,30 +918,34 @@ INPUT_PORTS_END
void btoads_state::btoads(machine_config &config)
{
TMS34020(config, m_maincpu, CPU_CLOCK/2);
constexpr XTAL CPU_CLOCK = XTAL(64'000'000);
constexpr XTAL VIDEO_CLOCK = XTAL(20'000'000);
constexpr XTAL SOUND_CLOCK = XTAL(24'000'000);
TMS34020(config, m_maincpu, CPU_CLOCK / 2);
m_maincpu->set_addrmap(AS_PROGRAM, &btoads_state::main_map);
m_maincpu->set_halt_on_reset(false);
m_maincpu->set_pixel_clock(VIDEO_CLOCK/2);
m_maincpu->set_pixel_clock(VIDEO_CLOCK / 2);
m_maincpu->set_pixels_per_clock(1);
m_maincpu->set_scanline_rgb32_callback(FUNC(btoads_state::scanline_update));
m_maincpu->set_shiftreg_in_callback(FUNC(btoads_state::to_shiftreg));
m_maincpu->set_shiftreg_out_callback(FUNC(btoads_state::from_shiftreg));
Z80(config, m_audiocpu, SOUND_CLOCK/4);
Z80(config, m_audiocpu, SOUND_CLOCK / 4);
m_audiocpu->set_addrmap(AS_PROGRAM, &btoads_state::sound_map);
m_audiocpu->set_addrmap(AS_IO, &btoads_state::sound_io_map);
m_audiocpu->set_periodic_int(FUNC(btoads_state::irq0_line_assert), attotime::from_hz(SOUND_CLOCK/4/32768));
m_audiocpu->set_periodic_int(FUNC(btoads_state::irq0_line_assert), attotime::from_hz(SOUND_CLOCK / 4 / 32768));
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1);
/* video hardware */
// video hardware
TLC34076(config, m_tlc34076, tlc34076_device::TLC34076_6_BIT);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(VIDEO_CLOCK/2, 640, 0, 512, 257, 0, 224);
m_screen->set_raw(VIDEO_CLOCK / 2, 640, 0, 512, 257, 0, 224);
m_screen->set_screen_update("maincpu", FUNC(tms34020_device::tms340x0_rgb32));
/* sound hardware */
// sound hardware
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
@ -365,25 +963,26 @@ void btoads_state::btoads(machine_config &config)
*************************************/
ROM_START( btoads )
ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound program, M27C256B rom */
ROM_LOAD( "bt.u102", 0x0000, 0x8000, CRC(a90b911a) SHA1(6ec25161e68df1c9870d48cc2b1f85cd1a49aba9) )
ROM_REGION32_LE( 0x800000, "user1", 0 ) /* 34020 code, M27C322 roms */
ROM_REGION32_LE( 0x800000, "maincpu", 0 ) // M27C322 ROMs
ROM_LOAD32_WORD( "btc0-p0.u120", 0x000000, 0x400000, CRC(0dfd1e35) SHA1(733a0a4235bebd598c600f187ed2628f28cf9bd0) )
ROM_LOAD32_WORD( "btc0-p1.u121", 0x000002, 0x400000, CRC(df7487e1) SHA1(67151b900767bb2653b5261a98c81ff8827222c3) )
ROM_REGION( 0x1000000, "bsmt", 0 ) /* BSMT data, M27C160 rom */
ROM_REGION( 0x10000, "audiocpu", 0 ) // M27C256B ROM
ROM_LOAD( "bt.u102", 0x0000, 0x8000, CRC(a90b911a) SHA1(6ec25161e68df1c9870d48cc2b1f85cd1a49aba9) )
ROM_REGION( 0x1000000, "bsmt", 0 ) // M27C160 ROM
ROM_LOAD( "btc0-s.u109", 0x00000, 0x200000, CRC(d9612ddb) SHA1(f186dfb013e81abf81ba8ac5dc7eb731c1ad82b6) )
ROM_REGION( 0x080a, "plds", 0 )
ROM_LOAD( "u10.bin", 0x0000, 0x0157, CRC(b1144178) SHA1(15fb047adee4125e9fcf04171e0a502655e0a3d8) ) /* GAL20V8A-15LP Located at U10. */
ROM_LOAD( "u11.bin", 0x0000, 0x0157, CRC(7c6beb96) SHA1(2f19d21889dd765b344ad7d257ea7c244baebec2) ) /* GAL20V8A-15LP Located at U11. */
ROM_LOAD( "u57.bin", 0x0000, 0x0157, CRC(be355a56) SHA1(975238bb1ea8fef14458d6f264a82aa77ecf865d) ) /* GAL20V8A-15LP Located at U57. */
ROM_LOAD( "u58.bin", 0x0000, 0x0157, CRC(41ed339c) SHA1(5853c805a902e6d12c979958d878d1cefd6908cc) ) /* GAL20V8A-15LP Located at U58. */
ROM_LOAD( "u90.bin", 0x0000, 0x0157, CRC(a0d0c3f1) SHA1(47464c2ef9fadbba933df27767f377e0c29158aa) ) /* GAL20V8A-15LP Located at U90. */
ROM_LOAD( "u144.bin", 0x0000, 0x0157, CRC(8597017f) SHA1(003d7b5de57e48f831ab211e2783fff338ce2f32) ) /* GAL20V8A-15LP Located at U144. */
ROM_LOAD( "u10.bin", 0x0000, 0x0157, CRC(b1144178) SHA1(15fb047adee4125e9fcf04171e0a502655e0a3d8) ) // GAL20V8A-15LP Located at U10.
ROM_LOAD( "u11.bin", 0x0000, 0x0157, CRC(7c6beb96) SHA1(2f19d21889dd765b344ad7d257ea7c244baebec2) ) // GAL20V8A-15LP Located at U11.
ROM_LOAD( "u57.bin", 0x0000, 0x0157, CRC(be355a56) SHA1(975238bb1ea8fef14458d6f264a82aa77ecf865d) ) // GAL20V8A-15LP Located at U57.
ROM_LOAD( "u58.bin", 0x0000, 0x0157, CRC(41ed339c) SHA1(5853c805a902e6d12c979958d878d1cefd6908cc) ) // GAL20V8A-15LP Located at U58.
ROM_LOAD( "u90.bin", 0x0000, 0x0157, CRC(a0d0c3f1) SHA1(47464c2ef9fadbba933df27767f377e0c29158aa) ) // GAL20V8A-15LP Located at U90.
ROM_LOAD( "u144.bin", 0x0000, 0x0157, CRC(8597017f) SHA1(003d7b5de57e48f831ab211e2783fff338ce2f32) ) // GAL20V8A-15LP Located at U144.
ROM_END
} // anonymous namespace
/*************************************

View File

@ -1,123 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/*************************************************************************
BattleToads
Common definitions
*************************************************************************/
#include "cpu/tms34010/tms34010.h"
#include "cpu/z80/z80.h"
#include "video/tlc34076.h"
#include "sound/bsmt2000.h"
#include "machine/nvram.h"
#include "emupal.h"
#include "screen.h"
class btoads_state : public driver_device
{
public:
btoads_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_vram_fg0(*this, "vram_fg0", 0x200000, ENDIANNESS_LITTLE),
m_vram_fg1(*this, "vram_fg1", 0x200000, ENDIANNESS_LITTLE),
m_vram_fg_data(*this, "vram_fg_data"),
m_vram_bg0(*this, "vram_bg0", 0x400000, ENDIANNESS_LITTLE),
m_vram_bg1(*this, "vram_bg1", 0x400000, ENDIANNESS_LITTLE),
m_sprite_scale(*this, "sprite_scale"),
m_sprite_control(*this, "sprite_control"),
m_maincpu(*this, "maincpu"),
m_audiocpu(*this, "audiocpu"),
m_bsmt(*this, "bsmt"),
m_tlc34076(*this, "tlc34076"),
m_screen(*this, "screen") { }
int main_to_sound_r();
int sound_to_main_r();
void btoads(machine_config &config);
protected:
// driver_device overrides
virtual void machine_start() override;
virtual void video_start() override;
TIMER_CALLBACK_MEMBER(delayed_sound);
TIMER_CALLBACK_MEMBER(audio_sync) { }
private:
// shared pointers
memory_share_creator<uint8_t> m_vram_fg0;
memory_share_creator<uint8_t> m_vram_fg1;
required_shared_ptr<uint32_t> m_vram_fg_data;
memory_share_creator<uint16_t> m_vram_bg0;
memory_share_creator<uint16_t> m_vram_bg1;
required_shared_ptr<uint32_t> m_sprite_scale;
required_shared_ptr<uint32_t> m_sprite_control;
// state
uint8_t m_main_to_sound_data = 0;
uint8_t m_main_to_sound_ready = 0;
uint8_t m_sound_to_main_data = 0;
uint8_t m_sound_to_main_ready = 0;
uint8_t m_sound_int_state = 0;
uint8_t *m_vram_fg_draw = nullptr;
uint8_t *m_vram_fg_display = nullptr;
int32_t m_xscroll0 = 0;
int32_t m_yscroll0 = 0;
int32_t m_xscroll1 = 0;
int32_t m_yscroll1 = 0;
uint8_t m_screen_control = 0;
uint16_t m_sprite_source_offs = 0;
uint8_t *m_sprite_dest_base = nullptr;
uint16_t m_sprite_dest_offs = 0;
uint16_t m_misc_control = 0;
int m_xcount = 0;
std::unique_ptr<uint8_t[]> m_nvram_data;
emu_timer *m_delayed_sound_timer;
emu_timer *m_audio_sync_timer;
// in drivers/btoads
void nvram_w(offs_t offset, uint8_t data);
uint8_t nvram_r(offs_t offset);
void main_sound_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t main_sound_r();
void sound_data_w(uint8_t data);
uint8_t sound_data_r();
uint8_t sound_ready_to_send_r();
uint8_t sound_data_ready_r();
void sound_int_state_w(uint8_t data);
uint8_t bsmt_ready_r();
void bsmt2000_port_w(offs_t offset, uint8_t data);
// in video/btoads
void misc_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void display_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void scroll0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void scroll1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void vram_bg0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void vram_bg1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t vram_bg0_r(offs_t offset);
uint16_t vram_bg1_r(offs_t offset);
void vram_fg_display_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void vram_fg_draw_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t vram_fg_display_r(offs_t offset);
uint16_t vram_fg_draw_r(offs_t offset);
void render_sprite_row(uint16_t *sprite_source, uint32_t address);
TMS340X0_TO_SHIFTREG_CB_MEMBER(to_shiftreg);
TMS340X0_FROM_SHIFTREG_CB_MEMBER(from_shiftreg);
TMS340X0_SCANLINE_RGB32_CB_MEMBER(scanline_update);
// devices
required_device<tms34020_device> m_maincpu;
required_device<z80_device> m_audiocpu;
required_device<bsmt2000_device> m_bsmt;
required_device<tlc34076_device> m_tlc34076;
required_device<screen_device> m_screen;
void main_map(address_map &map);
void sound_io_map(address_map &map);
void sound_map(address_map &map);
};

View File

@ -1,533 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/*************************************************************************
BattleToads
Video hardware emulation
**************************************************************************/
#include "emu.h"
#include "btoads.h"
#define BT_DEBUG 0
/*************************************
*
* Video system start
*
*************************************/
void btoads_state::video_start()
{
// initialize the swapped pointers
m_vram_fg_draw = m_vram_fg0;
m_vram_fg_display = m_vram_fg1;
save_item(NAME(m_xscroll0));
save_item(NAME(m_xscroll1));
save_item(NAME(m_yscroll0));
save_item(NAME(m_yscroll1));
save_item(NAME(m_screen_control));
save_item(NAME(m_sprite_source_offs));
save_item(NAME(m_sprite_dest_offs));
save_item(NAME(m_misc_control));
}
/*************************************
*
* Control registers
*
*************************************/
void btoads_state::misc_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_misc_control);
// bit 3 controls sound reset line
m_audiocpu->set_input_line(INPUT_LINE_RESET, (m_misc_control & 8) ? CLEAR_LINE : ASSERT_LINE);
}
void btoads_state::display_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (ACCESSING_BITS_8_15)
{
// allow multiple changes during display
int scanline = m_screen->vpos();
if (scanline > 0)
m_screen->update_partial(scanline - 1);
// bit 15 controls which page is rendered and which page is displayed
if (data & 0x8000)
{
m_vram_fg_draw = m_vram_fg1;
m_vram_fg_display = m_vram_fg0;
}
else
{
m_vram_fg_draw = m_vram_fg0;
m_vram_fg_display = m_vram_fg1;
}
// stash the remaining data for later
m_screen_control = data >> 8;
}
}
/*************************************
*
* Scroll registers
*
*************************************/
void btoads_state::scroll0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
// allow multiple changes during display
// m_screen->update_now();
m_screen->update_partial(m_screen->vpos());
// upper bits are Y scroll, lower bits are X scroll
if (ACCESSING_BITS_8_15)
m_yscroll0 = data >> 8;
if (ACCESSING_BITS_0_7)
m_xscroll0 = data & 0xff;
}
void btoads_state::scroll1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
// allow multiple changes during display
// m_screen->update_now();
m_screen->update_partial(m_screen->vpos());
// upper bits are Y scroll, lower bits are X scroll
if (ACCESSING_BITS_8_15)
m_yscroll1 = data >> 8;
if (ACCESSING_BITS_0_7)
m_xscroll1 = data & 0xff;
}
/*************************************
*
* Background video RAM
*
*************************************/
void btoads_state::vram_bg0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_vram_bg0[offset & 0x3fcff]);
}
void btoads_state::vram_bg1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_vram_bg1[offset & 0x3fcff]);
}
uint16_t btoads_state::vram_bg0_r(offs_t offset)
{
return m_vram_bg0[offset & 0x3fcff];
}
uint16_t btoads_state::vram_bg1_r(offs_t offset)
{
return m_vram_bg1[offset & 0x3fcff];
}
/*************************************
*
* Foreground video RAM
*
*************************************/
void btoads_state::vram_fg_display_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (ACCESSING_BITS_0_7)
m_vram_fg_display[offset] = data;
}
void btoads_state::vram_fg_draw_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (ACCESSING_BITS_0_7)
m_vram_fg_draw[offset] = data;
}
uint16_t btoads_state::vram_fg_display_r(offs_t offset)
{
return m_vram_fg_display[offset];
}
uint16_t btoads_state::vram_fg_draw_r(offs_t offset)
{
return m_vram_fg_draw[offset];
}
/*************************************
*
* Sprite rendering
*
*************************************/
void btoads_state::render_sprite_row(uint16_t *sprite_source, uint32_t address)
{
int flipxor = ((*m_sprite_control >> 10) & 1) ? 0xffff : 0x0000;
int width = (~*m_sprite_control & 0x1ff) + 2;
int color = (~*m_sprite_control >> 8) & 0xf0;
int srcoffs = m_sprite_source_offs << 8;
int srcend = srcoffs + (width << 8);
int srcstep = 0x100 - (m_sprite_scale[0] & 0xffff);
int dststep = 0x100 - (m_sprite_scale[4] & 0xffff);
int dstoffs = m_sprite_dest_offs << 8;
if (!(m_misc_control & 0x10))
{
// non-shadow case
for ( ; srcoffs < srcend; srcoffs += srcstep, dstoffs += dststep)
{
uint16_t src = sprite_source[(srcoffs >> 10) & 0x1ff];
if (src)
{
src = (src >> (((srcoffs ^ flipxor) >> 6) & 0x0c)) & 0x0f;
if (src)
m_sprite_dest_base[(dstoffs >> 8) & 0x1ff] = src | color;
}
}
}
else
{
// shadow case
for ( ; srcoffs < srcend; srcoffs += srcstep, dstoffs += dststep)
{
uint16_t src = sprite_source[(srcoffs >> 10) & 0x1ff];
if (src)
{
src = (src >> (((srcoffs ^ flipxor) >> 6) & 0x0c)) & 0x0f;
if (src)
m_sprite_dest_base[(dstoffs >> 8) & 0x1ff] = color;
}
}
}
m_sprite_source_offs += width;
m_sprite_dest_offs = dstoffs >> 8;
}
/*************************************
*
* Shift register read/write
*
*************************************/
TMS340X0_TO_SHIFTREG_CB_MEMBER(btoads_state::to_shiftreg)
{
address &= ~0x40000000;
if (address >= 0xa0000000 && address <= 0xa3ffffff)
{
// reads from this first region are usual shift register reads
memcpy(shiftreg, &m_vram_fg_display[(address & 0x3fffff) >> 4], 0x200);
}
else if (address >= 0xa4000000 && address <= 0xa7ffffff)
{
// reads from this region set the sprite destination address
m_sprite_dest_base = &m_vram_fg_draw[(address & 0x3fc000) >> 4];
m_sprite_dest_offs = (address & 0x003fff) >> 5;
}
else if (address >= 0xa8000000 && address <= 0xabffffff)
{
// reads from this region set the sprite source address
const u32 *src = &m_vram_fg_data[(address & 0x7fc000) >> 5];
u16 *dest = shiftreg;
for (unsigned int i = 0; i != 0x100; i++)
{
*dest++ = *src;
*dest++ = *src >> 16;
src++;
}
m_sprite_source_offs = (address & 0x003fff) >> 3;
}
else
logerror("%s:btoads_to_shiftreg(%08X)\n", machine().describe_context(), address);
}
TMS340X0_FROM_SHIFTREG_CB_MEMBER(btoads_state::from_shiftreg)
{
address &= ~0x40000000;
if (address >= 0xa0000000 && address <= 0xa3ffffff)
{
// writes to this first region are usual shift register writes
memcpy(&m_vram_fg_display[(address & 0x3fc000) >> 4], shiftreg, 0x200);
}
else if (address >= 0xa4000000 && address <= 0xa7ffffff)
{
// writes to this region are ignored for our purposes
}
else if (address >= 0xa8000000 && address <= 0xabffffff)
{
// writes to this region copy standard data
const u16 *src = shiftreg;
u32 *dest = &m_vram_fg_data[(address & 0x7fc000) >> 5];
for (unsigned int i = 0; i != 0x100; i++)
{
*dest++ = src[0] | (src[1] << 16);
src += 2;
}
}
else if (address >= 0xac000000 && address <= 0xafffffff)
{
// writes to this region render the current sprite data
render_sprite_row(shiftreg, address);
}
else
logerror("%s:btoads_from_shiftreg(%08X)\n", machine().describe_context(), address);
}
/*************************************
*
* Main refresh
*
*************************************/
TMS340X0_SCANLINE_RGB32_CB_MEMBER(btoads_state::scanline_update)
{
uint32_t fulladdr = ((params->rowaddr << 16) | params->coladdr) >> 4;
uint16_t *bg0_base = &m_vram_bg0[(fulladdr + (m_yscroll0 << 10)) & 0x3fc00];
uint16_t *bg1_base = &m_vram_bg1[(fulladdr + (m_yscroll1 << 10)) & 0x3fc00];
uint8_t *spr_base = &m_vram_fg_display[fulladdr & 0x3fc00];
uint32_t *const dst = &bitmap.pix(scanline);
const pen_t *pens = m_tlc34076->pens();
int coladdr = fulladdr & 0x3ff;
/* for each scanline, switch off the render mode */
switch (m_screen_control & 3)
{
/* mode 0: used in ship level, snake boss, title screen (free play) */
/* priority is:
1. Sprite pixels with high bit clear
2. BG1 pixels with the high bit set
3. Sprites
4. BG1
5. BG0
*/
case 0:
for (int x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
{
uint8_t sprpix = spr_base[coladdr & 0xff];
if (sprpix && !(sprpix & 0x80))
{
dst[x + 0] = pens[sprpix];
dst[x + 1] = pens[sprpix];
}
else
{
uint16_t bg0pix = bg0_base[(coladdr + m_xscroll0) & 0xff];
uint16_t bg1pix = bg1_base[(coladdr + m_xscroll1) & 0xff];
uint8_t sprpix = spr_base[coladdr & 0xff];
if (bg1pix & 0x80)
dst[x + 0] = pens[bg1pix & 0xff];
else if (sprpix)
dst[x + 0] = pens[sprpix];
else if (bg1pix & 0xff)
dst[x + 0] = pens[bg1pix & 0xff];
else
dst[x + 0] = pens[bg0pix & 0xff];
if (bg1pix & 0x8000)
dst[x + 1] = pens[bg1pix >> 8];
else if (sprpix)
dst[x + 1] = pens[sprpix];
else if (bg1pix >> 8)
dst[x + 1] = pens[bg1pix >> 8];
else
dst[x + 1] = pens[bg0pix >> 8];
}
}
break;
/* mode 1: used in snow level, title screen (free play), top part of rolling ball level */
/* priority is:
1. Sprite pixels with high bit clear
2. BG0
3. BG1 pixels with high bit set
4. Sprites
5. BG1
*/
case 1:
for (int x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
{
uint8_t sprpix = spr_base[coladdr & 0xff];
if (sprpix && !(sprpix & 0x80))
{
dst[x + 0] = pens[sprpix];
dst[x + 1] = pens[sprpix];
}
else
{
uint16_t bg0pix = bg0_base[(coladdr + m_xscroll0) & 0xff];
uint16_t bg1pix = bg1_base[(coladdr + m_xscroll1) & 0xff];
if (bg0pix & 0xff)
dst[x + 0] = pens[bg0pix & 0xff];
else if (bg1pix & 0x80)
dst[x + 0] = pens[bg1pix & 0xff];
else if (sprpix)
dst[x + 0] = pens[sprpix];
else
dst[x + 0] = pens[bg1pix & 0xff];
if (bg0pix >> 8)
dst[x + 1] = pens[bg0pix >> 8];
else if (bg1pix & 0x8000)
dst[x + 1] = pens[bg1pix >> 8];
else if (sprpix)
dst[x + 1] = pens[sprpix];
else
dst[x + 1] = pens[bg1pix >> 8];
}
}
break;
/* mode 2: used in EOA screen, jetpack level, first level, high score screen */
/* priority is:
1. Sprites
2. BG1
3. BG0
*/
case 2:
for (int x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
{
uint8_t sprpix = spr_base[coladdr & 0xff];
if (sprpix)
{
dst[x + 0] = pens[sprpix];
dst[x + 1] = pens[sprpix];
}
else
{
uint16_t bg0pix = bg0_base[(coladdr + m_xscroll0) & 0xff];
uint16_t bg1pix = bg1_base[(coladdr + m_xscroll1) & 0xff];
if (bg1pix & 0xff)
dst[x + 0] = pens[bg1pix & 0xff];
else
dst[x + 0] = pens[bg0pix & 0xff];
if (bg1pix >> 8)
dst[x + 1] = pens[bg1pix >> 8];
else
dst[x + 1] = pens[bg0pix >> 8];
}
}
break;
/* mode 3: used in toilet level, toad intros, bottom of rolling ball level */
/* priority is:
1. BG1 pixels with the high bit set
2. Sprite pixels with the high bit set
3. BG1
4. Sprites
5. BG0
*/
case 3:
for (int x = params->heblnk; x < params->hsblnk; x += 2, coladdr++)
{
uint16_t bg0pix = bg0_base[(coladdr + m_xscroll0) & 0xff];
uint16_t bg1pix = bg1_base[(coladdr + m_xscroll1) & 0xff];
uint8_t sprpix = spr_base[coladdr & 0xff];
if (bg1pix & 0x80)
dst[x + 0] = pens[bg1pix & 0xff];
else if (sprpix & 0x80)
dst[x + 0] = pens[sprpix];
else if (bg1pix & 0xff)
dst[x + 0] = pens[bg1pix & 0xff];
else if (sprpix)
dst[x + 0] = pens[sprpix];
else
dst[x + 0] = pens[bg0pix & 0xff];
if (bg1pix & 0x8000)
dst[x + 1] = pens[bg1pix >> 8];
else if (sprpix & 0x80)
dst[x + 1] = pens[sprpix];
else if (bg1pix >> 8)
dst[x + 1] = pens[bg1pix >> 8];
else if (sprpix)
dst[x + 1] = pens[sprpix];
else
dst[x + 1] = pens[bg0pix >> 8];
}
break;
}
/* debugging - dump the screen contents to a file */
#if BT_DEBUG
popmessage("screen_control = %02X", m_screen_control & 0x7f);
if (machine().input().code_pressed(KEYCODE_X))
{
char name[10];
FILE *f;
while (machine().input().code_pressed(KEYCODE_X)) { }
sprintf(name, "disp%d.log", m_xcount++);
f = fopen(name, "w");
fprintf(f, "screen_control = %04X\n\n", m_screen_control << 8);
for (int i = 0; i < 3; i++)
{
uint16_t *base = (i == 0) ? (uint16_t *)m_vram_fg_display : (i == 1) ? m_vram_bg0 : m_vram_bg1;
int xscr = (i == 0) ? 0 : (i == 1) ? m_xscroll0 : m_xscroll1;
int yscr = (i == 0) ? 0 : (i == 1) ? m_yscroll0 : m_yscroll1;
for (int y = 0; y < 224; y++)
{
uint32_t offs = ((y + yscr) & 0xff) * TOWORD(0x4000);
for (int x = 0; x < 256; x++)
{
uint16_t pix = base[offs + ((x + xscr) & 0xff)];
fprintf(f, "%02X%02X", pix & 0xff, pix >> 8);
if (x % 16 == 15) fprintf(f, " ");
}
fprintf(f, "\n");
}
fprintf(f, "\n\n");
}
fclose(f);
}
logerror("---VBLANK---\n");
#endif
}