Subversion Repositories SvarDOS

Rev

Rev 1483 | Rev 1485 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1479 mateusz.vi 1
;
1480 mateusz.vi 2
; SvarDOS MORE
1479 mateusz.vi 3
;
4
; Displays output one screen at a time
5
;
6
;  - multilingual (looks up the LANG env variable)
7
;  - tiny (fits in a single disk sector)
8
;
1480 mateusz.vi 9
; This program is part of the SvarDOS project <http://svardos.org>
1479 mateusz.vi 10
;
1480 mateusz.vi 11
; ****************************************************************************
1479 mateusz.vi 12
; *** Distributed under the terms of the MIT LICENSE *************************
1480 mateusz.vi 13
; ****************************************************************************
1479 mateusz.vi 14
;
15
; Copyright (C) 2023 Mateusz Viste
16
;
17
; Permission is hereby granted, free of charge, to any person obtaining a copy
18
; of this software and associated documentation files (the "Software"), to
19
; deal in the Software without restriction, including without limitation the
20
; rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
21
; sell copies of the Software, and to permit persons to whom the Software is
22
; furnished to do so, subject to the following conditions:
23
;
24
; The above copyright notice and this permission notice shall be included in
25
; all copies or substantial portions of the Software.
26
;
27
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32
; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33
; IN THE SOFTWARE.
34
; ****************************************************************************
35
;
36
; To be compiled with the A72 assembler:
37
; A72 MORE.ASM MORE.COM
38
;
39
 
40
 
41
; COM file always has a 100h origin
42
ORG     100h
43
 
44
 
45
; ****************************************************************************
46
; * Display a short help screen if any (non-empty) argument is provided.     *
47
; *                                                                          *
48
; * detect presence of arguments in the command's tail (PSP 81h), looking    *
49
; * at the first non-space character. If it's a CR then no argument (CR is   *
50
; * the tail's terminator).                                                  *
51
; ****************************************************************************
52
mov     ax, ds
53
mov     es, ax
54
mov     al, ' '
55
mov     cx, 0ffh
56
mov     di, 81h
57
repe    scasb                          ; compare AL with [ES:DI++]
58
mov     al, [di-1]
59
 
60
cmp     al, 0Dh
61
je      NO_ARGS
62
 
63
; some arg found: display help and quit
64
mov     ah, 9h
65
mov     dx, offset HELP
66
int     21h
67
int     20h
68
 
1480 mateusz.vi 69
HELP db "SvarDOS MORE 2023.0", 13, 10
1479 mateusz.vi 70
     db 10
71
     db "MORE < README.TXT", 13, 10
1480 mateusz.vi 72
     db "TYPE README.TXT | MORE", 13, 10, '$'
1479 mateusz.vi 73
 
74
NO_ARGS:
75
 
76
 
77
; ****************************************************************************
78
; * detect screen dimensions (max usable row and column)                     *
79
; ****************************************************************************
80
mov     ah, 0Fh                        ; GET CURRENT VIDEO MODE
81
int     10h
82
mov     byte ptr [MAXCOL], ah
83
mov     ax, 40h
84
mov     es, ax
85
mov     ah, [es:84h]                   ; 0040:0084
86
test    ah, ah                         ; ancient PCes do not know this
87
jz      SKIP_ROWS_DETECTION
88
mov     byte ptr [MAXROW], ah
89
 
90
SKIP_ROWS_DETECTION:
91
 
92
 
93
; ****************************************************************************
94
; * Scan the environement block looking for the LANG variable                *
95
; ****************************************************************************
96
 
97
; set ES to point at the environment segment (PSP's offset 2Ch)
98
mov     es, [2Ch]
99
 
100
; compare DS:[SI] with ES:[DI], up to 5 bytes ("LANG=")
101
cld
102
mov     di, 0
103
CMP_NEXT_VAR:
104
 
105
; if it points at a nul already then it's the end of the env block
106
mov     al, [es:di]
107
test    al, al
108
jz      ENDOFENV
109
 
110
mov     si, LANG
111
mov     cx, 5
112
repe    cmpsb
113
 
114
; if CX == 0 then found a LANG= match
115
jcxz    FOUND_LANG
116
 
117
; otherwise jump to next var (look for nearest nul terminator)
118
xor     al, al
119
mov     cx, 0ffffh
120
repne   scasb                          ; compare AL with [ES:DI++]
121
jmp     CMP_NEXT_VAR
122
 
123
; FOUND THE LANG VARIABLE (at ES:DI)
124
FOUND_LANG:
125
 
126
mov     ax, [es:di]                    ; load the LANG ID to AX and make
127
and     ax, 0DFDFh                     ; sure it is always upper case
128
 
129
 
130
; ****************************************************************************
131
; * Now I have a LANG ID in AX and I have to match it for something I know.  *
132
; * The LANG ID is simply the value for the two uppercase LANG letters, for  *
133
; * example the LANG ID for "PL" is 4C50h (50h = 'P', 4Ch = 'L').            *
134
; ****************************************************************************
135
 
136
; DE [44h 45h]
1484 mateusz.vi 137
mov     bp, TEXT_DE
1479 mateusz.vi 138
cmp     ax, 4544h
139
je      LANGOK
140
 
141
; FR [46h 52h]
1484 mateusz.vi 142
mov     bp, TEXT_FR
1479 mateusz.vi 143
cmp     ax, 5246h
144
je      LANGOK
145
 
146
; NL [4Eh 4Ch]
1484 mateusz.vi 147
mov     bp, TEXT_NL
1479 mateusz.vi 148
cmp     ax, 4C4Eh
149
je      LANGOK
150
 
151
; PL [50h 4Ch]
1484 mateusz.vi 152
mov     bp, TEXT_PL
1479 mateusz.vi 153
cmp     ax, 4C50h
154
je      LANGOK
155
 
156
; RU [52h 55h]
1484 mateusz.vi 157
mov     bp, TEXT_RU
1479 mateusz.vi 158
cmp     ax, 5552h
159
je      LANGOK
160
 
161
; TR [54h 52h]
1484 mateusz.vi 162
mov     bp, TEXT_TR
1479 mateusz.vi 163
cmp     ax, 5254h
164
je      LANGOK
165
 
166
 
167
; *** LANG NOT FOUND OR LANG ID MATCH FAILED: FALL BACK TO EN ****************
168
 
169
ENDOFENV:
1484 mateusz.vi 170
mov     bp, TEXT_EN
1479 mateusz.vi 171
 
172
LANGOK:
173
 
174
 
175
; ****************************************************************************
176
; * DUPLICATING HANDLES: here I duplicate stdin into a new handle so I can   *
177
; * safely close original stdin (file handle 0) and then duplicate stderr    *
178
; * into stdin. The purpose of these shenanigans is to be able to cope with  *
179
; * situations when stdin is redirected (eg. with CTTY)                      *
180
; ****************************************************************************
181
 
1484 mateusz.vi 182
; duplicate stdin and keep the new file handle in FHANDLE
1479 mateusz.vi 183
xor     bx, bx
184
mov     ah, 45h
185
int     21h
1484 mateusz.vi 186
mov     [FHANDLE], ax
1479 mateusz.vi 187
 
188
; I can close stdin now
189
mov     ah, 3Eh
190
int     21h
191
 
192
; duplicate stderr to stdin
193
; bx = file handle / cx = file handle to become duplicate of bx
194
mov     ah, 46h
195
mov     bx, 2
196
xor     cx, cx
197
int     21h
198
; ****************************************************************************
199
 
200
 
201
; make sure cursor is on column 0
202
mov ah, 2h                             ; write character in DL to stdout
203
mov dl, 0Dh                            ; carriage return
204
int 21h
205
 
1484 mateusz.vi 206
; reset BX - from now on bh = cur row and bl = cur col
207
xor     bx, bx
1479 mateusz.vi 208
 
209
; consume stdin bytes by loading them into buffer
210
RELOADBUF:
1484 mateusz.vi 211
xchg    di, bx                         ; save BX to DI (contains cur row+col)
1479 mateusz.vi 212
mov     ah, 3Fh                        ; DOS 2+ - read from file or device
1484 mateusz.vi 213
mov     bx, [FHANDLE]                  ; duplicated stdin was saved in FHANDLE
1479 mateusz.vi 214
mov     cx, 1024
215
mov     dx, offset BUFFER
216
int     21h
217
 
218
; abort on error
219
jc EXIT
220
 
1484 mateusz.vi 221
; restore bx
222
xchg    bx, di
223
 
1479 mateusz.vi 224
; did I get any bytes? 0 bytes read means "EOF"
225
test    ax, ax
226
jnz     PREPLOOP
227
 
228
EXIT:
229
int     20h
230
 
231
; prepare the LODSB loop
232
PREPLOOP:
233
mov     cx, ax
234
mov     si, dx
235
 
236
NEXTCHAR:
237
 
238
; AL = DS:[SI++]
239
cld
240
lodsb
241
 
242
; EOF char? (check this first so a short jump to exit is still possible)
243
cmp     al, 1Ah
244
jz      EXIT
245
 
246
; [7h] BELL?
247
cmp     al, 7h
248
je      OUTPUT_CHAR
249
 
250
; [8h] BACKSPACE? moves the cursor back by one column, no effect if it is on
251
; first column already. it does not blank the characters it passes over.
252
cmp     al, 8h
253
jne     NOTBS
1484 mateusz.vi 254
test    bl, bl                         ; am I on on column 0? (bl = cur col)
255
jz      OUTPUT_CHAR
256
dec     bl
1479 mateusz.vi 257
jmp     short OUTPUT_CHAR
258
NOTBS:
259
 
260
; [9h] TAB?
261
cmp     al, 9h
262
jne     NOTTAB
1484 mateusz.vi 263
add     bl, 8                          ; bl = cur col
264
and     bl, 248
1479 mateusz.vi 265
jmp     short OUTPUT_CHAR
266
NOTTAB:
267
 
268
; [0Ah] LF?
269
cmp     al, 0Ah
270
jne     NOTLF
1484 mateusz.vi 271
inc     bh                             ; bh = cur row
1479 mateusz.vi 272
jmp     short OUTPUT_CHAR
273
NOTLF:
274
 
275
; [0Dh] CR?
276
cmp     al, 0Dh
277
jnz     NOTCR
1484 mateusz.vi 278
xor     bl, bl                         ; bl = cur col
1479 mateusz.vi 279
jmp     short OUTPUT_CHAR
280
NOTCR:
281
 
282
; otherwise: increment cur column, and then maybe cur row
1484 mateusz.vi 283
inc     bl                             ; bl = cur col
284
cmp     bl, [MAXCOL]
1479 mateusz.vi 285
jb      OUTPUT_CHAR
1484 mateusz.vi 286
inc     bh                             ; bh = cur row
287
xor     bl, bl                         ; bl = cur col
1479 mateusz.vi 288
 
289
OUTPUT_CHAR:
290
mov     dl, al
291
mov     ah, 2h
292
int     21h
1484 mateusz.vi 293
cmp     bh, [MAXROW]                   ; bh = cur row
1479 mateusz.vi 294
jae     PRESSANYKEY
295
 
296
CHARLOOP:
297
loop    NEXTCHAR                       ; dec cx and jmp to NEXTCHAR if cx > 0
298
jmp     RELOADBUF
299
 
300
 
1482 mateusz.vi 301
; display " --- More ---"
1479 mateusz.vi 302
PRESSANYKEY:
303
mov     ah, 9h                         ; disp $-termin. string pointed by DX
1482 mateusz.vi 304
mov     dx, offset SEPAR1
1479 mateusz.vi 305
int     21h
1484 mateusz.vi 306
mov     dx, bp
1479 mateusz.vi 307
int     21h
1482 mateusz.vi 308
mov     dx, offset SEPAR2
309
int     21h
1479 mateusz.vi 310
 
1483 mateusz.vi 311
; wait for a keypress
312
mov     ah, 08h                        ; read char from stdin, no echo
1479 mateusz.vi 313
int     21h
1483 mateusz.vi 314
; read again if an extended key was pressed
315
test    al, al
316
jnz     GETKEY_DONE
317
int     21h
318
GETKEY_DONE:
1479 mateusz.vi 319
 
320
; output a CR/LF pair and reset counters
321
mov     dx, offset CRLF
322
mov     ah, 9h
323
int     21h
1484 mateusz.vi 324
xor     bx, bx                         ; bh = cur row, bl = cur col
1479 mateusz.vi 325
jmp     CHARLOOP
326
 
327
 
328
; ****************************************************************************
329
; * DATA                                                                     *
330
; ****************************************************************************
331
 
332
MAXROW  db      24                     ; maximum *addressable* row (not total)
333
MAXCOL  db      80                     ; total available columns
334
 
335
CRLF DB 13, 10, '$'
336
LANG DB "LANG="
1482 mateusz.vi 337
SEPAR1 DB "--- $"
338
SEPAR2 DB " ---$"
1479 mateusz.vi 339
 
340
TEXT_DE DB "WEITER$"
341
TEXT_EN DB "MORE$"
342
TEXT_FR DB "PLUS$"
343
TEXT_NL DB "MEER$"
344
TEXT_PL DB "DALEJ$"
1480 mateusz.vi 345
TEXT_RU DB 84h,80h,8Bh,85h,85h,'$'     ; "DALEE" (CP 866)
1479 mateusz.vi 346
TEXT_TR DB "DAHA FAZLA$"
347
 
1484 mateusz.vi 348
; uninitialized area (must be defined last)
349
 
350
FHANDLE dw      ?                      ; file handle I read from (DUPed stdin)
351
 
1479 mateusz.vi 352
BUFFER: