From 8b1e0e5d570d0dbbf1b6c788a08cd2cdbbf79561 Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Sat, 11 Aug 2018 12:49:53 -0700 Subject: [PATCH] Remove delta savestate compression Its a huge mess and the same thing can be accomplished by setting the emu directory to a zfs partition. This will make working on the SD card interface significantly easier. --- missingFunctions.txt | 1 + qtBuildSystem/Mu/Mu.pro | 5 - qtBuildSystem/Mu/emuwrapper.cpp | 4 - qtBuildSystem/Mu/statemanager.cpp | 10 + qtBuildSystem/Mu/statemanager.h | 1 + qtBuildSystem/Mu/statemanager.ui | 10 + src/bps/crc32.c | 21 -- src/bps/crc32.h | 10 - src/bps/global.h | 22 -- src/bps/libbps.c | 394 ----------------------------- src/bps/libbps.h | 76 ------ src/emulator.c | 152 +++++------ src/emulator.h | 43 +--- src/hardwareRegistersAccessors.c.h | 2 +- src/makefile.all | 2 - src/sdcard.c | 168 +----------- src/sdcard.h | 11 - 17 files changed, 89 insertions(+), 843 deletions(-) delete mode 100755 src/bps/crc32.c delete mode 100755 src/bps/crc32.h delete mode 100755 src/bps/global.h delete mode 100755 src/bps/libbps.c delete mode 100755 src/bps/libbps.h diff --git a/missingFunctions.txt b/missingFunctions.txt index f458965..4657540 100644 --- a/missingFunctions.txt +++ b/missingFunctions.txt @@ -6,6 +6,7 @@ When running OS commands through callFunction() it can crash Only runs in debug mode because the touchscreen can only be pushed with a jump to OS function hack Holding the buttons emulates pressing them like a turbo button(may be caused by the lack of sound emulation, a sound plays on app switch and may block the CPU while waiting for the button to release) State manager goes bezerk and crashes when saving on android, also can't close the window or it won't open again(also only on android) +Deleting a save state Fixed: Screenshots use window size and that makes them blurry from filtering diff --git a/qtBuildSystem/Mu/Mu.pro b/qtBuildSystem/Mu/Mu.pro index 733e19f..0484f54 100644 --- a/qtBuildSystem/Mu/Mu.pro +++ b/qtBuildSystem/Mu/Mu.pro @@ -51,8 +51,6 @@ SOURCES += \ main.cpp \ mainwindow.cpp \ touchscreen.cpp \ - src/bps/crc32.c \ - src/bps/libbps.c \ src/m68k/m68kcpu.c \ src/m68k/m68kdasm.c \ src/m68k/m68kopac.c \ @@ -73,9 +71,6 @@ SOURCES += \ statemanager.cpp HEADERS += \ - src/bps/crc32.h \ - src/bps/global.h \ - src/bps/libbps.h \ src/m68k/m68k.h \ src/m68k/m68kconf.h \ src/m68k/m68kcpu.h \ diff --git a/qtBuildSystem/Mu/emuwrapper.cpp b/qtBuildSystem/Mu/emuwrapper.cpp index 1cd6bda..ef33f37 100644 --- a/qtBuildSystem/Mu/emuwrapper.cpp +++ b/qtBuildSystem/Mu/emuwrapper.cpp @@ -56,10 +56,6 @@ void frontendHandleDebugPrint(){ } } -uint64_t frontendGetSysTime(){ - return QDateTime::currentMSecsSinceEpoch(); -} - EmuWrapper::EmuWrapper(){ if(alreadyExists == true) diff --git a/qtBuildSystem/Mu/statemanager.cpp b/qtBuildSystem/Mu/statemanager.cpp index e456622..6ab6339 100644 --- a/qtBuildSystem/Mu/statemanager.cpp +++ b/qtBuildSystem/Mu/statemanager.cpp @@ -81,6 +81,16 @@ void StateManager::on_loadState_clicked(){ } } +void StateManager::on_deleteState_clicked(){ + if(ui->states->currentItem()){ + QString statePath = ((MainWindow*)parentWidget())->settings.value("resourceDirectory", "").toString() + "/saveStates/" + ui->states->currentItem()->text(); + + //not hooked up yet + //((MainWindow*)parentWidget())->emu.loadState(statePath + ".state"); + updateStatePreview(); + } +} + void StateManager::on_states_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous){ updateStatePreview(); } diff --git a/qtBuildSystem/Mu/statemanager.h b/qtBuildSystem/Mu/statemanager.h index 79a094b..b3758e4 100644 --- a/qtBuildSystem/Mu/statemanager.h +++ b/qtBuildSystem/Mu/statemanager.h @@ -25,6 +25,7 @@ private slots: void on_saveState_clicked(); void on_loadState_clicked(); + void on_deleteState_clicked(); void on_states_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous); diff --git a/qtBuildSystem/Mu/statemanager.ui b/qtBuildSystem/Mu/statemanager.ui index 3f56025..237ba18 100644 --- a/qtBuildSystem/Mu/statemanager.ui +++ b/qtBuildSystem/Mu/statemanager.ui @@ -90,6 +90,16 @@ + + + + Delete State + + + false + + + diff --git a/src/bps/crc32.c b/src/bps/crc32.c deleted file mode 100755 index 14bc4f0..0000000 --- a/src/bps/crc32.c +++ /dev/null @@ -1,21 +0,0 @@ -//Module name: crc32 -//Author: Alcaro -//Date: June 3, 2015 -//Licence: GPL v3.0 or higher - -#include "crc32.h" - -static const uint32_t crctable_4bits[]={ - 0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4, 0x4DB26158, 0x5005713C, - 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C, 0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C, -}; -uint32_t crc32_update(const uint8_t* data, size_t len, uint32_t crc) -{ - crc = ~crc; - for (size_t i=0;i>4); - crc = crctable_4bits[(crc^(data[i]>>4))&0x0F] ^ (crc>>4); - } - return ~crc; -} diff --git a/src/bps/crc32.h b/src/bps/crc32.h deleted file mode 100755 index 9a28542..0000000 --- a/src/bps/crc32.h +++ /dev/null @@ -1,10 +0,0 @@ -//Module name: crc32 -//Author: Alcaro -//Date: June 3, 2015 -//Licence: GPL v3.0 or higher - -#include -#include - -uint32_t crc32_update(const uint8_t* data, size_t len, uint32_t crc); -static inline uint32_t crc32(const uint8_t* data, size_t len) { return crc32_update(data, len, 0); } diff --git a/src/bps/global.h b/src/bps/global.h deleted file mode 100755 index 6798831..0000000 --- a/src/bps/global.h +++ /dev/null @@ -1,22 +0,0 @@ -//Module name: Floating IPS, global header -//Author: Alcaro -//Date: See Git history -//Licence: GPL v3.0 or higher - -#ifndef struct_mem -#define struct_mem - -//the standard library can be assumed to exist -#include //size_t, SIZE_MAX -#include //uint8_t - -#ifndef SIZE_MAX -#define SIZE_MAX ((size_t)-1) -#endif - -struct mem { - uint8_t * ptr; - size_t len; -}; - -#endif diff --git a/src/bps/libbps.c b/src/bps/libbps.c deleted file mode 100755 index 4dcfa7c..0000000 --- a/src/bps/libbps.c +++ /dev/null @@ -1,394 +0,0 @@ -//Module name: libbps -//Author: Alcaro -//Date: November 7, 2015 -//Licence: GPL v3.0 or higher - -#include "libbps.h" - -#include //malloc, realloc, free -#include //memcpy, memset -#include //uint8_t, uint32_t -#include "crc32.h"//crc32 - -static uint32_t read32(uint8_t * ptr) -{ - uint32_t out; - out =ptr[0]; - out|=ptr[1]<<8; - out|=ptr[2]<<16; - out|=ptr[3]<<24; - return out; -} - -enum { SourceRead, TargetRead, SourceCopy, TargetCopy }; - -static bool try_add(size_t* a, size_t b) -{ - if (SIZE_MAX-*a < b) return false; - *a+=b; - return true; -} - -static bool try_shift(size_t* a, size_t b) -{ - if (SIZE_MAX>>b < *a) return false; - *a<<=b; - return true; -} - -static bool decodenum(const uint8_t* ptr, size_t* out) -{ - *out=0; - uint32_t shift=0; - while (true) - { - uint8_t next=*ptr++; - size_t addthis=(next&0x7F); - if (shift) addthis++; - if (!try_shift(&addthis, shift)) return false; - // unchecked because if it was shifted, the lowest bit is zero, and if not, it's <=0x7F. - if (!try_add(out, addthis)) return false; - if (next&0x80) return true; - shift+=7; - } -} - -#define error(which) do { error=which; goto exit; } while(0) -#define assert_sum(a,b) do { if (SIZE_MAX-(a)<(b)) error(bps_too_big); } while(0) -#define assert_shift(a,b) do { if (SIZE_MAX>>(b)<(a)) error(bps_too_big); } while(0) -enum bpserror bps_apply(struct mem patch, struct mem in, struct mem * out, struct mem * metadata, bool accept_wrong_input) -{ - enum bpserror error = bps_ok; - out->len=0; - out->ptr=NULL; - if (metadata) - { - metadata->len=0; - metadata->ptr=NULL; - } - if (patch.len<4+3+12) return bps_broken; - - if (true) - { -#define read8() (*(patchat++)) -#define decodeto(var) \ - do { \ - if (!decodenum(patchat, &var)) error(bps_too_big); \ - } while(false) -#define write8(byte) (*(outat++)=byte) - - const uint8_t * patchat=patch.ptr; - const uint8_t * patchend=patch.ptr+patch.len-12; - - if (read8()!='B') error(bps_broken); - if (read8()!='P') error(bps_broken); - if (read8()!='S') error(bps_broken); - if (read8()!='1') error(bps_broken); - - uint32_t crc_in_e = read32(patch.ptr+patch.len-12); - uint32_t crc_out_e = read32(patch.ptr+patch.len-8); - uint32_t crc_patch_e = read32(patch.ptr+patch.len-4); - - uint32_t crc_in_a = crc32(in.ptr, in.len); - uint32_t crc_patch_a = crc32(patch.ptr, patch.len-4); - - if (crc_patch_a != crc_patch_e) error(bps_broken); - - size_t inlen; - decodeto(inlen); - - size_t outlen; - decodeto(outlen); - - if (inlen!=in.len || crc_in_a!=crc_in_e) - { - if (in.len==outlen && crc_in_a==crc_out_e) error=bps_to_output; - else error=bps_not_this; - if (!accept_wrong_input) goto exit; - } - - out->len=outlen; - out->ptr=(uint8_t*)malloc(outlen); - - const uint8_t * instart=in.ptr; - const uint8_t * inreadat=in.ptr; - const uint8_t * inend=in.ptr+in.len; - - uint8_t * outstart=out->ptr; - uint8_t * outreadat=out->ptr; - uint8_t * outat=out->ptr; - uint8_t * outend=out->ptr+out->len; - - size_t metadatalen; - decodeto(metadatalen); - - if (metadata && metadatalen) - { - metadata->len=metadatalen; - metadata->ptr=(uint8_t*)malloc(metadatalen+1); - for (size_t i=0;iptr[i]=read8(); - metadata->ptr[metadatalen]='\0';//just to be on the safe side - that metadata is assumed to be text, might as well terminate it - } - else - { - for (size_t i=0;i>2)+1; - int action=(thisinstr&3); - if (outat+length>outend) error(bps_broken); - - switch (action) - { - case SourceRead: - { - if (outat-outstart+length > in.len) error(bps_broken); - for (size_t i=0;ipatchend) error(bps_broken); - for (size_t i=0;i>1; - if ((encodeddistance&1)==0) inreadat+=distance; - else inreadat-=distance; - - if (inreadatinend) error(bps_broken); - for (size_t i=0;i>1; - if ((encodeddistance&1)==0) outreadat+=distance; - else outreadat-=distance; - - if (outreadat=outat || outreadat+length>outend) error(bps_broken); - for (size_t i=0;iptr, out->len); - - if (crc_out_a!=crc_out_e) - { - error=bps_not_this; - if (!accept_wrong_input) goto exit; - } - return error; -#undef read8 -#undef decodeto -#undef write8 - } - -exit: - free(out->ptr); - out->len=0; - out->ptr=NULL; - if (metadata) - { - free(metadata->ptr); - metadata->len=0; - metadata->ptr=NULL; - } - return error; -} - - - -#define write(val) \ - do { \ - out[outlen++]=(val); \ - if (outlen==outbuflen) \ - { \ - outbuflen*=2; \ - out=(uint8_t*)realloc(out, outbuflen); \ - } \ - } while(0) -#define write32(val) \ - do { \ - uint32_t tmp=(val); \ - write(tmp); \ - write(tmp>>8); \ - write(tmp>>16); \ - write(tmp>>24); \ - } while(0) -#define writenum(val) \ - do { \ - size_t tmpval=(val); \ - while (true) \ - { \ - uint8_t tmpbyte=(tmpval&0x7F); \ - tmpval>>=7; \ - if (!tmpval) \ - { \ - write(tmpbyte|0x80); \ - break; \ - } \ - write(tmpbyte); \ - tmpval--; \ - } \ - } while(0) - -enum bpserror bps_create_linear(struct mem sourcemem, struct mem targetmem, struct mem metadata, struct mem * patchmem) -{ - if (sourcemem.len>=(SIZE_MAX>>2) - 16) return bps_too_big;//the 16 is just to be on the safe side, I don't think it's needed. - if (targetmem.len>=(SIZE_MAX>>2) - 16) return bps_too_big; - - const uint8_t * source=sourcemem.ptr; - const uint8_t * sourceend=sourcemem.ptr+sourcemem.len; - if (sourcemem.len>targetmem.len) sourceend=sourcemem.ptr+targetmem.len; - const uint8_t * targetbegin=targetmem.ptr; - const uint8_t * target=targetmem.ptr; - const uint8_t * targetend=targetmem.ptr+targetmem.len; - - const uint8_t * targetcopypos=targetbegin; - - size_t outbuflen=4096; - uint8_t * out=(uint8_t*)malloc(outbuflen); - size_t outlen=0; - write('B'); - write('P'); - write('S'); - write('1'); - writenum(sourcemem.len); - writenum(targetmem.len); - writenum(metadata.len); - for (size_t i=0;i1 || numunchanged == (uintptr_t)(targetend-target)) - { - //assert_shift((numunchanged-1), 2); - writenum((numunchanged-1)<<2 | 0);//SourceRead - source+=numunchanged; - target+=numunchanged; - } - - size_t numchanged=0; - if (lastknownchange>target) numchanged=lastknownchange-target; - while ((source+numchanged>=sourceend || - source[numchanged]!=target[numchanged] || - source[numchanged+1]!=target[numchanged+1] || - source[numchanged+2]!=target[numchanged+2]) && - target+numchanged=sourceend) numchanged=targetend-target; - } - lastknownchange=target+numchanged; - if (numchanged) - { - //assert_shift((numchanged-1), 2); - size_t rle1start=(target==targetbegin); - while (true) - { - if ( - target[rle1start-1]==target[rle1start+0] && - target[rle1start+0]==target[rle1start+1] && - target[rle1start+1]==target[rle1start+2] && - target[rle1start+2]==target[rle1start+3]) - { - numchanged=rle1start; - break; - } - if ( - target[rle1start-2]==target[rle1start+0] && - target[rle1start-1]==target[rle1start+1] && - target[rle1start+0]==target[rle1start+2] && - target[rle1start+1]==target[rle1start+3] && - target[rle1start+2]==target[rle1start+4]) - { - numchanged=rle1start; - break; - } - if (rle1start+3>=numchanged) break; - rle1start++; - } - if (numchanged) - { - writenum((numchanged-1)<<2 | TargetRead); - for (size_t i=0;iptr=out; - patchmem->len=outlen; - - //while this may look like it can be fooled by a patch containing one of any other command, it - // can't, because the ones that aren't SourceRead requires an argument. - size_t i; - for (i=mainContentPos;(out[i]&0x80)==0x00;i++) {} - if (i==outlen-12-1) return bps_identical; - - return bps_ok; -} - -#undef write_nocrc -#undef write -#undef writenum - -void bps_free(struct mem mem) -{ - free(mem.ptr); -} -#undef error diff --git a/src/bps/libbps.h b/src/bps/libbps.h deleted file mode 100755 index 8a1fe81..0000000 --- a/src/bps/libbps.h +++ /dev/null @@ -1,76 +0,0 @@ -//Module name: libbps -//Author: Alcaro -//Date: November 30, 2015 -//Licence: GPL v3.0 or higher - -#include "global.h" -#include - -#ifndef __cplusplus -#include //bool; if this file does not exist (hi msvc), remove it and uncomment the following three lines. -//#define bool int -//#define true 1 -//#define false 0 -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -enum bpserror { - bps_ok,//Patch applied or created successfully. - - bps_to_output,//You attempted to apply a patch to its output. - bps_not_this, //This is not the intended input file for this patch. - bps_broken, //This is not a BPS patch, or it's malformed somehow. - bps_io, //The patch could not be read. - - bps_identical, //The input files are identical. - bps_too_big, //Somehow, you're asking for something a size_t can't represent. - bps_out_of_mem,//Memory allocation failure. - bps_canceled, //The callback returned false. - - bps_shut_up_gcc//This one isn't used, it's just to kill a stray comma warning. -}; - -//Applies the given BPS patch to the given ROM and puts it in 'out'. Metadata, if present and -// requested ('metadata'!=NULL), is also returned. Send both to bps_free when you're done with them. -//If accept_wrong_input is true, it may return bps_to_output or bps_not_this, while putting non-NULL in out/metadata. -enum bpserror bps_apply(struct mem patch, struct mem in, struct mem * out, struct mem * metadata, bool accept_wrong_input); - -//Creates a BPS patch that converts source to target and stores it to patch. It is safe to give -// {NULL,0} as metadata. -enum bpserror bps_create_linear(struct mem source, struct mem target, struct mem metadata, struct mem * patch); - -//Frees the memory returned in the output parameters of the above. Do not call it twice on the same -// input, nor on anything you got from anywhere else. bps_free is guaranteed to be equivalent to -// calling stdlib.h's free() on mem.ptr. -void bps_free(struct mem mem); - -struct bpsinfo { - enum bpserror error; // If this is not bps_ok, all other values are undefined. - - size_t size_in; - size_t size_out; - - uint32_t crc_in; - uint32_t crc_out; - uint32_t crc_patch; - - size_t meta_start; - size_t meta_size; - - //Tells approximately how much of the input ROM is changed compared to the output ROM. - //It's quite heuristic. The algorithm may change with or without notice. - //As of writing, I believe this is accurate to 2 significant digits in base 10. - //It's also more expensive to calculate than the other data, so it's optional. - //If you don't want it, their values are undefined. - //The denominator is always guaranteed nonzero, even if something else says it's undefined. - //Note that this can return success for invalid patches. - size_t change_num; - size_t change_denom; -}; - -#ifdef __cplusplus -} -#endif diff --git a/src/emulator.c b/src/emulator.c index 5c9fbf7..41191de 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -35,7 +35,7 @@ uint8_t* palmRam; uint8_t* palmRom; uint8_t palmReg[REG_SIZE]; input_t palmInput; -sd_card_t palmSdCard; +buffer_t palmSdCard; misc_hw_t palmMisc; uint16_t palmFramebuffer[160 * (160 + 60)];//really 160*160, the extra pixels are the silkscreened digitizer area uint16_t* palmExtendedFramebuffer; @@ -45,18 +45,6 @@ double palmCycleCounter;//can be greater then 0 if too many cycles where run double palmClockMultiplier;//used by the emulator to overclock the emulated Palm -uint64_t (*emulatorGetSysTime)() = NULL; -uint64_t* (*emulatorGetSdCardStateChunkList)(uint64_t sessionId, uint64_t stateId) = NULL;//returns the BPS chunkIds for a stateId in the order they need to be applied -void (*emulatorSetSdCardStateChunkList)(uint64_t sessionId, uint64_t stateId, uint64_t* data) = NULL;//sets the BPS chunkIds for a stateId in the order they need to be applied -buffer_t (*emulatorGetSdCardChunk)(uint64_t sessionId, uint64_t chunkId) = NULL; -void (*emulatorSetSdCardChunk)(uint64_t sessionId, uint64_t chunkId, buffer_t chunk) = NULL; - -static inline bool allSdCardCallbacksPresent(){ - if(emulatorGetSysTime && emulatorGetSdCardStateChunkList && emulatorSetSdCardStateChunkList && emulatorGetSdCardChunk && emulatorSetSdCardChunk) - return true; - return false; -} - uint32_t emulatorInit(buffer_t palmRomDump, buffer_t palmBootDump, uint32_t specialFeatures){ if(emulatorInitialized) return EMU_ERROR_NONE; @@ -113,7 +101,6 @@ uint32_t emulatorInit(buffer_t palmRomDump, buffer_t palmBootDump, uint32_t spec resetAddressSpace(); sed1376Reset(); ads7846Reset(); - sdCardInit(); sandboxInit(); memset(&palmInput, 0x00, sizeof(palmInput)); @@ -140,7 +127,8 @@ void emulatorExit(){ free(palmRom); if(palmSpecialFeatures & FEATURE_320x320) free(palmExtendedFramebuffer); - sdCardExit(); + if(palmSdCard.data) + free(palmSdCard.data); emulatorInitialized = false; } } @@ -159,51 +147,6 @@ void emulatorSetRtc(uint16_t days, uint8_t hours, uint8_t minutes, uint8_t secon setRtc(days, hours, minutes, seconds); } -uint32_t emulatorSetNewSdCard(uint64_t size, uint8_t type){ - if(!allSdCardCallbacksPresent()) - return EMU_ERROR_CALLBACKS_NOT_SET; - - //more than 2gb/too large for FAT16 or not a card type - if(size > 0x80000000 || type >= CARD_END) - return EMU_ERROR_INVALID_PARAMETER; - - if(type != CARD_NONE){ - palmSdCard.sessionId = emulatorGetSysTime();//completely new SD card, reset delta state chain - palmSdCard.stateId = 0x0000000000000000;//set when saving state - palmSdCard.size = size; - palmSdCard.type = type; - palmSdCard.inserted = true; - } - else{ - memset(&palmSdCard, 0x00, sizeof(palmSdCard)); - } - - return EMU_ERROR_NONE; -} - -buffer_t emulatorGetSdCardImage(){ - return sdCardGetImage(); -} - -uint32_t emulatorSetSdCardFromImage(buffer_t image, uint8_t type){ - if(!allSdCardCallbacksPresent()) - return EMU_ERROR_CALLBACKS_NOT_SET; - - //invalid pointer, more than 2gb/too large for FAT16 or not a card type - if(!image.data || image.size > 0x80000000 || type == CARD_NONE || type >= CARD_END) - return EMU_ERROR_INVALID_PARAMETER; - - sdCardSetFromImage(image); - - palmSdCard.sessionId = emulatorGetSysTime();//completely new SD card, reset delta state chain - palmSdCard.stateId = 0x0000000000000000;//set when saving state - palmSdCard.size = image.size; - palmSdCard.type = type; - palmSdCard.inserted = true; - - return EMU_ERROR_NONE; -} - uint64_t emulatorGetStateSize(){ uint64_t size = 0; @@ -222,8 +165,6 @@ uint64_t emulatorGetStateSize(){ size += TOTAL_MEMORY_BANKS;//bank handlers size += sizeof(uint32_t) * 4 * CHIP_END;//chip select states size += sizeof(uint8_t) * 5 * CHIP_END;//chip select states - size += sizeof(uint64_t) * 3;//palmSdCard - size += sizeof(uint8_t) * 2;//palmSdCard size += sizeof(uint64_t) * 4;//32.32 fixed point double, timerXCycleCounter and CPU cycle timers size += sizeof(int32_t);//pllWakeWait size += sizeof(uint32_t);//clk32Counter @@ -236,6 +177,8 @@ uint64_t emulatorGetStateSize(){ size += sizeof(uint8_t);//ads7846PenIrqEnabled size += sizeof(uint16_t);//ads7846 size += sizeof(uint8_t) * 7;//palmMisc + size += sizeof(uint64_t);//palmSdCard.size + size += palmSdCard.size;//palmSdCard.data return size; } @@ -308,23 +251,6 @@ bool emulatorSaveState(buffer_t buffer){ memcpy(buffer.data + offset, sed1376Framebuffer, SED1376_FB_SIZE); offset += SED1376_FB_SIZE; - //SD card - //update SD card struct and save SD card data - if(allSdCardCallbacksPresent() && palmSdCard.type != CARD_NONE){ - palmSdCard.stateId = emulatorGetSysTime(); - sdCardSaveState(palmSdCard.sessionId, palmSdCard.stateId); - } - writeStateValueUint64(buffer.data + offset, palmSdCard.sessionId); - offset += sizeof(uint64_t); - writeStateValueUint64(buffer.data + offset, palmSdCard.stateId); - offset += sizeof(uint64_t); - writeStateValueUint64(buffer.data + offset, palmSdCard.size); - offset += sizeof(uint64_t); - writeStateValueUint8(buffer.data + offset, palmSdCard.type); - offset += sizeof(uint8_t); - writeStateValueBool(buffer.data + offset, palmSdCard.inserted); - offset += sizeof(uint8_t); - //timing writeStateValueDouble(buffer.data + offset, palmCrystalCycles); offset += sizeof(uint64_t); @@ -385,6 +311,12 @@ bool emulatorSaveState(buffer_t buffer){ writeStateValueUint8(buffer.data + offset, palmMisc.dataPort); offset += sizeof(uint8_t); + //SD card + writeStateValueUint64(buffer.data + offset, palmSdCard.size); + offset += sizeof(uint64_t); + memcpy(palmSdCard.data, buffer.data + offset, palmSdCard.size); + offset += palmSdCard.size; + return true; } @@ -458,21 +390,6 @@ bool emulatorLoadState(buffer_t buffer){ offset += SED1376_FB_SIZE; sed1376RefreshLut(); - //SD card - palmSdCard.sessionId = readStateValueUint64(buffer.data + offset); - offset += sizeof(uint64_t); - palmSdCard.stateId = readStateValueUint64(buffer.data + offset); - offset += sizeof(uint64_t); - palmSdCard.size = readStateValueUint64(buffer.data + offset); - offset += sizeof(uint64_t); - palmSdCard.type = readStateValueUint8(buffer.data + offset); - offset += sizeof(uint8_t); - palmSdCard.inserted = readStateValueBool(buffer.data + offset); - offset += sizeof(uint8_t); - //update SD card data from SD card struct - if(allSdCardCallbacksPresent() && palmSdCard.type != CARD_NONE) - sdCardLoadState(palmSdCard.sessionId, palmSdCard.stateId); - //timing palmCrystalCycles = readStateValueDouble(buffer.data + offset); offset += sizeof(uint64_t); @@ -533,6 +450,23 @@ bool emulatorLoadState(buffer_t buffer){ palmMisc.dataPort = readStateValueUint8(buffer.data + offset); offset += sizeof(uint8_t); + //SD card + if(palmSdCard.data){ + free(palmSdCard.data); + palmSdCard.data = NULL; + } + palmSdCard.size = readStateValueUint64(buffer.data + offset); + offset += sizeof(uint64_t); + if(palmSdCard.size > 0){ + palmSdCard.data = malloc(palmSdCard.size); + + if(!palmSdCard.data) + return false; + + memcpy(palmSdCard.data, buffer.data + offset, palmSdCard.size); + } + offset += palmSdCard.size; + return true; } @@ -545,6 +479,36 @@ buffer_t emulatorGetRamBuffer(){ return ramInfo; } +buffer_t emulatorGetSdCardBuffer(){ + return palmSdCard; +} + +uint32_t emulatorInsertSdCard(buffer_t image){ + //SD card is currently inserted + if(palmSdCard.data) + return EMU_ERROR_RESOURCE_LOCKED; + + palmSdCard.data = malloc(image.size); + if(!palmSdCard.data) + return EMU_ERROR_OUT_OF_MEMORY; + + if(image.data) + memcpy(palmSdCard.data, image.data, image.size); + else + memset(palmSdCard.data, 0x00, image.size); + + palmSdCard.size = image.size; + + return EMU_ERROR_NONE; +} + +void emulatorEjectSdCard(){ + if(palmSdCard.data) + free(palmSdCard.data); + palmSdCard.data = NULL; + palmSdCard.size = 0; +} + uint32_t emulatorInstallPrcPdb(buffer_t file){ //pretend to pass for now //return EMU_ERROR_NOT_IMPLEMENTED; diff --git a/src/emulator.h b/src/emulator.h index ae8ee7c..3546b31 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -50,15 +50,8 @@ enum{ EMU_ERROR_NOT_IMPLEMENTED, EMU_ERROR_CALLBACKS_NOT_SET, EMU_ERROR_OUT_OF_MEMORY, - EMU_ERROR_INVALID_PARAMETER -}; - -//SD card types -enum{ - CARD_NONE = 0, - CARD_SD, - CARD_MMC, - CARD_END + EMU_ERROR_INVALID_PARAMETER, + EMU_ERROR_RESOURCE_LOCKED }; //port types @@ -97,20 +90,6 @@ typedef struct{ bool touchscreenTouched; }input_t; -typedef struct{ - //the SD card is stored as a directory structure with an /(SESSIONID)/sdCard(STATEID).info and /(SESSIONID)/sdCard(CHUNKID).bps - //each emulator instance has its own SD card SESSIONID directory if it has an SD card - //sdCard(STATEID).info specifys the BPS files to use - //every savestate a new BPS file is created with the changes made to the SD card since the last savestate - //the first BPS is a patch over a buffer of SD card size filled with 0x00 - //the frontend provides file access but the emulator does all the patching - uint64_t sessionId;//64 bit system time when emulator starts - uint64_t stateId;//64 bit system time when the savestate was taken - uint64_t size; - uint8_t type; - bool inserted; -}sd_card_t; - typedef struct{ bool powerButtonLed; bool lcdOn; @@ -127,15 +106,14 @@ typedef struct{ //config options #define EMU_FPS 60.0 -#define SD_CARD_CHUNK_VECTOR_SIZE 100 -#define SAVE_STATE_VERSION 1 +#define SAVE_STATE_VERSION 2 //emulator data, some are GUI interface variables, some should be left alone extern uint8_t* palmRam;//dont touch extern uint8_t* palmRom;//dont touch extern uint8_t palmReg[];//dont touch extern input_t palmInput;//write allowed -extern sd_card_t palmSdCard;//dont touch +extern buffer_t palmSdCard;//dont touch extern misc_hw_t palmMisc;//read/write allowed extern uint16_t palmFramebuffer[];//read allowed if FEATURE_320x320 is off, or else invalid data will be displayed extern uint16_t* palmExtendedFramebuffer;//read allowed if FEATURE_320x320 is on, or else SIGSEGV @@ -144,25 +122,18 @@ extern double palmCrystalCycles;//dont touch extern double palmCycleCounter;//dont touch extern double palmClockMultiplier;//read/write allowed -//callbacks -extern uint64_t (*emulatorGetSysTime)(); -extern uint64_t* (*emulatorGetSdCardStateChunkList)(uint64_t sessionId, uint64_t stateId);//returns the BPS chunkIds for a stateId in the order they need to be applied -extern void (*emulatorSetSdCardStateChunkList)(uint64_t sessionId, uint64_t stateId, uint64_t* data);//sets the BPS chunkIds for a stateId in the order they need to be applied -extern buffer_t (*emulatorGetSdCardChunk)(uint64_t sessionId, uint64_t chunkId); -extern void (*emulatorSetSdCardChunk)(uint64_t sessionId, uint64_t chunkId, buffer_t chunk); - //functions uint32_t emulatorInit(buffer_t palmRomDump, buffer_t palmBootDump, uint32_t specialFeatures);//calling any emulator functions before emulatorInit results in undefined behavior void emulatorExit(); void emulatorReset(); void emulatorSetRtc(uint16_t days, uint8_t hours, uint8_t minutes, uint8_t seconds); -uint32_t emulatorSetNewSdCard(uint64_t size, uint8_t type); -buffer_t emulatorGetSdCardImage();//this is a direct pointer to the SD card data, do not free it -uint32_t emulatorSetSdCardFromImage(buffer_t image, uint8_t type); uint64_t emulatorGetStateSize(); bool emulatorSaveState(buffer_t buffer);//true = success bool emulatorLoadState(buffer_t buffer);//true = success buffer_t emulatorGetRamBuffer();//this is a direct pointer to RAM, do not free it +buffer_t emulatorGetSdCardBuffer();//this is a direct pointer to the SD card data, do not free it +uint32_t emulatorInsertSdCard(buffer_t image);//use (NULL, desired size) to create a new empty SD card +void emulatorEjectSdCard(); uint32_t emulatorInstallPrcPdb(buffer_t file); void emulateFrame(); diff --git a/src/hardwareRegistersAccessors.c.h b/src/hardwareRegistersAccessors.c.h index 6a431c5..365dc52 100644 --- a/src/hardwareRegistersAccessors.c.h +++ b/src/hardwareRegistersAccessors.c.h @@ -431,7 +431,7 @@ static inline uint8_t getPortDInputPinValues(){ //portDInputValues |= 0x80;//battery dead bit, dont know the proper level to set this - if(palmSdCard.inserted) + if(palmSdCard.data) portDInputValues |= 0x20; //kbd row 0 diff --git a/src/makefile.all b/src/makefile.all index c8929bc..4e246f2 100644 --- a/src/makefile.all +++ b/src/makefile.all @@ -12,6 +12,4 @@ EMU_SOURCES_C := $(EMU_PATH)/emulator.c \ $(EMU_PATH)/m68k/m68kopac.c \ $(EMU_PATH)/m68k/m68kdasm.c \ $(EMU_PATH)/m68k/m68kcpu.c \ - $(EMU_PATH)/bps/libbps.c \ - $(EMU_PATH)/bps/crc32.c \ $(EMU_PATH)/debug/sandbox.c diff --git a/src/sdcard.c b/src/sdcard.c index c3d75a9..a1b570c 100644 --- a/src/sdcard.c +++ b/src/sdcard.c @@ -1,174 +1,8 @@ -#include #include -#include -#include -#include "emulator.h" -#include "bps/libbps.h" +//#include "emulator.h" -static uint8_t* sdCardData; -static uint8_t* sdCardOldData; -static uint64_t* sdCardChunks;//0 terminated array -static uint64_t sdCardChunkIndex; -static uint64_t sdCardChunkMaxIndex; -static uint64_t sdCardSize; - - -static inline void updateChunkBufferLength(){ - uint64_t newChunkLength = 0; - - while(true){ - newChunkLength++; - if(sdCardChunks[newChunkLength] == 0x0000000000000000) - break; - } - - sdCardChunkIndex = newChunkLength; - sdCardChunkMaxIndex = newChunkLength; -} - - -void sdCardInit(){ - sdCardData = NULL; - sdCardOldData = NULL; - sdCardChunks = NULL; - sdCardChunkIndex = 0; - sdCardChunkMaxIndex = 0; - sdCardSize = 0; -} - -void sdCardExit(){ - if(sdCardData) - free(sdCardData); - if(sdCardOldData) - free(sdCardOldData); - sdCardData = NULL; - sdCardOldData = NULL; - sdCardChunks = NULL; - sdCardChunkIndex = 0; - sdCardChunkMaxIndex = 0; - sdCardSize = 0; -} - -uint32_t sdCardReconfigure(uint64_t size){ - if(sdCardData) - free(sdCardData); - if(sdCardOldData) - free(sdCardOldData); - if(sdCardChunks) - free(sdCardChunks); - - sdCardData = malloc(size); - if(!sdCardData) - return EMU_ERROR_OUT_OF_MEMORY; - - sdCardOldData = malloc(size); - if(!sdCardOldData) - return EMU_ERROR_OUT_OF_MEMORY; - - sdCardChunks = malloc(sizeof(uint64_t) * SD_CARD_CHUNK_VECTOR_SIZE); - if(!sdCardChunks) - return EMU_ERROR_OUT_OF_MEMORY; - - memset(sdCardData, 0x00, size); - memset(sdCardOldData, 0x00, size); - sdCardChunks[0] = 0x0000000000000000;//0 terminated array - - sdCardSize = size; - sdCardChunkIndex = 0; - - return EMU_ERROR_NONE; -} - -buffer_t sdCardGetImage(){ - buffer_t image; - - image.data = sdCardData; - image.size = sdCardSize; - - return image; -} - -uint32_t sdCardSetFromImage(buffer_t image){ - uint32_t error = sdCardReconfigure(image.size); - - if(error != EMU_ERROR_NONE) - return error; - - memcpy(sdCardData, image.data, image.size); - - return EMU_ERROR_NONE; -} - -void sdCardSaveState(uint64_t sessionId, uint64_t stateId){ - //make single BPS if SD card data has changed - if(memcmp(sdCardOldData, sdCardData, sdCardSize) != 0){ - struct mem source; - struct mem target; - struct mem metadata; - struct mem patch; - buffer_t chunk; - - source.ptr = sdCardOldData; - source.len = sdCardSize; - - target.ptr = sdCardData; - target.len = sdCardSize; - - metadata.ptr = NULL; - metadata.len = 0; - - bps_create_linear(source, target, metadata, &patch); - chunk.data = patch.ptr; - chunk.size = patch.len; - emulatorSetSdCardChunk(sessionId, stateId, chunk); - bps_free(patch); - - if(sdCardChunkIndex + 2 >= sdCardChunkMaxIndex){ - //resize vector if needed - sdCardChunks = realloc(sdCardChunks, sizeof(uint64_t) * (sdCardChunkMaxIndex + SD_CARD_CHUNK_VECTOR_SIZE)); - sdCardChunkMaxIndex += SD_CARD_CHUNK_VECTOR_SIZE; - } - sdCardChunks[sdCardChunkIndex] = stateId; - sdCardChunkIndex++; - sdCardChunks[sdCardChunkIndex] = 0x0000000000000000; - - emulatorSetSdCardStateChunkList(sessionId, stateId, sdCardChunks); - - memcpy(sdCardOldData, sdCardData, sdCardSize); - } -} - -void sdCardLoadState(uint64_t sessionId, uint64_t stateId){ - //rebuild SD card from BPS chain - free(sdCardChunks); - sdCardChunks = emulatorGetSdCardStateChunkList(sessionId, stateId); - updateChunkBufferLength(); - - memset(sdCardData, 0x00, sdCardSize); - for(uint64_t index = 0; index < sdCardChunkIndex; index++){ - struct mem patch; - struct mem input; - struct mem output; - buffer_t chunk = emulatorGetSdCardChunk(sessionId, sdCardChunks[index]); - - patch.ptr = chunk.data; - patch.len = chunk.size; - - input.ptr = sdCardData; - input.len = sdCardSize; - - output.ptr = sdCardData; - output.len = sdCardSize; - - - //bps_apply(patch, input, output, NULL, true);//bps_apply needs to be modified to patch the existing buffer instead of making a new one - } - - memcpy(sdCardOldData, sdCardData, sdCardSize); -} - bool sdCardExchangeBit(bool bit){ //not done return true;//eek diff --git a/src/sdcard.h b/src/sdcard.h index 84805b5..3f0ebb0 100644 --- a/src/sdcard.h +++ b/src/sdcard.h @@ -1,16 +1,5 @@ #pragma once -#include #include -#include "emulator.h" - -void sdCardInit(); -void sdCardExit(); -uint32_t sdCardReconfigure(uint64_t size); -buffer_t sdCardGetImage(); -uint32_t sdCardSetFromImage(buffer_t image); -void sdCardSaveState(uint64_t sessionId, uint64_t stateId); -void sdCardLoadState(uint64_t sessionId, uint64_t stateId); - bool sdCardExchangeBit(bool bit);