parse more parts of blades scenario
This commit is contained in:
@@ -6,12 +6,13 @@ import haxe.io.Bytes;
|
||||
class ByteStream {
|
||||
var bytes = Bytes.alloc(0);
|
||||
var position = 0;
|
||||
|
||||
var file = "";
|
||||
function new () {}
|
||||
|
||||
public static function fromFile(file) {
|
||||
var s = new ByteStream();
|
||||
s.bytes = File.getBytes(file);
|
||||
s.file = file;
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -37,13 +38,38 @@ class ByteStream {
|
||||
}
|
||||
|
||||
// Read a C-style 0-terminated ascii string
|
||||
public function readCString():String {
|
||||
public function readCString(maxLength = 0):String {
|
||||
var string = "";
|
||||
while (true) {
|
||||
var pos = position;
|
||||
var _maxBytes = if (maxLength <= 0) bytes.length - position else maxLength; // TODO test this for off-by-one error
|
||||
for (idx in 0..._maxBytes) {
|
||||
var next = readByte();
|
||||
if (next == 0) break;
|
||||
if (next == 0) {
|
||||
if (maxLength > 0)
|
||||
paddingBytes(_maxBytes - idx);
|
||||
return string;
|
||||
}
|
||||
else string += String.fromCharCode(next);
|
||||
}
|
||||
return string;
|
||||
if (maxLength <= 0) {
|
||||
throw 'C String starting at byte $pos in $file ends in unexpected EOF';
|
||||
} else {
|
||||
throw 'C String starting at byte $pos in $file is longer than $maxLength bytes: $string';
|
||||
}
|
||||
}
|
||||
|
||||
public function skipZeros() {
|
||||
while (readByte() == 0) {}
|
||||
|
||||
position--;
|
||||
}
|
||||
|
||||
public function unknownBytes(num:Int) {
|
||||
trace('Warning: ignoring $num unknown bytes starting at $position in $file');
|
||||
paddingBytes(num);
|
||||
}
|
||||
|
||||
public function paddingBytes(num) {
|
||||
for (_ in 0...num) readByte();
|
||||
}
|
||||
}
|
||||
|
@@ -4,11 +4,18 @@ import kiss.ByteStream;
|
||||
|
||||
import data.blades.TileMap;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class Scenario {
|
||||
private var outdoorSections:TileArray<TileMap>;
|
||||
private var towns:Array<TileMap>;
|
||||
private var name = "";
|
||||
private var decription = "";
|
||||
public var outdoorSections:TileArray<TileMap>;
|
||||
public var towns:Array<TileMap>;
|
||||
public var name = "";
|
||||
public var description1 = "";
|
||||
public var description2 = "";
|
||||
public var credit1 = "";
|
||||
public var credit2 = "";
|
||||
|
||||
public var intro:Array<Array<String>>;
|
||||
|
||||
function new() {
|
||||
|
||||
@@ -28,6 +35,14 @@ class Scenario {
|
||||
var scen = fromBasFile("Blades of Avernum Scenarios/Valley of Dying Things/valleydy.bas");
|
||||
|
||||
assert(scen.name == "Valley of Dying Things", '${scen.name} is the wrong title');
|
||||
assert(scen.description1.startsWith("Everything in the valley is dying."), '${scen.description1} is the wrong description');
|
||||
assert(scen.description2 == 'Can you cure them?', '${scen.description2} is the wrong description');
|
||||
assert(scen.intro[0][0].startsWith("Adventurers, at last!"), 'problem with ${scen.intro[0][0]}');
|
||||
assert(scen.intro[0][0].endsWith("rewards to earn!"), 'problem with ${scen.intro[0][0]}');
|
||||
assert(scen.intro[0][1] == 'Soon you will be heroes, if you have anything to say about it.', 'problem with ${scen.intro[0][1]}');
|
||||
assert(scen.intro[0][5] == 'Apparently, you are to go to Skylark Vale and investigate a minor plague or disaster or something. They aren\'t specific.', 'problem with ${scen.intro[0][5]}');
|
||||
assert(scen.intro[1][2] == "You've just stayed the night in your room at the fort. You had a good night's sleep and a good meal. Now the sun is rising. Finally, it's time to go out and be heroes!", 'problem with ${scen.intro[1][2]}');
|
||||
assert(scen.intro[1][3] == "", 'problem with ${scen.intro[1][3]}');
|
||||
|
||||
trace('$passed assertions passed');
|
||||
if (failed.length > 0) {
|
||||
@@ -40,29 +55,45 @@ class Scenario {
|
||||
var scen = new Scenario();
|
||||
var stream = ByteStream.fromFile(file);
|
||||
|
||||
function unknownBytes(num:Int) {
|
||||
trace('Warning: ignoring $num unknown bytes');
|
||||
for (_ in 0...num) stream.readByte();
|
||||
}
|
||||
|
||||
function paddingBytes(num) {
|
||||
for (_ in 0...num) stream.readByte();
|
||||
}
|
||||
|
||||
// TODO
|
||||
unknownBytes(11);
|
||||
stream.unknownBytes(11);
|
||||
|
||||
var numTowns = stream.readUInt16();
|
||||
var outdoorWidth = stream.readUInt16();
|
||||
var outdoorHeight = stream.readUInt16();
|
||||
trace(outdoorWidth);
|
||||
trace(outdoorHeight);
|
||||
|
||||
// TODO
|
||||
unknownBytes(5);
|
||||
// TODO scenario title 49 bytes 0-terminated
|
||||
scen.name = stream.readCString();
|
||||
paddingBytes(49 - scen.name.length);
|
||||
stream.unknownBytes(5);
|
||||
// scenario title, 49 char max, 0-terminated
|
||||
scen.name = stream.readCString(49);
|
||||
|
||||
// in valleydy, it's 07 6C
|
||||
// in stealth, it's 07 6D
|
||||
stream.unknownBytes(2);
|
||||
|
||||
scen.description1 = stream.readCString();
|
||||
stream.skipZeros();
|
||||
scen.credit1 = stream.readCString();
|
||||
stream.skipZeros();
|
||||
// weirdly, this is the one that can be changed in the editor, and the only one to appear in "About this scenario"
|
||||
scen.credit2 = stream.readCString();
|
||||
stream.skipZeros();
|
||||
// Weirdly, this doesn't seem to appear anywhere, but in the case of valleydy, it would make a punchier description
|
||||
scen.description2 = stream.readCString();
|
||||
stream.skipZeros();
|
||||
|
||||
// TODO in valleydy and stealth, it's 02 26 02 27 FF FF
|
||||
stream.unknownBytes(6);
|
||||
|
||||
// Intro paragraphs are c-strings fitting in 16*16 bytes.
|
||||
// After the 0 terminator there are usually junk characters.
|
||||
// 3 pages of 6 paragraphs
|
||||
scen.intro = [for (page in 0...3) {
|
||||
[for (paragraph in 0...6)
|
||||
stream.readCString(16*16-1)];
|
||||
}];
|
||||
|
||||
// 1D30 08 is the first outdoor section
|
||||
|
||||
return scen;
|
||||
}
|
||||
|
Reference in New Issue
Block a user