Subversion Repositories SvarDOS

Rev

Rev 392 | Rev 397 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 392 Rev 396
1
/*
1
/*
2
 * a variety of helper functions
2
 * a variety of helper functions
3
 * Copyright (C) 2021 Mateusz Viste
3
 * Copyright (C) 2021 Mateusz Viste
4
 */
4
 */
5
 
5
 
-
 
6
#include <i86.h>    /* MK_FP() */
-
 
7
 
6
#include "helpers.h"
8
#include "helpers.h"
7
 
9
 
8
/* case-insensitive comparison of strings, returns non-zero on equality */
10
/* case-insensitive comparison of strings, returns non-zero on equality */
9
int imatch(const char *s1, const char *s2) {
11
int imatch(const char *s1, const char *s2) {
10
  for (;;) {
12
  for (;;) {
11
    char c1, c2;
13
    char c1, c2;
12
    c1 = *s1;
14
    c1 = *s1;
13
    c2 = *s2;
15
    c2 = *s2;
14
    if ((c1 >= 'a') && (c1 <= 'z')) c1 -= ('a' - 'A');
16
    if ((c1 >= 'a') && (c1 <= 'z')) c1 -= ('a' - 'A');
15
    if ((c2 >= 'a') && (c2 <= 'z')) c2 -= ('a' - 'A');
17
    if ((c2 >= 'a') && (c2 <= 'z')) c2 -= ('a' - 'A');
16
    /* */
18
    /* */
17
    if (c1 != c2) return(0);
19
    if (c1 != c2) return(0);
18
    if (c1 == 0) return(1);
20
    if (c1 == 0) return(1);
19
    s1++;
21
    s1++;
20
    s2++;
22
    s2++;
21
  }
23
  }
22
}
24
}
23
 
25
 
24
 
26
 
25
/* returns zero if s1 starts with s2 */
27
/* returns zero if s1 starts with s2 */
26
int strstartswith(const char *s1, const char *s2) {
28
int strstartswith(const char *s1, const char *s2) {
27
  while (*s2 != 0) {
29
  while (*s2 != 0) {
28
    if (*s1 != *s2) return(-1);
30
    if (*s1 != *s2) return(-1);
29
    s1++;
31
    s1++;
30
    s2++;
32
    s2++;
31
  }
33
  }
32
  return(0);
34
  return(0);
33
}
35
}
34
 
36
 
35
 
37
 
36
/* outputs a NULL-terminated string to stdout */
38
/* outputs a NULL-terminated string to stdout */
37
void output_internal(const char *s, unsigned short nl) {
39
void output_internal(const char *s, unsigned short nl) {
38
  _asm {
40
  _asm {
39
    mov ah, 0x02 /* AH=9 - write character in DL to stdout */
41
    mov ah, 0x02 /* AH=9 - write character in DL to stdout */
40
    mov si, s
42
    mov si, s
41
    cld          /* clear DF so lodsb increments SI */
43
    cld          /* clear DF so lodsb increments SI */
42
    NEXTBYTE:
44
    NEXTBYTE:
43
    lodsb /* load byte from DS:SI into AL, SI++ */
45
    lodsb /* load byte from DS:SI into AL, SI++ */
44
    mov dl, al
46
    mov dl, al
45
    or al, 0  /* is al == 0? */
47
    or al, 0  /* is al == 0? */
46
    jz DONE
48
    jz DONE
47
    int 0x21
49
    int 0x21
48
    jmp NEXTBYTE
50
    jmp NEXTBYTE
49
    DONE:
51
    DONE:
50
    or nl, 0
52
    or nl, 0
51
    jz FINITO
53
    jz FINITO
52
    /* print out a CR/LF trailer if nl set */
54
    /* print out a CR/LF trailer if nl set */
53
    mov dl, 0x0D /* CR */
55
    mov dl, 0x0D /* CR */
54
    int 0x21
56
    int 0x21
55
    mov dl, 0x0A /* LF */
57
    mov dl, 0x0A /* LF */
56
    int 0x21
58
    int 0x21
57
    FINITO:
59
    FINITO:
58
  }
60
  }
59
}
61
}
60
 
62
 
61
 
63
 
62
/* find first matching files using a FindFirst DOS call
64
/* find first matching files using a FindFirst DOS call
63
 * returns 0 on success or a DOS err code on failure */
65
 * returns 0 on success or a DOS err code on failure */
64
unsigned short findfirst(struct DTA *dta, const char *pattern, unsigned short attr) {
66
unsigned short findfirst(struct DTA *dta, const char *pattern, unsigned short attr) {
65
  unsigned short res = 0;
67
  unsigned short res = 0;
66
  _asm {
68
  _asm {
67
    /* set DTA location */
69
    /* set DTA location */
68
    mov ah, 0x1a
70
    mov ah, 0x1a
69
    mov dx, dta
71
    mov dx, dta
70
    int 0x21
72
    int 0x21
71
    /* */
73
    /* */
72
    mov ah, 0x4e    /* FindFirst */
74
    mov ah, 0x4e    /* FindFirst */
73
    mov dx, pattern
75
    mov dx, pattern
74
    mov cx, attr
76
    mov cx, attr
75
    int 0x21        /* CF set on error + err code in AX, DTA filled with FileInfoRec on success */
77
    int 0x21        /* CF set on error + err code in AX, DTA filled with FileInfoRec on success */
76
    jnc DONE
78
    jnc DONE
77
    mov [res], ax
79
    mov [res], ax
78
    DONE:
80
    DONE:
79
  }
81
  }
80
  return(res);
82
  return(res);
81
}
83
}
82
 
84
 
83
 
85
 
