Subversion Repositories SvarDOS

Rev

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

Rev 449 Rev 450
1
/* This file is part of the SvarCOM project and is published under the terms
1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
2
 * of the MIT license.
3
 *
3
 *
4
 * Copyright (C) 2021 Mateusz Viste
4
 * Copyright (C) 2021 Mateusz Viste
5
 *
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
12
 *
13
 * The above copyright notice and this permission notice shall be included in
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
14
 * all copies or substantial portions of the Software.
15
 *
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
22
 * DEALINGS IN THE SOFTWARE.
23
 */
23
 */
24
 
24
 
25
#include <i86.h>
25
#include <i86.h>
26
#include <string.h>
26
#include <string.h>
27
 
27
 
28
#include "env.h"
28
#include "env.h"
29
#include "helpers.h"
29
#include "helpers.h"
30
 
30
 
31
#include "rmod.h"
31
#include "rmod.h"
32
 
32
 
33
#include "rmodinit.h"
33
#include "rmodinit.h"
34
 
34
 
35
 
35
 
36
/* returns far pointer to rmod's settings block on success */
36
/* returns far pointer to rmod's settings block on success */
37
struct rmod_props far *rmod_install(unsigned short envsize) {
37
struct rmod_props far *rmod_install(unsigned short envsize) {
38
  char far *myptr, far *mcb;
38
  char far *myptr, far *mcb;
39
  unsigned short far *owner;
39
  unsigned short far *owner;
40
  const unsigned short sizeof_rmodandprops_paras = rmod_len + sizeof(struct rmod_props) + 15 / 16;
40
  const unsigned short sizeof_rmodandprops_paras = rmod_len + sizeof(struct rmod_props) + 15 / 16;
41
  unsigned int rmodseg = 0xffff;
41
  unsigned int rmodseg = 0xffff;
42
  unsigned int envseg = 0;
42
  unsigned int envseg = 0;
43
  struct rmod_props far *res = NULL;
43
  struct rmod_props far *res = NULL;
44
 
44
 
45
  /* read my current env segment from PSP */
45
  /* read my current env segment from PSP */
46
  _asm {
46
  _asm {
47
    push ax
47
    push ax
48
    push bx
48
    push bx
49
    mov bx, 0x2c
49
    mov bx, 0x2c
50
    mov ax, [bx]
50
    mov ax, [bx]
51
    mov envseg, ax
51
    mov envseg, ax
52
    pop bx
52
    pop bx
53
    pop ax
53
    pop ax
54
  }
54
  }
55
 
55
 
56
  /* printf("original (PSP) env buffer at %04X\r\n", envseg); */
56
  /* printf("original (PSP) env buffer at %04X\r\n", envseg); */
57
 
57
 
58
  /* if envseg is zero, then enforce our own one (MSDOS 5 does not provide a default env) */
58
  /* if envseg is zero, then enforce our own one (MSDOS 5 does not provide a default env) */
59
  if ((envseg == 0) && (envsize == 0)) envsize = 256;
59
  if ((envseg == 0) && (envsize == 0)) envsize = 256;
60
 
60
 
61
  /* if custom envsize requested, convert it to number of paragraphs */
61
  /* if custom envsize requested, convert it to number of paragraphs */
62
  if (envsize != 0) {
62
  if (envsize != 0) {
63
    envsize += 15;
63
    envsize += 15;
64
    envsize /= 16;
64
    envsize /= 16;
65
  }
65
  }
66
 
66
 
67
 
67
 
68
  _asm {
68
  _asm {
69
    /* link in the UMB memory chain for enabling high-memory allocation (and save initial status on stack) */
69
    /* link in the UMB memory chain for enabling high-memory allocation (and save initial status on stack) */
70
    mov ax, 0x5802  /* GET UMB LINK STATE */
70
    mov ax, 0x5802  /* GET UMB LINK STATE */
71
    int 0x21
71
    int 0x21
72
    xor ah, ah
72
    xor ah, ah
73
    push ax         /* save link state on stack */
73
    push ax         /* save link state on stack */
74
    mov ax, 0x5803  /* SET UMB LINK STATE */
74
    mov ax, 0x5803  /* SET UMB LINK STATE */
75
    mov bx, 1
75
    mov bx, 1
76
    int 0x21
76
    int 0x21
77
    /* get current allocation strategy and save it in DX */
77
    /* get current allocation strategy and save it in DX */
78
    mov ax, 0x5800
78
    mov ax, 0x5800
79
    int 0x21
79
    int 0x21
80
    push ax
80
    push ax
81
    pop dx
81
    pop dx
82
    /* set strategy to 'last fit, try high then low memory' */
82
    /* set strategy to 'last fit, try high then low memory' */
83
    mov ax, 0x5801
83
    mov ax, 0x5801
84
    mov bx, 0x0082
84
    mov bx, 0x0082
85
    int 0x21
85
    int 0x21
86
    /* ask for a memory block and save the given segment to rmodseg */
86
    /* ask for a memory block and save the given segment to rmodseg */
87
    mov ah, 0x48
87
    mov ah, 0x48
88
    mov bx, sizeof_rmodandprops_paras
88
    mov bx, sizeof_rmodandprops_paras
89
    int 0x21
89
    int 0x21
90
    jc ALLOC_FAIL
90
    jc ALLOC_FAIL
91
    mov rmodseg, ax
91
    mov rmodseg, ax
92
    /* ask for a memory block for the environment and save it to envseg (only if custom size requested) */
92
    /* ask for a memory block for the environment and save it to envseg (only if custom size requested) */
93
    mov bx, envsize
93
    mov bx, envsize
94
    test bx, bx
94
    test bx, bx
95
    jz ALLOC_FAIL
95
    jz ALLOC_FAIL
96
    mov ah, 0x48
96
    mov ah, 0x48
97
    int 0x21
97
    int 0x21
98
    jc ALLOC_FAIL
98
    jc ALLOC_FAIL
99
    mov envseg, ax
99
    mov envseg, ax
100
 
100
 
101
    ALLOC_FAIL:
101
    ALLOC_FAIL:
102
    /* restore initial allocation strategy */
102
    /* restore initial allocation strategy */
103
    mov ax, 0x5801
103
    mov ax, 0x5801
104
    mov bx, dx
104
    mov bx, dx
105
    int 0x21
105
    int 0x21
106
    /* restore initial UMB memory link state */
106
    /* restore initial UMB memory link state */
107
    mov ax, 0x5803
107
    mov ax, 0x5803
108
    pop bx       /* pop initial UMB link state from stack */
108
    pop bx       /* pop initial UMB link state from stack */
109
    int 0x21
109
    int 0x21
110
  }
110
  }
111
 
111
 
112
  if (rmodseg == 0xffff) {
112
  if (rmodseg == 0xffff) {
113
    outputnl("malloc error");
113
    outputnl("malloc error");
114
    return(NULL);
114
    return(NULL);
115
  }
115
  }
116
 
116
 
117
  /* copy rmod to its destination */
117
  /* copy rmod to its destination */
118
  myptr = MK_FP(rmodseg, 0);
118
  myptr = MK_FP(rmodseg, 0);
119
  _fmemcpy(myptr, rmod, rmod_len);
119
  _fmemcpy(myptr, rmod, rmod_len);
120
 
120
 
121
  /* mark rmod memory as "self owned" */
121
  /* mark rmod memory as "self owned" */
122
  mcb = MK_FP(rmodseg - 1, 0);
122
  mcb = MK_FP(rmodseg - 1, 0);
123
  owner = (void far *)(mcb + 1);
123
  owner = (void far *)(mcb + 1);
124
  *owner = rmodseg;
124
  *owner = rmodseg;
125
  _fmemcpy(mcb + 8, "SVARCOM", 8);
125
  _fmemcpy(mcb + 8, "SVARCOM", 8);
126
 
126
 
127
  /* mark env memory as "owned by rmod" */
127
  /* mark env memory as "owned by rmod" */
128
  mcb = MK_FP(envseg - 1, 0);
128
  mcb = MK_FP(envseg - 1, 0);
129
  owner = (void far *)(mcb + 1);
129
  owner = (void far *)(mcb + 1);
130
  *owner = rmodseg;
130
  *owner = rmodseg;
131
  _fmemcpy(mcb + 8, "SVARENV", 8);
131
  _fmemcpy(mcb + 8, "SVARENV", 8);
132
 
132
 
133
  /* if env block is newly allocated, fill it with a few NULLs */
133
  /* if env block is newly allocated, fill it with a few NULLs */
134
  if (envsize != 0) {
134
  if (envsize != 0) {
135
    owner = MK_FP(envseg, 0);
135
    owner = MK_FP(envseg, 0);
136
    owner[0] = 0;
136
    owner[0] = 0;
137
    owner[1] = 0;
137
    owner[1] = 0;
138
  }
138
  }
139
 
139
 
140
  /* prepare result (rmod props) */
140
  /* prepare result (rmod props) */
141
  res = MK_FP(rmodseg, rmod_len);
141
  res = MK_FP(rmodseg, rmod_len);
142
  _fmemset(res, 0, sizeof(*res));
142
  _fmemset(res, 0, sizeof(*res));  /* zero out */
143
  res->rmodseg = rmodseg;
143
  res->rmodseg = rmodseg;          /* rmod segment */
-
 
144
  res->inputbuf[0] = 128;          /* input buffer for INT 0x21, AH=0Ah*/
-
 
145
  res->echoflag = 1;               /* ECHO ON */
144
 
146
 
145
  /* write env segment to rmod buffer */
147
  /* write env segment to rmod buffer */
146
  owner = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG);
148
  owner = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG);
