====== Mozaïc ====== Some game distributed with lottery tickets from Loto-Québec Download and install instructions: [[https://www.youtube.com/watch?v=YygmFM3qP8w]] (also hacked to bypass ticket validity checks) ===== Install on Wine ===== This game makes heavy use of Indeo 5 and other DirectShow codecs so make sure to install it. Ideally, use a 32-bit prefix and pretend you're Windows XP. # mount the ISO sudo mount MOZAIC.iso /mnt/cdrom # create a new 32-bit prefix, and optionally pretend you're on Windows XP # it currently won't work in a 64-bit prefix like the one that is created by default export WINEARCH=win32 export WINEPREFIX=~/.wine32 winecfg # install the codecs winetricks -q allcodecs # install and run the game (also make sure $WINEPREFIX is set) wine /mnt/cdrom/Mozaic.exe The installation may fail because you have an ''ï'' in the install path, you may remove it and put a normal ''i'' instead. ===== PAK file format ===== Data is in little-endian. ^Nom^Type^Offset^Size^Notes^ |magic|string|0|4 bytes|"PACK"| |size|u32|4|4 bytes|Number of entries| |???| |8|32 bytes|Unknown| |filelist|File|40|size * (12 + name)| | ==== File ==== ^Nom^Type^Offset^Size^Notes^ |filesize|u32|0|4 bytes| | |offset|u32|4|4 bytes|Byte offset from the beginning of the file| |???|u32|8|4 bytes|Unknown| |name|Null-terminated string|12| |File path and name| ==== ImHex pattern ==== import std.string; struct File { u32 filesize; u32 offset; u32 unknown; std::string::NullString name; char data[filesize] @ offset; }; char magic[4] @ 0; u32 size @ 4; char unknown[32] @ 8; File filelist[size] @ 40; ===== Hacking =====
Node.js pak extractor const fs = require('node:fs'); const path = require('node:path'); if(process.argv.length < 3) { console.log("error: no input file"); process.exit(1); } var f = fs.readFileSync(process.argv[2]); var magic = f.toString('hex', 0, 4); if(magic != "5041434b") { console.log("error: invalid file"); process.exit(1); } var size = f.readUInt32LE(4); var offset = 40; for(var i = 0; i < size; i++) { var filesize = f.readUint32LE(offset); offset+=4; var fileoffset = f.readUint32LE(offset); offset+=4; var mystery = f.readUint32LE(offset); offset+=4; var next = f.indexOf(0, offset, 'ascii'); var name = f.toString('ascii', offset, next).replaceAll("\\", "/"); offset = next+1; console.log("%s; %s", name, mystery); fs.mkdirSync(path.dirname(name), { recursive: true }); var data = fs.createWriteStream(name, 'binary'); data.end(f.slice(fileoffset, fileoffset+filesize)); }