TopToyLauncher: use 8.3 filename for TTMENU.SYS

Fixes an issue on some SD card
This commit is contained in:
lifehackerhansol 2024-11-01 02:59:00 -07:00
parent 30836cdae3
commit 7ebc6abf53
No known key found for this signature in database
GPG Key ID: 80FB184AFC0B3B0E
11 changed files with 896 additions and 3 deletions

View File

@ -20,6 +20,7 @@
#include "../ui/progresswnd.h" #include "../ui/progresswnd.h"
#include "ILauncher.h" #include "ILauncher.h"
#include "TopToyLauncher.h" #include "TopToyLauncher.h"
#include "libfat_ext/fat_ext.h"
static void resetAndLoop() { static void resetAndLoop() {
DC_FlushAll(); DC_FlushAll();
@ -117,6 +118,7 @@ typedef struct {
// TTMENU.SYS file creation. Sets up parameters for ttpatch.dat // TTMENU.SYS file creation. Sets up parameters for ttpatch.dat
bool TopToyLauncher::prepareTTSYS(void) { bool TopToyLauncher::prepareTTSYS(void) {
char fname[0x1004] = {};
TTSYSHeader* ttsys_header = (TTSYSHeader*)malloc(sizeof(TTSYSHeader)); TTSYSHeader* ttsys_header = (TTSYSHeader*)malloc(sizeof(TTSYSHeader));
ttsys_header->TTSYSMagic[0] = 't'; ttsys_header->TTSYSMagic[0] = 't';
ttsys_header->TTSYSMagic[1] = 't'; ttsys_header->TTSYSMagic[1] = 't';
@ -132,10 +134,12 @@ bool TopToyLauncher::prepareTTSYS(void) {
fseek(TTSYSFile, 0, SEEK_SET); fseek(TTSYSFile, 0, SEEK_SET);
fwrite(ttsys_header, sizeof(TTSYSHeader), 1, TTSYSFile); fwrite(ttsys_header, sizeof(TTSYSHeader), 1, TTSYSFile);
free(ttsys_header); free(ttsys_header);
fatGetAliasPath("fat:/", mRomPath.c_str(), fname);
fseek(TTSYSFile, 0x100, SEEK_SET); fseek(TTSYSFile, 0x100, SEEK_SET);
fwrite(mRomPath.c_str() + 4, 1, 0x1000, TTSYSFile); fwrite(fname + 4, 1, 0x1000, TTSYSFile);
fatGetAliasPath("fat:/", mSavePath.c_str(), fname);
fseek(TTSYSFile, 0x1100, SEEK_SET); fseek(TTSYSFile, 0x1100, SEEK_SET);
fwrite(mSavePath.c_str() + 4, 1, 0x1000, TTSYSFile); fwrite(fname + 4, 1, 0x1000, TTSYSFile);
if (mFlags & PATCH_CHEATS) { if (mFlags & PATCH_CHEATS) {
fseek(TTSYSFile, 0x2100, SEEK_SET); fseek(TTSYSFile, 0x2100, SEEK_SET);
fwrite("/YSMENU.ARP", 1, 0x12, TTSYSFile); fwrite("/YSMENU.ARP", 1, 0x12, TTSYSFile);

View File

@ -0,0 +1,129 @@
// clang-format off
/*
cache.h
The cache is not visible to the user. It should be flushed
when any file is closed or changes are made to the filesystem.
This cache implements a least-used-page replacement policy. This will
distribute sectors evenly over the pages, so if less than the maximum
pages are used at once, they should all eventually remain in the cache.
This also has the benefit of throwing out old sectors, so as not to keep
too many stale pages around.
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _CACHE_H
#define _CACHE_H
#include "fatcommon.h"
typedef struct {
sec_t sector;
unsigned int count;
unsigned int last_access;
bool dirty;
uint8_t* cache;
} CACHE_ENTRY;
typedef struct {
const DISC_INTERFACE* disc;
sec_t endOfPartition;
unsigned int numberOfPages;
unsigned int sectorsPerPage;
unsigned int bytesPerSector;
CACHE_ENTRY* cacheEntries;
} CACHE;
/*
Read data from a sector in the cache
If the sector is not in the cache, it will be swapped in
offset is the position to start reading from
size is the amount of data to read
Precondition: offset + size <= BYTES_PER_READ
*/
bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size);
bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes);
/*
Write data to a sector in the cache
If the sector is not in the cache, it will be swapped in.
When the sector is swapped out, the data will be written to the disc
offset is the position to start writing to
size is the amount of data to write
Precondition: offset + size <= BYTES_PER_READ
*/
bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size);
bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int num_bytes);
/*
Write data to a sector in the cache, zeroing the sector first
If the sector is not in the cache, it will be swapped in.
When the sector is swapped out, the data will be written to the disc
offset is the position to start writing to
size is the amount of data to write
Precondition: offset + size <= BYTES_PER_READ
*/
bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size);
/*
Read several sectors from the cache
*/
bool _FAT_cache_readSectors (CACHE* cache, sec_t sector, sec_t numSectors, void* buffer);
/*
Read a full sector from the cache
*/
static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, sec_t sector) {
return _FAT_cache_readPartialSector (cache, buffer, sector, 0, cache->bytesPerSector);
}
/*
Write a full sector to the cache
*/
static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, sec_t sector) {
return _FAT_cache_writePartialSector (cache, buffer, sector, 0, cache->bytesPerSector);
}
bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer);
/*
Write any dirty sectors back to disc and clear out the contents of the cache
*/
bool _FAT_cache_flush (CACHE* cache);
/*
Clear out the contents of the cache without writing any dirty sectors first
*/
void _FAT_cache_invalidate (CACHE* cache);
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, unsigned int bytesPerSector);
void _FAT_cache_destructor (CACHE* cache);
#endif // _CACHE_H

