dzura/www/js/util.js
2024-08-11 21:10:05 -07:00

174 lines
4.3 KiB
JavaScript

const PACK = {
u8(value) {
return new Uint8Array([ value & 0xFF ]);
},
u16(value) {
return new Uint8Array([ (value >> 8) & 0xFF, value & 0xFF ]);
},
u32(value) {
return new Uint8Array([
(value >> 24) & 0xFF,
(value >> 16) & 0xFF,
(value >> 8) & 0xFF,
value & 0xFF
]);
},
};
const UNPACK = {
u8(data, index) {
let result = 0;
if(index + 1 <= data.length) {
result = data[index];
index += 1;
}
return { data: result, index: index };
},
u16(data, index) {
let result = 0;
if(index + 2 <= data.length) {
result = (data[index] << 8) + data[index + 1];
index += 2;
}
return { data: result, index: index };
},
u32(data, index) {
let result = 0;
if(index + 4 <= data.length) {
result = (data[index] << 24)
+ (data[index + 1] << 16)
+ (data[index + 1] << 8)
+ data[index + 1];
index += 4;
}
return { data: result, index: index };
},
string(data, index) {
let result = UNPACK.u16(data, index);
index = result.index;
let length = result.data;
let dec = new TextDecoder();
let result_str = "";
if(index + length <= data.length) {
let bytes = new Uint8Array(length);
for(let i = 0; i < length; ++i) {
bytes[i] = data[index + i];
}
index += length;
result_str = dec.decode(bytes);
}
return { data: result_str, index: index };
},
move(bytes) {
function piece_by_id(id) {
switch(id) {
case 0: return "";
case 1: return "M";
case 2: return "N";
case 3: return "L";
case 4: return "T";
case 5: return "C";
case 6: return "D";
case 7: return "K";
}
}
/*
** From [6]
** To [6]
** Piece [3]
** Take [3]
**
*/
let from = (bytes[0] & 0xFC) >> 2;
let to = ((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xC0) >> 6);
let piece = piece_by_id((bytes[1] & 0x38) >> 3);
let take = piece_by_id(bytes[1] & 0x07);
let source = (bytes[2] & 0x80) >> 7;
switch((bytes[2] & 0x60) >> 5) {
case 0: state = "";
case 1: state = "◇"; break;
case 2: state = "◈"; break;
case 3: state = "◆"; break;
}
let str = "";
if(state.length > 0) {
if(source == 1) {
str = "" + piece + " " + state + " " + to;
} else {
str = "" + from + " " + piece + " " + state + " " + to + " " + take;
}
if(take != "") { str += " " + take; }
}
return str;
}
};
const BITWISE = {
lsb(x) {
return x & -x;
},
ffs(x) {
return 31 - Math.clz32(x & -x);
},
count(mask) {
// source: https://graphics.stanford.edu/~seander/bithacks.html
mask = mask|0;
mask = mask - ((mask >> 1) & 0x55555555);
mask = (mask & 0x33333333) + ((mask >> 2) & 0x33333333);
return ((mask + (mask >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
},
rotate_blocks(mask)
{
const r1 = 0x00003F; // first 6 bits
const r2 = 0x000FC0; // second 6 bits
const r3 = 0x03F000; // third 6 bits
let v1 = (r1 & mask) << 3;
let v2 = (r2 & mask) << 3;
let v3 = (r3 & mask) << 3;
v1 = (v1 & r1) | ((v1 & ~r1) >> 6);
v2 = (v2 & r2) | ((v2 & ~r2) >> 6);
v3 = (v3 & r3) | ((v3 & ~r3) >> 6);
return v1 | v2 | v3;
},
};
const MATH = {
Vec2: class {
constructor(x, y) {
this.x = x;
this.y = y;
}
},
sign(a) {
return 1 - ((a < 0) << 1);
},
mod(a, b) {
return ((a % b) + b) % b
},
};
const COLOR = {
rgba(r, g, b, a) {
let ur = Math.floor(r * 255);
let ug = Math.floor(r * 255);
let ub = Math.floor(r * 255);
let ua = Math.floor(r * 255);
return "rgba(" + ur + "," + ug + "," + ub + "," + ua + ")";
},
}