GameBoy Advance Multiboot & RPC

Dependencies:   mbed-rpc mbed

multiboot.cpp

Committer:
akkera102
Date:
2014-12-09
Revision:
0:147f4cedc929

File content as of revision 0:147f4cedc929:

//  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.01);

    } while(r != comp);
}

int MultiBoot(char* filename) 
{
    spi.format(16, 3);
    spi.frequency(100000); // 100 kHz


    FILE *fp = fopen(filename, "rb");
    if(fp == NULL)
    {
        pc.printf("Err: Can't open file\n");
        return 1;
    }

    fseek(fp, 0L, SEEK_END);
    long fsize = (ftell(fp) + 0x0f) & 0xfffffff0;

    if(fsize > 0x40000)
    {
        pc.printf("Err: Max file size 256kB\n");
        return 1;
    }

    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 0;
}