Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Controller Pak management view #91

Draft
wants to merge 64 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
e08d0c4
Add CPak management view
networkfusion Mar 17, 2024
4270a51
Add handler
networkfusion Mar 18, 2024
e3d35b4
cleanups
networkfusion Mar 18, 2024
8dbc0aa
Further improvements
networkfusion Mar 18, 2024
ec708de
remove un-needed headers
networkfusion Mar 18, 2024
646c107
Minor improvements
networkfusion Mar 19, 2024
dc79389
add info structure
networkfusion Mar 19, 2024
ae0d19b
Improve repair function
networkfusion Mar 19, 2024
81b31b5
Merge branch 'main' into cpak-management
networkfusion Apr 25, 2024
28ee429
Likely incorrect fix for STDIO
networkfusion Apr 25, 2024
7e9bd18
Merge branch 'main' into cpak-management
networkfusion Apr 29, 2024
a32373e
Add CPak management view
networkfusion Mar 17, 2024
2670c84
Add handler
networkfusion Mar 18, 2024
6a278bb
cleanups
networkfusion Mar 18, 2024
77ff2bf
Further improvements
networkfusion Mar 18, 2024
c57a5be
remove un-needed headers
networkfusion Mar 18, 2024
d21328b
Minor improvements
networkfusion Mar 19, 2024
ecd131b
add info structure
networkfusion Mar 19, 2024
02dbcc0
Improve repair function
networkfusion Mar 19, 2024
c101dc2
Likely incorrect fix for STDIO
networkfusion Apr 25, 2024
d038eff
Improve menu for when CPak is not inserted.
networkfusion Apr 29, 2024
9746a1d
Merge branch 'cpak-management' of https://github.com/networkfusion/N6…
networkfusion Apr 29, 2024
d0683e9
Add "pak" extensions
networkfusion Apr 29, 2024
2871ff7
Merge remote-tracking branch 'upstream/main' into cpak-management
networkfusion Apr 29, 2024
4f01b3f
Minor improvments
networkfusion Apr 29, 2024
9869b6f
Improve path
networkfusion Apr 30, 2024
4f99e48
Remove block entry
networkfusion Apr 30, 2024
ce5d6f7
Merge remote-tracking branch 'upstream/main' into cpak-management
networkfusion May 5, 2024
ac5e519
Fix review commenrt
networkfusion May 5, 2024
5bba830
Merge remote-tracking branch 'upstream/main' into cpak-management
networkfusion May 19, 2024
20ee708
Merge branch 'develop' into cpak-management
networkfusion Jun 5, 2024
7fbe623
Merge branch 'develop' into cpak-management
networkfusion Jun 5, 2024
2677e05
Merge branch 'develop' into cpak-management
networkfusion Jun 11, 2024
5ae7cce
Merge branch 'develop' into cpak-management
networkfusion Jun 29, 2024
0787805
Merge branch 'develop' into cpak-management
networkfusion Jul 7, 2024
b1ea3f3
Merge branch 'develop' into cpak-management
networkfusion Jul 9, 2024
35f51fd
Merge branch 'develop' into cpak-management
networkfusion Jul 9, 2024
99abea6
Merge branch 'develop' into cpak-management
networkfusion Jul 19, 2024
967d846
Improve menu response
networkfusion Jul 20, 2024
9bb6e66
Create Cpak dir if it does not exist
networkfusion Jul 20, 2024
0cd5455
Code improvements
networkfusion Jul 20, 2024
8ed610f
Further improvements
networkfusion Jul 20, 2024
3ed121d
Make backup unique
networkfusion Jul 20, 2024
2aa1aed
Minor improvements
networkfusion Jul 20, 2024
5bf3728
Merge branch 'develop' into cpak-management
networkfusion Aug 4, 2024
83367c2
Merge branch 'develop' into cpak-management
networkfusion Aug 8, 2024
056e664
Merge branch 'develop' into cpak-management
networkfusion Sep 30, 2024
f5209c8
Merge branch 'develop' into cpak-management
networkfusion Oct 12, 2024
1bfde7c
Merge branch 'develop' into cpak-management
networkfusion Oct 25, 2024
4f06086
Merge branch 'develop' into cpak-management
networkfusion Nov 5, 2024
2c10eb5
Merge branch 'develop' into cpak-management
networkfusion Nov 7, 2024
ef4ee1b
Merge branch 'develop' into cpak-management
networkfusion Nov 11, 2024
7220d37
Rename components to ui_components (#160)
networkfusion Nov 11, 2024
19bce7e
Merge branch 'develop' into cpak-management
networkfusion Nov 11, 2024
5cd3260
Merge branch 'develop' into cpak-management
networkfusion Nov 11, 2024
4ac3b38
Apply merge fixes
networkfusion Nov 11, 2024
05c0f30
Update src/menu/views/joypad_controller_pak.c
networkfusion Nov 11, 2024
84c635b
Update src/menu/views/joypad_controller_pak.c
networkfusion Nov 11, 2024
f01614a
Update src/menu/views/joypad_controller_pak.c
networkfusion Nov 11, 2024
cef5d43
Update src/menu/views/joypad_controller_pak.c
networkfusion Nov 11, 2024
72d8139
Update src/menu/views/joypad_controller_pak.c
networkfusion Nov 11, 2024
c5a6e69
Update src/menu/views/joypad_controller_pak.c
networkfusion Nov 11, 2024
dc57d9b
Update src/menu/views/joypad_controller_pak.c
networkfusion Nov 11, 2024
7e93276
Update src/menu/views/joypad_controller_pak.c
networkfusion Nov 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ SRCS = \
menu/components/common.c \
menu/components/context_menu.c \
menu/components/file_list.c \
menu/cpak_handler.c \
menu/disk_info.c \
menu/fonts.c \
menu/hdmi.c \
Expand All @@ -62,6 +63,7 @@ SRCS = \
menu/views/fault.c \
menu/views/file_info.c \
menu/views/image_viewer.c \
menu/views/joypad_controller_pak.c \
menu/views/text_viewer.c \
menu/views/load_disk.c \
menu/views/load_emulator.c \
Expand Down
79 changes: 79 additions & 0 deletions src/menu/cpak_handler.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <libdragon.h>

#include <stdio.h>
#include "../utils/fs.h"
#include "cpak_handler.h"

#define CPAK_BLOCKS 128
#define CPAK_BLOCK_SIZE MEMPAK_BLOCK_SIZE

cpak_err_t cpak_info_load(uint8_t port, cpak_info_t *cpak_info)
{
int res = validate_mempak(port);
if (res != CONTROLLER_PAK_OK) {
return CONTROLLER_PAK_ERR_INVALID;
}

for (int j = 0; j < 16; j++)
{
entry_structure_t entry;

get_mempak_entry(port, j, &entry);

cpak_info->entries[j] = entry;
}

cpak_info->free_pages = get_mempak_free_space(port);

return CONTROLLER_PAK_OK;
}
Comment on lines +10 to +29
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error handling for get_mempak_entry.

The function lacks error handling for get_mempak_entry. If get_mempak_entry fails, it should return an appropriate error code.

-  get_mempak_entry(port, j, &entry);
+  int entry_res = get_mempak_entry(port, j, &entry);
+  if (entry_res != CONTROLLER_PAK_OK) {
+    return entry_res;
+  }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cpak_err_t cpak_info_load(uint8_t port, cpak_info_t *cpak_info)
{
int res = validate_mempak(port);
if (res != CONTROLLER_PAK_OK) {
return CONTROLLER_PAK_ERR_INVALID;
}
for (int j = 0; j < 16; j++)
{
entry_structure_t entry;
get_mempak_entry(port, j, &entry);
cpak_info->entries[j] = entry;
}
cpak_info->free_pages = get_mempak_free_space(port);
return CONTROLLER_PAK_OK;
}
cpak_err_t cpak_info_load(uint8_t port, cpak_info_t *cpak_info)
{
int res = validate_mempak(port);
if (res != CONTROLLER_PAK_OK) {
return CONTROLLER_PAK_ERR_INVALID;
}
for (int j = 0; j < 16; j++)
{
entry_structure_t entry;
int entry_res = get_mempak_entry(port, j, &entry);
if (entry_res != CONTROLLER_PAK_OK) {
return entry_res;
}
cpak_info->entries[j] = entry;
}
cpak_info->free_pages = get_mempak_free_space(port);
return CONTROLLER_PAK_OK;
}


int cpak_clone_contents_to_file(char *path, uint8_t port) {
uint8_t cpak_data[CPAK_BLOCKS * CPAK_BLOCK_SIZE];
int err;
for (int i = 0; i < CPAK_BLOCKS; i++) {
err = read_mempak_sector(port, i, &cpak_data[i * CPAK_BLOCK_SIZE]);
if (err) {
return err;
}
}

FILE *f;

if ((f = fopen(path, "wb")) == NULL) {
return CONTROLLER_PAK_ERR_IO;
}


if (fwrite(&cpak_data, 1, sizeof(cpak_data), f) != sizeof(cpak_data)) {
err = 3;
}
fclose(f);

if (err) {
return err;
}
else {
return CONTROLLER_PAK_OK;
}
}
Comment on lines +31 to +59
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error handling for fwrite.

The function lacks error handling for fwrite. If fwrite fails, it should return an appropriate error code.

-  if (fwrite(&cpak_data, 1, sizeof(cpak_data), f) != sizeof(cpak_data)) {
-    err = 3;
+  if (fwrite(&cpak_data, 1, sizeof(cpak_data), f) != sizeof(cpak_data)) {
+    fclose(f);
+    return CONTROLLER_PAK_ERR_IO;
  }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int cpak_clone_contents_to_file(char *path, uint8_t port) {
uint8_t cpak_data[CPAK_BLOCKS * CPAK_BLOCK_SIZE];
int err;
for (int i = 0; i < CPAK_BLOCKS; i++) {
err = read_mempak_sector(port, i, &cpak_data[i * CPAK_BLOCK_SIZE]);
if (err) {
return err;
}
}
FILE *f;
if ((f = fopen(path, "wb")) == NULL) {
return CONTROLLER_PAK_ERR_IO;
}
if (fwrite(&cpak_data, 1, sizeof(cpak_data), f) != sizeof(cpak_data)) {
err = 3;
}
fclose(f);
if (err) {
return err;
}
else {
return CONTROLLER_PAK_OK;
}
}
int cpak_clone_contents_to_file(char *path, uint8_t port) {
uint8_t cpak_data[CPAK_BLOCKS * CPAK_BLOCK_SIZE];
int err;
for (int i = 0; i < CPAK_BLOCKS; i++) {
err = read_mempak_sector(port, i, &cpak_data[i * CPAK_BLOCK_SIZE]);
if (err) {
return err;
}
}
FILE *f;
if ((f = fopen(path, "wb")) == NULL) {
return CONTROLLER_PAK_ERR_IO;
}
if (fwrite(&cpak_data, 1, sizeof(cpak_data), f) != sizeof(cpak_data)) {
fclose(f);
return CONTROLLER_PAK_ERR_IO;
}
fclose(f);
if (err) {
return err;
}
else {
return CONTROLLER_PAK_OK;
}
}


cpak_err_t cpak_overwrite_contents_from_file(char *path, uint8_t port) {
// TODO: implementation.
return CONTROLLER_PAK_ERR_IO;
}
Comment on lines +61 to +64
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implement the function cpak_overwrite_contents_from_file.

The function is currently a placeholder with a TODO comment.

Do you want me to assist with the implementation or open a GitHub issue to track this task?


cpak_err_t cpak_attempt_repair(uint8_t port, bool allow_formatting) {
int result = validate_mempak(port);
if (result == CONTROLLER_PAK_OK) {
return CONTROLLER_PAK_OK;
}

// TODO: repair implementation.

// last resort would be to format it completely!
if (result == -3 && allow_formatting) {
result = format_mempak(port);
}
return result;
Comment on lines +66 to +78
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implement the function cpak_attempt_repair.

The function is currently a placeholder with a TODO comment.

Do you want me to assist with the implementation or open a GitHub issue to track this task?

}
33 changes: 33 additions & 0 deletions src/menu/cpak_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @file cpak_handler.h
* @brief ControllerPak handler
* @ingroup menu
*/

#include <stdbool.h>
#include <stdint.h>

#ifndef CPAK_HANDLER_H__
#define CPAK_HANDLER_H__

/** @brief Controller Pak state enumeration. */
typedef enum {
CONTROLLER_PAK_OK,
CONTROLLER_PAK_ERR_IO,
CONTROLLER_PAK_ERR_NO_FILE,
CONTROLLER_PAK_ERR_INVALID,
} cpak_err_t;

/** @brief Controller Pak Information Structure. */
typedef struct {
entry_structure_t entries[16];
int free_pages;

} cpak_info_t;

cpak_err_t cpak_info_load(uint8_t port, cpak_info_t *cpak_info);
int cpak_clone_contents_to_file(char *path, uint8_t port);
cpak_err_t cpak_overwrite_contents_from_file(char *path, uint8_t port);
cpak_err_t cpak_attempt_repair(uint8_t port, bool allow_formatting);

#endif
1 change: 1 addition & 0 deletions src/menu/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ static view_t menu_views[] = {
{ MENU_MODE_CREDITS, view_credits_init, view_credits_display },
{ MENU_MODE_SETTINGS_EDITOR, view_settings_init, view_settings_display },
{ MENU_MODE_RTC, view_rtc_init, view_rtc_display },
{ MENU_MODE_JOYPAD_CPAK, view_joypad_controller_pak_init, view_joypad_controller_pak_display },
{ MENU_MODE_FLASHCART, view_flashcart_info_init, view_flashcart_info_display },
{ MENU_MODE_LOAD_ROM, view_load_rom_init, view_load_rom_display },
{ MENU_MODE_LOAD_DISK, view_load_disk_init, view_load_disk_display },
Expand Down
1 change: 1 addition & 0 deletions src/menu/menu_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ typedef enum {
MENU_MODE_CREDITS,
MENU_MODE_SETTINGS_EDITOR,
MENU_MODE_RTC,
MENU_MODE_JOYPAD_CPAK,
MENU_MODE_FLASHCART,
MENU_MODE_LOAD_ROM,
MENU_MODE_LOAD_DISK,
Expand Down
2 changes: 2 additions & 0 deletions src/menu/views/browser.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ static const char *disk_extensions[] = { "ndd", NULL };
static const char *emulator_extensions[] = { "nes", "sfc", "smc", "gb", "gbc", "sms", "gg", "sg", NULL };
// TODO: "eep", "sra", "srm", "fla" could be used if transfered from different flashcarts.
static const char *save_extensions[] = { "sav", NULL };
//static const char *joypad_accessory_save_extensions[] = { "cpak", "mpk", "pak", NULL };
static const char *image_extensions[] = { "png", NULL };
static const char *text_extensions[] = { "txt", "ini", "yml", "yaml", NULL };
static const char *music_extensions[] = { "mp3", NULL };
Expand Down Expand Up @@ -283,6 +284,7 @@ static component_context_menu_t settings_context_menu = {
{ .text = "Show credits", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_CREDITS) },
{ .text = "Adjust RTC", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_RTC) },
{ .text = "Show cart info", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_FLASHCART) },
{ .text = "CPak Management", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_JOYPAD_CPAK) },
COMPONENT_CONTEXT_MENU_LIST_END,
}
};
Expand Down
150 changes: 150 additions & 0 deletions src/menu/views/joypad_controller_pak.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#include "views.h"
#include "../cpak_handler.h"
#include "utils/fs.h"

