Compare commits
12 Commits
Author | SHA1 | Date |
---|---|---|
ABelliqueux | f7c89f7094 | |
ABelliqueux | 55a09d5c38 | |
ABelliqueux | e0e23bee34 | |
ABelliqueux | 59c50e4356 | |
ABelliqueux | 2371e8fa32 | |
ABelliqueux | 362bdb244b | |
ABelliqueux | 7bf316c9f9 | |
ABelliqueux | 1af3a1bf87 | |
ABelliqueux | 179a080b3d | |
ABelliqueux | 505c08a549 | |
ABelliqueux | a865750dca | |
ABelliqueux | da195bbba5 |
1
Makefile
1
Makefile
|
@ -2,6 +2,7 @@ TARGET = ovl-upload
|
||||||
TYPE = ps-exe
|
TYPE = ps-exe
|
||||||
|
|
||||||
SRCS = ovl-upload.c \
|
SRCS = ovl-upload.c \
|
||||||
|
pcdrv.c \
|
||||||
TIM/cubetex.tim \
|
TIM/cubetex.tim \
|
||||||
../common/crt0/crt0.s \
|
../common/crt0/crt0.s \
|
||||||
tritex.c \
|
tritex.c \
|
||||||
|
|
BIN
Overlay.ovl0
BIN
Overlay.ovl0
Binary file not shown.
BIN
Overlay.ovl1
BIN
Overlay.ovl1
Binary file not shown.
Binary file not shown.
299
ovl-upload.c
299
ovl-upload.c
|
@ -1,26 +1,14 @@
|
||||||
|
|
||||||
/* ovl-upload.c, by ABelliqueux, 04-2021 license GNU General Public License v3.0
|
/* ovl-upload.c, by ABelliqueux, 04-2021 license GNU General Public License v3.0
|
||||||
|
|
||||||
This example code demonstrates how to use the companion 'ovl-upload.py' script that should be provided with this file.
|
This example code demonstrates how to use the companion 'ovl-upload.py' script that should be provided with this file.
|
||||||
|
|
||||||
Once the code is loaded on a unirom enabled PSX via a serial/USB cable, 'ovl-upload.py' listens for a specific command
|
Once the code is loaded on a unirom enabled PSX via a serial/USB cable, 'ovl-upload.py' listens for a specific command
|
||||||
|
|
||||||
to load an overlay file on demand.
|
to load an overlay file on demand.
|
||||||
|
|
||||||
For an explanation about overlays, see http://psx.arthus.net/sdk/Psy-Q/DOCS/TRAINING/FALL96/overlay.pdf
|
For an explanation about overlays, see http://psx.arthus.net/sdk/Psy-Q/DOCS/TRAINING/FALL96/overlay.pdf
|
||||||
|
|
||||||
For a basic example see @JaberwockySeamonstah's https://github.com/JaberwockySeamonstah/PSXOverlayExample
|
For a basic example see @JaberwockySeamonstah's https://github.com/JaberwockySeamonstah/PSXOverlayExample
|
||||||
|
|
||||||
Unirom can be found here : https://github.com/JonathanDotCel/unirom8_bootdisc_and_firmware_for_ps1
|
Unirom can be found here : https://github.com/JonathanDotCel/unirom8_bootdisc_and_firmware_for_ps1
|
||||||
|
|
||||||
with it's companion pc side software : https://github.com/JonathanDotCel/NOTPSXSerial
|
with it's companion pc side software : https://github.com/JonathanDotCel/NOTPSXSerial
|
||||||
|
|
||||||
Thanks to @JaberwockySeamonstah, @JonathanDotCel, @nicolasnoble, @Lameguy64 for their help and patience.
|
Thanks to @JaberwockySeamonstah, @JonathanDotCel, @nicolasnoble, @Lameguy64 for their help and patience.
|
||||||
|
|
||||||
Demonstrates:
|
Demonstrates:
|
||||||
|
|
||||||
* Using overlays to store different data and loading them in memory as needed.
|
* Using overlays to store different data and loading them in memory as needed.
|
||||||
|
|
||||||
Controls:
|
Controls:
|
||||||
Select - Load alternative overlay
|
Select - Load alternative overlay
|
||||||
*/
|
*/
|
||||||
|
@ -30,408 +18,275 @@
|
||||||
#include <libgpu.h>
|
#include <libgpu.h>
|
||||||
#include <libetc.h>
|
#include <libetc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <libsio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "pcdrv.h"
|
||||||
// If USECD is defined, files will be loaded from the CD. Use this method for testing in an emulator.
|
// If USECD is defined, files will be loaded from the CD. Use this method for testing in an emulator.
|
||||||
// Additionaly, generate the bin/cue with mkpsxiso.
|
// Additionaly, generate the bin/cue with mkpsxiso :
|
||||||
|
// $ mkpsxiso -y config/OverlayExample.xml
|
||||||
//~ #define USECD
|
//~ #define USECD
|
||||||
|
|
||||||
#ifdef USECD
|
#ifdef USECD
|
||||||
|
|
||||||
#include <libcd.h>
|
#include <libcd.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Sample vector models
|
// Sample vector models
|
||||||
|
|
||||||
#include "tritex.h"
|
#include "tritex.h"
|
||||||
|
|
||||||
#include "cubetex.h"
|
#include "cubetex.h"
|
||||||
|
|
||||||
#define VMODE 0
|
#define VMODE 0
|
||||||
|
|
||||||
#define SCREENXRES 320
|
#define SCREENXRES 320
|
||||||
|
|
||||||
#define SCREENYRES 240
|
#define SCREENYRES 240
|
||||||
|
|
||||||
#define CENTERX SCREENXRES/2
|
#define CENTERX SCREENXRES/2
|
||||||
|
|
||||||
#define CENTERY SCREENYRES/2
|
#define CENTERY SCREENYRES/2
|
||||||
|
|
||||||
#define OTLEN 2048 // Maximum number of OT entries
|
#define OTLEN 2048 // Maximum number of OT entries
|
||||||
|
|
||||||
#define PRIMBUFFLEN 32768 // Maximum number of POLY_GT3 primitives
|
#define PRIMBUFFLEN 32768 // Maximum number of POLY_GT3 primitives
|
||||||
|
|
||||||
// Display and draw environments, double buffered
|
// Display and draw environments, double buffered
|
||||||
|
|
||||||
DISPENV disp[2];
|
DISPENV disp[2];
|
||||||
|
|
||||||
DRAWENV draw[2];
|
DRAWENV draw[2];
|
||||||
|
|
||||||
u_long ot[2][OTLEN]; // Ordering table (contains addresses to primitives)
|
u_long ot[2][OTLEN]; // Ordering table (contains addresses to primitives)
|
||||||
|
|
||||||
char primbuff[2][PRIMBUFFLEN] = {0}; // Primitive list // That's our prim buffer
|
char primbuff[2][PRIMBUFFLEN] = {0}; // Primitive list // That's our prim buffer
|
||||||
|
|
||||||
//~ int primcnt=0; // Primitive counter
|
//~ int primcnt=0; // Primitive counter
|
||||||
|
|
||||||
char * nextpri = primbuff[0]; // Primitive counter
|
char * nextpri = primbuff[0]; // Primitive counter
|
||||||
|
|
||||||
short db = 0; // Current buffer counter
|
short db = 0; // Current buffer counter
|
||||||
|
|
||||||
// Texture image
|
// Texture image
|
||||||
|
|
||||||
extern unsigned long _binary_TIM_cubetex_tim_start[];
|
extern unsigned long _binary_TIM_cubetex_tim_start[];
|
||||||
|
|
||||||
extern unsigned long _binary_TIM_cubetex_tim_end[];
|
extern unsigned long _binary_TIM_cubetex_tim_end[];
|
||||||
|
|
||||||
extern unsigned long _binary_TIM_cubetex_tim_length;
|
extern unsigned long _binary_TIM_cubetex_tim_length;
|
||||||
|
|
||||||
TIM_IMAGE tim_cube;
|
TIM_IMAGE tim_cube;
|
||||||
|
|
||||||
// OVERLAYS CONFIG
|
// OVERLAYS CONFIG
|
||||||
|
|
||||||
// These symbols name are defined in 'overlay.ld', l.8, l.24 and l.41
|
// These symbols name are defined in 'overlay.ld', l.8, l.24 and l.41
|
||||||
// Use &load_all_overlays_here to get the memory adress where the overlay files are loaded.
|
// Use &load_all_overlays_here to get the memory adress where the overlay files are loaded.
|
||||||
// Those adresses you can check in the generated .map file at compile time.
|
// Those adresses you can check in the generated .map file at compile time.
|
||||||
|
|
||||||
extern u_long load_all_overlays_here;
|
extern u_long load_all_overlays_here;
|
||||||
|
|
||||||
extern u_long __lvl0_end; // Use &__lvl0_end to get end address of corresponding overlay.
|
extern u_long __lvl0_end; // Use &__lvl0_end to get end address of corresponding overlay.
|
||||||
|
|
||||||
extern u_long __lvl1_end;
|
extern u_long __lvl1_end;
|
||||||
|
|
||||||
//~ u_long overlaySize = 0;
|
//~ u_long overlaySize = 0;
|
||||||
|
char * overlayFile; // Will hold the name of the file to load.
|
||||||
static char* overlayFile; // Will hold the name of the file to load.
|
char * ptrToChar[8]; // Will hold the name of the file to load.
|
||||||
|
u_char overlayFileID = 0, loadFileIDwas = 0;
|
||||||
u_char overlayFileID, loadFileIDwas, loadFileID = 0; // Will hold an ID that's unique for each file.
|
|
||||||
|
|
||||||
// Timer for the pad
|
// Timer for the pad
|
||||||
|
|
||||||
u_short timer = 0;
|
u_short timer = 0;
|
||||||
|
// pcdrv protocol
|
||||||
|
u_char escape = 0x00; // Hypothetical Escape char for unirom
|
||||||
|
u_char protocol = 0x01; // Hypothetical ID number for the pcdrv protocol in unirom
|
||||||
|
u_char command = LOAD; // We're loading the data here
|
||||||
|
uint32_t checkSum = 0;
|
||||||
|
volatile u_char inBuffer[BUFFER_LEN] = {0};
|
||||||
|
volatile u_char dataBuffer[64] = "DEBOUTLESENFANTS";
|
||||||
// Prototypes
|
// Prototypes
|
||||||
|
|
||||||
void init(void);
|
void init(void);
|
||||||
|
|
||||||
void display(void);
|
void display(void);
|
||||||
|
|
||||||
void LoadTexture(u_long * tim, TIM_IMAGE * tparam);
|
void LoadTexture(u_long * tim, TIM_IMAGE * tparam);
|
||||||
|
|
||||||
void init(){
|
void init(){
|
||||||
|
|
||||||
// Reset the GPU before doing anything and the controller
|
// Reset the GPU before doing anything and the controller
|
||||||
PadInit(0);
|
PadInit(0);
|
||||||
ResetGraph(0);
|
ResetGraph(0);
|
||||||
|
|
||||||
// Initialize and setup the GTE
|
// Initialize and setup the GTE
|
||||||
InitGeom();
|
InitGeom();
|
||||||
SetGeomOffset(CENTERX, CENTERY); // x, y offset
|
SetGeomOffset(CENTERX, CENTERY); // x, y offset
|
||||||
SetGeomScreen(CENTERX); // Distance between eye and screen
|
SetGeomScreen(CENTERX); // Distance between eye and screen
|
||||||
|
|
||||||
// Set the display and draw environments
|
// Set the display and draw environments
|
||||||
SetDefDispEnv(&disp[0], 0, 0 , SCREENXRES, SCREENYRES);
|
SetDefDispEnv(&disp[0], 0, 0 , SCREENXRES, SCREENYRES);
|
||||||
SetDefDispEnv(&disp[1], 0, SCREENYRES, SCREENXRES, SCREENYRES);
|
SetDefDispEnv(&disp[1], 0, SCREENYRES, SCREENXRES, SCREENYRES);
|
||||||
|
|
||||||
SetDefDrawEnv(&draw[0], 0, SCREENYRES, SCREENXRES, SCREENYRES);
|
SetDefDrawEnv(&draw[0], 0, SCREENYRES, SCREENXRES, SCREENYRES);
|
||||||
SetDefDrawEnv(&draw[1], 0, 0, SCREENXRES, SCREENYRES);
|
SetDefDrawEnv(&draw[1], 0, 0, SCREENXRES, SCREENYRES);
|
||||||
|
|
||||||
if (VMODE)
|
if (VMODE)
|
||||||
{
|
{
|
||||||
SetVideoMode(MODE_PAL);
|
SetVideoMode(MODE_PAL);
|
||||||
disp[0].screen.y += 8;
|
disp[0].screen.y += 8;
|
||||||
disp[1].screen.y += 8;
|
disp[1].screen.y += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
setRGB0(&draw[0], 0, 0, 255);
|
setRGB0(&draw[0], 0, 0, 255);
|
||||||
setRGB0(&draw[1], 0, 0, 255);
|
setRGB0(&draw[1], 0, 0, 255);
|
||||||
|
|
||||||
draw[0].isbg = 1;
|
draw[0].isbg = 1;
|
||||||
draw[1].isbg = 1;
|
draw[1].isbg = 1;
|
||||||
|
|
||||||
PutDispEnv(&disp[db]);
|
PutDispEnv(&disp[db]);
|
||||||
PutDrawEnv(&draw[db]);
|
PutDrawEnv(&draw[db]);
|
||||||
|
|
||||||
// Init font system
|
// Init font system
|
||||||
FntLoad(960, 0);
|
FntLoad(960, 0);
|
||||||
FntOpen(16, 16, 196, 64, 0, 256);
|
FntOpen(16, 16, 196, 196, 0, 512);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void display(void){
|
void display(void){
|
||||||
|
|
||||||
DrawSync(0);
|
DrawSync(0);
|
||||||
VSync(0);
|
VSync(0);
|
||||||
|
|
||||||
PutDispEnv(&disp[db]);
|
PutDispEnv(&disp[db]);
|
||||||
PutDrawEnv(&draw[db]);
|
PutDrawEnv(&draw[db]);
|
||||||
|
|
||||||
SetDispMask(1);
|
SetDispMask(1);
|
||||||
|
|
||||||
DrawOTag(ot[db] + OTLEN - 1);
|
DrawOTag(ot[db] + OTLEN - 1);
|
||||||
|
|
||||||
db = !db;
|
db = !db;
|
||||||
|
|
||||||
nextpri = primbuff[db];
|
nextpri = primbuff[db];
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadTexture(u_long * tim, TIM_IMAGE * tparam){ // This part is from Lameguy64's tutorial series : lameguy64.net/svn/pstutorials/chapter1/3-textures.html login/pw: annoyingmous
|
void LoadTexture(u_long * tim, TIM_IMAGE * tparam){ // This part is from Lameguy64's tutorial series : lameguy64.net/svn/pstutorials/chapter1/3-textures.html login/pw: annoyingmous
|
||||||
OpenTIM(tim); // Open the tim binary data, feed it the address of the data in memory
|
OpenTIM(tim); // Open the tim binary data, feed it the address of the data in memory
|
||||||
ReadTIM(tparam); // This read the header of the TIM data and sets the corresponding members of the TIM_IMAGE structure
|
ReadTIM(tparam); // This read the header of the TIM data and sets the corresponding members of the TIM_IMAGE structure
|
||||||
|
|
||||||
LoadImage(tparam->prect, tparam->paddr); // Transfer the data from memory to VRAM at position prect.x, prect.y
|
LoadImage(tparam->prect, tparam->paddr); // Transfer the data from memory to VRAM at position prect.x, prect.y
|
||||||
DrawSync(0); // Wait for the drawing to end
|
DrawSync(0); // Wait for the drawing to end
|
||||||
|
|
||||||
if (tparam->mode & 0x8){ // check 4th bit // If 4th bit == 1, TIM has a CLUT
|
if (tparam->mode & 0x8){ // check 4th bit // If 4th bit == 1, TIM has a CLUT
|
||||||
LoadImage(tparam->crect, tparam->caddr); // Load it to VRAM at position crect.x, crect.y
|
LoadImage(tparam->crect, tparam->caddr); // Load it to VRAM at position crect.x, crect.y
|
||||||
DrawSync(0); // Wait for drawing to end
|
DrawSync(0); // Wait for drawing to end
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
int fileDesc = 0;
|
||||||
|
int fileRead = 0;
|
||||||
|
int filePos = 0;
|
||||||
|
int fileCreated = 0;
|
||||||
int main() {
|
int main() {
|
||||||
|
|
||||||
// Update this value to avoid trigger at launch
|
// Update this value to avoid trigger at launch
|
||||||
|
loadFileIDwas = overlayFileID;
|
||||||
loadFileIDwas = overlayFileID = loadFileID;
|
if ( overlayFileID == 0 ){
|
||||||
|
|
||||||
if ( loadFileID == 0 ){
|
|
||||||
|
|
||||||
overlayFile = "\\cube.bin;1";
|
overlayFile = "\\cube.bin;1";
|
||||||
|
} else if ( overlayFileID == 1) {
|
||||||
} else if ( loadFileID == 1) {
|
|
||||||
|
|
||||||
overlayFile = "\\tri.bin;1";
|
overlayFile = "\\tri.bin;1";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load overlay from CD if definde
|
// Load overlay from CD if definde
|
||||||
|
|
||||||
#ifdef USECD
|
#ifdef USECD
|
||||||
|
|
||||||
CdInit();
|
CdInit();
|
||||||
|
|
||||||
int cdread = 0, cdsync = 1;
|
int cdread = 0, cdsync = 1;
|
||||||
|
|
||||||
cdread = CdReadFile( (char *)(overlayFile), &load_all_overlays_here, 0);
|
cdread = CdReadFile( (char *)(overlayFile), &load_all_overlays_here, 0);
|
||||||
|
|
||||||
cdsync = CdReadSync(0, 0);
|
cdsync = CdReadSync(0, 0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
int PadStatus;
|
int PadStatus;
|
||||||
|
|
||||||
int TPressed=0;
|
int TPressed=0;
|
||||||
|
|
||||||
int AutoRotate=1;
|
int AutoRotate=1;
|
||||||
|
|
||||||
long t, p, OTz, Flag; // t == vertex count, p == depth cueing interpolation value, OTz == value to create Z-ordered OT, Flag == see LibOver47.pdf, p.143
|
long t, p, OTz, Flag; // t == vertex count, p == depth cueing interpolation value, OTz == value to create Z-ordered OT, Flag == see LibOver47.pdf, p.143
|
||||||
|
|
||||||
MESH * model = &Tri;
|
MESH * model = &Tri;
|
||||||
|
|
||||||
POLY_GT3 *poly = {0}; // pointer to a POLY_GT3
|
POLY_GT3 *poly = {0}; // pointer to a POLY_GT3
|
||||||
|
|
||||||
SVECTOR Rotate={ 0 }; // Rotation coordinates
|
SVECTOR Rotate={ 0 }; // Rotation coordinates
|
||||||
VECTOR Trans={ 0, 0, CENTERX, 0 }; // Translation coordinates
|
VECTOR Trans={ 0, 0, CENTERX, 0 }; // Translation coordinates
|
||||||
VECTOR Scale={ ONE, ONE, ONE, 0 }; // ONE == 4096
|
VECTOR Scale={ ONE, ONE, ONE, 0 }; // ONE == 4096
|
||||||
MATRIX Matrix={0}; // Matrix data for the GTE
|
MATRIX Matrix={0}; // Matrix data for the GTE
|
||||||
|
|
||||||
// Texture window
|
// Texture window
|
||||||
|
|
||||||
DR_MODE * dr_mode; // Pointer to dr_mode prim
|
DR_MODE * dr_mode; // Pointer to dr_mode prim
|
||||||
|
|
||||||
RECT tws = {0, 0, 32, 32}; // Texture window coordinates : x, y, w, h
|
RECT tws = {0, 0, 32, 32}; // Texture window coordinates : x, y, w, h
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
LoadTexture(_binary_TIM_cubetex_tim_start, &tim_cube);
|
LoadTexture(_binary_TIM_cubetex_tim_start, &tim_cube);
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
while (1) {
|
while (1) {
|
||||||
|
FntPrint("%02d - %04d - %02d", fileDesc, filePos, fileRead );
|
||||||
// Overlay switch
|
// If filedescriptor is not null and not -1, try to open the file
|
||||||
|
if ( fileDesc > 0 ){
|
||||||
if ( loadFileID != loadFileIDwas ){
|
switch (fileRead){
|
||||||
|
case 0: PCwrite( fileDesc, filePos, 7, dataBuffer, inBuffer);
|
||||||
// Update previous file value
|
fileRead = 1;
|
||||||
|
|
||||||
loadFileIDwas = loadFileID;
|
|
||||||
|
|
||||||
// Change file to load
|
|
||||||
|
|
||||||
switch ( loadFileID ){
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
|
|
||||||
overlayFile = "\\cube.bin;1";
|
|
||||||
|
|
||||||
overlayFileID = 0;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
case 1: PCseek( fileDesc, 7, 3, 1, inBuffer);
|
||||||
case 1:
|
fileRead = 2;
|
||||||
|
break;
|
||||||
overlayFile = "\\tri.bin;1";
|
case 2: PCwrite( fileDesc, 10, 7, dataBuffer + 7, inBuffer);
|
||||||
|
fileRead = 3;
|
||||||
overlayFileID = 1;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
//~ PCclose(fileDesc, inBuffer);
|
||||||
|
PCinit(inBuffer);
|
||||||
|
fileDesc = 0;
|
||||||
|
fileRead = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Overlay switch
|
||||||
|
if ( overlayFileID != loadFileIDwas ){
|
||||||
|
// Change file to load
|
||||||
|
switch ( overlayFileID ){
|
||||||
|
case 0:
|
||||||
overlayFile = "\\cube.bin;1";
|
overlayFile = "\\cube.bin;1";
|
||||||
|
//~ overlayFileID = 0;
|
||||||
overlayFileID = 0;
|
break;
|
||||||
|
case 1:
|
||||||
|
overlayFile = "\\tri.bin;1";
|
||||||
|
//~ overlayFileID = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
overlayFile = "\\cube.bin;1";
|
||||||
|
//~ overlayFileID = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#ifndef USECD
|
||||||
|
if(!fileRead){
|
||||||
|
fileDesc = PCopen("HELLO.WD", O_RDWR, inBuffer);
|
||||||
|
//~ fileDesc = PCcreate("HELLO.WD", O_RDWR, inBuffer);
|
||||||
|
//~ returnVal = PCseek(1, 0, 369, 1, inBuffer);
|
||||||
|
//~ returnVal = PCread(88, 369, 16, dataBuffer, inBuffer);
|
||||||
|
//~ returnVal = PCwrite(88, 10, 5, dataBuffer, inBuffer);
|
||||||
|
if ( fileDesc ){
|
||||||
|
loadFileIDwas = overlayFileID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef USECD
|
#ifdef USECD
|
||||||
|
|
||||||
cdread = CdReadFile( (char *)(overlayFile), &load_all_overlays_here, 0);
|
cdread = CdReadFile( (char *)(overlayFile), &load_all_overlays_here, 0);
|
||||||
|
if ( CdReadSync(0, 0) == 0 ){
|
||||||
CdReadSync(0, 0);
|
loadFileIDwas = overlayFileID;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pad button timer
|
// Pad button timer
|
||||||
|
|
||||||
while ( timer > 0 ) {
|
while ( timer > 0 ) {
|
||||||
|
|
||||||
timer --;
|
timer --;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read pad status
|
// Read pad status
|
||||||
|
|
||||||
PadStatus = PadRead(0);
|
PadStatus = PadRead(0);
|
||||||
|
|
||||||
// If select is pressed, change overlay
|
// If select is pressed, change overlay
|
||||||
|
if ( ( PadStatus & PADselect ) && !timer ) {
|
||||||
if (PadStatus & PADselect && !timer) {
|
overlayFileID = !overlayFileID;
|
||||||
|
timer = 150;
|
||||||
// We send the memory address where the file should be loaded, the memory address of the loadFileID, so that the screen is updated when it changes, and the file id.
|
|
||||||
|
|
||||||
printf("load:%p:%08x:%d", &load_all_overlays_here, &loadFileID, overlayFileID);
|
|
||||||
|
|
||||||
#ifdef USECD
|
|
||||||
|
|
||||||
// We can do that because we only have two files
|
|
||||||
|
|
||||||
loadFileID = !loadFileID;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
timer = 30;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AutoRotate) {
|
if (AutoRotate) {
|
||||||
|
|
||||||
Rotate.vy += 8; // Pan
|
Rotate.vy += 8; // Pan
|
||||||
|
|
||||||
Rotate.vx += 8; // Tilt
|
Rotate.vx += 8; // Tilt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Clear the current OT
|
// Clear the current OT
|
||||||
|
|
||||||
ClearOTagR(ot[db], OTLEN);
|
ClearOTagR(ot[db], OTLEN);
|
||||||
|
|
||||||
// Convert and set the matrixes
|
// Convert and set the matrixes
|
||||||
|
|
||||||
RotMatrix(&Rotate, &Matrix);
|
RotMatrix(&Rotate, &Matrix);
|
||||||
|
|
||||||
TransMatrix(&Matrix, &Trans);
|
TransMatrix(&Matrix, &Trans);
|
||||||
|
|
||||||
ScaleMatrix(&Matrix, &Scale);
|
ScaleMatrix(&Matrix, &Scale);
|
||||||
|
|
||||||
SetRotMatrix(&Matrix);
|
SetRotMatrix(&Matrix);
|
||||||
|
|
||||||
SetTransMatrix(&Matrix);
|
SetTransMatrix(&Matrix);
|
||||||
|
|
||||||
|
|
||||||
// Render the sample vector model
|
// Render the sample vector model
|
||||||
t=0;
|
t=0;
|
||||||
|
|
||||||
// modelCube is a TMESH, len member == # vertices, but here it's # of triangle... So, for each tri * 3 vertices ...
|
// modelCube is a TMESH, len member == # vertices, but here it's # of triangle... So, for each tri * 3 vertices ...
|
||||||
|
|
||||||
for (i = 0; i < (model->tmesh->len*3); i += 3) {
|
for (i = 0; i < (model->tmesh->len*3); i += 3) {
|
||||||
|
|
||||||
poly = (POLY_GT3 *)nextpri;
|
poly = (POLY_GT3 *)nextpri;
|
||||||
|
|
||||||
// Initialize the primitive and set its color values
|
// Initialize the primitive and set its color values
|
||||||
|
|
||||||
SetPolyGT3(poly);
|
SetPolyGT3(poly);
|
||||||
|
|
||||||
((POLY_GT3 *)poly)->tpage = getTPage(tim_cube.mode&0x3, 0,
|
((POLY_GT3 *)poly)->tpage = getTPage(tim_cube.mode&0x3, 0,
|
||||||
tim_cube.prect->x,
|
tim_cube.prect->x,
|
||||||
tim_cube.prect->y
|
tim_cube.prect->y
|
||||||
);
|
);
|
||||||
|
|
||||||
setRGB0(poly, model->tmesh->c[i].r , model->tmesh->c[i].g , model->tmesh->c[i].b);
|
setRGB0(poly, model->tmesh->c[i].r , model->tmesh->c[i].g , model->tmesh->c[i].b);
|
||||||
setRGB1(poly, model->tmesh->c[i+1].r, model->tmesh->c[i+1].g, model->tmesh->c[i+1].b);
|
setRGB1(poly, model->tmesh->c[i+1].r, model->tmesh->c[i+1].g, model->tmesh->c[i+1].b);
|
||||||
setRGB2(poly, model->tmesh->c[i+2].r, model->tmesh->c[i+2].g, model->tmesh->c[i+2].b);
|
setRGB2(poly, model->tmesh->c[i+2].r, model->tmesh->c[i+2].g, model->tmesh->c[i+2].b);
|
||||||
|
|
||||||
setUV3(poly, model->tmesh->u[i].vx , model->tmesh->u[i].vy,
|
setUV3(poly, model->tmesh->u[i].vx , model->tmesh->u[i].vy,
|
||||||
model->tmesh->u[i+1].vx, model->tmesh->u[i+1].vy,
|
model->tmesh->u[i+1].vx, model->tmesh->u[i+1].vy,
|
||||||
model->tmesh->u[i+2].vx, model->tmesh->u[i+2].vy);
|
model->tmesh->u[i+2].vx, model->tmesh->u[i+2].vy);
|
||||||
|
|
||||||
// Rotate, translate, and project the vectors and output the results into a primitive
|
// Rotate, translate, and project the vectors and output the results into a primitive
|
||||||
|
|
||||||
OTz = RotTransPers(&model->tmesh->v[model->index[t]] , (long*)&poly->x0, &p, &Flag);
|
OTz = RotTransPers(&model->tmesh->v[model->index[t]] , (long*)&poly->x0, &p, &Flag);
|
||||||
OTz += RotTransPers(&model->tmesh->v[model->index[t+1]], (long*)&poly->x1, &p, &Flag);
|
OTz += RotTransPers(&model->tmesh->v[model->index[t+1]], (long*)&poly->x1, &p, &Flag);
|
||||||
OTz += RotTransPers(&model->tmesh->v[model->index[t+2]], (long*)&poly->x2, &p, &Flag);
|
OTz += RotTransPers(&model->tmesh->v[model->index[t+2]], (long*)&poly->x2, &p, &Flag);
|
||||||
|
|
||||||
// Sort the primitive into the OT
|
// Sort the primitive into the OT
|
||||||
OTz /= 3;
|
OTz /= 3;
|
||||||
if ((OTz > 0) && (OTz < OTLEN))
|
if ((OTz > 0) && (OTz < OTLEN))
|
||||||
AddPrim(&ot[db][OTz-2], poly);
|
AddPrim(&ot[db][OTz-2], poly);
|
||||||
|
|
||||||
nextpri += sizeof(POLY_GT3);
|
nextpri += sizeof(POLY_GT3);
|
||||||
|
|
||||||
t+=3;
|
t+=3;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dr_mode = (DR_MODE *)nextpri;
|
dr_mode = (DR_MODE *)nextpri;
|
||||||
|
|
||||||
setDrawMode(dr_mode,1,0, getTPage(tim_cube.mode&0x3, 0,
|
setDrawMode(dr_mode,1,0, getTPage(tim_cube.mode&0x3, 0,
|
||||||
tim_cube.prect->x,
|
tim_cube.prect->x,
|
||||||
tim_cube.prect->y), &tws); //set texture window
|
tim_cube.prect->y), &tws); //set texture window
|
||||||
|
|
||||||
AddPrim(&ot[db], dr_mode);
|
AddPrim(&ot[db], dr_mode);
|
||||||
|
|
||||||
nextpri += sizeof(DR_MODE);
|
nextpri += sizeof(DR_MODE);
|
||||||
|
|
||||||
|
|
||||||
FntPrint("Hello overlay!\n");
|
FntPrint("Hello overlay!\n");
|
||||||
|
|
||||||
#ifndef USECD
|
#ifndef USECD
|
||||||
|
FntPrint("loadFileIDwas : %d\n", loadFileIDwas);
|
||||||
FntPrint("Overlay with id %d loaded at 0x%08x", overlayFileID, &load_all_overlays_here);
|
FntPrint("Overlay with id %d loaded at 0x%08x\n", overlayFileID, &load_all_overlays_here );
|
||||||
|
FntPrint("buffer at %08x : %s\n", inBuffer, inBuffer);
|
||||||
|
FntPrint("dataBuffer at %08x : \n %s", dataBuffer, dataBuffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USECD
|
#ifdef USECD
|
||||||
|
|
||||||
FntPrint("File: %s\n", overlayFile);
|
FntPrint("File: %s\n", overlayFile);
|
||||||
|
|
||||||
FntPrint("Bytes read: %d", cdread);
|
FntPrint("Bytes read: %d", cdread);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FntFlush(-1);
|
FntFlush(-1);
|
||||||
|
|
||||||
display();
|
display();
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
787
ovl-upload.py
787
ovl-upload.py
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,293 @@
|
||||||
|
#include "pcdrv.h"
|
||||||
|
void wait(){
|
||||||
|
for(u_int wait = 0; wait < 60; wait++){
|
||||||
|
wait = wait;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
static char sio_read(){
|
||||||
|
char c;
|
||||||
|
c = getchar();
|
||||||
|
return c;
|
||||||
|
};
|
||||||
|
u_int strLen( const char * str){
|
||||||
|
u_int l = 0;
|
||||||
|
while ( * str++ ){
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
// Hashing algorythm from @nicolasnoble : https://github.com/grumpycoders/pcsx-redux/blob/main/src/mips/common/util/djbhash.h
|
||||||
|
static inline uint32_t djbProcess(uint32_t hash, const char str[], unsigned n) {
|
||||||
|
return n ? djbProcess ( ( ( hash << 5 ) + hash ) ^ str[0], str + 1, n - 1) : hash;
|
||||||
|
}
|
||||||
|
static inline uint32_t djbHash( const char* str, unsigned n ){
|
||||||
|
return djbProcess( 5381, str, n);
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
uint32_t charsToU32 ( char * byte ) {
|
||||||
|
unsigned int packet = (byte[0] << 24) | (byte[1] << 16) | (byte[2] << 8) | (byte[3]);
|
||||||
|
return packet;
|
||||||
|
};
|
||||||
|
u_char U32ToChars( u_int memoryAddress, u_int byteNbr){
|
||||||
|
// This one I found on my own )'u'(
|
||||||
|
u_char byte = { 0 };
|
||||||
|
byte = ( (u_int) memoryAddress >> ( 24 - (byteNbr << 3) ) ) & 0xFF;
|
||||||
|
return byte;
|
||||||
|
};
|
||||||
|
void sendU32(uint32_t data) {
|
||||||
|
putchar(data & 0xff);
|
||||||
|
data >>= 8;
|
||||||
|
putchar(data & 0xff);
|
||||||
|
data >>= 8;
|
||||||
|
putchar(data & 0xff);
|
||||||
|
data >>= 8;
|
||||||
|
putchar(data & 0xff);
|
||||||
|
};
|
||||||
|
void sendRU32(uint32_t data) {
|
||||||
|
putchar((data >> 24) & 0xff);
|
||||||
|
putchar((data >> 16) & 0xff);
|
||||||
|
putchar((data >> 8) & 0xff);
|
||||||
|
putchar(data & 0xff);
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
int waitForSIODone( const char * answer, volatile char * bufferAddress){
|
||||||
|
// This watches the buffer at &bufferAddress and waits for it to contain the first two chars of answer,
|
||||||
|
// which is sent by the server when PC->PSX data upload is over.
|
||||||
|
// If answer is OK, act as ACK. If answer is DT, the next 2 chars contains data.
|
||||||
|
// Returns 1 if ok, 0 else.
|
||||||
|
// Return value
|
||||||
|
int SIOdone = 0;
|
||||||
|
// Error code sent by the PC
|
||||||
|
const char * error = "-1";
|
||||||
|
// Mini buffer for the data when two first chars are DT
|
||||||
|
char returnValue[BUFFER_LEN] = {0};
|
||||||
|
// Counter to avoid infinite loop
|
||||||
|
int i = 0;
|
||||||
|
while(1){
|
||||||
|
// Continually get the content at &bufferAddress
|
||||||
|
const char * buffer = ( const char * )bufferAddress;
|
||||||
|
// Rolling buffer
|
||||||
|
if( strlen( buffer ) > BUFFER_LEN){
|
||||||
|
memmove( ( char * ) buffer, buffer + 1, strlen(buffer));
|
||||||
|
}
|
||||||
|
// Check inBuffer for answer
|
||||||
|
// If buffer does not contain "-1"
|
||||||
|
if ( buffer[0] != error[0] && buffer[1] != error[1] ){
|
||||||
|
// If two first chars == answer
|
||||||
|
if( (buffer[0] == answer[0]) &&
|
||||||
|
(buffer[1] == answer[1]) ){ // "DT369000"
|
||||||
|
memmove( ( char * ) buffer, buffer + 2, strlen(buffer)); // "36900000"
|
||||||
|
//~ returnValue[0] = buffer[0];
|
||||||
|
//~ returnValue[1] = buffer[1];
|
||||||
|
for(short i = 0; i < BUFFER_LEN; i++){ // "00000000" >
|
||||||
|
returnValue[i] = buffer[i];
|
||||||
|
}
|
||||||
|
//~ returnValue[0] = buffer[2];
|
||||||
|
//~ returnValue[1] = buffer[3];
|
||||||
|
//~ returnValue[2] = buffer[4];
|
||||||
|
// Get data as int
|
||||||
|
SIOdone = atoi(returnValue);
|
||||||
|
// Empty buffer
|
||||||
|
for (short i; i < BUFFER_LEN; i++ ){ bufferAddress[i] = 0; }
|
||||||
|
// Return data
|
||||||
|
return SIOdone;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
// Avoid infinite loop
|
||||||
|
if ( i > 3000 ){
|
||||||
|
// empty buffer
|
||||||
|
for ( short i; i < BUFFER_LEN;i++ ){ bufferAddress[i] = 0; }
|
||||||
|
// Get out of function after X iterations
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Should never be reached, but just to be sure
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
u_short PCload( u_long * loadAddress, volatile u_char * bufferAddress, u_char * overlayFileID ) {
|
||||||
|
// Send filename , load address, and flag address
|
||||||
|
// Returns 1 if ok, 0 else
|
||||||
|
// E.G : 00 01 06 04 80010000 08 80010001 01 + 0000000000 <- cmd checksum
|
||||||
|
// 00 01 06 08 8003edf8 08 8001f0f0 00 2439964735 -> 38 Bytes
|
||||||
|
// Expected answer
|
||||||
|
const char * answer = "OK";
|
||||||
|
// Using hardcoded length of 28 B
|
||||||
|
char commandBuffer[28];
|
||||||
|
// pointer is 4 B, but represented here by 8 B / chars.
|
||||||
|
u_short addLenInChar = sizeof(loadAddress) * 2;
|
||||||
|
sprintf(commandBuffer, "%02u%02u%02u%02u%08x%02u%08x%02u", ESCAPE, PROTOCOL, LOAD, addLenInChar, loadAddress, addLenInChar, bufferAddress, *overlayFileID);
|
||||||
|
u_int cmdChecksum = djbHash(commandBuffer, 28);
|
||||||
|
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
|
||||||
|
// Need delay ?
|
||||||
|
wait();
|
||||||
|
return waitForSIODone( answer , bufferAddress );
|
||||||
|
};
|
||||||
|
int PCinit( volatile u_char * bufferAddress ){
|
||||||
|
// Close all the files on the PC.
|
||||||
|
// Returns OK if success, -1 if fail
|
||||||
|
// E.G : 00 01 07 + 00 00 00 00 00
|
||||||
|
const char * answer = "OK";
|
||||||
|
u_int bufferLen = 16;
|
||||||
|
char commandBuffer[ bufferLen ];
|
||||||
|
sprintf(commandBuffer, "%02u%02u%02u08%08x", ESCAPE, PROTOCOL, INIT, bufferAddress);
|
||||||
|
u_int cmdChecksum = djbHash( commandBuffer, bufferLen);
|
||||||
|
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
|
||||||
|
wait();
|
||||||
|
return waitForSIODone( answer, bufferAddress );
|
||||||
|
};
|
||||||
|
int PCclose( int fileDesc, volatile u_char * bufferAddress ){
|
||||||
|
// Close file corresponding to fileDesc
|
||||||
|
// Returns OK if success, -1 if fail
|
||||||
|
// E.G : 00 01 01 16 + 00 00 00 00 00
|
||||||
|
const char * answer = "OK";
|
||||||
|
u_int bufferLen = 8;
|
||||||
|
char commandBuffer[ bufferLen ];
|
||||||
|
sprintf(commandBuffer, "%02u%02u%02u%02u", ESCAPE, PROTOCOL, CLOSE, fileDesc);
|
||||||
|
u_int cmdChecksum = djbHash( commandBuffer, bufferLen);
|
||||||
|
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
|
||||||
|
wait();
|
||||||
|
return waitForSIODone( answer, bufferAddress );
|
||||||
|
};
|
||||||
|
int PCopen( const char * filename, u_char mode, volatile u_char * bufferAddress ){
|
||||||
|
// Open filename in mode
|
||||||
|
// Returns file descriptor or -1 if fail
|
||||||
|
// Mode can be 00 (RO), 01(WO), 02 (RW) (see pcdrv.h, l.52)
|
||||||
|
// E.G : 00 01 00 08 48454C4F 00 + 0000000000 <- cmd checksum 18 + CHECKSUM_LEN B
|
||||||
|
// Expected answer DaTa + 2 chars of data
|
||||||
|
const char * answer = "DT";
|
||||||
|
// Should we allow names > 8 chars ? If so, use strlen() to determine buffer length
|
||||||
|
u_int bufferLen = 20 + strlen( filename ); // else use a length of 28
|
||||||
|
u_short addLenInChar = sizeof(bufferAddress) * 2;
|
||||||
|
char commandBuffer[ bufferLen ];
|
||||||
|
sprintf(commandBuffer, "%02u%02u%02u%02u%*s%02u%08x%02u", ESCAPE, PROTOCOL, OPEN, strlen( filename ), strlen( filename ), filename, addLenInChar, bufferAddress, mode);
|
||||||
|
u_int cmdChecksum = djbHash( commandBuffer, bufferLen);
|
||||||
|
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
|
||||||
|
wait();
|
||||||
|
return waitForSIODone( answer, bufferAddress );
|
||||||
|
};
|
||||||
|
int PCcreate( const char * filename, u_char mode, volatile u_char * bufferAddress ){
|
||||||
|
// Create and open file with filename in mode
|
||||||
|
// Returns file descriptor or -1 if fail
|
||||||
|
// Mode can be 00 (RO), 01(WO), 02 (RW) (see pcdrv.h, l.52)
|
||||||
|
// E.G : 00 01 00 08 48454C4F 00 + 0000000000 <- cmd checksum 18 + CHECKSUM_LEN B
|
||||||
|
// Expected answer DaTa + 2 chars of data
|
||||||
|
const char * answer = "DT";
|
||||||
|
u_int bufferLen = 20 + strlen( filename );
|
||||||
|
u_short addLenInChar = sizeof(bufferAddress) * 2;
|
||||||
|
char commandBuffer[ bufferLen ];
|
||||||
|
sprintf(commandBuffer, "%02u%02u%02u%02u%*s%02u%08x%02u", ESCAPE, PROTOCOL, CREATE, strlen( filename ), strlen( filename ), filename, addLenInChar, bufferAddress, mode);
|
||||||
|
u_int cmdChecksum = djbHash( commandBuffer, bufferLen);
|
||||||
|
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
|
||||||
|
wait();
|
||||||
|
return waitForSIODone( answer, bufferAddress );
|
||||||
|
};
|
||||||
|
int PCseek( int fd, int curPos, int offset, int accessMode, volatile u_char * bufferAddress ){
|
||||||
|
// Seek offset in file
|
||||||
|
// Return new position or -1 if fail
|
||||||
|
// accessMode can be relative to start : 0 , relative to current pos : 1 , relative to end of file : 2
|
||||||
|
// E.G : 00 01 02 02 09 08 00000000 08 00000369 08 80025808 01 1907502951
|
||||||
|
const char * answer = "DT";
|
||||||
|
u_int bufferLen = 42; // Will we need file desc > 99 ?
|
||||||
|
char commandBuffer[ bufferLen ];
|
||||||
|
sprintf(commandBuffer, "%02u%02u%02u02%02u08%08d08%08d08%08x%02u", ESCAPE, PROTOCOL, SEEK, fd, curPos, offset, bufferAddress, accessMode);
|
||||||
|
u_int cmdChecksum = djbHash( commandBuffer, bufferLen);
|
||||||
|
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
|
||||||
|
wait();
|
||||||
|
return waitForSIODone( answer, bufferAddress );
|
||||||
|
};
|
||||||
|
int PCread( int fd, int pos, int len, volatile char * dataBuffer, volatile char * bufferAddress ){
|
||||||
|
// Read and returns len bytes at pos on file fd
|
||||||
|
// Send read bytes to dataBuffer
|
||||||
|
// Return OK or -1 if fail
|
||||||
|
// E.G : 00 01 03 02 88 08 00000369 08 00000016 08 80025808 08 80025848 1841163114
|
||||||
|
const char * answer = "OK";
|
||||||
|
u_int bufferLen = 50;
|
||||||
|
char commandBuffer[ bufferLen ];
|
||||||
|
sprintf(commandBuffer, "%02u%02u%02u02%02u08%08d08%08d08%08x08%08x", ESCAPE, PROTOCOL, READ, fd, pos, len, dataBuffer, bufferAddress);
|
||||||
|
u_int cmdChecksum = djbHash( commandBuffer, bufferLen);
|
||||||
|
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
|
||||||
|
wait();
|
||||||
|
return waitForSIODone( answer, bufferAddress );
|
||||||
|
};
|
||||||
|
int PCwrite( int fd, int pos, int len, volatile u_char * dataBuffer, volatile u_char * bufferAddress ){
|
||||||
|
// Send len bytes from dataBuffer to be written in file fd at pos
|
||||||
|
// Return OK or -1 if fail
|
||||||
|
// E.G : 00 01 04 02 88 08 00000000 08 00000016 16 ALLEZONYVALESENF 08 80025808 4060903934
|
||||||
|
const char * answer = "OK";
|
||||||
|
// Add space for null terminator
|
||||||
|
u_char tempBuffer[len + 1];
|
||||||
|
// Fill tempBuffer with data at dataBuffer
|
||||||
|
for( int b = 0; b < len; b++ ){
|
||||||
|
tempBuffer[b] = dataBuffer[b];
|
||||||
|
}
|
||||||
|
// Set null terminator
|
||||||
|
tempBuffer[len] = 0;
|
||||||
|
u_int bufferLen = 42 + len;
|
||||||
|
char commandBuffer[ bufferLen ];
|
||||||
|
sprintf(commandBuffer, "%02u%02u%02u02%02u08%08d08%08d%02u%*s08%08x", ESCAPE, PROTOCOL, WRITE, fd, pos, len, len, len, tempBuffer, bufferAddress);
|
||||||
|
u_int cmdChecksum = djbHash( commandBuffer, bufferLen);
|
||||||
|
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
|
||||||
|
wait();
|
||||||
|
return waitForSIODone( answer, bufferAddress );
|
||||||
|
};
|
||||||
|
// WIP : Build command for use with putchar instead of printf
|
||||||
|
/*
|
||||||
|
void BuildCmd(){
|
||||||
|
// Build command in the buffer
|
||||||
|
u_char escape = 0x00; // Hypothetical Escape char for unirom
|
||||||
|
u_char protocol = 0x01; // Hypothetical protocol indicator for unirom
|
||||||
|
// Command is 18 B data + 10 B checksum
|
||||||
|
char commandBuffer[28] = {0};
|
||||||
|
u_char checkSumLen = 10;
|
||||||
|
short i = 0;
|
||||||
|
u_long * loadAddress;
|
||||||
|
u_char * flagAddress;
|
||||||
|
// FntPrint("%x\n", loadAddress);
|
||||||
|
while( i < sizeof( commandBuffer) - checkSumLen ){
|
||||||
|
if( i == 0 ){
|
||||||
|
commandBuffer[0] = escape;
|
||||||
|
commandBuffer[1] = protocol;
|
||||||
|
i = 2;
|
||||||
|
}
|
||||||
|
if( i == 2 ){
|
||||||
|
commandBuffer[i] = LOAD;
|
||||||
|
i ++;
|
||||||
|
}
|
||||||
|
commandBuffer[i] = sizeof(&loadAddress);
|
||||||
|
i ++;
|
||||||
|
for( u_int b = 0; b < sizeof(&loadAddress); b++ ){
|
||||||
|
commandBuffer[i] = U32ToChars( ( u_int ) loadAddress, b );
|
||||||
|
// FntPrint("i: %d b: %d, %02x\n", i, b, commandBuffer[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
commandBuffer[i] = sizeof(&flagAddress);
|
||||||
|
i ++;
|
||||||
|
for( u_int b = 0; b < sizeof(&flagAddress); b++ ){
|
||||||
|
commandBuffer[i] = U32ToChars( ( u_int ) flagAddress, b );
|
||||||
|
// FntPrint("i: %d b: %d, %02x\n", i, b, commandBuffer[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
// commandBuffer[i] = overlayFileID;
|
||||||
|
i++;
|
||||||
|
for(short c = 0; c < sizeof(commandBuffer) - checkSumLen; c++){
|
||||||
|
// FntPrint("%x", commandBuffer[c]);
|
||||||
|
}
|
||||||
|
// FntPrint("\n%d, %d", i, sizeof(commandBuffer) );
|
||||||
|
}
|
||||||
|
for(u_int b = 0; b < sizeof(commandBuffer)-3; b+=4 ){
|
||||||
|
u_char bytes[4] = {0};
|
||||||
|
bytes[0] = commandBuffer[b + 0];
|
||||||
|
bytes[1] = commandBuffer[b + 1];
|
||||||
|
bytes[2] = commandBuffer[b + 2];
|
||||||
|
bytes[3] = commandBuffer[b + 3];
|
||||||
|
sendU32( charsToU32(bytes) );
|
||||||
|
}
|
||||||
|
// u_int cmdChecksum = djbHash((const char * )commandBuffer, sizeof(commandBuffer) - checkSumLen);
|
||||||
|
// FntPrint("\n%d\n", cmdChecksum);
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,63 @@
|
||||||
|
// https://discord.com/channels/642647820683444236/646765703143227394/836663602718048297
|
||||||
|
// 28-04-2021 - @nicolasnoble:
|
||||||
|
//
|
||||||
|
// step 0 : have a protocol that can handle open / close / seek / read / write
|
||||||
|
//
|
||||||
|
// step 1 : have an unhandled exception handler installed in the kernel to capture the pcdrv functions; that sounds scary, but it's extremely straightforward (I think @sickle currently has one for his debugger)
|
||||||
|
//
|
||||||
|
// step 1.5: implement the pcopen / pcclose / pcread / pcwrite / pcseek functions, which are basically the same model as my syscalls.h file
|
||||||
|
//
|
||||||
|
// step 2 : implement the unhandler exception handler in a way that properly redirects the calls to the step 0 protocol, and returns gracefully to the caller when done - that can be a bit tricky, but it's totally doable
|
||||||
|
// this step requires understanding the ReturnFromException mechanism basically which, to be fair, is sort of understandable from this one file:
|
||||||
|
// https://github.com/grumpycoders/pcsx-redux/blob/main/src/mips/openbios/handlers/syscall.c
|
||||||
|
// you can see the syscall_unresolvedException() call at the bottom , this just needs to follow the same pattern
|
||||||
|
// and break down the caller, modify the current thread's registers, and return to the caller
|
||||||
|
// at this point, we have a working basic pcdrv feature, using pcopen / pcclose / pcread / pcwrite / pcseek
|
||||||
|
//
|
||||||
|
// step 3 : add a kernel driver for "pcdrv:" that just piggy backs on pc* functions so that people can simply do a int file = open("pcdrv:blah.txt", O_RDONLY);
|
||||||
|
// (and thus support things like CSOTN technically)
|
||||||
|
//
|
||||||
|
// https://discord.com/channels/642647820683444236/646765703143227394/837416216640618558
|
||||||
|
// So like we'd have, say,
|
||||||
|
// 00 01 00 03 58 58 58 01 xx for pcdrv' file open to open the file name "XXX" and attribute 1
|
||||||
|
// (escape) (pcdrv command) (pcdrv open) (filename with length as prefix) (attributes) (checksum)
|
||||||
|
#pragma once
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
//~ #include <libsio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define BUFFER_LEN 8
|
||||||
|
#define ESCAPE 0x00 // Hypothetical Escape char for unirom
|
||||||
|
#define PROTOCOL 0x01
|
||||||
|
//pcdrv commands
|
||||||
|
#define OPEN 0x00
|
||||||
|
#define CLOSE 0x01
|
||||||
|
#define SEEK 0x02
|
||||||
|
#define READ 0x03
|
||||||
|
#define WRITE 0x04
|
||||||
|
#define CREATE 0x05
|
||||||
|
#define LOAD 0x06
|
||||||
|
#define INIT 0x07
|
||||||
|
// flags parameters
|
||||||
|
#define O_RDONLY 0x00
|
||||||
|
#define O_WRONLY 0x01
|
||||||
|
#define O_RDWR 0x02
|
||||||
|
#define CHECKSUM_LEN 10
|
||||||
|
//~ static char sio_read();
|
||||||
|
int waitForSIODone( const char * answer, volatile char * bufferAddress);
|
||||||
|
static inline uint32_t djbHash( const char* str, unsigned n );
|
||||||
|
static inline uint32_t djbProcess(uint32_t hash, const char str[], unsigned n);
|
||||||
|
//~ uint32_t charsToU32 ( char * byte );
|
||||||
|
//~ u_char U32ToChars( u_int memoryAddress, u_int byteNbr);
|
||||||
|
//~ void sendU32(uint32_t data);
|
||||||
|
//~ void sendRU32(uint32_t data);
|
||||||
|
u_short PCload( u_long * loadAddress, volatile u_char * bufferAddress, u_char * overlayFileID );
|
||||||
|
int PCinit( volatile u_char * bufferAddress );
|
||||||
|
int PCclose( int fileDesc, volatile u_char * bufferAddress );
|
||||||
|
int PCopen( const char * filename, u_char mode, volatile u_char * bufferAddress );
|
||||||
|
int PCcreate( const char * filename, u_char mode, volatile u_char * bufferAddress );
|
||||||
|
int PCseek( int fd, int curPos, int offset, int accessMode, volatile u_char * bufferAddress );
|
||||||
|
int PCread( int fd, int pos, int len, volatile char * dataBuffer, volatile char * bufferAddress );
|
||||||
|
int PCwrite( int fd, int pos, int len, volatile u_char * dataBuffer, volatile u_char * bufferAddress );
|
Loading…
Reference in New Issue