PVSnesLib  4.3.0
Documentation to code in C or ASM for the Nintendo SNES
games/likemario/LikeMario.c
/*---------------------------------------------------------------------------------
Simple game with map and sprite engine demo
-- alekmaul
---------------------------------------------------------------------------------*/
#include <snes.h>
#include "soundbank.h"
//---------------------------------------------------------------------------------
extern char SOUNDBANK__;
extern char jumpsnd, jumpsndend;
//---------------------------------------------------------------------------------
#define GRAVITY 48
#define JUMPVALUE (GRAVITY * 20)
#define MARIO_MAXACCEL 0x0140
#define MARIO_ACCEL 0x0038
#define MARIO_JUMPING 0x0394
#define MARIO_HIJUMPING 0x0594
enum
{
MARIODOWN = 0,
MARIOJUMPING = 1,
MARIOWALK = 2,
MARIOSTAND = 6
}; // Mario state
//---------------------------------------------------------------------------------
extern char tileset, tilesetend, tilepal;
extern char tilesetdef, tilesetatt; // for map & tileset of map
extern char mapmario, objmario;
extern char mariogfx, mariogfx_end;
extern char mariopal;
extern char snesfont, snespal;
//---------------------------------------------------------------------------------
brrsamples Jump; // The sound for jumping
u16 pad0; // pad variable
t_objs *marioobj; // pointer to mario object
s16 *marioox, *mariooy; // basics x/y coordinates pointers with fixed point
s16 *marioxv, *marioyv; // basics x/y velocity pointers with fixed point
u16 mariox, marioy; // x & y coordinates of mario with map depth (not only screen)
u8 mariofidx, marioflp, flip; // to manage sprite display
//---------------------------------------------------------------------------------
// Init function for mario object
void marioinit(u16 xp, u16 yp, u16 type, u16 minx, u16 maxx)
{
// to have a little message regarding init (DO NOT USE FOR REAL SNES GAME, JUST DEBUGGING PURPOSE)
consoleNocashMessage("marioinit %d %d\n", (u16)xp, (u16)yp);
// prepare new object
if (objNew(type, xp, yp) == 0)
// no more space, get out
return;
// Init some vars for snes sprite (objgetid is the current object id)
marioobj = &objbuffers[objptr - 1];
marioobj->width = 16;
marioobj->height = 16;
// grab the coordinates & velocity pointers
marioox = (u16 *)&(marioobj->xpos + 1);
mariooy = (u16 *)&(marioobj->ypos + 1);
marioxv = (short *)&(marioobj->xvel);
marioyv = (short *)&(marioobj->yvel);
// update some variables for mario
mariofidx = 0;
marioflp = 0;
marioobj->action = ACT_STAND;
// prepare dynamic sprite object
oambuffer[0].oamattribute = 0x60 | (0 << 1); // palette 0 of sprite and sprite 16x16 and priority 2 and flip sprite
oambuffer[0].oamgraphics = &mariogfx;
// Init Sprites palette
setPalette(&mariopal, 128 + 0 * 16, 16 * 2);
}
//---------------------------------------------------------------------------------
// mario walk management
void mariowalk(u8 idx)
{
// update animation
flip++;
if ((flip & 3) == 3)
{
mariofidx++;
mariofidx = mariofidx & 1;
oambuffer[0].oamframeid = marioflp + mariofidx;
}
// check if we are still walking or not with the velocity properties of object
if (*marioyv != 0)
marioobj->action = ACT_FALL;
else if ((*marioxv == 0) && (*marioyv == 0))
marioobj->action = ACT_STAND;
}
//---------------------------------------------------------------------------------
// mario fall management
void mariofall(u8 idx)
{
// if no more falling, just stand
if (*marioyv == 0)
{
marioobj->action = ACT_STAND;
}
}
//---------------------------------------------------------------------------------
// mario jump management
void mariojump(u8 idx)
{
// change sprite
if (oambuffer[0].oamframeid != 1)
{
}
// if no more jumping, then fall
if (*marioyv >= 0)
marioobj->action = ACT_FALL;
}
//---------------------------------------------------------------------------------
// Update function for mario object
void marioupdate(u8 idx)
{
// Get pad value, no move for the moment
pad0 = padsCurrent(0);
// check only the keys for the game
if (pad0 & (KEY_RIGHT | KEY_LEFT | KEY_A))
{
// go to the left
if (pad0 & KEY_LEFT)
{
// update anim (sprites 2-3)
if ((marioflp > 3) || (marioflp < 2))
{
marioflp = 2;
}
oambuffer[0].oamattribute &= ~0x40; // do not flip sprite
// update velocity
marioobj->action = ACT_WALK;
*marioxv -= (MARIO_ACCEL);
if (*marioxv <= (-MARIO_MAXACCEL))
*marioxv = (-MARIO_MAXACCEL);
}
// go to the right
if (pad0 & KEY_RIGHT)
{
// update anim (sprites 2-3)
if ((marioflp > 3) || (marioflp < 2))
{
marioflp = 2;
}
oambuffer[0].oamattribute |= 0x40; // flip sprite
// update velocity
marioobj->action = ACT_WALK;
*marioxv += (MARIO_ACCEL);
if (*marioxv >= (MARIO_MAXACCEL))
*marioxv = (MARIO_MAXACCEL);
}
// jump
if (pad0 & KEY_A)
{
// we can jump only if we are on ground
if ((marioobj->tilestand != 0))
{
marioobj->action = ACT_JUMP;
// if key up, jump 2x more
if (pad0 & KEY_UP)
*marioyv = -(MARIO_HIJUMPING);
else
*marioyv = -(MARIO_JUMPING);
}
}
}
// 1st, check collision with map
// update animation regarding current mario state
if (marioobj->action == ACT_WALK)
mariowalk(idx);
else if (marioobj->action == ACT_FALL)
mariofall(idx);
else if (marioobj->action == ACT_JUMP)
mariojump(idx);
// Update position
// check boundaries
if (*marioox <= 0)
*marioox = 0;
if (*mariooy <= 0)
*mariooy = 0;
// change sprite coordinates regarding map location
mariox = (*marioox);
marioy = (*mariooy);
oambuffer[0].oamx = mariox - x_pos;
oambuffer[0].oamy = marioy - y_pos;
// update camera regarding mario object
mapUpdateCamera(mariox, marioy);
}
//---------------------------------------------------------------------------------
int main(void)
{
// Initialize sound engine (take some time)
// Initialize SNES
// Initialize text console with our font
consoleInitText(1, 16 * 2, &snesfont, &snespal);
// Set give soundbank
spcSetBank(&SOUNDBANK__);
// allocate around 10K of sound ram (39 256-byte blocks)
// Load music
spcLoad(MOD_OVERWORLD);
// Load sample
spcSetSoundEntry(15, 8, 6, &jumpsndend - &jumpsnd, &jumpsnd, &Jump);
// Init layer with tiles and init also map length 0x6800 is mandatory for map engine
bgSetGfxPtr(1, 0x3000);
bgSetMapPtr(1, 0x6000, SC_32x32);
bgInitTileSet(0, &tileset, &tilepal, 0, (&tilesetend - &tileset), 16 * 2, BG_16COLORS, 0x2000);
bgSetMapPtr(0, 0x6800, SC_64x32);
// Init sprite engine (0x0000 for large, 0x1000 for small)
oamInitDynamicSprite(0x0000, 0x1000, 0, 0, OBJ_SIZE8_L16);
// Object engine activate
// Init function for state machine
objInitFunctions(0, &marioinit, &marioupdate, NULL);
// Load all objects into memory
objLoadObjects((char *)&objmario);
// Load map in memory and update it regarding current location of the sprite
mapLoad((u8 *)&mapmario, (u8 *)&tilesetdef, (u8 *)&tilesetatt);
// Now Put in 16 color mode and disable BG3
setMode(BG_MODE1, 0);
// Put some text
consoleDrawText(6, 16, "MARIOx00 WORLD TIME");
consoleDrawText(6, 17, " 00000 ox00 1-1 000");
// Put screen on
// Play file from the beginning
spcPlay(0);
// Wait VBL 'and update sprites too ;-) )
// Wait for nothing :P
while (1)
{
// Update the map regarding the camera
// Update all the available objects
// prepare next frame and wait vblank
}
return 0;
}
void bgSetGfxPtr(u8 bgNumber, u16 address)
Definition of each background address.
void bgSetDisable(u8 bgNumber)
Disable a BG in the actual SNES mode.
void bgSetMapPtr(u8 bgNumber, u16 address, u8 mapSize)
Change Background Map address.
void bgInitTileSet(u8 bgNumber, u8 *tileSource, u8 *tilePalette, u8 paletteEntry, u16 tileSize, u16 paletteSize, u16 colorMode, u16 address)
Initializes a Tile Set and Loads the Tile GFX into VRAM.
void consoleSetTextVramAdr(u16 vramfont)
Change text graphics address (4K aligned)
void consoleNocashMessage(char *fmt,...)
Send a message to the no$sns debug window.
void consoleInitText(u8 palnum, u8 palsize, u8 *tilfont, u8 *palfont)
Initialize the Text System.
void consoleInit(void)
Initialize console.
void consoleDrawText(u16 x, u16 y, char *fmt,...)
Output formatted string on a screen (tiles mode)
void consoleSetTextVramBGAdr(u16 offsetfont)
Change text Background map address for display (must be BG address)
#define padsCurrent(value)
Return current value of selected pad.
Definition: input.h:161
@ KEY_UP
pad UP button.
Definition: input.h:55
@ KEY_LEFT
pad LEFT button.
Definition: input.h:53
@ KEY_RIGHT
pad RIGHT button.
Definition: input.h:52
@ KEY_A
pad A button.
Definition: input.h:48
void WaitForVBlank(void)
Wait for vblank interrupt
void mapVblank(void)
Display map regarding current buffer (must be done once per frame, near Vblank)
#define ACT_STAND
Action type STAND for object.
Definition: map.h:45
void mapUpdate(void)
Update map regarding current camera position (must be done once per frame)
#define ACT_JUMP
Action type JUMP for object.
Definition: map.h:47
u16 y_pos
Current value of camera in x & y coordinates.
Definition: map.h:57
#define ACT_FALL
Action type FALL for object.
Definition: map.h:48
#define ACT_WALK
Action type WALK for object.
Definition: map.h:46
void mapLoad(u8 *layer1map, u8 *layertiles, u8 *tilesprop)
Load map definition into memory.
void mapUpdateCamera(u16 xpos, u16 ypos)
Update map camera (must be done once per frame)
void objUpdateXY(u16 objhandle)
Update X & Y coordinates of object regarding its own velocitys.
t_objs objbuffers[OB_MAX]
current object buffer with all objects
u16 objNew(u8 objtype, u16 x, u16 y)
Initialize a new object in game, objgetid will has the id of the object.
void objCollidMap(u16 objhandle)
check if an object collides the map
void objInitFunctions(u8 objtype, void *initfct, void *updfct, void *reffct)
Initialize the object type functions (initialize, update)
u16 objptr
pointer to current object
void objUpdateAll(void)
call update function for all objects currently active (if they are in "virtual screen" coordinates).
void objGetPointer(u16 objhandle)
get the pointer to an object from its handle (need to do -1 to have offset after),...
void objInitEngine(void)
Initialize object engine, need to be called once.
u16 objgetid
id of current object (useful when creating it)
void objLoadObjects(u8 *sourceO)
Load all objects for a specific table in memory.
the master include file for snes applications.
void spcAllocateSoundRegion(u8 size)
set the size of the sound region (this must be big enough to hold your longest/largest sound) this fu...
void spcLoad(u16 musIndex)
load module into sm-spc. this function may take some time to execute
void spcSetSoundEntry(u8 vol, u8 panning, u8 pitch, u16 length, u8 *sampleaddr, brrsamples *ptr)
set the values and address of the SOUND TABLE for a sound entry
void spcPlaySound(u8 sndIndex)
Play sound from memory (using default arguments)
void spcSetBank(u8 *bank)
set soundbank origin. soundbank must have dedicated bank(s)
void spcProcess(void)
Process messages This function will try to give messages to the spc until a few scanlines pass.
void spcBoot(void)
boots the spc700 with sm-spc. call once at startup
void spcSetModuleVolume(u8 vol)
set the module playback volume
void spcPlay(u8 startPos)
play module. note: this simply queues a message, use spcFlush if you want to wait until the message i...
t_sprites oambuffer[128]
Sprite Table (from no$sns help file) Contains data for 128 OBJs. OAM Size is 512+32 Bytes....
void oamVramQueueUpdate(void)
Update VRAM graphics for sprites 32x32, 16x16 and 8x8 (can but call in Vblank if needed).
#define OBJ_SIZE8_L16
default OAM size 8x8 (SM) and 16x16 (LG) pix for OBJSEL register
Definition: sprite.h:39
void oamInitDynamicSpriteEndFrame(void)
Must be call at the end of the frame, initialize the dynamic sprite engine for the next frame.
void oamInitDynamicSprite(u16 gfxsp0adr, u16 gfxsp1adr, u16 oamsp0init, u16 oamsp1init, u8 oamsize)
initialize the dynamic sprite engine with each sprite size entries
void oamDynamic16Draw(u16 id)
Add a 16x16 sprite on screen. oambuffer[id] needs to be populate before.
brr sample sound header(8 bytes)
Definition: sound.h:51
object definition (64 bytes)
Definition: object.h:49
s16 xvel
Definition: object.h:68
u16 height
Definition: object.h:65
s16 yvel
Definition: object.h:69
u16 width
Definition: object.h:64
u8 xpos[3]
Definition: object.h:60
u16 tilestand
Definition: object.h:70
u8 ypos[3]
Definition: object.h:61
u16 action
Definition: object.h:74
u16 oamframeid
4 frame index in graphic file of the sprite
Definition: sprite.h:62
s16 oamx
0 x position on the screen
Definition: sprite.h:60
u8 * oamgraphics
8..11 pointer to graphic file
Definition: sprite.h:65
s16 oamy
2 y position on the screen
Definition: sprite.h:61
u8 oamattribute
6 sprite attribute value (vhoopppc v : vertical flip h: horizontal flip o: priority bits p: palette n...
Definition: sprite.h:63
u8 oamrefresh
7 =1 if we need to load graphics from graphic file
Definition: sprite.h:64
void setScreenOn(void)
Put screen On.
#define setPalette(palette, paletteEntry, paletteSize)
Change a palette in CGRAM.
Definition: video.h:388
void setMode(u8 mode, u8 size)
Set the SNES hardware to operate in new display mode.