#define CPAK_MAX_PAGES 123
#define CPAK_MAX_NOTES 16
#define CPAK_BACKUP_DIRECTORY "/cpak_backups"
#define CPAK_BACKUP_FILE_PREFIX "cpak_backup"
#define CPAK_BACKUP_FILE_EXT "pak"


static int accessory_is_cpak[4];
static cpak_info_t cpak_info;
static bool backup_in_progress = false;


const static char *format_cpak_entries(entry_structure_t *entries) {
// TODO: either show the note descriptions, or show the notes used.
// for (int i = 0; i< 16; i++) {

// }
return "?/16"; //CPAK_MAX_NOTES
}
Comment on lines +17 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete function: format_cpak_entries.

The function contains a TODO comment and returns a placeholder string.

Do you want me to help complete this function or open a GitHub issue to track this task?


static void exec_cpak_backup(menu_t *menu, uint8_t port) {
backup_in_progress = true;
char file_name[32];

path_t *path = path_init(menu->storage_prefix, CPAK_BACKUP_DIRECTORY);
directory_create(path_get(path));

sprintf(file_name, "%s-%lld.%s", CPAK_BACKUP_FILE_PREFIX, time( NULL ), CPAK_BACKUP_FILE_EXT);

path_push(path, file_name);

//int res =
cpak_clone_contents_to_file(path_get(path), port);

// TODO: draw progress bar or error!
// if (res == CONTROLLER_PAK_OK) {

// }
// else {

// }

path_free(path);

backup_in_progress = false;
}
Comment on lines +25 to +50
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete error handling: exec_cpak_backup.

