about summary refs log tree commit diff stats
path: root/gba
diff options
context:
space:
mode:
Diffstat (limited to 'gba')
-rw-r--r--gba/Makefile13
-rw-r--r--gba/gba_pkjb.ld296
-rw-r--r--gba/gba_pkjb.specs8
-rw-r--r--gba/source/main.c262
-rw-r--r--gba/start/pkjb_crt0.s98
5 files changed, 444 insertions, 233 deletions
diff --git a/gba/Makefile b/gba/Makefile index 99dfbb6..f9cb296 100644 --- a/gba/Makefile +++ b/gba/Makefile
@@ -7,6 +7,10 @@ ifeq ($(strip $(DEVKITARM)),)
7$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM) 7$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM)
8endif 8endif
9 9
10%_pkjb.elf:
11 @echo linking pkjb
12 @$(LD) -specs=../gba_pkjb.specs $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
13
10include $(DEVKITARM)/gba_rules 14include $(DEVKITARM)/gba_rules
11 15
12#--------------------------------------------------------------------------------- 16#---------------------------------------------------------------------------------
@@ -16,7 +20,7 @@ include $(DEVKITARM)/gba_rules
16# DATA is a list of directories containing data files 20# DATA is a list of directories containing data files
17# INCLUDES is a list of directories containing header files 21# INCLUDES is a list of directories containing header files
18#--------------------------------------------------------------------------------- 22#---------------------------------------------------------------------------------
19TARGET := $(shell basename $(CURDIR))_mb 23TARGET := $(shell basename $(CURDIR))_pkjb
20BUILD := build 24BUILD := build
21SOURCES := source 25SOURCES := source
22DATA := 26DATA :=
@@ -38,8 +42,8 @@ CFLAGS += $(INCLUDE)
38 42
39CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions 43CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
40 44
41ASFLAGS := $(ARCH) 45ASFLAGS := -g $(ARCH)
42LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir $@).map 46LDFLAGS = $(ARCH) -Wl,-Map,$(notdir $@).map
43 47
44#--------------------------------------------------------------------------------- 48#---------------------------------------------------------------------------------
45# any extra libraries we wish to link with the project 49# any extra libraries we wish to link with the project
@@ -109,6 +113,7 @@ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
109#--------------------------------------------------------------------------------- 113#---------------------------------------------------------------------------------
110$(BUILD): 114$(BUILD):
111 @[ -d $@ ] || mkdir -p $@ 115 @[ -d $@ ] || mkdir -p $@
116 $(CC) -MMD -MP -MF start/pkjb_crt0.d -x assembler-with-cpp $(ASFLAGS) -c start/pkjb_crt0.s -o start/pkjb_crt0.o $(ERROR_FILTER)
112 @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 117 @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
113 118
114all : $(BUILD) 119all : $(BUILD)
@@ -150,7 +155,7 @@ $(OUTPUT).elf : $(OFILES)
150#--------------------------------------------------------------------------------- 155#---------------------------------------------------------------------------------
151 @echo $(notdir $<) 156 @echo $(notdir $<)
152 @$(bin2o) 157 @$(bin2o)
153 158
154#--------------------------------------------------------------------------------- 159#---------------------------------------------------------------------------------
155# This rule creates assembly source files using grit 160# This rule creates assembly source files using grit
156# grit takes an image file and a .grit describing how the file is to be processed 161# grit takes an image file and a .grit describing how the file is to be processed
diff --git a/gba/gba_pkjb.ld b/gba/gba_pkjb.ld new file mode 100644 index 0000000..102cb42 --- /dev/null +++ b/gba/gba_pkjb.ld
@@ -0,0 +1,296 @@
1/* Linker Script Original v1.3 by Jeff Frohwein */
2/* v1.0 - Original release */
3/* v1.1 - Added proper .data section support */
4/* v1.2 - Added support for c++ & iwram overlays */
5/* - Major contributions by Jason Wilkins. */
6/* v1.3 - .ewram section now can be used when */
7/* compiling for MULTIBOOT mode. This fixes */
8/* malloc() in DevKitAdvance which depends */
9/* on __eheap_start instead of end to define*/
10/* the starting location of heap space. */
11/* External global variable __gba_iwram_heap*/
12/* support added to allow labels end, _end, */
13/* & __end__ to point to end of iwram or */
14/* the end of ewram. */
15/* Additions by WinterMute */
16/* v1.4 - .sbss section added for unitialised */
17/* data in ewram */
18/* v1.5 - padding section added to stop EZF */
19/* stripping important data */
20/* v1.6 - added memory sections */
21
22/* This file is released into the public domain */
23/* for commercial or non-commercial use with no */
24/* restrictions placed upon it. */
25
26/* NOTE!!!: This linker script defines the RAM & */
27/* ROM start addresses. In order for it to work */
28/* properly, remove -Ttext and -Tbss linker */
29/* options from your makefile if they are */
30/* present. */
31
32/* You can use the following to view section */
33/* addresses in your .elf file: */
34/* objdump -h file.elf */
35/* Please note that empty sections may incorrectly*/
36/* list the lma address as the vma address for */
37/* some versions of objdump. */
38
39OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
40OUTPUT_ARCH(arm)
41ENTRY(_start)
42
43MEMORY {
44
45 rom : ORIGIN = 0x08000000, LENGTH = 32M
46 iwram : ORIGIN = 0x03000000, LENGTH = 32K
47 ewram : ORIGIN = 0x02000000, LENGTH = 256K
48}
49
50
51
52__text_start = ORIGIN(ewram);
53__eheap_end = ORIGIN(ewram) + LENGTH(ewram);
54__iwram_start = ORIGIN(iwram);
55__iwram_top = ORIGIN(iwram) + LENGTH(iwram);;
56
57__sp_irq = __iwram_top - 0x060;
58__sp_usr = __sp_irq - 0x0a0;
59__irq_flags = 0x03007ff8;
60
61SECTIONS
62{
63 . = __text_start;
64 .init :
65 {
66 KEEP (*(.init))
67 . = ALIGN(4);
68 } >ewram =0xff
69
70 .plt :
71 {
72 *(.plt)
73 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
74 } >ewram
75
76 .text ALIGN (4):
77 {
78 *(EXCLUDE_FILE (*.iwram*) .text)
79 *(.text .stub .text.* .gnu.linkonce.t.*)
80 KEEP (*(.text.*personality*))
81 /* .gnu.warning sections are handled specially by elf32.em. */
82 *(.gnu.warning)
83 *(.glue_7t) *(.glue_7) *(.vfp11_veneer)
84 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
85 } >ewram = 0xff
86
87 __text_end = .;
88 .fini :
89 {
90 KEEP (*(.fini))
91 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
92 } >ewram =0
93
94 .rodata :
95 {
96 *(.rodata)
97 *all.rodata*(*)
98 *(.roda)
99 *(.rodata.*)
100 *(.gnu.linkonce.r*)
101 SORT(CONSTRUCTORS)
102 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
103 } >ewram = 0xff
104
105 .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >ewram
106 __exidx_start = .;
107 .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >ewram
108 __exidx_end = .;
109 /* Ensure the __preinit_array_start label is properly aligned. We
110 could instead move the label definition inside the section, but
111 the linker would then create the section even if it turns out to
112 be empty, which isn't pretty. */
113 . = ALIGN(32 / 8);
114 PROVIDE (__preinit_array_start = .);
115 .preinit_array : { KEEP (*(.preinit_array)) } >ewram = 0xff
116 PROVIDE (__preinit_array_end = .);
117 PROVIDE (__init_array_start = .);
118 .init_array : { KEEP (*(.init_array)) } >ewram = 0xff
119 PROVIDE (__init_array_end = .);
120 PROVIDE (__fini_array_start = .);
121 .fini_array : { KEEP (*(.fini_array)) } >ewram = 0xff
122 PROVIDE (__fini_array_end = .);
123 .ctors :
124 {
125 /* gcc uses crtbegin.o to find the start of the constructors, so
126 we make sure it is first. Because this is a wildcard, it
127 doesn't matter if the user does not actually link against
128 crtbegin.o; the linker won't look for a file to match a
129 wildcard. The wildcard also means that it doesn't matter which
130 directory crtbegin.o is in. */
131 KEEP (*crtbegin.o(.ctors))
132 KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
133 KEEP (*(SORT(.ctors.*)))
134 KEEP (*(.ctors))
135 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
136 } >ewram = 0
137
138 .dtors :
139 {
140 KEEP (*crtbegin.o(.dtors))
141 KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
142 KEEP (*(SORT(.dtors.*)))
143 KEEP (*(.dtors))
144 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
145 } >ewram = 0
146
147 .jcr : { KEEP (*(.jcr)) } >ewram
148 .eh_frame :
149 {
150 KEEP (*(.eh_frame))
151 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
152 } >ewram = 0
153
154 .gcc_except_table :
155 {
156 *(.gcc_except_table)
157 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
158 } >ewram = 0
159
160 __iwram_lma = .;
161
162 .iwram __iwram_start : AT (__iwram_lma)
163 {
164 __iwram_start__ = ABSOLUTE(.) ;
165 *(.iwram)
166 *iwram.*(.text)
167 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
168 __iwram_end__ = ABSOLUTE(.) ;
169 } >iwram = 0xff
170
171 __data_lma = __iwram_lma + SIZEOF(.iwram) ;
172
173 .bss ALIGN(4) (NOLOAD):
174 {
175 __bss_start__ = ABSOLUTE(.);
176 *(.dynbss)
177 *(.gnu.linkonce.b*)
178 *(.bss*)
179 *(COMMON)
180 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
181 __bss_end__ = ABSOLUTE(.) ;
182 }
183
184 .data ALIGN(4) : AT (__data_lma)
185 {
186 __data_start__ = ABSOLUTE(.);
187 *(.data)
188 *(.data.*)
189 *(.gnu.linkonce.d*)
190 CONSTRUCTORS
191 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
192 __data_end__ = ABSOLUTE(.);
193 } >iwram = 0xff
194
195 __iwram_overlay_lma = __data_lma + SIZEOF(.data);
196
197 PROVIDE (edata = .);
198 __iwram_overlay_start = . ;
199
200 OVERLAY ALIGN(4) : NOCROSSREFS AT (__iwram_overlay_lma)
201 {
202 .iwram0 { *(.iwram0) . = ALIGN(4);}
203 .iwram1 { *(.iwram1) . = ALIGN(4);}
204 .iwram2 { *(.iwram2) . = ALIGN(4);}
205 .iwram3 { *(.iwram3) . = ALIGN(4);}
206 .iwram4 { *(.iwram4) . = ALIGN(4);}
207 .iwram5 { *(.iwram5) . = ALIGN(4);}
208 .iwram6 { *(.iwram6) . = ALIGN(4);}
209 .iwram7 { *(.iwram7) . = ALIGN(4);}
210 .iwram8 { *(.iwram8) . = ALIGN(4);}
211 .iwram9 { *(.iwram9) . = ALIGN(4);}
212 } >iwram = 0xff
213
214 __ewram_lma = LOADADDR(.iwram0) + SIZEOF(.iwram0)+SIZEOF(.iwram1)+SIZEOF(.iwram2)+SIZEOF(.iwram3)+SIZEOF(.iwram4)+SIZEOF(.iwram5)+SIZEOF(.iwram6)+SIZEOF(.iwram7)+SIZEOF(.iwram8)+SIZEOF(.iwram9);
215
216 __iwram_overlay_end = __ewram_lma ;
217
218 /* v1.3 */
219 __ewram_start = __ewram_lma ;
220
221 .ewram __ewram_start : AT (__ewram_lma)
222 {
223 *(.ewram)
224 . = ALIGN(4); /* REQUIRED. LD is flaky without it. */
225 __ewram_end = ABSOLUTE(.);
226 } >ewram = 0xff
227
228 __ewram_overlay_lma = __ewram_lma + SIZEOF(.ewram);
229
230 .sbss ALIGN(4)(NOLOAD):
231 {
232 __sbss_start__ = ABSOLUTE(.);
233 *(.sbss)
234 . = ALIGN(4);
235 __sbss_end__ = ABSOLUTE(.);
236 __end__ = ABSOLUTE(.);
237 __eheap_start = ABSOLUTE(.);
238 }
239
240 OVERLAY ALIGN(4): NOCROSSREFS AT (__ewram_overlay_lma)
241 {
242 .ewram0 { *(.ewram0) . = ALIGN(4);}
243 .ewram1 { *(.ewram1) . = ALIGN(4);}
244 .ewram2 { *(.ewram2) . = ALIGN(4);}
245 .ewram3 { *(.ewram3) . = ALIGN(4);}
246 .ewram4 { *(.ewram4) . = ALIGN(4);}
247 .ewram5 { *(.ewram5) . = ALIGN(4);}
248 .ewram6 { *(.ewram6) . = ALIGN(4);}
249 .ewram7 { *(.ewram7) . = ALIGN(4);}
250 .ewram8 { *(.ewram8) . = ALIGN(4);}
251 .ewram9 { *(.ewram9) . = ALIGN(4);}
252 } >ewram = 0xff
253 __ewram_overlay_end = ABSOLUTE(.);
254
255 __eheap_start = __ewram_overlay_end ;
256
257 _end = __ewram_overlay_end;
258 __end__ = __ewram_overlay_end;
259 __rom_end__ = __ewram_overlay_end;
260
261 /* Stabs debugging sections. */
262 .stab 0 : { *(.stab) }
263 .stabstr 0 : { *(.stabstr) }
264 .stab.excl 0 : { *(.stab.excl) }
265 .stab.exclstr 0 : { *(.stab.exclstr) }
266 .stab.index 0 : { *(.stab.index) }
267 .stab.indexstr 0 : { *(.stab.indexstr) }
268 .comment 0 : { *(.comment) }
269 /* DWARF debug sections.
270 Symbols in the DWARF debugging sections are relative to the beginning
271 of the section so we begin them at 0. */
272 /* DWARF 1 */
273 .debug 0 : { *(.debug) }
274 .line 0 : { *(.line) }
275 /* GNU DWARF 1 extensions */
276 .debug_srcinfo 0 : { *(.debug_srcinfo) }
277 .debug_sfnames 0 : { *(.debug_sfnames) }
278 /* DWARF 1.1 and DWARF 2 */
279 .debug_aranges 0 : { *(.debug_aranges) }
280 .debug_pubnames 0 : { *(.debug_pubnames) }
281 /* DWARF 2 */
282 .debug_info 0 : { *(.debug_info) }
283 .debug_abbrev 0 : { *(.debug_abbrev) }
284 .debug_line 0 : { *(.debug_line) }
285 .debug_frame 0 : { *(.debug_frame) }
286 .debug_str 0 : { *(.debug_str) }
287 .debug_loc 0 : { *(.debug_loc) }
288 .debug_macinfo 0 : { *(.debug_macinfo) }
289 /* SGI/MIPS DWARF 2 extensions */
290 .debug_weaknames 0 : { *(.debug_weaknames) }
291 .debug_funcnames 0 : { *(.debug_funcnames) }
292 .debug_typenames 0 : { *(.debug_typenames) }
293 .debug_varnames 0 : { *(.debug_varnames) }
294 .stack 0x80000 : { _stack = .; *(.stack) }
295 /* These must appear regardless of . */
296}
diff --git a/gba/gba_pkjb.specs b/gba/gba_pkjb.specs new file mode 100644 index 0000000..7c9027b --- /dev/null +++ b/gba/gba_pkjb.specs
@@ -0,0 +1,8 @@
1%rename link old_link
2
3*link:
4-T ../gba_pkjb.ld%s %(old_link) --gc-sections
5
6*startfile:
7../start/pkjb_crt0%O%s crti%O%s crtbegin%O%s
8
diff --git a/gba/source/main.c b/gba/source/main.c index ee94c35..ce6969b 100644 --- a/gba/source/main.c +++ b/gba/source/main.c
@@ -1,241 +1,45 @@
1/* 1/*
2 * Copyright (C) 2016 FIX94 2 * Example Gen3-multiboot payload by slipstream/RoL 2017.
3 * Supports only English Ruby, v1.0-1.2.
3 * 4 *
4 * This software may be modified and distributed under the terms 5 * This software may be modified and distributed under the terms
5 * of the MIT license. See the LICENSE file for details. 6 * of the MIT license. See the LICENSE file for details.
6 */ 7 */
7#include <gba.h> 8#include <gba.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include "libSave.h"
11 9
12#define REG_WAITCNT *(vu16 *)(REG_BASE + 0x204)
13#define JOY_WRITE 2
14#define JOY_READ 4
15#define JOY_RW 6
16
17u8 save_data[0x20000] __attribute__ ((section (".sbss")));
18
19s32 getGameSize(void)
20{
21 if(*(vu32*)(0x08000004) != 0x51AEFF24)
22 return -1;
23 s32 i;
24 for(i = (1<<20); i < (1<<25); i<<=1)
25 {
26 vu16 *rompos = (vu16*)(0x08000000+i);
27 int j;
28 bool romend = true;
29 for(j = 0; j < 0x1000; j++)
30 {
31 if(rompos[j] != j)
32 {
33 romend = false;
34 break;
35 }
36 }
37 if(romend) break;
38 }
39 return i;
40}
41
42//---------------------------------------------------------------------------------
43// Program entry point
44//---------------------------------------------------------------------------------
45int main(void) { 10int main(void) {
46//--------------------------------------------------------------------------------- 11 // check the ROM code, make sure this game is supported.
47 12 char* ROM = 0x8000000;
48 // the vblank interrupt must be enabled for VBlankIntrWait() to work 13
49 // since the default dispatcher handles the bios flags no vblank handler 14 if ((*(u32*)(&ROM[0xAC])) != 'EVXA') return 0; // Pokémon Ruby english, nothing else supported!
50 // is required 15
51 irqInit(); 16 void(*loadsave)(char a1);
52 irqEnable(IRQ_VBLANK); 17 // get the address of the save loading function.
53 18 switch (ROM[0xBC]) { // version number
54 consoleDemoInit(); 19 case 0:
55 REG_JOYTR = 0; 20 loadsave = 0x8125EC9;
56 // ansi escape sequence to set print co-ordinates 21 break;
57 // /x1b[line;columnH 22 case 1:
58 u32 i; 23 case 2:
59 iprintf("\x1b[9;2HGBA Link Cable Dumper v1.6\n"); 24 loadsave = 0x8125EE9;
60 iprintf("\x1b[10;4HPlease look at the TV\n"); 25 break;
61 // disable this, needs power 26 default:
62 SNDSTAT = 0; 27 return 0; //bail out
63 SNDBIAS = 0;
64 // Set up waitstates for EEPROM access etc.
65 REG_WAITCNT = 0x0317;
66 //clear out previous messages
67 REG_HS_CTRL |= JOY_RW;
68 while (1) {
69 if(REG_HS_CTRL&JOY_READ)
70 {
71 REG_HS_CTRL |= JOY_RW;
72 s32 gamesize = getGameSize();
73 u32 savesize = SaveSize(save_data,gamesize);
74 REG_JOYTR = gamesize;
75 //wait for a cmd receive for safety
76 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
77 REG_HS_CTRL |= JOY_RW;
78 REG_JOYTR = savesize;
79 //wait for a cmd receive for safety
80 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
81 REG_HS_CTRL |= JOY_RW;
82 if(gamesize == -1)
83 {
84 REG_JOYTR = 0;
85 continue; //nothing to read
86 }
87 //game in, send header
88 for(i = 0; i < 0xC0; i+=4)
89 {
90 REG_JOYTR = *(vu32*)(0x08000000+i);
91 while((REG_HS_CTRL&JOY_READ) == 0) ;
92 REG_HS_CTRL |= JOY_RW;
93 }
94 REG_JOYTR = 0;
95 //wait for other side to choose
96 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
97 REG_HS_CTRL |= JOY_RW;
98 u32 choseval = REG_JOYRE;
99 if(choseval == 0)
100 {
101 REG_JOYTR = 0;
102 continue; //nothing to read
103 }
104 else if(choseval == 1)
105 {
106 //disable interrupts
107 u32 prevIrqMask = REG_IME;
108 REG_IME = 0;
109 //dump the game
110 for(i = 0; i < gamesize; i+=4)
111 {
112 REG_JOYTR = *(vu32*)(0x08000000+i);
113 while((REG_HS_CTRL&JOY_READ) == 0) ;
114 REG_HS_CTRL |= JOY_RW;
115 }
116 //restore interrupts
117 REG_IME = prevIrqMask;
118 }
119 else if(choseval == 2)
120 {
121 //disable interrupts
122 u32 prevIrqMask = REG_IME;
123 REG_IME = 0;
124 //backup save
125 switch (savesize){
126 case 0x200:
127 GetSave_EEPROM_512B(save_data);
128 break;
129 case 0x2000:
130 GetSave_EEPROM_8KB(save_data);
131 break;
132 case 0x8000:
133 GetSave_SRAM_32KB(save_data);
134 break;
135 case 0x10000:
136 GetSave_FLASH_64KB(save_data);
137 break;
138 case 0x20000:
139 GetSave_FLASH_128KB(save_data);
140 break;
141 default:
142 break;
143 }
144 //restore interrupts
145 REG_IME = prevIrqMask;
146 //say gc side we read it
147 REG_JOYTR = savesize;
148 //wait for a cmd receive for safety
149 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
150 REG_HS_CTRL |= JOY_RW;
151 //send the save
152 for(i = 0; i < savesize; i+=4)
153 {
154 REG_JOYTR = *(vu32*)(save_data+i);
155 while((REG_HS_CTRL&JOY_READ) == 0) ;
156 REG_HS_CTRL |= JOY_RW;
157 }
158 }
159 else if(choseval == 3 || choseval == 4)
160 {
161 REG_JOYTR = savesize;
162 if(choseval == 3)
163 {
164 //receive the save
165 for(i = 0; i < savesize; i+=4)
166 {
167 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
168 REG_HS_CTRL |= JOY_RW;
169 *(vu32*)(save_data+i) = REG_JOYRE;
170 }
171 }
172 else
173 {
174 //clear the save
175 for(i = 0; i < savesize; i+=4)
176 *(vu32*)(save_data+i) = 0;
177 }
178 //disable interrupts
179 u32 prevIrqMask = REG_IME;
180 REG_IME = 0;
181 //write it
182 switch (savesize){
183 case 0x200:
184 PutSave_EEPROM_512B(save_data);
185 break;
186 case 0x2000:
187 PutSave_EEPROM_8KB(save_data);
188 break;
189 case 0x8000:
190 PutSave_SRAM_32KB(save_data);
191 break;
192 case 0x10000:
193 PutSave_FLASH_64KB(save_data);
194 break;
195 case 0x20000:
196 PutSave_FLASH_128KB(save_data);
197 break;
198 default:
199 break;
200 }
201 //restore interrupts
202 REG_IME = prevIrqMask;
203 //say gc side we're done
204 REG_JOYTR = 0;
205 //wait for a cmd receive for safety
206 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
207 REG_HS_CTRL |= JOY_RW;
208 }
209 REG_JOYTR = 0;
210 }
211 else if(REG_HS_CTRL&JOY_WRITE)
212 {
213 REG_HS_CTRL |= JOY_RW;
214 u32 choseval = REG_JOYRE;
215 if(choseval == 5)
216 {
217 //disable interrupts
218 u32 prevIrqMask = REG_IME;
219 REG_IME = 0;
220 //dump BIOS
221 for (i = 0; i < 0x4000; i+=4)
222 {
223 // the lower bits are inaccurate, so just get it four times :)
224 u32 a = MidiKey2Freq((WaveData *)(i-4), 180-12, 0) * 2;
225 u32 b = MidiKey2Freq((WaveData *)(i-3), 180-12, 0) * 2;
226 u32 c = MidiKey2Freq((WaveData *)(i-2), 180-12, 0) * 2;
227 u32 d = MidiKey2Freq((WaveData *)(i-1), 180-12, 0) * 2;
228 REG_JOYTR = ((a>>24<<24) | (d>>24<<16) | (c>>24<<8) | (b>>24));
229 while((REG_HS_CTRL&JOY_READ) == 0) ;
230 REG_HS_CTRL |= JOY_RW;
231 }
232 //restore interrupts
233 REG_IME = prevIrqMask;
234 }
235 REG_JOYTR = 0;
236 }
237 Halt();
238 } 28 }
29 loadsave(0);
30 // now the save is loaded, we can do what we want with the loaded blocks.
31 // here as a small PoC, changing first letter of player name to 'z'.
32 u8* gSaveBlock2 = 0x2024EA4;
33 gSaveBlock2[0] = 0xee; // 'z'
34 // Now we've done what we want, time to return to the game.
35 // Can't just return, the game will reload the save.
36 // So let's just call the main-loop directly ;)
37 void(*mainloop)() = 0x80002A5;
38 // turn the sound back on before we head back to the game
39 *(vu16 *)(REG_BASE + 0x84) = 0x8f;
40 mainloop();
41 // Anything past here will not be executed.
42 return 0;
239} 43}
240 44
241 45
diff --git a/gba/start/pkjb_crt0.s b/gba/start/pkjb_crt0.s new file mode 100644 index 0000000..1bf5bd7 --- /dev/null +++ b/gba/start/pkjb_crt0.s
@@ -0,0 +1,98 @@
1 .section ".init"
2 .global _start
3 .align
4 .arm
5@---------------------------------------------------------------------------------
6_start:
7@---------------------------------------------------------------------------------
8 b rom_header_end
9
10 .fill 156,1,0 @ Nintendo Logo Character Data (8000004h)
11 .fill 16,1,0 @ Game Title
12 .byte 0x30,0x31 @ Maker Code (80000B0h)
13 .byte 0x96 @ Fixed Value (80000B2h)
14 .byte 0x00 @ Main Unit Code (80000B3h)
15 .byte 0x00 @ Device Type (80000B4h)
16 .fill 7,1,0 @ unused
17 .byte 0x00 @ Software Version No (80000BCh)
18 .byte 0xf0 @ Complement Check (80000BDh)
19 .byte 0x00,0x00 @ Checksum (80000BEh)
20
21@---------------------------------------------------------------------------------
22rom_header_end:
23@---------------------------------------------------------------------------------
24 b start_vector @ This branch must be here for proper
25 @ positioning of the following header.
26
27 .GLOBAL __boot_method, __slave_number
28@---------------------------------------------------------------------------------
29__boot_method:
30@---------------------------------------------------------------------------------
31 .byte 0 @ boot method (0=ROM boot, 3=Multiplay boot)
32@---------------------------------------------------------------------------------
33__slave_number:
34@---------------------------------------------------------------------------------
35 .byte 0 @ slave # (1=slave#1, 2=slave#2, 3=slave#3)
36
37 .byte 0 @ reserved
38 .byte 0 @ reserved
39 .word 0 @ reserved
40 .word 0 @ reserved
41 .word 0 @ reserved
42 .word 0 @ reserved
43 .word 0 @ reserved
44 .word 0 @ reserved
45
46 .fill 4096,1,0 @ 4kb of filler so no useful code gets overwritten when flash bytes get copied over the top.
47 .global start_vector
48 .align
49@---------------------------------------------------------------------------------
50start_vector:
51@---------------------------------------------------------------------------------
52
53@---------------------------------------------------------------------------------
54@ Enter Thumb mode
55@---------------------------------------------------------------------------------
56 add r0, pc, #1
57 bx r0
58
59 .thumb
60@ Turn off sound
61 ldr r1, =0x4000084
62 eor r0, r0, r0
63 strh r0, [r1]
64
65@---------------------------------------------------------------------------------
66@ set heap end
67@---------------------------------------------------------------------------------
68 ldr r1, =fake_heap_end
69 ldr r0, =__eheap_end
70 str r0, [r1]
71@---------------------------------------------------------------------------------
72@ global constructors
73@---------------------------------------------------------------------------------
74 ldr r3, =__libc_init_array
75 push {lr}
76 bl _blx_r3_stub
77@---------------------------------------------------------------------------------
78@ Jump to user code
79@---------------------------------------------------------------------------------
80 mov r0, #0 @ int argc
81 mov r1, #0 @ char *argv[]
82 ldr r3, =main
83 bl _blx_r3_stub
84@; If we're here, turn the sound back on before we return
85 ldr r1, =0x4000084
86 mov r0, #0x8F
87 strh r0, [r1]
88 pop {pc}
89
90@---------------------------------------------------------------------------------
91_blx_r3_stub:
92@---------------------------------------------------------------------------------
93 bx r3
94
95 .align
96 .pool
97 .end
98