gatekeep.c 6.76 KB
#include <PR/bcp.h>
#include <PR/R4300.h>
#include <PR/bbsim.h>
#include <PR/bbskapi.h>

#include <PR/os.h>
#include <PR/os_bb.h>
#include <PR/os_bbfs.h>
#include <PR/os_bbatb.h>
#include <PR/os_bbexec.h>
#include <PR/ramrom.h>

#include <libfb.h>
#include "gatekeep.h"

#define ALIGN_DCACHE __attribute__((aligned(DCACHE_LINESIZE)))
#define printstr fbPrintf

static u32 gMiSecModeRegEntryVal;
extern u32  __osBbHackFlags;

/*
 * debug print support
 */

#undef PRINTF

#ifdef DEBUG
#define	PRINTF	osSyncPrintf
#else
#define	PRINTF(format, args...)
#endif

#define fbhBlue         GPACK_RGBA5551(0,0,80,1)
#define fbhGreen        GPACK_RGBA5551(0,80,0,1)
#define fbhRed          GPACK_RGBA5551(80,0,0,1)
#define fbhYellow       GPACK_RGBA5551(80,80,0,1)
#define fbhMagenta      GPACK_RGBA5551(80,0,80,1)
#define fbhCyan         GPACK_RGBA5551(0,80,80,1)

#define fbLemonChiffon          GPACK_RGBA5551(255,250,205,1)
#define fbLightSlateBlue        GPACK_RGBA5551(132,112,255,1)
#define fbLightPink1            GPACK_RGBA5551(255,174,185,1)
#define fbThistle2              GPACK_RGBA5551(238,210,238,1)
#define fbSeaGreen4             GPACK_RGBA5551(105,139,105,1)
#define fbTomato1               GPACK_RGBA5551(255,99,71,1)
#define fbTurquoise2            GPACK_RGBA5551(0,229,238,1)
#define fbSienna4               GPACK_RGBA5551(139,71,38,1)


/*
 * Thread and stack structures
 */

char   bootStack[STACKSIZE] __attribute__ ((aligned (8)));

static OSThread idleThread;
static char     idleThreadStack[STACKSIZE] __attribute__ ((aligned (8)));

static OSThread mainThread;
static char     mainThreadStack[STACKSIZE] __attribute__ ((aligned (8)));

/* 
 * FS specific definitions
 */

static void	idleproc(char *);
static void	mainproc(char *);


#define DMA_QUEUE_SIZE	200

static OSMesg           PiMessages[DMA_QUEUE_SIZE];
static OSMesgQueue      PiMessageQ;

static OSMesg           SiMessages[DMA_QUEUE_SIZE];
static OSMesgQueue      SiMessageQ;


/*
 * simple graphics
 */

static OSMesgQueue      retraceMessageQ;
static OSMesg           dummyMessage, retraceMessageBuf;
static u16 cfb[320*240] __attribute__((aligned(64)));

/*
 * controller
 */
static OSMesgQueue      contMessageQ;
OSContStatus statusData[MAXCONTROLLERS];
OSContPad controllerData[MAXCONTROLLERS];
static u16 lastbutton[MAXCONTROLLERS];
static int no_controller = 1;

int gBeginTest = 0;

static void
initController(void)
{
    int i, c = 0;
    u8 pattern;

    if (__osBbIsBb<2)
        __osBbHackFlags = 1;
    else
        __osBbHackFlags = 0;

    osCreateMesgQueue(&contMessageQ, &dummyMessage, 1);
    osSetEventMesg(OS_EVENT_SI, &contMessageQ, (OSMesg) 0);

    osContInit(&contMessageQ, &pattern, &statusData[0]);

    for (i = 0; i < MAXCONTROLLERS; i++) {
        if ((pattern & (1 << i)) &&
            !(statusData[i].errno & CONT_NO_RESPONSE_ERROR)) {
            ++c;
            no_controller = 0;
        }
    }
}


static void
processButton(u16 button, int lastbutton)
{
    if (button & D_JPAD && !(lastbutton & D_JPAD)) {
        // pad down
    }

    if (button & U_JPAD && !(lastbutton & U_JPAD)) {
        // pad up
    }

    // output anything changing here

    if ((button & A_BUTTON && !(lastbutton & A_BUTTON)) ||
        (button & START_BUTTON && !(lastbutton & START_BUTTON))){
        // start or A button pressed
        gBeginTest = 1;
    }
}

