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