mirror of
https://github.com/holub/mame
synced 2025-06-06 12:53:46 +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
|
- 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
|
S.P.Y. In this game, however, the only thing it seems to do is clear the
|
||||||
screen.
|
screen.
|
||||||
This is the program for the 052591:
|
|
||||||
00: 5f 80 01 e0 08
|
This is the 052591 PMC code loaded at startup, it contains a RAM/VRAM filling program.
|
||||||
01: df 80 00 e0 0c
|
See https://github.com/furrtek/SiliconRE/tree/master/Konami/052591 for details
|
||||||
02: df 90 02 e0 0c
|
|
||||||
03: df a0 03 e0 0c
|
00: 5f 80 01 e0 08 Entry point, set OUT0 high
|
||||||
04: df b0 0f e0 0c
|
01: df 80 00 e0 0c r0 = 0
|
||||||
05: df c0 ff bf 0c
|
02: df 90 02 e0 0c r1 = 2
|
||||||
06: 5c 02 00 33 0c
|
03: df a0 03 e0 0c r2 = 3
|
||||||
07: 5f 80 04 80 0c
|
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
|
08: 5c 0e 00 2b 0c
|
||||||
09: df 70 00 cb 08
|
09: df 70 00 cb 08 r7 = RAM(4)
|
||||||
0a: 5f 80 00 80 0c
|
0a: 5f 80 00 80 0c ExtAddr = 0
|
||||||
0b: 5c 04 00 2b 0c
|
0b: 5c 04 00 2b 0c
|
||||||
0c: df 60 00 cb 08
|
0c: df 60 00 cb 08 r6 = RAM(0) (commands 0, 1 and 30 are used)
|
||||||
0d: 5c 0c 1f e9 0c
|
0d: 5c 0c 1f e9 0c JP 1F if r6 == 0
|
||||||
0e: 4c 0c 2d e9 08
|
0e: 4c 0c 2d e9 08 JP 2D if r6 == 1
|
||||||
0f: 5f 80 03 80 0c
|
|
||||||
|
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
|
10: 5c 04 00 2b 0c
|
||||||
11: 5f 00 00 cb 00
|
11: 5f 00 00 cb 00 Read MSB from RAM[3]
|
||||||
12: 5f 80 02 a0 0c
|
12: 5f 80 02 a0 0c ExtAddr = 2
|
||||||
13: df d0 00 c0 04
|
13: df d0 00 c0 04 r5.w = RAM[3], RAM[2]
|
||||||
14: 01 3a 00 f3 0a
|
14: 01 3a 00 f3 0a acc = r5 + r3 = r5 + f
|
||||||
15: 5c 08 00 b3 0c
|
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
|
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
|
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
|
1b: 84 5a 00 b3 0c
|
||||||
1c: 48 0a 5b d1 0c
|
1c: 48 0a 5b d1 0c Write 0 to RAM[r5++] until r5 > acc (16 times)
|
||||||
1d: 5f 80 00 e0 08
|
1d: 5f 80 00 e0 08 Set OUT0 low
|
||||||
1e: 5f 00 1e fd 0c
|
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
|
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
|
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
|
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
|
25: 5c 00 00 33 0c
|
||||||
26: 5c 08 00 93 0c
|
26: 5c 08 00 93 0c Write 0 to RAM[0]
|
||||||
27: 9f 91 ff cf 0e
|
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
|
28: 5c 84 00 20 0c
|
||||||
29: 84 00 00 b3 0c
|
29: 84 00 00 b3 0c ExtAddr = r0
|
||||||
2a: 49 10 69 d1 0c
|
2a: 49 10 69 d1 0c Write r2 to RAM[r0++] while r0 < r1
|
||||||
2b: 5f 80 00 e0 08
|
2b: 5f 80 00 e0 08 Set OUT0 low
|
||||||
2c: 5f 00 2c fd 0c
|
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
|
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
|
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
|
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
|
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
|
35: 5c 00 00 33 0c
|
||||||
36: 5c 08 00 93 0c
|
36: 5c 08 00 93 0c Write 0 to RAM[0]
|
||||||
37: 9f 91 ff cf 0e
|
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
|
38: 5c 84 00 20 0c
|
||||||
39: 84 00 00 b3 0c
|
39: 84 00 00 b3 0c
|
||||||
3a: 49 10 79 d1 0c
|
3a: 49 10 79 d1 0c Write r2 to RAM[r0++] while r0 < r1
|
||||||
3b: 5f 80 00 e0 08
|
3b: 5f 80 00 e0 08 Set OUT0 low
|
||||||
3c: 5f 00 3c fd 0c
|
3c: 5f 00 3c fd 0c JP 3C, infinite loop
|
||||||
3d: ff ff ff ff ff
|
|
||||||
3e: ff ff ff ff ff
|
3d: ff ff ff ff ff Garbage
|
||||||
3f: ff ff ff ff ff
|
3e: ff ff ff ff ff Garbage
|
||||||
|
3f: ff ff ff ff ff Garbage
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@ -92,6 +102,7 @@ Notes:
|
|||||||
#include "emupal.h"
|
#include "emupal.h"
|
||||||
#include "speaker.h"
|
#include "speaker.h"
|
||||||
#include "tilemap.h"
|
#include "tilemap.h"
|
||||||
|
#include "multibyte.h"
|
||||||
|
|
||||||
|
|
||||||
// configurable logging
|
// configurable logging
|
||||||
@ -120,7 +131,7 @@ public:
|
|||||||
m_gfxdecode(*this, "gfxdecode"),
|
m_gfxdecode(*this, "gfxdecode"),
|
||||||
m_palette(*this, "palette"),
|
m_palette(*this, "palette"),
|
||||||
m_vram(*this, "vram%u", 0U, 0x2000U, ENDIANNESS_LITTLE),
|
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_rombank(*this, "rombank"),
|
||||||
m_tilesrom(*this, "tiles")
|
m_tilesrom(*this, "tiles")
|
||||||
{ }
|
{ }
|
||||||
@ -138,7 +149,7 @@ private:
|
|||||||
required_device<palette_device> m_palette;
|
required_device<palette_device> m_palette;
|
||||||
|
|
||||||
memory_share_array_creator<uint8_t, 2> m_vram;
|
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_memory_bank m_rombank;
|
||||||
required_region_ptr<uint8_t> m_tilesrom;
|
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
|
// bits 0-3 select ROM bank
|
||||||
m_rombank->set_entry(data & 0x0f);
|
m_rombank->set_entry(data & 0x0f);
|
||||||
|
|
||||||
// does bit 6 trigger the 052591?
|
// bit 6 triggers the 052591
|
||||||
if (data & 0x40)
|
if (data & 0x40)
|
||||||
{
|
{
|
||||||
int bank = m_unkram[0] & 1;
|
uint8_t command = m_pmcram[0];
|
||||||
memset(m_vram[bank], m_unkram[1], 0x2000);
|
if (command <= 1)
|
||||||
m_bg_tilemap[bank]->mark_all_dirty();
|
{
|
||||||
|
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
|
// bit 7 = PMC-BK
|
||||||
m_pmcbank = (data & 0x80) >> 7;
|
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)
|
else if (m_bankctrl == 2 && offset < 0x800)
|
||||||
{
|
{
|
||||||
return m_unkram[offset];
|
return m_pmcram[offset];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -289,8 +309,8 @@ void hexion_state::bankedram_w(offs_t offset, uint8_t data)
|
|||||||
{
|
{
|
||||||
if (m_pmcbank)
|
if (m_pmcbank)
|
||||||
{
|
{
|
||||||
LOGBANKEDRAM("%s: unkram_w offset %04x, data %02x, bankctrl = %02x\n", m_maincpu->pc(), offset, data, m_bankctrl);
|
LOGBANKEDRAM("%s: pmcram_w offset %04x, data %02x, bankctrl = %02x\n", m_maincpu->pc(), offset, data, m_bankctrl);
|
||||||
m_unkram[offset] = data;
|
m_pmcram[offset] = data;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOGBANKEDRAM("%04x pmc internal ram %04x = %02x\n", m_maincpu->pc(), offset, data);
|
LOGBANKEDRAM("%04x pmc internal ram %04x = %02x\n", m_maincpu->pc(), offset, data);
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
|
|
||||||
Revisions:
|
Revisions:
|
||||||
|
|
||||||
|
31-01-2024 Furrtek
|
||||||
|
- updated PMCU collision check code to match what the original program does
|
||||||
|
|
||||||
05-10-2002 Acho A. Tang
|
05-10-2002 Acho A. Tang
|
||||||
- simulated PMCU protection(guess only)
|
- simulated PMCU protection(guess only)
|
||||||
- changed priority scheme to fix graphics in 3D levels
|
- changed priority scheme to fix graphics in 3D levels
|
||||||
@ -34,6 +37,7 @@
|
|||||||
#include "sound/ymopl.h"
|
#include "sound/ymopl.h"
|
||||||
#include "emupal.h"
|
#include "emupal.h"
|
||||||
#include "speaker.h"
|
#include "speaker.h"
|
||||||
|
#include "multibyte.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -63,6 +67,7 @@ private:
|
|||||||
/* misc */
|
/* misc */
|
||||||
int m_rambank = 0;
|
int m_rambank = 0;
|
||||||
int m_pmcbank = 0;
|
int m_pmcbank = 0;
|
||||||
|
uint8_t m_pmcpc = 0;
|
||||||
int m_video_enable = 0;
|
int m_video_enable = 0;
|
||||||
int m_old_3f90 = 0;
|
int m_old_3f90 = 0;
|
||||||
|
|
||||||
@ -85,7 +90,7 @@ private:
|
|||||||
virtual void machine_start() override;
|
virtual void machine_start() override;
|
||||||
virtual void machine_reset() override;
|
virtual void machine_reset() override;
|
||||||
uint32_t screen_update_spy(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
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_callback0(uint8_t data);
|
||||||
void volume_callback1(uint8_t data);
|
void volume_callback1(uint8_t data);
|
||||||
K052109_CB_MEMBER(tile_callback);
|
K052109_CB_MEMBER(tile_callback);
|
||||||
@ -172,8 +177,7 @@ uint8_t spy_state::spy_bankedram1_r(offs_t offset)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//logerror("%04x read pmc internal ram %04x\n", m_maincpu->pc(), offset);
|
return 0; // PMC internal RAM can't be read back
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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);
|
//logerror("%04x pmcram %04x = %02x\n", m_maincpu->pc(), offset, data);
|
||||||
m_pmcram[offset] = data;
|
m_pmcram[offset] = data;
|
||||||
}
|
}
|
||||||
//else
|
else
|
||||||
//logerror("%04x pmc internal ram %04x = %02x\n", m_maincpu->pc(), offset, data);
|
{
|
||||||
|
// Set initial PMC PC
|
||||||
|
m_pmcpc = data & 0x3f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_ram[offset] = data;
|
m_ram[offset] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this is the data written to internal ram on startup:
|
This is the 052591 PMC code loaded at startup, it contains both projection and collision check programs.
|
||||||
00: e7 7e 38 fc 08
|
See https://github.com/furrtek/SiliconRE/tree/master/Konami/052591 for details
|
||||||
01: df 36 38 dc 00
|
|
||||||
02: df 12 3a dc 00
|
Coordinate projection routine:
|
||||||
03: df 00 38 dc 08
|
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
|
04: 1f 7e 00 db 00
|
||||||
05: 26 fe 00 ff 0c
|
05: 26 fe 00 ff 0c Acc.w = RAM[5],00
|
||||||
06: 89 03 34 fc 0d
|
06: 89 03 34 fc 0d 1+16 division steps, CALL 34...
|
||||||
07: 81 03 34 fc 09
|
07: 81 03 34 fc 09 add/sub, CALL 34
|
||||||
08: 81 03 34 fc 09
|
08: 81 03 34 fc 09 add/sub, CALL 34
|
||||||
09: 81 03 34 fc 09
|
09: 81 03 34 fc 09 add/sub, CALL 34
|
||||||
0a: 81 03 2f fc 09
|
0a: 81 03 2f fc 09 add/sub, CALL 34
|
||||||
0b: cc 36 0e d9 08
|
0b: cc 36 0e d9 08 r3--, JP 0e if 0
|
||||||
0c: 84 7e 00 ab 0c
|
0c: 84 7e 00 ab 0c
|
||||||
0d: 5f 7e 03 cd 08
|
0d: 5f 7e 03 cd 08 JP 03
|
||||||
0e: 7f 80 fe ef 08
|
|
||||||
0f: 5f 7e 0f fd 08
|
0e: 7f 80 fe ef 08 Set OUT0 low
|
||||||
10: e7 7e 38 fc 08
|
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
|
11: df 00 3a dc 00
|
||||||
12: df 12 0e d9 08
|
12: df 12 0e d9 08 r1 = RAM[2], JP 0e if 0
|
||||||
13: df ec 10 e0 0c
|
13: df ec 10 e0 0c r6 = 10
|
||||||
14: 1f fe 03 e0 0c
|
14: 1f fe 03 e0 0c Acc = 3
|
||||||
15: df fe 03 e0 0c
|
15: df fe 03 e0 0c r7 = 3
|
||||||
16: dc 5e 3e fc 08
|
16: dc 5e 3e fc 08 r5 = 3
|
||||||
17: df 12 2b d9 08
|
17: df 12 2b d9 08 r1 = RAM[r6++], JP 2b if 0
|
||||||
18: 67 25 38 fc 0c
|
18: 67 25 38 fc 0c r2 = 8000 ?
|
||||||
19: df 12 3c dc 00
|
19: df 12 3c dc 00
|
||||||
1a: df 36 00 db 00
|
1a: df 36 00 db 00
|
||||||
1b: c1 14 00 fb 08
|
1b: c1 14 00 fb 08 r1 += r2
|
||||||
1c: c1 34 38 fc 08
|
1c: c1 34 38 fc 08 r3 += r2
|
||||||
1d: c5 22 37 dc 00
|
1d: c5 22 37 dc 00
|
||||||
1e: cd 12 3c dc 04
|
1e: cd 12 3c dc 04
|
||||||
1f: c5 46 3b dc 00
|
1f: c5 46 3b dc 00
|
||||||
20: cd 36 00 db 04
|
20: cd 36 00 db 04
|
||||||
21: 49 16 ed f9 0c
|
21: 49 16 ed f9 0c JP 2d if r1 < r3
|
||||||
22: c9 18 ea f9 0c
|
22: c9 18 ea f9 0c JP 2a if r1 < r4
|
||||||
23: dc 12 2a f9 08
|
23: dc 12 2a f9 08
|
||||||
24: cc 5a 26 f9 08
|
24: cc 5a 26 f9 08 r5--, JP 26 if 0
|
||||||
25: 5f 7e 18 fd 08
|
25: 5f 7e 18 fd 08 JP 18
|
||||||
26: 5a 7e 32 f8 08
|
26: 5a 7e 32 f8 08 Clear RAM(r7++) if Acc is 0
|
||||||
27: 84 6c 33 9c 0c
|
27: 84 6c 33 9c 0c RAM(r6++) = Acc
|
||||||
28: cc 00 0e d9 08
|
28: cc 00 0e d9 08 r0--, JP 0e if 0
|
||||||
29: 5f 7e 14 fd 08
|
29: 5f 7e 14 fd 08
|
||||||
2a: 0a 7e 24 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
|
2c: 5f 7e 28 fd 08
|
||||||
2d: dc 16 00 fb 08
|
2d: dc 16 00 fb 08 r1 = r3
|
||||||
2e: dc 44 22 fd 08
|
2e: dc 44 22 fd 08 r4 = r2
|
||||||
2f: cd fe 02 e0 0c
|
2f: cd fe 02 e0 0c r7 -= 3
|
||||||
30: 84 7e 00 bb 0c
|
30: 84 7e 00 bb 0c
|
||||||
31: 5a 7e 00 73 08
|
31: 5a 7e 00 73 08
|
||||||
32: 84 7e 00 9b 0c
|
32: 84 7e 00 9b 0c
|
||||||
33: 5a 7e 00 36 08
|
33: 5a 7e 00 36 08
|
||||||
34: 81 03 00 fb 09
|
|
||||||
35: 81 03 00 fb 09
|
34: 81 03 00 fb 09 add/sub
|
||||||
36: 81 03 00 fe 09
|
35: 81 03 00 fb 09 add/sub
|
||||||
37: cd fe 01 e0 0c
|
36: 81 03 00 fe 09 add/sub, ret
|
||||||
|
|
||||||
|
37: cd fe 01 e0 0c r7 -= 2
|
||||||
38: 84 7e 00 ab 0c
|
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
|
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
|
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
|
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)
|
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);
|
membank("bank1")->set_entry(bank);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spy_state::spy_collision( )
|
void spy_state::pmc_run( )
|
||||||
{
|
{
|
||||||
#define MAX_SPRITES 64
|
constexpr uint16_t MAX_SPRITES = 64;
|
||||||
#define DEF_NEAR_PLANE 0x6400
|
constexpr uint16_t DEF_NEAR_PLANE = 0x6400;
|
||||||
#define NEAR_PLANE_ZOOM 0x0100
|
|
||||||
#define FAR_PLANE_ZOOM 0x0000
|
if (m_pmcpc == 0x00)
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
x1 = (m_pmcram[0x3] << 8) + m_pmcram[0x4];
|
// Projection program
|
||||||
w1 = (m_pmcram[0x5] << 8) + m_pmcram[0x6];
|
// Basically divides a list of 16-bit words by a constant, results are 8.8 fixed point
|
||||||
z1 = (m_pmcram[0x7] << 8) + m_pmcram[0x8];
|
uint16_t loopend, nearplane;
|
||||||
d1 = (m_pmcram[0x9] << 8) + m_pmcram[0xa];
|
uint32_t op;
|
||||||
y1 = (m_pmcram[0xb] << 8) + m_pmcram[0xc];
|
|
||||||
h1 = (m_pmcram[0xd] << 8) + m_pmcram[0xe];
|
loopend = get_u16be(&m_pmcram[0]);
|
||||||
|
nearplane = get_u16be(&m_pmcram[2]);
|
||||||
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];
|
|
||||||
|
|
||||||
// fail safe
|
// fail safe
|
||||||
if (loopend > MAX_SPRITES)
|
if (loopend > MAX_SPRITES)
|
||||||
@ -354,16 +323,65 @@ void spy_state::spy_collision( )
|
|||||||
|
|
||||||
loopend = (loopend << 1) + 4;
|
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];
|
op = get_u16be(&m_pmcram[i]);
|
||||||
op2 = (op2 * (NEAR_PLANE_ZOOM - FAR_PLANE_ZOOM)) / nearplane + FAR_PLANE_ZOOM;
|
op = (op << 8) / nearplane;
|
||||||
m_pmcram[i] = op2 >> 8;
|
put_u16be(&m_pmcram[i], op);
|
||||||
m_pmcram[i + 1] = op2 & 0xff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(m_pmcram + loopend, 0, 0x800 - loopend); // clean up for next frame
|
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 */
|
/* bit 7 = PMC-BK */
|
||||||
m_pmcbank = (data & 0x80) >> 7;
|
m_pmcbank = (data & 0x80) >> 7;
|
||||||
|
|
||||||
//logerror("%04x: 3f90_w %02x\n", m_maincpu->pc(), data);
|
|
||||||
/* bit 6 = PMC-START */
|
/* bit 6 = PMC-START */
|
||||||
if ((data & 0x40) && !(m_old_3f90 & 0x40))
|
if ((data & 0x40) && !(m_old_3f90 & 0x40))
|
||||||
{
|
{
|
||||||
/* we should handle collision here */
|
pmc_run();
|
||||||
//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
|
|
||||||
m_maincpu->set_input_line(M6809_FIRQ_LINE, HOLD_LINE);
|
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_paletteram));
|
||||||
save_item(NAME(m_rambank));
|
save_item(NAME(m_rambank));
|
||||||
save_item(NAME(m_pmcbank));
|
save_item(NAME(m_pmcbank));
|
||||||
|
save_item(NAME(m_pmcpc));
|
||||||
save_item(NAME(m_video_enable));
|
save_item(NAME(m_video_enable));
|
||||||
save_item(NAME(m_old_3f90));
|
save_item(NAME(m_old_3f90));
|
||||||
save_item(NAME(m_pmcram));
|
save_item(NAME(m_pmcram));
|
||||||
@ -610,6 +613,7 @@ void spy_state::machine_reset()
|
|||||||
{
|
{
|
||||||
m_rambank = 0;
|
m_rambank = 0;
|
||||||
m_pmcbank = 0;
|
m_pmcbank = 0;
|
||||||
|
m_pmcpc = 0;
|
||||||
m_video_enable = 0;
|
m_video_enable = 0;
|
||||||
m_old_3f90 = -1;
|
m_old_3f90 = -1;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "emupal.h"
|
#include "emupal.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "speaker.h"
|
#include "speaker.h"
|
||||||
|
#include "multibyte.h"
|
||||||
|
|
||||||
//#define VERBOSE 1
|
//#define VERBOSE 1
|
||||||
#include "logmacro.h"
|
#include "logmacro.h"
|
||||||
@ -164,8 +165,8 @@ private:
|
|||||||
void thunderx_videobank_w(uint8_t data);
|
void thunderx_videobank_w(uint8_t data);
|
||||||
void thunderx_1f98_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 run_collisions(int s0, int e0, int s1, int e1, int cm, int hm);
|
||||||
void calculate_collisions();
|
void pmc_run();
|
||||||
|
|
||||||
void thunderx_map(address_map &map) ATTR_COLD;
|
void thunderx_map(address_map &map) ATTR_COLD;
|
||||||
};
|
};
|
||||||
@ -258,8 +259,7 @@ uint8_t thunderx_state::pmc_r(offs_t offset)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG("%04x read pmc internal ram %04x\n", m_audiocpu->pc(), offset);
|
return 0; // PMC internal RAM can't be read back
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,141 +272,86 @@ void thunderx_state::pmc_w(offs_t offset, uint8_t data)
|
|||||||
}
|
}
|
||||||
else
|
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
|
Japan version US version
|
||||||
00: e7 00 00 ad 08 e7 00 00 ad 08
|
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 LDW ACC,RAM+05
|
01: 5f 80 05 a0 0c 1f 80 05 a0 0c Set ext address to 5
|
||||||
02: 42 7e 00 8b 04 regE
|
02: 42 7e 00 8b 04
|
||||||
03: df 00 e2 8b 08 df 8e 00 cb 04 regE
|
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 LDB ACC,RAM+07
|
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 LDB R7,[Rx]
|
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 LDPTR #0 PTR2,RAM+00
|
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 LDB R1,[PTR] (fl) LDB R1,[Rx] (flags)
|
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 LDB R0,[3] (cm) LDB ACC,RAM+03 load collide mask
|
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 LD CMP2,R0 test (AND) R1 vs ACC
|
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 PTR LEA Rx,[++PTR2]
|
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 LDB R2,[PTR] (w) LDB R2,[Rx] (width)
|
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 PTR LEA Rx,[++PTR2]
|
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 LDB R3,[PTR] (h) LDB R3,[Rx] (height)
|
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 PTR LEA Rx,[++PTR2]
|
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 LDB R4,[PTR] (x) LDB R4,[Rx] (x)
|
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 PTR LEA Rx,[++PTR2]
|
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 LDB R5,[PTR] (y) LDB R5,[Rx] (y)
|
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 BANDZ CMP2,R1,36 R2/R1, BEQ 36
|
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 MOVE PTR,INNER LEA Rx,[PTR,0] load flags
|
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 LDB R6,[PTR] (fl) LDB R6,[Rx]
|
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 LDB R0,[4] (hm) LDB ACC,RAM+04 load hit mask
|
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 LD CMP6,R0 test R6 and ACC (AND)
|
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 BANDZ CMP6,R6,32 R6, BEQ 32
|
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 LDB R0,[INNER+1] LDB Ry,[PTR,1] (width)
|
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 ADD ACC,R0,R2 R6 = ADD Ry,R2
|
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 LDB R0,[INNER+3] LDB Ry,[PTR,3] (x)
|
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 MOV CMP,R0 ??? DEC Ry
|
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 SUB CMP,R4 ; BGE 1E SUB R4,Ry; Bcc 1E
|
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 CMP ??? NEG Ry
|
1d: 12 00 00 eb 0c 12 00 00 eb 0c NEG acc
|
||||||
1e: 48 6c 71 e9 0c 48 6c 72 e9 0c B (CMP > ACC) 32 R6, BLO 32
|
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 LDB R0,[INNER+2] LDB Ry,[PTR,2] (height)
|
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 ADD ACC,R0,R3 R6 = ADD Ry,R3
|
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 LDB R0,[INNER+4] LDB Ry,[PTR,4] (y)
|
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 MOV CMP,R0 ??? DEC Ry
|
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 SUB CMP,R5 ; BGE 25 SUB R5,Ry; Bcc 25
|
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 CMP ??? NEG Ry
|
24: 12 00 00 eb 0c 12 00 00 eb 0c NEG acc
|
||||||
25: 48 6c 71 e9 0c 48 6c 72 e9 0c B (CMP > ACC) 32 R6, BLO 32
|
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
|
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
|
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]
|
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 LDB R6,
|
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
|
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
|
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 STB R6,[PTR2,-4]
|
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
|
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 RAM+03
|
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
|
2f: df e0 e6 e0 0c df e0 36 e1 0c r6 = #$E6
|
||||||
30: 49 60 75 f1 08 49 60 76 f1 08 Jcc 36
|
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 Jcc 36
|
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 ADD R7,R7,5 ADD regE,#5
|
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 LDB R0, [2] LDB ACC,RAM+02
|
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 LCMP CMP0,R0
|
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 BNEQ CMP0,R7, 33 R6/R7, BLO 13
|
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 PTR LEA Rx,[++PTR2]
|
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
|
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 MOVE PTR, OUTER
|
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 LCMP CMP0 ?? test PTR2 vs ACC
|
39: 1f 00 00 cb 00 1f 00 00 cb 00
|
||||||
3a: 48 00 43 c9 00 48 00 44 c9 00 BLT 4 BLT 04 next in set 0
|
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
|
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
|
3c: 5f 7e 00 ed 08 5f 7e 00 ed 08 JP 0
|
||||||
3d: ff 04 00 ff 06 ff 04 00 ff 06 STOP STOP
|
3d: ff 04 00 ff 06 ff 04 00 ff 06 Garbage
|
||||||
3e: 05 07 ff 02 03 05 07 ff 02 03
|
3e: 05 07 ff 02 03 05 07 ff 02 03 Garbage
|
||||||
3f: 01 01 e0 02 6c 01 00 60 00 a0
|
3f: 01 01 e0 02 6c 01 00 60 00 a0 Garbage
|
||||||
03 6c 04 40 04
|
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
|
// emulates K052591 collision detection
|
||||||
|
|
||||||
void thunderx_state::calculate_collisions()
|
void thunderx_state::pmc_run()
|
||||||
{
|
{
|
||||||
// the data at 0x00 to 0x06 defines the operation
|
// 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
|
// 0x07 : byte : first byte of set 1
|
||||||
//
|
//
|
||||||
// the operation is to intersect set 0 with set 1
|
// the operation is to intersect set 0 with set 1
|
||||||
// collide mask specifies objects to ignore
|
// masks specify 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
|
|
||||||
|
|
||||||
const int e0 = (m_pmcram[0] << 8) | m_pmcram[1];
|
const uint16_t e0 = get_u16be(&m_pmcram[0]);
|
||||||
const int e1 = m_pmcram[2];
|
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)
|
if (m_pmcram[5] < 16)
|
||||||
{
|
{
|
||||||
// US Thunder Cross uses this form
|
// US Thunder Cross uses this form
|
||||||
s0 = (m_pmcram[5] << 8) + m_pmcram[6];
|
s0 = get_u16be(&m_pmcram[5]);
|
||||||
s1 = m_pmcram[7];
|
s1 = m_pmcram[7];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -444,10 +388,44 @@ void thunderx_state::calculate_collisions()
|
|||||||
s1 = m_pmcram[6];
|
s1 = m_pmcram[6];
|
||||||
}
|
}
|
||||||
|
|
||||||
const int cm = m_pmcram[3];
|
const uint8_t cm = m_pmcram[3];
|
||||||
const int hm = m_pmcram[4];
|
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)
|
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)
|
// bit 2 = PMC START (do collision detection when 0->1)
|
||||||
if ((data & 4) && !(m_1f98_latch & 4))
|
if ((data & 4) && !(m_1f98_latch & 4))
|
||||||
{
|
{
|
||||||
calculate_collisions();
|
pmc_run();
|
||||||
|
|
||||||
// 100 cycle delay is arbitrary
|
|
||||||
m_thunderx_firq_timer->adjust(m_maincpu->cycles_to_attotime(100));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scontra_1f98_w(data);
|
scontra_1f98_w(data);
|
||||||
|
Loading…
Reference in New Issue
Block a user