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:
notaz 2009-09-05 21:13:30 +00:00
parent af37bca858
commit 45f2f245f5
30 changed files with 948 additions and 1027 deletions

View file

@ -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().

View file

@ -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)

View file

@ -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")

View file

@ -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.flags |= SRF_EEPROM;
SRam.flags |= SRF_ENABLED;
}
SRam.start &= ~0xff000000;
SRam.end &= ~0xff000000;
Pico.m.sram_status |= SRS_DETECTED;
}
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
View 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

View file

@ -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)
carthw_Xin1_do(a, 0x7e, 15);
return 0;
}
static void carthw_radica_mem_setup(void)
{
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);
return 0;
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;
PicoCartMemSetup = carthw_radica_mem_setup;
PicoResetHook = carthw_radica_reset;
PicoLoadStateHook = carthw_radica_statef;
carthw_chunks = carthw_radica_state;
carthw_chunks = carthw_Xin1_state;
}

View file

@ -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);

View file

@ -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 EL_LOGMASK & EL_SVP
{
static int a15004_looping = 0;
if (a == 0xa15004 && (d & 1))
a15004_looping = 0;
if (!a15004_looping)
elprintf(EL_SVP, "SVP r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
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;
else
a15004_looping = 0;
}
#endif
return d;
}
//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);
}

View file

@ -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());

View file

@ -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;

View file

@ -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

View file

@ -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
View 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);
}

View file

@ -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);
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
if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) {
m68k_unmapped_write8(a, d);
return;
}
elprintf(EL_SRAMIO, "sram w8 [%06x] %02x @ %06x", a, d & 0xff, SekPc);
if (SRam.flags & SRF_EEPROM)
{
// 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();
EEPROM_write8(a, d);
}
}
else if (!(srs & SRS_READONLY)) {
u8 *pm=(u8 *)(SRam.data - SRam.start + a);
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)
{
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..
PicoWrite8_sram(a + 1, d);
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-...
if ((SRam.flags & SRF_ENABLED) && SRam.data != NULL) {
rs = SRam.end - SRam.start;
if (rs > 0 && SRam.data != NULL) {
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;
}

View file

@ -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];

View file

@ -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
{

View file

@ -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)

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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 \

View file

@ -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,

View file

@ -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

View file

@ -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;

View file

@ -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__)

View file

@ -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);