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 = ((*a)[0]>>4) * 100 + ((*a)[0]&0x0F) * 10 + ((*a)[1]>>4) - 100; expB = ((*b)[0]>>4) * 100 + ((*b)[0]&0x0F) * 10 + ((*b)[1]>>4) - 100; 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++; } biggerExp_int += 100; //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; unsigned char tempByte; int result[15] = {0}; //Check for special cases //a > 0 and b < 0 -> a+(-b) //Ex: 3-(-4) -> 3+4 if ((*a)[0] < 0x30 && (*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 && (*b)[0] < 0x30) { BCDvar a2; memcpy(a2, a, 9); a2[0] -= 0x50; B2C_add(buffer, &a2, b); (*buffer)[0] += 0x50; return buffer; } //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, &a2, &b2); } //if a < b sub b-a if (B2C_greaterThan(b, a)) { return B2C_sub(buffer, b, a); } //Determine the exponent difference; A is always the biggest number expA = ((*a)[0]>>4) * 100 + ((*a)[0]&0x0F) * 10 + ((*a)[1]>>4); expB = ((*b)[0]>>4) * 100 + ((*b)[0]&0x0F) * 10 + ((*b)[1]>>4); 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; } int B2C_greaterThan(BCDvar *a, BCDvar *b) { return FALSE; } BCDvar *B2C_not(BCDvar *a) { if ((*a)[1]) return &_0_; return &_1_; } unsigned char* B2C_convToStr(BCDvar *nb) { bcdToStr(nb, stringBuffer); return stringBuffer; } void B2C_setListRow(unsigned int nbList, unsigned int row, BCDvar *value) { //TODO: handle complex numbers unsigned short nbElements = 0; char listName[] = "0LIST\0\0"; listName[0] = getSetupEntry(SETUP_LISTFILE) + '0'; if (nbList >= 10) { listName[5] = nbList/10 + '0'; listName[6] = nbList%10 + '0'; } else { listName[5] = nbList + '0'; } //Three possible cases: the list exists and the row isn't a new one, list exists and the row //has to be added, list doesn't exist and has to be created //First case: list has to be created if (getItemData("main", listName, 8, 2, &nbElements)) { //most likely an error "file does not exist" - it can be another error but doing checks is time consuming unsigned char listContent[28] = {0,0,0,0,0,0,0,0, 0,1, 0,0,0,0,0,0}; memcpy(listContent+16, value, 12); putInternalItem(DIR_LIST, listName, 28, listContent); } else { //Second case: row has to be added if (row > nbElements) { //char str[2] = {0}; unsigned short existingListElements; unsigned int existingListLength; unsigned char* buffer; getItemSize("main", listName, &existingListLength); buffer = calloc(existingListLength+12, 1); //Copy existing list data getItemData("main", listName, 0, existingListLength, buffer); //Increase number of elements memcpy(buffer+8, &existingListElements, 2); existingListElements++; memcpy(&existingListElements, buffer+8, 2); //Put the new value in the buffer memcpy(buffer+existingListLength, value, 12); deleteInternalItem(DIR_LIST, listName); putInternalItem(DIR_LIST, listName, existingListLength+12, buffer); free(buffer); } else if (1) { overwriteItemData("main", listName, 12, value, 4+12*row); //DO NOT REMOVE THIS CONDITION OR ANYTHING INSIDE IT; THE DEMON INSIDE THIS FUNCTION WILL NOT APPROVE } else { locate(1,6); Print("test"); locate(23,2); Print(" "); } } } void B2C_setDimList(unsigned int nbList, unsigned short nbElements) { unsigned char* content = calloc(12*nbElements+LIST_START, 1); char listName[] = "0LIST\0\0"; listName[0] = getSetupEntry(SETUP_LISTFILE) + '0'; if (nbList >= 10) { listName[5] = nbList/10 + '0'; listName[6] = nbList%10 + '0'; } else { listName[5] = nbList + '0'; } content[8] = nbElements>>8; content[9] = nbElements&0xFF; deleteInternalItem(DIR_LIST, listName); putInternalItem(DIR_LIST, listName, 12*nbElements+LIST_START, content); free(content); } /* List B2C_newList(int nbElements, ...) { List list; va_list vaList; list.nbElements = nbElements; list.data = calloc(nbElements+1, sizeof(BCDvar)); va_start(vaList, nbElements); list.data[0] = _0_; for (i = 1; i <= nbElements; i++) { list.data[i] = va_arg(vaList, BCDvar); } va_end(vaList); return list; } */ void B2C_setDimMat(unsigned char matrix, unsigned short y, unsigned short x) { unsigned char* content = calloc(12*y*x + MAT_START, 1); char matName[] = "MAT_ \0\0"; matName[4] = matrix; memcpy(content+8, &y, 2); memcpy(content+10, &x, 2); deleteInternalItem(DIR_MAT, matName); putInternalItem(DIR_MAT, matName, 12*y*x+MAT_START, content); free(content); } void B2C_setMat(unsigned char matrix, unsigned int y, unsigned int x, BCDvar *value) { char matName[] = "MAT_ \0\0"; unsigned short matWidth; matName[4] = matrix; getItemData("main", matName, 10, 2, &matWidth); overwriteItemData("main", matName, 12, value, MAT_START+12*((y-1)*matWidth+(x-1))); } 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, exitTimerHandler); } } #endif void B2C_exit(int exitCode) { /*installTimer(6, (void*)&timerHandler, 1); startTimer(6); GetKey(&key); uninstallTimer(6);*/ 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; } locate(4,5); Print((unsigned char*)"Appuyer:[EXIT]"); while (1) { putMatrixCode(&menuCode); do { GetKey(&key); } while (key != KEY_CTRL_EXIT); } } BCDvar *B2C_ranInt(BCDvar *a, BCDvar *b) { return &_1_; /*BCDvar result; //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, &result, 1); return result;*/ } 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 var, BCDvar *value) { setAlphaVar(var, *value); } void B2C_setStr(Str *value, int isString, int strNum) { free(strings[strNum].data); strings[strNum].length = value->length; strings[strNum].data = malloc((value->length+2)*2); strings[strNum].data[(value->length+1)*2] = 0x00; memcpy(strings[strNum].data + 2, value->data + 2, value->length * 2); free_str(value); } unsigned char* B2C_strToCharArray(Str *str, int isString) { int j = 0; //Initialize the buffer memset(stringBuffer, 0x00, 256); //Goes through the string, starting at 2 for (i = 2; i <= (str->length+1) * 2; i++) { //Skip null bytes if (str->data[i]) { stringBuffer[j] = str->data[i]; j++; } } free_str(str); return stringBuffer; } Str *B2C_charArrayToStr(unsigned char* charArray) { int strPos = 2; Str *result = malloc(sizeof(Str)); result->data = calloc(strlen(charArray)+1, 2); result->length = 0; for (i = 0; charArray[i]; i++) { if (!(strPos%2) && charArray[i] != 0xE5 && charArray[i] != 0xE6 && charArray[i] != 0xE7 && charArray[i] != 0xF7 && charArray[i] != 0xF9 && charArray[i] != 0x7F) { strPos++; } result->data[strPos] = charArray[i]; strPos++; } result->length = (strPos-2)/2; return result; } BCDvar *B2C_strCmp(Str *str1, Str *str2, int isString1, int isString2) { unsigned char str_1[256] = {0}, str_2[256] = {0}; int j = 0, isString; //Can't use strToCharArray because the buffer can't be used twice for (i = 2; i <= (str1->length+1) * 2; i++) { //Skip null bytes if (str1->data[i]) { str_1[j] = str1->data[i]; j++; } } for (i = 2; i <= (str2->length+1) * 2; i++) { //Skip null bytes if (str2->data[i]) { str_2[j] = str2->data[i]; j++; } } isString = isString1; //Can't use strcmp() because it must return -1, 0 or 1 //so just implement strcmp while adapting free_str to free both str1 and str2 for (i = 0; str_1[i] || str_2[i]; i++) { if (str_1[i] < str_2[i]) { free_str(str1); isString = isString2; free_str(str2); return &__1_; } else if (str_1[i] > str_2[i]) { free_str(str1); isString = isString2; free_str(str2); return &_1_; } } free_str(str1); isString = isString2; free_str(str2); return &_0_; } Str *B2C_strInv(Str *str, int isString) { Str *result = malloc(sizeof(Str)); result->data = malloc(2*(str->length+1)); result->length = str->length; for (i = 2*str->length; i >= 2; i -= 2) { memcpy(result->data + 2*str->length-i, str->data + i, 2); } free_str(str); return result; } Str *B2C_strJoin(Str *str1, Str *str2, int isString1, int isString2) { int isString = isString1; Str *result = malloc(sizeof(Str)); result->data = malloc(2*(str1->length + str2->length + 1)); result->length = str1->length + str2->length; memcpy(result->data + 2, str1->data + 2, str1->length * 2); memcpy(result->data + 2 + str1->length * 2, str2->data + 2, str2->length * 2); free_str(str1); isString = isString2; free_str(str2); return result; } BCDvar *B2C_strLen(Str *str, int isString) { unsigned char length[4] = {0}; BCDvar *result; sprintf(length, "%d", str->length); result = B2C_calcExp(length); free_str(str); return result; } Str *B2C_strMid(Str *str, int isString, int start, int offset) { Str *result = malloc(sizeof(Str)); if (!offset) { offset = str->length-start; } result->data = malloc((offset+2) * 2); //Set null byte at the end result->data[(offset+1) * 2] = 0x00; result->length = offset; //Copy the substring memcpy(result->data + 2, str->data + start*2, 2*offset); free_str(str); return result; } Str *B2C_charAt(Str *str, int isString, int charPos) { Str *result = malloc(sizeof(Str)); result->data = malloc(3*2); result->data[2*2] = 0x00; result->length = 1; memcpy(result->data+2, str->data+charPos*2, 2); free_str(str); return result; } Str *B2C_strUpr(Str *str, int isString) { Str *result = malloc(sizeof(Str)); unsigned short currentChar; result->data = malloc((str->length+2) * 2); result->data[str->length+1] = 0x00; memcpy(result->data+2, str->data+2, str->length * 2); result->length = str->length; for (i = 3; i <= result->length*2; i+=2) { 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)); unsigned short currentChar; result->data = malloc((str->length+2) * 2); result->data[str->length+1] = 0x00; memcpy(result->data+2, str->data+2, str->length * 2); result->length = str->length; for (i = 3; i <= result->length*2; i+=2) { 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)); result->data = malloc((offset+2)*2); result->data[(offset+1)*2] = 0x00; result->length = offset; memcpy(result->data+2, str->data + (str->length - offset + 1)*2, offset * 2); free_str(str); return result; } Str *B2C_strLeft(Str *str, int isString, int offset) { Str *result = malloc(sizeof(Str)); result->data = malloc((offset+2)*2); result->data[(offset+1)*2] = 0x00; result->length = offset; memcpy(result->data+2, str->data + 2, 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+1)*2); offset %= str->length; if (offset > 0) { memcpy(result->data+2, str->data+2+2*offset, (str->length-offset)*2); memcpy(result->data+2+2*(str->length-offset), str->data+2, offset*2); } else { memcpy(result->data+2, str->data+2+2*(str->length+offset), -offset*2); memcpy(result->data+2+2*-offset, str->data+2, (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); }