REM
REM List a binary blassic program.
REM

rem DEF FN peekvalue (p$, a)=asc (mid$ (p$, a, 1) ) + 256 * (asc (mid$ (p$, a + 1, 1) ) + 256 * (asc (mid$ (p$, a + 2, 1) ) + 256 * asc (mid$ (p$, a + 3, 1) ) ) )

DEF FN peekvalue (a)=asc (mid$ (prog$, a, 1) ) + 256 * (asc (mid$ (prog$, a + 1, 1) ) + 256 * (asc (mid$ (prog$, a + 2, 1) ) + 256 * asc (mid$ (prog$, a + 3, 1) ) ) )

GOTO init

LABEL peekvalue

r= ASC (MID$ (prog$, a, 1) ) + 256 * (ASC (MID$ (prog$, a + 1, 1) ) + 256 * (ASC (MID$ (prog$, a + 2, 1) ) + 256 * ASC (MID$ (prog$, a + 3, 1) ) ) )
RETURN

LABEL decodeline

endline= p + l + 7
FOR i= p + 8 TO endline
	c= ASC (MID$ (prog$, i, 1) )

	if c <> 0 then goto no_padding
	if deb then li$= li$ + "(padding: " + str$ (endline - i + 1) + ")"
	i= endline
	goto nextchar

	label no_padding
	IF c = 1 OR c = 2 OR c = 3 OR c = 4 OR c = 6 THEN GOTO iscode
	IF c = 5 THEN GOTO isinteger
	IF c <> ASC ("""") THEN GOTO noliteral

	li$= li$ + """" : i= i + 1
	WHILE MID$ (prog$, i, 1) <> CHR$ (0)
		IF MID$ (prog$, i, 1) <> """" THEN li$= li$ + MID$ (prog$, i, 1) ELSE li$= li$ + """"""
		i= i + 1
	WEND
	li$= li$ + """"
	GOTO nextchar

	LABEL noliteral

	li$= li$ + MID$ (prog$, i, 1)
	GOTO nextchar

	LABEL isinteger
	num%= fn peekvalue (i+1)
	if deb then li$= li$ + "[INT "
	li$= li$ + str$ (num%)
	if deb then li$= li$ + "]"
	i= i + 4
	GOTO nextchar

	LABEL iscode

	code= 256 * ASC (MID$ (prog$, i, 1) ) + ASC (MID$ (prog$, i + 1, 1) )
	GOSUB gettoken
	if deb then li$= li$ + "[KEY "
	li$= li$ + token$
	if deb then li$= li$ + "]"
	i= i + 1

	LABEL nextchar
NEXT

RETURN


REM Bucle principal

LABEL init

numbers= not 0

arg= 1
label moreargs
if programarg$ (arg) = "-n" then numbers= 0: arg= arg + 1: goto moreargs
if programarg$ (arg) = "-d" then deb= not 0: arg= arg + 1: goto moreargs

progname$= PROGRAMARG$ (arg)

IF progname$ = "" THEN PRINT "Falta argumento" : END

LOAD progname$, prog$

IF LEFT$ (prog$, 8) <> "Blassic" + CHR$ (0) THEN PRINT "No es un binario Blassic" : END

gosub loadtable

endprog= LEN (prog$)
p= 17 : REM Salta la identificacion y cabecera

WHILE p < endprog
	'if deb then: print "(at "; hex$ (p - 17, 8); ") ";
	if deb then print "(at "; hex$ (p - 1, 8); ") ";
	rem a= p: GOSUB peekvalue: n= r
	rem n= FN peekvalue (prog$, p)
	n= FN peekvalue (p)
	li$= ""
	if numbers then li$= RIGHT$ ("       " + str$ (n), 7) + " "
	rem a= p + 4: GOSUB peekvalue: l= r
	rem l= FN peekvalue (prog$, p + 4)
	l= FN peekvalue (p + 4)
	IF l > 0 THEN GOSUB decodeline
	PRINT li$
	p= p + 8 + l
WEND

END

REM Carga la tabla de codigos

LABEL loadtable

numcod= 252
dim name$ (numcod), cod (numcod)
for i= 1 to numcod
	read name$ (i), cod$: cod (i)= val (cod$)
	rem print name$ (i), cod (i)
next
read check$ : if check$ <> "***" then print "ERROR EN DATAS" : end
return


REM Obtiene el token correspondiente al codigo

LABEL gettoken

res= 0
b1=1
if cod (b1) = code then res= b1: goto tokenfound
b2= numcod
if cod (b2) = code then res= b2: goto tokenfound

label othertoken
bm= int ((b1 + b2) / 2)
if cod (bm) = code then res= bm: goto tokenfound
if cod (bm) < code then b1= bm else b2= bm
if b2 > b1 + 1 then goto othertoken

label tokenfound
if res = 0 then token$= "??" + str$ (code) + "??" else token$= name$ (res)
return

REM Comandos

DATA "END", &0101
DATA "LIST", &0102
DATA "REM", &0103
DATA "LOAD", &0104
DATA "SAVE", &0105
DATA "NEW", &0106
DATA "EXIT", &0107
DATA "RUN", &0108
DATA "PRINT", &0109
DATA "FOR", &010A
DATA "NEXT", &010B
DATA "TO", &010C
DATA "STEP", &010D
DATA "IF", &010E
DATA "THEN", &010F
DATA "ELSE", &0110
DATA "TRON", &0111
DATA "TROFF", &0112
DATA "LET", &0113
DATA "GOTO", &0114
DATA "STOP", &0115
DATA "CONT", &0116
DATA "CLEAR", &0117
DATA "GOSUB", &0118
DATA "RETURN", &0119
DATA "POKE", &011A
DATA "DATA", &011B
DATA "READ", &011C
DATA "RESTORE", &011D
DATA "INPUT", &011E
DATA "LINE", &011F
DATA "RANDOMIZE", &0120
DATA "PLEASE", &0121
DATA "AUTO", &0122
DATA "DIM", &0123
DATA "SYSTEM", &0124
DATA "ON", &0125
DATA "ERROR", &0126
DATA "OPEN", &0127
DATA "CLOSE", &0128
DATA "OUTPUT", &0129
DATA "AS", &012A
DATA "LOCATE", &012B
DATA "CLS", &012C
DATA "APPEND", &012D
DATA "WRITE", &012E
DATA "MODE", &012F
DATA "MOVE", &0130
DATA "COLOR", &0131
DATA "GET", &0132
DATA "LABEL", &0133
DATA "DELIMITER", &0134
DATA "REPEAT", &0135
DATA "UNTIL", &0136
DATA "WHILE", &0137
DATA "WEND", &0138
DATA "PLOT", &0139
DATA "POPEN", &013A
DATA "RESUME", &013B
DATA "DELETE", &013C
DATA "LOCAL", &013D
DATA "RANDOM", &013E
DATA "PUT", &013F
DATA "FIELD", &0140
DATA "LSET", &0141
DATA "RSET", &0142
DATA "SOCKET", &0143
DATA "DRAW", &0144
DATA "DEF", &0145
DATA "FN", &0146
DATA "ERASE", &0147
DATA "SWAP", &0148
DATA "SYMBOL", &0149
DATA "ZONE", &014A
DATA "POP", &014B
DATA "NAME", &014C
DATA "KILL", &014D
DATA "FILES", &014E
DATA "PAPER", &014F
DATA "PEN", &0150
DATA "SHELL", &0151
DATA "MERGE", &0152
DATA "CHDIR", &0153
DATA "MKDIR", &0154
DATA "RMDIR", &0155
DATA "BREAK", &0156
DATA "SYNCHRONIZE", &0157
DATA "PAUSE", &0158
DATA "CHAIN", &0159
DATA "STR", &015A
DATA "REAL", &015B
DATA "ENVIRON", &015C
DATA "EDIT", &015D
DATA "DRAWR", &015E
DATA "PLOTR", &015F
DATA "MOVER", &0160
DATA "POKE16", &0161
DATA "POKE32", &0162
DATA "RENUM", &0163
DATA "CIRCLE", &0164
DATA "MASK", &0165
DATA "WINDOW", &0166
DATA "GRAPHICS", &0167
DATA "AFTER", &0168
DATA "BEEP", &0169
DATA "DEFINT", &016A
DATA "DEFSTR", &016B
DATA "DEFREAL", &016C
DATA "DEFSNG", &016D
DATA "DEFDBL", &016E
DATA "INK", &016F
DATA "SET_TITLE", &0170
DATA "TAG", &0171
DATA "TAGOFF", &0172
DATA "ORIGIN", &0173
DATA "DEG", &0174
DATA "RAD", &0175
DATA "INVERSE", &0176
DATA "IF_DEBUG", &0177
DATA "LPRINT", &0178
DATA "LLIST", &0179
DATA "WIDTH", &017A
DATA "BRIGHT", &017B
DATA "BINARY", &017C
DATA "DRAWARC", &017D
DATA "PULL", &017E
DATA "PAINT", &017F
DATA "FREE_MEMORY", &0180
DATA "SCROLL", &0181
DATA "ZX_PLOT", &0182
DATA "ZX_UNPLOT", &0183

REM Funciones de cadena

DATA "MID$", &0201
DATA "LEFT$", &0202
DATA "RIGHT$", &0203
DATA "CHR$", &0204
DATA "ENVIRON$", &0205
DATA "STRING$", &0206
DATA "OSFAMILY$", &0207
DATA "HEX$", &0208
DATA "SPACE$", &0209
DATA "UPPER$", &020A
DATA "LOWER$", &020B
DATA "STR$", &020C
DATA "OCT$", &020D
DATA "BIN$", &020E
DATA "INKEY$", &020F
DATA "PROGRAMARG$", &0210
DATA "DATE$", &0211
DATA "TIME$", &0212
DATA "INPUT$", &0213
DATA "MKI$", &0214
DATA "MKS$", &0215
DATA "MKD$", &0216
DATA "MKL$", &0217
DATA "TRIM$", &0218
DATA "LTRIM$", &0219
DATA "RTRIM$", &021A
DATA "OSNAME$", &021B
DATA "FINDFIRST$", &021C
DATA "FINDNEXT$", &021D
DATA "COPYCHR$", &021E
DATA "STRERR$", &021F
DATA "DEC$", &0220
DATA "VAL$", &0221
DATA "SCREEN$", &0222
DATA "MKSMBF$", &0223
DATA "MKDMBF$", &0224
DATA "REGEXP_REPLACE$", &0225
DATA "UCASE$", &0226
DATA "LCASE$", &0227

REM Funciones numericas

DATA "ASC", &0301
DATA "LEN", &0302
DATA "PEEK", &0303
DATA "PROGRAMPTR", &0304
DATA "RND", &0305
DATA "INT", &0306
DATA "SIN", &0307
DATA "COS", &0308
DATA "PI", &0309
DATA "TAN", &030A
DATA "SQR", &030B
DATA "ASIN", &030C
DATA "ACOS", &030D
DATA "INSTR", &030E
DATA "ATAN", &030F
DATA "ABS", &0310
DATA "USR", &0311
DATA "VAL", &0312
DATA "EOF", &0313
DATA "VARPTR", &0314
DATA "SYSVARPTR", &0315
DATA "SGN", &0316
DATA "LOG", &0317
DATA "LOG10", &0318
DATA "EXP", &0319
DATA "TIME", &031A
DATA "ERR", &031B
DATA "ERL", &031C
DATA "CVI", &031D
DATA "CVS", &031E
DATA "CVD", &031F
DATA "CVL", &0320
DATA "MIN", &0321
DATA "MAX", &0322
DATA "CINT", &0323
DATA "FIX", &0324
DATA "XMOUSE", &0325
DATA "YMOUSE", &0326
DATA "XPOS", &0327
DATA "YPOS", &0328
DATA "PEEK16", &0329
DATA "PEEK32", &032A
DATA "RINSTR", &032B
DATA "FIND_FIRST_OF", &032C
DATA "FIND_LAST_OF", &032D
DATA "FIND_FIRST_NOT_OF", &032E
DATA "FIND_LAST_NOT_OF", &032F
DATA "SINH", &0330
DATA "COSH", &0331
DATA "TANH", &0332
DATA "ASINH", &0333
DATA "ACOSH", &0334
DATA "ATANH", &0335
DATA "ATAN2", &0336
DATA "TEST", &0337
DATA "TESTR", &0338
DATA "POS", &0339
DATA "VPOS", &033A
DATA "LOF", &033B
DATA "FREEFILE", &033C
DATA "INKEY", &033D
DATA "ROUND", &033E
DATA "CVSMBF", &033F
DATA "CVDMBF", &0340
DATA "REGEXP_INSTR", &0341
DATA "ALLOC_MEMORY", &0342
DATA "LOC", &0343

REM Operadores

DATA "NOT", &0401
DATA "OR", &0402
DATA "AND", &0403
DATA "TAB", &0404
DATA "SPC", &0405
DATA "AT", &0406
DATA "XOR", &0407
DATA "MOD", &0408
DATA "USING", &0409

REM Comparaciones

DATA "<>", &0604
DATA "<=", &0605
DATA ">=", &0606
DATA "=<", &0608
DATA "=>", &0609
DATA "><", &060A

DATA "***"

REM Fin
