commit be50e9fc66dc34d752718ab4a629583de86f2253 Author: Yann MAGNIN Date: Sun Aug 14 16:31:09 2022 +0200 add first two menus diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..39e4579 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vxsdk +*.map +test/ diff --git a/GravityDuck b/GravityDuck new file mode 100755 index 0000000..c49901a Binary files /dev/null and b/GravityDuck differ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..68b03fb --- /dev/null +++ b/Makefile @@ -0,0 +1,93 @@ +#! /usr/bin/make -f + + +# +# variable definition +# + +# color definition, for swagg :D +red := \033[1;31m +green := \033[1;32m +blue := \033[1;34m +white := \033[1;37m +nocolor := \033[1;0m + +src := $(foreach path,\ + $(shell find src -not -path "*/\.*" -type d), \ + $(wildcard $(path)/*.c) \ + $(wildcard $(path)/*.S) \ + $(wildcard $(path)/*.s)) + +obj := $(patsubst src_%,$(VXSDK_PREFIX_BUILD)/%.o,$(subst /,_,$(src))) +obj += $(patsubst \ + $(VXSDK_ASSETS_SRC)/%,\ + $(VXSDK_ASSETS_BUILD)/%.o,\ + $(wildcard $(VXSDK_ASSETS_SRC)/*.c) \ + ) + +cflags := -ffreestanding -nostdlib -m4-nofpu -fPIE -O1 +cflags += -mb -fstrict-volatile-bitfields -Wa,--dsp +cflags += $(VXSDK_CFLAGS_INCLUDE) -Iinclude + +# debug vars +VERBOSE ?= true + +# +# build rules +# + +GravityDuck: $(obj) + @ printf "$(blue)Create $(red)$@$(nocolor)\n" + sh-elf-vhex-gcc \ + -T $(VXSDK_PREFIX_LIB)/fxcg50.ld \ + -Wl,-q -Wl,-Map=$(VXSDK_PREFIX_BUILD)/map \ + $(VXSDK_CFLAGS_LINK) \ + -o $@ $^ \ + -Wl,--whole-archive -lvhex-fxcg50 \ + -Wl,--no-whole-archive -lc -lgcc + #vxsdk conv addin -b $@ -n vxaddin -o /tmp/vxaddin + +version: + @echo "$(VXSDK_PKG_VERSION)" + +help: + @ echo 'Rules listing:' + @ echo '... all the default, if no target is provided' + @ echo '... clean remove build object' + @ echo '... fclean remove all generated object' + @ echo '... re same as `make fclean all`' + @ echo '... version display version' + @ echo '... install install the library' + @ echo '... uninstall uninstall the library' + +.PHONY: help version + +# +# Object rules +# + +$(VXSDK_PREFIX_BUILD)%.o: +ifneq ($(VERBOSE),false) + @ mkdir -p $(dir $@) + sh-elf-vhex-gcc \ + $(cflags) -D FXCG50 \ + -o $@ \ + -c $(addprefix src/,$(subst _,/,$(notdir $(basename $@)))) +else + @ mkdir -p $(dir $@) + @ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n" + @ sh-elf-vhex-gcc \ + $(cflags) -D FXCG50 \ + -o $@ \ + -c $(addprefix src/,$(subst _,/,$(notdir $(basename $@)))) +endif + +$(VXSDK_ASSETS_BUILD)%.o: $(VXSDK_ASSETS_SRC)/% +ifneq ($(VERBOSE),false) + @ mkdir -p $(dir $@) + sh-elf-vhex-gcc $(cflags) -D FXCG50 -o $@ -c $< +else + @ mkdir -p $(dir $@) + @ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n" + @ sh-elf-vhex-gcc $(cflags) -D FXCG50 -o $@ -c $< +endif diff --git a/assets/gduck_menu_select_button_0.png b/assets/gduck_menu_select_button_0.png new file mode 100644 index 0000000..59aa83a Binary files /dev/null and b/assets/gduck_menu_select_button_0.png differ diff --git a/assets/gduck_menu_select_button_1.png b/assets/gduck_menu_select_button_1.png new file mode 100644 index 0000000..ee1e17f Binary files /dev/null and b/assets/gduck_menu_select_button_1.png differ diff --git a/assets/gduck_menu_select_button_2.png b/assets/gduck_menu_select_button_2.png new file mode 100644 index 0000000..6dd976a Binary files /dev/null and b/assets/gduck_menu_select_button_2.png differ diff --git a/assets/gduck_menu_select_button_bg.png b/assets/gduck_menu_select_button_bg.png new file mode 100644 index 0000000..24525c4 Binary files /dev/null and b/assets/gduck_menu_select_button_bg.png differ diff --git a/assets/gduck_menu_select_title.png b/assets/gduck_menu_select_title.png new file mode 100644 index 0000000..d134727 Binary files /dev/null and b/assets/gduck_menu_select_title.png differ diff --git a/assets/gduck_menu_title.png b/assets/gduck_menu_title.png new file mode 100644 index 0000000..75ab9f5 Binary files /dev/null and b/assets/gduck_menu_title.png differ diff --git a/assets/troll.png b/assets/troll.png new file mode 100644 index 0000000..4c89494 Binary files /dev/null and b/assets/troll.png differ diff --git a/assets/vxconv.toml b/assets/vxconv.toml new file mode 100644 index 0000000..a5d0137 --- /dev/null +++ b/assets/vxconv.toml @@ -0,0 +1,34 @@ +[gduck_menu_title] +type = 'image' +profile = 'p4a' +path = 'gduck_menu_title.png' + +[gduck_menu_select_title] +type = 'image' +profile = 'p4a' +path = 'gduck_menu_select_title.png' + +[gduck_menu_select_button_bg] +type = 'image' +profile = 'p4a' +path = 'gduck_menu_select_button_bg.png' + +[gduck_menu_select_button_0] +type = 'image' +profile = 'p4a' +path = 'gduck_menu_select_button_0.png' + +[gduck_menu_select_button_1] +type = 'image' +profile = 'p4a' +path = 'gduck_menu_select_button_1.png' + +[gduck_menu_select_button_2] +type = 'image' +profile = 'p4a' +path = 'gduck_menu_select_button_2.png' + +[troll] +type = 'image' +profile = 'p4' +path = 'troll.png' diff --git a/include/gduck/menu.h b/include/gduck/menu.h new file mode 100644 index 0000000..7ea2f48 --- /dev/null +++ b/include/gduck/menu.h @@ -0,0 +1,10 @@ +#ifndef _MENU +#define _MENU + +/* menu_title() : display logo/animation and wait user interaction */ +extern void menu_title(void); + +/* menu_main() : display menu selection */ +extern int menu_main(void); + +#endif //_MENU diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..0354b34 --- /dev/null +++ b/src/main.c @@ -0,0 +1,47 @@ +#include + +#include +#include + +extern void menu_title(void); +extern int menu_select(int max_level); + +int main(void) +{ + extern const image_t troll; + int level; + + menu_title(); + level = menu_select(12); + + dclear(C_WHITE); + dimage( + &troll, + dwidth() / 2, + dheight() / 2, + DIMAGE_CENTER | DIMAGE_MIDDLE + ); + dprint(0, 0, C_BLACK, "selected level = %d", level); + dupdate(); + while (1) { __asm__("sleep"); } +#if 0 + unlock = 0; + id_level = 0; + while(1) { + id_level = menu_main(id_level, unlock); + if (id_level < 0) break; + if(id_level == 1) intro(); + + id_level = engine_main(id_level); + if(id_level > unlock) { + unlock = id_level; + save_write(unlock); + } + if(id_level > NB_LEVEL) { + ending(); + menu_title(); + } + } +#endif + return (0); +} diff --git a/src/menu.c b/src/menu.c new file mode 100644 index 0000000..db48384 --- /dev/null +++ b/src/menu.c @@ -0,0 +1,290 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define BG_COLOR 0x869c +#define CIRCLE_COLOR 0xcf1c +#define NB_CIRCLE 9 +#define NB_BUTTON_ROW 8 +#define NB_BUTTON_COL 5 +#define NB_BUTTON_TOTAL (NB_BUTTON_ROW * NB_BUTTON_COL) + +/* define internal circle information structure */ +struct circle { + int x; + int y; + int size; +} circle[NB_CIRCLE] = { + { .x = 42, .y = 163, .size = 35 }, + { .x = 72, .y = 31, .size = 55 }, + { .x = 223, .y = 239, .size = 60 }, + { .x = 265, .y = 109, .size = 51 }, + { .x = 358, .y = 0, .size = 34 }, + { .x = 396, .y = 185, .size = 50 }, + { .x = 506, .y = 83, .size = 65 }, + { .x = 587, .y = 230, .size = 53 }, + { .x = 606, .y = 38, .size = 27 }, +}; + +//--- +// Internal functions +//--- + +/* menu_background() : update and draw circle */ +static void menu_background(void) +{ + for (int i = 0; i < NB_CIRCLE; ++i) { + circle[i].x += 1; + if ((circle[i].x - circle[i].size) >= (int)dwidth()) + circle[i].x -= (dwidth() + (circle[i].size << 1)); + dcircle_filled( + circle[i].x, + circle[i].y, + circle[i].size, + DCIRCLE_CENTER | DCIRCLE_MIDDLE, + CIRCLE_COLOR + ); + } +} + +/* title menu */ + +/* menu_title_background() : display circle */ +static void menu_title_background(void) +{ + menu_background(); +} + +/* menu_icon() : display the game icon */ +static void menu_title_icon(void) +{ + extern const image_t gduck_menu_title; + did_t did; + + did = dimage( + &gduck_menu_title, + dwidth() / 2, + (dheight() / 2) - (dheight() / 8), + DIMAGE_CENTER | DIMAGE_MIDDLE + ); + dimage_shader_shadow(did, -4, 4); +} + +/* menu_hub() : display HUD information */ +static void menu_title_hud(fps_t *fps, int trigger) +{ + dprint(0, 0, C_WHITE, "FPS: %d", fps->fps); + if (trigger != 0) { + dtext_opt( + dwidth() / 2, + (dheight() / 2) + (dheight() / 4), + C_WHITE, + C_NONE, + DTEXT_CENTER | DTEXT_MIDDLE, + "Press [SHIFT] to start !", + -1 + ); + } +} + +/* menu_text_blink() : change trigger status each 500ms */ +static int menu_title_text_blink(volatile int *trigger) +{ + *trigger ^= 1; + return TIMER_CONTINUE; +} + +/* selection menu */ + +/* menu_select_background() : display circle */ +static void menu_select_background(void) +{ + menu_background(); +} + +/* menu_select_ui() : display button selection */ +static void menu_select_ui(int max_level, int cursor) +{ + extern const image_t gduck_menu_select_title; + extern const image_t gduck_menu_select_button_bg; + extern const image_t gduck_menu_select_button_0; + extern const image_t gduck_menu_select_button_1; + extern const image_t gduck_menu_select_button_2; + const image_t *image; + int counter; + int imgx; + int imgy; + int imgs; + + dimage( + &gduck_menu_select_title, + dwidth() / 2, + dheight() / 6, + DIMAGE_CENTER | DIMAGE_MIDDLE + ); + dimage( + &gduck_menu_select_button_bg, + dwidth() / 2, + (dheight() / 2) + (dheight() / 8), + DIMAGE_CENTER | DIMAGE_MIDDLE + ); + + imgx = (NB_BUTTON_ROW * gduck_menu_select_button_0.width); + imgx += (NB_BUTTON_ROW - 1); + imgx = (dwidth() / 2) - (imgx / 2); + imgx += (gduck_menu_select_button_0.width / 2); + + imgy = (NB_BUTTON_COL * gduck_menu_select_button_0.height); + imgy += (NB_BUTTON_COL - 1); + imgy = ((dheight() / 2) + (dheight() / 8)) - (imgy / 2); + imgy += (gduck_menu_select_button_0.height / 2); + + imgs = imgx; + counter = 0; + for (int y = 0; y < NB_BUTTON_COL; ++y) + { + imgx = imgs; + for (int x = 0; x < NB_BUTTON_ROW; ++x) + { + image = &gduck_menu_select_button_0; + if (counter == cursor) + image = &gduck_menu_select_button_1; + if (counter >= max_level) + image = &gduck_menu_select_button_2; + + dimage( + image, + imgx, + imgy, + DIMAGE_CENTER | DIMAGE_MIDDLE + ); + + if (image != &gduck_menu_select_button_2) { + dprint_opt( + imgx - 1, + imgy + 1, + C_WHITE, + C_NONE, + DTEXT_CENTER | DTEXT_MIDDLE, + "%d", + counter + 1 + ); + } + + imgx += image->width + 1; + counter += 1; + } + imgy += image->height + 1; + } +} + +/* menu_select_hud() : display HUB information */ +static void menu_select_hud(fps_t *fps) +{ + dprint(0, 0, C_WHITE, "FPS: %d (%d us)", fps->fps, fps->render); +} + +//--- +// Public function +//---- + +/* menu_title() : display logo/animation and wait user interaction */ +void menu_title(void) +{ + volatile int trigger; + key_event_t e; + fps_t fps; + int exit; + int timer; + + trigger = 1; + timer = timer_configure( + TIMER_DELAY_MS(500), + VHEX_CALL(&menu_title_text_blink, &trigger) + ); + timer_start(timer); + + uint32_t cache_us = 0; + uint32_t render_us = 0; + uint32_t key_us = 0; + + exit = 1; + timer_fps_init(&fps); + while (exit) + { + cache_us = timer_prof_exec({ + dclear(BG_COLOR); + menu_title_background(); + menu_title_icon(); + menu_title_hud(&fps, trigger); + dprint(0, 20, C_WHITE, + "cache = %d us\nrender = %d us\nkey = %d us", + cache_us, render_us, key_us + ); + }); + render_us = timer_prof_exec({ dupdate(); }); + + //timer_fps_sync(&fps, 30); + + key_us = timer_prof_exec({ + while (1) { + e = keyvent_poll(); + if (e.type == KEYEV_NONE) + break; + if (e.type != KEYEV_UP) + continue; + if (e.key == KEY_SHIFT) + exit = 0; + } + }); + } + timer_fps_quit(&fps); + timer_stop(timer); +} + +/* menu_select() : level selection */ +int menu_select(int max_level) +{ + key_event_t e; + fps_t fps; + int cursor; + int exit; + + exit = -1; + cursor = 0; + timer_fps_init(&fps); + while (exit < 0) + { + dclear(BG_COLOR); + menu_select_background(); + menu_select_ui(max_level, cursor); + menu_select_hud(&fps); + dupdate(); + + timer_fps_sync(&fps, 3); + + while (1) { + e = keyvent_poll(); + if (e.type == KEYEV_NONE) + break; + if (e.type != KEYEV_UP) + continue; + if (e.key == KEY_LEFT) cursor -= 1; + if (e.key == KEY_RIGHT) cursor += 1; + if (e.key == KEY_DOWN) cursor += NB_BUTTON_ROW; + if (e.key == KEY_UP) cursor -= NB_BUTTON_ROW; + + if (cursor < 0) cursor = 0; + if (cursor >= max_level) cursor = max_level - 1; + + if (e.key == KEY_SHIFT) exit = cursor; + } + } + timer_fps_quit(&fps); + return (cursor); +} diff --git a/vxsdk.toml b/vxsdk.toml new file mode 100644 index 0000000..ef3adb0 --- /dev/null +++ b/vxsdk.toml @@ -0,0 +1,11 @@ +[project] +name = 'GravityDuck' + +[dependencies] +vxKernel = 'dev' + +[build] +build = 'make' + +[extra.vxKernel] +configure = '--static --verbose'