Launcher work

Gonna try and make the launcher as simple as possible, no zip files, the frontend can handle that if it wants.

Going to make the Qt port launch directorys instead of files too since the file dialog only allows selecting files or directorys and some apps have resource files.
This commit is contained in:
meepingsnesroms
2019-05-18 20:01:28 -07:00
parent 2238274f51
commit 4d88e893e0
10 changed files with 161 additions and 79 deletions

View File

@@ -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

View File

@@ -1,11 +1,11 @@
#include "debugviewer.h"
#include "ui_debugviewer.h"
#include <QVector>
#include <QString>
#include <QFile>
#include <QDir>
#include <vector>
#include <stdint.h>
#include "mainwindow.h"
@@ -133,8 +133,8 @@ void DebugViewer::on_debugShowRegisters_clicked(){
void DebugViewer::on_debugShowDebugLogs_clicked(){
EmuWrapper& emu = ((MainWindow*)parentWidget())->emu;
std::vector<QString>& debugStrings = emu.getDebugStrings();
std::vector<uint64_t>& duplicateCallCount = emu.getDuplicateCallCount();
QVector<QString>& debugStrings = emu.getDebugStrings();
QVector<uint64_t>& duplicateCallCount = emu.getDuplicateCallCount();
int64_t length = numberFromString(ui->debugLength->text(), true/*negative allowed*/);
ui->debugValueList->clear();

View File

@@ -1,6 +1,8 @@
#include <QString>
#include <QVector>
#include <QPixmap>
#include <QImage>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QByteArray>
@@ -11,7 +13,6 @@
#include <new>
#include <chrono>
#include <thread>
#include <vector>
#include <string>
#include <stdint.h>
@@ -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<QString> debugStrings;
static std::vector<uint64_t> duplicateCallCount;
uint32_t frontendDebugStringSize;
char* frontendDebugString;
static QVector<QString> debugStrings;
static QVector<uint64_t> 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<QByteArray> fileDataBuffers;
QVector<QByteArray> 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<QString>& EmuWrapper::getDebugStrings(){
QVector<QString>& EmuWrapper::getDebugStrings(){
return debugStrings;
}
std::vector<uint64_t>& EmuWrapper::getDuplicateCallCount(){
QVector<uint64_t>& EmuWrapper::getDuplicateCallCount(){
return duplicateCallCount;
}

View File

@@ -1,12 +1,12 @@
#pragma once
#include <QPixmap>
#include <QVector>
#include <QString>
#include <QByteArray>
#include <thread>
#include <atomic>
#include <vector>
#include <stdint.h>
#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<QString>& getDebugStrings();
std::vector<uint64_t>& getDuplicateCallCount();
QVector<QString>& getDebugStrings();
QVector<uint64_t>& getDuplicateCallCount();
QString getCpuRegisterString();
uint16_t screenWidth() const{return palmFramebufferWidth;}

View File

@@ -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));
}
}
}

View File

@@ -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;

View File

@@ -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).
/

View File

@@ -2,6 +2,7 @@
#include <stdbool.h>
#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;

View File

@@ -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
}

View File

@@ -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)