-unsp: opcodes that use the data segment affect it on rollover. Fixes many Vii and Zone 60 video bugs. [Ryan Holtz]

-vii: Fixed a typo which caused several tilemap bugs. [Ryan Holtz]
This commit is contained in:
mooglyguy 2018-10-01 16:54:18 +02:00
parent 02fcc308c0
commit 0247bafad1
3 changed files with 112 additions and 52 deletions

View File

@ -1,12 +1,12 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/**************************\
*
* SunPlus u'nSP core
*
* by Ryan Holtz
*
\**************************/
/*****************************************************************************
SunPlus micro'nSP core
based primarily on Unununium, by segher
*****************************************************************************/
#include "emu.h"
#include "unsp.h"
@ -248,7 +248,7 @@ void unsp_device::check_irqs()
}
else
{
trigger_irq(highest_irq);
trigger_irq(highest_irq - 1);
}
}
@ -605,15 +605,21 @@ void unsp_device::execute_run()
if (OP0 != 0x0d)
r1 = read16(r2);
UNSP_REG_I(opb)--;
if (UNSP_REG_I(opb) == 0xffff)
UNSP_REG(SR) -= 0x0400;
break;
case 2: // r, [<ds:>r++]
r2 = UNSP_LREG_I(opb);
if (OP0 != 0x0d)
r1 = read16(r2);
UNSP_REG_I(opb)++;
if (UNSP_REG_I(opb) == 0x0000)
UNSP_REG(SR) += 0x0400;
break;
case 3: // r, [<ds:>++r]
UNSP_REG_I(opb)++;
if (UNSP_REG_I(opb) == 0x0000)
UNSP_REG(SR) += 0x0400;
r2 = UNSP_LREG_I(opb);
if (OP0 != 0x0d)
r1 = read16(r2);

View File

