Skip to content

Commit

Permalink
Fixes #79
Browse files Browse the repository at this point in the history
  • Loading branch information
BlockoS committed Oct 11, 2023
1 parent 17aa773 commit ea39c5b
Show file tree
Hide file tree
Showing 17 changed files with 613 additions and 287 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ set(etripator_SRC
section/load.c
section/save.c
opcodes.c
comment.c
label.c
label/load.c
label/save.c
Expand All @@ -61,9 +62,8 @@ set(etripator_HDR
section/load.h
section/save.h
opcodes.h
comment.h
label.h
label/load.h
label/save.h
irq.h
memory.h
memorymap.h
Expand Down
28 changes: 19 additions & 9 deletions cli/etripator.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
#include <decode.h>
#include <irq.h>
#include <label.h>
#include <label/load.h>
#include <label/save.h>
#include <comment.h>
#include <memorymap.h>
#include <opcodes.h>
#include <rom.h>
#include <ipl.h>
#include <section.h>
#include <section/load.h>
#include <comment.h>

#include "options.h"

Expand Down Expand Up @@ -208,8 +208,19 @@ int main(int argc, const char **argv) {

section_sort(section, section_count);

comment_repository_t *comments_repository = comment_repository_create();
/* Load comments */
if(NULL != option.comments_in) {
for(i=0; option.comments_in[i]; i++) {
ret = comment_repository_load(option.comments_in[i], comments_repository);
if (!ret) {
ERROR_MSG("An error occured while loading comments from %s : %s", option.comments_in[i], strerror(errno));
goto error_3;
}
}
}

label_repository_t *repository = label_repository_create();

/* Load labels */
if (NULL != option.labels_in) {
for(i=0; option.labels_in[i]; i++) {
Expand Down Expand Up @@ -311,11 +322,11 @@ int main(int argc, const char **argv) {
/* Process opcodes */
uint16_t logical = section[i].logical;
do {
(void)decode(out, &logical, &section[i], &map, repository);
(void)decode(out, &logical, &section[i], &map, repository, comments_repository);
} while (logical < (section[i].logical+section[i].size));
fputc('\n', out);
} else {
ret = data_extract(out, &section[i], &map, repository);
ret = data_extract(out, &section[i], &map, repository, comments_repository);
if (!ret) {
// [todo]
}
Expand Down Expand Up @@ -351,13 +362,12 @@ int main(int argc, const char **argv) {

error_4:
label_repository_destroy(repository);
error_3:
comment_repository_destroy(comments_repository);
error_2:
memmap_destroy(&map);
error_1:
if(option.labels_in) {
free(option.labels_in);
option.labels_in = NULL;
}
release_cli_opt(&option);

for (i = 0; i < section_count; ++i) {
free(section[i].name);
Expand Down
24 changes: 19 additions & 5 deletions cli/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@

#include <argparse/argparse.h>

struct labels_in_payload {
struct payload_t {
size_t capacity;
size_t size;
const char ***array;
};

static int labels_opt_callback(struct argparse *self, const struct argparse_option *option) {
struct labels_in_payload *payload = (struct labels_in_payload*)option->data;
static int opt_callback(struct argparse *self, const struct argparse_option *option) {
struct payload_t *payload = (struct payload_t*)option->data;
size_t last = payload->size++;
if(payload->capacity <= payload->size) {
payload->capacity += 4;
Expand All @@ -49,15 +49,17 @@ int get_cli_opt(int argc, const char** argv, cli_opt_t* option) {
};

char *dummy;
struct labels_in_payload payload = { 0, 0, &option->labels_in };
struct payload_t labels_payload = { 0, 0, &option->labels_in };
struct payload_t comments_payload = {0, 0, &option->comments_in};

struct argparse_option options[] = {
OPT_HELP(),
OPT_BOOLEAN('i', "irq-detect", &option->extract_irq, "automatically detect and extract irq vectors when disassembling a ROM, or extract opening code and gfx from CDROM IPL data", NULL, 0, 0),
OPT_BOOLEAN('c', "cd", &option->cdrom, "cdrom image disassembly. Irq detection and rom. Header jump is not performed", NULL, 0, 0),
OPT_STRING('o', "out", &option->main_filename, "main asm file containing includes for all sections as long the irq vector table if the irq-detect option is enabled", NULL, 0, 0),
OPT_STRING('l', "labels", &dummy, "labels definition filename", labels_opt_callback, (intptr_t)&payload, 0),
OPT_STRING('l', "labels", &dummy, "labels definition filename", opt_callback, (intptr_t)&labels_payload, 0),
OPT_STRING(0, "labels-out", &option->labels_out, "extracted labels output filename. Otherwise the labels will be written to <in>.YYMMDDhhmmss.lbl", NULL, 0, 0),
OPT_STRING(0, "comments", &dummy, "comments description filename", opt_callback, (intptr_t)&comments_payload, 0),
OPT_END(),
};

Expand All @@ -70,6 +72,7 @@ int get_cli_opt(int argc, const char** argv, cli_opt_t* option) {
option->main_filename = "main.asm";
option->labels_in = NULL;
option->labels_out = NULL;
option->comments_in = NULL;

argparse_init(&argparse, options, usages, 0);
argparse_describe(&argparse, "\nEtripator : a PC Engine disassembler", " ");
Expand All @@ -95,3 +98,14 @@ int get_cli_opt(int argc, const char** argv, cli_opt_t* option) {
}
return 1;
}

/* Release allocated resources during command line parsing */
void release_cli_opt(cli_opt_t* option) {
if(option->comments_in) {
free(option->comments_in);
}
if(option->labels_in) {
free(option->labels_in);
}
memset(option, 0, sizeof(cli_opt_t));
}
4 changes: 4 additions & 0 deletions cli/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ typedef struct {
const char *main_filename;
const char *labels_out;
const char **labels_in;
const char **comments_in;
} cli_opt_t;

/* Extract command line options */
int get_cli_opt(int argc, const char** argv, cli_opt_t* option);

/* Release allocated resources during command line parsing */
void release_cli_opt(cli_opt_t* option);

#endif // ETRIPATOR_OPTIONS_H
213 changes: 213 additions & 0 deletions comment.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
/*
This file is part of Etripator,
copyright (c) 2009--2023 Vincent Cruz.
Etripator is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Etripator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Etripator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "comment.h"
#include "message.h"

#include <jansson.h>
#include "jsonhelpers.h"

#define COMMENT_ARRAY_INC 16

/**
* Comment repository.
*/
struct comment_repository_impl {
size_t size; /**< Size of comment repository */
size_t last; /**< Last element in the repository */
comment_t *comments; /**< Comments */
};

/**
* Get comment index by its address.
* \param [in] repository Coment repository.
* \param [in] logical Logical address.
* \param [in] page Memory page.
* \return comment index or -1 if the label was not found.
*/
static int comment_repository_index(comment_repository_t* repository, uint16_t logical, uint8_t page) {
size_t i;
for(i=0; i<repository->last; i++) {
if( (repository->comments[i].page == page) &&
(repository->comments[i].logical == logical) ) {
return (int)i;
}
}
return -1;
}

/* Create comment repository. */
comment_repository_t* comment_repository_create() {
comment_repository_t *repository;
repository = (comment_repository_t*)malloc(sizeof(comment_repository_t));
if(repository == NULL) {
ERROR_MSG("Failed to create comment repository: %s", strerror(errno));
} else {
repository->last = 0;
repository->comments = NULL;

repository->size = COMMENT_ARRAY_INC;
repository->comments = (comment_t*)malloc(repository->size * sizeof(comment_t));
if(repository->comments == NULL) {
ERROR_MSG("Failed to create comments: %s", strerror(errno));
comment_repository_destroy(repository);
free(repository);
repository = NULL;
}
}
return repository;
}

/* Release comment repository resources. */
void comment_repository_destroy(comment_repository_t* repository) {
repository->size = 0;
repository->last = 0;

if(repository->comments != NULL) {
for(int i=0; i<repository->last; i++) {
if(repository->comments[i].text) {
free(repository->comments[i].text);
}
}
free(repository->comments);
repository->comments = NULL;
}
}

/* Add comment to repository. */
int comment_repository_add(comment_repository_t* repository, uint16_t logical, uint8_t page, const char *text) {
int ret = 1;
int index = comment_repository_index(repository, logical, page);
if(index >= 0) {
WARNING_MSG("Duplicate comment for logical address $%04x in page $%02x", logical, page);
} else {
/* Expand arrays if necessary */
if(repository->last >= repository->size) {
comment_t *ptr;
repository->size += COMMENT_ARRAY_INC;
ptr = (comment_t*)realloc(repository->comments, repository->size * sizeof(comment_t));
if(ptr == NULL) {
comment_repository_destroy(repository);
ret = 0;
} else {
repository->comments = ptr;
}
}
if(ret != 0) {
/* Push addresses & text */
repository->comments[repository->last].logical = logical;
repository->comments[repository->last].page = page;
repository->comments[repository->last].text = strdup(text);

++repository->last;
}
}
return ret;
}

/* Find a comment by its address. */
int comment_repository_find(comment_repository_t* repository, uint16_t logical, uint8_t page, comment_t *out) {
int index = comment_repository_index(repository, logical, page);
if(index < 0) {
memset(out, 0, sizeof(comment_t));
return 0;
}
memcpy(out, &repository->comments[index], sizeof(comment_t));
return 1;
}

/* Get the number of comments stored in the repository. */
int comment_repository_size(comment_repository_t* repository) {
return repository ? (int)repository->last : 0;
}

/* Retrieve the comment at the specified index. */
int comment_repository_get(comment_repository_t* repository, int index, comment_t *out) {
if((repository != NULL) && ((index >= 0) && (index < (int)repository->last))) {
memcpy(out, &repository->comments[index], sizeof(comment_t));
return 1;
} else {
memset(out, 0, sizeof(comment_t));
return 0;
}
}

/* Delete comments. */
int comment_repository_delete(comment_repository_t* repository, uint16_t first, uint16_t end, uint8_t page) {
size_t i;
for(i=0; i<repository->last; i++) {
if( (repository->comments[i].page == page) &&
(repository->comments[i].logical >= first) &&
(repository->comments[i].logical < end) ) {
if(repository->last) {
repository->last--;
if(repository->comments[i].text) {
free(repository->comments[i].text);
}
memcpy(&repository->comments[i], &repository->comments[repository->last], sizeof(comment_t));
i--;
}
}
}
return 1;}

/* Load comments from file. */
int comment_repository_load(const char* filename, comment_repository_t* repository) {
json_t* root;
json_error_t err;
json_t* value;
int ret = 0, index = 0;
root = json_load_file(filename, 0, &err);
if(!root) {
ERROR_MSG("Failed to parse %s: %s", filename, err.text);
} else {
if(!json_is_array(root)) {
ERROR_MSG("Array expected.");
} else for (index = 0, ret = 1; ret && (index < json_array_size(root)) && (value = json_array_get(root, index)); index++) {
ret = 0;
if(!json_is_object(value)) {
ERROR_MSG("Expected object.");
} else {
int num;
// logical
json_t *tmp = json_object_get(value, "logical");
if(!json_validate_int(tmp, &num)) {
ERROR_MSG("Invalid or missing logical address.");
} else if((num < 0) || (num > 0xffff)) {
ERROR_MSG("Logical address out of range.");
} else {
uint16_t logical = (uint16_t)num;
// page
tmp = json_object_get(value, "page");
if(!json_validate_int(tmp, &num)) {
ERROR_MSG("Invalid or missing page.");
} else {
// text (same format as section/label description)
const char* text = json_load_description(value, "text");
if((num < 0) || (num > 0xff)) {
ERROR_MSG("Page value out of range.");
} else if(comment_repository_add(repository, logical, (uint8_t)num, text)) {
ret = 1;
}
}
}
}
}
json_decref(root);
}
return ret;
}
Loading

0 comments on commit ea39c5b

Please sign in to comment.