mirror of
https://github.com/coderkei/akmenu-next.git
synced 2025-06-18 08:55:46 -04:00
Extract akmenu4 from woodrpg v1.25
This commit is contained in:
parent
f33df81056
commit
6fe395b92f
114
Makefile
Normal file
114
Makefile
Normal 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
BIN
akmenu4.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 630 B |
137
arm7/Makefile
Normal file
137
arm7/Makefile
Normal 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
|
||||
#---------------------------------------------------------------------------------------
|
104
arm7/source/crt/ds_arm7_crt1.s
Normal file
104
arm7/source/crt/ds_arm7_crt1.s
Normal 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
178
arm7/source/main.cpp
Normal 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
198
arm7/specs/ds_arm7.ld
Normal 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
8
arm7/specs/ds_arm7.specs
Normal 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
150
arm9/Makefile
Normal 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
|
||||
#---------------------------------------------------------------------------------------
|
BIN
arm9/data/akloader_public/akloader_arm7.bin
Normal file
BIN
arm9/data/akloader_public/akloader_arm7.bin
Normal file
Binary file not shown.
BIN
arm9/data/akloader_public/akloader_arm9.bin
Normal file
BIN
arm9/data/akloader_public/akloader_arm9.bin
Normal file
Binary file not shown.
BIN
arm9/data/akloader_public_0911/akloader_arm7.bin
Normal file
BIN
arm9/data/akloader_public_0911/akloader_arm7.bin
Normal file
Binary file not shown.
BIN
arm9/data/akloader_public_0911/akloader_arm9.bin
Normal file
BIN
arm9/data/akloader_public_0911/akloader_arm9.bin
Normal file
Binary file not shown.
BIN
arm9/data/discarded/file_banner.bin
Normal file
BIN
arm9/data/discarded/file_banner.bin
Normal file
Binary file not shown.
BIN
arm9/data/discarded/unknown_banner.bin
Normal file
BIN
arm9/data/discarded/unknown_banner.bin
Normal file
Binary file not shown.
BIN
arm9/data/folder_banner.bin
Normal file
BIN
arm9/data/folder_banner.bin
Normal file
Binary file not shown.
BIN
arm9/data/gba_banner.bin
Normal file
BIN
arm9/data/gba_banner.bin
Normal file
Binary file not shown.
BIN
arm9/data/gba_nes_patch.bin
Normal file
BIN
arm9/data/gba_nes_patch.bin
Normal file
Binary file not shown.
BIN
arm9/data/gba_sleep_patch.bin
Normal file
BIN
arm9/data/gba_sleep_patch.bin
Normal file
Binary file not shown.
BIN
arm9/data/gbarom_banner.bin
Normal file
BIN
arm9/data/gbarom_banner.bin
Normal file
Binary file not shown.
1
arm9/data/icon_bg.bin
Normal file
1
arm9/data/icon_bg.bin
Normal 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ηφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφήφή
|
BIN
arm9/data/microsd_banner.bin
Normal file
BIN
arm9/data/microsd_banner.bin
Normal file
Binary file not shown.
BIN
arm9/data/nand_banner.bin
Normal file
BIN
arm9/data/nand_banner.bin
Normal file
Binary file not shown.
BIN
arm9/data/nds_banner.bin
Normal file
BIN
arm9/data/nds_banner.bin
Normal file
Binary file not shown.
BIN
arm9/data/nds_save_banner.bin
Normal file
BIN
arm9/data/nds_save_banner.bin
Normal file
Binary file not shown.
BIN
arm9/data/unknown_banner.bin
Normal file
BIN
arm9/data/unknown_banner.bin
Normal file
Binary file not shown.
BIN
arm9/data/unknown_nds_banner.bin
Normal file
BIN
arm9/data/unknown_nds_banner.bin
Normal file
Binary file not shown.
72
arm9/source/animation.cpp
Normal file
72
arm9/source/animation.cpp
Normal 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
80
arm9/source/animation.h
Normal 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
129
arm9/source/bigclock.cpp
Normal 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
70
arm9/source/bigclock.h
Normal 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
151
arm9/source/bmp15.cpp
Normal 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
73
arm9/source/bmp15.h
Normal 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
160
arm9/source/calendar.cpp
Normal 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
77
arm9/source/calendar.h
Normal 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_
|
56
arm9/source/calendarwnd.cpp
Normal file
56
arm9/source/calendarwnd.cpp
Normal 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
55
arm9/source/calendarwnd.h
Normal 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
509
arm9/source/cheatwnd.cpp
Normal 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
101
arm9/source/cheatwnd.h
Normal 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
121
arm9/source/crtsmall.cpp
Normal 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
97
arm9/source/datetime.cpp
Normal 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
57
arm9/source/datetime.h
Normal 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
78
arm9/source/dbgtool.h
Normal 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
89
arm9/source/diskicon.cpp
Normal 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
64
arm9/source/diskicon.h
Normal 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
19
arm9/source/dslight.h
Normal 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
290
arm9/source/dsrom.cpp
Normal 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
75
arm9/source/dsrom.h
Normal 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
370
arm9/source/exptools.cpp
Normal 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
69
arm9/source/exptools.h
Normal 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
251
arm9/source/expwnd.cpp
Normal 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
61
arm9/source/expwnd.h
Normal 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
73
arm9/source/favorites.cpp
Normal 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
33
arm9/source/favorites.h
Normal 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
115
arm9/source/fileicons.cpp
Normal 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
64
arm9/source/fileicons.h
Normal 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
516
arm9/source/files.cpp
Normal 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( ©Length, 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
55
arm9/source/files.h
Normal 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
106
arm9/source/font/font.cpp
Normal 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
44
arm9/source/font/font.h
Normal 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_
|
325
arm9/source/font/font_pcf.cpp
Normal file
325
arm9/source/font/font_pcf.cpp
Normal 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;
|
||||
}
|
86
arm9/source/font/font_pcf.h
Normal file
86
arm9/source/font/font_pcf.h
Normal 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
|
94
arm9/source/font/font_pcf_internals.h
Normal file
94
arm9/source/font/font_pcf_internals.h
Normal 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
|
43
arm9/source/font/fontfactory.cpp
Normal file
43
arm9/source/font/fontfactory.cpp
Normal 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());
|
||||
}
|
46
arm9/source/font/fontfactory.h
Normal file
46
arm9/source/font/fontfactory.h
Normal 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
471
arm9/source/gbaloader.cpp
Normal 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
46
arm9/source/gbaloader.h
Normal 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
50
arm9/source/gbanes.cpp
Normal 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
1829
arm9/source/gbapatcher.cpp
Normal file
File diff suppressed because it is too large
Load Diff
157
arm9/source/gbapatcher.h
Normal file
157
arm9/source/gbapatcher.h
Normal 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
286
arm9/source/gbasleep.cpp
Normal 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&®_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
672
arm9/source/gdi.cpp
Normal 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
151
arm9/source/gdi.h
Normal 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_
|
177
arm9/source/globalsettings.cpp
Normal file
177
arm9/source/globalsettings.cpp
Normal 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
|
102
arm9/source/globalsettings.h
Normal file
102
arm9/source/globalsettings.h
Normal 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
133
arm9/source/helpwnd.cpp
Normal 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
65
arm9/source/helpwnd.h
Normal 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
39
arm9/source/icons.cpp
Normal 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
30
arm9/source/icons.h
Normal 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
396
arm9/source/inifile.cpp
Normal 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
66
arm9/source/inifile.h
Normal 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
32
arm9/source/iocmn.h
Normal 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
105
arm9/source/irqs.cpp
Normal 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
57
arm9/source/irqs.h
Normal 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
26
arm9/source/language.cpp
Normal 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
50
arm9/source/language.h
Normal 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
266
arm9/source/main.cpp
Normal 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
575
arm9/source/mainlist.cpp
Normal 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
158
arm9/source/mainlist.h
Normal 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
909
arm9/source/mainwnd.cpp
Normal 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
108
arm9/source/mainwnd.h
Normal 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
29
arm9/source/padding.s
Normal 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
617
arm9/source/rominfownd.cpp
Normal 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
118
arm9/source/rominfownd.h
Normal 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
408
arm9/source/romlauncher.cpp
Normal 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
36
arm9/source/romlauncher.h
Normal 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
103
arm9/source/romloader.cpp
Normal 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
32
arm9/source/romloader.h
Normal 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
105
arm9/source/save64m.cpp
Normal 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,§orsPerCluster))
|
||||
{
|
||||
u32 cluster=1;
|
||||
while(true)
|
||||
{
|
||||
u32 sector;
|
||||
cluster=ELM_GetFAT(aFileDes,cluster,§or);
|
||||
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
51
arm9/source/save64m.h
Normal 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
489
arm9/source/savechip.cpp
Normal 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
Loading…
Reference in New Issue
Block a user