├── .gitignore ├── .gitmodules ├── Makefile ├── README.md ├── build.sh ├── doc └── functions.txt ├── docker ├── Dockerfile └── setup-docker.sh ├── inc ├── chksum64.h ├── cic.h ├── constants.h ├── debug.h ├── diskio.h ├── errors.h ├── everdrive.h ├── ff.h ├── ffconf.h ├── font_patch │ ├── font.h │ └── info.txt ├── hashtable.h ├── image.h ├── ini.h ├── integer.h ├── localevar.h ├── main.h ├── mem.h ├── memorypak.h ├── mempak.h ├── menu.h ├── mp3.h ├── regsinternal.h ├── rom.h ├── sd.h ├── sound.h ├── sram.h ├── stb_image.h ├── stb_truetype.h ├── strlib.h ├── sys.h ├── types.h ├── usb.h ├── utils.h └── version.h ├── res ├── ALTRA64.INI ├── WALLPAPER │ └── bg.bmp ├── emulators │ ├── UltraSMS.z64 │ ├── gb.v64 │ ├── neon64bu.rom │ └── ultraMSX2.z64 ├── filesystem │ ├── sounds │ │ ├── bamboo.wav │ │ ├── bgm21.it │ │ ├── boot.wav │ │ ├── done.wav │ │ ├── doned.wav │ │ ├── ed64_mono.wav │ │ └── warning.wav │ └── sprites │ │ ├── background.png │ │ ├── background.sprite │ │ ├── n64controller.png │ │ ├── n64controller.sprite │ │ ├── old │ │ ├── background.png │ │ ├── background.sprite │ │ ├── n64controller.png │ │ ├── n64controller.sprite │ │ ├── splash.png │ │ └── splash.sprite │ │ └── splash.sprite └── header.ed64 ├── src ├── chksum64.c ├── cic.c ├── debug.c ├── diskio.c ├── everdrive.c ├── ff.c ├── ffsystem.c ├── ffunicode.c ├── hashtable.c ├── image.c ├── ini.c ├── main.c ├── mem.c ├── memorypak.c ├── mempak.c ├── menu.c ├── menu_about.c ├── menu_controls.c ├── menu_delete.c ├── mp3.c ├── rom.c ├── sd.c ├── sound.c ├── sram.c ├── strlib.c ├── sys.c ├── usb.c ├── utils.c └── version.c └── tools ├── deploy-sd.sh ├── extract-firmware.cmd ├── release-deploy.sh ├── reset-wsfl.cmd ├── setup-linux.sh └── setup-wsfl.cmd /.gitignore: -------------------------------------------------------------------------------- 1 | ## Build folder 2 | /build/* 3 | ## Build files 4 | *.v64 5 | *.elf 6 | *.o 7 | *.bin 8 | *.dfs 9 | ## Don't delete emulators 10 | !res/emulators/* 11 | 12 | ## OSX junk 13 | .DS_Store 14 | .Trashes 15 | ._* 16 | 17 | ## Temporary files 18 | *.tmp 19 | *~ 20 | *.VC.db* 21 | *properties.json 22 | /.vs 23 | /.vscode 24 | release 25 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libdragon"] 2 | path = libdragon 3 | url = https://github.com/DragonMinded/libdragon 4 | branch = trunk 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2017 The Altra64 project contributors 3 | # See LICENSE file in the project root for full license information. 4 | # 5 | 6 | ROOTDIR = $(N64_INST) 7 | GCCN64PREFIX = $(ROOTDIR)/bin/mips64-elf- 8 | CHKSUM64PATH = $(ROOTDIR)/bin/chksum64 9 | MKDFSPATH = $(ROOTDIR)/bin/mkdfs 10 | N64TOOL = $(ROOTDIR)/bin/n64tool 11 | 12 | HEADERNAME = header.ed64 13 | HEADERTITLE = "ED64Plus OS" 14 | 15 | SRCDIR = ./src 16 | INCDIR = ./inc 17 | RESDIR = ./res 18 | OBJDIR = ./obj 19 | BINDIR = ./bin 20 | TOOLSDIR = ./tools 21 | 22 | LINK_FLAGS = -O3 -L$(ROOTDIR)/lib -L$(ROOTDIR)/mips64-elf/lib -ldragon -lyaml -lmad -lmikmod -lc -lm -ldragonsys -lnosys $(LIBS) -Tn64ld.x 23 | PROG_NAME = OS64P 24 | CFLAGS = -std=gnu99 -march=vr4300 -mtune=vr4300 -O3 -I$(INCDIR) -I$(ROOTDIR)/include -I$(ROOTDIR)/mips64-elf/include -lpthread -lrt -D_REENTRANT -DUSE_TRUETYPE $(SET_DEBUG) 25 | ASFLAGS = -mtune=vr4300 -march=vr4300 26 | CC = $(GCCN64PREFIX)gcc 27 | AS = $(GCCN64PREFIX)as 28 | LD = $(GCCN64PREFIX)ld 29 | OBJCOPY = $(GCCN64PREFIX)objcopy 30 | 31 | SOURCES := $(wildcard $(SRCDIR)/*.c) 32 | OBJECTS = $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o) 33 | 34 | $(PROG_NAME).v64: $ $(PROG_NAME).elf $(PROG_NAME).dfs 35 | $(OBJCOPY) $(BINDIR)/$(PROG_NAME).elf $(BINDIR)/$(PROG_NAME).bin -O binary 36 | rm -f $(BINDIR)/$(PROG_NAME).v64 37 | $(N64TOOL) -l 4M -t $(HEADERTITLE) -h $(RESDIR)/$(HEADERNAME) -o $(BINDIR)/$(PROG_NAME).v64 $(BINDIR)/$(PROG_NAME).bin -s 1M $(BINDIR)/$(PROG_NAME).dfs 38 | $(CHKSUM64PATH) $(BINDIR)/$(PROG_NAME).v64 39 | 40 | $(PROG_NAME).elf : $(OBJECTS) 41 | @mkdir -p $(BINDIR) 42 | $(LD) -o $(BINDIR)/$(PROG_NAME).elf $(OBJECTS) $(LINK_FLAGS) 43 | 44 | $(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c 45 | @mkdir -p $(OBJDIR) 46 | $(CC) $(CFLAGS) -c $< -o $@ 47 | 48 | copy: $(PROG_NAME).v64 49 | sh $(TOOLSDIR)/upload.sh 50 | 51 | $(PROG_NAME).dfs: 52 | $(MKDFSPATH) $(BINDIR)/$(PROG_NAME).dfs $(RESDIR)/filesystem/ 53 | 54 | all: $(PROG_NAME).v64 55 | 56 | debug: $(PROG_NAME).v64 57 | 58 | debug: SET_DEBUG=-DDEBUG 59 | 60 | clean: 61 | rm -f $(BINDIR)/*.v64 $(BINDIR)/*.elf $(OBJDIR)/*.o $(BINDIR)/*.bin $(BINDIR)/*.dfs 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Altra64 2 | [![Build and release](https://github.com/ariahiro64/altra64/actions/workflows/build-release.yml/badge.svg)](https://github.com/ariahiro64/altra64/actions/workflows/build-release.yml) 3 | [![Build docker dev build image](https://github.com/ariahiro64/altra64/actions/workflows/docker-image.yml/badge.svg)](https://github.com/ariahiro64/altra64/actions/workflows/docker-image.yml) 4 | 5 | Alternative Everdrive64 menu 6 | 7 | `Altra64` is an open source menu for [Everdrive64](http://krikzz.com/) and ED64+
8 | Based on [a fork of alt64](https://github.com/parasyte/alt64) which was originally written by saturnu, and released on the [Everdrive64 forum](http://krikzz.com/forum/index.php?topic=816.0). 9 | 10 | ## Setup 11 | 1. Format your SD card to FAT32. 12 | 2. Extract the contents of ALTRA64.zip into the root of your SD card. 13 | 3. Change ALT64.ini to your hearts content. 14 | 4. Add legally obtained ROMs. 15 | 5. Insert the SD card into the ED64plus and enjoy! 16 | 17 | ## Controls 18 | ``` 19 | [L] - Opens MEMPAK menu 20 | [B] - Abort 21 | [A] - Backup 22 | [R] - Format 23 | [Z] - View Controller Pak 24 | [Z] - About Screen 25 | [A] - Start ROM / Open Directory / View MEMPAK 26 | [B] - Back / Cancel 27 | [START] - Start Last ROM 28 | [C-Left] - ROM Info / MEMPAK Content View 29 | [C-Right] - ROM Config Screen 30 | [C-Up] - View Full Filename 31 | [C-Down] - TOP 15 List 32 | [L+R] - Delete File 33 | ``` 34 | 35 | ## Building 36 | [Stable Releases Here](https://github.com/Suprapote/Altra64)
37 | [Automated Builds Here](https://github.com/ariahiro64/altra64/actions)
38 | [Docker Image](https://github.com/ariahiro64/altra64/pkgs/container/altra64) 39 | 40 | ```sh 41 | # Run in project root to build project: 42 | sudo docker run --rm -v "$(pwd):/build" ghcr.io/ariahiro64/altra64:master make 43 | # Output: bin/OS64P.v64 44 | ``` 45 | ``` 46 | # Run in project root to clean project from build objects: 47 | sudo docker run --rm -v "$(pwd):/build" ghcr.io/ariahiro64/altra64:master make clean 48 | ``` 49 | 50 | ### Big thanks to the countless people who make Altra64 possible!!! Enjoy! 51 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | sudo docker run --rm -v "$(pwd):/build" ghcr.io/ariahiro64/altra64:master make -------------------------------------------------------------------------------- /doc/functions.txt: -------------------------------------------------------------------------------- 1 | beta9 2 | 3 | rom loading function flow: 4 | 5 | main() 6 | 7 | //init n64, fs, controller 8 | 9 | //joypad loop 10 | //button (A) -> select rom 11 | 12 | 13 | loadrom(disp,name_file); 14 | //readout rom header 15 | //check if swapped 16 | evd_mmcSetDmaSwap(1); 17 | 18 | //dma read file to 0xb0000000 cartspace 19 | diskWriteSD(); 20 | 21 | //change key mapping 22 | 23 | //if (START) 24 | bootRom(); 25 | 26 | //save LAST.CRT for reboot cart-save 27 | 28 | //set fpga to eeprom, sram, flashram 29 | evd_setSaveType(boot_save); 30 | 31 | //do pif simulation to boot the rom 32 | simulate_boot(boot_cic, bios_cic); 33 | 34 | 35 | 36 | cart-save overview: 37 | 38 | before pif simulation the cart_id and cart_savetype is stored in 39 | LAST.CRT [maybe it's a better solution to use rom filenames 40 | 'cause the cart_id includes no game-version] 41 | -> bootRom(); 42 | 43 | at every start of the menu a function is called that checks 44 | LAST.CRT, if there is something todo and disable it for next boot 45 | by setting a flag in that file 46 | -> backupSaveData(disp); 47 | 48 | if it's a warm boot (reset) the fpga savegame is still there 49 | -> save_cfg_stat = evd_readReg(REG_SAV_CFG); 50 | 51 | if it's a reset reboot to backup a savegame into a file 52 | saveTypeToSd(disp, cartID, save_t) 53 | is called 54 | 55 | it's only for some file operations and calls 56 | utils.c: getSaveFromCart(stype, cartsave_data) 57 | to store the savegame into a buffer, which could 58 | be saved into a file 59 | 60 | 61 | some notes: 62 | eeprom is connected directly to the pif (i2c?) 63 | and could be read out stable with the libdragon function 64 | 65 | sram/flashram is a serial device that is mapped into 66 | memory 67 | it has to be accessed with dma to rdram through the pif 68 | 69 | it's a domain2 device which needs other timing than the cart 70 | 71 | timings: 72 | 73 | PI_BSD_DOM2_XXX_REG 74 | 75 | sram/fram: 76 | 77 | val XXX desc 78 | 05 LAT Latency 79 | OC PWD Pulse Width 80 | 81 | //sram - 0D 82 | //fram Animal Forest - 0F 83 | OD PGS Page Size 84 | 85 | 02 RLS Release Duration 86 | 87 | 88 | carts/dev-carts: 89 | 40 Latency 90 | 12 Pulse Width 91 | 07 Page Size 92 | 03 Release Duration 93 | 94 | IPL at 0xA6000000: 95 | 40 Latency 96 | 07 Pulse Width 97 | 07 Page Size 98 | 02 Release Duration 99 | 100 | cartidge: 101 | PI_BSD_DOM1_XXX_REG 102 | 103 | is set with the first word in the header 104 | e.g. 0x[80]371240 -> 3.7.12.40 ~ 40,12,07,03 105 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | 2 | # to build and test: 3 | # docker build -t altra64-dev . && docker run --rm -v "$(pwd):/build" -it altra64-dev 4 | 5 | # to use to compile altra64 (or other n64 stuff I guess) 6 | # docker run --rm -v "$(pwd):/build" altra64-dev make 7 | 8 | #FROM ubuntu:18.04 9 | FROM ubuntu:16.04 10 | 11 | ARG INSTALL_DEPS="wget build-essential git texinfo libc6 libgmp-dev libmpfr-dev libmpc-dev libpng-dev zlib1g-dev libtool autoconf" 12 | 13 | RUN apt-get update \ 14 | && apt-get -y upgrade \ 15 | && apt-get -y install ${INSTALL_DEPS} \ 16 | && apt-get -y autoremove \ 17 | && apt-get autoclean 18 | 19 | ENV N64_INST=/usr/local/libdragon 20 | ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/libdragon/bin 21 | 22 | RUN mkdir /build 23 | 24 | COPY setup-docker.sh /usr/bin/setup-docker.sh 25 | 26 | # run it then delete all build artifacts 27 | RUN /usr/bin/setup-docker.sh && rm -rf /root/* 28 | 29 | VOLUME [ "/build" ] 30 | 31 | WORKDIR /build 32 | 33 | CMD ["bash"] 34 | -------------------------------------------------------------------------------- /docker/setup-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (c) 2017 The Altra64 project contributors 4 | # See LICENSE file in the project root for full license information. 5 | # 6 | 7 | set -euxo pipefail 8 | 9 | # change to the users root directory 10 | cd $HOME 11 | 12 | #wget -c https://github.com/anacierdem/libdragon-docker/releases/download/v10.2.1/libdragon-linux-x86_64.tar.gz -O - | tar -xz 13 | 14 | # Pull the latest libdragon source code and make a build directory 15 | git clone https://github.com/dragonminded/libdragon.git 16 | # set to correct commit 17 | cd libdragon && git checkout --force b26fce6 && cd .. 18 | 19 | # fix issues with the build scripts 20 | sed -i -- 's|${N64_INST:-/usr/local}|/usr/local/libdragon|g' libdragon/tools/build 21 | sed -i -- 's|--with-newlib|--with-newlib --with-system-zlib|g' libdragon/tools/build 22 | 23 | sed -i -- 's| -lpng|\nLDLIBS = -lpng|g' libdragon/tools/mksprite/Makefile 24 | sed -i -- 's| -Werror| -w|g' libdragon/tools/mksprite/Makefile 25 | 26 | # make a build folder for libdragon 27 | mkdir libdragon/build_gcc 28 | cp libdragon/tools/build libdragon/build_gcc 29 | 30 | # run the build script (this will take a while! and if not sudo, will ask for password mid flow!) 31 | cd libdragon/build_gcc 32 | ./build 33 | 34 | cd .. 35 | # run the install script [sudo req] 36 | make 37 | make install 38 | make tools 39 | make tools-install 40 | 41 | cd .. 42 | # install libmikmod (custom version) 43 | git clone https://github.com/n64-tools/libmikmod 44 | cd libmikmod/n64 45 | make 46 | make install 47 | cd .. # we have are in a subfolder, this is not a duplicate... 48 | 49 | cd .. 50 | # install libyaml 51 | git clone https://github.com/yaml/libyaml 52 | cd libyaml 53 | ./bootstrap 54 | #$(N64_INST) converterd to $N64_INST below otherwise it will not run on WSFL 55 | export PATH=$PATH:$N64_INST/bin 56 | CFLAGS="-std=gnu99 -march=vr4300 -mtune=vr4300" \ 57 | LDFLAGS="-L$N64_INST/lib -Tn64ld.x" \ 58 | LIBS="-ldragon -lc -ldragonsys -lnosys" \ 59 | ./configure --host=mips64-elf --prefix=$N64_INST 60 | make 61 | make install 62 | 63 | cd .. 64 | # install libmad (custom version) 65 | git clone https://github.com/n64-tools/libmad 66 | cd libmad 67 | export PATH=$PATH:$N64_INST/bin 68 | CFLAGS="-std=gnu99 -march=vr4300 -mtune=vr4300" \ 69 | LDFLAGS="-L$N64_INST/lib -Tn64ld.x" \ 70 | LIBS="-ldragon -lc -ldragonsys -lnosys" \ 71 | ./configure --host=mips64-elf --prefix=$N64_INST 72 | make 73 | make install 74 | 75 | cd .. 76 | 77 | find /usr/local/libdragon/bin /usr/local/libdragon/mips64-elf/bin /usr/local/libdragon/libexec/gcc/mips64-elf -type f -print0 | xargs -0 strip || true 78 | -------------------------------------------------------------------------------- /inc/chksum64.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #ifndef _CHKSUM64_H 7 | #define _CHKSUM64_H 8 | 9 | void checksum_sdram(void); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /inc/cic.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright (c) 2017 The Altra64 project contributors 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _CIC_H 8 | #define _CIC_H 9 | 10 | #define CIC_6101 1 11 | #define CIC_6102 2 12 | #define CIC_6103 3 13 | #define CIC_5101 4 //aleck64 14 | //#define CIC_6104 6104 //Unused in any game so used for Aleck64 instead 15 | #define CIC_6105 5 16 | #define CIC_6106 6 17 | #define CIC_8303 7 18 | 19 | int get_cic(unsigned char *rom_data); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /inc/constants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #ifndef _CONSTANTS_H_ 7 | #define _CONSTANTS_H_ 8 | 9 | #define ED64PLUS 10 | #define MAX_SUPPORTED_PATH_LEN 256 11 | 12 | #ifdef ED64PLUS 13 | #define ED64_FIRMWARE_PATH "ED64P" 14 | #else 15 | #define ED64_FIRMWARE_PATH "ED64" 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /inc/debug.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #ifndef _DEBUG_H 7 | #define _DEBUG_H 8 | 9 | #ifdef DEBUG 10 | #define TRACEF(disp, text, ...) dbg_printf(disp, text, __VA_ARGS__); 11 | #define TRACE(disp, text) dbg_print(disp, text); 12 | #else 13 | #define TRACEF(disp, text, ...) do { if (0) dbg_printf(disp, text, __VA_ARGS__); } while (0) 14 | #define TRACE(disp, text) do { if (0) dbg_print(disp, text); } while (0) 15 | #endif 16 | 17 | void dbg_printf(display_context_t disp, const char *fmt, ...); 18 | void dbg_print(display_context_t disp, char *fmt); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /inc/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface modlue include file (C)ChaN, 2014 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #include "integer.h" 13 | 14 | 15 | /* Status of Disk Functions */ 16 | typedef BYTE DSTATUS; 17 | 18 | /* Results of Disk Functions */ 19 | typedef enum { 20 | RES_OK = 0, /* 0: Successful */ 21 | RES_ERROR, /* 1: R/W Error */ 22 | RES_WRPRT, /* 2: Write Protected */ 23 | RES_NOTRDY, /* 3: Not Ready */ 24 | RES_PARERR /* 4: Invalid Parameter */ 25 | } DRESULT; 26 | 27 | 28 | /*---------------------------------------*/ 29 | /* Prototypes for disk control functions */ 30 | 31 | 32 | DSTATUS disk_initialize (BYTE pdrv); 33 | DSTATUS disk_status (BYTE pdrv); 34 | DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); 35 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); 36 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 37 | 38 | 39 | /* Disk Status Bits (DSTATUS) */ 40 | 41 | #define STA_NOINIT 0x01 /* Drive not initialized */ 42 | #define STA_NODISK 0x02 /* No medium in the drive */ 43 | #define STA_PROTECT 0x04 /* Write protected */ 44 | 45 | 46 | /* Command code for disk_ioctrl fucntion */ 47 | 48 | /* Generic command (Used by FatFs) */ 49 | #define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ 50 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ 51 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ 52 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ 53 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ 54 | 55 | /* Generic command (Not used by FatFs) */ 56 | #define CTRL_POWER 5 /* Get/Set power status */ 57 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 58 | #define CTRL_EJECT 7 /* Eject media */ 59 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 60 | 61 | /* MMC/SDC specific ioctl command */ 62 | #define MMC_GET_TYPE 10 /* Get card type */ 63 | #define MMC_GET_CSD 11 /* Get CSD */ 64 | #define MMC_GET_CID 12 /* Get CID */ 65 | #define MMC_GET_OCR 13 /* Get OCR */ 66 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 67 | #define ISDIO_READ 55 /* Read data form SD iSDIO register */ 68 | #define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ 69 | #define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ 70 | 71 | /* ATA/CF specific ioctl command */ 72 | #define ATA_GET_REV 20 /* Get F/W revision */ 73 | #define ATA_GET_MODEL 21 /* Get model name */ 74 | #define ATA_GET_SN 22 /* Get serial number */ 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /inc/errors.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2011 KRIK 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _ERRORS_H 8 | #define _ERRORS_H 9 | 10 | 11 | #define EVD_ERROR_FIFO_TIMEOUT 90; 12 | #define EVD_ERROR_MMC_TIMEOUT 91; 13 | 14 | #define BOOT_UPD_ERR_WRONG_SIZE 95 15 | #define BOOT_UPD_ERR_HDR 96 16 | #define BOOT_UPD_ERR_CMP 97 17 | #define BOOT_UPD_ERR_CIC_DTCT 98 18 | 19 | #define FAT_ERR_NOT_EXIST 100 20 | #define FAT_ERR_EXIST 101 21 | #define FAT_ERR_NAME 102 22 | #define FAT_ERR_OUT_OF_FILE 103 23 | #define FAT_ERR_BAD_BASE_CLUSTER 104; 24 | #define FAT_ERR_NO_FRE_SPACE 105 25 | #define FAT_ERR_NOT_FILE 106 26 | #define FAT_ERR_FILE_MODE 107 27 | #define FAT_ERR_ROT_OVERFLOW 108 28 | #define FAT_ERR_OUT_OF_TABLE 109 29 | #define FAT_ERR_INIT 110 30 | #define FAT_LFN_BUFF_OVERFLOW 111 31 | #define FAT_DISK_NOT_READY 112 32 | #define FAT_ERR_SIZE 113 33 | #define FAT_ERR_RESIZE 114 34 | 35 | #define ERR_FILE8_TOO_BIG 140 36 | #define ERR_FILE16_TOO_BIG 141 37 | #define ERR_WRON_OS_SIZE 142 38 | #define ERR_OS_VERIFY 143 39 | #define ERR_OS_VERIFY2 144 40 | #define ERR_EMU_NOT_FOUND 145 41 | #define ERR_SAVE_FORMAT 146 42 | #define ERR_EEPROM 147 43 | #define ERR_NO_FAV_SPACE 150 44 | 45 | 46 | 47 | #define DISK_ERR_INIT 50 48 | 49 | #define DISK_ERR_RD1 62 50 | #define DISK_ERR_RD2 63 51 | 52 | #define DISK_ERR_WR1 64 53 | #define DISK_ERR_WR2 65 54 | #define DISK_ERR_WR3 66 55 | #define DISK_ERR_WRX 67 56 | #define DISK_WR_SB_TOUT 68 57 | #define DISK_ERR_WR_CRC 69 58 | 59 | #define DISK_RD_FE_TOUT 70 60 | #define DISK_ERR_CLOSE_RW1 71 61 | #define DISK_ERR_CLOSE_RW2 72 62 | 63 | #define SD_CMD_TIMEOUT 75 64 | #define SD_CMD_CRC_ERROR 76 65 | 66 | #define SD_INIT_ERROR 80 67 | 68 | 69 | #endif /* _ERRORS_H */ 70 | -------------------------------------------------------------------------------- /inc/everdrive.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2011 KRIK 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _EVERDRIVE_H 8 | #define _EVERDRIVE_H 9 | 10 | #include "types.h" 11 | 12 | #define OS_VER "1.29" 13 | 14 | #define ROM_LEN 0x4000000 15 | #define ROM_ADDR 0xb0000000 16 | #define ROM_END_ADDR (0xb0000000 + 0x4000000) 17 | 18 | 19 | #define SAVE_TYPE_OFF 0 20 | #define SAVE_TYPE_SRAM 1 21 | #define SAVE_TYPE_SRAM128 2 22 | #define SAVE_TYPE_EEP4k 3 23 | #define SAVE_TYPE_EEP16k 4 24 | #define SAVE_TYPE_FLASH 5 25 | #define SAVE_TYPE_SRAM768 6 26 | #define DMA_BUFF_ADDR (ROM_LEN - 0x100000) 27 | 28 | #define REG_CFG 0 29 | #define REG_STATUS 1 30 | #define REG_DMA_LEN 2 31 | #define REG_DMA_RAM_ADDR 3 32 | #define REG_MSG 4 33 | #define REG_DMA_CFG 5 34 | #define REG_SPI 6 35 | #define REG_SPI_CFG 7 36 | #define REG_KEY 8 37 | #define REG_SAV_CFG 9 38 | #define REG_SEC 10 39 | #define REG_VER 11 40 | 41 | 42 | #define REG_CFG_CNT 16 43 | #define REG_CFG_DAT 17 44 | #define REG_MAX_MSG 18 45 | #define REG_CRC 19 46 | 47 | 48 | #define DCFG_SD_TO_RAM 1 49 | #define DCFG_RAM_TO_SD 2 50 | #define DCFG_FIFO_TO_RAM 3 51 | #define DCFG_RAM_TO_FIFO 4 52 | 53 | #define ED_CFG_SDRAM_ON 0 54 | #define ED_CFG_SWAP 1 55 | #define ED_CFG_WR_MOD 2 56 | #define ED_CFG_WR_ADDR_MASK 3 57 | 58 | //new firmware load 59 | #define REGS_BASE 0xA8040000 60 | //-- 61 | 62 | void evd_setCfgBit(u8 option, u8 state); 63 | 64 | void evd_init(); 65 | u8 evd_fifoRxf(); 66 | u8 evd_fifoTxe(); 67 | u8 evd_isDmaBusy(); 68 | u8 evd_isDmaTimeout(); 69 | u8 evd_fifoRd(void *buff, u16 blocks); 70 | u8 evd_fifoWr(void *buff, u16 blocks); 71 | u8 evd_fifoRdToCart(u32 cart_addr, u16 blocks); 72 | u8 evd_fifoWrFromCart(u32 cart_addr, u16 blocks); 73 | 74 | u8 evd_SPI(u8 dat); 75 | void evd_mmcSetDmaSwap(u8 state); 76 | u8 evd_mmcReadToCart(u32 cart_addr, u32 len); 77 | 78 | void evd_ulockRegs(void); 79 | void evd_lockRegs(); 80 | u16 evd_readReg(u8 reg); 81 | void evd_writeReg(u8 reg, u16 val); 82 | void evd_setSaveType(u8 type); 83 | 84 | 85 | u8 romLoadSettingsFromSD(); 86 | u8 romSaveInfoToLog(); 87 | void evd_writeMsg(u8 dat); 88 | u8 evd_readMsg(); 89 | u16 evd_getFirmVersion(); 90 | 91 | void evd_spiSSOn(); 92 | void evd_spiSSOff(); 93 | u8 evd_isSpiBusy(); 94 | void evd_setSpiSpeed(u8 speed); 95 | 96 | void evd_SDcmdWriteMode(u8 bit1_mode); 97 | void evd_SDcmdReadMode(u8 bit1_mode); 98 | void evd_SDdatWriteMode(u8 bit4_mode); 99 | void evd_SDdatReadMode(u8 bit4_mode); 100 | void evd_enableSDMode(); 101 | void evd_enableSPIMode(); 102 | u8 evd_isSDMode(); 103 | void evd_setDmaCallback(void (*callback)()); 104 | 105 | 106 | //firmware upload 107 | extern u32 bi_reg_rd(u32 reg); 108 | extern void bi_reg_wr(u32 reg, u32 data); 109 | void bi_init(); 110 | void bi_load_firmware(u8 *firm); 111 | void bi_speed25(); 112 | void bi_speed50(); 113 | 114 | /* 115 | u8 evd_mmcWriteNextBlock(void *dat); 116 | u8 evd_mmcOpenWrite(u32 addr); 117 | u8 evd_mmcWriteBlock(void *dat, u32 addr); 118 | u8 evd_mmcInit(); 119 | u8 evd_mmcReadBlock(void *dat, u32 addr); 120 | u8 evd_mmcOpenRead(u32 addr); 121 | u8 evd_mmcReadNextBlock(void *dat); 122 | void evd_mmcCloseRW(); 123 | */ 124 | 125 | 126 | #endif /* _EVERDRIVE_H */ 127 | -------------------------------------------------------------------------------- /inc/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 1 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 0 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 0 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 0 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 1000 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 | -------------------------------------------------------------------------------- /inc/font_patch/info.txt: -------------------------------------------------------------------------------- 1 | libdragon: include/font.h -------------------------------------------------------------------------------- /inc/hashtable.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2011 @marekweb https://github.com/marekweb/datastructs-c 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _HASHTABLE_H 8 | #define _HASHTABLE_H 9 | 10 | typedef struct hashtable hashtable; 11 | void hashtable_destroy(hashtable *t); 12 | typedef struct hashtable_entry hashtable_entry; 13 | hashtable_entry *hashtable_body_allocate(unsigned int capacity); 14 | hashtable *hashtable_create(); 15 | void hashtable_remove(hashtable *t,char *key); 16 | void hashtable_resize(hashtable *t,unsigned int capacity); 17 | void hashtable_set(hashtable *t,char *key,void *value); 18 | void *hashtable_get(hashtable *t,char *key); 19 | unsigned int hashtable_find_slot(hashtable *t,char *key); 20 | unsigned long hashtable_hash(char *str); 21 | struct hashtable { 22 | unsigned int size; 23 | unsigned int capacity; 24 | hashtable_entry* body; 25 | }; 26 | struct hashtable_entry { 27 | char* key; 28 | void* value; 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /inc/image.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #ifndef _IMAGE_H 7 | #define _IMAGE_H 8 | 9 | sprite_t *loadImage32DFS(char *fname); 10 | sprite_t *loadImageDFS(char *fname); 11 | sprite_t *loadImage32(u8 *tbuf, int size); 12 | void drawImage(display_context_t dcon, sprite_t *sprite); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /inc/ini.h: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 | home page for more info: 5 | 6 | http://code.google.com/p/inih/ 7 | 8 | */ 9 | 10 | #ifndef __INI_H__ 11 | #define __INI_H__ 12 | 13 | /* Make this header file easier to include in C++ code */ 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | /* Parse given INI-style file. May have [section]s, name=value pairs 21 | (whitespace stripped), and comments starting with ';' (semicolon). Section 22 | is "" if name=value pair parsed before any section heading. name:value 23 | pairs are also supported as a concession to Python's ConfigParser. 24 | 25 | For each name=value pair parsed, call handler function with given user 26 | pointer as well as section, name, and value (data only valid for duration 27 | of handler call). Handler should return nonzero on success, zero on error. 28 | 29 | Returns 0 on success, line number of first error on parse error (doesn't 30 | stop on first error), -1 on file open error, or -2 on memory allocation 31 | error (only when INI_USE_STACK is zero). 32 | */ 33 | int ini_parse(const char* filename, 34 | int (*handler)(void* user, const char* section, 35 | const char* name, const char* value), 36 | void* user); 37 | 38 | /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't 39 | close the file when it's finished -- the caller must do that. */ 40 | int ini_parse_file(FILE* file, 41 | int (*handler)(void* user, const char* section, 42 | const char* name, const char* value), 43 | void* user); 44 | 45 | int ini_parse_str(char* ini_string, 46 | int (*handler)(void*, const char*, const char*, 47 | const char*), 48 | void* user); 49 | 50 | /* Nonzero to allow multi-line value parsing, in the style of Python's 51 | ConfigParser. If allowed, ini_parse() will call the handler with the same 52 | name for each subsequent line parsed. */ 53 | #ifndef INI_ALLOW_MULTILINE 54 | #define INI_ALLOW_MULTILINE 1 55 | #endif 56 | 57 | /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of 58 | the file. See http://code.google.com/p/inih/issues/detail?id=21 */ 59 | #ifndef INI_ALLOW_BOM 60 | #define INI_ALLOW_BOM 1 61 | #endif 62 | 63 | /* Nonzero to use stack, zero to use heap (malloc/free). */ 64 | #ifndef INI_USE_STACK 65 | #define INI_USE_STACK 1 66 | #endif 67 | 68 | /* Maximum line length for any line in INI file. */ 69 | #ifndef INI_MAX_LINE 70 | #define INI_MAX_LINE 200 71 | #endif 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif /* __INI_H__ */ 78 | -------------------------------------------------------------------------------- /inc/integer.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------*/ 2 | /* Integer type definitions for FatFs module */ 3 | /*-------------------------------------------*/ 4 | 5 | #ifndef FF_INTEGER 6 | #define FF_INTEGER 7 | 8 | #ifdef _WIN32 /* FatFs development platform */ 9 | 10 | #include 11 | #include 12 | typedef unsigned __int64 QWORD; 13 | 14 | 15 | #else /* Embedded platform */ 16 | 17 | /* These types MUST be 16-bit or 32-bit */ 18 | typedef int INT; 19 | typedef unsigned int UINT; 20 | 21 | /* This type MUST be 8-bit */ 22 | typedef unsigned char BYTE; 23 | 24 | /* These types MUST be 16-bit */ 25 | typedef short SHORT; 26 | typedef unsigned short WORD; 27 | typedef unsigned short WCHAR; 28 | 29 | /* These types MUST be 32-bit */ 30 | typedef long LONG; 31 | typedef unsigned long DWORD; 32 | 33 | /* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */ 34 | typedef unsigned long long QWORD; 35 | 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /inc/localevar.h: -------------------------------------------------------------------------------- 1 | //language 2 | char *dirempty; 3 | char *fnddb; 4 | char *done; 5 | char *romloaded; 6 | char *loadgb; 7 | char *loading; 8 | char *plgmp3; 9 | char *savemem; 10 | char *save32; 11 | char *save128; 12 | char *save768; 13 | char *save4k; 14 | char *save16k; 15 | char *saveflash; 16 | char *OpComsucc; 17 | char *mpksub; 18 | char *viewcont; 19 | char *viewmpk; 20 | char *backnew; 21 | char *formatt; 22 | char *abortmen; 23 | char *restoreback; 24 | char *confreq; 25 | char *aresure; 26 | char *cupcont; 27 | char *cancelmenu; 28 | char *romconfig; 29 | char *updatelastgamerecord; 30 | char *ramarea2sd; 31 | char *cpyingram2SD; 32 | char *transfersavedat; 33 | char *tvforceoff; 34 | char *cheatoff; 35 | char *cheaton; 36 | char *checksumenable; 37 | char *checksumdisable; 38 | char *presstart; 39 | char *reallyformatrpak; 40 | char *searchfds; 41 | char *formating; 42 | char *mpkformat; 43 | char *plswait; 44 | char *errorformating; 45 | char *ratoff; 46 | char *ratcomo; 47 | char *ratuncomo; 48 | char *ratrare; 49 | char *ratepic; 50 | char *ratlegend; 51 | char *bcancel; 52 | char *countrydef; 53 | char *countryntsc; 54 | char *countrypal; 55 | char *Asaveconf; 56 | char *directoriesNO; 57 | char *bexit; 58 | char *deletefile; 59 | char *aconfirm; 60 | char *znpage; 61 | char *fcontents; 62 | char *freebock; 63 | char *freespace; 64 | char *blocks; 65 | char *emptyfile; 66 | char *filexist; 67 | char *overridefile; 68 | char *fileMPK; 69 | char *backupdone; 70 | char *sizeMB; 71 | char *savetypeinf; 72 | char *mpkbackup; 73 | char *mpkrestore; 74 | char *quickback; 75 | char *cheatnofound; 76 | char *parsingfail; 77 | char *resetconsol; 78 | char *cheatfound; 79 | char *emunofound; 80 | char *controlsmenucon; 81 | char *showmpkmenu; 82 | char *aboutscreen; 83 | char *Astartromdirectory; 84 | char *Amempak; 85 | char *Bbackcancel; 86 | char *Startlastrom; 87 | char *CLEFT; 88 | char *CLEFTVIEMPK; 89 | char *CRIGHT; 90 | char *CUP; 91 | char *CDOWN; 92 | char *LplusR; 93 | char *errornoready; 94 | char *filenoexist; 95 | char *pathnoexist; 96 | char *invalidname; 97 | char *operdenied; 98 | char *filealrrexist; 99 | char *errtimeout; 100 | char *devicelocked; 101 | char *orparsingfailed; 102 | char *done3p; 103 | char *readystr; 104 | char *cheatsysact; 105 | char *cupactcheat; 106 | char *crightv; 107 | char *donepresstart; 108 | char *filopenerror; 109 | char *nosavfund; 110 | char *trssavedata; 111 | char *errtrssavedata; 112 | char *errsavSD; 113 | char *errsavSDnocrfile; 114 | char *trloadchfile; 115 | char *chsfund; 116 | char *forcetvmd; -------------------------------------------------------------------------------- /inc/main.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | #ifndef MAIN_H 7 | #define MAIN_H 8 | 9 | //TODO: these should probably be static not protos in main 10 | void bootRom(display_context_t disp, int silent); 11 | void loadrom(display_context_t disp, u8 *buff, int fast); 12 | 13 | void HideSysvolumeinfo(char* fname); 14 | 15 | int showThisFolder(int hide_sysfolder, char* fname); 16 | 17 | void readSDcard(display_context_t disp, char *directory); 18 | int saveTypeToSd(display_context_t disp, char* save_filename ,int type); 19 | 20 | void drawShortInfoBox(display_context_t disp, char* text, u8 mode); 21 | void drawTextInput(display_context_t disp,char *msg); 22 | 23 | //#define ishexchar(c) (((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f'))) 24 | 25 | /** 26 | * @brief Return the uncached memory address of a cached address 27 | * 28 | * @param[in] x 29 | * The cached address 30 | *uint32_t 31 | * @return The uncached address 32 | */ 33 | //#define UNCACHED_ADDR(x) ((void *)(((uint32_t)(x)) | 0xA0000000)) 34 | 35 | /** 36 | * @brief Align a memory address to 16 byte offset 37 | * 38 | * @param[in] x 39 | * Unaligned memory address 40 | * 41 | * @return An aligned address guaranteed to be >= the unaligned address 42 | */ 43 | //#define ALIGN_16BYTE(x) ((void *)(((uint32_t)(x)+15) & 0xFFFFFFF0)) 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /inc/mem.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2011 KRIK 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _MEM_H 8 | #define _MEM_H 9 | 10 | #define SPI_SPEED_INIT 2 11 | #define SPI_SPEED_25 1 12 | #define SPI_SPEED_50 0 13 | 14 | #define mem_spi evd_SPI 15 | #define memSpiSetSpeed evd_setSpiSpeed 16 | #define memSpiIsBusy evd_isSpiBusy 17 | #define memSpiSSOff evd_spiSSOff 18 | #define memSpiSSOn evd_spiSSOn 19 | 20 | 21 | void memSpiSSOn(); 22 | void memSpiSSOff(); 23 | void memSpiBusy(); 24 | u8 memSpiIsBusy(); 25 | void memSpiSetSpeed(u8 speed); 26 | void spiReadBlock(void *dat); 27 | void spiWriteBlock(void *dat); 28 | u8 memSpiRead(void *dst, u16 slen); 29 | u8 memSpiWrite(const void *src); 30 | //u8 mem_spi(u8 dat); 31 | void memfill(void *dst, u8 val, u16 len); 32 | void memcopy(void *src, void *dst, u16 len); 33 | void memSpiSetDma(u8 mode); 34 | void memRomWrite32(u32 addr, u32 val); 35 | u32 memRomRead32(u32 addr); 36 | 37 | #endif /* _MEM_H */ -------------------------------------------------------------------------------- /inc/memorypak.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #ifndef _MEMORYPAK_H 7 | #define _MEMORYPAK_H 8 | 9 | //TODO: not sure if this is correct!!! 10 | extern char *mempak_path; 11 | 12 | int file_to_mpk(display_context_t disp, u8 *filename); 13 | void mpk_to_file(display_context_t disp, char *mpk_filename, int quick); 14 | void view_mpk_file(display_context_t disp, char *mpk_filename); 15 | void view_mpk(display_context_t disp); 16 | 17 | #endif -------------------------------------------------------------------------------- /inc/mempak.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mempak.h 3 | * @brief Mempak Filesystem Routines 4 | * @ingroup mempak 5 | */ 6 | #ifndef __LIBDRAGON_MEMPAK_H 7 | #define __LIBDRAGON_MEMPAK_H 8 | 9 | /** 10 | * @addtogroup mempak 11 | * @{ 12 | */ 13 | 14 | /** @brief Size in bytes of a Mempak block */ 15 | #define MEMPAK_BLOCK_SIZE 256 16 | 17 | /** 18 | * @brief Structure representing a save entry in a mempak 19 | */ 20 | typedef struct entry_structure 21 | { 22 | /** @brief Vendor ID */ 23 | uint32_t vendor; 24 | /** @brief Game ID */ 25 | uint16_t game_id; 26 | /** @brief Inode pointer */ 27 | uint16_t inode; 28 | /** @brief Intended region */ 29 | uint8_t region; 30 | /** @brief Number of blocks used by this entry. 31 | * @see MEMPAK_BLOCK_SIZE */ 32 | uint8_t blocks; 33 | /** @brief Validity of this entry. */ 34 | uint8_t valid; 35 | /** @brief ID of this entry */ 36 | uint8_t entry_id; 37 | /** 38 | * @brief Name of this entry 39 | * 40 | * The complete list of valid ASCII characters in a note name is: 41 | * 42 | *
43 |      * ABCDEFGHIJKLMNOPQRSTUVWXYZ!"#`*+,-./:=?\@
44 |      * 
45 | * 46 | * The space character is also allowed. Any other character will be 47 | * converted to a space before writing to the mempak. 48 | */ 49 | char name[19]; 50 | } entry_structure_t; 51 | 52 | #ifdef __cplusplus 53 | extern "C" { 54 | #endif 55 | 56 | int read_mempak_sector( int controller, int sector, uint8_t *sector_data ); 57 | int write_mempak_sector( int controller, int sector, uint8_t *sector_data ); 58 | int validate_mempak( int controller ); 59 | int get_mempak_free_space( int controller ); 60 | int get_mempak_entry( int controller, int entry, entry_structure_t *entry_data ); 61 | int format_mempak( int controller ); 62 | int read_mempak_entry_data( int controller, entry_structure_t *entry, uint8_t *data ); 63 | int write_mempak_entry_data( int controller, entry_structure_t *entry, uint8_t *data ); 64 | int delete_mempak_entry( int controller, entry_structure_t *entry ); 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | 70 | /** @} */ /* mempak */ 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /inc/menu.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #ifndef _MENU_H_ 7 | #define _MENU_H_ 8 | 9 | extern int text_offset; 10 | 11 | void printText(char *msg, int x, int y, display_context_t dcon); 12 | 13 | void menu_about(display_context_t disp); 14 | void menu_controls(display_context_t disp); 15 | void menu_delete(display_context_t disp, bool isdir); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /inc/mp3.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _MP3_H_ 8 | #define _MP3_H_ 9 | 10 | void mp3_Start(char *fname, long long *samples, int *rate, int *channels); 11 | void mp3_Stop(void); 12 | int mp3_Update(char *buf, int bytes); 13 | 14 | #endif // _MP3_H_ 15 | -------------------------------------------------------------------------------- /inc/regsinternal.h: -------------------------------------------------------------------------------- 1 | //TODO: this file is actually part of the libdragon source and should be included from there!!! 2 | 3 | /** 4 | * @file regsinternal.h 5 | * @brief Register definitions for various hardware in the N64 6 | * @ingroup lowlevel 7 | */ 8 | #ifndef __LIBDRAGON_REGSINTERNAL_H 9 | #define __LIBDRAGON_REGSINTERNAL_H 10 | 11 | /** 12 | * @defgroup lowlevel Low Level Hardware Interfaces 13 | * @ingroup libdragon 14 | * @brief Low level hardware interface descriptions and functionality 15 | * 16 | * The low level hardware interfaces handle several functions in the N64 that 17 | * would otherwise be handled by a kernel or RTOS. This includes the @ref dma, 18 | * the @ref exceptions, the @ref interrupt and the @ref n64sys. The DMA controller 19 | * handles DMA requests between the cartridge and the N64 RDRAM. Other systems 20 | * in the N64 have their own DMA controllers that are handled in the relevant 21 | * subsystems. The exception handler traps any exceptions raised by the N64, 22 | * including the reset exception. The interrupt handler sets up the MIPS 23 | * interface (MI) which handles low level interrupt functionality for all other 24 | * systems in the N64. The N64 system interface provides the ability for code to 25 | * manipulate cache and boot options. 26 | */ 27 | 28 | /** 29 | * @brief Register definition for the AI interface 30 | * @ingroup lowlevel 31 | */ 32 | typedef struct AI_regs_s { 33 | /** @brief Pointer to uncached memory buffer of samples to play */ 34 | volatile void * address; 35 | /** @brief Size in bytes of the buffer to be played. Should be 36 | * number of stereo samples * 2 * sizeof( uint16_t ) 37 | */ 38 | uint32_t length; 39 | /** @brief DMA start register. Write a 1 to this register to start 40 | * playing back an audio sample. */ 41 | uint32_t control; 42 | /** @brief AI status register. Bit 31 is the full bit, bit 30 is the busy bit. */ 43 | uint32_t status; 44 | /** @brief Rate at which the buffer should be played. 45 | * 46 | * Use the following formula to calculate the value: ((2 * clockrate / frequency) + 1) / 2 - 1 47 | */ 48 | uint32_t dacrate; 49 | /** @brief The size of a single sample in bits. */ 50 | uint32_t samplesize; 51 | } AI_regs_t; 52 | 53 | /** 54 | * @brief Register definition for the MI interface 55 | * @ingroup lowlevel 56 | */ 57 | typedef struct MI_regs_s { 58 | /** @brief Mode register */ 59 | uint32_t mode; 60 | /** @brief Version register */ 61 | uint32_t version; 62 | /** @brief Current interrupts on the system */ 63 | uint32_t intr; 64 | /** @brief Interrupt mask */ 65 | uint32_t mask; 66 | } MI_regs_t; 67 | 68 | /** 69 | * @brief Register definition for the VI interface 70 | * @ingroup lowlevel 71 | */ 72 | typedef struct VI_regs_s { 73 | /** @brief VI control register. Sets up various rasterization modes */ 74 | uint32_t control; 75 | /** @brief Pointer to uncached buffer in memory to rasterize */ 76 | void * framebuffer; 77 | /** @brief Width of the buffer in pixels */ 78 | uint32_t width; 79 | /** @brief Vertical interrupt control register. Controls which horizontal 80 | * line must be hit to generate a VI interrupt 81 | */ 82 | uint32_t v_int; 83 | /** @brief Current vertical line counter. */ 84 | uint32_t cur_line; 85 | /** @brief Timing generation register for PAL/NTSC signals */ 86 | uint32_t timing; 87 | /** @brief Number of lines per frame */ 88 | uint32_t v_sync; 89 | /** @brief Number of pixels in line and leap pattern */ 90 | uint32_t h_sync; 91 | /** @brief Number of pixels in line, set identically to h_sync */ 92 | uint32_t h_sync2; 93 | /** @brief Beginning and end of video horizontally */ 94 | uint32_t h_limits; 95 | /** @brief Beginning and end of video vertically */ 96 | uint32_t v_limits; 97 | /** @brief Beginning and end of color burst in vertical lines */ 98 | uint32_t color_burst; 99 | /** @brief Horizontal scaling factor from buffer to screen */ 100 | uint32_t h_scale; 101 | /** @brief Vertical scaling factor from buffer to screen */ 102 | uint32_t v_scale; 103 | } VI_regs_t; 104 | 105 | /** 106 | * @brief Register definition for the PI interface 107 | * @ingroup lowlevel 108 | */ 109 | typedef struct PI_regs_s { 110 | /** @brief Uncached address in RAM where data should be found */ 111 | volatile void * ram_address; 112 | /** @brief Address of data on peripheral */ 113 | uint32_t pi_address; 114 | /** @brief How much data to read from RAM into the peripheral */ 115 | uint32_t read_length; 116 | /** @brief How much data to write to RAM from the peripheral */ 117 | uint32_t write_length; 118 | /** @brief Status of the PI, including DMA busy */ 119 | uint32_t status; 120 | } PI_regs_t; 121 | 122 | /** 123 | * @brief Register definition for the SI interface 124 | * @ingroup lowlevel 125 | */ 126 | typedef struct SI_regs_s { 127 | /** @brief Uncached address in RAM where data should be found */ 128 | volatile void * DRAM_addr; 129 | /** @brief Address to read when copying from PIF RAM */ 130 | volatile void * PIF_addr_read; 131 | /** @brief Reserved word */ 132 | uint32_t reserved1; 133 | /** @brief Reserved word */ 134 | uint32_t reserved2; 135 | /** @brief Address to write when copying to PIF RAM */ 136 | volatile void * PIF_addr_write; 137 | /** @brief Reserved word */ 138 | uint32_t reserved3; 139 | /** @brief SI status, including DMA busy and IO busy */ 140 | uint32_t status; 141 | } SI_regs_t; 142 | 143 | /** 144 | * @brief Register definition for the SP interface 145 | * @ingroup lowlevel 146 | */ 147 | typedef struct SP_regs_s { 148 | /** @brief RSP memory address (IMEM/DMEM) */ 149 | volatile void * RSP_addr; 150 | /** @brief RDRAM memory address */ 151 | volatile void * RDAM_addr; 152 | /** @brief RDRAM->RSP DMA length */ 153 | uint32_t rsp_read_length; 154 | /** @brief RDP->RDRAM DMA length */ 155 | uint32_t rsp_write_length; 156 | /** @brief RSP status */ 157 | uint32_t status; 158 | /** @brief RSP DMA full */ 159 | uint32_t rsp_dma_full; 160 | /** @brief RSP DMA busy */ 161 | uint32_t rsp_dma_busy; 162 | /** @brief RSP Semaphore */ 163 | uint32_t rsp_semaphore; 164 | } SP_regs_t; 165 | 166 | #endif -------------------------------------------------------------------------------- /inc/rom.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _ROM_H 8 | #define _ROM_H 9 | 10 | /* 11 | * 12 | 0000h (1 byte): initial PI_BSB_DOM1_LAT_REG value (0x80) 13 | 0001h (1 byte): initial PI_BSB_DOM1_PGS_REG value (0x37) 14 | 0002h (1 byte): initial PI_BSB_DOM1_PWD_REG value (0x12) 15 | 0003h (1 byte): initial PI_BSB_DOM1_PGS_REG value (0x40) 16 | 0004h - 0007h (1 dword): ClockRate 17 | 0008h - 000Bh (1 dword): Program Counter (PC) 18 | 000Ch - 000Fh (1 dword): Release 19 | 0010h - 0013h (1 dword): CRC1 20 | 0014h - 0017h (1 dword): CRC2 21 | 0018h - 001Fh (2 dwords): Unknown (0x0000000000000000) 22 | 0020h - 0033h (20 bytes): Image name 23 | Padded with 0x00 or spaces (0x20) 24 | 0034h - 0037h (1 dword): Unknown (0x00000000) 25 | 0038h - 003Bh (1 dword): Manufacturer ID 26 | 0x0000004E = Nintendo ('N') 27 | 003Ch - 003Dh (1 word): Cartridge ID 28 | 003Eh - 003Fh (1 word): Country code 29 | 0x4400 = Germany ('D') 30 | 0x4500 = USA ('E') 31 | 0x4A00 = Japan ('J') 32 | 0x5000 = Europe ('P') 33 | 0x5500 = Australia ('U') 34 | 0040h - 0FFFh (1008 dwords): Boot code 35 | */ 36 | 37 | #define DP_BASE_REG 0x04100000 38 | #define VI_BASE_REG 0x04400000 39 | #define PI_BASE_REG 0x04600000 40 | #define PIF_RAM_START 0x1FC007C0 41 | 42 | 43 | /* 44 | * PI status register has 3 bits active when read from (PI_STATUS_REG - read) 45 | * Bit 0: DMA busy - set when DMA is in progress 46 | * Bit 1: IO busy - set when IO is in progress 47 | * Bit 2: Error - set when CPU issues IO request while DMA is busy 48 | */ 49 | 50 | #define PI_STATUS_REG (PI_BASE_REG+0x10) 51 | 52 | /* PI DRAM address (R/W): starting RDRAM address */ 53 | #define PI_DRAM_ADDR_REG (PI_BASE_REG+0x00) /* DRAM address */ 54 | 55 | /* PI pbus (cartridge) address (R/W): starting AD16 address */ 56 | #define PI_CART_ADDR_REG (PI_BASE_REG+0x04) 57 | 58 | /* PI read length (R/W): read data length */ 59 | #define PI_RD_LEN_REG (PI_BASE_REG+0x08) 60 | 61 | /* PI write length (R/W): write data length */ 62 | #define PI_WR_LEN_REG (PI_BASE_REG+0x0C) 63 | 64 | /* 65 | * PI status (R): [0] DMA busy, [1] IO busy, [2], error 66 | * (W): [0] reset controller (and abort current op), [1] clear intr 67 | */ 68 | 69 | #define PI_BSD_DOM1_LAT_REG (PI_BASE_REG+0x14) 70 | 71 | /* PI dom1 pulse width (R/W): [7:0] domain 1 device R/W strobe pulse width */ 72 | #define PI_BSD_DOM1_PWD_REG (PI_BASE_REG+0x18) 73 | 74 | /* PI dom1 page size (R/W): [3:0] domain 1 device page size */ 75 | #define PI_BSD_DOM1_PGS_REG (PI_BASE_REG+0x1C) /* page size */ 76 | 77 | /* PI dom1 release (R/W): [1:0] domain 1 device R/W release duration */ 78 | #define PI_BSD_DOM1_RLS_REG (PI_BASE_REG+0x20) 79 | /* PI dom2 latency (R/W): [7:0] domain 2 device latency */ 80 | #define PI_BSD_DOM2_LAT_REG (PI_BASE_REG+0x24) /* Domain 2 latency */ 81 | 82 | /* PI dom2 pulse width (R/W): [7:0] domain 2 device R/W strobe pulse width */ 83 | #define PI_BSD_DOM2_PWD_REG (PI_BASE_REG+0x28) /* pulse width */ 84 | 85 | /* PI dom2 page size (R/W): [3:0] domain 2 device page size */ 86 | #define PI_BSD_DOM2_PGS_REG (PI_BASE_REG+0x2C) /* page size */ 87 | 88 | /* PI dom2 release (R/W): [1:0] domain 2 device R/W release duration */ 89 | #define PI_BSD_DOM2_RLS_REG (PI_BASE_REG+0x30) /* release duration */ 90 | 91 | 92 | #define PI_DOMAIN1_REG PI_BSD_DOM1_LAT_REG 93 | #define PI_DOMAIN2_REG PI_BSD_DOM2_LAT_REG 94 | 95 | 96 | #define PI_STATUS_ERROR 0x04 97 | #define PI_STATUS_IO_BUSY 0x02 98 | #define PI_STATUS_DMA_BUSY 0x01 99 | 100 | #define DPC_START (DP_BASE_REG + 0x00) 101 | #define DPC_END (DP_BASE_REG + 0x04) 102 | #define DPC_CURRENT (DP_BASE_REG + 0x08) 103 | #define DPC_STATUS (DP_BASE_REG + 0x0C) 104 | #define DPC_CLOCK (DP_BASE_REG + 0x10) 105 | #define DPC_BUFBUSY (DP_BASE_REG + 0x14) 106 | #define DPC_PIPEBUSY (DP_BASE_REG + 0x18) 107 | #define DPC_TMEM (DP_BASE_REG + 0x1C) 108 | 109 | #define VI_CONTROL (VI_BASE_REG + 0x00) 110 | #define VI_FRAMEBUFFER (VI_BASE_REG + 0x04) 111 | #define VI_WIDTH (VI_BASE_REG + 0x08) 112 | #define VI_V_INT (VI_BASE_REG + 0x0C) 113 | #define VI_CUR_LINE (VI_BASE_REG + 0x10) 114 | #define VI_TIMING (VI_BASE_REG + 0x14) 115 | #define VI_V_SYNC (VI_BASE_REG + 0x18) 116 | #define VI_H_SYNC (VI_BASE_REG + 0x1C) 117 | #define VI_H_SYNC2 (VI_BASE_REG + 0x20) 118 | #define VI_H_LIMITS (VI_BASE_REG + 0x24) 119 | #define VI_COLOR_BURST (VI_BASE_REG + 0x28) 120 | #define VI_H_SCALE (VI_BASE_REG + 0x2C) 121 | #define VI_VSCALE (VI_BASE_REG + 0x30) 122 | 123 | #define PHYS_TO_K0(x) ((u32)(x)|0x80000000) /* physical to kseg0 */ 124 | #define K0_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) /* kseg0 to physical */ 125 | #define PHYS_TO_K1(x) ((u32)(x)|0xA0000000) /* physical to kseg1 */ 126 | #define K1_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) /* kseg1 to physical */ 127 | 128 | #define IO_READ(addr) (*(volatile u32*)PHYS_TO_K1(addr)) 129 | #define IO_WRITE(addr,data) (*(volatile u32*)PHYS_TO_K1(addr)=(u32)(data)) 130 | 131 | #define SAVE_SIZE_SRAM 32768 132 | #define SAVE_SIZE_SRAM128 131072 133 | #define SAVE_SIZE_SRAM768 98304 134 | #define SAVE_SIZE_EEP4k 512 135 | #define SAVE_SIZE_EEP16k 2048 136 | #define SAVE_SIZE_FLASH 131072 137 | 138 | #define ROM_ADDR 0xb0000000 139 | 140 | 141 | #define FRAM_EXECUTE_CMD 0xD2000000 142 | #define FRAM_STATUS_MODE_CMD 0xE1000000 143 | #define FRAM_ERASE_OFFSET_CMD 0x4B000000 144 | #define FRAM_WRITE_OFFSET_CMD 0xA5000000 145 | #define FRAM_ERASE_MODE_CMD 0x78000000 146 | #define FRAM_WRITE_MODE_CMD 0xB4000000 147 | #define FRAM_READ_MODE_CMD 0xF0000000 148 | 149 | #define FRAM_STATUS_REG 0xA8000000 150 | #define FRAM_COMMAND_REG 0xA8010000 151 | 152 | //see also utils.c 153 | #define REGION_UNKNOWN 0 //leave auto/off 154 | #define REGION_NTSC 1 155 | #define REGION_PAL 2 156 | #define REGION_PAL_M 3 157 | 158 | 159 | 160 | //void romFill(...); 161 | void pif_boot(); 162 | 163 | int is_valid_rom(unsigned char *buffer); 164 | void swap_header(unsigned char* header, int loadlength); 165 | 166 | u8 getCicType(u8 bios_cic); 167 | 168 | void send_game_id(uint8_t* crc_hi, uint8_t* crc_lo, uint8_t media_format, uint8_t country_id); 169 | void get_country_and_region(unsigned char ccode, char* region_string); 170 | unsigned char get_region(unsigned char ccode); 171 | #endif 172 | -------------------------------------------------------------------------------- /inc/sd.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2011 KRIK 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _SD_H 8 | #define _SD_H 9 | 10 | #include "types.h" 11 | 12 | u8 sdGetInterface(); 13 | u8 sdInit(); 14 | u8 sdRead(u32 sector, u8 *buff, u16 count); 15 | u8 sdWrite(u32 sector, const u8 *buff, u16 count); 16 | 17 | void sdSetInterface(u32 interface); 18 | 19 | 20 | 21 | #define WAIT 1024 22 | 23 | #define DISK_IFACE_SPI 0 24 | #define DISK_IFACE_SD 1 25 | 26 | 27 | #endif /* _SD_H */ 28 | -------------------------------------------------------------------------------- /inc/sound.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | #ifndef _SOUND_H 6 | #define _SOUND_H 7 | 8 | void sndInit(void); 9 | void sndPlayBGM(char* filename); 10 | void sndStopAll(void); 11 | void sndPlaySFX(char* filename); 12 | void sndUpdate(void); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /inc/sram.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _SRAM_H 8 | #define _SRAM_H 9 | 10 | #include 11 | #include "types.h" 12 | 13 | void data_cache_hit_writeback_invalidate(volatile void *, unsigned long); 14 | void dma_write_sram(void* src, u32 offset, u32 size); 15 | void dma_read_sram(void *dest, u32 offset, u32 size); 16 | void dma_write_s(void * ram_address, unsigned long pi_address, unsigned long len); 17 | void dma_read_s(void * ram_address, unsigned long pi_address, unsigned long len); 18 | int writeSram(void* src, u32 size); 19 | void setSDTiming(void); 20 | 21 | 22 | void PI_Init(void); 23 | void PI_Init_SRAM(void); 24 | void PI_DMAWait(void); 25 | void PI_DMAFromCart(void* dest, void* src, u32 size); 26 | void PI_DMAToCart(void* dest, void* src, u32 size); 27 | void PI_DMAFromSRAM(void *dest, u32 offset, u32 size); 28 | void PI_DMAToSRAM(void* src, u32 offset, u32 size); 29 | void PI_SafeDMAFromCart(void *dest, void *src, u32 size); 30 | 31 | //memory 32 | /*** MEMORY ***/ 33 | void *safe_memalign(size_t boundary, size_t size); 34 | void *safe_calloc(size_t nmemb, size_t size); 35 | void *safe_malloc(size_t size); 36 | void safe_free(void *ptr); 37 | void *safe_memset(void *s, int c, size_t n); 38 | void *safe_memcpy(void *dest, const void *src, size_t n); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /inc/strlib.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _STRLIB_H 8 | #define _STRLIB_H 9 | 10 | #include "types.h" 11 | 12 | enum strtrim_mode_t { 13 | STRLIB_MODE_ALL = 0, 14 | STRLIB_MODE_RIGHT = 0x01, 15 | STRLIB_MODE_LEFT = 0x02, 16 | STRLIB_MODE_BOTH = 0x03 17 | }; 18 | 19 | char *strcpytrim(char *d, // destination 20 | char *s, // source 21 | int mode, 22 | char *delim 23 | ); 24 | 25 | char *strtriml(char *d, char *s); 26 | char *strtrimr(char *d, char *s); 27 | char *strtrim(char *d, char *s); 28 | char *strstrlibkill(char *d, char *s); 29 | 30 | char *triml(char *s); 31 | char *trimr(char *s); 32 | char *trim(char *s); 33 | char *strlibkill(char *s); 34 | 35 | void strhicase(u8 *str, u8 len); 36 | u16 strcon(u8 *str1, u8 *str2, u8 *dst, u16 max_len); 37 | u8 slen(u8 *str); 38 | u8 scopy(u8 *src, u8 *dst); 39 | 40 | u8 streq(u8 *str1, u8 *str2); 41 | u8 streql(u8 *str1, u8 *str2, u8 len); 42 | 43 | u16 strContain(u8 *target, u8 *str); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /inc/sys.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2011 KRIK 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _SYS_H 8 | #define _SYS_H 9 | 10 | #include "types.h" 11 | 12 | 13 | void dma_read_s(void * ram_address, unsigned long pi_address, unsigned long len); 14 | void dma_write_s(void * ram_address, unsigned long pi_address, unsigned long len); 15 | 16 | 17 | void sleep(u32 ms); 18 | void dma_write_sram(void* src, u32 offset, u32 size); 19 | void dma_read_sram(void *dest, u32 offset, u32 size); 20 | u8 getSaveType(); 21 | 22 | 23 | typedef struct SP_regs_s { 24 | u32 mem_addr; 25 | u32 dram_addr; 26 | u32 rd_len; 27 | u32 wr_len; 28 | u32 status; 29 | } _SP_regs_s; 30 | 31 | #define SP_PC *((volatile u32 *)0xA4080000) 32 | #define SP_IBIST_REG *((volatile u32 *)0xA4080004) 33 | 34 | static volatile struct AI_regs_s * const AI_regs = (struct AI_regs_s *) 0xa4500000; 35 | static volatile struct MI_regs_s * const MI_regs = (struct MI_regs_s *) 0xa4300000; 36 | static volatile struct VI_regs_s * const VI_regs = (struct VI_regs_s *) 0xa4400000; 37 | static volatile struct PI_regs_s * const PI_regs = (struct PI_regs_s *) 0xa4600000; 38 | static volatile struct SP_regs_s * const SP_regs = (struct SP_regs_s *) 0xA4040000; 39 | 40 | extern u32 native_tv_mode; 41 | 42 | typedef struct { 43 | u16 sd_speed; 44 | u16 font_size; 45 | u16 tv_mode; 46 | u8 wall[256]; 47 | } Options_st; 48 | 49 | 50 | extern Options_st options; 51 | extern u32 asm_date; 52 | 53 | #endif /* _SYS_H */ 54 | -------------------------------------------------------------------------------- /inc/types.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2011 KRIK 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _TYPES_H 8 | #define _TYPES_H 9 | 10 | #include 11 | 12 | #define u8 unsigned char 13 | #define u16 unsigned short 14 | #define u32 unsigned long 15 | #define u64 unsigned long long 16 | 17 | #define vu8 volatile unsigned char 18 | #define vu16 volatile unsigned short 19 | #define vu32 volatile unsigned long 20 | #define vu64 volatile unsigned long long 21 | 22 | #define s8 signed char 23 | #define s16 short 24 | #define s32 long 25 | #define s64 long long 26 | 27 | 28 | typedef volatile uint64_t sim_vu64; 29 | typedef volatile uint64_t sim_vu64; 30 | typedef unsigned int sim_u32; 31 | typedef uint64_t sim_u64; 32 | 33 | 34 | #endif /* _TYPES_H */ 35 | 36 | -------------------------------------------------------------------------------- /inc/usb.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2011 KRIK 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #ifndef _USB_H 8 | #define _USB_H 9 | 10 | //#include "types.h" 11 | u8 usbListener(); 12 | 13 | 14 | #endif /* _USB_H */ 15 | -------------------------------------------------------------------------------- /inc/utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | 8 | #ifndef _UTILS_H 9 | #define _UTILS_H 10 | 11 | #if !defined(MIN) 12 | #define MIN(a, b) ({ \ 13 | __typeof__ (a) _a = (a); \ 14 | __typeof__ (b) _b = (b); \ 15 | _a < _b ? _a : _b; \ 16 | }) 17 | #endif 18 | 19 | #if !defined(MAX) 20 | #define MAX(a, b) ({ \ 21 | __typeof__ (a) _a = (a); \ 22 | __typeof__ (b) _b = (b); \ 23 | _a > _b ? _a : _b; \ 24 | }) 25 | #endif 26 | 27 | 28 | void _sync_bus(void); 29 | void _data_cache_invalidate_all(void); 30 | 31 | // End ... 32 | 33 | 34 | void restoreTiming(void); 35 | 36 | void simulate_boot(u32 boot_cic, u8 bios_cic, u32 *cheat_list[2]); 37 | 38 | 39 | int get_cic_save(char *cartid, int *cic, int *save); 40 | //const char* saveTypeToExtension(int type); 41 | const char* saveTypeToExtension(int type, int etype); 42 | int saveTypeToSize(int type); 43 | int getSaveFromCart(int stype, uint8_t *buffer); 44 | int pushSaveToCart(int stype, uint8_t *buffer); 45 | 46 | int getSRAM( uint8_t *buffer,int size); 47 | int getSRAM32( uint8_t *buffer); 48 | int getSRAM128( uint8_t *buffer); 49 | int getSRAM768( uint8_t *buffer); 50 | int getEeprom4k( uint8_t *buffer); 51 | int getEeprom16k( uint8_t *buffer); 52 | int getFlashRAM( uint8_t *buffer); 53 | 54 | int setSRAM(uint8_t *buffer,int size); 55 | int setSRAM32( uint8_t *buffer); 56 | int setSRAM128( uint8_t *buffer); 57 | int setSRAM768( uint8_t *buffer); 58 | int setEeprom4k( uint8_t *buffer); 59 | int setEeprom16k( uint8_t *buffer); 60 | int setFlashRAM( uint8_t *buffer); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /inc/version.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #ifndef _VERSION_H 7 | #define _VERSION_H 8 | 9 | const char* Altra64_GetVersionString(void); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /res/ALTRA64.INI: -------------------------------------------------------------------------------- 1 | ; alt64 config file 2 | 3 | [ed64] ; Menu config 4 | build=18 ; Release build nr 5 | border_color_1=FFFFFFFF ; 0x00000080 RGBT 6 | border_color_2=FFFFFFFF ; 0x3F3F3FFF RGBT 00000060 w light 7 | box_color=000000B6 ; 0x00000080 RGBT 8 | selection_color=80008070 ; 80008070 RGBT 6495ED60 9 | list_font_color=CDC9C940 ; 80008070 RGBT 6495ED60 10 | list_dir_font_color=FFFFE040 ; 80008070 RGBT 6495ED60 11 | selection_font_color=FFB90FFF ; 80008070 RGBT 6495ED60 12 | text_offset=0 ; shift menu horizontal e.g. -1 13 | cd_behaviour=1 ; 0=first entry 1=last entry 14 | scroll_behaviour=0 ; 0=page-system 1=classic 15 | quick_boot=1 ; 'START' boots last rom 16 | bgm_on=0 17 | sound_on=1 ; sounds 1=on 0=off 18 | page_display=1 ; display page 19 | tv_mode=0 ; 1=ntsc 2=pal 3=mpal 0=force_off 20 | enable_colored_list=1 ; 1=enable 0=disalbe 21 | ext_type=1 ; 0=classic 1=OS64 22 | sd_speed=2 ; 1=25MHz 2=50MHz 23 | background_image=bgr2.png ; backgrund png image 320x240 32bit 24 | hide_sysfolder=0 ; 1=hide 0=don't hide 25 | mempak_path=/ED64P/MEMPAKS/ ; surround with slashes 26 | save_path=SDSAVE ; save directory inside ED64P 27 | language=1 ;0=ENG 1=ES 2=FR 28 | show_splash=0 ;show splash 29 | splash_image= ;splash image 30 | save_backup=0 ; 31 | 32 | [user] 33 | name = saturnu ; Username -------------------------------------------------------------------------------- /res/WALLPAPER/bg.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/WALLPAPER/bg.bmp -------------------------------------------------------------------------------- /res/emulators/UltraSMS.z64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/emulators/UltraSMS.z64 -------------------------------------------------------------------------------- /res/emulators/gb.v64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/emulators/gb.v64 -------------------------------------------------------------------------------- /res/emulators/neon64bu.rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/emulators/neon64bu.rom -------------------------------------------------------------------------------- /res/emulators/ultraMSX2.z64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/emulators/ultraMSX2.z64 -------------------------------------------------------------------------------- /res/filesystem/sounds/bamboo.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/bamboo.wav -------------------------------------------------------------------------------- /res/filesystem/sounds/bgm21.it: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/bgm21.it -------------------------------------------------------------------------------- /res/filesystem/sounds/boot.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/boot.wav -------------------------------------------------------------------------------- /res/filesystem/sounds/done.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/done.wav -------------------------------------------------------------------------------- /res/filesystem/sounds/doned.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/doned.wav -------------------------------------------------------------------------------- /res/filesystem/sounds/ed64_mono.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/ed64_mono.wav -------------------------------------------------------------------------------- /res/filesystem/sounds/warning.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/warning.wav -------------------------------------------------------------------------------- /res/filesystem/sprites/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/background.png -------------------------------------------------------------------------------- /res/filesystem/sprites/background.sprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/background.sprite -------------------------------------------------------------------------------- /res/filesystem/sprites/n64controller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/n64controller.png -------------------------------------------------------------------------------- /res/filesystem/sprites/n64controller.sprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/n64controller.sprite -------------------------------------------------------------------------------- /res/filesystem/sprites/old/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/background.png -------------------------------------------------------------------------------- /res/filesystem/sprites/old/background.sprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/background.sprite -------------------------------------------------------------------------------- /res/filesystem/sprites/old/n64controller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/n64controller.png -------------------------------------------------------------------------------- /res/filesystem/sprites/old/n64controller.sprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/n64controller.sprite -------------------------------------------------------------------------------- /res/filesystem/sprites/old/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/splash.png -------------------------------------------------------------------------------- /res/filesystem/sprites/old/splash.sprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/splash.sprite -------------------------------------------------------------------------------- /res/filesystem/sprites/splash.sprite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/splash.sprite -------------------------------------------------------------------------------- /res/header.ed64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/header.ed64 -------------------------------------------------------------------------------- /src/chksum64.c: -------------------------------------------------------------------------------- 1 | /* 2 | checksum rom in psram, based on 3 | 4 | chksum64 V1.2, a program to calculate the ROM checksum of Nintendo64 ROMs. 5 | Copyright (C) 1997 Andreas Sterbenz (stan@sbox.tu-graz.ac.at) 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 20 | */ 21 | 22 | #include 23 | 24 | #include "sys.h" 25 | #include "chksum64.h" 26 | 27 | 28 | #define BUFSIZE 0x8000 29 | #define SDRAM_START 0xb0000000 30 | 31 | #define CHECKSUM_START 0x1000 32 | #define CHECKSUM_LENGTH 0x100000L 33 | #define CHECKSUM_HEADERPOS 0x10 34 | #define CHECKSUM_END (CHECKSUM_START + CHECKSUM_LENGTH) 35 | 36 | #define CHECKSUM_STARTVALUE 0xf8ca4ddc 37 | 38 | #define ROL(i, b) (((i)<<(b)) | ((i)>>(32-(b)))) 39 | 40 | #define BYTES2LONG(b) ( (((b)[0] & 0xffL) << 24) | \ 41 | (((b)[1] & 0xffL) << 16) | \ 42 | (((b)[2] & 0xffL) << 8) | \ 43 | (((b)[3] & 0xffL)) ) 44 | 45 | #define LONG2BYTES(l, b) (b)[0] = ((l)>>24)&0xff; \ 46 | (b)[1] = ((l)>>16)&0xff; \ 47 | (b)[2] = ((l)>> 8)&0xff; \ 48 | (b)[3] = ((l) )&0xff; 49 | 50 | 51 | static unsigned char __attribute__((aligned(16))) buffer1[BUFSIZE]; 52 | 53 | 54 | void checksum_sdram(void) 55 | { 56 | unsigned int sum1, sum2, offs; 57 | 58 | { 59 | unsigned int i; 60 | unsigned int c1, k1, k2; 61 | unsigned int t1, t2, t3, t4; 62 | unsigned int t5, t6; 63 | unsigned int n; 64 | unsigned int clen = CHECKSUM_LENGTH; 65 | 66 | t1 = CHECKSUM_STARTVALUE; 67 | t2 = CHECKSUM_STARTVALUE; 68 | t3 = CHECKSUM_STARTVALUE; 69 | t4 = CHECKSUM_STARTVALUE; 70 | t5 = CHECKSUM_STARTVALUE; 71 | t6 = CHECKSUM_STARTVALUE; 72 | 73 | offs = CHECKSUM_START; 74 | 75 | for( ;; ) { 76 | n = (BUFSIZE < clen) ? BUFSIZE : clen; 77 | dma_read_s(buffer1, SDRAM_START+offs, n); 78 | data_cache_hit_writeback_invalidate(buffer1,n); 79 | 80 | offs += n; 81 | 82 | for( i=0; i 14 | #include 15 | #include 16 | #include 17 | #include "regsinternal.h" 18 | #include "cic.h" 19 | #include "types.h" 20 | #include "rom.h" //TODO: perhaps the pifram defines should be global 21 | 22 | 23 | 24 | // CIC seeds and status bits passed from PIF to IPL through PIF RAM 25 | // Bits | Description 26 | // 00080000 | ROM type (0 = Game Pack, 1 = DD) 27 | // 00040000 | Version 28 | // 00020000 | Reset Type (0 = cold reset, 1 = NMI) 29 | // 0000FF00 | CIC IPL3 seed value 30 | // 000000FF | CIC IPL2 seed value 31 | // #define CIC_SEED_NUS_5101 0x0000AC00U 32 | // #define CIC_SEED_NUS_6101 0x00043F3FU 33 | // #define CIC_SEED_NUS_6102 0x00003F3FU 34 | // #define CIC_SEED_NUS_6103 0x0000783FU 35 | // #define CIC_SEED_NUS_6105 0x0000913FU 36 | // #define CIC_SEED_NUS_6106 0x0000853FU 37 | // #define CIC_SEED_NUS_8303 0x0000DD00U 38 | 39 | #define CRC_NUS_5101 0x587BD543U 40 | #define CRC_NUS_6101 0x6170A4A1U 41 | #define CRC_NUS_7102 0x009E9EA3U 42 | #define CRC_NUS_6102 0x90BB6CB5U 43 | #define CRC_NUS_6103 0x0B050EE0U 44 | #define CRC_NUS_6105 0x98BC2C86U 45 | #define CRC_NUS_6106 0xACC8580AU 46 | #define CRC_NUS_8303 0x0E018159U 47 | 48 | static uint32_t si_crc32(const uint8_t *data, size_t size); 49 | 50 | // Determines the CIC seed for a cart, given the ROM data. 51 | //int get_cic_seed(const uint8_t *rom_data, uint32_t *cic_seed) { 52 | int get_cic(unsigned char *rom_data) { 53 | uint32_t crc = si_crc32(rom_data + 0x40, 0x1000 - 0x40); 54 | uint32_t aleck64crc = si_crc32(rom_data + 0x40, 0xC00 - 0x40); 55 | 56 | if (aleck64crc == CRC_NUS_5101) 57 | return 4;//*cic_seed = CIC_SEED_NUS_5101; 58 | else 59 | { 60 | switch (crc) { 61 | case CRC_NUS_6101: 62 | case CRC_NUS_7102: 63 | //*cic_seed = CIC_SEED_NUS_6101; 64 | return 1; 65 | break; 66 | 67 | case CRC_NUS_6102: 68 | //*cic_seed = CIC_SEED_NUS_6102; 69 | return 2; 70 | break; 71 | 72 | case CRC_NUS_6103: 73 | //*cic_seed = CIC_SEED_NUS_6103; 74 | return 3; 75 | break; 76 | 77 | case CRC_NUS_6105: 78 | //*cic_seed = CIC_SEED_NUS_6105; 79 | return 5; 80 | break; 81 | 82 | case CRC_NUS_6106: 83 | //*cic_seed = CIC_SEED_NUS_6106; 84 | return 6; 85 | break; 86 | 87 | case CRC_NUS_8303: //not sure if this is necessary as we are using cart conversions 88 | //cic_seed = CIC_SEED_NUS_8303; 89 | return 7; 90 | break; 91 | 92 | default: 93 | break; 94 | } 95 | } 96 | return 2; 97 | } 98 | 99 | uint32_t si_crc32(const uint8_t *data, size_t size) { 100 | uint32_t table[256]; 101 | unsigned n, k; 102 | uint32_t c; 103 | 104 | for (n = 0; n < 256; n++) { 105 | c = (uint32_t) n; 106 | 107 | for (k = 0; k < 8; k++) { 108 | if (c & 1) 109 | c = 0xEDB88320L ^ (c >> 1); 110 | else 111 | c = c >> 1; 112 | } 113 | 114 | table[n] = c; 115 | } 116 | 117 | c = 0L ^ 0xFFFFFFFF; 118 | 119 | for (n = 0; n < size; n++) 120 | c = table[(c ^ data[n]) & 0xFF] ^ (c >> 8); 121 | 122 | return c ^ 0xFFFFFFFF; 123 | } 124 | 125 | static volatile struct SI_regs_s * const SI_regs = (struct SI_regs_s *) 0xa4800000; 126 | static void * const PIF_RAM = (void *) 0x1fc007c0; 127 | 128 | /** @brief SI DMA busy */ 129 | #define SI_STATUS_DMA_BUSY ( 1 << 0 ) 130 | /** @brief SI IO busy */ 131 | #define SI_STATUS_IO_BUSY ( 1 << 1 ) 132 | 133 | static void __SI_DMA_wait(void) { 134 | while (SI_regs->status & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)); 135 | } 136 | 137 | static void __controller_exec_PIF(void *inblock, void *outblock) { 138 | volatile uint64_t inblock_temp[8]; 139 | volatile uint64_t outblock_temp[8]; 140 | 141 | data_cache_hit_writeback_invalidate(inblock_temp, 64); 142 | memcpy(UncachedAddr(inblock_temp), inblock, 64); 143 | 144 | /* Be sure another thread doesn't get into a resource fight */ 145 | disable_interrupts(); 146 | 147 | __SI_DMA_wait(); 148 | 149 | SI_regs->DRAM_addr = inblock_temp; // only cares about 23:0 150 | MEMORY_BARRIER(); 151 | SI_regs->PIF_addr_write = PIF_RAM; // is it really ever anything else? 152 | MEMORY_BARRIER(); 153 | 154 | __SI_DMA_wait(); 155 | 156 | data_cache_hit_writeback_invalidate(outblock_temp, 64); 157 | 158 | SI_regs->DRAM_addr = outblock_temp; 159 | MEMORY_BARRIER(); 160 | SI_regs->PIF_addr_read = PIF_RAM; 161 | MEMORY_BARRIER(); 162 | 163 | __SI_DMA_wait(); 164 | 165 | /* Now that we've copied, its safe to let other threads go */ 166 | enable_interrupts(); 167 | 168 | memcpy(outblock, UncachedAddr(outblock_temp), 64); 169 | } 170 | 171 | int pifram_x105_response_test() { 172 | 173 | static unsigned long long SI_eeprom_read_block[8] = { 174 | 0xFFFFFFFFFFFFFFFF, 175 | 0xFFFFFFFFFFFFFFFF, 176 | 0xFFFFFFFFFFFFFFFF, 177 | 0xFFFFFFFFFFFFFFFF, 178 | 0xFFFFFFFFFFFFFFFF, 179 | 0xFFFFFFFFFFFF0F0F, 180 | 0x8B00620018000600, 181 | 0x0100C000B0000002 //0x3f=02 182 | 183 | }; 184 | static unsigned long long output[8]; 185 | 186 | __controller_exec_PIF(SI_eeprom_read_block,output); 187 | 188 | /* 189 | expected result 190 | FF FF FF FF FF FF FF FF 191 | FF FF FF FF FF FF FF FF 192 | FF FF FF FF FF FF FF FF 193 | FF FF FF FF FF FF FF FF 194 | FF FF FF FF FF FF FF FF 195 | FF FF FF FF FF FF 00 00 196 | 3E C6 C0 4E BD 37 15 55 197 | 5A 8C 2A 8C D3 71 71 00 198 | */ 199 | 200 | /* We are looking for 0x55 in [6], which 201 | * signifies that there is an x105 present.*/ 202 | 203 | if( (output[6] & 0xFF) == 0x55 ) 204 | { 205 | //x105 found! 206 | return 1; 207 | 208 | } else { 209 | //x105 not found! 210 | return 0; 211 | 212 | } 213 | 214 | } -------------------------------------------------------------------------------- /src/debug.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "types.h" 5 | #include "debug.h" 6 | #include "menu.h" 7 | #include "sys.h" 8 | 9 | void dbg_printf(display_context_t disp, const char *fmt, ...) 10 | { 11 | char buf[256] = {0}; 12 | setbuf(stderr, buf); 13 | 14 | va_list args; 15 | va_start(args, fmt); 16 | vfprintf(stderr, fmt, args); 17 | va_end(args); 18 | 19 | u8 tmp[256] = {0}; 20 | sprintf(tmp, "%s", buf); 21 | printText(tmp, 3, -1, disp); 22 | display_show(disp); 23 | sleep(3000); 24 | } 25 | 26 | 27 | void dbg_print(display_context_t disp, char *fmt) 28 | { 29 | printText(fmt, 3, -1, disp); 30 | display_show(disp); 31 | sleep(3000); 32 | } -------------------------------------------------------------------------------- /src/diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ 3 | /*-----------------------------------------------------------------------*/ 4 | /* If a working storage control module is available, it should be */ 5 | /* attached to the FatFs via a glue function rather than modifying it. */ 6 | /* This is an example of glue functions to attach various exsisting */ 7 | /* storage control modules to the FatFs module with a defined API. */ 8 | /*-----------------------------------------------------------------------*/ 9 | 10 | #include "diskio.h" /* FatFs lower layer API */ 11 | #include "sd.h" 12 | 13 | /* Definitions of physical drive number for each drive */ 14 | #define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */ 15 | #define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */ 16 | #define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */ 17 | 18 | 19 | /*-----------------------------------------------------------------------*/ 20 | /* Get Drive Status */ 21 | /*-----------------------------------------------------------------------*/ 22 | 23 | DSTATUS disk_status ( 24 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 25 | ) 26 | { 27 | DSTATUS stat; 28 | // int result; 29 | 30 | // switch (pdrv) { 31 | // case DEV_RAM : 32 | // result = RAM_disk_status(); 33 | 34 | // // translate the reslut code here 35 | 36 | // return stat; 37 | 38 | // case DEV_MMC : 39 | // result = MMC_disk_status(); 40 | 41 | // // translate the reslut code here 42 | 43 | // return stat; 44 | 45 | // case DEV_USB : 46 | // result = USB_disk_status(); 47 | 48 | // // translate the reslut code here 49 | 50 | // return stat; 51 | // } 52 | // return STA_NOINIT; 53 | 54 | if(pdrv) 55 | { 56 | return STA_NOINIT; 57 | } 58 | return RES_OK; 59 | } 60 | 61 | 62 | 63 | /*-----------------------------------------------------------------------*/ 64 | /* Initialize a Drive */ 65 | /*-----------------------------------------------------------------------*/ 66 | 67 | DSTATUS disk_initialize ( 68 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 69 | ) 70 | { 71 | DSTATUS stat; 72 | int result; 73 | 74 | // switch (pdrv) { 75 | // case DEV_RAM : 76 | // result = RAM_disk_initialize(); 77 | 78 | // // translate the reslut code here 79 | 80 | // return stat; 81 | 82 | // case DEV_MMC : 83 | // result = MMC_disk_initialize(); 84 | 85 | // // translate the reslut code here 86 | 87 | // return stat; 88 | 89 | // case DEV_USB : 90 | // result = USB_disk_initialize(); 91 | 92 | // // translate the reslut code here 93 | 94 | // return stat; 95 | // } 96 | 97 | stat=sdInit(); //SD card initialization 98 | 99 | if(stat == STA_NODISK) 100 | { 101 | return STA_NODISK; 102 | } 103 | else if(stat != 0) 104 | { 105 | return STA_NOINIT; 106 | } 107 | else 108 | { 109 | return 0; 110 | } 111 | 112 | return STA_NOINIT; 113 | } 114 | 115 | 116 | 117 | /*-----------------------------------------------------------------------*/ 118 | /* Read Sector(s) */ 119 | /*-----------------------------------------------------------------------*/ 120 | 121 | DRESULT disk_read ( 122 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 123 | BYTE *buff, /* Data buffer to store read data */ 124 | DWORD sector, /* Start sector in LBA */ 125 | UINT count /* Number of sectors to read */ 126 | ) 127 | { 128 | DRESULT res; 129 | // int result; 130 | 131 | // switch (pdrv) { 132 | // case DEV_RAM : 133 | // // translate the arguments here 134 | 135 | // result = RAM_disk_read(buff, sector, count); 136 | 137 | // // translate the reslut code here 138 | 139 | // return res; 140 | 141 | // case DEV_MMC : 142 | // // translate the arguments here 143 | 144 | // result = MMC_disk_read(buff, sector, count); 145 | 146 | // // translate the reslut code here 147 | 148 | // return res; 149 | 150 | // case DEV_USB : 151 | // // translate the arguments here 152 | 153 | // result = USB_disk_read(buff, sector, count); 154 | 155 | // // translate the reslut code here 156 | 157 | // return res; 158 | // } 159 | 160 | // return RES_PARERR; 161 | 162 | if (pdrv || !count) 163 | { 164 | return RES_PARERR; 165 | } 166 | 167 | res = sdRead(sector, buff, count); 168 | 169 | if(res == 0x00) 170 | { 171 | return RES_OK; 172 | } 173 | else 174 | { 175 | return RES_ERROR; 176 | } 177 | } 178 | 179 | 180 | 181 | /*-----------------------------------------------------------------------*/ 182 | /* Write Sector(s) */ 183 | /*-----------------------------------------------------------------------*/ 184 | 185 | DRESULT disk_write ( 186 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 187 | const BYTE *buff, /* Data to be written */ 188 | DWORD sector, /* Start sector in LBA */ 189 | UINT count /* Number of sectors to write */ 190 | ) 191 | { 192 | DRESULT res; 193 | // int result; 194 | 195 | // switch (pdrv) { 196 | // case DEV_RAM : 197 | // // translate the arguments here 198 | 199 | // result = RAM_disk_write(buff, sector, count); 200 | 201 | // // translate the reslut code here 202 | 203 | // return res; 204 | 205 | // case DEV_MMC : 206 | // // translate the arguments here 207 | 208 | // result = MMC_disk_write(buff, sector, count); 209 | 210 | // // translate the reslut code here 211 | 212 | // return res; 213 | 214 | // case DEV_USB : 215 | // // translate the arguments here 216 | 217 | // result = USB_disk_write(buff, sector, count); 218 | 219 | // // translate the reslut code here 220 | 221 | // return res; 222 | // } 223 | 224 | //return RES_PARERR; 225 | 226 | if (pdrv || !count) 227 | { 228 | return RES_PARERR; 229 | } 230 | 231 | res = sdWrite(sector, buff, count); 232 | 233 | if(res == 0) 234 | { 235 | return RES_OK; 236 | } 237 | else 238 | { 239 | return RES_ERROR; 240 | } 241 | } 242 | 243 | 244 | 245 | /*-----------------------------------------------------------------------*/ 246 | /* Miscellaneous Functions */ 247 | /*-----------------------------------------------------------------------*/ 248 | 249 | DRESULT disk_ioctl ( 250 | BYTE pdrv, /* Physical drive nmuber (0..) */ 251 | BYTE cmd, /* Control code */ 252 | void *buff /* Buffer to send/receive control data */ 253 | ) 254 | { 255 | DRESULT res; 256 | // int result; 257 | 258 | // switch (pdrv) { 259 | // case DEV_RAM : 260 | 261 | // // Process of the command for the RAM drive 262 | 263 | // return res; 264 | 265 | // case DEV_MMC : 266 | 267 | // // Process of the command for the MMC/SD card 268 | 269 | // return res; 270 | 271 | // case DEV_USB : 272 | 273 | // // Process of the command the USB drive 274 | 275 | // return res; 276 | // } 277 | 278 | switch (cmd) { 279 | case CTRL_SYNC: 280 | return RES_OK; 281 | case GET_SECTOR_SIZE: 282 | *(WORD*)buff = 512; 283 | return RES_OK; 284 | case GET_SECTOR_COUNT: 285 | //*(DWORD*)buff = sdGetSectors(); 286 | return RES_OK; 287 | case GET_BLOCK_SIZE: 288 | //*(DWORD*)buff = sdGetBlockSize(); 289 | return RES_OK; 290 | } 291 | 292 | return RES_PARERR; 293 | } 294 | 295 | DWORD get_fattime (void) 296 | { 297 | //TODO: can we use the V3 RTC? 298 | return 0; 299 | } 300 | 301 | -------------------------------------------------------------------------------- /src/everdrive.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #include "everdrive.h" 8 | #include "sys.h" 9 | #include "errors.h" 10 | 11 | #define CMD0 0x40 // software reset 12 | #define CMD1 0x41 // brings card out of idle state 13 | #define CMD2 0x42 // not used in SPI mode 14 | #define CMD3 0x43 // not used in SPI mode 15 | #define CMD4 0x44 // not used in SPI mode 16 | #define CMD5 0x45 // Reserved 17 | #define CMD6 0x46 // Reserved 18 | #define CMD7 0x47 // not used in SPI mode 19 | #define CMD8 0x48 // Reserved 20 | #define CMD9 0x49 // ask card to send card speficic data (CSD) 21 | #define CMD10 0x4A // ask card to send card identification (CID) 22 | #define CMD11 0x4B // not used in SPI mode 23 | #define CMD12 0x4C // stop transmission on multiple block read 24 | #define CMD13 0x4D // ask the card to send it's status register 25 | #define CMD14 0x4E // Reserved 26 | #define CMD15 0x4F // not used in SPI mode 27 | #define CMD16 0x50 // sets the block length used by the memory card 28 | #define CMD17 0x51 // read single block 29 | #define CMD18 0x52 // read multiple block 30 | #define CMD19 0x53 // Reserved 31 | #define CMD20 0x54 // not used in SPI mode 32 | #define CMD21 0x55 // Reserved 33 | #define CMD22 0x56 // Reserved 34 | #define CMD23 0x57 // Reserved 35 | #define CMD24 0x58 // writes a single block 36 | #define CMD25 0x59 // writes multiple blocks 37 | #define CMD26 0x5A // not used in SPI mode 38 | #define CMD27 0x5B // change the bits in CSD 39 | #define CMD28 0x5C // sets the write protection bit 40 | #define CMD29 0x5D // clears the write protection bit 41 | #define CMD30 0x5E // checks the write protection bit 42 | #define CMD31 0x5F // Reserved 43 | #define CMD32 0x60 // Sets the address of the first sector of the erase group 44 | #define CMD33 0x61 // Sets the address of the last sector of the erase group 45 | #define CMD34 0x62 // removes a sector from the selected group 46 | #define CMD35 0x63 // Sets the address of the first group 47 | #define CMD36 0x64 // Sets the address of the last erase group 48 | #define CMD37 0x65 // removes a group from the selected section 49 | #define CMD38 0x66 // erase all selected groups 50 | #define CMD39 0x67 // not used in SPI mode 51 | #define CMD40 0x68 // not used in SPI mode 52 | #define CMD41 0x69 // Reserved 53 | #define CMD42 0x6A // locks a block 54 | // CMD43 ... CMD57 are Reserved 55 | #define CMD58 0x7A // reads the OCR register 56 | #define CMD59 0x7B // turns CRC off 57 | // CMD60 ... CMD63 are not used in SPI mode 58 | 59 | 60 | 61 | 62 | 63 | 64 | #define ED_STATE_DMA_BUSY 0 65 | #define ED_STATE_DMA_TOUT 1 66 | #define ED_STATE_TXE 2 67 | #define ED_STATE_RXF 3 68 | #define ED_STATE_SPI 4 69 | 70 | #define SPI_CFG_SPD0 0 71 | #define SPI_CFG_SPD1 1 72 | #define SPI_CFG_SS 2 73 | #define SPI_CFG_RD 3 74 | #define SPI_CFG_DAT 4 75 | #define SPI_CFG_1BIT 5 76 | 77 | #define SAV_EEP_ON 0 78 | #define SAV_SRM_ON 1 79 | #define SAV_EEP_SIZE 2 80 | #define SAV_SRM_SIZE 3 81 | 82 | //was missing 83 | //#define BI_SPI_SPD_LO 0 84 | 85 | #define BI_SPI_SPD_LO 2 // around 200khz (only for sd initialization) 86 | #define BI_SPI_SPD_25 1 87 | #define BI_SPI_SPD_50 0 88 | 89 | 90 | void evd_setSpiSpeed(u8 speed); 91 | u8 evd_mmcCmd(u8 cmd, u32 arg); 92 | 93 | u8 sd_mode; 94 | volatile u8 spi_cfg; 95 | volatile u8 evd_cfg; 96 | u8 sd_type; 97 | volatile u32 *regs_ptr = (u32 *) 0xA8040000; 98 | 99 | /* 100 | result[2] <= ad[15:8] == {ad[6], ad[1], ad[0], ad[7], ad[5], ad[4], ad[3], ad[2]} ^ 8'h37 ^ prv[7:0]; 101 | prv[7:0] <= ad[15:8]; 102 | */ 103 | void (*dma_busy_callback)(); 104 | 105 | 106 | void evd_setDmaAddr(u32 addr) { 107 | 108 | } 109 | 110 | 111 | inline u32 bi_reg_rd(u32 reg) { 112 | 113 | *(vu32 *) (REGS_BASE); 114 | return *(vu32 *) (REGS_BASE + reg * 4); 115 | } 116 | 117 | inline void bi_reg_wr(u32 reg, u32 data) { 118 | 119 | *(vu32 *) (REGS_BASE); 120 | *(vu32 *) (REGS_BASE + reg * 4) = data; 121 | } 122 | 123 | 124 | void bi_init() { 125 | 126 | evd_cfg = ED_CFG_SDRAM_ON; 127 | spi_cfg = 0 | BI_SPI_SPD_LO; 128 | bi_reg_wr(REG_KEY, 0x1234); 129 | bi_reg_wr(REG_CFG, evd_cfg); 130 | bi_reg_wr(REG_SPI_CFG, spi_cfg); 131 | } 132 | 133 | void bi_speed50() { 134 | 135 | spi_cfg = 0 | BI_SPI_SPD_50; 136 | bi_reg_wr(REG_KEY, 0x1234); 137 | bi_reg_wr(REG_SPI_CFG, spi_cfg); 138 | } 139 | 140 | void bi_speed25() { 141 | 142 | spi_cfg = 0 | BI_SPI_SPD_25; 143 | bi_reg_wr(REG_KEY, 0x1234); 144 | bi_reg_wr(REG_SPI_CFG, spi_cfg); 145 | } 146 | 147 | void bi_load_firmware(u8 *firm) { 148 | 149 | u32 i; 150 | u16 f_ctr = 0; 151 | 152 | evd_cfg &= ~ED_CFG_SDRAM_ON; 153 | bi_reg_wr(REG_CFG, evd_cfg); 154 | 155 | bi_reg_wr(REG_CFG_CNT, 0); 156 | sleep(10); 157 | bi_reg_wr(REG_CFG_CNT, 1); 158 | sleep(10); 159 | 160 | i = 0; 161 | for (;;) { 162 | 163 | bi_reg_wr(REG_CFG_DAT, *(u16 *) & firm[i]); 164 | while ((bi_reg_rd(REG_CFG_CNT) & 8) != 0); 165 | 166 | f_ctr = firm[i++] == 0xff ? f_ctr + 1 : 0; 167 | if (f_ctr >= 47)break; 168 | f_ctr = firm[i++] == 0xff ? f_ctr + 1 : 0; 169 | if (f_ctr >= 47)break; 170 | } 171 | 172 | while ((bi_reg_rd(REG_CFG_CNT) & 4) == 0) { 173 | bi_reg_wr(REG_CFG_DAT, 0xffff); 174 | while ((bi_reg_rd(REG_CFG_CNT) & 8) != 0); 175 | } 176 | 177 | sleep(20); 178 | 179 | bi_init(); 180 | } 181 | 182 | 183 | void evd_init() { 184 | 185 | volatile u8 val; 186 | sd_mode = 0; 187 | dma_busy_callback = 0; 188 | 189 | sleep(1); 190 | val = regs_ptr[0]; 191 | 192 | spi_cfg = (0 << SPI_CFG_SPD0) | (1 << SPI_CFG_SPD1) | (1 << SPI_CFG_SS); 193 | evd_cfg = (1 << ED_CFG_SDRAM_ON); 194 | 195 | val = regs_ptr[0]; 196 | regs_ptr[REG_KEY] = 0x1234; 197 | 198 | val = regs_ptr[0]; 199 | regs_ptr[REG_CFG] = evd_cfg; 200 | val = regs_ptr[0]; 201 | regs_ptr[REG_SPI_CFG] = spi_cfg; 202 | 203 | evd_fifoRxf(); 204 | if (!evd_fifoRxf()) { 205 | 206 | val = regs_ptr[0]; 207 | regs_ptr[REG_DMA_LEN] = 7; //clean 16k 208 | val = regs_ptr[0]; 209 | regs_ptr[REG_DMA_RAM_ADDR] = (ROM_LEN - 0x200000) / 2048; 210 | val = regs_ptr[0]; 211 | regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM; 212 | while (evd_isDmaBusy()); 213 | } 214 | } 215 | 216 | void evd_ulockRegs(){ 217 | 218 | volatile u8 val; 219 | 220 | val = regs_ptr[0]; 221 | regs_ptr[REG_KEY] = 0x1234; 222 | } 223 | 224 | void evd_lockRegs() { 225 | 226 | volatile u8 val; 227 | 228 | val = regs_ptr[0]; 229 | regs_ptr[REG_KEY] = 0; 230 | } 231 | 232 | u8 evd_fifoRxf() { 233 | 234 | u16 val; 235 | //regs_ptr[REG_STATE]++; 236 | val = regs_ptr[REG_STATUS]; 237 | 238 | return (val >> ED_STATE_RXF) & 1; 239 | } 240 | 241 | u8 evd_fifoTxe() { 242 | 243 | u16 val; 244 | //regs_ptr[REG_STATE]++; 245 | val = regs_ptr[REG_STATUS]; 246 | 247 | return (val >> ED_STATE_TXE) & 1; 248 | } 249 | 250 | u8 evd_isDmaBusy() { 251 | 252 | u16 val; 253 | //volatile u32 i; 254 | sleep(1); 255 | if(dma_busy_callback != 0)dma_busy_callback(); 256 | //regs_ptr[REG_STATE]++; 257 | val = regs_ptr[REG_STATUS]; 258 | 259 | return (val >> ED_STATE_DMA_BUSY) & 1; 260 | } 261 | 262 | u8 evd_isDmaTimeout() { 263 | 264 | u16 val; 265 | //regs_ptr[REG_STATE]++; 266 | val = regs_ptr[REG_STATUS]; 267 | 268 | return (val >> ED_STATE_DMA_TOUT) & 1; 269 | } 270 | 271 | u8 evd_fifoRdToCart(u32 cart_addr, u16 blocks) { 272 | 273 | volatile u8 val; 274 | cart_addr /= 2048; 275 | 276 | val = regs_ptr[0]; 277 | regs_ptr[REG_DMA_LEN] = (blocks - 1); 278 | val = regs_ptr[0]; 279 | regs_ptr[REG_DMA_RAM_ADDR] = cart_addr; 280 | val = regs_ptr[0]; 281 | regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM; 282 | 283 | while (evd_isDmaBusy()); 284 | if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT; 285 | 286 | return 0; 287 | } 288 | 289 | u8 evd_fifoWrFromCart(u32 cart_addr, u16 blocks) { 290 | 291 | volatile u8 val; 292 | cart_addr /= 2048; 293 | 294 | val = regs_ptr[0]; 295 | regs_ptr[REG_DMA_LEN] = (blocks - 1); 296 | val = regs_ptr[0]; 297 | regs_ptr[REG_DMA_RAM_ADDR] = cart_addr; 298 | val = regs_ptr[0]; 299 | regs_ptr[REG_DMA_CFG] = DCFG_RAM_TO_FIFO; 300 | 301 | while (evd_isDmaBusy()); 302 | if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT; 303 | 304 | return 0; 305 | } 306 | 307 | u8 evd_fifoRd(void *buff, u16 blocks) { 308 | 309 | volatile u8 val; 310 | u32 len = blocks == 0 ? 65536 * 512 : blocks * 512; 311 | u32 ram_buff_addr = DMA_BUFF_ADDR / 2048; //(ROM_LEN - len - 65536 * 4) / 2048; 312 | 313 | val = regs_ptr[0]; 314 | regs_ptr[REG_DMA_LEN] = (blocks - 1); 315 | val = regs_ptr[0]; 316 | regs_ptr[REG_DMA_RAM_ADDR] = ram_buff_addr; 317 | val = regs_ptr[0]; 318 | regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM; 319 | 320 | while (evd_isDmaBusy()); 321 | dma_read_s(buff, (0xb0000000 + ram_buff_addr * 2048), len); 322 | if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT; 323 | 324 | return 0; 325 | } 326 | 327 | 328 | 329 | u8 evd_fifoWr(void *buff, u16 blocks) { 330 | 331 | volatile u8 val; 332 | u32 len = blocks == 0 ? 65536 * 512 : blocks * 512; 333 | u32 ram_buff_addr = DMA_BUFF_ADDR / 2048; //(ROM_LEN - len - 65536 * 4) / 2048; 334 | 335 | dma_write_s(buff, (0xb0000000 + ram_buff_addr * 1024 * 2), len); 336 | 337 | val = regs_ptr[0]; 338 | regs_ptr[REG_DMA_LEN] = (blocks - 1); 339 | val = regs_ptr[0]; 340 | regs_ptr[REG_DMA_RAM_ADDR] = ram_buff_addr; 341 | val = regs_ptr[0]; 342 | regs_ptr[REG_DMA_CFG] = DCFG_RAM_TO_FIFO; 343 | 344 | while (evd_isDmaBusy()); 345 | if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT; 346 | 347 | return 0; 348 | } 349 | 350 | u8 evd_isSpiBusy() { 351 | 352 | volatile u16 val; 353 | 354 | regs_ptr[REG_STATUS]; 355 | val = regs_ptr[REG_STATUS]; 356 | 357 | return (val >> ED_STATE_SPI) & 1; 358 | } 359 | 360 | u8 evd_SPI(u8 dat) { 361 | 362 | volatile u8 val; 363 | 364 | val = regs_ptr[0]; 365 | regs_ptr[REG_SPI] = dat; 366 | while (evd_isSpiBusy()); 367 | //osInvalICache((u32*) & regs_ptr[REG_SPI], 1); 368 | val = regs_ptr[REG_SPI]; 369 | 370 | return val; 371 | } 372 | 373 | void evd_spiSSOn() { 374 | 375 | volatile u8 val; 376 | 377 | if (sd_mode)return; 378 | spi_cfg &= ~(1 << SPI_CFG_SS); 379 | val = regs_ptr[0]; 380 | regs_ptr[REG_SPI_CFG] = spi_cfg; 381 | } 382 | 383 | void evd_spiSSOff() { 384 | 385 | volatile u8 val; 386 | 387 | spi_cfg |= (1 << SPI_CFG_SS); 388 | val = regs_ptr[0]; 389 | regs_ptr[REG_SPI_CFG] = spi_cfg; 390 | } 391 | 392 | void evd_enableSDMode() { 393 | 394 | sd_mode = 1; 395 | } 396 | 397 | void evd_enableSPIMode() { 398 | 399 | sd_mode = 0; 400 | } 401 | 402 | u8 evd_isSDMode() { 403 | 404 | return sd_mode; 405 | } 406 | 407 | void evd_SDcmdWriteMode(u8 bit1_mode) { 408 | 409 | volatile u8 val; 410 | 411 | if (!sd_mode)return; 412 | spi_cfg &= ~((1 << SPI_CFG_RD) | (1 << SPI_CFG_DAT)); 413 | if (bit1_mode) { 414 | spi_cfg |= (1 << SPI_CFG_1BIT); 415 | } else { 416 | spi_cfg &= ~(1 << SPI_CFG_1BIT); 417 | } 418 | val = regs_ptr[0]; 419 | regs_ptr[REG_SPI_CFG] = spi_cfg; 420 | 421 | } 422 | 423 | void evd_SDcmdReadMode(u8 bit1_mode) { 424 | 425 | volatile u8 val; 426 | 427 | if (!sd_mode)return; 428 | spi_cfg |= (1 << SPI_CFG_RD); 429 | spi_cfg &= ~(1 << SPI_CFG_DAT); 430 | if (bit1_mode) { 431 | spi_cfg |= (1 << SPI_CFG_1BIT); 432 | } else { 433 | spi_cfg &= ~(1 << SPI_CFG_1BIT); 434 | } 435 | val = regs_ptr[0]; 436 | regs_ptr[REG_SPI_CFG] = spi_cfg; 437 | } 438 | 439 | void evd_SDdatWriteMode(u8 bit4_mode) { 440 | 441 | volatile u8 val; 442 | 443 | if (!sd_mode)return; 444 | spi_cfg &= ~(1 << SPI_CFG_RD); 445 | spi_cfg |= (1 << SPI_CFG_DAT); 446 | if (bit4_mode) { 447 | spi_cfg |= (1 << SPI_CFG_1BIT); 448 | } else { 449 | spi_cfg &= ~(1 << SPI_CFG_1BIT); 450 | } 451 | val = regs_ptr[0]; 452 | regs_ptr[REG_SPI_CFG] = spi_cfg; 453 | } 454 | 455 | void evd_SDdatReadMode(u8 bit4_mode) { 456 | 457 | volatile u8 val; 458 | 459 | if (!sd_mode)return; 460 | spi_cfg |= (1 << SPI_CFG_RD) | (1 << SPI_CFG_DAT); 461 | if (bit4_mode) { 462 | spi_cfg |= (1 << SPI_CFG_1BIT); 463 | } else { 464 | spi_cfg &= ~(1 << SPI_CFG_1BIT); 465 | } 466 | val = regs_ptr[0]; 467 | regs_ptr[REG_SPI_CFG] = spi_cfg; 468 | } 469 | 470 | void evd_setSpiSpeed(u8 speed) { 471 | 472 | volatile u8 val; 473 | 474 | spi_cfg &= ~3; //((1 << SPI_CFG_SPD0) | (1 << SPI_CFG_SPD1)); 475 | spi_cfg |= speed & 3; 476 | val = regs_ptr[0]; 477 | regs_ptr[REG_SPI_CFG] = spi_cfg; 478 | } 479 | 480 | u8 evd_mmcReadToCart(u32 cart_addr, u32 len) { 481 | 482 | volatile u8 val; 483 | cart_addr /= 2048; 484 | 485 | val = regs_ptr[0]; 486 | regs_ptr[REG_DMA_LEN] = (len - 1); 487 | val = regs_ptr[0]; 488 | regs_ptr[REG_DMA_RAM_ADDR] = cart_addr; 489 | val = regs_ptr[0]; 490 | regs_ptr[REG_DMA_CFG] = DCFG_SD_TO_RAM; 491 | 492 | while (evd_isDmaBusy()); 493 | if (evd_isDmaTimeout())return EVD_ERROR_MMC_TIMEOUT; 494 | 495 | return 0; 496 | } 497 | 498 | void evd_setCfgBit(u8 option, u8 state) { 499 | 500 | volatile u8 val; 501 | 502 | if (state)evd_cfg |= (1 << option); 503 | else 504 | evd_cfg &= ~(1 << option); 505 | 506 | val = regs_ptr[0]; 507 | regs_ptr[REG_CFG] = evd_cfg; 508 | val = regs_ptr[0]; 509 | } 510 | 511 | u16 evd_readReg(u8 reg) { 512 | 513 | volatile u32 tmp; 514 | 515 | tmp = regs_ptr[0]; 516 | 517 | return regs_ptr[reg]; 518 | } 519 | 520 | void evd_setSaveType(u8 type) { 521 | 522 | u8 eeprom_on, sram_on, eeprom_size, sram_size; 523 | eeprom_on = 0; 524 | sram_on = 0; 525 | eeprom_size = 0; 526 | sram_size = 0; 527 | 528 | switch (type) { 529 | case SAVE_TYPE_EEP16k: 530 | eeprom_on = 1; 531 | eeprom_size = 1; 532 | break; 533 | case SAVE_TYPE_EEP4k: 534 | eeprom_on = 1; 535 | break; 536 | case SAVE_TYPE_SRAM: 537 | sram_on = 1; 538 | break; 539 | case SAVE_TYPE_SRAM128: 540 | sram_on = 1; 541 | sram_size = 1; 542 | break; 543 | case SAVE_TYPE_FLASH: 544 | sram_on = 0; 545 | sram_size = 1; 546 | break; 547 | case SAVE_TYPE_SRAM768: 548 | sram_on = 1; 549 | sram_size = 1; 550 | break; 551 | default: 552 | sram_on = 0; 553 | sram_size = 0; 554 | break; 555 | } 556 | 557 | volatile u8 val; 558 | val = regs_ptr[0]; 559 | regs_ptr[REG_SAV_CFG] = (eeprom_on << SAV_EEP_ON | sram_on << SAV_SRM_ON | eeprom_size << SAV_EEP_SIZE | sram_size << SAV_SRM_SIZE); 560 | } 561 | 562 | void evd_writeReg(u8 reg, u16 val) { 563 | 564 | volatile u8 tmp; 565 | tmp = regs_ptr[0]; 566 | regs_ptr[reg] = val; 567 | } 568 | 569 | void evd_mmcSetDmaSwap(u8 state) { 570 | 571 | evd_setCfgBit(ED_CFG_SWAP, state); 572 | } 573 | 574 | void evd_writeMsg(u8 dat) { 575 | 576 | evd_writeReg(REG_MSG, dat); 577 | } 578 | 579 | u8 evd_readMsg() { 580 | 581 | return evd_readReg(REG_MSG); 582 | } 583 | 584 | u16 evd_getFirmVersion() { 585 | 586 | return evd_readReg(REG_VER); 587 | } 588 | 589 | 590 | void evd_setDmaCallback(void (*callback)()) { 591 | 592 | dma_busy_callback = callback; 593 | } 594 | -------------------------------------------------------------------------------- /src/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:Win32, 1:uITRON4.0, 2:uC/OS-II, 3:FreeRTOS, 4:CMSIS-RTOS */ 43 | 44 | 45 | #if OS_TYPE == 0 /* Win32 */ 46 | #include 47 | static HANDLE Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */ 48 | 49 | #elif OS_TYPE == 1 /* uITRON */ 50 | #include "itron.h" 51 | #include "kernel.h" 52 | static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */ 53 | 54 | #elif OS_TYPE == 2 /* uc/OS-II */ 55 | #include "includes.h" 56 | static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */ 57 | 58 | #elif OS_TYPE == 3 /* FreeRTOS */ 59 | #include "FreeRTOS.h" 60 | #include "semphr.h" 61 | static SemaphoreHandle_t Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */ 62 | 63 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 64 | #include "cmsis_os.h" 65 | static osMutexId Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */ 66 | 67 | #endif 68 | 69 | 70 | 71 | /*------------------------------------------------------------------------*/ 72 | /* Create a Mutex */ 73 | /*------------------------------------------------------------------------*/ 74 | /* This function is called in f_mount function to create a new mutex 75 | / or semaphore for the volume. When a 0 is returned, the f_mount function 76 | / fails with FR_INT_ERR. 77 | */ 78 | 79 | int ff_mutex_create ( /* Returns 1:Function succeeded or 0:Could not create the mutex */ 80 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 81 | ) 82 | { 83 | #if OS_TYPE == 0 /* Win32 */ 84 | Mutex[vol] = CreateMutex(NULL, FALSE, NULL); 85 | return (int)(Mutex[vol] != INVALID_HANDLE_VALUE); 86 | 87 | #elif OS_TYPE == 1 /* uITRON */ 88 | T_CMTX cmtx = {TA_TPRI,1}; 89 | 90 | Mutex[vol] = acre_mtx(&cmtx); 91 | return (int)(Mutex[vol] > 0); 92 | 93 | #elif OS_TYPE == 2 /* uC/OS-II */ 94 | OS_ERR err; 95 | 96 | Mutex[vol] = OSMutexCreate(0, &err); 97 | return (int)(err == OS_NO_ERR); 98 | 99 | #elif OS_TYPE == 3 /* FreeRTOS */ 100 | Mutex[vol] = xSemaphoreCreateMutex(); 101 | return (int)(Mutex[vol] != NULL); 102 | 103 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 104 | osMutexDef(cmsis_os_mutex); 105 | 106 | Mutex[vol] = osMutexCreate(osMutex(cmsis_os_mutex)); 107 | return (int)(Mutex[vol] != NULL); 108 | 109 | #endif 110 | } 111 | 112 | 113 | /*------------------------------------------------------------------------*/ 114 | /* Delete a Mutex */ 115 | /*------------------------------------------------------------------------*/ 116 | /* This function is called in f_mount function to delete a mutex or 117 | / semaphore of the volume created with ff_mutex_create function. 118 | */ 119 | 120 | void ff_mutex_delete ( /* Returns 1:Function succeeded or 0:Could not delete due to an error */ 121 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 122 | ) 123 | { 124 | #if OS_TYPE == 0 /* Win32 */ 125 | CloseHandle(Mutex[vol]); 126 | 127 | #elif OS_TYPE == 1 /* uITRON */ 128 | del_mtx(Mutex[vol]); 129 | 130 | #elif OS_TYPE == 2 /* uC/OS-II */ 131 | OS_ERR err; 132 | 133 | OSMutexDel(Mutex[vol], OS_DEL_ALWAYS, &err); 134 | 135 | #elif OS_TYPE == 3 /* FreeRTOS */ 136 | vSemaphoreDelete(Mutex[vol]); 137 | 138 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 139 | osMutexDelete(Mutex[vol]); 140 | 141 | #endif 142 | } 143 | 144 | 145 | /*------------------------------------------------------------------------*/ 146 | /* Request a Grant to Access the Volume */ 147 | /*------------------------------------------------------------------------*/ 148 | /* This function is called on enter file functions to lock the volume. 149 | / When a 0 is returned, the file function fails with FR_TIMEOUT. 150 | */ 151 | 152 | int ff_mutex_take ( /* Returns 1:Succeeded or 0:Timeout */ 153 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 154 | ) 155 | { 156 | #if OS_TYPE == 0 /* Win32 */ 157 | return (int)(WaitForSingleObject(Mutex[vol], FF_FS_TIMEOUT) == WAIT_OBJECT_0); 158 | 159 | #elif OS_TYPE == 1 /* uITRON */ 160 | return (int)(tloc_mtx(Mutex[vol], FF_FS_TIMEOUT) == E_OK); 161 | 162 | #elif OS_TYPE == 2 /* uC/OS-II */ 163 | OS_ERR err; 164 | 165 | OSMutexPend(Mutex[vol], FF_FS_TIMEOUT, &err)); 166 | return (int)(err == OS_NO_ERR); 167 | 168 | #elif OS_TYPE == 3 /* FreeRTOS */ 169 | return (int)(xSemaphoreTake(Mutex[vol], FF_FS_TIMEOUT) == pdTRUE); 170 | 171 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 172 | return (int)(osMutexWait(Mutex[vol], FF_FS_TIMEOUT) == osOK); 173 | 174 | #endif 175 | } 176 | 177 | 178 | 179 | /*------------------------------------------------------------------------*/ 180 | /* Release a Grant to Access the Volume */ 181 | /*------------------------------------------------------------------------*/ 182 | /* This function is called on leave file functions to unlock the volume. 183 | */ 184 | 185 | void ff_mutex_give ( 186 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 187 | ) 188 | { 189 | #if OS_TYPE == 0 /* Win32 */ 190 | ReleaseMutex(Mutex[vol]); 191 | 192 | #elif OS_TYPE == 1 /* uITRON */ 193 | unl_mtx(Mutex[vol]); 194 | 195 | #elif OS_TYPE == 2 /* uC/OS-II */ 196 | OSMutexPost(Mutex[vol]); 197 | 198 | #elif OS_TYPE == 3 /* FreeRTOS */ 199 | xSemaphoreGive(Mutex[vol]); 200 | 201 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 202 | osMutexRelease(Mutex[vol]); 203 | 204 | #endif 205 | } 206 | 207 | #endif /* FF_FS_REENTRANT */ 208 | 209 | -------------------------------------------------------------------------------- /src/hashtable.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2011 @marekweb https://github.com/marekweb/datastructs-c 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | /** 8 | * Hashtable implementation 9 | * Uses dynamic addressing with linear probing. 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "hashtable.h" 17 | 18 | /* 19 | * Interface section used for `makeheaders`. 20 | */ 21 | #if INTERFACE 22 | struct hashtable_entry { 23 | char* key; 24 | void* value; 25 | }; 26 | 27 | struct hashtable { 28 | unsigned int size; 29 | unsigned int capacity; 30 | hashtable_entry* body; 31 | }; 32 | #endif 33 | 34 | #define HASHTABLE_INITIAL_CAPACITY 2 35 | 36 | /** 37 | * Compute the hash value for the given string. 38 | * Implements the djb k=33 hash function. 39 | */ 40 | unsigned long hashtable_hash(char* str) 41 | { 42 | unsigned long hash = 5381; 43 | int c; 44 | while ((c = *str++)) 45 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 46 | return hash; 47 | } 48 | 49 | /** 50 | * Find an available slot for the given key, using linear probing. 51 | */ 52 | unsigned int hashtable_find_slot(hashtable* t, char* key) 53 | { 54 | int index = hashtable_hash(key) % t->capacity; 55 | while (t->body[index].key != NULL && strcmp(t->body[index].key, key) != 0) { 56 | index = (index + 1) % t->capacity; 57 | } 58 | return index; 59 | } 60 | 61 | /** 62 | * Return the item associated with the given key, or NULL if not found. 63 | */ 64 | void* hashtable_get(hashtable* t, char* key) 65 | { 66 | int index = hashtable_find_slot(t, key); 67 | if (t->body[index].key != NULL) { 68 | return t->body[index].value; 69 | } else { 70 | return NULL; 71 | } 72 | } 73 | 74 | /** 75 | * Assign a value to the given key in the table. 76 | */ 77 | void hashtable_set(hashtable* t, char* key, void* value) 78 | { 79 | int index = hashtable_find_slot(t, key); 80 | if (t->body[index].key != NULL) { 81 | /* Entry exists; update it. */ 82 | t->body[index].value = value; 83 | } else { 84 | t->size++; 85 | /* Create a new entry */ 86 | if ((float)t->size / t->capacity > 0.8) { 87 | /* Resize the hash table */ 88 | hashtable_resize(t, t->capacity * 2); 89 | index = hashtable_find_slot(t, key); 90 | } 91 | t->body[index].key = key; 92 | t->body[index].value = value; 93 | } 94 | } 95 | 96 | /** 97 | * Remove a key from the table 98 | */ 99 | void hashtable_remove(hashtable* t, char* key) 100 | { 101 | int index = hashtable_find_slot(t, key); 102 | if (t->body[index].key != NULL) { 103 | t->body[index].key = NULL; 104 | t->body[index].value = NULL; 105 | t->size--; 106 | } 107 | } 108 | 109 | /** 110 | * Create a new, empty hashtable 111 | */ 112 | hashtable* hashtable_create() 113 | { 114 | hashtable* new_ht = malloc(sizeof(hashtable)); 115 | new_ht->size = 0; 116 | new_ht->capacity = HASHTABLE_INITIAL_CAPACITY; 117 | new_ht->body = hashtable_body_allocate(new_ht->capacity); 118 | return new_ht; 119 | } 120 | 121 | #if 0 122 | /** 123 | * Adds all items from another table. 124 | */ 125 | hashtable* hashtable_merge(hashtable* ht, hashtable* other) 126 | { 127 | } 128 | #endif 129 | 130 | /** 131 | * Allocate a new memory block with the given capacity. 132 | */ 133 | hashtable_entry* hashtable_body_allocate(unsigned int capacity) 134 | { 135 | return (hashtable_entry*)calloc(capacity, sizeof(hashtable_entry)); 136 | } 137 | 138 | /** 139 | * Resize the allocated memory. 140 | * Warning: clears the table of all entries. 141 | */ 142 | void hashtable_resize(hashtable* t, unsigned int capacity) 143 | { 144 | assert(capacity >= t->size); 145 | unsigned int old_capacity = t->capacity; 146 | hashtable_entry* old_body = t->body; 147 | t->body = hashtable_body_allocate(capacity); 148 | t->capacity = capacity; 149 | for (int i = 0; i < old_capacity; i++) { 150 | if (old_body[i].key != NULL) { 151 | hashtable_set(t, old_body[i].key, old_body[i].value); 152 | } 153 | } 154 | } 155 | 156 | /** 157 | * Destroy the table and deallocate it from memory. This does not deallocate the contained items. 158 | */ 159 | void hashtable_destroy(hashtable* t) 160 | { 161 | free(t->body); 162 | free(t); 163 | } 164 | -------------------------------------------------------------------------------- /src/image.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "types.h" 4 | #include "image.h" 5 | 6 | //#define STBI_HEADER_FILE_ONLY 7 | #define STB_IMAGE_IMPLEMENTATION 8 | #include "stb_image.h" 9 | 10 | 11 | /* 12 | * Load an image from the rom filesystem, returning a pointer to the 13 | * sprite that hold the image. 14 | */ 15 | sprite_t *loadImageDFS(char *fname) { 16 | int size, x, y, n, fd; 17 | u8 *tbuf; 18 | u8 *ibuf; 19 | sprite_t *sbuf; 20 | 21 | fd = dfs_open(fname); 22 | if (fd < 0) 23 | return 0; // couldn't open image 24 | 25 | size = dfs_size(fd); 26 | tbuf = malloc(size); 27 | if (!tbuf) { 28 | dfs_close(fd); 29 | return 0; // out of memory 30 | } 31 | 32 | dfs_read(tbuf, 1, size, fd); 33 | dfs_close(fd); 34 | 35 | ibuf = stbi_load_from_memory(tbuf, size, &x, &y, &n, 4); 36 | free(tbuf); 37 | if (!ibuf) 38 | return 0; // couldn't decode image 39 | 40 | sbuf = (sprite_t*)malloc(sizeof(sprite_t) + x * y * 2); 41 | if (!sbuf) { 42 | stbi_image_free(ibuf); 43 | return 0; // out of memory 44 | } 45 | sbuf->width = x; 46 | sbuf->height = y; 47 | sbuf->bitdepth = 2; 48 | sbuf->format = 0; 49 | sbuf->hslices = x / 32; 50 | sbuf->vslices = y / 16; 51 | 52 | color_t *src = (color_t*)ibuf; 53 | u16 *dst = (u16*)((u32)sbuf + sizeof(sprite_t)); 54 | 55 | for (int j=0; jdata, sbuf->width * sbuf->height * sbuf->bitdepth ); 61 | 62 | stbi_image_free(ibuf); 63 | return sbuf; 64 | } 65 | 66 | 67 | sprite_t *loadImage32(u8 *png, int size) { 68 | int x, y, n, fd; 69 | u8 *tbuf; 70 | u32 *ibuf; 71 | sprite_t *sbuf; 72 | 73 | tbuf = malloc(size); 74 | memcpy(tbuf,png,size); 75 | 76 | ibuf = (u32*)stbi_load_from_memory(tbuf, size, &x, &y, &n, 4); 77 | free(tbuf); 78 | if (!ibuf) 79 | return 0; // couldn't decode image 80 | 81 | sbuf = (sprite_t*)malloc(sizeof(sprite_t) + x * y * 4); 82 | if (!sbuf) { 83 | stbi_image_free(ibuf); 84 | return 0; // out of memory 85 | } 86 | 87 | sbuf->width = x; 88 | sbuf->height = y; 89 | sbuf->bitdepth = 4; 90 | sbuf->format = 0; 91 | sbuf->hslices = x / 32; 92 | sbuf->vslices = y / 32; 93 | 94 | // color_t *src = (color_t*)ibuf; 95 | u32 *dst = (u32*)((u32)sbuf + sizeof(sprite_t)); 96 | 97 | for (int j=0; jdata, sbuf->width * sbuf->height * sbuf->bitdepth ); 103 | 104 | stbi_image_free(ibuf); 105 | return sbuf; 106 | } 107 | 108 | sprite_t *loadImage32DFS(char *fname) { 109 | int size, x, y, n, fd; 110 | u8 *tbuf; 111 | u32 *ibuf; 112 | sprite_t *sbuf; 113 | 114 | fd = dfs_open(fname); 115 | if (fd < 0) 116 | return 0; // couldn't open image 117 | 118 | size = dfs_size(fd); 119 | tbuf = malloc(size); 120 | if (!tbuf) { 121 | dfs_close(fd); 122 | return 0; // out of memory 123 | } 124 | 125 | dfs_read(tbuf, 1, size, fd); 126 | dfs_close(fd); 127 | 128 | ibuf = (u32*)stbi_load_from_memory(tbuf, size, &x, &y, &n, 4); 129 | free(tbuf); 130 | if (!ibuf) 131 | return 0; // couldn't decode image 132 | 133 | sbuf = (sprite_t*)malloc(sizeof(sprite_t) + x * y * 4); 134 | if (!sbuf) { 135 | stbi_image_free(ibuf); 136 | return 0; // out of memory 137 | } 138 | 139 | sbuf->width = x; 140 | sbuf->height = y; 141 | sbuf->bitdepth = 4; 142 | sbuf->format = 0; 143 | sbuf->hslices = x / 32; 144 | sbuf->vslices = y / 32; 145 | 146 | // color_t *src = (color_t*)ibuf; 147 | u32 *dst = (u32*)((u32)sbuf + sizeof(sprite_t)); 148 | 149 | for (int j=0; jdata, sbuf->width * sbuf->height * sbuf->bitdepth ); 155 | 156 | stbi_image_free(ibuf); 157 | return sbuf; 158 | } 159 | 160 | /* 161 | * Draw an image to the screen using the sprite passed. 162 | */ 163 | void drawImage(display_context_t dcon, sprite_t *sprite) { 164 | int x, y = 0; 165 | 166 | rdp_sync(SYNC_PIPE); 167 | rdp_set_default_clipping(); 168 | rdp_enable_texture_copy(); 169 | rdp_attach_display(dcon); 170 | // Draw image 171 | for (int j=0; jvslices; j++) { 172 | x = 0; 173 | for (int i=0; ihslices; i++) { 174 | rdp_sync(SYNC_PIPE); 175 | rdp_load_texture_stride(0, 0, MIRROR_DISABLED, sprite, j*sprite->hslices + i); 176 | rdp_draw_sprite(0, x, y); 177 | x += 32; 178 | } 179 | y += 16; 180 | } 181 | rdp_detach_display(); 182 | } -------------------------------------------------------------------------------- /src/ini.c: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 | home page for more info: 5 | 6 | http://code.google.com/p/inih/ 7 | 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | #include "ini.h" 16 | 17 | #if !INI_USE_STACK 18 | #include 19 | #endif 20 | 21 | #define MAX_SECTION 50 22 | #define MAX_NAME 50 23 | 24 | 25 | /* Strip whitespace chars off end of given string, in place. Return s. */ 26 | static char* rstrip(char* s) 27 | { 28 | char* p = s + strlen(s); 29 | while (p > s && isspace((unsigned char)(*--p))) 30 | *p = '\0'; 31 | return s; 32 | } 33 | 34 | /* Return pointer to first non-whitespace char in given string. */ 35 | static char* lskip(const char* s) 36 | { 37 | while (*s && isspace((unsigned char)(*s))) 38 | s++; 39 | return (char*)s; 40 | } 41 | 42 | /* Return pointer to first char c or ';' comment in given string, or pointer to 43 | null at end of string if neither found. ';' must be prefixed by a whitespace 44 | character to register as a comment. */ 45 | static char* find_char_or_comment(const char* s, char c) 46 | { 47 | int was_whitespace = 0; 48 | while (*s && *s != c && !(was_whitespace && *s == ';')) { 49 | was_whitespace = isspace((unsigned char)(*s)); 50 | s++; 51 | } 52 | return (char*)s; 53 | } 54 | 55 | /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ 56 | static char* strncpy0(char* dest, const char* src, size_t size) 57 | { 58 | strncpy(dest, src, size); 59 | dest[size - 1] = '\0'; 60 | return dest; 61 | } 62 | 63 | 64 | /* See documentation in header file. */ 65 | int ini_parse_str(char* ini_string, 66 | int (*handler)(void*, const char*, const char*, 67 | const char*), 68 | void* user) 69 | { 70 | /* Uses a fair bit of stack (use heap instead if you need to) */ 71 | #if INI_USE_STACK 72 | char line[INI_MAX_LINE]; 73 | #else 74 | char* line; 75 | #endif 76 | char section[MAX_SECTION] = ""; 77 | char prev_name[MAX_NAME] = ""; 78 | 79 | char* start; 80 | char* end; 81 | char* name; 82 | char* value; 83 | int lineno = 0; 84 | int error = 0; 85 | 86 | #if !INI_USE_STACK 87 | line = (char*)malloc(INI_MAX_LINE); 88 | if (!line) { 89 | return -2; 90 | } 91 | #endif 92 | 93 | 94 | int i=1; 95 | char *ptr; 96 | 97 | // initialisieren und ersten Abschnitt erstellen 98 | ptr = strtok(ini_string, "\n"); 99 | 100 | 101 | /* Scan through file line by line */ 102 | while(ptr != NULL) { 103 | 104 | sprintf(line, "%s\n",ptr); 105 | ptr = strtok(NULL, "\n"); 106 | // while (line=gets( ini_string) != NULL) { 107 | lineno++; 108 | 109 | start = line; 110 | #if INI_ALLOW_BOM 111 | if (lineno == 1 && (unsigned char)start[0] == 0xEF && 112 | (unsigned char)start[1] == 0xBB && 113 | (unsigned char)start[2] == 0xBF) { 114 | start += 3; 115 | } 116 | #endif 117 | start = lskip(rstrip(start)); 118 | 119 | if (*start == ';' || *start == '#') { 120 | /* Per Python ConfigParser, allow '#' comments at start of line */ 121 | } 122 | #if INI_ALLOW_MULTILINE 123 | else if (*prev_name && *start && start > line) { 124 | /* Non-black line with leading whitespace, treat as continuation 125 | of previous name's value (as per Python ConfigParser). */ 126 | if (!handler(user, section, prev_name, start) && !error) 127 | error = lineno; 128 | } 129 | #endif 130 | else if (*start == '[') { 131 | /* A "[section]" line */ 132 | end = find_char_or_comment(start + 1, ']'); 133 | if (*end == ']') { 134 | *end = '\0'; 135 | strncpy0(section, start + 1, sizeof(section)); 136 | *prev_name = '\0'; 137 | } 138 | else if (!error) { 139 | /* No ']' found on section line */ 140 | error = lineno; 141 | } 142 | } 143 | else if (*start && *start != ';') { 144 | /* Not a comment, must be a name[=:]value pair */ 145 | end = find_char_or_comment(start, '='); 146 | if (*end != '=') { 147 | end = find_char_or_comment(start, ':'); 148 | } 149 | if (*end == '=' || *end == ':') { 150 | *end = '\0'; 151 | name = rstrip(start); 152 | value = lskip(end + 1); 153 | end = find_char_or_comment(value, '\0'); 154 | if (*end == ';') 155 | *end = '\0'; 156 | rstrip(value); 157 | 158 | /* Valid name[=:]value pair found, call handler */ 159 | strncpy0(prev_name, name, sizeof(prev_name)); 160 | if (!handler(user, section, name, value) && !error) 161 | error = lineno; 162 | } 163 | else if (!error) { 164 | /* No '=' or ':' found on name[=:]value line */ 165 | error = lineno; 166 | } 167 | } 168 | } 169 | 170 | #if !INI_USE_STACK 171 | free(line); 172 | #endif 173 | 174 | return error; 175 | } 176 | 177 | 178 | 179 | /* See documentation in header file. */ 180 | int ini_parse_file(FILE* file, 181 | int (*handler)(void*, const char*, const char*, 182 | const char*), 183 | void* user) 184 | { 185 | /* Uses a fair bit of stack (use heap instead if you need to) */ 186 | #if INI_USE_STACK 187 | char line[INI_MAX_LINE]; 188 | #else 189 | char* line; 190 | #endif 191 | char section[MAX_SECTION] = ""; 192 | char prev_name[MAX_NAME] = ""; 193 | 194 | char* start; 195 | char* end; 196 | char* name; 197 | char* value; 198 | int lineno = 0; 199 | int error = 0; 200 | 201 | #if !INI_USE_STACK 202 | line = (char*)malloc(INI_MAX_LINE); 203 | if (!line) { 204 | return -2; 205 | } 206 | #endif 207 | 208 | /* Scan through file line by line */ 209 | while (fgets(line, INI_MAX_LINE, file) != NULL) { 210 | lineno++; 211 | 212 | start = line; 213 | #if INI_ALLOW_BOM 214 | if (lineno == 1 && (unsigned char)start[0] == 0xEF && 215 | (unsigned char)start[1] == 0xBB && 216 | (unsigned char)start[2] == 0xBF) { 217 | start += 3; 218 | } 219 | #endif 220 | start = lskip(rstrip(start)); 221 | 222 | if (*start == ';' || *start == '#') { 223 | /* Per Python ConfigParser, allow '#' comments at start of line */ 224 | } 225 | #if INI_ALLOW_MULTILINE 226 | else if (*prev_name && *start && start > line) { 227 | /* Non-black line with leading whitespace, treat as continuation 228 | of previous name's value (as per Python ConfigParser). */ 229 | if (!handler(user, section, prev_name, start) && !error) 230 | error = lineno; 231 | } 232 | #endif 233 | else if (*start == '[') { 234 | /* A "[section]" line */ 235 | end = find_char_or_comment(start + 1, ']'); 236 | if (*end == ']') { 237 | *end = '\0'; 238 | strncpy0(section, start + 1, sizeof(section)); 239 | *prev_name = '\0'; 240 | } 241 | else if (!error) { 242 | /* No ']' found on section line */ 243 | error = lineno; 244 | } 245 | } 246 | else if (*start && *start != ';') { 247 | /* Not a comment, must be a name[=:]value pair */ 248 | end = find_char_or_comment(start, '='); 249 | if (*end != '=') { 250 | end = find_char_or_comment(start, ':'); 251 | } 252 | if (*end == '=' || *end == ':') { 253 | *end = '\0'; 254 | name = rstrip(start); 255 | value = lskip(end + 1); 256 | end = find_char_or_comment(value, '\0'); 257 | if (*end == ';') 258 | *end = '\0'; 259 | rstrip(value); 260 | 261 | /* Valid name[=:]value pair found, call handler */ 262 | strncpy0(prev_name, name, sizeof(prev_name)); 263 | if (!handler(user, section, name, value) && !error) 264 | error = lineno; 265 | } 266 | else if (!error) { 267 | /* No '=' or ':' found on name[=:]value line */ 268 | error = lineno; 269 | } 270 | } 271 | } 272 | 273 | #if !INI_USE_STACK 274 | free(line); 275 | #endif 276 | 277 | return error; 278 | } 279 | 280 | /* See documentation in header file. */ 281 | int ini_parse(const char* filename, 282 | int (*handler)(void*, const char*, const char*, const char*), 283 | void* user) 284 | { 285 | FILE* file; 286 | int error; 287 | 288 | // file = fopen(filename, "r"); 289 | 290 | 291 | fputs(filename, file); 292 | 293 | 294 | 295 | 296 | if (!file) 297 | return -1; 298 | error = ini_parse_file(file, handler, user); 299 | fclose(file); 300 | return error; 301 | } 302 | -------------------------------------------------------------------------------- /src/mem.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #include "everdrive.h" 8 | #include "sys.h" 9 | #include "errors.h" 10 | #include "mem.h" 11 | 12 | u8 spi_dma; 13 | 14 | u8 memSpiReadDma(void *dst, u16 slen); 15 | u8 memSpiReadPio(void *dst, u16 slen); 16 | u8 mem_buff[512]; 17 | 18 | void memSpiSetDma(u8 mode) { 19 | spi_dma = mode; 20 | } 21 | 22 | void memcopy(void *src, void *dst, u16 len) { 23 | 24 | u8 *s = (u8 *) src; 25 | u8 *d = (u8 *) dst; 26 | while (len--)*d++ = *s++; 27 | } 28 | 29 | void memfill(void *dst, u8 val, u16 len) { 30 | u8 *d = (u8 *) dst; 31 | while (len--)*d++ = val; 32 | } 33 | 34 | 35 | // buff len 36 | u8 memSpiRead(void *dst, u16 slen) { 37 | 38 | u8 copy_to_rom = 0; 39 | u32 addr = (u32) dst; //if ROM_ADDR 0xb0000000 40 | if (addr >= ROM_ADDR && addr < ROM_END_ADDR)copy_to_rom = 1; 41 | 42 | //if (copy_to_rom || spi_dma) { 43 | if ((copy_to_rom || spi_dma) && addr % 4 == 0) { 44 | return memSpiReadDma(dst, slen); 45 | } else { 46 | return memSpiReadPio(dst, slen); 47 | 48 | } 49 | 50 | } 51 | 52 | u8 memSpiReadPio(void *dst, u16 slen) { 53 | 54 | u16 i; 55 | u16 u; 56 | u8 *ptr8 = (u8 *) dst; 57 | 58 | 59 | 60 | for (i = 0; i < slen; i++) { 61 | 62 | evd_SDdatReadMode(1); 63 | for (u = 0; u < 65535; u++)if ((evd_SPI(0xff) & 0xf1) == 0xf0)break; 64 | evd_SDdatReadMode(0); 65 | if (u == 65535) { 66 | evd_spiSSOff(); 67 | return DISK_RD_FE_TOUT; 68 | } 69 | 70 | for (u = 0; u < 512; u++)*ptr8++ = evd_SPI(0xff); 71 | 72 | u = evd_isSDMode() ? 8 : 2; 73 | 74 | while (u--) { 75 | // console_printf("XRC: %02X", evd_SPI(0xff)); 76 | //console_printf("%02X\n", evd_SPI(0xff)); 77 | u--; 78 | evd_SPI(0xff); 79 | evd_SPI(0xff); 80 | } 81 | //evd_SPI(0xff); 82 | //evd_SPI(0xff); 83 | } 84 | 85 | 86 | return 0; 87 | } 88 | 89 | u8 memSpiReadDma(void *dst, u16 slen) { 90 | 91 | u8 resp = 0; 92 | u8 copy_to_rom = 0; 93 | u32 addr = (u32) dst; 94 | 95 | evd_SDdatReadMode(0); 96 | // console_printf("dma\n"); 97 | if (addr >= ROM_ADDR && addr < ROM_END_ADDR)copy_to_rom = 1; 98 | 99 | if (copy_to_rom) { 100 | 101 | return evd_mmcReadToCart(addr, slen); 102 | 103 | } else { 104 | 105 | resp = evd_mmcReadToCart(0, slen); 106 | dma_read_s(dst, ROM_ADDR, slen * 512); 107 | } 108 | 109 | 110 | return resp; 111 | } 112 | 113 | u8 memSpiWrite(const void *src) { 114 | 115 | u16 i; 116 | 117 | u8 *ptr8 = (u8 *) src; 118 | 119 | if ((u32) src >= ROM_ADDR && (u32) src < ROM_END_ADDR) { 120 | dma_read_s(mem_buff, (u32) src, 512); 121 | for (i = 0; i < 512; i++)mem_spi(mem_buff[i]); 122 | } else { 123 | for (i = 0; i < 512; i++)mem_spi(*ptr8++); 124 | } 125 | 126 | 127 | return 0; 128 | } 129 | 130 | void memSpiBusy() { 131 | 132 | while (evd_isSpiBusy()); 133 | 134 | } 135 | 136 | void memRomWrite32(u32 addr, u32 val) { 137 | 138 | vu32 *ptr = (u32 *) (addr + ROM_ADDR); 139 | vu8 tmp; 140 | 141 | tmp = *ptr; 142 | *ptr = val; 143 | tmp = *ptr; 144 | } 145 | 146 | u32 memRomRead32(u32 addr) { 147 | 148 | vu32 *ptr = (u32 *) (addr + ROM_ADDR); 149 | vu8 tmp; 150 | vu32 val; 151 | 152 | tmp = *ptr; 153 | val = *ptr; 154 | 155 | return val; 156 | } 157 | 158 | 159 | /* 160 | u8 mem_spi(u8 dat) { 161 | return evd_SPI(dat); 162 | } 163 | */ -------------------------------------------------------------------------------- /src/memorypak.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include "types.h" 11 | #include "mempak.h" 12 | #include "memorypak.h" 13 | #include "ff.h" 14 | #include "menu.h" 15 | #include "debug.h" 16 | #include "strlib.h" 17 | #include "sys.h" 18 | #include "localevar.h" 19 | #include "constants.h" 20 | 21 | enum MemoryPakFormat 22 | { 23 | None, 24 | DexDrive, 25 | Z64 26 | }; 27 | 28 | static uint8_t mempak_data[128 * 256]; 29 | char *mempak_path; 30 | 31 | char ___TranslateNotes(uint8_t *bNote, char *Text) 32 | { 33 | #pragma warning(disable : 4305 4309) 34 | char cReturn = 0x00; 35 | const char aSpecial[] = {0x21, 0x22, 0x23, 0x60, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x3A, 0x3D, 0x3F, 0x40, 0x74, 0xA9, 0xAE}; 36 | // { '!' , '\"', '#' , '`' , '*' , '+' , ',' , '-' , '.' , '/' , ':' , '=' , '?' , '>' , 'tm', '(r)','(c)' }; 37 | #pragma warning(default : 4305 4309) 38 | int i = 16; 39 | do 40 | { 41 | char b = bNote[i]; 42 | if ((b > 0) && i < 32) 43 | { 44 | if (b <= 0x0F) // translate Icons as Spaces 45 | *Text = 0x20; 46 | else if (b <= 0x19) // Numbers 47 | *Text = 0x20 + b; 48 | else if (b <= 0x33) // Characters 49 | *Text = 0x47 + b; 50 | else if (b <= 0x44) // special Symbols 51 | *Text = aSpecial[b - 0x34]; 52 | else if (b <= 0x94) // Japan 53 | *Text = 0xC0 + (b % 40); 54 | else // unknown 55 | *Text = (char)0xA4; 56 | 57 | ++i; 58 | ++Text; 59 | } 60 | else 61 | { 62 | *Text = '\0'; 63 | if (b) 64 | { 65 | i = 12; 66 | Text = &cReturn; 67 | } 68 | else 69 | i = 13; 70 | } 71 | } while (i != 13); 72 | 73 | return cReturn; 74 | } 75 | 76 | char ___CountBlocks(uint8_t *bMemPakBinary, char *aNoteSizes) 77 | { 78 | int wRemainingBlocks = 123; 79 | char bNextIndex; 80 | int i = 0; 81 | while (i < 16 && wRemainingBlocks <= 123) 82 | { 83 | aNoteSizes[i] = 0; 84 | bNextIndex = bMemPakBinary[0x307 + (i * 0x20)]; 85 | while ((bNextIndex >= 5) && (aNoteSizes[i] < wRemainingBlocks)) 86 | { 87 | aNoteSizes[i]++; 88 | bNextIndex = bMemPakBinary[0x101 + (bNextIndex * 2)]; 89 | } 90 | 91 | if (aNoteSizes[i] > wRemainingBlocks) 92 | wRemainingBlocks = 0xFF; 93 | else 94 | wRemainingBlocks -= aNoteSizes[i]; 95 | 96 | i++; 97 | } 98 | return wRemainingBlocks; 99 | } 100 | 101 | //old method to write a file to the mempak at controller 1 102 | int file_to_mpk(display_context_t disp, u8 *filename) 103 | { 104 | enum MemoryPakFormat memorypak_format; 105 | u8 buff[64]; 106 | 107 | FRESULT result; 108 | FIL file; 109 | UINT bytesread; 110 | result = f_open(&file, filename, FA_READ); 111 | 112 | if (result == FR_OK) 113 | { 114 | //int fsize = f_size(&file); 115 | 116 | u8 *pch; 117 | pch = strrchr(filename, '.'); 118 | sprintf(buff, "%s", (pch + 2)); 119 | 120 | if (strcmp(buff, "64") == 0) 121 | { 122 | TRACE(disp, "Dexdrive format"); 123 | memorypak_format = DexDrive; 124 | //skip header 125 | result = f_lseek ( 126 | &file, /* [IN] File object */ 127 | 4160 /* [IN] File read/write pointer */ 128 | ); 129 | } 130 | 131 | TRACE(disp, "Z64 format"); 132 | memorypak_format = Z64; 133 | 134 | result = 135 | f_read ( 136 | &file, /* [IN] File object */ 137 | mempak_data, /* [OUT] Buffer to store read data */ 138 | 32768, /* [IN] Number of bytes to read */ 139 | &bytesread /* [OUT] Number of bytes read */ 140 | ); 141 | 142 | f_close(&file); 143 | 144 | int err = 0; 145 | for (int j = 0; j < 128; j++) 146 | { 147 | err |= write_mempak_sector(0, j, &mempak_data[j * MEMPAK_BLOCK_SIZE]); 148 | } 149 | } 150 | else 151 | { 152 | memorypak_format = None; 153 | } 154 | 155 | return (int)memorypak_format; //TODO: should return enum 156 | } 157 | 158 | void view_mpk_file(display_context_t disp, char *mpk_filename) 159 | { 160 | u8 buff[64]; 161 | 162 | FRESULT result; 163 | FIL file; 164 | UINT bytesread; 165 | result = f_open(&file, mpk_filename, FA_READ); 166 | 167 | if (result == FR_OK) 168 | { 169 | //int fsize = f_size(&file); 170 | 171 | u8 *pch; 172 | pch = strrchr(mpk_filename, '.'); 173 | sprintf(buff, "%s", (pch + 2)); 174 | 175 | if (strcmp(buff, "64") == 0) //DEXDRIVE format 176 | { 177 | //skip header 178 | result = f_lseek ( 179 | &file, /* [IN] File object */ 180 | 4160 /* [IN] File read/write pointer */ 181 | ); 182 | } 183 | 184 | result = 185 | f_read ( 186 | &file, /* [IN] File object */ 187 | mempak_data, /* [OUT] Buffer to store read data */ 188 | 32768, /* [IN] Number of bytes to read */ 189 | &bytesread /* [OUT] Number of bytes read */ 190 | ); 191 | 192 | 193 | f_close(&file); 194 | 195 | printText(fcontents, 11, 5, disp); 196 | printText(" ", 11, -1, disp); 197 | 198 | int notes_c = 0; 199 | 200 | char szBuffer[58], 201 | cAppendix; 202 | int bFirstChar; 203 | 204 | int i = 0, 205 | nNotes = 0, 206 | iSum = 0, 207 | iRemainingBlocks; 208 | 209 | char aNoteSizes[16]; 210 | 211 | for (i = 0x10A; i < 0x200; i++) 212 | iSum += mempak_data[i]; 213 | 214 | if (((iSum % 256) == mempak_data[0x101])) 215 | { 216 | iRemainingBlocks = ___CountBlocks(mempak_data, aNoteSizes); 217 | 218 | if (iRemainingBlocks <= 123) 219 | { 220 | for (notes_c = 0; notes_c < 16; notes_c++) 221 | { 222 | if (mempak_data[0x300 + (notes_c * 32)] || 223 | mempak_data[0x301 + (notes_c * 32)] || 224 | mempak_data[0x302 + (notes_c * 32)]) 225 | { 226 | cAppendix = ___TranslateNotes(&mempak_data[0x300 + (notes_c * 32)], szBuffer); 227 | 228 | if (cAppendix != '\0') 229 | { 230 | char *buf = szBuffer; 231 | 232 | int strLength = snprintf(0, 0, "%s. %c", buf, cAppendix); 233 | //assert(strLength >= 0); // TODO add proper error handling 234 | //szBuffer = malloc(sizeof(char) * (strLength + 1)); 235 | snprintf(szBuffer, strLength+1, "%s. %c", buf, cAppendix); 236 | } 237 | 238 | bFirstChar = 1; 239 | for (i = 0; i < (int)strlen(szBuffer); i++) 240 | { 241 | if (szBuffer[i] == ' ') 242 | bFirstChar = 1; 243 | else 244 | { 245 | if (bFirstChar && (szBuffer[i] >= 'a') && (szBuffer[i] <= 'z')) 246 | { 247 | bFirstChar = 0; 248 | szBuffer[i] -= 0x20; 249 | } 250 | } 251 | } 252 | printText(szBuffer, 11, -1, disp); 253 | 254 | switch (mempak_data[0x303 + (notes_c * 32)]) 255 | { 256 | case 0x00: 257 | sprintf(szBuffer, "None"); 258 | break; 259 | case 0x37: 260 | sprintf(szBuffer, "Beta"); 261 | break; 262 | case 0x41: 263 | sprintf(szBuffer, "NTSC"); 264 | break; 265 | case 0x44: 266 | sprintf(szBuffer, "Germany"); 267 | break; 268 | case 0x45: 269 | sprintf(szBuffer, "USA"); 270 | break; 271 | case 0x46: 272 | sprintf(szBuffer, "France"); 273 | break; 274 | case 0x49: 275 | sprintf(szBuffer, "Italy"); 276 | break; 277 | case 0x4A: 278 | sprintf(szBuffer, "Japan"); 279 | break; 280 | case 0x50: 281 | sprintf(szBuffer, "Europe"); 282 | break; 283 | case 0x53: 284 | sprintf(szBuffer, "Spain"); 285 | break; 286 | case 0x55: 287 | sprintf(szBuffer, "Australia"); 288 | break; 289 | case 0x58: 290 | case 0x59: 291 | sprintf(szBuffer, "PAL"); 292 | break; 293 | default: 294 | sprintf(szBuffer, "Unknown(%02X)", mempak_data[0x303 + (notes_c * 32)]); 295 | } 296 | 297 | sprintf(szBuffer, "%i", aNoteSizes[notes_c]); 298 | nNotes++; 299 | } 300 | } 301 | } 302 | 303 | int free_c = 0; 304 | for (free_c = nNotes; free_c < 16; free_c++) 305 | printText(freebock, 11, -1, disp); 306 | 307 | char buff[512]; 308 | printText(" ", 11, -1, disp); 309 | printText(freespace, 11, -1, disp); 310 | sprintf(buff, blocks, iRemainingBlocks); 311 | printText(buff, 11, -1, disp); 312 | } 313 | else 314 | { 315 | printText(emptyfile, 11, -1, disp); 316 | } 317 | } 318 | } 319 | 320 | void view_mpk(display_context_t disp) 321 | { 322 | int err; 323 | 324 | printText("Mempak content:", 11, 5, disp); 325 | struct controller_data output; 326 | get_accessories_present( &output); 327 | 328 | /* Make sure they don't have a rumble pak inserted instead */ 329 | switch (identify_accessory(0)) 330 | { 331 | case ACCESSORY_NONE: 332 | 333 | printText(" ", 11, -1, disp); 334 | printText("no Mempak", 11, -1, disp); 335 | break; 336 | 337 | case ACCESSORY_MEMPAK: 338 | if ((err = validate_mempak(0))) 339 | { 340 | if (err == -3) 341 | { 342 | printText(" ", 11, -1, disp); 343 | 344 | printText("not formatted", 11, -1, disp); 345 | } 346 | else 347 | { 348 | printText(" ", 11, -1, disp); 349 | printText("read error", 11, -1, disp); 350 | } 351 | } 352 | else 353 | { 354 | printText(" ", 11, -1, disp); 355 | for (int j = 0; j < 16; j++) 356 | { 357 | entry_structure_t entry; 358 | 359 | get_mempak_entry(0, j, &entry); 360 | 361 | if (entry.valid) 362 | { 363 | char tmp[512]; 364 | sprintf(tmp, "%s", entry.name); 365 | printText(tmp, 11, -1, disp); 366 | } 367 | else 368 | { 369 | printText("[free]", 11, -1, disp); 370 | } 371 | } 372 | 373 | char buff[512]; 374 | printText(" ", 11, -1, disp); 375 | printText("Free space:", 11, -1, disp); 376 | sprintf(buff, "%d blocks", get_mempak_free_space(0)); 377 | printText(buff, 11, -1, disp); 378 | } 379 | break; 380 | 381 | case ACCESSORY_RUMBLEPAK: 382 | printText("RumblePak inserted", 11, -1, disp); 383 | break; 384 | 385 | default: 386 | break; 387 | } 388 | } 389 | 390 | //old function to dump a mempak to a file 391 | void mpk_to_file(display_context_t disp, char *mpk_filename, int quick) 392 | { 393 | u8 buff[MAX_SUPPORTED_PATH_LEN]; 394 | u8 v = 0; 395 | 396 | if (quick) 397 | sprintf(buff,"/"ED64_FIRMWARE_PATH"/%s/%s", mempak_path, mpk_filename); 398 | else 399 | sprintf(buff, "/"ED64_FIRMWARE_PATH"/%s/%s.MPK", mempak_path, mpk_filename); 400 | 401 | FRESULT fr; 402 | FILINFO fno; 403 | 404 | fr = f_stat(buff, &fno); 405 | if(fr == FR_OK) 406 | { 407 | printText(filexist, 9, -1, disp); 408 | if (quick) 409 | printText(overridefile, 9, -1, disp); 410 | else 411 | while (fr == FR_OK) 412 | { 413 | sprintf(buff, "/"ED64_FIRMWARE_PATH"/%s/%s.%i.MPK", mempak_path, mpk_filename, v); 414 | 415 | fr = f_stat(buff, &fno); 416 | if (fr == FR_OK) 417 | v++; 418 | else 419 | break; 420 | } 421 | } 422 | 423 | FRESULT result; 424 | FIL file; 425 | result = f_open(&file, buff, FA_WRITE | FA_OPEN_ALWAYS); 426 | 427 | if (result == FR_OK) 428 | { 429 | controller_init(); 430 | 431 | int err = 0; 432 | for (int j = 0; j < 128; j++) 433 | { 434 | err |= read_mempak_sector(0, j, &mempak_data[j * 256]); 435 | } 436 | 437 | UINT bw; 438 | result = 439 | f_write ( 440 | &file, /* [IN] Pointer to the file object structure */ 441 | mempak_data, /* [IN] Pointer to the data to be written */ 442 | 32768, /* [IN] Number of bytes to write */ 443 | &bw /* [OUT] Pointer to the variable to return number of bytes written */ 444 | ); 445 | 446 | f_close(&file); 447 | 448 | 449 | sprintf(buff, fileMPK, mpk_filename, v); 450 | 451 | printText(buff, 9, -1, disp); 452 | printText(backupdone, 9, -1, disp); 453 | } 454 | } -------------------------------------------------------------------------------- /src/menu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "types.h" 3 | #include "debug.h" 4 | 5 | short int gCursorX; 6 | short int gCursorY; 7 | 8 | int text_offset = 0; 9 | 10 | void printText(char *msg, int x, int y, display_context_t dcon) 11 | { 12 | x = x + text_offset; 13 | 14 | if (x != -1) 15 | gCursorX = x; 16 | if (y != -1) 17 | gCursorY = y; 18 | 19 | if (dcon) 20 | graphics_draw_text(dcon, gCursorX * 8, gCursorY * 8, msg); 21 | 22 | gCursorY++; 23 | if (gCursorY > 29) 24 | { 25 | gCursorY = 0; 26 | gCursorX++; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/menu_about.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "types.h" 4 | #include "menu.h" 5 | #include "version.h" 6 | #include "main.h" 7 | #include "everdrive.h" 8 | #include "localevar.h" 9 | 10 | 11 | void menu_about(display_context_t disp) 12 | { 13 | char version_str[32]; 14 | char firmware_str[32]; 15 | 16 | sprintf(version_str, "Altra 64: v%s", Altra64_GetVersionString()); 17 | printText(version_str, 9, 8, disp); //1 18 | sprintf(firmware_str, "ED64 firmware: v%03x", evd_getFirmVersion()); //2 19 | printText(firmware_str, 9, -1, disp); 20 | printText("by JonesAlmighty", 9, -1, disp); //3 21 | printText("Based on ALT64", 9, -1, disp); //4 22 | printText("Credits to:", 9, -1, disp); //5 23 | printText("Altra 64 Contibutors", 9, -1, disp); //6 24 | printText("", 9, -1, disp); //7 25 | printText("Libraries:", 9, -1, disp); //8 26 | printText("Libdragon", 9, -1, disp); //9 27 | printText("Libmikmod-N64", 9, -1, disp); //10 28 | printText("Libmad-N64", 9, -1, disp); //11 29 | printText("Libyaml", 9, -1, disp); //12 30 | printText(" ", 9, -1, disp); //13 31 | printText(znpage, 9, -1, disp); //14 32 | 33 | } //TODO: make scrolling text, should include libraries used. 34 | -------------------------------------------------------------------------------- /src/menu_controls.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "types.h" 5 | #include "menu.h" 6 | #include "version.h" 7 | #include "main.h" 8 | #include "everdrive.h" 9 | #include "localevar.h" 10 | 11 | void menu_controls(display_context_t disp) 12 | { 13 | printText(controlsmenucon, 4, 4, disp); 14 | printText(" ", 4, -1, disp); 15 | printText(showmpkmenu, 4, -1, disp); 16 | printText(" ", 4, -1, disp); 17 | printText(aboutscreen, 4, -1, disp); 18 | printText(" ", 4, -1, disp); 19 | printText(Astartromdirectory, 4, -1, disp); 20 | printText(Amempak, 4, -1, disp); 21 | printText(" ", 4, -1, disp); 22 | printText(Bbackcancel, 4, -1, disp); 23 | printText(" ", 4, -1, disp); 24 | printText(Startlastrom, 4, -1, disp); 25 | printText(" ", 4, -1, disp); 26 | printText(CLEFT, 4, -1, disp); 27 | printText(CLEFTVIEMPK, 4, -1, disp); 28 | printText(" ", 4, -1, disp); 29 | printText(CRIGHT, 4, -1, disp); 30 | printText(" ", 4, -1, disp); 31 | printText(CUP, 4, -1, disp); 32 | printText(" ", 4, -1, disp); 33 | printText(CDOWN, 4, -1, disp); 34 | printText(" ", 4, -1, disp); 35 | printText(LplusR, 4, -1, disp); 36 | } 37 | -------------------------------------------------------------------------------- /src/menu_delete.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "types.h" 5 | #include "menu.h" 6 | #include "version.h" 7 | #include "main.h" 8 | #include "everdrive.h" 9 | #include "localevar.h" 10 | 11 | 12 | void menu_delete(display_context_t disp, bool isdir) 13 | { 14 | if (isdir) 15 | { 16 | printText(directoriesNO, 7, 14, disp); 17 | printText(bexit, 13, 16, disp); 18 | } 19 | else 20 | { 21 | printText(deletefile, 10, 14, disp); 22 | printText(aconfirm, 13, 16, disp); 23 | printText(bcancel, 13, 17, disp); 24 | } 25 | } -------------------------------------------------------------------------------- /src/mp3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "mp3.h" 7 | #include "ff.h" 8 | 9 | 10 | static struct mad_stream Stream; 11 | static struct mad_header Header; 12 | static struct mad_frame Frame; 13 | static struct mad_synth Synth; 14 | static mad_timer_t Timer; 15 | 16 | typedef struct { 17 | short left; 18 | short right; 19 | } Sample; 20 | 21 | static int eos; 22 | 23 | #define INPUT_BUFFER_SIZE 2048 24 | static unsigned char fileBuffer[INPUT_BUFFER_SIZE]; 25 | static unsigned char readBuffer[INPUT_BUFFER_SIZE]; 26 | static int useReadBuffer; 27 | static int readPos; 28 | static UINT readLen; 29 | static int samplesRead; 30 | 31 | static FIL mp3File; 32 | static FRESULT mp3Fd; 33 | 34 | 35 | static int mp3_seek(int offset, int whence) 36 | { 37 | DWORD offs = 0; 38 | switch (whence) 39 | { 40 | case SEEK_SET: 41 | offs = offset; 42 | break; 43 | case SEEK_CUR: 44 | offs = mp3File.fptr + offset; 45 | break; 46 | case SEEK_END: 47 | offs = f_size(&mp3File) + offset; 48 | break; 49 | } 50 | f_lseek(&mp3File, offs); 51 | return offs; 52 | } 53 | 54 | static int mp3_size() 55 | { 56 | return f_size(&mp3File); 57 | } 58 | 59 | static int mp3_read(unsigned char *ptr, int size) 60 | { 61 | UINT ts; 62 | if (useReadBuffer) 63 | { 64 | int total = 0; 65 | while (size) 66 | { 67 | if (!readLen) 68 | { 69 | f_read ( 70 | &mp3File, /* [IN] File object */ 71 | readBuffer, /* [OUT] Buffer to store read data */ 72 | INPUT_BUFFER_SIZE, /* [IN] Number of bytes to read */ 73 | &readLen /* [OUT] Number of bytes read */ 74 | ); 75 | readPos = 0; 76 | if (readLen == 0) 77 | return total; // EOF 78 | } 79 | int rlen = (size= MAD_F_ONE) 214 | return (32767); 215 | if (Fixed <= -MAD_F_ONE) 216 | return (-32768); 217 | 218 | /* Conversion. */ 219 | Fixed = Fixed >> (MAD_F_FRACBITS - 15); 220 | 221 | return ((short)Fixed); 222 | } 223 | 224 | static int fillFileBuffer() 225 | { 226 | int leftOver = Stream.bufend - Stream.next_frame; 227 | int want = INPUT_BUFFER_SIZE - leftOver; 228 | 229 | // move left-over bytes 230 | if (leftOver > 0) 231 | memmove(fileBuffer, fileBuffer + want, leftOver); 232 | 233 | // fill remainder of buffer 234 | unsigned char* bufferPos = fileBuffer + leftOver; 235 | while (want > 0) 236 | { 237 | int got = mp3_read(bufferPos, want); 238 | if (got <= 0) 239 | return 1; // EOF 240 | 241 | want -= got; 242 | bufferPos += got; 243 | } 244 | return 0; 245 | } 246 | 247 | static void decode() 248 | { 249 | while (mad_frame_decode(&Frame, &Stream) == -1) 250 | { 251 | if ((Stream.error == MAD_ERROR_BUFLEN) || (Stream.error == MAD_ERROR_BUFPTR)) 252 | { 253 | if (fillFileBuffer()) 254 | { 255 | eos = 1; 256 | break; 257 | } 258 | mad_stream_buffer(&Stream, fileBuffer, INPUT_BUFFER_SIZE); 259 | } 260 | else if (Stream.error == MAD_ERROR_LOSTSYNC) 261 | { 262 | /* LOSTSYNC - due to ID3 tags? */ 263 | int tagsize = id3_tag_size(Stream.this_frame, Stream.bufend - Stream.this_frame); 264 | if (tagsize > 0) 265 | { 266 | mad_stream_skip (&Stream, tagsize); 267 | continue; 268 | } 269 | } 270 | } 271 | 272 | mad_timer_add(&Timer, Frame.header.duration); 273 | mad_synth_frame(&Synth, &Frame); 274 | } 275 | 276 | static void convertLeftSamples(Sample* first, Sample* last, const mad_fixed_t* src) 277 | { 278 | for (Sample *dst = first; dst != last; ++dst) 279 | dst->left = convertSample(*src++); 280 | } 281 | 282 | static void convertRightSamples(Sample* first, Sample* last, const mad_fixed_t* src) 283 | { 284 | for (Sample *dst = first; dst != last; ++dst) 285 | dst->right = convertSample(*src++); 286 | } 287 | 288 | static void MP3_Callback(void *buffer, unsigned int samplesToWrite) 289 | { 290 | Sample *destination = (Sample*)buffer; 291 | 292 | while (samplesToWrite > 0) 293 | { 294 | while (!eos && (Synth.pcm.length == 0)) 295 | decode(); 296 | 297 | if (eos) 298 | { 299 | // done 300 | memset(destination, 0, samplesToWrite*4); 301 | break; 302 | } 303 | 304 | unsigned int samplesAvailable = Synth.pcm.length - samplesRead; 305 | if (samplesAvailable > samplesToWrite) 306 | { 307 | convertLeftSamples(destination, destination + samplesToWrite, &Synth.pcm.samples[0][samplesRead]); 308 | convertRightSamples(destination, destination + samplesToWrite, &Synth.pcm.samples[1][samplesRead]); 309 | 310 | samplesRead += samplesToWrite; 311 | samplesToWrite = 0; 312 | } 313 | else 314 | { 315 | convertLeftSamples(destination, destination + samplesAvailable, &Synth.pcm.samples[0][samplesRead]); 316 | convertRightSamples(destination, destination + samplesAvailable, &Synth.pcm.samples[1][samplesRead]); 317 | 318 | destination += samplesAvailable; 319 | samplesToWrite -= samplesAvailable; 320 | 321 | samplesRead = 0; 322 | decode(); 323 | } 324 | } 325 | } 326 | 327 | static void MP3_Init() 328 | { 329 | /* First the structures used by libmad must be initialized. */ 330 | mad_stream_init(&Stream); 331 | mad_header_init(&Header); 332 | mad_frame_init(&Frame); 333 | mad_synth_init(&Synth); 334 | mad_timer_reset(&Timer); 335 | } 336 | 337 | static void MP3_Exit() 338 | { 339 | mad_synth_finish(&Synth); 340 | mad_header_finish(&Header); 341 | mad_frame_finish(&Frame); 342 | mad_stream_finish(&Stream); 343 | } 344 | 345 | static void MP3_GetInfo(long long *samples, int *rate) 346 | { 347 | unsigned long FrameCount = 0; 348 | int bufferSize = 1024*512; 349 | unsigned char *localBuffer; 350 | long bytesread = 0; 351 | double totalBitrate = 0.0; 352 | double mediumBitrate = 0.0; 353 | struct mad_stream stream; 354 | struct mad_header header; 355 | long size = mp3_size(); 356 | long count = size; 357 | 358 | mad_stream_init (&stream); 359 | mad_header_init (&header); 360 | 361 | localBuffer = (unsigned char *)malloc(bufferSize); 362 | 363 | for (int i=0; i<3; i++) 364 | { 365 | memset(localBuffer, 0, bufferSize); 366 | 367 | if (count > bufferSize) 368 | bytesread = mp3_read(localBuffer, bufferSize); 369 | else 370 | bytesread = mp3_read(localBuffer, count); 371 | count -= bytesread; 372 | if (!bytesread) 373 | break; // ran out of data 374 | 375 | mad_stream_buffer (&stream, localBuffer, bytesread); 376 | 377 | for ( ;; ) 378 | { 379 | if (mad_header_decode(&header, &stream) == -1) 380 | { 381 | if (stream.buffer == NULL || stream.error == MAD_ERROR_BUFLEN) 382 | break; 383 | else if (MAD_RECOVERABLE(stream.error)) 384 | { 385 | continue; 386 | } 387 | else 388 | { 389 | break; 390 | } 391 | } 392 | if (FrameCount++ == 0) 393 | *rate = header.samplerate; 394 | totalBitrate += header.bitrate; 395 | } 396 | } 397 | 398 | mediumBitrate = totalBitrate / (double)FrameCount; 399 | int secs = size * 8 / mediumBitrate; 400 | *samples = *rate * secs; 401 | 402 | mad_header_finish (&header); 403 | mad_stream_finish (&stream); 404 | 405 | if (localBuffer) 406 | free(localBuffer); 407 | 408 | mp3_seek(0, SEEK_SET); 409 | } 410 | 411 | 412 | void mp3_Start(char *fname, long long *samples, int *rate, int *channels) 413 | { 414 | 415 | mp3Fd = f_open(&mp3File, fname, FA_READ); 416 | 417 | if (mp3Fd == FR_OK) 418 | { 419 | useReadBuffer = 0; 420 | MP3_GetInfo(samples, rate); 421 | *channels = 2; 422 | 423 | MP3_Init(); 424 | MP3_SkipHdr(); 425 | eos = readLen = readPos = 0; 426 | useReadBuffer = 1; 427 | return; 428 | } 429 | 430 | *samples = 0; 431 | return; 432 | } 433 | 434 | void mp3_Stop(void) 435 | { 436 | MP3_Exit(); 437 | if (mp3Fd == FR_OK) 438 | { 439 | f_close(&mp3File); 440 | } 441 | mp3Fd = FR_NO_FILE; 442 | } 443 | 444 | int mp3_Update(char *buf, int bytes) 445 | { 446 | MP3_Callback(buf, bytes/4); 447 | return eos ? 0 : 1; 448 | } -------------------------------------------------------------------------------- /src/rom.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 The Altra64 project contributors 2 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #include "sram.h" 7 | #include "everdrive.h" 8 | #include "sys.h" 9 | #include "rom.h" 10 | #include "cic.h" 11 | #include 12 | #include 13 | 14 | void pif_boot() 15 | { 16 | //TODO: implement 17 | } 18 | 19 | 20 | 21 | int is_valid_rom(unsigned char *buffer) { 22 | /* Test if rom is a native .z64 image with header 0x80371240. [ABCD] */ 23 | if((buffer[0]==0x80)&&(buffer[1]==0x37)&&(buffer[2]==0x12)&&(buffer[3]==0x40)) 24 | return 0; 25 | /* Test if rom is a byteswapped .v64 image with header 0x37804012. [BADC] */ 26 | else if((buffer[0]==0x37)&&(buffer[1]==0x80)&&(buffer[2]==0x40)&&(buffer[3]==0x12)) 27 | return 1; 28 | /* Test if rom is a wordswapped .n64 image with header 0x40123780. [DCBA] */ 29 | else if((buffer[0]==0x40)&&(buffer[1]==0x12)&&(buffer[2]==0x37)&&(buffer[3]==0x80)) 30 | return 2; 31 | else 32 | return 0; 33 | } 34 | 35 | void swap_header(unsigned char* header, int loadlength) { 36 | unsigned char temp; 37 | int i; 38 | 39 | /* Btyeswap if .v64 image. */ 40 | if( header[0]==0x37) { 41 | for (i = 0; i < loadlength; i+=2) { 42 | temp= header[i]; 43 | header[i]= header[i+1]; 44 | header[i+1]=temp; 45 | } 46 | } 47 | /* Wordswap if .n64 image. */ 48 | else if( header[0]==0x40) { 49 | for (i = 0; i < loadlength; i+=4) { 50 | temp= header[i]; 51 | header[i]= header[i+3]; 52 | header[i+3]=temp; 53 | temp= header[i+1]; 54 | header[i+1]= header[i+2]; 55 | header[i+2]=temp; 56 | } 57 | } 58 | } 59 | 60 | u8 getCicType(u8 bios_cic) { 61 | u8 cic_buff[2048]; 62 | volatile u8 cic_chip; 63 | volatile u32 val; 64 | if (bios_cic) { 65 | evd_setCfgBit(ED_CFG_SDRAM_ON, 0); 66 | sleep(10); 67 | val = *(u32 *) 0xB0000170; 68 | dma_read_s(cic_buff, 0xB0000040, 1024); 69 | cic_chip = get_cic(cic_buff); 70 | evd_setCfgBit(ED_CFG_SDRAM_ON, 1); 71 | sleep(10); 72 | } 73 | else { 74 | val = *(u32 *) 0xB0000170; 75 | dma_read_s(cic_buff, 0xB0000040, 1024); 76 | cic_chip = get_cic(cic_buff); 77 | } 78 | 79 | return cic_chip; 80 | } 81 | 82 | //send game id for n64digital hdmi mod 83 | //source: https://gitlab.com/pixelfx-public/n64-game-id 84 | void send_game_id(uint8_t* crc_hi, uint8_t* crc_lo, uint8_t media_format, uint8_t country_id) 85 | { 86 | #define N64_CONTROLLER_PORT 0 87 | #define GAME_ID_COMMAND 0x1D 88 | 89 | uint8_t out[10]; 90 | uint8_t dummy[1]; 91 | 92 | memcpy(out, crc_hi, 4); 93 | memcpy(&out[4], crc_lo, 4); 94 | 95 | out[8] = media_format; 96 | out[9] = country_id; 97 | 98 | execute_raw_command(N64_CONTROLLER_PORT, GAME_ID_COMMAND, sizeof(out), sizeof(dummy), out, dummy); 99 | } 100 | 101 | // get the country and region string from country code "headerdata[0x3E]" (region type via www.bubblevision.com/PAL-NTSC.htm) 102 | // NTSC, PAL, MPAL or unknown 103 | void get_country_and_region(unsigned char ccode, char* region_string) 104 | { 105 | switch (ccode) 106 | { 107 | case '7': strcpy(region_string, "Beta"); break; 108 | case 'A': strcpy(region_string, "Asia-NTSC"); break; 109 | case 'B': strcpy(region_string, "Brazil-MPAL"); break; 110 | case 'C': strcpy(region_string, "China-PAL"); break; 111 | case 'D': strcpy(region_string, "Germany-PAL"); break; 112 | case 'E': strcpy(region_string, "NorthAmerica-NTSC"); break; 113 | case 'F': strcpy(region_string, "France-PAL"); break; 114 | case 'G': strcpy(region_string, "Gateway64-NTSC"); break; 115 | case 'H': strcpy(region_string, "Netherlands-PAL"); break; 116 | case 'I': strcpy(region_string, "Italy-PAL"); break; 117 | case 'J': strcpy(region_string, "Japan-NTSC"); break; 118 | case 'K': strcpy(region_string, "Korea-NTSC"); break; 119 | case 'L': strcpy(region_string, "Gateway64-PAL"); break; 120 | case 'N': strcpy(region_string, "Canada-NTSC"); break; 121 | case 'P': strcpy(region_string, "Europe-PAL"); break; 122 | case 'S': strcpy(region_string, "Spain-PAL"); break; 123 | case 'U': strcpy(region_string, "Australia-PAL"); break; 124 | case 'W': strcpy(region_string, "Scandinavia-PAL"); break; 125 | case 'X': strcpy(region_string, "Europe-PAL"); break; 126 | case 'Y': strcpy(region_string, "Europe-PAL"); break; 127 | case 'Z': strcpy(region_string, "Europe-PAL"); break; 128 | default: strcpy(region_string, "No Country"); 129 | } 130 | } 131 | 132 | // get the region from country code "headerdata[0x3E]" (region type via www.bubblevision.com/PAL-NTSC.htm) 133 | unsigned char get_region(unsigned char ccode) 134 | { 135 | switch (ccode) 136 | { 137 | case '7': return REGION_UNKNOWN; 138 | case 'A': return REGION_NTSC; 139 | case 'B': return REGION_PAL_M; 140 | case 'C': return REGION_PAL; 141 | case 'D': return REGION_PAL; 142 | case 'E': return REGION_NTSC; 143 | case 'F': return REGION_PAL; 144 | case 'G': return REGION_NTSC; 145 | case 'H': return REGION_PAL; 146 | case 'I': return REGION_PAL; 147 | case 'J': return REGION_NTSC; 148 | case 'K': return REGION_NTSC; 149 | case 'L': return REGION_PAL; 150 | case 'N': return REGION_NTSC; 151 | case 'P': return REGION_PAL; 152 | case 'S': return REGION_PAL; 153 | case 'U': return REGION_PAL; 154 | case 'W': return REGION_PAL; 155 | case 'X': return REGION_PAL; 156 | case 'Y': return REGION_PAL; 157 | case 'Z': return REGION_PAL; 158 | default: return REGION_UNKNOWN; 159 | } 160 | return REGION_UNKNOWN; 161 | } -------------------------------------------------------------------------------- /src/sound.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | #define SOUND_ENABLED 6 | #if !defined(SOUND_ENABLED) 7 | 8 | void sndInit(void) 9 | { 10 | } 11 | 12 | void sndPlayBGM(char* filename) 13 | { 14 | } 15 | 16 | void sndStopAll(void) 17 | { 18 | } 19 | 20 | void sndPlaySFX(char* filename) 21 | { 22 | } 23 | 24 | void sndUpdate(void) 25 | { 26 | } 27 | 28 | #else 29 | 30 | #include 31 | #include //needed for audio_get_frequency() 32 | #include "hashtable.h" 33 | 34 | MODULE *moduleBGM = NULL; 35 | 36 | /* sound effects */ 37 | hashtable* samples = NULL; 38 | 39 | /* voices */ 40 | SBYTE voiceSFX; 41 | 42 | void sndInit(void) 43 | { 44 | samples = hashtable_create(); 45 | 46 | /* register all the drivers */ 47 | MikMod_RegisterAllDrivers(); 48 | MikMod_RegisterAllLoaders(); 49 | 50 | /* initialize the library */ 51 | md_mode = 0; 52 | md_mode |= DMODE_16BITS; 53 | md_mode |= DMODE_SOFT_MUSIC; 54 | md_mode |= DMODE_SOFT_SNDFX; 55 | md_mode |= DMODE_INTERP; 56 | 57 | md_mixfreq = audio_get_frequency(); 58 | 59 | MikMod_Init(""); 60 | 61 | /* reserve 2 voices for sound effects */ 62 | MikMod_SetNumVoices(-1, 2); 63 | 64 | /* get ready to play */ 65 | MikMod_EnableOutput(); 66 | 67 | 68 | } 69 | 70 | void sndPlayBGM(char* filename) 71 | { 72 | if (Player_Active()) 73 | { 74 | Player_Stop(); 75 | } 76 | Player_Free(moduleBGM); 77 | moduleBGM = NULL; 78 | 79 | moduleBGM = Player_Load(filename, 64, 0); 80 | 81 | if (moduleBGM) 82 | { 83 | Player_Start(moduleBGM); 84 | Player_SetVolume(80); 85 | } 86 | } 87 | 88 | void sndStopAll(void) 89 | { 90 | Voice_Stop(voiceSFX); 91 | Player_Stop(); 92 | MikMod_DisableOutput(); 93 | 94 | int index = 0; 95 | while (index < samples->capacity) { 96 | Sample_Free(samples->body[index].value); 97 | index = index + 1; 98 | } 99 | 100 | hashtable_destroy(samples); 101 | 102 | Player_Free(moduleBGM); 103 | moduleBGM = NULL; 104 | 105 | samples = hashtable_create(); 106 | //MikMod_Exit(); //I dont think we should ever exit as that would mean reinitialising?! 107 | } 108 | 109 | void sndPlaySFX(char* filename) 110 | { 111 | if (!Voice_Stopped(voiceSFX)) 112 | { 113 | Voice_Stop(voiceSFX); 114 | } 115 | 116 | 117 | if (hashtable_get(samples, filename) == NULL) 118 | { 119 | hashtable_set(samples, filename, Sample_Load(filename)); 120 | } 121 | 122 | //audio_write_silence(); 123 | Voice_SetVolume(voiceSFX, 800); 124 | voiceSFX = Sample_Play(hashtable_get(samples, filename), 0, 0); 125 | 126 | MikMod_Update(); //force an update so that the voice is registered as playing! 127 | 128 | } 129 | 130 | void sndUpdate(void) 131 | { 132 | if (!Voice_Stopped(voiceSFX) || Player_Active()) 133 | { 134 | MikMod_Update(); 135 | 136 | } 137 | } 138 | #endif 139 | -------------------------------------------------------------------------------- /src/sram.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #include 8 | #include 9 | 10 | #include "sys.h" 11 | #include "utils.h" 12 | #include "sram.h" 13 | #include "rom.h" 14 | 15 | 16 | void PI_Init(void) { 17 | PI_DMAWait(); 18 | IO_WRITE(PI_STATUS_REG, 0x03); 19 | } 20 | 21 | // Inits PI for sram transfer 22 | void PI_Init_SRAM(void) { 23 | 24 | 25 | IO_WRITE(PI_BSD_DOM2_LAT_REG, 0x05); 26 | IO_WRITE(PI_BSD_DOM2_PWD_REG, 0x0C); 27 | IO_WRITE(PI_BSD_DOM2_PGS_REG, 0x0D); 28 | IO_WRITE(PI_BSD_DOM2_RLS_REG, 0x02); 29 | 30 | } 31 | 32 | void PI_DMAWait(void) { 33 | 34 | 35 | /*PI DMA wait 36 | 37 | 1. Read PI_STATUS_REG then AND it with 0x3, if its true... then wait until 38 | it is not true. 39 | */ 40 | 41 | while (IO_READ(PI_STATUS_REG) & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)); 42 | } 43 | 44 | 45 | void PI_DMAFromSRAM(void *dest, u32 offset, u32 size) { 46 | 47 | 48 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest)); 49 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset)); 50 | asm volatile ("" : : : "memory"); 51 | IO_WRITE(PI_WR_LEN_REG, (size - 1)); 52 | asm volatile ("" : : : "memory"); 53 | 54 | 55 | /* 56 | PI_DMAWait(); 57 | 58 | IO_WRITE(PI_STATUS_REG, 0x03); 59 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest)); 60 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset)); 61 | _data_cache_invalidate_all(); 62 | IO_WRITE(PI_WR_LEN_REG, (size - 1)); 63 | */ 64 | } 65 | 66 | 67 | void PI_DMAToSRAM(void *src, u32 offset, u32 size) { //void* 68 | PI_DMAWait(); 69 | 70 | IO_WRITE(PI_STATUS_REG, 2); 71 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(src)); 72 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset)); 73 | _data_cache_invalidate_all(); 74 | //data_cache_hit_writeback_invalidate(src,size); 75 | 76 | /* Write back . nusys - only writeback 77 | osWritebackDCache((void*)buf_ptr, (s32)size); 78 | */ 79 | //libdragon equivalent 80 | // data_cache_hit_writeback (src, size); 81 | 82 | IO_WRITE(PI_RD_LEN_REG, (size - 1)); 83 | } 84 | 85 | void PI_DMAFromCart(void* dest, void* src, u32 size) { 86 | PI_DMAWait(); 87 | 88 | IO_WRITE(PI_STATUS_REG, 0x03); 89 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest)); 90 | IO_WRITE(PI_CART_ADDR_REG, K0_TO_PHYS(src)); 91 | //_data_cache_invalidate_all(); 92 | IO_WRITE(PI_WR_LEN_REG, (size - 1)); 93 | } 94 | 95 | 96 | void PI_DMAToCart(void* dest, void* src, u32 size) { 97 | PI_DMAWait(); 98 | 99 | IO_WRITE(PI_STATUS_REG, 0x02); 100 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(src)); 101 | IO_WRITE(PI_CART_ADDR_REG, K0_TO_PHYS(dest)); 102 | //_data_cache_invalidate_all(); 103 | IO_WRITE(PI_RD_LEN_REG, (size - 1)); 104 | } 105 | 106 | 107 | // Wrapper to support unaligned access to memory 108 | void PI_SafeDMAFromCart(void *dest, void *src, u32 size) { 109 | if (!dest || !src || !size) return; 110 | 111 | u32 unalignedSrc = ((u32)src) % 2; 112 | u32 unalignedDest = ((u32)dest) % 8; 113 | 114 | //FIXME: Do i really need to check if size is 16bit aligned? 115 | if (!unalignedDest && !unalignedSrc && !(size % 2)) { 116 | PI_DMAFromCart(dest, src, size); 117 | PI_DMAWait(); 118 | 119 | return; 120 | } 121 | 122 | void* newSrc = (void*)(((u32)src) - unalignedSrc); 123 | u32 newSize = (size + unalignedSrc) + ((size + unalignedSrc) % 2); 124 | 125 | u8 *buffer = memalign(8, newSize); 126 | PI_DMAFromCart(buffer, newSrc, newSize); 127 | PI_DMAWait(); 128 | 129 | memcpy(dest, (buffer + unalignedSrc), size); 130 | 131 | free(buffer); 132 | } 133 | 134 | -------------------------------------------------------------------------------- /src/strlib.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #include "strlib.h" 8 | #include "types.h" 9 | 10 | char *strcpytrim(char *d, // destination 11 | char *s, // source 12 | int mode, 13 | char *delim 14 | ) { 15 | char *o = d; // save orig 16 | char *e = 0; // end space ptr. 17 | char dtab[256] = {0}; 18 | if (!s || !d) return 0; 19 | 20 | if (!delim) delim = " \t\n\f"; 21 | while (*delim) 22 | dtab[*delim++] = 1; 23 | 24 | while ( (*d = *s++) != 0 ) { 25 | if (!dtab[*d]) { // Not a match char 26 | e = 0; // Reset end pointer 27 | } else { 28 | if (!e) e = d; // Found first match. 29 | 30 | if ( mode == STRLIB_MODE_ALL || ((mode != STRLIB_MODE_RIGHT) && (d == o)) ) 31 | continue; 32 | } 33 | d++; 34 | } 35 | if (mode != STRLIB_MODE_LEFT && e) { // for everything but trim_left, delete trailing matches. 36 | *e = 0; 37 | } 38 | return o; 39 | } 40 | 41 | // perhaps these could be inlined in strlib.h 42 | char *strtriml(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_LEFT, 0); } 43 | char *strtrimr(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_RIGHT, 0); } 44 | char *strtrim(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_BOTH, 0); } 45 | char *strstrlibkill(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_ALL, 0); } 46 | 47 | char *triml(char *s) { return strcpytrim(s, s, STRLIB_MODE_LEFT, 0); } 48 | char *trimr(char *s) { return strcpytrim(s, s, STRLIB_MODE_RIGHT, 0); } 49 | char *trim(char *s) { return strcpytrim(s, s, STRLIB_MODE_BOTH, 0); } 50 | char *strlibkill(char *s) { return strcpytrim(s, s, STRLIB_MODE_ALL, 0); } 51 | 52 | u16 strcon(u8 *str1, u8 *str2, u8 *dst, u16 max_len) { 53 | 54 | u16 len = 0; 55 | max_len -= 1; 56 | 57 | while (*str1 != 0 && len < max_len) { 58 | *dst++ = *str1++; 59 | len++; 60 | } 61 | 62 | while (*str2 != 0 && len < max_len) { 63 | *dst++ = *str2++; 64 | len++; 65 | } 66 | *dst++ = 0; 67 | return len; 68 | 69 | } 70 | 71 | u8 streq(u8 *str1, u8 *str2) { 72 | 73 | u8 s1; 74 | u8 s2; 75 | 76 | for (;;) { 77 | s1 = *str1++; 78 | s2 = *str2++; 79 | if (s1 >= 'a' && s1 <= 'z')s1 -= 0x20; 80 | if (s2 >= 'a' && s2 <= 'z')s2 -= 0x20; 81 | 82 | if (s1 != s2) return 0; 83 | 84 | if (*str1 == 0 && *str2 == 0)return 1; 85 | } 86 | } 87 | 88 | u8 streql(u8 *str1, u8 *str2, u8 len) { 89 | 90 | u8 s1; 91 | u8 s2; 92 | while (len--) { 93 | 94 | s1 = *str1++; 95 | s2 = *str2++; 96 | if (s1 >= 'a' && s1 <= 'z')s1 -= 0x20; 97 | if (s2 >= 'a' && s2 <= 'z')s2 -= 0x20; 98 | 99 | if (s1 != s2) return 0; 100 | } 101 | 102 | return 1; 103 | } 104 | 105 | u16 strContain(u8 *target, u8 *str) { 106 | 107 | u16 targ_len = slen(target); 108 | u16 eq_len; 109 | 110 | 111 | for (eq_len = 0; eq_len < targ_len;) { 112 | 113 | if (*str == 0)return 0; 114 | if (*str++ == target[eq_len]) { 115 | eq_len++; 116 | } else { 117 | eq_len = 0; 118 | } 119 | } 120 | 121 | if (eq_len != targ_len)return 0; 122 | return 1; 123 | 124 | } 125 | 126 | u8 slen(u8 *str) { 127 | 128 | u8 len = 0; 129 | while (*str++)len++; 130 | return len; 131 | } 132 | 133 | u8 scopy(u8 *src, u8 *dst) { 134 | 135 | u8 len = 0; 136 | while (*src != 0) { 137 | *dst++ = *src++; 138 | len++; 139 | } 140 | *dst = 0; 141 | return len; 142 | } 143 | 144 | void strhicase(u8 *str, u8 len) { 145 | 146 | if (len) { 147 | while (len--) { 148 | if (*str >= 'a' && *str <= 'z')*str -= 0x20; 149 | str++; 150 | } 151 | } else { 152 | while (*str != 0) { 153 | if (*str >= 'a' && *str <= 'z')*str -= 0x20; 154 | str++; 155 | } 156 | } 157 | 158 | } -------------------------------------------------------------------------------- /src/sys.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include "sys.h" 11 | #include "rom.h" 12 | 13 | 14 | u32 asm_date; 15 | 16 | Options_st options; 17 | 18 | u32 native_tv_mode; 19 | 20 | void dma_read_s(void * ram_address, unsigned long pi_address, unsigned long len) { 21 | 22 | u32 buff[256]; 23 | 24 | u32 *bptr; 25 | 26 | u32 *rptr = (u32 *) ram_address; 27 | 28 | // if(len==32768) 29 | // rptr = (u32 *) 0x803F7988; 30 | 31 | u16 i; 32 | 33 | //u16 blen = 512; 34 | //if (len < 512)blen = len; 35 | //*(volatile u32*) 0x1FC007FC = 0x08; 36 | 37 | IO_WRITE(PI_STATUS_REG, 3); 38 | while (len) { 39 | dma_read(buff, pi_address, 512); 40 | while ((IO_READ(PI_STATUS_REG) & 3) != 0); 41 | //while ((*((volatile u32*) PI_STATUS_REG) & 0x02) != 1); 42 | data_cache_hit_invalidate(buff, 512); 43 | bptr = buff; 44 | for (i = 0; i < 512 && i < len; i += 4)*rptr++ = *bptr++; 45 | len = len < 512 ? 0 : len - 512; 46 | pi_address += 512; 47 | } 48 | } 49 | 50 | void dma_write_s(void * ram_address, unsigned long pi_address, unsigned long len) { 51 | 52 | 53 | //if(len==32768) 54 | //ram_address = (u32 *) 0x803F7988; 55 | 56 | 57 | data_cache_hit_writeback(ram_address, len); 58 | dma_write(ram_address, pi_address, len); 59 | 60 | 61 | 62 | } 63 | 64 | 65 | /* 66 | void showError(char *str, u32 code) { 67 | 68 | 69 | console_printf("%s%u\n", str, code); 70 | joyWait(); 71 | 72 | 73 | } 74 | */ 75 | void sleep(u32 ms) { 76 | 77 | u32 current_ms = get_ticks_ms(); 78 | 79 | while (get_ticks_ms() - current_ms < ms); 80 | 81 | } 82 | 83 | void dma_read_sram(void *dest, u32 offset, u32 size) { 84 | /* 85 | PI_DMAWait(); 86 | 87 | IO_WRITE(PI_STATUS_REG, 0x03); 88 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest)); 89 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset)); 90 | // data_cache_invalidate_all(); 91 | IO_WRITE(PI_WR_LEN_REG, (size - 1)); 92 | */ 93 | /* 0xA8000000 94 | * 0xb0000000 95 | * 0x4000000 96 | * */ 97 | dma_read_s(dest, 0xA8000000 + offset, size); 98 | //data_cache_invalidate(dest,size); 99 | 100 | } 101 | 102 | void dma_write_sram(void* src, u32 offset, u32 size) { 103 | /* 104 | PI_DMAWait(); 105 | 106 | IO_WRITE(PI_STATUS_REG, 0x02); 107 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(src)); 108 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset)); 109 | // data_cache_invalidate_all(); 110 | IO_WRITE(PI_RD_LEN_REG, (size - 1)); 111 | */ 112 | dma_write_s(src, 0xA8000000 + offset, size); 113 | 114 | } 115 | 116 | 117 | 118 | 119 | 120 | 121 | u32 ii; 122 | volatile u32 *pt; 123 | void clean(); 124 | 125 | #define MEM32(addr) *((volatile u32 *)addr) 126 | 127 | 128 | u8 STR_intToDecString(u32 val, u8 *str) { 129 | 130 | int len; 131 | 132 | if (val < 10)len = 1; 133 | else 134 | if (val < 100)len = 2; 135 | else 136 | if (val < 1000)len = 3; 137 | else 138 | if (val < 10000)len = 4; 139 | else 140 | if (val < 100000)len = 5; 141 | else 142 | if (val < 1000000)len = 6; 143 | else 144 | if (val < 10000000)len = 7; 145 | else 146 | if (val < 100000000)len = 8; 147 | else 148 | if (val < 1000000000)len = 9; 149 | else len = 10; 150 | 151 | str += len; 152 | str[0] = 0; 153 | if (val == 0)*--str = '0'; 154 | while (val) { 155 | 156 | *--str = '0' + val % 10; 157 | val /= 10; 158 | } 159 | 160 | 161 | return len; 162 | } 163 | 164 | void STR_intToDecStringMin(u32 val, u8 *str, u8 min_size) { 165 | 166 | int len; 167 | u8 i; 168 | 169 | if (val < 10)len = 1; 170 | else 171 | if (val < 100)len = 2; 172 | else 173 | if (val < 1000)len = 3; 174 | else 175 | if (val < 10000)len = 4; 176 | else 177 | if (val < 100000)len = 5; 178 | else 179 | if (val < 1000000)len = 6; 180 | else 181 | if (val < 10000000)len = 7; 182 | else 183 | if (val < 100000000)len = 8; 184 | else 185 | if (val < 1000000000)len = 9; 186 | else len = 10; 187 | 188 | if (len < min_size) { 189 | 190 | i = min_size - len; 191 | while (i--)str[i] = '0'; 192 | len = min_size; 193 | } 194 | str += len; 195 | str[0] = 0; 196 | if (val == 0)*--str = '0'; 197 | while (val) { 198 | 199 | *--str = '0' + val % 10; 200 | val /= 10; 201 | } 202 | } 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /src/usb.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | // See LICENSE file in the project root for full license information. 5 | // 6 | 7 | #include "everdrive.h" 8 | #include "sys.h" 9 | #include "rom.h" 10 | 11 | u8 cmdTest(); 12 | u8 cmdFill(); 13 | u8 cmdReadRom(); 14 | u8 cmdWriteRom(); 15 | 16 | u64 usb_buff[128]; 17 | u8 *usb_buff8; // = (u8 *) usb_buff; 18 | 19 | 20 | #define PI_BSD_DOM1_LAT_REG (PI_BASE_REG+0x14) 21 | 22 | /* PI dom1 pulse width (R/W): [7:0] domain 1 device R/W strobe pulse width */ 23 | #define PI_BSD_DOM1_PWD_REG (PI_BASE_REG+0x18) 24 | 25 | /* PI dom1 page size (R/W): [3:0] domain 1 device page size */ 26 | #define PI_BSD_DOM1_PGS_REG (PI_BASE_REG+0x1C) /* page size */ 27 | 28 | /* PI dom1 release (R/W): [1:0] domain 1 device R/W release duration */ 29 | #define PI_BSD_DOM1_RLS_REG (PI_BASE_REG+0x20) 30 | /* PI dom2 latency (R/W): [7:0] domain 2 device latency */ 31 | #define PI_BSD_DOM2_LAT_REG (PI_BASE_REG+0x24) /* Domain 2 latency */ 32 | 33 | /* PI dom2 pulse width (R/W): [7:0] domain 2 device R/W strobe pulse width */ 34 | #define PI_BSD_DOM2_PWD_REG (PI_BASE_REG+0x28) /* pulse width */ 35 | 36 | /* PI dom2 page size (R/W): [3:0] domain 2 device page size */ 37 | #define PI_BSD_DOM2_PGS_REG (PI_BASE_REG+0x2C) /* page size */ 38 | 39 | /* PI dom2 release (R/W): [1:0] domain 2 device R/W release duration */ 40 | #define PI_BSD_DOM2_RLS_REG (PI_BASE_REG+0x30) /* release duration */ 41 | 42 | #define PHYS_TO_K1(x) ((u32)(x)|0xA0000000) /* physical to kseg1 */ 43 | #define IO_WRITE(addr,data) (*(volatile u32*)PHYS_TO_K1(addr)=(u32)(data)) 44 | #define PI_BASE_REG 0x04600000 45 | 46 | extern u8 system_cic; 47 | 48 | u8 usbListener() { 49 | 50 | volatile u16 resp; 51 | volatile u8 cmd; 52 | usb_buff8 = (u8 *) usb_buff; 53 | 54 | 55 | if (evd_fifoRxf())return 0; 56 | 57 | resp = evd_fifoRd(usb_buff, 1); 58 | 59 | if (resp != 0) return 1; 60 | 61 | if (usb_buff8[0] != 'C' || usb_buff8[1] != 'M' || usb_buff8[2] != 'D')return 2; 62 | 63 | cmd = usb_buff8[3]; 64 | 65 | 66 | switch (cmd) { 67 | 68 | case 'R': 69 | resp = cmdReadRom(); 70 | if (resp)return 10; 71 | break; 72 | case 'W': 73 | resp = cmdWriteRom(); 74 | if (resp)return 11; 75 | break; 76 | case 'T': 77 | resp = cmdTest(); 78 | if (resp)return 12; 79 | break; 80 | case 'F': 81 | resp = cmdFill(); 82 | if (resp)return 13; 83 | break; 84 | case 'S': 85 | //IO_WRITE(PI_BSD_DOM1_PGS_REG, 0x0c); 86 | //IO_WRITE(PI_BSD_DOM1_PGS_REG, 0x80); 87 | //evdSetESaveType(SAVE_TYPE_EEP16k); 88 | //system_cic = CIC_6102; //TODO: re-enable 89 | evd_lockRegs(); 90 | IO_WRITE(PI_STATUS_REG, 3); 91 | sleep(2); 92 | pif_boot(); 93 | break; 94 | case 'D': 95 | //TODO: initiate debug session 96 | break; 97 | default: 98 | break; 99 | 100 | } 101 | 102 | 103 | return 0; 104 | } 105 | 106 | u8 cmdTest() { 107 | 108 | u16 resp; 109 | usb_buff8[3] = 'k'; 110 | resp = evd_fifoWr(usb_buff, 1); 111 | if (resp)return 1; 112 | 113 | return 0; 114 | 115 | } 116 | 117 | u8 cmdFill() { 118 | 119 | u16 resp; 120 | u32 i; 121 | //console_printf("fill...\n"); 122 | 123 | for (i = 0; i < 512; i++) { 124 | usb_buff8[i] = 0; 125 | } 126 | //console_printf("buff prepared\n"); 127 | //romFill(0, 0x200000, 0); //TODO: re-enable 128 | //console_printf("fill done\n"); 129 | 130 | usb_buff8[3] = 'k'; 131 | resp = evd_fifoWr(usb_buff, 1); 132 | 133 | if (resp)return 1; 134 | //console_printf("resp sent ok\n"); 135 | 136 | return 0; 137 | } 138 | 139 | u8 cmdReadRom() { 140 | 141 | u16 resp; 142 | u16 ptr; 143 | u16 len; 144 | u32 addr; 145 | ptr = 4; 146 | 147 | 148 | addr = usb_buff8[ptr++]; 149 | addr <<= 8; 150 | addr |= usb_buff8[ptr++]; 151 | addr *= 2048; 152 | 153 | len = usb_buff8[ptr++]; 154 | len <<= 8; 155 | len |= usb_buff8[ptr++]; 156 | 157 | 158 | resp = evd_fifoWrFromCart(addr, len); 159 | if (resp)return 1; 160 | 161 | 162 | return 0; 163 | } 164 | 165 | u8 cmdWriteRom() { 166 | 167 | u16 resp; 168 | u16 ptr; 169 | u16 len; 170 | u32 addr; 171 | ptr = 4; 172 | 173 | addr = usb_buff8[ptr++]; 174 | addr <<= 8; 175 | addr |= usb_buff8[ptr++]; 176 | addr *= 2048; 177 | 178 | len = usb_buff8[ptr++]; 179 | len <<= 8; 180 | len |= usb_buff8[ptr++]; 181 | 182 | resp = evd_fifoRdToCart(addr, len); 183 | if (resp)return 1; 184 | 185 | return 0; 186 | 187 | } 188 | -------------------------------------------------------------------------------- /src/version.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2017 The Altra64 project contributors 3 | // See LICENSE file in the project root for full license information. 4 | // 5 | 6 | #include "version.h" 7 | 8 | #define ALTRA64_VERSION "3.8.1" 9 | 10 | const char* Altra64_GetVersionString(void) 11 | { 12 | return ALTRA64_VERSION; 13 | } 14 | -------------------------------------------------------------------------------- /tools/deploy-sd.sh: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2017 The Altra64 project contributors 3 | # Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod 4 | # See LICENSE file in the project root for full license information. 5 | # 6 | 7 | #! /bin/bash 8 | sudo mount /dev/sdb1 /mnt 9 | file=/mnt/ED64/OS64.v64 10 | if [ -e $file ] 11 | then 12 | echo -e "File $file exists - mount ok" 13 | echo -e "copy..." 14 | sudo cp ../bin/OS64.v64 /mnt/ED64/ 15 | sudo cp ../res/ALT64.INI /mnt/ED64/ 16 | echo -e "umounting..." 17 | sudo umount /mnt 18 | echo -e "done..." 19 | else 20 | echo -e "File $file doesnt exists - sdcard problem?" 21 | fi 22 | -------------------------------------------------------------------------------- /tools/extract-firmware.cmd: -------------------------------------------------------------------------------- 1 | :: 2 | :: Copyright (c) 2017 The Altra64 project contributors 3 | :: See LICENSE file in the project root for full license information. 4 | :: 5 | 6 | @echo off 7 | cd .. 8 | set "fs=%cd%\res\filesystem\firmware" 9 | set "lfs=%fs%" 10 | 11 | set "drive=%lfs:~0,1%" 12 | 13 | set lfs=%lfs:~2% 14 | set "lfs=%lfs:\=/%" 15 | 16 | if %drive%==A set "drive=a" 17 | if %drive%==B set "drive=b" 18 | if %drive%==C set "drive=c" 19 | if %drive%==D set "drive=d" 20 | if %drive%==E set "drive=e" 21 | if %drive%==F set "drive=f" 22 | if %drive%==G set "drive=g" 23 | if %drive%==H set "drive=h" 24 | if %drive%==I set "drive=i" 25 | if %drive%==J set "drive=j" 26 | if %drive%==K set "drive=k" 27 | if %drive%==L set "drive=l" 28 | if %drive%==M set "drive=m" 29 | if %drive%==N set "drive=n" 30 | if %drive%==O set "drive=o" 31 | if %drive%==P set "drive=p" 32 | if %drive%==Q set "drive=q" 33 | if %drive%==R set "drive=r" 34 | if %drive%==S set "drive=s" 35 | if %drive%==T set "drive=t" 36 | if %drive%==U set "drive=u" 37 | if %drive%==V set "drive=v" 38 | if %drive%==W set "drive=w" 39 | if %drive%==X set "drive=x" 40 | if %drive%==Y set "drive=y" 41 | if %drive%==Z set "drive=z" 42 | 43 | set "lfs=/mnt/%drive%%lfs%" 44 | 45 | echo "Windows dir is %fs%" 46 | echo "Linux dir is %lfs%" 47 | 48 | :: del old firmware dir in ../res/filesystem 49 | RD /S /Q "%fs%" 50 | :: mk firmware dir in ../res/filesystem 51 | MKDIR "%fs%" 52 | 53 | SET "rom=%1" 54 | IF %1.==. ( 55 | SET /P rom="Please enter full path to OS64.v64 V2.12:" 56 | ) 57 | 58 | set "drive=%rom:~0,1%" 59 | 60 | set rom=%rom:~2% 61 | set "rom=%rom:\=/%" 62 | 63 | if %drive%==A set "drive=a" 64 | if %drive%==B set "drive=b" 65 | if %drive%==C set "drive=c" 66 | if %drive%==D set "drive=d" 67 | if %drive%==E set "drive=e" 68 | if %drive%==F set "drive=f" 69 | if %drive%==G set "drive=g" 70 | if %drive%==H set "drive=h" 71 | if %drive%==I set "drive=i" 72 | if %drive%==J set "drive=j" 73 | if %drive%==K set "drive=k" 74 | if %drive%==L set "drive=l" 75 | if %drive%==M set "drive=m" 76 | if %drive%==N set "drive=n" 77 | if %drive%==O set "drive=o" 78 | if %drive%==P set "drive=p" 79 | if %drive%==Q set "drive=q" 80 | if %drive%==R set "drive=r" 81 | if %drive%==S set "drive=s" 82 | if %drive%==T set "drive=t" 83 | if %drive%==U set "drive=u" 84 | if %drive%==V set "drive=v" 85 | if %drive%==W set "drive=w" 86 | if %drive%==X set "drive=x" 87 | if %drive%==Y set "drive=y" 88 | if %drive%==Z set "drive=z" 89 | 90 | set "rom=/mnt/%drive%%rom%" 91 | 92 | echo "Linux rom dir is %rom%" 93 | 94 | 95 | 96 | ::echo. "This script is not yet ready and will now exit." 97 | ::GOTO exit 98 | 99 | @echo ON 100 | 101 | :: OS64.V64 - Version 2.12 firmware offsets: 102 | :: cart offset (hex) offset (dec) length 103 | :: v2_old 0x25070 151664 61552 104 | :: v2 0x15930 88368 63276 105 | :: v2.5 0x340F0 213232 69911 106 | :: v3 0x45210 283152 71187 107 | 108 | :: Count = lengh / blocksize 109 | :: Seek = offset converted to decimal / blocksize 110 | 111 | :: ED rev 2_old 112 | bash --verbose -c "dd skip=9479 count=3847 if=%rom% of=%lfs%/firmware_v2_old.bin bs=16" 113 | 114 | :: ED rev 2.0 (default should return 0x214) 115 | bash --verbose -c "dd skip=5523 count=3954 if=%rom% of=%lfs%/firmware_v2.bin bs=16" 116 | 117 | :: ED rev 2.5 (default should return 0x250) 118 | bash --verbose -c "dd skip=13327 count=4369 if=%rom% of=%lfs%/firmware_v2_5.bin bs=16" 119 | 120 | :: ED rev 3 (default should return 0x300) 121 | bash --verbose -c "dd skip=17697 count=4449 if=%rom% of=%lfs%/firmware_v3.bin bs=16" 122 | 123 | 124 | pause 125 | :exit -------------------------------------------------------------------------------- /tools/release-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | EXEC_DIR=$(pwd) 3 | RELEASE_ARTIFACT="ALTRA64.zip" 4 | docker run --rm -v "$EXEC_DIR:/build" ${REGISTRY}/${IMAGE_NAME}:master make 5 | 6 | # make the release dirs 7 | 8 | if [ ! -f "$EXEC_DIR/bin/OS64P.v64" ]; then 9 | echo "$EXEC_DIR/bin/OS64P.v64 doesnt exists, build failed." 10 | exit 1 11 | fi 12 | 13 | mkdir -p "$EXEC_DIR/release/ED64P/CFG" "$EXEC_DIR/release/ED64P/CHEATS" "$EXEC_DIR/release/ED64P/SDSAVE" "$EXEC_DIR/release/ED64P/WALLPAPER" "$EXEC_DIR/release/ED64P/MEMPAKS" "$EXEC_DIR/release/EMULATORS" "$EXEC_DIR/release/ROMS/" 14 | cp "$EXEC_DIR/bin/OS64P.v64" "$EXEC_DIR/release/ED64P/" 15 | cp "$EXEC_DIR/res/ALT64.INI" "$EXEC_DIR/release/ED64P/" 16 | cp "$EXEC_DIR/res/WALLPAPER/bg.bmp" "$EXEC_DIR/release/ED64P/WALLPAPER" 17 | cp "$EXEC_DIR/res/emulators/gb.v64" "$EXEC_DIR/release/EMULATORS" 18 | cp "$EXEC_DIR/res/emulators/neon64bu.rom" "$EXEC_DIR/release/EMULATORS" 19 | cp "$EXEC_DIR/res/emulators/ultraMSX2.z64" "$EXEC_DIR/release/EMULATORS" 20 | cp "$EXEC_DIR/res/emulators/UltraSMS.z64" "$EXEC_DIR/release/EMULATORS" 21 | cd "$EXEC_DIR/release" 22 | 23 | zip -9 -r $RELEASE_ARTIFACT . 24 | -------------------------------------------------------------------------------- /tools/reset-wsfl.cmd: -------------------------------------------------------------------------------- 1 | :::::::::::::::::::::::::::::::::::::::::::: 2 | :: Elevate.cmd - Version 2 3 | :: Automatically check & get admin rights 4 | :::::::::::::::::::::::::::::::::::::::::::: 5 | @echo off 6 | CLS 7 | ECHO. 8 | ECHO ============================= 9 | ECHO Running Admin shell 10 | ECHO ============================= 11 | 12 | :init 13 | setlocal DisableDelayedExpansion 14 | set "batchPath=%~0" 15 | for %%k in (%0) do set batchName=%%~nk 16 | set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs" 17 | setlocal EnableDelayedExpansion 18 | 19 | :checkPrivileges 20 | NET FILE 1>NUL 2>NUL 21 | if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges ) 22 | 23 | :getPrivileges 24 | if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges) 25 | ECHO. 26 | ECHO ************************************** 27 | ECHO Invoking UAC for Privilege Escalation 28 | ECHO ************************************** 29 | 30 | ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%" 31 | ECHO args = "ELEV " >> "%vbsGetPrivileges%" 32 | ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%" 33 | ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%" 34 | ECHO Next >> "%vbsGetPrivileges%" 35 | ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%" 36 | "%SystemRoot%\System32\WScript.exe" "%vbsGetPrivileges%" %* 37 | exit /B 38 | 39 | :gotPrivileges 40 | setlocal & pushd . 41 | cd /d %~dp0 42 | if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1) 43 | 44 | :::::::::::::::::::::::::::: 45 | ::START 46 | :::::::::::::::::::::::::::: 47 | @echo on 48 | 49 | lxrun /uninstall /full 50 | 51 | pause -------------------------------------------------------------------------------- /tools/setup-linux.sh: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2017 The Altra64 project contributors 3 | # See LICENSE file in the project root for full license information. 4 | # 5 | 6 | #!/bin/bash 7 | # Download and install latest updates for the system [sudo req.] 8 | apt-get update 9 | apt-get -y upgrade 10 | 11 | # Install essential packages [sudo req.] 12 | apt-get -y install wget build-essential git texinfo libc6 libgmp-dev libmpfr-dev libmpc-dev libpng-dev zlib1g-dev libtool autoconf 13 | 14 | # change to the users root directory 15 | cd ~/ 16 | 17 | # add a system variable and make it perminent 18 | # echo 'N64_INST=/usr/local/libdragon' >> /etc/environment 19 | # echo 'export N64_INST=/usr/local/libdragon' >> ~/.bashrc 20 | export N64_INST=/usr/local/libdragon 21 | # source ~/.bashrc 22 | 23 | # Pull the latest libdragon source code and make a build directory 24 | git clone https://github.com/dragonminded/libdragon.git 25 | # set to correct commit 26 | cd libdragon && git checkout b26fce6 && cd .. 27 | 28 | # fix issues with the build scripts 29 | sed -i -- 's|${N64_INST:-/usr/local}|/usr/local/libdragon|g' libdragon/tools/build 30 | sed -i -- 's|--with-newlib|--with-newlib --with-system-zlib|g' libdragon/tools/build 31 | 32 | sed -i -- 's| -lpng|\nLDLIBS = -lpng|g' libdragon/tools/mksprite/Makefile 33 | sed -i -- 's| -Werror| -w|g' libdragon/tools/mksprite/Makefile 34 | 35 | # make a build folder for libdragon 36 | mkdir libdragon/build_gcc 37 | cp libdragon/tools/build libdragon/build_gcc 38 | 39 | # run the build script (this will take a while! and if not sudo, will ask for password mid flow!) 40 | cd libdragon/build_gcc 41 | ./build 42 | 43 | cd .. 44 | # run the install script [sudo req] 45 | make 46 | make install 47 | make tools 48 | make tools-install 49 | 50 | cd .. 51 | # install libmikmod (custom version) 52 | git clone https://github.com/n64-tools/libmikmod 53 | cd libmikmod/n64 54 | make 55 | make install 56 | cd .. # we have are in a subfolder, this is not a duplicate... 57 | 58 | cd .. 59 | # install libyaml 60 | git clone https://github.com/yaml/libyaml 61 | cd libyaml 62 | ./bootstrap 63 | #$(N64_INST) converterd to $N64_INST below otherwise it will not run on WSFL 64 | export PATH=$PATH:$N64_INST/bin 65 | CFLAGS="-std=gnu99 -march=vr4300 -mtune=vr4300" \ 66 | LDFLAGS="-L$N64_INST/lib -Tn64ld.x" \ 67 | LIBS="-ldragon -lc -ldragonsys -lnosys" \ 68 | ./configure --host=mips64-elf --prefix=$N64_INST 69 | make 70 | make install 71 | 72 | cd .. 73 | # install libmad (custom version) 74 | git clone https://github.com/n64-tools/libmad 75 | cd libmad 76 | export PATH=$PATH:$N64_INST/bin 77 | CFLAGS="-std=gnu99 -march=vr4300 -mtune=vr4300" \ 78 | LDFLAGS="-L$N64_INST/lib -Tn64ld.x" \ 79 | LIBS="-ldragon -lc -ldragonsys -lnosys" \ 80 | ./configure --host=mips64-elf --prefix=$N64_INST 81 | make 82 | make install 83 | 84 | cd .. 85 | 86 | # Perform cleanup 87 | apt-get -y autoremove 88 | apt-get autoclean 89 | -------------------------------------------------------------------------------- /tools/setup-wsfl.cmd: -------------------------------------------------------------------------------- 1 | :::::::::::::::::::::::::::::::::::::::::::: 2 | :: Elevate.cmd - Version 2 3 | :: Automatically check & get admin rights 4 | :::::::::::::::::::::::::::::::::::::::::::: 5 | @echo off 6 | CLS 7 | ECHO. 8 | ECHO ============================= 9 | ECHO Running Admin shell 10 | ECHO ============================= 11 | 12 | :init 13 | setlocal DisableDelayedExpansion 14 | set "batchPath=%~0" 15 | for %%k in (%0) do set batchName=%%~nk 16 | set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs" 17 | setlocal EnableDelayedExpansion 18 | 19 | :checkPrivileges 20 | NET FILE 1>NUL 2>NUL 21 | if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges ) 22 | 23 | :getPrivileges 24 | if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges) 25 | ECHO. 26 | ECHO ************************************** 27 | ECHO Invoking UAC for Privilege Escalation 28 | ECHO ************************************** 29 | 30 | ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%" 31 | ECHO args = "ELEV " >> "%vbsGetPrivileges%" 32 | ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%" 33 | ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%" 34 | ECHO Next >> "%vbsGetPrivileges%" 35 | ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%" 36 | "%SystemRoot%\System32\WScript.exe" "%vbsGetPrivileges%" %* 37 | exit /B 38 | 39 | :gotPrivileges 40 | setlocal & pushd . 41 | cd /d %~dp0 42 | if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1) 43 | 44 | :::::::::::::::::::::::::::: 45 | ::START 46 | :::::::::::::::::::::::::::: 47 | @echo on 48 | 49 | lxrun /install /y 50 | bash -c "echo 'export N64_INST=/usr/local/libdragon' >> ~/.bashrc; source ~/.bashrc" 51 | bash -c "chmod +x ./setup-linux.sh" 52 | bash --verbose -c "source ./setup-linux.sh" 53 | 54 | ::bash 55 | 56 | pause 57 | --------------------------------------------------------------------------------