The main problem I was running into with ArrayBuffers is that there's no built-in JS facility for decoding strings from them. DataView gives you plenty of stuff for decoding integers and floats, but nothing for strings, so you end up having to construct them character-by-character (possibly including UTF-8 decoding logic) by reading single bytes at a time. I don't trust Duktape's performance quite enough to do this in script--plus you run into performance issues with string interning when building a string piecemeal like that--so it was easier just to put the string I/O into the engine.
Reading the Turbo code, I saw you had the same problem, and ended up falling back on CreateStringFromByteArray(). Since I consider the ByteArray stuff deprecated at this point, I didn't want to do that.
By the way, here's a schema to read an RMP file through the layer data. Alas, I don't think I can represent the entire RMP format using a single read call unless I make the schema system Turing complete--persons and triggers have a completely different set of fields, but are both interleaved within the "entities" section.
var segmentSchema =
[
{ id: 'x1', type: 'uintLE', size: 4 },
{ id: 'y1', type: 'uintLE', size: 4 },
{ id: 'x2', type: 'uintLE', size: 4 },
{ id: 'y2', type: 'uintLE', size: 4 },
];
var layerSchema =
[
{ id: 'width', type: 'uintLE', size: 2 },
{ id: 'height', type: 'uintLE', size: 2 },
{ id: 'flags', type: 'uintLE', size: 2 },
{ id: 'parallaxX', type: 'floatLE' },
{ id: 'parallaxY', type: 'floatLE' },
{ id: 'scrollX', type: 'floatLE' },
{ id: 'scrollY', type: 'floatLE' },
{ id: 'numSegments', type: 'uintLE', size: 4 },
{ id: 'reflective', type: 'bool' },
{ type: 'reserved', size: 3 },
{ id: 'name', type: 'pstringLE', size: 2 },
{ id: 'tilemap', type: 'array', count: '@height', subtype: { type: 'array', count: '@width', subtype: { type: 'uintLE', size: 2 } } },
{ id: 'segments', type: 'array', count: '@numSegments', subtype: { type: 'object', schema: segmentSchema } },
];
var mapSchema =
[
{ id: 'signature', type: 'fstring', size: 4, regex: "\\.rmp" },
{ id: 'version', type: 'uintLE', size: 2 },
{ id: 'type', type: 'uintLE', size: 1 },
{ id: 'numLayers', type: 'uintLE', size: 1 },
{ type: 'reserved', size: 1 }, // reserved
{ id: 'numEntities', type: 'uintLE', size: 2 },
{ id: 'startX', type: 'uintLE', size: 2 },
{ id: 'startY', type: 'uintLE', size: 2 },
{ id: 'startLayer', type: 'uintLE', size: 1 },
{ id: 'startDir', type: 'uintLE', size: 1 },
{ id: 'numStrings', type: 'uintLE', size: 2 },
{ id: 'numZones', type: 'uintLE', size: 2 },
{ id: 'repeating', type: 'bool' },
{ type: 'reserved', size: 234 }, // reserved
{ id: 'strings', type: 'array', count: '@numStrings', subtype: { type: 'pstringLE', size: 2 } },
{ id: 'layers', type: 'array', count: '@numLayers', subtype: { type: 'object', schema: layerSchema } },
];