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

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

Changes:

  • Fixed what appears to be a mistake in EBIOS.inc
  • Added a 'release' option to the makefile of the Serial Server (invokes UPX)
  • Some very minor optimizations
  • Removed the eSEG macro and did some other cleanups (fixed typos etc)
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    cs lodsb                    ; load next byte of the string
160
161    mov     ch,al               ; save a copy for later processing of high order bits
162
163    test    al,0c0h             ; check for translation/format character
164    jz      DisplayFormatCompressed_TranslatesAndFormats
165
166    and     al,03fh                             ; "Normal" character, mask off high order bits
167    add     al,StringsCompressed_NormalBase     ; and add character offset (usually around 0x40)
168
169.output:
170    call    DisplayPrint_CharacterFromAL
171
172.process_after_output:
173    shl     ch,1                                ; check high order bits for end of string or space
174    jns     short DisplayFormatCompressed_ret
175    jnc     .decode
176    mov     al,' '
177    call    DisplayPrint_CharacterFromAL
178    jmp     .decode
179
180
181ALIGN JUMP_ALIGN
182DisplayFormatCompressed_TranslatesAndFormats:
183;
184; This routine is here (above DisplayFormat_ParseCharacters) to reduce the amount of code between
185; DisplayFormatCompressed_BaseFormatOffset and jump targets (must fit in 256 bytes)
186;
187    shl     ch,1                ; setup ch for later testing of null in .process_after_output
188    and     ax,0001fh           ; also clears AH for addition with BX and DX below
189
190    mov     bx,StringsCompressed_TranslatesAndFormats   ; calculate offset of translation/formats offset byte
191    add     bx,ax
192
193    cmp     al,StringsCompressed_FormatsBegin           ; determine if this is a translation or a format
194
195    mov     al,[cs:bx]                                  ; fetch translation/formats byte
196
197    jb      DisplayFormat_ParseCharacters.output        ; check if this a translation or a format
198                                                        ; if it is translation, output and postprocess for eos
199                                                        ; note that the flags for this conditional jump were
200                                                        ; set with the cmp al,StringsCompressed_FormatsBegin
201
202    mov     dx,DisplayFormatCompressed_BaseFormatOffset   ; calculate address to jump to for format handler
203    sub     dx,ax
204
205    mov     ax,[bp]             ; preload ax with parameter
206    dec     bp                  ; if no parameter is needed (format 'nl' for example),
207    dec     bp                  ; the format handler can reincrement bp
208
209    mov     bx,0500h            ; preload bh with 5 decimal places for numeric output
210                                ; bl is zero, indicating not to output a 'h' (default base 10)
211
212    push    si                  ; preserve si and cx, in the case of outputing a string
213    push    cx
214
215    mov     si,10               ; preload si with 10 for numeric output (default base 10)
216
217    call    dx                  ; call the format routine
218
219    pop     cx                  ; restore cx and si
220    pop     si
221
222    jmp     DisplayFormat_ParseCharacters.process_after_output  ; continue postprocessing, check for end of string
223
Note: See TracBrowser for help on using the repository browser.