The function contains a TODO comment for drawing a progress bar or error message and does not handle the result of the backup operation.

Do you want me to help complete the error handling or open a GitHub issue to track this task?


static void process (menu_t *menu) {

if (menu->actions.enter) {
// TODO: handle all ports
if (accessory_is_cpak[JOYPAD_PORT_1]) {
exec_cpak_backup(menu, JOYPAD_PORT_1);
}
} else if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
}
}
Comment on lines +52 to +62
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete functionality: process.

The function contains a TODO comment for handling all ports and currently only handles JoyPad port 1.

Do you want me to help complete this functionality or open a GitHub issue to track this task?


static void draw (menu_t *menu, surface_t *d) {
rdpq_attach(d, NULL);

component_background_draw();
networkfusion marked this conversation as resolved.
Show resolved Hide resolved

if (backup_in_progress) {
component_messagebox_draw("Saving...");
networkfusion marked this conversation as resolved.
Show resolved Hide resolved
}

component_layout_draw();
networkfusion marked this conversation as resolved.
Show resolved Hide resolved

// TODO: Backup from other ports, restore from SD, and/or Repair functions.
component_main_text_draw(
networkfusion marked this conversation as resolved.
Show resolved Hide resolved
ALIGN_CENTER, VALIGN_TOP,
"CONTROLLER PAK MENU\n"
"\n"
"This menu only supports cloning the\n"
"Controller Pak connected to JoyPad 1.\n"
);

// Bonus would be to handle individual per game entries!
if (accessory_is_cpak[0]) {
component_main_text_draw(
networkfusion marked this conversation as resolved.
Show resolved Hide resolved
ALIGN_LEFT, VALIGN_TOP,
"\n"
"\n"
"\n"
"\n"
"\n"
"Controller Pak (1).\n"
" Pages: %d/%d. \n"
" Notes: %s.",
cpak_info.free_pages, CPAK_MAX_PAGES,
format_cpak_entries(cpak_info.entries)
);
}
else {
component_main_text_draw(
networkfusion marked this conversation as resolved.
Show resolved Hide resolved
ALIGN_LEFT, VALIGN_TOP,
"\n"
"\n"
"\n"
"\n"
"\n"
"Controller Pak (1).\n"
" Not inserted.\n"
" - If it is, retry inserting it a few times.\n"
" - Load another ROM that has a Controller Pak manager.\n"
);
}

if (accessory_is_cpak[0]) {
component_actions_bar_text_draw(
networkfusion marked this conversation as resolved.
Show resolved Hide resolved
ALIGN_LEFT, VALIGN_TOP,
"A: Clone to SD Card\n"
"B: Back"
);
}
else {
component_actions_bar_text_draw(
networkfusion marked this conversation as resolved.
Show resolved Hide resolved
ALIGN_LEFT, VALIGN_TOP,
"\n"
"B: Back"
);
}

rdpq_detach_show();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete functionality: draw.

The function contains a TODO comment for additional features and has room for improvements.

Do you want me to help complete this functionality or open a GitHub issue to track this task?

}

