#include "../unzip/unzip_stream.h"\r
\r
\r
-static char *rom_exts[] = { "bin", "gen", "smd", "iso" };\r
+static const char *rom_exts[] = { "bin", "gen", "smd", "iso", "sms", "gg", "sg" };\r
\r
void (*PicoCartUnloadHook)(void) = NULL;\r
\r
if (zipentry->uncompressed_size >= 128*1024) goto found_rom_zip;\r
if (strlen(zipentry->name) < 5) continue;\r
\r
- ext = zipentry->name+strlen(zipentry->name)-3;\r
+ ext = zipentry->name + strlen(zipentry->name) - 2;\r
+ if (ext[-1] != '.') ext--;\r
+ if (ext[-1] != '.') ext--;\r
+\r
for (i = 0; i < sizeof(rom_exts)/sizeof(rom_exts[0]); i++)\r
if (strcasecmp(ext, rom_exts[i]) == 0) goto found_rom_zip;\r
}\r
return rom;\r
}\r
\r
-int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize)\r
+int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms)\r
{\r
unsigned char *rom=NULL; int size, bytes_read;\r
if (f==NULL) return 1;\r
return 3;\r
}\r
\r
- // maybe we are loading MegaCD BIOS?\r
- if (!(PicoAHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) ||\r
- !strncmp((char *)rom+0x128, "BOOT", 4))) {\r
- PicoAHW |= PAHW_MCD;\r
- rom = cd_realloc(rom, size);\r
- }\r
+ if (!is_sms)\r
+ {\r
+ // maybe we are loading MegaCD BIOS?\r
+ if (!(PicoAHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) ||\r
+ !strncmp((char *)rom+0x128, "BOOT", 4))) {\r
+ PicoAHW |= PAHW_MCD;\r
+ rom = cd_realloc(rom, size);\r
+ }\r
\r
- // Check for SMD:\r
- if (size >= 0x4200 && (size&0x3fff)==0x200 &&\r
- ((rom[0x2280] == 'S' && rom[0x280] == 'E') || (rom[0x280] == 'S' && rom[0x2281] == 'E'))) {\r
- DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD\r
+ // Check for SMD:\r
+ if (size >= 0x4200 && (size&0x3fff)==0x200 &&\r
+ ((rom[0x2280] == 'S' && rom[0x280] == 'E') || (rom[0x280] == 'S' && rom[0x2281] == 'E'))) {\r
+ DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD\r
+ }\r
+ else Byteswap(rom,size); // Just byteswap\r
}\r
- else Byteswap(rom,size); // Just byteswap\r
\r
if (prom) *prom=rom;\r
if (psize) *psize=size;\r
PicoCartUnloadHook = NULL;\r
}\r
\r
- PicoAHW &= PAHW_MCD;\r
+ PicoAHW &= PAHW_MCD|PAHW_SMS;\r
\r
PicoMemResetHooks();\r
PicoDmaHook = NULL;\r
\r
PicoMemReset();\r
\r
- if (!(PicoAHW & PAHW_MCD))\r
+ if (!(PicoAHW & (PAHW_MCD|PAHW_SMS)))\r
PicoCartDetect();\r
\r
// setup correct memory map for loaded ROM\r
case PAHW_SVP: PicoMemSetup(); break;\r
case PAHW_MCD: PicoMemSetupCD(); break;\r
case PAHW_PICO: PicoMemSetupPico(); break;\r
+ case PAHW_SMS: PicoMemSetupMS(); break;\r
}\r
PicoMemReset();\r
\r
- PicoPower();\r
+ if (PicoAHW & PAHW_SMS)\r
+ PicoPowerMS();\r
+ else\r
+ PicoPower();\r
+\r
return 0;\r
}\r
\r
void PicoCartUnload(void)\r
{\r
+ if (PicoCartUnloadHook != NULL) {\r
+ PicoCartUnloadHook();\r
+ PicoCartUnloadHook = NULL;\r
+ }\r
+\r
if (Pico.rom != NULL) {\r
SekFinishIdleDet();\r
free(Pico.rom);\r
PicoFrameMCD();\r
return;\r
}\r
+ else if (PicoAHW & PAHW_SMS) {\r
+ PicoFrameMS();\r
+ return;\r
+ }\r
\r
//if(Pico.video.reg[12]&0x2) Pico.video.status ^= 0x10; // change odd bit in interlace mode\r
\r
#define PAHW_32X (1<<1)\r
#define PAHW_SVP (1<<2)\r
#define PAHW_PICO (1<<3)\r
+#define PAHW_SMS (1<<4)\r
extern int PicoAHW; // Pico active hw\r
extern int PicoVer;\r
extern int PicoSkipFrame; // skip rendering frame, but still do sound (if enabled) and emulation stuff\r
size_t pm_read(void *ptr, size_t bytes, pm_file *stream);\r
int pm_seek(pm_file *stream, long offset, int whence);\r
int pm_close(pm_file *fp);\r
-int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize);\r
+int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms);\r
int PicoCartInsert(unsigned char *rom,unsigned int romsize);\r
void Byteswap(unsigned char *data,int len);\r
void PicoCartUnload(void);\r
PICO_INTERNAL void PsndGetSamples(int y);\r
extern int PsndDacLine;\r
\r
+// sms.c\r
+void PicoPowerMS(void);\r
+void PicoMemSetupMS(void);\r
+void PicoFrameMS(void);\r
+\r
// emulation event logging\r
#ifndef EL_LOGMASK\r
#define EL_LOGMASK 0\r
#define cdprintf(x...)\r
#endif\r
\r
-#if defined(__GNUC__) && !defined(ARM)\r
+#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3\r
#define MEMH_FUNC __attribute__((aligned(4)))\r
#else\r
#define MEMH_FUNC\r
--- /dev/null
+#include "pico_int.h"
+
+static unsigned char z80_sms_in(unsigned short p)
+{
+ elprintf(EL_ANOMALY, "Z80 port %04x read", p);
+ return 0xff;
+}
+
+static void z80_sms_out(unsigned short p, unsigned char d)
+{
+ elprintf(EL_ANOMALY, "Z80 port %04x write %02x", p, d);
+}
+
+static unsigned char MEMH_FUNC xread(unsigned short a)
+{
+ elprintf(EL_ANOMALY, "Z80 read [%04x]", a);
+ return 0;
+}
+
+static void MEMH_FUNC xwrite(unsigned int a, unsigned char data)
+{
+ elprintf(EL_ANOMALY, "Z80 write [%04x] %02x", a, data);
+}
+
+void PicoPowerMS(void)
+{
+}
+
+void PicoMemSetupMS(void)
+{
+ z80_map_set(z80_read_map, 0x0000, 0xbfff, Pico.rom, 0);
+ z80_map_set(z80_read_map, 0xc000, 0xdfff, Pico.zram, 0);
+ z80_map_set(z80_read_map, 0xe000, 0xffff, xread, 1);
+
+ z80_map_set(z80_write_map, 0x0000, 0xbfff, Pico.rom, 0);
+ z80_map_set(z80_write_map, 0xc000, 0xdfff, Pico.zram, 0);
+ z80_map_set(z80_write_map, 0xe000, 0xffff, xwrite, 1);
+
+#ifdef _USE_DRZ80
+ drZ80.z80_in = z80_sms_in;
+ drZ80.z80_out = z80_sms_out;
+#endif
+#ifdef _USE_CZ80
+ Cz80_Set_Fetch(&CZ80, 0x0000, 0xbfff, (UINT32)Pico.rom);
+ Cz80_Set_Fetch(&CZ80, 0xc000, 0xdfff, (UINT32)Pico.zram);
+ Cz80_Set_INPort(&CZ80, z80_sms_in);
+ Cz80_Set_OUTPort(&CZ80, z80_sms_out);
+#endif
+}
+
+void PicoFrameMS(void)
+{
+ z80_run(OSC_NTSC / 13 / 60);
+}
+
drZ80.z80irqvector = 0xff0000; // RST 38h
drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1;
// drZ80 is locked in single bank
- drZ80.Z80SP_BASE = z80_read_map[0] << 1;
+ drZ80.Z80SP_BASE = ((PicoAHW & PAHW_SMS) ?
+ z80_read_map[0xc000 >> Z80_MEM_SHIFT] : z80_read_map[0]) << 1;
// drZ80.Z80SP = drZ80.z80_rebaseSP(0x2000); // 0xf000 ?
#endif
#ifdef _USE_CZ80
\r
static unsigned char id_header[0x100];\r
\r
-/* checks if fname points to valid MegaCD image\r
- * if so, checks for suitable BIOS */\r
+/* checks if fname points to valid MegaCD image */\r
static int emu_cd_check(int *pregion, const char *fname_in)\r
{\r
const char *fname = fname_in;\r
return type;\r
}\r
\r
+static int detect_media(const char *fname)\r
+{\r
+ static const short sms_offsets[] = { 0x7ff0, 0x3ff0, 0x1ff0 };\r
+ pm_file *pmf;\r
+ char buff[32];\r
+ char ext[5];\r
+ int i;\r
+\r
+ get_ext(fname, ext);\r
+\r
+ // detect wrong extensions\r
+ if (!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) // s.gz ~ .mds.gz\r
+ return PM_BAD;\r
+\r
+ /* don't believe in extensions, except .cue */\r
+ if (strcasecmp(ext, ".cue") == 0)\r
+ return PM_CD;\r
+\r
+ pmf = pm_open(fname);\r
+ if (pmf == NULL)\r
+ return PM_BAD;\r
+\r
+ if (pm_read(buff, 32, pmf) != 32) {\r
+ pm_close(pmf);\r
+ return PM_BAD;\r
+ }\r
+\r
+ if (strncasecmp("SEGADISCSYSTEM", buff + 0x00, 14) == 0 ||\r
+ strncasecmp("SEGADISCSYSTEM", buff + 0x10, 14) == 0) {\r
+ pm_close(pmf);\r
+ return PM_CD;\r
+ }\r
+\r
+ for (i = 0; i < array_size(sms_offsets); i++) {\r
+ if (pm_seek(pmf, sms_offsets[i], SEEK_SET) != sms_offsets[i])\r
+ goto not_mark3; /* actually it could be but can't be detected */\r
+\r
+ if (pm_read(buff, 16, pmf) != 16)\r
+ goto not_mark3;\r
+\r
+ if (strncasecmp("TMR SEGA", buff, 8) == 0) {\r
+ pm_close(pmf);\r
+ return PM_MARK3;\r
+ }\r
+ }\r
+\r
+not_mark3:\r
+ pm_close(pmf);\r
+ /* the main emu function is to emulate MD, so assume MD */\r
+ return PM_MD_CART;\r
+}\r
+\r
static int extract_text(char *dest, const unsigned char *src, int len, int swab)\r
{\r
char *p = dest;\r
}\r
\r
// note: this function might mangle rom_fname\r
+// XXX: portions of this code should move to pico/\r
int emu_reload_rom(char *rom_fname)\r
{\r
unsigned int rom_size = 0;\r
unsigned char *rom_data = NULL;\r
char ext[5];\r
pm_file *rom = NULL;\r
- int ret, cd_state, cd_region, cfg_loaded = 0;\r
+ int cd_state = CIT_NOT_CD;\r
+ int ret, media_type, cd_region;\r
+ int cfg_loaded = 0, bad_rom = 0;\r
\r
lprintf("emu_ReloadRom(%s)\n", rom_fname);\r
\r
get_ext(rom_fname, ext);\r
\r
- // detect wrong extensions\r
- if (!strcmp(ext, ".srm") || !strcmp(ext, "s.gz") || !strcmp(ext, ".mds")) { // s.gz ~ .mds.gz\r
- me_update_msg("Not a ROM/CD selected.");\r
- return 0;\r
- }\r
-\r
- PicoPatchUnload();\r
-\r
// check for movie file\r
if (movie_data) {\r
free(movie_data);\r
get_ext(rom_fname, ext);\r
}\r
\r
+ media_type = detect_media(rom_fname);\r
+ if (media_type == PM_BAD) {\r
+ me_update_msg("Not a ROM/CD img selected.");\r
+ return 0;\r
+ }\r
+\r
shutdown_MCD();\r
+ PicoPatchUnload();\r
\r
- // check for MegaCD image\r
- cd_state = emu_cd_check(&cd_region, rom_fname);\r
- if (cd_state >= 0 && cd_state != CIT_NOT_CD)\r
+ if (media_type == PM_CD)\r
{\r
- PicoAHW |= PAHW_MCD;\r
- // valid CD image, check for BIOS..\r
+ // check for MegaCD image\r
+ cd_state = emu_cd_check(&cd_region, rom_fname);\r
+ if (cd_state >= 0 && cd_state != CIT_NOT_CD)\r
+ {\r
+ // valid CD image, check for BIOS..\r
\r
- // we need to have config loaded at this point\r
- ret = emu_read_config(1, 0);\r
- if (!ret) emu_read_config(0, 0);\r
- cfg_loaded = 1;\r
+ // we need to have config loaded at this point\r
+ ret = emu_read_config(1, 0);\r
+ if (!ret) emu_read_config(0, 0);\r
+ cfg_loaded = 1;\r
+\r
+ if (PicoRegionOverride) {\r
+ cd_region = PicoRegionOverride;\r
+ lprintf("override region to %s\n", cd_region != 4 ?\r
+ (cd_region == 8 ? "EU" : "JAP") : "USA");\r
+ }\r
+ if (!find_bios(cd_region, &used_rom_name))\r
+ return 0;\r
\r
- if (PicoRegionOverride) {\r
- cd_region = PicoRegionOverride;\r
- lprintf("overrided region to %s\n", cd_region != 4 ? (cd_region == 8 ? "EU" : "JAP") : "USA");\r
+ get_ext(used_rom_name, ext);\r
+ PicoAHW |= PAHW_MCD;\r
}\r
- if (!find_bios(cd_region, &used_rom_name)) {\r
- PicoAHW &= ~PAHW_MCD;\r
+ else {\r
+ me_update_msg("Invalid CD image");\r
return 0;\r
}\r
-\r
- get_ext(used_rom_name, ext);\r
}\r
- else\r
- {\r
- if (PicoAHW & PAHW_MCD) Stop_CD();\r
- PicoAHW &= ~PAHW_MCD;\r
+ else if (media_type == PM_MARK3) {\r
+ lprintf("detected SMS ROM\n");\r
+ PicoAHW = PAHW_SMS;\r
}\r
\r
rom = pm_open(used_rom_name);\r
- if (!rom) {\r
- me_update_msg("Failed to open ROM/CD image");\r
- goto fail;\r
- }\r
-\r
- if (cd_state < 0) {\r
- me_update_msg("Invalid CD image");\r
- goto fail;\r
+ if (rom == NULL) {\r
+ me_update_msg("Failed to open ROM");\r
+ return 0;\r
}\r
\r
menu_romload_prepare(used_rom_name); // also CD load\r
PicoCartUnload();\r
rom_loaded = 0;\r
\r
- if ( (ret = PicoCartLoad(rom, &rom_data, &rom_size)) ) {\r
+ ret = PicoCartLoad(rom, &rom_data, &rom_size, (PicoAHW & PAHW_SMS) ? 1 : 0);\r
+ pm_close(rom);\r
+ if (ret != 0) {\r
if (ret == 2) me_update_msg("Out of memory");\r
else if (ret == 3) me_update_msg("Read failed");\r
else me_update_msg("PicoCartLoad() failed.");\r
- goto fail2;\r
+ goto fail;\r
}\r
- pm_close(rom);\r
- rom = NULL;\r
-\r
- // detect wrong files (Pico crashes on very small files), also see if ROM EP is good\r
- if (rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 ||\r
- ((*(unsigned char *)(rom_data+4)<<16)|(*(unsigned short *)(rom_data+6))) >= (int)rom_size) {\r
- if (rom_data) free(rom_data);\r
- me_update_msg("Not a ROM selected.");\r
- goto fail2;\r
+\r
+ // detect wrong files\r
+ if (strncmp((char *)rom_data, "Pico", 4) == 0)\r
+ bad_rom = 1;\r
+ else if (!(PicoAHW & PAHW_SMS)) {\r
+ unsigned short *d = (unsigned short *)(rom_data + 4);\r
+ if ((((d[0] << 16) | d[1]) & 0xffffff) >= (int)rom_size) {\r
+ lprintf("bad reset vector\n");\r
+ bad_rom = 1;\r
+ }\r
+ }\r
+\r
+ if (bad_rom) {\r
+ me_update_msg("Bad ROM detected.");\r
+ goto fail;\r
}\r
\r
// load config for this ROM (do this before insert to get correct region)\r
if (!ret) emu_read_config(0, 0);\r
}\r
\r
- lprintf("PicoCartInsert(%p, %d);\n", rom_data, rom_size);\r
if (PicoCartInsert(rom_data, rom_size)) {\r
me_update_msg("Failed to load ROM.");\r
- goto fail2;\r
+ goto fail;\r
}\r
\r
// insert CD if it was detected\r
if (cd_state != CIT_NOT_CD) {\r
ret = Insert_CD(rom_fname, cd_state);\r
if (ret != 0) {\r
+ PicoCartUnload();\r
+ rom_data = NULL; // freed by unload\r
me_update_msg("Insert_CD() failed, invalid CD image?");\r
- goto fail2;\r
+ goto fail;\r
}\r
}\r
\r
}\r
else\r
{\r
+ const char *sys_name, *tv_standard;\r
+ int fps;\r
+\r
+ if (PicoAHW & PAHW_SMS) {\r
+ sys_name = "Master System";\r
+ } else {\r
+ sys_name = "MegaDrive";\r
+ if ((Pico.m.hardware&0xc0) == 0x80)\r
+ sys_name = "Genesis";\r
+ }\r
+ tv_standard = Pico.m.pal ? "PAL" : "NTSC";\r
+ fps = Pico.m.pal ? 50 : 60;\r
+\r
+ emu_status_msg("%s %s / %dFPS", tv_standard, sys_name, fps);\r
+\r
PicoOpt &= ~POPT_DIS_VDP_FIFO;\r
- emu_status_msg(Pico.m.pal ? "PAL SYSTEM / 50 FPS" : "NTSC SYSTEM / 60 FPS");\r
}\r
\r
strncpy(rom_fname_loaded, rom_fname, sizeof(rom_fname_loaded)-1);\r
\r
return 1;\r
\r
-fail2:\r
- menu_romload_end();\r
fail:\r
- if (rom != NULL) pm_close(rom);\r
+ if (rom_data)\r
+ free(rom_data);\r
+ menu_romload_end();\r
return 0;\r
}\r
\r
extern "C" {
#endif
+#define array_size(x) (sizeof(x) / sizeof(x[0]))
+
extern void *g_screen_ptr;
#if SCREEN_SIZE_FIXED
PGS_SuspendWake, /* PSP */
};
+// media types
+enum {
+ PM_BAD = 0,
+ PM_MD_CART, /* also 32x */
+ PM_MARK3,
+ PM_CD,
+};
void emu_init(void);
void emu_finish(void);
#include <pico/pico_int.h>\r
#include <pico/patch.h>\r
\r
-#define array_size(x) (sizeof(x) / sizeof(x[0]))\r
-\r
static char static_buff[64];\r
static char menu_error_msg[64] = { 0, };\r
static int menu_error_time = 0;\r
CFLAGS += -ftracer -fstrength-reduce -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math
CFLAGS += -fprofile-generate
else
-CFLAGS = -ggdb -Wall
+CFLAGS = -ggdb -Wall -falign-functions=2
endif
DEFINES = _UNZIP_SUPPORT IO_STATS IN_EVDEV
CFLAGS += -I../.. -I.
# Pico
OBJS += pico/area.o pico/cart.o pico/memory.o pico/misc.o pico/pico.o pico/sek.o \
- pico/videoport.o pico/draw2.o pico/draw.o pico/z80if.o pico/patch.o pico/debug.o
+ pico/videoport.o pico/draw2.o pico/draw.o pico/z80if.o pico/patch.o \
+ pico/sms.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 \