commit 19db03d
zzo38
·
2022-11-06 06:41:41 +0000 UTC
parent 3e1f3a7
Some enhancements in the assembler.
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) {
M
uxnasm.c
+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 }