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

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

Space optimizations in the Boot Menu and BootInfo routines, taking advantage of nested %s. Optimization in the init of RamVars to avoid writing the signature twice. Preparing for addition of serial floppy support, starting to break the assumption that our drives are always 80h or higher.

File size: 8.8 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_z:
71    xor     bx, bx
72    xchg    si, ax
73    jmp     short DisplayPrint_NullTerminatedStringFromBXSI
74
75DisplayFormatCompressed_Format_x:
76DisplayFormatCompressed_Format_5_x:
77    mov     si,16                       ; hex output, change base to 16
78    mov     bx,(04<<8) + 'h'            ; 4 bytes, with postfix character 'h' to emit
79                                        ; (note that the count includes the 'h')
80    jmp     DisplayFormatCompressed_Format_u
81
82DisplayFormatCompressed_Format_2_I:
83    mov     si,g_szDashForZero          ; preload dash string in case we jump
84    test    ax,ax                       ; if parameter equals zero, emit dash string instead
85    jz      DisplayFormat_ParseCharacters
86    ; fall through
87
88DisplayFormatCompressed_Format_2_u:
89    mov     bh,2                        ; only two characters (instead of the default 5)
90    ; fall through
91
92DisplayFormatCompressed_Format_u:
93DisplayFormatCompressed_Format_5_u:
94    push    bx                          ; push postfix character - either a zero (default) or a 'h'
95    mov     bl,bh                       ; preserve character count for .PrintLoop
96
97.DivLoop:
98    xor     dx, dx                      ; Zero DX for division
99    div     si                          ; DX:AX / 10 => AX=quot, DX=rem
100    push    dx                          ; Push digit
101
102    dec     bh
103    jnz     .DivLoop
104
105.PrintLoop:
106    pop     ax                          ; Pop digit, postfix character on last iteration
107
108    dec     bl                          ; on second to last iteration, emit digit whether it is zero or not
109    jz      .PrintDigit
110
111    js      short DisplayPrint_CharacterFromAL  ; on last iteration, emit postfix character
112                                                ; if it is zero, DisplayPrint_CharacterFromAL will not emit
113
114    or      bh, al                      ; skip leading zeros, bh keeps track if we have emitted anything non-zero
115    jnz     .PrintDigit                 ; note that bh starts at zero, from the loop above
116
117    test    ch,2                        ; are we padding with leading spaces?
118    jnz     .PrintLoop                  ; test the even/odd of the format byte in the string
119
120    mov     al, 89h                     ; emit space
121
122.PrintDigit:
123    add     al, 90h                     ; Convert binary digit in AL to ASCII hex digit (0 - 9 or A - F)
124    daa
125    adc     al, 40h
126    daa
127
128    call    DisplayPrint_CharacterFromAL
129
130    jmp     .PrintLoop
131
132
133;--------------------------------------------------------------------
134; DisplayFormat_ParseCharacters
135;   Parameters:
136;       DS:     BDA segment (zero)
137;       SS:BP:  Pointer to first format parameter (-=2 updates to next parameter)
138;       CS:SI:  Pointer to string to format
139;       ES:DI:  Ptr to cursor location in video RAM
140;   Returns:
141;       CS:SI:  Ptr to end of format string (ptr to one past NULL)
142;       DI:     Updated offset to video RAM
143;   Corrupts registers:
144;       AX, BX, CX, DX, BP
145;--------------------------------------------------------------------
146
147DisplayFormatCompressed_BaseFormatOffset:
148
149DisplayFormat_ParseCharacters_FromAX:
150    mov     si,ax
151    ; fall through to DisplayFormat_ParseCharacters
152
153ALIGN JUMP_ALIGN
154DisplayFormat_ParseCharacters:
155;
156; This routine is used to output all strings from the ROM.  The strings in ROMVARS are not compressed,
157; and must be handled differently.
158;
159    cmp     si,byte 07fh        ; well within the boundaries of ROMVARS_size
160    mov     bx,cs               ; preload bx with cs in case we take the following jump
161    jb      short DisplayPrint_NullTerminatedStringFromBXSI
162
163.decode:
164    cs lodsb                    ; load next byte of the string
165
166    mov     ch,al               ; save a copy for later processing of high order bits
167
168    test    al,0c0h             ; check for translation/format character
169    jz      DisplayFormatCompressed_TranslatesAndFormats
170
171    and     al,03fh                             ; "Normal" character, mask off high order bits
172    add     al,StringsCompressed_NormalBase     ; and add character offset (usually around 0x40)
173
174.output:
175    call    DisplayPrint_CharacterFromAL
176
177.process_after_output:
178    shl     ch,1                                ; check high order bits for end of string or space
179    jns     short DisplayFormatCompressed_ret
180    jnc     .decode
181    mov     al,' '
182    call    DisplayPrint_CharacterFromAL
183    jmp     .decode
184
185
186ALIGN JUMP_ALIGN
187DisplayFormatCompressed_TranslatesAndFormats:
188;
189; This routine is here (above DisplayFormat_ParseCharacters) to reduce the amount of code between
190; DisplayFormatCompressed_BaseFormatOffset and jump targets (must fit in 256 bytes)
191;
192    shl     ch,1                ; setup ch for later testing of null in .process_after_output
193    and     ax,0001fh           ; also clears AH for addition with BX and DX below
194
195    mov     bx,StringsCompressed_TranslatesAndFormats   ; calculate offset of translation/formats offset byte
196    add     bx,ax
197
198    cmp     al,StringsCompressed_FormatsBegin           ; determine if this is a translation or a format
199
200    mov     al,[cs:bx]                                  ; fetch translation/formats byte
201
202    jb      DisplayFormat_ParseCharacters.output        ; check if this a translation or a format
203                                                        ; if it is translation, output and postprocess for eos
204                                                        ; note that the flags for this conditional jump were
205                                                        ; set with the cmp al,StringsCompressed_FormatsBegin
206
207    mov     dx,DisplayFormatCompressed_BaseFormatOffset   ; calculate address to jump to for format handler
208    sub     dx,ax
209
210    mov     ax,[bp]             ; preload ax with parameter
211    dec     bp                  ; if no parameter is needed (format 'nl' for example),
212    dec     bp                  ; the format handler can reincrement bp
213
214    mov     bx,0500h            ; preload bh with 5 decimal places for numeric output
215                                ; bl is zero, indicating not to output a 'h' (default base 10)
216
217    push    si                  ; preserve si and cx, in the case of outputing a string
218    push    cx
219
220    mov     si,10               ; preload si with 10 for numeric output (default base 10)
221
222    call    dx                  ; call the format routine
223
224    pop     cx                  ; restore cx and si
225    pop     si
226
227    jmp     DisplayFormat_ParseCharacters.process_after_output  ; continue postprocessing, check for end of string
228
Note: See TracBrowser for help on using the repository browser.