void GBASavedataDeinit(struct GBASavedata* savedata) { if (savedata->vf) { size_t size = GBASavedataSize(savedata); if (savedata->data) { savedata->vf->unmap(savedata->vf, savedata->data, size); } savedata->vf = NULL; } else { switch (savedata->type) { case SAVEDATA_SRAM: mappedMemoryFree(savedata->data, SIZE_CART_SRAM); break; case SAVEDATA_FLASH512: mappedMemoryFree(savedata->data, SIZE_CART_FLASH512); break; case SAVEDATA_FLASH1M: mappedMemoryFree(savedata->data, SIZE_CART_FLASH1M); break; case SAVEDATA_EEPROM: mappedMemoryFree(savedata->data, SIZE_CART_EEPROM); break; case SAVEDATA_EEPROM512: mappedMemoryFree(savedata->data, SIZE_CART_EEPROM512); break; case SAVEDATA_FORCE_NONE: case SAVEDATA_AUTODETECT: break; } } savedata->data = 0; savedata->type = SAVEDATA_AUTODETECT; }
void GBUnloadROM(struct GB* gb) { // TODO: Share with GBAUnloadROM if (gb->memory.rom && gb->pristineRom != gb->memory.rom) { if (gb->yankedRomSize) { gb->yankedRomSize = 0; } mappedMemoryFree(gb->memory.rom, GB_SIZE_CART_MAX); } gb->memory.rom = 0; if (gb->romVf) { #ifndef _3DS gb->romVf->unmap(gb->romVf, gb->pristineRom, gb->pristineRomSize); #endif gb->romVf->close(gb->romVf); gb->pristineRom = 0; gb->romVf = 0; } if (gb->sramVf) { gb->sramVf->unmap(gb->sramVf, gb->memory.sram, 0x8000); gb->sramVf = 0; } else if (gb->memory.sram) { mappedMemoryFree(gb->memory.sram, 0x8000); } gb->memory.sram = 0; }
void retro_unload_game(void) { core->deinit(core); mappedMemoryFree(data, dataSize); data = 0; mappedMemoryFree(savedata, SIZE_CART_FLASH1M); savedata = 0; CircleBufferDeinit(&rumbleHistory); }
void GBVideoReset(struct GBVideo* video) { video->ly = 0; video->mode = 1; video->stat = 1; video->nextEvent = INT_MAX; video->eventDiff = 0; video->nextMode = INT_MAX; video->dotCounter = INT_MIN; video->nextFrame = INT_MAX; video->frameCounter = 0; video->frameskipCounter = 0; if (video->vram) { mappedMemoryFree(video->vram, GB_SIZE_VRAM); } video->vram = anonymousMemoryMap(GB_SIZE_VRAM); GBVideoSwitchBank(video, 0); video->renderer->vram = video->vram; memset(&video->oam, 0, sizeof(video->oam)); video->renderer->oam = &video->oam; memset(&video->palette, 0, sizeof(video->palette)); video->renderer->deinit(video->renderer); video->renderer->init(video->renderer, video->p->model); }
bool _vfmCloseFree(struct VFile* vf) { struct VFileMem* vfm = (struct VFileMem*) vf; mappedMemoryFree(vfm->mem, vfm->bufferSize); vfm->mem = 0; free(vfm); return true; }
void GBUnloadROM(struct GB* gb) { // TODO: Share with GBAUnloadROM if (gb->memory.rom && gb->pristineRom != gb->memory.rom) { if (gb->yankedRomSize) { gb->yankedRomSize = 0; } mappedMemoryFree(gb->memory.rom, GB_SIZE_CART_MAX); gb->memory.rom = gb->pristineRom; } if (gb->memory.rom && gb->memory.romBase != gb->memory.rom) { free(gb->memory.romBase); } gb->memory.rom = 0; if (gb->romVf) { #ifndef _3DS gb->romVf->unmap(gb->romVf, gb->pristineRom, gb->pristineRomSize); #endif gb->romVf->close(gb->romVf); gb->romVf = 0; } gb->pristineRom = 0; GBSavedataUnmask(gb); GBSramDeinit(gb); if (gb->sramRealVf) { gb->sramRealVf->close(gb->sramRealVf); } gb->sramRealVf = NULL; gb->sramVf = NULL; }
void GBResizeSram(struct GB* gb, size_t size) { if (gb->memory.sram && size <= gb->sramSize) { return; } mLOG(GB, INFO, "Resizing SRAM to %"PRIz"u bytes", size); struct VFile* vf = gb->sramVf; if (vf) { if (vf == gb->sramRealVf) { ssize_t vfSize = vf->size(vf); if (vfSize >= 0 && (size_t) vfSize < size) { uint8_t extdataBuffer[0x100]; if (vfSize & 0xFF) { vf->seek(vf, -(vfSize & 0xFF), SEEK_END); vf->read(vf, extdataBuffer, vfSize & 0xFF); } if (gb->memory.sram) { vf->unmap(vf, gb->memory.sram, gb->sramSize); } vf->truncate(vf, size + (vfSize & 0xFF)); if (vfSize & 0xFF) { vf->seek(vf, size, SEEK_SET); vf->write(vf, extdataBuffer, vfSize & 0xFF); } gb->memory.sram = vf->map(vf, size, MAP_WRITE); memset(&gb->memory.sram[gb->sramSize], 0xFF, size - gb->sramSize); } else if (size > gb->sramSize || !gb->memory.sram) { if (gb->memory.sram) { vf->unmap(vf, gb->memory.sram, gb->sramSize); } gb->memory.sram = vf->map(vf, size, MAP_WRITE); } } else { if (gb->memory.sram) { vf->unmap(vf, gb->memory.sram, gb->sramSize); } gb->memory.sram = vf->map(vf, size, MAP_READ); } if (gb->memory.sram == (void*) -1) { gb->memory.sram = NULL; } } else { uint8_t* newSram = anonymousMemoryMap(size); if (gb->memory.sram) { if (size > gb->sramSize) { memcpy(newSram, gb->memory.sram, gb->sramSize); memset(&newSram[gb->sramSize], 0xFF, size - gb->sramSize); } else { memcpy(newSram, gb->memory.sram, size); } mappedMemoryFree(gb->memory.sram, gb->sramSize); } else { memset(newSram, 0xFF, size); } gb->memory.sram = newSram; } if (gb->sramSize < size) { gb->sramSize = size; } }
static void _vffUnmap(struct VFile* vf, void* memory, size_t size) { struct VFileFILE* vff = (struct VFileFILE*) vf; long pos = ftell(vff->file); fseek(vff->file, 0, SEEK_SET); fwrite(memory, size, 1, vff->file); fseek(vff->file, pos, SEEK_SET); mappedMemoryFree(memory, size); }
static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer) { struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; if (softwareRenderer->temporaryBuffer) { mappedMemoryFree(softwareRenderer->temporaryBuffer, GB_VIDEO_HORIZONTAL_PIXELS * GB_VIDEO_VERTICAL_PIXELS * 4); softwareRenderer->temporaryBuffer = 0; } softwareRenderer->currentWy = softwareRenderer->wy; }
bool _vfzClose(struct VFile* vf) { struct VFileZip* vfz = (struct VFileZip*) vf; unzCloseCurrentFile(vfz->z); if (vfz->buffer) { mappedMemoryFree(vfz->buffer, vfz->bufferSize); } free(vfz); return true; }
static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size) { struct VFileSce* vfsce = (struct VFileSce*) vf; SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR); sceIoLseek(vfsce->fd, 0, SEEK_SET); sceIoWrite(vfsce->fd, memory, size); sceIoLseek(vfsce->fd, cur, SEEK_SET); sceIoSyncByFd(vfsce->fd); mappedMemoryFree(memory, size); }
void _vfzUnmap(struct VFile* vf, void* memory, size_t size) { struct VFileZip* vfz = (struct VFileZip*) vf; if (memory != vfz->buffer) { return; } mappedMemoryFree(vfz->buffer, size); vfz->buffer = 0; }
void GBMemoryReset(struct GB* gb) { if (gb->memory.wram) { mappedMemoryFree(gb->memory.wram, GB_SIZE_WORKING_RAM); } gb->memory.wram = anonymousMemoryMap(GB_SIZE_WORKING_RAM); if (gb->model >= GB_MODEL_CGB) { uint32_t* base = (uint32_t*) gb->memory.wram; size_t i; uint32_t pattern = 0; for (i = 0; i < GB_SIZE_WORKING_RAM / 4; i += 4) { if ((i & 0x1FF) == 0) { pattern = ~pattern; } base[i + 0] = pattern; base[i + 1] = pattern; base[i + 2] = ~pattern; base[i + 3] = ~pattern; } } GBMemorySwitchWramBank(&gb->memory, 1); gb->memory.romBank = &gb->memory.rom[GB_SIZE_CART_BANK0]; gb->memory.currentBank = 1; gb->memory.sramCurrentBank = 0; gb->memory.ime = false; gb->memory.ie = 0; gb->memory.dmaNext = INT_MAX; gb->memory.dmaRemaining = 0; gb->memory.dmaSource = 0; gb->memory.dmaDest = 0; gb->memory.hdmaNext = INT_MAX; gb->memory.hdmaRemaining = 0; gb->memory.hdmaSource = 0; gb->memory.hdmaDest = 0; gb->memory.isHdma = false; gb->memory.sramAccess = false; gb->memory.rtcAccess = false; gb->memory.activeRtcReg = 0; gb->memory.rtcLatched = false; memset(&gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs)); memset(&gb->memory.hram, 0, sizeof(gb->memory.hram)); memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState)); GBMBCInit(gb); gb->memory.sramBank = gb->memory.sram; if (!gb->memory.wram) { GBMemoryDeinit(gb); } }
static void GBSramDeinit(struct GB* gb) { if (gb->sramVf) { gb->sramVf->unmap(gb->sramVf, gb->memory.sram, gb->sramSize); if (gb->memory.mbcType == GB_MBC3_RTC) { GBMBCRTCWrite(gb); } gb->sramVf = NULL; } else if (gb->memory.sram) { mappedMemoryFree(gb->memory.sram, gb->sramSize); } gb->memory.sram = 0; }
void GBVideoDeinit(struct GBVideo* video) { video->renderer->deinit(video->renderer); mappedMemoryFree(video->vram, GB_SIZE_VRAM); if (video->renderer->sgbCharRam) { mappedMemoryFree(video->renderer->sgbCharRam, SGB_SIZE_CHAR_RAM); video->renderer->sgbCharRam = NULL; } if (video->renderer->sgbMapRam) { mappedMemoryFree(video->renderer->sgbMapRam, SGB_SIZE_MAP_RAM); video->renderer->sgbMapRam = NULL; } if (video->renderer->sgbPalRam) { mappedMemoryFree(video->renderer->sgbPalRam, SGB_SIZE_PAL_RAM); video->renderer->sgbPalRam = NULL; } if (video->renderer->sgbAttributeFiles) { mappedMemoryFree(video->renderer->sgbAttributeFiles, SGB_SIZE_ATF_RAM); video->renderer->sgbAttributeFiles = NULL; } if (video->renderer->sgbAttributes) { free(video->renderer->sgbAttributes); video->renderer->sgbAttributes = NULL; } }
void GBApplyPatch(struct GB* gb, struct Patch* patch) { size_t patchedSize = patch->outputSize(patch, gb->memory.romSize); if (!patchedSize) { return; } if (patchedSize > GB_SIZE_CART_MAX) { patchedSize = GB_SIZE_CART_MAX; } gb->memory.rom = anonymousMemoryMap(GB_SIZE_CART_MAX); if (!patch->applyPatch(patch, gb->pristineRom, gb->pristineRomSize, gb->memory.rom, patchedSize)) { mappedMemoryFree(gb->memory.rom, patchedSize); gb->memory.rom = gb->pristineRom; return; } gb->memory.romSize = patchedSize; gb->romCrc32 = doCrc32(gb->memory.rom, gb->memory.romSize); }
void _vfmExpand(struct VFileMem* vfm, size_t newSize) { size_t alignedSize = toPow2(newSize); if (alignedSize > vfm->bufferSize) { void* oldBuf = vfm->mem; vfm->mem = anonymousMemoryMap(alignedSize); if (oldBuf) { if (newSize < vfm->size) { memcpy(vfm->mem, oldBuf, newSize); } else { memcpy(vfm->mem, oldBuf, vfm->size); } mappedMemoryFree(oldBuf, vfm->bufferSize); } vfm->bufferSize = alignedSize; } vfm->size = newSize; }
void GBMemoryReset(struct GB* gb) { if (gb->memory.wram) { mappedMemoryFree(gb->memory.wram, GB_SIZE_WORKING_RAM); } gb->memory.wram = anonymousMemoryMap(GB_SIZE_WORKING_RAM); if (gb->model >= GB_MODEL_CGB) { uint32_t* base = (uint32_t*) gb->memory.wram; size_t i; uint32_t pattern = 0; for (i = 0; i < GB_SIZE_WORKING_RAM / 4; i += 4) { if ((i & 0x1FF) == 0) { pattern = ~pattern; } base[i + 0] = pattern; base[i + 1] = pattern; base[i + 2] = ~pattern; base[i + 3] = ~pattern; } } GBMemorySwitchWramBank(&gb->memory, 1); gb->memory.romBank = &gb->memory.rom[GB_SIZE_CART_BANK0]; gb->memory.currentBank = 1; gb->memory.sramCurrentBank = 0; gb->memory.ime = false; gb->memory.ie = 0; gb->memory.dmaRemaining = 0; gb->memory.dmaSource = 0; gb->memory.dmaDest = 0; gb->memory.hdmaRemaining = 0; gb->memory.hdmaSource = 0; gb->memory.hdmaDest = 0; gb->memory.isHdma = false; gb->memory.dmaEvent.context = gb; gb->memory.dmaEvent.name = "GB DMA"; gb->memory.dmaEvent.callback = _GBMemoryDMAService; gb->memory.dmaEvent.priority = 0x40; gb->memory.hdmaEvent.context = gb; gb->memory.hdmaEvent.name = "GB HDMA"; gb->memory.hdmaEvent.callback = _GBMemoryHDMAService; gb->memory.hdmaEvent.priority = 0x41; memset(&gb->memory.hram, 0, sizeof(gb->memory.hram)); switch (gb->memory.mbcType) { case GB_MBC1: gb->memory.mbcState.mbc1.mode = 0; break; default: memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState)); } GBMBCInit(gb); gb->memory.sramBank = gb->memory.sram; if (!gb->memory.wram) { GBMemoryDeinit(gb); } }
void GBMemoryDeinit(struct GB* gb) { mappedMemoryFree(gb->memory.wram, GB_SIZE_WORKING_RAM); if (gb->memory.rom) { mappedMemoryFree(gb->memory.rom, gb->memory.romSize); } }
bool retro_load_game(const struct retro_game_info* game) { struct VFile* rom; if (game->data) { data = anonymousMemoryMap(game->size); dataSize = game->size; memcpy(data, game->data, game->size); rom = VFileFromMemory(data, game->size); } else { data = 0; rom = VFileOpen(game->path, O_RDONLY); } if (!rom) { return false; } core = NULL; #ifdef M_CORE_GBA if (!core && GBAIsROM(rom)) { core = GBACoreCreate(); } #endif #ifdef M_CORE_GB if (!core && GBIsROM(rom)) { core = GBCoreCreate(); } #endif if (!core) { rom->close(rom); mappedMemoryFree(data, game->size); return false; } mCoreInitConfig(core, NULL); core->init(core); core->setAVStream(core, &stream); outputBuffer = malloc(256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); core->setVideoBuffer(core, outputBuffer, 256); core->setAudioBufferSize(core, SAMPLES); blip_set_rates(core->getAudioChannel(core, 0), core->frequency(core), 32768); blip_set_rates(core->getAudioChannel(core, 1), core->frequency(core), 32768); core->setRumble(core, &rumble); #ifdef M_CORE_GBA if (core->platform(core) == PLATFORM_GBA) { struct GBA* gba = core->board; gba->luminanceSource = &lux; const char* sysDir = 0; if (environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir)) { char biosPath[PATH_MAX]; snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, "gba_bios.bin"); struct VFile* bios = VFileOpen(biosPath, O_RDONLY); if (bios) { core->loadBIOS(core, bios, 0); } } GBACheatDeviceCreate(&cheats); GBACheatAttachDevice(gba, &cheats); GBACheatSetInit(&cheatSet, "libretro"); GBACheatAddSet(&cheats, &cheatSet); } #endif savedata = anonymousMemoryMap(SIZE_CART_FLASH1M); struct VFile* save = VFileFromMemory(savedata, SIZE_CART_FLASH1M); _reloadSettings(); core->loadROM(core, rom); core->loadSave(core, save); core->reset(core); return true; }
void RingFIFODeinit(struct RingFIFO* buffer) { mappedMemoryFree(buffer->data, buffer->capacity); buffer->data = 0; }
void GBADeallocateState(struct GBASerializedState* state) { mappedMemoryFree(state, sizeof(struct GBASerializedState)); }
static void _vf3dUnmap(struct VFile* vf, void* memory, size_t size) { struct VFile3DS* vf3d = (struct VFile3DS*) vf; u32 sizeWritten; FSFILE_Write(vf3d->handle, &sizeWritten, 0, memory, size, FS_WRITE_FLUSH); mappedMemoryFree(memory, size); }
void GBVideoDeinit(struct GBVideo* video) { GBVideoAssociateRenderer(video, &dummyRenderer); mappedMemoryFree(video->vram, GB_SIZE_VRAM); }
bool retro_load_game(const struct retro_game_info* game) { struct VFile* rom; if (game->data) { data = anonymousMemoryMap(game->size); dataSize = game->size; memcpy(data, game->data, game->size); rom = VFileFromMemory(data, game->size); } else { data = 0; rom = VFileOpen(game->path, O_RDONLY); } if (!rom) { return false; } core = mCoreFindVF(rom); if (!core) { rom->close(rom); mappedMemoryFree(data, game->size); return false; } mCoreInitConfig(core, NULL); core->init(core); core->setAVStream(core, &stream); size_t size = 256 * 224 * BYTES_PER_PIXEL; outputBuffer = malloc(size); memset(outputBuffer, 0xFF, size); core->setVideoBuffer(core, outputBuffer, 256); core->setAudioBufferSize(core, SAMPLES); blip_set_rates(core->getAudioChannel(core, 0), core->frequency(core), 32768); blip_set_rates(core->getAudioChannel(core, 1), core->frequency(core), 32768); core->setPeripheral(core, mPERIPH_RUMBLE, &rumble); savedata = anonymousMemoryMap(SIZE_CART_FLASH1M); struct VFile* save = VFileFromMemory(savedata, SIZE_CART_FLASH1M); _reloadSettings(); core->loadROM(core, rom); core->loadSave(core, save); const char* sysDir = 0; const char* biosName = 0; char biosPath[PATH_MAX]; environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir); #ifdef M_CORE_GBA if (core->platform(core) == PLATFORM_GBA) { core->setPeripheral(core, mPERIPH_GBA_LUMINANCE, &lux); biosName = "gba_bios.bin"; } #endif #ifdef M_CORE_GB if (core->platform(core) == PLATFORM_GB) { memset(&cam, 0, sizeof(cam)); cam.height = GBCAM_HEIGHT; cam.width = GBCAM_WIDTH; cam.caps = 1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER; cam.frame_raw_framebuffer = _updateCamera; core->setPeripheral(core, mPERIPH_IMAGE_SOURCE, &imageSource); environCallback(RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE, &cam); const char* modelName = mCoreConfigGetValue(&core->config, "gb.model"); struct GB* gb = core->board; if (modelName) { gb->model = GBNameToModel(modelName); } else { GBDetectModel(gb); } switch (gb->model) { case GB_MODEL_AGB: case GB_MODEL_CGB: biosName = "gbc_bios.bin"; break; case GB_MODEL_SGB: biosName = "sgb_bios.bin"; break; case GB_MODEL_DMG: default: biosName = "gb_bios.bin"; break; } } #endif if (core->opts.useBios && sysDir && biosName) { snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, biosName); struct VFile* bios = VFileOpen(biosPath, O_RDONLY); if (bios) { core->loadBIOS(core, bios, 0); } } core->reset(core); _setupMaps(core); return true; }