Files
Mu/tools/palm/hwTestSuite/testSuite.c
2018-10-30 13:26:02 -07:00

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