d1f55e8b45
* Timers with no repeat flag were being set to NULL, but this is not actually desired! * Reenabled transparency for aircraft shadow. * Deprecated NotificationRequest flags, and replaced by system timer handling.
879 lines
20 KiB
C
879 lines
20 KiB
C
/* *************************************
|
|
* Includes
|
|
* *************************************/
|
|
|
|
#include "System.h"
|
|
|
|
/* *************************************
|
|
* Defines
|
|
* *************************************/
|
|
|
|
#define FILE_BUFFER_SIZE 0x20014
|
|
#define SYSTEM_MAX_TIMERS 16
|
|
|
|
#define END_STACK_PATTERN (uint32_t) 0x18022015
|
|
#define BEGIN_STACK_ADDRESS (uint32_t*) 0x801FFF00
|
|
#define STACK_SIZE 0x1000
|
|
#define I_MASK (*(unsigned int*)0x1F801074)
|
|
|
|
/* *************************************
|
|
* Local Prototypes
|
|
* *************************************/
|
|
|
|
static void SystemCheckTimer(bool* timer, uint64_t* last_timer, uint8_t step);
|
|
static void SystemSetStackPattern(void);
|
|
static void SystemEnableVBlankInterrupt(void);
|
|
static void SystemDisableVBlankInterrupt(void);
|
|
|
|
/* *************************************
|
|
* Local Variables
|
|
* *************************************/
|
|
|
|
//Buffer to store any kind of files. It supports files up to 128 kB
|
|
static uint8_t file_buffer[FILE_BUFFER_SIZE];
|
|
//Global timer (called by interrupt)
|
|
static volatile uint64_t global_timer;
|
|
//Tells whether rand seed has been set
|
|
static bool rand_seed;
|
|
//Screen refresh flag (called by interrupt)
|
|
static volatile bool refresh_needed;
|
|
//Timers
|
|
static bool one_second_timer;
|
|
static bool hundred_ms_timer;
|
|
static bool five_hundred_ms_timer;
|
|
//Emergency mode flag. Toggled on pad connected/disconnected
|
|
static bool emergency_mode;
|
|
//Critical section is entered (i.e.: when accessing fopen() or other BIOS functions
|
|
static volatile bool system_busy;
|
|
//Timer array.
|
|
static TYPE_TIMER timer_array[SYSTEM_MAX_TIMERS];
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: void SystemInit(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: Calls main intialization routines.
|
|
*
|
|
* @remarks: To be called before main loop.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
void SystemInit(void)
|
|
{
|
|
//Reset global timer
|
|
global_timer = 0;
|
|
//Reset 1 second timer
|
|
one_second_timer = 0;
|
|
//PSXSDK init
|
|
PSX_InitEx(PSX_INIT_SAVESTATE | PSX_INIT_CD);
|
|
//Graphics init
|
|
GsInit();
|
|
//Clear VRAM
|
|
GsClearMem();
|
|
//Set Video Resolution
|
|
#ifdef _PAL_MODE_
|
|
GsSetVideoMode(X_SCREEN_RESOLUTION, Y_SCREEN_RESOLUTION, VMODE_PAL);
|
|
#else
|
|
GsSetVideoMode(X_SCREEN_RESOLUTION, Y_SCREEN_RESOLUTION, VMODE_NTSC);
|
|
#endif //_PAL_MODE_
|
|
//SPU init
|
|
SsInit();
|
|
//Reset all user-handled timers
|
|
SystemResetTimers();
|
|
//Pads init
|
|
PadInit();
|
|
//Set Drawing Environment
|
|
GfxInitDrawEnv();
|
|
//Set Display Environment
|
|
GfxInitDispEnv();
|
|
//Set VBlank Handler for screen refresh
|
|
SetVBlankHandler(&ISR_SystemDefaultVBlank);
|
|
//Set Primitive List
|
|
GfxSetPrimitiveList();
|
|
// Init memory card
|
|
MemCardInit();
|
|
//Initial value for system_busy
|
|
system_busy = false;
|
|
|
|
GfxSetGlobalLuminance(NORMAL_LUMINANCE);
|
|
|
|
SystemSetStackPattern();
|
|
|
|
SetRCnt(RCntCNT2,0xFFFF,RCntSC);
|
|
StartRCnt(RCntCNT2);
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: void SystemInit(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief:
|
|
* Calls srand() while avoiding multiple calls by setting internal
|
|
* variable rand_seed to true. Internal variable "global_timer" is
|
|
* used to generate the new seed.
|
|
*
|
|
* @remarks:
|
|
* It is recommended to call it once user has pressed any key.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
void SystemSetRandSeed(void)
|
|
{
|
|
if(rand_seed == false)
|
|
{
|
|
rand_seed = true;
|
|
//Set random seed using global timer as reference
|
|
srand((unsigned int)global_timer);
|
|
|
|
dprintf("Seed used: %d\n",(unsigned int)global_timer);
|
|
}
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: bool SystemIsRandSeedSet(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief:
|
|
* Reportedly, returns whether rand seed has already been set.
|
|
*
|
|
* @remarks:
|
|
*
|
|
* @return:
|
|
* Reportedly, returns whether rand seed has already been set.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
bool SystemIsRandSeedSet(void)
|
|
{
|
|
return rand_seed;
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: bool SystemRefreshNeeded(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief:
|
|
*
|
|
* @remarks:
|
|
*
|
|
* @return:
|
|
* Returns whether VSync flag has been enabled.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
bool SystemRefreshNeeded(void)
|
|
{
|
|
return refresh_needed;
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: void ISR_SystemDefaultVBlank(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief:
|
|
*
|
|
* @remarks:
|
|
* Called from VSync interrupt. Called 50 times a second in PAL mode,
|
|
* 60 times a second in NTSC mode.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
void ISR_SystemDefaultVBlank(void)
|
|
{
|
|
refresh_needed = true;
|
|
SystemIncreaseGlobalTimer();
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: void SystemIncreaseGlobalTimer(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief:
|
|
* Increases internal variable responsible for time handling.
|
|
*
|
|
* @remarks:
|
|
* Usually called from ISR_SystemDefaultVBlank().
|
|
*
|
|
* *******************************************************************/
|
|
|
|
void SystemIncreaseGlobalTimer(void)
|
|
{
|
|
global_timer++;
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: uint64_t SystemGetGlobalTimer(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: Returns internal global timer value.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
uint64_t SystemGetGlobalTimer(void)
|
|
{
|
|
return global_timer;
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: void SystemDisableScreenRefresh(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: Resets VBlank IRQ flag.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
void SystemDisableScreenRefresh(void)
|
|
{
|
|
refresh_needed = false;
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: bool System1SecondTick(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @return: bool variable with a 1-cycle-length pulse that gets
|
|
* set each second.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
bool System1SecondTick(void)
|
|
{
|
|
return one_second_timer;
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name: bool System100msTick(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @return: bool variable with a 1-cycle-length pulse that gets
|
|
* set every 100 milliseconds.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
bool System100msTick(void)
|
|
{
|
|
return hundred_ms_timer;
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name bool System500msTick(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @return: bool variable with a 1-cycle-length pulse that gets
|
|
* set every 500 milliseconds.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
bool System500msTick(void)
|
|
{
|
|
return five_hundred_ms_timer;
|
|
}
|
|
|
|
/* *******************************************************************
|
|
*
|
|
* @name void SystemRunTimers(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: general timer handler
|
|
*
|
|
* @remarks: 1 second, 500 ms and 100 ms ticks get updated here.
|
|
*
|
|
* *******************************************************************/
|
|
|
|
void SystemRunTimers(void)
|
|
{
|
|
static uint64_t last_one_second_tick;
|
|
static uint64_t last_100_ms_tick;
|
|
static uint64_t last_500_ms_tick;
|
|
|
|
SystemCheckTimer(&one_second_timer, &last_one_second_tick, REFRESH_FREQUENCY);
|
|
|
|
#ifdef _PAL_MODE_
|
|
SystemCheckTimer(&hundred_ms_timer, &last_100_ms_tick, 2 /* 2 * 50 ms = 100 ms */);
|
|
SystemCheckTimer(&five_hundred_ms_timer, &last_500_ms_tick, 10 /* 10 * 50 ms = 500 ms */);
|
|
#else // _PAL_MODE_
|
|
SystemCheckTimer(&hundred_ms_timer, &last_100_ms_tick, 3);
|
|
#endif // _PAL_MODE_
|
|
|
|
}
|
|
|
|
/* ********************************************************************************
|
|
*
|
|
* @name void SystemCheckTimer(bool* timer, uint64_t* last_timer, uint8_t step)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: Checks if needed time step has been elapsed. If true, flag gets set.
|
|
*
|
|
* *******************************************************************************/
|
|
|
|
void SystemCheckTimer(bool* timer, uint64_t* last_timer, uint8_t step)
|
|
{
|
|
if(*timer == true)
|
|
{
|
|
*timer = false;
|
|
}
|
|
|
|
if(global_timer >= (*last_timer + step) )
|
|
{
|
|
*timer = true;
|
|
*last_timer = global_timer;
|
|
}
|
|
}
|
|
|
|
/* ****************************************************************************************
|
|
*
|
|
* @name bool SystemLoadFileToBuffer(char* fname, uint8_t* buffer, uint32_t szBuffer)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: Given an input path, it fills a buffer pointed to by "buffer" with
|
|
* maximum size "szBuffer" with data from CD-ROM.
|
|
*
|
|
* @return: true if file has been loaded successfully, false otherwise.
|
|
*
|
|
* ****************************************************************************************/
|
|
|
|
bool SystemLoadFileToBuffer(char* fname, uint8_t* buffer, uint32_t szBuffer)
|
|
{
|
|
FILE *f;
|
|
int32_t size;
|
|
|
|
// Wait for possible previous operation from the GPU before entering this section.
|
|
while( (SystemIsBusy() == true) || (GfxIsGPUBusy() == true) );
|
|
|
|
if(fname == NULL)
|
|
{
|
|
dprintf("SystemLoadFile: NULL fname!\n");
|
|
return false;
|
|
}
|
|
|
|
memset(buffer,0,szBuffer);
|
|
|
|
system_busy = true;
|
|
|
|
SystemDisableVBlankInterrupt();
|
|
|
|
f = fopen(fname, "r");
|
|
|
|
if(f == NULL)
|
|
{
|
|
dprintf("SystemLoadFile: file could not be found!\n");
|
|
//File couldn't be found
|
|
return false;
|
|
}
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
|
|
size = ftell(f);
|
|
|
|
if(size > szBuffer)
|
|
{
|
|
dprintf("SystemLoadFile: Exceeds file buffer size (%d bytes)\n",size);
|
|
//Bigger than 128 kB (buffer's max size)
|
|
return false;
|
|
}
|
|
|
|
fseek(f, 0, SEEK_SET); //f->pos = 0;
|
|
|
|
fread(buffer, sizeof(char), size, f);
|
|
|
|
fclose(f);
|
|
|
|
SystemEnableVBlankInterrupt();
|
|
|
|
system_busy = false;
|
|
|
|
dprintf("File \"%s\" loaded successfully!\n",fname);
|
|
|
|
return true;
|
|
}
|
|
|
|
/* ****************************************************************************************
|
|
*
|
|
* @name bool SystemLoadFile(char*fname)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: Given an input file name, it loads its conents into internal buffer.
|
|
*
|
|
* @return: true if file has been loaded successfully, false otherwise.
|
|
*
|
|
* ****************************************************************************************/
|
|
|
|
bool SystemLoadFile(char*fname)
|
|
{
|
|
return SystemLoadFileToBuffer(fname,file_buffer,sizeof(file_buffer));
|
|
}
|
|
|
|
/* ******************************************************************
|
|
*
|
|
* @name uint8_t* SystemGetBufferAddress(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @return: Reportedly, returns internal buffer initial address.
|
|
*
|
|
* *****************************************************************/
|
|
|
|
uint8_t* SystemGetBufferAddress(void)
|
|
{
|
|
return file_buffer;
|
|
}
|
|
|
|
/* ******************************************************************
|
|
*
|
|
* @name void SystemClearBuffer(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @return: Fills internal buffer with zeros
|
|
*
|
|
* *****************************************************************/
|
|
|
|
void SystemClearBuffer(void)
|
|
{
|
|
memset(file_buffer, 0, sizeof(file_buffer));
|
|
}
|
|
|
|
/* ******************************************************************
|
|
*
|
|
* @name void SystemWaitCycles(uint32_t cycles)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @return: halts program execution for n-"cycles"
|
|
*
|
|
* *****************************************************************/
|
|
|
|
void SystemWaitCycles(uint32_t cycles)
|
|
{
|
|
uint64_t currentTime = global_timer;
|
|
|
|
while(global_timer < (currentTime + cycles) );
|
|
}
|
|
|
|
/* ******************************************************************
|
|
*
|
|
* @name uint32_t SystemRand(uint32_t min, uint32_t max)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @return: random number between "min" and "max".
|
|
*
|
|
* @remarks: rand seed must be set before using this function, or
|
|
* you will predictable values otherwise!
|
|
*
|
|
* *****************************************************************/
|
|
|
|
uint32_t SystemRand(uint32_t min, uint32_t max)
|
|
{
|
|
return rand() % (max - min + 1) + min;
|
|
}
|
|
|
|
/* ***********************************************************************
|
|
*
|
|
* @name void SystemSetEmergencyMode(bool value)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: Sets emergency mode flag.
|
|
*
|
|
* @remarks: emergency mode is set once that a controller is unplugged.
|
|
*
|
|
* ***********************************************************************/
|
|
|
|
void SystemSetEmergencyMode(bool value)
|
|
{
|
|
emergency_mode = value;
|
|
}
|
|
|
|
/* ***********************************************************************
|
|
*
|
|
* @name bool SystemGetEmergencyMode(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @return: returns emergency mode flag.
|
|
*
|
|
* ***********************************************************************/
|
|
|
|
bool SystemGetEmergencyMode(void)
|
|
{
|
|
return emergency_mode;
|
|
}
|
|
|
|
/* ***********************************************************************
|
|
*
|
|
* @name volatile bool SystemIsBusy(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @return: returns system busy flag.
|
|
*
|
|
* ***********************************************************************/
|
|
|
|
volatile bool SystemIsBusy(void)
|
|
{
|
|
return system_busy;
|
|
}
|
|
|
|
/* ****************************************************************************
|
|
*
|
|
* @name bool SystemContains_u8(uint8_t value, uint8_t* buffer, size_t sz)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: checks if a certain value is contained in a buffer with size "sz".
|
|
*
|
|
* @return: true if value is contained inside buffer, false otherwise.
|
|
*
|
|
* ****************************************************************************/
|
|
|
|
bool SystemContains_u8(uint8_t value, uint8_t* buffer, size_t sz)
|
|
{
|
|
size_t i = 0;
|
|
|
|
for(i = 0; i < sz; i++)
|
|
{
|
|
if(buffer[i] == value)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* ****************************************************************************
|
|
*
|
|
* @name bool SystemContains_u16(uint16_t value, uint16_t* buffer, size_t sz)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: checks if a certain value is contained in a buffer with size "sz".
|
|
* Variant for u16 variables.
|
|
*
|
|
* @return: true if value is contained inside buffer, false otherwise.
|
|
*
|
|
* ****************************************************************************/
|
|
|
|
bool SystemContains_u16(uint16_t value, uint16_t* buffer, size_t sz)
|
|
{
|
|
size_t i = 0;
|
|
|
|
for(i = 0; i < sz; i++)
|
|
{
|
|
if(buffer[i] == value)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* ********************************************************************************************
|
|
*
|
|
* @name TYPE_TIMER* SystemCreateTimer(uint32_t t, bool rf, void (*timer_callback)(void) )
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: fills a TYPE_TIMER structure with input parameters
|
|
*
|
|
* @param: uint32_t t:
|
|
* Timeout value (1 unit = 10 ms)
|
|
* bool rf:
|
|
* Repeat flag
|
|
* void (*timer_callback)(void)
|
|
* Function to be called on timeout
|
|
*
|
|
* @return: pointer to TYPE_TIMER structure if filled correctly, NULL pointer otherwise.
|
|
*
|
|
* ********************************************************************************************/
|
|
|
|
TYPE_TIMER* SystemCreateTimer(uint32_t t, bool rf, void (*timer_callback)(void) )
|
|
{
|
|
bool success = false;
|
|
uint8_t i;
|
|
|
|
if(t == 0)
|
|
{
|
|
dprintf("Cannot create timer with time == 0!\n");
|
|
return NULL;
|
|
}
|
|
|
|
for(i = 0; i < SYSTEM_MAX_TIMERS; i++)
|
|
{
|
|
if(timer_array[i].busy == false)
|
|
{
|
|
timer_array[i].Timeout_Callback = timer_callback;
|
|
timer_array[i].time = t;
|
|
timer_array[i].orig_time = t;
|
|
timer_array[i].repeat_flag = rf;
|
|
timer_array[i].busy = true;
|
|
success = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(success == false)
|
|
{
|
|
dprintf("Could not find any free timer!\n");
|
|
return NULL;
|
|
}
|
|
|
|
return &timer_array[i];
|
|
}
|
|
|
|
/* *******************************************
|
|
*
|
|
* @name void SystemResetTimers(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: reportedly, removes all timers.
|
|
*
|
|
* *******************************************/
|
|
|
|
void SystemResetTimers(void)
|
|
{
|
|
uint8_t i;
|
|
|
|
for(i = 0; i < SYSTEM_MAX_TIMERS; i++)
|
|
{
|
|
SystemTimerRemove(&timer_array[i]);
|
|
}
|
|
}
|
|
|
|
/* *****************************************************
|
|
*
|
|
* @name void SystemUserTimersHandler(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: reportedly, handles all available timers.
|
|
*
|
|
* @remarks: calls callback on timeout.
|
|
*
|
|
* *****************************************************/
|
|
|
|
void SystemUserTimersHandler(void)
|
|
{
|
|
uint8_t i;
|
|
|
|
for(i = 0; i < SYSTEM_MAX_TIMERS; i++)
|
|
{
|
|
if(timer_array[i].busy == true)
|
|
{
|
|
if(System100msTick() == true)
|
|
{
|
|
timer_array[i].time--;
|
|
|
|
if(timer_array[i].time == 0)
|
|
{
|
|
timer_array[i].Timeout_Callback();
|
|
|
|
if(timer_array[i].repeat_flag == true)
|
|
{
|
|
timer_array[i].time = timer_array[i].orig_time;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* *********************************************************************
|
|
*
|
|
* @name void SystemUserTimersHandler(void)
|
|
*
|
|
* @author: Xavier Del Campo
|
|
*
|
|
* @brief: sets time left for TYPE_TIMER instance to initial value.
|
|
*
|
|
* @remarks: specially used when TYPE_TIMER.rf is enabled.
|
|
*
|
|
* *********************************************************************/
|
|
|
|
void SystemTimerRestart(TYPE_TIMER* timer)
|
|
{
|
|
timer->time = timer->orig_time;
|
|
dprintf("Time set to %d seconds, timer 0x%08X\n", timer->time, timer);
|
|
}
|
|
|
|
void SystemTimerRemove(TYPE_TIMER* timer)
|
|
{
|
|
timer->time = 0;
|
|
timer->orig_time = 0;
|
|
timer->Timeout_Callback = NULL;
|
|
timer->busy = false;
|
|
timer->repeat_flag = false;
|
|
}
|
|
|
|
bool SystemArrayCompare(unsigned short* arr1, unsigned short* arr2, size_t sz)
|
|
{
|
|
size_t i;
|
|
|
|
for(i = 0; i < sz; i++)
|
|
{
|
|
if(arr1[i] != arr2[i])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void SystemPrintStackPointerAddress(void)
|
|
{
|
|
#ifdef PSXSDK_DEBUG // Used to avoid unused variable warning
|
|
void * ptr = NULL;
|
|
fix16_t used_bytes = fix16_from_int((int)((void*)BEGIN_STACK_ADDRESS - (void*)&ptr));
|
|
fix16_t stackPercent = fix16_sdiv(used_bytes,fix16_from_int((int)STACK_SIZE));
|
|
|
|
stackPercent = fix16_smul(stackPercent, fix16_from_int((int)100));
|
|
|
|
dprintf("stackPercent: %d\n", stackPercent);
|
|
|
|
dprintf("Stack begin pointer: 0x%08X\n"
|
|
"Stack pointer address: 0x%08X\n"
|
|
"Used %d%% of stack size.\n"
|
|
"\tUsed bytes: %d\n",
|
|
(void*)BEGIN_STACK_ADDRESS,
|
|
(void*)&ptr,
|
|
fix16_to_int(stackPercent),
|
|
fix16_to_int(used_bytes) );
|
|
#endif // PSXSDK_DEBUG
|
|
|
|
}
|
|
|
|
void SystemCheckStack(void)
|
|
{
|
|
uint32_t * ptrStack = BEGIN_STACK_ADDRESS;
|
|
uint32_t data;
|
|
|
|
ptrStack -= STACK_SIZE;
|
|
data = (*ptrStack);
|
|
|
|
if(data != END_STACK_PATTERN)
|
|
{
|
|
dprintf("Stack overflow?\n");
|
|
|
|
while(1);
|
|
}
|
|
}
|
|
|
|
void SystemSetStackPattern(void)
|
|
{
|
|
uint32_t * ptrStack = BEGIN_STACK_ADDRESS;
|
|
|
|
ptrStack -= STACK_SIZE;
|
|
|
|
*ptrStack = END_STACK_PATTERN;
|
|
}
|
|
|
|
int32_t SystemIndexOfStringArray(char* str, char** array)
|
|
{
|
|
int32_t i;
|
|
|
|
for(i = 0; array[i] != NULL; i++)
|
|
{
|
|
dprintf("String to find: %s\nEntry: %s\n", str, array[i]);
|
|
|
|
if(strcmp(str, array[i]) == 0)
|
|
{
|
|
dprintf("Match! Returning index %d...\n", i);
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int32_t SystemIndexOf_U16(uint16_t value, uint16_t* array, uint32_t sz)
|
|
{
|
|
int32_t i;
|
|
|
|
for(i = 0; i < sz; i++)
|
|
{
|
|
if(value == array[i])
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int32_t SystemIndexOf_U8(uint8_t value, uint8_t* array, uint32_t from, uint32_t sz)
|
|
{
|
|
int32_t i;
|
|
|
|
for(i = from; i < sz; i++)
|
|
{
|
|
if(value == array[i])
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void SystemCyclicHandler(void)
|
|
{
|
|
if(UpdatePads() == false)
|
|
{
|
|
SystemSetEmergencyMode(true);
|
|
}
|
|
else
|
|
{
|
|
SystemSetEmergencyMode(false);
|
|
}
|
|
|
|
SystemRunTimers();
|
|
|
|
SystemUserTimersHandler();
|
|
|
|
SystemDisableScreenRefresh();
|
|
|
|
MemCardHandler();
|
|
|
|
SystemCheckStack();
|
|
}
|
|
|
|
void SystemDisableVBlankInterrupt(void)
|
|
{
|
|
I_MASK &= ~(0x0001);
|
|
}
|
|
|
|
void SystemEnableVBlankInterrupt(void)
|
|
{
|
|
I_MASK |= (0x0001);
|
|
}
|