Ken Kaarvik
/
gba_multiboot
GameBoy Advance Multiboot
Diff: main.cpp
- Revision:
- 0:b046e1b46227
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sat Nov 13 10:42:21 2010 +0000 @@ -0,0 +1,204 @@ +// mbed GBA Loader - Boot up a GameBoy Advance using Multiboot (no cart req.) +// +// Ken Kaarvik kkaarvik@yahoo.com +// Nov 13, 2010 +// +// mbed gba serial port +// 1-0V 6-0V +// p5-mosi 3-SI +// p6-miso 2-SO +// p7-sck 5-SC +// p8-input 1-3V3 +// +// p15-analogIn 0-3V3 test voltage pot +// p16-analogIn 0-3V3 test voltage pot +// +// note: the GBA does not power the mbed +// +// The GBA file that you wish to load into the GBA is stored on the mbed's local file system. +// (Just drag and drop it onto the drive where mbed is located.) +// The GBA can be multibooted with a maximum file size of 256kB (the mbed shows up on my +// computer as a flash drive with 2MB of memory, room for several GBA files!) +// +// Apply power to the mbed (or reset) before turning on the GBA. +// + +#include "mbed.h" + +Serial pc(USBTX, USBRX); //debug info - see raw data being transferred back and forth as GBA is booting + +SPI spi(p5, p6, p7); // mosi, miso, sclk + +LocalFileSystem local("local"); + +DigitalIn gba_present(p8); + +DigitalOut myled1(LED1); //used for my demo program (volt4.gba) +DigitalOut myled2(LED2); //used for my demo program (volt4.gba) +DigitalOut myled3(LED3); //used for my demo program (volt4.gba) +DigitalOut myled4(LED4); //used for my demo program (volt4.gba) +AnalogIn voltmeter1(p15); //used for my demo program (volt4.gba) +AnalogIn voltmeter2(p16); //used for my demo program (volt4.gba) + +unsigned long read_from_gba; +//unsigned long test_counter; + +long writeSPI32bits(long write32) +{ + pc.printf("0x%08x ",write32); + long read32 = (spi.write(write32>>16))<<16; + read32 = (spi.write(write32))|read32; + pc.printf("0x%08x ",read32); + return read32; +} + +long writeSPI32bits_nodebug(long write32) +{ + long read32 = (spi.write(write32>>16))<<16; + read32 = (spi.write(write32))|read32; + return read32; +} + +int main() +{ + // Setup the spi for 8 bit data, high steady state clock, + // second edge capture, with a 100 kHz clock rate + spi.format(16,3); + spi.frequency(100000); + + pc.printf("\n\n\r.....GBA Multiboot Hack......\n\n\r"); + if (gba_present) + pc.printf(".....Please turn off GBA.....\n\r"); + while(gba_present); + wait(0.2); + if(!gba_present) + pc.printf(".....Please turn on GBA......\n\r"); + while(!gba_present); + wait(0.2); + pc.printf(".....GBA power up detected!..\n\r"); + + FILE *fp = fopen("/local/volt4.gba", "rb"); //*****change .gba file here***** + pc.printf(".....Opening GBA file readonly\r\n"); + + fseek(fp, 0L, SEEK_END); //get *.gba file length + long gba_file_length= ftell(fp); + gba_file_length = (gba_file_length+0x0f)&0xfffffff0; //align length to xfer to 16 + fseek(fp, 0L, SEEK_SET); + pc.printf(".....GBA file length 0x%08x\r\n\n",gba_file_length); + pc.printf("MBED(mstr) GBA(slave) \r\n\n"); + + while(read_from_gba!=0x72026202) + { + wait(0.01); + read_from_gba = writeSPI32bits(0x00006202); + pc.printf(" ;Looking for GBA\r\n"); + } + + read_from_gba = writeSPI32bits(0x00006202); + pc.printf(" ;Found GBA\r\n"); + + read_from_gba = writeSPI32bits(0x00006102); + pc.printf(" ;Recognition ok\r\n"); + + int i; + for(int Counter=0;Counter<=0x5f;Counter++) + { + i = getc(fp); //Read in 16 bits of .gba file + i = getc(fp)<<8|i; //Read in 16 bits of .gba file + + read_from_gba = writeSPI32bits_nodebug(0x0000ffff&i); + // pc.printf(" ;send header a\r\n"); + } + + read_from_gba = writeSPI32bits(0x00006200); + pc.printf(" ;Transfer of header data complete\r\n"); + + read_from_gba = writeSPI32bits(0x00006202); + pc.printf(" ;Exchange master/slave info again\r\n"); + + read_from_gba = writeSPI32bits(0x000063d1); + pc.printf(" ;Send palette data\r\n"); + + read_from_gba = writeSPI32bits(0x000063d1); + pc.printf(" ;Send palette data, receive 0x73hh****\r\n"); + + long m = ((read_from_gba&0x00ff0000)>>8)+0xffff00d1; + long hh = ((read_from_gba&0x00ff0000)>>16)+0xf; + + writeSPI32bits((((read_from_gba>>16)+0x0000000f)&0xff)|0x00006400); + pc.printf(" ;Send handshake data\r\n"); + + read_from_gba = writeSPI32bits((gba_file_length-0x190)/4); + pc.printf(" ;Send length info, receive seed 0x**cc****\r\n"); + + long c = 0x0000c387; + long f = ((((read_from_gba&0x00ff0000)>>8)+hh)+0x00)|0xffff0000; + + pc.printf(" ;Send encrypted data (takes too long to show it all!)\r\n"); + + unsigned int gba_file_location = 0xc0; + while(gba_file_location<gba_file_length) + { + long gba_data = getc(fp); //Read in 32 bits of .gba file + gba_data = getc(fp)<<8|gba_data; + gba_data = getc(fp)<<16|gba_data; + gba_data = getc(fp)<<24|gba_data; + + long gba_data2 = gba_data; + + for(int bit=0;bit<32;bit++) + { + if((c^gba_data)&0x01) + c =(c>>1)^0x0000c37b; + else + c = c>>1; + gba_data = gba_data>>1; + } + m = (0x6f646573*m)+1; + writeSPI32bits_nodebug(gba_data2^((~(0x02000000+gba_file_location))+1)^m^0x43202f2f);//This line or next two +// writeSPI32bits(gba_data2^((~(0x02000000+gba_file_location))+1)^m^0x43202f2f); //*****Uncomment two line to see all data being transfered***** +// pc.printf(" ;\n\r"); //*****Uncomment two line to see all data being transfered***** + gba_file_location=gba_file_location+4; + } + + for(int bit=0;bit<32;bit++) + { + if((c^f)&0x01) + c =(c>>1)^0x0000c37b; + else + c = c>>1; + f = f>>1; + } + + while (writeSPI32bits(0x00000065)!=0x00750065) + { + pc.printf(" ;Wait for GBA to respond with CRC\n\r"); + } + + pc.printf(" ;GBA ready with CRC\n\r"); + + writeSPI32bits(0x00000066); + + pc.printf(" ;Let's exchange CRC!\n\r"); + + writeSPI32bits(c); + + pc.printf(" ;CRC ...hope they match!\n\r"); + pc.printf(" ;All done!\n\r\n"); + + fclose(fp); //****Done with multiboot******************************************************** + + //****Following is code to talk to GBA running my custom program (volt4.gba)***** + + while(1) //read in analog values on p15 and p16, only use 9 bits from both, pack up and send to GBA + { + read_from_gba = writeSPI32bits((voltmeter1.read_u16()>>7)|((voltmeter2.read_u16()&0xff80)<<2)); + pc.printf("\r"); + read_from_gba =(~read_from_gba)&0x3ff; + myled1 = (read_from_gba & 0x1); //turn on led1 when "A" button on GBA is pressed + myled2 = (read_from_gba & 0x2); //B + myled3 = (read_from_gba & 0x4); //Select + myled4 = (read_from_gba & 0x8); //Start + } + +}