diff --git a/ovl-upload.c b/ovl-upload.c index dde479b..514c5b7 100644 --- a/ovl-upload.c +++ b/ovl-upload.c @@ -36,7 +36,8 @@ #include "pcdrv.h" // 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 @@ -126,12 +127,10 @@ u_char command = LOAD; // We're loading the data here uint32_t checkSum = 0; -//~ const char OKAY[4] = "OKYA"; +volatile u_char inBuffer[BUFFER_LEN] = {0}; -volatile u_char inBuffer[4] = " "; +volatile u_char dataBuffer[64] = "ALLEZONYVALESENFANTS"; -//~ char byte; - // Prototypes void init(void); @@ -176,7 +175,7 @@ void init(){ // Init font system FntLoad(960, 0); - FntOpen(16, 16, 196, 96, 0, 356); + FntOpen(16, 16, 196, 196, 0, 512); } @@ -213,6 +212,10 @@ void LoadTexture(u_long * tim, TIM_IMAGE * tparam){ // This part is from Lam } +int returnVal = 0; + +int fileCreated = 0; + int main() { // Update this value to avoid trigger at launch @@ -273,16 +276,24 @@ int main() { LoadTexture(_binary_TIM_cubetex_tim_start, &tim_cube); // Main loop + while (1) { + FntPrint("%08d - ", returnVal); + + //~ if ( returnVal > 0 ){ + + //~ returnVal = PCopen("HELO.WLD", O_RDWR, inBuffer); + + //~ fileCreated = returnVal; + + //~ returnVal = 0; + //~ } + // Overlay switch if ( overlayFileID != loadFileIDwas ){ - // Update previous file value - - loadFileIDwas = overlayFileID; - // Change file to load switch ( overlayFileID ){ @@ -315,22 +326,30 @@ int main() { #ifndef USECD - if (! PCload( &load_all_overlays_here, inBuffer, &overlayFileID ) ){ + //~ returnVal = PCopen("HELO.WLD", O_RDWR, inBuffer); + //~ returnVal = PCcreate("HELO.WLD", 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 ( returnVal ){ - overlayFileID = !overlayFileID; + loadFileIDwas = overlayFileID; - loadFileIDwas = !loadFileIDwas; - - }; - + } + #endif #ifdef USECD cdread = CdReadFile( (char *)(overlayFile), &load_all_overlays_here, 0); - - CdReadSync(0, 0); + if ( CdReadSync(0, 0) == 0 ){ + + loadFileIDwas = overlayFileID; + + } + #endif } @@ -352,7 +371,7 @@ int main() { if ( ( PadStatus & PADselect ) && !timer ) { overlayFileID = !overlayFileID; - + timer = 150; } @@ -446,6 +465,8 @@ int main() { FntPrint("buffer at %08x : %s\n", inBuffer, inBuffer); + FntPrint("dataBuffer at %08x : \n %s", dataBuffer, dataBuffer); + #endif #ifdef USECD diff --git a/ovl-upload.py b/ovl-upload.py index 9688778..d735513 100755 --- a/ovl-upload.py +++ b/ovl-upload.py @@ -40,13 +40,30 @@ pcdrvProtocol = '01' # Commands -LOAD = '06' +OPEN = '00' +CLOSE = '01' +SEEK = '02' +READ = '03' +WRITE = '04' +CREAT = '05' +LOAD = '06' +INIT = '07' -OPEN = '00' +# Param sets -loadParams = {'memAddr':-1,'bufferAddr':-1, 'loadFile':-1} +loadParams = {'memAddr':-1, 'loadFile':-1, 'bufferAddr':-1} -openParams = {'fileName':-1,'bufferAddr':-1,'mode':-1} +creatParams = {'fileName':-1, 'bufferAddr':-1, 'mode':-1} + +openParams = {'fileName':-1, 'bufferAddr':-1,'mode':-1 } + +closeParams = {'fileDesc':-1, 'bufferAddr':-1} + +seekParams = {'fileDesc':-1,'curPos': -1,'offset':-1, 'bufferAddr':-1, 'accessMode':-1} + +readParams = {'fileDesc':-1,'pos': -1, 'length':-1, 'dataAddr':-1, 'bufferAddr':-1} + +writeParams = {'fileDesc':-1,'pos': -1, 'length':-1, 'data':-1, 'bufferAddr':-1} paramBuffer = {} @@ -101,6 +118,26 @@ Transfer = 0 sleepTime = 0.08 # Seems like safe minimum +# https://www.tutorialspoint.com/How-to-close-all-the-opened-files-using-Python + +class openFiles(): + + def __init__(self): + + self.files = [] + + def open(self, file_name, mode): + + f = os.open(file_name, mode) + + self.files.append(f) + + return f + + def close(self): + + list( map( lambda f : os.close(f), self.files ) ) + def setDEBG(): global sleepTime, ser, uniDebugMode @@ -122,7 +159,6 @@ def setDEBG(): uniDebugMode = 1 # stole it here : https://gist.github.com/amakukha/7854a3e910cb5866b53bf4b2af1af968 -# TODO : fixit to have the same results as https://github.com/grumpycoders/pcsx-redux/blob/main/src/mips/common/util/djbhash.h def hash_djb2(s): @@ -235,13 +271,15 @@ def getData(dataInBuffer): # Get data length byte + # If only 2 bytes left, dont't bother + if len(dataInBuffer) == 2: parsedData = dataInBuffer dataInBuffer = "" - return [dataInBuffer, parsedData] # does it break ? + return [dataInBuffer, parsedData] dataLen = int( dataInBuffer[:2] ) @@ -515,10 +553,12 @@ def resetListener(): def main(args): + files = openFiles() + while True: global checkSum, checkSumLen, data, Listen, Transfer, dataSize, loadFile, paramBuffer - + # Flush serial buffers to avoid residual data ser.reset_input_buffer() @@ -573,7 +613,6 @@ def main(args): # Remove checksum from data - # ~ inputBuffer = inputBuffer[:28] inputBuffer = inputBuffer[:-checkSumLen] dataCheckSum = hash_djb2(bytes(inputBuffer, 'ascii')) @@ -612,9 +651,18 @@ def main(args): print( "Received Cmd: " + inputBuffer[:2] ) + + # Command butes are OPEN == 00 + + if inputBuffer[:2] == INIT: + + paramTmp = {} + + Command = INIT + # Command bytes are LOAD == 06 - if inputBuffer[:2] == LOAD: + elif inputBuffer[:2] == LOAD: # Set corresponding parameters and mode @@ -629,7 +677,47 @@ def main(args): paramTmp = openParams Command = OPEN + + # Command butes are OPEN == 00 + elif inputBuffer[:2] == CLOSE: + + paramTmp = closeParams + + Command = CLOSE + + # Command butes are OPEN == 00 + + elif inputBuffer[:2] == SEEK: + + paramTmp = seekParams + + Command = SEEK + + # Command butes are OPEN == 00 + + elif inputBuffer[:2] == READ: + + paramTmp = readParams + + Command = READ + + # Command butes are OPEN == 00 + + elif inputBuffer[:2] == WRITE: + + paramTmp = writeParams + + Command = WRITE + + # Command butes are OPEN == 00 + + elif inputBuffer[:2] == CREAT: + + paramTmp = creatParams + + Command = CREAT + else: print("Command not recognized : got " + inputBuffer[:2] ) @@ -661,7 +749,7 @@ def main(args): ser.reset_input_buffer() inputBuffer = "" - + Listen = 0 break @@ -674,14 +762,6 @@ def main(args): inputBuffer = "" break - - # ~ else: - - # ~ ser.reset_input_buffer() - - # ~ inputBuffer = "" - - # ~ break if len(paramBuffer): @@ -695,7 +775,43 @@ def main(args): break + if Command == INIT: + + # Close all opened files + + files.close() + + # Send OK + + SendBin( b'OKYA' , paramBuffer['bufferAddr']) + + if Command == CLOSE: + + fileDesc = paramBuffer['fileDesc'] + + # Close all opened files + + try: + + os.close(fileDesc) + + except OSError as errMsg: + + SendBin( b'-1', paramBuffer['bufferAddr']) + + print(errMsg) + + return 0 + + # Send OK + + SendBin( b'OKYA' , paramBuffer['bufferAddr']) + if Command == LOAD: + + # Load file + + print("Received LOAD.") if DEBUG > 1: @@ -749,17 +865,13 @@ def main(args): print("DONE!") - # ~ else: - - # ~ print(" No filename provided, doing nothing. ") - - # ~ resetListener() - if Command == OPEN: + # Open file + print("Received OPEN.") - # paramBuffer['mode'] can be 0 (RO), 1(WO), 2 (RW) + # paramBuffer['mode'] can be 0 (RO), 1(WO), 2 (RW). See `pcdrv.h` l.52 osMode = os.O_RDONLY @@ -771,26 +883,347 @@ def main(args): osMode = os.O_RDWR - if os.path.isfile( 'work/' + paramBuffer['fileName']): + # ~ if os.path.isfile( 'work/' + paramBuffer['fileName']): - localFile = os.open( 'work/' + paramBuffer['fileName'], osMode ) + try: + # Open file in osMode. + + localFile = files.open( 'work/' + paramBuffer['fileName'], osMode ) + + if DEBUG: + + print("File opened. FD : " + str(localFile)) + + # Return fd. SendBin( b'DT' + bytes( str(localFile), 'ascii' ), paramBuffer['bufferAddr']) - # ~ time.sleep( sleepTime ) - - # ~ SendBin( bytes( str(localFile), 'ascii' ), paramBuffer['bufferAddr']) - - else: + # ~ else: + except OSError as errMsg: SendBin( b'-1', paramBuffer['bufferAddr']) + + print(errMsg + " - Try using PCcreate()") + + return 0 resetListener() print("DONE!") - - # ~ break - + + if Command == CREAT: + + # Create and open file + + print("Received CREAT.") + + # Should we return an error if file exists ? + + if not os.path.isfile( 'work/' + paramBuffer['fileName']): + + # paramBuffer['mode'] can be 0 (RO), 1(WO), 2 (RW) + + osMode = os.O_RDONLY + + if int(paramBuffer['mode']) == 1: + + osMode = os.O_WRONLY + + else: + + osMode = os.O_RDWR + + # We're using osMode | os.O_CREAT as open mode here. + + localFile = files.open( 'work/' + paramBuffer['fileName'], osMode | os.O_CREAT ) + + if DEBUG: + + print("File created. FD : " + str(localFile)) + + # Return fd. + + SendBin( b'DT' + bytes( str(localFile), 'ascii' ), paramBuffer['bufferAddr']) + + else: + + SendBin( b'-1', paramBuffer['bufferAddr']) + + print("File exists ! Use PCopen.") + + resetListener() + + print("DONE!") + + if Command == SEEK: + + # Seek pos in open file + + print("Received SEEK.") + + # mode can be 0 (rel to start), 1(rel to cur pos), 2 (rel to end) + + # ~ fd = int( paramBuffer['fileDesc'] ) + + fd = files.open("work/" + 'HELO.WLD', os.O_RDWR) + + mode = int( paramBuffer['accessMode'] ) + + offset = int( paramBuffer['offset'] ) + + curPos = int( paramBuffer['curPos'] ) + + # get filesize in bytes + + try: + + # fileEnd corresponds to file size in bytes + + fileEnd = os.stat(fd).st_size + + except OSError as errMsg: + + SendBin( b'-1', paramBuffer['bufferAddr']) + + print( errMsg ) + + resetListener() + + return 0 + + # by default, use mode 0 + + pos = offset + + if mode == 1: + + pos = curPos + offset + + if mode == 2: + + pos = fileEnd - offset + + # avoid overflow + + if pos > fileEnd: + + pos = fileEnd + + if pos < 0: + + pos = 0 + + if DEBUG : + + print( "Fd : " + str(fd) + "\n" + + + "Mode : " + str(mode) + "\n" + + + "Ofst : " + str(offset) + "\n" + + + "curPos: "+ str(curPos) + "\n" + + + "Pos : " + str(pos) + + ) + + try: + + # TODO : replace os.lseek() with file.lseek + + curPos = os.lseek( fd, pos, mode ) + + if DEBUG: + + print( "File seeked. CP : " + str(curPos) ) + + # Return fd. + + SendBin( b'DT' + bytes( str(curPos), 'ascii' ), paramBuffer['bufferAddr']) + + except OSError as errMsg: + + SendBin( b'-1', paramBuffer['bufferAddr']) + + print( errMsg ) + + resetListener() + + return 0 + + resetListener() + + print("DONE!") + + if Command == READ: + + # Read from pos in open file + + print("Received READ.") + + # ~ fd = int( paramBuffer['fileDesc'] ) + + fd = files.open("work/" + 'HELO.WLD', os.O_RDWR) + + length = int( paramBuffer['length'] ) + + pos = int( paramBuffer['pos'] ) + + # get filesize in bytes + + try: + + # fileEnd corresponds to file size in bytes + + fileEnd = os.stat(fd).st_size + + except OSError as errMsg: + + SendBin( b'-1', paramBuffer['bufferAddr']) + + print( errMsg ) + + resetListener() + + return 0 + + if DEBUG : + + print( "Fd : " + str(fd) + "\n" + + + "Length : " + str(length) + "\n" + + + "Pos : " + str(pos) + "\n" + + + "dataBuffer : " + paramBuffer['dataAddr'] + ) + + # Avoid overflow + + if pos + length > fileEnd: + + length = fileEnd - pos + + if pos == fileEnd: + + print("End of file reached. Doing nothing") + + SendBin( b'OKYA', paramBuffer['bufferAddr']) + + resetListener() + + return 0 + + try: + + # TODO : replace os.pread() with file.pread + + readBytes = os.pread( fd, length, pos ) + + if DEBUG: + + print( "File read. Bytes : " + str( readBytes ) ) + + # Send data to data buffer + + dataSent = SendBin( readBytes, paramBuffer['dataAddr']) + + # ~ time.sleep(sleepTime) + + # Send OK if all went well + + if dataSent: + + SendBin( b'OKYA', paramBuffer['bufferAddr']) + + except OSError as errMsg: + + SendBin( b'-1', paramBuffer['bufferAddr']) + + print( errMsg ) + + resetListener() + + return 0 + + resetListener() + + print("DONE!") + + if Command == WRITE: + + # Write to pos in open file + + print("Received WRITE.") + + # ~ fd = int( paramBuffer['fileDesc'] ) + + fd = files.open("work/" + 'HELO.WLD', os.O_RDWR) + + length = int( paramBuffer['length'] ) + + pos = int( paramBuffer['pos'] ) + + data = paramBuffer['data'] + + # ~ # Avoid overflow + + # ~ if pos + length > bufferLength: + + # ~ length = bufferLength - pos + + # ~ if pos == bufferLength: + + # ~ print("End of buffer reached. Doing nothing") + + # ~ SendBin( b'OKYA', paramBuffer['bufferAddr']) + + # ~ resetListener() + + # ~ return 0 + + if DEBUG : + + print( "Fd : " + str(fd) + "\n" + + + "Length : " + str(length) + "\n" + + + "Pos : " + str(pos) + "\n" + + + "data : " + data + + ) + + try: + + # TODO : replace os.pread() with file.pread + + writeBytes = os.pwrite( fd, bytes( data, 'ascii' ), pos ) + + if DEBUG: + + print( "Buffer write. Bytes : " + str( writeBytes ) ) + + # Send OK if all went well + + if writeBytes == length: + + SendBin( b'OKYA', paramBuffer['bufferAddr']) + + except OSError as errMsg: + + SendBin( b'-1', paramBuffer['bufferAddr']) + + print( errMsg ) + + resetListener() + + return 0 + + resetListener() + + print("DONE!") + return 0 if __name__ == '__main__': diff --git a/pcdrv.c b/pcdrv.c index c2e5d9f..ad084de 100644 --- a/pcdrv.c +++ b/pcdrv.c @@ -3,13 +3,13 @@ void wait(){ - for(u_int wait = 0; wait < 100; wait++){ + for(u_int wait = 0; wait < 60; wait++){ wait = wait; } }; - +/* static char sio_read(){ char c; @@ -30,6 +30,7 @@ u_int strLen( const char * str){ return l; }; +*/ // Hashing algorythm from @nicolasnoble : https://github.com/grumpycoders/pcsx-redux/blob/main/src/mips/common/util/djbhash.h @@ -44,6 +45,7 @@ static inline uint32_t djbHash( const char* str, unsigned n ){ }; +/* uint32_t charsToU32 ( char * byte ) { unsigned int packet = (byte[0] << 24) | (byte[1] << 16) | (byte[2] << 8) | (byte[3]); @@ -93,55 +95,110 @@ void sendRU32(uint32_t data) { 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"; -u_short waitForSIODone( volatile u_char * bufferAddress){ + // Mini buffer for the data when two first chars are DT + + char returnValue[BUFFER_LEN] = {0}; - // 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; + // Counter to avoid infinite loop int i = 0; while(1){ - const u_char * buffer = ( const u_char * )bufferAddress; + // Continually get the content at &bufferAddress + + const char * buffer = ( const char * )bufferAddress; // Rolling buffer - if( strlen( buffer ) > 4){ + if( strlen( buffer ) > BUFFER_LEN){ - memmove( ( u_char * ) buffer, buffer + 1, strlen(buffer)); + memmove( ( char * ) buffer, buffer + 1, strlen(buffer)); } // Check inBuffer for answer - - if( strcmp(buffer, OKYA) == 0 ){ - - SIOdone = 1; - break; - + // 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 > 1000 ){ + if ( i > 2000 ){ - break; + + // empty buffer + + for ( short i; i < BUFFER_LEN;i++ ){ bufferAddress[i] = 0; } + + // Get out of function after X iterations + + return 0; } } - for (short i; i < 4;i++){ bufferAddress[i] = 0; } + // Should never be reached, but just to be sure - return SIOdone; + return 0; }; @@ -152,9 +209,19 @@ u_short PCload( u_long * loadAddress, volatile u_char * bufferAddress, u_char * // 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]; - sprintf(commandBuffer, "%02u%02u%02u%02u%08x%02u%08x%02u", ESCAPE, PROTOCOL, LOAD, sizeof(loadAddress), loadAddress,sizeof(bufferAddress), bufferAddress, *overlayFileID); + // 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); @@ -163,22 +230,23 @@ u_short PCload( u_long * loadAddress, volatile u_char * bufferAddress, u_char * // Need delay ? wait(); - return waitForSIODone(bufferAddress); + 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 - // E.G : 00 01 00 04 48454C4F 00 + 0000000000 <- cmd checksum 18 + CHECKSUM_LEN B - - u_int bufferLen = 10 + strlen( filename ); - +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 = 6; + char commandBuffer[ bufferLen ]; - sprintf(commandBuffer, "%02u%02u%02u%02u%*s%02u", ESCAPE, PROTOCOL, OPEN, strlen( filename ), strlen( filename ), filename, mode); + sprintf(commandBuffer, "%02u%02u%02u", ESCAPE, PROTOCOL, INIT); u_int cmdChecksum = djbHash( commandBuffer, bufferLen); @@ -186,12 +254,180 @@ int PCopen( const char * filename, u_char mode, volatile u_char * bufferAddress wait(); - return waitForSIODone(bufferAddress); -} + 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]; + + // 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 + sizeof(tempBuffer); + + 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 @@ -261,13 +497,13 @@ void BuildCmd(){ } - //~ commandBuffer[i] = overlayFileID; + // commandBuffer[i] = overlayFileID; i++; for(short c = 0; c < sizeof(commandBuffer) - checkSumLen; c++){ - //~ FntPrint("%x", commandBuffer[c]); + // FntPrint("%x", commandBuffer[c]); } // FntPrint("\n%d, %d", i, sizeof(commandBuffer) ); @@ -292,3 +528,4 @@ void BuildCmd(){ // FntPrint("\n%d\n", cmdChecksum); } +*/ diff --git a/pcdrv.h b/pcdrv.h index 9b2d9f0..90fcdc7 100644 --- a/pcdrv.h +++ b/pcdrv.h @@ -27,10 +27,13 @@ #include #include +#include #include //~ #include #include +#define BUFFER_LEN 8 + #define ESCAPE 0x00 // Hypothetical Escape char for unirom #define PROTOCOL 0x01 @@ -38,12 +41,13 @@ //pcdrv commands #define OPEN 0x00 -#define CLOSE 0x01 +#define CLOSE 0x01 #define SEEK 0x02 #define READ 0x03 #define WRITE 0x04 #define CREATE 0x05 #define LOAD 0x06 +#define INIT 0x07 // flags parameters @@ -51,32 +55,36 @@ #define O_WRONLY 0x01 #define O_RDWR 0x02 -#define CHECKSUM_LEN 9 +#define CHECKSUM_LEN 10 -static char sio_read(); +//~ static char sio_read(); -u_short waitForSIODone( volatile u_char * bufferAddress); +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 ); +//~ uint32_t charsToU32 ( char * byte ); -u_char U32ToChars( u_int memoryAddress, u_int byteNbr); +//~ u_char U32ToChars( u_int memoryAddress, u_int byteNbr); -void sendU32(uint32_t data); +//~ void sendU32(uint32_t data); -void sendRU32(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, int attributes ); +int PCcreate( const char * filename, u_char mode, volatile u_char * bufferAddress ); -int PCclose( int fd ); +int PCseek( int fd, int curPos, int offset, int accessMode, volatile u_char * bufferAddress ); -int PCseek( int fd, int offset, int accessMode ); +int PCread( int fd, int pos, int len, volatile char * dataBuffer, volatile char * bufferAddress ); -int PCread( int fd, int len, char * buffer ); +int PCwrite( int fd, int pos, int len, volatile u_char * dataBuffer, volatile u_char * bufferAddress ); diff --git a/pcdrv.h.gch b/pcdrv.h.gch new file mode 100644 index 0000000..b7b5803 Binary files /dev/null and b/pcdrv.h.gch differ