Subversion Repositories SvarDOS

Rev

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

Rev Author Line No. Line
352 mateuszvis 1
/*
2
 * a variety of helper functions
3
 * Copyright (C) 2021 Mateusz Viste
4
 */
5
 
396 mateuszvis 6
#include <i86.h>    /* MK_FP() */
7
 
352 mateuszvis 8
#include "helpers.h"
9
 
10
/* case-insensitive comparison of strings, returns non-zero on equality */
11
int imatch(const char *s1, const char *s2) {
12
  for (;;) {
13
    char c1, c2;
14
    c1 = *s1;
15
    c2 = *s2;
16
    if ((c1 >= 'a') && (c1 <= 'z')) c1 -= ('a' - 'A');
17
    if ((c2 >= 'a') && (c2 <= 'z')) c2 -= ('a' - 'A');
18
    /* */
19
    if (c1 != c2) return(0);
20
    if (c1 == 0) return(1);
21
    s1++;
22
    s2++;
23
  }
24
}
25
 
26
 
27
/* returns zero if s1 starts with s2 */
28
int strstartswith(const char *s1, const char *s2) {
29
  while (*s2 != 0) {
30
    if (*s1 != *s2) return(-1);
31
    s1++;
32
    s2++;
33
  }
34
  return(0);
35
}
369 mateuszvis 36
 
37
 
38
/* outputs a NULL-terminated string to stdout */
39
void output_internal(const char *s, unsigned short nl) {
40
  _asm {
41
    mov ah, 0x02 /* AH=9 - write character in DL to stdout */
42
    mov si, s
43
    cld          /* clear DF so lodsb increments SI */
44
    NEXTBYTE:
45
    lodsb /* load byte from DS:SI into AL, SI++ */
46
    mov dl, al
47
    or al, 0  /* is al == 0? */
48
    jz DONE
49
    int 0x21
50
    jmp NEXTBYTE
51
    DONE:
52
    or nl, 0
53
    jz FINITO
54
    /* print out a CR/LF trailer if nl set */
55
    mov dl, 0x0D /* CR */
56
    int 0x21
57
    mov dl, 0x0A /* LF */
58
    int 0x21
59
    FINITO:
60
  }
61
}
388 mateuszvis 62
 
63
 
64
/* find first matching files using a FindFirst DOS call
65
 * returns 0 on success or a DOS err code on failure */
66
unsigned short findfirst(struct DTA *dta, const char *pattern, unsigned short attr) {
67
  unsigned short res = 0;
68
  _asm {
69
    /* set DTA location */
70
    mov ah, 0x1a
71
    mov dx, dta
72
    int 0x21
73
    /* */
74
    mov ah, 0x4e    /* FindFirst */
75
    mov dx, pattern
76
    mov cx, attr
77
    int 0x21        /* CF set on error + err code in AX, DTA filled with FileInfoRec on success */
78
    jnc DONE
79
    mov [res], ax
80
    DONE:
81
  }
82
  return(res);
83
}
84
 
85
 
86
/* find next matching, ie. continues an action intiated by findfirst() */
87
unsigned short findnext(struct DTA *dta) {
88
  unsigned short res = 0;
89
  _asm {
90
    mov ah, 0x4f    /* FindNext */
91
    mov dx, dta
92
    int 0x21        /* CF set on error + err code in AX, DTA filled with FileInfoRec on success */
93
    jnc DONE
94
    mov [res], ax
95
    DONE:
96
  }
97
  return(res);
98
}
392 mateuszvis 99
 
100
 
101
/* print s string and wait for a single key press from stdin. accepts only
102
 * key presses defined in the c ASCIIZ string. returns offset of pressed key
103
 * in string. keys in c MUST BE UPPERCASE! */
104
unsigned short askchoice(const char *s, const char *c) {
105
  unsigned short res;
106
  char key = 0;
107
 
108
  AGAIN:
109
  output(s);
110
  output(" ");
111
 
112
  _asm {
113
    push ax
114
    push dx
115
 
116
    mov ax, 0x0c01 /* clear input buffer and execute getchar (INT 21h,AH=1) */
117
    int 0x21
118
    /* if AL == 0 then this is an extended character */
119
    test al, al
120
    jnz GOTCHAR
121
    mov ah, 0x08   /* read again to flush extended char from input buffer */
122
    int 0x21
123
    xor al, al     /* all extended chars are ignored */
124
    GOTCHAR:       /* received key is in AL now */
125
    mov [key], al  /* save key */
126
 
127
    /* print a cr/lf */
128
    mov ah, 0x02
129
    mov dl, 0x0D
130
    int 0x21
131
    mov dl, 0x0A
132
    int 0x21
133
 
134
    pop dx
135
    pop ax
136
  }
137
 
138
  /* ucase() result */
139
  if ((key >= 'a') && (key <= 'z')) key -= ('a' - 'A');
140
 
141
  /* is there a match? */
142
  for (res = 0; c[res] != 0; res++) if (c[res] == key) return(res);
143
 
144
  goto AGAIN;
145
}
146
 
