From a7dd6151a430f33b596fdef6916d1f3b2f7a61ff Mon Sep 17 00:00:00 2001 From: lifehackerhansol Date: Fri, 4 Oct 2024 12:08:27 -0700 Subject: [PATCH] Make it build on latest devkitARM - UTF8-ify where possible - Remove custom linkerscript - Update Makefiles - devkitPro/nds-examples@6afa09b2054c9f47685514c32873b3905721c9ee - Comment out akloader binaries - This will be reworked soon:tm: - Eradicate sdidentify - AKRPG specific - Eradicate libelm - Eradicate save64m - Eradicate file operations - Eradicate libio* - Eradicate crtsmall - Fix paths for new root drive naming in latest libfat - dsrom: fix type cast issue in homebrew check - MAX_FILENAME_LENGTH -> PATH_MAX - adapt directory listing operations to new dkP way - timer: unstaticify _factor - Remove all flashcart-specific bits - fix type of cPopMenu::itemBelowPoint - gbaloader: use updated vramSetPrimaryBanks function - Move arm9-specific headers to arm9 --- Makefile | 114 +- arm7/Makefile | 97 +- arm7/source/crt/ds_arm7_crt1.s | 104 - arm7/specs/ds_arm7.ld | 198 -- arm7/specs/ds_arm7.specs | 8 - arm9/Makefile | 121 +- arm9/data/akloader_public/akloader_arm7.bin | Bin 2600 -> 0 bytes arm9/data/akloader_public/akloader_arm9.bin | Bin 87116 -> 0 bytes .../akloader_public_0911/akloader_arm7.bin | Bin 2600 -> 0 bytes .../akloader_public_0911/akloader_arm9.bin | Bin 87116 -> 0 bytes arm9/data/discarded/file_banner.bin | Bin 2112 -> 0 bytes arm9/data/discarded/unknown_banner.bin | Bin 2112 -> 0 bytes arm9/source/bigclock.cpp | 2 +- arm9/source/bmp15.cpp | 12 +- arm9/source/bmp15.h | 2 +- arm9/source/calendar.cpp | 2 +- arm9/source/cheatwnd.cpp | 6 +- arm9/source/crtsmall.cpp | 121 - arm9/source/datetime.h | 2 +- arm9/source/diskicon.cpp | 2 +- arm9/source/dsrom.cpp | 10 +- arm9/source/expwnd.cpp | 6 +- arm9/source/fileicons.cpp | 25 +- arm9/source/files.cpp | 516 ---- arm9/source/files.h | 55 - {share => arm9/source}/flags.h | 0 arm9/source/font/font.cpp | 1 - arm9/source/font/fontfactory.h | 2 +- {share => arm9/source}/gamecode.h | 0 arm9/source/gbaloader.cpp | 7 +- arm9/source/gbaloader.h | 3 + arm9/source/gdi.cpp | 40 +- arm9/source/globalsettings.cpp | 10 - arm9/source/globalsettings.h | 4 - arm9/source/helpwnd.cpp | 6 +- arm9/source/inifile.cpp | 7 +- arm9/source/iocmn.h | 32 - arm9/source/irqs.cpp | 12 - arm9/source/main.cpp | 23 +- arm9/source/mainlist.cpp | 48 +- arm9/source/mainlist.h | 6 +- arm9/source/mainwnd.cpp | 176 +- arm9/source/padding.s | 29 - arm9/source/rominfownd.cpp | 122 +- arm9/source/rominfownd.h | 4 - arm9/source/romlauncher.cpp | 140 +- arm9/source/romloader.cpp | 60 +- arm9/source/romloader.h | 5 +- arm9/source/save64m.cpp | 105 - arm9/source/save64m.h | 51 - arm9/source/savechip.cpp | 489 ---- arm9/source/savechip.h | 47 - arm9/source/savemngr.cpp | 729 +---- arm9/source/savemngr.h | 61 - arm9/source/sdidentify.cpp | 138 - arm9/source/sdidentify.h | 39 - arm9/source/singleton.h | 4 +- arm9/source/sram.cpp | 6 +- arm9/source/startmenu.cpp | 4 - arm9/source/startmenu.h | 12 +- {share => arm9/source}/stringtool.cpp | 0 {share => arm9/source}/stringtool.h | 0 arm9/source/systemfilenames.h | 4 +- arm9/source/testcases.cpp | 347 +-- arm9/source/testcases.h | 4 - arm9/source/timer.cpp | 2 +- arm9/source/timer.h | 2 +- {share => arm9/source}/timetool.cpp | 0 {share => arm9/source}/timetool.h | 0 arm9/source/ui/bitmapdesc.h | 2 +- arm9/source/ui/button.cpp | 2 +- arm9/source/ui/button.h | 2 +- arm9/source/ui/form.cpp | 3 +- arm9/source/ui/formdesc.cpp | 4 +- arm9/source/ui/listview.cpp | 5 +- arm9/source/ui/msgbox.cpp | 20 +- arm9/source/ui/point.h | 16 +- arm9/source/ui/popmenu.cpp | 6 +- arm9/source/ui/popmenu.h | 2 +- arm9/source/ui/sigslot.h.new | 2500 ----------------- arm9/source/ui/ui.h | 5 +- arm9/source/userwnd.cpp | 2 +- arm9/source/version.h | 4 +- arm9/specs/ds_arm9.ld | 254 -- arm9/specs/ds_arm9.specs | 8 - akmenu4.bmp => icon.bmp | Bin 86 files changed, 308 insertions(+), 6711 deletions(-) delete mode 100644 arm7/source/crt/ds_arm7_crt1.s delete mode 100644 arm7/specs/ds_arm7.ld delete mode 100644 arm7/specs/ds_arm7.specs delete mode 100644 arm9/data/akloader_public/akloader_arm7.bin delete mode 100644 arm9/data/akloader_public/akloader_arm9.bin delete mode 100644 arm9/data/akloader_public_0911/akloader_arm7.bin delete mode 100644 arm9/data/akloader_public_0911/akloader_arm9.bin delete mode 100644 arm9/data/discarded/file_banner.bin delete mode 100644 arm9/data/discarded/unknown_banner.bin delete mode 100644 arm9/source/crtsmall.cpp delete mode 100644 arm9/source/files.cpp delete mode 100644 arm9/source/files.h rename {share => arm9/source}/flags.h (100%) rename {share => arm9/source}/gamecode.h (100%) delete mode 100644 arm9/source/iocmn.h delete mode 100644 arm9/source/padding.s delete mode 100644 arm9/source/save64m.cpp delete mode 100644 arm9/source/save64m.h delete mode 100644 arm9/source/savechip.cpp delete mode 100644 arm9/source/savechip.h delete mode 100644 arm9/source/sdidentify.cpp delete mode 100644 arm9/source/sdidentify.h rename {share => arm9/source}/stringtool.cpp (100%) rename {share => arm9/source}/stringtool.h (100%) rename {share => arm9/source}/timetool.cpp (100%) rename {share => arm9/source}/timetool.h (100%) delete mode 100644 arm9/source/ui/sigslot.h.new delete mode 100644 arm9/specs/ds_arm9.ld delete mode 100644 arm9/specs/ds_arm9.specs rename akmenu4.bmp => icon.bmp (100%) diff --git a/Makefile b/Makefile index 9dfa4c6..bc938e2 100644 --- a/Makefile +++ b/Makefile @@ -2,113 +2,57 @@ .SUFFIXES: #--------------------------------------------------------------------------------- ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") endif +export TARGET := $(shell basename $(CURDIR)) +export TOPDIR := $(CURDIR) + +# GMAE_ICON is the image used to create the game icon, leave blank to use default rule +GAME_ICON := + +# specify a directory which contains the nitro filesystem +# this is relative to the Makefile +NITRO_FILES := + +# These set the information text in the nds file +GAME_TITLE := acekard +GAME_SUBTITLE1 := Real Play Gear +GAME_SUBTITLE2 := www.acekard.com + 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 +.PHONY: checkarm7 checkarm9 clean #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -all: rpg r4 +all: checkarm7 checkarm9 $(TARGET).nds #--------------------------------------------------------------------------------- -# 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: +checkarm7: $(MAKE) -C arm7 #--------------------------------------------------------------------------------- -arm9/rpg/$(TARGET).arm9: +checkarm9: $(MAKE) -C arm9 #--------------------------------------------------------------------------------- -_DS_MENU.DAT : $(TARGET)_r4.nds - r4denc $(TARGET)_r4.nds _DS_MENU.DAT +$(TARGET).nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9/$(TARGET).elf + ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \ + -b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1);$(GAME_SUBTITLE2)" \ + $(_ADDFILES) #--------------------------------------------------------------------------------- -$(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/$(TARGET).elf: + $(MAKE) -C arm7 #--------------------------------------------------------------------------------- -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 +arm9/$(TARGET).elf: + $(MAKE) -C arm9 #--------------------------------------------------------------------------------- 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 + rm -f $(TARGET).nds diff --git a/arm7/Makefile b/arm7/Makefile index 84b2604..4ec84b7 100644 --- a/arm7/Makefile +++ b/arm7/Makefile @@ -14,92 +14,86 @@ include $(DEVKITARM)/ds_rules # 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 +BUILD := build +SOURCES := source +INCLUDES := include build ../share $(SOURCES) +DATA := #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -mthumb-interwork +ARCH := -mthumb-interwork -CFLAGS := -g -Wall -Os\ - -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\ - -ffast-math \ - $(ARCH) +CFLAGS := -g -Wall -O3\ + $(ARCH) $(INCLUDE) -DARM7 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,--nmagic -Wl,-Map,$(notdir $*).map -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 +LIBS := -ldswifi7 -lmm7 -lnds7 #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib #--------------------------------------------------------------------------------- -LIBDIRS := $(LIBUNDS) - +LIBDIRS := $(LIBNDS) #--------------------------------------------------------------------------------- # 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))) +ifneq ($(BUILD),$(notdir $(CURDIR))) #--------------------------------------------------------------------------------- -export ARM7BIN := $(CURDIR)/$(STORAGE)/$(TARGET).arm7 -export ARM7ELF := $(CURDIR)/$(STORAGE)/$(TARGET).arm7.elf -export DEPSDIR := $(CURDIR)/$(BUILD) +export ARM7ELF := $(CURDIR)/$(TARGET).elf +export DEPSDIR := $(CURDIR)/$(BUILD) -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) +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)/*.*))) - -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) +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) + export LD := $(CC) #--------------------------------------------------------------------------------- else #--------------------------------------------------------------------------------- - export LD := $(CXX) + export LD := $(CXX) #--------------------------------------------------------------------------------- endif #--------------------------------------------------------------------------------- +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) + +export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) + +export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir))\ + $(foreach dir,$(LIBDIRS),-I$(dir)/include)\ + -I$(CURDIR)/$(BUILD) +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + .PHONY: $(BUILD) clean #--------------------------------------------------------------------------------- $(BUILD): @[ -d $@ ] || mkdir -p $@ - @[ -d $@/crt ] || mkdir -p $@/crt - @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr $(STORAGE) *.elf + @rm -fr $(BUILD) $(TARGET).elf #--------------------------------------------------------------------------------- @@ -110,28 +104,19 @@ DEPENDS := $(OFILES:.o=.d) #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -$(ARM7BIN) : $(ARM7ELF) - @$(OBJCOPY) -O binary $< $@ - @echo built ... $(notdir $@) - - -$(ARM7ELF) : $(OFILES) $(CRT) +$(ARM7ELF) : $(OFILES) @echo linking $(notdir $@) @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ #--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o : %.bin +%.bin.o %_bin.h : %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) -$(CRT) : $(CRT:.o=.s) - -include $(DEPENDS) #--------------------------------------------------------------------------------------- endif -#--------------------------------------------------------------------------------------- \ No newline at end of file +#--------------------------------------------------------------------------------------- diff --git a/arm7/source/crt/ds_arm7_crt1.s b/arm7/source/crt/ds_arm7_crt1.s deleted file mode 100644 index 565a82f..0000000 --- a/arm7/source/crt/ds_arm7_crt1.s +++ /dev/null @@ -1,104 +0,0 @@ -@--------------------------------------------------------------------------------- - .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 -@--------------------------------------------------------------------------------- diff --git a/arm7/specs/ds_arm7.ld b/arm7/specs/ds_arm7.ld deleted file mode 100644 index 811c854..0000000 --- a/arm7/specs/ds_arm7.ld +++ /dev/null @@ -1,198 +0,0 @@ -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 . */ -} diff --git a/arm7/specs/ds_arm7.specs b/arm7/specs/ds_arm7.specs deleted file mode 100644 index c2b3259..0000000 --- a/arm7/specs/ds_arm7.specs +++ /dev/null @@ -1,8 +0,0 @@ -%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 - diff --git a/arm9/Makefile b/arm9/Makefile index e949dee..cc57e5a 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -11,140 +11,127 @@ 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 +# DATA is a list of directories containing binary files embedded using bin2o +# GRAPHICS is a list of directories containing image files to be converted with grit # all directories are relative to this makefile #--------------------------------------------------------------------------------- -STORAGE ?= rpg -BUILD := $(STORAGE)/build -SOURCES := source source/ui ../share source/font -INCLUDES := source source/ui ../share source/font $(BUILD) -DATA := data data/$(STORAGE) +BUILD := build +SOURCES := source source/ui source/font +INCLUDES := include ../share $(SOURCES) +DATA := data +GRAPHICS := #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -mthumb -mthumb-interwork -# +ARCH := -marm -mthumb-interwork -march=armv5te -mtune=arm946e-s -# 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) +CFLAGS := -g -Wall -O3\ + $(ARCH) $(INCLUDE) -DARM9 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -lelm -lio$(STORAGE) -lunds9 +LIBS := -lfat -lnds9 #--------------------------------------------------------------------------------- # 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 +LIBDIRS := $(LIBNDS) $(PORTLIBS) #--------------------------------------------------------------------------------- # 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))) +ifneq ($(BUILD),$(notdir $(CURDIR))) #--------------------------------------------------------------------------------- -export ARM9BIN := $(CURDIR)/$(STORAGE)/$(TARGET).arm9 -export ARM9ELF := $(CURDIR)/$(STORAGE)/$(TARGET).arm9.elf -export DEPSDIR := $(CURDIR)/$(BUILD) +export ARM9ELF := $(CURDIR)/$(TARGET).elf -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))\ + $(foreach dir,$(DATA),$(CURDIR)/$(dir))\ + $(foreach dir,$(GRAPHICS),$(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 DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C #--------------------------------------------------------------------------------- ifeq ($(strip $(CPPFILES)),) #--------------------------------------------------------------------------------- - export LD := $(CC) + export LD := $(CC) #--------------------------------------------------------------------------------- else #--------------------------------------------------------------------------------- - export LD := $(CXX) + export LD := $(CXX) #--------------------------------------------------------------------------------- endif #--------------------------------------------------------------------------------- -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) +export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) +export OFILES := $(PNGFILES:.png=.o) $(OFILES_BIN) $(OFILES_SOURCES) + +export HFILES := $(PNGFILES:.png=.h) $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir))\ + $(foreach dir,$(LIBDIRS),-I$(dir)/include)\ + -I$(CURDIR)/$(BUILD) +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) .PHONY: $(BUILD) clean #--------------------------------------------------------------------------------- $(BUILD): @[ -d $@ ] || mkdir -p $@ - @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr $(STORAGE) *.elf *.nds* *.bin + @rm -fr $(BUILD) $(TARGET).elf #--------------------------------------------------------------------------------- else -DEPENDS := $(OFILES:.o=.d) - #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -$(ARM9BIN) : $(ARM9ELF) - @$(OBJCOPY) -O binary $< $@ - @echo built ... $(notdir $@) - -$(ARM9ELF) : $(OFILES) +$(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 +%.bin.o %_bin.h : %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) +#--------------------------------------------------------------------------------- +# This rule creates assembly source files using grit +# grit takes an image file and a .grit describing how the file is to be processed +# add additional rules like this for each image extension +# you use in the graphics folders +#--------------------------------------------------------------------------------- +%.s %.h: %.png %.grit +#--------------------------------------------------------------------------------- + grit $< -fts -o$* --include $(DEPENDS) +-include $(DEPSDIR)/*.d #--------------------------------------------------------------------------------------- endif -#--------------------------------------------------------------------------------------- \ No newline at end of file +#--------------------------------------------------------------------------------------- diff --git a/arm9/data/akloader_public/akloader_arm7.bin b/arm9/data/akloader_public/akloader_arm7.bin deleted file mode 100644 index f9ae9b944008034d100089345c39ceec805ce8d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2600 zcmZveYi!%r6@bqrDUo_uW-N8JWhS9T*Rw4rrR}8X)&TY-kABcu(|Q>K1Vz~{>(nIy zIBeLIKdWMGfZGn6QSXOi54F)B#js+n21Nhd!fUXhT`)jOVl2T{Sh674*)oJ}mg>>Y z+_{qMq(~`z;=PyWo)>w~y@XvZ2uz~b0?P%kdh)ZGrJ}#lp27D1MmvG+1R&y45yWrg zcz}P$)umz=-hs-9%Y`%84`H7{oud6{o|TsijCelBh}rx;`%wbe=U{n@6QA1n+_r-_ zmS@zF982e`$sDLxYjOnsxJBTNEl!=<_^ctfY$w>|ZRCFmw)?L`jQ8>obNs_0=I)<{ z7_^_?p`2dT$}7Uk>zX+V^jcjiN@(Zq2SbdQ<|mang!!yfhcJ_IjDZy{6Gbt_6|w@O zR4<(((R5 zom6I^dru}PK?j$6xiu(xT=Nmv4P|B_SXy%&eY$OD?Cy27=7SS};|T!uUQ9QSduB+; zA8qHRQ|(^p^d!jdJma1T@*A)`pSg7@Aq+}}Yl0{zBYs2B*$|To8ue&U5er-jZ(ab0 zzyKFOyq~s$q_+m%Pgi40b{LjTWH$=mWISbwQ1F_?ozCft?b z!aW%hzLS-XhGWtsJEz2$IlJ@+`;=^#Ua?!p+a^F!B{B!rdsSx9Eh~my`kBox`X<9@ zW3dX>(yq4aS-UiAgEd>dyy?}w6K%2C(^pP|^(&0Yfu4b)81HQY`g#H1udw|R(}{qE z5R3)K0sAx-E6qtw67)1>KyL10pJ|iYT?=rfwSV|&c)67vC+aUEcd}M3w^sUD?K|30 zZA7y!Mkg<5KT^)85}IPF@+;b$29{p^DSito#;;YQ+TJ*HeO0>U`mv%!+nw#cCu&c= zR{e=0MLV6Hz9Y4Mf0aCT+PT*!9K4yG(nz@T22uK+oFAd{i84O|UD%hT;V)|W$``bd z$G~c;o)v_HTUq)h7e=V2kFvT3VI>2PKv(PJsfK5j$_tIwe=ABHzl{i&@k?(F52BCz zeB`ijU@Lo4+hqQrGT2o$^Ytj*TGcr!hnI-@xcIi>HTFS0~B1|(KFtJ$S* z+5F+>>SGG&=#}i!H|=nIfoInS<3l0;@Sv$mY=>Ryw3(Dydnb@irXcj9#>UCO)VGN$ z^j5N`6ptCxgof45hE-e>yLP{~YnQLtZF#`1Ysc=nn%y6&5|4Jbws-8RX!opkMsuLQ z{GqTJl8Dlck=UhM+oAZX5{$Srh7!g+`lF}KZi#7l^U*e&QtO`MVj0yE7pGGW$%kKH za|SxeJH|6V(4LUo9bgSsV391e6Myu($H}2LBOhm(6o*-_=exeXy%Kc0GXWhsf-&e7 zGP4n9hV%=AZ9Si6#hMl0#AW#HvBlOC#wFgl=GB8ULWeur!nJsVi6oBjI3n(jI41lt zHtIKWn`2mqMi36yzliG|(zSIaeb5hb&^TcTgRe%aS=WS1_Zu$VJ<)3H)DRL1ChB#K z&Oi6(A?9m=-1ltbNdNGSZRo8&16qp^+$wdiDTz>K>g>;}FxNQ^qWd4`h<&_Fg8Vjoiu) z4O@f^M%?`{m-+P#RP_{^d6jc3mLGD3CGSZGW%HtMH+-v#UDD2s52 z1K|+?an%qcbJTm$weDRJjW)v^_28%%X+nHRGa@2;kQT&`1dxXiClW;35eXTV_pdY3 zer&C3_kLs$&j&4YMPVRW1b8y<2<~MMfmKc{~$=ha1#)74uGH_Pj8fM`(J^UWYGifZV7nzS-5YDRQ9O?Zh1jGL*ze28LZ^_b@~0m zetEjU;F%=ApzYxUHzD`yjXk)R!|=OXHNU7&D$1&t3a_cj0*kUcy1{xePxY7aozw3a zFe(8N5xO_aNH?M)k0Zm#7;+3bffz^(q1iCgF5NY;7<^rXgFLSCha}-|$(D{heGw$?&yb_c1QuKxtF`) zmU^Qs)+kTr`F)P7o;c}eO`?*oSFUtR>I$NnBUN2Q^u>YIpcCnJaW|#`^ACg ozE7^RecTPdMOzqT3 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 R(aoX_d_VPA6@P`2{x^bn1LObz diff --git a/arm9/data/akloader_public_0911/akloader_arm7.bin b/arm9/data/akloader_public_0911/akloader_arm7.bin deleted file mode 100644 index f9ae9b944008034d100089345c39ceec805ce8d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2600 zcmZveYi!%r6@bqrDUo_uW-N8JWhS9T*Rw4rrR}8X)&TY-kABcu(|Q>K1Vz~{>(nIy zIBeLIKdWMGfZGn6QSXOi54F)B#js+n21Nhd!fUXhT`)jOVl2T{Sh674*)oJ}mg>>Y z+_{qMq(~`z;=PyWo)>w~y@XvZ2uz~b0?P%kdh)ZGrJ}#lp27D1MmvG+1R&y45yWrg zcz}P$)umz=-hs-9%Y`%84`H7{oud6{o|TsijCelBh}rx;`%wbe=U{n@6QA1n+_r-_ zmS@zF982e`$sDLxYjOnsxJBTNEl!=<_^ctfY$w>|ZRCFmw)?L`jQ8>obNs_0=I)<{ z7_^_?p`2dT$}7Uk>zX+V^jcjiN@(Zq2SbdQ<|mang!!yfhcJ_IjDZy{6Gbt_6|w@O zR4<(((R5 zom6I^dru}PK?j$6xiu(xT=Nmv4P|B_SXy%&eY$OD?Cy27=7SS};|T!uUQ9QSduB+; zA8qHRQ|(^p^d!jdJma1T@*A)`pSg7@Aq+}}Yl0{zBYs2B*$|To8ue&U5er-jZ(ab0 zzyKFOyq~s$q_+m%Pgi40b{LjTWH$=mWISbwQ1F_?ozCft?b z!aW%hzLS-XhGWtsJEz2$IlJ@+`;=^#Ua?!p+a^F!B{B!rdsSx9Eh~my`kBox`X<9@ zW3dX>(yq4aS-UiAgEd>dyy?}w6K%2C(^pP|^(&0Yfu4b)81HQY`g#H1udw|R(}{qE z5R3)K0sAx-E6qtw67)1>KyL10pJ|iYT?=rfwSV|&c)67vC+aUEcd}M3w^sUD?K|30 zZA7y!Mkg<5KT^)85}IPF@+;b$29{p^DSito#;;YQ+TJ*HeO0>U`mv%!+nw#cCu&c= zR{e=0MLV6Hz9Y4Mf0aCT+PT*!9K4yG(nz@T22uK+oFAd{i84O|UD%hT;V)|W$``bd z$G~c;o)v_HTUq)h7e=V2kFvT3VI>2PKv(PJsfK5j$_tIwe=ABHzl{i&@k?(F52BCz zeB`ijU@Lo4+hqQrGT2o$^Ytj*TGcr!hnI-@xcIi>HTFS0~B1|(KFtJ$S* z+5F+>>SGG&=#}i!H|=nIfoInS<3l0;@Sv$mY=>Ryw3(Dydnb@irXcj9#>UCO)VGN$ z^j5N`6ptCxgof45hE-e>yLP{~YnQLtZF#`1Ysc=nn%y6&5|4Jbws-8RX!opkMsuLQ z{GqTJl8Dlck=UhM+oAZX5{$Srh7!g+`lF}KZi#7l^U*e&QtO`MVj0yE7pGGW$%kKH za|SxeJH|6V(4LUo9bgSsV391e6Myu($H}2LBOhm(6o*-_=exeXy%Kc0GXWhsf-&e7 zGP4n9hV%=AZ9Si6#hMl0#AW#HvBlOC#wFgl=GB8ULWeur!nJsVi6oBjI3n(jI41lt zHtIKWn`2mqMi36yzliG|(zSIaeb5hb&^TcTgRe%aS=WS1_Zu$VJ<)3H)DRL1ChB#K z&Oi6(A?9m=-1ltbNdNGSZRo8&16qp^+$wdiDTz>K>g>;}FxNQ^qWd4`h<&_Fg8Vjoiu) z4O@f^M%?`{m-+P#RP_{^d6jc3mLGD3CGSZGW%HtMH+-v#UDD2s52 z1K|+?an%qcbJTm$weDRJjW)v^_28%%X+nHRGa@2;kQT&`1dxXiClW;35eXTV_pdY3 zer&C3_kLs$&j&4YMPVRW1b8y<2<~MMfmKc{~$=ha1#)74uGH_Pj8fM`(J^UWYGifZV7nzS-5YDRQ9O?Zh1jGL*ze28LZ^_b@~0m zetEjU;F%=ApzYxUHzD`yjXk)R!|=OXHNU7&D$1&t3a_cj0*kUcy1{xePxY7aozw3a zFe(8N5xO_aNH?M)k0Zm#7;+3bffz^(q1iCgF5NY;7<^rXgFLSCha}-|$(D{heGw$?&yb_c1QuKxtF`) zmU^Qs)+kTr`F)P7o;c}eO`?*oSFUtR>I$NnBUN2Q^u>YIpcCnJaW|#`^ACg ozE7^RecTPdMOzqT3 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 R(aoX_d_VPA6@P`2{x^bn1LObz diff --git a/arm9/data/discarded/file_banner.bin b/arm9/data/discarded/file_banner.bin deleted file mode 100644 index 0603fdce52059279ff42a0c2aaaf7b26fab379cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2112 zcmeH@u}T9$6h)tvmEb@ivgLMSC0p8s#b^YJz&2tdet-)prU;Usu(X*bEmJC;@;SFnX*PefPZXUe1^mwF?$DSkaGH0C2JQzp*>D;1Q^R8!;=WYLz zUS%b6Qh<61kLqC=Lg1aS3ZX!Jg%ZWCJ^H;VKcGWBjE7(JVisY4MSN(i(WGjtI0q^U>b4z`C9&|>SRk|S{{Wwaq6udZAdx^`<6 zIp*uqrC(Wy}R%6>F!iuKL>0Lo*IU+2SAKH zf|6mFCg-J6>56l1-_GCrpNQzfvaBy4ftD3x^=d!teN66vHb{gKcJZM;0t^Ij(=
    DeoafXyznrFN-1NL?s#L$Zs-FP?kZTBN;IU>|!wrIln`;QwdPML) z-f2U+$++hx$AO#7wVQMTqPgz%Iw4K8mcuaovwrYb{bgRhPLMAYDV6t+?~%T$*Xvrh zWEi$&mbIiWT2i5JA-oT{54$dhc}^#k!+9o$r-Gtu)klL%|8ad^kWdI%*2nfIj4is0 zX7~B8?Pl?N;Z5QF*0-12>}K~z``O#W>Z0qifSrP8tc~#nd(BSRJ9f0@M*UmXrvJ_P NZ|?u*{r|83zu!dO9Nqu` diff --git a/arm9/source/bigclock.cpp b/arm9/source/bigclock.cpp index 623a09f..d06d254 100644 --- a/arm9/source/bigclock.cpp +++ b/arm9/source/bigclock.cpp @@ -19,7 +19,7 @@ */ #include "bigclock.h" -#include "../../share/stringtool.h" +#include "stringtool.h" #include "systemfilenames.h" #include "windowmanager.h" #include "inifile.h" diff --git a/arm9/source/bmp15.cpp b/arm9/source/bmp15.cpp index 103f40f..426ab41 100644 --- a/arm9/source/bmp15.cpp +++ b/arm9/source/bmp15.cpp @@ -18,7 +18,7 @@ along with this program. If not, see . */ -// +//� #include #include @@ -34,7 +34,7 @@ cBMP15::cBMP15( u32 width, u32 height ) : _width(0), _height(0), _pitch(0), _buf _width = width; _height = height; _pitch = (width + (width & 1)) << 1; - //u32 pitch = (((width*16)+31)>>5)<<2; // ͨ㷨 + //u32 pitch = (((width*16)+31)>>5)<<2; // 通用算法? } cBMP15::~cBMP15() @@ -46,12 +46,12 @@ cBMP15 createBMP15( u32 width, u32 height ) { cBMP15 bmp( width, height ); - u32 pitch = bmp.pitch(); // 15bit bmp pitch 㷨 + 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ֽڶ룬Ͱ + if( bufferSize & 3 ) // 如果 bufferSize 不是按4字节对齐,就把他调整到对齐 bufferSize += 4 - (bufferSize & 3); bmp._buffer = new u32[bufferSize>>2]; return bmp; @@ -85,7 +85,7 @@ cBMP15 createBMP15FromFile( const std::string & filename ) return cBMP15(); } - // ȡļ + // 读取文件长度 fseek( f, 0, SEEK_END ); int fileSize = ftell( f ); @@ -103,7 +103,7 @@ cBMP15 createBMP15FromFile( const std::string & filename ) return cBMP15(); } - // ҳbmpߺͿ + // 找出bmp高和宽 u32 width = 0; u32 height = 0; fseek( f, 0x12, SEEK_SET ); diff --git a/arm9/source/bmp15.h b/arm9/source/bmp15.h index 1f0bb34..b58eb9b 100644 --- a/arm9/source/bmp15.h +++ b/arm9/source/bmp15.h @@ -60,7 +60,7 @@ protected: u32 _pitch; - u32 * _buffer; // 32 λַ룬 bitblt ʱӿٶ + u32 * _buffer; // 按 32 位地址对齐,可以在 bitblt 的时候加快速度 }; cBMP15 createBMP15( u32 width, u32 height ); diff --git a/arm9/source/calendar.cpp b/arm9/source/calendar.cpp index 69d46e3..0a36438 100644 --- a/arm9/source/calendar.cpp +++ b/arm9/source/calendar.cpp @@ -23,7 +23,7 @@ #include "windowmanager.h" #include "inifile.h" #include "globalsettings.h" -#include "../../share/stringtool.h" +#include "stringtool.h" #include "../../share/memtool.h" using namespace akui; diff --git a/arm9/source/cheatwnd.cpp b/arm9/source/cheatwnd.cpp index 6653ea9..dd1c855 100644 --- a/arm9/source/cheatwnd.cpp +++ b/arm9/source/cheatwnd.cpp @@ -23,9 +23,9 @@ #include "windowmanager.h" #include "language.h" #include "msgbox.h" -#include "../../share/gamecode.h" +#include "gamecode.h" #include -#include +#include using namespace akui; @@ -272,7 +272,6 @@ static void updateDB(u8 value,u32 offset,FILE* db) void cCheatWnd::onGenerate(void) { - NandFast(); FILE* db=fopen(SFN_CHEATS,"r+b"); if(db) { @@ -284,7 +283,6 @@ void cCheatWnd::onGenerate(void) } fclose(db); } - NandFlush(); cForm::onOK(); } diff --git a/arm9/source/crtsmall.cpp b/arm9/source/crtsmall.cpp deleted file mode 100644 index fd670ea..0000000 --- a/arm9/source/crtsmall.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - 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 . -*/ - -#include -#include - -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(); - } -} diff --git a/arm9/source/datetime.h b/arm9/source/datetime.h index f487d4d..907a745 100644 --- a/arm9/source/datetime.h +++ b/arm9/source/datetime.h @@ -24,7 +24,7 @@ #include #include #include "singleton.h" -#include "../../share/stringtool.h" +#include "stringtool.h" class cDateTime { diff --git a/arm9/source/diskicon.cpp b/arm9/source/diskicon.cpp index 67209ee..818a541 100644 --- a/arm9/source/diskicon.cpp +++ b/arm9/source/diskicon.cpp @@ -23,7 +23,7 @@ #include "inifile.h" #include "systemfilenames.h" #include "../../share/memtool.h" -#include "../../share/timetool.h" +#include "timetool.h" #include "globalsettings.h" using namespace akui; diff --git a/arm9/source/dsrom.cpp b/arm9/source/dsrom.cpp index 2a1a5e9..d53753e 100644 --- a/arm9/source/dsrom.cpp +++ b/arm9/source/dsrom.cpp @@ -26,7 +26,7 @@ #include "unknown_nds_banner_bin.h" #include "gbarom_banner_bin.h" #include "icon_bg_bin.h" -#include "../../share/gamecode.h" +#include "gamecode.h" #include "fileicons.h" DSRomInfo & DSRomInfo::operator =( const DSRomInfo & src ) @@ -47,14 +47,14 @@ bool DSRomInfo::loadDSRomInfo( const std::string & filename, bool loadBanner ) _isDSRom = EFalse; _isHomebrew = EFalse; FILE * f = fopen( filename.c_str(), "rb" ); - if( NULL == f )// ���ļ�ʧ�� + if( NULL == f )// 锟斤拷锟侥硷拷失锟斤拷 { return false; } tNDSHeader header; - if( 512 != fread( &header, 1, 512, f ) ) // ���ļ�ͷʧ�� + if( 512 != fread( &header, 1, 512, f ) ) // 锟斤拷锟侥硷拷头失锟斤拷 { dbg_printf( "read rom header fail\n" ); memcpy( &_banner, unknown_nds_banner_bin, sizeof(_banner) ); @@ -64,7 +64,7 @@ bool DSRomInfo::loadDSRomInfo( const std::string & filename, bool loadBanner ) ///////// ROM Header ///////// u16 crc = swiCRC16( 0xFFFF, &header, 0x15E ); - if( crc != header.headerCRC16 ) // �ļ�ͷ CRC ���󣬲���nds��Ϸ + if( crc != header.headerCRC16 ) // 锟侥硷拷头 CRC 锟斤拷锟襟,诧拷锟斤拷nds锟斤拷戏 { dbg_printf( "%s rom header crc error\n", filename.c_str() ); memcpy( &_banner, unknown_nds_banner_bin, sizeof(_banner) ); @@ -72,7 +72,7 @@ bool DSRomInfo::loadDSRomInfo( const std::string & filename, bool loadBanner ) return true; } else { _isDSRom = ETrue; - if( header.arm7destination >= 0x037F8000 || 0x23232323 == gamecode(header.gameCode) ) {//23->'#' + if( (u32)(header.arm7destination) >= 0x037F8000 || 0x23232323 == gamecode(header.gameCode) ) {//23->'#' _isHomebrew = ETrue; } diff --git a/arm9/source/expwnd.cpp b/arm9/source/expwnd.cpp index bf706c5..fe7e584 100644 --- a/arm9/source/expwnd.cpp +++ b/arm9/source/expwnd.cpp @@ -26,7 +26,7 @@ #include "datetime.h" #include "progresswnd.h" #include "fontfactory.h" -#include +#include using namespace akui; @@ -214,9 +214,8 @@ void cExpWnd::onRAM() void cExpWnd::onSRAM() { - std::string saveName="fat0:/sram-"+datetime().getTimeStampString()+".sav"; + std::string saveName="fat:/sram-"+datetime().getTimeStampString()+".sav"; const u32 size=4096*128,page=4096,pages=128; - NandFast(); FILE* saveFile=fopen(saveName.c_str(),"wb"); if(saveFile) { @@ -241,7 +240,6 @@ void cExpWnd::onSRAM() } fclose(saveFile); } - NandFlush(); cForm::onOK(); } diff --git a/arm9/source/fileicons.cpp b/arm9/source/fileicons.cpp index d69142e..f6f6aaa 100644 --- a/arm9/source/fileicons.cpp +++ b/arm9/source/fileicons.cpp @@ -22,7 +22,7 @@ #include "icons.h" #include "globalsettings.h" #include -#include +#include cFileIconItem::cFileIconItem(const std::string& aFolderName,const std::string& aFileName):_loaded(false),_foldername(aFolderName),_filename(aFileName) { @@ -67,28 +67,25 @@ cFileIcons::cFileIcons() 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); + DIR *dir=opendir(aFolder.c_str()); + struct dirent *entry; + + if (NULL!=dir){ + while ((entry=readdir(dir))!=NULL) { + if(entry->d_type != DT_DIR) { + size_t len=strlen(entry->d_name); if(len>4) { - char* extName=longFilename+len-4; + char* extName=entry->d_name+len-4; if(strcasecmp(extName,".bmp")==0) { *extName=0; - aPaths.insert(cFileIconItem(aFolder,longFilename)); + aPaths.insert(cFileIconItem(aFolder,entry->d_name)); } } } } - dirclose(dir); + closedir(dir); } } diff --git a/arm9/source/files.cpp b/arm9/source/files.cpp deleted file mode 100644 index c9346d8..0000000 --- a/arm9/source/files.cpp +++ /dev/null @@ -1,516 +0,0 @@ -/* - 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 . -*/ - -#include -#include -#include "files.h" -//#include "dbgtool.h" -#include -#include -#include "msgbox.h" -#include "progresswnd.h" -#include -#include -#include -#include "language.h" -#include "datetime.h" -#include "dsrom.h" -#include "favorites.h" - -#define USE_OPEN -#ifdef USE_OPEN -#include -#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; -} diff --git a/arm9/source/files.h b/arm9/source/files.h deleted file mode 100644 index d718a1f..0000000 --- a/arm9/source/files.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - 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 . -*/ - -#ifndef _FILES_H_ -#define _FILES_H_ - -#include - -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_ diff --git a/share/flags.h b/arm9/source/flags.h similarity index 100% rename from share/flags.h rename to arm9/source/flags.h diff --git a/arm9/source/font/font.cpp b/arm9/source/font/font.cpp index acb358b..6d7b8bf 100644 --- a/arm9/source/font/font.cpp +++ b/arm9/source/font/font.cpp @@ -21,7 +21,6 @@ #include #include #include "font.h" -#include "files.h" #include "dbgtool.h" #include "systemfilenames.h" diff --git a/arm9/source/font/fontfactory.h b/arm9/source/font/fontfactory.h index be241b4..252af39 100644 --- a/arm9/source/font/fontfactory.h +++ b/arm9/source/font/fontfactory.h @@ -21,7 +21,7 @@ #include -#include +#include "singleton.h" #include "font.h" class cFontFactory diff --git a/share/gamecode.h b/arm9/source/gamecode.h similarity index 100% rename from share/gamecode.h rename to arm9/source/gamecode.h diff --git a/arm9/source/gbaloader.cpp b/arm9/source/gbaloader.cpp index 1d7b068..2eb4778 100644 --- a/arm9/source/gbaloader.cpp +++ b/arm9/source/gbaloader.cpp @@ -31,7 +31,7 @@ #include "sram.h" #include "gbapatcher.h" #include "gbaloader.h" -#include +#include #define LEN 0x100000 #define LEN_NOR 0x8000 @@ -225,7 +225,6 @@ bool CGbaLoader::CheckPSRAM(u32 aSize) void CGbaLoader::StartGBA(void) { LoadBorder(); - ELM_Unmount(); BootGBA(); while(true) swiWaitForVBlank(); } @@ -241,7 +240,7 @@ 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); + vramSetPrimaryBanks(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; @@ -358,7 +357,7 @@ bool CGbaLoader::LoadNor(void) cSram::CreateDefaultFile(iFileName.c_str(),saveSize); /* FILE *log; - log=fopen("fat0:/test.bin","wb"); + log=fopen("fat:/test.bin","wb"); fwrite((void*)0x08000000,iSize,1,log); fclose(log); // */ diff --git a/arm9/source/gbaloader.h b/arm9/source/gbaloader.h index 5ccde04..3e1178f 100644 --- a/arm9/source/gbaloader.h +++ b/arm9/source/gbaloader.h @@ -20,6 +20,9 @@ #ifndef __GBALOADER_H__ #define __GBALOADER_H__ +#include +#include + class CGbaLoader { private: diff --git a/arm9/source/gdi.cpp b/arm9/source/gdi.cpp index 4a8780c..5318d3c 100644 --- a/arm9/source/gdi.cpp +++ b/arm9/source/gdi.cpp @@ -155,16 +155,16 @@ void cGdi::activeFbMain(void) 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_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_BG3PA = 1 << 8; // 2 =放大倍数 + REG_BG3PD = 1 << 8; // 2 =放大倍数 REG_BG3PB = 0; REG_BG3PC = 0; REG_BG3Y = 0; @@ -200,14 +200,14 @@ void cGdi::activeFbSub(void) MyInitConsole(_bufferSub3+0x2000,_bufferSub3); #endif - // Դ棬 128k + // 分配显存存, 128k vramSetBankC( VRAM_C_SUB_BG_0x06200000 ); // 128k - // ʼΪģʽ + // 初始化为文字模式 _subEngineMode = SEM_GRAPHICS; //_subEngineMode = SEM_TEXT; - // BMP bg IJã VRAMַ 0x06200000 ʼȼ3 + // 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; @@ -225,18 +225,18 @@ void cGdi::activeFbSub(void) 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 + // 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 - // ģʽ5BGһBMPһ(ڵ)bmpĬϹر + // 模式5,开两层BG,一层BMP,一层文字(用于调试),bmp层现在默认关闭 videoSetModeSub( MODE_5_2D | DISPLAY_BG2_ACTIVE );// | DISPLAY_BG2_ACTIVE ); } @@ -483,8 +483,8 @@ void cGdi::bitBlt( const void * src, s16 destX, s16 destY, u16 destW, u16 destH, } } -// maskBlt ҪdestWżٶȿԿһ -// żҲԣҪڴ src pitch ճż +// 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 ); @@ -618,7 +618,7 @@ void cGdi::textOutRect( s16 x, s16 y, u16 w, u16 h, const char * text, GRAPHICS_ void cGdi::present( GRAPHICS_ENGINE engine ) { - if( GE_MAIN == engine ) { // ת + if( GE_MAIN == engine ) { // 翻转主引擎 //u16 * temp = _bufferMain1; //_bufferMain1 = _bufferMain2; //_bufferMain2 = temp; @@ -629,7 +629,7 @@ void cGdi::present( GRAPHICS_ENGINE engine ) fillMemory( (void *)(_bufferMain2 + _layerPitch), 256 * 192 * 2, 0 ); - } else if ( GE_SUB == engine ) { // ת + } else if ( GE_SUB == engine ) { // 翻转副引擎 if( SEM_GRAPHICS == _subEngineMode ) dmaCopyWordsGdi( 3, (void *)_bufferSub2, (void *)_bufferSub1, 256 * 192 * 2 ); //else if( SEM_TEXT == _subEngineMode ) @@ -651,16 +651,16 @@ void cGdi::present(void) #ifdef DEBUG void cGdi::switchSubEngineMode() { - // Ҫͻָıģʽֳ + // 需要保存和恢复文本模式的现场 switch( _subEngineMode ) { - case SEM_GRAPHICS: // ǰͼģʽĻͻָղŵtextֳ + 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: // ǰģʽĻֳеͼģʽ + case SEM_TEXT: // 当前是文字模式的话,保存现场,切到图形模式 videoSetModeSub( MODE_5_2D | DISPLAY_BG2_ACTIVE ); custom_console.fontBgMap=_bufferSub3+0x2000; custom_console.fontBgGfx=_bufferSub3; diff --git a/arm9/source/globalsettings.cpp b/arm9/source/globalsettings.cpp index b4ea11b..e2a7b28 100644 --- a/arm9/source/globalsettings.cpp +++ b/arm9/source/globalsettings.cpp @@ -28,9 +28,7 @@ cGlobalSettings::cGlobalSettings() { fontHeight=12; -#if defined(_STORAGE_r4) brightness=1; -#endif language=1; langDirectory="English"; uiName="zelda"; @@ -98,11 +96,9 @@ void cGlobalSettings::loadSettings() 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(); } @@ -154,9 +150,6 @@ u32 cGlobalSettings::CopyBufferSize(void) 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); @@ -166,12 +159,9 @@ void cGlobalSettings::nextBrightness(void) 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 diff --git a/arm9/source/globalsettings.h b/arm9/source/globalsettings.h index 06e0935..4b54654 100644 --- a/arm9/source/globalsettings.h +++ b/arm9/source/globalsettings.h @@ -60,14 +60,10 @@ public: 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; diff --git a/arm9/source/helpwnd.cpp b/arm9/source/helpwnd.cpp index c3a9e14..c9ad195 100644 --- a/arm9/source/helpwnd.cpp +++ b/arm9/source/helpwnd.cpp @@ -18,7 +18,6 @@ along with this program. If not, see . */ -#include "iocmn.h" #include "helpwnd.h" #include "msgbox.h" #include "windowmanager.h" @@ -61,9 +60,8 @@ _buttonOK(0,0,46,18,this,"\x01 OK") //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() ); + _helpText += formatString( "wood akmenu %s.%s ", AKMENU_VERSION_MAIN, AKMENU_VERSION_SUB ); + _helpText += formatString( "\nfont: %dk", font().FontRAM()/1024 ); } cHelpWnd::~cHelpWnd() diff --git a/arm9/source/inifile.cpp b/arm9/source/inifile.cpp index 013fa7f..5010c88 100644 --- a/arm9/source/inifile.cpp +++ b/arm9/source/inifile.cpp @@ -21,9 +21,9 @@ #include #include #include "inifile.h" -#include "../../share/stringtool.h" +#include "stringtool.h" #include "dbgtool.h" -#include +#include static bool freadLine(FILE* f,std::string& str) { @@ -229,11 +229,9 @@ 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; } @@ -255,7 +253,6 @@ bool CIniFile::SaveIniFile(const std::string& FileName) } fclose(f); - NandFlush(); m_bModified=false; diff --git a/arm9/source/iocmn.h b/arm9/source/iocmn.h deleted file mode 100644 index d41feb2..0000000 --- a/arm9/source/iocmn.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - 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 . -*/ - -#ifndef __IOCMN_H__ -#define __IOCMN_H__ - -#if defined(_STORAGE_rpg) -#include -#elif defined(_STORAGE_r4) -#include -#elif defined(_STORAGE_ak2i) -#include -#elif defined(_STORAGE_r4idsn) -#include -#endif - -#endif diff --git a/arm9/source/irqs.cpp b/arm9/source/irqs.cpp index 352b16e..bf68bf9 100644 --- a/arm9/source/irqs.cpp +++ b/arm9/source/irqs.cpp @@ -28,7 +28,6 @@ #include "bigclock.h" #include "timer.h" #include "animation.h" -#include "files.h" #include "userwnd.h" using namespace akui; @@ -64,17 +63,6 @@ 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; diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp index 2b65550..45ff859 100644 --- a/arm9/source/main.cpp +++ b/arm9/source/main.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include "dbgtool.h" #include "gdi.h" @@ -91,8 +91,7 @@ int main(void) //wait_press_b(); // init fat - //bool succ = fatInitDefault(); - bool succ = (ELM_Mount()&1)?false:true; + bool succ = fatInitDefault(); if( !succ ) dbg_printf( "init fat %d\n", succ ); @@ -172,25 +171,7 @@ int main(void) } { //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()) { diff --git a/arm9/source/mainlist.cpp b/arm9/source/mainlist.cpp index 2a123d6..7ef3ed0 100644 --- a/arm9/source/mainlist.cpp +++ b/arm9/source/mainlist.cpp @@ -21,16 +21,14 @@ //� #include -#include -#define ATTRIB_HID 0x02 +#include #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 "timetool.h" #include "../../share/memtool.h" #include "inifile.h" #include "unknown_banner_bin.h" @@ -47,11 +45,7 @@ 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; @@ -59,7 +53,6 @@ _topCount(3),_topuSD(0),_topSlot2(1),_topFavorites(2) _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); @@ -69,7 +62,6 @@ _topCount(3),_topuSD(0),_topSlot2(1),_topFavorites(2) _topSlot2=2; _topFavorites=1; } -#endif } cMainList::~cMainList() @@ -144,15 +136,6 @@ bool cMainList::enterDir( const std::string & dirName ) 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( "" ); @@ -184,11 +167,12 @@ bool cMainList::enterDir( const std::string & dirName ) } bool favorites=("favorites:/"==dirName); - DIR_ITER* dir=NULL; + DIR* dir=NULL; + struct dirent *entry; if(!favorites) { - dir = diropen( dirName.c_str() ); + dir = opendir( dirName.c_str() ); if (dir == NULL) { if( SD_ROOT == dirName ) { @@ -217,10 +201,7 @@ bool cMainList::enterDir( const std::string & dirName ) savNames.push_back( ".sav" ); // insert 一堆文件, 两列,一列作为显示,一列作为真实文件名 - struct stat st; - char longFilename[MAX_FILENAME_LENGTH]; std::string extName; - u8 attr=0; // list dir { @@ -257,21 +238,20 @@ bool cMainList::enterDir( const std::string & dirName ) } else if(dir) { - while(dirnext(dir,longFilename,&st)==0) + while((entry=readdir(dir))!=NULL) { - attr=st.st_spare1; - std::string lfn( longFilename ); + std::string lfn( entry->d_name ); - // st.st_mode & S_IFDIR indicates a directory + // entry->d_type == DT_DIR 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)); + dbg_printf( "%s: %s %s\n", (entry->d_type == DT_DIR ? " DIR" : "FILE"), entry->d_name, extName.c_str() ); + bool showThis=(entry->d_type == DT_DIR)?(strcmp(entry->d_name,".")&&strcmp(entry->d_name,"..")):extnameFilter( extNames, extName ); + showThis=showThis&&(_showAllFiles||gs().showHiddenFiles||!(FAT_getAttr(entry->d_name) & ATTR_HIDDEN)); // 如果有后缀名,或者是个目录,就push进去 if(showThis) { @@ -282,7 +262,7 @@ bool cMainList::enterDir( const std::string & dirName ) a_row.push_back( "" ); // make a space for internal name a_row.push_back(dirName+lfn); //real name - if( st.st_mode & S_IFDIR ) { + if( entry->d_type == DT_DIR ) { a_row[SHOWNAME_COLUMN] += "/"; a_row[REALNAME_COLUMN] += "/"; } @@ -297,7 +277,7 @@ bool cMainList::enterDir( const std::string & dirName ) _saves.push_back(dirName+lfn); } } - dirclose( dir ); + closedir( dir ); } std::sort( _rows.begin(), _rows.end(), itemSortComp ); std::sort(_saves.begin(),_saves.end(),stringComp); @@ -379,7 +359,7 @@ void cMainList::backParentDir() return; bool fat1=(SD_ROOT==_currentDir),favorites=("favorites:/"==_currentDir); - if( "fat0:/" == _currentDir || fat1 || favorites || "/" == _currentDir ) { + if( "fat:/" == _currentDir || fat1 || favorites || "/" == _currentDir ) { enterDir( "..." ); if(fat1) selectRow(_topuSD); if(favorites) selectRow(_topFavorites); diff --git a/arm9/source/mainlist.h b/arm9/source/mainlist.h index 542489d..e7af8af 100644 --- a/arm9/source/mainlist.h +++ b/arm9/source/mainlist.h @@ -29,11 +29,7 @@ #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_0 "fat:" #define SD_ROOT SD_ROOT_0"/" // 显示游戏列表,文件列表等等 diff --git a/arm9/source/mainwnd.cpp b/arm9/source/mainwnd.cpp index 9209d77..bd4e39e 100644 --- a/arm9/source/mainwnd.cpp +++ b/arm9/source/mainwnd.cpp @@ -24,7 +24,7 @@ #include "msgbox.h" #include "systemfilenames.h" #include "timer.h" -#include "../../share/timetool.h" +#include "timetool.h" #include "../../share/fifotool.h" #include "testcases.h" @@ -32,7 +32,6 @@ #include "romloader.h" #include "progresswnd.h" -#include "files.h" #include "inifile.h" #include "language.h" #include "testcases.h" @@ -41,15 +40,11 @@ #include "expwnd.h" #include "gbaloader.h" #include "romlauncher.h" -#include "sdidentify.h" #include "favorites.h" -#ifdef DEBUG -#include "iocmn.h" -#endif - +#include #include -#include +#include using namespace akui; @@ -96,7 +91,7 @@ void cMainWnd::init() _mainList->selectedRowHeadClicked.connect( this, &cMainWnd::onMainListSelItemHeadClicked ); _mainList->directoryChanged.connect( this, &cMainWnd::onFolderChanged ); _mainList->animateIcons.connect( this, &cMainWnd::onAnimation ); - //_mainList->enterDir( "fat0:/" ); + //_mainList->enterDir( "fat:/" ); addChildWindow( _mainList ); dbg_printf( "mainlist %08x\n", _mainList ); @@ -200,64 +195,7 @@ 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 ) { + if( START_MENU_ITEM_SETTING == i ) { showSettings(); } @@ -389,18 +327,7 @@ bool cMainWnd::processKeyMessage( const cKeyMessage & msg ) } 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; @@ -463,12 +390,6 @@ bool cMainWnd::processTouchMessage( const cTouchMessage & msg ) void cMainWnd::onKeyYPressed() { if(gs().safeMode) return; -#ifdef DEBUG - // hardware version check - { - dbg_printf("HW: %02x\n",ioVersion()); - } -#endif//#ifdef DEBUG showFileInfo(); } @@ -517,26 +438,6 @@ void cMainWnd::launchSelected() 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"); @@ -564,17 +465,16 @@ void cMainWnd::setParam(void) //user interface style _values.clear(); std::vector uiNames; - DIR_ITER* dir=diropen(SFN_UI_DIRECTORY); + DIR* dir=opendir(SFN_UI_DIRECTORY); + struct dirent *entry; if(NULL!=dir) { - struct stat st; - char longFilename[MAX_FILENAME_LENGTH]; - while(dirnext(dir,longFilename,&st)==0) + while((entry=readdir(dir))!=NULL) { - std::string lfn(longFilename); + std::string lfn(entry->d_name); if(lfn!=".."&&lfn!=".") _values.push_back(lfn); } - dirclose(dir); + closedir(dir); dir=NULL; } else @@ -584,7 +484,7 @@ void cMainWnd::setParam(void) 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; + if(0==strcasecmp(_values[ii].c_str(),gs().uiName.c_str())) uiIndex=ii; } uiNames=_values; settingWnd.addSettingItem(LANG("ui style","text"),_values,uiIndex); @@ -592,17 +492,15 @@ void cMainWnd::setParam(void) //language _values.clear(); std::vector langNames; - dir=diropen(SFN_LANGUAGE_DIRECTORY); + dir=opendir(SFN_LANGUAGE_DIRECTORY); if(NULL!=dir ) { - struct stat st; - char longFilename[MAX_FILENAME_LENGTH]; - while(dirnext(dir,longFilename,&st)==0) + while ((entry=readdir(dir))!=NULL) { - std::string lfn(longFilename); + std::string lfn(entry->d_name); if(lfn!=".."&&lfn!=".") _values.push_back(lfn); } - dirclose(dir); + closedir(dir); dir=NULL; } else @@ -612,7 +510,7 @@ void cMainWnd::setParam(void) 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; + if(0==strcasecmp(_values[ii].c_str(),gs().langDirectory.c_str())) langIndex=ii; } langNames=_values; settingWnd.addSettingItem(LANG("language","text"),_values,langIndex); @@ -682,12 +580,6 @@ void cMainWnd::setParam(void) 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")); @@ -737,12 +629,6 @@ void cMainWnd::setParam(void) 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); @@ -758,16 +644,7 @@ void cMainWnd::setParam(void) 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 - + loadRom( "fat:/akmenu4.nds", "", 0, 0, 0 ); } } @@ -781,15 +658,7 @@ void cMainWnd::setParam(void) { 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 + loadRom( "fat:/akmenu4.nds", "", 0, 0, 0 ); } } @@ -840,11 +709,6 @@ 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() ) @@ -878,11 +742,7 @@ void cMainWnd::onFolderChanged() } 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 { diff --git a/arm9/source/padding.s b/arm9/source/padding.s deleted file mode 100644 index 2599387..0000000 --- a/arm9/source/padding.s +++ /dev/null @@ -1,29 +0,0 @@ -/* - 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 . -*/ - - .arch armv5te - .cpu arm946e-s - .section .pad,"ax",%progbits - .align 2 - .arm -#if defined(_STORAGE_r4idsn) - ldr pc, target -target: - .word 0x02000450 -#endif - .end diff --git a/arm9/source/rominfownd.cpp b/arm9/source/rominfownd.cpp index 0d28470..ffa773e 100644 --- a/arm9/source/rominfownd.cpp +++ b/arm9/source/rominfownd.cpp @@ -27,7 +27,6 @@ #include "uisettings.h" #include "language.h" #include "unicode.h" -#include "files.h" #include "gbaloader.h" #include "cheatwnd.h" #include "ui/binaryfind.h" @@ -229,21 +228,6 @@ static std::string getFriendlyFileSizeString( u64 size ) 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; @@ -258,8 +242,7 @@ void cRomInfoWnd::setFileInfo( const std::string & fullName, const std::string & return; } - if( "fat0:/" == fullName || "fat1:/" == fullName ) { - setDiskInfo(); + if( "fat:/" == fullName ) { return; } @@ -339,21 +322,6 @@ 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 @@ -363,20 +331,6 @@ void cRomInfoWnd::onShow() #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) { @@ -398,25 +352,9 @@ void cRomInfoWnd::pressSaveType(void) _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(); @@ -440,14 +378,6 @@ void cRomInfoWnd::pressSaveType(void) _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) @@ -476,7 +406,6 @@ void cRomInfoWnd::pressSaveType(void) 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; @@ -494,70 +423,21 @@ void cRomInfoWnd::pressSaveType(void) _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 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()) diff --git a/arm9/source/rominfownd.h b/arm9/source/rominfownd.h index b1d0268..02ecd65 100644 --- a/arm9/source/rominfownd.h +++ b/arm9/source/rominfownd.h @@ -59,8 +59,6 @@ public: protected: - void setDiskInfo(void); - void pressFlash(void); void pressSaveType(void); @@ -69,8 +67,6 @@ protected: void pressCheats(void); - void pressCopySlot(void); - bool processKeyMessage( const akui::cKeyMessage & msg ); void onOK(); diff --git a/arm9/source/romlauncher.cpp b/arm9/source/romlauncher.cpp index 47d22e3..6adb2a3 100644 --- a/arm9/source/romlauncher.cpp +++ b/arm9/source/romlauncher.cpp @@ -16,38 +16,13 @@ along with this program. If not, see . */ -#include "iocmn.h" #include "romlauncher.h" -#include "../../share/flags.h" +#include "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) @@ -59,10 +34,8 @@ static SAVE_TYPE PrefillGame(u32 aGameCode) { 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 @@ -175,9 +148,7 @@ TLaunchResult launchRom(const std::string& aFullPath,DSRomInfo& aRomInfo,bool aM { 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; @@ -188,42 +159,10 @@ TLaunchResult launchRom(const std::string& aFullPath,DSRomInfo& aRomInfo,bool aM // 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 + flags|=PATCH_DMA; /* if((gameCode&0xffffff)==0x425841) //2385 - Daigassou! Band-Brothers DX (Japan) { @@ -248,38 +187,13 @@ TLaunchResult launchRom(const std::string& aFullPath,DSRomInfo& aRomInfo,bool aM } } -#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<cardControl13=0x00406000|speed; //3in1 support @@ -367,16 +253,6 @@ TLaunchResult launchRom(const std::string& aFullPath,DSRomInfo& aRomInfo,bool aM } 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< +#include #include -#include +#include #include "romloader.h" #include "dbgtool.h" -#include "akloader_arm7_bin.h" -#include "akloader_arm9_bin.h" -#include "savechip.h" +//#include "akloader_arm7_bin.h" +//#include "akloader_arm9_bin.h" #include "savemngr.h" #include "../../share/fifotool.h" -#include "../../share/timetool.h" +#include "timetool.h" #include "globalsettings.h" -#if defined(_STORAGE_rpg) -#include -#endif + +// FIFO_CHANNEL_BITS - number of bits used to specify the channel in a packet - default=4 +#define FIFO_CHANNEL_BITS 4 +#define FIFO_CHANNEL_SHIFT (32-FIFO_CHANNEL_BITS) +#define FIFO_IMMEDIATEBIT_SHIFT (FIFO_CHANNEL_SHIFT-2) +#define FIFO_IMMEDIATEBIT (1<arm7executeAddress = 0x023FA000; +// memcpy( (void *)0x023FA000, akloader_arm7_bin, akloader_arm7_bin_size ); + __NDSHeader->arm7executeAddress = (void*)0x023FA000; // copy loader's arm9 code - memcpy( (void *)0x023c0000, akloader_arm9_bin, akloader_arm9_bin_size ); - __NDSHeader->arm9executeAddress = 0x023c0000; +// memcpy( (void *)0x023c0000, akloader_arm9_bin, akloader_arm9_bin_size ); + __NDSHeader->arm9executeAddress = (void*)0x023c0000; dbg_printf( "load done\n" ); - ELM_Unmount(); - resetAndLoop(); return true; } diff --git a/arm9/source/romloader.h b/arm9/source/romloader.h index 2f8a4f5..0da996f 100644 --- a/arm9/source/romloader.h +++ b/arm9/source/romloader.h @@ -21,12 +21,9 @@ #ifndef _ROMLOADER_H_ #define _ROMLOADER_H_ +#include #include -#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_ diff --git a/arm9/source/save64m.cpp b/arm9/source/save64m.cpp deleted file mode 100644 index 26ccd27..0000000 --- a/arm9/source/save64m.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - 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 . -*/ - -#if defined(_STORAGE_rpg) || defined(_STORAGE_r4) - -#include "save64m.h" -#include -#include -#include "dbgtool.h" -#include "../../share/memtool.h" -#if defined(_STORAGE_rpg) -#include "savemngr.h" -#include -#elif defined(_STORAGE_r4) -#include -#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=0) - { - if(write(f,buffer,KMaxSave*sizeof(u32))==KMaxSave*sizeof(u32)) - { - success=true; - aSaveName=result; - } - close(f); - } - } - return success; -} -#endif - -#endif diff --git a/arm9/source/save64m.h b/arm9/source/save64m.h deleted file mode 100644 index ad6686b..0000000 --- a/arm9/source/save64m.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - 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 . -*/ - -#ifndef __SAVE64M_H__ -#define __SAVE64M_H__ - -#include -#include - -#if defined(_STORAGE_rpg) || defined(_STORAGE_r4) - -#include -#include - -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 diff --git a/arm9/source/savechip.cpp b/arm9/source/savechip.cpp deleted file mode 100644 index b97065e..0000000 --- a/arm9/source/savechip.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* - 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 . -*/ - -#if defined(_STORAGE_rpg) -#include -#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? ʕs - 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> 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 diff --git a/arm9/source/savechip.h b/arm9/source/savechip.h deleted file mode 100644 index a7aa26a..0000000 --- a/arm9/source/savechip.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - savechip.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 . -*/ - -#ifndef _SAVECHIP_H_ -#define _SAVECHIP_H_ - -#include - -#if defined(_STORAGE_rpg) -enum CHIP_TYPE -{ - CT_NONE = 0, - CT_4K, - CT_512K, - CT_8M, - CT_AUTO -}; - -void saveChipRead( u32 address, u8 * data, u32 length, u8 chipType ); -void saveChipWrite( u32 address, u8 * data, u32 length, u8 chipType ); -void saveChipSectorErase( u32 address ); -int saveChipFlashErase(u32 sectorCount); -void saveChipEEPROMErase( int type ); -u8 saveChipGetType(); -u32 saveChipSize( u8 chipType ); -u8 saveChipCMD( u8 cmd, u32 address ); - -#endif - -#endif//_SAVECHIP_H_ diff --git a/arm9/source/savemngr.cpp b/arm9/source/savemngr.cpp index 3213163..7339a71 100644 --- a/arm9/source/savemngr.cpp +++ b/arm9/source/savemngr.cpp @@ -26,14 +26,10 @@ #include "dbgtool.h" #include "systemfilenames.h" #include "progresswnd.h" -#if defined(_STORAGE_rpg) -#include "rpgprotocol.h" -#include "nanddriver.h" -#endif #include "language.h" #include "datetime.h" #include "ui.h" -#include +#include #include #include @@ -41,89 +37,12 @@ using namespace akui; cSaveManager::cSaveManager() { -#if defined(_STORAGE_rpg) - lockSave(); - for( size_t i = 0; i < 64; ++i ) { - _saveBlockTable[i] = 0xFFFFFFFF; - } -#endif } cSaveManager::~cSaveManager() { } -#if defined(_STORAGE_rpg) -//EEP 指令 -//D2 00 00 00 00 00 00 00 -// -//bit 51 - 48 -//48 eep enable -//49 eep to nand enable -//53 - 50 0001=auto 0000=95040 1000=95640 0100=95512 0010=25pe80 - -void selectSaveChip( CHIP_TYPE type, bool nandON ) -{ - u8 byte2 = 0; - switch( type ) - { - case CT_NONE: - byte2 = 0x00; - break; - case CT_4K: - byte2 = 0x03; // 0000 0011 - break; - case CT_512K: - byte2 = 0x13; // 0001 0011 - break; - case CT_8M: - byte2 = 0x0b; // 0000 1011 - break; - case CT_AUTO: // auto detect - byte2 = 0x07; // 0000 0111 - break; - default: - byte2 = 0x00; - }; - if( !nandON ) - byte2 &= 0xFD; // 1111 1101 - - u32 cmd[2] = { 0xd2000000 | (byte2 <<16 ), 0x00000000 }; - ioRpgSendCommand( cmd, 0, 0, NULL ); -} - - -void cSaveManager::lockChips() -{ - selectSaveChip( CT_NONE, false ); -} - -bool cSaveManager::unlockChip(SAVE_TYPE saveType,bool writeToDisk) -{ - CHIP_TYPE chipType=chipTypeFromSaveType(saveType); - selectSaveChip(chipType,writeToDisk); - - if(writeToDisk||CT_AUTO==chipType) - { - clearSaveBlocks(); - u32 nandAddress[64]; - if(!assignSaveBlocks(saveType,chipType,nandAddress)) - return false; - } - return true; -} - -void cSaveManager::lockSave() -{ - lockChips(); -} - -bool cSaveManager::unlockSave(SAVE_TYPE saveType,bool writeToDisk) -{ - return unlockChip(saveType,writeToDisk); -} -#endif - static bool loadSaveList(const std::string& filename,std::vector& buffer) { u8* data=NULL; @@ -141,7 +60,7 @@ static bool loadSaveList(const std::string& filename,std::vector& if(1!=fread(&header,sizeof(header),1,f)) break; if(header.marker!=SAVE_INFO_EX_HEADER_MAGIC) break; data=new u8[header.itemSize*header.itemCount]; - u32 copiedSize=std::min(header.itemSize,sizeof(SAVE_INFO_EX)); + u32 copiedSize=std::min((unsigned int)header.itemSize,sizeof(SAVE_INFO_EX)); if(header.itemCount!=fread(data,header.itemSize,header.itemCount,f)) break; buffer.resize(header.itemCount); for(u32 ii=0;ii= saveDataBuffer + SAVEDATA_BUFFER_SIZE ) { - written = fwrite( saveDataBuffer, 1, SAVEDATA_BUFFER_SIZE, f ); - pSaveDataBuffer = saveDataBuffer; - dbg_printf("written %d\n", written); - } - } - } - } - written = fwrite( saveDataBuffer, 1, pSaveDataBuffer - saveDataBuffer, f ); - dbg_printf("written %d\n", written); - progressWnd().setPercent( 100 ); - - progressWnd().hide(); - fclose( f ); - NandFlush(); - clearLastInfo(); - clearSaveBlocks(); - - delete[] saveDataBuffer; - - return true; -} - -static void checkRedund() -{ - ALIGN(4) u8 cfgPage[528]; - dbg_printf( "checkRedund cfgPage\n"); - ioRpgReadNand( 0x00000000, cfgPage, 528 ); - - // read zones count - u32 totalZones = 1 << (cfgPage[0x0c] - 10); - //wait_press_b(); - - u32 saveBlockTable[64]; - for( size_t i = 0; i < 64; ++i ) - saveBlockTable[i] = 0xFFFFFFFF; - - ALIGN(4) u8 redundData[16]; - u8 ctByte = 0x00; - u32 saveBlockCountCheck = 0; - for( size_t i = 0; i < totalZones * 1024; ++i ) { - ioRpgReadNandRedundant( (i << 17) + 512 * 3, redundData ); - if( redundData[0] != 0xff && redundData[0] != 0x00 ) - dbg_printf("(%02x%02x%02x)", redundData[1],redundData[2],redundData[3] ); - if( redundData[0] >= 0x80 && redundData[0] < 0x80 + 64 ) { - saveBlockCountCheck++; - u8 saveIndex = redundData[3] - 0x80; - if( saveBlockTable[saveIndex] != 0xFFFFFFFF ) { - dbg_printf("checkRedund() FATAL ERROR: Multi save block assign found\n"); - dbg_printf("saveTable[%d] 1=%08x 2=%08x\n", saveIndex, saveBlockTable[saveIndex], (i << 17) ); - wait_press_b(); - } - saveBlockTable[saveIndex] = (i << 17); - if( redundData[2] >= 0xc0 && redundData[2] <= 0xc4 && 0 == ctByte ) { - ctByte = redundData[2]; - } - } - } - - if( saveBlockCountCheck != 0 && saveBlockCountCheck != 16 && saveBlockCountCheck != 32 && saveBlockCountCheck != 64 ) - { - dbg_printf("checkRedund() FATAL ERROR: saveblock COUNT ERROR %d\n", saveBlockCountCheck ); - dbg_printf("totalZones %d\n", totalZones ); - wait_press_b(); - } else { - dbg_printf("checkRedund() OK OK OK OK OK OK OK OK OK OK OK %d\n", saveBlockCountCheck ); - } - - -} - -static void clearSaveSram() -{ - progressWnd().setTipText( LANG("progress window", "processing save") ); - progressWnd().show(); - progressWnd().setPercent( 0 ); - - // clear sram, fill with 0xff, to keep consist with empty save blocks - u32 fillData = 0xFFFFFFFF; - for( size_t i = 0;i < 1024 * 1024; i += 4 ) { - ioRpgWriteSram( SRAM_SAVEDATA_START + i, &fillData, 4 ); - if( !(i % (1024 * 128)) ) { - dbg_printf("clear sram %d%s\n", i*100/(1024*1024), "%" ); - progressWnd().setPercent( i*100 / (1024 * 1024) ); - } - } - for( size_t i = 0;i < 2048; i += 4 ) { - ioRpgWriteSram( SRAM_EEP_BUFFER_START + i, &fillData, 4 ); - } - progressWnd().setPercent(100); -} - -bool cSaveManager::restoreSaveData( const std::string & romFilename, SAVE_TYPE saveType, u8 slot ) -{ - dbg_printf( "SaveManager::restoreSaveData()\n" ); - - CHIP_TYPE chipType = chipTypeFromSaveType( saveType ); - if( CT_NONE == chipType ) { - lockChips(); - saveLastInfo( romFilename ); - return true; - } - - unlockSave( saveType, true ); - checkRedund(); - - if( ST_UNKNOWN == saveType || ST_AUTO == saveType ) { - clearSaveSram(); - saveLastInfo( romFilename ); - return true; - } - - u32 saveSize = saveSizeFromSaveType( saveType ); - std::string saveFilename=generateSaveName(romFilename,slot); - - // - FILE * f = fopen( saveFilename.c_str(), "rb" ); - if( NULL == f ) { - clearSaveSram(); - saveLastInfo( romFilename ); - return true; - } - - // clear FLASH - if(saveType>=ST_2M&&saveType<=ST_8M ) - { - switch(saveType) - { - case ST_2M: - saveChipFlashErase(4); - break; - case ST_4M: - saveChipFlashErase(8); - break; - case ST_8M: - saveChipFlashErase(16); - break; - default: - break; - } - } - - const u32 blockSize = 512; - static ALIGN(4) u8 buffer[blockSize]; - u32 readCount = 0; - - progressWnd().setTipText( LANG("progress window", "processing save") ); - progressWnd().show(); - progressWnd().setPercent( 0 ); - for( u32 i = 0; i < saveSize; i += blockSize ) - { - u8 percent = i * 100 / saveSize; - if( !(percent & 0x07) ) - progressWnd().setPercent( percent ); - - u32 readed = fread( buffer, 1, blockSize, f ); - readCount += readed; - //if( blockSize != readed ) { - // break; - //} - if( 0 == readed ) - break; - saveChipWrite( i, buffer, readed, chipType ); - } - progressWnd().setPercent( 100 ); - progressWnd().hide(); - fclose( f ); - - saveLastInfo( romFilename ); - - return true; -} - -static ALIGN(4) u8 cfgPage[528]; -bool cSaveManager::buildSaveBlockTable( CHIP_TYPE * ct ) -{ - // read cfg page - // 53 4d 54 44 4d 47 20 00 0e 00 01 06 0d (14) 03 02 - dbg_printf( "cfgPage\n"); - ioRpgReadNand( 0x00000000, cfgPage, 528 ); - for( u32 i = 0; i < 16; ++i ) { - dbg_printf("%02x", cfgPage[i] ); - } - // read zones count - u32 totalZones = 1 << (cfgPage[0x0c] - 10); - - for( size_t i = 0; i < 64; ++i ) - _saveBlockTable[i] = 0xFFFFFFFF; - - // if user turn power off during writting save data(in game or in menu), - // the content of save blocks is undefined. Don't write save data to .sav - // file if this function returns false - ALIGN(4) u8 redundData[16]; - u8 ctByte = 0x00; - u32 saveBlockCount = 0; - for( size_t i = 0; i < totalZones * 1024; ++i ) { - ioRpgReadNandRedundant( (i << 17) + 512 * 3, redundData ); - if( redundData[0] != 0xff && redundData[0] != 0x00 && redundData[0] != 0xf0 ) - dbg_printf("(%02x%02x%02x)", redundData[1],redundData[2],redundData[3] ); - - if( redundData[0] >= 0x80 && redundData[0] < 0x80 + 64 ) { - u8 saveIndex = redundData[3] - 0x80; - if( saveIndex < 64 ) { - saveBlockCount++; - if( _saveBlockTable[saveIndex] != 0xFFFFFFFF ) { - dbg_printf("FATAL ERROR: Multi save block assign found\n"); - dbg_printf("saveTable[%d] 1=%08x 2=%08x\n", saveIndex, _saveBlockTable[saveIndex], (i << 17) ); - wait_press_b(); - return false; - } - _saveBlockTable[saveIndex] = (i << 17); - if( redundData[2] >= 0xc0 && redundData[2] <= 0xc4 && 0 == ctByte ) { - ctByte = redundData[2]; - } - } else { - dbg_printf("FATAL ERROR: idx err, shouldn't have a %d\n", saveIndex ); - dbg_printf("redunt0-4:(%02x%02x%02x%02x%02x)\n", redundData[0], redundData[1], - redundData[2],redundData[3], redundData[4] ); - dbg_printf("at block: %d\n", i ); - wait_press_b(); - return false; - } - } - } - dbg_printf( "saveBlockCount %d\n", saveBlockCount ); - if( 0 != saveBlockCount && saveBlockCount != 16 && saveBlockCount != 32 && saveBlockCount != 64 ) { - dbg_printf("FATAL ERROR: Multi save block assign found, saveBlockCount %d\n", saveBlockCount ); - wait_press_b(); - return false; - } - - *ct = CT_NONE; - switch( ctByte ) { - case 0xc0: // 40 - *ct = CT_4K; - break; - case 0xc1: // 80 - *ct = CT_8M; - break; - case 0xc2: // 512 - *ct = CT_512K; - break; - case 0xc4: // 640 - *ct = CT_512K; - break; - default: - *ct = CT_NONE; - } - dbg_printf("save mark %02x, type %d\n", ctByte, *ct ); - //wait_press_b(); - - return true; -} - -bool cSaveManager::clearSaveBlocks() -{ - ioRpgReadNand( 0x00000000, cfgPage, 528 ); - for( u32 i = 0; i < 16; ++i ) { - dbg_printf("%02x", cfgPage[i] ); - } - // read zones count - u32 totalZones = 1 << (cfgPage[0x0c] - 10); - - dbg_printf("clear save: \n"); - ALIGN(4) u8 redundData[16]; - for( size_t i = 0; i < totalZones * 1024; ++i ) { - ioRpgReadNandRedundant( (i << 17) + 512 * 3, redundData ); - if( redundData[0] >= 0x80 && redundData[0] < 0x80 + 64 ) { - ioRpgEraseNand( i << 17 ); - } - } - dbg_printf( "end\n" ); - - // 这个地方是否需要重新建表? - - return true; -} - -int cSaveManager::CompareIndex(const void* a,const void* b) -{ - return (static_cast(a)->iIndex-static_cast(b)->iIndex); -} - -int cSaveManager::CompareFree(const void* a,const void* b) -{ - return (static_cast(a)->iFree-static_cast(b)->iFree); -} - -bool cSaveManager::assignSaveBlocks(SAVE_TYPE saveType,CHIP_TYPE chipType,u32 nandAddress[64]) -{ - if( CT_NONE == chipType ) { - lockChips(); - return true; - } - - memset( nandAddress, 0xFF, 64 * 4 ); - - ioRpgReadNand( 0x00000000, cfgPage, 528 ); - for( u32 i = 0; i < 16; ++i ) { - dbg_printf("%02x", cfgPage[i] ); - } - u32 neededBlocks=32; - if(saveType==ST_8M) neededBlocks=64; - else if(saveType==ST_2M) neededBlocks=16; - // read zones count - u32 totalZones = 1 << (cfgPage[0x0c] - 10); - - SZoneInfo zones[totalZones]; - memset(zones,0,sizeof(SZoneInfo)*totalZones); - u32 totalFreeBlocks=0,totalAllocatedBlocks=0; - for(u32 ii=0;ii=0) { @@ -856,60 +244,9 @@ bool cSaveManager::initializeSaveFile(const std::string& romFilename,u8 slot,u32 } close(f); } - NandFlush(); return res; } -#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i) -bool cSaveManager::generateProtectionFix(const std::string& romFilename,u32 bytesPerCluster) -{ - bool result=false; - std::string fixFilename(romFilename); - fixFilename+=".fix"; - FILE* check=fopen(fixFilename.c_str(),"rb"); - if(check) - { - fclose(check); - return true; - } - NandFast(); - FILE* rom=fopen(romFilename.c_str(),"rb"); - if(rom) - { - fseek(rom,0x8000,SEEK_SET); - char buffer[512]; - if(fread(buffer,512,1,rom)==1) - { - FILE* fix=fopen(fixFilename.c_str(),"wb"); - if(fix) - { - for(int ii=0;ii<64;ii++) - { - if(fwrite(buffer,512,1,fix)!=1) goto error; - } - if(bytesPerCluster>32768) - { - if(fwrite(buffer,512,1,fix)!=1) goto error; - int counter=bytesPerCluster-32768-512; - while(counter>0) - { - if(fread(buffer,512,1,rom)!=1) goto error; - if(fwrite(buffer,512,1,fix)!=1) goto error; - counter-=512; - } - } - result=true; -error: - fclose(fix); - } - } - fclose(rom); - } - NandFlush(); - return result; -} -#endif - std::string cSaveManager::generateSaveName(const std::string& romFilename,u8 slot) { std::string saveFilename(romFilename); @@ -927,68 +264,6 @@ std::string cSaveManager::generateSaveName(const std::string& romFilename,u8 slo return saveFilename; } -#if defined(_STORAGE_rpg) -CHIP_TYPE cSaveManager::chipTypeFromSaveType( SAVE_TYPE saveType ) -{ - if( saveType == ST_NOSAVE ) - return CT_NONE; - if( saveType <= ST_4K ) - return CT_4K; - if( saveType <= ST_512K ) - return CT_512K; - if( saveType <= ST_8M ) - return CT_8M; - if( ST_AUTO == saveType ) - return CT_AUTO; - - return CT_NONE; -} - -SAVE_TYPE cSaveManager::saveTypeFromChipType( CHIP_TYPE chipType ) -{ - switch( chipType ) - { - case CT_4K: - return ST_4K; - case CT_512K: - return ST_512K; - case CT_8M: - return ST_4M; - default: - return ST_UNKNOWN; - } - return ST_UNKNOWN; -} - - -u32 cSaveManager::saveSizeFromSaveType( SAVE_TYPE saveType ) -{ - switch( saveType ) - { - case ST_UNKNOWN: - return 0; - case ST_NOSAVE: - return 0; - case ST_4K: - return 512; - case ST_64K: - return 8192; - case ST_512K: - return 65536; - case ST_2M: - return 262144; - case ST_4M: - return 524288; - case ST_8M: - return 1048576; - case ST_NEW: - return 2097152; - default: - return 0; - }; -} -#endif - SAVE_TYPE cSaveManager::getSaveTypeByFile( const std::string & romFilename ) { return ST_UNKNOWN; diff --git a/arm9/source/savemngr.h b/arm9/source/savemngr.h index 53937d2..82ba972 100644 --- a/arm9/source/savemngr.h +++ b/arm9/source/savemngr.h @@ -25,7 +25,6 @@ #include #include #include "singleton.h" -#include "savechip.h" #include "globalsettings.h" typedef struct _SAVE_INFO_T @@ -186,17 +185,6 @@ typedef struct SAVE_INFO_EX_HEADER_T u32 reserved; } SAVE_INFO_EX_HEADER; -#if defined(_STORAGE_rpg) -typedef struct _SAVE_BLOCK_INFO_T -{ - u32 saveSize; - u32 eepPageSize; - u32 nandPageSize; - u32 validPageCount; - u32 nandBlockCount; -} SAVE_BLOCK_INFO; -#endif - class cSaveManager { public: @@ -219,18 +207,8 @@ class cSaveManager bool clearLastInfo(); -#if defined(_STORAGE_rpg) - bool backupSaveData(); - - bool restoreSaveData( const std::string & romFilename, SAVE_TYPE saveType, u8 slot ); -#endif - static bool initializeSaveFile(const std::string& romFilename,u8 slot,u32 size); -#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i) - static bool generateProtectionFix(const std::string& romFilename,u32 bytesPerCluster); -#endif - static std::string generateSaveName(const std::string& romFilename,u8 slot); SAVE_TYPE getSaveTypeByFile( const std::string & romFilename ); @@ -240,46 +218,7 @@ class cSaveManager static DISPLAY_SAVE_TYPE SaveTypeToDisplaySaveType(SAVE_TYPE aSaveType); static SAVE_TYPE DisplaySaveTypeToSaveType(DISPLAY_SAVE_TYPE aSaveType); -#if defined(_STORAGE_rpg) - void lockSave(); - - bool unlockSave( SAVE_TYPE st, bool writeToDisk ); - - bool clearSaveBlocks(); - - bool buildSaveBlockTable( CHIP_TYPE * ct ); - protected: - struct SZoneInfo - { - u32 iIndex; - u32 iFree; - u32 iAllocated; - u32 iUnused; - }; -#endif - protected: - -#if defined(_STORAGE_rpg) - void lockChips(); - - bool unlockChip( SAVE_TYPE saveType, bool writeToDisk ); - - static u32 saveSizeFromSaveType( SAVE_TYPE saveType ); - - static CHIP_TYPE chipTypeFromSaveType( SAVE_TYPE saveType ); - - static SAVE_TYPE saveTypeFromChipType( CHIP_TYPE chipType ); - - static SAVE_BLOCK_INFO getBlockInfo( CHIP_TYPE chipType ); - - bool assignSaveBlocks( SAVE_TYPE saveType, CHIP_TYPE chipType, u32 nandAddress[64] ); - - static int CompareIndex(const void* a,const void* b); - static int CompareFree(const void* a,const void* b); - - u32 _saveBlockTable[64]; -#endif std::vector _saveList; diff --git a/arm9/source/sdidentify.cpp b/arm9/source/sdidentify.cpp deleted file mode 100644 index 9209cfc..0000000 --- a/arm9/source/sdidentify.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - sdidentify.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 . -*/ - -#include "iocmn.h" -#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i) -#include -#include "timer.h" -#include "sdidentify.h" -#include "irqs.h" -#include "inifile.h" -#include "stringtool.h" -#include "systemfilenames.h" -#include "language.h" -#include "progresswnd.h" - -std::string sdidGetSDName() -{ - u8 sdinfo[8] = {}; - sddGetSDInfo( sdinfo ); - for( u8 i = 0; i < 5; ++i ) { - if( ' ' ==sdinfo[i+1] ) - sdinfo[i+1] = '_'; - } - return (const char *)(sdinfo + 1); - -} - -std::string sdidGetSDManufacturerID() -{ - u8 sdinfo[8] = {}; - sddGetSDInfo( sdinfo ); - return formatString( "%02x", sdinfo[0] ); -} - -std::string sdidGetSDManufacturerName() -{ - CIniFile ini( SFN_SDCARD_LIST ); - u8 sdinfo[8] = {}; - sddGetSDInfo( sdinfo ); - std::string manufacturerID = formatString( "%02x", sdinfo[0] ); - std::string manufacturerName = ini.GetString( "SD Card Manufacturers", manufacturerID, manufacturerID ); - return manufacturerName; -} - -u32 sdidCheckSDSpeed( u32 readCount ) -{ - CIniFile ini( SFN_SDCARD_LIST ); - - std::string name = sdidGetSDName(); - std::string manufacturerID = sdidGetSDManufacturerID(); - - u32 ret = ini.GetInt( "SD Card Speed", manufacturerID + name, 0 ); - - if( ret != 0 ) - return ret; - - u32 totalSectors; - if(!ELM_SectorsFromDisk(ioSD(),&totalSectors)) - { - dbg_printf("no sd card\n"); - return 0; - } - dbg_printf("total sectors %d, max addr %08x\n", totalSectors, (totalSectors << 9) - 0x200); - - // some sd card needs to be readed one time for initialization - sddReadBlocks( 0, 1, NULL ); - - irq().vblankStop(); - double maxAccessTime = 0.f; - - std::string tipText = LANG("progress window", "first use sd"); - progressWnd().setTipText( tipText ); - progressWnd().show(); - progressWnd().setPercent( 0 ); - - vu64 tick1 = 0; - vu64 tick2 = 0; - for( size_t i = 0; i < readCount; ++i ) { - u32 randAddr = ((rand() % totalSectors)<<(isSDHC()?0:9) ) & (~(0x200-1)); - - u32 sdReadSingleBlock[2] = { 0xD5030011, randAddr }; // input read address here - ioRpgSendCommand( sdReadSingleBlock, 0, 80, NULL ); - timer().initTimer(); - tick1 = timer().getTick(); - ioRpgWaitCmdBusy( true ); - tick2 = timer().getTick(); - - u32 readSD[2] = { 0xB7000000, 0x00000000 | 0x00130000 }; // address dont care here - ioRpgSendCommand( readSD, 512, 4, NULL ); - - if( tick2 < tick1 ) { - tick2 += 65536; - } - tick1 = tick2 - tick1; - double timeCostUs = timer().tickToUs( tick1 ); - if( timeCostUs > maxAccessTime ) { - maxAccessTime = timeCostUs; - } - - u32 percent = i * 100 / readCount; - if( (i & 0x1ff) == 0x1ff ) { - dbg_printf( "%02d ", percent ); - progressWnd().setPercent( percent ); - } - } - progressWnd().hide(); - irq().vblankStart(); - - - maxAccessTime = ((u32)(maxAccessTime / 15 + 0.5)) * 15; - - ret = ((u32)(maxAccessTime * 1000 / 150)); - - dbg_printf("max access time: max %4.2fus\n", maxAccessTime ); - - ini.SetInt( "SD Card Speed", manufacturerID + name, ret ); - ini.SaveIniFile( SFN_SDCARD_LIST ); - - return ret; -} -#endif diff --git a/arm9/source/sdidentify.h b/arm9/source/sdidentify.h deleted file mode 100644 index a4e8792..0000000 --- a/arm9/source/sdidentify.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - sdidentify.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 . -*/ - -#ifndef _SDIDENTIFY_H_ -#define _SDIDENTIFY_H_ - -#include -#include - -#if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i) - -std::string sdidGetSDName(); - -std::string sdidGetSDManufacturerID(); - -std::string sdidGetSDManufacturerName(); - -u32 sdidCheckSDSpeed( u32 readCount ); - -#endif - -#endif//_SDIDENTIFY_H_ diff --git a/arm9/source/singleton.h b/arm9/source/singleton.h index 9655d27..a107e29 100644 --- a/arm9/source/singleton.h +++ b/arm9/source/singleton.h @@ -34,8 +34,8 @@ public: { create_instance(); //atexit( release_instance ); - // t_singleton ԼDzʵģ޷ͷڴ - // atexit ˳ʱͷڴ + // t_singleton 他自己是不会有实例的,无法利用析构函数来释放内存 + // 所以利用 atexit 来在整个程序退出时释放内存 } return *_instance; } diff --git a/arm9/source/sram.cpp b/arm9/source/sram.cpp index e17006d..36dcc47 100644 --- a/arm9/source/sram.cpp +++ b/arm9/source/sram.cpp @@ -23,7 +23,7 @@ #include #include "progresswnd.h" #include "language.h" -#include +#include bool cSram::SaveFileName(const char* romName,char* saveName) { @@ -120,7 +120,6 @@ void cSram::SaveSramToFile(const char* romName,u16 aStartPage) saveFile=NULL; } NormalizeSize(saveInfo); - NandFast(); saveFile=fopen(saveName,"wb"); if(saveFile) { @@ -138,7 +137,6 @@ void cSram::SaveSramToFile(const char* romName,u16 aStartPage) progressWnd().hide(); fclose(saveFile); } - NandFlush(); } u8* cSram::SaveSramToMemory(u16 aStartPage,sSaveInfo& aSaveInfo,bool aShowProgress) @@ -179,14 +177,12 @@ void cSram::CreateDefaultFile(const char* romName,u32 size) } else { - NandFast(); FILE* saveFile=fopen(saveName,"wb"); if(saveFile) { fwrite(&saveInfo,sizeof(saveInfo),1,saveFile); fclose(saveFile); } - NandFlush(); } } diff --git a/arm9/source/startmenu.cpp b/arm9/source/startmenu.cpp index a79becf..7512dda 100644 --- a/arm9/source/startmenu.cpp +++ b/arm9/source/startmenu.cpp @@ -29,10 +29,6 @@ using namespace akui; void cStartMenu::init() { - addItem( START_MENU_ITEM_COPY, LANG("start menu", "Copy") ); - addItem( START_MENU_ITEM_CUT, LANG("start menu", "Cut") ); - addItem( START_MENU_ITEM_DELETE, LANG("start menu", "Delete") ); - addItem( START_MENU_ITEM_PASTE, LANG("start menu", "Paste") ); addItem( START_MENU_ITEM_SETTING, LANG("start menu", "Setting") ); addItem( START_MENU_ITEM_INFO, LANG("start menu", "Info") ); addItem( START_MENU_ITEM_HELP, LANG("start menu", "Help") ); diff --git a/arm9/source/startmenu.h b/arm9/source/startmenu.h index 8e61389..45fb7fd 100644 --- a/arm9/source/startmenu.h +++ b/arm9/source/startmenu.h @@ -23,14 +23,10 @@ #include "popmenu.h" -#define START_MENU_ITEM_COPY 0 -#define START_MENU_ITEM_CUT 1 -#define START_MENU_ITEM_DELETE 2 -#define START_MENU_ITEM_PASTE 3 -#define START_MENU_ITEM_SETTING 4 -#define START_MENU_ITEM_INFO 5 -#define START_MENU_ITEM_HELP 6 -#define START_MENU_ITEM_TOOLS 7 +#define START_MENU_ITEM_SETTING 0 +#define START_MENU_ITEM_INFO 1 +#define START_MENU_ITEM_HELP 2 +#define START_MENU_ITEM_TOOLS 3 class cStartMenu : public akui::cPopMenu { diff --git a/share/stringtool.cpp b/arm9/source/stringtool.cpp similarity index 100% rename from share/stringtool.cpp rename to arm9/source/stringtool.cpp diff --git a/share/stringtool.h b/arm9/source/stringtool.h similarity index 100% rename from share/stringtool.h rename to arm9/source/stringtool.h diff --git a/arm9/source/systemfilenames.h b/arm9/source/systemfilenames.h index af65cea..eb44608 100644 --- a/arm9/source/systemfilenames.h +++ b/arm9/source/systemfilenames.h @@ -21,7 +21,7 @@ #ifndef _SYSTEMFILENAMES_H_ #define _SYSTEMFILENAMES_H_ -#define SFN_SYSTEM_DIR "fat0:/__rpg/" +#define SFN_SYSTEM_DIR "fat:/__rpg/" #define SFN_OFFICIAL_SAVELIST SFN_SYSTEM_DIR"savelist.bin" #define SFN_CUSTOM_SAVELIST SFN_SYSTEM_DIR"gamedata.bin" #define SFN_LAST_SAVEINFO SFN_SYSTEM_DIR"lastsave.ini" @@ -29,9 +29,7 @@ #define SFN_SDCARD_LIST SFN_SYSTEM_DIR"sdlist.ini" #define SFN_GLOBAL_SETTINGS SFN_SYSTEM_DIR"globalsettings.ini" #define SFN_FAVORITES SFN_SYSTEM_DIR"favorites.ini" -#if defined(_STORAGE_r4) #define SFN_BACKLIGHT SFN_SYSTEM_DIR"backlight.ini" -#endif #define SFN_UI_DIRECTORY SFN_SYSTEM_DIR"ui/" #define SFN_UI_CURRENT_DIRECTORY SFN_UI_DIRECTORY + gs().uiName + "/" diff --git a/arm9/source/testcases.cpp b/arm9/source/testcases.cpp index 928f7a3..32daaa1 100644 --- a/arm9/source/testcases.cpp +++ b/arm9/source/testcases.cpp @@ -20,11 +20,8 @@ #include #include -#include +#include #include -#if defined(_STORAGE_rpg) -#include -#endif #include #include "dbgtool.h" @@ -38,7 +35,7 @@ void testIni() { CIniFile ini; - ini.LoadIniFile( "fat0:/moonshl/moonshl.ini" ); + ini.LoadIniFile( "fat:/moonshl/moonshl.ini" ); int bright = ini.GetInt( "System", "NDSLiteDefaultBrightness", 0 ); int WhenStandby= ini.GetInt( "BacklightTimeout", "WhenStandby", 0 ); int WhenPicture = ini.GetInt( "BacklightTimeout", "WhenPicture", 0 ); @@ -103,18 +100,15 @@ void testUnicode() void testCopy() { #define CONTINUOUS_COPY_SIZE 16384 -#if defined(_STORAGE_rpg) - ioRpgSetMapTableAddress( MTN_NAND_OFFSET1, 0 ); -#endif static ALIGN(4) u8 copyBuffer[CONTINUOUS_COPY_SIZE]; struct stat srcSt; - if( 0 != stat( "fat0:/1Mdummy.nds", &srcSt ) ) { + if( 0 != stat( "fat:/1Mdummy.nds", &srcSt ) ) { printf( "copy file error\n" ); return; } - FILE * rf = fopen( "fat0:/1Mdummy.nds", "rb" ); - FILE * wf = fopen( "fat0:/__rpg/1Mdummy.nds", "wb" ); + FILE * rf = fopen( "fat:/1Mdummy.nds", "rb" ); + FILE * wf = fopen( "fat:/__rpg/1Mdummy.nds", "wb" ); u32 writeCount = srcSt.st_size / CONTINUOUS_COPY_SIZE; if( srcSt.st_size & (CONTINUOUS_COPY_SIZE - 1) ) @@ -148,12 +142,9 @@ void testCopy() void testWrite() { #define CONTINUOUS_COPY_SIZE 16384 -#if defined(_STORAGE_rpg) - ioRpgSetMapTableAddress( MTN_NAND_OFFSET1, 0 ); -#endif static ALIGN(4) u8 copyBuffer[CONTINUOUS_COPY_SIZE]; - FILE * wf = fopen( "fat0:/__rpg/1mdummy2.bin", "wb" ); + FILE * wf = fopen( "fat:/__rpg/1mdummy2.bin", "wb" ); u32 writeCount = 1024 * 1024 / CONTINUOUS_COPY_SIZE; @@ -184,8 +175,8 @@ void testWrite() void testWriteFile() { - FILE * f = fopen( "fat0:/testWriteSpeed.bin", "wb" ); - //FILE * f = fopen( "fat0:/test_nand4.nds", "wb" ); + FILE * f = fopen( "fat:/testWriteSpeed.bin", "wb" ); + //FILE * f = fopen( "fat:/test_nand4.nds", "wb" ); if( NULL == f ) return; #define SAVEDATA_BUFFER_SIZE (1024 * 1024) @@ -205,43 +196,6 @@ void testWriteFile() fclose( f ); } -#include "files.h" -void testViolenceCopy() -{ - while( true ) { - unlink( "fat0:/800mdummy.rar" ); - if( !copyFile( "fat1:/800mdummy.rar", "fat0:/800mdummy.rar", false ) ) - return; - - FILE * f = fopen("fat0:/800mdummy.rar", "rb"); - u32 readed = 0; - //PrintFreeMem(); - u8 * buffer = new u8[1048576]; - //PrintFreeMem(); - do { - readed = fread( buffer, 1, 1048555, f ); - dbg_printf("."); - scanKeys(); - if( keysHeld() & KEY_R ) { - delete[] buffer; - dbg_printf("\n"); - fclose(f); - return; - } - } while( readed > 0 ); - delete[] buffer; - dbg_printf("\n"); - - fclose(f); - } -} - -void testSDIdentify() -{ - //u16 sdspeed = sdidCheckSDSpeed( 4096 ); - //dbg_printf("sd speed %04x\n\n", sdspeed ); -} - void testTextOut() { //char msg[32] = {}; @@ -280,289 +234,4 @@ void testLoadWithOutSave() //loadRom( shortPath ); } - -#if defined(_STORAGE_rpg) -static void checkRedund( u32 saveBlockTable[64] ) -{ - ALIGN(4) u8 cfgPage[528]; - dbg_printf( "checkRedund cfgPage\n"); - ioRpgReadNand( 0x00000000, cfgPage, 528 ); - - // read zones count - u32 totalZones = 1 << (cfgPage[0x0c] - 10); - //wait_press_b(); - - for( size_t i = 0; i < 64; ++i ) - saveBlockTable[i] = 0xFFFFFFFF; - - ALIGN(4) u8 redundData[16]; - u8 ctByte = 0x00; - u32 saveBlockCountCheck = 0; - for( size_t i = 0; i < totalZones * 1024; ++i ) { - ioRpgReadNandRedundant( (i << 17) + 512 * 3, redundData ); - if( redundData[0] != 0xff && redundData[0] != 0x00 ) - dbg_printf("(%02x%02x%02x)", redundData[1],redundData[2],redundData[3] ); - if( redundData[0] >= 0x80 && redundData[0] < 0x80 + 64 ) { - u8 saveIndex = redundData[3] - 0x80; - if( saveIndex < 64 ) { - saveBlockCountCheck++; - if( saveBlockTable[saveIndex] != 0xFFFFFFFF ) { - dbg_printf("checkRedund() FATAL ERROR: Multi save block assign found\n"); - dbg_printf("saveTable[%d] 1=%08x 2=%08x\n", saveIndex, saveBlockTable[saveIndex], (i << 17) ); - wait_press_b(); - } - saveBlockTable[saveIndex] = (i << 17); - if( redundData[2] >= 0xc0 && redundData[2] <= 0xc4 && 0 == ctByte ) { - ctByte = redundData[2]; - } - } else { - dbg_printf("idx err, shouldn't have a %d\n", saveIndex ); - dbg_printf("redunt0-4:(%02x%02x%02x%02x%02x)\n", redundData[0], redundData[1],redundData[2],redundData[3], redundData[4] ); - dbg_printf("at block: %d\n", i ); - wait_press_b(); - } - } - } - - printf("\n"); - if( saveBlockCountCheck != 0 && saveBlockCountCheck != 32 && saveBlockCountCheck != 64 ) - { - dbg_printf("checkRedund() FATAL ERROR: saveblock COUNT ERROR %d\n", saveBlockCountCheck ); - dbg_printf("totalZones %d\n", totalZones ); - wait_press_b(); - } else { - dbg_printf("checkRedund() OK OK OK OK %d\n", saveBlockCountCheck ); - } - - -} - -void testViolenceEEP4Kauto( u32 count ) -{ - static ALIGN(4) u8 buffer[512]; - static ALIGN(4) u8 verifyBuffer[512]; - - memset( buffer, 0xff, 512 ); - u32 saveBlockTable1[64]; - u32 saveBlockTable2[64]; - u32 round = 0; - while( count-- ) - { - saveManager().unlockSave( ST_AUTO, true ); - - checkRedund( saveBlockTable1 ); - printf("4K"); - - for( size_t count = 0; count < 8; ++count ) { - for( size_t i = 0; i < 512; ++i ) { - buffer[i] = rand() & 0xff; - } - u8 addr = rand() % 512; - while( 0 == (addr % 16) ) { - addr = rand() % 512; - } - u8 length = 16 - (addr % 16); - length &= (~1); - if( length > 0 ) { - saveChipWrite( addr, buffer, length, 1 ); - saveChipRead( addr, verifyBuffer, length, 1 ); - if( 0 != memcmp( buffer, verifyBuffer, length ) ) { - dbg_printf("save verify error\n"); - wait_press_b(); - } - } - dbg_printf("."); - } - dbg_printf("\n"); - - checkRedund( saveBlockTable2 ); - printf("4K"); - - if( 0 != memcmp( saveBlockTable1, saveBlockTable2, 64 * 4 ) ) { - dbg_printf("4K save error, table1/2 are different\n"); - for( size_t i = 0; i < 64; ++i ) { - if( saveBlockTable1[i] != saveBlockTable2[i] ) { - dbg_printf("%d:%08x-%08x\n", i, saveBlockTable1[i], saveBlockTable2[i]); - } - } - dbg_printf("round %d\n", round ); - wait_press_b(); - } - -//////////////////////// - saveManager().clearSaveBlocks(); - - dbg_printf("round %d wait 1 seconds....\n", round ); - swiDelay( 16 * 1000 * 1000 * 1 ); - - scanKeys(); - if( keysHeld() & KEY_R ) { - return; - } - ++round; - - } -} - -void testViolenceEEP512Kauto( u32 count ) -{ - static ALIGN(4) u8 buffer[512]; - static ALIGN(4) u8 verifyBuffer[512]; - - memset( buffer, 0xff, 512 ); - u32 saveBlockTable1[64]; - u32 saveBlockTable2[64]; - u32 round = 0; - while( count-- ) - { - saveManager().unlockSave( ST_AUTO, true ); - - checkRedund( saveBlockTable1 ); - printf("512K"); - - for( size_t count = 0; count < 32; ++count ) { - for( size_t i = 0; i < 512; ++i ) { - buffer[i] = rand() & 0xff; - } - u16 addr = rand() % 65536; - while( 0 == (addr % 128) ) { - addr = rand() % 65536; - } - u8 length = 128 - (addr % 128); - length &= (~1); - if( length > 0 ) { - saveChipWrite( addr, buffer, length, 2 ); - saveChipRead( addr, verifyBuffer, length, 2 ); - if( 0 != memcmp( buffer, verifyBuffer, length ) ) { - dbg_printf("save verify error\n"); - wait_press_b(); - } - } - dbg_printf("."); - } - dbg_printf("\n"); - - checkRedund( saveBlockTable2 ); - printf("512K"); - - if( 0 != memcmp( saveBlockTable1, saveBlockTable2, 64 * 4 ) ) { - dbg_printf("512K save error, table1/2 are different\n"); - for( size_t i = 0; i < 64; ++i ) { - if( saveBlockTable1[i] != saveBlockTable2[i] ) { - dbg_printf("%d:%08x-%08x\n", i, saveBlockTable1[i], saveBlockTable2[i]); - } - } - dbg_printf("round %d\n", round ); - wait_press_b(); - } - -//////////////////////// - saveManager().clearSaveBlocks(); - - dbg_printf("round %d wait 1 seconds....\n", round ); - swiDelay( 16 * 1000 * 1000 * 1 ); - - scanKeys(); - if( keysHeld() & KEY_R ) { - return; - } - ++round; - - } -} - -void testViolenceEEP8Mauto( u32 count ) -{ - static ALIGN(4) u8 buffer[512]; - static ALIGN(4) u8 verifyBuffer[512]; - - memset( buffer, 0xff, 512 ); - u32 saveBlockTable1[64]; - u32 saveBlockTable2[64]; - u32 round = 0; - while( count-- ) - { - saveManager().unlockSave( ST_AUTO, true ); - - checkRedund( saveBlockTable1 ); - printf("8M"); - - for( size_t count = 0; count < 1; ++count ) { - for( size_t i = 0; i < 512; ++i ) { - buffer[i] = rand() & 0xff; - } - u32 addr = rand() % 1048576; - while( 0 == (addr % 256) ) { - addr = rand() % 1048576; - } - u8 length = 256 - (addr % 256); - length &= (~1); - if( length > 0 ) { - saveChipWrite( addr, buffer, length, 3 ); - saveChipRead( addr, verifyBuffer, length, 3 ); - if( 0 != memcmp( buffer, verifyBuffer, length ) ) { - dbg_printf("save verify error\n"); - wait_press_b(); - } - } - dbg_printf("."); - } - dbg_printf("\n"); - - checkRedund( saveBlockTable2 ); - printf("8M"); - - if( 0 != memcmp( saveBlockTable1, saveBlockTable2, 64 * 4 ) ) { - dbg_printf("8M save error, table1/2 are different\n"); - for( size_t i = 0; i < 64; ++i ) { - if( saveBlockTable1[i] != saveBlockTable2[i] ) { - dbg_printf("%d:%08x-%08x\n", i, saveBlockTable1[i], saveBlockTable2[i]); - } - } - dbg_printf("round %d\n", round ); - wait_press_b(); - } - -//////////////////////// - saveManager().clearSaveBlocks(); - - dbg_printf("round %d wait 1 seconds....\n", round ); - swiDelay( 16 * 1000 * 1000 * 1 ); - - scanKeys(); - if( keysHeld() & KEY_R ) { - return; - } - ++round; - - } -} - -void testEEPReadStatus() -{ - REG_AUXSPICNT = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40; - - REG_AUXSPIDATA = 0x05; - while (REG_AUXSPICNT & /*BUSY*/0x80); - - REG_AUXSPIDATA = 0x00; - while (REG_AUXSPICNT & /*BUSY*/0x80); - - u8 d = REG_AUXSPIDATA; - - dbg_printf("cmd 05 returns %02x\n", d ); - - REG_AUXSPICNT = /*MODE*/0x40; - -} -#endif - -void testGetDiskFreeSpace() -{ - u64 dirSize = 0; - if( getDirSize( "fat0:/", true, &dirSize ) ) { - dbg_printf("fat0 file takes %d bytes\n", dirSize ); - } -} - #endif//DEBUG diff --git a/arm9/source/testcases.h b/arm9/source/testcases.h index 4135ce4..8e77ca2 100644 --- a/arm9/source/testcases.h +++ b/arm9/source/testcases.h @@ -39,10 +39,6 @@ void testViolenceEEP512Kauto( u32 count ); void testViolenceEEP8Mauto( u32 count ); -void testViolenceCopy(); - void testEEPReadStatus(); -void testGetDiskFreeSpace(); - #endif//_TESTCASES_H_ diff --git a/arm9/source/timer.cpp b/arm9/source/timer.cpp index a394a0d..2e926da 100644 --- a/arm9/source/timer.cpp +++ b/arm9/source/timer.cpp @@ -74,7 +74,7 @@ vu64 cTimer::getTick() static vu64 lastTick = 0; vu64 tick = _overFlow + TIMER0_DATA; if( tick < lastTick ) - tick += 65536;// ʱ TIMER0_DATA Ѿ0overflow ûмϣʱҪ65536 + tick += 65536;// 有时候 TIMER0_DATA 已经归0,但overflow 还没有加上,这个时候需要加上65536 lastTick = tick; irqEnable( IRQ_TIMER0 ); return tick; diff --git a/arm9/source/timer.h b/arm9/source/timer.h index cf99ae6..f2f10ee 100644 --- a/arm9/source/timer.h +++ b/arm9/source/timer.h @@ -54,7 +54,7 @@ private: double _lastTime; double _currentTime; static vu64 _overFlow; - static const double _factor = 1.f/(33.514*1000000.f); + const double _factor = 1.f/(33.514*1000000.f); double _fps; u32 _fpsCounter; }; diff --git a/share/timetool.cpp b/arm9/source/timetool.cpp similarity index 100% rename from share/timetool.cpp rename to arm9/source/timetool.cpp diff --git a/share/timetool.h b/arm9/source/timetool.h similarity index 100% rename from share/timetool.h rename to arm9/source/timetool.h diff --git a/arm9/source/ui/bitmapdesc.h b/arm9/source/ui/bitmapdesc.h index 377741f..e032a05 100644 --- a/arm9/source/ui/bitmapdesc.h +++ b/arm9/source/ui/bitmapdesc.h @@ -27,7 +27,7 @@ namespace akui { -// bitmap descֻ𻭱 +// bitmap desc,只负责画背景 enum BLTMODE { BM_BITBLT, diff --git a/arm9/source/ui/button.cpp b/arm9/source/ui/button.cpp index ea6eaa9..b390a8d 100644 --- a/arm9/source/ui/button.cpp +++ b/arm9/source/ui/button.cpp @@ -175,7 +175,7 @@ void cButtonDesc::draw( const cRect & area, GRAPHICS_ENGINE engine ) const _background.width(), height, _button->selectedEngine() ); } - // + // 按半角字来算 u32 textPixels = font().getStringScreenWidth( _button->text().c_str(), _button->text().size() ); u32 textX = 0, textY = area.position().y + (( area.size().y - SYSTEM_FONT_HEIGHT ) >> 1 ) + 1; switch(_button->alignment()) diff --git a/arm9/source/ui/button.h b/arm9/source/ui/button.h index ac29756..886ac55 100644 --- a/arm9/source/ui/button.h +++ b/arm9/source/ui/button.h @@ -110,7 +110,7 @@ protected: }; -// form descֻ𻭱 +// form desc,只负责画背景 class cButtonDesc : public cRenderDesc { public: diff --git a/arm9/source/ui/form.cpp b/arm9/source/ui/form.cpp index 3c96ca5..e1a808d 100644 --- a/arm9/source/ui/form.cpp +++ b/arm9/source/ui/form.cpp @@ -21,7 +21,6 @@ #include "ui.h" #include "form.h" #include "timer.h" -//#include "files.h" //#include "dbgtool.h" //#include "windowmanager.h" @@ -165,7 +164,7 @@ bool cForm::processKeyMessage( const cKeyMessage & msg ) cWindow* cForm::windowBelow(const cPoint& p) { - cWindow* ret = cWindow::windowBelow(p); // ȿԼڲڵ + cWindow* ret = cWindow::windowBelow(p); // 先看自己在不在点下面 if(ret != 0) { diff --git a/arm9/source/ui/formdesc.cpp b/arm9/source/ui/formdesc.cpp index 1f9a660..0d6a9cc 100644 --- a/arm9/source/ui/formdesc.cpp +++ b/arm9/source/ui/formdesc.cpp @@ -27,9 +27,9 @@ namespace akui { -// ߿ɫb5c71f +// 边框颜色:b5c71f // 23, 25, 4 -// ڱɫeeebae +// 框内背景色:eeebae // 30, 29, 22 cFormDesc::cFormDesc() diff --git a/arm9/source/ui/listview.cpp b/arm9/source/ui/listview.cpp index 4e9b438..f69c2b0 100644 --- a/arm9/source/ui/listview.cpp +++ b/arm9/source/ui/listview.cpp @@ -18,12 +18,11 @@ along with this program. If not, see . */ -// +//� #include "ui.h" #include "listview.h" //#include "gdi.h" -//#include "files.h" //#include "dbgtool.h" namespace akui { @@ -99,7 +98,7 @@ bool cListView::insertRow( size_t index, const std::vector< std::string > & text { std::string itemText; if( col >= texts.size() ) - itemText = "Empty"; // Ĭַ + itemText = "Empty"; // 默认字符串 else itemText = texts[col]; diff --git a/arm9/source/ui/msgbox.cpp b/arm9/source/ui/msgbox.cpp index bd33ebb..ff4855e 100644 --- a/arm9/source/ui/msgbox.cpp +++ b/arm9/source/ui/msgbox.cpp @@ -109,10 +109,10 @@ cMessageBox::cMessageBox( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const st s16 nextButtonX = size().x; s16 buttonPitch = 60; s16 buttonY = size().y - _buttonNO->size().y - 4; - // һҪİťλ + // 下一个要画的按钮的位置 if( _style & MB_NO ) { - // nextButtonXλû NO ť - // nextButtonX -= ť + հ + // 在nextButtonX位置画 NO 按钮 + // nextButtonX -= 按钮宽度 + 空白区宽度 buttonPitch = _buttonNO->size().x + 8; nextButtonX -= buttonPitch; _buttonNO->setRelativePosition( cPoint(nextButtonX, buttonY) ); @@ -121,8 +121,8 @@ cMessageBox::cMessageBox( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const st if( _style & MB_YES ) { - // nextButtonXλû YES ť - // nextButtonX -= ť + հ + // 在nextButtonX位置画 YES 按钮 + // nextButtonX -= 按钮宽度 + 空白区宽度 buttonPitch = _buttonYES->size().x + 8; nextButtonX -= buttonPitch; _buttonYES->setRelativePosition( cPoint(nextButtonX, buttonY) ); @@ -131,8 +131,8 @@ cMessageBox::cMessageBox( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const st if( _style & MB_CANCEL ) { - // nextButtonXλû CANCEL ť - // nextButtonX -= ť + հ + // 在nextButtonX位置画 CANCEL 按钮 + // nextButtonX -= 按钮宽度 + 空白区宽度 buttonPitch = _buttonCANCEL->size().x + 8; nextButtonX -= buttonPitch; _buttonCANCEL->setRelativePosition( cPoint(nextButtonX, buttonY) ); @@ -140,8 +140,8 @@ cMessageBox::cMessageBox( s32 x, s32 y, u32 w, u32 h, cWindow * parent, const st } if( _style & MB_OK ) { - // nextButtonXλû OK ť - // nextButtonX -= ť + հ + // 在nextButtonX位置画 OK 按钮 + // nextButtonX -= 按钮宽度 + 空白区宽度 buttonPitch = _buttonOK->size().x + 8; nextButtonX -= buttonPitch; _buttonOK->setRelativePosition( cPoint(nextButtonX, buttonY) ); @@ -238,7 +238,7 @@ cWindow& cMessageBox::loadAppearance(const std::string& aFileName ) u32 messageBox( cWindow * parent, const std::string & title, const std::string & msg, u32 style ) { - // check point ֵĶԻʧͼ + // check point 如果出现奇怪的对话框消失问题就检查这里 cMessageBox msgbox( 12, 36, 232, 120, parent, title, msg, style ); //cMessageBox msgbox( 0, 0, 256, 192, parent, text, style ); diff --git a/arm9/source/ui/point.h b/arm9/source/ui/point.h index 8f77f40..1a65634 100644 --- a/arm9/source/ui/point.h +++ b/arm9/source/ui/point.h @@ -43,14 +43,14 @@ namespace akui t_point& operator+=(const t_point &p) { x+=p.x,y+=p.y; return *this; } t_point& operator-=(const t_point &p) { x-=p.x,y-=p.y; return *this; } t_point& operator=(const t_point &p) { x=p.x,y=p.y; return *this; } - //ǰǷp - bool is_left(const t_point &p) const { return xp.x; } // Ƿڵұ - //ǰǷpϷ - bool is_up(const t_point &p) const { return yp.y; } // Ƿڵ± + //当前点是否在p的左侧 + bool is_left(const t_point &p) const { return xp.x; } // 是否在点的右边 + //当前点是否在p的上方 + bool is_up(const t_point &p) const { return yp.y; } // 是否在点的下边 t_point& operator () (value_type x_,value_type y_){x=x_;y=y_;return *this;} }; diff --git a/arm9/source/ui/popmenu.cpp b/arm9/source/ui/popmenu.cpp index fc8328f..a65955b 100644 --- a/arm9/source/ui/popmenu.cpp +++ b/arm9/source/ui/popmenu.cpp @@ -18,7 +18,7 @@ along with this program. If not, see . */ -// +//� #include "ui.h" #include "popmenu.h" @@ -92,7 +92,7 @@ void cPopMenu::draw() void cPopMenu::drawItems() { - // ѭitem֣ selected ־Ȼѡ + // 循环绘制item文字,遇见 selected 文字就先绘制选择条 for( size_t i = 0; i < _items.size(); ++i ) { s16 itemX = _position.x + _itemTopLeftPoint.x; @@ -197,7 +197,7 @@ bool cPopMenu::processTouchMessage( const cTouchMessage & msg ) return ret; } -u32 cPopMenu::itemBelowPoint( const cPoint & pt ) +size_t cPopMenu::itemBelowPoint( const cPoint & pt ) { cPoint menuPos(position().x + _barLeft, position().y + _itemTopLeftPoint.y - 2); cSize menuSize(barWidth(), _itemHeight * _items.size()); cRect rect(menuPos, menuPos + menuSize); diff --git a/arm9/source/ui/popmenu.h b/arm9/source/ui/popmenu.h index 5f96975..c003486 100644 --- a/arm9/source/ui/popmenu.h +++ b/arm9/source/ui/popmenu.h @@ -44,7 +44,7 @@ public: bool process( const cMessage & msg ); - // ѡе + // 返回选中的项 void popup(); void addItem( size_t index, const std::string & itemText ); diff --git a/arm9/source/ui/sigslot.h.new b/arm9/source/ui/sigslot.h.new deleted file mode 100644 index b9c9f76..0000000 --- a/arm9/source/ui/sigslot.h.new +++ /dev/null @@ -1,2500 +0,0 @@ -// sigslot.h: Signal/Slot classes -// -// Written by Sarah Thompson (sarah@telergy.com) 2002. -// -// License: Public domain. You are free to use this code however you like, with the proviso that -// the author takes on no responsibility or liability for any use. -// -// QUICK DOCUMENTATION -// -// (see also the full documentation at http://sigslot.sourceforge.net/) -// -// #define switches -// SIGSLOT_PURE_ISO - Define this to force ISO C++ compliance. This also disables -// all of the thread safety support on platforms where it is -// available. -// -// SIGSLOT_USE_POSIX_THREADS - Force use of Posix threads when using a C++ compiler other than -// gcc on a platform that supports Posix threads. (When using gcc, -// this is the default - use SIGSLOT_PURE_ISO to disable this if -// necessary) -// -// SIGSLOT_DEFAULT_MT_POLICY - Where thread support is enabled, this defaults to multi_threaded_global. -// Otherwise, the default is single_threaded. #define this yourself to -// override the default. In pure ISO mode, anything other than -// single_threaded will cause a compiler error. -// -// PLATFORM NOTES -// -// Win32 - On Win32, the WIN32 symbol must be #defined. Most mainstream -// compilers do this by default, but you may need to define it -// yourself if your build environment is less standard. This causes -// the Win32 thread support to be compiled in and used automatically. -// -// Unix/Linux/BSD, etc. - If you're using gcc, it is assumed that you have Posix threads -// available, so they are used automatically. You can override this -// (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using -// something other than gcc but still want to use Posix threads, you -// need to #define SIGSLOT_USE_POSIX_THREADS. -// -// ISO C++ - If none of the supported platforms are detected, or if -// SIGSLOT_PURE_ISO is defined, all multithreading support is turned off, -// along with any code that might cause a pure ISO C++ environment to -// complain. Before you ask, gcc -ansi -pedantic won't compile this -// library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of -// errors that aren't really there. If you feel like investigating this, -// please contact the author. -// -// -// THREADING MODES -// -// single_threaded - Your program is assumed to be single threaded from the point of view -// of signal/slot usage (i.e. all objects using signals and slots are -// created and destroyed from a single thread). Behaviour if objects are -// destroyed concurrently is undefined (i.e. you'll get the occasional -// segmentation fault/memory exception). -// -// multi_threaded_global - Your program is assumed to be multi threaded. Objects using signals and -// slots can be safely created and destroyed from any thread, even when -// connections exist. In multi_threaded_global mode, this is achieved by a -// single global mutex (actually a critical section on Windows because they -// are faster). This option uses less OS resources, but results in more -// opportunities for contention, possibly resulting in more context switches -// than are strictly necessary. -// -// multi_threaded_local - Behaviour in this mode is essentially the same as multi_threaded_global, -// except that each signal, and each object that inherits has_slots, all -// have their own mutex/critical section. In practice, this means that -// mutex collisions (and hence context switches) only happen if they are -// absolutely essential. However, on some platforms, creating a lot of -// mutexes can slow down the whole OS, so use this option with care. -// -// USING THE LIBRARY -// -// See the full documentation at http://sigslot.sourceforge.net/ -// -// - -#ifndef SIGSLOT_H__ -#define SIGSLOT_H__ - -#define SIGSLOT_PURE_ISO - -#include -#include - - -#if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS)) -# define _SIGSLOT_SINGLE_THREADED -#elif defined(WIN32) -# define _SIGSLOT_HAS_WIN32_THREADS -# include -#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS) -# define _SIGSLOT_HAS_POSIX_THREADS -# include -#else -# define _SIGSLOT_SINGLE_THREADED -#endif - -#ifndef SIGSLOT_DEFAULT_MT_POLICY -# ifdef _SIGSLOT_SINGLE_THREADED -# define SIGSLOT_DEFAULT_MT_POLICY single_threaded -# else -# define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local -# endif -#endif - - -namespace sigslot { - - class single_threaded - { - public: - single_threaded() - { - ; - } - - virtual ~single_threaded() - { - ; - } - - virtual void lock() - { - ; - } - - virtual void unlock() - { - ; - } - }; - -#ifdef _SIGSLOT_HAS_WIN32_THREADS - // The multi threading policies only get compiled in if they are enabled. - class multi_threaded_global - { - public: - multi_threaded_global() - { - static bool isinitialised = false; - - if(!isinitialised) - { - InitializeCriticalSection(get_critsec()); - isinitialised = true; - } - } - - multi_threaded_global(const multi_threaded_global&) - { - ; - } - - virtual ~multi_threaded_global() - { - ; - } - - virtual void lock() - { - EnterCriticalSection(get_critsec()); - } - - virtual void unlock() - { - LeaveCriticalSection(get_critsec()); - } - - private: - CRITICAL_SECTION* get_critsec() - { - static CRITICAL_SECTION g_critsec; - return &g_critsec; - } - }; - - class multi_threaded_local - { - public: - multi_threaded_local() - { - InitializeCriticalSection(&m_critsec); - } - - multi_threaded_local(const multi_threaded_local&) - { - InitializeCriticalSection(&m_critsec); - } - - virtual ~multi_threaded_local() - { - DeleteCriticalSection(&m_critsec); - } - - virtual void lock() - { - EnterCriticalSection(&m_critsec); - } - - virtual void unlock() - { - LeaveCriticalSection(&m_critsec); - } - - private: - CRITICAL_SECTION m_critsec; - }; -#endif // _SIGSLOT_HAS_WIN32_THREADS - -#ifdef _SIGSLOT_HAS_POSIX_THREADS - // The multi threading policies only get compiled in if they are enabled. - class multi_threaded_global - { - public: - multi_threaded_global() - { - pthread_mutex_init(get_mutex(), NULL); - } - - multi_threaded_global(const multi_threaded_global&) - { - ; - } - - virtual ~multi_threaded_global() - { - ; - } - - virtual void lock() - { - pthread_mutex_lock(get_mutex()); - } - - virtual void unlock() - { - pthread_mutex_unlock(get_mutex()); - } - - private: - pthread_mutex_t* get_mutex() - { - static pthread_mutex_t g_mutex; - return &g_mutex; - } - }; - - class multi_threaded_local - { - public: - multi_threaded_local() - { - pthread_mutex_init(&m_mutex, NULL); - } - - multi_threaded_local(const multi_threaded_local&) - { - pthread_mutex_init(&m_mutex, NULL); - } - - virtual ~multi_threaded_local() - { - pthread_mutex_destroy(&m_mutex); - } - - virtual void lock() - { - pthread_mutex_lock(&m_mutex); - } - - virtual void unlock() - { - pthread_mutex_unlock(&m_mutex); - } - - private: - pthread_mutex_t m_mutex; - }; -#endif // _SIGSLOT_HAS_POSIX_THREADS - - template - class lock_block - { - public: - mt_policy *m_mutex; - - lock_block(mt_policy *mtx) - : m_mutex(mtx) - { - m_mutex->lock(); - } - - ~lock_block() - { - m_mutex->unlock(); - } - }; - - template - class has_slots; - - template - class _connection_base0 - { - public: - virtual has_slots* getdest() const = 0; - virtual void emit() = 0; - virtual _connection_base0* clone() = 0; - virtual _connection_base0* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base1 - { - public: - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type) = 0; - virtual _connection_base1* clone() = 0; - virtual _connection_base1* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base2 - { - public: - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type) = 0; - virtual _connection_base2* clone() = 0; - virtual _connection_base2* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base3 - { - public: - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type) = 0; - virtual _connection_base3* clone() = 0; - virtual _connection_base3* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base4 - { - public: - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0; - virtual _connection_base4* clone() = 0; - virtual _connection_base4* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base5 - { - public: - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type) = 0; - virtual _connection_base5* clone() = 0; - virtual _connection_base5* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base6 - { - public: - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type) = 0; - virtual _connection_base6* clone() = 0; - virtual _connection_base6* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base7 - { - public: - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type, arg7_type) = 0; - virtual _connection_base7* clone() = 0; - virtual _connection_base7* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _connection_base8 - { - public: - virtual has_slots* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type, arg7_type, arg8_type) = 0; - virtual _connection_base8* clone() = 0; - virtual _connection_base8* duplicate(has_slots* pnewdest) = 0; - }; - - template - class _signal_base : public mt_policy - { - public: - virtual void slot_disconnect(has_slots* pslot) = 0; - virtual void slot_duplicate(const has_slots* poldslot, has_slots* pnewslot) = 0; - }; - - template - class has_slots : public mt_policy - { - private: - typedef typename std::set<_signal_base *> sender_set; - typedef typename sender_set::const_iterator const_iterator; - - public: - has_slots() - { - ; - } - - has_slots(const has_slots& hs) - : mt_policy(hs) - { - lock_block lock(this); - const_iterator it = hs.m_senders.begin(); - const_iterator itEnd = hs.m_senders.end(); - - while(it != itEnd) - { - (*it)->slot_duplicate(&hs, this); - m_senders.insert(*it); - ++it; - } - } - - void signal_connect(_signal_base* sender) - { - lock_block lock(this); - m_senders.insert(sender); - } - - void signal_disconnect(_signal_base* sender) - { - lock_block lock(this); - m_senders.erase(sender); - } - - virtual ~has_slots() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - const_iterator it = m_senders.begin(); - const_iterator itEnd = m_senders.end(); - - while(it != itEnd) - { - (*it)->slot_disconnect(this); - ++it; - } - - m_senders.erase(m_senders.begin(), m_senders.end()); - } - - private: - sender_set m_senders; - }; - - template - class _signal_base0 : public _signal_base - { - public: - typedef typename std::list<_connection_base0 *> connections_list; - - _signal_base0() - { - ; - } - - _signal_base0(const _signal_base0& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - ~_signal_base0() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base1 : public _signal_base - { - public: - typedef std::list<_connection_base1 *> connections_list; - - _signal_base1() - { - ; - } - - _signal_base1(const _signal_base1& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base1() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base2 : public _signal_base - { - public: - typedef std::list<_connection_base2 *> - connections_list; - - _signal_base2() - { - ; - } - - _signal_base2(const _signal_base2& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base2() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base3 : public _signal_base - { - public: - typedef std::list<_connection_base3 *> - connections_list; - - _signal_base3() - { - ; - } - - _signal_base3(const _signal_base3& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base3() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base4 : public _signal_base - { - public: - typedef std::list<_connection_base4 *> connections_list; - - _signal_base4() - { - ; - } - - _signal_base4(const _signal_base4& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base4() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base5 : public _signal_base - { - public: - typedef std::list<_connection_base5 *> connections_list; - - _signal_base5() - { - ; - } - - _signal_base5(const _signal_base5& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base5() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base6 : public _signal_base - { - public: - typedef std::list<_connection_base6 *> connections_list; - - _signal_base6() - { - ; - } - - _signal_base6(const _signal_base6& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base6() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base7 : public _signal_base - { - public: - typedef std::list<_connection_base7 *> connections_list; - - _signal_base7() - { - ; - } - - _signal_base7(const _signal_base7& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base7() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base8 : public _signal_base - { - public: - typedef std::list<_connection_base8 *> - connections_list; - - _signal_base8() - { - ; - } - - _signal_base8(const _signal_base8& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base8() - { - disconnect_all(); - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - - void disconnect(has_slots* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - m_connected_slots.erase(it); - // delete *it; - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - - template - class _connection0 : public _connection_base0 - { - public: - _connection0() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection0(dest_type* pobject, void (dest_type::*pmemfun)()) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual _connection_base0* clone() - { - return new _connection0(*this); - } - - virtual _connection_base0* duplicate(has_slots* pnewdest) - { - return new _connection0((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit() - { - (m_pobject->*m_pmemfun)(); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(); - }; - - template - class _connection1 : public _connection_base1 - { - public: - _connection1() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual _connection_base1* clone() - { - return new _connection1(*this); - } - - virtual _connection_base1* duplicate(has_slots* pnewdest) - { - return new _connection1((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1) - { - (m_pobject->*m_pmemfun)(a1); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type); - }; - - template - class _connection2 : public _connection_base2 - { - public: - _connection2() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual _connection_base2* clone() - { - return new _connection2(*this); - } - - virtual _connection_base2* duplicate(has_slots* pnewdest) - { - return new _connection2((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2) - { - (m_pobject->*m_pmemfun)(a1, a2); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type); - }; - - template - class _connection3 : public _connection_base3 - { - public: - _connection3() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual _connection_base3* clone() - { - return new _connection3(*this); - } - - virtual _connection_base3* duplicate(has_slots* pnewdest) - { - return new _connection3((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3) - { - (m_pobject->*m_pmemfun)(a1, a2, a3); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type); - }; - - template - class _connection4 : public _connection_base4 - { - public: - _connection4() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual _connection_base4* clone() - { - return new _connection4(*this); - } - - virtual _connection_base4* duplicate(has_slots* pnewdest) - { - return new _connection4((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, - arg4_type a4) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, - arg4_type); - }; - - template - class _connection5 : public _connection_base5 - { - public: - _connection5() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual _connection_base5* clone() - { - return new _connection5(*this); - } - - virtual _connection_base5* duplicate(has_slots* pnewdest) - { - return new _connection5((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type); - }; - - template - class _connection6 : public _connection_base6 - { - public: - _connection6() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual _connection_base6* clone() - { - return new _connection6(*this); - } - - virtual _connection_base6* duplicate(has_slots* pnewdest) - { - return new _connection6((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type); - }; - - template - class _connection7 : public _connection_base7 - { - public: - _connection7() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual _connection_base7* clone() - { - return new _connection7(*this); - } - - virtual _connection_base7* duplicate(has_slots* pnewdest) - { - return new _connection7((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type, arg7_type); - }; - - template - class _connection8 : public _connection_base8 - { - public: - _connection8() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type, arg8_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual _connection_base8* clone() - { - return new _connection8(*this); - } - - virtual _connection_base8* duplicate(has_slots* pnewdest) - { - return new _connection8((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8); - } - - virtual has_slots* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type, arg7_type, arg8_type); - }; - - template - class signal0 : public _signal_base0 - { - public: - signal0() - { - ; - } - - signal0(const signal0& s) - : _signal_base0(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)()) - { - lock_block lock(this); - _connection0* conn = - new _connection0(pclass, pmemfun); - _signal_base0::m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit() - { - lock_block lock(this); - typename _signal_base0::connections_list::const_iterator itNext, it = _signal_base0::m_connected_slots.begin(); - typename _signal_base0::connections_list::const_iterator itEnd = _signal_base0::m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(); - - it = itNext; - } - } - - void operator()() - { - lock_block lock(this); - typename _signal_base0::connections_list::const_iterator itNext, it = _signal_base0::m_connected_slots.begin(); - typename _signal_base0::connections_list::const_iterator itEnd = _signal_base0::m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(); - - it = itNext; - } - } - }; - - template - class signal1 : public _signal_base1 - { - public: - signal1() - { - ; - } - - signal1(const signal1& s) - : _signal_base1(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type)) - { - lock_block lock(this); - _connection1* conn = - new _connection1(pclass, pmemfun); - _signal_base1::m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1); - - it = itNext; - } - } - - void operator()(arg1_type a1) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1); - - it = itNext; - } - } - }; - - template - class signal2 : public _signal_base2 - { - public: - signal2() - { - ; - } - - signal2(const signal2& s) - : _signal_base2(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type)) - { - lock_block lock(this); - _connection2* conn = new - _connection2(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2); - - it = itNext; - } - } - }; - - template - class signal3 : public _signal_base3 - { - public: - signal3() - { - ; - } - - signal3(const signal3& s) - : _signal_base3(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type)) - { - lock_block lock(this); - _connection3* conn = - new _connection3(pclass, - pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3); - - it = itNext; - } - } - }; - - template - class signal4 : public _signal_base4 - { - public: - signal4() - { - ; - } - - signal4(const signal4& s) - : _signal_base4(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type)) - { - lock_block lock(this); - _connection4* - conn = new _connection4(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4); - - it = itNext; - } - } - }; - - template - class signal5 : public _signal_base5 - { - public: - signal5() - { - ; - } - - signal5(const signal5& s) - : _signal_base5(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type)) - { - lock_block lock(this); - _connection5* conn = new _connection5(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5); - - it = itNext; - } - } - }; - - - template - class signal6 : public _signal_base6 - { - public: - signal6() - { - ; - } - - signal6(const signal6& s) - : _signal_base6(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) - { - lock_block lock(this); - _connection6* conn = - new _connection6(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6); - - it = itNext; - } - } - }; - - template - class signal7 : public _signal_base7 - { - public: - signal7() - { - ; - } - - signal7(const signal7& s) - : _signal_base7(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type)) - { - lock_block lock(this); - _connection7* conn = - new _connection7(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7); - - it = itNext; - } - } - }; - - template - class signal8 : public _signal_base8 - { - public: - signal8() - { - ; - } - - signal8(const signal8& s) - : _signal_base8(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type, arg8_type)) - { - lock_block lock(this); - _connection8* conn = - new _connection8(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); - - it = itNext; - } - } - }; - -}; // namespace sigslot - -#endif // SIGSLOT_H__ - diff --git a/arm9/source/ui/ui.h b/arm9/source/ui/ui.h index 658e547..b13efdf 100644 --- a/arm9/source/ui/ui.h +++ b/arm9/source/ui/ui.h @@ -22,12 +22,11 @@ #define _AKUI_H_ #include -#include "files.h" #include "gdi.h" #include "dbgtool.h" #include "../../share/memtool.h" -#include "../../share/stringtool.h" -#include "../../share/timetool.h" +#include "stringtool.h" +#include "timetool.h" #include "sigslot.h" diff --git a/arm9/source/userwnd.cpp b/arm9/source/userwnd.cpp index 2c178d0..3b3d5d4 100644 --- a/arm9/source/userwnd.cpp +++ b/arm9/source/userwnd.cpp @@ -25,7 +25,7 @@ #include "inifile.h" #include "globalsettings.h" #include "unicode.h" -#include "../../share/stringtool.h" +#include "stringtool.h" #include "../../share/memtool.h" using namespace akui; diff --git a/arm9/source/version.h b/arm9/source/version.h index ccf40d5..f658cec 100644 --- a/arm9/source/version.h +++ b/arm9/source/version.h @@ -18,5 +18,5 @@ along with this program. If not, see . */ -#define AKMENU_VRESION_MAIN "1" -#define AKMENU_VRESION_SUB "25" +#define AKMENU_VERSION_MAIN "1" +#define AKMENU_VERSION_SUB "25" diff --git a/arm9/specs/ds_arm9.ld b/arm9/specs/ds_arm9.ld deleted file mode 100644 index fb98f46..0000000 --- a/arm9/specs/ds_arm9.ld +++ /dev/null @@ -1,254 +0,0 @@ -OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") -OUTPUT_ARCH(arm) -ENTRY(_start) - -MEMORY { - - rom : ORIGIN = 0x08000000, LENGTH = 32M - fwram : ORIGIN = 0x02000000, LENGTH = 0x450 - ewram : ORIGIN = 0x02000450, LENGTH = 3200K - 0x450 - dtcm : ORIGIN = 0x0b000000, LENGTH = 16K - vectors : ORIGIN = 0x01000000, LENGTH = 256 - itcm : ORIGIN = 0x01000100, LENGTH = 32K - 256 -} - -__vectors_start = ORIGIN(vectors); -__itcm_start = ORIGIN(itcm); -__ewram_end = ORIGIN(ewram) + LENGTH(ewram); -__eheap_end = ORIGIN(ewram) + LENGTH(ewram); -__dtcm_start = ORIGIN(dtcm); -__dtcm_top = ORIGIN(dtcm) + LENGTH(dtcm); -__irq_flags = __dtcm_top - 0x08; -__irq_vector = __dtcm_top - 0x04; - -__sp_svc = __dtcm_top - 0x100; -__sp_irq = __sp_svc - 0x100; -__sp_usr = __sp_irq - 0x100; - -SECTIONS -{ - .pad : - { - *(.pad) - } >fwram = 0xff - .init : - { - __text_start = . ; - KEEP (*(.init)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >ewram = 0xff - - .plt : { *(.plt) } >ewram = 0xff - - .text : /* ALIGN (4): */ - { - *(EXCLUDE_FILE (*.itcm*) .text) - - *(.text.*) - *(.stub) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.gnu.linkonce.t*) - *(.glue_7) - *(.glue_7t) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >ewram = 0xff - - .fini : - { - KEEP (*(.fini)) - } >ewram =0xff - - __text_end = . ; - - .rodata : - { - *(.rodata) - *all.rodata*(*) - *(.roda) - *(.rodata.*) - *(.gnu.linkonce.r*) - SORT(CONSTRUCTORS) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >ewram = 0xff - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >ewram - __exidx_start = .; - .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >ewram - __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)) } >ewram = 0xff - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : - { - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array)) - } >ewram = 0xff - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : - { - KEEP (*(.fini_array)) - KEEP (*(SORT(.fini_array.*))) - } >ewram = 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. */ - } >ewram = 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. */ - } >ewram = 0xff - - .eh_frame : - { - KEEP (*(.eh_frame)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >ewram = 0xff - - .gcc_except_table : - { - *(.gcc_except_table) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >ewram = 0xff - .jcr : { KEEP (*(.jcr)) } >ewram = 0 - .got : { *(.got.plt) *(.got) *(.rel.got) } >ewram = 0 - - .ewram ALIGN(4) : - { - __ewram_start = ABSOLUTE(.) ; - *(.ewram) - *ewram.*(.text) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >ewram = 0xff - - - .data ALIGN(4) : - { - __data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d*) - CONSTRUCTORS - . = ALIGN(4); - __data_end = ABSOLUTE(.) ; - } >ewram = 0xff - - - __dtcm_lma = . ; - __bss_vma = . ; - - .dtcm __dtcm_start : AT (__dtcm_lma) - { - *(.dtcm) - *(.dtcm.*) - . = ALIGN(4); - __dtcm_end = ABSOLUTE(.); - } >dtcm = 0xff - - - __itcm_lma = __dtcm_lma + SIZEOF(.dtcm); - - .itcm __itcm_start : AT (__itcm_lma) - { - *(.itcm) - *itcm.*(.text) - . = ALIGN(4); - __itcm_end = ABSOLUTE(.); - } >itcm = 0xff - - __vectors_lma = __itcm_lma + SIZEOF(.itcm); - - .vectors __vectors_start : AT (__vectors_lma) - { - *(.vectors) - *vectors.*(.text) - . = ALIGN(4); - __vectors_end = ABSOLUTE(.); - } >vectors = 0xff - - .sbss __dtcm_end (NOLOAD): - { - __sbss_start = ABSOLUTE(.); - __sbss_start__ = ABSOLUTE(.); - *(.sbss) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - __sbss_end = ABSOLUTE(.); - } >dtcm - - .bss __bss_vma (NOLOAD): - { - __bss_start = ABSOLUTE(.); - __bss_start__ = ABSOLUTE(.); - *(.dynbss) - *(.gnu.linkonce.b*) - *(.bss*) - *(COMMON) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - __bss_end = ABSOLUTE(.) ; - __bss_end__ = __bss_end ; - } AT>ewram - - - _end = __bss_end__ ; - __end__ = __bss_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 . */ -} diff --git a/arm9/specs/ds_arm9.specs b/arm9/specs/ds_arm9.specs deleted file mode 100644 index bf490ad..0000000 --- a/arm9/specs/ds_arm9.specs +++ /dev/null @@ -1,8 +0,0 @@ -%rename link old_link - -*link: -%(old_link) -T ../../specs/ds_arm9.ld%s - -*startfile: -ds_arm9_crt0%O%s crti%O%s crtbegin%O%s - diff --git a/akmenu4.bmp b/icon.bmp similarity index 100% rename from akmenu4.bmp rename to icon.bmp