dmolony-DiskBrowser/src/com/bytezone/diskbrowser/applefile/BasicProgramGS.java

237 lines
9.5 KiB
Java

package com.bytezone.diskbrowser.applefile;
import static com.bytezone.diskbrowser.utilities.Utility.isHighBitSet;
import java.util.ArrayList;
import java.util.List;
import com.bytezone.diskbrowser.utilities.Utility;;
// -----------------------------------------------------------------------------------//
public class BasicProgramGS extends BasicProgram
// -----------------------------------------------------------------------------------//
{
private static String[] //
tokens = { "AUTO", "DEL", "EDI", "HLIST ", // 0x80 - 0x83
"LIST", "RENUM", "BREAK ", "FN ", // 0x84 - 0x87
"PROC ", "GOSUB", " GOTO ", "FOR ", // 0x88 - 0x8B
" THEN ", "ELSE ", "NEXT ", "OFF ", // 0x8C - 0x8F
"ON ", "INPUT ", "OUTPUT ", "TEXT ", // 0x90 - 0x93
"TIMER ", "EXCEPTION ", "CAT ", " 97 ", // 0x94 - 0x97
"INIT ", "INVOKE ", "LIBRARY ", "PREFIX ", // 0x98 - 0x9B
"TYPE ", "LOAD ", "SAVE ", "DELETE ", // 0x9C - 0x9F
"RUN ", "RENAME ", "CREATE ", "LOCK ", // 0xA0 - 0xA3
"UNLOCK ", "EXEC ", "CHAIN ", "CATALOG ", // 0xA4 - 0xA7
"OPEN ", "QUIT ", "DIR ", "DIM ", // 0xA8 - 0xAB
"READ ", "WRITE ", "CLOSE ", "TASKPOLL ", // 0xAC - 0xAF
"LOCATE ", "EVENTDEF ", "MENUDEF ", "VOLUMES ", // 0xB0 - 0xB3
"CALL% ", "CALL ", "_", "TEXTPORT ", // 0xB4 - 0xB7
"PERFORM ", "GRAF ", "DBUG ", "POP ", // 0xB8 - 0xBB
"HOME ", "SUB$(", "TRACE ", "NOTRACE ", // 0xBC - 0xBF
"NORMAL ", "INVERSE ", "RESUME ", "LET ", // 0xC0 - 0xC3
"IF ", "RESTORE ", "SWAP ", "RETURN ", // 0xC4 - 0xC7
"REM ", "STOP ", "DATA ", "IMAGE ", // 0xC8 - 0xCB
"LIBFIND ", "DEF ", "PRINT ", "CLEAR ", // 0xCC - 0xCF
"RANDOMIZE ", "NEW ", "POKE ", "ASSIGN ", // 0xD0 - 0xD3
"GET ", "PUT ", "SET ", "ERROR ", // 0xD4 - 0xD7
"ERASE ", "LOCAL ", "WHILE ", "CONT ", // 0xD8 - 0xDB
"DO ", "UNTIL ", "END ", " DF ", // 0xDC - 0xDF
" E0 ", " E1 ", " E2 ", " E3 ", // 0xE0 - 0xE3
" E4 ", " E5 ", " E6 ", " E7 ", // 0xE4 - 0xE7
" E8 ", " E9 ", " EA ", " EB ", // 0xE8 - 0xEB
" EC ", " ED ", " EE ", " EF ", // 0xEC - 0xEF
" F0 ", " F1 ", " F2 ", " F3 ", // 0xF0 - 0xF3
" F4 ", " F5 ", " F6 ", " F7 ", // 0xF4 - 0xF7
" F8 ", " F9 ", " FA ", " FB ", // 0xF8 - 0xFB
" FC ", " FD ", " FE ", " FF ", // 0xFC - 0xFF
};
private static String[] //
tokensDF = { " TAB(", " TO ", " SPC(", " USING ", // 0x80 - 0x83
"APPEND ", " MOD ", " REMDR ", " STEP ", // 0x84 - 0x87
" AND ", " OR ", " XOR ", " DIV ", // 0x88 - 0x8B
" SRC ", " NOT ", " 8E ", " UPDATE ", // 0x8C - 0x8F
" TXT ", " BDF ", " FILTYPE= ", " AS ", // 0x90 - 0x93
" 94 ", " 95 ", " SGN(", " INT ", // 0x94 - 0x97
" ABS(", " TYP(", " REC(", " JOYX(", // 0x98 - 0x9B
" PDL(", " BTN(", " R.STACK% ", " R.STACK@ ", // 0x9C - 0x9F
" R.STACK&(", " SQR(", " RND(", " LOG(", // 0xA0 - 0xA3
" LOG1(", " LOG2(", " LOGB%(", " EXP(", // 0xA4 - 0xA7
" EXP1(", " EXP2(", " COS(", " SIN(", // 0xA8 - 0xAB
" TAN(", " ATN(", " BASIC@(", " DATE(", // 0xAC - 0xAF
" EOFMARK(", " FILTYP(", " FIX(", " FREMEM(", // 0XB0 - 0xB3
" NEGATE(", " PEEK(", " ROUND(", " TASKREC%(", // 0xB4 - 0xB7
" TASKREC@(", " TIME(", " UIR(", " STR$(", // 0xB8 - 0xBB
" HEX$(", " PFX$(", " SPACE$(", " ERRTXT$(", // 0xBC - 0xBF
" CHR$(", " RELATION(", " ANU(", " COMPI(", // 0xC0 - 0xC3
" SCALB(", " SCALE(", " LEN(", " VAL(", // 0xC4 - 0xC7
" ASC(", " UCASE$(", "TEN(", " CONV#(", // 0xC8 - 0xCB
" CONV@(", " CONV(", " CONV&(", " CONV$", // 0xCC - 0xCF
" CONV%(", " LEFT$(", " RIGHT$(", " REP$(", // 0xD0 - 0xD3
" MID$(", " INSTR(", "VARPTR(", "VARPTR$(", // 0xD4 - 0xD7
"VAR$(", "VAR(", " UBOUND(", " FILE(", // 0xD8 - 0xDB
" EXEVENT@(", " DD ", " DE ", " DF ", // 0xDC - 0xDF
" HPOS ", " VPOS ", " TIME$ ", " DATE$ ", // 0xE0 - 0xE3
" PREFIX$ ", " E5 ", " OUTREC ", " INDENT ", // 0xE4 - 0xE7
" SHOWDIGITS ", " LISTTAB ", " AUXID@ ", " EXFN ", // 0xE8 - 0xEB
" SECONDS@ ", " FRE ", " ERRLIN ", "ERR ", // 0xEC - 0xEF
" KBD ", " EOF ", " JOYY ", " PDL9 ", // 0xF0 - 0xF3
" PI ", " ERRTOOL ", " F6 ", " F7 ", // 0xF4 - 0xF7
" F8 ", " F9 ", " FA ", " FB ", // 0xF8 - 0xFB
" FC ", " FD ", " FE ", " FF ", // 0xFC - 0xFF
};
private final List<SourceLine> sourceLines = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
public BasicProgramGS (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
// need to validate these files - seem to sometimes contain palette files
// 0132 816-Paint.po
int ptr = 5;
while (ptr < buffer.length)
{
SourceLine sourceLine = new SourceLine (ptr);
if (sourceLine.lineNumber == 0)
break;
sourceLines.add (sourceLine);
ptr += sourceLine.length;
}
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
for (SourceLine sourceLine : sourceLines)
text.append (sourceLine + "\n");
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private class SourceLine
// ---------------------------------------------------------------------------------//
{
int lineNumber;
int length;
String label;
String line;
public SourceLine (int ptr)
{
int labelLength = buffer[ptr] & 0xFF;
if (labelLength > 1)
label = new String (buffer, ptr + 1, labelLength - 1);
else
label = "";
ptr += labelLength;
int lineLength = buffer[ptr] & 0xFF;
lineNumber = Utility.getShort (buffer, ptr + 1);
length = labelLength + lineLength;
if (lineNumber == 0)
return;
ptr += 3;
int max = ptr + lineLength - 4;
StringBuilder text = new StringBuilder ();
while (ptr < max)
{
byte b1 = buffer[ptr++];
if (isHighBitSet (b1))
ptr = tokenOrNumber (b1, text, ptr);
else
text.append ((b1 & 0xFF) < 32 ? '.' : (char) b1);
}
line = text.toString ();
}
private int tokenOrNumber (byte b1, StringBuilder text, int ptr)
{
if (b1 == (byte) 0xDF)
{
append (tokensDF[(buffer[ptr++] & 0x7F)], text);
return ptr;
}
if (b1 < (byte) 0xE0)
{
append (tokens[(b1 & 0x7F)], text);
return ptr;
}
if (b1 == (byte) 0xFC) // 3 bytes
{
text.append (get (ptr, 3));
return ptr + 4; // skip trailing zero
}
if (b1 == (byte) 0xFA) // 2 bytes
{
text.append (get (ptr, 2));
return ptr + 2;
}
if (b1 == (byte) 0xFB)
{
return ptr + 3; // ignore next 3 bytes (why?)
}
if ((b1 & 0xF0) == 0xF0) // F0:F9 = 0:9
{
text.append (b1 & 0x0F);
return ptr;
}
if ((b1 & 0xE0) == 0xE0) // 3 nybbles
{
text.append (((b1 & 0x0F) << 8) | (buffer[ptr++] & 0xFF));
return ptr;
}
System.out.printf ("not handled: %02X%n", b1);
return ptr;
}
private void append (String word, StringBuilder text)
{
if (word.startsWith (" ") && text.length () > 0
&& text.charAt (text.length () - 1) == ' ')
text.deleteCharAt (text.length () - 1);
text.append (word);
}
private int get (int ptr, int size)
{
int val = 0;
for (int i = 0; i < size; i++)
val |= (buffer[ptr++] & 0xFF) << (i * 8);
return val;
}
private void show (int ptr, int size)
{
for (int i = 0; i < size; i++)
System.out.printf (" %02X ", buffer[ptr++]);
System.out.println ();
}
@Override
public String toString ()
{
return String.format ("%5d %-12s %s", lineNumber, label, line);
}
}
}