Subversion Repositories SvarDOS

Rev

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

Rev Author Line No. Line
1290 bernd.boec 1
/* This file is part of the svarlang project and is published under the terms
2
 * of the MIT license.
3
 *
4
 * Copyright (C) 2021-2023 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
 */
24
 
25
/* if WITHSTDIO is enabled, then remap file operations to use the standard
26
 * stdio amenities */
27
#ifdef WITHSTDIO
28
 
29
#include <stdio.h>   /* FILE, fopen(), fseek(), etc */
30
typedef FILE* FHANDLE;
31
#define FOPEN(x) fopen(x, "rb")
32
#define FCLOSE(x) fclose(x)
33
#define FSEEK(f,b) fseek(f,b,SEEK_CUR)
34
#define FREAD(f,t,b) fread(t, 1, b, f)
35
 
36
#else
37
 
38
#include <i86.h>
39
typedef unsigned short FHANDLE;
40
 
41
#endif
42
 
43
 
1298 mateusz.vi 44
#include <string.h>  /* strcpy() */
45
 
1290 bernd.boec 46
#include "svarlang.h"
47
 
48
 
49
/* supplied through DEFLANG.C */
50
extern char svarlang_mem[];
51
extern unsigned short svarlang_dict[];
52
extern const unsigned short svarlang_memsz;
53
extern const unsigned short svarlang_string_count;
54
 
1298 mateusz.vi 55
 
1290 bernd.boec 56
const char *svarlang_strid(unsigned short id) {
1298 mateusz.vi 57
  size_t left = 0, right = svarlang_string_count - 1, x;
58
  unsigned short v;
1290 bernd.boec 59
 
1298 mateusz.vi 60
  if (svarlang_string_count == 0) return("");
1290 bernd.boec 61
 
1298 mateusz.vi 62
  while (left <= right) {
63
    x = left + ( (right - left ) >> 2 );
64
    v = svarlang_dict[x * 2];
65
 
66
    if (id == v) return(svarlang_mem + svarlang_dict[x * 2 + 1]);
67
 
68
    if (id > v) {
69
      left = x + 1;
70
    } else {
71
      right = x - 1;
72
    }
73
  }
74
 
75
  return("");
1290 bernd.boec 76
}
77
 
1293 mateusz.vi 78
 
1290 bernd.boec 79
/* routines below are simplified (dos-based) versions of the libc FILE-related
80
 * functions. Using them avoids a dependency on FILE, hence makes the binary
81
 * smaller if the application does not need to pull fopen() and friends */
82
#ifndef WITHSTDIO
83
static unsigned short FOPEN(const char *s) {
84
  unsigned short fname_seg = FP_SEG(s);
85
  unsigned short fname_off = FP_OFF(s);
86
  unsigned short res = 0; /* fd 0 is already used by stdout so it's a good error value */
87
  _asm {
88
    push dx
89
    push ds
90
 
91
    mov ax, fname_seg
92
    mov dx, fname_off
93
    mov ds, ax
94
    mov ax, 0x3d00  /* open file, read-only (fname at DS:DX) */
95
    int 0x21
96
    pop ds
97
    jc ERR
98
    mov res, ax
99
 
100
    ERR:
101
    pop dx
102
  }
103
 
104
  return(res);
105
}
106
 
107
 
108
static void FCLOSE(unsigned short handle) {
109
  _asm {
110
    push bx
111
 
112
    mov ah, 0x3e
113
    mov bx, handle
114
    int 0x21
115
 
116
    pop bx
117
  }
118
}
119
 
120
 
121
static unsigned short FREAD(unsigned short handle, void *buff, unsigned short bytes) {
122
  unsigned short buff_seg = FP_SEG(buff);
123
  unsigned short buff_off = FP_OFF(buff);
124
  unsigned short res = 0;
125
 
126
  _asm {
127
    push bx
128
    push cx
129
    push dx
130
 
131
    mov bx, handle
132
    mov cx, bytes
133
    mov dx, buff_off
134
    mov ax, buff_seg
135
    push ds
136
    mov ds, ax
137
    mov ah, 0x3f    /* read cx bytes from file handle bx to DS:DX */
138
    int 0x21
139
    pop ds
140
    jc ERR
141
 
142
    mov res, ax
143
    ERR:
144
 
145
    pop dx
146
    pop cx
147
    pop bx
148
  }
149
 
150
  return(res);
151
}
152
 
153
 
154
static void FSEEK(unsigned short handle, unsigned short bytes) {
155
  _asm {
156
    push bx
157
    push cx
158
    push dx
159
 
160
    mov ax, 0x4201  /* move file pointer from cur pos + CX:DX */
161
    mov bx, handle
162
    xor cx, cx
163
    mov dx, bytes
164
    int 0x21
165
 
166
    pop dx
167
    pop cx
168
    pop bx
169
  }
170
}
171
#endif
172
 
1293 mateusz.vi 173
 
1290 bernd.boec 174
int svarlang_load(const char *fname, const char *lang) {
175
  unsigned short langid;
1293 mateusz.vi 176
  unsigned long hdr;
1290 bernd.boec 177
  unsigned short buff16[2];
178
  FHANDLE fd;
179
  unsigned short string_count;
180
 
181
  langid = *((unsigned short *)lang);
182
  langid &= 0xDFDF; /* make sure lang is upcase */
183
 
184
  fd = FOPEN(fname);
185
  if (!fd) return(-1);
186
 
1293 mateusz.vi 187
  /* read hdr, should be "SvL\x1a" */
188
  if ((FREAD(fd, &hdr, 4) != 4) || (hdr != 0x1a4c7653L)) { /* 0x1a4c7653 = 'SvL\x1a' */
1290 bernd.boec 189
    FCLOSE(fd);
190
    return(-3);
191
  }
192
 
193
  /* read string count */
194
  if ((FREAD(fd, &string_count, 2) != 2) || (string_count != svarlang_string_count)) {
195
    FCLOSE(fd);
196
    return(-6);
197
  }
198
 
199
  /* read next lang id and string table size in file */
200
  while (FREAD(fd, buff16, 4) == 4) {
201
 
202
    /* is it the lang I am looking for? */
203
    if (buff16[0] != langid) { /* skip to next lang */
204
      FSEEK(fd, svarlang_string_count * 4);
205
      FSEEK(fd, buff16[1]);
206
      continue;
207
    }
208
 
209
    /* found - but do I have enough memory space? */
210
    if (buff16[1] >= svarlang_memsz) {
211
      FCLOSE(fd);
212
      return(-4);
213
    }
214
 
215
    /* load dictionary & strings */
216
    if ((FREAD(fd, svarlang_dict, svarlang_string_count * 4) != svarlang_string_count * 4) ||
217
       (FREAD(fd, svarlang_mem, buff16[1]) != buff16[1])) {
218
      FCLOSE(fd);
219
      return -7;
220
    }
221
    FCLOSE(fd);
222
    return(0);
223
  }
224
 
225
  FCLOSE(fd);
226
  return(-5);
227
}