Skip to content

Commit

Permalink
feat(project): add option to create json files
Browse files Browse the repository at this point in the history
add support to create instance json files for the Analogue Pocket
  • Loading branch information
boogermann committed Sep 23, 2022
1 parent b300147 commit 2a48893
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 32 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ endif ()

# Project Information
project(ORCA
VERSION "0.1.0"
VERSION "0.2.0"
DESCRIPTION "Open ROM Conversion Assistant"
HOMEPAGE_URL "https://github.com/opengateware/tools-orca"
LANGUAGES C)
Expand Down
12 changes: 4 additions & 8 deletions src/arc.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@
#include "globals.h"
#include "utils.h"

#define MAX_LINE_LENGTH 256
#define MAX_CONTENT_LENGTH 25
#define MAX_CONF_OPT_LENGTH 128

char *format_bits(t_mra *mra, t_dip *dip) {
char buffer[256] = "O";
int start = 1;
Expand Down Expand Up @@ -70,8 +66,8 @@ char *format_bits(t_mra *mra, t_dip *dip) {
}

int check_ids_len(t_dip *dip) {
int nlen;
int tlen;
unsigned long nlen;
unsigned long tlen;
char copy[MAX_LINE_LENGTH];
char *tok;

Expand All @@ -80,7 +76,7 @@ int check_ids_len(t_dip *dip) {
tok = strtok(copy, ",");
tlen = nlen;
while(tok) {
int j = strlen(tok);
unsigned long j = strlen(tok);
tlen += j + 1;
if(tlen > MAX_CONF_OPT_LENGTH) {
return 1;
Expand Down Expand Up @@ -146,7 +142,7 @@ int write_arc(t_mra *mra, char *filename) {
fwrite(buffer, 1, n, out);

if(mra->switches.n_dips && mra->switches.defaults) {
n = snprintf(buffer, MAX_LINE_LENGTH, "DEFAULT=0x%llX\n", mra->switches.defaults << mra->switches.base);
n = snprintf(buffer, MAX_LINE_LENGTH, "DEFAULT=0x%X\n", mra->switches.defaults << mra->switches.base);
fwrite(buffer, 1, n, out);
}
if(mra->switches.page_id && mra->switches.page_name) {
Expand Down
6 changes: 6 additions & 0 deletions src/arc.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@

#include "mra.h"

#define MAX_LINE_LENGTH 256
#define MAX_CONTENT_LENGTH 25
#define MAX_CONF_OPT_LENGTH 128

int write_arc(t_mra *mra, char *filename);
char *format_bits(t_mra *mra, t_dip *dip);
int check_ids_len(t_dip *dip);

#endif
110 changes: 110 additions & 0 deletions src/json.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*******************************************************************************
* SPDX-License-Identifier: MPL-2.0
* SPDX-FileType: SOURCE
* SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors
*******************************************************************************
*
* ORCA (Open ROM Conversion Assistant)
* Copyright (c) 2022, OpenGateware authors and contributors (see AUTHORS file)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*
******************************************************************************/

/*!*****************************************************************************
* @file build.cpp
* @brief
******************************************************************************/

#include <stdio.h>
#include <string.h>

#include "globals.h"
#include "arc.h"
#include "json.h"

int write_json(t_mra *mra, char *filename) {
FILE *out;
char buffer[MAX_JSON_LENGTH + 1];
int i, n;
unsigned int mod = 0;
char mode[8] = "";


out = fopen(filename, "wb");
if(out == NULL) {
fprintf(stderr, "Couldn't open %s for writing!\n", filename);
return -1;
}

i = mra_get_rom_by_index(mra, 1, 0);
if(i != -1 && mra->roms[i].n_parts == 1 && !mra->roms[i].parts[0].is_group) {
for(size_t k = mra->roms[i].parts[0].p.data_length; k-- > 0;) {
char temp[2 + 1] = "";
sprintf(temp, "%02X", mra->roms[i].parts[0].p.data[k]);
strcat(mode, temp);
}
sscanf(mode, "%x", &mod);
}

const char *json = "{\n"
"\t\"instance\": {\n"
"\t\t\"magic\": \"APF_VER_1\",\n"
"\t\t\"variant_select\": {\n"
"\t\t\t\"id\": 777,\n"
"\t\t\t\"select\": false\n"
"\t\t},\n"
"\t\t\"data_slots\": [\n"
"\t\t\t{\n"
"\t\t\t\t\"id\": 1,\n"
"\t\t\t\t\"filename\": \"%s.rom\"\n"
"\t\t\t}\n"
"\t\t],\n"
"\t\t\"memory_writes\": [\n"
"\t\t\t{\n"
"\t\t\t\t\"address\": \"0xfd000000\",\n"
"\t\t\t\t\"data\": \"0x%08x\"\n"
"\t\t\t},\n"
"\t\t\t{\n"
"\t\t\t\t\"address\": \"0xfe000000\",\n"
"\t\t\t\t\"data\": \"0x%02x\"\n"
"\t\t\t}\n"
"\t\t]\n"
"\t}\n"
"}";

n = snprintf(buffer, MAX_JSON_LENGTH, json, rom_basename, mra->switches.defaults << mra->switches.base, (mod != -1 ? mod : 0));
if(n >= MAX_JSON_LENGTH) {
printf("%s:%d: warning: line was truncated while writing in JSON file!\n", __FILE__, __LINE__);
}
fwrite(buffer, 1, n, out);

fclose(out);
return 0;
}

void write_interact(t_mra *mra) {
// if(mra->switches.page_id && mra->switches.page_name) {
// n = snprintf(buffer, MAX_JSON_LINE_LENGTH, "CONF=\"P%d,%s\"\n", mra->switches.page_id, mra->switches.page_name);
// fwrite(buffer, 1, n, out);
// }
// for(i = 0; i < mra->switches.n_dips; i++) {
// t_dip *dip = mra->switches.dips + i;
// if(!strstr(str_tolower(dip->name), "unused")) {
// if(dip->ids) {
// n = snprintf(buffer, MAX_JSON_LINE_LENGTH, "CONF=\"%s,%s,%s\"\n", format_bits(mra, dip), dip->name, dip->ids);
// } else {
// n = snprintf(buffer, MAX_JSON_LINE_LENGTH, "CONF=\"%s,%s\"\n", format_bits(mra, dip), dip->name);
// }
// if(n >= MAX_JSON_LINE_LENGTH) {
// printf("%s:%d: warning (%s): line was truncated while writing in JSON file!\n", __FILE__, __LINE__, mra->setname);
// continue;
// }
// fwrite(buffer, 1, n, out);
// } else {
// printf("warning (%s): \"%s\" dip setting skipped (unused)\n", mra->setname, dip->name);
// }
// }
}
28 changes: 28 additions & 0 deletions src/json.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*******************************************************************************
* SPDX-License-Identifier: MPL-2.0
* SPDX-FileType: SOURCE
* SPDX-FileCopyrightText: (c) 2022, OpenGateware authors and contributors
*******************************************************************************
*
* ORCA (Open ROM Conversion Assistant)
* Copyright (c) 2022, OpenGateware authors and contributors (see AUTHORS file)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*
******************************************************************************/

/*!*****************************************************************************
* @file build.cpp
* @brief
******************************************************************************/

#ifndef ORCA_JSON_H
#define ORCA_JSON_H

#define MAX_JSON_LENGTH 8192

int write_json(t_mra *mra, char *filename);

#endif // ORCA_JSON_H
57 changes: 40 additions & 17 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "rom.h"
#include "utils.h"
#include "version.h"
#include "json.h"

int trace = 0;
int verbose = 0;
Expand All @@ -40,31 +41,33 @@ void print_version() {
void print_usage() {
printf(PROJECT_NAME " v%s [%s] (%s)\n", PROJECT_VER, BUILD_REF, BUILD_DATE);
printf("Usage:\n");
printf(" orca [-vlzoOaA] <recipe.xml>\n");
printf("\nConvert ROM recipes to a single file for usage with arcade cores.\nOptionally creates the associated support files.\n\n");
printf(" orca [-vlzoOaAJ] <recipe.xml>\n");
printf("\nConvert ROM recipes to a single file for usage with arcade cores.\nOptionally creates the associated metadata files.\n\n");
printf("Options:\n");
printf(" -h\t\tthis help.\n");
printf(" -v\t\twhen it is the only parameter, display version information and exit. Otherwise, set Verbose on (default: off).\n");
printf(" -l\t\tlist recipe content instead of creating the ROM file.\n");
printf(" -z directory\tadd directory to include zip files. Directories added with -z have priority over the current dir.\n");
printf(" -o filename\tset the output ROM file name. Overrides the internal generation of the filename.\n");
printf(" -O directory\tset the output directory. By default, ROM and ARC files are created in the current directory.\n");
printf(" -a filename\tset the output ARC file name. Overrides the internal generation of the filename.\n");
printf(" -O directory\tset the output directory. By default, ROM and metadata files are created in the current directory.\n");
printf(" -a filename\tset the output metadata file name. Overrides the internal generation of the filename.\n");
printf(" -A\t\tcreate ARC file. This is done in addition to creating the ROM file.\n");
printf(" -s\t\tskip ROM creation. This is useful if only the ARC file is required.\n");
printf(" -J\t\tcreate JSON file. This is done in addition to creating the ROM file.\n");
printf(" -s\t\tskip ROM creation. This is useful if only the metadata file is required.\n");
}

int main(int argc, char **argv) {
char *rom_filename = NULL;
char *arc_filename = NULL;
char *output_dir = NULL;
char *output_dir = NULL;
char *mra_filename;
char *mra_basename;
t_string_list *dirs = string_list_new(NULL);
int i, res;
int dump_mra = 0;
int dump_rom = -1;
int dump_mra = 0;
int dump_rom = -1;
int create_arc = 0;
int create_json = 0;

if(trace > 0) {
for(i = 0; i < argc; i++) {
Expand All @@ -83,24 +86,21 @@ int main(int argc, char **argv) {
// put ':' in the starting of the
// string so that program can
// distinguish between '?' and ':'
while((opt = getopt(argc, argv, ":vlhAo:a:O:z:s")) != -1) {
while((opt = getopt(argc, argv, ":vlhAJo:a:O:z:s")) != -1) {
switch(opt) {
case 'v': verbose = -1; break;
case 'l': dump_mra = -1; break;
case 'A': create_arc = -1; break;
case 'J': create_json = -1; break;
case 'z': string_list_add(dirs, replace_backslash(optarg)); break;
case 'O': output_dir = replace_backslash(strndup(optarg, 1024)); break;
case 'o': rom_filename = replace_backslash(strndup(optarg, 1024)); break;
case 'a': arc_filename = replace_backslash(strndup(optarg, 1024)); break;
case 's': dump_rom = 0; break;
case 'h': print_usage(); exit(0);
case ':':
printf("option needs a value\n");
case '?':
printf("unknown option: %c\n", optopt);
default:
print_usage();
exit(-1);
case ':': printf("option needs a value\n");
case '?': printf("unknown option: %c\n", optopt);
default: print_usage(); exit(-1);
}
}

Expand Down Expand Up @@ -174,7 +174,6 @@ int main(int argc, char **argv) {
if(trace > 0) {
printf("create_arc set...\n");
}

if(arc_filename) {
if(output_dir) {
arc_filename = get_filename(output_dir, get_basename(arc_filename, 1), "arc");
Expand All @@ -195,6 +194,30 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
arc_filename = NULL;

}

if(create_json) {
if(trace > 0) {
printf("create_json set...\n");
}

char *arc_mra_filename = strdup(mra.name ? mra.name : mra_basename);
make_fat32_compatible(arc_mra_filename, 1);
arc_filename = get_filename(output_dir ? output_dir : ".", arc_mra_filename, "json");
free(arc_mra_filename);

if(verbose) {
printf("Creating JSON file %s\n", arc_filename);
}
res = write_json(&mra, arc_filename);
if(res != 0) {
printf("Writing JSON file failed with error code: %d\n. Retry without -J if you still want to create the ROM file.\n", res);
exit(EXIT_FAILURE);
}
arc_filename = NULL;


}
if(dump_rom) {
if(trace > 0) {
Expand Down
10 changes: 5 additions & 5 deletions src/mra.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,9 @@ int read_switches(XMLNode *node, t_switches *switches) {
// Read all attributes
for(i = 0; i < node->n_attributes; i++) {
XMLAttribute *attr = &node->attributes[i];
if(strncmp(attr->name, "base", 10) == 0) {
if(strncmp(attr->name, "base", 4) == 0) {
switches->base = strtol(strndup(attr->value, 256), NULL, 0);
} else if(strncmp(attr->name, "default", 8) == 0) {
} else if(strncmp(attr->name, "default", 7) == 0) {
int a, b, c, d, n; // up to four values
// Fix incorrect spaces
char *temp = attr->value;
Expand All @@ -264,17 +264,17 @@ int read_switches(XMLNode *node, t_switches *switches) {
if(n-- > 0) {
switches->defaults |= ((d & 0xff) << 24);
}
} else if(strncmp(attr->name, "page_id", 8) == 0) {
} else if(strncmp(attr->name, "page_id", 7) == 0) {
switches->page_id = strtol(strndup(attr->value, 256), NULL, 0);
} else if(strncmp(attr->name, "page_name", 10) == 0) {
} else if(strncmp(attr->name, "page_name", 9) == 0) {
switches->page_name = strndup(attr->value, 26);
}
}

// Read DIPs
for(i = 0; i < node->n_children; i++) {
XMLNode *child = node->children[i];
if(strncmp(child->tag, "dip", 4) == 0) {
if(strncmp(child->tag, "dip", 3) == 0) {
switches->n_dips++;
switches->dips = (t_dip *)realloc(switches->dips, sizeof(t_dip) * (switches->n_dips));
read_dip_switch(child, switches->dips + switches->n_dips - 1);
Expand Down
2 changes: 1 addition & 1 deletion src/mra.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ typedef struct s_dip {
typedef struct s_switches {
t_dip *dips;
int n_dips;
long long defaults;
uint32_t defaults;
int base;
int page_id;
char *page_name;
Expand Down

0 comments on commit 2a48893

Please sign in to comment.