* and m68k_read_pcrelative_xx() for PC-relative addressing.\r
* If off, all read requests from the CPU will be redirected to m68k_read_xx()\r
*/\r
-#define M68K_SEPARATE_READS OPT_ON\r
+#define M68K_SEPARATE_READS OPT_OFF\r
\r
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a\r
* predecrement destination EA mode instead of m68k_write_32().\r
FLAG_INT_MASK = int_level<<8;\r
\r
/* Get the new PC */\r
- //new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);\r
- new_pc = m68k_read_immediate_32((vector<<2) + REG_VBR); // notaz hack\r
+ new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);\r
+ //new_pc = m68k_read_immediate_32((vector<<2) + REG_VBR); // notaz hack\r
\r
/* If vector is uninitialized, call the uninitialized interrupt vector */\r
if(new_pc == 0)\r
SCAN_VAR(Pico.m ,"misc")\r
SCAN_VAR(Pico.video,"video")\r
\r
+ // no longer keeping eeprom data in sram_reg\r
+ if (!is_write && (Pico.m.sram_reg & 4))\r
+ Pico.m.sram_reg = SRR_MAPPED;\r
+\r
if (is_write)\r
z80_pack(cpu_z80);\r
ret = SCAN_VAR(cpu_z80,"cpu_z80")\r
\r
static const char *rom_exts[] = { "bin", "gen", "smd", "iso", "sms", "gg", "sg" };\r
\r
-void (*PicoCartUnloadHook)(void) = NULL;\r
+void (*PicoCartUnloadHook)(void);\r
+void (*PicoCartMemSetup)(void);\r
\r
void (*PicoCartLoadProgressCB)(int percent) = NULL;\r
void (*PicoCDLoadProgressCB)(const char *fname, int percent) = NULL; // handled in Pico/cd/cd_file.c\r
\r
PicoAHW &= PAHW_MCD|PAHW_SMS;\r
\r
- PicoMemResetHooks();\r
+ PicoCartMemSetup = NULL;\r
PicoDmaHook = NULL;\r
PicoResetHook = NULL;\r
PicoLineHook = NULL;\r
case PAHW_SMS: PicoMemSetupMS(); break;\r
}\r
\r
+ if (PicoCartMemSetup != NULL)\r
+ PicoCartMemSetup();\r
+\r
if (PicoAHW & PAHW_SMS)\r
PicoPowerMS();\r
else\r
static int rom_strcmp(int rom_offset, const char *s1)\r
{\r
int i, len = strlen(s1);\r
- const char *s_rom = (const char *)Pico.rom + rom_offset;\r
+ const char *s_rom = (const char *)Pico.rom;\r
for (i = 0; i < len; i++)\r
- if (s1[i] != s_rom[i^1])\r
+ if (s1[i] != s_rom[(i + rom_offset) ^ 1])\r
return 1;\r
return 0;\r
}\r
\r
-static int name_cmp(const char *name)\r
-{\r
- return rom_strcmp(0x150, name);\r
-}\r
-\r
static unsigned int rom_read32(int addr)\r
{\r
unsigned short *m = (unsigned short *)(Pico.rom + addr);\r
return (m[0] << 16) | m[1];\r
}\r
\r
+static char *sskip(char *s)\r
+{\r
+ while (*s && isspace_(*s))\r
+ s++;\r
+ return s;\r
+}\r
+\r
+static void rstrip(char *s)\r
+{\r
+ char *p;\r
+ for (p = s + strlen(s) - 1; p >= s; p--)\r
+ if (isspace_(*p))\r
+ *p = 0;\r
+}\r
+\r
+static int is_expr(const char *expr, char **pr)\r
+{\r
+ int len = strlen(expr);\r
+ char *p = *pr;\r
+\r
+ if (strncmp(expr, p, len) != 0)\r
+ return 0;\r
+ p = sskip(p + len);\r
+ if (*p != '=')\r
+ return 0; // wrong or malformed\r
+\r
+ *pr = sskip(p + 1);\r
+ return 1;\r
+}\r
+\r
+static void parse_carthw(int *fill_sram)\r
+{\r
+ int line = 0, any_checks_passed = 0, skip_sect = 0;\r
+ char buff[256], *p, *r;\r
+ FILE *f;\r
+\r
+ f = fopen("carthw.cfg", "r");\r
+ if (f == NULL) {\r
+ elprintf(EL_STATUS, "couldn't open carthw.txt!");\r
+ return;\r
+ }\r
+\r
+ while ((p = fgets(buff, sizeof(buff), f)))\r
+ {\r
+ line++;\r
+ p = sskip(p);\r
+ if (*p == 0 || *p == '#')\r
+ continue;\r
+\r
+ if (*p == '[') {\r
+ any_checks_passed = 0;\r
+ skip_sect = 0;\r
+ continue;\r
+ }\r
+ \r
+ if (skip_sect)\r
+ continue;\r
+\r
+ /* look for checks */\r
+ if (is_expr("check_str", &p))\r
+ {\r
+ int offs;\r
+ offs = strtoul(p, &r, 0);\r
+ if (offs < 0 || offs > Pico.romsize) {\r
+ elprintf(EL_STATUS, "carthw:%d: check_str offs out of range: %d\n", line, offs);\r
+ goto bad;\r
+ }\r
+ p = sskip(r);\r
+ if (*p != ',')\r
+ goto bad;\r
+ p = sskip(p + 1);\r
+ if (*p != '"')\r
+ goto bad;\r
+ p++;\r
+ r = strchr(p, '"');\r
+ if (r == NULL)\r
+ goto bad;\r
+ *r = 0;\r
+\r
+ if (rom_strcmp(offs, p) == 0)\r
+ any_checks_passed = 1;\r
+ else\r
+ skip_sect = 1;\r
+ continue;\r
+ }\r
+ else if (is_expr("check_size_gt", &p))\r
+ {\r
+ int size;\r
+ size = strtoul(p, &r, 0);\r
+ if (r == p || size < 0)\r
+ goto bad;\r
+\r
+ if (Pico.romsize > size)\r
+ any_checks_passed = 1;\r
+ else\r
+ skip_sect = 1;\r
+ continue;\r
+ }\r
+ else if (is_expr("check_csum", &p))\r
+ {\r
+ int csum;\r
+ csum = strtoul(p, &r, 0);\r
+ if (r == p || (csum & 0xffff0000))\r
+ goto bad;\r
+\r
+ if (csum == (rom_read32(0x18c) & 0xffff))\r
+ any_checks_passed = 1;\r
+ else\r
+ skip_sect = 1;\r
+ continue;\r
+ }\r
+\r
+ /* now time for actions */\r
+ if (is_expr("hw", &p)) {\r
+ if (!any_checks_passed)\r
+ goto no_checks;\r
+ rstrip(p);\r
+\r
+ if (strcmp(p, "svp") == 0)\r
+ PicoSVPStartup();\r
+ else if (strcmp(p, "pico") == 0)\r
+ PicoInitPico();\r
+ else if (strcmp(p, "x_in_1_mapper") == 0)\r
+ carthw_Xin1_startup();\r
+ else if (strcmp(p, "realtec_mapper") == 0)\r
+ carthw_realtec_startup();\r
+ else if (strcmp(p, "radica_mapper") == 0)\r
+ carthw_radica_startup();\r
+ else {\r
+ elprintf(EL_STATUS, "carthw:%d: unsupported mapper: %s", line, p);\r
+ skip_sect = 1;\r
+ }\r
+ continue;\r
+ }\r
+ if (is_expr("sram_range", &p)) {\r
+ int start, end;\r
+\r
+ if (!any_checks_passed)\r
+ goto no_checks;\r
+ rstrip(p);\r
+\r
+ start = strtoul(p, &r, 0);\r
+ if (r == p)\r
+ goto bad;\r
+ p = sskip(r);\r
+ if (*p != ',')\r
+ goto bad;\r
+ p = sskip(p + 1);\r
+ end = strtoul(p, &r, 0);\r
+ if (r == p)\r
+ goto bad;\r
+ if (((start | end) & 0xff000000) || start > end) {\r
+ elprintf(EL_STATUS, "carthw:%d: bad sram_range: %08x - %08x", line, start, end);\r
+ goto bad_nomsg;\r
+ }\r
+ SRam.start = start;\r
+ SRam.end = end;\r
+ continue;\r
+ }\r
+ else if (is_expr("prop", &p)) {\r
+ if (!any_checks_passed)\r
+ goto no_checks;\r
+ rstrip(p);\r
+\r
+ if (strcmp(p, "no_sram") == 0)\r
+ SRam.flags &= ~SRF_ENABLED;\r
+ else if (strcmp(p, "no_eeprom") == 0)\r
+ SRam.flags &= ~SRF_EEPROM;\r
+ else if (strcmp(p, "filled_sram") == 0)\r
+ *fill_sram = 1;\r
+ else {\r
+ elprintf(EL_STATUS, "carthw:%d: unsupported prop: %s", line, p);\r
+ goto bad_nomsg;\r
+ }\r
+ continue;\r
+ }\r
+ else if (is_expr("eeprom_type", &p)) {\r
+ int type;\r
+ if (!any_checks_passed)\r
+ goto no_checks;\r
+ rstrip(p);\r
+\r
+ type = strtoul(p, &r, 0);\r
+ if (r == p || type < 0)\r
+ goto bad;\r
+ SRam.eeprom_type = type;\r
+ SRam.flags |= SRF_EEPROM;\r
+ continue;\r
+ }\r
+ else if (is_expr("eeprom_lines", &p)) {\r
+ int scl, sda_in, sda_out;\r
+ if (!any_checks_passed)\r
+ goto no_checks;\r
+ rstrip(p);\r
+\r
+ scl = strtoul(p, &r, 0);\r
+ if (r == p || scl < 0 || scl > 15)\r
+ goto bad;\r
+ p = sskip(r);\r
+ if (*p++ != ',')\r
+ goto bad;\r
+ sda_in = strtoul(p, &r, 0);\r
+ if (r == p || sda_in < 0 || sda_in > 15)\r
+ goto bad;\r
+ p = sskip(r);\r
+ if (*p++ != ',')\r
+ goto bad;\r
+ sda_out = strtoul(p, &r, 0);\r
+ if (r == p || sda_out < 0 || sda_out > 15)\r
+ goto bad;\r
+\r
+ SRam.eeprom_bit_cl = scl;\r
+ SRam.eeprom_bit_in = sda_in;\r
+ SRam.eeprom_bit_out= sda_out;\r
+ continue;\r
+ }\r
+\r
+\r
+bad:\r
+ elprintf(EL_STATUS, "carthw:%d: unrecognized expression: %s", line, buff);\r
+bad_nomsg:\r
+ skip_sect = 1;\r
+ continue;\r
+\r
+no_checks:\r
+ elprintf(EL_STATUS, "carthw:%d: command without any checks before it: %s", line, buff);\r
+ skip_sect = 1;\r
+ continue;\r
+ }\r
+ fclose(f);\r
+}\r
+\r
/*\r
* various cart-specific things, which can't be handled by generic code\r
- * (maybe I should start using CRC for this stuff?)\r
*/\r
static void PicoCartDetect(void)\r
{\r
- int sram_size = 0, csum;\r
- Pico.m.sram_status = 0;\r
+ int fill_sram = 0, csum;\r
\r
csum = rom_read32(0x18c) & 0xffff;\r
\r
+ memset(&SRam, 0, sizeof(SRam));\r
if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A')\r
{\r
+ SRam.start = rom_read32(0x1B4) & ~0xff000001; // align\r
+ SRam.end = (rom_read32(0x1B8) & ~0xff000000) | 1;\r
if (Pico.rom[0x1B2] & 0x40)\r
- {\r
// EEPROM\r
- SRam.start = rom_read32(0x1B4) & ~1; // zero address is used for clock by some games\r
- SRam.end = rom_read32(0x1B8);\r
- sram_size = 0x2000;\r
- Pico.m.sram_status |= SRS_EEPROM;\r
- } else {\r
- // normal SRAM\r
- SRam.start = rom_read32(0x1B4) & ~0xff;\r
- SRam.end = rom_read32(0x1B8) | 1;\r
- sram_size = SRam.end - SRam.start + 1;\r
- }\r
- SRam.start &= ~0xff000000;\r
- SRam.end &= ~0xff000000;\r
- Pico.m.sram_status |= SRS_DETECTED;\r
+ SRam.flags |= SRF_EEPROM;\r
+ SRam.flags |= SRF_ENABLED;\r
}\r
- if (sram_size <= 0)\r
+ if (SRam.end == 0 || SRam.start > SRam.end)\r
{\r
// some games may have bad headers, like S&K and Sonic3\r
// note: majority games use 0x200000 as starting address, but there are some which\r
// use something else (0x300000 by HardBall '95). Luckily they have good headers.\r
SRam.start = 0x200000;\r
SRam.end = 0x203FFF;\r
- sram_size = 0x004000;\r
- }\r
-\r
- // this game actually doesn't have SRAM, but some weird protection\r
- if (rom_strcmp(0x120, "PUGGSY") == 0)\r
- {\r
- SRam.start = SRam.end = sram_size = 0;\r
- }\r
-\r
- if (sram_size)\r
- {\r
- SRam.data = (unsigned char *) calloc(sram_size, 1);\r
- if (SRam.data == NULL) return;\r
+ SRam.flags |= SRF_ENABLED;\r
}\r
- SRam.changed = 0;\r
\r
// set EEPROM defaults, in case it gets detected\r
SRam.eeprom_type = 0; // 7bit (24C01)\r
- SRam.eeprom_abits = 3; // eeprom access must be odd addr for: bit0 ~ cl, bit1 ~ in\r
SRam.eeprom_bit_cl = 1;\r
SRam.eeprom_bit_in = 0;\r
SRam.eeprom_bit_out= 0;\r
\r
- // some known EEPROM data (thanks to EkeEke)\r
- if (name_cmp("COLLEGE SLAM") == 0 ||\r
- name_cmp("FRANK THOMAS BIGHURT BASEBAL") == 0)\r
- {\r
- SRam.eeprom_type = 3;\r
- SRam.eeprom_abits = 2;\r
- SRam.eeprom_bit_cl = 0;\r
- }\r
- else if (name_cmp("NBA JAM TOURNAMENT EDITION") == 0 ||\r
- name_cmp("NFL QUARTERBACK CLUB") == 0)\r
- {\r
- SRam.eeprom_type = 2;\r
- SRam.eeprom_abits = 2;\r
- SRam.eeprom_bit_cl = 0;\r
- }\r
- else if (name_cmp("NBA JAM") == 0)\r
- {\r
- SRam.eeprom_type = 2;\r
- SRam.eeprom_bit_out = 1;\r
- SRam.eeprom_abits = 0;\r
- }\r
- else if (name_cmp("NHLPA HOCKEY '93") == 0 ||\r
- name_cmp("NHLPA Hockey '93") == 0 ||\r
- name_cmp("RINGS OF POWER") == 0)\r
- {\r
- SRam.start = SRam.end = 0x200000;\r
- Pico.m.sram_status = SRS_DETECTED|SRS_EEPROM;\r
- SRam.eeprom_abits = 0;\r
- SRam.eeprom_bit_cl = 6;\r
- SRam.eeprom_bit_in = 7;\r
- SRam.eeprom_bit_out= 7;\r
- }\r
- else if ( name_cmp("MICRO MACHINES II") == 0 ||\r
- (name_cmp(" ") == 0 && // Micro Machines {Turbo Tournament '96, Military - It's a Blast!}\r
- (csum == 0x165e || csum == 0x168b || csum == 0xCEE0 || csum == 0x2C41)))\r
- {\r
- SRam.start = 0x300000;\r
- SRam.end = 0x380001;\r
- Pico.m.sram_status = SRS_DETECTED|SRS_EEPROM;\r
- SRam.eeprom_type = 2;\r
- SRam.eeprom_abits = 0;\r
- SRam.eeprom_bit_cl = 1;\r
- SRam.eeprom_bit_in = 0;\r
- SRam.eeprom_bit_out= 7;\r
- }\r
-\r
- // SVP detection\r
- else if (name_cmp("Virtua Racing") == 0 ||\r
- name_cmp("VIRTUA RACING") == 0)\r
- {\r
- PicoSVPStartup();\r
- }\r
-\r
- // Pico\r
- else if (rom_strcmp(0x100, "SEGA PICO") == 0 ||\r
- rom_strcmp(0x100, "IMA IKUNOUJYUKU") == 0) // what is that supposed to mean?\r
- {\r
- PicoInitPico();\r
- }\r
+ parse_carthw(&fill_sram);\r
\r
- // Detect 12-in-1 mapper\r
- else if ((name_cmp("ROBOCOP 3") == 0 && Pico.romsize == 0x200000) ||\r
- (rom_strcmp(0x160, "FLICKY") == 0 && Pico.romsize >= 0x200000) ||\r
- (name_cmp(" SHOVE IT!") == 0 && Pico.romsize >= 0x200000) ||\r
- (name_cmp("MS PACMAN") == 0 && Pico.romsize >= 0x200000) || // bad dump?\r
- (name_cmp("ALIEN 3") == 0 && Pico.romsize == 0x200000))\r
+ if (SRam.flags & SRF_ENABLED)\r
{\r
- carthw_12in1_startup();\r
- }\r
+ if (SRam.flags & SRF_EEPROM)\r
+ SRam.size = 0x2000;\r
+ else\r
+ SRam.size = SRam.end - SRam.start + 1;\r
\r
- // Realtec mapper\r
- else if (Pico.romsize == 512*1024 && (\r
- rom_strcmp(0x94, "THE EARTH DEFEND") == 0 ||\r
- rom_strcmp(0xfe, "WISEGAME 11-03-1993") == 0 || // Funny World\r
- rom_strcmp(0x95, "MALLET LEGEND ") == 0)) // Whac-A-Critter\r
- {\r
- carthw_realtec_startup();\r
- }\r
+ SRam.data = calloc(SRam.size, 1);\r
+ if (SRam.data == NULL)\r
+ SRam.flags &= ~SRF_ENABLED;\r
\r
- // Radica mapper\r
- else if (name_cmp("KID CHAMELEON") == 0 && Pico.romsize > 0x100000)\r
- {\r
- carthw_radica_startup();\r
+ if (SRam.eeprom_type == 1) // 1 == 0 in PD EEPROM code\r
+ SRam.eeprom_type = 0;\r
}\r
\r
- // Some games malfunction if SRAM is not filled with 0xff\r
- if (name_cmp("DINO DINI'S SOCCER") == 0 ||\r
- name_cmp("MICRO MACHINES II") == 0)\r
+ if ((SRam.flags & SRF_ENABLED) && fill_sram)\r
{\r
- memset(SRam.data, 0xff, sram_size);\r
+ elprintf(EL_STATUS, "SRAM fill");\r
+ memset(SRam.data, 0xff, SRam.size);\r
}\r
\r
// Unusual region 'code'\r
if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0)\r
- *(int *) (Pico.rom+0x1f0) = 0x20204520;\r
+ *(int *) (Pico.rom + 0x1f0) = 0x20204520;\r
}\r
\r
--- /dev/null
+# 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
+
/*
* 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;
-
-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;
-}
+/* 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 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 }
+};
+
+// TODO: test a0, reads, w16
+static void carthw_Xin1_write8(u32 a, u32 d)
+{
+ if ((a & 0xffff00) != 0xa13000) {
+ PicoWrite8_io(a, d);
+ return;
+ }
+
+ carthw_Xin1_do(a, 0x3f, 16);
}
-static void carthw_12in1_statef(void)
+static void carthw_Xin1_mem_setup(void)
{
- carthw_12in1_write8(carthw_12in1_baddr, 0, 0);
+ cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, carthw_Xin1_write8, 1);
}
-void carthw_12in1_startup(void)
+static void carthw_Xin1_reset(void)
{
- void *tmp;
+ carthw_Xin1_write8(0xa13000, 0);
+}
- elprintf(EL_STATUS, "12-in-1 mapper detected");
+static void carthw_Xin1_statef(void)
+{
+ carthw_Xin1_write8(carthw_Xin1_baddr, 0);
+}
- 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);
+void carthw_Xin1_startup(void)
+{
+ elprintf(EL_STATUS, "X-in-1 mapper startup");
- PicoRead16Hook = carthw_12in1_read16;
- PicoWrite8Hook = carthw_12in1_write8;
- PicoResetHook = carthw_12in1_reset;
- PicoLoadStateHook = carthw_12in1_statef;
- carthw_chunks = carthw_12in1_state;
+ PicoCartMemSetup = carthw_Xin1_mem_setup;
+ PicoResetHook = carthw_Xin1_reset;
+ PicoLoadStateHook = carthw_Xin1_statef;
+ carthw_chunks = carthw_Xin1_state;
}
* 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;
(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[] =
-{
- { CHUNK_CARTHW, sizeof(carthw_radica_baddr), &carthw_radica_baddr },
- { 0, 0, NULL }
-};
-
-static unsigned int carthw_radica_read16(unsigned int a, int realsize)
+static u32 carthw_radica_read16(u32 a)
{
- if ((a & 0xffff80) != 0xa13000) {
- elprintf(EL_UIO, "radica: r16 %06x", a);
- return 0;
- }
+ if ((a & 0xffff00) != 0xa13000)
+ return PicoRead16_io(a);
- 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;
}
-
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);
#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
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:
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 (a == 0xa15004 && !(d&1)) {
- if (!a15004_looping)
- elprintf(EL_SVP, "SVP det TIGHT loop: a15004");
- a15004_looping = 1;
+#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, 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);
-}
-
-void PicoSVPWrite16(unsigned int a, unsigned int d, int realsize)
-{
- static int clearing_ram = 0;
+ elprintf(EL_SVP, "SVP w16: [%06x] %04x @%06x", a, d, SekPc);
- // 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;
}
//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;
+*/
+}
+
+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);
- // 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;
+ // DRAM (cell arrange) - TODO
- elprintf(EL_SVP, "SVP w%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
+ // 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);
}
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());
{
void *tmp;
- elprintf(EL_SVP, "SVP init");
+ elprintf(EL_STATUS, "SVP startup");
tmp = realloc(Pico.rom, 0x200000 + sizeof(*svp));
if (tmp == NULL)
#endif
// init ok, setup hooks..
- PicoRead16Hook = PicoSVPRead16;
- PicoWrite8Hook = PicoSVPWrite8;
- PicoWrite16Hook = PicoSVPWrite16;
+ PicoCartMemSetup = PicoSVPMemSetup;
PicoDmaHook = PicoSVPDma;
PicoResetHook = PicoSVPReset;
PicoLineHook = PicoSVPLine;
if (m68ki_cpu_p == &PicoCpuMS68k) s68k_write32(a, d); else m68k_write32(a, d);\r
}\r
\r
-// these are allowed to access RAM\r
-static unsigned int m68k_read_pcrelative_CD8 (unsigned int a)\r
-{\r
- a&=0xffffff;\r
- if(m68ki_cpu_p == &PicoCpuMS68k) {\r
- if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram\r
- if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)\r
- return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));\r
- if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)\r
- int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
- return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));\r
- }\r
- elprintf(EL_ANOMALY, "s68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);\r
- } else {\r
- if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram\r
- if(a<0x20000) return *(u8 *)(Pico.rom+(a^1)); // Bios\r
- if((a&0xfc0000)==0x200000) { // word RAM\r
- if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?\r
- return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));\r
- else if (a < 0x220000) {\r
- int bank = Pico_mcd->s68k_regs[3]&1;\r
- return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));\r
- }\r
- }\r
- elprintf(EL_ANOMALY, "m68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);\r
- }\r
- return 0;//(u8) lastread_d;\r
-}\r
-static unsigned int m68k_read_pcrelative_CD16(unsigned int a)\r
-{\r
- a&=0xffffff;\r
- if(m68ki_cpu_p == &PicoCpuMS68k) {\r
- if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram\r
- if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)\r
- return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
- if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)\r
- int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
- return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
- }\r
- elprintf(EL_ANOMALY, "s68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);\r
- } else {\r
- if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram\r
- if(a<0x20000) return *(u16 *)(Pico.rom+(a&~1)); // Bios\r
- if((a&0xfc0000)==0x200000) { // word RAM\r
- if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?\r
- return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
- else if (a < 0x220000) {\r
- int bank = Pico_mcd->s68k_regs[3]&1;\r
- return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
- }\r
- }\r
- elprintf(EL_ANOMALY, "m68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);\r
- }\r
- return 0;\r
-}\r
-static unsigned int m68k_read_pcrelative_CD32(unsigned int a)\r
-{\r
- u16 *pm;\r
- a&=0xffffff;\r
- if(m68ki_cpu_p == &PicoCpuMS68k) {\r
- if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram\r
- if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)\r
- { pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }\r
- if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)\r
- int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
- pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
- return (pm[0]<<16)|pm[1];\r
- }\r
- elprintf(EL_ANOMALY, "s68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);\r
- } else {\r
- if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram\r
- if(a<0x20000) { u16 *pm=(u16 *)(Pico.rom+(a&~1)); return (pm[0]<<16)|pm[1]; }\r
- if((a&0xfc0000)==0x200000) { // word RAM\r
- if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?\r
- { pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }\r
- else if (a < 0x220000) {\r
- int bank = Pico_mcd->s68k_regs[3]&1;\r
- pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
- return (pm[0]<<16)|pm[1];\r
- }\r
- }\r
- elprintf(EL_ANOMALY, "m68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);\r
- }\r
- return 0;\r
-}\r
-\r
extern unsigned int (*pm68k_read_memory_8) (unsigned int address);\r
extern unsigned int (*pm68k_read_memory_16)(unsigned int address);\r
extern unsigned int (*pm68k_read_memory_32)(unsigned int address);\r
extern void (*pm68k_write_memory_8) (unsigned int address, unsigned char value);\r
extern void (*pm68k_write_memory_16)(unsigned int address, unsigned short value);\r
extern void (*pm68k_write_memory_32)(unsigned int address, unsigned int value);\r
-extern unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address);\r
-extern unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address);\r
-extern unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address);\r
\r
static void m68k_mem_setup_cd(void)\r
{\r
pm68k_write_memory_8 = PicoWriteCD8w;\r
pm68k_write_memory_16 = PicoWriteCD16w;\r
pm68k_write_memory_32 = PicoWriteCD32w;\r
- pm68k_read_memory_pcr_8 = m68k_read_pcrelative_CD8;\r
- pm68k_read_memory_pcr_16 = m68k_read_pcrelative_CD16;\r
- pm68k_read_memory_pcr_32 = m68k_read_pcrelative_CD32;\r
}\r
#endif // EMU_M68K\r
\r
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)
--- /dev/null
+/*\r
+ * rarely used EEPROM code\r
+ *\r
+ * (see Genesis Plus for Wii/GC code and docs for info,\r
+ * full game list and better code).\r
+ */\r
+\r
+#include "pico_int.h"\r
+\r
+static unsigned int last_write = 0xffff0000;\r
+\r
+// eeprom_status: LA.. s.la (L=pending SCL, A=pending SDA,\r
+// s=started, l=old SCL, a=old SDA)\r
+static void EEPROM_write_do(unsigned int d) // ???? ??la (l=SCL, a=SDA)\r
+{\r
+ unsigned int sreg = Pico.m.eeprom_status, saddr = Pico.m.eeprom_addr;\r
+ unsigned int scyc = Pico.m.eeprom_cycle, ssa = Pico.m.eeprom_slave;\r
+\r
+ elprintf(EL_EEPROM, "eeprom: scl/sda: %i/%i -> %i/%i, newtime=%i", (sreg&2)>>1, sreg&1,\r
+ (d&2)>>1, d&1, SekCyclesDoneT() - last_write);\r
+ saddr &= 0x1fff;\r
+\r
+ if(sreg & d & 2) {\r
+ // SCL was and is still high..\r
+ if((sreg & 1) && !(d&1)) {\r
+ // ..and SDA went low, means it's a start command, so clear internal addr reg and clock counter\r
+ elprintf(EL_EEPROM, "eeprom: -start-");\r
+ //saddr = 0;\r
+ scyc = 0;\r
+ sreg |= 8;\r
+ } else if(!(sreg & 1) && (d&1)) {\r
+ // SDA went high == stop command\r
+ elprintf(EL_EEPROM, "eeprom: -stop-");\r
+ sreg &= ~8;\r
+ }\r
+ }\r
+ else if((sreg & 8) && !(sreg & 2) && (d&2))\r
+ {\r
+ // we are started and SCL went high - next cycle\r
+ scyc++; // pre-increment\r
+ if(SRam.eeprom_type) {\r
+ // X24C02+\r
+ if((ssa&1) && scyc == 18) {\r
+ scyc = 9;\r
+ saddr++; // next address in read mode\r
+ /*if(SRam.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask\r
+ }\r
+ else if(SRam.eeprom_type == 2 && scyc == 27) scyc = 18;\r
+ else if(scyc == 36) scyc = 27;\r
+ } else {\r
+ // X24C01\r
+ if(scyc == 18) {\r
+ scyc = 9; // wrap\r
+ if(saddr&1) { saddr+=2; saddr&=0xff; } // next addr in read mode\r
+ }\r
+ }\r
+ elprintf(EL_EEPROM, "eeprom: scyc: %i", scyc);\r
+ }\r
+ else if((sreg & 8) && (sreg & 2) && !(d&2))\r
+ {\r
+ // we are started and SCL went low (falling edge)\r
+ if(SRam.eeprom_type) {\r
+ // X24C02+\r
+ if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles\r
+ else if( (SRam.eeprom_type == 3 && scyc > 27) || (SRam.eeprom_type == 2 && scyc > 18) ) {\r
+ if(!(ssa&1)) {\r
+ // data write\r
+ unsigned char *pm=SRam.data+saddr;\r
+ *pm <<= 1; *pm |= d&1;\r
+ if(scyc == 26 || scyc == 35) {\r
+ saddr=(saddr&~0xf)|((saddr+1)&0xf); // only 4 (?) lowest bits are incremented\r
+ elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr, *pm);\r
+ }\r
+ SRam.changed = 1;\r
+ }\r
+ } else if(scyc > 9) {\r
+ if(!(ssa&1)) {\r
+ // we latch another addr bit\r
+ saddr<<=1;\r
+ if(SRam.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask\r
+ saddr|=d&1;\r
+ if(scyc==17||scyc==26) {\r
+ elprintf(EL_EEPROM, "eeprom: addr reg done: %x", saddr);\r
+ if(scyc==17&&SRam.eeprom_type==2) { saddr&=0xff; saddr|=(ssa<<7)&0x700; } // add device bits too\r
+ }\r
+ }\r
+ } else {\r
+ // slave address\r
+ ssa<<=1; ssa|=d&1;\r
+ if(scyc==8) elprintf(EL_EEPROM, "eeprom: slave done: %x", ssa);\r
+ }\r
+ } else {\r
+ // X24C01\r
+ if(scyc == 9); // ACK cycle, do nothing\r
+ else if(scyc > 9) {\r
+ if(!(saddr&1)) {\r
+ // data write\r
+ unsigned char *pm=SRam.data+(saddr>>1);\r
+ *pm <<= 1; *pm |= d&1;\r
+ if(scyc == 17) {\r
+ saddr=(saddr&0xf9)|((saddr+2)&6); // only 2 lowest bits are incremented\r
+ elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr>>1, *pm);\r
+ }\r
+ SRam.changed = 1;\r
+ }\r
+ } else {\r
+ // we latch another addr bit\r
+ saddr<<=1; saddr|=d&1; saddr&=0xff;\r
+ if(scyc==8) elprintf(EL_EEPROM, "eeprom: addr done: %x", saddr>>1);\r
+ }\r
+ }\r
+ }\r
+\r
+ sreg &= ~3; sreg |= d&3; // remember SCL and SDA\r
+ Pico.m.eeprom_status = (unsigned char) sreg;\r
+ Pico.m.eeprom_cycle = (unsigned char) scyc;\r
+ Pico.m.eeprom_slave = (unsigned char) ssa;\r
+ Pico.m.eeprom_addr = (unsigned short)saddr;\r
+}\r
+\r
+static void EEPROM_upd_pending(unsigned int d)\r
+{\r
+ unsigned int d1, sreg = Pico.m.eeprom_status;\r
+\r
+ sreg &= ~0xc0;\r
+\r
+ // SCL\r
+ d1 = (d >> SRam.eeprom_bit_cl) & 1;\r
+ sreg |= d1 << 7;\r
+\r
+ // SDA in\r
+ d1 = (d >> SRam.eeprom_bit_in) & 1;\r
+ sreg |= d1 << 6;\r
+\r
+ Pico.m.eeprom_status = (unsigned char) sreg;\r
+}\r
+\r
+void EEPROM_write16(unsigned int d)\r
+{\r
+ // this diff must be at most 16 for NBA Jam to work\r
+ if (SekCyclesDoneT() - last_write < 16) {\r
+ // just update pending state\r
+ elprintf(EL_EEPROM, "eeprom: skip because cycles=%i",\r
+ SekCyclesDoneT() - last_write);\r
+ EEPROM_upd_pending(d);\r
+ } else {\r
+ int srs = Pico.m.eeprom_status;\r
+ EEPROM_write_do(srs >> 6); // execute pending\r
+ EEPROM_upd_pending(d);\r
+ if ((srs ^ Pico.m.eeprom_status) & 0xc0) // update time only if SDA/SCL changed\r
+ last_write = SekCyclesDoneT();\r
+ }\r
+}\r
+\r
+void EEPROM_write8(unsigned int a, unsigned int d)\r
+{\r
+ unsigned char *wb = Pico.m.eeprom_wb;\r
+ wb[a & 1] = d;\r
+ EEPROM_write16((wb[0] << 8) | wb[1]);\r
+}\r
+\r
+unsigned int EEPROM_read(void)\r
+{\r
+ unsigned int shift, d;\r
+ unsigned int sreg, saddr, scyc, ssa, interval;\r
+\r
+ // flush last pending write\r
+ EEPROM_write_do(Pico.m.eeprom_status>>6);\r
+\r
+ sreg = Pico.m.eeprom_status; saddr = Pico.m.eeprom_addr&0x1fff; scyc = Pico.m.eeprom_cycle; ssa = Pico.m.eeprom_slave;\r
+ interval = SekCyclesDoneT() - last_write;\r
+ d = (sreg>>6)&1; // use SDA as "open bus"\r
+\r
+ // NBA Jam is nasty enough to read <before> raising the SCL and starting the new cycle.\r
+ // this is probably valid because data changes occur while SCL is low and data can be read\r
+ // before it's actual cycle begins.\r
+ if (!(sreg&0x80) && interval >= 24) {\r
+ elprintf(EL_EEPROM, "eeprom: early read, cycles=%i", interval);\r
+ scyc++;\r
+ }\r
+\r
+ if (!(sreg & 8)); // not started, use open bus\r
+ else if (scyc == 9 || scyc == 18 || scyc == 27) {\r
+ elprintf(EL_EEPROM, "eeprom: r ack");\r
+ d = 0;\r
+ } else if (scyc > 9 && scyc < 18) {\r
+ // started and first command word received\r
+ shift = 17-scyc;\r
+ if (SRam.eeprom_type) {\r
+ // X24C02+\r
+ if (ssa&1) {\r
+ elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg);\r
+ if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr]);\r
+ d = (SRam.data[saddr]>>shift)&1;\r
+ }\r
+ } else {\r
+ // X24C01\r
+ if (saddr&1) {\r
+ elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr>>1, scyc, sreg);\r
+ if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr>>1]);\r
+ d = (SRam.data[saddr>>1]>>shift)&1;\r
+ }\r
+ }\r
+ }\r
+\r
+ return (d << SRam.eeprom_bit_out);\r
+}\r
+\r
\r
// for nonstandard reads\r
// TODO: mv to carthw\r
-static u32 OtherRead16End(u32 a, int realsize)\r
+u32 OtherRead16End(u32 a, int realsize)\r
{\r
u32 d=0;\r
\r
// our default behaviour is to return whatever was last written a 0x400000-0x7fffff range (used by Squirrel King (R) [!])\r
// Lion King II, The (Unl) [!] writes @ 400000 and wants to get that val @ 400002 and wites another val\r
// @ 400004 which is expected @ 400006, so we really remember 2 values here\r
- d = Pico.m.prot_bytes[(a>>2)&1]<<8;\r
+/// d = Pico.m.prot_bytes[(a>>2)&1]<<8;\r
}\r
else if (a == 0xa13000 && Pico.romsize >= 1024*1024) {\r
if (*(int *)(Pico.rom+0xc8af0) == 0x30133013 && *(int *)(Pico.rom+0xc8af4) == 0x000f0240) { // Rockman X3 (Unl) [!]\r
return d;\r
}\r
\r
-static void OtherWrite8End(u32 a,u32 d,int realsize)\r
+void OtherWrite8End(u32 a,u32 d,int realsize)\r
{\r
-#ifdef _ASM_MEMORY_C\r
- // special ROM hardware (currently only banking and sram reg supported)\r
- if((a&0xfffff1) == 0xA130F1) {\r
- PicoWriteRomHW_SSF2(a, d); // SSF2 or SRAM\r
- return;\r
- }\r
-#else\r
- // sram access register\r
- if(a == 0xA130F1) {\r
- elprintf(EL_SRAMIO, "sram reg=%02x", d);\r
- Pico.m.sram_status &= ~(SRS_MAPPED|SRS_READONLY);\r
- Pico.m.sram_status |= (u8)(d&3);\r
- return;\r
- }\r
-#endif\r
- elprintf(EL_UIO, "strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc);\r
-\r
// for games with simple protection devices, discovered by Haze\r
if ((a>>22) == 1)\r
- Pico.m.prot_bytes[(a>>2)&1] = (u8)d;\r
+;/// Pico.m.prot_bytes[(a>>2)&1] = (u8)d;\r
}\r
\r
// -----------------------------------------------------------------\r
// cart (save) RAM area (usually 0x200000 - ...)\r
static u32 PicoRead8_sram(u32 a)\r
{\r
- int srs = Pico.m.sram_status;\r
u32 d;\r
- if (SRam.end >= a && a >= SRam.start && (srs & (SRS_MAPPED|SRS_EEPROM)))\r
+ if (SRam.start <= a && a <= SRam.end && (Pico.m.sram_reg & SRR_MAPPED))\r
{\r
- if (srs & SRS_EEPROM)\r
+ if (SRam.flags & SRF_EEPROM) {\r
d = EEPROM_read();\r
- else\r
+ if (!(a & 1))\r
+ d >>= 8;\r
+ } else\r
d = *(u8 *)(SRam.data - SRam.start + a);\r
- elprintf(EL_SRAMIO, "sram r8 [%06x] %02x @ %06x", a, d, SekPc);\r
+ elprintf(EL_SRAMIO, "sram r8 [%06x] %02x @ %06x", a, d, SekPc);\r
return d;\r
}\r
\r
+ // XXX: this is banking unfriendly\r
if (a < Pico.romsize)\r
return Pico.rom[a ^ 1];\r
\r
\r
static u32 PicoRead16_sram(u32 a)\r
{\r
- int srs = Pico.m.sram_status;\r
u32 d;\r
- if (SRam.end >= a && a >= SRam.start && (srs & (SRS_MAPPED|SRS_EEPROM)))\r
+ if (SRam.end >= a && a >= SRam.start && (Pico.m.sram_reg & SRR_MAPPED))\r
{\r
- if (srs & SRS_EEPROM) {\r
+ if (SRam.flags & SRF_EEPROM)\r
d = EEPROM_read();\r
- d |= d << 8;\r
- } else {\r
+ else {\r
u8 *pm = (u8 *)(SRam.data - SRam.start + a);\r
d = pm[0] << 8;\r
d |= pm[1];\r
\r
static void PicoWrite8_sram(u32 a, u32 d)\r
{\r
- unsigned int srs = Pico.m.sram_status;\r
- elprintf(EL_SRAMIO, "sram wX [%06x] %02x @ %06x", a, d & 0xffff, SekPc);\r
- if (srs & SRS_EEPROM) // EEPROM write\r
+ if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) {\r
+ m68k_unmapped_write8(a, d);\r
+ return;\r
+ }\r
+\r
+ elprintf(EL_SRAMIO, "sram w8 [%06x] %02x @ %06x", a, d & 0xff, SekPc);\r
+ if (SRam.flags & SRF_EEPROM)\r
{\r
- // this diff must be at most 16 for NBA Jam to work\r
- if (SekCyclesDoneT() - lastSSRamWrite < 16) {\r
- // just update pending state\r
- elprintf(EL_EEPROM, "eeprom: skip because cycles=%i",\r
- SekCyclesDoneT() - lastSSRamWrite);\r
- EEPROM_upd_pending(a, d);\r
- } else {\r
- EEPROM_write(srs >> 6); // execute pending\r
- EEPROM_upd_pending(a, d);\r
- if ((srs ^ Pico.m.sram_status) & 0xc0) // update time only if SDA/SCL changed\r
- lastSSRamWrite = SekCyclesDoneT();\r
- }\r
+ EEPROM_write8(a, d);\r
}\r
- else if (!(srs & SRS_READONLY)) {\r
- u8 *pm=(u8 *)(SRam.data - SRam.start + a);\r
+ else {\r
+ u8 *pm = (u8 *)(SRam.data - SRam.start + a);\r
if (*pm != (u8)d) {\r
SRam.changed = 1;\r
*pm = (u8)d;\r
\r
static void PicoWrite16_sram(u32 a, u32 d)\r
{\r
- // XXX: hardware could easily use MSB too..\r
- PicoWrite8_sram(a + 1, d);\r
+ if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) {\r
+ m68k_unmapped_write16(a, d);\r
+ return;\r
+ }\r
+\r
+ elprintf(EL_SRAMIO, "sram w16 [%06x] %04x @ %06x", a, d & 0xffff, SekPc);\r
+ if (SRam.flags & SRF_EEPROM)\r
+ {\r
+ EEPROM_write16(d);\r
+ }\r
+ else {\r
+ // XXX: hardware could easily use MSB too..\r
+ u8 *pm = (u8 *)(SRam.data - SRam.start + a);\r
+ if (*pm != (u8)d) {\r
+ SRam.changed = 1;\r
+ *pm = (u8)d;\r
+ }\r
+ }\r
}\r
\r
// z80 area (0xa00000 - 0xa0ffff)\r
}\r
if (a == 0xa130f1) { // sram access register\r
elprintf(EL_SRAMIO, "sram reg=%02x", d);\r
- Pico.m.sram_status &= ~(SRS_MAPPED|SRS_READONLY);\r
- Pico.m.sram_status |= (u8)(d & 3);\r
+ Pico.m.sram_reg &= ~(SRR_MAPPED|SRR_READONLY);\r
+ Pico.m.sram_reg |= (u8)(d & 3);\r
return;\r
}\r
m68k_unmapped_write8(a, d);\r
}\r
if (a == 0xa130f0) { // sram access register\r
elprintf(EL_SRAMIO, "sram reg=%02x", d);\r
- Pico.m.sram_status &= ~(SRS_MAPPED|SRS_READONLY);\r
- Pico.m.sram_status |= (u8)(d & 3);\r
+ Pico.m.sram_reg &= ~(SRR_MAPPED|SRR_READONLY);\r
+ Pico.m.sram_reg |= (u8)(d & 3);\r
return;\r
}\r
m68k_unmapped_write16(a, d);\r
\r
// -----------------------------------------------------------------\r
\r
-// TODO: rm\r
-static void OtherWrite16End(u32 a,u32 d,int realsize)\r
-{\r
- PicoWrite8Hook(a, d>>8, realsize);\r
- PicoWrite8Hook(a+1,d&0xff, realsize);\r
-}\r
-\r
-u32 (*PicoRead16Hook) (u32 a, int realsize) = OtherRead16End;\r
-void (*PicoWrite8Hook) (u32 a, u32 d, int realsize) = OtherWrite8End;\r
-void (*PicoWrite16Hook)(u32 a, u32 d, int realsize) = OtherWrite16End;\r
-\r
-PICO_INTERNAL void PicoMemResetHooks(void)\r
-{\r
- // default unmapped/cart specific handlers\r
- PicoRead16Hook = OtherRead16End;\r
- PicoWrite8Hook = OtherWrite8End;\r
- PicoWrite16Hook = OtherWrite16End;\r
-}\r
-\r
#ifdef EMU_M68K\r
static void m68k_mem_setup(void);\r
#endif\r
cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0);\r
\r
// Common case of on-cart (save) RAM, usually at 0x200000-...\r
- rs = SRam.end - SRam.start;\r
- if (rs > 0 && SRam.data != NULL) {\r
+ if ((SRam.flags & SRF_ENABLED) && SRam.data != NULL) {\r
+ rs = SRam.end - SRam.start;\r
rs = (rs + mask) & ~mask;\r
if (SRam.start + rs >= 0x1000000)\r
rs = 0x1000000 - SRam.start;\r
z80_mem_setup();\r
}\r
\r
-/* some nasty things below :( */\r
#ifdef EMU_M68K\r
unsigned int (*pm68k_read_memory_8) (unsigned int address) = NULL;\r
unsigned int (*pm68k_read_memory_16)(unsigned int address) = NULL;\r
void (*pm68k_write_memory_8) (unsigned int address, unsigned char value) = NULL;\r
void (*pm68k_write_memory_16)(unsigned int address, unsigned short value) = NULL;\r
void (*pm68k_write_memory_32)(unsigned int address, unsigned int value) = NULL;\r
-unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address) = NULL;\r
-unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address) = NULL;\r
-unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address) = NULL;\r
-\r
-// these are here for core debugging mode\r
-static unsigned int m68k_read_8 (unsigned int a, int do_fake)\r
-{\r
- a&=0xffffff;\r
- if(a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k) return *(u8 *)(Pico.rom+(a^1)); // Rom\r
-#ifdef EMU_CORE_DEBUG\r
- if(do_fake&&((ppop&0x3f)==0x3a||(ppop&0x3f)==0x3b)) return lastread_d[lrp_mus++&15];\r
-#endif\r
- return pm68k_read_memory_pcr_8(a);\r
-}\r
-static unsigned int m68k_read_16(unsigned int a, int do_fake)\r
-{\r
- a&=0xffffff;\r
- if(a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k) return *(u16 *)(Pico.rom+(a&~1)); // Rom\r
-#ifdef EMU_CORE_DEBUG\r
- if(do_fake&&((ppop&0x3f)==0x3a||(ppop&0x3f)==0x3b)) return lastread_d[lrp_mus++&15];\r
-#endif\r
- return pm68k_read_memory_pcr_16(a);\r
-}\r
-static unsigned int m68k_read_32(unsigned int a, int do_fake)\r
-{\r
- a&=0xffffff;\r
- if(a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k) { u16 *pm=(u16 *)(Pico.rom+(a&~1)); return (pm[0]<<16)|pm[1]; }\r
-#ifdef EMU_CORE_DEBUG\r
- if(do_fake&&((ppop&0x3f)==0x3a||(ppop&0x3f)==0x3b)) return lastread_d[lrp_mus++&15];\r
-#endif\r
- return pm68k_read_memory_pcr_32(a);\r
-}\r
-\r
-unsigned int m68k_read_pcrelative_8 (unsigned int a) { return m68k_read_8 (a, 1); }\r
-unsigned int m68k_read_pcrelative_16(unsigned int a) { return m68k_read_16(a, 1); }\r
-unsigned int m68k_read_pcrelative_32(unsigned int a) { return m68k_read_32(a, 1); }\r
-unsigned int m68k_read_immediate_16(unsigned int a) { return m68k_read_16(a, 0); }\r
-unsigned int m68k_read_immediate_32(unsigned int a) { return m68k_read_32(a, 0); }\r
-unsigned int m68k_read_disassembler_8 (unsigned int a) { return m68k_read_8 (a, 0); }\r
-unsigned int m68k_read_disassembler_16(unsigned int a) { return m68k_read_16(a, 0); }\r
-unsigned int m68k_read_disassembler_32(unsigned int a) { return m68k_read_32(a, 0); }\r
-\r
-static unsigned int m68k_read_memory_pcr_8(unsigned int a)\r
-{\r
- if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram\r
- return 0;\r
-}\r
-\r
-static unsigned int m68k_read_memory_pcr_16(unsigned int a)\r
-{\r
- if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram\r
- return 0;\r
-}\r
-\r
-static unsigned int m68k_read_memory_pcr_32(unsigned int a)\r
-{\r
- if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram\r
- return 0;\r
-}\r
-\r
-#ifdef EMU_CORE_DEBUG\r
-// ROM only\r
-unsigned int m68k_read_memory_8(unsigned int a)\r
-{\r
- u8 d;\r
- if (a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k)\r
- d = *(u8 *) (Pico.rom+(a^1));\r
- else d = (u8) lastread_d[lrp_mus++&15];\r
- elprintf(EL_IO, "r8_mu : %06x, %02x @%06x", a&0xffffff, d, SekPc);\r
- return d;\r
-}\r
-unsigned int m68k_read_memory_16(unsigned int a)\r
-{\r
- u16 d;\r
- if (a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k)\r
- d = *(u16 *)(Pico.rom+(a&~1));\r
- else d = (u16) lastread_d[lrp_mus++&15];\r
- elprintf(EL_IO, "r16_mu: %06x, %04x @%06x", a&0xffffff, d, SekPc);\r
- return d;\r
-}\r
-unsigned int m68k_read_memory_32(unsigned int a)\r
-{\r
- u32 d;\r
- if (a<Pico.romsize && m68ki_cpu_p==&PicoCpuMM68k)\r
- { u16 *pm=(u16 *)(Pico.rom+(a&~1));d=(pm[0]<<16)|pm[1]; }\r
- else if (a <= 0x78) d = m68k_read_32(a, 0);\r
- else d = lastread_d[lrp_mus++&15];\r
- elprintf(EL_IO, "r32_mu: %06x, %08x @%06x", a&0xffffff, d, SekPc);\r
- return d;\r
-}\r
-\r
-// ignore writes, Cyclone already done that\r
-void m68k_write_memory_8(unsigned int address, unsigned int value) { lastwrite_mus_d[lwp_mus++&15] = value; }\r
-void m68k_write_memory_16(unsigned int address, unsigned int value) { lastwrite_mus_d[lwp_mus++&15] = value; }\r
-void m68k_write_memory_32(unsigned int address, unsigned int value) { lastwrite_mus_d[lwp_mus++&15] = value; }\r
-\r
-#else // if !EMU_CORE_DEBUG\r
\r
/* it appears that Musashi doesn't always mask the unused bits */\r
unsigned int m68k_read_memory_8 (unsigned int address) { return pm68k_read_memory_8 (address) & 0xff; }\r
void m68k_write_memory_8 (unsigned int address, unsigned int value) { pm68k_write_memory_8 (address, (u8)value); }\r
void m68k_write_memory_16(unsigned int address, unsigned int value) { pm68k_write_memory_16(address,(u16)value); }\r
void m68k_write_memory_32(unsigned int address, unsigned int value) { pm68k_write_memory_32(address, value); }\r
-#endif // !EMU_CORE_DEBUG\r
\r
static void m68k_mem_setup(void)\r
{\r
pm68k_write_memory_8 = m68k_write8;\r
pm68k_write_memory_16 = m68k_write16;\r
pm68k_write_memory_32 = m68k_write32;\r
- pm68k_read_memory_pcr_8 = m68k_read_memory_pcr_8;\r
- pm68k_read_memory_pcr_16 = m68k_read_memory_pcr_16;\r
- pm68k_read_memory_pcr_32 = m68k_read_memory_pcr_32;\r
}\r
#endif // EMU_M68K\r
\r
addr68k = Pico.m.z80_bank68k<<15;\r
addr68k += a & 0x7fff;\r
\r
- if (addr68k < Pico.romsize) {\r
- ret = Pico.rom[addr68k^1];\r
- goto out;\r
- }\r
-\r
ret = m68k_read8(addr68k);\r
- elprintf(EL_ANOMALY, "z80->68k upper read [%06x] %02x", addr68k, ret);\r
\r
-out:\r
elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret);\r
return ret;\r
}\r
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];
};\r
\r
\r
-// rarely used EEPROM SRAM code\r
-// known games which use this:\r
-// Wonder Boy in Monster World, Megaman - The Wily Wars (X24C01, 128 bytes)\r
-\r
-// (see Genesis Plus for Wii/GC code and docs for info,\r
-// full game list and better code).\r
-\r
-unsigned int lastSSRamWrite = 0xffff0000;\r
-\r
-// sram_status: LAtd sela (L=pending SCL, A=pending SDA, t=(unused),\r
-// d=SRAM was detected (header or by access), s=started, e=save is EEPROM, l=old SCL, a=old SDA)\r
-PICO_INTERNAL void EEPROM_write(unsigned int d) // ???? ??la (l=SCL, a=SDA)\r
-{\r
- unsigned int sreg = Pico.m.sram_status, saddr = Pico.m.eeprom_addr, scyc = Pico.m.eeprom_cycle, ssa = Pico.m.eeprom_slave;\r
-\r
- elprintf(EL_EEPROM, "eeprom: scl/sda: %i/%i -> %i/%i, newtime=%i", (sreg&2)>>1, sreg&1,\r
- (d&2)>>1, d&1, SekCyclesDoneT()-lastSSRamWrite);\r
- saddr&=0x1fff;\r
-\r
- if(sreg & d & 2) {\r
- // SCL was and is still high..\r
- if((sreg & 1) && !(d&1)) {\r
- // ..and SDA went low, means it's a start command, so clear internal addr reg and clock counter\r
- elprintf(EL_EEPROM, "eeprom: -start-");\r
- //saddr = 0;\r
- scyc = 0;\r
- sreg |= 8;\r
- } else if(!(sreg & 1) && (d&1)) {\r
- // SDA went high == stop command\r
- elprintf(EL_EEPROM, "eeprom: -stop-");\r
- sreg &= ~8;\r
- }\r
- }\r
- else if((sreg & 8) && !(sreg & 2) && (d&2))\r
- {\r
- // we are started and SCL went high - next cycle\r
- scyc++; // pre-increment\r
- if(SRam.eeprom_type) {\r
- // X24C02+\r
- if((ssa&1) && scyc == 18) {\r
- scyc = 9;\r
- saddr++; // next address in read mode\r
- /*if(SRam.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask\r
- }\r
- else if(SRam.eeprom_type == 2 && scyc == 27) scyc = 18;\r
- else if(scyc == 36) scyc = 27;\r
- } else {\r
- // X24C01\r
- if(scyc == 18) {\r
- scyc = 9; // wrap\r
- if(saddr&1) { saddr+=2; saddr&=0xff; } // next addr in read mode\r
- }\r
- }\r
- elprintf(EL_EEPROM, "eeprom: scyc: %i", scyc);\r
- }\r
- else if((sreg & 8) && (sreg & 2) && !(d&2))\r
- {\r
- // we are started and SCL went low (falling edge)\r
- if(SRam.eeprom_type) {\r
- // X24C02+\r
- if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles\r
- else if( (SRam.eeprom_type == 3 && scyc > 27) || (SRam.eeprom_type == 2 && scyc > 18) ) {\r
- if(!(ssa&1)) {\r
- // data write\r
- unsigned char *pm=SRam.data+saddr;\r
- *pm <<= 1; *pm |= d&1;\r
- if(scyc == 26 || scyc == 35) {\r
- saddr=(saddr&~0xf)|((saddr+1)&0xf); // only 4 (?) lowest bits are incremented\r
- elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr, *pm);\r
- }\r
- SRam.changed = 1;\r
- }\r
- } else if(scyc > 9) {\r
- if(!(ssa&1)) {\r
- // we latch another addr bit\r
- saddr<<=1;\r
- if(SRam.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask\r
- saddr|=d&1;\r
- if(scyc==17||scyc==26) {\r
- elprintf(EL_EEPROM, "eeprom: addr reg done: %x", saddr);\r
- if(scyc==17&&SRam.eeprom_type==2) { saddr&=0xff; saddr|=(ssa<<7)&0x700; } // add device bits too\r
- }\r
- }\r
- } else {\r
- // slave address\r
- ssa<<=1; ssa|=d&1;\r
- if(scyc==8) elprintf(EL_EEPROM, "eeprom: slave done: %x", ssa);\r
- }\r
- } else {\r
- // X24C01\r
- if(scyc == 9); // ACK cycle, do nothing\r
- else if(scyc > 9) {\r
- if(!(saddr&1)) {\r
- // data write\r
- unsigned char *pm=SRam.data+(saddr>>1);\r
- *pm <<= 1; *pm |= d&1;\r
- if(scyc == 17) {\r
- saddr=(saddr&0xf9)|((saddr+2)&6); // only 2 lowest bits are incremented\r
- elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr>>1, *pm);\r
- }\r
- SRam.changed = 1;\r
- }\r
- } else {\r
- // we latch another addr bit\r
- saddr<<=1; saddr|=d&1; saddr&=0xff;\r
- if(scyc==8) elprintf(EL_EEPROM, "eeprom: addr done: %x", saddr>>1);\r
- }\r
- }\r
- }\r
-\r
- sreg &= ~3; sreg |= d&3; // remember SCL and SDA\r
- Pico.m.sram_status = (unsigned char) sreg;\r
- Pico.m.eeprom_cycle= (unsigned char) scyc;\r
- Pico.m.eeprom_slave= (unsigned char) ssa;\r
- Pico.m.eeprom_addr = (unsigned short)saddr;\r
-}\r
-\r
-PICO_INTERNAL_ASM unsigned int EEPROM_read(void)\r
-{\r
- unsigned int shift, d;\r
- unsigned int sreg, saddr, scyc, ssa, interval;\r
-\r
- // flush last pending write\r
- EEPROM_write(Pico.m.sram_status>>6);\r
-\r
- sreg = Pico.m.sram_status; saddr = Pico.m.eeprom_addr&0x1fff; scyc = Pico.m.eeprom_cycle; ssa = Pico.m.eeprom_slave;\r
- interval = SekCyclesDoneT()-lastSSRamWrite;\r
- d = (sreg>>6)&1; // use SDA as "open bus"\r
-\r
- // NBA Jam is nasty enough to read <before> raising the SCL and starting the new cycle.\r
- // this is probably valid because data changes occur while SCL is low and data can be read\r
- // before it's actual cycle begins.\r
- if (!(sreg&0x80) && interval >= 24) {\r
- elprintf(EL_EEPROM, "eeprom: early read, cycles=%i", interval);\r
- scyc++;\r
- }\r
-\r
- if (!(sreg & 8)); // not started, use open bus\r
- else if (scyc == 9 || scyc == 18 || scyc == 27) {\r
- elprintf(EL_EEPROM, "eeprom: r ack");\r
- d = 0;\r
- } else if (scyc > 9 && scyc < 18) {\r
- // started and first command word received\r
- shift = 17-scyc;\r
- if (SRam.eeprom_type) {\r
- // X24C02+\r
- if (ssa&1) {\r
- elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg);\r
- if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr]);\r
- d = (SRam.data[saddr]>>shift)&1;\r
- }\r
- } else {\r
- // X24C01\r
- if (saddr&1) {\r
- elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr>>1, scyc, sreg);\r
- if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr>>1]);\r
- d = (SRam.data[saddr>>1]>>shift)&1;\r
- }\r
- }\r
- }\r
-\r
- return (d << SRam.eeprom_bit_out);\r
-}\r
-\r
-PICO_INTERNAL void EEPROM_upd_pending(unsigned int a, unsigned int d)\r
-{\r
- unsigned int d1, sreg = Pico.m.sram_status;\r
-\r
- if (!((SRam.eeprom_abits^a)&1))\r
- {\r
- // SCL\r
- sreg &= ~0x80;\r
- d1 = (d >> SRam.eeprom_bit_cl) & 1;\r
- sreg |= d1<<7;\r
- }\r
- if (!(((SRam.eeprom_abits>>1)^a)&1))\r
- {\r
- // SDA in\r
- sreg &= ~0x40;\r
- d1 = (d >> SRam.eeprom_bit_in) & 1;\r
- sreg |= d1<<6;\r
- }\r
-\r
- Pico.m.sram_status = (unsigned char) sreg;\r
-}\r
-\r
-\r
#ifndef _ASM_MISC_C\r
typedef struct\r
{\r
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)
\r
PicoInitMCD();\r
PicoSVPInit();\r
-\r
- SRam.data=0;\r
}\r
\r
// to be called once on emu exit\r
PicoCartUnload();\r
z80_exit();\r
\r
- if (SRam.data) free(SRam.data); SRam.data=0;\r
+ if (SRam.data)\r
+ free(SRam.data);\r
}\r
\r
void PicoPower(void)\r
{\r
- unsigned char sram_status = Pico.m.sram_status; // must be preserved\r
-\r
Pico.m.frame_count = 0;\r
\r
// clear all memory of the emulated machine\r
if (PicoAHW & PAHW_MCD)\r
PicoPowerMCD();\r
\r
- Pico.m.sram_status = sram_status;\r
PicoReset();\r
}\r
\r
\r
int PicoReset(void)\r
{\r
- unsigned char sram_status = Pico.m.sram_status; // must be preserved\r
-\r
if (Pico.romsize <= 0)\r
return 1;\r
\r
SekInitIdleDet();\r
\r
// reset sram state; enable sram access by default if it doesn't overlap with ROM\r
- Pico.m.sram_status = sram_status & (SRS_DETECTED|SRS_EEPROM);\r
- if (!(Pico.m.sram_status & SRS_EEPROM) && Pico.romsize <= SRam.start)\r
- Pico.m.sram_status |= SRS_MAPPED;\r
+ Pico.m.sram_reg = 0;\r
+ if ((SRam.flags & SRF_EEPROM) || Pico.romsize <= SRam.start)\r
+ Pico.m.sram_reg |= SRR_MAPPED;\r
\r
- elprintf(EL_STATUS, "sram: det: %i; eeprom: %i; start: %06x; end: %06x",\r
- !!(sram_status & SRS_DETECTED), !!(sram_status & SRS_EEPROM), SRam.start, SRam.end);\r
+ if (SRam.flags & SRF_ENABLED)\r
+ elprintf(EL_STATUS, "sram: %06x - %06x; eeprom: %i", SRam.start, SRam.end,\r
+ !!(SRam.flags & SRF_EEPROM));\r
\r
return 0;\r
}\r
#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;
-
- 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
+ static FILE *f[0x10] = { NULL, };
+ char fname[32];
+ int num = PicoPicohw.r12 & 0xf;
- a&=0xffffff;
+ 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);
+}
+*/
- if ((a&0xfffff0)==0xc00000) { // VDP
- d=PicoVideoRead8(a);
- goto end;
- }
+static u32 PicoRead8_pico(u32 a)
+{
+ u32 d = 0;
- if ((a&0xffffe0)==0x800000) // Pico I/O
+ if ((a & 0xffffe0) == 0x800000) // Pico I/O
{
switch (a & 0x1f)
{
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, "r16: %06x, %04x @%06x", a&0xffffff, d, SekPc);
+ elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, 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)
{
PicoReratePico();
}
else
- elprintf(EL_UIO, "w16: %06x, %04x", a&0xffffff, d);
-
- //elprintf(EL_UIO, "w16: %06x, %04x", a&0xffffff, d);
-}
-
-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);
+ elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
}
-#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);
}
PICO_INTERNAL void PicoInitPico(void)
{
- elprintf(EL_STATUS, "Pico detected");
+ elprintf(EL_STATUS, "Pico startup");
PicoLineHook = PicoLinePico;
PicoResetHook = PicoResetPico;
char dirtyPal; // 06 Is the palette dirty (1 - change @ this frame, 2 - some time before)\r
unsigned char hardware; // 07 Hardware value for country\r
unsigned char pal; // 08 1=PAL 0=NTSC\r
- unsigned char sram_status; // 09 SRAM status. See SRS_* below\r
+ unsigned char sram_reg; // 09 SRAM reg. See SRR_* below\r
unsigned short z80_bank68k; // 0a\r
unsigned short z80_lastaddr; // this is for Z80 faking\r
- unsigned char z80_fakeval;\r
+ unsigned char pad0;\r
unsigned char z80_reset; // z80 reset held\r
unsigned char padDelay[2]; // 10 gamepad phase time outs, so we count a delay\r
unsigned short eeprom_addr; // EEPROM address register\r
- unsigned char eeprom_cycle; // EEPROM SRAM cycle number\r
+ unsigned char eeprom_cycle; // EEPROM cycle number\r
unsigned char eeprom_slave; // EEPROM slave word for X24C02 and better SRAMs\r
- unsigned char prot_bytes[2]; // simple protection faking\r
+ unsigned char eeprom_status;\r
+ unsigned char pad1;\r
unsigned short dma_xfers; // 18\r
- unsigned char pad[2];\r
+ unsigned char eeprom_wb[2]; // EEPROM latch/write buffer\r
unsigned int frame_count; // 1c for movies and idle det\r
};\r
\r
};\r
\r
// sram\r
-#define SRS_MAPPED (1 << 0)\r
-#define SRS_READONLY (1 << 1)\r
-#define SRS_EEPROM (1 << 2)\r
-#define SRS_DETECTED (1 << 4)\r
+#define SRR_MAPPED (1 << 0)\r
+#define SRR_READONLY (1 << 1)\r
+\r
+#define SRF_ENABLED (1 << 0)\r
+#define SRF_EEPROM (1 << 1)\r
\r
struct PicoSRAM\r
{\r
unsigned char *data; // actual data\r
unsigned int start; // start address in 68k address space\r
unsigned int end;\r
- unsigned char unused1; // 0c: unused\r
+ unsigned char flags; // 0c: SRF_*\r
unsigned char unused2;\r
unsigned char changed;\r
- unsigned char eeprom_type; // eeprom type: 0: 7bit (24C01), 2: device with 2 addr words (X24C02+), 3: dev with 3 addr words\r
- unsigned char eeprom_abits; // eeprom access must be odd addr for: bit0 ~ cl, bit1 ~ out\r
+ unsigned char eeprom_type; // eeprom type: 0: 7bit (24C01), 2: 2 addr words (X24C02+), 3: 3 addr words\r
+ unsigned char unused3;\r
unsigned char eeprom_bit_cl; // bit number for cl\r
unsigned char eeprom_bit_in; // bit number for in\r
unsigned char eeprom_bit_out; // bit number for out\r
+ unsigned int size;\r
};\r
\r
// MCD\r
extern areaclose *areaClose;\r
\r
// cart.c\r
+extern void (*PicoCartMemSetup)(void);\r
extern void (*PicoCartUnloadHook)(void);\r
\r
// debug.c\r
PICO_INTERNAL void PicoInitPc(unsigned int pc);\r
PICO_INTERNAL unsigned int PicoCheckPc(unsigned int pc);\r
PICO_INTERNAL void PicoMemSetup(void);\r
-PICO_INTERNAL void PicoMemResetHooks(void);\r
-extern unsigned int (*PicoRead16Hook)(unsigned int a, int realsize);\r
-extern void (*PicoWrite8Hook) (unsigned int a,unsigned int d,int realsize);\r
-extern void (*PicoWrite16Hook)(unsigned int a,unsigned int d,int realsize);\r
unsigned int PicoRead8_io(unsigned int a);\r
unsigned int PicoRead16_io(unsigned int a);\r
void PicoWrite8_io(unsigned int a, unsigned int d);\r
extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp);\r
\r
// misc.c\r
-PICO_INTERNAL void EEPROM_write(unsigned int d);\r
-PICO_INTERNAL void EEPROM_upd_pending(unsigned int a, unsigned int d);\r
-PICO_INTERNAL_ASM unsigned int EEPROM_read(void);\r
PICO_INTERNAL_ASM void memcpy16(unsigned short *dest, unsigned short *src, int count);\r
PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count);\r
PICO_INTERNAL_ASM void memcpy32(int *dest, int *src, int count); // 32bit word count\r
PICO_INTERNAL_ASM void memset32(int *dest, int c, int count);\r
\r
+// eeprom.c\r
+void EEPROM_write8(unsigned int a, unsigned int d);\r
+void EEPROM_write16(unsigned int d);\r
+unsigned int EEPROM_read(void);\r
+\r
// z80 functionality wrappers\r
PICO_INTERNAL void z80_init(void);\r
PICO_INTERNAL void z80_pack(unsigned char *data);\r
void PicoFrameMS(void);\r
void PicoFrameDrawOnlyMS(void);\r
\r
+/* avoid dependency on newer glibc */\r
+static __inline int isspace_(int c)\r
+{\r
+ return (0x09 <= c && c <= 0x0d) || c == ' ';\r
+}\r
+\r
// emulation event logging\r
#ifndef EL_LOGMASK\r
#define EL_LOGMASK 0\r
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
int truncate = 1;\r
if (PicoAHW & PAHW_MCD)\r
{\r
- if (PicoOpt&POPT_EN_MCD_RAMCART) {\r
+ if (PicoOpt & POPT_EN_MCD_RAMCART) {\r
sram_size = 0x12000;\r
sram_data = SRam.data;\r
if (sram_data)\r
truncate = 0; // the .brm may contain RAM cart data after normal brm\r
}\r
} else {\r
- sram_size = SRam.end-SRam.start+1;\r
- if (Pico.m.sram_status & SRS_EEPROM)\r
- sram_size = 0x2000;\r
+ sram_size = SRam.size;\r
sram_data = SRam.data;\r
}\r
if (!sram_data) return 0; // SRam forcefully disabled for this game\r
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)
ifeq "$(amalgamate)" "1"\r
OBJS += ../../picoAll.o\r
else\r
-OBJS += pico/area.o pico/cart.o pico/memory.o pico/misc.o pico/pico.o pico/sek.o pico/z80if.o \\r
- pico/videoport.o pico/draw2.o pico/draw.o pico/mode4.o pico/sms.o pico/patch.o pico/debug.o\r
+OBJS += pico/area.o pico/cart.o pico/memory.o pico/pico.o pico/sek.o pico/z80if.o \\r
+ pico/videoport.o pico/draw2.o pico/draw.o pico/mode4.o pico/sms.o \\r
+ pico/misc.o pico/eeprom.o pico/patch.o pico/debug.o\r
# Pico - CD\r
OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \\r
pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \\r
gp2x_video_setpalette(localPal, ret);\r
}\r
// a hack for VR\r
- if (PicoRead16Hook == PicoSVPRead16)\r
+ if (PicoAHW & PAHW_SVP)\r
memset32((int *)(PicoDraw2FB+328*8+328*223), 0xe0e0e0e0, 328);\r
// do actual copy\r
vidcpyM2(g_screen_ptr, PicoDraw2FB+328*8,\r
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 \
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
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;
#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__)
// gp2x_video_setpalette(localPal, 0x40);\r
}\r
// a hack for VR\r
- if (PicoRead16Hook == PicoSVPRead16)\r
+ if (PicoAHW & PAHW_SVP)\r
memset32((int *)(PicoDraw2FB+328*8+328*223), 0xe0e0e0e0, 328);\r
// do actual copy\r
vidCpyM2((unsigned char *)g_screen_ptr+g_screen_width*8, PicoDraw2FB+328*8);\r