GameBoy Advance Multiboot & Dumper

Dependencies:   SDFileSystem mbed

Committer:
akkera102
Date:
Mon Nov 24 13:28:15 2014 +0000
Revision:
0:66a93ef88e4e
1st;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
akkera102 0:66a93ef88e4e 1 // mbed GBA Loader - Boot up a GameBoy Advance using Multiboot (no cart req.)
akkera102 0:66a93ef88e4e 2 //
akkera102 0:66a93ef88e4e 3 // Ken Kaarvik kkaarvik@yahoo.com Nov 13, 2010
akkera102 0:66a93ef88e4e 4 // akkera102 Nov 08, 2014(modified)
akkera102 0:66a93ef88e4e 5 //
akkera102 0:66a93ef88e4e 6 // mbed(LPC1768) gba serial port(color)
akkera102 0:66a93ef88e4e 7 // p1-0V 6-GND (blue)
akkera102 0:66a93ef88e4e 8 // p5-mosi 3-SI (orange)
akkera102 0:66a93ef88e4e 9 // p6-miso 2-SO (red)
akkera102 0:66a93ef88e4e 10 // p7-sck 5-SC (green)
akkera102 0:66a93ef88e4e 11 //
akkera102 0:66a93ef88e4e 12 // The GBA file that you wish to load into the GBA is stored on the mbed's local file system.
akkera102 0:66a93ef88e4e 13 // Apply power to the mbed (or reset) before turning on the GBA.
akkera102 0:66a93ef88e4e 14
akkera102 0:66a93ef88e4e 15 #include "multiboot.h"
akkera102 0:66a93ef88e4e 16
akkera102 0:66a93ef88e4e 17 static LocalFileSystem local("local");
akkera102 0:66a93ef88e4e 18 static Serial pc(USBTX, USBRX);
akkera102 0:66a93ef88e4e 19 static SPI spi(p5, p6, p7);
akkera102 0:66a93ef88e4e 20
akkera102 0:66a93ef88e4e 21
akkera102 0:66a93ef88e4e 22 uint32_t WriteSPI32(uint32_t w, char* msg)
akkera102 0:66a93ef88e4e 23 {
akkera102 0:66a93ef88e4e 24 uint32_t r = WriteSPI32NoDebug(w);
akkera102 0:66a93ef88e4e 25
akkera102 0:66a93ef88e4e 26 pc.printf("0x%08x 0x%08x ; %s\n",r , w, msg);
akkera102 0:66a93ef88e4e 27 return r;
akkera102 0:66a93ef88e4e 28 }
akkera102 0:66a93ef88e4e 29
akkera102 0:66a93ef88e4e 30 uint32_t WriteSPI32NoDebug(uint32_t w)
akkera102 0:66a93ef88e4e 31 {
akkera102 0:66a93ef88e4e 32 uint16_t w1 = w >> 16;
akkera102 0:66a93ef88e4e 33 uint16_t w2 = w & 0xffff;
akkera102 0:66a93ef88e4e 34
akkera102 0:66a93ef88e4e 35 uint32_t r;
akkera102 0:66a93ef88e4e 36 r = spi.write(w1) << 16;
akkera102 0:66a93ef88e4e 37 r = spi.write(w2) | r;
akkera102 0:66a93ef88e4e 38
akkera102 0:66a93ef88e4e 39 return r;
akkera102 0:66a93ef88e4e 40 }
akkera102 0:66a93ef88e4e 41
akkera102 0:66a93ef88e4e 42 void WaitSPI32(uint32_t w, uint32_t comp, char* msg)
akkera102 0:66a93ef88e4e 43 {
akkera102 0:66a93ef88e4e 44 pc.printf("%s 0x%08x\n", msg, comp);
akkera102 0:66a93ef88e4e 45 uint32_t r;
akkera102 0:66a93ef88e4e 46
akkera102 0:66a93ef88e4e 47 do
akkera102 0:66a93ef88e4e 48 {
akkera102 0:66a93ef88e4e 49 r = WriteSPI32NoDebug(w);
akkera102 0:66a93ef88e4e 50 wait(0.1);
akkera102 0:66a93ef88e4e 51
akkera102 0:66a93ef88e4e 52 } while(r != comp);
akkera102 0:66a93ef88e4e 53 }
akkera102 0:66a93ef88e4e 54
akkera102 0:66a93ef88e4e 55 int MultiBoot(char* filename)
akkera102 0:66a93ef88e4e 56 {
akkera102 0:66a93ef88e4e 57 spi.format(16, 3);
akkera102 0:66a93ef88e4e 58 spi.frequency(100000);
akkera102 0:66a93ef88e4e 59
akkera102 0:66a93ef88e4e 60
akkera102 0:66a93ef88e4e 61 FILE *fp = fopen(filename, "rb");
akkera102 0:66a93ef88e4e 62 if(fp == NULL)
akkera102 0:66a93ef88e4e 63 {
akkera102 0:66a93ef88e4e 64 pc.printf("Err: Can't open file\n");
akkera102 0:66a93ef88e4e 65 return EXIT_FAILURE;
akkera102 0:66a93ef88e4e 66 }
akkera102 0:66a93ef88e4e 67
akkera102 0:66a93ef88e4e 68 fseek(fp, 0L, SEEK_END);
akkera102 0:66a93ef88e4e 69 long fsize = (ftell(fp) + 0x0f) & 0xfffffff0;
akkera102 0:66a93ef88e4e 70
akkera102 0:66a93ef88e4e 71 if(fsize > 0x40000)
akkera102 0:66a93ef88e4e 72 {
akkera102 0:66a93ef88e4e 73 pc.printf("Err: Max file size 256kB\n");
akkera102 0:66a93ef88e4e 74 return EXIT_FAILURE;
akkera102 0:66a93ef88e4e 75 }
akkera102 0:66a93ef88e4e 76
akkera102 0:66a93ef88e4e 77 fseek(fp, 0L, SEEK_SET);
akkera102 0:66a93ef88e4e 78 long fcnt = 0;
akkera102 0:66a93ef88e4e 79
akkera102 0:66a93ef88e4e 80
akkera102 0:66a93ef88e4e 81 uint32_t r, w, w2;
akkera102 0:66a93ef88e4e 82 int i, bit;
akkera102 0:66a93ef88e4e 83
akkera102 0:66a93ef88e4e 84 WaitSPI32(0x00006202, 0x72026202, "Looking for GBA");
akkera102 0:66a93ef88e4e 85
akkera102 0:66a93ef88e4e 86 r = WriteSPI32(0x00006202, "Found GBA");
akkera102 0:66a93ef88e4e 87 r = WriteSPI32(0x00006102, "Recognition OK");
akkera102 0:66a93ef88e4e 88
akkera102 0:66a93ef88e4e 89 pc.printf("Send Header(NoDebug)\n");
akkera102 0:66a93ef88e4e 90 for(i=0; i<=0x5f; i++)
akkera102 0:66a93ef88e4e 91 {
akkera102 0:66a93ef88e4e 92 w = getc(fp);
akkera102 0:66a93ef88e4e 93 w = getc(fp) << 8 | w;
akkera102 0:66a93ef88e4e 94 fcnt += 2;
akkera102 0:66a93ef88e4e 95
akkera102 0:66a93ef88e4e 96 r = WriteSPI32NoDebug(w);
akkera102 0:66a93ef88e4e 97 }
akkera102 0:66a93ef88e4e 98
akkera102 0:66a93ef88e4e 99 r = WriteSPI32(0x00006200, "Transfer of header data complete");
akkera102 0:66a93ef88e4e 100 r = WriteSPI32(0x00006202, "Exchange master/slave info again");
akkera102 0:66a93ef88e4e 101
akkera102 0:66a93ef88e4e 102 r = WriteSPI32(0x000063d1, "Send palette data");
akkera102 0:66a93ef88e4e 103 r = WriteSPI32(0x000063d1, "Send palette data, receive 0x73hh****");
akkera102 0:66a93ef88e4e 104
akkera102 0:66a93ef88e4e 105 uint32_t m = ((r & 0x00ff0000) >> 8) + 0xffff00d1;
akkera102 0:66a93ef88e4e 106 uint32_t h = ((r & 0x00ff0000) >> 16) + 0xf;
akkera102 0:66a93ef88e4e 107
akkera102 0:66a93ef88e4e 108 r = WriteSPI32((((r >> 16) + 0xf) & 0xff) | 0x00006400, "Send handshake data");
akkera102 0:66a93ef88e4e 109 r = WriteSPI32((fsize - 0x190) / 4, "Send length info, receive seed 0x**cc****");
akkera102 0:66a93ef88e4e 110
akkera102 0:66a93ef88e4e 111 uint32_t f = (((r & 0x00ff0000) >> 8) + h) | 0xffff0000;
akkera102 0:66a93ef88e4e 112 uint32_t c = 0x0000c387;
akkera102 0:66a93ef88e4e 113
akkera102 0:66a93ef88e4e 114
akkera102 0:66a93ef88e4e 115 pc.printf("Send encrypted data(NoDebug)\n");
akkera102 0:66a93ef88e4e 116
akkera102 0:66a93ef88e4e 117 while(fcnt < fsize)
akkera102 0:66a93ef88e4e 118 {
akkera102 0:66a93ef88e4e 119 w = getc(fp);
akkera102 0:66a93ef88e4e 120 w = getc(fp) << 8 | w;
akkera102 0:66a93ef88e4e 121 w = getc(fp) << 16 | w;
akkera102 0:66a93ef88e4e 122 w = getc(fp) << 24 | w;
akkera102 0:66a93ef88e4e 123
akkera102 0:66a93ef88e4e 124 w2 = w;
akkera102 0:66a93ef88e4e 125
akkera102 0:66a93ef88e4e 126 for(bit=0; bit<32; bit++)
akkera102 0:66a93ef88e4e 127 {
akkera102 0:66a93ef88e4e 128 if((c ^ w) & 0x01)
akkera102 0:66a93ef88e4e 129 {
akkera102 0:66a93ef88e4e 130 c = (c >> 1) ^ 0x0000c37b;
akkera102 0:66a93ef88e4e 131 }
akkera102 0:66a93ef88e4e 132 else
akkera102 0:66a93ef88e4e 133 {
akkera102 0:66a93ef88e4e 134 c = c >> 1;
akkera102 0:66a93ef88e4e 135 }
akkera102 0:66a93ef88e4e 136
akkera102 0:66a93ef88e4e 137 w = w >> 1;
akkera102 0:66a93ef88e4e 138 }
akkera102 0:66a93ef88e4e 139
akkera102 0:66a93ef88e4e 140 m = (0x6f646573 * m) + 1;
akkera102 0:66a93ef88e4e 141 WriteSPI32NoDebug(w2 ^ ((~(0x02000000 + fcnt)) + 1) ^m ^0x43202f2f);
akkera102 0:66a93ef88e4e 142
akkera102 0:66a93ef88e4e 143 fcnt = fcnt + 4;
akkera102 0:66a93ef88e4e 144 }
akkera102 0:66a93ef88e4e 145 fclose(fp);
akkera102 0:66a93ef88e4e 146
akkera102 0:66a93ef88e4e 147
akkera102 0:66a93ef88e4e 148 for(bit=0; bit<32; bit++)
akkera102 0:66a93ef88e4e 149 {
akkera102 0:66a93ef88e4e 150 if((c ^ f) & 0x01)
akkera102 0:66a93ef88e4e 151 {
akkera102 0:66a93ef88e4e 152 c =( c >> 1) ^ 0x0000c37b;
akkera102 0:66a93ef88e4e 153 }
akkera102 0:66a93ef88e4e 154 else
akkera102 0:66a93ef88e4e 155 {
akkera102 0:66a93ef88e4e 156 c = c >> 1;
akkera102 0:66a93ef88e4e 157 }
akkera102 0:66a93ef88e4e 158
akkera102 0:66a93ef88e4e 159 f = f >> 1;
akkera102 0:66a93ef88e4e 160 }
akkera102 0:66a93ef88e4e 161
akkera102 0:66a93ef88e4e 162 WaitSPI32(0x00000065, 0x00750065, "Wait for GBA to respond with CRC");
akkera102 0:66a93ef88e4e 163
akkera102 0:66a93ef88e4e 164 r = WriteSPI32(0x00000066, "GBA ready with CRC");
akkera102 0:66a93ef88e4e 165 r = WriteSPI32(c, "Let's exchange CRC!");
akkera102 0:66a93ef88e4e 166
akkera102 0:66a93ef88e4e 167 pc.printf("CRC ...hope they match!\n");
akkera102 0:66a93ef88e4e 168 pc.printf("MulitBoot done\n");
akkera102 0:66a93ef88e4e 169
akkera102 0:66a93ef88e4e 170 return EXIT_SUCCESS;
akkera102 0:66a93ef88e4e 171 }