GameBoy Advance Multiboot & Dumper
Dependencies: SDFileSystem mbed
Diff: multiboot.cpp
- Revision:
- 0:66a93ef88e4e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multiboot.cpp Mon Nov 24 13:28:15 2014 +0000 @@ -0,0 +1,171 @@ +// mbed GBA Loader - Boot up a GameBoy Advance using Multiboot (no cart req.) +// +// Ken Kaarvik kkaarvik@yahoo.com Nov 13, 2010 +// akkera102 Nov 08, 2014(modified) +// +// mbed(LPC1768) gba serial port(color) +// p1-0V 6-GND (blue) +// p5-mosi 3-SI (orange) +// p6-miso 2-SO (red) +// p7-sck 5-SC (green) +// +// The GBA file that you wish to load into the GBA is stored on the mbed's local file system. +// Apply power to the mbed (or reset) before turning on the GBA. + +#include "multiboot.h" + +static LocalFileSystem local("local"); +static Serial pc(USBTX, USBRX); +static SPI spi(p5, p6, p7); + + +uint32_t WriteSPI32(uint32_t w, char* msg) +{ + uint32_t r = WriteSPI32NoDebug(w); + + pc.printf("0x%08x 0x%08x ; %s\n",r , w, msg); + return r; +} + +uint32_t WriteSPI32NoDebug(uint32_t w) +{ + uint16_t w1 = w >> 16; + uint16_t w2 = w & 0xffff; + + uint32_t r; + r = spi.write(w1) << 16; + r = spi.write(w2) | r; + + return r; +} + +void WaitSPI32(uint32_t w, uint32_t comp, char* msg) +{ + pc.printf("%s 0x%08x\n", msg, comp); + uint32_t r; + + do + { + r = WriteSPI32NoDebug(w); + wait(0.1); + + } while(r != comp); +} + +int MultiBoot(char* filename) +{ + spi.format(16, 3); + spi.frequency(100000); + + + FILE *fp = fopen(filename, "rb"); + if(fp == NULL) + { + pc.printf("Err: Can't open file\n"); + return EXIT_FAILURE; + } + + fseek(fp, 0L, SEEK_END); + long fsize = (ftell(fp) + 0x0f) & 0xfffffff0; + + if(fsize > 0x40000) + { + pc.printf("Err: Max file size 256kB\n"); + return EXIT_FAILURE; + } + + fseek(fp, 0L, SEEK_SET); + long fcnt = 0; + + + uint32_t r, w, w2; + int i, bit; + + WaitSPI32(0x00006202, 0x72026202, "Looking for GBA"); + + r = WriteSPI32(0x00006202, "Found GBA"); + r = WriteSPI32(0x00006102, "Recognition OK"); + + pc.printf("Send Header(NoDebug)\n"); + for(i=0; i<=0x5f; i++) + { + w = getc(fp); + w = getc(fp) << 8 | w; + fcnt += 2; + + r = WriteSPI32NoDebug(w); + } + + r = WriteSPI32(0x00006200, "Transfer of header data complete"); + r = WriteSPI32(0x00006202, "Exchange master/slave info again"); + + r = WriteSPI32(0x000063d1, "Send palette data"); + r = WriteSPI32(0x000063d1, "Send palette data, receive 0x73hh****"); + + uint32_t m = ((r & 0x00ff0000) >> 8) + 0xffff00d1; + uint32_t h = ((r & 0x00ff0000) >> 16) + 0xf; + + r = WriteSPI32((((r >> 16) + 0xf) & 0xff) | 0x00006400, "Send handshake data"); + r = WriteSPI32((fsize - 0x190) / 4, "Send length info, receive seed 0x**cc****"); + + uint32_t f = (((r & 0x00ff0000) >> 8) + h) | 0xffff0000; + uint32_t c = 0x0000c387; + + + pc.printf("Send encrypted data(NoDebug)\n"); + + while(fcnt < fsize) + { + w = getc(fp); + w = getc(fp) << 8 | w; + w = getc(fp) << 16 | w; + w = getc(fp) << 24 | w; + + w2 = w; + + for(bit=0; bit<32; bit++) + { + if((c ^ w) & 0x01) + { + c = (c >> 1) ^ 0x0000c37b; + } + else + { + c = c >> 1; + } + + w = w >> 1; + } + + m = (0x6f646573 * m) + 1; + WriteSPI32NoDebug(w2 ^ ((~(0x02000000 + fcnt)) + 1) ^m ^0x43202f2f); + + fcnt = fcnt + 4; + } + fclose(fp); + + + for(bit=0; bit<32; bit++) + { + if((c ^ f) & 0x01) + { + c =( c >> 1) ^ 0x0000c37b; + } + else + { + c = c >> 1; + } + + f = f >> 1; + } + + WaitSPI32(0x00000065, 0x00750065, "Wait for GBA to respond with CRC"); + + r = WriteSPI32(0x00000066, "GBA ready with CRC"); + r = WriteSPI32(c, "Let's exchange CRC!"); + + pc.printf("CRC ...hope they match!\n"); + pc.printf("MulitBoot done\n"); + + return EXIT_SUCCESS; +}