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); }