Skip to content

Instantly share code, notes, and snippets.

@seth10
Last active January 3, 2017 04:14
Show Gist options
  • Save seth10/c969b079c6e367573b5484964c78b2ff to your computer and use it in GitHub Desktop.
Save seth10/c969b079c6e367573b5484964c78b2ff to your computer and use it in GitHub Desktop.
Minimal GBA platformer... with just a floor
// gba.h by eloist
#ifndef GBA_HEADER
#define GBA_HEADER
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
typedef signed char s8;
typedef signed short s16;
typedef signed long s32;
typedef unsigned char byte;
typedef unsigned short hword;
typedef unsigned long word;
#define OAMmem (u32*)0x7000000
#define VideoBuffer (u16*)0x6000000
#define OAMdata (u16*)0x6100000
#define BGPaletteMem (u16*)0x5000000
#define OBJPaletteMem (u16*)0x5000200
#define REG_INTERUPT *(u32*)0x3007FFC
#define REG_DISPCNT *(u32*)0x4000000
#define REG_DISPCNT_L *(u16*)0x4000000
#define REG_DISPCNT_H *(u16*)0x4000002
#define REG_DISPSTAT *(u16*)0x4000004
#define REG_VCOUNT *(u16*)0x4000006
#define REG_BG0CNT *(u16*)0x4000008
#define REG_BG1CNT *(u16*)0x400000A
#define REG_BG2CNT *(u16*)0x400000C
#define REG_BG3CNT *(u16*)0x400000E
#define REG_BG0HOFS *(u16*)0x4000010
#define REG_BG0VOFS *(u16*)0x4000012
#define REG_BG1HOFS *(u16*)0x4000014
#define REG_BG1VOFS *(u16*)0x4000016
#define REG_BG2HOFS *(u16*)0x4000018
#define REG_BG2VOFS *(u16*)0x400001A
#define REG_BG3HOFS *(u16*)0x400001C
#define REG_BG3VOFS *(u16*)0x400001E
#define REG_BG2PA *(u16*)0x4000020
#define REG_BG2PB *(u16*)0x4000022
#define REG_BG2PC *(u16*)0x4000024
#define REG_BG2PD *(u16*)0x4000026
#define REG_BG2X *(u32*)0x4000028
#define REG_BG2X_L *(u16*)0x4000028
#define REG_BG2X_H *(u16*)0x400002A
#define REG_BG2Y *(u32*)0x400002C
#define REG_BG2Y_L *(u16*)0x400002C
#define REG_BG2Y_H *(u16*)0x400002E
#define REG_BG3PA *(u16*)0x4000030
#define REG_BG3PB *(u16*)0x4000032
#define REG_BG3PC *(u16*)0x4000034
#define REG_BG3PD *(u16*)0x4000036
#define REG_BG3X *(u32*)0x4000038
#define REG_BG3X_L *(u16*)0x4000038
#define REG_BG3X_H *(u16*)0x400003A
#define REG_BG3Y *(u32*)0x400003C
#define REG_BG3Y_L *(u16*)0x400003C
#define REG_BG3Y_H *(u16*)0x400003E
#define REG_WIN0H *(u16*)0x4000040
#define REG_WIN1H *(u16*)0x4000042
#define REG_WIN0V *(u16*)0x4000044
#define REG_WIN1V *(u16*)0x4000046
#define REG_WININ *(u16*)0x4000048
#define REG_WINOUT *(u16*)0x400004A
#define REG_MOSAIC *(u32*)0x400004C
#define REG_MOSAIC_L *(u32*)0x400004C
#define REG_MOSAIC_H *(u32*)0x400004E
#define REG_BLDMOD *(u16*)0x4000050
#define REG_COLEV *(u16*)0x4000052
#define REG_COLEY *(u16*)0x4000054
#define REG_SG10 *(u32*)0x4000060
#define REG_SG10_L *(u16*)0x4000060
#define REG_SG10_H *(u16*)0x4000062
#define REG_SG11 *(u16*)0x4000064
#define REG_SG20 *(u16*)0x4000068
#define REG_SG21 *(u16*)0x400006C
#define REG_SG30 *(u32*)0x4000070
#define REG_SG30_L *(u16*)0x4000070
#define REG_SG30_H *(u16*)0x4000072
#define REG_SG31 *(u16*)0x4000074
#define REG_SG40 *(u16*)0x4000078
#define REG_SG41 *(u16*)0x400007C
#define REG_SGCNT0 *(u32*)0x4000080
#define REG_SGCNT0_L *(u16*)0x4000080
#define REG_SGCNT0_H *(u16*)0x4000082
#define REG_SGCNT1 *(u16*)0x4000084
#define REG_SGBIAS *(u16*)0x4000088
#define REG_SGWR0 *(u32*)0x4000090
#define REG_SGWR0_L *(u16*)0x4000090
#define REG_SGWR0_H *(u16*)0x4000092
#define REG_SGWR1 *(u32*)0x4000094
#define REG_SGWR1_L *(u16*)0x4000094
#define REG_SGWR1_H *(u16*)0x4000096
#define REG_SGWR2 *(u32*)0x4000098
#define REG_SGWR2_L *(u16*)0x4000098
#define REG_SGWR2_H *(u16*)0x400009A
#define REG_SGWR3 *(u32*)0x400009C
#define REG_SGWR3_L *(u16*)0x400009C
#define REG_SGWR3_H *(u16*)0x400009E
#define REG_SGFIF0A *(u32*)0x40000A0
#define REG_SGFIFOA_L *(u16*)0x40000A0
#define REG_SGFIFOA_H *(u16*)0x40000A2
#define REG_SGFIFOB *(u32*)0x40000A4
#define REG_SGFIFOB_L *(u16*)0x40000A4
#define REG_SGFIFOB_H *(u16*)0x40000A6
#define REG_DM0SAD *(u32*)0x40000B0
#define REG_DM0SAD_L *(u16*)0x40000B0
#define REG_DM0SAD_H *(u16*)0x40000B2
#define REG_DM0DAD *(u32*)0x40000B4
#define REG_DM0DAD_L *(u16*)0x40000B4
#define REG_DM0DAD_H *(u16*)0x40000B6
#define REG_DM0CNT *(u32*)0x40000B8
#define REG_DM0CNT_L *(u16*)0x40000B8
#define REG_DM0CNT_H *(u16*)0x40000BA
#define REG_DM1SAD *(u32*)0x40000BC
#define REG_DM1SAD_L *(u16*)0x40000BC
#define REG_DM1SAD_H *(u16*)0x40000BE
#define REG_DM1DAD *(u32*)0x40000C0
#define REG_DM1DAD_L *(u16*)0x40000C0
#define REG_DM1DAD_H *(u16*)0x40000C2
#define REG_DM1CNT *(u32*)0x40000C4
#define REG_DM1CNT_L *(u16*)0x40000C4
#define REG_DM1CNT_H *(u16*)0x40000C6
#define REG_DM2SAD *(u32*)0x40000C8
#define REG_DM2SAD_L *(u16*)0x40000C8
#define REG_DM2SAD_H *(u16*)0x40000CA
#define REG_DM2DAD *(u32*)0x40000CC
#define REG_DM2DAD_L *(u16*)0x40000CC
#define REG_DM2DAD_H *(u16*)0x40000CE
#define REG_DM2CNT *(u32*)0x40000D0
#define REG_DM2CNT_L *(u16*)0x40000D0
#define REG_DM2CNT_H *(u16*)0x40000D2
#define REG_DM3SAD *(u32*)0x40000D4
#define REG_DM3SAD_L *(u16*)0x40000D4
#define REG_DM3SAD_H *(u16*)0x40000D6
#define REG_DM3DAD *(u32*)0x40000D8
#define REG_DM3DAD_L *(u16*)0x40000D8
#define REG_DM3DAD_H *(u16*)0x40000DA
#define REG_DM3CNT *(u32*)0x40000DC
#define REG_DM3CNT_L *(u16*)0x40000DC
#define REG_DM3CNT_H *(u16*)0x40000DE
#define REG_TM0D *(u16*)0x4000100
#define REG_TM0CNT *(u16*)0x4000102
#define REG_TM1D *(u16*)0x4000104
#define REG_TM1CNT *(u16*)0x4000106
#define REG_TM2D *(u16*)0x4000108
#define REG_TM2CNT *(u16*)0x400010A
#define REG_TM3D *(u16*)0x400010C
#define REG_TM3CNT *(u16*)0x400010E
#define REG_SCD0 *(u16*)0x4000120
#define REG_SCD1 *(u16*)0x4000122
#define REG_SCD2 *(u16*)0x4000124
#define REG_SCD3 *(u16*)0x4000126
#define REG_SCCNT *(u32*)0x4000128
#define REG_SCCNT_L *(u16*)0x4000128
#define REG_SCCNT_H *(u16*)0x400012A
#define REG_P1 *(u16*)0x4000130
#define REG_P1CNT *(u16*)0x4000132
#define REG_R *(u16*)0x4000134
#define REG_HS_CTRL *(u16*)0x4000140
#define REG_JOYRE *(u32*)0x4000150
#define REG_JOYRE_L *(u16*)0x4000150
#define REG_JOYRE_H *(u16*)0x4000152
#define REG_JOYTR *(u32*)0x4000154
#define REG_JOYTR_L *(u16*)0x4000154
#define REG_JOYTR_H *(u16*)0x4000156
#define REG_JSTAT *(u32*)0x4000158
#define REG_JSTAT_L *(u16*)0x4000158
#define REG_JSTAT_H *(u16*)0x400015A
#define REG_IE *(u16*)0x4000200
#define REG_IF *(u16*)0x4000202
#define REG_WSCNT *(u16*)0x4000204
#define REG_IME *(u16*)0x4000208
#define REG_PAUSE *(u16*)0x4000300
#endif
// Implementation of gfx.h stuff
#include "screenmode.h"
#include "gfx.h"
// used to slow down the gba between frames, and for displaying stuff pretty cool eh?
void Sleep(int i)
{
int x, y;
int c;
for (y = 0; y < i; y++)
{
for (x = 0; x < 30000; x++)
c = c + 2; // do something to slow things down
}
}
void SeedRandom(void)
{
RAND_RandomData = REG_VCOUNT;
}
s32 RAND(s32 Value)
{
RAND_RandomData *= 20077;
RAND_RandomData += 12345;
return ((((RAND_RandomData >> 16) & RAND_MAX) * Value) >> 15);
}
// Gfx.h created 30 Nov 2001
// Desc: Store some of the main graphics routines used by the game
#ifndef GFX_H
#define GFX_H
#include "gba.h"
// GBA stores 15 bit color in blue green red format meaing first 5
// bits are red, next five green, next blue. What is the 16bit?
#define RGB(r,g,b) ((r)+((g)<<5)+((b)<<10))
// do some looping so the gba will wait
// 125 is a good delay for displaying something
// 1 is a good delay for a game (like 30/60 fps) or something like that
void Sleep(int i);
// The following code for random was taken from Mines10.zip of gbadev.org, that author
// had the following comment in it:
// random stuff extracted from an email from 'ninge1'
#define RAND_MAX 32767
volatile s32 RAND_RandomData;
void SeedRandom(void);
s32 RAND(s32 Value);
//usage somwhere in program SeedRandom();
//then xrand = RAND(MAX_X); where MAX_X is range upper bound for value you want returned!
#endif
#include "gba.h"
#define KEY_A 1<<0
#define KEY_B 1<<1
#define KEY_SELECT 1<<2
#define KEY_START 1<<3
#define KEY_RIGHT 1<<4
#define KEY_LEFT 1<<5
#define KEY_UP 1<<6
#define KEY_DOWN 1<<7
#define KEY_R 1<<8
#define KEY_L 1<<9
#define KEYS ~REG_P1
/*
* Main written by Seth Tenembaum beginning Jan 2, 2017
*
* The purpose of this document is to come to a better understanding of the fundamentals of game developmeny by building a simple platformer from scratch at a low level (but not quite down to assembly at the moment).
*
* TODO
* - make git repo, many incremental commits
* - fix issue when holding left and right (actually not possible on physical hardware...)
* - add a single platform
* - implement a global coordinate system, array of platform positions and sizes, and a camera
*
*/
#include "gba.h" //memory addresses and type shortcuts
#include "screenmode.h" //video mode bits and SetMode macro
#include "keypad.h" //buttons and input register
#include "gfx.h" //RGB macro, sleep, random
int main(void) {
SetMode(MODE_3 | BG2_ENABLE); //screenmode.h
// 240 px wide, 160 px tall
s32 xpos = 10, // must be signed
ypos = 100,
xvel = 0,
yvel = 0,
xacc = 0,
yacc = 0;
const s32 GRAV = 1,
FLOOR = 30,
SPEED = 7,
JUMP = 10;
// draw floor
word i;
for (i = 0; i < 240; i++)
(VideoBuffer)[(160-FLOOR+2)*240+i] = RGB(0,10,31);
while (1) {
// erase old sprite (well, point)
(VideoBuffer)[(160-ypos)*240+xpos] = RGB(0,0,0);
// get input
if (KEYS & KEY_LEFT)
xacc--;
if (KEYS & KEY_RIGHT)
xacc++;
if (!(KEYS & (KEY_LEFT|KEY_RIGHT))) // decelerate if neither pressed (TODO: unexpected behavior when both pressed)
if (xvel > 0)
xacc = -1;
else if (xvel < 0)
xacc = 1;
else
xacc = 0;
if (KEYS & KEY_UP && ypos == FLOOR) // only jump if on floor
yvel = JUMP;
// simulate
yvel -= GRAV; // apply gravity
xvel += xacc; // apply acceleration
yvel += yacc;
if (xvel > SPEED) // enfore maximum velocities
xvel = SPEED;
if (xvel < -1*SPEED)
xvel = -1*SPEED;
// apply velocity
if (ypos > FLOOR)
xpos += 0.7*xvel; // air resistance
else
xpos += xvel;
ypos += yvel;
if (ypos < FLOOR) { // pop out of floor
ypos = FLOOR;
yvel = 0;
}
// draw sprite (point)
(VideoBuffer)[(160-ypos)*240+xpos] = RGB(31,31,31);
// pause
int dummy = 0;
while (dummy < 5000) dummy++;
}
}
/****************************************
screenmode.h
by Dovoto
****************************************/
#ifndef SCREENMODE_H
#define SCREENMODE_H
#include "gba.h" //REG_DISPCNT definition
#define MODE_0 0x0
#define MODE_1 0x1
#define MODE_2 0x2
#define MODE_3 0x3
#define MODE_4 0x4
#define MODE_5 0x5
#define BACKBUFFER 0x10
#define H_BLANK_OAM 0x20
#define OBJ_MAP_2D 0x0
#define OBJ_MAP_1D 0x40
#define FORCE_BLANK 0x80
#define BG0_ENABLE 0x100
#define BG1_ENABLE 0x200
#define BG2_ENABLE 0x400
#define BG3_ENABLE 0x800
#define OBJ_ENABLE 0x1000
#define WIN1_ENABLE 0x2000
#define WIN2_ENABLE 0x4000
#define WINOBJ_ENABLE 0x8000
/******SetMode Macro */
#define SetMode(mode) REG_DISPCNT = (mode)
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment