AeThex-OS/package_bootanim.cjs
MrPiglr b3c308b2c8 Add functional marketplace modules, bottom nav bar, root terminal, arcade games
- ModuleManager: Central tracking for installed marketplace modules
- DataAnalyzerWidget: Real-time CPU/RAM/Battery/Storage widget (unlocked by Data Analyzer module)
- BottomNavBar: Navigation bar for Projects/Chat/Marketplace/Settings
- RootShell: Real root command execution utility
- TerminalActivity: Full root shell with neofetch, sysinfo, real Linux commands
- Terminal Pro module: Adds aliases (ll, la, h), command history
- ArcadeActivity + SnakeGame: Pixel Arcade module unlocks retro games
- fade_in/fade_out animations for smooth transitions
2026-02-18 22:03:50 -07:00

143 lines
5.3 KiB
JavaScript

// Package boot animation as a zip with STORE (no compression) method
// Android bootanimation.zip MUST use store method, not deflate
const fs = require('fs');
const path = require('path');
const baseDir = 'C:\\Users\\PCOEM\\AeThexOS\\bootanimation';
const outFile = 'C:\\Users\\PCOEM\\AeThexOS\\bootanimation.zip';
// Collect all files to include
const files = [];
// desc.txt
files.push({ name: 'desc.txt', path: path.join(baseDir, 'desc.txt') });
// part0 PNGs
const part0 = fs.readdirSync(path.join(baseDir, 'part0')).sort();
for (const f of part0) {
files.push({ name: 'part0/' + f, path: path.join(baseDir, 'part0', f) });
}
// part1 PNGs
const part1 = fs.readdirSync(path.join(baseDir, 'part1')).sort();
for (const f of part1) {
files.push({ name: 'part1/' + f, path: path.join(baseDir, 'part1', f) });
}
// Build ZIP manually with STORE method (no compression)
const entries = [];
let offset = 0;
for (const file of files) {
const data = fs.readFileSync(file.path);
const nameBytes = Buffer.from(file.name, 'utf8');
// Local file header (30 bytes + name length)
const localHeader = Buffer.alloc(30 + nameBytes.length);
localHeader.writeUInt32LE(0x04034b50, 0); // Local file header signature
localHeader.writeUInt16LE(10, 4); // Version needed (1.0)
localHeader.writeUInt16LE(0, 6); // General purpose bit flag
localHeader.writeUInt16LE(0, 8); // Compression method: STORE
localHeader.writeUInt16LE(0, 10); // Last mod time
localHeader.writeUInt16LE(0, 12); // Last mod date
// CRC-32
const crc = crc32(data);
localHeader.writeUInt32LE(crc, 14);
localHeader.writeUInt32LE(data.length, 18); // Compressed size
localHeader.writeUInt32LE(data.length, 22); // Uncompressed size
localHeader.writeUInt16LE(nameBytes.length, 26); // File name length
localHeader.writeUInt16LE(0, 28); // Extra field length
nameBytes.copy(localHeader, 30);
entries.push({
localHeaderOffset: offset,
nameBytes,
data,
crc
});
offset += localHeader.length + data.length;
}
// Build the full ZIP
const centralDirStart = offset;
const centralHeaders = [];
for (const entry of entries) {
const ch = Buffer.alloc(46 + entry.nameBytes.length);
ch.writeUInt32LE(0x02014b50, 0); // Central directory header signature
ch.writeUInt16LE(10, 4); // Version made by
ch.writeUInt16LE(10, 6); // Version needed
ch.writeUInt16LE(0, 8); // Flags
ch.writeUInt16LE(0, 10); // Compression: STORE
ch.writeUInt16LE(0, 12); // Time
ch.writeUInt16LE(0, 14); // Date
ch.writeUInt32LE(entry.crc, 16); // CRC
ch.writeUInt32LE(entry.data.length, 20); // Compressed size
ch.writeUInt32LE(entry.data.length, 24); // Uncompressed size
ch.writeUInt16LE(entry.nameBytes.length, 28); // Name length
ch.writeUInt16LE(0, 30); // Extra length
ch.writeUInt16LE(0, 32); // Comment length
ch.writeUInt16LE(0, 34); // Disk number start
ch.writeUInt16LE(0, 36); // Internal file attributes
ch.writeUInt32LE(0, 38); // External file attributes
ch.writeUInt32LE(entry.localHeaderOffset, 42); // Relative offset of local header
entry.nameBytes.copy(ch, 46);
centralHeaders.push(ch);
offset += ch.length;
}
// End of central directory
const eocd = Buffer.alloc(22);
eocd.writeUInt32LE(0x06054b50, 0); // EOCD signature
eocd.writeUInt16LE(0, 4); // Disk number
eocd.writeUInt16LE(0, 6); // Disk with central dir
eocd.writeUInt16LE(entries.length, 8); // Entries on this disk
eocd.writeUInt16LE(entries.length, 10); // Total entries
const centralDirSize = offset - centralDirStart;
eocd.writeUInt32LE(centralDirSize, 12); // Central dir size
eocd.writeUInt32LE(centralDirStart, 16); // Central dir offset
eocd.writeUInt16LE(0, 20); // Comment length
// Write everything
const fd = fs.openSync(outFile, 'w');
for (let i = 0; i < entries.length; i++) {
const e = entries[i];
const localHeader = Buffer.alloc(30 + e.nameBytes.length);
localHeader.writeUInt32LE(0x04034b50, 0);
localHeader.writeUInt16LE(10, 4);
localHeader.writeUInt16LE(0, 6);
localHeader.writeUInt16LE(0, 8);
localHeader.writeUInt16LE(0, 10);
localHeader.writeUInt16LE(0, 12);
localHeader.writeUInt32LE(e.crc, 14);
localHeader.writeUInt32LE(e.data.length, 18);
localHeader.writeUInt32LE(e.data.length, 22);
localHeader.writeUInt16LE(e.nameBytes.length, 26);
localHeader.writeUInt16LE(0, 28);
e.nameBytes.copy(localHeader, 30);
fs.writeSync(fd, localHeader);
fs.writeSync(fd, e.data);
}
for (const ch of centralHeaders) {
fs.writeSync(fd, ch);
}
fs.writeSync(fd, eocd);
fs.closeSync(fd);
const stat = fs.statSync(outFile);
console.log(`bootanimation.zip created: ${stat.size} bytes (${files.length} files)`);
// CRC-32 implementation
function crc32(buf) {
let crc = 0xFFFFFFFF;
for (let i = 0; i < buf.length; i++) {
crc ^= buf[i];
for (let j = 0; j < 8; j++) {
crc = (crc >>> 1) ^ (crc & 1 ? 0xEDB88320 : 0);
}
}
return (crc ^ 0xFFFFFFFF) >>> 0;
}