added the TI-74 BASIC port and the mu808asm'MU74 export support
This commit is contained in:
@@ -303,7 +303,10 @@ Reference implementations
|
|||||||
* [Python 3](mu808asm.py): supports assembling MU8A source files into both
|
* [Python 3](mu808asm.py): supports assembling MU8A source files into both
|
||||||
plain text (MU8) and binary (MU8B) machine code formats. Also supports
|
plain text (MU8) and binary (MU8B) machine code formats. Also supports
|
||||||
disassembling MU8 and MU8B files into their MU8A sources and converting
|
disassembling MU8 and MU8B files into their MU8A sources and converting
|
||||||
machine code between MU8 and MU8B formats.
|
machine code between MU8 and MU8B formats. Additionally, this assembler
|
||||||
|
implementation provides the `t74` mode to convert plaintext MU8 machine code
|
||||||
|
into the format suitable for entering into TI-74 BASIC for running on the
|
||||||
|
TI-74 port of mu808 (see below).
|
||||||
|
|
||||||
These lists are going to be expanded as soon as new reference implementations
|
These lists are going to be expanded as soon as new reference implementations
|
||||||
appear.
|
appear.
|
||||||
@@ -331,6 +334,59 @@ keys of the standard phone keypad, the following convention is recommended:
|
|||||||
* the `#` (pound) key actually confirms entering a single number field, and
|
* the `#` (pound) key actually confirms entering a single number field, and
|
||||||
all instructions are required to contain exactly five numbers.
|
all instructions are required to contain exactly five numbers.
|
||||||
|
|
||||||
|
Retro/minimal platform implementations
|
||||||
|
--------------------------------------
|
||||||
|
Here's the list of known/existing mu808 implementations that adhere to the
|
||||||
|
specification to most extent and run compatible machine code but cannot
|
||||||
|
provide full operating environment functionality due to the limits of the
|
||||||
|
platform itself.
|
||||||
|
|
||||||
|
### TI-74 BASIC
|
||||||
|
|
||||||
|
The [mu808.b74](mu808.b74) file contains a BASIC port of mu808 for the Texas
|
||||||
|
Instruments TI-74 portable computer (tested on the TI-74S variant). Due to
|
||||||
|
the resource constraints, the following limitations apply:
|
||||||
|
|
||||||
|
* only 149 program steps and 256 data cells supported (adjustable at line 110),
|
||||||
|
* no interactive mode (the `RUN` command directly executes the predefined
|
||||||
|
program in the VM),
|
||||||
|
* the program itself is entered into the DATA statements in the so-called
|
||||||
|
MU74 format (see below),
|
||||||
|
* no support for I/O port 2, tracing or intruction dumping,
|
||||||
|
* no boundary checks for the addresses inside the program.
|
||||||
|
|
||||||
|
Also, since the VM runs on top of a BASIC interpreter, program execution is
|
||||||
|
extremely slow most of the time. Keep in mind, this is more of a proof of
|
||||||
|
concept than a viable solution, and using the "native" TI BASIC is preferred
|
||||||
|
for any serious computing on that machine.
|
||||||
|
|
||||||
|
In order to store your programs on the device to run via this mu808 VM version,
|
||||||
|
you need to enter them in DATA statements in two-number pairs starting from
|
||||||
|
`DATA 0,0` at the BASIC line 5000. The last `DATA` line of the program must be
|
||||||
|
`DATA -1,0`. In between these two, every program instruction `lno cmd a1 a2 a3`
|
||||||
|
must be compressed into the form:
|
||||||
|
```
|
||||||
|
[5000+lno] DATA [cmd*10000 + a1], [a2 * 10000 + a3]
|
||||||
|
```
|
||||||
|
This storage format is called MU74. For example, the compound interest
|
||||||
|
calculator from the official mu808 examples will transform into:
|
||||||
|
```
|
||||||
|
5000 DATA 0,0
|
||||||
|
5001 DATA 50100,1
|
||||||
|
5002 DATA 40002,30000
|
||||||
|
5003 DATA 90002,10004
|
||||||
|
5004 DATA 50001,5
|
||||||
|
5005 DATA 70005,40005
|
||||||
|
5006 DATA 130001,50005
|
||||||
|
5007 DATA 70000,30005
|
||||||
|
5008 DATA 130000,50005
|
||||||
|
5009 DATA 30005,50000
|
||||||
|
5010 DATA -1,0
|
||||||
|
```
|
||||||
|
To make the conversion easier, the official mu808 assembler, `mu808asm.py`, now
|
||||||
|
supports the `t74` mode that accepts a plain MU8 machine code file and outputs
|
||||||
|
the same program in the MU74 format.
|
||||||
|
|
||||||
FAQ
|
FAQ
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
100 RANDOMIZE:RAD
|
||||||
|
110 DIM PMEM(300),DMEM(256)
|
||||||
|
120 RESTORE 5000
|
||||||
|
130 I=0
|
||||||
|
140 READ PMEM(I), PMEM(I+1)
|
||||||
|
150 I=I+2
|
||||||
|
160 IF PMEM(I-2)>-1 THEN 140
|
||||||
|
170 L=1:IAT,V1,V2,V3=0
|
||||||
|
180 M=L+L:A=PMEM(M):B=PMEM(M+1)
|
||||||
|
190 IF A<0 THEN 730
|
||||||
|
200 CMD=INT(A/10000)
|
||||||
|
210 IF IAT=1 THEN 220 ELSE 230
|
||||||
|
220 X=INT(V1):Y=INT(V2):Z=INT(V3):IAT=0:GOTO 240
|
||||||
|
230 X=A-CMD*10000:Y=INT(B/10000):Z=B-Y*10000
|
||||||
|
240 V1,V2,V3=0
|
||||||
|
250 IF CMD=5 THEN DMEM(Z)=X+(Y/10000):GOTO 720
|
||||||
|
260 V1=DMEM(X):V2=DMEM(Y):V3=DMEM(Z)
|
||||||
|
270 IF CMD=1 THEN 280 ELSE 420
|
||||||
|
280 IF X=0 AND V2=0 THEN L=Z-1:GOTO 720
|
||||||
|
290 IF X=1 AND V2>0 THEN L=Z-1:GOTO 720
|
||||||
|
300 IF X=2 AND V2<0 THEN L=Z-1:GOTO 720
|
||||||
|
310 IF X=3 AND V2>=0 THEN L=Z-1:GOTO 720
|
||||||
|
320 IF X=4 AND V2<=0 THEN L=Z-1:GOTO 720
|
||||||
|
330 IF X=5 AND V2<>0 THEN L=Z-1:GOTO 720
|
||||||
|
340 IF X=6 THEN L=Z-1:GOTO 720
|
||||||
|
350 IF X=7 AND V2=0 THEN L=INT(V3)-1:GOTO 720
|
||||||
|
360 IF X=8 AND V2>0 THEN L=INT(V3)-1:GOTO 720
|
||||||
|
370 IF X=9 AND V2<0 THEN L=INT(V3)-1:GOTO 720
|
||||||
|
380 IF X=10 AND V2>=0 THEN L=INT(V3)-1:GOTO 720
|
||||||
|
390 IF X=11 AND V2<=0 THEN L=INT(V3)-1:GOTO 720
|
||||||
|
400 IF X=12 AND V2<>0 THEN L=INT(V3)-1:GOTO 720
|
||||||
|
410 IF X=13 THEN L=INT(V3)-1:GOTO 720
|
||||||
|
420 IF CMD=2 THEN IAT=1:GOTO 720
|
||||||
|
430 IF CMD=3 THEN 440 ELSE 490
|
||||||
|
440 FOR I=X TO Y
|
||||||
|
450 IF Z=0 THEN PRINT(DMEM(I)):PAUSE
|
||||||
|
460 IF Z=1 THEN 470 ELSE 480
|
||||||
|
470 IF DMEM(I)=10 THEN PAUSE ELSE PRINT(CHR$(INT(DMEM(I))));
|
||||||
|
480 NEXT I:GOTO 720
|
||||||
|
490 IF CMD=4 THEN 500 ELSE 530
|
||||||
|
500 FOR I=X TO Y
|
||||||
|
510 IF Z=0 THEN INPUT DMEM(I)
|
||||||
|
520 NEXT I:GOTO 720
|
||||||
|
530 IF CMD=6 THEN 540 ELSE 570
|
||||||
|
540 IF X=0 THEN DMEM(Z)=Y:GOTO 720
|
||||||
|
550 IF X=1 THEN DMEM(Z)=V2:GOTO 720
|
||||||
|
560 IF X>1 THEN DMEM(INT(V3))=DMEM(INT(V2)):GOTO 720
|
||||||
|
570 IF CMD=7 THEN DMEM(Z)=V1+V2*V3:GOTO 720
|
||||||
|
580 IF CMD=8 THEN DMEM(Z)=V1-V2:GOTO 720
|
||||||
|
590 IF CMD=9 THEN 600 ELSE 610
|
||||||
|
600 IF V2=0 THEN DMEM(Z)=0:GOTO 720 ELSE DMEM(Z)=V1/V2:GOTO 720
|
||||||
|
610 IF CMD=10 THEN 620 ELSE 630
|
||||||
|
620 IF V2=0 THEN DMEM(Z)=INT(V1):GOTO 720 ELSE DMEM(Z)=V1-V2*INT(V1/V2):GOTO 720
|
||||||
|
630 IF CMD=11 THEN DMEM(Z)=ABS(V2):GOTO 720
|
||||||
|
640 IF CMD=12 THEN DMEM(Z)=SQR(ABS(V2)):GOTO 720
|
||||||
|
650 IF CMD=13 THEN 660 ELSE 670
|
||||||
|
660 IF X=0 THEN DMEM(Z)=EXP(V2):GOTO 720 ELSE DMEM(Z)=LN(ABS(V2)):GOTO 720
|
||||||
|
670 IF CMD=14 THEN 680 ELSE 710
|
||||||
|
680 IF X=0 THEN DMEM(Z)=SIN(V2):GOTO 720
|
||||||
|
690 IF X=1 THEN DMEM(Z)=COS(V2):GOTO 720
|
||||||
|
700 IF X>1 THEN DMEM(Z)=ATN(V2):GOTO 720
|
||||||
|
710 IF CMD=15 THEN DMEM(Z)=INT(V1)+INT(RND*(INT(V2)-INT(V1)+1))
|
||||||
|
720 L=L+1:GOTO 180
|
||||||
|
730 END
|
||||||
+31
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# a simple assembler/disassembler for the mu808 VM
|
# a simple assembler/disassembler for the mu808 VM
|
||||||
# supports both text and binary program formats
|
# supports both text and binary program formats
|
||||||
# usage: mu808asm [at|ab|dt|db|t2b|b2t] file outfile
|
# usage: mu808asm [at|ab|dt|db|t2b|b2t|t74] file outfile
|
||||||
# modes:
|
# modes:
|
||||||
# at: assemble to plaintext (MU8) machine code
|
# at: assemble to plaintext (MU8) machine code
|
||||||
# ab: assemble to binary (MU8B) machine code
|
# ab: assemble to binary (MU8B) machine code
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
# db: disassemble binary (MU8B) machine code
|
# db: disassemble binary (MU8B) machine code
|
||||||
# t2b: convert from plaintext MU8 to binary MU8B
|
# t2b: convert from plaintext MU8 to binary MU8B
|
||||||
# b2t: convert from binary MU8B to plaintext MU8
|
# b2t: convert from binary MU8B to plaintext MU8
|
||||||
|
# t74: convert from plaintext MU8 to the TI-74 representation
|
||||||
|
|
||||||
import sys, re, struct
|
import sys, re, struct
|
||||||
|
|
||||||
@@ -132,6 +133,33 @@ def totext(binrep):
|
|||||||
out += ' '.join([str(lno), str(cmd), str(x), str(y), str(z)]) + '\n'
|
out += ' '.join([str(lno), str(cmd), str(x), str(y), str(z)]) + '\n'
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
# converts the MU8 plaintext machine code to the TI-74 DATA statements (MU74)
|
||||||
|
def ti74data(txtrep:str, baseaddr:int=5000):
|
||||||
|
instrs = [] # instruction list to store here
|
||||||
|
vreg = re.compile(r'\s+')
|
||||||
|
iindex = 0
|
||||||
|
instr = []
|
||||||
|
for instrpart in vreg.split(txtrep):
|
||||||
|
if iindex == 5:
|
||||||
|
instrs.append(instr)
|
||||||
|
instr = []
|
||||||
|
iindex = 0
|
||||||
|
if len(instrpart) > 0:
|
||||||
|
instr.append(int(instrpart))
|
||||||
|
iindex += 1
|
||||||
|
# now, instrs contains 5-number groups
|
||||||
|
out = f'{baseaddr} DATA 0,0\n'
|
||||||
|
maxlno = 0
|
||||||
|
for instr in instrs:
|
||||||
|
lno, cmd, x, y, z = instr
|
||||||
|
if lno > maxlno:
|
||||||
|
maxlno = lno
|
||||||
|
a = cmd*10000 + x
|
||||||
|
b = y*10000 + z
|
||||||
|
out += f'{baseaddr + lno} DATA {a},{b}\n'
|
||||||
|
out += f'{baseaddr + maxlno + 1} DATA -1,0\n'
|
||||||
|
return out
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) < 4:
|
if len(sys.argv) < 4:
|
||||||
print("Usage: mu808asm [at|ab|dt|db|t2b|b2t] file outfile")
|
print("Usage: mu808asm [at|ab|dt|db|t2b|b2t] file outfile")
|
||||||
@@ -162,6 +190,8 @@ def main():
|
|||||||
elif mode == 'db': # disassemble binary
|
elif mode == 'db': # disassemble binary
|
||||||
srctext = totext(srctext)
|
srctext = totext(srctext)
|
||||||
output = disassemble(srctext)
|
output = disassemble(srctext)
|
||||||
|
elif mode == 't74': # convert to TI-74 DATA statements
|
||||||
|
output = ti74data(srctext)
|
||||||
else: # assemble
|
else: # assemble
|
||||||
output = assemble(srctext) # default mode
|
output = assemble(srctext) # default mode
|
||||||
if mode == 'ab':
|
if mode == 'ab':
|
||||||
|
|||||||
Reference in New Issue
Block a user