Subversion Repositories SvarDOS

Rev

Rev 392 | Rev 397 | 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
 
148
/* converts a path to its canonic representation */
149
void file_truename(const char *src, char *dst) {
150
  _asm {
151
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
152
    push ds
153
    pop es
154
    mov si, src
155
    mov di, dst
156
    int 0x21
157
  }
158
}
159
 
160
 
161
/* returns DOS attributes of file, or -1 on error */
162
int file_getattr(const char *fname) {
163
  int res = -1;
164
  _asm {
165
    mov ax, 0x4300  /* query file attributes, fname at DS:DX */
166
    mov dx, fname
167
    int 0x21        /* CX=attributes if CF=0, otherwise AX=errno */
168
    jc DONE
169
    mov [res], cx
170
    DONE:
171
  }
172
  return(res);
173
}
396 mateuszvis 174
 
175
 
176
/* returns screen's width (in columns) */
177
unsigned short screen_getwidth(void) {
178
  /* BIOS 0040:004A = word containing screen width in text columns */
179
  unsigned short far *scrw = MK_FP(0x40, 0x4a);
180
  return(*scrw);
181
}
182
 
183
 
184
/* returns screen's height (in rows) */
185
unsigned short screen_getheight(void) {
186
  /* BIOS 0040:0084 = byte containing maximum valid row value (EGA ONLY) */
187
  unsigned char far *scrh = MK_FP(0x40, 0x84);
188
  if (*scrh == 0) return(25);  /* pre-EGA adapter */
189
  return(*scrh + 1);
190
}
191
 
192
 
193
/* displays the "Press any key to continue" msg and waits for a keypress */
194
void press_any_key(void) {
195
  output("Press any key to continue...");
196
  _asm {
197
    mov ah, 0x08  /* no echo console input */
198
    int 0x21      /* pressed key in AL now (0 for extended keys) */
199
    test al, al
200
    jnz DONE
201
    int 0x21      /* executed ah=8 again to read the rest of extended key */
202
    DONE:
203
    /* output CR/LF */
204
    mov ah, 0x02
205
    mov dl, 0x0D
206
    int 0x21
207
    mov dl, 0x0A
208
    int 0x21
209
  }
210
}