import 'dart:typed_data'; import 'package:wolf_dart/classes/matrix.dart'; import 'package:wolf_dart/classes/sprite.dart'; class VswapParser { /// Extracts the 64x64 wall textures from VSWAP.WL1 static List> parseWalls(ByteData vswap) { // 1. Read Header int chunks = vswap.getUint16(0, Endian.little); int spriteStart = vswap.getUint16(2, Endian.little); // int soundStart = vswap.getUint16(4, Endian.little); // We don't need this yet // 2. Read Offsets (Where does each chunk start in the file?) List offsets = []; for (int i = 0; i < spriteStart; i++) { offsets.add(vswap.getUint32(6 + (i * 4), Endian.little)); } // 3. Extract the Wall Textures List textures = []; // Walls are chunks 0 through (spriteStart - 1) for (int i = 0; i < spriteStart; i++) { int offset = offsets[i]; if (offset == 0) continue; // Empty chunk // Walls are always exactly 64x64 pixels (4096 bytes) // Note: Wolf3D stores pixels in COLUMN-MAJOR order (Top to bottom, then left to right) Sprite texture = List.generate(64, (_) => List.filled(64, 0)); for (int x = 0; x < 64; x++) { for (int y = 0; y < 64; y++) { int byteIndex = offset + (x * 64) + y; texture[x][y] = vswap.getUint8(byteIndex); } } textures.add(texture); } return textures; } /// Extracts the compiled scaled sprites from VSWAP.WL1 static List> parseSprites(ByteData vswap) { int chunks = vswap.getUint16(0, Endian.little); int spriteStart = vswap.getUint16(2, Endian.little); int soundStart = vswap.getUint16(4, Endian.little); List offsets = []; for (int i = 0; i < chunks; i++) { offsets.add(vswap.getUint32(6 + (i * 4), Endian.little)); } List> sprites = []; // Sprites are located between the walls and the sounds for (int i = spriteStart; i < soundStart; i++) { int offset = offsets[i]; if (offset == 0) continue; // Some chunks are empty placeholders // Initialize the 64x64 grid with 255 (The Magenta Transparency Color!) Matrix sprite = List.generate(64, (_) => List.filled(64, 255)); int leftPix = vswap.getUint16(offset, Endian.little); int rightPix = vswap.getUint16(offset + 2, Endian.little); // Read the offsets for each vertical column of the sprite List colOffsets = []; for (int x = leftPix; x <= rightPix; x++) { colOffsets.add( vswap.getUint16(offset + 4 + ((x - leftPix) * 2), Endian.little), ); } for (int x = leftPix; x <= rightPix; x++) { int colOffset = colOffsets[x - leftPix]; if (colOffset == 0) continue; int cmdOffset = offset + colOffset; // Execute the column drawing commands while (true) { int endY = vswap.getUint16(cmdOffset, Endian.little); if (endY == 0) break; // 0 marks the end of the column endY ~/= 2; // Wolf3D stores Y coordinates multiplied by 2 int pixelOfs = vswap.getUint16(cmdOffset + 2, Endian.little); int startY = vswap.getUint16(cmdOffset + 4, Endian.little); startY ~/= 2; for (int y = startY; y < endY; y++) { // The Carmack 286 Hack: pixelOfs + y gives the exact byte address! sprite[x][y] = vswap.getUint8(offset + pixelOfs + y); } cmdOffset += 6; // Move to the next 6-byte instruction } } sprites.add(sprite); } return sprites; } }