Browse Source

Initial Commit: v0.186

master
Jay Oster 8 years ago
commit
bb1e653309
  1. 15
      .gitignore
  2. 32
      ALT64.INI
  3. 38
      Makefile
  4. 56
      README
  5. 106
      chksum64.c
  6. 711
      disk.c
  7. 29
      disk.h
  8. 104
      doc/functions.txt
  9. 70
      errors.h
  10. 596
      everdrive.c
  11. 125
      everdrive.h
  12. 1931
      fat.c
  13. 128
      fat.h
  14. BIN
      filesystem/bamboo.wav
  15. BIN
      filesystem/done.wav
  16. BIN
      filesystem/ed64_mono.wav
  17. BIN
      filesystem/n64controller.sprite
  18. BIN
      filesystem/sprites/background.sprite
  19. BIN
      filesystem/sprites/splash.sprite
  20. BIN
      filesystem/warning.wav
  21. 275
      font_patch/font.h
  22. 1
      font_patch/info.txt
  23. BIN
      header.ed64
  24. 301
      ini.c
  25. 77
      ini.h
  26. 160
      mem.c
  27. 39
      mem.h
  28. 5784
      menu.c
  29. 108
      menu.h
  30. 446
      mp3.c
  31. 127
      sram.c
  32. 32
      sram.h
  33. 4940
      stb_image.c
  34. 1807
      stb_truetype.h
  35. 43
      strlib.c
  36. 24
      strlib.h
  37. 359
      sys.c
  38. 61
      sys.h
  39. 36
      types.h
  40. 15
      upload.sh
  41. 180
      usb.c
  42. 16
      usb.h
  43. 1640
      utils.c
  44. 170
      utils.h

15
.gitignore vendored

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
## Build files
*.v64
*.elf
*.o
*.bin
*.dfs
## OSX junk
.DS_Store
.Trashes
._*
## Temporary files
*.tmp
*~

32
ALT64.INI

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
; alt64 config file
[ed64] ; Menu config
build=18 ; Release build nr
border_color_1=FFFFFFFF ; 0x00000080 RGBT
border_color_2=3F3F3FFF ; 0x3F3F3FFF RGBT 00000060 w light
box_color=000000B6 ; 0x00000080 RGBT
selection_color=80008070 ; 80008070 RGBT 6495ED60
list_font_color=CDC9C940 ; 80008070 RGBT 6495ED60
list_dir_font_color=FFFFE040 ; 80008070 RGBT 6495ED60
selection_font_color=FFB90FFF ; 80008070 RGBT 6495ED60
text_offset=0 ; shift menu horizontal e.g. -1
cd_behaviour=1 ; 0=first entry 1=last entry
scroll_behaviour=0 ; 0=page-system 1=classic
quick_boot=1 ; 'START' boots last rom
sound_on=1 ; sounds 1=on 0=off
page_display=1 ; display page
tv_mode=1 ; 1=ntsc 2=pal 3=mpal 0=force_off
enable_colored_list=1 ; 1=enable 0=disalbe
ext_type=0 ; 0=classic 1=OS64
sd_speed=2 ; 1=25MHz 2=50MHz
background_image=background.png ; backgrund png image 320x240 32bit
hide_sysfolder=0 ; 1=hide 0=don't hide
mempak_path=/MEMPAKS/ ; surround with slashes
save_path=SDSAVE ; save directory inside ED64
[user]
name = saturnu ; Username
[gblite]
save_path=/ED64/SDSAVE/ ; save directory surround with slashes
tv_mode=0 ; 1=ntsc 2=pal 3=mpal 0=force_off

38
Makefile

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
ROOTDIR = $(N64_INST)
GCCN64PREFIX = $(ROOTDIR)/bin/mips64-elf-
CHKSUM64PATH = $(ROOTDIR)/bin/chksum64
MKDFSPATH = $(ROOTDIR)/bin/mkdfs
HEADERPATH = $(ROOTDIR)/lib
N64TOOL = $(ROOTDIR)/bin/n64tool
HEADERNAME = header
LINK_FLAGS = -G4 -L$(ROOTDIR)/toolchain_font/lib -L$(ROOTDIR)/mips64-elf/lib -ldragon -L$(ROOTDIR)/toolchain_font/lib -lmikmod -lmad -lc -lm -ldragonsys -lnosys $(LIBS) -Tn64ld.x
PROG_NAME = menu
CFLAGS = -std=gnu99 -march=vr4300 -mtune=vr4300 -G4 -I$(ROOTDIR)/toolchain_font/include -I$(ROOTDIR)/mips64-elf/include -lpthread -lrt -D_REENTRANT -DUSE_TRUETYPE
ASFLAGS = -mtune=vr4300 -march=vr4300
CC = $(GCCN64PREFIX)gcc
AS = $(GCCN64PREFIX)as
LD = $(GCCN64PREFIX)ld
OBJCOPY = $(GCCN64PREFIX)objcopy
OBJS = $(PROG_NAME).o everdrive.o fat.o disk.o mem.o sys.o ini.o strlib.o utils.o sram.o stb_image.o chksum64.o mp3.o
$(PROG_NAME).v64: $(PROG_NAME).elf test.dfs
$(OBJCOPY) $(PROG_NAME).elf $(PROG_NAME).bin -O binary
rm -f $(PROG_NAME).v64
$(N64TOOL) -l 4M -t "EverDrive OS" -h ./header.ed64 -o OS64.v64 $(PROG_NAME).bin -s 1M test.dfs
$(CHKSUM64PATH) OS64.v64
$(PROG_NAME).elf : $(OBJS)
$(LD) -o $(PROG_NAME).elf $(OBJS) $(LINK_FLAGS)
copy: $(PROG_NAME).v64
sh upload.sh
test.dfs:
$(MKDFSPATH) test.dfs ./filesystem/
all: $(PROG_NAME).v64
clean:
rm -f *.v64 *.elf *.o *.bin *.dfs

