Sunplus unsp2.0 experiments for jak_car2 (nw) (#6073)

* let the hacking move us forward (nw)

* testing (nw)

* shifter behavior seems to bleed between regs (nw)

* (nw)

* avoid hang (nw)

* some hacks to get to the jak_gtg service mode too (nw)
This commit is contained in:
David Haywood 2019-12-19 17:13:11 +00:00 committed by ajrhacker
parent dc86fe6b1c
commit 699b8b14c7
8 changed files with 485 additions and 71 deletions

View File

@ -35,12 +35,32 @@ void unsp_20_device::execute_extended_group(uint16_t op)
switch (aluop)
{
case 0x00: // add
{
// A += B
logerror( "(Extended group 0) %s += %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
, (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
unimplemented_opcode(op, ximm);
//logerror( "(Extended group 0) %s += %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
// , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
m_core->m_icount -= 1; // TODO
uint16_t r0 = (ra & 0x8) ? m_secondary_r[ra & 0x7] : m_core->m_r[ra & 0x7];
uint16_t r1 = (rb & 0x8) ? m_secondary_r[rb & 0x7] : m_core->m_r[rb & 0x7];
uint32_t lres = r0 + r1;
update_nzsc(lres, r0, r1);
if (ra & 0x8)
{
m_secondary_r[ra & 0x7] = (uint16_t)lres;
}
else
{
m_core->m_r[ra & 0x7] = (uint16_t)lres;
}
//unimplemented_opcode(op, ximm);
return;
break;
}
case 0x01: // adc
// A += B, Carry
@ -67,12 +87,22 @@ void unsp_20_device::execute_extended_group(uint16_t op)
break;
case 0x04: // cmp
{
// CMP A,B
logerror( "(Extended group 0) cmp %s, %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
, (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
unimplemented_opcode(op, ximm);
//logerror( "(Extended group 0) cmp %s, %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
// , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
m_core->m_icount -= 1; // TODO
uint16_t r0 = (ra & 0x8) ? m_secondary_r[ra & 0x7] : m_core->m_r[ra & 0x7];
uint16_t r1 = (rb & 0x8) ? m_secondary_r[rb & 0x7] : m_core->m_r[rb & 0x7];
uint32_t lres = r0 + (uint16_t)(~r1) + uint32_t(1);
update_nzsc(lres, r0 , ~r1);
//unimplemented_opcode(op, ximm);
return;
break;
}
case 0x06: // neg
// A = -B
@ -91,13 +121,26 @@ void unsp_20_device::execute_extended_group(uint16_t op)
break;
case 0x09: // load
{
// A = B
logerror( "(Extended group 0) %s = %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
, (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
unimplemented_opcode(op, ximm);
//logerror("(Extended group 0) %s = %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
// , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
m_core->m_icount -= 1; // TODO
uint32_t lres = (rb & 0x8) ? m_secondary_r[rb & 0x7] : m_core->m_r[rb & 0x7];
update_nz(lres);
if (ra & 0x8)
{
m_secondary_r[ra & 0x7] = (uint16_t)lres;
}
else
{
m_core->m_r[ra & 0x7] = (uint16_t)lres;
}
return;
break;
}
case 0x0a: // or
// A |= B
logerror( "(Extended group 0) %s |= %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
@ -296,7 +339,7 @@ void unsp_20_device::execute_extended_group(uint16_t op)
// , imm16_2);
m_core->m_icount -= 1; // TODO
uint16_t lres = imm16_2;
uint32_t lres = imm16_2;
update_nz(lres);
if (ra & 0x8)
{
@ -437,7 +480,7 @@ void unsp_20_device::execute_extended_group(uint16_t op)
//uin32_t lreg = UNSP_LREG_I(imm16_2);
uint16_t lres = read16(imm16_2);
uint32_t lres = read16(imm16_2);
update_nz(lres);
if (ra & 0x8)
{
@ -960,7 +1003,7 @@ void unsp_20_device::execute_extended_group(uint16_t op)
m_core->m_icount -= 1; // TODO
uint16_t lres = m_secondary_r[rx] + (uint16_t)(~imm6) + uint32_t(1);
uint32_t lres = m_secondary_r[rx] + (uint16_t)(~imm6) + uint32_t(1);
update_nzsc(lres, m_secondary_r[rx] , ~imm6);
//unimplemented_opcode(op, ximm);
@ -988,7 +1031,7 @@ void unsp_20_device::execute_extended_group(uint16_t op)
m_core->m_icount -= 1; // TODO
uint16_t lres = imm6;
uint32_t lres = imm6;
update_nz(lres);
m_secondary_r[rx] = (uint16_t)lres;
@ -1042,18 +1085,46 @@ void unsp_20_device::execute_extended_group(uint16_t op)
switch (aluop)
{
case 0x00: // add
{
// A += B
logerror( "(Extended group 7) %s += [BP+%02x]\n", extregs[rx], imm6 );
unimplemented_opcode(op, ximm);
return;
break;
// logerror( "(Extended group 7) %s += [BP+%02x]\n", extregs[rx], imm6 );
m_core->m_icount -= 1; // TODO
case 0x01: // adc
// A += B, Carry
logerror( "(Extended group 7) %s += [BP+%02x], carry\n", extregs[rx], imm6 );
unimplemented_opcode(op, ximm);
uint16_t addr = (uint16_t)(m_core->m_r[REG_BP] + (imm6 & 0x3f));
uint16_t r0 = m_secondary_r[rx];
uint16_t r1 = read16(addr);
uint32_t lres = r0 + r1;
update_nzsc(lres, r0, r1);
m_secondary_r[rx] = lres;
//unimplemented_opcode(op, ximm);
return;
break;
}
case 0x01: // adc
{
// A += B, Carry
//logerror( "(Extended group 7) %s += [BP+%02x], carry\n", extregs[rx], imm6 );
m_core->m_icount -= 1; // TODO
uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0;
uint16_t addr = (uint16_t)(m_core->m_r[REG_BP] + (imm6 & 0x3f));
uint16_t r0 = m_secondary_r[rx];
uint16_t r1 = read16(addr);
uint32_t lres = r0 + r1 + c;
update_nzsc(lres, r0, r1);
m_secondary_r[rx] = lres;
//unimplemented_opcode(op, ximm);
return;
break;
}
case 0x02: // sub
// A -= B

View File

@ -181,34 +181,64 @@ void unsp_12_device::execute_exxx_group(uint16_t op)
case 0x02:
logerror("pc:%06x: %s = %s lsl %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]);
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) << (m_core->m_r[rs] & 0x0f));
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) << (m_core->m_r[rs] & 0x01f));
logerror("result %04x\n", m_core->m_r[rd]);
return;
case 0x03:
{
// wrlshunt uses this
logerror("pc:%06x: %s = %s lslor %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]);
uint16_t tmp = m_core->m_r[rd];
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) << (m_core->m_r[rs] & 0x0f));
m_core->m_r[rd] |= tmp; // guess
if (rd != 3) // 4 = R4 3 = R3 - the 'register bleeding' is only verified as needed between r3/r4, so bail for other regs until verified
unimplemented_opcode(op);
uint32_t res = (uint16_t)(m_core->m_r[rd]);
res <<= (m_core->m_r[rs] & 0x01f);
m_core->m_r[rd] = (res & 0xffff);
m_core->m_r[rd + 1] |= (res >> 16); // register bleeding?
logerror("result %04x\n", m_core->m_r[rd]);
return;
}
case 0x04:
// smartfp loops increasing shift by 4 up to values of 28? (but regs are 16-bit?)
// smartfp loops increasing shift by 4 up to values of 28? (but regs are 16-bit?)
logerror("pc:%06x: %s = %s lsr %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]);
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) >> (m_core->m_r[rs] & 0xf));
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) >> (m_core->m_r[rs] & 0x1f));
logerror("result %04x\n", m_core->m_r[rd]);
return;
case 0x05:
{
logerror("pc:%06x: %s = %s lsror %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]);
uint16_t tmp = m_core->m_r[rd];
m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) >> (m_core->m_r[rs] & 0x0f));
m_core->m_r[rd] |= tmp; // guess
if (rd != 4) // 4 = R4 3 = R3 - the 'register bleeding' is only verified as needed between r3/r4, so bail for other regs until verified
unimplemented_opcode(op);
uint32_t res = (uint16_t)(m_core->m_r[rd]);
res <<= 16;
res = res >> (m_core->m_r[rs] & 0x01f);
// register bleeding behavior needed (for example) in jak_cars2 nand browser when increasing upper digits of address
// TODO: check if I'm missing something becaus this doesn't really seem logical, maybe other code is meant to take care of those bits?
// (although R3/R4 are the 'MR' register used for multiply stuff, so maybe there is some logic to this?)
// code attempts to put a 32-bit value in r4/r3 then shift it like this?
//3c990: e92a r4 = r4 lsl r2
//3c991: e73a r3 = r3 lslor r2
m_core->m_r[rd] = (res >> 16);
m_core->m_r[rd - 1] |= (res & 0xffff); // register bleeding?
logerror("result %04x\n", m_core->m_r[rd]);
return;
}

View File

@ -45,14 +45,14 @@ inline void unsp_device::execute_fxxx_000_group(uint16_t op)
{
int r = op & 0x7;
logerror("%s = fr\n", regs[r]);
unimplemented_opcode(op);
// unimplemented_opcode(op);
return;
}
else if (((op & 0xf1f8) == 0xf038) && m_iso >= 12)
{
int r = op & 0x7;
logerror("fr = %s\n", regs[r]);
unimplemented_opcode(op);
// unimplemented_opcode(op);
return;
}

View File

@ -258,6 +258,12 @@ WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_7883_w) { LOGMASKED(LOG_GCM39
WRITE16_MEMBER(sunplus_gcm394_base_device::unkarea_78a0_w) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a0_w %04x\n", machine().describe_context(), data); m_78a0 = data; }
READ16_MEMBER(sunplus_gcm394_base_device::unkarea_78a0_r)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a0_r\n", machine().describe_context());
return machine().rand();
}
READ16_MEMBER(sunplus_gcm394_base_device::unkarea_78a1_r)
{
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a1_r\n", machine().describe_context());
@ -367,6 +373,7 @@ void sunplus_gcm394_base_device::gcm394_internal_map(address_map &map)
map(0x00702f, 0x00702f).w(m_spg_video, FUNC(gcm394_base_video_device::unk_vid2_gfxbase_msb_w)); // written with other unknown_video_device2 regs (roz layer or line layer?)
map(0x007030, 0x007030).rw(m_spg_video, FUNC(gcm394_base_video_device::video_7030_brightness_r), FUNC(gcm394_base_video_device::video_7030_brightness_w));
map(0x007038, 0x007038).r(m_spg_video, FUNC(gcm394_base_video_device::video_curline_r));
map(0x00703a, 0x00703a).rw(m_spg_video, FUNC(gcm394_base_video_device::video_703a_palettebank_r), FUNC(gcm394_base_video_device::video_703a_palettebank_w));
map(0x00703c, 0x00703c).w(m_spg_video, FUNC(gcm394_base_video_device::video_703c_w)); // TV Control 1
@ -455,7 +462,7 @@ void sunplus_gcm394_base_device::gcm394_internal_map(address_map &map)
map(0x007882, 0x007882).rw(FUNC(sunplus_gcm394_base_device::unkarea_7882_r), FUNC(sunplus_gcm394_base_device::unkarea_7882_w));
map(0x007883, 0x007883).rw(FUNC(sunplus_gcm394_base_device::unkarea_7883_r), FUNC(sunplus_gcm394_base_device::unkarea_7883_w));
map(0x0078a0, 0x0078a0).w(FUNC(sunplus_gcm394_base_device::unkarea_78a0_w));
map(0x0078a0, 0x0078a0).rw(FUNC(sunplus_gcm394_base_device::unkarea_78a0_r), FUNC(sunplus_gcm394_base_device::unkarea_78a0_w));
map(0x0078a1, 0x0078a1).r(FUNC(sunplus_gcm394_base_device::unkarea_78a1_r));
@ -518,11 +525,31 @@ READ16_MEMBER(generalplus_gpac800_device::unkarea_7854_r)
// jak_tsm code looks for various 'magic values'
if (m_testval == 1)
return 0xc2;
return 0x98;
else
return 0x58;
return 0x79;
}
// 7998
WRITE16_MEMBER(generalplus_gpac800_device::flash_addr_low_w)
{
//logerror("%s:sunplus_gcm394_base_device::flash_addr_low_w %04x\n", machine().describe_context(), data);
m_flash_addr_low = data;
}
WRITE16_MEMBER(generalplus_gpac800_device::flash_addr_high_w)
{
//logerror("%s:sunplus_gcm394_base_device::flash_addr_high_w %04x\n", machine().describe_context(), data);
m_flash_addr_high = data;
uint32_t address = (m_flash_addr_high << 16) | m_flash_addr_low;
logerror("%s: flash address is now %08x\n", machine().describe_context(), address);
}
// all tilemap registers etc. appear to be in the same place as the above system, including the 'extra' ones not on the earlier models
// so it's likely this is built on top of that just with NAND support
void generalplus_gpac800_device::gpac800_internal_map(address_map& map)
@ -535,6 +562,11 @@ void generalplus_gpac800_device::gpac800_internal_map(address_map& map)
// this should be the NAND device, as the games attempt to do a DMA operation with '7854' as the source, and the target
// as the RAM location where code needs to end up before jumping to it
map(0x007850, 0x007850).r(FUNC(generalplus_gpac800_device::unkarea_7850_r)); // 'device ready' status flag?
map(0x007852, 0x007852).w(FUNC(generalplus_gpac800_device::flash_addr_low_w));
map(0x007853, 0x007853).w(FUNC(generalplus_gpac800_device::flash_addr_high_w));
map(0x007854, 0x007854).r(FUNC(generalplus_gpac800_device::unkarea_7854_r)); // data read port (timing appears to be important)
}
@ -637,9 +669,17 @@ void sunplus_gcm394_base_device::device_reset()
}
void generalplus_gpac800_device::device_reset()
{
sunplus_gcm394_base_device::device_reset();
m_flash_addr_low = 0x0000;
m_flash_addr_high = 0x0000;
}
IRQ_CALLBACK_MEMBER(sunplus_gcm394_base_device::irq_vector_cb)
{
//printf("irq_vector_cb %d\n", irqline);
//logerror("irq_vector_cb %d\n", irqline);
if (irqline == UNSP_IRQ6_LINE)
set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);

View File

@ -213,6 +213,7 @@ private:
DECLARE_WRITE16_MEMBER(unkarea_78a0_w);
DECLARE_READ16_MEMBER(unkarea_78a0_r);
DECLARE_READ16_MEMBER(unkarea_78a1_r);
DECLARE_WRITE16_MEMBER(unkarea_78a4_w);
@ -291,11 +292,21 @@ public:
protected:
void gpac800_internal_map(address_map &map);
//virtual void device_start() override;
virtual void device_reset() override;
private:
DECLARE_READ16_MEMBER(unkarea_7850_r);
DECLARE_READ16_MEMBER(unkarea_7854_r);
DECLARE_WRITE16_MEMBER(flash_addr_low_w);
DECLARE_WRITE16_MEMBER(flash_addr_high_w);
int m_testval;
uint16_t m_flash_addr_low;
uint16_t m_flash_addr_high;
};

View File

@ -389,24 +389,24 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
{
uint32_t xscroll = regs[0];
uint32_t yscroll = regs[1];
uint32_t attr = regs[2];
uint32_t ctrl = regs[3];
uint32_t attr_reg = regs[2];
uint32_t ctrl_reg = regs[3];
uint32_t tilemap = regs[4];
uint32_t palette_map = regs[5];
address_space &space = m_cpu->space(AS_PROGRAM);
if (!(ctrl & PAGE_ENABLE_MASK))
if (!(ctrl_reg & PAGE_ENABLE_MASK))
{
return;
}
if (((attr & PAGE_PRIORITY_FLAG_MASK) >> PAGE_PRIORITY_FLAG_SHIFT) != priority)
if (((attr_reg & PAGE_PRIORITY_FLAG_MASK) >> PAGE_PRIORITY_FLAG_SHIFT) != priority)
{
return;
}
uint32_t tile_h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
uint32_t tile_w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
uint32_t tile_h = 8 << ((attr_reg & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
uint32_t tile_w = 8 << ((attr_reg & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
uint32_t tile_count_x = 512 / tile_w;
@ -419,23 +419,22 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
{
uint32_t yy = ((tile_h * y0 - yscroll + 0x10) & 0xff) - 0x10;
uint32_t xx = (tile_w * x0 - xscroll) & 0x1ff;
uint32_t tile = (ctrl & PAGE_WALLPAPER_MASK) ? space.read_word(tilemap) : space.read_word(tilemap + tile_address);
uint32_t tile = (ctrl_reg & PAGE_WALLPAPER_MASK) ? space.read_word(tilemap) : space.read_word(tilemap + tile_address);
uint16_t palette = (ctrl & PAGE_WALLPAPER_MASK) ? space.read_word(palette_map) : space.read_word(palette_map + tile_address / 2);
uint16_t palette = (ctrl_reg & PAGE_WALLPAPER_MASK) ? space.read_word(palette_map) : space.read_word(palette_map + tile_address / 2);
if (x0 & 1)
palette >>= 8;
tile |= (palette & 0x0007) << 16;
if (!tile)
continue;
uint32_t tileattr = attr;
uint32_t tilectrl = ctrl;
uint32_t tileattr = attr_reg;
uint32_t tilectrl = ctrl_reg;
#if 0
if ((ctrl & 2) == 0)
if ((ctrl_reg & 2) == 0)
{ // -(1) bld(1) flip(2) pal(4)
tileattr &= ~0x000c;
tileattr |= (palette >> 2) & 0x000c; // flip
@ -447,32 +446,55 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
tilectrl |= (palette << 2) & 0x0100; // blend
}
#endif
const bool blend = (tileattr & 0x4000 || tilectrl & 0x0100);
const bool row_scroll = (tilectrl & 0x0010);
const bool flip_x = (tileattr & TILE_X_FLIP);
const uint32_t yflipmask = tileattr & TILE_Y_FLIP ? tile_h - 1 : 0;
uint32_t palette_offset = (tileattr & 0x0f00) >> 4;
bool blend;
bool row_scroll;
bool flip_x;
uint32_t yflipmask;
uint32_t palette_offset;
blend = (tileattr & 0x4000 || tilectrl & 0x0100);
row_scroll = (tilectrl & 0x0010);
int use_alt_drawmode;
if ((ctrl_reg & 2) == 0)
{
flip_x = 0;
yflipmask = 0;
palette_offset = (palette & 0x0f) << 4;
use_alt_drawmode = 1;
}
else
{
flip_x = (tileattr & TILE_X_FLIP);
yflipmask = tileattr & TILE_Y_FLIP ? tile_h - 1 : 0;
palette_offset = (tileattr & 0x0f00) >> 4;
tile |= (palette & 0x0007) << 16;
use_alt_drawmode = 0;
}
//palette_offset |= 0x0900;
palette_offset |= 0x0100;
const uint8_t bpp = tileattr & 0x0003;
if (blend)
{
if (row_scroll)
{
if (flip_x)
draw<BlendOn, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
draw<BlendOn, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
else
draw<BlendOn, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
draw<BlendOn, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
}
else
{
if (flip_x)
draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
draw<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
else
draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
draw<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
}
}
else
@ -480,16 +502,16 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
if (row_scroll)
{
if (flip_x)
draw<BlendOff, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
draw<BlendOff, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
else
draw<BlendOff, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
draw<BlendOff, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
}
else
{
if (flip_x)
draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
draw<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
else
draw<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, 0);
draw<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, bitmap_addr, tile, tile_h, tile_w, bpp, yflipmask, palette_offset, use_alt_drawmode);
}
}
}
@ -963,6 +985,12 @@ WRITE16_MEMBER(gcm394_base_video_device::video_7063_videoirq_source_ack_w)
WRITE16_MEMBER(gcm394_base_video_device::video_702a_w) { LOGMASKED(LOG_GCM394_VIDEO, "%s:gcm394_base_video_device::video_702a_w %04x\n", machine().describe_context(), data); m_702a = data; }
READ16_MEMBER(gcm394_base_video_device::video_curline_r)
{
LOGMASKED(LOG_GCM394_VIDEO, "%s: video_r: Current Line: %04x\n", machine().describe_context(), m_screen->vpos());
return m_screen->vpos();
}
// read in IRQ
READ16_MEMBER(gcm394_base_video_device::video_7030_brightness_r)
{

View File

@ -68,6 +68,7 @@ public:
DECLARE_WRITE16_MEMBER(video_702a_w);
DECLARE_READ16_MEMBER(video_7030_brightness_r);
DECLARE_WRITE16_MEMBER(video_7030_brightness_w);
DECLARE_READ16_MEMBER(video_curline_r);
DECLARE_WRITE16_MEMBER(video_703c_w);
DECLARE_READ16_MEMBER(video_707c_r);

View File

@ -5,12 +5,29 @@
Compared to vii.cpp this is clearly newer, has extra opcodes, different internal map etc. also scaling and higher resolutions based on Spongebob
GPL600
Smart Fit Park
SpongeBob SquarePants Bikini Bottom 500
Spiderman - The Masked Menace 'Spider Sense' (pad type with Spiderman model)
(Wireless Hunting? - maybe, register map looks the same even if it sets stack to 2fff not 6fff)
as these use newer opcodes in the FExx range they probably need a derived unSP type too
GPL800 (== GPL600 with NAND support + maybe more)
Wireless Air 60
Golden Tee Golf
Cars 2
Toy Story Mania
V.Baby
Playskool Heroes Transformers Rescue Bots Beam Box
GPL500 (unknown, might be GPL600 but without the higher resolution support?)
The Price is Right
Bejeweled? (might be GPL600)
Notes
smartfp: hold button Circle, Star and Home on startup for Test Menu
these are both unsp 2.0 type, as they use the extended ocpodes
*/
#include "emu.h"
@ -373,7 +390,7 @@ static INPUT_PORTS_START( gcm394 )
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON15 ) PORT_CODE(KEYCODE_OPENBRACE) PORT_NAME("10")
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON16 ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_NAME("11")
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(KEYCODE_A) PORT_NAME("Circle / Red") // hold button Circle and Star on startup for test menu (other conditions? doesn't always work?)
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(KEYCODE_A) PORT_NAME("Circle / Red")
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(KEYCODE_S) PORT_NAME("Square / Orange")
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CODE(KEYCODE_D) PORT_NAME("Triangle / Yellow")
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_CODE(KEYCODE_F) PORT_NAME("Star / Blue")
@ -432,6 +449,188 @@ static INPUT_PORTS_START( wrlshunt )
PORT_START("P2")
INPUT_PORTS_END
static INPUT_PORTS_START( jak_car2 )
PORT_START("P1")
PORT_DIPNAME( 0x0001, 0x0001, "P1" )
PORT_DIPSETTING( 0x0001, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0008, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0010, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_UP )
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON3 ) // unused
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )
PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_START("P2")
PORT_DIPNAME( 0x0001, 0x0001, "P2" )
PORT_DIPSETTING( 0x0001, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0008, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0010, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0020, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0040, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0100, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0200, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0400, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0800, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
INPUT_PORTS_END
static INPUT_PORTS_START( jak_gtg )
PORT_START("P1")
PORT_DIPNAME( 0x0001, 0x0001, "P1" )
PORT_DIPSETTING( 0x0001, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0100, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0200, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0400, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0800, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_START("P2")
PORT_DIPNAME( 0x0001, 0x0001, "P2" )
PORT_DIPSETTING( 0x0001, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0008, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0010, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0020, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0040, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0100, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0200, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0400, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x0800, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x4000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
INPUT_PORTS_END
/*
Wireless Hunting Video Game System
(info provided with dump)
@ -605,7 +804,41 @@ void generalplus_gpac800_game_state::machine_reset()
mem.write_word(dest+i, word);
}
int rambase = 0x30000;
for (int i = 0x4000/2; i < 0x37c000/2; i++)
{
uint16_t word = m_strippedrom[(i * 2) + 0] | (m_strippedrom[(i * 2) + 1] << 8);
m_mainram[rambase] = word;
rambase++;
}
mem.write_word(0xfff5, 0x6fea);
mem.write_word(0xfff6, 0x6fec);
mem.write_word(0xfff7, dest+0x20); // point boot vector at code in RAM
mem.write_word(0xfff8, 0x6ff0);
mem.write_word(0xfff9, 0x6ff2);
mem.write_word(0xfffa, 0x6ff4);
mem.write_word(0xfffb, 0x6ff6);
mem.write_word(0xfffc, 0x6ff8);
mem.write_word(0xfffd, 0x6ffa);
mem.write_word(0xfffe, 0x6ffc);
mem.write_word(0xffff, 0x6ffe);
// note, these patch the code copied to SRAM so the 'PROGRAM ROM' check fails (it passes otherwise)
if (mem.read_word(0x3f368) == 0x4840)
mem.write_word(0x3f368, 0x4841); // cars 2 IRQ? wait hack
if (mem.read_word(0x4368c) == 0x4846)
mem.write_word(0x4368c, 0x4840); // cars 2 force service mode
if (mem.read_word(0x4d8d4) == 0x4840)
mem.write_word(0x4d8d4, 0x4841); // golden tee IRQ? wait hack
if (mem.read_word(0x34410) == 0x4846)
mem.write_word(0x34410, 0x4840); // golden tee force service mode
m_maincpu->reset(); // reset CPU so vector gets read etc.
}
@ -631,7 +864,7 @@ void generalplus_gpac800_game_state::nand_init(int blocksize, int blocksize_stri
}
// debug to allow for easy use of unidasm.exe
if (1)
if (0)
{
FILE *fp;
char filename[256];
@ -657,9 +890,9 @@ void generalplus_gpac800_game_state::nand_init840()
// NAND dumps w/ internal bootstrap (and u'nSP 2.0 extended opcodes) (have gpnandnand strings)
// the JAKKS ones seem to be known as 'Generalplus GPAC800' hardware
CONS(2010, wlsair60, 0, 0, generalplus_gpac800, gcm394, generalplus_gpac800_game_state, nand_init840, "Jungle Soft / Kids Station Toys Inc", "Wireless Air 60", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_gtg, 0, 0, generalplus_gpac800, gcm394, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Golden Tee Golf (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_car2, 0, 0, generalplus_gpac800, gcm394, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Cars 2 (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_tsm , 0, 0, generalplus_gpac800, gcm394, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Toy Story Mania (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, vbaby, 0, 0, generalplus_gpac800, gcm394, generalplus_gpac800_game_state, nand_init840, "VTech", "V.Baby", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, beambox, 0, 0, generalplus_gpac800, gcm394, generalplus_gpac800_game_state, nand_init210, "Hasbro", "Playskool Heroes Transformers Rescue Bots Beam Box (Spain)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(2010, wlsair60, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init840, "Jungle Soft / Kids Station Toys Inc", "Wireless Air 60", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_gtg, 0, 0, generalplus_gpac800, jak_gtg, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Golden Tee Golf (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_car2, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Cars 2 (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, jak_tsm , 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init210, "JAKKS Pacific Inc", "Toy Story Mania (JAKKS Pacific TV Game)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, vbaby, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init840, "VTech", "V.Baby", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
CONS(200?, beambox, 0, 0, generalplus_gpac800, jak_car2, generalplus_gpac800_game_state, nand_init210, "Hasbro", "Playskool Heroes Transformers Rescue Bots Beam Box (Spain)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)