int main(int argc, char *argv[]) { FILE *out; FILE *dbg = NULL; //FILE *list = NULL; int i; int format = FORMAT_HEX; int create_list = 0; char *infile = NULL, *outfile = NULL; struct _asm_context asm_context; int error_flag=0; puts(credits); if (argc < 2) { printf("Usage: naken_asm [options] <infile>\n" " -o <outfile>\n" " -h [output hex file]\n" #ifndef DISABLE_ELF " -e [output elf file]\n" #endif " -b [output binary file]\n" " -s [output srec file]\n" " -l [create .lst listing file]\n" " -I [add to include path]\n" " -q Quiet (only output errors)\n" "\n"); exit(0); } memset(&asm_context, 0, sizeof(asm_context)); for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-o") == 0) { outfile = argv[++i]; } else if (strcmp(argv[i], "-h") == 0) { format = FORMAT_HEX; } else if (strcmp(argv[i], "-b") == 0) { format = FORMAT_BIN; } else if (strcmp(argv[i], "-s") == 0) { format = FORMAT_SREC; } #ifndef DISABLE_ELF else if (strcmp(argv[i], "-e") == 0) { format = FORMAT_ELF; } #endif #if 0 else if (strcmp(argv[i], "-d") == 0) { asm_context.debug_file = 1; } #endif else if (strcmp(argv[i], "-l") == 0) { create_list = 1; } else if (strncmp(argv[i], "-I", 2) == 0) { char *s = argv[i]; if (s[2] == 0) { if (add_to_include_path(&asm_context, argv[++i]) != 0) { printf("Internal Error: Too many include paths\n"); exit(1); } } else { if (add_to_include_path(&asm_context, s+2) != 0) { printf("Internal Error: Too many include paths\n"); exit(1); } } } else if (strcmp(argv[i], "-q") == 0) { asm_context.quiet_output = 1; } else { if (infile != NULL) { printf("Error: Cannot use %s as input file since %s was already chosen.\n", argv[1], infile); exit(1); } infile = argv[i]; } } if (infile == NULL) { printf("No input file specified.\n"); exit(1); } if (outfile == NULL) { switch(format) { case FORMAT_HEX: outfile = "out.hex"; break; case FORMAT_BIN: outfile = "out.bin"; break; case FORMAT_ELF: outfile = "out.elf"; break; case FORMAT_SREC: outfile = "out.srec"; break; default: outfile = "out.err"; break; } } #ifdef INCLUDE_PATH if (add_to_include_path(&asm_context, INCLUDE_PATH) != 0) { printf("Internal Error: Too many include paths\n"); exit(1); } #endif if (tokens_open_file(&asm_context, infile) != 0) { printf("Couldn't open %s for reading.\n", infile); exit(1); } out = fopen(outfile, "wb"); if (out == NULL) { printf("Couldn't open %s for writing.\n", outfile); exit(1); } if (asm_context.quiet_output == 0) { printf(" Input file: %s\n", infile); printf("Output file: %s\n", outfile); } #if 0 if (asm_context.debug_file == 1) { char filename[1024]; strcpy(filename, outfile); new_extension(filename, "ndbg", 1024); dbg = fopen(filename,"wb"); if (dbg == NULL) { printf("Couldn't open %s for writing.\n",filename); exit(1); } printf(" Debug file: %s\n",filename); fprintf(dbg, "%s\n", infile); } #endif if (create_list == 1) { char filename[1024]; strcpy(filename, outfile); new_extension(filename, "lst", 1024); asm_context.list = fopen(filename, "wb"); if (asm_context.list == NULL) { printf("Couldn't open %s for writing.\n", filename); exit(1); } if (asm_context.quiet_output == 0) { printf(" List file: %s\n", filename); } } if (asm_context.quiet_output == 0) { printf("\nPass 1...\n"); } symbols_init(&asm_context.symbols); macros_init(&asm_context.macros); asm_context.pass = 1; assemble_init(&asm_context); error_flag = assemble(&asm_context); if (error_flag != 0) { printf("** Errors... bailing out\n"); unlink(outfile); } else { symbols_lock(&asm_context.symbols); // macros_lock(&asm_context.defines_heap); if (asm_context.quiet_output == 0) { printf("Pass 2...\n"); } asm_context.pass = 2; assemble_init(&asm_context); error_flag = assemble(&asm_context); if (format == FORMAT_HEX) { write_hex(&asm_context.memory, out); } else if (format == FORMAT_BIN) { write_bin(&asm_context.memory, out); } else if (format == FORMAT_SREC) { write_srec(&asm_context.memory, out); } #ifndef DISABLE_ELF else if (format == FORMAT_ELF) { write_elf(&asm_context.memory, out, &asm_context.symbols, asm_context.filename, asm_context.cpu_type); } #endif if (dbg != NULL) { for (i = 0; i < asm_context.memory.size; i++) { int debug_line = memory_debug_line(&asm_context, i); putc(debug_line >> 8, dbg); putc(debug_line & 0xff, dbg); } fclose(dbg); } } fclose(out); if (create_list == 1) { int ch = 0; char str[17]; int ptr = 0; fprintf(asm_context.list, "data sections:"); for (i = asm_context.memory.low_address; i <= asm_context.memory.high_address; i++) { if (memory_debug_line(&asm_context, i) == -2) { if (ch == 0) { if (ptr != 0) { output_hex_text(asm_context.list, str, ptr); } fprintf(asm_context.list, "\n%04x:", i/asm_context.bytes_per_address); ptr = 0; } unsigned char data = memory_read(&asm_context, i); fprintf(asm_context.list, " %02x", data); if (data >= ' ' && data <= 120) { str[ptr++] = data; } else { str[ptr++] = '.'; } ch++; if (ch == 16) { ch = 0; } } else { output_hex_text(asm_context.list, str, ptr); ch = 0; ptr = 0; } } output_hex_text(asm_context.list, str, ptr); fprintf(asm_context.list, "\n\n"); assemble_print_info(&asm_context, asm_context.list); } assemble_print_info(&asm_context, stdout); //symbols_free(&asm_context.symbols); //macros_free(&asm_context.macros); if (asm_context.list != NULL) { fclose(asm_context.list); } fclose(asm_context.in); if (error_flag != 0) { printf("*** Failed ***\n\n"); unlink(outfile); } //memory_free(&asm_context.memory); assemble_free(&asm_context); if (error_flag != 0) { return -1; } return 0; }
int main(int argc, char **argv) { FILE *fp, *ipl; char *p; char cmd[80]; int i, j; int file; int ram_bank; /* get program name */ if ((prg_name = strrchr(argv[0], '/')) != NULL) prg_name++; else { if ((prg_name = strrchr(argv[0], '\\')) == NULL) prg_name = argv[0]; else prg_name++; } /* remove extension */ if ((p = strrchr(prg_name, '.')) != NULL) *p = '\0'; /* machine detection */ if (!strncasecmp(prg_name, "PCE", 3)) machine = &pce; else machine = &nes; /* init assembler options */ list_level = 2; header_opt = 1; develo_opt = 0; mlist_opt = 0; srec_opt = 0; run_opt = 0; scd_opt = 0; cd_opt = 0; mx_opt = 0; file = 0; // 2010/12/30 minachun add autozp_opt = 0; // 2010/12/30 minachun end /* display assembler version message */ printf("%s\n\n", machine->asm_title); /* parse command line */ if (argc > 1) { for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { /* segment usage */ if (!strcmp(argv[i], "-s")) dump_seg = 1; else if (!strcmp(argv[i], "-S")) dump_seg = 2; /* forces macros expansion */ else if (!strcmp(argv[i], "-m")) mlist_opt = 1; /* no header */ else if (!strcmp(argv[i], "-raw")) header_opt = 0; /* output s-record file */ else if (!strcmp(argv[i], "-srec")) srec_opt = 1; /* output level */ else if (!strncmp(argv[i], "-l", 2)) { /* get level */ if (strlen(argv[i]) == 2) list_level = atol(argv[++i]); else list_level = atol(&argv[i][2]); /* check range */ if (list_level < 0 || list_level > 3) list_level = 2; } /* help */ else if (!strcmp(argv[i], "-?")) { help(); return (0); } else { /* PCE specific functions */ if (machine->type == MACHINE_PCE) { /* cd-rom */ if (!strcmp(argv[i], "-cd")) { cd_opt = STANDARD_CD; scd_opt = 0; } /* super cd-rom */ else if (!strcmp(argv[i], "-scd")) { scd_opt = SUPER_CD; cd_opt = 0; } /* develo auto-run */ else if (!strcmp(argv[i], "-develo")) develo_opt = 1; else if (!strcmp(argv[i], "-dev")) develo_opt = 1; /* output mx file */ else if (!strcmp(argv[i], "-mx")) mx_opt = 1; } // 2010/12/30 minachun add. /* NES specific functions */ else if ( machine->type == MACHINE_NES ) { /* auto zeropage mode */ if (!strcmp(argv[i], "-autozp")) { autozp_opt = 1; } } // 2010/12/30 minachun end. } } else { strcpy(in_fname, argv[i]); file++; } } } if (!file) { help(); return (0); } /* search file extension */ if ((p = strrchr(in_fname, '.')) != NULL) { if (!strchr(p, PATH_SEPARATOR)) *p = '\0'; else p = NULL; } /* auto-add file extensions */ strcpy(out_fname, in_fname); strcpy(bin_fname, in_fname); strcpy(lst_fname, in_fname); strcat(bin_fname, (cd_opt || scd_opt) ? ".bin" : machine->rom_ext); strcat(lst_fname, ".lst"); if (p) *p = '.'; else strcat(in_fname, ".asm"); /* init include path */ init_path(); /* init crc functions */ crc_init(); /* open the input file */ if (open_input(in_fname)) { printf("Can not open input file '%s'!\n", in_fname); exit(1); } /* clear the ROM array */ memset(rom, 0xFF, 8192 * 128); memset(map, 0xFF, 8192 * 128); /* clear symbol hash tables */ for (i = 0; i < 256; i++) { hash_tbl[i] = NULL; macro_tbl[i] = NULL; func_tbl[i] = NULL; inst_tbl[i] = NULL; } /* fill the instruction hash table */ addinst(base_inst); addinst(base_pseudo); /* add machine specific instructions and pseudos */ addinst(machine->inst); addinst(machine->pseudo_inst); /* predefined symbols */ lablset("MAGICKIT", 1); lablset("DEVELO", develo_opt | mx_opt); lablset("CDROM", cd_opt | scd_opt); lablset("_bss_end", 0); lablset("_bank_base", 0); lablset("_nb_bank", 1); lablset("_call_bank", 0); /* init global variables */ max_zp = 0x01; max_bss = 0x0201; max_bank = 0; rom_limit = 0x100000; /* 1MB */ bank_limit = 0x7F; bank_base = 0; errcnt = 0; if (cd_opt) { rom_limit = 0x10000; /* 64KB */ bank_limit = 0x07; } else if (scd_opt) { rom_limit = 0x40000; /* 256KB */ bank_limit = 0x1F; } else if (develo_opt || mx_opt) { rom_limit = 0x30000; /* 192KB */ bank_limit = 0x17; } /* assemble */ for (pass = FIRST_PASS; pass <= LAST_PASS; pass++) { infile_error = -1; page = 7; bank = 0; loccnt = 0; slnum = 0; mcounter = 0; mcntmax = 0; xlist = 0; glablptr = NULL; skip_lines = 0; rsbase = 0; proc_nb = 0; /* reset assembler options */ asm_opt[OPT_LIST] = 0; asm_opt[OPT_MACRO] = mlist_opt; asm_opt[OPT_WARNING] = 0; asm_opt[OPT_OPTIMIZE] = 0; /* reset bank arrays */ for (i = 0; i < 4; i++) { for (j = 0; j < 256; j++) { bank_loccnt[i][j] = 0; bank_glabl[i][j] = NULL; bank_page[i][j] = 0; } } /* reset sections */ ram_bank = machine->ram_bank; section = S_CODE; /* .zp */ section_bank[S_ZP] = ram_bank; bank_page[S_ZP][ram_bank] = machine->ram_page; bank_loccnt[S_ZP][ram_bank] = 0x0000; /* .bss */ section_bank[S_BSS] = ram_bank; bank_page[S_BSS][ram_bank] = machine->ram_page; bank_loccnt[S_BSS][ram_bank] = 0x0200; /* .code */ section_bank[S_CODE] = 0x00; bank_page[S_CODE][0x00] = 0x07; bank_loccnt[S_CODE][0x00] = 0x0000; /* .data */ section_bank[S_DATA] = 0x00; bank_page[S_DATA][0x00] = 0x07; bank_loccnt[S_DATA][0x00] = 0x0000; /* pass message */ printf("pass %i\n", pass + 1); /* assemble */ while (readline() != -1) { assemble(); if (loccnt > 0x2000) { if (proc_ptr == NULL) fatal_error("Bank overflow, offset > $1FFF!"); else { char tmp[128]; sprintf(tmp, "Proc : '%s' is too large (code > 8KB)!", proc_ptr->name); fatal_error(tmp); } break; } if (stop_pass) break; } /* relocate procs */ if (pass == FIRST_PASS) proc_reloc(); /* abord pass on errors */ if (errcnt) { printf("# %d error(s)\n", errcnt); break; } /* adjust bank base */ if (pass == FIRST_PASS) bank_base = calc_bank_base(); /* update predefined symbols */ if (pass == FIRST_PASS) { lablset("_bss_end", machine->ram_base + max_bss); lablset("_bank_base", bank_base); lablset("_nb_bank", max_bank + 1); } /* adjust the symbol table for the develo or for cd-roms */ if (pass == FIRST_PASS) { if (develo_opt || mx_opt || cd_opt || scd_opt) lablremap(); } /* rewind input file */ rewind(in_fp); /* open the listing file */ if (pass == FIRST_PASS) { if (xlist && list_level) { if ((lst_fp = fopen(lst_fname, "w")) == NULL) { printf("Can not open listing file '%s'!\n", lst_fname); exit(1); } fprintf(lst_fp, "#[1] %s\n", input_file[1].name); } } } /* rom */ if (errcnt == 0) { /* cd-rom */ if (cd_opt || scd_opt) { /* open output file */ if ((fp = fopen(bin_fname, "wb")) == NULL) { printf("Can not open output file '%s'!\n", bin_fname); exit(1); } /* boot code */ if (header_opt) { /* open ipl binary file */ if ((ipl = open_file("boot.bin", "rb")) == NULL) { printf("Can not find CD boot file 'boot.bin'!\n"); exit(1); } /* load ipl */ fread(ipl_buffer, 1, 4096, ipl); fclose(ipl); memset(&ipl_buffer[0x800], 0, 32); /* prg sector base */ ipl_buffer[0x802] = 2; /* nb sectors */ ipl_buffer[0x803] = 4; /* loading address */ ipl_buffer[0x804] = 0x00; ipl_buffer[0x805] = 0x40; /* starting address */ ipl_buffer[0x806] = 0x10; ipl_buffer[0x807] = 0x40; /* mpr registers */ ipl_buffer[0x808] = 0x00; ipl_buffer[0x809] = 0x01; ipl_buffer[0x80A] = 0x02; ipl_buffer[0x80B] = 0x03; ipl_buffer[0x80C] = 0x04; /* load mode */ ipl_buffer[0x80D] = 0x60; /* write boot code */ fwrite(ipl_buffer, 1, 4096, fp); } /* write rom */ fwrite(rom, 8192, (max_bank + 1), fp); fclose(fp); } /* develo box */ else if (develo_opt || mx_opt) { page = (map[0][0] >> 5); /* save mx file */ if ((page + max_bank) < 7) /* old format */ write_srec(out_fname, "mx", page << 13); else /* new format */ write_srec(out_fname, "mx", 0xD0000); /* execute */ if (develo_opt) { sprintf(cmd, "perun %s", out_fname); system(cmd); } } /* save */ else { /* s-record file */ if (srec_opt)