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

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

WIDE checkin... Added copyright and license information to sorce files, as per the GPL instructions for usage.

File size: 9.6 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;
8; XTIDE Universal BIOS and Associated Tools 
9; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
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.
15; 
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
19; GNU General Public License for more details.     
20; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21;
22
23;=============================================================================================
24;
25; Strings are compressed in a simple manner:
26;   1. The two most common characters, space and null, are removed
27;   2. Format specifiers are reduced to a single byte, including length information
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)
32;     11 xxxxxx     Character in x plus StringsCompressed_NormalBase, followed by a space
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
44; which is easy to test for.  The '01' for "normal" (no null or space) and '001' for translates/format "normal"
45; match, allowing the translates/format codes to be shifted left by 1 and then tested with the same instructions.
46;
47; It is always possible to say that a null character follows the current character - thus there is
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;
54
55; Section containing code
56SECTION .text
57
58;--------------------------------------------------------------------
59; Format Handlers
60;
61; Names of format handlers are DisplayFormatCompressed_Format_* where * is
62; replaced with the format code after the '%' in the original string,
63; with '-' replaced with '_'.
64;
65;   Parameters:
66;       DS:     BDA segment (zero)
67;       AX:     Parameter to Format
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
83DisplayFormatCompressed_Format_A:
84    mov     [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute], al
85DisplayFormatCompressed_ret:            ; jump target for other routines who need a "ret"
86    ret
87
88DisplayFormatCompressed_Format_z:
89    xor     bx, bx
90    xchg    si, ax
91    jmp     short DisplayPrint_NullTerminatedStringFromBXSI
92
93DisplayFormatCompressed_Format_x:
94DisplayFormatCompressed_Format_5_x:
95    mov     si,16                       ; hex output, change base to 16
96    mov     bx,(04<<8) + 'h'            ; 4 bytes, with postfix character 'h' to emit
97                                        ; (note that the count includes the 'h')
98    jmp     DisplayFormatCompressed_Format_u
99
100DisplayFormatCompressed_Format_2_I:
101    mov     si,g_szDashForZero          ; preload dash string in case we jump
102    test    ax,ax                       ; if parameter equals zero, emit dash string instead
103    jz      DisplayFormat_ParseCharacters
104    ; fall through
105
106DisplayFormatCompressed_Format_2_u:
107    mov     bh,2                        ; only two characters (instead of the default 5)
108    ; fall through
109
110DisplayFormatCompressed_Format_u:
111DisplayFormatCompressed_Format_5_u:
112    push    bx                          ; push postfix character - either a zero (default) or a 'h'
113    mov     bl,bh                       ; preserve character count for .PrintLoop
114
115.DivLoop:
116    xor     dx, dx                      ; Zero DX for division
117    div     si                          ; DX:AX / 10 => AX=quot, DX=rem
118    push    dx                          ; Push digit
119
120    dec     bh
121    jnz     .DivLoop
122
123.PrintLoop:
124    pop     ax                          ; Pop digit, postfix character on last iteration
125
126    dec     bl                          ; on second to last iteration, emit digit whether it is zero or not
127    jz      .PrintDigit
128
129    js      short DisplayPrint_CharacterFromAL  ; on last iteration, emit postfix character
130                                                ; if it is zero, DisplayPrint_CharacterFromAL will not emit
131
132    or      bh, al                      ; skip leading zeros, bh keeps track if we have emitted anything non-zero
133    jnz     .PrintDigit                 ; note that bh starts at zero, from the loop above
134
135    test    ch,2                        ; are we padding with leading spaces?
136    jnz     .PrintLoop                  ; test the even/odd of the format byte in the string
137
138    mov     al, 89h                     ; emit space
139
140.PrintDigit:
141    add     al, 90h                     ; Convert binary digit in AL to ASCII hex digit (0 - 9 or A - F)
142    daa
143    adc     al, 40h
144    daa
145
146    call    DisplayPrint_CharacterFromAL
147
148    jmp     .PrintLoop
149
150
151;--------------------------------------------------------------------
152; DisplayFormat_ParseCharacters
153;   Parameters:
154;       DS:     BDA segment (zero)
155;       SS:BP:  Pointer to first format parameter (-=2 updates to next parameter)
156;       CS:SI:  Pointer to string to format
157;       ES:DI:  Ptr to cursor location in video RAM
158;   Returns:
159;       CS:SI:  Ptr to end of format string (ptr to one past NULL)
160;       DI:     Updated offset to video RAM
161;   Corrupts registers:
162;       AX, BX, CX, DX, BP
163;--------------------------------------------------------------------
164
165DisplayFormatCompressed_BaseFormatOffset:
166
167DisplayFormat_ParseCharacters_FromAX:
168    mov     si,ax
169    ; fall through to DisplayFormat_ParseCharacters
170
171ALIGN DISPLAY_JUMP_ALIGN
172DisplayFormat_ParseCharacters:
173;
174; This routine is used to output all strings from the ROM.  The strings in ROMVARS are not compressed,
175; and must be handled differently.
176;
177    cmp     si,byte 07fh        ; well within the boundaries of ROMVARS_size
178    mov     bx,cs               ; preload bx with cs in case we take the following jump
179    jb      short DisplayPrint_NullTerminatedStringFromBXSI
180
181.decode:
182    cs lodsb                    ; load next byte of the string
183
184    mov     ch,al               ; save a copy for later processing of high order bits
185
186    test    al,0c0h             ; check for translation/format character
187    jz      DisplayFormatCompressed_TranslatesAndFormats
188
189    and     al,03fh                             ; "Normal" character, mask off high order bits
190    add     al,StringsCompressed_NormalBase     ; and add character offset (usually around 0x40)
191
192.output:
193    call    DisplayPrint_CharacterFromAL
194
195.process_after_output:
196    shl     ch,1                                ; check high order bits for end of string or space
197    jns     short DisplayFormatCompressed_ret
198    jnc     .decode
199    mov     al,' '
200    call    DisplayPrint_CharacterFromAL
201    jmp     .decode
202
203
204ALIGN DISPLAY_JUMP_ALIGN
205DisplayFormatCompressed_TranslatesAndFormats:
206;
207; This routine is here (above DisplayFormat_ParseCharacters) to reduce the amount of code between
208; DisplayFormatCompressed_BaseFormatOffset and jump targets (must fit in 256 bytes)
209;
210    shl     ch,1                ; setup ch for later testing of null in .process_after_output
211    and     ax,0001fh           ; also clears AH for addition with BX and DX below
212
213    mov     bx,StringsCompressed_TranslatesAndFormats   ; calculate offset of translation/formats offset byte
214    add     bx,ax
215
216    cmp     al,StringsCompressed_FormatsBegin           ; determine if this is a translation or a format
217
218    mov     al,[cs:bx]                                  ; fetch translation/formats byte
219
220    jb      DisplayFormat_ParseCharacters.output        ; check if this a translation or a format
221                                                        ; if it is translation, output and postprocess for eos
222                                                        ; note that the flags for this conditional jump were
223                                                        ; set with the cmp al,StringsCompressed_FormatsBegin
224
225    mov     dx,DisplayFormatCompressed_BaseFormatOffset   ; calculate address to jump to for format handler
226    sub     dx,ax
227
228    mov     ax,[bp]             ; preload ax with parameter
229    dec     bp                  ; if no parameter is needed (format 'nl' for example),
230    dec     bp                  ; the format handler can reincrement bp
231
232    mov     bx,0500h            ; preload bh with 5 decimal places for numeric output
233                                ; bl is zero, indicating not to output a 'h' (default base 10)
234
235    push    si                  ; preserve si and cx, in the case of outputing a string
236    push    cx
237
238    mov     si,10               ; preload si with 10 for numeric output (default base 10)
239
240    call    dx                  ; call the format routine
241
242    pop     cx                  ; restore cx and si
243    pop     si
244
245    jmp     DisplayFormat_ParseCharacters.process_after_output  ; continue postprocessing, check for end of string
246
Note: See TracBrowser for help on using the repository browser.