#include "mkhiblib.h" /** * Return the width of a character, in the specified format * * @param font the font of the character * @param character the character * @param italic true is the character is italic * @param bold true is the character is bold * * @return the width of the character */ short hl_charWidth(h_Font * font, unsigned char character, BOOL italic, BOOL bold) { short size = font->width; if (size == 0) { size = *(font->tab + character * font->size_item); } if (italic) { size += (font->upperline + font->underline) / 3; } size += bold-font->include_space; return size; } /** * Return the width of a string, in the specified format * * @param font the font of the string * @param str the string * @param italic true is the string is italic * @param bold true is the string is bold * * @return the width of the string */ short hl_strWidth(h_Font * font, const unsigned char * str, BOOL italic, BOOL bold) { short offset = (italic ? 1 - hl_italicWidth(font) : 1 ); short size = -offset; while (*str!='\0') { size += hl_charWidth(font, *(str++), italic, bold) + offset; } return size; } /** * Draws a character (internal use only) * * @param height the height of the character * @param offset the offset in the screen * @param sprite the sprite of the character * @param italic true is the character is italic * @param bold true is the character is bold * @param screen the screen to draw in */ void drawCharacter(short height, short offset, unsigned char * sprite, BOOL italic, BOOL bold, h_ScreenMem screen) { short j; for (j = 0; j < height; j++) { (*(screen.ptr)) |= ((*sprite) >> offset); (*(screen.ptr + 1)) |= ((*sprite) << (8 - offset)); if (bold) { (*(screen.ptr)) |= ((*sprite) >> (offset + 1)); (*(screen.ptr + 1)) |= ((*sprite) << (8 - offset - 1)); } if (italic && j % 3 == 2) { offset++; if (offset == 8) { offset = 0; screen.ptr++; } } screen.ptr -= screen.byte_width; sprite--; } } /** * Draw a character * * @param font the font * @param x the starting x position * @param y the top y position * @param character the character to draw * @param italic true is the character is italic * @param bold true is the character is bold * @param screen the screen to draw in * * @return the size of the draw character */ short hl_drawChar(h_Font * font, short x, short y, unsigned char character, BOOL italic, BOOL bold, h_ScreenMem screen) { short charsize; unsigned char * sprite; short offset; short height = font->underline + font->upperline; sprite = font->tab + font->size_item * character; charsize = font->width; screen.ptr += (y + height - 1) * screen.byte_width + (x >> 3); if (charsize == 0) { charsize = *sprite; } offset = (x & 7) - font->include_space; if (offset < 0) { screen.ptr--; offset = 7; } drawCharacter(height, offset, sprite + font->size_item - 1, italic, bold, screen); charsize += bold - font->include_space; return charsize; } /** * Draw a string * * @param font the font * @param x the starting x position * @param y the top y position * @param character the string to draw * @param italic true is the string is italic * @param bold true is the string is bold * @param screen the screen to draw in * * @return the size of the draw string */ short hl_drawStr(h_Font * font, short x, short y, const unsigned char * str, BOOL italic, BOOL bold, h_ScreenMem screen) { short x_ini = x; short charsize; unsigned char * screen_ini; unsigned char * sprite; short size_add = bold + 1 - font->include_space; short offset; short height = font->underline + font->upperline; screen_ini = screen.ptr + (y + height - 1) * screen.byte_width; while (*str != '\0' && *str != 13) { screen.ptr = screen_ini + (x >> 3); charsize = font->width; sprite = font->tab + font->size_item * (*str); if (charsize == 0) { charsize = *sprite; } offset = (x & 7) - font->include_space; if (offset < 0) { screen.ptr--; offset = 7; } drawCharacter(height, offset, sprite + font->size_item - 1, italic, bold, screen); x += charsize + size_add; str++; } return x - x_ini - 1; } /** * Function to get the TiOS font datas (internal use only) * * This function was coded by the TICT Team. Thanks for them. */ extern short SetupCharSet(void); asm(" .data .even .xdef SetupCharSet SetupCharSet: | The method is fast in both cases. Therefore, there is no need to suppress interrupts. pea (%a2) move.l %d3,-(%sp) movea.l 0xC8.w,%a2 | A cmpi.w would be enough... cmpi.l #1000,-4(%a2) bgt.s __Prepare_fonts_AMS_2xx__ __Prepare_fonts_AMS_1xx__: | Get the address of DrawStr. movea.l 0x1A9*4(%a2),%a0 | Check if we have an old PedroM version. cmpi.l #0x50656472,-(%a0) | 'Pedr', a signature of PedroM. bne.s __The_ROM_we_re_running_on_is_not_PedroM__ | We have PedroM. | Setup all fonts. This will suppress crashes consecutive to the use of a | font that was not initialized... | d(pc) mode is forbidden for general purpose code. lea __F_6x8_Font__(%pc),%a1 subq.l #4,%a0 move.l -(%a0),(%a1) move.l -(%a0),-(%a1) bra.s __Prepare_fonts_end__ lea __F_4x6_Font__(%pc),%a1 move.l -12(%a0),(%a1) __The_ROM_we_re_running_on_is_not_PedroM__: | Retrieving the addresses of the fonts is easy (but slightly nasty) on AMS 1.xx. | Catch a pc-relative jump to a subroutine in which are the three addresses we're looking for. lea 58+4(%a0),%a0 | Get rid of the cmpi.l #0x50656472,-(%a0) above. movea.w (%a0),%a1 adda.l %a0,%a1 | a1 now contains the absolute address of the subroutine. | d(pc) mode is forbidden for general purpose code. lea __FontsTable__(%pc),%a0 | Setup all fonts. This will suppress crashes consecutive to the use of a | font that was not initialized... | Setup F_4x6 move.l 122(%a1),(%a0)+ | Setup F_6x8 move.l 106(%a1),(%a0)+ | Setup F_8x10 move.l 82(%a1),(%a0) bra.s __Prepare_fonts_end__ .even __Prepare_fonts_AMS_2xx__: | The fonts can be redefined on AMS 2.xx. So, retrieving the addresses of the fonts must be | performed with FlashApp functions. movea.l 0x45D*4(%a2),%a0 | EV_runningApp move.w (%a0),%d3 beq.s __Prepare_fonts_GetAttr__ | OO_GetAppAttr calls OO_GetAttr with the frame of the given application. | So we are going to catch the frame of the running application, to pass it | to OO_CondGetAttr. | We have AMS 2.xx, we can use ROM_CALL 441 'HeapTable' (smaller and faster | than pushing d3.w on the stack, calling HeapDeref, correcting sp). movea.l 0x441*4(%a2),%a0 | HeapTable lsl.w #2,%d3 movea.l 0(%a0,%d3.w),%a0 | The pFrame of an ACB structure is located 20 bytes after the beginning. movea.l 20(%a0),%a0 bra.s _Prepare_fonts_GetAttr__ __Prepare_fonts_GetAttr__: lea 0xFF000000.l,%a0 _Prepare_fonts_GetAttr__: movea.l 0x3FA*4(%a2),%a2 | OO_CondGetAttr | We use OO_CondGetAttr because it does not throw errors, unlike OO_GetAttr | (which can call OO_CondGetAttr anyway). /* | Setup all fonts. This will suppress crashes consecutive to the use of a | font that was not initialized... */ | Setup F_4x6 | d(pc) mode is forbidden for general purpose code. pea __F_4x6_Font__(%pc) pea 0x300.w pea (%a0) jsr (%a2) tst.w %d0 beq.s __Prepare_fonts_problem__ | Setup F_6x8 addq.l #4,8(%sp) addq.w #1,6(%sp) jsr (%a2) tst.w %d0 beq.s __Prepare_fonts_problem__ | Setup F_8x10 addq.l #4,8(%sp) addq.w #1,6(%sp) jsr (%a2) tst.w %d0 beq.s __Prepare_fonts_problem__ lea 12(%sp),%sp __Prepare_fonts_end__: moveq #1,%d0 _Prepare_fonts_end__: | Don't forget to restore registers... move.l (%sp)+,%d3 move.l (%sp)+,%a2 | This is not an inlined version of the routine... rts __Prepare_fonts_problem__: moveq #0,%d0 bra.s _Prepare_fonts_end__ "); extern unsigned char* __FontsTable__; extern unsigned char* __F_4x6_Font__; extern unsigned char* __F_6x8_Font__; extern unsigned char* __F_8x10_Font__; asm(" | The three pointers are always stored into the program. This wastes 8 bytes maximum, but | increases the speed of some of the functions. | The pointer to F_4x6 also points to the character widths of F_4x6, due to the way the | characters are stored. .xdef __FontsTable__ .even __FontsTable__: .xdef __F_4x6_Font__ .even __F_4x6_Font__: .long 0 .xdef __F_6x8_Font__ .even __F_6x8_Font__: .long 0 .xdef __F_8x10_Font__ .even __F_8x10_Font__: .long 0 "); /** * Function to load the TiOS fonts * * @param font1 the h-Font struct to fill for the little TiOS font * @param font2 the h-Font struct to fill for the medium TiOS font * @param font3 the h-Font struct to fill for the big TiOS font */ void hl_loadTiosFont(h_Font * font1, h_Font * font2, h_Font * font3) { SetupCharSet(); *font1 = (h_Font) { .h = H_NULL, .filename = {'t', 'i', 'o', 's', '1', '\0', ' ', ' ', ' '}, .width = 0, .upperline = 5, .underline = 0, .size_item = 6, .include_space = 1, .tab= __F_4x6_Font__ }; *font2 = (h_Font) { .h = H_NULL, .filename = {'t', 'i', 'o', 's', '2', '\0', ' ', ' ', ' '}, .width = 6, .upperline = 7, .underline = 1, .size_item = 8, .include_space = 1, .tab = __F_6x8_Font__ }; *font3 = (h_Font) { .h = H_NULL, .filename = {'t', 'i', 'o', 's', '3', '\0', ' ', ' ', ' '}, .width = 8, .upperline = 9, .underline = 1, .size_item = 10, .include_space = 1, .tab = __F_8x10_Font__ }; } /** * Load every fonts (including TiOS fonts) * * @param fonttab the table of the h_Fonts to fill * * @return the number of found fonts or NOK (-1) if there is a memory error */ short hl_loadAllFont(h_Font * * fonttab) { SYM_ENTRY * SymPtr; unsigned char * data; h_Font * ptr; short version; h_Font font; short nb_font = 0; *fonttab = malloc(3 * sizeof(h_Font)); if (*fonttab == NULL) { return NOK; } hl_loadTiosFont(&((*fonttab)[0]), &((*fonttab)[1]), &((*fonttab)[2])); nb_font = 3; //research of every font file in the Ti SymPtr = SymFindFirst(NULL, FO_RECURSE | FO_SKIP_TEMPS); while (SymPtr != NULL) { data = HeapDeref(SymPtr->handle); if (data[*(unsigned short *)data + 1] == OTH_TAG) { if (strcmp(&(data[*(unsigned short *)data - 4]), "FONT") == 0) { //it's a font file data = HLock(SymPtr->handle); if (data != NULL) { data += 2; version = *(unsigned short *)data; if (version <= FONTVAR_VERSION) { //the version of the FONT file is known nb_font++; ptr = realloc(*fonttab, nb_font * sizeof(h_Font)); if (ptr == NULL) { free(fonttab); return NOK; } *fonttab = ptr; strncpy(font.filename, SymPtr->name, 8); font.filename[8] = '\0'; font.h = SymPtr->handle; data += 2; font.width = *(data++); font.underline = *(data++); font.upperline = *(data++); font.size_item = *(data++); font.include_space = *(data++); font.tab = data; (*fonttab)[nb_font - 1] = font; } } } } SymPtr = SymFindNext(); } return nb_font; } /** * Unload every font * * @param fonttab the table of the fonts * @param nb_font the number of font in the table */ void hl_unloadAllFont(h_Font * fonttab, short nb_font) { while (nb_font-- > 0) { HeapUnlock(fonttab[nb_font].h); } free(fonttab); } /** * Find a font in the table of fonts * * @param filename_font the name of the font * @param fonttab the table of the fonts * @param nb_font the number of font in the table * * @return the pointer on the found font, NULL if not found */ h_Font * hl_findFont(const unsigned char * filename_font, h_Font * fonttab, short nb_font) { while (--nb_font >= 0) { if (strcmp(filename_font, fonttab[nb_font].filename) == 0) { // found ! return &(fonttab[nb_font]); } } return NULL; }