84
/* find next matching, ie. continues an action intiated by findfirst() */
86
/* find next matching, ie. continues an action intiated by findfirst() */
85
unsigned short findnext(struct DTA *dta) {
87
unsigned short findnext(struct DTA *dta) {
86
  unsigned short res = 0;
88
  unsigned short res = 0;
87
  _asm {
89
  _asm {
88
    mov ah, 0x4f    /* FindNext */
90
    mov ah, 0x4f    /* FindNext */
89
    mov dx, dta
91
    mov dx, dta
90
    int 0x21        /* CF set on error + err code in AX, DTA filled with FileInfoRec on success */
92
    int 0x21        /* CF set on error + err code in AX, DTA filled with FileInfoRec on success */
91
    jnc DONE
93
    jnc DONE
92
    mov [res], ax
94
    mov [res], ax
93
    DONE:
95
    DONE:
94
  }
96
  }
95
  return(res);
97
  return(res);
96
}
98
}
97
 
99
 
98
 
100
 
99
/* print s string and wait for a single key press from stdin. accepts only
101
/* print s string and wait for a single key press from stdin. accepts only
100
 * key presses defined in the c ASCIIZ string. returns offset of pressed key
102
 * key presses defined in the c ASCIIZ string. returns offset of pressed key
101
 * in string. keys in c MUST BE UPPERCASE! */
103
 * in string. keys in c MUST BE UPPERCASE! */
102
unsigned short askchoice(const char *s, const char *c) {
104
unsigned short askchoice(const char *s, const char *c) {
103
  unsigned short res;
105
  unsigned short res;
104
  char key = 0;
106
  char key = 0;
105
 
107
 
106
  AGAIN:
108
  AGAIN:
107
  output(s);
109
  output(s);
108
  output(" ");
110
  output(" ");
109
 
111
 
110
  _asm {
112
  _asm {
111
    push ax
113
    push ax
112
    push dx
114
    push dx
113
 
115
 
114
    mov ax, 0x0c01 /* clear input buffer and execute getchar (INT 21h,AH=1) */
116
    mov ax, 0x0c01 /* clear input buffer and execute getchar (INT 21h,AH=1) */
115
    int 0x21
117
    int 0x21
116
    /* if AL == 0 then this is an extended character */
118
    /* if AL == 0 then this is an extended character */
117
    test al, al
119
    test al, al
118
    jnz GOTCHAR
120
    jnz GOTCHAR
119
    mov ah, 0x08   /* read again to flush extended char from input buffer */
121
    mov ah, 0x08   /* read again to flush extended char from input buffer */
120
    int 0x21
122
    int 0x21
121
    xor al, al     /* all extended chars are ignored */
123
    xor al, al     /* all extended chars are ignored */
122
    GOTCHAR:       /* received key is in AL now */
124
    GOTCHAR:       /* received key is in AL now */
123
    mov [key], al  /* save key */
125
    mov [key], al  /* save key */
124
 
126
 
125
    /* print a cr/lf */
127
    /* print a cr/lf */
126
    mov ah, 0x02
128
    mov ah, 0x02
127
    mov dl, 0x0D
129
    mov dl, 0x0D
128
    int 0x21
130
    int 0x21
129
    mov dl, 0x0A
131
    mov dl, 0x0A
130
    int 0x21
132
    int 0x21
131
 
133
 
132
    pop dx
134
    pop dx
133
    pop ax
135
    pop ax
134
  }
136
  }
135
 
137
 
136
  /* ucase() result */
138
  /* ucase() result */
137
  if ((key >= 'a') && (key <= 'z')) key -= ('a' - 'A');
139
  if ((key >= 'a') && (key <= 'z')) key -= ('a' - 'A');
138
 
140
 
139
  /* is there a match? */
141
  /* is there a match? */
140
  for (res = 0; c[res] != 0; res++) if (c[res] == key) return(res);
142
  for (res = 0; c[res] != 0; res++) if (c[res] == key) return(res);
141
 
143
 
142
  goto AGAIN;
144
  goto AGAIN;
143
}
145
}
144
 
146
 
145
 
147
 
146
/* converts a path to its canonic representation */
148
/* converts a path to its canonic representation */
147
void file_truename(const char *src, char *dst) {
149
void file_truename(const char *src, char *dst) {
148
  _asm {
150
  _asm {
149
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
151
    mov ah, 0x60  /* query truename, DS:SI=src, ES:DI=dst */
150
    push ds
152
    push ds
151
    pop es
153
    pop es
152
    mov si, src
154
    mov si, src
153
    mov di, dst
155
    mov di, dst
154
    int 0x21
156
    int 0x21
155
  }
157
  }
156
}
158
}
157
 
159
 
158
 
160
 
159
/* returns DOS attributes of file, or -1 on error */
161
/* returns DOS attributes of file, or -1 on error */
160
int file_getattr(const char *fname) {
162
int file_getattr(const char *fname) {
161
  int res = -1;
163
  int res = -1;
162
  _asm {
164
  _asm {
163
    mov ax, 0x4300  /* query file attributes, fname at DS:DX */
165
    mov ax, 0x4300  /* query file attributes, fname at DS:DX */
164
    mov dx, fname
166
    mov dx, fname
165
    int 0x21        /* CX=attributes if CF=0, otherwise AX=errno */
167
    int 0x21        /* CX=attributes if CF=0, otherwise AX=errno */
166
    jc DONE
168
    jc DONE
167
    mov [res], cx
169
    mov [res], cx
168
    DONE:
170
    DONE:
169
  }
171
  }
170
  return(res);
172
  return(res);
171
}
173
}
-
 
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
}
172
 
211