├── .gitignore
├── IOSerial.asm
├── LICENSE
├── MAIN.asm
├── MINT – Forth2020_presentation_10_5_25.pptx
├── MINT – Forth’s Kid Brother.pptx
├── MINT-Forth's Kid Brother.pptx
├── README.md
├── TEC-1ROM10.z80
├── TEC-1ROM10.z80.hex
├── TEC-1ROM10.z80.lst
├── constants.asm
├── inspiration.md
├── mycomputer.emu
├── ram.asm
├── snippets.md
├── test.FAST.z80
├── test.RUN.z80
├── test.fast.mac.asm
├── testbed.z80
├── testbed.z80.hex
└── testbed.z80.lst
/.gitignore:
--------------------------------------------------------------------------------
1 | notes.txt
2 | .vscode/
3 | test.*.hex
4 | test.*.lst
5 | notes.md
6 | tec-test.z80-1
7 | tutorial.md
8 | tutorial-raw.md
9 | x.md
--------------------------------------------------------------------------------
/IOSerial.asm:
--------------------------------------------------------------------------------
1 | ; ROM code
2 | ; Targets:
3 | ; TEC-1,TEC-1D,TEC-1F,Southern Cross,RC2014
4 | ; Memory Map: 2k ROM/RAM, 8K ROM/RAM, RC2014
5 | ; Serial: Bit Bang, 6850 ACIA
6 |
7 | .if TEC_1
8 | .if BITBANG
9 |
10 | ; bit bang baud rate constants @ 4MHz
11 | B300: .EQU 0220H
12 | B1200: .EQU 0080H
13 | B2400: .EQU 003FH
14 | B4800: .EQU 001BH
15 | B9600: .EQU 000BH
16 |
17 | .else ;6850
18 |
19 | ;
20 | ; 6850 ACIA registers
21 | ;----------------------
22 | CONTROL .EQU $80 ;(write)
23 | STATUS .EQU $80 ;(read)
24 | TDR .EQU $81 ;(write)
25 | RDR .EQU $81 ;(read)
26 | ;
27 | ; control register bits
28 | ;----------------------
29 | ;
30 | ;clock divisor
31 | ;
32 | MRESET .EQU $03 ;master reset the ACIA
33 | ; DIV_0 .EQU $00 ;CLOCK/1
34 | ; DIV_16 .EQU $01 ;CLOCK/16
35 | DIV_64 .EQU $02 ;CLOCK/64
36 | ;
37 | ; format select
38 | ;
39 | F7E2 .EQU $00 ;7 data bits, EVEN parity, 2 stop bits (1+7+1+2= 11 bits)
40 | F7O2 .EQU $04 ;7 data bits, ODD parity, 2 stop bits (1+7+1+2= 11 bits)
41 | F7E1 .EQU $08 ;7 data bits, EVEN parity, 1 stop bit (1+7+1+1= 10 bits)
42 | F7O1 .EQU $0C ;7 data bits, ODD parity, 1 stop bit (1+7+1+1= 10 bits)
43 | F8N2 .EQU $10 ;8 data bits, NO parity, 2 stop bits (1+8+0+2= 11 bits)
44 | F8N1 .EQU $14 ;8 data bits, NO parity, 1 stop bit (1+8+0+1= 10 bits)
45 | F8E1 .EQU $18 ;8 data bits, EVEN parity, 1 stop bit (1+8+1+1= 11 bits)
46 | F8O1 .EQU $1C ;8 data bits, ODD parity,1 stop bit (1+8+1+1= 11 bits)
47 | ;
48 | ; transmitter control
49 | ;
50 | RTSLID .EQU $00 ;RTS LOW, transmit interrupt disabled
51 | RTSLIE .EQU $20 ;RTS LOW, transmit interrupt enabled
52 | RTSHID .EQU $40 ;RTS HIGH, transmit interrupt disabled
53 | RTSLIDB .EQU $60 ;RTS LOW, transmit interrupt disabled and 'break' transmitted
54 | ;
55 | ; receiver interrupt
56 | ;
57 | RIE .EQU $80 ;receiver interrupt enabled
58 | ;
59 | ; status register bits
60 | ;---------------------
61 | RDRF .EQU 0 ;receive data register full
62 | TDRE .EQU 1 ;transmit data register empty
63 | DCD .EQU 2 ;data carrier detect
64 | CTS .EQU 3 ;clear to send
65 | FE .EQU 4 ;framing error
66 | OVRN .EQU 5 ;overrun
67 | PE .EQU 6 ;parity error
68 | IRQ .EQU 7 ;interrupt request
69 |
70 | .endif
71 | .endif
72 |
73 | ; I/O port addresses
74 |
75 | .if TEC_1
76 | KEYBUF: .EQU 00H ;MM74C923N KEYBOARD ENCODER
77 | SCAN: .EQU 01H ;DISPLAY SCAN LATCH
78 | DISPLY: .EQU 02H ;DISPLAY LATCH
79 | PORT3: .EQU 03H ;ST3 (8X8), STROBE (RELAY BOARD) DATLATCH (DAT BOARD)
80 | PORT4: .EQU 04H ;ST4 (8X8), LCD 'E' (DAT BOARD)
81 | PORT5: .EQU 05H
82 | PORT6: .EQU 06H
83 | PORT7: .EQU 07H ;ENABLE/DISABLE SINGLE STEPPER (IF INSTALLED)
84 | .else ;SC
85 | IO0: .EQU 80H ;IO PORT 0
86 | IO1: .EQU 81H ;IO PORT 1
87 | IO2: .EQU 82H ;IO PORT 2
88 | IO3: .EQU 83H ;IO PORT 3
89 | DISPLY: .EQU 84H ;DISPLAY LATCH
90 | SCAN: .EQU 85H ;DISPLAY SCAN LATCH
91 | KEYBUF: .EQU 86H ;KEYBOARD BUFFER
92 | IO7: .EQU 87H ;ENABLE/DISABLE SINGLE STEPPER (IF INSTALLED)
93 | .endif
94 |
95 | ; ASCII codes
96 | ESC: .EQU 1BH
97 | CR: .EQU 0DH
98 | LF: .EQU 0AH
99 |
100 | .ORG ROMSTART
101 | ;reset
102 | RSTVEC:
103 | JP RESET
104 |
105 | rst1:
106 | .ORG ROMSTART+$08
107 | ld l,1
108 | jp ISR
109 |
110 | rst2:
111 | .ORG ROMSTART+$10
112 | ld l,2
113 | jp ISR
114 |
115 | rst3:
116 | .ORG ROMSTART+$18
117 | ld l,3
118 | jp ISR
119 |
120 | rst4:
121 | .ORG ROMSTART+$20
122 | ld l,4
123 | jp ISR
124 |
125 | rst5:
126 | .ORG ROMSTART+$28
127 | ld l,5
128 | jp ISR
129 |
130 | rst6:
131 | .ORG ROMSTART+$30
132 | ld l,6
133 | jp ISR
134 |
135 | ;RST 7 Interrupt
136 | .ORG ROMSTART+$38
137 |
138 | .if BITBANG
139 |
140 | ld l,7
141 | jp ISR
142 | .else
143 |
144 | ret
145 |
146 | .endif
147 |
148 | .ORG ROMSTART+$40
149 |
150 | ;hexadecimal to 7 segment display code table
151 | .if TEC_1
152 |
153 | sevensegment:
154 | .DB 0EBH,28H,0CDH,0ADH ;0,1,2,3
155 | .DB 2EH,0A7H,0E7H,29H ;4,5,6,7
156 | .DB 0EFH,2FH,6FH,0E6H ;8,9,A,B
157 | .DB 0C3H,0ECH,0C7H,47H ;C,D,E,F
158 | .else ;SC
159 |
160 | sevensegment:
161 | .DB 3FH,06H,5BH,4FH ;0,1,2,3
162 | .DB 66H,6DH,7DH,07H ;4,5,6,7
163 | .DB 7FH,6FH,77H,7CH ;8,9,A,B
164 | .DB 39H,5EH,79H,71H ;C,D,E,F
165 | .endif
166 |
167 |
168 | ;---------------
169 | ; BIT TIME DELAY
170 | ;---------------
171 | ;DELAY FOR ONE SERIAL BIT TIME
172 | ;ENTRY : HL = DELAY TIME
173 | ; NO REGISTERS MODIFIED
174 | ;
175 | PWRUP:
176 | LD hl,$2000
177 | BITIME:
178 | PUSH HL
179 | PUSH DE
180 | LD DE,0001H
181 | BITIM1:
182 | SBC HL,DE
183 | JP NC,BITIM1
184 | POP DE
185 | POP HL
186 | IntRet:
187 | RET
188 |
189 | ;RST 8 Non Maskable Interrupt
190 | .ORG ROMSTART+$66
191 | ; PUSH HL
192 | ; LD HL,(NMIVEC)
193 | ; JP (HL)
194 |
195 | ld l,8
196 | jp ISR
197 |
198 |
199 | .if BITBANG
200 |
201 | ;------------------------
202 | ; SERIAL TRANSMIT ROUTINE
203 | ;------------------------
204 | ;TRANSMIT BYTE SERIALLY ON DOUT
205 | ;
206 | ; ENTRY : A = BYTE TO TRANSMIT
207 | ; EXIT : NO REGISTERS MODIFIED
208 | ;
209 |
210 | TxChar:
211 | TXDATA:
212 | PUSH AF
213 | PUSH BC
214 | PUSH HL
215 | LD HL,(BAUD)
216 | LD C,A
217 | ;
218 | ; TRANSMIT START BIT
219 | ;
220 | XOR A
221 | OUT (SCAN),A
222 | CALL BITIME
223 | ;
224 | ; TRANSMIT DATA
225 | ;
226 | LD B,08H
227 | RRC C
228 | NXTBIT:
229 | RRC C ;SHIFT BITS TO D6,
230 | LD A,C ;LSB FIRST AND OUTPUT
231 | AND 40H ;THEM FOR ONE BIT TIME.
232 | OUT (SCAN),A
233 | CALL BITIME
234 | DJNZ NXTBIT
235 | ;
236 | ; SEND STOP BITS
237 | ;
238 | LD A,40H
239 | OUT (SCAN),A
240 | CALL BITIME
241 | CALL BITIME
242 | POP HL
243 | POP BC
244 | POP AF
245 | RET
246 | ;-----------------------
247 | ; SERIAL RECEIVE ROUTINE
248 | ;-----------------------
249 | ;RECEIVE SERIAL BYTE FROM DIN
250 | ;
251 | ; ENTRY : NONE
252 | ; EXIT : A= RECEIVED BYTE IF CARRY CLEAR
253 | ;
254 | ; REGISTERS MODIFIED A AND F
255 | ;
256 | RxChar:
257 | RXDATA:
258 | PUSH BC
259 | PUSH HL
260 | ;
261 | ; WAIT FOR START BIT
262 | ;
263 | RXDAT1: IN A,(KEYBUF)
264 | BIT 7,A
265 | JR NZ,RXDAT1 ;NO START BIT
266 | ;
267 | ; DETECTED START BIT
268 | ;
269 | LD HL,(BAUD)
270 | SRL H
271 | RR L ;DELAY FOR HALF BIT TIME
272 | CALL BITIME
273 | IN A,(KEYBUF)
274 | BIT 7,A
275 | JR NZ,RXDAT1 ;START BIT NOT VALID
276 | ;
277 | ; DETECTED VALID START BIT,READ IN DATA
278 | ;
279 | LD B,08H
280 | RXDAT2:
281 | LD HL,(BAUD)
282 | CALL BITIME ;DELAY ONE BIT TIME
283 | IN A,(KEYBUF)
284 | RL A
285 | RR C ;SHIFT BIT INTO DATA REG
286 | DJNZ RXDAT2
287 | LD A,C
288 | OR A ;CLEAR CARRY FLAG
289 | POP HL
290 | POP BC
291 | RET
292 |
293 | .else ;6850
294 | ;
295 | ; transmit a character in a
296 | ;--------------------------
297 | TXDATA:
298 | TxChar:
299 | push bc
300 | ld b,a ;save the character for later
301 | TxChar1:
302 | in a,(STATUS) ;get the ACIA status
303 | bit 1,a
304 | ; bit TDRE,a ;is the TDRE bit high?
305 | jr z,TxChar1 ;no, the TDR is not empty
306 | ld a,b ;yes, get the character
307 | out (TDR),a ;and put it in the TDR
308 | pop bc
309 | ret
310 | ;
311 | ; receive a character in a
312 | ;---------------------------------
313 | RXDATA:
314 | RxChar:
315 | in a,(STATUS) ;get the ACIA status
316 | bit 0,a
317 | ; bit RDRF,a ;is the RDRF bit high?
318 | jr z,RxChar ;no, the RDR is empty
319 | in a,(RDR) ;yes, read the received char
320 | ret
321 | .endif
322 |
323 | .if LOADER
324 | ; .ORG ROMSTART + $0700
325 | ;-----------------------
326 | ; RECEIVE INTEL HEX FILE
327 | ;-----------------------
328 | INTELH:
329 | LD IX,BUF
330 | ;
331 | ; WAIT FOR RECORD MARK
332 | ;
333 | INTEL1:
334 | XOR A
335 | LD (IX+3),A ;CLEAR CHECKSUM
336 | CALL RXDATA ;WAIT FOR THE RECORD MARK
337 | CP ':' ;TO BE TRANSMITTED
338 | JR NZ,INTEL1 ;NOT RECORD MARK
339 | ;
340 | ; GET RECORD LENGTH
341 | ;
342 | CALL GETBYT
343 | LD (IX+0),A ;NUMBER OF DATA BYTES
344 | ;
345 | ; GET ADDRESS FIELD
346 | ;
347 | CALL GETBYT
348 | LD (IX+2),A ;LOAD ADDRESS HIGH BYTE
349 | CALL GETBYT
350 | LD (IX+1),A ;LOAD ADDRESS LOW BYTE
351 | ;
352 | ; GET RECORD TYPE
353 | ;
354 | CALL GETBYT
355 | JR NZ,INTEL4 ;END OF FILE RECORD
356 | ;
357 | ; READ IN THE DATA
358 | ;
359 | LD B,(IX+0) ;NUMBER OF DATA BYTES
360 | LD H,(IX+2) ;LOAD ADDRESS HIGH BYTE
361 | LD L,(IX+1) ;LOAD ADDRESS LOW BYTE
362 |
363 | INTEL2:
364 | CALL GETBYT ;GET DATA BYTE
365 | LD (HL),A ;STORE DATA BYTE
366 | INC HL
367 | DJNZ INTEL2 ;LOAD MORE BYTES
368 | ;
369 | ; GET CHECKSUM AND COMPARE
370 | ;
371 | LD A,(IX+3) ;CONVERT CHECKSUM TO
372 | NEG ;TWO'S COMPLEMENT
373 | LD (IX+4),A ;SAVE COMPUTED CHECKSUM
374 | CALL GETBYT
375 | LD (IX+3),A ;SAVE RECORD CHECKSUM
376 | CP (IX+4) ;COMPARE CHECKSUM
377 | JR Z,INTEL1 ;CHECKSUM OK,NEXT RECORD
378 | RET ;NZ=CHECKSUM ERROR
379 | ;
380 | ; END OF FILE RECORD
381 | ;
382 | INTEL4:
383 | LD A,(IX+3) ;CONVERT CHECKSUM TO
384 | NEG ;TWO'S COMPLEMENT
385 | LD (IX+4),A ;SAVE COMPUTED CHECKSUM
386 | CALL GETBYT
387 | LD (IX+3),A ;SAVE EOF CHECKSUM
388 | CP (IX+4) ;COMPARE CHECKSUM
389 | RET ;NZ=CHECKSUM ERROR
390 | ;--------------------------
391 | ; GET BYTE FROM SERIAL PORT
392 | ;--------------------------
393 | GETBYT:
394 | PUSH BC
395 | CALL RXDATA
396 | BIT 6,A
397 | JR Z,GETBT1
398 | ADD A,09H
399 | GETBT1:
400 | AND 0FH
401 | SLA A
402 | SLA A
403 | SLA A
404 | SLA A
405 | LD C,A
406 | ;
407 | ; GET LOW NYBBLE
408 | ;
409 | CALL RXDATA
410 | BIT 6,A
411 | JR Z,GETBT2
412 | ADD A,09H
413 | GETBT2 AND 0FH
414 | OR C
415 | LD B,A
416 | ADD A,(IX+3)
417 | LD (IX+3),A ;ADD TO CHECKSUM
418 | LD A,B
419 | AND A ;CLEAR CARRY
420 | POP BC
421 | RET
422 | .endif
423 |
424 | ; in this example code just wait for an INTEL Hex file download
425 | ;just going to send a char to let you know I'm here
426 | .if LOADER
427 |
428 | Load:
429 | ld a,'L' ; L for load
430 | call TxChar
431 | call INTELH
432 | jp z,RAMSTART ;assume the downloaded code starts here
433 | ld a,'0' ;0 is false
434 | call TxChar
435 | jr load ;if at first you don't succeed...
436 | .endif
437 |
438 | getchar:
439 | LD HL,(GETCVEC)
440 | JP (HL)
441 |
442 | putchar:
443 | PUSH HL
444 | LD HL,(PUTCVEC)
445 | EX (SP),HL
446 | RET
447 |
448 | ISR:
449 | ld h,0
450 | ld (vIntID),hl
451 | call enter
452 | .cstr "Z"
453 | ret
454 |
455 | RESET:
456 | ld SP,stack
457 | LD HL,IntRet
458 | LD (RST08),HL
459 | LD (RST10),HL
460 | LD (RST18),HL
461 | LD (RST20),HL
462 | LD (RST28),HL
463 | LD (RST30),HL
464 | LD (INTVEC),HL
465 | LD (NMIVEC),HL
466 |
467 | LD HL,RXDATA
468 | LD (GETCVEC),HL
469 | LD HL,TXDATA
470 | LD (PUTCVEC),HL
471 |
472 | .if TEC_1
473 | .if BITBANG = 0
474 |
475 | ld a,MRESET
476 | out (CONTROL),a ;reset the ACIA
477 |
478 | .endif
479 | .endif
480 |
481 | call PWRUP
482 | IM 1
483 | EI
484 |
485 | .if TEC_1
486 | .if BITBANG
487 |
488 | ;inline serial initialisation
489 | LD A,$40
490 | LD C,SCAN
491 | OUT (C),A
492 | LD HL,B4800
493 | LD (BAUD),HL
494 |
495 | .else ;6850
496 |
497 | ld a,RTSLID+F8N2+DIV_64
498 | out (CONTROL),a ;initialise ACIA 8 bit word, No parity 2 stop divide by 64 for 115200 baud
499 |
500 | .endif
501 | .endif
502 |
503 |
504 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/MAIN.asm:
--------------------------------------------------------------------------------
1 | ; *************************************************************************
2 | ;
3 | ; MINT 2.0 Minimal Interpreter for the Z80
4 | ;
5 | ; John Hardy and Ken Boak
6 | ; incorporates bit-bang serial routines by Craig Jones
7 | ;
8 | ; GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
9 | ;
10 | ; see the LICENSE file in this repo for more information
11 | ;
12 | ; *****************************************************************************
13 | TRUE EQU -1
14 | FALSE EQU 0
15 | UNLIMITED EQU -1
16 |
17 | CTRL_C equ 3
18 | CTRL_E equ 5
19 | CTRL_H equ 8
20 | CTRL_L equ 12
21 | CTRL_R equ 18
22 | CTRL_S equ 19
23 |
24 | BSLASH equ $5c
25 |
26 | .macro LITDAT,len
27 | db len
28 | .endm
29 |
30 | .macro REPDAT,len,data ; compress the command tables
31 |
32 | db (len | $80)
33 | db data
34 | .endm
35 |
36 | .macro ENDDAT
37 | db 0
38 | .endm
39 |
40 | ; **************************************************************************
41 | ; Page 0 Initialisation
42 | ; **************************************************************************
43 |
44 | .ORG ROMSTART + $180 ; 0+180 put mint code from here
45 |
46 | ; **************************************************************************
47 | ; Macros must be written in Mint and end with ;
48 | ; this code must not span pages
49 | ; **************************************************************************
50 | macros:
51 |
52 | reedit_:
53 | db "/z/Z;" ; remembers last line edited
54 |
55 | edit_:
56 | .cstr "`?`/K/P/Z;"
57 |
58 | list_:
59 | .cstr "/N26(/i65+/Z/k0>(/N))/P;"
60 |
61 | printStack_:
62 | .cstr "`=> `/s2- /D1-(",$22,",2-)'/N/P;"
63 |
64 | iOpcodes:
65 | LITDAT 15
66 | db lsb(bang_) ; !
67 | db lsb(dquote_) ; "
68 | db lsb(hash_) ; #
69 | db lsb(dollar_) ; $
70 | db lsb(percent_) ; %
71 | db lsb(amper_) ; &
72 | db lsb(quote_) ; '
73 | db lsb(lparen_) ; (
74 | db lsb(rparen_) ; )
75 | db lsb(star_) ; *
76 | db lsb(plus_) ; +
77 | db lsb(comma_) ; ,
78 | db lsb(minus_) ; -
79 | db lsb(dot_) ; .
80 | db lsb(slash_) ; /
81 |
82 | REPDAT 10, lsb(num_) ; 10 x repeat lsb of add to the num routine
83 |
84 | LITDAT 7
85 | db lsb(colon_) ; :
86 | db lsb(semi_) ; ;
87 | db lsb(lt_) ; <
88 | db lsb(eq_) ; =
89 | db lsb(gt_) ; >
90 | db lsb(question_) ; ?
91 | db lsb(at_) ; @
92 |
93 | REPDAT 26, lsb(call_) ; call a command a, B ....Z
94 |
95 | LITDAT 6
96 | db lsb(lbrack_) ; [
97 | db lsb(bslash_) ; \
98 | db lsb(rbrack_) ; ]
99 | db lsb(caret_) ; ^
100 | db lsb(underscore_) ; _
101 | db lsb(grave_) ; ` ; for printing `hello`
102 |
103 | REPDAT 26, lsb(var_) ; a b c .....z
104 |
105 | LITDAT 4
106 | db lsb(lbrace_) ; {
107 | db lsb(pipe_) ; |
108 | db lsb(rbrace_) ; }
109 | db lsb(tilde_) ; ~ ( a b c -- b c a ) rotate
110 |
111 | iAltCodes:
112 |
113 | LITDAT 26
114 | db lsb(alloc_) ;A allocate some heap memory
115 | db lsb(aNop_) ;B
116 | db lsb(printChar_) ;C print a char
117 | db lsb(depth_) ;D depth of stack
118 | db lsb(else_) ;E else
119 | db lsb(falsex_) ;F false condition
120 | db lsb(go_) ;G go execute mint code
121 | db lsb(aNop_) ;H
122 | db lsb(inPort_) ;I input from port
123 | db lsb(aNop_) ;J
124 | db lsb(key_) ;K read a char from input
125 | db lsb(aNop_) ;L
126 | db lsb(aNop_) ;M
127 | db lsb(newln_) ;N prints a newline to output
128 | db lsb(outPort_) ;O output to port
129 | db lsb(prompt_) ;P print MINT prompt
130 | db lsb(aNop_) ;Q
131 | db lsb(aNop_) ;R
132 | db lsb(arrSize_) ;S array size
133 | db lsb(truex_) ;T true condition
134 | db lsb(unlimit_) ;U unlimited loop
135 | db lsb(varAccess_) ;V address of last access
136 | db lsb(while_) ;W conditional break from loop
137 | db lsb(exec_) ;X execute machine code
138 | db lsb(aNop_) ;Y
139 | db lsb(editDef_) ;Z edit line
140 | ENDDAT
141 |
142 | backSpace:
143 | ld a,c
144 | or b
145 | jr z, interpret2
146 | dec bc
147 | call printStr
148 | .cstr "\b \b"
149 | jr interpret2
150 |
151 | start:
152 | ld SP,DSTACK ; start of MINT
153 | call init ; setups
154 | call printStr ; prog count to stack, put code line 235 on stack then call print
155 | .cstr "MINT2.0\r\n"
156 |
157 | interpret:
158 | call prompt
159 |
160 | ld bc,0 ; load bc with offset into TIB, decide char into tib or execute or control
161 | ld (vTIBPtr),bc
162 |
163 | interpret2: ; calc nesting (a macro might have changed it)
164 | ld E,0 ; initilize nesting value
165 | push bc ; save offset into TIB,
166 | ; bc is also the count of chars in TIB
167 | ld hl,TIB ; hl is start of TIB
168 | jr interpret4
169 |
170 | interpret3:
171 | ld a,(hl) ; A = char in TIB
172 | inc hl ; inc pointer into TIB
173 | dec bc ; dec count of chars in TIB
174 | call nesting ; update nesting value
175 |
176 | interpret4:
177 | ld a,C ; is count zero?
178 | or B
179 | jr NZ, interpret3 ; if not loop
180 | pop bc ; restore offset into TIB
181 |
182 | waitchar:
183 | call getchar ; loop around waiting for character from serial port
184 | cp $20 ; compare to space
185 | jr NC,waitchar1 ; if >= space, if below 20 set cary flag
186 | cp $0 ; is it end of string? null end of string
187 | jr Z,waitchar4
188 | cp '\r' ; carriage return? ascii 13
189 | jr Z,waitchar3 ; if anything else its macro/control
190 | cp CTRL_H
191 | jr z,backSpace
192 | ld d,msb(macros)
193 | cp CTRL_E
194 | ld e,lsb(edit_)
195 | jr z,macro
196 | cp CTRL_R
197 | ld e,lsb(reedit_)
198 | jr z,macro
199 | cp CTRL_L
200 | ld e,lsb(list_)
201 | jr z,macro
202 | cp CTRL_S
203 | ld e,lsb(printStack_)
204 | jr z,macro
205 | jr interpret2
206 |
207 | macro:
208 | ld (vTIBPtr),bc
209 | push de
210 | call ENTER ;mint go operation and jump to it
211 | .cstr "/G"
212 | ld bc,(vTIBPtr)
213 | jr interpret2
214 |
215 | waitchar1:
216 | ld hl,TIB
217 | add hl,bc
218 | ld (hl),A ; store the character in textbuf
219 | inc bc
220 | call putchar ; echo character to screen
221 | call nesting
222 | jr waitchar ; wait for next character
223 |
224 | waitchar3:
225 | ld hl,TIB
226 | add hl,bc
227 | ld (hl),"\r" ; store the crlf in textbuf
228 | inc hl
229 | ld (hl),"\n"
230 | inc hl ; ????
231 | inc bc
232 | inc bc
233 | call crlf ; echo character to screen
234 | ld a,E ; if zero nesting append and ETX after \r
235 | or A
236 | jr NZ,waitchar
237 | ld (hl),$03 ; store end of text ETX in text buffer
238 | inc bc
239 |
240 | waitchar4:
241 | ld (vTIBPtr),bc
242 | ld bc,TIB ; Instructions stored on heap at address HERE, we pressed enter
243 | dec bc
244 |
245 | NEXT:
246 | inc bc ; Increment the IP
247 | ld a,(bc) ; Get the next character and dispatch
248 | or a ; is it NUL?
249 | jr z,exit
250 | cp CTRL_C
251 | jr z,etx
252 | sub "!"
253 | jr c,NEXT
254 | ld L,A ; Index into table
255 | ld H,msb(opcodes) ; Start address of jump table
256 | ld L,(hl) ; get low jump address
257 | ld H,msb(page4) ; Load H with the 1st page address
258 | jp (hl) ; Jump to routine
259 |
260 | exit:
261 | inc bc ; store offests into a table of bytes, smaller
262 | ld de,bc
263 | call rpop ; Restore Instruction pointer
264 | ld bc,hl
265 | EX de,hl
266 | jp (hl)
267 |
268 | etx:
269 | ld hl,-DSTACK ; check if stack pointer is underwater
270 | add hl,SP
271 | jr NC,etx1
272 | ld SP,DSTACK
273 | etx1:
274 | jp interpret
275 |
276 | init:
277 | ld IX,RSTACK
278 | ld IY,NEXT ; IY provides a faster jump to NEXT
279 |
280 | ld hl,vars
281 | ld de,hl
282 | inc de
283 | ld (hl),0
284 | ld bc,VARS_SIZE * 3 ; init vars, defs and altVars
285 | LDIR
286 |
287 | ld hl,dStack
288 | ld (vStkStart),hl
289 | ld hl,65
290 | ld (vLastDef),hl
291 | ld hl,HEAP
292 | ld (vHeapPtr),hl
293 |
294 | initOps:
295 | ld hl, iOpcodes
296 | ld de, opcodes
297 | ld bc, $80-32-1-1+26
298 |
299 | initOps1:
300 | ld a,(hl)
301 | inc hl
302 | SLA A
303 | ret Z
304 | jr C, initOps2
305 | SRL A
306 | ld C,A
307 | ld B,0
308 | LDIR
309 | jr initOps1
310 |
311 | initOps2:
312 | SRL A
313 | ld B,A
314 | ld a,(hl)
315 | inc hl
316 | initOps2a:
317 | ld (de),A
318 | inc de
319 | DJNZ initOps2a
320 | jr initOps1
321 |
322 | lookupRef0:
323 | ld hl,defs
324 | sub "A"
325 | jr lookupRef1
326 | lookupRef:
327 | sub "a"
328 | lookupRef1:
329 | add a,a
330 | add a,l
331 | ld l,a
332 | ld a,0
333 | ADC a,h
334 | ld h,a
335 | XOR a
336 | or e ; sets Z flag if A-Z
337 | ret
338 |
339 | printhex:
340 | ; Display hl as a 16-bit number in hex.
341 | push bc ; preserve the IP
342 | ld a,H
343 | call printhex2
344 | ld a,L
345 | call printhex2
346 | pop bc
347 | ret
348 | printhex2:
349 | ld C,A
350 | RRA
351 | RRA
352 | RRA
353 | RRA
354 | call printhex3
355 | ld a,C
356 | printhex3:
357 | and 0x0F
358 | add a,0x90
359 | DAA
360 | ADC a,0x40
361 | DAA
362 | jp putchar
363 |
364 | ; **************************************************************************
365 | ; calculate nesting value
366 | ; A is char to be tested,
367 | ; E is the nesting value (initially 0)
368 | ; E is increased by ( and [
369 | ; E is decreased by ) and ]
370 | ; E has its bit 7 toggled by `
371 | ; limited to 127 levels
372 | ; **************************************************************************
373 |
374 | nesting:
375 | cp '`'
376 | jr NZ,nesting1
377 | ld a,$80
378 | xor e
379 | ld e,a
380 | ret
381 | nesting1:
382 | BIT 7,E
383 | ret NZ
384 | cp ':'
385 | jr Z,nesting2
386 | cp '['
387 | jr Z,nesting2
388 | cp '('
389 | jr NZ,nesting3
390 | nesting2:
391 | inc E
392 | ret
393 | nesting3:
394 | cp ';'
395 | jr Z,nesting4
396 | cp ']'
397 | jr Z,nesting4
398 | cp ')'
399 | ret NZ
400 | nesting4:
401 | dec E
402 | ret
403 |
404 | prompt:
405 | call printStr
406 | .cstr "\r\n> "
407 | ret
408 |
409 | crlf:
410 | call printStr
411 | .cstr "\r\n"
412 | ret
413 |
414 | printStr:
415 | EX (SP),hl ; swap
416 | call putStr
417 | inc hl ; inc past null
418 | EX (SP),hl ; put it back
419 | ret
420 |
421 | putStr0:
422 | call putchar
423 | inc hl
424 | putStr:
425 | ld a,(hl)
426 | or A
427 | jr NZ,putStr0
428 | ret
429 |
430 | rpush:
431 | dec IX
432 | ld (IX+0),H
433 | dec IX
434 | ld (IX+0),L
435 | ret
436 |
437 | rpop:
438 | ld L,(IX+0)
439 | inc IX
440 | ld H,(IX+0)
441 | inc IX
442 | rpop2:
443 | ret
444 |
445 | writeChar:
446 | ld (hl),A
447 | inc hl
448 | jp putchar
449 |
450 | enter:
451 | ld hl,bc
452 | call rpush ; save Instruction Pointer
453 | pop bc
454 | dec bc
455 | jp (iy)
456 |
457 | carry:
458 | ld hl,0
459 | rl l
460 | ld (vCarry),hl
461 | jp (iy)
462 |
463 | setByteMode:
464 | ld a,$FF
465 | jr assignByteMode
466 | resetByteMode:
467 | xor a
468 | assignByteMode:
469 | ld (vByteMode),a
470 | ld (vByteMode+1),a
471 | jp (iy)
472 |
473 | false_:
474 | ld hl,FALSE
475 | jr true1
476 |
477 | true_:
478 | ld hl,TRUE
479 | true1:
480 | push hl
481 | jp (iy)
482 |
483 | ; **********************************************************************
484 | ; Page 4 primitive routines
485 | ; **********************************************************************
486 | .align $100
487 | page4:
488 |
489 | quote_: ; Discard the top member of the stack
490 | pop hl
491 | at_:
492 | underscore_:
493 | jp (iy)
494 |
495 | bslash_:
496 | jr setByteMode
497 |
498 | var_:
499 | ld a,(bc)
500 | ld hl,vars
501 | call lookupRef
502 | var1:
503 | ld (vPointer),hl
504 | ld d,0
505 | ld e,(hl)
506 | ld a,(vByteMode)
507 | inc a ; is it byte?
508 | jr z,var2
509 | inc hl
510 | ld d,(hl)
511 | var2:
512 | push de
513 | jr resetByteMode
514 |
515 | bang_: ; Store the value at the address placed on the top of the stack
516 | assign:
517 | pop hl ; discard value of last accessed variable
518 | pop de ; new value
519 | ld hl,(vPointer)
520 | ld (hl),e
521 | ld a,(vByteMode)
522 | inc a ; is it byte?
523 | jr z,assign1
524 | inc hl
525 | ld (hl),d
526 | assign1:
527 | jr resetByteMode
528 |
529 | amper_:
530 | pop de ; Bitwise and the top 2 elements of the stack
531 | pop hl
532 | ld a,E
533 | and L
534 | ld L,A
535 | ld a,D
536 | and H
537 | and1:
538 | ld h,a
539 | and2:
540 | push hl
541 | jp (iy)
542 |
543 | pipe_:
544 | pop de ; Bitwise or the top 2 elements of the stack
545 | pop hl
546 | ld a,E
547 | or L
548 | ld L,A
549 | ld a,D
550 | or h
551 | jr and1
552 |
553 | caret_:
554 | pop de ; Bitwise XOR the top 2 elements of the stack
555 | xor1:
556 | pop hl
557 | ld a,E
558 | XOR L
559 | ld L,A
560 | ld a,D
561 | XOR H
562 | jr and1
563 |
564 | tilde_:
565 | invert: ; Bitwise INVert the top member of the stack
566 | ld de, $FFFF ; by xoring with $FFFF
567 | jr xor1
568 |
569 | plus_: ; add the top 2 members of the stack
570 | pop de
571 | pop hl
572 | add hl,de
573 | push hl
574 | jp carry
575 |
576 | call_:
577 | ld a,(bc)
578 | call lookupRef0
579 | ld E,(hl)
580 | inc hl
581 | ld D,(hl)
582 | jp go1
583 |
584 | dot_:
585 | pop hl
586 | call printDec
587 | dot2:
588 | ld a,' '
589 | call putChar
590 | jp (iy)
591 |
592 | comma_: ; print hexadecimal
593 | pop hl
594 | call printhex
595 | jr dot2
596 |
597 | dquote_:
598 | pop hl ; Duplicate the top member of the stack
599 | push hl
600 | push hl
601 | jp (iy)
602 |
603 | jp NEXT ; hardwire white space to always go to NEXT (important for arrays)
604 |
605 | percent_:
606 | pop hl ; Duplicate 2nd element of the stack
607 | pop de
608 | push de
609 | push hl
610 | push de ; and push it to top of stack
611 | jp (iy)
612 |
613 | semi_:
614 | call rpop ; Restore Instruction pointer
615 | ld bc,hl
616 | jp (iy)
617 |
618 | ; Left shift { is multiply by 2
619 | lbrace_:
620 | pop hl ; Duplicate the top member of the stack
621 | add hl,hl
622 | jr and2 ; shift left fallthrough into plus_
623 |
624 | ; Right shift } is a divide by 2
625 | rbrace_:
626 | pop hl ; Get the top member of the stack
627 | shr1:
628 | SRL H
629 | RR L
630 | jr and2
631 |
632 | ; $ swap ; a b -- b a Swap the top 2 elements of the stack
633 | dollar_:
634 | pop hl
635 | EX (SP),hl
636 | jr and2
637 |
638 | minus_: ; Subtract the value 2nd on stack from top of stack
639 | inc bc ; check if sign of a number
640 | ld a,(bc)
641 | dec bc
642 | cp "0"
643 | jr c,sub1
644 | cp "9"+1
645 | jp c,num
646 | sub1:
647 | pop de
648 | pop hl
649 | sub2:
650 | and A
651 | sbc hl,de
652 | push hl
653 | jp carry
654 |
655 | eq_:
656 | pop hl
657 | pop de
658 | or a ; reset the carry flag
659 | sbc hl,de ; only equality sets hl=0 here
660 | jp z,true_
661 | jp false_
662 |
663 | gt_:
664 | pop hl
665 | pop de
666 | jr lt1_
667 |
668 | lt_:
669 | pop de
670 | pop hl
671 |
672 | lt1_:
673 | or a ; reset the carry flag
674 | sbc hl,de ; only equality sets hl=0 here
675 | jp c,true_
676 | jp false_
677 |
678 | grave_:
679 | str:
680 | inc bc
681 |
682 | str1:
683 | ld a, (bc)
684 | inc bc
685 | cp "`" ; ` is the string terminator
686 | jr Z,str2
687 | call putchar
688 | jr str1
689 | str2:
690 | dec bc
691 | jp (IY)
692 |
693 | lbrack_:
694 | arrDef:
695 | ld hl,0
696 | add hl,sp ; save
697 | call rpush
698 | jp (iy)
699 |
700 | num_:
701 | jp num
702 | rparen_:
703 | jp again ; close loop
704 | rbrack_:
705 | jp arrEnd
706 | colon_:
707 | jp def
708 | lparen_:
709 | jp begin
710 |
711 | question_:
712 | jr arrAccess
713 | hash_:
714 | jr hex
715 | star_:
716 | jr mul
717 | slash_:
718 |
719 | alt_: ; falls through (must be on page 4)
720 | ;*******************************************************************
721 | ; Page 5 primitive routines
722 | ;*******************************************************************
723 | alt:
724 | inc bc
725 | ld a,(bc)
726 | cp "z"+1
727 | jr nc,alt1
728 | cp "a"
729 | jr nc,altVar
730 | cp "Z"+1
731 | jr nc,alt1
732 | cp "A"
733 | jr nc,altCode
734 | alt1:
735 | dec bc
736 | jp div
737 |
738 | altVar:
739 | cp "i"
740 | ld l,0
741 | jp z,loopVar
742 | cp "j"
743 | ld l,8
744 | jr z,loopVar
745 | ld hl,altVars
746 | call lookupRef
747 | jp var1
748 |
749 | loopVar:
750 | ld h,0
751 | ld d,ixh
752 | ld e,ixl
753 | add hl,de
754 | jp var1
755 |
756 | comment:
757 | inc bc ; point to next char
758 | ld a,(bc)
759 | cp "\r" ; terminate at cr
760 | jr NZ,comment
761 | dec bc
762 | jp (IY)
763 |
764 | altCode:
765 | ld hl,altCodes
766 | sub "A"
767 | add a,L
768 | ld L,A
769 | ld a,(hl) ; get low jump address
770 | ld hl,page6
771 | ld L,A
772 | jp (hl) ; Jump to routine
773 |
774 | arrAccess:
775 | pop hl ; hl = index
776 | pop de ; de = array
777 | ld a,(vByteMode) ; a = data width
778 | inc a
779 | jr z,arrAccess1
780 | add hl,hl ; if data width = 2 then double
781 | arrAccess1:
782 | add hl,de ; hl = addr
783 | jp var1
784 |
785 | hex:
786 | ld hl,0 ; Clear hl to accept the number
787 | hex1:
788 | inc bc
789 | ld a,(bc) ; Get the character which is a numeral
790 | BIT 6,A ; is it uppercase alpha?
791 | jp Z, hex2 ; no a decimal
792 | sub 7 ; sub 7 to make $A - $F
793 | hex2:
794 | sub $30 ; Form decimal digit
795 | jp C,num2
796 | cp $0F+1
797 | jp NC,num2
798 | add hl,hl ; 2X ; Multiply digit(s) in hl by 16
799 | add hl,hl ; 4X
800 | add hl,hl ; 8X
801 | add hl,hl ; 16X
802 | add a,L ; add into bottom of hl
803 | ld L,A
804 | jp hex1
805 |
806 | mul:
807 | pop de ; de = 2nd arg
808 | pop hl ; hl = 1st arg
809 | push bc ; save IP
810 | ld a,l
811 | ld c,h
812 | ld b,16
813 | ld hl,0
814 | mul1:
815 | add hl,hl
816 | rla
817 | rl c
818 | jr nc,mul2
819 | add hl,de
820 | adc a,0
821 | jp nc,mul2
822 | inc c
823 | mul2:
824 | djnz mul1
825 | ex de,hl ; de = lsw result
826 | ld h,c
827 | ld l,a ; hl = msw result
828 | pop bc ; restore IP
829 | jp divExit ; pushes lsw, puts msw in vRemain
830 |
831 | begin:
832 | loopStart:
833 | ld (vTemp1),bc ; save start
834 | ld e,1 ; skip to loop end, nesting = 1
835 | loopStart1:
836 | inc bc
837 | ld a,(bc)
838 | call nesting ; affects zero flag
839 | jr nz,loopStart1
840 | pop de ; de = limit
841 | ld a,e ; is it zero?
842 | or d
843 | jr nz,loopStart2
844 | dec de ; de = TRUE
845 | ld (vElse),de
846 | jr loopStart4 ; yes continue after skip
847 | loopStart2:
848 | ld a,2 ; is it TRUE
849 | add a,e
850 | add a,d
851 | jr nz,loopStart3
852 | ld de,1 ; yes make it 1
853 | loopStart3:
854 | ld hl,bc
855 | call rpush ; rpush loop end
856 | dec bc ; IP points to ")"
857 | ld hl,(vTemp1) ; restore start
858 | call rpush ; rpush start
859 | ex de,hl ; hl = limit
860 | call rpush ; rpush limit
861 | ld hl,-1 ; hl = count = -1
862 | call rpush ; rpush count
863 | loopstart4:
864 | jp (iy)
865 |
866 | again:
867 | loopEnd:
868 | ld e,(ix+2) ; de = limit
869 | ld d,(ix+3)
870 | ld a,e ; a = lsb(limit)
871 | or d ; if limit 0 exit loop
872 | jr z,loopEnd4
873 | inc de ; is limit -2
874 | inc de
875 | ld a,e ; a = lsb(limit)
876 | or d ; if limit 0 exit loop
877 | jr z,loopEnd2 ; yes, loop again
878 | dec de
879 | dec de
880 | dec de
881 | ld (ix+2),e
882 | ld (ix+3),d
883 | loopEnd2:
884 | ld e,(ix+0) ; inc counter
885 | ld d,(ix+1)
886 | inc de
887 | ld (ix+0),e
888 | ld (ix+1),d
889 | loopEnd3:
890 | ld de,FALSE ; if clause ran then vElse = FALSE
891 | ld (vElse),de
892 | ld c,(ix+4) ; IP = start
893 | ld b,(ix+5)
894 | jp (iy)
895 | loopEnd4:
896 | ld de,2*4 ; rpop frame
897 | add ix,de
898 | jp (iy)
899 |
900 | ; **************************************************************************
901 | ; Page 6 Alt primitives
902 | ; **************************************************************************
903 | .align $100
904 | page6:
905 |
906 | ; allocates raw heap memory in bytes (ignores byte mode)
907 | ; n -- a
908 | alloc_:
909 | pop de
910 | ld hl,(vHeapPtr)
911 | push hl
912 | add hl,de
913 | ld (vHeapPtr),hl
914 | aNop_:
915 | jp (iy)
916 |
917 | ; returns the size of an array
918 | ; a -- n
919 | arrSize_:
920 | arrSize:
921 | pop hl
922 | dec hl ; msb size
923 | ld d,(hl)
924 | dec hl ; lsb size
925 | ld e,(hl)
926 | push de
927 | jp (iy)
928 |
929 | break_:
930 | while_:
931 | while:
932 | pop hl
933 | ld a,l
934 | or h
935 | jr nz,while2
936 | ld c,(ix+6) ; IP = )
937 | ld b,(ix+7)
938 | jp loopEnd4
939 | while2:
940 | jp (iy)
941 |
942 | depth_:
943 | depth:
944 | ld hl,0
945 | add hl,SP
946 | EX de,hl
947 | ld hl,DSTACK
948 | or A
949 | sbc hl,de
950 | jp shr1
951 |
952 | falsex_:
953 | jp false_
954 |
955 | printChar_:
956 | pop hl
957 | ld a,L
958 | call putchar
959 | jp (iy)
960 |
961 | else_:
962 | ld hl,(vElse)
963 | else1:
964 | push hl
965 | jp (iy)
966 |
967 | exec_:
968 | call exec1
969 | jp (iy)
970 | exec1:
971 | pop hl
972 | EX (SP),hl
973 | jp (hl)
974 |
975 | editDef_:
976 | call editDef
977 | jp (iy)
978 |
979 | prompt_:
980 | call prompt
981 | jp (iy)
982 |
983 | go_:
984 | pop de
985 | go1:
986 | ld a,D ; skip if destination address is null
987 | or E
988 | jr Z,go3
989 | ld hl,bc
990 | inc bc ; read next char from source
991 | ld a,(bc) ; if ; to tail call optimise
992 | cp ";" ; by jumping to rather than calling destination
993 | jr Z,go2
994 | call rpush ; save Instruction Pointer
995 | go2:
996 | ld bc,de
997 | dec bc
998 | go3:
999 | jp (iy)
1000 |
1001 | key_:
1002 | call getchar
1003 | ld H,0
1004 | ld L,A
1005 | jr else1
1006 |
1007 | inPort_:
1008 | pop hl
1009 | ld a,C
1010 | ld C,L
1011 | IN L,(C)
1012 | ld H,0
1013 | ld C,A
1014 | jr else1
1015 |
1016 | newln_:
1017 | call crlf
1018 | jp (iy)
1019 |
1020 | outPort_:
1021 | pop hl
1022 | ld E,C
1023 | ld C,L
1024 | pop hl
1025 | OUT (C),L
1026 | ld C,E
1027 | jp (iy)
1028 |
1029 | truex_:
1030 | jp true_
1031 |
1032 | unlimit_:
1033 | ld hl,-2
1034 | jr else1
1035 |
1036 | varAccess_:
1037 | ld hl,vPointer
1038 | ld e,(hl)
1039 | inc hl
1040 | ld d,(hl)
1041 | push de
1042 | jp (iy)
1043 |
1044 | ;*******************************************************************
1045 | ; Subroutines
1046 | ;*******************************************************************
1047 |
1048 | editDef: ; lookup up def based on number
1049 | pop hl ; pop ret address
1050 | EX (SP),hl ; swap with TOS
1051 | ld a,L
1052 | EX AF,AF'
1053 | ld a,l
1054 | call lookupRef0
1055 | ld E,(hl)
1056 | inc hl
1057 | ld D,(hl)
1058 | ld a,D
1059 | or E
1060 | ld hl,TIB
1061 | jr Z,editDef3
1062 | ld a,":"
1063 | call writeChar
1064 | EX AF,AF'
1065 | call writeChar
1066 | jr editDef2
1067 | editDef1:
1068 | inc de
1069 | editDef2:
1070 | ld a,(de)
1071 | call writeChar
1072 | cp ";"
1073 | jr NZ,editDef1
1074 | editDef3:
1075 | ld de,TIB
1076 | or A
1077 | sbc hl,de
1078 | ld (vTIBPtr),hl
1079 | ret
1080 |
1081 | ; hl = value
1082 | printDec:
1083 | bit 7,h
1084 | jr z,printDec2
1085 | ld a,'-'
1086 | call putchar
1087 | xor a
1088 | sub l
1089 | ld l,a
1090 | sbc a,a
1091 | sub h
1092 | ld h,a
1093 | printDec2:
1094 | push bc
1095 | ld c,0 ; leading zeros flag = false
1096 | ld de,-10000
1097 | call printDec4
1098 | ld de,-1000
1099 | call printDec4
1100 | ld de,-100
1101 | call printDec4
1102 | ld e,-10
1103 | call printDec4
1104 | inc c ; flag = true for at least digit
1105 | ld e,-1
1106 | call printDec4
1107 | pop bc
1108 | ret
1109 | printDec4:
1110 | ld b,'0'-1
1111 | printDec5:
1112 | inc b
1113 | add hl,de
1114 | jr c,printDec5
1115 | sbc hl,de
1116 | ld a,'0'
1117 | cp b
1118 | jr nz,printDec6
1119 | xor a
1120 | or c
1121 | ret z
1122 | jr printDec7
1123 | printDec6:
1124 | inc c
1125 | printDec7:
1126 | ld a,b
1127 | jp putchar
1128 |
1129 | ;*******************************************************************
1130 | ; Page 5 primitive routines continued
1131 | ;*******************************************************************
1132 |
1133 | def: ; Create a colon definition
1134 | inc bc
1135 | ld a,(bc) ; Get the next character
1136 | cp "@" ; is it anonymous
1137 | jr nz,def0
1138 | inc bc
1139 | ld de,(vHeapPtr) ; return start of definition
1140 | push de
1141 | jr def1
1142 | def0:
1143 | ld (vLastDef),a
1144 | call lookupRef0
1145 | ld de,(vHeapPtr) ; start of defintion
1146 | ld (hl),E ; Save low byte of address in CFA
1147 | inc hl
1148 | ld (hl),D ; Save high byte of address in CFA+1
1149 | inc bc
1150 | def1: ; Skip to end of definition
1151 | ld a,(bc) ; Get the next character
1152 | inc bc ; Point to next character
1153 | ld (de),A
1154 | inc de
1155 | cp ";" ; Is it a semicolon
1156 | jr Z, def2 ; end the definition
1157 | jr def1 ; get the next element
1158 | def2:
1159 | dec bc
1160 | def3:
1161 | ld (vHeapPtr),de ; bump heap ptr to after definiton
1162 | jp (iy)
1163 |
1164 | num:
1165 | ld hl,$0000 ; Clear hl to accept the number
1166 | ld a,(bc) ; Get numeral or -
1167 | cp '-'
1168 | jr nz,num0
1169 | inc bc ; move to next char, no flags affected
1170 | num0:
1171 | ex af,af' ; save zero flag = 0 for later
1172 | num1:
1173 | ld a,(bc) ; read digit
1174 | sub "0" ; less than 0?
1175 | jr c, num2 ; not a digit, exit loop
1176 | cp 10 ; greater that 9?
1177 | jr nc, num2 ; not a digit, exit loop
1178 | inc bc ; inc IP
1179 | ld de,hl ; multiply hl * 10
1180 | add hl,hl
1181 | add hl,hl
1182 | add hl,de
1183 | add hl,hl
1184 | add a,l ; add digit in a to hl
1185 | ld l,a
1186 | ld a,0
1187 | adc a,h
1188 | ld h,a
1189 | jr num1
1190 | num2:
1191 | dec bc
1192 | ex af,af' ; restore zero flag
1193 | jr nz, num3
1194 | ex de,hl ; negate the value of hl
1195 | ld hl,0
1196 | or a ; jump to sub2
1197 | sbc hl,de
1198 | num3:
1199 | push hl ; Put the number on the stack
1200 | jp (iy) ; and process the next character
1201 |
1202 | arrEnd:
1203 | ld (vTemp1),bc ; save IP
1204 | call rpop
1205 | ld (vTemp2),hl ; save old SP
1206 | ld de,hl ; de = hl = old SP
1207 | or a
1208 | sbc hl,sp ; hl = array count (items on stack)
1209 | srl h ; num items = num bytes / 2
1210 | rr l
1211 | ld bc,hl ; bc = count
1212 | ld hl,(vHeapPtr) ; hl = array[-4]
1213 | ld (hl),c ; write num items in length word
1214 | inc hl
1215 | ld (hl),b
1216 | inc hl ; hl = array[0], bc = count
1217 | ; de = old SP, hl = array[0], bc = count
1218 | jr arrayEnd2
1219 | arrayEnd1:
1220 | dec bc ; dec items count
1221 | dec de
1222 | dec de
1223 | ld a,(de) ; a = lsb of stack item
1224 | ld (hl),a ; write lsb of array item
1225 | inc hl ; move to msb of array item
1226 | ld a,(vByteMode) ; vByteMode=1?
1227 | inc a
1228 | jr z,arrayEnd2
1229 | inc de
1230 | ld a,(de) ; a = msb of stack item
1231 | dec de
1232 | ld (hl),a ; write msb of array item
1233 | inc hl ; move to next word in array
1234 | arrayEnd2:
1235 | ld a,c ; if not zero loop
1236 | or b
1237 | jr nz,arrayEnd1
1238 | ex de,hl ; de = end of array
1239 | ld hl,(vTemp2)
1240 | ld sp,hl ; SP = old SP
1241 | ld hl,(vHeapPtr) ; de = array[-2]
1242 | inc hl
1243 | inc hl
1244 | push hl ; return array[0]
1245 | ld (vHeapPtr),de ; move heap* to end of array
1246 | ld bc,(vTemp1) ; restore IP
1247 | jp resetByteMode
1248 |
1249 | div:
1250 | ld hl,bc ; hl = IP
1251 | pop bc ; bc = denominator
1252 | ex (sp),hl ; save IP, hl = numerator
1253 | ld a,h
1254 | xor b
1255 | push af
1256 | xor b
1257 | jp p,absbc
1258 | ;absHL
1259 | xor a
1260 | sub l
1261 | ld l,a
1262 | sbc a,a
1263 | sub h
1264 | ld h,a
1265 | absbc:
1266 | xor b
1267 | jp p,$+9
1268 | xor a
1269 | sub c
1270 | ld c,a
1271 | sbc a,a
1272 | sub b
1273 | ld b,a
1274 | add hl,hl
1275 | ld a,15
1276 | ld de,0
1277 | ex de,hl
1278 | jr jumpin
1279 | Loop1:
1280 | add hl,bc ;--
1281 | Loop2:
1282 | dec a ;4
1283 | jr z,EndSDiv ;12|7
1284 | jumpin:
1285 | sla e ;8
1286 | rl d ;8
1287 | adc hl,hl ;15
1288 | sbc hl,bc ;15
1289 | jr c,Loop1 ;23-2b
1290 | inc e ;--
1291 | jp Loop2 ;--
1292 | EndSDiv:
1293 | pop af
1294 | jp p,div10
1295 | xor a
1296 | sub e
1297 | ld e,a
1298 | sbc a,a
1299 | sub d
1300 | ld d,a
1301 | div10:
1302 | pop bc
1303 | divExit:
1304 | push de ; quotient
1305 | ld (vRemain),hl ; remainder
1306 | jp (iy)
1307 |
1308 | ; *******************************************************************************
1309 | ; ********* END OF MAIN ******************************************************
1310 | ; *******************************************************************************
1311 | ; *******************************************************************************
1312 |
--------------------------------------------------------------------------------
/MINT – Forth2020_presentation_10_5_25.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orgMINT/MINT/4efa64e621380732ccac84d00a188224e707d224/MINT – Forth2020_presentation_10_5_25.pptx
--------------------------------------------------------------------------------
/MINT – Forth’s Kid Brother.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orgMINT/MINT/4efa64e621380732ccac84d00a188224e707d224/MINT – Forth’s Kid Brother.pptx
--------------------------------------------------------------------------------
/MINT-Forth's Kid Brother.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orgMINT/MINT/4efa64e621380732ccac84d00a188224e707d224/MINT-Forth's Kid Brother.pptx
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MINT Language 2.0
2 |
3 | MINT is a minimalist character-based interpreter but one which aims at fast performance, readability and ease of use. It is written for the Z80 microprocessor and is 2K.
4 |
5 | - [What is MINT?](#what-is-mint)
6 | - [Reverse Polish Notation (RPN)](<#reverse-polish-notation-(rpn)>)
7 | - [Numbers in MINT](#numbers-in-mint)
8 | - [Decimal numbers](#decimal-numbers)
9 | - [Hexadecimal numbers](#hexadecimal-numbers)
10 | - [Formatting numbers](#formatting-numbers)
11 | - [Printing](#printing)
12 | - [Printing numbers](#printing-numbers)
13 | - [Printing text](#printing-text)
14 | - [Stack Manipulation in MINT](#stack-maniplation-in-mint)
15 | - [Duplicate](#duplicate)
16 | - [Drop](#drop)
17 | - [Swap](#swap)
18 | - [Over](#over)
19 | - [Rotate](#rotate)
20 | - [Basic arithmetic operations](#basic-arithmetic-operations)
21 | - [Logical operators](#logical-operators)
22 | - [Variables](#variables)
23 | - [Arrays](#arrays)
24 | - [Basic arrays](#basic-arrays)
25 | - [Array size](#array-size)
26 | - [Nested arrays](#nested-arrays)
27 | - [Byte arrays](#byte-arrays)
28 | - [Memory allocation](#memory-allocation)
29 | - [Loops](#loops)
30 | - [Conditional code](#conditional-code)
31 | - [Functions in MINT](#functions-in-mint)
32 | - [Function with multiple arguments](#function-with-multiple-arguments)
33 | - [Calling functions](#calling-functions)
34 | - [Using functions](#using-functions)
35 | - [Anonymous functions](#anonymous-functions)
36 | - [Appendices](#appendices)
37 | - [Using MINT on the TEC-1](#using-mint-on-the-tec-1)
38 | - [List of operators](#list-of-operators)
39 | - [Maths Operators](#maths-operators)
40 | - [Logical Operators](#logical-operators-1)
41 | - [Stack Operations](#stack-operations)
42 | - [Input & Output Operations](#input-&-output-operations)
43 | - [Functions](#functions)
44 | - [Loops and conditional execution](#loops-and-conditional-execution)
45 | - [Memory and Variable Operations](#memory-and-variable-operations)
46 | - [Array Operations](#array-operations)
47 | - [Byte Mode Operations](#byte-mode)
48 | - [System variables](#system-variables)
49 | - [Miscellaneous](#miscellaneous)
50 | - [Utility commands](#utility-commands)
51 | - [Control keys](#control-keys)
52 |
53 | ## What is MINT?
54 |
55 | MINT is a bytecode interpreter - this means that all of its instructions are 1 byte long. However,
56 | the choice of instruction uses printable ASCII characters, as a human readable alternative to assembly
57 | language. The interpreter handles 16-bit integers and addresses which is sufficient for small applications
58 | running on an 8-bit cpu.
59 |
60 | ## Reverse Polish Notation (RPN)
61 |
62 | RPN is a [concatenative](https:/concatenative.org/wiki/view/Concatenative%20language)
63 | way of writing expressions in which the operators come after their operands. Concatenative
64 | languages make use of a stack which is uses to collect data to do work on. The results
65 | are pushed back on the stack.
66 |
67 | Here is an example of a simple MINT program that uses RPN:
68 |
69 | ```
70 | 10 20 + .
71 | ```
72 |
73 | As the interpreter encounters numbers it pushes them on to the stack. Then it encounters the
74 | `+` operator which is uses to add the two items on the stack and pushes the result back on the stack.
75 | The result becomes the data for the `.` operator which prints the number to the console.
76 |
77 | ## Numbers in MINT
78 |
79 | MINT on the Z80 uses 16-bit integers to represent numbers. A valid (but not very
80 | interesting) MINT program can be simply a sequence of numbers. Nothing will happen
81 | to them though until the program encounters an operator.
82 |
83 | There are two main types of numbers in MINT: decimal numbers and hexadecimal numbers.
84 |
85 | ### Decimal numbers
86 |
87 | Decimal numbers are represented in MINT in the same way that they are represented
88 | in most other programming languages. For example, the number `12345` is represented
89 | as `12345`. A negative number is preceded by a `-` as in `-786`.
90 |
91 | ### Hexadecimal numbers
92 |
93 | Hexadecimal numbers are represented in MINT using the uppercase letters `A` to `F`
94 | to represent the digits `10` to `15`. Hexadecimal numbers are prefixed with a `#`.
95 | So for example, the hexadecimal number `1F3A` is represented as `#1F3A`.
96 | Unlike decimal numbers, hexadecimal numbers are assumed to be positive in MINT.
97 |
98 | ## Printing
99 |
100 | ### Printing numbers
101 |
102 | MINT provides commands for printing numbers in decimal and hexadecimal format.
103 |
104 | The `.` operator prints numbers to the console in decimal.
105 | The `,` operator prints numbers to the console in hexadecimal.
106 |
107 | ### Printing text
108 |
109 | MINT allows the user to easily print literal text by using \` quotes.
110 |
111 | For example
112 |
113 | ```
114 | 100 x !
115 | `The value of x is ` x .
116 | ```
117 |
118 | prints `The value of x is 100`
119 |
120 | ## Stack Manipulation in MINT
121 |
122 | In MINT, the stack is a central data structure that stores values temporarily.
123 | It's essential to master stack manipulation to write effective code. Let's explore
124 | some fundamental operator that help you manage the stack
125 |
126 | ### Duplicate
127 |
128 | The `"` or "dup" operator _duplicates_ the top element of the stack.
129 |
130 | ```
131 | 10 " . .
132 | ```
133 |
134 | The code prints `10 10`
135 |
136 | ### Drop
137 |
138 | The `'` or "drop" removes the top element of the stack.
139 |
140 | ```
141 | 20 30 ' .
142 | ```
143 |
144 | The code prints `20`
145 |
146 | ### Swap
147 |
148 | The `$` of "swap" operator exchanges the positions of the top two elements on the stack.
149 |
150 | ```
151 | 40 50 $ . .
152 | ```
153 |
154 | The code prints `50 40`
155 |
156 | ### Over
157 |
158 | The `%` of "over" operator copies the second element from the top of the stack and
159 | places it on top.
160 |
161 | ```
162 | 60 70 % . . .
163 | ```
164 |
165 | The code prints `70 60 70`
166 |
167 | ## Basic arithmetic operations
168 |
169 | ```
170 | 10 20 + .
171 | ```
172 |
173 | This program adds `20` from `10` which results in the value `30`
174 | The `.` operator prints the sum.
175 |
176 | ```
177 | 5 4 * .
178 | ```
179 |
180 | In this program the numbers `5` and `4` are operands to the operator `*` which
181 | multiplies them together. The `.` operator prints the result of the
182 | multiplication.
183 |
184 | NOTE: For multiplications that result in a value greater than #FFFF, the `overflow` of the
185 | last multiplication operation is available in the /r system variable.
186 |
187 | ```
188 | /r .
189 | ```
190 |
191 | ```
192 | 10 20 - .
193 | ```
194 |
195 | This program subtracts `20` from `10` which results in the negative value `-10`
196 | The `.` operator prints the difference.
197 |
198 | ```
199 | 5 4 / .
200 | ```
201 |
202 | This program divides 5 with 4 prints the result.
203 |
204 | The remainder of the last division operation is available in the /r
205 | system variable.
206 |
207 | ```
208 | /r .
209 | ```
210 |
211 | ## Logical operators
212 |
213 | MINT uses numbers to define boolean values.
214 |
215 | - false is represented by the number `0` or `/F`
216 | - true is represented by the number `1` or `/T`
217 |
218 | ```
219 | 3 0 = .
220 | ```
221 |
222 | prints `0`
223 |
224 | ```
225 | 0 0 = .
226 | ```
227 |
228 | prints `1`
229 |
230 | MINT has a set of bitwise logical operators that can be used to manipulate bits. These operators are:
231 |
232 | ```
233 | & performs a bitwise AND operation on the two operands.
234 | | performs a bitwise OR operation on the two operands.
235 | ^ performs a bitwise XOR operation on the two operands.
236 | { shifts the bits of the operand to the left by one.
237 | } shifts the bits of the operand to the right by one.
238 | ```
239 |
240 | The bitwise logical operators can be used to perform a variety of operations on bits, such as:
241 |
242 | - Checking if a bit is set or unset.
243 | - Setting or clearing a bit.
244 | - Flipping a bit.
245 | - Counting the number of set bits in a number.
246 |
247 | Here is an example of how to use the bitwise logical operators in MINT:
248 |
249 | Check if the first bit of the number 10 is set
250 |
251 | ```
252 | 11 1 & ,
253 | ```
254 |
255 | this will print 0001
256 |
257 | Shift 1 three times to the left (i.e. multiple by 8) and then OR 1 with the least significant bit.
258 |
259 | ```
260 | 1 {{{ 1 | ,
261 | ```
262 |
263 | prints 0009
264 |
265 | Shift 1 two times to the left (i.e. multiple by 4) and then XOR #000F and then mask with #000F.
266 |
267 | ```
268 | 1 {{ #F ^ #F & ,
269 | ```
270 |
271 | prints 000B
272 |
273 | ## Variables
274 |
275 | Variables are named locations in memory that can store data. MINT has a limited
276 | number of global variables which have single letter names. In MINT a variable can
277 | be referred to by a singer letter from `a` to `z` so there are 26
278 | global variables in MINT. Global variables can be used to store numbers, strings, arrays, blocks, functions etc.
279 |
280 | To assign the value `10` to the global variable `x` use the `!` operator.
281 |
282 | ```
283 | 10 x !
284 | ```
285 |
286 | In this example, the number `10` is assigned to the variable `x`
287 |
288 | To access a value in a variable `x`, simply refer to it in your code.
289 | The code below adds `3` to the value stored in variable `x` and then prints it.
290 |
291 | ```
292 | 3 x + .
293 | ```
294 |
295 | The following code assigns the hexadecimal number `#3FFF` to variable `a`
296 | The second line fetches the value stored in `a` and prints it.
297 |
298 | ```
299 | #3FFF a !
300 | a .
301 | ```
302 |
303 | In this longer example, the number 10 is stored in `a` and the number `20` is
304 | stored in `b`. The values in these two variables are then added together and the answer
305 | `30` is stored in `z`. Finally `z` is printed.
306 |
307 | ```
308 | 10 a !
309 | 20 b !
310 | a b + z !
311 | z .
312 | ```
313 |
314 | ## Arrays
315 |
316 | ### Basic arrays
317 |
318 | MINT arrays are a type of data structure that can be used to store a collection of elements. Arrays are indexed, which means that each element in the array has a unique number associated with it. This number is called the index of the element.
319 | In MINT, array indexes start at 0
320 |
321 | To create a MINT array, you can use the following syntax:
322 |
323 | _[ element1 element2 ... ]_
324 |
325 | for example
326 |
327 | ```
328 | [ 1 2 3 ]
329 | ```
330 |
331 | Arrays can be assigned to variables just like number values
332 |
333 | ```
334 | [ 1 2 3 ] a !
335 | ```
336 |
337 | An array of 16-bit numbers can be defined by enclosing them within square brackets:
338 |
339 | ```
340 | [ 1 2 3 4 5 6 7 8 9 0 ]
341 | ```
342 |
343 | Defining an array puts its start address onto the stack
344 |
345 | These can then be allocated to a variable, which acts as a pointer to the array in memory
346 |
347 | ```
348 | [ 1 2 3 4 5 6 7 8 9 0 ] a !
349 | ```
350 |
351 | To fetch the Nth member of the array, we can create use the index operator `?`
352 |
353 | The following prints the item at index 2 (which is 3).
354 |
355 | ```
356 | [ 1 2 3 ] 2? .
357 | ```
358 |
359 | ### Array size
360 |
361 | The size of an array can be determined with the `/S` operator which puts the number
362 | of items in the array on the stack.
363 |
364 | The following prints 5 on the console.
365 |
366 | ```
367 | [ 1 2 3 4 5 ] /S .
368 | ```
369 |
370 | ### Nested arrays
371 |
372 | In MINT arrays can be nested inside one another.
373 |
374 | The following code shows an array with another array as its second item.
375 | This code accesses the second item of the first array with `1?`. It then accesses
376 | the first item of the inner array with `0?` and prints the result (which is 2).
377 |
378 | ```
379 | [1 [2 3]] 1? 0? .
380 | ```
381 |
382 | ### Byte arrays
383 |
384 | MINT by default declares arrays of 16 bit words however it is also possible to declare
385 | and array of 8 bit byte values by using `\` which puts MINT into `byte mode`.
386 |
387 | ```
388 | \[1 2 3]
389 | ```
390 |
391 | The size of a byte array can be determined with the `/S` operator.
392 | The following code prints 3.
393 |
394 | ```
395 | \[1 2 3] /S .
396 | ```
397 |
398 | The following prints 2
399 |
400 | ```
401 | \[1 2 3] 1\? .
402 | ```
403 |
404 | Note: MINT will leave byte mode (and return to normal word mode) after it executes a `]`, `?` or `!`
405 |
406 | ### Memory allocation
407 |
408 | The final kind of memory allocation in MINT is the simplest raw memory allocation on the heap.
409 |
410 | This type of allocation is similar to arrays of bytes and are created using the `/A` allocation operator.
411 |
412 | ```
413 | 1000 /A
414 | ```
415 |
416 | This code allocates a 1000 byte block of uninitialized memory and returns a pointer to the start of this block.
417 |
418 | ## Loops
419 |
420 | Looping in MINT is of the form
421 |
422 | ```
423 | number (code to execute)
424 | ```
425 |
426 | The number represents the number of times the code between parentheses will be repeated. If the number is zero then the code will be skipped. If the number
427 | is ten it will be repeated ten times. If the number is -1 then the loop will repeat forever.
428 |
429 | ```
430 | 0(this code will not be executed but skipped)
431 | 1(this code will be execute once)
432 | 10(this code will execute 10 times)
433 | /F(this code will not be executed but skipped)
434 | /T(this code will be execute once)
435 | /U(this code will be execute forever)
436 | ```
437 |
438 | This code following prints ten x's.
439 |
440 | ```
441 | 10 (`x`)
442 | ```
443 |
444 | The following code repeats ten times and adds 1 to the variable `t` each time.
445 | When the loop ends it prints the value of t which is 10.
446 |
447 | ```
448 | 0t! 10( t 1+ t! ) t .
449 | ```
450 |
451 | MINT provides a special variable `/i` which acts as a loop counter. The counter counts up from zero. Just before the
452 | counter reaches the limit number it terminates.
453 |
454 | This prints the numbers 0 to 9.
455 |
456 | ```
457 | 10 ( /i . )
458 | ```
459 |
460 | Loops can repeat forever by specifying an "unlimited" loop with /U. These can be controlled with the "while" operator `/W`. Passing a false value to /W will terminate the loop.
461 |
462 | This code initialises `t` to zero and starts a loop to repeat 10 times.
463 | The code to repeat accesses the `/i` variable and compares it to 4. When `/i` exceeds 4 it breaks the loop.
464 | Otherwise it accesses `t` and adds 1 to it.
465 |
466 | Finally when the loop ends it prints the value of t which is 5.
467 |
468 | ```
469 | 0t! /U(/i 4 < /W /i t 1+ t!) t .
470 | ```
471 |
472 | Loops can be nested and then special `/j` variable is provided to access the counter of the outer loop.
473 |
474 | The following has two nested loops with limits of 2. The two counter variables are summed and added to `t`.
475 | When the loop ends `t` prints 4.
476 |
477 | ```
478 | 0t! 2(2(/i /j + t + t! )) t .
479 | ```
480 |
481 | ## Conditional code
482 |
483 | MINT's looping mechanism can also be used to execute code conditionally. In MINT boolean `false` is represented
484 | by 0 or `/F` and `true` is represented by 1 or `/T`.
485 |
486 | ```
487 | /F(this code will not be executed but skipped)
488 | /T(this code will be execute once)
489 | ```
490 |
491 | The following tests if `x` is less that 5.
492 |
493 | ```
494 | 3 x!
495 | x 5 < (`true`)
496 | ```
497 |
498 | The syntax for a MINT IF-THEN-ELSE or "if...else" operator in MINT is and
499 | extension of the loop syntax.
500 |
501 | ```
502 | boolean (code-block-then) /E (code-block-else)
503 | ```
504 |
505 | If the condition is true, then code-block-then is executed. Otherwise, code-block-else is executed.
506 |
507 | Here is an example of a "if...else" operator in MINT:
508 |
509 | ```
510 | 10 x !
511 | 20 y !
512 |
513 | x y > ( `x is greater than y` ) /E ( `y is greater than x` )
514 |
515 | ```
516 |
517 | In this example, the variable x is assigned the value 10 and the variable y is assigned the value 20.
518 | The "if...else" operator then checks to see if x is greater than y. If it is, then the string
519 | "x is greater than y" is returned. Otherwise, the string "y is greater than x" is returned.
520 |
521 | Here is another example of the "if...else" operator in MINT. This time, instead of creating a string just to print it, the following
522 | code conditionally prints text straight to the console.
523 |
524 | ```
525 | 18 a !
526 |
527 | `This person` a 17 > (`can`) /E (`cannot`) `vote`
528 | ```
529 |
530 | In this example, the variable a is assigned the value 18. The "if...else" operator
531 | then checks to see if age is greater than 17. If it is,
532 | then the text "can" is printed to the console. Otherwise, the string "cannot" is printed.
533 |
534 | ## Functions in MINT
535 |
536 | You can put any code inside `:` and `;` block which tells MINT to "execute this later".
537 |
538 | Functions are stored in variables with uppercase letters. There are 26 variables
539 | for storing functions in MINT and use the uppercase letter A to Z.
540 |
541 | The following stores a function in the variable `Z`.
542 |
543 | ```
544 | :Z `hello` 1. 2. 3. ;
545 | ```
546 |
547 | Running the function by stored in uppercase `Z` by referring to it
548 |
549 | ```
550 | Z
551 | ```
552 |
553 | will print out.
554 |
555 | ```
556 | hello 1 2 3
557 | ```
558 |
559 | A basic function to square a value.
560 |
561 | ```
562 | :F " * ;
563 | ```
564 |
565 | The function stored in F duplicates the value on the stack and then multiplies them together.
566 |
567 | ```
568 | 4 F .
569 | ```
570 |
571 | Calling the function with 4 returns 16 which is then printed.
572 |
573 | ### Function with multiple arguments
574 |
575 | You can also define functions with multiple arguments. For example:
576 |
577 | ```
578 | :F $ . . ;
579 | ```
580 |
581 | This function swaps the top two arguments on the stack and then prints them using `.`.
582 |
583 | ### Calling functions
584 |
585 | Functions are called by referring to them
586 |
587 | ```
588 | :F * ;
589 | 30 20 F .
590 | ```
591 |
592 | This code passes the numbers `30` and `20` to a function which multiplies them and returns
593 | the result which is then printed.
594 |
595 | ### Using functions
596 |
597 | Once you've assigned functions to variables, you can use them in your MINT code.
598 |
599 | Example:
600 |
601 | ```
602 | 10 A / prints 10
603 | 3 7 B / prints 10, the sum of 3 and 7
604 | ```
605 |
606 | In the first line, we execute the function stored in variable `A` with the argument `10`,
607 | which prints `10`. In the second line, we execute the function stored in variable `B` with
608 | arguments `3` and `7`, which results in `10` being printed (the sum of the two arguments).
609 |
610 | ### Anonymous functions
611 |
612 | MINT code is not restricted to upper case variables. Functions an be declared without a
613 | variable(i.e. anonymously) by using the `:@` operator. A function declared this way puts
614 | the address of the function on the stack.
615 |
616 | A function at an address can be executed with the `/G` operator.
617 |
618 | This code declares an anonymous function and stores its address in `a`. This function will
619 | increment its argument by 1.
620 |
621 | The next line pushs the number 3 on the stack and executes the function in `a`.
622 | The function adds 1 and prints 4 to the console.
623 |
624 | ```
625 | :@ 1+ ; a!
626 | 3 a /G .
627 | ```
628 |
629 | Anonymous functions can be stored in arrays and can even be used as a kind of "switch" statement.
630 | This code declares an array containing 3 anonymous functions. The next line accesses the array at
631 | index 2 and runs it. "two" is printed to the console.
632 |
633 | ```
634 | [:@ `zero` ; :@ `one` ; :@ `two` ;] b!
635 | b 2? /G
636 | ```
637 |
638 | ## Appendices
639 |
640 | ### Using MINT on the TEC-1
641 |
642 | MINT was designed for for small Z80 based systems but specifically with the small memory configuration
643 | of the TEC-1 single board computer. It is only 2K to work with the original TEC-1 and interfaces to the
644 | serial interface via a simple adapter.
645 |
646 | On initialisation it will present a user prompt ">" followed by a CR and LF. It is now ready to accept
647 | commands from the keyboard.
648 |
649 | ### List of operators
650 |
651 | ### Maths Operators
652 |
653 | | Symbol | Description | Effect |
654 | | ------ | ----------------------------------------- | -------- |
655 | | - | 16-bit integer subtraction SUB | n n -- n |
656 | | / | 16-bit by 8-bit division DIV | n n -- n |
657 | | + | 16-bit integer addition ADD | n n -- n |
658 | | \* | 8-bit by 8-bit integer multiplication MUL | n n -- n |
659 |
660 | ### Logical Operators
661 |
662 | | Symbol | Description | Effect |
663 | | ------ | -------------------- | -------- |
664 | | > | 16-bit comparison GT | n n -- b |
665 | | < | 16-bit comparison LT | n n -- b |
666 | | = | 16 bit comparison EQ | n n -- b |
667 | | & | 16-bit bitwise AND | n n -- b |
668 | | \| | 16-bit bitwise OR | n n -- b |
669 | | ^ | 16-bit bitwise XOR | n n -- b |
670 | | ~ | 16-bit NOT | n -- n |
671 | | { | shift left | n -- n |
672 | | } | shift right | -- |
673 |
674 | ### Stack Operations
675 |
676 | | Symbol | Description | Effect |
677 | | ------ | -------------------------------------------------------------------- | ------------ |
678 | | ' | drop the top member of the stack DROP | m n -- m |
679 | | " | duplicate the top member of the stack DUP | n -- n n |
680 | | % | over - take the 2nd member of the stack and copy to top of the stack | m n -- m n m |
681 | | $ | swap the top 2 members of the stack SWAP | m n -- n m |
682 | | /D | stack depth | -- n |
683 |
684 | ### Input & Output Operations
685 |
686 | | Symbol | Description | Effect |
687 | | ------ | ---------------------------------------------- | ------ |
688 | | . | print the number on the stack as a decimal | n -- |
689 | | , | print the number on the stack as a hexadecimal | n -- |
690 | | \` | print the literal string between \` and \` | -- |
691 | | /C | prints a character to output | n -- |
692 | | /K | read a char from input | -- n |
693 | | /O | output to an I/O port | n p -- |
694 | | /I | input from a I/O port | p -- n |
695 |
696 | ### Functions
697 |
698 | | Symbol | Description | Effect |
699 | | -------- | ------------------------------- | ------ |
700 | | :A ... ; | define a new command DEF | -- |
701 | | :@ ... ; | define an anonymous command DEF | -- a |
702 | | /G | execute mint code at address | a -- ? |
703 | | /X | execute machine code at address | a -- ? |
704 |
705 | where "A" represents any uppcase letter
706 |
707 | ### Loops and conditional execution
708 |
709 | | Symbol | Description | Effect |
710 | | ------ | -------------------------------------- | ------ |
711 | | ( | BEGIN a loop which will repeat n times | n -- |
712 | | ) | END a loop code block | -- |
713 | | /U | unlimited loop constant | -- b |
714 | | /W | if false break out of loop | b -- |
715 | | /E | else condition | -- b |
716 | | /F | false constant | -- b |
717 | | /T | true constant | -- b |
718 |
719 | ### Memory and Variable Operations
720 |
721 | | Symbol | Description | Effect |
722 | | ------ | ----------------------- | ------ |
723 | | a..z | variable access | -- n |
724 | | ! | STORE a value to memory | n a -- |
725 | | /V | address of last access. | -- a |
726 |
727 | ### Array Operations
728 |
729 | | Symbol | Description | Effect |
730 | | ------ | ------------------------- | -------- |
731 | | [ | begin an array definition | -- |
732 | | ] | end an array definition | -- a |
733 | | ? | get array item | a n -- n |
734 | | /S | array size | a -- n |
735 | | /A | allocate heap memory | n -- a |
736 |
737 | ### Byte Mode Operations
738 |
739 | | Symbol | Description | Effect |
740 | | ------ | ----------------------------- | -------- |
741 | | \\ | put MINT into byte mode | -- |
742 | | \\! | STORE a byte to memory | b a -- |
743 | | \\[ | begin a byte array definition | -- |
744 | | \\? | get byte array item | a n -- b |
745 |
746 | ### System variables
747 |
748 | | Symbol | Description | Effect |
749 | | ------ | ---------------------------------------- | ------ |
750 | | /c | carry variable | -- n |
751 | | /h | heap pointer variable | -- a |
752 | | /i | loop variable | -- n |
753 | | /j | outer loop variable | -- n |
754 | | /k | (internal) offset into text input buffer | -- a |
755 | | /r | remainder/overflow of last div/mul | -- n |
756 | | /s | address of start of stack | -- a |
757 | | /z | (internal) name of last defined function | -- c |
758 |
759 | ### Miscellaneous
760 |
761 | | Symbol | Description | Effect |
762 | | ------ | --------------------------------------------- | ------ |
763 | | // | comment text, skips reading until end of line | -- |
764 |
765 | ### Utility commands
766 |
767 | | Symbol | Description | Effect |
768 | | ------ | ------------- | ------ |
769 | | /N | prints a CRLF | -- |
770 | | /P | print prompt | -- |
771 |
772 | ### Control keys
773 |
774 | | Symbol | Description |
775 | | ------ | ----------------- |
776 | | ^E | edit a definition |
777 | | ^H | backspace |
778 | | ^L | list definitions |
779 | | ^R | re-edit |
780 | | ^S | print stack |
781 |
782 | ## Algorithm Examples
783 |
784 | ### 1. Fibonacci Sequence
785 |
786 | A loop that prints the first 10 numbers of the Fibonacci sequence.
787 |
788 | ```
789 | :F n ! // Pop the number of iterations (n) from the stack
790 | 0 a ! 1 b ! // Initialize a = 0, b = 1
791 | n ( // Loop n times
792 | a . // Print current Fibonacci number
793 | a b + c ! // c = a + b
794 | b a ! // a = b
795 | c b ! // b = c
796 | )
797 | ;
798 | ```
799 |
800 | - **`n !`**: Pops the number of iterations from the stack and assigns it to `n`.
801 | - The loop runs `n` times, printing `a` and updating `a` and `b` in each iteration.
802 |
803 | ### Example of Calling the Function:
804 |
805 | ```
806 | 10 F // Print the first 10 Fibonacci numbers
807 | ```
808 |
809 | ### 2. Factorial Function
810 |
811 | A recursive function that calculates the factorial of a number.
812 |
813 | ```
814 | :F
815 | " // Duplicate n
816 | 1 > // Check if n > 1
817 | ( // If true
818 | " 1 - F * // n * factorial(n - 1)
819 | ) /E ( // Else condition wrapped in parentheses
820 | 1 // Return 1
821 | )
822 | ;
823 | 5 F . // Calculate factorial of 5, prints: 120
824 | ```
825 |
826 | - This function recursively calculates the factorial of a number `n`.
827 | - If `n > 1`, it calls itself with `n - 1` and multiplies `n` by the result.
828 | - If `n` is 1 or less, it returns 1, which is the base case to stop recursion.
829 |
830 | ### 3. Sieve of Eratosthenes
831 |
832 | A simple implementation of the Sieve of Eratosthenes to find prime numbers up to 30.
833 |
834 | ```
835 | :S l ! // Pop the limit from the stack
836 | 2 p ! // Initialize p to 2 (start from the first prime)
837 | l 2 - ( // Loop from 2 to the limit
838 | /T f ! // Set flag assuming p is prime
839 | p 2 * l < ( // Loop for multiples of p within the limit
840 | p i % 0 = ( // If p is divisible by i
841 | /F f ! // Set flag to false if divisible
842 | )
843 | )
844 | f /T = ( // If the flag is still true, print the prime
845 | p .
846 | )
847 | p 1 + p ! // Increment p
848 | )
849 | ;
850 | ```
851 |
852 | ### Explanation:
853 |
854 | - **`S l !`**: The limit `l` (e.g., 30) is passed from the stack and stored in `l`.
855 | - **`2 p !`**: The starting number for checking primes is set to `2` (the first prime number).
856 | - **Loop**: The loop iterates over numbers from 2 to `l - 1`.
857 | - **`/T f !`**: A flag `f` is initially set to true, assuming the number is prime.
858 | - **Multiples Check**: For each number `p`, another loop checks if `p` is divisible by any number between `2` and `p - 1`. If `p` is divisible by `i` (i.e., `p % i == 0`), the flag `f` is set to false (`/F f !`).
859 | - **Prime Check**: After checking all divisors, if the flag `f` remains true (`f /T =`), the number `p` is prime and is printed (`p .`).
860 | - **Increment**: After each iteration, `p` is incremented by 1 (`p 1 + p !`).
861 |
862 | ### Example of Calling the Function:
863 |
864 | ```
865 | 30 S // Set the limit to 30 and call the sieve function
866 | ```
867 |
868 | ### 4. Greatest Common Divisor (GCD) using Euclidean Algorithm
869 |
870 | This program finds the GCD of two numbers using the Euclidean algorithm.
871 |
872 | ```
873 | :A b ! a ! // Pop two numbers from the stack in LIFO order (b first, then a)
874 | /U ( // Begin an unlimited loop
875 | b 0 > /W // Continue while b > 0 (break if b == 0)
876 | a b % a ! // a = a mod b
877 | a b ! // Swap: b = old a, repeat
878 | )
879 | a . // Print the GCD
880 | ;
881 | ```
882 |
883 | - **`/W` as a Loop-While**: The `/W` construct functions as a loop-while, where the loop continues as long as the condition is **true** (non-zero). When the condition becomes **false** (zero), the loop terminates.
884 | - **`b 0 > /W`**: This checks if `b` is greater than 0 at each iteration. The loop continues while `b > 0` and breaks when `b == 0`, completing the Euclidean algorithm.
885 |
886 | ### Example of Calling the Function:
887 |
888 | ```
889 | 30 20 A // Calculates the GCD of 30 and 20, prints GCD: 10
890 | ```
891 |
892 | ### Example:
893 |
894 | To find the GCD of 30 and 20, you would call the function like this:
895 |
896 | ```
897 | 30 20 A // Call the GCD function with 30 and 20, prints GCD: 10
898 | ```
899 |
900 | ### 5. Bubble Sort
901 |
902 | ```
903 | :S l ! // Store the list passed from the stack into variable l
904 | l /S s ! // Get the size of the list and store it in s
905 | /T c ! // Initialize the continue flag (c) to true
906 | /U ( // Start an unlimited loop for swapping
907 | c /W // Break the loop early if no swaps occurred (c == false)
908 | s 1 - ( // Iterate over the list (size - 1 times)
909 | l i ? x ! // Store l[i] in x
910 | l i 1 + ? y ! // Store l[i+1] in y
911 | x y > ( // Compare x and y (l[i] and l[i+1])
912 | y l i ! // Move y (l[i+1]) to l[i]
913 | x l i 1 + ! // Move x (l[i]) to l[i+1]
914 | /F c ! // Set the continue flag to false (indicating a swap occurred)
915 | )
916 | )
917 | )
918 | ;
919 | ```
920 |
921 | - **Temporary Variables**: `x` stores `l[i]` and `y` stores `l[i+1]` to avoid repetition when swapping elements.
922 | - **Continue Flag Initialization**: The continue flag `c` is initialized to **true** (`/T c !`) once at the start before the loop begins.
923 | - **Early Check for Continue Flag**: The loop checks `c /W` early in each pass. If `c == false` (no swaps occurred in the previous pass), the loop terminates early.
924 |
925 | ### Example of Calling the Function:
926 |
927 | ```
928 | [5 3 8 4 2] S // Calls the bubble sort function on the list [5, 3, 8, 4, 2]
929 | ```
930 |
931 | ### Example of Calling the Function:
932 |
933 | ```
934 | [5 3 8 4 2] S // Calls the bubble sort function on the list [5, 3, 8, 4, 2]
935 | ```
936 |
937 | ### Example of Calling the Function:
938 |
939 | ```
940 | [5 3 8 4 2] S // Calls the bubble sort function on the list [5, 3, 8, 4, 2]
941 | ```
942 |
943 | ### 6. Binary Search
944 |
945 | A binary search algorithm that searches for a value in a sorted array.
946 |
947 | ```
948 | :B h ! l ! // Pop high and low indices from the stack (LIFO order)
949 | l h <= ( // While low <= high
950 | m l h + 2 / ! // Find the middle index
951 | m a ? t = ( // If value at m is target
952 | m . // Print index
953 | ) /E ( // Else block for equality wrapped in parentheses
954 | m a ? t < ( // If target is smaller, search left half
955 | m 1 - h !
956 | ) /E ( // Else block for greater condition wrapped
957 | l m 1 + !
958 | )
959 | )
960 | )
961 | ;
962 | ```
963 |
964 | - **`h ! l !`**: Pops the high (`h`) and low (`l`) indices from the stack in the correct LIFO order. When the function is called, you push the high value first, followed by the low value.
965 | - The binary search logic proceeds as normal:
966 | - **Find the middle**: `m l h + 2 / !` calculates the middle index.
967 | - **Compare**: If the middle value matches the target, print the index. Otherwise, adjust the search range accordingly (either update `l` or `h`).
968 |
969 | ### Example of Calling the Function:
970 |
971 | ```
972 | 0 9 B // Searches in a sorted array from index 0 to 9
973 | ```
974 |
975 | ### 7. Quick Sort
976 |
977 | An implementation of the Quick Sort algorithm.
978 |
979 | ```
980 | :Q s ! l ! // Pop the list and its size from the stack (LIFO order)
981 | l s > 1 ( // If list length is greater than 1
982 | l p c ! // Choose a pivot element
983 | l s p p ! // Partition list around pivot
984 | s Q ! p Q ! // Recursively sort partitions
985 | )
986 | ;
987 | ```
988 |
989 | - **`s ! l !`**: Pops the list `l` and its size `s` from the stack in the correct LIFO order.
990 | - **`l s > 1`**: Checks if the list length is greater than 1 to determine whether sorting is necessary.
991 | - **Recursive Sorting**: It partitions the list around a pivot and recursively sorts both partitions until the base case is reached.
992 |
993 | ### Example of Calling the Function:
994 |
995 | ```
996 | [5 3 8 4 2] 5 Q // Sort the list [5, 3, 8, 4, 2]
997 | ```
998 |
999 | ### 8. Tower of Hanoi
1000 |
1001 | ```
1002 | :H s ! t ! f ! n ! // Pop the number of disks and rods (source, target, spare) from the stack
1003 | n 1 = ( // If there is only 1 disk
1004 | f t m ! // Move from source to destination
1005 | ) /E ( // Else
1006 | n 1 - f t s H ! // Move n-1 disks from source to spare
1007 | f t m ! // Move nth disk to destination
1008 | s t f H ! // Move n-1 disks from spare to destination
1009 | )
1010 | ;
1011 | ```
1012 |
1013 | - **`s ! t ! f ! n !`**: Pops the number of disks `n`, source rod `f`, target rod `t`, and spare rod `s` from the stack in the correct LIFO order.
1014 | - **Recursive Steps**:
1015 | - If there's only 1 disk, it moves directly from the source to the destination.
1016 | - If there are more than 1 disk, it recursively moves `n-1` disks to the spare rod, moves the nth disk to the target, and then moves the `n-1` disks from the spare to the target.
1017 |
1018 | ### Example of Calling the Function:
1019 |
1020 | ```
1021 | 3 f t s H . // Solve Tower of Hanoi for 3 disks
1022 | ```
1023 |
1024 | ### 9. Insertion Sort
1025 |
1026 | An implementation of the insertion sort algorithm.
1027 |
1028 | ```
1029 | :I l ! // Pop the list from the stack
1030 | l /S s ! // Get the size of the list
1031 | s 2 > ( // If list has more than 1 element
1032 | s 1 to ( // Loop through the list starting from index 1
1033 | l i ? k ! // Assign key from list element at index i
1034 | i 1 - j ! // Initialize j to i - 1
1035 | j 0 > k l j ? < ( // While j > 0 and key is less than list[j]
1036 | l j 1 + l j ! // Shift elements to the right
1037 | j 1 - j ! // Decrement j
1038 | )
1039 | k l j 1 + ! // Place the key at the correct position
1040 | )
1041 | )
1042 | ;
1043 | ```
1044 |
1045 | - **`l !`**: Pop the list from the stack.
1046 | - **`l /S s !`**: Use `/S` to get the size of the list and store it in `s`.
1047 | - **Key and Comparison**: Iterates over the list starting from index 1, compares the current element (`k`) with previous elements, and shifts larger elements to the right until the correct position for `k` is found.
1048 |
1049 | ### Example of Calling the Function:
1050 |
1051 | ```
1052 | [5 3 8 4 2] I // Sort the list [5, 3, 8, 4, 2]
1053 | ```
1054 |
1055 | ### 10. Dijkstra's Algorithm (Shortest Path)
1056 |
1057 | An implementation of Dijkstra's algorithm to find the shortest path in a graph.
1058 |
1059 | ```
1060 | :N g ! // Pop the graph from the stack
1061 | u 0 ! // Initialize u (index) to 0
1062 | g /S ( // Loop over all nodes in the graph
1063 | u g ? d < ( // If the node at index u has a smaller distance
1064 | u g ! // Update u to be the new minimum
1065 | )
1066 | u 1 + u ! // Increment u
1067 | )
1068 | u ! // Return the index of the minimum distance node
1069 | ;
1070 |
1071 | :D g ! s ! d ! // Pop the graph, start node, and distances from the stack
1072 | d ! v /F ! // Initialize distances and visited nodes
1073 | g /S ( // Loop over all nodes in the graph
1074 | N m ! // Get the minimum distance node using N
1075 | m u ! // Update distances of neighboring nodes
1076 | )
1077 | d . // Print the shortest path
1078 | ;
1079 | ```
1080 |
1081 | ### Example of Calling the Function:
1082 |
1083 | ```
1084 | [ 0 7 9 0 0 14 0 0 10 15 0 11 0 6 ] g ! // Graph (Adjacency matrix)
1085 | [ 0 999 999 999 999 ] d ! // Distances (start at 0, others infinity)
1086 | 0 s ! // Start node is 0
1087 | g s d D // Call Dijkstra's algorithm
1088 | ```
1089 |
1090 | ### Explanation:
1091 |
1092 | - **Graph**: `[ 0 7 9 0 0 14 0 0 10 15 0 11 0 6 ]` represents an adjacency matrix.
1093 | - **Distances**: `[ 0 999 999 999 999 ]` represents the distances from the start node to all other nodes, initialized with infinity (or a large value) except the start node (which is 0).
1094 | - **Start Node**: `s = 0` sets the start node to 0.
1095 |
--------------------------------------------------------------------------------
/TEC-1ROM10.z80:
--------------------------------------------------------------------------------
1 | .engine mycomputer
2 |
3 | .include "constants.asm"
4 | .include "IOSerial.asm"
5 |
6 | jp start ; into #180 of the prog
7 |
8 | .include "MAIN.asm"
9 | .include "ram.asm"
10 |
--------------------------------------------------------------------------------
/TEC-1ROM10.z80.hex:
--------------------------------------------------------------------------------
1 | :03000000C39600A4
2 | :050008002E01C38B0076
3 | :050010002E02C38B006D
4 | :050018002E03C38B0064
5 | :050020002E04C38B005B
6 | :050028002E05C38B0052
7 | :050030002E06C38B0049
8 | :01003800C9FE
9 | :10004000EB28CDAD2EA7E729EF2F6FE6C3ECC7470E
10 | :10005000210020E5D5110100ED52D25800D1E1C9AF
11 | :100066002E08C38B00C547DB80CB4F28FA78D38197
12 | :10007600C1C9DB80CB4728FADB81C92A180AE9E522
13 | :100086002A1A0AE3C9260022920CCDBD035A00C9DA
14 | :1000960031000A215F0022060A22080A220A0A22E1
15 | :1000A6000C0A220E0A22100A22140A22160A2178A3
16 | :1000B6000022180A216B00221A0A3E03D380CD5073
17 | :0B00C60000ED56FB3E12D380C3180271
18 | :100180002F7A2F5A3B603F602F4B2F502F5A3B0046
19 | :100190002F4E3236282F6936352B2F5A2F6B303E93
20 | :1001A000282F4E29292F503B00603D3E20602F73A1
21 | :1001B000322D202F44312D28222C322D29272F4E4D
22 | :1001C0002F503B000F1D71EE92792D00E9E0F04FAA
23 | :1001D0006B9660F28ADD07E680BAABB6EC019A5600
24 | :1001E00006D403E34101C59A050487388B4A1A00F7
25 | :1001F0000934233B31530970096809097A7F4E0994
26 | :10020000090B888B90134109490079B028270BCD41
27 | :10021000920308200800181D31000ACDDE02CD929D
28 | :10022000034D494E54322E300D0A00CD8203010099
29 | :1002300000ED437C0C1E00C521000818067E230B30
30 | :10024000CD5B0379B020F6C1CD8100FE203039FEB0
31 | :10025000002859FE0D283FFE0828AF1601FE051E96
32 | :10026000852814FE121E80280EFE0C1E902808FE03
33 | :10027000131EA9280218BEED437C0CD5CDBD032F5B
34 | :100280004700ED4B7C0C18AD210008097703CD85A4
35 | :1002900000CD5B0318B221000809360D23360A236E
36 | :1002A0000303CD8B037BB7209F360303ED437C0C08
37 | :1002B0000100080B030AB7280FFE032815D62138C2
38 | :1002C000F36F260B6E2604E9035059CDAD03444D60
39 | :1002D000EBE92100F639300331000AC32B02DD219E
40 | :1002E0008009FD21B40221000C545D133600019CED
41 | :1002F00000EDB021000A228C0C214100229A0C2131
42 | :10030000A00C22760C21C40111000B0178007E2381
43 | :10031000CB27C83809CB3F4F0600EDB018F0CB3FD4
44 | :10032000477E23121310FC18E521340CD641180225
45 | :10033000D66187856F3E008C67AFB3C9C57CCD475A
46 | :10034000037DCD4703C1C94F1F1F1F1FCD50037928
47 | :10035000E60FC69027CE4027C38500FE6020053EED
48 | :1003600080AB5FC9CB7BC0FE3A2808FE5B2804FE49
49 | :100370002820021CC9FE3B2807FE5D2803FE29C079
50 | :100380001DC9CD92030D0A3E2000C9CD92030D0A6E
51 | :1003900000C9E3CD9D0323E3C9CD8500237EB720AB
52 | :1003A000F8C9DD2BDD7400DD2BDD7500C9DD6E00C5
53 | :1003B000DD23DD6600DD23C97723C385006069CDB9
54 | :1003C000A203C10BFDE9210000CB15226C0CFDE955
55 | :1003D0003EFF1801AF326A0C326B0CFDE9210000C0
56 | :0803E000180321FFFFE5FDE910
57 | :10040000E1FDE918CB0A21000CCD3003229C0C162B
58 | :10041000005E3A6A0C3C28022356D518B7E1D12A6F
59 | :100420009C0C733A6A0C3C2802237218A7D1E17B1A
60 | :10043000A56F7AA467E5FDE9D1E17BB56F7AB418C1
61 | :10044000F3D1E17BAD6F7AAC18EA11FFFF18F3D15D
62 | :10045000E119E5C3C6030ACD29035E2356C354063A
63 | :10046000E1CDC9063E20CD8500FDE9E1CD3C031874
64 | :10047000F3E1E5E5FDE9C3B402E1D1D5E5D5FDE958
65 | :10048000CDAD03444DFDE9E12918AAE1CB3CCB1DDC
66 | :1004900018A3E1E3189F030A0BFE303805FE3ADA91
67 | :1004A0003E07D1E1A7ED52E5C3C603E1D1B7ED5256
68 | :1004B000CAE203C3DD03E1D11802D1E1B7ED52DA9C
69 | :1004C000E203C3DD03030A03FE602805CD8500189F
70 | :1004D000F50BFDE921000039CDA203FDE9C33E077C
71 | :1004E000C3C405C36E07C31107C38A051850185B40
72 | :1004F0001878030AFE7B300CFE61300CFE5B300482
73 | :10050000FE41302D0BC3B707FE692E00CA1E05FE43
74 | :100510006A2E08280921680CCD3003C30C0426007C
75 | :10052000DD54DD5D19C30C04030AFE0D20FA0BFD3A
76 | :10053000E9215E0BD641856F7E2100066FE9E1D18E
77 | :100540003A6A0C3C28012919C30C04210000030A53
78 | :10055000CB77CA5705D607D630DA6007FE10D260CF
79 | :100560000729292929856FC34E05D1E1C57D4C0690
80 | :10057000102100002917CB11300719CE00D28105B8
81 | :100580000C10F1EB616FC1C3F807ED43020A1E01C5
82 | :10059000030ACD5B0320F9D17BB220071BED539EEC
83 | :1005A0000C181F3E02838220031101006069CDA256
84 | :1005B000030B2A020ACDA203EBCDA20321FFFFCD3C
85 | :1005C000A203FDE9DD5E02DD56037BB2282B131387
86 | :1005D0007BB228091B1B1BDD7302DD7203DD5E008D
87 | :1005E000DD560113DD7300DD7201110000ED539E35
88 | :1005F0000CDD4E04DD4605FDE9110800DD19FDE9BD
89 | :10060000D12A760CE51922760CFDE9E12B562B5EFA
90 | :10061000D5FDE9E17DB42009DD4E06DD4607C3F9CD
91 | :1006200005FDE921000039EB21000AB7ED52C38C2A
92 | :1006300004C3DD03E17DCD8500FDE92A9E0CE5FDC7
93 | :10064000E9CD4606FDE9E1E3E9CD9906FDE9CD8274
94 | :1006500003FDE9D17AB3280E6069030AFE3B280343
95 | :10066000CDA203424B0BFDE9CD810026006F18CED1
96 | :10067000E1794DED6826004F18C4CD8B03FDE9E10B
97 | :10068000594DE1ED694BFDE9C3E20321FEFF18AED0
98 | :10069000219C0C5E2356D5FDE9E1E37D087DCD2943
99 | :1006A000035E23567AB321000828143E3ACDB803DE
100 | :1006B00008CDB8031801131ACDB803FE3B20F7117B
101 | :1006C0000008B7ED52227C0CC9CB7C280B3E2DCD07
102 | :1006D0008500AF956F9F9467C50E0011F0D8CDFAD5
103 | :1006E000061118FCCDFA06119CFFCDFA061EF6CDB8
104 | :1006F000FA060C1EFFCDFA06C1C9062F041938FCF4
105 | :10070000ED523E30B82005AFB1C818010C78C38552
106 | :1007100000030AFE40200803ED5B760CD5180E326C
107 | :100720009A0CCD2903ED5B760C732372030A031236
108 | :1007300013FE3B280218F60BED53760CFDE9210061
109 | :10074000000AFE2D200103080AD6303813FE0A30B5
110 | :100750000F03545D29291929856F3E008C6718E81D
111 | :100760000B082007EB210000B7ED52E5FDE9ED4352
112 | :10077000020ACDAD0322040A545DB7ED72CB3CCB27
113 | :100780001D444D2A760C7123702318110B1B1B1A64
114 | :1007900077233A6A0C3C2805131A1B772379B0207B
115 | :1007A000EBEB2A040AF92A760C2323E5ED53760CA9
116 | :1007B000ED4B020AC3D4036069C1E37CA8F5A8F23B
117 | :1007C000C807AF956F9F9467A8F2D207AF914F9F6C
118 | :1007D0009047293E0F110000EB1804093D280ECB6D
119 | :1007E00023CB12ED6AED4238F21CC3DC07F1F2F7BD
120 | :0E07F00007AF935F9F9257C1D5228A0CFDE997
121 | :00000001FF
--------------------------------------------------------------------------------
/constants.asm:
--------------------------------------------------------------------------------
1 | TEC_1 EQU 1
2 | RC2014 EQU 0
3 |
4 | EXTENDED EQU 0
5 |
6 | .if RC2014
7 |
8 | ; Configuration for RC2014
9 |
10 | ROMSTART EQU $8000
11 | RAMSTART EQU $8800
12 | LOADER EQU 0
13 | BITBANG EQU 0
14 |
15 | .endif
16 |
17 | .if TEC_1
18 |
19 | ; Configuration for TEC-1
20 | LOADER EQU 0
21 | BITBANG EQU 0
22 |
23 | ROMSTART EQU $0000
24 | RAMSTART EQU $0800
25 | ROMSIZE EQU $0800
26 | RAMSIZE EQU $0800
27 |
28 | ;TEC-1D SC 8k rom/ram
29 | ; ROMSTART .equ $0000
30 | ; RAMSTART .equ $2000
31 | ; ROMSIZE .equ 8192
32 | ; RAMSIZE .equ 8192
33 |
34 | .endif
35 |
--------------------------------------------------------------------------------
/inspiration.md:
--------------------------------------------------------------------------------
1 | ## Inspiration
2 |
3 | The design of the Mint interpreter has drawn from many sources of inspiration. First amongst these is the work of Charles Moore and his design of the Forth programming language. Another important source of inspiration is the STABLE programming language, a small and minimal interpreter written by Sandor Schneider. Also Mint takes inspiration from Chris Curl's S4 programming language.
4 |
5 | Mint is a direct descendant of Ken Boak's own SIMPL programming language and has been expanded and extended greatly with many elements from Forth. Mint has been influenced by discussions in various online communities. In particular in the Minimalist Computing Facebook community and the Forth 2020 Facebook.
6 |
7 | Mint's fast and efficient design has been strongly influenced by Peter Jackaki's Forth implementations, especially his TAQOZ Forth engine for the Propeller chips.
8 |
9 | Mint is a collaboration between Ken Boak, John Hardy and Craig Jones.
--------------------------------------------------------------------------------
/mycomputer.emu:
--------------------------------------------------------------------------------
1 | cpu Z80
2 |
3 | memory.rom.from 0x0000
4 | memory.rom.to 0x7ff
5 | memory.ram.from 0x800
6 | memory.ram.to 0xffff
7 |
8 | serial 6850
9 | serial.data 0x81
10 | serial.control 0x80
11 |
12 | serial.interrupt 1
13 |
14 | terminal.caps 0
15 |
--------------------------------------------------------------------------------
/ram.asm:
--------------------------------------------------------------------------------
1 | DSIZE EQU $80
2 | RSIZE EQU $80
3 | TIBSIZE EQU $100 ; 256 bytes , along line!
4 | VARS_SIZE equ 26*2
5 |
6 | .ORG RAMSTART
7 |
8 | TIB: DS TIBSIZE
9 |
10 | DS RSIZE
11 | rStack:
12 |
13 | DS DSIZE
14 | dStack:
15 | stack:
16 | tbPtr: DS 2 ; reserved for tests
17 | vTemp1: ds 2 ;
18 | vTemp2: ds 2 ;
19 |
20 | RST08: DS 2
21 | RST10: DS 2
22 | RST18: DS 2
23 | RST20: DS 2
24 | RST28: DS 2
25 | RST30: DS 2 ;
26 | BAUD DS 2 ;
27 | INTVEC: DS 2 ;
28 | NMIVEC: DS 2 ;
29 | GETCVEC: DS 2 ;
30 | PUTCVEC: DS 2 ;
31 |
32 | .align $100
33 | opcodes:
34 | DS $80-32-1-1
35 | altCodes:
36 | DS 26
37 |
38 | .align $100
39 |
40 | vars: DS VARS_SIZE
41 | defs: DS VARS_SIZE
42 |
43 | altVars:
44 | DS 2 ; a
45 | vByteMode: DS 2 ; b
46 | vCarry: DS 2 ; c carry variable
47 | DS 2 ; d
48 | DS 2 ; e
49 | vIntFunc: DS 2 ; f interrupt func
50 | DS 2 ; g
51 | vHeapPtr: DS 2 ; h heap pointer variable
52 | DS 2 ; i loop variable
53 | DS 2 ; j outer loop variable
54 | vTIBPtr: DS 2 ; k address of text input buffer
55 | DS 2 ; l
56 | DS 2 ; m
57 | DS 2 ; n
58 | DS 2 ; o
59 | DS 2 ; p
60 | DS 2 ; q
61 | vRemain: DS 2 ; r remainder of last division
62 | vStkStart: DS 2 ; s address of start of stack
63 | DS 2 ; t
64 | DS 2 ; u
65 | vIntID: DS 2 ; v interrupt id
66 | DS 2 ; w
67 | DS 2 ; x
68 | DS 2 ; y
69 | vLastDef: DS 2 ; z name of last defined function
70 |
71 | vPointer: DS 2 ;
72 | vElse: DS 2 ;
73 |
74 | HEAP:
75 |
--------------------------------------------------------------------------------
/snippets.md:
--------------------------------------------------------------------------------
1 |
2 | strDef_: ;= 21
3 | strDef: ;= 21
4 | LD DE,(vHeapPtr) ; HL = heap ptr
5 | PUSH DE ; save start of string
6 | INC BC ; point to next char
7 | JR strDef2
8 | strDef1:
9 | LD (DE),A
10 | INC DE ; increase count
11 | INC BC ; point to next char
12 | strDef2:
13 | LD A,(BC)
14 | CP "`" ; ` is the string terminator
15 | JR NZ,strDef1
16 | XOR A ; write null to terminate string
17 | LD (DE),A
18 | INC DE
19 | JP def3
20 |
21 | def3:
22 | ld (vHeapPtr),de ; bump heap ptr to after definiton
23 | jp (IY)
24 |
25 | prnStr_:
26 | prnStr:
27 | POP HL
28 | CALL putStr
29 | JP (IY)
30 |
31 | .engine mycomputer
32 |
33 | .include "constants.asm"
34 | .include "IOSerial.asm"
35 |
36 | LD SP,DSTACK
37 | CALL init
38 | JP testsStart
39 |
40 | .include "MINT.asm"
41 | .include "ram.asm"
42 | .include "test.util.mac.asm"
43 | .include "test.array.mac.asm"
44 | .include "test.tester.mac.asm"
45 |
46 | .org $4000
47 |
48 | testsStart:
49 |
50 | CALL enter
51 | utilDefs
52 | arrayDefs
53 |
54 | tester "[1 2 3 4 5 6] \\:2/$ '; F H", "[1 3 5] H"
55 | tester "0 [1 4 3 6 2] \\:'1+; R", "5"
56 | tester "0 [1 4 3 6 2] \\:+; R", "16"
57 | tester "1 [1 4 3 6 2] \\:%%>\\(')($ '); R", "6"
58 | tester "1 [1 4 3 6 2] \\:%%<\\(')($ '); R", "1"
59 | tester "[1 2 3] \\:{; M H", "[2 4 6] H"
60 |
61 | .cstr "`Done!`"
62 | HALT
63 |
64 | .macro arrayDefs
65 | DB ":R \\f! $\\a! $\\v! (\\v@ %@ \\f@\\^ \\v! 2+) ' \\v@;" ; v0 arr len fun -- val reduce array
66 | DB ":R \\f!~\\v! (\\v@ %@ \\f@\\^ \\v! 2+) ' \\v@;" ; v0 arr len fun -- val reduce array
67 |
68 | DB ":R \\f! ( $%@ \\f@\\^ $ 2+) ' ;" ; v0 arr len fun -- val reduce array
69 |
70 | DB ":M \\f! \\h@~~ " ; arr len fun -- arr' len' map array
71 | DB "(Q@"
72 | DB "\\f@\\^ W 2+"
73 | DB ")"
74 | DB "' \\h@ % -};"
75 |
76 | DB ":F \\f! \\h@ ~~ "
77 | DB "(Q@Q "
78 | DB "\\f@\\^ "
79 | DB "\\(W)(') 2+ "
80 | DB ")"
81 | DB " ' \\h@ % -};"
82 | .endm
83 |
84 |
85 | .engine mycomputer
86 |
87 | .include "constants.asm"
88 | .include "IOSerial.asm"
89 |
90 | LD SP,DSTACK
91 | CALL init
92 | JP testsStart
93 |
94 | .include "MINT.asm"
95 | .include "ram.asm"
96 | .include "test.util.mac.asm"
97 | ; .include "test.co.mac.asm"
98 | .include "test.tester.mac.asm"
99 |
100 | .org $4000
101 |
102 | testsStart:
103 |
104 | CALL enter
105 | utilDefs
106 |
107 | ; does not work with loop frames on RSTACK
108 | ; does not work with loop stack because 2 loops exist at the same time
109 | ; because of coroutines
110 |
111 | DB ":F \\{ \\{ \\{ $~ \\} ;" ; -- val 2rfrom 2r>
112 | DB ":T $ \\{ $ \\} $ \\} \\} ;" ; val -- 2tor 2>r
113 | DB ":Y F $ T ;"
114 |
115 | DB ":P 100+ Y 1000() P;" ; endless loop
116 | DB ":C P 50( \\#7. Y ) \\{ ;"
117 | DB "C `done`\\$"
118 |
119 | .cstr "`Done!`"
120 | HALT
121 |
122 | .macro coDefs
123 | DB ":T $ \\#1 \\#1 ;" ; val -- 2tor 2>r
124 | DB ":F \\#2 \\#2 $ ;" ; -- val 2rfrom 2r>
125 |
126 | DB ":Y F $ T ;"
127 | DB ":P 1_( 100+ Q Y ) ;" ; endless
128 | DB ":C \\$ 0 P 1_( Q.\\$ 1000 > \\_ Y ) ' B ;"
129 | .endm
130 |
131 | .engine mycomputer
132 |
133 | .include "constants.asm"
134 | .include "IOSerial.asm"
135 |
136 | LD SP,DSTACK
137 | CALL init
138 | JP testsStart
139 |
140 | .include "MINT.asm"
141 | .include "ram.asm"
142 | .include "test.util.mac.asm"
143 | .include "test.tester.mac.asm"
144 |
145 | .org $4000
146 |
147 | testsStart:
148 |
149 | CALL enter
150 | utilDefs
151 |
152 | tester "1 2 3", "1 2 3"
153 | tester "1Q", "1 1"
154 | tester "25(\\i@ 2\\> 1 30(Q #40 | 1\\> { #3F & Q0=('1))') #40 1\\>", ""
155 | tester ":G %%> (')($ '); 5 2 G", "5"
156 | tester "1", "1"
157 | tester "#1#12#123#1234", "1 18 291 4660"
158 | tester "0", "0"
159 | tester "10", "10"
160 | tester "#10", "16"
161 | tester "#FF", "255"
162 | tester "2 3=", "0"
163 | tester "3 3=", "1"
164 | tester "2 3<", "1"
165 | tester "3 3<", "0"
166 | tester "3 3>", "0"
167 | tester "4 3>", "1"
168 | tester "1 2+", "3"
169 | tester "123 456+", "579"
170 | tester "64 128+", "192"
171 | tester "5 3-", "2"
172 | tester "-1 2+", "1"
173 | tester "-1 1+", "0"
174 | tester "3 5&", "1"
175 | tester "3 5|", "7"
176 | tester "1{", "2"
177 | tester "1}", "0"
178 | tester "2}", "1"
179 | tester "1 2 3 ' +", "3"
180 | tester "2 3*", "6"
181 | tester "1 2 3+*", "5"
182 | tester "1 3 Q ++", "7"
183 | tester "5 2/'", "2"
184 | tester "3 5$ -", "2"
185 | tester "1 2 3~''", "2"
186 | tester "1 2 3~+*", "8"
187 | tester "5 2/$ '", "1"
188 | tester "2 3%++", "7"
189 | tester "10 11 12\\#3$ ' $ ' $ '", "3"
190 | tester "2a!a@", "2"
191 | tester "3x! 1 x@+x! x@", "4"
192 | tester "3x! -1 x@+x! x@", "2"
193 | tester ":X1; X", "1"
194 | tester ":A100;A", "100"
195 | tester ":Aa!; 3A a@", "3"
196 | tester ":Aa!;:Ba@;4AB", "4"
197 | tester "\\:2; \\^", "2"
198 | tester "[]$ '", "0"
199 | tester "[3]$ '", "1"
200 | tester "[3]'@", "3"
201 | tester "[1 2 3]'@", "1"
202 | tester "[1 2 3]'2+@", "2"
203 | tester "\\h@[1]''\\h@$-", "2"
204 | tester "\\h@[1 2 3]''\\h@$-", "6"
205 | tester "\\[]$ '", "0"
206 | tester "\\[3]'\\@", "3"
207 | tester "\\[3]$ '", "1"
208 | tester "\\[1 2 3]'\\@", "1"
209 | tester "\\[1 2 3]'1+\\@", "2"
210 | tester "\\h@\\[1 2 3]''\\h@$-", "3"
211 | tester "\\h@\\[1]''\\h@$-", "1"
212 | tester "\\`A`\\@", "65"
213 | tester "0 0(1+)", "0"
214 | tester "0 1(1+)", "1"
215 | tester "0 2(1+)", "2"
216 | tester "0 1(0(1+))", "0"
217 | tester "0 1(1(1+))", "1"
218 | tester "0 2(1(1+))", "2"
219 | tester "0 2(2(1+))", "4"
220 | tester "0 1(\\i@+)", "0"
221 | tester "0 2(\\i@+)", "1"
222 | tester "0 3(\\i@+)", "3"
223 | tester "0 2(2(\\i@ \\i6+@ ++))", "4"
224 | tester "0t! 10(1 t@+t!) t@", "10"
225 | tester "0(100)(200)", "200"
226 | tester "1(100)(200)", "100"
227 | tester "0t! 10(\\i@ 4>\\~ 1 t@+t!) t@", "5"
228 | tester "0t! [1 2 3] $ a! ( a@ \\i@ {+ @ t@+t! ) t@", "6"
229 |
230 | .cstr "`Done!`"
231 | HALT
232 |
233 | .macro tester, test1, expect1
234 | DB "`.`\\#3\\t!"
235 | DB " ",test1," "
236 | DB "K\\#3\\t!" ; ( -- hash1 )
237 | DB " ",expect1," "
238 | DB "K=0=(\\$`fail: ",test1," expected: "
239 | DB expect1,"`\\$\\$",0,")"
240 | .endm
241 |
242 |
--------------------------------------------------------------------------------
/test.FAST.z80:
--------------------------------------------------------------------------------
1 | .engine mycomputer
2 |
3 | .include "constants.asm"
4 | .include "test.fast.mac.asm"
5 |
6 | .include "IOSerial.asm"
7 |
8 | JP testsStart
9 |
10 | .include "MAIN.asm"
11 | .include "ram.asm"
12 |
13 | .org $4000
14 |
15 | testsStart:
16 |
17 | test "1", 1
18 | test "0", 0
19 | test "10", 10
20 | test "#10", $10
21 | test "#FF", $FF
22 | test "2 3=", FALSE
23 | test "3 3=", TRUE
24 | test "2 3<", TRUE
25 | test "3 3<", FALSE
26 | test "3 3>", FALSE
27 | test "4 3>", TRUE
28 | test "0~", TRUE
29 | test "1 2+", 3
30 | test "123 456+", 123+456
31 | test "64 128+", 64+128
32 | test "5 3-", 2
33 | test "-1 2+",1
34 | test "-1 1+",0
35 | test "#FFFF 1 + /c +", 1
36 | test "0 1 - /c +", 0
37 | test "3 5&", 1
38 | test "3 5|", 7
39 | test "1{", 2
40 | test "1}", 0
41 | test "2}", 1
42 | test "1 2 3 ' +", 3
43 | test "2 3*", 6
44 | test "1 2 3+*", 5
45 | test "#8001 2 * /r +", 3
46 | test "1 2 /D", 2
47 | test "7 2/", 3
48 | test "7 2/' /r", 1
49 | test "1 1/", 1
50 | test "-1 1/", -1
51 | test "1 -1/", -1
52 | test "-1 -1/", 1
53 | test "3 5$ -", 2
54 | test "2 3%++", 7
55 | test "2a!a",2
56 | test "3x! 1 x+x! x", 4
57 | test "3x! -1 x+x! x", 2
58 | test ":X1; X", 1
59 | test ":A100;A", 100
60 | test ":Aa!; 3A a", 3
61 | test ":Aa!;:Ba;4AB", 4
62 | test ":@2; /G", 2
63 | test "[]", heap+2
64 | test "[1]", heap+2
65 | test "[]/S", 0
66 | test "[3]/S", 1
67 | test "[3]0?", 3
68 | test "[1 2 3]1?", 2
69 | test "[1 [2]] 1? 0?", 2
70 | test "/h[1]'/h$-", 4
71 | test "/h[1 2 3]'/h$-", 8
72 | test "\\[3]/S", 1
73 | test "\\[3] 0\\?", 3
74 | test "\\[1 2 3] 0\\?", 1
75 | test "\\[1 2 3] 1\\?", 2
76 | test "/h \\[1 2 3] ' /h $ -", 2+3
77 | test "/h \\[1] ' /h $ -", 2+1
78 | test "/h 1000/A ' /h $ -", 1000
79 | test "0 0(1+)", 0
80 | test "0 1(1+)", 1
81 | test "0 2(1+)", 2
82 | test "0 1(0(1+))", 0
83 | test "0 1(1(1+))", 1
84 | test "0 2(1(1+))", 2
85 | test "0 2(2(1+))", 4
86 | test "0 1(/i+)", 0
87 | test "0 0(/i+)", 0
88 | test "0 5(/i+)", 10
89 | test "0 /U(/i5