Skip to content

Commit

Permalink
Merge branch 'develop' into ed64-xseries
Browse files Browse the repository at this point in the history
  • Loading branch information
networkfusion authored Sep 28, 2024
2 parents bd210dd + 55e7663 commit 490e624
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 116 deletions.
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ $(SPNG_OBJS): N64_CFLAGS+=-isystem $(SOURCE_DIR)/libs/miniz -DSPNG_USE_MINIZ -fc
$(FILESYSTEM_DIR)/FiraMonoBold.font64: MKFONT_FLAGS+=-c 1 --size 16 -r 20-7F -r 80-1FF -r 2026-2026 --ellipsis 2026,1
$(FILESYSTEM_DIR)/%.wav64: AUDIOCONV_FLAGS=--wav-compress 1


$(@info $(shell mkdir -p ./$(FILESYSTEM_DIR) &> /dev/null))

$(FILESYSTEM_DIR)/%.font64: $(ASSETS_DIR)/%.ttf
Expand Down
55 changes: 39 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,45 @@ An open source menu for N64 flashcarts.
## Experimental features
These features are subject to change:

### ROM Boxart
To use boxart, place PNG files in the `/menu/boxart` folder on the SD card with the following dimensions:
* Standard covers: 158x112
* 64DD covers: 129x112
* Japanese covers: 112x158

Each file must be named according to the 2 letter ROM ID, or 3 letter ROM ID including media type.
i.e. for GoldenEye 2 letters, this would be `GE.png`.
i.e. for GoldenEye 3 letters, this would be `NGE.png`.
You can download these boxart packs:

