Beispiel #1
0
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;
}
Beispiel #2
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)