mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-04 23:07:46 -04:00
Finish migrating to new mem handling. Make carthw db external.
Still need to fix asm and protection emulation. git-svn-id: file:///home/notaz/opt/svn/PicoDrive@769 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
af37bca858
commit
45f2f245f5
30 changed files with 948 additions and 1027 deletions
|
@ -75,7 +75,7 @@
|
|||
* and m68k_read_pcrelative_xx() for PC-relative addressing.
|
||||
* If off, all read requests from the CPU will be redirected to m68k_read_xx()
|
||||
*/
|
||||
#define M68K_SEPARATE_READS OPT_ON
|
||||
#define M68K_SEPARATE_READS OPT_OFF
|
||||
|
||||
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
|
||||
* predecrement destination EA mode instead of m68k_write_32().
|
||||
|
|
|
@ -2011,8 +2011,8 @@ void m68ki_exception_interrupt(uint int_level)
|
|||
FLAG_INT_MASK = int_level<<8;
|
||||
|
||||
/* Get the new PC */
|
||||
//new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);
|
||||
new_pc = m68k_read_immediate_32((vector<<2) + REG_VBR); // notaz hack
|
||||
new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);
|
||||
//new_pc = m68k_read_immediate_32((vector<<2) + REG_VBR); // notaz hack
|
||||
|
||||
/* If vector is uninitialized, call the uninitialized interrupt vector */
|
||||
if(new_pc == 0)
|
||||
|
|
|
@ -144,6 +144,10 @@ static int PicoAreaScan(int is_write, unsigned int ver, void *PmovFile)
|
|||
SCAN_VAR(Pico.m ,"misc")
|
||||
SCAN_VAR(Pico.video,"video")
|
||||
|
||||
// no longer keeping eeprom data in sram_reg
|
||||
if (!is_write && (Pico.m.sram_reg & 4))
|
||||
Pico.m.sram_reg = SRR_MAPPED;
|
||||
|
||||
if (is_write)
|
||||
z80_pack(cpu_z80);
|
||||
ret = SCAN_VAR(cpu_z80,"cpu_z80")
|
||||
|
|
395
pico/cart.c
395
pico/cart.c
|
@ -15,7 +15,8 @@
|
|||
|
||||
static const char *rom_exts[] = { "bin", "gen", "smd", "iso", "sms", "gg", "sg" };
|
||||
|
||||
void (*PicoCartUnloadHook)(void) = NULL;
|
||||
void (*PicoCartUnloadHook)(void);
|
||||
void (*PicoCartMemSetup)(void);
|
||||
|
||||
void (*PicoCartLoadProgressCB)(int percent) = NULL;
|
||||
void (*PicoCDLoadProgressCB)(const char *fname, int percent) = NULL; // handled in Pico/cd/cd_file.c
|
||||
|
@ -565,7 +566,7 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize)
|
|||
|
||||
PicoAHW &= PAHW_MCD|PAHW_SMS;
|
||||
|
||||
PicoMemResetHooks();
|
||||
PicoCartMemSetup = NULL;
|
||||
PicoDmaHook = NULL;
|
||||
PicoResetHook = NULL;
|
||||
PicoLineHook = NULL;
|
||||
|
@ -586,6 +587,9 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize)
|
|||
case PAHW_SMS: PicoMemSetupMS(); break;
|
||||
}
|
||||
|
||||
if (PicoCartMemSetup != NULL)
|
||||
PicoCartMemSetup();
|
||||
|
||||
if (PicoAHW & PAHW_SMS)
|
||||
PicoPowerMS();
|
||||
else
|
||||
|
@ -611,178 +615,311 @@ void PicoCartUnload(void)
|
|||
static int rom_strcmp(int rom_offset, const char *s1)
|
||||
{
|
||||
int i, len = strlen(s1);
|
||||
const char *s_rom = (const char *)Pico.rom + rom_offset;
|
||||
const char *s_rom = (const char *)Pico.rom;
|
||||
for (i = 0; i < len; i++)
|
||||
if (s1[i] != s_rom[i^1])
|
||||
if (s1[i] != s_rom[(i + rom_offset) ^ 1])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int name_cmp(const char *name)
|
||||
{
|
||||
return rom_strcmp(0x150, name);
|
||||
}
|
||||
|
||||
static unsigned int rom_read32(int addr)
|
||||
{
|
||||
unsigned short *m = (unsigned short *)(Pico.rom + addr);
|
||||
return (m[0] << 16) | m[1];
|
||||
}
|
||||
|
||||
static char *sskip(char *s)
|
||||
{
|
||||
while (*s && isspace_(*s))
|
||||
s++;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void rstrip(char *s)
|
||||
{
|
||||
char *p;
|
||||
for (p = s + strlen(s) - 1; p >= s; p--)
|
||||
if (isspace_(*p))
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
static int is_expr(const char *expr, char **pr)
|
||||
{
|
||||
int len = strlen(expr);
|
||||
char *p = *pr;
|
||||
|
||||
if (strncmp(expr, p, len) != 0)
|
||||
return 0;
|
||||
p = sskip(p + len);
|
||||
if (*p != '=')
|
||||
return 0; // wrong or malformed
|
||||
|
||||
*pr = sskip(p + 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void parse_carthw(int *fill_sram)
|
||||
{
|
||||
int line = 0, any_checks_passed = 0, skip_sect = 0;
|
||||
char buff[256], *p, *r;
|
||||
FILE *f;
|
||||
|
||||
f = fopen("carthw.cfg", "r");
|
||||
if (f == NULL) {
|
||||
elprintf(EL_STATUS, "couldn't open carthw.txt!");
|
||||
return;
|
||||
}
|
||||
|
||||
while ((p = fgets(buff, sizeof(buff), f)))
|
||||
{
|
||||
line++;
|
||||
p = sskip(p);
|
||||
if (*p == 0 || *p == '#')
|
||||
continue;
|
||||
|
||||
if (*p == '[') {
|
||||
any_checks_passed = 0;
|
||||
skip_sect = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skip_sect)
|
||||
continue;
|
||||
|
||||
/* look for checks */
|
||||
if (is_expr("check_str", &p))
|
||||
{
|
||||
int offs;
|
||||
offs = strtoul(p, &r, 0);
|
||||
if (offs < 0 || offs > Pico.romsize) {
|
||||
elprintf(EL_STATUS, "carthw:%d: check_str offs out of range: %d\n", line, offs);
|
||||
goto bad;
|
||||
}
|
||||
p = sskip(r);
|
||||
if (*p != ',')
|
||||
goto bad;
|
||||
p = sskip(p + 1);
|
||||
if (*p != '"')
|
||||
goto bad;
|
||||
p++;
|
||||
r = strchr(p, '"');
|
||||
if (r == NULL)
|
||||
goto bad;
|
||||
*r = 0;
|
||||
|
||||
if (rom_strcmp(offs, p) == 0)
|
||||
any_checks_passed = 1;
|
||||
else
|
||||
skip_sect = 1;
|
||||
continue;
|
||||
}
|
||||
else if (is_expr("check_size_gt", &p))
|
||||
{
|
||||
int size;
|
||||
size = strtoul(p, &r, 0);
|
||||
if (r == p || size < 0)
|
||||
goto bad;
|
||||
|
||||
if (Pico.romsize > size)
|
||||
any_checks_passed = 1;
|
||||
else
|
||||
skip_sect = 1;
|
||||
continue;
|
||||
}
|
||||
else if (is_expr("check_csum", &p))
|
||||
{
|
||||
int csum;
|
||||
csum = strtoul(p, &r, 0);
|
||||
if (r == p || (csum & 0xffff0000))
|
||||
goto bad;
|
||||
|
||||
if (csum == (rom_read32(0x18c) & 0xffff))
|
||||
any_checks_passed = 1;
|
||||
else
|
||||
skip_sect = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* now time for actions */
|
||||
if (is_expr("hw", &p)) {
|
||||
if (!any_checks_passed)
|
||||
goto no_checks;
|
||||
rstrip(p);
|
||||
|
||||
if (strcmp(p, "svp") == 0)
|
||||
PicoSVPStartup();
|
||||
else if (strcmp(p, "pico") == 0)
|
||||
PicoInitPico();
|
||||
else if (strcmp(p, "x_in_1_mapper") == 0)
|
||||
carthw_Xin1_startup();
|
||||
else if (strcmp(p, "realtec_mapper") == 0)
|
||||
carthw_realtec_startup();
|
||||
else if (strcmp(p, "radica_mapper") == 0)
|
||||
carthw_radica_startup();
|
||||
else {
|
||||
elprintf(EL_STATUS, "carthw:%d: unsupported mapper: %s", line, p);
|
||||
skip_sect = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (is_expr("sram_range", &p)) {
|
||||
int start, end;
|
||||
|
||||
if (!any_checks_passed)
|
||||
goto no_checks;
|
||||
rstrip(p);
|
||||
|
||||
start = strtoul(p, &r, 0);
|
||||
if (r == p)
|
||||
goto bad;
|
||||
p = sskip(r);
|
||||
if (*p != ',')
|
||||
goto bad;
|
||||
p = sskip(p + 1);
|
||||
end = strtoul(p, &r, 0);
|
||||
if (r == p)
|
||||
goto bad;
|
||||
if (((start | end) & 0xff000000) || start > end) {
|
||||
elprintf(EL_STATUS, "carthw:%d: bad sram_range: %08x - %08x", line, start, end);
|
||||
goto bad_nomsg;
|
||||
}
|
||||
SRam.start = start;
|
||||
SRam.end = end;
|
||||
continue;
|
||||
}
|
||||
else if (is_expr("prop", &p)) {
|
||||
if (!any_checks_passed)
|
||||
goto no_checks;
|
||||
rstrip(p);
|
||||
|
||||
if (strcmp(p, "no_sram") == 0)
|
||||
SRam.flags &= ~SRF_ENABLED;
|
||||
else if (strcmp(p, "no_eeprom") == 0)
|
||||
SRam.flags &= ~SRF_EEPROM;
|
||||
else if (strcmp(p, "filled_sram") == 0)
|
||||
*fill_sram = 1;
|
||||
else {
|
||||
elprintf(EL_STATUS, "carthw:%d: unsupported prop: %s", line, p);
|
||||
goto bad_nomsg;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (is_expr("eeprom_type", &p)) {
|
||||
int type;
|
||||
if (!any_checks_passed)
|
||||
goto no_checks;
|
||||
rstrip(p);
|
||||
|
||||
type = strtoul(p, &r, 0);
|
||||
if (r == p || type < 0)
|
||||
goto bad;
|
||||
SRam.eeprom_type = type;
|
||||
SRam.flags |= SRF_EEPROM;
|
||||
continue;
|
||||
}
|
||||
else if (is_expr("eeprom_lines", &p)) {
|
||||
int scl, sda_in, sda_out;
|
||||
if (!any_checks_passed)
|
||||
goto no_checks;
|
||||
rstrip(p);
|
||||
|
||||
scl = strtoul(p, &r, 0);
|
||||
if (r == p || scl < 0 || scl > 15)
|
||||
goto bad;
|
||||
p = sskip(r);
|
||||
if (*p++ != ',')
|
||||
goto bad;
|
||||
sda_in = strtoul(p, &r, 0);
|
||||
if (r == p || sda_in < 0 || sda_in > 15)
|
||||
goto bad;
|
||||
p = sskip(r);
|
||||
if (*p++ != ',')
|
||||
goto bad;
|
||||
sda_out = strtoul(p, &r, 0);
|
||||
if (r == p || sda_out < 0 || sda_out > 15)
|
||||
goto bad;
|
||||
|
||||
SRam.eeprom_bit_cl = scl;
|
||||
SRam.eeprom_bit_in = sda_in;
|
||||
SRam.eeprom_bit_out= sda_out;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
bad:
|
||||
elprintf(EL_STATUS, "carthw:%d: unrecognized expression: %s", line, buff);
|
||||
bad_nomsg:
|
||||
skip_sect = 1;
|
||||
continue;
|
||||
|
||||
no_checks:
|
||||
elprintf(EL_STATUS, "carthw:%d: command without any checks before it: %s", line, buff);
|
||||
skip_sect = 1;
|
||||
continue;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
/*
|
||||
* various cart-specific things, which can't be handled by generic code
|
||||
* (maybe I should start using CRC for this stuff?)
|
||||
*/
|
||||
static void PicoCartDetect(void)
|
||||
{
|
||||
int sram_size = 0, csum;
|
||||
Pico.m.sram_status = 0;
|
||||
int fill_sram = 0, csum;
|
||||
|
||||
csum = rom_read32(0x18c) & 0xffff;
|
||||
|
||||
memset(&SRam, 0, sizeof(SRam));
|
||||
if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A')
|
||||
{
|
||||
SRam.start = rom_read32(0x1B4) & ~0xff000001; // align
|
||||
SRam.end = (rom_read32(0x1B8) & ~0xff000000) | 1;
|
||||
if (Pico.rom[0x1B2] & 0x40)
|
||||
{
|
||||
// EEPROM
|
||||
SRam.start = rom_read32(0x1B4) & ~1; // zero address is used for clock by some games
|
||||
SRam.end = rom_read32(0x1B8);
|
||||
sram_size = 0x2000;
|
||||
Pico.m.sram_status |= SRS_EEPROM;
|
||||
} else {
|
||||
// normal SRAM
|
||||
SRam.start = rom_read32(0x1B4) & ~0xff;
|
||||
SRam.end = rom_read32(0x1B8) | 1;
|
||||
sram_size = SRam.end - SRam.start + 1;
|
||||
}
|
||||
SRam.start &= ~0xff000000;
|
||||
SRam.end &= ~0xff000000;
|
||||
Pico.m.sram_status |= SRS_DETECTED;
|
||||
SRam.flags |= SRF_EEPROM;
|
||||
SRam.flags |= SRF_ENABLED;
|
||||
}
|
||||
if (sram_size <= 0)
|
||||
if (SRam.end == 0 || SRam.start > SRam.end)
|
||||
{
|
||||
// some games may have bad headers, like S&K and Sonic3
|
||||
// note: majority games use 0x200000 as starting address, but there are some which
|
||||
// use something else (0x300000 by HardBall '95). Luckily they have good headers.
|
||||
SRam.start = 0x200000;
|
||||
SRam.end = 0x203FFF;
|
||||
sram_size = 0x004000;
|
||||
SRam.flags |= SRF_ENABLED;
|
||||
}
|
||||
|
||||
// this game actually doesn't have SRAM, but some weird protection
|
||||
if (rom_strcmp(0x120, "PUGGSY") == 0)
|
||||
{
|
||||
SRam.start = SRam.end = sram_size = 0;
|
||||
}
|
||||
|
||||
if (sram_size)
|
||||
{
|
||||
SRam.data = (unsigned char *) calloc(sram_size, 1);
|
||||
if (SRam.data == NULL) return;
|
||||
}
|
||||
SRam.changed = 0;
|
||||
|
||||
// set EEPROM defaults, in case it gets detected
|
||||
SRam.eeprom_type = 0; // 7bit (24C01)
|
||||
SRam.eeprom_abits = 3; // eeprom access must be odd addr for: bit0 ~ cl, bit1 ~ in
|
||||
SRam.eeprom_bit_cl = 1;
|
||||
SRam.eeprom_bit_in = 0;
|
||||
SRam.eeprom_bit_out= 0;
|
||||
|
||||
// some known EEPROM data (thanks to EkeEke)
|
||||
if (name_cmp("COLLEGE SLAM") == 0 ||
|
||||
name_cmp("FRANK THOMAS BIGHURT BASEBAL") == 0)
|
||||
parse_carthw(&fill_sram);
|
||||
|
||||
if (SRam.flags & SRF_ENABLED)
|
||||
{
|
||||
SRam.eeprom_type = 3;
|
||||
SRam.eeprom_abits = 2;
|
||||
SRam.eeprom_bit_cl = 0;
|
||||
}
|
||||
else if (name_cmp("NBA JAM TOURNAMENT EDITION") == 0 ||
|
||||
name_cmp("NFL QUARTERBACK CLUB") == 0)
|
||||
{
|
||||
SRam.eeprom_type = 2;
|
||||
SRam.eeprom_abits = 2;
|
||||
SRam.eeprom_bit_cl = 0;
|
||||
}
|
||||
else if (name_cmp("NBA JAM") == 0)
|
||||
{
|
||||
SRam.eeprom_type = 2;
|
||||
SRam.eeprom_bit_out = 1;
|
||||
SRam.eeprom_abits = 0;
|
||||
}
|
||||
else if (name_cmp("NHLPA HOCKEY '93") == 0 ||
|
||||
name_cmp("NHLPA Hockey '93") == 0 ||
|
||||
name_cmp("RINGS OF POWER") == 0)
|
||||
{
|
||||
SRam.start = SRam.end = 0x200000;
|
||||
Pico.m.sram_status = SRS_DETECTED|SRS_EEPROM;
|
||||
SRam.eeprom_abits = 0;
|
||||
SRam.eeprom_bit_cl = 6;
|
||||
SRam.eeprom_bit_in = 7;
|
||||
SRam.eeprom_bit_out= 7;
|
||||
}
|
||||
else if ( name_cmp("MICRO MACHINES II") == 0 ||
|
||||
(name_cmp(" ") == 0 && // Micro Machines {Turbo Tournament '96, Military - It's a Blast!}
|
||||
(csum == 0x165e || csum == 0x168b || csum == 0xCEE0 || csum == 0x2C41)))
|
||||
{
|
||||
SRam.start = 0x300000;
|
||||
SRam.end = 0x380001;
|
||||
Pico.m.sram_status = SRS_DETECTED|SRS_EEPROM;
|
||||
SRam.eeprom_type = 2;
|
||||
SRam.eeprom_abits = 0;
|
||||
SRam.eeprom_bit_cl = 1;
|
||||
SRam.eeprom_bit_in = 0;
|
||||
SRam.eeprom_bit_out= 7;
|
||||
if (SRam.flags & SRF_EEPROM)
|
||||
SRam.size = 0x2000;
|
||||
else
|
||||
SRam.size = SRam.end - SRam.start + 1;
|
||||
|
||||
SRam.data = calloc(SRam.size, 1);
|
||||
if (SRam.data == NULL)
|
||||
SRam.flags &= ~SRF_ENABLED;
|
||||
|
||||
if (SRam.eeprom_type == 1) // 1 == 0 in PD EEPROM code
|
||||
SRam.eeprom_type = 0;
|
||||
}
|
||||
|
||||
// SVP detection
|
||||
else if (name_cmp("Virtua Racing") == 0 ||
|
||||
name_cmp("VIRTUA RACING") == 0)
|
||||
if ((SRam.flags & SRF_ENABLED) && fill_sram)
|
||||
{
|
||||
PicoSVPStartup();
|
||||
}
|
||||
|
||||
// Pico
|
||||
else if (rom_strcmp(0x100, "SEGA PICO") == 0 ||
|
||||
rom_strcmp(0x100, "IMA IKUNOUJYUKU") == 0) // what is that supposed to mean?
|
||||
{
|
||||
PicoInitPico();
|
||||
}
|
||||
|
||||
// Detect 12-in-1 mapper
|
||||
else if ((name_cmp("ROBOCOP 3") == 0 && Pico.romsize == 0x200000) ||
|
||||
(rom_strcmp(0x160, "FLICKY") == 0 && Pico.romsize >= 0x200000) ||
|
||||
(name_cmp(" SHOVE IT!") == 0 && Pico.romsize >= 0x200000) ||
|
||||
(name_cmp("MS PACMAN") == 0 && Pico.romsize >= 0x200000) || // bad dump?
|
||||
(name_cmp("ALIEN 3") == 0 && Pico.romsize == 0x200000))
|
||||
{
|
||||
carthw_12in1_startup();
|
||||
}
|
||||
|
||||
// Realtec mapper
|
||||
else if (Pico.romsize == 512*1024 && (
|
||||
rom_strcmp(0x94, "THE EARTH DEFEND") == 0 ||
|
||||
rom_strcmp(0xfe, "WISEGAME 11-03-1993") == 0 || // Funny World
|
||||
rom_strcmp(0x95, "MALLET LEGEND ") == 0)) // Whac-A-Critter
|
||||
{
|
||||
carthw_realtec_startup();
|
||||
}
|
||||
|
||||
// Radica mapper
|
||||
else if (name_cmp("KID CHAMELEON") == 0 && Pico.romsize > 0x100000)
|
||||
{
|
||||
carthw_radica_startup();
|
||||
}
|
||||
|
||||
// Some games malfunction if SRAM is not filled with 0xff
|
||||
if (name_cmp("DINO DINI'S SOCCER") == 0 ||
|
||||
name_cmp("MICRO MACHINES II") == 0)
|
||||
{
|
||||
memset(SRam.data, 0xff, sram_size);
|
||||
elprintf(EL_STATUS, "SRAM fill");
|
||||
memset(SRam.data, 0xff, SRam.size);
|
||||
}
|
||||
|
||||
// Unusual region 'code'
|
||||
if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0)
|
||||
*(int *) (Pico.rom+0x1f0) = 0x20204520;
|
||||
*(int *) (Pico.rom + 0x1f0) = 0x20204520;
|
||||
}
|
||||
|
||||
|
|
180
pico/carthw.cfg
Normal file
180
pico/carthw.cfg
Normal file
|
@ -0,0 +1,180 @@
|
|||
# hardware (hw = ...):
|
||||
# svp - Sega Virtua Processor
|
||||
# pico - Sega Pico (not really cart hw, but convenient to support here)
|
||||
#
|
||||
# cartridge properties (prop = ...):
|
||||
# no_sram - don't emulate sram/EEPROM even if ROM headers tell it's there
|
||||
# no_eeprom - save storage is not EEPROM, even if ROM headers tell it is
|
||||
# filled_sram - save storage needs to be initialized with FFh instead of 00h
|
||||
#
|
||||
# mappers (hw = ...):
|
||||
# x_in_1_mapper - used in many *-in-1 pirate carts
|
||||
# realtec_mapper
|
||||
# radica_mapper - similar to x_in_1_mapper
|
||||
#
|
||||
# save storage memory range (inclusive, overrides ROM header):
|
||||
# sram_range = <start, end>
|
||||
#
|
||||
# EEPROM:
|
||||
# eeprom_type = <1|2|3> - enable EEPROM, use type X (7bit, 2 addr words, 3 addr words).
|
||||
# See EkeEke's gen_eeprom.pdf "mode" descriptions for 24Cxx EEPROMs.
|
||||
# eeprom_lines = <SCL,SDA_IN,SDA_OUT>
|
||||
# - select data bus pins that are connected to EEPROM
|
||||
# SCL, SDA_IN and SDA_OUT pins (0-15 for D0-D15).
|
||||
|
||||
[Virtua Racing - SVP]
|
||||
check_str = 0x150, "Virtua Racing"
|
||||
hw = svp
|
||||
|
||||
[Virtua Racing - SVP]
|
||||
check_str = 0x150, "VIRTUA RACING"
|
||||
hw = svp
|
||||
|
||||
[Pico]
|
||||
check_str = 0x100, "SEGA PICO"
|
||||
hw = pico
|
||||
|
||||
[Pico]
|
||||
check_str = 0x100, "IMA IKUNOUJYUKU"
|
||||
hw = pico
|
||||
|
||||
# sram emulation triggers some protection for this one
|
||||
[Puggsy]
|
||||
check_str = 0x120, "PUGGSY"
|
||||
prop = no_sram
|
||||
|
||||
# game has problems if it's save RAM is not initialized with FFh:
|
||||
[Dino Dini's Soccer]
|
||||
check_str = 0x150, "DINO DINI'S SOCCER"
|
||||
prop = filled_sram
|
||||
|
||||
[Micro Machines 2 - Turbo Tournament]
|
||||
check_str = 0x150, "MICRO MACHINES II"
|
||||
prop = filled_sram
|
||||
|
||||
# detect *_in_1 based on first game and if it's larger than it should be,
|
||||
# as some dumps look like to be incomplete.
|
||||
# This will also pick overdumps, but those should still work with the mapper applied.
|
||||
[12-in-1 (Unl)]
|
||||
check_str = 0x120, "FLICKY"
|
||||
check_size_gt = 0x020000
|
||||
hw = x_in_1_mapper
|
||||
|
||||
[4-in-1]
|
||||
check_str = 0x150, "ROBOCOP 3"
|
||||
check_size_gt = 0x080000
|
||||
hw = x_in_1_mapper
|
||||
|
||||
[4-in-1 a1]
|
||||
check_str = 0x150, "ALIEN 3"
|
||||
check_size_gt = 0x080000
|
||||
hw = x_in_1_mapper
|
||||
|
||||
[Super 15-in-1]
|
||||
check_str = 0x150, " SHOVE IT!"
|
||||
check_size_gt = 0x020000
|
||||
hw = x_in_1_mapper
|
||||
|
||||
[Super 19-in-1]
|
||||
check_str = 0x150, "MS PACMAN"
|
||||
check_size_gt = 0x020000
|
||||
hw = x_in_1_mapper
|
||||
|
||||
# radica
|
||||
[radica_v1]
|
||||
check_str = 0x150, "KID CHAMELEON"
|
||||
check_size_gt = 0x100000
|
||||
hw = radica_mapper
|
||||
|
||||
# realtec
|
||||
[Earth Defend, The (Unl)]
|
||||
check_str = 0x94, "THE EARTH DEFEND"
|
||||
hw = realtec_mapper
|
||||
|
||||
[Funny World & Balloon Boy (Unl)]
|
||||
check_str = 0xfe, "WISEGAME 11-03-1993"
|
||||
hw = realtec_mapper
|
||||
|
||||
[Whac-A-Critter (Unl)]
|
||||
check_str = 0x95, "MALLET LEGEND"
|
||||
hw = realtec_mapper
|
||||
|
||||
# EEPROM games - thanks to EkeEke for most of this info
|
||||
[College Slam]
|
||||
check_str = 0x150, "COLLEGE SLAM"
|
||||
eeprom_type = 3
|
||||
eeprom_lines = 8,0,0
|
||||
|
||||
[Frank Thomas Big Hurt Baseball]
|
||||
check_str = 0x150, "FRANK THOMAS BIGHURT BASEBAL"
|
||||
eeprom_type = 3
|
||||
eeprom_lines = 8,0,0
|
||||
|
||||
[MICRO MACHINES II]
|
||||
check_str = 0x150, "MICRO MACHINES II"
|
||||
sram_range = 0x300000,0x380001
|
||||
eeprom_type = 2
|
||||
eeprom_lines = 9,8,7
|
||||
|
||||
[Micro Machines - Turbo Tournament '96]
|
||||
check_str = 0x150, " "
|
||||
check_csum = 0x165e
|
||||
sram_range = 0x300000,0x380001
|
||||
eeprom_type = 2
|
||||
eeprom_lines = 9,8,7
|
||||
|
||||
[Micro Machines - Turbo Tournament '96]
|
||||
check_str = 0x150, " "
|
||||
check_csum = 0x2c41
|
||||
sram_range = 0x300000,0x380001
|
||||
eeprom_type = 2
|
||||
eeprom_lines = 9,8,7
|
||||
|
||||
[Micro Machines Military]
|
||||
check_str = 0x150, " "
|
||||
check_csum = 0x168b
|
||||
sram_range = 0x300000,0x380001
|
||||
eeprom_type = 2
|
||||
eeprom_lines = 9,8,7
|
||||
|
||||
[Micro Machines Military]
|
||||
check_str = 0x150, " "
|
||||
check_csum = 0xcee0
|
||||
sram_range = 0x300000,0x380001
|
||||
eeprom_type = 2
|
||||
eeprom_lines = 9,8,7
|
||||
|
||||
[NBA Jam]
|
||||
check_str = 0x150, "NBA JAM "
|
||||
eeprom_type = 2
|
||||
eeprom_lines = 1,0,1
|
||||
|
||||
[NBA Jam Tournament Edition]
|
||||
check_str = 0x150, "NBA JAM TOURNAMENT EDITION"
|
||||
sram_range = 0x200000,0x200001
|
||||
eeprom_type = 2
|
||||
eeprom_lines = 8,0,0
|
||||
|
||||
[NFL Quarterback Club]
|
||||
check_str = 0x150, "NFL QUARTERBACK CLUB"
|
||||
eeprom_type = 2
|
||||
eeprom_lines = 8,0,0
|
||||
|
||||
[NHLPA Hockey '93]
|
||||
check_str = 0x150, "NHLPA Hockey '93"
|
||||
sram_range = 0x200000,0x200001
|
||||
eeprom_type = 1
|
||||
eeprom_lines = 6,7,7
|
||||
|
||||
[NHLPA Hockey '93]
|
||||
check_str = 0x150, "NHLPA HOCKEY '93"
|
||||
sram_range = 0x200000,0x200001
|
||||
eeprom_type = 1
|
||||
eeprom_lines = 6,7,7
|
||||
|
||||
[Rings of Power]
|
||||
check_str = 0x150, "RINGS OF POWER"
|
||||
sram_range = 0x200000,0x200001
|
||||
eeprom_type = 1
|
||||
eeprom_lines = 6,7,7
|
||||
|
|
@ -1,86 +1,79 @@
|
|||
/*
|
||||
* Support for a few cart mappers.
|
||||
*
|
||||
* (c) Copyright 2008, Grazvydas "notaz" Ignotas
|
||||
* (c) Copyright 2008-2009, Grazvydas "notaz" Ignotas
|
||||
* Free for non-commercial use.
|
||||
*
|
||||
*
|
||||
* I should better do some pointer stuff here. But as none of these bankswitch
|
||||
* while the game runs, memcpy will suffice.
|
||||
*/
|
||||
|
||||
#include "../pico_int.h"
|
||||
#include "../memory.h"
|
||||
|
||||
|
||||
/* 12-in-1 and 4-in-1. Assuming >= 2MB ROMs here. */
|
||||
static unsigned int carthw_12in1_baddr = 0;
|
||||
/* Common *-in-1 pirate mapper.
|
||||
* Switches banks based on addr lines when /TIME is set.
|
||||
* TODO: verify
|
||||
*/
|
||||
static unsigned int carthw_Xin1_baddr = 0;
|
||||
|
||||
static carthw_state_chunk carthw_12in1_state[] =
|
||||
{
|
||||
{ CHUNK_CARTHW, sizeof(carthw_12in1_baddr), &carthw_12in1_baddr },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static unsigned int carthw_12in1_read16(unsigned int a, int realsize)
|
||||
{
|
||||
// ??
|
||||
elprintf(EL_UIO, "12-in-1: read [%06x] @ %06x", a, SekPc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void carthw_12in1_write8(unsigned int a, unsigned int d, int realsize)
|
||||
static void carthw_Xin1_do(u32 a, int mask, int shift)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (a < 0xA13000 || a >= 0xA13040) {
|
||||
/* 4-in-1 has Real Deal Boxing, which uses serial eeprom,
|
||||
* but I really doubt that pirate cart had it */
|
||||
if (a != 0x200001)
|
||||
elprintf(EL_ANOMALY, "12-in-1: unexpected write [%06x] %02x @ %06x", a, d, SekPc);
|
||||
return;
|
||||
}
|
||||
|
||||
carthw_12in1_baddr = a;
|
||||
a &= 0x3f; a <<= 16;
|
||||
carthw_Xin1_baddr = a;
|
||||
a &= mask;
|
||||
a <<= shift;
|
||||
len = Pico.romsize - a;
|
||||
if (len <= 0) {
|
||||
elprintf(EL_ANOMALY|EL_STATUS, "12-in-1: missing bank @ %06x", a);
|
||||
elprintf(EL_ANOMALY|EL_STATUS, "X-in-1: missing bank @ %06x", a);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(Pico.rom, Pico.rom + Pico.romsize + a, len);
|
||||
len = (len + M68K_BANK_MASK) & ~M68K_BANK_MASK;
|
||||
cpu68k_map_set(m68k_read8_map, 0x000000, len - 1, Pico.rom + a, 0);
|
||||
cpu68k_map_set(m68k_read16_map, 0x000000, len - 1, Pico.rom + a, 0);
|
||||
}
|
||||
|
||||
static void carthw_12in1_reset(void)
|
||||
static carthw_state_chunk carthw_Xin1_state[] =
|
||||
{
|
||||
carthw_12in1_write8(0xA13000, 0, 0);
|
||||
}
|
||||
{ CHUNK_CARTHW, sizeof(carthw_Xin1_baddr), &carthw_Xin1_baddr },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static void carthw_12in1_statef(void)
|
||||
// TODO: test a0, reads, w16
|
||||
static void carthw_Xin1_write8(u32 a, u32 d)
|
||||
{
|
||||
carthw_12in1_write8(carthw_12in1_baddr, 0, 0);
|
||||
}
|
||||
|
||||
void carthw_12in1_startup(void)
|
||||
{
|
||||
void *tmp;
|
||||
|
||||
elprintf(EL_STATUS, "12-in-1 mapper detected");
|
||||
|
||||
tmp = realloc(Pico.rom, Pico.romsize * 2);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
elprintf(EL_STATUS, "OOM");
|
||||
if ((a & 0xffff00) != 0xa13000) {
|
||||
PicoWrite8_io(a, d);
|
||||
return;
|
||||
}
|
||||
Pico.rom = tmp;
|
||||
memcpy(Pico.rom + Pico.romsize, Pico.rom, Pico.romsize);
|
||||
|
||||
PicoRead16Hook = carthw_12in1_read16;
|
||||
PicoWrite8Hook = carthw_12in1_write8;
|
||||
PicoResetHook = carthw_12in1_reset;
|
||||
PicoLoadStateHook = carthw_12in1_statef;
|
||||
carthw_chunks = carthw_12in1_state;
|
||||
carthw_Xin1_do(a, 0x3f, 16);
|
||||
}
|
||||
|
||||
static void carthw_Xin1_mem_setup(void)
|
||||
{
|
||||
cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, carthw_Xin1_write8, 1);
|
||||
}
|
||||
|
||||
static void carthw_Xin1_reset(void)
|
||||
{
|
||||
carthw_Xin1_write8(0xa13000, 0);
|
||||
}
|
||||
|
||||
static void carthw_Xin1_statef(void)
|
||||
{
|
||||
carthw_Xin1_write8(carthw_Xin1_baddr, 0);
|
||||
}
|
||||
|
||||
void carthw_Xin1_startup(void)
|
||||
{
|
||||
elprintf(EL_STATUS, "X-in-1 mapper startup");
|
||||
|
||||
PicoCartMemSetup = carthw_Xin1_mem_setup;
|
||||
PicoResetHook = carthw_Xin1_reset;
|
||||
PicoLoadStateHook = carthw_Xin1_statef;
|
||||
carthw_chunks = carthw_Xin1_state;
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,9 +81,8 @@ void carthw_12in1_startup(void)
|
|||
* http://www.sharemation.com/TascoDLX/REALTEC%20Cart%20Mapper%20-%20description%20v1.txt
|
||||
*/
|
||||
static int realtec_bank = 0x80000000, realtec_size = 0x80000000;
|
||||
static int realtec_romsize = 0;
|
||||
|
||||
static void carthw_realtec_write8(unsigned int a, unsigned int d, int realsize)
|
||||
static void carthw_realtec_write8(u32 a, u32 d)
|
||||
{
|
||||
int i, bank_old = realtec_bank, size_old = realtec_size;
|
||||
|
||||
|
@ -121,105 +113,92 @@ static void carthw_realtec_write8(unsigned int a, unsigned int d, int realsize)
|
|||
(realtec_bank != bank_old || realtec_size != size_old))
|
||||
{
|
||||
elprintf(EL_ANOMALY, "realtec: new bank %06x, size %06x", realtec_bank, realtec_size, SekPc);
|
||||
if (realtec_size > realtec_romsize - realtec_bank || realtec_bank >= realtec_romsize)
|
||||
if (realtec_size > Pico.romsize - realtec_bank)
|
||||
{
|
||||
elprintf(EL_ANOMALY, "realtec: bank too large / out of range?");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 0x400000; i += realtec_size)
|
||||
memcpy(Pico.rom + i, Pico.rom + 0x400000 + realtec_bank, realtec_size);
|
||||
for (i = 0; i < 0x400000; i += realtec_size) {
|
||||
cpu68k_map_set(m68k_read8_map, i, realtec_size - 1, Pico.rom + realtec_bank, 0);
|
||||
cpu68k_map_set(m68k_read16_map, i, realtec_size - 1, Pico.rom + realtec_bank, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void carthw_realtec_reset(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* map boot code */
|
||||
for (i = 0; i < 0x400000; i += 0x2000)
|
||||
memcpy(Pico.rom + i, Pico.rom + 0x400000 + realtec_romsize - 0x2000, 0x2000);
|
||||
for (i = 0; i < 0x400000; i += M68K_BANK_SIZE) {
|
||||
cpu68k_map_set(m68k_read8_map, i, i + M68K_BANK_SIZE - 1, Pico.rom + Pico.romsize, 0);
|
||||
cpu68k_map_set(m68k_read16_map, i, i + M68K_BANK_SIZE - 1, Pico.rom + Pico.romsize, 0);
|
||||
}
|
||||
cpu68k_map_set(m68k_write8_map, 0x400000, 0x400000 + M68K_BANK_SIZE - 1, carthw_realtec_write8, 1);
|
||||
realtec_bank = realtec_size = 0x80000000;
|
||||
}
|
||||
|
||||
void carthw_realtec_startup(void)
|
||||
{
|
||||
void *tmp;
|
||||
int i;
|
||||
|
||||
elprintf(EL_STATUS, "Realtec mapper detected");
|
||||
elprintf(EL_STATUS, "Realtec mapper startup");
|
||||
|
||||
realtec_romsize = Pico.romsize;
|
||||
Pico.romsize = 0x400000;
|
||||
tmp = realloc(Pico.rom, 0x400000 + realtec_romsize);
|
||||
// allocate additional bank for boot code
|
||||
// (we know those ROMs have aligned size)
|
||||
tmp = realloc(Pico.rom, Pico.romsize + M68K_BANK_SIZE);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
elprintf(EL_STATUS, "OOM");
|
||||
return;
|
||||
}
|
||||
Pico.rom = tmp;
|
||||
memcpy(Pico.rom + 0x400000, Pico.rom, realtec_romsize);
|
||||
|
||||
PicoWrite8Hook = carthw_realtec_write8;
|
||||
// create bank for boot code
|
||||
for (i = 0; i < M68K_BANK_SIZE; i += 0x2000)
|
||||
memcpy(Pico.rom + Pico.romsize + i, Pico.rom + Pico.romsize - 0x2000, 0x2000);
|
||||
|
||||
PicoResetHook = carthw_realtec_reset;
|
||||
}
|
||||
|
||||
/* Radica mapper, based on DevSter's info
|
||||
* http://devster.monkeeh.com/sega/radica/
|
||||
* XXX: mostly the same as X-in-1, merge?
|
||||
*/
|
||||
static unsigned int carthw_radica_baddr = 0;
|
||||
|
||||
static carthw_state_chunk carthw_radica_state[] =
|
||||
static u32 carthw_radica_read16(u32 a)
|
||||
{
|
||||
{ CHUNK_CARTHW, sizeof(carthw_radica_baddr), &carthw_radica_baddr },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
if ((a & 0xffff00) != 0xa13000)
|
||||
return PicoRead16_io(a);
|
||||
|
||||
static unsigned int carthw_radica_read16(unsigned int a, int realsize)
|
||||
{
|
||||
if ((a & 0xffff80) != 0xa13000) {
|
||||
elprintf(EL_UIO, "radica: r16 %06x", a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
carthw_radica_baddr = a;
|
||||
a = (a & 0x7e) << 15;
|
||||
if (a >= Pico.romsize) {
|
||||
elprintf(EL_ANOMALY|EL_STATUS, "radica: missing bank @ %06x", a);
|
||||
return 0;
|
||||
}
|
||||
memcpy(Pico.rom, Pico.rom + Pico.romsize + a, Pico.romsize - a);
|
||||
carthw_Xin1_do(a, 0x7e, 15);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void carthw_radica_mem_setup(void)
|
||||
{
|
||||
cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, carthw_radica_read16, 1);
|
||||
}
|
||||
|
||||
static void carthw_radica_statef(void)
|
||||
{
|
||||
carthw_radica_read16(carthw_radica_baddr, 0);
|
||||
carthw_radica_read16(carthw_Xin1_baddr);
|
||||
}
|
||||
|
||||
static void carthw_radica_reset(void)
|
||||
{
|
||||
memcpy(Pico.rom, Pico.rom + Pico.romsize, Pico.romsize);
|
||||
carthw_radica_read16(0xa13000);
|
||||
}
|
||||
|
||||
void carthw_radica_startup(void)
|
||||
{
|
||||
void *tmp;
|
||||
elprintf(EL_STATUS, "Radica mapper startup");
|
||||
|
||||
elprintf(EL_STATUS, "Radica mapper detected");
|
||||
|
||||
tmp = realloc(Pico.rom, Pico.romsize * 2);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
elprintf(EL_STATUS, "OOM");
|
||||
return;
|
||||
}
|
||||
Pico.rom = tmp;
|
||||
memcpy(Pico.rom + Pico.romsize, Pico.rom, Pico.romsize);
|
||||
|
||||
PicoRead16Hook = carthw_radica_read16;
|
||||
PicoResetHook = carthw_radica_reset;
|
||||
PicoCartMemSetup = carthw_radica_mem_setup;
|
||||
PicoResetHook = carthw_radica_reset;
|
||||
PicoLoadStateHook = carthw_radica_statef;
|
||||
carthw_chunks = carthw_radica_state;
|
||||
carthw_chunks = carthw_Xin1_state;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,12 +12,9 @@ extern svp_t *svp;
|
|||
|
||||
void PicoSVPInit(void);
|
||||
void PicoSVPStartup(void);
|
||||
|
||||
unsigned int PicoSVPRead16(unsigned int a, int realsize);
|
||||
void PicoSVPWrite8 (unsigned int a, unsigned int d, int realsize);
|
||||
void PicoSVPWrite16(unsigned int a, unsigned int d, int realsize);
|
||||
void PicoSVPMemSetup(void);
|
||||
|
||||
/* misc */
|
||||
void carthw_12in1_startup(void);
|
||||
void carthw_Xin1_startup(void);
|
||||
void carthw_realtec_startup(void);
|
||||
void carthw_radica_startup(void);
|
||||
|
|
|
@ -7,32 +7,9 @@
|
|||
|
||||
|
||||
#include "../../pico_int.h"
|
||||
#include "../../memory.h"
|
||||
|
||||
#ifndef UTYPES_DEFINED
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
#define UTYPES_DEFINED
|
||||
#endif
|
||||
|
||||
#define CLEAR_DETECT(pc_start,pc_end,text) \
|
||||
if (d == 0 && SekPc >= pc_start && SekPc < pc_end) \
|
||||
{ \
|
||||
if (!clearing_ram) \
|
||||
elprintf(EL_SVP, text); \
|
||||
clearing_ram = 1; \
|
||||
return; \
|
||||
}
|
||||
|
||||
unsigned int PicoSVPRead16(unsigned int a, int realsize)
|
||||
{
|
||||
unsigned int d = 0;
|
||||
static int a15004_looping = 0;
|
||||
|
||||
// dram: 300000-31ffff
|
||||
if ((a & 0xfe0000) == 0x300000)
|
||||
d = *(u16 *)(svp->dram + (a&0x1fffe));
|
||||
|
||||
/*
|
||||
// "cell arrange" 1: 390000-39ffff
|
||||
else if ((a & 0xff0000) == 0x390000) {
|
||||
// this is rewritten 68k code
|
||||
|
@ -48,9 +25,15 @@ unsigned int PicoSVPRead16(unsigned int a, int realsize)
|
|||
a1 = (a1 & 0x7801) | ((a1 & 0x1e) << 6) | ((a1 & 0x7e0) >> 4);
|
||||
d = ((u16 *)svp->dram)[a1];
|
||||
}
|
||||
*/
|
||||
|
||||
// IO/control area (0xa10000 - 0xa1ffff)
|
||||
static u32 PicoRead16_svpr(u32 a)
|
||||
{
|
||||
u32 d = 0;
|
||||
|
||||
// regs
|
||||
else if ((a & 0xfffff0) == 0xa15000) {
|
||||
if ((a & 0xfffff0) == 0xa15000) {
|
||||
switch (a & 0xf) {
|
||||
case 0:
|
||||
case 2:
|
||||
|
@ -60,44 +43,41 @@ unsigned int PicoSVPRead16(unsigned int a, int realsize)
|
|||
case 4:
|
||||
d = svp->ssp1601.gr[SSP_PM0].h;
|
||||
svp->ssp1601.gr[SSP_PM0].h &= ~1;
|
||||
if (d&1) a15004_looping = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
elprintf(EL_UIO|EL_SVP|EL_ANOMALY, "SVP FIXME: unhandled r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
|
||||
|
||||
if (!a15004_looping)
|
||||
elprintf(EL_SVP, "SVP r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
|
||||
#if EL_LOGMASK & EL_SVP
|
||||
{
|
||||
static int a15004_looping = 0;
|
||||
if (a == 0xa15004 && (d & 1))
|
||||
a15004_looping = 0;
|
||||
|
||||
if (a == 0xa15004 && !(d&1)) {
|
||||
if (!a15004_looping)
|
||||
elprintf(EL_SVP, "SVP det TIGHT loop: a15004");
|
||||
a15004_looping = 1;
|
||||
if (!a15004_looping)
|
||||
elprintf(EL_SVP, "SVP r%i: [%06x] %04x @%06x", realsize, a, d, SekPc);
|
||||
|
||||
if (a == 0xa15004 && !(d&1)) {
|
||||
if (!a15004_looping)
|
||||
elprintf(EL_SVP, "SVP det TIGHT loop: a15004");
|
||||
a15004_looping = 1;
|
||||
}
|
||||
else
|
||||
a15004_looping = 0;
|
||||
}
|
||||
#endif
|
||||
return d;
|
||||
}
|
||||
else a15004_looping = 0;
|
||||
|
||||
//if (a == 0x30fe02 && d == 0)
|
||||
// elprintf(EL_ANOMALY, "SVP lag?");
|
||||
|
||||
return d;
|
||||
return PicoRead16_io(a);
|
||||
}
|
||||
|
||||
void PicoSVPWrite8(unsigned int a, unsigned int d, int realsize)
|
||||
static void PicoWrite16_svpr(u32 a, u32 d)
|
||||
{
|
||||
elprintf(EL_UIO|EL_SVP|EL_ANOMALY, "!!! SVP w%i: [%06x], %08x @%06x", realsize, a&0xffffff, d, SekPc);
|
||||
}
|
||||
elprintf(EL_SVP, "SVP w16: [%06x] %04x @%06x", a, d, SekPc);
|
||||
|
||||
void PicoSVPWrite16(unsigned int a, unsigned int d, int realsize)
|
||||
{
|
||||
static int clearing_ram = 0;
|
||||
|
||||
// DRAM
|
||||
if ((a & 0xfe0000) == 0x300000)
|
||||
*(u16 *)(svp->dram + (a&0x1fffe)) = d;
|
||||
|
||||
// regs
|
||||
else if ((a & 0xfffff0) == 0xa15000) {
|
||||
if ((a & 0xfffff0) == 0xa15000) {
|
||||
if (a == 0xa15000 || a == 0xa15002) {
|
||||
// just guessing here
|
||||
svp->ssp1601.gr[SSP_XST].h = d;
|
||||
|
@ -106,24 +86,34 @@ void PicoSVPWrite16(unsigned int a, unsigned int d, int realsize)
|
|||
}
|
||||
//else if (a == 0xa15006) svp->ssp1601.gr[SSP_PM0].h = d | (d << 1);
|
||||
// 0xa15006 probably has 'halt'
|
||||
return;
|
||||
}
|
||||
else
|
||||
elprintf(EL_UIO|EL_SVP|EL_ANOMALY, "SVP FIXME: unhandled w%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
|
||||
|
||||
|
||||
PicoWrite16_io(a, d);
|
||||
/*
|
||||
if (a == 0x30fe06 && d != 0)
|
||||
svp->ssp1601.emu_status &= ~SSP_WAIT_30FE06;
|
||||
|
||||
if (a == 0x30fe08 && d != 0)
|
||||
svp->ssp1601.emu_status &= ~SSP_WAIT_30FE08;
|
||||
|
||||
// debug: detect RAM clears..
|
||||
CLEAR_DETECT(0x0221dc, 0x0221f0, "SVP RAM CLEAR (full) @ 0221C2");
|
||||
CLEAR_DETECT(0x02204c, 0x022068, "SVP RAM CLEAR 300000-31ffbf (1) @ 022032");
|
||||
CLEAR_DETECT(0x021900, 0x021ff0, "SVP RAM CLEAR 300000-305fff");
|
||||
CLEAR_DETECT(0x0220b0, 0x0220cc, "SVP RAM CLEAR 300000-31ffbf (2) @ 022096");
|
||||
clearing_ram = 0;
|
||||
|
||||
elprintf(EL_SVP, "SVP w%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
|
||||
*/
|
||||
}
|
||||
|
||||
void PicoSVPMemSetup(void)
|
||||
{
|
||||
// 68k memmap:
|
||||
// DRAM
|
||||
cpu68k_map_set(m68k_read8_map, 0x300000, 0x31ffff, svp->dram, 0);
|
||||
cpu68k_map_set(m68k_read16_map, 0x300000, 0x31ffff, svp->dram, 0);
|
||||
cpu68k_map_set(m68k_write8_map, 0x300000, 0x31ffff, svp->dram, 0);
|
||||
cpu68k_map_set(m68k_write16_map, 0x300000, 0x31ffff, svp->dram, 0);
|
||||
|
||||
// DRAM (cell arrange) - TODO
|
||||
|
||||
// regs
|
||||
cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_io, 1); // PicoRead8_svpr
|
||||
cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_svpr, 1);
|
||||
cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_io, 1); // PicoWrite8_svpr
|
||||
cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_svpr, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -647,12 +647,14 @@ static void write_XST(u32 d)
|
|||
static u32 read_PM4(void)
|
||||
{
|
||||
u32 d = pm_io(4, 0, 0);
|
||||
/* TODO?
|
||||
if (d == 0) {
|
||||
switch (GET_PPC_OFFS()) {
|
||||
case 0x0854: ssp->emu_status |= SSP_WAIT_30FE08; elprintf(EL_SVP, "det TIGHT loop: [30fe08]"); break;
|
||||
case 0x4f12: ssp->emu_status |= SSP_WAIT_30FE06; elprintf(EL_SVP, "det TIGHT loop: [30fe06]"); break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (d != (u32)-1) return d;
|
||||
// can be removed?
|
||||
elprintf(EL_SVP|EL_ANOMALY, "PM4 raw r %04x @ %04x", rPM4, GET_PPC_OFFS());
|
||||
|
|
|
@ -121,7 +121,7 @@ void PicoSVPStartup(void)
|
|||
{
|
||||
void *tmp;
|
||||
|
||||
elprintf(EL_SVP, "SVP init");
|
||||
elprintf(EL_STATUS, "SVP startup");
|
||||
|
||||
tmp = realloc(Pico.rom, 0x200000 + sizeof(*svp));
|
||||
if (tmp == NULL)
|
||||
|
@ -150,9 +150,7 @@ void PicoSVPStartup(void)
|
|||
#endif
|
||||
|
||||
// init ok, setup hooks..
|
||||
PicoRead16Hook = PicoSVPRead16;
|
||||
PicoWrite8Hook = PicoSVPWrite8;
|
||||
PicoWrite16Hook = PicoSVPWrite16;
|
||||
PicoCartMemSetup = PicoSVPMemSetup;
|
||||
PicoDmaHook = PicoSVPDma;
|
||||
PicoResetHook = PicoSVPReset;
|
||||
PicoLineHook = PicoSVPLine;
|
||||
|
|
|
@ -1044,101 +1044,12 @@ static void PicoWriteCD32w(unsigned int a, unsigned int d) {
|
|||
if (m68ki_cpu_p == &PicoCpuMS68k) s68k_write32(a, d); else m68k_write32(a, d);
|
||||
}
|
||||
|
||||
// these are allowed to access RAM
|
||||
static unsigned int m68k_read_pcrelative_CD8 (unsigned int a)
|
||||
{
|
||||
a&=0xffffff;
|
||||
if(m68ki_cpu_p == &PicoCpuMS68k) {
|
||||
if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram
|
||||
if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)
|
||||
return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));
|
||||
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)
|
||||
int bank = (Pico_mcd->s68k_regs[3]&1)^1;
|
||||
return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));
|
||||
}
|
||||
elprintf(EL_ANOMALY, "s68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);
|
||||
} else {
|
||||
if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram
|
||||
if(a<0x20000) return *(u8 *)(Pico.rom+(a^1)); // Bios
|
||||
if((a&0xfc0000)==0x200000) { // word RAM
|
||||
if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?
|
||||
return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));
|
||||
else if (a < 0x220000) {
|
||||
int bank = Pico_mcd->s68k_regs[3]&1;
|
||||
return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));
|
||||
}
|
||||
}
|
||||
elprintf(EL_ANOMALY, "m68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);
|
||||
}
|
||||
return 0;//(u8) lastread_d;
|
||||
}
|
||||
static unsigned int m68k_read_pcrelative_CD16(unsigned int a)
|
||||
{
|
||||
a&=0xffffff;
|
||||
if(m68ki_cpu_p == &PicoCpuMS68k) {
|
||||
if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram
|
||||
if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)
|
||||
return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
|
||||
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)
|
||||
int bank = (Pico_mcd->s68k_regs[3]&1)^1;
|
||||
return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
|
||||
}
|
||||
elprintf(EL_ANOMALY, "s68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);
|
||||
} else {
|
||||
if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram
|
||||
if(a<0x20000) return *(u16 *)(Pico.rom+(a&~1)); // Bios
|
||||
if((a&0xfc0000)==0x200000) { // word RAM
|
||||
if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?
|
||||
return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
|
||||
else if (a < 0x220000) {
|
||||
int bank = Pico_mcd->s68k_regs[3]&1;
|
||||
return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
|
||||
}
|
||||
}
|
||||
elprintf(EL_ANOMALY, "m68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static unsigned int m68k_read_pcrelative_CD32(unsigned int a)
|
||||
{
|
||||
u16 *pm;
|
||||
a&=0xffffff;
|
||||
if(m68ki_cpu_p == &PicoCpuMS68k) {
|
||||
if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram
|
||||
if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)
|
||||
{ pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }
|
||||
if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)
|
||||
int bank = (Pico_mcd->s68k_regs[3]&1)^1;
|
||||
pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
|
||||
return (pm[0]<<16)|pm[1];
|
||||
}
|
||||
elprintf(EL_ANOMALY, "s68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);
|
||||
} else {
|
||||
if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram
|
||||
if(a<0x20000) { u16 *pm=(u16 *)(Pico.rom+(a&~1)); return (pm[0]<<16)|pm[1]; }
|
||||
if((a&0xfc0000)==0x200000) { // word RAM
|
||||
if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?
|
||||
{ pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }
|
||||
else if (a < 0x220000) {
|
||||
int bank = Pico_mcd->s68k_regs[3]&1;
|
||||
pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
|
||||
return (pm[0]<<16)|pm[1];
|
||||
}
|
||||
}
|
||||
elprintf(EL_ANOMALY, "m68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern unsigned int (*pm68k_read_memory_8) (unsigned int address);
|
||||
extern unsigned int (*pm68k_read_memory_16)(unsigned int address);
|
||||
extern unsigned int (*pm68k_read_memory_32)(unsigned int address);
|
||||
extern void (*pm68k_write_memory_8) (unsigned int address, unsigned char value);
|
||||
extern void (*pm68k_write_memory_16)(unsigned int address, unsigned short value);
|
||||
extern void (*pm68k_write_memory_32)(unsigned int address, unsigned int value);
|
||||
extern unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address);
|
||||
extern unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address);
|
||||
extern unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address);
|
||||
|
||||
static void m68k_mem_setup_cd(void)
|
||||
{
|
||||
|
@ -1148,9 +1059,6 @@ static void m68k_mem_setup_cd(void)
|
|||
pm68k_write_memory_8 = PicoWriteCD8w;
|
||||
pm68k_write_memory_16 = PicoWriteCD16w;
|
||||
pm68k_write_memory_32 = PicoWriteCD32w;
|
||||
pm68k_read_memory_pcr_8 = m68k_read_pcrelative_CD8;
|
||||
pm68k_read_memory_pcr_16 = m68k_read_pcrelative_CD16;
|
||||
pm68k_read_memory_pcr_32 = m68k_read_pcrelative_CD32;
|
||||
}
|
||||
#endif // EMU_M68K
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@ char *PDebugMain(void)
|
|||
sprintf(dstrp, "mode set 4: %02x\n", (r=reg[0xC])); MVP;
|
||||
sprintf(dstrp, "interlace: %i%i, cells: %i, shadow: %i\n", bit(r,2), bit(r,1), (r&0x80) ? 40 : 32, bit(r,3)); MVP;
|
||||
sprintf(dstrp, "scroll size: w: %i, h: %i SRAM: %i; eeprom: %i (%i)\n", reg[0x10]&3, (reg[0x10]&0x30)>>4,
|
||||
bit(Pico.m.sram_status, 4), bit(Pico.m.sram_status, 2), SRam.eeprom_type); MVP;
|
||||
sprintf(dstrp, "sram range: %06x-%06x, reg: %02x\n", SRam.start, SRam.end, Pico.m.sram_status); MVP;
|
||||
!!(SRam.flags & SRF_ENABLED), !!(SRam.flags & SRF_EEPROM), SRam.eeprom_type); MVP;
|
||||
sprintf(dstrp, "sram range: %06x-%06x, reg: %02x\n", SRam.start, SRam.end, Pico.m.sram_reg); MVP;
|
||||
sprintf(dstrp, "pend int: v:%i, h:%i, vdp status: %04x\n", bit(pv->pending_ints,5), bit(pv->pending_ints,4), pv->status); MVP;
|
||||
sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count); MVP;
|
||||
#if defined(EMU_C68K)
|
||||
|
|
208
pico/eeprom.c
Normal file
208
pico/eeprom.c
Normal file
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* rarely used EEPROM code
|
||||
*
|
||||
* (see Genesis Plus for Wii/GC code and docs for info,
|
||||
* full game list and better code).
|
||||
*/
|
||||
|
||||
#include "pico_int.h"
|
||||
|
||||
static unsigned int last_write = 0xffff0000;
|
||||
|
||||
// eeprom_status: LA.. s.la (L=pending SCL, A=pending SDA,
|
||||
// s=started, l=old SCL, a=old SDA)
|
||||
static void EEPROM_write_do(unsigned int d) // ???? ??la (l=SCL, a=SDA)
|
||||
{
|
||||
unsigned int sreg = Pico.m.eeprom_status, saddr = Pico.m.eeprom_addr;
|
||||
unsigned int scyc = Pico.m.eeprom_cycle, ssa = Pico.m.eeprom_slave;
|
||||
|
||||
elprintf(EL_EEPROM, "eeprom: scl/sda: %i/%i -> %i/%i, newtime=%i", (sreg&2)>>1, sreg&1,
|
||||
(d&2)>>1, d&1, SekCyclesDoneT() - last_write);
|
||||
saddr &= 0x1fff;
|
||||
|
||||
if(sreg & d & 2) {
|
||||
// SCL was and is still high..
|
||||
if((sreg & 1) && !(d&1)) {
|
||||
// ..and SDA went low, means it's a start command, so clear internal addr reg and clock counter
|
||||
elprintf(EL_EEPROM, "eeprom: -start-");
|
||||
//saddr = 0;
|
||||
scyc = 0;
|
||||
sreg |= 8;
|
||||
} else if(!(sreg & 1) && (d&1)) {
|
||||
// SDA went high == stop command
|
||||
elprintf(EL_EEPROM, "eeprom: -stop-");
|
||||
sreg &= ~8;
|
||||
}
|
||||
}
|
||||
else if((sreg & 8) && !(sreg & 2) && (d&2))
|
||||
{
|
||||
// we are started and SCL went high - next cycle
|
||||
scyc++; // pre-increment
|
||||
if(SRam.eeprom_type) {
|
||||
// X24C02+
|
||||
if((ssa&1) && scyc == 18) {
|
||||
scyc = 9;
|
||||
saddr++; // next address in read mode
|
||||
/*if(SRam.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask
|
||||
}
|
||||
else if(SRam.eeprom_type == 2 && scyc == 27) scyc = 18;
|
||||
else if(scyc == 36) scyc = 27;
|
||||
} else {
|
||||
// X24C01
|
||||
if(scyc == 18) {
|
||||
scyc = 9; // wrap
|
||||
if(saddr&1) { saddr+=2; saddr&=0xff; } // next addr in read mode
|
||||
}
|
||||
}
|
||||
elprintf(EL_EEPROM, "eeprom: scyc: %i", scyc);
|
||||
}
|
||||
else if((sreg & 8) && (sreg & 2) && !(d&2))
|
||||
{
|
||||
// we are started and SCL went low (falling edge)
|
||||
if(SRam.eeprom_type) {
|
||||
// X24C02+
|
||||
if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles
|
||||
else if( (SRam.eeprom_type == 3 && scyc > 27) || (SRam.eeprom_type == 2 && scyc > 18) ) {
|
||||
if(!(ssa&1)) {
|
||||
// data write
|
||||
unsigned char *pm=SRam.data+saddr;
|
||||
*pm <<= 1; *pm |= d&1;
|
||||
if(scyc == 26 || scyc == 35) {
|
||||
saddr=(saddr&~0xf)|((saddr+1)&0xf); // only 4 (?) lowest bits are incremented
|
||||
elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr, *pm);
|
||||
}
|
||||
SRam.changed = 1;
|
||||
}
|
||||
} else if(scyc > 9) {
|
||||
if(!(ssa&1)) {
|
||||
// we latch another addr bit
|
||||
saddr<<=1;
|
||||
if(SRam.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask
|
||||
saddr|=d&1;
|
||||
if(scyc==17||scyc==26) {
|
||||
elprintf(EL_EEPROM, "eeprom: addr reg done: %x", saddr);
|
||||
if(scyc==17&&SRam.eeprom_type==2) { saddr&=0xff; saddr|=(ssa<<7)&0x700; } // add device bits too
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// slave address
|
||||
ssa<<=1; ssa|=d&1;
|
||||
if(scyc==8) elprintf(EL_EEPROM, "eeprom: slave done: %x", ssa);
|
||||
}
|
||||
} else {
|
||||
// X24C01
|
||||
if(scyc == 9); // ACK cycle, do nothing
|
||||
else if(scyc > 9) {
|
||||
if(!(saddr&1)) {
|
||||
// data write
|
||||
unsigned char *pm=SRam.data+(saddr>>1);
|
||||
*pm <<= 1; *pm |= d&1;
|
||||
if(scyc == 17) {
|
||||
saddr=(saddr&0xf9)|((saddr+2)&6); // only 2 lowest bits are incremented
|
||||
elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr>>1, *pm);
|
||||
}
|
||||
SRam.changed = 1;
|
||||
}
|
||||
} else {
|
||||
// we latch another addr bit
|
||||
saddr<<=1; saddr|=d&1; saddr&=0xff;
|
||||
if(scyc==8) elprintf(EL_EEPROM, "eeprom: addr done: %x", saddr>>1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sreg &= ~3; sreg |= d&3; // remember SCL and SDA
|
||||
Pico.m.eeprom_status = (unsigned char) sreg;
|
||||
Pico.m.eeprom_cycle = (unsigned char) scyc;
|
||||
Pico.m.eeprom_slave = (unsigned char) ssa;
|
||||
Pico.m.eeprom_addr = (unsigned short)saddr;
|
||||
}
|
||||
|
||||
static void EEPROM_upd_pending(unsigned int d)
|
||||
{
|
||||
unsigned int d1, sreg = Pico.m.eeprom_status;
|
||||
|
||||
sreg &= ~0xc0;
|
||||
|
||||
// SCL
|
||||
d1 = (d >> SRam.eeprom_bit_cl) & 1;
|
||||
sreg |= d1 << 7;
|
||||
|
||||
// SDA in
|
||||
d1 = (d >> SRam.eeprom_bit_in) & 1;
|
||||
sreg |= d1 << 6;
|
||||
|
||||
Pico.m.eeprom_status = (unsigned char) sreg;
|
||||
}
|
||||
|
||||
void EEPROM_write16(unsigned int d)
|
||||
{
|
||||
// this diff must be at most 16 for NBA Jam to work
|
||||
if (SekCyclesDoneT() - last_write < 16) {
|
||||
// just update pending state
|
||||
elprintf(EL_EEPROM, "eeprom: skip because cycles=%i",
|
||||
SekCyclesDoneT() - last_write);
|
||||
EEPROM_upd_pending(d);
|
||||
} else {
|
||||
int srs = Pico.m.eeprom_status;
|
||||
EEPROM_write_do(srs >> 6); // execute pending
|
||||
EEPROM_upd_pending(d);
|
||||
if ((srs ^ Pico.m.eeprom_status) & 0xc0) // update time only if SDA/SCL changed
|
||||
last_write = SekCyclesDoneT();
|
||||
}
|
||||
}
|
||||
|
||||
void EEPROM_write8(unsigned int a, unsigned int d)
|
||||
{
|
||||
unsigned char *wb = Pico.m.eeprom_wb;
|
||||
wb[a & 1] = d;
|
||||
EEPROM_write16((wb[0] << 8) | wb[1]);
|
||||
}
|
||||
|
||||
unsigned int EEPROM_read(void)
|
||||
{
|
||||
unsigned int shift, d;
|
||||
unsigned int sreg, saddr, scyc, ssa, interval;
|
||||
|
||||
// flush last pending write
|
||||
EEPROM_write_do(Pico.m.eeprom_status>>6);
|
||||
|
||||
sreg = Pico.m.eeprom_status; saddr = Pico.m.eeprom_addr&0x1fff; scyc = Pico.m.eeprom_cycle; ssa = Pico.m.eeprom_slave;
|
||||
interval = SekCyclesDoneT() - last_write;
|
||||
d = (sreg>>6)&1; // use SDA as "open bus"
|
||||
|
||||
// NBA Jam is nasty enough to read <before> raising the SCL and starting the new cycle.
|
||||
// this is probably valid because data changes occur while SCL is low and data can be read
|
||||
// before it's actual cycle begins.
|
||||
if (!(sreg&0x80) && interval >= 24) {
|
||||
elprintf(EL_EEPROM, "eeprom: early read, cycles=%i", interval);
|
||||
scyc++;
|
||||
}
|
||||
|
||||
if (!(sreg & 8)); // not started, use open bus
|
||||
else if (scyc == 9 || scyc == 18 || scyc == 27) {
|
||||
elprintf(EL_EEPROM, "eeprom: r ack");
|
||||
d = 0;
|
||||
} else if (scyc > 9 && scyc < 18) {
|
||||
// started and first command word received
|
||||
shift = 17-scyc;
|
||||
if (SRam.eeprom_type) {
|
||||
// X24C02+
|
||||
if (ssa&1) {
|
||||
elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg);
|
||||
if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr]);
|
||||
d = (SRam.data[saddr]>>shift)&1;
|
||||
}
|
||||
} else {
|
||||
// X24C01
|
||||
if (saddr&1) {
|
||||
elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr>>1, scyc, sreg);
|
||||
if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr>>1]);
|
||||
d = (SRam.data[saddr>>1]>>shift)&1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (d << SRam.eeprom_bit_out);
|
||||
}
|
||||
|
234
pico/memory.c
234
pico/memory.c
|
@ -320,7 +320,7 @@ static void ctl_write_z80reset(u32 d)
|
|||
|
||||
// for nonstandard reads
|
||||
// TODO: mv to carthw
|
||||
static u32 OtherRead16End(u32 a, int realsize)
|
||||
u32 OtherRead16End(u32 a, int realsize)
|
||||
{
|
||||
u32 d=0;
|
||||
|
||||
|
@ -364,7 +364,7 @@ static u32 OtherRead16End(u32 a, int realsize)
|
|||
// our default behaviour is to return whatever was last written a 0x400000-0x7fffff range (used by Squirrel King (R) [!])
|
||||
// Lion King II, The (Unl) [!] writes @ 400000 and wants to get that val @ 400002 and wites another val
|
||||
// @ 400004 which is expected @ 400006, so we really remember 2 values here
|
||||
d = Pico.m.prot_bytes[(a>>2)&1]<<8;
|
||||
/// d = Pico.m.prot_bytes[(a>>2)&1]<<8;
|
||||
}
|
||||
else if (a == 0xa13000 && Pico.romsize >= 1024*1024) {
|
||||
if (*(int *)(Pico.rom+0xc8af0) == 0x30133013 && *(int *)(Pico.rom+0xc8af4) == 0x000f0240) { // Rockman X3 (Unl) [!]
|
||||
|
@ -397,28 +397,11 @@ end:
|
|||
return d;
|
||||
}
|
||||
|
||||
static void OtherWrite8End(u32 a,u32 d,int realsize)
|
||||
void OtherWrite8End(u32 a,u32 d,int realsize)
|
||||
{
|
||||
#ifdef _ASM_MEMORY_C
|
||||
// special ROM hardware (currently only banking and sram reg supported)
|
||||
if((a&0xfffff1) == 0xA130F1) {
|
||||
PicoWriteRomHW_SSF2(a, d); // SSF2 or SRAM
|
||||
return;
|
||||
}
|
||||
#else
|
||||
// sram access register
|
||||
if(a == 0xA130F1) {
|
||||
elprintf(EL_SRAMIO, "sram reg=%02x", d);
|
||||
Pico.m.sram_status &= ~(SRS_MAPPED|SRS_READONLY);
|
||||
Pico.m.sram_status |= (u8)(d&3);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
elprintf(EL_UIO, "strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc);
|
||||
|
||||
// for games with simple protection devices, discovered by Haze
|
||||
if ((a>>22) == 1)
|
||||
Pico.m.prot_bytes[(a>>2)&1] = (u8)d;
|
||||
;/// Pico.m.prot_bytes[(a>>2)&1] = (u8)d;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
@ -426,18 +409,20 @@ static void OtherWrite8End(u32 a,u32 d,int realsize)
|
|||
// cart (save) RAM area (usually 0x200000 - ...)
|
||||
static u32 PicoRead8_sram(u32 a)
|
||||
{
|
||||
int srs = Pico.m.sram_status;
|
||||
u32 d;
|
||||
if (SRam.end >= a && a >= SRam.start && (srs & (SRS_MAPPED|SRS_EEPROM)))
|
||||
if (SRam.start <= a && a <= SRam.end && (Pico.m.sram_reg & SRR_MAPPED))
|
||||
{
|
||||
if (srs & SRS_EEPROM)
|
||||
if (SRam.flags & SRF_EEPROM) {
|
||||
d = EEPROM_read();
|
||||
else
|
||||
if (!(a & 1))
|
||||
d >>= 8;
|
||||
} else
|
||||
d = *(u8 *)(SRam.data - SRam.start + a);
|
||||
elprintf(EL_SRAMIO, "sram r8 [%06x] %02x @ %06x", a, d, SekPc);
|
||||
elprintf(EL_SRAMIO, "sram r8 [%06x] %02x @ %06x", a, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
|
||||
// XXX: this is banking unfriendly
|
||||
if (a < Pico.romsize)
|
||||
return Pico.rom[a ^ 1];
|
||||
|
||||
|
@ -446,14 +431,12 @@ static u32 PicoRead8_sram(u32 a)
|
|||
|
||||
static u32 PicoRead16_sram(u32 a)
|
||||
{
|
||||
int srs = Pico.m.sram_status;
|
||||
u32 d;
|
||||
if (SRam.end >= a && a >= SRam.start && (srs & (SRS_MAPPED|SRS_EEPROM)))
|
||||
if (SRam.end >= a && a >= SRam.start && (Pico.m.sram_reg & SRR_MAPPED))
|
||||
{
|
||||
if (srs & SRS_EEPROM) {
|
||||
if (SRam.flags & SRF_EEPROM)
|
||||
d = EEPROM_read();
|
||||
d |= d << 8;
|
||||
} else {
|
||||
else {
|
||||
u8 *pm = (u8 *)(SRam.data - SRam.start + a);
|
||||
d = pm[0] << 8;
|
||||
d |= pm[1];
|
||||
|
@ -470,25 +453,18 @@ static u32 PicoRead16_sram(u32 a)
|
|||
|
||||
static void PicoWrite8_sram(u32 a, u32 d)
|
||||
{
|
||||
unsigned int srs = Pico.m.sram_status;
|
||||
elprintf(EL_SRAMIO, "sram wX [%06x] %02x @ %06x", a, d & 0xffff, SekPc);
|
||||
if (srs & SRS_EEPROM) // EEPROM write
|
||||
{
|
||||
// this diff must be at most 16 for NBA Jam to work
|
||||
if (SekCyclesDoneT() - lastSSRamWrite < 16) {
|
||||
// just update pending state
|
||||
elprintf(EL_EEPROM, "eeprom: skip because cycles=%i",
|
||||
SekCyclesDoneT() - lastSSRamWrite);
|
||||
EEPROM_upd_pending(a, d);
|
||||
} else {
|
||||
EEPROM_write(srs >> 6); // execute pending
|
||||
EEPROM_upd_pending(a, d);
|
||||
if ((srs ^ Pico.m.sram_status) & 0xc0) // update time only if SDA/SCL changed
|
||||
lastSSRamWrite = SekCyclesDoneT();
|
||||
}
|
||||
if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) {
|
||||
m68k_unmapped_write8(a, d);
|
||||
return;
|
||||
}
|
||||
else if (!(srs & SRS_READONLY)) {
|
||||
u8 *pm=(u8 *)(SRam.data - SRam.start + a);
|
||||
|
||||
elprintf(EL_SRAMIO, "sram w8 [%06x] %02x @ %06x", a, d & 0xff, SekPc);
|
||||
if (SRam.flags & SRF_EEPROM)
|
||||
{
|
||||
EEPROM_write8(a, d);
|
||||
}
|
||||
else {
|
||||
u8 *pm = (u8 *)(SRam.data - SRam.start + a);
|
||||
if (*pm != (u8)d) {
|
||||
SRam.changed = 1;
|
||||
*pm = (u8)d;
|
||||
|
@ -498,8 +474,24 @@ static void PicoWrite8_sram(u32 a, u32 d)
|
|||
|
||||
static void PicoWrite16_sram(u32 a, u32 d)
|
||||
{
|
||||
// XXX: hardware could easily use MSB too..
|
||||
PicoWrite8_sram(a + 1, d);
|
||||
if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) {
|
||||
m68k_unmapped_write16(a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
elprintf(EL_SRAMIO, "sram w16 [%06x] %04x @ %06x", a, d & 0xffff, SekPc);
|
||||
if (SRam.flags & SRF_EEPROM)
|
||||
{
|
||||
EEPROM_write16(d);
|
||||
}
|
||||
else {
|
||||
// XXX: hardware could easily use MSB too..
|
||||
u8 *pm = (u8 *)(SRam.data - SRam.start + a);
|
||||
if (*pm != (u8)d) {
|
||||
SRam.changed = 1;
|
||||
*pm = (u8)d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// z80 area (0xa00000 - 0xa0ffff)
|
||||
|
@ -645,8 +637,8 @@ void PicoWrite8_io(u32 a, u32 d)
|
|||
}
|
||||
if (a == 0xa130f1) { // sram access register
|
||||
elprintf(EL_SRAMIO, "sram reg=%02x", d);
|
||||
Pico.m.sram_status &= ~(SRS_MAPPED|SRS_READONLY);
|
||||
Pico.m.sram_status |= (u8)(d & 3);
|
||||
Pico.m.sram_reg &= ~(SRR_MAPPED|SRR_READONLY);
|
||||
Pico.m.sram_reg |= (u8)(d & 3);
|
||||
return;
|
||||
}
|
||||
m68k_unmapped_write8(a, d);
|
||||
|
@ -668,8 +660,8 @@ void PicoWrite16_io(u32 a, u32 d)
|
|||
}
|
||||
if (a == 0xa130f0) { // sram access register
|
||||
elprintf(EL_SRAMIO, "sram reg=%02x", d);
|
||||
Pico.m.sram_status &= ~(SRS_MAPPED|SRS_READONLY);
|
||||
Pico.m.sram_status |= (u8)(d & 3);
|
||||
Pico.m.sram_reg &= ~(SRR_MAPPED|SRR_READONLY);
|
||||
Pico.m.sram_reg |= (u8)(d & 3);
|
||||
return;
|
||||
}
|
||||
m68k_unmapped_write16(a, d);
|
||||
|
@ -728,25 +720,6 @@ static void PicoWrite16_vdp(u32 a, u32 d)
|
|||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// TODO: rm
|
||||
static void OtherWrite16End(u32 a,u32 d,int realsize)
|
||||
{
|
||||
PicoWrite8Hook(a, d>>8, realsize);
|
||||
PicoWrite8Hook(a+1,d&0xff, realsize);
|
||||
}
|
||||
|
||||
u32 (*PicoRead16Hook) (u32 a, int realsize) = OtherRead16End;
|
||||
void (*PicoWrite8Hook) (u32 a, u32 d, int realsize) = OtherWrite8End;
|
||||
void (*PicoWrite16Hook)(u32 a, u32 d, int realsize) = OtherWrite16End;
|
||||
|
||||
PICO_INTERNAL void PicoMemResetHooks(void)
|
||||
{
|
||||
// default unmapped/cart specific handlers
|
||||
PicoRead16Hook = OtherRead16End;
|
||||
PicoWrite8Hook = OtherWrite8End;
|
||||
PicoWrite16Hook = OtherWrite16End;
|
||||
}
|
||||
|
||||
#ifdef EMU_M68K
|
||||
static void m68k_mem_setup(void);
|
||||
#endif
|
||||
|
@ -769,8 +742,8 @@ PICO_INTERNAL void PicoMemSetup(void)
|
|||
cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0);
|
||||
|
||||
// Common case of on-cart (save) RAM, usually at 0x200000-...
|
||||
rs = SRam.end - SRam.start;
|
||||
if (rs > 0 && SRam.data != NULL) {
|
||||
if ((SRam.flags & SRF_ENABLED) && SRam.data != NULL) {
|
||||
rs = SRam.end - SRam.start;
|
||||
rs = (rs + mask) & ~mask;
|
||||
if (SRam.start + rs >= 0x1000000)
|
||||
rs = 0x1000000 - SRam.start;
|
||||
|
@ -849,7 +822,6 @@ PICO_INTERNAL void PicoMemSetup(void)
|
|||
z80_mem_setup();
|
||||
}
|
||||
|
||||
/* some nasty things below :( */
|
||||
#ifdef EMU_M68K
|
||||
unsigned int (*pm68k_read_memory_8) (unsigned int address) = NULL;
|
||||
unsigned int (*pm68k_read_memory_16)(unsigned int address) = NULL;
|
||||
|
@ -857,103 +829,6 @@ unsigned int (*pm68k_read_memory_32)(unsigned int address) = NULL;
|
|||
void (*pm68k_write_memory_8) (unsigned int address, unsigned char value) = NULL;
|
||||
void (*pm68k_write_memory_16)(unsigned int address, unsigned short value) = NULL;
|
||||
void (*pm68k_write_memory_32)(unsigned int address, unsigned int value) = NULL;
|
||||
unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address) = NULL;
|
||||
unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address) = NULL;
|
||||
unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address) = NULL;
|
||||
|
||||
// these are here for core debugging mode
|
||||
static unsigned int m68k_read_8 (unsigned int a, int do_fake)
|
||||
{
|
||||
a&=0xffffff;
|
||||
if(a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k) return *(u8 *)(Pico.rom+(a^1)); // Rom
|
||||
#ifdef EMU_CORE_DEBUG
|
||||
if(do_fake&&((ppop&0x3f)==0x3a||(ppop&0x3f)==0x3b)) return lastread_d[lrp_mus++&15];
|
||||
#endif
|
||||
return pm68k_read_memory_pcr_8(a);
|
||||
}
|
||||
static unsigned int m68k_read_16(unsigned int a, int do_fake)
|
||||
{
|
||||
a&=0xffffff;
|
||||
if(a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k) return *(u16 *)(Pico.rom+(a&~1)); // Rom
|
||||
#ifdef EMU_CORE_DEBUG
|
||||
if(do_fake&&((ppop&0x3f)==0x3a||(ppop&0x3f)==0x3b)) return lastread_d[lrp_mus++&15];
|
||||
#endif
|
||||
return pm68k_read_memory_pcr_16(a);
|
||||
}
|
||||
static unsigned int m68k_read_32(unsigned int a, int do_fake)
|
||||
{
|
||||
a&=0xffffff;
|
||||
if(a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k) { u16 *pm=(u16 *)(Pico.rom+(a&~1)); return (pm[0]<<16)|pm[1]; }
|
||||
#ifdef EMU_CORE_DEBUG
|
||||
if(do_fake&&((ppop&0x3f)==0x3a||(ppop&0x3f)==0x3b)) return lastread_d[lrp_mus++&15];
|
||||
#endif
|
||||
return pm68k_read_memory_pcr_32(a);
|
||||
}
|
||||
|
||||
unsigned int m68k_read_pcrelative_8 (unsigned int a) { return m68k_read_8 (a, 1); }
|
||||
unsigned int m68k_read_pcrelative_16(unsigned int a) { return m68k_read_16(a, 1); }
|
||||
unsigned int m68k_read_pcrelative_32(unsigned int a) { return m68k_read_32(a, 1); }
|
||||
unsigned int m68k_read_immediate_16(unsigned int a) { return m68k_read_16(a, 0); }
|
||||
unsigned int m68k_read_immediate_32(unsigned int a) { return m68k_read_32(a, 0); }
|
||||
unsigned int m68k_read_disassembler_8 (unsigned int a) { return m68k_read_8 (a, 0); }
|
||||
unsigned int m68k_read_disassembler_16(unsigned int a) { return m68k_read_16(a, 0); }
|
||||
unsigned int m68k_read_disassembler_32(unsigned int a) { return m68k_read_32(a, 0); }
|
||||
|
||||
static unsigned int m68k_read_memory_pcr_8(unsigned int a)
|
||||
{
|
||||
if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int m68k_read_memory_pcr_16(unsigned int a)
|
||||
{
|
||||
if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int m68k_read_memory_pcr_32(unsigned int a)
|
||||
{
|
||||
if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef EMU_CORE_DEBUG
|
||||
// ROM only
|
||||
unsigned int m68k_read_memory_8(unsigned int a)
|
||||
{
|
||||
u8 d;
|
||||
if (a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k)
|
||||
d = *(u8 *) (Pico.rom+(a^1));
|
||||
else d = (u8) lastread_d[lrp_mus++&15];
|
||||
elprintf(EL_IO, "r8_mu : %06x, %02x @%06x", a&0xffffff, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
unsigned int m68k_read_memory_16(unsigned int a)
|
||||
{
|
||||
u16 d;
|
||||
if (a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k)
|
||||
d = *(u16 *)(Pico.rom+(a&~1));
|
||||
else d = (u16) lastread_d[lrp_mus++&15];
|
||||
elprintf(EL_IO, "r16_mu: %06x, %04x @%06x", a&0xffffff, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
unsigned int m68k_read_memory_32(unsigned int a)
|
||||
{
|
||||
u32 d;
|
||||
if (a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k)
|
||||
{ u16 *pm=(u16 *)(Pico.rom+(a&~1));d=(pm[0]<<16)|pm[1]; }
|
||||
else if (a <= 0x78) d = m68k_read_32(a, 0);
|
||||
else d = lastread_d[lrp_mus++&15];
|
||||
elprintf(EL_IO, "r32_mu: %06x, %08x @%06x", a&0xffffff, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
|
||||
// ignore writes, Cyclone already done that
|
||||
void m68k_write_memory_8(unsigned int address, unsigned int value) { lastwrite_mus_d[lwp_mus++&15] = value; }
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value) { lastwrite_mus_d[lwp_mus++&15] = value; }
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value) { lastwrite_mus_d[lwp_mus++&15] = value; }
|
||||
|
||||
#else // if !EMU_CORE_DEBUG
|
||||
|
||||
/* it appears that Musashi doesn't always mask the unused bits */
|
||||
unsigned int m68k_read_memory_8 (unsigned int address) { return pm68k_read_memory_8 (address) & 0xff; }
|
||||
|
@ -962,7 +837,6 @@ unsigned int m68k_read_memory_32(unsigned int address) { return pm68k_read_memor
|
|||
void m68k_write_memory_8 (unsigned int address, unsigned int value) { pm68k_write_memory_8 (address, (u8)value); }
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value) { pm68k_write_memory_16(address,(u16)value); }
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value) { pm68k_write_memory_32(address, value); }
|
||||
#endif // !EMU_CORE_DEBUG
|
||||
|
||||
static void m68k_mem_setup(void)
|
||||
{
|
||||
|
@ -972,9 +846,6 @@ static void m68k_mem_setup(void)
|
|||
pm68k_write_memory_8 = m68k_write8;
|
||||
pm68k_write_memory_16 = m68k_write16;
|
||||
pm68k_write_memory_32 = m68k_write32;
|
||||
pm68k_read_memory_pcr_8 = m68k_read_memory_pcr_8;
|
||||
pm68k_read_memory_pcr_16 = m68k_read_memory_pcr_16;
|
||||
pm68k_read_memory_pcr_32 = m68k_read_memory_pcr_32;
|
||||
}
|
||||
#endif // EMU_M68K
|
||||
|
||||
|
@ -1286,15 +1157,8 @@ static unsigned char MEMH_FUNC z80_md_bank_read(unsigned short a)
|
|||
addr68k = Pico.m.z80_bank68k<<15;
|
||||
addr68k += a & 0x7fff;
|
||||
|
||||
if (addr68k < Pico.romsize) {
|
||||
ret = Pico.rom[addr68k^1];
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = m68k_read8(addr68k);
|
||||
elprintf(EL_ANOMALY, "z80->68k upper read [%06x] %02x", addr68k, ret);
|
||||
|
||||
out:
|
||||
elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ typedef unsigned short u16;
|
|||
typedef unsigned int u32;
|
||||
|
||||
#define M68K_MEM_SHIFT 16
|
||||
// minimum size we can map
|
||||
#define M68K_BANK_SIZE (1 << M68K_MEM_SHIFT)
|
||||
#define M68K_BANK_MASK (M68K_BANK_SIZE - 1)
|
||||
|
||||
extern unsigned long m68k_read8_map [0x1000000 >> M68K_MEM_SHIFT];
|
||||
extern unsigned long m68k_read16_map [0x1000000 >> M68K_MEM_SHIFT];
|
||||
|
|
187
pico/misc.c
187
pico/misc.c
|
@ -86,193 +86,6 @@ const unsigned char hcounts_32[] = {
|
|||
};
|
||||
|
||||
|
||||
// rarely used EEPROM SRAM code
|
||||
// known games which use this:
|
||||
// Wonder Boy in Monster World, Megaman - The Wily Wars (X24C01, 128 bytes)
|
||||
|
||||
// (see Genesis Plus for Wii/GC code and docs for info,
|
||||
// full game list and better code).
|
||||
|
||||
unsigned int lastSSRamWrite = 0xffff0000;
|
||||
|
||||
// sram_status: LAtd sela (L=pending SCL, A=pending SDA, t=(unused),
|
||||
// d=SRAM was detected (header or by access), s=started, e=save is EEPROM, l=old SCL, a=old SDA)
|
||||
PICO_INTERNAL void EEPROM_write(unsigned int d) // ???? ??la (l=SCL, a=SDA)
|
||||
{
|
||||
unsigned int sreg = Pico.m.sram_status, saddr = Pico.m.eeprom_addr, scyc = Pico.m.eeprom_cycle, ssa = Pico.m.eeprom_slave;
|
||||
|
||||
elprintf(EL_EEPROM, "eeprom: scl/sda: %i/%i -> %i/%i, newtime=%i", (sreg&2)>>1, sreg&1,
|
||||
(d&2)>>1, d&1, SekCyclesDoneT()-lastSSRamWrite);
|
||||
saddr&=0x1fff;
|
||||
|
||||
if(sreg & d & 2) {
|
||||
// SCL was and is still high..
|
||||
if((sreg & 1) && !(d&1)) {
|
||||
// ..and SDA went low, means it's a start command, so clear internal addr reg and clock counter
|
||||
elprintf(EL_EEPROM, "eeprom: -start-");
|
||||
//saddr = 0;
|
||||
scyc = 0;
|
||||
sreg |= 8;
|
||||
} else if(!(sreg & 1) && (d&1)) {
|
||||
// SDA went high == stop command
|
||||
elprintf(EL_EEPROM, "eeprom: -stop-");
|
||||
sreg &= ~8;
|
||||
}
|
||||
}
|
||||
else if((sreg & 8) && !(sreg & 2) && (d&2))
|
||||
{
|
||||
// we are started and SCL went high - next cycle
|
||||
scyc++; // pre-increment
|
||||
if(SRam.eeprom_type) {
|
||||
// X24C02+
|
||||
if((ssa&1) && scyc == 18) {
|
||||
scyc = 9;
|
||||
saddr++; // next address in read mode
|
||||
/*if(SRam.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask
|
||||
}
|
||||
else if(SRam.eeprom_type == 2 && scyc == 27) scyc = 18;
|
||||
else if(scyc == 36) scyc = 27;
|
||||
} else {
|
||||
// X24C01
|
||||
if(scyc == 18) {
|
||||
scyc = 9; // wrap
|
||||
if(saddr&1) { saddr+=2; saddr&=0xff; } // next addr in read mode
|
||||
}
|
||||
}
|
||||
elprintf(EL_EEPROM, "eeprom: scyc: %i", scyc);
|
||||
}
|
||||
else if((sreg & 8) && (sreg & 2) && !(d&2))
|
||||
{
|
||||
// we are started and SCL went low (falling edge)
|
||||
if(SRam.eeprom_type) {
|
||||
// X24C02+
|
||||
if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles
|
||||
else if( (SRam.eeprom_type == 3 && scyc > 27) || (SRam.eeprom_type == 2 && scyc > 18) ) {
|
||||
if(!(ssa&1)) {
|
||||
// data write
|
||||
unsigned char *pm=SRam.data+saddr;
|
||||
*pm <<= 1; *pm |= d&1;
|
||||
if(scyc == 26 || scyc == 35) {
|
||||
saddr=(saddr&~0xf)|((saddr+1)&0xf); // only 4 (?) lowest bits are incremented
|
||||
elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr, *pm);
|
||||
}
|
||||
SRam.changed = 1;
|
||||
}
|
||||
} else if(scyc > 9) {
|
||||
if(!(ssa&1)) {
|
||||
// we latch another addr bit
|
||||
saddr<<=1;
|
||||
if(SRam.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask
|
||||
saddr|=d&1;
|
||||
if(scyc==17||scyc==26) {
|
||||
elprintf(EL_EEPROM, "eeprom: addr reg done: %x", saddr);
|
||||
if(scyc==17&&SRam.eeprom_type==2) { saddr&=0xff; saddr|=(ssa<<7)&0x700; } // add device bits too
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// slave address
|
||||
ssa<<=1; ssa|=d&1;
|
||||
if(scyc==8) elprintf(EL_EEPROM, "eeprom: slave done: %x", ssa);
|
||||
}
|
||||
} else {
|
||||
// X24C01
|
||||
if(scyc == 9); // ACK cycle, do nothing
|
||||
else if(scyc > 9) {
|
||||
if(!(saddr&1)) {
|
||||
// data write
|
||||
unsigned char *pm=SRam.data+(saddr>>1);
|
||||
*pm <<= 1; *pm |= d&1;
|
||||
if(scyc == 17) {
|
||||
saddr=(saddr&0xf9)|((saddr+2)&6); // only 2 lowest bits are incremented
|
||||
elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr>>1, *pm);
|
||||
}
|
||||
SRam.changed = 1;
|
||||
}
|
||||
} else {
|
||||
// we latch another addr bit
|
||||
saddr<<=1; saddr|=d&1; saddr&=0xff;
|
||||
if(scyc==8) elprintf(EL_EEPROM, "eeprom: addr done: %x", saddr>>1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sreg &= ~3; sreg |= d&3; // remember SCL and SDA
|
||||
Pico.m.sram_status = (unsigned char) sreg;
|
||||
Pico.m.eeprom_cycle= (unsigned char) scyc;
|
||||
Pico.m.eeprom_slave= (unsigned char) ssa;
|
||||
Pico.m.eeprom_addr = (unsigned short)saddr;
|
||||
}
|
||||
|
||||
PICO_INTERNAL_ASM unsigned int EEPROM_read(void)
|
||||
{
|
||||
unsigned int shift, d;
|
||||
unsigned int sreg, saddr, scyc, ssa, interval;
|
||||
|
||||
// flush last pending write
|
||||
EEPROM_write(Pico.m.sram_status>>6);
|
||||
|
||||
sreg = Pico.m.sram_status; saddr = Pico.m.eeprom_addr&0x1fff; scyc = Pico.m.eeprom_cycle; ssa = Pico.m.eeprom_slave;
|
||||
interval = SekCyclesDoneT()-lastSSRamWrite;
|
||||
d = (sreg>>6)&1; // use SDA as "open bus"
|
||||
|
||||
// NBA Jam is nasty enough to read <before> raising the SCL and starting the new cycle.
|
||||
// this is probably valid because data changes occur while SCL is low and data can be read
|
||||
// before it's actual cycle begins.
|
||||
if (!(sreg&0x80) && interval >= 24) {
|
||||
elprintf(EL_EEPROM, "eeprom: early read, cycles=%i", interval);
|
||||
scyc++;
|
||||
}
|
||||
|
||||
if (!(sreg & 8)); // not started, use open bus
|
||||
else if (scyc == 9 || scyc == 18 || scyc == 27) {
|
||||
elprintf(EL_EEPROM, "eeprom: r ack");
|
||||
d = 0;
|
||||
} else if (scyc > 9 && scyc < 18) {
|
||||
// started and first command word received
|
||||
shift = 17-scyc;
|
||||
if (SRam.eeprom_type) {
|
||||
// X24C02+
|
||||
if (ssa&1) {
|
||||
elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg);
|
||||
if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr]);
|
||||
d = (SRam.data[saddr]>>shift)&1;
|
||||
}
|
||||
} else {
|
||||
// X24C01
|
||||
if (saddr&1) {
|
||||
elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr>>1, scyc, sreg);
|
||||
if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr>>1]);
|
||||
d = (SRam.data[saddr>>1]>>shift)&1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (d << SRam.eeprom_bit_out);
|
||||
}
|
||||
|
||||
PICO_INTERNAL void EEPROM_upd_pending(unsigned int a, unsigned int d)
|
||||
{
|
||||
unsigned int d1, sreg = Pico.m.sram_status;
|
||||
|
||||
if (!((SRam.eeprom_abits^a)&1))
|
||||
{
|
||||
// SCL
|
||||
sreg &= ~0x80;
|
||||
d1 = (d >> SRam.eeprom_bit_cl) & 1;
|
||||
sreg |= d1<<7;
|
||||
}
|
||||
if (!(((SRam.eeprom_abits>>1)^a)&1))
|
||||
{
|
||||
// SDA in
|
||||
sreg &= ~0x40;
|
||||
d1 = (d >> SRam.eeprom_bit_in) & 1;
|
||||
sreg |= d1<<6;
|
||||
}
|
||||
|
||||
Pico.m.sram_status = (unsigned char) sreg;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _ASM_MISC_C
|
||||
typedef struct
|
||||
{
|
||||
|
|
|
@ -213,12 +213,6 @@ unsigned int PicoRead16(unsigned int a);
|
|||
void PicoWrite16(unsigned int a, unsigned short d);
|
||||
|
||||
|
||||
/* avoid dependency on newer glibc */
|
||||
static int isspace_(int c)
|
||||
{
|
||||
return (0x09 <= c && c <= 0x0d) || c == ' ';
|
||||
}
|
||||
|
||||
void PicoPatchUnload(void)
|
||||
{
|
||||
if (PicoPatches != NULL)
|
||||
|
|
21
pico/pico.c
21
pico/pico.c
|
@ -40,8 +40,6 @@ void PicoInit(void)
|
|||
|
||||
PicoInitMCD();
|
||||
PicoSVPInit();
|
||||
|
||||
SRam.data=0;
|
||||
}
|
||||
|
||||
// to be called once on emu exit
|
||||
|
@ -52,13 +50,12 @@ void PicoExit(void)
|
|||
PicoCartUnload();
|
||||
z80_exit();
|
||||
|
||||
if (SRam.data) free(SRam.data); SRam.data=0;
|
||||
if (SRam.data)
|
||||
free(SRam.data);
|
||||
}
|
||||
|
||||
void PicoPower(void)
|
||||
{
|
||||
unsigned char sram_status = Pico.m.sram_status; // must be preserved
|
||||
|
||||
Pico.m.frame_count = 0;
|
||||
|
||||
// clear all memory of the emulated machine
|
||||
|
@ -78,7 +75,6 @@ void PicoPower(void)
|
|||
if (PicoAHW & PAHW_MCD)
|
||||
PicoPowerMCD();
|
||||
|
||||
Pico.m.sram_status = sram_status;
|
||||
PicoReset();
|
||||
}
|
||||
|
||||
|
@ -141,8 +137,6 @@ PICO_INTERNAL void PicoDetectRegion(void)
|
|||
|
||||
int PicoReset(void)
|
||||
{
|
||||
unsigned char sram_status = Pico.m.sram_status; // must be preserved
|
||||
|
||||
if (Pico.romsize <= 0)
|
||||
return 1;
|
||||
|
||||
|
@ -194,12 +188,13 @@ int PicoReset(void)
|
|||
SekInitIdleDet();
|
||||
|
||||
// reset sram state; enable sram access by default if it doesn't overlap with ROM
|
||||
Pico.m.sram_status = sram_status & (SRS_DETECTED|SRS_EEPROM);
|
||||
if (!(Pico.m.sram_status & SRS_EEPROM) && Pico.romsize <= SRam.start)
|
||||
Pico.m.sram_status |= SRS_MAPPED;
|
||||
Pico.m.sram_reg = 0;
|
||||
if ((SRam.flags & SRF_EEPROM) || Pico.romsize <= SRam.start)
|
||||
Pico.m.sram_reg |= SRR_MAPPED;
|
||||
|
||||
elprintf(EL_STATUS, "sram: det: %i; eeprom: %i; start: %06x; end: %06x",
|
||||
!!(sram_status & SRS_DETECTED), !!(sram_status & SRS_EEPROM), SRam.start, SRam.end);
|
||||
if (SRam.flags & SRF_ENABLED)
|
||||
elprintf(EL_STATUS, "sram: %06x - %06x; eeprom: %i", SRam.start, SRam.end,
|
||||
!!(SRam.flags & SRF_EEPROM));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,32 +1,28 @@
|
|||
#include "../pico_int.h"
|
||||
#include "../memory.h"
|
||||
#include "../sound/sn76496.h"
|
||||
|
||||
#ifndef UTYPES_DEFINED
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
#define UTYPES_DEFINED
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Read Rom and read Ram
|
||||
|
||||
static u32 PicoReadPico8(u32 a)
|
||||
/*
|
||||
void dump(u16 w)
|
||||
{
|
||||
u32 d=0;
|
||||
static FILE *f[0x10] = { NULL, };
|
||||
char fname[32];
|
||||
int num = PicoPicohw.r12 & 0xf;
|
||||
|
||||
if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram
|
||||
if (a<Pico.romsize) { d = *(u8 *)(Pico.rom+(a^1)); goto end; } // Rom
|
||||
w = (w << 8) | (w >> 8);
|
||||
sprintf(fname, "ldump%i.bin", num);
|
||||
if (f[num] == NULL)
|
||||
f[num] = fopen(fname, "wb");
|
||||
fwrite(&w, 1, 2, f[num]);
|
||||
//fclose(f);
|
||||
}
|
||||
*/
|
||||
|
||||
a&=0xffffff;
|
||||
static u32 PicoRead8_pico(u32 a)
|
||||
{
|
||||
u32 d = 0;
|
||||
|
||||
if ((a&0xfffff0)==0xc00000) { // VDP
|
||||
d=PicoVideoRead8(a);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((a&0xffffe0)==0x800000) // Pico I/O
|
||||
if ((a & 0xffffe0) == 0x800000) // Pico I/O
|
||||
{
|
||||
switch (a & 0x1f)
|
||||
{
|
||||
|
@ -44,120 +40,42 @@ static u32 PicoReadPico8(u32 a)
|
|||
case 0x0d: d = (1 << (PicoPicohw.page & 7)) - 1; break;
|
||||
case 0x12: d = PicoPicohw.fifo_bytes == 0 ? 0x80 : 0; break; // guess
|
||||
default:
|
||||
elprintf(EL_UIO, "r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPc);
|
||||
break;
|
||||
goto unhandled;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
//elprintf(EL_UIO, "r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPc);
|
||||
|
||||
end:
|
||||
elprintf(EL_IO, "r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPc);
|
||||
unhandled:
|
||||
elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc);
|
||||
return d;
|
||||
}
|
||||
|
||||
static u32 PicoReadPico16(u32 a)
|
||||
static u32 PicoRead16_pico(u32 a)
|
||||
{
|
||||
u32 d=0;
|
||||
|
||||
if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram
|
||||
|
||||
a&=0xfffffe;
|
||||
|
||||
if (a<Pico.romsize) { d = *(u16 *)(Pico.rom+a); goto end; } // Rom
|
||||
|
||||
if ((a&0xfffff0)==0xc00000) {
|
||||
d = PicoVideoRead(a);
|
||||
goto end;
|
||||
}
|
||||
u32 d = 0;
|
||||
|
||||
if (a == 0x800010)
|
||||
d = (PicoPicohw.fifo_bytes > 0x3f) ? 0 : (0x3f - PicoPicohw.fifo_bytes);
|
||||
else if (a == 0x800012)
|
||||
d = PicoPicohw.fifo_bytes == 0 ? 0x8000 : 0; // guess
|
||||
else
|
||||
elprintf(EL_UIO, "r16: %06x, %04x @%06x", a&0xffffff, d, SekPc);
|
||||
elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
|
||||
|
||||
//elprintf(EL_UIO, "r16: %06x, %04x @%06x", a&0xffffff, d, SekPc);
|
||||
|
||||
end:
|
||||
elprintf(EL_IO, "r16: %06x, %04x @%06x", a&0xffffff, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
|
||||
static u32 PicoReadPico32(u32 a)
|
||||
static void PicoWrite8_pico(u32 a, u32 d)
|
||||
{
|
||||
u32 d=0;
|
||||
|
||||
if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); d = (pm[0]<<16)|pm[1]; goto end; } // Ram
|
||||
|
||||
a&=0xfffffe;
|
||||
|
||||
if (a<Pico.romsize) { u16 *pm=(u16 *)(Pico.rom+a); d = (pm[0]<<16)|pm[1]; goto end; } // Rom
|
||||
|
||||
if ((a&0xfffff0)==0xc00000) {
|
||||
d = (PicoVideoRead(a)<<16)|PicoVideoRead(a+2);
|
||||
goto end;
|
||||
}
|
||||
|
||||
elprintf(EL_UIO, "r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);
|
||||
|
||||
end:
|
||||
elprintf(EL_IO, "r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);
|
||||
return d;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Write Ram
|
||||
/*
|
||||
void dump(u16 w)
|
||||
{
|
||||
static FILE *f[0x10] = { NULL, };
|
||||
char fname[32];
|
||||
int num = PicoPicohw.r12 & 0xf;
|
||||
|
||||
w = (w << 8) | (w >> 8);
|
||||
sprintf(fname, "ldump%i.bin", num);
|
||||
if (f[num] == NULL)
|
||||
f[num] = fopen(fname, "wb");
|
||||
fwrite(&w, 1, 2, f[num]);
|
||||
//fclose(f);
|
||||
}
|
||||
*/
|
||||
|
||||
static void PicoWritePico8(u32 a,u8 d)
|
||||
{
|
||||
elprintf(EL_IO, "w8 : %06x, %02x @%06x", a&0xffffff, d, SekPc);
|
||||
|
||||
if ((a&0xe00000)==0xe00000) { *(u8 *)(Pico.ram+((a^1)&0xffff))=d; return; } // Ram
|
||||
|
||||
a&=0xffffff;
|
||||
if ((a&0xfffff9)==0xc00011) { if (PicoOpt&2) SN76496Write(d); return; } // PSG Sound
|
||||
|
||||
if ((a&0xfffff0)==0xc00000) { // VDP
|
||||
d&=0xff;
|
||||
PicoVideoWrite(a,(u16)(d|(d<<8))); // Byte access gets mirrored
|
||||
return;
|
||||
}
|
||||
|
||||
switch (a & 0x1f) {
|
||||
switch (a & ~0x800000) {
|
||||
case 0x19: case 0x1b: case 0x1d: case 0x1f: break; // 'S' 'E' 'G' 'A'
|
||||
default:
|
||||
elprintf(EL_UIO, "w8 : %06x, %02x @%06x", a&0xffffff, d, SekPc);
|
||||
elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
|
||||
break;
|
||||
}
|
||||
//elprintf(EL_UIO, "w8 : %06x, %02x @%06x", a&0xffffff, d, SekPc);
|
||||
}
|
||||
|
||||
static void PicoWritePico16(u32 a,u16 d)
|
||||
static void PicoWrite16_pico(u32 a, u32 d)
|
||||
{
|
||||
elprintf(EL_IO, "w16: %06x, %04x", a&0xffffff, d);
|
||||
|
||||
if ((a&0xe00000)==0xe00000) { *(u16 *)(Pico.ram+(a&0xfffe))=d; return; } // Ram
|
||||
|
||||
a&=0xfffffe;
|
||||
if ((a&0xfffff0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; } // VDP
|
||||
|
||||
//if (a == 0x800010) dump(d);
|
||||
if (a == 0x800010)
|
||||
{
|
||||
|
@ -179,97 +97,21 @@ static void PicoWritePico16(u32 a,u16 d)
|
|||
PicoReratePico();
|
||||
}
|
||||
else
|
||||
elprintf(EL_UIO, "w16: %06x, %04x", a&0xffffff, d);
|
||||
|
||||
//elprintf(EL_UIO, "w16: %06x, %04x", a&0xffffff, d);
|
||||
elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
|
||||
}
|
||||
|
||||
static void PicoWritePico32(u32 a,u32 d)
|
||||
{
|
||||
elprintf(EL_IO, "w32: %06x, %08x", a&0xffffff, d);
|
||||
|
||||
if ((a&0xe00000)==0xe00000)
|
||||
{
|
||||
// Ram:
|
||||
u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));
|
||||
pm[0]=(u16)(d>>16); pm[1]=(u16)d;
|
||||
return;
|
||||
}
|
||||
|
||||
a&=0xfffffe;
|
||||
if ((a&0xfffff0)==0xc00000)
|
||||
{
|
||||
// VDP:
|
||||
PicoVideoWrite(a, (u16)(d>>16));
|
||||
PicoVideoWrite(a+2,(u16)d);
|
||||
return;
|
||||
}
|
||||
|
||||
elprintf(EL_UIO, "w32: %06x, %08x", a&0xffffff, d);
|
||||
}
|
||||
|
||||
#ifdef EMU_M68K
|
||||
extern unsigned int (*pm68k_read_memory_8) (unsigned int address);
|
||||
extern unsigned int (*pm68k_read_memory_16)(unsigned int address);
|
||||
extern unsigned int (*pm68k_read_memory_32)(unsigned int address);
|
||||
extern void (*pm68k_write_memory_8) (unsigned int address, unsigned char value);
|
||||
extern void (*pm68k_write_memory_16)(unsigned int address, unsigned short value);
|
||||
extern void (*pm68k_write_memory_32)(unsigned int address, unsigned int value);
|
||||
extern unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address);
|
||||
extern unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address);
|
||||
extern unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address);
|
||||
|
||||
static unsigned int m68k_read_memory_pcrp_8(unsigned int a)
|
||||
{
|
||||
if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int m68k_read_memory_pcrp_16(unsigned int a)
|
||||
{
|
||||
if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int m68k_read_memory_pcrp_32(unsigned int a)
|
||||
{
|
||||
if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram
|
||||
return 0;
|
||||
}
|
||||
#endif // EMU_M68K
|
||||
|
||||
|
||||
PICO_INTERNAL void PicoMemSetupPico(void)
|
||||
{
|
||||
#ifdef EMU_C68K
|
||||
PicoCpuCM68k.checkpc=PicoCheckPc;
|
||||
PicoCpuCM68k.fetch8 =PicoCpuCM68k.read8 =PicoReadPico8;
|
||||
PicoCpuCM68k.fetch16=PicoCpuCM68k.read16=PicoReadPico16;
|
||||
PicoCpuCM68k.fetch32=PicoCpuCM68k.read32=PicoReadPico32;
|
||||
PicoCpuCM68k.write8 =PicoWritePico8;
|
||||
PicoCpuCM68k.write16=PicoWritePico16;
|
||||
PicoCpuCM68k.write32=PicoWritePico32;
|
||||
#endif
|
||||
#ifdef EMU_M68K
|
||||
pm68k_read_memory_8 = PicoReadPico8;
|
||||
pm68k_read_memory_16 = PicoReadPico16;
|
||||
pm68k_read_memory_32 = PicoReadPico32;
|
||||
pm68k_write_memory_8 = PicoWritePico8;
|
||||
pm68k_write_memory_16 = PicoWritePico16;
|
||||
pm68k_write_memory_32 = PicoWritePico32;
|
||||
pm68k_read_memory_pcr_8 = m68k_read_memory_pcrp_8;
|
||||
pm68k_read_memory_pcr_16 = m68k_read_memory_pcrp_16;
|
||||
pm68k_read_memory_pcr_32 = m68k_read_memory_pcrp_32;
|
||||
#endif
|
||||
#ifdef EMU_F68K
|
||||
// use standard setup, only override handlers
|
||||
PicoMemSetup();
|
||||
PicoCpuFM68k.read_byte =PicoReadPico8;
|
||||
PicoCpuFM68k.read_word =PicoReadPico16;
|
||||
PicoCpuFM68k.read_long =PicoReadPico32;
|
||||
PicoCpuFM68k.write_byte=PicoWritePico8;
|
||||
PicoCpuFM68k.write_word=PicoWritePico16;
|
||||
PicoCpuFM68k.write_long=PicoWritePico32;
|
||||
#endif
|
||||
|
||||
// no MD IO or Z80 on Pico
|
||||
m68k_map_unmap(0x400000, 0xbfffff);
|
||||
|
||||
// map Pico I/O
|
||||
cpu68k_map_set(m68k_read8_map, 0x800000, 0x80ffff, PicoRead8_pico, 1);
|
||||
cpu68k_map_set(m68k_read16_map, 0x800000, 0x80ffff, PicoRead16_pico, 1);
|
||||
cpu68k_map_set(m68k_write8_map, 0x800000, 0x80ffff, PicoWrite8_pico, 1);
|
||||
cpu68k_map_set(m68k_write16_map, 0x800000, 0x80ffff, PicoWrite16_pico, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ static void PicoResetPico(void)
|
|||
|
||||
PICO_INTERNAL void PicoInitPico(void)
|
||||
{
|
||||
elprintf(EL_STATUS, "Pico detected");
|
||||
elprintf(EL_STATUS, "Pico startup");
|
||||
PicoLineHook = PicoLinePico;
|
||||
PicoResetHook = PicoResetPico;
|
||||
|
||||
|
|
|
@ -255,18 +255,19 @@ struct PicoMisc
|
|||
char dirtyPal; // 06 Is the palette dirty (1 - change @ this frame, 2 - some time before)
|
||||
unsigned char hardware; // 07 Hardware value for country
|
||||
unsigned char pal; // 08 1=PAL 0=NTSC
|
||||
unsigned char sram_status; // 09 SRAM status. See SRS_* below
|
||||
unsigned char sram_reg; // 09 SRAM reg. See SRR_* below
|
||||
unsigned short z80_bank68k; // 0a
|
||||
unsigned short z80_lastaddr; // this is for Z80 faking
|
||||
unsigned char z80_fakeval;
|
||||
unsigned char pad0;
|
||||
unsigned char z80_reset; // z80 reset held
|
||||
unsigned char padDelay[2]; // 10 gamepad phase time outs, so we count a delay
|
||||
unsigned short eeprom_addr; // EEPROM address register
|
||||
unsigned char eeprom_cycle; // EEPROM SRAM cycle number
|
||||
unsigned char eeprom_cycle; // EEPROM cycle number
|
||||
unsigned char eeprom_slave; // EEPROM slave word for X24C02 and better SRAMs
|
||||
unsigned char prot_bytes[2]; // simple protection faking
|
||||
unsigned char eeprom_status;
|
||||
unsigned char pad1;
|
||||
unsigned short dma_xfers; // 18
|
||||
unsigned char pad[2];
|
||||
unsigned char eeprom_wb[2]; // EEPROM latch/write buffer
|
||||
unsigned int frame_count; // 1c for movies and idle det
|
||||
};
|
||||
|
||||
|
@ -293,24 +294,26 @@ struct Pico
|
|||
};
|
||||
|
||||
// sram
|
||||
#define SRS_MAPPED (1 << 0)
|
||||
#define SRS_READONLY (1 << 1)
|
||||
#define SRS_EEPROM (1 << 2)
|
||||
#define SRS_DETECTED (1 << 4)
|
||||
#define SRR_MAPPED (1 << 0)
|
||||
#define SRR_READONLY (1 << 1)
|
||||
|
||||
#define SRF_ENABLED (1 << 0)
|
||||
#define SRF_EEPROM (1 << 1)
|
||||
|
||||
struct PicoSRAM
|
||||
{
|
||||
unsigned char *data; // actual data
|
||||
unsigned int start; // start address in 68k address space
|
||||
unsigned int end;
|
||||
unsigned char unused1; // 0c: unused
|
||||
unsigned char flags; // 0c: SRF_*
|
||||
unsigned char unused2;
|
||||
unsigned char changed;
|
||||
unsigned char eeprom_type; // eeprom type: 0: 7bit (24C01), 2: device with 2 addr words (X24C02+), 3: dev with 3 addr words
|
||||
unsigned char eeprom_abits; // eeprom access must be odd addr for: bit0 ~ cl, bit1 ~ out
|
||||
unsigned char eeprom_type; // eeprom type: 0: 7bit (24C01), 2: 2 addr words (X24C02+), 3: 3 addr words
|
||||
unsigned char unused3;
|
||||
unsigned char eeprom_bit_cl; // bit number for cl
|
||||
unsigned char eeprom_bit_in; // bit number for in
|
||||
unsigned char eeprom_bit_out; // bit number for out
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
// MCD
|
||||
|
@ -414,6 +417,7 @@ extern areaseek *areaSeek;
|
|||
extern areaclose *areaClose;
|
||||
|
||||
// cart.c
|
||||
extern void (*PicoCartMemSetup)(void);
|
||||
extern void (*PicoCartUnloadHook)(void);
|
||||
|
||||
// debug.c
|
||||
|
@ -441,10 +445,6 @@ void PicoDrawSetColorFormatMode4(int which);
|
|||
PICO_INTERNAL void PicoInitPc(unsigned int pc);
|
||||
PICO_INTERNAL unsigned int PicoCheckPc(unsigned int pc);
|
||||
PICO_INTERNAL void PicoMemSetup(void);
|
||||
PICO_INTERNAL void PicoMemResetHooks(void);
|
||||
extern unsigned int (*PicoRead16Hook)(unsigned int a, int realsize);
|
||||
extern void (*PicoWrite8Hook) (unsigned int a,unsigned int d,int realsize);
|
||||
extern void (*PicoWrite16Hook)(unsigned int a,unsigned int d,int realsize);
|
||||
unsigned int PicoRead8_io(unsigned int a);
|
||||
unsigned int PicoRead16_io(unsigned int a);
|
||||
void PicoWrite8_io(unsigned int a, unsigned int d);
|
||||
|
@ -537,14 +537,16 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead8(unsigned int a);
|
|||
extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp);
|
||||
|
||||
// misc.c
|
||||
PICO_INTERNAL void EEPROM_write(unsigned int d);
|
||||
PICO_INTERNAL void EEPROM_upd_pending(unsigned int a, unsigned int d);
|
||||
PICO_INTERNAL_ASM unsigned int EEPROM_read(void);
|
||||
PICO_INTERNAL_ASM void memcpy16(unsigned short *dest, unsigned short *src, int count);
|
||||
PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count);
|
||||
PICO_INTERNAL_ASM void memcpy32(int *dest, int *src, int count); // 32bit word count
|
||||
PICO_INTERNAL_ASM void memset32(int *dest, int c, int count);
|
||||
|
||||
// eeprom.c
|
||||
void EEPROM_write8(unsigned int a, unsigned int d);
|
||||
void EEPROM_write16(unsigned int d);
|
||||
unsigned int EEPROM_read(void);
|
||||
|
||||
// z80 functionality wrappers
|
||||
PICO_INTERNAL void z80_init(void);
|
||||
PICO_INTERNAL void z80_pack(unsigned char *data);
|
||||
|
@ -574,6 +576,12 @@ void PicoMemSetupMS(void);
|
|||
void PicoFrameMS(void);
|
||||
void PicoFrameDrawOnlyMS(void);
|
||||
|
||||
/* avoid dependency on newer glibc */
|
||||
static __inline int isspace_(int c)
|
||||
{
|
||||
return (0x09 <= c && c <= 0x0d) || c == ' ';
|
||||
}
|
||||
|
||||
// emulation event logging
|
||||
#ifndef EL_LOGMASK
|
||||
#define EL_LOGMASK 0
|
||||
|
|
|
@ -106,7 +106,6 @@ PICO_INTERNAL void z80_reset(void)
|
|||
Cz80_Set_Reg(&CZ80, CZ80_IY, 0xffff);
|
||||
Cz80_Set_Reg(&CZ80, CZ80_SP, 0x2000);
|
||||
#endif
|
||||
Pico.m.z80_fakeval = 0; // for faking when Z80 is disabled
|
||||
}
|
||||
|
||||
// XXX TODO: should better use universal z80 save format
|
||||
|
|
|
@ -977,7 +977,7 @@ int emu_save_load_game(int load, int sram)
|
|||
int truncate = 1;
|
||||
if (PicoAHW & PAHW_MCD)
|
||||
{
|
||||
if (PicoOpt&POPT_EN_MCD_RAMCART) {
|
||||
if (PicoOpt & POPT_EN_MCD_RAMCART) {
|
||||
sram_size = 0x12000;
|
||||
sram_data = SRam.data;
|
||||
if (sram_data)
|
||||
|
@ -988,9 +988,7 @@ int emu_save_load_game(int load, int sram)
|
|||
truncate = 0; // the .brm may contain RAM cart data after normal brm
|
||||
}
|
||||
} else {
|
||||
sram_size = SRam.end-SRam.start+1;
|
||||
if (Pico.m.sram_status & SRS_EEPROM)
|
||||
sram_size = 0x2000;
|
||||
sram_size = SRam.size;
|
||||
sram_data = SRam.data;
|
||||
}
|
||||
if (!sram_data) return 0; // SRam forcefully disabled for this game
|
||||
|
|
|
@ -170,7 +170,7 @@ static void blit(const char *fps, const char *notice)
|
|||
vidConvCpyRGB565(localPal, Pico.cram, 0x40);
|
||||
}
|
||||
// a hack for VR
|
||||
if (PicoRead16Hook == PicoSVPRead16)
|
||||
if (PicoAHW & PAHW_SVP)
|
||||
memset32((int *)(PicoDraw2FB+328*8+328*223), 0xe0e0e0e0, 328);
|
||||
if (!(Pico.video.reg[12]&1)) lines_flags|=0x10000;
|
||||
if (currentConfig.EmuOpt&0x4000)
|
||||
|
|
|
@ -64,8 +64,9 @@ OBJS += platform/common/emu.o platform/common/menu.o platform/common/fonts.o pla
|
|||
ifeq "$(amalgamate)" "1"
|
||||
OBJS += ../../picoAll.o
|
||||
else
|
||||
OBJS += pico/area.o pico/cart.o pico/memory.o pico/misc.o pico/pico.o pico/sek.o pico/z80if.o \
|
||||
pico/videoport.o pico/draw2.o pico/draw.o pico/mode4.o pico/sms.o pico/patch.o pico/debug.o
|
||||
OBJS += pico/area.o pico/cart.o pico/memory.o pico/pico.o pico/sek.o pico/z80if.o \
|
||||
pico/videoport.o pico/draw2.o pico/draw.o pico/mode4.o pico/sms.o \
|
||||
pico/misc.o pico/eeprom.o pico/patch.o pico/debug.o
|
||||
# Pico - CD
|
||||
OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \
|
||||
pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \
|
||||
|
|
|
@ -327,7 +327,7 @@ void pemu_update_display(const char *fps, const char *notice)
|
|||
gp2x_video_setpalette(localPal, ret);
|
||||
}
|
||||
// a hack for VR
|
||||
if (PicoRead16Hook == PicoSVPRead16)
|
||||
if (PicoAHW & PAHW_SVP)
|
||||
memset32((int *)(PicoDraw2FB+328*8+328*223), 0xe0e0e0e0, 328);
|
||||
// do actual copy
|
||||
vidcpyM2(g_screen_ptr, PicoDraw2FB+328*8,
|
||||
|
|
|
@ -32,9 +32,9 @@ OBJS += platform/gp2x/in_gp2x.o
|
|||
endif
|
||||
|
||||
# Pico
|
||||
OBJS += pico/area.o pico/cart.o pico/memory.o pico/misc.o pico/pico.o pico/sek.o \
|
||||
OBJS += pico/area.o pico/cart.o pico/memory.o pico/pico.o pico/sek.o \
|
||||
pico/videoport.o pico/draw2.o pico/draw.o pico/z80if.o pico/patch.o \
|
||||
pico/mode4.o pico/sms.o pico/debug.o
|
||||
pico/mode4.o pico/sms.o pico/misc.o pico/eeprom.o pico/debug.o
|
||||
# Pico - CD
|
||||
OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \
|
||||
pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \
|
||||
|
@ -55,7 +55,7 @@ OBJS += unzip/unzip.o unzip/unzip_stream.o
|
|||
ifeq "$(use_musashi)" "1"
|
||||
DEFINES += EMU_M68K
|
||||
OBJS += cpu/musashi/m68kops.o cpu/musashi/m68kcpu.o
|
||||
OBJS += cpu/musashi/m68kdasm.o
|
||||
#OBJS += cpu/musashi/m68kdasm.o
|
||||
endif
|
||||
ifeq "$(use_fame)" "1"
|
||||
DEFINES += EMU_F68K
|
||||
|
|
|
@ -425,6 +425,7 @@ void *gp2x_video_setpalette = gp2x_video_setpalette_;
|
|||
void *gp2x_video_RGB_setscaling = do_nothing;
|
||||
void *gp2x_video_wait_vsync = do_nothing;
|
||||
void *gp2x_set_cpuclk = do_nothing;
|
||||
void *gp2x_read_battery = do_nothing;
|
||||
void *set_lcd_custom_rate = do_nothing;
|
||||
void *unset_lcd_custom_rate = do_nothing;
|
||||
void *set_lcd_gamma = do_nothing;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define SIMPLE_WRITE_SOUND 0
|
||||
#define mix_32_to_16l_stereo_lvl mix_32_to_16l_stereo
|
||||
|
||||
#define EL_LOGMASK (EL_ANOMALY|EL_STATUS|EL_UIO|EL_IDLE)//|EL_VDPDMA|EL_HVCNT|EL_ASVDP)//|EL_SVP)
|
||||
#define EL_LOGMASK (EL_ANOMALY|EL_STATUS|EL_UIO|EL_IDLE|EL_SRAMIO|EL_EEPROM)//|EL_VDPDMA|EL_HVCNT|EL_ASVDP)//|EL_SVP)
|
||||
// EL_VDPDMA|EL_ASVDP|EL_SR) // |EL_BUSREQ|EL_Z80BNK)
|
||||
|
||||
//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)
|
||||
|
|
|
@ -253,7 +253,7 @@ static void blit(const char *fps, const char *notice)
|
|||
// gp2x_video_setpalette(localPal, 0x40);
|
||||
}
|
||||
// a hack for VR
|
||||
if (PicoRead16Hook == PicoSVPRead16)
|
||||
if (PicoAHW & PAHW_SVP)
|
||||
memset32((int *)(PicoDraw2FB+328*8+328*223), 0xe0e0e0e0, 328);
|
||||
// do actual copy
|
||||
vidCpyM2((unsigned char *)g_screen_ptr+g_screen_width*8, PicoDraw2FB+328*8);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue