copcom/main.c

155 lines
3.4 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
const char* cs[3] = {"MOVE", "WAIT", "SKIP"};
unsigned int nlen(char* s, char c) {
unsigned int r = 0;
while(s[r] != c) r++;
return r;
}
int hexint(char* s) {
long r = 0;
int n;
for(int i = 0; i < strlen(s); i++) {
if(s[i] > 47 && s[i] < 58) n = s[i] - 48;
else if(s[i] > 64 && s[i] < 71) n = s[i] - 55;
else if(s[i] > 96 && s[i] < 103) n = s[i] - 87;
else return -1;
r <<= 4;
r |= n;
}
return r;
}
int intget(char* s, char c) {
int l = nlen(s, c);
char* ns = malloc(l + 1);
memcpy(ns, s, l);
int r;
ns[l] = 0;
if(*s == 'x') r = hexint(ns + 1);
else r = atoi(ns);
free(ns);
return r;
}
#define wslb(s) (intget(s, ' ') << 8) | ((intget(s + 1 + nlen(s, ' '), ' ') & 0x7F) << 1)
unsigned int toarr(char* d, unsigned int l, char*** line) {
unsigned int r = 0, c = 0;
*line = malloc(sizeof(char*));
for(; c < l; r++) {
unsigned int sl = nlen(d + c, '\n');
if(sl == 0) {
r--;
c++;
continue;
}
*line = realloc(*line, sizeof(char*) * r+1);
(*line)[r] = malloc(sl + 1);
memcpy((*line)[r], d + c, sl);
(*line)[r][sl] = 0;
c += sl + 1;
}
return r++;
}
int main(int argc, char** argv) {
if(argc < 2 || !(argc & 1)) exit(!!printf("arg format: [src] [out] [src] [out]\n"));
for(int ac = 0; ac < argc / 2; ac++) {
char* srcfile = argv[1 + (ac * 2)];
char* destfile = argv[2 + (ac * 2)];
printf("; -- %s > %s --\n", srcfile, destfile);
struct stat ssi, sdi;
int si = open(srcfile, O_RDONLY);
if(si == -1) {
printf("error opening %s: %s\n", srcfile, strerror(errno));
continue;
}
int di = open(destfile, O_CREAT | O_RDWR, 0666);
if(di == -1) {
printf("error opening %s: %s\n", destfile, strerror(errno));
if(si != -1) close(si);
continue;
}
fstat(si, &ssi);
fstat(di, &sdi);
char* sm = malloc(ssi.st_size);
read(si, sm, ssi.st_size);
close(si);
char** line;
unsigned int colnum = toarr(sm, ssi.st_size, &line);
uint16_t* o = malloc(4 * colnum);
for(unsigned int i = 0; i < colnum; i++) {
if(strlen(line[i]) < 3) goto err;
int command = 5;
for(int c = 0; c < 3; c++) if(*line[i] == "mws"[c]) command = c;
if(command == 5) goto err;
if(line[i][1] != ' ') goto err;
uint16_t l = 0, h = 0;
switch(command) {
case 0: // m
h = (intget(line[i] + 2, ' ') & 0xFF) << 1;
l = intget(line[i] + 3 + nlen(line[i] + 2, ' '), 0);
break;
case 1: // w
h = (((intget(line[i] + 2, ' ') & 0xFF) << 8)
| (intget(line[i] + 3 + nlen(line[i] + 2, ' '), ' ')
& 0x7F) << 1) | 1;
int c = nlen(line[i] + 2, ' ') + 3;
l = wslb(line[i] + c + nlen(line[i] + c, ' ') + 1);
break;
case 2: // s
h = (((intget(line[i] + 2, ' ') & 0xFF) << 8)
| (intget(line[i] + 3 + nlen(line[i] + 2, ' '), ' ')
& 0x7F) << 1) | 1;
c = nlen(line[i] + 2, ' ') + 3;
l = wslb(line[i] + c + nlen(line[i] + c, ' ') + 1) | 1;
break;
}
o[(i<<1)|1] = l;
o[(i<<1)] = h;
printf("dc.w $%04X, $%04X; decode %s (%s)\n", h, l, cs[command], line[i]);
}
goto end;
err:
for(unsigned int i = 0; i < colnum; i++) free(line[i]);
free(line);
close(di);
free(sm);
exit(!!printf("parse err\n"));
end:
for(unsigned int i = 0; i < colnum; i++) free(line[i]);
free(sm);
free(line);
ftruncate(di, 4 * colnum);
write(di, o, 4 * colnum);
close(di);
}
}