GameBoy Advance Multiboot

Dependencies:   mbed

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
+    }
+
+}