mirror of
https://github.com/coderkei/akmenu-next.git
synced 2025-06-19 01:15:32 -04:00
TopToyLauncher: use 8.3 filename for TTMENU.SYS
Fixes an issue on some SD card
This commit is contained in:
parent
30836cdae3
commit
7ebc6abf53
@ -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);
|
||||||
|
129
arm9/source/launcher/libfat_ext/cache.h
Normal file
129
arm9/source/launcher/libfat_ext/cache.h
Normal 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
|
||||||
|
|
182
arm9/source/launcher/libfat_ext/directory.h
Normal file
182
arm9/source/launcher/libfat_ext/directory.h
Normal 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
|
28
arm9/source/launcher/libfat_ext/fat_ext.h
Normal file
28
arm9/source/launcher/libfat_ext/fat_ext.h
Normal 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
|
48
arm9/source/launcher/libfat_ext/fatcommon.h
Normal file
48
arm9/source/launcher/libfat_ext/fatcommon.h
Normal 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
|
141
arm9/source/launcher/libfat_ext/libfat_ext.c
Normal file
141
arm9/source/launcher/libfat_ext/libfat_ext.c
Normal 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);
|
||||||
|
}
|
74
arm9/source/launcher/libfat_ext/lock.h
Normal file
74
arm9/source/launcher/libfat_ext/lock.h
Normal 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
|
||||||
|
|
108
arm9/source/launcher/libfat_ext/partition.h
Normal file
108
arm9/source/launcher/libfat_ext/partition.h
Normal 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
|
134
arm9/source/launcher/libfat_ext/tonccpy.c
Normal file
134
arm9/source/launcher/libfat_ext/tonccpy.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
45
arm9/source/launcher/libfat_ext/tonccpy.h
Normal file
45
arm9/source/launcher/libfat_ext/tonccpy.h
Normal 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
|
@ -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 :=
|
||||||
|
Loading…
Reference in New Issue
Block a user