mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
473 lines
11 KiB
C
473 lines
11 KiB
C
/*
|
|
* UAE - The Un*x Amiga Emulator
|
|
*
|
|
* Arcadia emulation
|
|
*
|
|
* Copyright 2005-2007 Toni Wilen
|
|
*
|
|
*
|
|
*/
|
|
|
|
#include "sysconfig.h"
|
|
#include "sysdeps.h"
|
|
|
|
#include "options.h"
|
|
#include "uae.h"
|
|
#include "memory.h"
|
|
#include "custom.h"
|
|
#include "newcpu.h"
|
|
#include "debug.h"
|
|
#include "arcadia.h"
|
|
#include "zfile.h"
|
|
|
|
/* supported roms (mame 0.90)
|
|
*
|
|
* - ar_airh
|
|
* - ar_bowl
|
|
* - ar_fast
|
|
* - ar_ldrb
|
|
* - ar_ldrba
|
|
* - ar_ninj
|
|
* - ar_rdwr
|
|
* - ar_socc (99u8)
|
|
* - ar_sdwr
|
|
* - ar_spot
|
|
* - ar_sprg
|
|
* - ar_xeon
|
|
*
|
|
*/
|
|
|
|
static void multigame(int);
|
|
|
|
int arcadia_flag, arcadia_coin[2];
|
|
struct arcadiarom *arcadia_bios, *arcadia_game;
|
|
|
|
#define BIOS_VERSION_211 2
|
|
#define BIOS_VERSION_300 3
|
|
|
|
static struct arcadiarom roms[] = {
|
|
|
|
{ 49, L"ar_bios.zip", L"scpa21", ARCADIA_BIOS, 0, 6, 1, 0, 2, 3, 4, 5, 7 },
|
|
{ 50, L"ar_bios.zip", L"gcp-", ARCADIA_BIOS, 3, 7, 6, 5, 4, 3, 2, 1, 0 },
|
|
{ 51, L"ar_bios.zip", L"scpav3_0.", ARCADIA_BIOS, 0, 6, 1, 0, 2, 3, 4, 5, 7 },
|
|
|
|
{ 33, L"ar_airh.zip", L"airh_", ARCADIA_GAME, 1, 5, 0, 2, 4, 7, 6, 1, 3 },
|
|
{ 34, L"ar_bowl.zip", L"bowl_", ARCADIA_GAME, 1, 7, 6, 0, 1, 2, 3, 4, 5 },
|
|
{ 35, L"ar_dart.zip", L"dart_", ARCADIA_GAME, 1, 4, 0, 7, 6, 3, 1, 2, 5 },
|
|
{ 36, L"ar_fast.zip", L"fastv28.", ARCADIA_GAME, 0, 7, 6, 5, 4, 3, 2, 1, 0 },
|
|
{ 37, L"ar_ldrb.zip", L"lbg240", ARCADIA_GAME, 0, 7, 6, 5, 4, 3, 2, 1, 0 },
|
|
{ 38, L"ar_ldrba.zip",L"ldrb_", ARCADIA_GAME, 1, 2, 3, 4, 1, 0, 7, 5, 6 },
|
|
{ 39, L"ar_ninj.zip", L"ninj_", ARCADIA_GAME, 1, 1, 6, 5, 7, 4, 2, 0, 3 },
|
|
{ 40, L"ar_rdwr.zip", L"rdwr_", ARCADIA_GAME, 1, 3, 1, 6, 4, 0, 5, 2, 7 },
|
|
{ 41, L"ar_sdwr.zip", L"sdwr_", ARCADIA_GAME, 1, 6, 3, 4, 5, 2, 1, 0, 7 },
|
|
{ 42, L"ar_spot.zip", L"spotv2.", ARCADIA_GAME, 0, 7, 6, 5, 4, 3, 2, 1, 0 },
|
|
{ 43, L"ar_sprg.zip", L"sprg_", ARCADIA_GAME, 1, 4, 7, 3, 0, 6, 5, 2, 1 },
|
|
{ 44, L"ar_xeon.zip", L"xeon_", ARCADIA_GAME, 1, 3, 1, 2, 4, 0, 5, 6, 7 },
|
|
{ 45, L"ar_socc.zip", L"socc30.", ARCADIA_GAME, 2, 0, 7, 1, 6, 5, 4, 3, 2 },
|
|
|
|
{ -1 }
|
|
};
|
|
|
|
static uae_u8 *arbmemory, *arbbmemory;
|
|
static int boot_read;
|
|
|
|
#define arb_start 0x800000
|
|
#define arb_mask 0x1fffff
|
|
#define allocated_arbmemory 0x200000
|
|
|
|
#define arbb_start 0xf00000
|
|
#define arbb_mask 0x7ffff
|
|
#define allocated_arbbmemory 0x80000
|
|
|
|
#define nvram_offset 0x1fc000
|
|
#define bios_offset 0x180000
|
|
#define NVRAM_SIZE 0x4000
|
|
|
|
static int nvwrite;
|
|
|
|
static int load_rom8 (TCHAR *xpath, uae_u8 *mem, int extra)
|
|
{
|
|
struct zfile *zf;
|
|
TCHAR path[MAX_DPATH];
|
|
int i;
|
|
uae_u8 *tmp = xmalloc (131072);
|
|
TCHAR *bin = extra == 1 ? L".bin" : L"";
|
|
|
|
memset (tmp, 0, 131072);
|
|
_stprintf (path, L"%s%s%s", xpath, extra == 3 ? L"-hi" : (extra == 2 ? L"hi" : L"h"), bin);
|
|
zf = zfile_fopen (path, L"rb", ZFD_NORMAL);
|
|
if (!zf)
|
|
goto end;
|
|
if (zfile_fread (tmp, 65536, 1, zf) == 0)
|
|
goto end;
|
|
zfile_fclose (zf);
|
|
_stprintf (path, L"%s%s%s", xpath, extra == 3 ? L"-lo" : (extra == 2 ? L"lo" : L"l"), bin);
|
|
zf = zfile_fopen (path, L"rb", ZFD_NORMAL);
|
|
if (!zf)
|
|
goto end;
|
|
if (zfile_fread (tmp + 65536, 65536, 1, zf) == 0)
|
|
goto end;
|
|
zfile_fclose (zf);
|
|
for (i = 0; i < 65536; i++) {
|
|
mem[i * 2 + 0] = tmp[i];
|
|
mem[i * 2 + 1] = tmp[i + 65536];
|
|
}
|
|
xfree (tmp);
|
|
return 1;
|
|
end:
|
|
xfree (tmp);
|
|
return 0;
|
|
}
|
|
|
|
static struct arcadiarom *is_arcadia (const TCHAR *xpath, int cnt)
|
|
{
|
|
TCHAR path[MAX_DPATH], *p;
|
|
struct arcadiarom *rom = NULL;
|
|
int i;
|
|
|
|
_tcscpy (path, xpath);
|
|
p = path;
|
|
for (i = _tcslen (xpath) - 1; i > 0; i--) {
|
|
if (path[i] == '\\' || path[i] == '/') {
|
|
path[i++] = 0;
|
|
p = path + i;
|
|
break;
|
|
}
|
|
}
|
|
for (i = 0; roms[i].romid > 0; i++) {
|
|
if (!_tcsicmp (p, roms[i].name) || !_tcsicmp (p, roms[i].rom)) {
|
|
if (cnt > 0) {
|
|
cnt--;
|
|
continue;
|
|
}
|
|
rom = &roms[i];
|
|
break;
|
|
}
|
|
}
|
|
if (!rom)
|
|
return 0;
|
|
return rom;
|
|
}
|
|
|
|
static int load_roms (struct arcadiarom *rom)
|
|
{
|
|
TCHAR path[MAX_DPATH], path2[MAX_DPATH], path3[MAX_DPATH], *p;
|
|
int i, offset;
|
|
TCHAR *xpath;
|
|
|
|
if (rom->type == ARCADIA_BIOS)
|
|
xpath = currprefs.romextfile;
|
|
else
|
|
xpath = currprefs.cartfile;
|
|
|
|
_tcscpy (path3, xpath);
|
|
p = path3 + _tcslen (path3) - 1;
|
|
while (p > path3) {
|
|
if (p[0] == '\\' || p[0] == '/') {
|
|
*p = 0;
|
|
break;
|
|
}
|
|
p--;
|
|
}
|
|
if (p == path3)
|
|
*p = 0;
|
|
_tcscpy (path2, xpath);
|
|
|
|
offset = 0;
|
|
if (rom->type == ARCADIA_BIOS)
|
|
offset = bios_offset;
|
|
i = 0;
|
|
for (;;) {
|
|
_stprintf (path, L"%s%d", xpath, i + 1);
|
|
if (!load_rom8 (path, arbmemory + 2 * 65536 * i + offset, rom->extra)) {
|
|
if (i == 0)
|
|
write_log (L"Arcadia: %s rom load failed ('%s')\n", rom->type == ARCADIA_BIOS ? "bios" : "game", path);
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if (i == 0)
|
|
return 0;
|
|
write_log (L"Arcadia: %s rom %s loaded\n", rom->type == ARCADIA_BIOS ? "bios" : "game", xpath);
|
|
return 1;
|
|
}
|
|
|
|
static uae_u8 bswap (uae_u8 v,int b7,int b6,int b5,int b4,int b3,int b2,int b1,int b0)
|
|
{
|
|
uae_u8 b = 0;
|
|
|
|
b |= ((v >> b7) & 1) << 7;
|
|
b |= ((v >> b6) & 1) << 6;
|
|
b |= ((v >> b5) & 1) << 5;
|
|
b |= ((v >> b4) & 1) << 4;
|
|
b |= ((v >> b3) & 1) << 3;
|
|
b |= ((v >> b2) & 1) << 2;
|
|
b |= ((v >> b1) & 1) << 1;
|
|
b |= ((v >> b0) & 1) << 0;
|
|
return b;
|
|
}
|
|
|
|
static void decrypt_roms (struct arcadiarom *rom)
|
|
{
|
|
int i, start = 1, end = 0x20000;
|
|
|
|
if (rom->type == ARCADIA_BIOS) {
|
|
start += bios_offset;
|
|
end += bios_offset;
|
|
}
|
|
for (i = start; i < end; i += 2) {
|
|
arbmemory[i] = bswap (arbmemory[i],
|
|
rom->b7,rom->b6,rom->b5,rom->b4,rom->b3,rom->b2,rom->b1,rom->b0);
|
|
if (rom->extra == 2)
|
|
arbmemory[i - 1] = bswap (arbmemory[i - 1],7,6,5,4,3,2,1,0);
|
|
}
|
|
}
|
|
|
|
static uae_u32 REGPARAM2 arbb_lget (uaecptr addr)
|
|
{
|
|
uae_u32 *m;
|
|
|
|
addr -= arbb_start & arbb_mask;
|
|
addr &= arbb_mask;
|
|
m = (uae_u32 *)(arbbmemory + addr);
|
|
return do_get_mem_long (m);
|
|
}
|
|
static uae_u32 REGPARAM2 arbb_wget (uaecptr addr)
|
|
{
|
|
uae_u16 *m;
|
|
|
|
addr -= arbb_start & arbb_mask;
|
|
addr &= arbb_mask;
|
|
m = (uae_u16 *)(arbbmemory + addr);
|
|
return do_get_mem_word (m);
|
|
}
|
|
static uae_u32 REGPARAM2 arbb_bget (uaecptr addr)
|
|
{
|
|
addr -= arbb_start & arbb_mask;
|
|
addr &= arbb_mask;
|
|
return arbbmemory[addr];
|
|
}
|
|
|
|
static void REGPARAM2 arbb_lput (uaecptr addr, uae_u32 l)
|
|
{
|
|
}
|
|
|
|
static void REGPARAM2 arbb_wput (uaecptr addr, uae_u32 w)
|
|
{
|
|
}
|
|
|
|
static void REGPARAM2 arbb_bput (uaecptr addr, uae_u32 b)
|
|
{
|
|
}
|
|
|
|
static addrbank arcadia_boot_bank = {
|
|
arbb_lget, arbb_wget, arbb_bget,
|
|
arbb_lput, arbb_wput, arbb_bput,
|
|
default_xlate, default_check, NULL, L"Arcadia BIOS",
|
|
arbb_lget, arbb_wget, ABFLAG_ROM
|
|
};
|
|
|
|
static uae_u32 REGPARAM2 arb_lget (uaecptr addr)
|
|
{
|
|
uae_u32 *m;
|
|
|
|
addr -= arb_start & arb_mask;
|
|
addr &= arb_mask;
|
|
m = (uae_u32 *)(arbmemory + addr);
|
|
return do_get_mem_long (m);
|
|
}
|
|
static uae_u32 REGPARAM2 arb_wget (uaecptr addr)
|
|
{
|
|
uae_u16 *m;
|
|
|
|
addr -= arb_start & arb_mask;
|
|
addr &= arb_mask;
|
|
m = (uae_u16 *)(arbmemory + addr);
|
|
return do_get_mem_word (m);
|
|
}
|
|
static uae_u32 REGPARAM2 arb_bget (uaecptr addr)
|
|
{
|
|
addr -= arb_start & arb_mask;
|
|
addr &= arb_mask;
|
|
return arbmemory[addr];
|
|
}
|
|
static void REGPARAM2 arb_lput (uaecptr addr, uae_u32 l)
|
|
{
|
|
uae_u32 *m;
|
|
|
|
addr -= arb_start & arb_mask;
|
|
addr &= arb_mask;
|
|
if (addr >= nvram_offset) {
|
|
m = (uae_u32 *)(arbmemory + addr);
|
|
do_put_mem_long (m, l);
|
|
nvwrite++;
|
|
}
|
|
}
|
|
static void REGPARAM2 arb_wput (uaecptr addr, uae_u32 w)
|
|
{
|
|
uae_u16 *m;
|
|
|
|
addr -= arb_start & arb_mask;
|
|
addr &= arb_mask;
|
|
if (addr >= nvram_offset) {
|
|
m = (uae_u16 *)(arbmemory + addr);
|
|
do_put_mem_word (m, w);
|
|
nvwrite++;
|
|
if (addr == 0x1ffffe)
|
|
multigame(w);
|
|
}
|
|
}
|
|
static void REGPARAM2 arb_bput (uaecptr addr, uae_u32 b)
|
|
{
|
|
addr -= arb_start & arb_mask;
|
|
addr &= arb_mask;
|
|
if (addr >= nvram_offset) {
|
|
arbmemory[addr] = b;
|
|
nvwrite++;
|
|
}
|
|
}
|
|
|
|
static addrbank arcadia_rom_bank = {
|
|
arb_lget, arb_wget, arb_bget,
|
|
arb_lput, arb_wput, arb_bput,
|
|
default_xlate, default_check, NULL, L"Arcadia Game ROM",
|
|
arb_lget, arb_wget, ABFLAG_ROM
|
|
};
|
|
|
|
|
|
static void multigame(int v)
|
|
{
|
|
if (v != 0)
|
|
map_banks (&kickmem_bank, arb_start >> 16,
|
|
8, 0);
|
|
else
|
|
map_banks (&arcadia_rom_bank, arb_start >> 16,
|
|
allocated_arbmemory >> 16, 0);
|
|
}
|
|
|
|
int is_arcadia_rom (const TCHAR *path)
|
|
{
|
|
struct arcadiarom *rom;
|
|
|
|
rom = is_arcadia (path, 0);
|
|
if (!rom || rom->type == NO_ARCADIA_ROM)
|
|
return NO_ARCADIA_ROM;
|
|
if (rom->type == ARCADIA_BIOS) {
|
|
arcadia_bios = rom;
|
|
return ARCADIA_BIOS;
|
|
}
|
|
arcadia_game = rom;
|
|
return ARCADIA_GAME;
|
|
}
|
|
|
|
static void nvram_write (void)
|
|
{
|
|
struct zfile *f = zfile_fopen (currprefs.flashfile, L"rb+", ZFD_NORMAL);
|
|
if (!f) {
|
|
f = zfile_fopen (currprefs.flashfile, L"wb", 0);
|
|
if (!f)
|
|
return;
|
|
}
|
|
zfile_fwrite (arbmemory + nvram_offset, NVRAM_SIZE, 1, f);
|
|
zfile_fclose (f);
|
|
}
|
|
|
|
static void nvram_read (void)
|
|
{
|
|
struct zfile *f;
|
|
|
|
f = zfile_fopen (currprefs.flashfile, L"rb", ZFD_NORMAL);
|
|
memset (arbmemory + nvram_offset, 0, NVRAM_SIZE);
|
|
if (!f)
|
|
return;
|
|
zfile_fread (arbmemory + nvram_offset, NVRAM_SIZE, 1, f);
|
|
zfile_fclose (f);
|
|
}
|
|
|
|
void arcadia_unmap (void)
|
|
{
|
|
xfree (arbmemory);
|
|
arbmemory = NULL;
|
|
arcadia_bios = NULL;
|
|
arcadia_game = NULL;
|
|
}
|
|
|
|
int arcadia_map_banks (void)
|
|
{
|
|
if (!arcadia_bios)
|
|
return 0;
|
|
arbmemory = (uae_u8*)xmalloc (allocated_arbmemory);
|
|
arbbmemory = arbmemory + bios_offset;
|
|
memset (arbmemory, 0, allocated_arbmemory);
|
|
if (!load_roms (arcadia_bios)) {
|
|
arcadia_unmap ();
|
|
return 0;
|
|
}
|
|
if (arcadia_game)
|
|
load_roms (arcadia_game);
|
|
decrypt_roms (arcadia_bios);
|
|
if (arcadia_game)
|
|
decrypt_roms (arcadia_game);
|
|
nvram_read ();
|
|
multigame(0);
|
|
map_banks (&arcadia_boot_bank, 0xf0,
|
|
8, 0);
|
|
return 1;
|
|
}
|
|
|
|
void arcadia_vsync (void)
|
|
{
|
|
static int cnt;
|
|
|
|
cnt--;
|
|
if (cnt > 0)
|
|
return;
|
|
cnt = 50;
|
|
if (!nvwrite)
|
|
return;
|
|
nvram_write ();
|
|
nvwrite = 0;
|
|
}
|
|
|
|
uae_u8 arcadia_parport (int port, uae_u8 pra, uae_u8 dra)
|
|
{
|
|
uae_u8 v;
|
|
|
|
v = (pra & dra) | (dra ^ 0xff);
|
|
if (port) {
|
|
if (dra & 1)
|
|
arcadia_coin[0] = arcadia_coin[1] = 0;
|
|
return 0;
|
|
}
|
|
v = 0;
|
|
v |= (arcadia_flag & 1) ? 0 : 2;
|
|
v |= (arcadia_flag & 2) ? 0 : 4;
|
|
v |= (arcadia_flag & 4) ? 0 : 8;
|
|
v |= (arcadia_coin[0] & 3) << 4;
|
|
v |= (arcadia_coin[1] & 3) << 6;
|
|
return v;
|
|
}
|
|
|
|
struct romdata *scan_arcadia_rom (TCHAR *path, int cnt)
|
|
{
|
|
struct romdata *rd = 0;
|
|
struct romlist **arc_rl;
|
|
struct arcadiarom *arcadia_rom;
|
|
int i;
|
|
|
|
arcadia_rom = is_arcadia (path, cnt);
|
|
if (arcadia_rom) {
|
|
arc_rl = getarcadiaroms();
|
|
for (i = 0; arc_rl[i]; i++) {
|
|
if (arc_rl[i]->rd->id == arcadia_rom->romid) {
|
|
rd = arc_rl[i]->rd;
|
|
_tcscat (path, L"/");
|
|
_tcscat (path, arcadia_rom->rom);
|
|
break;
|
|
}
|
|
}
|
|
xfree (arc_rl);
|
|
}
|
|
return rd;
|
|
}
|