GameBoy Advance Multiboot & RPC

Dependencies:   mbed-rpc mbed

Committer:
akkera102
Date:
Tue Dec 09 08:58:06 2014 +0000
Revision:
0:147f4cedc929
GameBoy Advance Multiboot & Dumper

Who changed what in which revision?

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