147
  *owner = envseg;
149
  *owner = envseg;
148
 
150
 
149
  /* write boot drive to rmod bootdrive field */
151
  /* write boot drive to rmod bootdrive field */
150
  _asm {
152
  _asm {
151
    push ax
153
    push ax
152
    push bx
154
    push bx
153
    push dx
155
    push dx
154
    push ds
156
    push ds
155
    mov ax, 0x3305 /* DOS 4.0+ - GET BOOT DRIVE */
157
    mov ax, 0x3305 /* DOS 4.0+ - GET BOOT DRIVE */
156
    int 0x21 /* boot drive is in DL now (1=A:, 2=B:, etc) */
158
    int 0x21 /* boot drive is in DL now (1=A:, 2=B:, etc) */
157
    add dl, 'A'-1 /* convert to a proper ASCII letter */
159
    add dl, 'A'-1 /* convert to a proper ASCII letter */
158
    /* set DS to rmodseg */
160
    /* set DS to rmodseg */
159
    mov ax, rmodseg
161
    mov ax, rmodseg
160
    mov ds, ax
162
    mov ds, ax
161
    /* write boot drive to rmod bootdrive field */
163
    /* write boot drive to rmod bootdrive field */
162
    mov bx, RMOD_OFFSET_BOOTDRIVE
164
    mov bx, RMOD_OFFSET_BOOTDRIVE
163
    mov [bx], dl
165
    mov [bx], dl
164
    pop ds
166
    pop ds
165
    pop dx
167
    pop dx
166
    pop bx
168
    pop bx
167
    pop ax
169
    pop ax
168
  }
170
  }
