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

Last change on this file since 202 was 202, checked in by krille_n_@…, 12 years ago

Changes:

  • Library/BIOS: Minor optimizations to DisplayFormatCompressed.asm and BootMenuEvent.asm
  • XTIDECFG: Trimmed trailing CRLFs from some of the text files in Help (also fixed a typo)
File size: 8.7 KB
Line 
1; Project name  :   Assembly Library
2; Description   :   Functions for displaying formatted strings.
3;                   ** Compressed Strings edition **
4;                   This is a plug replacement for DisplayFormat.asm,
5;                   working instead with precompiled and slightly compressed strings.
6;
7; Strings are compressed in a simple manner:
8;   1. The two most common characters, space and null, are removed
9;   2. Format specifiers are reduced to a single byte, including length information
10;
11; Format of bytes in the string are:
12;     01 xxxxxx     Character in x plus StringsCompressed_NormalBase
13;     10 xxxxxx     Character in x plus StringsCompressed_NormalBase, followed by a null (last character)
14;     11 xxxxxx     Character in x plus StringsCompressed_NormalBase, followed by a space
15;     00 1 yyyyy    Character/Format in lookup table StringsCopmressed_TranslatesAndFormats
16;     00 0 yyyyy    Character/Format in lookup table StringsCompressed_TranslatesAndFormats, followed by a null
17;
18; StringsCompressed_NormalBase is defined by the compressor, but is usually around 0x40,
19; which gives a range of 0x40 to 0x7f, or roughly the upper and lower case letters.
20;
21; StringsCompressed_TranslatesAndFormats is a lookup table with the first few bytes being translation
22; characters, and the last few bytes being format jump offsets from DisplayFormatCompressed_BaseFormatOffset.
23; The dividing line is defined by StringsCompressed_FormatsBegin
24;
25; The assignments of the first two bits above is not by accident.  The translates/format branch is 00
26; which is easy to test for.  The '01' for "normal" (no null or space) and '001' for translates/format "normal"
27; match, allowing the translates/format codes to be shifted left by 1 and then tested with the same instructions.
28;
29; It is always possible to say that a null character follows the current character - thus there is
30; no way (nor need) to specify a zero character.
31;
32; Note that this code is optimized for size, not speed.  Since this code is used only during initialization
33; and only for the user interface, small performance hits should not be noticed.  It will seem odd to do so
34; much "preload", just in case a branch is taken, but that is cheaper (in size) than adding additional branches.
35;
36
37; Section containing code
38SECTION .text
39
40;--------------------------------------------------------------------
41; Format Handlers
42;
43; Names of format handlers are DisplayFormatCompressed_Format_* where * is
44; replaced with the format code after the '%' in the original string,
45; with '-' replaced with '_'.
46;
47;   Parameters:
48;       DS:     BDA segment (zero)
49;       AX:     Parameter to Format
50;       ES:DI:  Ptr to cursor location in video RAM
51;   Returns:
52;       DI:     Updated offset to video RAM
53;   Corrupts registers:
54;       AX, BX, CX, DX, SI
55;--------------------------------------------------------------------
56
57;
58; The following routines do not need any pre or post processing and can be jumped to directly.
59; Note that they need to be within 256 bytes of DisplayFormatCompressed_BaseFormatOffset
60;
61%define DisplayFormatCompressed_Format_c DisplayPrint_CharacterFromAL
62%define DisplayFormatCompressed_Format_nl DisplayPrint_Newline_FormatAdjustBP
63%define DisplayFormatCompressed_Format_s DisplayFormat_ParseCharacters_FromAX
64
65DisplayFormatCompressed_Format_A:
66    mov     [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute], al
67DisplayFormatCompressed_ret:            ; jump target for other routines who need a "ret"
68    ret
69
70DisplayFormatCompressed_Format_x:
71DisplayFormatCompressed_Format_5_x:
72    mov     si,16                       ; hex output, change base to 16
73    mov     bx,(04<<8) + 'h'            ; 4 bytes, with postfix character 'h' to emit
74                                        ; (note that the count includes the 'h')
75    jmp     DisplayFormatCompressed_Format_u
76
77DisplayFormatCompressed_Format_2_I:
78    mov     si,g_szDashForZero          ; preload dash string in case we jump
79    test    ax,ax                       ; if parameter equals zero, emit dash string instead
80    jz      DisplayFormat_ParseCharacters
81    ; fall through
82
83DisplayFormatCompressed_Format_2_u:
84    mov     bh,2                        ; only two characters (instead of the default 5)
85    ; fall through
86
87DisplayFormatCompressed_Format_u:
88DisplayFormatCompressed_Format_5_u:
89    push    bx                          ; push postfix character - either a zero (default) or a 'h'
90    mov     bl,bh                       ; preserve character count for .PrintLoop
91
92.DivLoop:
93    xor     dx, dx                      ; Zero DX for division
94    div     si                          ; DX:AX / 10 => AX=quot, DX=rem
95    push    dx                          ; Push digit
96
97    dec     bh
98    jnz     .DivLoop
99
100.PrintLoop:
101    pop     ax                          ; Pop digit, postfix character on last iteration
102
103    dec     bl                          ; on second to last iteration, emit digit whether it is zero or not
104    jz      .PrintDigit
105
106    js      short DisplayPrint_CharacterFromAL  ; on last iteration, emit postfix character
107                                                ; if it is zero, DisplayPrint_CharacterFromAL will not emit
108
109    or      bh, al                      ; skip leading zeros, bh keeps track if we have emitted anything non-zero
110    jnz     .PrintDigit                 ; note that bh starts at zero, from the loop above
111
112    test    ch,2                        ; are we padding with leading spaces?
113    jnz     .PrintLoop                  ; test the even/odd of the format byte in the string
114
115    mov     al, 89h                     ; emit space
116
117.PrintDigit:
118    add     al, 90h                     ; Convert binary digit in AL to ASCII hex digit (0 - 9 or A - F)
119    daa
120    adc     al, 40h
121    daa
122
123    call    DisplayPrint_CharacterFromAL
124
125    jmp     .PrintLoop
126
127
128;--------------------------------------------------------------------
129; DisplayFormat_ParseCharacters
130;   Parameters:
131;       DS:     BDA segment (zero)
132;       SS:BP:  Pointer to first format parameter (-=2 updates to next parameter)
133;       CS:SI:  Pointer to string to format
134;       ES:DI:  Ptr to cursor location in video RAM
135;   Returns:
136;       CS:SI:  Ptr to end of format string (ptr to one past NULL)
137;       DI:     Updated offset to video RAM
138;   Corrupts registers:
139;       AX, BX, CX, DX, BP
140;--------------------------------------------------------------------
141
142DisplayFormatCompressed_BaseFormatOffset:
143
144DisplayFormat_ParseCharacters_FromAX:
145    mov     si,ax
146    ; fall through to DisplayFormat_ParseCharacters
147
148ALIGN JUMP_ALIGN
149DisplayFormat_ParseCharacters:
150;
151; This routine is used to output all strings from the ROM.  The strings in ROMVARS are not compressed,
152; and must be handled differently.
153;
154    cmp     si,byte 07fh        ; well within the boundaries of ROMVARS_size
155    mov     bx,cs               ; preload bx with cs in case we take the following jump
156    jb      short DisplayPrint_NullTerminatedStringFromBXSI
157
158.decode:
159    eSEG    cs
160    lodsb                       ; load next byte of the string
161
162    mov     ch,al               ; save a copy for later processing of high order bits
163
164    test    al,0c0h             ; check for translation/format character
165    jz      DisplayFormatCompressed_TranslatesAndFormats
166
167    and     al,03fh                             ; "Normal" character, mask off high order bits
168    add     al,StringsCompressed_NormalBase     ; and add character offset (usually around 0x40)
169
170.output:
171    call    DisplayPrint_CharacterFromAL
172
173.process_after_output:
174    shl     ch,1                                ; check high order bits for end of string or space
175    jns     short DisplayFormatCompressed_ret
176    jnc     .decode
177    mov     al,' '
178    call    DisplayPrint_CharacterFromAL
179    jmp     .decode
180
181
182ALIGN JUMP_ALIGN
183DisplayFormatCompressed_TranslatesAndFormats:
184;
185; This routine is here (above DisplayFormat_ParseCharacters) to reduce the amount of code between
186; DisplayFormatCompressed_BaseFormatOffset and jump targets (must fit in 256 bytes)
187;
188    shl     ch,1                ; setup ch for later testing of null in .process_after_output
189    and     ax,0001fh           ; also clears AH for addition with BX and DX below
190
191    mov     bx,StringsCompressed_TranslatesAndFormats   ; calculate offset of translation/formats offset byte
192    add     bx,ax
193
194    cmp     al,StringsCompressed_FormatsBegin           ; determine if this is a translation or a format
195
196    mov     al,[cs:bx]                                  ; fetch translation/formats byte
197
198    jb      DisplayFormat_ParseCharacters.output        ; check if this a translation or a format
199                                                        ; if it is translation, output and postprocess for eos
200                                                        ; note that the flags for this conditional jump were
201                                                        ; set with the cmp al,StringsCompressed_FormatsBegin
202
203    mov     dx,DisplayFormatCompressed_BaseFormatOffset   ; calculate address to jump to for format handler
204    sub     dx,ax
205
206    mov     ax,[bp]             ; preload ax with parameter
207    dec     bp                  ; if no parameter is needed (format 'nl' for example),
208    dec     bp                  ; the format handler can reincrement bp
209
210    mov     bx,0500h            ; preload bh with 5 decimal places for numeric output
211                                ; bl is zero, indicating not to output a 'h' (default base 10)
212
213    push    si                  ; preserve si and cx, in the case of outputing a string
214    push    cx
215
216    mov     si,10               ; preload si with 10 for numeric output (default base 10)
217
218    call    dx                  ; call the format routine
219
220    pop     cx                  ; restore cx and si
221    pop     si
222
223    jmp     DisplayFormat_ParseCharacters.process_after_output  ; continue postprocessing, check for end of string
224
Note: See TracBrowser for help on using the repository browser.