View File

@ -0,0 +1,182 @@
// clang-format off
/*
directory.h
Reading, writing and manipulation of the directory structure on
a FAT partition
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DIRECTORY_H
#define _DIRECTORY_H
#include <sys/stat.h>
#include <sys/syslimits.h>
#include "partition.h"
#define DIR_ENTRY_DATA_SIZE 0x20
#define MAX_LFN_LENGTH 256
#define MAX_ALIAS_LENGTH 13
#define LFN_ENTRY_LENGTH 13
#define ALIAS_ENTRY_LENGTH 11
#define MAX_ALIAS_EXT_LENGTH 3
#define MAX_ALIAS_PRI_LENGTH 8
#define MAX_NUMERIC_TAIL 999999
#define FAT16_ROOT_DIR_CLUSTER 0
#define DIR_SEPARATOR '/'
// File attributes
#define ATTRIB_ARCH 0x20 // Archive
#define ATTRIB_DIR 0x10 // Directory
#define ATTRIB_LFN 0x0F // Long file name
#define ATTRIB_VOL 0x08 // Volume
#define ATTRIB_SYS 0x04 // System
#define ATTRIB_HID 0x02 // Hidden
#define ATTRIB_RO 0x01 // Read only
#define CASE_LOWER_EXT 0x10 // WinNT lowercase extension
#define CASE_LOWER_BASE 0x08 // WinNT lowercase basename
typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE;
typedef struct {
uint32_t cluster;
sec_t sector;
int32_t offset;
} DIR_ENTRY_POSITION;
typedef struct {
uint8_t entryData[DIR_ENTRY_DATA_SIZE];
DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN
DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry
char filename[NAME_MAX];
} DIR_ENTRY;
// Directory entry offsets
enum DIR_ENTRY_offset {
DIR_ENTRY_name = 0x00,
DIR_ENTRY_extension = 0x08,
DIR_ENTRY_attributes = 0x0B,
DIR_ENTRY_caseInfo = 0x0C,
DIR_ENTRY_cTime_ms = 0x0D,
DIR_ENTRY_cTime = 0x0E,
DIR_ENTRY_cDate = 0x10,
DIR_ENTRY_aDate = 0x12,
DIR_ENTRY_clusterHigh = 0x14,
DIR_ENTRY_mTime = 0x16,
DIR_ENTRY_mDate = 0x18,
DIR_ENTRY_cluster = 0x1A,
DIR_ENTRY_fileSize = 0x1C
};
/*
Returns true if the file specified by entry is a directory
*/
static inline bool _FAT_directory_isDirectory (DIR_ENTRY* entry) {
return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) != 0);
}
static inline bool _FAT_directory_isWritable (DIR_ENTRY* entry) {
return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO) == 0);
}
static inline bool _FAT_directory_isDot (DIR_ENTRY* entry) {
return ((entry->filename[0] == '.') && ((entry->filename[1] == '\0') ||
((entry->filename[1] == '.') && entry->filename[2] == '\0')));
}
/*
Reads the first directory entry from the directory starting at dirCluster
Places result in entry
entry will be destroyed even if no directory entry is found
Returns true on success, false on failure
*/
bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster);
/*
Reads the next directory entry after the one already pointed to by entry
Places result in entry
entry will be destroyed even if no directory entry is found
Returns true on success, false on failure
*/
bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry);
/*
Gets the directory entry corrsponding to the supplied path
entry will be destroyed even if no directory entry is found
pathEnd specifies the end of the path string, for cutting strings short if needed
specify NULL to use the full length of path
pathEnd is only a suggestion, and the path string will be searched up until the next PATH_SEPARATOR
after pathEND.
Returns true on success, false on failure
*/
bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd);
/*
Changes the current directory to the one specified by path
Returns true on success, false on failure
*/
bool _FAT_directory_chdir (PARTITION* partition, const char* path);
/*
Removes the directory entry specified by entry
Assumes that entry is valid
Returns true on success, false on failure
*/
bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry);
/*
Add a directory entry to the directory specified by dirCluster
The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are
updated with the new directory entry position and alias.
Returns true on success, false on failure
*/
bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster);
/*
Get the start cluster of a file from it's entry data
*/
uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData);
/*
Fill in the file name and entry data of DIR_ENTRY* entry.
Assumes that the entry's dataStart and dataEnd are correct
Returns true on success, false on failure
*/
bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry);
/*
Fill in a stat struct based on a file entry
*/
void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st);
/*
Get volume label
*/
bool _FAT_directory_getVolumeLabel (PARTITION* partition, char *label);
#endif // _DIRECTORY_H

