#159192 - cornaljoe - Thu Jun 26, 2008 6:03 pm
Here is the code I'm using:
It's a modified version of Chishm dldi_chain demo posted here. I use this function in place of fatInitDefault() in order to load 2 FAT systems.
Everything seems fine only the custom interface thats loaded from 'fat0:/fat3.dldi' is only readable. When attempting to write to the disk (fat3:/) it writes a 0 byte file and freezes the DS. Anyone know how I can fix this? Thanks for the help.
Last edited by cornaljoe on Sat Jul 05, 2008 3:25 am; edited 1 time in total
Code: |
/*---------------------------------------------------------------------------------
Quick DLDI chaining example Loads "/fat3.dldi" from the first device, then uses that to read from a second device. This is quickly written, messy code. No warranty is given. Copyright 2007 by Michael "Chishm" Chisholm ---------------------------------------------------------------------------------*/ #include <nds.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fat.h> #include <malloc.h> #include <stdio.h> #include <string.h> #include <sys/dir.h> #include <sys/stat.h> #include "dldi_chain.h" #ifdef __cplusplus extern "C" { #endif #define MAGIC_TOKEN 0xBF8DA5ED #define FIX_ALL 0x01 #define FIX_GLUE 0x02 #define FIX_GOT 0x04 #define FIX_BSS 0x08 #define DLDI_VERSION 1 enum DldiOffsets { DO_magicString = 0x00, // "\xED\xA5\x8D\xBF Chishm" DO_magicToken = 0x00, // 0xBF8DA5ED DO_magicShortString = 0x04, // " Chishm" DO_version = 0x0C, DO_driverSize = 0x0D, DO_fixSections = 0x0E, DO_allocatedSpace = 0x0F, DO_friendlyName = 0x10, DO_text_start = 0x40, // Data start DO_data_end = 0x44, // Data end DO_glue_start = 0x48, // Interworking glue start -- Needs address fixing DO_glue_end = 0x4C, // Interworking glue end DO_got_start = 0x50, // GOT start -- Needs address fixing DO_got_end = 0x54, // GOT end DO_bss_start = 0x58, // bss start -- Needs setting to zero DO_bss_end = 0x5C, // bss end DO_driverStart = 0x60, // IO_INTERFACE data DO_ioType = 0x60, DO_features = 0x64, DO_startup = 0x68, DO_isInserted = 0x6C, DO_readSectors = 0x70, DO_writeSectors = 0x74, DO_clearStatus = 0x78, DO_shutdown = 0x7C, DO_code = 0x80 }; const u8 dldiMagicString[] = "\xED\xA5\x8D\xBF Chishm"; #define READ_ADDR(d,o) (*(u32*)((d)+(o))) #define WRITE_ADDR(d,o,v) *(u32*)((d)+(o)) = (v) int dldiPatch (u8* data, u32 len) { unsigned int memOffset, ddmemOffset, relocationOffset; unsigned int ddmemStart, ddmemSize, ddmemEnd; unsigned int addrIter; // Make sure the DLDI file is valid and usable if (strcmp ((char*)dldiMagicString, (char*)&data[DO_magicString]) != 0) { return -1; } if (data[DO_version] != DLDI_VERSION) { return -1; } memOffset = (u32)data; ddmemOffset = READ_ADDR (data, DO_text_start); relocationOffset = memOffset - ddmemOffset; ddmemStart = READ_ADDR (data, DO_text_start); ddmemSize = (1 << data[DO_driverSize]); ddmemEnd = ddmemStart + ddmemSize; // Fix the section pointers in the header WRITE_ADDR (data, DO_text_start, READ_ADDR (data, DO_text_start) + relocationOffset); WRITE_ADDR (data, DO_data_end, READ_ADDR (data, DO_data_end) + relocationOffset); WRITE_ADDR (data, DO_glue_start, READ_ADDR (data, DO_glue_start) + relocationOffset); WRITE_ADDR (data, DO_glue_end, READ_ADDR (data, DO_glue_end) + relocationOffset); WRITE_ADDR (data, DO_got_start, READ_ADDR (data, DO_got_start) + relocationOffset); WRITE_ADDR (data, DO_got_end, READ_ADDR (data, DO_got_end) + relocationOffset); WRITE_ADDR (data, DO_bss_start, READ_ADDR (data, DO_bss_start) + relocationOffset); WRITE_ADDR (data, DO_bss_end, READ_ADDR (data, DO_bss_end) + relocationOffset); // Fix the function pointers in the header WRITE_ADDR (data, DO_startup, READ_ADDR (data, DO_startup) + relocationOffset); WRITE_ADDR (data, DO_isInserted, READ_ADDR (data, DO_isInserted) + relocationOffset); WRITE_ADDR (data, DO_readSectors, READ_ADDR (data, DO_readSectors) + relocationOffset); WRITE_ADDR (data, DO_writeSectors, READ_ADDR (data, DO_writeSectors) + relocationOffset); WRITE_ADDR (data, DO_clearStatus, READ_ADDR (data, DO_clearStatus) + relocationOffset); WRITE_ADDR (data, DO_shutdown, READ_ADDR (data, DO_shutdown) + relocationOffset); if (data[DO_fixSections] & FIX_ALL) { // Search through and fix pointers within the data section of the file for (addrIter = (READ_ADDR(data, DO_text_start) - ddmemStart); addrIter < (READ_ADDR(data, DO_data_end) - ddmemStart); addrIter++) { if ((ddmemStart <= READ_ADDR(data, addrIter)) && (READ_ADDR(data, addrIter) < ddmemEnd)) { WRITE_ADDR (data, addrIter, READ_ADDR(data, addrIter) + relocationOffset); } } } if (data[DO_fixSections] & FIX_GLUE) { // Search through and fix pointers within the glue section of the file for (addrIter = (READ_ADDR(data, DO_glue_start) - ddmemStart); addrIter < (READ_ADDR(data, DO_glue_end) - ddmemStart); addrIter++) { if ((ddmemStart <= READ_ADDR(data, addrIter)) && (READ_ADDR(data, addrIter) < ddmemEnd)) { WRITE_ADDR (data, addrIter, READ_ADDR(data, addrIter) + relocationOffset); } } } if (data[DO_fixSections] & FIX_GOT) { // Search through and fix pointers within the Global Offset Table section of the file for (addrIter = (READ_ADDR(data, DO_got_start) - ddmemStart); addrIter < (READ_ADDR(data, DO_got_end) - ddmemStart); addrIter++) { if ((ddmemStart <= READ_ADDR(data, addrIter)) && (READ_ADDR(data, addrIter) < ddmemEnd)) { WRITE_ADDR (data, addrIter, READ_ADDR(data, addrIter) + relocationOffset); } } } if (data[DO_fixSections] & FIX_BSS) { // Initialise the BSS to 0 memset (&data[READ_ADDR(data, DO_bss_start) - ddmemStart] , 0, READ_ADDR(data, DO_bss_end) - READ_ADDR(data, DO_bss_start)); } return 0; } //--------------------------------------------------------------------------------- void CustomFatInit() { //--------------------------------------------------------------------------------- fatInitDefault(); FILE* customDriver = fopen ("/fat3.dldi", "rb"); if (customDriver == NULL) { while(1) swiWaitForVBlank(); } fseek (customDriver, 0, SEEK_END); size_t driverSize = ftell (customDriver); fseek (customDriver, 0, SEEK_SET); u8* driverData = malloc (driverSize); fread (driverData, 1, driverSize, customDriver); fclose (customDriver); if (dldiPatch (driverData, driverSize) < 0) { while(1) swiWaitForVBlank(); } fatMountCustomInterface ((struct IO_INTERFACE_STRUCT*) (driverData + DO_driverStart), 8); } #ifdef __cplusplus } #endif |
It's a modified version of Chishm dldi_chain demo posted here. I use this function in place of fatInitDefault() in order to load 2 FAT systems.
Everything seems fine only the custom interface thats loaded from 'fat0:/fat3.dldi' is only readable. When attempting to write to the disk (fat3:/) it writes a 0 byte file and freezes the DS. Anyone know how I can fix this? Thanks for the help.
Last edited by cornaljoe on Sat Jul 05, 2008 3:25 am; edited 1 time in total