Initial Commit

* Initial read/write test of SRAM implemented.
This commit is contained in:
ApacheThunder 2024-08-21 13:28:49 -05:00
parent 43be916e74
commit 86f5dab921
17 changed files with 1493 additions and 0 deletions

54
.gitignore vendored Normal file
View File

@ -0,0 +1,54 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# devkitARM/libnds/3DS compiled stuff
*.tmd
*.cia
*.cmd
*.nds
*.app
*.tmd
*.zip
*.arm7
*.arm9
*.elf
build
data
# Stuff used to build custom banner/misc other things that shouldn't be in repo.
*.dldi
*.zip
# Stuff generated by Windows.
Thumbs.db
desktop.ini

50
Makefile Normal file
View File

@ -0,0 +1,50 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
export TARGET := nrioSaveTester
export TOPDIR := $(CURDIR)
# specify a directory which contains the nitro filesystem
# this is relative to the Makefile
NITRO_FILES :=
include $(DEVKITARM)/ds_rules
.PHONY: checkarm7 checkarm9 clean
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all: checkarm7 checkarm9 $(TARGET).nds
#---------------------------------------------------------------------------------
checkarm7:
$(MAKE) -C arm7
#---------------------------------------------------------------------------------
checkarm9:
$(MAKE) -C arm9
#---------------------------------------------------------------------------------
$(TARGET).nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9/$(TARGET).elf
ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \
-h 0x200 -t banner.bin \
$(_ADDFILES)
#---------------------------------------------------------------------------------
arm7/$(TARGET).elf:
$(MAKE) -C arm7
#---------------------------------------------------------------------------------
arm9/$(TARGET).elf:
$(MAKE) -C arm9
#---------------------------------------------------------------------------------
clean:
$(MAKE) -C arm9 clean
$(MAKE) -C arm7 clean
rm -f $(TARGET).nds $(TARGET).arm7 $(TARGET).arm9

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# NRIO Save Tester: N-Card Save Test Tool
Simple program to test SRAM on N-Cards to make sure battery is still good.
Note. Program may hang on initial boot with fresh save file. If this occurs, just reboot and once XMENU generates a save file, it should operate normally.
On initial boot. Use B button to write test save to SRAM. Once down follow prompt to exit and power down. Leave powered off for a minute, an hour, a day...however long you desire to test.
A good battery should hold a save for at least a day. Though techinically if it holds a save longer then a few minutes you could reasonably get by if you remember to reboot quickly to backup save.
Program will show what the expected CRCs should be and what the CRC's the save tile returned and will indicate accordingly if they do not match.

126
arm7/Makefile Normal file
View File

@ -0,0 +1,126 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/ds_rules
#---------------------------------------------------------------------------------
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
# DATA is a list of directories containing binary files
# all directories are relative to this makefile
#---------------------------------------------------------------------------------
BUILD := build
SOURCES := source
INCLUDES := include build
DATA :=
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb-interwork
CFLAGS := -g -Wall -O2 \
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer \
-ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM7
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -fno-rtti
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,--nmagic -Wl,-Map,$(notdir $*).map
LIBS := -lnds7
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(LIBNDS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export ARM7ELF := $(CURDIR)/$(TARGET).elf
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) *.elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(ARM7ELF) : $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

66
arm7/source/main.c Normal file
View File

@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------
default ARM7 core
Copyright (C) 2005 - 2010
Michael Noland (joat)
Jason Rogers (dovoto)
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
---------------------------------------------------------------------------------*/
#include <nds.h>
volatile bool exitflag = false;
void VblankHandler(void) { }
void VcountHandler() { inputGetAndSend(); }
void powerButtonCB() { exitflag = true; }
int main() {
readUserSettings();
ledBlink(0);
irqInit();
// Start the RTC tracking IRQ
initClockIRQ();
fifoInit();
touchInit();
SetYtrigger(80);
installSystemFIFO();
irqSet(IRQ_VCOUNT, VcountHandler);
irqSet(IRQ_VBLANK, VblankHandler);
irqEnable(IRQ_VBLANK | IRQ_VCOUNT);
setPowerButtonCB(powerButtonCB);
// Keep the ARM7 mostly idle
while (!exitflag) {
if ( 0 == (REG_KEYINPUT & (KEY_SELECT | KEY_START | KEY_L | KEY_R)))exitflag = true;
swiWaitForVBlank();
}
return 0;
}

