Compare commits

...

7 Commits

6 changed files with 246 additions and 164 deletions

22
include/controls.h Normal file
View File

@ -0,0 +1,22 @@
/* controls.h
* manage input and actuate controls
*
* receive and manage user input & have them actuate in-game things
*
* For license details see COPYING.
*/
#ifndef CONTROLS_H
#define CONTROLS_H
/* copying shadow oam to true oam is left to the user to allow for many
* operations on different sprites and then copy all of them at once */
// move player around the screen
// sprite must have 2-frames, and should be toggled via xors of tile_toggle
void player_update (struct spriteReg *sprite, int base_tile, int tile_toggle);
// scroll screen when player nears edges
void player_scroll (struct spriteReg *sprite, struct bgReg *background);
#endif /* CONTROLS_H */

65
include/globals.h Normal file
View File

@ -0,0 +1,65 @@
/* globals.h
* all the good global stuff
*
* defines and global variables and more for use wherever needed
*
* For license details see COPYING.
*/
#ifndef GLOBALS_H
#define GLOBALS_H
/* Defines */
// pixel widths for schnoz (since he doesn't take up the full 16x32 frame)
#define SCHNOZ_L 0
#define SCHNOZ_R 15
#define SCHNOZ_T 9
#define SCHNOZ_B 31
#define SCREEN_CENTER_X (SCREEN_WIDTH/2)-((SCHNOZ_R-SCHNOZ_L)/2)
#define SCREEN_CENTER_Y (SCREEN_HEIGHT/2)-((SCHNOZ_B-SCHNOZ_T)/2)
// schnoz base tile id and animation toggle value
#define SCHNOZ_BSE 0
#define SCHNOZ_TGL 8
/* Inline Functions */
/* Typedefs & composite types */
/* Regular-type sprite
* stores pointer to OBJect in shadow oam, Tile ID, PalBank, current X
* coordinates, current Y coordinates, and the last Delta applied to X and Y
* (deltas can be 0 if nothing was applied last time the sprite was updated)
*/
struct spriteReg {
OBJ_ATTR *obj;
u32 tid, pb;
int x, y, dx, dy;
};
/* regular-type background
* charblock number, screenblock number, current screen
* display coordinates, size (in tiles), and bg_reg_00x00 register
*/
struct bgReg {
int cb, sb;
s16 x, y;
int sx, sy;
};
// background tile types (extensible)
enum bgTileTypes {
EMPTY,
SOLID,
DAMAGING
};
/* Globals */
extern OBJ_ATTR obj_buffer[128];
extern OBJ_AFFINE *obj_aff_buffer;
extern uint frame_counter;
extern int obj_counter;
extern const GBFS_FILE *gbfs_start;
#endif /* GLOBALS_H */

View File

@ -1,7 +1,7 @@
/* load.h
* Load things into memory
* load things into memory
*
* Will eventually be used to quickly load levels and sprites from GBFS into
* will eventually be used to quickly load levels and sprites from gbfs into
* video memory
*
* For license details see COPYING.
@ -10,31 +10,17 @@
#ifndef LOAD_H
#define LOAD_H
void load_region (
const GBFS_FILE *gbfs_start,
const char filename[],
int filename_len,
COLOR *palbank,
TILE *charblock,
SCR_ENTRY *screenblock
);
void load_region (const char filename[],
int filename_len,
COLOR *palbank,
TILE *charblock,
SCR_ENTRY *screenblock);
// varargs: num_frames of TILE* pointing to location in tile_mem
// Assumes shared palette for all frames
// Assumes filename convention of "<filename>_f<frame_number>.img.bin"
void load_sprite (
const GBFS_FILE *gbfs_start,
const char filename[],
int filename_len,
int num_frames,
...
);
// assumes shared palette for all frames
// assumes filename convention of "<filename>_f<frame_number>.img.bin"
void load_sprite (const char filename[], int filename_len, int num_frames, ...);
void load_hub (
const GBFS_FILE *gbfs_start,
COLOR *palbank,
TILE *charblock,
SCR_ENTRY *screenblock
);
void load_hub (COLOR *palbank, TILE *charblock, SCR_ENTRY *screenblock);
#endif /* LOAD_H */

70
src/controls.c Normal file
View File

