Subversion Repositories SvarDOS

Rev

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

Rev Author Line No. Line
351 mateuszvis 1
 
2
#include <i86.h>
3
#include <string.h>
4
 
367 mateuszvis 5
#include "env.h"
369 mateuszvis 6
#include "helpers.h"
367 mateuszvis 7
 
351 mateuszvis 8
#include "rmod.h"
9
 
10
#include "rmodinit.h"
11
 
12
 
13
/* returns segment where rmod is installed */
14
unsigned short rmod_install(unsigned short envsize) {
15
  char far *myptr, far *mcb;
16
  unsigned short far *owner;
17
  unsigned int rmodseg = 0xffff;
18
  unsigned int envseg = 0;
19
 
20
  /* read my current env segment from PSP */
21
  _asm {
22
    push ax
23
    push bx
24
    mov bx, 0x2c
25
    mov ax, [bx]
26
    mov envseg, ax
27
    pop bx
28
    pop ax
29
  }
30
 
369 mateuszvis 31
  /* printf("original (PSP) env buffer at %04X\r\n", envseg); */
351 mateuszvis 32
  /* if custom envsize requested, convert it to number of paragraphs */
33
  if (envsize != 0) {
34
    envsize += 15;
35
    envsize /= 16;
36
  }
37
 
38
 
39
  _asm {
40
    /* link in the UMB memory chain for enabling high-memory allocation (and save initial status on stack) */
41
    mov ax, 0x5802  /* GET UMB LINK STATE */
42
    int 0x21
43
    xor ah, ah
44
    push ax         /* save link state on stack */
45
    mov ax, 0x5803  /* SET UMB LINK STATE */
46
    mov bx, 1
47
    int 0x21
48
    /* get current allocation strategy and save it in DX */
49
    mov ax, 0x5800
50
    int 0x21
51
    push ax
52
    pop dx
53
    /* set strategy to 'last fit, try high then low memory' */
54
    mov ax, 0x5801
55
    mov bx, 0x0082
56
    int 0x21
57
    /* ask for a memory block and save the given segment to rmodseg */
58
    mov ah, 0x48
59
    mov bx, (rmod_len + 15) / 16
60
    int 0x21
61
    jc ALLOC_FAIL
62
    mov rmodseg, ax
63
    /* ask for a memory block for the environment and save it to envseg (only if custom size requested) */
64
    mov bx, envsize
65
    test bx, bx
66
    jz ALLOC_FAIL
67
    mov ah, 0x48
68
    int 0x21
69
    jc ALLOC_FAIL
70
    mov envseg, ax
71
 
72
    ALLOC_FAIL:
73
    /* restore initial allocation strategy */
74
    mov ax, 0x5801
75
    mov bx, dx
76
    int 0x21
77
    /* restore initial UMB memory link state */
78
    mov ax, 0x5803
79
    pop bx       /* pop initial UMB link state from stack */
80
    int 0x21
81
  }
82
 
83
  if (rmodseg == 0xffff) {
369 mateuszvis 84
    outputnl("malloc error");
351 mateuszvis 85
    return(0xffff);
86
  }
87
 
88
  /* copy rmod to its destination */
89
  myptr = MK_FP(rmodseg, 0);
90
  _fmemcpy(myptr, rmod, rmod_len);
91
 
92
  /* mark rmod memory as "self owned" */
93
  mcb = MK_FP(rmodseg - 1, 0);
94
  owner = (void far *)(mcb + 1);
95
  *owner = rmodseg;
96
  _fmemcpy(mcb + 8, "SVARCOM", 8);
97
 
359 mateuszvis 98
  /* mark env memory as "self owned" */
99
  mcb = MK_FP(envseg - 1, 0);
100
  owner = (void far *)(mcb + 1);
101
  *owner = rmodseg;
102
  _fmemcpy(mcb + 8, "SVARENV", 8);
351 mateuszvis 103
 
104
  /* write env segment to rmod buffer */
105
  owner = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG);
106
  *owner = envseg;
107
 
366 mateuszvis 108
  /* write boot drive to rmod bootdrive field */
109
  _asm {
110
    push ax
111
    push bx
112
    push dx
113
    push ds
114
    mov ax, 0x3305 /* DOS 4.0+ - GET BOOT DRIVE */
115
    int 0x21 /* boot drive is in DL now (1=A:, 2=B:, etc) */
116
    add dl, 'A'-1 /* convert to a proper ASCII letter */
117
    /* set DS to rmodseg */
118
    mov ax, rmodseg
119
    mov ds, ax
120
    /* write boot drive to rmod bootdrive field */
121
    mov bx, RMOD_OFFSET_BOOTDRIVE
122
    mov [bx], dl
123
    pop ds
124
    pop dx
125
    pop bx
126
    pop ax
127
  }
128
 
351 mateuszvis 129
  /* set the int22 handler in my PSP to rmod so DOS jumps to rmod after I terminate */
130
  _asm {
366 mateuszvis 131
    push ax
132
    push bx
351 mateuszvis 133
    mov bx, 0x0a                   /* int22 handler is at 0x0A of the PSP */
134
    mov ax, RMOD_OFFSET_ROUTINE
135
    mov [bx], ax                   /* int handler offset */
136
    mov ax, rmodseg
137
    mov [bx+2], ax                 /* int handler segment */
366 mateuszvis 138
    pop bx
139
    pop ax
351 mateuszvis 140
  }
141
 
142
  return(rmodseg);
143
}
144
 
145
 
146
/* scan memory for rmod, returns its segment if found, 0xffff otherwise */
147
unsigned short rmod_find(void) {
148
  unsigned short i;
358 mateuszvis 149
  unsigned short far *ptrword;
150
  unsigned char far *ptrbyte;
351 mateuszvis 151
 
152
  /* iterate over all paragraphs, looking for my signature */
358 mateuszvis 153
  for (i = 1; i != 65535; i++) {
154
    ptrword = MK_FP(i, 0);
155
    if (ptrword[0] != 0x1983) continue;
156
    if (ptrword[1] != 0x1985) continue;
157
    if (ptrword[2] != 0x2017) continue;
158
    if (ptrword[3] != 0x2019) continue;
159
    /* extra check: make sure the paragraph before is an MCB block and that it
160
     * belongs to itself. otherwise I could find the rmod code embedded inside
161
     * the command.com binary... */
162
    ptrbyte = MK_FP(i - 1, 0);
163
    if ((*ptrbyte != 'M') && (*ptrbyte != 'Z')) continue; /* not an MCB */
164
    ptrword = MK_FP(i - 1, 1);
165
    if (*ptrword != i) continue; /* not belonging to self */
351 mateuszvis 166
    return(i);
167
  }
168
  return(0xffff);
169
}
367 mateuszvis 170
 
171
 
172
/* update rmod's pointer to comspec */
173
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg) {
174
  unsigned short far *comspecptr = MK_FP(rmod_seg, RMOD_OFFSET_COMSPECPTR);
175
  char far *comspecfp = env_lookup(env_seg, "COMSPEC");
176
  if (comspecfp != NULL) {
177
    *comspecptr = FP_OFF(comspecfp) + 8; /* +8 to skip the "COMSPEC=" prefix */
178
  } else {
179
    *comspecptr = 0;
180
  }
181
}