diff --git a/.gitignore b/.gitignore index 43365e5..a74695c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,7 @@ -arm7/build/ -arm9/build/ -host/build/ -data/ +.*/ +build/ host/dslink host/dslink.exe -arm7/*.bin -arm9/*.bin *.o *.d *.elf diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a094c0b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.13) + +set(NDS_ARCH_THUMB TRUE) + +project(dslink LANGUAGES C ASM) + +add_executable(${PROJECT_NAME}) + +nds_create_rom(${PROJECT_NAME} + ARM7 bobtail + NAME "dslink" + SUBTITLE1 "The Wi-Fi code loader" + SUBTITLE2 "Developed by devkitPro" + ICON dslink.bmp +) + +dkp_target_generate_symbol_list(${PROJECT_NAME}) + +target_compile_options(${PROJECT_NAME} PRIVATE + -Wall +) + +target_link_options(${PROJECT_NAME} PRIVATE + -Wl,--section-start,.crt0=0x02300000 +) + +target_sources(${PROJECT_NAME} PRIVATE + source/main.c + source/console.c +) + +target_link_libraries(${PROJECT_NAME} PRIVATE dswifi9) diff --git a/Makefile b/Makefile deleted file mode 100644 index 4aec244..0000000 --- a/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/ds_rules - -dslink7sourcefiles := $(wildcard arm7/source/*.c) $(wildcard arm7/source/*.s) - -dslink9sourcefiles := $(wildcard arm9/source/*.c) $(wildcard arm9/source/*.s) \ - $(wildcard arm9/data/*.*) - -dslink7sfiles := source/bootstubarm7.s -dslink7cfiles := source/exodecr.c - -dslink9files := source/bootstubarm9.s - -dslink7ofiles := $(dslink7sfiles:.s=.o) $(dslink7cfiles:.c=.o) -dslink9ofiles := $(dslink9files:.s=.o) - -DEPSDIR := . - -export TOPDIR := $(CURDIR) - -UNAME := $(shell uname -s) - -ifneq (,$(findstring MINGW,$(UNAME))) - EXEEXT := .exe -endif - -.PHONY: host/dslink$(EXEEXT) - -all: host/dslink$(EXEEXT) dslink.nds - -dslink.nds: data dslink7.elf dslink9.elf - ndstool -h 0x200 -c $@ -b dslink.bmp "dslink;the wifi code loader;" -7 dslink7.elf -9 dslink9.elf - -host/dslink$(EXEEXT): - $(MAKE) -C host - -source/bootstubarm9.o: data/dslink.arm9.exo data/dslink.arm7.exo - -CFLAGS := -O2 - -dslink7.elf: $(dslink7ofiles) - $(CC) -nostartfiles -nostdlib -specs=ds_arm7.specs -Wl,--nmagic -Wl,-Map,dslink7.map $^ -o $@ - -dslink9.elf: $(dslink9ofiles) - $(CC) -nostartfiles -nostdlib -specs=ds_arm9.specs -Wl,--nmagic -Wl,-Map,dslink9.map $^ -o $@ - -deps: - mkdir deps - -data: - mkdir data - -data/dslink.arm7.exo: arm7/dslink.arm7.bin - exomizer raw -b -q $< -o $@ - -data/dslink.arm9.exo: arm9/dslink.arm9.bin - exomizer raw -b -q $< -o $@ - -arm7/dslink.arm7.bin: arm7/dslink.arm7.elf - $(OBJCOPY) -O binary $< $@ - -arm9/dslink.arm9.bin: arm9/dslink.arm9.elf - $(OBJCOPY) -O binary $< $@ - -arm7/dslink.arm7.elf: $(dslink7sourcefiles) - @$(MAKE) ARM7ELF=$(CURDIR)/$@ -C arm7 - -arm9/dslink.arm9.elf: $(dslink9sourcefiles) arm9/Makefile - @$(MAKE) ARM9ELF=$(TOPDIR)/$@ -C arm9 - -clean: - @rm -fr data deps $(dslink7ofiles) source/bootstubarm9i.o $(dslink9ofiles) - @rm -fr dslink7.elf dslink9.elf dslink7.map dslink9.map dslink.nds source/*.d - @$(MAKE) -C arm7 clean - @$(MAKE) -C arm9 clean - @$(MAKE) -C host clean diff --git a/arm7/Makefile b/arm7/Makefile deleted file mode 100644 index 4f62141..0000000 --- a/arm7/Makefile +++ /dev/null @@ -1,127 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/ds_rules - -#--------------------------------------------------------------------------------- -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# INCLUDES is a list of directories containing extra header files -# DATA is a list of directories containing binary files -# all directories are relative to this makefile -#--------------------------------------------------------------------------------- -BUILD := build -SOURCES := source -INCLUDES := include build -DATA := - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -mthumb-interwork - -CFLAGS := -DNDEBUG -Wall -Os\ - -ffunction-sections -fdata-sections \ - -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\ - -ffast-math \ - $(ARCH) - -CFLAGS += $(INCLUDE) -DARM7 -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -fno-rtti - - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=ds_arm7_vram.specs -g $(ARCH) -Wl,--gc-sections -Wl,-Map,$(notdir $(ARM7ELF)).map -Wl,--section-start,.crt0=0x06020000,--nmagic - - -LIBS := -ldswifi7 -lnds7 - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(LIBNDS) - - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export DEPSDIR := $(CURDIR)/$(BUILD) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -.PHONY: $(BUILD) clean - -#--------------------------------------------------------------------------------- -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) *.elf *.bin - - -#--------------------------------------------------------------------------------- -else - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -$(ARM7ELF) : $(OFILES) - @echo linking $(notdir $@) - @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ - - -#--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/arm7/source/main.c b/arm7/source/main.c deleted file mode 100644 index c3e5009..0000000 --- a/arm7/source/main.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - Copyright 2009 - 2015 Dave Murphy (WinterMute) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ -#include -#include - - -#include "memcpy.h" - -//--------------------------------------------------------------------------------- -void VcountHandler() { -//--------------------------------------------------------------------------------- - inputGetAndSend(); -} - -//--------------------------------------------------------------------------------- -void VblankHandler(void) { -//--------------------------------------------------------------------------------- - Wifi_Update(); -} - -volatile bool exitflag = false; - -//--------------------------------------------------------------------------------- -void powerButtonCB() { -//--------------------------------------------------------------------------------- - exitflag = true; -} - -void arm7Reset(); - -//--------------------------------------------------------------------------------- -void reboot() { -//--------------------------------------------------------------------------------- - - irqDisable(IRQ_ALL); - - REG_IME=0; - - REG_IPC_SYNC = 0x700; - - while((REG_IPC_SYNC &0xf)!=7); - - REG_IPC_SYNC = 0; - while((REG_IPC_SYNC &0xf)!=0); - - arm7Reset(); - -} - -//--------------------------------------------------------------------------------- -int main() { -//--------------------------------------------------------------------------------- - - // read User Settings from firmware - readUserSettings(); - ledBlink(0); - - irqInit(); - - // Start the RTC tracking IRQ - initClockIRQ(); - - fifoInit(); - touchInit(); - - SetYtrigger(80); - - installWifiFIFO(); - - installSystemFIFO(); - - irqSet(IRQ_VCOUNT, VcountHandler); - irqSet(IRQ_VBLANK, VblankHandler); - - irqEnable( IRQ_VBLANK | IRQ_VCOUNT | IRQ_NETWORK); - - setPowerButtonCB(powerButtonCB); - - // Keep the ARM7 mostly idle - while (!exitflag) { - swiHalt(); - if (fifoCheckValue32(FIFO_USER_01)) { - int cmd = fifoGetValue32(FIFO_USER_01); - switch(cmd) { - case 1: - memcpy32((void*)__NDSHeader->arm7destination,(void*)0x02000000 ,((__NDSHeader->arm7binarySize)+3)>>2); - fifoSendValue32(FIFO_USER_01,0); - break; - case 2: - irqDisable(IRQ_VCOUNT); - reboot(); - break; - } - } - - if ( 0 == (REG_KEYINPUT & (KEY_SELECT | KEY_START | KEY_L | KEY_R))) { - exitflag = true; - } - } - return 0; - -} - - diff --git a/arm7/source/memcpy.h b/arm7/source/memcpy.h deleted file mode 100644 index 9c595a8..0000000 --- a/arm7/source/memcpy.h +++ /dev/null @@ -1 +0,0 @@ -void memcpy32(void *dst, void *src, int size); diff --git a/arm7/source/memcpy.s b/arm7/source/memcpy.s deleted file mode 100644 index 4ef7244..0000000 --- a/arm7/source/memcpy.s +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright 2009 - 2015 Dave Murphy (WinterMute) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ - -@ === procedure memcpy32(dest: pointer; const src: pointer; wcount: u32); ====== -@ Fast-copy by words. -@ param dest Destination address. -@ param src Source address. -@ param wcount Number of words. -@ note: src and dst must be word aligned. -@ note: r0 and r1 return as dst + wdn and src + wdn. - -@ Reglist: -@ r0, r1: dst, src -@ r2: wcount, then wcount>>3 -@ r3-r10: data buffer -@ r12: wcount&7 - - .align 2 - .code 32 - .global memcpy32 -memcpy32: - cmp r1, r0 - bge copy_forward - - add r3, r1, r2, lsl #2 - cmp r0, r3 - blt copy_backward - -copy_forward: - and r12, r2, #7 - movs r2, r2, lsr #3 - beq .Lres_cpy32 - stmfd sp!, {r4-r10} - @ copy 32byte chunks with 8fold xxmia -.Lmain_cpy32: - ldmia r1!, {r3-r10} - stmia r0!, {r3-r10} - subs r2, r2, #1 - bhi .Lmain_cpy32 - ldmfd sp!, {r4-r10} - @ and the residual 0-7 words -.Lres_cpy32: - subs r12, r12, #1 - ldmcsia r1!, {r3} - stmcsia r0!, {r3} - bcs .Lres_cpy32 - bx lr - -copy_backward: - add r0, r0, r2, lsl #2 - add r1, r1, r2, lsl #2 - - and r12, r2, #7 - movs r2, r2, lsr #3 - beq .Lres_bcpy32 - stmfd sp!, {r4-r10} - @ copy 32byte chunks with 8fold xxmia -.Lmain_bcpy32: - ldmdb r1!, {r3-r10} - stmdb r0!, {r3-r10} - subs r2, r2, #1 - bhi .Lmain_bcpy32 - ldmfd sp!, {r4-r10} - @ and the residual 0-7 words -.Lres_bcpy32: - subs r12, r12, #1 - ldmcsdb r1!, {r3} - stmcsdb r0!, {r3} - bcs .Lres_bcpy32 - bx lr diff --git a/arm7/source/reset.s b/arm7/source/reset.s deleted file mode 100644 index 6d8772f..0000000 --- a/arm7/source/reset.s +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright 2015 Dave Murphy (WinterMute) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ - .text - .align 4 - - .arm -@--------------------------------------------------------------------------------- - .global arm7Reset - .type arm7Reset STT_FUNC -@--------------------------------------------------------------------------------- -arm7Reset: -@--------------------------------------------------------------------------------- - mrs r0, cpsr @ cpu interrupt disable - orr r0, r0, #0x80 @ (set i flag) - msr cpsr, r0 - - ldr r0, =0x380FFFC @ irq vector - mov r1, #0 - str r1, [r0] - sub r0, r0, #4 @ IRQ1 Check Bits - str r1, [r0] - sub r0, r0, #4 @ IRQ2 Check Bits - str r1, [r0] - - bic r0, r0, #0x7f - - msr cpsr_c, #0xd3 @ svc mode - mov sp, r0 - sub r0, r0, #64 - msr cpsr_c, #0xd2 @ irq mode - mov sp, r0 - sub r0, r0, #512 - msr cpsr_c, #0xdf @ system mode - mov sp, r0 - - mov r12, #0x04000000 - add r12, r12, #0x180 - - mov r0, #6 - bl waitsync - mov r0, #0x600 - strh r0, [r12] - - mov r0, #0 - bl waitsync - strh r0, [r12] - - ldr r0,=0x2FFFE34 - - ldr r0,[r0] - bx r0 - - .pool - -@--------------------------------------------------------------------------------- -waitsync: -@--------------------------------------------------------------------------------- - ldrh r1, [r12] - and r1, r1, #0x000f - cmp r0, r1 - bne waitsync - bx lr diff --git a/arm9/Makefile b/arm9/Makefile deleted file mode 100644 index 5563b2d..0000000 --- a/arm9/Makefile +++ /dev/null @@ -1,128 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/ds_rules - -#--------------------------------------------------------------------------------- -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# INCLUDES is a list of directories containing extra header files -# DATA is a list of directories containing binary files -# all directories are relative to this makefile -#--------------------------------------------------------------------------------- -BUILD := build -SOURCES := source -INCLUDES := include -DATA := data - - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -march=armv5te -mtune=arm946e-s -mthumb -mthumb-interwork - -CFLAGS := -g -flto -DNDEBUG -Wall -Os\ - -ffunction-sections -fdata-sections \ - -fomit-frame-pointer\ - -ffast-math \ - $(ARCH) - -CFLAGS += $(INCLUDE) -DARM9 -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions - -ASFLAGS := -g $(ARCH) $(INCLUDE) - -BASE := 0x02e40000 - -LDFLAGS = -specs=dsi_arm9.specs -g -flto $(ARCH) -Wl,--gc-sections -Wl,--section-start,.crt0=$(BASE) -Wl,-Map,$(notdir $(ARM9ELF)).map - -#--------------------------------------------------------------------------------- -# any extra libraries we wish to link with the project -#--------------------------------------------------------------------------------- -LIBS := -ldswifi9 -lnds9 - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(LIBNDS) - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- -export DEPSDIR := $(CURDIR)/$(BUILD) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -.PHONY: $(BUILD) clean - -#--------------------------------------------------------------------------------- -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) *.elf *.nds* *.bin - - -#--------------------------------------------------------------------------------- -else - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -$(ARM9ELF) : $(OFILES) ../Makefile - @echo linking $(notdir $@) - @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ - -#--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - --include $(DEPSDIR)/*.d - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/arm9/data/font.bin b/arm9/data/font.bin deleted file mode 100644 index 0dc4820..0000000 Binary files a/arm9/data/font.bin and /dev/null differ diff --git a/arm9/source/display.c b/arm9/source/display.c deleted file mode 100644 index 5458c45..0000000 --- a/arm9/source/display.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - Copyright 2010 - 2015 Dave Murphy (WinterMute) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ -#include - -#include "font_bin.h" -//--------------------------------------------------------------------------------- -// upcvt_4bit() -// Convert a 1-bit font to GBA 4-bit format. -//--------------------------------------------------------------------------------- -void upcvt_4bit(void *dst, const u8 *src, u32 len) { -//--------------------------------------------------------------------------------- - u32 *out = dst; - - for(; len > 0; len--) { - u32 dst_bits = 0; - u32 src_bits = *src++; - u32 x; - - for(x = 0; x < 8; x++) { - dst_bits <<= 4; - dst_bits |= src_bits & 1; - src_bits >>= 1; - } - *out++ = dst_bits; - } -} - -static int conx = 0, cony = 0; - -//--------------------------------------------------------------------------------- -static void newRow() { -//--------------------------------------------------------------------------------- - cony++; - conx = 0; - if (cony > 23) { - u32 *src = (u32*)(BG_MAP_RAM(4) + 32); - u32 *dst = (u32*)BG_MAP_RAM(4); - memcpy(dst,src,64*24); - cony = 23; - } -} - -//--------------------------------------------------------------------------------- -static void writeChar(char c) { -//--------------------------------------------------------------------------------- - u16 *mapcell = BG_MAP_RAM(4) + conx + (cony * 32); - switch(c) { - - case 10: - newRow(); - case 13: - conx = 0; - break; - default: - *mapcell = c - 32; - conx++; - break; - } - if (conx > 31) newRow(); -} - -//--------------------------------------------------------------------------------- -static void writeString(char *str, int len) { -//--------------------------------------------------------------------------------- - while(len--) { - writeChar(*str++); - } -} - -//--------------------------------------------------------------------------------- -void setCursor(int row, int column) { -//--------------------------------------------------------------------------------- - conx = column; - cony = row; -} - -void getCursor(int *row, int*column) { - *column = conx; - *row = cony; -} - -//--------------------------------------------------------------------------------- -void initDisplay() { -//--------------------------------------------------------------------------------- - videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE); - videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE); - - upcvt_4bit(BG_TILE_RAM(0),font_bin,font_bin_size); - upcvt_4bit(BG_TILE_RAM_SUB(0),font_bin,font_bin_size); - BGCTRL[0] = BG_MAP_BASE(4) | BG_TILE_BASE(0) | BG_COLOR_16 | BG_32x32; - BGCTRL_SUB[0] = BG_MAP_BASE(4) | BG_TILE_BASE(0) | BG_COLOR_16 | BG_32x32; - - u16 *top = BG_MAP_RAM(4); - u16 *btm = BG_MAP_RAM_SUB(4); - int i; - for ( i = 0; i < 32*32; i++ ) { - *top++ = 0; - *btm++ = 0; - } - BG_PALETTE[0]=RGB8(58,110,165); - BG_PALETTE[1]=RGB5(31,31,31); - BG_PALETTE_SUB[0]=RGB8(58,110,165); - BG_PALETTE_SUB[1]=RGB5(31,31,31); - -} - -//--------------------------------------------------------------------------------- -u32 vramDefault() { -//--------------------------------------------------------------------------------- - u32 tmp = VRAM_CR; - vramSetBankA(VRAM_A_MAIN_BG); - return tmp; -} - -/* - * linux/lib/vsprintf.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ - -/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ -/* - * Wirzenius wrote this portably, Torvalds fucked it up :-) - */ - -#include -#include -#include - -/* we use this so that we can do without the ctype library */ -#define is_digit(c) ((c) >= '0' && (c) <= '9') - -static int skip_atoi(const char **s) -{ - int i=0; - - while (is_digit(**s)) - i = i*10 + *((*s)++) - '0'; - return i; -} - -#define ZEROPAD 1 /* pad with zero */ -#define SIGN 2 /* unsigned/signed long */ -#define PLUS 4 /* show plus */ -#define SPACE 8 /* space if plus */ -#define LEFT 16 /* left justified */ -#define SPECIAL 32 /* 0x */ -#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ - -#define do_div(n,base) ({ \ -int __res; \ -__res = ((unsigned long) n) % (unsigned) base; \ -n = ((unsigned long) n) / (unsigned) base; \ -__res; }) - -static char * number(char * str, long num, int base, int size, int precision - ,int type) -{ - char c,sign,tmp[66]; - const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; - int i; - - if (type & LARGE) - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - if (type & LEFT) - type &= ~ZEROPAD; - if (base < 2 || base > 36) - return 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if (num < 0) { - sign = '-'; - num = -num; - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; - } - } - if (type & SPECIAL) { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - i = 0; - if (num == 0) - tmp[i++]='0'; - else while (num != 0) - tmp[i++] = digits[do_div(num,base)]; - if (i > precision) - precision = i; - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - *str++ = ' '; - if (sign) - *str++ = sign; - if (type & SPECIAL) { - if (base==8) - *str++ = '0'; - else if (base==16) { - *str++ = '0'; - *str++ = digits[33]; - } - } - if (!(type & LEFT)) - while (size-- > 0) - *str++ = c; - while (i < precision--) - *str++ = '0'; - while (i-- > 0) - *str++ = tmp[i]; - while (size-- > 0) - *str++ = ' '; - return str; -} - -int kvsprintf(char *buf, const char *fmt, va_list args) -{ - int len; - unsigned long num; - int i, base; - char * str; - const char *s; - - int flags; /* flags to number() */ - - int field_width; /* width of output field */ - int precision; /* min. # of digits for integers; max - number of chars for from string */ - int qualifier; /* 'h', 'l', or 'L' for integer fields */ - - for (str=buf ; *fmt ; ++fmt) { - if (*fmt != '%') { - *str++ = *fmt; - continue; - } - - /* process flags */ - flags = 0; - repeat: - ++fmt; /* this also skips first '%' */ - switch (*fmt) { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= SPECIAL; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - - /* get field width */ - field_width = -1; - if (is_digit(*fmt)) - field_width = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) { - field_width = -field_width; - flags |= LEFT; - } - } - - /* get the precision */ - precision = -1; - if (*fmt == '.') { - ++fmt; - if (is_digit(*fmt)) - precision = skip_atoi(&fmt); - else if (*fmt == '*') { - ++fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) - precision = 0; - } - - /* get the conversion qualifier */ - qualifier = -1; - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { - qualifier = *fmt; - ++fmt; - } - - /* default base */ - base = 10; - - switch (*fmt) { - case 'c': - if (!(flags & LEFT)) - while (--field_width > 0) - *str++ = ' '; - *str++ = (unsigned char) va_arg(args, int); - while (--field_width > 0) - *str++ = ' '; - continue; - - case 's': - s = va_arg(args, char *); - if (!s) - s = ""; - - len = strnlen(s, precision); - - if (!(flags & LEFT)) - while (len < field_width--) - *str++ = ' '; - for (i = 0; i < len; ++i) - *str++ = *s++; - while (len < field_width--) - *str++ = ' '; - continue; - - case 'p': - if (field_width == -1) { - field_width = 2*sizeof(void *); - flags |= ZEROPAD; - } - str = number(str, - (unsigned long) va_arg(args, void *), 16, - field_width, precision, flags); - continue; - - - case 'n': - if (qualifier == 'l') { - long * ip = va_arg(args, long *); - *ip = (str - buf); - } else { - int * ip = va_arg(args, int *); - *ip = (str - buf); - } - continue; - - case '%': - *str++ = '%'; - continue; - - /* integer number formats - set up the flags and "break" */ - case 'o': - base = 8; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - *str++ = '%'; - if (*fmt) - *str++ = *fmt; - else - --fmt; - continue; - } - if (qualifier == 'l') - num = va_arg(args, unsigned long); - else if (qualifier == 'h') { - num = (unsigned short) va_arg(args, int); - if (flags & SIGN) - num = (short) num; - } else if (flags & SIGN) - num = va_arg(args, int); - else - num = va_arg(args, unsigned int); - str = number(str, num, base, field_width, precision, flags); - } - *str = '\0'; - return str-buf; -} - -#define __DOUTBUFSIZE 256 - -char __outstr[__DOUTBUFSIZE]; - -//--------------------------------------------------------------------------------- -void kprintf(const char *str, ...) { -//--------------------------------------------------------------------------------- - - int len; - - va_list args; - - va_start(args, str); - len=kvsprintf(__outstr,str,args); - va_end(args); - - writeString(__outstr, len); -} - diff --git a/arm9/source/display.h b/arm9/source/display.h deleted file mode 100644 index ca74961..0000000 --- a/arm9/source/display.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _display_h_ -#define _display_h_ - -void initDisplay(); -void kprintf(const char *str, ...); -void setCursor(int row, int column); -void getCursor(int *row, int *column); - -#endif diff --git a/arm9/source/main.c b/arm9/source/main.c deleted file mode 100644 index d17a532..0000000 --- a/arm9/source/main.c +++ /dev/null @@ -1,325 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "display.h" - -const int __secure_area__ = 0; - -//--------------------------------------------------------------------------------- -void waitButtonA() { -//--------------------------------------------------------------------------------- - while(1) { - scanKeys(); - swiWaitForVBlank(); - if (keysDown() & KEY_A) break; - } -} - -extern char _start[]; - -//--------------------------------------------------------------------------------- -int recvall(int socket, void *buffer, int size, int flags) { -//--------------------------------------------------------------------------------- - int len, sizeleft = size; - int row,column; - getCursor(&row,&column); - - while (sizeleft) { - len = recv(socket,buffer,sizeleft,flags); - if (len == 0) { - size = 0; - break; - }; - if (len == -1) { - len = 0; - kprintf("\nrecv -1, errno %d\n",errno); - size = 0; - break; - } - sizeleft -=len; - buffer +=len; - } - setCursor(row,column); - return size; -} - -//--------------------------------------------------------------------------------- -int progressRead(int socket, char *buffer, int size) { -//--------------------------------------------------------------------------------- - - int row,column; - getCursor(&row,&column); - - int sizeleft = size, len; - int chunksize = size/100; - int target = size - chunksize; - - if (chunksize < 1024) chunksize = 1024; - if (chunksize > size) chunksize = size; - - int percent = 0; - - while(sizeleft) { - len = recvall(socket,buffer,chunksize,0); - if (len == 0) break; - sizeleft -= len; - buffer += len; - if (sizeleft <= target) { - percent = (100 * (size - sizeleft))/size; - target -= chunksize; - if (target<0) target = 0; - } - setCursor(row,column); - kprintf("%%%d ",percent); - if ( sizeleft < chunksize) chunksize = sizeleft; - } - - setCursor(row,column); - if (sizeleft) { - kprintf("\nReceive Error\n"); - } else { - kprintf("%%100\n"); - } - return sizeleft; -} - -void arm9Reset(void *clearfrom); - -char *DSiBuffer[0x1000]; - -//--------------------------------------------------------------------------------- -int loadNDS(int socket, u32 remote) { -//--------------------------------------------------------------------------------- - int len; - - int i=0; - ioctl(socket,FIONBIO,&i); - - kprintf("Reading NDS header: "); - len = recvall(socket,__NDSHeader,512,0); - - if (len != 512) { - kprintf("Error.\n"); - return 1; - } - - kprintf("OK.\n"); - - char *arm7dest = __NDSHeader->arm7destination; - int arm7size = __NDSHeader->arm7binarySize; - - char *arm9dest = __NDSHeader->arm9destination; - int arm9size = __NDSHeader->arm9binarySize; - - volatile int response = 0; - - if (arm9dest + arm9size > _start) response = 1; - if (arm7dest >= (char *)0x02000000 && arm7dest < (char *)0x03000000 && arm7dest + arm7size > _start) response = 2; - - if (isDSiMode() && (__NDSHeader->unitCode & 0x02)) response |= (1<<16); - - send(socket,(int *)&response,sizeof(response),0); - - if(response & 0x0f) return 1; - - if(response & (1<<16)) { - kprintf("Reading DSi header: "); - len = recvall(socket,__DSiHeader,0x1000,0); - if (len != 0x1000) { - kprintf("Error.\n"); - return 1; - } - kprintf("OK.\n"); - } - - kprintf("Reading arm7 binary: "); - if (progressRead(socket,(char *)memUncached((void*)0x02000000),arm7size)) { - kprintf("\nReceive error.\n"); - return 1; - } - - fifoSendValue32(FIFO_USER_01,1); - - while(!fifoCheckValue32(FIFO_USER_01)) { - swiIntrWait(1,IRQ_FIFO_NOT_EMPTY); - } - fifoGetValue32(FIFO_USER_01); - - kprintf("Reading arm9 binary: "); - if(progressRead(socket,(char *)arm9dest,arm9size)) { - kprintf("\nReceive error.\n"); - return 1; - } - - if(response & (1<<16)) { - char *arm7idest = __DSiHeader->arm7idestination; - int arm7isize = __DSiHeader->arm7ibinarySize; - - char *arm9idest = __DSiHeader->arm9idestination; - int arm9isize = __DSiHeader->arm9ibinarySize; - - if (arm7isize) { - kprintf("Reading arm7i binary: "); - if (progressRead(socket,(char *)memUncached((void*)arm7idest),arm7isize)) { - kprintf("\nReceive error.\n"); - return 1; - } - } - - if (arm9isize) { - kprintf("Reading arm9i binary: "); - if (progressRead(socket,(char *)arm9idest,arm9isize)) { - kprintf("\nReceive error.\n"); - return 1; - } - } - } - - volatile int cmdlen=0; - char *cmdline; - if (arm9size != 0){ - cmdline = (char*)(arm9dest+arm9size); - } else { - cmdline = (char*)(arm7dest+arm7size); - } - len = recvall(socket,(char*)&cmdlen,4,0); - - if (cmdlen) { - len = recvall(socket,cmdline,cmdlen,0); - - __system_argv->argvMagic = ARGV_MAGIC; - __system_argv->commandLine = cmdline; - __system_argv->length = cmdlen; - __system_argv->host = remote; - } - - Wifi_DisableWifi(); - - DC_FlushAll(); - REG_IPC_SYNC = 0; - - fifoSendValue32(FIFO_USER_01,2); - - irqDisable(IRQ_ALL); - REG_IME = 0; - - //clear out ARM9 DMA channels - for (i=0; i<4; i++) { - DMA_CR(i) = 0; - DMA_SRC(i) = 0; - DMA_DEST(i) = 0; - TIMER_CR(i) = 0; - TIMER_DATA(i) = 0; - } - - u16 *mainregs = (u16*)0x04000000; - u16 *subregs = (u16*)0x04001000; - - for (i=0; i<43; i++) { - mainregs[i] = 0; - subregs[i] = 0; - } - - REG_DISPSTAT = 0; - - dmaFillWords(0, BG_PALETTE, (2*1024)); - VRAM_A_CR = 0x80; - dmaFillWords(0, VRAM, 128*1024); - VRAM_A_CR = 0; - VRAM_B_CR = 0; -// Don't mess with the ARM7's VRAM -// VRAM_C_CR = 0; -// VRAM_D_CR = 0; - VRAM_E_CR = 0; - VRAM_F_CR = 0; - VRAM_G_CR = 0; - VRAM_H_CR = 0; - VRAM_I_CR = 0; - REG_POWERCNT = 0x820F; - REG_EXMEMCNT = 0xE880; - - //set shared ram to ARM7 - WRAM_CR = 0x03; - - while((REG_IPC_SYNC &0xf)!=7); - REG_IPC_SYNC = 0x700; - while((REG_IPC_SYNC &0xf)!=0); - REG_IPC_SYNC = 0; - - arm9Reset(cmdline+cmdlen); - while(1); -} - -//--------------------------------------------------------------------------------- -int main(void) { -//--------------------------------------------------------------------------------- - - initDisplay(); - - kprintf("dslink ... connecting ...\n"); - - if(!Wifi_InitDefault(WFC_CONNECT)) { - kprintf(" Failed to connect!\n"); - waitButtonA(); - return 0; - } - - struct in_addr ip, gateway, mask, dns1, dns2; - - ip = Wifi_GetIPInfo(&gateway, &mask, &dns1, &dns2); - kprintf("Connected: %s\n",inet_ntoa(ip)); - - int sock_udp = socket(PF_INET, SOCK_DGRAM, 0); - struct sockaddr_in sa_udp, sa_udp_remote; - - sa_udp.sin_family = AF_INET; - sa_udp.sin_addr.s_addr = INADDR_ANY; - sa_udp.sin_port = htons(17491); - - if(bind(sock_udp, (struct sockaddr*) &sa_udp, sizeof(sa_udp)) < 0) { - kprintf(" UDP socket error\n"); - waitButtonA(); - return 0; - } - - struct sockaddr_in sa_tcp; - sa_tcp.sin_addr.s_addr=INADDR_ANY; - sa_tcp.sin_family=AF_INET; - sa_tcp.sin_port=htons(17491); - int sock_tcp=socket(AF_INET,SOCK_STREAM,0); - bind(sock_tcp,(struct sockaddr *)&sa_tcp,sizeof(sa_tcp)); - int i=1; - ioctl(sock_tcp,FIONBIO,&i); - ioctl(sock_udp,FIONBIO,&i); - listen(sock_tcp,2); - - int dummy, sock_tcp_remote; - char recvbuf[256]; - - while(1) { - int len = recvfrom(sock_udp, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*) &sa_udp_remote, &dummy); - - if (len!=-1) { - if (strncmp(recvbuf,"dsboot",strlen("dsboot")) == 0) { - sa_udp_remote.sin_family=AF_INET; - sa_udp_remote.sin_port=htons(17491); - sendto(sock_udp, "bootds", strlen("bootds"), 0, (struct sockaddr*) &sa_udp_remote,sizeof(sa_udp_remote)); - } - } - - sock_tcp_remote = accept(sock_tcp,(struct sockaddr *)&sa_tcp,&dummy); - if (sock_tcp_remote != -1) { - loadNDS(sock_tcp_remote,sa_tcp.sin_addr.s_addr); - closesocket(sock_tcp_remote); - } - swiWaitForVBlank(); - scanKeys(); - if (keysDown() & KEY_START) break; - } - return 0; -} diff --git a/arm9/source/mpusetup.s b/arm9/source/mpusetup.s deleted file mode 100644 index d8e50f0..0000000 --- a/arm9/source/mpusetup.s +++ /dev/null @@ -1,219 +0,0 @@ -/* - Copyright 2006 - 2015 Dave Murphy (WinterMute) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ - -#include - -@--------------------------------------------------------------------------------- -@ DS processor selection -@--------------------------------------------------------------------------------- - .arch armv5te - .cpu arm946e-s - - .text - .arm - - .global __libnds_mpu_setup - .type __libnds_mpu_setup STT_FUNC -@--------------------------------------------------------------------------------- -__libnds_mpu_setup: -@--------------------------------------------------------------------------------- -@ turn the power on for M3 -@--------------------------------------------------------------------------------- - ldr r1, =0x8203 - mov r0, #0x04000000 - add r0, r0, #0x304 - strh r1, [r0] - - ldr r1, =0x00002078 @ disable TCM and protection unit - mcr p15, 0, r1, c1, c0 - -@--------------------------------------------------------------------------------- -@ Protection Unit Setup added by Sasq -@--------------------------------------------------------------------------------- - @ Disable cache - mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 @ Instruction cache - mcr p15, 0, r0, c7, c6, 0 @ Data cache - - @ Wait for write buffer to empty - mcr p15, 0, r0, c7, c10, 4 - - ldr r0, =__dtcm_start - orr r0,r0,#0x0a - mcr p15, 0, r0, c9, c1,0 @ DTCM base = __dtcm_start, size = 16 KB - - mov r0,#0x20 - mcr p15, 0, r0, c9, c1,1 @ ITCM base = 0 , size = 32 MB - -@--------------------------------------------------------------------------------- -@ Setup memory regions similar to Release Version -@--------------------------------------------------------------------------------- - - @------------------------------------------------------------------------- - @ Region 0 - IO registers - @------------------------------------------------------------------------- - ldr r0,=( PAGE_64M | 0x04000000 | 1) - mcr p15, 0, r0, c6, c0, 0 - - @------------------------------------------------------------------------- - @ Region 1 - System ROM - @------------------------------------------------------------------------- - ldr r0,=( PAGE_32K | 0xFFFF0000 | 1) - mcr p15, 0, r0, c6, c1, 0 - - @------------------------------------------------------------------------- - @ Region 2 - alternate vector base - @------------------------------------------------------------------------- - ldr r0,=( PAGE_4K | 0x00000000 | 1) - mcr p15, 0, r0, c6, c2, 0 - - @------------------------------------------------------------------------- - @ Region 3 - DTCM - @------------------------------------------------------------------------- - ldr r0,=__dtcm_start - orr r0,r0,#(PAGE_16K | 1) - mcr p15, 0, r0, c6, c3, 0 - - @------------------------------------------------------------------------- - @ Region 4 - ITCM - @------------------------------------------------------------------------- - ldr r0,=__itcm_start - - @ align to 32k boundary - mov r0,r0,lsr #15 - mov r0,r0,lsl #15 - - orr r0,r0,#(PAGE_32K | 1) - mcr p15, 0, r0, c6, c4, 0 - - ldr r0,=0x4004008 - ldr r0,[r0] - ands r0,r0,#0x8000 - bne dsi_mode - - swi 0xf0000 - - ldr r1,=( PAGE_128M | 0x08000000 | 1) - cmp r0,#0 - bne debug_mode - - ldr r3,=( PAGE_4M | 0x02C00000 | 1) - ldr r2,=( PAGE_16M | 0x02000000 | 1) - mov r8,#0x03000000 - - adr r9,dsmasks - b setregions - -debug_mode: - ldr r3,=( PAGE_8M | 0x02000000 | 1) - ldr r2,=( PAGE_8M | 0x02800000 | 1) - mov r8,#0x02800000 - adr r9,debugmasks - b setregions - -dsi_mode: - ldr r1,=( PAGE_8M | 0x03000000 | 1) - ldr r3,=( PAGE_16M | 0x02000000 | 1) - ldr r2,=( PAGE_16M | 0x0C000000 | 1) - mov r8,#0x03000000 - adr r9,dsimasks - -setregions: - - @------------------------------------------------------------------------- - @ Region 5 - DS Accessory (GBA Cart) / DSi switchable iwram - @------------------------------------------------------------------------- - mcr p15, 0, r1, c6, c5, 0 - - @------------------------------------------------------------------------- - @ Region 6 - non cacheable main ram - @------------------------------------------------------------------------- - mcr p15, 0, r2, c6, c6, 0 - - @------------------------------------------------------------------------- - @ Region 7 - cacheable main ram - @------------------------------------------------------------------------- - mcr p15, 0, r3, c6, c7, 0 - - - @------------------------------------------------------------------------- - @ Write buffer enable - @------------------------------------------------------------------------- - ldr r0,=0b10000000 - mcr p15, 0, r0, c3, c0, 0 - - @------------------------------------------------------------------------- - @ DCache & ICache enable - @------------------------------------------------------------------------- - ldr r0,=0b10000010 - mcr p15, 0, r0, c2, c0, 0 - mcr p15, 0, r0, c2, c0, 1 - - @------------------------------------------------------------------------- - @ IAccess - @------------------------------------------------------------------------- - ldr r0,=0x33333363 - mcr p15, 0, r0, c5, c0, 3 - - @------------------------------------------------------------------------- - @ DAccess - @------------------------------------------------------------------------- - mcr p15, 0, r0, c5, c0, 2 - - @------------------------------------------------------------------------- - @ Enable ICache, DCache, ITCM & DTCM - @------------------------------------------------------------------------- - mrc p15, 0, r0, c1, c0, 0 - ldr r1,= ITCM_ENABLE | DTCM_ENABLE | ICACHE_ENABLE | DCACHE_ENABLE | PROTECT_ENABLE - orr r0,r0,r1 - mcr p15, 0, r0, c1, c0, 0 - - ldr r0,=masks - str r9,[r0] - - bx lr - -dsmasks: - .word 0x003fffff, 0x02c00000, 0x02000000 -debugmasks: - .word 0x007fffff, 0x02000000, 0x02800000 -dsimasks: - .word 0x00ffffff, 0x02000000, 0x0c000000 - -masks: .word dsmasks - - .global memCached - .type memCached STT_FUNC -memCached: - ldr r1,masks - ldr r2,[r1],#4 - and r0,r0,r2 - ldr r2,[r1] - orr r0,r0,r2 - bx lr - - .global memUncached - .type memUncached STT_FUNC -memUncached: - ldr r1,masks - ldr r2,[r1],#8 - and r0,r0,r2 - ldr r2,[r1] - orr r0,r0,r2 - bx lr - diff --git a/arm9/source/reset.s b/arm9/source/reset.s deleted file mode 100644 index 92f2813..0000000 --- a/arm9/source/reset.s +++ /dev/null @@ -1,199 +0,0 @@ -/* - Copyright 2006 - 2015 Dave Murphy (WinterMute) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ - -#include - - .text - .align 4 - - .arm - - .arch armv5te - .cpu arm946e-s - -@--------------------------------------------------------------------------------- - .global arm9Reset - .type arm9Reset STT_FUNC -@--------------------------------------------------------------------------------- -arm9Reset: -@--------------------------------------------------------------------------------- - @ address to start clearing from - mov r8, r0 - - mrs r0, cpsr @ cpu interrupt disable - orr r0, r0, #0x80 @ (set i flag) - msr cpsr, r0 - - adr r1, itcm_reset_code - mov r2, #0 - adr r3, itcm_reset_code_end - -copy_itcm_reset: - ldmia r1!, {r0} - stmia r2!, {r0} - cmp r1, r3 - bne copy_itcm_reset - - mov r0, #0 - bx r0 - -@--------------------------------------------------------------------------------- -itcm_reset_code: -@--------------------------------------------------------------------------------- - @ Switch off MPU - mrc p15, 0, r0, c1, c0, 0 - bic r0, r0, #PROTECT_ENABLE - mcr p15, 0, r0, c1, c0, 0 - - - adr r12, mpu_initial_data - ldmia r12, {r0-r10} - - mcr p15, 0, r0, c2, c0, 0 - mcr p15, 0, r0, c2, c0, 1 - mcr p15, 0, r1, c3, c0, 0 - mcr p15, 0, r2, c5, c0, 2 - mcr p15, 0, r3, c5, c0, 3 - mcr p15, 0, r4, c6, c0, 0 - mcr p15, 0, r5, c6, c1, 0 - mcr p15, 0, r6, c6, c3, 0 - mcr p15, 0, r7, c6, c4, 0 - mcr p15, 0, r8, c6, c6, 0 - mcr p15, 0, r9, c6, c7, 0 - mcr p15, 0, r10, c9, c1, 0 - - mov r0, #0 - mcr p15, 0, r0, c6, c2, 0 @ PU Protection Unit Data/Unified Region 2 - mcr p15, 0, r0, c6, c5, 0 @ PU Protection Unit Data/Unified Region 5 - - mrc p15, 0, r0, c9, c1, 0 @ DTCM - mov r0, r0, lsr #12 @ base - mov r0, r0, lsl #12 @ size - add r0, r0, #0x4000 @ dtcm top - - sub r0, r0, #4 @ irq vector - mov r1, #0 - str r1, [r0] - sub r0, r0, #4 @ IRQ1 Check Bits - str r1, [r0] - - bic r0, r0, #0x7f - - msr cpsr_c, #0xd3 @ svc mode - mov sp, r0 - sub r0, r0, #64 - msr cpsr_c, #0xd2 @ irq mode - mov sp, r0 - sub r0, r0, #4096 - msr cpsr_c, #0xdf @ system mode - mov sp, r0 - - - ldr r10, =0x2FFFE24 - - mov r0, #0 - mov r1, #0 - mov r2, #0 - mov r3, #0 - mov r4, #0 - mov r5, #0 - mov r6, #0 - mov r7, #0 - - cmp r8, #0x2000000 - blt noclear - cmp r8, #0x3000000 - bge noclear - -doclear: - ldr r9, [r10, #8] @ arm9 size - add r8, r8, r9 - add r9, r8, #31 - bic r9, r9, #31 - -clear1: - cmp r8, r9 - beq endclear1 - - str r0, [r8, #4]! - b clear1 - -endclear1: - - ldr r9,=0x4004008 - ldr r9,[r9] - ands r9,r9,#0x8000 - bne dsi_mode - - mov r9, #0x02400000 - b ds_mode -dsi_mode: - mov r9, #0x03000000 -ds_mode: - sub r9, #0x0000c000 -clear2: - stmia r8!, {r0, r1, r2, r3, r4, r5, r6, r7} - cmp r8, r9 - blt clear2 - -noclear: - mov r12, #0x04000000 - add r12, r12, #0x180 - - mov r0, #0x600 - strh r0, [r12] - mov r0, #6 - bl waitsync - - mov r0, #0 - strh r0, [r12] - bl waitsync - - ldr r10, =0x2FFFE24 - ldr r2, [r10] - - @ Switch MPU to startup default - ldr r0, =0x00012078 - mcr p15, 0, r0, c1, c0, 0 - - bx r2 - - .pool - -@--------------------------------------------------------------------------------- -waitsync: -@--------------------------------------------------------------------------------- - ldrh r1, [r12] - and r1, r1, #0x000f - cmp r0, r1 - bne waitsync - bx lr - -mpu_initial_data: - .word 0x00000042 @ p15,0,c2,c0,0..1,r0 ;PU Cachability Bits for Data/Unified+Instruction Protection Region - .word 0x00000002 @ p15,0,c3,c0,0,r1 ;PU Write-Bufferability Bits for Data Protection Regions - .word 0x15111011 @ p15,0,c5,c0,2,r2 ;PU Extended Access Permission Data/Unified Protection Region - .word 0x05100011 @ p15,0,c5,c0,3,r3 ;PU Extended Access Permission Instruction Protection Region - .word 0x04000033 @ p15,0,c6,c0,0,r4 ;PU Protection Unit Data/Unified Region 0 - .word 0x0200002b @ p15,0,c6,c1,0,r5 ;PU Protection Unit Data/Unified Region 1 4MB - .word 0x08000035 @ p15,0,c6,c3,0,r6 ;PU Protection Unit Data/Unified Region 3 - .word 0x0300001b @ p15,0,c6,c4,0,r7 ;PU Protection Unit Data/Unified Region 4 - .word 0xffff001d @ p15,0,c6,c6,0,r8 ;PU Protection Unit Data/Unified Region 6 - .word 0x027ff017 @ p15,0,c6,c7,0,r9 ;PU Protection Unit Data/Unified Region 7 4KB - .word 0x0300000a @ p15,0,c9,c1,0,r10 ;TCM Data TCM Base and Virtual Size -itcm_reset_code_end: \ No newline at end of file diff --git a/source/bootstubarm7.s b/source/bootstubarm7.s deleted file mode 100644 index 8dfdfa9..0000000 --- a/source/bootstubarm7.s +++ /dev/null @@ -1,108 +0,0 @@ - .global _start - .arm - .section ".crt0","ax" - -_start: - ldr r1, =__arm7_lma__ - ldr r2, =__arm7_start__ - ldr r4, =__arm7_end__ - sub r3, r4, r2 - - mov r0, #3 - add r3, r3, r0 - bics r3, r3, r0 -CIDLoop: - ldmia r1!, {r0} - stmia r2!, {r0} - subs r3, r3, #4 - bne CIDLoop - b decrunch_bins - - .text -decrunch_bins: - ldr sp, =0x380FE7C - - mov r12, #0x04000000 - mov r0, #0 - - str r0, [r12, #0x208] - - mov r0, #0x100 - add r3, r12, #0x180 - strh r0, [r3] - - mov r2, #1 - bl waitsync - - mov r2, #0 - strh r2, [r3] - - bl waitsync - - mov r4, #0x02000000 - ldr r0, [r4,#4] - mov r1, #0x02f00000 - - ldr r2, =0x06020000 - bl decrunch - - ldr r0, [r4,#8] - mov r1, #0x02f00000 - ldr r2, [r4,#12] - bl decrunch - - ldr r0, [r4,#12] - ldr r1, =0x02FFFE24 - str r0, [r1] - ldr r1, =0x06020000 - bx r1 - - .pool - -waitsync: - ldrh r0, [r3] - and r0, r0, #0x000f - cmp r0, r2 - bne waitsync - bx lr - - -decrunch: - push {r2,lr} - bl exo_decrunch - - mov r1, r0 - mov r2, r0 - mov r2, #0x02f00000 - sub r2, r2, r0 - asr r2, #2 - - pop {r0,lr} - - -@ Reglist: -@ r0, r1: dst, src -@ r2: wcount, then wcount>>3 -@ r3-r10: data buffer -@ r12: wcount&7 - -memcpy32: - and r12, r2, #7 - movs r2, r2, lsr #3 - beq .Lres_cpy32 - stmfd sp!, {r4-r10} - @ copy 32byte chunks with 8fold xxmia -.Lmain_cpy32: - ldmia r1!, {r3-r10} - stmia r0!, {r3-r10} - subs r2, r2, #1 - bhi .Lmain_cpy32 - ldmfd sp!, {r4-r10} - @ and the residual 0-7 words -.Lres_cpy32: - subs r12, r12, #1 - ldmcsia r1!, {r3} - stmcsia r0!, {r3} - bcs .Lres_cpy32 - bx lr - diff --git a/source/bootstubarm9.s b/source/bootstubarm9.s deleted file mode 100644 index 3fb852e..0000000 --- a/source/bootstubarm9.s +++ /dev/null @@ -1,69 +0,0 @@ - .global _start - -_start: - b setup - - .word endarm7 - .word endarm9 - .word 0x02e40000 - -setup: - mov r0, #0 - mov r12, #0x04000000 - str r0, [r12, #0x208] - - ldr r0, =0x00002078 @ disable TCM and protection unit - mcr p15, 0, r0, c1, c0 - - @ Disable caches - mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 @ Instruction cache - mcr p15, 0, r0, c7, c6, 0 @ Data cache - - @ Wait for write buffer to empty - mcr p15, 0, r0, c7, c10, 4 - - mov r0, #0x8a000000 - mov r12, #0x04000000 - str r0,[r12,#0x240] - - add r3, r12, #0x180 @ r3 = 4000180 - - mov r2, #1 - bl waitsync - - mov r0, #0x100 - strh r0, [r3] - - mov r2, #0 - bl waitsync - - strh r2, [r3] - - ldr r12, =0x02FFFE04 - mov r1, #0 - str r1, [r12,#0xf8] - ldr r1, =0xE59FF018 - str r1, [r12] - str r12, [r12,#0x20] - bx r12 - - .pool - -waitsync: - ldrh r0, [r3] - and r0, r0, #0x000f - cmp r0, r2 - bne waitsync - bx lr - - .data - - .align 2 -arm7bin: - .incbin "data/dslink.arm7.exo" -endarm7: - .align 2 -arm9bin: - .incbin "data/dslink.arm9.exo" -endarm9: diff --git a/source/console.c b/source/console.c new file mode 100644 index 0000000..1df7b3e --- /dev/null +++ b/source/console.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: Copyright fincs, devkitPro +#include +#include +#include + +extern const u8 default_font_bin[]; + +static Mutex s_conMutex; +static u16* s_conTilemap; +static int s_conCursorX, s_conCursorY; + +static void _consoleNewRow(void) +{ + s_conCursorY ++; + if (s_conCursorY >= 24) { + s_conCursorY --; + svcCpuSet(&s_conTilemap[32], &s_conTilemap[0], SVC_SET_UNIT_16 | SVC_SET_SIZE_16(23*32*2)); + } + u16 fill = 0; + svcCpuSet(&fill, &s_conTilemap[s_conCursorY*32], SVC_SET_UNIT_16 | SVC_SET_FIXED | SVC_SET_SIZE_16(32*2)); +} + +static void _consolePutChar(int c) +{ + if (s_conCursorX >= 32 && c != '\n') { + s_conCursorX = 0; + _consoleNewRow(); + } + + switch (c) { + default: + s_conTilemap[s_conCursorY*32 + s_conCursorX] = c; + s_conCursorX++; + break; + + case '\t': + s_conCursorX = (s_conCursorX + 4) &~ 3; + break; + + case '\n': + _consoleNewRow(); + /* fallthrough */ + + case '\r': + s_conCursorX = 0; + break; + } +} + +static void consoleWrite(const char* buf, size_t size) +{ + mutexLock(&s_conMutex); + + if_likely (buf) { + for (size_t i = 0; i < size; i ++) { + _consolePutChar(buf[i]); + } + } else { + for (size_t i = 0; i < size; i ++) { + _consolePutChar(' '); + } + } + + mutexUnlock(&s_conMutex); +} + +void miniconsoleInit(void) +{ + vramSetBankA(VRAM_A_MAIN_BG); + + SvcBitUnpackParams params = { + .in_length_bytes = 256*8, + .in_width_bits = 1, + .out_width_bits = 4, + .data_offset = 14, // 1+14 = 15 + .zero_data_flag = 0, + }; + svcBitUnpack(default_font_bin, (void*)MM_VRAM_BG_A, ¶ms); + + REG_BG0CNT = BG_PRIORITY_0 | BG_TILE_BASE(0) | BG_MOSAIC_OFF | BG_32x32 | BG_MAP_BASE(4); + + s_conTilemap = BG_MAP_RAM(4); + armFillMem32(s_conTilemap, 0, 32*32*2); + + REG_DISPCNT = MODE_0_2D | DISPLAY_BG0_ACTIVE; + REG_DISPCNT_SUB = MODE_0_2D; + + BG_PALETTE[0] = RGB15( 7, 14, 21); + BG_PALETTE[15] = RGB15(31, 31, 31); + BG_PALETTE_SUB[0] = RGB15( 7, 14, 21); + + dietPrintSetFunc(consoleWrite); + installArm7DebugSupport(consoleWrite, MAIN_THREAD_PRIO-1); + + threadWaitForVBlank(); +} + +void miniconsoleSetCursorX(unsigned pos) +{ + mutexLock(&s_conMutex); + if (s_conCursorY >= 0) { + s_conCursorY --; + } + s_conCursorX = pos; + mutexUnlock(&s_conMutex); +} diff --git a/source/exodecr.c b/source/exodecr.c deleted file mode 100644 index 1689f78..0000000 --- a/source/exodecr.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2005-2017 Magnus Lind. - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented * you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any distribution. - * - * 4. The names of this software and/or it's copyright holders may not be - * used to endorse or promote products derived from this software without - * specific prior written permission. - */ - -/** - * This decompressor decompresses files that have been compressed - * using the raw sub-sub command with the -b (not default) and -P39 - * (default) setting of the raw command. - */ -#include "exodecr.h" - -static unsigned short int base[52]; -static char bits[52]; -static unsigned char bit_buffer; - -static int bitbuffer_rotate(int carry) -{ - int carry_out; - /* rol */ - carry_out = (bit_buffer & 0x80) != 0; - bit_buffer <<= 1; - if (carry) - { - bit_buffer |= 0x01; - } - return carry_out; -} - -static unsigned char read_byte(const char **inp) -{ - unsigned char val = *--(*inp) & 0xff; - return val; -} - -static unsigned short int -read_bits(const char **inp, int bit_count) -{ - unsigned short int bits = 0; - int byte_copy = bit_count & 8; - bit_count &= 7; - - while(bit_count-- > 0) - { - int carry = bitbuffer_rotate(0); - if (bit_buffer == 0) - { - bit_buffer = read_byte(inp); - carry = bitbuffer_rotate(1); - } - bits <<= 1; - bits |= carry; - } - if (byte_copy != 0) - { - bits <<= 8; - bits |= read_byte(inp); - } - return bits; -} - -static void -init_table(const char **inp) -{ - int i; - unsigned short int b2; - - for(i = 0; i < 52; ++i) - { - unsigned short int b1; - if((i & 15) == 0) - { - b2 = 1; - } - base[i] = b2; - - b1 = read_bits(inp, 3); - b1 |= read_bits(inp, 1) << 3; - bits[i] = b1; - - b2 += 1 << b1; - } -} - -char * -exo_decrunch(const char *in, char *out) -{ - unsigned short int index; - unsigned short int length; - unsigned short int offset; - char c; - char literal = 1; - char reuse_offset_state = 1; - - bit_buffer = read_byte(&in); - - init_table(&in); - - goto implicit_literal_byte; - for(;;) - { - literal = read_bits(&in, 1); - if(literal == 1) - { - implicit_literal_byte: - /* literal byte */ - length = 1; - goto copy; - } - index = 0; - while(read_bits(&in, 1) == 0) - { - ++index; - } - if(index == 16) - { - break; - } - if(index == 17) - { - literal = 1; - length = read_byte(&in) << 8; - length |= read_byte(&in); - goto copy; - } - length = base[index]; - length += read_bits(&in, bits[index]); - - if ((reuse_offset_state & 3) != 1 || !read_bits(&in, 1)) - { - switch(length) - { - case 1: - index = read_bits(&in, 2); - index += 48; - break; - case 2: - index = read_bits(&in, 4); - index += 32; - break; - default: - index = read_bits(&in, 4); - index += 16; - break; - } - offset = base[index]; - offset += read_bits(&in, bits[index]); - } - copy: - do - { - --out; - if(literal) - { - c = read_byte(&in); - } - else - { - c = out[offset]; - } - *out = c; - } - while(--length > 0); - - reuse_offset_state = (reuse_offset_state << 1) | literal; - } - return out; -} diff --git a/source/exodecr.h b/source/exodecr.h deleted file mode 100644 index 6840ca9..0000000 --- a/source/exodecr.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef EXO_DECR_ALREADY_INCLUDED -#define EXO_DECR_ALREADY_INCLUDED - -/* - * Copyright (c) 2005 Magnus Lind. - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented * you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any distribution. - * - * 4. The names of this software and/or it's copyright holders may not be - * used to endorse or promote products derived from this software without - * specific prior written permission. - */ - -/** - * This decompressor decompresses files that have been compressed - * using the raw sub-sub command with the -b (not default) and -P39 - * (default) setting of the raw command. - */ -char *exo_decrunch(const char *in, char *out); - -#endif /* EXO_DECRUNCH_ALREADY_INCLUDED */ diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..257044d --- /dev/null +++ b/source/main.c @@ -0,0 +1,398 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: Copyright fincs, devkitPro +#include +#include + +#include +#include +#include + +#include +#include +#include + +void miniconsoleInit(void); +void miniconsoleSetCursorX(unsigned pos); + +extern void *fake_heap_start, *fake_heap_end; + +void systemUserStartup(void) +{ + // Override heap limit + fake_heap_end = (void*)0x02380000; + if (fake_heap_start > fake_heap_end) { + for (;;); + } +} + +void systemUserExit(void) +{ + // Clean up graphics + REG_DISPCNT = 0; + REG_DISPCNT_SUB = 0; + + // Clear palettes + armFillMem32((void*)MM_PALRAM, 0, MM_PALRAM_SZ); + + // Clear VRAM_A + REG_VRAMCNT_A = VRAM_CONFIG(0, 0); + armFillMem32((void*)MM_VRAM_A, 0, MM_VRAM_A_SZ); + REG_VRAMCNT_A = 0; +} + +static int _dslinkFindHost(in_addr_t* out_addr) +{ + // Set up listening port/address + struct sockaddr_in sa; + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = INADDR_ANY; + sa.sin_port = htons(17491); + + // Create and bind sockets + int sock_udp = socket(PF_INET, SOCK_DGRAM, 0); + int sock_tcp = socket(PF_INET, SOCK_STREAM, 0); + bind(sock_udp, (struct sockaddr*)&sa, sizeof(sa)); + bind(sock_tcp, (struct sockaddr*)&sa, sizeof(sa)); + + // Set sockets to non-blocking + int i = 1; + ioctl(sock_udp, FIONBIO, &i); + ioctl(sock_tcp, FIONBIO, &i); + + // Begin listening for TCP host connections + listen(sock_tcp, 2); + + int fd = -1; + + for (;;) { + struct sockaddr_in sa_remote; + socklen_t dummy; + + // Probe if we have an incoming connection + static const char request[6] = "dsboot"; + static const char reply[6] = "bootds"; + fd = accept(sock_tcp, (struct sockaddr*)&sa_remote, &dummy); + if (fd >= 0) { + *out_addr = sa_remote.sin_addr.s_addr; + break; + } + + // Reply to UDP requests + char recvbuf[256]; + ssize_t len = recvfrom(sock_udp, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&sa_remote, &dummy); + if (len == sizeof(request)) { + sa_remote.sin_family = AF_INET; + sa_remote.sin_port = htons(17491); + sendto(sock_udp, reply, sizeof(reply), 0, (struct sockaddr*)&sa_remote, sizeof(sa_remote)); + } + + threadWaitForVBlank(); + } + + // Set the host connection socket to blocking + i = 0; + ioctl(fd, FIONBIO, &i); + + // Cleanup + closesocket(sock_tcp); + closesocket(sock_udp); + return fd; +} + +static bool _dslinkReadData(int fd, void* out, size_t size, bool show_progress) +{ + size_t orig_size = size; + + while (size) { + ssize_t cursize = recv(fd, out, size, 0); + if (cursize == 0) { + dietPrint("Error: host closed connection\n"); + return false; + } + if (cursize < 0) { + dietPrint("recv() fail, errno = %d\n", errno); + return false; + } + + size -= cursize; + out = (u8*)out + cursize; + + if (show_progress) { + miniconsoleSetCursorX(32-5); + dietPrint("%3u%%\n", (orig_size - size) * 100U / orig_size); + } + } + + return true; +} + +typedef enum DSLinkError { + DSLinkError_None = 0, + DSLinkError_InvalidArm9 = 1, + DSLinkError_InvalidArm7 = 2, +} DSLinkError; + +#define DSLINK_FLAG_TWL_HEADER (1U << 16) + +#define ARM9_MAIN_START 0x2000000 +#define ARM9_MAIN_END 0x2300000 +#define ARM7_MAIN_START 0x2380000 +#define ARM7_MAIN_END 0x23c0000 +#define ARM7_WRAM_START 0x37f8000 +#define ARM7_WRAM_END 0x380f000 + +#define ARM9i_MAIN_START 0x2400000 +#define ARM9i_MAIN_END 0x2680000 +#define ARM7i_MAIN_START 0x2e80000 +#define ARM7i_MAIN_END 0x2f88000 + +MK_INLINE bool _dslinkValidateSection(u32 start, u32 size, u32 sect_start, u32 sect_end, const char* name) +{ + u32 max_size; + if (start >= sect_start && start < sect_end) { + max_size = sect_end - start; + } else { + dietPrint("Invalid %s load address\n", name); + return false; + } + + if (size > max_size) { + dietPrint("%s section is too large\n", name); + return false; + } + + return true; +} + +MK_INLINE bool _dslinkValidateArm7(u32 start, u32 size) +{ + u32 max_size; + if (start >= ARM7_MAIN_START && start < ARM7_MAIN_END) { + max_size = ARM7_MAIN_END - start; + } else if (start >= ARM7_WRAM_START && start < ARM7_WRAM_END) { + max_size = ARM7_WRAM_END - start; + } else { + dietPrint("Invalid arm7 load address\n"); + return false; + } + + if (size > max_size) { + dietPrint("arm7 section is too large\n"); + return false; + } + + return true; +} + +static bool _dslinkLoadFromHost(int fd, struct in_addr addr) +{ + dietPrint("Host: %s\n", inet_ntoa(addr)); + + dietPrint("Reading NDS header...\n"); + if (!_dslinkReadData(fd, g_envAppNdsHeader, sizeof(EnvNdsHeader), false)) { + return false; + } + + // Unused + u8 footer[0x200 - sizeof(EnvNdsHeader)]; + if (!_dslinkReadData(fd, footer, sizeof(footer), false)) { + return false; + } + + bool has_twl_support = g_envAppNdsHeader->unitcode & (1U<<1); + bool is_twl_only = has_twl_support && (g_envAppNdsHeader->unitcode & (1U<<0)); + + u32 response = DSLinkError_None; + + // Sanity checks + if (systemIsTwlMode()) { + if (!has_twl_support) { + dietPrint( + "Error:\n" + "This program is not compatible\n" + "with TWL mode. Switching to NTR\n" + "mode is not implemented yet.\n" + ); + return false; + } + response |= DSLINK_FLAG_TWL_HEADER; + } else if (is_twl_only) { + dietPrint( + "Error:\n" + "This program can only run on a\n" + "DSi in TWL mode.\n" + ); + return false; + } + + dietPrint("arm9 addr:%.8lX size:%.lX\n", g_envAppNdsHeader->arm9_ram_address, g_envAppNdsHeader->arm9_size); + dietPrint("arm7 addr:%.8lX size:%.lX\n", g_envAppNdsHeader->arm7_ram_address, g_envAppNdsHeader->arm7_size); + + if (!_dslinkValidateSection(g_envAppNdsHeader->arm9_ram_address, g_envAppNdsHeader->arm9_size, ARM9_MAIN_START, ARM9_MAIN_END, "arm9")) { + response = DSLinkError_InvalidArm9; + } else if (!_dslinkValidateArm7(g_envAppNdsHeader->arm7_ram_address, g_envAppNdsHeader->arm7_size)) { + response = DSLinkError_InvalidArm7; + } + + // Calculate command line buffer address + char* cmdline = (char*)(g_envAppNdsHeader->arm9_ram_address + g_envAppNdsHeader->arm9_size); + u32 cmdline_max_len = ARM9_MAIN_END - (u32)cmdline; + + send(fd, &response, sizeof(response), 0); + if ((response & 0xffff) != DSLinkError_None) { + return false; + } + + if (response & DSLINK_FLAG_TWL_HEADER) { + dietPrint("Reading DSi header...\n"); + if (!_dslinkReadData(fd, g_envAppTwlHeader, sizeof(EnvTwlHeader), false)) { + return false; + } + + if (memcmp(g_envAppTwlHeader, g_envAppNdsHeader, sizeof(EnvNdsHeader)) != 0) { + dietPrint( + "Error:\n" + "DSi & NDS headers do not match\n" + ); + return false; + } + + dietPrint("arm9i addr:%.8lX size:%.lX\n", g_envAppTwlHeader->arm9i_ram_address, g_envAppTwlHeader->arm9i_size); + dietPrint("arm7i addr:%.8lX size:%.lX\n", g_envAppTwlHeader->arm7i_ram_address, g_envAppTwlHeader->arm7i_size); + + if (!_dslinkValidateSection(g_envAppTwlHeader->arm9i_ram_address, g_envAppTwlHeader->arm9i_size, ARM9i_MAIN_START, ARM9i_MAIN_END, "arm9i")) { + return false; + } + + if (!_dslinkValidateSection(g_envAppTwlHeader->arm7i_ram_address, g_envAppTwlHeader->arm7i_size, ARM7i_MAIN_START, ARM7i_MAIN_END, "arm7i")) { + return false; + } + } + + if (g_envAppNdsHeader->arm7_size) { + // Special case for ARM7 binaries loaded directly into private ARM7 WRAM + void* arm7_dest = (void*)g_envAppNdsHeader->arm7_ram_address; + if ((u32)arm7_dest >= ARM7_WRAM_START) { + arm7_dest = (void*)ARM7_MAIN_START; + } + + dietPrint("Reading ARM7 section...\n"); + if (!_dslinkReadData(fd, arm7_dest, g_envAppNdsHeader->arm7_size, true)) { + return false; + } + } + + if (g_envAppNdsHeader->arm9_size) { + dietPrint("Reading ARM9 section...\n"); + if (!_dslinkReadData(fd, (void*)g_envAppNdsHeader->arm9_ram_address, g_envAppNdsHeader->arm9_size, true)) { + return false; + } + } + + if (response & DSLINK_FLAG_TWL_HEADER) { + if (g_envAppTwlHeader->arm7i_size) { + dietPrint("Reading ARM7i section...\n"); + if (!_dslinkReadData(fd, (void*)g_envAppTwlHeader->arm7i_ram_address, g_envAppTwlHeader->arm7i_size, true)) { + return false; + } + } + + if (g_envAppTwlHeader->arm9i_size) { + dietPrint("Reading ARM9i section...\n"); + if (!_dslinkReadData(fd, (void*)g_envAppTwlHeader->arm9i_ram_address, g_envAppTwlHeader->arm9i_size, true)) { + return false; + } + } + } + + u32 cmdline_len = 0; + dietPrint("Reading command line...\n"); + if (!_dslinkReadData(fd, &cmdline_len, sizeof(u32), false) || + cmdline_len > cmdline_max_len || + !_dslinkReadData(fd, cmdline, cmdline_len, false)) { + return false; + } + + // Set up argv header + g_envNdsArgvHeader->magic = ENV_NDS_ARGV_MAGIC; + g_envNdsArgvHeader->args_str = cmdline; + g_envNdsArgvHeader->args_str_size = cmdline_len; + g_envNdsArgvHeader->dslink_host_ipv4 = addr.s_addr; + + // Set up boot parameter block + armFillMem32(g_envBootParam, 0, sizeof(EnvBootParam)); + g_envBootParam->boot_src = EnvBootSrc_Wireless; + // XX: do we want to fill the rest? + + // Enable chainload + g_envExtraInfo->pm_chainload_flag = 1; + + dietPrint("Taking the plunge\n"); + return true; +} + +static int _dslinkThreadMain(void* arg) +{ + for (;;) { + struct in_addr addr; + int fd = _dslinkFindHost(&addr.s_addr); + if (fd < 0) { + break; + } + + bool ok = _dslinkLoadFromHost(fd, addr); + closesocket(fd); + + if (ok) { + pmPrepareToReset(); + break; + } + } + + return 0; +} + +int main(int argc, char* argv[]) +{ + Thread thr; + alignas(8) u8 thr_stack[4096]; + + miniconsoleInit(); + + dietPrint("dslink started in %s mode\n", systemIsTwlMode() ? "TWL" : "NTR"); + dietPrint("Developed by devkitPro\n\n"); + + dietPrint("Connecting to Wi-Fi... "); + + if (Wifi_InitDefault(WFC_CONNECT)) { + struct in_addr ip = Wifi_GetIPInfo(NULL, NULL, NULL, NULL); + dietPrint("[OK]\n\n DS IP: %s\n\n", inet_ntoa(ip)); + + threadPrepare(&thr, _dslinkThreadMain, NULL, &thr_stack[sizeof(thr_stack)], MAIN_THREAD_PRIO+1); + threadStart(&thr); + } else { + dietPrint( + "[FAIL]\n\n" + "Make sure your Nintendo WFC\n" + "settings are correct, and that\n" + "a configured Access Point is\n" + "in range of your Nintendo DS.\n\n" + ); + } + + dietPrint("Push START to exit\n"); + + Keypad pad; + keypadRead(&pad); + + while (pmMainLoop()) { + threadWaitForVBlank(); + keypadRead(&pad); + + if (keypadDown(&pad) & KEY_START) { + break; + } + } + + return 0; +}