Ken Kaarvik
/
gba_multiboot
GameBoy Advance Multiboot
main.cpp@0:b046e1b46227, 2010-11-13 (annotated)
- Committer:
- kek
- Date:
- Sat Nov 13 10:42:21 2010 +0000
- Revision:
- 0:b046e1b46227
Who changed what in which revision?
User | Revision | Line number | New 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 | } |