Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cosmic scale master #1442

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
# OPL Build with Full Retro GEM Game ID Support for PS2 Games, PS1 Games, and Homebrew Apps

## Features

### PS2 Games:
- Game ID support for PS2 games launched from OPL via HDD, MASS, and SMB.
- Added Game ID support for the "Auto Loading" feature used by [OPL-Launcher](https://github.com/ps2homebrew/OPL-Launcher). Games launched directly from the HDD-OSD or PSBBN now support Game ID.

### PS1 Games:
- Full Game ID support added for PS1 games launched from the "Apps" tab. All PS1 games must be named in the standard format with the Game ID as a prefix, e.g., "SCUS_941.94.Gran Turismo.VCD".

### Homebrew Apps:
- Full Game ID support for homebrew apps. The Game ID will be set to the first 11 characters of the ELF file.

## Companion App

Please check out my companion app, [Retro GEM GameId Resetter](https://github.com/CosmicScale/Retro-GEM-GameId-Resetter). With this app, when you quit a game (For PS2 games: L1 + L2 + R1 + R2 + SELECT + START; For PS1 games: L1 + R1 + SELECT + START) and return to the OSD, the Game ID is reset, and the Retro GEM settings are returned to global.

## Credits

Modified by CosmicScale. Uses code based on the AppCakeLtd gameid-with-gem fork of [Open-PS2-Loader](https://github.com/AppCakeLtd/Open-PS2-Loader/tree/gameid-with-gem).

# Open PS2 Loader

Copyright 2013, Ifcaro & jimmikaelkael
Expand Down
4 changes: 4 additions & 0 deletions include/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ extern int guiFrameId;
#define GUI_SCREEN_GAME_MENU 3
#define GUI_SCREEN_APP_MENU 4

extern char g_GameId[32]; // Declare the global variable

void guiSetGameId(const char* GameId);

void guiSwitchScreen(int target);

void guiReloadScreenExtents();
Expand Down
79 changes: 79 additions & 0 deletions src/gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <limits.h>
#include <stdlib.h>
#include <libvux.h>
#include <string.h>

// Last Played Auto Start
#include <time.h>
Expand All @@ -50,6 +51,8 @@ static int showLngPopup;

static clock_t popupTimer;

char g_GameId[32];

// forward decl.
static void guiShow();

Expand Down Expand Up @@ -108,6 +111,75 @@ static float fadetbl[FADE_SIZE + 1];

static VU_VECTOR pgrad3[12] = {{1, 1, 0, 1}, {-1, 1, 0, 1}, {1, -1, 0, 1}, {-1, -1, 0, 1}, {1, 0, 1, 1}, {-1, 0, 1, 1}, {1, 0, -1, 1}, {-1, 0, -1, 1}, {0, 1, 1, 1}, {0, -1, 1, 1}, {0, 1, -1, 1}, {0, -1, -1, 1}};

// Function to set the game ID, ensuring the first 3 characters are ignored if they are "XX." or "SB."
void guiSetGameId(const char* GameId) {
const char *adjustedGameId = GameId;

// Check if the GameId starts with "XX." or "SB."
if (strncmp(GameId, "XX.", 3) == 0 || strncmp(GameId, "SB.", 3) == 0) {
adjustedGameId = GameId + 3; // Skip the first 3 characters
}

size_t length = strlen(adjustedGameId);

// Check if the GameId ends with ".ELF" or ".elf" and adjust length
if (length > 4 && strcasecmp(adjustedGameId + length - 4, ".elf") == 0) {
length -= 4; // Exclude the ".elf" suffix
}

// Copy only the first 11 characters of the adjusted GameId
length = length > 11 ? 11 : length; // Ensure the length does not exceed 11 characters
strncpy(g_GameId, adjustedGameId, length);
g_GameId[length] = '\0'; // Null-terminate the string
}

static uint8_t gameid_calc_crc(uint8_t *data, int len) {
uint8_t crc = 0x00;
for (int i = 0; i < len; i++) {
crc += data[i];
}
crc = 0x100 - crc;
return crc;
}

static void gameid_draw(char* game_id) {
static uint8_t data[64] = { 0 };
int gidlen = strlen(game_id);

int dpos = 0;

data[dpos++] = 0xA5; // detect word
data[dpos++] = 0x00; // address offset;
dpos++;
data[dpos++] = gidlen;

memcpy(&data[dpos], game_id, gidlen);
dpos += gidlen;

data[dpos++] = 0x00;
data[dpos++] = 0xD5; // end word
data[dpos++] = 0x00; // padding

int data_len = dpos;

data[2] = gameid_calc_crc(&data[3], data_len - 3);

int xstart = (screenWidth / 2) - (data_len * 8);
int ystart = screenHeight - (((screenHeight / 8) * 2) + 20);
int height = 2;

for (int i = 0; i < data_len; i++) {
for (int ii = 7; ii >= 0; ii--) {
rmDrawRect(xstart + (i * 16 + ((7 - ii) * 2)), ystart, 1, height, GS_SETREG_RGBA(0xFF, 0x00, 0xFF, 0x80));
if ((data[i] >> ii) & 1) {
rmDrawRect(xstart + (i * 16 + ((7 - ii) * 2) + 1), ystart, 1, height, GS_SETREG_RGBA(0x00, 0xFF, 0xFF, 0x80));
} else {
rmDrawRect(xstart + (i * 16 + ((7 - ii) * 2) + 1), ystart, 1, height, GS_SETREG_RGBA(0xFF, 0xFF, 0x00, 0x80));
}
}
}
}

void guiReloadScreenExtents()
{
rmGetScreenExtents(&screenWidth, &screenHeight);
Expand Down Expand Up @@ -1549,6 +1621,9 @@ void guiIntroLoop(void)

guiHandleDeferredOps();

if (greetingAlpha >= 0x80)
gameid_draw("");

guiEndFrame();

if (!screenHandlerTarget && screenHandler)
Expand Down Expand Up @@ -1719,6 +1794,10 @@ void guiRenderTextScreen(const char *message)

guiDrawOverlays();

if (strlen(g_GameId)) {
gameid_draw(g_GameId);
}

guiEndFrame();
}

Expand Down
113 changes: 113 additions & 0 deletions src/opl.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@
#include "include/sound.h"
#include "include/xparam.h"

#include <stdio.h>
#include <gsKit.h>
#include <dmaKit.h>
#include <gsToolkit.h>
#include <unistd.h>
#include <string.h>

// Declare the GSGLOBAL pointer as extern
extern GSGLOBAL *gsGlobal;

// FIXME: We should not need this function.
// Use newlib's 'stat' to get GMT time.
#define NEWLIB_PORT_AWARE
Expand Down Expand Up @@ -266,6 +276,12 @@ static void itemExecSelect(struct menu_item *curMenu)
if (support) {
if (support->enabled) {
if (curMenu->current) {
char *gameid = support->itemGetStartup(curMenu->current->item.id);

guiSetGameId(gameid);
guiRenderTextScreen(g_GameId);
sleep(1);

config_set_t *configSet = menuLoadConfig();
support->itemLaunch(support, curMenu->current->item.id, configSet);
}
Expand Down Expand Up @@ -1832,6 +1848,99 @@ static void deferredAudioInit(void)
// --------------------- Auto Loading -----------------------
// ----------------------------------------------------------

// Declare screen dimensions
int screenWidth = 640;
int screenHeight = 448;

// Function to calculate CRC
static uint8_t gameid_calc_crc(uint8_t *data, int len) {
uint8_t crc = 0x00;
for (int i = 0; i < len; i++) {
crc += data[i];
}
crc = 0x100 - crc;
return crc;
}

// Function to draw game ID using GSKit
void gameid_draw_auto(const char* game_id) {
static uint8_t data[64] = { 0 };
int gidlen = strlen(game_id);
if (gidlen > 11) {
gidlen = 11; // Ensure the length does not exceed 11 characters
}

int dpos = 0;

data[dpos++] = 0xA5; // detect word
data[dpos++] = 0x00; // address offset;
dpos++;
data[dpos++] = gidlen;

memcpy(&data[dpos], game_id, gidlen);
dpos += gidlen;

data[dpos++] = 0x00;
data[dpos++] = 0xD5; // end word
data[dpos++] = 0x00; // padding

int data_len = dpos;

data[2] = gameid_calc_crc(&data[3], data_len - 3);

int xstart = (screenWidth / 2) - (data_len * 8);
int ystart = screenHeight - (((screenHeight / 8) * 2) + 20);
int height = 2;

for (int i = 0; i < data_len; i++) {
for (int ii = 7; ii >= 0; ii--) {

gsKit_prim_sprite(gsGlobal, xstart + (i * 16 + ((7 - ii) * 2)), ystart,
xstart + (i * 16 + ((7 - ii) * 2)) + 1, ystart + height,
1,
GS_SETREG_RGBA(0xFF, 0x00, 0xFF, 0x80));

if ((data[i] >> ii) & 1) {
gsKit_prim_sprite(gsGlobal, xstart + (i * 16 + ((7 - ii) * 2) + 1), ystart,
xstart + (i * 16 + ((7 - ii) * 2) + 1) + 1, ystart + height,
1,
GS_SETREG_RGBA(0x00, 0xFF, 0xFF, 0x80));
} else {
gsKit_prim_sprite(gsGlobal, xstart + (i * 16 + ((7 - ii) * 2) + 1), ystart,
xstart + (i * 16 + ((7 - ii) * 2) + 1) + 1, ystart + height,
1,
GS_SETREG_RGBA(0xFF, 0xFF, 0x00, 0x80));
}
}
}
}

// Function to initialize graphics and display the game ID on the screen
void displayGameID(const char *game_id) {
// Initialize GS Global and set up the video mode
gsGlobal = gsKit_init_global();
gsGlobal->Mode = GS_MODE_DTV_480P; // Set to 480p mode
gsGlobal->Width = 640; // Width of the screen
gsGlobal->Height = 448; // Height of the screen
gsGlobal->Interlace = GS_NONINTERLACED; // Non-interlaced mode for progressive scan
gsGlobal->Field = GS_FRAME; // Frame mode
gsGlobal->PSM = GS_PSM_CT24; // Pixel storage format (24-bit color)
gsGlobal->PSMZ = GS_PSMZ_32; // Z buffer format (32-bit depth)
gsGlobal->DoubleBuffering = GS_SETTING_OFF; // Disable double buffering
gsGlobal->ZBuffering = GS_SETTING_OFF; // Disable Z buffering

gsKit_vram_clear(gsGlobal); // Clear VRAM
gsKit_init_screen(gsGlobal); // Initialize the screen

// Draw the game ID on the screen using rectangles
gameid_draw_auto(game_id);

// Execute the GS queue
gsKit_queue_exec(gsGlobal);
// Sync and flip the buffer
gsKit_sync_flip(gsGlobal);
}

static void miniInit(int mode)
{
int ret;
Expand Down Expand Up @@ -1913,6 +2022,8 @@ static void autoLaunchHDDGame(char *argv[])
configSet = configAlloc(0, NULL, path);
configRead(configSet);

// Display GameId before launching the game
displayGameID(gAutoLaunchGame->startup);
hddLaunchGame(NULL, -1, configSet);
}

Expand Down Expand Up @@ -1976,6 +2087,8 @@ static void autoLaunchBDMGame(char *argv[])
configSet = configAlloc(0, NULL, path);
configRead(configSet);

// Display GameId before launching the game
displayGameID(gAutoLaunchGame->startup);
bdmLaunchGame(NULL, -1, configSet);
}

Expand Down
31 changes: 29 additions & 2 deletions src/themes.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,35 @@
#include "include/lang.h"
#include "include/pad.h"
#include "include/sound.h"

#include <string.h>
#define MENU_POS_V 50
#define HINT_HEIGHT 32
#define DECORATOR_SIZE 20

extern const char conf_theme_OPL_cfg;
extern u16 size_conf_theme_OPL_cfg;

// Function to adjust the item ID
const char* adjustItemId(const char* itemId) {
static char adjustedItemId[12]; // Static buffer to hold the adjusted ID (11 characters + null terminator)
const char *originalItemId = itemId;

// Check if the itemId starts with "XX." or "SB."
if (strncmp(itemId, "XX.", 3) == 0 || strncmp(itemId, "SB.", 3) == 0) {
originalItemId = itemId + 3; // Skip the first 3 characters
}

// Apply additional rules to shorten the itemId to 11 characters
if (originalItemId[0] == 'S' && originalItemId[4] == '_' && originalItemId[8] == '.') {
strncpy(adjustedItemId, originalItemId, 11); // Copy the first 11 characters
adjustedItemId[11] = '\0'; // Ensure null-termination
} else {
return originalItemId; // Return the original itemId if rules do not apply
}

return adjustedItemId;
}

theme_t *gTheme;

static int screenWidth;
Expand Down Expand Up @@ -908,7 +929,13 @@ static void drawItemText(struct menu_list *menu, struct submenu_list *item, conf
{
if (item) {
item_list_t *support = menu->item->userdata;
fntRenderString(elem->font, elem->posX, elem->posY, elem->aligned, 0, 0, support->itemGetStartup(support, item->item.id), elem->color);

// Get the item ID and adjust it
const char* itemId = support->itemGetStartup(support, item->item.id);
const char* adjustedItemId = adjustItemId(itemId);

// Render the adjusted item ID
fntRenderString(elem->font, elem->posX, elem->posY, elem->aligned, 0, 0, adjustedItemId, elem->color);
}
}

Expand Down
Loading