@ -0,0 +1,70 @@
/* controls.c
* manage input and actuate controls
*
* receive and manage user input & have them actuate in-game things
*
* For license details see COPYING.
*/
#include <tonc.h>
#include "gbfs.h" // needs to be included here or else globals.h freaks
#include "globals.h"
#include "controls.h"
void player_update (struct spriteReg *sprite, int base_tile, int tile_toggle)
{
/* update deltas then set ->x and ->y later so that way additional deltas
* could be applied in the future (knockback, etc.) then added all at once
*/
sprite->dx = key_tri_horz();
sprite->dy = key_tri_vert();
// compiler (should) automatically expand n % 2^i to n & (2^i - 1)
if ((key_tri_horz() || key_tri_vert()) && !(frame_counter % 16)) {
sprite->tid ^= tile_toggle;
} else if (!(key_tri_horz() || key_tri_vert())) {
sprite->tid = base_tile;
}
if (key_tri_horz() > 0) {
sprite->obj->attr1 |= ATTR1_HFLIP;
} else if (key_tri_horz() < 0) {
sprite->obj->attr1 &= ~ATTR1_HFLIP;
}
/* may remove or modify later if i decide that i want the player to be able
* to go off screen for some reason */
sprite->x = clamp(sprite->x+sprite->dx, SCHNOZ_L, SCREEN_WIDTH-SCHNOZ_R);
sprite->y = clamp(sprite->y+sprite->dy, -SCHNOZ_T, SCREEN_HEIGHT-SCHNOZ_B);
obj_set_pos(sprite->obj, sprite->x, sprite->y);
sprite->obj->attr2 = ATTR2_BUILD(sprite->tid, sprite->pb, 0);
return;
}
void player_scroll (struct spriteReg *sprite, struct bgReg *background)
{
if (background->x == 0 && sprite->x < SCREEN_CENTER_X) {
sprite->x = clamp(sprite->x, SCHNOZ_L, SCREEN_CENTER_X);
} else if (background->x == 512-SCREEN_WIDTH && sprite->x > SCREEN_CENTER_X) {
sprite->x = clamp(sprite->x, SCREEN_CENTER_X, SCREEN_WIDTH-SCHNOZ_R);
} else {
sprite->x = SCREEN_CENTER_X;
background->x = clamp(background->x + sprite->dx, 0, 512-SCREEN_WIDTH+1);
}
/* when physics are implemented, write in a way so the background isn't
* constantly scrolling when jumping or falling
*/
if (background->y == 0 && sprite->y < SCREEN_CENTER_Y) {
sprite->y = clamp(sprite->y, -SCHNOZ_T, SCREEN_CENTER_Y);
} else if (background->y == 256-SCREEN_HEIGHT && sprite->y > SCREEN_CENTER_Y) {
sprite->y = clamp(sprite->y, SCREEN_CENTER_Y, SCREEN_HEIGHT-SCHNOZ_B);
} else {
sprite->y = SCREEN_CENTER_Y;
background->y = clamp(background->y + sprite->dy, 0, 256-SCREEN_HEIGHT+1);
}
obj_set_pos(sprite->obj, sprite->x, sprite->y);
return;
}

View File

