• R/O
  • HTTP
  • SSH
  • HTTPS

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

oga's tools


File Info

Rev. d6f35a911265152c0ebe479a6552316ce6024300
Tamaño 5,454 octetos
Tiempo 2024-12-28 17:25:55
Autor hyperoga
Log Message

change access permission

Content

/*
 *  VIC-1001 t64 file analyzer
 *
 *    11/05/05 V0.10 by oga.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define T64_HEADER  "C64S tape image file"

typedef unsigned int	uint;
typedef unsigned short	ushort;
typedef struct _fname_t {
	char fname[20];
} fname_t;

/* basic operation code (0x80-0xff) */
char *op[128] = {
  /* 80 */ "end", "for", "next", "data", "input#", "input", "dim", "read",
  /* 88 */ "let", "goto", "run", "if", "restore", "gosub", "return", "rem",
  /* 90 */ "stop", "on", "wait", "load", "save", "verify", "def ", "poke",
  /* 98 */ "print#", "print", "cont", "list", "clr", "cmd ", "sys ", "open",
  /* a0 */ "close", "get ", "new", "tab(", "to", "fn", "spc(", " then",
  /* a8 */ "not", "step", "+", "-", "*", "/", "^", "and",
  /* b0 */ "or", ">", "=", "<", "sgn", "int", "abs", "usr",
  /* b8 */ "fre", "pos", "sqr", "rnd", "log", "exp", "cos", "sin",
  /* c0 */ "tan", "atn", "peek", "len", "str$", "val", "asc", "chr$",
           /* 0xcc-0xfe : Ver2.0 Super Expander */
  /* c8 */ "left$", "right$", "mid$", "go", "key", "graphic", "xxx", "xxx",
  /* d0 */ "draw", "region", "color", "point", "sound", "char", "paint", "rpot",
  /* d8 */ "rpen", "rsnd", "rcolr", "rgr", "rjoy", "rdot", "", "",
  /* e0 */ "", "", "", "", "", "", "", "",
  /* e8 */ "", "", "", "", "", "", "", "",
  /* f0 */ "", "", "", "", "", "", "", "",
  /* f8 */ "", "", "", "", "", "", "", "pi",
};


int  vf  = 0;		/* -v : verbose     */
int  lff = 0;		/* -lf: line format */

void usage()
{
	printf("usage: t64an [-lf] <xxx.t64>\n");
	printf("       -lf: line format\n");
	exit(1);
}

/* dump hex code */
void dump(FILE *fp, int size)
{
	uint c;
	int  i;
	for (i = 0; i < size; i++) {
		if (i != 0 && (i % 4) == 0) {
			printf(" ");
		}
		c = getc(fp);
		if (c == EOF) break;
		printf("%02x", c);
	}
	printf("\n");
}

/* BASIC 行番号 表示
 * nnnnmmmm  nnnn:source addr  mmmm:line number 
 *   nnnn:source addr
 *   mmmm:line number
 *
 *  IN : fp
 *  OUT: ret : line no  (0: EOS)
 */
int disp_lineno(FILE *fp)
{
	ushort val;
	int    size;

	fread(&val, 1, 2, fp);
	if (vf) printf("0x%4x ", val);

	if (val == 0) {
		/* End of 1 Program Source */
		/* source addr値(nnnn)が(0000)の場合はEOSのため行番号表示しない */
		printf("--------------------\n");
		return 0;
	}

	size = fread(&val, 1, 2, fp);
	if (size == 2) {
		if (lff) {
			printf("%5d ", val);
		} else {
			printf("%d ", val);
		}
		return val;
	}
	return 0;
}


/*
 *   BASIC 中間コードを文字列に変換する
 *
 *   IN     : c    変換対象コード 
 *   OUT    : buf  変換結果 
 *   IN/OUT : strf 文字列中かどうかのフラグ 1:文字列中  
 */

void cbm_bas_trans(uint c, char *obuf, int *strfp)
{
	if (*strfp == 0 && (c >= 0x80 && c <= 0xff) && strlen(op[c-0x80])) {
		sprintf(obuf, "%s", op[c-0x80]);
	} else {
		sprintf(obuf, "%c", c);
		if (c == '"') {
			*strfp = 1 - *strfp;
		}
	}
}

/*
 *   analyze t64
 *
 *     <format>
 *     +00-13(0x14) "C64S tape image file"
 *     +14-27(0x14) ???1 (00000000 00000000 00000000 01000100 01000000)
 *                                                       ==   == num of entry
 *     +28-3f(0x18) tape name (space filled)
 *     -----------------------------------------+
 *     +40-4f(0x10) file header                 | 1 entry 〜 n entry
 *     +50-5f(0x10) file name (space filled)    |
 *     -----------------------------------------+
 *     +60-63(0x04) <src_addr(2byte)><basic_line(2byte)>  (little endian)
 *     +64-         Source (null terminate)
 *     +nn          "0x000000"  End Of Source
 *
 */
void t64an(FILE *fp)
{
	char buf[4096];
	char wk[4096];
	int  strf = 0;     /* 1:文字列中 */
	int  nent = 0;
	int  size;
	int  i;
	int  ret;
	uint c;
	fname_t *fnames = NULL;

	/* header */
	size = fread(buf, 1, 20, fp);
	buf[20] = '\0';
	if (strcmp(buf, T64_HEADER))  {
		printf("Error: This is not t64 file!!\n");
		exit(1);
	}

	/* TapeHeader */
	size = fread(buf, 1, 20, fp);
	nent = buf[14];      /* num of tape entry */

	/* file name */
	size = fread(buf, 1, 24, fp);
	buf[24] = '\0';
	//printf("Tape Name: [%s]\n", buf);
	printf("Tape Name: %s\n", buf);
	printf("Num Entry: %d\n", nent);
	fnames = (fname_t *)malloc(nent*sizeof(fname_t));

	for (i = 0; i < nent; i++) {
		/* File Header */
		size = fread(buf, 1, 16, fp);

		/* File Name   */
		size = fread(buf, 1, 16, fp);
		buf[16] = '\0';
		strcpy(fnames[i].fname, buf);
		//printf("File %03d : [%s]\n", i, buf);
		printf("File %03d : %s\n", i+1, fnames[i].fname);
	}


	for (i = 0; i < nent; i++) {
		printf("\n");
		printf("###### File %03d : %s\n", i+1, fnames[i].fname);
		printf("--------------------\n");

		/* source area */
		c = 0;
		while (c != EOF) {
			/* dump(fp, 4); */      /* line data */
			ret = disp_lineno(fp);  /* disp line */
			if (ret == 0) break;    /* EOS       */
			strf = 0;
			while (1) {
				c = getc(fp);
				if (c == 0 || c == EOF) {
					printf("\n");
					break;
				}
				cbm_bas_trans(c, wk, &strf);
				printf("%s", wk);
			}
		}

	}
}

int main(int a, char *b[])
{
	int  i;
	char *filename = NULL;
	FILE *fp;

	for (i = 1; i<a; i++) {
		if (!strcmp(b[i],"-h")) {
			usage();
		}
		if (!strcmp(b[i],"-lf")) {
			lff = 1;   /* line format */
			continue;
		}
		if (!strcmp(b[i],"-v")) {
			vf = 1;
			continue;
		}
		filename = b[i];
	}

	if (filename) {
		if (!(fp = fopen(filename,"r"))) {
			perror("fopen");
			exit(1);
		}
	} else {
		fp = stdin;
	}

	t64an(fp);

	fclose(fp);
}

/* vim:ts=4:sw=4:
 */