147
 
399 mateuszvis 148
/* converts a path to its canonic representation, returns 0 on success
149
 * or DOS err on failure (invalid drive) */
150
unsigned short file_truename(const char *src, char *dst) {
151
  unsigned short res = 0;
392 mateuszvis 152
  _asm {
399 mateuszvis 153
    push es
392 mateuszvis 154
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
155
    push ds
156
    pop es
157
    mov si, src
158
    mov di, dst
159
    int 0x21
399 mateuszvis 160
    jnc DONE
161
    mov [res], ax
162
    DONE:
163
    pop es
392 mateuszvis 164
  }
399 mateuszvis 165
  return(res);
392 mateuszvis 166
}
167
 
168
 
169
/* returns DOS attributes of file, or -1 on error */
170
int file_getattr(const char *fname) {
171
  int res = -1;
172
  _asm {
173
    mov ax, 0x4300  /* query file attributes, fname at DS:DX */
174
    mov dx, fname
175
    int 0x21        /* CX=attributes if CF=0, otherwise AX=errno */
176
    jc DONE
177
    mov [res], cx
178
    DONE:
179
  }
180
  return(res);
181
}
396 mateuszvis 182
 
183
 
184
/* returns screen's width (in columns) */
185
unsigned short screen_getwidth(void) {
186
  /* BIOS 0040:004A = word containing screen width in text columns */
187
  unsigned short far *scrw = MK_FP(0x40, 0x4a);
188
  return(*scrw);
189
}
190
 
191
 
192
/* returns screen's height (in rows) */
193
unsigned short screen_getheight(void) {
194
  /* BIOS 0040:0084 = byte containing maximum valid row value (EGA ONLY) */
195
  unsigned char far *scrh = MK_FP(0x40, 0x84);
196
  if (*scrh == 0) return(25);  /* pre-EGA adapter */
197
  return(*scrh + 1);
198
}
199
 
200
 
201
/* displays the "Press any key to continue" msg and waits for a keypress */
202
void press_any_key(void) {
203
  output("Press any key to continue...");
204
  _asm {
205
    mov ah, 0x08  /* no echo console input */
206
    int 0x21      /* pressed key in AL now (0 for extended keys) */
207
    test al, al
208
    jnz DONE
209
    int 0x21      /* executed ah=8 again to read the rest of extended key */
210
    DONE:
211
    /* output CR/LF */
212
    mov ah, 0x02
213
    mov dl, 0x0D
214
    int 0x21
215
    mov dl, 0x0A
216
    int 0x21
217
  }
218
}
399 mateuszvis 219
 
220
 
221
/* validate a drive (A=0, B=1, etc). returns 1 if valid, 0 otherwise */
222
int isdrivevalid(unsigned char drv) {
223
  _asm {
224
    mov ah, 0x19  /* query default (current) disk */
225
    int 0x21      /* drive in AL (0=A, 1=B, etc) */
226
    mov ch, al    /* save current drive to ch */
227
    /* try setting up the drive as current */
228
    mov ah, 0x0E   /* select default drive */
229
    mov dl, [drv]  /* 0=A, 1=B, etc */
230
    int 0x21
231
    /* this call does not set CF on error, I must check cur drive to look for success */
232
    mov ah, 0x19  /* query default (current) disk */
233
    int 0x21      /* drive in AL (0=A, 1=B, etc) */
234
    mov [drv], 1  /* preset result as success */
235
    cmp al, dl    /* is eq? */
236
    je DONE
237
    mov [drv], 0  /* fail */
238
    jmp FAILED
239
    DONE:
240
    /* set current drive back to what it was initially */
241
    mov ah, 0x0E
242
    mov dl, ch
243
    int 0x21
244
    FAILED:
245
  }
246
  return(drv);
247
}