~nytpu/gba-keystroke-programming-demo

035bc86a07893dcf5849c1d6351a216a2d954e03 — nytpu 3 months ago 1acfa1e
add keystroke programming demo
4 files changed, 90 insertions(+), 8 deletions(-)

A res/tiles.ase
A res/tiles.grit
A res/tiles.png
M src/main.c
A res/tiles.ase => res/tiles.ase +0 -0
A res/tiles.grit => res/tiles.grit +1 -0
@@ 0,0 1,1 @@
-g -m! -p -gB4

A res/tiles.png => res/tiles.png +0 -0
M src/main.c => src/main.c +89 -8
@@ 4,33 4,114 @@
 */

#include "game.h"
#include "tiles.h"
#include <stddef.h>
#include <tonc.h>

typedef void  colt45;
enum LineValue {
	START,
	UP_ARROW,
	DOWN_ARROW,
	LEFT_ARROW,
	RIGHT_ARROW,
	NOP,
	END,
};

colt45****** shootin_iron; // got my shootin' iron loaded
enum LineValue lines[20] = { [0] = START };
const size_t linesLen = sizeof(lines) / sizeof(lines[0]);
size_t lineSelected = 0;

bool vBlankTriggered = false;
void
redrawLines(void)
{
	size_t line = 0;
	for (; line < linesLen; line++) {
		const size_t baseID = line*32;
		se_mem[30][baseID + 1] = ((line / 10) + 1) & 0x3ff;
		se_mem[30][baseID + 2] = ((line % 10) + 1) & 0x3ff;
		se_mem[30][baseID + 3] = 11;
		if (line == lineSelected) se_mem[30][baseID + 4] = 12;
		else  se_mem[30][baseID + 4] = 0;
		const size_t symbolID = baseID + 5;
		se_mem[30][symbolID] = 0;
		se_mem[30][symbolID+1] = 0;
		switch (lines[line]) {
			break; case START:
				se_mem[30][symbolID] = SE_BUILD(17, 0, 0, 0);
				se_mem[30][symbolID+1] = SE_BUILD(18, 0, 0, 0);
			break; case UP_ARROW: se_mem[30][symbolID] = SE_BUILD(13, 0, 0, 0);
			break; case DOWN_ARROW: se_mem[30][symbolID] = SE_BUILD(13, 0, 0, 1);
			break; case RIGHT_ARROW: se_mem[30][symbolID] = SE_BUILD(14, 0, 0, 0);
			break; case LEFT_ARROW: se_mem[30][symbolID] = SE_BUILD(14, 0, 1, 0);
			break; case NOP: se_mem[30][symbolID] = SE_BUILD(15, 0, 0, 0);
			break; case END:
				se_mem[30][symbolID] = SE_BUILD(19, 0, 0, 0);
				se_mem[30][symbolID+1] = SE_BUILD(20, 0, 0, 0);
		}
		if (lines[line] == END) break;
	}
	for (line++; line < linesLen; line++) toncset16(&se_mem[30][line*32 + 1], 0, 6);
}

void
vBlankHandler(void)
delLine(void)
{
	key_poll();
	if (lineSelected == 0 || lineSelected >= linesLen-1 || lines[lineSelected] == END) return;
	for (size_t i = lineSelected; i < linesLen - 1; i++) lines[i] = lines[i + 1];
	lines[linesLen - 1] = END;
}

void
init(void)
insertLine(enum LineValue val)
{
	irq_init(NULL);
	irq_add(II_VBLANK, vBlankHandler);
	if (lineSelected >= linesLen-1 || lines[lineSelected] == END) return;
	lineSelected++;
	for (size_t i = linesLen - 1; i > lineSelected && i > 0; i--) lines[i] = lines[i - 1];
	lines[lineSelected] = val;
	lines[linesLen - 1] = END;
	if (lineSelected == linesLen-1) lineSelected--;
}

int
main(void)
{
	irq_init(NULL);
	irq_add(II_VBLANK, NULL);
	VBlankIntrWait();

	LZ77UnCompVram(tilesTiles, &tile_mem[0][0]);
	LZ77UnCompVram(tilesPal, pal_bg_mem);

	se_fill(&se_mem[31][0], SE_BUILD(0, 0, 0, 0));
	se_fill(&se_mem[30][0], SE_BUILD(0, 0, 0, 0));

	for (size_t line = 1; line < linesLen; line++) lines[line] = END;

	// Dividing line between program area and whatever would be in the play area
	for (size_t row = 0; row < 32; row++) se_mem[31][(row*32)+8] = SE_BUILD(16, 0, 0, 0);

	REG_BG0CNT = BG_CBB(0) | BG_SBB(31) | BG_4BPP | BG_REG_32x32;
	REG_BG0HOFS = 0; REG_BG0VOFS = 0;
	REG_BG1CNT = BG_CBB(0) | BG_SBB(30) | BG_4BPP | BG_REG_32x32;
	REG_BG1HOFS = 0; REG_BG1VOFS = 0;
	REG_DISPCNT = DCNT_MODE0 | DCNT_BG0 | DCNT_BG1;

	while (1) {
		VBlankIntrWait();
		key_poll();
		if (key_hit(KEY_B)) delLine();
		else if (key_held(KEY_L)) {
			if (key_hit(KEY_UP) && lineSelected > 0) lineSelected--;
			else if (key_hit(KEY_DOWN) && lineSelected < linesLen-2 && lines[lineSelected+1] != END) {
				lineSelected++;
			}
		} else if (key_hit(KEY_A)) insertLine(NOP);
		else if (key_hit(KEY_UP)) insertLine(UP_ARROW);
		else if (key_hit(KEY_DOWN)) insertLine(DOWN_ARROW);
		else if (key_hit(KEY_LEFT)) insertLine(LEFT_ARROW);
		else if (key_hit(KEY_RIGHT)) insertLine(RIGHT_ARROW);
		redrawLines();
	}
	return 0;
}