@ -1,112 +1,84 @@
/* load.c
* Load things into memory
* load things into memory
*
* Used to quickly load levels and sprites from GBFS into video memory and
* used to quickly load levels and sprites from gbfs into video memory and
* for running other memory loads as necessary
*
* For license details see COPYING.
*/
#include <tonc.h>
#include "gbfs.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "gbfs.h"
#include "globals.h"
#include "load.h"
void load_region (
const GBFS_FILE *gbfs_start,
const char filename[],
int filename_len,
COLOR *palbank,
TILE *charblock,
SCR_ENTRY *screenblock
)
// lengths of gbfs filename extensions
#define FILENAME_EXT_REG 8
#define FILENAME_EXT_FRAMES 12
void load_region (const char filename[],
int filename_len,
COLOR *palbank,
TILE *charblock,
SCR_ENTRY *screenblock)
{
// filename + .typ.bin (filename_len + 8 chars)
// It is expected that filename_len already includes the null terminator
char pal_name[filename_len + 8];
char img_name[filename_len + 8];
char map_name[filename_len + 8];
snprintf(pal_name, filename_len + 8, "%s.pal.bin", filename);
snprintf(img_name, filename_len + 8, "%s.img.bin", filename);
snprintf(map_name, filename_len + 8, "%s.map.bin", filename);
// LZ77 decompress files to proper vram location
LZ77UnCompVram(
(u32*) gbfs_get_obj(gbfs_start, pal_name, NULL),
palbank
);
LZ77UnCompVram(
(u32*) gbfs_get_obj(gbfs_start, img_name, NULL),
charblock
);
LZ77UnCompVram(
(u32*) gbfs_get_obj(gbfs_start, map_name, NULL),
screenblock
);
// it is expected that filename_len already includes the null terminator
char pal_name[filename_len + FILENAME_EXT_REG];
char img_name[filename_len + FILENAME_EXT_REG];
char map_name[filename_len + FILENAME_EXT_REG];
snprintf(pal_name, filename_len + FILENAME_EXT_REG, "%s.pal.bin", filename);
snprintf(img_name, filename_len + FILENAME_EXT_REG, "%s.img.bin", filename);
snprintf(map_name, filename_len + FILENAME_EXT_REG, "%s.map.bin", filename);
// lz77 decompress files to proper vram location
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, pal_name, NULL), palbank);
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, img_name, NULL), charblock);
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, map_name, NULL), screenblock);
return;
}
void load_sprite (
const GBFS_FILE *gbfs_start,
const char filename[],
int filename_len,
int num_frames,
...
)
void load_sprite (const char filename[], int filename_len, int num_frames, ...)
{
va_list frame_location;
va_start(frame_location, num_frames);
char pal_name[filename_len + 8];
snprintf(pal_name, filename_len + 8, "%s.pal.bin", filename);
char pal_name[filename_len + FILENAME_EXT_REG];
snprintf(pal_name, filename_len + FILENAME_EXT_REG, "%s.pal.bin", filename);
// filename + _##.typ.bin (filename_len + 12 chars)
// It is expected that filename_len already includes the null terminator
char frame_names[num_frames][filename_len + 12];
for (int i = 0; i < num_frames; i++) {
snprintf(
frame_names[i],
filename_len + 12,
"%s_f%i.img.bin",
filename, i+1
);
// it is expected that filename_len already includes the null terminator
char frame_names[num_frames][filename_len + FILENAME_EXT_FRAMES];
for (int i = 0; i < num_frames; ++i) {
snprintf(frame_names[i],
filename_len + FILENAME_EXT_FRAMES,
"%s_f%i.img.bin",
filename, i+1);
}
LZ77UnCompVram(
(u32*) gbfs_get_obj(gbfs_start, pal_name, NULL),
pal_obj_mem
);
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, pal_name, NULL), pal_obj_mem);
TILE *location;
for (int i = 0; i < num_frames; i++) {
for (int i = 0; i < num_frames; ++i) {
location = va_arg(frame_location, TILE*);
LZ77UnCompVram(
(u32*) gbfs_get_obj(gbfs_start, frame_names[i], NULL),
location
);
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, frame_names[i], NULL),
location);
}
va_end(frame_location);
return;
}
void load_hub (
const GBFS_FILE *gbfs_start,
COLOR *palbank,
TILE *charblock,
SCR_ENTRY *screenblock
)
void load_hub (COLOR *palbank, TILE *charblock, SCR_ENTRY *screenblock)
{
load_region(
gbfs_start,
"hub",
4, // Length of "hub" including null char
palbank,
charblock,
screenblock
);
load_region("hub",
4, // length of "hub" including null char
palbank,
charblock,
screenblock);
return;
}

View File

