From db4953618caeb794f4b2bf34cd9979678178e918 Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Mon, 28 Mar 2022 13:55:49 +1000 Subject: [PATCH] allow woz format pascal disks --- .../applefile/SegmentDictionary.java | 4 +- .../diskbrowser/disk/DiskFactory.java | 11 +- .../diskbrowser/pascal/CatalogEntry.java | 5 +- .../diskbrowser/pascal/PascalCodeObject.java | 1 + .../diskbrowser/pascal/PascalDisk.java | 34 ++- .../diskbrowser/wizardry/Monster.java | 207 +++++++++++++----- .../bytezone/diskbrowser/wizardry/Reward.java | 7 + .../wizardry/WizardryScenarioDisk.java | 3 +- 8 files changed, 184 insertions(+), 88 deletions(-) diff --git a/src/com/bytezone/diskbrowser/applefile/SegmentDictionary.java b/src/com/bytezone/diskbrowser/applefile/SegmentDictionary.java index da5f057..12ef456 100644 --- a/src/com/bytezone/diskbrowser/applefile/SegmentDictionary.java +++ b/src/com/bytezone/diskbrowser/applefile/SegmentDictionary.java @@ -33,8 +33,8 @@ public class SegmentDictionary ptr += 8; } - for (int seg = 0; seg < 16; seg++) - System.out.printf ("%04X %04X %s%n", codeAddress[seg], codeLength[seg], segName[seg]); + // for (int seg = 0; seg < 16; seg++) + // System.out.printf ("%04X %04X %s%n", codeAddress[seg], codeLength[seg], segName[seg]); } // ---------------------------------------------------------------------------------// diff --git a/src/com/bytezone/diskbrowser/disk/DiskFactory.java b/src/com/bytezone/diskbrowser/disk/DiskFactory.java index 540be5b..d05a9a8 100755 --- a/src/com/bytezone/diskbrowser/disk/DiskFactory.java +++ b/src/com/bytezone/diskbrowser/disk/DiskFactory.java @@ -356,6 +356,8 @@ public class DiskFactory disk = checkDos (appleDisk256); if (disk == null) disk = checkProdos (new AppleDisk (wozFile, 35, 8)); + if (disk == null) + disk = checkPascalDisk (new AppleDisk (wozFile, 35, 8)); if (disk == null) disk = new DataDisk (appleDisk256); } @@ -409,8 +411,7 @@ public class DiskFactory if (length != DISK_143K) // 16 sector floppy disk { - System.out.printf ("%s: invalid file length : %,d%n", file.getName (), - file.length ()); + System.out.printf ("%s: invalid file length : %,d%n", file.getName (), file.length ()); return null; } @@ -570,8 +571,8 @@ public class DiskFactory disk = new DataDisk (appleDisk256); if (debug) - System.out.println ( - "Factory creating disk : " + disk.getDisk ().getFile ().getAbsolutePath ()); + System.out + .println ("Factory creating disk : " + disk.getDisk ().getFile ().getAbsolutePath ()); if (disk != null && compressed) disk.setOriginalPath (originalPath); @@ -583,7 +584,7 @@ public class DiskFactory private static FormattedDisk check (FormattedDisk disk) // ---------------------------------------------------------------------------------// { - if (disk.getDisk ()instanceof AppleDisk appleDisk) + if (disk.getDisk () instanceof AppleDisk appleDisk) { if (nuFX != null) appleDisk.setNuFX (nuFX); diff --git a/src/com/bytezone/diskbrowser/pascal/CatalogEntry.java b/src/com/bytezone/diskbrowser/pascal/CatalogEntry.java index ba5db18..c908226 100644 --- a/src/com/bytezone/diskbrowser/pascal/CatalogEntry.java +++ b/src/com/bytezone/diskbrowser/pascal/CatalogEntry.java @@ -52,6 +52,7 @@ abstract class CatalogEntry implements AppleFileSource for (DiskAddress sector : blocks) if (sector.matches (da)) return true; + return false; } @@ -85,8 +86,8 @@ abstract class CatalogEntry implements AppleFileSource // ---------------------------------------------------------------------------------// { int size = lastBlock - firstBlock; - String fileTypeText = fileType < 0 || fileType >= parent.fileTypes.length ? "????" - : parent.fileTypes[fileType]; + String fileTypeText = + fileType < 0 || fileType >= parent.fileTypes.length ? "????" : parent.fileTypes[fileType]; return String.format ("%03d %s %-15s", size, fileTypeText, name); } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/pascal/PascalCodeObject.java b/src/com/bytezone/diskbrowser/pascal/PascalCodeObject.java index c8a84e7..49f3df8 100644 --- a/src/com/bytezone/diskbrowser/pascal/PascalCodeObject.java +++ b/src/com/bytezone/diskbrowser/pascal/PascalCodeObject.java @@ -66,6 +66,7 @@ class PascalCodeObject implements AppleFileSource for (DiskAddress sector : blocks) if (sector.matches (da)) return true; + return false; } diff --git a/src/com/bytezone/diskbrowser/pascal/PascalDisk.java b/src/com/bytezone/diskbrowser/pascal/PascalDisk.java index a6cb0ce..623e0c6 100755 --- a/src/com/bytezone/diskbrowser/pascal/PascalDisk.java +++ b/src/com/bytezone/diskbrowser/pascal/PascalDisk.java @@ -47,8 +47,8 @@ public class PascalDisk extends AbstractFormattedDisk SectorType fotoSector = new SectorType ("Foto", Color.gray); SectorType badSector = new SectorType ("Bad", Color.darkGray); - SectorType[] sectors = { catalogSector, badSector, codeSector, textSector, infoSector, - dataSector, grafSector, fotoSector }; + SectorType[] sectors = { catalogSector, badSector, codeSector, textSector, infoSector, dataSector, + grafSector, fotoSector }; // ---------------------------------------------------------------------------------// public PascalDisk (Disk disk) @@ -99,8 +99,7 @@ public class PascalDisk extends AbstractFormattedDisk freeBlocks.set (i, false); } - diskCatalogSector = - new PascalCatalogSector (disk, disk.readBlocks (sectors), sectors); + diskCatalogSector = new PascalCatalogSector (disk, disk.readBlocks (sectors), sectors); // read the catalog List addresses = new ArrayList<> (); @@ -143,14 +142,16 @@ public class PascalDisk extends AbstractFormattedDisk disk.setInterleave (1); // should only ever be Prodos if (checkFormat (disk, debug)) return true; + disk.setInterleave (0); // see SANE Disk 2.po if (checkFormat (disk, debug)) return true; + return false; } // ---------------------------------------------------------------------------------// - public static boolean checkFormat (AppleDisk disk, boolean debug) + private static boolean checkFormat (AppleDisk disk, boolean debug) // ---------------------------------------------------------------------------------// { byte[] buffer = disk.readBlock (2); @@ -277,16 +278,14 @@ public class PascalDisk extends AbstractFormattedDisk { String newLine = String.format ("%n"); String newLine2 = newLine + newLine; - String line = "---- --------------- ---- -------- ------- ---- ---- ----" - + newLine; - String date = - volumeEntry.date == null ? "--" : df.format (volumeEntry.date.getTime ()); + String line = + "---- --------------- ---- -------- ------- ---- ---- ----" + newLine; + String date = volumeEntry.date == null ? "--" : df.format (volumeEntry.date.getTime ()); StringBuilder text = new StringBuilder (); text.append ("File : " + getDisplayPath () + newLine2); text.append ("Volume : " + volumeEntry.name + newLine); text.append ("Date : " + date + newLine2); - text.append ( - "Blks Name Type Date Length Frst Last Blks\n"); + text.append ("Blks Name Type Date Length Frst Last Blks\n"); text.append (line); int usedBlocks = 6; @@ -297,15 +296,14 @@ public class PascalDisk extends AbstractFormattedDisk usedBlocks += size; date = ce.date == null ? "--" : df.format (ce.date.getTime ()); int bytes = (size - 1) * 512 + ce.bytesUsedInLastBlock; - String fileType = ce.fileType < 0 || ce.fileType >= fileTypes.length ? "????" - : fileTypes[ce.fileType]; - text.append (String.format ("%4d %-15s %s %8s %,8d $%03X $%03X $%03X%n", - size, ce.name, fileType, date, bytes, ce.firstBlock, ce.lastBlock, size)); + String fileType = + ce.fileType < 0 || ce.fileType >= fileTypes.length ? "????" : fileTypes[ce.fileType]; + text.append (String.format ("%4d %-15s %s %8s %,8d $%03X $%03X $%03X%n", size, + ce.name, fileType, date, bytes, ce.firstBlock, ce.lastBlock, size)); } text.append (line); - text.append ( - String.format ("Blocks free : %3d Blocks used : %3d Total blocks : %3d%n", - (volumeEntry.totalBlocks - usedBlocks), usedBlocks, volumeEntry.totalBlocks)); + text.append (String.format ("Blocks free : %3d Blocks used : %3d Total blocks : %3d%n", + (volumeEntry.totalBlocks - usedBlocks), usedBlocks, volumeEntry.totalBlocks)); return new DefaultAppleFileSource (volumeEntry.name, text.toString (), this); } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/wizardry/Monster.java b/src/com/bytezone/diskbrowser/wizardry/Monster.java index 9158efb..aa95199 100755 --- a/src/com/bytezone/diskbrowser/wizardry/Monster.java +++ b/src/com/bytezone/diskbrowser/wizardry/Monster.java @@ -14,6 +14,7 @@ class Monster extends AbstractFile public final String genericName; public final String realName; public final int monsterID; + List monsters; Reward goldReward; Reward chestReward; @@ -25,13 +26,14 @@ class Monster extends AbstractFile public final int partnerID; public final int partnerOdds; public final int armourClass; - public final int speed; + public final int recsn; public final int mageSpellLevel; public final int priestSpellLevel; int levelDrain; - int bonus1; - int bonus2; - int bonus3; + int healPts; + int breathe; + int unaffect; + int unique; int resistance; int abilities; public final Dice groupSize, hitPoints; @@ -56,9 +58,21 @@ class Monster extends AbstractFile 1475, 1540, 1720, 1900, 1240, 1220, 1020, 20435, 5100, 3515, // 60-69 2115, 2920, 2060, 2140, 1400, 1640, 1280, 4450, 42840, 3300, // 70-79 40875, 5000, 3300, 2395, 1935, 1600, 3330, 44090, 40840, 5200, // 80-89 - 4155, 3000, 9200, 3160, 7460, 7320, 15880, 1600, 2200, 1000, 1900 // 90-100 + 4155, 3000, 9200, 3160, 7460, 7320, 15880, 1600, 2200, 1000, // 90-99 + 1900 // 100 }; + int expHitPoints; + int expMage; + int expPriest; + int expDrain; + int expHeal; + int expAc; + int expDamage; + int expUnaffect; + int expFlags1; + int expFlags2; + // ---------------------------------------------------------------------------------// Monster (String name, byte[] buffer, List rewards, List monsters) // ---------------------------------------------------------------------------------// @@ -69,36 +83,41 @@ class Monster extends AbstractFile genericName = HexFormatter.getPascalString (buffer, 0); this.monsterID = counter++; this.monsters = monsters; + goldReward = rewards.get (buffer[136]); chestReward = rewards.get (buffer[138]); goldReward.addMonster (this, 0); chestReward.addMonster (this, 1); imageID = buffer[64]; - type = buffer[78]; - armourClass = buffer[80]; - speed = buffer[82]; - levelDrain = buffer[132]; - bonus1 = buffer[134]; - rewardTable1 = buffer[136]; - rewardTable2 = buffer[138]; - partnerID = buffer[140]; - partnerOdds = buffer[142]; - mageSpellLevel = buffer[144]; - priestSpellLevel = buffer[146]; - bonus2 = buffer[150]; - bonus3 = buffer[152]; - resistance = buffer[154]; - abilities = buffer[156]; groupSize = new Dice (buffer, 66); hitPoints = new Dice (buffer, 72); + type = buffer[78]; + armourClass = buffer[80]; + recsn = buffer[82]; // number of dice for (int i = 0, ptr = 84; i < 8; i++, ptr += 6) { if (buffer[ptr] == 0) break; damage.add (new Dice (buffer, ptr)); } + + levelDrain = buffer[132]; + healPts = buffer[134]; + rewardTable1 = buffer[136]; + rewardTable2 = buffer[138]; + partnerID = buffer[140]; + partnerOdds = buffer[142]; + mageSpellLevel = buffer[144]; + priestSpellLevel = buffer[146]; + + unique = buffer[148]; + breathe = buffer[150]; + unaffect = buffer[152]; + + resistance = buffer[154]; // bit flags + abilities = buffer[156]; // bit flags } // ---------------------------------------------------------------------------------// @@ -109,17 +128,30 @@ class Monster extends AbstractFile StringBuilder text = new StringBuilder (); // these values definitely affect the damage a monster does (when breathing?) - int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20; - int exp3 = weight2[speed]; // 1-6 - int exp4 = (10 - armourClass) * 40; - int exp5 = getBonus (35, mageSpellLevel); - int exp6 = getBonus (35, priestSpellLevel); - int exp10 = getBonus (200, levelDrain); - int exp8 = getBonus (90, bonus1); - int exp7 = weight1[bonus3 / 10] * 80; - int exp11 = bonus2 > 0 ? exp2 + 20 : 0; - int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E)); - int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F)); + // int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20; + // int exp2 = hitPoints.qty * hitPoints.sides; + // exp2 *= breathe == 0 ? 20 : 40; + + // int exp3 = weight2[recsn]; // 1-6 + // int exp3 = 0; + // if (recsn > 1) + // exp3 = recsn * 30; + + // int exp4 = (11 - armourClass) * 40; + + // int exp5 = getBonus (35, mageSpellLevel); // correct + // int exp6 = getBonus (35, priestSpellLevel); // correct + // int exp10 = getBonus (200, levelDrain); // correct + // int exp8 = getBonus (90, healPts); // correct + + // int exp7 = weight1[unaffect / 10] * 80; + // int exp7 = unaffect > 0 ? (unaffect / 10 + 1) * 40 : 0; + + // int exp11 = breathe > 0 ? exp2 + 20 : 0; + // int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E)); + // int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F)); + + int totalExperience = setExperience (); text.append ("ID .............. " + monsterID); text.append ("\nMonster name .... " + realName); @@ -129,24 +161,25 @@ class Monster extends AbstractFile text.append ("\nGroup size ...... " + groupSize); text.append ("\nHit points ...... " + hitPoints); if (debug) - text.append (" " + exp2); + text.append (" " + expHitPoints); - text.append ("\n\nMonster class ... " + type + " " + monsterClass[type]); + text.append ("\n\nMonster class ... " + type + " " + monsterClass[type]); text.append ("\nArmour class .... " + armourClass); if (debug) - text.append (" " + exp4); - text.append ("\nSpeed ........... " + speed); - if (debug) - text.append (" " + exp3); + text.append (" " + expAc); - text.append ("\n\nDamage .......... " + getDamage ()); + text.append ("\n\n# damage ........ " + recsn); + if (debug) + text.append (" " + expDamage); + + text.append ("\nDamage .......... " + getDamage ()); text.append ("\n\nLevel drain ..... " + levelDrain); if (debug) - text.append (" " + exp10); - text.append ("\nExtra hit pts? .. " + bonus1); + text.append (" " + expDrain); + text.append ("\nHeal pts? ....... " + healPts); if (debug) - text.append (" " + exp8); + text.append (" " + expHeal); text.append ("\n\nPartner ID ...... " + partnerID); if (partnerOdds > 0) @@ -155,27 +188,28 @@ class Monster extends AbstractFile text.append ("\n\nMage level ...... " + mageSpellLevel); if (debug) - text.append (" " + exp5); + text.append (" " + expMage); text.append ("\nPriest level .... " + priestSpellLevel); if (debug) - text.append (" " + exp6); + text.append (" " + expPriest); - text.append ("\n\nExperience bonus " + bonus2); + text.append ("\n\nUnique .......... " + unique); + text.append ("\nBreathe ......... " + breathe); + // if (debug) + // text.append (" " + expBreathe); + text.append ("\nUnaffect ........ " + unaffect); if (debug) - text.append (" " + exp11); - text.append ("\nExperience bonus " + bonus3); - if (debug) - text.append (" " + exp7); + text.append (" " + expUnaffect); text.append ("\n\nResistance ...... " + String.format ("%02X", resistance)); if (debug) - text.append (" " + exp12); + text.append (" " + expFlags1); text.append ("\nAbilities ....... " + String.format ("%02X", abilities)); if (debug) - text.append (" " + exp9); + text.append (" " + expFlags2); - text.append ("\n\nExperience ...... " - + (exp2 + exp3 + exp4 + exp5 + exp6 + exp7 + exp8 + exp9 + exp10 + exp11 + exp12)); + text.append ( + String.format ("%n%nExperience ...... %,7d %,7d", totalExperience, experience[monsterID])); text.append ("\n\n===== Gold reward ======"); // text.append ("\nTable ........... " + rewardTable1); @@ -191,21 +225,71 @@ class Monster extends AbstractFile } // ---------------------------------------------------------------------------------// - public int getExperience () + private int setExperience2 () + // ---------------------------------------------------------------------------------// + { + expHitPoints = hitPoints.qty * hitPoints.sides * breathe == 0 ? 20 : 40; + + expMage = 35 * mageSpellLevel; + expPriest = 35 * priestSpellLevel; + expDrain = 200 * levelDrain; + expHeal = 90 * healPts; + + expAc = 40 * (11 - armourClass); + + expDamage = recsn <= 1 ? 0 : 30 * recsn; + expUnaffect = unaffect == 0 ? 0 : 40 * (unaffect / 10 + 1); + expFlags1 = 35 * Integer.bitCount (resistance & 0x7E); + expFlags2 = 40 * Integer.bitCount (abilities & 0x7F); + + return expHitPoints + expMage + expPriest + expDrain + expHeal + expAc + expDamage + expUnaffect + + expFlags1 + expFlags2; + } + + // ---------------------------------------------------------------------------------// + private int setExperience () + // ---------------------------------------------------------------------------------// + { + expHitPoints = hitPoints.qty * hitPoints.sides * breathe == 0 ? 20 : 40; + + expMage = getBonus (35, mageSpellLevel); + expPriest = getBonus (35, priestSpellLevel); + expDrain = getBonus (200, levelDrain); + expHeal = getBonus (90, healPts); + + expAc = 40 * (11 - armourClass); + + expDamage = recsn <= 1 ? 0 : getBonus (30, recsn); + expUnaffect = unaffect == 0 ? 0 : getBonus (40, (unaffect / 10 + 1)); + expFlags1 = getBonus (35, Integer.bitCount (resistance & 0x7E)); + expFlags2 = getBonus (40, Integer.bitCount (abilities & 0x7F)); + + return expHitPoints + expMage + expPriest + expDrain + expHeal + expAc + expDamage + expUnaffect + + expFlags1 + expFlags2; + } + + // ---------------------------------------------------------------------------------// + private int getExperienceOld () // ---------------------------------------------------------------------------------// { // these values definitely affect the damage a monster does (when breathing?) - int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20; - int exp3 = weight2[speed]; - int exp4 = (10 - armourClass) * 40; + // int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20; + int exp2 = hitPoints.qty * hitPoints.sides; + exp2 *= breathe == 0 ? 20 : 40; + + int exp3 = weight2[recsn]; + int exp4 = (11 - armourClass) * 40; + int exp5 = getBonus (35, mageSpellLevel); int exp6 = getBonus (35, priestSpellLevel); int exp10 = getBonus (200, levelDrain); - int exp8 = getBonus (90, bonus1); - int exp7 = weight1[bonus3 / 10] * 80; - int exp11 = bonus2 > 0 ? exp2 + 20 : 0; + int exp8 = getBonus (90, healPts); + + int exp7 = weight1[unaffect / 10] * 80; + int exp11 = breathe > 0 ? exp2 + 20 : 0; int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E)); int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F)); + return exp2 + exp3 + exp4 + exp5 + exp6 + exp7 + exp8 + exp9 + exp10 + exp11 + exp12; } @@ -243,10 +327,13 @@ class Monster extends AbstractFile // ---------------------------------------------------------------------------------// { StringBuilder text = new StringBuilder (); + for (Dice d : damage) text.append (d + ", "); + text.deleteCharAt (text.length () - 1); text.deleteCharAt (text.length () - 1); + return text.toString (); } @@ -263,7 +350,7 @@ class Monster extends AbstractFile line.append (String.format ("%02X ", buffer[i])); if (block == 3) { - int exp = getExperience (); + int exp = setExperience (); line.append (String.format (" %,6d", exp)); if (exp != experience[monsterID]) line.append (String.format (" %,6d", experience[monsterID])); diff --git a/src/com/bytezone/diskbrowser/wizardry/Reward.java b/src/com/bytezone/diskbrowser/wizardry/Reward.java index f4c57ca..45c0da2 100755 --- a/src/com/bytezone/diskbrowser/wizardry/Reward.java +++ b/src/com/bytezone/diskbrowser/wizardry/Reward.java @@ -11,8 +11,10 @@ class Reward extends AbstractFile { static String[] types = { "gold", "item" }; static final int SEGMENT_LENGTH = 18; + int id; int totalElements; + List elements; List items; List goldMonsters = new ArrayList<> (); @@ -23,8 +25,10 @@ class Reward extends AbstractFile // ---------------------------------------------------------------------------------// { super (name, buffer); + this.id = id; this.items = items; + totalElements = buffer[4]; elements = new ArrayList<> (totalElements); @@ -130,11 +134,13 @@ class Reward extends AbstractFile case 0: text.append ("Gold ............ " + buffer[10] + "d" + buffer[12] + "\n"); break; + case 1: int lo = buffer[10] & 0xFF; int qty = buffer[16] & 0xFF; boolean title = true; String[] lineItem = new String[4]; + for (int i = lo, max = lo + qty; i <= max; i += lineItem.length) { String lineTitle = title ? "Items ..........." : ""; @@ -145,6 +151,7 @@ class Reward extends AbstractFile lineItem[1], lineItem[2], lineItem[3])); } break; + default: System.out.println ("Unknown reward type " + type); } diff --git a/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java b/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java index b74be31..0191461 100755 --- a/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java +++ b/src/com/bytezone/diskbrowser/wizardry/WizardryScenarioDisk.java @@ -277,9 +277,10 @@ public class WizardryScenarioDisk extends PascalDisk { int nameLength = buffer[ptr] & 0xFF; if (nameLength == 0xC3) - // || buffer[ptr + 40] == 0x07) 7 = LOST continue; String name = HexFormatter.getString (buffer, ptr + 1, nameLength); + if ("UNSET".equals (name) && buffer[ptr + 40] == 0x07) // 7 = LOST + continue; byte[] data2 = new byte[recLen]; System.arraycopy (buffer, ptr, data2, 0, recLen);