Add separated files for screens

This commit is contained in:
Lucas S. Vieira 2024-08-28 02:12:57 -03:00
parent 58c2876531
commit bea08e09cc
9 changed files with 559 additions and 393 deletions

17
include/screen.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef SCREEN_H
#define SCREEN_H
typedef enum {
SCREEN_DISCLAIMER,
SCREEN_LEVELSELECT,
SCREEN_LEVEL,
} ScreenIndex;
void scene_change(ScreenIndex scr);
void scene_load();
void scene_unload();
void scene_update();
void scene_draw();
#endif

View file

@ -0,0 +1,9 @@
#ifndef SCREENS_DISCLAIMER_H
#define SCREENS_DISCLAIMER_H
void screen_disclaimer_load();
void screen_disclaimer_unload();
void screen_disclaimer_update();
void screen_disclaimer_draw();
#endif

13
include/screens/level.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef SCREENS_LEVEL_H
#define SCREENS_LEVEL_H
#include <stdint.h>
void screen_level_load();
void screen_level_unload();
void screen_level_update();
void screen_level_draw();
void screen_level_setlevel(uint8_t menuchoice);
#endif

View file

@ -0,0 +1,9 @@
#ifndef SCREENS_LEVELSELECT_H
#define SCREENS_LEVELSELECT_H
void screen_levelselect_load();
void screen_levelselect_unload();
void screen_levelselect_update();
void screen_levelselect_draw();
#endif

View file

