source: xtideuniversalbios/trunk/Configurator/Src/Libraries/menu/menumsg.asm @ 181

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

Changes to all parts of the project:

  • Size optimizations.
  • Added a define (EXCLUDE_FROM_XTIDECFG) to exclude unused library code from XTIDECFG.
  • Tried to minimize time spent with interrupts disabled.
  • Some minor attempts to improve speed (reordering instructions etc).
  • Tried to improve readability, did some cleanup and fixed some errors in comments.
File size: 8.7 KB
Line 
1; Project name  :   Menu library
2; Description   :   ASM library for menu system.
3;                   Contains functions for displaying messages.
4
5;--------------- Equates -----------------------------
6
7; Control characters for Menu Message string.
8; Normal control characters cannot be used since message string
9; will be tokenized and converted to menuitems.
10%define MNU_NL          " |n "  ; Menu newline defined as token string
11W_MNU_NL            EQU "|n"    ; Menu newline defined as WORD
12
13; Total border chars on left and right side of string menuitem
14SIZE_MSG_HBRDR      EQU     4   ; Horizontal border size
15
16; Message variables. This is an expanded MENUVARS struct.
17struc MSGVARS
18    .menuVars   resb    MENUVARS_size
19    .dwStrPtr:                  ; Far pointer to string to display
20    .wStrOff:   resb    2       ; Offset to string to display
21    .wStrSeg:   resb    2       ; Segment to string to display
22endstruc
23
24
25;-------------- Private global variables -------------
26; Section containing initialized data
27;SECTION .data
28
29
30;-------------- Public functions ---------------------
31; Section containing code
32SECTION .text
33
34;--------------------------------------------------------------------
35; Displays message string.
36;
37; MenuMsg_ShowMessage
38;   Parameters:
39;       BL:     Dialog width with borders included
40;       SS:BP:  Ptr to MENUVARS
41;       ES:DI:  Ptr to STOP terminated string to display
42;   Returns:
43;       Nothing
44;   Corrupts registers:
45;       AX, BX, CX, DX
46;--------------------------------------------------------------------
47ALIGN JUMP_ALIGN
48MenuMsg_ShowMessage:
49    ; Create stack frame
50    eENTER  MSGVARS_size, 0
51    sub     bp, MSGVARS_size                ; Point to MSGVARS
52
53    ; Initialize menu variables
54    mov     [bp+MENUVARS.bWidth], bl        ; Menu size
55    mov     WORD [bp+MENUVARS.wTopDwnH], 0  ; Title and Info size
56    mov     WORD [bp+MENUVARS.fnEvent], MenuMsg_MsgEvent
57    mov     [bp+MSGVARS.wStrOff], di        ; Store far ptr...
58    mov     [bp+MSGVARS.wStrSeg], es        ; ...to string to display
59
60    ; Enter menu
61    call    MenuMsg_GetLineCnt              ; Get message line count to CX
62    mov     ax, CNT_SCRN_ROW-2              ; Load max line rows to AX
63    MIN_U   ax, cx                          ; String lines to display to AX
64    times 2 inc ax                          ; Include borders for dlg height
65    mov     [bp+MENUVARS.bHeight], al       ; Store dialog height
66    call    MenuCrsr_GetCenter              ; Get X and Y coordinates to DX
67    xor     ax, ax                          ; Selection timeout (disable)
68    mov     bl, FLG_MNU_NOARRW              ; Menu flags
69    call    Menu_Init                       ; Returns only after dlg closed
70
71    ; Return
72    add     bp, MSGVARS_size                ; Point to old BP
73    eLEAVE                                  ; Destroy stack frame
74    ret
75
76
77;-------------- Private functions ---------------------
78
79;--------------------------------------------------------------------
80; Calculates number of string lines needed by string to display.
81;
82; MenuMsg_GetLineCnt
83;   Parameters:
84;       SS:BP:  Ptr to MSGVARS
85;       ES:DI:  Ptr to STOP terminated string to display
86;   Returns:
87;       CX:     Number of lines needed
88;   Corrupts registers:
89;       AX, BX, DX
90;--------------------------------------------------------------------
91ALIGN JUMP_ALIGN
92MenuMsg_GetLineCnt:
93    push    di
94
95    ; Get index for last line
96    mov     cx, -1                  ; Get last possible line
97    call    MenuMsg_GetTokenForLine
98    inc     cx                      ; Last index to line count
99
100    ; Return
101    pop     di
102    ret
103
104
105;--------------------------------------------------------------------
106; Check if line has space for token.
107;
108; MenuMsg_HasLineSpace
109;   Parameters:
110;       AX:     Token length in characters
111;       DX:     Characters left on line
112;       ES:DI:  Ptr to token string (not terminated!)
113;   Returns:
114;       DX:     Chars left after token + space at the end
115;       CF:     Set if space left for token
116;               Cleared if not enough space
117;   Corrupts registers:
118;       Nothing
119;--------------------------------------------------------------------
120ALIGN JUMP_ALIGN
121MenuMsg_HasLineSpace:
122    sub     dx, ax
123    jl      .NoSpace
124    cmp     WORD [es:di], W_MNU_NL  ; Newline token?
125    je      .NoSpace                ;  If so, end line
126    dec     dx                      ; Decrement for space after token
127    stc                             ; Set CF since space left
128    ret
129ALIGN JUMP_ALIGN
130.NoSpace:
131    xor     dx, dx                  ; Clear space left and CF
132    ret
133
134
135;--------------------------------------------------------------------
136; Return pointer to first token for wanted message line.
137;
138; MenuMsg_GetTokenForLine
139;   Parameters:
140;       CX:     Line index
141;       ES:DI:  Ptr to STOP terminated string to display
142;       SS:BP:  Ptr to MSGVARS
143;   Returns:
144;       AX:     Length of first token in characters
145;       CX:     Index of last line found (if wanted line not found)
146;       ES:DI:  Ptr to token
147;       CF:     Set if message line found
148;               Cleared if message line not found
149;   Corrupts registers:
150;       BX, DX
151;--------------------------------------------------------------------
152ALIGN JUMP_ALIGN
153MenuMsg_GetTokenForLine:
154    jcxz    .GetFirst           ; Line 0 wanted? If so, just get token length
155    push    bp
156    push    si
157
158    ; Prepare to scan tokens
159    eMOVZX  si, [bp+MENUVARS.bWidth]
160    sub     si, SIZE_MSG_HBRDR  ; Max number of chars per line
161    mov     dx, si              ; Initialize chars left on line
162    mov     bp, cx              ; Copy line index to BP
163    xor     bx, bx              ; Zero line index counter
164    xor     ax, ax              ; Zero token length
165
166    ; Scan all tokens to calculate lines needed
167ALIGN JUMP_ALIGN
168.TokenLoop:
169    ; Get token and length
170    xor     cx, cx              ; Always read token at index 0
171    add     di, ax              ; Increment offset for next token
172    call    String_StrToken     ; Get token length to AX, ptr to ES:DI
173    jnc     .Return             ; Return if no more tokens (CF cleared)
174    ; Check does line have space left for token
175    call    MenuMsg_HasLineSpace
176    jc      .TokenLoop          ; Space left, check next token
177    ; Change to next line
178    mov     dx, si              ; Copy max chars on line
179    call    MenuMsg_HasLineSpace; Update chars left
180    inc     bx                  ; Increment line index
181    cmp     bx, bp              ; Correct line found?
182    jne     .TokenLoop          ;  If not, check more tokens
183    stc                         ; Set CF since line found
184ALIGN JUMP_ALIGN
185.Return:
186    mov     cx, bx              ; Copy idx of last line found to CX
187    pop     si
188    pop     bp
189    ret
190ALIGN JUMP_ALIGN
191.GetFirst:
192    jmp     String_StrToken     ; Get token length to AX, ptr to ES:DI
193
194
195;--------------------------------------------------------------------
196; Message dialog menu event handler.
197;
198; MenuMsg_WriteLine
199;   Parameters:
200;       CX:     Index of line to display
201;       ES:DI:  Ptr to STOP terminated string to display
202;       SS:BP:  Ptr to MSGVARS
203;   Returns:
204;       CF:     Set if end of string
205;               Cleared if string has unwritten tokens
206;   Corrupts registers:
207;       AX, BX, CX, DX
208;--------------------------------------------------------------------
209ALIGN JUMP_ALIGN
210MenuMsg_WriteLine:
211    push    di
212    call    MenuMsg_GetTokenForLine         ; Get ptr to first token, length to AX
213    jnc     .EndOfString                    ; Return if no tokens
214    eMOVZX  dx, BYTE [bp+MENUVARS.bWidth]   ; Menu width
215    sub     dl, SIZE_MSG_HBRDR              ; To line length
216    mov     bl, ' '                         ; Space character
217ALIGN JUMP_ALIGN
218.PrintToken:
219    ; Check if space for token
220    call    MenuMsg_HasLineSpace    ; Space left on line?
221    jnc     .PrintDone              ;  If not, all done
222    ; Print token
223    push    ax                      ; Store token length
224    mov     cx, ax                  ; Copy token length to CX
225    call    Print_CharBuffer        ; Print token
226    xchg    dx, bx                  ; Space char to DL
227    PRINT_CHAR
228    xchg    dx, bx                  ; Restore DX
229    pop     ax                      ; Pop token length
230    ; Get next token
231    add     di, ax                  ; Point to next token
232    xor     cx, cx                  ; Get token at index 0
233    call    String_StrToken         ; Get next token to ES:DI, len to AX
234    jc      .PrintToken             ; Print while tokens left
235ALIGN JUMP_ALIGN
236.EndOfString:   ; Last token written
237    stc
238ALIGN JUMP_ALIGN
239.PrintDone:     ; End of line but tokens left
240    pop     di
241    ret
242
243
244;--------------------------------------------------------------------
245; Message dialog menu event handler.
246;
247; MenuMsg_MsgEvent
248;   Parameters:
249;       BX:     Callback event
250;       CX:     Selected menuitem index
251;       DX:     Event parameter (event specific)
252;       SS:BP:  Ptr to MSGVARS
253;   Returns:
254;       AH:     Event specific or unused
255;       AL:     1=Event processed
256;               0=Event not processed (default action if any)
257;   Corrupts registers:
258;       BX, CX, DX
259;--------------------------------------------------------------------
260ALIGN JUMP_ALIGN
261MenuMsg_MsgEvent:
262    cmp     bx, EVNT_MMU_SELCHG     ; Selection changed?
263    je      .RetProcessed           ;  If so, return
264    cmp     bx, EVNT_MNU_SELSET     ; Enter to close dialog?
265    je      .CloseDialog            ;  If so, jump to close dialog
266    cmp     bx, EVNT_MNU_UPD        ; Draw menuitem string?
267    je      .DrawLine               ;  If so, jump to draw
268    cmp     bx, EVNT_MNU_KEY        ; Any key pressed to close dialog?
269    jne     .RetUnhandled           ;  If not, ignore message
270
271    ; Close dialog since key pressed
272ALIGN JUMP_ALIGN
273.CloseDialog:
274    or      BYTE [bp+MENUVARS.bFlags], FLG_MNU_EXIT ; Any key, exit
275ALIGN JUMP_ALIGN
276.RetUnhandled:
277    xor     ax, ax
278    ret
279
280ALIGN JUMP_ALIGN
281.DrawLine:
282    push    es
283    push    di
284
285    ; Print string line
286    mov     di, [bp+MSGVARS.wStrOff]; Load string offset
287    mov     es, [bp+MSGVARS.wStrSeg]; Load string segment
288    call    MenuMsg_WriteLine
289    pop     di
290    pop     es
291ALIGN JUMP_ALIGN
292.RetProcessed:
293    mov     ax, 1                   ; Event processed
294    ret
Note: See TracBrowser for help on using the repository browser.