138
arm9/Makefile Normal file
View File

@ -0,0 +1,138 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/ds_rules
#---------------------------------------------------------------------------------
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
# DATA is a list of directories containing binary files embedded using bin2o
# GRAPHICS is a list of directories containing image files to be converted with grit
# all directories are relative to this makefile
#---------------------------------------------------------------------------------
BUILD := build
SOURCES := source include
INCLUDES := include
DATA := ../data
GRAPHICS := fonts
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb -mthumb-interwork -march=armv5te -mtune=arm946e-s
CFLAGS := -g -Wall -Os \
$(ARCH) $(INCLUDE) -DARM9
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lnds9
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(LIBNDS) $(PORTLIBS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export ARM9ELF := $(CURDIR)/$(TARGET).elf
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BMPFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.bmp)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(BMPFILES:.bmp=.o) $(OFILES_BIN) $(OFILES_SOURCES)
export HFILES := $(BMPFILES:.bmp=.h) $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir))\
$(foreach dir,$(LIBDIRS),-I$(dir)/include)\
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).elf
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(ARM9ELF) : $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
# This rule creates assembly source files using grit
# grit takes an image file and a .grit describing how the file is to be processed
# add additional rules like this for each image extension
# you use in the graphics folders
#---------------------------------------------------------------------------------
%.s %.h: %.bmp %.grit
#---------------------------------------------------------------------------------
grit $< -fts -o$*
-include $(DEPSDIR)/*.d
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

BIN
arm9/fonts/font.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

25
arm9/fonts/font.grit Normal file
View File

@ -0,0 +1,25 @@
#-------------------------------------------------------
# graphics in tile format
#-------------------------------------------------------
-gt
#-------------------------------------------------------
# output first 16 colors of the palette
#-------------------------------------------------------
-pw16
#-------------------------------------------------------
# no tile reduction
#-------------------------------------------------------
-mR!
#-------------------------------------------------------
# no map output
#-------------------------------------------------------
-m!
#-------------------------------------------------------
# graphics bit depth is 4 (16 color)
#-------------------------------------------------------
-gB4

540
arm9/include/cardme.cpp Normal file
View File

@ -0,0 +1,540 @@
/*
see:CARDME.H
*/
#include <nds/card.h>
#include "cardme.h"
// #define CARDME_CR1 (*(vuint16*)0x040001A0) /*fixed*/
// #define CARDME_EEPDATA (*(vuint16*)0x040001A2) /*fixed*/
// #define EepromWaitBusy() while (REG_AUXSPICNT & /*BUSY*/0x80);
void EepromWaitBusy() {
while (REG_AUXSPICNT & /*BUSY*/0x80);
}
// void cardmeReadEeprom(u32 address, u8 *data, u32 length, u32 addrtype);
// void cardmeWriteEepromT1(u32 address, u8 *apData, u32 aLength, u32 addrtype);
// void cardmeWriteEepromT2(u32 address, u8 *apData, u32 aLength, u32 addrtype);
// void cardmeWriteEepromT3(u32 address, u8 *apData, u32 aLength, u32 addrtype);
// #define WAIT_CR REG_EXMEMCNT
/***********************
void cardmeReadHeader(uint8 * header) {
//---------------------------------------------------------------------------------
cardRead00(0, (uint32 *)header, 512, 0xA93F1FFF);
}
**********************/
u8 cardmeCMD(u8 cmd,int address) {
// int address=i & 1;
u8 ret;
int k;
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPICNT = 0xFFFF;
REG_AUXSPIDATA = cmd; //
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 16) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 8) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = (address) & 0xFF;
EepromWaitBusy();
for(k=0;k<256;k++) {
ret = REG_AUXSPIDATA;
if(ret!=0xFF)break;
EepromWaitBusy();
}
REG_AUXSPICNT = /*MODE*/0x40;
return ret;
}
u8 cardmeReadID(int i) {
int address=i & 1;
u8 ret;
int k;
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPICNT = 0xFFFF;
REG_AUXSPIDATA = 0xAB; // READ ID
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 16) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 8) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = (address) & 0xFF;
EepromWaitBusy();
for(k=0;k<16;k++) {
ret = REG_AUXSPIDATA;
if(ret!=0xFF)break;
EepromWaitBusy();
}
REG_AUXSPICNT = /*MODE*/0x40;
return ret;
}
extern int cardmeSizeT2(void);
int cardmeGetType(void) {
// u8 ret;
u8 c00;
u8 c05;
u8 c9f;
// u8 c03;
REG_EXMEMCNT &= ~0x0880; // DS Card access ARM9:bit11=0 GBA Cart access ARM9:bit7=0
// c03=cardmeCMD(0x03,0);
cardmeCMD(0x03,0);
c05=cardmeCMD(0x05,0);
c9f=cardmeCMD(0x9f,0);
c00=cardmeCMD(0x00,0);
// if((c00==0x00) && (c9f==0x00))return 0; // PassMe? 判別不可
if((c00==0x00) && (c9f==0x00))return 1; // PassMe? 判別不可
// if((c00==0xff) && (c05==0xff) && (c9f==0xff))return -1;
if((c00==0xff) && (c05 & 0xFD) == 0xF0 && (c9f==0xff))return 1;
if((c00==0xff) && (c05 & 0xFD) == 0x00 && (c9f==0xff))return 2;
if((c00==0xff) && (c05 & 0xFD) == 0x00 && (c9f==0x00))return 3;
if((c00==0xff) && (c05 & 0xFD) == 0x00 && (c9f==0x12))return 3; // NEW TYPE 3
if((c00==0xff) && (c05 & 0xFD) == 0x00 && (c9f==0x13))return 3; // NEW TYPE 3+ 4Mbit
if((c00==0xff) && (c05 & 0xFD) == 0x00 && (c9f==0x14))return 3; // NEW TYPE 3+ 8Mbit
if((c00==0xff) && (c05 & 0xFD) == 0x00 && (c9f==0x16))return 3; // NEW TYPE 3+ 32Mbit
if((c00==0xff) && (c05 & 0xFD) == 0x84 && (c9f==0x17))return 3; // NEW TYPE 3+ 64Mbit
// /* 判定不可 */
if(cardmeSizeT2() != 0)return 2;
// return 0;
return 1;
}
int cardmeSizeT3(void) {
u8 c9f;
c9f=cardmeCMD(0x9f,0);
if(c9f==0x17) { // NEW TYPE 3+ 64Mbit(8192MByte)
return 8192*1024; // NEW TYPE 3+ 8Mbit(1024KByte)
}
if(c9f==0x14) { // NEW TYPE 3+ 8Mbit(1024MByte)
return 1024*1024; // NEW TYPE 3+ 8Mbit(1024KByte)
}
if(c9f==0x13) { // NEW TYPE 3+ 4Mbit(512MByte)
return 512*1024; // NEW TYPE 3+ 4Mbit(512KByte)
}
return 256*1024; // TYPE 3 2Mbit(256KByte)
}
#define OFOT0 (8*1024-1) // 8KBの末端
#define OFOT1 (2*8*1024-1) // 16KBの末端
int cardmeSizeT2(void) {
int tp=2;
u8 buf1[1]; // +0k data read -> write
u8 buf2[1]; // +8k data read -> read
u8 buf3[1]; // +0k ~data write
u8 buf4[1]; // +8k data new comp buf2
cardmeReadEeprom(OFOT0,buf1,1,tp);
cardmeReadEeprom(OFOT1,buf2,1,tp);
buf3[0]=~buf2[0];
cardmeWriteEeprom(OFOT0,buf3,1,tp);
cardmeReadEeprom(OFOT0,buf4,1,tp);
cardmeWriteEeprom(OFOT0,buf1,1,tp);
if(buf4[0]!=buf3[0])return 0; // Not type 2
cardmeReadEeprom(OFOT1,buf4,1,tp);
// +8kも書き換わっている
if(buf4[0]!=buf2[0])return 8*1024; // 8KB(64kbit)
return 64*1024; // 64KB(512kbit)
}
int cardmeSize(int tp) {
if(-1 <= tp && tp <= 3) {
// -1 0 1 2 3
// int eepsz[5]={ 0,8192, 512, 8192, 256*1024};
int eepsz[5]={ 0,8192, 512, 64*1024, 256*1024};
if((tp==2) || (tp==0))return cardmeSizeT2();
if(tp==3)return cardmeSizeT3();
tp++;
return eepsz[tp];
}
// return 0;
return 512;
}
//////////////////////////////////////////////////////////////////////
void cardmeReadEeprom(u32 address, u8 *data, u32 length, u32 addrtype) {
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
// REG_AUXSPICNT = 0xFFFF;
REG_AUXSPIDATA = 0x03 | ((addrtype == 1) ? address>>8<<3 : 0);
EepromWaitBusy();
if (addrtype == 3) {
REG_AUXSPIDATA = (address >> 16) & 0xFF;
EepromWaitBusy();
}
if (addrtype >= 2) {
REG_AUXSPIDATA = (address >> 8) & 0xFF;
EepromWaitBusy();
}
REG_AUXSPIDATA = (address) & 0xFF;
EepromWaitBusy();
while (length > 0) {
REG_AUXSPIDATA = 0;
EepromWaitBusy();
*data++ = REG_AUXSPIDATA;
length--;
}
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
}
//////////////////////////////////////////////////////////////////////
#define T1BLOCKSZ (16)
// TYPE1 4kbit EEPROM
void cardmeWriteEepromT1(u32 address, u8 *apData, u32 aLength, u32 addrtype) {
int i;
u32 last=address+aLength;
while (address < last) {
// set WEL (Write Enable Latch)
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x06;
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
// program maximum of 16 bytes
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
// WRITE COMMAND 0x02 + A8 << 3
REG_AUXSPIDATA = 0x02 | (address & BIT(8)) >> (8-3) ;
EepromWaitBusy();
REG_AUXSPIDATA = address & 0xFF;
EepromWaitBusy();
for (i = 0; address < last && i < T1BLOCKSZ; i++, address++) {
REG_AUXSPIDATA = *apData;
EepromWaitBusy();
apData++;
}
REG_AUXSPICNT = /*MODE*/0x40;
// wait programming to finish
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x05;
EepromWaitBusy();
do {
REG_AUXSPIDATA = 0;
EepromWaitBusy();
} while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
}
}
// TYPE2 64kbit EEPROM
void cardmeWriteEepromT2(u32 address, u8 *apData, u32 aLength, u32 addrtype) {
int i;
u32 last=address+aLength;
while (address < last) {
// set WEL (Write Enable Latch)
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x06;
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
// program maximum of 32 bytes
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x02;
EepromWaitBusy();
REG_AUXSPIDATA = address >> 8;
EepromWaitBusy();
REG_AUXSPIDATA = address & 0xFF;
EepromWaitBusy();
for (i = 0; address < last && i < 32; i++, address++) {
REG_AUXSPIDATA = *apData;
EepromWaitBusy();
apData++;
}
REG_AUXSPICNT = /*MODE*/0x40;
// wait programming to finish
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x05;
EepromWaitBusy();
do {
REG_AUXSPIDATA = 0;
EepromWaitBusy();
} while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
}
}
#define T3BLOCKSZ (256)
// TYPE3 2Mbit FLASH MEMORY
void cardmeWriteEepromT3(u32 address, u8 *apData, u32 aLength, u32 addrtype) {
int i;
u32 last=address+aLength;
while (address < last) {
// set WEL (Write Enable Latch)
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x06;
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
// program maximum of 32 bytes
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x02;
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 16) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 8) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = address & 0xFF;
EepromWaitBusy();
for (i = 0; address < last && i < T3BLOCKSZ; i++, address++) {
REG_AUXSPIDATA = *apData;
EepromWaitBusy();
apData++;
}
REG_AUXSPICNT = /*MODE*/0x40;
// wait programming to finish
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x05;
EepromWaitBusy();
do {
REG_AUXSPIDATA = 0;
EepromWaitBusy();
} while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
}
}
// Chip Erase NEW : clear FLASH MEMORY (TYPE 3 ONLY)
int cardmeChipErase(void) {
int sz;
void cardmeSectorErase(u32 address);
sz= cardmeSizeT3();
cardmeSectorErase(0x00000);
cardmeSectorErase(0x10000);
cardmeSectorErase(0x20000);
cardmeSectorErase(0x30000);
if(sz==512*1024) {
cardmeSectorErase(0x40000);
cardmeSectorErase(0x50000);
cardmeSectorErase(0x60000);
cardmeSectorErase(0x70000);
}
if(sz==1024*1024) {
cardmeSectorErase(0x80000);
cardmeSectorErase(0x90000);
cardmeSectorErase(0xA0000);
cardmeSectorErase(0xB0000);
cardmeSectorErase(0xC0000);
cardmeSectorErase(0xD0000);
cardmeSectorErase(0xE0000);
cardmeSectorErase(0xF0000);
}
return 0;
}
// COMMAND Sec.erase 0xD8
void cardmeSectorErase(u32 address) {
// int i;
// set WEL (Write Enable Latch)
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x06;
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
// SectorErase 0xD8
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0xD8;
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 16) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 8) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = address & 0xFF;
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
// wait erase to finish
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x05;
EepromWaitBusy();
do {
REG_AUXSPIDATA = 0;
EepromWaitBusy();
} while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
// EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
}
/*void cardmeSectorUnlock(u32 address) {
// set WEL (Write Enable Latch)
REG_AUXSPICNT = 0x8000 | 0x2000 | 0x40;
REG_AUXSPIDATA = 0x06;
EepromWaitBusy();
REG_AUXSPICNT = 0x40;
// Individual block unlock command for PUYA flash chip P25Q32SH used in EZP
REG_AUXSPICNT = 0x8000 | 0x2000 | 0x40;
REG_AUXSPIDATA = 0x39;
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 16) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = (address >> 8) & 0xFF;
EepromWaitBusy();
REG_AUXSPIDATA = address & 0xFF;
EepromWaitBusy();
REG_AUXSPICNT = 0x40;
// wait erase to finish
REG_AUXSPICNT = 0x8000 | 0x2000 | 0x40;
REG_AUXSPIDATA = 0x05;
EepromWaitBusy();
do {
REG_AUXSPIDATA = 0;
EepromWaitBusy();
} while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
REG_AUXSPICNT = 0x40;
}
void cardmeChipUnlock() {
REG_AUXSPICNT = 0x8000 | 0x2000 | 0x40;
REG_AUXSPIDATA = 0x06;
EepromWaitBusy();
REG_AUXSPICNT = 0x40;
// Global unlock command for PUYA flash chip P25Q32SH used in EZP
REG_AUXSPICNT = 0x8000 | 0x2000 | 0x40;
REG_AUXSPIDATA = 0x98;
EepromWaitBusy();
REG_AUXSPICNT = 0x40;
// wait programming to finish
REG_AUXSPICNT = 0x8000 | 0x2000 | 0x40;
REG_AUXSPIDATA = 0x05;
EepromWaitBusy();
do {
REG_AUXSPIDATA = 0;
EepromWaitBusy();
} while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
EepromWaitBusy();
REG_AUXSPICNT = 0x40;
}*/
// Chip Erase : clear FLASH MEMORY (TYPE 3 ONLY)
// COMMAND 0xC7
int cardmeChipErase_old(void) {
// {
// set WEL (Write Enable Latch)
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x06;
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
// Chip Erase 0xC7
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0xC7;
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
// wait programming to finish
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
REG_AUXSPIDATA = 0x05;
EepromWaitBusy();
do {
REG_AUXSPIDATA = 0;
EepromWaitBusy();
} while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
EepromWaitBusy();
REG_AUXSPICNT = /*MODE*/0x40;
// }
return 0;
}
void cardmeWriteEeprom(u32 address, u8 *apData, u32 aLength, u32 addrtype) {
switch(addrtype) {
case 1: {
cardmeWriteEepromT1(address,apData,aLength,addrtype);
return;
}break;
case 2: {
cardmeWriteEepromT2(address,apData,aLength,addrtype);
return;
}break;
case 3: {
cardmeWriteEepromT3(address,apData,aLength,addrtype);
return;
}break;
}
}
//////////////////////////////////////////////////////////////////////