View File

@ -0,0 +1,28 @@
// clang-format off
#ifndef _LIBFAT_EXT_H
#define _LIBFAT_EXT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <nds/disc_io.h>
/*
Get Alias Name
*/
extern void fatGetAliasName (const char* drive, const char* name, char *alias);
/*
Get Alias Path
*/
extern void fatGetAliasPath (const char* drive, const char* path, char *alias);
#ifdef __cplusplus
}
#endif
#endif // _LIBFAT_EXT_H

View File

@ -0,0 +1,48 @@
// clang-format off
/*
common.h
Common definitions and included files for the FATlib
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FAT_COMMON_H
#define _FAT_COMMON_H
#include <fat.h>
#include <stddef.h>
#include <stdint.h>
// Platform specific includes
#include <nds/ndstypes.h>
#include <nds/system.h>
#include <nds/disc_io.h>
// Platform specific options
#define DEFAULT_CACHE_PAGES 16
#define DEFAULT_SECTORS_PAGE 8
#define USE_RTC_TIME
#endif // _FAT_COMMON_H

View File

@ -0,0 +1,141 @@
// clang-format off
#include <sys/iosupport.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <malloc.h>
static inline void* _FAT_mem_allocate (size_t size) {
return malloc (size);
}
static inline void* _FAT_mem_align (size_t size) {
return malloc (size);
}
static inline void _FAT_mem_free (void* mem) {
free (mem);
}
#include "directory.h"
#include "partition.h"
#include "tonccpy.h"
//static int timesRan = 0;
static int fatGetAlias (const char* drive, const char* name, const char* nameEnd, char *alias) {
devoptab_t *devops;
PARTITION* partition;
DIR_ENTRY entry;
char *buf;
int drivelen/*,namelen*/,i;
if (!drive || !name)
return -1;
drivelen = strlen(drive);
//namelen = strlen(name);
buf=(char*)_FAT_mem_allocate(sizeof(char)*drivelen+2);
strcpy(buf,drive);
if (drive[drivelen-1] == '/') {
buf[drivelen-1]='\0';
drivelen--;
}
if (drive[drivelen-1] != ':') {
buf[drivelen]=':';
buf[drivelen+1]='\0';
}
/*if (name[namelen-1] == '/') {
name[namelen-1]='\0';
namelen--;
}*/
devops = (devoptab_t*)GetDeviceOpTab(buf);
for (i=0;buf[i]!='\0' && buf[i]!=':';i++);
if (!devops || strncasecmp(buf,devops->name,i)) {
_FAT_mem_free(buf);
return -1;
}
_FAT_mem_free(buf);
partition = (PARTITION*)devops->deviceData;
int resultLen = 0;
if (_FAT_directory_entryFromPath(partition, &entry, name, nameEnd)) {
tonccpy(alias,&entry.entryData,8);
int i = 0;
if (strncmp((char*)entry.entryData+8, " ", 3) != 0) {
for (i = 0; i < 8; i++) {
if (entry.entryData[i] == ' ') {
break;
}
}
alias[i] = '.';
alias[i+1] = entry.entryData[8];
alias[i+2] = entry.entryData[9];
alias[i+3] = entry.entryData[10];
alias[i+4] = '\0';
resultLen = i+4;
} else {
for (i = 0; i <= 8; i++) {
if (entry.entryData[i] == ' ') {
alias[i] = _FAT_directory_isDirectory(&entry) ? '\x2F' : '\0';
break;
}
}
resultLen = i+1;
}
/*tonccpy((char*)0x02800000+(timesRan*0x20), entry.entryData, 0x20);
tonccpy((char*)0x02800100+(timesRan*0x10), alias, 12);
timesRan++;*/
}
return resultLen;
}
void fatGetAliasName (const char* drive, const char* name, char *alias) {
fatGetAlias (drive, name, NULL, alias);
}
void fatGetAliasPath (const char* drive, const char* path, char *alias) {
char dirBak[PATH_MAX];
getcwd(dirBak, PATH_MAX);
chdir(drive);
char name[128];
int len = (int)strlen(drive);
int lfnLen = len;
if (path[0] == '\x2F') {
len = 1;
lfnLen = len;
}
int nameEnd = 0;
tonccpy(alias, drive, len);
for (int i = len; i < 256; i++) {
for (nameEnd = 0; nameEnd < 128; nameEnd++) {
name[nameEnd] = path[i+nameEnd];
if (path[i+nameEnd] == '\0' || path[i+nameEnd] == '\x2F' /*|| path[i+nameEnd] == '\x5C'*/) {
name[nameEnd] = '\0';
break;
}
}
//tonccpy((char*)0x02800040+(timesRan*0x10), name, nameEnd);
len += fatGetAlias (drive, path+lfnLen, path+lfnLen+nameEnd, alias+len);
lfnLen += nameEnd+1;
i += nameEnd;
//timesRan++;
if (path[i] == '\0') break;
chdir(name);
}
chdir(dirBak);
}

