about summary refs log tree commit diff stats
path: root/gba/source/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'gba/source/main.c')
-rw-r--r--gba/source/main.c592
1 files changed, 384 insertions, 208 deletions
diff --git a/gba/source/main.c b/gba/source/main.c index ee94c35..104866a 100644 --- a/gba/source/main.c +++ b/gba/source/main.c
@@ -8,6 +8,8 @@
8#include <stdio.h> 8#include <stdio.h>
9#include <stdlib.h> 9#include <stdlib.h>
10#include "libSave.h" 10#include "libSave.h"
11#include "gamedata.h"
12#include "link.h"
11 13
12#define REG_WAITCNT *(vu16 *)(REG_BASE + 0x204) 14#define REG_WAITCNT *(vu16 *)(REG_BASE + 0x204)
13#define JOY_WRITE 2 15#define JOY_WRITE 2
@@ -18,224 +20,398 @@ u8 save_data[0x20000] __attribute__ ((section (".sbss")));
18 20
19s32 getGameSize(void) 21s32 getGameSize(void)
20{ 22{
21 if(*(vu32*)(0x08000004) != 0x51AEFF24) 23 if(*(vu32*)(0x08000004) != 0x51AEFF24)
22 return -1; 24 return -1;
23 s32 i; 25 s32 i;
24 for(i = (1<<20); i < (1<<25); i<<=1) 26 for(i = (1<<20); i < (1<<25); i<<=1)
27 {
28 vu16 *rompos = (vu16*)(0x08000000+i);
29 int j;
30 bool romend = true;
31 for(j = 0; j < 0x1000; j++)
32 {
33 if(rompos[j] != j)
34 {
35 romend = false;
36 break;
37 }
38 }
39 if(romend) break;
40 }
41 return i;
42}
43
44
45// === (from tonc_memdef.h) ===========================================
46
47// --- REG_DISPCNT defines ---
48#define DCNT_MODE0 0x0000
49#define DCNT_MODE1 0x0001
50#define DCNT_MODE2 0x0002
51#define DCNT_MODE3 0x0003
52#define DCNT_MODE4 0x0004
53#define DCNT_MODE5 0x0005
54// layers
55#define DCNT_BG0 0x0100
56#define DCNT_BG1 0x0200
57#define DCNT_BG2 0x0400
58#define DCNT_BG3 0x0800
59#define DCNT_OBJ 0x1000
60typedef u16 COLOR;
61#define MEM_VRAM 0x06000000
62#define SCREEN_WIDTH 240
63#define vid_mem ((u16*)MEM_VRAM)
64static inline void m3_plot(int x, int y, COLOR clr)
65{ vid_mem[y*SCREEN_WIDTH+x]= clr; }
66static inline COLOR RGB15(u32 red, u32 green, u32 blue)
67{ return red | (green<<5) | (blue<<10); }
68void plot_sqr(int x, int y, COLOR clr)
69{
70 /*for (int j=0;j<8; j++)
25 { 71 {
26 vu16 *rompos = (vu16*)(0x08000000+i); 72 for (int i=0;i<8; i++)
27 int j;
28 bool romend = true;
29 for(j = 0; j < 0x1000; j++)
30 { 73 {
31 if(rompos[j] != j) 74 vid_mem[(y*8+j+32)*SCREEN_WIDTH+x*8+i+32] = clr;
32 {
33 romend = false;
34 break;
35 }
36 } 75 }
37 if(romend) break;
38 } 76 }
39 return i; 77 vid_mem[(y*8+1+32)*SCREEN_WIDTH+x*8+1+32] = RGB15(31,31,31);*/
78}
79void m3_fill(COLOR clr)
80{
81 /*int ii;
82 u32 *dst= (u32*)vid_mem;
83 u32 wd= (clr<<16) | clr;
84
85 for(ii=0; ii<SCREEN_WIDTH/4; ii++)
86 *dst++= wd;*/
40} 87}
41 88
42//--------------------------------------------------------------------------------- 89//---------------------------------------------------------------------------------
43// Program entry point 90// Program entry point
44//--------------------------------------------------------------------------------- 91//---------------------------------------------------------------------------------
45int main(void) { 92int main(void)
46//--------------------------------------------------------------------------------- 93{
94 //REG_IME = 0;
95 //REG_DISPCNT= DCNT_MODE3 | DCNT_BG2;
96 m3_fill(RGB15(31,31,31));
97 plot_sqr( 4, 4, RGB15(31, 0, 0) ); // or CLR_RED
47 98
48 // the vblank interrupt must be enabled for VBlankIntrWait() to work 99
49 // since the default dispatcher handles the bios flags no vblank handler 100
50 // is required 101 //*(vu16 *)(REG_BASE + 0x84) = 0x8f;
51 irqInit(); 102 //REG_IME = 1;
52 irqEnable(IRQ_VBLANK); 103 // the vblank interrupt must be enabled for VBlankIntrWait() to work
53 104 // since the default dispatcher handles the bios flags no vblank handler
54 consoleDemoInit(); 105 // is required
55 REG_JOYTR = 0; 106 //irqInit();
56 // ansi escape sequence to set print co-ordinates 107 //irqEnable(IRQ_VBLANK);
57 // /x1b[line;columnH 108
58 u32 i; 109 //consoleDemoInit();
59 iprintf("\x1b[9;2HGBA Link Cable Dumper v1.6\n"); 110 //REG_JOYTR = 0;
60 iprintf("\x1b[10;4HPlease look at the TV\n"); 111
61 // disable this, needs power 112 // ansi escape sequence to set print co-ordinates
62 SNDSTAT = 0; 113 // /x1b[line;columnH
63 SNDBIAS = 0; 114 //u32 i;
64 // Set up waitstates for EEPROM access etc. 115 //iprintf("\x1b[9;2HPokemon Gen III Data Extractor\n");
65 REG_WAITCNT = 0x0317; 116 //iprintf("\x1b[10;4HPlease look at the TV\n");
66 //clear out previous messages 117
67 REG_HS_CTRL |= JOY_RW; 118 // disable this, needs power
68 while (1) { 119 //SNDSTAT = 0;
69 if(REG_HS_CTRL&JOY_READ) 120 //SNDBIAS = 0;
70 { 121
71 REG_HS_CTRL |= JOY_RW; 122 // Set up waitstates for EEPROM access etc.
72 s32 gamesize = getGameSize(); 123 //REG_WAITCNT = 0x0317;
73 u32 savesize = SaveSize(save_data,gamesize); 124
74 REG_JOYTR = gamesize; 125 //clear out previous messages
75 //wait for a cmd receive for safety 126 REG_HS_CTRL |= JOY_RW;
76 while((REG_HS_CTRL&JOY_WRITE) == 0) ; 127 sendU32(0);
77 REG_HS_CTRL |= JOY_RW; 128 plot_sqr( 4, 5, RGB15( 0,31, 0) ); // or CLR_LIME
78 REG_JOYTR = savesize; 129 while (1)
79 //wait for a cmd receive for safety 130 {
80 while((REG_HS_CTRL&JOY_WRITE) == 0) ; 131 waitForWriteAccess();
81 REG_HS_CTRL |= JOY_RW; 132 //while (recieveU32() != 0);
82 if(gamesize == -1) 133 //waitForAck();
83 { 134 plot_sqr( 4, 6, RGB15( 0, 0,31) ); // or CLR_BLUE
84 REG_JOYTR = 0; 135 // Send game size to acknowledge that an actual cart is inserted.
85 continue; //nothing to read 136 //s32 gamesize = getGameSize();
86 } 137 //sendS32(gamesize);
87 //game in, send header 138 //waitForAck();
88 for(i = 0; i < 0xC0; i+=4) 139
89 { 140 // If the game size is illegal, start over.
90 REG_JOYTR = *(vu32*)(0x08000000+i); 141 //if (gamesize == -1)
91 while((REG_HS_CTRL&JOY_READ) == 0) ; 142 //{
92 REG_HS_CTRL |= JOY_RW; 143 // sendS32(0);
93 } 144 //
94 REG_JOYTR = 0; 145 // continue;
95 //wait for other side to choose 146 //}
96 while((REG_HS_CTRL&JOY_WRITE) == 0) ; 147
97 REG_HS_CTRL |= JOY_RW; 148 // Identify the inserted game.
98 u32 choseval = REG_JOYRE; 149 if (GAME_RUBY)
99 if(choseval == 0) 150 {
100 { 151 sendS32(1);
101 REG_JOYTR = 0; 152 } else if (GAME_SAPP)
102 continue; //nothing to read 153 {
103 } 154 sendS32(2);
104 else if(choseval == 1) 155 } else if (GAME_FR)
105 { 156 {
106 //disable interrupts 157 sendS32(3);
107 u32 prevIrqMask = REG_IME; 158 } else if (GAME_LG)
108 REG_IME = 0; 159 {
109 //dump the game 160 sendS32(4);
110 for(i = 0; i < gamesize; i+=4) 161 } else if (GAME_EM)
111 { 162 {
112 REG_JOYTR = *(vu32*)(0x08000000+i); 163 sendS32(5);
113 while((REG_HS_CTRL&JOY_READ) == 0) ; 164 } else {
114 REG_HS_CTRL |= JOY_RW; 165 sendS32(-1);
115 } 166 waitForAck();
116 //restore interrupts 167
117 REG_IME = prevIrqMask; 168 sendS32(0);
118 } 169
119 else if(choseval == 2) 170 continue;
120 { 171 }
121 //disable interrupts 172 plot_sqr( 5, 4, RGB15( 31, 0,31) );
122 u32 prevIrqMask = REG_IME; 173 waitForAck();
123 REG_IME = 0; 174 plot_sqr( 5, 5, RGB15( 16, 16,16) );
124 //backup save 175 // Get access to save data.
125 switch (savesize){ 176 pSaveBlock1 SaveBlock1;
126 case 0x200: 177 pSaveBlock2 SaveBlock2;
127 GetSave_EEPROM_512B(save_data); 178 pSaveBlock3 SaveBlock3;
128 break; 179 if (!initSaveData(&SaveBlock1, &SaveBlock2, &SaveBlock3))
129 case 0x2000: 180 {
130 GetSave_EEPROM_8KB(save_data); 181 // Unsupported game version.
131 break; 182 //iprintf("Unsupported game version\n");
132 case 0x8000: 183 sendS32(-1);
133 GetSave_SRAM_32KB(save_data); 184 waitForAck();
134 break; 185
135 case 0x10000: 186 sendS32(0);
136 GetSave_FLASH_64KB(save_data); 187
137 break; 188 continue;
138 case 0x20000: 189 }
139 GetSave_FLASH_128KB(save_data); 190 plot_sqr( 5, 6, RGB15( 0, 31,16) );
140 break; 191 sendS32(1);
141 default: 192 waitForAck();
142 break; 193 /*
143 } 194 // Send trainer name.
144 //restore interrupts 195 u8* trainerName;
145 REG_IME = prevIrqMask; 196
146 //say gc side we read it 197 if (GAME_RS)
147 REG_JOYTR = savesize; 198 {
148 //wait for a cmd receive for safety 199 trainerName = SaveBlock2->rs.playerName;
149 while((REG_HS_CTRL&JOY_WRITE) == 0) ; 200 } else if (GAME_FRLG)
150 REG_HS_CTRL |= JOY_RW; 201 {
151 //send the save 202 trainerName = SaveBlock2->frlg.playerName;
152 for(i = 0; i < savesize; i+=4) 203 } else if (GAME_EM)
153 { 204 {
154 REG_JOYTR = *(vu32*)(save_data+i); 205 trainerName = SaveBlock2->e.playerName;
155 while((REG_HS_CTRL&JOY_READ) == 0) ; 206 }
156 REG_HS_CTRL |= JOY_RW; 207 iprintf("%d\n", trainerName[0]);
157 } 208 iprintf("%d\n", trainerName[1]);
158 } 209 iprintf("%d\n", trainerName[2]);
159 else if(choseval == 3 || choseval == 4) 210 iprintf("%d\n", trainerName[3]);
160 { 211 iprintf("%d\n", trainerName[4]);
161 REG_JOYTR = savesize; 212 iprintf("%d\n", trainerName[5]);
162 if(choseval == 3) 213 iprintf("%d\n", trainerName[6]);
163 { 214 iprintf("%d\n", trainerName[7]);
164 //receive the save 215
165 for(i = 0; i < savesize; i+=4) 216 u32 tn1 =
166 { 217 (trainerName[0] << 24)
167 while((REG_HS_CTRL&JOY_WRITE) == 0) ; 218 | (trainerName[1] << 16)
168 REG_HS_CTRL |= JOY_RW; 219 | (trainerName[2] << 8)
169 *(vu32*)(save_data+i) = REG_JOYRE; 220 | (trainerName[3]);
170 } 221
171 } 222 u32 tn2 =
172 else 223 (trainerName[4] << 24)
173 { 224 | (trainerName[5] << 16)
174 //clear the save 225 | (trainerName[6] << 8)
175 for(i = 0; i < savesize; i+=4) 226 | (trainerName[7]);
176 *(vu32*)(save_data+i) = 0; 227
177 } 228 sendU32(tn1);
178 //disable interrupts 229 waitForAck();
179 u32 prevIrqMask = REG_IME; 230
180 REG_IME = 0; 231 sendU32(tn2);
181 //write it 232 waitForAck();
182 switch (savesize){ 233*/
183 case 0x200: 234 // Send trainer ID.
184 PutSave_EEPROM_512B(save_data); 235 u8* trainerId = 0;
185 break; 236
186 case 0x2000: 237 if (GAME_RS)
187 PutSave_EEPROM_8KB(save_data); 238 {
188 break; 239 trainerId = SaveBlock2->rs.playerTrainerId;
189 case 0x8000: 240 } else if (GAME_FRLG)
190 PutSave_SRAM_32KB(save_data); 241 {
191 break; 242 trainerId = SaveBlock2->frlg.playerTrainerId;
192 case 0x10000: 243 } else if (GAME_EM)
193 PutSave_FLASH_64KB(save_data); 244 {
194 break; 245 trainerId = SaveBlock2->e.playerTrainerId;
195 case 0x20000: 246 }
196 PutSave_FLASH_128KB(save_data); 247
197 break; 248 u32 tti =
198 default: 249 (trainerId[2] << 8)
199 break; 250 | (trainerId[3]);
200 } 251
201 //restore interrupts 252 sendU32(tti);
202 REG_IME = prevIrqMask; 253 waitForAck();
203 //say gc side we're done 254
204 REG_JOYTR = 0; 255 // Restart, because we're just testing.
205 //wait for a cmd receive for safety 256 sendS32(0);
206 while((REG_HS_CTRL&JOY_WRITE) == 0) ; 257 //continue;
207 REG_HS_CTRL |= JOY_RW; 258 break;
208 } 259
209 REG_JOYTR = 0; 260/*
210 } 261
211 else if(REG_HS_CTRL&JOY_WRITE) 262
212 { 263 //game in, send header
213 REG_HS_CTRL |= JOY_RW; 264 for(i = 0; i < 0xC0; i+=4)
214 u32 choseval = REG_JOYRE; 265 {
215 if(choseval == 5) 266 REG_JOYTR = *(vu32*)(0x08000000+i);
216 { 267 while((REG_HS_CTRL&JOY_READ) == 0) ;
217 //disable interrupts 268 REG_HS_CTRL |= JOY_RW;
218 u32 prevIrqMask = REG_IME; 269 }
219 REG_IME = 0; 270 REG_JOYTR = 0;
220 //dump BIOS 271 //wait for other side to choose
221 for (i = 0; i < 0x4000; i+=4) 272 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
222 { 273 REG_HS_CTRL |= JOY_RW;
223 // the lower bits are inaccurate, so just get it four times :) 274 u32 choseval = REG_JOYRE;
224 u32 a = MidiKey2Freq((WaveData *)(i-4), 180-12, 0) * 2; 275 if(choseval == 0)
225 u32 b = MidiKey2Freq((WaveData *)(i-3), 180-12, 0) * 2; 276 {
226 u32 c = MidiKey2Freq((WaveData *)(i-2), 180-12, 0) * 2; 277 REG_JOYTR = 0;
227 u32 d = MidiKey2Freq((WaveData *)(i-1), 180-12, 0) * 2; 278 continue; //nothing to read
228 REG_JOYTR = ((a>>24<<24) | (d>>24<<16) | (c>>24<<8) | (b>>24)); 279 }
229 while((REG_HS_CTRL&JOY_READ) == 0) ; 280 else if(choseval == 1)
230 REG_HS_CTRL |= JOY_RW; 281 {
231 } 282 //disable interrupts
232 //restore interrupts 283 u32 prevIrqMask = REG_IME;
233 REG_IME = prevIrqMask; 284 REG_IME = 0;
234 } 285 //dump the game
235 REG_JOYTR = 0; 286 for(i = 0; i < gamesize; i+=4)
236 } 287 {
237 Halt(); 288 REG_JOYTR = *(vu32*)(0x08000000+i);
238 } 289 while((REG_HS_CTRL&JOY_READ) == 0) ;
290 REG_HS_CTRL |= JOY_RW;
291 }
292 //restore interrupts
293 REG_IME = prevIrqMask;
294 }
295 else if(choseval == 2)
296 {
297 //disable interrupts
298 u32 prevIrqMask = REG_IME;
299 REG_IME = 0;
300 //backup save
301 switch (savesize){
302 case 0x200:
303 GetSave_EEPROM_512B(save_data);
304 break;
305 case 0x2000:
306 GetSave_EEPROM_8KB(save_data);
307 break;
308 case 0x8000:
309 GetSave_SRAM_32KB(save_data);
310 break;
311 case 0x10000:
312 GetSave_FLASH_64KB(save_data);
313 break;
314 case 0x20000:
315 GetSave_FLASH_128KB(save_data);
316 break;
317 default:
318 break;
319 }
320 //restore interrupts
321 REG_IME = prevIrqMask;
322 //say gc side we read it
323 REG_JOYTR = savesize;
324 //wait for a cmd receive for safety
325 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
326 REG_HS_CTRL |= JOY_RW;
327 //send the save
328 for(i = 0; i < savesize; i+=4)
329 {
330 REG_JOYTR = *(vu32*)(save_data+i);
331 while((REG_HS_CTRL&JOY_READ) == 0) ;
332 REG_HS_CTRL |= JOY_RW;
333 }
334 }
335 else if(choseval == 3 || choseval == 4)
336 {
337 REG_JOYTR = savesize;
338 if(choseval == 3)
339 {
340 //receive the save
341 for(i = 0; i < savesize; i+=4)
342 {
343 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
344 REG_HS_CTRL |= JOY_RW;
345 *(vu32*)(save_data+i) = REG_JOYRE;
346 }
347 }
348 else
349 {
350 //clear the save
351 for(i = 0; i < savesize; i+=4)
352 *(vu32*)(save_data+i) = 0;
353 }
354 //disable interrupts
355 u32 prevIrqMask = REG_IME;
356 REG_IME = 0;
357 //write it
358 switch (savesize){
359 case 0x200:
360 PutSave_EEPROM_512B(save_data);
361 break;
362 case 0x2000:
363 PutSave_EEPROM_8KB(save_data);
364 break;
365 case 0x8000:
366 PutSave_SRAM_32KB(save_data);
367 break;
368 case 0x10000:
369 PutSave_FLASH_64KB(save_data);
370 break;
371 case 0x20000:
372 PutSave_FLASH_128KB(save_data);
373 break;
374 default:
375 break;
376 }
377 //restore interrupts
378 REG_IME = prevIrqMask;
379 //say gc side we're done
380 REG_JOYTR = 0;
381 //wait for a cmd receive for safety
382 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
383 REG_HS_CTRL |= JOY_RW;
384 }
385 REG_JOYTR = 0;
386 }
387 } else if(REG_HS_CTRL&JOY_WRITE)
388 {
389 REG_HS_CTRL |= JOY_RW;
390 u32 choseval = REG_JOYRE;
391 if(choseval == 5)
392 {
393 //disable interrupts
394 u32 prevIrqMask = REG_IME;
395 REG_IME = 0;
396 //dump BIOS
397 for (i = 0; i < 0x4000; i+=4)
398 {
399 // the lower bits are inaccurate, so just get it four times :)
400 u32 a = MidiKey2Freq((WaveData *)(i-4), 180-12, 0) * 2;
401 u32 b = MidiKey2Freq((WaveData *)(i-3), 180-12, 0) * 2;
402 u32 c = MidiKey2Freq((WaveData *)(i-2), 180-12, 0) * 2;
403 u32 d = MidiKey2Freq((WaveData *)(i-1), 180-12, 0) * 2;
404 REG_JOYTR = ((a>>24<<24) | (d>>24<<16) | (c>>24<<8) | (b>>24));
405 while((REG_HS_CTRL&JOY_READ) == 0) ;
406 REG_HS_CTRL |= JOY_RW;
407 }
408 //restore interrupts
409 REG_IME = prevIrqMask;
410 }
411 REG_JOYTR = 0;
412 }*/
413 Halt();
414 }
239} 415}
240 416
241 417