@ -36,7 +36,8 @@ enum
enum
{
UNSP_IRQ0_LINE = 0,
UNSP_FIQ_LINE = 0,
UNSP_IRQ0_LINE,
UNSP_IRQ1_LINE,
UNSP_IRQ2_LINE,
UNSP_IRQ3_LINE,
@ -44,7 +45,6 @@ enum
UNSP_IRQ5_LINE,
UNSP_IRQ6_LINE,
UNSP_IRQ7_LINE,
UNSP_FIQ_LINE,
UNSP_BRK_LINE,
UNSP_NUM_LINES

View File

@ -52,14 +52,10 @@ also on this hardware
Detailed list of bugs:
- When loading a cart from file manager, sometimes it will crash
- On 'vii_vc1' & 'vii_vc2' cart, the left-right keys are transposed with the up-down keys
- The game 'Jewel Master' on both above carts displays a priority error at top of screen
- In the default bios (no cart loaded):
-- In the menu, when 'Come On!' is selected, a graphics error appears
-- Bowling, in between frames (bowling frames, not emulator frames) there is a small glitched sprite towards the lower-right
-- The "MOTOR" option in the diagnostic menu does nothing when selected
- Zone 60 / Wireless 60:
-- Speed Runner is missing the majority of its title screen. Opcode bug?
-- Auto Racing / Auto X, Dragon, Yummy, some other games: some sprites are inverted or opaque where they should be transparent
-- Auto Racing / Auto X, Dragon, some other games: some sprites are inverted or opaque where they should be transparent
-- Basketball: emulator crashes when starting the game due to jumping to invalid code.
@ -77,6 +73,7 @@ Detailed list of bugs:
#include "screen.h"
#include "softlist.h"
#define VII_DEBUG_VIDEO (0)
#define PAGE_ENABLE_MASK 0x0008
#define PAGE_BLANK_MASK 0x0004
@ -180,6 +177,9 @@ private:
bool m_hide_page0;
bool m_hide_page1;
bool m_hide_sprites;
bool m_debug_sprites;
bool m_debug_blit;
uint8_t m_sprite_index_to_debug;
uint16_t m_io_regs[0x200];
std::unique_ptr<uint8_t[]> m_serial_eeprom;
@ -260,7 +260,7 @@ private:
#define VERBOSE_LEVEL (4)
#define ENABLE_VERBOSE_LOG (1)
#define ENABLE_VERBOSE_LOG (0)
inline void spg2xx_game_state::verboselog(int n_level, const char *s_fmt, ...)
{
@ -325,8 +325,17 @@ void spg2xx_game_state::blit(bitmap_rgb32 &bitmap, const rectangle &cliprect, ui
uint32_t nc = ((attr & 0x0003) + 1) << 1;
uint32_t palette_offset = (attr & 0x0f00) >> 4;
if (m_debug_blit && VII_DEBUG_VIDEO)
{
printf("xy:%08x,%08x attr:%08x ctrl:%08x bitmap_addr:%08x tile:%04x\n", xoff, yoff, attr, ctrl, bitmap_addr, tile);
printf("hw:%d,%d f:%d,%d fm:%d,%d ncols:%d pobs:%02x ", w, h, (attr & TILE_X_FLIP) ? 1 : 0, (attr & TILE_Y_FLIP) ? 1 : 0, xflipmask, yflipmask, nc, palette_offset);
}
palette_offset >>= nc;
palette_offset <<= nc;
if (m_debug_blit && VII_DEBUG_VIDEO)
{
printf("poas:%02x\n", palette_offset);
}
uint32_t m = bitmap_addr + nc * w*h / 16 * tile;
uint32_t bits = 0;
@ -338,21 +347,30 @@ void spg2xx_game_state::blit(bitmap_rgb32 &bitmap, const rectangle &cliprect, ui
if (yy >= 0x01c0)
yy -= 0x0200;
if (m_debug_blit && VII_DEBUG_VIDEO)
printf("%3d:\n", yy);
for (uint32_t x = 0; x < w; x++)
{
int xx = xoff + (x ^ xflipmask);
bits <<= nc;
if (m_debug_blit && VII_DEBUG_VIDEO)
printf(" %08x:%d ", bits, nbits);
if (nbits < nc)
{
uint16_t b = space.read_word(m++ & 0x3fffff);
b = (b << 8) | (b >> 8);
bits |= b << (nc - nbits);
nbits += 16;
if (m_debug_blit && VII_DEBUG_VIDEO)
printf("(%04x:%08x:%d) ", b, bits, nbits);
}
nbits -= nc;
uint32_t pal = palette_offset + (bits >> 16);
if (m_debug_blit && VII_DEBUG_VIDEO)
printf("%02x:%02x:%04x ", bits >> 16, pal, bits & 0xffff);
bits &= 0xffff;
if ((ctrl & 0x0010) && yy < 240)
@ -365,17 +383,27 @@ void spg2xx_game_state::blit(bitmap_rgb32 &bitmap, const rectangle &cliprect, ui
if (xx >= 0 && xx < 320 && yy >= 0 && yy < 240)
{
uint16_t rgb = m_p_palette[pal];
if (m_debug_blit && VII_DEBUG_VIDEO)
printf("rgb:%04x ", rgb);
if (!(rgb & 0x8000))
{
if (attr & 0x4000 || ctrl & 0x0100)
{
if (m_debug_blit && VII_DEBUG_VIDEO)
printf("M\n");
mix_pixel(xx + 320 * yy, rgb);
}
else
{
if (m_debug_blit && VII_DEBUG_VIDEO)
printf("S\n");
set_pixel(xx + 320 * yy, rgb);
}
}
else if (m_debug_blit && VII_DEBUG_VIDEO)
{
printf("X\n");
}
}
}
}
@ -436,8 +464,8 @@ void spg2xx_game_state::blit_page(bitmap_rgb32 &bitmap, const rectangle &cliprec
tileattr &= ~0x0f00;
tileattr |= (palette << 8) & 0x0f00; // palette
tileattr &= ~0x0100;
tileattr |= (palette << 2) & 0x0100; // blend
tilectrl &= ~0x0100;
tilectrl |= (palette << 2) & 0x0100; // blend
}
yy = ((h*y0 - yscroll + 0x10) & 0xff) - 0x10;
@ -451,15 +479,12 @@ void spg2xx_game_state::blit_page(bitmap_rgb32 &bitmap, const rectangle &cliprec
void spg2xx_game_state::blit_sprite(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth, uint32_t base_addr)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
uint16_t tile, attr;
int16_t x, y;
uint32_t h, w;
uint32_t bitmap_addr = 0x40 * m_video_regs[0x22];
tile = space.read_word(base_addr + 0);
x = space.read_word(base_addr + 1);
y = space.read_word(base_addr + 2);
attr = space.read_word(base_addr + 3);
uint16_t tile = space.read_word(base_addr + 0);
int16_t x = space.read_word(base_addr + 1);
int16_t y = space.read_word(base_addr + 2);
uint16_t attr = space.read_word(base_addr + 3);
if (!tile)
{
@ -476,8 +501,8 @@ void spg2xx_game_state::blit_sprite(bitmap_rgb32 &bitmap, const rectangle &clipr
x = 160 + x;
y = 120 - y;
h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
x -= (w / 2);
y -= (h / 2) - 8;
@ -486,7 +511,14 @@ void spg2xx_game_state::blit_sprite(bitmap_rgb32 &bitmap, const rectangle &clipr
x &= 0x01ff;
y &= 0x01ff;
#if VII_DEBUG_VIDEO
if (m_debug_sprites && machine().input().code_pressed(KEYCODE_MINUS))
m_debug_blit = true;
blit(bitmap, cliprect, x, y, attr, 0, bitmap_addr, tile);
m_debug_blit = false;
#else
blit(bitmap, cliprect, x, y, attr, 0, bitmap_addr, tile);
#endif
}
void spg2xx_game_state::blit_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, int depth)
@ -496,13 +528,21 @@ void spg2xx_game_state::blit_sprites(bitmap_rgb32 &bitmap, const rectangle &clip
return;
}
for (uint32_t n = 0; n < 256; n++)
#if VII_DEBUG_VIDEO
if (!m_debug_sprites)
{
//if(space.read_word(0x2c00 + 4*n)
#endif
for (uint32_t n = 0; n < 256; n++)
{
blit_sprite(bitmap, cliprect, depth, 0x2c00 + 4 * n);
}
#if VII_DEBUG_VIDEO
}
else
{
blit_sprite(bitmap, cliprect, depth, 0x2c00 + 4 * m_sprite_index_to_debug);
}
#endif
}
uint32_t spg2xx_game_state::screen_update_vii(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -599,15 +639,19 @@ WRITE16_MEMBER(spg2xx_game_state::video_w)
case 0x37: // IRQ pos H
data &= 0x01ff;
COMBINE_DATA(&m_video_regs[offset]);
m_screenpos_timer->adjust(m_screen->time_until_pos(m_video_regs[0x36], m_video_regs[0x37]));
verboselog(0, "video_w: Video IRQ Position: %04x,%04x (%04x)\n", m_video_regs[0x37], m_video_regs[0x36], 0x2800 | offset);
if (m_video_regs[0x37] < 160 && m_video_regs[0x36] < 240)
m_screenpos_timer->adjust(m_screen->time_until_pos(m_video_regs[0x36], m_video_regs[0x37] << 1));
else
m_screenpos_timer->adjust(attotime::never);
break;
case 0x62: // Video IRQ Enable
{
verboselog(0, "video_w: Video IRQ Enable = %04x (%04x)\n", data, mem_mask);
const uint16_t old = VII_VIDEO_IRQ_ENABLE;
const uint16_t old = VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS;
COMBINE_DATA(&VII_VIDEO_IRQ_ENABLE);
const uint16_t changed = old ^ VII_VIDEO_IRQ_ENABLE;
const uint16_t changed = old ^ (VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS);
if (changed)
check_video_irq();
break;
@ -616,9 +660,9 @@ WRITE16_MEMBER(spg2xx_game_state::video_w)
case 0x63: // Video IRQ Acknowledge
{
verboselog(0, "video_w: Video IRQ Acknowledge = %04x (%04x)\n", data, mem_mask);
const uint16_t old = VII_VIDEO_IRQ_STATUS;
const uint16_t old = VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS;
VII_VIDEO_IRQ_STATUS &= ~data;
const uint16_t changed = old ^ VII_VIDEO_IRQ_STATUS;
const uint16_t changed = old ^ (VII_VIDEO_IRQ_ENABLE & VII_VIDEO_IRQ_STATUS);
if (changed)
check_video_irq();
break;
@ -1369,7 +1413,6 @@ void spg2xx_game_state::device_timer(emu_timer &timer, device_timer_id id, int p
}
void spg2xx_cart_state::machine_start()
{
spg2xx_game_state::machine_start();
@ -1384,6 +1427,22 @@ void spg2xx_cart_state::machine_start()
}
void spg2xx_game_state::machine_start()
{
m_tmb1 = timer_alloc(TIMER_TMB1);
m_tmb2 = timer_alloc(TIMER_TMB2);
m_tmb1->adjust(attotime::never);
m_tmb2->adjust(attotime::never);
m_screenpos_timer = timer_alloc(TIMER_SCREENPOS);
m_screenpos_timer->adjust(attotime::never);
m_bank->configure_entries(0, ceilf((float)memregion("maincpu")->bytes() / 0x800000), memregion("maincpu")->base(), 0x800000);
m_bank->set_entry(0);
m_serial_eeprom = std::make_unique<uint8_t[]>(0x400);
}
void spg2xx_game_state::machine_reset()
{
memset(m_video_regs, 0, 0x100 * sizeof(m_video_regs[0]));
memset(m_io_regs, 0, 0x200 * sizeof(m_io_regs[0]));
@ -1398,26 +1457,12 @@ void spg2xx_game_state::machine_start()
m_video_regs[0x36] = 0xffff;
m_video_regs[0x37] = 0xffff;
m_tmb1 = timer_alloc(TIMER_TMB1);
m_tmb2 = timer_alloc(TIMER_TMB2);
m_tmb1->adjust(attotime::never);
m_tmb2->adjust(attotime::never);
m_screenpos_timer = timer_alloc(TIMER_SCREENPOS);
m_screenpos_timer->adjust(attotime::never);
m_bank->configure_entries(0, ceilf((float)memregion("maincpu")->bytes() / 0x800000), memregion("maincpu")->base(), 0x800000);
m_bank->set_entry(0);
m_serial_eeprom = std::make_unique<uint8_t[]>(0x400);
m_hide_page0 = false;
m_hide_page1 = false;
m_hide_sprites = false;
}
void spg2xx_game_state::machine_reset()
{
m_debug_sprites = false;
m_debug_blit = false;
m_sprite_index_to_debug = 0;
}
WRITE_LINE_MEMBER(spg2xx_game_state::vii_vblank)
@ -1425,12 +1470,21 @@ WRITE_LINE_MEMBER(spg2xx_game_state::vii_vblank)
if (!state)
return;
#if VII_DEBUG_VIDEO
if (machine().input().code_pressed_once(KEYCODE_5))
m_hide_page0 = !m_hide_page0;
if (machine().input().code_pressed_once(KEYCODE_6))
m_hide_page1 = !m_hide_page1;
if (machine().input().code_pressed_once(KEYCODE_7))
m_hide_sprites = !m_hide_sprites;
if (machine().input().code_pressed_once(KEYCODE_8))
m_debug_sprites = !m_debug_sprites;
if (machine().input().code_pressed_once(KEYCODE_9))
m_sprite_index_to_debug--;
if (machine().input().code_pressed_once(KEYCODE_0))
m_sprite_index_to_debug++;
#endif
int32_t x = m_io_motionx ? ((int32_t)m_io_motionx->read() - 0x200) : 0;
int32_t y = m_io_motiony ? ((int32_t)m_io_motiony->read() - 0x200) : 0;
int32_t z = m_io_motionz ? ((int32_t)m_io_motionz->read() - 0x200) : 0;