View File

@ -0,0 +1,74 @@
// clang-format off
/*
lock.h
Copyright (c) 2008 Sven Peter <svpe@gmx.net>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOCK_H
#define _LOCK_H
#include "fatcommon.h"
#ifdef USE_LWP_LOCK
static inline void _FAT_lock_init(mutex_t *mutex)
{
LWP_MutexInit(mutex, false);
}
static inline void _FAT_lock_deinit(mutex_t *mutex)
{
LWP_MutexDestroy(*mutex);
}
static inline void _FAT_lock(mutex_t *mutex)
{
LWP_MutexLock(*mutex);
}
static inline void _FAT_unlock(mutex_t *mutex)
{
LWP_MutexUnlock(*mutex);
}
#else
// We still need a blank lock type
#ifndef mutex_t
typedef int mutex_t;
#endif
void _FAT_lock_init(mutex_t *mutex);
void _FAT_lock_deinit(mutex_t *mutex);
void _FAT_lock(mutex_t *mutex);
void _FAT_unlock(mutex_t *mutex);
#endif // USE_LWP_LOCK
#endif // _LOCK_H

View File

@ -0,0 +1,108 @@
// clang-format off
/*
partition.h
Functions for mounting and dismounting partitions
on various block devices.
Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PARTITION_H
#define _PARTITION_H
#include "cache.h"
#include "lock.h"
#define MIN_SECTOR_SIZE 512
#define MAX_SECTOR_SIZE 4096
// Filesystem type
typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE;
typedef struct {
sec_t fatStart;
uint32_t sectorsPerFat;
uint32_t lastCluster;
uint32_t firstFree;
uint32_t numberFreeCluster;
uint32_t numberLastAllocCluster;
} FAT;
typedef struct {
const DISC_INTERFACE* disc;
CACHE* cache;
// Info about the partition
FS_TYPE filesysType;
uint64_t totalSize;
sec_t rootDirStart;
uint32_t rootDirCluster;
uint32_t numberOfSectors;
sec_t dataStart;
uint32_t bytesPerSector;
uint32_t sectorsPerCluster;
uint32_t bytesPerCluster;
uint32_t fsInfoSector;
FAT fat;
// Values that may change after construction
uint32_t cwdCluster; // Current working directory cluster
int openFileCount;
struct _FILE_STRUCT* firstOpenFile; // The start of a linked list of files
mutex_t lock; // A lock for partition operations
bool readOnly; // If this is set, then do not try writing to the disc
char label[12]; // Volume label
} PARTITION;
/*
Mount the supplied device and return a pointer to the struct necessary to use it
*/
PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t SectorsPerPage, sec_t startSector);
/*
Dismount the device and free all structures used.
Will also attempt to synchronise all open files to disc.
*/
void _FAT_partition_destructor (PARTITION* partition);
/*
Return the partition specified in a path, as taken from the devoptab.
*/
PARTITION* _FAT_partition_getPartitionFromPath (const char* path);
/*
Create the fs info sector.
*/
void _FAT_partition_createFSinfo(PARTITION * partition);
/*
Read the fs info sector data.
*/
void _FAT_partition_readFSinfo(PARTITION * partition);
/*
Write the fs info sector data.
*/
void _FAT_partition_writeFSinfo(PARTITION * partition);
#endif // _PARTITION_H

