diff options
author | Bardur Arantsson <bardur@scientician.net> | 2010-01-08 20:28:34 +0100 |
---|---|---|
committer | Bardur Arantsson <bardur@scientician.net> | 2010-01-08 23:46:06 +0100 |
commit | 6aa48afdd57d03314fdf4be6c9da911c32277c84 (patch) | |
tree | 2dc401f9aae2dc6736d2fc3811c8f8099d3eabe6 /src/main-vme.c |
Import tome-2.3.5.
Diffstat (limited to 'src/main-vme.c')
-rw-r--r-- | src/main-vme.c | 1198 |
1 files changed, 1198 insertions, 0 deletions
diff --git a/src/main-vme.c b/src/main-vme.c new file mode 100644 index 00000000..81fc0e78 --- /dev/null +++ b/src/main-vme.c @@ -0,0 +1,1198 @@ +/* File: main-vme.c */ + +/* Purpose: Support for "Vax Angband" */ + +/* +This is MAIN-VME C for VM/ESA machines. +First enable definition of VM in file "h-config.h" +You need to unpack archive EXT-VM VMARC . + +To do that first set fixed file record length: +'COPYFILE EXT-VM VMARC A = = = ( REC F' +Then unpack: +VMARC UNPACK EXT-VM VMARC A + +( if you don't have archivator vmarc, there is many places where you +get it, i got it from cc1.kuleuven.ac.be ) + +Then read MAKEFILE EXEC. It contains all neccessary information to +compile Angband. + +EXT-VM VMARC content: +MAKEFILE EXEC +VMSERV TXTLIB +CNSHND ASSEMBLE + +You will need about 3-4 MB free disk space to compile it. +If you have any problems, mail to + +SM20616@vm.lanet.lv or SD30066@vm.lanet.lv + +A large amount of this file appears to be a complete hack, but +what can you expect from a system designed for the Vax... :-) + */ + + +#include "angband.h" + +#if defined(USE_VME) || defined(VM) + + +/* + * Convert EBCDIC to ASCII + */ +char e2a[] = +{ + 0x00, 0x01, 0x02, 0x03, 0x1A, 0x09, 0x1A, 0x7F, 0x1A, 0x1A, 0x1A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x1A, 0x0A, 0x08, 0x1A, 0x18, 0x19, 0x1A, 0x1A, 0x1C, 0x1D, 0x1E, 0x1F, + 0x1A, 0x1A, 0x1C, 0x1A, 0x1A, 0x0A, 0x17, 0x1B, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x05, 0x06, 0x07, + 0x1A, 0x1A, 0x16, 0x1A, 0x1A, 0x1E, 0x1A, 0x04, 0x1A, 0x1A, 0x1A, 0x1A, 0x14, 0x15, 0x1A, 0x1A, + 0x20, 0xA6, 0xE1, 0x80, 0xEB, 0x90, 0x9F, 0xE2, 0xAB, 0x8B, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, + 0x26, 0xA9, 0xAA, 0x9C, 0xDB, 0xA5, 0x99, 0xE3, 0xA8, 0x9E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, + 0x2D, 0x2F, 0xDF, 0xDC, 0x9A, 0xDD, 0xDE, 0x98, 0x9D, 0xAC, 0xBA, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + 0xD7, 0x88, 0x94, 0xB0, 0xB1, 0xB2, 0xFC, 0xD6, 0xFB, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + 0xF8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x96, 0xA4, 0xF3, 0xAF, 0xAE, 0xC5, + 0x8C, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x97, 0x87, 0xCE, 0x93, 0xF1, 0xFE, + 0xC8, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xEF, 0xC0, 0xDA, 0x5B, 0xF2, 0xF9, + 0xB5, 0xB6, 0xFD, 0xB7, 0xB8, 0xB9, 0xE6, 0xBB, 0xBC, 0xBD, 0x8D, 0xD9, 0xBF, 0x5D, 0xD8, 0xC4, + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0xCB, 0xCA, 0xBE, 0xE8, 0xEC, 0xED, + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0xA1, 0xAD, 0xF5, 0xF4, 0xA3, 0x8F, + 0x5C, 0xE7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0xA0, 0x85, 0x8E, 0xE9, 0xE4, 0xD1, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xB3, 0xF7, 0xF0, 0xFA, 0xA7, 0xFF +}; + + +/* + * Convert ASCII to EBCDIC + */ +char a2e[] = +{ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x35, 0x1F, + 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, 0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x35, 0x1F, + 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07 +}; + + +/* + * System headers (already included by "angband.h" XXX XXX XXX) + */ +#include <string.h> +#include <ctype.h> +#include <stdio.h> + +/* Some prototypes and definitions */ + +#define FIELD_SY 1 +#define FIELD_SX 80 +#define FIELD_EY 2 +#define FIELD_EX 10 + +void GetAddr(int, int, char *); +void InitConsole(void); +void TerminateConsole(void); +void ResetScrBuf(void); +void AddScrBuf(char *, int); +char InKey(void); +char InKeyBuf(void); +void ScreenClear(void); +void ResetDISP(void); +int kbhit(void); +void ShowLine(int y, int x, int len); +void LoadProfile(void); + +/* Changed lines marker. */ + +char DISP[26]; + +/* Max rows & columns number in screen (note that in older version + ** than 2.7.9 we needed 25 lines, though 24th was unused. So it is set + ** to 25 although screen actually has only 24 lines. (we just used to + ** transfer 25th line into 24th. + ** But in new version we no longer use it. + */ + +int rows, cols; + +/* Game cursor position on screen */ + +int curx = 1; +int cury = 1; + +/* + * Virtual Screen + */ +byte VirtualScreen[2048]; +byte ScreenAttr[2048]; + +/* + * This array is used for "wiping" the screen, initialized in "init_wat()" + */ +byte wiper[256]; + +/* + * The main screen + */ +static term term_screen_body; + + +/* Update line on screen. + ** Actually just set flag that we should update it. + */ +void ScreenUpdateLine(int line) +{ + DISP[line + 1] = 1; +} + +/* + * Clear the whole screen + */ +void ScreenClear(void) +{ + int iy; + + for (iy = 0; iy < rows; iy++) + { + memcpy(VirtualScreen + (iy*cols), wiper, cols); + memset(ScreenAttr + (iy*cols), 0xF1, cols); + ScreenUpdateLine(iy); + } +} + + +/* + * Nuke a Term + */ +static void Term_nuke_vm(term *t) +{ + TerminateConsole(); + puts("Console has been terminated(nuke)."); +} + +/* + * Move the cursor + */ +static errr Term_curs_vm(int x, int y) +{ + /* Hack: mark line cursor was at as changed to ensure that old + ** cursor would be removed. + */ + DISP[cury] = 1; + curx = x + 1; + cury = y + 1; + return (0); +} + + +/* + * The Angband color table + * + * Comment: White has been changed to blue to make screen look better. + * Green and Light Green are exchanged for the same reason. + * -0x80 means changing to bold font. + * + * Color Table: + * Dark to Blue, White to Blue, Slate to Blue, Orange to Pink, + * Red to Red, Green to GreenB, Blue to BlueB, Umber to Yellow, + * Gray to Blue, Light White to WhiteB, Violet to PinkB, Yellow to Yellow + * Light colors: Red to RedB,Green to Green,Blue to Cyan, Umber to YellB + */ +static const byte vm_color[] = +{ + 0xF1, 0xF1, 0xF1, 0xF3, + 0xF2, 0xF4 - 0x80, 0xF1 - 0x80, 0xF6, + 0xF1, 0xF7 - 0x80, 0xF3 - 0x80, 0xF6, + 0xF2 - 0x80, 0xF4, 0xF5, 0xF6 - 0x80 +}; + +/* + * Place some text on the screen using an attribute + */ +static errr Term_text_vm(int x, int y, int n, byte a, cptr s) +{ + register int i; + register byte attr; + register byte *dest; + register byte *dest2; + + /* Attribute... */ + attr = vm_color[a & 0x0F]; + + /* Paranoia */ + if (n > cols - x) n = cols - x; + + /* Access the destination */ + dest = VirtualScreen + ((cols * y) + x); + dest2 = ScreenAttr + ((cols * y) + x); + + /* Virtually write the string */ + for (i = 0; (i < n) && s[i]; i++) + { + *dest++ = s[i]; + *dest2++ = attr; + } + + /* Dump the line */ + ScreenUpdateLine(y); + + /* Success */ + return (0); +} + + +/* + * Erase part of line. + */ +static errr Term_wipe_vm(int x, int y, int w) +{ + + /* Paranoia -- Verify the dimensions */ + if (cols < (w + x)) w = (cols - x); + + /* Wipe part of the virtual screen, and update */ + memcpy(VirtualScreen + (y*cols + x), wiper, w); + memset(ScreenAttr + (y*cols + x), 0xF1, w); + ScreenUpdateLine(y); + + /* Success */ + return (0); +} + + +/* + * Handle special request. + */ +static errr Term_xtra_vm(int n, int v) +{ + int i, j; + char tmp; + + /* Analyze the request */ + switch (n) + { + + /* Make a noise */ + case TERM_XTRA_NOISE: + + /* No noises here! :) */ + return (0); + + /* Wait for a single event */ + case TERM_XTRA_EVENT: + + /* No wait key press check */ + if (!v && !kbhit()) return (1); + + /* Wait for a keypress */ + i = getkey(); + + /* Save keypress */ + Term_keypress(i); + + /* Success */ + return (0); + + case TERM_XTRA_CLEAR: + + ScreenClear(); + return (0); + +#if 0 + case TERM_XTRA_FROSH: + ScreenUpdateLine(VirtualScreen + (cols*v), v); + return (0); +#endif + + case TERM_XTRA_FLUSH: + + /* Flush keys */ + while (1) + { + tmp = getkeybuf(); + if (!tmp) break; + Term_keypress(tmp); + } + + /* Success */ + return (0); + } + + /* Unknown request */ + return (1); +} + + +/* + * Initialize the VM/CNSconsole. + */ +errr init_vme(void) +{ + register i; + + term *t = &term_screen_body; + + short blank = ' '; + + static int done = FALSE; + + /* Paranoia -- Already done */ + if (done) return ( -1); + + /* Build a "wiper line" of blank spaces */ + for (i = 0; i < 256; i++) wiper[i] = blank; + + /* Acquire the size of the screen */ + rows = 25; + cols = 80; + + /* Initialize the console */ + InitConsole(); + + /* Wipe the screen */ + for (i = 0; i < rows; i++) + { + /* Wipe that row */ + memcpy(VirtualScreen + (i*cols), wiper, cols); + memset(ScreenAttr + (i*cols), 0xF1, cols); + } + + /* Erase the screen */ + ScreenClear(); + + /* Initialize the term -- very large key buffer */ + term_init(t, cols, rows - 1, 1024); + + /* Prepare the init/nuke hooks */ + t->nuke_hook = Term_nuke_vm; + + /* Connect the hooks */ + t->text_hook = Term_text_vm; + t->wipe_hook = Term_wipe_vm; + t->curs_hook = Term_curs_vm; + t->xtra_hook = Term_xtra_vm; + + /* Save it */ + term_screen = t; + + /* Activate it */ + Term_activate(term_screen); + + /* Done */ + done = TRUE; + + /* Success */ + return 0; +} + +/* Wait for keypress */ +int +getkey(void) +{ + return ((int)InKey()); +} + +/* Read key buffer if not empty */ + +int +getkeybuf(void) +{ + return ((int)InKeyBuf()); +} + + +/*********************************************************************/ +/*********************************************************************/ +/****************** Actual work with console *********************/ +/*********************************************************************/ + + +/* Low-level functions */ +int CNSINIT(char *path, int device); +int CNSTERM(char *path); +int CNSREAD(char *path, char *buffer, int buflen); +int CNSWRITE(char *path, char *buffer, int buflen); + +#define _PF1 (0xF1) +#define _PF2 (0xF2) +#define _PF3 (0xF3) +#define _PF4 (0xF4) +#define _PF5 (0xF5) +#define _PF6 (0xF6) +#define _PF7 (0xF7) +#define _PF8 (0xF8) +#define _PF9 (0xF9) +#define _PF10 (0x7A) +#define _PF11 (0x7B) +#define _PF12 (0x7C) +#define _PF13 (0xC1) +#define _PF14 (0xC2) +#define _PF15 (0xC3) +#define _PF16 (0xC4) +#define _PF17 (0xC5) +#define _PF18 (0xC6) +#define _PF19 (0xC7) +#define _PF20 (0xC8) +#define _PF21 (0xC9) +#define _PF22 (0x4A) +#define _PF23 (0x4B) +#define _PF24 (0x4C) + +#define _PA2 (0x6E) +#define _PA3 (0x6B) + +#define _CLEAR (0x60) + +#define _ENTER (0x7D) + +extern char cnscrstb[]; /* Hardware 3270 cursor offsets */ + +/* Console identificator */ +char *cons = "console"; + +/* Console interrupt flag; should be set by assembler patch */ +int CNSINTR; +/* Assembler function prototype; this handles console interrupt */ +extern int CNSHD(); + +/* Buffer for output stream (VM/ESA uses streams to control terminals */ +static char * ScrBuf; +/* Incoming buffer from console after cnsread */ +static char * InBuf; +/* User entered command buffer (paranoia: make it so long no one will + ** ever run short of it :) + */ +static char ComBuf[256]; +/* Pointer to current position in ComBuf */ +static char * ComPtr; +/* This array is used to clean up input field. + ** Comment: erase everything user entered after we accepted it. + */ +static char wiping[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +/* Flag: should we wipe input field ? */ +static int wipe = 0; +/* Counter: how many times did game checked if we pressed any key. + ** Comment: after every 100th we update the screen. + ** Comment2: because of slow work with screen it would be _very_ + ** unwise to make it more often. + */ +static int kbhitcount; +/* Keep length of collected output stream */ +static int BufLen; +/* Define array which will be used to bring actual cursor + ** (not game cursor!!!) back to the beginning of input field. + */ +static char CursorHome[] = {0, 0, 0, 0x13}; +/* Define array to make fields on the screen. + ** Comment: 2 fields: input field(writable), and game field(protected). + ** Comment2: We will change PSS settings into dumb repeating of color + ** setting if PSS fonts are not abailable. + */ +static char ScrField[] = + {0, 0, 0, 0x29, 0x03, 0xC0, 0xC1, 0x42, 0xF3, 0x43, 0xC1, \ + 0, 0, 0, 0x29, 0x03, 0xC0, 0x60, 0x42, 0xF1, 0x43, 0xC1}; +/* Last command user entered (for repeating purposes */ +static char LastCmd[256]; +/* Array which holds PFkeys definitions */ +static char PFcmd[25][80]; + + +/* Actually initialize console ... */ +void InitConsole(void) +{ + /* Use this to activate full screen mode after console has been + ** initialized. + */ + unsigned char init[6] = + {0xC2, 0x11, 0x40, 0x40, 0, 0}; + int i; + /* Array for checking is PSS fonts are loaded */ + char pss[256]; + + /* Allocate memory */ + ScrBuf = malloc(4100); + if (ScrBuf == NULL) + { + puts("Cannot mallocate memory for screen buffer!"); + exit(77); + } + /* Block system standarts... */ + system("cp set msg off"); + system("cp set emsg off"); + system("cp set imsg off"); + system("cp term brkkey none"); + /* Test PSS */ + system("desbuf"); + system("query display (stack"); + gets(pss); + i = 1; + if (pss[63] != 'P') i = 0; + if (pss[64] != 'S') i = 0; + if (pss[65] != 'S') i = 0; + if (pss[72] != '0') i = 0; + if (pss[73] != '1') i = 0; + if (pss[74] != 'A') i = 0; + if (pss[75] != 'B') i = 0; + if (i == 0) + { + /* No PSS. Cannot run without them... */ + puts("ERROR: Cannot run without PSS fonts!"); + exit(77); + } + ScrBuf[0] = 0xC2; + ScrBuf[1] = 0; + BufLen = 1; + /* Allocate memory */ + InBuf = malloc(200); + if (InBuf == NULL) + { + puts("Cannot mallocate memory for screen buffer!"); + exit(77); + } + /* Okay, lets make some intial assigments */ + InBuf[0] = 0; + ComBuf[0] = 0; + ComPtr = ComBuf; + LastCmd[0] = 0; + GetAddr(FIELD_SY, FIELD_SX, ScrField); + GetAddr(FIELD_EY, FIELD_EX, ScrField + 11); + GetAddr(FIELD_SY, FIELD_SX + 1, wiping); + GetAddr(FIELD_SY, FIELD_SX + 1, CursorHome); + /* Initialize console */ + cnsxinit(cons, 0x9, 1, CNSHD); + /* Activate full-screen mode */ + cnswrite(cons, init, 6); + /* No lines on screen were changed */ + for (i = 1; i < 25; i++) + DISP[i] = 0; + /* Corsor home... */ + AddScrBuf(CursorHome, sizeof(CursorHome)); + /* No console interrupt yet */ + CNSINTR = 0; + /* No check keypresses yet */ + kbhitcount = 0; + /* Let's load 'profile angband' for PFs settings */ + LoadProfile(); +} + +void TerminateConsole(void) +{ + free(ScrBuf); + free(InBuf); + /* Terminate console */ + cnsterm(cons); + /* Restore system defaults. + ** Comment: better we should have written them down at start but + ** it is reasonably difficult to make, so just set standart values. + */ + system("cp set msg on"); + system("cp set emsg on"); + system("cp set imsg on"); + system("cp term brkkey pa1"); +} + +/* Reset collected output stream */ +void ResetScrBuf(void) +{ + int i; + unsigned char attr; + + /* Where shall cursor be ? */ + GetAddr(cury, curx, ScrBuf + BufLen); + BufLen += 3; + /* Actually 'make' cursor : underline symbol */ + ScrBuf[BufLen++] = 0x28; + ScrBuf[BufLen++] = 0x41; + ScrBuf[BufLen++] = 0xF4; + attr = *(ScreenAttr + (cury - 1) * cols + curx - 1); + ScrBuf[BufLen++] = 0x28; + ScrBuf[BufLen++] = 0x42; + ScrBuf[BufLen++] = attr | 0x80; + ScrBuf[BufLen++] = 0x28; + ScrBuf[BufLen++] = 0x43; + if (attr > 0x80) ScrBuf[BufLen++] = 0xC1; + else ScrBuf[BufLen++] = 0xC2; + ScrBuf[BufLen++] = *(VirtualScreen + (cury - 1) * cols + curx - 1); + ScrBuf[BufLen++] = 0x28; + ScrBuf[BufLen++] = 0x41; + ScrBuf[BufLen++] = 0x00; + ScrBuf[BufLen++] = 0x28; + ScrBuf[BufLen++] = 0x43; + ScrBuf[BufLen++] = 0xC1; + /* Draw screen fields. + ** Comment: paranoia, should always be there, but won't be any worse + ** if we redraw them. + */ + memcpy(ScrBuf + BufLen, ScrField, 22); + if (wipe) + { + /* If we should wipe input field, let's do it. */ + wipe = 0; + memcpy(ScrBuf + BufLen + 22, wiping, sizeof(wiping)); + /* Actually write to terminal */ + cnswrite(cons, ScrBuf, BufLen + 22 + sizeof(wiping)); + } + else + { + /* Actually write to terminal */ + cnswrite(cons, ScrBuf, BufLen + 22); + } + /* Discard old output stream */ + ScrBuf[0] = 0xC2; + ScrBuf[1] = 0; + BufLen = 1; +} + +/* Just add some more to output stream */ +void AddScrBuf(char * ptr, int len) +{ + /* Stream cannot be longer than 4k, so reset it */ + if (len + BufLen > 4000) ResetScrBuf(); + memcpy(ScrBuf + BufLen, ptr, len); + BufLen += len; +} + +/* Calculate codes for cursor setting and write them down into *stream. + ** Comment: system has _really crazy tables for this calculation so + ** we need function for this. + */ +void GetAddr(int y, int x, char *stream) +{ + int sx, sy, len; + + len = y * 80 + x - 81; + + sx = len & 0x3F; + sy = len >> 6; + + *stream++ = 0x11; + /* Use standart array for cursor offsets (VMSERV TXTLIB) */ + *stream++ = cnscrstb[sy]; + *stream = cnscrstb[sx]; +} + +/* Okay, program requested pressed key, let's return it */ +char InKey(void) +{ + char ret; + char * info; + int i; + char *ptr, *ptrs; + int PF; + int prev; + + /* If we didn't finish previous line user entered just return + ** next symbol. + ** Comment: unlikely IBM PC and others user may enter string + ** of any length (limited by input field length to 9 + ** symbols) and only them by pressing ENTER key or + ** functional key make real console interrupt. + ** So we should handle everything user entered. + */ + if (*ComPtr) + { + ret = *ComPtr; + ComPtr++; + return (ret); + } + /* If we get here than user command buffer is empty and we have + ** actually wait for new command. + */ + /* Okay, update screen before :) */ + ResetDISP(); + /* Well, now wait till user enters something and read it. */ + cnsread(cons, InBuf, 200); + /* Oh, we already handling interrupt so, reset interrupt flag */ + CNSINTR = 0; + /* No previous cmd inserted yet */ + prev = 0; + /* User pressed CLEAR key. Redraw all screen then. */ + if (*InBuf == 0x6D) + { + /* Hack: mark all lines as changed */ + for (i = 1; i < 26; i++) + DISP[i] = 1; + /* Cursor home */ + AddScrBuf(CursorHome, sizeof(CursorHome)); + /* Redraw the whole screen */ + ResetDISP(); + /* Hack: we should return something, shouldn't we? + ** Just return CR. It seems safest. + */ + return (13); + } + /* Okay parse stream from console to make string only of + ** user's input. + */ + info = memchr(InBuf, 0x1D, 200); + info += 2; + info[9] = 0; + /* Mark that we should clear input field */ + wipe = 1; + /* Cursor home */ + AddScrBuf(CursorHome, sizeof(CursorHome)); + /* Pointer to current letter in buffered command set to start */ + ComPtr = ComBuf; + /* Clear length buffer */ + ComBuf[0] = 0; + switch (*InBuf) + { + /* PA2 & PA1 */ + case 0x6E: + ; + case 0x6C: + /* These 2 keys are supposed to mean 'ESC' */ + return (27); + break; + /* Hack: determine which PF key was exactly pressed. + */ + case _PF1: + PF = 1; + break; + case _PF2: + PF = 2; + break; + case _PF3: + PF = 3; + break; + case _PF4: + PF = 4; + break; + case _PF5: + PF = 5; + break; + case _PF6: + PF = 6; + break; + case _PF7: + PF = 7; + break; + case _PF8: + PF = 8; + break; + case _PF9: + PF = 9; + break; + case _PF10: + PF = 10; + break; + case _PF11: + PF = 11; + break; + case _PF12: + PF = 12; + break; + case _PF13: + PF = 13; + break; + case _PF14: + PF = 14; + break; + case _PF15: + PF = 15; + break; + case _PF16: + PF = 16; + break; + case _PF17: + PF = 17; + break; + case _PF18: + PF = 18; + break; + case _PF19: + PF = 19; + break; + case _PF20: + PF = 20; + break; + case _PF21: + PF = 21; + break; + case _PF22: + PF = 22; + break; + case _PF23: + PF = 23; + break; + case _PF24: + PF = 24; + break; + /* Uh, user pressed ENTER. + ** Determine if we should add 'CR' at the end or not ? + */ + case _ENTER: + PF = 0; + /* Copy entered string into buffer */ + strcpy(ComBuf, info); + /* Never end strings of length 1 or 0 with CR */ + if (strlen(ComBuf) < 2) break; + /* If string ends with R* or R& add CR */ + ptr = info + strlen(info) - 1; + if (*ptr == '*' || *ptr == '&') + { + ptr--; + if (ptr < info) break; + if (*ptr != 'R') break; + ptr = ComBuf + strlen(ComBuf); + ptr[0] = 13; + ptr[1] = 0; + break; + } + /* Well, only numbers should be padded with CR. + ** Comment: handle 18/... too. + */ + if (!isdigit(*ptr)) break; + ptr--; + i = 1; + while (ptr >= info) + { + if (*ptr == 'R') break; + if (*ptr == '@' && ptr == info) + break; + if (*ptr == '/') + { + i = 0; + if (*(ptr - 1) != '8') break; + if (*(ptr - 2) != '1') break; + if ((ptr - 2) != info) break; + i = 1; + break; + } + if (!isdigit(*ptr)) + { + i = 0; + break; + } + ptr--; + } + if (i) + ptr = ComBuf + strlen(ComBuf); + ptr[0] = 13; + ptr[1] = 0; + break; + default: + PF = 0; + } + /* Okay let's proceed with parsing PFkeys commands */ + ptrs = PFcmd[PF]; + ptr = ComBuf; + /* If key actually was PF and we didn't run into end of PF + ** command definition... + */ + while (*ptrs && PF) + { + /* If not '\' just copy symbol into buffer */ + if (*ptrs != '\\') + { + *ptr = *ptrs; + ptr++; + ptrs++; + continue; + } + /* We have discovered '\'. Let's resolve it. */ + ptrs++; + switch (*ptrs) + { + /* End of line ? Do nothing then. */ + case 0: + break; + /* User actually wants '\' */ + case '\\': + *ptr = '\\'; + ptr++; + break; + /* User wants his previous command inserted. */ + case 'p': + /* Set flag that we used previous command */ + prev = 1; + strcpy(ptr, LastCmd); + ptr = ComBuf + strlen(ComBuf); + break; + /* Insert string user actually entered */ + case 's': + strcpy(ptr, info); + ptr = ComBuf + strlen(ComBuf); + break; + /* User wants 'CR' */ + case 'n': + *ptr = 13; + ptr++; + break; + /* Simulate CTRL key pressing */ + case '^': + ptrs++; + if (!(*ptrs)) break; + *ptr = KTRL(*ptrs); + ptr++; + break; + /* ESC */ + case 'c': + *ptr = 27; + ptr++; + break; + /* Hmm, urecognized command. Just copy letter. */ + default: + *ptr = *ptrs; + ptr++; + } + if (ptrs) ptrs++; + } + /* Terminate string with 0 if neccessary */ + if (PF) *ptr = 0; + /* Empty string? User probably wants to send CR. */ + if (!(*ComBuf)) + { + return (13); + } + /* Okay, set pointer to next letter */ + ComPtr++; + /* Backup last command if not empty */ + ptr = ComBuf; + /* String still "empty" */ + i = 1; + while ((*ptr) && i) + { + if ((*ptr != 13) && (*ptr != 27) && (*ptr != ' ')) + i = 0; + ptr++; + } + /* Never update previous command if we inserted it. + ** Comment: this is to avoid recursively multiplying previous + ** commands. + */ + if ((!i) && (!prev)) + strcpy(LastCmd, ComBuf); + /* Return something */ + return (*ComBuf); +} + +/* Get symbol from buffer if exists */ + +char InKeyBuf(void) +{ + char ret; + + ret = *ComPtr; + if (ret) ComPtr++; + return (ret); +} + +/* Here we draw all changed lines */ +void ResetDISP(void) +{ + int i; + + /* No need to redraw screen in near future */ + kbhitcount = 0; + for (i = 1; i < 25; i++) + if (DISP[i] != 0) + { + /* If line was changed, it won't stay changed any more */ + DISP[i] = 0; + /* We don't want to erase input field definitons from + ** screen, so check it carefully. + */ + switch (i) + { + case FIELD_SY: + ShowLine(i, 1, FIELD_SX - 1); + if (i == FIELD_EY) + { + ShowLine(i, FIELD_EX + 1, 80-FIELD_EX); + } + break; + case FIELD_EY: + ShowLine(i, FIELD_EX + 1, 80-FIELD_EX); + break; + default: + ShowLine(i, 1, 80); + } + } + /* Okay, actually show something */ + ResetScrBuf(); +} + +/* Did user press something? */ +int kbhit(void) +{ + kbhitcount++; + if (kbhitcount > 99) + { + /* We waited long enough, time to redraw screen. + ** Comment: during sleep every 100th turn is shown. + */ + kbhitcount = 0; + ResetDISP(); + } + return (CNSINTR); +} + +/* Let's show requested line(or part of it). */ +void ShowLine(int y, int x, int len) +{ + char slbuf[512]; + char *ptr, *scr, *attr; + int i; + unsigned char curattr; + + ptr = slbuf + 3; + /* Hack: was used for older version to place 25th string on + ** 24th. + */ + if (y < 25) + GetAddr(y, x, slbuf); + else + GetAddr(24, x, slbuf); + /* Set some adresses */ + curattr = 0; + scr = VirtualScreen + (y - 1) * cols + x - 1; + attr = ScreenAttr + (y - 1) * cols + x - 1; + /* Let's proceed with string. */ + for (i = 0; i < len; i++) + { + /* Attribute has changed ? Let's add codes for changing color */ + if (*attr != curattr) + { + /* Pss has changed ? Let's change pss. */ + if (((*attr)&0x80) != (curattr&0x80) || (!curattr)) + { + *ptr++ = 0x28; + *ptr++ = 0x43; + if (*attr > 0x80) *ptr++ = 0xC1; + else *ptr++ = 0xC2; + } + /* Color has changed ? Let's change it. */ + if (((*attr)&0x7F) != (curattr&0x7F)) + { + *ptr++ = 0x28; + *ptr++ = 0x42; + if (*attr > 0x80) *ptr++ = *attr; + else *ptr++ = *attr + 0x80; + } + curattr = *attr; + } + *ptr++ = *scr; + scr++; + attr++; + } + /* Add string to output stream */ + AddScrBuf(slbuf, ptr - slbuf); +} + +void LoadProfile(void) +{ + + FILE *fp; + char line[128], *ptr, *pfptr, *p; + int pf, i; + + for (i = 1; i <= 24; i++) strcpy(PFcmd[i], "\\s"); + + fp = fopen("PROFILE ANGBAND", "r"); + if (!fp) return; + { + while (fgets(line, 128, fp)) + { + if (*line == '#') continue; + ptr = strstr(line, "PF"); + if (!ptr) continue; + ptr += 2; + p = ptr; + while (isdigit(*p)) ++p; + *p++ = 0; + pf = atoi(ptr); + if (pf < 1 || pf > 24) continue; + ptr = strchr(p, '"'); + ++ptr; + p = strchr(ptr, '"'); + if (!p) + { + puts("'\"' missing in PROFILE ANGBAND."); + continue; + } + *p = 0; + strcpy(PFcmd[pf], ptr); + } + } +} + +/* + ** + ** File descriptor emulation for VM/ESA + ** + ** + */ + +#include <string.h> +#include <stdio.h> +#include "fcntl.h" + +static FILE *file_descriptors[40]; + +int +open(char *name, int flags, int mode) +{ + char fmode[16]; + FILE *fp; + int i; + + strcpy(fmode, "rb"); + if ((flags & O_WRONLY) || (flags & O_RDWR)) strcpy(fmode, "wb+"); + + fp = fopen(name, fmode); + + if (!fp) return ( -1); + for (i = 1; i < 40; i++) + if (!file_descriptors[i]) + { + file_descriptors[i] = fp; + return (i); + } + return ( -1); +} + +void +close(int fd) +{ + fclose(file_descriptors[fd]); +} + +int +read(int fd, char *buff, int bytes) +{ + return (fread(buff, 1, bytes, file_descriptors[fd])); +} + +int +write(int fd, char *buff, int bytes) +{ + return (fwrite(buff, 1, bytes, file_descriptors[fd])); +} + +long +lseek(int fd, long pos, int set) +{ + return (fseek(file_descriptors[fd], pos, set)); +} + +void +unlink(char *filename) +{ + remove(filename); +} + + +#endif /* USE_VME */ + |