From d592ce4834411a63c89670f7990e86ae5dbaf40f Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Mon, 29 Apr 2024 18:37:04 -0400 Subject: xex.c: add xex_get_run_addr() and xex_get_init_addr(). --- TODO | 3 ++- xex.c | 22 ++++++++++++++++++++++ xex.h | 8 ++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index bb1f1a6..d656b9a 100644 --- a/TODO +++ b/TODO @@ -2,7 +2,8 @@ for now: These may need library (xex.c) changes: xexcat: handle run/init addresses embedded in a segment longer than 2 bytes. -xexcat: handle or at least detect DOS 1.0 executables. +xexcat: handle or at least detect DOS 1.0 executables. currently + xex_fread_seg_header() will warn about them, but that's all. xexcat: warn if an an init address occurs before the code it references. or at least if it occurs before *any* code! diff --git a/xex.c b/xex.c index e4b66ce..8584286 100644 --- a/xex.c +++ b/xex.c @@ -114,6 +114,10 @@ int xex_fread_seg_header(xex_segment *seg, FILE *file) { if(d == EOF) return 0; addr = XEX_ADDR(c, d); + if(addr == 0x0984) { + fprintf(stderr, "xex_fread_seg_header(): warning: this might be a DOS 1.0 file (not supported)\n"); + } + if(addr == 0xffff) { seg->has_ff_header = 1; c = read_char(file); @@ -289,6 +293,24 @@ int xex_check_seg(xex_segment *seg) { return ret; } +static int xex_get_addr_from(xex_segment *seg, int location) { + int i; + + if(seg->start_addr > location) return -1; + if(seg->end_addr <= location) return -1; + + i = location - seg->start_addr; + return XEX_ADDR(seg->object[i], seg->object[i + 1]); +} + +int xex_get_run_addr(xex_segment *seg) { + return xex_get_addr_from(seg, XEX_RUNAD); +} + +int xex_get_init_addr(xex_segment *seg) { + return xex_get_addr_from(seg, XEX_INITAD); +} + char *xex_strerror(int err) { if(err < 0 || err >= XERR_MAXERR) err = XERR_MAXERR; diff --git a/xex.h b/xex.h index 2300481..2b113fc 100644 --- a/xex.h +++ b/xex.h @@ -104,6 +104,14 @@ int xex_get_object(xex_segment *seg, unsigned char *data); Returns true if segment is OK. */ int xex_check_seg(xex_segment *seg); +/* Get run address from a segment, if there is one. This can handle the case + where the address is embedded in a larger segment (that doesn't just consist + of 2 bytes loaded at RUNAD). Returns -1 if there is no run address. */ +int xex_get_run_addr(xex_segment *seg); + +/* Same as above, for init address. */ +int xex_get_init_addr(xex_segment *seg); + /* Get human-readable error message. If xex_errno is XSYSCALL, the system's strerror() is called. */ char *xex_strerror(int err); -- cgit v1.2.3