From d46e146ae7bc26cd85631c32f8f74405f8cbface Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Sun, 26 May 2019 20:08:45 -0700 Subject: [PATCH 1/5] Prevent invalid paths and get custom state dirs working --- qtBuildSystem/Mu/emuwrapper.cpp | 2 +- qtBuildSystem/Mu/statemanager.cpp | 6 ++++++ qtBuildSystem/Mu/statemanager.h | 2 ++ roadmap.txt | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/qtBuildSystem/Mu/emuwrapper.cpp b/qtBuildSystem/Mu/emuwrapper.cpp index c84fd1b..6580347 100644 --- a/qtBuildSystem/Mu/emuwrapper.cpp +++ b/qtBuildSystem/Mu/emuwrapper.cpp @@ -352,7 +352,7 @@ uint32_t EmuWrapper::bootFromFileOrDirectory(const QString& mainPath){ emuSaveStatePath = mainPath + "." + emuOsName + ".states"; //make the place to store the saves - QDir(mainPath + ".states").mkdir("."); + QDir(mainPath + "." + emuOsName + ".states").mkdir("."); //need this goto because the emulator must be released before returning errorOccurred: diff --git a/qtBuildSystem/Mu/statemanager.cpp b/qtBuildSystem/Mu/statemanager.cpp index e445a37..b023b5c 100644 --- a/qtBuildSystem/Mu/statemanager.cpp +++ b/qtBuildSystem/Mu/statemanager.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include "mainwindow.h" @@ -24,10 +26,14 @@ StateManager::StateManager(QWidget* parent) : ui->statePreview->installEventFilter(this); ui->statePreview->setObjectName("statePreview"); + noBadPaths = new QRegExpValidator(QRegExp("[a-z0-9_()-\\s]*")); + ui->newStateName->setValidator(noBadPaths); + updateStateList(); } StateManager::~StateManager(){ + delete noBadPaths; delete ui; } diff --git a/qtBuildSystem/Mu/statemanager.h b/qtBuildSystem/Mu/statemanager.h index a28f76e..59e2edd 100644 --- a/qtBuildSystem/Mu/statemanager.h +++ b/qtBuildSystem/Mu/statemanager.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "emuwrapper.h" @@ -35,4 +36,5 @@ private slots: private: Ui::StateManager* ui; EmuWrapper* emu; + QRegExpValidator* noBadPaths; }; diff --git a/roadmap.txt b/roadmap.txt index 6aaa4bb..38edfe4 100644 --- a/roadmap.txt +++ b/roadmap.txt @@ -25,6 +25,7 @@ RetroArch GUI: *add multithreading and pipeline speedups Qt GUI: +/TODO: fix state manager not loading until a state is saved //TODO: get circleci builds for QT port on Win/Mac/Linux //TODO: allow reiniting the emu without closing the program *boot button uses install button icon now, changed install button to icon a "+" From 892359f226e3ce2e26eb96d46648340b40cf7b81 Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Sun, 26 May 2019 22:14:06 -0700 Subject: [PATCH 2/5] Fix state manager not loading state list when opened --- qtBuildSystem/Mu/mainwindow.cpp | 7 ------- qtBuildSystem/Mu/statemanager.cpp | 11 +++++------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/qtBuildSystem/Mu/mainwindow.cpp b/qtBuildSystem/Mu/mainwindow.cpp index bbf1a8f..afab1be 100644 --- a/qtBuildSystem/Mu/mainwindow.cpp +++ b/qtBuildSystem/Mu/mainwindow.cpp @@ -260,10 +260,6 @@ void MainWindow::updateDisplay(){ //allow next frame to start emu.frameHandled(); - - //update GUI - ui->display->repaint(); - ui->powerButtonLed->repaint(); } } @@ -393,8 +389,6 @@ void MainWindow::on_ctrlBtn_clicked(){ emu.resume(); ui->ctrlBtn->setIcon(QIcon(":/buttons/images/pause.svg")); } - - ui->ctrlBtn->repaint(); } void MainWindow::on_install_clicked(){ @@ -425,7 +419,6 @@ void MainWindow::on_debugger_clicked(){ if(emu.isInited()){ emu.pause(); ui->ctrlBtn->setIcon(QIcon(":/buttons/images/play.svg")); - ui->ctrlBtn->repaint(); emuDebugger->exec(); } } diff --git a/qtBuildSystem/Mu/statemanager.cpp b/qtBuildSystem/Mu/statemanager.cpp index b023b5c..948cd4e 100644 --- a/qtBuildSystem/Mu/statemanager.cpp +++ b/qtBuildSystem/Mu/statemanager.cpp @@ -23,13 +23,12 @@ StateManager::StateManager(QWidget* parent) : ui->setupUi(this); //this allows resizing the screenshot of the savestate + this->installEventFilter(this); ui->statePreview->installEventFilter(this); ui->statePreview->setObjectName("statePreview"); noBadPaths = new QRegExpValidator(QRegExp("[a-z0-9_()-\\s]*")); ui->newStateName->setValidator(noBadPaths); - - updateStateList(); } StateManager::~StateManager(){ @@ -38,6 +37,10 @@ StateManager::~StateManager(){ } bool StateManager::eventFilter(QObject* object, QEvent* event){ + if(object->objectName() == "StateManager" && event->type() == QEvent::WindowActivate){ + updateStateList(); + ui->states->setCurrentRow(0); + } if(object->objectName() == "statePreview" && event->type() == QEvent::Resize) updateStatePreview(); @@ -73,8 +76,6 @@ void StateManager::updateStatePreview(){ //remove outdated image ui->statePreview->clear(); } - - ui->statePreview->update(); } int StateManager::getStateIndexRowByName(const QString& name){ @@ -121,6 +122,4 @@ void StateManager::on_deleteState_clicked(){ void StateManager::on_states_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous){ updateStatePreview(); - ui->states->repaint(); - ui->statePreview->repaint(); } From 8e9ef22f42baa27a0003bde782e9109db9391305 Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Sun, 26 May 2019 22:58:51 -0700 Subject: [PATCH 3/5] Fix another state path issue Also disabled keyboard focus so mapping keys like space and enter dont do anything weird. --- qtBuildSystem/Mu/emuwrapper.cpp | 4 +- qtBuildSystem/Mu/mainwindow.ui | 57 +++++++++++++++++ qtBuildSystem/Mu/settingsmanager.ui | 99 +++++++++++++++++++++++++++++ roadmap.txt | 2 +- 4 files changed, 159 insertions(+), 3 deletions(-) diff --git a/qtBuildSystem/Mu/emuwrapper.cpp b/qtBuildSystem/Mu/emuwrapper.cpp index 6580347..82017e4 100644 --- a/qtBuildSystem/Mu/emuwrapper.cpp +++ b/qtBuildSystem/Mu/emuwrapper.cpp @@ -179,7 +179,7 @@ uint32_t EmuWrapper::init(const QString& assetPath, bool useOs5, uint32_t featur emuSaveStatePath = assetPath + "/states-" + model + ".states"; //make the place to store the saves - QDir(assetPath + "states-" + model + ".states").mkdir("."); + QDir(emuSaveStatePath).mkdir("."); //skip the boot screen if(fastBoot) @@ -352,7 +352,7 @@ uint32_t EmuWrapper::bootFromFileOrDirectory(const QString& mainPath){ emuSaveStatePath = mainPath + "." + emuOsName + ".states"; //make the place to store the saves - QDir(mainPath + "." + emuOsName + ".states").mkdir("."); + QDir(emuSaveStatePath).mkdir("."); //need this goto because the emulator must be released before returning errorOccurred: diff --git a/qtBuildSystem/Mu/mainwindow.ui b/qtBuildSystem/Mu/mainwindow.ui index fcbed94..c3f0620 100644 --- a/qtBuildSystem/Mu/mainwindow.ui +++ b/qtBuildSystem/Mu/mainwindow.ui @@ -105,6 +105,9 @@ 0 + + Qt::NoFocus + :/buttons/images/calendar.svg:/buttons/images/calendar.svg @@ -119,6 +122,9 @@ 0 + + Qt::NoFocus + Run/Pause @@ -142,6 +148,9 @@ 0 + + Qt::NoFocus + Reset @@ -162,6 +171,9 @@ 0 + + Qt::NoFocus + Save/Load State @@ -179,6 +191,9 @@ 0 + + Qt::NoFocus + Settings @@ -199,6 +214,9 @@ 0 + + Qt::NoFocus + :/buttons/images/power.svg:/buttons/images/power.svg @@ -216,6 +234,9 @@ 0 + + Qt::NoFocus + Boot App @@ -236,6 +257,9 @@ 0 + + Qt::NoFocus + Install App @@ -256,6 +280,9 @@ 0 + + Qt::NoFocus + Snapshot @@ -267,6 +294,9 @@ + + Qt::NoFocus + This is an LED not a button.😜 @@ -292,6 +322,9 @@ 0 + + Qt::NoFocus + :/buttons/images/addressBook.svg:/buttons/images/addressBook.svg @@ -309,6 +342,9 @@ 0 + + Qt::NoFocus + @@ -329,6 +365,9 @@ 0 + + Qt::NoFocus + :/buttons/images/up.svg:/buttons/images/up.svg @@ -346,6 +385,9 @@ 0 + + Qt::NoFocus + @@ -366,6 +408,9 @@ 0 + + Qt::NoFocus + :/buttons/images/down.svg:/buttons/images/down.svg @@ -383,6 +428,9 @@ 0 + + Qt::NoFocus + @@ -415,6 +463,9 @@ 0 + + Qt::NoFocus + :/buttons/images/todo.svg:/buttons/images/todo.svg @@ -432,6 +483,9 @@ 0 + + Qt::NoFocus + :/buttons/images/notes.svg:/buttons/images/notes.svg @@ -449,6 +503,9 @@ 0 + + Qt::NoFocus + Debugger diff --git a/qtBuildSystem/Mu/settingsmanager.ui b/qtBuildSystem/Mu/settingsmanager.ui index 7371bdc..b4c18ec 100644 --- a/qtBuildSystem/Mu/settingsmanager.ui +++ b/qtBuildSystem/Mu/settingsmanager.ui @@ -37,6 +37,9 @@ + + Qt::NoFocus + true @@ -44,13 +47,22 @@ + + Qt::NoFocus + Pick Home Directory + + false + + + Qt::NoFocus + Show Onscreen Keys @@ -58,6 +70,9 @@ + + Qt::NoFocus + Set Palm Button Map: @@ -80,6 +95,9 @@ 0 + + Qt::NoFocus + MAXSIZE @@ -87,6 +105,9 @@ :/buttons/images/notes.svg:/buttons/images/notes.svg + + false + @@ -97,6 +118,9 @@ 0 + + Qt::NoFocus + MAXSIZE @@ -104,10 +128,16 @@ :/buttons/images/calendar.svg:/buttons/images/calendar.svg + + false + + + Qt::NoFocus + MAXSIZE @@ -115,6 +145,9 @@ :/buttons/images/down.svg:/buttons/images/down.svg + + false + @@ -125,6 +158,9 @@ 0 + + Qt::NoFocus + MAXSIZE @@ -132,6 +168,9 @@ :/buttons/images/todo.svg:/buttons/images/todo.svg + + false + @@ -142,6 +181,9 @@ 0 + + Qt::NoFocus + MAXSIZE @@ -149,10 +191,16 @@ :/buttons/images/power.svg:/buttons/images/power.svg + + false + + + Qt::NoFocus + MAXSIZE @@ -160,6 +208,9 @@ :/buttons/images/up.svg:/buttons/images/up.svg + + false + @@ -170,6 +221,9 @@ 0 + + Qt::NoFocus + MAXSIZE @@ -177,10 +231,16 @@ :/buttons/images/addressBook.svg:/buttons/images/addressBook.svg + + false + + + Qt::NoFocus + MAXSIZE @@ -188,10 +248,16 @@ :/buttons/images/center.svg:/buttons/images/center.svg + + false + + + Qt::NoFocus + MAXSIZE @@ -199,10 +265,16 @@ :/buttons/images/left.svg:/buttons/images/left.svg + + false + + + Qt::NoFocus + MAXSIZE @@ -210,6 +282,9 @@ :/buttons/images/right.svg:/buttons/images/right.svg + + false + @@ -224,13 +299,22 @@ + + Qt::NoFocus + Clear Key Bind + + false + + + Qt::NoFocus + Use OS 5 @@ -238,6 +322,9 @@ + + Qt::NoFocus + Fast Boot(Fastforwards Through The Boot Screen) @@ -245,6 +332,9 @@ + + Qt::NoFocus + Set Emulator Features(Restart Required): @@ -255,6 +345,9 @@ + + Qt::NoFocus + Overclocking @@ -262,6 +355,9 @@ + + Qt::NoFocus + HLE APIs(Speed Hack) @@ -276,6 +372,9 @@ + + Qt::NoFocus + Sync Real Time Clock diff --git a/roadmap.txt b/roadmap.txt index 38edfe4..8288fb2 100644 --- a/roadmap.txt +++ b/roadmap.txt @@ -25,9 +25,9 @@ RetroArch GUI: *add multithreading and pipeline speedups Qt GUI: -/TODO: fix state manager not loading until a state is saved //TODO: get circleci builds for QT port on Win/Mac/Linux //TODO: allow reiniting the emu without closing the program +*fixed state manager not loading until a state is saved *boot button uses install button icon now, changed install button to icon a "+" *put back left/right/center keys *added install and boot buttons to both modes, content loaded with the boot button has separate save paths just like cartridge systems From 5c1547467bc164ecd4039d3a752ff0ef4fc679ee Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Mon, 27 May 2019 15:20:42 -0700 Subject: [PATCH 4/5] Completley redo how launcher works RetroArch still works. Also tested .img file with a separate .info file in RetroArch and it worked. --- libretroBuildSystem/libretro.c | 198 +++++++++++----------- qtBuildSystem/Mu/emuwrapper.cpp | 143 +++++++--------- qtBuildSystem/Mu/emuwrapper.h | 2 +- qtBuildSystem/Mu/mainwindow.cpp | 2 +- roadmap.txt | 1 + src/fileLauncher/launcher.c | 285 +++++++++++--------------------- src/fileLauncher/launcher.h | 47 +----- 7 files changed, 266 insertions(+), 412 deletions(-) diff --git a/libretroBuildSystem/libretro.c b/libretroBuildSystem/libretro.c index 2571142..08f21b8 100644 --- a/libretroBuildSystem/libretro.c +++ b/libretroBuildSystem/libretro.c @@ -43,6 +43,7 @@ static float touchCursorX; static float touchCursorY; static char contentPath[PATH_MAX_LENGTH]; static uint16_t mouseCursorOldArea[32 * 32]; +static bool runningImgFile; static void renderMouseCursor(int16_t screenX, int16_t screenY){ @@ -377,6 +378,7 @@ bool retro_load_game(const struct retro_game_info *info){ const char* systemDir; time_t rawTime; struct tm* timeInfo; + bool hasSram = false; uint32_t error; //updates the emulator configuration @@ -387,11 +389,13 @@ bool retro_load_game(const struct retro_game_info *info){ if(info && !string_is_empty(info->path)){ //boot application strlcpy(contentPath, info->path, PATH_MAX_LENGTH); + runningImgFile = string_is_equal_case_insensitive(contentPath + strlen(contentPath) - 4, ".img"); } else{ //boot standard device image, "os5" or "os4" gets appended below strlcpy(contentPath, systemDir, PATH_MAX_LENGTH); strlcat(contentPath, "/default", PATH_MAX_LENGTH); + runningImgFile = false; } //ROM @@ -445,70 +449,6 @@ bool retro_load_game(const struct retro_game_info *info){ if(error != EMU_ERROR_NONE) return false; - //see if RetroArch wants something launched - if(info && !string_is_empty(info->path)){ - launcher_file_t file; - struct RFILE* contentFile; - - contentFile = filestream_open(contentPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(contentFile){ - file.fileSize = filestream_get_size(contentFile); - file.fileData = malloc(file.fileSize); - - if(file.fileData) - filestream_read(contentFile, file.fileData, file.fileSize); - else - return false; - filestream_close(contentFile); - } - else{ - //no content at path, fail time - return false; - } - - if(string_is_equal_case_insensitive(contentPath + strlen(contentPath) - 4, ".img")){ - char infoPath[PATH_MAX_LENGTH]; - struct RFILE* infoFile; - - file.type = LAUNCHER_FILE_TYPE_IMG; - - //TODO: need to load info file here - strlcpy(infoPath, contentPath, PATH_MAX_LENGTH); - infoPath[strlen(infoPath) - 4] = '\0';//chop off ".img" - strlcat(infoPath, ".info", PATH_MAX_LENGTH); - infoFile = filestream_open(infoPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(infoFile){ - file.infoSize = filestream_get_size(infoFile); - file.infoData = malloc(file.infoSize); - - if(file.infoData) - filestream_read(infoFile, file.infoData, file.infoSize); - else - file.infoSize = 0; - filestream_close(romFile); - } - else{ - //no info file - file.infoData = NULL; - file.infoSize = 0; - } - } - else{ - file.type = LAUNCHER_FILE_TYPE_RESOURCE_FILE; - file.infoData = NULL; - file.infoSize = 0; - } - - //the SRAM and SD card are loaded after, so just pass NULL for now - error = launcherLaunch(&file, 1, NULL, 0, NULL, 0); - if(error != EMU_ERROR_NONE) - return false; - - free(file.fileData); - if(file.infoData) - free(file.infoData); - } - //save RAM strlcpy(saveRamPath, contentPath, PATH_MAX_LENGTH); #if defined(EMU_SUPPORT_PALM_OS5) @@ -520,6 +460,7 @@ bool retro_load_game(const struct retro_game_info *info){ strlcat(saveRamPath, ".ram", PATH_MAX_LENGTH); saveRamFile = filestream_open(saveRamPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); if(saveRamFile){ + hasSram = true; if(filestream_get_size(saveRamFile) == emulatorGetRamSize()){ filestream_read(saveRamFile, palmRam, emulatorGetRamSize()); swap16BufferIfLittle(palmRam, emulatorGetRamSize() / sizeof(uint16_t)); @@ -527,26 +468,28 @@ bool retro_load_game(const struct retro_game_info *info){ filestream_close(saveRamFile); } - //SD card - strlcpy(sdImgPath, contentPath, PATH_MAX_LENGTH); + if(!runningImgFile){ + //SD card + strlcpy(sdImgPath, contentPath, PATH_MAX_LENGTH); #if defined(EMU_SUPPORT_PALM_OS5) - if(useOs5) - strlcat(sdImgPath, ".os5", PATH_MAX_LENGTH); - else + if(useOs5) + strlcat(sdImgPath, ".os5", PATH_MAX_LENGTH); + else #endif - strlcat(sdImgPath, ".os4", PATH_MAX_LENGTH); - strlcat(sdImgPath, ".sd.img", PATH_MAX_LENGTH); - sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(sdImgFile){ - uint32_t sdImgSize = filestream_get_size(sdImgFile); - - //use the NULL, size, NULL method because it takes less RAM - - error = emulatorInsertSdCard(NULL, sdImgSize, NULL); - if(error == EMU_ERROR_NONE) - filestream_read(sdImgFile, palmSdCard.flashChipData, sdImgSize); - - filestream_close(sdImgFile); + strlcat(sdImgPath, ".os4", PATH_MAX_LENGTH); + strlcat(sdImgPath, ".sd.img", PATH_MAX_LENGTH); + sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); + if(sdImgFile){ + uint32_t sdImgSize = filestream_get_size(sdImgFile); + + //use the NULL, size, NULL method because it takes less RAM + + error = emulatorInsertSdCard(NULL, sdImgSize, NULL); + if(error == EMU_ERROR_NONE) + filestream_read(sdImgFile, palmSdCard.flashChipData, sdImgSize); + + filestream_close(sdImgFile); + } } //set RTC @@ -554,6 +497,71 @@ bool retro_load_game(const struct retro_game_info *info){ timeInfo = localtime(&rawTime); emulatorSetRtc(timeInfo->tm_yday, timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec); + //see if RetroArch wants something launched + if(info && !string_is_empty(info->path)){ + struct RFILE* contentFile; + uint8_t* contentData; + uint32_t contentSize; + + contentFile = filestream_open(contentPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); + if(contentFile){ + contentSize = filestream_get_size(contentFile); + contentData = malloc(contentSize); + + if(contentData) + filestream_read(contentFile, contentData, contentSize); + else + return false; + filestream_close(contentFile); + } + else{ + //no content at path, fail time + return false; + } + + launcherBootInstantly(hasSram); + + if(runningImgFile){ + char infoPath[PATH_MAX_LENGTH]; + struct RFILE* infoFile; + uint8_t* infoData = NULL; + uint32_t infoSize; + sd_card_info_t sdInfo; + + memset(&sdInfo, 0x00, sizeof(sdInfo)); + + strlcpy(infoPath, contentPath, PATH_MAX_LENGTH); + infoPath[strlen(infoPath) - 4] = '\0';//chop off ".img" + strlcat(infoPath, ".info", PATH_MAX_LENGTH); + infoFile = filestream_open(infoPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); + if(infoFile){ + infoSize = filestream_get_size(infoFile); + infoData = malloc(infoSize); + + if(infoData) + filestream_read(infoFile, infoData, infoSize); + + filestream_close(infoFile); + } + + if(infoData) + launcherGetSdCardInfoFromInfoFile(infoData, infoSize, &sdInfo); + error = emulatorInsertSdCard(contentData, contentSize, infoData ? &sdInfo : NULL); + if(infoData) + free(infoData); + } + else{ + if(!hasSram) + error = launcherInstallFile(contentData, contentSize); + if(error == EMU_ERROR_NONE) + error = launcherExecute(launcherGetAppId(contentData, contentSize)); + } + + free(contentData); + if(error != EMU_ERROR_NONE) + return false; + } + //set mouse position touchCursorX = palmFramebufferWidth / 2; touchCursorY = palmFramebufferHeight / 2; @@ -587,20 +595,22 @@ void retro_unload_game(void){ filestream_close(saveRamFile); } - //SD card - if(palmSdCard.flashChipData){ - strlcpy(sdImgPath, contentPath, PATH_MAX_LENGTH); + if(!runningImgFile){ + //SD card + if(palmSdCard.flashChipData){ + strlcpy(sdImgPath, contentPath, PATH_MAX_LENGTH); #if defined(EMU_SUPPORT_PALM_OS5) - if(useOs5) - strlcat(sdImgPath, ".os5", PATH_MAX_LENGTH); - else + if(useOs5) + strlcat(sdImgPath, ".os5", PATH_MAX_LENGTH); + else #endif - strlcat(sdImgPath, ".os4", PATH_MAX_LENGTH); - strlcat(sdImgPath, ".sd.img", PATH_MAX_LENGTH); - sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(sdImgFile){ - filestream_write(sdImgFile, palmSdCard.flashChipData, palmSdCard.flashChipSize); - filestream_close(sdImgFile); + strlcat(sdImgPath, ".os4", PATH_MAX_LENGTH); + strlcat(sdImgPath, ".sd.img", PATH_MAX_LENGTH); + sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE); + if(sdImgFile){ + filestream_write(sdImgFile, palmSdCard.flashChipData, palmSdCard.flashChipSize); + filestream_close(sdImgFile); + } } } diff --git a/qtBuildSystem/Mu/emuwrapper.cpp b/qtBuildSystem/Mu/emuwrapper.cpp index 82017e4..5bfb564 100644 --- a/qtBuildSystem/Mu/emuwrapper.cpp +++ b/qtBuildSystem/Mu/emuwrapper.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "emuwrapper.h" #include "../../src/emulator.h" @@ -248,97 +249,36 @@ void EmuWrapper::reset(bool hard){ } } -uint32_t EmuWrapper::bootFromFileOrDirectory(const QString& mainPath){ +uint32_t EmuWrapper::bootFromFile(const QString& mainPath){ bool wasPaused = isPaused(); uint32_t error = EMU_ERROR_NONE; QFileInfo pathInfo(mainPath); - QStringList paths; - QVector fileDataBuffers; - QVector fileInfoBuffers; - launcher_file_t* files; + QFile appFile(mainPath); QFile ramFile(mainPath + "." + emuOsName + ".ram"); QFile sdCardFile(mainPath + "." + emuOsName + ".sd.img"); + QString suffix = QFileInfo(mainPath).suffix().toLower(); + uint32_t appId; bool hasSaveRam; bool hasSaveSdCard; if(!wasPaused) pause(); - if(pathInfo.isDir()){ - //get Palm file list - QDir dirInfo(mainPath); - QStringList filters; - - filters += "*.prc"; - filters += "*.pdb"; - filters += "*.pqa"; - filters += "*.img"; - - paths = dirInfo.entryList(filters); - - //make paths full direct paths - for(int index = 0; index < paths.length(); index++) - paths[index].prepend(mainPath + "/"); - } - else if(pathInfo.exists()){ - //use single file - paths = QStringList(mainPath); - } - else{ - //error - error = EMU_ERROR_INVALID_PARAMETER; - goto errorOccurred; - } - - fileDataBuffers.resize(paths.length()); - fileInfoBuffers.resize(paths.length()); - files = new launcher_file_t[paths.length()]; - - memset(files, 0x00, sizeof(launcher_file_t) * paths.length()); - - for(int index = 0; index < paths.length(); index++){ - QFile appFile(paths[index]); - - if(appFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ - QString suffix = QFileInfo(paths[index]).suffix().toLower(); - - fileDataBuffers[index] = appFile.readAll(); - appFile.close(); - - files[index].fileData = (uint8_t*)fileDataBuffers[index].data(); - files[index].fileSize = fileDataBuffers[index].size(); - - if(suffix == "img"){ - QFile infoFile(paths[index].remove(paths[index].size() - 3, 3) + "info");//swap "img" for "info" - - if(infoFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ - fileInfoBuffers[index] = infoFile.readAll(); - files[index].infoData = (uint8_t*)fileInfoBuffers[index].data(); - files[index].infoSize = fileInfoBuffers[index].size(); - infoFile.close(); - } - files[index].type = LAUNCHER_FILE_TYPE_IMG; - } - else{ - files[index].type = LAUNCHER_FILE_TYPE_RESOURCE_FILE; - } - } - else{ - error = EMU_ERROR_RESOURCE_LOCKED; - goto errorOccurred; - } - } - //save the current data for the last program launched, or the standard device image if none where launched writeOutSaves(); //its OK if these fail, the buffer will just be NULL, 0 if they do hasSaveRam = ramFile.open(QFile::ReadOnly | QFile::ExistingOnly); - hasSaveSdCard = sdCardFile.open(QFile::ReadOnly | QFile::ExistingOnly); + hasSaveSdCard = suffix != "img" ? sdCardFile.open(QFile::ReadOnly | QFile::ExistingOnly) : false; - error = launcherLaunch(files, paths.length(), hasSaveRam ? (uint8_t*)ramFile.readAll().data() : NULL, hasSaveRam ? ramFile.size() : 0, hasSaveSdCard ? (uint8_t*)sdCardFile.readAll().data() : NULL, hasSaveSdCard ? sdCardFile.size() : 0); - if(error != EMU_ERROR_NONE) - goto errorOccurred; + //fully clear the emu + emulatorEjectSdCard(); + emulatorHardReset(); + + if(hasSaveRam) + emulatorLoadRam((uint8_t*)ramFile.readAll().data(), ramFile.size()); + if(hasSaveSdCard) + emulatorInsertSdCard((uint8_t*)sdCardFile.readAll().data(), sdCardFile.size(), NULL); //its OK if these fail if(hasSaveRam) @@ -346,6 +286,45 @@ uint32_t EmuWrapper::bootFromFileOrDirectory(const QString& mainPath){ if(hasSaveSdCard) sdCardFile.close(); + launcherBootInstantly(hasSaveRam); + + if(appFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ + QByteArray fileBuffer = appFile.readAll(); + + appFile.close(); + + if(suffix == "img"){ + QFile infoFile(mainPath.mid(0, mainPath.length() - 3) + "info");//swap "img" for "info" + sd_card_info_t sdInfo; + + memset(&sdInfo, 0x00, sizeof(sdInfo)); + + if(infoFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ + launcherGetSdCardInfoFromInfoFile((uint8_t*)infoFile.readAll().data(), infoFile.size(), &sdInfo); + infoFile.close(); + } + + error = emulatorInsertSdCard((uint8_t*)fileBuffer.data(), fileBuffer.size(), &sdInfo); + if(error != EMU_ERROR_NONE) + goto errorOccurred; + } + else{ + if(!hasSaveRam){ + error = launcherInstallFile((uint8_t*)fileBuffer.data(), fileBuffer.size()); + if(error != EMU_ERROR_NONE) + goto errorOccurred; + } + appId = launcherGetAppId((uint8_t*)fileBuffer.data(), fileBuffer.size()); + } + } + + //img files just boot to the homescreen + if(suffix != "img"){ + error = launcherExecute(appId); + if(error != EMU_ERROR_NONE) + goto errorOccurred; + } + //everything worked, set output save files emuRamFilePath = mainPath + "." + emuOsName + ".ram"; emuSdCardFilePath = mainPath + "." + emuOsName + ".sd.img"; @@ -356,6 +335,11 @@ uint32_t EmuWrapper::bootFromFileOrDirectory(const QString& mainPath){ //need this goto because the emulator must be released before returning errorOccurred: + if(error != EMU_ERROR_NONE){ + //try and recover from error + emulatorEjectSdCard(); + emulatorHardReset(); + } if(!wasPaused) resume(); @@ -372,17 +356,8 @@ uint32_t EmuWrapper::installApplication(const QString& path){ pause(); if(appFile.open(QFile::ReadOnly | QFile::ExistingOnly)){ - QByteArray appDataBuffer = appFile.readAll(); - QString suffix = QFileInfo(appFile).suffix().toLower(); - launcher_file_t launcherFile; - + error = launcherInstallFile((uint8_t*)appFile.readAll().data(), appFile.size()); appFile.close(); - - launcherFile.type = LAUNCHER_FILE_TYPE_RESOURCE_FILE; - launcherFile.fileData = (uint8_t*)appDataBuffer.data(); - launcherFile.fileSize = appDataBuffer.size(); - - error = launcherInstallFiles(&launcherFile, 1); } if(!wasPaused) diff --git a/qtBuildSystem/Mu/emuwrapper.h b/qtBuildSystem/Mu/emuwrapper.h index a322575..0ee98d7 100644 --- a/qtBuildSystem/Mu/emuwrapper.h +++ b/qtBuildSystem/Mu/emuwrapper.h @@ -54,7 +54,7 @@ public: void pause(); void resume(); void reset(bool hard); - uint32_t bootFromFileOrDirectory(const QString& mainPath); + uint32_t bootFromFile(const QString& mainPath); uint32_t installApplication(const QString& path); const QString& getStatePath() const{return emuSaveStatePath;}//needed for looking up state pictures in the GUI uint32_t saveState(const QString& name); diff --git a/qtBuildSystem/Mu/mainwindow.cpp b/qtBuildSystem/Mu/mainwindow.cpp index afab1be..8cca3fe 100644 --- a/qtBuildSystem/Mu/mainwindow.cpp +++ b/qtBuildSystem/Mu/mainwindow.cpp @@ -483,7 +483,7 @@ void MainWindow::on_bootApp_clicked(){ app = QFileDialog::getOpenFileName(this, "Select File", QDir::root().path(), "Palm OS File (*.prc *.pqa *.img)"); if(app != ""){ - uint32_t error = emu.bootFromFileOrDirectory(app); + uint32_t error = emu.bootFromFile(app); if(error == EMU_ERROR_NONE) loadedNewApp = true; diff --git a/roadmap.txt b/roadmap.txt index 8288fb2..cb93b85 100644 --- a/roadmap.txt +++ b/roadmap.txt @@ -21,6 +21,7 @@ RetroArch GUI: *now launches content like cartridge based systems //TODO: allow adding more content after boot //TODO: get EMU_MANAGE_HOST_CPU_PIPELINE working on other platforms then the main 4 +//TODO: when compiling with "make platform=windows_x86_64" the dll wont load, may have to do with a missing library(maybe libc++) *booting without game works again *add multithreading and pipeline speedups diff --git a/src/fileLauncher/launcher.c b/src/fileLauncher/launcher.c index 90831fc..cc1a445 100644 --- a/src/fileLauncher/launcher.c +++ b/src/fileLauncher/launcher.c @@ -154,7 +154,7 @@ static uint32_t launcherM515CallGuestFunction(uint32_t address, uint16_t trap, c return functionReturn; } -static uint32_t launcherInstallAppM515(launcher_file_t* file){ +static uint32_t launcherInstallAppM515(uint8_t* data, uint32_t size){ /* #define memNewChunkFlagNonMovable 0x0200 #define memNewChunkFlagAllowLarge 0x1000 // this is not in the sdk *g* @@ -167,7 +167,7 @@ static uint32_t launcherInstallAppM515(launcher_file_t* file){ //try and get guest memory buffer memChunkNewArgs[0] = 1/*heapID, storage RAM*/; - memChunkNewArgs[1] = file->fileSize; + memChunkNewArgs[1] = size; memChunkNewArgs[2] = 0x1200/*attr, seems to work without memOwnerID*/; palmSideResourceData = launcherM515CallGuestFunction(0x00000000, MemChunkNew, "p(wlw)", memChunkNewArgs); @@ -176,8 +176,8 @@ static uint32_t launcherInstallAppM515(launcher_file_t* file){ return false; dbvzChipSelects[DBVZ_CHIP_DX_RAM].readOnlyForProtectedMemory = false;//need to unprotect storage RAM - MULTITHREAD_LOOP(count) for(count = 0; count < file->fileSize; count++) - m68k_write_memory_8(palmSideResourceData + count, file->fileData[count]); + MULTITHREAD_LOOP(count) for(count = 0; count < size; count++) + m68k_write_memory_8(palmSideResourceData + count, data[count]); dbvzChipSelects[DBVZ_CHIP_DX_RAM].readOnlyForProtectedMemory = storageRamReadOnly;//restore old protection state error = launcherM515CallGuestFunction(0x00000000, DmCreateDatabaseFromImage, "w(p)", &palmSideResourceData);//Err DmCreateDatabaseFromImage(MemPtr bufferP);//this looks best launcherM515CallGuestFunction(0x00000000, MemChunkFree, "w(p)", &palmSideResourceData); @@ -190,7 +190,7 @@ static uint32_t launcherInstallAppM515(launcher_file_t* file){ } #if defined(EMU_SUPPORT_PALM_OS5) -static uint32_t launcherInstallAppTungstenT3(launcher_file_t* file){ +static uint32_t launcherInstallAppTungstenT3(uint8_t* data, uint32_t size){ //TODO return EMU_ERROR_NOT_IMPLEMENTED; } @@ -358,192 +358,6 @@ static void launcherPushHomeButtonTouchscreenTungstenT3(void){ } #endif -static void launcherGetSdCardInfoFromInfoFile(launcher_file_t* file, sd_card_info_t* returnValue){ - //parse a small binary file with the extra SD card data - uint32_t offset = 0; - - //clear everything - memset(returnValue, 0x00, sizeof(sd_card_info_t)); - - //csd - if(file->infoSize < offset + 16) - return; - memcpy(returnValue->csd, file->infoData + offset, 16); - offset += 16; - - //cid - if(file->infoSize < offset + 16) - return; - memcpy(returnValue->cid, file->infoData + offset, 16); - offset += 16; - - //scr - if(file->infoSize < offset + 8) - return; - memcpy(returnValue->scr, file->infoData + offset, 8); - offset += 8; - - //ocr - if(file->infoSize < offset + sizeof(uint32_t)) - return; - returnValue->ocr = readStateValue32(file->infoData + offset); - offset += sizeof(uint32_t); - - //writeProtectSwitch - if(file->infoSize < offset + sizeof(uint8_t)) - return; - returnValue->writeProtectSwitch = readStateValue8(file->infoData + offset); - offset += sizeof(uint8_t); - - //this can keep growing with new values but all the current values are fixed!! -} - -uint32_t launcherLaunch(launcher_file_t* files, uint32_t fileCount, uint8_t* sramData, uint32_t sramSize, uint8_t* sdCardData, uint32_t sdCardSize){ - bool cardImageHasBeenLoaded = false; - uint32_t cardImage; - uint32_t totalSize = 0; - uint32_t error; - uint32_t index; - bool hasBootResource = false; - uint32_t bootResource; - - for(index = 0; index < fileCount; index++){ - //cant load a 2 card images - if(cardImageHasBeenLoaded && files[index].type == LAUNCHER_FILE_TYPE_IMG) - return EMU_ERROR_INVALID_PARAMETER; - - if(files[index].type == LAUNCHER_FILE_TYPE_IMG){ - cardImageHasBeenLoaded = true; - cardImage = index; - } - else if(files[index].type == LAUNCHER_FILE_TYPE_RESOURCE_FILE){ - if(files[index].fileSize > 0x4D){ - //has full prc header - if(files[index].fileData[0x21] & 0x01){ - //is a prc - uint32_t type = readStateValue32(files[index].fileData + 0x3C); - uint32_t creator = readStateValue32(files[index].fileData + 0x40); - - if(type == 'appl'){ - //is an application - hasBootResource = true; - bootResource = creator; - } - } - } - } - - totalSize += files[index].fileSize; - } - - //in case the installed apps store anything on the SD card - launcherSaveSdCardImage = true; - - //in case the emulator is currently running with an SD card inserted - emulatorEjectSdCard(); - - //dont want a data leak, could cause glitches - emulatorHardReset(); - - //insert card if present - if(cardImageHasBeenLoaded){ - if(files[cardImage].infoData){ - //with info file - sd_card_info_t sdInfo; - - //get SD info from file - launcherGetSdCardInfoFromInfoFile(&files[cardImage], &sdInfo); - - //load card image - error = emulatorInsertSdCard(files[cardImage].fileData, files[cardImage].fileSize, &sdInfo); - if(error != EMU_ERROR_NONE) - return error; - - //dont save read only card images - if(sdInfo.writeProtectSwitch) - launcherSaveSdCardImage = false; - } - else{ - //without info file - error = emulatorInsertSdCard(files[0].fileData, files[0].fileSize, NULL); - if(error != EMU_ERROR_NONE) - return error; - } - } - else{ - if(sdCardData){ - //use existing SD card image - error = emulatorInsertSdCard(sdCardData, sdCardSize, NULL); - if(error != EMU_ERROR_NONE) - return error; - } - } - - //use the existing SRAM file if available - if(sramData){ - emulatorLoadRam(sramData, sramSize); - launcherBootInstantly(true); - - if(hasBootResource){ - //launch the app -#if defined(EMU_SUPPORT_PALM_OS5) - if(palmEmulatingTungstenT3) - error = launcherLaunchAppTungstenT3(bootResource); - else -#endif - error = launcherLaunchAppM515(bootResource); - if(error != EMU_ERROR_NONE) - return error; - } - } - else{ - launcherBootInstantly(false); - - //install all resource files - for(index = 0; index < fileCount; index++) - if(files[index].type == LAUNCHER_FILE_TYPE_RESOURCE_FILE) - launcherInstallFiles(&files[index], 1); - - if(hasBootResource){ - //launch the app -#if defined(EMU_SUPPORT_PALM_OS5) - if(palmEmulatingTungstenT3) - error = launcherLaunchAppTungstenT3(bootResource); - else -#endif - error = launcherLaunchAppM515(bootResource); - if(error != EMU_ERROR_NONE) - return error; - } - } - - return EMU_ERROR_NONE; -} - -uint32_t launcherInstallFiles(launcher_file_t* files, uint32_t fileCount){ - uint32_t index; - - for(index = 0; index < fileCount; index++){ - uint32_t error; - - //cant install img files - if(files[index].type != LAUNCHER_FILE_TYPE_RESOURCE_FILE) - return EMU_ERROR_INVALID_PARAMETER; - -#if defined(EMU_SUPPORT_PALM_OS5) - if(palmEmulatingTungstenT3) - error = launcherInstallAppTungstenT3(&files[index]); - else -#endif - error = launcherInstallAppM515(&files[index]); - - if(error != EMU_ERROR_NONE) - return error; - } - - return EMU_ERROR_NONE; -} - void launcherBootInstantly(bool hasSram){ uint32_t index; @@ -582,3 +396,92 @@ void launcherBootInstantly(bool hasSram){ emulatorSkipFrame(); } } + +uint32_t launcherInstallFile(uint8_t* data, uint32_t size){ +#if defined(EMU_SUPPORT_PALM_OS5) + if(palmEmulatingTungstenT3) + return launcherInstallAppTungstenT3(data, size); + else +#endif + return launcherInstallAppM515(data, size); +} + +bool launcherIsExecutable(uint8_t* data, uint32_t size){ + if(size > 0x4D){ + //has full prc header + if(data[0x21] & 0x01){ + //is a prc + uint32_t type = readStateValue32(data + 0x3C); + + if(type == 'appl') + return true; + } + } + + return false; +} + +uint32_t launcherGetAppId(uint8_t* data, uint32_t size){ + if(size > 0x4D){ + //has full prc header + if(data[0x21] & 0x01){ + //is a prc + uint32_t type = readStateValue32(data + 0x3C); + uint32_t creator = readStateValue32(data + 0x40); + + if(type == 'appl') + return creator; + } + } + + return 0x00000000; +} + +uint32_t launcherExecute(uint32_t appId){ +#if defined(EMU_SUPPORT_PALM_OS5) + if(palmEmulatingTungstenT3) + return launcherLaunchAppTungstenT3(appId); + else +#endif + return launcherLaunchAppM515(appId); +} + +void launcherGetSdCardInfoFromInfoFile(uint8_t* data, uint32_t size, sd_card_info_t* returnValue){ + //parse a small binary file with the extra SD card data + uint32_t offset = 0; + + //clear everything + memset(returnValue, 0x00, sizeof(sd_card_info_t)); + + //csd + if(size < offset + 16) + return; + memcpy(returnValue->csd, data + offset, 16); + offset += 16; + + //cid + if(size < offset + 16) + return; + memcpy(returnValue->cid, data + offset, 16); + offset += 16; + + //scr + if(size < offset + 8) + return; + memcpy(returnValue->scr, data + offset, 8); + offset += 8; + + //ocr + if(size < offset + sizeof(uint32_t)) + return; + returnValue->ocr = readStateValue32(data + offset); + offset += sizeof(uint32_t); + + //writeProtectSwitch + if(size < offset + sizeof(uint8_t)) + return; + returnValue->writeProtectSwitch = readStateValue8(data + offset); + offset += sizeof(uint8_t); + + //this can keep growing with new values but all the current values are fixed!! +} diff --git a/src/fileLauncher/launcher.h b/src/fileLauncher/launcher.h index 29d4b80..7998595 100644 --- a/src/fileLauncher/launcher.h +++ b/src/fileLauncher/launcher.h @@ -11,48 +11,13 @@ extern "C" { #include "../emulator.h" -enum{ - LAUNCHER_FILE_TYPE_NONE = 0, - LAUNCHER_FILE_TYPE_RESOURCE_FILE, - LAUNCHER_FILE_TYPE_IMG -}; +void launcherBootInstantly(bool hasSram);//fastforwards through the boot sequence +uint32_t launcherInstallFile(uint8_t* data, uint32_t size);//only call after the emu has booted, launcherBootInstantly() will ensure a full boot has completed otherwise this is up to the frontend to be safe +bool launcherIsExecutable(uint8_t* data, uint32_t size); +uint32_t launcherGetAppId(uint8_t* data, uint32_t size); +uint32_t launcherExecute(uint32_t appId);//must first be installed with launcherInstallFile -typedef struct{ - uint8_t type;//file type - uint8_t* fileData; - uint32_t fileSize; - uint8_t* infoData;//only used with LAUNCHER_FILE_TYPE_IMG right now - uint32_t infoSize; -}launcher_file_t; - -extern bool launcherSaveSdCardImage;//false if loading a read only SD card image - -/* -the launcher is called after emulatorInit when its enabled -the order is: -launcher_file_t* files[...]; -uint32_t fileCount; -uint8_t* saveData = NULL; -uint32_t saveSize = 0; -uint8_t* oldSdCardData = NULL; -uint32_t oldSdCardSize = 0; -uint32_t error; - -error = emulatorInit(romFileData, romFileSize, bootloaderFileData(if m515), bootloaderFileSize(if m515), features); -if(error) - return error; -error = launcherLaunch(files, fileCount, saveData, saveSize, oldSdCardData, oldSdCardSize);//this can fail installing apps -if(error) - return error; -//its now safe to call emulatorFrame for frames -*/ -//if first launch NULL should be passed for sramData and sdCardData -uint32_t launcherLaunch(launcher_file_t* files, uint32_t fileCount, uint8_t* sramData, uint32_t sramSize, uint8_t* sdCardData, uint32_t sdCardSize); - -//only call after the emu has booted, launcherLaunch() will ensure a full boot has completed otherwise this is up to the frontend to be safe -uint32_t launcherInstallFiles(launcher_file_t* files, uint32_t fileCount); - -void launcherBootInstantly(bool hasSram); +void launcherGetSdCardInfoFromInfoFile(uint8_t* data, uint32_t size, sd_card_info_t* returnValue); #ifdef __cplusplus } From d0ca2655bb19ef7b41e87de18e8634eade4d1323 Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Mon, 27 May 2019 15:41:04 -0700 Subject: [PATCH 5/5] Update roadmap.txt --- roadmap.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roadmap.txt b/roadmap.txt index cb93b85..87040fc 100644 --- a/roadmap.txt +++ b/roadmap.txt @@ -21,7 +21,7 @@ RetroArch GUI: *now launches content like cartridge based systems //TODO: allow adding more content after boot //TODO: get EMU_MANAGE_HOST_CPU_PIPELINE working on other platforms then the main 4 -//TODO: when compiling with "make platform=windows_x86_64" the dll wont load, may have to do with a missing library(maybe libc++) +//TODO: when compiling with "make platform=windows_x86_64" the dll wont load(theres a really good chance its because "libgomp-1.dll"(the OpenMP handler library) is missing from the RetroArch folder) *booting without game works again *add multithreading and pipeline speedups