Created
April 23, 2011 13:28
-
-
Save kovrov/938607 to your computer and use it in GitHub Desktop.
fb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| DATA |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import resource; | |
| import std.stdio; | |
| import std.stream; | |
| import std.conv; | |
| enum Flag { End = 1 << 7 } | |
| class Cutscene | |
| { | |
| ushort _id; | |
| resource.CMD res_cmd; | |
| resource.POL res_pol; | |
| std.stream.Stream cmdStream; | |
| ubyte frameDelay; | |
| ubyte _clearScreen; | |
| this(ushort id) | |
| { | |
| _id = id; | |
| } | |
| void play() | |
| { | |
| auto cutName = _offsetsTable[_id][0]; | |
| this.load(cutName); | |
| auto cutOff = _offsetsTable[_id][1]; | |
| this.mainLoop(cutOff); | |
| } | |
| void load(ushort cutName) | |
| { | |
| assert (cutName != 0xFFFF); | |
| auto name = _namesTable[cutName & 0b11111111]; | |
| this.res_cmd = new resource.CMD("DATA/"~name~".cmd"); | |
| this.res_pol = new resource.POL("DATA/"~name~".pol"); | |
| } | |
| void mainLoop(ushort offset) | |
| { | |
| this.cmdStream = cast(std.stream.Stream)this.res_cmd; | |
| assert (this.cmdStream !is null); | |
| if (offset != 0) | |
| { | |
| this.cmdStream.seekSet((offset + 1) * 2); | |
| this.cmdStream.read(offset); | |
| this.cmdStream.seekSet(0); | |
| } | |
| ushort startOffset; | |
| this.cmdStream.read(startOffset); | |
| startOffset = cast(ushort)((startOffset + 1) * 2); | |
| this.cmdStream.seekSet(startOffset + offset); | |
| writefln("startOffset = %d; offset = %d; cmd = %s;", startOffset, offset, this.cmdStream.position()); | |
| for (ubyte op = 7<<2; !(op & Flag.End); this.cmdStream.read(op)) | |
| { | |
| writefln("play() opcode = 0x%X (%d)", op, (op >> 2)); | |
| _opcodeTable[op >> 2](this); | |
| } | |
| } | |
| static | |
| { | |
| void op_markCurPos(ref Cutscene ctx) | |
| { | |
| writeln("op_markCurPos"); | |
| } | |
| void op_refreshScreen(ref Cutscene ctx) | |
| { | |
| writeln("op_refreshScreen"); | |
| ctx.cmdStream.read(ctx._clearScreen); | |
| } | |
| void op_waitForSync(ref Cutscene ctx) | |
| { | |
| writeln("op_waitForSync"); | |
| ctx.cmdStream.read(ctx.frameDelay); ctx.frameDelay *= 4; | |
| } | |
| void op_drawShape(ref Cutscene ctx) | |
| { | |
| writeln("op_drawShape"); | |
| ushort shapeOffset; | |
| ctx.cmdStream.read(shapeOffset); | |
| short x = 0, y = 0; | |
| if (shapeOffset & (1 << 15)) | |
| { | |
| ctx.cmdStream.read(x); | |
| ctx.cmdStream.read(y); | |
| } | |
| foreach (primitive; ctx.res_pol.scenes[shapeOffset & 0b_00000111_11111111]) | |
| { | |
| switch (primitive.type) | |
| { | |
| case primitive.Type.Polygon: | |
| writefln("Polygon %s", to!string(primitive.polygon)); | |
| break; | |
| case primitive.Type.Point: | |
| writefln("Point %s", to!string(primitive.point)); | |
| break; | |
| case primitive.Type.Ellipse: | |
| writefln("Ellipse %s", to!string(primitive.ellipse)); | |
| break; | |
| } | |
| } | |
| } | |
| void op_setPalette(ref Cutscene ctx) | |
| { | |
| writeln("op_setPalette"); | |
| ubyte num, palNum; | |
| ctx.cmdStream.read(num); | |
| ctx.cmdStream.read(palNum); | |
| } | |
| void op_drawStringAtBottom(ref Cutscene ctx) | |
| { | |
| writeln("op_drawStringAtBottom"); | |
| ushort strId; | |
| ctx.cmdStream.read(strId); | |
| } | |
| void op_nop(ref Cutscene ctx) | |
| { | |
| writeln("op_nop"); | |
| } | |
| void op_skip3(ref Cutscene ctx) | |
| { | |
| writeln("op_skip3"); | |
| } | |
| void op_refreshAll(ref Cutscene ctx) | |
| { | |
| writeln("op_refreshAll"); | |
| } | |
| void op_drawShapeScale(ref Cutscene ctx) | |
| { | |
| writeln("op_drawShapeScale"); | |
| short x = 0, y = 0; | |
| ushort shapeOffset; | |
| ctx.cmdStream.read(shapeOffset); | |
| if (shapeOffset & (1 << 15)) | |
| { | |
| ctx.cmdStream.read(x); | |
| ctx.cmdStream.read(y); | |
| } | |
| ushort zoom = 512; | |
| if (shapeOffset & (1 << 14)) | |
| { | |
| ctx.cmdStream.read(zoom); | |
| zoom += 512; | |
| } | |
| ubyte _shape_ix, _shape_iy; | |
| ctx.cmdStream.read(_shape_ix); | |
| ctx.cmdStream.read(_shape_iy); | |
| ushort r1, r2 = 180, r3 = 90; | |
| ctx.cmdStream.read(r1); | |
| if (shapeOffset & (1 << 13)) | |
| { | |
| ctx.cmdStream.read(r2); | |
| } | |
| if (shapeOffset & (1 << 12)) | |
| { | |
| ctx.cmdStream.read(r3); | |
| } | |
| } | |
| void op_drawShapeScaleRotate(ref Cutscene ctx) | |
| { | |
| writeln("op_drawShapeScaleRotate"); | |
| ushort shapeOffset; | |
| ctx.cmdStream.read(shapeOffset); | |
| short x = 0, y = 0; | |
| if (shapeOffset & (1 << 15)) | |
| { | |
| ctx.cmdStream.read(x); | |
| ctx.cmdStream.read(y); | |
| } | |
| ushort zoom = 512; | |
| if (shapeOffset & (1 << 14)) | |
| { | |
| ctx.cmdStream.read(zoom); | |
| zoom += 512; | |
| } | |
| ubyte _shape_ix, _shape_iy; | |
| ctx.cmdStream.read(_shape_ix); | |
| ctx.cmdStream.read(_shape_iy); | |
| ushort r1, r2 = 180, r3 = 90; | |
| ctx.cmdStream.read(r1); | |
| if (shapeOffset & (1 << 13)) | |
| { | |
| ctx.cmdStream.read(r2); | |
| } | |
| if (shapeOffset & (1 << 12)) | |
| { | |
| ctx.cmdStream.read(r3); | |
| } | |
| } | |
| void op_drawCreditsText(ref Cutscene ctx) | |
| { | |
| writeln("op_drawCreditsText"); | |
| } | |
| void op_drawStringAtPos(ref Cutscene ctx) | |
| { | |
| writeln("op_drawStringAtPos"); | |
| ushort strId; | |
| ctx.cmdStream.read(strId); | |
| if (strId != 0xFFFF) | |
| { | |
| short x,y; | |
| ctx.cmdStream.read(x); x *= 8; | |
| ctx.cmdStream.read(y); y *= 8; | |
| } | |
| } | |
| void op_handleKeys(ref Cutscene ctx) | |
| { | |
| writeln("op_handleKeys"); | |
| assert (false); | |
| } | |
| auto _opcodeTable = [ | |
| &op_markCurPos, | |
| &op_refreshScreen, | |
| &op_waitForSync, | |
| &op_drawShape, | |
| &op_setPalette, | |
| &op_markCurPos, | |
| &op_drawStringAtBottom, | |
| &op_nop, | |
| &op_skip3, | |
| &op_refreshAll, | |
| &op_drawShapeScale, | |
| &op_drawShapeScaleRotate, | |
| &op_drawCreditsText, | |
| &op_drawStringAtPos, | |
| &op_handleKeys]; | |
| immutable ushort[2][] _offsetsTable = [ | |
| [0x0000, 0x0000], [0x0001, 0x0003], [0x0001, 0x0004], [0xFFFF, 0x0000], | |
| [0x0001, 0x0002], [0x0003, 0x0000], [0x0004, 0x0000], [0xFFFF, 0x0100], | |
| [0xFFFF, 0x0000], [0x0006, 0x0000], [0x0001, 0x0001], [0xFFFF, 0x0000], | |
| [0xFFFF, 0x0200], [0x8007, 0x0000], [0x0003, 0x0001], [0x0001, 0x000B], | |
| [0x0001, 0x0005], [0x0009, 0x0000], [0x0001, 0x0006], [0xFFFF, 0x0000], | |
| [0x000B, 0x0000], [0x0001, 0x000A], [0xFFFF, 0x0001], [0xFFFF, 0x0002], | |
| [0xFFFF, 0x0000], [0x000D, 0x0004], [0x000D, 0x0000], [0x000D, 0x0001], | |
| [0x000D, 0x0002], [0x000D, 0x0003], [0xFFFF, 0x0000], [0xFFFF, 0x0001], | |
| [0x0001, 0x000C], [0x0001, 0x000D], [0x0001, 0x000E], [0x0001, 0x000F], | |
| [0x0001, 0x0010], [0x000F, 0x0000], [0x000F, 0x0001], [0x000F, 0x0001], | |
| [0x000F, 0x0003], [0x000F, 0x0002], [0x000F, 0x0004], [0x0001, 0x0008], | |
| [0x0001, 0x0007], [0x000F, 0x0005], [0xFFFF, 0x0000], [0x0004, 0x0001], | |
| [0x0011, 0x0000], [0x0001, 0x0009], [0x0012, 0x0000], [0xFFFF, 0x0000], | |
| [0x0014, 0x0000], [0x0015, 0x0000], [0x0016, 0x0000], [0x0016, 0x0001], | |
| [0xFFFF, 0x0012], [0x0017, 0x0000], [0x0001, 0x0011], [0x0018, 0x0000], | |
| [0x0001, 0x0013], [0x0019, 0x0000], [0x001A, 0x0000], [0x0019, 0x0001], | |
| [0x001B, 0x0000], [0x001C, 0x0000], [0x000F, 0x0006], [0x000F, 0x0006], | |
| [0x000F, 0x0007], [0x000F, 0x0008], [0x000F, 0x0009], [0x000F, 0x000A], | |
| [0x001D, 0x0000], [0x001B, 0x0001], [0x001E, 0x0000], [0xFFFF, 0x0000]]; | |
| immutable string[] _namesTable = [ | |
| "DEBUT", | |
| "OBJET", | |
| "CARTE", | |
| "GEN", | |
| "CHUTE", | |
| "CODE", | |
| "DESINTEG", | |
| "intro1",//"INTRO1", | |
| "STREM", | |
| "HOLOSEQ", | |
| "CARTEID", | |
| "PONT", | |
| "ASC", | |
| "MAP", | |
| "METRO", | |
| "MISSIONS", | |
| "GENMIS", | |
| "MEMO", | |
| "TAXI", | |
| "ACCROCHE", | |
| "VOYAGE", | |
| "TELEPORT", | |
| "LIFT", | |
| "ESPIONS", | |
| "LOG", | |
| "FIN", | |
| "GENEXP", | |
| "LOGOS", | |
| "OVER", | |
| "SCORE", | |
| "INTRO2"]; | |
| } | |
| } | |
| void main() | |
| { | |
| auto cut = new Cutscene(13); | |
| cut.play(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import std.stdio; | |
| import std.system : Endian; | |
| import std.stream : MemoryStream, EndianStream, Stream; | |
| class CMD | |
| { | |
| ubyte[] _data; | |
| this(string path) | |
| { | |
| auto f = std.stdio.File(path, "rb"); | |
| _data.length = cast(size_t)f.size(); | |
| _data = f.rawRead(_data); | |
| } | |
| Stream opCast(T)() if (is(Stream == T)) | |
| { | |
| return new EndianStream(new MemoryStream(_data), Endian.BigEndian); | |
| } | |
| } | |
| class POL | |
| { | |
| align (1) struct Point { short x; short y; } | |
| align (1) struct Ellipse { Point center; ushort rx; ushort ry; } | |
| struct Primitive | |
| { | |
| enum Type { Ellipse, Point, Polygon } | |
| Type type; | |
| ubyte color; | |
| bool hasAlphaColor; | |
| short x, y; | |
| union | |
| { | |
| Ellipse ellipse; | |
| Point point; | |
| Point[] polygon; | |
| } | |
| } | |
| Primitive[][] scenes; | |
| this(string path) | |
| { | |
| scope file = new std.stream.BufferedFile(path); | |
| scope stream = new EndianStream(file, Endian.BigEndian); | |
| ushort shape_offset_index, unknown_index, shape_data_index, vertices_offset_index, vertices_data_index; | |
| stream.seekSet(2); stream.read(shape_offset_index); | |
| stream.seekSet(6); stream.read(unknown_index); | |
| stream.seekSet(14); stream.read(shape_data_index); | |
| stream.seekSet(10); stream.read(vertices_offset_index); | |
| stream.seekSet(18); stream.read(vertices_data_index); | |
| scope ushort[] shape_offset_table; | |
| shape_offset_table.length = (unknown_index - shape_offset_index) / 2; | |
| stream.seekSet(shape_offset_index); | |
| foreach (ref shape_offset; shape_offset_table) | |
| stream.read(shape_offset); | |
| scope ushort[] vertices_offset_table; | |
| vertices_offset_table.length = (vertices_data_index - vertices_offset_index) / 2; | |
| stream.seekSet(vertices_offset_index); | |
| foreach (ref vertices_offset; vertices_offset_table) | |
| stream.read(vertices_offset); | |
| foreach (i, shape_offset; shape_offset_table) | |
| { | |
| stream.seekSet(shape_data_index + shape_offset); | |
| ushort primitive_count; stream.read(primitive_count); | |
| scenes.length += 1; | |
| scenes[$-1].length = primitive_count; | |
| foreach (ref primitive; scenes[$-1]) | |
| { | |
| ushort primitive_header; stream.read(primitive_header); | |
| if (primitive_header & (1 << 15)) | |
| { | |
| stream.read(primitive.x); | |
| stream.read(primitive.y); | |
| } | |
| stream.read(primitive.color); | |
| primitive.hasAlphaColor = (primitive_header & (1 << 14)) != 0; | |
| auto shape_data_position = stream.position(); | |
| auto vertices_offset = vertices_offset_table[primitive_header & 0b_00111111_11111111]; | |
| stream.seekSet(vertices_data_index + vertices_offset); | |
| ubyte numVertices; stream.read(numVertices); | |
| if (numVertices & (1 << 7)) | |
| { | |
| primitive.type = Primitive.Type.Ellipse; | |
| stream.read(primitive.ellipse.center.x); | |
| stream.read(primitive.ellipse.center.y); | |
| stream.read(primitive.ellipse.rx); | |
| stream.read(primitive.ellipse.ry); | |
| } | |
| else if (numVertices == 0) | |
| { | |
| primitive.type = Primitive.Type.Point; | |
| stream.read(primitive.point.x); | |
| stream.read(primitive.point.y); | |
| } | |
| else | |
| { | |
| primitive.type = Primitive.Type.Polygon; | |
| primitive.polygon = []; // union initialization is unreliable? | |
| short ix, iy; | |
| stream.read(ix); | |
| stream.read(iy); | |
| primitive.polygon.length += 1; | |
| primitive.polygon[$-1].x = ix; | |
| primitive.polygon[$-1].y = iy; | |
| byte[] vertices; | |
| vertices.length = numVertices * 2; | |
| stream.readExact(vertices.ptr, vertices.length); | |
| auto vertices_ptr = vertices.ptr; | |
| foreach (n; 0 .. numVertices) | |
| { | |
| short x = *vertices_ptr++; | |
| short y = *vertices_ptr++; | |
| if (y == 0 && n != (numVertices - 1) && vertices_ptr[1] == 0) | |
| { | |
| ix += x; | |
| } | |
| else | |
| { | |
| ix += x; | |
| iy += y; | |
| primitive.polygon.length += 1; | |
| primitive.polygon[$-1].x = ix; | |
| primitive.polygon[$-1].y = iy; | |
| } | |
| } | |
| } | |
| stream.seekSet(shape_data_position); | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment