From: twinaphex Date: Tue, 29 Jan 2013 00:59:01 +0000 (+0100) Subject: Merge git://github.com/notaz/pcsx_rearmed X-Git-Tag: r24l~970 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2dfdc938c99783e187f60c1d13db73e0ee434c92;hp=e5f4d90401d099d5191f95e9f771ab5a81c87ed8;p=pcsx_rearmed.git Merge git://github.com/notaz/pcsx_rearmed --- diff --git a/frontend/libpicofe b/frontend/libpicofe index 4db02226..215e7ed2 160000 --- a/frontend/libpicofe +++ b/frontend/libpicofe @@ -1 +1 @@ -Subproject commit 4db02226eb3c80f49f5c412f7718c437c5e817fc +Subproject commit 215e7ed2510e191664b611a578ffb987cf4fdab3 diff --git a/frontend/libretro.c b/frontend/libretro.c index e7153ac6..4f6879ed 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -35,6 +35,7 @@ static bool vout_can_dupe; static int samples_sent, samples_to_send; static int plugins_opened; +static int is_pal_mode; /* memory card data */ extern char Mcd1Data[MCD_SIZE]; @@ -182,6 +183,7 @@ void pl_frame_limit(void) void pl_timing_prepare(int is_pal) { + is_pal_mode = is_pal; } void plat_trigger_vibrate(int is_strong) @@ -254,7 +256,7 @@ void retro_get_system_info(struct retro_system_info *info) void retro_get_system_av_info(struct retro_system_av_info *info) { memset(info, 0, sizeof(*info)); - info->timing.fps = 60; + info->timing.fps = is_pal_mode ? 50 : 60; info->timing.sample_rate = 44100; info->geometry.base_width = 320; info->geometry.base_height = 240; @@ -446,7 +448,7 @@ void retro_unload_game(void) unsigned retro_get_region(void) { - return RETRO_REGION_NTSC; + return is_pal_mode ? RETRO_REGION_PAL : RETRO_REGION_NTSC; } void *retro_get_memory_data(unsigned id) @@ -501,7 +503,7 @@ void retro_run(void) stop = 0; psxCpu->Execute(); - samples_to_send += 44100 / 60; + samples_to_send += is_pal_mode ? 44100 / 50 : 44100 / 60; video_cb((vout_fb_dirty || !vout_can_dupe) ? vout_buf : NULL, vout_width, vout_height, vout_width * 2); diff --git a/frontend/main.c b/frontend/main.c index 43a1a032..0f0e641b 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -33,6 +33,8 @@ #include "libpicofe/readpng.h" static void toggle_fast_forward(int force_off); +static void check_profile(void); +static void check_memcards(void); #endif #ifndef BOOT_MSG #define BOOT_MSG "Booting up..." @@ -66,28 +68,6 @@ static void make_path(char *buf, size_t size, const char *dir, const char *fname #define MAKE_PATH(buf, dir, fname) \ make_path(buf, sizeof(buf), dir, fname) -static void create_profile_dir(const char *directory) { - char path[MAXPATHLEN]; - - MAKE_PATH(path, directory, NULL); - mkdir(path, S_IRWXU | S_IRWXG); -} - -static void CheckSubDir() { - // make sure that ~/.pcsx exists - create_profile_dir(PCSX_DOT_DIR); - - create_profile_dir(BIOS_DIR); - create_profile_dir(MEMCARD_DIR); - create_profile_dir(STATES_DIR); - create_profile_dir(PLUGINS_DIR); - create_profile_dir(PLUGINS_CFG_DIR); - create_profile_dir(CHEATS_DIR); - create_profile_dir(PATCHES_DIR); - create_profile_dir(PCSX_DOT_DIR "cfg"); - create_profile_dir("/screenshots/"); -} - static int get_gameid_filename(char *buf, int size, const char *fmt, int i) { char trimlabel[33]; int j; @@ -126,9 +106,12 @@ void set_cd_image(const char *fname) static void set_default_paths(void) { +#ifndef NO_FRONTEND + snprintf(Config.PatchesDir, sizeof(Config.PatchesDir), "." PATCHES_DIR); MAKE_PATH(Config.Mcd1, MEMCARD_DIR, "card1.mcd"); MAKE_PATH(Config.Mcd2, MEMCARD_DIR, "card2.mcd"); strcpy(Config.BiosDir, "bios"); +#endif strcpy(Config.PluginsDir, "plugins"); strcpy(Config.Gpu, "builtin_gpu"); @@ -137,8 +120,6 @@ static void set_default_paths(void) strcpy(Config.Pad1, "builtin_pad"); strcpy(Config.Pad2, "builtin_pad"); strcpy(Config.Net, "Disabled"); - - snprintf(Config.PatchesDir, sizeof(Config.PatchesDir), "." PATCHES_DIR); } void emu_set_default_config(void) @@ -175,25 +156,6 @@ void emu_set_default_config(void) in_type2 = PSE_PAD_TYPE_STANDARD; } -static void check_memcards(void) -{ - char buf[MAXPATHLEN]; - FILE *f; - int i; - - for (i = 1; i <= 9; i++) { - snprintf(buf, sizeof(buf), ".%scard%d.mcd", MEMCARD_DIR, i); - - f = fopen(buf, "rb"); - if (f == NULL) { - SysPrintf("Creating memcard: %s\n", buf); - CreateMcd(buf); - } - else - fclose(f); - } -} - void do_emu_action(void) { int ret; @@ -454,8 +416,12 @@ int emu_core_preinit(void) int emu_core_init(void) { - CheckSubDir(); + SysPrintf("Starting PCSX-ReARMed " REV "\n"); + +#ifndef NO_FRONTEND + check_profile(); check_memcards(); +#endif if (EmuInit() == -1) { SysPrintf("PSX emulator couldn't be initialized.\n"); @@ -472,6 +438,47 @@ int emu_core_init(void) } #ifndef NO_FRONTEND +static void create_profile_dir(const char *directory) { + char path[MAXPATHLEN]; + + MAKE_PATH(path, directory, NULL); + mkdir(path, S_IRWXU | S_IRWXG); +} + +static void check_profile(void) { + // make sure that ~/.pcsx exists + create_profile_dir(PCSX_DOT_DIR); + + create_profile_dir(BIOS_DIR); + create_profile_dir(MEMCARD_DIR); + create_profile_dir(STATES_DIR); + create_profile_dir(PLUGINS_DIR); + create_profile_dir(PLUGINS_CFG_DIR); + create_profile_dir(CHEATS_DIR); + create_profile_dir(PATCHES_DIR); + create_profile_dir(PCSX_DOT_DIR "cfg"); + create_profile_dir("/screenshots/"); +} + +static void check_memcards(void) +{ + char buf[MAXPATHLEN]; + FILE *f; + int i; + + for (i = 1; i <= 9; i++) { + snprintf(buf, sizeof(buf), ".%scard%d.mcd", MEMCARD_DIR, i); + + f = fopen(buf, "rb"); + if (f == NULL) { + SysPrintf("Creating memcard: %s\n", buf); + CreateMcd(buf); + } + else + fclose(f); + } +} + int main(int argc, char *argv[]) { char file[MAXPATHLEN] = ""; @@ -553,7 +560,8 @@ int main(int argc, char *argv[]) plat_init(); menu_init(); // loads config - emu_core_init(); + if (emu_core_init() != 0) + return 1; if (psxout) Config.PsxOut = 1; @@ -761,6 +769,8 @@ int emu_load_state(int slot) return LoadState(fname); } +#ifndef ANDROID + void SysPrintf(const char *fmt, ...) { va_list list; @@ -769,16 +779,31 @@ void SysPrintf(const char *fmt, ...) { va_end(list); } +#else + +#include + +void SysPrintf(const char *fmt, ...) { + va_list list; + + va_start(list, fmt); + __android_log_vprint(ANDROID_LOG_INFO, "PCSX", fmt, list); + va_end(list); +} + +#endif + void SysMessage(const char *fmt, ...) { - va_list list; - char msg[512]; + va_list list; + char msg[512]; + int ret; - va_start(list, fmt); - vsnprintf(msg, sizeof(msg), fmt, list); - va_end(list); + va_start(list, fmt); + ret = vsnprintf(msg, sizeof(msg), fmt, list); + va_end(list); - if (msg[strlen(msg) - 1] == '\n') - msg[strlen(msg) - 1] = 0; + if (ret < sizeof(msg) && msg[ret - 1] == '\n') + msg[ret - 1] = 0; SysPrintf("%s\n", msg); } diff --git a/frontend/menu.c b/frontend/menu.c index 7dab2e68..81195051 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -8,7 +8,7 @@ * See the COPYING file in the top-level directory. */ -#define _GNU_SOURCE +#define _GNU_SOURCE 1 #include #include #include @@ -251,7 +251,9 @@ static int optional_cdimg_filter(struct dirent **namelist, int count, p = strrchr(buf2, '/'); if (p == NULL) p = strrchr(buf2, '\\'); - if (p == NULL) + if (p != NULL) + p++; + else p = buf2; snprintf(buf, sizeof(buf), "%s/%s", basedir, p); @@ -327,6 +329,7 @@ static void menu_set_defconfig(void) g_opts = 0; g_scaler = SCALE_4_3; + g_gamma = 100; volume_boost = 0; frameskip = 0; analog_deadzone = 50; @@ -391,6 +394,7 @@ static const struct { CE_CONFIG_VAL(Cpu), CE_INTVAL(region), CE_INTVAL_V(g_scaler, 2), + CE_INTVAL(g_gamma), CE_INTVAL(g_layer_x), CE_INTVAL(g_layer_y), CE_INTVAL(g_layer_w), @@ -1696,10 +1700,10 @@ out: static void handle_memcard_sel(void) { - Config.Mcd1[0] = 0; + strcpy(Config.Mcd1, "none"); if (memcard1_sel != 0) snprintf(Config.Mcd1, sizeof(Config.Mcd1), ".%s%s", MEMCARD_DIR, memcards[memcard1_sel]); - Config.Mcd2[0] = 0; + strcpy(Config.Mcd2, "none"); if (memcard2_sel != 0) snprintf(Config.Mcd2, sizeof(Config.Mcd2), ".%s%s", MEMCARD_DIR, memcards[memcard2_sel]); LoadMcds(Config.Mcd1, Config.Mcd2); diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c index 94bd3ebd..21203da8 100644 --- a/libpcsxcore/cdriso.c +++ b/libpcsxcore/cdriso.c @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #include "psxcommon.h" @@ -28,6 +28,7 @@ #ifdef _WIN32 #include #include +#define strcasecmp _stricmp #else #include #include @@ -46,6 +47,8 @@ static boolean subChanMixed = FALSE; static boolean subChanRaw = FALSE; static boolean subChanMissing = FALSE; +static boolean multifile = FALSE; + static unsigned char cdbuffer[CD_FRAMESIZE_RAW]; static unsigned char subbuffer[SUB_FRAMESIZE]; @@ -71,6 +74,8 @@ static unsigned int cdda_file_offset; * XXX: there could be multiple pregaps but PSX dumps only have one? */ static unsigned int pregapOffset; +#define cddaCurPos cdda_cur_sector + // compressed image stuff static struct { unsigned char buff_raw[16][CD_FRAMESIZE_RAW]; @@ -93,10 +98,8 @@ long CALLBACK CDR__getStatus(struct CdrStat *stat); static void DecodeRawSubData(void); -extern void *hCDRDriver; - struct trackinfo { - enum {DATA, CDDA} type; + enum {DATA=1, CDDA} type; char start[3]; // MSF-format char length[3]; // MSF-format FILE *handle; // for multi-track images CDDA @@ -289,10 +292,11 @@ static void startCDDA(void) { static int parsetoc(const char *isofile) { char tocname[MAXPATHLEN]; FILE *fi; - char linebuf[256], dummy[256], name[256]; + char linebuf[256], tmp[256], name[256]; char *token; char time[20], time2[20]; - unsigned int t, sector_offs; + unsigned int t, sector_offs, sector_size; + unsigned int current_zero_gap = 0; numtracks = 0; @@ -328,17 +332,21 @@ static int parsetoc(const char *isofile) { memset(&ti, 0, sizeof(ti)); cddaBigEndian = TRUE; // cdrdao uses big-endian for CD Audio + sector_size = CD_FRAMESIZE_RAW; sector_offs = 2 * 75; // parse the .toc file while (fgets(linebuf, sizeof(linebuf), fi) != NULL) { // search for tracks - strncpy(dummy, linebuf, sizeof(linebuf)); - token = strtok(dummy, " "); + strncpy(tmp, linebuf, sizeof(linebuf)); + token = strtok(tmp, " "); if (token == NULL) continue; if (!strcmp(token, "TRACK")) { + sector_offs += current_zero_gap; + current_zero_gap = 0; + // get type of track token = strtok(NULL, " "); numtracks++; @@ -349,9 +357,11 @@ static int parsetoc(const char *isofile) { // check if this image contains mixed subchannel data token = strtok(NULL, " "); - if (token != NULL && !strncmp(token, "RW_RAW", 6)) { + if (token != NULL && !strncmp(token, "RW", 2)) { + sector_size = CD_FRAMESIZE_RAW + SUB_FRAMESIZE; subChanMixed = TRUE; - subChanRaw = TRUE; + if (!strncmp(token, "RW_RAW", 6)) + subChanRaw = TRUE; } } else if (!strncmp(token, "AUDIO", 5)) { @@ -362,8 +372,7 @@ static int parsetoc(const char *isofile) { if (ti[numtracks].type == CDDA) { sscanf(linebuf, "DATAFILE \"%[^\"]\" #%d %8s", name, &t, time2); ti[numtracks].start_offset = t; - t /= CD_FRAMESIZE_RAW + (subChanMixed ? SUB_FRAMESIZE : 0); - t += sector_offs; + t = t / sector_size + sector_offs; sec2msf(t, (char *)&ti[numtracks].start); tok2msf((char *)&time2, (char *)&ti[numtracks].length); } @@ -375,22 +384,39 @@ static int parsetoc(const char *isofile) { else if (!strcmp(token, "FILE")) { sscanf(linebuf, "FILE \"%[^\"]\" #%d %8s %8s", name, &t, time, time2); tok2msf((char *)&time, (char *)&ti[numtracks].start); + t += msf2sec(ti[numtracks].start) * sector_size; ti[numtracks].start_offset = t; - t /= CD_FRAMESIZE_RAW + (subChanMixed ? SUB_FRAMESIZE : 0); - t += msf2sec(ti[numtracks].start) + sector_offs; + t = t / sector_size + sector_offs; sec2msf(t, (char *)&ti[numtracks].start); tok2msf((char *)&time2, (char *)&ti[numtracks].length); } - else if (!strcmp(token, "ZERO")) { - sscanf(linebuf, "ZERO AUDIO RW_RAW %8s", time); - tok2msf((char *)&time, dummy); - sector_offs += msf2sec(dummy); + else if (!strcmp(token, "ZERO") || !strcmp(token, "SILENCE")) { + // skip unneeded optional fields + while (token != NULL) { + token = strtok(NULL, " "); + if (strchr(token, ':') != NULL) + break; + } + if (token != NULL) { + tok2msf(token, tmp); + current_zero_gap = msf2sec(tmp); + } if (numtracks > 1) { t = ti[numtracks - 1].start_offset; - t /= CD_FRAMESIZE_RAW + (subChanMixed ? SUB_FRAMESIZE : 0); + t /= sector_size; pregapOffset = t + msf2sec(ti[numtracks - 1].length); } } + else if (!strcmp(token, "START")) { + token = strtok(NULL, " "); + if (token != NULL && strchr(token, ':')) { + tok2msf(token, tmp); + t = msf2sec(tmp); + ti[numtracks].start_offset += (t - current_zero_gap) * sector_size; + t = msf2sec(ti[numtracks].start) + t; + sec2msf(t, (char *)&ti[numtracks].start); + } + } } fclose(fi); @@ -444,10 +470,12 @@ static int parsecue(const char *isofile) { // build a path for files referenced in .cue strncpy(filepath, cuename, sizeof(filepath)); - tmp = strrchr(filepath, '/') + 1; - if (tmp == NULL) - tmp = strrchr(filepath, '\\') + 1; + tmp = strrchr(filepath, '/'); if (tmp == NULL) + tmp = strrchr(filepath, '\\'); + if (tmp != NULL) + tmp++; + else tmp = filepath; *tmp = 0; filepath[sizeof(filepath) - 1] = 0; @@ -535,8 +563,10 @@ static int parsecue(const char *isofile) { } // update global offset if this is not first file in this .cue - if (numtracks + 1 > 1) + if (numtracks + 1 > 1) { + multifile = 1; sector_offs += file_len; + } file_len = 0; if (ti[numtracks + 1].handle == NULL) { @@ -1192,6 +1222,7 @@ static long CALLBACK ISOopen(void) { subChanRaw = FALSE; pregapOffset = 0; cdrIsoMultidiskCount = 1; + multifile = 0; CDR_getBuffer = ISOgetBuffer; cdimg_read_func = cdread_normal; @@ -1326,7 +1357,6 @@ static long CALLBACK ISOgetTN(unsigned char *buffer) { // byte 2 - minute static long CALLBACK ISOgetTD(unsigned char track, unsigned char *buffer) { if (track == 0) { - // CD length according pcsxr-svn (done a bit different here) unsigned int sect; unsigned char time[3]; sect = msf2sec(ti[numtracks].start) + msf2sec(ti[numtracks].length); @@ -1443,20 +1473,74 @@ static unsigned char* CALLBACK ISOgetBufferSub(void) { } static long CALLBACK ISOgetStatus(struct CdrStat *stat) { - int sec; - + u32 sect; + CDR__getStatus(stat); - + if (playing) { stat->Type = 0x02; stat->Status |= 0x80; } else { - stat->Type = 0x01; + // BIOS - boot ID (CD type) + stat->Type = ti[1].type; + } + + // relative -> absolute time + sect = cddaCurPos; + sec2msf(sect, (char *)stat->Time); + + return 0; +} + +// read CDDA sector into buffer +long CALLBACK ISOreadCDDA(unsigned char m, unsigned char s, unsigned char f, unsigned char *buffer) { + unsigned char msf[3] = {m, s, f}; + unsigned int file, track, track_start = 0; + int ret; + + cddaCurPos = msf2sec((char *)msf); + + // find current track index + for (track = numtracks; ; track--) { + track_start = msf2sec(ti[track].start); + if (track_start <= cddaCurPos) + break; + if (track == 1) + break; + } + + // data tracks play silent + if (ti[track].type != CDDA) { + memset(buffer, 0, CD_FRAMESIZE_RAW); + return 0; } - sec = cdda_cur_sector; - sec2msf(sec, (char *)stat->Time); + file = 1; + if (multifile) { + // find the file that contains this track + for (file = track; file > 1; file--) + if (ti[file].handle != NULL) + break; + } + + ret = cdimg_read_func(ti[file].handle, ti[track].start_offset, + buffer, cddaCurPos - track_start); + if (ret != CD_FRAMESIZE_RAW) { + memset(buffer, 0, CD_FRAMESIZE_RAW); + return -1; + } + + if (cddaBigEndian) { + int i; + unsigned char tmp; + + for (i = 0; i < CD_FRAMESIZE_RAW / 2; i++) { + tmp = buffer[i * 2]; + buffer[i * 2] = buffer[i * 2 + 1]; + buffer[i * 2 + 1] = tmp; + } + } return 0; } @@ -1474,6 +1558,7 @@ void cdrIsoInit(void) { CDR_stop = ISOstop; CDR_getBufferSub = ISOgetBufferSub; CDR_getStatus = ISOgetStatus; + CDR_readCDDA = ISOreadCDDA; CDR_getDriveLetter = CDR__getDriveLetter; CDR_configure = CDR__configure; diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 2a1ce610..966bb702 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -14,10 +14,10 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ -/* +/* * Handles all CD-ROM registers and functions. */ @@ -76,6 +76,7 @@ static unsigned char *pTransfer; #define CdlID 26 #define CdlReadS 27 #define CdlReset 28 +#define CdlGetQ 29 #define CdlReadToc 30 char *CmdName[0x100]= { @@ -108,6 +109,7 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; #define MODE_STRSND (1<<6) // 0x40 ADPCM on/off #define MODE_SIZE_2340 (1<<5) // 0x20 #define MODE_SIZE_2328 (1<<4) // 0x10 +#define MODE_SIZE_2048 (0<<4) // 0x00 #define MODE_SF (1<<3) // 0x08 channel on/off #define MODE_REPORT (1<<2) // 0x04 #define MODE_AUTOPAUSE (1<<1) // 0x02 @@ -123,13 +125,24 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; #define STATUS_ROTATING (1<<1) // 0x02 #define STATUS_ERROR (1<<0) // 0x01 - +/* Errors */ +#define ERROR_NOT_READY (1<<7) // 0x80 +#define ERROR_INVALIDCMD (1<<6) // 0x40 +#define ERROR_INVALIDARG (1<<5) // 0x20 // 1x = 75 sectors per second // PSXCLK = 1 sec in the ps // so (PSXCLK / 75) = cdr read time (linuzappz) #define cdReadTime (PSXCLK / 75) +enum drive_state { + DRIVESTATE_STANDBY = 0, + DRIVESTATE_LID_OPEN, + DRIVESTATE_RESCAN_CD, + DRIVESTATE_PREPARE_CD, + DRIVESTATE_STOPPED, +}; + // for cdr.Seeked enum seeked_state { SEEK_PENDING = 0, @@ -218,165 +231,76 @@ static void setIrq(void) psxHu32ref(0x1070) |= SWAP32((u32)0x4); } +// timing used in this function was taken from tests on real hardware +// (yes it's slow, but you probably don't want to modify it) void cdrLidSeekInterrupt() { - // turn back on checking - if( cdr.LidCheck == 0x10 ) - { - cdr.LidCheck = 0; - } - - // official lid close - else if( cdr.LidCheck == 0x30 ) - { - // GS CDX 3.3: $13 - cdr.StatP |= STATUS_ROTATING; - - - // GS CDX 3.3 - ~50 getlocp tries - CDRLID_INT( cdReadTime * 3 ); - cdr.LidCheck = 0x40; - } - - // turn off ready - else if( cdr.LidCheck == 0x40 ) - { - // GS CDX 3.3: $01 - cdr.StatP &= ~STATUS_SHELLOPEN; - cdr.StatP &= ~STATUS_ROTATING; - - - // GS CDX 3.3 - ~50 getlocp tries - CDRLID_INT( cdReadTime * 3 ); - cdr.LidCheck = 0x50; - } - - // now seek - else if( cdr.LidCheck == 0x50 ) - { - // GameShark Lite: Start seeking ($42) - cdr.StatP |= STATUS_SEEK; - cdr.StatP |= STATUS_ROTATING; - cdr.StatP &= ~STATUS_ERROR; - - - CDRLID_INT( cdReadTime * 3 ); - cdr.LidCheck = 0x60; - } - - // done = cd ready - else if( cdr.LidCheck == 0x60 ) - { - // GameShark Lite: Seek detection done ($02) + switch (cdr.DriveState) { + default: + case DRIVESTATE_STANDBY: cdr.StatP &= ~STATUS_SEEK; - cdr.LidCheck = 0; - } -} - -static void Check_Shell( int Irq ) -{ - // check case open/close - if (cdr.LidCheck > 0) - { - CDR_LOG( "LidCheck\n" ); + if (CDR_getStatus(&stat) == -1) + return; - // $20 = check lid state - if( cdr.LidCheck == 0x20 ) + if (stat.Status & STATUS_SHELLOPEN) { - u32 i; - - i = stat.Status; - if (CDR_getStatus(&stat) != -1) - { - // BIOS hangs + BIOS error messages - //if (stat.Type == 0xff) - //cdr.Stat = DiskError; - - // case now open - if (stat.Status & STATUS_SHELLOPEN) - { - // Vib Ribbon: pre-CD swap - StopCdda(); - - - // GameShark Lite: Death if DiskError happens - // - // Vib Ribbon: Needs DiskError for CD swap - - if (Irq != CdlNop) - { - cdr.Stat = DiskError; - - cdr.StatP |= STATUS_ERROR; - cdr.Result[0] |= STATUS_ERROR; - } - - // GameShark Lite: Wants -exactly- $10 - cdr.StatP |= STATUS_SHELLOPEN; - cdr.StatP &= ~STATUS_ROTATING; - - - CDRLID_INT( cdReadTime * 3 ); - cdr.LidCheck = 0x10; - - - // GS CDX 3.3 = $11 - } - - // case just closed - else if ( i & STATUS_SHELLOPEN ) - { - cdr.StatP |= STATUS_ROTATING; - - CheckCdrom(); - - - if( cdr.Stat == NoIntr ) - cdr.Stat = Acknowledge; - - setIrq(); + StopCdda(); + cdr.DriveState = DRIVESTATE_LID_OPEN; + CDRLID_INT(0x800); + } + break; - // begin close-seek-ready cycle - CDRLID_INT( cdReadTime * 3 ); - cdr.LidCheck = 0x30; + case DRIVESTATE_LID_OPEN: + if (CDR_getStatus(&stat) == -1) + stat.Status &= ~STATUS_SHELLOPEN; + // 02, 12, 10 + if (!(cdr.StatP & STATUS_SHELLOPEN)) { + StopReading(); + cdr.StatP |= STATUS_SHELLOPEN; - // GameShark Lite: Wants -exactly- $42, then $02 - // GS CDX 3.3: Wants $11/$80, $13/$80, $01/$00 - } + // could generate error irq here, but real hardware + // only sometimes does that + // (not done when lots of commands are sent?) - // case still closed - wait for recheck - else - { - CDRLID_INT( cdReadTime * 3 ); - cdr.LidCheck = 0x10; - } - } + CDRLID_INT(cdReadTime * 30); + break; } + else if (cdr.StatP & STATUS_ROTATING) { + cdr.StatP &= ~STATUS_ROTATING; + } + else if (!(stat.Status & STATUS_SHELLOPEN)) { + // closed now + CheckCdrom(); + // cdr.StatP STATUS_SHELLOPEN is "sticky" + // and is only cleared by CdlNop - // GS CDX: clear all values but #1,#2 - if( (cdr.LidCheck >= 0x30) || (cdr.StatP & STATUS_SHELLOPEN) ) - { - SetResultSize(16); - memset( cdr.Result, 0, 16 ); - - cdr.Result[0] = cdr.StatP; + cdr.DriveState = DRIVESTATE_RESCAN_CD; + CDRLID_INT(cdReadTime * 105); + break; + } + // recheck for close + CDRLID_INT(cdReadTime * 3); + break; - // GS CDX: special return value - if( cdr.StatP & STATUS_SHELLOPEN ) - { - cdr.Result[1] = 0x80; - } + case DRIVESTATE_RESCAN_CD: + cdr.StatP |= STATUS_ROTATING; + cdr.DriveState = DRIVESTATE_PREPARE_CD; + // this is very long on real hardware, over 6 seconds + // make it a bit faster here... + CDRLID_INT(cdReadTime * 150); + break; - if( cdr.Stat == NoIntr ) - cdr.Stat = Acknowledge; + case DRIVESTATE_PREPARE_CD: + cdr.StatP |= STATUS_SEEK; - setIrq(); - } + cdr.DriveState = DRIVESTATE_STANDBY; + CDRLID_INT(cdReadTime * 26); + break; } } @@ -487,9 +411,16 @@ static void ReadTrack(const u8 *time) { cdr.subq.Absolute[0], cdr.subq.Absolute[1], cdr.subq.Absolute[2]); } -static void AddIrqQueue(unsigned char irq, unsigned long ecycle) { - if (cdr.Irq != 0) +static void AddIrqQueue(unsigned short irq, unsigned long ecycle) { + if (cdr.Irq != 0) { + if (irq == cdr.Irq || irq + 0x100 == cdr.Irq) { + cdr.IrqRepeated = 1; + CDR_INT(ecycle); + return; + } + CDR_LOG_I("cdr: override cmd %02x -> %02x\n", cdr.Irq, irq); + } cdr.Irq = irq; cdr.eCycle = ecycle; @@ -599,8 +530,11 @@ void cdrPlayInterrupt() } void cdrInterrupt() { - int i; - unsigned char Irq = cdr.Irq; + u16 Irq = cdr.Irq; + int no_busy_error = 0; + int start_rotating = 0; + int error = 0; + int delay; // Reschedule IRQ if (cdr.Stat) { @@ -609,34 +543,39 @@ void cdrInterrupt() { return; } - cdr.Irq = 0; cdr.Ctrl &= ~0x80; + // default response + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + + if (cdr.IrqRepeated) { + cdr.IrqRepeated = 0; + if (cdr.eCycle > psxRegs.cycle) { + CDR_INT(cdr.eCycle); + goto finish; + } + } + + cdr.Irq = 0; + switch (Irq) { case CdlSync: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; + // TOOD: sometimes/always return error? break; case CdlNop: - SetResultSize(1); - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; - - if (cdr.LidCheck == 0) cdr.LidCheck = 0x20; + if (cdr.DriveState != DRIVESTATE_LID_OPEN) + cdr.StatP &= ~STATUS_SHELLOPEN; + no_busy_error = 1; break; case CdlSetloc: - cdr.CmdProcess = 0; - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; break; case CdlPlay: + StopCdda(); if (cdr.Seeked == SEEK_PENDING) { // XXX: wrong, should seek instead.. memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 ); @@ -685,30 +624,21 @@ void cdrInterrupt() { // Vib Ribbon: gameplay checks flag cdr.StatP &= ~STATUS_SEEK; - - cdr.CmdProcess = 0; - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; cdr.StatP |= STATUS_PLAY; - // BIOS player - set flag again cdr.Play = TRUE; CDRMISC_INT( cdReadTime ); + start_rotating = 1; break; case CdlForward: - cdr.CmdProcess = 0; - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; + // TODO: error 80 if stopped cdr.Stat = Complete; - // GameShark CD Player: Calls 2x + Play 2x if( cdr.FastForward == 0 ) cdr.FastForward = 2; else cdr.FastForward++; @@ -717,13 +647,8 @@ void cdrInterrupt() { break; case CdlBackward: - cdr.CmdProcess = 0; - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; cdr.Stat = Complete; - // GameShark CD Player: Calls 2x + Play 2x if( cdr.FastBackward == 0 ) cdr.FastBackward = 2; else cdr.FastBackward++; @@ -732,29 +657,46 @@ void cdrInterrupt() { break; case CdlStandby: - cdr.CmdProcess = 0; - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; + if (cdr.DriveState != DRIVESTATE_STOPPED) { + error = ERROR_INVALIDARG; + goto set_error; + } + AddIrqQueue(CdlStandby + 0x100, cdReadTime * 125 / 2); + start_rotating = 1; + break; + + case CdlStandby + 0x100: cdr.Stat = Complete; break; case CdlStop: - cdr.CmdProcess = 0; - SetResultSize(1); + if (cdr.Play) { + // grab time for current track + CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD); + + cdr.SetSectorPlay[0] = cdr.ResultTD[2]; + cdr.SetSectorPlay[1] = cdr.ResultTD[1]; + cdr.SetSectorPlay[2] = cdr.ResultTD[0]; + } + + StopCdda(); + StopReading(); + + delay = 0x800; + if (cdr.DriveState == DRIVESTATE_STANDBY) + delay = cdReadTime * 30 / 2; + + cdr.DriveState = DRIVESTATE_STOPPED; + AddIrqQueue(CdlStop + 0x100, delay); + break; + + case CdlStop + 0x100: cdr.StatP &= ~STATUS_ROTATING; cdr.Result[0] = cdr.StatP; cdr.Stat = Complete; -// cdr.Stat = Acknowledge; - - if (cdr.LidCheck == 0) cdr.LidCheck = 0x20; break; case CdlPause: - SetResultSize(1); - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; - /* Gundam Battle Assault 2: much slower (*) - Fixes boot, gameplay @@ -765,80 +707,56 @@ void cdrInterrupt() { InuYasha - Feudal Fairy Tale: slower - Fixes battles */ - AddIrqQueue(CdlPause + 0x20, cdReadTime * 3); + AddIrqQueue(CdlPause + 0x100, cdReadTime * 3); cdr.Ctrl |= 0x80; break; - case CdlPause + 0x20: - SetResultSize(1); + case CdlPause + 0x100: cdr.StatP &= ~STATUS_READ; - cdr.StatP |= STATUS_ROTATING; cdr.Result[0] = cdr.StatP; cdr.Stat = Complete; break; case CdlInit: - SetResultSize(1); - cdr.StatP = STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; -// if (!cdr.Init) { - AddIrqQueue(CdlInit + 0x20, 0x800); -// } - break; + AddIrqQueue(CdlInit + 0x100, cdReadTime * 6); + no_busy_error = 1; + start_rotating = 1; + break; - case CdlInit + 0x20: - SetResultSize(1); - cdr.Result[0] = cdr.StatP; + case CdlInit + 0x100: cdr.Stat = Complete; - cdr.Init = 1; break; case CdlMute: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; + cdr.Muted = TRUE; break; case CdlDemute: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; + cdr.Muted = FALSE; break; case CdlSetfilter: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; + cdr.File = cdr.Param[0]; + cdr.Channel = cdr.Param[1]; break; case CdlSetmode: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; + no_busy_error = 1; break; case CdlGetmode: SetResultSize(6); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; cdr.Result[1] = cdr.Mode; cdr.Result[2] = cdr.File; cdr.Result[3] = cdr.Channel; cdr.Result[4] = 0; cdr.Result[5] = 0; - cdr.Stat = Acknowledge; + no_busy_error = 1; break; case CdlGetlocL: SetResultSize(8); - for (i = 0; i < 8; i++) - cdr.Result[i] = cdr.Transfer[i]; - cdr.Stat = Acknowledge; + memcpy(cdr.Result, cdr.Transfer, 8); break; case CdlGetlocP: @@ -847,20 +765,20 @@ void cdrInterrupt() { if (!cdr.Play && !cdr.Reading) cdr.Result[1] = 0; // HACK? + break; - cdr.Stat = Acknowledge; + case CdlReadT: // SetSession? + // really long + AddIrqQueue(CdlReadT + 0x100, cdReadTime * 290 / 4); + start_rotating = 1; break; - case CdlGetTN: - // 5-Star Racing: don't stop CDDA - // - // Vib Ribbon: CD swap - StopReading(); + case CdlReadT + 0x100: + cdr.Stat = Complete; + break; - cdr.CmdProcess = 0; + case CdlGetTN: SetResultSize(3); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; if (CDR_getTN(cdr.ResultTN) == -1) { cdr.Stat = DiskError; cdr.Result[0] |= STATUS_ERROR; @@ -872,10 +790,8 @@ void cdrInterrupt() { break; case CdlGetTD: - cdr.CmdProcess = 0; cdr.Track = btoi(cdr.Param[0]); SetResultSize(4); - cdr.StatP |= STATUS_ROTATING; if (CDR_getTD(cdr.Track, cdr.ResultTD) == -1) { cdr.Stat = DiskError; cdr.Result[0] |= STATUS_ERROR; @@ -890,11 +806,9 @@ void cdrInterrupt() { case CdlSeekL: case CdlSeekP: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; + StopCdda(); + StopReading(); cdr.StatP |= STATUS_SEEK; - cdr.Stat = Acknowledge; /* Crusaders of Might and Magic = 0.5x-4x @@ -911,10 +825,10 @@ void cdrInterrupt() { */ CDRMISC_INT(cdr.Seeked == SEEK_DONE ? 0x800 : cdReadTime * 4); cdr.Seeked = SEEK_PENDING; + start_rotating = 1; break; case CdlTest: - cdr.Stat = Acknowledge; switch (cdr.Param[0]) { case 0x20: // System Controller ROM Version SetResultSize(4); @@ -929,90 +843,65 @@ void cdrInterrupt() { memcpy(cdr.Result, Test23, 4); break; } + no_busy_error = 1; break; case CdlID: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; - AddIrqQueue(CdlID + 0x20, 0x800); + AddIrqQueue(CdlID + 0x100, 20480); break; - case CdlID + 0x20: + case CdlID + 0x100: SetResultSize(8); + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = 0; + cdr.Result[2] = 0; + cdr.Result[3] = 0; - if (CDR_getStatus(&stat) == -1) { - cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player - cdr.Result[1] = 0x80; // 0x80 leads to the menu in the bios, else loads CD + // 0x10 - audio | 0x40 - disk missing | 0x80 - unlicensed + if (CDR_getStatus(&stat) == -1 || stat.Type == 0 || stat.Type == 0xff) { + cdr.Result[1] = 0xc0; } else { - if (stat.Type == 2) { - // Music CD - cdr.Result[0] = 0x08; - cdr.Result[1] = 0x10; - + if (stat.Type == 2) + cdr.Result[1] |= 0x10; + if (CdromId[0] == '\0') cdr.Result[1] |= 0x80; - } - else { - // Data CD - if (CdromId[0] == '\0') { - cdr.Result[0] = 0x00; - cdr.Result[1] = 0x80; - } - else { - cdr.Result[0] = 0x08; - cdr.Result[1] = 0x00; - } - } } + cdr.Result[0] |= (cdr.Result[1] >> 4) & 0x08; - cdr.Result[2] = 0x00; - cdr.Result[3] = 0x00; strncpy((char *)&cdr.Result[4], "PCSX", 4); cdr.Stat = Complete; break; case CdlReset: - SetResultSize(1); - cdr.StatP = STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; + // yes, it really sets STATUS_SHELLOPEN + cdr.StatP |= STATUS_SHELLOPEN; + cdr.DriveState = DRIVESTATE_RESCAN_CD; + CDRLID_INT(20480); + no_busy_error = 1; + start_rotating = 1; break; - case CdlReadT: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; - AddIrqQueue(CdlReadT + 0x20, 0x800); - break; - - case CdlReadT + 0x20: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Complete; + case CdlGetQ: + // TODO? + CDR_LOG_I("got CdlGetQ\n"); break; case CdlReadToc: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; - AddIrqQueue(CdlReadToc + 0x20, 0x800); + AddIrqQueue(CdlReadToc + 0x100, cdReadTime * 180 / 4); + no_busy_error = 1; + start_rotating = 1; break; - case CdlReadToc + 0x20: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; + case CdlReadToc + 0x100: cdr.Stat = Complete; + no_busy_error = 1; break; case CdlReadN: case CdlReadS: - if (!cdr.Reading) return; + cdr.Reading = 1; + cdr.FirstSector = 1; // Fighting Force 2 - update subq time immediately // - fixes new game @@ -1050,29 +939,54 @@ void cdrInterrupt() { CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1); } - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; + start_rotating = 1; break; default: - cdr.Stat = Complete; + CDR_LOG_I("Invalid command: %02x\n", Irq); + error = ERROR_INVALIDCMD; + // FALLTHROUGH + + set_error: + SetResultSize(2); + cdr.Result[0] = cdr.StatP | STATUS_ERROR; + cdr.Result[1] = error; + cdr.Stat = DiskError; break; } - Check_Shell( Irq ); + if (cdr.DriveState == DRIVESTATE_STOPPED && start_rotating) { + cdr.DriveState = DRIVESTATE_STANDBY; + cdr.StatP |= STATUS_ROTATING; + } - cdr.ParamC = 0; + if (!no_busy_error) { + switch (cdr.DriveState) { + case DRIVESTATE_LID_OPEN: + case DRIVESTATE_RESCAN_CD: + case DRIVESTATE_PREPARE_CD: + SetResultSize(2); + cdr.Result[0] = cdr.StatP | STATUS_ERROR; + cdr.Result[1] = ERROR_NOT_READY; + cdr.Stat = DiskError; + break; + } + } +finish: setIrq(); + cdr.ParamC = 0; #ifdef CDR_LOG_CMD_IRQ - SysPrintf("cdrInterrupt() Log: CDR Interrupt IRQ %d %02x: ", - cdr.Stat != NoIntr && cdr.Reg2 != 0x18, Irq); - for (i = 0; i < cdr.ResultC; i++) - SysPrintf("%02x ", cdr.Result[i]); - SysPrintf("\n"); + { + int i; + SysPrintf("CDR IRQ %d cmd %02x stat %02x: ", + !!(cdr.Stat & cdr.Reg2), Irq, cdr.Stat); + for (i = 0; i < cdr.ResultC; i++) + SysPrintf("%02x ", cdr.Result[i]); + SysPrintf("\n"); + } #endif } @@ -1171,24 +1085,14 @@ void cdrReadInterrupt() { cdr.Channel = cdr.Transfer[4 + 1]; } - if ((cdr.Transfer[4 + 2] & 0x4) && + if((cdr.Transfer[4 + 2] & 0x4) && (cdr.Transfer[4 + 1] == cdr.Channel) && - (cdr.Transfer[4 + 0] == cdr.File)) { + (cdr.Transfer[4 + 0] == cdr.File)) { int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); if (!ret) { - cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo); SPU_playADPCMchannel(&cdr.Xa); cdr.FirstSector = 0; - -#if 0 - // Crash Team Racing: music, speech - // - done using cdda decoded buffer (spu irq) - // - don't do here - - // signal ADPCM data ready - setIrq(); -#endif } else cdr.FirstSector = -1; } @@ -1221,8 +1125,6 @@ void cdrReadInterrupt() { // update for CdlGetlocP ReadTrack(cdr.SetSector); - - Check_Shell(0); } /* @@ -1295,7 +1197,7 @@ void cdrWrite1(unsigned char rt) { cdr.OCUP = 0; #ifdef CDR_LOG_CMD_IRQ - SysPrintf("cdrWrite1() Log: CD1 write: %x (%s)", rt, CmdName[rt]); + SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]); if (cdr.ParamC) { SysPrintf(" Param[%d] = {", cdr.ParamC); for (i = 0; i < cdr.ParamC; i++) @@ -1312,22 +1214,7 @@ void cdrWrite1(unsigned char rt) { AddIrqQueue(cdr.Cmd, 0x800); switch (cdr.Cmd) { - case CdlSync: - case CdlNop: - case CdlForward: - case CdlBackward: - case CdlReadT: - case CdlTest: - case CdlID: - case CdlReadToc: - case CdlGetmode: - case CdlGetlocL: - case CdlGetlocP: - case CdlGetTD: - break; - case CdlSetloc: - StopReading(); for (i = 0; i < 3; i++) set_loc[i] = btoi(cdr.Param[i]); @@ -1345,69 +1232,9 @@ void cdrWrite1(unsigned char rt) { cdr.SetSector[3] = 0; break; - case CdlPlay: - // Vib Ribbon: try same track again - StopCdda(); - -#if 0 - if (!cdr.SetSector[0] & !cdr.SetSector[1] & !cdr.SetSector[2]) { - if (CDR_getTN(cdr.ResultTN) != -1) { - if (cdr.CurTrack > cdr.ResultTN[1]) - cdr.CurTrack = cdr.ResultTN[1]; - if (CDR_getTD((unsigned char)(cdr.CurTrack), cdr.ResultTD) != -1) { - int tmp = cdr.ResultTD[2]; - cdr.ResultTD[2] = cdr.ResultTD[0]; - cdr.ResultTD[0] = tmp; - if (!Config.Cdda) CDR_play(cdr.ResultTD); - } - } - } -#endif - // Vib Ribbon - decoded buffer IRQ for CDDA reading - // - fixes ribbon timing + music CD mode - //TODO? - //CDRDBUF_INT( PSXCLK / 44100 * 0x100 ); - - cdr.Play = TRUE; - - cdr.StatP |= STATUS_SEEK; - cdr.StatP &= ~STATUS_ROTATING; - break; - case CdlReadN: - StopReading(); - cdr.Reading = 1; - cdr.FirstSector = 1; - cdr.Readed = 0xff; - break; - - case CdlStandby: - StopCdda(); - StopReading(); - break; - - case CdlStop: - // GameShark CD Player: Reset CDDA to track start - if (cdr.Play) { - // grab time for current track - CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD); - - cdr.SetSectorPlay[0] = cdr.ResultTD[2]; - cdr.SetSectorPlay[1] = cdr.ResultTD[1]; - cdr.SetSectorPlay[2] = cdr.ResultTD[0]; - } - - StopCdda(); - StopReading(); - break; - + case CdlReadS: case CdlPause: - /* - GameShark CD Player: save time for resume - - Twisted Metal - World Tour: don't mix Setloc / CdlPlay cursors - */ - StopCdda(); StopReading(); break; @@ -1419,28 +1246,6 @@ void cdrWrite1(unsigned char rt) { StopReading(); break; - case CdlMute: - cdr.Muted = TRUE; - // Duke Nukem - Time to Kill - // - do not directly set cd-xa volume - //SPU_writeRegister( H_CDLeft, 0x0000 ); - //SPU_writeRegister( H_CDRight, 0x0000 ); - break; - - case CdlDemute: - cdr.Muted = FALSE; - - // Duke Nukem - Time to Kill - // - do not directly set cd-xa volume - //SPU_writeRegister( H_CDLeft, 0x7f00 ); - //SPU_writeRegister( H_CDRight, 0x7f00 ); - break; - - case CdlSetfilter: - cdr.File = cdr.Param[0]; - cdr.Channel = cdr.Param[1]; - break; - case CdlSetmode: CDR_LOG("cdrWrite1() Log: Setmode %x\n", cdr.Param[0]); @@ -1451,32 +1256,6 @@ void cdrWrite1(unsigned char rt) { if( cdr.Play && (cdr.Mode & MODE_CDDA) == 0 ) StopCdda(); break; - - case CdlGetTN: - //AddIrqQueue(cdr.Cmd, 0x800); - - // GameShark CDX CD Player: very long time - AddIrqQueue(cdr.Cmd, 0x100000); - break; - - case CdlSeekL: - case CdlSeekP: - // Tomb Raider 2 - reset cdda - StopCdda(); - StopReading(); - break; - - case CdlReadS: - StopReading(); - cdr.Reading = 2; - cdr.FirstSector = 1; - cdr.Readed = 0xff; - break; - - default: - cdr.ParamC = 0; - CDR_LOG_I("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd); - return; } } @@ -1590,10 +1369,11 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { // - fix boot if( cdsize == 0 ) { - switch (cdr.Mode & 0x30) { - case 0x00: cdsize = 2048; break; - case MODE_SIZE_2328: cdsize = 2328; break; + switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) { case MODE_SIZE_2340: cdsize = 2340; break; + case MODE_SIZE_2328: cdsize = 2328; break; + default: + case MODE_SIZE_2048: cdsize = 2048; break; } } @@ -1665,6 +1445,10 @@ void cdrReset() { cdr.CurTrack = 1; cdr.File = 1; cdr.Channel = 1; + cdr.Reg2 = 0x1f; + cdr.Stat = NoIntr; + cdr.DriveState = DRIVESTATE_STANDBY; + cdr.StatP = STATUS_ROTATING; pTransfer = cdr.Transfer; // BIOS player - default values @@ -1722,17 +1506,7 @@ int cdrFreeze(void *f, int Mode) { } void LidInterrupt() { - cdr.LidCheck = 0x20; // start checker - getCdInfo(); - StopCdda(); - CDRLID_INT( cdReadTime * 3 ); - - // generate interrupt if none active - open or close - if (cdr.Irq == 0 || cdr.Irq == 0xff) { - cdr.Ctrl |= 0x80; - cdr.Stat = NoIntr; - AddIrqQueue(CdlNop, 0x800); - } + cdrLidSeekInterrupt(); } diff --git a/libpcsxcore/cdrom.h b/libpcsxcore/cdrom.h index fc1df467..5d7c3584 100644 --- a/libpcsxcore/cdrom.h +++ b/libpcsxcore/cdrom.h @@ -92,12 +92,13 @@ typedef struct { int Init; - unsigned char Irq; + u16 Irq; + u8 IrqRepeated; u32 eCycle; u8 Seeked; - u8 LidCheck; + u8 DriveState; u8 FastForward; u8 FastBackward; u8 pad; diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index fdc129ef..b3435ad0 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -990,7 +990,7 @@ _start: case 'g': case 'G': ptmp += sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break; case 'p': - case 'i': + case 'i': case 'u': case 'd': case 'D': case 'o': case 'O': case 'x': case 'X': diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 27663f1f..9e442675 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -42,10 +42,15 @@ void *psxMap(unsigned long addr, size_t size, int is_fixed, enum psxMapTag tag) { int flags = MAP_PRIVATE | MAP_ANONYMOUS; + int tried_to_align = 0; + unsigned long mask; void *req, *ret; - if (psxMapHook != NULL) - return psxMapHook(addr, size, is_fixed, tag); +retry: + if (psxMapHook != NULL) { + ret = psxMapHook(addr, size, is_fixed, tag); + goto out; + } if (is_fixed) flags |= MAP_FIXED; @@ -55,9 +60,24 @@ void *psxMap(unsigned long addr, size_t size, int is_fixed, if (ret == MAP_FAILED) return NULL; - if (req != NULL && ret != req) - SysMessage("psxMap: warning: wanted to map @%p, got %p\n", - req, ret); +out: + if (addr != 0 && ret != (void *)addr) { + SysMessage("psxMap: warning: wanted to map @%08x, got %p\n", + addr, ret); + + if (ret != NULL && ((addr ^ (long)ret) & 0x00ffffff) + && !tried_to_align) + { + psxUnmap(ret, size, tag); + + // try to use similarly aligned memory instead + // (recompiler needs this) + mask = (addr - 1) & ~addr & 0x07ffffff; + addr = (unsigned long)(ret + mask) & ~mask; + tried_to_align = 1; + goto retry; + } + } return ret; } @@ -110,7 +130,7 @@ int psxMemInit() { psxM = psxMap(0x80000000, 0x00210000, 1, MAP_TAG_RAM); #ifndef RAM_FIXED if (psxM == NULL) - psxM = psxMap(0x70000000, 0x00210000, 0, MAP_TAG_RAM); + psxM = psxMap(0x78000000, 0x00210000, 0, MAP_TAG_RAM); #endif if (psxM == NULL) { SysMessage(_("mapping main RAM failed")); diff --git a/libpcsxcore/sio.c b/libpcsxcore/sio.c index ea96e95b..b3732d29 100644 --- a/libpcsxcore/sio.c +++ b/libpcsxcore/sio.c @@ -409,10 +409,13 @@ void LoadMcd(int mcd, char *str) { } McdDisable[mcd - 1] = 0; - if (str == NULL || *str == 0) { + if (str == NULL || strcmp(str, "none") == 0) { McdDisable[mcd - 1] = 1; return; } + if (*str == 0) + return; + f = fopen(str, "rb"); if (f == NULL) { SysPrintf(_("The memory card %s doesn't exist - creating it\n"), str); @@ -455,6 +458,9 @@ void LoadMcds(char *mcd1, char *mcd2) { void SaveMcd(char *mcd, char *data, uint32_t adr, int size) { FILE *f; + if (mcd == NULL || *mcd == 0 || strcmp(mcd, "none") == 0) + return; + f = fopen(mcd, "r+b"); if (f != NULL) { struct stat buf;