source: xtideuniversalbios/tags/v2.0.0_beta_3/Assembly_Library/Src/Display/DisplayFormatCompressed.asm@ 514

Last change on this file since 514 was 505, checked in by krille_n_@…, 11 years ago

Changes:

  • Reverted the changes to MenuEvents.inc done in r492 since they broke the F1 key function in XTIDECFG.
  • Added a tail-call optimized variant of the CALL_DISPLAY_LIBRARY macro (JMP_DISPLAY_LIBRARY).
  • Put a block size limit in AH1Eh_ChangeXTCFmodeBasedOnControlRegisterInAL. I think it's needed but if not, it's easy to remove.
  • Other optimizations and fixes.
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 cmp al, 10 ; Convert binary digit in AL to ASCII hex digit ('0'-'9' or 'A'-'F')
142 sbb al, 69h
143 das
144
145 call DisplayPrint_CharacterFromAL
146
147 jmp .PrintLoop
148
149
150;--------------------------------------------------------------------
151; DisplayFormat_ParseCharacters
152; Parameters:
153; DS: BDA segment (zero)
154; SS:BP: Pointer to first format parameter (-=2 updates to next parameter)
155; CS:SI: Pointer to string to format
156; ES:DI: Ptr to cursor location in video RAM
157; Returns:
158; CS:SI: Ptr to end of format string (ptr to one past NULL)
159; DI: Updated offset to video RAM
160; Corrupts registers:
161; AX, BX, CX, DX, BP
162;--------------------------------------------------------------------
163
164DisplayFormatCompressed_BaseFormatOffset:
165
166DisplayFormat_ParseCharacters_FromAX:
167 mov si,ax
168 ; fall through to DisplayFormat_ParseCharacters
169
170ALIGN DISPLAY_JUMP_ALIGN
171DisplayFormat_ParseCharacters:
172;
173; This routine is used to output all strings from the ROM. The strings in ROMVARS are not compressed,
174; and must be handled differently.
175;
176 cmp si,byte 07fh ; well within the boundaries of ROMVARS_size
177 mov bx,cs ; preload bx with cs in case we take the following jump
178 jb short DisplayPrint_NullTerminatedStringFromBXSI
179
180.decode:
181 cs lodsb ; load next byte of the string
182
183 mov ch,al ; save a copy for later processing of high order bits
184
185 test al,0c0h ; check for translation/format character
186 jz DisplayFormatCompressed_TranslatesAndFormats
187
188 and al,03fh ; "Normal" character, mask off high order bits
189 add al,StringsCompressed_NormalBase ; and add character offset (usually around 0x40)
190
191.output:
192 call DisplayPrint_CharacterFromAL
193
194.process_after_output:
195 eSHL_IM ch,1 ; check high order bits for end of string or space
196 jns short DisplayFormatCompressed_ret
197 jnc .decode
198 mov al,' '
199 call DisplayPrint_CharacterFromAL
200 jmp .decode
201
202
203ALIGN DISPLAY_JUMP_ALIGN
204DisplayFormatCompressed_TranslatesAndFormats:
205;
206; This routine is here (above DisplayFormat_ParseCharacters) to reduce the amount of code between
207; DisplayFormatCompressed_BaseFormatOffset and jump targets (must fit in 256 bytes)
208;
209 eSHL_IM ch,1 ; setup ch for later testing of null in .process_after_output
210 and ax,0001fh ; also clears AH for addition with BX and DX below
211
212 mov bx,StringsCompressed_TranslatesAndFormats ; calculate offset of translation/formats offset byte
213 add bx,ax
214
215 cmp al,StringsCompressed_FormatsBegin ; determine if this is a translation or a format
216
217 mov al,[cs:bx] ; fetch translation/formats byte
218
219 jb DisplayFormat_ParseCharacters.output ; check if this a translation or a format
220 ; if it is translation, output and postprocess for eos
221 ; note that the flags for this conditional jump were
222 ; set with the cmp al,StringsCompressed_FormatsBegin
223
224 mov dx,DisplayFormatCompressed_BaseFormatOffset ; calculate address to jump to for format handler
225 sub dx,ax
226
227 mov ax,[bp] ; preload ax with parameter
228 dec bp ; if no parameter is needed (format 'nl' for example),
229 dec bp ; the format handler can reincrement bp
230
231 mov bx,0500h ; preload bh with 5 decimal places for numeric output
232 ; bl is zero, indicating not to output a 'h' (default base 10)
233
234 push si ; preserve si and cx, in the case of outputing a string
235 push cx
236
237 mov si,10 ; preload si with 10 for numeric output (default base 10)
238
239 call dx ; call the format routine
240
241 pop cx ; restore cx and si
242 pop si
243
244 jmp DisplayFormat_ParseCharacters.process_after_output ; continue postprocessing, check for end of string
245
Note: See TracBrowser for help on using the repository browser.