@ -19,414 +19,34 @@
#include "timer.h"
#include "camera.h"
#include "memalloc.h"
#include "screen.h"
int debug_mode = 0;
static int dx = 1, dy = 1;
static SVECTOR vertices[] = {
{ -64, -64, -64, 0 },
{ 64, -64, -64, 0 },
{ 64, -64, 64, 0 },
{ -64, -64, 64, 0 },
{ -64, 64, -64, 0 },
{ 64, 64, -64, 0 },
{ 64, 64, 64, 0 },
{ -64, 64, 64, 0 }
};
static short faces[] = {
2, 1, 3, 0, // top
1, 5, 0, 4, // front
5, 6, 4, 7, // bottomn
2, 6, 1, 5, // right
7, 6, 3, 2, // back
7, 3, 4, 0 // left
};
static SVECTOR rotation = { 0 };
static VECTOR pos = { 0, 0, 450 };
static VECTOR scale = { ONE >> 1, ONE >> 1, ONE >> 1 };
static MATRIX world = { 0 };
static Player player;
TileMap16 map16;
TileMap128 map128;
LevelData leveldata;
#define CHANNELS_PER_BGM 3
static uint32_t bgm_loop_sectors[] = {
4000,
4800,
3230,
11000,
};
static uint8_t music_channel = 0;
Camera camera;
static uint8_t current_scene = 0;
static uint8_t menu_choice = 0;
static uint8_t paused = 0;
// Disclaimer
static uint8_t *disclaimer_bg = NULL;
static uint16_t disclaimer_timer = 0;
void
engine_load_disclaimer()
{
current_scene = 0;
uint32_t length;
disclaimer_bg = file_read("\\MISC\\DISK.TIM;1", &length);
}
void
engine_load_player()
{
uint32_t filelength;
TIM_IMAGE tim;
uint8_t *timfile = file_read("\\SPRITES\\SONIC.TIM;1", &filelength);
if(timfile) {
load_texture(timfile, &tim);
free(timfile);
}
load_player(&player, "\\SPRITES\\SONIC.CHARA;1", &tim);
player.pos = (VECTOR){ 250 << 12, CENTERY << 12, 0 };
}
void
engine_load_level(uint8_t level)
{
set_clear_color(63, 0, 127);
paused = 0;
char basepath[255];
char filename0[255], filename1[255];
uint8_t round = level >> 1;
snprintf(basepath, 255, "\\LEVELS\\R%1u", round);
TIM_IMAGE tim;
uint32_t filelength;
snprintf(filename0, 255, "%s\\TILES.TIM;1", basepath);
printf("Loading %s...\n", filename0);
uint8_t *timfile = file_read(filename0, &filelength);
if(timfile) {
load_texture(timfile, &tim);
free(timfile);
} else {
// If not single "TILES.TIM" was found, then perharps try a
// "TILES0.TIM" and a "TILES1.TIM".
snprintf(filename0, 255, "%s\\TILES0.TIM;1", basepath);
printf("Loading %s...\n", filename0);
timfile = file_read(filename0, &filelength);
if(timfile) {
load_texture(timfile, &tim);
free(timfile);
}
snprintf(filename0, 255, "%s\\TILES1.TIM;1", basepath);
printf("Loading %s...\n", filename0);
timfile = file_read(filename0, &filelength);
if(timfile) {
load_texture(timfile, &tim);
free(timfile);
}
}
snprintf(filename0, 255, "%s\\MAP16.MAP;1", basepath);
snprintf(filename1, 255, "%s\\MAP16.COL;1", basepath);
printf("Loading %s and %s...\n", filename0, filename1);
load_map(&map16, filename0, filename1);
snprintf(filename0, 255, "%s\\MAP128.MAP;1", basepath);
printf("Loading %s...\n", filename0);
load_map(&map128, filename0, NULL);
snprintf(filename0, 255, "%s\\Z%1u.LVL;1", basepath, (level & 0x01) + 1);
printf("Loading %s...\n", filename0);
load_lvl(&leveldata, filename0);
level_debrief();
camera_init(&camera);
// Level 0 Zone 2 actually has background sound effects
/* if(level == 1) { */
/* SoundEffect sfx_rain = sound_load_vag("\\SFX\\RAIN.VAG;1"); */
/* sound_play_vag(sfx_rain, 1); */
/* } */
// Start playback after we don't need the CD anymore.
sound_stop_xa();
snprintf(filename0, 255, "\\BGM\\BGM%03u.XA;1", (level / CHANNELS_PER_BGM) + 1);
music_channel = level % CHANNELS_PER_BGM;
sound_play_xa(filename0, 0, music_channel, bgm_loop_sectors[level]);
}
void
engine_unload_level()
{
sound_stop_xa();
level_reset();
sound_reset_mem();
}
void
engine_load_menu()
{
set_clear_color(0, 0, 0);
render_loading_text();
current_scene = 1;
menu_choice = 0;
}
void
engine_init()
int
main(void)
{
// Engine initialization
setup_context();
sound_init();
CdInit();
pad_init();
timer_init();
fastalloc_init();
level_init();
set_clear_color(0, 0, 0);
render_loading_text();
set_clear_color(63, 0, 127);
engine_load_disclaimer();
}
void
engine_update()
{
sound_update();
pad_update();
#define MAX_LEVELS 4
if(current_scene == 0) { // Disclaimer
disclaimer_timer++;
if(disclaimer_timer > 1200
|| pad_pressed(PAD_START)
|| pad_pressed(PAD_CROSS)) {
free(disclaimer_bg);
disclaimer_bg = NULL;
disclaimer_timer = 0;
current_scene = 1;
set_clear_color(0, 0, 0);
render_loading_text();
engine_load_menu();
}
} else if(current_scene == 1) { // Menu
if(pad_pressed(PAD_DOWN))
menu_choice++;
else if(pad_pressed(PAD_UP)) {
if(menu_choice == 0) menu_choice = MAX_LEVELS - 1;
else menu_choice--;
}
menu_choice = (menu_choice % MAX_LEVELS);
if(pad_pressed(PAD_START) || pad_pressed(PAD_CROSS)) {
set_clear_color(0, 0, 0);
render_loading_text();
engine_load_player();
engine_load_level(menu_choice);
camera_set(&camera, player.pos.vx, player.pos.vy);
menu_choice = 0;
current_scene = 2;
}
} else if(current_scene == 2) { // Level
if(pad_pressed(PAD_START)) paused = !paused;
if(paused) {
if(pad_pressed(PAD_SELECT)) {
set_clear_color(0, 0, 0);
render_loading_text();
engine_unload_level();
engine_load_menu();
}
return;
}
if(pos.vx < -CENTERX || pos.vx > CENTERX) dx = -dx;
if(pos.vy < -CENTERY || pos.vy > CENTERY) dy = -dy;
pos.vx += dx;
pos.vy += dy;
rotation.vx += 6;
rotation.vy -= 8;
rotation.vz -= 12;
if((pad_pressing(PAD_L1) && pad_pressed(PAD_R1)) ||
(pad_pressed(PAD_L1) && pad_pressing(PAD_R1))) {
debug_mode = (debug_mode + 1) % 3;
}
if(pad_pressed(PAD_SELECT)) {
player.pos = (VECTOR){ 250 << 12, CENTERY << 12, 0 };
player.grnd = 0;
player.anim_dir = 1;
player.vel.vx = player.vel.vy = player.vel.vz = 0;
}
camera_update(&camera, &player);
player_update(&player);
}
}
// Text
static char buffer[255] = { 0 };
void
engine_draw()
{
if(current_scene == 0) {
TIM_IMAGE tim;
GetTimInfo((const uint32_t *)disclaimer_bg, &tim);
RECT r2 = *tim.prect;
r2.y += 240;
set_clear_color(0, 0, 0);
LoadImage(tim.prect, tim.paddr);
LoadImage(&r2, tim.paddr);
} else if(current_scene == 1) {
int16_t x;
const char *title = "*** engine-psx ***";
x = CENTERX - (strlen(title) * 4);
draw_text(x, 12, 0, title);
const char *subtitle = "https://luksamuk.codes/";
x = CENTERX - (strlen(subtitle) * 4);
draw_text(x, 24, 0, subtitle);
snprintf(buffer, 255, "%s %s", __DATE__, __TIME__);
x = SCREEN_XRES - (strlen(buffer) * 8) - 8;
draw_text(x, SCREEN_YRES - 24, 0, buffer);
snprintf(
buffer, 255,
"%c Round 0 Zone 1\n"
"%c Round 0 Zone 2\n"
"%c Round 1 Zone 1\n"
"%c Round 1 Zone 2\n",
(menu_choice == 0) ? '>' : ' ',
(menu_choice == 1) ? '>' : ' ',
(menu_choice == 2) ? '>' : ' ',
(menu_choice == 3) ? '>' : ' ');
draw_text(8, 60, 0, buffer);
} else if(current_scene == 2) {
if(abs((player.pos.vx - camera.pos.vx) >> 12) <= SCREEN_XRES
&& abs((player.pos.vy - camera.pos.vy) >> 12) <= SCREEN_YRES) {
VECTOR player_canvas_pos = {
player.pos.vx - camera.pos.vx + (CENTERX << 12),
player.pos.vy - camera.pos.vy + (CENTERY << 12),
0
};
player_draw(&player, &player_canvas_pos);
}
render_lvl(&leveldata, &map128, &map16, camera.pos.vx, camera.pos.vy);
// Gouraud-shaded cube
RotMatrix(&rotation, &world);
TransMatrix(&world, &pos);
ScaleMatrix(&world, &scale);
gte_SetRotMatrix(&world);
gte_SetTransMatrix(&world);
for(int i = 0; i < 24; i += 4) {
int nclip, otz;
POLY_G4 *poly = (POLY_G4 *) get_next_prim();
setPolyG4(poly);
setRGB0(poly, 96, 0, 0);
setRGB1(poly, 0, 96, 0);
setRGB2(poly, 0, 0, 96);
setRGB3(poly, 96, 96, 0);
nclip = RotAverageNclip4(
&vertices[faces[i]],
&vertices[faces[i + 1]],
&vertices[faces[i + 2]],
&vertices[faces[i + 3]],
(uint32_t *)&poly->x0,
(uint32_t *)&poly->x1,
(uint32_t *)&poly->x2,
(uint32_t *)&poly->x3,
&otz);
if((nclip > 0) && (otz > 0) && (otz < OT_LENGTH)) {
sort_prim(poly, otz);
increment_prim(sizeof(POLY_G4));
}
}
// Pause text
if(paused) {
const char *line1 = "Paused";
int16_t x = CENTERX - (strlen(line1) * 4);
draw_text(x, CENTERY - 12, 0, line1);
}
// Sound and video debug
//uint32_t elapsed_sectors;
//sound_xa_get_elapsed_sectors(&elapsed_sectors);
snprintf(buffer, 255,
"%4s %3d\n"
//"%08u"
,
GetVideoMode() == MODE_PAL ? "PAL" : "NTSC",
get_frame_rate()
//elapsed_sectors
);
draw_text(248, 12, 0, buffer);
// Player debug
if(debug_mode) {
snprintf(buffer, 255,
"GSP %08x\n"
"SPD %08x %08x\n"
"ANG %04x\n"
"POS %08x %08x\n"
"ACT %02u\n"
"REV %08x\n"
,
player.vel.vz,
player.vel.vx, player.vel.vy,
player.angle,
player.pos.vx, player.pos.vy,
player.action,
player.spinrev
);
draw_text(8, 12, 0, buffer);
}
}
}
int
main(void)
{
engine_init();
// Set first scene
scene_change(SCREEN_DISCLAIMER);
while(1) {
engine_update();
engine_draw();
// Update systems
sound_update();
pad_update();
scene_update();
timer_update();
// Draw scene
scene_draw();
swap_buffers();
}

71
src/screen.c Normal file
View file

@ -0,0 +1,71 @@
#include "screen.h"
#include <stdint.h>
#include <stdio.h>
#include "render.h"
#include "screens/disclaimer.h"
#include "screens/levelselect.h"
#include "screens/level.h"
int8_t current_scene = -1;
void
scene_change(ScreenIndex scr)
{
if((int8_t)scr != current_scene) {
printf("Change scene: %d -> %d\n", current_scene, scr);
set_clear_color(0, 0, 0);
render_loading_text();
if(current_scene >= 0)
scene_unload();
current_scene = scr;
scene_load();
}
}
void
scene_load()
{
switch(current_scene) {
case SCREEN_DISCLAIMER: screen_disclaimer_load(); break;
case SCREEN_LEVELSELECT: screen_levelselect_load(); break;
case SCREEN_LEVEL: screen_level_load(); break;
default: break; // Unknown scene???
}
}
void
scene_unload()
{
switch(current_scene) {
case SCREEN_DISCLAIMER: screen_disclaimer_unload(); break;
case SCREEN_LEVELSELECT: screen_levelselect_unload(); break;
case SCREEN_LEVEL: screen_level_unload(); break;
default: break; // Unknown scene???
}
}
void
scene_update()
{
switch(current_scene) {
case SCREEN_DISCLAIMER: screen_disclaimer_update(); break;
case SCREEN_LEVELSELECT: screen_levelselect_update(); break;
case SCREEN_LEVEL: screen_level_update(); break;
default: break; // Unknown scene???
}
}
void
scene_draw()
{
switch(current_scene) {
case SCREEN_DISCLAIMER: screen_disclaimer_draw(); break;
case SCREEN_LEVELSELECT: screen_levelselect_draw(); break;
case SCREEN_LEVEL: screen_level_draw(); break;
default: break; // Unknown scene???
}
}

43
src/screen_disclaimer.c Normal file
View file

@ -0,0 +1,43 @@
#include "screens/disclaimer.h"
#include <stdint.h>
#include <stdlib.h>
#include "util.h"
#include "input.h"
#include "screen.h"
#include "render.h"
static uint8_t *disclaimer_bg = NULL;
static uint16_t disclaimer_timer = 0;
void screen_disclaimer_load()
{
uint32_t length;
disclaimer_bg = file_read("\\MISC\\DISK.TIM;1", &length);
}
void screen_disclaimer_unload()
{
free(disclaimer_bg);
disclaimer_bg = NULL;
disclaimer_timer = 0;
}
void screen_disclaimer_update()
{
disclaimer_timer++;
if((disclaimer_timer > 1200) || pad_pressed(PAD_START) || pad_pressed(PAD_CROSS)) {
scene_change(SCREEN_LEVELSELECT);
}
}
void screen_disclaimer_draw()
{
TIM_IMAGE tim;
GetTimInfo((const uint32_t *)disclaimer_bg, &tim);
RECT r2 = *tim.prect;
r2.y += 240;
set_clear_color(0, 0, 0);
LoadImage(tim.prect, tim.paddr);
LoadImage(&r2, tim.paddr);
}

316
src/screen_level.c Normal file
View file

@ -0,0 +1,316 @@
#include "screens/level.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inline_c.h>
#include "util.h"
#include "player.h"
#include "camera.h"
#include "render.h"
#include "sound.h"
#include "input.h"
#include "screen.h"
#include "level.h"
#include "timer.h"
extern int debug_mode;
static uint8_t level = 0;
static uint8_t paused = 0;
static uint8_t music_channel = 0;
static Player player;
TileMap16 map16;
TileMap128 map128;
LevelData leveldata;
Camera camera;
#define CHANNELS_PER_BGM 3
static uint32_t bgm_loop_sectors[] = {
4000,
4800,
3230,
11000,
};
/* Related to rotating cube on background */
static int dx = 1, dy = 1;
static SVECTOR vertices[] = {
{ -64, -64, -64, 0 },
{ 64, -64, -64, 0 },
{ 64, -64, 64, 0 },
{ -64, -64, 64, 0 },
{ -64, 64, -64, 0 },
{ 64, 64, -64, 0 },
{ 64, 64, 64, 0 },
{ -64, 64, 64, 0 }
};
static short faces[] = {
2, 1, 3, 0, // top
1, 5, 0, 4, // front
5, 6, 4, 7, // bottomn
2, 6, 1, 5, // right
7, 6, 3, 2, // back
7, 3, 4, 0 // left
};
static SVECTOR rotation = { 0 };
static VECTOR pos = { 0, 0, 450 };
static VECTOR scale = { ONE >> 1, ONE >> 1, ONE >> 1 };
static MATRIX world = { 0 };
/* -------------------------------------- */
// Forward function declarations
static void level_load_player();
static void level_load_level();
void screen_level_load()
{
level_load_player();
level_load_level();
camera_set(&camera, player.pos.vx, player.pos.vy);
}
void screen_level_unload()
{
sound_stop_xa();
level_reset();
sound_reset_mem();
}
void screen_level_update()
{
if(pad_pressed(PAD_START)) paused = !paused;
if(paused) {
if(pad_pressed(PAD_SELECT)) {
scene_change(SCREEN_LEVELSELECT);
}
return;
}
/* Rotating cube */
if(pos.vx < -CENTERX || pos.vx > CENTERX) dx = -dx;
if(pos.vy < -CENTERY || pos.vy > CENTERY) dy = -dy;
pos.vx += dx;
pos.vy += dy;
rotation.vx += 6;
rotation.vy -= 8;
rotation.vz -= 12;
/* --------- */
if((pad_pressing(PAD_L1) && pad_pressed(PAD_R1)) ||
(pad_pressed(PAD_L1) && pad_pressing(PAD_R1))) {
debug_mode = (debug_mode + 1) % 3;
}
if(pad_pressed(PAD_SELECT)) {
player.pos = (VECTOR){ 250 << 12, CENTERY << 12, 0 };
player.grnd = 0;
player.anim_dir = 1;
player.vel.vx = player.vel.vy = player.vel.vz = 0;
}
camera_update(&camera, &player);
player_update(&player);
}
void screen_level_draw()
{
char buffer[255] = { 0 };
if(abs((player.pos.vx - camera.pos.vx) >> 12) <= SCREEN_XRES
&& abs((player.pos.vy - camera.pos.vy) >> 12) <= SCREEN_YRES) {
VECTOR player_canvas_pos = {
player.pos.vx - camera.pos.vx + (CENTERX << 12),
player.pos.vy - camera.pos.vy + (CENTERY << 12),
0
};
player_draw(&player, &player_canvas_pos);
}
render_lvl(&leveldata, &map128, &map16, camera.pos.vx, camera.pos.vy);
// Gouraud-shaded cube
RotMatrix(&rotation, &world);
TransMatrix(&world, &pos);
ScaleMatrix(&world, &scale);
gte_SetRotMatrix(&world);
gte_SetTransMatrix(&world);
for(int i = 0; i < 24; i += 4) {
int nclip, otz;
POLY_G4 *poly = (POLY_G4 *) get_next_prim();
setPolyG4(poly);
setRGB0(poly, 96, 0, 0);
setRGB1(poly, 0, 96, 0);
setRGB2(poly, 0, 0, 96);
setRGB3(poly, 96, 96, 0);
nclip = RotAverageNclip4(
&vertices[faces[i]],
&vertices[faces[i + 1]],
&vertices[faces[i + 2]],
&vertices[faces[i + 3]],
(uint32_t *)&poly->x0,
(uint32_t *)&poly->x1,
(uint32_t *)&poly->x2,
(uint32_t *)&poly->x3,
&otz);
if((nclip > 0) && (otz > 0) && (otz < OT_LENGTH)) {
sort_prim(poly, otz);
increment_prim(sizeof(POLY_G4));
}
}
// Pause text
if(paused) {
const char *line1 = "Paused";
int16_t x = CENTERX - (strlen(line1) * 4);
draw_text(x, CENTERY - 12, 0, line1);
}
// Sound and video debug
//uint32_t elapsed_sectors;
//sound_xa_get_elapsed_sectors(&elapsed_sectors);
snprintf(buffer, 255,
"%4s %3d\n"
//"%08u"
,
GetVideoMode() == MODE_PAL ? "PAL" : "NTSC",
get_frame_rate()
//elapsed_sectors
);
draw_text(248, 12, 0, buffer);
// Player debug
if(debug_mode) {
snprintf(buffer, 255,
"GSP %08x\n"
"SPD %08x %08x\n"
"ANG %04x\n"
"POS %08x %08x\n"
"ACT %02u\n"
"REV %08x\n"
,
player.vel.vz,
player.vel.vx, player.vel.vy,
player.angle,
player.pos.vx, player.pos.vy,
player.action,
player.spinrev
);
draw_text(8, 12, 0, buffer);
}
}
/* ============================== */
void
screen_level_setlevel(uint8_t menuchoice)
{
level = menuchoice;
}
/* ============================== */
static void
level_load_player()
{
uint32_t filelength;
TIM_IMAGE tim;
uint8_t *timfile = file_read("\\SPRITES\\SONIC.TIM;1", &filelength);
if(timfile) {
load_texture(timfile, &tim);
free(timfile);
}
load_player(&player, "\\SPRITES\\SONIC.CHARA;1", &tim);
player.pos = (VECTOR){ 250 << 12, CENTERY << 12, 0 };
}
static void
level_load_level()
{
set_clear_color(63, 0, 127);
paused = 0;
char basepath[255];
char filename0[255], filename1[255];
uint8_t round = level >> 1;
snprintf(basepath, 255, "\\LEVELS\\R%1u", round);
TIM_IMAGE tim;
uint32_t filelength;
snprintf(filename0, 255, "%s\\TILES.TIM;1", basepath);
printf("Loading %s...\n", filename0);
uint8_t *timfile = file_read(filename0, &filelength);
if(timfile) {
load_texture(timfile, &tim);
free(timfile);
} else {
// If not single "TILES.TIM" was found, then perharps try a
// "TILES0.TIM" and a "TILES1.TIM".
snprintf(filename0, 255, "%s\\TILES0.TIM;1", basepath);
printf("Loading %s...\n", filename0);
timfile = file_read(filename0, &filelength);
if(timfile) {
load_texture(timfile, &tim);
free(timfile);
}
snprintf(filename0, 255, "%s\\TILES1.TIM;1", basepath);
printf("Loading %s...\n", filename0);
timfile = file_read(filename0, &filelength);
if(timfile) {
load_texture(timfile, &tim);
free(timfile);
}
}
snprintf(filename0, 255, "%s\\MAP16.MAP;1", basepath);
snprintf(filename1, 255, "%s\\MAP16.COL;1", basepath);
printf("Loading %s and %s...\n", filename0, filename1);
load_map(&map16, filename0, filename1);
snprintf(filename0, 255, "%s\\MAP128.MAP;1", basepath);
printf("Loading %s...\n", filename0);
load_map(&map128, filename0, NULL);
snprintf(filename0, 255, "%s\\Z%1u.LVL;1", basepath, (level & 0x01) + 1);
printf("Loading %s...\n", filename0);
load_lvl(&leveldata, filename0);
level_debrief();
camera_init(&camera);
// Level 0 Zone 2 actually has background sound effects
/* if(level == 1) { */
/* SoundEffect sfx_rain = sound_load_vag("\\SFX\\RAIN.VAG;1"); */
/* sound_play_vag(sfx_rain, 1); */
/* } */
// Start playback after we don't need the CD anymore.
sound_stop_xa();
snprintf(filename0, 255, "\\BGM\\BGM%03u.XA;1", (level / CHANNELS_PER_BGM) + 1);
music_channel = level % CHANNELS_PER_BGM;
sound_play_xa(filename0, 0, music_channel, bgm_loop_sectors[level]);
}

68
src/screen_levelselect.c Normal file
View file

@ -0,0 +1,68 @@
#include "screens/levelselect.h"
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "input.h"
#include "screen.h"
#include "render.h"
#include "screens/level.h"
#define MAX_LEVELS 4
static uint8_t menu_choice = 0;
void screen_levelselect_load()
{
menu_choice = 0;
}
void screen_levelselect_unload() {}
void screen_levelselect_update()
{
if(pad_pressed(PAD_DOWN))
menu_choice++;
else if(pad_pressed(PAD_UP)) {
if(menu_choice == 0) menu_choice = MAX_LEVELS - 1;
else menu_choice--;
}
menu_choice = (menu_choice % MAX_LEVELS);
if(pad_pressed(PAD_START) || pad_pressed(PAD_CROSS)) {
screen_level_setlevel(menu_choice);
scene_change(SCREEN_LEVEL);
}
}
void screen_levelselect_draw()
{
char buffer[255] = { 0 };
int16_t x;
const char *title = "*** engine-psx ***";
x = CENTERX - (strlen(title) * 4);
draw_text(x, 12, 0, title);
const char *subtitle = "https://luksamuk.codes/";
x = CENTERX - (strlen(subtitle) * 4);
draw_text(x, 24, 0, subtitle);
snprintf(buffer, 255, "%s %s", __DATE__, __TIME__);
x = SCREEN_XRES - (strlen(buffer) * 8) - 8;
draw_text(x, SCREEN_YRES - 24, 0, buffer);
snprintf(
buffer, 255,
"%c Round 0 Zone 1\n"
"%c Round 0 Zone 2\n"
"%c Round 1 Zone 1\n"
"%c Round 1 Zone 2\n",
(menu_choice == 0) ? '>' : ' ',
(menu_choice == 1) ? '>' : ' ',
(menu_choice == 2) ? '>' : ' ',
(menu_choice == 3) ? '>' : ' ');
draw_text(8, 60, 0, buffer);
}