Add nds-exception-stub

This commit is contained in:
RocketRobz 2018-10-05 22:15:55 -06:00
parent 2a0f5e7c38
commit af9cd48fb6
9 changed files with 1195 additions and 4 deletions

View File

@ -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
View File

@ -0,0 +1,5 @@
*.elf
*.bin
build
!/data/font.bin

145
nds-exception-stub/Makefile Normal file
View 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
#---------------------------------------------------------------------------------------

Binary file not shown.

View 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 . */
}

View 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);
}

View 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

View 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);
}

View 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