View File

@ -0,0 +1,134 @@
// clang-format off
#include "tonccpy.h"
#include <stddef.h>
//# tonccpy.c
//! VRAM-safe cpy.
/*! This version mimics memcpy in functionality, with
the benefit of working for VRAM as well. It is also
slightly faster than the original memcpy, but faster
implementations can be made.
\param dst Destination pointer.
\param src Source pointer.
\param size Fill-length in bytes.
\note The pointers and size need not be word-aligned.
*/
void tonccpy(void *dst, const void *src, uint size)
{
if (size == 0 || dst == NULL || src == NULL)
return;
uint count;
u16 *dst16; // hword destination
u8 *src8; // byte source
// Ideal case: copy by 4x words. Leaves tail for later.
if (((u32)src|(u32)dst) %4 == 0 && size >= 4) {
u32 *src32= (u32*)src, *dst32= (u32*)dst;
count = size/4;
uint tmp = count&3;
count /= 4;
// Duff's Device, good friend!
switch(tmp) {
do { *dst32++ = *src32++;
case 3: *dst32++ = *src32++;
case 2: *dst32++ = *src32++;
case 1: *dst32++ = *src32++;
case 0: ; } while (count--);
}
// Check for tail
size &= 3;
if (size == 0)
return;
src8 = (u8*)src32;
dst16 = (u16*)dst32;
} else {
// Unaligned
uint dstOfs = (u32)dst&1;
src8 = (u8*)src;
dst16 = (u16*)(dst-dstOfs);
// Head: 1 byte.
if (dstOfs != 0) {
*dst16 = (*dst16 & 0xFF) | *src8++<<8;
dst16++;
if (--size == 0)
return;
}
}
// Unaligned main: copy by 2x byte.
count = size/2;
while (count--) {
*dst16++ = src8[0] | src8[1]<<8;
src8 += 2;
}
// Tail: 1 byte.
if (size & 1)
*dst16 = (*dst16 &~ 0xFF) | *src8;
}
//# toncset.c
//! VRAM-safe memset, internal routine.
/*! This version mimics memset in functionality, with
the benefit of working for VRAM as well. It is also
slightly faster than the original memset.
\param dst Destination pointer.
\param fill Word to fill with.
\param size Fill-length in bytes.
\note The \a dst pointer and \a size need not be
word-aligned. In the case of unaligned fills, \a fill
will be masked off to match the situation.
*/
void __toncset(void *dst, u32 fill, uint size)
{
if (size == 0 || dst == NULL)
return;
uint left = (u32)dst&3;
u32 *dst32 = (u32*)(dst-left);
u32 count, mask;
// Unaligned head.
if (left != 0) {
// Adjust for very small stint.
if (left + size < 4) {
mask = BIT_MASK(size*8)<<(left*8);
*dst32 = (*dst32 &~ mask) | (fill & mask);
return;
}
mask = BIT_MASK(left*8);
*dst32 = (*dst32 & mask) | (fill&~mask);
dst32++;
size -= 4 - left;
}
// Main stint.
count = size/4;
uint tmp = count&3;
count /= 4;
switch(tmp) {
do { *dst32++ = fill;
case 3: *dst32++ = fill;
case 2: *dst32++ = fill;
case 1: *dst32++ = fill;
case 0: ; } while (count--);
}
// Tail
size &= 3;
if (size) {
mask= BIT_MASK(size*8);
*dst32= (*dst32 &~ mask) | (fill & mask);
}
}

