commit 19db03d

zzo38  ·  2022-11-06 06:41:41 +0000 UTC
parent 3e1f3a7
Some enhancements in the assembler.
2 files changed,  +110, -14
M main.c
M main.c
+0, -3
 1@@ -1014,9 +1014,6 @@ int main(int argc,char**argv) {
 2     while(run_screen()) {
 3       for(i=0;i<15;i++) for(j=0;j<16;j++) device[i].d[j]=0;
 4       load_rom();
 5-      // PUT16(device[2].d+2,default_width);
 6-      // PUT16(device[2].d+4,default_height);
 7-      // set_screen_mode(default_width,default_height);
 8       goto restart;
 9     }
10   } else if(audio_option) {
+110, -11
  1@@ -9,6 +9,11 @@ copyright notice and this permission notice appear in all copies.
  2 
  3 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  4 WITH REGARD TO THIS SOFTWARE.
  5+
  6+[This file has been modified from the original that the above copyright
  7+notice applies to. The same license conditions apply to the modified
  8+version, although the person who modified it is not the person who is
  9+named in the above copyright notice.]
 10 */
 11 
 12 #define TRIM 0x0100
 13@@ -43,7 +48,10 @@ typedef struct {
 14 	char scope[0x40];
 15 } Program;
 16 
 17-Program p;
 18+static Program p;
 19+static char line_comment;
 20+static int ssptr;
 21+static Uint16 sstack[256];
 22 
 23 /* clang-format off */
 24 
 25@@ -142,7 +150,7 @@ makemacro(char *name, FILE *f)
 26 	while(fscanf(f, "%63s", word) == 1) {
 27 		if(word[0] == '{') continue;
 28 		if(word[0] == '}') break;
 29-		if(word[0] == '%')
 30+		if(word[0] == '%' || line_comment)
 31 			return error("Macro error", name);
 32 		if(m->len >= 0x40)
 33 			return error("Macro size exceeded", name);
 34@@ -237,21 +245,70 @@ doinclude(const char *filename)
 35 {
 36 	FILE *f;
 37 	char w[0x40];
 38+	int c;
 39 	if(!(f = fopen(filename, "r")))
 40 		return error("Include missing", filename);
 41-	while(fscanf(f, "%63s", w) == 1)
 42+	while(fscanf(f, "%63s", w) == 1) {
 43 		if(!parse(w, f))
 44 			return error("Unknown token", w);
 45+		if(line_comment) {
 46+		  while((c=fgetc(f))>0 && c!='\n');
 47+		  line_comment=0;
 48+		}
 49+	}
 50 	fclose(f);
 51+	line_comment=0;
 52 	return 1;
 53 }
 54 
 55+static int doinclude_binary(const char*filename) {
 56+  FILE*f;
 57+  int c;
 58+  if(!(f = fopen(filename, "r"))) return error("Include missing", filename);
 59+  while((c=fgetc(f))!=EOF) writebyte(c);
 60+  fclose(f);
 61+  return 1;
 62+}
 63+
 64+static int special_calc(const char*w) {
 65+  const char*loop=w;
 66+  Uint16 a,b;
 67+  while(*w) switch(*w++) {
 68+    case '_': loop=w; break;
 69+    case '0' ... '9': if(ssptr>255) return 0; sstack[ssptr++]=w[-1]-'0'; break;
 70+    case '!': if(ssptr<1) return 0; p.ptr=sstack[--ssptr]; break;
 71+    case '@': if(ssptr>255) return 0; sstack[ssptr++]=p.ptr; break;
 72+    case '#': if(ssptr<1) return 0; p.length=sstack[--ssptr]; break;
 73+    case '$': if(ssptr>255) return 0; sstack[ssptr++]=p.length; break;
 74+    case '+': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; sstack[ssptr++]=a+b; break;
 75+    case '-': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; sstack[ssptr++]=a-b; break;
 76+    case '*': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; sstack[ssptr++]=a*b; break;
 77+    case '/': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; if(!b) return 0; sstack[ssptr++]=a/b; break;
 78+    case '%': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; if(!b) return 0; sstack[ssptr++]=a%b; break;
 79+    case '&': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; sstack[ssptr++]=a&b; break;
 80+    case '|': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; sstack[ssptr++]=a|b; break;
 81+    case '^': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; sstack[ssptr++]=a^b; break;
 82+    case ':': if(ssptr<1 || ssptr>255) return 0; a=sstack[ssptr-1]; sstack[ssptr++]=a; break;
 83+    case ',': if(ssptr<2) return 0; b=sstack[--ssptr]; a=sstack[--ssptr]; sstack[ssptr++]=b; sstack[ssptr++]=a; break;
 84+    case '.': if(ssptr<1) return 0; --ssptr; break;
 85+    case 'g': if(ssptr<1) return 0; a=sstack[--ssptr]; sstack[ssptr++]=p.data[a]; break;
 86+    case 'G': if(ssptr<1) return 0; a=sstack[--ssptr]; if(a==0xFFFF) return 0; sstack[ssptr++]=(p.data[a]<<8)|p.data[a+1]; break;
 87+    case 'p': if(ssptr<2) return 0; a=sstack[--ssptr]; b=sstack[--ssptr]; p.data[a]=b; break;
 88+    case 'P': if(ssptr<2) return 0; a=sstack[--ssptr]; b=sstack[--ssptr]; if(a==0xFFFF) return 0; p.data[a]=b>>8; p.data[a+1]=b&255; break;
 89+    case 'w': if(ssptr<1) return 0; a=sstack[--ssptr]; writebyte(a); break;
 90+    case 'W': if(ssptr<1) return 0; a=sstack[--ssptr]; writeshort(a,0); break;
 91+    default: return 0;
 92+  }
 93+  return 1;
 94+}
 95+
 96 static int
 97 parse(char *w, FILE *f)
 98 {
 99 	int i;
100 	char word[0x40], subw[0x40], c;
101 	Macro *m;
102+	Label*l;
103 	if(slen(w) >= 63)
104 		return error("Invalid token", w);
105 	switch(w[0]) {
106@@ -324,10 +381,34 @@ parse(char *w, FILE *f)
107 		while((c = w[++i]))
108 			if(!writebyte(c)) return 0;
109 		break;
110+	case '\\': /* specials */
111+		switch(w[1]) {
112+		  case '\\': line_comment=1; break;
113+		  case '~': if(!doinclude_binary(w+2)) return error("Invalid include",w); break;
114+		  case ':':
115+		    if(!(l=findlabel(w+2))) return error("Invalid reference",w);
116+		    if(ssptr==256) return error("Stack overflow",w);
117+		    sstack[ssptr++]=l->addr;
118+		    break;
119+		  case '0' ... '9': case 'a' ... 'f':
120+		    if(!sihx(w+1)) return error("Invalid hex literal",w);
121+		    if(ssptr==256) return error("Stack overflow",w);
122+		    sstack[ssptr++]=shex(w+1);
123+		    break;
124+		  case '@':
125+		    if(!ssptr) return error("Stack underflow",w);
126+		    i=p.ptr;
127+		    if(!makelabel(w+2)) return error("Invalid label",w);
128+		    p.ptr=i;
129+		    break;
130+		  case '_': if(!special_calc(w+2)) return error("Special calculation error",w); break;
131+		  default: return error("Invalid special",w);
132+		}
133+		break;
134 	case '[':
135 	case ']':
136 		if(slen(w) == 1) break; /* else fallthrough */
137-	default:
138+	default: defa:
139 		/* opcode */
140 		if(findopcode(w) || scmp(w, "BRK", 4)) {
141 			if(!writeopcode(w)) return 0;
142@@ -345,6 +426,7 @@ parse(char *w, FILE *f)
143 			for(i = 0; i < m->len; i++)
144 				if(!parse(m->items[i], f))
145 					return 0;
146+			line_comment=0;
147 			return 1;
148 		} else
149 			return error("Unknown token", w);
150@@ -399,10 +481,16 @@ static int
151 assemble(FILE *f)
152 {
153 	char w[0x40];
154+	int c;
155 	scpy("on-reset", p.scope, 0x40);
156-	while(fscanf(f, "%63s", w) == 1)
157+	while(fscanf(f, "%63s", w) == 1) {
158 		if(!parse(w, f))
159 			return error("Unknown token", w);
160+		if(line_comment) {
161+		  while((c=fgetc(f))>0 && c!='\n');
162+		  line_comment=0;
163+		}
164+	}
165 	return resolve();
166 }
167 
168@@ -418,27 +506,38 @@ review(char *filename)
169 	fprintf(stderr,
170 		"Assembled %s in %d bytes(%.2f%% used), %d labels, %d macros.\n",
171 		filename,
172-		p.length - TRIM,
173-		(p.length - TRIM) / 652.80,
174+		p.length<TRIM?0:p.length-TRIM,
175+		p.length<TRIM?0:((p.length - TRIM) / 652.80),
176 		p.llen,
177 		p.mlen);
178 }
179 
180+static void send_name_output(FILE*dst) {
181+  int i;
182+  for(i=0;i<p.llen;i++) fprintf(dst,"|%04x @%s\n",p.labels[i].addr,p.labels[i].name);
183+}
184+
185 int
186 main(int argc, char *argv[])
187 {
188 	FILE *src, *dst;
189 	if(argc < 3)
190-		return !error("usage", "input.tal output.rom");
191+		return !error("usage", "input.tal output.rom [output.nam]");
192 	if(!(src = fopen(argv[1], "r")))
193 		return !error("Invalid input", argv[1]);
194 	if(!assemble(src))
195 		return !error("Assembly", "Failed to assemble rom.");
196 	if(!(dst = fopen(argv[2], "wb")))
197-		return !error("Invalid Output", argv[2]);
198+		return !error("Invalid output", argv[2]);
199 	if(p.length <= TRIM)
200-		return !error("Assembly", "Output rom is empty.");
201-	fwrite(p.data + TRIM, p.length - TRIM, 1, dst);
202+		error("Assembly", "Output rom is empty.");
203+	else
204+		fwrite(p.data + TRIM, p.length - TRIM, 1, dst);
205 	review(argv[2]);
206+	if(argc>3 && argv[3][0]) {
207+	  fclose(dst);
208+	  if(!(dst=fopen(argv[3],"w"))) return !error("Invalid name output",argv[3]);
209+	  send_name_output(dst);
210+	}
211 	return 0;
212 }