User Tools

Site Tools


project:gba:code

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

project:gba:code [2007/04/27 00:21] (current)
Line 1: Line 1:
 +====== Code ======
 +The project is complete, all code was tidied and presented in the project report (available on the [[:project]] page), and instructions on its use was added along with pre-compiled versions and //all// libraries necessary to do compilation. Note that if you are only interested in using the GBA serial port, you might do better to look at my [[:project:gba]] page, which includes pre-compiled versions of ''CommsProbe'' and ''RS232 Terminal'' programs, along with their relevant instructions.
  
 +===== Random snippets of code =====
 +
 +==== BitTest ====
 +
 +<code cpp>
 +// BitTest - initialize two variables and output the
 +// results of applying the ~, &, | and ^
 +// operations
 +
 +#include <iostream.h>
 +
 +char* toBinary(int n){
 + static char sResult[(sizeof(n)*8)]; // static so the return doesn't point to a local var
 +
 + // Use bit-wise AND to check if the LSB of n is set, and place into
 + // our string accordingly (filling right->left due to numerical significance)
 + for(int i=sizeof(sResult); i>=0; i--){
 + sResult[i] = (n & 1) ? '1' : '0' ;
 + n >>= 1;
 + }
 +
 + return sResult; // Return a pointer
 +}
 +
 +int main(int nArg, char* pszArgs[]){
 +
 + //initialize two arguments
 + int nArg1 = 0x0f0f;
 + int nArg2 = 0xf0f0;
 +
 + //now perform each operation in turn
 + //first the unary NOT operator
 + cout << "nArg1 = b" << toBinary(nArg1) << endl;
 + cout << "nArg2 = b" << toBinary(nArg2) << endl;
 + cout << "~nArg1 = b" << toBinary(~nArg1) << endl;
 + cout << "~nArg2 = b" << toBinary(~nArg2) << endl;
 +
 + //now the binary operators
 + cout << "nArg1 & nArg2 = b" << toBinary(nArg1 & nArg2) << endl;
 + cout << "nArg1 | nArg2 = b" << toBinary(nArg1 | nArg2) << endl;
 + cout << "nArg1 ^ nArg2 = b" << toBinary(nArg1 ^ nArg2) << endl;
 +}
 +
 +</code>
 +
 +==== CommsProbe ====
 +
 +<code cpp>
 +#define false 0
 +#define true 1
 +
 +#include <mygba.h>
 +#include "general-purpose-comms.h"
 +
 +short SC, SD, SI, SO, IO;
 +int data;
 +
 +MULTIBOOT
 +int main(void)
 +{
 +    ham_Init();
 +    ham_InitText(0);
 +
 +    SC = SD = SI = SO = IO = 0;
 +    while(1)
 +    {
 +        if(F_CTRLINPUT_LEFT_PRESSED) SC=(SC+1)%2;
 +        if(F_CTRLINPUT_RIGHT_PRESSED) SD=(SD+1)%2;
 +        if(F_CTRLINPUT_B_PRESSED) SI=(SI+1)%2;
 +        if(F_CTRLINPUT_A_PRESSED) SO=(SO+1)%2;
 +        
 +        if(F_CTRLINPUT_L_PRESSED) IO=1;
 +        if(F_CTRLINPUT_R_PRESSED) IO=0;
 +
 +        set_comms(SC, SD, SI, SO, IO);
 +        
 +        int i=0;
 +        while(i<250000)i++;
 +    }
 +}
 +</code>
 +Where ''mygba.h'' is the [[http://www.ngine.de|Ham]] library function and ''general-purpose-comm.h'' is as follows:
 +<code cpp>
 +#ifndef SIO_MULTIPLAYER_H
 +#define SIO_MULTIPLAYER_H 1
 +
 +//RCNT is used for mode selection
 +#define R_RCNT  *(volatile u16*) 0x4000134
 +
 +#include <stdio.h>
 +
 +/* GBAtek 1.4:
 +134h - RCNT (R) - SIO Mode, usage in GENERAL-PURPOSE Mode (R/W)
 +Interrupts can be requested when SI changes from HIGH to LOW, as General Purpose mode does
 +not require a serial shift clock, this interrupt may be produced even when the GBA is in
 +Stop (low power standby) state.
 +
 +  Bit   Expl.
 +  0     SC Data Bit         (0=Low, 1=High)
 +  1     SD Data Bit         (0=Low, 1=High)
 +  2     SI Data Bit         (0=Low, 1=High)
 +  3     SO Data Bit         (0=Low, 1=High)
 +  4     SC Direction        (0=Input, 1=Output)
 +  5     SD Direction        (0=Input, 1=Output)
 +  6     SI Direction        (0=Input, 1=Output, but see below)
 +  7     SO Direction        (0=Input, 1=Output)
 +  8     Interrupt Request   (0=Disable, 1=Enable)
 +  9-13  Not used
 +  14    Must be "0" for General-Purpose Mode
 +  15    Must be "1" for General-Purpose or JOYBUS Mode
 +
 +SI should be always used as Input to avoid problems with other hardware which does not
 +expect data to be output there.
 +*/
 +
 +// Accept a string input of 0 and 1 chars
 +void set_comms(short SC, short SD, short SI, short SO, short IO){
 +    u16 data;
 +    data = (1*SC) + (2*SD) + (4*SI) + (8*SO);
 +    data = data + (IO * 0xf0);  // Set all pins to IO (1=Out, 0=In)
 +    data = data + 0x8000;       // Set general purpose mode ('10' MSB-LSB)
 +
 +    R_RCNT = data;
 +
 +    char st[100];
 +    sprintf(st,"[%04x]",R_RCNT);
 +    ham_DrawText(1,1, st);
 +
 +    if(IO) ham_DrawText(1,2, "Output"); else ham_DrawText(1,2, "Input ");
 +
 +    if(0x1 & R_RCNT) ham_DrawText(1,11,"SC"); else ham_DrawText(1,11,"--");
 +    if(0x2 & R_RCNT) ham_DrawText(5,11,"SD"); else ham_DrawText(5,11,"--");
 +    if(0x4 & R_RCNT) ham_DrawText(10,11,"SI"); else ham_DrawText(10,11,"--");
 +    if(0x8 & R_RCNT) ham_DrawText(15,11,"SO"); else ham_DrawText(15,11,"--");
 +}
 +
 +#endif
 +</code>
 +
 +
 +==== SuspendTest ====
 +NB, has occasional problems with interrupt-driven progress indicator at present, so it's been disabled.
 +
 +<code cpp>
 +#include "mygba.h"
 +
 +MULTIBOOT
 +
 +u32 count=0;
 +
 +void interrupt();
 +char* toBinary(u8 n);
 +
 +int main(void)
 +{
 +    ham_Init();
 +    ham_InitText(0);
 +    ham_InitPad();
 +
 +
 +    // Setup the keypad interrupt register
 +    R_CTRLINT=
 +        256+    // Button R
 +        512+    // Button L
 +        4+      // Select
 +        16384+  // Enable interrupt flag
 +        32768   // Enable logical AND mdoe (all button required)
 +        ;
 +
 +    // Enable keypad interrupt handling
 +    ham_StartIntHandler(INT_TYPE_KEY,&interrupt);
 +    
 +    ham_DrawText(1,1,"Press A to sleep");
 +    ham_DrawText(1,2,"Press L & R & Select to wake");
 +
 +    while(1)
 +    {
 +        ham_UpdatePad();
 +        
 +        if(Pad.Pressed.A)
 +        {
 +            // BIOS 'Stop' command (turn everything off until interrupted)
 +            asm volatile("swi 0x30000");
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +
 +void interrupt()
 +{
 +   count++;
 +   ham_DrawText(1,3,"%d",count);
 +   return;
 +}
 +
 +char* toBinary(u8 n){
 + static char sResult[(sizeof(n)*8)]; // static so the return doesn't point to a local var
 +
 + // Use bit-wise AND to check if the LSB of n is set, and place into
 + // our string accordingly (filling right->left due to numerical significance)
 + int i=sizeof(sResult);
 +    while(i>=0){
 + sResult[i] = (n & 1) ? '1' : '0' ;
 + n >>= 1;
 + i--;
 + }
 +
 + return sResult; // Return a pointer
 +}
 +</code>
 +
 +==== SRAM Backup ====
 +Written to solve problems with my brother's GBA cart (which was losing his save game to Fire Emblam because he plays too quickly).
 +
 +This is designed to use a [[http://www.devrs.com/gba/files/mbv2faqs.php|Multi-Boot v2 cable]] (often shortened to MBv2) and copies to/from the PC as well as displaying a menu on the PC which requires user input to proceed.
 +
 +<code cpp>
 +#include <mygba.h>
 +#include "mbv2lib.c"
 +
 +MULTIBOOT
 +
 +int i = 0;
 +const int SRAM_size = 65536;
 +
 +void displayProgress();
 +
 +int main (void)
 +{
 +    ham_Init();
 +    ham_InitText(0);
 +    ham_DrawText(1,1,"Program started\n");
 +
 +    char c;
 +    int l = 1;
 +    FILE fp = 0;
 +
 +    dprintf("Program Started.\n");
 +    dprintf("Choose:\n");
 +    dprintf("c : Complete (GBA->before.bin, sram.bin->GBA, verify, GBA->after.bin)\n");
 +    dprintf("b : Backup (to sram.bin) and verify\n");
 +    dprintf("B : Backup (to sram.bin)\n");
 +    dprintf("v : Verify (against sram.bin)\n");
 +    dprintf("r : Restore (from sram.bin) and verify\n");
 +    dprintf("R : Restore (from sram.bin)\n");
 +    dprintf("\n");
 +
 +    // Get character from PC keyboard
 +    c = dgetch ();
 +    
 +    dprintf("Setting SRAM waitstate\n");
 +    R_WAITCNT = 3;  // Set SRAM wait state for reliable reading/writing
 +    
 +    // Setup a timer and interrupt for displaying progress indicators
 +    M_TIM0CNT_SPEED_SELECT_SET(1);     // increment timer count every 3,841ms
 +    M_TIM0COUNT_SET(3);                 // Count up to this number
 +    M_TIM0CNT_TIMER_START;
 +    M_TIM0CNT_IRQ_ENABLE;               // This timer can trigger interrupts
 +    
 +    // Disabled as it's randomly causing the program to hang
 +    //ham_StartIntHandler(INT_TYPE_TIM0,&displayProgress);
 +
 +    // Backup
 +    if(c == 'c' || c == 'b')
 +    {
 +        // Copy SRAM or Flash backup to PC
 +        switch(c){
 +            case 'c':
 +                ham_DrawText(1,++l,"Backing up SRAM (before.bin)");
 +                dprintf("\nCopying SRAM to before.bin\n");
 +                fp = dfopen("before.bin","wb");
 +                break;
 +            case 'B':
 +            case 'b':
 +                ham_DrawText(1,++l,"Backing up SRAM (sram.bin)");
 +                dprintf("\nCopying SRAM to sram.bin\n");
 +                fp = dfopen("sram.bin","wb");
 +                break;
 +        }
 +        for (i = 0; i != SRAM_size; i++)
 +        {
 +           dfputc(*(unsigned char *)(i + 0xE000000), fp);
 +        }
 +        ham_DrawText(1,++l, "Done");
 +        dfclose(fp);
 +        dprintf("Done.\n");
 +    }
 +
 +    // Restore
 +    if(c == 'c' || c == 'r' || c == 'R')
 +    {
 +        // Copy PC to SRAM
 +        ham_DrawText(1,++l,"Restoring SRAM (sram.bin)");
 +        dprintf("\nWriting sram.bin to GBA...\n");
 +        dprintf("Opening file...");
 +        fp = dfopen("sram.bin","rb");
 +        dprintf(" Done.\n");
 +        dprintf("Entering loop.\n");
 +
 +        for (i = 0; i != SRAM_size; i++)
 +        {
 +            *(unsigned char *)(i + 0xE000000) = dfgetc (fp);
 +        }
 +        dprintf("End of loop, closing file...");
 +        dfclose(fp);
 +        dprintf("Done.\n");
 +        dprintf("Writing phase complete.\n");
 +        ham_DrawText(1,++l,"Done");
 +    }
 +
 +    // Verify
 +    if(c == 'c' || c == 'b' || c == 'r' || c == 'v')
 +    {
 +        ham_DrawText(1,++l,"Verifying SRAM (sram.bin)");
 +        dprintf("\nVerifying SRAM against sram.bin\n");
 +        dprintf("Opening file...");
 +        fp = dfopen("sram.bin","rb");
 +        dprintf(" Done.\n");
 +        dprintf("Entering loop.\n");
 +
 +        int errors = 0;
 +        for (i = 0; i != SRAM_size; i++)
 +        {
 +            // File char != SRAM char
 +            if(dfgetc (fp) != *(unsigned char *)(i+0xE000000))
 +            {
 +                errors++;
 +            }
 +       }
 +       dprintf("End of loop, closing file...");
 +       dfclose(fp);
 +       dprintf("Done.\n");
 +
 +       if(errors)
 +       {
 +            ham_DrawText(1,++l,"%d bytes failed verification",errors);
 +            dprintf("%d bytes failed verification.\n", errors);
 +       }
 +       else
 +       {
 +            ham_DrawText(1,++l,"Verify OK!");
 +            dprintf("Verify OK!\n");
 +       }
 +    }
 +
 +    // Backup to after.bin
 +    if(c == 'c')
 +    {
 +        ham_DrawText(1,++l,"Backing up SRAM (after.bin)");
 +        dprintf("\nCopying current SRAM to after.bin\n");
 +        fp = dfopen("after.bin","wb");
 +        for (i = 0; i != SRAM_size; i++)
 +        {
 +           dfputc(*(unsigned char *)(i + 0xE000000), fp);
 +        }
 +        ham_DrawText(1,++l, "Done backing up SRAM");
 +        dfclose(fp);
 +        dprintf("Done.\n");
 +    }
 +    
 +    // Remove interrupt to ensure clean restart
 +    ham_StopIntHandler(INT_TYPE_TIM0);
 +    M_TIM0CNT_TIMER_STOP;
 +    M_TIM0CNT_IRQ_DISABLE;
 +
 +    displayProgress();  // Avoid the progress showing '98 percent done' etc
 +
 +    ham_DrawText(1,++l,"Program completed");
 +    dprintf("\nProgram complete. Press any key to restart\n\n\n");
 +    dgetch ();
 +
 +    return 0;
 +}
 +
 +void displayProgress()
 +{
 +    M_INTMST_DISABLE;   // Disable interrupts
 +
 +    ham_DrawText(1,19,"%d percent done.  ", i / (SRAM_size/100));
 +
 +    M_INTMST_ENABLE;    // Re-Enable interrupts
 +}
 +</code>
 +
 +where mbv2lib.c is
 +<code cpp>
 +
 +#define __ANSI_NAMES 0
 +//
 +// v1.40 - Initial release.
 +// v1.41 - Put received keyboard & file data in separate buffers
 +//         to prevent mixing of data during simultaneous use.
 +//         Added dfprintf library function.
 +// v1.42 - Fixed bug in dfputc() where escape characters caused
 +//         character 0x01 to be sent to console. Thanks to
 +//         Tim Schuerewegen for finding this bug.
 +//
 +//  MB v1.41 or later pc software is required to use this library
 +// software.
 +//
 +// NOTE: THIS LIBRARY USES GLOBAL INITIALIZED DATA SO YOU MUST USE
 +// A CRT0.S AND A LINKER SCRIPT THAT SUPPORTS THIS AS WELL. GET
 +// CRTLS V1.1 OR LATER FROM HTTP://www.devrs.com/gba FOR PROPER SUPPORT.
 +//
 +// The following library functions are supported:
 +//
 +// Library name   Standard Name      Function
 +//   dprintf        printf       Print a string on PC console.
 +//   dputchar       putchar      Print a char on PC console.
 +//   dgetch         getch        Get a char from PC keyboard.
 +//   dkbhit         kbhit        Return 1 if PC keyboard char is ready.
 +//
 +//   dfopen         fopen        Open PC file.
 +//   dfclose        fclose       Close PC file.
 +//   dfprintf       fprintf      Print a string to PC file.
 +//   dfgetc         fgetc        Get char from PC file.
 +//   dfputc         fputc        Write a char to PC file.
 +//   drewind        rewind       Set file pointer to start of file.
 +//
 +// If you wish to use the standard naming conventions
 +// rather than the library names then change "__ANSI_NAMES 0"
 +// to "__ANSI_NAMES 1" instead.
 +//
 +// Notes:
 +//
 +//  Currently only ONE file may be open at a time.
 +//
 +//  If you are sending raw binary data to a PC file, use
 +//  dfputc instead of dfprintf. Dfprintf will insert
 +//  carriage return characters before linefeed characters
 +//  on the PC side if the PC console software is running on
 +//  dos/windows for proper text formatting.
 +//
 +//  If you are missing some .h files during compile than get
 +// 'arminc.zip' from http://www.devrs.com/gba in the
 +//  Apps / C Compilers section.
 +//
 +// Example command line:
 +//    mb -s file.mb -c -w 50 -x 255 -m
 +//
 +//  In this example, after transferring "file.mb" to the GBA,
 +// the PC goes into console/file server mode (-c) and also
 +// shows all of the file open/file close/fgetc/fputc commands
 +// (-m) on screen. The -w value should be a large enough value
 +// where the -s is reliable and the -x value should be a large
 +// enough value where the -c is reliable with the GBA.
 +//
 +//      [Sending a file & console mode each have
 +//       their own delay settings because they
 +//       each use a different method for transferring
 +//       data. Each method is about ideal for it's
 +//       application.]
 +//
 +// Example GBA Code:
 +//
 +//  #include "mbv2lib.c"
 +//
 +//  int main (void)
 +//    {
 +//
 +//    int i,j,k;
 +//    FILE fp;
 +//
 +//    dprintf ("Hello world!");
 +//
 +//    // Get character from PC keyboard
 +//    i = dgetch ();
 +//
 +//    // Copy SRAM or Flash backup to PC
 +//    fp = dfopen("sram.bin","wb");
 +//    for (i = 0; i != 0x8000; i++)
 +//       dfputc(*(unsigned char *)(i + 0xE000000), fp);
 +//    dfclose(fp);
 +//
 +//    // Copy PC to SRAM
 +//    fp = dfopen("sram.bin","rb");
 +//    for (i = 0; i != 0x8000; i++)
 +//       *(unsigned char *)(i + 0xE000000) = dfgetc (fp);
 +//    dfclose(fp);
 +
 +//    // Read data from file
 +//    fp = dfopen ("foo.bin", "rb");
 +//    i = dfgetc (fp);
 +//    j = dfgetc (fp);
 +//    k = dfgetc (fp);
 +//    dfclose (fp);
 +//
 +//    }
 +
 +// Data transfer format
 +// --------------------
 +//
 +// PC -> GBA Comms:
 +// Raw data is PC File read data.
 +// ESCCHR 0x00 = nada (used for input polling)
 +// ESCCHR 0x01 = Escape character from PC file read
 +// ESCCHR 0x08 0x?? = Keyboard read data
 +//
 +//
 +// GBA -> PC comms
 +// Raw data is console print data.
 +// ESCCHR = escape sequence
 +// ESCCHR 0x00 = nada (used for input polling)
 +// ESCCHR 0x01 = Escape character for console print
 +// ESCCHR 0x02 = file open (gba -> PC)
 +// ESCCHR 0x03 = file close (gba -> PC)
 +// ESCCHR 0x04 = fgetc (gba -> PC)
 +// ESCCHR 0x05 0x?? = fputc (gba -> PC)
 +// ESCCHR 0x06 = rewind (gba -> PC)
 +// ESCCHR 0x07 = fputc processed (gba -> pC) (Add CR before LF char if win/DOS machine)
 +
 +#define FILE int
 +
 +// Uncomment the following line to define the following types if needed
 +//#define INC_SHORT_NAME_TYPES 1
 +
 +#ifdef INC_SHORT_NAME_TYPES
 + typedef     volatile unsigned char           vu8;
 + typedef     volatile unsigned short int      vu16;
 + typedef     volatile unsigned int            vu32;
 + typedef     volatile unsigned long long int  vu64;
 +
 + typedef     unsigned char           u8;
 + typedef     unsigned short int      u16;
 + typedef     unsigned int            u32;
 + typedef     unsigned long long int  u64;
 +
 + typedef     signed char             s8;
 + typedef     signed short int        s16;
 + typedef     signed int              s32;
 + typedef     signed long long int    s64;
 +#endif
 +
 +#ifdef INC_REG_DEFS
 + #define REG_BASE        0x4000000
 + #define REG_SIOCNT      (REG_BASE + 0x128)  // Serial Communication Control
 + #define REG_SIODATA8    (REG_BASE + 0x12a)  // 8bit Serial Communication Data
 + #define REG_RCNT        (REG_BASE + 0x134)  // General Input/Output Control
 +#endif
 +
 +#include "vsprintf.c"
 +
 +#define __DOUTBUFSIZE 256
 +#define __FINBUFSIZE 256  //Must be a multiple of 2! (ex: 32,64,128,256,512..)
 +#define __KINBUFSIZE 64   //Must be a multiple of 2! (ex: 32,64,128,256,512..)
 +#define __ESCCHR 27
 +
 +#define __ESC_NADA   0
 +#define __ESC_ESCCHR 1
 +#define __ESC_FOPEN  2
 +#define __ESC_FCLOSE 3
 +#define __ESC_FGETC  4
 +#define __ESC_FPUTC  5
 +#define __ESC_REWIND 6
 +#define __ESC_FPUTC_PROCESSED 7         // PC side add CR before LF if DOS machine
 +#define __ESC_KBDCHR 8
 +
 +unsigned char __outstr[__DOUTBUFSIZE];
 +unsigned char __finstr[__FINBUFSIZE];
 +unsigned char __kinstr[__KINBUFSIZE];
 +int finptr = 0;
 +int foutptr = 0;
 +int kinptr = 0;
 +int koutptr = 0;
 +
 +int __dputchar (int c)
 +   {
 +   int rcv;
 +   static int LastChar = 0;
 +   static int KbdCharNext = 0;
 +
 +   // Set non-general purpose comms mode
 +   *(u16 *)REG_RCNT = 0;
 +
 +   // Init normal comms, 8 bit transfer, receive clocking
 +   *(u16 *)REG_SIODATA8 = c;
 +   *(u16 *)REG_SIOCNT = 0x80;
 +
 +   // Wait until transfer is complete
 +   while (*(vu16 *)REG_SIOCNT & 0x80) {}
 +
 +   // Wait until SC is low
 +   while (*(vu16 *)REG_RCNT & 1) {}
 +
 +   // Force SD high
 +   *(u16 *)REG_RCNT = 0x8022;
 +
 +   // Wait until SC is high
 +   while ((*(vu16 *)REG_RCNT & 1)==0) {}
 +
 +   rcv = *(vu16 *)REG_SIODATA8;
 +
 +   if (KbdCharNext)
 +      {
 +      // Put into keyboard buffer
 +      __kinstr[kinptr++] = rcv;
 +      kinptr &= (__KINBUFSIZE-1);
 +
 +      KbdCharNext = 0;
 +
 +      // Make received char look like a NADA character
 +      // so that it won't be buffered elsewhere.
 +      LastChar = __ESCCHR;
 +      rcv = __ESC_NADA;
 +      }
 +
 +   if (LastChar == __ESCCHR)
 +      {
 +      // Process escape character
 +      switch (rcv)
 +         {
 +         case __ESC_ESCCHR:
 +            __finstr[finptr++] = __ESCCHR;
 +            finptr &= (__FINBUFSIZE-1);
 +            break;
 +         case __ESC_KBDCHR:
 +            KbdCharNext = 1;
 +            break;
 +         }
 +      LastChar = 0;
 +      }
 +   else
 +      {
 +      if (rcv == __ESCCHR)
 +         LastChar = __ESCCHR;
 +      else
 +         {
 +         // If char received from PC then save in receive FIFO
 +         __finstr[finptr++] = rcv;
 +         finptr &= (__FINBUFSIZE-1);
 +         }
 +      }
 +   return(1);
 +   }
 +
 +int dputchar (int c)
 +   {
 +   (void) __dputchar(c);
 +   if (c == __ESCCHR)
 +      (void) __dputchar(__ESC_ESCCHR);
 +   return (1);
 +   }
 +
 +void __PrintStr (char *str)
 +   {
 +   while (*str)
 +      (void) dputchar(*str++);
 +   }
 +
 +int dgetch (void)
 +   {
 +   int c;
 +
 +   // If no character is in FIFO then wait for one.
 +   while (kinptr == koutptr)
 +      {
 +      __dputchar(__ESCCHR);
 +      __dputchar(__ESC_NADA);
 +      }
 +
 +   c = __kinstr[koutptr++];
 +   koutptr &= (__KINBUFSIZE-1);
 +
 +   return (c);
 +   }
 +
 +int dfgetch (void)
 +   {
 +   int c;
 +
 +   // If no character is in FIFO then wait for one.
 +   while (finptr == foutptr)
 +      {
 +      __dputchar(__ESCCHR);
 +      __dputchar(__ESC_NADA);
 +      }
 +
 +   c = __finstr[foutptr++];
 +   foutptr &= (__FINBUFSIZE-1);
 +
 +   return (c);
 +   }
 +
 +int dkbhit (void)
 +   {
 +   return(kinptr != koutptr);
 +   }
 +
 +FILE dfopen (const char *file, const char *type)
 +   {
 +   __dputchar(__ESCCHR);
 +   __dputchar(__ESC_FOPEN);
 +
 +   while (*file)
 +      (void) dputchar(*file++);
 +   dputchar(0);
 +
 +   while (*type)
 +      (void) dputchar(*type++);
 +   dputchar(0);
 +
 +   return(1);
 +   }
 +
 +int dfclose (FILE fp)
 +   {
 +   __dputchar(__ESCCHR);
 +   __dputchar(__ESC_FCLOSE);
 +
 +   return(1);
 +   }
 +
 +int dfgetc (FILE fp)
 +   {
 +   __dputchar(__ESCCHR);
 +   __dputchar(__ESC_FGETC);
 +
 +   return(dfgetch());
 +   }
 +
 +int dfputc (int ch, FILE fp)
 +   {
 +   __dputchar(__ESCCHR);
 +   __dputchar(__ESC_FPUTC);
 +
 +   __dputchar(ch);                 /* Bug fix. Was:  dputchar(ch); */
 +
 +   return(1);
 +   }
 +
 +void drewind (FILE fp)
 +   {
 +   __dputchar(__ESCCHR);
 +   __dputchar(__ESC_REWIND);
 +   }
 +
 +void __PrintStrToFile (FILE fp, char *str)
 +   {
 +   while (*str)
 +      {
 +      __dputchar(__ESCCHR);
 +      __dputchar(__ESC_FPUTC_PROCESSED);
 +
 +      dputchar(*str++);
 +      }
 +   }
 +
 +#ifndef dprintf
 + #define dprintf(x...) ({ dsprintf(__outstr, x); __PrintStr(__outstr); })
 +#endif
 +#define dfprintf(y,x...) ({ dsprintf(__outstr, x); __PrintStrToFile(y,__outstr); })
 +
 +#ifdef __ANSI_NAMES
 +  #define printf  dprintf
 +  #define fprintf dfprintf
 +  #define putchar dputchar
 +  #define getch   dgetch
 +  #define kbhit   dkbhit
 +
 +  #define fopen   dfopen
 +  #define fclose  dfclose
 +  #define fgetc   dfgetc
 +  #define fputc   dfputc
 +  #define rewind  drewind
 +#endif
 +</code>
 +
 +==== RS232 Terminal ====
 +Adapted from [[http://www.fivemouse.com.com/gba]] to compile with HAM and echo sent characters locally, the code is spread accross multiple files, so I've just compressed the files into a .rar file. 
 +
 +[[http://robmeerman.co.uk/downloads/GBA%20RS232%20Terminal.rar]]
project/gba/code.txt · Last modified: 2007/04/27 00:21 (external edit)