233 lines
4.3 KiB
C
233 lines
4.3 KiB
C
#ifndef EZGB_H
|
|
#define EZGB_H
|
|
/**
|
|
EZgb: a set of helpers for easy GB indie development in pure C
|
|
for Z88DK (in text mode)
|
|
|
|
Created by Luxferre in 2026, released into public domain
|
|
*/
|
|
|
|
#include <gb/gb.h>
|
|
#include <conio.h>
|
|
#include <curses.h>
|
|
|
|
#define u8 unsigned char
|
|
#define u16 unsigned short
|
|
#define s8 signed char
|
|
#define s16 signed short
|
|
|
|
/* Generic constants */
|
|
|
|
#define SCREEN_WIDTH 20
|
|
#define SCREEN_HEIGHT 18
|
|
#define SCREEN_CENTER_X (SCREEN_WIDTH >> 1)
|
|
#define SCREEN_CENTER_Y (SCREEN_HEIGHT >> 1)
|
|
#define NL "\n"
|
|
|
|
#define EZJOY_UP 1
|
|
#define EZJOY_DN 2
|
|
#define EZJOY_LT 3
|
|
#define EZJOY_RT 4
|
|
#define EZJOY_A 5
|
|
#define EZJOY_B 6
|
|
#define EZJOY_SL 7
|
|
#define EZJOY_ST 8
|
|
|
|
/* RNG stuff */
|
|
static u16 _ez_entropy = 0;
|
|
|
|
u16 ezrand() {
|
|
_ez_entropy = 1 + ((_ez_entropy >> 15) | (_ez_entropy << 1));
|
|
return ((u16) rand()) ^ _ez_entropy;
|
|
}
|
|
|
|
u8 joy_input_wait() {
|
|
u8 last_joy = 0, joy, pressed;
|
|
/* wait until the previous key is released */
|
|
while(joypad());
|
|
/* wait for a new press */
|
|
while(1) {
|
|
++_ez_entropy;
|
|
joy = joypad();
|
|
pressed = joy & ~last_joy;
|
|
if(pressed & J_UP) return EZJOY_UP;
|
|
if(pressed & J_DOWN) return EZJOY_DN;
|
|
if(pressed & J_LEFT) return EZJOY_LT;
|
|
if(pressed & J_RIGHT) return EZJOY_RT;
|
|
if(pressed & J_A) return EZJOY_A;
|
|
if(pressed & J_B) return EZJOY_B;
|
|
if(pressed & J_SELECT) return EZJOY_SL;
|
|
if(pressed & J_START) return EZJOY_ST;
|
|
last_joy = joy;
|
|
wait_vbl_done();
|
|
}
|
|
}
|
|
|
|
/* wait until Start is pressed */
|
|
void wait_for_start() {
|
|
u8 joy;
|
|
while(1) {
|
|
++_ez_entropy;
|
|
joy = joypad();
|
|
if(joy & J_START) break;
|
|
wait_vbl_done();
|
|
}
|
|
}
|
|
|
|
/* randomize until Start is pressed */
|
|
void wait_for_start_rand() {
|
|
u8 joy;
|
|
#ifdef _randomize
|
|
_randomize();
|
|
#endif
|
|
_ez_entropy = rand();
|
|
while(1) {
|
|
++_ez_entropy;
|
|
joy = joypad();
|
|
if(joy & J_START) break;
|
|
wait_vbl_done();
|
|
}
|
|
srand(_ez_entropy);
|
|
}
|
|
|
|
/* Sound methods */
|
|
|
|
void init_sound() {
|
|
NR52_REG = 0x80;
|
|
NR50_REG = 0x77;
|
|
NR51_REG = 0xFF;
|
|
}
|
|
|
|
u16 get_timer_by_freq(u16 freq) {
|
|
return (u16) (2048 - (131072 / freq));
|
|
}
|
|
|
|
void play_pulse(u8 channel, u16 freq, u16 duration) {
|
|
u16 tm = get_timer_by_freq(freq);
|
|
|
|
if(channel == 0) {
|
|
NR10_REG = 0x00;
|
|
NR11_REG = 0x80 | duration;
|
|
NR12_REG = 0xF3;
|
|
NR13_REG = tm & 255;
|
|
NR14_REG = 0xC0 | (tm >> 8);
|
|
} else {
|
|
NR21_REG = 0x80 | duration;
|
|
NR22_REG = 0xF3;
|
|
NR23_REG = tm & 255;
|
|
NR24_REG = 0xC0 | (tm >> 8);
|
|
}
|
|
}
|
|
|
|
void play_jingle(u16 n1f1,
|
|
u16 n1f2,
|
|
u16 n2f1,
|
|
u16 n2f2,
|
|
u16 n3f1,
|
|
u16 n3f2) {
|
|
u16 i, dl = 2600;
|
|
play_pulse(0, n1f1, 1);
|
|
play_pulse(1, n1f2, 1);
|
|
for(i=0;i<dl;++i);
|
|
play_pulse(0, n2f1, 1);
|
|
play_pulse(1, n2f2, 1);
|
|
for(i=0;i<dl;++i);
|
|
play_pulse(0, n3f1, 1);
|
|
play_pulse(1, n3f2, 1);
|
|
}
|
|
|
|
/* Generic helper methods */
|
|
|
|
/* Array shuffle method */
|
|
void shuffle(s8 *array, u16 n) {
|
|
u16 i, j, t;
|
|
if(n > 1) {
|
|
for(i=n-1;i>0;--i) {
|
|
j = (u16) (ezrand()%(i+1));
|
|
t = array[j];
|
|
array[j] = array[i];
|
|
array[i] = t;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Delay by n cycles */
|
|
void delay_cycles(u16 n) {
|
|
u16 i;
|
|
for(i=0;i<n;++i);
|
|
}
|
|
|
|
/* CC65 compat */
|
|
|
|
#define EZ_HLINE (char) 0x0e
|
|
#define EZ_VLINE (char) 0x0f
|
|
#define EZ_CORNER_UL (char) 0x1c
|
|
#define EZ_CORNER_UR (char) 0x1d
|
|
#define EZ_CORNER_DL (char) 0x1e
|
|
#define EZ_CORNER_DR (char) 0x1f
|
|
|
|
#define cprintf printf
|
|
|
|
void convdigits(char *s, u16 len) {
|
|
u16 i;
|
|
for(i=0;i<len;i++) {
|
|
if(s[i] >= 0x30 && s[i] < 0x3A)
|
|
s[i] -= 0x20;
|
|
}
|
|
}
|
|
|
|
void cputcxy(u8 x, u8 y, char c) {
|
|
gotoxy(x, y);
|
|
cputc(c);
|
|
}
|
|
|
|
void cputsxy(u8 x, u8 y, char *s) {
|
|
gotoxy(x, y);
|
|
cprintf("%s", s);
|
|
}
|
|
|
|
void chlinexy(u8 x, u8 y, u8 l) {
|
|
u8 i;
|
|
gotoxy(x, y);
|
|
for(i=0;i<l;++i) cputc(EZ_HLINE);
|
|
}
|
|
|
|
void cvlinexy(u8 x, u8 y, u8 l) {
|
|
u8 i;
|
|
for(i=0;i<l;++i) {
|
|
gotoxy(x, y+i);
|
|
cputc(EZ_VLINE);
|
|
}
|
|
}
|
|
|
|
/* Draw a proper rectangle with corners */
|
|
void rect(u8 x, u8 y, u8 w, u8 h) {
|
|
u8 i, bl_y = y + h - 1, tr_x = x + w - 1;
|
|
gotoxy(x, y);
|
|
cputc(EZ_CORNER_UL);
|
|
for(i=0;i<w-2;++i) cputc(EZ_HLINE);
|
|
cputc(EZ_CORNER_UR);
|
|
for(i=0;i<h-2;++i) {
|
|
gotoxy(x, y+i+1); cputc(EZ_VLINE);
|
|
gotoxy(tr_x, y+i+1); cputc(EZ_VLINE);
|
|
}
|
|
gotoxy(x, bl_y);
|
|
cputc(EZ_CORNER_DL);
|
|
for(i=0;i<w-2;++i) cputc(EZ_HLINE);
|
|
cputc(EZ_CORNER_DR);
|
|
}
|
|
|
|
void termreset() {
|
|
clrscr();
|
|
move_bkg(0, 0);
|
|
gotoxy(0, 0);
|
|
}
|
|
|
|
void gamereset() {
|
|
#asm
|
|
jp 0
|
|
#endasm
|
|
}
|
|
|
|
#endif
|