mirror of
https://github.com/AeThex-Corporation/AeThex-OS.git
synced 2026-04-17 22:07:20 +00:00
- 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
143 lines
5.3 KiB
JavaScript
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;
|
|
}
|