Extract akmenu4 from woodrpg v1.25

This commit is contained in:
lifehackerhansol 2024-10-04 12:05:13 -07:00
parent f33df81056
commit 6fe395b92f
No known key found for this signature in database
GPG Key ID: 80FB184AFC0B3B0E
209 changed files with 1208467 additions and 0 deletions

114
Makefile Normal file
View File

@ -0,0 +1,114 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM)
endif
include $(DEVKITARM)/ds_rules
export TARGET := $(shell basename $(CURDIR))
export TOPDIR := $(CURDIR)
#---------------------------------------------------------------------------------
# path to tools - this can be deleted if you set the path in windows
#---------------------------------------------------------------------------------
export PATH := $(DEVKITARM)/bin:$(PATH)
.PHONY: all rpg r4 ak2i r4idsn clean
.PHONY: arm7/rpg/$(TARGET).arm7 arm9/rpg/$(TARGET).arm9
.PHONY: arm7/r4/$(TARGET).arm7 arm9/r4/$(TARGET).arm9
.PHONY: arm7/ak2i/$(TARGET).arm7 arm9/ak2i/$(TARGET).arm9
.PHONY: arm7/r4idsn/$(TARGET).arm7 arm9/r4idsn/$(TARGET).arm9
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all: rpg r4
#---------------------------------------------------------------------------------
# rpg target
#---------------------------------------------------------------------------------
rpg: $(TARGET).nds
#---------------------------------------------------------------------------------
# r4 target
#---------------------------------------------------------------------------------
r4: _DS_MENU.DAT
#---------------------------------------------------------------------------------
# ak2i target
#---------------------------------------------------------------------------------
ak2i: ak2i/$(TARGET).nds
#---------------------------------------------------------------------------------
# r4idsn target
#---------------------------------------------------------------------------------
r4idsn: _DSMENU.DAT
#---------------------------------------------------------------------------------
$(TARGET).nds : arm7/rpg/$(TARGET).arm7 arm9/rpg/$(TARGET).arm9
ndstool -c $(TARGET).nds -7 arm7/rpg/$(TARGET).arm7 -9 arm9/rpg/$(TARGET).arm9 -e9 0x02000450 -e7 0x02380000 -b $(TARGET).bmp "acekard;Real Play Gear;www.acekard.com"
#---------------------------------------------------------------------------------
arm7/rpg/$(TARGET).arm7:
$(MAKE) -C arm7
#---------------------------------------------------------------------------------
arm9/rpg/$(TARGET).arm9:
$(MAKE) -C arm9
#---------------------------------------------------------------------------------
_DS_MENU.DAT : $(TARGET)_r4.nds
r4denc $(TARGET)_r4.nds _DS_MENU.DAT
#---------------------------------------------------------------------------------
$(TARGET)_r4.nds : arm7/r4/$(TARGET).arm7 arm9/r4/$(TARGET).arm9
ndstool -c $(TARGET)_r4.nds -7 arm7/r4/$(TARGET).arm7 -9 arm9/r4/$(TARGET).arm9 -e9 0x02000450 -e7 0x02380000 -b $(TARGET).bmp "wood r4"
#---------------------------------------------------------------------------------
arm7/r4/$(TARGET).arm7:
$(MAKE) -C arm7 STORAGE=r4
#---------------------------------------------------------------------------------
arm9/r4/$(TARGET).arm9:
$(MAKE) -C arm9 STORAGE=r4
#---------------------------------------------------------------------------------
ak2i/$(TARGET).nds : arm7/ak2i/$(TARGET).arm7 arm9/ak2i/$(TARGET).arm9
mkdir -p ak2i
ndstool -c ak2i/$(TARGET).nds -7 arm7/ak2i/$(TARGET).arm7 -9 arm9/ak2i/$(TARGET).arm9 -e9 0x02000450 -e7 0x02380000 -b $(TARGET).bmp "wood ak2i"
#---------------------------------------------------------------------------------
_DSMENU.DAT : arm7/r4idsn/$(TARGET).arm7 arm9/r4idsn/$(TARGET).arm9
ndstool -c _DSMENU.DAT -7 arm7/r4idsn/$(TARGET).arm7 -9 arm9/r4idsn/$(TARGET).arm9 -e9 0x02000000 -e7 0x02380000 -b $(TARGET).bmp "wood r4idsn"
#---------------------------------------------------------------------------------
arm7/ak2i/$(TARGET).arm7:
$(MAKE) -C arm7 STORAGE=ak2i
#---------------------------------------------------------------------------------
arm9/ak2i/$(TARGET).arm9:
$(MAKE) -C arm9 STORAGE=ak2i
#---------------------------------------------------------------------------------
arm7/r4idsn/$(TARGET).arm7:
$(MAKE) -C arm7 STORAGE=r4idsn
#---------------------------------------------------------------------------------
arm9/r4idsn/$(TARGET).arm9:
$(MAKE) -C arm9 STORAGE=r4idsn
#---------------------------------------------------------------------------------
clean:
$(MAKE) -C arm9 clean
$(MAKE) -C arm7 clean
$(MAKE) -C arm9 STORAGE=r4 clean
$(MAKE) -C arm7 STORAGE=r4 clean
$(MAKE) -C arm9 STORAGE=ak2i clean
$(MAKE) -C arm7 STORAGE=ak2i clean
$(MAKE) -C arm9 STORAGE=r4idsn clean
$(MAKE) -C arm7 STORAGE=r4idsn clean
rm -f $(TARGET).nds _DS_MENU.DAT $(TARGET)_r4.nds _DSMENU.DAT
rm -rf ak2i

BIN
akmenu4.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

137
arm7/Makefile Normal file
View File

@ -0,0 +1,137 @@
#---------------------------------------------------------------------------------
.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
#---------------------------------------------------------------------------------
STORAGE ?= rpg
BUILD := $(STORAGE)/build
SOURCES := source
INCLUDES := include $(BUILD)
DATA :=
CRT := crt/ds_arm7_crt1.o
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb-interwork
CFLAGS := -g -Wall -Os\
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
-ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM7 -fno-dwarf2-cfi-asm
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -fno-rtti
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=../../specs/ds_arm7.specs -g $(ARCH) -mno-fpu -Wl,-Map,$(notdir $*).map
LIBS := -lunds7
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(LIBUNDS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(notdir $(BUILD)),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export ARM7BIN := $(CURDIR)/$(STORAGE)/$(TARGET).arm7
export ARM7ELF := $(CURDIR)/$(STORAGE)/$(TARGET).arm7.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 $@
@[ -d $@/crt ] || mkdir -p $@/crt
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(STORAGE) *.elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(ARM7BIN) : $(ARM7ELF)
@$(OBJCOPY) -O binary $< $@
@echo built ... $(notdir $@)
$(ARM7ELF) : $(OFILES) $(CRT)
@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)
$(CRT) : $(CRT:.o=.s)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,104 @@
@---------------------------------------------------------------------------------
.arch armv4t
.cpu arm7tdmi
.section ".init"
.global _start
@---------------------------------------------------------------------------------
.align 4
.arm
@---------------------------------------------------------------------------------
_start:
@---------------------------------------------------------------------------------
mov r0, #0x04000000 @ IME = 0;
mov r1, #0
str r1, [r0, #0x208]
mov r0, #0x12 @ Switch to IRQ Mode
msr cpsr, r0
ldr sp, =__sp_irq @ Set IRQ stack
mov r0, #0x13 @ Switch to SVC Mode
msr cpsr, r0
ldr sp, =__sp_svc @ Set SVC stack
mov r0, #0x1F @ Switch to System Mode
msr cpsr, r0
ldr sp, =__sp_usr @ Set user stack
ldr r1, =__iwram_lma
ldr r2, =__iwram_start
ldr r4, =__iwram_end
bl CopyMemCheck
ldr r0, =__bss_start @ Clear BSS section to 0x00
ldr r1, =__bss_end
sub r1, r1, r0
bl ClearMem
ldr r3, =__libc_init_array @ global constructors
bl _blx_r3_stub
mov r0, #0 @ int argc
mov r1, #0 @ char *argv[]
ldr r3, =main
ldr lr,=__libnds_exit
bx r3
@---------------------------------------------------------------------------------
_blx_r3_stub:
@---------------------------------------------------------------------------------
bx r3
@---------------------------------------------------------------------------------
@ Clear memory to 0x00 if length != 0
@ r0 = Start Address
@ r1 = Length
@---------------------------------------------------------------------------------
ClearMem:
@---------------------------------------------------------------------------------
mov r2, #3 @ Round down to nearest word boundary
add r1, r1, r2 @ Shouldn't be needed
bics r1, r1, r2 @ Clear 2 LSB (and set Z)
bxeq lr @ Quit if copy size is 0
mov r2, #0
ClrLoop:
stmia r0!, {r2}
subs r1, r1, #4
bne ClrLoop
bx lr
@---------------------------------------------------------------------------------
@ Copy memory if length != 0
@ r1 = Source Address
@ r2 = Dest Address
@ r4 = Dest Address + Length
@---------------------------------------------------------------------------------
CopyMemCheck:
@---------------------------------------------------------------------------------
sub r3, r4, r2 @ Is there any data to copy?
@---------------------------------------------------------------------------------
@ Copy memory
@ r1 = Source Address
@ r2 = Dest Address
@ r3 = Length
@---------------------------------------------------------------------------------
CopyMem:
@---------------------------------------------------------------------------------
mov r0, #3 @ These commands are used in cases where
add r3, r3, r0 @ the length is not a multiple of 4,
bics r3, r3, r0 @ even though it should be.
bxeq lr @ Length is zero, so exit
CIDLoop:
ldmia r1!, {r0}
stmia r2!, {r0}
subs r3, r3, #4
bne CIDLoop
bx lr
@---------------------------------------------------------------------------------
.align
.pool
.end
@---------------------------------------------------------------------------------

178
arm7/source/main.cpp Normal file
View File

@ -0,0 +1,178 @@
/*
main.cpp
Copyright (C) 2008-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <nds.h>
#include <string.h>
#include "../../share/fifotool.h"
#include "../../share/memtool.h"
#ifdef __cplusplus
extern "C" {
#endif
void __libnds_exit(int rc) {}
#ifdef __cplusplus
}
#endif
void VblankHandler(void)
{
inputGetAndSend();
}
#define PM_NDSLITE_ADR (4)
#define PM_CONTROL2_REG (16)
#define PM_CONTROL2_RESET (1)
#define PM_NDSLITE_ISLITE BIT(6)
#define PM_NDSLITE_BRIGHTNESS(x) ((x&0x03)<<0)
#define PM_NDSLITE_BRIGHTNESS_MASK (PM_NDSLITE_BRIGHTNESS(3))
static u32 getSystem(void)
{
static u32 dsGen=0;
if(!dsGen)
{
dsGen=1; // default ds phat
if(readPowerManagement(PM_NDSLITE_ADR)&PM_NDSLITE_ISLITE) dsGen++; // dslite and dsi
if(readPowerManagement(PM_NDSLITE_ADR)==readPowerManagement(5)) dsGen++; // dslite
}
return dsGen;
}
static void prepairReset()
{
//enable sound
if(2==getSystem()) writePowerManagement(PM_CONTROL_REG,(readPowerManagement(PM_CONTROL_REG)&~PM_SOUND_MUTE)|PM_SOUND_AMP);
//disble rtc irq, on some games enabled rtc irq caused tearing.
uint8 command[2];
command[0]=WRITE_STATUS_REG2;
command[1]=0x00;
rtcTransaction(command,2,0,0);
REG_POWERCNT|=POWER_SOUND;
//reset DMA
zeroMemory((void *)0x40000B0,0x30);
REG_IME=IME_DISABLE;
REG_IE=0;
REG_IF=~0;
fifoSendValue32(FIFO_USER_01,MENU_MSG_ARM7_READY_BOOT);
swiDelay(1);
}
static void brightnessNext(void)
{
u8 data=readPowerManagement(PM_NDSLITE_ADR);
if(0==(data&PM_NDSLITE_ISLITE)) // this is not a DS Lite machine
return;
u8 level=data&PM_NDSLITE_BRIGHTNESS_MASK;
level++;
data&=~PM_NDSLITE_BRIGHTNESS_MASK;
data|=PM_NDSLITE_BRIGHTNESS(level);
writePowerManagement(PM_NDSLITE_ADR,data);
}
static void brightnessSet(u8 level)
{
u8 data=readPowerManagement(PM_NDSLITE_ADR);
if(0==(data&PM_NDSLITE_ISLITE)) // this is not a DS Lite machine
return;
data&=~PM_NDSLITE_BRIGHTNESS_MASK;
data|=PM_NDSLITE_BRIGHTNESS(level);
writePowerManagement(PM_NDSLITE_ADR,data);
}
static u8 brightnessGet(void)
{
u8 data=readPowerManagement(PM_NDSLITE_ADR);
if(0==(data&PM_NDSLITE_ISLITE)) // this is not a DS Lite machine
return 0;
return data&PM_NDSLITE_BRIGHTNESS_MASK;
}
static void menuValue32Handler(u32 value,void* data)
{
switch(value)
{
case MENU_MSG_GBA:
{
u32 ii=0;
if(PersonalData->gbaScreen)
ii=(1*PM_BACKLIGHT_BOTTOM)|PM_SOUND_AMP;
else
ii=(1*PM_BACKLIGHT_TOP)|PM_SOUND_AMP;
writePowerManagement(PM_CONTROL_REG,ii);
swiChangeSoundBias(0,0x400);
swiSwitchToGBAMode();
}
break;
case MENU_MSG_ARM7_REBOOT:
prepairReset();
swiSoftReset();
break;
case MENU_MSG_BRIGHTNESS_NEXT:
brightnessNext();
break;
case MENU_MSG_SYSTEM:
fifoSendValue32(FIFO_USER_02,getSystem());
break;
case MENU_MSG_BRIGHTNESS_GET:
fifoSendValue32(FIFO_USER_01,brightnessGet());
break;
case MENU_MSG_BRIGHTNESS_SET0:
case MENU_MSG_BRIGHTNESS_SET1:
case MENU_MSG_BRIGHTNESS_SET2:
case MENU_MSG_BRIGHTNESS_SET3:
brightnessSet(value&3);
break;
case MENU_MSG_SHUTDOWN:
if(2==getSystem()) writePowerManagement(PM_CONTROL2_REG,readPowerManagement(PM_CONTROL2_REG)|PM_CONTROL2_RESET);
else systemShutDown();
default:
break;
}
}
int main()
{
//mute sound
if(2==getSystem()) writePowerManagement(PM_CONTROL_REG,(readPowerManagement(PM_CONTROL_REG)&~PM_SOUND_AMP)|PM_SOUND_MUTE);
//switch on backlight on both screens
writePowerManagement(PM_CONTROL_REG,readPowerManagement(PM_CONTROL_REG)|PM_BACKLIGHT_BOTTOM|PM_BACKLIGHT_TOP);
// read User Settings from firmware
readUserSettings();
irqInit();
fifoInit();
// Start the RTC tracking IRQ
initClockIRQ();
fifoSetValue32Handler(FIFO_USER_01,menuValue32Handler,0);
installSystemFIFO();
irqSet(IRQ_VBLANK,VblankHandler);
irqEnable(IRQ_VBLANK|IRQ_NETWORK);
while(true) swiWaitForVBlank();
}

198
arm7/specs/ds_arm7.ld Normal file
View File

@ -0,0 +1,198 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
MEMORY {
rom : ORIGIN = 0x08000000, LENGTH = 32M
iwram : ORIGIN = 0x03800000, LENGTH = 64K
awram : ORIGIN = 0x02380000, LENGTH = 128K
}
__iwram_start = ORIGIN(iwram);
__iwram_top = ORIGIN(iwram)+ LENGTH(iwram);
__awram_start = ORIGIN(awram);
__awram_top = ORIGIN(awram)+ LENGTH(awram);
__sp_irq = __iwram_top - 0x100;
__sp_svc = __sp_irq - 0x100;
__sp_usr = __sp_svc - 0x100;
__irq_flags = 0x04000000 - 8;
__irq_flagsaux = 0x04000000 - 0x40;
__irq_vector = 0x04000000 - 4;
SECTIONS
{
.init :
{
__text_start = . ;
KEEP (*(.init))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >awram = 0xff
__iwram_lma = . ;
.plt : { *(.plt) } >iwram AT>awram = 0xff
.text : /* ALIGN (4): */
{
*(.text .stub .text.* .gnu.linkonce.t.*)
KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.glue_7t) *(.glue_7) *(.vfp11_veneer)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >iwram = 0xff
.fini :
{
KEEP (*(.fini))
} >iwram =0xff
__text_end = . ;
.rodata :
{
*(.rodata)
*all.rodata*(*)
*(.roda)
*(.rodata.*)
*(.gnu.linkonce.r*)
SORT(CONSTRUCTORS)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >iwram = 0xff
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >iwram
__exidx_start = .;
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >iwram
__exidx_end = .;
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
the linker would then create the section even if it turns out to
be empty, which isn't pretty. */
. = ALIGN(32 / 8);
PROVIDE (__preinit_array_start = .);
.preinit_array : { KEEP (*(.preinit_array)) } >iwram = 0xff
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
.init_array : { KEEP (*(.init_array)) } >iwram = 0xff
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
.fini_array : { KEEP (*(.fini_array)) } >iwram = 0xff
PROVIDE (__fini_array_end = .);
.ctors :
{
/* gcc uses crtbegin.o to find the start of the constructors, so
we make sure it is first. Because this is a wildcard, it
doesn't matter if the user does not actually link against
crtbegin.o; the linker won't look for a file to match a
wildcard. The wildcard also means that it doesn't matter which
directory crtbegin.o is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >iwram = 0xff
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >iwram = 0xff
.eh_frame :
{
KEEP (*(.eh_frame))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >iwram = 0xff
.gcc_except_table :
{
*(.gcc_except_table)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >iwram = 0xff
.jcr : { KEEP (*(.jcr)) } >iwram = 0
.got : { *(.got.plt) *(.got) } >iwram = 0
.iwram ALIGN(4) :
{
*(.iwram)
*iwram.*(.text)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >iwram = 0xff
.data ALIGN(4) : {
__data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
CONSTRUCTORS
. = ALIGN(4);
__data_end = ABSOLUTE(.) ;
__iwram_end = ABSOLUTE(.);
} >iwram = 0xff
.bss ALIGN(4) :
{
__bss_start = ABSOLUTE(.);
__bss_start__ = ABSOLUTE(.);
*(.dynbss)
*(.gnu.linkonce.b*)
*(.bss*)
*(COMMON)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >iwram
__bss_end = . ;
__bss_end__ = . ;
_end = . ;
__end__ = . ;
PROVIDE (end = _end);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.stack 0x80000 : { _stack = .; *(.stack) }
/* These must appear regardless of . */
}

8
arm7/specs/ds_arm7.specs Normal file
View File

@ -0,0 +1,8 @@
%rename link old_link
*link:
%(old_link) -T ../../specs/ds_arm7.ld%s
*startfile:
crt/ds_arm7_crt1%O%s crti%O%s crtbegin%O%s

150
arm9/Makefile Normal file
View File

@ -0,0 +1,150 @@
#---------------------------------------------------------------------------------
.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
#---------------------------------------------------------------------------------
STORAGE ?= rpg
BUILD := $(STORAGE)/build
SOURCES := source source/ui ../share source/font
INCLUDES := source source/ui ../share source/font $(BUILD)
DATA := data data/$(STORAGE)
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb -mthumb-interwork
#
# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD
# *insists* it has a FPU or VFP, and it won't take no for an answer!
CFLAGS := -g -Wall -Os\
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
-ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM9 -fno-dwarf2-cfi-asm -D_STORAGE_$(STORAGE)
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
#--ansi
ASFLAGS := -g $(ARCH) -march=armv5te -mtune=arm946e-s -D_STORAGE_$(STORAGE)
LDFLAGS = -specs=../../specs/ds_arm9.specs -g $(ARCH) -mno-fpu -Wl,-Map,$(notdir $*.map)
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lelm -lio$(STORAGE) -lunds9
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(LIBELM) $(LIBUNDS)
ifeq ($(STORAGE),rpg)
LIBDIRS += $(LIBIORPG)
endif
ifeq ($(STORAGE),r4)
LIBDIRS += $(LIBIOR4)
endif
ifeq ($(STORAGE),ak2i)
LIBDIRS += $(LIBIOAK2I)
endif
ifeq ($(STORAGE),r4idsn)
LIBDIRS += $(LIBIOR4IDSN)
endif
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(notdir $(BUILD)),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export ARM9BIN := $(CURDIR)/$(STORAGE)/$(TARGET).arm9
export ARM9ELF := $(CURDIR)/$(STORAGE)/$(TARGET).arm9.elf
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(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)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
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)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(STORAGE) *.elf *.nds* *.bin
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(ARM9BIN) : $(ARM9ELF)
@$(OBJCOPY) -O binary $< $@
@echo built ... $(notdir $@)
$(ARM9ELF) : $(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
#---------------------------------------------------------------------------------------

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
arm9/data/folder_banner.bin Normal file

Binary file not shown.

BIN
arm9/data/gba_banner.bin Normal file

Binary file not shown.

BIN
arm9/data/gba_nes_patch.bin Normal file

Binary file not shown.

Binary file not shown.

BIN
arm9/data/gbarom_banner.bin Normal file

Binary file not shown.

1
arm9/data/icon_bg.bin Normal file
View File

@ -0,0 +1 @@
ΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσΌχσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοσyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyοyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyοyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8η8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8ηyο8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8η8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφήφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8η8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφήφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8η8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφήφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8η8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφή8ηφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφή

Binary file not shown.

BIN
arm9/data/nand_banner.bin Normal file

Binary file not shown.

BIN
arm9/data/nds_banner.bin Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

72
arm9/source/animation.cpp Normal file
View File

@ -0,0 +1,72 @@
/*
animation.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "animation.h"
cAnimation::cAnimation()
{
_visible = false;
}
cAnimation::~cAnimation()
{
}
void cAnimation::show()
{
_visible = true;
}
void cAnimation::hide()
{
_visible = false;
}
cAnimationManager::cAnimationManager()
{
}
cAnimationManager::~cAnimationManager()
{
}
void cAnimationManager::update()
{
std::list< cAnimation * >::iterator itr = _animations.begin();
while( itr != _animations.end() )
{
(*itr)->update();
++itr;
}
}
void cAnimationManager::addAnimation( cAnimation * animation )
{
_animations.push_back( animation );
}
void cAnimationManager::removeAnimation( cAnimation * animation )
{
_animations.remove( animation );
}

80
arm9/source/animation.h Normal file
View File

@ -0,0 +1,80 @@
/*
animation.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ANIMATION_H_
#define _ANIMATION_H_
#include "ui.h"
class cAnimation
{
public:
cAnimation();
virtual ~cAnimation();
public:
virtual void update() = 0;
void show();
void hide();
bool visible() { return _visible; }
protected:
akui::cPoint _position;
akui::cSize _size;
bool _visible;
};
class cAnimationManager
{
public:
cAnimationManager();
~cAnimationManager();
public:
void update();
void addAnimation( cAnimation * animation );
void removeAnimation( cAnimation * animation );
protected:
std::list< cAnimation * > _animations;
};
typedef t_singleton< cAnimationManager > animationManager_s;
inline cAnimationManager & animationManager() { return animationManager_s::instance(); }
#endif//_ANIMATION_H_

129
arm9/source/bigclock.cpp Normal file
View File

@ -0,0 +1,129 @@
/*
bigclock.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "bigclock.h"
#include "../../share/stringtool.h"
#include "systemfilenames.h"
#include "windowmanager.h"
#include "inifile.h"
#include "globalsettings.h"
using namespace akui;
cBigClock::cBigClock() : cWindow( NULL, "big clock" )
{
_size = cSize( 0, 0 );
_position = cPoint( 8, 80 );
_engine = GE_SUB;
_show = false;
_colonShow = false;
_ampmShow = false;
_ampmColor = RGB15(17,12,0);
}
void cBigClock::init()
{
loadAppearance( SFN_UI_SETTINGS );
}
cWindow& cBigClock::loadAppearance(const std::string& aFileName )
{
CIniFile ini( aFileName );
_position.x = ini.GetInt( "big clock", "x", 8 );
_position.y = ini.GetInt( "big clock", "y", 80 );
_show = ini.GetInt( "big clock", "show", _show );
_ampmPosition.x = ini.GetInt( "am pm", "x", 8 );
_ampmPosition.y = ini.GetInt( "am pm", "y", 80 );
_ampmShow = ini.GetInt( "am pm", "show", _ampmShow );
_ampmColor = ini.GetInt( "am pm", "color", _ampmColor );
_numbers = createBMP15FromFile( SFN_CLOCK_NUMBERS );
_colon = createBMP15FromFile( SFN_CLOCK_COLON );
return *this;
}
void cBigClock::drawNumber( u8 id, u8 number )
{
if( number > 10 )
return;
u8 x = _position.x + id * (_numbers.width() + 2);
if( id > 2 ) {// minute number
x -= 8;
}
if( _numbers.valid() )
{
u8 w = _numbers.width();
u8 h = _numbers.height() / 10;
u8 pitch = _numbers.pitch()>>1;
gdi().maskBlt( _numbers.buffer() + number * pitch * h / 2, x, _position.y, w, h, selectedEngine() );
}
}
void cBigClock::drawColon()
{
u8 x = _position.x + 2 * _numbers.width();
if( _colon.valid() ) {
gdi().maskBlt( _colon.buffer(),
x, _position.y, _colon.width(), _colon.height(), selectedEngine() );
}
}
void cBigClock::draw()
{
if( !_show )
return;
u8 hours = datetime().hours();
u8 minutes = datetime().minutes();
const char* ampm=(hours<12)?"AM":"PM";
if(gs().show12hrClock)
{
if(hours>12) hours-=12;
if(hours==0) hours=12;
}
u8 number1 = hours / 10;
u8 number2 = hours % 10;
u8 number3 = minutes / 10;
u8 number4 = minutes % 10;
//u8 number5 = datetime().seconds() / 10;
//u8 number6 = datetime().seconds() % 10;
drawNumber( 0, number1 );
drawNumber( 1, number2 );
drawNumber( 3, number3 );
drawNumber( 4, number4 );
if( _colonShow)
drawColon();
if(gs().show12hrClock&&_ampmShow)
{
gdi().setPenColor(_ampmColor,_engine);
gdi().textOut(_ampmPosition.x,_ampmPosition.y,ampm,_engine);
}
}
void cBigClock::blinkColon()
{
_colonShow = !_colonShow;
}

70
arm9/source/bigclock.h Normal file
View File

@ -0,0 +1,70 @@
/*
bigclock.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _BIGCLOCK_H_
#define _BIGCLOCK_H_
#include "window.h"
#include "bmp15.h"
#include "datetime.h"
#include "singleton.h"
//class cClockNumber : public
class cBigClock : public akui::cWindow
{
public:
cBigClock();
~cBigClock() {}
public:
void init();
void draw();
void blinkColon();
akui::cWindow & loadAppearance(const std::string& aFileName );
protected:
void drawNumber( u8 id, u8 number );
void drawColon();
cBMP15 _numbers;
cBMP15 _colon;
bool _show;
bool _colonShow;
bool _ampmShow;
akui::cPoint _ampmPosition;
COLOR _ampmColor;
};
typedef t_singleton< cBigClock > bigClock_s;
inline cBigClock & bigClock() { return bigClock_s::instance(); }
#endif//_BIGCLOCK_H_

151
arm9/source/bmp15.cpp Normal file
View File

@ -0,0 +1,151 @@
/*
bmp15.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
//<2F>
#include <list>
#include <string>
#include "bmp15.h"
#include "dbgtool.h"
cBMP15::cBMP15() : _width(0), _height(0), _pitch(0), _buffer(NULL)
{
}
cBMP15::cBMP15( u32 width, u32 height ) : _width(0), _height(0), _pitch(0), _buffer(NULL)
{
_width = width;
_height = height;
_pitch = (width + (width & 1)) << 1;
//u32 pitch = (((width*16)+31)>>5)<<2; // 通用算法?
}
cBMP15::~cBMP15()
{
// dbg_printf( "cBMP15 %08x destructed\n", this );
}
cBMP15 createBMP15( u32 width, u32 height )
{
cBMP15 bmp( width, height );
u32 pitch = bmp.pitch(); // 15bit bmp pitch 算法
//dbg_printf( "pitch: %d bytes\n", pitch );
//dbg_printf( "buffer %08x\n", bmp.buffer() );
u32 bufferSize = height * pitch;
if( bufferSize & 3 ) // 如果 bufferSize 不是按4字节对齐就把他调整到对齐
bufferSize += 4 - (bufferSize & 3);
bmp._buffer = new u32[bufferSize>>2];
return bmp;
}
typedef std::pair< std::string, cBMP15 > str_bmp_pair;
typedef std::list< str_bmp_pair > str_bmp_list;
static str_bmp_list _bmpPool;
cBMP15 createBMP15FromMem( void * mem )
{
return cBMP15();
}
cBMP15 createBMP15FromFile( const std::string & filename )
{
//dbg_printf( "createBMP15FromFile (%s)\n", filename );
str_bmp_list::iterator it;
for( it = _bmpPool.begin(); it != _bmpPool.end(); ++it )
{
if( filename == it->first ) {
return it->second;
}
}
FILE * f = fopen( filename.c_str(), "rb" );
if( NULL == f ) {
dbg_printf("(%s) file does not exist\n", filename.c_str() );
return cBMP15();
}
// 读取文件长度
fseek( f, 0, SEEK_END );
int fileSize = ftell( f );
if( -1 == fileSize ) {
fclose( f );
return cBMP15();
}
u16 bmMark = 0;
fseek( f, 0, SEEK_SET );
fread( &bmMark, 1, 2, f );
if( bmMark != 0x4d42 ) {// 'B' 'M' header
dbg_printf( "not a bmp file\n" );
fclose( f );
return cBMP15();
}
// 找出bmp高和宽
u32 width = 0;
u32 height = 0;
fseek( f, 0x12, SEEK_SET );
fread( &width, 1, 4, f );
fseek( f, 0x16, SEEK_SET );
fread( &height, 1, 4, f );
//dbg_printf( "w:%d h:%d\n", width, height );
cBMP15 bmp = createBMP15( width, height );
u32 bmpDataOffset = 0;
fseek( f, 0x0a, SEEK_SET );
fread( &bmpDataOffset, 1, 4, f );
long position = bmpDataOffset;
fseek( f, position, SEEK_SET );
u16 * pbuffer = ((u16 *)bmp.buffer()) + (bmp.pitch()>>1) * height - (bmp.pitch()>>1);
for( u32 i = 0; i < height; ++i ) {
fread( pbuffer, 1, bmp.pitch(), f );
position += bmp.pitch();
pbuffer -= bmp.pitch() >> 1;
fseek( f, position, SEEK_SET );
}
fclose( f );
pbuffer = (u16 *)bmp.buffer();
for( u32 i = 0; i < height; ++i )
{
for( u32 j = 0; j < (bmp.pitch()>>1); ++j )
{
u16 pixelColor = pbuffer[i*(bmp.pitch()>>1)+j];
pixelColor = ((pixelColor & 0x7C00) >> 10)
| ((pixelColor & 0x03E0)) | ((pixelColor & 0x1F) << 10);
pbuffer[i*(bmp.pitch()>>1)+j] = pixelColor | (pixelColor ? BIT(15):0);
//dbg_printf("%d %d\n", j, i );
}
}
str_bmp_pair bmpPoolItem( std::string(filename), bmp );
_bmpPool.push_back( bmpPoolItem );
//dbg_printf( "load bmp success, %08x\n", bmp.buffer() );
return bmp;
}

73
arm9/source/bmp15.h Normal file
View File

@ -0,0 +1,73 @@
/*
bmp15.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _BMP15_H_
#define _BMP15_H_
#include <nds.h>
#include <memory>
#include <string>
class cBMP15
{
friend cBMP15 createBMP15( u32 width, u32 height );
friend cBMP15 createBMP15FromFile( const std::string & filename );
friend cBMP15 createBMP15FromMem( void * mem );
//friend void destroyBMP15( cBMP15 * bmp );
public:
explicit cBMP15();
explicit cBMP15( u32 width, u32 height );
~cBMP15();
public:
u32 width() const { return _width; } // width is memory bitmap's width
u32 height() const { return _height; } // height is memory bitmap's height
u32 pitch() const { return _pitch; } // pitch returns bytes per line
u32 * buffer() { return _buffer; }
const u32 * buffer() const { return _buffer; }
bool valid() const { return NULL != _buffer; }
protected:
u32 _width;
u32 _height;
u32 _pitch;
u32 * _buffer; // 按 32 位地址对齐,可以在 bitblt 的时候加快速度
};
cBMP15 createBMP15( u32 width, u32 height );
cBMP15 createBMP15FromFile( const std::string & filename );
cBMP15 createBMP15FromMem( void * mem );
//void destroyBMP15( cBMP15 * bmp );
//void destroyBMP15ByFilename( const char * filename );
#endif//_BMP15_H_

160
arm9/source/calendar.cpp Normal file
View File

@ -0,0 +1,160 @@
/*
calendar.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "calendar.h"
#include "systemfilenames.h"
#include "windowmanager.h"
#include "inifile.h"
#include "globalsettings.h"
#include "../../share/stringtool.h"
#include "../../share/memtool.h"
using namespace akui;
cCalendar::cCalendar() : cWindow( NULL, "calendar" )
{
_size = cSize( 0, 0 );
_position = cPoint( 134, 34 );
_engine = GE_SUB;
_showYear = false;
_showMonth = false;
_showDayX = false;
_showDay = false;
}
void cCalendar::init()
{
loadAppearance( SFN_UI_SETTINGS );
}
cWindow& cCalendar::loadAppearance(const std::string& aFileName )
{
// load day number
_dayNumbers = createBMP15FromFile( SFN_DAY_NUMBERS );
// load year number
_yearNumbers = createBMP15FromFile( SFN_YEAR_NUMBERS );
CIniFile ini( aFileName );
_dayPosition.x = ini.GetInt( "calendar day", "x", 134 );
_dayPosition.y = ini.GetInt( "calendar day", "y", 34 );
_daySize.x = ini.GetInt( "calendar day", "dw", 16 );
_daySize.y = ini.GetInt( "calendar day", "dh", 14 );
_dayHighlightColor = ini.GetInt( "calendar day", "highlightColor", 0xfc00 );
_showDay = ini.GetInt( "calendar day", "show", _showDay );
_dayxPosition.x = ini.GetInt( "calendar dayx", "x", 0 );
_dayxPosition.y = ini.GetInt( "calendar dayx", "y", 28 );
_showDayX = ini.GetInt( "calendar dayx", "show", _showDayX );
_monthPosition.x = ini.GetInt( "calendar month", "x", 12 );
_monthPosition.y = ini.GetInt( "calendar month", "y", 28 );
_showMonth = ini.GetInt( "calendar month", "show", _showMonth );
_yearPosition.x = ini.GetInt( "calendar year", "x", 52 );
_yearPosition.y = ini.GetInt( "calendar year", "y", 28 );
_showYear = ini.GetInt( "calendar year", "show", _showYear );
return *this;
}
#define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0)
static u8 daysOfMonth() {
return ( 28 | (((IS_LEAP(datetime().year())? 62648028 : 62648012) >> (datetime().month()*2)) & 3) );
}
void cCalendar::drawDayNumber( u8 day )
{
if( day > 31 )
return;
u8 weekDayOfDay = (((day - 1) % 7) + weekDayOfFirstDay()) % 7;
u8 x = weekDayOfDay * _daySize.x + _dayPosition.x;
u8 y = ((day - 1 + weekDayOfFirstDay()) / 7 * _daySize.y) + _dayPosition.y;
u8 pitch = _dayNumbers.pitch()>>1;
u8 w = _dayNumbers.width();
u8 h = _dayNumbers.height() / 10;
u8 firstNumber = day / 10;
u8 secondNumber = day % 10;
if( day == datetime().day() )
gdi().fillRect( _dayHighlightColor, _dayHighlightColor,
x-(_daySize.x/2-w), y-(_daySize.y-h)/2, _daySize.x-1, _daySize.y-1, selectedEngine() );
if( _dayNumbers.valid() ) {
gdi().maskBlt( _dayNumbers.buffer() + firstNumber * pitch * h / 2, x, y, w, h, selectedEngine() );
gdi().maskBlt( _dayNumbers.buffer() + secondNumber * pitch * h / 2, x+w, y, w, h, selectedEngine() );
}
}
u8 cCalendar::weekDayOfFirstDay()
{
return (datetime().weekday() + 7 - (( datetime().day() - 1) % 7)) % 7;
}
void cCalendar::drawNumber( const akui::cPoint& position, u32 index, u32 value )
{
if( !_yearNumbers.valid() )
return;
u8 w = _yearNumbers.width();
u8 h = _yearNumbers.height() / 10;
u8 pitch = _yearNumbers.pitch()>>1;
u8 x = position.x + index * w;
u8 y = position.y;
gdi().maskBlt( _yearNumbers.buffer() + value * pitch * h / 2, x, y, w, h, selectedEngine() );
}
void cCalendar::drawText( const akui::cPoint& position, u32 value, u32 factor )
{
u32 ii = 0;
while( true )
{
u8 number = value / factor;
value %= factor;
drawNumber( position, ii, number );
factor /= 10;
ii++;
if(0 == factor) break;
}
}
void cCalendar::draw()
{
if( _showDay ) {
for( u8 i = 1; i <= daysOfMonth(); ++i )
{
drawDayNumber( i );
}
}
if( _showDayX ) {
drawText( _dayxPosition, datetime().day(), 10 );
}
if( _showMonth ) {
drawText( _monthPosition, datetime().month(), 10 );
}
if( _showYear ) {
drawText( _yearPosition, datetime().year(), 1000 );
}
}

77
arm9/source/calendar.h Normal file
View File

@ -0,0 +1,77 @@
/*
calendar.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CALENDAR_H_
#define _CALENDAR_H_
#include "window.h"
#include "bmp15.h"
#include "datetime.h"
#include "singleton.h"
#include "point.h"
class cCalendar : public akui::cWindow
{
public:
cCalendar();
~cCalendar() {}
public:
void init();
void draw();
akui::cWindow & loadAppearance(const std::string& aFileName );
protected:
u8 weekDayOfFirstDay();
void drawDayNumber( u8 day );
void drawText( const akui::cPoint& position, u32 value, u32 factor );
void drawNumber( const akui::cPoint& position, u32 index, u32 value );
akui::cPoint _dayPosition;
akui::cSize _daySize;
akui::cPoint _dayxPosition;
akui::cPoint _monthPosition;
akui::cPoint _yearPosition;
COLOR _dayHighlightColor;
cBMP15 _dayNumbers; // index 10 means colon
cBMP15 _yearNumbers;
bool _showYear;
bool _showMonth;
bool _showDayX;
bool _showDay;
bool _colonShow;
};
typedef t_singleton< cCalendar > calendar_s;
inline cCalendar & calendar() { return calendar_s::instance(); }
#endif//_CALENDAR_H_

View File

@ -0,0 +1,56 @@
/*
calendarwnd.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "calendarwnd.h"
#include "gdi.h"
#include "bmp15.h"
#include "systemfilenames.h"
#include "globalsettings.h"
using namespace akui;
cCalendarWnd::cCalendarWnd() : cForm( 0, 0, 256, 192, NULL, "calendar window" )
{
}
cCalendarWnd::~cCalendarWnd()
{
}
void cCalendarWnd::init()
{
setEngine( GE_SUB );
loadAppearance( SFN_UPPER_SCREEN_BG );
}
cWindow& cCalendarWnd::loadAppearance(const std::string& aFileName )
{
_background = createBMP15FromFile( aFileName );
return *this;
}
void cCalendarWnd::draw()
{
if( _background.valid() )
gdi().bitBlt( _background.buffer(), 0, 0, 256, 192, selectedEngine() );
}

55
arm9/source/calendarwnd.h Normal file
View File

@ -0,0 +1,55 @@
/*
calendarwnd.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CALENDARWND_H_
#define _CALENDARWND_H_
#include <nds.h>
#include "form.h"
#include "singleton.h"
class cCalendarWnd : public akui::cForm
{
public:
cCalendarWnd();
~cCalendarWnd();
public:
cWindow& loadAppearance(const std::string& aFileName );
void init();
void draw();
protected:
cBMP15 _background;
};
typedef t_singleton< cCalendarWnd > calendarWnd_s;
inline cCalendarWnd & calendarWnd() { return calendarWnd_s::instance(); }
#endif//_CALENDARWND_H_

509
arm9/source/cheatwnd.cpp Normal file
View File

@ -0,0 +1,509 @@
/*
cheatwnd.cpp
Portions copyright (C) 2008 Normmatt, www.normmatt.com, Smiths (www.emuholic.com)
Portions copyright (C) 2008 bliss (bliss@hanirc.org)
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "cheatwnd.h"
#include "uisettings.h"
#include "windowmanager.h"
#include "language.h"
#include "msgbox.h"
#include "../../share/gamecode.h"
#include <sys/stat.h>
#include <elm.h>
using namespace akui;
#define CRCPOLY 0xedb88320
static u32 crc32(const u8* p,size_t len)
{
u32 crc=-1;
while(len--)
{
crc^=*p++;
for(int ii=0;ii<8;++ii) crc=(crc>>1)^((crc&1)?CRCPOLY:0);
}
return crc;
}
cCheatWnd::cCheatWnd(s32 x,s32 y,u32 w,u32 h,cWindow* parent,const std::string& text):
cForm(x,y,w,h,parent,text),
_buttonDeselect(0,0,46,18,this,"\x05 Deselect"),
_buttonInfo(0,0,46,18,this,"\x04 Info"),
_buttonGenerate(0,0,46,18,this,"\x03 OK"),
_buttonCancel(0,0,46,18,this,"\x02 Cancel"),
_List(0,0,w-8,h-44,this,"cheat tree")
{
s16 buttonY=size().y-_buttonCancel.size().y-4;
_buttonCancel.setStyle(cButton::press);
_buttonCancel.setText("\x02 "+LANG("setting window","cancel"));
_buttonCancel.setTextColor(uis().buttonTextColor);
_buttonCancel.loadAppearance(SFN_BUTTON3);
_buttonCancel.clicked.connect(this,&cCheatWnd::onCancel);
addChildWindow(&_buttonCancel);
_buttonGenerate.setStyle(cButton::press);
_buttonGenerate.setText( "\x03 " + LANG( "setting window", "ok" ) );
_buttonGenerate.setTextColor(uis().buttonTextColor);
_buttonGenerate.loadAppearance(SFN_BUTTON2);
_buttonGenerate.clicked.connect(this,&cCheatWnd::onGenerate);
addChildWindow(&_buttonGenerate);
_buttonInfo.setStyle(cButton::press);
_buttonInfo.setText( "\x04 " + LANG( "cheats", "info" ) );
_buttonInfo.setTextColor(uis().buttonTextColor);
_buttonInfo.loadAppearance(SFN_BUTTON3);
_buttonInfo.clicked.connect(this,&cCheatWnd::onInfo);
addChildWindow(&_buttonInfo);
_buttonDeselect.setStyle(cButton::press);
_buttonDeselect.setText( "\x05 " + LANG( "cheats", "deselect" ) );
_buttonDeselect.setTextColor(uis().buttonTextColor);
_buttonDeselect.loadAppearance(SFN_BUTTON4);
_buttonDeselect.clicked.connect(this,&cCheatWnd::onDeselectAll);
addChildWindow(&_buttonDeselect);
s16 nextButtonX=size().x;
s16 buttonPitch=_buttonCancel.size().x+4;
nextButtonX-=buttonPitch;
_buttonCancel.setRelativePosition(cPoint(nextButtonX,buttonY));
buttonPitch=_buttonGenerate.size().x+4;
nextButtonX-=buttonPitch;
_buttonGenerate.setRelativePosition(cPoint(nextButtonX,buttonY));
buttonPitch=_buttonInfo.size().x+4;
nextButtonX-=buttonPitch;
_buttonInfo.setRelativePosition(cPoint(nextButtonX,buttonY));
buttonPitch=_buttonDeselect.size().x+4;
nextButtonX-=buttonPitch;
_buttonDeselect.setRelativePosition(cPoint(nextButtonX,buttonY));
_List.setRelativePosition(cPoint(4, 20));
//CIniFile ini(SFN_UI_SETTINGS);
//_List.setColors(ini.GetInt("main list","textColor",RGB15(7,7,7)),ini.GetInt("main list","textColorHilight",RGB15(31,0,31)),ini.GetInt("main list","selectionBarColor1",RGB15(16,20,24)),ini.GetInt("main list","selectionBarColor2",RGB15(20,25,0)));
_List.insertColumn(0,"icon",EIconWidth);
_List.insertColumn(1,"showName",_List.size().x+2-EIconWidth);
_List.arangeColumnsSize();
_List.setRowHeight(ERowHeight);
_List.selectedRowClicked.connect(this,&cCheatWnd::onItemClicked);
_List.ownerDraw.connect(this,&cCheatWnd::onDraw);
addChildWindow(&_List);
loadAppearance("");
arrangeChildren();
}
cCheatWnd::~cCheatWnd()
{}
void cCheatWnd::draw()
{
_renderDesc.draw(windowRectangle(),_engine);
cForm::draw();
}
bool cCheatWnd::process(const akui::cMessage& msg)
{
bool ret=false;
ret=cForm::process(msg);
if(!ret)
{
if(msg.id()>cMessage::keyMessageStart&&msg.id()<cMessage::keyMessageEnd)
{
ret=processKeyMessage((cKeyMessage&)msg);
}
}
return ret;
}
bool cCheatWnd::processKeyMessage(const cKeyMessage& msg)
{
bool ret=false;
if(msg.id()==cMessage::keyDown)
{
switch(msg.keyCode())
{
case cKeyMessage::UI_KEY_DOWN:
_List.selectNext();
ret=true;
break;
case cKeyMessage::UI_KEY_UP:
_List.selectPrev();
ret=true;
break;
case cKeyMessage::UI_KEY_LEFT:
{
size_t ii=_List.selectedRowId();
while(--ii>0)
{
if(_data[_indexes[ii]]._flags&cParsedItem::EFolder) break;
}
_List.selectRow(ii);
}
ret=true;
break;
case cKeyMessage::UI_KEY_RIGHT:
{
size_t ii=_List.selectedRowId(),top=_List.getRowCount();
while(++ii<top)
{
if(_data[_indexes[ii]]._flags&cParsedItem::EFolder) break;
}
_List.selectRow(ii);
}
ret=true;
break;
case cKeyMessage::UI_KEY_A:
onSelect();
ret=true;
break;
case cKeyMessage::UI_KEY_B:
onCancel();
ret=true;
break;
case cKeyMessage::UI_KEY_X:
onGenerate();
ret=true;
break;
case cKeyMessage::UI_KEY_Y:
onInfo();
ret=true;
break;
case cKeyMessage::UI_KEY_L:
onDeselectAll();
ret=true;
break;
default:
break;
}
}
return ret;
}
cWindow& cCheatWnd::loadAppearance(const std::string& aFileName )
{
_renderDesc.loadData(SFN_FORM_TITLE_L,SFN_FORM_TITLE_R,SFN_FORM_TITLE_M);
_renderDesc.setTitleText(_text);
return *this;
}
void cCheatWnd::onItemClicked(u32 index)
{
(void)index;
onSelect();
}
void cCheatWnd::onSelect(void)
{
size_t index=_indexes[_List.selectedRowId()];
if(_data[index]._flags&cParsedItem::EFolder)
{
_data[index]._flags^=cParsedItem::EOpen;
u32 first=_List.firstVisibleRowId(),row=_List.selectedRowId();
generateList();
_List.setFirstVisibleIdAndSelectRow(first,row);
}
else
{
bool deselect=(_data[index]._flags&(cParsedItem::EOne|cParsedItem::ESelected))==(cParsedItem::EOne|cParsedItem::ESelected);
if(_data[index]._flags&cParsedItem::EOne) deselectFolder(index);
if(!deselect) _data[index]._flags^=cParsedItem::ESelected;
}
}
void cCheatWnd::onDeselectAll(void)
{
std::vector<cParsedItem>::iterator itr=_data.begin();
while(itr!=_data.end())
{
(*itr)._flags&=~cParsedItem::ESelected;
++itr;
}
}
void cCheatWnd::onInfo(void)
{
size_t index=_indexes[_List.selectedRowId()];
std::string body(_data[index]._title);
body+="\n\n";
body+=_data[index]._comment;
messageBox(this,LANG("cheats","title"),body,MB_OK);
}
void cCheatWnd::onCancel(void)
{
cForm::onCancel();
}
static void updateDB(u8 value,u32 offset,FILE* db)
{
u8 oldvalue;
if(!db) return;
if(!offset) return;
if(fseek(db,offset,SEEK_SET)) return;
if(fread(&oldvalue,sizeof(oldvalue),1,db)!=1) return;
if(oldvalue!=value)
{
if(fseek(db,offset,SEEK_SET)) return;
fwrite(&value,sizeof(value),1,db);
}
}
void cCheatWnd::onGenerate(void)
{
NandFast();
FILE* db=fopen(SFN_CHEATS,"r+b");
if(db)
{
std::vector<cParsedItem>::iterator itr=_data.begin();
while(itr!=_data.end())
{
updateDB(((*itr)._flags&cParsedItem::ESelected)?1:0,(*itr)._offset,db);
++itr;
}
fclose(db);
}
NandFlush();
cForm::onOK();
}
void cCheatWnd::drawMark(const cListView::cOwnerDraw& od,u16 width)
{
u16 color=gdi().getPenColor(od._engine);
u16 size=od._size.y-ESelectTop*2;
gdi().fillRect(color,color,od._position.x+((width-size)>>1)-1,od._position.y+ESelectTop,size,size,od._engine);
}
void cCheatWnd::onDraw(const cListView::cOwnerDraw& od)
{
size_t index=_indexes[od._row];
u32 flags=_data[index]._flags;
if(od._col==EIconColumn)
{
if(flags&cParsedItem::EFolder)
{
u16 size=od._size.y-EFolderTop*2;
s16 x1=od._position.x+((od._size.x-size)>>1)-1,x2=x1+(size>>1),y1=od._position.y+EFolderTop,y2=y1+(size>>1);
gdi().frameRect(x1,y1,size,size,od._engine);
gdi().drawLine(x1,y2,x1+size,y2,od._engine);
if(!(flags&cParsedItem::EOpen)) gdi().drawLine(x2,y1,x2,y1+size,od._engine);
}
else if(!(flags&cParsedItem::EInFolder))
{
if(flags&cParsedItem::ESelected) drawMark(od,od._size.x);
}
}
else if(od._col==ETextColumn)
{
if(flags&cParsedItem::EInFolder)
{
if(flags&cParsedItem::ESelected) drawMark(od,EFolderWidth);
}
s16 x=od._position.x; u16 w=od._size.x;
if(flags&cParsedItem::EInFolder)
{
x+=EFolderWidth;
w-=EFolderWidth;
}
gdi().textOutRect(x,od._textY,w,od._textHeight,od._text,od._engine);
}
}
bool cCheatWnd::parse(const std::string& aFileName)
{
bool res=false;
_fileName=aFileName;
u32 romcrc32,gamecode;
if(romData(_fileName,gamecode,romcrc32))
{
FILE* dat=fopen(SFN_CHEATS,"rb");
if(dat)
{
res=parseInternal(dat,gamecode,romcrc32);
fclose(dat);
}
}
return res;
}
bool cCheatWnd::romData(const std::string& aFileName,u32& aGameCode,u32& aCrc32)
{
bool res=false;
FILE* rom=fopen(aFileName.c_str(),"rb");
if(rom)
{
u8 header[512];
if(1==fread(header,sizeof(header),1,rom))
{
aCrc32=crc32(header,sizeof(header));
aGameCode=gamecode((const char*)(header+12));
res=true;
}
fclose(rom);
}
return res;
}
bool cCheatWnd::searchCheatData(FILE* aDat,u32 gamecode,u32 crc32,long& aPos,size_t& aSize)
{
aPos=0;
aSize=0;
const char* KHeader="R4 CheatCode";
char header[12];
fread(header,12,1,aDat);
if(strncmp(KHeader,header,12)) return false;
sDatIndex idx,nidx;
fseek(aDat,0,SEEK_END);
long fileSize=ftell(aDat);
fseek(aDat,0x100,SEEK_SET);
fread(&nidx,sizeof(nidx),1,aDat);
bool done=false;
while(!done)
{
memcpy(&idx,&nidx,sizeof(idx));
fread(&nidx,sizeof(nidx),1,aDat);
if(gamecode==idx._gameCode&&crc32==idx._crc32)
{
aSize=((nidx._offset)?nidx._offset:fileSize)-idx._offset;
aPos=idx._offset;
done=true;
}
if(!nidx._offset) done=true;
}
return (aPos&&aSize);
}
bool cCheatWnd::parseInternal(FILE* aDat,u32 gamecode,u32 crc32)
{
dbg_printf("%x, %x\n",gamecode,crc32);
_data.clear();
long dataPos; size_t dataSize;
if(!searchCheatData(aDat,gamecode,crc32,dataPos,dataSize)) return false;
fseek(aDat,dataPos,SEEK_SET);
dbg_printf("record found: %d\n",dataSize);
char* buffer=(char*)malloc(dataSize);
if(!buffer) return false;
fread(buffer,dataSize,1,aDat);
char* gameTitle=buffer;
u32* ccode=(u32*)(((u32)gameTitle+strlen(gameTitle)+4)&~3);
u32 cheatCount=*ccode;
cheatCount&=0x0fffffff;
ccode+=9;
u32 cc=0;
while(cc<cheatCount)
{
u32 folderCount=1;
char* folderName=NULL;
char* folderNote=NULL;
u32 flagItem=0;
if((*ccode>>28)&1)
{
flagItem|=cParsedItem::EInFolder;
if((*ccode>>24)==0x11) flagItem|=cParsedItem::EOne;
folderCount=*ccode&0x00ffffff;
folderName=(char*)((u32)ccode+4);
folderNote=(char*)((u32)folderName+strlen(folderName)+1);
_data.push_back(cParsedItem(folderName,folderNote,cParsedItem::EFolder));
cc++;
ccode=(u32*)(((u32)folderName+strlen(folderName)+1+strlen(folderNote)+1+3)&~3);
}
u32 selectValue=cParsedItem::ESelected;
for(size_t ii=0;ii<folderCount;++ii)
{
char* cheatName=(char*)((u32)ccode+4);
char* cheatNote=(char*)((u32)cheatName+strlen(cheatName)+1);
u32* cheatData=(u32*)(((u32)cheatNote+strlen(cheatNote)+1+3)&~3);
u32 cheatDataLen=*cheatData++;
if(cheatDataLen)
{
_data.push_back(cParsedItem(cheatName,cheatNote,flagItem|((*ccode&0xff000000)?selectValue:0),dataPos+(((char*)ccode+3)-buffer)));
if((*ccode&0xff000000)&&(flagItem&cParsedItem::EOne)) selectValue=0;
for(size_t jj=0;jj<cheatDataLen;++jj)
{
_data.back()._cheat+=formatString("%08X",*(cheatData+jj));
_data.back()._cheat+=((jj+1)%2)?" ":"\n";
}
if(cheatDataLen%2) _data.back()._cheat+="\n";
}
cc++;
ccode=(u32*)((u32)ccode+(((*ccode&0x00ffffff)+1)*4));
}
}
free(buffer);
generateList();
return true;
}
void cCheatWnd::generateList(void)
{
_indexes.clear();
_List.removeAllRows();
std::vector<cParsedItem>::iterator itr=_data.begin();
while(itr!=_data.end())
{
std::vector<std::string> row;
row.push_back("");
row.push_back((*itr)._title);
_List.insertRow(_List.getRowCount(),row);
_indexes.push_back(itr-_data.begin());
u32 flags=(*itr)._flags;
++itr;
if((flags&cParsedItem::EFolder)&&(flags&cParsedItem::EOpen)==0)
{
while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end()) ++itr;
}
}
}
void cCheatWnd::deselectFolder(size_t anIndex)
{
std::vector<cParsedItem>::iterator itr=_data.begin()+anIndex;
while(--itr>=_data.begin())
{
if((*itr)._flags&cParsedItem::EFolder)
{
++itr;
break;
}
}
while(((*itr)._flags&cParsedItem::EInFolder)&&itr!=_data.end())
{
(*itr)._flags&=~cParsedItem::ESelected;
++itr;
}
}

101
arm9/source/cheatwnd.h Normal file
View File

@ -0,0 +1,101 @@
/*
cheatwnd.h
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CHEATWND_H__
#define __CHEATWND_H__
#include "form.h"
#include "formdesc.h"
#include "statictext.h"
#include "button.h"
#include "listview.h"
class cCheatWnd: public akui::cForm
{
public:
cCheatWnd(s32 x,s32 y,u32 w,u32 h,cWindow* parent,const std::string& text);
~cCheatWnd();
bool parse(const std::string& aFileName);
static bool searchCheatData(FILE* aDat,u32 gamecode,u32 crc32,long& aPos,size_t& aSize);
static bool romData(const std::string& aFileName,u32& aGameCode,u32& aCrc32);
protected:
void draw();
bool process(const akui::cMessage& msg);
cWindow& loadAppearance(const std::string& aFileName);
protected:
bool processKeyMessage(const akui::cKeyMessage& msg);
void onItemClicked(u32 index);
void onSelect(void);
void onDeselectAll(void);
void onInfo(void);
void onGenerate(void);
void onCancel(void);
void onDraw(const akui::cListView::cOwnerDraw& data);
void drawMark(const akui::cListView::cOwnerDraw& od,u16 width);
void generateList(void);
akui::cButton _buttonDeselect;
akui::cButton _buttonInfo;
akui::cButton _buttonGenerate;
akui::cButton _buttonCancel;
akui::cFormDesc _renderDesc;
akui::cListView _List;
protected:
bool parseInternal(FILE* aDat,u32 gamecode,u32 crc32);
void deselectFolder(size_t anIndex);
private:
struct sDatIndex
{
u32 _gameCode;
u32 _crc32;
u64 _offset;
};
class cParsedItem
{
public:
std::string _title;
std::string _comment;
std::string _cheat;
u32 _flags;
u32 _offset;
cParsedItem(const std::string& title,const std::string& comment,u32 flags,u32 offset=0):_title(title),_comment(comment),_flags(flags),_offset(offset) {};
enum
{
EFolder=1,
EInFolder=2,
EOne=4,
ESelected=8,
EOpen=16
};
};
enum
{
EIconColumn=0,
ETextColumn=1,
EIconWidth=15,
EFolderWidth=11,
ERowHeight=15,
EFolderTop=3,
ESelectTop=5
};
private:
std::vector<cParsedItem> _data;
std::vector<size_t> _indexes;
std::string _fileName;
};
#endif

121
arm9/source/crtsmall.cpp Normal file
View File

@ -0,0 +1,121 @@
/*
crtsmall.cpp
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <new>
#include <nds.h>
const std::nothrow_t std::nothrow={};
static void Halt(void) __attribute__((__noreturn__));
static void Halt(void)
{
while(true) swiWaitForVBlank();
}
void* operator new(std::size_t size)
{
void* result=malloc(size);
if(!result) Halt();
return result;
}
void* operator new(std::size_t size,const std::nothrow_t&)
{
return malloc(size);
}
void* operator new[](std::size_t size)
{
return ::operator new(size);
}
void* operator new[](std::size_t size,const std::nothrow_t&)
{
return ::operator new(size,std::nothrow);
}
void operator delete(void* block)
{
free(block);
}
void operator delete[] (void *ptr)
{
::operator delete(ptr);
}
namespace std
{
void __throw_bad_alloc(void)
{
Halt();
}
void __throw_length_error(const char*)
{
Halt();
}
void __throw_out_of_range(const char*)
{
Halt();
}
void __throw_logic_error(const char*)
{
Halt();
}
}
extern "C"
{
void __gxx_personality_v0(void)
{
Halt();
}
void __cxa_end_catch(void)
{
Halt();
}
void __cxa_begin_catch(void)
{
Halt();
}
void __cxa_rethrow(void)
{
Halt();
}
void __cxa_end_cleanup(void)
{
Halt();
}
void __cxa_pure_virtual(void)
{
Halt();
}
void __aeabi_unwind_cpp_pr0(void)
{
Halt();
}
void __aeabi_unwind_cpp_pr1(void)
{
Halt();
}
void __aeabi_unwind_cpp_pr2(void)
{
Halt();
}
}

97
arm9/source/datetime.cpp Normal file
View File

@ -0,0 +1,97 @@
/*
datetime.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <string.h> //memset
#include "datetime.h"
const char * cDateTime::weekdayStrings[]= { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
void cDateTime::FillTimeParts(void)
{
time_t epochTime;
if(time(&epochTime)==(time_t)-1)
{
memset(&iTimeParts,0,sizeof(iTimeParts));
}
else
{
localtime_r(&epochTime,&iTimeParts);
}
}
u16 cDateTime::year()
{
FillTimeParts();
return iTimeParts.tm_year+1900;
}
u8 cDateTime::month()
{
FillTimeParts();
return iTimeParts.tm_mon+1;
}
u8 cDateTime::day()
{
FillTimeParts();
return iTimeParts.tm_mday;
}
u8 cDateTime::weekday()
{
FillTimeParts();
return iTimeParts.tm_wday;
}
u8 cDateTime::hours()
{
FillTimeParts();
return iTimeParts.tm_hour;
}
u8 cDateTime::minutes()
{
FillTimeParts();
return iTimeParts.tm_min;
}
u8 cDateTime::seconds()
{
FillTimeParts();
return iTimeParts.tm_sec;
}
std::string cDateTime::getDateString()
{
//FillTimeParts();
return formatString( "%d/%d%/%d %s\n", year(), month(), day(), weekdayStrings[weekday()] );
}
std::string cDateTime::getTimeString()
{
//FillTimeParts();
return formatString( "%d:%d%:%d\n", hours(), minutes(), seconds() );
}
std::string cDateTime::getTimeStampString()
{
//FillTimeParts();
return formatString( "%04d%02d%02d%02d%02d%02d", year(), month(), day(), hours(), minutes(), seconds() );
}

57
arm9/source/datetime.h Normal file
View File

@ -0,0 +1,57 @@
/*
datetime.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DATETIME_H_
#define _DATETIME_H_
#include <nds.h>
#include <time.h>
#include "singleton.h"
#include "../../share/stringtool.h"
class cDateTime
{
private:
tm iTimeParts;
private:
void FillTimeParts(void);
public:
cDateTime() {}
~cDateTime() {}
public:
static const char * weekdayStrings[];
u16 year(void);
u8 month(void);
u8 day(void);
u8 weekday(void);
u8 hours(void);
u8 minutes(void);
u8 seconds(void);
std::string getDateString(void);
std::string getTimeString(void);
std::string getTimeStampString(void);
};
typedef t_singleton< cDateTime > dateTime_s;
inline cDateTime & datetime() { return dateTime_s::instance(); }
#endif//_DATETIME_H_

78
arm9/source/dbgtool.h Normal file
View File

@ -0,0 +1,78 @@
/*
dbgtool.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBG_TOOL_H_
#define _DBG_TOOL_H_
#include <nds.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
//#define DEBUG
#ifdef DEBUG
static inline int dbg_printf( const char* format, ... )
{
va_list args;
va_start( args, format );
int ret = vprintf( format, args );
va_end(args);
return ret;
}
#else
#define dbg_printf(...)
#endif//DEBUG
#ifdef DEBUG
static inline void _cwl(const char *file,int line)
{
const char *seek=file;
while(*seek!=0){
if(*seek=='/') file=seek;
seek++;
}
dbg_printf("%s(%d)\n",file,line);
}
#define cwl(); _cwl( __FILE__, __LINE__ );
#else
#define cwl()
#endif//DEBUG
#ifdef DEBUG
static inline void wait_press_b()
{
dbg_printf("\npress B to continue.\n");
scanKeys();
u16 keys_up = 0;
while( 0 == (keys_up & KEY_B) )
{
scanKeys();
keys_up = keysUp();
}
}
#else
#define wait_press_b()
#endif//DEBUG
#endif//_DBG_TOOL_H_

89
arm9/source/diskicon.cpp Normal file
View File

@ -0,0 +1,89 @@
/*
diskicon.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "diskicon.h"
#include "bmp15.h"
#include "inifile.h"
#include "systemfilenames.h"
#include "../../share/memtool.h"
#include "../../share/timetool.h"
#include "globalsettings.h"
using namespace akui;
cDiskIcon::cDiskIcon() : cWindow( NULL, "diskicon" )
{
_size = cSize( 0, 0 );
_position = cPoint( 0, 0 );
_engine = GE_MAIN;
_icon.init( 1 );
_icon.setPosition( 226, 174 );
_icon.setPriority( 3 );
_icon.setBufferOffset( 16 );
_icon.show();
fillMemory( _icon.buffer(), 32 * 32 * 2, 0x00000000 );
}
void cDiskIcon::draw()
{
// do nothing
}
cWindow & cDiskIcon::loadAppearance(const std::string& aFileName )
{
CIniFile ini( SFN_UI_SETTINGS );
u16 x = ini.GetInt( "disk icon", "x", 238 );
u16 y = ini.GetInt( "disk icon", "y", 172 );
_icon.setPosition( x, y );
cBMP15 icon = createBMP15FromFile( aFileName );
u32 pitch = icon.pitch()>>1;
for( u8 i = 0; i < icon.height(); ++i ) {
for( u8 j = 0; j < icon.width(); ++j ) {
((u16 *)_icon.buffer())[i*32+j] = ((u16 *)icon.buffer())[i * pitch + j];
}
}
dbg_printf("cDiskIcon::loadAppearance ok %d\n", icon.valid() );
return *this;
}
void cDiskIcon::blink( void )
{
if( _icon.visible() )
_icon.hide();
else
_icon.show();
}
void cDiskIcon::turnOn()
{
_icon.show();
}
void cDiskIcon::turnOff()
{
_icon.hide();
}

64
arm9/source/diskicon.h Normal file
View File

@ -0,0 +1,64 @@
/*
diskicon.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DISKICON_H_
#define _DISKICON_H_
#include <nds.h>
#include "window.h"
#include "sprite.h"
#include "singleton.h"
class cDiskIcon : public akui::cWindow
{
public:
cDiskIcon();
~cDiskIcon() {}
public:
void draw();
void turnOn();
void turnOff();
akui::cWindow & loadAppearance(const std::string& aFileName );
void blink( void );
protected:
bool _draw;
float _lightTime;
cSprite _icon;
};
typedef t_singleton< cDiskIcon > diskIcon_s;
inline cDiskIcon & diskIcon() { return diskIcon_s::instance(); }
#endif//_DISKIOICON_H_

19
arm9/source/dslight.h Normal file
View File

@ -0,0 +1,19 @@
/*
dslight.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/

290
arm9/source/dsrom.cpp Normal file
View File

@ -0,0 +1,290 @@
/*
dsrom.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "dsrom.h"
#include "dbgtool.h"
#include "fileicons.h"
#include "icons.h"
#include "nds_banner_bin.h"
#include "unknown_nds_banner_bin.h"
#include "gbarom_banner_bin.h"
#include "icon_bg_bin.h"
#include "../../share/gamecode.h"
#include "fileicons.h"
DSRomInfo & DSRomInfo::operator =( const DSRomInfo & src )
{
memcpy(&_banner,&src._banner,sizeof(_banner));
memcpy(&_saveInfo,&src._saveInfo,sizeof(_saveInfo));
_isDSRom=src._isDSRom;
_isHomebrew=src._isHomebrew;
_isGbaRom=src._isGbaRom;
_fileName=src._fileName;
_romVersion=src._romVersion;
_extIcon=src._extIcon;
return *this;
}
bool DSRomInfo::loadDSRomInfo( const std::string & filename, bool loadBanner )
{
_isDSRom = EFalse;
_isHomebrew = EFalse;
FILE * f = fopen( filename.c_str(), "rb" );
if( NULL == f )// <20><><EFBFBD>ļ<EFBFBD>ʧ<EFBFBD><CAA7>
{
return false;
}
tNDSHeader header;
if( 512 != fread( &header, 1, 512, f ) ) // <20><><EFBFBD>ļ<EFBFBD>ͷʧ<CDB7><CAA7>
{
dbg_printf( "read rom header fail\n" );
memcpy( &_banner, unknown_nds_banner_bin, sizeof(_banner) );
fclose( f );
return false;
}
///////// ROM Header /////////
u16 crc = swiCRC16( 0xFFFF, &header, 0x15E );
if( crc != header.headerCRC16 ) // <20>ļ<EFBFBD>ͷ CRC <20><><EFBFBD>󣬲<EFBFBD><F3A3ACB2><EFBFBD>nds<64><73>Ϸ
{
dbg_printf( "%s rom header crc error\n", filename.c_str() );
memcpy( &_banner, unknown_nds_banner_bin, sizeof(_banner) );
fclose( f );
return true;
} else {
_isDSRom = ETrue;
if( header.arm7destination >= 0x037F8000 || 0x23232323 == gamecode(header.gameCode) ) {//23->'#'
_isHomebrew = ETrue;
}
}
///////// saveInfo /////////
memcpy( _saveInfo.gameTitle, header.gameTitle, 12 );
memcpy( _saveInfo.gameCode, header.gameCode, 4 );
_saveInfo.gameCRC = header.headerCRC16;
saveManager().updateSaveInfoByInfo( _saveInfo );
_romVersion=header.romversion;
//dbg_printf( "save type %d\n", _saveInfo.saveType );
///////// banner /////////
if( header.bannerOffset != 0 ) {
fseek( f, header.bannerOffset, SEEK_SET );
tNDSBanner banner;
u32 readed = fread( &banner, 1, 0x840, f );
if( sizeof(tNDSBanner) != readed ) {
memcpy( &_banner, nds_banner_bin, sizeof(_banner) );
} else {
crc = swiCRC16( 0xffff, banner.icon, 0x840 - 32 );
if( crc != banner.crc ) {
dbg_printf("banner crc error, %04x/%04x\n", banner.crc, crc );
memcpy( &_banner, nds_banner_bin, sizeof(_banner) );
} else {
memcpy( &_banner, &banner, sizeof(_banner) );
}
}
} else {
//dbg_printf( "%s has no banner\n", filename );
memcpy( &_banner, nds_banner_bin, sizeof(_banner) );
}
fclose( f );
return true;
}
void DSRomInfo::drawDSRomIcon( u8 x, u8 y, GRAPHICS_ENGINE engine )
{
if(_extIcon>=0)
{
fileIcons().Draw(_extIcon,x,y,engine);
return;
}
load();
bool skiptransparent=false;
switch(_saveInfo.getIcon())
{
case SAVE_INFO_EX_ICON_TRANSPARENT:
break;
case SAVE_INFO_EX_ICON_AS_IS:
skiptransparent=true;
break;
case SAVE_INFO_EX_ICON_FIRMWARE:
gdi().maskBlt(icon_bg_bin,x,y,32,32,engine);
break;
}
for( int tile=0; tile < 16; ++tile )
{
for( int pixel=0; pixel < 32; ++pixel )
{
u8 a_byte = _banner.icon[(tile<<5)+pixel];
//int px = (tile & 3) * 8 + (2 * pixel & 7);
//int py = (tile / 4) * 8 + (2 * pixel / 8);
int px = ((tile & 3) << 3) + ((pixel<<1) & 7);
int py = ((tile >> 2) << 3) + (pixel >> 2);
u8 idx1 = (a_byte & 0xf0) >> 4;
if(skiptransparent||0!=idx1)
{
gdi().setPenColor( _banner.palette[idx1], engine );
gdi().drawPixel( px+1+x, py+y, engine );
}
u8 idx2 = (a_byte & 0x0f);
if(skiptransparent||0!=idx2)
{
gdi().setPenColor( _banner.palette[idx2], engine );
gdi().drawPixel( px+x, py+y, engine );
}
}
}
}
void DSRomInfo::drawDSRomIconMem( void * mem )
{
if(_extIcon>=0)
{
fileIcons().DrawMem(_extIcon,mem);
return;
}
load();
u16 * pmem = (u16 *)mem;
bool skiptransparent=false;
switch(_saveInfo.getIcon())
{
case SAVE_INFO_EX_ICON_TRANSPARENT:
break;
case SAVE_INFO_EX_ICON_AS_IS:
skiptransparent=true;
break;
case SAVE_INFO_EX_ICON_FIRMWARE:
cIcons::maskBlt((const u16*)icon_bg_bin,pmem);
break;
}
for( int tile=0; tile < 16; ++tile )
{
for( int pixel=0; pixel < 32; ++pixel )
{
u8 a_byte = _banner.icon[(tile<<5)+pixel];
//int px = (tile & 3) * 8 + (2 * pixel & 7);
//int py = (tile / 4) * 8 + (2 * pixel / 8);
int px = ((tile & 3) << 3) + ((pixel<<1) & 7);
int py = ((tile >> 2) << 3) + (pixel >> 2);
u8 idx1 = (a_byte & 0xf0) >> 4;
if(skiptransparent||0!=idx1)
{
pmem[py*32+px+1] = _banner.palette[idx1] | BIT(15);
//gdi().setPenColor( _banner.palette[idx1] );
//gdi().drawPixel( px+1+x, py+y, engine );
}
u8 idx2 = (a_byte & 0x0f);
if(skiptransparent||0!=idx2)
{
pmem[py*32+px] = _banner.palette[idx2] | BIT(15);
//gdi().setPenColor( _banner.palette[idx2] );
//gdi().drawPixel( px+x, py+y, engine );
}
}
}
}
bool DSRomInfo::loadGbaRomInfo(const std::string& filename)
{
_isGbaRom=EFalse;
FILE* gbaFile=fopen(filename.c_str(),"rb");
if(gbaFile)
{
sGBAHeader header;
fread(&header,1,sizeof(header),gbaFile);
fclose(gbaFile);
if(header.is96h==0x96)
{
_isGbaRom=ETrue;
memcpy(_saveInfo.gameCode,header.gamecode,4);
_romVersion=header.version;
memcpy(&_banner,gbarom_banner_bin,sizeof(tNDSBanner));
return true;
}
}
return false;
}
void DSRomInfo::load(void)
{
if(_isDSRom==EMayBe) loadDSRomInfo(_fileName,true);
if(_isGbaRom==EMayBe) loadGbaRomInfo(_fileName);
}
tNDSBanner& DSRomInfo::banner(void)
{
load();
return _banner;
}
SAVE_INFO_EX& DSRomInfo::saveInfo(void)
{
load();
return _saveInfo;
}
u8 DSRomInfo::version(void)
{
load();
return _romVersion;
}
bool DSRomInfo::isDSRom(void)
{
load();
return (_isDSRom==ETrue)?true:false;
}
bool DSRomInfo::isHomebrew(void)
{
load();
return (_isHomebrew==ETrue)?true:false;
}
bool DSRomInfo::isGbaRom(void)
{
load();
return (_isGbaRom==ETrue)?true:false;
}
void DSRomInfo::setExtIcon(const std::string& aValue)
{
_extIcon=fileIcons().Icon(aValue);
};
void DSRomInfo::setBanner(const std::string& anExtIcon,const u8* aBanner)
{
setExtIcon(anExtIcon);
memcpy(&banner(),aBanner,sizeof(tNDSBanner));
}

75
arm9/source/dsrom.h Normal file
View File

@ -0,0 +1,75 @@
/*
dsrom.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DSROM_H_
#define _DSROM_H_
#include <nds.h>
#include <string.h>
#include "savemngr.h"
#include "gdi.h"
class DSRomInfo
{
private:
enum TBool
{
ETrue,EFalse,EMayBe
};
private:
tNDSBanner _banner;
SAVE_INFO_EX _saveInfo;
TBool _isDSRom;
TBool _isHomebrew;
TBool _isGbaRom;
std::string _fileName;
s32 _extIcon;
u8 _romVersion;
private:
void load(void);
bool loadGbaRomInfo(const std::string& filename);
bool loadDSRomInfo(const std::string& filename,bool loadBanner);
public:
DSRomInfo(): _isDSRom(EFalse),_isHomebrew(EFalse),_isGbaRom(EFalse),_extIcon(-1),_romVersion(0)
{
//memcpy(&_banner,unknown_banner_bin,unknown_banner_bin_size);
memset(&_banner,0,sizeof(_banner));
memset(&_saveInfo,0,sizeof(_saveInfo));
}
public:
void drawDSRomIcon(u8 x,u8 y,GRAPHICS_ENGINE engine);
void drawDSRomIconMem(void* mem);
tNDSBanner& banner(void);
SAVE_INFO_EX& saveInfo(void);
u8 version(void);
void setExtIcon(const std::string& aValue);
inline bool isExtIcon(void) {return _extIcon>=0;};
bool isDSRom(void);
bool isHomebrew(void);
bool isGbaRom(void);
DSRomInfo& operator=(const DSRomInfo& src);
void MayBeDSRom(const std::string& filename) {_isDSRom=EMayBe;_isHomebrew=EMayBe;_fileName=filename;};
void MayBeGbaRom(const std::string& filename) {_isGbaRom=EMayBe;_fileName=filename;};
void setBanner(const std::string& anExtIcon,const u8* aBanner);
};
#endif//_DSROM_H_

370
arm9/source/exptools.cpp Normal file
View File

@ -0,0 +1,370 @@
/*
exptools.cpp
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "exptools.h"
#define _PSRAM 0x08060000 // an offset into PSRAM to write to so stuff doesn't get lost...
void cExpansion::OpenNorWrite(void)
{
*(vu16*)0x9fe0000=0xd200;
*(vu16*)0x8000000=0x1500;
*(vu16*)0x8020000=0xd200;
*(vu16*)0x8040000=0x1500;
*(vu16*)0x9c40000=0x1500;
*(vu16*)0x9fc0000=0x1500;
}
void cExpansion::CloseNorWrite(void)
{
*(vu16*)0x9fe0000=0xd200;
*(vu16*)0x8000000=0x1500;
*(vu16*)0x8020000=0xd200;
*(vu16*)0x8040000=0x1500;
*(vu16*)0x9c40000=0xd200;
*(vu16*)0x9fc0000=0x1500;
}
void cExpansion::SetRompage(u16 page)
{
*(vu16*)0x9fe0000=0xd200;
*(vu16*)0x8000000=0x1500;
*(vu16*)0x8020000=0xd200;
*(vu16*)0x8040000=0x1500;
*(vu16*)0x9880000=page;
*(vu16*)0x9fc0000=0x1500;
}
void cExpansion::SetRampage(u16 page)
{
*(vu16*)0x9fe0000=0xd200;
*(vu16*)0x8000000=0x1500;
*(vu16*)0x8020000=0xd200;
*(vu16*)0x8040000=0x1500;
*(vu16*)0x9c00000=page;
*(vu16*)0x9fc0000=0x1500;
iRamPage=page;
}
u16 cExpansion::Rampage(void)
{
return iRamPage;
}
void cExpansion::SetSerialMode(void)
{
*(vu16*)0x9fe0000=0xd200;
*(vu16*)0x8000000=0x1500;
*(vu16*)0x8020000=0xd200;
*(vu16*)0x8040000=0x1500;
*(vu16*)0x9a40000=0xe200;
*(vu16*)0x9fc0000=0x1500;
}
void cExpansion::SetShake(u16 data)
{
*(vu16*)0x9fe0000=0xd200;
*(vu16*)0x8000000=0x1500;
*(vu16*)0x8020000=0xd200;
*(vu16*)0x8040000=0x1500;
*(vu16*)0x9e20000=data;
*(vu16*)0x9fc0000=0x1500;
}
void cExpansion::EnableBrowser(void)
{
for(u32 i=0;i<0x100;i+=4)
{
*(vu32*)(0x9000000+i)=0xffffffff;
*(vu32*)(0x8000000+i)=0xffffffff;
}
*(vu32*)0x90000b0=0xffff;
*(vu32*)0x90000b4=0x24242400;
*(vu32*)0x90000b8=0xffffffff;
*(vu32*)0x90000bc=0x7fffffff;
*(vu32*)0x901fffc=0x7fffffff;
*(vu16*)0x9240002=1;
}
void cExpansion::Block_Erase(u32 blockAdd)
{
vu16 v1,v2;
u32 Address;
u32 loop;
u32 off=0;
if((blockAdd>=0x1000000)&&(iId==0x227E2202))
{
off=0x1000000;
*((vu16*)(FlashBase+off+0x555*2))=0xF0;
*((vu16*)(FlashBase+off+0x1555*2))=0xF0;
}
else
off=0;
Address=blockAdd;
*((vu16*)(FlashBase+0x555*2))=0xF0;
*((vu16*)(FlashBase+0x1555*2))=0xF0;
if((blockAdd==0)||(blockAdd==0x1FC0000)||(blockAdd==0xFC0000)||(blockAdd==0x1000000))
{
for(loop=0;loop<0x40000;loop+=0x8000)
{
*((vu16*)(FlashBase+off+0x555*2))=0xAA;
*((vu16*)(FlashBase+off+0x2AA*2))=0x55;
*((vu16*)(FlashBase+off+0x555*2))=0x80;
*((vu16*)(FlashBase+off+0x555*2))=0xAA;
*((vu16*)(FlashBase+off+0x2AA*2))=0x55;
*((vu16*)(FlashBase+Address+loop))=0x30;
*((vu16*)(FlashBase+off+0x1555*2))=0xAA;
*((vu16*)(FlashBase+off+0x12AA*2))=0x55;
*((vu16*)(FlashBase+off+0x1555*2))=0x80;
*((vu16*)(FlashBase+off+0x1555*2))=0xAA;
*((vu16*)(FlashBase+off+0x12AA*2))=0x55;
*((vu16*)(FlashBase+Address+loop+0x2000))=0x30;
*((vu16*)(FlashBase+off+0x2555*2))=0xAA;
*((vu16*)(FlashBase+off+0x22AA*2))=0x55;
*((vu16*)(FlashBase+off+0x2555*2))=0x80;
*((vu16*)(FlashBase+off+0x2555*2))=0xAA;
*((vu16*)(FlashBase+off+0x22AA*2))=0x55;
*((vu16*)(FlashBase+Address+loop+0x4000))=0x30;
*((vu16*)(FlashBase+off+0x3555*2))=0xAA;
*((vu16*)(FlashBase+off+0x32AA*2))=0x55;
*((vu16*)(FlashBase+off+0x3555*2))=0x80;
*((vu16*)(FlashBase+off+0x3555*2))=0xAA;
*((vu16*)(FlashBase+off+0x32AA*2))=0x55;
*((vu16*)(FlashBase+Address+loop+0x6000))=0x30;
do
{
v1=*((vu16*)(FlashBase+Address+loop));
v2=*((vu16*)(FlashBase+Address+loop));
} while(v1!=v2);
do
{
v1=*((vu16*)(FlashBase+Address+loop+0x2000));
v2=*((vu16*)(FlashBase+Address+loop+0x2000));
} while(v1!=v2);
do
{
v1=*((vu16*)(FlashBase+Address+loop+0x4000));
v2=*((vu16*)(FlashBase+Address+loop+0x4000));
}while(v1!=v2);
do
{
v1=*((vu16*)(FlashBase+Address+loop+0x6000));
v2=*((vu16*)(FlashBase+Address+loop+0x6000));
}while(v1!=v2);
}
}
else
{
*((vu16*)(FlashBase+off+0x555*2))=0xAA;
*((vu16*)(FlashBase+off+0x2AA*2))=0x55;
*((vu16*)(FlashBase+off+0x555*2))=0x80;
*((vu16*)(FlashBase+off+0x555*2))=0xAA;
*((vu16*)(FlashBase+off+0x2AA*2))=0x55;
*((vu16*)(FlashBase+Address))=0x30;
*((vu16*)(FlashBase+off+0x1555*2))=0xAA;
*((vu16*)(FlashBase+off+0x12AA*2))=0x55;
*((vu16*)(FlashBase+off+0x1555*2))=0x80;
*((vu16*)(FlashBase+off+0x1555*2))=0xAA;
*((vu16*)(FlashBase+off+0x12AA*2))=0x55;
*((vu16*)(FlashBase+Address+0x2000))=0x30;
do
{
v1=*((vu16*)(FlashBase+Address));
v2=*((vu16*)(FlashBase+Address));
}while(v1!=v2);
do
{
v1=*((vu16*)(FlashBase+Address+0x2000));
v2=*((vu16*)(FlashBase+Address+0x2000));
}while(v1!=v2);
*((vu16*)(FlashBase+off+0x555*2))=0xAA;
*((vu16*)(FlashBase+off+0x2AA*2))=0x55;
*((vu16*)(FlashBase+off+0x555*2))=0x80;
*((vu16*)(FlashBase+off+0x555*2))=0xAA;
*((vu16*)(FlashBase+off+0x2AA*2))=0x55;
*((vu16*)(FlashBase+Address+0x20000))=0x30;
*((vu16*)(FlashBase+off+0x1555*2))=0xAA;
*((vu16*)(FlashBase+off+0x12AA*2))=0x55;
*((vu16*)(FlashBase+off+0x1555*2))=0x80;
*((vu16*)(FlashBase+off+0x1555*2))=0xAA;
*((vu16*)(FlashBase+off+0x12AA*2))=0x55;
*((vu16*)(FlashBase+Address+0x2000+0x20000))=0x30;
do
{
v1=*((vu16*)(FlashBase+Address+0x20000));
v2=*((vu16*)(FlashBase+Address+0x20000));
} while(v1!=v2);
do
{
v1=*((vu16*)(FlashBase+Address+0x2000+0x20000));
v2=*((vu16*)(FlashBase+Address+0x2000+0x20000));
} while(v1!=v2);
}
}
void cExpansion::WriteNorFlash(u32 address,const u8* buffer,u32 size)
{
vu16 v1,v2;
register u32 loopwrite;
vu16* buf=(vu16*)buffer;
u32 size2,lop;
u32 mapaddress;
u32 j;
v1=0;v2=1;
u32 off=0;
if((address>=0x1000000)&&(iId==0x227E2202))
{
off=0x1000000;
}
else
off=0;
if(size>0x4000)
{
size2=size>>1;
lop=2;
}
else
{
size2=size;
lop=1;
}
mapaddress=address;
for(j=0;j<lop;j++)
{
if(j!=0)
{
mapaddress+=0x4000;
buf=(vu16*)(buffer+0x4000);
}
for(loopwrite=0;loopwrite<(size2>>2);loopwrite++)
{
*((vu16*)(FlashBase+off+0x555*2))=0xAA;
*((vu16*)(FlashBase+off+0x2AA*2))=0x55;
*((vu16*)(FlashBase+off+0x555*2))=0xA0;
*((vu16*)(FlashBase+mapaddress+loopwrite*2))=buf[loopwrite];
*((vu16*)(FlashBase+off+0x1555*2))=0xAA;
*((vu16*)(FlashBase+off+0x12AA*2))=0x55;
*((vu16*)(FlashBase+off+0x1555*2))=0xA0;
*((vu16*)(FlashBase+mapaddress+0x2000+loopwrite*2))=buf[0x1000+loopwrite];
do
{
v1=*((vu16*)(FlashBase+mapaddress+loopwrite*2));
v2=*((vu16*)(FlashBase+mapaddress+loopwrite*2));
}while(v1!=v2);
do
{
v1=*((vu16*)(FlashBase+mapaddress+0x2000+loopwrite*2));
v2=*((vu16*)(FlashBase+mapaddress+0x2000+loopwrite*2));
}while(v1!=v2);
}
}
}
void cExpansion::WritePSRAM(u32 address,const u8* buffer,u32 size)
{
u16* addr=(u16*)(address+_PSRAM);
u16* pData=(u16*)buffer;
for(u32 i=0;i<size;i+=2)
{
addr[i>>1]=pData[i>>1];
}
}
void cExpansion::WriteSram(uint32 address,const u8* data,uint32 size)
{
for(u32 i=0;i<size;i++)
*(u8*)(address+i)=data[i];
}
void cExpansion::ReadSram(uint32 address,u8* data,uint32 size)
{
u16* pData=(u16*)data;
for(u32 i=0;i<size;i+=2)
{
pData[i>>1]=*(u8*)(address+i)+(*(u8*)(address+i+1)*0x100);
}
}
void cExpansion::SoftReset(void)
{
CloseNorWrite();
SetRompage(0);
SetRampage(16);
SetShake(8);
}
void cExpansion::ReadNorFlashID(void)
{
vu16 id1,id2;
*((vu16*)(FlashBase+0x555*2))=0xAA;
*((vu16*)(FlashBase+0x2AA*2))=0x55;
*((vu16*)(FlashBase+0x555*2))=0x90;
*((vu16*)(FlashBase+0x1555*2))=0xAA;
*((vu16*)(FlashBase+0x12AA*2))=0x55;
*((vu16*)(FlashBase+0x1555*2))=0x90;
id1=*((vu16*)(FlashBase+0x2));
id2=*((vu16*)(FlashBase+0x2002));
if((id1!=0x227E)||(id2!=0x227E)) return;
id1=*((vu16*)(FlashBase+0xE*2));
id2=*((vu16*)(FlashBase+0x100e*2));
if(id1==0x2218&&id2==0x2218) //H6H6
{
iId=0x227E2218;
return;
}
if(id1==0x2202&&id2==0x2202) //VZ064
{
iId=0x227E2202;
return;
}
if(id1==0x2202&&id2==0x2220) //VZ064
{
iId=0x227E2202;
return;
}
if(id1==0x2202&&id2==0x2215) //VZ064
{
iId=0x227E2202;
return;
}
}
void cExpansion::ChipReset(void)
{
*((vu16*)(FlashBase))=0xF0;
*((vu16*)(FlashBase+0x1000*2))=0xF0;
if(iId==0x227E2202)
{
*((vu16*)(FlashBase+0x1000000))=0xF0 ;
*((vu16*)(FlashBase+0x1000000+0x1000*2))=0xF0;
}
}

69
arm9/source/exptools.h Normal file
View File

@ -0,0 +1,69 @@
/*
exptools.h
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __EXPTOOLS_H__
#define __EXPTOOLS_H__
#include <nds.h>
#include "singleton.h"
class cExpansion
{
public:
enum TPages
{
ENorPage=16,
EPsramPage=96
};
public:
static void OpenNorWrite(void);
static void CloseNorWrite(void);
static void SetRompage(u16 page);
void SetRampage(u16 page);
u16 Rampage(void);
static void SetSerialMode(void);
static void SetShake(u16 data);
static void EnableBrowser(void);
static void WritePSRAM(u32 address,const u8* buffer,u32 size);
static void WriteSram(uint32 address,const u8* data,uint32 size);
static void ReadSram(uint32 address,u8* data,uint32 size);
public:
void SoftReset(void);
public:
cExpansion(): iId(0),iRamPage(ENorPage) {SetShake(8);OpenNorWrite();ReadNorFlashID();ChipReset();CloseNorWrite();};
void Block_Erase(u32 blockAdd);
void WriteNorFlash(u32 address,const u8* buffer,u32 size);
bool IsValid(void) {return iId;};
private:
void ReadNorFlashID(void);
void ChipReset(void);
private:
enum
{
FlashBase=0x08000000
};
private:
u32 iId;
u16 iRamPage;
};
typedef t_singleton<cExpansion> cExpansion_s;
inline cExpansion& expansion() {return cExpansion_s::instance();}
#endif

251
arm9/source/expwnd.cpp Normal file
View File

@ -0,0 +1,251 @@
/*
expwnd.cpp
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "expwnd.h"
#include "msgbox.h"
#include "windowmanager.h"
#include "uisettings.h"
#include "language.h"
#include "exptools.h"
#include "datetime.h"
#include "progresswnd.h"
#include "fontfactory.h"
#include <elm.h>
using namespace akui;
cExpWnd::cExpWnd( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text )
: cForm( x, y, w, h, parent, text ),
_buttonOK(0,0,46,18,this,"\x01 OK"),
_buttonCancel(0,0,48,18,this,"\x02 Cancel"),
_buttonRAM(0,0,46,18,this,"\x03 RAM"),
_buttonSRAM(0,0,46,18,this,"\x04 SRAM"),
_Rumble(0,0,108,18,this,"spin"),
_Label( 0, 0, 20 * 6, gs().fontHeight, this, "rumble strength" )
{
s16 buttonY = size().y - _buttonCancel.size().y - 4;
_buttonCancel.setStyle( cButton::press );
_buttonCancel.setText( "\x02 " + LANG( "setting window", "cancel" ) );
_buttonCancel.setTextColor( uis().buttonTextColor );
_buttonCancel.loadAppearance( SFN_BUTTON3 );
_buttonCancel.clicked.connect( this, &cExpWnd::onCancel );
addChildWindow( &_buttonCancel );
_buttonOK.setStyle( cButton::press );
_buttonOK.setText( "\x01 " + LANG( "setting window", "ok" ) );
_buttonOK.setTextColor( uis().buttonTextColor );
_buttonOK.loadAppearance( SFN_BUTTON3 );
_buttonOK.clicked.connect( this, &cExpWnd::onOK );
addChildWindow( &_buttonOK );
_buttonRAM.setStyle( cButton::press );
_buttonRAM.setText( "\x03 " + LANG( "exp window", "ram" ) );
_buttonRAM.setTextColor( uis().buttonTextColor );
_buttonRAM.loadAppearance( SFN_BUTTON3 );
_buttonRAM.clicked.connect( this, &cExpWnd::onRAM );
addChildWindow( &_buttonRAM );
_buttonSRAM.setStyle( cButton::press );
_buttonSRAM.setText( "\x04 " + LANG( "exp window", "sram" ) );
_buttonSRAM.setTextColor( uis().buttonTextColor );
_buttonSRAM.loadAppearance( SFN_BUTTON3 );
_buttonSRAM.clicked.connect( this, &cExpWnd::onSRAM );
addChildWindow( &_buttonSRAM );
s16 nextButtonX = size().x;
s16 buttonPitch = _buttonCancel.size().x + 4;
nextButtonX -= buttonPitch;
_buttonCancel.setRelativePosition( cPoint(nextButtonX, buttonY) );
buttonPitch = _buttonOK.size().x + 4;
nextButtonX -= buttonPitch;
_buttonOK.setRelativePosition( cPoint(nextButtonX, buttonY) );
buttonPitch = _buttonRAM.size().x + 4;
nextButtonX -= buttonPitch;
_buttonRAM.setRelativePosition( cPoint(nextButtonX, buttonY) );
buttonPitch = _buttonSRAM.size().x + 4;
nextButtonX -= buttonPitch;
_buttonSRAM.setRelativePosition( cPoint(nextButtonX, buttonY) );
s32 itemY = 32;
s32 itemX = 8;
const char* rumbleLang[]={"off","low","mid","high"};
for( size_t i = 0; i < 4; ++i ) {
_Rumble.insertItem( LANG( "exp window", rumbleLang[i] ) , i );
}
CIniFile ini( SFN_UI_SETTINGS );
u32 spinBoxWidth = ini.GetInt( "setting window", "spinBoxWidth", 108 );
_Rumble.loadAppearance( "" );
_Rumble.setSize( cSize(spinBoxWidth, 18) );
_Rumble.setRelativePosition( cPoint( _size.x - spinBoxWidth - 4, itemY ) );
addChildWindow( &_Rumble );
_Rumble.selectItem(0);
itemY += (_Rumble.windowRectangle().height() - _Label.windowRectangle().height()) / 2;
_Label.setText(LANG( "exp window","strength"));
_Label.setRelativePosition( cPoint( itemX, itemY ) );
_Label.setTextColor( uis().formTextColor );
_Label.setSize( cSize( _size.x / 2 + 8, 12 ) );
addChildWindow( &_Label );
loadAppearance( "" );
arrangeChildren();
CIniFile f;
_romName=f.LoadIniFile(SFN_LAST_GBA_SAVEINFO)?f.GetString("Save Info","lastLoadedNOR",""):"";
_romName=font().breakLine(_romName,size().x-16);
}
cExpWnd::~cExpWnd()
{}
void cExpWnd::draw()
{
_renderDesc.draw( windowRectangle(), _engine );
gdi().setPenColor( uiSettings().formTextColor,_engine );
int textY=_Rumble.position().y+_Rumble.size().y+8,textHeight=_buttonOK.position().y-8-textY;
gdi().textOutRect(position().x+8,textY,size().x-16,textHeight,_romName.c_str(),_engine);
cForm::draw();
}
bool cExpWnd::process( const akui::cMessage & msg )
{
bool ret = false;
ret = cForm::process( msg );
if( !ret ) {
if( msg.id() > cMessage::keyMessageStart && msg.id()
< cMessage::keyMessageEnd )
{
ret = processKeyMessage( (cKeyMessage &)msg );
}
}
return ret;
}
bool cExpWnd::processKeyMessage( const cKeyMessage & msg )
{
bool ret = false;
if( msg.id() == cMessage::keyDown )
{
switch( msg.keyCode() )
{
case cKeyMessage::UI_KEY_A:
onOK();
ret = true;
break;
case cKeyMessage::UI_KEY_B:
onCancel();
ret = true;
break;
case cKeyMessage::UI_KEY_X:
onRAM();
ret = true;
break;
case cKeyMessage::UI_KEY_Y:
onSRAM();
ret = true;
break;
case cKeyMessage::UI_KEY_LEFT:
_Rumble.selectPrev();
ret = true;
break;
case cKeyMessage::UI_KEY_RIGHT:
_Rumble.selectNext();
ret = true;
break;
default:
{}
};
}
return ret;
}
cWindow& cExpWnd::loadAppearance(const std::string& aFileName )
{
_renderDesc.loadData( SFN_FORM_TITLE_L, SFN_FORM_TITLE_R, SFN_FORM_TITLE_M );
_renderDesc.setTitleText( _text );
return *this;
}
void cExpWnd::onOK()
{
expansion().SoftReset();
if(_Rumble.selectedItemId()>0) cExpansion::SetShake(0xEF+_Rumble.selectedItemId());
cForm::onOK();
}
void cExpWnd::onCancel()
{
cForm::onCancel();
}
void cExpWnd::onRAM()
{
expansion().SoftReset();
cExpansion::SetRompage(0x300);
cExpansion::OpenNorWrite();
cExpansion::EnableBrowser();
cForm::onOK();
}
void cExpWnd::onSRAM()
{
std::string saveName="fat0:/sram-"+datetime().getTimeStampString()+".sav";
const u32 size=4096*128,page=4096,pages=128;
NandFast();
FILE* saveFile=fopen(saveName.c_str(),"wb");
if(saveFile)
{
u8* buf=(u8*)malloc(size);
if(buf)
{
u16 ramPage=expansion().Rampage();
progressWnd().setTipText(LANG("progress window","gba save store" ));
progressWnd().show();
progressWnd().setPercent(0);
for(u32 ii=0;ii<pages;ii++)
{
expansion().SetRampage(ii);
cExpansion::ReadSram(0x0A000000,buf+ii*page,page);
progressWnd().setPercent(ii*page*90/size);
}
expansion().SetRampage(ramPage);
fwrite(buf,size,1,saveFile);
progressWnd().setPercent(100);
progressWnd().hide();
free(buf);
}
fclose(saveFile);
}
NandFlush();
cForm::onOK();
}
void cExpWnd::onShow()
{
centerScreen();
}

61
arm9/source/expwnd.h Normal file
View File

@ -0,0 +1,61 @@
/*
expwnd.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __EXPWND_H__
#define __EXPWND_H__
#include "form.h"
#include "formdesc.h"
#include "spinbox.h"
#include "statictext.h"
#include "message.h"
#include <string>
#include "dsrom.h"
class cExpWnd: public akui::cForm
{
public:
cExpWnd(s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text );
~cExpWnd();
public:
void draw();
bool process( const akui::cMessage & msg );
cWindow& loadAppearance(const std::string& aFileName );
protected:
bool processKeyMessage( const akui::cKeyMessage & msg );
void onOK();
void onCancel();
void onRAM();
void onSRAM();
void onShow();
akui::cButton _buttonOK;
akui::cButton _buttonCancel;
akui::cButton _buttonRAM;
akui::cButton _buttonSRAM;
akui::cSpinBox _Rumble;
akui::cStaticText _Label;
akui::cFormDesc _renderDesc;
std::string _romName;
};
#endif//_HELPWND_H_

73
arm9/source/favorites.cpp Normal file
View File

@ -0,0 +1,73 @@
/*
favorites.cpp
Copyright (C) 2008 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "favorites.h"
#include "inifile.h"
#include "systemfilenames.h"
bool cFavorites::AddToFavorites(const std::string& aFileName)
{
CIniFile ini(SFN_FAVORITES);
std::vector<std::string> items;
ini.GetStringVector("main","list",items,'|');
for(size_t ii=0;ii<items.size();++ii)
{
if(items[ii]==aFileName) return false;
}
items.push_back(aFileName);
ini.SetStringVector("main","list",items,'|');
ini.SaveIniFile(SFN_FAVORITES);
return true;
}
bool cFavorites::UpdateFavorites(const std::string& aOldFileName,const std::string& aNewFileName)
{
CIniFile ini(SFN_FAVORITES);
std::vector<std::string> items;
ini.GetStringVector("main","list",items,'|');
for(size_t ii=0;ii<items.size();++ii)
{
if(items[ii]==aOldFileName)
{
items[ii]=aNewFileName;
ini.SetStringVector("main","list",items,'|');
ini.SaveIniFile(SFN_FAVORITES);
return true;
}
}
return false;
}
bool cFavorites::RemoveFromFavorites(const std::string& aFileName)
{
CIniFile ini(SFN_FAVORITES);
std::vector<std::string> items;
ini.GetStringVector("main","list",items,'|');
for(size_t ii=0;ii<items.size();++ii)
{
if(items[ii]==aFileName)
{
items.erase(items.begin()+ii);
ini.SetStringVector("main","list",items,'|');
ini.SaveIniFile(SFN_FAVORITES);
return true;
}
}
return false;
}

33
arm9/source/favorites.h Normal file
View File

@ -0,0 +1,33 @@
/*
favorites.h
Copyright (C) 2008 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FAVORITES_H__
#define __FAVORITES_H__
#include <string>
class cFavorites
{
public:
static bool AddToFavorites(const std::string& aFileName);
static bool UpdateFavorites(const std::string& aOldFileName,const std::string& aNewFileName);
static bool RemoveFromFavorites(const std::string& aFileName);
};
#endif

115
arm9/source/fileicons.cpp Normal file
View File

@ -0,0 +1,115 @@
/*
fileicons.cpp
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "fileicons.h"
#include "systemfilenames.h"
#include "ui/binaryfind.h"
#include "icons.h"
#include "globalsettings.h"
#include <sys/dir.h>
#include <elm.h>
cFileIconItem::cFileIconItem(const std::string& aFolderName,const std::string& aFileName):_loaded(false),_foldername(aFolderName),_filename(aFileName)
{
}
cBMP15& cFileIconItem::Icon(void)
{
Load();
return _icon;
}
void cFileIconItem::Load(void)
{
if(!_loaded)
{
_icon=createBMP15FromFile(_foldername+_filename+".bmp");
_loaded=true;
}
}
static bool Comp(const cFileIconItem& item1,const cFileIconItem& item2)
{
return strcasecmp(item1.FileName().c_str(),item2.FileName().c_str())<0;
}
bool cFileIconItem::operator<(const cFileIconItem& aValue)const
{
return Comp(*this,aValue);
}
cFileIcons::cFileIcons()
{
cIconPaths* paths=new cIconPaths;
LoadFolder(*paths,SFN_UI_ICONS_DIRECTORY);
LoadFolder(*paths,SFN_ICONS_DIRECTORY);
for(cIconPaths::const_iterator it=paths->begin();it!=paths->end();++it)
{
_icons.push_back(*it);
}
delete paths;
}
void cFileIcons::LoadFolder(cIconPaths& aPaths,const std::string& aFolder)
{
DIR_ITER* dir=diropen(aFolder.c_str());
if(NULL!=dir)
{
struct stat st;
char longFilename[MAX_FILENAME_LENGTH];
while(dirnext(dir,longFilename,&st)==0)
{
if((st.st_mode&S_IFDIR)==0)
{
size_t len=strlen(longFilename);
if(len>4)
{
char* extName=longFilename+len-4;
if(strcasecmp(extName,".bmp")==0)
{
*extName=0;
aPaths.insert(cFileIconItem(aFolder,longFilename));
}
}
}
}
dirclose(dir);
}
}
s32 cFileIcons::Icon(const std::string& aValue)
{
if(!_icons.size()) return -1;
std::vector<cFileIconItem>::iterator result=akui::binary_find(_icons.begin(),_icons.end(),cFileIconItem("",aValue),Comp);
if(result==_icons.end())
{
return -1;
}
cBMP15& image=(*result).Icon();
return ((image.valid()&&image.width()==32&&image.height()==32)?(result-_icons.begin()):-1);
}
void cFileIcons::Draw(s32 idx,u8 x,u8 y,GRAPHICS_ENGINE engine)
{
gdi().maskBlt(_icons[idx].Icon().buffer(),x,y,32,32,engine);
}
void cFileIcons::DrawMem(s32 idx,void* mem)
{
cIcons::maskBlt((const u16*)_icons[idx].Icon().buffer(),(u16*)mem);
}

64
arm9/source/fileicons.h Normal file
View File

@ -0,0 +1,64 @@
/*
fileicons.h
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FILEICONS_H__
#define __FILEICONS_H__
#include "bmp15.h"
#include <vector>
#include <set>
#include "singleton.h"
#include "gdi.h"
class cFileIconItem
{
public:
cFileIconItem():_loaded(false) {};
cFileIconItem(const std::string& aFolderName,const std::string& aFileName);
const std::string& FileName(void) const {return _filename;};
const std::string& FolderName(void) const {return _foldername;};
cBMP15& Icon(void);
bool operator<(const cFileIconItem& aValue)const;
private:
void Load(void);
private:
bool _loaded;
std::string _foldername;
std::string _filename;
cBMP15 _icon;
};
class cFileIcons
{
public:
cFileIcons();
s32 Icon(const std::string& aValue);
void Draw(s32 idx,u8 x,u8 y,GRAPHICS_ENGINE engine);
void DrawMem(s32 idx,void* mem);
private:
std::vector<cFileIconItem> _icons;
private:
typedef std::set<cFileIconItem> cIconPaths;
static void LoadFolder(cIconPaths& aPaths,const std::string& aFolder);
};
typedef t_singleton<cFileIcons> fileIcons_s;
inline cFileIcons& fileIcons() {return fileIcons_s::instance();}
#endif

516
arm9/source/files.cpp Normal file
View File

@ -0,0 +1,516 @@
/*
files.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <nds.h>
#include <string>
#include "files.h"
//#include "dbgtool.h"
#include <elm.h>
#include <sys/iosupport.h>
#include "msgbox.h"
#include "progresswnd.h"
#include <errno.h>
#include <cstdio>
#include <unistd.h>
#include "language.h"
#include "datetime.h"
#include "dsrom.h"
#include "favorites.h"
#define USE_OPEN
#ifdef USE_OPEN
#include <fcntl.h>
#endif
using namespace akui;
static SRC_FILE_MODE _srcFileMode = SFM_COPY;
static std::string _srcFilename = "";
bool loadFile( void * buffer, const std::string & filename, size_t offset, size_t & readCount )
{
if( "" == filename )
return false;
if( NULL == buffer ) {
dbg_printf("invalid buffer pointer\n");
struct stat st;
stat( filename.c_str(), &st );
readCount = st.st_size;
return false;
}
FILE * f = fopen( filename.c_str(), "rb" );
if( NULL == f ) {
dbg_printf("file does not exist\n");
readCount = 0;
return false;
}
fseek( f, 0, SEEK_END );
int fileSize = ftell( f );
if( -1 == fileSize ) {
fclose( f );
readCount = 0;
return false;
}
fseek( f, offset, SEEK_SET );
size_t readed = fread( buffer, 1, fileSize, f );
fclose( f );
readCount = readed;
if( readed != (size_t)fileSize-offset ) {
dbg_printf("fread fail: %d/%d\n", readed, fileSize );
readCount = 0;
return false;
}
return true;
}
int getFileSize( const std::string & filename )
{
if( "" == filename )
return -1;
struct stat st;
if( -1 == stat( filename.c_str(), &st ) ) {
return -1;
}
return st.st_size;
}
//---------------------------------------------------------------------------------//
bool stopCopying = false;
bool copyingFile = false;
bool copyFile( const std::string & srcFilename, const std::string & destFilename, bool silently, size_t copyLength )
{
dbg_printf("copy %s to %s\n", srcFilename.c_str(), destFilename.c_str() );
struct stat srcSt;
if( 0 != stat( srcFilename.c_str(), &srcSt ) ) {
messageBox( NULL, LANG("copy file error","title"), LANG("copy file error","text"), MB_OK );
return false;
}
u64 total = 0;
u64 used = 0;
u64 freeSpace = 0;
std::string destDiskName = destFilename.substr( 0, 6 );
if( destDiskName != "fat0:/" && destDiskName != "fat1:/" )
return false;
if( !getDiskSpaceInfo( destDiskName, total, used, freeSpace ) ) {
messageBox( NULL, LANG("no free space","title"), LANG("no free space","text"), MB_OK );
return false;
}
if( 0 == copyLength || copyLength > (size_t)srcSt.st_size )
copyLength = srcSt.st_size;
if( freeSpace < copyLength ) {
messageBox( NULL, LANG("no free space","title"), LANG("no free space","text"), MB_OK );
return false;
}
if( !silently ) {
struct stat destSt;
if( 0 == stat( destFilename.c_str(), &destSt ) ) {
if( !( destSt.st_mode & S_IFDIR ) ) {
u32 ret = messageBox( NULL, LANG("copy file exists","title"),
LANG("copy file exists","text"), MB_YES | MB_NO );
if( ret != ID_YES )
return false;
} else {
messageBox( NULL, LANG("copy dest is directory","title"),
LANG("copy dest is directory","text"), MB_CANCEL );
return false;
}
}
}
u32 copyBufferSize=gs().CopyBufferSize();
u8* copyBuffer=new(std::nothrow)u8[copyBufferSize];
if(copyBuffer==NULL)
{
messageBox(NULL,LANG("ram allocation","title"),LANG("ram allocation","memory allocation error"),MB_OK);
return false;
}
std::string tempText = LANG("progress window", "processing copy");
std::string copyTip = formatString( tempText.c_str(), (char)0x02 );
progressWnd().setTipText( copyTip );
progressWnd().show();
progressWnd().setPercent( 0 );
stopCopying = false;
copyingFile = true;
NandFast();
#ifdef USE_OPEN
int wf=open(destFilename.c_str(),O_WRONLY|O_CREAT|O_TRUNC);
int rf=open(srcFilename.c_str(),O_RDONLY);
#else
FILE * wf = fopen( destFilename.c_str(), "wb" );
FILE * rf = fopen( srcFilename.c_str(), "rb" );
#endif
u8 percent = 0;
dbg_printf("start: %s", datetime().getTimeString().c_str() );
u32 writeCount = copyLength / copyBufferSize;
if( copyLength % copyBufferSize )
writeCount++;
dbg_printf("write count %d\n", writeCount );
u32 remain = copyLength;
for( size_t i = 0; i < writeCount; ++i ) {
if( stopCopying ) {
copyingFile = false;
u32 ret = messageBox( &progressWnd(), LANG("stop copying file","title"),
LANG("stop copying file","text"), MB_YES | MB_NO );
if( ID_YES == ret ) {
#ifdef USE_OPEN
close(rf);
close(wf);
#else
fclose( rf );
fclose( wf );
#endif
NandFlush();
progressWnd().hide();
copyingFile = false;
delete[] copyBuffer;
return false;
}
copyingFile = true;
stopCopying = false;
}
u32 toRead = remain > copyBufferSize ? copyBufferSize : remain;
#ifdef USE_OPEN
ssize_t readed=read(rf,copyBuffer,toRead);
ssize_t written=write(wf,copyBuffer,readed);
#else
u32 readed = fread( copyBuffer, 1, toRead, rf );
u32 written = fwrite( copyBuffer, 1, (int)readed, wf );
#endif
if( written != readed ) {
dbg_printf("err %d\n", errno );
dbg_printf("COPY FILE ERROR! %d/%d\n", readed, written );
// todo: judge error types in errno
#ifdef USE_OPEN
close(rf);
close(wf);
#else
fclose( rf );
fclose( wf );
#endif
NandFlush();
progressWnd().hide();
copyingFile = false;
delete[] copyBuffer;
messageBox( NULL, LANG("no free space","title"), LANG("no free space","text"), MB_OK );
return false;
}
remain -= written;
percent = i * 100 / writeCount;
progressWnd().setPercent( percent );
}
#ifdef USE_OPEN
close(rf);
close(wf);
#else
fclose( rf );
fclose( wf );
#endif
NandFlush();
progressWnd().hide();
copyingFile = false;
delete[] copyBuffer;
dbg_printf("finish: %s", datetime().getTimeString().c_str());
return true;
}
bool renameFile( const std::string & oldName, const std::string & newName )
{
if( "" == oldName || "" == newName )
return false;
struct stat destSt;
if( 0 == stat( newName.c_str(), &destSt ) ) {
if( !( destSt.st_mode & S_IFDIR ) ) {
u32 ret = messageBox( NULL, LANG("copy file exists","title"),
LANG("copy file exists","text"), MB_YES | MB_NO );
if( ret != ID_YES )
return false;
} else {
messageBox( NULL, LANG("move dest is directory","title"),
LANG("move dest is directory","text"), MB_CANCEL );
return false;
}
}
if( 0 != rename( oldName.c_str(), newName.c_str() ) ) {
if( EEXIST == errno || EXDEV == errno ) {
bool success = copyFile( oldName, newName, true );
if( success ) {
unlink( oldName.c_str() );
return true;
} else {
unlink( newName.c_str() );
return false;
}
}
return false;
}
return true;
}
bool deleteFile( const std::string & filename )
{
if( "" == filename )
return false;
struct stat destSt;
if( 0 != stat( filename.c_str(), &destSt ) ) {
return false;
}
std::string confirmText = LANG("confirm delete file","text");
std::string showname,realname;
if( '/' == filename[filename.size()-1] )
showname = filename.substr( 0, filename.size() - 1 );
else
showname = filename;
realname = showname;
size_t slashPos = showname.find_last_of( '/' );
if( showname.npos != slashPos )
showname = showname.substr( slashPos + 1 );
confirmText = formatString( confirmText.c_str(), showname.c_str() );
u32 result = messageBox( NULL, LANG("confirm delete file","title"), confirmText.c_str(), MB_YES | MB_NO );
if( result != ID_YES ) {
return false;
}
int ret = unlink( realname.c_str() );
if( 0 != ret ) {
if( EACCES == errno ) {
messageBox( NULL, LANG("do not delete directory","title"), LANG("do not delete directory","text"), MB_OK );
}
return false;
}
cFavorites::RemoveFromFavorites(filename);
return true;
}
void setSrcFile( const std::string & filename, SRC_FILE_MODE mode )
{
_srcFilename = filename;
_srcFileMode = mode;
}
const std::string& getSrcFile(void)
{
return _srcFilename;
}
bool copyOrMoveFile( const std::string & destDir )
{
if( "" == _srcFilename )
return false;
const char * pPath = _srcFilename.c_str();
const char * pName = NULL;
while( pPath < _srcFilename.c_str() + _srcFilename.size() )
{
if( '/' == *pPath++ )
pName = pPath;
}
if( 0 == *pName )
return false;
std::string destPath = destDir + pName;
if( destPath == _srcFilename )
return false;
if( SFM_COPY == _srcFileMode )
{
u32 copyLength = 0;
if( gs().romTrim ) {
std::string extName;
size_t lastDotPos = _srcFilename.find_last_of( '.' );
if( _srcFilename.npos != lastDotPos )
extName = _srcFilename.substr( lastDotPos );
else
extName = "";
for( size_t i = 0; i < extName.size(); ++i )
extName[i] = tolower( extName[i] );
if( ".nds" == extName ) {
DSRomInfo info;
info.MayBeDSRom(_srcFilename);
if( info.isDSRom() && !info.isHomebrew() ) {
FILE * f = fopen( _srcFilename.c_str(), "rb" );
fseek( f, 0x80, SEEK_SET );
fread( &copyLength, 1, 4, f );
fclose(f);
copyLength += 0x88; // to keep RSA signature
}
}
}
bool copyOK = copyFile( _srcFilename, destPath, false, copyLength );
if( copyOK ) {
_srcFilename = "";
}
return copyOK;
}
if( SFM_CUT == _srcFileMode )
{
bool moveOK = renameFile( _srcFilename, destPath );
if( moveOK ) {
cFavorites::UpdateFavorites(_srcFilename,destPath);
_srcFilename = "";
}
return moveOK;
}
return false;
}
bool getDirSize( const std::string & path, bool includeSubdirs, u64 * dirSize )
{
if( "" == path )
return false;
u64 size = 0;
std::string dirPath = path;
if( dirPath[dirPath.size()-1] != '/' )
dirPath += "/";
if( dirPath.size() > MAX_FILENAME_LENGTH )
return false;
DIR_ITER * dir = NULL;
dir = diropen(dirPath.c_str());
if (dir == NULL) {
//dbg_printf("getDirSize couldn't open dir %s", path.c_str() );
return false;
}
size = 0;
char filename[MAX_FILENAME_LENGTH];
struct stat stat_buf;
while (dirnext(dir, filename, &stat_buf) == 0) {
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) {
continue;
}
//dbg_printf("getDirSize dir entry '%s'", path.c_str());
if (!(stat_buf.st_mode & S_IFDIR)) {
//dbg_printf("getDirSize add size %d for '%s'", (int)stat_buf.st_size, path.c_str());
size += (u64)stat_buf.st_size;
} else if (includeSubdirs) {
/* calculate the size recursively */
u64 subDirSize = 0;
bool succ = getDirSize( dirPath + filename, includeSubdirs, &subDirSize );
/* ignore failure in subdirs */
if( succ ) {
size += subDirSize;
}
}
}
dirclose(dir);
*dirSize = size;
return true;
}
static bool getDiskFromString(const std::string& diskName,u32& disk)
{
if(tolower(diskName[0])=='f'&&tolower(diskName[1])=='a'&&tolower(diskName[2])=='t'&&(diskName[3]=='0'||diskName[3]=='1')&&diskName[4]==':')
{
disk=diskName[3]-'0';
return true;
}
return false;
}
static bool getDiskTotalSpace(u32 disk,u64& diskSpace)
{
u32 clusters,clusterSize;
if(ELM_ClusterSizeFromDisk(disk,&clusterSize)&&ELM_ClustersFromDisk(disk,&clusters))
{
diskSpace=(u64)clusters*(u64)clusterSize;
return true;
}
return false;
}
static bool getDiskFreeSpace(u32 disk,u64& freeSpace)
{
u32 clusters,clusterSize;
if(ELM_ClusterSizeFromDisk(disk,&clusterSize)&&ELM_FreeClustersFromDisk(disk,&clusters))
{
freeSpace=(u64)clusters*(u64)clusterSize;
return true;
}
return false;
}
bool getDiskSpaceInfo(const std::string& diskName,u64& total,u64& used,u64& freeSpace)
{
if(""==diskName) return false;
u32 disk;
if(!getDiskFromString(diskName,disk))
{
cwl();
return false;
}
if(!getDiskTotalSpace(disk,total))
{
cwl();
return false;
}
if(!getDiskFreeSpace(disk,freeSpace))
{
cwl();
return false;
}
cwl();
used=total-freeSpace;
return true;
}

55
arm9/source/files.h Normal file
View File

@ -0,0 +1,55 @@
/*
files.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _FILES_H_
#define _FILES_H_
#include <string>
bool loadFile( void * buffer, const std::string & filename, size_t offset, size_t & readCount );
// 返回文件大小,-1表示文件不存在
int getFileSize( const std::string & filename );
extern bool stopCopying;
extern bool copyingFile;
bool copyFile( const std::string & srcFilename, const std::string & destFilename, bool silently, size_t copyLength = 0 );
bool renameFile( const std::string & oldName, const std::string & newName );
bool deleteFile( const std::string & filename );
enum SRC_FILE_MODE
{
SFM_COPY = 0,
SFM_CUT = 1
};
void setSrcFile( const std::string & filename, SRC_FILE_MODE mode );
const std::string& getSrcFile(void);
bool copyOrMoveFile( const std::string & destDir );
bool getDirSize( const std::string & path, bool includeSubdirs, u64 * dirSize );
bool getDiskSpaceInfo( const std::string & diskName, u64 & total, u64 & used, u64 & freeSpace );
#endif//_FILES_H_

106
arm9/source/font/font.cpp Normal file
View File

@ -0,0 +1,106 @@
/*
font.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <nds.h>
#include <string.h>
#include "font.h"
#include "files.h"
#include "dbgtool.h"
#include "systemfilenames.h"
cFont::cFont()
{
}
cFont::~cFont()
{
}
u32 cFont::getStringScreenWidth( const char * str, size_t len )
{
if( NULL == str || 0 == len )
return 0;
size_t strLen = strlen( str );
if( len > strLen )
len = strLen;
const char * endstr = str + len;
u32 width = 0;
const char * p = str;
while( *p != 0 && p < endstr ) {
u32 ww,add;
Info(p,&ww,&add);
width+=ww;
p+=add;
}
return width;
}
std::string cFont::breakLine( const std::string & text, u32 maxLineWidth )
{
if( 0 == maxLineWidth )
return text;
std::string ret;
// 找空格
// 找到之后,和上次空格相减,传入 计算width 函数
// 如果tempwdith超过 maxwidth把上次的空格换成 \n
// tempwidth 清零,继续
const char * p = text.c_str();
bool hasSpace = false;
u32 tempWidth = 0;
while( *p != 0 )
{
u32 ww,add;
Info(p,&ww,&add);
if( ' ' == *p ) hasSpace=true;
tempWidth+=ww;
if( tempWidth > maxLineWidth )
{
if( hasSpace )
{
u32 lastSpacePos = ret.find_last_of( ' ' );
ret[lastSpacePos] = '\n';
tempWidth = getStringScreenWidth(
text.c_str() + lastSpacePos, (size_t)(p - text.c_str()) - lastSpacePos );
hasSpace = false;
} else {
ret.push_back( '\n' );
tempWidth = 0;
}
}
for(u32 ii=0;ii<add;ii++) ret.push_back( *p++ );
}
if(ret[ret.length()-1]!='\n') ret.push_back('\n');
return ret;
}
u32 cFont::FontRAM(void)
{
return 0;
}

44
arm9/source/font/font.h Normal file
View File

@ -0,0 +1,44 @@
/*
font.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _FONT_H_
#define _FONT_H_
#include <string>
#include "singleton.h"
#include "gdi.h"
class cFont
{
public:
cFont();
virtual ~cFont();
public:
u32 getStringScreenWidth( const char * str, size_t len );
std::string breakLine( const std::string & text, u32 maxLineWidth );
public:
virtual void Info(const char* aString,u32* aWidth,u32* aSymbolCount)=0;
virtual void Draw(u16* mem,s16 x,s16 y,const u8* aText,u16 color)=0;
virtual bool Load(const char* aFileName)=0;
virtual u32 FontRAM(void);
};
#endif//_FONT_H_

View File

@ -0,0 +1,325 @@
/*
font_pcf.cpp
Copyright (C) 2008-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "font_pcf.h"
#include "font_pcf_internals.h"
#include "language.h"
#include <fcntl.h>
#include <unistd.h>
cFontPcf::cFontPcf(): cFont(),iGlyphs(NULL),iData(NULL),iCount(0),iDataSize(0),iHeight(0),iAscent(0),iDescent(0)
{
//FIXME: test on nds
//printf("%d\n",sizeof(cFontPcf::SGlyph));
}
cFontPcf::~cFontPcf()
{
delete[]iGlyphs;
delete[]iData;
}
void cFontPcf::Info(const char* aString,u32* aWidth,u32* aSymbolCount)
{
u32 len;
u32 code=utf8toucs2((const u8*)aString,&len);
if(aSymbolCount) *aSymbolCount=len;
if(aWidth)
{
s32 index=Search(code);
*aWidth=(index>=0)?iGlyphs[index].iWidth:((code>0&&code<8)?10:0);
}
}
bool cFontPcf::ParseAccels(int aFont,u32 aSize,u32 aOffset)
{
bool res=false;
if(lseek(aFont,aOffset,SEEK_SET)<0) return false;
SPcfAccel header;
if(read(aFont,&header,sizeof(header))!=sizeof(header)) return false;
res=true;
iAscent=header.iFontAscent;
iDescent=header.iFontDescent;
iHeight=iAscent+iDescent;
return res;
}
bool cFontPcf::ParseBitmaps(int aFont,u32 aSize,u32 aOffset)
{
bool res=false;
if(lseek(aFont,aOffset,SEEK_SET)<0) return false;
SPcfBitmapsHeader header;
if(read(aFont,&header,sizeof(header))!=sizeof(header)) return false;
iGlyphs=new(std::nothrow)SGlyph[header.iCount];
if(!iGlyphs) return false;
iCount=header.iCount;
iDataSize=aSize-sizeof(SPcfBitmapsHeader)-header.iCount*sizeof(u32)-16;
iData=new(std::nothrow)u8[iDataSize];
if(iData)
{
u32* offsets=new(std::nothrow)u32[header.iCount];
if(offsets)
{
do
{
if(read(aFont,offsets,sizeof(u32)*header.iCount)!=(ssize_t)(sizeof(u32)*header.iCount)) break;
for(u32 ii=0;ii<header.iCount;ii++)
{
iGlyphs[ii].iOffset=offsets[ii];
}
if(lseek(aFont,16,SEEK_CUR)<0) break;
if(read(aFont,iData,iDataSize)!=(ssize_t)iDataSize) break;
res=true;
} while(false);
delete[]offsets;
}
}
return res;
}
bool cFontPcf::ParseMetrics(int aFont,u32 aSize,u32 aOffset)
{
bool res=false;
if(lseek(aFont,aOffset,SEEK_SET)<0) return false;
u8* buffer=new(std::nothrow)u8[aSize];
if(buffer)
{
if(read(aFont,buffer,aSize)==(ssize_t)aSize)
{
u32 format=*(u32*)buffer;
if(format&PCF_COMPRESSED_METRICS)
{
u32 count=*(u16*)(buffer+4);
if(count==iCount)
{
SPcfCompressedMetric* metrics=(SPcfCompressedMetric*)(buffer+6);
for(u32 ii=0;ii<iCount;ii++)
{
iGlyphs[ii].iWidth=metrics[ii].iCharacterWidth-0x80;
iGlyphs[ii].iLeft=metrics[ii].iLeftSideBearing-0x80;
iGlyphs[ii].iRight=metrics[ii].iRightSideBearing-0x80;
iGlyphs[ii].iAscent=metrics[ii].iAscent-0x80;
iGlyphs[ii].iDescent=metrics[ii].iDescent-0x80;
//printf("0x%08x: w=%d,l=%d,r=%d,a=%d,d=%d,offset=0x%08x\n",iGlyphs[ii].iCode,iGlyphs[ii].iWidth,iGlyphs[ii].iLeft,iGlyphs[ii].iRight,iGlyphs[ii].iAscent,iGlyphs[ii].iDescent,iGlyphs[ii].iOffset);
}
res=true;
}
}
}
delete[]buffer;
}
return res;
}
bool cFontPcf::ParseEncodings(int aFont,u32 aSize,u32 aOffset)
{
bool res=false;
if(lseek(aFont,aOffset,SEEK_SET)<0) return false;
u8* buffer=new(std::nothrow)u8[aSize];
if(buffer)
{
if(read(aFont,buffer,aSize)==(ssize_t)aSize)
{
SPcfEncodingsHeader& header=*(SPcfEncodingsHeader*)(buffer);
u32 nencoding=(header.iLastCol-header.iFirstCol+1)*(header.iLastRow-header.iFirstRow+1);
u16* codes=(u16*)(buffer+sizeof(SPcfEncodingsHeader));
for(u32 ii=0;ii<nencoding;ii++)
{
if(codes[ii]!=0xffff)
{
iGlyphs[codes[ii]].iCode=(((ii/(header.iLastCol-header.iFirstCol+1))+header.iFirstRow)*256)+((ii%(header.iLastCol-header.iFirstCol+1))+header.iFirstCol);
}
}
res=true;
}
delete[]buffer;
}
return res;
}
int cFontPcf::Compare(const void* a,const void* b)
{
return (static_cast<const SGlyph*>(a)->iCode-static_cast<const SGlyph*>(b)->iCode);
}
bool cFontPcf::Load(const char* aFileName)
{
bool res=false;
int font=open(aFileName,O_RDONLY);
if(font>=0)
{
do
{
SPcfHeader header;
if(read(font,&header,sizeof(header))!=sizeof(header)) break;
if(header.iVersion!=PCF_FILE_VERSION) break;
SPcfEntry entries[header.iCount];
if(read(font,entries,sizeof(SPcfEntry)*header.iCount)!=(ssize_t)(sizeof(SPcfEntry)*header.iCount)) break;
s32 accelsIndex=-1,bitmapsIndex=-1,metricsIndex=-1,encodingsIndex=-1;
for(u32 ii=0;ii<header.iCount;ii++)
{
if(entries[ii].iType==PCF_ACCELERATORS) accelsIndex=ii;
else if(entries[ii].iType==PCF_BITMAPS) bitmapsIndex=ii;
else if(entries[ii].iType==PCF_METRICS) metricsIndex=ii;
else if(entries[ii].iType==PCF_BDF_ENCODINGS) encodingsIndex=ii;
}
if(accelsIndex>=0&&bitmapsIndex>=0&&metricsIndex>=0&&encodingsIndex>=0)
{
if(!ParseAccels(font,entries[accelsIndex].iSize,entries[accelsIndex].iOffset)) break;
if(!ParseBitmaps(font,entries[bitmapsIndex].iSize,entries[bitmapsIndex].iOffset)) break;
if(!ParseMetrics(font,entries[metricsIndex].iSize,entries[metricsIndex].iOffset)) break;
if(!ParseEncodings(font,entries[encodingsIndex].iSize,entries[encodingsIndex].iOffset)) break;
if(lang().GetInt("font","sort",0)) qsort(iGlyphs,iCount,sizeof(SGlyph),Compare);
res=true;
}
} while(false);
close(font);
}
return res;
}
s32 cFontPcf::Search(u16 aCode)
{
s32 result=SearchInternal(aCode);
if(result<0&&aCode>' ') result=SearchInternal('?');
return result;
}
s32 cFontPcf::SearchInternal(u16 aCode)
{
s32 low=0,high=iCount-1,curr;
while(true)
{
curr=(low+high)/2;
//curr=((aCode-iGlyphs[low].iCode)*(high-low)/(iGlyphs[high].iCode-iGlyphs[low].iCode))+low;
if(aCode<iGlyphs[curr].iCode)
{
high=curr-1;
}
else if(aCode>iGlyphs[curr].iCode)
{
low=curr+1;
}
else
{
return curr;
}
if(low>high) return -1;
}
}
void cFontPcf::DrawInternal(u16* mem,s16 x,s16 y,const u8* data,u16 color,u32 width,u32 height)
{
u32 byteW=width;
byteW=byteW/8+(byteW&7?1:0);
for(u32 ii=0;ii<height;ii++)
{
u32 cur_width=width;
for(u32 jj=0;jj<byteW;jj++)
{
u32 curr=*data++;
u32 top=(cur_width>8)?8:cur_width;
for(u32 kk=0;kk<top;kk++)
{
if(curr&(1<<kk))
{
if(y+ii>=0&&x+jj>=0)
{
*(mem+x+(jj<<3)+kk+((y+ii)<<8))=color;
}
}
}
cur_width-=8;
}
}
}
void cFontPcf::Draw(u16* mem,s16 x,s16 y,const u8* aText,u16 color)
{
if(!(iData&&iGlyphs)) return;
u32 code=utf8toucs2(aText,NULL);
s32 index=Search(code);
if(index>=0)
{
x+=iGlyphs[index].iLeft;
y+=-iGlyphs[index].iAscent+iAscent;
DrawInternal(mem,x,y,iData+iGlyphs[index].iOffset,color,-iGlyphs[index].iLeft+iGlyphs[index].iRight,iGlyphs[index].iAscent+iGlyphs[index].iDescent);
}
else if(code>0&&code<8)
{
y+=-9+iAscent;
u8 special[]=
{
0x7c,0,0xfe,0,0xef,1,0xd7,1,0xd7,1,0x83,1,0xbb,1,0xfe,0,0x7c,0,
0x7c,0,0xfe,0,0xc3,1,0xbb,1,0xc3,1,0xbb,1,0xc3,1,0xfe,0,0x7c,0,
0x7c,0,0xfe,0,0xbb,1,0xd7,1,0xef,1,0xd7,1,0xbb,1,0xfe,0,0x7c,0,
0x7c,0,0xfe,0,0xbb,1,0xd7,1,0xef,1,0xef,1,0xef,1,0xfe,0,0x7c,0,
0xf8,1,0xfc,1,0xf6,1,0xf7,1,0xf7,1,0xf7,1,0x87,1,0xff,1,0xff,1,
0x3f,0,0x7f,0,0xc3,0,0xbb,1,0xc3,1,0xdb,1,0xbb,1,0xff,1,0xff,1,
0x38,0,0x38,0,0x38,0,0xff,1,0xef,1,0xff,1,0x38,0,0x38,0,0x38,0,
};
DrawInternal(mem,x,y,special+(code-1)*18,color,9,9);
}
}
#define ONE_BYTE_MASK 0x80
#define ONE_BYTE_SIGN 0x00
#define TWO_BYTE_MASK 0xc0e0
#define TWO_BYTE_SIGN 0x80c0
#define THREE_BYTE_MASK 0xc0c0f0
#define THREE_BYTE_SIGN 0x8080e0
#define FIRST_BYTE 0xff
#define SECOND_BYTE 0xff00
#define THIRD_BYTE 0xff0000
u32 cFontPcf::utf8toucs2(const u8* aSource,u32* aLength)
{
u32 data=aSource[0],len=1,res='?';
if((data&ONE_BYTE_MASK)==ONE_BYTE_SIGN)
{
res=data;
}
else
{
data+=aSource[1]*0x100;
if((data&TWO_BYTE_MASK)==TWO_BYTE_SIGN)
{
res=data&~TWO_BYTE_MASK;
res=((res&SECOND_BYTE)>>8)|((res&FIRST_BYTE)<<6);
len=2;
}
else
{
data+=aSource[2]*0x10000;
if((data&THREE_BYTE_MASK)==THREE_BYTE_SIGN)
{
res=data&~THREE_BYTE_MASK;
res=((res&FIRST_BYTE)<<12)|((res&SECOND_BYTE)>>2)|((res&THIRD_BYTE)>>16);
len=3;
}
}
}
if(aLength) *aLength=len;
return res;
}
u32 cFontPcf::FontRAM(void)
{
return iDataSize+sizeof(SGlyph)*iCount;
}

View File

@ -0,0 +1,86 @@
/*
font_pcf.h
Copyright (C) 2008-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
/*
very base pcf font implementation
supported only fonts with ...
*/
#ifndef __FONT_PCF_H__
#define __FONT_PCF_H__
#include "font.h"
//#define SMALL 1
class cFontPcf: public cFont
{
private:
#ifdef SMALL
struct PACKED SGlyph
{
unsigned iOffset:19;
unsigned iWidth:5;
signed iLeft:6;
signed iRight:6;
signed iAscent:6;
signed iDescent:6;
unsigned iCode:16;
};
#else
struct SGlyph
{
u32 iOffset;
u16 iCode;
u8 iWidth;
u8 iReserved;
s8 iLeft;
s8 iRight;
s8 iAscent;
s8 iDescent;
};
#endif
private:
SGlyph* iGlyphs;
u8* iData;
u32 iCount;
u32 iDataSize;
u32 iHeight;
u32 iAscent;
u32 iDescent;
private:
bool ParseAccels(int aFont,u32 aSize,u32 aOffset);
bool ParseBitmaps(int aFont,u32 aSize,u32 aOffset);
bool ParseMetrics(int aFont,u32 aSize,u32 aOffset);
bool ParseEncodings(int aFont,u32 aSize,u32 aOffset);
s32 SearchInternal(u16 aCode);
s32 Search(u16 aCode);
static u32 utf8toucs2(const u8* aSource,u32* aLength);
void DrawInternal(u16* mem,s16 x,s16 y,const u8* data,u16 color,u32 width,u32 height);
static int Compare(const void* a,const void* b);
public:
cFontPcf();
~cFontPcf();
bool Load(const char* aFileName);
void Draw(u16* mem,s16 x,s16 y,const u8* aText,u16 color);
void Info(const char* aString,u32* aWidth,u32* aSymbolCount);
u32 FontRAM(void);
};
#endif

View File

@ -0,0 +1,94 @@
/*
font_pcf_internals.h
Copyright (C) 2008-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FONT_PCF_INTERNALS_H__
#define __FONT_PCF_INTERNALS_H__
#include <nds.h>
#define PCF_COMPRESSED_METRICS 0x00000100UL
#define PCF_FILE_VERSION ( ( 'p' << 24 ) | ( 'c' << 16 ) | ( 'f' << 8 ) | 1 )
#define PCF_PROPERTIES ( 1 << 0 )
#define PCF_ACCELERATORS ( 1 << 1 )
#define PCF_METRICS ( 1 << 2 )
#define PCF_BITMAPS ( 1 << 3 )
#define PCF_INK_METRICS ( 1 << 4 )
#define PCF_BDF_ENCODINGS ( 1 << 5 )
#define PCF_SWIDTHS ( 1 << 6 )
#define PCF_GLYPH_NAMES ( 1 << 7 )
#define PCF_BDF_ACCELERATORS ( 1 << 8 )
struct SPcfHeader
{
u32 iVersion;
u32 iCount;
};
struct SPcfEntry
{
u32 iType;
u32 iFormat;
u32 iSize;
u32 iOffset;
};
struct SPcfBitmapsHeader
{
u32 iFormat;
u32 iCount;
};
struct PACKED SPcfEncodingsHeader
{
u32 iFormat;
u16 iFirstCol;
u16 iLastCol;
u16 iFirstRow;
u16 iLastRow;
u16 iDefaultChar;
};
struct SPcfCompressedMetric
{
u8 iLeftSideBearing;
u8 iRightSideBearing;
u8 iCharacterWidth;
u8 iAscent;
u8 iDescent;
};
struct SPcfAccel
{
u32 iFormat;
u8 iNoOverlap;
u8 iConstantMetrics;
u8 iTerminalFont;
u8 iConstantWidth;
u8 iInkInside;
u8 iInkMetrics;
u8 iDrawDirection;
u8 iUnused;
u32 iFontAscent;
u32 iFontDescent;
u32 iMaxOverlap;
};
#endif

View File

@ -0,0 +1,43 @@
/*
fontfactory.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "fontfactory.h"
#include "font_pcf.h"
#include "systemfilenames.h"
#include "stringtool.h"
#include "language.h"
cFontFactory::cFontFactory() : _font( NULL )
{
}
cFontFactory::~cFontFactory()
{
if( NULL != _font )
delete _font;
}
void cFontFactory::makeFont(void)
{
std::string filename(SFN_FONTS_DIRECTORY+lang().GetString("font","main",SFN_DEFAULT_FONT));
_font=new cFontPcf();
_font->Load(filename.c_str());
}

View File

@ -0,0 +1,46 @@
/*
fontfactory.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <nds.h>
#include <singleton.h>
#include "font.h"
class cFontFactory
{
public:
cFontFactory();
~cFontFactory();
void makeFont(void);
cFont & font() { return *_font; }
protected:
cFont * _font;
};
typedef t_singleton< cFontFactory > fontFactory_s;
inline cFontFactory & fontFactory() { return fontFactory_s::instance(); }
inline cFont & font() { return fontFactory_s::instance().font(); }

471
arm9/source/gbaloader.cpp Normal file
View File

@ -0,0 +1,471 @@
/*
gbaloader.cpp
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <nds.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include "exptools.h"
#include "../../share/fifotool.h"
#include "progresswnd.h"
#include "language.h"
#include "sram.h"
#include "gbapatcher.h"
#include "gbaloader.h"
#include <elm.h>
#define LEN 0x100000
#define LEN_NOR 0x8000
#define MAX_PSRAM 0x1000000
#define MAX_NOR 0x2000000
// writers >
class CGbaWriterPSRAM: public CGbaWriter
{
public:
void Open(void);
void Write(u32 address,const u8* buffer,u32 size);
void Close(void);
u32 MaxSize(void);
};
void CGbaWriterPSRAM::Open(void)
{
}
void CGbaWriterPSRAM::Write(u32 address,const u8* buffer,u32 size)
{
cExpansion::WritePSRAM(address,buffer,size);
}
void CGbaWriterPSRAM::Close(void)
{
}
u32 CGbaWriterPSRAM::MaxSize(void)
{
return 16*1024*1024;
}
class CGbaWriterNor: public CGbaWriter
{
private:
u8* iBuffer;
u32 iCurPage;
private:
enum
{
EPageSize=0x40000,
EGuardSize=256
};
private:
void Commit(void);
void Fill(void);
public:
void Open(void);
void Write(u32 address,const u8* buffer,u32 size);
void Close(void);
u32 MaxSize(void);
};
void CGbaWriterNor::Commit(void)
{
u8* backupBuffer=NULL;
if(iCurPage!=0)
{
backupBuffer=(u8*)malloc(0x4000);
if(backupBuffer) memcpy(backupBuffer,(void*)0x08004000,0x4000);
}
expansion().Block_Erase(iCurPage);
for(u32 ii=0;ii<8;ii++)
expansion().WriteNorFlash(iCurPage+ii*0x8000,iBuffer+ii*0x8000,0x8000);
if(backupBuffer&&memcmp(backupBuffer,(void*)0x08004000,0x4000)!=0)
{
expansion().WriteNorFlash(0x4000,backupBuffer,0x4000);
free(backupBuffer);
}
}
void CGbaWriterNor::Fill(void)
{
memcpy(iBuffer,(void*)(0x08000000+iCurPage),EPageSize+EGuardSize);
}
void CGbaWriterNor::Open(void)
{
iCurPage=0x666;
iBuffer=(u8*)malloc(EPageSize+EGuardSize);
}
void CGbaWriterNor::Write(u32 address,const u8* buffer,u32 size)
{
if(iBuffer)
{
if(iCurPage==0x666) //first time
{
iCurPage=address&~0x3ffff;
Fill();
}
u32 newPage=address&~0x3ffff;
if(newPage==iCurPage)
{
memcpy(iBuffer+(address-iCurPage),buffer,size);
}
else
{
Commit();
u8 overlap[EGuardSize]; bool overlaped=false;
memcpy(overlap,iBuffer+EPageSize,EGuardSize);
if(memcmp(overlap,(void*)(0x08000000+iCurPage+EPageSize),EGuardSize))
{
if(newPage-iCurPage==EPageSize)
overlaped=true;
else
{
iCurPage+=EPageSize;
Fill();
memcpy(iBuffer,overlap,EGuardSize);
Commit();
}
}
iCurPage=newPage;
Fill();
if(overlaped) memcpy(iBuffer,overlap,EGuardSize);
Write(address,buffer,size);
}
}
}
void CGbaWriterNor::Close(void)
{
if(iBuffer)
{
if(iCurPage!=0x666)
{
Commit();
}
free(iBuffer);
}
}
u32 CGbaWriterNor::MaxSize(void)
{
return 32*1024*1024;
}
// writers <
CGbaLoader::CGbaLoader(const std::string& aFileName): iFileName(aFileName)
{
}
bool CGbaLoader::Load(bool aForce,bool aNotStart)
{
if(!expansion().IsValid()) return false;
bool load=false,nor=false;
struct stat st;
if(-1==stat(iFileName.c_str(),&st))
{
return false;
}
iSize=st.st_size;
if(iSize>MAX_PSRAM)
{
nor=true;
}
else if(iSize>MAX_NOR)
{
akui::messageBox( NULL, LANG("gba warn", "title"), LANG("gba warn", "text"), MB_OK );
return false;
}
FILE* gbaFile=fopen(iFileName.c_str(),"rb");
if(gbaFile)
{
sGBAHeader header;
fread(&header,1,sizeof(header),gbaFile);
fclose(gbaFile);
if(header.is96h==0x96)
{
load=LoadInternal(nor,aForce);
}
}
if(!aNotStart&&load&&!CheckLink())
{
StartGBA();
}
return load;
}
bool CGbaLoader::CheckPSRAM(u32 aSize)
{
return (aSize>MAX_PSRAM)?false:true;
}
void CGbaLoader::StartGBA(void)
{
LoadBorder();
ELM_Unmount();
BootGBA();
while(true) swiWaitForVBlank();
}
bool CGbaLoader::CheckLink(void)
{
u32* data=(u32*)0x08000000;
if(data[0]==0xffffffff&&data[43]==0x4a42425a) return true;
return false;
}
void CGbaLoader::LoadBorder(void)
{
videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
videoSetModeSub(MODE_5_2D | DISPLAY_BG3_ACTIVE);
vramSetMainBanks(VRAM_A_MAIN_BG_0x06000000, VRAM_B_MAIN_BG_0x06020000, VRAM_C_SUB_BG_0x06200000, VRAM_D_LCD);
// for the main screen
REG_BG3CNT = BG_BMP16_256x256 | BG_BMP_BASE(0) | BG_WRAP_OFF;
REG_BG3PA = 1 << 8; //scale x
REG_BG3PB = 0; //rotation x
REG_BG3PC = 0; //rotation y
REG_BG3PD = 1 << 8; //scale y
REG_BG3X = 0; //translation x
REG_BG3Y = 0; //translation y
memset((void*)BG_BMP_RAM(0),0,0x18000);
memset((void*)BG_BMP_RAM(8),0,0x18000);
cBMP15 frameBMP=createBMP15FromFile(SFN_GBAFRAME);
if(frameBMP.valid()&&frameBMP.width()==SCREEN_WIDTH&&frameBMP.height()==SCREEN_HEIGHT)
{
DC_FlushRange(frameBMP.buffer(),SCREEN_WIDTH*SCREEN_HEIGHT*2);
dmaCopy(frameBMP.buffer(),(void*)BG_BMP_RAM(0),SCREEN_WIDTH*SCREEN_HEIGHT*2);
dmaCopy(frameBMP.buffer(),(void*)BG_BMP_RAM(8),SCREEN_WIDTH*SCREEN_HEIGHT*2);
}
}
void CGbaLoader::BootGBA(void)
{
sysSetBusOwners(BUS_OWNER_ARM7,BUS_OWNER_ARM7);
if(PersonalData->gbaScreen)
REG_POWERCNT=1;
else
REG_POWERCNT=(POWER_SWAP_LCDS|1)&0xffff;
fifoSendValue32(FIFO_USER_01,MENU_MSG_GBA);
}
bool CGbaLoader::LoadPSRAM(void)
{
bool load=false;
int gbaFile=open(iFileName.c_str(),O_RDONLY);
if(gbaFile>=0)
{
u8* buf=(u8*)malloc(LEN);
if(buf)
{
REG_EXMEMCNT&=~0x0880;
cExpansion::SetRompage(381);
cExpansion::OpenNorWrite();
cExpansion::SetSerialMode();
progressWnd().setTipText(LANG("progress window","gba load" ));
progressWnd().show();
progressWnd().setPercent(0);
for(u32 address=0;address<iSize&&address<MAX_PSRAM;address+=LEN)
{
memset(buf,0xff,LEN);
read(gbaFile,buf,LEN);
cExpansion::WritePSRAM(address,buf,LEN);
progressWnd().setPercent(address*100/iSize);
}
progressWnd().setPercent(100);
progressWnd().hide();
CGbaWriterPSRAM writer;
u32 saveSize=CGbaPatcher(iSize,&writer,(u32*)0x08060000,cExpansion::EPsramPage).Patch();
cSram::CreateDefaultFile(iFileName.c_str(),saveSize);
cExpansion::CloseNorWrite();
load=true;
free(buf);
}
close(gbaFile);
}
return load;
}
bool CGbaLoader::LoadNor(void)
{
bool load=false;
FILE* gbaFile=fopen(iFileName.c_str(),"rb");
if(gbaFile)
{
u8* buf=(u8*)malloc(LEN_NOR);
if(buf)
{
//erase
cExpansion::OpenNorWrite();
cExpansion::SetSerialMode();
progressWnd().setTipText(LANG("progress window","erase nor" ));
progressWnd().show();
progressWnd().setPercent(0);
for(u32 address=0;address<iSize&&address<MAX_NOR;address+=0x40000)
{
expansion().Block_Erase(address);
progressWnd().setPercent(address*100/iSize);
}
progressWnd().setPercent(100);
progressWnd().hide();
//write
progressWnd().setTipText(LANG("progress window","gba load" ));
progressWnd().show();
progressWnd().setPercent(0);
for(u32 address=0;address<iSize&&address<MAX_NOR;address+=LEN_NOR)
{
memset(buf,0xff,LEN_NOR);
fread(buf,LEN_NOR,1,gbaFile);
expansion().WriteNorFlash(address,buf,LEN_NOR);
progressWnd().setPercent(address*100/iSize);
}
progressWnd().setPercent(100);
progressWnd().hide();
CGbaWriterNor writer;
u32 saveSize=CGbaPatcher(iSize,&writer,(u32*)0x08000000,cExpansion::ENorPage).Patch();
cSram::CreateDefaultFile(iFileName.c_str(),saveSize);
/*
FILE *log;
log=fopen("fat0:/test.bin","wb");
fwrite((void*)0x08000000,iSize,1,log);
fclose(log);
// */
cExpansion::CloseNorWrite();
load=true;
free(buf);
}
fclose(gbaFile);
}
return load;
}
void CGbaLoader::InitNor(void)
{
cExpansion::SetRompage(0);
expansion().SetRampage(cExpansion::ENorPage);
}
void CGbaLoader::InitPSRAM(void)
{
cExpansion::SetRompage(384);
expansion().SetRampage(cExpansion::EPsramPage);
}
bool CGbaLoader::StoreOldSave(std::string& aFileName)
{
bool res=false;
const u8 sign[]="ACEKARD R.P.G GBA SIGN*";
u8 buffer[sizeof(sign)];
expansion().SetRampage(0);
cExpansion::ReadSram(0x0A000000,buffer,sizeof(buffer));
if(memcmp(buffer,sign,sizeof(buffer))) //old save
{
if(aFileName!="")
{
cSram::SaveSramToFile(aFileName.c_str(),0);
res=true;
}
expansion().SetRampage(0);
cExpansion::WriteSram(0x0A000000,sign,sizeof(sign));
}
return res;
}
bool CGbaLoader::LoadInternal(bool nor,bool force)
{
bool load=false;
expansion().SoftReset();
std::string oldFile,oldFileNOR;
CIniFile f;
oldFile=f.LoadIniFile(SFN_LAST_GBA_SAVEINFO)?f.GetString("Save Info","lastLoaded",""):"";
oldFileNOR=f.LoadIniFile(SFN_LAST_GBA_SAVEINFO)?f.GetString("Save Info","lastLoadedNOR",""):"";
if(StoreOldSave(oldFile))
{
oldFile="";
f.SetString("Save Info","lastLoaded","");
f.SaveIniFile(SFN_LAST_GBA_SAVEINFO);
}
u32 state=0;
if(nor) state|=1;
if(oldFile==iFileName) state|=2;
if(oldFileNOR==iFileName) state|=4;
if(force) state|=8;
switch(state)
{
case 0:
if(oldFile!="") cSram::SaveSramToFile(oldFile.c_str(),cExpansion::EPsramPage);
cSram::LoadSramFromFile(iFileName.c_str(),cExpansion::EPsramPage);
f.SetString("Save Info","lastLoaded",iFileName);
f.SaveIniFile(SFN_LAST_GBA_SAVEINFO);
load=LoadPSRAM();
InitPSRAM();
break;
case 10:
case 11:
if(oldFile!="") cSram::SaveSramToFile(oldFile.c_str(),cExpansion::EPsramPage);
f.SetString("Save Info","lastLoaded","");
case 1:
case 8:
case 9:
if(oldFileNOR!="") cSram::SaveSramToFile(oldFileNOR.c_str(),cExpansion::ENorPage);
cSram::LoadSramFromFile(iFileName.c_str(),cExpansion::ENorPage);
f.SetString("Save Info","lastLoadedNOR",iFileName);
f.SaveIniFile(SFN_LAST_GBA_SAVEINFO);
load=LoadNor();
InitNor();
break;
case 2:
case 3:
load=LoadPSRAM();
InitPSRAM();
break;
case 4:
case 5:
case 6:
case 7:
case 12:
case 13:
case 14:
case 15:
load=true;
InitNor();
break;
default:
expansion().SoftReset();
break;
}
return load;
}

46
arm9/source/gbaloader.h Normal file
View File

@ -0,0 +1,46 @@
/*
gbaloader.h
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GBALOADER_H__
#define __GBALOADER_H__
class CGbaLoader
{
private:
std::string iFileName;
u32 iSize;
private:
CGbaLoader();
static void LoadBorder(void);
static void BootGBA(void);
bool LoadPSRAM(void);
bool LoadNor(void);
bool LoadInternal(bool nor,bool force);
void InitNor(void);
void InitPSRAM(void);
bool StoreOldSave(std::string& aFileName);
bool CheckLink(void);
public:
CGbaLoader(const std::string& aFileName);
bool Load(bool aForce,bool aNotStart);
static bool CheckPSRAM(u32 aSize);
static void StartGBA(void);
};
#endif

50
arm9/source/gbanes.cpp Normal file
View File

@ -0,0 +1,50 @@
/*
gbanes.cpp
Copyright (C) 2008-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "gbapatcher.h"
#include <stdio.h>
#include <string.h>
#include "gba_nes_patch_bin.h"
bool CGbaPatcher::PatchNes(void)
{
bool res=false;
u32 jump=Data()[0];
if((jump&0xff000000)==0xea000000)
{
size_t index=(jump&0xffffff)+2;
if(Data()[index]==0xe28f503c&&Data()[index+1]==0xe8b503d3&&Data()[index+2]==0xe129f007&&Data()[index+3]==0xe281deba&&Data()[index+4]==0xe129f008&&Data()[index+5]==0xe281debe&&Data()[index+6]==0xe129f009&&Data()[index+7]==0xe281dc0b&&Data()[index+8]==0xe92d0003&&Data()[index+9]==0xef110000&&Data()[index+10]==0xe8bd8001)
{
res=true;
iSaveSize=8*1024;
u32 patch=0xea000000|(0x3fdf5-index);
iWriter->Write(36+index*4,(u8*)&patch,sizeof(patch));
iWriter->Write(0xff800,gba_nes_patch_bin,gba_nes_patch_bin_size);
patch=Data()[index+17];
iWriter->Write(0xff840,(u8*)&patch,sizeof(patch));
size_t index2=(patch-0x08000000)/4;
if(Data()[index2-1]==0x3032)
{
patch=0x060000f8;
iWriter->Write(0xff86c,(u8*)&patch,sizeof(patch));
}
}
}
return res;
}

1829
arm9/source/gbapatcher.cpp Normal file

File diff suppressed because it is too large Load Diff

157
arm9/source/gbapatcher.h Normal file
View File

@ -0,0 +1,157 @@
/*
gbapatcher.h
Copyright (C) 2008-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GBAPATCHER_H__
#define __GBAPATCHER_H__
#include <nds.h>
#include <setjmp.h>
//typedef void (*TFlashWriteFunc)(u32 address,const u8* buffer,u32 size);
class CGbaWriter
{
public:
virtual ~CGbaWriter();
virtual void Open(void)=0;
virtual void Write(u32 address,const u8* buffer,u32 size)=0;
virtual void Close(void)=0;
virtual u32 MaxSize(void)=0;
};
class CGbaPatcher
{
private:
enum TPatchType
{
//flash
ESRAMLabel,
EEEPROMLabel,
EEEPROMRead,
EEEPROMWrite,
EEEPROMWrite124,
EEEPROMWrite126,
EFLASH1M10XLabel,
EFLASH1M102_1,
EFLASH1M102_2,
EFLASH1M102_3,
EFLASH1M102_4,
EFLASH1M102_5,
EFLASH1M103_1,
EFLASH1M103_2,
EFLASH1M103_3,
EFLASH1M103_4,
EFLASHLabel,
EFLASH_1,
EFLASH_2,
EFLASH_3,
EFLASH_4,
EFLASHV123_1,
EFLASHV123_2,
EFLASHV123_3,
EFLASHV123_4,
EFLASHV123_5,
EFLASH512Label,
EFLASH512_1,
EFLASH512_2,
//last
ELast
};
enum
{
EMax=32
};
private:
struct SPatchInfo
{
u32 iOffset;
TPatchType iType;
};
struct SPatchInfo2
{
u32 iOffset;
u32 iValue;
};
struct SPatchInfo3
{
u32 iLocation;
u32 iAddress;
u32 iRa;
u32 iRb;
};
struct SPatchInfo4
{
u32 iOffset;
u16 iValue;
};
private:
SPatchInfo iPatchInfo[EMax];
u32 iCount;
SPatchInfo2 iPatchInfo2[EMax*2];
u32 iCount2;
SPatchInfo3 iPatchInfo3[EMax];
u32 iCount3;
SPatchInfo4 iPatchInfo4[EMax];
u32 iCount4;
u32 iSize;
u32* iData;
u32 iTrimSize;
u32 iResultSize;
jmp_buf iJumpBuf;
u32 iSaveSize;
CGbaWriter* iWriter;
u8 iRamPage;
private:
CGbaPatcher();
void Error(const char* anError);
inline u32* Data(void) {return iData;};
inline u16* Data16(void) {return (u16*)iData;};
inline u8* Data8(void) {return (u8*)iData;};
void Add(u32 anOffset,TPatchType aType);
void Add2(u32 anOffset,u32 aValue);
void Add3(u32 aLocation,u32 anAddress,u32 aRa,u32 aRb);
void Add4(u32 anOffset,u16 aValue);
void PatchInternal(void);
//flash
bool PatchSRAM(void);
bool PatchEEPROM(void);
bool PatchFLASH1M_V10X(void);
bool PatchFLASH(void);
void PatchEEPROM111(void);
//sleep
bool PatchSleep(void);
//common sleep
void CommonSleepSearch(void);
void CommonSleepPatch(void);
void SetTrimSize(void);
//classic nes collection
bool PatchNes(void);
//cracks
bool PatchDragonBallZ(void);
#ifdef __TEST
private:
void DumpPatchInfo(void);
#endif
public:
CGbaPatcher(u32 aSize,CGbaWriter* aWriter,u32* aData,u8 aRamPage);
u32 Patch(void);
inline u32 ResultSize(void) {return iResultSize;};
};
#endif

286
arm9/source/gbasleep.cpp Normal file
View File

@ -0,0 +1,286 @@
/*
gbasleep.cpp
Copyright (C) 2007 By Dan Weiss (Dwedit)
Copyright (C) 2008-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "gbapatcher.h"
#include <stdio.h>
#include <string.h>
#include "gba_sleep_patch_bin.h"
const int ACTIVATION_SIZE=36;
const int FAKE_SIZE=512*1024; //search in first 512k
const int PATCH_LENGTH=2048;
void CGbaPatcher::CommonSleepSearch(void)
{
//The LDR,=xxxxxxxx ARM instruction:
//
//Load/Store=1
//Writeback=0
//Byte/Word=0
//Up/Down=either
//Pre/Post=?
//Immediate Offset=0
//rn = r15
//cond= always
//1110 01 0 p u 0 0 1 1111 rrrr oooooooooooo
//Instruction Mask:
//1111 11 1 0 0 1 1 1 1111 0000 000000000000
//Instruction Bits:
//1110 01 0 0 0 0 0 1 1111 0000 000000000000
//The STR rd,[rn] ARM instruction:
//Load/Store=0
//Writeback=0
//Byte/Word=0
//Up/Down=?
//Pre/Post=?
//Immediate Offset=0
//cond= always
//1110 01 0 p u 0 0 0 rnrn rdrd 000000000000
//MASK:
//1111 11 1 0 0 1 1 1 0000 0000 111111111111
//BITS:
//1110 01 0 0 0 0 0 0 0000 0000 000000000000
//THUMB:
//LDR rd,=xxxxxxxx
//01001rrroooooooo
//1111100000000000
//0100100000000000
//STR rd,[rb]
//01100 00000 bbb ddd
//11111 11111 000 000
//01100 00000 000 000
const u32 ldr_mask=0xFE7F0000;
const u32 ldr_bits=0xE41F0000;
const u32 str_mask=0xFE700FFF;
const u32 str_bits=0xE4000000;
const u32 t_ldr_mask=0xF800;
const u32 t_ldr_bits=0x4800;
const u32 t_str_mask=0xFFC0;
const u32 t_str_bits=0x6000;
u32 reg_data[16]; //contents of register
u32 reg_addr[16]; //address of the data which got written
u32 reg_lastwrite[16]; //PC at which the data was written to
memset(reg_data,0,sizeof(reg_data));
memset(reg_addr,0,sizeof(reg_addr));
memset(reg_lastwrite,0,sizeof(reg_lastwrite));
SetTrimSize();
if((iTrimSize+PATCH_LENGTH)>iWriter->MaxSize()) return;
u32 fake_size=FAKE_SIZE;
if(fake_size>iTrimSize) fake_size=iTrimSize;
//arm
u32 patch_location=iTrimSize;
u32 activation_location=patch_location+gba_sleep_patch_bin_size;
u32 search_size=fake_size/sizeof(u32);
for(u32 ii=0;ii<search_size;ii++)
{
u32 word=Data()[ii];
//check for LDR xx,=xxxxxxxx
if((word&ldr_mask)==ldr_bits)
{
u32 pc=ii*sizeof(u32)+8;
//1110 01 0 p u 0 0 1 1111 rrrr oooooooooooo
//0000 00 0 0 1 0 0 0 0000 0000 000000000000
int updown=-1;
if((word&0x800000))
{
updown=1;
}
int rd=((word>>12)&0x0F);
int offset=(word&0xFFF);
u32 address=(updown)*offset + pc;
u32 memdata=0xDEADBEEF;
if(address>=0&&address<iSize-3)
{
if((address&0x03)==0x00)
{
memdata=Data()[address/sizeof(u32)];
}
}
reg_data[rd]=memdata;
reg_addr[rd]=address;
reg_lastwrite[rd]=ii*sizeof(u32);
}
else if((word&str_mask)==str_bits)
{
//1110 01 0 p u 0 0 0 rnrn rdrd 000000000000
int rn,rd;
rn=((word>>16)&0x0F);
rd=((word>>12)&0x0F);
u32 myaddress=ii*sizeof(u32);
bool okay=true
&&(reg_data[rn]==0x03007FFC)
&&(myaddress-reg_lastwrite[rd]<64)
&&(myaddress-reg_lastwrite[rn]<64)
&&(reg_lastwrite[rd]!=0)
&&(reg_lastwrite[rn]!=0)
&&((reg_data[rd]&0xFF000000)==0x03000000)
;
if(!okay&&reg_data[rn]==0x03007FFC)
{
if(myaddress==0xE0)
{
okay=true;
}
}
if(myaddress<reg_lastwrite[rd]||myaddress<reg_lastwrite[rn])
{
okay=false;
}
if(okay)
{
{
//str rd,[rn] >> BX rn
Add2(myaddress,0xE12FFF10+rn);
//ldr rn,=XXXX >> ldr rn,=activation_jump
u32 data_address=reg_addr[rn];
if(data_address>=0&&data_address<iSize-3)
{
Add2(data_address,0x08000000+activation_location);
}
}
Add3(activation_location,myaddress+4,rd,rn);
activation_location+=ACTIVATION_SIZE;
}
}
}
//thumb
memset(reg_data,0,sizeof(reg_data));
memset(reg_addr,0,sizeof(reg_addr));
memset(reg_lastwrite,0,sizeof(reg_lastwrite));
search_size=fake_size/sizeof(u16);
//this code is Little Endian Only
for(u32 ii=0;ii<search_size;ii++)
{
u16 word=Data16()[ii];
//check for LDR xx,=xxxxxxxx
if ((word&t_ldr_mask)==t_ldr_bits)
{
u32 pc=ii*sizeof(u16)+4;
//01001rrroooooooo
int rd=((word>>8)&0x07);
int offset=(word&0xFF);
u32 address=offset*4+pc;
u32 memdata=0xDEADBEEF;
address&=~0x03;
if(address>=0&&address<iSize-3)
{
if((address&0x03)==0x00)
{
memdata=Data()[address/sizeof(u32)];
}
}
reg_data[rd]=memdata;
reg_addr[rd]=address;
reg_lastwrite[rd]=ii*sizeof(u16);
}
else if((word&t_str_mask)==t_str_bits)
{
//01100 00000 bbb ddd
int rb,rd;
rb=((word>>3)&0x07);
rd=((word>>0)&0x07);
u32 myaddress=ii*sizeof(u16);
bool okay=true
&&(reg_data[rb]==0x03007FFC)
&&(myaddress-reg_lastwrite[rd]<80)
&&(myaddress-reg_lastwrite[rb]<64)
&&(reg_lastwrite[rd]!=0)
&&(reg_lastwrite[rb]!=0)
&&((reg_data[rd]&0xFF000000)==0x03000000)
;
if(okay)
{
{
//str rd,[rn] >> BX rb
Add4(myaddress,0x4700+(rb<<3));
//ldr rn,=XXXX >> ldr rn,=activation_jump
u32 data_address=reg_addr[rb];
if(data_address>=0&&data_address<iSize-3)
{
Add2(data_address,0x08000000+activation_location);
}
}
Add3(activation_location,myaddress+1+2,rd,rb);
activation_location+=ACTIVATION_SIZE;
reg_data[rb]=0; //for mario kart. may regress for another games.
}
}
}
}
void CGbaPatcher::SetTrimSize(void)
{
u8 byte=Data8()[iSize-1];
u32 bottom=iSize-2,top=bottom-PATCH_LENGTH-16,alignedSize=iSize+(16-(iSize&15));
for(u32 ii=bottom;ii>=top;ii--)
{
if(Data8()[ii]!=byte||ii==top)
{
iTrimSize=ii+4;
iTrimSize=iTrimSize+(16-(iTrimSize&15));
if(iTrimSize>alignedSize) iTrimSize=alignedSize;
break;
}
}
}
void CGbaPatcher::CommonSleepPatch(void)
{
if(!(iCount2+iCount4)) return;
for(u32 ii=0;ii<iCount2;ii++)
{
iWriter->Write(iPatchInfo2[ii].iOffset,(u8*)&(iPatchInfo2[ii].iValue),sizeof(iPatchInfo2[ii].iValue));
}
for(u32 ii=0;ii<iCount4;ii++)
{
iWriter->Write(iPatchInfo4[ii].iOffset,(u8*)&(iPatchInfo4[ii].iValue),sizeof(iPatchInfo4[ii].iValue));
}
iResultSize=iTrimSize;
iWriter->Write(iTrimSize,gba_sleep_patch_bin,gba_sleep_patch_bin_size);
iResultSize=iTrimSize+gba_sleep_patch_bin_size+ACTIVATION_SIZE*iCount3;
for(u32 ii=0;ii<iCount3;ii++)
{
u32 mem[9];
mem[0]=0xE92D5003;
mem[1]=0xE1A0C000+iPatchInfo3[ii].iRa;
mem[2]=0xE1A01000+iPatchInfo3[ii].iRb;
mem[3]=0xE1A0000C;
mem[4]=0xEB000000+((0x00FFFFFF)&((iTrimSize-(iPatchInfo3[ii].iLocation+8+16))>>2));
mem[5]=0xE8BD5003;
mem[6]=0xE59F0000+(iPatchInfo3[ii].iRb<<12);
mem[7]=0xE12FFF10+iPatchInfo3[ii].iRb;
mem[8]=iPatchInfo3[ii].iAddress+0x08000000;
iWriter->Write(iPatchInfo3[ii].iLocation,(u8*)mem,sizeof(mem));
}
}

672
arm9/source/gdi.cpp Normal file
View File

@ -0,0 +1,672 @@
/*
gdi.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <cstring>
#include <cstdio>
#include "dbgtool.h"
#include "gdi.h"
#include "sprite.h"
#include "../../share/memtool.h"
#include "userinput.h"
#include "globalsettings.h"
#include "fontfactory.h"
static inline void dmaCopyWordsGdi(uint8 channel,const void* src,void* dest,uint32 size)
{
DC_FlushRange(src,size);
dmaCopyWords(channel,src,dest,size);
DC_InvalidateRange(dest,size);
}
#ifdef DEBUG
PrintConsole custom_console;
static void MyInitConsole(u16* aBufferSub1,u16* aBufferSub2)
{
custom_console=*consoleGetDefault();
custom_console.loadGraphics=false;
consoleInit(&custom_console, custom_console.bgLayer, BgType_Text4bpp, BgSize_T_256x256, custom_console.mapBase, custom_console.gfxBase, false, false);
custom_console.fontBgMap=aBufferSub1;
custom_console.fontBgGfx=aBufferSub2;
dmaCopy(custom_console.font.gfx, custom_console.fontBgGfx, custom_console.font.numChars * 64 / 2);
custom_console.fontCurPal = 15 << 12;
u16* palette = BG_PALETTE_SUB;
palette[1 * 16 - 15] = RGB15(0,0,0); //30 normal black
palette[2 * 16 - 15] = RGB15(15,0,0); //31 normal red
palette[3 * 16 - 15] = RGB15(0,15,0); //32 normal green
palette[4 * 16 - 15] = RGB15(15,15,0); //33 normal yellow
palette[5 * 16 - 15] = RGB15(0,0,15); //34 normal blue
palette[6 * 16 - 15] = RGB15(15,0,15); //35 normal magenta
palette[7 * 16 - 15] = RGB15(0,15,15); //36 normal cyan
palette[8 * 16 - 15] = RGB15(24,24,24); //37 normal white
palette[9 * 16 - 15] = RGB15(15,15,15); //40 bright black
palette[10 * 16 - 15] = RGB15(31,0,0); //41 bright red
palette[11 * 16 - 15] = RGB15(0,31,0); //42 bright green
palette[12 * 16 - 15] = RGB15(31,31,0); //43 bright yellow
palette[13 * 16 - 15] = RGB15(0,0,31); //44 bright blue
palette[14 * 16 - 15] = RGB15(31,0,31); //45 bright magenta
palette[15 * 16 - 15] = RGB15(0,31,31); //46 bright cyan
palette[16 * 16 - 15] = RGB15(31,31,31); //47 & 39 bright white
}
#endif
cGdi::cGdi()
{
_transColor=0;
_mainEngineLayer=MEL_UP;
_subEngineMode=SEM_TEXT;
_bufferMain2=NULL;
_bufferSub2=NULL;
#ifdef DEBUG
_bufferSub3=NULL;
#endif
_sprites=NULL;
}
cGdi::~cGdi()
{
if( NULL != _bufferMain2 )
delete[] _bufferMain2;
if( NULL != _bufferSub2 )
delete[] _bufferSub2;
#ifdef DEBUG
if( NULL != _bufferSub3 )
delete[] _bufferSub3;
#endif
if( NULL != _sprites )
delete[] _sprites;
}
void cGdi::init()
{
swapLCD();
activeFbMain();
activeFbSub();
cSprite::sysinit();
}
void cGdi::initBg(const std::string& aFileName)
{
_sprites=new cSprite[12];
_background=createBMP15FromFile(aFileName);
if(_background.width()<SCREEN_WIDTH&&_background.height()<SCREEN_WIDTH)
{
_background=createBMP15(SCREEN_WIDTH,SCREEN_HEIGHT);
zeroMemory(_background.buffer(),_background.height()*_background.pitch());
}
u32 pitch=_background.pitch()>>1;
for(size_t ii=0;ii<3;++ii)
{
for(size_t jj=0;jj<4;++jj)
{
size_t index=ii*4+jj;
_sprites[index].init(2+index);
_sprites[index].setSize(SS_SIZE_64);
_sprites[index].setPriority(3);
_sprites[index].setBufferOffset(32+index*64);
_sprites[index].setPosition(jj*64,ii*64);
for(size_t kk=0;kk<64;++kk)
{
for(size_t ll=0;ll<64;++ll)
{
((u16*)_sprites[index].buffer())[kk*64+ll]=((u16*)_background.buffer())[(kk+ii*64)*pitch+(ll+jj*64)];
}
}
_sprites[index].show();
}
}
}
void cGdi::swapLCD(void)
{
lcdSwap();
}
void cGdi::activeFbMain(void)
{
vramSetBankB( VRAM_B_MAIN_BG_0x06000000 );
vramSetBankD( VRAM_D_MAIN_BG_0x06020000 );
vramSetBankA( VRAM_A_MAIN_SPRITE_0x06400000 );
REG_BG2CNT = BG_BMP16_256x256 | BG_BMP_BASE(0) | BG_PRIORITY_1;
REG_BG2PA = 1 << 8; // 2 =放大倍数
REG_BG2PD = 1 << 8; // 2 =放大倍数
REG_BG2PB = 0;
REG_BG2PC = 0;
REG_BG2Y = 0;
REG_BG2X = 0;
REG_BG3CNT = BG_BMP16_256x256 | BG_BMP_BASE(8) | BG_PRIORITY_2;
REG_BG3PA = 1 << 8; // 2 =放大倍数
REG_BG3PD = 1 << 8; // 2 =放大倍数
REG_BG3PB = 0;
REG_BG3PC = 0;
REG_BG3Y = 0;
REG_BG3X = 0;
_bufferMain1 = (u16 *)0x06000000;
_bufferMain2 = (u16 *)new u32[256*192];
_bufferMain3 = (u16 *)0x06020000;
setMainEngineLayer( MEL_UP );
zeroMemory( _bufferMain1, 0x20000 );
//fillMemory( _bufferMain3, 0x20000, 0x8f008f00 );
fillMemory( _bufferMain3, 0x20000, 0xffffffff );
REG_BLDCNT = BLEND_ALPHA | BLEND_DST_BG2 | BLEND_DST_BG3;
REG_BLDALPHA = (4 << 8) | 7;
swiWaitForVBlank(); //remove tearing at bottop screen
videoSetMode( MODE_5_2D
| DISPLAY_BG2_ACTIVE
| DISPLAY_BG3_ACTIVE
| DISPLAY_SPR_ACTIVE
| DISPLAY_SPR_1D_BMP_SIZE_128
| DISPLAY_SPR_1D_BMP );
}
void cGdi::activeFbSub(void)
{
#ifdef DEBUG
_bufferSub3 = (u16 *)new u32[0x1200];
MyInitConsole(_bufferSub3+0x2000,_bufferSub3);
#endif
// 分配显存存, 128k
vramSetBankC( VRAM_C_SUB_BG_0x06200000 ); // 128k
// 初始化为文字模式
_subEngineMode = SEM_GRAPHICS;
//_subEngineMode = SEM_TEXT;
// BMP bg 的参数设置,从 VRAM地址 0x06200000 开始优先级3
REG_BG2CNT_SUB = BG_BMP16_256x256 | BG_BMP_BASE(0) | BG_PRIORITY_1;
REG_BG2PA_SUB = 1<<8;
REG_BG2PD_SUB = 1<<8;
REG_BG2PB_SUB = 0;
REG_BG2PC_SUB = 0;
REG_BG2Y_SUB = 0;
REG_BG2X_SUB = 0;
_bufferSub1 = (u16 *)0x06200000;
_bufferSub2 = (u16 *)new u32[256*192/2];
//fillMemory( _bufferSub2, 0x18000, 0xfc00fc00 );
//fillMemory( _bufferSub1, 0x18000, 0xfc00fc00 );
fillMemory( _bufferSub2, 0x18000, 0xffffffff );
fillMemory( _bufferSub1, 0x18000, 0xffffffff );
// text BG
// text bg 的字模占用 32(字节/字模) * 256(个ascii字) = 8192 字节显存,
// 文字显示占用 32 x 32 * 2 = 2048 字节显存
// 字模从 block 8 开始 = 0x06200000 + 8 * 0x4000 = 0x06220000
// 文字信息从 block 72 开始 = 0x06200000 + 72 * 0x800 = 0x06224000
// 优先级 2
#ifdef DEBUG
BG_PALETTE_SUB[255] = RGB15(31,31,31); //by default font will be rendered with color 255
REG_BG0CNT_SUB = BG_TILE_BASE(0) | BG_MAP_BASE(8) | BG_PRIORITY_2;
#endif
swiWaitForVBlank(); //remove tearing at top screen
// 模式5开两层BG一层BMP一层文字(用于调试)bmp层现在默认关闭
videoSetModeSub( MODE_5_2D | DISPLAY_BG2_ACTIVE );// | DISPLAY_BG2_ACTIVE );
}
void cGdi::drawLine( s16 x1, s16 y1, s16 x2, s16 y2, GRAPHICS_ENGINE engine )
{
if((x1==x2)&&(y1==y2)) return;
if(x1==x2) {
int ys,ye;
if(y1<y2) {
ys=y1;
ye=y2-1;
} else {
ys=y2+1;
ye=y1;
}
for(int py=ys;py<=ye;py++) {
drawPixel(x1,py,engine);
}
return;
}
if(y1==y2) {
int xs,xe;
if(x1<x2) {
xs=x1;
xe=x2-1;
} else {
xs=x2+1;
xe=x1;
}
//for(int px=xs;px<=xe;px++) {
// drawPixel(px,y1,engine);
// //SetPixel(px,y1,Color);
//}
if( GE_MAIN == engine )
fillRect( _penColor, _penColor, xs, y1, xe - xs + 1, 1, engine );
else
fillRect( _penColorSub, _penColorSub, xs, y1, xe - xs + 1, 1, engine );
return;
}
if(abs(x2-x1)>abs(y2-y1)) {
int px=0;
float py=0;
int xe=x2-x1;
float ye=y2-y1;
int xv;
float yv;
if(0<xe) {
xv=1;
} else {
xv=-1;
}
yv=ye/abs(xe);
while(px!=xe) {
drawPixel(x1+px,y1+(int)py,engine);
px+=xv;
py+=yv;
}
return;
}
else {
float px=0;
int py=0;
float xe=x2-x1;
int ye=y2-y1;
float xv;
int yv;
xv=xe/abs(ye);
if(0<ye) {
yv=1;
} else {
yv=-1;
}
while(py!=ye) {
//if(AALineFlag==false){
drawPixel(x1+(int)px,y1+py,engine);
//}else{
// int Alpha=(int)(px*32);
// if(Alpha<0){
// while(Alpha<=0) Alpha+=32;
// }else{
// while(32<=Alpha) Alpha-=32;
// }
// SetPixelAlpha(x1+(int)px+0,y1+py,Color,32-Alpha);
// SetPixelAlpha(x1+(int)px+1,y1+py,Color,Alpha);
//}
px+=xv;
py+=yv;
}
return;
}
}
void cGdi::frameRect( s16 x, s16 y, u16 w, u16 h, GRAPHICS_ENGINE engine )
{
drawLine( x, y, x + w - 1, y, engine );
drawLine( x + w - 1, y, x + w - 1, y + h - 1, engine );
drawLine( x + w - 1, y + h - 1, x, y + h - 1, engine );
drawLine( x, y + h - 1, x, y, engine );
}
void cGdi::frameRect( s16 x, s16 y, u16 w, u16 h, u16 thickness, GRAPHICS_ENGINE engine )
{
for(size_t ii=0;ii<thickness;++ii)
{
frameRect(x,y,w,h,engine);
if(h<=2||w<=2) break;
++x; ++y; w-=2; h-=2;
}
}
void cGdi::fillRect( u16 color1, u16 color2, s16 x, s16 y, u16 w, u16 h, GRAPHICS_ENGINE engine )
{
ALIGN(4) u16 color[2] = { BIT(15) | color1 , BIT(15) | color2 };
u16 * pSrc = (u16 *)color;
u16 * pDest = NULL;
if( GE_MAIN == engine )
pDest = _bufferMain2 + (y << 8) + x + _layerPitch;//_bufferMain2 + y * 256 + x + _layerPitch;
else
pDest = _bufferSub2 + (y << 8) + x; //_bufferSub2 + y * 256 + x;
bool destAligned = !(x & 1);
u16 destInc = 256 - w;
u16 halfWidth = w >> 1;
u16 remain = w & 1;
if( destAligned )
for( u32 i = 0; i < h; ++i ) {
swiFastCopy( pSrc, pDest, COPY_MODE_WORD | COPY_MODE_FILL | halfWidth );
pDest += halfWidth << 1;
if( remain )
*pDest++ = *pSrc;
pDest += destInc;
}
else
for( u32 i = 0; i < h; ++i ) {
for( u32 j = 0; j < w; ++j ) {
*pDest++ = pSrc[j&1];
}
pDest += destInc;
}
}
void cGdi::fillRectBlend( u16 color1, u16 color2, s16 x, s16 y, u16 w, u16 h, GRAPHICS_ENGINE engine, u16 opacity)
{
if(opacity==0) return;
if(opacity==100)
{
fillRect(color1,color2,x,y,w,h,engine);
return;
}
u16* pSrc=((GE_MAIN==engine)?(u16*)_background.buffer():_bufferSub2)+(y<<8)+x;
u16* pDest=((GE_MAIN==engine)?(_bufferMain2+_layerPitch):_bufferSub2)+(y<<8)+x;
u32 alpha=(opacity*32)/100;
u32 destInc=256-w;
for(u32 ii=0;ii<h;++ii)
{
for(u32 jj=0;jj<w;++jj)
{
u32 original=*pSrc++&0x7fff;
u32 color=(jj&1)?color2:color1;
u32 rb=((color&0x7c1f)*alpha+(original&0x7c1f)*(32-alpha))&0xf83e0;
u32 g=((color&0x3e0)*alpha+(original&0x3e0)*(32-alpha))&0x7c00;
*pDest++=((rb|g)>>5)|BIT(15);
}
pDest+=destInc;
pSrc+=destInc;
}
}
void cGdi::bitBlt( const void * src, s16 srcW, s16 srcH, s16 destX, s16 destY, u16 destW, u16 destH, GRAPHICS_ENGINE engine )
{
if( destW <= 0 )
return;
u16 * pSrc = (u16 *)src;
u16 * pDest = NULL;
if( GE_MAIN == engine )
pDest = _bufferMain2 + (destY) * 256 + destX + _layerPitch;
else
pDest = _bufferSub2 + (destY) * 256 + destX;
bool destAligned = !(destX & 1);
if( destW > srcW )
destW = srcW;
if( destH > srcH )
destH = srcH;
u16 srcInc = srcW - destW;
u16 destInc = 256 - destW;
u16 destHalfWidth = destW >> 1;
u16 lineSize = destW << 1;
u16 remain = destW & 1;
if( destAligned ) {
for( u32 i = 0; i < destH; ++i ) {
dmaCopyWordsGdi( 3, pSrc, pDest, lineSize );
pDest += destHalfWidth << 1;
pSrc += destHalfWidth << 1;
if( remain )
*pDest++ = *pSrc++;
pDest += destInc;
pSrc += srcInc;
}
}
}
void cGdi::bitBlt( const void * src, s16 destX, s16 destY, u16 destW, u16 destH, GRAPHICS_ENGINE engine )
{
//dbg_printf("x %d y %d w %d h %d\n", destX, destY, destW, destH );
u16 * pSrc = (u16 *)src;
u16 * pDest = NULL;
if( GE_MAIN == engine )
pDest = _bufferMain2 + (destY) * 256 + destX + _layerPitch;
else
pDest = _bufferSub2 + (destY) * 256 + destX;
u16 pitchPixel = (destW + (destW & 1));
u16 destInc = 256 - pitchPixel;
u16 halfPitch = pitchPixel >> 1;
u16 remain = pitchPixel & 1;
for( u16 i = 0; i < destH; ++i ) {
swiFastCopy( pSrc, pDest, COPY_MODE_WORD | COPY_MODE_COPY | halfPitch );
pDest += halfPitch << 1;
pSrc += halfPitch << 1;
if( remain )
*pDest++ = *pSrc++;
pDest += destInc;
}
}
// maskBlt 要destW是偶数速度可以快一倍
// 不是偶数也可以,但要求在内存中 src 的 pitch 凑成偶数
void cGdi::maskBlt( const void * src, s16 destX, s16 destY, u16 destW, u16 destH, GRAPHICS_ENGINE engine )
{
//dbg_printf("x %d y %d w %d h %d\n", destX, destY, destW, destH );
u16 * pSrc = (u16 *)src;
u16 * pDest = NULL;
bool destAligned = !(destX & 1);
if( GE_MAIN == engine )
pDest = _bufferMain2 + (destY) * 256 + destX + _layerPitch;
else
pDest = _bufferSub2 + (destY) * 256 + destX;
u16 pitch = (destW + (destW & 1));
u16 destInc = 256 - pitch;
u16 halfPitch = pitch >> 1;
if( destAligned )
for( u32 i = 0; i < destH; ++i ) {
for( u32 j = 0; j < halfPitch; ++j ) {
if( ((*(u32 *)pSrc) & 0x80008000) == 0x80008000 ) {
*(u32 *)pDest = *(u32 *)pSrc;
pSrc += 2; pDest += 2;
}
else {
if( *pSrc & 0x8000 )
*pDest = *pSrc;
pSrc++; pDest++;
if( *pSrc & 0x8000 )
*pDest = *pSrc;
pSrc++; pDest++;
}
}
pDest += destInc;
}
else
for( u16 i = 0; i < destH; ++i ) {
for( u16 j = 0; j < pitch; ++j ) {
if( *pSrc & 0x8000 )
*pDest = *pSrc;
pDest++; pSrc++;
}
pDest += destInc;
}
}
void cGdi::maskBlt( const void * src, s16 srcW, s16 srcH, s16 destX, s16 destY, u16 destW, u16 destH, GRAPHICS_ENGINE engine )
{
if( destW <= 0 )
return;
u16 * pSrc = (u16 *)src;
u16 * pDest = NULL;
if( GE_MAIN == engine )
pDest = _bufferMain2 + (destY) * 256 + destX + _layerPitch;
else
pDest = _bufferSub2 + (destY) * 256 + destX;
bool destAligned = !(destX & 1);
if( destW > srcW )
destW = srcW;
if( destH > srcH )
destH = srcH;
u16 srcInc = srcW - destW;
u16 destInc = 256 - destW;
u16 destHalfWidth = destW >> 1;
u16 pitch = (destW + (destW & 1));
u16 remain = destW & 1;
if( destAligned ) {
for( u32 i = 0; i < destH; ++i ) {
for( u32 j = 0; j < destHalfWidth; ++j ) {
if( ((*(u32 *)pSrc) & 0x80008000) == 0x80008000 ) {
*(u32 *)pDest = *(u32 *)pSrc;
pSrc += 2; pDest += 2;
}
else {
if( *pSrc & 0x8000 )
*pDest = *pSrc;
pSrc++; pDest++;
if( *pSrc & 0x8000 )
*pDest = *pSrc;
pSrc++; pDest++;
}
}
if( remain )
*pDest++ = *pSrc++;
pDest += destInc;
pSrc += srcInc;
}
}
else
for( u16 i = 0; i < destH; ++i ) {
for( u16 j = 0; j < pitch; ++j ) {
if( *pSrc & 0x8000 )
*pDest = *pSrc;
pDest++; pSrc++;
}
pDest += destInc;
pSrc += srcInc;
}
}
void cGdi::textOutRect( s16 x, s16 y, u16 w, u16 h, const char * text, GRAPHICS_ENGINE engine )
{
const s16 originX=x,limitY=y+h-gs().fontHeight;
while(*text)
{
if('\r'==*text||'\n'==*text)
{
y+=gs().fontHeight; //FIXME
x=originX;
++text;
if(y>limitY) break;
}
else
{
u32 ww,add;
font().Info(text,&ww,&add);
if(x+(s16)ww<originX+w)
{
font().Draw((GE_MAIN==engine)?(_bufferMain2+_layerPitch):_bufferSub2,x,y,(const u8*)text,(GE_MAIN==engine)?_penColor:_penColorSub);
}
text+=add;
x+=ww;
}
}
}
void cGdi::present( GRAPHICS_ENGINE engine )
{
if( GE_MAIN == engine ) { // 翻转主引擎
//u16 * temp = _bufferMain1;
//_bufferMain1 = _bufferMain2;
//_bufferMain2 = temp;
//REG_BG2CNT ^= BG_BMP_BASE( 128 / 16 );
dmaCopyWordsGdi( 3, _bufferMain2 + _layerPitch,
_bufferMain1 + (_mainEngineLayer << 16), 256 * 192 * 2 );
fillMemory( (void *)(_bufferMain2 + _layerPitch), 256 * 192 * 2, 0 );
} else if ( GE_SUB == engine ) { // 翻转副引擎
if( SEM_GRAPHICS == _subEngineMode )
dmaCopyWordsGdi( 3, (void *)_bufferSub2, (void *)_bufferSub1, 256 * 192 * 2 );
//else if( SEM_TEXT == _subEngineMode )
// dmaCopyWords( 3, (void *)_bufferSub3, (void *)_bufferSub1, 32768 );
fillMemory( (void *)_bufferSub2, 0x18000, 0xffffffff );
}
//dbg_printf( "\x1b[0;20%f\n", updateTimer() );
}
//special version for window switching
void cGdi::present(void)
{
swiWaitForVBlank();
dmaCopyWordsGdi(3,_bufferMain2,_bufferMain1,256*192*2);
dmaCopyWordsGdi(3,_bufferMain2+(256*192),_bufferMain1+(1<<16),256*192*2);
fillMemory((void *)_bufferMain2,256*192*4,0);
}
#ifdef DEBUG
void cGdi::switchSubEngineMode()
{
// 需要保存和恢复文本模式的现场
switch( _subEngineMode )
{
case SEM_GRAPHICS: // 当前是图形模式的话就恢复刚才的text现场
videoSetModeSub( MODE_5_2D | DISPLAY_BG0_ACTIVE );
custom_console.fontBgMap=(u16*)0x6204000;
custom_console.fontBgGfx=(u16*)0x6200000;
dmaCopyWordsGdi( 3, (void *)_bufferSub3, (void *)_bufferSub1, 0x4800 );
break;
case SEM_TEXT: // 当前是文字模式的话,保存现场,切到图形模式
videoSetModeSub( MODE_5_2D | DISPLAY_BG2_ACTIVE );
custom_console.fontBgMap=_bufferSub3+0x2000;
custom_console.fontBgGfx=_bufferSub3;
dmaCopyWordsGdi( 3, (void *)_bufferSub1, (void *)_bufferSub3, 0x4800 );
break;
};
_subEngineMode = (SUB_ENGINE_MODE)(_subEngineMode^1);
}
#endif

151
arm9/source/gdi.h Normal file
View File

@ -0,0 +1,151 @@
/*
gdi.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _GDI_H_
#define _GDI_H_
#include <nds.h>
#include <vector>
#include "singleton.h"
#include "gdi.h"
#include "bmp15.h"
#define SYSTEM_FONT_HEIGHT 12
#define COLOR u16
enum GRAPHICS_ENGINE
{
GE_MAIN = 0,
GE_SUB = 1
};
enum MAIN_ENGINE_LAYER
{
MEL_UP = 0,
MEL_DOWN = 1
};
enum SUB_ENGINE_MODE
{
SEM_TEXT = 0,
SEM_GRAPHICS = 1
};
class cSprite;
class cGdi
{
public:
cGdi();
virtual ~cGdi();
public:
void init();
void initBg(const std::string& aFileName);
void drawPixel( u8 x, u8 y, GRAPHICS_ENGINE engine ) {
//if( y > (u8)SCREEN_HEIGHT - 1 ) y = (u8)SCREEN_WIDTH - 1;
if( GE_MAIN == engine )
*(_bufferMain2 + ((u32)y << 8) + x + _layerPitch ) = _penColor; //_bufferMain2[y * SCREEN_WIDTH + x] = _penColor;
else
_bufferSub2[((u32)y << 8) + x] = _penColor; //_bufferSub2[y * SCREEN_WIDTH + x] = _penColor;
}
void drawLine( s16 x1, s16 y1, s16 x2, s16 y2, GRAPHICS_ENGINE engine );
void frameRect( s16 x, s16 y, u16 w, u16 h, GRAPHICS_ENGINE engine );
void frameRect( s16 x, s16 y, u16 w, u16 h, u16 thickness, GRAPHICS_ENGINE engine );
void fillRect( u16 color1, u16 color2, s16 x, s16 y, u16 w, u16 h, GRAPHICS_ENGINE engine );
void fillRectBlend( u16 color1, u16 color2, s16 x, s16 y, u16 w, u16 h, GRAPHICS_ENGINE engine, u16 opacity);
void maskBlt( const void * src, s16 destX, s16 destY, u16 destW, u16 destH, GRAPHICS_ENGINE engine );
void maskBlt( const void * src, s16 srcW, s16 srcH, s16 destX, s16 destY, u16 destW, u16 destH, GRAPHICS_ENGINE engine );
void bitBlt( const void * src, s16 srcW, s16 srcH, s16 destX, s16 destY, u16 destW, u16 destH, GRAPHICS_ENGINE engine );
void bitBlt( const void * src, s16 destX, s16 destY, u16 destW, u16 destH, GRAPHICS_ENGINE engine );
u16 getPenColor( GRAPHICS_ENGINE engine ) {
if( GE_MAIN == engine ) return _penColor & ~BIT(15);
else return _penColorSub & ~BIT(15);
}
void setPenColor( u16 color, GRAPHICS_ENGINE engine ) {
if( GE_MAIN == engine ) _penColor = color | BIT(15);
else _penColorSub = color | BIT(15);
}
void setTransColor( u16 color ) { _transColor = color | BIT(15); }
void textOutRect( s16 x, s16 y, u16 w, u16 h, const char * text, GRAPHICS_ENGINE engine );
inline void textOut( s16 x, s16 y, const char * text, GRAPHICS_ENGINE engine ) {
textOutRect( x, y, 256, 192, text, engine );
}
void setMainEngineLayer( MAIN_ENGINE_LAYER layer ) { _mainEngineLayer = layer; _layerPitch = layer * 256 * 192; }
void present( GRAPHICS_ENGINE engine );
void present( void );
#ifdef DEBUG
void switchSubEngineMode();
#endif
protected:
void swapLCD(void);
void activeFbMain(void); // fb = frame buffer
void activeFbSub(void);
private:
std::vector< u16 > _penColorStack;
u16 _penColor;
u16 _penColorSub;
u16 _transColor;
u16 * _bufferMain1;
u16 * _bufferMain2;
u16 * _bufferMain3;
MAIN_ENGINE_LAYER _mainEngineLayer;
SUB_ENGINE_MODE _subEngineMode;
u32 _layerPitch;
u16 * _bufferSub1;
u16 * _bufferSub2;
#ifdef DEBUG
u16 * _bufferSub3;
#endif
cSprite* _sprites;
cBMP15 _background;
};
typedef t_singleton< cGdi > cGdi_s;
inline cGdi & gdi() { return cGdi_s::instance(); }
#endif//_GDI_H_

View File

@ -0,0 +1,177 @@
/*
globalsettings.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "globalsettings.h"
#include "inifile.h"
#include "systemfilenames.h"
#include "fontfactory.h"
#include <string.h>
#include <sys/stat.h>
cGlobalSettings::cGlobalSettings()
{
fontHeight=12;
#if defined(_STORAGE_r4)
brightness=1;
#endif
language=1;
langDirectory="English";
uiName="zelda";
startupFolder="...";
fileListType=0;
romTrim=0;
showHiddenFiles=false;
enterLastDirWhenBoot=true;
scrollSpeed = EScrollFast;
showGbaRoms=true;
viewMode=EViewInternal;
gbaSleepHack=false;
gbaAutoSave=false;
Animation=true;
cheats=false;
softreset=true;
dma=true;
sdsave=true;
cheatDB=false;
slot2mode=ESlot2Ask;
saveExt=false;
safeMode=false;
show12hrClock=false;
autorunWithLastRom=false;
homebrewreset=false;
}
void cGlobalSettings::loadSettings()
{
std::string temp;
CIniFile ini( SFN_GLOBAL_SETTINGS );
fontHeight = ini.GetInt( "system", "fontHeight", fontHeight );
langDirectory = ini.GetString( "system", "langDirectory", langDirectory );
uiName = ini.GetString( "system", "uiName", uiName );
startupFolder = ini.GetString( "system", "startupFolder", startupFolder );
if('/'!=startupFolder[startupFolder.length()-1]) startupFolder+='/';
fileListType = ini.GetInt( "system", "fileListType", fileListType );
romTrim = ini.GetInt( "system", "romTrim", romTrim );
showHiddenFiles = ini.GetInt( "system", "showHiddenFiles", showHiddenFiles );
enterLastDirWhenBoot = ini.GetInt( "system", "enterLastDirWhenBoot", enterLastDirWhenBoot );
gbaSleepHack=ini.GetInt("system","gbaSleepHack",gbaSleepHack);
gbaAutoSave=ini.GetInt("system","gbaAutoSave",gbaAutoSave);
Animation=ini.GetInt("system","Animation",Animation);
cheats=ini.GetInt("system","cheats",cheats);
softreset=ini.GetInt("system","softreset",softreset);
dma=ini.GetInt("system","dma",dma);
sdsave=ini.GetInt("system","sdsave",sdsave);
safeMode=ini.GetInt("system","safemode",safeMode);
show12hrClock=ini.GetInt("system","Show12hrClock",show12hrClock);
autorunWithLastRom=ini.GetInt("system","autorunWithLastRom",autorunWithLastRom);
homebrewreset=ini.GetInt("system","homebrewreset",homebrewreset);
temp = ini.GetString( "system", "scrollSpeed", "fast" );
scrollSpeed = (temp=="slow")?EScrollSlow:((temp=="medium")?EScrollMedium:EScrollFast);
temp = ini.GetString( "system", "viewMode", "icon" );
viewMode = (temp=="list")?EViewList:((temp=="icon")?EViewIcon:EViewInternal);
temp = ini.GetString( "system", "slot2mode", "ask" );
slot2mode = (temp=="gba")?ESlot2Gba:((temp=="nds")?ESlot2Nds:ESlot2Ask);
temp = ini.GetString( "system", "saveext", ".nds.sav" );
saveExt = (temp==".sav");
struct stat st;
if(0==stat(SFN_CHEATS,&st)) cheatDB=true;
#if defined(_STORAGE_r4)
CIniFile iniBacklight(SFN_BACKLIGHT);
brightness=iniBacklight.GetInt("brightness","brightness",brightness);
setBrightness(brightness);
#endif
updateSafeMode();
}
void cGlobalSettings::saveSettings()
{
// the commented code means those parameters are not allow to change in menu
CIniFile ini( SFN_GLOBAL_SETTINGS );
//ini.SetInt( "system", "fontHeight", fontHeight );
ini.SetString( "system", "uiName", uiName );
ini.SetString( "system", "langDirectory", langDirectory );
ini.SetInt( "system", "fileListType", fileListType );
ini.SetInt( "system", "romTrim", romTrim );
ini.SetInt( "system", "showHiddenFiles", showHiddenFiles );
ini.SetInt("system","gbaSleepHack",gbaSleepHack);
ini.SetInt("system","gbaAutoSave",gbaAutoSave);
ini.SetInt("system","Animation",Animation);
ini.SetInt("system","cheats",cheats);
ini.SetInt("system","softreset",softreset);
ini.SetInt("system","dma",dma);
ini.SetInt("system","sdsave",sdsave);
ini.SetInt("system","safemode",safeMode);
ini.SetInt("system","Show12hrClock",show12hrClock);
ini.SetInt("system","homebrewreset",homebrewreset);
ini.SetString( "system", "scrollSpeed", (scrollSpeed==EScrollSlow)?"slow":((scrollSpeed==EScrollMedium)?"medium":"fast") );
ini.SetString( "system", "viewMode", (viewMode==EViewList)?"list":((viewMode==EViewIcon)?"icon":"internal") );
ini.SetString( "system", "slot2mode", (slot2mode==ESlot2Gba)?"gba":((slot2mode==ESlot2Nds)?"nds":"ask") );
ini.SetString( "system", "saveext", saveExt?".sav":".nds.sav" );
ini.SaveIniFile( SFN_GLOBAL_SETTINGS );
updateSafeMode();
}
void cGlobalSettings::updateSafeMode(void)
{
if(safeMode)
{
fileListType=0;
showHiddenFiles=false;
viewMode=EViewInternal;
}
}
u32 cGlobalSettings::CopyBufferSize(void)
{
if(font().FontRAM()<300*1024) return 1024*1024;
return 512*1024;
}
void cGlobalSettings::nextBrightness(void)
{
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
fifoSendValue32(FIFO_USER_01,MENU_MSG_BRIGHTNESS_NEXT);
#elif defined(_STORAGE_r4)
fifoSendValue32(FIFO_USER_01,MENU_MSG_BRIGHTNESS_GET);
while(!fifoCheckValue32(FIFO_USER_01));
u32 currentLevel=fifoGetValue32(FIFO_USER_01);
brightness=(currentLevel+1)&3;
setBrightness(brightness);
CIniFile ini(SFN_BACKLIGHT);
ini.SetInt("brightness","brightness",brightness);
ini.SaveIniFile(SFN_BACKLIGHT);
#endif
}
#if defined(_STORAGE_r4)
void cGlobalSettings::setBrightness(u32 level)
{
fifoSendValue32(FIFO_USER_01,MENU_MSG_BRIGHTNESS_SET0+(brightness&3));
}
#endif

View File

@ -0,0 +1,102 @@
/*
globalsettings.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _GLOBALSETTINGS_H_
#define _GLOBALSETTINGS_H_
#include <nds.h>
#include <string>
#include "singleton.h"
#include "../../share/fifotool.h"
class cGlobalSettings
{
public:
enum TScrollSpeed
{
EScrollFast=4,
EScrollMedium=10,
EScrollSlow=16
};
enum TViewMode
{
EViewList=0,
EViewIcon=1,
EViewInternal=2
};
enum TSlot2Mode
{
ESlot2Ask=0,
ESlot2Gba=1,
ESlot2Nds=2
};
public:
cGlobalSettings();
~cGlobalSettings();
public:
void loadSettings();
void saveSettings();
void updateSafeMode(void);
static u32 CopyBufferSize(void);
void nextBrightness(void);
#if defined(_STORAGE_r4)
void setBrightness(u32 level);
#endif
public:
u8 fontHeight;
#if defined(_STORAGE_r4)
u8 brightness;
#endif
u8 language;
u8 fileListType;
u8 romTrim;
std::string langDirectory;
std::string uiName;
std::string startupFolder;
bool showHiddenFiles;
bool enterLastDirWhenBoot;
int scrollSpeed;
bool showGbaRoms;
int viewMode;
bool gbaSleepHack;
bool gbaAutoSave;
bool Animation;
bool cheats;
bool softreset;
bool dma;
bool sdsave;
bool cheatDB;
int slot2mode;
bool saveExt;
bool safeMode;
bool show12hrClock;
bool autorunWithLastRom;
bool homebrewreset;
};
typedef t_singleton< cGlobalSettings > globalSettings_s;
inline cGlobalSettings & gs() { return globalSettings_s::instance(); }
#endif//_GLOBALSETTINGS_H_

133
arm9/source/helpwnd.cpp Normal file
View File

@ -0,0 +1,133 @@
/*
helpwnd.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "iocmn.h"
#include "helpwnd.h"
#include "msgbox.h"
#include "windowmanager.h"
#include "uisettings.h"
#include "language.h"
#include "version.h"
#include "fontfactory.h"
using namespace akui;
cHelpWnd::cHelpWnd( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text )
: cForm( x, y, w, h, parent, text ),
_buttonOK(0,0,46,18,this,"\x01 OK")
{
s16 buttonY = size().y - _buttonOK.size().y - 4;
_buttonOK.setStyle( cButton::press );
_buttonOK.setText( "\x01 " + LANG( "setting window", "ok" ) );
_buttonOK.setTextColor( uis().buttonTextColor );
_buttonOK.loadAppearance( SFN_BUTTON3 );
_buttonOK.clicked.connect( this, &cHelpWnd::onOK );
addChildWindow( &_buttonOK );
s16 nextButtonX = size().x;
s16 buttonPitch = _buttonOK.size().x + 8;
buttonPitch = _buttonOK.size().x + 8;
nextButtonX -= buttonPitch;
_buttonOK.setRelativePosition( cPoint(nextButtonX, buttonY) );
loadAppearance( "" );
arrangeChildren();
for( size_t i = 0; i < 9; ++i ) {
std::string textIndex = formatString( "item%d", i );
_helpText += LANG( "help window", textIndex );
_helpText += "\n";
}
_helpText = formatString( _helpText.c_str(), 7,1,2,4,3,5,6, "START", "SELECT" );
//u8 nandDriverVer = getNandDriverVer();
_helpText += '\n';
_helpText += formatString( "wood akmenu %s.%s ", AKMENU_VRESION_MAIN, AKMENU_VRESION_SUB );
_helpText += formatString( "HW: %02x", ioVersion() );
_helpText += formatString( "\nfont: %dk size: %x", font().FontRAM()/1024, ioSize() );
}
cHelpWnd::~cHelpWnd()
{}
void cHelpWnd::draw()
{
_renderDesc.draw( windowRectangle(), _engine );
gdi().setPenColor( uiSettings().formTextColor,_engine );
gdi().textOutRect( position().x + 8, position().y + 17 + uiSettings().thickness , size().x - 8, size().y - 20 - 2*uiSettings().thickness, _helpText.c_str(), _engine );
cForm::draw();
}
bool cHelpWnd::process( const akui::cMessage & msg )
{
bool ret = false;
ret = cForm::process( msg );
if( !ret ) {
if( msg.id() > cMessage::keyMessageStart && msg.id()
< cMessage::keyMessageEnd )
{
ret = processKeyMessage( (cKeyMessage &)msg );
}
}
return ret;
}
bool cHelpWnd::processKeyMessage( const cKeyMessage & msg )
{
bool ret = false;
if( msg.id() == cMessage::keyDown )
{
switch( msg.keyCode() )
{
case cKeyMessage::UI_KEY_A:
case cKeyMessage::UI_KEY_B:
onOK();
ret = true;
break;
default:
{}
};
}
return ret;
}
cWindow& cHelpWnd::loadAppearance(const std::string& aFileName )
{
_renderDesc.loadData( SFN_FORM_TITLE_L, SFN_FORM_TITLE_R, SFN_FORM_TITLE_M );
_renderDesc.setTitleText( _text );
return *this;
}
void cHelpWnd::onOK()
{
cForm::onOK();
}
void cHelpWnd::onShow()
{
centerScreen();
}

65
arm9/source/helpwnd.h Normal file
View File

@ -0,0 +1,65 @@
/*
helpwnd.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _HELPWND_H_
#define _HELPWND_H_
#include "form.h"
#include "formdesc.h"
#include "spinbox.h"
#include "statictext.h"
#include "message.h"
#include <string>
#include "dsrom.h"
class cHelpWnd : public akui::cForm
{
public:
cHelpWnd( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text );
~cHelpWnd();
public:
void draw();
bool process( const akui::cMessage & msg );
cWindow& loadAppearance(const std::string& aFileName );
protected:
bool processKeyMessage( const akui::cKeyMessage & msg );
void onOK();
void onShow();
akui::cButton _buttonOK;
akui::cFormDesc _renderDesc;
std::string _helpText;
};
#endif//_HELPWND_H_

39
arm9/source/icons.cpp Normal file
View File

@ -0,0 +1,39 @@
/*
icons.cpp
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "icons.h"
void cIcons::maskBlt(const u16* aSrc,u16* aDst)
{
for(u32 ii=0;ii<32;++ii)
{
for(u32 jj=0;jj<16;++jj)
{
if(((*(u32*)aSrc)&0x80008000)==0x80008000)
{
*(u32*)aDst=*(u32*)aSrc;
}
else
{
if(aSrc[0]&0x8000) aDst[0]=aSrc[0];
if(aSrc[1]&0x8000) aDst[1]=aSrc[1];
}
aSrc+=2;aDst+=2;
}
}
}

30
arm9/source/icons.h Normal file
View File

@ -0,0 +1,30 @@
/*
icons.h
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ICONS_H__
#define __ICONS_H__
#include <nds.h>
class cIcons
{
public:
static void maskBlt(const u16* aSrc,u16* aDst);
};
#endif

396
arm9/source/inifile.cpp Normal file
View File

@ -0,0 +1,396 @@
/*
inifile.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <cstdio>
#include <cstdlib>
#include "inifile.h"
#include "../../share/stringtool.h"
#include "dbgtool.h"
#include <elm.h>
static bool freadLine(FILE* f,std::string& str)
{
str.clear();
__read:
char p=0;
size_t readed=fread(&p,1,1,f);
if(0==readed)
{
str="";
return false;
}
if('\n'==p||'\r'==p)
{
str="";
return true;
}
while(p!='\n'&&p!='\r'&&readed)
{
str+=p;
readed=fread(&p,1,1,f);
}
if(str.empty()||""==str)
{
goto __read;
}
return true;
}
static void trimString(std::string& str)
{
size_t first=str.find_first_not_of(" \t"),last;
if(first==str.npos)
{
str="";
}
else
{
last=str.find_last_not_of(" \t");
if(first>0||(last+1)<str.length()) str=str.substr(first,last-first+1);
}
}
CIniFile::CIniFile()
{
m_bLastResult=false;
m_bModified=false;
m_bReadOnly=false;
}
CIniFile::CIniFile(const std::string& filename)
{
m_sFileName=filename;
m_bLastResult=false;
m_bModified=false;
m_bReadOnly=false;
LoadIniFile(m_sFileName);
}
CIniFile::~CIniFile()
{
if(m_FileContainer.size()>0)
{
m_FileContainer.clear();
}
}
void CIniFile::SetString(const std::string& Section,const std::string& Item,const std::string& Value)
{
if(GetFileString(Section,Item)!=Value)
{
SetFileString(Section,Item,Value);
m_bModified=true;
}
}
void CIniFile::SetInt(const std::string& Section,const std::string& Item,int Value)
{
std::string strtemp=formatString("%d",Value);
if(GetFileString(Section,Item)!=strtemp)
{
SetFileString(Section,Item,strtemp);
m_bModified=true;
}
}
std::string CIniFile::GetString(const std::string& Section,const std::string& Item)
{
return GetFileString(Section,Item);
}
std::string CIniFile::GetString(const std::string& Section,const std::string& Item,const std::string& DefaultValue)
{
std::string temp=GetString(Section,Item);
if(!m_bLastResult)
{
SetString(Section,Item,DefaultValue);
temp=DefaultValue;
}
return temp;
}
void CIniFile::GetStringVector(const std::string& Section,const std::string& Item,std::vector< std::string >& strings,char delimiter)
{
std::string strValue=GetFileString(Section,Item);
strings.clear();
size_t pos;
while((pos=strValue.find(delimiter),strValue.npos!=pos))
{
const std::string string=strValue.substr(0,pos);
if(string.length())
{
strings.push_back(string);
}
strValue=strValue.substr(pos+1,strValue.npos);
}
if(strValue.length())
{
strings.push_back(strValue);
}
}
void CIniFile::SetStringVector(const std::string& Section,const std::string& Item,std::vector<std::string>& strings,char delimiter)
{
std::string strValue;
for(size_t ii=0;ii<strings.size();++ii)
{
if(ii) strValue+=delimiter;
strValue+=strings[ii];
}
SetString(Section,Item,strValue);
}
int CIniFile::GetInt(const std::string& Section,const std::string& Item)
{
std::string value=GetFileString(Section,Item);
if(value.size()>2&&'0'==value[0]&&('x'==value[1]||'X'==value[1]))
return strtol(value.c_str(),NULL,16);
else
return strtol(value.c_str(),NULL,10);
}
int CIniFile::GetInt(const std::string& Section,const std::string& Item,int DefaultValue)
{
int temp;
temp=GetInt(Section,Item);
if(!m_bLastResult)
{
SetInt(Section,Item,DefaultValue);
temp=DefaultValue;
}
return temp;
}
bool CIniFile::LoadIniFile(const std::string& FileName)
{
dbg_printf("load %s\n",FileName.c_str());
if(FileName!="") m_sFileName=FileName;
FILE* f=fopen(FileName.c_str(),"rb");
if(NULL==f) return false;
//check for utf8 bom.
char bom[3];
if(fread(bom,3,1,f)==1&&bom[0]==0xef&&bom[1]==0xbb&&bom[2]==0xbf) ;
else fseek(f,0,SEEK_SET);
std::string strline("");
m_FileContainer.clear();
while(freadLine(f,strline))
{
trimString(strline);
if(strline!=""&&';'!=strline[0]&&'/'!=strline[0]&&'!'!=strline[0]) m_FileContainer.push_back(strline);
}
fclose(f);
m_bLastResult=false;
m_bModified=false;
return true;
}
bool CIniFile::SaveIniFileModified(const std::string& FileName)
{
if(m_bModified==true)
{
return SaveIniFile(FileName);
}
return true;
}
bool CIniFile::SaveIniFile(const std::string& FileName)
{
if(FileName!="")
m_sFileName=FileName;
NandFast();
FILE* f=fopen(m_sFileName.c_str(),"wb");
if(NULL==f)
{
NandFlush();
return false;
}
for(size_t ii=0;ii<m_FileContainer.size();ii++)
{
std::string& strline=m_FileContainer[ii];
size_t notSpace=strline.find_first_not_of(' ');
strline=strline.substr(notSpace);
if(strline.find('[')==0&&ii>0)
{
if(!m_FileContainer[ii-1].empty()&&m_FileContainer[ii-1]!="")
fwrite("\r\n",1,2,f);
}
if(!strline.empty()&&strline!="")
{
fwrite(strline.c_str(),1,strline.length(),f);
fwrite("\r\n",1,2,f);
}
}
fclose(f);
NandFlush();
m_bModified=false;
return true;
}
std::string CIniFile::GetFileString(const std::string& Section,const std::string& Item)
{
std::string strline;
std::string strSection;
std::string strItem;
std::string strValue;
size_t ii=0;
size_t iFileLines=m_FileContainer.size();
if(m_bReadOnly)
{
cSectionCache::iterator it=m_Cache.find(Section);
if((it!=m_Cache.end())) ii=it->second;
}
m_bLastResult=false;
if(iFileLines>=0)
{
while(ii<iFileLines)
{
strline=m_FileContainer[ii++];
size_t rBracketPos=0;
if('['==strline[0]) rBracketPos=strline.find(']');
if(rBracketPos>0&&rBracketPos!=std::string::npos)
{
strSection=strline.substr(1,rBracketPos-1);
if(m_bReadOnly) m_Cache.insert(std::make_pair(strSection,ii-1));
if(strSection==Section)
{
while(ii<iFileLines)
{
strline=m_FileContainer[ii++];
size_t equalsignPos=strline.find('=');
if(equalsignPos!=strline.npos)
{
size_t last=equalsignPos?strline.find_last_not_of(" \t",equalsignPos-1):strline.npos;
if(last==strline.npos) strItem="";
else strItem=strline.substr(0,last+1);
if(strItem==Item)
{
size_t first=strline.find_first_not_of(" \t",equalsignPos+1);
if(first==strline.npos) strValue="";
else strValue=strline.substr(first);
m_bLastResult=true;
return strValue;
}
}
else if('['==strline[0])
{
break;
}
}
break;
}
}
}
}
return std::string("");
}
void CIniFile::SetFileString(const std::string& Section,const std::string& Item,const std::string& Value)
{
std::string strline;
std::string strSection;
std::string strItem;
if(m_bReadOnly) return;
size_t ii=0;
size_t iFileLines=m_FileContainer.size();
while(ii<iFileLines)
{
strline=m_FileContainer[ii++];
size_t rBracketPos=0;
if('['==strline[0]) rBracketPos=strline.find(']');
if(rBracketPos>0&&rBracketPos!=std::string::npos)
{
strSection=strline.substr(1,rBracketPos-1);
if(strSection==Section)
{
while(ii<iFileLines)
{
strline=m_FileContainer[ii++];
size_t equalsignPos=strline.find('=');
if(equalsignPos!=strline.npos)
{
size_t last=equalsignPos?strline.find_last_not_of(" \t",equalsignPos-1):strline.npos;
if(last==strline.npos) strItem="";
else strItem=strline.substr(0,last+1);
if(Item==strItem)
{
ReplaceLine(ii-1,Item+" = "+Value);
return;
}
}
else if('['==strline[0])
{
InsertLine(ii-1,Item+" = "+Value);
return;
}
}
InsertLine(ii,Item+" = "+Value);
return;
}
}
}
InsertLine(ii,"["+Section+"]");
InsertLine(ii+1,Item+" = "+Value);
return;
}
bool CIniFile::InsertLine(size_t line,const std::string& str)
{
m_FileContainer.insert(m_FileContainer.begin()+line,str);
return true;
}
bool CIniFile::ReplaceLine(size_t line,const std::string& str)
{
m_FileContainer[line]=str;
return true;
}

66
arm9/source/inifile.h Normal file
View File

@ -0,0 +1,66 @@
/*
inifile.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009-2010 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _INIFILE_H_
#define _INIFILE_H_
#include <string>
#include <vector>
#include <map>
class CIniFile
{
public:
CIniFile();
CIniFile(const std::string& filename);
virtual ~CIniFile();
public:
bool LoadIniFile(const std::string& FileName);
bool SaveIniFile(const std::string& FileName);
bool SaveIniFileModified(const std::string& FileName);
std::string GetString(const std::string& Section,const std::string& Item,const std::string& DefaultValue);
void SetString(const std::string& Section,const std::string& Item,const std::string& Value);
int GetInt(const std::string& Section,const std::string& Item,int DefaultValue);
void SetInt(const std::string& Section,const std::string& Item,int Value);
void GetStringVector(const std::string& Section,const std::string& Item,std::vector<std::string>& strings,char delimiter=',');
void SetStringVector(const std::string& Section,const std::string& Item,std::vector<std::string>& strings,char delimiter=',');
protected:
std::string m_sFileName;
typedef std::vector<std::string> cStringArray;
cStringArray m_FileContainer;
bool m_bLastResult;
bool m_bModified;
bool m_bReadOnly;
typedef std::map<std::string,size_t> cSectionCache;
cSectionCache m_Cache;
bool InsertLine(size_t line,const std::string& str);
bool ReplaceLine(size_t line,const std::string& str);
void SetFileString(const std::string& Section,const std::string& Item,const std::string& Value);
std::string GetFileString(const std::string& Section,const std::string& Item);
std::string GetString(const std::string& Section,const std::string& Item);
int GetInt(const std::string& Section,const std::string& Item);
};
#endif // _INIFILE_H_

32
arm9/source/iocmn.h Normal file
View File

@ -0,0 +1,32 @@
/*
iocmn.h
Copyright (C) 2010 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __IOCMN_H__
#define __IOCMN_H__
#if defined(_STORAGE_rpg)
#include <iorpg.h>
#elif defined(_STORAGE_r4)
#include <ior4.h>
#elif defined(_STORAGE_ak2i)
#include <ioak2i.h>
#elif defined(_STORAGE_r4idsn)
#include <ior4idsn.h>
#endif
#endif

105
arm9/source/irqs.cpp Normal file
View File

@ -0,0 +1,105 @@
/*
irqs.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "irqs.h"
#include "dbgtool.h"
#include "userinput.h"
#include "windowmanager.h"
#include "diskicon.h"
#include "calendarwnd.h"
#include "calendar.h"
#include "bigclock.h"
#include "timer.h"
#include "animation.h"
#include "files.h"
#include "userwnd.h"
using namespace akui;
bool cIRQ::_vblankStarted(false);
void cIRQ::init()
{
irqSet( IRQ_VBLANK, vBlank );
irqSet( IRQ_CARD_LINE, cardMC );
}
void cIRQ::cardMC()
{
dbg_printf("cardMC\n");
diskIcon().blink();
REG_IF &= ~IRQ_CARD_LINE;
}
void cIRQ::vblankStart()
{
_vblankStarted = true;
}
void cIRQ::vblankStop()
{
_vblankStarted = false;
}
void cIRQ::vBlank()
{
if( !_vblankStarted )
return;
// get inputs when file copying because the main route
// can't do any thing at that time
if( true == copyingFile) {
if( false == stopCopying ) {
INPUT & input = updateInput();
if( (input.keysDown & KEY_B) ) {
stopCopying = true;
}
}
}
timer().updateTimer();
static u32 vBlankCounter = 0;
if( vBlankCounter++ > 30 ) {
vBlankCounter = 0;
bigClock().blinkColon();
calendarWnd().draw();
calendar().draw();
bigClock().draw();
userWindow().draw();
#if 0
char fpsText[16];
sprintf( fpsText, "fps %.2f\n", timer().getFps() );
gdi().setPenColor( 1, GE_SUB );
gdi().textOut( 40, 178, fpsText, GE_SUB );
#endif
gdi().present( GE_SUB );
}
animationManager().update();
if( REG_ROMCTRL & CARD_BUSY )
diskIcon().turnOn();
else
diskIcon().turnOff();
}

57
arm9/source/irqs.h Normal file
View File

@ -0,0 +1,57 @@
/*
irqs.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _IRQS_H_
#define _IRQS_H_
#include <nds.h>
#include "singleton.h"
class cIRQ
{
public:
cIRQ() {}
~cIRQ() {}
public:
void init();
void vblankStart();
void vblankStop();
static void cardMC();
static void vBlank();
static bool _vblankStarted;
};
typedef t_singleton< cIRQ > irq_s;
inline cIRQ & irq() { return irq_s::instance(); }
#endif//_IRQS_H_

26
arm9/source/language.cpp Normal file
View File

@ -0,0 +1,26 @@
/*
language.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "language.h"
bool stringComp(const std::string& item1,const std::string& item2)
{
return strcasecmp(item1.c_str(),item2.c_str())<0;
}

50
arm9/source/language.h Normal file
View File

@ -0,0 +1,50 @@
/*
language.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _LANGUAGE_H_
#define _LANGUAGE_H_
#include "inifile.h"
#include "singleton.h"
#include "systemfilenames.h"
#include "globalsettings.h"
#include "stringtool.h"
#include "dbgtool.h"
#include "timetool.h"
class cLanguageFile : public CIniFile
{
public:
cLanguageFile()
{
m_bReadOnly=true;
LoadIniFile(SFN_LANGUAGE_TEXT);
}
~cLanguageFile() {};
};
typedef t_singleton<cLanguageFile> languageFile_s;
inline cLanguageFile& lang() {return languageFile_s::instance();}
#define LANG(i,t) lang().GetString(i,t,t)
bool stringComp(const std::string& item1,const std::string& item2);
#endif//_LANGUAGE_H_

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

@ -0,0 +1,266 @@
/*
main.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <nds.h>
#include <cstdio>
#include <vector>
#include <map>
#include <list>
#include <elm.h>
#include "dbgtool.h"
#include "gdi.h"
#include "ui.h"
#include "systemfilenames.h"
#include "mainlist.h"
#include "startmenu.h"
#include "mainwnd.h"
#include "timer.h"
#include "datetime.h"
#include "calendarwnd.h"
#include "bigclock.h"
#include "calendar.h"
#include "inifile.h"
#include "irqs.h"
#include "diskicon.h"
#include "progresswnd.h"
#include "language.h"
#include "fontfactory.h"
#include "userwnd.h"
#include "sram.h"
#include "exptools.h"
#include "romlauncher.h"
using namespace akui;
#ifdef __cplusplus
extern "C" {
#endif
void __libnds_exit(int rc) {}
#ifdef __cplusplus
}
#endif
int main(void)
{
irq().init();
windowManager();
// init basic system
sysSetBusOwners( BUS_OWNER_ARM9, BUS_OWNER_ARM9 );
// init tick timer/fps counter
timer().initTimer();
// init inputs
initInput();
//turn led on
ledBlink(PM_LED_ON);
// init graphics
gdi().init();
#ifdef DEBUG
gdi().switchSubEngineMode();
#endif//DEBUG
dbg_printf( "gdi ok\n" );
//wait_press_b();
// init fat
//bool succ = fatInitDefault();
bool succ = (ELM_Mount()&1)?false:true;
if( !succ )
dbg_printf( "init fat %d\n", succ );
//wait_press_b();
// setting scripts
gs().loadSettings();
// init unicode
//if( initUnicode() )
// _FAT_unicode_init( unicodeL2UTable, unicodeU2LTable, unicodeAnkTable );
cwl();
lang(); // load language file
gs().language=lang().GetInt("font","language",gs().language);
fontFactory().makeFont(); // load font file
uiSettings().loadSettings();
bool saveListOK = saveManager().importSaveList( SFN_CUSTOM_SAVELIST, SFN_OFFICIAL_SAVELIST );
if( !saveListOK ) {
//messageBox( NULL,
// LANG("no savelist","title"),
// LANG("no savelist", "text"), MB_OK );
dbg_printf("WARNING: savelist.bin missed\n");
}
gdi().initBg(SFN_LOWER_SCREEN_BG);
cMainWnd * wnd = new cMainWnd( 0, 0, 256, 192, NULL, "main window" );
wnd->init();
progressWnd().init();
diskIcon().loadAppearance( SFN_CARD_ICON_BLUE );
diskIcon().show();
windowManager().update();
timer().updateFps();
calendarWnd().init();
calendarWnd().draw();
calendar().init();
calendar().draw();
bigClock().init();
bigClock().draw();
userWindow().draw();
gdi().present( GE_MAIN );
gdi().present( GE_SUB );
dbg_printf( "loop start\n" );
irq().vblankStart();
// enter last directory
std::string lastDirectory="...",lastFile="...";
if(gs().enterLastDirWhenBoot||gs().autorunWithLastRom)
{
CIniFile f;
if(f.LoadIniFile(SFN_LAST_SAVEINFO))
{
lastFile=f.GetString("Save Info","lastLoaded","");
if(""==lastFile)
{
lastFile="...";
}
else if(gs().enterLastDirWhenBoot)
{
size_t slashPos=lastFile.find_last_of('/');
if(lastFile.npos!=slashPos) lastDirectory=lastFile.substr(0,slashPos+1);
}
}
}
{ //backup save data from chip to flash. pressing LShift+Up aborts backup.
#if defined(_STORAGE_rpg)
INPUT & inputs = updateInput();
if((inputs.keysHeld&(KEY_UP|KEY_L))==(KEY_UP|KEY_L))
{
u32 ret = messageBox( NULL, LANG("abort save", "title"), LANG("abort save", "text"), MB_YES | MB_NO );
if(ret==ID_YES)
{
saveManager().clearLastInfo();
saveManager().clearSaveBlocks();
}
else saveManager().backupSaveData();
}
else
{
saveManager().backupSaveData();
}
#elif defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
saveManager().clearLastInfo();
#endif
//backup gba sram save date to flash.
if(gs().gbaAutoSave&&expansion().IsValid())
{
CIniFile f;
if(f.LoadIniFile(SFN_LAST_GBA_SAVEINFO))
{
std::string psramFile=f.GetString("Save Info","lastLoaded","");
if(psramFile!="")
{
cSram::SaveSramToFile(psramFile.c_str(),cExpansion::EPsramPage);
f.SetString("Save Info","lastLoaded","");
f.SaveIniFile(SFN_LAST_GBA_SAVEINFO);
}
std::string norFile=f.GetString("Save Info","lastLoadedNOR","");
if(norFile!="")
{
std::string norFileSave=norFile+".sav";
FILE* saveFile=fopen(norFileSave.c_str(),"rb");
if(saveFile)
{
cSram::sSaveInfo saveInfo;
cSram::ProcessRAW(saveFile,saveInfo);
u8* bufFile=(u8*)malloc(saveInfo.size);
if(bufFile)
{
memset(bufFile,0,saveInfo.size);
fread(bufFile,saveInfo.size,1,saveFile);
u8* bufData=cSram::SaveSramToMemory(cExpansion::ENorPage,saveInfo,false);
if(bufData)
{
if(memcmp(bufFile,bufData,saveInfo.size)!=0)
{
cSram::SaveSramToFile(norFile.c_str(),cExpansion::ENorPage);
}
free(bufData);
}
free(bufFile);
}
fclose(saveFile);
}
}
}
}
}
if(gs().autorunWithLastRom&&"..."!=lastFile)
{
INPUT & inputs = updateInput();
if(!(inputs.keysHeld&KEY_B)) autoLaunchRom(lastFile);
}
dbg_printf("lastDirectory '%s'\n", lastDirectory.c_str() );
if(!wnd->_mainList->enterDir("..."!=lastDirectory?lastDirectory:gs().startupFolder)) wnd->_mainList->enterDir("...");
if(*(u32*)0x04000604) fifoSendValue32(FIFO_USER_01,MENU_MSG_SHUTDOWN);
while( true )
{
timer().updateFps();
INPUT & inputs = updateInput();
processInput( inputs );
//swiWaitForVBlank();
windowManager().update();
gdi().present( GE_MAIN );
}
return 0;
}

575
arm9/source/mainlist.cpp Normal file
View File

@ -0,0 +1,575 @@
/*
mainlist.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
//<2F>
#include <sys/dir.h>
#include <elm.h>
#define ATTRIB_HID 0x02
#include "mainlist.h"
#include "files.h"
#include "dbgtool.h"
#include "startmenu.h"
#include "systemfilenames.h"
#include "romloader.h"
#include "windowmanager.h"
#include "../../share/timetool.h"
#include "../../share/memtool.h"
#include "inifile.h"
#include "unknown_banner_bin.h"
#include "nds_save_banner_bin.h"
#include "nand_banner_bin.h"
#include "microsd_banner_bin.h"
#include "gba_banner_bin.h"
#include "folder_banner_bin.h"
#include "progresswnd.h"
#include "language.h"
#include "unicode.h"
using namespace akui;
cMainList::cMainList( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text )
: cListView( x, y, w, h, parent, text ),_showAllFiles(false),
#if defined(_STORAGE_rpg)
_topCount(4),_topuSD(1),_topSlot2(2),_topFavorites(3)
#elif defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
_topCount(3),_topuSD(0),_topSlot2(1),_topFavorites(2)
#endif
{
_viewMode = VM_LIST;
_activeIconScale = 1;
_activeIcon.hide();
_activeIcon.update();
animationManager().addAnimation( &_activeIcon );
dbg_printf("_activeIcon.init\n");
#if defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
fifoSendValue32(FIFO_USER_01,MENU_MSG_SYSTEM);
while(!fifoCheckValue32(FIFO_USER_02));
u32 system=fifoGetValue32(FIFO_USER_02);
if(2==system) //dsi
{
_topCount=2;
_topSlot2=2;
_topFavorites=1;
}
#endif
}
cMainList::~cMainList()
{}
int cMainList::init()
{
CIniFile ini(SFN_UI_SETTINGS);
_textColor=ini.GetInt("main list","textColor",RGB15(7,7,7));
_textColorHilight=ini.GetInt("main list","textColorHilight",RGB15(31,0,31));
_selectionBarColor1=ini.GetInt("main list","selectionBarColor1",RGB15(16,20,24));
_selectionBarColor2=ini.GetInt("main list","selectionBarColor2",RGB15(20,25,0));
_selectionBarOpacity=ini.GetInt("main list","selectionBarOpacity",100);
//selectedRowClicked.connect(this,&cMainList::executeSelected);
insertColumn(ICON_COLUMN,"icon",0);
insertColumn(SHOWNAME_COLUMN,"showName",0);
insertColumn(INTERNALNAME_COLUMN,"internalName",0);
insertColumn(REALNAME_COLUMN,"realName",0); // hidden column for contain real filename
insertColumn(SAVETYPE_COLUMN,"saveType",0);
insertColumn(FILESIZE_COLUMN,"fileSize",0);
setViewMode((cMainList::VIEW_MODE)gs().viewMode);
_activeIcon.hide();
return 1;
}
static bool itemSortComp( const cListView::itemVector & item1, const cListView::itemVector & item2 ) {
const std::string & fn1 = item1[cMainList::SHOWNAME_COLUMN].text();
const std::string & fn2 = item2[cMainList::SHOWNAME_COLUMN].text();
if( "../" == fn1 )
return true;
if( "../" == fn2 )
return false;
if( '/' == fn1[fn1.size()-1] && '/' == fn2[fn2.size()-1] )
return fn1 < fn2;
if( '/' == fn1[fn1.size()-1] )
return true;
if( '/' == fn2[fn2.size()-1] )
return false;
return fn1 < fn2;
}
static bool extnameFilter( const std::vector<std::string> & extNames, std::string extName )
{
if( 0 == extNames.size() )
return true;
for( size_t i = 0; i < extName.size(); ++i )
extName[i] = tolower( extName[i] );
for( size_t i = 0; i < extNames.size(); ++i ) {
if( extName == extNames[i] ) {
return true;
}
}
return false;
}
bool cMainList::enterDir( const std::string & dirName )
{
_saves.clear();
if( "..." == dirName ) // select RPG or SD card
{
removeAllRows();
_romInfoList.clear();
for( size_t i = 0; i < _topCount; ++i ) {
std::vector< std::string > a_row;
a_row.push_back( "" ); // make a space for icon
DSRomInfo rominfo;
#if defined(_STORAGE_rpg)
if( 0 == i ) {
a_row.push_back( LANG("mainlist","flash memory") );
a_row.push_back( "" );
a_row.push_back( "fat0:/" );
rominfo.setBanner("nand",nand_banner_bin);
}
else
#endif
if( _topuSD == i ) {
a_row.push_back( LANG("mainlist","microsd card") );
a_row.push_back( "" );
a_row.push_back( SD_ROOT );
rominfo.setBanner("usd",microsd_banner_bin);
} else if( _topSlot2 == i ) {
a_row.push_back( LANG("mainlist","slot2 card") );
a_row.push_back( "" );
a_row.push_back( "slot2:/" );
rominfo.setBanner("slot2",gba_banner_bin);
} else if( _topFavorites == i ) {
a_row.push_back( LANG("mainlist","favorites") );
a_row.push_back( "" );
a_row.push_back( "favorites:/" );
rominfo.setBanner("folder",folder_banner_bin);
}
insertRow( i, a_row );
_romInfoList.push_back( rominfo );
}
_currentDir = "";
directoryChanged();
return true;
}
if( "slot2:/" == dirName ) {
_currentDir = "";
directoryChanged();
return true;
}
bool favorites=("favorites:/"==dirName);
DIR_ITER* dir=NULL;
if(!favorites)
{
dir = diropen( dirName.c_str() );
if (dir == NULL) {
if( SD_ROOT == dirName ) {
std::string title = LANG( "sd card error", "title" );
std::string sdError = LANG( "sd card error", "text" );
messageBox( NULL, title, sdError, MB_OK );
}
dbg_printf ("Unable to open directory<%s>.\n", dirName.c_str() );
return false;
}
}
removeAllRows();
_romInfoList.clear();
std::vector< std::string > extNames;
extNames.push_back( ".nds" );
extNames.push_back( ".ids" );
if( gs().showGbaRoms > 0 )
extNames.push_back( ".gba" );
if( gs().fileListType > 0 )
extNames.push_back( ".sav" );
if( _showAllFiles || gs().fileListType > 1 )
extNames.clear();
std::vector< std::string > savNames;
savNames.push_back( ".sav" );
// insert 一堆文件, 两列,一列作为显示,一列作为真实文件名
struct stat st;
char longFilename[MAX_FILENAME_LENGTH];
std::string extName;
u8 attr=0;
// list dir
{
cwl();
if(favorites)
{
CIniFile ini(SFN_FAVORITES);
std::vector<std::string> items;
ini.GetStringVector("main","list",items,'|');
for(size_t ii=0;ii<items.size();++ii)
{
u32 row_count=getRowCount();
std::vector<std::string> a_row;
a_row.push_back(""); // make a space for icon
size_t pos=items[ii].rfind('/',items[ii].length()-2);
if(pos==items[ii].npos)
{
a_row.push_back(items[ii]); //show name
}
else
{
a_row.push_back(items[ii].substr(pos+1,items[ii].npos)); //show name
}
a_row.push_back(""); // make a space for internal name
a_row.push_back(items[ii]); //real name
size_t insertPos(row_count);
insertRow(insertPos,a_row);
DSRomInfo rominfo;
_romInfoList.push_back(rominfo);
}
}
else if(dir)
{
while(dirnext(dir,longFilename,&st)==0)
{
attr=st.st_spare1;
std::string lfn( longFilename );
// st.st_mode & S_IFDIR indicates a directory
size_t lastDotPos = lfn.find_last_of( '.' );
if( lfn.npos != lastDotPos )
extName = lfn.substr( lastDotPos );
else
extName = "";
dbg_printf( "%s: %s %s\n", (st.st_mode & S_IFDIR ? " DIR" : "FILE"), longFilename, extName.c_str() );
bool showThis=(st.st_mode & S_IFDIR)?(strcmp(longFilename,".")&&strcmp(longFilename,"..")):extnameFilter( extNames, extName );
showThis=showThis&&(_showAllFiles||gs().showHiddenFiles||!(attr&ATTRIB_HID));
// 如果有后缀名或者是个目录就push进去
if(showThis) {
u32 row_count = getRowCount();
std::vector< std::string > a_row;
a_row.push_back( "" ); // make a space for icon
a_row.push_back(lfn); //show name
a_row.push_back( "" ); // make a space for internal name
a_row.push_back(dirName+lfn); //real name
if( st.st_mode & S_IFDIR ) {
a_row[SHOWNAME_COLUMN] += "/";
a_row[REALNAME_COLUMN] += "/";
}
size_t insertPos( row_count );
insertRow( insertPos, a_row );
DSRomInfo rominfo;
_romInfoList.push_back( rominfo );
}
if(extnameFilter(savNames,extName))
{
_saves.push_back(dirName+lfn);
}
}
dirclose( dir );
}
std::sort( _rows.begin(), _rows.end(), itemSortComp );
std::sort(_saves.begin(),_saves.end(),stringComp);
for( size_t ii = 0; ii < _rows.size(); ++ii )
{
////_romInfoList.push_back( rominfo );
// 这段代码会引起拷贝文件完成后的图标显示不正确因为图标的内容还没有被读入就去更新了active icon的内容
//u8 percent = ii * 100 / _rows.size();
//if( !(percent & 0x07) )
// progressWnd().setPercent( percent );
DSRomInfo & rominfo = _romInfoList[ii];
std::string filename = _rows[ii][REALNAME_COLUMN].text();
size_t lastDotPos = filename.find_last_of( '.' );
if( filename.npos != lastDotPos )
extName = filename.substr( lastDotPos );
else
extName = "";
for( size_t jj = 0; jj < extName.size(); ++jj )
extName[jj] = tolower( extName[jj] );
if( '/' == filename[filename.size()-1] )
{
rominfo.setBanner("folder",folder_banner_bin);
}
else
{
bool allowExt=true,allowUnknown=false;
if( ".sav" == extName ) {
memcpy( &rominfo.banner(), nds_save_banner_bin, sizeof(tNDSBanner) );
} else if( ".gba" == extName ) {
rominfo.MayBeGbaRom(filename);
} else if( ".nds" != extName && ".ids" != extName ) {
memcpy( &rominfo.banner(), unknown_banner_bin, sizeof(tNDSBanner) );
allowUnknown=true;
} else {
rominfo.MayBeDSRom(filename);
allowExt=false;
}
rominfo.setExtIcon(_rows[ii][SHOWNAME_COLUMN].text());
if(allowExt&&extName.length()&&!rominfo.isExtIcon()) rominfo.setExtIcon(extName.substr(1));
if(allowUnknown&&!rominfo.isExtIcon()) rominfo.setExtIcon("unknown");
}
}
_currentDir = dirName;
}
directoryChanged();
return true;
}
void cMainList::onSelectChanged( u32 index )
{
dbg_printf( "%s\n", _rows[index][3].text().c_str() );
}
void cMainList::onSelectedRowClicked( u32 index )
{
const INPUT & input = getInput();
//dbg_printf("%d %d", input.touchPt.px, _position.x );
if( input.touchPt.px > _position.x && input.touchPt.px < _position.x + 32 )
selectedRowHeadClicked( index );
}
void cMainList::onScrolled( u32 index )
{
_activeIconScale = 1;
//updateActiveIcon( CONTENT );
}
void cMainList::backParentDir()
{
if( "..." == _currentDir )
return;
bool fat1=(SD_ROOT==_currentDir),favorites=("favorites:/"==_currentDir);
if( "fat0:/" == _currentDir || fat1 || favorites || "/" == _currentDir ) {
enterDir( "..." );
if(fat1) selectRow(_topuSD);
if(favorites) selectRow(_topFavorites);
return;
}
size_t pos = _currentDir.rfind( "/", _currentDir.size() - 2 );
std::string parentDir = _currentDir.substr( 0, pos + 1 );
dbg_printf( "%s->%s\n", _currentDir.c_str(), parentDir.c_str() );
std::string oldCurrentDir = _currentDir;
if( enterDir( parentDir ) ) { // select last entered director
for( size_t i = 0; i < _rows.size(); ++i ){
if( parentDir + _rows[i][SHOWNAME_COLUMN].text() == oldCurrentDir ) {
selectRow( i );
}
}
}
}
std::string cMainList::getSelectedFullPath()
{
if( !_rows.size() )
return std::string("");
return _rows[_selectedRowId][REALNAME_COLUMN].text();
}
std::string cMainList::getSelectedShowName()
{
if( !_rows.size() )
return std::string("");
return _rows[_selectedRowId][SHOWNAME_COLUMN].text();
}
bool cMainList::getRomInfo( u32 rowIndex, DSRomInfo & info ) const
{
if( rowIndex < _romInfoList.size() ) {
info = _romInfoList[rowIndex];
return true;
}
else {
return false;
}
}
void cMainList::setRomInfo( u32 rowIndex, const DSRomInfo & info )
{
if( !_romInfoList[rowIndex].isDSRom() )
return;
if( rowIndex < _romInfoList.size() ) {
_romInfoList[rowIndex] = info;
}
}
void cMainList::draw()
{
updateInternalNames();
cListView::draw();
updateActiveIcon( POSITION );
drawIcons();
}
void cMainList::drawIcons() // 直接画家算法画 icons
{
if( VM_LIST != _viewMode ) {
size_t total = _visibleRowCount;
if( total > _rows.size() - _firstVisibleRowId )
total = _rows.size() - _firstVisibleRowId;
for( size_t i = 0; i < total; ++i ) {
// 这里图像呈现比真正的 MAIN buffer 翻转要早,所以会闪一下
// 解决方法是在 gdi().present 里边统一呈现翻转
if( _firstVisibleRowId + i == _selectedRowId ) {
if( _activeIcon.visible() ) {
continue;
}
}
s32 itemX = _position.x + 1;
s32 itemY = _position.y + i * _rowHeight + ((_rowHeight-32)>>1) - 1;
_romInfoList[_firstVisibleRowId+i].drawDSRomIcon( itemX, itemY, _engine );
}
}
}
void cMainList::setViewMode(VIEW_MODE mode)
{
if(!_columns.size()) return;
_viewMode=mode;
switch(_viewMode)
{
case VM_LIST:
_columns[ICON_COLUMN].width=0;
_columns[SHOWNAME_COLUMN].width=250;
_columns[INTERNALNAME_COLUMN].width=0;
arangeColumnsSize();
setRowHeight(15);
break;
case VM_ICON:
_columns[ICON_COLUMN].width=36;
_columns[SHOWNAME_COLUMN].width=214;
_columns[INTERNALNAME_COLUMN].width=0;
arangeColumnsSize();
setRowHeight(38);
break;
case VM_INTERNAL:
_columns[ICON_COLUMN].width=36;
_columns[SHOWNAME_COLUMN].width=0;
_columns[INTERNALNAME_COLUMN].width=214;
arangeColumnsSize();
setRowHeight(38);
break;
}
scrollTo(_selectedRowId-_visibleRowCount+1);
}
void cMainList::updateActiveIcon( bool updateContent )
{
const INPUT & temp = getInput();
bool allowAnimation = true;
animateIcons(allowAnimation);
//do not show active icon when hold key to list files. Otherwise the icon will not show correctly.
if( getInputIdleMs() > 1000 && VM_LIST != _viewMode && allowAnimation && _romInfoList.size() && 0 == temp.keysHeld && gs().Animation)
{
if( !_activeIcon.visible() ) {
u8 backBuffer[32*32*2];
zeroMemory( backBuffer, 32 * 32 * 2 );
_romInfoList[_selectedRowId].drawDSRomIconMem( backBuffer );
memcpy( _activeIcon.buffer(), backBuffer, 32 * 32 * 2 );
_activeIcon.setBufferChanged();
s32 itemX = _position.x;
s32 itemY = _position.y + (_selectedRowId - _firstVisibleRowId) * _rowHeight + ((_rowHeight-32)>>1) - 1;
_activeIcon.setPosition( itemX, itemY );
_activeIcon.show();
dbg_printf("sel %d ac ico x %d y %d\n", _selectedRowId, itemX, itemY );
for( u8 i = 0; i < 8; ++i )
dbg_printf("%02x", backBuffer[i] );
dbg_printf("\n");
}
} else {
if( _activeIcon.visible() ) {
_activeIcon.hide();
cwl();
}
}
}
std::string cMainList::getCurrentDir()
{
return _currentDir;
}
void cMainList::updateInternalNames(void)
{
if(_viewMode==VM_INTERNAL)
{
size_t total=_visibleRowCount;
if(total>_rows.size()-_firstVisibleRowId) total=_rows.size()-_firstVisibleRowId;
for(size_t ii=0;ii<total;++ii)
{
if(0==_rows[_firstVisibleRowId+ii][INTERNALNAME_COLUMN].text().length())
{
if(_romInfoList[_firstVisibleRowId+ii].isDSRom())
{
_rows[_firstVisibleRowId+ii][INTERNALNAME_COLUMN].setText(unicode_to_local_string(_romInfoList[_firstVisibleRowId+ii].banner().titles[gs().language],128,NULL));
}
else
{
_rows[_firstVisibleRowId+ii][INTERNALNAME_COLUMN].setText(_rows[_firstVisibleRowId+ii][SHOWNAME_COLUMN].text());
}
}
}
}
}
bool cMainList::IsFavorites(void)
{
return ("favorites:/"==_currentDir);
}
const std::vector<std::string>* cMainList::Saves(void)
{
return IsFavorites()?NULL:&_saves;
}
void cMainList::SwitchShowAllFiles(void)
{
_showAllFiles=!_showAllFiles;
enterDir(getCurrentDir());
}

158
arm9/source/mainlist.h Normal file
View File

@ -0,0 +1,158 @@
/*
mainlist.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MAINLIST_H_
#define _MAINLIST_H_
#include <nds.h>
#include "listview.h"
#include "sigslot.h"
#include "keymessage.h"
#include "touchmessage.h"
#include "dsrom.h"
#include "zoomingicon.h"
#if defined(_STORAGE_rpg)
#define SD_ROOT_0 "fat1:"
#else
#define SD_ROOT_0 "fat0:"
#endif
#define SD_ROOT SD_ROOT_0"/"
// 显示游戏列表,文件列表等等
class cMainList : public akui::cListView
{
public:
enum VIEW_MODE
{
VM_LIST = 0,
VM_ICON,
VM_INTERNAL
};
enum //COLUMN_LIST
{
ICON_COLUMN = 0,
SHOWNAME_COLUMN = 1,
INTERNALNAME_COLUMN = 2,
REALNAME_COLUMN = 3,
SAVETYPE_COLUMN = 4,
FILESIZE_COLUMN = 5
};
public:
cMainList( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text );
~cMainList();
public:
int init();
bool enterDir( const std::string & dirName );
void backParentDir();
void refresh();
std::string getCurrentDir();
bool getRomInfo( u32 rowIndex, DSRomInfo & info ) const;
void setRomInfo( u32 rowIndex, const DSRomInfo & info );
void setViewMode( VIEW_MODE mode );
std::string getSelectedFullPath();
std::string getSelectedShowName();
VIEW_MODE getViewMode() { return _viewMode; }
void arrangeIcons();
akui::Signal1< u32 > selectedRowHeadClicked;
akui::Signal0 directoryChanged;
akui::Signal1< bool& > animateIcons;
public:
bool IsFavorites(void);
void SwitchShowAllFiles(void);
const std::vector<std::string>* Saves(void);
protected:
void draw();
void drawIcons(); // 直接画家算法画 icons
enum {
POSITION = 0,
CONTENT = 1
};
void updateActiveIcon( bool updateContent ); // 更新活动图标的坐标等等
void updateInternalNames(void);
protected:
void onSelectedRowClicked( u32 index );
void onSelectChanged( u32 index );
void onScrolled( u32 index );
protected:
VIEW_MODE _viewMode;
std::string _currentDir;
std::vector< std::string > _extnameFilter;
std::vector< DSRomInfo > _romInfoList;
cZoomingIcon _activeIcon;
float _activeIconScale;
bool _showAllFiles;
std::vector< std::string > _saves;
protected:
u32 _topCount;
u32 _topuSD;
u32 _topSlot2;
u32 _topFavorites;
public:
u32 Slot2(void) {return _topSlot2;}
};
#endif//_MAINLIST_H_

909
arm9/source/mainwnd.cpp Normal file
View File

@ -0,0 +1,909 @@
/*
mainwnd.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "dbgtool.h"
#include "windowmanager.h"
#include "mainwnd.h"
#include "msgbox.h"
#include "systemfilenames.h"
#include "timer.h"
#include "../../share/timetool.h"
#include "../../share/fifotool.h"
#include "testcases.h"
#include "datetime.h"
#include "romloader.h"
#include "progresswnd.h"
#include "files.h"
#include "inifile.h"
#include "language.h"
#include "testcases.h"
#include "rominfownd.h"
#include "helpwnd.h"
#include "expwnd.h"
#include "gbaloader.h"
#include "romlauncher.h"
#include "sdidentify.h"
#include "favorites.h"
#ifdef DEBUG
#include "iocmn.h"
#endif
#include <sys/iosupport.h>
#include <elm.h>
using namespace akui;
cMainWnd::cMainWnd( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text ):
cForm( x, y, w, h, parent, text ),_mainList(NULL),_startMenu(NULL),_startButton(NULL),
_brightnessButton(NULL),_folderUpButton(NULL),_folderText(NULL),_processL(false)
{
}
cMainWnd::~cMainWnd()
{
delete _folderText;
delete _folderUpButton;
delete _brightnessButton;
delete _startButton;
delete _startMenu;
delete _mainList;
windowManager().removeWindow(this);
}
void cMainWnd::init()
{
int x = 0;
int y = 0;
int w = 0;
int h = 0;
COLOR color = 0;
std::string file("");
std::string text("");
CIniFile ini( SFN_UI_SETTINGS );
// self init
dbg_printf( "mainwnd init() %08x\n", this );
loadAppearance( SFN_LOWER_SCREEN_BG );
windowManager().addWindow( this );
// init game file list
//waitMs( 2000 );
_mainList = new cMainList( 4, 20, 248, 152, this, "main list" );
_mainList->setRelativePosition( cPoint(4, 20) );
_mainList->init();
_mainList->selectChanged.connect( this, &cMainWnd::listSelChange );
_mainList->selectedRowClicked.connect( this, &cMainWnd::onMainListSelItemClicked );
_mainList->selectedRowHeadClicked.connect( this, &cMainWnd::onMainListSelItemHeadClicked );
_mainList->directoryChanged.connect( this, &cMainWnd::onFolderChanged );
_mainList->animateIcons.connect( this, &cMainWnd::onAnimation );
//_mainList->enterDir( "fat0:/" );
addChildWindow( _mainList );
dbg_printf( "mainlist %08x\n", _mainList );
//waitMs( 1000 );
// init start button
x = ini.GetInt( "start button", "x", 0 );
y = ini.GetInt( "start button", "y", 172 );
w = ini.GetInt( "start button", "w", 48 );
h = ini.GetInt( "start button", "h", 10 );
color = ini.GetInt( "start button", "textColor", 0x7fff );
file = ini.GetString( "start button", "file", "none" );
text = ini.GetString( "start button", "text", "START" );
if(file!="none")
{
file=SFN_UI_CURRENT_DIRECTORY+file;
}
if(text=="ini")
{
text=LANG("start menu","START");
}
//_startButton = new cButton( 0, 172, 48, 18, this, " Start" );
_startButton = new cButton( x, y, w, h, this, text );
_startButton->setStyle(cButton::press);
_startButton->setRelativePosition( cPoint(x, y) );
_startButton->loadAppearance( file );
_startButton->clicked.connect( this, &cMainWnd::startButtonClicked );
_startButton->setTextColor( color | BIT(15) );
if(!ini.GetInt( "start button", "show", 1 )) _startButton->hide();
addChildWindow( _startButton );
// init brightness button
x = ini.GetInt( "brightness btn", "x", 240 );
y = ini.GetInt( "brightness btn", "y", 1 );
w = ini.GetInt( "brightness btn", "w", 16 );
h = ini.GetInt( "brightness btn", "h", 16 );
_brightnessButton = new cButton( x, y, w, h, this, "" );
_brightnessButton->setRelativePosition( cPoint(x, y) );
_brightnessButton->loadAppearance( SFN_BRIGHTNESS_BUTTON );
_brightnessButton->pressed.connect( this, &cMainWnd::brightnessButtonClicked );
addChildWindow( _brightnessButton );
x = ini.GetInt( "folderup btn", "x", 0 );
y = ini.GetInt( "folderup btn", "y", 2 );
w = ini.GetInt( "folderup btn", "w", 32 );
h = ini.GetInt( "folderup btn", "h", 16 );
_folderUpButton = new cButton( x, y, w, h, this, "" );
_folderUpButton->setRelativePosition( cPoint(x, y) );
_folderUpButton->loadAppearance( SFN_FOLDERUP_BUTTON );
_folderUpButton->setSize( cSize(w,h) );
_folderUpButton->pressed.connect( _mainList, &cMainList::backParentDir );
addChildWindow( _folderUpButton );
x = ini.GetInt( "folder text", "x", 20 );
y = ini.GetInt( "folder text", "y", 2 );
w = ini.GetInt( "folder text", "w", 160 );
h = ini.GetInt( "folder text", "h", 16 );
_folderText = new cStaticText( x, y, w, h, this, "" );
_folderText->setRelativePosition( cPoint(x, y) );
_folderText->setTextColor( ini.GetInt( "folder text", "color", 0 ) );
addChildWindow( _folderText );
// init startmenu
_startMenu = new cStartMenu( 160, 40, 61,108, this, "start menu" );
//_startMenu->setRelativePosition( cPoint(160, 40) );
_startMenu->init();
_startMenu->itemClicked.connect( this, &cMainWnd::startMenuItemClicked );
_startMenu->hide();
_startMenu->setRelativePosition( _startMenu->position() );
addChildWindow( _startMenu );
//windowManager().addWindow( _startMenu );
dbg_printf( "startMenu %08x\n", _startMenu );
arrangeChildren();
}
void cMainWnd::draw()
{
cForm::draw();
}
void cMainWnd::listSelChange( u32 i )
{
#ifdef DEBUG
//dbg_printf( "main list item %d\n", i );
DSRomInfo info;
if( _mainList->getRomInfo( i, info ) ) {
char title[13] = {}; memcpy( title, info.saveInfo().gameTitle, 12 );
char code[5] = {}; memcpy( code, info.saveInfo().gameCode, 4 );
u16 crc = swiCRC16( 0xffff, ((unsigned char *)&(info.banner())) + 32, 0x840 - 32);
dbg_printf( "%s %s %04x %d %04x/%04x\n",
title, code, info.saveInfo().gameCRC, info.isDSRom(), info.banner().crc,crc );
//dbg_printf("sizeof banner %08x\n", sizeof( info.banner() ) );
}
#endif//DEBUG
}
void cMainWnd::startMenuItemClicked( s16 i )
{
dbg_printf( "start menu item %d\n", i );
//messageBox( this, "Power Off", "Are you sure you want to turn off ds?", MB_YES | MB_NO );
if( START_MENU_ITEM_COPY == i ) {
if( "" == _mainList->getSelectedFullPath() )
return;
struct stat st;
stat( _mainList->getSelectedFullPath().c_str(), &st );
if( st.st_mode & S_IFDIR ) {
messageBox( this, LANG("no copy dir", "title"), LANG("no copy dir", "text"), MB_YES | MB_NO );
return;
}
setSrcFile( _mainList->getSelectedFullPath(), SFM_COPY );
}
else if( START_MENU_ITEM_CUT == i ) {
if( "" == _mainList->getSelectedFullPath() )
return;
struct stat st;
stat( _mainList->getSelectedFullPath().c_str(), &st );
if( st.st_mode & S_IFDIR ) {
messageBox( this, LANG("no copy dir", "title"), LANG("no copy dir", "text"), MB_YES | MB_NO );
return;
}
setSrcFile( _mainList->getSelectedFullPath(), SFM_CUT );
}
else if( START_MENU_ITEM_PASTE == i )
{
bool ret=false;
if(_mainList->IsFavorites())
{
ret=cFavorites::AddToFavorites(getSrcFile());
}
else
{
ret=copyOrMoveFile(_mainList->getCurrentDir());
}
if(ret) // refresh current directory
_mainList->enterDir(_mainList->getCurrentDir());
}
else if( START_MENU_ITEM_DELETE == i ) {
std::string fullPath = _mainList->getSelectedFullPath();
if( "" != fullPath )
{
bool ret=false;
if(_mainList->IsFavorites())
{
ret=cFavorites::RemoveFromFavorites(fullPath);
}
else
{
ret=deleteFile(fullPath);
}
if(ret)
_mainList->enterDir(_mainList->getCurrentDir());
}
}
else if( START_MENU_ITEM_SETTING == i ) {
showSettings();
}
else if( START_MENU_ITEM_INFO == i ) {
showFileInfo();
}
else if( START_MENU_ITEM_HELP == i ) {
CIniFile ini(SFN_UI_SETTINGS); //(256-)/2,(192-128)/2, 220, 128
u32 w = 200;
u32 h = 160;
w = ini.GetInt( "help window", "w", w );
h = ini.GetInt( "help window", "h", h );
cHelpWnd * helpWnd = new cHelpWnd( (256-w)/2, (192-h)/2, w, h, this, LANG("help window", "title" ) );
helpWnd->doModal();
delete helpWnd;
}
else if( START_MENU_ITEM_TOOLS == i ) {
u32 w=250;
u32 h=130;
cExpWnd expWnd((256-w)/2,(192-h)/2,w,h,NULL,LANG("exp window","title"));
expWnd.doModal();
}
}
void cMainWnd::startButtonClicked()
{
if( _startMenu->isVisible() )
{
_startMenu->hide();
}
else {
if(!gs().safeMode) _startMenu->show();
}
}
void cMainWnd::brightnessButtonClicked()
{
gs().nextBrightness();
}
cWindow& cMainWnd::loadAppearance(const std::string & aFileName )
{
return *this;
}
bool cMainWnd::process( const cMessage & msg )
{
if( _startMenu->isVisible() ) return _startMenu->process( msg );
bool ret = false;
ret = cForm::process( msg );
if( !ret ) {
if( msg.id() > cMessage::keyMessageStart && msg.id()
< cMessage::keyMessageEnd )
{
ret = processKeyMessage( (cKeyMessage &)msg );
}
if( msg.id() > cMessage::touchMessageStart && msg.id()
< cMessage::touchMessageEnd )
{
ret = processTouchMessage( (cTouchMessage &)msg );
}
}
return ret;
}
bool cMainWnd::processKeyMessage( const cKeyMessage & msg )
{
bool ret = false, isL = msg.shift()&cKeyMessage::UI_SHIFT_L;
bool allow = !gs().safeMode;
if( msg.id() == cMessage::keyDown )
{
switch( msg.keyCode() )
{
case cKeyMessage::UI_KEY_DOWN:
_mainList->selectNext();
ret = true;
break;
case cKeyMessage::UI_KEY_UP:
_mainList->selectPrev();
ret = true;
break;
case cKeyMessage::UI_KEY_LEFT:
_mainList->selectRow( _mainList->selectedRowId() - _mainList->visibleRowCount() );
ret = true;
break;
case cKeyMessage::UI_KEY_RIGHT:
_mainList->selectRow( _mainList->selectedRowId() + _mainList->visibleRowCount() );
ret = true;
break;
case cKeyMessage::UI_KEY_A:
onKeyAPressed();
ret = true;
break;
case cKeyMessage::UI_KEY_B:
onKeyBPressed();
ret = true;
break;
case cKeyMessage::UI_KEY_Y:
if(isL)
{
showSettings();
_processL = false;
}
else
{
onKeyYPressed();
}
ret = true;
break;
case cKeyMessage::UI_KEY_X: {
if(isL)
{
if(allow)
{
DSRomInfo rominfo;
if(_mainList->getRomInfo(_mainList->selectedRowId(),rominfo)&&rominfo.isDSRom()&&!rominfo.isHomebrew())
{
cRomInfoWnd::showCheats(_mainList->getSelectedFullPath());
}
}
_processL = false;
}
else
{
#if defined(_STORAGE_rpg)
const std::string dir = _mainList->getCurrentDir();
if( dir.length() < 5 ) {
_mainList->enterDir( "fat0:/" );
} else if( dir.substr( 0, 5 ) == "fat0:" ) {
_mainList->enterDir( "fat1:/" );
} else {
_mainList->enterDir( "fat0:/" );
}
#elif defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
_mainList->enterDir( "favorites:/" );
#endif
}
ret = true;
break;
}
case cKeyMessage::UI_KEY_START:
startButtonClicked();
ret = true;
break;
case cKeyMessage::UI_KEY_SELECT:
if(isL)
{
if(allow) _mainList->SwitchShowAllFiles();
_processL = false;
}
else
{
if(allow) _mainList->setViewMode((cMainList::VIEW_MODE)((_mainList->getViewMode()+1)%3));
}
ret = true;
break;
case cKeyMessage::UI_KEY_L:
_processL = true;
ret = true;
break;
case cKeyMessage::UI_KEY_R:
brightnessButtonClicked();
#ifdef DEBUG
gdi().switchSubEngineMode();gdi().present( GE_SUB );
#endif//DEBUG
ret = true;
break;
default:
{}
};
}
if( msg.id() == cMessage::keyUp )
{
switch( msg.keyCode() )
{
case cKeyMessage::UI_KEY_L:
if(_processL)
{
_mainList->backParentDir();
_processL = false;
}
ret = true;
break;
}
}
return ret;
}
bool cMainWnd::processTouchMessage( const cTouchMessage & msg )
{
bool ret = false;
return ret;
}
void cMainWnd::onKeyYPressed()
{
if(gs().safeMode) return;
#ifdef DEBUG
// hardware version check
{
dbg_printf("HW: %02x\n",ioVersion());
}
#endif//#ifdef DEBUG
showFileInfo();
}
void cMainWnd::onMainListSelItemClicked( u32 index )
{
}
void cMainWnd::onMainListSelItemHeadClicked( u32 index )
{
onKeyAPressed();
}
void cMainWnd::onKeyAPressed()
{
launchSelected();
}
void cMainWnd::launchSelected()
{
std::string fullPath = _mainList->getSelectedFullPath();
if( fullPath[fullPath.size()-1] == '/' ) {
_mainList->enterDir( fullPath );
return;
}
DSRomInfo rominfo;
if( !_mainList->getRomInfo( _mainList->selectedRowId(), rominfo ) )
return;
//rominfo.loadDSRomInfo( fullPath, false );
if( rominfo.isGbaRom() )
{
CGbaLoader(fullPath).Load(false,false);
return;
}
if(!rominfo.isDSRom()) return;
dbg_printf("(%s)\n", fullPath.c_str() );
dbg_printf("%d\n", fullPath[fullPath.size()-1] );
std::string title,text; bool show=true;
switch(launchRom(fullPath,rominfo,rominfo.isHomebrew()&&"akmenu4.nds"==_mainList->getSelectedShowName()))
{
#if defined(_STORAGE_rpg)
case ELaunchSDOnly:
title=LANG("sd save","title");
text=LANG("sd save","text");
break;
case ELaunchRestoreFail:
title=LANG("restore save fail","title");
text=LANG("restore save fail","text");
break;
#endif
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
case ELaunchSlowSD:
{
std::string model=sdidGetSDManufacturerName()+" "+sdidGetSDName();
title=LANG("unsupported sd","title");
text=LANG("unsupported sd","text");
text=formatString(text.c_str(),model.c_str());
}
break;
#endif
case ELaunchNoFreeSpace:
title=LANG("no free space","title");
text=LANG("no free space","text");
break;
default:
show=false;
break;
}
if(show) messageBox(this,title,text,MB_OK);
}
void cMainWnd::onKeyBPressed()
{
_mainList->backParentDir();
}
void cMainWnd::setParam(void)
{
cSettingWnd settingWnd(0,0,252,188,NULL,LANG("system setting","title"));
//page 1: system
std::string currentUIStyle=gs().uiName;
std::vector<std::string> _values;
u32 uiIndex=0,langIndex=0;
//user interface style
_values.clear();
std::vector<std::string> uiNames;
DIR_ITER* dir=diropen(SFN_UI_DIRECTORY);
if(NULL!=dir)
{
struct stat st;
char longFilename[MAX_FILENAME_LENGTH];
while(dirnext(dir,longFilename,&st)==0)
{
std::string lfn(longFilename);
if(lfn!=".."&&lfn!=".") _values.push_back(lfn);
}
dirclose(dir);
dir=NULL;
}
else
{
_values.push_back(gs().uiName);
}
std::sort(_values.begin(),_values.end());
for(size_t ii=0;ii<_values.size();++ii)
{
if(0==stricmp(_values[ii].c_str(),gs().uiName.c_str())) uiIndex=ii;
}
uiNames=_values;
settingWnd.addSettingItem(LANG("ui style","text"),_values,uiIndex);
//language
_values.clear();
std::vector<std::string> langNames;
dir=diropen(SFN_LANGUAGE_DIRECTORY);
if(NULL!=dir )
{
struct stat st;
char longFilename[MAX_FILENAME_LENGTH];
while(dirnext(dir,longFilename,&st)==0)
{
std::string lfn(longFilename);
if(lfn!=".."&&lfn!=".") _values.push_back(lfn);
}
dirclose(dir);
dir=NULL;
}
else
{
_values.push_back(gs().langDirectory);
}
std::sort(_values.begin(),_values.end());
for(size_t ii=0;ii<_values.size();++ii)
{
if(0==stricmp(_values[ii].c_str(),gs().langDirectory.c_str())) langIndex=ii;
}
langNames=_values;
settingWnd.addSettingItem(LANG("language","text"),_values,langIndex);
//file list type
_values.clear();
for(size_t ii=0;ii<3;++ii)
{
std::string itemName=formatString("item%d",ii);
_values.push_back(LANG("filelist type",itemName));
}
settingWnd.addSettingItem(LANG("filelist type","text"),_values,gs().fileListType);
_values.clear();
_values.push_back(LANG("switches","Disable"));
_values.push_back(LANG("switches","Enable"));
settingWnd.addSettingItem(LANG("system setting","safe mode"),_values,gs().safeMode);
//page 2: interface
settingWnd.addSettingTab(LANG("interface settings","title"));
size_t scrollSpeed=0;
switch(gs().scrollSpeed)
{
case cGlobalSettings::EScrollFast:
scrollSpeed=0;
break;
case cGlobalSettings::EScrollMedium:
scrollSpeed=1;
break;
case cGlobalSettings::EScrollSlow:
scrollSpeed=2;
break;
}
_values.clear();
_values.push_back(LANG("scrolling","fast"));
_values.push_back(LANG("scrolling","medium"));
_values.push_back(LANG("scrolling","slow"));
settingWnd.addSettingItem(LANG("interface settings","scrolling speed"),_values,scrollSpeed);
_values.clear();
_values.push_back(LANG("interface settings","oldschool"));
_values.push_back(LANG("interface settings","modern"));
_values.push_back(LANG("interface settings","internal"));
settingWnd.addSettingItem(LANG("interface settings","filelist style"),_values,gs().viewMode);
_values.clear();
_values.push_back(LANG("switches","Disable"));
_values.push_back(LANG("switches","Enable"));
settingWnd.addSettingItem(LANG("interface settings","animation"),_values,gs().Animation);
settingWnd.addSettingItem(LANG("interface settings","12 hour"),_values,gs().show12hrClock);
//page 3: filesystem
settingWnd.addSettingTab(LANG("file settings","title"));
_values.clear();
_values.push_back(LANG("switches","Disable"));
_values.push_back(LANG("switches","Enable"));
settingWnd.addSettingItem(LANG("file settings","show hidden files"),_values,gs().showHiddenFiles);
settingWnd.addSettingItem(LANG("rom trim","text"),_values,gs().romTrim);
_values.clear();
_values.push_back(".nds.sav");
_values.push_back(".sav");
settingWnd.addSettingItem(LANG("file settings","save extension"),_values,gs().saveExt);
//page 4: patches
settingWnd.addSettingTab(LANG("setting window","patches"));
_values.clear();
_values.push_back(LANG("switches","Disable"));
_values.push_back(LANG("switches","Enable"));
settingWnd.addSettingItem(LANG("patches","cheating system"),_values,gs().cheats);
settingWnd.addSettingItem(LANG("patches","reset in game"),_values,gs().softreset);
settingWnd.addSettingItem(LANG("patches","homebrew reset"),_values,gs().homebrewreset);
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
settingWnd.addSettingItem(LANG("patches","dma"),_values,gs().dma);
#endif
#if defined(_STORAGE_rpg)
settingWnd.addSettingItem(LANG("patches","sd save"),_values,gs().sdsave);
#endif
//page 5: gba
settingWnd.addSettingTab(LANG("gba settings","title"));
_values.clear();
_values.push_back(LANG("switches","Disable"));
_values.push_back(LANG("switches","Enable"));
settingWnd.addSettingItem(LANG("gba settings","sleephack"),_values,gs().gbaSleepHack);
settingWnd.addSettingItem(LANG("gba settings","autosave"),_values,gs().gbaAutoSave);
_values.clear();
_values.push_back(LANG("gba settings","modeask"));
_values.push_back(LANG("gba settings","modegba"));
_values.push_back(LANG("gba settings","modends"));
settingWnd.addSettingItem(LANG("gba settings","mode"),_values,gs().slot2mode);
u32 ret=settingWnd.doModal();
if(ID_CANCEL==ret) return;
//page 1: system
u32 uiIndexAfter=settingWnd.getItemSelection(0,0);
u32 langIndexAfter=settingWnd.getItemSelection(0,1);
gs().fileListType=settingWnd.getItemSelection(0,2);
gs().safeMode=settingWnd.getItemSelection(0,3);
//page 2: interface
switch(settingWnd.getItemSelection(1,0))
{
case 0:
gs().scrollSpeed=cGlobalSettings::EScrollFast;
break;
case 1:
gs().scrollSpeed=cGlobalSettings::EScrollMedium;
break;
case 2:
gs().scrollSpeed=cGlobalSettings::EScrollSlow;
break;
}
gs().viewMode=settingWnd.getItemSelection(1,1);
gs().Animation=settingWnd.getItemSelection(1,2);
gs().show12hrClock=settingWnd.getItemSelection(1,3);
//page 3: filesystem
gs().showHiddenFiles=settingWnd.getItemSelection(2,0);
gs().romTrim=settingWnd.getItemSelection(2,1);
gs().saveExt=settingWnd.getItemSelection(2,2);
//page 4: patches
gs().cheats=settingWnd.getItemSelection(3,0);
gs().softreset=settingWnd.getItemSelection(3,1);
gs().homebrewreset=settingWnd.getItemSelection(3,2);
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
gs().dma=settingWnd.getItemSelection(3,3);
#endif
#if defined(_STORAGE_rpg)
gs().sdsave=settingWnd.getItemSelection(3,4);
#endif
//page 5: gba
gs().gbaSleepHack=settingWnd.getItemSelection(4,0);
gs().gbaAutoSave=settingWnd.getItemSelection(4,1);
gs().slot2mode=settingWnd.getItemSelection(4,2);
if( uiIndex != uiIndexAfter )
{
u32 ret = messageBox( this,
LANG("ui style changed", "title"),
LANG("ui style changed", "text"), MB_YES | MB_NO );
if( ID_YES == ret ) {
gs().uiName = uiNames[uiIndexAfter];
gs().langDirectory = langNames[langIndexAfter];
gs().saveSettings();
#if defined(_STORAGE_rpg)
loadRom( "fat0:/akmenu4.nds", 0, 0, 0 );
#elif defined(_STORAGE_r4)
loadRom( "fat0:/_ds_menu.dat", "", 0, 0, 0 );
#elif defined(_STORAGE_ak2i)
loadRom( "fat0:/akmenu4.nds", "", 0, 0, 0 );
#elif defined(_STORAGE_r4idsn)
loadRom( "fat0:/_dsmenu.dat", "", 0, 0, 0 );
#endif
}
}
if( langIndex != langIndexAfter )
{
u32 ret = messageBox( this,
LANG("language changed", "title"),
LANG("language changed", "text"), MB_YES | MB_NO );
if( ID_YES == ret )
{
gs().langDirectory = langNames[langIndexAfter];
gs().saveSettings();
#if defined(_STORAGE_rpg)
loadRom( "fat0:/akmenu4.nds", 0, 0, 0 );
#elif defined(_STORAGE_r4)
loadRom( "fat0:/_ds_menu.dat", "", 0, 0, 0 );
#elif defined(_STORAGE_ak2i)
loadRom( "fat0:/akmenu4.nds", "", 0, 0, 0 );
#elif defined(_STORAGE_r4idsn)
loadRom( "fat0:/_dsmenu.dat", "", 0, 0, 0 );
#endif
}
}
gs().saveSettings();
_mainList->setViewMode((cMainList::VIEW_MODE)gs().viewMode);
}
void cMainWnd::showSettings(void)
{
if(gs().safeMode) return;
u8 currentFileListType = gs().fileListType,currentShowHiddenFiles=gs().showHiddenFiles;
setParam();
if(gs().fileListType!=currentFileListType||gs().showHiddenFiles!=currentShowHiddenFiles)
{
_mainList->enterDir(_mainList->getCurrentDir());
}
}
void cMainWnd::showFileInfo()
{
DSRomInfo rominfo;
if( !_mainList->getRomInfo( _mainList->selectedRowId(), rominfo ) ) {
return;
}
dbg_printf("show '%s' info\n", _mainList->getSelectedFullPath().c_str() );
CIniFile ini(SFN_UI_SETTINGS); //(256-)/2,(192-128)/2, 220, 128
u32 w = 240;
u32 h = 144;
w = ini.GetInt( "rom info window", "w", w );
h = ini.GetInt( "rom info window", "h", h );
cRomInfoWnd * romInfoWnd = new cRomInfoWnd( (256-w)/2, (192-h)/2, w, h, this, LANG("rom info", "title" ) );
std::string showName = _mainList->getSelectedShowName();
std::string fullPath = _mainList->getSelectedFullPath();
romInfoWnd->setFileInfo( fullPath, showName );
romInfoWnd->setRomInfo( rominfo );
romInfoWnd->setSaves(_mainList->Saves());
romInfoWnd->doModal();
rominfo = romInfoWnd->getRomInfo();
_mainList->setRomInfo( _mainList->selectedRowId(), rominfo );
delete romInfoWnd;
}
void cMainWnd::onFolderChanged()
{
resetInputIdle();
std::string dirShowName = _mainList->getCurrentDir();
#if defined(_STORAGE_rpg)
if( dirShowName.substr( 0, 5 ) == "fat0:" )
dirShowName.replace( 0, 4, "Flash" );
else
#endif
if( dirShowName.substr( 0, 5 ) == SD_ROOT_0 )
dirShowName.replace( 0, 4, "SD" );
else if( "favorites:/" != dirShowName && "slot2:/" == _mainList->getSelectedFullPath() )
{
u8 chk = 0;
for( u32 i = 0xA0; i < 0xBD; ++i ) {
chk = chk - *(u8*)(0x8000000+i);
}
chk = (chk- 0x19) & 0xff;
if( chk != GBA_HEADER.complement ) {
dbg_printf("chk %02x header checksum %02x\n", chk, GBA_HEADER.complement );
std::string title = LANG("no gba card", "title");
std::string text = LANG("no gba card", "text");
messageBox( NULL, title, text, MB_OK );
_mainList->enterDir( "..." );
_mainList->selectRow( _mainList->Slot2() );
return;
}
int mode=gs().slot2mode;
if(mode==cGlobalSettings::ESlot2Ask)
{
if(ID_YES==messageBox(NULL,LANG("gba settings","mode"),LANG("gba settings","modetext"),MB_YES_NO))
{
mode=cGlobalSettings::ESlot2Nds;
}
else
{
mode=cGlobalSettings::ESlot2Gba;
}
}
if(mode==cGlobalSettings::ESlot2Nds)
{
#if defined(_STORAGE_rpg)
loadRom("slot2:/",0,0,0);
#elif defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
loadRom("slot2:/","",0,0,0);
#endif
}
else
{
CGbaLoader::StartGBA();
}
}
dbg_printf("%s\n", _mainList->getSelectedFullPath().c_str() );
_folderText->setText( dirShowName );
}
void cMainWnd::onAnimation(bool& anAllow)
{
if(_startMenu->isVisible()) anAllow=false;
else if(windowManager().currentWindow()!=this) anAllow=false;
}
cWindow* cMainWnd::windowBelow(const cPoint & p)
{
cWindow* wbp=cForm::windowBelow(p);
if(_startMenu->isVisible()&&wbp!=_startButton) wbp=_startMenu;
return wbp;
}

108
arm9/source/mainwnd.h Normal file
View File

@ -0,0 +1,108 @@
/*
mainwnd.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MAINWND_H_
#define _MAINWND_H_
#include "form.h"
#include "mainlist.h"
#include "button.h"
#include "keymessage.h"
#include "touchmessage.h"
#include "spinbox.h"
#include "settingwnd.h"
#include "startmenu.h"
class cMainWnd : public akui::cForm
{
public:
cMainWnd( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text );
~cMainWnd();
public:
bool process( const akui::cMessage & msg );
cWindow& loadAppearance(const std::string& aFileName );
void init();
void draw();
cWindow* windowBelow(const akui::cPoint & p);
cMainList * _mainList;
protected:
void onMainListSelItemClicked( u32 index );
void onMainListSelItemHeadClicked( u32 index );
void onKeyAPressed();
void onKeyBPressed();
void onKeyXPressed();
void onKeyYPressed();
void listSelChange( u32 i );
void startMenuItemClicked( s16 i );
void startButtonClicked();
void brightnessButtonClicked();
bool processKeyMessage( const akui::cKeyMessage & msg );
bool processTouchMessage( const akui::cTouchMessage & msg );
void setParam(void);
void showSettings(void);
void onFolderChanged();
void onAnimation(bool& anAllow);
void showFileInfo();
void launchSelected();
cStartMenu * _startMenu;
akui::cButton * _startButton;
akui::cButton * _brightnessButton;
akui::cButton * _folderUpButton;
akui::cStaticText * _folderText;
bool _processL;
};
#endif//_MAINWND_H_

29
arm9/source/padding.s Normal file
View File

@ -0,0 +1,29 @@
/*
padding.s
Copyright (C) 2010 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
.arch armv5te
.cpu arm946e-s
.section .pad,"ax",%progbits
.align 2
.arm
#if defined(_STORAGE_r4idsn)
ldr pc, target
target:
.word 0x02000450
#endif
.end

617
arm9/source/rominfownd.cpp Normal file
View File

@ -0,0 +1,617 @@
/*
rominfownd.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <sys/stat.h>
#include "rominfownd.h"
#include "systemfilenames.h"
#include "msgbox.h"
#include "windowmanager.h"
#include "globalsettings.h"
#include "uisettings.h"
#include "language.h"
#include "unicode.h"
#include "files.h"
#include "gbaloader.h"
#include "cheatwnd.h"
#include "ui/binaryfind.h"
using namespace akui;
cRomInfoWnd::cRomInfoWnd( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text )
: cForm( x, y, w, h, parent, text ),
_buttonOK(0,0,46,18,this,"\x01 OK"),
_buttonSaveType(0,0,76,18,this,"\x04 Save Type"),
_buttonFlash(0,0,46,18,this,"\x03 to NOR"),
_buttonCopy(0,0,46,18,this,"\x05 to RAM"),
_buttonCheats(0,0,46,18,this,"\x03 Cheats"),
_settingWnd(NULL),
_saves(NULL)
{
s16 buttonY = size().y - _buttonOK.size().y - 4;
_buttonOK.setStyle( cButton::press );
_buttonOK.setText( "\x01 " + LANG( "setting window", "ok" ) );
_buttonOK.setTextColor( uis().buttonTextColor );
_buttonOK.loadAppearance( SFN_BUTTON3 );
_buttonOK.clicked.connect( this, &cRomInfoWnd::onOK );
addChildWindow( &_buttonOK );
s16 nextButtonX = size().x;
s16 buttonPitch = _buttonOK.size().x + 8;
nextButtonX -= buttonPitch;
_buttonOK.setRelativePosition( cPoint(nextButtonX, buttonY) );
_buttonSaveType.setStyle( cButton::press );
_buttonSaveType.setText( "\x04 " + LANG( "setting window", "savetype" ) );
_buttonSaveType.setTextColor( uis().buttonTextColor );
_buttonSaveType.loadAppearance( SFN_BUTTON4 );
_buttonSaveType.clicked.connect( this, &cRomInfoWnd::pressSaveType );
addChildWindow( &_buttonSaveType );
buttonPitch = _buttonSaveType.size().x + 8;
s16 nextButtonXone = nextButtonX - buttonPitch;
_buttonSaveType.setRelativePosition( cPoint(nextButtonXone, buttonY) );
_buttonCheats.setStyle( cButton::press );
_buttonCheats.setText( "\x03 " + LANG( "cheats", "title" ) );
_buttonCheats.setTextColor( uis().buttonTextColor );
_buttonCheats.loadAppearance( SFN_BUTTON3 );
_buttonCheats.clicked.connect( this, &cRomInfoWnd::pressCheats );
addChildWindow( &_buttonCheats );
buttonPitch = _buttonCheats.size().x + 8;
nextButtonXone -= buttonPitch;
_buttonCheats.setRelativePosition( cPoint(nextButtonXone, buttonY) );
_buttonFlash.setStyle( cButton::press );
_buttonFlash.setText( "\x03 " + LANG( "exp window", "flash to nor" ) );
_buttonFlash.setTextColor( uis().buttonTextColor );
_buttonFlash.loadAppearance( SFN_BUTTON3 );
_buttonFlash.clicked.connect( this, &cRomInfoWnd::pressFlash );
addChildWindow( &_buttonFlash );
buttonPitch = _buttonFlash.size().x + 8;
nextButtonX -= buttonPitch;
_buttonFlash.setRelativePosition( cPoint(nextButtonX, buttonY) );
_buttonCopy.setStyle( cButton::press );
_buttonCopy.setText( "\x05 " + LANG( "exp window", "copy to psram" ) );
_buttonCopy.setTextColor( uis().buttonTextColor );
_buttonCopy.loadAppearance( SFN_BUTTON3 );
_buttonCopy.clicked.connect( this, &cRomInfoWnd::pressCopy );
addChildWindow( &_buttonCopy );
buttonPitch = _buttonCopy.size().x + 8;
nextButtonX -= buttonPitch;
_buttonCopy.setRelativePosition( cPoint(nextButtonX, buttonY) );
loadAppearance( "" );
arrangeChildren();
}
cRomInfoWnd::~cRomInfoWnd()
{}
void cRomInfoWnd::draw()
{
_renderDesc.draw( windowRectangle(), _engine );
_romInfo.drawDSRomIcon( position().x + 8, position().y + 24, selectedEngine() );
gdi().setPenColor( uiSettings().formTextColor, selectedEngine() );
gdi().textOutRect( position().x + 48, position().y + 22, size().x - 40, 40, _romInfoText.c_str(), selectedEngine() );
gdi().textOutRect( position().x + 8, position().y + 64 , size().x - 8, 40, _filenameText.c_str(), selectedEngine() );
gdi().textOutRect( position().x + 8, position().y + 64 + 14, size().x - 8, 40, _fileDateText.c_str(), selectedEngine() );
gdi().textOutRect( position().x + 8, position().y + 64 + 14 + 14, size().x - 8, 40, _fileSizeText.c_str(), selectedEngine() );
gdi().textOutRect( position().x + 8, position().y + 64 + 14 + 14 + 14, size().x - 8, 40, _saveTypeText.c_str(), selectedEngine() );
cForm::draw();
}
bool cRomInfoWnd::process( const akui::cMessage & msg )
{
bool ret = false;
ret = cForm::process( msg );
if( !ret ) {
if( msg.id() > cMessage::keyMessageStart && msg.id()
< cMessage::keyMessageEnd )
{
ret = processKeyMessage( (cKeyMessage &)msg );
}
}
return ret;
}
bool cRomInfoWnd::processKeyMessage( const cKeyMessage & msg )
{
bool ret = false;
if( msg.id() == cMessage::keyDown )
{
switch( msg.keyCode() )
{
case cKeyMessage::UI_KEY_A:
case cKeyMessage::UI_KEY_B:
onOK();
ret = true;
break;
case cKeyMessage::UI_KEY_Y:
pressSaveType();
ret = true;
break;
case cKeyMessage::UI_KEY_X:
if(_buttonCheats.isVisible())
{
pressCheats();
}
else if(_buttonFlash.isVisible())
{
pressFlash();
}
ret = true;
break;
case cKeyMessage::UI_KEY_L:
pressCopy();
ret = true;
break;
default:
{}
};
}
return ret;
}
cWindow& cRomInfoWnd::loadAppearance(const std::string& aFileName )
{
_renderDesc.loadData( SFN_FORM_TITLE_L, SFN_FORM_TITLE_R, SFN_FORM_TITLE_M );
_renderDesc.setTitleText( _text );
return *this;
}
static std::string getFriendlyFileSizeString( u64 size )
{
std::string fileSize;
std::string sizeUnit;
if( size<1024)
{
fileSize=formatString( "%d", size);
sizeUnit=" Byte";
}
else
{
u32 divider;
if(size<1024*1024)
{
divider=1024;
sizeUnit=" KB";
}
else if(size<1024*1024*1024)
{
divider=1024*1024;
sizeUnit=" MB";
}
else
{
divider=1024*1024*1024;
sizeUnit=" GB";
}
fileSize=formatString("%d.%02d",(u32)(size/divider),(u32)((size*100+(divider>>1))/divider%100));
}
return fileSize+sizeUnit;
}
void cRomInfoWnd::setDiskInfo(void)
{
u64 total = 0;
u64 used = 0;
u64 freeSpace = 0;
if( !getDiskSpaceInfo( _fullName, total, used, freeSpace ) )
return;
_filenameText = formatString( LANG("disk info", "total").c_str(), getFriendlyFileSizeString(total).c_str() );
_fileDateText = formatString( LANG("disk info", "used").c_str(), getFriendlyFileSizeString(used).c_str() );
_fileSizeText = formatString( LANG("disk info", "free").c_str(), getFriendlyFileSizeString(freeSpace).c_str() );
}
void cRomInfoWnd::setFileInfo( const std::string & fullName, const std::string & showName )
{
_fullName=fullName;
if( "" == showName ) {
dbg_printf("show name %s\n", showName.c_str() );
return;
}
struct stat st;
if( -1 == stat( fullName.c_str(), &st ) ) {
return;
}
if( "fat0:/" == fullName || "fat1:/" == fullName ) {
setDiskInfo();
return;
}
if( showName.size() > 0 && '/' == showName[showName.size()-1] )
_filenameText = showName.substr( 0, showName.size() - 1 );
else
_filenameText = showName;
//dbg_printf("st.st_mtime %d\n", st.st_mtime );
//struct tm * filetime = localtime(&st.st_mtime);
struct tm * filetime = gmtime(&st.st_mtime);
_fileDateText = formatString( LANG("rom info", "file date").c_str(),
filetime->tm_year + 1900, filetime->tm_mon+1, filetime->tm_mday,
filetime->tm_hour, filetime->tm_min, filetime->tm_sec );
dbg_printf("st.st_mtime %d\n", (u32)st.st_mtime );
dbg_printf( "%d-%d-%d %02d:%02d:%02d\n",
filetime->tm_year + 1900, filetime->tm_mon+1, filetime->tm_mday,
filetime->tm_hour, filetime->tm_min, filetime->tm_sec );
_fileSizeText = formatString( LANG("rom info", "file size").c_str(), getFriendlyFileSizeString(st.st_size).c_str() );
_size = st.st_size;
}
void cRomInfoWnd::setRomInfo( const DSRomInfo & romInfo )
{
_romInfo = romInfo;
_romInfoText = unicode_to_local_string( _romInfo.banner().titles[gs().language], 128, NULL );
_buttonSaveType.hide();
_buttonFlash.hide();
_buttonCopy.hide();
_buttonCheats.hide();
if( _romInfo.isDSRom()&&!_romInfo.isHomebrew() )
{
const char * stLangStrings[] = { "Unknown", "No Save", "4K", "64K", "512K", "2M", "4M", "8M", "Unknown", "Unknown", "1M", "16M", "32M", "64M" };
if( _romInfo.saveInfo().saveType < sizeof(stLangStrings)/sizeof(char*) )
{
_saveTypeText = formatString( LANG("rom info", "save type").c_str(),
LANG("save type", stLangStrings[_romInfo.saveInfo().saveType]).c_str() );
}
else _saveTypeText = "";
addCode();
_buttonSaveType.show();
if(gs().cheatDB) _buttonCheats.show();
}
else if(_romInfo.isGbaRom())
{
_buttonFlash.show();
_buttonSaveType.setText( "\x03 " + LANG( "exp window", "flash to nor" ) );
if(CGbaLoader::CheckPSRAM(_size)) _buttonCopy.show();
addCode();
}
}
const DSRomInfo & cRomInfoWnd::getRomInfo()
{
return _romInfo;
}
void cRomInfoWnd::setSaves(const std::vector<std::string>* saves)
{
_saves=saves;
}
void cRomInfoWnd::onOK()
{
cForm::onOK();
}
void cRomInfoWnd::onShow()
{
centerScreen();
}
#if defined(_STORAGE_rpg)
#define ITEM_SAVETYPE 0,0
#define ITEM_DOWNLOADPLAY 0,1
#define ITEM_DMA 0,2
#define ITEM_PROTECTION 0,3
#define ITEM_LINKAGE 0,4
#define ITEM_RUMBLE 0,5
#define ITEM_CHEATS 1,0
#define ITEM_SOFTRESET 1,1
#define ITEM_SDSAVE 1,2
#define ITEM_SAVESLOT 1,3
#define ITEM_ICON 1,4
#define ITEM_LANGUAGE 1,5
#elif defined(_STORAGE_r4) || defined(_STORAGE_r4idsn)
#define ITEM_SAVETYPE 0,0
#define ITEM_LINKAGE 0,1
#define ITEM_RUMBLE 0,2
#define ITEM_CHEATS 1,0
#define ITEM_SOFTRESET 1,1
#define ITEM_SAVESLOT 1,2
#define ITEM_ICON 1,3
#define ITEM_LANGUAGE 1,4
#elif defined(_STORAGE_ak2i)
#define ITEM_SAVETYPE 0,0
#define ITEM_DOWNLOADPLAY 0,1
#define ITEM_DMA 0,2
#define ITEM_PROTECTION 0,3
#define ITEM_LINKAGE 0,4
#define ITEM_RUMBLE 0,5
#define ITEM_CHEATS 1,0
#define ITEM_SOFTRESET 1,1
#define ITEM_SAVESLOT 1,2
#define ITEM_ICON 1,3
#define ITEM_LANGUAGE 1,4
#endif
void cRomInfoWnd::pressSaveType(void)
{
if(!_romInfo.isDSRom()||_romInfo.isHomebrew()) return;
cSettingWnd settingWnd( 0,0, 252, 188, this, LANG("save type", "tab1" ) );
std::vector< std::string > _values;
_values.push_back( LANG("save type", "Unknown" ) );
_values.push_back( LANG("save type", "No Save" ) );
_values.push_back( LANG("save type", "4K" ) );
_values.push_back( LANG("save type", "64K" ) );
_values.push_back( LANG("save type", "512K" ) );
_values.push_back( LANG("save type", "1M" ) );
_values.push_back( LANG("save type", "2M" ) );
_values.push_back( LANG("save type", "4M" ) );
_values.push_back( LANG("save type", "8M" ) );
_values.push_back( LANG("save type", "16M" ) );
_values.push_back( LANG("save type", "32M" ) );
_values.push_back( LANG("save type", "64M" ) );
settingWnd.addSettingItem( LANG("save type", "text" ), _values, cSaveManager::SaveTypeToDisplaySaveType((SAVE_TYPE)_romInfo.saveInfo().saveType) );
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
_values.clear();
_values.push_back( LANG("switches", "Disable" ) );
_values.push_back( LANG("switches", "Enable" ) );
settingWnd.addSettingItem( LANG("patches", "download play" ), _values, _romInfo.saveInfo().getDownloadPlay() );
_values.clear();
_values.push_back( LANG("switches", "Disable" ) );
_values.push_back( LANG("switches", "Enable" ) );
_values.push_back(formatString(LANG("switches","Global").c_str(),gs().dma?LANG("switches","Enable").c_str():LANG("switches","Disable").c_str()));
settingWnd.addSettingItem( LANG("patches", "dma" ), _values, _romInfo.saveInfo().getDMA() );
#endif
_values.clear();
_values.push_back( LANG("switches", "Disable" ) );
_values.push_back( LANG("switches", "Enable" ) );
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
settingWnd.addSettingItem( LANG("patches", "protection" ), _values, _romInfo.saveInfo().getProtection() );
#endif
settingWnd.addSettingItem( LANG("patches", "linkage" ), _values, _romInfo.saveInfo().getLinkage() );
_values.clear();
const char* rumbleLang[]={"off","low","mid","high"};
for( size_t i = 0; i < 4; ++i ) {
_values.push_back( LANG( "exp window", rumbleLang[i] ) );
}
settingWnd.addSettingItem( LANG( "exp window","strength"), _values, _romInfo.saveInfo().getRumble() );
settingWnd.addSettingTab(LANG("save type","tab2"));
_values.clear();
_values.push_back( LANG("switches", "Disable" ) );
_values.push_back( LANG("switches", "Enable" ) );
_values.push_back(formatString(LANG("switches","Global").c_str(),gs().cheats?LANG("switches","Enable").c_str():LANG("switches","Disable").c_str()));
settingWnd.addSettingItem( LANG("patches", "cheating system" ), _values, _romInfo.saveInfo().getCheat() );
_values.clear();
_values.push_back( LANG("switches", "Disable" ) );
_values.push_back( LANG("switches", "Enable" ) );
_values.push_back(formatString(LANG("switches","Global").c_str(),gs().softreset?LANG("switches","Enable").c_str():LANG("switches","Disable").c_str()));
settingWnd.addSettingItem( LANG("patches", "reset in game" ), _values, _romInfo.saveInfo().getSoftReset() );
#if defined(_STORAGE_rpg)
_values.clear();
_values.push_back( LANG("switches", "Disable" ) );
_values.push_back( LANG("switches", "Enable" ) );
_values.push_back(formatString(LANG("switches","Global").c_str(),gs().sdsave?LANG("switches","Enable").c_str():LANG("switches","Disable").c_str()));
settingWnd.addSettingItem( LANG("patches", "sd save" ), _values, _romInfo.saveInfo().getSDSave() );
#endif
_values.clear();
std::string slotValue;
for(size_t ii=0;ii<4;++ii)
{
if(ii) slotValue='0'+ii;
else slotValue=LANG("save type","default");
if(SlotExists(ii)) slotValue+="*";
_values.push_back(slotValue);
}
settingWnd.addSettingItem( LANG("save type", "save slot" ), _values, _romInfo.saveInfo().getSlot() );
_values.clear();
_values.push_back( LANG("icon", "transparent" ) );
_values.push_back( LANG("icon", "as is" ) );
_values.push_back( LANG("icon", "firmware" ) );
settingWnd.addSettingItem( LANG("icon", "icon" ), _values, _romInfo.saveInfo().getIcon() );
_values.clear();
_values.push_back( LANG("save type", "default" ) );
_values.push_back( LANG("language", "ja" ) );
_values.push_back( LANG("language", "en" ) );
_values.push_back( LANG("language", "fr" ) );
_values.push_back( LANG("language", "de" ) );
_values.push_back( LANG("language", "it" ) );
_values.push_back( LANG("language", "es" ) );
settingWnd.addSettingItem( LANG("language", "text" ), _values, _romInfo.saveInfo().getLanguage() );
_settingWnd = &settingWnd;
settingWnd.addYButton(LANG("rom info","copy slot"),this,&cRomInfoWnd::pressCopySlot);
u32 ret = settingWnd.doModal();
_settingWnd = NULL;
if( ID_CANCEL == ret )
return;
_romInfo.saveInfo().saveType = cSaveManager::DisplaySaveTypeToSaveType((DISPLAY_SAVE_TYPE)settingWnd.getItemSelection(ITEM_SAVETYPE));
const char * stLangStrings[] = { "Unknown", "No Save", "4K", "64K", "512K", "2M", "4M", "8M", "Unknown", "Unknown", "1M", "16M", "32M", "64M" };
if( _romInfo.saveInfo().saveType < sizeof(stLangStrings)/sizeof(char*) ) {
_saveTypeText = formatString( LANG("rom info", "save type").c_str(),
LANG("save type", stLangStrings[_romInfo.saveInfo().saveType]).c_str() );
addCode();
}
_romInfo.saveInfo().setFlags
(
settingWnd.getItemSelection(ITEM_RUMBLE),
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
settingWnd.getItemSelection(ITEM_DOWNLOADPLAY),
#elif defined(_STORAGE_r4) || defined(_STORAGE_r4idsn)
0,
#endif
settingWnd.getItemSelection(ITEM_SOFTRESET),
settingWnd.getItemSelection(ITEM_CHEATS),
settingWnd.getItemSelection(ITEM_SAVESLOT),
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
settingWnd.getItemSelection(ITEM_DMA),
settingWnd.getItemSelection(ITEM_PROTECTION),
#elif defined(_STORAGE_r4) || defined(_STORAGE_r4idsn)
2,
0,
#endif
settingWnd.getItemSelection(ITEM_LINKAGE),
settingWnd.getItemSelection(ITEM_ICON),
#if defined(_STORAGE_rpg)
settingWnd.getItemSelection(ITEM_SDSAVE),
#elif defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
2,
#endif
settingWnd.getItemSelection(ITEM_LANGUAGE)
);
saveManager().updateCustomSaveList( _romInfo.saveInfo() );
}
void cRomInfoWnd::pressCopySlot(void)
{
if(_settingWnd)
{
u8 slot=_settingWnd->getItemSelection(ITEM_SAVESLOT);
std::string saveSrc=cSaveManager::generateSaveName(_fullName,slot);
struct stat st;
if(0==stat(saveSrc.c_str(),&st))
{
std::vector<std::string> values;
std::string slotValue,srcValue;
for(size_t ii=0;ii<4;++ii)
{
if(ii) slotValue='0'+ii;
else slotValue=LANG("save type","default");
if(slot!=ii)
{
if(SlotExists(ii)) slotValue+="*";
values.push_back(slotValue);
}
else srcValue=slotValue;
}
cSettingWnd settingWnd(0,0,252,188,NULL,LANG("saveslot","title")+": "+srcValue);
settingWnd.addSettingItem(LANG("saveslot","target slot" ),values,0);
settingWnd.setConfirmMessage(LANG("saveslot","confirm"));
u32 ret=settingWnd.doModal();
if(ret==ID_CANCEL) return;
u8 new_slot=settingWnd.getItemSelection(0,0);
if(new_slot>=slot) ++new_slot;
std::string saveDst=cSaveManager::generateSaveName(_fullName,new_slot);
copyFile(saveSrc,saveDst,false,st.st_size);
}
}
}
void cRomInfoWnd::pressFlash(void)
{
if(_romInfo.isGbaRom())
{
CGbaLoader(_fullName).Load(true,true);
}
}
void cRomInfoWnd::pressCopy(void)
{
if(_romInfo.isGbaRom()&&CGbaLoader::CheckPSRAM(_size))
{
CGbaLoader(_fullName).Load(false,true);
}
}
void cRomInfoWnd::pressCheats(void)
{
if(!_romInfo.isDSRom()||_romInfo.isHomebrew()) return;
showCheats(_fullName);
}
void cRomInfoWnd::showCheats(const std::string& aFileName)
{
u32 w=256;
u32 h=179;
cCheatWnd cheatWnd((256-w)/2,(192-h)/2,w,h,NULL,LANG("cheats","title"));
if(cheatWnd.parse(aFileName)) cheatWnd.doModal();
}
void cRomInfoWnd::addCode(void)
{
char gameCode[5];
memcpy(gameCode,_romInfo.saveInfo().gameCode,sizeof(_romInfo.saveInfo().gameCode));
gameCode[4]=0;
if(_saveTypeText.length()) _saveTypeText+=", ";
_saveTypeText+=formatString(LANG("rom info","game code").c_str(),gameCode);
if(_romInfo.version()>0)
{
_saveTypeText+=formatString("v%02d",_romInfo.version());
}
}
bool cRomInfoWnd::SlotExists(u8 slot)
{
std::string save=cSaveManager::generateSaveName(_fullName,slot);
if(_saves)
{
if(_saves->size()&&akui::binary_find(_saves->begin(),_saves->end(),save,stringComp)!=_saves->end()) return true;
}
else
{
struct stat st;
if(0==stat(save.c_str(),&st)) return true;
}
return false;
}

118
arm9/source/rominfownd.h Normal file
View File

@ -0,0 +1,118 @@
/*
rominfownd.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ROMINFOWND_H_
#define _ROMINFOWND_H_
#include "form.h"
#include "formdesc.h"
#include "spinbox.h"
#include "statictext.h"
#include "message.h"
#include <string>
#include "dsrom.h"
#include "settingwnd.h"
class cRomInfoWnd : public akui::cForm
{
public:
cRomInfoWnd( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const std::string & text );
~cRomInfoWnd();
public:
void draw();
bool process( const akui::cMessage & msg );
cWindow& loadAppearance(const std::string& aFileName );
void setFileInfo( const std::string & fullName, const std::string & showName );
void setRomInfo( const DSRomInfo & romInfo );
const DSRomInfo & getRomInfo();
void setSaves(const std::vector<std::string>* saves);
bool SlotExists(u8 slot);
static void showCheats(const std::string& aFileName);
protected:
void setDiskInfo(void);
void pressFlash(void);
void pressSaveType(void);
void pressCopy(void);
void pressCheats(void);
void pressCopySlot(void);
bool processKeyMessage( const akui::cKeyMessage & msg );
void onOK();
void onShow();
void addCode(void);
akui::cButton _buttonOK;
akui::cButton _buttonSaveType;
akui::cButton _buttonFlash;
akui::cButton _buttonCopy;
akui::cButton _buttonCheats;
akui::cFormDesc _renderDesc;
DSRomInfo _romInfo;
std::string _romInfoText;
std::string _filenameText;
std::string _fileDateText;
std::string _fileSizeText;
std::string _saveTypeText;
std::string _fullName;
u32 _size;
cSettingWnd* _settingWnd;
const std::vector<std::string>* _saves;
};
#endif//_ROMINFOWND_H_

408
arm9/source/romlauncher.cpp Normal file
View File

@ -0,0 +1,408 @@
/*
romlauncher.cpp
Copyright (C) 2010 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "iocmn.h"
#include "romlauncher.h"
#include "../../share/flags.h"
#include "language.h"
#include "save64m.h"
#include "exptools.h"
#include "romloader.h"
#include "sdidentify.h"
#include "cheatwnd.h"
#if defined(_STORAGE_rpg)
static bool OnlySDGame(u32 aGameCode)
{
if(0x45444759==aGameCode) //YGDE: 2209 - Diary Girl (USA)
{
return false;
}
switch(aGameCode&0xffffff)
{
case 0x385959: //YY8*: 2436 - Kakushi E Mystery - Riku to Yohan - Kieta 2-mai no E (Japan)
case 0x425841: //AXB*: 2385 - Daigassou! Band-Brothers DX (Japan)
case 0x425855: //UXB*: 4950 - Jam with the Band (Europe) (En,Fr,De,Es,It)
case 0x524f55: //UOR*: 3690 - Made in Ore (Japan) & 4812 - WarioWare D.I.Y. (USA) & 4913 - WarioWare - Do It Yourself (Europe) (En,Fr,De,Es,It)
case 0x414156: //VAA*: 5054 - Eigokoro Kyoushitsu DS (Japan) (NDSi Enhanced)
case 0x444759: //YGD*: 3453 - Winx Club - Secret Diary 2009 (Europe) (En,Fr,De,Es,It)
case 0x565042: //BPV*: 4244 - Puzzler World (Europe) (En,Fr,De,Es,It)
return true;
}
return false;
}
#endif
static SAVE_TYPE PrefillGame(u32 aGameCode)
{
if(0x45444759==aGameCode) //YGDE: 2209 - Diary Girl (USA)
{
//usa game dont have 16M save
return ST_UNKNOWN;
}
switch(aGameCode&0xffffff)
{
case 0x385959: //YY8*: 2436 - Kakushi E Mystery - Riku to Yohan - Kieta 2-mai no E (Japan)
return ST_64K;
#if defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
case 0x533243: //C2S*: Pokemon Mystery Dungeon - Explorers of Sky
return ST_1M;
#endif
case 0x593241: //A2Y*: Ganbaru Watashi no Kakei Diary
case 0x4c5a41: //AZL*: Nintendo Presents - Style Boutique
case 0x494b42: //BKI*: Legend of Zelda, The - Spirit Tracks
case 0x503643: //C6P*: Picross 3D
case 0x574d49: //IMW*: Walk with Me!
case 0x4e4259: //YBN*: 100 Classic Book Collection
case 0x544556: //VET*: 1000 Cooking Recipes from Elle a Table
return ST_8M;
case 0x444759: //YGD*: Winx Club - Secret Diary 2009
case 0x565042: //BPV*: Puzzler World
return ST_16M;
case 0x425841: //AXB*: Daigassou! Band-Brothers DX
case 0x414156: //VAA*: Eigokoro Kyoushitsu DS
return ST_64M;
}
return ST_UNKNOWN;
}
static u32 SaveMask(SAVE_TYPE st)
{
u32 result;
switch(st)
{
case ST_NOSAVE:
result=PATCH_SAVE_NO;
break;
case ST_4K:
result=0;
break;
case ST_64K:
result=4;
break;
case ST_512K:
result=7;
break;
case ST_1M:
result=8;
break;
case ST_2M:
result=9;
break;
case ST_4M:
result=10;
break;
case ST_8M:
result=11;
break;
case ST_16M:
result=12;
break;
case ST_32M:
result=13;
break;
case ST_64M:
result=14;
break;
default:
result=10; //4M default
break;
}
return result;
}
static u32 SaveSize(SAVE_TYPE st)
{
u32 result;
switch(st)
{
case ST_NOSAVE:
result=0;
break;
case ST_4K:
result=512;
break;
case ST_64K:
result=8192;
break;
case ST_512K:
result=65536;
break;
case ST_1M:
result=131072;
break;
case ST_2M:
result=262144;
break;
case ST_4M:
result=524288;
break;
case ST_8M:
result=1048576;
break;
case ST_16M:
result=2097152;
break;
case ST_32M:
result=4194304;
break;
case ST_64M:
result=8388608;
break;
default:
result=524288; //4M default
break;
};
return result;
}
TLaunchResult launchRom(const std::string& aFullPath,DSRomInfo& aRomInfo,bool aMenu)
{
u32 flags=0;
long cheatOffset=0; size_t cheatSize=0;
#if defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
std::string saveName;
#endif
if(!aRomInfo.isHomebrew())
{
u32 gameCode;
memcpy(&gameCode,aRomInfo.saveInfo().gameCode,sizeof(gameCode)); //because alignment
bool isBigSave=false;
u32 bigSaveSize=8*1024*1024;
u32 bigSaveMask=14;
// reading speed setting
std::string disk=aFullPath.substr(0,5);
bool dma=false,protection=aRomInfo.saveInfo().isProtection(); u32 speed=0;
int mount=0;
#if defined(_STORAGE_rpg)
if(disk=="fat0:"||disk=="FAT0:") // if we are using internal NAND flash, use fast reading setting
{
speed=0xd0;
if(OnlySDGame(gameCode))
{
return ELaunchSDOnly;
}
}
else if(disk=="fat1:"||disk=="FAT1:") // check sd card, warn user if sd card is not suitable for running offical ds program
#endif
{
if(protection) speed=0x1fff;
mount=ioSD();
dma=aRomInfo.saveInfo().isDMA();
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
if(dma)
#endif
{
flags|=PATCH_DMA;
}
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
else
{
u32 sdSpeed=sdidCheckSDSpeed(8192);
if(sdSpeed>=0x2000)
{
return ELaunchSlowSD;
}
else
{
speed=(sdSpeed&0x1fff);
}
}
#endif
/*
if((gameCode&0xffffff)==0x425841) //2385 - Daigassou! Band-Brothers DX (Japan)
{
isBigSave=true;
}
if((gameCode&0xffffff)==0x414156) //5054 - Eigokoro Kyoushitsu DS (Japan) (NDSi Enhanced)
{
isBigSave=true;
}
*/
if((gameCode&0xffffff)==0x425855) //4950 - Jam with the Band (Europe) (En,Fr,De,Es,It)
{
isBigSave=true;
bigSaveSize=32*1024*1024;
bigSaveMask=0;
}
if((gameCode&0xffffff)==0x524f55) //3690 - Made in Ore (Japan) & 4812 - WarioWare D.I.Y. (USA)
{
isBigSave=true;
bigSaveSize=32*1024*1024;
bigSaveMask=0;
}
}
#if defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
saveName=cSaveManager::generateSaveName(aFullPath,aRomInfo.saveInfo().getSlot());
#endif
if(isBigSave)
{
isBigSave=cSaveManager::initializeSaveFile(aFullPath,aRomInfo.saveInfo().getSlot(),bigSaveSize);
if(!isBigSave) return ELaunchNoFreeSpace;
}
if
(
isBigSave
#if defined(_STORAGE_rpg)
&&cSave64m::GenerateSaveMap(aFullPath,aRomInfo.saveInfo().getSlot())
#endif
)
{
flags|=PATCH_SD_SAVE|(bigSaveMask<<PATCH_SAVE_SHIFT);
#if defined(_STORAGE_rpg)
saveManager().restoreSaveData(aFullPath.c_str(),ST_NOSAVE,aRomInfo.saveInfo().getSlot());
if(!dma) speed=0x1fff;
#elif defined(_STORAGE_r4)
saveManager().saveLastInfo(aFullPath);
if(!bigSaveMask) //MiO
{
if(!cSave64m::GenerateSaveMap(saveName)) return ELaunchNoFreeSpace;
}
#elif defined(_STORAGE_ak2i)
saveManager().saveLastInfo(aFullPath);
if(!dma) speed=0x1fff;
#elif defined(_STORAGE_r4idsn)
saveManager().saveLastInfo(aFullPath);
#endif
}
else
{
// restore save data only for offical programs
SAVE_TYPE st=(SAVE_TYPE)aRomInfo.saveInfo().saveType;
if(ST_UNKNOWN==st) st=ST_AUTO;
SAVE_TYPE st_new=PrefillGame(gameCode);
if(st_new!=ST_UNKNOWN) //special save size
{
if(st_new!=st)
{
st=st_new;
aRomInfo.saveInfo().saveType=st;
saveManager().updateCustomSaveList(aRomInfo.saveInfo());
}
}
#if defined(_STORAGE_rpg)
if(ioSD()==mount&&(aRomInfo.saveInfo().isSDSave()||OnlySDGame(gameCode)))
#endif
{
if
(
cSaveManager::initializeSaveFile(aFullPath,aRomInfo.saveInfo().getSlot(),SaveSize(st))
#if defined(_STORAGE_rpg)
&&cSave64m::GenerateSaveMap(aFullPath,aRomInfo.saveInfo().getSlot())
#endif
)
{
flags|=PATCH_SD_SAVE|(SaveMask(st)<<PATCH_SAVE_SHIFT);
#if defined(_STORAGE_rpg)
saveManager().restoreSaveData(aFullPath.c_str(),ST_NOSAVE,aRomInfo.saveInfo().getSlot());
if(!dma) speed=0x1fff;
#elif defined(_STORAGE_r4) || defined(_STORAGE_r4idsn)
saveManager().saveLastInfo(aFullPath);
#elif defined(_STORAGE_ak2i)
saveManager().saveLastInfo(aFullPath);
if(!dma) speed=0x1fff;
#endif
}
else
{
return ELaunchNoFreeSpace;
}
}
#if defined(_STORAGE_rpg)
else
{
if(!saveManager().restoreSaveData(aFullPath.c_str(),st,aRomInfo.saveInfo().getSlot()))
{
return ELaunchRestoreFail;
}
}
#endif
}
__NDSHeader->cardControl13=0x00406000|speed;
//3in1 support
if(gameCode==0x4a524255||gameCode==0x50524255)
{
expansion().SoftReset();
cExpansion::SetRompage(0x300);
cExpansion::OpenNorWrite();
cExpansion::EnableBrowser();
}
if(aRomInfo.saveInfo().getRumble())
{
expansion().SoftReset();
cExpansion::SetShake(0xEF+aRomInfo.saveInfo().getRumble());
}
if(aRomInfo.saveInfo().isDownloadPlay()) flags|=PATCH_DOWNLOAD_PLAY;
if(aRomInfo.saveInfo().isCheat())
{
u32 gameCode,crc32;
if(cCheatWnd::romData(aFullPath,gameCode,crc32))
{
FILE* dat=fopen(SFN_CHEATS,"rb");
if(dat)
{
if(cCheatWnd::searchCheatData(dat,gameCode,crc32,cheatOffset,cheatSize))
{
flags|=PATCH_CHEATS;
}
fclose(dat);
}
}
}
if(aRomInfo.saveInfo().isSoftReset()) flags|=PATCH_SOFT_RESET;
if(expansion().Rampage()==cExpansion::EPsramPage) flags|=PATCH_PSRAM;
#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i)
if(protection)
{
u32 bytesPerCluster;
if(ELM_ClusterSizeFromDisk(mount,&bytesPerCluster)&&cSaveManager::generateProtectionFix(aFullPath,bytesPerCluster))
{
flags|=PATCH_PROTECTION;
}
}
#endif
if(aRomInfo.saveInfo().isLinkage()) flags|=PATCH_LINKAGE;
u8 language=aRomInfo.saveInfo().getLanguage();
if(language) flags|=(language<<PATCH_LANGUAGE_SHIFT)&PATCH_LANGUAGE_MASK;
}
else
{
if(!aMenu) saveManager().saveLastInfo(aFullPath);
const u16 lameboy[]={'L','a','m','e','b','o','y'};
if(memcmp(aRomInfo.banner().titles[0],lameboy,sizeof(lameboy))==0)
{
expansion().SoftReset();
cExpansion::SetShake(0xF0);
}
if(gs().homebrewreset) flags|=PATCH_SOFT_RESET;
}
#if defined(_STORAGE_rpg)
loadRom(aFullPath,flags,cheatOffset,cheatSize);
#elif defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
loadRom(aFullPath,saveName,flags,cheatOffset,cheatSize);
#endif
return ELaunchRomOk;
}
void autoLaunchRom(const std::string& aFullPath)
{
DSRomInfo rominfo;
rominfo.MayBeDSRom(aFullPath);
if(rominfo.isDSRom()) launchRom(aFullPath,rominfo,false);
}

36
arm9/source/romlauncher.h Normal file
View File

@ -0,0 +1,36 @@
/*
romlauncher.h
Copyright (C) 2010 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ROMLAUNCHER_H__
#define __ROMLAUNCHER_H__
#include "dsrom.h"
enum TLaunchResult
{
ELaunchRomOk,
ELaunchSDOnly,
ELaunchRestoreFail,
ELaunchSlowSD,
ELaunchNoFreeSpace
};
TLaunchResult launchRom(const std::string& aFullPath,DSRomInfo& aRomInfo,bool aMenu);
void autoLaunchRom(const std::string& aFullPath);
#endif

103
arm9/source/romloader.cpp Normal file
View File

@ -0,0 +1,103 @@
/*
romloader.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <nds.h>
#include <elm.h>
#include "romloader.h"
#include "dbgtool.h"
#include "akloader_arm7_bin.h"
#include "akloader_arm9_bin.h"
#include "savechip.h"
#include "savemngr.h"
#include "../../share/fifotool.h"
#include "../../share/timetool.h"
#include "globalsettings.h"
#if defined(_STORAGE_rpg)
#include <iorpg.h>
#endif
static void resetAndLoop()
{
// Interrupt
REG_IME = 0;
REG_IE = 0;
REG_IF = ~0;
DC_FlushAll();
DC_InvalidateAll();
fifoSendValue32(FIFO_USER_01,MENU_MSG_ARM7_REBOOT);
while(true)
{
while(REG_IPC_FIFO_CR&IPC_FIFO_RECV_EMPTY);
u32 res=REG_IPC_FIFO_RX;
if(FIFO_PACK_VALUE32(FIFO_USER_01,MENU_MSG_ARM7_READY_BOOT)==res) break;
}
swiSoftReset();
}
#if defined(_STORAGE_rpg)
bool loadRom( const std::string & filename, u32 flags, long cheatOffset,size_t cheatSize )
#elif defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
bool loadRom( const std::string & filename, const std::string & savename, u32 flags, long cheatOffset,size_t cheatSize )
#endif
{
#if defined(_STORAGE_rpg)
// copy filename to sram
ALIGN(4) u8 filenameBuffer[MAX_FILENAME_LENGTH];
memset( filenameBuffer, 0, MAX_FILENAME_LENGTH );
memcpy( filenameBuffer, filename.c_str(), filename.length() );
u32 address=SRAM_LOADING_FILENAME_START;
ioRpgWriteSram( address, filenameBuffer, MAX_FILENAME_LENGTH );
address+=MAX_FILENAME_LENGTH;
ioRpgWriteSram( address, &flags, sizeof(flags) );
address+=sizeof(u32);
ioRpgWriteSram( address, &cheatOffset, sizeof(cheatOffset) );
address+=sizeof(u32);
ioRpgWriteSram( address, &cheatSize, sizeof(cheatSize) );
#elif defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
*(u32*)0x23fd900=flags;
*(u32*)0x23fd904=cheatOffset;
*(u32*)0x23fd908=cheatSize;
memset((void*)0x23fda00,0,MAX_FILENAME_LENGTH*2);
strcpy((char*)0x23fda00,filename.c_str());
strcpy((char*)(0x23fda00+MAX_FILENAME_LENGTH),savename.c_str());
#endif
dbg_printf( "load %s\n", filename.c_str() );
// copy loader's arm7 code
memcpy( (void *)0x023FA000, akloader_arm7_bin, akloader_arm7_bin_size );
__NDSHeader->arm7executeAddress = 0x023FA000;
// copy loader's arm9 code
memcpy( (void *)0x023c0000, akloader_arm9_bin, akloader_arm9_bin_size );
__NDSHeader->arm9executeAddress = 0x023c0000;
dbg_printf( "load done\n" );
ELM_Unmount();
resetAndLoop();
return true;
}

32
arm9/source/romloader.h Normal file
View File

@ -0,0 +1,32 @@
/*
romloader.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ROMLOADER_H_
#define _ROMLOADER_H_
#include <string>
#if defined(_STORAGE_rpg)
bool loadRom( const std::string & filename, u32 flags, long cheatOffset,size_t cheatSize );
#elif defined(_STORAGE_r4) || defined(_STORAGE_ak2i) || defined(_STORAGE_r4idsn)
bool loadRom( const std::string & filename, const std::string & savename, u32 flags, long cheatOffset,size_t cheatSize );
#endif
#endif//_ROMLOADER_H_

105
arm9/source/save64m.cpp Normal file
View File

@ -0,0 +1,105 @@
/*
save64m.cpp
Copyright (C) 2008 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#if defined(_STORAGE_rpg) || defined(_STORAGE_r4)
#include "save64m.h"
#include <fcntl.h>
#include <unistd.h>
#include "dbgtool.h"
#include "../../share/memtool.h"
#if defined(_STORAGE_rpg)
#include "savemngr.h"
#include <iorpg.h>
#elif defined(_STORAGE_r4)
#include <ior4.h>
#endif
void cSave64m::IterateFileCluster(int aFileDes,u32* aFatMap)
{
u32 sectorsPerCluster;
u32 shift=isSDHC()?0:9;
if(ELM_SectorsPerClusterFromHandle(aFileDes,&sectorsPerCluster))
{
u32 cluster=1;
while(true)
{
u32 sector;
cluster=ELM_GetFAT(aFileDes,cluster,&sector);
if(!cluster) break;
for(u32 ii=0;ii<sectorsPerCluster;ii++)
*aFatMap++=(sector+ii)<<shift;
}
}
}
bool cSave64m::GenerateSaveMapInternal(const char* aPath,u32* aFatMap)
{
int fd=open(aPath,O_RDONLY);
if(fd<0) return false;
IterateFileCluster(fd,aFatMap);
close(fd);
return true;
}
#if defined(_STORAGE_rpg)
bool cSave64m::GenerateSaveMap(const std::string& aRomFilename,u8 aSlot)
{
bool res=false;
u32* buffer=new u32[KMaxSave];
fillMemory(buffer,KMaxSave*sizeof(u32),0xffffffff);
std::string saveFilename=cSaveManager::generateSaveName(aRomFilename,aSlot);
if(GenerateSaveMapInternal(saveFilename.c_str(),buffer))
{
u32 saveMapAddress=SRAM_SAVEDATA_START;
for(u32 ii=0;ii<KMaxSave;++ii)
{
ioRpgWriteSram(saveMapAddress+ii*4,buffer+ii,sizeof(u32));
}
res=true;
}
delete[] buffer;
return res;
}
#elif defined(_STORAGE_r4)
bool cSave64m::GenerateSaveMap(std::string& aSaveName)
{
bool success=false;
std::string result=aSaveName;
u32* buffer=new u32[KMaxSave];
fillMemory(buffer,KMaxSave*sizeof(u32),0xffffffff);
if(GenerateSaveMapInternal(aSaveName.c_str(),buffer))
{
result+=".fix";
int f=open(result.c_str(),O_WRONLY|O_CREAT|O_TRUNC);
if(f>=0)
{
if(write(f,buffer,KMaxSave*sizeof(u32))==KMaxSave*sizeof(u32))
{
success=true;
aSaveName=result;
}
close(f);
}
}
return success;
}
#endif
#endif

51
arm9/source/save64m.h Normal file
View File

@ -0,0 +1,51 @@
/*
save64m.h
Copyright (C) 2008 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SAVE64M_H__
#define __SAVE64M_H__
#include <nds.h>
#include <elm.h>
#if defined(_STORAGE_rpg) || defined(_STORAGE_r4)
#include <sys/iosupport.h>
#include <string>
class cSave64m
{
private:
enum
{
KMaxSave=(32*1024*1024)/512 //32 megabytes
};
private:
static void IterateFileCluster(int aFileDes,u32* aFatMap);
static bool GenerateSaveMapInternal(const char* aPath,u32* aFatMap);
public:
#if defined(_STORAGE_rpg)
static bool GenerateSaveMap(const std::string& aRomFilename,u8 aSlot);
#elif defined(_STORAGE_r4)
static bool GenerateSaveMap(std::string& aSaveName);
#endif
};
#endif
#endif

489
arm9/source/savechip.cpp Normal file
View File

@ -0,0 +1,489 @@
/*
savechip.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 3 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, see <http://www.gnu.org/licenses/>.
*/
#if defined(_STORAGE_rpg)
#include <cstring>
#include "savechip.h"
#include "dbgtool.h"
#include "rpgprotocol.h"
#include "diskicon.h"
#define EepromWaitBusy() while (REG_AUXSPICNT & /*BUSY*/0x80);
//void saveChipReadEeprom(u32 address, u8 *data, u32 length, u8 chipType);
void saveChipWriteT1(u32 address, u8 *apData, u32 aLength, u8 chipType);
void saveChipWriteT2(u32 address, u8 *apData, u32 aLength, u8 chipType);
void saveChipWriteT3(u32 address, u8 *apData, u32 aLength, u8 chipType);
u8 saveChipCMD( u8 cmd, u32 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 saveChipReadID(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;
}
u8 saveChipGetType(void)
{
u8 c00;
u8 c05;
u8 c9f;
u8 c03;
REG_EXMEMCNT &= ~0x0880; // DS Card access ARM9:bit11=0 GBA Cart access ARM9:bit7=0
c03=saveChipCMD(0x03,0);
c05=saveChipCMD(0x05,0);
c9f=saveChipCMD(0x9f,0);
c00=saveChipCMD(0x00,0);
if((c00==0x00) && (c9f==0x00))return 0; // 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
return 0;
}
u32 saveChipSizeT3(void)
{
u8 c9f;
c9f=saveChipCMD(0x9f,0);
if(c9f==0x12) {
return 256*1024; // TYPE 3 2Mbit(256KByte)
}
if(c9f==0x13) {
return 512*1024; // NEW TYPE 3+ 4Mbit(512KByte)
}
if(c9f==0x14) {
return 1024*1204; // NEW TYPE 3++ 8Mbit(512KByte)
}
return 0;
}
int saveChipSizeT2(void)
{
int tp=2;
#define OFOT0 (8*1024-1) // 8KBの末端
#define OFOT1 (2*8*1024-1) // 16KBの末端
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
saveChipRead(OFOT0,buf1,1,tp);
saveChipRead(OFOT1,buf2,1,tp);
buf3[0]=~buf1[0];
saveChipWrite(OFOT0,buf3,1,tp);
saveChipRead(OFOT1,buf4,1,tp);
saveChipWrite(OFOT0,buf1,1,tp);
if(buf4[0]!=buf2[0]) // +8kも書き換わっている
{
return 8*1024; // 8KB(64kbit)
}
return 64*1024; // 64KB(512kbit)
}
u32 saveChipSize(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)
{
return saveChipSizeT2();
}
if(tp==3)
{
return saveChipSizeT3();
}
tp++;
return eepsz[tp];
}
return 0;
}
//////////////////////////////////////////////////////////////////////
void saveChipRead( u32 address, u8 *data, u32 length, u8 chipType )
{
REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40;
// REG_AUXSPICNT = 0xFFFF;
REG_AUXSPIDATA = 0x03 | ((chipType == 1) ? address>>8<<3 : 0);
EepromWaitBusy();
if (chipType == 3)
{
REG_AUXSPIDATA = (address >> 16) & 0xFF;
EepromWaitBusy();
}
if (chipType >= 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;
}
//////////////////////////////////////////////////////////////////////
void saveChipWrite( u32 address, u8 *apData, u32 aLength, u8 chipType )
{
switch(chipType)
{
case 1:
saveChipWriteT1(address,apData,aLength,chipType);
return;
case 2:
saveChipWriteT2(address,apData,aLength,chipType);
return;
case 3:
saveChipWriteT3(address,apData,aLength,chipType);
return;
}
}
#define T1BLOCKSZ (16)
// TYPE1 4kbit EEPROM
void saveChipWriteT1(u32 address, u8 *apData, u32 aLength, u8 chipType)
{
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 saveChipWriteT2(u32 address, u8 *apData, u32 aLength, u8 chipType)
{
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 < 128; 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 saveChipWriteT3(u32 address, u8 *apData, u32 aLength, u8 chipType)
{
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;
}
}
void saveChipEEPROMErase( int type )
{
u32 save_size = 0;
if( 1 == type ) save_size = 512;
if( 2 == type ) save_size = 65536;
if( 0 == save_size )
return ;
u8 * buffer = new u8[save_size];
memset( buffer, 0xff, save_size );
saveChipWrite( 0, buffer, save_size, type );
delete[] buffer;
}
// Chip Erase NEW : clear FLASH MEMORY (TYPE 3 ONLY)
int saveChipFlashErase(u32 sectorCount)
{
for(u32 ii=0;ii<sectorCount;++ii)
{
saveChipSectorErase(0x10000*ii);
diskIcon().blink();
}
return 0;
}
// COMMAND Sec.erase 0xD8
void saveChipSectorErase(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;
}
// Chip Erase : clear FLASH MEMORY (TYPE 3 ONLY)
// COMMAND 0xC7
int saveChipFlashErase2(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;
}
//////////////////////////////////////////////////////////////////////
#endif

Some files were not shown because too many files have changed in this diff Show More