Subversion Repositories SvarDOS

Rev

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

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