void view_joypad_controller_pak_init (menu_t *menu){

//TODO: handle all paks.
// check which paks are available
// JOYPAD_PORT_FOREACH (port) {
// accessory_is_cpak[port] = joypad_get_accessory_type(port) == JOYPAD_ACCESSORY_TYPE_CONTROLLER_PAK;
// }

if (joypad_get_accessory_type(JOYPAD_PORT_1) == JOYPAD_ACCESSORY_TYPE_CONTROLLER_PAK) {
accessory_is_cpak[JOYPAD_PORT_1] = JOYPAD_ACCESSORY_TYPE_CONTROLLER_PAK;
cpak_info_load(JOYPAD_PORT_1, &cpak_info);
}
}
Comment on lines +133 to +145
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete functionality: view_joypad_controller_pak_init.

The function contains a TODO comment for handling all paks and currently only checks the accessory type for JoyPad port 1.

Do you want me to help complete this functionality or open a GitHub issue to track this task?


void view_joypad_controller_pak_display (menu_t *menu, surface_t *display) {
process(menu);
draw(menu, display);
}
3 changes: 3 additions & 0 deletions src/menu/views/views.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ void view_settings_display (menu_t *menu, surface_t *display);
void view_rtc_init (menu_t *menu);
void view_rtc_display (menu_t *menu, surface_t *display);

void view_joypad_controller_pak_init (menu_t *menu);
void view_joypad_controller_pak_display (menu_t *menu, surface_t *display);

void view_flashcart_info_init (menu_t *menu);
void view_flashcart_info_display (menu_t *menu, surface_t *display);

Expand Down