├── .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