source: xtideuniversalbios/trunk/Assembly_Library/Src/Display/DisplayFormatCompressed.asm

Last change on this file was 580, checked in by krille_n_@…, 9 years ago

Changes:

  • XTIDECFG: Fixed a bug from r459 where the menu option for selection of default boot drive would be missing if the BIOS had been built without MODULE_HOTKEYS. The menu option is now visible if either or both of MODULE_HOTKEYS and MODULE_BOOT_MENU is available.
  • BIOS: Disabled ATA-ID validation by adding a new define (NO_ATAID_VALIDATION) and making it the default for all builds since at least two WD Caviar drive models are incompatible with it.
  • Fixed the "No Fixed Disk Present in FDISK"-bug introduced in r551 which means the Tiny build now works without including MODULE_DRIVEXLATE.
  • Fixed a bug from r528 where pressing hotkey F6 would not initiate detection of serial drives.
  • Fixed a bug from r186 in DisplayFormatCompressed.asm where the boot menu would print the IRQ in hexadecimal format when it should be in decimal format.
  • Optimizations and fixes.
File size: 9.7 KB
RevLine 
[186]1; Project name  :   Assembly Library
2; Description   :   Functions for displaying formatted strings.
[202]3;                   ** Compressed Strings edition **
4;                   This is a plug replacement for DisplayFormat.asm,
5;                   working instead with precompiled and slightly compressed strings.
[376]6
[186]7;
[445]8; XTIDE Universal BIOS and Associated Tools
[526]9; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
[376]10;
11; This program is free software; you can redistribute it and/or modify
12; it under the terms of the GNU General Public License as published by
13; the Free Software Foundation; either version 2 of the License, or
14; (at your option) any later version.
[445]15;
[376]16; This program is distributed in the hope that it will be useful,
17; but WITHOUT ANY WARRANTY; without even the implied warranty of
18; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
[445]19; GNU General Public License for more details.
[376]20; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21;
22
23;=============================================================================================
24;
[186]25; Strings are compressed in a simple manner:
26;   1. The two most common characters, space and null, are removed
[202]27;   2. Format specifiers are reduced to a single byte, including length information
[186]28;
29; Format of bytes in the string are:
30;     01 xxxxxx     Character in x plus StringsCompressed_NormalBase
31;     10 xxxxxx     Character in x plus StringsCompressed_NormalBase, followed by a null (last character)
[202]32;     11 xxxxxx     Character in x plus StringsCompressed_NormalBase, followed by a space
[186]33;     00 1 yyyyy    Character/Format in lookup table StringsCopmressed_TranslatesAndFormats
34;     00 0 yyyyy    Character/Format in lookup table StringsCompressed_TranslatesAndFormats, followed by a null
35;
36; StringsCompressed_NormalBase is defined by the compressor, but is usually around 0x40,
37; which gives a range of 0x40 to 0x7f, or roughly the upper and lower case letters.
38;
39; StringsCompressed_TranslatesAndFormats is a lookup table with the first few bytes being translation
40; characters, and the last few bytes being format jump offsets from DisplayFormatCompressed_BaseFormatOffset.
41; The dividing line is defined by StringsCompressed_FormatsBegin
42;
43; The assignments of the first two bits above is not by accident.  The translates/format branch is 00
[202]44; which is easy to test for.  The '01' for "normal" (no null or space) and '001' for translates/format "normal"
[186]45; match, allowing the translates/format codes to be shifted left by 1 and then tested with the same instructions.
46;
[202]47; It is always possible to say that a null character follows the current character - thus there is
[186]48; no way (nor need) to specify a zero character.
49;
50; Note that this code is optimized for size, not speed.  Since this code is used only during initialization
51; and only for the user interface, small performance hits should not be noticed.  It will seem odd to do so
52; much "preload", just in case a branch is taken, but that is cheaper (in size) than adding additional branches.
53;
[202]54
[186]55; Section containing code
56SECTION .text
57
58;--------------------------------------------------------------------
59; Format Handlers
60;
61; Names of format handlers are DisplayFormatCompressed_Format_* where * is
[202]62; replaced with the format code after the '%' in the original string,
[186]63; with '-' replaced with '_'.
64;
65;   Parameters:
66;       DS:     BDA segment (zero)
[567]67;       AX:     Parameter to Format
[186]68;       ES:DI:  Ptr to cursor location in video RAM
69;   Returns:
70;       DI:     Updated offset to video RAM
71;   Corrupts registers:
72;       AX, BX, CX, DX, SI
73;--------------------------------------------------------------------
74
75;
76; The following routines do not need any pre or post processing and can be jumped to directly.
77; Note that they need to be within 256 bytes of DisplayFormatCompressed_BaseFormatOffset
78;
79%define DisplayFormatCompressed_Format_c DisplayPrint_CharacterFromAL
80%define DisplayFormatCompressed_Format_nl DisplayPrint_Newline_FormatAdjustBP
81%define DisplayFormatCompressed_Format_s DisplayFormat_ParseCharacters_FromAX
82
[194]83DisplayFormatCompressed_Format_A:
[186]84    mov     [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute], al
85DisplayFormatCompressed_ret:            ; jump target for other routines who need a "ret"
86    ret
87
[241]88DisplayFormatCompressed_Format_z:
89    xor     bx, bx
90    xchg    si, ax
[580]91    jmp     SHORT DisplayPrint_NullTerminatedStringFromBXSI
[241]92
[186]93DisplayFormatCompressed_Format_x:
94DisplayFormatCompressed_Format_5_x:
[580]95    mov     si, 16                      ; hex output, change base to 16
96    mov     bx, (04<<8) + 'h'           ; 4 bytes, with postfix character 'h' to emit
[186]97                                        ; (note that the count includes the 'h')
[580]98    SKIP2B  f                           ; Fall through to DisplayFormatCompressed_Format_u
[186]99
100DisplayFormatCompressed_Format_2_u:
[580]101    mov     bh, 2                       ; only two characters (instead of the default 5)
[194]102    ; fall through
[202]103
[186]104DisplayFormatCompressed_Format_u:
105DisplayFormatCompressed_Format_5_u:
106    push    bx                          ; push postfix character - either a zero (default) or a 'h'
[580]107    mov     bl, bh                      ; preserve character count for .PrintLoop
[186]108
109.DivLoop:
110    xor     dx, dx                      ; Zero DX for division
111    div     si                          ; DX:AX / 10 => AX=quot, DX=rem
112    push    dx                          ; Push digit
[202]113
114    dec     bh
[580]115    jnz     SHORT .DivLoop
[186]116
117.PrintLoop:
118    pop     ax                          ; Pop digit, postfix character on last iteration
119
120    dec     bl                          ; on second to last iteration, emit digit whether it is zero or not
[580]121    jz      SHORT .PrintDigit
122    js      SHORT DisplayPrint_CharacterFromAL  ; on last iteration, emit postfix character
[186]123                                                ; if it is zero, DisplayPrint_CharacterFromAL will not emit
124
[202]125    or      bh, al                      ; skip leading zeros, bh keeps track if we have emitted anything non-zero
[580]126    jnz     SHORT .PrintDigit           ; note that bh starts at zero, from the loop above
[186]127
[580]128    test    ch, 2                       ; are we padding with leading spaces?
129    jnz     SHORT .PrintLoop            ; test the even/odd of the format byte in the string
[186]130
[202]131    mov     al, 89h                     ; emit space
[186]132
[202]133.PrintDigit:
[505]134    cmp     al, 10                      ; Convert binary digit in AL to ASCII hex digit ('0'-'9' or 'A'-'F')
135    sbb     al, 69h
136    das
[186]137
138    call    DisplayPrint_CharacterFromAL
[580]139    jmp     SHORT .PrintLoop
[186]140
[580]141DisplayFormatCompressed_Format_2_I:
142    test    ax, ax
143    jnz     SHORT DisplayFormatCompressed_Format_2_u
144    mov     si, g_szDashForZero         ; if parameter equals zero, emit dash string instead
145    SKIP2B  bx                          ; Fall through to DisplayFormat_ParseCharacters
[186]146
147;--------------------------------------------------------------------
148; DisplayFormat_ParseCharacters
149;   Parameters:
150;       DS:     BDA segment (zero)
151;       SS:BP:  Pointer to first format parameter (-=2 updates to next parameter)
152;       CS:SI:  Pointer to string to format
153;       ES:DI:  Ptr to cursor location in video RAM
154;   Returns:
155;       CS:SI:  Ptr to end of format string (ptr to one past NULL)
156;       DI:     Updated offset to video RAM
157;   Corrupts registers:
158;       AX, BX, CX, DX, BP
[202]159;--------------------------------------------------------------------
[194]160DisplayFormatCompressed_BaseFormatOffset:
161DisplayFormat_ParseCharacters_FromAX:
[580]162    mov     si, ax
[194]163    ; fall through to DisplayFormat_ParseCharacters
[186]164
[369]165ALIGN DISPLAY_JUMP_ALIGN
[202]166DisplayFormat_ParseCharacters:
[186]167;
[202]168; This routine is used to output all strings from the ROM.  The strings in ROMVARS are not compressed,
[186]169; and must be handled differently.
170;
[580]171    cmp     si, BYTE 7Fh        ; well within the boundaries of ROMVARS_size
172    mov     bx, cs              ; preload bx with cs in case we take the following jump
173    jb      SHORT DisplayPrint_NullTerminatedStringFromBXSI
[186]174
175.decode:
[223]176    cs lodsb                    ; load next byte of the string
[580]177    mov     ch, al              ; save a copy for later processing of high order bits
178    test    al, 0C0h            ; check for translation/format character
179    jz      SHORT DisplayFormatCompressed_TranslatesAndFormats
[186]180
[580]181    and     al, 3Fh                             ; "Normal" character, mask off high order bits
182    add     al, StringsCompressed_NormalBase    ; and add character offset (usually around 0x40)
[186]183
184.output:
[202]185    call    DisplayPrint_CharacterFromAL
[186]186
187.process_after_output:
[580]188    eSHL_IM ch, 1                               ; check high order bits for end of string or space
189    jns     SHORT DisplayFormatCompressed_ret
190    jnc     SHORT .decode
191    mov     al, ' '
[186]192    call    DisplayPrint_CharacterFromAL
[580]193    jmp     SHORT .decode
[186]194
195
[369]196ALIGN DISPLAY_JUMP_ALIGN
[202]197DisplayFormatCompressed_TranslatesAndFormats:
[186]198;
199; This routine is here (above DisplayFormat_ParseCharacters) to reduce the amount of code between
200; DisplayFormatCompressed_BaseFormatOffset and jump targets (must fit in 256 bytes)
201;
[580]202    eSHL_IM ch, 1               ; setup ch for later testing of null in .process_after_output
203    and     ax, 001Fh           ; also clears AH for addition with BX and DX below
[186]204
[580]205    mov     bx, StringsCompressed_TranslatesAndFormats  ; calculate offset of translation/formats offset byte
206    add     bx, ax
[186]207
[580]208    cmp     al, StringsCompressed_FormatsBegin          ; determine if this is a translation or a format
209    mov     al, [cs:bx]                                 ; fetch translation/formats byte
210    jb      SHORT DisplayFormat_ParseCharacters.output  ; check if this a translation or a format
[186]211                                                        ; if it is translation, output and postprocess for eos
212                                                        ; note that the flags for this conditional jump were
213                                                        ; set with the cmp al,StringsCompressed_FormatsBegin
[202]214
[580]215    mov     dx, DisplayFormatCompressed_BaseFormatOffset    ; calculate address to jump to for format handler
216    sub     dx, ax
[186]217
[580]218    mov     ax, [bp]            ; preload ax with parameter
[186]219    dec     bp                  ; if no parameter is needed (format 'nl' for example),
220    dec     bp                  ; the format handler can reincrement bp
221
[580]222    mov     bx, 0500h           ; preload bh with 5 decimal places for numeric output
[186]223                                ; bl is zero, indicating not to output a 'h' (default base 10)
224
225    push    si                  ; preserve si and cx, in the case of outputing a string
226    push    cx
227
[580]228    mov     si, 10              ; preload si with 10 for numeric output (default base 10)
[186]229    call    dx                  ; call the format routine
230
231    pop     cx                  ; restore cx and si
232    pop     si
233
[580]234    jmp     SHORT DisplayFormat_ParseCharacters.process_after_output    ; continue postprocessing, check for end of string
Note: See TracBrowser for help on using the repository browser.