@ -1,99 +1,66 @@
/* main.c
* Initialization and game loop
* initialization and game loop
*
* For license details see COPYING.
*/
#include <tonc.h>
#include "gbfs.h"
#include "load.h" // Load from rom/gbfs into memory
#include "globals.h" // data types, miscellaneous structures
#include "load.h" // load from rom/gbfs into memory
#include "controls.h" // manage input & controls
OBJ_ATTR obj_buffer[128];
OBJ_AFFINE *obj_aff_buffer = (OBJ_AFFINE*)obj_buffer;
uint frame_counter = 0;
int obj_counter = 0;
typedef struct {
OBJ_ATTR *obj;
u32 tid, pb;
int x, y, x_prev, y_prev;
} spriteReg;
// make sure gbfs_start is a global even though it can't be initialized here
const GBFS_FILE *gbfs_start;
int main (void)
{
// Find the beginning of the GBFS 'sector'
const GBFS_FILE *gbfs_start = find_first_gbfs_file(find_first_gbfs_file);
// find the beginning of the gbfs 'sector'
gbfs_start = find_first_gbfs_file(find_first_gbfs_file);
// Load hub into palbank 0, charblock 0, and screenblock 30
load_hub(gbfs_start, &pal_bg_mem[0], &tile_mem[0][0], &se_mem[30][0]);
// load hub into palbank 0, charblock 0, and screenblock 30
load_hub(&pal_bg_mem[0], &tile_mem[0][0], &se_mem[30][0]);
// Load schnoz into tile_mem[4][0] and tile_mem[4][8];
load_sprite(gbfs_start, "schnoz", 7, 2, &tile_mem[4][0], &tile_mem[4][8]);
// load schnoz into tile_mem[4][0] and tile_mem[4][8]
// length of "schnoz" is 7, and 2 frames pointed to by remaining arguments
load_sprite("schnoz", 7, 2, &tile_mem[4][0], &tile_mem[4][8]);
oam_init(obj_buffer, 128);
spriteReg player = {&obj_buffer[0], 0, 0, 5, 80};
obj_set_attr(
player.obj,
ATTR0_TALL,
ATTR1_SIZE_32 | ATTR1_HFLIP,
ATTR2_PALBANK(player.pb) | player.tid
);
struct spriteReg player = {&obj_buffer[0], 0, 0, 5, 80, 0, 0};
++obj_counter;
obj_set_attr(player.obj,
ATTR0_TALL,
ATTR1_SIZE_32 | ATTR1_HFLIP,
ATTR2_PALBANK(player.pb) | player.tid);
obj_set_pos(player.obj, player.x, player.y);
oam_copy(oam_mem, obj_buffer, 1);
BG_POINT bg1_pos = {0, 96};
struct bgReg bg1 = {0, 30, 0, 96, 64, 32};
// Use background 1 to leave background 0 free for sprites to move behind
REG_BG1CNT = BG_CBB(0) | BG_SBB(30) | BG_4BPP | BG_REG_64x32;
// use background 1 to leave background 0 free for sprites to move behind
REG_BG1CNT = BG_CBB(bg1.cb) | BG_SBB(bg1.sb) | BG_4BPP | BG_REG_64x32;
REG_DISPCNT = DCNT_BG1 | DCNT_OBJ | DCNT_OBJ_1D;
u32 fcounter = 0;
while (1) {
vid_vsync();
++frame_counter;
key_poll();
++fcounter;
player.x_prev = player.x;
player.y_prev = player.y;
player.x += key_tri_horz();
player.y += key_tri_vert();
player_update(&player, SCHNOZ_BSE, SCHNOZ_TGL);
player_scroll(&player, &bg1);
if ((key_tri_horz() || key_tri_vert()) && !(fcounter % 16)) {
player.tid ^= 8;
} else if (!(key_tri_horz() || key_tri_vert())) {
player.tid = 0;
}
if (key_tri_horz() > 0) {
player.obj->attr1 |= ATTR1_HFLIP;
} else if (key_tri_horz() < 0) {
player.obj->attr1 &= ~ATTR1_HFLIP;
}
if ((player.x >= 3*(SCREEN_WIDTH/4)-15) && (bg1_pos.x < 512-SCREEN_WIDTH)) {
++bg1_pos.x;
player.x = clamp(player.x, 0, 3*(SCREEN_WIDTH/4)-15);
} else if ((player.x <= (SCREEN_WIDTH/4)) && (bg1_pos.x > 0)) {
--bg1_pos.x;
player.x = clamp(player.x, (SCREEN_WIDTH/4)+1, SCREEN_WIDTH);
}
if ((player.y >= 3*(SCREEN_HEIGHT/4)-31) && (bg1_pos.y < 256-SCREEN_HEIGHT)) {
++bg1_pos.y;
player.y = clamp(player.y, -9, 3*(SCREEN_HEIGHT/4)-31);
} else if ((player.y <= (SCREEN_HEIGHT/4)) && (bg1_pos.y > 0)) {
--bg1_pos.y;
player.y = clamp(player.y, (SCREEN_HEIGHT/4)+1, SCREEN_HEIGHT-9);
}
player.x = clamp(player.x, 0, SCREEN_WIDTH-15);
player.y = clamp(player.y, -9, SCREEN_HEIGHT-31);
obj_set_pos(player.obj, player.x, player.y);
player.obj->attr2 = ATTR2_BUILD(player.tid, player.pb, 0);
oam_copy(oam_mem, obj_buffer, 1);
REG_BG1HOFS = bg1_pos.x;
REG_BG1VOFS = bg1_pos.y;
oam_copy(oam_mem, obj_buffer, obj_counter);
REG_BG1HOFS = bg1.x;
REG_BG1VOFS = bg1.y;
}
return 0; // in case?
}