mirror of
https://github.com/rvtr/GodMode9i.git
synced 2025-11-02 00:11:07 -04:00
Add nds-exception-stub
This commit is contained in:
parent
2a0f5e7c38
commit
af9cd48fb6
12
Makefile
12
Makefile
@ -80,7 +80,7 @@ CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
BMPFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.bmp)))
|
||||
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := load.bin bootstub.bin
|
||||
BINFILES := load.bin bootstub.bin exceptionstub.bin
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
@ -117,9 +117,9 @@ endif
|
||||
|
||||
export GAME_TITLE := $(TARGET)
|
||||
|
||||
.PHONY: bootloader bootstub clean arm7/$(TARGET).elf arm9/$(TARGET).elf
|
||||
.PHONY: bootloader bootstub exceptionstub clean arm7/$(TARGET).elf arm9/$(TARGET).elf
|
||||
|
||||
all: bootloader bootstub $(TARGET).nds
|
||||
all: bootloader bootstub exceptionstub $(TARGET).nds
|
||||
|
||||
dist: all
|
||||
@rm -fr hbmenu
|
||||
@ -160,6 +160,7 @@ clean:
|
||||
@rm -fr $(TARGET).arm9.elf
|
||||
@$(MAKE) -C bootloader clean
|
||||
@$(MAKE) -C bootstub clean
|
||||
@$(MAKE) -C nds-exception-stub clean
|
||||
@$(MAKE) -C arm9 clean
|
||||
@$(MAKE) -C arm7 clean
|
||||
|
||||
@ -167,7 +168,10 @@ data:
|
||||
@mkdir -p data
|
||||
|
||||
bootloader: data
|
||||
@$(MAKE) -C bootloader
|
||||
@$(MAKE) -C bootloader LOADBIN=$(CURDIR)/data/load.bin
|
||||
|
||||
exceptionstub: data
|
||||
@$(MAKE) -C nds-exception-stub STUBBIN=$(CURDIR)/data/exceptionstub.bin
|
||||
|
||||
bootstub: data
|
||||
@$(MAKE) -C bootstub
|
||||
|
||||
5
nds-exception-stub/.gitignore
vendored
Normal file
5
nds-exception-stub/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*.elf
|
||||
*.bin
|
||||
build
|
||||
|
||||
!/data/font.bin
|
||||
145
nds-exception-stub/Makefile
Normal file
145
nds-exception-stub/Makefile
Normal file
@ -0,0 +1,145 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||
endif
|
||||
|
||||
include $(DEVKITARM)/ds_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
# DATA is a list of directories containing binary files embedded using bin2o
|
||||
# GRAPHICS is a list of directories containing image files to be converted with grit
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(shell basename $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
INCLUDES := include ../include
|
||||
DATA := data
|
||||
GRAPHICS := gfx
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ARCH := -mthumb -mthumb-interwork -flto -Os
|
||||
|
||||
CFLAGS := -g -Wall \
|
||||
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
|
||||
-ffast-math \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM9
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -nostartfiles -T../exceptionstub.ld -Wl,--section-start,.crt0=0x2ffa000 -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project (order is important)
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -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 STUBBIN ?= $(CURDIR)/$(TARGET).bin
|
||||
export STUBELF := $(CURDIR)/$(TARGET).elf
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
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)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(PNGFILES:.png=.o) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
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)
|
||||
|
||||
icons := $(wildcard *.bmp)
|
||||
|
||||
ifneq (,$(findstring $(TARGET).bmp,$(icons)))
|
||||
export GAME_ICON := $(CURDIR)/$(TARGET).bmp
|
||||
else
|
||||
ifneq (,$(findstring icon.bmp,$(icons)))
|
||||
export GAME_ICON := $(CURDIR)/icon.bmp
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).elf $(TARGET).bin
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(STUBBIN) : $(STUBELF)
|
||||
$(OBJCOPY) -O binary $< $@
|
||||
@echo built ... $(notdir $@)
|
||||
|
||||
$(STUBELF) : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
-include $(DEPSDIR)/*.d
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
BIN
nds-exception-stub/data/font.bin
Normal file
BIN
nds-exception-stub/data/font.bin
Normal file
Binary file not shown.
202
nds-exception-stub/exceptionstub.ld
Normal file
202
nds-exception-stub/exceptionstub.ld
Normal file
@ -0,0 +1,202 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY {
|
||||
ewram : ORIGIN = 0x02000000, LENGTH = 16M
|
||||
}
|
||||
|
||||
|
||||
PHDRS {
|
||||
main PT_LOAD FLAGS(7);
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.crt0 :
|
||||
{
|
||||
__text_start = . ;
|
||||
KEEP (*(.crt0))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >ewram :main = 0x00
|
||||
|
||||
.plt : { *(.plt) } >ewram :main = 0xff
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
} >ewram :main
|
||||
|
||||
.text : /* ALIGN (4): */
|
||||
{
|
||||
*(EXCLUDE_FILE(*.itcm* *.vectors* *.twl*) .text)
|
||||
*(EXCLUDE_FILE(*.itcm* *.vectors* *.twl*) .stub)
|
||||
*(EXCLUDE_FILE(*.itcm* *.vectors* *.twl*) .text.*)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(EXCLUDE_FILE(*.twl*) .gnu.warning)
|
||||
*(EXCLUDE_FILE(*.twl*) .gnu.linkonce.t*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >ewram :main = 0xff
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(.fini))
|
||||
} >ewram :main =0xff
|
||||
|
||||
__text_end = . ;
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(EXCLUDE_FILE(*.twl*) .rodata)
|
||||
*all.rodata*(*)
|
||||
*(EXCLUDE_FILE(*.twl*) .roda)
|
||||
*(EXCLUDE_FILE(*.twl*) .rodata.*)
|
||||
*(EXCLUDE_FILE(*.twl*) .gnu.linkonce.r*)
|
||||
SORT(CONSTRUCTORS)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >ewram :main = 0xff
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >ewram :main
|
||||
__exidx_start = .;
|
||||
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >ewram :main
|
||||
__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 :main = 0xff
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
PROVIDE (__init_array_start = .);
|
||||
.init_array :
|
||||
{
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
} >ewram :main = 0xff
|
||||
PROVIDE (__init_array_end = .);
|
||||
PROVIDE (__fini_array_start = .);
|
||||
.fini_array :
|
||||
{
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
} >ewram :main = 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 :main = 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 :main = 0xff
|
||||
|
||||
.eh_frame :
|
||||
{
|
||||
KEEP (*(.eh_frame))
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >ewram :main = 0xff
|
||||
|
||||
.gcc_except_table :
|
||||
{
|
||||
*(.gcc_except_table)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >ewram :main = 0xff
|
||||
.jcr : { KEEP (*(.jcr)) } >ewram :main = 0
|
||||
.got : { *(.got.plt) *(.got) *(.rel.got) } >ewram :main = 0
|
||||
|
||||
.ewram ALIGN(4) :
|
||||
{
|
||||
__ewram_start = ABSOLUTE(.) ;
|
||||
*(.ewram)
|
||||
*ewram.*(.text)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
} >ewram :main = 0xff
|
||||
|
||||
|
||||
.data ALIGN(4) :
|
||||
{
|
||||
__data_start = ABSOLUTE(.);
|
||||
*(EXCLUDE_FILE(*.twl*) .data)
|
||||
*(EXCLUDE_FILE(*.twl*) .data.*)
|
||||
*(EXCLUDE_FILE(*.twl*) .gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
. = ALIGN(4);
|
||||
__data_end = ABSOLUTE(.) ;
|
||||
} >ewram :main = 0xff
|
||||
|
||||
__bss_vma = . ;
|
||||
|
||||
.bss __bss_vma (NOLOAD):
|
||||
{
|
||||
__bss_start = ABSOLUTE(.);
|
||||
__bss_start__ = ABSOLUTE(.);
|
||||
*(EXCLUDE_FILE(*.twl*) .dynbss)
|
||||
*(EXCLUDE_FILE(*.twl*) .gnu.linkonce.b*)
|
||||
*(EXCLUDE_FILE(*.twl*) .bss*)
|
||||
*(EXCLUDE_FILE(*.twl*) COMMON)
|
||||
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||
__bss_end__ = ABSOLUTE(.) ;
|
||||
__end__ = ABSOLUTE(.) ;
|
||||
} >ewram :NONE
|
||||
|
||||
|
||||
/* 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 . */
|
||||
}
|
||||
442
nds-exception-stub/source/display.c
Normal file
442
nds-exception-stub/source/display.c
Normal file
@ -0,0 +1,442 @@
|
||||
/*---------------------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2005 - 2017
|
||||
Dave Murphy (WinterMute)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
---------------------------------------------------------------------------------*/
|
||||
#include <nds.h>
|
||||
|
||||
#include "font_bin.h"
|
||||
|
||||
typedef struct con {
|
||||
int x,y;
|
||||
} consoleVars;
|
||||
|
||||
|
||||
static consoleVars topCON = {0,0} , btmCON = {0,0};
|
||||
|
||||
static consoleVars *currentCON = &topCON;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void setScreen(int screen) {
|
||||
//---------------------------------------------------------------------------------
|
||||
currentCON = (screen == 0 ) ? &btmCON : &topCON;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// 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 void newRow() {
|
||||
//---------------------------------------------------------------------------------
|
||||
currentCON->y++;
|
||||
currentCON->x = 0;
|
||||
if (currentCON->y > 23) {
|
||||
u32 *src = (u32*)(BG_MAP_RAM(4) + 32);
|
||||
u32 *dst = (u32*)BG_MAP_RAM(4);
|
||||
memcpy(dst,src,64*24);
|
||||
currentCON->y = 23;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static void writeChar(char c) {
|
||||
//---------------------------------------------------------------------------------
|
||||
u16 *mapcell = BG_MAP_RAM(4) + currentCON->x + (currentCON->y * 32);
|
||||
switch(c) {
|
||||
|
||||
case 10:
|
||||
newRow();
|
||||
case 13:
|
||||
currentCON->x = 0;
|
||||
break;
|
||||
default:
|
||||
*mapcell = c;
|
||||
currentCON->x++;
|
||||
break;
|
||||
}
|
||||
if (currentCON->x > 31) newRow();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static void writeString(char *str, int len) {
|
||||
//---------------------------------------------------------------------------------
|
||||
while(len--) {
|
||||
writeChar(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void setCursor(int row, int column) {
|
||||
//---------------------------------------------------------------------------------
|
||||
currentCON->x = column;
|
||||
currentCON->y = row;
|
||||
}
|
||||
|
||||
void getCursor(int *row, int*column) {
|
||||
*column = currentCON->x;
|
||||
*row = currentCON->y;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
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++ = 0x20;
|
||||
*btm++ = 0x20;
|
||||
}
|
||||
BG_PALETTE[0]=RGB5(31,0,0);
|
||||
BG_PALETTE[1]=RGB5(31,31,31);
|
||||
BG_PALETTE_SUB[0]=RGB5(31,0,0);
|
||||
BG_PALETTE_SUB[1]=RGB5(31,31,31);
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
u32 vramDefault() {
|
||||
//---------------------------------------------------------------------------------
|
||||
u32 tmp = VRAM_CR;
|
||||
vramSetBankA(VRAM_A_MAIN_BG);
|
||||
vramSetBankC(VRAM_C_SUB_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 <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* 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 = "<NULL>";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
13
nds-exception-stub/source/display.h
Normal file
13
nds-exception-stub/source/display.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _display_h_
|
||||
#define _display_h_
|
||||
|
||||
#define TOPSCREEN 0
|
||||
#define BTMSCREEM 0
|
||||
|
||||
void initDisplay();
|
||||
void kprintf(const char *str, ...);
|
||||
void setCursor(int row, int column);
|
||||
void getCursor(int *row, int *column);
|
||||
void setScreen(int screen);
|
||||
|
||||
#endif
|
||||
271
nds-exception-stub/source/gurumeditation.c
Normal file
271
nds-exception-stub/source/gurumeditation.c
Normal file
@ -0,0 +1,271 @@
|
||||
/*---------------------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2005 - 2017
|
||||
Dave Murphy (WinterMute)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
#include <nds/ndstypes.h>
|
||||
#include <nds/memory.h>
|
||||
|
||||
#include <nds/arm9/video.h>
|
||||
#include <nds/arm9/console.h>
|
||||
#include <nds/arm9/exceptions.h>
|
||||
#include <nds/arm9/background.h>
|
||||
|
||||
#include "display.h"
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
unsigned long ARMShift(unsigned long value,unsigned char shift) {
|
||||
//---------------------------------------------------------------------------------
|
||||
// no shift at all
|
||||
if (shift == 0x0B) return value ;
|
||||
int index ;
|
||||
if (shift & 0x01) {
|
||||
// shift index is a register
|
||||
index = exceptionRegisters[(shift >> 4) & 0x0F];
|
||||
} else {
|
||||
// constant shift index
|
||||
index = ((shift >> 3) & 0x1F) ;
|
||||
} ;
|
||||
int i ;
|
||||
bool isN ;
|
||||
switch (shift & 0x06) {
|
||||
case 0x00:
|
||||
// logical left
|
||||
return (value << index) ;
|
||||
case 0x02:
|
||||
// logical right
|
||||
return (value >> index) ;
|
||||
case 0x04:
|
||||
// arithmetical right
|
||||
isN = (value & 0x80000000) ;
|
||||
value = value >> index ;
|
||||
if (isN) {
|
||||
for (i=31;i>31-index;i--) {
|
||||
value = value | (1 << i) ;
|
||||
} ;
|
||||
} ;
|
||||
return value ;
|
||||
case 0x06:
|
||||
// rotate right
|
||||
index = index & 0x1F;
|
||||
value = (value >> index) | (value << (32-index));
|
||||
return value;
|
||||
};
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
u32 getExceptionAddress( u32 opcodeAddress, u32 thumbState) {
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
int Rf, Rb, Rd, Rn, Rm;
|
||||
|
||||
if (thumbState) {
|
||||
// Thumb
|
||||
|
||||
unsigned short opcode = *(unsigned short *)opcodeAddress ;
|
||||
// ldr r,[pc,###] 01001ddd ffffffff
|
||||
// ldr r,[r,r] 0101xx0f ffbbbddd
|
||||
// ldrsh 0101xx1f ffbbbddd
|
||||
// ldr r,[r,imm] 011xxfff ffbbbddd
|
||||
// ldrh 1000xfff ffbbbddd
|
||||
// ldr r,[sp,###] 1001xddd ffffffff
|
||||
// push 1011x10l llllllll
|
||||
// ldm 1100xbbb llllllll
|
||||
|
||||
|
||||
if ((opcode & 0xF800) == 0x4800) {
|
||||
// ldr r,[pc,###]
|
||||
s8 offset = opcode & 0xff;
|
||||
return exceptionRegisters[15] + offset;
|
||||
} else if ((opcode & 0xF200) == 0x5000) {
|
||||
// ldr r,[r,r]
|
||||
Rb = (opcode >> 3) & 0x07 ;
|
||||
Rf = (opcode >> 6) & 0x07 ;
|
||||
return exceptionRegisters[Rb] + exceptionRegisters[Rf];
|
||||
|
||||
} else if ((opcode & 0xF200) == 0x5200) {
|
||||
// ldrsh
|
||||
Rb = (opcode >> 3) & 0x07;
|
||||
Rf = (opcode >> 6) & 0x03;
|
||||
return exceptionRegisters[Rb] + exceptionRegisters[Rf];
|
||||
|
||||
} else if ((opcode & 0xE000) == 0x6000) {
|
||||
// ldr r,[r,imm]
|
||||
Rb = (opcode >> 3) & 0x07;
|
||||
Rf = (opcode >> 6) & 0x1F ;
|
||||
return exceptionRegisters[Rb] + (Rf << 2);
|
||||
} else if ((opcode & 0xF000) == 0x8000) {
|
||||
// ldrh
|
||||
Rb = (opcode >> 3) & 0x07 ;
|
||||
Rf = (opcode >> 6) & 0x1F ;
|
||||
return exceptionRegisters[Rb] + (Rf << 2);
|
||||
} else if ((opcode & 0xF000) == 0x9000) {
|
||||
// ldr r,[sp,#imm]
|
||||
s8 offset = opcode & 0xff;
|
||||
return exceptionRegisters[13] + offset;
|
||||
} else if ((opcode & 0xF700) == 0xB500) {
|
||||
// push/pop
|
||||
return exceptionRegisters[13];
|
||||
} else if ((opcode & 0xF000) == 0xC000) {
|
||||
// ldm/stm
|
||||
Rd = (opcode >> 8) & 0x07;
|
||||
return exceptionRegisters[Rd];
|
||||
}
|
||||
} else {
|
||||
// arm32
|
||||
unsigned long opcode = *(unsigned long *)opcodeAddress ;
|
||||
|
||||
// SWP xxxx0001 0x00nnnn dddd0000 1001mmmm
|
||||
// STR/LDR xxxx01xx xxxxnnnn ddddffff ffffffff
|
||||
// STRH/LDRH xxxx000x x0xxnnnn dddd0000 1xx1mmmm
|
||||
// STRH/LDRH xxxx000x x1xxnnnn ddddffff 1xx1ffff
|
||||
// STM/LDM xxxx100x xxxxnnnn llllllll llllllll
|
||||
|
||||
if ((opcode & 0x0FB00FF0) == 0x01000090) {
|
||||
// SWP
|
||||
Rn = (opcode >> 16) & 0x0F;
|
||||
return exceptionRegisters[Rn];
|
||||
} else if ((opcode & 0x0C000000) == 0x04000000) {
|
||||
// STR/LDR
|
||||
Rn = (opcode >> 16) & 0x0F;
|
||||
if (opcode & 0x02000000) {
|
||||
// Register offset
|
||||
Rm = opcode & 0x0F;
|
||||
if (opcode & 0x01000000) {
|
||||
unsigned short shift = (unsigned short)((opcode >> 4) & 0xFF) ;
|
||||
// pre indexing
|
||||
long Offset = ARMShift(exceptionRegisters[Rm],shift);
|
||||
// add or sub the offset depending on the U-Bit
|
||||
return exceptionRegisters[Rn] + ((opcode & 0x00800000)?Offset:-Offset);
|
||||
} else {
|
||||
// post indexing
|
||||
return exceptionRegisters[Rn];
|
||||
}
|
||||
} else {
|
||||
// Immediate offset
|
||||
unsigned long Offset = (opcode & 0xFFF) ;
|
||||
if (opcode & 0x01000000) {
|
||||
// pre indexing
|
||||
// add or sub the offset depending on the U-Bit
|
||||
return exceptionRegisters[Rn] + ((opcode & 0x00800000)?Offset:-Offset);
|
||||
} else {
|
||||
// post indexing
|
||||
return exceptionRegisters[Rn];
|
||||
}
|
||||
}
|
||||
} else if ((opcode & 0x0E400F90) == 0x00000090) {
|
||||
// LDRH/STRH with register Rm
|
||||
Rn = (opcode >> 16) & 0x0F;
|
||||
Rd = (opcode >> 12) & 0x0F;
|
||||
Rm = opcode & 0x0F;
|
||||
unsigned short shift = (unsigned short)((opcode >> 4) & 0xFF);
|
||||
long Offset = ARMShift(exceptionRegisters[Rm],shift);
|
||||
// add or sub the offset depending on the U-Bit
|
||||
return exceptionRegisters[Rn] + ((opcode & 0x00800000)?Offset:-Offset);
|
||||
} else if ((opcode & 0x0E400F90) == 0x00400090) {
|
||||
// LDRH/STRH with immediate offset
|
||||
Rn = (opcode >> 16) & 0x0F;
|
||||
Rd = (opcode >> 12) & 0x0F;
|
||||
unsigned long Offset = (opcode & 0xF) | ((opcode & 0xF00)>>8) ;
|
||||
// add or sub the offset depending on the U-Bit
|
||||
return exceptionRegisters[Rn] + ((opcode & 0x00800000)?Offset:-Offset) ;
|
||||
} else if ((opcode & 0x0E000000) == 0x08000000) {
|
||||
// LDM/STM
|
||||
Rn = (opcode >> 16) & 0x0F;
|
||||
return exceptionRegisters[Rn];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *registerNames[] =
|
||||
{ "r0","r1","r2","r3","r4","r5","r6","r7",
|
||||
"r8 ","r9 ","r10","r11","r12","sp ","lr ","pc " };
|
||||
|
||||
|
||||
u32 __itcm_start = 0;
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void guruMeditation() {
|
||||
//---------------------------------------------------------------------------------
|
||||
kprintf(" Guru Meditation Error!\n");
|
||||
u32 currentMode = getCPSR() & 0x1f;
|
||||
u32 thumbState = ((*(u32*)0x02FFFD90) & 0x20);
|
||||
|
||||
u32 codeAddress, exceptionAddress = 0;
|
||||
|
||||
int offset = 8;
|
||||
|
||||
if ( currentMode == 0x17 ) {
|
||||
kprintf (" data abort!\n\n");
|
||||
codeAddress = exceptionRegisters[15] - offset;
|
||||
if ( (codeAddress > 0x02000000 && codeAddress < 0x03000000) )
|
||||
exceptionAddress = getExceptionAddress( codeAddress, thumbState);
|
||||
else
|
||||
exceptionAddress = codeAddress;
|
||||
|
||||
} else {
|
||||
if (thumbState)
|
||||
offset = 2;
|
||||
else
|
||||
offset = 4;
|
||||
kprintf(" undefined instruction!\n\n");
|
||||
codeAddress = exceptionRegisters[15] - offset;
|
||||
exceptionAddress = codeAddress;
|
||||
}
|
||||
|
||||
kprintf(" pc: %08X addr: %08X\n\n",codeAddress,exceptionAddress);
|
||||
|
||||
int i;
|
||||
for ( i=0; i < 8; i++ ) {
|
||||
kprintf( " %s: %08X %s: %08X\n",
|
||||
registerNames[i], exceptionRegisters[i],
|
||||
registerNames[i+8],exceptionRegisters[i+8]);
|
||||
}
|
||||
kprintf("\ncpsr: %08X\n",getCPSR());
|
||||
u32 *stack = (u32 *)exceptionRegisters[13];
|
||||
for ( i=0; i<8; i++ ) {
|
||||
setCursor(8-i+16,2);
|
||||
kprintf( "%08X: %08X %08X", (u32)&stack[i*2],stack[i*2], stack[(i*2)+1] );
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((weak)) initSystem(void);
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void excepthandler() {
|
||||
//---------------------------------------------------------------------------------
|
||||
REG_MASTER_BRIGHT = 0;
|
||||
REG_MASTER_BRIGHT_SUB = 0;
|
||||
initSystem();
|
||||
initDisplay();
|
||||
guruMeditation();
|
||||
while(1);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void installException() {
|
||||
//---------------------------------------------------------------------------------
|
||||
setExceptionHandler(excepthandler);
|
||||
}
|
||||
109
nds-exception-stub/source/start.s
Normal file
109
nds-exception-stub/source/start.s
Normal file
@ -0,0 +1,109 @@
|
||||
/*---------------------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2005 - 2017
|
||||
Dave Murphy (WinterMute)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
@ DS processor selection
|
||||
@---------------------------------------------------------------------------------
|
||||
.arch armv5te
|
||||
.cpu arm946e-s
|
||||
@---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
.section ".crt0","ax"
|
||||
.global _start
|
||||
@---------------------------------------------------------------------------------
|
||||
.align 4
|
||||
.arm
|
||||
@---------------------------------------------------------------------------------
|
||||
_start:
|
||||
@---------------------------------------------------------------------------------
|
||||
push {lr}
|
||||
|
||||
ldr r0, =__bss_start__ @ Clear BSS section
|
||||
ldr r1, =__bss_end__
|
||||
sub r1, r1, r0
|
||||
bl ClearMem
|
||||
|
||||
ldr r0, =installException
|
||||
blx r0
|
||||
|
||||
pop {lr}
|
||||
|
||||
bx lr
|
||||
|
||||
.pool
|
||||
|
||||
@---------------------------------------------------------------------------------
|
||||
@ 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 2
|
||||
|
||||
Loading…
Reference in New Issue
Block a user