169
 
171
 
-
 
172
  /* save my original parent in rmod's memory */
-
 
173
  res->origparent = *((unsigned long *)0x0a); /* original parent seg:off is at 0x0a of my PSP */
-
 
174
 
170
  /* set the int22 handler in my PSP to rmod so DOS jumps to rmod after I
175
  /* set the int22 handler in my PSP to rmod so DOS jumps to rmod after I
171
   * terminate and save the original handler in rmod's memory */
176
   * terminate and save the original handler in rmod's memory */
172
  _asm {
177
  _asm {
173
    push ax
178
    push ax
174
    push bx
179
    push bx
175
    push si
180
    push si
176
    push di
181
    push di
177
    push es
182
    push es
178
 
183
 
179
    /* save my original parent in rmod's memory */
-
 
180
    mov es, [rmodseg]
-
 
181
    mov si, 0x0a
-
 
182
    mov di, RMOD_OFFSET_ORIGPARENT
-
 
183
    cld
-
 
184
    movsw  /* mov ES:[DI], DS:[SI] and SI += 2 and DI += 2 */
-
 
185
    movsw
-
 
186
 
-
 
187
    mov bx, 0x0a                   /* int22 handler is at 0x0A of the PSP */
184
    mov bx, 0x0a                   /* int22 handler is at 0x0A of the PSP */
188
    mov ax, RMOD_OFFSET_ROUTINE
185
    mov ax, RMOD_OFFSET_ROUTINE
189
    mov [bx], ax                   /* int handler offset */
186
    mov [bx], ax                   /* int handler offset */
190
    mov ax, rmodseg
187
    mov ax, rmodseg
191
    mov [bx+2], ax                 /* int handler segment */
188
    mov [bx+2], ax                 /* int handler segment */
192
 
189
 
193
    pop es
190
    pop es
194
    pop di
191
    pop di
195
    pop si
192
    pop si
196
    pop bx
193
    pop bx
197
    pop ax
194
    pop ax
198
  }
195
  }
