├── .gitignore ├── LICENSE ├── README.md ├── ff ├── diskio.c ├── diskio.h ├── ff.c ├── ff.h ├── ffconf.h ├── ffsystem.c ├── ffunicode.c ├── memcmp.c └── memset.c ├── include └── cart.h ├── libultra └── include │ ├── abi.h │ ├── gbi.h │ └── ultra64.h ├── makefile ├── src ├── cart.c ├── cart │ ├── cartcardinit.c │ ├── cartcardrdcart.c │ ├── cartcardrddram.c │ ├── cartcardwrcart.c │ ├── cartcardwrdram.c │ ├── cartexit.c │ └── cartinit.c ├── cartbuf.c ├── cartbuf.s ├── cartint.h ├── ci │ ├── ci.c │ ├── ci.h │ ├── cicardinit.c │ ├── cicardrdcart.c │ ├── cicardrddram.c │ ├── cicardwrcart.c │ ├── cicardwrdram.c │ ├── ciexit.c │ └── ciinit.c ├── ed │ ├── ed.h │ ├── edcard.c │ ├── edcardinit.c │ ├── edcardrdcart.c │ ├── edcardrddram.c │ ├── edcardwrcart.c │ ├── edcardwrdram.c │ ├── edexit.c │ └── edinit.c ├── edx │ ├── edx.h │ ├── edxcard.c │ ├── edxcardinit.c │ ├── edxcardrdcart.c │ ├── edxcardrddram.c │ ├── edxcardwrcart.c │ ├── edxcardwrdram.c │ ├── edxexit.c │ └── edxinit.c ├── sc │ ├── sc.c │ ├── sc.h │ ├── sccardinit.c │ ├── sccardrdcart.c │ ├── sccardrddram.c │ ├── sccardwrcart.c │ ├── sccardwrdram.c │ ├── scexit.c │ └── scinit.c ├── sd.c ├── sd.h ├── sdcrc16.c └── sdcrc16.s └── tools └── cat /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /lib/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2022 - 2023 devwizard 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libcart - Nintendo 64 flash cartridge library 2 | Copyright (C) 2022 - 2023 devwizard 3 | 4 | ## About 5 | This library provides an interface to several Nintendo 64 flash cartridges. It 6 | automatically detects the hardware in use, and uses the appropriate protocol for 7 | the hardware. 8 | 9 | ## Supported hardware 10 | * 64Drive HW1 and HW2 11 | * EverDrive-64 V1, V2, V2.5, V3, X7 and X5 12 | * ED64Plus / Super 64 13 | * SummerCart64 14 | 15 | [Testing result spreadsheet](https://docs.google.com/spreadsheets/d/19opOv4e_4ABqgOmqRBSREtXLdGy08VzMsymtxWky0NU/edit?usp=sharing) 16 | 17 | ## Features 18 | * Unlocks the cartridge ROM, making it rewritable. 19 | * Uses optimised bus timing for faster DMA (EverDrive-64). 20 | * Memory card access, with I/O between RDRAM and cartridge ROM. 21 | 22 | ## Credits 23 | Special thanks to Reonu and Meeq for their extensive testing on ED64Plus and 24 | EverDrive-64 V2. Without them, this project would not be possible. 25 | -------------------------------------------------------------------------------- /ff/diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk I/O module for FatFs (libcart) (C)ChaN, 2019 */ 3 | /* (C)devwizard, 2022-2023 */ 4 | /*-----------------------------------------------------------------------*/ 5 | 6 | #include "ff.h" /* Obtains integer types */ 7 | #include "diskio.h" /* Declarations of disk functions */ 8 | #ifdef _ULTRA64 9 | #include 10 | #else 11 | #include 12 | #endif 13 | #include 14 | 15 | /* Definitions of physical drive number for each drive */ 16 | #define DEV_CARD 0 /* Cartridge memory card */ 17 | 18 | 19 | static DSTATUS card_status; 20 | 21 | /*-----------------------------------------------------------------------*/ 22 | /* Get Drive Status */ 23 | /*-----------------------------------------------------------------------*/ 24 | 25 | DSTATUS disk_status ( 26 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 27 | ) 28 | { 29 | switch (pdrv) { 30 | case DEV_CARD : 31 | return card_status; 32 | } 33 | return STA_NOINIT; 34 | } 35 | 36 | 37 | 38 | /*-----------------------------------------------------------------------*/ 39 | /* Inidialize a Drive */ 40 | /*-----------------------------------------------------------------------*/ 41 | 42 | DSTATUS disk_initialize ( 43 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 44 | ) 45 | { 46 | switch (pdrv) { 47 | case DEV_CARD : 48 | return card_status = cart_card_init() ? STA_NOINIT : 0; 49 | } 50 | return STA_NOINIT; 51 | } 52 | 53 | 54 | 55 | /*-----------------------------------------------------------------------*/ 56 | /* Read Sector(s) */ 57 | /*-----------------------------------------------------------------------*/ 58 | 59 | DRESULT disk_read ( 60 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 61 | BYTE *buff, /* Data buffer to store read data */ 62 | LBA_t sector, /* Start sector in LBA */ 63 | UINT count /* Number of sectors to read */ 64 | ) 65 | { 66 | u32 addr; 67 | 68 | switch (pdrv) { 69 | case DEV_CARD : 70 | #ifdef _ULTRA64 71 | addr = osVirtualToPhysical(buff); 72 | #else 73 | addr = PhysicalAddr(buff); 74 | #endif 75 | if (addr < 0x800000) return cart_card_rd_dram(buff, sector, count) ? RES_ERROR : RES_OK; 76 | else return cart_card_rd_cart(addr, sector, count) ? RES_ERROR : RES_OK; 77 | } 78 | 79 | return RES_PARERR; 80 | } 81 | 82 | 83 | 84 | /*-----------------------------------------------------------------------*/ 85 | /* Write Sector(s) */ 86 | /*-----------------------------------------------------------------------*/ 87 | 88 | #if FF_FS_READONLY == 0 89 | 90 | DRESULT disk_write ( 91 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 92 | const BYTE *buff, /* Data to be written */ 93 | LBA_t sector, /* Start sector in LBA */ 94 | UINT count /* Number of sectors to write */ 95 | ) 96 | { 97 | u32 addr; 98 | 99 | switch (pdrv) { 100 | case DEV_CARD : 101 | #ifdef _ULTRA64 102 | addr = osVirtualToPhysical((void *)buff); 103 | #else 104 | addr = PhysicalAddr(buff); 105 | #endif 106 | if (addr < 0x800000) return cart_card_wr_dram(buff, sector, count) ? RES_ERROR : RES_OK; 107 | else return cart_card_wr_cart(addr, sector, count) ? RES_ERROR : RES_OK; 108 | } 109 | 110 | return RES_PARERR; 111 | } 112 | 113 | #endif 114 | 115 | 116 | /*-----------------------------------------------------------------------*/ 117 | /* Miscellaneous Functions */ 118 | /*-----------------------------------------------------------------------*/ 119 | 120 | DRESULT disk_ioctl ( 121 | BYTE pdrv, /* Physical drive nmuber (0..) */ 122 | BYTE cmd, /* Control code */ 123 | void *buff /* Buffer to send/receive control data */ 124 | ) 125 | { 126 | (void)buff; 127 | 128 | switch (pdrv) { 129 | case DEV_CARD : 130 | switch (cmd) { 131 | #if !FF_FS_READONLY 132 | case CTRL_SYNC: 133 | return RES_OK; 134 | #endif 135 | 136 | #if !FF_FS_READONLY && FF_USE_MKFS 137 | #if 0 138 | case GET_SECTOR_COUNT: 139 | *(LBA_t *)buff = 0; 140 | break; 141 | #endif 142 | #endif 143 | 144 | #if FF_MAX_SS != FF_MIN_SS 145 | case GET_SECTOR_SIZE: 146 | *(WORD *)buff = 512; 147 | return RES_OK; 148 | #endif 149 | 150 | #if !FF_FS_READONLY && FF_USE_MKFS 151 | case GET_BLOCK_SIZE: 152 | *(DWORD *)buff = 512; 153 | return RES_OK; 154 | #endif 155 | } 156 | } 157 | 158 | return RES_PARERR; 159 | } 160 | 161 | 162 | #if !FF_FS_READONLY && !FF_FS_NORTC 163 | 164 | DWORD get_fattime (void) 165 | { 166 | return 0; 167 | } 168 | 169 | #endif 170 | 171 | -------------------------------------------------------------------------------- /ff/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface modlue include file (C)ChaN, 2019 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /* Status of Disk Functions */ 13 | typedef BYTE DSTATUS; 14 | 15 | /* Results of Disk Functions */ 16 | typedef enum { 17 | RES_OK = 0, /* 0: Successful */ 18 | RES_ERROR, /* 1: R/W Error */ 19 | RES_WRPRT, /* 2: Write Protected */ 20 | RES_NOTRDY, /* 3: Not Ready */ 21 | RES_PARERR /* 4: Invalid Parameter */ 22 | } DRESULT; 23 | 24 | 25 | /*---------------------------------------*/ 26 | /* Prototypes for disk control functions */ 27 | 28 | 29 | DSTATUS disk_initialize (BYTE pdrv); 30 | DSTATUS disk_status (BYTE pdrv); 31 | DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count); 32 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count); 33 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 34 | 35 | 36 | /* Disk Status Bits (DSTATUS) */ 37 | 38 | #define STA_NOINIT 0x01 /* Drive not initialized */ 39 | #define STA_NODISK 0x02 /* No medium in the drive */ 40 | #define STA_PROTECT 0x04 /* Write protected */ 41 | 42 | 43 | /* Command code for disk_ioctrl fucntion */ 44 | 45 | /* Generic command (Used by FatFs) */ 46 | #define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ 47 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ 48 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ 49 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ 50 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ 51 | 52 | /* Generic command (Not used by FatFs) */ 53 | #define CTRL_POWER 5 /* Get/Set power status */ 54 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 55 | #define CTRL_EJECT 7 /* Eject media */ 56 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 57 | 58 | /* MMC/SDC specific ioctl command */ 59 | #define MMC_GET_TYPE 10 /* Get card type */ 60 | #define MMC_GET_CSD 11 /* Get CSD */ 61 | #define MMC_GET_CID 12 /* Get CID */ 62 | #define MMC_GET_OCR 13 /* Get OCR */ 63 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 64 | #define ISDIO_READ 55 /* Read data form SD iSDIO register */ 65 | #define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ 66 | #define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ 67 | 68 | /* ATA/CF specific ioctl command */ 69 | #define ATA_GET_REV 20 /* Get F/W revision */ 70 | #define ATA_GET_MODEL 21 /* Get model name */ 71 | #define ATA_GET_SN 22 /* Get serial number */ 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /ff/ff.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------/ 2 | / FatFs - Generic FAT Filesystem module R0.15 / 3 | /-----------------------------------------------------------------------------/ 4 | / 5 | / Copyright (C) 2022, ChaN, all right reserved. 6 | / 7 | / FatFs module is an open source software. Redistribution and use of FatFs in 8 | / source and binary forms, with or without modification, are permitted provided 9 | / that the following condition is met: 10 | 11 | / 1. Redistributions of source code must retain the above copyright notice, 12 | / this condition and the following disclaimer. 13 | / 14 | / This software is provided by the copyright holder and contributors "AS IS" 15 | / and any warranties related to this software are DISCLAIMED. 16 | / The copyright owner or contributors be NOT LIABLE for any damages caused 17 | / by use of this software. 18 | / 19 | /----------------------------------------------------------------------------*/ 20 | 21 | 22 | #ifndef FF_DEFINED 23 | #define FF_DEFINED 80286 /* Revision ID */ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | #include "ffconf.h" /* FatFs configuration options */ 30 | 31 | #if FF_DEFINED != FFCONF_DEF 32 | #error Wrong configuration file (ffconf.h). 33 | #endif 34 | 35 | 36 | /* Integer types used for FatFs API */ 37 | 38 | #if defined(_WIN32) /* Windows VC++ (for development only) */ 39 | #define FF_INTDEF 2 40 | #include 41 | typedef unsigned __int64 QWORD; 42 | #include 43 | #define isnan(v) _isnan(v) 44 | #define isinf(v) (!_finite(v)) 45 | 46 | #elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */ 47 | #define FF_INTDEF 2 48 | #include 49 | typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ 50 | typedef unsigned char BYTE; /* char must be 8-bit */ 51 | typedef uint16_t WORD; /* 16-bit unsigned integer */ 52 | typedef uint32_t DWORD; /* 32-bit unsigned integer */ 53 | typedef uint64_t QWORD; /* 64-bit unsigned integer */ 54 | typedef WORD WCHAR; /* UTF-16 character type */ 55 | 56 | #else /* Earlier than C99 */ 57 | #define FF_INTDEF 1 58 | typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ 59 | typedef unsigned char BYTE; /* char must be 8-bit */ 60 | typedef unsigned short WORD; /* 16-bit unsigned integer */ 61 | typedef unsigned long DWORD; /* 32-bit unsigned integer */ 62 | typedef WORD WCHAR; /* UTF-16 character type */ 63 | #endif 64 | 65 | 66 | /* Type of file size and LBA variables */ 67 | 68 | #if FF_FS_EXFAT 69 | #if FF_INTDEF != 2 70 | #error exFAT feature wants C99 or later 71 | #endif 72 | typedef QWORD FSIZE_t; 73 | #if FF_LBA64 74 | typedef QWORD LBA_t; 75 | #else 76 | typedef DWORD LBA_t; 77 | #endif 78 | #else 79 | #if FF_LBA64 80 | #error exFAT needs to be enabled when enable 64-bit LBA 81 | #endif 82 | typedef DWORD FSIZE_t; 83 | typedef DWORD LBA_t; 84 | #endif 85 | 86 | 87 | 88 | /* Type of path name strings on FatFs API (TCHAR) */ 89 | 90 | #if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */ 91 | typedef WCHAR TCHAR; 92 | #define _T(x) L ## x 93 | #define _TEXT(x) L ## x 94 | #elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */ 95 | typedef char TCHAR; 96 | #define _T(x) u8 ## x 97 | #define _TEXT(x) u8 ## x 98 | #elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ 99 | typedef DWORD TCHAR; 100 | #define _T(x) U ## x 101 | #define _TEXT(x) U ## x 102 | #elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) 103 | #error Wrong FF_LFN_UNICODE setting 104 | #else /* ANSI/OEM code in SBCS/DBCS */ 105 | typedef char TCHAR; 106 | #define _T(x) x 107 | #define _TEXT(x) x 108 | #endif 109 | 110 | 111 | 112 | /* Definitions of volume management */ 113 | 114 | #if FF_MULTI_PARTITION /* Multiple partition configuration */ 115 | typedef struct { 116 | BYTE pd; /* Physical drive number */ 117 | BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ 118 | } PARTITION; 119 | extern PARTITION VolToPart[]; /* Volume - Partition mapping table */ 120 | #endif 121 | 122 | #if FF_STR_VOLUME_ID 123 | #ifndef FF_VOLUME_STRS 124 | extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ 125 | #endif 126 | #endif 127 | 128 | 129 | 130 | /* Filesystem object structure (FATFS) */ 131 | 132 | typedef struct { 133 | BYTE fs_type; /* Filesystem type (0:not mounted) */ 134 | BYTE pdrv; /* Volume hosting physical drive */ 135 | BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */ 136 | BYTE n_fats; /* Number of FATs (1 or 2) */ 137 | BYTE wflag; /* win[] status (b0:dirty) */ 138 | BYTE fsi_flag; /* FSINFO status (b7:disabled, b0:dirty) */ 139 | WORD id; /* Volume mount ID */ 140 | WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ 141 | WORD csize; /* Cluster size [sectors] */ 142 | #if FF_MAX_SS != FF_MIN_SS 143 | WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ 144 | #endif 145 | #if FF_USE_LFN 146 | WCHAR* lfnbuf; /* LFN working buffer */ 147 | #endif 148 | #if FF_FS_EXFAT 149 | BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ 150 | #endif 151 | #if !FF_FS_READONLY 152 | DWORD last_clst; /* Last allocated cluster */ 153 | DWORD free_clst; /* Number of free clusters */ 154 | #endif 155 | #if FF_FS_RPATH 156 | DWORD cdir; /* Current directory start cluster (0:root) */ 157 | #if FF_FS_EXFAT 158 | DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ 159 | DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ 160 | DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ 161 | #endif 162 | #endif 163 | DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ 164 | DWORD fsize; /* Number of sectors per FAT */ 165 | LBA_t volbase; /* Volume base sector */ 166 | LBA_t fatbase; /* FAT base sector */ 167 | LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */ 168 | LBA_t database; /* Data base sector */ 169 | #if FF_FS_EXFAT 170 | LBA_t bitbase; /* Allocation bitmap base sector */ 171 | #endif 172 | LBA_t winsect; /* Current sector appearing in the win[] */ 173 | BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ 174 | } FATFS; 175 | 176 | 177 | 178 | /* Object ID and allocation information (FFOBJID) */ 179 | 180 | typedef struct { 181 | FATFS* fs; /* Pointer to the hosting volume of this object */ 182 | WORD id; /* Hosting volume's mount ID */ 183 | BYTE attr; /* Object attribute */ 184 | BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */ 185 | DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ 186 | FSIZE_t objsize; /* Object size (valid when sclust != 0) */ 187 | #if FF_FS_EXFAT 188 | DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ 189 | DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ 190 | DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ 191 | DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ 192 | DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ 193 | #endif 194 | #if FF_FS_LOCK 195 | UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ 196 | #endif 197 | } FFOBJID; 198 | 199 | 200 | 201 | /* File object structure (FIL) */ 202 | 203 | typedef struct { 204 | FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ 205 | BYTE flag; /* File status flags */ 206 | BYTE err; /* Abort flag (error code) */ 207 | FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ 208 | DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ 209 | LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */ 210 | #if !FF_FS_READONLY 211 | LBA_t dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ 212 | BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ 213 | #endif 214 | #if FF_USE_FASTSEEK 215 | DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ 216 | #endif 217 | #if !FF_FS_TINY 218 | BYTE buf[FF_MAX_SS]; /* File private data read/write window */ 219 | #endif 220 | } FIL; 221 | 222 | 223 | 224 | /* Directory object structure (DIR) */ 225 | 226 | typedef struct { 227 | FFOBJID obj; /* Object identifier */ 228 | DWORD dptr; /* Current read/write offset */ 229 | DWORD clust; /* Current cluster */ 230 | LBA_t sect; /* Current sector (0:Read operation has terminated) */ 231 | BYTE* dir; /* Pointer to the directory item in the win[] */ 232 | BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ 233 | #if FF_USE_LFN 234 | DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ 235 | #endif 236 | #if FF_USE_FIND 237 | const TCHAR* pat; /* Pointer to the name matching pattern */ 238 | #endif 239 | } DIR; 240 | 241 | 242 | 243 | /* File information structure (FILINFO) */ 244 | 245 | typedef struct { 246 | FSIZE_t fsize; /* File size */ 247 | WORD fdate; /* Modified date */ 248 | WORD ftime; /* Modified time */ 249 | BYTE fattrib; /* File attribute */ 250 | #if FF_USE_LFN 251 | TCHAR altname[FF_SFN_BUF + 1];/* Alternative file name */ 252 | TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */ 253 | #else 254 | TCHAR fname[12 + 1]; /* File name */ 255 | #endif 256 | } FILINFO; 257 | 258 | 259 | 260 | /* Format parameter structure (MKFS_PARM) */ 261 | 262 | typedef struct { 263 | BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */ 264 | BYTE n_fat; /* Number of FATs */ 265 | UINT align; /* Data area alignment (sector) */ 266 | UINT n_root; /* Number of root directory entries */ 267 | DWORD au_size; /* Cluster size (byte) */ 268 | } MKFS_PARM; 269 | 270 | 271 | 272 | /* File function return code (FRESULT) */ 273 | 274 | typedef enum { 275 | FR_OK = 0, /* (0) Succeeded */ 276 | FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ 277 | FR_INT_ERR, /* (2) Assertion failed */ 278 | FR_NOT_READY, /* (3) The physical drive cannot work */ 279 | FR_NO_FILE, /* (4) Could not find the file */ 280 | FR_NO_PATH, /* (5) Could not find the path */ 281 | FR_INVALID_NAME, /* (6) The path name format is invalid */ 282 | FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ 283 | FR_EXIST, /* (8) Access denied due to prohibited access */ 284 | FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ 285 | FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ 286 | FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ 287 | FR_NOT_ENABLED, /* (12) The volume has no work area */ 288 | FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ 289 | FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ 290 | FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ 291 | FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ 292 | FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ 293 | FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ 294 | FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ 295 | } FRESULT; 296 | 297 | 298 | 299 | 300 | /*--------------------------------------------------------------*/ 301 | /* FatFs Module Application Interface */ 302 | /*--------------------------------------------------------------*/ 303 | 304 | FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ 305 | FRESULT f_close (FIL* fp); /* Close an open file object */ 306 | FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ 307 | FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ 308 | FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ 309 | FRESULT f_truncate (FIL* fp); /* Truncate the file */ 310 | FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ 311 | FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ 312 | FRESULT f_closedir (DIR* dp); /* Close an open directory */ 313 | FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ 314 | FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ 315 | FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ 316 | FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ 317 | FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ 318 | FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ 319 | FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ 320 | FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ 321 | FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ 322 | FRESULT f_chdir (const TCHAR* path); /* Change current directory */ 323 | FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ 324 | FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ 325 | FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ 326 | FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ 327 | FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ 328 | FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ 329 | FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */ 330 | FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ 331 | FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len); /* Create a FAT volume */ 332 | FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work); /* Divide a physical drive into some partitions */ 333 | FRESULT f_setcp (WORD cp); /* Set current code page */ 334 | int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ 335 | int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ 336 | int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ 337 | TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ 338 | 339 | /* Some API fucntions are implemented as macro */ 340 | 341 | #define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) 342 | #define f_error(fp) ((fp)->err) 343 | #define f_tell(fp) ((fp)->fptr) 344 | #define f_size(fp) ((fp)->obj.objsize) 345 | #define f_rewind(fp) f_lseek((fp), 0) 346 | #define f_rewinddir(dp) f_readdir((dp), 0) 347 | #define f_rmdir(path) f_unlink(path) 348 | #define f_unmount(path) f_mount(0, path, 0) 349 | 350 | 351 | 352 | 353 | /*--------------------------------------------------------------*/ 354 | /* Additional Functions */ 355 | /*--------------------------------------------------------------*/ 356 | 357 | /* RTC function (provided by user) */ 358 | #if !FF_FS_READONLY && !FF_FS_NORTC 359 | DWORD get_fattime (void); /* Get current time */ 360 | #endif 361 | 362 | 363 | /* LFN support functions (defined in ffunicode.c) */ 364 | 365 | #if FF_USE_LFN >= 1 366 | WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ 367 | WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */ 368 | DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */ 369 | #endif 370 | 371 | 372 | /* O/S dependent functions (samples available in ffsystem.c) */ 373 | 374 | #if FF_USE_LFN == 3 /* Dynamic memory allocation */ 375 | void* ff_memalloc (UINT msize); /* Allocate memory block */ 376 | void ff_memfree (void* mblock); /* Free memory block */ 377 | #endif 378 | #if FF_FS_REENTRANT /* Sync functions */ 379 | int ff_mutex_create (int vol); /* Create a sync object */ 380 | void ff_mutex_delete (int vol); /* Delete a sync object */ 381 | int ff_mutex_take (int vol); /* Lock sync object */ 382 | void ff_mutex_give (int vol); /* Unlock sync object */ 383 | #endif 384 | 385 | 386 | 387 | 388 | /*--------------------------------------------------------------*/ 389 | /* Flags and Offset Address */ 390 | /*--------------------------------------------------------------*/ 391 | 392 | /* File access mode and open method flags (3rd argument of f_open) */ 393 | #define FA_READ 0x01 394 | #define FA_WRITE 0x02 395 | #define FA_OPEN_EXISTING 0x00 396 | #define FA_CREATE_NEW 0x04 397 | #define FA_CREATE_ALWAYS 0x08 398 | #define FA_OPEN_ALWAYS 0x10 399 | #define FA_OPEN_APPEND 0x30 400 | 401 | /* Fast seek controls (2nd argument of f_lseek) */ 402 | #define CREATE_LINKMAP ((FSIZE_t)0 - 1) 403 | 404 | /* Format options (2nd argument of f_mkfs) */ 405 | #define FM_FAT 0x01 406 | #define FM_FAT32 0x02 407 | #define FM_EXFAT 0x04 408 | #define FM_ANY 0x07 409 | #define FM_SFD 0x08 410 | 411 | /* Filesystem type (FATFS.fs_type) */ 412 | #define FS_FAT12 1 413 | #define FS_FAT16 2 414 | #define FS_FAT32 3 415 | #define FS_EXFAT 4 416 | 417 | /* File attribute bits for directory entry (FILINFO.fattrib) */ 418 | #define AM_RDO 0x01 /* Read only */ 419 | #define AM_HID 0x02 /* Hidden */ 420 | #define AM_SYS 0x04 /* System */ 421 | #define AM_DIR 0x10 /* Directory */ 422 | #define AM_ARC 0x20 /* Archive */ 423 | 424 | 425 | #ifdef __cplusplus 426 | } 427 | #endif 428 | 429 | #endif /* FF_DEFINED */ 430 | -------------------------------------------------------------------------------- /ff/ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / Configurations of FatFs Module 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #define FFCONF_DEF 80286 /* Revision ID */ 6 | 7 | /*---------------------------------------------------------------------------/ 8 | / Function Configurations 9 | /---------------------------------------------------------------------------*/ 10 | 11 | #define FF_FS_READONLY 0 12 | /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) 13 | / Read-only configuration removes writing API functions, f_write(), f_sync(), 14 | / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 15 | / and optional writing functions as well. */ 16 | 17 | 18 | #define FF_FS_MINIMIZE 0 19 | /* This option defines minimization level to remove some basic API functions. 20 | / 21 | / 0: Basic functions are fully enabled. 22 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() 23 | / are removed. 24 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 25 | / 3: f_lseek() function is removed in addition to 2. */ 26 | 27 | 28 | #define FF_USE_FIND 0 29 | /* This option switches filtered directory read functions, f_findfirst() and 30 | / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ 31 | 32 | 33 | #define FF_USE_MKFS 0 34 | /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ 35 | 36 | 37 | #define FF_USE_FASTSEEK 0 38 | /* This option switches fast seek function. (0:Disable or 1:Enable) */ 39 | 40 | 41 | #define FF_USE_EXPAND 0 42 | /* This option switches f_expand function. (0:Disable or 1:Enable) */ 43 | 44 | 45 | #define FF_USE_CHMOD 0 46 | /* This option switches attribute manipulation functions, f_chmod() and f_utime(). 47 | / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ 48 | 49 | 50 | #define FF_USE_LABEL 0 51 | /* This option switches volume label functions, f_getlabel() and f_setlabel(). 52 | / (0:Disable or 1:Enable) */ 53 | 54 | 55 | #define FF_USE_FORWARD 0 56 | /* This option switches f_forward() function. (0:Disable or 1:Enable) */ 57 | 58 | 59 | #define FF_USE_STRFUNC 0 60 | #define FF_PRINT_LLI 1 61 | #define FF_PRINT_FLOAT 1 62 | #define FF_STRF_ENCODE 3 63 | /* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and 64 | / f_printf(). 65 | / 66 | / 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect. 67 | / 1: Enable without LF-CRLF conversion. 68 | / 2: Enable with LF-CRLF conversion. 69 | / 70 | / FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2 71 | / makes f_printf() support floating point argument. These features want C99 or later. 72 | / When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character 73 | / encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE 74 | / to be read/written via those functions. 75 | / 76 | / 0: ANSI/OEM in current CP 77 | / 1: Unicode in UTF-16LE 78 | / 2: Unicode in UTF-16BE 79 | / 3: Unicode in UTF-8 80 | */ 81 | 82 | 83 | /*---------------------------------------------------------------------------/ 84 | / Locale and Namespace Configurations 85 | /---------------------------------------------------------------------------*/ 86 | 87 | #define FF_CODE_PAGE 932 88 | /* This option specifies the OEM code page to be used on the target system. 89 | / Incorrect code page setting can cause a file open failure. 90 | / 91 | / 437 - U.S. 92 | / 720 - Arabic 93 | / 737 - Greek 94 | / 771 - KBL 95 | / 775 - Baltic 96 | / 850 - Latin 1 97 | / 852 - Latin 2 98 | / 855 - Cyrillic 99 | / 857 - Turkish 100 | / 860 - Portuguese 101 | / 861 - Icelandic 102 | / 862 - Hebrew 103 | / 863 - Canadian French 104 | / 864 - Arabic 105 | / 865 - Nordic 106 | / 866 - Russian 107 | / 869 - Greek 2 108 | / 932 - Japanese (DBCS) 109 | / 936 - Simplified Chinese (DBCS) 110 | / 949 - Korean (DBCS) 111 | / 950 - Traditional Chinese (DBCS) 112 | / 0 - Include all code pages above and configured by f_setcp() 113 | */ 114 | 115 | 116 | #define FF_USE_LFN 1 117 | #define FF_MAX_LFN 255 118 | /* The FF_USE_LFN switches the support for LFN (long file name). 119 | / 120 | / 0: Disable LFN. FF_MAX_LFN has no effect. 121 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 122 | / 2: Enable LFN with dynamic working buffer on the STACK. 123 | / 3: Enable LFN with dynamic working buffer on the HEAP. 124 | / 125 | / To enable the LFN, ffunicode.c needs to be added to the project. The LFN function 126 | / requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and 127 | / additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. 128 | / The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can 129 | / be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN 130 | / specification. 131 | / When use stack for the working buffer, take care on stack overflow. When use heap 132 | / memory for the working buffer, memory management functions, ff_memalloc() and 133 | / ff_memfree() exemplified in ffsystem.c, need to be added to the project. */ 134 | 135 | 136 | #define FF_LFN_UNICODE 0 137 | /* This option switches the character encoding on the API when LFN is enabled. 138 | / 139 | / 0: ANSI/OEM in current CP (TCHAR = char) 140 | / 1: Unicode in UTF-16 (TCHAR = WCHAR) 141 | / 2: Unicode in UTF-8 (TCHAR = char) 142 | / 3: Unicode in UTF-32 (TCHAR = DWORD) 143 | / 144 | / Also behavior of string I/O functions will be affected by this option. 145 | / When LFN is not enabled, this option has no effect. */ 146 | 147 | 148 | #define FF_LFN_BUF 255 149 | #define FF_SFN_BUF 12 150 | /* This set of options defines size of file name members in the FILINFO structure 151 | / which is used to read out directory items. These values should be suffcient for 152 | / the file names to read. The maximum possible length of the read file name depends 153 | / on character encoding. When LFN is not enabled, these options have no effect. */ 154 | 155 | 156 | #define FF_FS_RPATH 0 157 | /* This option configures support for relative path. 158 | / 159 | / 0: Disable relative path and remove related functions. 160 | / 1: Enable relative path. f_chdir() and f_chdrive() are available. 161 | / 2: f_getcwd() function is available in addition to 1. 162 | */ 163 | 164 | 165 | /*---------------------------------------------------------------------------/ 166 | / Drive/Volume Configurations 167 | /---------------------------------------------------------------------------*/ 168 | 169 | #define FF_VOLUMES 1 170 | /* Number of volumes (logical drives) to be used. (1-10) */ 171 | 172 | 173 | #define FF_STR_VOLUME_ID 0 174 | #define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" 175 | /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. 176 | / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive 177 | / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each 178 | / logical drives. Number of items must not be less than FF_VOLUMES. Valid 179 | / characters for the volume ID strings are A-Z, a-z and 0-9, however, they are 180 | / compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is 181 | / not defined, a user defined volume string table is needed as: 182 | / 183 | / const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... 184 | */ 185 | 186 | 187 | #define FF_MULTI_PARTITION 0 188 | /* This option switches support for multiple volumes on the physical drive. 189 | / By default (0), each logical drive number is bound to the same physical drive 190 | / number and only an FAT volume found on the physical drive will be mounted. 191 | / When this function is enabled (1), each logical drive number can be bound to 192 | / arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() 193 | / function will be available. */ 194 | 195 | 196 | #define FF_MIN_SS 512 197 | #define FF_MAX_SS 512 198 | /* This set of options configures the range of sector size to be supported. (512, 199 | / 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and 200 | / harddisk, but a larger value may be required for on-board flash memory and some 201 | / type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured 202 | / for variable sector size mode and disk_ioctl() function needs to implement 203 | / GET_SECTOR_SIZE command. */ 204 | 205 | 206 | #define FF_LBA64 0 207 | /* This option switches support for 64-bit LBA. (0:Disable or 1:Enable) 208 | / To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */ 209 | 210 | 211 | #define FF_MIN_GPT 0x10000000 212 | /* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and 213 | / f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */ 214 | 215 | 216 | #define FF_USE_TRIM 0 217 | /* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) 218 | / To enable Trim function, also CTRL_TRIM command should be implemented to the 219 | / disk_ioctl() function. */ 220 | 221 | 222 | 223 | /*---------------------------------------------------------------------------/ 224 | / System Configurations 225 | /---------------------------------------------------------------------------*/ 226 | 227 | #define FF_FS_TINY 1 228 | /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) 229 | / At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. 230 | / Instead of private sector buffer eliminated from the file object, common sector 231 | / buffer in the filesystem object (FATFS) is used for the file data transfer. */ 232 | 233 | 234 | #define FF_FS_EXFAT 1 235 | /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) 236 | / To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) 237 | / Note that enabling exFAT discards ANSI C (C89) compatibility. */ 238 | 239 | 240 | #define FF_FS_NORTC 1 241 | #define FF_NORTC_MON 1 242 | #define FF_NORTC_MDAY 1 243 | #define FF_NORTC_YEAR 2022 244 | /* The option FF_FS_NORTC switches timestamp feature. If the system does not have 245 | / an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the 246 | / timestamp feature. Every object modified by FatFs will have a fixed timestamp 247 | / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. 248 | / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be 249 | / added to the project to read current time form real-time clock. FF_NORTC_MON, 250 | / FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. 251 | / These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ 252 | 253 | 254 | #define FF_FS_NOFSINFO 0 255 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this 256 | / option, and f_getfree() function at the first time after volume mount will force 257 | / a full FAT scan. Bit 1 controls the use of last allocated cluster number. 258 | / 259 | / bit0=0: Use free cluster count in the FSINFO if available. 260 | / bit0=1: Do not trust free cluster count in the FSINFO. 261 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 262 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 263 | */ 264 | 265 | 266 | #define FF_FS_LOCK 0 267 | /* The option FF_FS_LOCK switches file lock function to control duplicated file open 268 | / and illegal operation to open objects. This option must be 0 when FF_FS_READONLY 269 | / is 1. 270 | / 271 | / 0: Disable file lock function. To avoid volume corruption, application program 272 | / should avoid illegal open, remove and rename to the open objects. 273 | / >0: Enable file lock function. The value defines how many files/sub-directories 274 | / can be opened simultaneously under file lock control. Note that the file 275 | / lock control is independent of re-entrancy. */ 276 | 277 | 278 | #define FF_FS_REENTRANT 0 279 | #define FF_FS_TIMEOUT -1 280 | /* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs 281 | / module itself. Note that regardless of this option, file access to different 282 | / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() 283 | / and f_fdisk() function, are always not re-entrant. Only file/directory access 284 | / to the same volume is under control of this featuer. 285 | / 286 | / 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect. 287 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 288 | / ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give() 289 | / function, must be added to the project. Samples are available in ffsystem.c. 290 | / 291 | / The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick. 292 | */ 293 | 294 | 295 | 296 | /*--- End of configuration options ---*/ 297 | -------------------------------------------------------------------------------- /ff/ffsystem.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------*/ 2 | /* A Sample Code of User Provided OS Dependent Functions for FatFs */ 3 | /*------------------------------------------------------------------------*/ 4 | 5 | #include "ff.h" 6 | 7 | 8 | #if FF_USE_LFN == 3 /* Use dynamic memory allocation */ 9 | 10 | /*------------------------------------------------------------------------*/ 11 | /* Allocate/Free a Memory Block */ 12 | /*------------------------------------------------------------------------*/ 13 | 14 | #include /* with POSIX API */ 15 | 16 | 17 | void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */ 18 | UINT msize /* Number of bytes to allocate */ 19 | ) 20 | { 21 | return malloc((size_t)msize); /* Allocate a new memory block */ 22 | } 23 | 24 | 25 | void ff_memfree ( 26 | void* mblock /* Pointer to the memory block to free (no effect if null) */ 27 | ) 28 | { 29 | free(mblock); /* Free the memory block */ 30 | } 31 | 32 | #endif 33 | 34 | 35 | 36 | 37 | #if FF_FS_REENTRANT /* Mutal exclusion */ 38 | /*------------------------------------------------------------------------*/ 39 | /* Definitions of Mutex */ 40 | /*------------------------------------------------------------------------*/ 41 | 42 | #define OS_TYPE 0 /* 0:libultra */ 43 | 44 | 45 | #if OS_TYPE == 0 /* libultra */ 46 | #include 47 | static struct { 48 | OSMesgQueue mq; 49 | OSMesg msg[1]; 50 | } Mutex[FF_VOLUMES + 1]; /* Table of mutex access queue */ 51 | 52 | #endif 53 | 54 | 55 | 56 | /*------------------------------------------------------------------------*/ 57 | /* Create a Mutex */ 58 | /*------------------------------------------------------------------------*/ 59 | /* This function is called in f_mount function to create a new mutex 60 | / or semaphore for the volume. When a 0 is returned, the f_mount function 61 | / fails with FR_INT_ERR. 62 | */ 63 | 64 | int ff_mutex_create ( /* Returns 1:Function succeeded or 0:Could not create the mutex */ 65 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 66 | ) 67 | { 68 | #if OS_TYPE == 0 /* libultra */ 69 | osCreateMesgQueue(&Mutex[vol].mq, Mutex[vol].msg, 1); 70 | osSendMesg(&Mutex[vol].mq, (OSMesg)0, OS_MESG_NOBLOCK); 71 | return 1; 72 | 73 | #endif 74 | } 75 | 76 | 77 | /*------------------------------------------------------------------------*/ 78 | /* Delete a Mutex */ 79 | /*------------------------------------------------------------------------*/ 80 | /* This function is called in f_mount function to delete a mutex or 81 | / semaphore of the volume created with ff_mutex_create function. 82 | */ 83 | 84 | void ff_mutex_delete ( /* Returns 1:Function succeeded or 0:Could not delete due to an error */ 85 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 86 | ) 87 | { 88 | #if OS_TYPE == 0 /* libultra */ 89 | (void)vol; 90 | return 1; 91 | 92 | #endif 93 | } 94 | 95 | 96 | /*------------------------------------------------------------------------*/ 97 | /* Request a Grant to Access the Volume */ 98 | /*------------------------------------------------------------------------*/ 99 | /* This function is called on enter file functions to lock the volume. 100 | / When a 0 is returned, the file function fails with FR_TIMEOUT. 101 | */ 102 | 103 | int ff_mutex_take ( /* Returns 1:Succeeded or 0:Timeout */ 104 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 105 | ) 106 | { 107 | #if OS_TYPE == 0 /* libultra */ 108 | #if FF_FS_TIMEOUT < 0 109 | osRecvMesg(&Mutex[vol].mq, NULL, OS_MESG_BLOCK); 110 | #endif 111 | #if FF_FS_TIMEOUT == 0 112 | if (osRecvMesg(&Mutex[vol].mq, NULL, OS_MESG_NOBLOCK) < 0) return 0; 113 | #endif 114 | #if FF_FS_TIMEOUT > 0 115 | OSMesg msg; 116 | OSTimer timer; 117 | osSetTimer(&timer, FF_FS_TIMEOUT, 0, &Mutex[vol].mq, (OSMesg)1); 118 | osRecvMesg(&Mutex[vol].mq, &msg, OS_MESG_BLOCK); 119 | osStopTimer(&timer); 120 | if (msg) return 0; 121 | osRecvMesg(&Mutex[vol].mq, NULL, OS_MESG_NOBLOCK); 122 | #endif 123 | return 1; 124 | 125 | #endif 126 | } 127 | 128 | 129 | 130 | /*------------------------------------------------------------------------*/ 131 | /* Release a Grant to Access the Volume */ 132 | /*------------------------------------------------------------------------*/ 133 | /* This function is called on leave file functions to unlock the volume. 134 | */ 135 | 136 | void ff_mutex_give ( 137 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 138 | ) 139 | { 140 | #if OS_TYPE == 0 /* libultra */ 141 | osSendMesg(&Mutex[vol].mq, (OSMesg)0, OS_MESG_BLOCK); 142 | 143 | #endif 144 | } 145 | 146 | #endif /* FF_FS_REENTRANT */ 147 | 148 | -------------------------------------------------------------------------------- /ff/memcmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int memcmp(const void *s1, const void *s2, size_t n) 4 | { 5 | const unsigned char *c1 = s1; 6 | const unsigned char *c2 = s2; 7 | while (n-- > 0) 8 | { 9 | unsigned char a = *c1++; 10 | unsigned char b = *c2++; 11 | if (a != b) return (a-b) >> 31 << 1 | 1; 12 | } 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /ff/memset.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void *memset(void *s, int c, size_t n) 4 | { 5 | char *dst = s; 6 | while (n-- > 0) *dst++ = c; 7 | return s; 8 | } 9 | -------------------------------------------------------------------------------- /include/cart.h: -------------------------------------------------------------------------------- 1 | #ifndef __CART_H__ 2 | #define __CART_H__ 3 | 4 | #ifdef _ULTRA64 5 | #include 6 | #else 7 | #include 8 | typedef uint32_t u32; 9 | #endif 10 | 11 | /* Cartridge types */ 12 | #define CART_NULL -1 13 | #define CART_CI 0 /* 64Drive */ 14 | #define CART_EDX 1 /* EverDrive-64 X-series */ 15 | #define CART_ED 2 /* EverDrive-64 V1, V2, V2.5, V3 and ED64+ */ 16 | #define CART_SC 3 /* SummerCart64 */ 17 | #define CART_MAX 4 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* Size of cartridge SDRAM */ 24 | extern u32 cart_size; 25 | 26 | /* Cartridge type */ 27 | extern int cart_type; 28 | 29 | /* Detect cartridge and initialize it */ 30 | extern int cart_init(void); 31 | /* Close the cartridge interface */ 32 | extern int cart_exit(void); 33 | 34 | /* Swap high and low bytes per 16-bit word when reading into SDRAM */ 35 | extern char cart_card_byteswap; 36 | 37 | /* Initialize card */ 38 | extern int cart_card_init(void); 39 | /* Read sectors from card to system RDRAM */ 40 | extern int cart_card_rd_dram(void *dram, u32 lba, u32 count); 41 | /* Read sectors from card to cartridge SDRAM */ 42 | extern int cart_card_rd_cart(u32 cart, u32 lba, u32 count); 43 | /* Write sectors from system RDRAM to card */ 44 | extern int cart_card_wr_dram(const void *dram, u32 lba, u32 count); 45 | /* Write sectors from cartridge SDRAM to card */ 46 | extern int cart_card_wr_cart(u32 cart, u32 lba, u32 count); 47 | 48 | /* 64Drive functions */ 49 | extern int ci_init(void); 50 | extern int ci_exit(void); 51 | extern int ci_card_init(void); 52 | extern int ci_card_byteswap(int flag); 53 | extern int ci_card_rd_dram(void *dram, u32 lba, u32 count); 54 | extern int ci_card_rd_cart(u32 cart, u32 lba, u32 count); 55 | extern int ci_card_wr_dram(const void *dram, u32 lba, u32 count); 56 | extern int ci_card_wr_cart(u32 cart, u32 lba, u32 count); 57 | 58 | /* EverDrive-64 X-series functions */ 59 | extern int edx_init(void); 60 | extern int edx_exit(void); 61 | extern int edx_card_init(void); 62 | extern int edx_card_byteswap(int flag); 63 | extern int edx_card_rd_dram(void *dram, u32 lba, u32 count); 64 | extern int edx_card_rd_cart(u32 cart, u32 lba, u32 count); 65 | extern int edx_card_wr_dram(const void *dram, u32 lba, u32 count); 66 | extern int edx_card_wr_cart(u32 cart, u32 lba, u32 count); 67 | 68 | /* EverDrive-64 functions */ 69 | extern int ed_init(void); 70 | extern int ed_exit(void); 71 | extern int ed_card_init(void); 72 | extern int ed_card_byteswap(int flag); 73 | extern int ed_card_rd_dram(void *dram, u32 lba, u32 count); 74 | extern int ed_card_rd_cart(u32 cart, u32 lba, u32 count); 75 | extern int ed_card_wr_dram(const void *dram, u32 lba, u32 count); 76 | extern int ed_card_wr_cart(u32 cart, u32 lba, u32 count); 77 | 78 | /* SummerCart64 functions */ 79 | extern int sc_init(void); 80 | extern int sc_exit(void); 81 | extern int sc_card_init(void); 82 | extern int sc_card_byteswap(int flag); 83 | extern int sc_card_rd_dram(void *dram, u32 lba, u32 count); 84 | extern int sc_card_rd_cart(u32 cart, u32 lba, u32 count); 85 | extern int sc_card_wr_dram(const void *dram, u32 lba, u32 count); 86 | extern int sc_card_wr_cart(u32 cart, u32 lba, u32 count); 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #endif /* __CART_H__ */ 93 | -------------------------------------------------------------------------------- /libultra/include/abi.h: -------------------------------------------------------------------------------- 1 | #ifndef _ABI_H_ 2 | #define _ABI_H_ 3 | 4 | /************************************************************************** 5 | * * 6 | * Copyright (C) 1994, Silicon Graphics, Inc. * 7 | * * 8 | * These coded instructions, statements, and computer programs contain * 9 | * unpublished proprietary information of Silicon Graphics, Inc., and * 10 | * are protected by Federal copyright law. They may not be disclosed * 11 | * to third parties or copied or duplicated in any form, in whole or * 12 | * in part, without the prior written consent of Silicon Graphics, Inc. * 13 | * * 14 | **************************************************************************/ 15 | 16 | /* 17 | * Header file for the Audio Binary Interface. 18 | * This is included in the Media Binary Interface file 19 | * mbi.h. 20 | * 21 | * This file follows the framework used for graphics. 22 | * 23 | */ 24 | 25 | /* Audio commands: */ 26 | #define A_SPNOOP 0 27 | #define A_ADPCM 1 28 | #define A_CLEARBUFF 2 29 | #define A_ENVMIXER 3 30 | #define A_LOADBUFF 4 31 | #define A_RESAMPLE 5 32 | #define A_SAVEBUFF 6 33 | #define A_SEGMENT 7 34 | #define A_SETBUFF 8 35 | #define A_SETVOL 9 36 | #define A_DMEMMOVE 10 37 | #define A_LOADADPCM 11 38 | #define A_MIXER 12 39 | #define A_INTERLEAVE 13 40 | #define A_POLEF 14 41 | #define A_SETLOOP 15 42 | 43 | #define ACMD_SIZE 32 44 | /* 45 | * Audio flags 46 | */ 47 | 48 | #define A_INIT 0x01 49 | #define A_CONTINUE 0x00 50 | #define A_LOOP 0x02 51 | #define A_OUT 0x02 52 | #define A_LEFT 0x02 53 | #define A_RIGHT 0x00 54 | #define A_VOL 0x04 55 | #define A_RATE 0x00 56 | #define A_AUX 0x08 57 | #define A_NOAUX 0x00 58 | #define A_MAIN 0x00 59 | #define A_MIX 0x10 60 | 61 | /* 62 | * BEGIN C-specific section: (typedef's) 63 | */ 64 | #if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) 65 | 66 | /* 67 | * Data Structures. 68 | */ 69 | 70 | typedef struct { 71 | unsigned int cmd:8; 72 | unsigned int flags:8; 73 | unsigned int gain:16; 74 | unsigned int addr; 75 | } Aadpcm; 76 | 77 | typedef struct { 78 | unsigned int cmd:8; 79 | unsigned int flags:8; 80 | unsigned int gain:16; 81 | unsigned int addr; 82 | } Apolef; 83 | 84 | typedef struct { 85 | unsigned int cmd:8; 86 | unsigned int flags:8; 87 | unsigned int pad1:16; 88 | unsigned int addr; 89 | } Aenvelope; 90 | 91 | typedef struct { 92 | unsigned int cmd:8; 93 | unsigned int pad1:8; 94 | unsigned int dmem:16; 95 | unsigned int pad2:16; 96 | unsigned int count:16; 97 | } Aclearbuff; 98 | 99 | typedef struct { 100 | unsigned int cmd:8; 101 | unsigned int pad1:8; 102 | unsigned int pad2:16; 103 | unsigned int inL:16; 104 | unsigned int inR:16; 105 | } Ainterleave; 106 | 107 | typedef struct { 108 | unsigned int cmd:8; 109 | unsigned int pad1:24; 110 | unsigned int addr; 111 | } Aloadbuff; 112 | 113 | typedef struct { 114 | unsigned int cmd:8; 115 | unsigned int flags:8; 116 | unsigned int pad1:16; 117 | unsigned int addr; 118 | } Aenvmixer; 119 | 120 | typedef struct { 121 | unsigned int cmd:8; 122 | unsigned int flags:8; 123 | unsigned int gain:16; 124 | unsigned int dmemi:16; 125 | unsigned int dmemo:16; 126 | } Amixer; 127 | 128 | typedef struct { 129 | unsigned int cmd:8; 130 | unsigned int flags:8; 131 | unsigned int dmem2:16; 132 | unsigned int addr; 133 | } Apan; 134 | 135 | typedef struct { 136 | unsigned int cmd:8; 137 | unsigned int flags:8; 138 | unsigned int pitch:16; 139 | unsigned int addr; 140 | } Aresample; 141 | 142 | typedef struct { 143 | unsigned int cmd:8; 144 | unsigned int flags:8; 145 | unsigned int pad1:16; 146 | unsigned int addr; 147 | } Areverb; 148 | 149 | typedef struct { 150 | unsigned int cmd:8; 151 | unsigned int pad1:24; 152 | unsigned int addr; 153 | } Asavebuff; 154 | 155 | typedef struct { 156 | unsigned int cmd:8; 157 | unsigned int pad1:24; 158 | unsigned int pad2:2; 159 | unsigned int number:4; 160 | unsigned int base:24; 161 | } Asegment; 162 | 163 | typedef struct { 164 | unsigned int cmd:8; 165 | unsigned int flags:8; 166 | unsigned int dmemin:16; 167 | unsigned int dmemout:16; 168 | unsigned int count:16; 169 | } Asetbuff; 170 | 171 | typedef struct { 172 | unsigned int cmd:8; 173 | unsigned int flags:8; 174 | unsigned int vol:16; 175 | unsigned int voltgt:16; 176 | unsigned int volrate:16; 177 | } Asetvol; 178 | 179 | typedef struct { 180 | unsigned int cmd:8; 181 | unsigned int pad1:8; 182 | unsigned int dmemin:16; 183 | unsigned int dmemout:16; 184 | unsigned int count:16; 185 | } Admemmove; 186 | 187 | typedef struct { 188 | unsigned int cmd:8; 189 | unsigned int pad1:8; 190 | unsigned int count:16; 191 | unsigned int addr; 192 | } Aloadadpcm; 193 | 194 | typedef struct { 195 | unsigned int cmd:8; 196 | unsigned int pad1:8; 197 | unsigned int pad2:16; 198 | unsigned int addr; 199 | } Asetloop; 200 | 201 | /* 202 | * Generic Acmd Packet 203 | */ 204 | 205 | typedef struct { 206 | unsigned int w0; 207 | unsigned int w1; 208 | } Awords; 209 | 210 | typedef union { 211 | Awords words; 212 | Aadpcm adpcm; 213 | Apolef polef; 214 | Aclearbuff clearbuff; 215 | Aenvelope envelope; 216 | Ainterleave interleave; 217 | Aloadbuff loadbuff; 218 | Aenvmixer envmixer; 219 | Aresample resample; 220 | Areverb reverb; 221 | Asavebuff savebuff; 222 | Asegment segment; 223 | Asetbuff setbuff; 224 | Asetvol setvol; 225 | Admemmove dmemmove; 226 | Aloadadpcm loadadpcm; 227 | Amixer mixer; 228 | Asetloop setloop; 229 | long long int force_union_align; /* dummy, force alignment */ 230 | } Acmd; 231 | 232 | /* 233 | * ADPCM State 234 | */ 235 | #define ADPCMVSIZE 8 236 | #define ADPCMFSIZE 16 237 | typedef short ADPCM_STATE[ADPCMFSIZE]; 238 | 239 | /* 240 | * Pole filter state 241 | */ 242 | typedef short POLEF_STATE[4]; 243 | 244 | /* 245 | * Resampler state 246 | */ 247 | typedef short RESAMPLE_STATE[16]; 248 | 249 | /* 250 | * Resampler constants 251 | */ 252 | #define UNITY_PITCH 0x8000 253 | #define MAX_RATIO 1.99996 /* within .03 cents of +1 octave */ 254 | 255 | /* 256 | * Enveloper/Mixer state 257 | */ 258 | typedef short ENVMIX_STATE[40]; 259 | 260 | /* 261 | * Macros to assemble the audio command list 262 | */ 263 | 264 | #define aADPCMdec(pkt, f, s) \ 265 | { \ 266 | Acmd *_a = (Acmd *)pkt; \ 267 | \ 268 | _a->words.w0 = _SHIFTL(A_ADPCM, 24, 8) | _SHIFTL(f, 16, 8); \ 269 | _a->words.w1 = (unsigned int)(s); \ 270 | } 271 | 272 | #define aPoleFilter(pkt, f, g, s) \ 273 | { \ 274 | Acmd *_a = (Acmd *)pkt; \ 275 | \ 276 | _a->words.w0 = (_SHIFTL(A_POLEF, 24, 8) | _SHIFTL(f, 16, 8) | \ 277 | _SHIFTL(g, 0, 16)); \ 278 | _a->words.w1 = (unsigned int)(s); \ 279 | } 280 | 281 | #define aClearBuffer(pkt, d, c) \ 282 | { \ 283 | Acmd *_a = (Acmd *)pkt; \ 284 | \ 285 | _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(d, 0, 24); \ 286 | _a->words.w1 = (unsigned int)(c); \ 287 | } 288 | 289 | #define aEnvMixer(pkt, f, s) \ 290 | { \ 291 | Acmd *_a = (Acmd *)pkt; \ 292 | \ 293 | _a->words.w0 = _SHIFTL(A_ENVMIXER, 24, 8) | _SHIFTL(f, 16, 8); \ 294 | _a->words.w1 = (unsigned int)(s); \ 295 | } 296 | 297 | #define aInterleave(pkt, l, r) \ 298 | { \ 299 | Acmd *_a = (Acmd *)pkt; \ 300 | \ 301 | _a->words.w0 = _SHIFTL(A_INTERLEAVE, 24, 8); \ 302 | _a->words.w1 = _SHIFTL(l, 16, 16) | _SHIFTL(r, 0, 16); \ 303 | } 304 | 305 | #define aLoadBuffer(pkt, s) \ 306 | { \ 307 | Acmd *_a = (Acmd *)pkt; \ 308 | \ 309 | _a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8); \ 310 | _a->words.w1 = (unsigned int)(s); \ 311 | } 312 | 313 | #define aMix(pkt, f, g, i, o) \ 314 | { \ 315 | Acmd *_a = (Acmd *)pkt; \ 316 | \ 317 | _a->words.w0 = (_SHIFTL(A_MIXER, 24, 8) | _SHIFTL(f, 16, 8) | \ 318 | _SHIFTL(g, 0, 16)); \ 319 | _a->words.w1 = _SHIFTL(i,16, 16) | _SHIFTL(o, 0, 16); \ 320 | } 321 | 322 | #define aPan(pkt, f, d, s) \ 323 | { \ 324 | Acmd *_a = (Acmd *)pkt; \ 325 | \ 326 | _a->words.w0 = (_SHIFTL(A_PAN, 24, 8) | _SHIFTL(f, 16, 8) | \ 327 | _SHIFTL(d, 0, 16)); \ 328 | _a->words.w1 = (unsigned int)(s); \ 329 | } 330 | 331 | #define aResample(pkt, f, p, s) \ 332 | { \ 333 | Acmd *_a = (Acmd *)pkt; \ 334 | \ 335 | _a->words.w0 = (_SHIFTL(A_RESAMPLE, 24, 8) | _SHIFTL(f, 16, 8) |\ 336 | _SHIFTL(p, 0, 16)); \ 337 | _a->words.w1 = (unsigned int)(s); \ 338 | } 339 | 340 | #define aSaveBuffer(pkt, s) \ 341 | { \ 342 | Acmd *_a = (Acmd *)pkt; \ 343 | \ 344 | _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8); \ 345 | _a->words.w1 = (unsigned int)(s); \ 346 | } 347 | 348 | #define aSegment(pkt, s, b) \ 349 | { \ 350 | Acmd *_a = (Acmd *)pkt; \ 351 | \ 352 | _a->words.w0 = _SHIFTL(A_SEGMENT, 24, 8); \ 353 | _a->words.w1 = _SHIFTL(s, 24, 8) | _SHIFTL(b, 0, 24); \ 354 | } 355 | 356 | #define aSetBuffer(pkt, f, i, o, c) \ 357 | { \ 358 | Acmd *_a = (Acmd *)pkt; \ 359 | \ 360 | _a->words.w0 = (_SHIFTL(A_SETBUFF, 24, 8) | _SHIFTL(f, 16, 8) | \ 361 | _SHIFTL(i, 0, 16)); \ 362 | _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \ 363 | } 364 | 365 | #define aSetVolume(pkt, f, v, t, r) \ 366 | { \ 367 | Acmd *_a = (Acmd *)pkt; \ 368 | \ 369 | _a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | \ 370 | _SHIFTL(v, 0, 16)); \ 371 | _a->words.w1 = _SHIFTL(t, 16, 16) | _SHIFTL(r, 0, 16); \ 372 | } 373 | 374 | #define aSetLoop(pkt, a) \ 375 | { \ 376 | Acmd *_a = (Acmd *)pkt; \ 377 | _a->words.w0 = _SHIFTL(A_SETLOOP, 24, 8); \ 378 | _a->words.w1 = (unsigned int)(a); \ 379 | } 380 | 381 | #define aDMEMMove(pkt, i, o, c) \ 382 | { \ 383 | Acmd *_a = (Acmd *)pkt; \ 384 | \ 385 | _a->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(i, 0, 24); \ 386 | _a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \ 387 | } 388 | 389 | #define aLoadADPCM(pkt, c, d) \ 390 | { \ 391 | Acmd *_a = (Acmd *)pkt; \ 392 | \ 393 | _a->words.w0 = _SHIFTL(A_LOADADPCM, 24, 8) | _SHIFTL(c, 0, 24); \ 394 | _a->words.w1 = (unsigned int) d; \ 395 | } 396 | 397 | #endif /* _LANGUAGE_C */ 398 | 399 | #endif /* !_ABI_H_ */ 400 | -------------------------------------------------------------------------------- /libultra/include/ultra64.h: -------------------------------------------------------------------------------- 1 | #ifndef _ULTRA64_H_ 2 | #define _ULTRA64_H_ 3 | 4 | /* ultratypes.h */ 5 | #ifndef TRUE 6 | #define TRUE 1 7 | #endif 8 | #ifndef FALSE 9 | #define FALSE 0 10 | #endif 11 | 12 | /* rcp.h */ 13 | #define K0BASE 0x80000000 14 | #define K1BASE 0xA0000000 15 | #define MI_BASE_REG 0x04300000 16 | #define MI_VERSION_REG (MI_BASE_REG+0x04) 17 | #define PI_BASE_REG 0x04600000 18 | #define PI_DRAM_ADDR_REG (PI_BASE_REG+0x00) 19 | #define PI_CART_ADDR_REG (PI_BASE_REG+0x04) 20 | #define PI_RD_LEN_REG (PI_BASE_REG+0x08) 21 | #define PI_WR_LEN_REG (PI_BASE_REG+0x0C) 22 | #define PI_STATUS_REG (PI_BASE_REG+0x10) 23 | #define PI_BSD_DOM1_LAT_REG (PI_BASE_REG+0x14) 24 | #define PI_BSD_DOM1_PWD_REG (PI_BASE_REG+0x18) 25 | #define PI_BSD_DOM1_PGS_REG (PI_BASE_REG+0x1C) 26 | #define PI_BSD_DOM1_RLS_REG (PI_BASE_REG+0x20) 27 | #define PI_BSD_DOM2_LAT_REG (PI_BASE_REG+0x24) 28 | #define PI_BSD_DOM2_PWD_REG (PI_BASE_REG+0x28) 29 | #define PI_BSD_DOM2_PGS_REG (PI_BASE_REG+0x2C) 30 | #define PI_BSD_DOM2_RLS_REG (PI_BASE_REG+0x30) 31 | #define PI_STATUS_ERROR 0x04 32 | #define PI_STATUS_IO_BUSY 0x02 33 | #define PI_STATUS_DMA_BUSY 0x01 34 | #define PI_DOM1_ADDR1 0x06000000 35 | #define PI_DOM1_ADDR2 0x10000000 36 | #define PI_DOM1_ADDR3 0x1FD00000 37 | #define PI_DOM2_ADDR1 0x05000000 38 | #define PI_DOM2_ADDR2 0x08000000 39 | 40 | /* math.h */ 41 | #define M_PI 3.14159265358979323846 42 | 43 | /* os.h */ 44 | #define OS_PIM_STACKSIZE 4096 45 | #define OS_VIM_STACKSIZE 4096 46 | #define OS_SIM_STACKSIZE 4096 47 | #define OS_MIN_STACKSIZE 72 48 | 49 | /* os_thread.h */ 50 | #define OS_STATE_STOPPED 1 51 | #define OS_STATE_RUNNABLE 2 52 | #define OS_STATE_RUNNING 4 53 | #define OS_STATE_WAITING 8 54 | #define OS_PRIORITY_MAX 255 55 | #define OS_PRIORITY_VIMGR 254 56 | #define OS_PRIORITY_RMON 250 57 | #define OS_PRIORITY_RMONSPIN 200 58 | #define OS_PRIORITY_PIMGR 150 59 | #define OS_PRIORITY_SIMGR 140 60 | #define OS_PRIORITY_APPMAX 127 61 | #define OS_PRIORITY_IDLE 0 62 | 63 | /* os_message.h */ 64 | #define OS_NUM_EVENTS 15 65 | #define OS_EVENT_SW1 0 66 | #define OS_EVENT_SW2 1 67 | #define OS_EVENT_CART 2 68 | #define OS_EVENT_COUNTER 3 69 | #define OS_EVENT_SP 4 70 | #define OS_EVENT_SI 5 71 | #define OS_EVENT_AI 6 72 | #define OS_EVENT_VI 7 73 | #define OS_EVENT_PI 8 74 | #define OS_EVENT_DP 9 75 | #define OS_EVENT_CPU_BREAK 10 76 | #define OS_EVENT_SP_BREAK 11 77 | #define OS_EVENT_FAULT 12 78 | #define OS_EVENT_THREADSTATUS 13 79 | #define OS_EVENT_PRENMI 14 80 | #define OS_MESG_NOBLOCK 0 81 | #define OS_MESG_BLOCK 1 82 | 83 | /* os_exception.h */ 84 | #define OS_FLAG_CPU_BREAK 1 85 | #define OS_FLAG_FAULT 2 86 | #define OS_IM_NONE 0x00000001 87 | #define OS_IM_SW1 0x00000501 88 | #define OS_IM_SW2 0x00000601 89 | #define OS_IM_CART 0x00000c01 90 | #define OS_IM_PRENMI 0x00001401 91 | #define OS_IM_RDBWRITE 0x00002401 92 | #define OS_IM_RDBREAD 0x00004401 93 | #define OS_IM_COUNTER 0x00008401 94 | #define OS_IM_CPU 0x0000ff01 95 | #define OS_IM_SP 0x00010401 96 | #define OS_IM_SI 0x00020401 97 | #define OS_IM_AI 0x00040401 98 | #define OS_IM_VI 0x00080401 99 | #define OS_IM_PI 0x00100401 100 | #define OS_IM_DP 0x00200401 101 | #define OS_IM_ALL 0x003fff01 102 | #define RCP_IMASK 0x003f0000 103 | #define RCP_IMASKSHIFT 16 104 | 105 | /* os_tlb.h */ 106 | #define OS_PM_4K 0x0000000 107 | #define OS_PM_16K 0x0006000 108 | #define OS_PM_64K 0x001e000 109 | #define OS_PM_256K 0x007e000 110 | #define OS_PM_1M 0x01fe000 111 | #define OS_PM_4M 0x07fe000 112 | #define OS_PM_16M 0x1ffe000 113 | 114 | /* os_pi.h */ 115 | #define OS_READ 0 116 | #define OS_WRITE 1 117 | #define OS_MESG_TYPE_BASE (10) 118 | #define OS_MESG_TYPE_LOOPBACK (OS_MESG_TYPE_BASE+0) 119 | #define OS_MESG_TYPE_DMAREAD (OS_MESG_TYPE_BASE+1) 120 | #define OS_MESG_TYPE_DMAWRITE (OS_MESG_TYPE_BASE+2) 121 | #define OS_MESG_TYPE_VRETRACE (OS_MESG_TYPE_BASE+3) 122 | #define OS_MESG_TYPE_COUNTER (OS_MESG_TYPE_BASE+4) 123 | #define OS_MESG_TYPE_EDMAREAD (OS_MESG_TYPE_BASE+5) 124 | #define OS_MESG_TYPE_EDMAWRITE (OS_MESG_TYPE_BASE+6) 125 | #define OS_MESG_PRI_NORMAL 0 126 | #define OS_MESG_PRI_HIGH 1 127 | 128 | /* os_vi.h */ 129 | #define OS_VI_NTSC_LPN1 0 130 | #define OS_VI_NTSC_LPF1 1 131 | #define OS_VI_NTSC_LAN1 2 132 | #define OS_VI_NTSC_LAF1 3 133 | #define OS_VI_NTSC_LPN2 4 134 | #define OS_VI_NTSC_LPF2 5 135 | #define OS_VI_NTSC_LAN2 6 136 | #define OS_VI_NTSC_LAF2 7 137 | #define OS_VI_NTSC_HPN1 8 138 | #define OS_VI_NTSC_HPF1 9 139 | #define OS_VI_NTSC_HAN1 10 140 | #define OS_VI_NTSC_HAF1 11 141 | #define OS_VI_NTSC_HPN2 12 142 | #define OS_VI_NTSC_HPF2 13 143 | #define OS_VI_PAL_LPN1 14 144 | #define OS_VI_PAL_LPF1 15 145 | #define OS_VI_PAL_LAN1 16 146 | #define OS_VI_PAL_LAF1 17 147 | #define OS_VI_PAL_LPN2 18 148 | #define OS_VI_PAL_LPF2 19 149 | #define OS_VI_PAL_LAN2 20 150 | #define OS_VI_PAL_LAF2 21 151 | #define OS_VI_PAL_HPN1 22 152 | #define OS_VI_PAL_HPF1 23 153 | #define OS_VI_PAL_HAN1 24 154 | #define OS_VI_PAL_HAF1 25 155 | #define OS_VI_PAL_HPN2 26 156 | #define OS_VI_PAL_HPF2 27 157 | #define OS_VI_GAMMA_ON 0x0001 158 | #define OS_VI_GAMMA_OFF 0x0002 159 | #define OS_VI_GAMMA_DITHER_ON 0x0004 160 | #define OS_VI_GAMMA_DITHER_OFF 0x0008 161 | #define OS_VI_DIVOT_ON 0x0010 162 | #define OS_VI_DIVOT_OFF 0x0020 163 | #define OS_VI_DITHER_FILTER_ON 0x0040 164 | #define OS_VI_DITHER_FILTER_OFF 0x0080 165 | #define OS_VI_BIT_NONINTERLACE 0x0001 166 | #define OS_VI_BIT_INTERLACE 0x0002 167 | #define OS_VI_BIT_NORMALINTERLACE 0x0004 168 | #define OS_VI_BIT_DEFLICKINTERLACE 0x0008 169 | #define OS_VI_BIT_ANTIALIAS 0x0010 170 | #define OS_VI_BIT_POINTSAMPLE 0x0020 171 | #define OS_VI_BIT_16PIXEL 0x0040 172 | #define OS_VI_BIT_32PIXEL 0x0080 173 | #define OS_VI_BIT_LORES 0x0100 174 | #define OS_VI_BIT_HIRES 0x0200 175 | #define OS_VI_BIT_NTSC 0x0400 176 | #define OS_VI_BIT_PAL 0x0800 177 | 178 | /* os_cont.h */ 179 | #define MAXCONTROLLERS 4 180 | #define CONT_NO_RESPONSE_ERROR 0x8 181 | #define CONT_OVERRUN_ERROR 0x4 182 | #define CONT_ABSOLUTE 0x0001 183 | #define CONT_RELATIVE 0x0002 184 | #define CONT_JOYPORT 0x0004 185 | #define CONT_EEPROM 0x8000 186 | #define CONT_EEP16K 0x4000 187 | #define CONT_TYPE_MASK 0x1f07 188 | #define CONT_TYPE_NORMAL 0x0005 189 | #define CONT_TYPE_MOUSE 0x0002 190 | #define CONT_CARD_ON 0x01 191 | #define CONT_CARD_PULL 0x02 192 | #define CONT_ADDR_CRC_ER 0x04 193 | #define CONT_EEPROM_BUSY 0x80 194 | #define CONT_A 0x8000 195 | #define CONT_B 0x4000 196 | #define CONT_G 0x2000 197 | #define CONT_START 0x1000 198 | #define CONT_UP 0x0800 199 | #define CONT_DOWN 0x0400 200 | #define CONT_LEFT 0x0200 201 | #define CONT_RIGHT 0x0100 202 | #define CONT_L 0x0020 203 | #define CONT_R 0x0010 204 | #define CONT_E 0x0008 205 | #define CONT_D 0x0004 206 | #define CONT_C 0x0002 207 | #define CONT_F 0x0001 208 | #define A_BUTTON CONT_A 209 | #define B_BUTTON CONT_B 210 | #define L_TRIG CONT_L 211 | #define R_TRIG CONT_R 212 | #define Z_TRIG CONT_G 213 | #define START_BUTTON CONT_START 214 | #define U_JPAD CONT_UP 215 | #define L_JPAD CONT_LEFT 216 | #define R_JPAD CONT_RIGHT 217 | #define D_JPAD CONT_DOWN 218 | #define U_CBUTTONS CONT_E 219 | #define L_CBUTTONS CONT_C 220 | #define R_CBUTTONS CONT_F 221 | #define D_CBUTTONS CONT_D 222 | #define CONT_ERR_NO_CONTROLLER 1 223 | #define CONT_ERR_CONTRFAIL 4 224 | #define CONT_ERR_INVALID 5 225 | #define CONT_ERR_DEVICE 11 226 | #define CONT_ERR_NOT_READY 12 227 | 228 | /* os_system.h */ 229 | #define OS_TV_PAL 0 230 | #define OS_TV_NTSC 1 231 | #define OS_TV_MPAL 2 232 | #define OS_APP_NMI_BUFSIZE 64 233 | 234 | /* sptask.h */ 235 | #if (defined(F3DEX_GBI)||defined(F3DLP_GBI)||defined(F3DEX_GBI_2)) 236 | #define OS_YIELD_DATA_SIZE 0xc00 237 | #else 238 | #define OS_YIELD_DATA_SIZE 0x900 239 | #endif 240 | #define OS_YIELD_AUDIO_SIZE 0x400 241 | 242 | /* mbi.h */ 243 | #define G_ON (1) 244 | #define G_OFF (0) 245 | #define M_GFXTASK 1 246 | #define M_AUDTASK 2 247 | #define NUM_SEGMENTS (16) 248 | #define SEGMENT_ADDR(num, off) (((num) << 24) + (off)) 249 | 250 | /* ucode.h */ 251 | #define SP_DRAM_STACK_SIZE8 (1024) 252 | #define SP_DRAM_STACK_SIZE64 (SP_DRAM_STACK_SIZE8 >> 3) 253 | #define SP_UCODE_SIZE 4096 254 | #define SP_UCODE_DATA_SIZE 2048 255 | 256 | #ifndef __ASSEMBLER__ 257 | 258 | /* ultratypes.h */ 259 | #ifdef sgi 260 | #ifndef NULL 261 | #define NULL ((void *)0) 262 | #endif 263 | typedef unsigned char u8; 264 | typedef unsigned short u16; 265 | typedef unsigned long u32; 266 | typedef unsigned long long u64; 267 | typedef signed char s8; 268 | typedef short s16; 269 | typedef long s32; 270 | typedef long long s64; 271 | typedef long intptr_t; 272 | typedef unsigned long uintptr_t; 273 | typedef unsigned long size_t; 274 | #else 275 | #include 276 | #include 277 | typedef int8_t s8; 278 | typedef uint8_t u8; 279 | typedef int16_t s16; 280 | typedef uint16_t u16; 281 | typedef int32_t s32; 282 | typedef uint32_t u32; 283 | typedef int64_t s64; 284 | typedef uint64_t u64; 285 | #endif 286 | 287 | typedef float f32; 288 | typedef double f64; 289 | 290 | /* rcp.h */ 291 | #define IO_READ(addr) (*(volatile u32 *)PHYS_TO_K1(addr)) 292 | #define IO_WRITE(addr,data) (*(volatile u32 *)PHYS_TO_K1(addr) = (u32)(data)) 293 | 294 | /* R4300.h */ 295 | #define K0_TO_K1(x) ((u32)(x)|0xA0000000) 296 | #define K1_TO_K0(x) ((u32)(x)&0x9FFFFFFF) 297 | #define K0_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) 298 | #define K1_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) 299 | #define KDM_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) 300 | #define PHYS_TO_K0(x) ((u32)(x)|0x80000000) 301 | #define PHYS_TO_K1(x) ((u32)(x)|0xA0000000) 302 | 303 | /* os_thread.h */ 304 | typedef s32 OSPri; 305 | typedef s32 OSId; 306 | typedef union {struct {f32 f_odd; f32 f_even;} f; f64 d;} __OSfp; 307 | typedef struct 308 | { 309 | u64 at, v0, v1, a0, a1, a2, a3; 310 | u64 t0, t1, t2, t3, t4, t5, t6, t7; 311 | u64 s0, s1, s2, s3, s4, s5, s6, s7; 312 | u64 t8, t9, gp, sp, s8, ra; 313 | u64 lo, hi; 314 | u32 sr, pc, cause, badvaddr, rcp; 315 | u32 fpcsr; 316 | __OSfp fp0, fp2, fp4, fp6, fp8, fp10, fp12, fp14; 317 | __OSfp fp16, fp18, fp20, fp22, fp24, fp26, fp28, fp30; 318 | } 319 | __OSThreadContext; 320 | typedef struct OSThread_s 321 | { 322 | struct OSThread_s *next; 323 | OSPri priority; 324 | struct OSThread_s **queue; 325 | struct OSThread_s *tlnext; 326 | u16 state; 327 | u16 flags; 328 | OSId id; 329 | s32 fp; 330 | __OSThreadContext context; 331 | } 332 | OSThread; 333 | 334 | /* os_message.h */ 335 | #define MQ_GET_COUNT(mq) ((mq)->validCount) 336 | #define MQ_IS_EMPTY(mq) (MQ_GET_COUNT(mq) == 0) 337 | #define MQ_IS_FULL(mq) (MQ_GET_COUNT(mq) >= (mq)->msgCount) 338 | typedef u32 OSEvent; 339 | typedef void *OSMesg; 340 | typedef struct OSMesgQueue_s 341 | { 342 | OSThread *mtqueue; 343 | OSThread *fullqueue; 344 | s32 validCount; 345 | s32 first; 346 | s32 msgCount; 347 | OSMesg *msg; 348 | } 349 | OSMesgQueue; 350 | 351 | /* os_exception.h */ 352 | typedef u32 OSIntMask; 353 | typedef u32 OSHWIntr; 354 | 355 | /* os_tlb.h */ 356 | typedef u32 OSPageMask; 357 | 358 | /* os_pi.h */ 359 | typedef struct 360 | { 361 | u16 type; 362 | u8 pri; 363 | u8 status; 364 | OSMesgQueue *retQueue; 365 | } 366 | OSIoMesgHdr; 367 | typedef struct 368 | { 369 | OSIoMesgHdr hdr; 370 | void *dramAddr; 371 | u32 devAddr; 372 | u32 size; 373 | } 374 | OSIoMesg; 375 | typedef struct 376 | { 377 | s32 active; 378 | OSThread *thread; 379 | OSMesgQueue *cmdQueue; 380 | OSMesgQueue *evtQueue; 381 | OSMesgQueue *acsQueue; 382 | s32 (*dma)(s32, u32, void *, u32); 383 | } 384 | OSDevMgr; 385 | 386 | /* os_vi.h */ 387 | typedef struct 388 | { 389 | u32 ctrl; 390 | u32 width; 391 | u32 burst; 392 | u32 vSync; 393 | u32 hSync; 394 | u32 leap; 395 | u32 hStart; 396 | u32 xScale; 397 | u32 vCurrent; 398 | } 399 | OSViCommonRegs; 400 | typedef struct 401 | { 402 | u32 origin; 403 | u32 yScale; 404 | u32 vStart; 405 | u32 vBurst; 406 | u32 vIntr; 407 | } 408 | OSViFieldRegs; 409 | typedef struct 410 | { 411 | u8 type; 412 | OSViCommonRegs comRegs; 413 | OSViFieldRegs fldRegs[2]; 414 | } 415 | OSViMode; 416 | 417 | /* os_time.h */ 418 | typedef u64 OSTime; 419 | typedef struct OSTimer_s 420 | { 421 | struct OSTimer_s *next; 422 | struct OSTimer_s *prev; 423 | OSTime interval; 424 | OSTime value; 425 | OSMesgQueue *mq; 426 | OSMesg msg; 427 | } 428 | OSTimer; 429 | 430 | /* os_cont.h */ 431 | typedef struct 432 | { 433 | u16 type; 434 | u8 status; 435 | u8 errno; 436 | } 437 | OSContStatus; 438 | typedef struct 439 | { 440 | u16 button; 441 | s8 stick_x; 442 | s8 stick_y; 443 | u8 errno; 444 | } 445 | OSContPad; 446 | 447 | /* os_convert.h */ 448 | #define OS_K0_TO_PHYSICAL(x) (u32)(((char *)(x)-0x80000000)) 449 | #define OS_PHYSICAL_TO_K0(x) (void *)(((u32)(x)+0x80000000)) 450 | 451 | /* sptask.h */ 452 | #define osSpTaskStart(tp) \ 453 | { \ 454 | osSpTaskLoad((tp)); \ 455 | osSpTaskStartGo((tp)); \ 456 | } 457 | typedef struct 458 | { 459 | u32 type; 460 | u32 flags; 461 | u64 *ucode_boot; 462 | u32 ucode_boot_size; 463 | u64 *ucode; 464 | u32 ucode_size; 465 | u64 *ucode_data; 466 | u32 ucode_data_size; 467 | u64 *dram_stack; 468 | u32 dram_stack_size; 469 | u64 *output_buff; 470 | u64 *output_buff_size; 471 | u64 *data_ptr; 472 | u32 data_size; 473 | u64 *yield_data_ptr; 474 | u32 yield_data_size; 475 | } 476 | OSTask_t; 477 | typedef union 478 | { 479 | OSTask_t t; 480 | u64 force_structure_alignment; 481 | } 482 | OSTask; 483 | typedef u32 OSYieldResult; 484 | 485 | /* mbi.h */ 486 | #define _SHIFTL(v, s, w) \ 487 | ((unsigned int) (((unsigned int)(v) & ((0x01 << (w)) - 1)) << (s))) 488 | #define _SHIFTR(v, s, w) \ 489 | ((unsigned int)(((unsigned int)(v) >> (s)) & ((0x01 << (w)) - 1))) 490 | #include 491 | #include 492 | #define SEGMENT_OFFSET(a) ((unsigned int)(a) & 0x00ffffff) 493 | #define SEGMENT_NUMBER(a) (((unsigned int)(a) << 4) >> 28) 494 | 495 | /* 0x80000300 */ extern s32 osTvType; 496 | /* 0x80000304 */ extern s32 osRomType; 497 | /* 0x80000308 */ extern void *osRomBase; 498 | /* 0x8000030C */ extern s32 osResetType; 499 | /* 0x80000310 */ extern s32 osCicId; 500 | /* 0x80000314 */ extern s32 osVersion; 501 | /* 0x80000318 */ extern u32 osMemSize; 502 | /* 0x8000031C */ extern s32 osAppNMIBuffer[]; 503 | 504 | /* 0x803223B0 */ extern void osSetTime(OSTime); 505 | /* 0x803223E0 */ extern void osMapTLB(s32, OSPageMask, void *, u32, u32, s32); 506 | /* 0x803224A0 */ extern void osUnmapTLBAll(void); 507 | /* 0x803224F0 */ extern s32 sprintf(char *, const char *, ...); 508 | /* 0x803225A0 */ extern void osCreateMesgQueue(OSMesgQueue *, OSMesg *, s32); 509 | /* 0x803225D0 */ extern void osSetEventMesg(OSEvent, OSMesgQueue *, OSMesg); 510 | /* 0x80322640 */ extern void osViSetEvent(OSMesgQueue *, OSMesg, u32); 511 | /* 0x803226B0 */ extern void osCreateThread( 512 | OSThread *, OSId, void (*)(void *), void *, void *, OSPri 513 | ); 514 | /* 0x80322800 */ extern s32 osRecvMesg(OSMesgQueue *, OSMesg *, s32); 515 | /* 0x80322A5C */ extern void osSpTaskLoad(OSTask *); 516 | /* 0x80322BBC */ extern s32 osSpTaskStartGo(OSTask *); 517 | /* 0x80322C00 */ extern s32 osSpTaskYield(void); 518 | /* 0x80322C20 */ extern void osSendMesg(OSMesgQueue *, OSMesg, s32); 519 | /* 0x80322D70 */ extern OSYieldResult osSpTaskYielded(OSTask *); 520 | /* 0x80322DF0 */ extern void osStartThread(OSThread *); 521 | /* 0x80322F40 */ extern void osWritebackDCacheAll(void); 522 | /* 0x80322F70 */ extern void osCreateViManager(OSPri); 523 | /* 0x803232D0 */ extern void osViSetMode(OSViMode *); 524 | /* 0x80323340 */ extern void osViBlack(u8); 525 | /* 0x803233B0 */ extern void osViSetSpecialFeatures(u32); 526 | /* 0x80323570 */ extern void osCreatePiManager( 527 | OSPri, OSMesgQueue *, OSMesg *, s32 528 | ); 529 | /* 0x803236F0 */ extern void osSetThreadPri(OSThread *, OSPri); 530 | /* 0x803237D0 */ extern void osInitialize(void); 531 | /* 0x80323A00 */ extern void osViSwapBuffer(void *); 532 | /* 0x80323A50 */ extern f32 sqrtf(f32); 533 | /* 0x80323A60 */ extern s32 osContStartReadData(OSMesgQueue *); 534 | /* 0x80323B24 */ extern void osContGetReadData(OSContPad *); 535 | /* 0x80323CC0 */ extern s32 osContInit(OSMesgQueue *, u8 *, OSContStatus *); 536 | /* 0x80324080 */ extern s32 osEepromProbe(OSMesgQueue *); 537 | /* 0x803243B0 */ extern void osInvalDCache(void *, s32); 538 | /* 0x80324460 */ extern s32 osPiStartDma( 539 | OSIoMesg *, s32, s32, u32, void *, u32, OSMesgQueue * 540 | ); 541 | /* 0x80324570 */ extern void bzero(void *, u32); 542 | /* 0x80324610 */ extern void osInvalICache(void *, s32); 543 | /* 0x80324690 */ extern s32 osEepromLongRead(OSMesgQueue *, u8, u8 *, s32); 544 | /* 0x803247D0 */ extern s32 osEepromLongWrite(OSMesgQueue *, u8, u8 *, s32); 545 | /* 0x80324910 */ extern void bcopy(const void *, void *, size_t); 546 | /* 0x80324C20 */ extern void guOrthoF( 547 | f32[4][4], f32, f32, f32, f32, f32, f32, f32 548 | ); 549 | /* 0x80324D74 */ extern void guOrtho(Mtx *, f32, f32, f32, f32, f32, f32, f32); 550 | /* 0x80324DE0 */ extern void guPerspectiveF( 551 | f32[4][4], u16 *, f32, f32, f32, f32, f32 552 | ); 553 | /* 0x80325010 */ extern void guPerspective( 554 | Mtx *, u16 *, f32, f32, f32, f32, f32 555 | ); 556 | /* 0x80325070 */ extern OSTime osGetTime(void); 557 | /* 0x80325310 */ extern f32 cosf(f32); 558 | /* 0x80325480 */ extern f32 sinf(f32); 559 | /* 0x80325640 */ extern void guTranslateF(f32[4][4], f32, f32, f32); 560 | /* 0x80325688 */ extern void guTranslate(Mtx *, f32, f32, f32); 561 | /* 0x803256E0 */ extern void guRotateF(f32[4][4], f32, f32, f32, f32); 562 | /* 0x80325874 */ extern void guRotate(Mtx *, f32, f32, f32, f32); 563 | /* 0x803258D0 */ extern void guScaleF(f32[4][4], f32, f32, f32); 564 | /* 0x80325924 */ extern void guScale(Mtx *, f32, f32, f32); 565 | /* 0x80325970 */ extern s32 osAiSetFrequency(u32); 566 | /* 0x80325CD8 */ extern void alSeqFileNew(void *, u8 *); 567 | /* 0x80325D20 */ extern void osWritebackDCache(void *, s32); 568 | /* 0x80325DA0 */ extern u32 osAiGetLength(void); 569 | /* 0x80325DB0 */ extern s32 osAiSetNextBuffer(void *, u32); 570 | /* 0x803273F0 */ extern void *memcpy(void *, const void *, size_t); 571 | /* 0x8032741C */ extern size_t strlen(const char *); 572 | /* 0x80327444 */ extern char *strchr(const char *, int); 573 | /* 0x80327EB0 */ extern u32 osVirtualToPhysical(void *); 574 | /* 0x80328050 */ extern OSPri osGetThreadPri(OSThread *); 575 | /* 0x803283E0 */ extern u32 osGetCount(void); 576 | /* 0x80328710 */ extern void __osSetSR(u32); 577 | /* 0x80328720 */ extern u32 __osGetSR(void); 578 | /* 0x80328730 */ extern u32 __osSetFpcCsr(u32); 579 | /* 0x803287E0 */ extern void osMapTLBRdb(void); 580 | /* 0x80328840 */ extern s32 osPiRawReadIo(u32, u32 *); 581 | /* 0x80328A10 */ extern s32 osSetTimer( 582 | OSTimer *, OSTime, OSTime, OSMesgQueue *, OSMesg 583 | ); 584 | /* 0x80328AF0 */ extern s32 osEepromWrite(OSMesgQueue *mq, u8, u8 *); 585 | /* 0x80328FD0 */ extern void osJamMesg(OSMesgQueue *, OSMesg, s32); 586 | /* 0x80329120 */ extern OSMesgQueue *osPiGetCmdQueue(void); 587 | /* 0x80329150 */ extern s32 osEepromRead(OSMesgQueue *, u8, u8 *); 588 | /* 0x80329450 */ extern void guMtxF2L(f32[4][4], Mtx *); 589 | /* 0x80329550 */ extern void guMtxIdentF(f32[4][4]); 590 | /* 0x803295D8 */ extern void guMtxIdent(Mtx *); 591 | /* 0x80329608 */ extern void guMtxL2F(f32[4][4], Mtx *); 592 | /* 0x803296C0 */ extern void guNormalize(f32 *, f32 *, f32 *); 593 | /* 0x80329780 */ extern void __osSetCompare(u32); 594 | /* 0x8032AE10 */ extern OSIntMask osSetIntMask(OSIntMask); 595 | /* 0x8032AE70 */ extern void osDestroyThread(OSThread *); 596 | /* 0x8032B1F0 */ extern u32 __osGetCause(void); 597 | 598 | /* 0x8032B260 */ extern u64 rspbootTextStart[]; 599 | /* 0x8032B330 */ extern u64 rspbootTextEnd[]; 600 | /* 0x8032B330 */ extern u64 gspFast3D_fifoTextStart[]; 601 | /* 0x8032C740 */ extern u64 gspFast3D_fifoTextEnd[]; 602 | /* 0x8032C740 */ extern u64 aspMainTextStart[]; 603 | /* 0x8032D560 */ extern u64 aspMainTextEnd[]; 604 | 605 | /* 0x80335010 */ extern OSViMode osViModeTable[]; 606 | /* 0x80335910 */ extern u64 osClockRate; 607 | /* 0x80335AA0 */ extern OSViMode osViModeNtscLan1; 608 | /* 0x80335AF0 */ extern OSViMode osViModePalLan1; 609 | 610 | /* 0x80339AC0 */ extern u64 gspFast3D_fifoDataStart[]; 611 | /* 0x8033A2C0 */ extern u64 gspFast3D_fifoDataEnd[]; 612 | /* 0x8033A2C0 */ extern u64 aspMainDataStart[]; 613 | /* 0x8033A580 */ extern u64 aspMainDataEnd[]; 614 | 615 | #else /* __ASSEMBLER__ */ 616 | 617 | /* R4300.h */ 618 | #define K0_TO_K1(x) ((x)|0xA0000000) 619 | #define K1_TO_K0(x) ((x)&0x9FFFFFFF) 620 | #define K0_TO_PHYS(x) ((x)&0x1FFFFFFF) 621 | #define K1_TO_PHYS(x) ((x)&0x1FFFFFFF) 622 | #define KDM_TO_PHYS(x) ((x)&0x1FFFFFFF) 623 | #define PHYS_TO_K0(x) ((x)|0x80000000) 624 | #define PHYS_TO_K1(x) ((x)|0xA0000000) 625 | #define C0_INX $0 626 | #define C0_RAND $1 627 | #define C0_ENTRYLO0 $2 628 | #define C0_ENTRYLO1 $3 629 | #define C0_CONTEXT $4 630 | #define C0_PAGEMASK $5 631 | #define C0_WIRED $6 632 | #define C0_BADVADDR $8 633 | #define C0_COUNT $9 634 | #define C0_ENTRYHI $10 635 | #define C0_COMPARE $11 636 | #define C0_SR $12 637 | #define C0_CAUSE $13 638 | #define C0_EPC $14 639 | #define C0_PRID $15 640 | #define C0_CONFIG $16 641 | #define C0_LLADDR $17 642 | #define C0_WATCHLO $18 643 | #define C0_WATCHHI $19 644 | #define C0_ECC $26 645 | #define C0_CACHE_ERR $27 646 | #define C0_TAGLO $28 647 | #define C0_TAGHI $29 648 | #define C0_ERROR_EPC $30 649 | 650 | #endif /* __ASSEMBLER__ */ 651 | 652 | #endif /* _ULTRA64_H_ */ 653 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CART_OBJ := \ 2 | cart/cartinit.o \ 3 | cart/cartexit.o \ 4 | cart/cartcardinit.o \ 5 | cart/cartcardrddram.o \ 6 | cart/cartcardrdcart.o \ 7 | cart/cartcardwrdram.o \ 8 | cart/cartcardwrcart.o 9 | 10 | CI_OBJ := \ 11 | ci/ci.o \ 12 | ci/ciinit.o \ 13 | ci/ciexit.o \ 14 | ci/cicardinit.o \ 15 | ci/cicardrddram.o \ 16 | ci/cicardrdcart.o \ 17 | ci/cicardwrdram.o \ 18 | ci/cicardwrcart.o 19 | 20 | EDX_OBJ := \ 21 | edx/edxinit.o \ 22 | edx/edxexit.o \ 23 | edx/edxcard.o \ 24 | edx/edxcardinit.o \ 25 | edx/edxcardrddram.o \ 26 | edx/edxcardrdcart.o \ 27 | edx/edxcardwrdram.o \ 28 | edx/edxcardwrcart.o 29 | 30 | ED_OBJ := \ 31 | ed/edinit.o \ 32 | ed/edexit.o \ 33 | ed/edcard.o \ 34 | ed/edcardinit.o \ 35 | ed/edcardrddram.o \ 36 | ed/edcardrdcart.o \ 37 | ed/edcardwrdram.o \ 38 | ed/edcardwrcart.o 39 | 40 | SC_OBJ := \ 41 | sc/sc.o \ 42 | sc/scinit.o \ 43 | sc/scexit.o \ 44 | sc/sccardinit.o \ 45 | sc/sccardrddram.o \ 46 | sc/sccardrdcart.o \ 47 | sc/sccardwrdram.o \ 48 | sc/sccardwrcart.o 49 | 50 | OBJ := \ 51 | cart.o \ 52 | cartbuf.o \ 53 | sd.o \ 54 | sdcrc16.o \ 55 | $(CART_OBJ) \ 56 | $(CI_OBJ) \ 57 | $(EDX_OBJ) \ 58 | $(ED_OBJ) \ 59 | $(SC_OBJ) 60 | 61 | INCLUDE := \ 62 | include/cart.h 63 | 64 | SRC := \ 65 | src/cartint.h \ 66 | src/cart.c \ 67 | src/cartbuf.c \ 68 | src/sd.h \ 69 | src/sd.c \ 70 | src/sdcrc16.c \ 71 | src/cart/cartinit.c \ 72 | src/cart/cartexit.c \ 73 | src/cart/cartcardinit.c \ 74 | src/cart/cartcardrddram.c \ 75 | src/cart/cartcardrdcart.c \ 76 | src/cart/cartcardwrdram.c \ 77 | src/cart/cartcardwrcart.c \ 78 | src/ci/ci.h \ 79 | src/ci/ci.c \ 80 | src/ci/ciinit.c \ 81 | src/ci/ciexit.c \ 82 | src/ci/cicardinit.c \ 83 | src/ci/cicardrddram.c \ 84 | src/ci/cicardrdcart.c \ 85 | src/ci/cicardwrdram.c \ 86 | src/ci/cicardwrcart.c \ 87 | src/edx/edx.h \ 88 | src/edx/edxinit.c \ 89 | src/edx/edxexit.c \ 90 | src/edx/edxcard.c \ 91 | src/edx/edxcardinit.c \ 92 | src/edx/edxcardrddram.c \ 93 | src/edx/edxcardrdcart.c \ 94 | src/edx/edxcardwrdram.c \ 95 | src/edx/edxcardwrcart.c \ 96 | src/ed/ed.h \ 97 | src/ed/edinit.c \ 98 | src/ed/edexit.c \ 99 | src/ed/edcard.c \ 100 | src/ed/edcardinit.c \ 101 | src/ed/edcardrddram.c \ 102 | src/ed/edcardrdcart.c \ 103 | src/ed/edcardwrdram.c \ 104 | src/ed/edcardwrcart.c \ 105 | src/sc/sc.h \ 106 | src/sc/sc.c \ 107 | src/sc/scinit.c \ 108 | src/sc/scexit.c \ 109 | src/sc/sccardinit.c \ 110 | src/sc/sccardrddram.c \ 111 | src/sc/sccardrdcart.c \ 112 | src/sc/sccardwrdram.c \ 113 | src/sc/sccardwrcart.c 114 | 115 | U64_PREFIX := mips-linux-gnu- 116 | U64_CC := $(U64_PREFIX)gcc 117 | U64_AR := $(U64_PREFIX)ar 118 | U64_ARCH := -mabi=32 -march=vr4300 -mfix4300 119 | U64_OPT := -Os 120 | U64_WARN := -Wall -Wextra -Wpedantic -Werror=implicit-function-declaration 121 | U64_CPPFLAGS = -Ilibultra/include -Iinclude -Isrc -D_ULTRA64 122 | U64_CFLAGS = $(U64_ARCH) -mno-abicalls -fno-PIC -mno-check-zero-division -fno-builtin -ffast-math -ftrapping-math -fno-associative-math -fsingle-precision-constant -G 0 $(U64_OPT) $(U64_WARN) 123 | U64_ASFLAGS = $(U64_ARCH) -mno-abicalls -fno-PIC -G 0 $(U64_FLAG) $(U64_OPT) 124 | 125 | .PHONY: default 126 | default: lib/libcart.a lib/ultra/cart.h lib/ultra/libcart.c lib/dragon/cart.h lib/dragon/libcart.c 127 | 128 | .PHONY: clean 129 | clean: 130 | rm -f -r build lib 131 | 132 | lib/libcart.a: $(addprefix build/,$(OBJ)) 133 | @mkdir -p $(dir $@) 134 | $(U64_AR) rc $@ $^ 135 | 136 | build/%.o: src/%.s 137 | @mkdir -p $(dir $@) 138 | $(U64_CC) $(U64_ASFLAGS) -c -o $@ $< 139 | 140 | build/%.o: src/%.c 141 | @mkdir -p $(dir $@) 142 | $(U64_CC) $(U64_CPPFLAGS) $(U64_CFLAGS) -c -o $@ $< 143 | 144 | lib/ultra/cart.h: $(INCLUDE) 145 | @mkdir -p $(dir $@) 146 | tools/cat -D_ULTRA64 -h $(INCLUDE) > $@ 147 | 148 | lib/ultra/libcart.c: $(SRC) 149 | @mkdir -p $(dir $@) 150 | tools/cat -D_ULTRA64 -c $(SRC) > $@ 151 | 152 | lib/dragon/cart.h: $(INCLUDE) 153 | @mkdir -p $(dir $@) 154 | tools/cat -h $(INCLUDE) > $@ 155 | 156 | lib/dragon/libcart.c: $(SRC) 157 | @mkdir -p $(dir $@) 158 | tools/cat -c $(SRC) > $@ 159 | -------------------------------------------------------------------------------- /src/cart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | 4 | #ifdef _ULTRA64 5 | extern void __osPiGetAccess(void); 6 | extern void __osPiRelAccess(void); 7 | #endif 8 | 9 | /* Temporary buffer aligned for DMA */ 10 | #ifdef __GNUC__ 11 | __attribute__((aligned(16))) 12 | #endif 13 | u64 __cart_buf[512/8]; 14 | 15 | static u32 __cart_dom1_rel; 16 | static u32 __cart_dom2_rel; 17 | u32 __cart_dom1; 18 | u32 __cart_dom2; 19 | 20 | u32 cart_size; 21 | 22 | void __cart_acs_get(void) 23 | { 24 | #ifdef _ULTRA64 25 | __osPiGetAccess(); 26 | #endif 27 | /* Save PI BSD configuration and reconfigure */ 28 | if (__cart_dom1) 29 | { 30 | __cart_dom1_rel = 31 | IO_READ(PI_BSD_DOM1_LAT_REG) << 0 | 32 | IO_READ(PI_BSD_DOM1_PWD_REG) << 8 | 33 | IO_READ(PI_BSD_DOM1_PGS_REG) << 16 | 34 | IO_READ(PI_BSD_DOM1_RLS_REG) << 20 | 35 | 1 << 31; 36 | IO_WRITE(PI_BSD_DOM1_LAT_REG, __cart_dom1 >> 0); 37 | IO_WRITE(PI_BSD_DOM1_PWD_REG, __cart_dom1 >> 8); 38 | IO_WRITE(PI_BSD_DOM1_PGS_REG, __cart_dom1 >> 16); 39 | IO_WRITE(PI_BSD_DOM1_RLS_REG, __cart_dom1 >> 20); 40 | } 41 | if (__cart_dom2) 42 | { 43 | __cart_dom2_rel = 44 | IO_READ(PI_BSD_DOM2_LAT_REG) << 0 | 45 | IO_READ(PI_BSD_DOM2_PWD_REG) << 8 | 46 | IO_READ(PI_BSD_DOM2_PGS_REG) << 16 | 47 | IO_READ(PI_BSD_DOM2_RLS_REG) << 20 | 48 | 1 << 31; 49 | IO_WRITE(PI_BSD_DOM2_LAT_REG, __cart_dom2 >> 0); 50 | IO_WRITE(PI_BSD_DOM2_PWD_REG, __cart_dom2 >> 8); 51 | IO_WRITE(PI_BSD_DOM2_PGS_REG, __cart_dom2 >> 16); 52 | IO_WRITE(PI_BSD_DOM2_RLS_REG, __cart_dom2 >> 20); 53 | } 54 | } 55 | 56 | void __cart_acs_rel(void) 57 | { 58 | /* Restore PI BSD configuration */ 59 | if (__cart_dom1_rel) 60 | { 61 | IO_WRITE(PI_BSD_DOM1_LAT_REG, __cart_dom1_rel >> 0); 62 | IO_WRITE(PI_BSD_DOM1_PWD_REG, __cart_dom1_rel >> 8); 63 | IO_WRITE(PI_BSD_DOM1_PGS_REG, __cart_dom1_rel >> 16); 64 | IO_WRITE(PI_BSD_DOM1_RLS_REG, __cart_dom1_rel >> 20); 65 | __cart_dom1_rel = 0; 66 | } 67 | if (__cart_dom2_rel) 68 | { 69 | IO_WRITE(PI_BSD_DOM2_LAT_REG, __cart_dom2_rel >> 0); 70 | IO_WRITE(PI_BSD_DOM2_PWD_REG, __cart_dom2_rel >> 8); 71 | IO_WRITE(PI_BSD_DOM2_PGS_REG, __cart_dom2_rel >> 16); 72 | IO_WRITE(PI_BSD_DOM2_RLS_REG, __cart_dom2_rel >> 20); 73 | __cart_dom2_rel = 0; 74 | } 75 | #ifdef _ULTRA64 76 | __osPiRelAccess(); 77 | #endif 78 | } 79 | 80 | #ifdef _ULTRA64 81 | 82 | u32 __cart_rd(u32 addr) 83 | { 84 | while (IO_READ(PI_STATUS_REG) & (PI_STATUS_DMA_BUSY|PI_STATUS_IO_BUSY)); 85 | return IO_READ(addr); 86 | } 87 | 88 | void __cart_wr(u32 addr, u32 data) 89 | { 90 | while (IO_READ(PI_STATUS_REG) & (PI_STATUS_DMA_BUSY|PI_STATUS_IO_BUSY)); 91 | IO_WRITE(addr, data); 92 | } 93 | 94 | typedef struct 95 | { 96 | OSMesgQueue *messageQueue; 97 | OSMesg message; 98 | } 99 | __OSEventState; 100 | extern __OSEventState __osEventStateTab[OS_NUM_EVENTS]; 101 | 102 | void __cart_dma_rd(void *dram, u32 cart, u32 size) 103 | { 104 | osInvalDCache(dram, size); 105 | while (IO_READ(PI_STATUS_REG) & (PI_STATUS_DMA_BUSY|PI_STATUS_IO_BUSY)); 106 | IO_WRITE(PI_DRAM_ADDR_REG, osVirtualToPhysical(dram)); 107 | IO_WRITE(PI_CART_ADDR_REG, cart); 108 | IO_WRITE(PI_WR_LEN_REG, size-1); 109 | osRecvMesg( 110 | __osEventStateTab[OS_EVENT_PI].messageQueue, NULL, OS_MESG_BLOCK 111 | ); 112 | } 113 | 114 | void __cart_dma_wr(const void *dram, u32 cart, u32 size) 115 | { 116 | osWritebackDCache((void *)dram, size); 117 | while (IO_READ(PI_STATUS_REG) & (PI_STATUS_DMA_BUSY|PI_STATUS_IO_BUSY)); 118 | IO_WRITE(PI_DRAM_ADDR_REG, osVirtualToPhysical((void *)dram)); 119 | IO_WRITE(PI_CART_ADDR_REG, cart); 120 | IO_WRITE(PI_RD_LEN_REG, size-1); 121 | osRecvMesg( 122 | __osEventStateTab[OS_EVENT_PI].messageQueue, NULL, OS_MESG_BLOCK 123 | ); 124 | } 125 | 126 | #else /* _ULTRA64 */ 127 | 128 | void __cart_dma_rd(void *dram, u32 cart, u32 size) 129 | { 130 | data_cache_hit_writeback_invalidate(dram, size); 131 | dma_read_raw_async(dram, cart, size); 132 | dma_wait(); 133 | } 134 | 135 | void __cart_dma_wr(const void *dram, u32 cart, u32 size) 136 | { 137 | data_cache_hit_writeback((void *)dram, size); 138 | dma_write_raw_async(dram, cart, size); 139 | dma_wait(); 140 | } 141 | 142 | #endif /* _ULTRA64 */ 143 | -------------------------------------------------------------------------------- /src/cart/cartcardinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | 4 | int cart_card_init(void) 5 | { 6 | static int (*const card_init[CART_MAX])(void) = 7 | { 8 | ci_card_init, 9 | edx_card_init, 10 | ed_card_init, 11 | sc_card_init, 12 | }; 13 | if (cart_type < 0) return -1; 14 | return card_init[cart_type](); 15 | } 16 | -------------------------------------------------------------------------------- /src/cart/cartcardrdcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | 4 | char cart_card_byteswap; 5 | 6 | int cart_card_rd_cart(u32 cart, u32 lba, u32 count) 7 | { 8 | static int (*const card_rd_cart[CART_MAX])( 9 | u32 cart, u32 lba, u32 count 10 | ) = 11 | { 12 | ci_card_rd_cart, 13 | edx_card_rd_cart, 14 | ed_card_rd_cart, 15 | sc_card_rd_cart, 16 | }; 17 | if (cart_type < 0) return -1; 18 | return card_rd_cart[cart_type](cart, lba, count); 19 | } 20 | -------------------------------------------------------------------------------- /src/cart/cartcardrddram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | 4 | int cart_card_rd_dram(void *dram, u32 lba, u32 count) 5 | { 6 | static int (*const card_rd_dram[CART_MAX])( 7 | void *dram, u32 lba, u32 count 8 | ) = 9 | { 10 | ci_card_rd_dram, 11 | edx_card_rd_dram, 12 | ed_card_rd_dram, 13 | sc_card_rd_dram, 14 | }; 15 | if (cart_type < 0) return -1; 16 | return card_rd_dram[cart_type](dram, lba, count); 17 | } 18 | -------------------------------------------------------------------------------- /src/cart/cartcardwrcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | 4 | int cart_card_wr_cart(u32 cart, u32 lba, u32 count) 5 | { 6 | static int (*const card_wr_cart[CART_MAX])( 7 | u32 cart, u32 lba, u32 count 8 | ) = 9 | { 10 | ci_card_wr_cart, 11 | edx_card_wr_cart, 12 | ed_card_wr_cart, 13 | sc_card_wr_cart, 14 | }; 15 | if (cart_type < 0) return -1; 16 | return card_wr_cart[cart_type](cart, lba, count); 17 | } 18 | -------------------------------------------------------------------------------- /src/cart/cartcardwrdram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | 4 | int cart_card_wr_dram(const void *dram, u32 lba, u32 count) 5 | { 6 | static int (*const card_wr_dram[CART_MAX])( 7 | const void *dram, u32 lba, u32 count 8 | ) = 9 | { 10 | ci_card_wr_dram, 11 | edx_card_wr_dram, 12 | ed_card_wr_dram, 13 | sc_card_wr_dram, 14 | }; 15 | if (cart_type < 0) return -1; 16 | return card_wr_dram[cart_type](dram, lba, count); 17 | } 18 | -------------------------------------------------------------------------------- /src/cart/cartexit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | 4 | int cart_exit(void) 5 | { 6 | static int (*const exit[CART_MAX])(void) = 7 | { 8 | ci_exit, 9 | edx_exit, 10 | ed_exit, 11 | sc_exit, 12 | }; 13 | if (cart_type < 0) return -1; 14 | return exit[cart_type](); 15 | } 16 | -------------------------------------------------------------------------------- /src/cart/cartinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | 4 | int cart_type = CART_NULL; 5 | 6 | int cart_init(void) 7 | { 8 | static int (*const init[CART_MAX])(void) = 9 | { 10 | ci_init, 11 | edx_init, 12 | ed_init, 13 | sc_init, 14 | }; 15 | int i, result; 16 | /* bbplayer */ 17 | if ((IO_READ(MI_VERSION_REG) & 0xF0) == 0xB0) return -1; 18 | if (!__cart_dom1) 19 | { 20 | __cart_dom1 = 0x8030FFFF; 21 | __cart_acs_get(); 22 | __cart_dom1 = __cart_rd(0x10000000); 23 | __cart_acs_rel(); 24 | } 25 | if (!__cart_dom2) __cart_dom2 = __cart_dom1; 26 | if (cart_type < 0) 27 | { 28 | for (i = 0; i < CART_MAX; i++) 29 | { 30 | if ((result = init[i]()) >= 0) 31 | { 32 | cart_type = i; 33 | return result; 34 | } 35 | } 36 | return -1; 37 | } 38 | return init[cart_type](); 39 | } 40 | -------------------------------------------------------------------------------- /src/cartbuf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | 4 | void __cart_buf_rd(const void *addr) 5 | { 6 | int i; 7 | const u_uint64_t *ptr = addr; 8 | for (i = 0; i < 512/8; i += 2) 9 | { 10 | uint64_t a = ptr[i+0]; 11 | uint64_t b = ptr[i+1]; 12 | __cart_buf[i+0] = a; 13 | __cart_buf[i+1] = b; 14 | } 15 | } 16 | 17 | void __cart_buf_wr(void *addr) 18 | { 19 | int i; 20 | u_uint64_t *ptr = addr; 21 | for (i = 0; i < 512/8; i += 2) 22 | { 23 | uint64_t a = __cart_buf[i+0]; 24 | uint64_t b = __cart_buf[i+1]; 25 | ptr[i+0] = a; 26 | ptr[i+1] = b; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/cartbuf.s: -------------------------------------------------------------------------------- 1 | #ifndef sgi 2 | .set gp=64 3 | #endif 4 | .set noreorder 5 | 6 | .globl __cart_buf_rd 7 | __cart_buf_rd: 8 | la $5, __cart_buf 9 | addu $6, $5, 512 10 | 1: 11 | uld $8, 0($4) 12 | uld $9, 8($4) 13 | sd $8, 0($5) 14 | sd $9, 8($5) 15 | addu $5, 16 16 | bne $5, $6, 1b 17 | addu $4, 16 18 | j $31 19 | nop 20 | 21 | .globl __cart_buf_wr 22 | __cart_buf_wr: 23 | la $5, __cart_buf 24 | addu $6, $5, 512 25 | 1: 26 | ld $8, 0($5) 27 | ld $9, 8($5) 28 | usd $8, 0($4) 29 | usd $9, 8($4) 30 | addu $5, 16 31 | bne $5, $6, 1b 32 | addu $4, 16 33 | j $31 34 | nop 35 | -------------------------------------------------------------------------------- /src/cartint.h: -------------------------------------------------------------------------------- 1 | #ifndef __CARTINT_H__ 2 | #define __CARTINT_H__ 3 | 4 | #ifdef _ULTRA64 5 | 6 | extern u32 __cart_rd(u32 addr); 7 | extern void __cart_wr(u32 addr, u32 data); 8 | 9 | #else /* _ULTRA64 */ 10 | 11 | #include 12 | #include 13 | #include 14 | typedef uint64_t u64; 15 | 16 | #define MI_BASE_REG 0x04300000 17 | #define MI_VERSION_REG (MI_BASE_REG+0x04) 18 | #define PI_BASE_REG 0x04600000 19 | #define PI_BSD_DOM1_LAT_REG (PI_BASE_REG+0x14) 20 | #define PI_BSD_DOM1_PWD_REG (PI_BASE_REG+0x18) 21 | #define PI_BSD_DOM1_PGS_REG (PI_BASE_REG+0x1C) 22 | #define PI_BSD_DOM1_RLS_REG (PI_BASE_REG+0x20) 23 | #define PI_BSD_DOM2_LAT_REG (PI_BASE_REG+0x24) 24 | #define PI_BSD_DOM2_PWD_REG (PI_BASE_REG+0x28) 25 | #define PI_BSD_DOM2_PGS_REG (PI_BASE_REG+0x2C) 26 | #define PI_BSD_DOM2_RLS_REG (PI_BASE_REG+0x30) 27 | 28 | #define IO_READ(addr) (*(volatile u32 *)PHYS_TO_K1(addr)) 29 | #define IO_WRITE(addr,data) (*(volatile u32 *)PHYS_TO_K1(addr) = (u32)(data)) 30 | 31 | #define PHYS_TO_K1(x) ((u32)(x)|0xA0000000) 32 | 33 | #define __cart_rd(addr) io_read(addr) 34 | #define __cart_wr(addr, data) io_write(addr, data) 35 | 36 | #endif /* _ULTRA64 */ 37 | 38 | #define CART_ABORT() {__cart_acs_rel(); return -1;} 39 | 40 | extern u32 __cart_dom1; 41 | extern u32 __cart_dom2; 42 | extern void __cart_acs_get(void); 43 | extern void __cart_acs_rel(void); 44 | extern void __cart_dma_rd(void *dram, u32 cart, u32 size); 45 | extern void __cart_dma_wr(const void *dram, u32 cart, u32 size); 46 | extern void __cart_buf_rd(const void *addr); 47 | extern void __cart_buf_wr(void *addr); 48 | extern u64 __cart_buf[512/8]; 49 | 50 | #endif /* __CARTINT_H__ */ 51 | -------------------------------------------------------------------------------- /src/ci/ci.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ci.h" 4 | 5 | int __ci_sync(void) 6 | { 7 | int n = 65536; 8 | do 9 | { 10 | if (--n == 0) return -1; 11 | } 12 | while (__cart_rd(CI_STATUS_REG) & CI_STATUS_MASK); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/ci/ci.h: -------------------------------------------------------------------------------- 1 | #ifndef __CI_H__ 2 | #define __CI_H__ 3 | 4 | #define CI_BASE_REG 0x18000000 5 | 6 | #define CI_BUFFER_REG (CI_BASE_REG+0x0000) 7 | #define CI_SDRAM_ADDR_REG (CI_BASE_REG+0x0004) 8 | 9 | #define CI_STATUS_REG (CI_BASE_REG+0x0200) 10 | #define CI_COMMAND_REG (CI_BASE_REG+0x0208) 11 | #define CI_LBA_REG (CI_BASE_REG+0x0210) 12 | #define CI_LENGTH_REG (CI_BASE_REG+0x0218) 13 | #define CI_RESULT_REG (CI_BASE_REG+0x0220) 14 | 15 | #define CI_MAGIC_REG (CI_BASE_REG+0x02EC) 16 | #define CI_VARIANT_REG (CI_BASE_REG+0x02F0) 17 | #define CI_REVISION_REG (CI_BASE_REG+0x02FC) 18 | 19 | #define CI_STATUS_MASK 0xF000 20 | #define CI_IDLE 0x0000 21 | #define CI_BUSY 0x1000 22 | 23 | #define CI_RD_BUFFER 0x01 24 | #define CI_RD_SDRAM 0x03 25 | #define CI_WR_BUFFER 0x10 26 | #define CI_WR_SDRAM 0x13 27 | #define CI_SD_RESET 0x1F 28 | #define CI_BYTESWAP_OFF 0xE0 29 | #define CI_BYTESWAP_ON 0xE1 30 | #define CI_CARTROM_WR_ON 0xF0 31 | #define CI_CARTROM_WR_OFF 0xF1 32 | #define CI_EXT_ADDR_ON 0xF8 33 | #define CI_EXT_ADDR_OFF 0xF9 34 | #define CI_ABORT 0xFF 35 | 36 | #define CI_MAGIC 0x55444556 /* UDEV */ 37 | 38 | #define CI_VARIANT_HW1 0x4100 /* A */ 39 | #define CI_VARIANT_HW2 0x4200 /* B */ 40 | 41 | extern int __ci_sync(void); 42 | 43 | #endif /* __CI_H__ */ 44 | -------------------------------------------------------------------------------- /src/ci/cicardinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ci.h" 4 | 5 | int ci_card_init(void) 6 | { 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /src/ci/cicardrdcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ci.h" 4 | 5 | int ci_card_rd_cart(u32 cart, u32 lba, u32 count) 6 | { 7 | __cart_acs_get(); 8 | __ci_sync(); 9 | if (cart_card_byteswap) 10 | { 11 | __cart_wr(CI_COMMAND_REG, CI_BYTESWAP_ON); 12 | __ci_sync(); 13 | } 14 | __cart_wr(CI_LBA_REG, lba); 15 | __cart_wr(CI_LENGTH_REG, count); 16 | __cart_wr(CI_SDRAM_ADDR_REG, (cart & 0xFFFFFFF) >> 1); 17 | __cart_wr(CI_COMMAND_REG, CI_RD_SDRAM); 18 | if (__ci_sync()) 19 | { 20 | __cart_wr(CI_COMMAND_REG, CI_ABORT); 21 | __ci_sync(); 22 | __cart_wr(CI_COMMAND_REG, CI_SD_RESET); 23 | __ci_sync(); 24 | __cart_wr(CI_COMMAND_REG, CI_BYTESWAP_OFF); 25 | __ci_sync(); 26 | CART_ABORT(); 27 | } 28 | if (cart_card_byteswap) 29 | { 30 | __cart_wr(CI_COMMAND_REG, CI_BYTESWAP_OFF); 31 | __ci_sync(); 32 | } 33 | __cart_acs_rel(); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /src/ci/cicardrddram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ci.h" 4 | 5 | int ci_card_rd_dram(void *dram, u32 lba, u32 count) 6 | { 7 | char *addr = dram; 8 | __cart_acs_get(); 9 | __ci_sync(); 10 | while (count-- > 0) 11 | { 12 | __cart_wr(CI_LBA_REG, lba); 13 | __cart_wr(CI_COMMAND_REG, CI_RD_BUFFER); 14 | if (__ci_sync()) 15 | { 16 | __cart_wr(CI_COMMAND_REG, CI_ABORT); 17 | __ci_sync(); 18 | __cart_wr(CI_COMMAND_REG, CI_SD_RESET); 19 | __ci_sync(); 20 | CART_ABORT(); 21 | } 22 | if ((long)addr & 7) 23 | { 24 | __cart_dma_rd(__cart_buf, CI_BUFFER_REG, 512); 25 | __cart_buf_wr(addr); 26 | } 27 | else 28 | { 29 | __cart_dma_rd(addr, CI_BUFFER_REG, 512); 30 | } 31 | addr += 512; 32 | lba++; 33 | } 34 | __cart_acs_rel(); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /src/ci/cicardwrcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ci.h" 4 | 5 | int ci_card_wr_cart(u32 cart, u32 lba, u32 count) 6 | { 7 | __cart_acs_get(); 8 | __ci_sync(); 9 | __cart_wr(CI_LBA_REG, lba); 10 | __cart_wr(CI_LENGTH_REG, count); 11 | __cart_wr(CI_SDRAM_ADDR_REG, (cart & 0xFFFFFFF) >> 1); 12 | __cart_wr(CI_COMMAND_REG, CI_WR_SDRAM); 13 | if (__ci_sync()) 14 | { 15 | __cart_wr(CI_COMMAND_REG, CI_ABORT); 16 | __ci_sync(); 17 | __cart_wr(CI_COMMAND_REG, CI_SD_RESET); 18 | __ci_sync(); 19 | CART_ABORT(); 20 | } 21 | __cart_acs_rel(); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/ci/cicardwrdram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ci.h" 4 | 5 | int ci_card_wr_dram(const void *dram, u32 lba, u32 count) 6 | { 7 | const char *addr = dram; 8 | __cart_acs_get(); 9 | __ci_sync(); 10 | while (count-- > 0) 11 | { 12 | if ((long)addr & 7) 13 | { 14 | __cart_buf_rd(addr); 15 | __cart_dma_wr(__cart_buf, CI_BUFFER_REG, 512); 16 | } 17 | else 18 | { 19 | __cart_dma_wr(addr, CI_BUFFER_REG, 512); 20 | } 21 | __cart_wr(CI_LBA_REG, lba); 22 | __cart_wr(CI_COMMAND_REG, CI_WR_BUFFER); 23 | if (__ci_sync()) 24 | { 25 | __cart_wr(CI_COMMAND_REG, CI_ABORT); 26 | __ci_sync(); 27 | __cart_wr(CI_COMMAND_REG, CI_SD_RESET); 28 | __ci_sync(); 29 | CART_ABORT(); 30 | } 31 | addr += 512; 32 | lba++; 33 | } 34 | __cart_acs_rel(); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /src/ci/ciexit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ci.h" 4 | 5 | int ci_exit(void) 6 | { 7 | __cart_acs_get(); 8 | __ci_sync(); 9 | __cart_wr(CI_COMMAND_REG, CI_CARTROM_WR_OFF); 10 | __ci_sync(); 11 | __cart_acs_rel(); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/ci/ciinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ci.h" 4 | 5 | int ci_init(void) 6 | { 7 | __cart_acs_get(); 8 | if (__cart_rd(CI_MAGIC_REG) != CI_MAGIC) CART_ABORT(); 9 | __ci_sync(); 10 | __cart_wr(CI_COMMAND_REG, CI_CARTROM_WR_ON); 11 | __ci_sync(); 12 | __cart_wr(CI_COMMAND_REG, CI_BYTESWAP_OFF); 13 | __ci_sync(); 14 | cart_size = 0x4000000; /* 64 MiB */ 15 | __cart_acs_rel(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/ed/ed.h: -------------------------------------------------------------------------------- 1 | #ifndef __ED_H__ 2 | #define __ED_H__ 3 | 4 | #define ED_BASE_REG 0x08040000 5 | 6 | #define ED_CFG_REG (ED_BASE_REG+0x00) 7 | #define ED_STATUS_REG (ED_BASE_REG+0x04) 8 | #define ED_DMA_LEN_REG (ED_BASE_REG+0x08) 9 | #define ED_DMA_ADDR_REG (ED_BASE_REG+0x0C) 10 | #define ED_MSG_REG (ED_BASE_REG+0x10) 11 | #define ED_DMA_CFG_REG (ED_BASE_REG+0x14) 12 | #define ED_SPI_REG (ED_BASE_REG+0x18) 13 | #define ED_SPI_CFG_REG (ED_BASE_REG+0x1C) 14 | #define ED_KEY_REG (ED_BASE_REG+0x20) 15 | #define ED_SAV_CFG_REG (ED_BASE_REG+0x24) 16 | #define ED_SEC_REG (ED_BASE_REG+0x28) 17 | #define ED_VER_REG (ED_BASE_REG+0x2C) 18 | 19 | #define ED_CFG_CNT_REG (ED_BASE_REG+0x40) 20 | #define ED_CFG_DAT_REG (ED_BASE_REG+0x44) 21 | #define ED_MAX_MSG_REG (ED_BASE_REG+0x48) 22 | #define ED_CRC_REG (ED_BASE_REG+0x4C) 23 | 24 | #define ED_DMA_SD_TO_RAM 1 25 | #define ED_DMA_RAM_TO_SD 2 26 | #define ED_DMA_FIFO_TO_RAM 3 27 | #define ED_DMA_RAM_TO_FIFO 4 28 | 29 | #define ED_CFG_SDRAM_OFF (0 << 0) 30 | #define ED_CFG_SDRAM_ON (1 << 0) 31 | #define ED_CFG_BYTESWAP (1 << 1) 32 | 33 | #define ED_STATE_DMA_BUSY (1 << 0) 34 | #define ED_STATE_DMA_TOUT (1 << 1) 35 | #define ED_STATE_TXE (1 << 2) 36 | #define ED_STATE_RXF (1 << 3) 37 | #define ED_STATE_SPI (1 << 4) 38 | 39 | #define ED_SPI_SPD_50 (0 << 0) 40 | #define ED_SPI_SPD_25 (1 << 0) 41 | #define ED_SPI_SPD_LO (2 << 0) 42 | #define ED_SPI_SS (1 << 2) 43 | #define ED_SPI_WR (0 << 3) 44 | #define ED_SPI_RD (1 << 3) 45 | #define ED_SPI_CMD (0 << 4) 46 | #define ED_SPI_DAT (1 << 4) 47 | #define ED_SPI_8BIT (0 << 5) 48 | #define ED_SPI_1BIT (1 << 5) 49 | 50 | #define ED_SAV_EEP_ON (1 << 0) 51 | #define ED_SAV_SRM_ON (1 << 1) 52 | #define ED_SAV_EEP_SIZE (1 << 2) 53 | #define ED_SAV_SRM_SIZE (1 << 3) 54 | 55 | #define ED_KEY 0x1234 56 | 57 | #define ED_SD_CMD_RD (ED_SPI_CMD|ED_SPI_RD) 58 | #define ED_SD_CMD_WR (ED_SPI_CMD|ED_SPI_WR) 59 | #define ED_SD_DAT_RD (ED_SPI_DAT|ED_SPI_RD) 60 | #define ED_SD_DAT_WR (ED_SPI_DAT|ED_SPI_WR) 61 | 62 | #define ED_SD_CMD_8b ED_SPI_8BIT 63 | #define ED_SD_CMD_1b ED_SPI_1BIT 64 | #define ED_SD_DAT_8b ED_SPI_8BIT 65 | #define ED_SD_DAT_1b ED_SPI_1BIT 66 | 67 | #define __ed_sd_mode(reg, val) __cart_wr(ED_SPI_CFG_REG, __sd_cfg|(reg)|(val)) 68 | #define __ed_sd_cmd_rd(val) __ed_spi((val) & 0xFF) 69 | #define __ed_sd_cmd_wr(val) __ed_spi((val) & 0xFF) 70 | #define __ed_sd_dat_rd() __ed_spi(0xFF) 71 | #define __ed_sd_dat_wr(val) __ed_spi((val) & 0xFF) 72 | 73 | extern int __ed_spi(int val); 74 | extern int __ed_sd_cmd(int cmd, u32 arg); 75 | extern int __ed_sd_close(int flag); 76 | 77 | #endif /* __ED_H__ */ 78 | -------------------------------------------------------------------------------- /src/ed/edcard.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "ed.h" 5 | 6 | /* SPI exchange */ 7 | int __ed_spi(int val) 8 | { 9 | __cart_wr(ED_SPI_REG, val); 10 | while (__cart_rd(ED_STATUS_REG) & ED_STATE_SPI); 11 | return __cart_rd(ED_SPI_REG); 12 | } 13 | 14 | int __ed_sd_cmd(int cmd, u32 arg) 15 | { 16 | int i; 17 | int n; 18 | char buf[6]; 19 | buf[0] = cmd; 20 | buf[1] = arg >> 24; 21 | buf[2] = arg >> 16; 22 | buf[3] = arg >> 8; 23 | buf[4] = arg >> 0; 24 | buf[5] = __sd_crc7(buf); 25 | /* Send the command */ 26 | __ed_sd_mode(ED_SD_CMD_WR, ED_SD_CMD_8b); 27 | __ed_sd_cmd_wr(0xFF); 28 | for (i = 0; i < 6; i++) __ed_sd_cmd_wr(buf[i]); 29 | /* Read the first response byte */ 30 | __sd_resp[0] = 0xFF; 31 | __ed_sd_mode(ED_SD_CMD_RD, ED_SD_CMD_1b); 32 | n = 2048; 33 | while (__sd_resp[0] & 0xC0) 34 | { 35 | if (--n == 0) return -1; 36 | __sd_resp[0] = __ed_sd_cmd_rd(__sd_resp[0]); 37 | } 38 | /* Read the rest of the response */ 39 | n = !__sd_type ? 40 | cmd == CMD8 || cmd == CMD58 ? 5 : 1 : 41 | cmd == CMD2 || cmd == CMD9 ? 17 : 6; 42 | __ed_sd_mode(ED_SD_CMD_RD, ED_SD_CMD_8b); 43 | for (i = 1; i < n; i++) __sd_resp[i] = __ed_sd_cmd_rd(0xFF); 44 | /* SPI: return "illegal command" flag */ 45 | return !__sd_type ? (__sd_resp[0] & 4) : 0; 46 | } 47 | 48 | int __ed_sd_close(int flag) 49 | { 50 | int n; 51 | if (!flag) 52 | { 53 | /* SPI: Stop token (write) */ 54 | __ed_sd_mode(ED_SD_DAT_WR, ED_SD_DAT_8b); 55 | __ed_sd_dat_wr(0xFD); 56 | __ed_sd_dat_wr(0xFF); 57 | } 58 | else 59 | { 60 | /* CMD12: STOP_TRANSMISSION */ 61 | if (__ed_sd_cmd(CMD12, 0) < 0) return -1; 62 | } 63 | /* Wait for card */ 64 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_8b); 65 | n = 65536; 66 | do 67 | { 68 | if (--n == 0) break; 69 | } 70 | while ((__ed_sd_dat_rd() & 0xFF) != 0xFF); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /src/ed/edcardinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "ed.h" 5 | 6 | int ed_card_init(void) 7 | { 8 | int i; 9 | int n; 10 | u32 rca; 11 | __cart_acs_get(); 12 | /* Detect SD interface */ 13 | /* 0: use SPI */ 14 | /* 1: use SD */ 15 | __sd_type = 0; 16 | if ((__cart_rd(ED_VER_REG) & 0xFFFF) >= 0x116) 17 | { 18 | /* Check bootloader ROM label for "ED64 SD boot" */ 19 | __cart_wr(ED_CFG_REG, ED_CFG_SDRAM_OFF); 20 | /* label[4:8] == " SD " */ 21 | if (__cart_rd(0x10000024) == 0x20534420) __sd_type = 1; 22 | __cart_wr(ED_CFG_REG, ED_CFG_SDRAM_ON); 23 | } 24 | /* SPI: SS = 0 */ 25 | /* SD : SS = 1 */ 26 | __sd_cfg = ED_SPI_SPD_LO; 27 | if (__sd_type) __sd_cfg |= ED_SPI_SS; 28 | /* Card needs 74 clocks, we do 80 */ 29 | __ed_sd_mode(ED_SD_CMD_WR, ED_SD_CMD_8b); 30 | for (i = 0; i < 10; i++) __ed_sd_cmd_wr(0xFF); 31 | /* CMD0: GO_IDLE_STATE */ 32 | __ed_sd_cmd(CMD0, 0); 33 | /* CMD8: SEND_IF_COND */ 34 | /* If it returns an error, it is SD V1 */ 35 | if (__ed_sd_cmd(CMD8, 0x1AA)) 36 | { 37 | /* SD V1 */ 38 | if (!__sd_type) 39 | { 40 | if (__ed_sd_cmd(CMD55, 0) < 0) CART_ABORT(); 41 | if (__ed_sd_cmd(ACMD41, 0x40300000) < 0) 42 | { 43 | n = 1024; 44 | do 45 | { 46 | if (--n == 0) CART_ABORT(); 47 | if (__ed_sd_cmd(CMD1, 0) < 0) CART_ABORT(); 48 | } 49 | while (__sd_resp[0] != 0); 50 | } 51 | else 52 | { 53 | n = 1024; 54 | do 55 | { 56 | if (--n == 0) CART_ABORT(); 57 | if (__ed_sd_cmd(CMD55, 0) < 0) CART_ABORT(); 58 | if (__sd_resp[0] != 1) continue; 59 | if (__ed_sd_cmd(ACMD41, 0x40300000) < 0) CART_ABORT(); 60 | } 61 | while (__sd_resp[0] != 0); 62 | } 63 | } 64 | else 65 | { 66 | n = 1024; 67 | do 68 | { 69 | if (--n == 0) CART_ABORT(); 70 | if (__ed_sd_cmd(CMD55, 0) < 0) CART_ABORT(); 71 | if (__ed_sd_cmd(ACMD41, 0x40300000) < 0) CART_ABORT(); 72 | } 73 | while (__sd_resp[1] == 0); 74 | } 75 | __sd_flag = 0; 76 | } 77 | else 78 | { 79 | /* SD V2 */ 80 | if (!__sd_type) 81 | { 82 | n = 1024; 83 | do 84 | { 85 | if (--n == 0) CART_ABORT(); 86 | if (__ed_sd_cmd(CMD55, 0) < 0) CART_ABORT(); 87 | if (__sd_resp[0] != 1) continue; 88 | if (__ed_sd_cmd(ACMD41, 0x40300000) < 0) CART_ABORT(); 89 | } 90 | while (__sd_resp[0] != 0); 91 | if (__ed_sd_cmd(CMD58, 0) < 0) CART_ABORT(); 92 | } 93 | else 94 | { 95 | n = 1024; 96 | do 97 | { 98 | if (--n == 0) CART_ABORT(); 99 | if (__ed_sd_cmd(CMD55, 0) < 0) CART_ABORT(); 100 | if (!(__sd_resp[3] & 1)) continue; 101 | __ed_sd_cmd(ACMD41, 0x40300000); 102 | } 103 | while (!(__sd_resp[1] & 0x80)); 104 | } 105 | /* Card is SDHC */ 106 | __sd_flag = __sd_resp[1] & 0x40; 107 | } 108 | if (!__sd_type) 109 | { 110 | __sd_cfg = ED_SPI_SPD_25; 111 | } 112 | else 113 | { 114 | /* CMD2: ALL_SEND_CID */ 115 | if (__ed_sd_cmd(CMD2, 0) < 0) CART_ABORT(); 116 | /* CMD3: SEND_RELATIVE_ADDR */ 117 | if (__ed_sd_cmd(CMD3, 0) < 0) CART_ABORT(); 118 | rca = 119 | __sd_resp[1] << 24 | 120 | __sd_resp[2] << 16 | 121 | __sd_resp[3] << 8 | 122 | __sd_resp[4] << 0; 123 | /* CMD9: SEND_CSD */ 124 | if (__ed_sd_cmd(CMD9, rca) < 0) CART_ABORT(); 125 | /* CMD7: SELECT_CARD */ 126 | if (__ed_sd_cmd(CMD7, rca) < 0) CART_ABORT(); 127 | /* ACMD6: SET_BUS_WIDTH */ 128 | if (__ed_sd_cmd(CMD55, rca) < 0) CART_ABORT(); 129 | if (__ed_sd_cmd(ACMD6, 2) < 0) CART_ABORT(); 130 | __sd_cfg = ED_SPI_SPD_50|ED_SPI_SS; 131 | } 132 | __cart_acs_rel(); 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /src/ed/edcardrdcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "ed.h" 5 | 6 | int ed_card_rd_cart(u32 cart, u32 lba, u32 count) 7 | { 8 | int i; 9 | int n; 10 | u32 resp; 11 | __cart_acs_get(); 12 | /* SDSC takes byte address, SDHC takes LBA */ 13 | if (!__sd_flag) lba *= 512; 14 | /* CMD18: READ_MULTIPLE_BLOCK */ 15 | if (__ed_sd_cmd(CMD18, lba) < 0) CART_ABORT(); 16 | /* DMA requires 2048-byte alignment */ 17 | if (cart & 0x7FF) 18 | { 19 | while (count-- > 0) 20 | { 21 | /* Wait for card */ 22 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_1b); 23 | n = 65536; 24 | do 25 | { 26 | if (--n == 0) CART_ABORT(); 27 | } 28 | while (__ed_sd_dat_rd() & 1); 29 | /* Read data */ 30 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_8b); 31 | for (i = 0; i < 512; i++) 32 | { 33 | ((char *)__cart_buf)[i] = __ed_sd_dat_rd(); 34 | } 35 | /* SPI: 1x16-bit CRC (2 byte) */ 36 | /* SD: 4x16-bit CRC (8 byte) */ 37 | /* We ignore the CRC */ 38 | n = !__sd_type ? 2 : 8; 39 | for (i = 0; i < n; i++) __ed_sd_dat_rd(); 40 | __cart_dma_wr(__cart_buf, cart, 512); 41 | cart += 512; 42 | } 43 | } 44 | else 45 | { 46 | if (cart_card_byteswap) 47 | { 48 | __cart_wr(ED_CFG_REG, ED_CFG_SDRAM_ON|ED_CFG_BYTESWAP); 49 | } 50 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_8b); 51 | __cart_wr(ED_DMA_LEN_REG, count-1); 52 | __cart_wr(ED_DMA_ADDR_REG, (cart & 0x3FFFFFF) >> 11); 53 | __cart_wr(ED_DMA_CFG_REG, ED_DMA_SD_TO_RAM); 54 | while ((resp = __cart_rd(ED_STATUS_REG)) & ED_STATE_DMA_BUSY) 55 | { 56 | if (resp & ED_STATE_DMA_TOUT) 57 | { 58 | __cart_wr(ED_CFG_REG, ED_CFG_SDRAM_ON); 59 | CART_ABORT(); 60 | } 61 | } 62 | if (cart_card_byteswap) 63 | { 64 | __cart_wr(ED_CFG_REG, ED_CFG_SDRAM_ON); 65 | } 66 | } 67 | if (__ed_sd_close(1)) CART_ABORT(); 68 | __cart_acs_rel(); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /src/ed/edcardrddram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "ed.h" 5 | 6 | int ed_card_rd_dram(void *dram, u32 lba, u32 count) 7 | { 8 | char *addr = dram; 9 | int i; 10 | int n; 11 | __cart_acs_get(); 12 | /* SDSC takes byte address, SDHC takes LBA */ 13 | if (!__sd_flag) lba *= 512; 14 | /* CMD18: READ_MULTIPLE_BLOCK */ 15 | if (__ed_sd_cmd(CMD18, lba) < 0) CART_ABORT(); 16 | while (count-- > 0) 17 | { 18 | /* Wait for card */ 19 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_1b); 20 | n = 65536; 21 | do 22 | { 23 | if (--n == 0) CART_ABORT(); 24 | } 25 | while (__ed_sd_dat_rd() & 1); 26 | /* Read data */ 27 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_8b); 28 | for (i = 0; i < 512; i++) addr[i] = __ed_sd_dat_rd(); 29 | /* SPI: 1x16-bit CRC (2 byte) */ 30 | /* SD: 4x16-bit CRC (8 byte) */ 31 | /* We ignore the CRC */ 32 | n = !__sd_type ? 2 : 8; 33 | for (i = 0; i < n; i++) __ed_sd_dat_rd(); 34 | addr += 512; 35 | } 36 | if (__ed_sd_close(1)) CART_ABORT(); 37 | __cart_acs_rel(); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /src/ed/edcardwrcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "ed.h" 5 | 6 | int ed_card_wr_cart(u32 cart, u32 lba, u32 count) 7 | { 8 | int i; 9 | int n; 10 | int resp; 11 | __cart_acs_get(); 12 | /* SDSC takes byte address, SDHC takes LBA */ 13 | if (!__sd_flag) lba *= 512; 14 | /* CMD25: WRITE_MULTIPLE_BLOCK */ 15 | if (__ed_sd_cmd(CMD25, lba) < 0) CART_ABORT(); 16 | if (!__sd_type) 17 | { 18 | /* SPI: padding (why 2 bytes?) */ 19 | __ed_sd_mode(ED_SD_DAT_WR, ED_SD_DAT_8b); 20 | __ed_sd_dat_wr(0xFF); 21 | __ed_sd_dat_wr(0xFF); 22 | } 23 | while (count-- > 0) 24 | { 25 | __ed_sd_mode(ED_SD_DAT_WR, ED_SD_DAT_8b); 26 | if (!__sd_type) 27 | { 28 | /* SPI: data token */ 29 | __ed_sd_dat_wr(0xFC); 30 | } 31 | else 32 | { 33 | /* SD: start bit (why not only write F0?) */ 34 | __ed_sd_dat_wr(0xFF); 35 | __ed_sd_dat_wr(0xF0); 36 | } 37 | __cart_dma_rd(__cart_buf, cart, 512); 38 | /* Write data */ 39 | for (i = 0; i < 512; i++) __ed_sd_dat_wr(((char *)__cart_buf)[i]); 40 | if (!__sd_type) 41 | { 42 | /* SPI: write dummy CRC */ 43 | for (i = 0; i < 2; i++) __ed_sd_dat_wr(0xFF); 44 | } 45 | else 46 | { 47 | /* SD: write real CRC */ 48 | __sd_crc16(__cart_buf, __cart_buf); 49 | for (i = 0; i < 8; i++) __ed_sd_dat_wr(((char *)__cart_buf)[i]); 50 | /* End bit */ 51 | __ed_sd_mode(ED_SD_DAT_WR, ED_SD_DAT_1b); 52 | __ed_sd_dat_wr(0xFF); 53 | /* Wait for start of response */ 54 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_1b); 55 | n = 1024; 56 | do 57 | { 58 | if (--n == 0) CART_ABORT(); 59 | } 60 | while (__ed_sd_dat_rd() & 1); 61 | /* Read response */ 62 | resp = 0; 63 | for (i = 0; i < 3; i++) resp = resp << 1 | (__ed_sd_dat_rd() & 1); 64 | if (resp != 2) CART_ABORT(); 65 | } 66 | /* Wait for card */ 67 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_8b); 68 | n = 65536; 69 | do 70 | { 71 | if (--n == 0) CART_ABORT(); 72 | } 73 | while ((__ed_sd_dat_rd() & 0xFF) != 0xFF); 74 | cart += 512; 75 | } 76 | if (__ed_sd_close(__sd_type)) CART_ABORT(); 77 | __cart_acs_rel(); 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /src/ed/edcardwrdram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "ed.h" 5 | 6 | int ed_card_wr_dram(const void *dram, u32 lba, u32 count) 7 | { 8 | const char *addr = dram; 9 | int i; 10 | int n; 11 | int resp; 12 | __cart_acs_get(); 13 | /* SDSC takes byte address, SDHC takes LBA */ 14 | if (!__sd_flag) lba *= 512; 15 | /* CMD25: WRITE_MULTIPLE_BLOCK */ 16 | if (__ed_sd_cmd(CMD25, lba) < 0) CART_ABORT(); 17 | if (!__sd_type) 18 | { 19 | /* SPI: padding (why 2 bytes?) */ 20 | __ed_sd_mode(ED_SD_DAT_WR, ED_SD_DAT_8b); 21 | __ed_sd_dat_wr(0xFF); 22 | __ed_sd_dat_wr(0xFF); 23 | } 24 | while (count-- > 0) 25 | { 26 | __ed_sd_mode(ED_SD_DAT_WR, ED_SD_DAT_8b); 27 | if (!__sd_type) 28 | { 29 | /* SPI: data token */ 30 | __ed_sd_dat_wr(0xFC); 31 | } 32 | else 33 | { 34 | /* SD: start bit (why not only write F0?) */ 35 | __ed_sd_dat_wr(0xFF); 36 | __ed_sd_dat_wr(0xF0); 37 | } 38 | /* Write data */ 39 | for (i = 0; i < 512; i++) __ed_sd_dat_wr(addr[i]); 40 | if (!__sd_type) 41 | { 42 | /* SPI: write dummy CRC */ 43 | for (i = 0; i < 2; i++) __ed_sd_dat_wr(0xFF); 44 | } 45 | else 46 | { 47 | /* SD: write real CRC */ 48 | if ((long)addr & 7) 49 | { 50 | __cart_buf_rd(addr); 51 | __sd_crc16(__cart_buf, __cart_buf); 52 | } 53 | else 54 | { 55 | __sd_crc16(__cart_buf, (const u64 *)addr); 56 | } 57 | for (i = 0; i < 8; i++) __ed_sd_dat_wr(((char *)__cart_buf)[i]); 58 | /* End bit */ 59 | __ed_sd_mode(ED_SD_DAT_WR, ED_SD_DAT_1b); 60 | __ed_sd_dat_wr(0xFF); 61 | /* Wait for start of response */ 62 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_1b); 63 | n = 1024; 64 | do 65 | { 66 | if (--n == 0) CART_ABORT(); 67 | } 68 | while (__ed_sd_dat_rd() & 1); 69 | /* Read response */ 70 | resp = 0; 71 | for (i = 0; i < 3; i++) resp = resp << 1 | (__ed_sd_dat_rd() & 1); 72 | if (resp != 2) CART_ABORT(); 73 | } 74 | /* Wait for card */ 75 | __ed_sd_mode(ED_SD_DAT_RD, ED_SD_DAT_8b); 76 | n = 65536; 77 | do 78 | { 79 | if (--n == 0) CART_ABORT(); 80 | } 81 | while ((__ed_sd_dat_rd() & 0xFF) != 0xFF); 82 | addr += 512; 83 | } 84 | if (__ed_sd_close(__sd_type)) CART_ABORT(); 85 | __cart_acs_rel(); 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/ed/edexit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ed.h" 4 | 5 | int ed_exit(void) 6 | { 7 | __cart_acs_get(); 8 | __cart_wr(ED_KEY_REG, 0); 9 | __cart_acs_rel(); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/ed/edinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "ed.h" 4 | 5 | int ed_init(void) 6 | { 7 | u32 ver; 8 | __cart_acs_get(); 9 | __cart_wr(ED_KEY_REG, ED_KEY); 10 | ver = __cart_rd(ED_VER_REG) & 0xFFFF; 11 | if (ver < 0x100 || ver >= 0x400) CART_ABORT(); 12 | __cart_wr(ED_CFG_REG, ED_CFG_SDRAM_ON); 13 | __cart_dom2 = 0x80370404; 14 | /* V1/V2/V2.5 do not have physical SRAM on board */ 15 | /* The end of SDRAM is used for SRAM or FlashRAM save types */ 16 | if (ver < 0x300) 17 | { 18 | u32 sav = __cart_rd(ED_SAV_CFG_REG); 19 | /* Have 1M SRAM or FlashRAM */ 20 | if (sav & ED_SAV_SRM_SIZE) 21 | { 22 | cart_size = 0x3FE0000; /* 64 MiB - 128 KiB */ 23 | } 24 | /* Have 256K SRAM */ 25 | else if (sav & ED_SAV_SRM_ON) 26 | { 27 | cart_size = 0x3FF8000; /* 64 MiB - 32KiB */ 28 | } 29 | else 30 | { 31 | cart_size = 0x4000000; /* 64 MiB */ 32 | } 33 | } 34 | __cart_acs_rel(); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /src/edx/edx.h: -------------------------------------------------------------------------------- 1 | #ifndef __EDX_H__ 2 | #define __EDX_H__ 3 | 4 | #define EDX_BASE_REG 0x1F800000 5 | 6 | #define EDX_BOOT_CFG_REG (EDX_BASE_REG+0x0010) 7 | #define EDX_EDID_REG (EDX_BASE_REG+0x0014) 8 | 9 | #define EDX_SYS_CFG_REG (EDX_BASE_REG+0x8000) 10 | #define EDX_KEY_REG (EDX_BASE_REG+0x8004) 11 | #define EDX_DMA_STA_REG (EDX_BASE_REG+0x8008) 12 | #define EDX_DMA_ADDR_REG (EDX_BASE_REG+0x8008) 13 | #define EDX_DMA_LEN_REG (EDX_BASE_REG+0x800C) 14 | #define EDX_SDIO_REG (EDX_BASE_REG+0x8020) 15 | #define EDX_SDIO_ARD_REG (EDX_BASE_REG+0x8200) 16 | #define EDX_SD_CMD_RD_REG (EDX_BASE_REG+0x8020) 17 | #define EDX_SD_CMD_WR_REG (EDX_BASE_REG+0x8024) 18 | #define EDX_SD_DAT_RD_REG (EDX_BASE_REG+0x8028) 19 | #define EDX_SD_DAT_WR_REG (EDX_BASE_REG+0x802C) 20 | #define EDX_SD_STATUS_REG (EDX_BASE_REG+0x8030) 21 | 22 | #define EDX_BCFG_BOOTMOD 0x0001 23 | #define EDX_BCFG_SD_INIT 0x0002 24 | #define EDX_BCFG_SD_TYPE 0x0004 25 | #define EDX_BCFG_GAMEMOD 0x0008 26 | #define EDX_BCFG_CICLOCK 0x8000 27 | 28 | #define EDX_DMA_STA_BUSY 0x0001 29 | #define EDX_DMA_STA_ERROR 0x0002 30 | #define EDX_DMA_STA_LOCK 0x0080 31 | 32 | #define EDX_SD_CFG_BITLEN 0x000F 33 | #define EDX_SD_CFG_SPD 0x0010 34 | #define EDX_SD_STA_BUSY 0x0080 35 | 36 | #define EDX_CFG_SDRAM_ON 0x0000 37 | #define EDX_CFG_SDRAM_OFF 0x0001 38 | #define EDX_CFG_REGS_OFF 0x0002 39 | #define EDX_CFG_BYTESWAP 0x0004 40 | 41 | #define EDX_KEY 0xAA55 42 | 43 | #define EDX_SD_CMD_RD EDX_SD_CMD_RD_REG 44 | #define EDX_SD_CMD_WR EDX_SD_CMD_WR_REG 45 | #define EDX_SD_DAT_RD EDX_SD_DAT_RD_REG 46 | #define EDX_SD_DAT_WR EDX_SD_DAT_WR_REG 47 | 48 | #define EDX_SD_CMD_8b 8 49 | #define EDX_SD_CMD_1b 1 50 | #define EDX_SD_DAT_16b 4 51 | #define EDX_SD_DAT_8b 2 52 | #define EDX_SD_DAT_4b 1 53 | 54 | #define __edx_sd_dat_wr(val) __cart_wr(EDX_SD_DAT_WR_REG, (val) << 8 | 0xFF) 55 | 56 | extern void __edx_sd_mode(u32 reg, int val); 57 | extern u32 __edx_sd_cmd_rd(void); 58 | extern void __edx_sd_cmd_wr(u32 val); 59 | extern u32 __edx_sd_dat_rd(void); 60 | extern int __edx_sd_cmd(int cmd, u32 arg); 61 | extern int __edx_sd_close(void); 62 | 63 | #endif /* __EDX_H__ */ 64 | -------------------------------------------------------------------------------- /src/edx/edxcard.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "edx.h" 5 | 6 | void __edx_sd_mode(u32 reg, int val) 7 | { 8 | static u32 mode; 9 | if (mode != reg) 10 | { 11 | mode = reg; 12 | __cart_wr(EDX_SD_STATUS_REG, __sd_cfg); 13 | __cart_wr(reg, 0xFFFF); 14 | while (__cart_rd(EDX_SD_STATUS_REG) & EDX_SD_STA_BUSY); 15 | } 16 | __cart_wr(EDX_SD_STATUS_REG, __sd_cfg | val); 17 | } 18 | 19 | u32 __edx_sd_cmd_rd(void) 20 | { 21 | __cart_wr(EDX_SD_CMD_RD_REG, 0xFFFF); 22 | while (__cart_rd(EDX_SD_STATUS_REG) & EDX_SD_STA_BUSY); 23 | return __cart_rd(EDX_SD_CMD_RD_REG); 24 | } 25 | 26 | void __edx_sd_cmd_wr(u32 val) 27 | { 28 | __cart_wr(EDX_SD_CMD_WR_REG, val); 29 | while (__cart_rd(EDX_SD_STATUS_REG) & EDX_SD_STA_BUSY); 30 | } 31 | 32 | u32 __edx_sd_dat_rd(void) 33 | { 34 | __cart_wr(EDX_SD_DAT_RD_REG, 0xFFFF); 35 | return __cart_rd(EDX_SD_DAT_RD_REG); 36 | } 37 | 38 | int __edx_sd_cmd(int cmd, u32 arg) 39 | { 40 | int i; 41 | int n; 42 | char buf[6]; 43 | buf[0] = cmd; 44 | buf[1] = arg >> 24; 45 | buf[2] = arg >> 16; 46 | buf[3] = arg >> 8; 47 | buf[4] = arg >> 0; 48 | buf[5] = __sd_crc7(buf); 49 | /* Send the command */ 50 | __edx_sd_mode(EDX_SD_CMD_WR, EDX_SD_CMD_8b); 51 | __edx_sd_cmd_wr(0xFF); 52 | for (i = 0; i < 6; i++) __edx_sd_cmd_wr(buf[i] & 0xFF); 53 | if (cmd == CMD18) return 0; 54 | /* Read the first response byte */ 55 | __edx_sd_mode(EDX_SD_CMD_RD, EDX_SD_CMD_8b); 56 | __sd_resp[0] = __edx_sd_cmd_rd(); 57 | __edx_sd_mode(EDX_SD_CMD_RD, EDX_SD_CMD_1b); 58 | n = 2048; 59 | while (__sd_resp[0] & 0xC0) 60 | { 61 | if (--n == 0) return -1; 62 | __sd_resp[0] = __edx_sd_cmd_rd(); 63 | } 64 | /* Read the rest of the response */ 65 | __edx_sd_mode(EDX_SD_CMD_RD, EDX_SD_CMD_8b); 66 | n = cmd == CMD2 || cmd == CMD9 ? 17 : 6; 67 | for (i = 1; i < n; i++) __sd_resp[i] = __edx_sd_cmd_rd(); 68 | return 0; 69 | } 70 | 71 | int __edx_sd_close(void) 72 | { 73 | int n; 74 | /* CMD12: STOP_TRANSMISSION */ 75 | if (__edx_sd_cmd(CMD12, 0) < 0) return -1; 76 | /* Wait for card */ 77 | __edx_sd_mode(EDX_SD_DAT_RD, EDX_SD_DAT_4b); 78 | __edx_sd_dat_rd(); 79 | __edx_sd_mode(EDX_SD_DAT_RD, EDX_SD_DAT_8b); 80 | __edx_sd_dat_rd(); 81 | n = 65536; 82 | do 83 | { 84 | if (--n == 0) break; 85 | } 86 | while ((__edx_sd_dat_rd() & 0xFF) != 0xFF); 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /src/edx/edxcardinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "edx.h" 5 | 6 | int edx_card_init(void) 7 | { 8 | int i; 9 | int n; 10 | uint32_t rca; 11 | uint32_t boot_cfg; 12 | __cart_acs_get(); 13 | /* Check if already init */ 14 | boot_cfg = __cart_rd(EDX_BOOT_CFG_REG); 15 | if (boot_cfg & EDX_BCFG_SD_INIT) 16 | { 17 | __sd_flag = boot_cfg & EDX_BCFG_SD_TYPE; 18 | } 19 | else 20 | { 21 | __sd_cfg = 0; 22 | /* Card needs 74 clocks, we do 80 */ 23 | __edx_sd_mode(EDX_SD_CMD_WR, EDX_SD_CMD_8b); 24 | for (i = 0; i < 10; i++) __edx_sd_cmd_wr(0xFF); 25 | /* CMD0: GO_IDLE_STATE */ 26 | __edx_sd_cmd(CMD0, 0); 27 | /* CMD8: SEND_IF_COND */ 28 | /* If it returns an error, it is SD V1 */ 29 | if (__edx_sd_cmd(CMD8, 0x1AA)) 30 | { 31 | /* SD V1 */ 32 | n = 1024; 33 | do 34 | { 35 | if (--n == 0) CART_ABORT(); 36 | if (__edx_sd_cmd(CMD55, 0) < 0) CART_ABORT(); 37 | if (__edx_sd_cmd(ACMD41, 0x40300000) < 0) CART_ABORT(); 38 | } 39 | while (__sd_resp[1] == 0); 40 | __sd_flag = 0; 41 | } 42 | else 43 | { 44 | /* SD V2 */ 45 | n = 1024; 46 | do 47 | { 48 | if (--n == 0) CART_ABORT(); 49 | if (__edx_sd_cmd(CMD55, 0) < 0) CART_ABORT(); 50 | if (!(__sd_resp[3] & 1)) continue; 51 | __edx_sd_cmd(ACMD41, 0x40300000); 52 | } 53 | while (!(__sd_resp[1] & 0x80)); 54 | /* Card is SDHC */ 55 | __sd_flag = __sd_resp[1] & 0x40; 56 | } 57 | /* CMD2: ALL_SEND_CID */ 58 | if (__edx_sd_cmd(CMD2, 0) < 0) CART_ABORT(); 59 | /* CMD3: SEND_RELATIVE_ADDR */ 60 | if (__edx_sd_cmd(CMD3, 0) < 0) CART_ABORT(); 61 | rca = 62 | __sd_resp[1] << 24 | 63 | __sd_resp[2] << 16 | 64 | __sd_resp[3] << 8 | 65 | __sd_resp[4] << 0; 66 | /* CMD9: SEND_CSD */ 67 | if (__edx_sd_cmd(CMD9, rca) < 0) CART_ABORT(); 68 | /* CMD7: SELECT_CARD */ 69 | if (__edx_sd_cmd(CMD7, rca) < 0) CART_ABORT(); 70 | /* ACMD6: SET_BUS_WIDTH */ 71 | if (__edx_sd_cmd(CMD55, rca) < 0) CART_ABORT(); 72 | if (__edx_sd_cmd(ACMD6, 2) < 0) CART_ABORT(); 73 | } 74 | __sd_cfg = EDX_SD_CFG_SPD; 75 | __cart_acs_rel(); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /src/edx/edxcardrdcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "edx.h" 5 | 6 | int edx_card_rd_cart(u32 cart, u32 lba, u32 count) 7 | { 8 | u32 resp; 9 | __cart_acs_get(); 10 | /* SDSC takes byte address, SDHC takes LBA */ 11 | if (!__sd_flag) lba *= 512; 12 | /* CMD18: READ_MULTIPLE_BLOCK */ 13 | if (__edx_sd_cmd(CMD18, lba) < 0) CART_ABORT(); 14 | if (cart_card_byteswap) 15 | { 16 | __cart_wr(EDX_SYS_CFG_REG, EDX_CFG_SDRAM_ON|EDX_CFG_BYTESWAP); 17 | } 18 | __cart_wr(EDX_DMA_ADDR_REG, cart & 0x3FFFFFF); 19 | __cart_wr(EDX_DMA_LEN_REG, count); 20 | __edx_sd_mode(EDX_SD_DAT_RD, EDX_SD_DAT_16b); 21 | while ((resp = __cart_rd(EDX_DMA_STA_REG)) & EDX_DMA_STA_BUSY) 22 | { 23 | if (resp & EDX_DMA_STA_ERROR) 24 | { 25 | __cart_wr(EDX_SYS_CFG_REG, EDX_CFG_SDRAM_ON); 26 | CART_ABORT(); 27 | } 28 | } 29 | if (cart_card_byteswap) 30 | { 31 | __cart_wr(EDX_SYS_CFG_REG, EDX_CFG_SDRAM_ON); 32 | } 33 | if (__edx_sd_close()) CART_ABORT(); 34 | __cart_acs_rel(); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /src/edx/edxcardrddram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "edx.h" 5 | 6 | int edx_card_rd_dram(void *dram, u32 lba, u32 count) 7 | { 8 | char *addr = dram; 9 | int n; 10 | __cart_acs_get(); 11 | /* SDSC takes byte address, SDHC takes LBA */ 12 | if (!__sd_flag) lba *= 512; 13 | /* CMD18: READ_MULTIPLE_BLOCK */ 14 | if (__edx_sd_cmd(CMD18, lba) < 0) CART_ABORT(); 15 | while (count-- > 0) 16 | { 17 | /* Wait for card */ 18 | __edx_sd_mode(EDX_SD_DAT_RD, EDX_SD_DAT_4b); 19 | n = 65536; 20 | do 21 | { 22 | if (--n == 0) CART_ABORT(); 23 | } 24 | while (__edx_sd_dat_rd() & 0xF); 25 | /* Read data */ 26 | __edx_sd_mode(EDX_SD_DAT_RD, EDX_SD_DAT_16b); 27 | if ((long)addr & 7) 28 | { 29 | __cart_dma_rd(__cart_buf, EDX_SDIO_ARD_REG, 512); 30 | __cart_buf_wr(addr); 31 | } 32 | else 33 | { 34 | __cart_dma_rd(addr, EDX_SDIO_ARD_REG, 512); 35 | } 36 | /* 4x16-bit CRC (8 byte) */ 37 | /* We ignore the CRC */ 38 | __cart_dma_rd(__cart_buf, EDX_SDIO_ARD_REG, 8); 39 | addr += 512; 40 | } 41 | if (__edx_sd_close()) CART_ABORT(); 42 | __cart_acs_rel(); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /src/edx/edxcardwrcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "edx.h" 5 | 6 | int edx_card_wr_cart(u32 cart, u32 lba, u32 count) 7 | { 8 | int i; 9 | int n; 10 | int resp; 11 | __cart_acs_get(); 12 | /* SDSC takes byte address, SDHC takes LBA */ 13 | if (!__sd_flag) lba *= 512; 14 | /* CMD25: WRITE_MULTIPLE_BLOCK */ 15 | if (__edx_sd_cmd(CMD25, lba) < 0) CART_ABORT(); 16 | while (count-- > 0) 17 | { 18 | /* SD: start bit (why not only write F0?) */ 19 | __edx_sd_mode(EDX_SD_DAT_WR, EDX_SD_DAT_8b); 20 | __edx_sd_dat_wr(0xFF); 21 | __edx_sd_dat_wr(0xF0); 22 | /* Write data and CRC */ 23 | __edx_sd_mode(EDX_SD_DAT_WR, EDX_SD_DAT_16b); 24 | __cart_dma_rd(__cart_buf, cart, 512); 25 | __cart_dma_wr(__cart_buf, EDX_SDIO_ARD_REG, 512); 26 | __sd_crc16(__cart_buf, __cart_buf); 27 | __cart_dma_wr(__cart_buf, EDX_SDIO_ARD_REG, 8); 28 | /* End bit */ 29 | __edx_sd_mode(EDX_SD_DAT_WR, EDX_SD_DAT_4b); 30 | __edx_sd_dat_wr(0xFF); 31 | /* Wait for start of response */ 32 | __edx_sd_mode(EDX_SD_DAT_RD, EDX_SD_DAT_4b); 33 | n = 1024; 34 | do 35 | { 36 | if (--n == 0) CART_ABORT(); 37 | } 38 | while (__edx_sd_dat_rd() & 1); 39 | /* Read response */ 40 | resp = 0; 41 | for (i = 0; i < 3; i++) resp = resp << 1 | (__edx_sd_dat_rd() & 1); 42 | if (resp != 2) CART_ABORT(); 43 | /* Wait for card */ 44 | n = 65536; 45 | do 46 | { 47 | if (--n == 0) CART_ABORT(); 48 | } 49 | while ((__edx_sd_dat_rd() & 0xFF) != 0xFF); 50 | cart += 512; 51 | } 52 | if (__edx_sd_close()) CART_ABORT(); 53 | __cart_acs_rel(); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /src/edx/edxcardwrdram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | #include "edx.h" 5 | 6 | int edx_card_wr_dram(const void *dram, u32 lba, u32 count) 7 | { 8 | const char *addr = dram; 9 | int i; 10 | int n; 11 | int resp; 12 | __cart_acs_get(); 13 | /* SDSC takes byte address, SDHC takes LBA */ 14 | if (!__sd_flag) lba *= 512; 15 | /* CMD25: WRITE_MULTIPLE_BLOCK */ 16 | if (__edx_sd_cmd(CMD25, lba) < 0) CART_ABORT(); 17 | while (count-- > 0) 18 | { 19 | /* SD: start bit (why not only write F0?) */ 20 | __edx_sd_mode(EDX_SD_DAT_WR, EDX_SD_DAT_8b); 21 | __edx_sd_dat_wr(0xFF); 22 | __edx_sd_dat_wr(0xF0); 23 | /* Write data and CRC */ 24 | __edx_sd_mode(EDX_SD_DAT_WR, EDX_SD_DAT_16b); 25 | if ((long)addr & 7) 26 | { 27 | __cart_buf_rd(addr); 28 | __cart_dma_wr(__cart_buf, EDX_SDIO_ARD_REG, 512); 29 | __sd_crc16(__cart_buf, __cart_buf); 30 | } 31 | else 32 | { 33 | __cart_dma_wr(addr, EDX_SDIO_ARD_REG, 512); 34 | __sd_crc16(__cart_buf, (const u64 *)addr); 35 | } 36 | __cart_dma_wr(__cart_buf, EDX_SDIO_ARD_REG, 8); 37 | /* End bit */ 38 | __edx_sd_mode(EDX_SD_DAT_WR, EDX_SD_DAT_4b); 39 | __edx_sd_dat_wr(0xFF); 40 | /* Wait for start of response */ 41 | __edx_sd_mode(EDX_SD_DAT_RD, EDX_SD_DAT_4b); 42 | n = 1024; 43 | do 44 | { 45 | if (--n == 0) CART_ABORT(); 46 | } 47 | while (__edx_sd_dat_rd() & 1); 48 | /* Read response */ 49 | resp = 0; 50 | for (i = 0; i < 3; i++) resp = resp << 1 | (__edx_sd_dat_rd() & 1); 51 | if (resp != 2) CART_ABORT(); 52 | /* Wait for card */ 53 | n = 65536; 54 | do 55 | { 56 | if (--n == 0) CART_ABORT(); 57 | } 58 | while ((__edx_sd_dat_rd() & 0xFF) != 0xFF); 59 | addr += 512; 60 | } 61 | if (__edx_sd_close()) CART_ABORT(); 62 | __cart_acs_rel(); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /src/edx/edxexit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "edx.h" 4 | 5 | int edx_exit(void) 6 | { 7 | __cart_acs_get(); 8 | __cart_wr(EDX_KEY_REG, 0); 9 | __cart_acs_rel(); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/edx/edxinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "edx.h" 4 | #include 5 | 6 | static const char edx_bootx[20] = "EverDrive bootloader"; 7 | static const char edx_boot3[12] = "ED64 SD boot"; 8 | 9 | int edx_init(void) 10 | { 11 | __cart_acs_get(); 12 | __cart_wr(EDX_KEY_REG, EDX_KEY); 13 | __cart_wr(EDX_SYS_CFG_REG, EDX_CFG_SDRAM_OFF); 14 | /* Check bootloader ROM label */ 15 | __cart_dma_rd(__cart_buf, 0x10000020, 20); 16 | if (memcmp(__cart_buf, edx_bootx, 20) && memcmp(__cart_buf, edx_boot3, 12)) 17 | { 18 | CART_ABORT(); 19 | } 20 | __cart_wr(EDX_SYS_CFG_REG, EDX_CFG_SDRAM_ON); 21 | __cart_dom1 = 0x80370C04; 22 | cart_size = 0x4000000; /* 64 MiB */ 23 | __cart_acs_rel(); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /src/sc/sc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sc.h" 4 | 5 | int __sc_sync(void) 6 | { 7 | while (__cart_rd(SC_STATUS_REG) & SC_CMD_BUSY); 8 | if (__cart_rd(SC_STATUS_REG) & SC_CMD_ERROR) return -1; 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/sc/sc.h: -------------------------------------------------------------------------------- 1 | #ifndef __SC_H__ 2 | #define __SC_H__ 3 | 4 | #define SC_BASE_REG 0x1FFF0000 5 | #define SC_BUFFER_REG 0x1FFE0000 6 | 7 | #define SC_STATUS_REG (SC_BASE_REG+0x00) 8 | #define SC_COMMAND_REG (SC_BASE_REG+0x00) 9 | #define SC_DATA0_REG (SC_BASE_REG+0x04) 10 | #define SC_DATA1_REG (SC_BASE_REG+0x08) 11 | #define SC_IDENTIFIER_REG (SC_BASE_REG+0x0C) 12 | #define SC_KEY_REG (SC_BASE_REG+0x10) 13 | 14 | #define SC_CMD_BUSY 0x80000000 15 | #define SC_CMD_ERROR 0x40000000 16 | #define SC_IRQ_PENDING 0x20000000 17 | 18 | #define SC_CONFIG_GET 'c' 19 | #define SC_CONFIG_SET 'C' 20 | #define SC_SD_OP 'i' 21 | #define SC_SD_SECTOR_SET 'I' 22 | #define SC_SD_READ 's' 23 | #define SC_SD_WRITE 'S' 24 | 25 | #define SC_CFG_ROM_WRITE 1 26 | #define SC_CFG_DD_MODE 3 27 | #define SC_CFG_SAVE_TYPE 6 28 | 29 | #define SC_SD_DEINIT 0 30 | #define SC_SD_INIT 1 31 | #define SC_SD_GET_STATUS 2 32 | #define SC_SD_GET_INFO 3 33 | #define SC_SD_BYTESWAP_ON 4 34 | #define SC_SD_BYTESWAP_OFF 5 35 | 36 | #define SC_DD_MODE_REGS 1 37 | #define SC_DD_MODE_IPL 2 38 | 39 | #define SC_IDENTIFIER 0x53437632 /* SCv2 */ 40 | 41 | #define SC_KEY_RESET 0x00000000 42 | #define SC_KEY_LOCK 0xFFFFFFFF 43 | #define SC_KEY_UNL 0x5F554E4C /* _UNL */ 44 | #define SC_KEY_OCK 0x4F434B5F /* OCK_ */ 45 | 46 | extern int __sc_sync(void); 47 | 48 | #endif /* __SC_H__ */ 49 | -------------------------------------------------------------------------------- /src/sc/sccardinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sc.h" 4 | 5 | int sc_card_init(void) 6 | { 7 | __cart_acs_get(); 8 | __sc_sync(); 9 | __cart_wr(SC_DATA1_REG, SC_SD_INIT); 10 | __cart_wr(SC_COMMAND_REG, SC_SD_OP); 11 | if (__sc_sync()) CART_ABORT(); 12 | __cart_acs_rel(); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/sc/sccardrdcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sc.h" 4 | 5 | int sc_card_rd_cart(u32 cart, u32 lba, u32 count) 6 | { 7 | __cart_acs_get(); 8 | __sc_sync(); 9 | if (cart_card_byteswap) 10 | { 11 | __cart_wr(SC_DATA1_REG, SC_SD_BYTESWAP_ON); 12 | __cart_wr(SC_COMMAND_REG, SC_SD_OP); 13 | if (__sc_sync()) CART_ABORT(); 14 | } 15 | __cart_wr(SC_DATA0_REG, lba); 16 | __cart_wr(SC_COMMAND_REG, SC_SD_SECTOR_SET); 17 | if (__sc_sync()) CART_ABORT(); 18 | __cart_wr(SC_DATA0_REG, cart); 19 | __cart_wr(SC_DATA1_REG, count); 20 | __cart_wr(SC_COMMAND_REG, SC_SD_READ); 21 | if (__sc_sync()) CART_ABORT(); 22 | if (cart_card_byteswap) 23 | { 24 | __cart_wr(SC_DATA1_REG, SC_SD_BYTESWAP_OFF); 25 | __cart_wr(SC_COMMAND_REG, SC_SD_OP); 26 | if (__sc_sync()) CART_ABORT(); 27 | } 28 | __cart_acs_rel(); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /src/sc/sccardrddram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sc.h" 4 | 5 | int sc_card_rd_dram(void *dram, u32 lba, u32 count) 6 | { 7 | char *addr = dram; 8 | int i; 9 | int n; 10 | __cart_acs_get(); 11 | __sc_sync(); 12 | while (count > 0) 13 | { 14 | n = count < 16 ? count : 16; 15 | __cart_wr(SC_DATA0_REG, lba); 16 | __cart_wr(SC_COMMAND_REG, SC_SD_SECTOR_SET); 17 | if (__sc_sync()) CART_ABORT(); 18 | __cart_wr(SC_DATA0_REG, SC_BUFFER_REG); 19 | __cart_wr(SC_DATA1_REG, n); 20 | __cart_wr(SC_COMMAND_REG, SC_SD_READ); 21 | if (__sc_sync()) CART_ABORT(); 22 | if ((long)addr & 7) 23 | { 24 | for (i = 0; i < n; i++) 25 | { 26 | __cart_dma_rd(__cart_buf, SC_BUFFER_REG+512*i, 512); 27 | __cart_buf_wr(addr); 28 | addr += 512; 29 | } 30 | } 31 | else 32 | { 33 | __cart_dma_rd(addr, SC_BUFFER_REG, 512*n); 34 | addr += 512*n; 35 | } 36 | lba += n; 37 | count -= n; 38 | } 39 | __cart_acs_rel(); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /src/sc/sccardwrcart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sc.h" 4 | 5 | int sc_card_wr_cart(u32 cart, u32 lba, u32 count) 6 | { 7 | __cart_acs_get(); 8 | __sc_sync(); 9 | __cart_wr(SC_DATA0_REG, lba); 10 | __cart_wr(SC_COMMAND_REG, SC_SD_SECTOR_SET); 11 | if (__sc_sync()) CART_ABORT(); 12 | __cart_wr(SC_DATA0_REG, cart); 13 | __cart_wr(SC_DATA1_REG, count); 14 | __cart_wr(SC_COMMAND_REG, SC_SD_WRITE); 15 | if (__sc_sync()) CART_ABORT(); 16 | __cart_acs_rel(); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/sc/sccardwrdram.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sc.h" 4 | 5 | int sc_card_wr_dram(const void *dram, u32 lba, u32 count) 6 | { 7 | const char *addr = dram; 8 | int i; 9 | int n; 10 | __cart_acs_get(); 11 | __sc_sync(); 12 | while (count > 0) 13 | { 14 | n = count < 16 ? count : 16; 15 | if ((long)addr & 7) 16 | { 17 | for (i = 0; i < n; i++) 18 | { 19 | __cart_buf_rd(addr); 20 | __cart_dma_wr(__cart_buf, SC_BUFFER_REG+512*i, 512); 21 | addr += 512; 22 | } 23 | } 24 | else 25 | { 26 | __cart_dma_wr(addr, SC_BUFFER_REG, 512*n); 27 | addr += 512*n; 28 | } 29 | __cart_wr(SC_DATA0_REG, lba); 30 | __cart_wr(SC_COMMAND_REG, SC_SD_SECTOR_SET); 31 | if (__sc_sync()) CART_ABORT(); 32 | __cart_wr(SC_DATA0_REG, SC_BUFFER_REG); 33 | __cart_wr(SC_DATA1_REG, n); 34 | __cart_wr(SC_COMMAND_REG, SC_SD_WRITE); 35 | if (__sc_sync()) CART_ABORT(); 36 | lba += n; 37 | count -= n; 38 | } 39 | __cart_acs_rel(); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /src/sc/scexit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sc.h" 4 | 5 | int sc_exit(void) 6 | { 7 | __cart_acs_get(); 8 | __sc_sync(); 9 | __cart_wr(SC_DATA1_REG, SC_SD_DEINIT); 10 | __cart_wr(SC_COMMAND_REG, SC_SD_OP); 11 | __sc_sync(); 12 | __cart_wr(SC_DATA0_REG, SC_CFG_ROM_WRITE); 13 | __cart_wr(SC_DATA1_REG, 0); 14 | __cart_wr(SC_COMMAND_REG, SC_CONFIG_SET); 15 | __sc_sync(); 16 | __cart_wr(SC_KEY_REG, SC_KEY_RESET); 17 | __cart_wr(SC_KEY_REG, SC_KEY_LOCK); 18 | __cart_acs_rel(); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /src/sc/scinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sc.h" 4 | 5 | int sc_init(void) 6 | { 7 | u32 cfg; 8 | __cart_acs_get(); 9 | __cart_wr(SC_KEY_REG, SC_KEY_RESET); 10 | __cart_wr(SC_KEY_REG, SC_KEY_UNL); 11 | __cart_wr(SC_KEY_REG, SC_KEY_OCK); 12 | if (__cart_rd(SC_IDENTIFIER_REG) != SC_IDENTIFIER) CART_ABORT(); 13 | __sc_sync(); 14 | __cart_wr(SC_DATA0_REG, SC_CFG_ROM_WRITE); 15 | __cart_wr(SC_DATA1_REG, 1); 16 | __cart_wr(SC_COMMAND_REG, SC_CONFIG_SET); 17 | __sc_sync(); 18 | /* SC64 uses SDRAM for 64DD */ 19 | __cart_wr(SC_DATA0_REG, SC_CFG_DD_MODE); 20 | __cart_wr(SC_COMMAND_REG, SC_CONFIG_GET); 21 | __sc_sync(); 22 | cfg = __cart_rd(SC_DATA1_REG); 23 | /* Have registers */ 24 | if (cfg & SC_DD_MODE_REGS) 25 | { 26 | cart_size = 0x2000000; /* 32 MiB */ 27 | } 28 | /* Have IPL */ 29 | else if (cfg & SC_DD_MODE_IPL) 30 | { 31 | cart_size = 0x3BC0000; /* 59.75 MiB */ 32 | } 33 | else 34 | { 35 | /* SC64 does not have physical SRAM on board */ 36 | /* The end of SDRAM is used for SRAM or FlashRAM save types */ 37 | __cart_wr(SC_DATA0_REG, SC_CFG_SAVE_TYPE); 38 | __cart_wr(SC_COMMAND_REG, SC_CONFIG_GET); 39 | __sc_sync(); 40 | /* Have SRAM or FlashRAM */ 41 | if (__cart_rd(SC_DATA1_REG) >= 3) 42 | { 43 | cart_size = 0x3FE0000; /* 64 MiB - 128 KiB */ 44 | } 45 | else 46 | { 47 | cart_size = 0x4000000; /* 64 MiB */ 48 | } 49 | } 50 | __cart_dom1 = 0x802F0C05; 51 | __cart_acs_rel(); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /src/sd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | 5 | unsigned char __sd_resp[17]; 6 | unsigned char __sd_cfg; 7 | unsigned char __sd_type; 8 | unsigned char __sd_flag; 9 | 10 | int __sd_crc7(const char *src) 11 | { 12 | int i; 13 | int n; 14 | int crc = 0; 15 | for (i = 0; i < 5; i++) 16 | { 17 | crc ^= src[i]; 18 | for (n = 0; n < 8; n++) 19 | { 20 | if ((crc <<= 1) & 0x100) crc ^= 0x12; 21 | } 22 | } 23 | return (crc & 0xFE) | 1; 24 | } 25 | -------------------------------------------------------------------------------- /src/sd.h: -------------------------------------------------------------------------------- 1 | #ifndef __SD_H__ 2 | #define __SD_H__ 3 | 4 | #define CMD0 (0x40| 0) 5 | #define CMD1 (0x40| 1) 6 | #define CMD2 (0x40| 2) 7 | #define CMD3 (0x40| 3) 8 | #define CMD7 (0x40| 7) 9 | #define CMD8 (0x40| 8) 10 | #define CMD9 (0x40| 9) 11 | #define CMD12 (0x40|12) 12 | #define CMD18 (0x40|18) 13 | #define CMD25 (0x40|25) 14 | #define CMD55 (0x40|55) 15 | #define CMD58 (0x40|58) 16 | #define ACMD6 (0x40| 6) 17 | #define ACMD41 (0x40|41) 18 | 19 | extern unsigned char __sd_resp[17]; 20 | extern unsigned char __sd_cfg; 21 | extern unsigned char __sd_type; 22 | extern unsigned char __sd_flag; 23 | 24 | extern int __sd_crc7(const char *src); 25 | extern void __sd_crc16(u64 *dst, const u64 *src); 26 | 27 | #endif /* __SD_H__ */ 28 | -------------------------------------------------------------------------------- /src/sdcrc16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cartint.h" 3 | #include "sd.h" 4 | 5 | /* Thanks to anacierdem for this brilliant implementation. */ 6 | 7 | /* Spread lower 32 bits into 64 bits */ 8 | /* x = **** **** **** **** abcd efgh ijkl mnop */ 9 | /* result: a0b0 c0d0 e0f0 g0h0 i0j0 k0l0 m0n0 o0p0 */ 10 | static uint64_t __sd_crc16_spread(uint64_t x) 11 | { 12 | x = (x << 16 | x) & 0x0000FFFF0000FFFF; 13 | x = (x << 8 | x) & 0x00FF00FF00FF00FF; 14 | x = (x << 4 | x) & 0x0F0F0F0F0F0F0F0F; 15 | x = (x << 2 | x) & 0x3333333333333333; 16 | x = (x << 1 | x) & 0x5555555555555555; 17 | return x; 18 | } 19 | 20 | /* Shuffle 32 bits of two values into 64 bits */ 21 | /* x = **** **** **** **** abcd efgh ijkl mnop */ 22 | /* y = **** **** **** **** ABCD EFGH IJKL MNOP */ 23 | /* result: aAbB cCdD eEfF gGhH iIjJ kKlL mMnN oOpP */ 24 | static uint64_t __sd_crc16_shuffle(uint32_t x, uint32_t y) 25 | { 26 | return __sd_crc16_spread(x) << 1 | __sd_crc16_spread(y); 27 | } 28 | 29 | void __sd_crc16(uint64_t *dst, const uint64_t *src) 30 | { 31 | int i; 32 | int n; 33 | uint64_t x; 34 | uint64_t y; 35 | uint32_t a; 36 | uint32_t b; 37 | uint16_t crc[4] = {0}; 38 | for (i = 0; i < 512/8; i++) 39 | { 40 | x = src[i]; 41 | /* Transpose every 2x2 bit block in the 8x8 matrix */ 42 | /* abcd efgh aick emgo */ 43 | /* ijkl mnop bjdl fnhp */ 44 | /* qrst uvwx qys0 u2w4 */ 45 | /* yz01 2345 \ rzt1 v3x5 */ 46 | /* 6789 ABCD / 6E8G AICK */ 47 | /* EFGH IJKL 7F9H BJDL */ 48 | /* MNOP QRST MUOW QYS? */ 49 | /* UVWX YZ?! NVPX RZT! */ 50 | y = (x ^ (x >> 7)) & 0x00AA00AA00AA00AA; 51 | x ^= y ^ (y << 7); 52 | /* Transpose 2x2 blocks inside their 4x4 blocks in the 8x8 matrix */ 53 | /* aick emgo aiqy emu2 */ 54 | /* bjdl fnhp bjrz fnv3 */ 55 | /* qys0 u2w4 cks0 gow4 */ 56 | /* rzt1 v3x5 \ dlt1 hpx5 */ 57 | /* 6E8G AICK / 6EMU AIQY */ 58 | /* 7F9H BJDL 7FNV BJRZ */ 59 | /* MUOW QYS? 8GOW CKS? */ 60 | /* NVPX RZT! 9HPX DLT! */ 61 | y = (x ^ (x >> 14)) & 0x0000CCCC0000CCCC; 62 | x ^= y ^ (y << 14); 63 | /* Interleave */ 64 | /* x = aiqy 6EMU bjrz 7FNV cks0 8GOW dlt1 9HPX */ 65 | /* y = emu2 AIQY fnv3 BJRZ gow4 CKS? hpx5 DLT! */ 66 | /* result: aeim quy2 6AEI MQUY bfjn rvz3 7BFJ NRVZ */ 67 | /* cgko sw04 8CGK OSW? dhlp tx15 9DHL PTX! */ 68 | x = __sd_crc16_shuffle( 69 | (x >> 32 & 0xF0F0F0F0) | (x >> 4 & 0x0F0F0F0F), 70 | (x >> 28 & 0xF0F0F0F0) | (x >> 0 & 0x0F0F0F0F) 71 | ); 72 | for (n = 3; n >= 0; n--) 73 | { 74 | a = crc[n]; 75 | /* (crc >> 8) ^ dat[0] */ 76 | b = ((x ^ a) >> 8) & 0xFF; 77 | b ^= b >> 4; 78 | a = (a << 8) ^ b ^ (b << 5) ^ (b << 12); 79 | /* (crc >> 8) ^ dat[1] */ 80 | b = (x ^ (a >> 8)) & 0xFF; 81 | b ^= b >> 4; 82 | a = (a << 8) ^ b ^ (b << 5) ^ (b << 12); 83 | crc[n] = a; 84 | x >>= 16; 85 | } 86 | } 87 | /* Interleave CRC */ 88 | x = __sd_crc16_shuffle(crc[0] << 16 | crc[1], crc[2] << 16 | crc[3]); 89 | *dst = __sd_crc16_shuffle(x >> 32, x); 90 | } 91 | -------------------------------------------------------------------------------- /src/sdcrc16.s: -------------------------------------------------------------------------------- 1 | #ifndef sgi 2 | .set gp=64 3 | #endif 4 | .set noreorder 5 | 6 | .globl __sd_crc16 7 | __sd_crc16: 8 | move $25, $31 9 | li $8, 0x00AA00AA 10 | li $9, 0x0000CCCC 11 | li $10, 0x55555555 12 | li $11, 0x33333333 13 | li $12, 0x0F0F0F0F 14 | li $13, 0x00FF00FF 15 | li $14, 0x0000FFFF 16 | dsll $15, $8, 32 17 | or $8, $15 18 | dsll $15, $9, 32 19 | or $9, $15 20 | dsll $15, $10, 32 21 | or $10, $15 22 | dsll $15, $11, 32 23 | or $11, $15 24 | dsll $15, $12, 32 25 | or $12, $15 26 | dsll $15, $13, 32 27 | or $13, $15 28 | dsll $15, $14, 32 29 | or $14, $15 30 | sd $0, ($29) 31 | addu $6, $5, 512-8 32 | 1: 33 | ld $2, ($5) 34 | dsrl $3, $2, 7 35 | xor $3, $2 36 | and $3, $8 37 | xor $2, $3 38 | dsll $3, 7 39 | xor $2, $3 40 | dsrl $3, $2, 14 41 | xor $3, $2 42 | and $3, $9 43 | xor $2, $3 44 | dsll $3, 14 45 | xor $2, $3 46 | li $15, 0x0F0F0F0F 47 | and $3, $2, $15 48 | dsll $15, 4 49 | dsrl $7, $2, 28 50 | and $7, $15 51 | or $3, $7 52 | dsrl $7, $2, 32 53 | and $7, $15 54 | and $2, $15 55 | dsrl $2, 4 56 | bal 3f 57 | or $2, $7 58 | addu $7, $29, 8-2 59 | 2: 60 | lhu $3, ($7) 61 | xor $24, $2, $3 62 | srl $24, 8 63 | and $24, 0xFF 64 | srl $15, $24, 4 65 | xor $24, $15 66 | sll $3, 8 67 | xor $3, $24 68 | sll $24, 5 69 | xor $3, $24 70 | sll $24, 7 71 | xor $3, $24 72 | srl $15, $3, 8 73 | xor $24, $2, $15 74 | and $24, 0xFF 75 | srl $15, $24, 4 76 | xor $24, $15 77 | sll $3, 8 78 | xor $3, $24 79 | sll $24, 5 80 | xor $3, $24 81 | sll $24, 7 82 | xor $3, $24 83 | sh $3, ($7) 84 | dsrl $2, 16 85 | bne $7, $29, 2b 86 | subu $7, 2 87 | bne $5, $6, 1b 88 | addu $5, 8 89 | lwu $2, 0($29) 90 | bal 3f 91 | lwu $3, 4($29) 92 | dsll $3, $2, 32 93 | dsrl $3, 32 94 | bal 3f 95 | dsrl $2, 32 96 | j $25 97 | sd $2, ($4) 98 | 3: 99 | move $24, $31 100 | bal 4f 101 | nop 102 | dsll $7, $2, 1 103 | bal 4f 104 | move $2, $3 105 | j $24 106 | or $2, $7 107 | 4: 108 | dsll $15, $2, 16 109 | or $2, $15 110 | and $2, $14 111 | dsll $15, $2, 8 112 | or $2, $15 113 | and $2, $13 114 | dsll $15, $2, 4 115 | or $2, $15 116 | and $2, $12 117 | dsll $15, $2, 2 118 | or $2, $15 119 | and $2, $11 120 | dsll $15, $2, 1 121 | or $2, $15 122 | j $31 123 | and $2, $10 124 | -------------------------------------------------------------------------------- /tools/cat: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | arg = [] 6 | flag = [] 7 | src = None 8 | i = 1 9 | while i < len(sys.argv): 10 | x = sys.argv[i] 11 | i += 1 12 | if x.startswith("-"): 13 | if x.startswith("-I") or x.startswith("-D"): 14 | if len(x) == 2: 15 | x += sys.argv[i] 16 | i += 1 17 | flag.append(x) 18 | elif x == "-c": 19 | src = True 20 | elif x == "-h": 21 | src = False 22 | else: 23 | sys.stderr.write("error: bad opt '%s'\n" % x) 24 | sys.exit(1) 25 | else: 26 | arg.append(x) 27 | if src is None: 28 | sys.stderr.write("error: type not specified\n") 29 | sys.exit(1) 30 | ultra = "-D_ULTRA64" in flag 31 | if src: 32 | lib = "libultra" if ultra else "libdragon" 33 | url = "https://github.com/devwizard64/libcart" 34 | banner = "Adapted for use with " + lib + " - " + url 35 | sys.stdout.write("/*"+"*"*76+"*/\n") 36 | sys.stdout.write("/*"+banner.center(76)+"*/\n") 37 | sys.stdout.write("/*"+"*"*76+"*/\n") 38 | sys.stdout.write("\n") 39 | if ultra: 40 | sys.stdout.write("#include \n") 41 | sys.stdout.write("#include \n") 42 | else: 43 | sys.stdout.write("#include \"n64types.h\"\n") 44 | sys.stdout.write("#include \"n64sys.h\"\n") 45 | sys.stdout.write("#include \"dma.h\"\n") 46 | sys.stdout.write("#include \"libcart/cart.h\"\n") 47 | sys.stdout.write("\n") 48 | flag = True 49 | for path in arg: 50 | code = 0 51 | for line in open(path, "r"): 52 | if src: 53 | if line.startswith("extern"): 54 | if "__os" not in line: continue 55 | if ( 56 | line.startswith("void __") or 57 | line.startswith("int __") or 58 | line.startswith("unsigned char __") or 59 | line.startswith("u32 __") or 60 | line.startswith("u64 __") 61 | ): line = "static "+line 62 | if line == "#ifdef __GNUC__\n": 63 | if not ultra: 64 | code = 2 65 | continue 66 | if line == "#ifdef _ULTRA64\n": 67 | code = 2 if ultra else 3 68 | continue 69 | if line == "#ifndef _ULTRA64\n": 70 | code = 3 if ultra else 2 71 | continue 72 | if line.startswith("#else"): 73 | if code & 2: 74 | code ^= 1 75 | continue 76 | if line.startswith("#endif"): 77 | if code & 2: 78 | code = 0 79 | continue 80 | if code & 1: continue 81 | if ultra: 82 | line = line.replace("u_uint64_t", "u64") 83 | line = line.replace("uint16_t", "u16") 84 | line = line.replace("uint32_t", "u32") 85 | line = line.replace("uint64_t", "u64") 86 | else: 87 | if line.startswith("typedef"): continue 88 | if line.startswith("#define __cart_"): continue 89 | line = line.replace("u16", "uint16_t") 90 | line = line.replace("u32", "uint32_t") 91 | line = line.replace("u64", "uint64_t") 92 | line = line.replace("__cart_rd", "io_read") 93 | line = line.replace("__cart_wr", "io_write") 94 | if line.startswith("#define IO_WRITE"): 95 | line = line[:28] + "\\\n\t\t" + line[28:] 96 | if line == "__attribute__((aligned(16)))\n": 97 | line = line[:-1] + " " 98 | line = line.replace("\t", " ") 99 | if src: 100 | if line.startswith("#include "): continue 101 | if line.endswith("_H__\n"): 102 | if line.startswith("#ifndef __"): continue 103 | if line.startswith("#define __"): continue 104 | if line.endswith("_H__ */\n"): 105 | if line.startswith("#endif /* __"): continue 106 | if line == "\n": 107 | if not flag: 108 | flag = True 109 | sys.stdout.write(line) 110 | else: 111 | flag = False 112 | sys.stdout.write(line) 113 | --------------------------------------------------------------------------------