mirror of
https://github.com/libretro/Mu.git
synced 2026-09-23 15:15:43 +00:00
313 lines
8.0 KiB
C
313 lines
8.0 KiB
C
#include <PalmOS.h>
|
|
#include <PalmCompatibility.h>
|
|
#include <stdint.h>
|
|
|
|
#include "ugui.h"
|
|
#include "testSuiteConfig.h"
|
|
#include "testSuite.h"
|
|
#include "viewer.h"
|
|
#include "debug.h"
|
|
#include "tools.h"
|
|
|
|
/*dont include this anywhere else*/
|
|
#include "TstSuiteRsc.h"
|
|
|
|
|
|
/*exported functions, cant be converted into macros*/
|
|
var makeVar(uint8_t length, uint8_t type, uint64_t value){
|
|
var newVar;
|
|
newVar.type = length & 0xF0 | type & 0x0F;
|
|
newVar.value = value;
|
|
return newVar;
|
|
}
|
|
|
|
static char floatString[maxStrIToALen * 2 + 3];/*2 ints and "-.\0"*/
|
|
char* floatToString(float data){
|
|
if(data == 1.0 / 0.0){
|
|
StrCopy(floatString, "+INF");
|
|
}
|
|
else if(data == -(1.0 / 0.0)){
|
|
StrCopy(floatString, "-INF");
|
|
}
|
|
else if(data == 0.0){
|
|
StrCopy(floatString, "0.0");
|
|
}
|
|
else{
|
|
char convertBuffer[maxStrIToALen];
|
|
Boolean negative;
|
|
|
|
if(data < 0.0){
|
|
negative = true;
|
|
data = -data;
|
|
}
|
|
else{
|
|
negative = false;
|
|
}
|
|
|
|
floatString[0] = '\0';
|
|
data = abs(data);
|
|
StrIToA(convertBuffer, (int32_t)data);
|
|
if(negative)
|
|
StrCat(floatString, "-");
|
|
StrCat(floatString, convertBuffer);
|
|
StrCat(floatString, ".");
|
|
data -= (int32_t)data;
|
|
data *= 1000000000;
|
|
StrIToA(convertBuffer, (int32_t)data);
|
|
StrCat(floatString, convertBuffer);
|
|
}
|
|
|
|
return floatString;
|
|
}
|
|
|
|
/*exports*/
|
|
uint16_t palmButtons;
|
|
uint16_t palmButtonsLastFrame;
|
|
Boolean isM515;
|
|
Boolean haveKsyms;
|
|
Boolean skipFrameDelay;
|
|
uint8_t* sharedDataBuffer;
|
|
|
|
/*video*/
|
|
static UG_GUI uguiStruct;
|
|
static BitmapType* offscreenBitmap;
|
|
static uint8_t* framebuffer;
|
|
|
|
/*other*/
|
|
static activity_t parentSubprograms[MAX_SUBPROGRAMS];
|
|
static uint32_t subprogramIndex;
|
|
static activity_t currentSubprogram;
|
|
static var subprogramData[MAX_SUBPROGRAMS];
|
|
static var subprogramArgs;/*optional arguments when one subprogram calls another*/
|
|
static var lastSubprogramReturnValue;
|
|
static Boolean subprogramArgsSet;
|
|
static Boolean applicationRunning;
|
|
|
|
|
|
static var errorSubprogramStackOverflow(){
|
|
static Boolean wipedScreen = false;
|
|
|
|
if(!wipedScreen){
|
|
debugSafeScreenClear(C_WHITE);
|
|
UG_PutString(0, 0, "Subprogram stack overflow!\nYou must close the program.");
|
|
wipedScreen = true;
|
|
}
|
|
if(getButtonPressed(buttonBack)){
|
|
/*force kill when back pressed*/
|
|
applicationRunning = false;
|
|
}
|
|
/*do nothing, this is a safe crash*/
|
|
}
|
|
|
|
var memoryAllocationError(){
|
|
static Boolean wipedScreen = false;
|
|
|
|
if(!wipedScreen){
|
|
debugSafeScreenClear(C_WHITE);
|
|
UG_PutString(0, 0, "Could not allocate memory!\nYou must close the program.");
|
|
wipedScreen = true;
|
|
}
|
|
if(getButtonPressed(buttonBack)){
|
|
/*force kill when back pressed*/
|
|
applicationRunning = false;
|
|
}
|
|
/*do nothing, this is a safe crash*/
|
|
}
|
|
|
|
static void uguiDrawPixel(UG_S16 x, UG_S16 y, UG_COLOR color){
|
|
/*using 1bit grayscale*/
|
|
int pixel = x + y * SCREEN_WIDTH;
|
|
int byte = pixel / 8;
|
|
int bit = pixel % 8;
|
|
|
|
/*ugui will call this function even if its over the screen bounds, dont let those writes through*/
|
|
if(pixel > SCREEN_WIDTH * SCREEN_HEIGHT - 1)
|
|
return;
|
|
|
|
if(!color){
|
|
/*1 is black not white*/
|
|
framebuffer[byte] |= (1 << (7 - bit));
|
|
}
|
|
else{
|
|
framebuffer[byte] &= ~(1 << (7 - bit));
|
|
}
|
|
}
|
|
|
|
/*needed to redraw after every call to setDebugTag(char*)*/
|
|
void forceFrameRedraw(){
|
|
WinDrawBitmap(offscreenBitmap, 0, 0);
|
|
}
|
|
|
|
void callSubprogram(activity_t activity){
|
|
if(subprogramIndex < MAX_SUBPROGRAMS - 1){
|
|
subprogramIndex++;
|
|
parentSubprograms[subprogramIndex] = activity;
|
|
currentSubprogram = activity;
|
|
if(!subprogramArgsSet)
|
|
subprogramArgs = makeVar(LENGTH_0, TYPE_NULL, 0);
|
|
subprogramArgsSet = false;/*clear to prevent next subprogram called from inheriting the args*/
|
|
setDebugTag("Subprogram Called");
|
|
}
|
|
else{
|
|
currentSubprogram = errorSubprogramStackOverflow;
|
|
/*cant recover from this*/
|
|
}
|
|
}
|
|
|
|
void exitSubprogram(){
|
|
if(subprogramIndex > 0){
|
|
subprogramIndex--;
|
|
currentSubprogram = parentSubprograms[subprogramIndex];
|
|
setDebugTag("Subprogram Exited");
|
|
}
|
|
else{
|
|
/*last subprogram is complete*/
|
|
setDebugTag("Application Exiting");
|
|
applicationRunning = false;
|
|
}
|
|
}
|
|
|
|
void execSubprogram(activity_t activity){
|
|
if(!subprogramArgsSet)
|
|
subprogramArgs = makeVar(LENGTH_0, TYPE_NULL, 0);
|
|
subprogramArgsSet = false;/*clear to prevent next subprogram called from inheriting the args*/
|
|
currentSubprogram = activity;
|
|
setDebugTag("Subprogram Swapped Out");
|
|
}
|
|
|
|
var getSubprogramReturnValue(){
|
|
return lastSubprogramReturnValue;
|
|
}
|
|
|
|
var getSubprogramArgs(){
|
|
return subprogramArgs;
|
|
}
|
|
|
|
void setSubprogramArgs(var args){
|
|
subprogramArgs = args;
|
|
subprogramArgsSet = true;
|
|
}
|
|
|
|
var subprogramGetData(){
|
|
return subprogramData[subprogramIndex];
|
|
}
|
|
|
|
void subprogramSetData(var data){
|
|
subprogramData[subprogramIndex] = data;
|
|
}
|
|
|
|
static Boolean testerInit(){
|
|
uint32_t osVer;
|
|
uint32_t deviceId;
|
|
Err error;
|
|
|
|
FtrGet(sysFtrCreator, sysFtrNumROMVersion, &osVer);
|
|
if(osVer < PalmOS35){
|
|
FrmCustomAlert(alt_err, "TestSuite requires at least PalmOS 3.5", 0, 0);
|
|
return false;
|
|
}
|
|
|
|
sharedDataBuffer = MemPtrNew(SHARED_DATA_BUFFER_SIZE);
|
|
if(!sharedDataBuffer){
|
|
FrmCustomAlert(alt_err, "Cant create memory buffer", 0, 0);
|
|
return false;
|
|
}
|
|
|
|
offscreenBitmap = BmpCreate(SCREEN_WIDTH, SCREEN_HEIGHT, 1, NULL, &error);
|
|
if(error != errNone){
|
|
FrmCustomAlert(alt_err, "Cant create bitmap", 0, 0);
|
|
return false;
|
|
}
|
|
|
|
KeySetMask(~(keyBitPageUp | keyBitPageDown | keyBitHard1 | keyBitHard2 | keyBitHard3 | keyBitHard4 ));
|
|
|
|
framebuffer = BmpGetBits(offscreenBitmap);
|
|
WinSetActiveWindow(WinGetDisplayWindow());
|
|
|
|
UG_Init(&uguiStruct, uguiDrawPixel, SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
UG_FontSelect(&SELECTED_FONT);
|
|
UG_SetBackcolor(C_WHITE);
|
|
UG_SetForecolor(C_BLACK);
|
|
UG_ConsoleSetBackcolor(C_WHITE);
|
|
UG_ConsoleSetForecolor(C_BLACK);
|
|
UG_FillScreen(C_WHITE);
|
|
|
|
/*setup subprogram enviroment*/
|
|
palmButtons = 0x0000;
|
|
palmButtonsLastFrame = 0x0000;
|
|
FtrGet(sysFtrCreator, sysFtrNumOEMDeviceID, &deviceId);
|
|
isM515 = deviceId == (uint32_t)'lith';/*"lith" is the Palm m515 device code, likely because it is one of the first with a lithium ion battery*/
|
|
haveKsyms = initUndocumentedApiHandlers();
|
|
skipFrameDelay = false;
|
|
subprogramIndex = 0;
|
|
subprogramArgsSet = false;
|
|
lastSubprogramReturnValue = makeVar(LENGTH_0, TYPE_NULL, 0);
|
|
subprogramArgs = makeVar(LENGTH_0, TYPE_NULL, 0);
|
|
currentSubprogram = functionPicker;
|
|
parentSubprograms[0] = functionPicker;
|
|
|
|
/*make function list, needs to be after setting isM515 and unsafeMode*/
|
|
resetFunctionViewer();
|
|
|
|
return true;
|
|
}
|
|
|
|
static void testerExit(){
|
|
MemPtrFree(sharedDataBuffer);
|
|
}
|
|
|
|
static void testerFrameLoop(){
|
|
static uint32_t lastResetTime = 0;
|
|
EventType event;
|
|
|
|
palmButtons = KeyCurrentState();
|
|
|
|
/*allow exiting the app normally and prevent filling up the event loop*/
|
|
do{
|
|
EvtGetEvent(&event, 1);
|
|
SysHandleEvent(&event);
|
|
if(event.eType == appStopEvent){
|
|
applicationRunning = false;
|
|
break;
|
|
}
|
|
}
|
|
while(event.eType != nilEvent);
|
|
|
|
/*disable auto off timer*/
|
|
if(TimGetSeconds() - lastResetTime > 50){
|
|
EvtResetAutoOffTimer();
|
|
lastResetTime = TimGetSeconds();
|
|
}
|
|
|
|
lastSubprogramReturnValue = currentSubprogram();
|
|
|
|
WinDrawBitmap(offscreenBitmap, 0, 0);
|
|
|
|
palmButtonsLastFrame = palmButtons;
|
|
|
|
if(!skipFrameDelay)
|
|
SysTaskDelay(4);/*30 fps*/
|
|
skipFrameDelay = false;
|
|
}
|
|
|
|
DWord PilotMain(Word cmd, Ptr cmdBPB, Word launchFlags){
|
|
if(cmd == sysAppLaunchCmdNormalLaunch){
|
|
Boolean initSuccess = testerInit();
|
|
|
|
if(!initSuccess)
|
|
return 0;
|
|
|
|
applicationRunning = true;
|
|
|
|
while(applicationRunning)
|
|
testerFrameLoop();
|
|
|
|
testerExit();
|
|
}
|
|
else if(cmd == sysAppLaunchCmdSystemReset){
|
|
/*eventualy boot time tests may go here*/
|
|
}
|
|
|
|
return 0;
|
|
}
|