static void
readControllers(void)
{
    int i;
    OSContPad *pad;

    osRecvMesg(&contMessageQ, &dummyMessage, OS_MESG_BLOCK);
    osContGetReadData(controllerData);

    for (i = 0; i < MAXCONTROLLERS; ++i) {
        pad = &controllerData[i];
        if (!pad->errno && pad->button != lastbutton[i]) {
            processButton(pad->button, lastbutton[i]);
            lastbutton[i] = pad->button;
        }
    }
}


static void
delay(void) {
    int k;
    for(k = 0; k < 1000000; k++)
	;
}

void  __osBbVideoPllInit(u32);
void boot(u32 miSecModeRegVal)
{
    gMiSecModeRegEntryVal = miSecModeRegVal;

    /* Init the video PLL */
    __osBbVideoPllInit(OS_TV_NTSC);

    osInitialize();

    osCreateThread(&idleThread, 1, (void(*)(void *))idleproc, (void *)0,
                   idleThreadStack+STACKSIZE, 8);
    osStartThread(&idleThread);
}


static void
idleproc(char *argv)		/* priority 8 */
{
    osCreateViManager(OS_PRIORITY_VIMGR);
    fbInit(FB_LOW_RES);

#ifdef DEBUG
    /* should allow usb printing */
    osUsbInit();
#endif

    /*
     * Start PI Mgr for access to cartridge - start before the debugger
     */
    osCreatePiManager((OSPri) OS_PRIORITY_PIMGR, &PiMessageQ, PiMessages,
            DMA_QUEUE_SIZE);

    osCreateMesgQueue(&SiMessageQ, SiMessages, DMA_QUEUE_SIZE);
    osSetEventMesg(OS_EVENT_SI, &SiMessageQ, (OSMesg)DMA_QUEUE_SIZE);

    /*
     * The main thread's priority must be the same or lower than the original
     * idle's thread priority. This allows the idle thread to change its
     * priority to 0 before the main thread starts execution.
     */
    osCreateThread(&mainThread, 3, (void(*)(void *))mainproc, argv,
           mainThreadStack+STACKSIZE/8, (OSPri)7);
    osStartThread(&mainThread);

    osSetThreadPri(0, OS_PRIORITY_IDLE);

    for(;;){}
}


void mainproc(char *argv)
{
    int ret;
    u32 *p;
    BbShaHash hash;
    BbEccSig sign;
    
    /* setup text output to screen */
    osCreateMesgQueue(&retraceMessageQ, &retraceMessageBuf, 1);
    osViSetEvent(&retraceMessageQ, dummyMessage, 1);
    osViBlack(1);
    osViSwapBuffer(cfb);
    fbSetBg(fbBlack);
    fbClear();
    osViBlack(0);
    osWritebackDCacheAll();
    osViSwapBuffer(cfb);
    fbClear();
    initController();

    printstr(fbWhite, 3, 2, "GateKeeper Test");
    osWritebackDCacheAll();

    printstr(fbWhite, 5, 4, "Press A to start");
    osWritebackDCacheAll();

    do {
        osRecvMesg(&retraceMessageQ, NULL, OS_MESG_BLOCK);
        osContStartReadData(&contMessageQ);
        readControllers();
    }while(!gBeginTest);

    printstr(fbWhite, 5, 4, "Starting             ");
    osWritebackDCacheAll();

    /* first check if cleared once sysapp launched */
    for(p=(u32 *)PHYS_TO_K0(INTERNAL_RAM_START);p<(u32 *)PHYS_TO_K0(INTERNAL_RAM_END);p++){
        if(*p!=0){
            fbPrintf(fbWhite, 3, 8, "sysapp first addr: %08x",(u32)p);
            break;
        }
    }

    /* make sk call which will generate internal iram stack */
    ret = skSignHash(hash,sign);

    for(p=(u32 *)PHYS_TO_K0(INTERNAL_RAM_START);p<(u32 *)PHYS_TO_K0(INTERNAL_RAM_END);p++){
        if(*p!=0){
            fbPrintf(fbWhite, 3, 10, "skapi first addr: %08x",(u32)p);
            break;
        }
    }

    printstr(fbWhite, 5, 4, "Complete, A to power down");
    osWritebackDCacheAll();

    gBeginTest = 0;
    do {
        osRecvMesg(&retraceMessageQ, NULL, OS_MESG_BLOCK);
        osContStartReadData(&contMessageQ);
        readControllers();
    }while(!gBeginTest);

    delay();
    osBbPowerOff();
    return;
}