mirror of
https://github.com/holub/mame
synced 2025-04-16 13:34:55 +03:00
Research into thoop and squash 'refresh rate' protection [Victor Fernandez (City Game), Peter Ferrie, David Haywood] (#8916)
* Research into thoop and squash 'refrsh rate' protection [Victor Fernandez (City Game), Peter Ferrie, David Haywood] - prevents freeze when dying in stage 4 of Thunder Hoop, and bad text on continue in Squash
This commit is contained in:
parent
45710aacf1
commit
edc0dfb627
@ -2032,7 +2032,7 @@ files {
|
|||||||
MAME_DIR .. "src/mame/includes/gaelco.h",
|
MAME_DIR .. "src/mame/includes/gaelco.h",
|
||||||
MAME_DIR .. "src/mame/video/gaelco.cpp",
|
MAME_DIR .. "src/mame/video/gaelco.cpp",
|
||||||
MAME_DIR .. "src/mame/machine/gaelcrpt.cpp",
|
MAME_DIR .. "src/mame/machine/gaelcrpt.cpp",
|
||||||
MAME_DIR .. "src/mame/includes/gaelcrpt.h",
|
MAME_DIR .. "src/mame/machine/gaelcrpt.h",
|
||||||
MAME_DIR .. "src/mame/drivers/gaelco2.cpp",
|
MAME_DIR .. "src/mame/drivers/gaelco2.cpp",
|
||||||
MAME_DIR .. "src/mame/includes/gaelco2.h",
|
MAME_DIR .. "src/mame/includes/gaelco2.h",
|
||||||
MAME_DIR .. "src/mame/machine/gaelco2.cpp",
|
MAME_DIR .. "src/mame/machine/gaelco2.cpp",
|
||||||
|
@ -2059,8 +2059,13 @@ void mcs51_cpu_device::execute_run()
|
|||||||
|
|
||||||
/* decrement the timed access window */
|
/* decrement the timed access window */
|
||||||
if (m_features & FEATURE_DS5002FP)
|
if (m_features & FEATURE_DS5002FP)
|
||||||
|
{
|
||||||
m_ds5002fp.ta_window = (m_ds5002fp.ta_window ? (m_ds5002fp.ta_window - 1) : 0x00);
|
m_ds5002fp.ta_window = (m_ds5002fp.ta_window ? (m_ds5002fp.ta_window - 1) : 0x00);
|
||||||
|
|
||||||
|
if (m_ds5002fp.rnr_delay > 0)
|
||||||
|
m_ds5002fp.rnr_delay-=m_inst_cycles;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the chip entered in idle mode, end the loop */
|
/* If the chip entered in idle mode, end the loop */
|
||||||
if ((m_features & FEATURE_CMOS) && GET_IDL)
|
if ((m_features & FEATURE_CMOS) && GET_IDL)
|
||||||
return;
|
return;
|
||||||
@ -2182,6 +2187,7 @@ void mcs51_cpu_device::device_start()
|
|||||||
save_item(NAME(m_irq_active) );
|
save_item(NAME(m_irq_active) );
|
||||||
save_item(NAME(m_ds5002fp.previous_ta) );
|
save_item(NAME(m_ds5002fp.previous_ta) );
|
||||||
save_item(NAME(m_ds5002fp.ta_window) );
|
save_item(NAME(m_ds5002fp.ta_window) );
|
||||||
|
save_item(NAME(m_ds5002fp.rnr_delay) );
|
||||||
save_item(NAME(m_ds5002fp.range) );
|
save_item(NAME(m_ds5002fp.range) );
|
||||||
save_item(NAME(m_uart.data_out));
|
save_item(NAME(m_uart.data_out));
|
||||||
save_item(NAME(m_uart.bits_to_send));
|
save_item(NAME(m_uart.bits_to_send));
|
||||||
@ -2326,6 +2332,7 @@ void mcs51_cpu_device::device_reset()
|
|||||||
m_ds5002fp.previous_ta = 0;
|
m_ds5002fp.previous_ta = 0;
|
||||||
m_ds5002fp.ta_window = 0;
|
m_ds5002fp.ta_window = 0;
|
||||||
m_ds5002fp.range = (GET_RG1 << 1) | GET_RG0;
|
m_ds5002fp.range = (GET_RG1 << 1) | GET_RG0;
|
||||||
|
m_ds5002fp.rnr_delay = 160;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_uart.data_out = 0;
|
m_uart.data_out = 0;
|
||||||
@ -2469,6 +2476,26 @@ void ds5002fp_device::sfr_write(size_t offset, uint8_t data)
|
|||||||
m_data.write_byte((size_t) offset | 0x100, data);
|
m_data.write_byte((size_t) offset | 0x100, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t ds5002fp_device::handle_rnr()
|
||||||
|
{
|
||||||
|
if (m_ds5002fp.rnr_delay <= 0)
|
||||||
|
{
|
||||||
|
m_ds5002fp.rnr_delay = 160; // delay before another random number can be read
|
||||||
|
return machine().rand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ds5002fp_device::is_rnr_ready()
|
||||||
|
{
|
||||||
|
if (m_ds5002fp.rnr_delay <= 0)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t ds5002fp_device::sfr_read(size_t offset)
|
uint8_t ds5002fp_device::sfr_read(size_t offset)
|
||||||
{
|
{
|
||||||
switch (offset)
|
switch (offset)
|
||||||
@ -2478,8 +2505,10 @@ uint8_t ds5002fp_device::sfr_read(size_t offset)
|
|||||||
case ADDR_CRCH: DS5_LOGR(CRCH, data); break;
|
case ADDR_CRCH: DS5_LOGR(CRCH, data); break;
|
||||||
case ADDR_MCON: DS5_LOGR(MCON, data); break;
|
case ADDR_MCON: DS5_LOGR(MCON, data); break;
|
||||||
case ADDR_TA: DS5_LOGR(TA, data); break;
|
case ADDR_TA: DS5_LOGR(TA, data); break;
|
||||||
case ADDR_RNR: DS5_LOGR(RNR, data); break;
|
case ADDR_RNR: DS5_LOGR(RNR, data);
|
||||||
case ADDR_RPCTL: DS5_LOGR(RPCTL, data); return 0x80; break; /* touchgo stalls unless bit 7 is set, why? documentation is unclear */
|
return handle_rnr();
|
||||||
|
case ADDR_RPCTL: DS5_LOGR(RPCTL, data); /* touchgo stalls unless bit 7 is set, RNR status (Random Number status) */
|
||||||
|
return (is_rnr_ready() ? 0x80 : 0x00); /* falling through to sfr_read for the remaining bits stops high score data loading? */
|
||||||
case ADDR_RPS: DS5_LOGR(RPS, data); break;
|
case ADDR_RPS: DS5_LOGR(RPS, data); break;
|
||||||
case ADDR_PCON:
|
case ADDR_PCON:
|
||||||
SET_PFW(0); /* reset PFW flag */
|
SET_PFW(0); /* reset PFW flag */
|
||||||
|
@ -158,7 +158,7 @@ protected:
|
|||||||
/* Serial Port TX/RX Callbacks */
|
/* Serial Port TX/RX Callbacks */
|
||||||
devcb_write8 m_serial_tx_cb; //Call back function when sending data out of serial port
|
devcb_write8 m_serial_tx_cb; //Call back function when sending data out of serial port
|
||||||
devcb_read8 m_serial_rx_cb; //Call back function to retrieve data when receiving serial port data
|
devcb_read8 m_serial_rx_cb; //Call back function to retrieve data when receiving serial port data
|
||||||
|
|
||||||
/* DS5002FP */
|
/* DS5002FP */
|
||||||
struct {
|
struct {
|
||||||
uint8_t previous_ta; /* Previous Timed Access value */
|
uint8_t previous_ta; /* Previous Timed Access value */
|
||||||
@ -168,6 +168,7 @@ protected:
|
|||||||
uint8_t mcon; /* bootstrap loader MCON register */
|
uint8_t mcon; /* bootstrap loader MCON register */
|
||||||
uint8_t rpctl; /* bootstrap loader RPCTL register */
|
uint8_t rpctl; /* bootstrap loader RPCTL register */
|
||||||
uint8_t crc; /* bootstrap loader CRC register */
|
uint8_t crc; /* bootstrap loader CRC register */
|
||||||
|
int32_t rnr_delay; /* delay before new random number available */
|
||||||
} m_ds5002fp;
|
} m_ds5002fp;
|
||||||
|
|
||||||
// for the debugger
|
// for the debugger
|
||||||
@ -604,6 +605,9 @@ protected:
|
|||||||
virtual void sfr_write(size_t offset, uint8_t data) override;
|
virtual void sfr_write(size_t offset, uint8_t data) override;
|
||||||
virtual uint8_t sfr_read(size_t offset) override;
|
virtual uint8_t sfr_read(size_t offset) override;
|
||||||
|
|
||||||
|
uint8_t handle_rnr();
|
||||||
|
bool is_rnr_ready();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
optional_memory_region m_region;
|
optional_memory_region m_region;
|
||||||
};
|
};
|
||||||
|
@ -281,12 +281,27 @@ void gaelco_gae1_device::device_start()
|
|||||||
|
|
||||||
if (LOG_WAVE)
|
if (LOG_WAVE)
|
||||||
wavraw = util::wav_open("gae1_snd.wav", rate, 2);
|
wavraw = util::wav_open("gae1_snd.wav", rate, 2);
|
||||||
|
|
||||||
|
for (int ch = 0; ch < NUM_CHANNELS; ch++)
|
||||||
|
{
|
||||||
|
save_item(NAME(m_channel[ch].active), ch);
|
||||||
|
save_item(NAME(m_channel[ch].loop), ch);
|
||||||
|
save_item(NAME(m_channel[ch].chunkNum), ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
save_item(NAME(m_sndregs));
|
||||||
}
|
}
|
||||||
|
|
||||||
void gaelco_gae1_device::device_reset()
|
void gaelco_gae1_device::device_reset()
|
||||||
{
|
{
|
||||||
for (int ch = 0; ch < NUM_CHANNELS; ch++)
|
for (int ch = 0; ch < NUM_CHANNELS; ch++)
|
||||||
|
{
|
||||||
m_channel[ch].active = 0;
|
m_channel[ch].active = 0;
|
||||||
|
m_channel[ch].loop = 0;
|
||||||
|
m_channel[ch].chunkNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fill(std::begin(m_sndregs), std::end(m_sndregs), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gaelco_gae1_device::device_stop()
|
void gaelco_gae1_device::device_stop()
|
||||||
|
@ -60,13 +60,16 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
sound_stream *m_stream; /* our stream */
|
sound_stream *m_stream; /* our stream */
|
||||||
int m_banks[4]; /* start of each ROM bank */
|
|
||||||
sound_channel m_channel[NUM_CHANNELS]; /* 7 stereo channels */
|
|
||||||
|
|
||||||
|
// live
|
||||||
|
sound_channel m_channel[NUM_CHANNELS]; /* 7 stereo channels */
|
||||||
uint16_t m_sndregs[0x38];
|
uint16_t m_sndregs[0x38];
|
||||||
|
|
||||||
// Table for converting from 8 to 16 bits with volume control
|
// Table for converting from 8 to 16 bits with volume control
|
||||||
int16_t m_volume_table[VOLUME_LEVELS][256];
|
int16_t m_volume_table[VOLUME_LEVELS][256];
|
||||||
|
|
||||||
|
// config
|
||||||
|
int m_banks[4]; /* start of each ROM bank */
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_DEVICE_TYPE(GAELCO_GAE1, gaelco_gae1_device)
|
DECLARE_DEVICE_TYPE(GAELCO_GAE1, gaelco_gae1_device)
|
||||||
|
@ -14,28 +14,84 @@ Year Game PCB NOTES
|
|||||||
1992 Squash REF 922804/1 Encrypted Video RAM
|
1992 Squash REF 922804/1 Encrypted Video RAM
|
||||||
1992 Thunder Hoop REF 922804/1 Encrypted Video RAM
|
1992 Thunder Hoop REF 922804/1 Encrypted Video RAM
|
||||||
1995 Biomechanical Toy REF 922804/2 Unprotected
|
1995 Biomechanical Toy REF 922804/2 Unprotected
|
||||||
1996 Maniac Square REF 922804/2 Prototype
|
1992 Maniac Square REF 922804/2 Prototype
|
||||||
|
|
||||||
TODO: Figure out why Thunder Hoop crashes if you die on Level 4
|
|
||||||
This can be bypassed by killing yourself at the same time as
|
|
||||||
the Level 3 boss dies, suggesting the end stage animation is
|
|
||||||
somehow corrupting the game state. Could this be a bug in
|
|
||||||
the supported revision of the game? It doesn't depend on
|
|
||||||
CPU clock, vblank timing, there are no unmapped reads or
|
|
||||||
writes of significance. Could it be related to a dipswitch
|
|
||||||
setting?
|
|
||||||
|
|
||||||
Priorities for all games - the games don't make extensive
|
Priorities for all games - the games don't make extensive
|
||||||
enough use of the priority scheme to properly draw any
|
enough use of the priority scheme to properly draw any
|
||||||
conclusions.
|
conclusions.
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
Note about 57.42 'FRAMERATE_922804' screen refresh
|
||||||
|
frequency and protection checks.
|
||||||
|
|
||||||
|
In thoop there's a timing loop at 0x49e-4ac. It's
|
||||||
|
counting frames between interrupt-triggers.
|
||||||
|
|
||||||
|
0x49e writes the count to 0xffdb62.
|
||||||
|
|
||||||
|
While fighting the second-stage boss, when the pink
|
||||||
|
things fly out, 0x8970 is called. 0x8988 fetches
|
||||||
|
from 0xffdb62. If the value is > 0xdd1 (via 0x898a)
|
||||||
|
or < 0xdb1 (via 0x8992), then 0x89ac sets 0xffdc45
|
||||||
|
to 5.
|
||||||
|
|
||||||
|
At 60hz the value returned is 0xd29, which causes
|
||||||
|
the fail condition to trigger. Values >=57.3 or
|
||||||
|
<=57.7 give a result within the required range. The
|
||||||
|
failure is not obvious at this point.
|
||||||
|
|
||||||
|
While fighting the third boss, 0xc2e8 is called.
|
||||||
|
After passing checks to know exactly when to trigger
|
||||||
|
(specifically, after the boss is defeated and the
|
||||||
|
power-up animation is finishes), 0xc350 checks if
|
||||||
|
0xffdc45 is 5. If it is, then we reach 0xc368, which
|
||||||
|
0xc368 sets 0xffe08e to 0x27. Again the failure is
|
||||||
|
not obvious at this point.
|
||||||
|
|
||||||
|
0xffe08e is checked during player respawn after
|
||||||
|
losing a life or continuing at 0x16d00, with an
|
||||||
|
explicit compare against 0x27, if this condition is
|
||||||
|
met, then the game will intentionally corrupt memory
|
||||||
|
and crash.
|
||||||
|
|
||||||
|
Many of these checks are done with obfuscated code
|
||||||
|
to hide the target addresses eg.
|
||||||
|
|
||||||
|
writing 0x27 to 0xffe08e
|
||||||
|
00C35C: lea $ffc92b.l, A4
|
||||||
|
00C362: adda.l #$1763, A4
|
||||||
|
00C368: move.b #$27, (A4)
|
||||||
|
|
||||||
|
This makes it more difficult to find where the checks
|
||||||
|
are being performed as an additional layer of
|
||||||
|
security
|
||||||
|
|
||||||
|
Squash has a similar timing loop, but with the
|
||||||
|
expected values adjusted due to the different 68000
|
||||||
|
clock on the otherwise identical Squash PCB (10Mhz on
|
||||||
|
Squash vs. 12Mhz on Thunder Hoop) In the case of
|
||||||
|
Squash the most obvious sign of failure is bad
|
||||||
|
'Insert Coin' sprites at the bottom of the screen
|
||||||
|
after a continue.
|
||||||
|
|
||||||
|
A refresh rate of 57.42, while not yet accurately
|
||||||
|
measured, allows a video of thoop to stay in sync with
|
||||||
|
MAME over a 10 minute period.
|
||||||
|
|
||||||
|
No checks have been observed in Biomechanical Toy,
|
||||||
|
the Maniac Square prototype, or the Last KM prototype.
|
||||||
|
|
||||||
|
Big Karnak runs on a different board type and does fail
|
||||||
|
if the CPU clock is set to 10Mhz rather than 12Mhz, it
|
||||||
|
also has additional checks which may still fail and
|
||||||
|
need more extensive research to determine exactly what
|
||||||
|
is being timed.
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "includes/gaelco.h"
|
#include "includes/gaelco.h"
|
||||||
|
|
||||||
#include "includes/gaelcrpt.h"
|
|
||||||
|
|
||||||
#include "cpu/m6809/m6809.h"
|
#include "cpu/m6809/m6809.h"
|
||||||
#include "cpu/m68000/m68000.h"
|
#include "cpu/m68000/m68000.h"
|
||||||
#include "sound/okim6295.h"
|
#include "sound/okim6295.h"
|
||||||
@ -88,7 +144,7 @@ void gaelco_state::irqack_w(uint16_t data)
|
|||||||
void gaelco_state::vram_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
void gaelco_state::vram_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||||
{
|
{
|
||||||
// osd_printf_debug("vram_encrypted_w!!\n");
|
// osd_printf_debug("vram_encrypted_w!!\n");
|
||||||
data = gaelco_decrypt(*m_maincpu, offset, data, 0x0f, 0x4228);
|
data = m_vramcrypt->gaelco_decrypt(*m_maincpu, offset, data);
|
||||||
vram_w(offset, data, mem_mask);
|
vram_w(offset, data, mem_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,23 +152,7 @@ void gaelco_state::vram_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_m
|
|||||||
void gaelco_state::encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
void gaelco_state::encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||||
{
|
{
|
||||||
// osd_printf_debug("encrypted_w!!\n");
|
// osd_printf_debug("encrypted_w!!\n");
|
||||||
data = gaelco_decrypt(*m_maincpu, offset, data, 0x0f, 0x4228);
|
data = m_vramcrypt->gaelco_decrypt(*m_maincpu, offset, data);
|
||||||
COMBINE_DATA(&m_screenram[offset]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********** Thunder Hoop Encryption Related Code ******************/
|
|
||||||
|
|
||||||
void gaelco_state::thoop_vram_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
|
||||||
{
|
|
||||||
// osd_printf_debug("vram_encrypted_w!!\n");
|
|
||||||
data = gaelco_decrypt(*m_maincpu, offset, data, 0x0e, 0x4228);
|
|
||||||
vram_w(offset, data, mem_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gaelco_state::thoop_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
|
||||||
{
|
|
||||||
// osd_printf_debug("encrypted_w!!\n");
|
|
||||||
data = gaelco_decrypt(*m_maincpu, offset, data, 0x0e, 0x4228);
|
|
||||||
COMBINE_DATA(&m_screenram[offset]);
|
COMBINE_DATA(&m_screenram[offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,8 +231,8 @@ void gaelco_state::squash_map(address_map &map)
|
|||||||
void gaelco_state::thoop_map(address_map &map)
|
void gaelco_state::thoop_map(address_map &map)
|
||||||
{
|
{
|
||||||
map(0x000000, 0x0fffff).rom(); // ROM
|
map(0x000000, 0x0fffff).rom(); // ROM
|
||||||
map(0x100000, 0x101fff).ram().w(FUNC(gaelco_state::thoop_vram_encrypted_w)).share("videoram"); // Video RAM
|
map(0x100000, 0x101fff).ram().w(FUNC(gaelco_state::vram_encrypted_w)).share("videoram"); // Video RAM
|
||||||
map(0x102000, 0x103fff).ram().w(FUNC(gaelco_state::thoop_encrypted_w)).share("screenram"); // Screen RAM
|
map(0x102000, 0x103fff).ram().w(FUNC(gaelco_state::encrypted_w)).share("screenram"); // Screen RAM
|
||||||
map(0x108000, 0x108007).writeonly().share("vregs"); // Video Registers
|
map(0x108000, 0x108007).writeonly().share("vregs"); // Video Registers
|
||||||
map(0x10800c, 0x10800d).w(FUNC(gaelco_state::irqack_w)); // INT 6 ACK/Watchdog timer
|
map(0x10800c, 0x10800d).w(FUNC(gaelco_state::irqack_w)); // INT 6 ACK/Watchdog timer
|
||||||
map(0x200000, 0x2007ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); // Palette
|
map(0x200000, 0x2007ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); // Palette
|
||||||
@ -707,7 +747,7 @@ void gaelco_state::maniacsq(machine_config &config)
|
|||||||
|
|
||||||
// Video hardware
|
// Video hardware
|
||||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||||
screen.set_refresh_hz(60);
|
screen.set_refresh_hz(FRAMERATE_922804);
|
||||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
|
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
|
||||||
screen.set_size(32*16, 32*16);
|
screen.set_size(32*16, 32*16);
|
||||||
screen.set_visarea(0, 320-1, 16, 256-1);
|
screen.set_visarea(0, 320-1, 16, 256-1);
|
||||||
@ -736,6 +776,9 @@ void gaelco_state::squash(machine_config &config)
|
|||||||
|
|
||||||
config.set_maximum_quantum(attotime::from_hz(600));
|
config.set_maximum_quantum(attotime::from_hz(600));
|
||||||
|
|
||||||
|
GAELCO_VRAM_ENCRYPTION(config, m_vramcrypt);
|
||||||
|
m_vramcrypt->set_params(0x0f, 0x4228);
|
||||||
|
|
||||||
LS259(config, m_outlatch); // B8
|
LS259(config, m_outlatch); // B8
|
||||||
m_outlatch->q_out_cb<0>().set(FUNC(gaelco_state::coin1_lockout_w)).invert();
|
m_outlatch->q_out_cb<0>().set(FUNC(gaelco_state::coin1_lockout_w)).invert();
|
||||||
m_outlatch->q_out_cb<1>().set(FUNC(gaelco_state::coin2_lockout_w)).invert();
|
m_outlatch->q_out_cb<1>().set(FUNC(gaelco_state::coin2_lockout_w)).invert();
|
||||||
@ -745,7 +788,7 @@ void gaelco_state::squash(machine_config &config)
|
|||||||
|
|
||||||
// Video hardware
|
// Video hardware
|
||||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||||
screen.set_refresh_hz(58);
|
screen.set_refresh_hz(FRAMERATE_922804);
|
||||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
|
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
|
||||||
screen.set_size(32*16, 32*16);
|
screen.set_size(32*16, 32*16);
|
||||||
screen.set_visarea(0, 320-1, 16, 256-1);
|
screen.set_visarea(0, 320-1, 16, 256-1);
|
||||||
@ -774,6 +817,9 @@ void gaelco_state::thoop(machine_config &config)
|
|||||||
|
|
||||||
config.set_maximum_quantum(attotime::from_hz(600));
|
config.set_maximum_quantum(attotime::from_hz(600));
|
||||||
|
|
||||||
|
GAELCO_VRAM_ENCRYPTION(config, m_vramcrypt);
|
||||||
|
m_vramcrypt->set_params(0x0e, 0x4228);
|
||||||
|
|
||||||
LS259(config, m_outlatch); // B8
|
LS259(config, m_outlatch); // B8
|
||||||
m_outlatch->q_out_cb<0>().set(FUNC(gaelco_state::coin1_lockout_w)); // not inverted
|
m_outlatch->q_out_cb<0>().set(FUNC(gaelco_state::coin1_lockout_w)); // not inverted
|
||||||
m_outlatch->q_out_cb<1>().set(FUNC(gaelco_state::coin2_lockout_w)); // not inverted
|
m_outlatch->q_out_cb<1>().set(FUNC(gaelco_state::coin2_lockout_w)); // not inverted
|
||||||
@ -783,7 +829,7 @@ void gaelco_state::thoop(machine_config &config)
|
|||||||
|
|
||||||
// Video hardware
|
// Video hardware
|
||||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||||
screen.set_refresh_hz(60);
|
screen.set_refresh_hz(FRAMERATE_922804);
|
||||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
|
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
|
||||||
screen.set_size(32*16, 32*16);
|
screen.set_size(32*16, 32*16);
|
||||||
screen.set_visarea(0, 320-1, 16, 256-1);
|
screen.set_visarea(0, 320-1, 16, 256-1);
|
||||||
@ -1184,6 +1230,6 @@ GAME( 1995, biomtoyb, biomtoy, maniacsq, biomtoy, gaelco_state, empty_init, RO
|
|||||||
GAME( 1994, biomtoyc, biomtoy, maniacsq, biomtoyc, gaelco_state, empty_init, ROT0, "Gaelco", "Biomechanical Toy (Ver. 1.0.1870)", MACHINE_SUPPORTS_SAVE )
|
GAME( 1994, biomtoyc, biomtoy, maniacsq, biomtoyc, gaelco_state, empty_init, ROT0, "Gaelco", "Biomechanical Toy (Ver. 1.0.1870)", MACHINE_SUPPORTS_SAVE )
|
||||||
GAME( 1994, bioplayc, biomtoy, maniacsq, bioplayc, gaelco_state, empty_init, ROT0, "Gaelco", "Bioplaything Cop (Ver. 1.0.1823, prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND ) // copyright based on Ver. 1.0.1870
|
GAME( 1994, bioplayc, biomtoy, maniacsq, bioplayc, gaelco_state, empty_init, ROT0, "Gaelco", "Bioplaything Cop (Ver. 1.0.1823, prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND ) // copyright based on Ver. 1.0.1870
|
||||||
GAME( 1992, maniacsp, 0, maniacsq, maniacsq, gaelco_state, empty_init, ROT0, "Gaelco", "Maniac Square (prototype)", MACHINE_SUPPORTS_SAVE ) // The prototype version was an earlier project, said to be from 1992, game was rewritten in 1996
|
GAME( 1992, maniacsp, 0, maniacsq, maniacsq, gaelco_state, empty_init, ROT0, "Gaelco", "Maniac Square (prototype)", MACHINE_SUPPORTS_SAVE ) // The prototype version was an earlier project, said to be from 1992, game was rewritten in 1996
|
||||||
GAME( 1995, lastkm, 0, maniacsq, lastkm, gaelco_state, empty_init, ROT0, "Gaelco", "Last KM (Ver 1.0.0275)", MACHINE_SUPPORTS_SAVE ) // used on 'Salter' exercise bikes
|
GAME( 1995, lastkm, 0, maniacsq, lastkm, gaelco_state, empty_init, ROT0, "Gaelco", "Last KM (Ver 1.0.0275, prototype)", MACHINE_SUPPORTS_SAVE ) // Similar 'bike controller' idea to the Salter gym equipment Gaelco developed, but in game form
|
||||||
GAME( 1992, squash, 0, squash, squash, gaelco_state, empty_init, ROT0, "Gaelco", "Squash (Ver. 1.0)", MACHINE_SUPPORTS_SAVE )
|
GAME( 1992, squash, 0, squash, squash, gaelco_state, empty_init, ROT0, "Gaelco", "Squash (Ver. 1.0)", MACHINE_SUPPORTS_SAVE )
|
||||||
GAME( 1992, thoop, 0, thoop, thoop, gaelco_state, empty_init, ROT0, "Gaelco", "Thunder Hoop (Ver. 1, Checksum 02A09F7D)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) // could be other versions, still Ver. 1 but different checksum listed on boot
|
GAME( 1992, thoop, 0, thoop, thoop, gaelco_state, empty_init, ROT0, "Gaelco", "Thunder Hoop (Ver. 1, Checksum 02A09F7D)", MACHINE_SUPPORTS_SAVE ) // could be other versions, still Ver. 1 but different checksum listed on boot
|
||||||
|
@ -2722,10 +2722,10 @@ GAME( 1994, aligatorun, aligator, alighunt, alighunt, gaelco2_state, i
|
|||||||
GAME( 1994, aligatoruna, aligator, alighunt, alighunt, gaelco2_state, init_alighunt, ROT0, "Gaelco", "Alligator Hunt (unprotected, set 2)", 0 ) // strange version, starts on space stages, but clearly a recompile not a trivial hack of the above, show version maybe?
|
GAME( 1994, aligatoruna, aligator, alighunt, alighunt, gaelco2_state, init_alighunt, ROT0, "Gaelco", "Alligator Hunt (unprotected, set 2)", 0 ) // strange version, starts on space stages, but clearly a recompile not a trivial hack of the above, show version maybe?
|
||||||
GAME( 1994, aligatorp, aligator, alighunt_d5002fp, alighunt, gaelco2_state, empty_init, ROT0, "Gaelco", "Alligator Hunt (protected, prototype?)", MACHINE_NOT_WORKING ) // requires different protection program / data
|
GAME( 1994, aligatorp, aligator, alighunt_d5002fp, alighunt, gaelco2_state, empty_init, ROT0, "Gaelco", "Alligator Hunt (protected, prototype?)", MACHINE_NOT_WORKING ) // requires different protection program / data
|
||||||
|
|
||||||
GAME( 1995, touchgo, 0, touchgo_d5002fp, touchgo, gaelco2_state, init_touchgo, ROT0, "Gaelco", "Touch & Go (World)", MACHINE_IMPERFECT_SOUND )
|
GAME( 1995, touchgo, 0, touchgo_d5002fp, touchgo, gaelco2_state, init_touchgo, ROT0, "Gaelco", "Touch & Go (World)", 0 )
|
||||||
GAME( 1995, touchgon, touchgo, touchgo_d5002fp, touchgo, gaelco2_state, init_touchgo, ROT0, "Gaelco", "Touch & Go (Non North America)", MACHINE_IMPERFECT_SOUND )
|
GAME( 1995, touchgon, touchgo, touchgo_d5002fp, touchgo, gaelco2_state, init_touchgo, ROT0, "Gaelco", "Touch & Go (Non North America)", 0 )
|
||||||
GAME( 1995, touchgoe, touchgo, touchgo_d5002fp, touchgo, gaelco2_state, init_touchgo, ROT0, "Gaelco", "Touch & Go (earlier revision)", MACHINE_IMPERFECT_SOUND )
|
GAME( 1995, touchgoe, touchgo, touchgo_d5002fp, touchgo, gaelco2_state, init_touchgo, ROT0, "Gaelco", "Touch & Go (earlier revision)", 0 )
|
||||||
GAME( 1995, touchgok, touchgo, touchgo, touchgo, gaelco2_state, init_touchgo, ROT0, "Gaelco", "Touch & Go (Korea, unprotected)", MACHINE_IMPERFECT_SOUND ) // doesn't say 'Korea' but was sourced there, shows 2 copyright lines like the 'earlier revision'
|
GAME( 1995, touchgok, touchgo, touchgo, touchgo, gaelco2_state, init_touchgo, ROT0, "Gaelco", "Touch & Go (Korea, unprotected)", 0 ) // doesn't say 'Korea' but was sourced there, shows 2 copyright lines like the 'earlier revision'
|
||||||
|
|
||||||
GAME( 1995, wrally2, 0, wrally2, wrally2, wrally2_state, init_wrally2, ROT0, "Gaelco", "World Rally 2: Twin Racing (mask ROM version)", 0 )
|
GAME( 1995, wrally2, 0, wrally2, wrally2, wrally2_state, init_wrally2, ROT0, "Gaelco", "World Rally 2: Twin Racing (mask ROM version)", 0 )
|
||||||
GAME( 1995, wrally2a, wrally2, wrally2, wrally2, wrally2_state, empty_init, ROT0, "Gaelco", "World Rally 2: Twin Racing (EPROM version)", 0 )
|
GAME( 1995, wrally2a, wrally2, wrally2, wrally2, wrally2_state, empty_init, ROT0, "Gaelco", "World Rally 2: Twin Racing (EPROM version)", 0 )
|
||||||
|
@ -126,7 +126,6 @@ The PCB has a layout that can either use the 4 rom set of I7, I9, I11 & I13 or l
|
|||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "includes/wrally.h"
|
#include "includes/wrally.h"
|
||||||
#include "includes/gaelcrpt.h"
|
|
||||||
|
|
||||||
#include "machine/gaelco_ds5002fp.h"
|
#include "machine/gaelco_ds5002fp.h"
|
||||||
|
|
||||||
@ -167,7 +166,7 @@ uint8_t wrally_state::shareram_r(offs_t offset)
|
|||||||
|
|
||||||
void wrally_state::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
void wrally_state::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||||
{
|
{
|
||||||
data = gaelco_decrypt(*m_maincpu, offset, data, 0x1f, 0x522a);
|
data = m_vramcrypt->gaelco_decrypt(*m_maincpu, offset, data);
|
||||||
COMBINE_DATA(&m_videoram[offset]);
|
COMBINE_DATA(&m_videoram[offset]);
|
||||||
|
|
||||||
m_tilemap[(offset & 0x1fff) >> 12]->mark_tile_dirty(((offset << 1) & 0x1fff) >> 2);
|
m_tilemap[(offset & 0x1fff) >> 12]->mark_tile_dirty(((offset << 1) & 0x1fff) >> 2);
|
||||||
@ -376,6 +375,9 @@ void wrally_state::wrally(machine_config &config)
|
|||||||
ds5002.set_addrmap(0, &wrally_state::mcu_hostmem_map);
|
ds5002.set_addrmap(0, &wrally_state::mcu_hostmem_map);
|
||||||
config.set_perfect_quantum("gaelco_ds5002fp:mcu");
|
config.set_perfect_quantum("gaelco_ds5002fp:mcu");
|
||||||
|
|
||||||
|
GAELCO_VRAM_ENCRYPTION(config, m_vramcrypt);
|
||||||
|
m_vramcrypt->set_params(0x1f, 0x522a);
|
||||||
|
|
||||||
// Video hardware
|
// Video hardware
|
||||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||||
screen.set_refresh_hz(60);
|
screen.set_refresh_hz(60);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "machine/gen_latch.h"
|
#include "machine/gen_latch.h"
|
||||||
#include "machine/74259.h"
|
#include "machine/74259.h"
|
||||||
|
#include "machine/gaelcrpt.h"
|
||||||
#include "emupal.h"
|
#include "emupal.h"
|
||||||
#include "tilemap.h"
|
#include "tilemap.h"
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ public:
|
|||||||
m_maincpu(*this, "maincpu"),
|
m_maincpu(*this, "maincpu"),
|
||||||
m_gfxdecode(*this, "gfxdecode"),
|
m_gfxdecode(*this, "gfxdecode"),
|
||||||
m_palette(*this, "palette"),
|
m_palette(*this, "palette"),
|
||||||
|
m_vramcrypt(*this, "vramcrypt"),
|
||||||
m_audiocpu(*this, "audiocpu"),
|
m_audiocpu(*this, "audiocpu"),
|
||||||
m_soundlatch(*this, "soundlatch"),
|
m_soundlatch(*this, "soundlatch"),
|
||||||
m_outlatch(*this, "outlatch"),
|
m_outlatch(*this, "outlatch"),
|
||||||
@ -40,6 +42,7 @@ private:
|
|||||||
required_device<cpu_device> m_maincpu;
|
required_device<cpu_device> m_maincpu;
|
||||||
required_device<gfxdecode_device> m_gfxdecode;
|
required_device<gfxdecode_device> m_gfxdecode;
|
||||||
required_device<palette_device> m_palette;
|
required_device<palette_device> m_palette;
|
||||||
|
optional_device<gaelco_vram_encryption_device> m_vramcrypt;
|
||||||
optional_device<cpu_device> m_audiocpu;
|
optional_device<cpu_device> m_audiocpu;
|
||||||
optional_device<generic_latch_8_device> m_soundlatch;
|
optional_device<generic_latch_8_device> m_soundlatch;
|
||||||
optional_device<ls259_device> m_outlatch;
|
optional_device<ls259_device> m_outlatch;
|
||||||
@ -61,8 +64,6 @@ private:
|
|||||||
void oki_bankswitch_w(uint8_t data);
|
void oki_bankswitch_w(uint8_t data);
|
||||||
void vram_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
void vram_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||||
void encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
void encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||||
void thoop_vram_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
|
||||||
void thoop_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
|
||||||
void vram_w(offs_t offset, u16 data, u16 mem_mask);
|
void vram_w(offs_t offset, u16 data, u16 mem_mask);
|
||||||
void irqack_w(uint16_t data);
|
void irqack_w(uint16_t data);
|
||||||
|
|
||||||
@ -87,4 +88,6 @@ private:
|
|||||||
|
|
||||||
/* per-game configuration */
|
/* per-game configuration */
|
||||||
uint8_t m_sprite_palette_force_high;
|
uint8_t m_sprite_palette_force_high;
|
||||||
|
|
||||||
|
static constexpr double FRAMERATE_922804 = 57.42;
|
||||||
};
|
};
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
// license:BSD-3-Clause
|
|
||||||
// copyright-holders:Manuel Abadia
|
|
||||||
/*----------- defined in machine/gaelcrpt.cpp -----------*/
|
|
||||||
|
|
||||||
uint16_t gaelco_decrypt(cpu_device &cpu, int offset, int data, int param1, int param2);
|
|
@ -6,6 +6,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "machine/74259.h"
|
#include "machine/74259.h"
|
||||||
|
#include "machine/gaelcrpt.h"
|
||||||
#include "video/gaelco_wrally_sprites.h"
|
#include "video/gaelco_wrally_sprites.h"
|
||||||
#include "emupal.h"
|
#include "emupal.h"
|
||||||
#include "tilemap.h"
|
#include "tilemap.h"
|
||||||
@ -21,6 +22,7 @@ public:
|
|||||||
m_palette(*this, "palette"),
|
m_palette(*this, "palette"),
|
||||||
m_sprites(*this, "sprites"),
|
m_sprites(*this, "sprites"),
|
||||||
m_okibank(*this, "okibank"),
|
m_okibank(*this, "okibank"),
|
||||||
|
m_vramcrypt(*this, "vramcrypt"),
|
||||||
m_videoram(*this, "videoram"),
|
m_videoram(*this, "videoram"),
|
||||||
m_vregs(*this, "vregs"),
|
m_vregs(*this, "vregs"),
|
||||||
m_spriteram(*this, "spriteram"),
|
m_spriteram(*this, "spriteram"),
|
||||||
@ -66,6 +68,7 @@ private:
|
|||||||
required_device<palette_device> m_palette;
|
required_device<palette_device> m_palette;
|
||||||
required_device<gaelco_wrally_sprites_device> m_sprites;
|
required_device<gaelco_wrally_sprites_device> m_sprites;
|
||||||
required_memory_bank m_okibank;
|
required_memory_bank m_okibank;
|
||||||
|
required_device<gaelco_vram_encryption_device> m_vramcrypt;
|
||||||
|
|
||||||
required_shared_ptr<uint16_t> m_videoram;
|
required_shared_ptr<uint16_t> m_videoram;
|
||||||
required_shared_ptr<uint16_t> m_vregs;
|
required_shared_ptr<uint16_t> m_vregs;
|
||||||
|
@ -6,12 +6,27 @@ Gaelco video RAM encryption
|
|||||||
|
|
||||||
Thanks to GAELCO SA for information on the algorithm.
|
Thanks to GAELCO SA for information on the algorithm.
|
||||||
|
|
||||||
|
TODO: the device must be able to know a 32-bit write was from the same
|
||||||
|
opcode WITHOUT looking at the host program counter.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "includes/gaelcrpt.h"
|
#include "gaelcrpt.h"
|
||||||
|
|
||||||
static int decrypt(int const param1, int const param2, int const enc_prev_word, int const dec_prev_word, int const enc_word)
|
DEFINE_DEVICE_TYPE(GAELCO_VRAM_ENCRYPTION, gaelco_vram_encryption_device, "gaelco_vram_crypt", "Gaelco VRAM Encryption")
|
||||||
|
|
||||||
|
|
||||||
|
gaelco_vram_encryption_device::gaelco_vram_encryption_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||||
|
: device_t(mconfig, GAELCO_VRAM_ENCRYPTION, tag, owner, clock),
|
||||||
|
m_param1(0),
|
||||||
|
m_param2(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int gaelco_vram_encryption_device::decrypt(int const enc_prev_word, int const dec_prev_word, int const enc_word)
|
||||||
{
|
{
|
||||||
int const swap = (BIT(dec_prev_word, 8) << 1) | BIT(dec_prev_word, 7);
|
int const swap = (BIT(dec_prev_word, 8) << 1) | BIT(dec_prev_word, 7);
|
||||||
int const type = (BIT(dec_prev_word,12) << 1) | BIT(dec_prev_word, 2);
|
int const type = (BIT(dec_prev_word,12) << 1) | BIT(dec_prev_word, 2);
|
||||||
@ -26,7 +41,7 @@ static int decrypt(int const param1, int const param2, int const enc_prev_word,
|
|||||||
case 3: res = bitswap<16>(enc_word, 3, 8, 1,13,14, 4,15, 0,10, 2, 7,12, 6,11, 9, 5); break;
|
case 3: res = bitswap<16>(enc_word, 3, 8, 1,13,14, 4,15, 0,10, 2, 7,12, 6,11, 9, 5); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
res ^= param2;
|
res ^= m_param2;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@ -67,11 +82,11 @@ static int decrypt(int const param1, int const param2, int const enc_prev_word,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
k ^= param1;
|
k ^= m_param1;
|
||||||
|
|
||||||
res = (res & 0xffc0) | ((res + k) & 0x003f);
|
res = (res & 0xffc0) | ((res + k) & 0x003f);
|
||||||
|
|
||||||
res ^= param1;
|
res ^= m_param1;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@ -109,46 +124,57 @@ static int decrypt(int const param1, int const param2, int const enc_prev_word,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
k ^= param1;
|
k ^= m_param1;
|
||||||
|
|
||||||
res = (res & 0x003f) |
|
res = (res & 0x003f) |
|
||||||
((res + (k << 6)) & 0x07c0) |
|
((res + (k << 6)) & 0x07c0) |
|
||||||
((res + (k << 11)) & 0xf800);
|
((res + (k << 11)) & 0xf800);
|
||||||
|
|
||||||
res ^= (param1 << 6) | (param1 << 11);
|
res ^= (m_param1 << 6) | (m_param1 << 11);
|
||||||
|
|
||||||
return bitswap<16>(res, 2,6,0,11,14,12,7,10,5,4,8,3,9,1,13,15);
|
return bitswap<16>(res, 2,6,0,11,14,12,7,10,5,4,8,3,9,1,13,15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t gaelco_decrypt(cpu_device &cpu, int offset, int data, int param1, int param2)
|
uint16_t gaelco_vram_encryption_device::gaelco_decrypt(cpu_device &cpu, int offset, int data)
|
||||||
{
|
{
|
||||||
static int lastpc, lastoffset, lastencword, lastdecword;
|
|
||||||
|
|
||||||
int thispc = cpu.pc();
|
int thispc = cpu.pc();
|
||||||
// int savedata = data;
|
// int savedata = data;
|
||||||
|
|
||||||
/* check if 2nd half of 32 bit */
|
/* check if 2nd half of 32 bit */
|
||||||
if(lastpc == thispc && offset == lastoffset + 1)
|
if(m_lastpc == thispc && offset == m_lastoffset + 1)
|
||||||
{
|
{
|
||||||
lastpc = 0;
|
m_lastpc = 0;
|
||||||
data = decrypt(param1, param2, lastencword, lastdecword, data);
|
data = decrypt(m_lastencword, m_lastdecword, data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* code as 1st word */
|
/* code as 1st word */
|
||||||
|
|
||||||
lastpc = thispc;
|
m_lastpc = thispc;
|
||||||
lastoffset = offset;
|
m_lastoffset = offset;
|
||||||
lastencword = data;
|
m_lastencword = data;
|
||||||
|
|
||||||
/* high word returned */
|
/* high word returned */
|
||||||
data = decrypt(param1, param2, 0, 0, data);
|
data = decrypt(0, 0, data);
|
||||||
|
|
||||||
lastdecword = data;
|
m_lastdecword = data;
|
||||||
|
|
||||||
// logerror("%s : data1 = %4x > %4x @ %8x\n",machine().describe_context(),savedata,data,lastoffset);
|
// logerror("%s : data1 = %4x > %4x @ %8x\n",machine().describe_context(),savedata,data,m_lastoffset);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gaelco_vram_encryption_device::device_start()
|
||||||
|
{
|
||||||
|
save_item(NAME(m_lastpc));
|
||||||
|
save_item(NAME(m_lastoffset));
|
||||||
|
save_item(NAME(m_lastencword));
|
||||||
|
save_item(NAME(m_lastdecword));
|
||||||
|
}
|
||||||
|
|
||||||
|
void gaelco_vram_encryption_device::device_reset()
|
||||||
|
{
|
||||||
|
m_lastpc = m_lastoffset = m_lastencword = m_lastdecword = -1;
|
||||||
|
}
|
||||||
|
35
src/mame/machine/gaelcrpt.h
Normal file
35
src/mame/machine/gaelcrpt.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Manuel Abadia
|
||||||
|
|
||||||
|
#ifndef MAME_MACHINE_GAELCRPT_H
|
||||||
|
#define MAME_MACHINE_GAELCRPT_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
DECLARE_DEVICE_TYPE(GAELCO_VRAM_ENCRYPTION, gaelco_vram_encryption_device)
|
||||||
|
|
||||||
|
|
||||||
|
class gaelco_vram_encryption_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// construction/destruction
|
||||||
|
gaelco_vram_encryption_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||||
|
void set_params(uint8_t param1, uint16_t param2) { m_param1 = param1; m_param2 = param2; }
|
||||||
|
|
||||||
|
uint16_t gaelco_decrypt(cpu_device &cpu, int offset, int data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void device_start() override;
|
||||||
|
virtual void device_reset() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int decrypt(int const enc_prev_word, int const dec_prev_word, int const enc_word);
|
||||||
|
|
||||||
|
int32_t m_lastpc, m_lastoffset, m_lastencword, m_lastdecword;
|
||||||
|
|
||||||
|
// config
|
||||||
|
uint8_t m_param1;
|
||||||
|
uint16_t m_param2;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAME_MACHINE_GAELCRPT_H
|
@ -8,8 +8,12 @@
|
|||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
verify priority implementations
|
verify priority implementations
|
||||||
understand bad sprites in Squash after the continue screen, these do not
|
|
||||||
occur on real hardware.
|
NOTE:
|
||||||
|
if Squash fails a protection check it will leave bad 'Insert Coin' text
|
||||||
|
on the screen after a continue, this is not a sprite emulation bug, the
|
||||||
|
machine expects a 68k clock of around 10Mhz and a refresh of around 57.4
|
||||||
|
to pass the protection, see notes in main driver file.
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user