aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorryo <ryo@nopwd.lol>2024-12-30 16:11:32 +0000
committerryo <ryo@nopwd.lol>2024-12-30 16:11:32 +0000
commit24c328db90627881d7c293e1ba481c6bd96e31da (patch)
tree0b125ab8a8d443b7b9bfc1f7943db0a0fc29a1cb /main.c
Initial commitHEADmain
Diffstat (limited to 'main.c')
-rw-r--r--main.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..1e7d289
--- /dev/null
+++ b/main.c
@@ -0,0 +1,208 @@
+#define STB_DS_IMPLEMENTATION
+#include "stb_ds.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#define STREQ(s1, s2) (strcmp((s1), (s2)) == 0)
+#define STRMT(s) ((s)[0] == '\0')
+#define LINE_LEN 100
+
+typedef struct {
+ char lab[10];
+ char opc[4];
+ char opr[10];
+ bool ind;
+ int psu;
+} token_t;
+
+token_t tokenize(char *);
+int split(char *, char [4][10]);
+void extfname(char *, char *);
+
+int main(int argc, char** argv)
+{
+ struct { char *key; uint16_t value; } *hopc = NULL;
+ struct { char *key; uint16_t value; } *hlab = NULL;
+ struct { uint8_t key; uint16_t value; } *hopr = NULL;
+ token_t tkn;
+ FILE *inpf, *outf;
+ char *lines, *tlines;
+ char line[LINE_LEN], opc[4], out[10], ofname[10];
+ uint16_t lc, ins, addr;
+ uint8_t opr, i;
+ bool unknown, end;
+
+ if (argc < 2) {
+ puts("no input file");
+ return 1;
+ }
+
+ sh_new_strdup(hopc);
+ sh_new_strdup(hlab);
+ shdefault(hopc, -1);
+ shdefault(hlab, -1);
+
+ inpf = fopen("opcodes", "r");
+ for (i = 25; i > 0; --i) {
+ fscanf(inpf, "%s %x", opc, &addr);
+ shput(hopc, opc, addr);
+ }
+
+ lines = (char *)malloc(LINE_LEN*100*sizeof(char));
+ inpf = fopen(argv[1], "r");
+ lc = 0, opr = 0, end = false;
+ while (fgets(line, LINE_LEN, inpf) != NULL) {
+ tkn = tokenize(line);
+ if (STRMT(tkn.opc) && tkn.psu == 0)
+ continue;
+
+ if (!STRMT(tkn.lab)) {
+ hmput(hopr, shget(hlab, tkn.lab), lc);
+ shput(hlab, tkn.lab, lc);
+ }
+
+ switch (tkn.psu) {
+ case 1:
+ lc = strtol(tkn.opr, NULL, 16);
+ continue;
+ case 2:
+ ins = strtol(tkn.opr, NULL, 10);
+ break;
+ case 3:
+ ins = strtol(tkn.opr, NULL, 16);
+ break;
+ case 4:
+ end = true;
+ }
+ if (end) break;
+
+ if (!STRMT(tkn.opc)) {
+ ins = shget(hopc, tkn.opc);
+ if (tkn.ind) ins += 8;
+ if (!STRMT(tkn.opr)) {
+ ins = ins << 12;
+ addr = shget(hlab, tkn.opr);
+ if (addr == 0xffff) {
+ unknown = true;
+ addr = opr;
+ shput(hlab, tkn.opr, opr++);
+ }
+ ins = ins | addr;
+ }
+ }
+
+ sprintf(out, "%03x %04x\n", lc, ins);
+ if (unknown) {
+ out[5] = '?';
+ unknown = false;
+ }
+
+ strcat(lines, out);
+ lc++;
+ }
+ fclose(inpf);
+ shfree(hopc);
+ shfree(hlab);
+
+ tlines = lines;
+ while ((tlines = strchr(tlines, '?')) != NULL) {
+ opr = strtol(++tlines, NULL, 16);
+ addr = hmget(hopr, opr);
+ sprintf(out, "%03x", addr);
+ strncpy(--tlines, out, 3);
+ }
+
+ puts(lines);
+ extfname(argv[1], ofname);
+ outf = fopen(ofname, "w");
+ fputs(lines, outf);
+
+ fclose(outf);
+ hmfree(hopr);
+ free(lines);
+ return 0;
+}
+
+token_t tokenize(char *start)
+{
+ const char pseudo[][4] = { "ORG", "DEC", "HEX", "END" };
+ token_t tkn = { '\0', '\0', '\0', false, 0 };
+ char parts[4][10];
+ int n, pi = 0, i;
+
+ n = split(start, parts);
+ if (n == 0) return tkn;
+
+ if (parts[0][strlen(parts[0])-1] == ',') {
+ parts[0][strlen(parts[0])-1] = '\0';
+ strcpy(tkn.lab, parts[0]);
+ pi++; n--;
+ if (n <= 0) return tkn;
+ }
+
+ for (i = 3; i >= 0; --i) {
+ if (STREQ(parts[pi], pseudo[i])) {
+ tkn.psu = i + 1; pi++;
+ if (n-- > 0)
+ strcpy(tkn.opr, parts[pi]);
+ return tkn;
+ }
+ }
+
+ if (parts[pi][0] != '\0') {
+ strcpy(tkn.opc, parts[pi++]); n--;
+ if (n > 0) {
+ strcpy(tkn.opr, parts[pi++]);
+ n--;
+ }
+ }
+
+ if (STREQ(parts[pi], "I"))
+ if (n-- > 0) tkn.ind = true;
+
+ return tkn;
+}
+
+int split(char *start, char list[4][10])
+{
+ int si = 0, wi = 0, li = 0;
+ char c;
+ do {
+ c = start[si++];
+ if (c == '\n' || c == '/') {
+ if (wi)
+ list[li++][wi] = '\0';
+ break;
+ }
+ if (c == ' ' || c == '\t') {
+ if (wi) {
+ list[li++][wi] = '\0';
+ wi = 0;
+ }
+ continue;
+ }
+ list[li][wi++] = c;
+ } while (c != '\0');
+ return li;
+}
+
+void extfname(char *path, char *fname)
+{
+ int si = 0, i;
+ char c;
+ for (i = 0; path[i] != '\0'; ++i) {
+ c = path[i];
+ fname[si++] = c;
+ if (c == '/') si = 0;
+ if (c == '.') {
+ si--;
+ break;
+ }
+ }
+ fname[si] = '\0';
+}
+