56
README

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
alt64
=====
alternative everdrive64 menu
Kuroneko!
:\ /; _
; \___/ ; ; ;
,:-"' `"-:. / ;
_ /,---. ,---.\ _ _; /
_:>(( | ) ( | ))<:_ ,-""_,"
\````` `````/""""",-""
'-.._ v _..-' )
/ ___ ____,.. \
/ / | | | ( \. \
ctr / / | | | | \ \
`" `" `" `"
nyannyannyannyannyannyannyannyannyannyannyannyannyannyannyannyannyan
hello here is my menu for the everdrive64.
if you don't have one you should visit krikzzs homepage
for ordering information. ^^
if you want to build the menu, you need a n64 toolchain
you can get one free from
http://www.dragonminded.com/n64dev/libdragon/
https://github.com/DragonMinded/libdragon
i used the libmikmod linked on his site too for the menu
http://www.dragonminded.com/n64dev/libmikmod-3.2.0-beta2.tgz
if you are on linux, try out the build script
https://github.com/DragonMinded/libdragon/tree/master/tools/build
here are a few setting hints
export INSTALL_PATH=/usr/mips64-elf
set this to your home directory if you don't have root access
i was in need to alter the cxxflags to G0 to lowercase
CXXFLAGS="-g0 -O2"
it's a good idea to the latest versions for the toolchain
export BINUTILS_V=2.23.52
export GCC_V=4.8.0
export NEWLIB_V=1.20.0
optional:
get libn64-hkz to get more into flashram savegames
http://sourceforge.net/projects/n64dev/

106
chksum64.c

@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
/*
checksum rom in psram, based on
chksum64 V1.2, a program to calculate the ROM checksum of Nintendo64 ROMs.
Copyright (C) 1997 Andreas Sterbenz (stan@sbox.tu-graz.ac.at)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <libdragon.h>
#define BUFSIZE 0x8000
#define SDRAM_START 0xb0000000
#define CHECKSUM_START 0x1000
#define CHECKSUM_LENGTH 0x100000L
#define CHECKSUM_HEADERPOS 0x10
#define CHECKSUM_END (CHECKSUM_START + CHECKSUM_LENGTH)
#define CHECKSUM_STARTVALUE 0xf8ca4ddc
#define ROL(i, b) (((i)<<(b)) | ((i)>>(32-(b))))
#define BYTES2LONG(b) ( (((b)[0] & 0xffL) << 24) | \
(((b)[1] & 0xffL) << 16) | \
(((b)[2] & 0xffL) << 8) | \
(((b)[3] & 0xffL)) )
#define LONG2BYTES(l, b) (b)[0] = ((l)>>24)&0xff; \
(b)[1] = ((l)>>16)&0xff; \
(b)[2] = ((l)>> 8)&0xff; \
(b)[3] = ((l) )&0xff;
static unsigned char __attribute__((aligned(16))) buffer1[BUFSIZE];
void checksum_sdram(void)
{
unsigned int sum1, sum2, offs;
{
unsigned int i;
unsigned int c1, k1, k2;
unsigned int t1, t2, t3, t4;
unsigned int t5, t6;
unsigned int n;
unsigned int clen = CHECKSUM_LENGTH;
t1 = CHECKSUM_STARTVALUE;
t2 = CHECKSUM_STARTVALUE;
t3 = CHECKSUM_STARTVALUE;
t4 = CHECKSUM_STARTVALUE;
t5 = CHECKSUM_STARTVALUE;
t6 = CHECKSUM_STARTVALUE;
offs = CHECKSUM_START;
for( ;; ) {
n = (BUFSIZE < clen) ? BUFSIZE : clen;
dma_read_s(buffer1, SDRAM_START+offs, n);
data_cache_hit_writeback_invalidate(buffer1,n);
offs += n;
for( i=0; i<n; i+=4 ) {
c1 = BYTES2LONG(&buffer1[i]);
k1 = t6 + c1;
if( k1 < t6 ) t4++;
t6 = k1;
t3 ^= c1;
k2 = c1 & 0x1f;
k1 = ROL(c1, k2);
t5 += k1;
if( c1 < t2 ) {
t2 ^= k1;
} else {
t2 ^= t6 ^ c1;
}
t1 += c1 ^ t5;
}
clen -= n;
if (!clen) break;
}
sum1 = t6 ^ t4 ^ t3;
sum2 = t5 ^ t2 ^ t1;
}
LONG2BYTES(sum1, &buffer1[0]);
LONG2BYTES(sum2, &buffer1[4]);
dma_write_s(buffer1, SDRAM_START+CHECKSUM_HEADERPOS, 8);
return;
}

711
disk.c

@ -0,0 +1,711 @@ @@ -0,0 +1,711 @@
#include <console.h>
#include "disk.h"
#include "mem.h"
#include "everdrive.h"
#include "errors.h"
#include "sys.h"
#include "usb.h"
#define CMD0 0x40 // software reset
#define CMD1 0x41 // brings card out of idle state
#define CMD8 0x48 // Reserved
#define CMD12 0x4C // stop transmission on multiple block read
#define CMD17 0x51 // read single block
#define CMD18 0x52 // read multiple block
#define CMD58 0x7A // reads the OCR register
#define CMD55 0x77
#define CMD41 0x69
#define CMD24 0x58 // writes a single block
#define CMD25 0x59 // writes a multi block
#define ACMD41 0x69
#define ACMD6 0x46
#define SD_V2 2
#define SD_HC 1
#define CMD2 0x42 //read cid
#define CMD3 0x43 //read rca
#define CMD7 0x47
#define CMD9 0x49
#define CMD6 0x46
#define R1 1
#define R2 2
#define R3 3
#define R6 6
#define R7 7
u8 card_type;
u8 sd_resp_buff[18];
u32 disk_interface;
unsigned int diskCrc7(unsigned char *buff, unsigned int len);
void diskCrc16SD(u8 *data, u16 *crc_out, u16 len);
u8 diskGetRespTypeSD(u8 cmd);
u8 diskCmdSD(u8 cmd, u32 arg);
u8 diskInitSD();
u8 diskReadSD(u32 saddr, void *buff, u16 slen);
u8 diskWriteSD(u32 saddr, u8 *buff, u16 slen);
u8 diskStopRwSD();
u8 diskCmdSPI(u8 cmd, u32 arg);
u8 diskInitSPI();
u8 diskReadSPI(u32 saddr, void *buff, u16 slen);
u8 diskWriteSPI(u32 saddr, u8 *buff, u16 slen);
const u16 sd_crc16_table[] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
void diskSetInterface(u32 interface) {
disk_interface = interface;
}
u8 diskGetInterface() {
return disk_interface;
}
u8 diskInit() {
if (disk_interface == DISK_IFACE_SD) {
return diskInitSD();
} else {
return diskInitSPI();
}
}
u8 diskRead(u32 saddr, void *buff, u16 slen) {
if (disk_interface == DISK_IFACE_SD) {
return diskReadSD(saddr, buff, slen);
} else {
return diskReadSPI(saddr, buff, slen);
}
}
u8 diskWrite(u32 saddr, u8 *buff, u16 slen) {
if (disk_interface == DISK_IFACE_SD) {
return diskWriteSD(saddr, buff, slen);
} else {
return diskWriteSPI(saddr, buff, slen);
}
}
void diskCrc16SD(u8 *data, u16 *crc_out, u16 len) {
///u16 len = 512;
u16 i, tmp1, u;
u8 dat[4];
u8 dat_tmp;
u16 crc_buff[4];
for (i = 0; i < 4; i++)crc_buff[i] = 0;
for (i = 0; i < 4; i++)crc_out[i] = 0;
//u16 dptr = 0;
while (len) {
len -= 4;
for (i = 0; i < 4; i++)dat[i] = 0;
for (u = 0; u < 4; u++) {
dat_tmp = data[3 - u];
//dat_tmp = 0xff;
for (i = 0; i < 4; i++) {
dat[i] >>= 1;
dat[i] |= (dat_tmp & 1) << 7;
dat_tmp >>= 1;
}
for (i = 0; i < 4; i++) {
dat[i] >>= 1;
dat[i] |= (dat_tmp & 1) << 7;
dat_tmp >>= 1;
}
}
data += 4;
for (u = 0; u < 4; u++) {
tmp1 = crc_buff[u];
crc_buff[u] = sd_crc16_table[(tmp1 >> 8) ^ dat[u]];
crc_buff[u] = crc_buff[u] ^ (tmp1 << 8);
}
}
for (i = 0; i < 4 * 16; i++) {
crc_out[3 - i / 16] >>= 1;
crc_out[3 - i / 16] |= (crc_buff[i % 4] & 1) << 15;
crc_buff[i % 4] >>= 1;
}
}
unsigned int diskCrc7(unsigned char *buff, unsigned int len) {
unsigned int a, crc = 0;
while (len--) {
crc ^= *buff++;
a = 8;
do {
crc <<= 1;
if (crc & (1 << 8)) crc ^= 0x12;
} while (--a);
}
return (crc & 0xfe);
}
u8 diskGetRespTypeSD(u8 cmd) {
switch (cmd) {
case CMD3:
return R6;
case CMD8:
return R7;
case CMD2:
case CMD9:
return R2;
case CMD58:
case CMD41:
return R3;
default: return R1;
}
}
u8 diskCmdSD(u8 cmd, u32 arg) {
u8 resp_type = diskGetRespTypeSD(cmd);
u8 p = 0;
u8 buff[6];
volatile u8 resp;
volatile u32 i = 0;
u8 resp_len = resp_type == R2 ? 17 : 6;
u8 crc;
buff[p++] = cmd;
buff[p++] = (arg >> 24);
buff[p++] = (arg >> 16);
buff[p++] = (arg >> 8);
buff[p++] = (arg >> 0);
crc = diskCrc7(buff, 5) | 1;
evd_SDcmdWriteMode(0);
mem_spi(0xff);
mem_spi(cmd);
mem_spi(arg >> 24);
mem_spi(arg >> 16);
mem_spi(arg >> 8);
mem_spi(arg);
mem_spi(crc);
evd_SDcmdReadMode(1);
i = 0;
resp = 0xff;
while ((resp & 192) != 0) {
resp = mem_spi(resp);
if (i++ == WAIT)return SD_CMD_TIMEOUT;
}
evd_SDcmdReadMode(0);
sd_resp_buff[0] = resp;
for (i = 1; i < resp_len; i++) {
sd_resp_buff[i] = mem_spi(0xff);
}
if (resp_type != R3) {
if (resp_type == R2) {
crc = diskCrc7(sd_resp_buff + 1, resp_len - 2) | 1;
} else {
crc = diskCrc7(sd_resp_buff, resp_len - 1) | 1;
}
if (crc != sd_resp_buff[resp_len - 1])return SD_CMD_CRC_ERROR;
}
return 0;
}
u8 diskInitSD() {
u16 i;
volatile u8 resp = 0;
u32 rca;
u32 wait_len = WAIT;
card_type = 0;
evd_enableSDMode();
memSpiSSOff();
memSpiSetSpeed(SPI_SPEED_INIT);
evd_SDcmdWriteMode(0);
for (i = 0; i < 40; i++)mem_spi(0xff);
resp = diskCmdSD(CMD0, 0x1aa);
for (i = 0; i < 40; i++)mem_spi(0xff);
resp = diskCmdSD(CMD8, 0x1aa);
if (resp != 0 && resp != SD_CMD_TIMEOUT) {
return SD_INIT_ERROR + 0;
}
if (resp == 0)card_type |= SD_V2;
if (card_type == SD_V2) {
for (i = 0; i < wait_len; i++) {
resp = diskCmdSD(CMD55, 0);
if (resp)return SD_INIT_ERROR + 1;
if ((sd_resp_buff[3] & 1) != 1)continue;
resp = diskCmdSD(CMD41, 0x40300000);
if ((sd_resp_buff[1] & 128) == 0)continue;
break;
}
} else {
i = 0;
do {
resp = diskCmdSD(CMD55, 0);
if (resp)return SD_INIT_ERROR + 2;
resp = diskCmdSD(CMD41, 0x40300000);
if (resp)return SD_INIT_ERROR + 3;
} while (sd_resp_buff[1] < 1 && i++ < wait_len);
}
if (i == wait_len)return SD_INIT_ERROR + 4;
if ((sd_resp_buff[1] & 64) && card_type != 0)card_type |= SD_HC;
resp = diskCmdSD(CMD2, 0);
if (resp)return SD_INIT_ERROR + 5;
resp = diskCmdSD(CMD3, 0);
if (resp)return SD_INIT_ERROR + 6;
resp = diskCmdSD(CMD7, 0);
//if (resp)return resp;
rca = (sd_resp_buff[1] << 24) | (sd_resp_buff[2] << 16) | (sd_resp_buff[3] << 8) | (sd_resp_buff[4] << 0);
resp = diskCmdSD(CMD9, rca); //get csd
if (resp)return SD_INIT_ERROR + 7;
resp = diskCmdSD(CMD7, rca);
if (resp)return SD_INIT_ERROR + 8;
resp = diskCmdSD(CMD55, rca);
if (resp)return SD_INIT_ERROR + 9;
resp = diskCmdSD(CMD6, 2);
if (resp)return SD_INIT_ERROR + 10;
memSpiSetSpeed(SPI_SPEED_25);
return 0;
}
u8 diskReadSD(u32 saddr, void *buff, u16 slen) {
u8 resp;
if (!(card_type & 1))saddr *= 512;
resp = diskCmdSD(CMD18, saddr);
if (resp)return DISK_ERR_RD1;
resp = memSpiRead(buff, slen);
if (resp)return resp;
//console_printf("drd: %0X\n", saddr);
resp = diskStopRwSD();
return resp;
}
u8 diskStopRwSD() {
u8 resp;
u16 i;
resp = diskCmdSD(CMD12, 0);
if (resp)return DISK_ERR_CLOSE_RW1;
evd_SDdatReadMode(0);
mem_spi(0xff);
i = 65535;
while (i--) {
if (mem_spi(0xff) == 0xff)break;
if (mem_spi(0xff) == 0xff)break;
if (mem_spi(0xff) == 0xff)break;
if (mem_spi(0xff) == 0xff)break;
}
if (i == 0)return DISK_ERR_CLOSE_RW2;
return 0;
}
u8 diskWriteSD(u32 saddr, u8 *buff, u16 slen) {
u8 resp;
u16 crc16[5];
u16 i;
u16 u;
u8 ram_buff[512];
u8 *buff_ptr;
if (!(card_type & 1))saddr *= 512;
resp = diskCmdSD(CMD25, saddr);
if (resp)return DISK_ERR_WR1;
evd_SDdatWriteMode(0);
while (slen--) {
if ((u32) buff >= ROM_ADDR && (u32) buff < ROM_END_ADDR) {
dma_read_s(ram_buff, (u32) buff, 512);
buff_ptr = ram_buff;
} else {
buff_ptr = buff;
}
diskCrc16SD(buff_ptr, crc16, 512);
evd_SDdatWriteMode(0);
mem_spi(0xff);
mem_spi(0xf0);
memSpiWrite(buff_ptr);
for (i = 0; i < 4; i++) {
mem_spi(crc16[i] >> 8);
mem_spi(crc16[i] & 0xff);
}
buff += 512;
evd_SDdatWriteMode(1);
mem_spi(0xff);
evd_SDdatReadMode(1);
i = 1024;
while ((mem_spi(0xff) & 1) != 0 && i-- != 0);
if (i == 0)return DISK_WR_SB_TOUT;
resp = 0;
for (i = 0; i < 3; i++) {
resp <<= 1;
u = mem_spi(0xff);
resp |= u & 1;
}
resp &= 7;
if (resp != 0x02) {
//console_printf("error blia: %0X\n", resp);
// joyWait();
if (resp == 5)return DISK_ERR_WR_CRC;
return DISK_ERR_WRX;
}
evd_SDdatReadMode(0);
mem_spi(0xff);
i = 65535;
while (i--) {
if (mem_spi(0xff) == 0xff)break;
if (mem_spi(0xff) == 0xff)break;
}
if (i == 0)return DISK_ERR_WR2;
}
resp = diskStopRwSD();
if (resp)return resp;
return 0;
}
u8 diskCmdSPI(u8 cmd, u32 arg) {
u8 crc;
u8 p = 0;
u8 buff[6];
buff[p++] = cmd;
buff[p++] = (arg >> 24);
buff[p++] = (arg >> 16);
buff[p++] = (arg >> 8);
buff[p++] = (arg >> 0);
crc = diskCrc7(buff, 5) | 1;
volatile u32 i = 0;
volatile u8 resp;
memSpiBusy();
memSpiSSOff();
memSpiSSOn();
//mem_spi(0x1);
mem_spi(0xff);
mem_spi(cmd);
mem_spi(arg >> 24);
mem_spi(arg >> 16);
mem_spi(arg >> 8);
mem_spi(arg);
mem_spi(crc);
mem_spi(0xff);
resp = mem_spi(0xff);
// memSpiSSOn();
while (resp == 0xff) {
resp = mem_spi(0xff);
if (i++ == WAIT)break;
}
memSpiSSOff();
return resp;
}
u8 diskInitSPI() {
u16 i;
u32 u;
volatile u8 resp = 0;
u8 cmd;
u32 wait_len = WAIT;
card_type = 0;
evd_enableSPIMode();
//return evd_mmcInit();
memSpiSetSpeed(SPI_SPEED_INIT);
for (u = 0; u < 4; u++) {
for (i = 0; i < 40; i++)mem_spi(0xff);
resp = diskCmdSPI(CMD0, 0);
if (resp == 1)break;
}
if (resp != 1) return DISK_ERR_INIT + 0;
//mmcCmdCrc(0x7b, 0, 0x91);
resp = diskCmdSPI(CMD8, 0x1aa);
for (i = 0; i < 5; i++)mem_spi(0xff);
if (resp == 0xff)return DISK_ERR_INIT + 1;
if (resp != 5)card_type |= SD_V2;
if (card_type == 2) {
for (i = 0; i < wait_len; i++) {
resp = diskCmdSPI(CMD55, 0xffff);
if (resp == 0xff)return DISK_ERR_INIT + 2;
if (resp != 1)continue;
resp = diskCmdSPI(CMD41, 0x40300000);
if (resp == 0xff)return DISK_ERR_INIT + 3;
if (resp != 0)continue;
break;
}
if (i == wait_len)return DISK_ERR_INIT + 4;
resp = diskCmdSPI(CMD58, 0);
if (resp == 0xff)return DISK_ERR_INIT + 5;
memSpiSSOn();
resp = mem_spi(0xff);
for (i = 0; i < 3; i++)mem_spi(0xff);
if ((resp & 0x40))card_type |= 1;
} else {
i = 0;
resp = diskCmdSPI(CMD55, 0);
if (resp == 0xff)return DISK_ERR_INIT + 6;
resp = diskCmdSPI(CMD41, 0);
if (resp == 0xff)return DISK_ERR_INIT + 7;
cmd = resp;
for (i = 0; i < wait_len; i++) {
if (resp < 1) {
resp = diskCmdSPI(CMD55, 0);
if (resp == 0xff)return DISK_ERR_INIT + 8;
if (resp != 1)continue;
resp = diskCmdSPI(CMD41, 0);
if (resp == 0xff)return DISK_ERR_INIT + 9;
if (resp != 0)continue;
} else {
resp = diskCmdSPI(CMD1, 0);
if (resp != 0)continue;
}
break;
}
if (i == wait_len)return DISK_ERR_INIT + 10;
}
memSpiSetSpeed(SPI_SPEED_25);
return 0;
}
u8 diskReadSPI(u32 saddr, void *buff, u16 slen) {
u8 resp;
if (!(card_type & 1))saddr *= 512;
resp = diskCmdSPI(CMD18, saddr);
if (resp != 0)return DISK_ERR_RD1;
memSpiSSOn();
resp = memSpiRead(buff, slen);
memSpiSSOff();
diskCmdSPI(CMD12, 0);
return resp;
}
u8 diskWriteSPI(u32 saddr, u8 *buff, u16 slen) {
u8 resp;
u16 i;
if (!(card_type & 1))saddr *= 512;
resp = diskCmdSPI(CMD25, saddr);
if (resp != 0)return DISK_ERR_WR1;
memSpiSSOn();
while (slen--) {
mem_spi(0xff);
mem_spi(0xff);
mem_spi(0xfc);
memSpiWrite(buff);
mem_spi(0xff);
mem_spi(0xff);
resp = mem_spi(0xff);
//resp = mem_spi(0xff);
buff += 512;
if ((resp & 0x1f) != 0x05) {
memSpiSSOff();
return DISK_ERR_WRX;
}
for (i = 0; i < 65535; i++) {
if (mem_spi(0xff) == 0xff)break;
if (mem_spi(0xff) == 0xff)break;
if (mem_spi(0xff) == 0xff)break;
if (mem_spi(0xff) == 0xff)break;
}
if (i == 65535) {
memSpiSSOff();
return DISK_ERR_WR2;
}
}
mem_spi(0xfd);
mem_spi(0xff);
for (i = 0; i < 65535; i++) {
if ((mem_spi(0xff) & 1) != 0)break;
if ((mem_spi(0xff) & 1) != 0)break;
if ((mem_spi(0xff) & 1) != 0)break;
if ((mem_spi(0xff) & 1) != 0)break;
}
memSpiSSOff();
if (i == 65535) return DISK_ERR_WR3;
return 0;
}

29
disk.h

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
/*
* File: disk.h
* Author: krik
*
* Created on 2 Èþíü 2011 ã., 4:07
*/
#ifndef _DISK_H
#define _DISK_H
#include "types.h"
u8 diskGetInterface();
u8 diskInit();
u8 diskRead(u32 saddr, void *buff, u16 slen);
u8 diskWrite(u32 saddr, u8 *buff, u16 slen);
void diskSetInterface(u32 interface);
#define WAIT 1024
#define DISK_IFACE_SPI 0
#define DISK_IFACE_SD 1
#endif /* _DISK_H */

104
doc/functions.txt

@ -0,0 +1,104 @@ @@ -0,0 +1,104 @@
beta9
rom loading function flow:
main()
//init n64, fs, controller
//joypad loop
//button (A) -> select rom
loadrom(disp,name_file);
//readout rom header
//check if swapped
evd_mmcSetDmaSwap(1);
//dma read file to 0xb0000000 cartspace
diskRead();
//change key mapping
//if (START)
bootRom();
//save LAST.CRT for reboot cart-save
//set fpga to eeprom, sram, flashram
evd_setSaveType(boot_save);
//do pif simulation to boot the rom
simulate_boot(boot_cic, bios_cic);
cart-save overview:
before pif simulation the cart_id and cart_savetype is stored in
LAST.CRT [maybe it's a better solution to use rom filenames
'cause the cart_id includes no game-version]
-> bootRom();
at every start of the menu a function is called that checks
LAST.CRT, if there is something todo and disable it for next boot
by setting a flag in that file
-> backupSaveData(disp);
if it's a warm boot (reset) the fpga savegame is still there
-> save_cfg_stat = evd_readReg(REG_SAV_CFG);
if it's a reset reboot to backup a savegame into a file
saveTypeToSd(disp, cartID, save_t)
is called
it's only for some file operations and calls
utils.c: getSaveFromCart(stype, cartsave_data)
to store the savegame into a buffer, which could
be saved into a file
some notes:
eeprom is connected directly to the pif (i2c?)
and could be read out stable with the libdragon function
sram/flashram is a serial device that is mapped into
memory
it has to be accessed with dma to rdram through the pif
it's a domain2 device which needs other timing than the cart
timings:
PI_BSD_DOM2_XXX_REG
sram/fram:
val XXX desc
05 LAT Latency
OC PWD Pulse Width
//sram - 0D
//fram Animal Forest - 0F
OD PGS Page Size
02 RLS Release Duration
carts/dev-carts:
40 Latency
12 Pulse Width
07 Page Size
03 Release Duration
IPL at 0xA6000000:
40 Latency
07 Pulse Width
07 Page Size
02 Release Duration
cartidge:
PI_BSD_DOM1_XXX_REG
is set with the first word in the header
e.g. 0x[80]371240 -> 3.7.12.40 ~ 40,12,07,03

70
errors.h

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
/*
* File: errors.h
* Author: KRIK
*
* Created on 14 Ìàé 2011 ã., 7:17
*/
#ifndef _ERRORS_H
#define _ERRORS_H
#define EVD_ERROR_FIFO_TIMEOUT 90;
#define EVD_ERROR_MMC_TIMEOUT 91;
#define BOOT_UPD_ERR_WRONG_SIZE 95
#define BOOT_UPD_ERR_HDR 96
#define BOOT_UPD_ERR_CMP 97
#define BOOT_UPD_ERR_CIC_DTCT 98
#define FAT_ERR_NOT_EXIST 100
#define FAT_ERR_EXIST 101
#define FAT_ERR_NAME 102
#define FAT_ERR_OUT_OF_FILE 103
#define FAT_ERR_BAD_BASE_CLUSTER 104;
#define FAT_ERR_NO_FRE_SPACE 105
#define FAT_ERR_NOT_FILE 106
#define FAT_ERR_FILE_MODE 107
#define FAT_ERR_ROT_OVERFLOW 108
#define FAT_ERR_OUT_OF_TABLE 109
#define FAT_ERR_INIT 110
#define FAT_LFN_BUFF_OVERFLOW 111
#define FAT_DISK_NOT_READY 112
#define FAT_ERR_SIZE 113
#define FAT_ERR_RESIZE 114
#define ERR_FILE8_TOO_BIG 140
#define ERR_FILE16_TOO_BIG 141
#define ERR_WRON_OS_SIZE 142
#define ERR_OS_VERIFY 143
#define ERR_OS_VERIFY2 144
#define ERR_EMU_NOT_FOUND 145
#define ERR_SAVE_FORMAT 146
#define ERR_EEPROM 147
#define ERR_NO_FAV_SPACE 150
#define DISK_ERR_INIT 50
#define DISK_ERR_RD1 62
#define DISK_ERR_RD2 63
#define DISK_ERR_WR1 64
#define DISK_ERR_WR2 65
#define DISK_ERR_WR3 66
#define DISK_ERR_WRX 67
#define DISK_WR_SB_TOUT 68
#define DISK_ERR_WR_CRC 69
#define DISK_RD_FE_TOUT 70
#define DISK_ERR_CLOSE_RW1 71
#define DISK_ERR_CLOSE_RW2 72
#define SD_CMD_TIMEOUT 75
#define SD_CMD_CRC_ERROR 76
#define SD_INIT_ERROR 80
#endif /* _ERRORS_H */

596
everdrive.c

@ -0,0 +1,596 @@ @@ -0,0 +1,596 @@
#include "types.h"
#include "everdrive.h"
#include <libdragon.h>
#include <stdio.h>
#include "sys.h"
#include "errors.h"
//#include "rom.h"
#include "disk.h"
#define CMD0 0x40 // software reset
#define CMD1 0x41 // brings card out of idle state
#define CMD2 0x42 // not used in SPI mode
#define CMD3 0x43 // not used in SPI mode
#define CMD4 0x44 // not used in SPI mode
#define CMD5 0x45 // Reserved
#define CMD6 0x46 // Reserved
#define CMD7 0x47 // not used in SPI mode
#define CMD8 0x48 // Reserved
#define CMD9 0x49 // ask card to send card speficic data (CSD)
#define CMD10 0x4A // ask card to send card identification (CID)
#define CMD11 0x4B // not used in SPI mode
#define CMD12 0x4C // stop transmission on multiple block read
#define CMD13 0x4D // ask the card to send it's status register
#define CMD14 0x4E // Reserved
#define CMD15 0x4F // not used in SPI mode
#define CMD16 0x50 // sets the block length used by the memory card
#define CMD17 0x51 // read single block
#define CMD18 0x52 // read multiple block
#define CMD19 0x53 // Reserved
#define CMD20 0x54 // not used in SPI mode
#define CMD21 0x55 // Reserved
#define CMD22 0x56 // Reserved
#define CMD23 0x57 // Reserved
#define CMD24 0x58 // writes a single block
#define CMD25 0x59 // writes multiple blocks
#define CMD26 0x5A // not used in SPI mode
#define CMD27 0x5B // change the bits in CSD
#define CMD28 0x5C // sets the write protection bit
#define CMD29 0x5D // clears the write protection bit
#define CMD30 0x5E // checks the write protection bit
#define CMD31 0x5F // Reserved
#define CMD32 0x60 // Sets the address of the first sector of the erase group
#define CMD33 0x61 // Sets the address of the last sector of the erase group
#define CMD34 0x62 // removes a sector from the selected group
#define CMD35 0x63 // Sets the address of the first group
#define CMD36 0x64 // Sets the address of the last erase group
#define CMD37 0x65 // removes a group from the selected section
#define CMD38 0x66 // erase all selected groups
#define CMD39 0x67 // not used in SPI mode
#define CMD40 0x68 // not used in SPI mode
#define CMD41 0x69 // Reserved
#define CMD42 0x6A // locks a block
// CMD43 ... CMD57 are Reserved
#define CMD58 0x7A // reads the OCR register
#define CMD59 0x7B // turns CRC off
// CMD60 ... CMD63 are not used in SPI mode
#define ED_STATE_DMA_BUSY 0
#define ED_STATE_DMA_TOUT 1
#define ED_STATE_TXE 2
#define ED_STATE_RXF 3
#define ED_STATE_SPI 4
#define SPI_CFG_SPD0 0
#define SPI_CFG_SPD1 1
#define SPI_CFG_SS 2
#define SPI_CFG_RD 3
#define SPI_CFG_DAT 4
#define SPI_CFG_1BIT 5
#define SAV_EEP_ON 0
#define SAV_SRM_ON 1
#define SAV_EEP_SIZE 2
#define SAV_SRM_SIZE 3
//was missing
//#define BI_SPI_SPD_LO 0
#define BI_SPI_SPD_LO 2 // around 200khz (only for sd initialization)
#define BI_SPI_SPD_25 1
#define BI_SPI_SPD_50 0
void evd_setSpiSpeed(u8 speed);
u8 evd_mmcCmd(u8 cmd, u32 arg);
u8 sd_mode;
volatile u8 spi_cfg;
volatile u8 evd_cfg;
u8 sd_type;
volatile u32 *regs_ptr = (u32 *) 0xA8040000;
/*
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];
prv[7:0] <= ad[15:8];
*/
void (*dma_busy_callback)();
void evd_setDmaAddr(u32 addr) {
}
inline u32 bi_reg_rd(u32 reg) {
*(vu32 *) (REGS_BASE);
return *(vu32 *) (REGS_BASE + reg * 4);
}
inline void bi_reg_wr(u32 reg, u32 data) {
*(vu32 *) (REGS_BASE);
*(vu32 *) (REGS_BASE + reg * 4) = data;
}
void bi_init() {
evd_cfg = ED_CFG_SDRAM_ON;
spi_cfg = 0 | BI_SPI_SPD_LO;
bi_reg_wr(REG_KEY, 0x1234);
bi_reg_wr(REG_CFG, evd_cfg);
bi_reg_wr(REG_SPI_CFG, spi_cfg);
}
void bi_speed50() {
spi_cfg = 0 | BI_SPI_SPD_50;
bi_reg_wr(REG_KEY, 0x1234);
bi_reg_wr(REG_SPI_CFG, spi_cfg);
}
void bi_speed25() {
spi_cfg = 0 | BI_SPI_SPD_25;
bi_reg_wr(REG_KEY, 0x1234);
bi_reg_wr(REG_SPI_CFG, spi_cfg);
}
void bi_load_firmware(u8 *firm) {
u32 i;
u16 f_ctr = 0;
evd_cfg &= ~ED_CFG_SDRAM_ON;
bi_reg_wr(REG_CFG, evd_cfg);
bi_reg_wr(REG_CFG_CNT, 0);
sleep(10);
bi_reg_wr(REG_CFG_CNT, 1);
sleep(10);
i = 0;
for (;;) {
bi_reg_wr(REG_CFG_DAT, *(u16 *) & firm[i]);
while ((bi_reg_rd(REG_CFG_CNT) & 8) != 0);
f_ctr = firm[i++] == 0xff ? f_ctr + 1 : 0;
if (f_ctr >= 47)break;
f_ctr = firm[i++] == 0xff ? f_ctr + 1 : 0;
if (f_ctr >= 47)break;
}
while ((bi_reg_rd(REG_CFG_CNT) & 4) == 0) {
bi_reg_wr(REG_CFG_DAT, 0xffff);
while ((bi_reg_rd(REG_CFG_CNT) & 8) != 0);
}
sleep(20);
bi_init();
}
void evd_init() {
volatile u8 val;
sd_mode = 0;
dma_busy_callback = 0;
sleep(1);
val = regs_ptr[0];
spi_cfg = (0 << SPI_CFG_SPD0) | (1 << SPI_CFG_SPD1) | (1 << SPI_CFG_SS);
evd_cfg = (1 << ED_CFG_SDRAM_ON);
val = regs_ptr[0];
regs_ptr[REG_KEY] = 0x1234;
val = regs_ptr[0];
regs_ptr[REG_CFG] = evd_cfg;
val = regs_ptr[0];
regs_ptr[REG_SPI_CFG] = spi_cfg;
evd_fifoRxf();
if (!evd_fifoRxf()) {
val = regs_ptr[0];
regs_ptr[REG_DMA_LEN] = 7; //clean 16k
val = regs_ptr[0];
regs_ptr[REG_DMA_RAM_ADDR] = (ROM_LEN - 0x200000) / 2048;
val = regs_ptr[0];
regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM;
while (evd_isDmaBusy());
}
}
void evd_ulockRegs(){
volatile u8 val;
val = regs_ptr[0];
regs_ptr[REG_KEY] = 0x1234;
}
void evd_lockRegs() {
volatile u8 val;
val = regs_ptr[0];
regs_ptr[REG_KEY] = 0;
}
u8 evd_fifoRxf() {
u16 val;
//regs_ptr[REG_STATE]++;
val = regs_ptr[REG_STATUS];
return (val >> ED_STATE_RXF) & 1;
}
u8 evd_fifoTxe() {
u16 val;
//regs_ptr[REG_STATE]++;
val = regs_ptr[REG_STATUS];
return (val >> ED_STATE_TXE) & 1;
}
u8 evd_isDmaBusy() {
u16 val;
//volatile u32 i;
sleep(1);
if(dma_busy_callback != 0)dma_busy_callback();
//regs_ptr[REG_STATE]++;
val = regs_ptr[REG_STATUS];
return (val >> ED_STATE_DMA_BUSY) & 1;
}
u8 evd_isDmaTimeout() {
u16 val;
//regs_ptr[REG_STATE]++;
val = regs_ptr[REG_STATUS];
return (val >> ED_STATE_DMA_TOUT) & 1;
}
u8 evd_fifoRdToCart(u32 cart_addr, u16 blocks) {
volatile u8 val;
cart_addr /= 2048;
val = regs_ptr[0];
regs_ptr[REG_DMA_LEN] = (blocks - 1);
val = regs_ptr[0];
regs_ptr[REG_DMA_RAM_ADDR] = cart_addr;
val = regs_ptr[0];
regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM;
while (evd_isDmaBusy());
if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT;
return 0;
}
u8 evd_fifoWrFromCart(u32 cart_addr, u16 blocks) {
volatile u8 val;
cart_addr /= 2048;
val = regs_ptr[0];
regs_ptr[REG_DMA_LEN] = (blocks - 1);
val = regs_ptr[0];
regs_ptr[REG_DMA_RAM_ADDR] = cart_addr;
val = regs_ptr[0];
regs_ptr[REG_DMA_CFG] = DCFG_RAM_TO_FIFO;
while (evd_isDmaBusy());
if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT;
return 0;
}