52
arm9/include/cardme.h Normal file
View File

@ -0,0 +1,52 @@
/*
cardme by SaTa. for Public Domain
2005/10/30
NEW TYPE 2 ASPJ has 512kbit(64Kbyte)EEPROM
2005/10/21
NEW TYPE 3
cardmeChipErase use cardmeSectorErase
*/
#ifndef CARDME_HEADER_FIX_NDSLIB_HELP__WATASI_MOMOI_SUKIDESU_YOROSIKU
#define CARDME_HEADER_FIX_NDSLIB_HELP__WATASI_MOMOI_SUKIDESU_YOROSIKU
#include <nds.h>
#include <string.h>
//#include "dbg.h"
#ifdef __cplusplus
extern "C" {
#endif
void cardmeReadEeprom(u32 address, u8 *data, u32 length, u32 addrtype);
int cardmeChipErase(void); // USE TO TYPE 3 FLASH MEMORY ONLY
void cardmeSectorErase(u32 address);
int cardmeGetType(void); //
/*
-1:no card or no EEPROM
0:unknown PassMe?
1:TYPE 1 4Kbit(512Byte) EEPROM
2:TYPE 2 64Kbit(8KByte)or 512kbit(64Kbyte) EEPROM
3:TYPE 3 2Mbit(256KByte) FLASH MEMORY
*/
int cardmeSize(int tp);
/*
tp:1~3
return:size (byte)
*/
u8 cardmeReadID(int i) ; // don't work ??
u8 cardmeCMD(u8 cmd,int address) ;
/*void cardmeSectorUnlock(u32 address);
void cardmeChipUnlock(void);*/
void cardmeReadHeader(uint8 * header);
void cardmeWriteEeprom(u32 address, u8 *data, u32 length, u32 addrtype);
#ifdef __cplusplus
}
#endif
#endif //CARDME_HEADER_FIX_NDSLIB_HELP__WATASI_MOMOI_SUKIDESU_YOROSIKU

