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

Last change on this file since 227 was 223, checked in by krille_n_@…, 13 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
RevLine 
[186]1; Project name : Assembly Library
2; Description : Functions for displaying formatted strings.
[202]3; ** Compressed Strings edition **
4; This is a plug replacement for DisplayFormat.asm,
5; working instead with precompiled and slightly compressed strings.
[186]6;
7; Strings are compressed in a simple manner:
8; 1. The two most common characters, space and null, are removed
[202]9; 2. Format specifiers are reduced to a single byte, including length information
[186]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)
[202]14; 11 xxxxxx Character in x plus StringsCompressed_NormalBase, followed by a space
[186]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
[202]26; which is easy to test for. The '01' for "normal" (no null or space) and '001' for translates/format "normal"
[186]27; match, allowing the translates/format codes to be shifted left by 1 and then tested with the same instructions.
28;
[202]29; It is always possible to say that a null character follows the current character - thus there is
[186]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;
[202]36
[186]37; Section containing code
38SECTION .text
39
40;--------------------------------------------------------------------
41; Format Handlers
42;
43; Names of format handlers are DisplayFormatCompressed_Format_* where * is
[202]44; replaced with the format code after the '%' in the original string,
[186]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
[194]65DisplayFormatCompressed_Format_A:
[186]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
[194]81 ; fall through
[202]82
[186]83DisplayFormatCompressed_Format_2_u:
84 mov bh,2 ; only two characters (instead of the default 5)
[194]85 ; fall through
[202]86
[186]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
[202]96
97 dec bh
[186]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
[202]109 or bh, al ; skip leading zeros, bh keeps track if we have emitted anything non-zero
[195]110 jnz .PrintDigit ; note that bh starts at zero, from the loop above
[186]111
[202]112 test ch,2 ; are we padding with leading spaces?
[186]113 jnz .PrintLoop ; test the even/odd of the format byte in the string
114
[202]115 mov al, 89h ; emit space
[186]116
[202]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
[186]122
123 call DisplayPrint_CharacterFromAL
124
125 jmp .PrintLoop
126
[202]127
[186]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
[202]140;--------------------------------------------------------------------
[186]141
[194]142DisplayFormatCompressed_BaseFormatOffset:
[202]143
[194]144DisplayFormat_ParseCharacters_FromAX:
[186]145 mov si,ax
[194]146 ; fall through to DisplayFormat_ParseCharacters
[186]147
[202]148ALIGN JUMP_ALIGN
149DisplayFormat_ParseCharacters:
[186]150;
[202]151; This routine is used to output all strings from the ROM. The strings in ROMVARS are not compressed,
[186]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:
[223]159 cs lodsb ; load next byte of the string
[186]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)
[202]168
[186]169.output:
[202]170 call DisplayPrint_CharacterFromAL
[186]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
[202]182DisplayFormatCompressed_TranslatesAndFormats:
[186]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
[202]194
[186]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
[202]201
[186]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.