ovl-upload/pcdrv.c

295 lines
6.1 KiB
C

#include "pcdrv.h"
void wait(){
for(u_int wait = 0; wait < 100; 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);
};
u_short waitForSIODone( volatile u_char * bufferAddress){
// This should wait for a signal from the SIO to tell when it's done
// Returns 1 if ok, 0 else
const char * OKYA = "OKYA";
u_char SIOdone = 0;
int i = 0;
while(1){
const u_char * buffer = ( const u_char * )bufferAddress;
// Rolling buffer
if( strlen( buffer ) > 4){
memmove( ( u_char * ) buffer, buffer + 1, strlen(buffer));
}
// Check inBuffer for answer
if( strcmp(buffer, OKYA) == 0 ){
SIOdone = 1;
break;
}
i++;
// Avoid infinite loop
if ( i > 1000 ){
break;
}
}
for (short i; i < 4;i++){ bufferAddress[i] = 0; }
return SIOdone;
};
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
char commandBuffer[28];
sprintf(commandBuffer, "%02u%02u%02u%02u%08x%02u%08x%02u", ESCAPE, PROTOCOL, LOAD, sizeof(loadAddress), loadAddress,sizeof(bufferAddress), bufferAddress, *overlayFileID);
u_int cmdChecksum = djbHash(commandBuffer, 28);
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
// Need delay ?
wait();
return waitForSIODone(bufferAddress);
};
int PCopen( const char * filename, u_char mode, volatile u_char * bufferAddress ){
// Open filename in mode
// Returns file descriptor or -1 if fail
// E.G : 00 01 00 04 48454C4F 00 + 0000000000 <- cmd checksum 18 + CHECKSUM_LEN B
u_int bufferLen = 10 + strlen( filename );
char commandBuffer[ bufferLen ];
sprintf(commandBuffer, "%02u%02u%02u%02u%*s%02u", ESCAPE, PROTOCOL, OPEN, strlen( filename ), strlen( filename ), filename, mode);
u_int cmdChecksum = djbHash( commandBuffer, bufferLen);
printf("%s%*u", commandBuffer, CHECKSUM_LEN, cmdChecksum);
wait();
return waitForSIODone(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);
}