mirror of
https://github.com/holub/mame
synced 2025-06-05 04:16:28 +03:00
Modified k052591 PMC emulation to reflect how the real programs work (#11992)
* Modified k052591 PMC emulation to reflect how the real programs work * spy: Confirmed projection function constants, more accurate collision check without the need for special case handling * thunderx: Simplified collision check, fixed object flags updates * hexion: Added special 16-byte VRAM clearing command * Added comments to PMC program dumps * Use multibyte.h functions, variable scope and type cleanup
This commit is contained in:
parent
534af5344a
commit
bfdcc04c7d
@ -10,71 +10,81 @@ Notes:
|
||||
- The board has a 052591, which is used for protection in Thunder Cross and
|
||||
S.P.Y. In this game, however, the only thing it seems to do is clear the
|
||||
screen.
|
||||
This is the program for the 052591:
|
||||
00: 5f 80 01 e0 08
|
||||
01: df 80 00 e0 0c
|
||||
02: df 90 02 e0 0c
|
||||
03: df a0 03 e0 0c
|
||||
04: df b0 0f e0 0c
|
||||
05: df c0 ff bf 0c
|
||||
06: 5c 02 00 33 0c
|
||||
07: 5f 80 04 80 0c
|
||||
|
||||
This is the 052591 PMC code loaded at startup, it contains a RAM/VRAM filling program.
|
||||
See https://github.com/furrtek/SiliconRE/tree/master/Konami/052591 for details
|
||||
|
||||
00: 5f 80 01 e0 08 Entry point, set OUT0 high
|
||||
01: df 80 00 e0 0c r0 = 0
|
||||
02: df 90 02 e0 0c r1 = 2
|
||||
03: df a0 03 e0 0c r2 = 3
|
||||
04: df b0 0f e0 0c r3 = f
|
||||
05: df c0 ff bf 0c ExtAddr = 1fff, r4 = ffff
|
||||
06: 5c 02 00 33 0c
|
||||
07: 5f 80 04 80 0c Write 2 to RAM (1fff) m_bankctrl, select pmcram
|
||||
08: 5c 0e 00 2b 0c
|
||||
09: df 70 00 cb 08
|
||||
0a: 5f 80 00 80 0c
|
||||
09: df 70 00 cb 08 r7 = RAM(4)
|
||||
0a: 5f 80 00 80 0c ExtAddr = 0
|
||||
0b: 5c 04 00 2b 0c
|
||||
0c: df 60 00 cb 08
|
||||
0d: 5c 0c 1f e9 0c
|
||||
0e: 4c 0c 2d e9 08
|
||||
0f: 5f 80 03 80 0c
|
||||
0c: df 60 00 cb 08 r6 = RAM(0) (commands 0, 1 and 30 are used)
|
||||
0d: 5c 0c 1f e9 0c JP 1F if r6 == 0
|
||||
0e: 4c 0c 2d e9 08 JP 2D if r6 == 1
|
||||
|
||||
Command anything other than 00 or 01: Set bank to r7, then clear 16 bytes starting from r5.w
|
||||
0f: 5f 80 03 80 0c ExtAddr = 3
|
||||
10: 5c 04 00 2b 0c
|
||||
11: 5f 00 00 cb 00
|
||||
12: 5f 80 02 a0 0c
|
||||
13: df d0 00 c0 04
|
||||
14: 01 3a 00 f3 0a
|
||||
11: 5f 00 00 cb 00 Read MSB from RAM[3]
|
||||
12: 5f 80 02 a0 0c ExtAddr = 2
|
||||
13: df d0 00 c0 04 r5.w = RAM[3], RAM[2]
|
||||
14: 01 3a 00 f3 0a acc = r5 + r3 = r5 + f
|
||||
15: 5c 08 00 b3 0c
|
||||
16: 5c 0e 00 13 0c
|
||||
16: 5c 0e 00 13 0c Write 3 to RAM[1fff] m_bankctrl
|
||||
17: 5f 80 00 a0 0c
|
||||
18: 5c 00 00 13 0c
|
||||
18: 5c 00 00 13 0c Write r7 to RAM[0]
|
||||
19: 5c 08 00 b3 0c
|
||||
1a: 5c 00 00 13 0c
|
||||
1a: 5c 00 00 13 0c Write 0 to RAM[1fff] m_bankctrl, select vram
|
||||
1b: 84 5a 00 b3 0c
|
||||
1c: 48 0a 5b d1 0c
|
||||
1d: 5f 80 00 e0 08
|
||||
1e: 5f 00 1e fd 0c
|
||||
1c: 48 0a 5b d1 0c Write 0 to RAM[r5++] until r5 > acc (16 times)
|
||||
1d: 5f 80 00 e0 08 Set OUT0 low
|
||||
1e: 5f 00 1e fd 0c JP 1E, infinite loop
|
||||
|
||||
Command is 00: Set bank to 0 and fill from 0 to 0x1fff with r2.b
|
||||
1f: 5f 80 01 a0 0c
|
||||
20: df 20 00 cb 08
|
||||
20: df 20 00 cb 08 r2 = RAM[1]
|
||||
21: 5c 08 00 b3 0c
|
||||
22: 5f 80 03 00 0c
|
||||
22: 5f 80 03 00 0c Write 3 to RAM[1fff] m_bankctrl
|
||||
23: 5c 08 00 b3 0c
|
||||
24: 5f 80 00 80 0c
|
||||
24: 5f 80 00 80 0c Write 3 to RAM[1fff] m_bankctrl
|
||||
25: 5c 00 00 33 0c
|
||||
26: 5c 08 00 93 0c
|
||||
27: 9f 91 ff cf 0e
|
||||
26: 5c 08 00 93 0c Write 0 to RAM[0]
|
||||
27: 9f 91 ff cf 0e Write 0 to RAM[1fff] m_bankctrl, select vram, r1 = fff << 1 = 1ffe
|
||||
28: 5c 84 00 20 0c
|
||||
29: 84 00 00 b3 0c
|
||||
2a: 49 10 69 d1 0c
|
||||
2b: 5f 80 00 e0 08
|
||||
2c: 5f 00 2c fd 0c
|
||||
29: 84 00 00 b3 0c ExtAddr = r0
|
||||
2a: 49 10 69 d1 0c Write r2 to RAM[r0++] while r0 < r1
|
||||
2b: 5f 80 00 e0 08 Set OUT0 low
|
||||
2c: 5f 00 2c fd 0c JP 2C, infinite loop
|
||||
|
||||
Command is 01: Set banks to 1 and fill from 0 to 0x1fff with r2.b
|
||||
2d: 5f 80 01 a0 0c
|
||||
2e: df 20 00 cb 08
|
||||
2e: df 20 00 cb 08 r2 = RAM(1)
|
||||
2f: 5c 08 00 b3 0c
|
||||
30: 5f 80 03 00 0c
|
||||
30: 5f 80 03 00 0c Write 3 to RAM[1fff] m_bankctrl
|
||||
31: 5c 00 00 b3 0c
|
||||
32: 5f 80 01 00 0c
|
||||
32: 5f 80 01 00 0c Write 3 to RAM[0]
|
||||
33: 5c 08 00 b3 0c
|
||||
34: 5f 80 00 80 0c
|
||||
34: 5f 80 00 80 0c Write 1 to RAM[1fff] m_bankctrl
|
||||
35: 5c 00 00 33 0c
|
||||
36: 5c 08 00 93 0c
|
||||
37: 9f 91 ff cf 0e
|
||||
36: 5c 08 00 93 0c Write 0 to RAM[0]
|
||||
37: 9f 91 ff cf 0e Write 0 to RAM[1fff] m_bankctrl, select vram, r1 = fff << 1 = 1ffe
|
||||
38: 5c 84 00 20 0c
|
||||
39: 84 00 00 b3 0c
|
||||
3a: 49 10 79 d1 0c
|
||||
3b: 5f 80 00 e0 08
|
||||
3c: 5f 00 3c fd 0c
|
||||
3d: ff ff ff ff ff
|
||||
3e: ff ff ff ff ff
|
||||
3f: ff ff ff ff ff
|
||||
3a: 49 10 79 d1 0c Write r2 to RAM[r0++] while r0 < r1
|
||||
3b: 5f 80 00 e0 08 Set OUT0 low
|
||||
3c: 5f 00 3c fd 0c JP 3C, infinite loop
|
||||
|
||||
3d: ff ff ff ff ff Garbage
|
||||
3e: ff ff ff ff ff Garbage
|
||||
3f: ff ff ff ff ff Garbage
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -92,6 +102,7 @@ Notes:
|
||||
#include "emupal.h"
|
||||
#include "speaker.h"
|
||||
#include "tilemap.h"
|
||||
#include "multibyte.h"
|
||||
|
||||
|
||||
// configurable logging
|
||||
@ -120,7 +131,7 @@ public:
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_palette(*this, "palette"),
|
||||
m_vram(*this, "vram%u", 0U, 0x2000U, ENDIANNESS_LITTLE),
|
||||
m_unkram(*this, "unkram", 0x800, ENDIANNESS_LITTLE),
|
||||
m_pmcram(*this, "pmcram", 0x800, ENDIANNESS_LITTLE), // Might be an unused area of VRAM
|
||||
m_rombank(*this, "rombank"),
|
||||
m_tilesrom(*this, "tiles")
|
||||
{ }
|
||||
@ -138,7 +149,7 @@ private:
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
memory_share_array_creator<uint8_t, 2> m_vram;
|
||||
memory_share_creator<uint8_t> m_unkram;
|
||||
memory_share_creator<uint8_t> m_pmcram;
|
||||
required_memory_bank m_rombank;
|
||||
required_region_ptr<uint8_t> m_tilesrom;
|
||||
|
||||
@ -231,12 +242,21 @@ void hexion_state::bankswitch_w(uint8_t data)
|
||||
// bits 0-3 select ROM bank
|
||||
m_rombank->set_entry(data & 0x0f);
|
||||
|
||||
// does bit 6 trigger the 052591?
|
||||
// bit 6 triggers the 052591
|
||||
if (data & 0x40)
|
||||
{
|
||||
int bank = m_unkram[0] & 1;
|
||||
memset(m_vram[bank], m_unkram[1], 0x2000);
|
||||
m_bg_tilemap[bank]->mark_all_dirty();
|
||||
uint8_t command = m_pmcram[0];
|
||||
if (command <= 1)
|
||||
{
|
||||
memset(m_vram[command], m_pmcram[1], 0x2000);
|
||||
m_bg_tilemap[command]->mark_all_dirty();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t bank = m_pmcram[4] & 1;
|
||||
memset(m_vram[bank] + (get_u16le(&m_pmcram[2]) & 0x1fff), 0, 16);
|
||||
m_bg_tilemap[bank]->mark_all_dirty();
|
||||
}
|
||||
}
|
||||
// bit 7 = PMC-BK
|
||||
m_pmcbank = (data & 0x80) >> 7;
|
||||
@ -258,7 +278,7 @@ uint8_t hexion_state::bankedram_r(offs_t offset)
|
||||
}
|
||||
else if (m_bankctrl == 2 && offset < 0x800)
|
||||
{
|
||||
return m_unkram[offset];
|
||||
return m_pmcram[offset];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -289,8 +309,8 @@ void hexion_state::bankedram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (m_pmcbank)
|
||||
{
|
||||
LOGBANKEDRAM("%s: unkram_w offset %04x, data %02x, bankctrl = %02x\n", m_maincpu->pc(), offset, data, m_bankctrl);
|
||||
m_unkram[offset] = data;
|
||||
LOGBANKEDRAM("%s: pmcram_w offset %04x, data %02x, bankctrl = %02x\n", m_maincpu->pc(), offset, data, m_bankctrl);
|
||||
m_pmcram[offset] = data;
|
||||
}
|
||||
else
|
||||
LOGBANKEDRAM("%04x pmc internal ram %04x = %02x\n", m_maincpu->pc(), offset, data);
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
Revisions:
|
||||
|
||||
31-01-2024 Furrtek
|
||||
- updated PMCU collision check code to match what the original program does
|
||||
|
||||
05-10-2002 Acho A. Tang
|
||||
- simulated PMCU protection(guess only)
|
||||
- changed priority scheme to fix graphics in 3D levels
|
||||
@ -34,6 +37,7 @@
|
||||
#include "sound/ymopl.h"
|
||||
#include "emupal.h"
|
||||
#include "speaker.h"
|
||||
#include "multibyte.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -63,6 +67,7 @@ private:
|
||||
/* misc */
|
||||
int m_rambank = 0;
|
||||
int m_pmcbank = 0;
|
||||
uint8_t m_pmcpc = 0;
|
||||
int m_video_enable = 0;
|
||||
int m_old_3f90 = 0;
|
||||
|
||||
@ -85,7 +90,7 @@ private:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
uint32_t screen_update_spy(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void spy_collision( );
|
||||
void pmc_run( );
|
||||
void volume_callback0(uint8_t data);
|
||||
void volume_callback1(uint8_t data);
|
||||
K052109_CB_MEMBER(tile_callback);
|
||||
@ -172,8 +177,7 @@ uint8_t spy_state::spy_bankedram1_r(offs_t offset)
|
||||
}
|
||||
else
|
||||
{
|
||||
//logerror("%04x read pmc internal ram %04x\n", m_maincpu->pc(), offset);
|
||||
return 0;
|
||||
return 0; // PMC internal RAM can't be read back
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -193,79 +197,90 @@ void spy_state::spy_bankedram1_w(offs_t offset, uint8_t data)
|
||||
//logerror("%04x pmcram %04x = %02x\n", m_maincpu->pc(), offset, data);
|
||||
m_pmcram[offset] = data;
|
||||
}
|
||||
//else
|
||||
//logerror("%04x pmc internal ram %04x = %02x\n", m_maincpu->pc(), offset, data);
|
||||
else
|
||||
{
|
||||
// Set initial PMC PC
|
||||
m_pmcpc = data & 0x3f;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_ram[offset] = data;
|
||||
}
|
||||
|
||||
/*
|
||||
this is the data written to internal ram on startup:
|
||||
00: e7 7e 38 fc 08
|
||||
01: df 36 38 dc 00
|
||||
02: df 12 3a dc 00
|
||||
03: df 00 38 dc 08
|
||||
This is the 052591 PMC code loaded at startup, it contains both projection and collision check programs.
|
||||
See https://github.com/furrtek/SiliconRE/tree/master/Konami/052591 for details
|
||||
|
||||
Coordinate projection routine:
|
||||
00: e7 7e 38 fc 08 Clear r7
|
||||
01: df 36 38 dc 00 r3.w = RAM[0]
|
||||
02: df 12 3a dc 00 r1.w = RAM[2]
|
||||
03: df 00 38 dc 08 r0 = RAM[4]
|
||||
04: 1f 7e 00 db 00
|
||||
05: 26 fe 00 ff 0c
|
||||
06: 89 03 34 fc 0d
|
||||
07: 81 03 34 fc 09
|
||||
08: 81 03 34 fc 09
|
||||
09: 81 03 34 fc 09
|
||||
0a: 81 03 2f fc 09
|
||||
0b: cc 36 0e d9 08
|
||||
05: 26 fe 00 ff 0c Acc.w = RAM[5],00
|
||||
06: 89 03 34 fc 0d 1+16 division steps, CALL 34...
|
||||
07: 81 03 34 fc 09 add/sub, CALL 34
|
||||
08: 81 03 34 fc 09 add/sub, CALL 34
|
||||
09: 81 03 34 fc 09 add/sub, CALL 34
|
||||
0a: 81 03 2f fc 09 add/sub, CALL 34
|
||||
0b: cc 36 0e d9 08 r3--, JP 0e if 0
|
||||
0c: 84 7e 00 ab 0c
|
||||
0d: 5f 7e 03 cd 08
|
||||
0e: 7f 80 fe ef 08
|
||||
0f: 5f 7e 0f fd 08
|
||||
10: e7 7e 38 fc 08
|
||||
0d: 5f 7e 03 cd 08 JP 03
|
||||
|
||||
0e: 7f 80 fe ef 08 Set OUT0 low
|
||||
0f: 5f 7e 0f fd 08 JP 0f, infinite loop
|
||||
|
||||
Collision check routine:
|
||||
10: e7 7e 38 fc 08 r0.w = RAM[0]
|
||||
11: df 00 3a dc 00
|
||||
12: df 12 0e d9 08
|
||||
13: df ec 10 e0 0c
|
||||
14: 1f fe 03 e0 0c
|
||||
15: df fe 03 e0 0c
|
||||
16: dc 5e 3e fc 08
|
||||
17: df 12 2b d9 08
|
||||
18: 67 25 38 fc 0c
|
||||
12: df 12 0e d9 08 r1 = RAM[2], JP 0e if 0
|
||||
13: df ec 10 e0 0c r6 = 10
|
||||
14: 1f fe 03 e0 0c Acc = 3
|
||||
15: df fe 03 e0 0c r7 = 3
|
||||
16: dc 5e 3e fc 08 r5 = 3
|
||||
17: df 12 2b d9 08 r1 = RAM[r6++], JP 2b if 0
|
||||
18: 67 25 38 fc 0c r2 = 8000 ?
|
||||
19: df 12 3c dc 00
|
||||
1a: df 36 00 db 00
|
||||
1b: c1 14 00 fb 08
|
||||
1c: c1 34 38 fc 08
|
||||
1b: c1 14 00 fb 08 r1 += r2
|
||||
1c: c1 34 38 fc 08 r3 += r2
|
||||
1d: c5 22 37 dc 00
|
||||
1e: cd 12 3c dc 04
|
||||
1f: c5 46 3b dc 00
|
||||
20: cd 36 00 db 04
|
||||
21: 49 16 ed f9 0c
|
||||
22: c9 18 ea f9 0c
|
||||
21: 49 16 ed f9 0c JP 2d if r1 < r3
|
||||
22: c9 18 ea f9 0c JP 2a if r1 < r4
|
||||
23: dc 12 2a f9 08
|
||||
24: cc 5a 26 f9 08
|
||||
25: 5f 7e 18 fd 08
|
||||
26: 5a 7e 32 f8 08
|
||||
27: 84 6c 33 9c 0c
|
||||
28: cc 00 0e d9 08
|
||||
24: cc 5a 26 f9 08 r5--, JP 26 if 0
|
||||
25: 5f 7e 18 fd 08 JP 18
|
||||
26: 5a 7e 32 f8 08 Clear RAM(r7++) if Acc is 0
|
||||
27: 84 6c 33 9c 0c RAM(r6++) = Acc
|
||||
28: cc 00 0e d9 08 r0--, JP 0e if 0
|
||||
29: 5f 7e 14 fd 08
|
||||
2a: 0a 7e 24 fd 08
|
||||
2b: c5 ec 0d e0 0c
|
||||
2b: c5 ec 0d e0 0c r6 += d, next object
|
||||
2c: 5f 7e 28 fd 08
|
||||
2d: dc 16 00 fb 08
|
||||
2e: dc 44 22 fd 08
|
||||
2f: cd fe 02 e0 0c
|
||||
2d: dc 16 00 fb 08 r1 = r3
|
||||
2e: dc 44 22 fd 08 r4 = r2
|
||||
2f: cd fe 02 e0 0c r7 -= 3
|
||||
30: 84 7e 00 bb 0c
|
||||
31: 5a 7e 00 73 08
|
||||
32: 84 7e 00 9b 0c
|
||||
33: 5a 7e 00 36 08
|
||||
34: 81 03 00 fb 09
|
||||
35: 81 03 00 fb 09
|
||||
36: 81 03 00 fe 09
|
||||
37: cd fe 01 e0 0c
|
||||
|
||||
34: 81 03 00 fb 09 add/sub
|
||||
35: 81 03 00 fb 09 add/sub
|
||||
36: 81 03 00 fe 09 add/sub, ret
|
||||
|
||||
37: cd fe 01 e0 0c r7 -= 2
|
||||
38: 84 7e 00 ab 0c
|
||||
39: 5f 7e 00 db 00
|
||||
39: 5f 7e 00 db 00 Set MSB as RAM(r7)
|
||||
3a: 84 7e 3f ad 0c
|
||||
3b: cd ec 01 e0 0c
|
||||
3b: cd ec 01 e0 0c r6 -= 2
|
||||
3c: 84 6c 00 ab 0c
|
||||
3d: 5f 7e 00 db 00
|
||||
3d: 5f 7e 00 db 00 Set MSB as RAM(r6)
|
||||
3e: 84 6c 00 ab 0c
|
||||
3f: 5f 7e 00 ce 08
|
||||
3f: 5f 7e 00 ce 08 ret
|
||||
*/
|
||||
|
||||
void spy_state::bankswitch_w(uint8_t data)
|
||||
@ -285,66 +300,20 @@ void spy_state::bankswitch_w(uint8_t data)
|
||||
membank("bank1")->set_entry(bank);
|
||||
}
|
||||
|
||||
void spy_state::spy_collision( )
|
||||
void spy_state::pmc_run( )
|
||||
{
|
||||
#define MAX_SPRITES 64
|
||||
#define DEF_NEAR_PLANE 0x6400
|
||||
#define NEAR_PLANE_ZOOM 0x0100
|
||||
#define FAR_PLANE_ZOOM 0x0000
|
||||
|
||||
int op1, x1, w1, z1, d1, y1, h1;
|
||||
int op2, x2, w2, z2, d2, y2, h2;
|
||||
int mode, i, loopend, nearplane;
|
||||
|
||||
mode = m_pmcram[0x1];
|
||||
op1 = m_pmcram[0x2];
|
||||
if (op1 == 1)
|
||||
constexpr uint16_t MAX_SPRITES = 64;
|
||||
constexpr uint16_t DEF_NEAR_PLANE = 0x6400;
|
||||
|
||||
if (m_pmcpc == 0x00)
|
||||
{
|
||||
x1 = (m_pmcram[0x3] << 8) + m_pmcram[0x4];
|
||||
w1 = (m_pmcram[0x5] << 8) + m_pmcram[0x6];
|
||||
z1 = (m_pmcram[0x7] << 8) + m_pmcram[0x8];
|
||||
d1 = (m_pmcram[0x9] << 8) + m_pmcram[0xa];
|
||||
y1 = (m_pmcram[0xb] << 8) + m_pmcram[0xc];
|
||||
h1 = (m_pmcram[0xd] << 8) + m_pmcram[0xe];
|
||||
|
||||
for (i = 16; i < 14 * MAX_SPRITES + 2; i += 14)
|
||||
{
|
||||
op2 = m_pmcram[i];
|
||||
if (op2 || mode == 0x0c)
|
||||
{
|
||||
x2 = (m_pmcram[i + 0x1] << 8) + m_pmcram[i + 0x2];
|
||||
w2 = (m_pmcram[i + 0x3] << 8) + m_pmcram[i + 0x4];
|
||||
z2 = (m_pmcram[i + 0x5] << 8) + m_pmcram[i + 0x6];
|
||||
d2 = (m_pmcram[i + 0x7] << 8) + m_pmcram[i + 0x8];
|
||||
y2 = (m_pmcram[i + 0x9] << 8) + m_pmcram[i + 0xa];
|
||||
h2 = (m_pmcram[i + 0xb] << 8) + m_pmcram[i + 0xc];
|
||||
/*
|
||||
The mad scientist's laser truck has both a high sprite center and a small height value.
|
||||
It has to be measured from the ground to detect correctly.
|
||||
*/
|
||||
if (w2 == 0x58 && d2 == 0x04 && h2 == 0x10 && y2 == 0x30)
|
||||
h2 = y2;
|
||||
|
||||
// what other sprites fall into:
|
||||
if ((abs(x1 - x2) < w1 + w2) && (abs(z1 - z2) < d1 + d2) && (abs(y1 - y2) < h1 + h2))
|
||||
{
|
||||
m_pmcram[0xf] = 0;
|
||||
m_pmcram[i + 0xd] = 0;
|
||||
}
|
||||
else
|
||||
m_pmcram[i + 0xd] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (op1 > 1)
|
||||
{
|
||||
/*
|
||||
The PMCU also projects geometries to screen coordinates. Unfortunately I'm unable to figure
|
||||
the scale factors from the PMCU code. Plugging 0 and 0x100 to the far and near planes seems
|
||||
to do the trick though.
|
||||
*/
|
||||
loopend = (m_pmcram[0] << 8) + m_pmcram[1];
|
||||
nearplane = (m_pmcram[2] << 8) + m_pmcram[3];
|
||||
// Projection program
|
||||
// Basically divides a list of 16-bit words by a constant, results are 8.8 fixed point
|
||||
uint16_t loopend, nearplane;
|
||||
uint32_t op;
|
||||
|
||||
loopend = get_u16be(&m_pmcram[0]);
|
||||
nearplane = get_u16be(&m_pmcram[2]);
|
||||
|
||||
// fail safe
|
||||
if (loopend > MAX_SPRITES)
|
||||
@ -354,16 +323,65 @@ void spy_state::spy_collision( )
|
||||
|
||||
loopend = (loopend << 1) + 4;
|
||||
|
||||
for (i = 4; i < loopend; i += 2)
|
||||
for (uint16_t i = 4; i < loopend; i += 2)
|
||||
{
|
||||
op2 = (m_pmcram[i] << 8) + m_pmcram[i + 1];
|
||||
op2 = (op2 * (NEAR_PLANE_ZOOM - FAR_PLANE_ZOOM)) / nearplane + FAR_PLANE_ZOOM;
|
||||
m_pmcram[i] = op2 >> 8;
|
||||
m_pmcram[i + 1] = op2 & 0xff;
|
||||
op = get_u16be(&m_pmcram[i]);
|
||||
op = (op << 8) / nearplane;
|
||||
put_u16be(&m_pmcram[i], op);
|
||||
}
|
||||
|
||||
memset(m_pmcram + loopend, 0, 0x800 - loopend); // clean up for next frame
|
||||
}
|
||||
else
|
||||
{
|
||||
// Collision check program
|
||||
|
||||
if (!m_pmcram[0x2])
|
||||
return;
|
||||
|
||||
const uint16_t count = get_u16be(&m_pmcram[0]);
|
||||
|
||||
for (uint16_t i = 16; i < 16 + (14 * count); i += 14)
|
||||
{
|
||||
if (!m_pmcram[i])
|
||||
continue;
|
||||
|
||||
// Check all 3 dimensions
|
||||
uint8_t tests_failed = 3;
|
||||
for (uint16_t j = 0; j < 3 * 4; j += 4)
|
||||
{
|
||||
const int16_t a_pos = get_s16be(&m_pmcram[j + 3]); // Object A center position
|
||||
const int16_t a_size = get_s16be(&m_pmcram[j + 5]); // Object A half size
|
||||
|
||||
const int16_t b_pos = get_s16be(&m_pmcram[i + j + 1]); // Object B center position
|
||||
const int16_t b_size = get_s16be(&m_pmcram[i + j + 3]); // Object B half size
|
||||
|
||||
const int16_t a_max = a_pos + a_size; // Object A right edge
|
||||
const int16_t a_min = a_pos - a_size; // Object A left edge
|
||||
const int16_t b_max = b_pos + b_size; // Object B right edge
|
||||
const int16_t b_min = b_pos - b_size; // Object B left edge
|
||||
|
||||
if (b_min > a_min)
|
||||
{
|
||||
// Object B left edge is > object A left edge
|
||||
// Checks if A.left < B.left <= A.right
|
||||
if (a_max >= b_min)
|
||||
tests_failed--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Object B left edge is <= object A left edge
|
||||
// Checks if B.left <= A.left <= B.right
|
||||
if (b_max >= a_min)
|
||||
tests_failed--;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark objects as collided or not
|
||||
if (!tests_failed) m_pmcram[0xf] = 0;
|
||||
m_pmcram[i + 0xd] = tests_failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -423,26 +441,10 @@ void spy_state::spy_3f90_w(uint8_t data)
|
||||
/* bit 7 = PMC-BK */
|
||||
m_pmcbank = (data & 0x80) >> 7;
|
||||
|
||||
//logerror("%04x: 3f90_w %02x\n", m_maincpu->pc(), data);
|
||||
/* bit 6 = PMC-START */
|
||||
if ((data & 0x40) && !(m_old_3f90 & 0x40))
|
||||
{
|
||||
/* we should handle collision here */
|
||||
//AT
|
||||
if (0)
|
||||
{
|
||||
int i;
|
||||
|
||||
logerror("collision test:\n");
|
||||
for (i = 0; i < 0xfe; i++)
|
||||
{
|
||||
logerror("%02x ", m_pmcram[i]);
|
||||
if (i == 0x0f || (i > 0x10 && (i - 0x10) % 14 == 13))
|
||||
logerror("\n");
|
||||
}
|
||||
}
|
||||
spy_collision();
|
||||
//ZT
|
||||
pmc_run();
|
||||
m_maincpu->set_input_line(M6809_FIRQ_LINE, HOLD_LINE);
|
||||
}
|
||||
|
||||
@ -601,6 +603,7 @@ void spy_state::machine_start()
|
||||
save_item(NAME(m_paletteram));
|
||||
save_item(NAME(m_rambank));
|
||||
save_item(NAME(m_pmcbank));
|
||||
save_item(NAME(m_pmcpc));
|
||||
save_item(NAME(m_video_enable));
|
||||
save_item(NAME(m_old_3f90));
|
||||
save_item(NAME(m_pmcram));
|
||||
@ -610,6 +613,7 @@ void spy_state::machine_reset()
|
||||
{
|
||||
m_rambank = 0;
|
||||
m_pmcbank = 0;
|
||||
m_pmcpc = 0;
|
||||
m_video_enable = 0;
|
||||
m_old_3f90 = -1;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
#include "multibyte.h"
|
||||
|
||||
//#define VERBOSE 1
|
||||
#include "logmacro.h"
|
||||
@ -164,8 +165,8 @@ private:
|
||||
void thunderx_videobank_w(uint8_t data);
|
||||
void thunderx_1f98_w(uint8_t data);
|
||||
|
||||
void run_collisions(int s0, int e0, int s1, int e1, int cm, int hm);
|
||||
void calculate_collisions();
|
||||
//void run_collisions(int s0, int e0, int s1, int e1, int cm, int hm);
|
||||
void pmc_run();
|
||||
|
||||
void thunderx_map(address_map &map) ATTR_COLD;
|
||||
};
|
||||
@ -258,8 +259,7 @@ uint8_t thunderx_state::pmc_r(offs_t offset)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("%04x read pmc internal ram %04x\n", m_audiocpu->pc(), offset);
|
||||
return 0;
|
||||
return 0; // PMC internal RAM can't be read back
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,141 +272,86 @@ void thunderx_state::pmc_w(offs_t offset, uint8_t data)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("%04x pmc internal ram %04x = %02x\n", m_audiocpu->pc(), offset, data);
|
||||
LOG("%04x pmc set initial PC %04x = %02x\n", m_audiocpu->pc(), offset, data);
|
||||
// thunderx only uses one PMC program which has its entry point at address 01
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
this is the data written to internal ram on startup:
|
||||
This is the 052591 PMC code loaded at startup, it contains a collision check program.
|
||||
See https://github.com/furrtek/SiliconRE/tree/master/Konami/052591 for details
|
||||
|
||||
Japan version US version
|
||||
00: e7 00 00 ad 08 e7 00 00 ad 08
|
||||
01: 5f 80 05 a0 0c 1f 80 05 a0 0c LDW ACC,RAM+05
|
||||
02: 42 7e 00 8b 04 regE
|
||||
03: df 00 e2 8b 08 df 8e 00 cb 04 regE
|
||||
04: 5f 80 06 a0 0c 5f 80 07 a0 0c LDB ACC,RAM+07
|
||||
05: df 7e 00 cb 08 df 7e 00 cb 08 LDB R7,[Rx]
|
||||
06: 1b 80 00 a0 0c 1b 80 00 a0 0c LDPTR #0 PTR2,RAM+00
|
||||
07: df 10 00 cb 08 df 10 00 cb 08 LDB R1,[PTR] (fl) LDB R1,[Rx] (flags)
|
||||
08: 5f 80 03 a0 0c 5f 80 03 a0 0c LDB R0,[3] (cm) LDB ACC,RAM+03 load collide mask
|
||||
09: 1f 20 00 cb 08 1f 20 00 cb 08 LD CMP2,R0 test (AND) R1 vs ACC
|
||||
0a: c4 00 00 ab 0c c4 00 00 ab 0c INC PTR LEA Rx,[++PTR2]
|
||||
0b: df 20 00 cb 08 df 20 00 cb 08 LDB R2,[PTR] (w) LDB R2,[Rx] (width)
|
||||
0c: c4 00 00 ab 0c c4 00 00 ab 0c INC PTR LEA Rx,[++PTR2]
|
||||
0d: df 30 00 cb 08 df 30 00 cb 08 LDB R3,[PTR] (h) LDB R3,[Rx] (height)
|
||||
0e: c4 00 00 ab 0c c4 00 00 ab 0c INC PTR LEA Rx,[++PTR2]
|
||||
0f: df 40 00 cb 08 df 40 00 cb 08 LDB R4,[PTR] (x) LDB R4,[Rx] (x)
|
||||
10: c4 00 00 ab 0c c4 00 00 ab 0c INC PTR LEA Rx,[++PTR2]
|
||||
11: df 50 00 cb 08 df 50 00 cb 08 LDB R5,[PTR] (y) LDB R5,[Rx] (y)
|
||||
12: 60 22 35 e9 08 60 22 36 e9 08 BANDZ CMP2,R1,36 R2/R1, BEQ 36
|
||||
13: 44 0e 00 ab 08 44 0e 00 ab 08 MOVE PTR,INNER LEA Rx,[PTR,0] load flags
|
||||
14: df 60 00 cb 08 df 60 00 cb 08 LDB R6,[PTR] (fl) LDB R6,[Rx]
|
||||
15: 5f 80 04 a0 0c 5f 80 04 a0 0c LDB R0,[4] (hm) LDB ACC,RAM+04 load hit mask
|
||||
16: 1f 60 00 cb 08 1f 60 00 cb 08 LD CMP6,R0 test R6 and ACC (AND)
|
||||
17: 60 6c 31 e9 08 60 6c 32 e9 08 BANDZ CMP6,R6,32 R6, BEQ 32
|
||||
18: 45 8e 01 a0 0c 45 8e 01 a0 0c LDB R0,[INNER+1] LDB Ry,[PTR,1] (width)
|
||||
19: c5 64 00 cb 08 c5 64 00 cb 08 ADD ACC,R0,R2 R6 = ADD Ry,R2
|
||||
1a: 45 8e 03 a0 0c 45 8e 03 a0 0c LDB R0,[INNER+3] LDB Ry,[PTR,3] (x)
|
||||
1b: 67 00 00 cb 0c 67 00 00 cb 0c MOV CMP,R0 ??? DEC Ry
|
||||
1c: 15 48 5d c9 0c 15 48 5e c9 0c SUB CMP,R4 ; BGE 1E SUB R4,Ry; Bcc 1E
|
||||
1d: 12 00 00 eb 0c 12 00 00 eb 0c NEG CMP ??? NEG Ry
|
||||
1e: 48 6c 71 e9 0c 48 6c 72 e9 0c B (CMP > ACC) 32 R6, BLO 32
|
||||
1f: 45 8e 02 a0 0c 45 8e 02 a0 0c LDB R0,[INNER+2] LDB Ry,[PTR,2] (height)
|
||||
20: c5 66 00 cb 08 c5 66 00 cb 08 ADD ACC,R0,R3 R6 = ADD Ry,R3
|
||||
21: 45 8e 04 a0 0c 45 8e 04 a0 0c LDB R0,[INNER+4] LDB Ry,[PTR,4] (y)
|
||||
22: 67 00 00 cb 0c 67 00 00 cb 0c MOV CMP,R0 ??? DEC Ry
|
||||
23: 15 5a 64 c9 0c 15 5a 65 c9 0c SUB CMP,R5 ; BGE 25 SUB R5,Ry; Bcc 25
|
||||
24: 12 00 00 eb 0c 12 00 00 eb 0c NEG CMP ??? NEG Ry
|
||||
25: 48 6c 71 e9 0c 48 6c 72 e9 0c B (CMP > ACC) 32 R6, BLO 32
|
||||
26: e5 92 9b e0 0c e5 92 9b e0 0c AND R1,#$9B
|
||||
27: dd 92 10 e0 0c dd 92 10 e0 0c OR R1,#$10
|
||||
28: 5c fe 00 a0 0c 5c fe 00 a0 0c ??? STB [PTR,0]
|
||||
29: df 60 00 d3 08 df 60 00 d3 08 LDB R6,
|
||||
2a: e5 ec 9f e0 0c e5 ec 9f e0 0c AND R6,#$9F
|
||||
2b: dd ec 10 00 0c dd ec 10 00 0c OR R6,#$10
|
||||
2c: 25 ec 04 c0 0c 25 ec 04 c0 0c STB R6,[PTR2,-4]
|
||||
2d: 18 82 00 00 0c 18 82 00 00 0c
|
||||
2e: 4d 80 03 a0 0c 4d 80 03 a0 0c RAM+03
|
||||
2f: df e0 e6 e0 0c df e0 36 e1 0c
|
||||
30: 49 60 75 f1 08 49 60 76 f1 08 Jcc 36
|
||||
31: 67 00 35 cd 08 67 00 36 cd 08 Jcc 36
|
||||
32: c5 fe 05 e0 0c c5 fe 05 e0 0c ADD R7,R7,5 ADD regE,#5
|
||||
33: 5f 80 02 a0 0c 5f 80 02 a0 0c LDB R0, [2] LDB ACC,RAM+02
|
||||
34: 1f 00 00 cb 08 1f 00 00 cb 08 LCMP CMP0,R0
|
||||
35: 48 6e 52 c9 0c 48 6e 53 c9 0c BNEQ CMP0,R7, 33 R6/R7, BLO 13
|
||||
36: c4 00 00 ab 0c c4 00 00 ab 0c INC PTR LEA Rx,[++PTR2]
|
||||
37: 27 00 00 ab 0c 27 00 00 ab 0c
|
||||
38: 42 00 00 8b 04 42 00 00 8b 04 MOVE PTR, OUTER
|
||||
39: 1f 00 00 cb 00 1f 00 00 cb 00 LCMP CMP0 ?? test PTR2 vs ACC
|
||||
3a: 48 00 43 c9 00 48 00 44 c9 00 BLT 4 BLT 04 next in set 0
|
||||
3b: 5f fe 00 e0 08 5f fe 00 e0 08
|
||||
3c: 5f 7e 00 ed 08 5f 7e 00 ed 08
|
||||
3d: ff 04 00 ff 06 ff 04 00 ff 06 STOP STOP
|
||||
3e: 05 07 ff 02 03 05 07 ff 02 03
|
||||
3f: 01 01 e0 02 6c 01 00 60 00 a0
|
||||
00: e7 00 00 ad 08 e7 00 00 ad 08 JP 00, infinite loop
|
||||
01: 5f 80 05 a0 0c 1f 80 05 a0 0c Set ext address to 5
|
||||
02: 42 7e 00 8b 04
|
||||
03: df 00 e2 8b 08 df 8e 00 cb 04 r0.b or r0.w = RAM[5]
|
||||
04: 5f 80 06 a0 0c 5f 80 07 a0 0c Set ext address to 6 or 7
|
||||
05: df 7e 00 cb 08 df 7e 00 cb 08 r7.b = RAM[6 or 7]
|
||||
06: 1b 80 00 a0 0c 1b 80 00 a0 0c Set ext address to r0
|
||||
07: df 10 00 cb 08 df 10 00 cb 08 r1.b = RAM[r0] (flags)
|
||||
08: 5f 80 03 a0 0c 5f 80 03 a0 0c Set ext address to 3
|
||||
09: 1f 20 00 cb 08 1f 20 00 cb 08 acc.b = RAM[3] (collide mask)
|
||||
0a: c4 00 00 ab 0c c4 00 00 ab 0c INC r0, set ext address to r0
|
||||
0b: df 20 00 cb 08 df 20 00 cb 08 r2.b = RAM[r0] (width)
|
||||
0c: c4 00 00 ab 0c c4 00 00 ab 0c INC r0, set ext address to r0
|
||||
0d: df 30 00 cb 08 df 30 00 cb 08 r3.b = RAM[r0] (height)
|
||||
0e: c4 00 00 ab 0c c4 00 00 ab 0c INC r0, set ext address to r0
|
||||
0f: df 40 00 cb 08 df 40 00 cb 08 r4.b = RAM[r0] (x)
|
||||
10: c4 00 00 ab 0c c4 00 00 ab 0c INC r0, set ext address to r0
|
||||
11: df 50 00 cb 08 df 50 00 cb 08 r5.b = RAM[r0] (y)
|
||||
12: 60 22 35 e9 08 60 22 36 e9 08 JP 35 or 36 if r1 AND acc == 0
|
||||
13: 44 0e 00 ab 08 44 0e 00 ab 08 Set ext address to r7
|
||||
14: df 60 00 cb 08 df 60 00 cb 08 r6.b = RAM[r7] (flags)
|
||||
15: 5f 80 04 a0 0c 5f 80 04 a0 0c Set ext address to 4
|
||||
16: 1f 60 00 cb 08 1f 60 00 cb 08 acc.b = RAM[4] (hit mask)
|
||||
17: 60 6c 31 e9 08 60 6c 32 e9 08 JP 32 if r6 AND acc == 0
|
||||
18: 45 8e 01 a0 0c 45 8e 01 a0 0c Set ext address to r7 + 1
|
||||
19: c5 64 00 cb 08 c5 64 00 cb 08 r6.b = RAM[r7 + 1] + r2 (add widths together)
|
||||
1a: 45 8e 03 a0 0c 45 8e 03 a0 0c Set ext address to r7 + 3
|
||||
1b: 67 00 00 cb 0c 67 00 00 cb 0c acc = RAM[r7 + 3] - r4 (x1 - x0)
|
||||
1c: 15 48 5d c9 0c 15 48 5e c9 0c JP 1D or 1E if positive
|
||||
1d: 12 00 00 eb 0c 12 00 00 eb 0c NEG acc
|
||||
1e: 48 6c 71 e9 0c 48 6c 72 e9 0c JP 31 or 32 if r6 < acc
|
||||
1f: 45 8e 02 a0 0c 45 8e 02 a0 0c Set ext address to r7 + 2
|
||||
20: c5 66 00 cb 08 c5 66 00 cb 08 r6.b = RAM[r7 + 2] + r3 (add heights together)
|
||||
21: 45 8e 04 a0 0c 45 8e 04 a0 0c Set ext address to r7 + 4
|
||||
22: 67 00 00 cb 0c 67 00 00 cb 0c acc = RAM[r7 + 4] - r5 (y1 - y0)
|
||||
23: 15 5a 64 c9 0c 15 5a 65 c9 0c JP 24 or 25 if positive
|
||||
24: 12 00 00 eb 0c 12 00 00 eb 0c NEG acc
|
||||
25: 48 6c 71 e9 0c 48 6c 72 e9 0c JP 31 or 32 if r6 < acc
|
||||
26: e5 92 9b e0 0c e5 92 9b e0 0c AND R1,#$9B
|
||||
27: dd 92 10 e0 0c dd 92 10 e0 0c OR R1,#$10
|
||||
28: 5c fe 00 a0 0c 5c fe 00 a0 0c Set ext address to r7
|
||||
29: df 60 00 d3 08 df 60 00 d3 08 r6.b = RAM[r7] (flags)
|
||||
2a: e5 ec 9f e0 0c e5 ec 9f e0 0c AND r6,#$9F
|
||||
2b: dd ec 10 00 0c dd ec 10 00 0c RAM[r7] = r6 | #$10
|
||||
2c: 25 ec 04 c0 0c 25 ec 04 c0 0c acc = r6 & 4
|
||||
2d: 18 82 00 00 0c 18 82 00 00 0c OR acc,r1
|
||||
2e: 4d 80 03 a0 0c 4d 80 03 a0 0c Set ext address to r7 - 4
|
||||
2f: df e0 e6 e0 0c df e0 36 e1 0c r6 = #$E6
|
||||
30: 49 60 75 f1 08 49 60 76 f1 08 JP 35 or 36 if r0 < r6
|
||||
31: 67 00 35 cd 08 67 00 36 cd 08 Write acc to [r7 - 4], JP 35
|
||||
32: c5 fe 05 e0 0c c5 fe 05 e0 0c r7 += 5, next object in set 1
|
||||
33: 5f 80 02 a0 0c 5f 80 02 a0 0c Set ext address to 2
|
||||
34: 1f 00 00 cb 08 1f 00 00 cb 08 acc.b = RAM[2]
|
||||
35: 48 6e 52 c9 0c 48 6e 53 c9 0c JP 12 or 13 if r7 < acc
|
||||
36: c4 00 00 ab 0c c4 00 00 ab 0c INC r0, next object in set 0
|
||||
37: 27 00 00 ab 0c 27 00 00 ab 0c Set ext address to 0
|
||||
38: 42 00 00 8b 04 42 00 00 8b 04 acc.w = RAM[0]
|
||||
39: 1f 00 00 cb 00 1f 00 00 cb 00
|
||||
3a: 48 00 43 c9 00 48 00 44 c9 00 JP 3 or 4 if r0 < acc
|
||||
3b: 5f fe 00 e0 08 5f fe 00 e0 08 Set OUT0 low
|
||||
3c: 5f 7e 00 ed 08 5f 7e 00 ed 08 JP 0
|
||||
3d: ff 04 00 ff 06 ff 04 00 ff 06 Garbage
|
||||
3e: 05 07 ff 02 03 05 07 ff 02 03 Garbage
|
||||
3f: 01 01 e0 02 6c 01 00 60 00 a0 Garbage
|
||||
03 6c 04 40 04
|
||||
*/
|
||||
|
||||
// run_collisions
|
||||
//
|
||||
// collide objects from s0 to e0 against
|
||||
// objects from s1 to e1
|
||||
//
|
||||
// only compare objects with the specified bits (cm) set in their flags
|
||||
// only set object 0's hit bit if (hm & 0x40) is true
|
||||
//
|
||||
// the data format is:
|
||||
//
|
||||
// +0 : flags
|
||||
// +1 : width (4 pixel units)
|
||||
// +2 : height (4 pixel units)
|
||||
// +3 : x (2 pixel units) of center of object
|
||||
// +4 : y (2 pixel units) of center of object
|
||||
|
||||
void thunderx_state::run_collisions( int s0, int e0, int s1, int e1, int cm, int hm )
|
||||
{
|
||||
for (uint8_t *p0 = &m_pmcram[s0]; p0 < &m_pmcram[e0]; p0 += 5)
|
||||
{
|
||||
// check valid
|
||||
if (!(p0[0] & cm))
|
||||
continue;
|
||||
|
||||
// get area
|
||||
const int l0 = p0[3] - p0[1];
|
||||
const int r0 = p0[3] + p0[1];
|
||||
const int t0 = p0[4] - p0[2];
|
||||
const int b0 = p0[4] + p0[2];
|
||||
|
||||
for (uint8_t *p1 = &m_pmcram[s1]; p1 < &m_pmcram[e1]; p1 += 5)
|
||||
{
|
||||
// check valid
|
||||
if (!(p1[0] & hm))
|
||||
continue;
|
||||
|
||||
// get area
|
||||
const int l1 = p1[3] - p1[1];
|
||||
const int r1 = p1[3] + p1[1];
|
||||
const int t1 = p1[4] - p1[2];
|
||||
const int b1 = p1[4] + p1[2];
|
||||
|
||||
// overlap check
|
||||
if (l1 >= r0) continue;
|
||||
if (l0 >= r1) continue;
|
||||
if (t1 >= b0) continue;
|
||||
if (t0 >= b1) continue;
|
||||
|
||||
// set flags
|
||||
p0[0] = (p0[0] & 0x8f) | (p1[0] & 0x04) | 0x10;
|
||||
p1[0] = (p1[0] & 0x8f) | 0x10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate_collisions
|
||||
//
|
||||
// emulates K052591 collision detection
|
||||
|
||||
void thunderx_state::calculate_collisions()
|
||||
void thunderx_state::pmc_run()
|
||||
{
|
||||
// the data at 0x00 to 0x06 defines the operation
|
||||
//
|
||||
@ -423,18 +368,17 @@ void thunderx_state::calculate_collisions()
|
||||
// 0x07 : byte : first byte of set 1
|
||||
//
|
||||
// the operation is to intersect set 0 with set 1
|
||||
// collide mask specifies objects to ignore
|
||||
// hit mask is 40 to set bit on object 0 and object 1
|
||||
// hit mask is 20 to set bit on object 1 only
|
||||
// masks specify objects to ignore
|
||||
|
||||
const int e0 = (m_pmcram[0] << 8) | m_pmcram[1];
|
||||
const int e1 = m_pmcram[2];
|
||||
const uint16_t e0 = get_u16be(&m_pmcram[0]);
|
||||
const uint8_t e1 = m_pmcram[2];
|
||||
|
||||
int s0, s1;
|
||||
uint16_t s0, s1;
|
||||
// Heuristic to determine version of program based on byte at 0x05
|
||||
if (m_pmcram[5] < 16)
|
||||
{
|
||||
// US Thunder Cross uses this form
|
||||
s0 = (m_pmcram[5] << 8) + m_pmcram[6];
|
||||
s0 = get_u16be(&m_pmcram[5]);
|
||||
s1 = m_pmcram[7];
|
||||
}
|
||||
else
|
||||
@ -444,10 +388,44 @@ void thunderx_state::calculate_collisions()
|
||||
s1 = m_pmcram[6];
|
||||
}
|
||||
|
||||
const int cm = m_pmcram[3];
|
||||
const int hm = m_pmcram[4];
|
||||
const uint8_t cm = m_pmcram[3];
|
||||
const uint8_t hm = m_pmcram[4];
|
||||
|
||||
run_collisions(s0, e0, s1, e1, cm, hm);
|
||||
// collide objects from s0 to e0 against objects from s1 to e1
|
||||
// only process objects with the specified bits (cm/hm) set in their flags
|
||||
//
|
||||
// the data format for each object is:
|
||||
//
|
||||
// +0 : flags
|
||||
// +1 : width (4 pixel units)
|
||||
// +2 : height (4 pixel units)
|
||||
// +3 : x (2 pixel units) of center of object
|
||||
// +4 : y (2 pixel units) of center of object
|
||||
for (uint8_t *p0 = &m_pmcram[s0]; p0 < &m_pmcram[e0]; p0 += 5)
|
||||
{
|
||||
// check object 0 flags
|
||||
if (!(p0[0] & cm))
|
||||
continue;
|
||||
|
||||
for (uint8_t *p1 = &m_pmcram[s1]; p1 < &m_pmcram[e1]; p1 += 5)
|
||||
{
|
||||
// check object 1 flags
|
||||
if (!(p1[0] & hm))
|
||||
continue;
|
||||
|
||||
if (p1[1] + p0[1] < abs(p1[3] - p0[3])) continue;
|
||||
if (p1[2] + p0[2] < abs(p1[4] - p0[4])) continue;
|
||||
|
||||
// set flags
|
||||
p1[0] = (p1[0] & 0x8f) | 0x10;
|
||||
if (p1 > (uint8_t*)0xe6) // This address value is hardcoded in the PMC program
|
||||
p0[0] = (p0[0] & 0x9b) | (p1[0] & 0x04) | 0x10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 100 cycle delay is arbitrary
|
||||
m_thunderx_firq_timer->adjust(m_maincpu->cycles_to_attotime(100));
|
||||
}
|
||||
|
||||
void thunderx_state_base::scontra_1f98_w(uint8_t data)
|
||||
@ -475,10 +453,7 @@ void thunderx_state::thunderx_1f98_w(uint8_t data)
|
||||
// bit 2 = PMC START (do collision detection when 0->1)
|
||||
if ((data & 4) && !(m_1f98_latch & 4))
|
||||
{
|
||||
calculate_collisions();
|
||||
|
||||
// 100 cycle delay is arbitrary
|
||||
m_thunderx_firq_timer->adjust(m_maincpu->cycles_to_attotime(100));
|
||||
pmc_run();
|
||||
}
|
||||
|
||||
scontra_1f98_w(data);
|
||||
|
Loading…
Reference in New Issue
Block a user