====== 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));
}