Advertisement
lgb

Enterprise-128 basic file lister

lgb
Jun 27th, 2012
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.29 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. from __future__ import division, absolute_import, print_function
  5.  
  6. """
  7. First try to display an Enteprise-128 BASIC program
  8. (C)2012 LGB Gábor Lénárt
  9. Nice information sources:
  10.     http://ep128.hu/Ep_Konyv/Tippek.htm
  11.     http://ep128.hu/Ep_Konyv/Gepi_kod_2.htm#342
  12. """
  13.  
  14. import sys
  15.  
  16.  
  17. tokens = [
  18.     "ALLOCATE", #  0
  19.     "ASK",      #  1
  20.     "AUTO",     #  2
  21.     "CALL",     #  3
  22.     "CAPTURE",  #  4
  23.     "CASE",     #  5
  24.     "CAUSE",    #  6
  25.     "CLEAR",    #  7
  26.     "CLOSE",    #  8
  27.     "CODE",     #  9
  28.     "CONTINUE", # 10
  29.     "COPY",     # 11
  30.     "DATA",     # 12
  31.     "DEF",      # 13
  32.     "DEF",      # 14
  33.     "DELETE",   # 15
  34.     "DIM",      # 16
  35.     "DISPLAY",  # 17
  36.     "DO",       # 18
  37.     "CHAIN",    # 19
  38.     "EDIT",     # 20
  39.     "ELSE",     # 21
  40.     "ELSE IF",  # 22
  41.     "END",      # 23
  42.     "END DEF",  # 24
  43.     "END HANDLER",  # 25
  44.     "END IF",   # 26
  45.     "END SELECT",   # 27
  46.     "END WHEN", # 28
  47.     "ENVELOPE", # 29
  48.     "EXIT",     # 30
  49.     "FOR",      # 31
  50.     "GOSUB",    # 32
  51.     "GOTO",     # 33
  52.     "GRAPHICS", # 34
  53.     "HANDLER",  # 35
  54.     "IMAGE",    # 36
  55.     "IF",       # 37
  56.     "IF",       # 38
  57.     "INPUT",    # 39
  58.     "LET",      # 40
  59.     "LINE",     # 41
  60.     "LIST",     # 42
  61.     "LOAD",     # 43
  62.     "LOOP",     # 44
  63.     "MERGE",    # 45
  64.     "NEW",      # 46
  65.     "NEXT",     # 47
  66.     "NUMERIC",  # 48
  67.     "OPEN",     # 49
  68.     "OPTION",   # 50
  69.     "OK",       # 51
  70.     "OUT",      # 52
  71.     "PLOT",     # 53
  72.     "POKE",     # 54
  73.     "SPOKE",    # 55
  74.     "PRINT",    # 56
  75.     "PROGRAM",  # 57
  76.     "RANDOMIZE",    # 58
  77.     "READ",     # 59
  78.     "REDIRECT", # 60
  79.     "REM",      # 61
  80.     "RENUMBER", # 62
  81.     "RESTORE",  # 63
  82.     "RETRY",    # 64
  83.     "RETURN",   # 65
  84.     "RUN",      # 66
  85.     "SAVE",     # 67
  86.     "SELECT",   # 68
  87.     "SET",      # 69
  88.     "SOUND",    # 70
  89.     "START",    # 71
  90.     "STOP",     # 72
  91.     "INFO",     # 73
  92.     "STRING",   # 74
  93.     "TEXT",     # 75
  94.     "TOGGLE",   # 76
  95.     "TRACE",    # 77
  96.     "TYPE",     # 78
  97.     "VERIFY",   # 79
  98.     "WHEN",     # 80
  99.     "!",        # 81
  100.     "LLIST",    # 82
  101.     "LPRINT",   # 83
  102.     "EXT",      # 84
  103.     "GET",      # 85
  104.     "FLUSH",    # 86
  105.     "LOOK",     # 87
  106.     "PING",     # 88
  107.     "DATE",     # 89
  108.     "TIME",     # 90
  109.     "WAIT",     # 91
  110.     "ON",       # 92
  111. ]
  112.  
  113. signs = [   # TODO: the first (0th ...) element and the ones marked with "?" ...
  114.     " ", "!","\"", "#", "$", "%", "&", "'",
  115.     "(", ")", "*", "+", ",", "-", ".", "/",
  116.     ":", ";", "<", "=", ">","<>","<=",">=",
  117.     "[","\\", "]", "^", "?", "?", "?", "?"
  118. ]
  119.  
  120.  
  121. def die(msg = None):
  122.     if msg is None: sys.exit(0)
  123.     sys.stderr.write("EXIT ON FATAL: " + msg + "\n")
  124.     sys.exit(1)
  125.  
  126. def hexbyte(h):
  127.     return hex(h).replace("x", "0")[-2:].upper()
  128.  
  129. def hexdump(m):
  130.     return " ".join([hexbyte(a) for a in m])
  131.  
  132.  
  133. def list_line(line):
  134.     #print(hexdump(line))
  135.     o = str(line[0] | (line[1] << 8))
  136.     o += " " + " " * line[2]    # one space + possibly other spaces based on the nesting level
  137.     p = 3
  138.     while p < len(line):
  139.         b = line[p]
  140.         #print("Pars[" + hex(p) + "] = " + hex(b))
  141.         if b < 0x20: # special sign
  142.             o += signs[b]
  143.             p += 1
  144.         elif b < 0x60:
  145.             b &= 31
  146.             o += str(line[p + 1:p + 1 + b])
  147.             p += b + 1
  148.         elif b == 0x80:
  149.             b = line[p + 1]
  150.             o += "\"" + str(line[p + 2:p + 2 + b]) + "\""
  151.             p += b + 2
  152.         elif b == 0x60:     # tokenized BASIC keyword
  153.             b = line[p + 1]
  154.             o += tokens[b]
  155.             #print("Basic token=" + str(b) + " ~ " + hex(b))
  156.             if b in [81, 61, 36, 12]: # REM or !, IMAGE, DATA marks start of "free" text till the end of the line (?)
  157.                 o += str(line[p + 2:])
  158.                 break
  159.             else:
  160.                 o += " " # should I print a space after a basic token, always?
  161.                 p += 2
  162.         elif b in [0xA2, 0xC2]:     # two byte (integer) constant
  163.             o += str(line[p + 1] | (line[p + 2] << 8))
  164.             p += 3
  165.         elif b == 0xC6: # float constant, or so ...
  166.             #print("FLOAT")
  167.             #print(hexdump(line[p + 1:p + 7]))
  168.             s = (hexbyte(line[p + 5]) + hexbyte(line[p + 4]) + hexbyte(line[p + 3]) + hexbyte(line[p + 2]) + hexbyte(line[p + 1]))
  169.             b = line[p + 6] - 0x3F
  170.             if b > 0: s = s[0:b] + "." + s[b:]
  171.             else: s = "." + "0" * -b + s
  172.             o += s.rstrip("0").rstrip(".")
  173.             p += 7
  174.         else:
  175.             print("Parsing state = \"" + o + "\"")
  176.             die("Unknown byte found in the stream: " + hex(b))
  177.     return o
  178.  
  179.  
  180. def list_program(prg):
  181.     pos = 0
  182.     while True:
  183.         ll = prg[pos]
  184.         #print("linelength=" + str(ll))
  185.         if ll == 0: return
  186.         if prg[pos + ll - 1] != 0: die("Invalid line, not terminated with zero")
  187.         print(list_line(prg[pos + 1:pos + ll - 1]))
  188.         pos += ll
  189.  
  190.  
  191. if __name__ == "__main__":
  192.     if len(sys.argv) != 2:
  193.         die("Bad usage, give the file name")
  194.     try:
  195.         with open(sys.argv[1], "r") as f: prg = bytearray(f.read())
  196.     except IOError as e:
  197.         die("Reading input file: " + str(e))
  198.     list_program(prg[0x10:])
  199.     die()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement