GameBoy Advance Multiboot

Dependencies:   mbed

Committer:
kek
Date:
Sat Nov 13 10:42:21 2010 +0000
Revision:
0:b046e1b46227

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kek 0:b046e1b46227 1 // mbed GBA Loader - Boot up a GameBoy Advance using Multiboot (no cart req.)
kek 0:b046e1b46227 2 //
kek 0:b046e1b46227 3 // Ken Kaarvik kkaarvik@yahoo.com
kek 0:b046e1b46227 4 // Nov 13, 2010
kek 0:b046e1b46227 5 //
kek 0:b046e1b46227 6 // mbed gba serial port
kek 0:b046e1b46227 7 // 1-0V 6-0V
kek 0:b046e1b46227 8 // p5-mosi 3-SI
kek 0:b046e1b46227 9 // p6-miso 2-SO
kek 0:b046e1b46227 10 // p7-sck 5-SC
kek 0:b046e1b46227 11 // p8-input 1-3V3
kek 0:b046e1b46227 12 //
kek 0:b046e1b46227 13 // p15-analogIn 0-3V3 test voltage pot
kek 0:b046e1b46227 14 // p16-analogIn 0-3V3 test voltage pot
kek 0:b046e1b46227 15 //
kek 0:b046e1b46227 16 // note: the GBA does not power the mbed
kek 0:b046e1b46227 17 //
kek 0:b046e1b46227 18 // The GBA file that you wish to load into the GBA is stored on the mbed's local file system.
kek 0:b046e1b46227 19 // (Just drag and drop it onto the drive where mbed is located.)
kek 0:b046e1b46227 20 // The GBA can be multibooted with a maximum file size of 256kB (the mbed shows up on my
kek 0:b046e1b46227 21 // computer as a flash drive with 2MB of memory, room for several GBA files!)
kek 0:b046e1b46227 22 //
kek 0:b046e1b46227 23 // Apply power to the mbed (or reset) before turning on the GBA.
kek 0:b046e1b46227 24 //
kek 0:b046e1b46227 25
kek 0:b046e1b46227 26 #include "mbed.h"
kek 0:b046e1b46227 27
kek 0:b046e1b46227 28 Serial pc(USBTX, USBRX); //debug info - see raw data being transferred back and forth as GBA is booting
kek 0:b046e1b46227 29
kek 0:b046e1b46227 30 SPI spi(p5, p6, p7); // mosi, miso, sclk
kek 0:b046e1b46227 31
kek 0:b046e1b46227 32 LocalFileSystem local("local");
kek 0:b046e1b46227 33
kek 0:b046e1b46227 34 DigitalIn gba_present(p8);
kek 0:b046e1b46227 35
kek 0:b046e1b46227 36 DigitalOut myled1(LED1); //used for my demo program (volt4.gba)
kek 0:b046e1b46227 37 DigitalOut myled2(LED2); //used for my demo program (volt4.gba)
kek 0:b046e1b46227 38 DigitalOut myled3(LED3); //used for my demo program (volt4.gba)
kek 0:b046e1b46227 39 DigitalOut myled4(LED4); //used for my demo program (volt4.gba)
kek 0:b046e1b46227 40 AnalogIn voltmeter1(p15); //used for my demo program (volt4.gba)
kek 0:b046e1b46227 41 AnalogIn voltmeter2(p16); //used for my demo program (volt4.gba)
kek 0:b046e1b46227 42
kek 0:b046e1b46227 43 unsigned long read_from_gba;
kek 0:b046e1b46227 44 //unsigned long test_counter;
kek 0:b046e1b46227 45
kek 0:b046e1b46227 46 long writeSPI32bits(long write32)
kek 0:b046e1b46227 47 {
kek 0:b046e1b46227 48 pc.printf("0x%08x ",write32);
kek 0:b046e1b46227 49 long read32 = (spi.write(write32>>16))<<16;
kek 0:b046e1b46227 50 read32 = (spi.write(write32))|read32;
kek 0:b046e1b46227 51 pc.printf("0x%08x ",read32);
kek 0:b046e1b46227 52 return read32;
kek 0:b046e1b46227 53 }
kek 0:b046e1b46227 54
kek 0:b046e1b46227 55 long writeSPI32bits_nodebug(long write32)
kek 0:b046e1b46227 56 {
kek 0:b046e1b46227 57 long read32 = (spi.write(write32>>16))<<16;
kek 0:b046e1b46227 58 read32 = (spi.write(write32))|read32;
kek 0:b046e1b46227 59 return read32;
kek 0:b046e1b46227 60 }
kek 0:b046e1b46227 61
kek 0:b046e1b46227 62 int main()
kek 0:b046e1b46227 63 {
kek 0:b046e1b46227 64 // Setup the spi for 8 bit data, high steady state clock,
kek 0:b046e1b46227 65 // second edge capture, with a 100 kHz clock rate
kek 0:b046e1b46227 66 spi.format(16,3);
kek 0:b046e1b46227 67 spi.frequency(100000);
kek 0:b046e1b46227 68
kek 0:b046e1b46227 69 pc.printf("\n\n\r.....GBA Multiboot Hack......\n\n\r");
kek 0:b046e1b46227 70 if (gba_present)
kek 0:b046e1b46227 71 pc.printf(".....Please turn off GBA.....\n\r");
kek 0:b046e1b46227 72 while(gba_present);
kek 0:b046e1b46227 73 wait(0.2);
kek 0:b046e1b46227 74 if(!gba_present)
kek 0:b046e1b46227 75 pc.printf(".....Please turn on GBA......\n\r");
kek 0:b046e1b46227 76 while(!gba_present);
kek 0:b046e1b46227 77 wait(0.2);
kek 0:b046e1b46227 78 pc.printf(".....GBA power up detected!..\n\r");
kek 0:b046e1b46227 79
kek 0:b046e1b46227 80 FILE *fp = fopen("/local/volt4.gba", "rb"); //*****change .gba file here*****
kek 0:b046e1b46227 81 pc.printf(".....Opening GBA file readonly\r\n");
kek 0:b046e1b46227 82
kek 0:b046e1b46227 83 fseek(fp, 0L, SEEK_END); //get *.gba file length
kek 0:b046e1b46227 84 long gba_file_length= ftell(fp);
kek 0:b046e1b46227 85 gba_file_length = (gba_file_length+0x0f)&0xfffffff0; //align length to xfer to 16
kek 0:b046e1b46227 86 fseek(fp, 0L, SEEK_SET);
kek 0:b046e1b46227 87 pc.printf(".....GBA file length 0x%08x\r\n\n",gba_file_length);
kek 0:b046e1b46227 88 pc.printf("MBED(mstr) GBA(slave) \r\n\n");
kek 0:b046e1b46227 89
kek 0:b046e1b46227 90 while(read_from_gba!=0x72026202)
kek 0:b046e1b46227 91 {
kek 0:b046e1b46227 92 wait(0.01);
kek 0:b046e1b46227 93 read_from_gba = writeSPI32bits(0x00006202);
kek 0:b046e1b46227 94 pc.printf(" ;Looking for GBA\r\n");
kek 0:b046e1b46227 95 }
kek 0:b046e1b46227 96
kek 0:b046e1b46227 97 read_from_gba = writeSPI32bits(0x00006202);
kek 0:b046e1b46227 98 pc.printf(" ;Found GBA\r\n");
kek 0:b046e1b46227 99
kek 0:b046e1b46227 100 read_from_gba = writeSPI32bits(0x00006102);
kek 0:b046e1b46227 101 pc.printf(" ;Recognition ok\r\n");
kek 0:b046e1b46227 102
kek 0:b046e1b46227 103 int i;
kek 0:b046e1b46227 104 for(int Counter=0;Counter<=0x5f;Counter++)
kek 0:b046e1b46227 105 {
kek 0:b046e1b46227 106 i = getc(fp); //Read in 16 bits of .gba file
kek 0:b046e1b46227 107 i = getc(fp)<<8|i; //Read in 16 bits of .gba file
kek 0:b046e1b46227 108
kek 0:b046e1b46227 109 read_from_gba = writeSPI32bits_nodebug(0x0000ffff&i);
kek 0:b046e1b46227 110 // pc.printf(" ;send header a\r\n");
kek 0:b046e1b46227 111 }
kek 0:b046e1b46227 112
kek 0:b046e1b46227 113 read_from_gba = writeSPI32bits(0x00006200);
kek 0:b046e1b46227 114 pc.printf(" ;Transfer of header data complete\r\n");
kek 0:b046e1b46227 115
kek 0:b046e1b46227 116 read_from_gba = writeSPI32bits(0x00006202);
kek 0:b046e1b46227 117 pc.printf(" ;Exchange master/slave info again\r\n");
kek 0:b046e1b46227 118
kek 0:b046e1b46227 119 read_from_gba = writeSPI32bits(0x000063d1);
kek 0:b046e1b46227 120 pc.printf(" ;Send palette data\r\n");
kek 0:b046e1b46227 121
kek 0:b046e1b46227 122 read_from_gba = writeSPI32bits(0x000063d1);
kek 0:b046e1b46227 123 pc.printf(" ;Send palette data, receive 0x73hh****\r\n");
kek 0:b046e1b46227 124
kek 0:b046e1b46227 125 long m = ((read_from_gba&0x00ff0000)>>8)+0xffff00d1;
kek 0:b046e1b46227 126 long hh = ((read_from_gba&0x00ff0000)>>16)+0xf;
kek 0:b046e1b46227 127
kek 0:b046e1b46227 128 writeSPI32bits((((read_from_gba>>16)+0x0000000f)&0xff)|0x00006400);
kek 0:b046e1b46227 129 pc.printf(" ;Send handshake data\r\n");
kek 0:b046e1b46227 130
kek 0:b046e1b46227 131 read_from_gba = writeSPI32bits((gba_file_length-0x190)/4);
kek 0:b046e1b46227 132 pc.printf(" ;Send length info, receive seed 0x**cc****\r\n");
kek 0:b046e1b46227 133
kek 0:b046e1b46227 134 long c = 0x0000c387;
kek 0:b046e1b46227 135 long f = ((((read_from_gba&0x00ff0000)>>8)+hh)+0x00)|0xffff0000;
kek 0:b046e1b46227 136
kek 0:b046e1b46227 137 pc.printf(" ;Send encrypted data (takes too long to show it all!)\r\n");
kek 0:b046e1b46227 138
kek 0:b046e1b46227 139 unsigned int gba_file_location = 0xc0;
kek 0:b046e1b46227 140 while(gba_file_location<gba_file_length)
kek 0:b046e1b46227 141 {
kek 0:b046e1b46227 142 long gba_data = getc(fp); //Read in 32 bits of .gba file
kek 0:b046e1b46227 143 gba_data = getc(fp)<<8|gba_data;
kek 0:b046e1b46227 144 gba_data = getc(fp)<<16|gba_data;
kek 0:b046e1b46227 145 gba_data = getc(fp)<<24|gba_data;
kek 0:b046e1b46227 146
kek 0:b046e1b46227 147 long gba_data2 = gba_data;
kek 0:b046e1b46227 148
kek 0:b046e1b46227 149 for(int bit=0;bit<32;bit++)
kek 0:b046e1b46227 150 {
kek 0:b046e1b46227 151 if((c^gba_data)&0x01)
kek 0:b046e1b46227 152 c =(c>>1)^0x0000c37b;
kek 0:b046e1b46227 153 else
kek 0:b046e1b46227 154 c = c>>1;
kek 0:b046e1b46227 155 gba_data = gba_data>>1;
kek 0:b046e1b46227 156 }
kek 0:b046e1b46227 157 m = (0x6f646573*m)+1;
kek 0:b046e1b46227 158 writeSPI32bits_nodebug(gba_data2^((~(0x02000000+gba_file_location))+1)^m^0x43202f2f);//This line or next two
kek 0:b046e1b46227 159 // writeSPI32bits(gba_data2^((~(0x02000000+gba_file_location))+1)^m^0x43202f2f); //*****Uncomment two line to see all data being transfered*****
kek 0:b046e1b46227 160 // pc.printf(" ;\n\r"); //*****Uncomment two line to see all data being transfered*****
kek 0:b046e1b46227 161 gba_file_location=gba_file_location+4;
kek 0:b046e1b46227 162 }
kek 0:b046e1b46227 163
kek 0:b046e1b46227 164 for(int bit=0;bit<32;bit++)
kek 0:b046e1b46227 165 {
kek 0:b046e1b46227 166 if((c^f)&0x01)
kek 0:b046e1b46227 167 c =(c>>1)^0x0000c37b;
kek 0:b046e1b46227 168 else
kek 0:b046e1b46227 169 c = c>>1;
kek 0:b046e1b46227 170 f = f>>1;
kek 0:b046e1b46227 171 }
kek 0:b046e1b46227 172
kek 0:b046e1b46227 173 while (writeSPI32bits(0x00000065)!=0x00750065)
kek 0:b046e1b46227 174 {
kek 0:b046e1b46227 175 pc.printf(" ;Wait for GBA to respond with CRC\n\r");
kek 0:b046e1b46227 176 }
kek 0:b046e1b46227 177
kek 0:b046e1b46227 178 pc.printf(" ;GBA ready with CRC\n\r");
kek 0:b046e1b46227 179
kek 0:b046e1b46227 180 writeSPI32bits(0x00000066);
kek 0:b046e1b46227 181
kek 0:b046e1b46227 182 pc.printf(" ;Let's exchange CRC!\n\r");
kek 0:b046e1b46227 183
kek 0:b046e1b46227 184 writeSPI32bits(c);
kek 0:b046e1b46227 185
kek 0:b046e1b46227 186 pc.printf(" ;CRC ...hope they match!\n\r");
kek 0:b046e1b46227 187 pc.printf(" ;All done!\n\r\n");
kek 0:b046e1b46227 188
kek 0:b046e1b46227 189 fclose(fp); //****Done with multiboot********************************************************
kek 0:b046e1b46227 190
kek 0:b046e1b46227 191 //****Following is code to talk to GBA running my custom program (volt4.gba)*****
kek 0:b046e1b46227 192
kek 0:b046e1b46227 193 while(1) //read in analog values on p15 and p16, only use 9 bits from both, pack up and send to GBA
kek 0:b046e1b46227 194 {
kek 0:b046e1b46227 195 read_from_gba = writeSPI32bits((voltmeter1.read_u16()>>7)|((voltmeter2.read_u16()&0xff80)<<2));
kek 0:b046e1b46227 196 pc.printf("\r");
kek 0:b046e1b46227 197 read_from_gba =(~read_from_gba)&0x3ff;
kek 0:b046e1b46227 198 myled1 = (read_from_gba & 0x1); //turn on led1 when "A" button on GBA is pressed
kek 0:b046e1b46227 199 myled2 = (read_from_gba & 0x2); //B
kek 0:b046e1b46227 200 myled3 = (read_from_gba & 0x4); //Select
kek 0:b046e1b46227 201 myled4 = (read_from_gba & 0x8); //Start
kek 0:b046e1b46227 202 }
kek 0:b046e1b46227 203
kek 0:b046e1b46227 204 }