ARES-SDK/qkeys.lsl

319 lines
9.6 KiB
Plaintext

#ifndef QKEYS
#define QKEYS
/*
***********************************************************
* *
* NANITE SYSTEMS ADVANCED TACTICAL OPERATING SYSTEM *
* *
* QKEYS COMPONENT *
* *
* Copyright, (C) Nanite Systems Corp., 1984, 1985, 2018 *
* *
* Copyright, (C) University of Michigan 1977-1981 *
* *
***********************************************************
NOTICE: UNAUTHORIZED DISTRIBUTION, COPYING, MODIFICATION,
OR REVERSE ENGINEERING OF PROPRIETARY NANITE SYSTEMS
MILITARY CONTROL CODE IS A FEDERAL OFFENSE. THIS CODE IS
CONFIDENTIAL.
PRODUCED UNDER CONTRACT TO THE GOVERNMENT OF THE TERRAN
REPUBLIC OR ONE OF ITS DEPENDENT POLITIES.
IDV: F0960303D0002
VENDOR DUNS: 005128988
*/
rotation k2q(key k) {
string kt = (string)llParseStringKeepNulls(k, ["-"], []);
/*integer e0 = (integer)("0x" & llGetSubString(kt, 0, 1)) - 126;
integer m0 = (integer)("0x" & llGetSubString(kt, 2, 7));
integer e1 = (integer)("0x" & llGetSubString(kt, 8, 9)) - 126;
integer m1 = (integer)("0x" & llGetSubString(kt, 10, 15));
integer e2 = (integer)("0x" & llGetSubString(kt, 16, 17)) - 126;
integer m2 = (integer)("0x" & llGetSubString(kt, 18, 23));
integer e3 = (integer)("0x" & llGetSubString(kt, 24, 25)) - 126;
integer m3 = (integer)("0x" & llGetSubString(kt, 26, 31));
return <(float)m0 * llPow(2, e0),
(float)m1 * llPow(2, e1),
(float)m2 * llPow(2, e2),
(float)m3 * llPow(2, e3)>; */
return <
iuf((integer)llGetSubString(kt, 0, 7)),
iuf((integer)llGetSubString(kt, 8, 15)),
iuf((integer)llGetSubString(kt, 16, 23)),
iuf((integer)llGetSubString(kt, 24, 31))
>;
}
key q2k(rotation q) {
return llInsertString(llInsertString(
i2h(fui(q.x)) + "-"
+ i2h(fui(q.y)) + "-"
+ i2h(fui(q.z))
+ i2h(fui(q.s)),
21, "-"), 12, "-");
}
// Strife Onizuka's Float-Union-Integer implementation
integer fui(float a)//Mono Safe, LSO Safe, Doubles Unsupported, LSLEditor Unsafe
{//union float to integer
integer b = 0x80000000 & ~llSubStringIndex(llList2CSV([a]), "-");//the sign
if((a)){//is it nonzero?
if((a = llFabs(a)) < 2.3509887016445750159374730744445e-38)//Denormalized range check & last stride of normalized range
return b | (integer)(a / 1.4012984643248170709237295832899e-45);//the math overlaps; saves cpu time.
if(a > 3.4028234663852885981170418348452e+38)//Round up to infinity
return b | 0x7F800000;//Positive or negative infinity
if(a > 1.4012984643248170709237295832899e-45){//It should at this point, except if it's NaN
integer c = ~-llFloor(llLog(a) * 1.4426950408889634073599246810019);//extremes will error towards extremes. following yuch corrects it
return b | (0x7FFFFF & (integer)(a * (0x1000000 >> c))) | ((126 + (c = ((integer)a - (3 <= (a *= llPow(2, -c))))) + c) * 0x800000);
}//the previous requires a lot of unwinding to understand it.
return b | 0x7FC00000;//NaN time! We have no way to tell NaN's apart so lets just choose one.
}//Mono does not support indeterminates so I'm not going to worry about them.
return b;//for grins, detect the sign on zero. it's not pretty but it works.
}
float iuf(integer a) { //union integer to float
if(0x7F800000 & ~a)
return llPow(2, (a | !a) + 0xffffff6a) * (((!!(a = (0xff & (a >> 23)))) * 0x800000) | (a & 0x7fffff)) * (1 | (a >> 31));
return (!(a & 0x7FFFFF)) * (float)"inf" * ((a >> 31) | 1);
}
// int2hexdword, also by Strife Onizuka
string i2h (integer I) {
integer A = (I >> 2) & 0x3C000000;//not an unsigned rshift
integer B = (I & 0x0F000000) >> 4;
integer C = (I & 0x00F00000) >> 6;
integer D = (I & 0x000F0000) >> 8;
integer E = (I & 0x0000F000) << 14;
integer F = (I & 0x00000F00) << 12;
integer G = (I & 0x000000F0) << 10;
integer H = (I & 0x0000000F) << 8;
return llGetSubString(
llInsertString(
llIntegerToBase64(
A + B + C + D + 0xD34D3400
- (0xF8000000 * (A / 0x28000000))//lowercase=0x90000000, uppercase=0xF8000000
- (0x03E00000 * (B / 0x00A00000))//lowercase=0x02400000, uppercase=0x03E00000
- (0x000F8000 * (C / 0x00028000))//lowercase=0x00090000, uppercase=0x000F8000
- (0x00003E00 * (D / 0x00000A00))//lowercase=0x00002400, uppercase=0x00003E00
),
4,
llIntegerToBase64(
E + F + G + H + 0xD34D3400
- (0xF8000000 * (E / 0x28000000))//lowercase=0x90000000, uppercase=0xF8000000
- (0x03E00000 * (F / 0x00A00000))//lowercase=0x02400000, uppercase=0x03E00000
- (0x000F8000 * (G / 0x00028000))//lowercase=0x00090000, uppercase=0x000F8000
- (0x00003E00 * (H / 0x00000A00))//lowercase=0x00002400, uppercase=0x00003E00
)
),
0,
7
);
}
// Copyright (C) 2009 Adam Wozniak and Doran Zemlja
// Released into the public domain.
// Free for anyone to use for any purpose they like.
//
// deep voodoo base 4096 key compression
//
// It produces fixed length encodings of 11 characters.
string compress_key(key k) {
string s = llToLower((string)llParseString2List((string)k, ["-"], []) + "0");
string ret;
integer i;
string A;
string B;
string C;
// string D;
while(i < 32) {
A = llGetSubString(s, i, i);
++i;
B = llGetSubString(s, i, i);
++i;
C = llGetSubString(s, i, i);
++i;
/*if(A == "0") {
A = "e";
D = "8";
} else if(A == "d") {
A = "e";
D = "9";
} else if(A == "f") {
A = "e";
D = "a";
} else
D = "b";
ret += "%e" + A + "%" + D + B + "%b" + C;*/
if(A == "0")
ret += "%ee%8";
else if(A == "d")
ret += "%ee%9";
else if(A == "f")
ret += "%ee%a";
else
ret += "%e" + A + "%b";
ret += B + "%b" + C;
}
return llUnescapeURL(ret);
}
key uncompress_key(string s) {
integer i;
string ret;
string A;
string B;
string C;
string D;
s = llToLower(llEscapeURL(s));
for(i = 0; i < 99; i += 9) {
A = llGetSubString(s,i+2,i+2);
B = llGetSubString(s,i+5,i+5);
C = llGetSubString(s,i+8,i+8);
D = llGetSubString(s,i+4,i+4);
if(D == "8") {
A = "0";
} else if(D == "9") {
A = "d";
} else if(D == "a") {
A = "f";
}
ret += A + B + C;
}
return (key)(llGetSubString(ret, 0, 7) + "-" +
llGetSubString(ret, 8,11) + "-" +
llGetSubString(ret,12,15) + "-" +
llGetSubString(ret,16,19) + "-" +
llGetSubString(ret,20,31));
}
/*
encode/decode 8 for compact keys
minimum weight of 3774-4338 bytes with 1 invocation of each function
rhet0rica, August 9, 2021
encodes keys into exactly 8 chars weighing 24 bytes on average
using the new llChar() and llOrd() built-ins
*/
string encode_8(key k) {
string o;
string in = llDumpList2String(llParseString2List(k, ["-"], []), "");
integer ri = 8;
while(ri--) {
integer cn = (integer)("0x" + substr(in, ri << 2, (ri << 2) + 3));
string c = llChar(cn);
if(llOrd(c, 0) != cn || cn < 256)
o += llChar(cn + 0x10000);
else
o += c;
}
return o;
}
key decode_8(string s) {
string o;
integer ri = 8;
while(ri--) {
integer c = llOrd(s, ri) & 0x0ffff;
integer rii = 4;
string word;
while(rii--) {
integer cn = (c >> (rii << 2)) & 0x0f;
if(cn < 10)
word += llChar(cn + 0x30);
else
word += llChar(cn + 0x57);
}
o += word;
}
return (key)(
substr(o, 0, 7) + "-" +
substr(o, 8, 11) + "-" +
substr(o, 12, 15) + "-" +
substr(o, 16, 19) + "-" +
substr(o, 20, 31)
);
}
/*
encode/decode 22 for compact keys
weight of 3778-4392 bytes with 1 invocation of each function
rhet0rica, August 13, 2022
encodes keys into 16 chars weighing up to 32 bytes
special NULL and EMPTY values for NULL_KEY and ""
less likely than encode_8 to break mono serialization (!) on uplifted regions
uses llChar() and llOrd()
*/
string encode_22(key u) {
if(u == "")
return "EMPTY";
if(u == NULL_KEY)
return "NULL";
/*string unhyphenated = substr(u, 0, 7) + substr(u, 9, 12)
+ substr(u, 14, 17) + substr(u, 19, 22)
+ substr(u, 24, 35);*/
string unhyphenated = llDumpList2String(llParseString2List(u, ["-"], []), "");
string outs;
integer cc = 16;
while(cc--) {
integer icc = cc << 1;
integer code = (integer)("0x" + substr(unhyphenated, icc, icc + 1));
if(code < 35 || code > 126) code += 0x100;
outs = llChar(code) + outs;
}
return outs;
}
key decode_22(string c) {
if(c == "EMPTY")
return "";
if(c == "NULL")
return NULL_KEY;
string prec;
integer cc = 16;
while(cc--) {
integer bits = llOrd(c, cc);
integer low = bits & 0xf;
integer high = (bits & 0xf0) >> 4;
#define decode_22_lookup "0123456789abcdef"
prec = substr(decode_22_lookup, high, high) + substr(decode_22_lookup, low, low) + prec;
#undef decode_22_lookup
}
// inexplicably, leaving this concatenation here is better for memory than putting it in the return line:
key hyphenated = (key)(substr(prec, 0, 7) + "-" + substr(prec, 8, 11) + "-"
+ substr(prec, 12, 15) + "-" + substr(prec, 16, 19) + "-"
+ substr(prec, 20, 31));
return hyphenated;
}
#endif // QKEYS