B2C/B2C/src/B2CFunctions.c

845 lines
22 KiB
C

BCDvar *B2C_add(BCDvar *buffer, BCDvar *a, BCDvar *b) {
int expA, expB, expDiff, carry = 0, tempadd, biggerExp_int;
unsigned char tempByte = 0;
int result[15] = {0};
BCDvar *smallerExp, *biggerExp;
//Determine if these numbers are negative
//If both are negative, add their opposites
//Ex: (-4)+(-3) -> -(4+3)
if ((*a)[0] > 0x30 && (*b)[0] > 0x30) {
BCDvar a2,b2;
memcpy(a2, *a, 9);
memcpy(b2, *b, 9);
a2[0] -= 0x50;
b2[0] -= 0x50;
B2C_add(buffer, &a2, &b2);
(*buffer)[0] += 0x50;
return buffer;
}
//If one of them is negative, substract them
//Ex: (-4)+3 -> 3-4
if ((*a)[0] > 0x30) {
BCDvar a2;
memcpy(a2, *a, 9);
a2[0] -= 0x50;
return B2C_sub(buffer, b, &a2);
}
if ((*b)[0] > 0x30) {
BCDvar b2;
memcpy(b2, *b, 9);
b2[0] -= 0x50;
return B2C_sub(buffer, a, &b2);
}
//First determine which number has a bigger exponent
expA = getExp(a);
expB = getExp(b);
if (expA > expB) {
smallerExp = b;
biggerExp = a;
expDiff = expA-expB;
biggerExp_int = expA;
} else {
smallerExp = a;
biggerExp = b;
expDiff = expB-expA;
biggerExp_int = expB;
}
//Add the number with the smallest exponent to the one with the biggest
for (i = 14; i >= 0; i--) {
tempadd = 0;
if (i >= expDiff) tempadd += getDigit(smallerExp, i-expDiff);
tempadd += getDigit(biggerExp, i) + carry;
if (tempadd >= 10) {
result[i] = tempadd-10;
carry = 1;
} else {
result[i] = tempadd;
carry = 0;
}
//locate(i+1, 3); printChar(carry+'0');
//locate(i+1, 4); printChar(tempadd+'0');
}
//Increment exponent if necessary
if (carry == 1) {
biggerExp_int++;
}
//locate(1,6); printChar(biggerExp_int);
//locate(3,6); printChar(expA+'0');
//locate(5,6); printChar(expB+'0');
//Put exponent in buffer
(*buffer)[0] = (biggerExp_int/100 << 4) + (biggerExp_int%100)/10;
tempByte = (biggerExp_int%10 << 4) + carry;
if (carry == 1) {
(*buffer)[1] = tempByte;
}
//Put result in buffer
for (i=0; i < 15-carry; i++) {
if ((i+carry)%2) {
tempByte = result[i] << 4;
} else {
(*buffer)[(i+carry+1)/2+1] = tempByte + result[i];
}
}
//locate(1,2); printBCDvarBytes(buffer);
//locate(1,1);
return buffer;
}
BCDvar *B2C_sub(BCDvar *buffer, BCDvar *a, BCDvar *b) {
//Substract a positive number B from a positive number A (A-B).
//A must be greater than B for the algorithm to function.
//However this function does the necessary checks so A and B can be any reals.
int expA, expB, expDiff, carry = 0, tempsub, compareResult;
unsigned char tempByte;
int result[15] = {0};
//Check for special cases
//a < 0 and b < 0 -> (-b)-(-a)
//Ex: (-4)-(-3) -> 3-4
if ((*a)[0] > 0x30 && (*b)[0] > 0x30) {
BCDvar a2, b2;
memcpy(a2, *a, 9);
memcpy(b2, *b, 9);
a2[0] -= 0x50;
b2[0] -= 0x50;
return B2C_sub(buffer, &b2, &a2);
}
//a > 0 and b < 0 -> a+(-b)
//Ex: 3-(-4) -> 3+4
if ((*b)[0] > 0x30) {
BCDvar b2;
memcpy(b2, *b, 9);
b2[0] -= 0x50;
return B2C_add(buffer, a, &b2);
}
//a < 0 and b > 0 -> -(a+b)
//Ex: (-4)-3 -> -(4+3)
if ((*a)[0] > 0x30) {
BCDvar a2;
memcpy(a2, *a, 9);
a2[0] -= 0x50;
B2C_add(buffer, &a2, b);
(*buffer)[0] += 0x50;
return buffer;
}
compareResult = B2C_compareBCDvars(a, b);
//a < b -> -(a-b)
//Ex : 3-4 -> -(4-3)
if (compareResult == A_LESS_THAN_B) {
B2C_sub(buffer, b, a);
(*buffer)[0] += 0x50;
return buffer;
//if a=b then a-b = 0
} else if (compareResult == A_EQUALS_B) {
return &_0_;
}
//Determine the exponent difference; A is always the biggest number
expA = getExp(a);
expB = getExp(b);
expDiff = expA-expB;
//Substract
for (i = 14; i >= 0; i--) {
tempsub = getDigit(a, i) - carry;
if (i >= expDiff) tempsub -= getDigit(b, i-expDiff);
if (tempsub < 0) {
tempsub += 10;
carry = 1;
} else {
carry = 0;
}
result[i] = tempsub;
}
//Determine new exponent, reuse the var expA and expDiff
//For example: 34-32 (3.4e1 - 3.2e1) will yield 2 (0.2e1) which must be converted to 2e0
for (i = 0; result[i] == 0 && i < 15; i++) {
expA--;
}
expDiff = i;
//Put exponent in buffer
(*buffer)[0] = (expA/100 << 4) + (expA%100)/10;
tempByte = (expA%10 << 4);
//Put result in buffer
for (i = 0; i < 15; i++) {
if (i%2) {
tempByte = (i < 15-expDiff ? result[i+expDiff] << 4 : 0);
} else {
(*buffer)[(i+1)/2+1] = tempByte + (i < 15-expDiff ? result[i+expDiff] : 0);
}
}
return buffer;
}
BCDvar *B2C_mult(BCDvar *buffer, BCDvar *a, BCDvar *b) {
//TODO: implement algorithm
//Here is my attempt at doing it (warning: yields completely false results)
//Algorithm from wikipedia: https://en.wikipedia.org/wiki/Multiplication_algorithm#Long_multiplication
/*int expA, expB, i, j, carry, tempDigit, expResult, firstDigitInResult = 0;
unsigned char tempByte;
char result[30] = {0};
expA = getExp(a)%500-100;
expB = getExp(b)%500-100;
for (i = 15; i > 0; i--) { //digits of b
carry = 0;
for (j = 15; j > 0; j--) { //digits of a
result[i+j-1] += carry + getDigit(a, j-1) + getDigit(b, i-1);
carry = result[i+j-1]/10;
result[i+j-1] %= 10;
}
result[i+15] += carry;
}
expResult = expA+expB + 100 + carry;
//Put exponent in buffer
(*buffer)[0] = (expResult/100 << 4) + (expResult%100)/10;
tempByte = (expResult%10 << 4);
//Calculate position of first non-zero digit in result
for (i = 0; result[i] == 0 && i < 30; i++) {
firstDigitInResult++;
locate(1,7); Print("test");
}
for (i = 0; i < 15; i++) {
locate(i+1, 4); printChar(result[i]+'0');
locate(i+1, 5); printChar(result[i+15]+'0');
}
//Put result in buffer
for (i = 0; i < 15; i++) {
if (i%2) {
tempByte = result[i+firstDigitInResult] << 4;
} else {
(*buffer)[(i+1)/2+1] = tempByte + result[i+firstDigitInResult];
}
}*/
const char *function = "A\xA9""B";
setAlphaVar('A', a);
setAlphaVar('B', b);
calcExp(&function, dummyOpCode, buffer, 1);
return buffer;
}
BCDvar *B2C_div(BCDvar *buffer, BCDvar *a, BCDvar *b) {
//TODO: make algorithm for division
const char *function = "A\xB9""B";
setAlphaVar('A', a);
setAlphaVar('B', b);
calcExp(&function, dummyOpCode, buffer, 1);
return buffer;
}
BCDvar *B2C_pow(BCDvar *buffer, BCDvar *a, BCDvar *b) {
//TODO: make algorithm for division
const char *function = "A\xA8""B";
setAlphaVar('A', a);
setAlphaVar('B', b);
calcExp(&function, dummyOpCode, buffer, 1);
return buffer;
}
BCDvar *B2C_sqrt(BCDvar *buffer, BCDvar *a, BCDvar *b) {
//TODO: make algorithm for division
const char *function = "A\x86""B";
setAlphaVar('A', a);
setAlphaVar('B', b);
calcExp(&function, dummyOpCode, buffer, 1);
return buffer;
}
BCDvar *B2C_greaterThan(BCDvar *a, BCDvar *b) {
if (B2C_compareBCDvars(a, b) == A_GREATER_THAN_B) return &_1_;
return &_0_;
}
BCDvar *B2C_greaterOrEqualThan(BCDvar *a, BCDvar *b) {
if (B2C_compareBCDvars(a, b) == A_LESS_THAN_B) return &_0_;
return &_1_;
}
BCDvar *B2C_lessThan(BCDvar *a, BCDvar *b) {
if (B2C_compareBCDvars(a, b) == A_LESS_THAN_B) return &_1_;
return &_0_;
}
BCDvar *B2C_lessOrEqualThan(BCDvar *a, BCDvar *b) {
if (B2C_compareBCDvars(a, b) == A_GREATER_THAN_B) return &_0_;
return &_1_;
}
BCDvar *B2C_equalTo(BCDvar *a, BCDvar *b) {
if (B2C_compareBCDvars(a, b) == A_EQUALS_B) return &_1_;
return &_0_;
}
BCDvar *B2C_notEqualTo(BCDvar *a, BCDvar *b) {
if (B2C_compareBCDvars(a, b) == A_EQUALS_B) return &_0_;
return &_1_;
}
int B2C_compareBCDvars(BCDvar *a, BCDvar *b) {
//Return: A_GREATER_THAN_B (1), A_EQUALS_B (0) or A_LESS_THAN_B (-1)
int expA, expB, areBothNegatives = 1, tempDigitA, tempDigitB;
//Compare sign
//If both are negatives we'll compare them then yield the opposite result
if ((*a)[0] > 0x30 && (*b)[0] > 0x30) {
areBothNegatives = -1;
}
//If a > 0 and b < 0 then a > b
if ((*a)[0] < 0x30 && (*b)[0] > 0x30) {
return A_GREATER_THAN_B;
}
//If a < 0 and b > 0 then a < b
if ((*a)[0] > 0x30 && (*b)[0] < 0x30) {
return A_LESS_THAN_B;
}
//Compare exponents
expA = getExp(a);
expB = getExp(b);
if (areBothNegatives) {
expA -= 500;
expB -= 500;
}
if (expA > expB) {
return areBothNegatives * A_GREATER_THAN_B;
} else if (expA < expB) {
return areBothNegatives * A_LESS_THAN_B;
}
//Exponents are equal ; compare digits
for (i = 0; i < 15; i++) {
tempDigitA = getDigit(a, i);
tempDigitB = getDigit(b, i);
if (tempDigitA > tempDigitB) {
return areBothNegatives * A_GREATER_THAN_B;
} else if (tempDigitA < tempDigitB) {
return areBothNegatives * A_LESS_THAN_B;
}
}
//At this point a = b
return A_EQUALS_B;
}
BCDvar *B2C_not(BCDvar *a) {
if ((*a)[1]) return &_0_;
return &_1_;
}
BCDvar *B2C_and(BCDvar *a, BCDvar *b) {
if ((*a)[1] && (*b)[1]) return &_1_;
return &_0_;
}
BCDvar *B2C_or(BCDvar *a, BCDvar *b) {
if ((*a)[1] || (*b)[1]) return &_1_;
return &_0_;
}
BCDvar *B2C_xor(BCDvar *a, BCDvar *b) {
//Thanks stackoverflow for optimized xor function
if (!((*a)[1]) != !((*b)[1])) return &_1_;
return &_0_;
}
BCDvar *B2C_int(BCDvar *buffer, BCDvar *a) {
const char *function = "\xA6""A";
setAlphaVar('A', a);
calcExp(&function, dummyOpCode, buffer, 1);
return buffer;
}
unsigned char* B2C_convToStr(BCDvar *nb) {
bcdToStr(nb, stringBuffer);
return stringBuffer;
}
void B2C_setListRow(unsigned int nbList, unsigned int row, BCDvar *value) {
memcpy(list[nbList].data[row], *value, sizeof(BCDvar)-3);
}
void B2C_setDimList(unsigned int nbList, unsigned short nbElements) {
list[nbList].nbElements = nbElements;
list[nbList].data = calloc(nbElements+1, sizeof(BCDvar));
}
List B2C_newList(int nbElements, ...) {
List list;
va_list vaList;
list.nbElements = nbElements;
list.data = calloc(nbElements+1, sizeof(BCDvar));
va_start(vaList, nbElements);
//memcpy(list.data[0], _0_, sizeof(BCDvar));
for (i = 1; i <= nbElements; i++) {
memcpy(list.data[i], va_arg(vaList, BCDvar), sizeof(BCDvar)-3);
}
va_end(vaList);
return list;
}
void B2C_setDimMat(unsigned char matrix, unsigned short x, unsigned short y) {
mat[matrix].width = x;
mat[matrix].height = y;
mat[matrix].data = calloc(x*y, sizeof(BCDvar));
}
void B2C_setMatCase(unsigned char matrix, unsigned int x, unsigned int y, BCDvar *value) {
memcpy(mat[matrix].data[mat[matrix].height*(x-1)+y-1], *value, sizeof(BCDvar)-3);
}
void B2C_fillMat(BCDvar *value, unsigned char matrix) {
for (i = 0; i < mat[matrix].width*mat[matrix].height; i++) {
memcpy(mat[matrix].data[i], *value, sizeof(BCDvar)-3);
}
}
void B2C_clrMat(unsigned char matrix) {
free(mat[matrix].data);
mat[matrix].width = 0;
mat[matrix].height = 0;
}
unsigned int B2C_convToUInt(BCDvar *nb) {
unsigned int result = 0;
//gets the 3rd digit of the exponent - that means it doesn't work for Uints > 10^10
//however this function is intended for locate, matrixes, lists, etc so it isn't needed
int power = ((*nb)[1]>>4) + 1;
for (i = 1; i <= power; i++) {
if (i%2) {
result += ((*nb)[i/2+1]&0xF) * pow(10, power-i);
} else {
result += ((*nb)[i/2+1]>>4) * pow(10, power-i);
}
}
return result;
}
int B2C_convToInt(BCDvar *nb) {
//(almost) copy of B2C_convToUInt, any changes made here must be reflected in the other function
int result = 0;
int power = ((*nb)[1]>>4) + 1;
for (i = 1; i <= power; i++) {
if (i%2) {
result += ((*nb)[i/2+1]&0xF) * pow(10, power-i);
} else {
result += ((*nb)[i/2+1]>>4) * pow(10, power-i);
}
}
if ((*nb)[0] > 0x30) { //exponent is higher than 300 so number is negative
result = -result;
}
return result;
}
BCDvar *B2C_getkey() {
if (!prgmGetkey(&getkeyBuffer)) {
B2C_exit(NO_ERROR);
}
return &getkeyBuffer;
}
#ifdef USES_INTERRUPTION_TIMER
void exitTimerHandler() {
/*short menuCode = 0x0308;
putMatrixCode(&menuCode);*/
if (IsKeyDown(KEY_CTRL_AC)) {
KillTimer(INTERRUPTION_TIMER);
B2C_exit(NO_ERROR);
} else {
SetTimer(INTERRUPTION_TIMER, 50, (void (*)(void))exitTimerHandler);
}
}
#endif
void B2C_exit(int exitCode) {
short menuCode = 0x0308;
PopUpWin(4);
switch(exitCode) {
case NO_ERROR:
locate(5,3); Print((unsigned char*)"Interruption");
break;
case MEMORY_ERROR:
locate(4,3); Print((unsigned char*)"Erreur m\xE6""\x0A""moire");
break;
case ARG_ERROR:
locate(4,3); Print((unsigned char*)"Erreur argument");
break;
}
locate(4,5); Print((unsigned char*)"Appuyer:[EXIT]");
//This syscall could resolve internationalisation problems,
//however it seems quite buggy (for example: interrupt by pressing
//AC/on, repress this key, then try to go back to the addin; the
//popup won't be there and you won't be able to do anything). I also
//managed to crash the main menu using this syscall.
//dispErrorMessage(exitCode);
while (1) {
putMatrixCode(&menuCode);
do {
GetKey(&key);
} while (key != KEY_CTRL_EXIT);
}
}
BCDvar *B2C_rand(BCDvar *buffer) {
int randDigit;
char tempByte;
//Initialise exponent to 99 (-1)
(*buffer)[0] = 9;
tempByte = 0x90;
for (i = 0; i < 15; i++) {
if (i%2) {
tempByte = (rand()%10) << 4;
} else {
(*buffer)[(i+1)/2+1] = tempByte + (rand()%10);
}
}
return buffer;
}
BCDvar *B2C_ranInt(BCDvar *buffer, BCDvar *a, BCDvar *b) {
//A + Int (Ran# * (B - A + 1))
const char *function = "A""\x89""\xA6""(""\xC1""\xA9""(B""\x99""A""\x89""1))";
setAlphaVar('A', a);
setAlphaVar('B', b);
calcExp(&function, dummyOpCode, buffer, 1);
return buffer;
}
/*
BCDvar *B2C_getAlphaVar(unsigned char var) {
getAlphaVar(var, alphaVarBuffer);
return &alphaVarBuffer;
}
*/
BCDvar *B2C_calcExp(unsigned char* exp) {
calcExp(&exp, dummyOpCode, &expressionBuffer, 1);
return &expressionBuffer;
}
void B2C_setAlphaVar(unsigned char alphaVar, BCDvar *value) {
memcpy(var[alphaVar], *value, sizeof(BCDvar)-3);
}
void B2C_setStr(Str *str, Str *value, int isString) {
free(str->data);
str->length = value->length;
str->data = malloc(value->length*2);
memcpy(str->data, value->data, value->length*2);
free_str(value);
}
unsigned char* B2C_strToCharArray(Str *str, int isString) {
int j = 0;
//Initialize the buffer
memset(stringBuffer, 0x00, 512);
//Goes through the string, starting at 2
for (i = 0; i < str->length; i++) {
//Skip null bytes
if ((str->data[i])&0xFF00) {
stringBuffer[j] = (((str->data[i])&0xFF00)>>8);
j++;
}
//There is normally no need to skip null bytes here
//if ((str->data[i])&0x00FF) {
stringBuffer[j] = ((str->data[i])&0x00FF);
j++;
//}
}
free_str(str);
return stringBuffer;
}
Str *B2C_charArrayToStr(unsigned char* charArray) {
int strPos = 0;
unsigned short currentChar;
Str *result = malloc(sizeof(Str));
result->data = calloc(strlen((char*)charArray), 2);
for (i = 0; charArray[i]; i++) {
currentChar = 0;
if (charArray[i] == 0xE5 ||
charArray[i] == 0xE6 ||
charArray[i] == 0xE7 ||
charArray[i] == 0xF7 ||
charArray[i] == 0xF9 ||
charArray[i] == 0x7F) {
currentChar = charArray[i] << 8;
i++;
}
result->data[strPos] = currentChar + charArray[i];
strPos++;
}
result->length = strPos;
return result;
}
BCDvar *B2C_strCmp(BCDvar *buffer, Str *str1, int isString1, Str *str2, int isString2) {
//Gotos are evil
//But sometimes evil is necessary for the greater good
int j, isString = isString1;
for (i = 0; i < str1->length && i < str1->length; i++) {
//Case 1, most common: both characters are single bytes
if (!(str1->data[i]&0xFF00) && !(str2->data[i]&0xFF00)) {
if (str1->data[i] < str2->data[i]) {
goto str1_lt_str2;
} else if (str1->data[i] > str2->data[i]) {
goto str1_gt_str2;
}
}
//Case 2: str1[i] is single byte, str2[i] is multi byte
//They can't be equal because the single byte at str1[i] can't match the multi byte prefix
else if (!(str1->data[i]&0xFF00)) {
if (str1->data[i] < (str2->data[i]>>8)) {
goto str1_lt_str2;
} else {
goto str1_gt_str2;
}
}
//Case 3: str1[i] is multi byte, str2[i] is single byte
else if (!(str2->data[i]&0xFF00)) {
if ((str1->data[i]>>8) < str2->data[i]) {
goto str1_lt_str2;
} else {
goto str1_gt_str2;
}
}
//Case 4: both are multi bytes
else {
if (str1->data[i] < str2->data[i]) {
goto str1_lt_str2;
} else if (str1->data[i] > str2->data[i]) {
goto str1_gt_str2;
}
}
}
//Test for length
if (str1->length < str2->length) {
goto str1_lt_str2;
} else if (str1->length > str2->length) {
goto str1_gt_str2;
}
//goto equalStrings;
//equalStrings:
buffer = &_0_;
goto freestrs;
str1_gt_str2:
buffer = &_1_;
goto freestrs;
str1_lt_str2:
buffer = &__1_;
//goto freestrs;
freestrs:
free_str(str1);
isString = isString2;
free_str(str2);
return buffer;
}
BCDvar *B2C_strSrc(BCDvar *buffer, Str *str1, int isString1, Str *str2, int isString2, int n) {
int isString = isString1;
n--;
exitIfNeg(n);
for (i = n; i < str1->length-str2->length+1; i++) {
if (!memcmp(str1->data+i, str2->data, str2->length*2)) {
intToBCD(i+1, buffer);
goto freestrs;
}
}
//str_not_found:
buffer = &_0_;
freestrs:
free_str(str1);
isString = isString2;
free_str(str2);
return buffer;
}
Str *B2C_strInv(Str *str, int isString) {
Str *result = malloc(sizeof(Str));
result->data = malloc(2*str->length);
result->length = str->length;
for (i = 0; i < str->length; i++) {
result->data[str->length-1-i] = str->data[i];
}
free_str(str);
return result;
}
Str *B2C_strJoin(Str *str1, int isString1, Str *str2, int isString2) {
int isString = isString1;
Str *result = malloc(sizeof(Str));
result->data = malloc(2*(str1->length + str2->length));
result->length = str1->length + str2->length;
memcpy(result->data, str1->data, str1->length * 2);
memcpy(result->data+str1->length, str2->data, str2->length * 2);
free_str(str1);
isString = isString2;
free_str(str2);
return result;
}
BCDvar *B2C_strLen(BCDvar *buffer, Str *str, int isString) {
intToBCD(str->length, buffer);
return buffer;
}
Str *B2C_strMid2args(Str *str, int isString, int start) {
//+1 because strings are 1-indexed in casio
return B2C_strMid(str, isString, start, str->length+1-start);
}
Str *B2C_strMid(Str *str, int isString, int start, int offset) {
Str *result = malloc(sizeof(Str));
start--; //In casio, strings are 1-indexed!
exitIfNeg(start);
exitIfNeg(offset);
if (offset+start > str->length) {
offset = str->length-start;
}
if (start > str->length) {
start = str->length;
}
result->data = malloc(offset * 2);
result->length = offset;
//Copy the substring
memcpy(result->data, str->data+start, 2*offset);
free_str(str);
return result;
}
Str *B2C_charAt(Str *str, int isString, int charPos) {
//Unused at the moment - not tested
Str *result = malloc(sizeof(Str));
charPos--; //In casio, strings are 1-indexed!
exitIfNeg(charPos);
result->data = malloc(2);
result->length = 1;
result->data[0] = str->data[charPos];
free_str(str);
return result;
}
Str *B2C_strUpr(Str *str, int isString) {
Str *result = malloc(sizeof(Str));
result->data = malloc(str->length * 2);
memcpy(result->data, str->data, str->length * 2);
result->length = str->length;
for (i = 0; i < result->length; i++) {
if (result->data[i] >= 'a' && result->data[i] <= 'z') {
result->data[i] -= 32;
}
}
free_str(str);
return result;
}
Str *B2C_strLwr(Str *str, int isString) { //(almost) copy of B2C_strUpr - any changes made here must be reflected in strUpr
Str *result = malloc(sizeof(Str));
result->data = malloc(str->length * 2);
memcpy(result->data, str->data, str->length * 2);
result->length = str->length;
for (i = 0; i < result->length; i++) {
if (result->data[i] >= 'A' && result->data[i] <= 'Z') {
result->data[i] += 32;
}
}
free_str(str);
return result;
}
Str *B2C_strRight(Str *str, int isString, int offset) {
Str *result = malloc(sizeof(Str));
exitIfNeg(offset);
result->data = malloc(offset*2);
if (offset > str->length) offset=str->length;
result->length = offset;
memcpy(result->data, str->data+(str->length-offset), offset*2);
free_str(str);
return result;
}
Str *B2C_strLeft(Str *str, int isString, int offset) {
Str *result = malloc(sizeof(Str));
exitIfNeg(offset);
result->data = malloc(offset*2);
if (offset > str->length) offset=str->length;
result->length = offset;
memcpy(result->data, str->data, offset*2);
free_str(str);
return result;
}
Str *B2C_strShift(Str *str, int isString, int offset) {
unsigned short* spaces = malloc(2*abs(offset));
Str *result = malloc(sizeof(Str));
for (i = 0; i < abs(offset); i++) {
spaces[i] = (unsigned short)' ';
}
result->length = str->length;
result->data = malloc(str->length*2);
if (offset > str->length) {
offset = str->length;
} else if (-offset > str->length) {
offset = -str->length;
}
if (offset > 0) {
memcpy(result->data, str->data+offset, (str->length-offset)*2);
memcpy(result->data+(str->length-offset), spaces, offset*2);
} else {
memcpy(result->data, spaces, -offset*2);
memcpy(result->data-offset, str->data, (str->length+offset)*2);
}
free_str(str);
return result;
}
Str *B2C_strRotate(Str *str, int isString, int offset) {
Str *result = malloc(sizeof(Str));
result->length = str->length;
result->data = malloc(str->length*2);
offset %= str->length;
if (offset > 0) {
memcpy(result->data, str->data+offset, (str->length-offset)*2);
memcpy(result->data+(str->length-offset), str->data, offset*2);
} else {
memcpy(result->data, str->data+(str->length+offset), -offset*2);
memcpy(result->data-offset, str->data, (str->length+offset)*2);
}
free_str(str);
return result;
}
//Debug function; is not used with converted programs
void printBCDvarBytes(BCDvar *var) {
unsigned char str[2] = {0};
for (i = 0; i < 18; i++) {
if (i%2) {
str[0] = '0'+((*var)[i/2]&0x0F);
} else {
str[0] = '0'+((*var)[i/2]>>4);
}
if (str[0] > '9') {
str[0] += 'A'-'9'-1;
}
Print(str);
}
}
void printChar(unsigned char c) {
unsigned char str[2] = {0};
str[0] = c;
Print(str);
}