fix 'crash when reviving shopkeeper'
[aNetHack.git] / sys / atari / tos.c
blobeee7bd40f34409d41a7c32c0277137d697ceddde
1 /* NetHack 3.6 tos.c $NHDT-Date: 1432512796 2015/05/25 00:13:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */
2 /* NetHack may be freely redistributed. See license for details. */
4 /*
5 * TOS system functions.
6 */
8 #define NEED_VARARGS
9 #include "hack.h"
11 #ifdef TTY_GRAPHICS
12 #include "tcap.h"
13 #else
14 /* To avoid error for tos.c; will be removed later */
15 static char *nh_HE = "\033q";
16 #endif
18 #ifdef TOS
20 #include <osbind.h>
21 #ifndef WORD
22 #define WORD short /* 16 bits -- redefine if necessary */
23 #endif
25 #include <ctype.h>
27 static char NDECL(DOSgetch);
28 static char NDECL(BIOSgetch);
29 static void NDECL(init_aline);
30 char *_a_line; /* for Line A variables */
31 #ifdef TEXTCOLOR
32 boolean colors_changed = FALSE;
33 #endif
35 int
36 tgetch()
38 char ch;
40 /* BIOSgetch can use the numeric key pad on IBM compatibles. */
41 if (iflags.BIOS)
42 ch = BIOSgetch();
43 else
44 ch = DOSgetch();
45 return ((ch == '\r') ? '\n' : ch);
49 * Keyboard translation tables.
51 #define KEYPADLO 0x61
52 #define KEYPADHI 0x71
54 #define PADKEYS (KEYPADHI - KEYPADLO + 1)
55 #define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI)
58 * Keypad keys are translated to the normal values below.
59 * When iflags.BIOS is active, shifted keypad keys are translated to the
60 * shift values below.
62 static const struct pad {
63 char normal, shift, cntrl;
64 } keypad[PADKEYS] =
66 { C('['), 'Q', C('[') }, /* UNDO */
67 { '?', '/', '?' }, /* HELP */
68 { '(', 'a', '(' }, /* ( */
69 { ')', 'w', ')' }, /* ) */
70 { '/', '/', '/' }, /* / */
71 { C('p'), '$', C('p') }, /* * */
72 { 'y', 'Y', C('y') }, /* 7 */
73 { 'k', 'K', C('k') }, /* 8 */
74 { 'u', 'U', C('u') }, /* 9 */
75 { 'h', 'H', C('h') }, /* 4 */
76 { '.', '.', '.' },
77 { 'l', 'L', C('l') }, /* 6 */
78 { 'b', 'B', C('b') }, /* 1 */
79 { 'j', 'J', C('j') }, /* 2 */
80 { 'n', 'N', C('n') }, /* 3 */
81 { 'i', 'I', C('i') }, /* Ins */
82 { '.', ':', ':' } /* Del */
84 numpad[PADKEYS] = {
85 { C('['), 'Q', C('[') }, /* UNDO */
86 { '?', '/', '?' }, /* HELP */
87 { '(', 'a', '(' }, /* ( */
88 { ')', 'w', ')' }, /* ) */
89 { '/', '/', '/' }, /* / */
90 { C('p'), '$', C('p') }, /* * */
91 { '7', M('7'), '7' }, /* 7 */
92 { '8', M('8'), '8' }, /* 8 */
93 { '9', M('9'), '9' }, /* 9 */
94 { '4', M('4'), '4' }, /* 4 */
95 { '.', '.', '.' }, /* 5 */
96 { '6', M('6'), '6' }, /* 6 */
97 { '1', M('1'), '1' }, /* 1 */
98 { '2', M('2'), '2' }, /* 2 */
99 { '3', M('3'), '3' }, /* 3 */
100 { 'i', 'I', C('i') }, /* Ins */
101 { '.', ':', ':' } /* Del */
105 * Unlike Ctrl-letter, the Alt-letter keystrokes have no specific ASCII
106 * meaning unless assigned one by a keyboard conversion table, so the
107 * keyboard BIOS normally does not return a character code when Alt-letter
108 * is pressed. So, to interpret unassigned Alt-letters, we must use a
109 * scan code table to translate the scan code into a letter, then set the
110 * "meta" bit for it. -3.
112 #define SCANLO 0x10
114 static const char scanmap[] = {
115 /* ... */
116 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a',
117 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x',
118 'c', 'v', 'b', 'N', 'm', ',', '.', '?' /* ... */
121 #define inmap(x) (SCANLO <= (x) && (x) < SCANLO + SIZE(scanmap))
124 * BIOSgetch gets keys directly with a BIOS call.
126 #define SHIFT (0x1 | 0x2)
127 #define CTRL 0x4
128 #define ALT 0x8
130 static char
131 BIOSgetch()
133 unsigned char scan, shift, ch;
134 const struct pad *kpad;
136 long x;
138 /* Get scan code.
140 x = Crawcin();
141 ch = x & 0x0ff;
142 scan = (x & 0x00ff0000L) >> 16;
143 /* Get shift status.
145 shift = Kbshift(-1);
147 /* Translate keypad keys */
148 if (iskeypad(scan)) {
149 kpad = iflags.num_pad ? numpad : keypad;
150 if (shift & SHIFT)
151 ch = kpad[scan - KEYPADLO].shift;
152 else if (shift & CTRL)
153 ch = kpad[scan - KEYPADLO].cntrl;
154 else
155 ch = kpad[scan - KEYPADLO].normal;
157 /* Translate unassigned Alt-letters */
158 if ((shift & ALT) && !ch) {
159 if (inmap(scan))
160 ch = scanmap[scan - SCANLO];
161 return (isprint(ch) ? M(ch) : ch);
163 return ch;
166 static char
167 DOSgetch()
169 return (Crawcin() & 0x007f);
172 long
173 freediskspace(path)
174 char *path;
176 int drive = 0;
177 struct {
178 long freal; /*free allocation units*/
179 long total; /*total number of allocation units*/
180 long bps; /*bytes per sector*/
181 long pspal; /*physical sectors per allocation unit*/
182 } freespace;
183 if (path[0] && path[1] == ':')
184 drive = (toupper(path[0]) - 'A') + 1;
185 if (Dfree(&freespace, drive) < 0)
186 return -1;
187 return freespace.freal * freespace.bps * freespace.pspal;
191 * Functions to get filenames using wildcards
194 findfirst(path)
195 char *path;
197 return (Fsfirst(path, 0) == 0);
201 findnext()
203 return (Fsnext() == 0);
206 char *
207 foundfile_buffer()
209 return (char *) Fgetdta() + 30;
212 long
213 filesize(file)
214 char *file;
216 if (findfirst(file))
217 return (*(long *) ((char *) Fgetdta() + 26));
218 else
219 return -1L;
223 * Chdrive() changes the default drive.
225 void
226 chdrive(str)
227 char *str;
229 char *ptr;
230 char drive;
232 if ((ptr = index(str, ':')) != (char *) 0) {
233 drive = toupper(*(ptr - 1));
234 (void) Dsetdrv(drive - 'A');
236 return;
239 void
240 get_scr_size()
242 #ifdef MINT
243 #include <ioctl.h>
244 struct winsize win;
245 char *tmp;
247 if ((tmp = nh_getenv("LINES")))
248 LI = atoi(tmp);
249 else if ((tmp = nh_getenv("ROWS")))
250 LI = atoi(tmp);
251 if (tmp && (tmp = nh_getenv("COLUMNS")))
252 CO = atoi(tmp);
253 else {
254 ioctl(0, TIOCGWINSZ, &win);
255 LI = win.ws_row;
256 CO = win.ws_col;
258 #else
259 init_aline();
260 LI = (*((WORD *) (_a_line + -42L))) + 1;
261 CO = (*((WORD *) (_a_line + -44L))) + 1;
262 #endif
265 #define BIGBUF 8192
268 _copyfile(from, to)
269 char *from, *to;
271 int fromfd, tofd, r;
272 char *buf;
274 if ((fromfd = open(from, O_RDONLY | O_BINARY, 0)) < 0)
275 return -1;
276 if ((tofd = open(to, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, FCMASK))
277 < 0)
278 return -1;
279 buf = (char *) alloc((size_t) BIGBUF);
280 while ((r = read(fromfd, buf, BIGBUF)) > 0)
281 write(tofd, buf, r);
282 close(fromfd);
283 close(tofd);
284 free(buf);
285 return 0; /* successful */
289 kbhit()
291 return Cconis();
294 static void
295 init_aline()
297 #ifdef __GNUC__
298 /* line A calls nuke registers d0-d2,a0-a2; not all compilers regard these
299 as scratch registers, though, so we save them
301 asm(" moveml d0-d2/a0-a2, sp@-");
302 asm(" .word 0xa000; movel d0, __a_line");
303 asm(" moveml sp@+, d0-d2/a0-a2");
304 #else
305 asm(" movem.l d0-d2/a0-a2, -(sp)");
306 asm(" .dc.w 0xa000"); /* tweak as necessary for your compiler */
307 asm(" move.l d0, __a_line");
308 asm(" movem.l (sp)+, d0-d2/a0-a2");
309 #endif
312 #ifdef TEXTCOLOR
313 /* used in termcap.c to decide how to set up the hilites */
314 unsigned long tos_numcolors = 2;
316 void
317 set_colors()
319 static char colorHE[] = "\033q\033b0";
321 if (!iflags.BIOS)
322 return;
323 init_aline();
324 tos_numcolors = 1 << (((unsigned char *) _a_line)[1]);
325 if (tos_numcolors <= 2) { /* mono */
326 iflags.use_color = FALSE;
327 return;
328 } else {
329 colors_changed = TRUE;
330 nh_HE = colorHE;
334 void
335 restore_colors()
337 static char plainHE[] = "\033q";
339 if (colors_changed)
340 nh_HE = plainHE;
341 colors_changed = FALSE;
343 #endif /* TEXTCOLOR */
345 #ifdef SUSPEND
347 #include <signal.h>
349 #ifdef MINT
350 extern int __mint;
351 #endif
354 dosuspend()
356 #ifdef MINT
357 extern int kill();
358 if (__mint == 0) {
359 #endif
360 pline("Sorry, it seems we have no SIGTSTP here. Try ! or S.");
361 #ifdef MINT
362 } else if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) {
363 suspend_nhwindows((char *) 0);
364 (void) signal(SIGTSTP, SIG_DFL);
365 (void) kill(0, SIGTSTP);
366 get_scr_size();
367 resume_nhwindows();
368 } else {
369 pline("I don't think your shell has job control.");
371 #endif /* MINT */
372 return (0);
374 #endif /* SUSPEND */
376 #endif /* TOS */