about summary refs log tree commit diff stats
path: root/gba/source/libSave.c
diff options
context:
space:
mode:
Diffstat (limited to 'gba/source/libSave.c')
-rw-r--r--gba/source/libSave.c596
1 files changed, 0 insertions, 596 deletions
diff --git a/gba/source/libSave.c b/gba/source/libSave.c deleted file mode 100644 index e3bda1d..0000000 --- a/gba/source/libSave.c +++ /dev/null
@@ -1,596 +0,0 @@
1/*
2 libSave
3 Cartridge backup memory save routines. To use, call the required
4 routine with a pointer to an appropriately sized array of data to
5 be read from or written to the cartridge.
6 Data types are from wintermute's gba_types.h libgba library.
7 Original file from SendSave by Chishm
8*/
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <gba_dma.h>
14
15#define EEPROM_ADDRESS (0xDFFFF00)
16#define REG_EEPROM *(vu16 *)(EEPROM_ADDRESS)
17#define REG_DMA3CNT_H *(vu16 *)(REG_BASE + 0x0de)
18#define REG_WAITCNT *(vu16 *)(REG_BASE + 0x204)
19
20//-----------------------------------------------------------------------
21// Common EEPROM Routines
22//-----------------------------------------------------------------------
23
24void EEPROM_SendPacket( u16* packet, int size )
25{
26 REG_WAITCNT = (REG_WAITCNT & 0xF8FF) | 0x0300;
27 REG_DMA3SAD = (u32)packet;
28 REG_DMA3DAD = EEPROM_ADDRESS;
29 REG_DMA3CNT = 0x80000000 + size;
30 while((REG_DMA3CNT_H & 0x8000) != 0) ;
31}
32
33void EEPROM_ReceivePacket( u16* packet, int size )
34{
35 REG_WAITCNT = (REG_WAITCNT & 0xF8FF) | 0x0300;
36 REG_DMA3SAD = EEPROM_ADDRESS;
37 REG_DMA3DAD = (u32)packet;
38 REG_DMA3CNT = 0x80000000 + size;
39 while((REG_DMA3CNT_H & 0x8000) != 0) ;
40}
41
42//-----------------------------------------------------------------------
43// Routines for 512B EEPROM
44//-----------------------------------------------------------------------
45
46void EEPROM_Read_512B( volatile u8 offset, u8* dest ) // dest must point to 8 bytes
47{
48 u16 packet[68];
49 u8* out_pos;
50 u16* in_pos;
51 u8 out_byte;
52 int byte, bit;
53
54 memset( packet, 0, 68*2 );
55
56 // Read request
57 packet[0] = 1;
58 packet[1] = 1;
59
60 // 6 bits eeprom address (MSB first)
61 packet[2] = (offset>>5)&1;
62 packet[3] = (offset>>4)&1;
63 packet[4] = (offset>>3)&1;
64 packet[5] = (offset>>2)&1;
65 packet[6] = (offset>>1)&1;
66 packet[7] = (offset)&1;
67
68 // End of request
69 packet[8] = 0;
70
71 // Do transfers
72 EEPROM_SendPacket( packet, 9 );
73 memset( packet, 0, 68*2 );
74 EEPROM_ReceivePacket( packet, 68 );
75
76 // Extract data
77 in_pos = &packet[4];
78 out_pos = dest;
79 for( byte = 7; byte >= 0; --byte )
80 {
81 out_byte = 0;
82 for( bit = 7; bit >= 0; --bit )
83 {
84// out_byte += (*in_pos++)<<bit;
85 out_byte += ((*in_pos++)&1)<<bit;
86 }
87 *out_pos++ = out_byte ;
88 }
89}
90
91void EEPROM_Write_512B( volatile u8 offset, u8* source ) // source must point to 8 bytes
92{
93 u16 packet[73];
94 u8* in_pos;
95 u16* out_pos;
96 u8 in_byte;
97 int byte, bit;
98
99 memset( packet, 0, 73*2 );
100
101 // Write request
102 packet[0] = 1;
103 packet[1] = 0;
104
105 // 6 bits eeprom address (MSB first)
106 packet[2] = (offset>>5)&1;
107 packet[3] = (offset>>4)&1;
108 packet[4] = (offset>>3)&1;
109 packet[5] = (offset>>2)&1;
110 packet[6] = (offset>>1)&1;
111 packet[7] = (offset)&1;
112
113 // Extract data
114 in_pos = source;
115 out_pos = &packet[8];
116 for( byte = 7; byte >= 0; --byte )
117 {
118 in_byte = *in_pos++;
119 for( bit = 7; bit >= 0; --bit )
120 {
121 *out_pos++ = (in_byte>>bit)&1;
122 }
123 }
124
125 // End of request
126 packet[72] = 0;
127
128 // Do transfers
129 EEPROM_SendPacket( packet, 73 );
130
131 // Wait for EEPROM to finish (should timeout after 10 ms)
132 while( (REG_EEPROM & 1) == 0 );
133}
134
135//---------------------------------------------------------------------------------
136void GetSave_EEPROM_512B(u8* data)
137//---------------------------------------------------------------------------------
138{
139 volatile u8 x;
140 u32 sleep;
141
142 for (x=0;x<64;++x){
143 EEPROM_Read_512B(x,&data[x*8]);
144 for(sleep=0;sleep<512000;sleep++);
145 }
146}
147
148//---------------------------------------------------------------------------------
149void PutSave_EEPROM_512B(u8* data)
150//---------------------------------------------------------------------------------
151{
152 volatile u8 x;
153 u32 sleep;
154
155 for (x=0;x<64;x++){
156 EEPROM_Write_512B(x,&data[x*8]);
157 for(sleep=0;sleep<512000;sleep++);
158 }
159}
160//-----------------------------------------------------------------------
161// Routines for 8KB EEPROM
162//-----------------------------------------------------------------------
163
164void EEPROM_Read_8KB( volatile u16 offset, u8* dest ) // dest must point to 8 bytes
165{
166 u16 packet[68];
167 u8* out_pos;
168 u16* in_pos;
169 u8 out_byte;
170 int byte, bit;
171
172 memset( packet, 0, 68*2 );
173
174 // Read request
175 packet[0] = 1;
176 packet[1] = 1;
177
178 // 14 bits eeprom address (MSB first)
179 packet[2] = (offset>>13)&1;
180 packet[3] = (offset>>12)&1;
181 packet[4] = (offset>>11)&1;
182 packet[5] = (offset>>10)&1;
183 packet[6] = (offset>>9)&1;
184 packet[7] = (offset>>8)&1;
185 packet[8] = (offset>>7)&1;
186 packet[9] = (offset>>6)&1;
187 packet[10] = (offset>>5)&1;
188 packet[11] = (offset>>4)&1;
189 packet[12] = (offset>>3)&1;
190 packet[13] = (offset>>2)&1;
191 packet[14] = (offset>>1)&1;
192 packet[15] = (offset)&1;
193
194 // End of request
195 packet[16] = 0;
196
197 // Do transfers
198 EEPROM_SendPacket( packet, 17 );
199 memset( packet, 0, 68*2 );
200 EEPROM_ReceivePacket( packet, 68 );
201
202 // Extract data
203 in_pos = &packet[4];
204 out_pos = dest;
205 for( byte = 7; byte >= 0; --byte )
206 {
207 out_byte = 0;
208 for( bit = 7; bit >= 0; --bit )
209 {
210// out_byte += (*in_pos++)<<bit;
211 out_byte += ((*in_pos++)&1)<<bit;
212 }
213 *out_pos++ = out_byte;
214 }
215
216}
217
218void EEPROM_Write_8KB( volatile u16 offset, u8* source ) // source must point to 8 bytes
219{
220 u16 packet[81];
221 u8* in_pos;
222 u16* out_pos;
223 u8 in_byte;
224 int byte, bit;
225
226 memset( packet, 0, 81*2 );
227
228 // Write request
229 packet[0] = 1;
230 packet[1] = 0;
231
232 // 14 bits eeprom address (MSB first)
233 packet[2] = (offset>>13)&1;
234 packet[3] = (offset>>12)&1;
235 packet[4] = (offset>>11)&1;
236 packet[5] = (offset>>10)&1;
237 packet[6] = (offset>>9)&1;
238 packet[7] = (offset>>8)&1;
239 packet[8] = (offset>>7)&1;
240 packet[9] = (offset>>6)&1;
241 packet[10] = (offset>>5)&1;
242 packet[11] = (offset>>4)&1;
243 packet[12] = (offset>>3)&1;
244 packet[13] = (offset>>2)&1;
245 packet[14] = (offset>>1)&1;
246 packet[15] = (offset)&1;
247
248 // Extract data
249 in_pos = source;
250 out_pos = &packet[16];
251 for( byte = 7; byte >= 0; --byte )
252 {
253 in_byte = *in_pos++;
254 for( bit = 7; bit >= 0; --bit )
255 {
256 *out_pos++ = (in_byte>>bit)&1;
257 }
258 }
259
260 // End of request
261 packet[80] = 0;
262
263 // Do transfers
264 EEPROM_SendPacket( packet, 81 );
265
266 // Wait for EEPROM to finish (should timeout after 10 ms)
267 while( (REG_EEPROM & 1) == 0 );
268}
269
270//---------------------------------------------------------------------------------
271void GetSave_EEPROM_8KB(u8* data)
272//---------------------------------------------------------------------------------
273{
274 volatile u16 x;
275 u32 sleep;
276
277 for (x=0;x<1024;x++){
278 EEPROM_Read_8KB(x,&data[x*8]);
279 for(sleep=0;sleep<512000;sleep++);
280 }
281
282}
283
284//---------------------------------------------------------------------------------
285void PutSave_EEPROM_8KB(u8* data)
286//---------------------------------------------------------------------------------
287{
288 volatile u16 x;
289 u32 sleep;
290
291 for (x=0;x<1024;x++){
292 EEPROM_Write_8KB(x,&data[x*8]);
293 for(sleep=0;sleep<512000;sleep++);
294 }
295}
296
297//---------------------------------------------------------------------------------
298void GetSave_SRAM_32KB(u8* data)
299//---------------------------------------------------------------------------------
300{
301 volatile u8 *sram= (u8*) 0x0E000000;
302 volatile u16 x;
303
304 for (x = 0; x < 0x8000; ++x)
305 {
306 data[x] = sram[x];
307 }
308
309}
310
311//---------------------------------------------------------------------------------
312void PutSave_SRAM_32KB(u8* data)
313//---------------------------------------------------------------------------------
314{
315 volatile u8 *sram= (u8*) 0x0E000000;
316 volatile u16 x;
317
318 for (x = 0; x < 0x8000; ++x)
319 {
320 sram[x] = data[x];
321 }
322}
323
324//---------------------------------------------------------------------------------
325void GetSave_FLASH_64KB(u8* data)
326//---------------------------------------------------------------------------------
327{
328 volatile u8 *sram= (u8*) 0x0E000000;
329 volatile u32 x;
330
331 for (x = 0; x < 0x10000; ++x)
332 {
333 data[x] = sram[x];
334 }
335}
336
337//---------------------------------------------------------------------------------
338void PutSave_FLASH_64KB(u8* foo)
339//---------------------------------------------------------------------------------
340{
341 volatile u8 *fctrl0 = (u8*) 0xE005555;
342 volatile u8 *fctrl1 = (u8*) 0xE002AAA;
343 volatile u8 *fctrl2 = (u8*) 0xE000000;
344
345 //init flash
346 *fctrl0 = 0xAA;
347 *fctrl1 = 0x55;
348 *fctrl0 = 0x90;
349 *fctrl2 = 0xF0;
350
351 //erase chip
352 *fctrl0 = 0xAA;
353 *fctrl1 = 0x55;
354 *fctrl0 = 0x80;
355 *fctrl0 = 0xAA;
356 *fctrl1 = 0x55;
357 *fctrl0 = 0x10;
358
359 //wait for erase done
360 u8 val1;
361 u8 val2;
362 val1 = *fctrl2;
363 val2 = *fctrl2;
364 while (val1 != val2) {
365 val1 = *fctrl2;
366 val2 = *fctrl2;
367 }
368 val1 = *fctrl2;
369 val2 = *fctrl2;
370 while (val1 != val2) {
371 val1 = *fctrl2;
372 val2 = *fctrl2;
373 }
374
375 volatile u8 *data = fctrl2;
376 u32 i;
377 //write data
378 for (i=0; i<65536; i++) {
379 *fctrl0 = 0xAA;
380 *fctrl1 = 0x55;
381 *fctrl0 = 0xA0;
382 data [i] = foo [ i ];
383 val1 = data [ i ];
384 val2 = data [ i ];
385
386 while (val1 != val2) {
387 val1 = data [ i ];
388 val2 = data [ i ];
389 }
390 val1 = data [ i ];
391 val2 = data [ i ];
392 while (val1 != val2) {
393 val1 = data [ i ];
394 val2 = data [ i ];
395 }
396 val1 = data [ i ];
397 val2 = data [ i ];
398 while (val1 != val2) {
399 val1 = data [ i ];
400 val2 = data [ i ];
401 }
402 }
403}
404
405//---------------------------------------------------------------------------------
406void GetSave_FLASH_128KB(u8* data)
407//---------------------------------------------------------------------------------
408{
409 const u32 size = 0x10000;
410
411 volatile u8 *fctrl0 = (u8*) 0xE005555;
412 volatile u8 *fctrl1 = (u8*) 0xE002AAA;
413 volatile u8 *fctrl2 = (u8*) 0xE000000;
414 volatile u32 i;
415 volatile u8 *sram= (u8*) 0x0E000000;
416
417 //init flash
418 *fctrl0 = 0xAA;
419 *fctrl1 = 0x55;
420 *fctrl0 = 0x90;
421 *fctrl2 = 0xF0;
422
423 // read first bank
424 *fctrl0 = 0xAA;
425 *fctrl1 = 0x55;
426 *fctrl0 = 0xB0;
427 *fctrl2 = 0x00;
428
429 for (i=0; i<size; i++){
430 data[i] = sram[i];
431 }
432
433 // read second bank
434 *fctrl0 = 0xAA;
435 *fctrl1 = 0x55;
436 *fctrl0 = 0xB0;
437 *fctrl2 = 0x01;
438
439 for (i=0; i<size; i++){
440 data[i + size] = sram[i];
441 }
442
443}
444
445//---------------------------------------------------------------------------------
446void PutSave_FLASH_128KB(u8* foo)
447//---------------------------------------------------------------------------------
448{
449 volatile u8 *fctrl0 = (u8*) 0xE005555;
450 volatile u8 *fctrl1 = (u8*) 0xE002AAA;
451 volatile u8 *fctrl2 = (u8*) 0xE000000;
452
453 u8 val1;
454 u8 val2;
455
456 //init flash
457 *fctrl0 = 0xAA;
458 *fctrl1 = 0x55;
459 *fctrl0 = 0x90;
460 *fctrl2 = 0xF0;
461
462 //erase chip
463 *fctrl0 = 0xAA;
464 *fctrl1 = 0x55;
465 *fctrl0 = 0x80;
466 *fctrl0 = 0xAA;
467 *fctrl1 = 0x55;
468 *fctrl0 = 0x10;
469
470 //wait for erase done
471 val1 = *fctrl2;
472 val2 = *fctrl2;
473 while (val1 != val2) {
474 val1 = *fctrl2;
475 val2 = *fctrl2;
476 }
477 val1 = *fctrl2;
478 val2 = *fctrl2;
479 while (val1 != val2) {
480 val1 = *fctrl2;
481 val2 = *fctrl2;
482 }
483
484 volatile u8 *data = fctrl2;
485 volatile u32 i;
486 // change to bank 0
487 *fctrl0 = 0xAA;
488 *fctrl1 = 0x55;
489 *fctrl0 = 0xB0;
490 *fctrl2 = 0x00;
491
492 //write data
493 for (i=0; i<65536; i++) {
494 *fctrl0 = 0xAA;
495 *fctrl1 = 0x55;
496 *fctrl0 = 0xA0;
497 data [i] = foo [ i ];
498 val1 = data [ i ];
499 val2 = data [ i ];
500
501 while (val1 != val2) {
502 val1 = data [ i ];
503 val2 = data [ i ];
504 }
505 val1 = data [ i ];
506 val2 = data [ i ];
507 while (val1 != val2) {
508 val1 = data [ i ];
509 val2 = data [ i ];
510 }
511 val1 = data [ i ];
512 val2 = data [ i ];
513 while (val1 != val2) {
514 val1 = data [ i ];
515 val2 = data [ i ];
516 }
517 }
518
519 // Change to bank 1
520 *fctrl0 = 0xAA;
521 *fctrl1 = 0x55;
522 *fctrl0 = 0xB0;
523 *fctrl2 = 0x01;
524
525 //write data
526 for (i=0; i<65536; i++) {
527 *fctrl0 = 0xAA;
528 *fctrl1 = 0x55;
529 *fctrl0 = 0xA0;
530 data [i] = foo [ i + 0x10000];
531 val1 = data [ i ];
532 val2 = data [ i ];
533
534 while (val1 != val2) {
535 val1 = data [ i ];
536 val2 = data [ i ];
537 }
538 val1 = data [ i ];
539 val2 = data [ i ];
540 while (val1 != val2) {
541 val1 = data [ i ];
542 val2 = data [ i ];
543 }
544 val1 = data [ i ];
545 val2 = data [ i ];
546 while (val1 != val2) {
547 val1 = data [ i ];
548 val2 = data [ i ];
549 }
550 }
551
552}
553
554//---------------------------------------------------------------------------------
555u32 SaveSize(u8* data, s32 gamesize)
556//---------------------------------------------------------------------------------
557{
558 if(gamesize < 0)
559 return 0;
560
561 u32 *pak= ((u32*)0x08000000);
562 s32 x;
563 u16 i;
564 s32 size = gamesize/4;
565
566
567 for (x=size-1;x>=0;x--){
568 switch (pak[x]) {
569 case 0x53414C46:
570 if (pak[x+1] == 0x5F4D3148){
571 return 0x20000; // FLASH_128KB
572 } else if ((pak[x+1] & 0x0000FFFF) == 0x00005F48){
573 return 0x10000; // FLASH_64KB
574 } else if (pak[x+1] == 0x32313548){
575 return 0x10000; // FLASH_64KB
576 }
577 break;
578 case 0x52504545:
579 if ((pak[x+1] & 0x00FFFFFF) == 0x005F4D4F){
580 GetSave_EEPROM_8KB(data);
581 for(i = 8; i < 0x800; i += 8) {
582 if(memcmp(data, data+i, 8) != 0)
583 return 0x2000; // EEPROM_8KB
584 }
585 return 0x200; // EEPROM_512B
586 }
587 break;
588 case 0x4D415253:
589 if ((pak[x+1] & 0x000000FF) == 0x0000005F){
590 return 0x8000; // SRAM_32KB
591 }
592 }
593 }
594 return 0;
595}
596