88
arm9/include/crc32.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef CRC32_H
#define CRC32_H
#ifdef __cplusplus
extern "C" {
#endif
#include <nds/ndstypes.h>
static const u32 crc32tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
};
u32 crc32(unsigned char *buf, u32 size) {
u32 i, crc;
crc = 0xFFFFFFFF;
for (i = 0; i < size; i++)crc = crc32tab[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
return crc^0xFFFFFFFF;
}
#ifdef __cplusplus
}
#endif
#endif

BIN
arm9/include/saveBinary.bin Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
.arm
.global saveBinary, saveBinaryEnd
saveBinary: .incbin "../include/saveBinary.bin"
saveBinaryEnd:

136
arm9/include/tonccpy.c Normal file
View File

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

43
arm9/include/tonccpy.h Normal file
View File

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

156
arm9/source/main.cpp Normal file
View File

@ -0,0 +1,156 @@
#include <nds.h>
#include <stdio.h>
#include <nds/arm9/console.h>
#include "font.h"
#include "tonccpy.h"
#include "crc32.h"
#include "cardme.h"
#define programSav 0x02000000
#define saveBuff 0x02000200
// #define saveTest 0x02000300
typedef struct sProgSAVStruct {
u8 padding[240];
u32 savCRC32;
u16 savCRC16;
u8 padding2[10];
u8 saveBinary[256];
} tProgSAVStruct;
volatile tProgSAVStruct* ProgSave;
volatile tProgSAVStruct* TestSave;
static PrintConsole tpConsole;
static PrintConsole btConsole;
extern PrintConsole* currentConsole;
static int bg;
static int bgSub;
const char* textBuffer = "X------------------------------X\nX------------------------------X";
volatile bool UpdateProgressText = false;
volatile bool PrintWithStat = false;
volatile bool ClearOnUpdate = true;
volatile int savetype = 0;
volatile u32 savesize = 0;
extern u8 saveBinary[512];
// DTCM_DATA u8 savebuf[512];
// DTCM_DATA u8 testbuf[256];
bool ReadOrWritePrompt() {
printf("\n Press [A] to test current save.");
printf("\n\n Press [B] to write new save\n and exit.\n");
while(1) {
swiWaitForVBlank();
scanKeys();
switch (keysDown()) {
case KEY_A:
consoleClear();
while(1) {
swiWaitForVBlank();
scanKeys();
if (keysUp())return true;
}
break;
case KEY_B: return false;
}
}
}
int ExitPrompt(bool isError) {
if (isError) {
printf("\n Failed to detect a valid\n save chip.\n");
} else {
printf("\n Finished save operations.\n");
}
printf("\n\n Press [A] to exit.\n");
while(1) {
swiWaitForVBlank();
scanKeys();
switch (keysDown()) {
case KEY_A: return 0;
}
}
return 0;
}
void CustomConsoleInit() {
videoSetMode(MODE_0_2D);
videoSetModeSub(MODE_0_2D);
vramSetBankA (VRAM_A_MAIN_BG);
vramSetBankC (VRAM_C_SUB_BG);
bg = bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 1, 0);
bgSub = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, 1, 0);
consoleInit(&btConsole, 3, BgType_Text4bpp, BgSize_T_256x256, 20, 0, false, false);
consoleInit(&tpConsole, 3, BgType_Text4bpp, BgSize_T_256x256, 20, 0, true, false);
ConsoleFont font;
font.gfx = (u16*)fontTiles;
font.pal = (u16*)fontPal;
font.numChars = 95;
font.numColors = fontPalLen / 2;
font.bpp = 4;
font.asciiOffset = 32;
font.convertSingleColor = true;
consoleSetFont(&btConsole, &font);
consoleSetFont(&tpConsole, &font);
consoleSelect(&tpConsole);
}
int main(void) {
defaultExceptionHandler();
CustomConsoleInit();
sysSetCartOwner(true);
printf("\n\n\n\n\n\n\n\n\n\n\n N-CARD SAVE BATTERY TESTER");
consoleSelect(&btConsole);
savetype = cardmeGetType();
if(savetype > 0)savesize = cardmeSize(savetype);
if ((savesize > 0) && (savetype > 0)) {
memset((u8*)saveBuff, 0xFF, 512);
memset((u8*)programSav, 0xFF, 512);
tonccpy((u8*)programSav, saveBinary, 512);
ProgSave = (tProgSAVStruct*)programSav;
if (ReadOrWritePrompt()) {
consoleClear();
// cardReadEeprom(0, (u8*)saveBuff, 512, savetype);
cardmeReadEeprom(0, (u8*)saveBuff, 512, savetype);
TestSave = (tProgSAVStruct*)saveBuff;
u16 get_crc16 = swiCRC16(0xFFFF, (void*)TestSave->saveBinary, 0x100);
u32 get_crc32 = crc32((unsigned char*)TestSave->saveBinary, 0x100);
iprintf(" Expected CRC16: %2X\n", (unsigned int)ProgSave->savCRC16);
iprintf(" Expected CRC32: %4X\n\n", (unsigned int)ProgSave->savCRC32);
iprintf(" Got save CRC16: %2X\n", (unsigned int)get_crc16);
iprintf(" Got save CRC32: %4X\n\n", (unsigned int)get_crc32);
if ((ProgSave->savCRC16 != get_crc16) || (ProgSave->savCRC32 != get_crc32)) {
if (ProgSave->savCRC16 != get_crc16)printf(" CRC16 mismatch!\n");
if (ProgSave->savCRC32 != get_crc32)printf(" CRC32 mismatch!\n\n");
printf(" Battery may need changing!");
}
} else {
if(savetype == 3)cardmeSectorErase(0);
cardmeWriteEeprom(0, (u8*)programSav, 512, savetype);
}
} else {
return ExitPrompt(true);
}
return ExitPrompt(false);
}

BIN
banner.bin Normal file

Binary file not shown.