mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
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:
parent
dc86fe6b1c
commit
699b8b14c7
@ -35,12 +35,32 @@ void unsp_20_device::execute_extended_group(uint16_t op)
|
|||||||
switch (aluop)
|
switch (aluop)
|
||||||
{
|
{
|
||||||
case 0x00: // add
|
case 0x00: // add
|
||||||
|
{
|
||||||
// A += B
|
// A += B
|
||||||
logerror( "(Extended group 0) %s += %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
|
//logerror( "(Extended group 0) %s += %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
|
||||||
, (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
|
// , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
|
||||||
unimplemented_opcode(op, ximm);
|
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;
|
return;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 0x01: // adc
|
case 0x01: // adc
|
||||||
// A += B, Carry
|
// A += B, Carry
|
||||||
@ -67,12 +87,22 @@ void unsp_20_device::execute_extended_group(uint16_t op)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04: // cmp
|
case 0x04: // cmp
|
||||||
|
{
|
||||||
// CMP A,B
|
// CMP A,B
|
||||||
logerror( "(Extended group 0) cmp %s, %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
|
//logerror( "(Extended group 0) cmp %s, %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
|
||||||
, (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
|
// , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
|
||||||
unimplemented_opcode(op, ximm);
|
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;
|
return;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 0x06: // neg
|
case 0x06: // neg
|
||||||
// A = -B
|
// A = -B
|
||||||
@ -91,13 +121,26 @@ void unsp_20_device::execute_extended_group(uint16_t op)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x09: // load
|
case 0x09: // load
|
||||||
|
{
|
||||||
// A = B
|
// A = B
|
||||||
logerror( "(Extended group 0) %s = %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
|
//logerror("(Extended group 0) %s = %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
|
||||||
, (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
|
// , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]);
|
||||||
unimplemented_opcode(op, ximm);
|
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;
|
return;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 0x0a: // or
|
case 0x0a: // or
|
||||||
// A |= B
|
// A |= B
|
||||||
logerror( "(Extended group 0) %s |= %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7]
|
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);
|
// , imm16_2);
|
||||||
m_core->m_icount -= 1; // TODO
|
m_core->m_icount -= 1; // TODO
|
||||||
|
|
||||||
uint16_t lres = imm16_2;
|
uint32_t lres = imm16_2;
|
||||||
update_nz(lres);
|
update_nz(lres);
|
||||||
if (ra & 0x8)
|
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);
|
//uin32_t lreg = UNSP_LREG_I(imm16_2);
|
||||||
|
|
||||||
uint16_t lres = read16(imm16_2);
|
uint32_t lres = read16(imm16_2);
|
||||||
update_nz(lres);
|
update_nz(lres);
|
||||||
if (ra & 0x8)
|
if (ra & 0x8)
|
||||||
{
|
{
|
||||||
@ -960,7 +1003,7 @@ void unsp_20_device::execute_extended_group(uint16_t op)
|
|||||||
|
|
||||||
m_core->m_icount -= 1; // TODO
|
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);
|
update_nzsc(lres, m_secondary_r[rx] , ~imm6);
|
||||||
|
|
||||||
//unimplemented_opcode(op, ximm);
|
//unimplemented_opcode(op, ximm);
|
||||||
@ -988,7 +1031,7 @@ void unsp_20_device::execute_extended_group(uint16_t op)
|
|||||||
|
|
||||||
m_core->m_icount -= 1; // TODO
|
m_core->m_icount -= 1; // TODO
|
||||||
|
|
||||||
uint16_t lres = imm6;
|
uint32_t lres = imm6;
|
||||||
update_nz(lres);
|
update_nz(lres);
|
||||||
m_secondary_r[rx] = (uint16_t)lres;
|
m_secondary_r[rx] = (uint16_t)lres;
|
||||||
|
|
||||||
@ -1042,18 +1085,46 @@ void unsp_20_device::execute_extended_group(uint16_t op)
|
|||||||
switch (aluop)
|
switch (aluop)
|
||||||
{
|
{
|
||||||
case 0x00: // add
|
case 0x00: // add
|
||||||
|
{
|
||||||
// A += B
|
// A += B
|
||||||
logerror( "(Extended group 7) %s += [BP+%02x]\n", extregs[rx], imm6 );
|
// logerror( "(Extended group 7) %s += [BP+%02x]\n", extregs[rx], imm6 );
|
||||||
unimplemented_opcode(op, ximm);
|
m_core->m_icount -= 1; // TODO
|
||||||
return;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x01: // adc
|
uint16_t addr = (uint16_t)(m_core->m_r[REG_BP] + (imm6 & 0x3f));
|
||||||
// A += B, Carry
|
uint16_t r0 = m_secondary_r[rx];
|
||||||
logerror( "(Extended group 7) %s += [BP+%02x], carry\n", extregs[rx], imm6 );
|
uint16_t r1 = read16(addr);
|
||||||
unimplemented_opcode(op, ximm);
|
|
||||||
|
uint32_t lres = r0 + r1;
|
||||||
|
|
||||||
|
update_nzsc(lres, r0, r1);
|
||||||
|
|
||||||
|
m_secondary_r[rx] = lres;
|
||||||
|
|
||||||
|
//unimplemented_opcode(op, ximm);
|
||||||
return;
|
return;
|
||||||
break;
|
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
|
case 0x02: // sub
|
||||||
// A -= B
|
// A -= B
|
||||||
|
@ -181,17 +181,28 @@ void unsp_12_device::execute_exxx_group(uint16_t op)
|
|||||||
|
|
||||||
case 0x02:
|
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]);
|
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]);
|
logerror("result %04x\n", m_core->m_r[rd]);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
{
|
{
|
||||||
// wrlshunt uses this
|
// 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]);
|
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));
|
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
|
||||||
m_core->m_r[rd] |= tmp; // guess
|
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]);
|
logerror("result %04x\n", m_core->m_r[rd]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -199,16 +210,35 @@ void unsp_12_device::execute_exxx_group(uint16_t op)
|
|||||||
case 0x04:
|
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]);
|
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]);
|
logerror("result %04x\n", m_core->m_r[rd]);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x05:
|
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]);
|
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));
|
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
|
||||||
m_core->m_r[rd] |= tmp; // guess
|
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]);
|
logerror("result %04x\n", m_core->m_r[rd]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -45,14 +45,14 @@ inline void unsp_device::execute_fxxx_000_group(uint16_t op)
|
|||||||
{
|
{
|
||||||
int r = op & 0x7;
|
int r = op & 0x7;
|
||||||
logerror("%s = fr\n", regs[r]);
|
logerror("%s = fr\n", regs[r]);
|
||||||
unimplemented_opcode(op);
|
// unimplemented_opcode(op);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (((op & 0xf1f8) == 0xf038) && m_iso >= 12)
|
else if (((op & 0xf1f8) == 0xf038) && m_iso >= 12)
|
||||||
{
|
{
|
||||||
int r = op & 0x7;
|
int r = op & 0x7;
|
||||||
logerror("fr = %s\n", regs[r]);
|
logerror("fr = %s\n", regs[r]);
|
||||||
unimplemented_opcode(op);
|
// unimplemented_opcode(op);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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; }
|
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)
|
READ16_MEMBER(sunplus_gcm394_base_device::unkarea_78a1_r)
|
||||||
{
|
{
|
||||||
LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78a1_r\n", machine().describe_context());
|
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(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(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(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
|
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(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(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));
|
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'
|
// jak_tsm code looks for various 'magic values'
|
||||||
|
|
||||||
if (m_testval == 1)
|
if (m_testval == 1)
|
||||||
return 0xc2;
|
return 0x98;
|
||||||
else
|
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
|
// 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
|
// 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)
|
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
|
// 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
|
// 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(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)
|
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)
|
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)
|
if (irqline == UNSP_IRQ6_LINE)
|
||||||
set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
|
set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE);
|
||||||
|
@ -213,6 +213,7 @@ private:
|
|||||||
|
|
||||||
DECLARE_WRITE16_MEMBER(unkarea_78a0_w);
|
DECLARE_WRITE16_MEMBER(unkarea_78a0_w);
|
||||||
|
|
||||||
|
DECLARE_READ16_MEMBER(unkarea_78a0_r);
|
||||||
DECLARE_READ16_MEMBER(unkarea_78a1_r);
|
DECLARE_READ16_MEMBER(unkarea_78a1_r);
|
||||||
|
|
||||||
DECLARE_WRITE16_MEMBER(unkarea_78a4_w);
|
DECLARE_WRITE16_MEMBER(unkarea_78a4_w);
|
||||||
@ -291,11 +292,21 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void gpac800_internal_map(address_map &map);
|
void gpac800_internal_map(address_map &map);
|
||||||
|
|
||||||
|
//virtual void device_start() override;
|
||||||
|
virtual void device_reset() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_READ16_MEMBER(unkarea_7850_r);
|
DECLARE_READ16_MEMBER(unkarea_7850_r);
|
||||||
DECLARE_READ16_MEMBER(unkarea_7854_r);
|
DECLARE_READ16_MEMBER(unkarea_7854_r);
|
||||||
|
|
||||||
|
DECLARE_WRITE16_MEMBER(flash_addr_low_w);
|
||||||
|
DECLARE_WRITE16_MEMBER(flash_addr_high_w);
|
||||||
|
|
||||||
int m_testval;
|
int m_testval;
|
||||||
|
|
||||||
|
uint16_t m_flash_addr_low;
|
||||||
|
uint16_t m_flash_addr_high;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -389,24 +389,24 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
|
|||||||
{
|
{
|
||||||
uint32_t xscroll = regs[0];
|
uint32_t xscroll = regs[0];
|
||||||
uint32_t yscroll = regs[1];
|
uint32_t yscroll = regs[1];
|
||||||
uint32_t attr = regs[2];
|
uint32_t attr_reg = regs[2];
|
||||||
uint32_t ctrl = regs[3];
|
uint32_t ctrl_reg = regs[3];
|
||||||
uint32_t tilemap = regs[4];
|
uint32_t tilemap = regs[4];
|
||||||
uint32_t palette_map = regs[5];
|
uint32_t palette_map = regs[5];
|
||||||
address_space &space = m_cpu->space(AS_PROGRAM);
|
address_space &space = m_cpu->space(AS_PROGRAM);
|
||||||
|
|
||||||
if (!(ctrl & PAGE_ENABLE_MASK))
|
if (!(ctrl_reg & PAGE_ENABLE_MASK))
|
||||||
{
|
{
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tile_h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT);
|
uint32_t tile_h = 8 << ((attr_reg & 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_w = 8 << ((attr_reg & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT);
|
||||||
|
|
||||||
uint32_t tile_count_x = 512 / tile_w;
|
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 yy = ((tile_h * y0 - yscroll + 0x10) & 0xff) - 0x10;
|
||||||
uint32_t xx = (tile_w * x0 - xscroll) & 0x1ff;
|
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)
|
if (x0 & 1)
|
||||||
palette >>= 8;
|
palette >>= 8;
|
||||||
|
|
||||||
tile |= (palette & 0x0007) << 16;
|
|
||||||
|
|
||||||
if (!tile)
|
if (!tile)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
uint32_t tileattr = attr;
|
uint32_t tileattr = attr_reg;
|
||||||
uint32_t tilectrl = ctrl;
|
uint32_t tilectrl = ctrl_reg;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if ((ctrl & 2) == 0)
|
if ((ctrl_reg & 2) == 0)
|
||||||
{ // -(1) bld(1) flip(2) pal(4)
|
{ // -(1) bld(1) flip(2) pal(4)
|
||||||
tileattr &= ~0x000c;
|
tileattr &= ~0x000c;
|
||||||
tileattr |= (palette >> 2) & 0x000c; // flip
|
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
|
tilectrl |= (palette << 2) & 0x0100; // blend
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
const bool blend = (tileattr & 0x4000 || tilectrl & 0x0100);
|
bool blend;
|
||||||
const bool row_scroll = (tilectrl & 0x0010);
|
bool row_scroll;
|
||||||
const bool flip_x = (tileattr & TILE_X_FLIP);
|
bool flip_x;
|
||||||
const uint32_t yflipmask = tileattr & TILE_Y_FLIP ? tile_h - 1 : 0;
|
uint32_t yflipmask;
|
||||||
uint32_t palette_offset = (tileattr & 0x0f00) >> 4;
|
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 |= 0x0900;
|
||||||
palette_offset |= 0x0100;
|
palette_offset |= 0x0100;
|
||||||
|
|
||||||
const uint8_t bpp = tileattr & 0x0003;
|
const uint8_t bpp = tileattr & 0x0003;
|
||||||
|
|
||||||
|
|
||||||
if (blend)
|
if (blend)
|
||||||
{
|
{
|
||||||
if (row_scroll)
|
if (row_scroll)
|
||||||
{
|
{
|
||||||
if (flip_x)
|
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
|
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
|
else
|
||||||
{
|
{
|
||||||
if (flip_x)
|
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
|
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
|
else
|
||||||
@ -480,16 +502,16 @@ void gcm394_base_video_device::draw_page(const rectangle &cliprect, uint32_t sca
|
|||||||
if (row_scroll)
|
if (row_scroll)
|
||||||
{
|
{
|
||||||
if (flip_x)
|
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
|
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
|
else
|
||||||
{
|
{
|
||||||
if (flip_x)
|
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
|
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; }
|
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
|
// read in IRQ
|
||||||
READ16_MEMBER(gcm394_base_video_device::video_7030_brightness_r)
|
READ16_MEMBER(gcm394_base_video_device::video_7030_brightness_r)
|
||||||
{
|
{
|
||||||
|
@ -68,6 +68,7 @@ public:
|
|||||||
DECLARE_WRITE16_MEMBER(video_702a_w);
|
DECLARE_WRITE16_MEMBER(video_702a_w);
|
||||||
DECLARE_READ16_MEMBER(video_7030_brightness_r);
|
DECLARE_READ16_MEMBER(video_7030_brightness_r);
|
||||||
DECLARE_WRITE16_MEMBER(video_7030_brightness_w);
|
DECLARE_WRITE16_MEMBER(video_7030_brightness_w);
|
||||||
|
DECLARE_READ16_MEMBER(video_curline_r);
|
||||||
DECLARE_WRITE16_MEMBER(video_703c_w);
|
DECLARE_WRITE16_MEMBER(video_703c_w);
|
||||||
|
|
||||||
DECLARE_READ16_MEMBER(video_707c_r);
|
DECLARE_READ16_MEMBER(video_707c_r);
|
||||||
|
@ -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
|
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
|
Smart Fit Park
|
||||||
SpongeBob SquarePants Bikini Bottom 500
|
SpongeBob SquarePants Bikini Bottom 500
|
||||||
Spiderman - The Masked Menace 'Spider Sense' (pad type with Spiderman model)
|
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)
|
(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"
|
#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( 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( 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( 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( 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")
|
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")
|
PORT_START("P2")
|
||||||
INPUT_PORTS_END
|
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
|
Wireless Hunting Video Game System
|
||||||
(info provided with dump)
|
(info provided with dump)
|
||||||
@ -605,7 +804,41 @@ void generalplus_gpac800_game_state::machine_reset()
|
|||||||
mem.write_word(dest+i, word);
|
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(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.
|
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
|
// debug to allow for easy use of unidasm.exe
|
||||||
if (1)
|
if (0)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char filename[256];
|
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)
|
// 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
|
// 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(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, 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_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, 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_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, 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?, 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, gcm394, generalplus_gpac800_game_state, nand_init840, "VTech", "V.Baby", 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, gcm394, generalplus_gpac800_game_state, nand_init210, "Hasbro", "Playskool Heroes Transformers Rescue Bots Beam Box (Spain)", 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)
|
||||||
|
Loading…
Reference in New Issue
Block a user