From b28059d49afce8524361fa7597adcc9e108f4eab Mon Sep 17 00:00:00 2001 From: Xavi Del Campo Date: Tue, 3 Mar 2020 18:10:15 +0100 Subject: Renamed folders to lowercase --- Bin/OPENSEND.bin | Bin 627984 -> 0 bytes Bin/OPENSEND.cue | 3 - Source/EndAnimation.c | 233 -------------------- Source/EndAnimation.h | 25 --- Source/Font.c | 194 ----------------- Source/Font.h | 44 ---- Source/GameStructures.h | 57 ----- Source/Gfx.c | 552 ----------------------------------------------- Source/Gfx.h | 109 ---------- Source/Global_Inc.h | 41 ---- Source/LoadMenu.c | 204 ------------------ Source/LoadMenu.h | 29 --- Source/Makefile | 74 ------- Source/Serial.c | 278 ------------------------ Source/Serial.h | 49 ----- Source/System.c | 493 ------------------------------------------ Source/System.h | 118 ---------- Source/main.c | 162 -------------- Sprites/Font_2.bmp | Bin 18486 -> 0 bytes Sprites/Font_2_4bit.bmp | Bin 3190 -> 0 bytes bin/OPENSEND.bin | Bin 0 -> 627984 bytes bin/OPENSEND.cue | 3 + include/EndAnimation.h | 25 +++ include/Font.h | 44 ++++ include/GameStructures.h | 57 +++++ include/Gfx.h | 109 ++++++++++ include/Global_Inc.h | 41 ++++ include/LoadMenu.h | 29 +++ include/Serial.h | 49 +++++ include/System.h | 118 ++++++++++ sprites/Font_2.bmp | Bin 0 -> 18486 bytes sprites/Font_2_4bit.bmp | Bin 0 -> 3190 bytes src/EndAnimation.c | 233 ++++++++++++++++++++ src/Font.c | 194 +++++++++++++++++ src/Gfx.c | 552 +++++++++++++++++++++++++++++++++++++++++++++++ src/LoadMenu.c | 204 ++++++++++++++++++ src/Makefile | 74 +++++++ src/Serial.c | 278 ++++++++++++++++++++++++ src/System.c | 493 ++++++++++++++++++++++++++++++++++++++++++ src/main.c | 161 ++++++++++++++ 40 files changed, 2664 insertions(+), 2665 deletions(-) delete mode 100644 Bin/OPENSEND.bin delete mode 100644 Bin/OPENSEND.cue delete mode 100644 Source/EndAnimation.c delete mode 100644 Source/EndAnimation.h delete mode 100644 Source/Font.c delete mode 100644 Source/Font.h delete mode 100644 Source/GameStructures.h delete mode 100644 Source/Gfx.c delete mode 100644 Source/Gfx.h delete mode 100644 Source/Global_Inc.h delete mode 100644 Source/LoadMenu.c delete mode 100644 Source/LoadMenu.h delete mode 100644 Source/Makefile delete mode 100644 Source/Serial.c delete mode 100644 Source/Serial.h delete mode 100644 Source/System.c delete mode 100644 Source/System.h delete mode 100644 Source/main.c delete mode 100644 Sprites/Font_2.bmp delete mode 100644 Sprites/Font_2_4bit.bmp create mode 100644 bin/OPENSEND.bin create mode 100644 bin/OPENSEND.cue create mode 100644 include/EndAnimation.h create mode 100644 include/Font.h create mode 100644 include/GameStructures.h create mode 100644 include/Gfx.h create mode 100644 include/Global_Inc.h create mode 100644 include/LoadMenu.h create mode 100644 include/Serial.h create mode 100644 include/System.h create mode 100644 sprites/Font_2.bmp create mode 100644 sprites/Font_2_4bit.bmp create mode 100644 src/EndAnimation.c create mode 100644 src/Font.c create mode 100644 src/Gfx.c create mode 100644 src/LoadMenu.c create mode 100644 src/Makefile create mode 100644 src/Serial.c create mode 100644 src/System.c create mode 100644 src/main.c diff --git a/Bin/OPENSEND.bin b/Bin/OPENSEND.bin deleted file mode 100644 index 39a962a..0000000 Binary files a/Bin/OPENSEND.bin and /dev/null differ diff --git a/Bin/OPENSEND.cue b/Bin/OPENSEND.cue deleted file mode 100644 index 4b18ec2..0000000 --- a/Bin/OPENSEND.cue +++ /dev/null @@ -1,3 +0,0 @@ -FILE "OPENSEND.bin" BINARY -TRACK 01 MODE2/2352 - INDEX 01 00:00:00 diff --git a/Source/EndAnimation.c b/Source/EndAnimation.c deleted file mode 100644 index 027ca1a..0000000 --- a/Source/EndAnimation.c +++ /dev/null @@ -1,233 +0,0 @@ -/* ************************************* - * Includes - * *************************************/ - -#include "EndAnimation.h" - -/* ************************************* - * Defines - * *************************************/ - -/* ************************************* - * Structs and enums - * *************************************/ - -enum -{ - END_ANIMATION_FADEOUT_STEP = 8, - - END_ANIMATION_LINE_STEP = 2, - - END_ANIMATION_SQUARES_SIZE_BITSHIFT = 5, - END_ANIMATION_SQUARES_SIZE = 32, - END_ANIMATION_SQUARES_PER_COLUMN = 8, - END_ANIMATION_SQUARES_PER_ROW = 12, - END_ANIMATION_SQUARES_TOTAL = END_ANIMATION_SQUARES_PER_COLUMN * - END_ANIMATION_SQUARES_PER_ROW, - - END_ANIMATION_SQUARES_TOTAL_MAX_INDEX = END_ANIMATION_SQUARES_TOTAL - 1, - - END_ANIMATION_SQUARES = 0, - END_ANIMATION_FADEOUT, - END_ANIMATION_LINE, - END_ANIMATION_MAX_RAND_VALUE = END_ANIMATION_LINE -}; - -/* ************************************* - * Local Prototypes - * *************************************/ - -static void EndAnimationSquares(void); -static void EndAnimationFadeOut(void); -static void EndAnimationLine(void); - -/* ************************************* - * Local Variables - * *************************************/ - -static GsRectangle EndAnimationRect; -static GsSprite EndAnimationDisplay; - -void EndAnimation(void) -{ - uint8_t randIndex = 0; - - GfxSaveDisplayData(&EndAnimationDisplay); - - GfxSetGlobalLuminance(NORMAL_LUMINANCE); - - if(SystemIsRandSeedSet() == false) - { - // Set default end animation - EndAnimationFadeOut(); - } - else - { - randIndex = rand() % (END_ANIMATION_MAX_RAND_VALUE + 1); - - switch(randIndex) - { - case END_ANIMATION_SQUARES: - EndAnimationSquares(); - break; - - case END_ANIMATION_FADEOUT: - EndAnimationFadeOut(); - break; - - case END_ANIMATION_LINE: - EndAnimationLine(); - break; - - default: - break; - } - } -} - -void EndAnimationFadeOut(void) -{ - uint8_t i; - - while(1) - { - if( GfxGetGlobalLuminance() > 0) - { - GfxSetGlobalLuminance(GfxGetGlobalLuminance() - END_ANIMATION_FADEOUT_STEP); - - GfxSortSprite(&EndAnimationDisplay);; - GfxDrawScene_Slow(); - } - else - { - GsSortCls(0,0,0); - - for(i = 0 ; i < 2 ; i++) - { - // Draw two frames to ensure black display - GfxDrawScene_Slow(); - } - - break; - } - } -} - -void EndAnimationLine(void) -{ - short rectIndex = 0; - - do - { - GfxSortSprite(&EndAnimationDisplay); - - // Draw upper half rectangle - - EndAnimationRect.x = 0; - EndAnimationRect.y = 0; - - EndAnimationRect.w = X_SCREEN_RESOLUTION; - EndAnimationRect.h = rectIndex; - - GsSortRectangle(&EndAnimationRect); - - EndAnimationRect.x = 0; - EndAnimationRect.y = Y_SCREEN_RESOLUTION - rectIndex; - - EndAnimationRect.w = X_SCREEN_RESOLUTION; - EndAnimationRect.h = rectIndex; - - GsSortRectangle(&EndAnimationRect); - - GfxDrawScene_Slow(); - - rectIndex += END_ANIMATION_LINE_STEP; - - }while(rectIndex <= (X_SCREEN_RESOLUTION >> 1) ); - -} - -void EndAnimationSquares(void) -{ - uint16_t i, j, k; - uint16_t randInd = 0; - bool sqPos[END_ANIMATION_SQUARES_TOTAL]; - uint16_t sqCounter = END_ANIMATION_SQUARES_TOTAL; - uint16_t maxIndex = END_ANIMATION_SQUARES_TOTAL_MAX_INDEX; - - EndAnimationRect.w = END_ANIMATION_SQUARES_SIZE; - EndAnimationRect.h = END_ANIMATION_SQUARES_SIZE; - - EndAnimationRect.r = 0; - EndAnimationRect.g = 0; - EndAnimationRect.b = 0; - - memset(sqPos, false , END_ANIMATION_SQUARES_TOTAL); - - for(i = 0; i < END_ANIMATION_SQUARES_TOTAL ; i++) - { - - do - { - randInd = SystemRand(0,maxIndex); - - /*dprintf("randInd = %d\t",randInd); - dprintf("sqPos[randInd] = %d\n", sqPos[randInd]);*/ - - if(sqPos[randInd] == false) - { - sqPos[randInd] = true; - sqCounter--; - - while(sqPos[maxIndex] == true) - { - // Lower maximum value for rand() so that it's - // easier to spot new empty index on next iteration. - maxIndex--; - } - - break; - } - else - { - if(sqCounter == 0) - { - break; - } - } - - }while(1); - - GfxSortSprite(&EndAnimationDisplay); - - if(sqCounter != 0) - { - for(j = 0; j < END_ANIMATION_SQUARES_TOTAL ; j++) - { - if(sqPos[j] == true) - { - EndAnimationRect.x = ((j) << END_ANIMATION_SQUARES_SIZE_BITSHIFT) - - (short)( (j / END_ANIMATION_SQUARES_PER_ROW) * - X_SCREEN_RESOLUTION); - - EndAnimationRect.y = (short) (j/ END_ANIMATION_SQUARES_PER_ROW) << - END_ANIMATION_SQUARES_SIZE_BITSHIFT; - - GsSortRectangle(&EndAnimationRect); - } - } - } - else - { - // Quick fix: draw a full black rectangle instead of multiple squares - for(k = 0 ; k < 2 ; k++) - { - // Draw two frames to ensure black display - GsSortCls(0,0,0); - GfxDrawScene_Slow(); - } - } - - GfxDrawScene_Slow(); - } -} diff --git a/Source/EndAnimation.h b/Source/EndAnimation.h deleted file mode 100644 index edb7b07..0000000 --- a/Source/EndAnimation.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __END_SCREEN_HEADER__ -#define __END_SCREEN_HEADER__ - -/* ************************************** - * Includes * - * **************************************/ - -#include "Global_Inc.h" -#include "Gfx.h" - -/* ************************************** - * Defines * - * **************************************/ - -/* ************************************** - * Global Prototypes * - * **************************************/ - -void EndAnimation(void); - -/* ************************************** - * Global Variables * - * **************************************/ - -#endif // __END_SCREEN_HEADER__ diff --git a/Source/Font.c b/Source/Font.c deleted file mode 100644 index c4b1491..0000000 --- a/Source/Font.c +++ /dev/null @@ -1,194 +0,0 @@ -/* ************************************* - * Includes - * *************************************/ - -#include "Font.h" - -/* ************************************* - * Defines - * *************************************/ - -#define FONT_INTERNAL_TEXT_BUFFER_MAX_SIZE 200 - -/* ************************************* - * Local Prototypes - * *************************************/ - -/* ************************************* - * Local Variables - * *************************************/ - -static char _internal_text[FONT_INTERNAL_TEXT_BUFFER_MAX_SIZE]; -static unsigned char _blend_effect_lum; - -bool FontLoadImage(char* strPath, TYPE_FONT * ptrFont) -{ - if(GfxSpriteFromFile(strPath, &ptrFont->spr) == false) - { - return false; - } - - ptrFont->spr_w = ptrFont->spr.w; - ptrFont->spr_h = ptrFont->spr.h; - ptrFont->spr_u = ptrFont->spr.u; - ptrFont->spr_v = ptrFont->spr.v; - - //Now set default values to font - - ptrFont->char_w = FONT_DEFAULT_CHAR_SIZE; - ptrFont->char_h = FONT_DEFAULT_CHAR_SIZE; - - ptrFont->spr.attribute |= COLORMODE(COLORMODE_4BPP); - ptrFont->spr.attribute &= COLORMODE(~(COLORMODE_8BPP | COLORMODE_16BPP | COLORMODE_24BPP)); - ptrFont->spr.r = NORMAL_LUMINANCE; - ptrFont->spr.g = NORMAL_LUMINANCE; - ptrFont->spr.b = NORMAL_LUMINANCE; - - //At this point, spr.w and spr.h = real w/h - ptrFont->char_per_row = (uint8_t)(ptrFont->spr_w / ptrFont->char_w); - ptrFont->max_ch_wrap = 0; - - ptrFont->spr.w = ptrFont->char_w; - ptrFont->spr.h = ptrFont->char_h; - - ptrFont->flags = FONT_NOFLAGS; - - ptrFont->init_ch = FONT_DEFAULT_INIT_CHAR; - - dprintf("Sprite CX = %d, sprite CY = %d\n",ptrFont->spr.cx, ptrFont->spr.cy); - - return true; -} - -void FontSetInitChar(TYPE_FONT * ptrFont, char c) -{ - ptrFont->init_ch = c; -} - -void FontSetFlags(TYPE_FONT * ptrFont, FONT_FLAGS flags) -{ - ptrFont->flags = flags; -} - -void FontSetSize(TYPE_FONT * ptrFont, short size, short bitshift) -{ - ptrFont->char_w = size; - ptrFont->char_h = size; - - ptrFont->char_w_bitshift = bitshift; - - //At this point, spr.w and spr.h = real w/h - ptrFont->char_per_row = (uint8_t)(ptrFont->spr_w / ptrFont->char_w); - ptrFont->max_ch_wrap = 0; - - ptrFont->spr.w = ptrFont->char_w; - ptrFont->spr.h = ptrFont->char_h; -} - -void FontSetSpacing(TYPE_FONT* ptrFont, short spacing) -{ - ptrFont->char_spacing = spacing; -} - -void FontCyclic(void) -{ - _blend_effect_lum -= 8; -} - -void FontPrintText(TYPE_FONT * ptrFont, short x, short y, char* str, ...) -{ - uint16_t i; - uint16_t line_count = 0; - int result; - short orig_x = x; - - va_list ap; - - va_start(ap, str); - - result = vsnprintf( _internal_text, - FONT_INTERNAL_TEXT_BUFFER_MAX_SIZE, - str, - ap ); - - if(ptrFont->flags & FONT_H_CENTERED) - { - x = (X_SCREEN_RESOLUTION >> 1) - ((result >> 1) << ptrFont->char_w_bitshift); - orig_x = x; - } - - for(i = 0; i < result ; i++) - { - char _ch = _internal_text[i]; - - if(_ch == '\0') - { - // End of string - break; - } - - switch(_ch) - { - case ' ': - x += ptrFont->char_w; - continue; - case '\n': - x = orig_x; - y += ptrFont->char_h; - break; - default: - if( (ptrFont->flags & FONT_WRAP_LINE) && (ptrFont->max_ch_wrap != 0) ) - { - if(++line_count >= ptrFont->max_ch_wrap) - { - line_count = 0; - x = orig_x; - y += ptrFont->char_h; - } - } - - ptrFont->spr.x = x; - ptrFont->spr.y = y; - ptrFont->spr.w = ptrFont->char_w; - ptrFont->spr.h = ptrFont->char_h; - ptrFont->spr.u = (short)( (_ch - ptrFont->init_ch) % ptrFont->char_per_row) * ptrFont->char_w; - ptrFont->spr.u += ptrFont->spr_u; // Add original offset for image - ptrFont->spr.v = (short)( (_ch - ptrFont->init_ch) / ptrFont->char_per_row) * ptrFont->char_h; - ptrFont->spr.v += ptrFont->spr_v; // Add original offset for image - - if(ptrFont->flags & FONT_BLEND_EFFECT) - { - ptrFont->spr.r += 8; - ptrFont->spr.g += 8; - ptrFont->spr.b += 8; - } - else - { - ptrFont->spr.r = NORMAL_LUMINANCE; - ptrFont->spr.g = NORMAL_LUMINANCE; - ptrFont->spr.b = NORMAL_LUMINANCE; - } - /*dprintf("char_w = %d, char_h = %d, char_per_row = %d, init_ch: %c\n", - ptrFont->char_w, - ptrFont->char_h, - ptrFont->char_per_row, - ptrFont->init_ch); - dprintf("Char: %c, spr.u = %d, spr.v = %d\n",str[i],ptrFont->spr.u, ptrFont->spr.v); - dprintf("Sprite CX = %d, sprite CY = %d\n",ptrFont->spr.cx, ptrFont->spr.cy);*/ - //dprintf("Sprite rgb={%d,%d,%d}\n",ptrFont->spr.r, ptrFont->spr.g, ptrFont->spr.b); - - GfxSortSprite(&ptrFont->spr); - x += ptrFont->char_spacing; - break; - } - } - - if(ptrFont->flags & FONT_BLEND_EFFECT) - { - ptrFont->spr.r = _blend_effect_lum; - ptrFont->spr.g = _blend_effect_lum; - ptrFont->spr.b = _blend_effect_lum; - } - - va_end(ap); -} diff --git a/Source/Font.h b/Source/Font.h deleted file mode 100644 index 5a7d6b5..0000000 --- a/Source/Font.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __FONT_HEADER__ -#define __FONT_HEADER__ - -/* ************************************* - * Includes - * *************************************/ - -#include "Global_Inc.h" -#include "System.h" -#include "Gfx.h" -#include "GameStructures.h" -#include - -/* ************************************* - * Defines - * *************************************/ - -#define FONT_DEFAULT_CHAR_SIZE 16 -#define FONT_DEFAULT_INIT_CHAR '!' - -/* ************************************** - * Structs and enums * - * *************************************/ - -/* ************************************* - * Global prototypes - * *************************************/ - -bool FontLoadImage(char* strPath, TYPE_FONT * ptrFont); -void FontSetSize(TYPE_FONT * ptrFont, short size, short bitshift); -void FontPrintText(TYPE_FONT *ptrFont, short x, short y, char* str, ...); -void FontSetInitChar(TYPE_FONT * ptrFont, char c); -void FontSetFlags(TYPE_FONT * ptrFont, FONT_FLAGS flags); -void FontCyclic(void); -void FontSetSpacing(TYPE_FONT* ptrFont, short spacing); - -/* ************************************* - * Global variables - * *************************************/ - -TYPE_FONT RadioFont; -TYPE_FONT SmallFont; - -#endif //__FONT_HEADER__ diff --git a/Source/GameStructures.h b/Source/GameStructures.h deleted file mode 100644 index e092e1d..0000000 --- a/Source/GameStructures.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __GAME_STRUCTURES__HEADER__ -#define __GAME_STRUCTURES__HEADER__ - -/* ************************************* - * Defines - * *************************************/ - -#define CHEAT_ARRAY_SIZE 16 - -/* ************************************* - * Structs and enums - * *************************************/ - -typedef enum t_fontflags -{ - FONT_NOFLAGS = 0, - FONT_CENTERED = 0x01, - FONT_WRAP_LINE = 0x02, - FONT_BLEND_EFFECT = 0x04, - FONT_1HZ_FLASH = 0x08, - FONT_2HZ_FLASH = 0x10, - FONT_H_CENTERED = 0x20 -}FONT_FLAGS; - -typedef struct t_Font -{ - GsSprite spr; - short char_spacing; - short char_w; - short char_w_bitshift; - short char_h; - char init_ch; - uint8_t char_per_row; - uint8_t max_ch_wrap; - FONT_FLAGS flags; - short spr_w; - short spr_h; - short spr_u; - short spr_v; -}TYPE_FONT; - -typedef struct t_Timer -{ - uint32_t time; - uint32_t orig_time; - bool repeat_flag; - bool busy; - void (*Timeout_Callback)(void); -}TYPE_TIMER; - -typedef struct t_Cheat -{ - unsigned short Combination[CHEAT_ARRAY_SIZE]; - void (*Callback)(void); -}TYPE_CHEAT; - -#endif // __GAME_STRUCTURES__HEADER__ diff --git a/Source/Gfx.c b/Source/Gfx.c deleted file mode 100644 index b9ffb63..0000000 --- a/Source/Gfx.c +++ /dev/null @@ -1,552 +0,0 @@ -/* ************************************* - * Includes - * *************************************/ - -#include "Gfx.h" - -/* ************************************* - * Defines - * *************************************/ - -#define PRIMITIVE_LIST_SIZE 0x1000 -#define DOUBLE_BUFFERING_SWAP_Y 256 -#define UPLOAD_IMAGE_FLAG 1 -#define MAX_LUMINANCE 0xFF -#define ROTATE_BIT_SHIFT 12 -#define GPUSTAT (*(unsigned int*)0x1F801814) -#define D2_CHCR (*(unsigned int*)0x1F8010A8) - -/* ************************************* - * Structs and enums - * *************************************/ - -enum -{ - BUTTON_SIZE = 16, - - BUTTON_CROSS_U = 48, - BUTTON_CROSS_V = 0, - - BUTTON_SQUARE_U = 0, - BUTTON_SQUARE_V = 0, - - BUTTON_TRIANGLE_U = 32, - BUTTON_TRIANGLE_V = 0, - - BUTTON_CIRCLE_U = 16, - BUTTON_CIRCLE_V = 0, - - BUTTON_DIRECTION_U = 64, - BUTTON_DIRECTION_V = 0, - - BUTTON_LR_U = 80, - BUTTON_LR_V = 0, - BUTTON_LR_SIZE = 24, - - LETTER_SIZE = 8, - - LETTER_L1_U = 104, - LETTER_L1_V = 0, - - LETTER_L2_U = 112, - LETTER_L2_V = 0, - - LETTER_R1_U = 104, - LETTER_R1_V = 8, - - LETTER_R2_U = 112, - LETTER_R2_V = 8, - - LETTER_OFFSET_INSIDE_BUTTON_LR_X = 8, - LETTER_OFFSET_INSIDE_BUTTON_LR_Y = 6 - -}; - -enum -{ - GFX_SECOND_DISPLAY_X = 384, - GFX_SECOND_DISPLAY_Y = 256, - GFX_SECOND_DISPLAY_TPAGE = 22 -}; - -/* ************************************* - * Global Variables - * *************************************/ - -GsSprite PSXButtons; - -/* ************************************* - * Local Prototypes - * *************************************/ - - - -/* ************************************* - * Local Variables - * *************************************/ - -// Drawing environment -static GsDrawEnv DrawEnv; -// Display environment -static GsDispEnv DispEnv; -// Primitive list (it contains all the graphical data for the GPU) -static unsigned int prim_list[PRIMITIVE_LIST_SIZE]; -// Tells other modules whether data is being loaded to GPU -static volatile bool gfx_busy; -// Dictates (R,G,B) brigthness to all sprites silently -static uint8_t global_lum; -// When true, it draws a rectangle on top of all primitives with -// information for development purposes. -static bool GfxDevMenuEnableFlag; - -void GfxSwapBuffers(void) -{ - // Consistency check -#if PSXSDK_DEBUG - - if(GsListPos() >= PRIMITIVE_LIST_SIZE) - { - dprintf("Linked list iterator overflow!\n"); - while(1); - } - - if( (DrawEnv.h != Y_SCREEN_RESOLUTION) - || - ( (DrawEnv.w != X_SCREEN_RESOLUTION) - && - (DrawEnv.w != X_SCREEN_RESOLUTION >> 1) ) - || - ( (DispEnv.y != DOUBLE_BUFFERING_SWAP_Y) - && - (DispEnv.y != 0) ) ) - { - dprintf("What the hell is happening?\n"); - DEBUG_PRINT_VAR(DispEnv.x); - DEBUG_PRINT_VAR(DispEnv.y); - DEBUG_PRINT_VAR(DrawEnv.x); - DEBUG_PRINT_VAR(DrawEnv.y); - - while(1); - } -#endif // PSXSDK_DEBUG - - if(DrawEnv.h == Y_SCREEN_RESOLUTION) - { - if(DispEnv.y == 0) - { - DispEnv.y = DOUBLE_BUFFERING_SWAP_Y; - DrawEnv.y = 0; - } - else if(DispEnv.y == DOUBLE_BUFFERING_SWAP_Y) - { - DispEnv.y = 0; - DrawEnv.y = DOUBLE_BUFFERING_SWAP_Y; - } - - GsSetDispEnv(&DispEnv); - GsSetDrawEnv(&DrawEnv); - } -} - -void GfxDevMenuEnable(void) -{ - GfxDevMenuEnableFlag = true; -} - -void GfxInitDrawEnv(void) -{ - DrawEnv.x = 0; - DrawEnv.y = 0; - DrawEnv.draw_on_display = false; - DrawEnv.w = X_SCREEN_RESOLUTION; - DrawEnv.h = Y_SCREEN_RESOLUTION; - - GsSetDrawEnv(&DrawEnv); -} - -void GfxInitDispEnv(void) -{ - DispEnv.x = 0; - DispEnv.y = 0; - - GsSetDispEnv(&DispEnv); -} - -void GfxSetPrimitiveList(void) -{ - GsSetList(prim_list); -} - -void GfxDrawScene_Fast(void) -{ - GfxSwapBuffers(); - FontCyclic(); - GsDrawList(); -} - -bool GfxReadyForDMATransfer(void) -{ - return ( (GPUSTAT & 1<<28) && !(D2_CHCR & 1<<24) ); -} - -void GfxDrawScene(void) -{ - while( (SystemRefreshNeeded() == false) - || - (GfxIsGPUBusy() == true) ); - - GfxDrawScene_Fast(); - - SystemCyclicHandler(); -} - -void GfxDrawScene_Slow(void) -{ - GfxDrawScene(); - while(GfxIsGPUBusy() == true); -} - -void GfxSortSprite(GsSprite * spr) -{ - uint8_t aux_r = spr->r; - uint8_t aux_g = spr->g; - uint8_t aux_b = spr->b; - unsigned char aux_tpage = spr->tpage; - short aux_w = spr->w; - short aux_x = spr->x; - - if( (spr->w <= 0) || (spr->h <= 0) ) - { - // Invalid width or heigth - return; - } - - if(GfxIsSpriteInsideScreenArea(spr) == false) - { - return; - } - - if(global_lum != NORMAL_LUMINANCE) - { - if(spr->r < NORMAL_LUMINANCE - global_lum) - { - spr->r = 0; - } - else - { - spr->r -= NORMAL_LUMINANCE - global_lum; - } - - if(spr->g < NORMAL_LUMINANCE - global_lum) - { - spr->g = 0; - } - else - { - spr->g -= NORMAL_LUMINANCE - global_lum; - } - - if(spr->b < NORMAL_LUMINANCE - global_lum) - { - spr->b = 0; - } - else - { - spr->b -= NORMAL_LUMINANCE - global_lum; - } - } - - if(spr->w > MAX_SIZE_FOR_GSSPRITE) - { - // GsSprites can't be bigger than 256x256, so since display - // resolution is 384x240, it must be split into two primitives. - - spr->w = MAX_SIZE_FOR_GSSPRITE; - GsSortSprite(spr); - - spr->x += MAX_SIZE_FOR_GSSPRITE; - spr->w = X_SCREEN_RESOLUTION - MAX_SIZE_FOR_GSSPRITE; - spr->tpage += MAX_SIZE_FOR_GSSPRITE / GFX_TPAGE_WIDTH; - GsSortSprite(spr); - - // Restore original values after sorting - spr->w = aux_w; - spr->tpage = aux_tpage; - spr->x = aux_x; - } - else - { - GsSortSprite(spr); - } - - spr->r = aux_r; - spr->g = aux_g; - spr->b = aux_b; -} - -uint8_t GfxGetGlobalLuminance(void) -{ - return global_lum; -} - -void GfxSetGlobalLuminance(uint8_t value) -{ - global_lum = value; -} - -void GfxIncreaseGlobalLuminance(int8_t step) -{ - if( ( (global_lum + step) < MAX_LUMINANCE ) - && - ( (global_lum + step) > 0 ) ) - { - global_lum += step; - } - else - { - global_lum = MAX_LUMINANCE; - } -} - -int GfxRotateFromDegrees(int deg) -{ - return deg << ROTATE_BIT_SHIFT; -} - -bool GfxIsGPUBusy(void) -{ - return (GsIsDrawing() || gfx_busy || (GfxReadyForDMATransfer() == false) ); -} - -bool GfxSpriteFromFile(char* fname, GsSprite * spr) -{ - GsImage gsi; - - if(SystemLoadFile(fname) == false) - { - return false; - } - - while(GfxIsGPUBusy() == true); - - gfx_busy = true; - - GsImageFromTim(&gsi,SystemGetBufferAddress() ); - - GsSpriteFromImage(spr,&gsi,UPLOAD_IMAGE_FLAG); - gfx_busy = false; - - DEBUG_PRINT_VAR(spr->tpage); - DEBUG_PRINT_VAR(spr->u); - DEBUG_PRINT_VAR(spr->v); - DEBUG_PRINT_VAR(spr->w); - DEBUG_PRINT_VAR(spr->h); - - return true; -} - -bool GfxCLUTFromFile(char* fname) -{ - GsImage gsi; - - if(SystemLoadFile(fname) == false) - { - return false; - } - - while(GfxIsGPUBusy() == true); - - gfx_busy = true; - - GsImageFromTim(&gsi,SystemGetBufferAddress() ); - - GsUploadCLUT(&gsi); - - gfx_busy = false; - - return true; -} - -bool GfxIsInsideScreenArea(short x, short y, short w, short h) -{ - if( ( (x + w) >= 0) - && - (x < DrawEnv.w) - && - ( (y + h) >= 0) - && - (y < DrawEnv.h) ) - { - return true; - } - - return false; -} - -bool GfxIsSpriteInsideScreenArea(GsSprite * spr) -{ - return GfxIsInsideScreenArea(spr->x, spr->y, spr->w, spr->h); -} - -void GfxButtonSetFlags(uint8_t flags) -{ - PSXButtons.attribute |= flags; -} - -void GfxButtonRemoveFlags(uint8_t flags) -{ - PSXButtons.attribute &= ~flags; -} - -void GfxDrawButton(short x, short y, unsigned short btn) -{ - static bool first_entered = true; - static short orig_u; - static short orig_v; - - if(first_entered == true) - { - first_entered = false; - orig_u = PSXButtons.u; - orig_v = PSXButtons.v; - } - - PSXButtons.w = BUTTON_SIZE; - PSXButtons.h = BUTTON_SIZE; - - PSXButtons.r = NORMAL_LUMINANCE; - PSXButtons.g = NORMAL_LUMINANCE; - PSXButtons.b = NORMAL_LUMINANCE; - - PSXButtons.x = x; - PSXButtons.y = y; - PSXButtons.mx = PSXButtons.w >> 1; - PSXButtons.my = PSXButtons.h >> 1; - - switch(btn) - { - case PAD_CROSS: - PSXButtons.u = BUTTON_CROSS_U; - PSXButtons.v = BUTTON_CROSS_V; - break; - - case PAD_SQUARE: - PSXButtons.u = BUTTON_SQUARE_U; - PSXButtons.v = BUTTON_SQUARE_V; - break; - - case PAD_TRIANGLE: - PSXButtons.u = BUTTON_TRIANGLE_U; - PSXButtons.v = BUTTON_TRIANGLE_V; - break; - - case PAD_CIRCLE: - PSXButtons.u = BUTTON_CIRCLE_U; - PSXButtons.v = BUTTON_CIRCLE_V; - break; - - case PAD_RIGHT: - PSXButtons.u = BUTTON_DIRECTION_U; - PSXButtons.v = BUTTON_DIRECTION_V; - break; - - case PAD_UP: - PSXButtons.u = BUTTON_DIRECTION_U; - PSXButtons.v = BUTTON_DIRECTION_V; - PSXButtons.rotate = 90 << ROTATE_BIT_SHIFT; - break; - - case PAD_DOWN: - PSXButtons.u = BUTTON_DIRECTION_U; - PSXButtons.v = BUTTON_DIRECTION_V; - PSXButtons.rotate = 270 << ROTATE_BIT_SHIFT; - break; - - case PAD_LEFT: - PSXButtons.u = BUTTON_DIRECTION_U; - PSXButtons.v = BUTTON_DIRECTION_V; - PSXButtons.attribute |= H_FLIP; - break; - - case PAD_L1: - // Fall through - case PAD_L2: - // Fall through - case PAD_R1: - // Fall through - case PAD_R2: - PSXButtons.u = BUTTON_LR_U; - PSXButtons.v = BUTTON_LR_V; - PSXButtons.w = BUTTON_LR_SIZE; - break; - - case PAD_SELECT: - // Fall through - case PAD_START: - // Fall through - default: - // Set null width and height so that sprite doesn't get sorted - PSXButtons.w = 0; - PSXButtons.h = 0; - break; - } - - PSXButtons.u += orig_u; - PSXButtons.v += orig_v; - - GfxSortSprite(&PSXButtons); - - PSXButtons.attribute &= ~H_FLIP; - PSXButtons.rotate = 0; -} - -void GfxSaveDisplayData(GsSprite *spr) -{ - while(GfxIsGPUBusy() == true); - - MoveImage( DispEnv.x, - DispEnv.y, - GFX_SECOND_DISPLAY_X, - GFX_SECOND_DISPLAY_Y, - X_SCREEN_RESOLUTION, - Y_SCREEN_RESOLUTION); - - spr->x = 0; - spr->y = 0; - spr->tpage = GFX_SECOND_DISPLAY_TPAGE; - spr->attribute |= COLORMODE(COLORMODE_16BPP); - spr->w = X_SCREEN_RESOLUTION; - spr->h = Y_SCREEN_RESOLUTION; - spr->u = 0; - spr->v = 0; - spr->r = NORMAL_LUMINANCE; - spr->g = NORMAL_LUMINANCE; - spr->b = NORMAL_LUMINANCE; - - while(GfxIsGPUBusy() == true); -} - -bool GfxTPageOffsetFromVRAMPosition(GsSprite * spr, short x, short y) -{ - if( (x >= VRAM_W) || (x < 0) || (y >= VRAM_H) || (y < 0) ) - { - return false; - } - - spr->tpage = x / GFX_TPAGE_WIDTH; - spr->tpage += (short)(VRAM_W / GFX_TPAGE_WIDTH) * (short)(y / GFX_TPAGE_HEIGHT); - - spr->u = (x % GFX_TPAGE_WIDTH); - - if(spr->attribute & COLORMODE(COLORMODE_8BPP)) - { - // On 8bpp images, it looks like U offset needs to be multiplied by 2. - spr->u <<= 1; - } - - spr->v = (y % GFX_TPAGE_HEIGHT); - - //dprintf("Sprite:\n\tTPAGE: %d\n\tU=%d\n\tV=%d\n",spr->tpage,spr->u, spr->v); - - return false; -} diff --git a/Source/Gfx.h b/Source/Gfx.h deleted file mode 100644 index b2b8295..0000000 --- a/Source/Gfx.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef __GFX_HEADER__ -#define __GFX_HEADER__ - -/* ************************************* - * Includes - * *************************************/ - -#include "Global_Inc.h" -#include "System.h" - - - -/* ************************************* - * Defines - * *************************************/ - -#define X_SCREEN_RESOLUTION 384 -#define Y_SCREEN_RESOLUTION 240 -#define VRAM_W 1024 -#define VRAM_H 512 -#define MAX_SIZE_FOR_GSSPRITE 256 -#define GFX_TPAGE_WIDTH 64 -#define GFX_TPAGE_HEIGHT 256 -#define GFX_1HZ_FLASH (1<<7) -#define GFX_2HZ_FLASH (1<<8) -#define FULL_LUMINANCE 0xFF - -/* ************************************* - * Global prototypes - * *************************************/ - -void GfxInitDrawEnv(void); -void GfxInitDispEnv(void); -void GfxSetPrimitiveList(void); - -// Renders new scene. Use this function unless you know what you are doing! -void GfxDrawScene(void); - -// Blocking version. Calls GfxDrawScene() and then adds a while(GfxIsBusy() ) -// after it. -void GfxDrawScene_Slow(void); - -void GfxDrawScene_NoSwap(void); - -void GfxSwapBuffers(void); - -// Only renders screen and does not update any pad data or timer data. -// To be used in ISR! -void GfxDrawScene_Fast(void); - -// Repotedly, tells is GPU is ready for a DMA transfer. -bool GfxReadyForDMATransfer(void); - -// Fills a GsSprite structure with information from a TIM file. -bool GfxSpriteFromFile(char* fname, GsSprite * spr); - -// Reportedly, loads CLUT data from a TIM image (image data is discarded) -bool GfxCLUTFromFile(char* fname); - -// Returns true if current object is within screen limits, false otherwise. -bool GfxIsInsideScreenArea(short x, short y, short w, short h); - -// Function overload for GsSprite structures. -bool GfxIsSpriteInsideScreenArea(GsSprite * spr); - -// Used to know whether GPU operation can be done. -bool GfxIsGPUBusy(void); - -// Draws a sprite on screen. First, it checks whether sprite is inside -// screen limits. -void GfxSortSprite(GsSprite * spr); - -uint8_t GfxGetGlobalLuminance(void); - -void GfxSetGlobalLuminance(uint8_t value); - -void GfxIncreaseGlobalLuminance(int8_t step); - -void GfxButtonSetFlags(uint8_t flags); - -void GfxButtonRemoveFlags(uint8_t flags); - -int GfxRotateFromDegrees(int deg); - -void GfxDrawButton(short x, short y, unsigned short btn); - -// Sends current display data on a specific VRAM section and fills -// sprite structure pointed to by "spr". -void GfxSaveDisplayData(GsSprite *spr); - -// Fills GsSprite structure pointed to by "spr" with texture page and U/V -// offset data given a position in VRAM. -bool GfxTPageOffsetFromVRAMPosition(GsSprite * spr, short x, short y); - -void GfxSetSplitScreen(uint8_t playerIndex); - -void GfxDisableSplitScreen(void); - -void GfxDrawScene_NoSwap(void); - -void GfxDevMenuEnable(void); - -/* ************************************* - * Global variables - * *************************************/ - -extern GsSprite PSXButtons; - -#endif //__GFX_HEADER__ diff --git a/Source/Global_Inc.h b/Source/Global_Inc.h deleted file mode 100644 index 0c8f446..0000000 --- a/Source/Global_Inc.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __GLOBAL_INC__H__ -#define __GLOBAL_INC__H__ - -/* ************************************* - * Includes - * *************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* ************************************* - * Defines - * *************************************/ - -#define REFRESH_FREQUENCY 50 //50 Hz PAL / 60 Hz NTSC -#define DEBUG_PRINT_VAR(var) dprintf(#var " = %d\n", var); - -#ifndef bool - typedef enum - { - false = 0, - true = 1 - }bool; -#endif - -#if (PSXSDK_VERSION != 0x0599) -#error "Wrong PSXSDK version! Please use version 0.5.99." -#endif - -/* Test for GCC > 5.2.0 */ -#if ( (__GNUC__ != 5) || (__GNUC_MINOR__ != 2) || (__GNUC_PATCHLEVEL__ != 0) ) -#error "Wrong GCC version! Please use version 5.2.0." -#endif - -#endif // __GLOBAL_INC__H__ diff --git a/Source/LoadMenu.c b/Source/LoadMenu.c deleted file mode 100644 index ba8efaf..0000000 --- a/Source/LoadMenu.c +++ /dev/null @@ -1,204 +0,0 @@ -/* ************************************** - * Includes * - * *************************************/ - -#include "LoadMenu.h" - -/* ************************************** - * Defines * - * *************************************/ - -/* ************************************** - * Structs and enums * - * *************************************/ - -enum -{ - SMALL_FONT_SIZE = 8, - SMALL_FONT_SIZE_BITSHIFT = 3, - SMALL_FONT_SPACING = 6 -}; - -enum -{ - BG_BLUE_TARGET_VALUE = 0xC0, - BG_WHITE_TARGET_VALUE = /*0x40*/ 0, - BG_INCREASE_STEP = 0x10 -}; - -enum -{ - LOADING_BAR_X = 64, - LOADING_BAR_Y = 200, - LOADING_BAR_N_LINES = 4, - - LOADING_BAR_WIDTH = 256, - LOADING_BAR_HEIGHT = 16, - - LOADING_BAR_LUMINANCE_TARGET = NORMAL_LUMINANCE, - LOADING_BAR_LUMINANCE_STEP = 10 -}; - -enum -{ - LOADING_TITLE_CLUT_X = 384, - LOADING_TITLE_CLUT_Y = 496, - LOADING_TITLE_X = 128, - LOADING_TITLE_Y = 32, - - LOADING_TITLE_U = 0, - LOADING_TITLE_V = 0, - - LOADING_TITLE_LUMINANCE_STEP = 10, - LOADING_TITLE_LUMINANCE_TARGET = NORMAL_LUMINANCE -}; - -enum -{ - PLANE_START_X = 56, - PLANE_START_Y = 200, - - PLANE_U = 0, - PLANE_V = 32, - PLANE_SIZE = 16, - - PLANE_LUMINANCE_STEP = 0x10, - PLANE_LUMINANCE_TARGET_VALUE = NORMAL_LUMINANCE -}; - -/* ************************************* - * Local Prototypes - * *************************************/ - -static void LoadMenuLoadFileList( char* fileList[], void * dest[], - uint8_t szFileList, uint8_t szDestList); - -/* ************************************* - * Local Variables - * *************************************/ - -static char* LoadMenuFiles[] = { "cdrom:\\DATA\\FONTS\\FONT_2.FNT;1" }; - -static void * LoadMenuDest[] = { (TYPE_FONT*)&SmallFont }; - -static char* strCurrentFile; - -// Flags to communicate with ISR state -// * startup_flag: background fades in from black to blue. -// * end_flag: tells the background to fade out to black. -// * isr_ended: background has totally faded out to black. -// * isr_started: tells the ISR has finished starting up. -static volatile bool startup_flag; -static volatile bool isr_started; -static volatile bool end_flag; -static volatile bool isr_ended; -// Set to true when LoadMenuInit() has been called, and set to false -// once LoadMenuEnd() is called. -// It's used when multiple modules call LoadMenu() at the same time, -// so load menu does not have to be initialised each time; -static bool load_menu_running; - -void LoadMenuInit(void) -{ - static bool first_load = false; - - if(first_load == false) - { - first_load = true; - LoadMenuLoadFileList( LoadMenuFiles, - LoadMenuDest, - sizeof(LoadMenuFiles) / sizeof(char*), - sizeof(LoadMenuDest) / sizeof(void*)); - } - - FontSetSize(&SmallFont, SMALL_FONT_SIZE, SMALL_FONT_SIZE_BITSHIFT); - FontSetSpacing(&SmallFont, SMALL_FONT_SPACING); - - SmallFont.spr.r = 0; - SmallFont.spr.g = 0; - SmallFont.spr.b = 0; - - GfxSetGlobalLuminance(NORMAL_LUMINANCE); -} - -void LoadMenu( char* fileList[], - void * dest[], - uint8_t szFileList , uint8_t szDestList) -{ - - if(load_menu_running == false) - { - LoadMenuInit(); - } - - LoadMenuLoadFileList(fileList,dest,szFileList,szDestList); -} - -void LoadMenuLoadFileList( char* fileList[], void * dest[], - uint8_t szFileList, uint8_t szDestList) -{ - char aux_file_name[100]; - char* extension; - uint8_t fileLoadedCount; - - if(szFileList != szDestList) - { - dprintf("File list size different from dest list size! %d vs %d\n", - szFileList, szDestList); - return; - } - - for(fileLoadedCount = 0; fileLoadedCount < szFileList ; fileLoadedCount++) - { - if(fileList[fileLoadedCount] == NULL) - { - continue; - } - - strCurrentFile = fileList[fileLoadedCount]; - - //dprintf("Files %d / %d loaded. New plane X = %d.\n",fileLoadedCount,szFileList,LoadMenuPlaneSpr.x); - - // Backup original file path - strncpy(aux_file_name,fileList[fileLoadedCount],100); - - //We want to get file extension, so split into tokens - strtok(fileList[fileLoadedCount],".;"); - extension = strtok(NULL,".;"); - - dprintf("File extension: .%s\n",extension); - //Restore original file path in order to load file - strncpy(fileList[fileLoadedCount],aux_file_name,100); - - if(strncmp(extension,"TIM",3) == 0) - { - if(GfxSpriteFromFile(fileList[fileLoadedCount], dest[fileLoadedCount]) == false) - { - dprintf("Could not load image file \"%s\"!\n",fileList[fileLoadedCount]); - } - } - else if(strncmp(extension,"CLT",3) == 0) - { - if(dest[fileLoadedCount] != NULL) - { - dprintf("WARNING: File %s linked to non-NULL destination pointer!\n", dest[fileLoadedCount]); - } - - if(GfxCLUTFromFile(fileList[fileLoadedCount]) == false) - { - dprintf("Could not load CLUT file \"%s\"!\n",fileList[fileLoadedCount]); - } - } - else if(strncmp(extension,"FNT",3) == 0) - { - if(FontLoadImage(fileList[fileLoadedCount], dest[fileLoadedCount]) == false) - { - dprintf("Could not load font file \"%s\"!\n",fileList[fileLoadedCount]); - } - } - else - { - dprintf("LoadMenu does not recognize following extension: %s\n",extension); - } - } -} diff --git a/Source/LoadMenu.h b/Source/LoadMenu.h deleted file mode 100644 index 8afc373..0000000 --- a/Source/LoadMenu.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __LOAD_MENU_HEADER__ -#define __LOAD_MENU_HEADER__ - -/* ************************************* - * Includes - * *************************************/ - -#include "Global_Inc.h" -#include "Gfx.h" -#include "System.h" -#include "Font.h" - -/* ************************************* - * Defines - * *************************************/ - -/* ************************************* - * Global prototypes - * *************************************/ - -void LoadMenuInit(void); - -void LoadMenu( char* fileList[], - void * dest[], - uint8_t szFileList , uint8_t szDestList); - -void LoadMenuEnd(void); - -#endif //__LOAD_MENU_HEADER__ diff --git a/Source/Makefile b/Source/Makefile deleted file mode 100644 index f20974f..0000000 --- a/Source/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -CC = psxsdkserial-gcc -DEFINE= -D_PAL_MODE_ -DEFINE += -DPSXSDK_DEBUG -LIBS=-lfixmath -CC_FLAGS = -Wall -Werror -c -Os -Wfatal-errors -g -LINKER = psxsdkserial-gcc - -PROJECT = OPENSEND -PROJECT_DIR = ~/OpenSend - -INIT_ADDR=0x801A0000 - -ELF2EXE = elf2exe -ELF2EXE_FLAGS = -mark="Open-source PSX-EXE loader created with PSXSDK" -init_addr=$(INIT_ADDR) -LICENSE_FILE = /usr/local/psxsdk/share/licenses/infoeur.dat - -PSXSDK_DIR = /usr/local/psxsdk/bin - -EMULATOR_DIR = ~/pcsxr -EMULATOR = pcsxr.exe -SOUND_INTERFACE = -EMULATOR_FLAGS = -nogui -psxout -OBJ_DIR = Obj -SRC_DIR = . -MUSIC_TRACKS = -#FFMPEG = ffmpeg -#FFMPEG_DIR = ../Music/ffmpeg/bin -#FFMPEG_FLAGS = -f s16le -acodec pcm_s16le - -GNU_SIZE = mipsel-unknown-elf-size - -all: build image clean -#emulator clean - -rebuild: remove build - -build: clean objects $(PROJECT).elf $(PROJECT).exe - -objects: $(addprefix $(OBJ_DIR)/,main.o System.o Gfx.o \ - LoadMenu.o EndAnimation.o \ - Font.o Serial.o) - -remove: - rm -f Obj/*.o - -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c - $(CC) $< -o $@ $(DEFINE) $(CC_FLAGS) - -$(PROJECT).elf: - $(LINKER) Obj/*.o -o Exe/$(PROJECT).elf $(LIBS) -Wl,--gc-sections - -$(PROJECT).exe: - $(ELF2EXE) Exe/$(PROJECT).elf Exe/$(PROJECT).exe $(ELF2EXE_FLAGS) - cp Exe/$(PROJECT).exe ../cdimg - -image: - rm -f $(PROJECT).iso $(PROJECT).bin - rm -f $(PROJECT).cue - mkisofs -o $(PROJECT).iso -V $(PROJECT) -sysid PLAYSTATION ../cdimg - mkpsxiso $(PROJECT).iso $(PROJECT).bin $(LICENSE_FILE) - mv $(PROJECT).bin ../Bin - mv $(PROJECT).cue ../Bin - rm -f $(PROJECT).cue - rm -f $(PROJECT).iso - $(GNU_SIZE) Exe/$(PROJECT).elf - -emulator: - export PATH=$$PATH:$(EMULATOR_DIR) - $(EMULATOR) -cdfile $(PROJECT_DIR)/Bin/$(PROJECT).bin $(EMULATOR_FLAGS) - -clean: - rm -f $(PROJECT).elf cdimg/$(PROJECT).exe $(PROJECT).bin $(PROJECT).cue cdimg/README.txt - rm -f $(PROJECT).iso $(PROJECT).exe $(PROJECT).elf - diff --git a/Source/Serial.c b/Source/Serial.c deleted file mode 100644 index 2e2a1a4..0000000 --- a/Source/Serial.c +++ /dev/null @@ -1,278 +0,0 @@ -/* ************************************* - * Includes - * *************************************/ - -#include "Serial.h" - -/* ************************************* - * Defines - * *************************************/ - -#define SERIAL_BAUDRATE 115200 -#define SERIAL_TX_RX_TIMEOUT 20000 -#define SERIAL_RX_FIFO_EMPTY 0 -#define SERIAL_TX_NOT_READY 0 - -/* ************************************* - * Local Variables - * *************************************/ - -static volatile SERIAL_STATE SerialState; -static volatile size_t bytesRead; -static volatile uint32_t initPC_Address; -static volatile uint32_t RAMDest_Address; -static volatile size_t ExeSize; -static volatile size_t totalBytes; -static volatile size_t exeBytesRead; -static volatile bool serial_busy; - -/* ************************************* - * Local Prototypes - * *************************************/ - -void ISR_Serial(void) -{ - enum - { - SERIAL_BG_X0 = 0, - SERIAL_BG_X1 = X_SCREEN_RESOLUTION - SERIAL_BG_X0, - SERIAL_BG_X2 = SERIAL_BG_X0, - SERIAL_BG_X3 = SERIAL_BG_X1, - - SERIAL_BG_Y0 = 0, - SERIAL_BG_Y1 = SERIAL_BG_Y0, - SERIAL_BG_Y2 = Y_SCREEN_RESOLUTION - SERIAL_BG_Y0, - SERIAL_BG_Y3 = SERIAL_BG_Y2, - - SERIAL_BG_R = 0, - SERIAL_BG_G = NORMAL_LUMINANCE, - SERIAL_BG_B = NORMAL_LUMINANCE, - }; - - static GsGPoly4 SerialBg = { .x[0] = SERIAL_BG_X0, - .x[1] = SERIAL_BG_X1, - .x[2] = SERIAL_BG_X2, - .x[3] = SERIAL_BG_X3, - - .y[0] = SERIAL_BG_Y0, - .y[1] = SERIAL_BG_Y1, - .y[2] = SERIAL_BG_Y2, - .y[3] = SERIAL_BG_Y3, - - .r[0] = 0, - .r[1] = 0, - .r[2] = SERIAL_BG_R, - .r[3] = SERIAL_BG_R, - - .g[0] = 0, - .g[1] = 0, - .g[2] = SERIAL_BG_G, - .g[3] = SERIAL_BG_G, - - .b[0] = 0, - .b[1] = 0, - .b[2] = SERIAL_BG_B, - .b[3] = SERIAL_BG_B, }; - - enum - { - SERIAL_STATE_TEXT_X = 148, - SERIAL_STATE_TEXT_Y = Y_SCREEN_RESOLUTION >> 1, - }; - - SystemIncreaseGlobalTimer(); - - if( (GfxIsGPUBusy() == true) || (SystemIsBusy() == true) ) - { - return; - } - - FontSetFlags(&SmallFont, FONT_BLEND_EFFECT | FONT_H_CENTERED); - - if(SerialState == SERIAL_STATE_READING_EXE_DATA) - { - if(System1SecondTick() == false) - { - return; - } - else - { - FontSetFlags(&SmallFont, FONT_H_CENTERED); - } - } - - GsSortGPoly4(&SerialBg); - - switch(SerialState) - { - case SERIAL_STATE_INIT: - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Serial initialization"); - break; - - case SERIAL_STATE_STANDBY: - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Waiting for PC..."); - break; - - case SERIAL_STATE_WRITING_ACK: - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Writing ACK"); - break; - - case SERIAL_STATE_READING_HEADER: - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Reading data from header (%d/%d bytes)...", bytesRead, totalBytes); - break; - - case SERIAL_STATE_READING_EXE_SIZE: - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Getting PSX-EXE size from PC..."); - break; - - case SERIAL_STATE_READING_EXE_DATA: - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Reading PSX-EXE data (%d/%d bytes)...", exeBytesRead, ExeSize); - break; - - case SERIAL_STATE_WAITING_USER_INPUT: - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Press any key to continue"); - break; - - case SERIAL_STATE_CLEANING_MEMORY: - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Cleaning RAM before EXE data transfer..."); - break; - - default: - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Unknown state"); - break; - } - - FontSetFlags(&SmallFont, FONT_H_CENTERED); - - if(RAMDest_Address != 0) - { - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y + 16, "RAM Dest address: 0x%08X", RAMDest_Address); - } - - if(initPC_Address != 0) - { - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y + 32, "Init PC address: 0x%08X", initPC_Address); - } - - if(ExeSize != 0) - { - FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y + 48, "PSX-EXE size: 0x%08X", ExeSize); - } - - GfxDrawScene_Fast(); -} - -void SerialSetState(SERIAL_STATE state) -{ - SerialState = state; -} - -void SerialSetPCAddress(uint32_t addr) -{ - initPC_Address = addr; -} - -void SerialSetRAMDestAddress(uint32_t addr) -{ - RAMDest_Address = addr; -} - -void SerialSetExeSize(size_t size) -{ - ExeSize = size; -} - -void SerialInit(void) -{ - uint8_t receivedBytes; - - SetVBlankHandler(&ISR_Serial); - - SerialState = SERIAL_STATE_INIT; - - SIOStart(SERIAL_BAUDRATE); - - SerialState = SERIAL_STATE_STANDBY; - - // ------------------------------------ - // Protocol description - // ------------------------------------ - - // 1. Wait to receive magic byte "99" from PC. - - SerialRead(&receivedBytes, sizeof(uint8_t) ); - - if(receivedBytes != 99) - { - dprintf("Did not receive input magic number!\n"); - return; - } - - // 2. Send ACK (magic byte is ASCII code for 'b'). - - SerialState = SERIAL_STATE_WRITING_ACK; - - SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t) ); -} - -void SerialSetExeBytesReceived(uint32_t bytes_read) -{ - exeBytesRead += bytes_read; -} - -bool SerialRead(uint8_t* ptrArray, size_t nBytes) -{ - bytesRead = 0; - totalBytes = nBytes; - - serial_busy = true; - - if(nBytes == 0) - { - SerialWrite("SerialRead: invalid size %d\n", strnlen("SerialRead: invalid size %d\n", 30)); - return false; - } - - do - { - //uint16_t timeout = SERIAL_TX_RX_TIMEOUT; - - while( (SIOCheckInBuffer() == SERIAL_RX_FIFO_EMPTY)); // Wait for RX FIFO not empty - - *(ptrArray++) = SIOReadByte(); - bytesRead++; - }while(--nBytes); - - serial_busy = false; - - return true; -} - -bool SerialWrite(void* ptrArray, size_t nBytes) -{ - serial_busy = true; - - SystemDisableVBlankInterrupt(); - - if(nBytes == 0) - { - SerialWrite("SerialRead: invalid size %d\n", strnlen("SerialRead: invalid size %d\n", 30)); - return false; - } - - do - { - //uint16_t timeout = SERIAL_TX_RX_TIMEOUT; - - while( (SIOCheckOutBuffer() == SERIAL_TX_NOT_READY)); // Wait for TX FIFO empty. - - SIOSendByte(*(uint8_t*)ptrArray++); - - }while(--nBytes); - - SystemEnableVBlankInterrupt(); - - serial_busy = false; - - return true; -} diff --git a/Source/Serial.h b/Source/Serial.h deleted file mode 100644 index da2c4ce..0000000 --- a/Source/Serial.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __SERIAL_HEADER__ -#define __SERIAL_HEADER__ - -/* ************************************* - * Includes - * *************************************/ - -#include "Global_Inc.h" -#include "System.h" -#include "Gfx.h" -#include "Font.h" - -/* ************************************* - * Defines - * *************************************/ - -#define ACK_BYTE_STRING "b" - -/* ************************************** - * Structs and enums * - * *************************************/ - -typedef enum -{ - SERIAL_STATE_INIT = 0, - SERIAL_STATE_STANDBY, - SERIAL_STATE_WRITING_ACK, - SERIAL_STATE_READING_HEADER, - SERIAL_STATE_READING_EXE_SIZE, - SERIAL_STATE_READING_EXE_DATA, - SERIAL_STATE_WAITING_USER_INPUT, - SERIAL_STATE_CLEANING_MEMORY, -}SERIAL_STATE; - -/* ************************************* - * Global prototypes - * *************************************/ - -void SerialInit(void); -bool SerialRead(uint8_t* ptrArray, size_t nBytes); -bool SerialWrite(void* ptrArray, size_t nBytes); -void ISR_Serial(void); -void SerialSetState(SERIAL_STATE state); -void SerialSetPCAddress(uint32_t addr); -void SerialSetRAMDestAddress(uint32_t addr); -void SerialSetExeSize(size_t size); -void SerialSetExeBytesReceived(uint32_t bytes_read); - -#endif // __SERIAL_HEADER__ diff --git a/Source/System.c b/Source/System.c deleted file mode 100644 index 852fea1..0000000 --- a/Source/System.c +++ /dev/null @@ -1,493 +0,0 @@ -/* ************************************* - * Includes - * *************************************/ - -#include "System.h" - -/* ************************************* - * Defines - * *************************************/ - -#define SYSTEM_MAX_TIMERS 16 -#define FILE_BUFFER_SIZE 0xC40 -#define END_STACK_PATTERN (uint32_t) 0x18022015 -#define BEGIN_STACK_ADDRESS (uint32_t*) 0x801FFF00 -#define STACK_SIZE 0x1000 -#define I_MASK (*(volatile unsigned int*)0x1F801074) - -/* ************************************* - * Local Prototypes - * *************************************/ - -static void SystemSetStackPattern(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; -//Critical section is entered (i.e.: when accessing fopen() or other BIOS functions -static volatile bool system_busy; - -/* ******************************************************************* - * - * @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(); - //Set Drawing Environment - GfxInitDrawEnv(); - //Set Display Environment - GfxInitDispEnv(); - //Set Primitive List - GfxSetPrimitiveList(); - //Initial value for system_busy - system_busy = false; - - GfxSetGlobalLuminance(NORMAL_LUMINANCE); - - SystemSetStackPattern(); -} - -size_t SystemGetBufferSize(void) -{ - return sizeof(file_buffer); -} - -/* ******************************************************************* - * - * @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 !(global_timer % REFRESH_FREQUENCY); -} - -/* **************************************************************************************** - * - * @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, uint32_t init_pos, 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, init_pos, 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, init_pos, 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; -} - -void SystemSetBusyFlag(bool value) -{ - system_busy = value; -} - -/* **************************************************************************************** - * - * @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,0,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 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 volatile bool SystemIsBusy(void) - * - * @author: Xavier Del Campo - * - * @return: returns system busy flag. - * - * ***********************************************************************/ - -volatile bool SystemIsBusy(void) -{ - return system_busy; -} - -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; -} -void SystemCyclicHandler(void) -{ - SystemDisableScreenRefresh(); - SystemCheckStack(); -} - -void SystemDisableVBlankInterrupt(void) -{ - I_MASK &= ~(0x00000001); -} - -void SystemEnableVBlankInterrupt(void) -{ - I_MASK |= (0x00000001); -} diff --git a/Source/System.h b/Source/System.h deleted file mode 100644 index 2994366..0000000 --- a/Source/System.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef __SYSTEM_HEADER__ -#define __SYSTEM_HEADER__ - -/* ************************************** - * Includes * - * **************************************/ - -#include "Global_Inc.h" -#include "Gfx.h" -#include "Serial.h" - -/* ************************************** - * Defines * - * **************************************/ - -#define TIMER_PRESCALER_1_SECOND 10 -#define TIMER_PRESCALER_1_MINUTE (TIMER_PRESCALER_1_SECOND * 60) - -/* ************************************** - * Global Prototypes * - * **************************************/ - -// Calls PSXSDK init routines -void SystemInit(void); - -// Sets default VSync (only sets flag to true and increases global_timer) -void ISR_SystemDefaultVBlank(void); - -void SystemSetBusyFlag(bool value); - -// Calls srand() using current global_timer value as seed -void SystemSetRandSeed(void); - -// Returns VSync flag value -bool SystemRefreshNeeded(void); - -// Loads a file into system's internal buffer -bool SystemLoadFile(char*fname); - -// Loads a file into desired buffer -bool SystemLoadFileToBuffer(char* fname, uint32_t init_pos, uint8_t* buffer, uint32_t szBuffer); - -// Clears VSync flag after each frame -void SystemDisableScreenRefresh(void); - -// Returns file buffer address -uint8_t* SystemGetBufferAddress(void); - -// Tells whether srand() has been called using a pseudo-random value -bool SystemIsRandSeedSet(void); - -// Stops program flow during X cycles -void SystemWaitCycles(uint32_t cycles); - -// 1 cycle-length flag with a frequency of 1 Hz -bool System1SecondTick(void); - -// 1 cycle-length flag with a frequency of 2 Hz -bool System500msTick(void); - -// 1 cycle-length flag with a frequency of 10 Hz -bool System100msTick(void); - -// Returns random value between given minimum and maximum values -uint32_t SystemRand(uint32_t min, uint32_t max); - -// Increases global timer by 1 step -void SystemIncreaseGlobalTimer(void); - -// Sets value to emergency mode flag -void SystemSetEmergencyMode(bool value); - -// Returns emergency mode flag state -bool SystemGetEmergencyMode(void); - -// (Experimental) -uint64_t SystemGetGlobalTimer(void); - -// Returns whether critical section of code is being entered -volatile bool SystemIsBusy(void); - -// Returns whether indicated value is contained inside buffer -bool SystemContains_u8(uint8_t value, uint8_t* buffer, size_t sz); - -// Overload for uint16_t -bool SystemContains_u16(uint16_t value, uint16_t* buffer, size_t sz); - -// Reportedly, sets all timer data to zero. -void SystemResetTimers(void); - -// To be called every cycle (i.e.: inside GfxDrawScene() ). -void SystemUserTimersHandler(void); - -// Looks for string "str" inside a string array pointed to by "array". -// Returns index inside string array on success, -1 if not found. -int32_t SystemIndexOfStringArray(char* str, char** array); - -// Function overload for uint16_t data type. -int32_t SystemIndexOf_U16(uint16_t value, uint16_t* array, uint32_t sz); - -// Function overload for uint8_t data type. -int32_t SystemIndexOf_U8(uint8_t value, uint8_t* array, uint32_t from, uint32_t sz); - -void SystemCyclicHandler(void); - -size_t SystemGetBufferSize(void); - -void SystemClearBuffer(void); - -void SystemDisableVBlankInterrupt(void); - -void SystemEnableVBlankInterrupt(void); - -/* ************************************** - * Global Variables * - * **************************************/ - -#endif //__SYSTEM_HEADER__ diff --git a/Source/main.c b/Source/main.c deleted file mode 100644 index 650f907..0000000 --- a/Source/main.c +++ /dev/null @@ -1,162 +0,0 @@ -/* ************************************* - * Includes - * *************************************/ - -#include "Global_Inc.h" -#include "System.h" -#include "Serial.h" -#include "LoadMenu.h" -#include "EndAnimation.h" - -/* ************************************* - * Defines - * *************************************/ - -#define PSX_EXE_HEADER_SIZE 2048 -#define EXE_DATA_PACKET_SIZE 8 - -/* ************************************* - * Local Prototypes - * *************************************/ - -/* ************************************* - * Local Variables - * *************************************/ - - /* Untitled1 (10/07/2017 18:57:47) - StartOffset: 00000000, EndOffset: 0000002F, Length: 00000030 */ - -/* Untitled2 (10/07/2017 21:10:19) - StartOffset: 00000000, EndOffset: 000357FF, Length: 00035800 */ - -extern void _start(void); - - - -int main(void) -{ - uint8_t* inBuffer = SystemGetBufferAddress(); - // int (*exeAddress)(void); - - //System initialization - dprintf("SystemInit()\n"); - SystemInit(); - - dprintf("LoadMenuInit()\n"); - - LoadMenuInit(); - - if(1) - { - uint32_t initPC_Address; - uint32_t RAMDest_Address; - uint32_t ExeSize = 0; - uint32_t i; - void (*exeAddress)(void); - - GfxSetGlobalLuminance(0); - - SerialInit(); - - // Read PSX-EXE header (32 bytes will be enough). - - SerialSetState(SERIAL_STATE_READING_HEADER); - - SerialRead(inBuffer, 32); - - // Get initial program counter address from PSX-EXE header. - - initPC_Address = (inBuffer[0x10] | (inBuffer[0x11] << 8) | (inBuffer[0x12] << 16) | (inBuffer[0x13] << 24) ); - - SerialSetPCAddress(initPC_Address); - - //dprintf("initPC_Address = 0x%08X\n", initPC_Address); - - // Get destination address in RAM from PSX-EXE header. - - RAMDest_Address = (inBuffer[0x18] | (inBuffer[0x19] << 8) | (inBuffer[0x1A] << 16) | (inBuffer[0x1B] << 24) ); - - SerialSetRAMDestAddress(RAMDest_Address); - - //dprintf("RAMDest_Address = 0x%08X\n", RAMDest_Address); - - // We have received all data correctly. Send ACK. - - memset(inBuffer, 0, SystemGetBufferSize()); - - SerialSetState(SERIAL_STATE_WRITING_ACK); - - SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t)); // Write ACK - - // Get PSX-EXE size, without header, in hexadecimal, little-endian format; - - SerialSetState(SERIAL_STATE_READING_EXE_SIZE); - - SerialRead(inBuffer, sizeof(uint32_t) ); - - for(i = 0; i < sizeof(uint32_t); i++) - { - ExeSize |= inBuffer[i] << (i << 3); // (i << 3) == (i * 8) - } - - SerialSetExeSize(ExeSize); - - //DEBUG_PRINT_VAR(ExeSize); - - SerialSetState(SERIAL_STATE_CLEANING_MEMORY); - - exeAddress = (void*)initPC_Address; - - // Clean memory where EXE data will be loaded, just in case... - - memset((void*)RAMDest_Address, 0, (uint32_t)((uint32_t)(&_start) - (uint32_t)(RAMDest_Address) ) ); - - SerialSetState(SERIAL_STATE_WRITING_ACK); - - // We have received PSX-EXE size (without header) correctly. Send ACK. - - SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t)); // Write ACK - - SerialSetState(SERIAL_STATE_READING_EXE_DATA); - - while(GfxIsGPUBusy() == true); - - for(i = 0; i < ExeSize; i += EXE_DATA_PACKET_SIZE) - { - uint32_t bytes_to_read; - - // Read actual EXE data into proper RAM address. - - if( (i + EXE_DATA_PACKET_SIZE) >= ExeSize) - { - bytes_to_read = ExeSize - i; - } - else - { - bytes_to_read = EXE_DATA_PACKET_SIZE; - } - - SerialRead((uint8_t*)RAMDest_Address + i, bytes_to_read); - - SerialSetExeBytesReceived(bytes_to_read); - - SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t)); // Write ACK - } - - SetVBlankHandler(&ISR_SystemDefaultVBlank); - - // Make a pretty animation before exeting OpenSend application. - - EndAnimation(); - - PSX_DeInit(); - - // PSX-EXE has been successfully loaded into RAM. Run executable! - - //dprintf("Entering exe...\n"); - - exeAddress(); - } - - return 0; -} diff --git a/Sprites/Font_2.bmp b/Sprites/Font_2.bmp deleted file mode 100644 index 878437b..0000000 Binary files a/Sprites/Font_2.bmp and /dev/null differ diff --git a/Sprites/Font_2_4bit.bmp b/Sprites/Font_2_4bit.bmp deleted file mode 100644 index fdd2473..0000000 Binary files a/Sprites/Font_2_4bit.bmp and /dev/null differ diff --git a/bin/OPENSEND.bin b/bin/OPENSEND.bin new file mode 100644 index 0000000..39a962a Binary files /dev/null and b/bin/OPENSEND.bin differ diff --git a/bin/OPENSEND.cue b/bin/OPENSEND.cue new file mode 100644 index 0000000..4b18ec2 --- /dev/null +++ b/bin/OPENSEND.cue @@ -0,0 +1,3 @@ +FILE "OPENSEND.bin" BINARY +TRACK 01 MODE2/2352 + INDEX 01 00:00:00 diff --git a/include/EndAnimation.h b/include/EndAnimation.h new file mode 100644 index 0000000..edb7b07 --- /dev/null +++ b/include/EndAnimation.h @@ -0,0 +1,25 @@ +#ifndef __END_SCREEN_HEADER__ +#define __END_SCREEN_HEADER__ + +/* ************************************** + * Includes * + * **************************************/ + +#include "Global_Inc.h" +#include "Gfx.h" + +/* ************************************** + * Defines * + * **************************************/ + +/* ************************************** + * Global Prototypes * + * **************************************/ + +void EndAnimation(void); + +/* ************************************** + * Global Variables * + * **************************************/ + +#endif // __END_SCREEN_HEADER__ diff --git a/include/Font.h b/include/Font.h new file mode 100644 index 0000000..5a7d6b5 --- /dev/null +++ b/include/Font.h @@ -0,0 +1,44 @@ +#ifndef __FONT_HEADER__ +#define __FONT_HEADER__ + +/* ************************************* + * Includes + * *************************************/ + +#include "Global_Inc.h" +#include "System.h" +#include "Gfx.h" +#include "GameStructures.h" +#include + +/* ************************************* + * Defines + * *************************************/ + +#define FONT_DEFAULT_CHAR_SIZE 16 +#define FONT_DEFAULT_INIT_CHAR '!' + +/* ************************************** + * Structs and enums * + * *************************************/ + +/* ************************************* + * Global prototypes + * *************************************/ + +bool FontLoadImage(char* strPath, TYPE_FONT * ptrFont); +void FontSetSize(TYPE_FONT * ptrFont, short size, short bitshift); +void FontPrintText(TYPE_FONT *ptrFont, short x, short y, char* str, ...); +void FontSetInitChar(TYPE_FONT * ptrFont, char c); +void FontSetFlags(TYPE_FONT * ptrFont, FONT_FLAGS flags); +void FontCyclic(void); +void FontSetSpacing(TYPE_FONT* ptrFont, short spacing); + +/* ************************************* + * Global variables + * *************************************/ + +TYPE_FONT RadioFont; +TYPE_FONT SmallFont; + +#endif //__FONT_HEADER__ diff --git a/include/GameStructures.h b/include/GameStructures.h new file mode 100644 index 0000000..e092e1d --- /dev/null +++ b/include/GameStructures.h @@ -0,0 +1,57 @@ +#ifndef __GAME_STRUCTURES__HEADER__ +#define __GAME_STRUCTURES__HEADER__ + +/* ************************************* + * Defines + * *************************************/ + +#define CHEAT_ARRAY_SIZE 16 + +/* ************************************* + * Structs and enums + * *************************************/ + +typedef enum t_fontflags +{ + FONT_NOFLAGS = 0, + FONT_CENTERED = 0x01, + FONT_WRAP_LINE = 0x02, + FONT_BLEND_EFFECT = 0x04, + FONT_1HZ_FLASH = 0x08, + FONT_2HZ_FLASH = 0x10, + FONT_H_CENTERED = 0x20 +}FONT_FLAGS; + +typedef struct t_Font +{ + GsSprite spr; + short char_spacing; + short char_w; + short char_w_bitshift; + short char_h; + char init_ch; + uint8_t char_per_row; + uint8_t max_ch_wrap; + FONT_FLAGS flags; + short spr_w; + short spr_h; + short spr_u; + short spr_v; +}TYPE_FONT; + +typedef struct t_Timer +{ + uint32_t time; + uint32_t orig_time; + bool repeat_flag; + bool busy; + void (*Timeout_Callback)(void); +}TYPE_TIMER; + +typedef struct t_Cheat +{ + unsigned short Combination[CHEAT_ARRAY_SIZE]; + void (*Callback)(void); +}TYPE_CHEAT; + +#endif // __GAME_STRUCTURES__HEADER__ diff --git a/include/Gfx.h b/include/Gfx.h new file mode 100644 index 0000000..b2b8295 --- /dev/null +++ b/include/Gfx.h @@ -0,0 +1,109 @@ +#ifndef __GFX_HEADER__ +#define __GFX_HEADER__ + +/* ************************************* + * Includes + * *************************************/ + +#include "Global_Inc.h" +#include "System.h" + + + +/* ************************************* + * Defines + * *************************************/ + +#define X_SCREEN_RESOLUTION 384 +#define Y_SCREEN_RESOLUTION 240 +#define VRAM_W 1024 +#define VRAM_H 512 +#define MAX_SIZE_FOR_GSSPRITE 256 +#define GFX_TPAGE_WIDTH 64 +#define GFX_TPAGE_HEIGHT 256 +#define GFX_1HZ_FLASH (1<<7) +#define GFX_2HZ_FLASH (1<<8) +#define FULL_LUMINANCE 0xFF + +/* ************************************* + * Global prototypes + * *************************************/ + +void GfxInitDrawEnv(void); +void GfxInitDispEnv(void); +void GfxSetPrimitiveList(void); + +// Renders new scene. Use this function unless you know what you are doing! +void GfxDrawScene(void); + +// Blocking version. Calls GfxDrawScene() and then adds a while(GfxIsBusy() ) +// after it. +void GfxDrawScene_Slow(void); + +void GfxDrawScene_NoSwap(void); + +void GfxSwapBuffers(void); + +// Only renders screen and does not update any pad data or timer data. +// To be used in ISR! +void GfxDrawScene_Fast(void); + +// Repotedly, tells is GPU is ready for a DMA transfer. +bool GfxReadyForDMATransfer(void); + +// Fills a GsSprite structure with information from a TIM file. +bool GfxSpriteFromFile(char* fname, GsSprite * spr); + +// Reportedly, loads CLUT data from a TIM image (image data is discarded) +bool GfxCLUTFromFile(char* fname); + +// Returns true if current object is within screen limits, false otherwise. +bool GfxIsInsideScreenArea(short x, short y, short w, short h); + +// Function overload for GsSprite structures. +bool GfxIsSpriteInsideScreenArea(GsSprite * spr); + +// Used to know whether GPU operation can be done. +bool GfxIsGPUBusy(void); + +// Draws a sprite on screen. First, it checks whether sprite is inside +// screen limits. +void GfxSortSprite(GsSprite * spr); + +uint8_t GfxGetGlobalLuminance(void); + +void GfxSetGlobalLuminance(uint8_t value); + +void GfxIncreaseGlobalLuminance(int8_t step); + +void GfxButtonSetFlags(uint8_t flags); + +void GfxButtonRemoveFlags(uint8_t flags); + +int GfxRotateFromDegrees(int deg); + +void GfxDrawButton(short x, short y, unsigned short btn); + +// Sends current display data on a specific VRAM section and fills +// sprite structure pointed to by "spr". +void GfxSaveDisplayData(GsSprite *spr); + +// Fills GsSprite structure pointed to by "spr" with texture page and U/V +// offset data given a position in VRAM. +bool GfxTPageOffsetFromVRAMPosition(GsSprite * spr, short x, short y); + +void GfxSetSplitScreen(uint8_t playerIndex); + +void GfxDisableSplitScreen(void); + +void GfxDrawScene_NoSwap(void); + +void GfxDevMenuEnable(void); + +/* ************************************* + * Global variables + * *************************************/ + +extern GsSprite PSXButtons; + +#endif //__GFX_HEADER__ diff --git a/include/Global_Inc.h b/include/Global_Inc.h new file mode 100644 index 0000000..0c8f446 --- /dev/null +++ b/include/Global_Inc.h @@ -0,0 +1,41 @@ +#ifndef __GLOBAL_INC__H__ +#define __GLOBAL_INC__H__ + +/* ************************************* + * Includes + * *************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* ************************************* + * Defines + * *************************************/ + +#define REFRESH_FREQUENCY 50 //50 Hz PAL / 60 Hz NTSC +#define DEBUG_PRINT_VAR(var) dprintf(#var " = %d\n", var); + +#ifndef bool + typedef enum + { + false = 0, + true = 1 + }bool; +#endif + +#if (PSXSDK_VERSION != 0x0599) +#error "Wrong PSXSDK version! Please use version 0.5.99." +#endif + +/* Test for GCC > 5.2.0 */ +#if ( (__GNUC__ != 5) || (__GNUC_MINOR__ != 2) || (__GNUC_PATCHLEVEL__ != 0) ) +#error "Wrong GCC version! Please use version 5.2.0." +#endif + +#endif // __GLOBAL_INC__H__ diff --git a/include/LoadMenu.h b/include/LoadMenu.h new file mode 100644 index 0000000..8afc373 --- /dev/null +++ b/include/LoadMenu.h @@ -0,0 +1,29 @@ +#ifndef __LOAD_MENU_HEADER__ +#define __LOAD_MENU_HEADER__ + +/* ************************************* + * Includes + * *************************************/ + +#include "Global_Inc.h" +#include "Gfx.h" +#include "System.h" +#include "Font.h" + +/* ************************************* + * Defines + * *************************************/ + +/* ************************************* + * Global prototypes + * *************************************/ + +void LoadMenuInit(void); + +void LoadMenu( char* fileList[], + void * dest[], + uint8_t szFileList , uint8_t szDestList); + +void LoadMenuEnd(void); + +#endif //__LOAD_MENU_HEADER__ diff --git a/include/Serial.h b/include/Serial.h new file mode 100644 index 0000000..da2c4ce --- /dev/null +++ b/include/Serial.h @@ -0,0 +1,49 @@ +#ifndef __SERIAL_HEADER__ +#define __SERIAL_HEADER__ + +/* ************************************* + * Includes + * *************************************/ + +#include "Global_Inc.h" +#include "System.h" +#include "Gfx.h" +#include "Font.h" + +/* ************************************* + * Defines + * *************************************/ + +#define ACK_BYTE_STRING "b" + +/* ************************************** + * Structs and enums * + * *************************************/ + +typedef enum +{ + SERIAL_STATE_INIT = 0, + SERIAL_STATE_STANDBY, + SERIAL_STATE_WRITING_ACK, + SERIAL_STATE_READING_HEADER, + SERIAL_STATE_READING_EXE_SIZE, + SERIAL_STATE_READING_EXE_DATA, + SERIAL_STATE_WAITING_USER_INPUT, + SERIAL_STATE_CLEANING_MEMORY, +}SERIAL_STATE; + +/* ************************************* + * Global prototypes + * *************************************/ + +void SerialInit(void); +bool SerialRead(uint8_t* ptrArray, size_t nBytes); +bool SerialWrite(void* ptrArray, size_t nBytes); +void ISR_Serial(void); +void SerialSetState(SERIAL_STATE state); +void SerialSetPCAddress(uint32_t addr); +void SerialSetRAMDestAddress(uint32_t addr); +void SerialSetExeSize(size_t size); +void SerialSetExeBytesReceived(uint32_t bytes_read); + +#endif // __SERIAL_HEADER__ diff --git a/include/System.h b/include/System.h new file mode 100644 index 0000000..2994366 --- /dev/null +++ b/include/System.h @@ -0,0 +1,118 @@ +#ifndef __SYSTEM_HEADER__ +#define __SYSTEM_HEADER__ + +/* ************************************** + * Includes * + * **************************************/ + +#include "Global_Inc.h" +#include "Gfx.h" +#include "Serial.h" + +/* ************************************** + * Defines * + * **************************************/ + +#define TIMER_PRESCALER_1_SECOND 10 +#define TIMER_PRESCALER_1_MINUTE (TIMER_PRESCALER_1_SECOND * 60) + +/* ************************************** + * Global Prototypes * + * **************************************/ + +// Calls PSXSDK init routines +void SystemInit(void); + +// Sets default VSync (only sets flag to true and increases global_timer) +void ISR_SystemDefaultVBlank(void); + +void SystemSetBusyFlag(bool value); + +// Calls srand() using current global_timer value as seed +void SystemSetRandSeed(void); + +// Returns VSync flag value +bool SystemRefreshNeeded(void); + +// Loads a file into system's internal buffer +bool SystemLoadFile(char*fname); + +// Loads a file into desired buffer +bool SystemLoadFileToBuffer(char* fname, uint32_t init_pos, uint8_t* buffer, uint32_t szBuffer); + +// Clears VSync flag after each frame +void SystemDisableScreenRefresh(void); + +// Returns file buffer address +uint8_t* SystemGetBufferAddress(void); + +// Tells whether srand() has been called using a pseudo-random value +bool SystemIsRandSeedSet(void); + +// Stops program flow during X cycles +void SystemWaitCycles(uint32_t cycles); + +// 1 cycle-length flag with a frequency of 1 Hz +bool System1SecondTick(void); + +// 1 cycle-length flag with a frequency of 2 Hz +bool System500msTick(void); + +// 1 cycle-length flag with a frequency of 10 Hz +bool System100msTick(void); + +// Returns random value between given minimum and maximum values +uint32_t SystemRand(uint32_t min, uint32_t max); + +// Increases global timer by 1 step +void SystemIncreaseGlobalTimer(void); + +// Sets value to emergency mode flag +void SystemSetEmergencyMode(bool value); + +// Returns emergency mode flag state +bool SystemGetEmergencyMode(void); + +// (Experimental) +uint64_t SystemGetGlobalTimer(void); + +// Returns whether critical section of code is being entered +volatile bool SystemIsBusy(void); + +// Returns whether indicated value is contained inside buffer +bool SystemContains_u8(uint8_t value, uint8_t* buffer, size_t sz); + +// Overload for uint16_t +bool SystemContains_u16(uint16_t value, uint16_t* buffer, size_t sz); + +// Reportedly, sets all timer data to zero. +void SystemResetTimers(void); + +// To be called every cycle (i.e.: inside GfxDrawScene() ). +void SystemUserTimersHandler(void); + +// Looks for string "str" inside a string array pointed to by "array". +// Returns index inside string array on success, -1 if not found. +int32_t SystemIndexOfStringArray(char* str, char** array); + +// Function overload for uint16_t data type. +int32_t SystemIndexOf_U16(uint16_t value, uint16_t* array, uint32_t sz); + +// Function overload for uint8_t data type. +int32_t SystemIndexOf_U8(uint8_t value, uint8_t* array, uint32_t from, uint32_t sz); + +void SystemCyclicHandler(void); + +size_t SystemGetBufferSize(void); + +void SystemClearBuffer(void); + +void SystemDisableVBlankInterrupt(void); + +void SystemEnableVBlankInterrupt(void); + +/* ************************************** + * Global Variables * + * **************************************/ + +#endif //__SYSTEM_HEADER__ diff --git a/sprites/Font_2.bmp b/sprites/Font_2.bmp new file mode 100644 index 0000000..878437b Binary files /dev/null and b/sprites/Font_2.bmp differ diff --git a/sprites/Font_2_4bit.bmp b/sprites/Font_2_4bit.bmp new file mode 100644 index 0000000..fdd2473 Binary files /dev/null and b/sprites/Font_2_4bit.bmp differ diff --git a/src/EndAnimation.c b/src/EndAnimation.c new file mode 100644 index 0000000..027ca1a --- /dev/null +++ b/src/EndAnimation.c @@ -0,0 +1,233 @@ +/* ************************************* + * Includes + * *************************************/ + +#include "EndAnimation.h" + +/* ************************************* + * Defines + * *************************************/ + +/* ************************************* + * Structs and enums + * *************************************/ + +enum +{ + END_ANIMATION_FADEOUT_STEP = 8, + + END_ANIMATION_LINE_STEP = 2, + + END_ANIMATION_SQUARES_SIZE_BITSHIFT = 5, + END_ANIMATION_SQUARES_SIZE = 32, + END_ANIMATION_SQUARES_PER_COLUMN = 8, + END_ANIMATION_SQUARES_PER_ROW = 12, + END_ANIMATION_SQUARES_TOTAL = END_ANIMATION_SQUARES_PER_COLUMN * + END_ANIMATION_SQUARES_PER_ROW, + + END_ANIMATION_SQUARES_TOTAL_MAX_INDEX = END_ANIMATION_SQUARES_TOTAL - 1, + + END_ANIMATION_SQUARES = 0, + END_ANIMATION_FADEOUT, + END_ANIMATION_LINE, + END_ANIMATION_MAX_RAND_VALUE = END_ANIMATION_LINE +}; + +/* ************************************* + * Local Prototypes + * *************************************/ + +static void EndAnimationSquares(void); +static void EndAnimationFadeOut(void); +static void EndAnimationLine(void); + +/* ************************************* + * Local Variables + * *************************************/ + +static GsRectangle EndAnimationRect; +static GsSprite EndAnimationDisplay; + +void EndAnimation(void) +{ + uint8_t randIndex = 0; + + GfxSaveDisplayData(&EndAnimationDisplay); + + GfxSetGlobalLuminance(NORMAL_LUMINANCE); + + if(SystemIsRandSeedSet() == false) + { + // Set default end animation + EndAnimationFadeOut(); + } + else + { + randIndex = rand() % (END_ANIMATION_MAX_RAND_VALUE + 1); + + switch(randIndex) + { + case END_ANIMATION_SQUARES: + EndAnimationSquares(); + break; + + case END_ANIMATION_FADEOUT: + EndAnimationFadeOut(); + break; + + case END_ANIMATION_LINE: + EndAnimationLine(); + break; + + default: + break; + } + } +} + +void EndAnimationFadeOut(void) +{ + uint8_t i; + + while(1) + { + if( GfxGetGlobalLuminance() > 0) + { + GfxSetGlobalLuminance(GfxGetGlobalLuminance() - END_ANIMATION_FADEOUT_STEP); + + GfxSortSprite(&EndAnimationDisplay);; + GfxDrawScene_Slow(); + } + else + { + GsSortCls(0,0,0); + + for(i = 0 ; i < 2 ; i++) + { + // Draw two frames to ensure black display + GfxDrawScene_Slow(); + } + + break; + } + } +} + +void EndAnimationLine(void) +{ + short rectIndex = 0; + + do + { + GfxSortSprite(&EndAnimationDisplay); + + // Draw upper half rectangle + + EndAnimationRect.x = 0; + EndAnimationRect.y = 0; + + EndAnimationRect.w = X_SCREEN_RESOLUTION; + EndAnimationRect.h = rectIndex; + + GsSortRectangle(&EndAnimationRect); + + EndAnimationRect.x = 0; + EndAnimationRect.y = Y_SCREEN_RESOLUTION - rectIndex; + + EndAnimationRect.w = X_SCREEN_RESOLUTION; + EndAnimationRect.h = rectIndex; + + GsSortRectangle(&EndAnimationRect); + + GfxDrawScene_Slow(); + + rectIndex += END_ANIMATION_LINE_STEP; + + }while(rectIndex <= (X_SCREEN_RESOLUTION >> 1) ); + +} + +void EndAnimationSquares(void) +{ + uint16_t i, j, k; + uint16_t randInd = 0; + bool sqPos[END_ANIMATION_SQUARES_TOTAL]; + uint16_t sqCounter = END_ANIMATION_SQUARES_TOTAL; + uint16_t maxIndex = END_ANIMATION_SQUARES_TOTAL_MAX_INDEX; + + EndAnimationRect.w = END_ANIMATION_SQUARES_SIZE; + EndAnimationRect.h = END_ANIMATION_SQUARES_SIZE; + + EndAnimationRect.r = 0; + EndAnimationRect.g = 0; + EndAnimationRect.b = 0; + + memset(sqPos, false , END_ANIMATION_SQUARES_TOTAL); + + for(i = 0; i < END_ANIMATION_SQUARES_TOTAL ; i++) + { + + do + { + randInd = SystemRand(0,maxIndex); + + /*dprintf("randInd = %d\t",randInd); + dprintf("sqPos[randInd] = %d\n", sqPos[randInd]);*/ + + if(sqPos[randInd] == false) + { + sqPos[randInd] = true; + sqCounter--; + + while(sqPos[maxIndex] == true) + { + // Lower maximum value for rand() so that it's + // easier to spot new empty index on next iteration. + maxIndex--; + } + + break; + } + else + { + if(sqCounter == 0) + { + break; + } + } + + }while(1); + + GfxSortSprite(&EndAnimationDisplay); + + if(sqCounter != 0) + { + for(j = 0; j < END_ANIMATION_SQUARES_TOTAL ; j++) + { + if(sqPos[j] == true) + { + EndAnimationRect.x = ((j) << END_ANIMATION_SQUARES_SIZE_BITSHIFT) - + (short)( (j / END_ANIMATION_SQUARES_PER_ROW) * + X_SCREEN_RESOLUTION); + + EndAnimationRect.y = (short) (j/ END_ANIMATION_SQUARES_PER_ROW) << + END_ANIMATION_SQUARES_SIZE_BITSHIFT; + + GsSortRectangle(&EndAnimationRect); + } + } + } + else + { + // Quick fix: draw a full black rectangle instead of multiple squares + for(k = 0 ; k < 2 ; k++) + { + // Draw two frames to ensure black display + GsSortCls(0,0,0); + GfxDrawScene_Slow(); + } + } + + GfxDrawScene_Slow(); + } +} diff --git a/src/Font.c b/src/Font.c new file mode 100644 index 0000000..c4b1491 --- /dev/null +++ b/src/Font.c @@ -0,0 +1,194 @@ +/* ************************************* + * Includes + * *************************************/ + +#include "Font.h" + +/* ************************************* + * Defines + * *************************************/ + +#define FONT_INTERNAL_TEXT_BUFFER_MAX_SIZE 200 + +/* ************************************* + * Local Prototypes + * *************************************/ + +/* ************************************* + * Local Variables + * *************************************/ + +static char _internal_text[FONT_INTERNAL_TEXT_BUFFER_MAX_SIZE]; +static unsigned char _blend_effect_lum; + +bool FontLoadImage(char* strPath, TYPE_FONT * ptrFont) +{ + if(GfxSpriteFromFile(strPath, &ptrFont->spr) == false) + { + return false; + } + + ptrFont->spr_w = ptrFont->spr.w; + ptrFont->spr_h = ptrFont->spr.h; + ptrFont->spr_u = ptrFont->spr.u; + ptrFont->spr_v = ptrFont->spr.v; + + //Now set default values to font + + ptrFont->char_w = FONT_DEFAULT_CHAR_SIZE; + ptrFont->char_h = FONT_DEFAULT_CHAR_SIZE; + + ptrFont->spr.attribute |= COLORMODE(COLORMODE_4BPP); + ptrFont->spr.attribute &= COLORMODE(~(COLORMODE_8BPP | COLORMODE_16BPP | COLORMODE_24BPP)); + ptrFont->spr.r = NORMAL_LUMINANCE; + ptrFont->spr.g = NORMAL_LUMINANCE; + ptrFont->spr.b = NORMAL_LUMINANCE; + + //At this point, spr.w and spr.h = real w/h + ptrFont->char_per_row = (uint8_t)(ptrFont->spr_w / ptrFont->char_w); + ptrFont->max_ch_wrap = 0; + + ptrFont->spr.w = ptrFont->char_w; + ptrFont->spr.h = ptrFont->char_h; + + ptrFont->flags = FONT_NOFLAGS; + + ptrFont->init_ch = FONT_DEFAULT_INIT_CHAR; + + dprintf("Sprite CX = %d, sprite CY = %d\n",ptrFont->spr.cx, ptrFont->spr.cy); + + return true; +} + +void FontSetInitChar(TYPE_FONT * ptrFont, char c) +{ + ptrFont->init_ch = c; +} + +void FontSetFlags(TYPE_FONT * ptrFont, FONT_FLAGS flags) +{ + ptrFont->flags = flags; +} + +void FontSetSize(TYPE_FONT * ptrFont, short size, short bitshift) +{ + ptrFont->char_w = size; + ptrFont->char_h = size; + + ptrFont->char_w_bitshift = bitshift; + + //At this point, spr.w and spr.h = real w/h + ptrFont->char_per_row = (uint8_t)(ptrFont->spr_w / ptrFont->char_w); + ptrFont->max_ch_wrap = 0; + + ptrFont->spr.w = ptrFont->char_w; + ptrFont->spr.h = ptrFont->char_h; +} + +void FontSetSpacing(TYPE_FONT* ptrFont, short spacing) +{ + ptrFont->char_spacing = spacing; +} + +void FontCyclic(void) +{ + _blend_effect_lum -= 8; +} + +void FontPrintText(TYPE_FONT * ptrFont, short x, short y, char* str, ...) +{ + uint16_t i; + uint16_t line_count = 0; + int result; + short orig_x = x; + + va_list ap; + + va_start(ap, str); + + result = vsnprintf( _internal_text, + FONT_INTERNAL_TEXT_BUFFER_MAX_SIZE, + str, + ap ); + + if(ptrFont->flags & FONT_H_CENTERED) + { + x = (X_SCREEN_RESOLUTION >> 1) - ((result >> 1) << ptrFont->char_w_bitshift); + orig_x = x; + } + + for(i = 0; i < result ; i++) + { + char _ch = _internal_text[i]; + + if(_ch == '\0') + { + // End of string + break; + } + + switch(_ch) + { + case ' ': + x += ptrFont->char_w; + continue; + case '\n': + x = orig_x; + y += ptrFont->char_h; + break; + default: + if( (ptrFont->flags & FONT_WRAP_LINE) && (ptrFont->max_ch_wrap != 0) ) + { + if(++line_count >= ptrFont->max_ch_wrap) + { + line_count = 0; + x = orig_x; + y += ptrFont->char_h; + } + } + + ptrFont->spr.x = x; + ptrFont->spr.y = y; + ptrFont->spr.w = ptrFont->char_w; + ptrFont->spr.h = ptrFont->char_h; + ptrFont->spr.u = (short)( (_ch - ptrFont->init_ch) % ptrFont->char_per_row) * ptrFont->char_w; + ptrFont->spr.u += ptrFont->spr_u; // Add original offset for image + ptrFont->spr.v = (short)( (_ch - ptrFont->init_ch) / ptrFont->char_per_row) * ptrFont->char_h; + ptrFont->spr.v += ptrFont->spr_v; // Add original offset for image + + if(ptrFont->flags & FONT_BLEND_EFFECT) + { + ptrFont->spr.r += 8; + ptrFont->spr.g += 8; + ptrFont->spr.b += 8; + } + else + { + ptrFont->spr.r = NORMAL_LUMINANCE; + ptrFont->spr.g = NORMAL_LUMINANCE; + ptrFont->spr.b = NORMAL_LUMINANCE; + } + /*dprintf("char_w = %d, char_h = %d, char_per_row = %d, init_ch: %c\n", + ptrFont->char_w, + ptrFont->char_h, + ptrFont->char_per_row, + ptrFont->init_ch); + dprintf("Char: %c, spr.u = %d, spr.v = %d\n",str[i],ptrFont->spr.u, ptrFont->spr.v); + dprintf("Sprite CX = %d, sprite CY = %d\n",ptrFont->spr.cx, ptrFont->spr.cy);*/ + //dprintf("Sprite rgb={%d,%d,%d}\n",ptrFont->spr.r, ptrFont->spr.g, ptrFont->spr.b); + + GfxSortSprite(&ptrFont->spr); + x += ptrFont->char_spacing; + break; + } + } + + if(ptrFont->flags & FONT_BLEND_EFFECT) + { + ptrFont->spr.r = _blend_effect_lum; + ptrFont->spr.g = _blend_effect_lum; + ptrFont->spr.b = _blend_effect_lum; + } + + va_end(ap); +} diff --git a/src/Gfx.c b/src/Gfx.c new file mode 100644 index 0000000..b9ffb63 --- /dev/null +++ b/src/Gfx.c @@ -0,0 +1,552 @@ +/* ************************************* + * Includes + * *************************************/ + +#include "Gfx.h" + +/* ************************************* + * Defines + * *************************************/ + +#define PRIMITIVE_LIST_SIZE 0x1000 +#define DOUBLE_BUFFERING_SWAP_Y 256 +#define UPLOAD_IMAGE_FLAG 1 +#define MAX_LUMINANCE 0xFF +#define ROTATE_BIT_SHIFT 12 +#define GPUSTAT (*(unsigned int*)0x1F801814) +#define D2_CHCR (*(unsigned int*)0x1F8010A8) + +/* ************************************* + * Structs and enums + * *************************************/ + +enum +{ + BUTTON_SIZE = 16, + + BUTTON_CROSS_U = 48, + BUTTON_CROSS_V = 0, + + BUTTON_SQUARE_U = 0, + BUTTON_SQUARE_V = 0, + + BUTTON_TRIANGLE_U = 32, + BUTTON_TRIANGLE_V = 0, + + BUTTON_CIRCLE_U = 16, + BUTTON_CIRCLE_V = 0, + + BUTTON_DIRECTION_U = 64, + BUTTON_DIRECTION_V = 0, + + BUTTON_LR_U = 80, + BUTTON_LR_V = 0, + BUTTON_LR_SIZE = 24, + + LETTER_SIZE = 8, + + LETTER_L1_U = 104, + LETTER_L1_V = 0, + + LETTER_L2_U = 112, + LETTER_L2_V = 0, + + LETTER_R1_U = 104, + LETTER_R1_V = 8, + + LETTER_R2_U = 112, + LETTER_R2_V = 8, + + LETTER_OFFSET_INSIDE_BUTTON_LR_X = 8, + LETTER_OFFSET_INSIDE_BUTTON_LR_Y = 6 + +}; + +enum +{ + GFX_SECOND_DISPLAY_X = 384, + GFX_SECOND_DISPLAY_Y = 256, + GFX_SECOND_DISPLAY_TPAGE = 22 +}; + +/* ************************************* + * Global Variables + * *************************************/ + +GsSprite PSXButtons; + +/* ************************************* + * Local Prototypes + * *************************************/ + + + +/* ************************************* + * Local Variables + * *************************************/ + +// Drawing environment +static GsDrawEnv DrawEnv; +// Display environment +static GsDispEnv DispEnv; +// Primitive list (it contains all the graphical data for the GPU) +static unsigned int prim_list[PRIMITIVE_LIST_SIZE]; +// Tells other modules whether data is being loaded to GPU +static volatile bool gfx_busy; +// Dictates (R,G,B) brigthness to all sprites silently +static uint8_t global_lum; +// When true, it draws a rectangle on top of all primitives with +// information for development purposes. +static bool GfxDevMenuEnableFlag; + +void GfxSwapBuffers(void) +{ + // Consistency check +#if PSXSDK_DEBUG + + if(GsListPos() >= PRIMITIVE_LIST_SIZE) + { + dprintf("Linked list iterator overflow!\n"); + while(1); + } + + if( (DrawEnv.h != Y_SCREEN_RESOLUTION) + || + ( (DrawEnv.w != X_SCREEN_RESOLUTION) + && + (DrawEnv.w != X_SCREEN_RESOLUTION >> 1) ) + || + ( (DispEnv.y != DOUBLE_BUFFERING_SWAP_Y) + && + (DispEnv.y != 0) ) ) + { + dprintf("What the hell is happening?\n"); + DEBUG_PRINT_VAR(DispEnv.x); + DEBUG_PRINT_VAR(DispEnv.y); + DEBUG_PRINT_VAR(DrawEnv.x); + DEBUG_PRINT_VAR(DrawEnv.y); + + while(1); + } +#endif // PSXSDK_DEBUG + + if(DrawEnv.h == Y_SCREEN_RESOLUTION) + { + if(DispEnv.y == 0) + { + DispEnv.y = DOUBLE_BUFFERING_SWAP_Y; + DrawEnv.y = 0; + } + else if(DispEnv.y == DOUBLE_BUFFERING_SWAP_Y) + { + DispEnv.y = 0; + DrawEnv.y = DOUBLE_BUFFERING_SWAP_Y; + } + + GsSetDispEnv(&DispEnv); + GsSetDrawEnv(&DrawEnv); + } +} + +void GfxDevMenuEnable(void) +{ + GfxDevMenuEnableFlag = true; +} + +void GfxInitDrawEnv(void) +{ + DrawEnv.x = 0; + DrawEnv.y = 0; + DrawEnv.draw_on_display = false; + DrawEnv.w = X_SCREEN_RESOLUTION; + DrawEnv.h = Y_SCREEN_RESOLUTION; + + GsSetDrawEnv(&DrawEnv); +} + +void GfxInitDispEnv(void) +{ + DispEnv.x = 0; + DispEnv.y = 0; + + GsSetDispEnv(&DispEnv); +} + +void GfxSetPrimitiveList(void) +{ + GsSetList(prim_list); +} + +void GfxDrawScene_Fast(void) +{ + GfxSwapBuffers(); + FontCyclic(); + GsDrawList(); +} + +bool GfxReadyForDMATransfer(void) +{ + return ( (GPUSTAT & 1<<28) && !(D2_CHCR & 1<<24) ); +} + +void GfxDrawScene(void) +{ + while( (SystemRefreshNeeded() == false) + || + (GfxIsGPUBusy() == true) ); + + GfxDrawScene_Fast(); + + SystemCyclicHandler(); +} + +void GfxDrawScene_Slow(void) +{ + GfxDrawScene(); + while(GfxIsGPUBusy() == true); +} + +void GfxSortSprite(GsSprite * spr) +{ + uint8_t aux_r = spr->r; + uint8_t aux_g = spr->g; + uint8_t aux_b = spr->b; + unsigned char aux_tpage = spr->tpage; + short aux_w = spr->w; + short aux_x = spr->x; + + if( (spr->w <= 0) || (spr->h <= 0) ) + { + // Invalid width or heigth + return; + } + + if(GfxIsSpriteInsideScreenArea(spr) == false) + { + return; + } + + if(global_lum != NORMAL_LUMINANCE) + { + if(spr->r < NORMAL_LUMINANCE - global_lum) + { + spr->r = 0; + } + else + { + spr->r -= NORMAL_LUMINANCE - global_lum; + } + + if(spr->g < NORMAL_LUMINANCE - global_lum) + { + spr->g = 0; + } + else + { + spr->g -= NORMAL_LUMINANCE - global_lum; + } + + if(spr->b < NORMAL_LUMINANCE - global_lum) + { + spr->b = 0; + } + else + { + spr->b -= NORMAL_LUMINANCE - global_lum; + } + } + + if(spr->w > MAX_SIZE_FOR_GSSPRITE) + { + // GsSprites can't be bigger than 256x256, so since display + // resolution is 384x240, it must be split into two primitives. + + spr->w = MAX_SIZE_FOR_GSSPRITE; + GsSortSprite(spr); + + spr->x += MAX_SIZE_FOR_GSSPRITE; + spr->w = X_SCREEN_RESOLUTION - MAX_SIZE_FOR_GSSPRITE; + spr->tpage += MAX_SIZE_FOR_GSSPRITE / GFX_TPAGE_WIDTH; + GsSortSprite(spr); + + // Restore original values after sorting + spr->w = aux_w; + spr->tpage = aux_tpage; + spr->x = aux_x; + } + else + { + GsSortSprite(spr); + } + + spr->r = aux_r; + spr->g = aux_g; + spr->b = aux_b; +} + +uint8_t GfxGetGlobalLuminance(void) +{ + return global_lum; +} + +void GfxSetGlobalLuminance(uint8_t value) +{ + global_lum = value; +} + +void GfxIncreaseGlobalLuminance(int8_t step) +{ + if( ( (global_lum + step) < MAX_LUMINANCE ) + && + ( (global_lum + step) > 0 ) ) + { + global_lum += step; + } + else + { + global_lum = MAX_LUMINANCE; + } +} + +int GfxRotateFromDegrees(int deg) +{ + return deg << ROTATE_BIT_SHIFT; +} + +bool GfxIsGPUBusy(void) +{ + return (GsIsDrawing() || gfx_busy || (GfxReadyForDMATransfer() == false) ); +} + +bool GfxSpriteFromFile(char* fname, GsSprite * spr) +{ + GsImage gsi; + + if(SystemLoadFile(fname) == false) + { + return false; + } + + while(GfxIsGPUBusy() == true); + + gfx_busy = true; + + GsImageFromTim(&gsi,SystemGetBufferAddress() ); + + GsSpriteFromImage(spr,&gsi,UPLOAD_IMAGE_FLAG); + gfx_busy = false; + + DEBUG_PRINT_VAR(spr->tpage); + DEBUG_PRINT_VAR(spr->u); + DEBUG_PRINT_VAR(spr->v); + DEBUG_PRINT_VAR(spr->w); + DEBUG_PRINT_VAR(spr->h); + + return true; +} + +bool GfxCLUTFromFile(char* fname) +{ + GsImage gsi; + + if(SystemLoadFile(fname) == false) + { + return false; + } + + while(GfxIsGPUBusy() == true); + + gfx_busy = true; + + GsImageFromTim(&gsi,SystemGetBufferAddress() ); + + GsUploadCLUT(&gsi); + + gfx_busy = false; + + return true; +} + +bool GfxIsInsideScreenArea(short x, short y, short w, short h) +{ + if( ( (x + w) >= 0) + && + (x < DrawEnv.w) + && + ( (y + h) >= 0) + && + (y < DrawEnv.h) ) + { + return true; + } + + return false; +} + +bool GfxIsSpriteInsideScreenArea(GsSprite * spr) +{ + return GfxIsInsideScreenArea(spr->x, spr->y, spr->w, spr->h); +} + +void GfxButtonSetFlags(uint8_t flags) +{ + PSXButtons.attribute |= flags; +} + +void GfxButtonRemoveFlags(uint8_t flags) +{ + PSXButtons.attribute &= ~flags; +} + +void GfxDrawButton(short x, short y, unsigned short btn) +{ + static bool first_entered = true; + static short orig_u; + static short orig_v; + + if(first_entered == true) + { + first_entered = false; + orig_u = PSXButtons.u; + orig_v = PSXButtons.v; + } + + PSXButtons.w = BUTTON_SIZE; + PSXButtons.h = BUTTON_SIZE; + + PSXButtons.r = NORMAL_LUMINANCE; + PSXButtons.g = NORMAL_LUMINANCE; + PSXButtons.b = NORMAL_LUMINANCE; + + PSXButtons.x = x; + PSXButtons.y = y; + PSXButtons.mx = PSXButtons.w >> 1; + PSXButtons.my = PSXButtons.h >> 1; + + switch(btn) + { + case PAD_CROSS: + PSXButtons.u = BUTTON_CROSS_U; + PSXButtons.v = BUTTON_CROSS_V; + break; + + case PAD_SQUARE: + PSXButtons.u = BUTTON_SQUARE_U; + PSXButtons.v = BUTTON_SQUARE_V; + break; + + case PAD_TRIANGLE: + PSXButtons.u = BUTTON_TRIANGLE_U; + PSXButtons.v = BUTTON_TRIANGLE_V; + break; + + case PAD_CIRCLE: + PSXButtons.u = BUTTON_CIRCLE_U; + PSXButtons.v = BUTTON_CIRCLE_V; + break; + + case PAD_RIGHT: + PSXButtons.u = BUTTON_DIRECTION_U; + PSXButtons.v = BUTTON_DIRECTION_V; + break; + + case PAD_UP: + PSXButtons.u = BUTTON_DIRECTION_U; + PSXButtons.v = BUTTON_DIRECTION_V; + PSXButtons.rotate = 90 << ROTATE_BIT_SHIFT; + break; + + case PAD_DOWN: + PSXButtons.u = BUTTON_DIRECTION_U; + PSXButtons.v = BUTTON_DIRECTION_V; + PSXButtons.rotate = 270 << ROTATE_BIT_SHIFT; + break; + + case PAD_LEFT: + PSXButtons.u = BUTTON_DIRECTION_U; + PSXButtons.v = BUTTON_DIRECTION_V; + PSXButtons.attribute |= H_FLIP; + break; + + case PAD_L1: + // Fall through + case PAD_L2: + // Fall through + case PAD_R1: + // Fall through + case PAD_R2: + PSXButtons.u = BUTTON_LR_U; + PSXButtons.v = BUTTON_LR_V; + PSXButtons.w = BUTTON_LR_SIZE; + break; + + case PAD_SELECT: + // Fall through + case PAD_START: + // Fall through + default: + // Set null width and height so that sprite doesn't get sorted + PSXButtons.w = 0; + PSXButtons.h = 0; + break; + } + + PSXButtons.u += orig_u; + PSXButtons.v += orig_v; + + GfxSortSprite(&PSXButtons); + + PSXButtons.attribute &= ~H_FLIP; + PSXButtons.rotate = 0; +} + +void GfxSaveDisplayData(GsSprite *spr) +{ + while(GfxIsGPUBusy() == true); + + MoveImage( DispEnv.x, + DispEnv.y, + GFX_SECOND_DISPLAY_X, + GFX_SECOND_DISPLAY_Y, + X_SCREEN_RESOLUTION, + Y_SCREEN_RESOLUTION); + + spr->x = 0; + spr->y = 0; + spr->tpage = GFX_SECOND_DISPLAY_TPAGE; + spr->attribute |= COLORMODE(COLORMODE_16BPP); + spr->w = X_SCREEN_RESOLUTION; + spr->h = Y_SCREEN_RESOLUTION; + spr->u = 0; + spr->v = 0; + spr->r = NORMAL_LUMINANCE; + spr->g = NORMAL_LUMINANCE; + spr->b = NORMAL_LUMINANCE; + + while(GfxIsGPUBusy() == true); +} + +bool GfxTPageOffsetFromVRAMPosition(GsSprite * spr, short x, short y) +{ + if( (x >= VRAM_W) || (x < 0) || (y >= VRAM_H) || (y < 0) ) + { + return false; + } + + spr->tpage = x / GFX_TPAGE_WIDTH; + spr->tpage += (short)(VRAM_W / GFX_TPAGE_WIDTH) * (short)(y / GFX_TPAGE_HEIGHT); + + spr->u = (x % GFX_TPAGE_WIDTH); + + if(spr->attribute & COLORMODE(COLORMODE_8BPP)) + { + // On 8bpp images, it looks like U offset needs to be multiplied by 2. + spr->u <<= 1; + } + + spr->v = (y % GFX_TPAGE_HEIGHT); + + //dprintf("Sprite:\n\tTPAGE: %d\n\tU=%d\n\tV=%d\n",spr->tpage,spr->u, spr->v); + + return false; +} diff --git a/src/LoadMenu.c b/src/LoadMenu.c new file mode 100644 index 0000000..ba8efaf --- /dev/null +++ b/src/LoadMenu.c @@ -0,0 +1,204 @@ +/* ************************************** + * Includes * + * *************************************/ + +#include "LoadMenu.h" + +/* ************************************** + * Defines * + * *************************************/ + +/* ************************************** + * Structs and enums * + * *************************************/ + +enum +{ + SMALL_FONT_SIZE = 8, + SMALL_FONT_SIZE_BITSHIFT = 3, + SMALL_FONT_SPACING = 6 +}; + +enum +{ + BG_BLUE_TARGET_VALUE = 0xC0, + BG_WHITE_TARGET_VALUE = /*0x40*/ 0, + BG_INCREASE_STEP = 0x10 +}; + +enum +{ + LOADING_BAR_X = 64, + LOADING_BAR_Y = 200, + LOADING_BAR_N_LINES = 4, + + LOADING_BAR_WIDTH = 256, + LOADING_BAR_HEIGHT = 16, + + LOADING_BAR_LUMINANCE_TARGET = NORMAL_LUMINANCE, + LOADING_BAR_LUMINANCE_STEP = 10 +}; + +enum +{ + LOADING_TITLE_CLUT_X = 384, + LOADING_TITLE_CLUT_Y = 496, + LOADING_TITLE_X = 128, + LOADING_TITLE_Y = 32, + + LOADING_TITLE_U = 0, + LOADING_TITLE_V = 0, + + LOADING_TITLE_LUMINANCE_STEP = 10, + LOADING_TITLE_LUMINANCE_TARGET = NORMAL_LUMINANCE +}; + +enum +{ + PLANE_START_X = 56, + PLANE_START_Y = 200, + + PLANE_U = 0, + PLANE_V = 32, + PLANE_SIZE = 16, + + PLANE_LUMINANCE_STEP = 0x10, + PLANE_LUMINANCE_TARGET_VALUE = NORMAL_LUMINANCE +}; + +/* ************************************* + * Local Prototypes + * *************************************/ + +static void LoadMenuLoadFileList( char* fileList[], void * dest[], + uint8_t szFileList, uint8_t szDestList); + +/* ************************************* + * Local Variables + * *************************************/ + +static char* LoadMenuFiles[] = { "cdrom:\\DATA\\FONTS\\FONT_2.FNT;1" }; + +static void * LoadMenuDest[] = { (TYPE_FONT*)&SmallFont }; + +static char* strCurrentFile; + +// Flags to communicate with ISR state +// * startup_flag: background fades in from black to blue. +// * end_flag: tells the background to fade out to black. +// * isr_ended: background has totally faded out to black. +// * isr_started: tells the ISR has finished starting up. +static volatile bool startup_flag; +static volatile bool isr_started; +static volatile bool end_flag; +static volatile bool isr_ended; +// Set to true when LoadMenuInit() has been called, and set to false +// once LoadMenuEnd() is called. +// It's used when multiple modules call LoadMenu() at the same time, +// so load menu does not have to be initialised each time; +static bool load_menu_running; + +void LoadMenuInit(void) +{ + static bool first_load = false; + + if(first_load == false) + { + first_load = true; + LoadMenuLoadFileList( LoadMenuFiles, + LoadMenuDest, + sizeof(LoadMenuFiles) / sizeof(char*), + sizeof(LoadMenuDest) / sizeof(void*)); + } + + FontSetSize(&SmallFont, SMALL_FONT_SIZE, SMALL_FONT_SIZE_BITSHIFT); + FontSetSpacing(&SmallFont, SMALL_FONT_SPACING); + + SmallFont.spr.r = 0; + SmallFont.spr.g = 0; + SmallFont.spr.b = 0; + + GfxSetGlobalLuminance(NORMAL_LUMINANCE); +} + +void LoadMenu( char* fileList[], + void * dest[], + uint8_t szFileList , uint8_t szDestList) +{ + + if(load_menu_running == false) + { + LoadMenuInit(); + } + + LoadMenuLoadFileList(fileList,dest,szFileList,szDestList); +} + +void LoadMenuLoadFileList( char* fileList[], void * dest[], + uint8_t szFileList, uint8_t szDestList) +{ + char aux_file_name[100]; + char* extension; + uint8_t fileLoadedCount; + + if(szFileList != szDestList) + { + dprintf("File list size different from dest list size! %d vs %d\n", + szFileList, szDestList); + return; + } + + for(fileLoadedCount = 0; fileLoadedCount < szFileList ; fileLoadedCount++) + { + if(fileList[fileLoadedCount] == NULL) + { + continue; + } + + strCurrentFile = fileList[fileLoadedCount]; + + //dprintf("Files %d / %d loaded. New plane X = %d.\n",fileLoadedCount,szFileList,LoadMenuPlaneSpr.x); + + // Backup original file path + strncpy(aux_file_name,fileList[fileLoadedCount],100); + + //We want to get file extension, so split into tokens + strtok(fileList[fileLoadedCount],".;"); + extension = strtok(NULL,".;"); + + dprintf("File extension: .%s\n",extension); + //Restore original file path in order to load file + strncpy(fileList[fileLoadedCount],aux_file_name,100); + + if(strncmp(extension,"TIM",3) == 0) + { + if(GfxSpriteFromFile(fileList[fileLoadedCount], dest[fileLoadedCount]) == false) + { + dprintf("Could not load image file \"%s\"!\n",fileList[fileLoadedCount]); + } + } + else if(strncmp(extension,"CLT",3) == 0) + { + if(dest[fileLoadedCount] != NULL) + { + dprintf("WARNING: File %s linked to non-NULL destination pointer!\n", dest[fileLoadedCount]); + } + + if(GfxCLUTFromFile(fileList[fileLoadedCount]) == false) + { + dprintf("Could not load CLUT file \"%s\"!\n",fileList[fileLoadedCount]); + } + } + else if(strncmp(extension,"FNT",3) == 0) + { + if(FontLoadImage(fileList[fileLoadedCount], dest[fileLoadedCount]) == false) + { + dprintf("Could not load font file \"%s\"!\n",fileList[fileLoadedCount]); + } + } + else + { + dprintf("LoadMenu does not recognize following extension: %s\n",extension); + } + } +} diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..f20974f --- /dev/null +++ b/src/Makefile @@ -0,0 +1,74 @@ +CC = psxsdkserial-gcc +DEFINE= -D_PAL_MODE_ +DEFINE += -DPSXSDK_DEBUG +LIBS=-lfixmath +CC_FLAGS = -Wall -Werror -c -Os -Wfatal-errors -g +LINKER = psxsdkserial-gcc + +PROJECT = OPENSEND +PROJECT_DIR = ~/OpenSend + +INIT_ADDR=0x801A0000 + +ELF2EXE = elf2exe +ELF2EXE_FLAGS = -mark="Open-source PSX-EXE loader created with PSXSDK" -init_addr=$(INIT_ADDR) +LICENSE_FILE = /usr/local/psxsdk/share/licenses/infoeur.dat + +PSXSDK_DIR = /usr/local/psxsdk/bin + +EMULATOR_DIR = ~/pcsxr +EMULATOR = pcsxr.exe +SOUND_INTERFACE = +EMULATOR_FLAGS = -nogui -psxout +OBJ_DIR = Obj +SRC_DIR = . +MUSIC_TRACKS = +#FFMPEG = ffmpeg +#FFMPEG_DIR = ../Music/ffmpeg/bin +#FFMPEG_FLAGS = -f s16le -acodec pcm_s16le + +GNU_SIZE = mipsel-unknown-elf-size + +all: build image clean +#emulator clean + +rebuild: remove build + +build: clean objects $(PROJECT).elf $(PROJECT).exe + +objects: $(addprefix $(OBJ_DIR)/,main.o System.o Gfx.o \ + LoadMenu.o EndAnimation.o \ + Font.o Serial.o) + +remove: + rm -f Obj/*.o + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c + $(CC) $< -o $@ $(DEFINE) $(CC_FLAGS) + +$(PROJECT).elf: + $(LINKER) Obj/*.o -o Exe/$(PROJECT).elf $(LIBS) -Wl,--gc-sections + +$(PROJECT).exe: + $(ELF2EXE) Exe/$(PROJECT).elf Exe/$(PROJECT).exe $(ELF2EXE_FLAGS) + cp Exe/$(PROJECT).exe ../cdimg + +image: + rm -f $(PROJECT).iso $(PROJECT).bin + rm -f $(PROJECT).cue + mkisofs -o $(PROJECT).iso -V $(PROJECT) -sysid PLAYSTATION ../cdimg + mkpsxiso $(PROJECT).iso $(PROJECT).bin $(LICENSE_FILE) + mv $(PROJECT).bin ../Bin + mv $(PROJECT).cue ../Bin + rm -f $(PROJECT).cue + rm -f $(PROJECT).iso + $(GNU_SIZE) Exe/$(PROJECT).elf + +emulator: + export PATH=$$PATH:$(EMULATOR_DIR) + $(EMULATOR) -cdfile $(PROJECT_DIR)/Bin/$(PROJECT).bin $(EMULATOR_FLAGS) + +clean: + rm -f $(PROJECT).elf cdimg/$(PROJECT).exe $(PROJECT).bin $(PROJECT).cue cdimg/README.txt + rm -f $(PROJECT).iso $(PROJECT).exe $(PROJECT).elf + diff --git a/src/Serial.c b/src/Serial.c new file mode 100644 index 0000000..2e2a1a4 --- /dev/null +++ b/src/Serial.c @@ -0,0 +1,278 @@ +/* ************************************* + * Includes + * *************************************/ + +#include "Serial.h" + +/* ************************************* + * Defines + * *************************************/ + +#define SERIAL_BAUDRATE 115200 +#define SERIAL_TX_RX_TIMEOUT 20000 +#define SERIAL_RX_FIFO_EMPTY 0 +#define SERIAL_TX_NOT_READY 0 + +/* ************************************* + * Local Variables + * *************************************/ + +static volatile SERIAL_STATE SerialState; +static volatile size_t bytesRead; +static volatile uint32_t initPC_Address; +static volatile uint32_t RAMDest_Address; +static volatile size_t ExeSize; +static volatile size_t totalBytes; +static volatile size_t exeBytesRead; +static volatile bool serial_busy; + +/* ************************************* + * Local Prototypes + * *************************************/ + +void ISR_Serial(void) +{ + enum + { + SERIAL_BG_X0 = 0, + SERIAL_BG_X1 = X_SCREEN_RESOLUTION - SERIAL_BG_X0, + SERIAL_BG_X2 = SERIAL_BG_X0, + SERIAL_BG_X3 = SERIAL_BG_X1, + + SERIAL_BG_Y0 = 0, + SERIAL_BG_Y1 = SERIAL_BG_Y0, + SERIAL_BG_Y2 = Y_SCREEN_RESOLUTION - SERIAL_BG_Y0, + SERIAL_BG_Y3 = SERIAL_BG_Y2, + + SERIAL_BG_R = 0, + SERIAL_BG_G = NORMAL_LUMINANCE, + SERIAL_BG_B = NORMAL_LUMINANCE, + }; + + static GsGPoly4 SerialBg = { .x[0] = SERIAL_BG_X0, + .x[1] = SERIAL_BG_X1, + .x[2] = SERIAL_BG_X2, + .x[3] = SERIAL_BG_X3, + + .y[0] = SERIAL_BG_Y0, + .y[1] = SERIAL_BG_Y1, + .y[2] = SERIAL_BG_Y2, + .y[3] = SERIAL_BG_Y3, + + .r[0] = 0, + .r[1] = 0, + .r[2] = SERIAL_BG_R, + .r[3] = SERIAL_BG_R, + + .g[0] = 0, + .g[1] = 0, + .g[2] = SERIAL_BG_G, + .g[3] = SERIAL_BG_G, + + .b[0] = 0, + .b[1] = 0, + .b[2] = SERIAL_BG_B, + .b[3] = SERIAL_BG_B, }; + + enum + { + SERIAL_STATE_TEXT_X = 148, + SERIAL_STATE_TEXT_Y = Y_SCREEN_RESOLUTION >> 1, + }; + + SystemIncreaseGlobalTimer(); + + if( (GfxIsGPUBusy() == true) || (SystemIsBusy() == true) ) + { + return; + } + + FontSetFlags(&SmallFont, FONT_BLEND_EFFECT | FONT_H_CENTERED); + + if(SerialState == SERIAL_STATE_READING_EXE_DATA) + { + if(System1SecondTick() == false) + { + return; + } + else + { + FontSetFlags(&SmallFont, FONT_H_CENTERED); + } + } + + GsSortGPoly4(&SerialBg); + + switch(SerialState) + { + case SERIAL_STATE_INIT: + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Serial initialization"); + break; + + case SERIAL_STATE_STANDBY: + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Waiting for PC..."); + break; + + case SERIAL_STATE_WRITING_ACK: + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Writing ACK"); + break; + + case SERIAL_STATE_READING_HEADER: + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Reading data from header (%d/%d bytes)...", bytesRead, totalBytes); + break; + + case SERIAL_STATE_READING_EXE_SIZE: + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Getting PSX-EXE size from PC..."); + break; + + case SERIAL_STATE_READING_EXE_DATA: + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Reading PSX-EXE data (%d/%d bytes)...", exeBytesRead, ExeSize); + break; + + case SERIAL_STATE_WAITING_USER_INPUT: + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Press any key to continue"); + break; + + case SERIAL_STATE_CLEANING_MEMORY: + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Cleaning RAM before EXE data transfer..."); + break; + + default: + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y, "Unknown state"); + break; + } + + FontSetFlags(&SmallFont, FONT_H_CENTERED); + + if(RAMDest_Address != 0) + { + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y + 16, "RAM Dest address: 0x%08X", RAMDest_Address); + } + + if(initPC_Address != 0) + { + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y + 32, "Init PC address: 0x%08X", initPC_Address); + } + + if(ExeSize != 0) + { + FontPrintText(&SmallFont, SERIAL_STATE_TEXT_X, SERIAL_STATE_TEXT_Y + 48, "PSX-EXE size: 0x%08X", ExeSize); + } + + GfxDrawScene_Fast(); +} + +void SerialSetState(SERIAL_STATE state) +{ + SerialState = state; +} + +void SerialSetPCAddress(uint32_t addr) +{ + initPC_Address = addr; +} + +void SerialSetRAMDestAddress(uint32_t addr) +{ + RAMDest_Address = addr; +} + +void SerialSetExeSize(size_t size) +{ + ExeSize = size; +} + +void SerialInit(void) +{ + uint8_t receivedBytes; + + SetVBlankHandler(&ISR_Serial); + + SerialState = SERIAL_STATE_INIT; + + SIOStart(SERIAL_BAUDRATE); + + SerialState = SERIAL_STATE_STANDBY; + + // ------------------------------------ + // Protocol description + // ------------------------------------ + + // 1. Wait to receive magic byte "99" from PC. + + SerialRead(&receivedBytes, sizeof(uint8_t) ); + + if(receivedBytes != 99) + { + dprintf("Did not receive input magic number!\n"); + return; + } + + // 2. Send ACK (magic byte is ASCII code for 'b'). + + SerialState = SERIAL_STATE_WRITING_ACK; + + SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t) ); +} + +void SerialSetExeBytesReceived(uint32_t bytes_read) +{ + exeBytesRead += bytes_read; +} + +bool SerialRead(uint8_t* ptrArray, size_t nBytes) +{ + bytesRead = 0; + totalBytes = nBytes; + + serial_busy = true; + + if(nBytes == 0) + { + SerialWrite("SerialRead: invalid size %d\n", strnlen("SerialRead: invalid size %d\n", 30)); + return false; + } + + do + { + //uint16_t timeout = SERIAL_TX_RX_TIMEOUT; + + while( (SIOCheckInBuffer() == SERIAL_RX_FIFO_EMPTY)); // Wait for RX FIFO not empty + + *(ptrArray++) = SIOReadByte(); + bytesRead++; + }while(--nBytes); + + serial_busy = false; + + return true; +} + +bool SerialWrite(void* ptrArray, size_t nBytes) +{ + serial_busy = true; + + SystemDisableVBlankInterrupt(); + + if(nBytes == 0) + { + SerialWrite("SerialRead: invalid size %d\n", strnlen("SerialRead: invalid size %d\n", 30)); + return false; + } + + do + { + //uint16_t timeout = SERIAL_TX_RX_TIMEOUT; + + while( (SIOCheckOutBuffer() == SERIAL_TX_NOT_READY)); // Wait for TX FIFO empty. + + SIOSendByte(*(uint8_t*)ptrArray++); + + }while(--nBytes); + + SystemEnableVBlankInterrupt(); + + serial_busy = false; + + return true; +} diff --git a/src/System.c b/src/System.c new file mode 100644 index 0000000..852fea1 --- /dev/null +++ b/src/System.c @@ -0,0 +1,493 @@ +/* ************************************* + * Includes + * *************************************/ + +#include "System.h" + +/* ************************************* + * Defines + * *************************************/ + +#define SYSTEM_MAX_TIMERS 16 +#define FILE_BUFFER_SIZE 0xC40 +#define END_STACK_PATTERN (uint32_t) 0x18022015 +#define BEGIN_STACK_ADDRESS (uint32_t*) 0x801FFF00 +#define STACK_SIZE 0x1000 +#define I_MASK (*(volatile unsigned int*)0x1F801074) + +/* ************************************* + * Local Prototypes + * *************************************/ + +static void SystemSetStackPattern(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; +//Critical section is entered (i.e.: when accessing fopen() or other BIOS functions +static volatile bool system_busy; + +/* ******************************************************************* + * + * @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(); + //Set Drawing Environment + GfxInitDrawEnv(); + //Set Display Environment + GfxInitDispEnv(); + //Set Primitive List + GfxSetPrimitiveList(); + //Initial value for system_busy + system_busy = false; + + GfxSetGlobalLuminance(NORMAL_LUMINANCE); + + SystemSetStackPattern(); +} + +size_t SystemGetBufferSize(void) +{ + return sizeof(file_buffer); +} + +/* ******************************************************************* + * + * @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 !(global_timer % REFRESH_FREQUENCY); +} + +/* **************************************************************************************** + * + * @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, uint32_t init_pos, 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, init_pos, 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, init_pos, 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; +} + +void SystemSetBusyFlag(bool value) +{ + system_busy = value; +} + +/* **************************************************************************************** + * + * @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,0,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 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 volatile bool SystemIsBusy(void) + * + * @author: Xavier Del Campo + * + * @return: returns system busy flag. + * + * ***********************************************************************/ + +volatile bool SystemIsBusy(void) +{ + return system_busy; +} + +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; +} +void SystemCyclicHandler(void) +{ + SystemDisableScreenRefresh(); + SystemCheckStack(); +} + +void SystemDisableVBlankInterrupt(void) +{ + I_MASK &= ~(0x00000001); +} + +void SystemEnableVBlankInterrupt(void) +{ + I_MASK |= (0x00000001); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..6fed452 --- /dev/null +++ b/src/main.c @@ -0,0 +1,161 @@ +/* ************************************* + * Includes + * *************************************/ + +#include "Global_Inc.h" +#include "System.h" +#include "Serial.h" +#include "LoadMenu.h" +#include "EndAnimation.h" + +/* ************************************* + * Defines + * *************************************/ + +#define PSX_EXE_HEADER_SIZE 2048 +#define EXE_DATA_PACKET_SIZE 8 + +/* ************************************* + * Local Prototypes + * *************************************/ + +/* ************************************* + * Local Variables + * *************************************/ + + /* Untitled1 (10/07/2017 18:57:47) + StartOffset: 00000000, EndOffset: 0000002F, Length: 00000030 */ + +/* Untitled2 (10/07/2017 21:10:19) + StartOffset: 00000000, EndOffset: 000357FF, Length: 00035800 */ + +extern void _start(void); + + + +int main(void) +{ + uint8_t* inBuffer = SystemGetBufferAddress(); + // int (*exeAddress)(void); + + //System initialization + dprintf("SystemInit()\n"); + SystemInit(); + + dprintf("LoadMenuInit()\n"); + + LoadMenuInit(); + + { + uint32_t initPC_Address; + uint32_t RAMDest_Address; + uint32_t ExeSize = 0; + uint32_t i; + void (*exeAddress)(void); + + GfxSetGlobalLuminance(0); + + SerialInit(); + + // Read PSX-EXE header (32 bytes will be enough). + + SerialSetState(SERIAL_STATE_READING_HEADER); + + SerialRead(inBuffer, 32); + + // Get initial program counter address from PSX-EXE header. + + initPC_Address = (inBuffer[0x10] | (inBuffer[0x11] << 8) | (inBuffer[0x12] << 16) | (inBuffer[0x13] << 24) ); + + SerialSetPCAddress(initPC_Address); + + //dprintf("initPC_Address = 0x%08X\n", initPC_Address); + + // Get destination address in RAM from PSX-EXE header. + + RAMDest_Address = (inBuffer[0x18] | (inBuffer[0x19] << 8) | (inBuffer[0x1A] << 16) | (inBuffer[0x1B] << 24) ); + + SerialSetRAMDestAddress(RAMDest_Address); + + //dprintf("RAMDest_Address = 0x%08X\n", RAMDest_Address); + + // We have received all data correctly. Send ACK. + + memset(inBuffer, 0, SystemGetBufferSize()); + + SerialSetState(SERIAL_STATE_WRITING_ACK); + + SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t)); // Write ACK + + // Get PSX-EXE size, without header, in hexadecimal, little-endian format; + + SerialSetState(SERIAL_STATE_READING_EXE_SIZE); + + SerialRead(inBuffer, sizeof(uint32_t) ); + + for(i = 0; i < sizeof(uint32_t); i++) + { + ExeSize |= inBuffer[i] << (i << 3); // (i << 3) == (i * 8) + } + + SerialSetExeSize(ExeSize); + + //DEBUG_PRINT_VAR(ExeSize); + + SerialSetState(SERIAL_STATE_CLEANING_MEMORY); + + exeAddress = (void*)initPC_Address; + + // Clean memory where EXE data will be loaded, just in case... + + memset((void*)RAMDest_Address, 0, (uint32_t)((uint32_t)(&_start) - (uint32_t)(RAMDest_Address) ) ); + + SerialSetState(SERIAL_STATE_WRITING_ACK); + + // We have received PSX-EXE size (without header) correctly. Send ACK. + + SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t)); // Write ACK + + SerialSetState(SERIAL_STATE_READING_EXE_DATA); + + while(GfxIsGPUBusy() == true); + + for(i = 0; i < ExeSize; i += EXE_DATA_PACKET_SIZE) + { + uint32_t bytes_to_read; + + // Read actual EXE data into proper RAM address. + + if( (i + EXE_DATA_PACKET_SIZE) >= ExeSize) + { + bytes_to_read = ExeSize - i; + } + else + { + bytes_to_read = EXE_DATA_PACKET_SIZE; + } + + SerialRead((uint8_t*)RAMDest_Address + i, bytes_to_read); + + SerialSetExeBytesReceived(bytes_to_read); + + SerialWrite(ACK_BYTE_STRING, sizeof(uint8_t)); // Write ACK + } + + SetVBlankHandler(&ISR_SystemDefaultVBlank); + + // Make a pretty animation before exeting OpenSend application. + + EndAnimation(); + + PSX_DeInit(); + + // PSX-EXE has been successfully loaded into RAM. Run executable! + + //dprintf("Entering exe...\n"); + + exeAddress(); + } + + return 0; +} -- cgit v1.2.3