199
 
196
 
200
  return(res);
197
  return(res);
201
}
198
}
202
 
199
 
203
 
200
 
204
/* look up my parent: if it's rmod then return a ptr to its props struct,
201
/* look up my parent: if it's rmod then return a ptr to its props struct,
205
 * otherwise return NULL */
202
 * otherwise return NULL */
206
struct rmod_props far *rmod_find(void) {
203
struct rmod_props far *rmod_find(void) {
207
  unsigned short *parent = (void *)0x0C; /* parent's seg in PSP[Ch] ("prev. int22 handler") */
204
  unsigned short *parent = (void *)0x0C; /* parent's seg in PSP[Ch] ("prev. int22 handler") */
208
  unsigned short far *ptr;
205
  unsigned short far *ptr;
209
  const unsigned short sig[] = {0x1983, 0x1985, 0x2017, 0x2019};
206
  const unsigned short sig[] = {0x1983, 0x1985, 0x2017, 0x2019};
210
  unsigned char i;
207
  unsigned char i;
211
  /* is it rmod? */
208
  /* is it rmod? */
212
  ptr = MK_FP(*parent, 0);
209
  ptr = MK_FP(*parent, 0);
213
  for (i = 0; i < 4; i++) if (ptr[i] != sig[i]) return(NULL);
210
  for (i = 0; i < 4; i++) if (ptr[i] != sig[i]) return(NULL);
214
  /* match successfull (rmod is my parent) */
211
  /* match successfull (rmod is my parent) */
215
  return(MK_FP(*parent, rmod_len));
212
  return(MK_FP(*parent, rmod_len));
216
}
213
}
217
 
214
 
218
 
215
 
219
/* update rmod's pointer to comspec */
216
/* update rmod's pointer to comspec */
220
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg) {
217
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg) {
221
  unsigned short far *comspecptr = MK_FP(rmod_seg, RMOD_OFFSET_COMSPECPTR);
218
  unsigned short far *comspecptr = MK_FP(rmod_seg, RMOD_OFFSET_COMSPECPTR);
222
  char far *comspecfp = env_lookup_val(env_seg, "COMSPEC");
219
  char far *comspecfp = env_lookup_val(env_seg, "COMSPEC");
223
  if (comspecfp != NULL) {
220
  if (comspecfp != NULL) {
224
    *comspecptr = FP_OFF(comspecfp);
221
    *comspecptr = FP_OFF(comspecfp);
225
  } else {
222
  } else {
226
    *comspecptr = 0;
223
    *comspecptr = 0;
227
  }
224
  }
228
}
225
}
229
 
226