[American Boxart](https://mega.nz/file/6cNGwSqI#8X5ukb65n3YMlGaUtSOGXkKo9HxVnnMOgqn94Epcr7w)

[European Boxart](https://mega.nz/file/O7AjDbRJ#VnVU10dq8HQvBUQptppI6PAcQMb8-Zembqav8WtAQ_M)

[64DD Boxart](https://mega.nz/file/O3JzwD7B#BYl1aV-pbrJ-MxWUbM_K0yGVIRbmSoxJJZqQInRzZyM)

### GamePak sprites
To use N64 `GamePak` sprites, place `PNG` files within the `sd:/menu/boxart/` folder.


#### Supported sprites
These must be `PNG` files that use the following dimensions:
* Standard N64 GamePak boxart sprites: 158x112
* Japanese N64 GamePak boxart sprites: 112x158
* 64DD boxart sprites: 129x112

They will be loaded by directories using each character of the full 4 character Game Code (as identified in the menus ROM information).
i.e. for GoldenEye NTSC USA (NGEE), this would be `sd:/menu/boxart/N/G/E/E/boxart_front.png`.
i.e. for GoldenEye PAL (NGEP), this would be `sd:/menu/boxart/N/G/E/P/boxart_front.png`.

To improve compatibility between regions (as a fallback), you may exclude the region ID (last matched directory) for GamePaks to match with 3 letter IDs instead:
i.e. for GoldenEye, this would be `sd:/menu/boxart/N/G/E/boxart_front.png`.

**Note1:** Excluding the region ID may show the wrong boxart.
**Note2:** For future support, boxart sprites should also include: `boxart_back.png`, `boxart_top.png`, `boxart_bottom.png`, `boxart_left.png`, `boxart_right.png`.


#### Compatibilty mode
If you cannot yet satisfy the correct boxart layout, The menu still has **deprecated** support for filenames containing the Game ID.

**Note:** This will add a noticeable delay for displaying parts of the menu.

Each file must be named according to the 2,3 or 4 letter GamePak ID (matched in this order).
i.e.
* for GoldenEye 4 letters, this would be `sd:/menu/boxart/NGEE.png` and/or `sd:/menu/boxart/NGEP.png`.
* for GoldenEye 3 letters, this would be `sd:/menu/boxart/NGE.png`.
* for GoldenEye 2 letters, this would be `sd:/menu/boxart/GE.png`.


As a starting point, here are some links to boxart packs:
* [Japan Boxart](https://mega.nz/file/KyJR0B6B#ERabLautAVPaqJTIdBSv4ghbudNhK7hnEr2ZS1Q6ub0)
* [American Boxart](https://mega.nz/file/rugAFYSQ#JHfgCU2amzNVpC4S6enP3vg--wtAAwsziKa7cej6QCc)
* [European Boxart](https://mega.nz/file/OmIV3aAK#kOWdutK1_41ffN64R6thbU7HEPR_M9qO0YM2mNG6RbQ)
* [64DD Boxart](https://mega.nz/file/ay5wQIxJ#k3PF-VMLrZJxJTr-BOaOKa2TBIK7c2t4zwbdshsQl40)


### Menu Settings
Expand Down
2 changes: 1 addition & 1 deletion docs/00_getting_started_sd.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ SD:\
│ │ ├── NDDJ2.n64
│ │ └── NDXJ0.n64
│ │
│ └── emulators
│ └── emulators\
│ ├── neon64bu.rom
│ ├── sodium64.z64
│ ├── gb.v64
Expand Down
2 changes: 1 addition & 1 deletion libdragon
Submodule libdragon updated 57 files
+4 −2 Makefile
+1 −1 examples/Makefile
+50 −34 examples/fontgallery/fontgallery.c
+1 −0 examples/loadspritefromsd/.gitignore
+20 −10 examples/loadspritefromsd/Makefile
+ examples/loadspritefromsd/assets/attack1.png
+ examples/loadspritefromsd/assets/attack2.png
+ examples/loadspritefromsd/assets/attack3.png
+ examples/loadspritefromsd/assets/attack4.png
+ examples/loadspritefromsd/filesystem/earthbound.sprite
+ examples/loadspritefromsd/filesystem/mudkip.sprite
+ examples/loadspritefromsd/filesystem/plane.sprite
+14 −42 examples/loadspritefromsd/loadspritefromsd.c
+1 −0 examples/spriteanim/.gitignore
+31 −0 examples/spriteanim/Makefile
+ examples/spriteanim/assets/knight.png
+105 −0 examples/spriteanim/spriteanim.c
+0 −19 examples/spritemap/Makefile
+ examples/spritemap/filesystem/earthbound.sprite
+ examples/spritemap/filesystem/mudkip.sprite
+ examples/spritemap/filesystem/plane.sprite
+0 −139 examples/spritemap/spritemap.c
+1 −1 examples/videoplayer/Makefile
+87 −55 examples/videoplayer/videoplayer.c
+5 −6 include/audio.h
+131 −4,108 include/font.h
+88 −0 include/ksemaphore.h
+3 −0 include/libdragon.h
+1 −1 include/mi.h
+5 −12 include/mpeg2.h
+41 −0 include/pifile.h
+1 −0 include/rdpq_font.h
+26 −11 include/rdpq_rect.h
+3 −2 include/rdpq_tex.h
+12 −10 include/yuv.h
+1 −0 src/GL/query.c
+112 −39 src/graphics.c
+4 −4 src/inspector.c
+16 −62 src/inthandler.S
+16 −0 src/kernel/kernel.c
+56 −0 src/kernel/ksemaphore.c
+6 −0 src/kernel/libdragon.mk
+141 −0 src/pifile.c
+103 −26 src/rdpq/rdpq_font.c
+536 −748 src/rdpq/rdpq_font_builtin.c
+11 −7 src/rdpq/rdpq_font_internal.h
+14 −3 src/rdpq/rdpq_paragraph.c
+1 −0 src/regs.S
+4 −0 src/system.c
+121 −0 src/system_newlib_locks.c
+30 −43 src/video/mpeg2.c
+9 −9 src/video/yuv.c
+6 −6 tools/build-toolchain.sh
+367 −15 tools/mkfont/mkfont.cpp
+5 −1 tools/mkfont/mkfont_bmfont.cpp
+270 −216 tools/mkfont/mkfont_out.cpp
+10 −2 tools/mkfont/mkfont_ttf.cpp
27 changes: 24 additions & 3 deletions src/menu/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,16 @@ static void actions_clear (menu_t *menu) {
}

static void actions_update_direction (menu_t *menu) {
joypad_8way_t held_dir = joypad_get_direction(JOYPAD_PORT_1, JOYPAD_2D_DPAD | JOYPAD_2D_STICK);
joypad_8way_t fast_dir = joypad_get_direction(JOYPAD_PORT_1, JOYPAD_2D_C);
joypad_8way_t held_dir;
joypad_8way_t fast_dir;

JOYPAD_PORT_FOREACH (i) {
held_dir = joypad_get_direction(i, JOYPAD_2D_DPAD | JOYPAD_2D_STICK);
fast_dir = joypad_get_direction(i, JOYPAD_2D_C);
if (held_dir != JOYPAD_8WAY_NONE || fast_dir != JOYPAD_8WAY_NONE) {
break;
}
}

if (fast_dir != JOYPAD_8WAY_NONE) {
held_dir = fast_dir;
Expand Down Expand Up @@ -82,7 +90,14 @@ static void actions_update_direction (menu_t *menu) {
}

static void actions_update_buttons (menu_t *menu) {
joypad_buttons_t pressed = joypad_get_buttons_pressed(JOYPAD_PORT_1);
joypad_buttons_t pressed;

JOYPAD_PORT_FOREACH (i) {
pressed = joypad_get_buttons_pressed(i);
if (pressed.raw) {
break;
}
}

if (pressed.a) {
menu->actions.enter = true;
Expand All @@ -98,6 +113,12 @@ static void actions_update_buttons (menu_t *menu) {
}


void actions_init (void) {
JOYPAD_PORT_FOREACH (port) {
joypad_set_rumble_active(port, false);
}
}

void actions_update (menu_t *menu) {
joypad_poll();

Expand Down
1 change: 1 addition & 0 deletions src/menu/actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "menu_state.h"


void actions_init (void);
void actions_update (menu_t *menu);


Expand Down
37 changes: 36 additions & 1 deletion src/menu/components.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,41 @@
#include <libdragon.h>
#include "menu_state.h"

/** @brief File image Enumeration. */
typedef enum {

/** @brief Boxart image from the front */
IMAGE_BOXART_FRONT,

/** @brief Boxart image from the back */
IMAGE_BOXART_BACK,

/** @brief Boxart image from the top */
IMAGE_BOXART_TOP,

/** @brief Boxart image from the bottom */
IMAGE_BOXART_BOTTOM,

/** @brief Boxart image from the left side */
IMAGE_BOXART_LEFT,

/** @brief Boxart image from the right side */
IMAGE_BOXART_RIGHT,

/** @brief GamePak image from the front */
IMAGE_GAMEPAK_FRONT,

/** @brief GamePak image from the back */
IMAGE_GAMEPAK_BACK,

/** @brief File image thumbnail */
IMAGE_THUMBNAIL,

/** @brief List end marker */
IMAGE_TYPE_END

} file_image_type_t;


/**
* @addtogroup
Expand Down Expand Up @@ -64,7 +99,7 @@ typedef struct {
surface_t *image;
} component_boxart_t;

component_boxart_t *component_boxart_init (const char *storage_prefix, char *game_code);
component_boxart_t *component_boxart_init (const char *storage_prefix, char *game_code, file_image_type_t current_image_view);
void component_boxart_free (component_boxart_t *b);
void component_boxart_draw (component_boxart_t *b);

Expand Down
13 changes: 4 additions & 9 deletions src/menu/components/background.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,20 @@ static void prepare_background (component_background_t *c) {
return;
}

uint16_t image_center_x = (c->image->width / 2);
uint16_t image_center_y = (c->image->height / 2);

// Darken the image
rdpq_attach(c->image, NULL);
rdpq_mode_push();
rdpq_set_mode_standard();
rdpq_set_prim_color(BACKGROUND_OVERLAY_COLOR);
rdpq_mode_combiner(RDPQ_COMBINER_FLAT);
rdpq_mode_blender(RDPQ_BLENDER_MULTIPLY);
rdpq_fill_rectangle(
0 - (DISPLAY_CENTER_X - image_center_x),
0 - (DISPLAY_CENTER_Y - image_center_y),
DISPLAY_WIDTH - (DISPLAY_CENTER_X - image_center_x),
DISPLAY_HEIGHT - (DISPLAY_CENTER_Y - image_center_y)
);
rdpq_fill_rectangle(0, 0, c->image->width, c->image->height);
rdpq_mode_pop();
rdpq_detach();

uint16_t image_center_x = (c->image->width / 2);
uint16_t image_center_y = (c->image->height / 2);

// Prepare display list
rspq_block_begin();
rdpq_mode_push();
Expand Down
94 changes: 78 additions & 16 deletions src/menu/components/boxart.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ static void png_decoder_callback (png_err_t err, surface_t *decoded_image, void
}


component_boxart_t *component_boxart_init (const char *storage_prefix, char *game_code) {
component_boxart_t *component_boxart_init (const char *storage_prefix, char *game_code, file_image_type_t current_image_view) {
component_boxart_t *b;
char file_name[8];
char boxart_id_path[8];

if ((b = calloc(1, sizeof(component_boxart_t))) == NULL) {
return NULL;
Expand All @@ -29,21 +29,83 @@ component_boxart_t *component_boxart_init (const char *storage_prefix, char *gam

path_t *path = path_init(storage_prefix, BOXART_DIRECTORY);

sprintf(file_name, "%.3s.png", game_code);
path_push(path, file_name);
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
path_free(path);
return b;
sprintf(boxart_id_path, "%c/%c/%c/%c", game_code[0], game_code[1], game_code[2], game_code[3]);
path_push(path, boxart_id_path);

if (!directory_exists(path_get(path))) { // Allow boxart to not specify the region code.
path_pop(path);
}

if (directory_exists(path_get(path))) {
switch (current_image_view) {
case IMAGE_GAMEPAK_FRONT:
path_push(path, "gamepak_front.png");
case IMAGE_GAMEPAK_BACK:
path_push(path, "gamepak_back.png");
case IMAGE_BOXART_BACK:
path_push(path, "boxart_back.png");
case IMAGE_BOXART_LEFT:
path_push(path, "boxart_left.png");
case IMAGE_BOXART_RIGHT:
path_push(path, "boxart_right.png");
case IMAGE_BOXART_BOTTOM:
path_push(path, "boxart_bottom.png");
case IMAGE_BOXART_TOP:
path_push(path, "boxart_top.png");
default:
path_push(path, "boxart_front.png");
}

if (file_exists(path_get(path))) {
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
path_free(path);
return b;
}
}
}
path_pop(path);

// TODO: This is bad, we should only check for 3 letter codes
sprintf(file_name, "%.2s.png", game_code + 1);
path_push(path, file_name);
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
path_free(path);
return b;
else { // compatibility mode

char file_name[8];

// reset the directory path used for boxart.
path = path_init(storage_prefix, BOXART_DIRECTORY);

sprintf(file_name, "%c%c%c%c.png", game_code[0], game_code[1], game_code[2], game_code[3]);
path_push(path, file_name);

if (file_exists(path_get(path))) {
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
path_free(path);
return b;
}
}

path_pop(path);
sprintf(file_name, "%c%c%c.png", game_code[0], game_code[1], game_code[2]);
path_push(path, file_name);

if (file_exists(path_get(path))) {
if (file_exists(path_get(path))) {
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
path_free(path);
return b;
}
}
}
else {
path_pop(path);

sprintf(file_name, "%c%c.png", game_code[1], game_code[2]);
path_push(path, file_name);
if (file_exists(path_get(path))) {
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
path_free(path);
return b;
}
}
}
}
// TODO: return default image.

path_free(path);
free(b);
Expand Down Expand Up @@ -89,4 +151,4 @@ void component_boxart_draw (component_boxart_t *b) {
BOXART_LOADING_COLOR
);
}
}
}
Loading

0 comments on commit 490e624

Please sign in to comment.