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

[Suggestion] Add syntax for uploading a portion of a file in UNFLoader. #111

Open
DavidSM64 opened this issue May 31, 2023 · 1 comment
Open
Assignees
Labels
UNFLoader This is related to the UNFLoader tool USB Library This is related to the USB library (usb.c)

Comments

@DavidSM64
Copy link
Contributor

Expected Behavior

Currently, you can only upload an entire binary file by surrounding a path with @ symbols when you send a command through UNFLoader. I'd like to be able to send a range of bytes of the file.

Possible Solution

I'm thinking it could be implemented like: @file.bin[start:end]@. The actual syntax doesn't really matter to me, just having the feature would be nice.

Context (Environment)

I recently added hot-reloading support to Diddy Kong Racing, in which I only reload the first megabyte of the ROM instead of the entire thing. During the building of the ROM, I added an extra step at the end to create a new file that contains only the first megabyte of the ROM to upload. I'm not actually monitoring if the ROM itself has changed for the hot reload, but instead I'm monitoring that copy.

Possible Implementation

debug_send() in UNFLoader/debug.c would need to be modified just before the fopen.

I made a function that can parse the range and should be easy to slot in:

/*==============================
    parse_file_range
    Parses out the file range syntax `[start:end]` for a given token if it exists.
    Note: end may be larger than the file size.
    @param token to parse (from debug_send). The range syntax will get removed after the function completes.
    @param The outputted start position of the file (0 by default)
    @param The outputted end position of the file. (4294967295 by default)
==============================*/
void parse_file_range(char *token, uint32_t *start, uint32_t *end)
{
    char *bracketOpen;
    char *bracketClose;
    char *colon;
    char *tokenEnd;
    char *number;
    
    bracketOpen  = strchr(token, '[');
    colon        = strchr(token, ':');
    bracketClose = strchr(token, ']');
    
    // Default values, representing the entire file.
    *start = 0;
    *end   = 4294967295; // Largest uint32_t value.
    
    // Check if there is a file range.
    if(!bracketOpen && !colon && !bracketClose) {
        return;
    }
    
    // Check for obvious syntax errors.
    if(!bracketOpen || !colon || !bracketClose || 
        (bracketClose < bracketOpen) || 
        (bracketClose < colon) || 
        (colon < bracketOpen)) 
    {
        terminate("Invalid file range syntax.");
    }
    
    // Fix token
    tokenEnd = bracketOpen;
    while(tokenEnd[-1] == ' ') tokenEnd--; // Exclude whitespace
    *tokenEnd = '\0'; // Make sure the token ends up being just the filepath.
    
    // Get start & end positions
    number = bracketOpen + 1;
    while(*number == ' ') number++; // skip over whitespace
    if(*number != ':')
    {
        *start = strtol(number, 0, 0);
    }
    number = colon + 1;
    while(*number == ' ') number++; // skip over whitespace
    if(*number != ']')
    {
        *end = strtol(number, 0, 0);
    }
}

Here are a few examples of it's usage:

char token[64] = "file.bin[16:0x1234]";
uint32_t start, end;
parse_file_range(token, &start, &end);
printf("%s, %d, %d\n", token, start, end); // Output: file.bin, 16, 4660
char token[64] = "file.bin[:0x100000]";
uint32_t start, end;
parse_file_range(token, &start, &end);
printf("%s, %d, %d\n", token, start, end); // Output: file.bin, 0, 1048576
char token[64] = "file.bin[250:]";
uint32_t start, end;
parse_file_range(token, &start, &end);
printf("%s, %d, %d\n", token, start, end); // Output: file.bin, 250, 4294967295
char token[64] = "file.bin";
uint32_t start, end;
parse_file_range(token, &start, &end);
printf("%s, %d, %d\n", token, start, end); // Output: file.bin, 0, 4294967295

Note that file.bin[:] would have the same output as file.bin.

You would need to check the bounds to the size of the file. if end is larger than the size of the file, which it is by default, then you'd need to overwrite end with the size of the file.

@buu342 buu342 self-assigned this May 31, 2023
@buu342 buu342 added USB Library This is related to the USB library (usb.c) UNFLoader This is related to the UNFLoader tool labels May 31, 2023
@buu342
Copy link
Owner

buu342 commented May 31, 2023

Sounds like a good feature to have. We'd have to think about how (or if) we should expose the file's offsets on the N64 side. Perhaps this data could be included next to the @ syntax already in use by USB reading.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
UNFLoader This is related to the UNFLoader tool USB Library This is related to the USB library (usb.c)
Projects
None yet
Development

No branches or pull requests

2 participants