Add note import and insert/replace

- Also cleanup file types
This commit is contained in:
Raphael Assenat 2015-10-25 15:21:45 -04:00
parent 3a65359501
commit 458b1a27e7
2 changed files with 204 additions and 9 deletions

View File

@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "mempak.h"
#define DEXDRIVE_DATA_OFFSET 0x1040
@ -21,6 +22,168 @@ mempak_structure_t *mempak_new(void)
return mpk;
}
static int mempak_findFreeNote(mempak_structure_t *mpk, entry_structure_t *entry_data, int *note_id)
{
int i;
if (!mpk)
return -1;
if (!entry_data)
return -1;
for (i=0; i<MEMPAK_NUM_NOTES; i++) {
if (0 != get_mempak_entry(mpk, i, entry_data)) {
return -1;
}
if (!entry_data->valid) {
if (note_id) {
*note_id = i;
}
return 0;
}
}
return -1;
}
/**
* \param mpk The memory pack to operate on
* \param notefile The filename of the note to load
* \param dst_note_id 0-15: (Over)write to specific note, -1: auto (first free)
* \param note_id Stores the id of the note that was used
*/
int mempak_importNote(mempak_structure_t *mpk, const char *notefile, int dst_note_id, int *note_id)
{
int free_blocks = get_mempak_free_space(mpk);
FILE *fptr;
unsigned char entry_data[32];
unsigned char *data = NULL;
entry_structure_t entry;
int res;
if (dst_note_id < -1 || dst_note_id > 15) {
fprintf(stderr, "Out of bound dst_note_id\n");
return -1;
}
printf("Current free blocks: %d\n", free_blocks);
fptr = fopen(notefile, "rb");
if (!fptr) {
perror("fopen");
return -1;
}
if (1 != fread(entry_data, 32, 1, fptr)) {
perror("fread");
fclose(fptr);
return -1;
}
/* I follow the same convention as bryc's javascript mempak editor[1]
* by looking for an inode number of 0xCAFE.
*
* [1] https://github.com/bryc/mempak
*
* If there are other note formats to support, this will need updating.
*/
if ((entry_data[0x06] == 0xCA) &&
(entry_data[0x07] == 0xFE))
{
entry_structure_t oldentry;
long filesize;
// Fixup the inode number (0xCAFE is invalid)
entry_data[0x06] = 0x00;
entry_data[0x07] = 0x05; // BLOCK_VALID_FIRST;
if (0 != mempak_parse_entry(entry_data, &entry)) {
fprintf(stderr, "Error loading note (invalid)\n");
fclose(fptr);
return -1;
}
fseek(fptr, 0, SEEK_END);
filesize = ftell(fptr);
fseek(fptr, 32, SEEK_SET);
// Remove the note header
filesize -= 32;
if (filesize % MEMPAK_BLOCK_SIZE) {
fprintf(stderr, "Invalid note file size\n");
fclose(fptr);
return -1;
}
entry.blocks = filesize / MEMPAK_BLOCK_SIZE;
printf("Note size: %d blocks\n", entry.blocks);
printf("Note name: %s\n", entry.name);
if (entry.blocks > free_blocks) {
fprintf(stderr, "Not enough space (note is %d blocks and only %d free blocks in mempak)\n",
entry.blocks, free_blocks);
fclose(fptr);
return -1;
}
data = calloc(1, entry.blocks * MEMPAK_BLOCK_SIZE);
if (!data) {
perror("calloc");
fclose(fptr);
return -1;
}
if (1 != fread(data, entry.blocks * MEMPAK_BLOCK_SIZE, 1, fptr)) {
perror("could not load note data");
free(data);
fclose(fptr);
return -1;
}
if (dst_note_id == -1) { // Auto (first free note)
if (0 != mempak_findFreeNote(mpk, &oldentry, note_id)) {
fprintf(stderr, "Could not find an empty note\n");
free(data);
fclose(fptr);
return -1;
}
} else { // Specific note
get_mempak_entry(mpk, dst_note_id, &oldentry);
if (oldentry.valid) {
printf("Overwriting note %d\n", dst_note_id);
delete_mempak_entry(mpk, &oldentry);
} else {
fprintf(stderr, "No note id %d\n", dst_note_id);
free(data);
fclose(fptr);
return -1;
}
if (note_id)
*note_id = dst_note_id;
}
res = write_mempak_entry_data(mpk, &entry, data);
if (res != 0) {
fprintf(stderr, "Failed to write note (error %d)\n", res);
free(data);
fclose(fptr);
return -1;
}
return 0;
} else {
fprintf(stderr, "Input file does not appear to be in a supported format.\n");
}
if (data)
free(data);
fclose(fptr);
return -1;
}
int mempak_exportNote(mempak_structure_t *mpk, int note_id, const char *dst_filename)
{
FILE *fptr;
@ -45,7 +208,7 @@ int mempak_exportNote(mempak_structure_t *mpk, int note_id, const char *dst_file
return -1;
}
fptr = fopen(dst_filename, "w");
fptr = fopen(dst_filename, "wb");
if (!fptr) {
perror("fopen");
return -1;
@ -56,8 +219,8 @@ int mempak_exportNote(mempak_structure_t *mpk, int note_id, const char *dst_file
*
* [1] https://github.com/bryc/mempak
*/
note_header.raw_data[0x07] = 0xCA;
note_header.raw_data[0x08] = 0xFE;
note_header.raw_data[0x06] = 0xCA;
note_header.raw_data[0x07] = 0xFE;
fwrite(note_header.raw_data, 32, 1, fptr);
fwrite(databuf, MEMPAK_BLOCK_SIZE, note_header.blocks, fptr);
@ -73,7 +236,7 @@ int mempak_saveToFile(mempak_structure_t *mpk, const char *dst_filename, unsigne
if (!mpk)
return -1;
fptr = fopen(dst_filename, "w");
fptr = fopen(dst_filename, "wb");
if (!fptr) {
perror("fopen");
return -1;
@ -143,9 +306,9 @@ mempak_structure_t *mempak_loadFromFile(const char *filename)
/* Raw binary images. Those can contain more than one card's data. For
* instance, Mupen64 seems to contain four saves. (I suppose each 32kB block is
* for the virtual mempak of one controller) */
for (i=0; i<4; i++) {
for (i=1; i<=4; i++) {
if (file_size == 0x8000*i) {
num_images = i+1;
num_images = i;
printf("MPK file Contains %d image(s)\n", num_images);
if (file_size == 0x8000) {
mpk->file_format = MPK_FORMAT_MPK;
@ -200,3 +363,30 @@ void mempak_free(mempak_structure_t *mpk)
free(mpk);
}
const char *mempak_format2string(int fmt)
{
switch(fmt)
{
case MPK_FORMAT_MPK: return "MPK";
case MPK_FORMAT_MPK4: return "MPK4";
case MPK_FORMAT_N64: return "N64";
case MPK_FORMAT_INVALID: return "Invalid";
default:
return "Unknown";
}
}
int mempak_string2format(const char *str)
{
if (0 == strcasecmp(str, "mpk"))
return MPK_FORMAT_MPK;
if (0 == strcasecmp(str, "mpk4"))
return MPK_FORMAT_MPK4;
if (0 == strcasecmp(str, "n64"))
return MPK_FORMAT_N64;
return MPK_FORMAT_INVALID;
}

View File

@ -5,9 +5,10 @@
#define MAX_NOTE_COMMENT_SIZE 257 // including 0 termination
#define MPK_FORMAT_MPK 0
#define MPK_FORMAT_MPK4 1 // MPK + 3 times 32kB padding
#define MPK_FORMAT_N64 2
#define MPK_FORMAT_INVALID 0
#define MPK_FORMAT_MPK 1
#define MPK_FORMAT_MPK4 2 // MPK + 3 times 32kB padding
#define MPK_FORMAT_N64 3
typedef struct mempak_structure
{
@ -22,8 +23,12 @@ mempak_structure_t *mempak_loadFromFile(const char *filename);
int mempak_saveToFile(mempak_structure_t *mpk, const char *dst_filename, unsigned char format);
int mempak_exportNote(mempak_structure_t *mpk, int note_id, const char *dst_filename);
int mempak_importNote(mempak_structure_t *mpk, const char *notefile, int dst_note_id, int *note_id);
void mempak_free(mempak_structure_t *mpk);
int mempak_string2format(const char *str);
const char *mempak_format2string(int fmt);
#include "mempak_fs.h"
#endif // _mempak_h__