void Disasm(uint8_t* ram, uint32_t start) { LogV("starting disassembly at: 0x%08x", start); uint32_t pc = start; int end = 1024 * 1024 * 16; while(ram[--end] == 0); while(pc <= end){ int hasRead = 0; uint8_t read8(){ hasRead++; return ram[pc++]; } uint32_t read16(){ uint16_t ret = read8(); ret |= read8() << 8; return ret; } uint32_t read32(){ uint32_t ret = read8(); ret |= read8() << 8; ret |= read8() << 16; ret |= read8() << 24; return ret; } DIns ins = read8(); LAssert(ins < DINS_NUM, "illegal instruction: 0x%02x", ins); int n = printf("\t%s ", dinsNames[ins]); for(int i = 0; i < InsNumOps(ins); i++){ DVals op = read8(); LAssert(op < DVALS_NUM, "illegal operand value: 0x%02x", op); char numStr[64] = {0}; if(OpHasNextWord(op)) sprintf(numStr, "0x%02x", read32()); LogD("op: %d", op); char str[64]; n += printf("%s", StrReplace(str, valNames[op], "nw", numStr)); if(i < InsNumOps(ins) - 1) n += printf(", "); } printf("%*s", 40 - n, "; "); printf("0x%08x | ", pc - hasRead); for(int i = 0; i < hasRead; i++) printf("%02x ", ram[pc - hasRead + i]); printf("\n"); } }
int main(int argc, char** argv) { const char* usage = "usage: %s (-vX | -d) [dcpu-16 binary]"; LAssert(argc >= 2, usage, argv[0]); logLevel = 2; const char* file = NULL; unsigned start = 0; int numFiles = 0; for(int i = 1; i < argc; i++){ char* v = argv[i]; if(v[0] == '-'){ if(!strcmp(v, "-h")){ LogI(usage, argv[0]); LogI(" "); LogI("Available flags:"); LogI(" -vX set log level, where X is [0-5] - default: 2"); LogI(" -sX start disassembly at address X - default 0"); return 0; } else if(sscanf(v, "-v%d", &logLevel) == 1){} else if(sscanf(v, "-s0x%x", &start) || sscanf(v, "-s%d", &start) == 1){} else{ LogF("No such flag: %s", v); return 1; } }else{ numFiles++; file = v; } } LAssert(numFiles == 1, "Please specify one file to disassemble"); // Allocate 16MB ROM/RAM uint8_t* ram = calloc(1, 1024 * 1024 * 16); ReadFile(ram, 1024 * 1024 * 16, file); Disasm(ram, start); free(ram); }
Apu* Apu_Create(Mem* mem) { Apu* me = calloc(1, sizeof(Apu)); LAssert(me, "could not allocate ram for APU"); me->mem = mem; me->nChannels = 32; return me; }
void WriteRam(uint16_t* ram, const char* filename, uint16_t end, DByteOrder bo) { FILE* out = fopen(filename, "wb"); LAssert(out, "could not open new file for writing: %s", filename); for(int i = 0; i < end + 1; i++){ if(bo == DBO_LittleEndian){ LogD("%02x %02x", ram[i] & 0xff, (ram[i] >> 8) & 0xff); fputc(ram[i] & 0xff, out); fputc((ram[i] >> 8) & 0xff, out); } else {
void WriteRam(uint16_t* ram, const char* filename, uint16_t end) { FILE* out = fopen(filename, "w"); LAssert(out, "could not open new file for writing: %s", filename); for(int i = 0; i < end + 1; i++){ fputc(ram[i] & 0xff, out); fputc(ram[i] >> 8, out); } fclose(out); }
int main(int argc, char** argv) { LAssert(argc == 4, "usage: %s [steps] [amplitude] [outfile]", argv[0]); FILE* f = fopen(argv[3], "w"); LAssert(f, "could not open output file"); float t = 0, amp = atof(argv[2]); int n = atoi(argv[1]); for(int i = 0; i < n; i++){ int32_t v = (sinf(t) * amp); LogD("%d", v); fputc(v & 0xff, f); fputc((v >> 8) & 0xff, f); fputc((v >> 16) & 0xff, f); fputc((v >> 24) & 0xff, f); t += ((float)M_PI * 2.0f) / (float)n; } fclose(f); }
Reader* Reader_CreateFromBuffer(char* buffer, int len, const char* name, int startLineNum) { Reader* me = calloc(1, sizeof(Reader)); LAssert(me, "could not allocate ram for reader"); me->Get = Reader_GetB; me->filename = strdup(name); me->lineNumber = startLineNum; me->buffer = buffer; me->len = len; return me; }
int LoadRamMax(uint16_t* ram, const char* filename, uint16_t lastAddr, DByteOrder bo) { FILE* f = fopen(filename, "r"); LAssert(f, "could not open file: %s", filename); int addr = 0; for(;;){ int c1 = 0, c2 = 0; if((c1 = fgetc(f)) == EOF || (c2 = fgetc(f)) == EOF) break; if(bo == DBO_LittleEndian) ram[addr] = (c2 & 0xff) << 8 | (c1 & 0xff); else ram[addr] = (c1 & 0xff) << 8 | (c2 & 0xff); if(addr >= lastAddr) break; addr++; } fclose(f); return (int)addr + 1; }
Reader* Reader_CreateFromFile(const char* filename) { Reader* me = calloc(1, sizeof(Reader)); LAssert(me, "could not allocate ram for reader"); me->Get = Reader_GetF; FILE* in = fopen(filename, "r"); if(!in){ free(me); return NULL; } me->filename = strdup(filename); me->f = in; return me; }
int main(int argc, char** argv) { logLevel = 2; int atFile = 0; unsigned addr = 0; unsigned lastAddr = 0xffff; bool debugSymbols = false; char c; DByteOrder byteOrder = DBO_LittleEndian; const char* files[2] = {NULL, NULL}; const char* usage = "usage: %s (-vX | -h | -sX | -d | -eX) [dasm file] [out binary]"; for(int i = 1; i < argc; i++){ char* v = argv[i]; if(STARTSWITH(v, '-')){ if(!strcmp(v, "-h")){ LogI(usage, argv[0]); LogI(" "); LogI("Available flags:"); LogI(" -vX set log level, where X is [0-5] - default: 2"); LogI(" -sX set assembly start address [0-FFFF] - default 0"); LogI(" -h show this help message"); LogI(" -d generate debug symbols"); LogI(" -eX set endianness of output, where X is [l | b] default: l"); return 0; } else if(sscanf(v, "-v%d", &logLevel) == 1){} else if(sscanf(v, "-s%x", &addr) == 1){} else if(sscanf(v, "-e%1c", &c) == 1){ byteOrder = c == 'l' ? DBO_LittleEndian : DBO_BigEndian; } else if(!strcmp(v, "-d")){ debugSymbols = true; } else{ LogF("No such flag: %s", v); return 1; } }else{ LAssert(atFile < 2, "Please specify exactly one input file and one output file"); files[atFile++] = v; } } LAssert(argc >= 3 && files[0] && files[1], usage, argv[0]); LAssert(addr <= 0xffff, "Assembly start address must be within range 0 - 0xFFFF (not %x)", addr); // Allocate 64 kword RAM file uint16_t* ram = calloc(1, sizeof(uint16_t) * 0x10000); Dasm* d = Dasm_Create(); if(debugSymbols){ char tmp[4096]; sprintf(tmp, "%s.dbg", files[1]); d->debugFile = fopen(tmp, "w"); LogV("Opening debug file: %s", tmp); LAssert(d->debugFile, "could not open file: %s", tmp); } uint16_t len = Dasm_Assemble(d, files[0], ram, addr, lastAddr); if(d->debugFile) fclose(d->debugFile); Dasm_Destroy(&d); if(logLevel == 0) DumpRam(ram, len - 1); LogV("Writing to: %s", files[1]); WriteRam(ram, files[1], len - 1, byteOrder); free(ram); return 0; }
char* GetToken(Hasm* me, char* line, char* token) { // skip spaces etc. while((*line <= 32 || *line == ',') && *line != 0) line++; // read into token until the next space or end of string int at = 0; int idx = 0; char expecting = 0; char start[] = "\"'["; char end[] = "\"']"; char stop[] = "()"; // already at the end of the line if(*line == 0){ *token = 0; return line; } // stop if the first character is a stop char if(strchr(stop, *line)){ *token = *line; token[1] = 0; return line + 1; } while((expecting || (*line > 32 && *line != ',')) && *line != 0){ if(*line == '\\'){ line++; LAssert(*line != 0, "can't end a line with escaping backslash"); }else{ if(expecting){ if(*line == expecting) expecting = 0; }else{ if((idx = StrIndexOfChr(start, *line)) != -1) expecting = end[idx]; else if(strchr(stop, *line)){ break; } } } token[at++] = *(line++); } LAssertError(!expecting, "unterminated quotation, expected: '%c'", expecting); token[at] = '\0'; // TODO this is broken, eg. [MY_DEFINE] doesn't work // Handle defines /*Define* it; Vector_ForEach(*me->defines, it){ if(!strcmp(token, it->searchReplace[0])){ strcpy(token, it->searchReplace[1]); } }*/ return line; }
int main(int argc, char** argv) { logLevel = 2; int atFile = 0; int romSize = 1024 * 1024 * 16; unsigned addr = 0; bool debugSymbols = false; const char* files[2] = {NULL, NULL}; const char* usage = "usage: %s (-vX | -h | -sX | -d | -eX) [hasm file] [out binary]"; for(int i = 1; i < argc; i++){ char* v = argv[i]; if(STARTSWITH(v, '-')){ if(!strcmp(v, "-h")){ LogI(usage, argv[0]); LogI(" "); LogI("Available flags:"); LogI(" -vX set log level, where X is [0-5] - default: 2"); LogI(" -sX set assembly start address [0-FFFF] - default 0"); LogI(" -h show this help message"); LogI(" -d generate debug symbols"); LogI(" -t unit tests"); return 0; } else if(sscanf(v, "-v%d", &logLevel) == 1){} else if(sscanf(v, "-s%x", &addr) == 1){} else if(!strcmp(v, "-d")){ debugSymbols = true; } else if(!strcmp(v, "-t")){ return Tests(argc, argv); } else{ LogF("No such flag: %s", v); return 1; } }else{ LAssert(atFile < 2, "Please specify exactly one input file and one output file"); files[atFile++] = v; } } LAssert(argc >= 3 && files[0] && files[1], usage, argv[0]); // Allocate 16 MB ROM uint8_t* ram = calloc(1, romSize); Hasm* d = Hasm_Create(); if(debugSymbols){ char tmp[4096]; sprintf(tmp, "%s.dbg", files[1]); d->debugFile = fopen(tmp, "w"); LogV("Opening debug file: %s", tmp); LAssert(d->debugFile, "could not open file: %s", tmp); } uint32_t len = Hasm_Assemble(d, files[0], ram, addr, romSize - 1); if(d->debugFile) fclose(d->debugFile); Hasm_Destroy(&d); if(logLevel == 0 && len) DumpRam(ram, len - 1); LogV("Writing to: %s", files[1]); WriteFile(ram, len ? len - 1 : 0, files[1]); LAssertWarn(len, "produced empty file"); free(ram); return 0; }