View File

@ -0,0 +1,45 @@
// clang-format off
//# Stuff you may not have yet.
#ifndef TONCCPY_H
#define TONCCPY_H
#ifdef __cplusplus
extern "C" {
#endif
#include <nds/ndstypes.h>
typedef unsigned int uint;
#define BIT_MASK(len) ( (1<<(len))-1 )
static inline u32 quad8(u16 x) { x |= x<<8; return x | x<<16; }
//# Declarations and inlines.
void tonccpy(void *dst, const void *src, uint size);
void __toncset(void *dst, u32 fill, uint size);
static inline void toncset(void *dst, u8 src, uint size);
static inline void toncset16(void *dst, u16 src, uint size);
static inline void toncset32(void *dst, u32 src, uint size);
//! VRAM-safe memset, byte version. Size in bytes.
static inline void toncset(void *dst, u8 src, uint size)
{ __toncset(dst, quad8(src), size); }
//! VRAM-safe memset, halfword version. Size in hwords.
static inline void toncset16(void *dst, u16 src, uint size)
{ __toncset(dst, src|src<<16, size*2); }
//! VRAM-safe memset, word version. Size in words.
static inline void toncset32(void *dst, u32 src, uint size)
{ __toncset(dst, src, size*4); }
#ifdef __cplusplus
}
#endif
#endif

View File

@ -17,7 +17,7 @@ SOURCE_PATH := ../arm9
# all directories are relative to this makefile # all directories are relative to this makefile
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
BUILD := build BUILD := build
SOURCES := $(SOURCE_PATH)/source $(SOURCE_PATH)/source/ui $(SOURCE_PATH)/source/font $(SOURCE_PATH)/source/launcher $(SOURCE_PATH)/source/saves SOURCES := $(SOURCE_PATH)/source $(SOURCE_PATH)/source/ui $(SOURCE_PATH)/source/font $(SOURCE_PATH)/source/launcher $(SOURCE_PATH)/source/launcher/libfat_ext $(SOURCE_PATH)/source/saves
INCLUDES := $(SOURCE_PATH)/include ../share $(SOURCES) INCLUDES := $(SOURCE_PATH)/include ../share $(SOURCES)
DATA := $(SOURCE_PATH)/data ../data DATA := $(SOURCE_PATH)/data ../data
GRAPHICS := GRAPHICS :=