diff --git a/bugs/unimplementedHardware.txt b/bugs/unimplementedHardware.txt index 1499fb8..265a608 100644 --- a/bugs/unimplementedHardware.txt +++ b/bugs/unimplementedHardware.txt @@ -1,6 +1,4 @@ CPU: -sysTrapPceNativeCall, ARM Emulator -VFP(floating point) coprocessor for ARM Test what bits of IMR are writable sandbox isnt notified about switches to Thumb mode function name finders for ARMv5 and Thumb are unimplemented @@ -58,8 +56,10 @@ Support for Silkyboard 2 silkscreen:https://archive.org/details/tucows_228076_SI Qt port dosent support Windows touchscreen input Qt GUI dosent resize properly with 320x320 framebuffer File Installer isnt working yet +Qt dosent have a hybrid file/folder selector so apps will always have to be launched from folders for now Fixed: +(CPU)VFP(floating point) coprocessor for ARM(dont think the ARM Palms even used VFP) (Other)need to get rid of buffer_t, its not used much anyway ARM dynarec SIGSEGVs on exit(pushing play in the debugger still lets it continue, dont think this is a bug) (Feature)need to add FEATURE_DURABLE which will ignore CPU errors, increasing stability at the cost of bugginess diff --git a/qtBuildSystem/Mu/debugviewer.cpp b/qtBuildSystem/Mu/debugviewer.cpp index 342c1e4..303aa33 100644 --- a/qtBuildSystem/Mu/debugviewer.cpp +++ b/qtBuildSystem/Mu/debugviewer.cpp @@ -1,11 +1,11 @@ #include "debugviewer.h" #include "ui_debugviewer.h" +#include #include #include #include -#include #include #include "mainwindow.h" @@ -133,8 +133,8 @@ void DebugViewer::on_debugShowRegisters_clicked(){ void DebugViewer::on_debugShowDebugLogs_clicked(){ EmuWrapper& emu = ((MainWindow*)parentWidget())->emu; - std::vector& debugStrings = emu.getDebugStrings(); - std::vector& duplicateCallCount = emu.getDuplicateCallCount(); + QVector& debugStrings = emu.getDebugStrings(); + QVector& duplicateCallCount = emu.getDuplicateCallCount(); int64_t length = numberFromString(ui->debugLength->text(), true/*negative allowed*/); ui->debugValueList->clear(); diff --git a/qtBuildSystem/Mu/emuwrapper.cpp b/qtBuildSystem/Mu/emuwrapper.cpp index 38db3ce..2cfadbf 100644 --- a/qtBuildSystem/Mu/emuwrapper.cpp +++ b/qtBuildSystem/Mu/emuwrapper.cpp @@ -1,6 +1,8 @@ #include +#include #include #include +#include #include #include #include @@ -11,7 +13,6 @@ #include #include #include -#include #include #include @@ -30,10 +31,10 @@ extern "C"{ static bool alreadyExists = false;//there can only be one of this class since it wrappers C code -static std::vector debugStrings; -static std::vector duplicateCallCount; -uint32_t frontendDebugStringSize; -char* frontendDebugString; +static QVector debugStrings; +static QVector duplicateCallCount; +uint32_t frontendDebugStringSize; +char* frontendDebugString; void frontendHandleDebugPrint(){ @@ -256,31 +257,62 @@ void EmuWrapper::reset(bool hard){ } } -uint32_t EmuWrapper::bootFromFileList(const QStringList& paths){ +uint32_t EmuWrapper::bootFromFileOrDirectory(const QString& mainPath){ bool wasPaused = isPaused(); uint32_t error = EMU_ERROR_NONE; - QByteArray* fileDataBuffers = new QByteArray[paths.length()]; - QByteArray infoBuffer; - file_t* files = new file_t[paths.length()]; - sd_card_info_t cardInfo; - int32_t newestBootableFile = -1; + QFileInfo pathInfo(mainPath); + QStringList paths; + QVector fileDataBuffers; + QVector fileInfoBuffers; + launcher_file_t* files; + int newestBootableFile = -1; if(!wasPaused) pause(); - memset(files, 0x00, sizeof(file_t) * paths.length()); + if(pathInfo.isDir()){ + //get Palm file list + QDir dirInfo(mainPath); + QStringList filters; - for(int32_t index = 0; index < paths.length(); index++){ + 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)){ QString suffix = QFileInfo(paths[index]).suffix().toLower(); - *fileDataBuffers = appFile.readAll(); + fileDataBuffers[index] = appFile.readAll(); appFile.close(); - files[index].fileData = (uint8_t*)fileDataBuffers->data(); - files[index].fileSize = fileDataBuffers->size(); + files[index].fileData = (uint8_t*)fileDataBuffers[index].data(); + files[index].fileSize = fileDataBuffers[index].size(); if(suffix == "prc"){ files[index].type = LAUNCHER_FILE_TYPE_PRC; @@ -293,15 +325,16 @@ uint32_t EmuWrapper::bootFromFileList(const QStringList& paths){ files[index].type = LAUNCHER_FILE_TYPE_PQA; newestBootableFile = index; } - else if(suffix == "zip"){ - files[index].type = LAUNCHER_FILE_TYPE_ZIP; - newestBootableFile = index; - } else if(suffix == "img"){ - //check for an info file - //TODO parse info file if it exists - //memset(&cardInfo, 0x00, sizeof(cardInfo)); - //files[index].info = &cardInfo; + QFile infoFile(paths[index]); + + if(infoFile.exists()){ + if(infoFile.open(QFile::ReadOnly)){ + fileInfoBuffers[index] = infoFile.readAll(); + files[index].infoData = (uint8_t*)fileInfoBuffers[index].data(); + files[index].infoSize = fileInfoBuffers[index].size(); + } + } files[index].type = LAUNCHER_FILE_TYPE_IMG; newestBootableFile = index; } @@ -334,7 +367,6 @@ uint32_t EmuWrapper::bootFromFileList(const QStringList& paths){ if(!wasPaused) resume(); - delete[] fileDataBuffers; return error; } @@ -454,11 +486,11 @@ uint32_t EmuWrapper::debugInstallApplication(const QString& path){ return error; } -std::vector& EmuWrapper::getDebugStrings(){ +QVector& EmuWrapper::getDebugStrings(){ return debugStrings; } -std::vector& EmuWrapper::getDuplicateCallCount(){ +QVector& EmuWrapper::getDuplicateCallCount(){ return duplicateCallCount; } diff --git a/qtBuildSystem/Mu/emuwrapper.h b/qtBuildSystem/Mu/emuwrapper.h index ab7a11d..4c696eb 100644 --- a/qtBuildSystem/Mu/emuwrapper.h +++ b/qtBuildSystem/Mu/emuwrapper.h @@ -1,12 +1,12 @@ #pragma once #include +#include #include #include #include #include -#include #include #include "../../src/emulator.h" @@ -48,7 +48,7 @@ public: void pause(); void resume(); void reset(bool hard); - uint32_t bootFromFileList(const QStringList& paths); + uint32_t bootFromFileOrDirectory(const QString& mainPath); uint32_t saveState(const QString& path); uint32_t loadState(const QString& path); bool isInited() const{return emuInited;} @@ -59,8 +59,8 @@ public: uint32_t debugInstallApplication(const QString& path); - std::vector& getDebugStrings(); - std::vector& getDuplicateCallCount(); + QVector& getDebugStrings(); + QVector& getDuplicateCallCount(); QString getCpuRegisterString(); uint16_t screenWidth() const{return palmFramebufferWidth;} diff --git a/qtBuildSystem/Mu/mainwindow.cpp b/qtBuildSystem/Mu/mainwindow.cpp index 8eb5125..4bd482f 100644 --- a/qtBuildSystem/Mu/mainwindow.cpp +++ b/qtBuildSystem/Mu/mainwindow.cpp @@ -431,13 +431,13 @@ void MainWindow::on_settings_clicked(){ void MainWindow::on_bootApp_clicked(){ if(emu.isInited()){ - QString app = QFileDialog::getOpenFileName(this, "Select Application", QDir::root().path(), "Palm OS Executable File (*.prc *.pqa *.zip)"); + QString appDir = QFileDialog::getExistingDirectory(this, "Select Directory", QDir::root().path()); - if(app != ""){ - uint32_t error = emu.bootFromFileList(QStringList(app)); + if(appDir != ""){ + uint32_t error = emu.bootFromFileOrDirectory(appDir); if(error != EMU_ERROR_NONE) - popupErrorDialog("Could not run app, Error:" + QString::number(error)); + popupErrorDialog("Could not load apps, Error:" + QString::number(error)); } } } diff --git a/src/fileLauncher/fatFs/diskio.c b/src/fileLauncher/fatFs/diskio.c index 6b89cae..f32b99f 100644 --- a/src/fileLauncher/fatFs/diskio.c +++ b/src/fileLauncher/fatFs/diskio.c @@ -110,8 +110,14 @@ DRESULT disk_ioctl ( ) { if(pdrv == DEV_RAM){ - //RAM has no ioctls - return RES_PARERR; + switch(cmd){ + case GET_BLOCK_SIZE: + *((uint32_t*)buff) = PALM_SD_CARD_SECTOR_SIZE; + return RES_OK; + + default: + return RES_PARERR; + } } return RES_PARERR; diff --git a/src/fileLauncher/fatFs/ffconf.h b/src/fileLauncher/fatFs/ffconf.h index db830c7..fcd2b1d 100644 --- a/src/fileLauncher/fatFs/ffconf.h +++ b/src/fileLauncher/fatFs/ffconf.h @@ -97,7 +97,7 @@ */ -#define FF_USE_LFN 2 +#define FF_USE_LFN 3 #define FF_MAX_LFN 255 /* The FF_USE_LFN switches the support for LFN (long file name). / diff --git a/src/fileLauncher/launcher.c b/src/fileLauncher/launcher.c index b890ccd..31d1a2a 100644 --- a/src/fileLauncher/launcher.c +++ b/src/fileLauncher/launcher.c @@ -2,6 +2,7 @@ #include #include "../emulator.h" +#include "../portability.h" #include "launcher.h" #include "fatFs/ff.h" @@ -57,7 +58,7 @@ static uint32_t launcherMakeBootRecord(const char* appName){ return EMU_ERROR_NONE; } -static uint32_t launcherCopyPrcPdbPqaToSdCard(file_t* file, uint32_t* fileId){ +static uint32_t launcherCopyPrcPdbPqaToSdCard(launcher_file_t* file, uint32_t* fileId){ FIL application; char name[FF_MAX_LFN]; FRESULT result; @@ -95,12 +96,7 @@ static uint32_t launcherCopyPrcPdbPqaToSdCard(file_t* file, uint32_t* fileId){ return EMU_ERROR_NONE; } -static uint32_t launcherCopyZipContentsToSdCard(file_t* file, uint32_t* fileId){ - //TODO - return EMU_ERROR_NOT_IMPLEMENTED; -} - -static uint32_t launcherSetupSdCardImageFromApps(file_t* files, uint32_t fileCount){ +static uint32_t launcherSetupSdCardImageFromApps(launcher_file_t* files, uint32_t fileCount){ uint32_t fileId = 0;//first file is named 0.p**, next is 1.p**, and the name continues going up with the file count FRESULT result; uint32_t error; @@ -124,13 +120,8 @@ static uint32_t launcherSetupSdCardImageFromApps(file_t* files, uint32_t fileCou error = launcherCopyPrcPdbPqaToSdCard(&files[index], &fileId); break; - case LAUNCHER_FILE_TYPE_ZIP: - error = launcherCopyZipContentsToSdCard(&files[index], &fileId); - break; - case LAUNCHER_FILE_TYPE_NONE: case LAUNCHER_FILE_TYPE_IMG: - case LAUNCHER_FILE_TYPE_INFO_IMG: default: error = EMU_ERROR_INVALID_PARAMETER; break; @@ -143,13 +134,54 @@ static uint32_t launcherSetupSdCardImageFromApps(file_t* files, uint32_t fileCou return EMU_ERROR_NONE; } -uint32_t launcherLaunch(file_t* files, uint32_t fileCount, uint8_t* sramData, uint32_t sramSize, uint8_t* sdCardData, uint32_t sdCardSize){ +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 applicationFileHasBeenLoaded = false; bool cardImageHasBeenLoaded = false; bool bootFileExists = false; uint32_t bootFileNum; uint32_t totalSize = 0; bool success; + uint32_t error; uint32_t index; for(index = 0; index < fileCount; index++){ @@ -158,7 +190,7 @@ uint32_t launcherLaunch(file_t* files, uint32_t fileCount, uint8_t* sramData, ui return EMU_ERROR_INVALID_PARAMETER; //cant load a card image if an app has been loaded already - if(applicationFileHasBeenLoaded && (files[index].type == LAUNCHER_FILE_TYPE_IMG || files[index].type == LAUNCHER_FILE_TYPE_INFO_IMG)) + if(applicationFileHasBeenLoaded && files[index].type == LAUNCHER_FILE_TYPE_IMG) return EMU_ERROR_INVALID_PARAMETER; //there must be exactly 1 boot file @@ -178,27 +210,43 @@ uint32_t launcherLaunch(file_t* files, uint32_t fileCount, uint8_t* sramData, ui //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(); + //make the card image or just copy it over if(cardImageHasBeenLoaded){ - //load card image - emulatorInsertSdCard(files[bootFileNum].fileData, files[bootFileNum].fileSize, files[bootFileNum].info); + if(files[bootFileNum].infoData){ + //with info file + sd_card_info_t sdInfo; - //dont save read only card images - if(files[bootFileNum].info && ((sd_card_info_t*)files[bootFileNum].info)->writeProtectSwitch) - launcherSaveSdCardImage = false; + //get SD info from file + launcherGetSdCardInfoFromInfoFile(&files[bootFileNum], &sdInfo); + + //load card image + error = emulatorInsertSdCard(files[bootFileNum].fileData, files[bootFileNum].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[bootFileNum].fileData, files[bootFileNum].fileSize, NULL); + if(error != EMU_ERROR_NONE) + return error; + } } else{ - //in case the emulator is currently running with an SD card inserted - emulatorEjectSdCard(); - if(sdCardData){ //use existing SD card image - emulatorInsertSdCard(sdCardData, sdCardSize, NULL); + error = emulatorInsertSdCard(sdCardData, sdCardSize, NULL); + if(error != EMU_ERROR_NONE) + return error; } else{ //load apps to new SD card image - uint32_t error; - error = emulatorInsertSdCard(NULL, totalSize, NULL); if(error != EMU_ERROR_NONE) return error; diff --git a/src/fileLauncher/launcher.h b/src/fileLauncher/launcher.h index e0de7c2..4669164 100644 --- a/src/fileLauncher/launcher.h +++ b/src/fileLauncher/launcher.h @@ -16,9 +16,7 @@ enum{ LAUNCHER_FILE_TYPE_PRC, LAUNCHER_FILE_TYPE_PDB, LAUNCHER_FILE_TYPE_PQA, - LAUNCHER_FILE_TYPE_ZIP, - LAUNCHER_FILE_TYPE_IMG, - LAUNCHER_FILE_TYPE_INFO_IMG + LAUNCHER_FILE_TYPE_IMG }; typedef struct{ @@ -26,15 +24,16 @@ typedef struct{ bool boot;//if set will be the application that is launched uint8_t* fileData; uint32_t fileSize; - void* info;//only used with LAUNCHER_FILE_TYPE_INFO_IMG right now, sd_card_info_t* -}file_t; + 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: -uint8_t* files[...]; +launcher_file_t* files[...]; uint32_t fileCount; uint8_t* saveData = NULL; uint32_t saveSize = 0; @@ -51,7 +50,7 @@ if(error) //its now safe to call emulatorFrame for frames */ //if first launch NULL should be passed for sramData and sdCardData -uint32_t launcherLaunch(file_t* files, uint32_t fileCount, uint8_t* sramData, uint32_t sramSize, uint8_t* sdCardData, uint32_t sdCardSize); +uint32_t launcherLaunch(launcher_file_t* files, uint32_t fileCount, uint8_t* sramData, uint32_t sramSize, uint8_t* sdCardData, uint32_t sdCardSize); #ifdef __cplusplus } diff --git a/src/fileLauncher/readme.md b/src/fileLauncher/readme.md index 6a24889..480ca48 100644 --- a/src/fileLauncher/readme.md +++ b/src/fileLauncher/readme.md @@ -3,17 +3,14 @@ ## This module is completely optional!!! By default it is not compiled in with the emu, to build it in define EMU_HAVE_FILE_LAUNCHER. -This along with an internal program allows booting .prc, .pqa, .zip and .img files, .img files can be passed with an optional .info file to specify any attributes not stored in the flash memory. +This along with an internal program allows booting .prc, .pqa and .img files, .img files can be passed with an optional .info file to specify any attributes not stored in the flash memory. There is also the option to load multiple files at the same time and specify the boot file. -In .zip files the file named "launch.prc" in the root of the zip is launched if the zip is the boot file. - The supported file types are: * .prc(bootable) * .pdb(not bootable) * .pqa(bootable) -* .zip(bootable) * .img(bootable) * .info + .img(bootable)