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

Last change on this file since 318 was 241, checked in by gregli@…, 13 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
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
[241]70DisplayFormatCompressed_Format_z:
71 xor bx, bx
72 xchg si, ax
73 jmp short DisplayPrint_NullTerminatedStringFromBXSI
74
[186]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
[194]86 ; fall through
[202]87
[186]88DisplayFormatCompressed_Format_2_u:
89 mov bh,2 ; only two characters (instead of the default 5)
[194]90 ; fall through
[202]91
[186]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
[202]101
102 dec bh
[186]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
[202]114 or bh, al ; skip leading zeros, bh keeps track if we have emitted anything non-zero
[195]115 jnz .PrintDigit ; note that bh starts at zero, from the loop above
[186]116
[202]117 test ch,2 ; are we padding with leading spaces?
[186]118 jnz .PrintLoop ; test the even/odd of the format byte in the string
119
[202]120 mov al, 89h ; emit space
[186]121
[202]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
[186]127
128 call DisplayPrint_CharacterFromAL
129
130 jmp .PrintLoop
131
[202]132
[186]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
[202]145;--------------------------------------------------------------------
[186]146
[194]147DisplayFormatCompressed_BaseFormatOffset:
[202]148
[194]149DisplayFormat_ParseCharacters_FromAX:
[186]150 mov si,ax
[194]151 ; fall through to DisplayFormat_ParseCharacters
[186]152
[202]153ALIGN JUMP_ALIGN
154DisplayFormat_ParseCharacters:
[186]155;
[202]156; This routine is used to output all strings from the ROM. The strings in ROMVARS are not compressed,
[186]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:
[223]164 cs lodsb ; load next byte of the string
[186]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)
[202]173
[186]174.output:
[202]175 call DisplayPrint_CharacterFromAL
[186]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
[202]187DisplayFormatCompressed_TranslatesAndFormats:
[186]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
[202]199
[186]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
[202]206
[186]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.