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

279 lines
8.5 KiB
Java
Raw Normal View History

2015-06-01 09:35:51 +00:00
package com.bytezone.diskbrowser.applefile;
2016-02-24 21:11:14 +00:00
import com.bytezone.diskbrowser.utilities.HexFormatter;
2015-06-01 09:35:51 +00:00
2019-08-09 23:45:49 +00:00
public class IntegerBasicProgram extends BasicProgram
2015-06-01 09:35:51 +00:00
{
2016-04-09 10:38:17 +00:00
private static String[] tokens =
2016-12-17 22:07:55 +00:00
{ "?", "?", "?", " : ", "?", "?", "?", "?", "?", "?", "?", "?", "CLR", "?", "?",
"?", "HIMEM: ", "LOMEM: ", " + ", " - ", " * ", " / ", " = ", " # ", " >= ",
" > ", " <= ", " <> ", " < ", " AND ", " OR ", " MOD ", "^", "+", "(", ",",
" THEN ", " THEN ", ",", ",", "\"", "\"", "(", "!", "!", "(", "PEEK ", "RND ",
"SGN", "ABS", "PDL", "RNDX", "(", "+", "-", "NOT ", "(", "=", "#", "LEN(", "ASC(",
"SCRN(", ",", "(", "$", "$", "(", ", ", ",", ";", ";", ";", ",", ",", ",", "TEXT",
"GR ", "CALL ", "DIM ", "DIM ", "TAB ", "END", "INPUT ", "INPUT ", "INPUT ",
"FOR ", " = ", " TO ", " STEP ", "NEXT ", ",", "RETURN", "GOSUB ", "REM ", "LET ",
"GOTO ", "IF ", "PRINT ", "PRINT ", "PRINT", "POKE ", ",", "COLOR=", "PLOT", ",",
"HLIN", ",", " AT ", "VLIN ", ",", " AT ", "VTAB ", " = ", " = ", ")", ")",
"LIST ", ",", "LIST ", "POP ", "NODSP ", "NODSP ", "NOTRACE ", "DSP ", "DSP ",
"TRACE ", "PR#", "IN#", };
2016-04-09 10:38:17 +00:00
public IntegerBasicProgram (String name, byte[] buffer)
{
super (name, buffer);
}
@Override
public String getText ()
{
StringBuilder pgm = new StringBuilder ();
pgm.append ("Name : " + name + "\n");
2019-08-01 07:31:49 +00:00
pgm.append (String.format ("Length : $%04X (%<,d)%n%n", buffer.length));
2016-04-09 10:38:17 +00:00
int ptr = 0;
boolean looksLikeAssembler = checkForAssembler (); // this can probably go
boolean looksLikeSCAssembler = checkForSCAssembler ();
while (ptr < buffer.length)
{
2016-12-17 22:07:55 +00:00
int lineLength = buffer[ptr] & 0xFF;
2016-04-09 10:38:17 +00:00
/*
* It appears that lines ending in 00 are S-C Assembler programs, and
* lines ending in 01 are Integer Basic programs.
*/
int p2 = ptr + lineLength - 1;
if (p2 < 0 || p2 >= buffer.length || (buffer[p2] != 1 && buffer[p2] != 0))
{
pgm.append ("\nPossible assembler code follows\n");
break;
}
2019-08-08 10:01:56 +00:00
2016-04-09 10:38:17 +00:00
if (lineLength <= 0)
break;
if (looksLikeSCAssembler)
2019-08-08 10:01:56 +00:00
appendSCAssembler (pgm, ptr);
2016-04-09 10:38:17 +00:00
else if (looksLikeAssembler)
appendAssembler (pgm, ptr, lineLength);
else
appendInteger (pgm, ptr, lineLength);
pgm.append ("\n");
ptr += lineLength;
}
2017-06-24 06:22:44 +00:00
if ((ptr + 4) < buffer.length)
2016-04-09 10:38:17 +00:00
{
int address = HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]);
int remainingBytes = buffer.length - ptr - 5;
byte[] newBuffer = new byte[remainingBytes];
System.arraycopy (buffer, ptr + 4, newBuffer, 0, remainingBytes);
AssemblerProgram ap = new AssemblerProgram ("embedded", newBuffer, address);
pgm.append ("\n" + ap.getText () + "\n");
}
pgm.deleteCharAt (pgm.length () - 1);
return pgm.toString ();
}
private void appendAssembler (StringBuilder pgm, int ptr, int lineLength)
{
for (int i = ptr + 3; i < ptr + lineLength - 1; i++)
{
if ((buffer[i] & 0x80) == 0x80)
{
int spaces = buffer[i] & 0x0F;
for (int j = 0; j < spaces; j++)
pgm.append (' ');
continue;
}
2016-12-17 22:07:55 +00:00
int b = buffer[i] & 0xFF;
2016-04-09 10:38:17 +00:00
pgm.append ((char) b);
}
}
private boolean checkForAssembler ()
{
int ptr = 0;
while (ptr < buffer.length)
{
2016-12-17 22:07:55 +00:00
int lineLength = buffer[ptr] & 0xFF;
2016-04-09 10:38:17 +00:00
if (lineLength == 255)
System.out.printf ("Line length %d%n", lineLength);
int p2 = ptr + lineLength - 1;
if (p2 < 0 || p2 >= buffer.length || (buffer[p2] != 1 && buffer[p2] != 0))
break;
if (lineLength <= 0) // in case of looping bug
break;
// check for comments
if (buffer[ptr + 3] == 0x3B || buffer[ptr + 3] == 0x2A)
return true;
ptr += lineLength;
}
return false;
}
private boolean checkForSCAssembler ()
{
2016-07-29 12:28:11 +00:00
if (buffer.length == 0)
{
System.out.println ("Empty buffer array");
return false;
}
2016-12-17 22:07:55 +00:00
int lineLength = buffer[0] & 0xFF;
2016-04-09 10:38:17 +00:00
if (lineLength <= 0)
return false;
return buffer[lineLength - 1] == 0;
}
2019-08-08 10:01:56 +00:00
private void appendSCAssembler (StringBuilder text, int ptr)
2016-04-09 10:38:17 +00:00
{
2016-12-17 22:07:55 +00:00
int lineNumber = (buffer[ptr + 2] & 0xFF) * 256 + (buffer[ptr + 1] & 0xFF);
2019-08-08 10:01:56 +00:00
text.append (String.format ("%4d: ", lineNumber));
2016-04-09 10:38:17 +00:00
int p2 = ptr + 3;
while (buffer[p2] != 0)
{
if (buffer[p2] == (byte) 0xC0)
{
int repeat = buffer[p2 + 1];
for (int i = 0; i < repeat; i++)
2019-08-08 10:01:56 +00:00
text.append ((char) buffer[p2 + 2]);
2016-04-09 10:38:17 +00:00
p2 += 2;
}
else if ((buffer[p2] & 0x80) != 0)
{
int spaces = buffer[p2] & 0x7F;
for (int i = 0; i < spaces; i++)
2019-08-08 10:01:56 +00:00
text.append (' ');
2016-04-09 10:38:17 +00:00
}
else
2019-08-08 10:01:56 +00:00
text.append ((char) buffer[p2]);
2016-04-09 10:38:17 +00:00
p2++;
}
}
2019-08-08 10:01:56 +00:00
private void appendInteger (StringBuilder text, int ptr, int lineLength)
2016-04-09 10:38:17 +00:00
{
int lineNumber = HexFormatter.intValue (buffer[ptr + 1], buffer[ptr + 2]);
boolean inString = false;
boolean inRemark = false;
String lineText = String.format ("%5d ", lineNumber);
int lineTab = lineText.length ();
2019-08-08 10:01:56 +00:00
text.append (lineText);
2016-04-09 10:38:17 +00:00
for (int p = ptr + 3; p < ptr + lineLength - 1; p++)
{
2016-12-17 22:07:55 +00:00
int b = buffer[p] & 0xFF;
2016-04-09 10:38:17 +00:00
2019-08-09 23:45:49 +00:00
if (b == 0x03 // token for colon (:)
&& !inString && !inRemark && buffer[p + 1] != 1) // not end of line
2016-04-09 10:38:17 +00:00
{
2019-08-08 10:01:56 +00:00
text.append (":\n" + " ".substring (0, lineTab));
2016-04-09 10:38:17 +00:00
continue;
}
if (b >= 0xB0 && b <= 0xB9 // numeric literal
2016-12-17 22:07:55 +00:00
&& (buffer[p - 1] & 0x80) == 0 // not a variable name
&& !inString && !inRemark)
2016-04-09 10:38:17 +00:00
{
2019-08-08 10:01:56 +00:00
text.append (HexFormatter.intValue (buffer[p + 1], buffer[p + 2]));
2016-04-09 10:38:17 +00:00
p += 2;
continue;
}
if (b >= 128)
{
b -= 128;
if (b >= 32)
2019-08-08 10:01:56 +00:00
text.append ((char) b);
2016-04-09 10:38:17 +00:00
else
2019-08-08 10:01:56 +00:00
text.append ("<ctrl-" + (char) (b + 64) + ">");
2016-04-09 10:38:17 +00:00
}
else if (!tokens[b].equals ("?"))
{
2019-08-08 10:01:56 +00:00
text.append (tokens[b]);
2016-04-09 10:38:17 +00:00
if ((b == 40 || b == 41) && !inRemark) // double quotes
inString = !inString;
if (b == 0x5D)
inRemark = true;
}
else
2019-08-08 10:01:56 +00:00
text.append (" ." + HexFormatter.format2 (b) + ". ");
2016-04-09 10:38:17 +00:00
}
}
@Override
public String getHexDump ()
{
if (false)
return super.getHexDump ();
StringBuffer pgm = new StringBuffer ();
pgm.append ("Name : " + name + "\n");
pgm.append ("Length : $" + HexFormatter.format4 (buffer.length) + " (" + buffer.length
2016-12-17 22:07:55 +00:00
+ ")\n\n");
2016-04-09 10:38:17 +00:00
int ptr = 0;
while (ptr < buffer.length)
{
2016-12-17 22:07:55 +00:00
int lineLength = buffer[ptr] & 0xFF;
2016-04-09 10:38:17 +00:00
int p2 = ptr + lineLength - 1;
if (p2 < 0 || p2 >= buffer.length || buffer[p2] > 1)
{
System.out.println ("invalid line");
break;
}
pgm.append (HexFormatter.formatNoHeader (buffer, ptr, lineLength));
pgm.append ("\n");
if (lineLength <= 0)
{
System.out.println ("looping");
break;
}
ptr += lineLength;
pgm.append ("\n");
}
if (pgm.length () > 0)
pgm.deleteCharAt (pgm.length () - 1);
return pgm.toString ();
}
2017-06-24 21:46:23 +00:00
/*
* To find integer basic in memory:
2017-07-09 09:26:13 +00:00
* $CA $CB contain the starting address ($9464)
2017-06-24 21:46:23 +00:00
* http://www.easy68k.com/paulrsm/6502/INTLST.TXT
*/
2017-05-08 01:46:28 +00:00
/*
* https://groups.google.com/forum/#!topic/comp.sys.apple2/Baf36jyqwAM
* To convert Integer Basic to Applesoft
INPUT comands - change comma to semi-colon
remove all DIM of a string variable (not needed)
change string variables to use MID$ - i.e. A$(1,1)(in INT) is MID$(A$,1,1)(in AS basic)
change GOTO or GOSUB with a variable to ON GOTO
2019-08-01 07:31:49 +00:00
change IF statements to ON GOTO where possible and convert to multiple lines.
All statements that follow an IF on the same line are executed whether the statement
2017-05-08 01:46:28 +00:00
is true or not.
change MOD function to X=Y-(INT(Y/Z)*Z)
change "#" to "<>"
change TAB to HTAB
change RND(X) to INT(RND(1)*X)
2019-08-01 07:31:49 +00:00
relocate ML programs and change CALL'S and POKE'S. Since INT programs go from
2017-05-08 01:46:28 +00:00
HIMEM down, binary code is usually in low memory.
These few are not necessary but make for compact code.
change CALL -384 to INVERSE
change CALL -380 to NORMAL
2019-08-01 07:31:49 +00:00
change CALL -936 to HOME
2017-05-08 01:46:28 +00:00
*/
2015-06-01 09:35:51 +00:00
}