void InputDevice_neGcon::UpdateInput(const void *data) { uint8 *d8 = (uint8 *)data; buttons[0] = d8[0]; buttons[1] = d8[1]; twist = ((32768 + MDFN_de32lsb((const uint8 *)data + 4) - (((int32)MDFN_de32lsb((const uint8 *)data + 8) * 32768 + 16383) / 32767)) * 255 + 32767) / 65535; anabuttons[0] = (MDFN_de32lsb((const uint8 *)data + 12) * 255 + 16383) / 32767; anabuttons[1] = (MDFN_de32lsb((const uint8 *)data + 16) * 255 + 16383) / 32767; anabuttons[2] = (MDFN_de32lsb((const uint8 *)data + 20) * 255 + 16383) / 32767; //printf("%02x %02x %02x %02x\n", twist, anabuttons[0], anabuttons[1], anabuttons[2]); }
int MDFNSS_LoadFP(gzFile fp) { uint8 header[32]; StateMem st; memset(&st, 0, sizeof(StateMem)); if(gzread(fp, header, 32) != 32) { return(0); } st.len = MDFN_de32lsb(header + 16 + 4); if(st.len < 32) return(0); if(!(st.data = (uint8 *)malloc(st.len))) return(0); memcpy(st.data, header, 32); if(gzread(fp, st.data + 32, st.len - 32) != ((int32)st.len - 32)) { free(st.data); return(0); } if(!MDFNSS_LoadSM(&st, 1, 0)) { free(st.data); return(0); } free(st.data); return(1); }
std::unique_ptr<Stream> MDFN_AmbigGZOpenHelper(const std::string& path, std::vector<size_t> good_sizes) { std::unique_ptr<Stream> fp(new FileStream(path, FileStream::MODE_READ)); if(fp->size() >= 18) { uint8 head[10]; fp->read(head, sizeof(head)); if(head[0] == 0x1F && head[1] == 0x8B && head[2] == 0x08) { uint8 footer[8]; uint32 fs; fp->seek(-8, SEEK_END); fp->read(footer, sizeof(footer)); fs = MDFN_de32lsb(&footer[4]); for(auto const s : good_sizes) { if(s == fs) { fp.reset(nullptr); fp.reset(new GZFileStream(path, GZFileStream::MODE::READ)); return fp; } } } fp->rewind(); } return fp; }
int MDFNSS_LoadSM(StateMem *st, int haspreview, int data_only) { uint8 header[32]; uint32 stateversion; if(data_only) { stateversion = MEDNAFEN_VERSION_NUMERIC; } else { smem_read(st, header, 32); // if(memcmp(header,"MEDNAFENSVESTATE",16)) // return(0); stateversion = MDFN_de32lsb(header + 16); if(stateversion < 0x0600) { // printf("State too old: %08x\n", stateversion); // return(0); } } currFrameCounter = MDFN_de32lsb(header + 12); pcejin.lagFrameCounter = MDFN_de32lsb(header + 16); if(haspreview) { uint32 width = MDFN_de32lsb(header + 24); uint32 height = MDFN_de32lsb(header + 28); uint32 psize; //PREVIEWIMAGE psize = width * height * 4; smem_seek(st, psize, SEEK_CUR); // Skip preview } // State rewinding code path hack, FIXME if(data_only) { // if(!MDFN_RawInputStateAction(st, stateversion, data_only)) return(0); } return(MDFNGameInfo->StateAction(st, stateversion, data_only)); }
void InputDevice_Mouse::UpdateInput(const void *data) { accum_xdelta += (int32)MDFN_de32lsb((uint8*)data + 0); accum_ydelta += (int32)MDFN_de32lsb((uint8*)data + 4); if(accum_xdelta > 30 * 127) accum_xdelta = 30 * 127; if(accum_xdelta < 30 * -128) accum_xdelta = 30 * -128; if(accum_ydelta > 30 * 127) accum_ydelta = 30 * 127; if(accum_ydelta < 30 * -128) accum_ydelta = 30 * -128; button |= *((uint8 *)data + 8); button_post_mask = *((uint8 *)data + 8); //if(button) // MDFN_DispMessage("Button\n"); //printf("%d %d\n", accum_xdelta, accum_ydelta); }
void MDFNSS_GetStateInfo(const char *filename, StateStatusStruct *status) { uint32 StateShowPBWidth; uint32 StateShowPBHeight; uint8 *previewbuffer = NULL; try { GZFileStream fp(filename, GZFileStream::MODE::READ); uint8 header[32]; fp.read(header, 32); uint32 width = MDFN_de32lsb(header + 24); uint32 height = MDFN_de32lsb(header + 28); if(width > 1024) width = 1024; if(height > 1024) height = 1024; previewbuffer = (uint8 *)MDFN_malloc_T(3 * width * height, _("Save state preview buffer")); fp.read(previewbuffer, 3 * width * height); StateShowPBWidth = width; StateShowPBHeight = height; } catch(std::exception &e) { if(previewbuffer != NULL) { MDFN_free(previewbuffer); previewbuffer = NULL; } StateShowPBWidth = MDFNGameInfo->nominal_width; StateShowPBHeight = MDFNGameInfo->nominal_height; } status->gfx = previewbuffer; status->w = StateShowPBWidth; status->h = StateShowPBHeight; }
void MDFNSS_GetStateInfo(const char *filename, StateStatusStruct *status) { gzFile fp; uint32 StateShowPBWidth; uint32 StateShowPBHeight; uint8 *previewbuffer = NULL; fp = gzopen(filename, "rb"); if(fp) { uint8 header[32]; gzread(fp, header, 32); uint32 width = MDFN_de32lsb(header + 24); uint32 height = MDFN_de32lsb(header + 28); if(width > 1024) width = 1024; if(height > 1024) height = 1024; if(!(previewbuffer = (uint8 *)MDFN_malloc(3 * width * height, _("Save state preview buffer")))) { StateShowPBWidth = 0; StateShowPBHeight = 0; } else { gzread(fp, previewbuffer, 3 * width * height); StateShowPBWidth = width; StateShowPBHeight = height; } gzclose(fp); } else { StateShowPBWidth = MDFNGameInfo->nominal_width; StateShowPBHeight = MDFNGameInfo->nominal_height; } status->gfx = previewbuffer; status->w = StateShowPBWidth; status->h = StateShowPBHeight; }
void MDFNSS_LoadSM(Stream *st, bool data_only) { if(MDFN_LIKELY(data_only)) { StateMem sm(st); MDFN_StateAction(&sm, MEDNAFEN_VERSION_NUMERIC, true); sm.ThrowDeferred(); } else { uint8 header[32]; uint32 width, height, preview_len; uint32 stateversion; uint32 total_len; int64 start_pos; bool svbe; start_pos = st->tell(); st->read(header, 32); if(memcmp(header, "MEDNAFENSVESTATE", 16) && memcmp(header, "MDFNSVST", 8)) throw MDFN_Error(0, _("Missing/Wrong save state header ID.")); stateversion = MDFN_de32lsb(header + 16); total_len = MDFN_de32lsb(header + 20) & 0x7FFFFFFF; svbe = MDFN_de32lsb(header + 20) & 0x80000000; width = MDFN_de32lsb(header + 24); height = MDFN_de32lsb(header + 28); preview_len = width * height * 3; if((int)stateversion < 0x900) // Ensuring that (int)stateversion is > 0 is the most important part. throw MDFN_Error(0, _("Invalid/Unsupported version in save state header.")); st->seek(preview_len, SEEK_CUR); // Skip preview StateMem sm(st, start_pos + total_len, svbe); MDFN_StateAction(&sm, stateversion, false); // Load state data. sm.ThrowDeferred(); st->seek(start_pos + total_len, SEEK_SET); // Seek to just beyond end of save state before returning. } }
void InputDevice_DualShock::UpdateInput(const void *data) { uint8 *d8 = (uint8 *)data; buttons[0] = d8[0]; buttons[1] = d8[1]; cur_ana_button_state = d8[2] & 0x01; for(int stick = 0; stick < 2; stick++) { for(int axis = 0; axis < 2; axis++) { int32 tmp; tmp = 32768 + MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 4) - ((int32)MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 8) * 32768 / 32767); tmp >>= 8; axes[stick][axis] = tmp; } } if(da_rumble_compat == false) { uint8 sneaky_weaky = 0; if(rumble_param[0] == 0x01) sneaky_weaky = 0xFF; MDFN_en32lsb(&d8[4 + 32 + 0], (sneaky_weaky << 0) | (rumble_param[1] << 8)); } else { uint8 sneaky_weaky = 0; if(((rumble_param[0] & 0xC0) == 0x40) && ((rumble_param[1] & 0x01) == 0x01)) sneaky_weaky = 0xFF; MDFN_en32lsb(&d8[4 + 32 + 0], sneaky_weaky << 0); } //printf("%d %d %d %d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]); // // // CheckManualAnaModeChange(); if(am_prev_info != analog_mode || aml_prev_info != analog_mode_locked) { MDFN_DispMessage(_("%s: Analog mode is %s(%s)."), gp_name.c_str(), analog_mode ? _("on") : _("off"), analog_mode_locked ? _("locked") : _("unlocked")); } am_prev_info = analog_mode; aml_prev_info = analog_mode_locked; }
void MDFNI_DisplayState() { gzFile fp; fp = gzopen(MDFN_MakeFName(MDFNMKF_STATE,CurrentState,NULL).c_str(),"rb"); if(fp) { uint8 header[32]; gzread(fp, header, 32); uint32 width = MDFN_de32lsb(header + 24); uint32 height = MDFN_de32lsb(header + 28); uint8 *previewbuffer = (uint8*)alloca(3 * width * height); gzread(fp, espec.pixels, 17 * width * height); gzclose(fp); } }
int MDFNFILE::read32le(uint32 *val) { if((location + 4) > size) return 0; *val = MDFN_de32lsb(data + location); location += 4; return(1); }
void InputDevice_GunCon::UpdateInput(const void *data) { uint8 *d8 = (uint8 *)data; nom_x = MDFN_de32lsb(&d8[0]); nom_y = MDFN_de32lsb(&d8[4]); trigger_noclear = (bool)(d8[8] & 0x1); trigger_eff |= trigger_noclear; buttons = d8[8] >> 1; if(os_shot_counter > 0) // FIXME if UpdateInput() is ever called more than once per video frame(at ~50 or ~60Hz). os_shot_counter--; // Eeeeiiiiiight. if((d8[8] & 0x8) && !prev_oss && os_shot_counter == 0) os_shot_counter = 4; prev_oss = d8[8] & 0x8; //MDFN_DispMessage("%08x %08x", nom_x, nom_y); }
int MDFNSS_LoadSM(StateMem *st, int haspreview, int data_only) { uint8 header[32]; uint32 stateversion; if(data_only) { stateversion = MEDNAFEN_VERSION_NUMERIC; } else { smem_read(st, header, 32); if(memcmp(header, "MEDNAFENSVESTATE", 16) && memcmp(header, "MDFNSVST", 8)) return(0); stateversion = MDFN_de32lsb(header + 16); } if(haspreview) { uint32 width = MDFN_de32lsb(header + 24); uint32 height = MDFN_de32lsb(header + 28); uint32 psize; psize = width * height * 3; smem_seek(st, psize, SEEK_CUR); // Skip preview } // State rewinding code path hack, FIXME if(data_only) { if(!MDFN_RawInputStateAction(st, stateversion, data_only)) return(0); } return(MDFNGameInfo->StateAction(st, stateversion, data_only)); }
int MDFNSS_LoadSM(void *st_p, int, int) { uint8_t header[32]; uint32_t stateversion; StateMem *st = (StateMem*)st_p; smem_read(st, header, 32); if(memcmp(header, "MEDNAFENSVESTATE", 16) && memcmp(header, "MDFNSVST", 8)) return(0); stateversion = MDFN_de32lsb(header + 16); return StateAction(st, stateversion, 0); }
static void RecvState(const uint32 clen) { StateMem sm; std::vector<uint8> cbuf; std::vector<uint8> buf; memset(&sm, 0, sizeof(StateMem)); if(clen < 4) { throw MDFN_Error(0, _("Compressed save state data is too small: %u"), clen); } if(clen > 8 * 1024 * 1024) // Compressed length sanity check - 8 MiB max. { throw MDFN_Error(0, _("Compressed save state data is too large: %u"), clen); } cbuf.resize(clen); MDFND_RecvData(&cbuf[0], clen); uLongf len = MDFN_de32lsb(&cbuf[0]); if(len > 12 * 1024 * 1024) // Uncompressed length sanity check - 12 MiB max. { throw MDFN_Error(0, _("Uncompressed save state data is too large: %llu"), (unsigned long long)len); } buf.resize(len); uncompress((Bytef *)&buf[0], &len, (Bytef *)&cbuf[0] + 4, clen - 4); sm.data = &buf[0]; sm.len = len; if(!MDFNSS_LoadSM(&sm, 0, 0)) { throw MDFN_Error(0, _("Error during save state loading.")); } if(MDFNMOV_IsRecording()) MDFNMOV_RecordState(); }
static void rom_display_header(void) { MDFN_printf(_("Name: %s\n"), ngpc_rom.name); MDFN_printf(_("System: ")); if(rom_header->mode & 0x10) MDFN_printf(_("Color")); else MDFN_printf(_("Greyscale")); MDFN_printf("\n"); MDFN_printf(_("Catalog: %u (sub %u)\n"), MDFN_de16lsb(rom_header->catalog), rom_header->subCatalog); //Starting PC MDFN_printf(_("Starting PC: 0x%06X\n"), MDFN_de32lsb(rom_header->startPC) & 0xFFFFFF); }
void InputDevice_DualAnalog::UpdateInput(const void *data) { uint8 *d8 = (uint8 *)data; buttons[0] = d8[0]; buttons[1] = d8[1]; for(int stick = 0; stick < 2; stick++) { for(int axis = 0; axis < 2; axis++) { int32 tmp; tmp = 32768 + MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 4) - ((int32)MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 8) * 32768 / 32767); tmp >>= 8; axes[stick][axis] = tmp; } } //printf("%d %d %d %d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]); }
void InputDevice_DualShock::UpdateInput(const void *data) { uint8 *d8 = (uint8 *)data; uint8* const rumb_dp = &d8[3 + 16]; buttons[0] = d8[0]; buttons[1] = d8[1]; cur_ana_button_state = d8[2] & 0x01; for(int stick = 0; stick < 2; stick++) { for(int axis = 0; axis < 2; axis++) { const uint8* aba = &d8[3] + stick * 8 + axis * 4; int32 tmp; //revert to 0.9.33, should be fixed on libretro side instead //tmp = 32767 + MDFN_de16lsb(&aba[0]) - MDFN_de16lsb(&aba[2]); //tmp = (tmp * 0x100) / 0xFFFF; tmp = 32768 + MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 4) - ((int32)MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 8) * 32768 / 32767); tmp >>= 8; axes[stick][axis] = tmp; } } //printf("%3d:%3d, %3d:%3d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]); //printf("RUMBLE: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", rumble_magic[0], rumble_magic[1], rumble_magic[2], rumble_magic[3], rumble_magic[4], rumble_magic[5]); //printf("%d, 0x%02x 0x%02x\n", da_rumble_compat, rumble_param[0], rumble_param[1]); if(da_rumble_compat == false) { uint8 sneaky_weaky = 0; if(rumble_param[0] == 0x01) sneaky_weaky = 0xFF; //revert to 0.9.33, should be fixed on libretro side instead //MDFN_en16lsb(rumb_dp, (sneaky_weaky << 0) | (rumble_param[1] << 8)); MDFN_en32lsb(&d8[4 + 32 + 0], (sneaky_weaky << 0) | (rumble_param[1] << 8)); } else { uint8 sneaky_weaky = 0; if(((rumble_param[0] & 0xC0) == 0x40) && ((rumble_param[1] & 0x01) == 0x01)) sneaky_weaky = 0xFF; //revert to 0.9.33, should be fixed on libretro side instead //MDFN_en16lsb(rumb_dp, sneaky_weaky << 0); MDFN_en32lsb(&d8[4 + 32 + 0], sneaky_weaky << 0); } //printf("%d %d %d %d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]); // // // CheckManualAnaModeChange(); if(am_prev_info != analog_mode || aml_prev_info != analog_mode_locked) { //MDFN_DispMessage(_("%s: Analog mode is %s(%s)."), gp_name.c_str(), analog_mode ? _("on") : _("off"), analog_mode_locked ? _("locked") : _("unlocked")); MDFN_DispMessage(_("%s: Analog toggle is %s, sticks are %s"), gp_name.c_str(), amct_enabled ? _("ENABLED") : _("DISABLED"), analog_mode ? _("ON") : _("OFF")); } aml_prev_info = analog_mode_locked; am_prev_info = analog_mode; }
static void ProcessCommand(const uint8 cmd, const uint32 raw_len, const char **PortDNames, void *PortData[], uint32 PortLen[], int NumPorts) { switch(cmd) { case 0: break; // No command default: MDFN_DoSimpleCommand(cmd); break; case MDFNNPCMD_INTEGRITY: SendIntegrity(); break; case MDFNNPCMD_REQUEST_STATE: SendState(); break; case MDFNNPCMD_LOADSTATE: RecvState(raw_len); MDFN_DispMessage(_("Remote state loaded.")); break; case MDFNNPCMD_SERVERTEXT: { static const uint32 MaxLength = 2000; uint8 neobuf[MaxLength + 1]; char *textbuf = NULL; const uint32 totallen = raw_len; if(totallen > MaxLength) // Sanity check { throw MDFN_Error(0, _("Text length is too long: %u"), totallen); } MDFND_RecvData(neobuf, totallen); neobuf[totallen] = 0; trio_asprintf(&textbuf, "** %s", neobuf); MDFND_NetplayText((UTF8*)textbuf, FALSE); free(textbuf); } break; case MDFNNPCMD_ECHO: { uint32 totallen = raw_len; uint64 then_time; uint64 now_time; if(totallen != sizeof(then_time)) { throw MDFN_Error(0, _("Echo response length is incorrect size: %u"), totallen); } MDFND_RecvData(&then_time, sizeof(then_time)); now_time = MDFND_GetTime(); char *textbuf = NULL; trio_asprintf(&textbuf, _("*** Round-trip time: %llu ms"), (unsigned long long)(now_time - then_time)); MDFND_NetplayText((UTF8*)textbuf, FALSE); free(textbuf); } break; case MDFNNPCMD_TEXT: { static const uint32 MaxLength = 2000; uint8 neobuf[MaxLength + 1]; const uint32 totallen = raw_len; uint32 nicklen; bool NetEcho = false; char *textbuf = NULL; if(totallen < 4) { throw MDFN_Error(0, _("Text command length is too short: %u"), totallen); } if(totallen > MaxLength) // Sanity check { throw MDFN_Error(0, _("Text command length is too long: %u"), totallen); } MDFND_RecvData(neobuf, totallen); nicklen = MDFN_de32lsb(neobuf); if(nicklen > (totallen - 4)) // Sanity check { throw MDFN_Error(0, _("Received nickname length is too long: %u"), nicklen); } neobuf[totallen] = 0; if(nicklen) { uint8 nickbuf[nicklen + 1]; memcpy(nickbuf, neobuf + 4, nicklen); nickbuf[nicklen] = 0; if(OurNick && !strcasecmp(OurNick, (char *)nickbuf)) { trio_asprintf(&textbuf, "> %s", &neobuf[4 + nicklen]); NetEcho = true; } else trio_asprintf(&textbuf, "<%s> %s", nickbuf, &neobuf[4 + nicklen]); } else { trio_asprintf(&textbuf, "* %s", &neobuf[4]); } MDFND_NetplayText((UTF8*)textbuf, NetEcho); free(textbuf); } break; case MDFNNPCMD_NICKCHANGED: { static const uint32 MaxLength = 2000; uint8 neobuf[MaxLength + 1]; uint8 *newnick; char *textbuf = NULL; const uint32 len = raw_len; if(len > MaxLength) // Sanity check { throw MDFN_Error(0, _("Nickname change length is too long: %u"), len); } MDFND_RecvData(neobuf, len); neobuf[len] = 0; newnick = (uint8*)strchr((char*)neobuf, '\n'); if(newnick) { bool IsMeow = FALSE; *newnick = 0; newnick++; if(OurNick) { if(!strcasecmp((char*)neobuf, (char*)OurNick)) { free(OurNick); OurNick = strdup((char*)newnick); textbuf = trio_aprintf(_("* You are now known as <%s>."), newnick); IsMeow = TRUE; } } if(!textbuf) textbuf = trio_aprintf(_("* <%s> is now known as <%s>"), neobuf, newnick); MDFND_NetplayText((UTF8*)textbuf, IsMeow); free(textbuf); } } break; case MDFNNPCMD_CTRL_CHANGE: { const uint32 len = raw_len; // // Joined = true; SendCommand(MDFNNPCMD_CTRL_CHANGE_ACK, len); // // LocalInputStateSize = 0; LocalPlayersMask = len; for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++) { if(LocalPlayersMask & (1 << x)) LocalInputStateSize += PortLen[x]; } } break; case MDFNNPCMD_CTRLR_SWAP_NOTIF: { const uint32 cm = raw_len; char textbuf[512]; trio_snprintf(textbuf, sizeof(textbuf), _("* All instances of controllers %u and %u have been swapped."), ((cm & 0xFF) + 1), ((cm >> 8) & 0xFF) + 1); MDFND_NetplayText((UTF8*)textbuf, false); } break; case MDFNNPCMD_CTRLR_TAKE_NOTIF: case MDFNNPCMD_CTRLR_DROP_NOTIF: case MDFNNPCMD_CTRLR_DUPE_NOTIF: { static const uint32 MaxNicknameLength = 1000; static const uint32 MaxLength = 12 + MaxNicknameLength; const char *fstr = NULL; const uint32 len = raw_len; uint8 ntf_buf[MaxLength + 1]; char *textbuf = NULL; if(len < 12) throw MDFN_Error(0, _("Take/drop/dupe notification is too short: %u"), len); if(len > MaxLength) throw MDFN_Error(0, _("Take/drop/dupe notification is too long: %u"), len); MDFND_RecvData(ntf_buf, len); ntf_buf[len] = 0; switch(cmd) { case MDFNNPCMD_CTRLR_TAKE_NOTIF: fstr = _("* <%s> took all instances of %s, and is now %s."); break; case MDFNNPCMD_CTRLR_DUPE_NOTIF: fstr = _("* <%s> took copies of %s, and is now %s."); break; case MDFNNPCMD_CTRLR_DROP_NOTIF: fstr = _("* <%s> dropped %s, and is now %s."); break; } trio_asprintf(&textbuf, fstr, ntf_buf + 12, GenerateMPSString(MDFN_de32lsb(&ntf_buf[0]), true).c_str(), GenerateMPSString(MDFN_de32lsb(&ntf_buf[4]), false).c_str()); MDFND_NetplayText((UTF8*)textbuf, false); free(textbuf); } break; case MDFNNPCMD_YOUJOINED: case MDFNNPCMD_YOULEFT: case MDFNNPCMD_PLAYERLEFT: case MDFNNPCMD_PLAYERJOINED: { static const uint32 MaxLength = 2000; uint8 neobuf[MaxLength + 1]; char *textbuf = NULL; uint32 mps; std::string mps_string; const uint32 len = raw_len; if(len < 8) { throw MDFN_Error(0, _("Join/Left length is too short: %u"), len); } if(len > MaxLength) // Sanity check { throw MDFN_Error(0, _("Join/Left length is too long: %u"), len); } MDFND_RecvData(neobuf, len); neobuf[len] = 0; // NULL-terminate the string mps = MDFN_de32lsb(&neobuf[0]); mps_string = GenerateMPSString(mps); if(cmd == MDFNNPCMD_YOULEFT) { // Uhm, not supported yet! LocalPlayersMask = 0; LocalInputStateSize = 0; Joined = FALSE; } else if(cmd == MDFNNPCMD_YOUJOINED) { if(OurNick) // This shouldn't happen, really... { free(OurNick); OurNick = NULL; } OurNick = strdup((char*)neobuf + 8); trio_asprintf(&textbuf, _("* You, %s, have connected as: %s"), neobuf + 8, mps_string.c_str()); LocalPlayersMask = mps; LocalInputStateSize = 0; for(int x = 0; x < MDFNGameInfo->InputInfo->InputPorts; x++) { if(LocalPlayersMask & (1U << x)) LocalInputStateSize += PortLen[x]; } Joined = TRUE; SendCommand(MDFNNPCMD_SETFPS, MDFNGameInfo->fps); } else if(cmd == MDFNNPCMD_PLAYERLEFT) { trio_asprintf(&textbuf, _("* %s(%s) has left"), neobuf + 8, mps_string.c_str()); } else { trio_asprintf(&textbuf, _("* %s has connected as: %s"), neobuf + 8, mps_string.c_str()); } MDFND_NetplayText((UTF8*)textbuf, FALSE); free(textbuf); } break; } }
void NetplayUpdate(const char **PortDNames, void *PortData[], uint32 PortLen[], int NumPorts) { uint8 buf[TotalInputStateSize + 1]; try { // // // if(Joined) { uint8 outgoing_buffer[1 + LocalInputStateSize]; bool Taken[NumPorts]; memset(Taken, 0, sizeof(Taken)); outgoing_buffer[0] = 0; // This is not a command, duh! int wpos = 1; for(int x = 0; x < NumPorts; x++) { if(LocalPlayersMask & (1 << x)) { for(int n = 0; n <= x; n++) { if(!Taken[n] && !strcmp(PortDNames[n], PortDNames[x])) { memcpy(outgoing_buffer + wpos, PortData[n], PortLen[n]); Taken[n] = TRUE; wpos += PortLen[n]; break; } } } } MDFND_SendData(outgoing_buffer, 1 + LocalInputStateSize); } // // // uint8 cmd; uint32 cmd_raw_len; do { MDFND_RecvData(buf, TotalInputStateSize + 1); cmd = buf[TotalInputStateSize]; cmd_raw_len = MDFN_de32lsb(&buf[0]); if(cmd != 0) ProcessCommand(cmd, cmd_raw_len, PortDNames, PortData, PortLen, NumPorts); } while(cmd != 0); // // Update local port data buffers with data received. // { unsigned rpos = 0; for(int x = 0; x < NumPorts; x++) { memcpy(PortData[x], buf + rpos, PortLen[x]); rpos += PortLen[x]; } } } catch(std::exception &e) { NetError("%s", e.what()); } }
int PCE_HESLoad(const uint8 *buf, uint32 size) { uint32 LoadAddr, LoadSize; uint32 CurPos; uint16 InitAddr; uint8 StartingSong; int TotalSongs; InitAddr = MDFN_de16lsb(&buf[0x6]); CurPos = 0x10; if(!(rom = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM")))) { return(0); } if(!(rom_backup = (uint8 *)MDFN_malloc(0x88 * 8192, _("HES ROM")))) { return(0); } memset(rom, 0, 0x88 * 8192); memset(rom_backup, 0, 0x88 * 8192); while(CurPos < (size - 0x10)) { LoadSize = MDFN_de32lsb(&buf[CurPos + 0x4]); LoadAddr = MDFN_de32lsb(&buf[CurPos + 0x8]); //printf("Size: %08x(%d), Addr: %08x, La: %02x\n", LoadSize, LoadSize, LoadAddr, LoadAddr / 8192); CurPos += 0x10; if(((uint64)LoadSize + CurPos) > size) { uint32 NewLoadSize = size - CurPos; MDFN_printf(_("Warning: HES is trying to load more data than is present in the file(%u attempted, %u left)!\n"), LoadSize, NewLoadSize); LoadSize = NewLoadSize; } // 0x88 * 8192 = 0x110000 if(((uint64)LoadAddr + LoadSize) > 0x110000) { MDFN_printf(_("Warning: HES is trying to load data past boundary.\n")); if(LoadAddr >= 0x110000) break; LoadSize = 0x110000 - LoadAddr; } memcpy(rom + LoadAddr, &buf[CurPos], LoadSize); CurPos += LoadSize; } for(int x = 0; x < 8; x++) mpr_start[x] = buf[0x8 + x]; memcpy(rom_backup, rom, 0x88 * 8192); CurrentSong = StartingSong = buf[5]; TotalSongs = 256; memset(IBP_Bank, 0, 0x2000); uint8 *IBP_WR = IBP_Bank + 0x1C00; for(int i = 0; i < 8; i++) { *IBP_WR++ = 0xA9; // LDA (immediate) *IBP_WR++ = mpr_start[i]; *IBP_WR++ = 0x53; // TAM *IBP_WR++ = 1 << i; } *IBP_WR++ = 0xAD; // LDA(absolute) *IBP_WR++ = 0x00; // *IBP_WR++ = 0x1D; // *IBP_WR++ = 0x20; // JSR *IBP_WR++ = InitAddr; // JSR target LSB *IBP_WR++ = InitAddr >> 8; // JSR target MSB *IBP_WR++ = 0x58; // CLI *IBP_WR++ = 0xFC; // (Mednafen Special) *IBP_WR++ = 0x80; // BRA *IBP_WR++ = 0xFD; // -3 Player_Init(TotalSongs, NULL, NULL, NULL, NULL); //UTF8 **snames); for(int x = 0; x < 0x80; x++) { HuCPUFastMap[x] = rom; PCERead[x] = HESROMRead; PCEWrite[x] = HESROMWrite; } HuCPUFastMap[0xFF] = IBP_Bank - (0xFF * 8192); // FIXME: If a HES rip tries to execute a SCSI command, the CD emulation code will probably crash. Obviously, a HES rip shouldn't do this, // but Mednafen shouldn't crash either. ;) PCE_IsCD = 1; PCE_InitCD(); ROMWriteWarningGiven = FALSE; return(1); }
PSFTags PSFLoader::LoadInternal(uint8 version, uint32 max_exe_size, MDFNFILE *fp, uint32 level, bool force_ignore_pcsp) { uint32 reserved_size, compressed_size, compressed_crc32; bool _lib_present = false; PSFTags tags; std::vector<uint8> decompress_buffer; uLongf decompress_len; if(!TestMagic(version, fp)) throw(MDFN_Error(0, _("Not a PSF(version=0x%02x) file!"), version)); reserved_size = MDFN_de32lsb(fp->data + 4); compressed_size = MDFN_de32lsb(fp->data + 8); compressed_crc32 = MDFN_de32lsb(fp->data + 12); if(fp->size < (16 + reserved_size + compressed_size)) throw(MDFN_Error(0, _("PSF is missing at least %u bytes of data!"), 16 + reserved_size + compressed_size - fp->size)); if(crc32(0, fp->data + 16 + reserved_size, compressed_size) != compressed_crc32) throw(MDFN_Error(0, _("PSF compressed CRC32 mismatch(data is corrupt)!"))); { const uint8 *tag_section = fp->data + 16 + reserved_size + compressed_size; uint32 tag_section_size = fp->size - 16 - reserved_size - compressed_size; if(tag_section_size > 5 && !memcmp(tag_section, "[TAG]", 5)) tags.LoadTags(tag_section + 5, tag_section_size - 5); } // // Handle minipsf simple _lib // if(level < 15) { if(tags.TagExists("_lib")) { std::string tp = tags.GetTag("_lib"); if(!MDFN_IsFIROPSafe(tp)) { throw(MDFN_Error(0, _("Referenced path \"%s\" is potentially unsafe. See \"filesys.untrusted_fip_check\" setting."), tp.c_str())); } MDFNFILE subfile(MDFN_MakeFName(MDFNMKF_AUX, 0, tp.c_str()).c_str(), NULL, NULL); LoadInternal(version, max_exe_size, &subfile, level + 1); _lib_present = true; } } // // // decompress_buffer.resize(max_exe_size); decompress_len = max_exe_size; switch( uncompress((Bytef *)&decompress_buffer[0], &decompress_len, (const Bytef *)(fp->data + 16 + reserved_size), compressed_size) ) { default: throw(MDFN_Error(0, "zlib unknown error")); case Z_OK: break; case Z_MEM_ERROR: throw(MDFN_Error(0, "zlib Z_MEM_ERROR")); case Z_BUF_ERROR: throw(MDFN_Error(0, _("PSF decompressed size exceeds maximum allowed!"))); case Z_DATA_ERROR: throw(MDFN_Error(0, _("PSF compressed data is bad."))); } HandleReserved(fp->data + 16, reserved_size); HandleEXE(&decompress_buffer[0], decompress_len, force_ignore_pcsp | _lib_present); decompress_buffer.resize(0); // // handle libN // if(level < 15) { for(unsigned int n = 2; n <= INT_MAX; n++) { char tmpbuf[32]; trio_snprintf(tmpbuf, 32, "_lib%d", (int)n); if(tags.TagExists(tmpbuf)) { MDFNFILE subfile(MDFN_MakeFName(MDFNMKF_AUX, 0, tags.GetTag(tmpbuf).c_str()).c_str(), NULL, NULL); LoadInternal(version, max_exe_size, &subfile, level + 1, true); } else break; } } return(tags); }
bool MDFNI_LoadState(const char *fname, const char *suffix) noexcept { bool ret = true; try { if(!MDFNGameInfo->StateAction) { throw MDFN_Error(0, _("Module \"%s\" doesn't support save states."), MDFNGameInfo->shortname); } /* For network play and movies, be load the state locally, and then save the state to a temporary buffer, and send or record that. This ensures that if an older state is loaded that is missing some information expected in newer save states, desynchronization won't occur(at least not from this ;)). */ { GZFileStream st(fname ? std::string(fname) : MDFN_MakeFName(MDFNMKF_STATE,CurrentState,suffix), GZFileStream::MODE::READ); uint8 header[32]; uint32 st_len; st.read(header, 32); st_len = MDFN_de32lsb(header + 16 + 4) & 0x7FFFFFFF; if(st_len < 32) throw MDFN_Error(0, _("Save state header length field is bad.")); MemoryStream sm(st_len, -1); memcpy(sm.map(), header, 32); st.read(sm.map() + 32, st_len - 32); MDFNSS_LoadSM(&sm, false); } if(MDFNnetplay) { NetplaySendState(); } if(MDFNMOV_IsRecording()) MDFNMOV_RecordState(); MDFND_SetStateStatus(NULL); if(!fname && !suffix) { SaveStateStatus[CurrentState] = true; MDFN_DispMessage(_("State %d loaded."), CurrentState); } } catch(std::exception &e) { if(!fname && !suffix) MDFN_DispMessage(_("State %d load error: %s"), CurrentState, e.what()); else MDFN_PrintError("%s", e.what()); if(MDFNnetplay) MDFND_NetplayText(e.what(), false); ret = false; } return(ret); }
void LoadNSFE(NSFINFO *nfe, const uint8 *buf, int32 size, int info_only) { const uint8 *nbuf = 0; size -= 4; buf += 4; while(size) { uint32 chunk_size; uint8 tb[4]; if(size < 4) throw MDFN_Error(0, _("Unexpected EOF while reading NSFE.")); chunk_size = MDFN_de32lsb(buf); size -= 4; buf += 4; if(size < 4) throw MDFN_Error(0, _("Unexpected EOF while reading NSFE.")); memcpy(tb, buf, 4); buf += 4; size -= 4; if((int32)chunk_size < 0 || (int32)chunk_size > size) throw MDFN_Error(0, _("NSFE chunk \"%.4s\" size(%u) is invalid."), (char*)&tb[0], chunk_size); //printf("\nChunk: %.4s %d\n", tb, chunk_size); if(!memcmp(tb, "INFO", 4)) { if(chunk_size < 8) throw MDFN_Error(0, _("NSFE chunk \"%.4s\" size(%u) is invalid."), (char*)&tb[0], chunk_size); nfe->LoadAddr = MDFN_de16lsb(buf); buf+=2; size-=2; nfe->InitAddr = MDFN_de16lsb(buf); buf+=2; size-=2; nfe->PlayAddr = MDFN_de16lsb(buf); buf+=2; size-=2; nfe->VideoSystem = *buf; buf++; size--; nfe->SoundChip = *buf; buf++; size--; chunk_size-=8; if(chunk_size) { nfe->TotalSongs = *buf; buf++; size--; chunk_size--; } else nfe->TotalSongs = 1; if(chunk_size) { nfe->StartingSong = *buf; buf++; size--; chunk_size--; } else nfe->StartingSong = 0; nfe->SongNames = (char **)malloc(sizeof(char *) * nfe->TotalSongs); memset(nfe->SongNames, 0, sizeof(char *) * nfe->TotalSongs); nfe->SongLengths = (int32 *)malloc(sizeof(int32) * nfe->TotalSongs); nfe->SongFades = (int32 *)malloc(sizeof(int32) * nfe->TotalSongs); { int x; for(x=0; x<nfe->TotalSongs; x++) { nfe->SongLengths[x] = -1; nfe->SongFades[x] = -1; } } } else if(!memcmp(tb, "DATA", 4)) { nfe->NSFSize=chunk_size; nbuf = buf; } else if(!memcmp(tb, "BANK", 4)) { memcpy(nfe->BankSwitch, buf, (chunk_size > 8) ? 8 : chunk_size); } else if(!memcmp(tb, "NEND", 4)) { if(chunk_size != 0) throw MDFN_Error(0, _("NSFE chunk \"%.4s\" size(%u) is invalid."), (char*)&tb[0], chunk_size); else if(!nbuf) throw MDFN_Error(0, _("NEND reached without preceding DATA chunk.")); else { nfe->NSFMaxBank = ((nfe->NSFSize+(nfe->LoadAddr&0xfff)+4095)/4096); nfe->NSFMaxBank = round_up_pow2(nfe->NSFMaxBank); if(!info_only) { if(!(nfe->NSFDATA=(uint8 *)malloc(nfe->NSFMaxBank*4096))) throw MDFN_Error(errno, _("Error allocating memory.")); memset(nfe->NSFDATA,0x00,nfe->NSFMaxBank*4096); memcpy(nfe->NSFDATA+(nfe->LoadAddr&0xfff),nbuf,nfe->NSFSize); nfe->NSFRawData = nfe->NSFDATA + (nfe->LoadAddr & 0xFFF); nfe->NSFRawDataSize = nfe->NSFSize; } nfe->NSFMaxBank--; return; } } else if(!memcmp(tb, "tlbl", 4)) { int songcount = 0; if(!nfe->TotalSongs) throw MDFN_Error(0, _("NSFE chunk \"%.4s\" is out of order.")); // Out of order chunk. while(chunk_size > 0) { int slen = strlen((char *)buf); nfe->SongNames[songcount++] = (char*)MDFN_RemoveControlChars(strdup((char *)buf)); buf += slen + 1; chunk_size -= slen + 1; } } else if(!memcmp(tb, "time", 4)) { int count = chunk_size / 4; int ws = 0; chunk_size -= count * 4; while(count--) { nfe->SongLengths[ws] = (int32)MDFN_de32lsb(buf); //printf("%d\n",fe->SongLengths[ws]/1000); buf += 4; ws++; } } else if(!memcmp(tb, "fade", 4)) { int count = chunk_size / 4; int ws = 0; chunk_size -= count * 4; while(count--) { nfe->SongFades[ws] = (int32)MDFN_de32lsb(buf); //printf("%d\n",fe->SongFades[ws]); buf += 4; ws++; } } else if(!memcmp(tb, "auth", 4)) { int which = 0; while(chunk_size > 0) { int slen = strlen((char *)buf); if(!which) nfe->GameName = (char*)MDFN_RemoveControlChars(strdup((char *)buf)); else if(which == 1) nfe->Artist = (char*)MDFN_RemoveControlChars(strdup((char *)buf)); else if(which == 2) nfe->Copyright = (char*)MDFN_RemoveControlChars(strdup((char *)buf)); else if(which == 3) nfe->Ripper = (char*)MDFN_RemoveControlChars(strdup((char *)buf)); which++; buf += slen +1; chunk_size -= slen + 1; } } else if(tb[0] >= 'A' && tb[0] <= 'Z') /* Unrecognized mandatory chunk */ { throw MDFN_Error(0, _("NSFE unrecognized mandatory chunk \"%.4s\"."), (char*)&tb[0]); } buf += chunk_size; size -= chunk_size; } }