diff -c src/.pcmrc src.new/.pcmrc *** src/.pcmrc Tue Apr 28 14:13:38 1992 --- src.new/.pcmrc Wed May 6 14:32:14 1992 *************** *** 1,5 **** floppy 720boot.dsk 720k bios pcmbios.bin keys apollo.keys ! floppy dos.floppy 1.2m ! --- 1,5 ---- floppy 720boot.dsk 720k bios pcmbios.bin keys apollo.keys ! #floppy /dev/rfd0c 720k ! floppy 12clear 1.2m diff -c src/Makefile src.new/Makefile *** src/Makefile Sat May 2 00:12:50 1992 --- src.new/Makefile Wed May 6 09:34:46 1992 *************** *** 1,25 **** ! all: pcm ! CFLAGS= -O ! LDFLAGS= -lX11 - bsd: - make "CFLAGS= -g -pg -DNEED_VPRINTF" "LDFLAGS = -pg -lX11" - - ultrix: - make "CFLAGS= -O -g3" "LDFLAGS = -lX11" - SRC = main.c interpret.c jmp.c dis.c mov.c operand.c bios.c flags.c \ ! write.c stack.c logical.c arith.c int.c window.c misc.c port.c \ ! vprintf.c OBJ = main.o interpret.o jmp.o dis.o mov.o operand.o bios.o flags.o \ ! write.o stack.o logical.o arith.o int.o window.o misc.o port.o \ ! vprintf.o ! pcm: $(OBJ) pcmbios.bin $(CC) -o pcm $(OBJ) $(LDFLAGS) saber_src: $(SRC) #load $(CFLAGS) $(SRC) $(LDFLAGS) --- 1,25 ---- ! all: pcm pcmbios.bin ! CFLAGS=-g -I/usr/openwin/include ! LDFLAGS= -L /usr/openwin/lib -lX11 SRC = main.c interpret.c jmp.c dis.c mov.c operand.c bios.c flags.c \ ! write.c stack.c logical.c arith.c int.c window.c misc.c port.c OBJ = main.o interpret.o jmp.o dis.o mov.o operand.o bios.o flags.o \ ! write.o stack.o logical.o arith.o int.o window.o misc.o port.o ! pcm: $(OBJ) $(CC) -o pcm $(OBJ) $(LDFLAGS) + pcmbios.bin: rasm pcmbios.asm + rasm -n -o pcmbios.bin pcmbios.asm + + rasm: rasm.o + $(CC) -o rasm rasm.o + + rasm.o: rasm.h + saber_src: $(SRC) #load $(CFLAGS) $(SRC) $(LDFLAGS) *************** *** 31,48 **** LDFLAGS="-L /usr/ucblib -lX11 -lnsl -lucb" clean: ! /bin/rm -f *~ *.o pcm tar: ! tar cvf pcm.tar $(SRC) $(RSRC) Makefile sim.h pcm.xbm pcmbios.bin \ ! .pcmrc pcm.icon apollo.keys sun.keys fonts README 720boot.dsk \ ! LICENSE notes pcm.tty dist: ! tar cvf pcm.tar $(SRC) $(RSRC) Makefile sim.h pcm.xbm pcmbios.bin \ ! .pcmrc pcm.icon apollo.keys sun.keys fonts README LICENSE \ ! pcmbios.asm notes pcm.tty - arith.c bios.c dis.c flags.c int.c interpret.c jmp.c logical.c: sim.h - main.c misc.c mov.c operand.c port.c stack.c window.c write.c: sim.h --- 31,45 ---- LDFLAGS="-L /usr/ucblib -lX11 -lnsl -lucb" clean: ! /bin/rm -f *~ *.o pcm + SRC_LIST = $(SRC) Makefile sim.h pcm.xbm rasm.c rasm.h .pcmrc pcm.icon \ + apollo.keys sun.keys dec.keys fonts README LICENSE notes pcm.tty \ + pcmbios.asm new.keys rasm.c rasm.h tar: ! tar cvf pcm.tar $(SRC_LIST) 720boot.dsk dist: ! tar cvf pcm.tar $(SRC_LIST) Only in src: RCS diff -c src/README src.new/README *** src/README Wed Apr 29 20:56:43 1992 --- src.new/README Wed May 6 14:17:42 1992 *************** *** 9,34 **** you might try the tty target instead (and have a look at the pcm.tty script). On startup, pcm reads a file called .pcmrc in the current directory. It contains information on mapping the bios, keyboard and ! floppy disks. ! BIOS: The bios source is in pcmbios.asm. Unfortunately, the assembler ! used to assemble it is a C translation of David Whitman's CHASM, which ! I may not redistribute. You must therefore use the pre-assembled version ! of this file (pcmbios.bin) until a replacement assembler is available. ! The bios is liberally sprinkled with special escapes to the emulator. ! My goal is to work toward reducing these as much as possible. Specify ! the bios file in .pcmrc. E.g., "bios pcmbios.bin" VIDEO: This needs more work. Currently only things that go through BIOS int 10 make it to the screen. The scrolling and cursor update occasionally leaves little artifacts around as well. At least CLS ! works. BTW, I am an X novice so if you see something in window.c ! that is stupid and you can do better, please dive right in. ! KEYBOARD: The keyboard interface directly maps X keycodes into PC ! scan codes. You need to setup a key definition file that specifies ! this mapping. There are examples in apollo.keys and sun.keys. ! Specify the keyboard in .pcmrc. E.g., "keys sun.keys" FLOPPY: Up to 4 floppies are supported. Right now only 720k, 360k 1.2m and 1.44m are included. Other types are straightforward to add --- 9,34 ---- you might try the tty target instead (and have a look at the pcm.tty script). On startup, pcm reads a file called .pcmrc in the current directory. It contains information on mapping the bios, keyboard and ! floppy disks. Lines with '#' as their first character are ignored. ! BIOS: The bios source is in pcmbios.asm. Use the real-mode assembler ! provided (rasm) to assemble it. The bios is liberally sprinkled with ! special escapes to the emulator. My goal is to work toward reducing ! these as much as possible. Specify the bios file in .pcmrc. E.g., ! "bios pcmbios.bin" VIDEO: This needs more work. Currently only things that go through BIOS int 10 make it to the screen. The scrolling and cursor update occasionally leaves little artifacts around as well. At least CLS ! works. BTW, I am an X novice so if you see something in window.c that ! is stupid and you can do better, please dive right in. ! KEYBOARD: The keyboard interface directly maps X keycodes into PC scan ! codes. You need to setup a key definition file that specifies this ! mapping. There are example files for apollo, dec and sun keyboards. ! There is also a perl script (new.keys) which may be useful in ! generating new key files. Specify the keyboard in .pcmrc. E.g., ! "keys sun.keys" FLOPPY: Up to 4 floppies are supported. Right now only 720k, 360k 1.2m and 1.44m are included. Other types are straightforward to add Only in src: bios-asm.arc diff -c src/bios.c src.new/bios.c *** src/bios.c Wed May 6 12:01:15 1992 --- src.new/bios.c Wed May 6 14:15:05 1992 *************** *** 25,36 **** * are only for providing a basic mechanism prior to better * support in the port emulation/8086 BIOS code. */ - #include #include "sim.h" unsigned char *vidbase; unsigned char *start_line; extern unsigned short retf2; - extern jmp_buf reboot_env; extern unsigned char keyhead, keytail; unsigned short infloop = 0xfeeb; unsigned char nop = 0x90; --- 25,34 ---- *************** *** 94,168 **** return CSPTR + 0xfff0; } - /* - * Bootstrap loader - */ - unsigned char *int_19() { - /* - * perform bootstrap operations - */ - unsigned char *cp; - int i; - - clear_window(); - - keyhead = keytail = 0; - - pc_mem[0x400+0x13] = 0x7f; /* installed memory = 640k */ - pc_mem[0x400+0x14] = 0x2; - /* - * interrupt vectors - */ - bcopy(bios_ivec,pc_mem,sizeof(bios_ivec)); - /* - * equipment word: no printers, serial ports, 1 disk drive - * 80x25 bw initial video mode - */ - pc_mem[0x400+0x10] = 0x30; - /* - * keyboard init - */ - pc_mem[0x41a] = 0x1e; /* buffer head ptr */ - pc_mem[0x41c] = 0x1e; /* buffer tail ptr */ - pc_mem[0x480] = 0x1e; /* buffer start */ - pc_mem[0x482] = 0x3e; /* buffer end (16 char) */ - /* - * video init - */ - pc_mem[0x400+0x49] = 0x7; /* monochrome mode */ - pc_mem[0x400+0x4a] = 0x50; /* 80 columns */ - pc_mem[0x400+0x4d] = 0x10; /* 4k page size */ - /* - * print banner - */ - AH = 0xe; - cp = pc_mem + 0xfe000; - while (*cp) { - AL = *cp++; - int_10(); - } - INTERRUPT = 1; - *((unsigned int *)(pc_mem+4*0x1e)) = 0xc7ef00f0; /* disk parm table */ - ESPTR = pc_mem; /* es:bx = 0:7c00 */ - BX = 0x7c00; - DX = 0; /* drive 0, head 0 */ - AX = 0x201; /* read 1 sector */ - CX = 1; /* track 0, sector 1 */ - int_13(); - CSPTR = DSPTR = ESPTR = SSPTR = pc_mem; - CS = DS = ES = SS = 0; - /* - * temp kludge init - */ - SP = 0xf8; - BP = 0; - SI = 0xe015; - DI = 0x80; - return CSPTR + 0x7c00; - } - - /* * BIOS video display */ --- 92,98 ---- *************** *** 187,193 **** scroll_screen(25, BH); } break; ! case 0x9: /* "write char and attr at cursor position */ /* AL = char, BH = page, BL = attr, CX = #times to write? */ { int tmp_X = CUR_X; --- 117,123 ---- scroll_screen(25, BH); } break; ! case 0x9: /* "write char and attr at cursor position */ /* AL = char, BH = page, BL = attr, CX = #times to write? */ { int tmp_X = CUR_X; *************** *** 194,204 **** int tmp_Y = CUR_Y; int count = CX; do { ! put_char(tmp_Y, tmp_X++, ((int) AL << 8) | BL, 1); ! if (tmp_X >= 80) { ! tmp_X = 0; ! tmp_Y++; ! } } while (--count > 0); } break; --- 124,134 ---- int tmp_Y = CUR_Y; int count = CX; do { ! put_char(tmp_Y, tmp_X++, ((int) AL << 8) | BL, 1); ! if (tmp_X >= 80) { ! tmp_X = 0; ! tmp_Y++; ! } } while (--count > 0); } break; *************** *** 267,283 **** track = CH; drive = DL; head = DH; - /* - * I'm putting this check here to protect to make sure that - * disk[drive] is valid and doesn't cause a crash. If this is - * change is sane, then you can remove the range checking for drive - * which occurs later on in this function --- TYT - */ if (drive < 0 || drive >= numdrives) { ! if (AH == 0x8) ! DX = 0; /* for Minix */ ! SET_CARRY; ! return; } diskaddr = ((disk[drive].heads * track + head) * disk[drive].sectors + sector - 1) * 512; --- 197,207 ---- track = CH; drive = DL; head = DH; if (drive < 0 || drive >= numdrives) { ! if (AH == 0x8) { ! DX = 0; /* For Minix */ ! } ! SET_CARRY; } diskaddr = ((disk[drive].heads * track + head) * disk[drive].sectors + sector - 1) * 512; *************** *** 284,295 **** memaddr = ESPTR + BX; switch (AH) { case 0x0: /* reset */ ! if (drive < 0 || drive >= numdrives) { ! SET_CARRY; ! } ! else { ! CLR_CARRY; ! } break; case 0x1: /* status */ AL = (DL & 0x80) ? 0x80 : 0; --- 208,214 ---- memaddr = ESPTR + BX; switch (AH) { case 0x0: /* reset */ ! CLR_CARRY; break; case 0x1: /* status */ AL = (DL & 0x80) ? 0x80 : 0; *************** *** 296,303 **** CLR_CARRY; break; case 0x2: /* read */ ! if (drive < 0 || drive > numdrives || ! sector < 0 || sector > disk[drive].sectors) { SET_CARRY; } else { --- 215,221 ---- CLR_CARRY; break; case 0x2: /* read */ ! if (sector < 0 || sector > disk[drive].sectors) { SET_CARRY; } else { *************** *** 308,315 **** } break; case 0x3: /* write */ ! if (drive < 0 || drive > numdrives || ! sector < 0 || sector > disk[drive].sectors || disk[drive].readonly) { SET_CARRY; } --- 226,232 ---- } break; case 0x3: /* write */ ! if (sector < 0 || sector > disk[drive].sectors || disk[drive].readonly) { SET_CARRY; } *************** *** 328,345 **** CLR_CARRY; break; case 0x08: /* get disk parameters */ ! if (drive < 0 || drive >= numdrives) { ! DX = 0; /* For minix */ ! SET_CARRY; ! } ! else { ! DH = disk[drive].heads-1; ! CH = disk[drive].tracks-1; ! CL = disk[drive].sectors; ! DL = 1; ! AH = DI = 0; ! CLR_CARRY; ! } break; case 0x15: /* read drive type */ AH = 2; --- 245,256 ---- CLR_CARRY; break; case 0x08: /* get disk parameters */ ! DH = disk[drive].heads-1; ! CH = disk[drive].tracks-1; ! CL = disk[drive].sectors; ! DL = 1; ! AH = DI = 0; ! CLR_CARRY; break; case 0x15: /* read drive type */ AH = 2; *************** *** 463,469 **** DH = to_bcd(the_time->tm_mon+1); CL = to_bcd(the_time->tm_year % 100); CH = to_bcd((the_time->tm_year/100) + 19); - /*debug = 1;*/ CLR_CARRY; default: printf("unknown int_1A command: 0x%x\n",AH); --- 374,379 ---- *************** *** 557,609 **** /*int_vec(0x1c);*/ /* return i_cf(0);*/ return 0; - } - - /* - * Keyboard support - */ - - unsigned char *int_16() { - unsigned char *headptr, *tailptr; - unsigned short offset, bufend; - headptr = pc_mem + 0x41a; - tailptr = pc_mem + 0x41c; - INTERRUPT = 1; - switch(AH) { - case 0x0: /* read */ - while (*(unsigned short *)headptr == - *(unsigned short *)tailptr) { /* no char */ - interpret(&nop); /* give int_9 a chance */ - } - offset = *headptr; - offset |= ((unsigned int)*(headptr+1)) << 8; - AH = pc_mem[0x400+offset++]; - AL = pc_mem[0x400+offset++]; - *headptr = offset; - *(headptr+1) = offset >> 8; - bufend = pc_mem[0x482] | ((unsigned int)pc_mem[0x483]) << 8; - if (offset == bufend) { /* overflow? */ - *(unsigned short *)(pc_mem+0x41a) = *(unsigned short *)(pc_mem+0x480); - } - return i_cf(0); - break; - case 0x1: /* check for input */ - FLAGS_OK = 1; - ZERO = (*(unsigned short *)headptr == *(unsigned short *)tailptr); - CARRY = 0; - return i_ca((unsigned char *)&retf2); - break; - default: - printf("unknown int_16 command: 0x%x\n",AH); - CARRY = 1; - FLAGS_OK = 0; - return i_ca((unsigned char *)&retf2); - } - } - - extern int debug; - void int_09() { - pcmexit("int_09 is obsolete...\n"); } mgetw(fp) --- 467,472 ---- Only in src: bios.c~ Only in src: buildpatch Only in src: buildpatch~ diff -c src/dec.keys src.new/dec.keys *** src/dec.keys Wed Apr 29 22:43:27 1992 --- src.new/dec.keys Fri May 1 11:09:37 1992 *************** *** 2,7 **** --- 2,8 ---- # keydef file for Vax LK201 keyboard # # Quickly hacked together by Ted Ts'o (tytso@mit.edu) + # Should work for both Vaxstations and Decstations. # # format is X-keycode PC-scancode (comment) # diff -c src/dis.c src.new/dis.c *** src/dis.c Mon Apr 27 14:56:32 1992 --- src.new/dis.c Wed May 6 10:49:40 1992 *************** *** 21,26 **** --- 21,36 ---- * An 8086 disassembler */ + + /* + * #define MAIN for a standalone version + */ + /* #define MAIN 1 */ + + #ifdef MAIN + #define extern + #endif /* MAIN */ + #include "sim.h" /* *************** *** 86,91 **** --- 96,140 ---- static unsigned char seg_val; static char fbuf[9] = " "; + #ifdef MAIN + + static unsigned char *start; + + unsigned char *buffer; + main(argc, argv) + int argc; char **argv; { + int fd; + int size; + char *filename; + unsigned char *bptr; + if (argc != 2) { + printf("usage: %s filename\n",argv[0]); + exit(1); + } + if ((fd = open(argv[1],0)) < 0) { + perror(argv[1]); + exit(1); + } + if ((size = lseek(fd,0,2)) < 0) { + perror("lseek"); + exit(1); + } + lseek(fd,0,0); + if ((buffer = (unsigned char *)malloc(size)) == NULL) { + printf("insufficient memory to load \"%s\"\n",argv[1]); + exit(1); + } + if (read(fd,(char *)buffer,size) != size) { + perror("read"); + exit(1); + } + close(fd); + start = buffer; + for (bptr = buffer; bptr < buffer+size; ) { + bptr += dis_86(bptr,start,CS); + } + } + #else char *pflags() { fbuf[0] = CARRY ? '1' : '0'; fbuf[1] = PARITY ? '1' : '0'; *************** *** 97,102 **** --- 146,152 ---- fbuf[7] = OVERFLOW ? '1' : '0'; return fbuf; } + #endif /* MAIN */ dis_86(cp,mem_start,cs_val) unsigned char *cp, *mem_start; *************** *** 439,446 **** } u__short = (cp - mem_start) - (cs_val << 4); ! printf("0x%x %d %04.4x.%04.4x.%04.4x.%04.4x.%04.4x.%04.4x.%04.4x.%04.4x %04.4x:%04.4x ", ! pc_mem[0xe450+0x5e7],TIMELEFT,AX,CX,DX,BX,SP,BP,SI,DI,CS,u__short); u__short2 = disbp - cp; for (u__short = 0; u__short < u__short2; u__short++) { printf("%02.2x",*(cp+u__short)); --- 489,499 ---- } u__short = (cp - mem_start) - (cs_val << 4); ! #ifndef MAIN ! printf("0x%x %d %04.4x.%04.4x.%04.4x.%04.4x.%04.4x.%04.4x.%04.4x.%04.4x ", ! pc_mem[0xbc],TIMELEFT,AX,CX,DX,BX,SP,BP,SI,DI); ! #endif /* MAIN */ ! printf("%04.4x:%04.4x ",CS,u__short); u__short2 = disbp - cp; for (u__short = 0; u__short < u__short2; u__short++) { printf("%02.2x",*(cp+u__short)); *************** *** 455,461 **** --- 508,518 ---- printf(" "); } } + #ifndef MAIN printf("%s %s\n",outbuf,pflags()); + #else + printf("%s\n",outbuf); + #endif /* MAIN */ if (segment_override) { seg_val = 1; cp++; Only in src: flags.c.orig Only in src: flags.c~ Common subdirectories: src/fonts and src.new/fonts diff -c src/interpret.c src.new/interpret.c *** src/interpret.c Fri May 1 23:30:53 1992 --- src.new/interpret.c Wed May 6 14:15:34 1992 *************** *** 85,91 **** if (--TIMELEFT == 0) { ip = do_interrupt(ip); } ! /* dis_86(ip,pc_mem,CS);*/ return (*ifun[*ip])(ip+1); } --- 85,91 ---- if (--TIMELEFT == 0) { ip = do_interrupt(ip); } ! /* dis_86(ip,pc_mem,CS); */ return (*ifun[*ip])(ip+1); } *************** *** 97,119 **** */ unsigned char *atomic_interpret(ip) unsigned char *ip; { return (*ifun[*ip])(ip+1); } #endif unsigned char *interpret_loop(start) ! unsigned char *start; ! { ! register unsigned char *ip; ! ! ip = start; ! ! while (1) { ! if (--TIMELEFT == 0) { ! ip = do_interrupt(ip); ! } ! ! /* dis_86(ip,pc_mem,CS);*/ ! ip = (*ifun[*ip])(ip+1); ! } } --- 97,116 ---- */ unsigned char *atomic_interpret(ip) unsigned char *ip; { + /* dis_86(ip,pc_mem,CS);*/ return (*ifun[*ip])(ip+1); } #endif unsigned char *interpret_loop(start) ! unsigned char *start; { ! register unsigned char *ip; ! ip = start; ! while (1) { ! if (--TIMELEFT == 0) { ! ip = do_interrupt(ip); ! } ! /* dis_86(ip,pc_mem,CS);*/ ! ip = (*ifun[*ip])(ip+1); ! } } Only in src: interpret.c.2 Only in src: interpret.c.orig Only in src: key-gen.pl Only in src: logical.c.orig diff -c src/main.c src.new/main.c *** src/main.c Fri May 1 18:18:43 1992 --- src.new/main.c Wed May 6 14:16:17 1992 *************** *** 18,34 **** */ #include - #include #define extern #include "sim.h" extern int xwin; - jmp_buf reboot_env; int pcm_quit; #ifndef SABER ! /* Saber 2.1 and 3.0.1 can't deal with varargs */ #include pcmexit(va_alist) --- 18,32 ---- */ #include #define extern #include "sim.h" extern int xwin; int pcm_quit; #ifndef SABER ! /* Saber is reported to have trouble with varargs */ #include pcmexit(va_alist) *************** *** 72,78 **** } } init_machine(); - setjmp(reboot_env); init_int(); pc = (unsigned char *)cold_boot(); interpret_loop(pc); --- 70,75 ---- *************** *** 92,97 **** --- 89,95 ---- pcmexit("error reading .pcmrc\n"); } while (fgets(buf, 127, rc)) { + if (buf[0] == '#') continue; if (cp = strchr(buf,'\n')) { *cp = 0; } Only in src: misc.c.orig Only in src: misc.c~ Only in src: mov.c.orig Only in src.new: new.keys diff -c src/notes src.new/notes *** src/notes Tue Apr 28 14:22:05 1992 --- src.new/notes Wed May 6 09:30:36 1992 *************** *** 40,44 **** network disk drives (ala Mach's mdos?) do video attributes right move more functionality into 8086 BIOS code - write a freely redistributable real mode assembler --- 40,43 ---- Only in src: out.keys Only in src: patches-sent diff -c src/pcmbios.asm src.new/pcmbios.asm *** src/pcmbios.asm Tue Apr 28 10:50:00 1992 --- src.new/pcmbios.asm Wed May 6 14:27:11 1992 *************** *** 1,45 **** ! ;/* ! ; Pcm: a PC eMulator ! ; Copyright (C) 1992 Electronetics, Inc. All rights reserved. ! ; ! ; This program is free software; you can redistribute it and/or modify ! ; it under the terms of the GNU General Public License as published by ! ; the Free Software Foundation; either version 2 of the License, or ! ; (at your option) any later version. ! ; ! ; This program is distributed in the hope that it will be useful, ! ; but WITHOUT ANY WARRANTY; without even the implied warranty of ! ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! ; GNU General Public License for more details. ! ; ! ; You should have received a copy of the GNU General Public License ! ; along with this program; if not, write to the Free Software ! ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! ; */ ! org 0e000 ! CR equ 0d ! LF equ 0a - banner db 'PCM v0.5 Copyright (c) Electronetics, Inc. 1991, 1992',CR,LF,00 ;----------; ! entry 0e05b ; IBM restart entry point ! cold: mov ax,40 ; Entered by POWER_ON/RESET mov ds,ax ! movw [0072],00 ; Show data areas not init warm: cli ! mov ax,27f ; installed memory = 640k ! mov [0013],ax ! movw [0015],00 ; POST status word ! mov ax,30 ; Set up IBM-compatible stack ! mov ss,ax ; ...segment 0030h ! mov sp,100 ; ...offset 0100h push ds xor ax,ax ; 8 nonsense vectors begin table --- 1,44 ---- ! /* ! Pcm: a PC eMulator ! Copyright (C) 1992 Electronetics, Inc. All rights reserved. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. ! This program is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! GNU General Public License for more details. ! You should have received a copy of the GNU General Public License ! along with this program; if not, write to the Free Software ! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! */ + .org 0xe000 + + banner: + .asciz "Pcm v0.5a Copyright (c) Electronetics, Inc. 1991, 1992\r\n" + + ;----------; ! .entry 0xe05b ; IBM restart entry point ! cold: mov ax,0x40 ; Entered by POWER_ON/RESET mov ds,ax ! movw [0x72],0 ; Show data areas not init warm: cli ! mov ax,0x27f ; installed memory = 640k ! mov [0x13],ax ! movw [0x15],0 ; POST status word ! mov ax,0x30 ; Set up IBM-compatible stack ! mov ss,ax ; ...segment 0030h ! mov sp,0x100 ; ...offset 0100h push ds xor ax,ax ; 8 nonsense vectors begin table *************** *** 50,63 **** xor di,di ; ...we start at vec 00h cld ! lo_vec: mov ax,offset(ignore); Nonsense interrupt stosw mov ax,cs ; ...bios ROM segment stosw loop lo_vec ! mov si,offset(vectors) ; SI --> Vector address table ! mov cx,18 ; ... vectors 08h - 1Fh busy hi_vec: movsw ; get INTERRUPT bios ROM offset mov ax,cs --- 49,62 ---- xor di,di ; ...we start at vec 00h cld ! lo_vec: mov ax,ignore ; Nonsense interrupt stosw mov ax,cs ; ...bios ROM segment stosw loop lo_vec ! mov si,vectors ; SI --> Vector address table ! mov cx,0x18 ; ... vectors 08h - 1Fh busy hi_vec: movsw ; get INTERRUPT bios ROM offset mov ax,cs *************** *** 65,104 **** loop hi_vec pop ds ! movw [0010],0030 ; no printers, serial ports, 1 disk drive ; 80x25 bw initial video mode ; ; keyboard init ; ! mov ax,01e ; keyboard buffer init ! mov [001a],ax ; buffer head pointer ! mov [001c],ax ; buffer tail pointer ! mov [0080],ax ; buffer start ! add ax,020 ; buffer size (16 char) ! mov [0082],ax ; buffer end ; ; video init ; ! movb [0049],07 ; mode is monochrome ! movw [004a],0050 ; 80 columns ! movw [004c],01000 ; 4k page size ! movw [004e],00000 ; offset within the video segment of page start xor ax,ax mov cx,8 push ds pop es ! mov di,050 ; es:di -> 40:50 (cursor coordinates) rep stosw ! mov ax,600 xor cx,cx ! mov dh,19 ! mov dl,50 ! int 10 ; clear screen mov ah,2 xor bh,bh xor dx,dx ! int 10 ; home cursor ; ; print bios banner --- 64,103 ---- loop hi_vec pop ds ! movw [0x10],0x30 ; no printers, serial ports, 1 disk drive ; 80x25 bw initial video mode ; ; keyboard init ; ! mov ax,0x1e ; keyboard buffer init ! mov [0x1a],ax ; buffer head pointer ! mov [0x1c],ax ; buffer tail pointer ! mov [0x80],ax ; buffer start ! add ax,0x20 ; buffer size (16 char) ! mov [0x82],ax ; buffer end ; ; video init ; ! movb [0x49],7 ; mode is monochrome ! movw [0x4a],0x50 ; 80 columns ! movw [0x4c],0x1000 ; 4k page size ! movw [0x4e],0 ; offset within the video segment of page start xor ax,ax mov cx,8 push ds pop es ! mov di,0x50 ; es:di -> 40:50 (cursor coordinates) rep stosw ! mov ax,0x600 xor cx,cx ! mov dh,0x19 ! mov dl,0x50 ! int 0x10 ; clear screen mov ah,2 xor bh,bh xor dx,dx ! int 0x10 ; home cursor ; ; print bios banner *************** *** 106,112 **** push ds push cs pop ds ! mov si,offset(banner) call print ; xor ax,ax --- 105,111 ---- push ds push cs pop ds ! mov si,banner call print ; xor ax,ax *************** *** 113,122 **** ; int 16 ; hlt ! int 19 ; post done, boot the machine print: ! proc near lodsb ; print null terminated string or al,al ; end of string? jnz print1 --- 112,121 ---- ; int 16 ; hlt ! int 0x19 ; post done, boot the machine print: ! ; proc near lodsb ; print null terminated string or al,al ; end of string? jnz print1 *************** *** 123,181 **** ret print1: call outchr ; output character in ax jmps print ! endp outchr: ! proc near push bx push ax ! mov ah,0e ; tty int 10 function mov bl,7 ! int 10 pop ax pop bx ret ! endp ;----------; ! entry 0e3fe ! int_13 db 0f,00,13,0cA,02,00 ; ! ; int_13 db 0d5,13; ! entry 0e6f2 ; warm boot entry int_19: bootstrap: sti xor ax,ax mov ds,ax ! movw [0078],offset(int_1e) ; save disk parameter table ! mov [007a],cs ! int 13 ; reset floppy jb failed mov es,ax ; segment 0 ! mov bx,7c00 ; offset 7c00 ! mov ax,0201 ; read 1 sector ! mov cx,0001 ; track 0, sector 1 ! int 13 ; read data jb failed xor dx,dx ! jmp 7c00,0000 ; transfer to boot block failed: hlt ! entry 0e739 ! int_14 db 0f,00,14,0cA,02,00 ; ! entry 0e82e ; keyboard bios service ;----------; int_16: ! proc far sti push ds push bx ! mov bx,040 mov ds,bx ; get BIOS work segment or ah,ah jz kbd_rd ; read keyboard buffer, ah = 0 --- 122,179 ---- ret print1: call outchr ; output character in ax jmps print ! ; endp outchr: ! ; proc near push bx push ax ! mov ah,0xe ; tty int 10 function mov bl,7 ! int 0x10 pop ax pop bx ret ! ; endp ;----------; ! .entry 0xe3fe ! int_13: .byte 0xf,0,0x13,0xca,0x02,0 ; ! .entry 0xe6f2 ; warm boot entry int_19: bootstrap: sti xor ax,ax mov ds,ax ! movw [0x78],int_1e ; save disk parameter table ! mov [0x7a],cs ! int 0x13 ; reset floppy jb failed mov es,ax ; segment 0 ! mov bx,0x7c00 ; offset 7c00 ! mov ax,0x201 ; read 1 sector ! mov cx,1 ; track 0, sector 1 ! int 0x13 ; read data jb failed xor dx,dx ! jmpf 0:0x7c00 ; transfer to boot block failed: hlt ! .entry 0xe739 ! int_14: .byte 0xf,0,0x14,0xca,0x2,0 ; ! .entry 0xe82e ; keyboard bios service ;----------; int_16: ! ; proc far sti push ds push bx ! mov bx,0x40 mov ds,bx ; get BIOS work segment or ah,ah jz kbd_rd ; read keyboard buffer, ah = 0 *************** *** 189,196 **** iret kbd_rd: cli ; no interrupts, alters buffer ! mov bx,[001a] ; point to buffer head ! cmp bx,[001c] ; equal buffer tail? jnz kbd_r1 sti jmps kbd_rd ; wait for character to be typed --- 187,194 ---- iret kbd_rd: cli ; no interrupts, alters buffer ! mov bx,[0x1a] ; point to buffer head ! cmp bx,[0x1c] ; equal buffer tail? jnz kbd_r1 sti jmps kbd_rd ; wait for character to be typed *************** *** 198,722 **** mov ax,[bx] ; fetch character into ax inc bx ; point to next character inc bx ; char = scan code + shift ! mov [001a],bx ; save position in head ! cmp bx,[0082] ; buffer overflowed? jnz kbd_exit ! mov bx,[0080] ; reset ! mov [001a],bx ; and correct head position jmps kbd_exit kbd_wt: cli ; no interrupts, critical code ! mov bx,[001a] ; point to buffer head ! cmp bx,[001c] ; equal buffer tail? mov ax,[bx] ; fetch (look ahead) sti ; enable interrupts pop bx pop ds ! ret 002 ; do iret, preserve flags kbd_sh: ! mov al,[0017] ; read keyboard shift status jmps kbd_exit ! endp ;----------; ! entry 0e885 ; hardware keyboard interrupt ! ascii db 000,037,02E,020 ; Scan -> Ascii. Sign bit set ! db 02F,030,031,021 ; ...if further work needed ! db 032,033,034,035 ! db 022,036,038,03E ! db 011,017,005,012 ! db 014,019,015,009 ! db 00F,010,039,03A ! db 03B,084,001,013 ! db 004,006,007,008 ! db 00A,00B,00C,03F ! db 040,041,082,03C ! db 01A,018,003,016 ! db 002,00E,00D,042 ! db 043,044,081,03D ! db 088,02D,0C0,023 ! db 024,025,026,027 ! db 028,029,02A,02B ! db 02C,0A0,090 ! NOALFA db 032,036,02D,0BB ; Non-Alphabetic secondary ! db 0BC,0BD,0BE,0BF ; ...translation table ! db 0C0,0C1,0C2,0C3 ! db 0C4,020,031,033 ! db 034,035,037,038 ! db 039,030,03D,01B ! db 008,05B,05D,00D ! db 05C,02A,009,03B ! db 027,060,02C,02E ! db 02F ! CTRLUP db 040,05E,05F,0D4 ; CTRL uppercase secondary ! db 0D5,0D6,0D7,0D8 ; ...translation table ! db 0D9,0DA,0DB,0DC ; ...for non-ASCII control ! db 0DD,020,021,023 ! db 024,025,026,02A ! db 028,029,02B,01B ! db 008,07B,07D,00D ! db 07C,005,08F,03A ! db 022,07E,03C,03E ! db 03F ! CTRLLO db 003,01E,01F,0DE ; CTRL lowercase secondary ! db 0DF,0E0,0E1,0E2 ; ...translation table ! db 0E3,0E4,0E5,0E6 ; ...for non-ASCII control ! db 0E7,020,005,005 ! db 005,005,005,005 ! db 005,005,005,01B ! db 07F,01B,01D,00A ! db 01C,0F2,005,005 ! db 005,005,005,005 ! db 005 ! ALTKEY db 0F9,0FD,002,0E8 ; ALT key secondary ! db 0E9,0EA,0EB,0EC ; ...translation table ! db 0ED,0EE,0EF,0F0 ! db 0F1,020,0F8,0FA ! db 0FB,0FC,0FE,0FF ! db 000,001,003,005 ! db 005,005,005,005 ! db 005,005,005,005 ! db 005,005,005,005 ! db 005 ! NUMPAD db '789-456+1230.' ; Keypad secondary tralsator ! NUMCTR db 0F7,005,004,005 ; Numeric keypad CTRL sec. ! db 0F3,005,0F4,005 ; ...translation table ! db 0F5,005,0F6,005 ! db 005 ! NUMUPP db 0C7,0C8,0C9,02D ; Numeric keypad SHIFT sec. ! db 0CB,005,0CD,02B ; ...translation table ! db 0CF,0D0,0D1,0D2 ! db 0D3 ! entry 0e987 ! ;int_9 db 0f,00,09,0ca,02,00 ; ! INT_9: STI ; Key press hardware interrupt ! PUSH AX ! PUSH BX ! PUSH CX ! PUSH DX ! PUSH SI ! PUSH DI ! PUSH DS ! PUSH ES ! CLD ! MOV AX,40 ! MOV DS,AX ! IN AL,60 ; Read the scan code data ! PUSH AX ; ...save it ! IN AL,61 ; Get control port status ! PUSH AX ; ...save it ! OR AL,080 ; Set "latch" bit to ! OUT 61,AL ; ...acknowledge data ! POP AX ; Restore control status ! OUT 61,AL ; ...to enable keyboard ! POP AX ; ...restore scan code ! MOV AH,AL ; Save copy of scan code ! CMP AL,0ff ; ...check for overrun ! JNZ KY_01 ; ...no, OK ! JMP KY_BEP ; Else beep bell on overrun ! KY_EOI: MOV AL,20 ; Send end_of_interrupt code ! OUT 20,AL ; ...to 8259 interrupt chip ! KY_XIT: POP ES ; Exit the interrupt ! POP DS ! POP DI ! POP SI ! POP DX ! POP CX ! POP BX ! POP AX ! IRET ! KY_01: AND AL,07f ; Valid scan code, no break ! CMP AL,46 ! JBE KY_02 ! JMP KY_CT8 ! KY_02: MOV BX,offset(ASCII) ; Table for ESC thru Scroll Lck seg cs ! XLAT ; ...translate to Ascii ! OR AL,AL ; Sign flags "Shift" type key ! JS KY_FLG ; ...shift,caps,num,scroll etc ! OR AH,AH ; Invalid scan code? ! JS KY_EOI ; ...exit if so ! jmps ky_asc ; Else normal character ! KY_FLG: AND AL,07f ; Remove sign flag bit ! OR AH,AH ; ...check scan code ! JS KY_SUP ; ...negative, key released ! CMP AL,10 ; Is it a "toggle" type key? ! jae ky_tog ; ...yes ! OR [0017],AL ; Else set bit in "flag" byte ! jmps KY_EOI ; ...and exit ! KY_TOG: TESTB [0017],004 ; Control key pressed? ! JNZ KY_ASC ; ...yes, skip ! TEST AL,[0018] ; Else check "CAPS, NUM, SCRL" ! JNZ KY_EOI ; ...set, invalid, exit ! OR [0018],AL ; Show set in "flag_1" byte ! XOR [0017],AL ; ...flip bits in "flag" byte ! jmps KY_EOI ! KY_SUP: CMP AL,10 ; Released - is it "toggle" key ! JAE KY_TUP ; ...skip if so ! NOT AL ; Else form two's complement ! AND [0017],AL ; ...to do BIT_CLEAR "flags" ! CMP AL,0f7 ; ALT key release special case ! JNZ KY_EOI ; ...no, exit ! MOV AL,[0019] ; Else get ALT-keypad character ! MOV AH,00 ; ...pretend null scan code ! MOV [0019],AH ; ...zero ALT-keypad character ! CMP AL,AH ; Was there a valid ALT-keypad? ! JZ KY_EOI ; ...no, ignore, exit ! JMP KY_NUL ; Else stuff it in ASCII buffer ! KY_TUP: NOT AL ; Form complement of toggle key ! AND [0018],AL ; ...to do BIT_CLEAR "flag_1" jmps ky_eoi ! KY_ASC: TESTB [0018],08 ; Scroll lock pressed? ! JZ KY_NLK ; ...no ! CMP AH,45 ; Is this a NUM LOCK character? ! JZ KY_03 ; ...no ! ANDB [0018],0f7 ; Else clear bits in "flag_1" ! KY_03: JMP KY_EOI ; ...and exit ! KY_NLK: TESTB [0017],008 ; ALT key pressed? ! JNZ KY_ALT ; ...yes ! TESTB [0017],004 ; CTRL key pressed? ! JNZ KY_CTL ; ...yes ! TESTB [0017],003 ; Either shift key pressed? ! JNZ KSHIFT ; ...yes ! KY_LC: CMP AL,1A ; Alphabetic character? ! JA KY_LC1 ; ...no ! ADD AL,060 ; Else add lower case base ! JMP KY_COM ! KY_LC1: MOV BX,offset(NOALFA) ; Non-alphabetic character ! SUB AL,20 seg cs ! XLAT ; ...do the xlate ! JMP KY_COM ! KY_ALT: CMP AL,1A ; Control key pressed? ! JA KY_AGN ; ...no, skip ! MOV AL,00 ; Else illegal key press ! JMP KY_BFR ! KY_AGN: MOV BX,offset(ALTKEY) ; Load ALT key translation ! SUB AL,20 ; ...bias to printing char. seg cs ! XLAT ; ...do the translation ! JMP KY_COM ! KY_CTL: CMP AH,46 ; Scroll lock key? ! JNZ KY_CT1 ; ...no, skip ! MOVB [0071],080 ; Else CTRL-"Scroll" = break ! MOV AX,[0080] ; ...get key buffer start ! MOV [001C],AX ; ...get key tail to start ! MOV [001A],AX ; ...get key head to start ! INT 1B ; Issue a "Break" interrupt ! SUB AX,AX ! JMP KY_CO2 ! KY_CT1: CMP AH,45 ; Num lock key? ! JNZ KY_CT2 ; ...no, skip ! ORB [0018],008 ; Else show scroll lock ! MOV AL,20 ; ...send end_of_interrupt ! OUT 20,AL ; ...to 8259 int. controller ! CMPB [0049],7 ; Monochrome monitor? ! JZ KY_POL ; ...yes, skip ! MOV DX,3D8 ; Else reset mode ! MOV AL,[0065] ; ...for the ! OUT DX,AL ; ...CGA color card ! KY_POL: TESTB [0018],008 ; Wait for him to type ! JNZ KY_POL ; ...not yet ! JMP KY_XIT ! KY_CT2: CMP AH,3 ; Is it a Control @ (null) ? ! JNZ KY_CT3 ; ...no ! MOV AL,00 ; Else force a null ! KY_CT4: JMP KY_BFR ; ...save in buffer ! KY_CT3: CMP AL,1A ; Is it a control character? ! JBE KY_CT4 ; ...yes ! MOV BX,offset(CTRLLO) ; Else non-ascii control ! SUB AL,20 ; ...lower case seg cs ! XLAT ; ...translation ! JMP KY_COM ! KSHIFT: CMP AH,37 ; Print_Screen pressed? ! JNZ KY_CT5 ! MOV AL,20 ; Yes, send end_of_interrupt ! OUT 20,AL ; ...to 8259 interrupt chip ! INT 5 ; Request print_screen service ! JMP KY_XIT ; ...and exit key service ! KY_CT5: CMP AL,1A ; Alphabetic char? ! JA KY_CT6 ; ...no ! ADD AL,040 ; Yes, add base for alphabet ! JMP KY_COM ! ! KY_CT6: MOV BX,offset(CTRLUP) ; Non-ascii control ! SUB AL,20 ; ...upper case seg cs ! XLAT ; ...translation ! JMP KY_COM ! KY_CT8: SUB AL,47 ; Keypad key, convert origin ! MOV BL,[0017] ; ...get "flag" byte ! TEST BL,008 ; Look for ALT keypad entry ! JNZ KB_NUM ; ...do special entry thing ! TEST BL,004 ; CTRL key pressed? ! JNZ KY_CTR ; ...skip if so ! TEST BL,020 ; Toggle "Num Lock" ? ! JZ KY_CT9 ; ...no, continue ! TEST BL,003 ; Shift keys hit? ! JNZ KY_CTA ; ...no, check "INS" ! jmp KY_CTD ; Else xlat keypad char. ! KY_CT9: TEST BL,003 ; Shift keys hit? ! JZ KY_CTA ; ...no, check "INS" key ! jmp KY_CTD ; Else xlat keypad char. ! KB_NUM: OR AH,AH ; ALT-keypad entry, scan code ! JS KY_EO1 ; ...out of range ! TESTB [0017],004 ; Else check CTRL state ! JZ KY_PAD ; ...not pressed, ALT keypad ! KY_PAT: CMP AH,53 ; Patch for CTRL ALT - toggle ! JNZ KY_PA1 ; ...not a DEL (reset) ! MOVW [0072],01234 ; Ctrl-Alt-Del, set init flag ! JMP WARM ; ...do a warm reboot ! KY_PA1: CMP AH,4A ; Is it a keypad "-" ? ! JNZ KY_PAD ; ...no, skip ! PUSH AX ! PUSH BX ! PUSH CX ! IN AL,61 ; Read equipment flags ! XOR AL,00c ; ...toggle speed ! OUT 61,AL ; Write new flags back ! ! MOV AH,1 ; Video func=Set cursor type ! MOV CX,607 ; ...start at 6, end at 7 ! AND AL,4 ; Is turbo mode set? ! JZ KY_CUR ; ...no, keep big cursor ! MOV CH,00 ; Else set tiny cursor ! ! KY_CUR: INT 10 ; Set cursor type service ! MOV BX,[0080] ; ...get start of key buf ! MOV [001A],BX ; ...set head to start ! MOV [001C],BX ; ...set tail to start ! POP CX ! POP BX ! POP AX ! ! KY_PAD: MOV BX,offset(NUMPAD) ; Get keypad translation table seg cs ! XLAT ; ...convert to number ! CMP AL,'0' ; Is it a valid ASCII digit? ! JB KY_EO1 ; ...no, ignore it ! SUB AL,30 ; Else convert to number ! MOV BL,AL ; ...save a copy ! MOV AL,[0019] ; Get partial ALT-keypad sum ! MOV AH,0A ; ...times 10 (decimal) ! MUL AL,AH ! ADD AL,BL ; Add in new digit to sum ! MOV [0019],AL ; ...save as new ALT entry ! KY_EO1: JMP KY_EOI ; End_of_interrupt, exit ! KY_CTR: OR AH,AH ; Key released? ! JS KY_EO1 ; ...ignore if so ! MOV BX,offset(NUMCTR) ; Else Numeric Keypad Control seg cs ! XLAT ; ...secondary translate ! jmps ky_com ; ...and save it ! KY_CTA: CMP AH,0D2 ; Was "INS" key released? ! JNZ KY_CTB ! ANDB [0018],07f ; Yes, clear "INS" in "FLAG_1" ! jmps KY_EO1 ! KY_CTB: OR AH,AH ; Key released? ! JS KY_EO1 ; ...ignore if so ! CMP AH,52 ; Else check for "INS" press ! JNZ KY_CTC ; ...not "INS" press ! TESTB [0018],080 ; Was INS key in effect? ! JNZ KY_EO1 ; ...yes, ignore ! XORB [0017],080 ; Else tog "INS" in "FLAG" byte ! ORB [0018],080 ; ...set "INS" in "FLAG_1" byte ! KY_CTC: MOV BX,offset(NUMUPP) ; Numeric Keypad Upper Case seg cs ! XLAT ; ...secondary translation ! jmps KY_COM ! KY_CTD: OR AH,AH ; Was the key released? ! JS KY_EO1 ; ...yes, ignore ! MOV BX,offset(NUMPAD) ; Load translation table seg cs ! XLAT ; ...do translate ! jmps KY_COM ! KY_COM: CMP AL,5 ; Common entry, char in AL ! JZ KY_EO2 ; ...Control E, ignore ! CMP AL,4 ! JA KY_CO1 ; Above Control D ! OR AL,080 ; Else set sign flag ! jmps KY_CO2 ! KY_CO1: TEST AL,080 ; Is sign bit set? ! JZ KY_CO3 ; ...skip if so ! AND AL,07f ; Else mask sign off ! KY_CO2: MOV AH,AL ; Save in high order byte ! MOV AL,00 ; ...set scan code to zero ! KY_CO3: TESTB [0017],040 ; Test for "CAPS LOCK" state ! JZ KY_BFR ; ...no, skip ! TESTB [0017],003 ; Test for SHIFT key ! JZ KY_CO4 ; ...skip if no shift ! CMP AL,'A' ; Check for alphabetic key ! JB KY_BFR ; ...not SHIFT_able ! CMP AL,'Z' ; Check for alphabetic key ! JA KY_BFR ; ...not SHIFT_able ! ADD AL,20 ; Else do the shift ! jmps KY_BFR ! KY_CO4: CMP AL,'a' ; Check for alphabetic key ! JB KY_BFR ; ...not SHIFT_able ! CMP AL,'z' ; Check for Alphabetic key ! JA KY_BFR ; ...not SHIFT_able ! SUB AL,20 ; Else do the shift ! KY_BFR: MOV BX,[001C] ; BX = tail of buffer ! MOV DI,BX ; ...save it ! INC BX ; ...advance ! INC BX ; ...by word ! CMP BX,[0082] ; End of buffer reached? ! JNZ KY_CHK ; ...no, skip ! MOV BX,[0080] ; Else BX = beginning of buffer ! KY_CHK: CMP BX,[001A] ; BX = Buffer Head ? ! JNZ KY_STF ; ...no, OK ! jmps KY_BEP ; Else buffer overrun, beep ! KY_STF: MOV [DI],AX ; Stuff scan code, char in bfr ! MOV [001C],BX ; ...and update bfr tail ! KY_EO2: JMP KY_EOI ! KY_BEP: MOV AL,20 ; Keyboard beeper routine ! OUT 20,AL ; ...send end_of_interrupt ! MOV BX,80 ; Cycles in beep ! IN AL,61 ; ...get status ! PUSH AX ; ...save copy ! KY_BE1: AND AL,0fc ; Mask off speaker bits ! OUT 61,AL ; ...disable speaker ! KY_BE2: MOV CX,64 ; Constant for pitch ! KY_BE3: LOOP KY_BE3 ; ...delay, speaker off ! XOR AL,002 ! OUT 61,AL ; Toggle speaker position ! TEST AL,002 ; Full cycle done yet? ! JZ KY_BE2 ; ...no, do other half cycle ! DEC BX ; Else show cycle sent ! JNZ KY_BE1 ; ...more cycles to send ! POP AX ! OUT 61,AL ; Restore flags ! MOV CX,32 ; Silence counter ! KY_BE4: LOOP KY_BE4 ; Send nothing for while ! JMP KY_XIT ! KY_NUL: MOV AH,38 ; ALT key pressed, released ! JMPs KY_BFR ; ...for no logical reason ! int_e db 00,00,0f4 ; ! entry 0efc7 ! int_1e db 00,00,00,00,00,00 ; disk parm table ! db 00,00,00,00,00 ! entry 0efd2 ! int_17 db 0f,00,17,0cA,02,00 ; ! entry 0f065 ! int_10 db 0f,00,10,0cA,02,00 ; ! entry 0f841 ! int_12 db 0f,00,12,0cA,02,00 ; ! entry 0f84d ! int_11 db 0f,00,11,0cA,02,00 ; ! entry 0f859 ! int_15 db 0f,00,15,0cA,02,00 ; ! entry 0fe6e ! int_1a db 0f,00,1A,0cA,02,00 ; ! entry 0fea5 ; hardware clock interrupt ! int_8 db 0f,00,08,0cf,00,00,00 ;----------; ! entry 0fef3 ; initial interrupt vector offsets loaded by POST vectors: ! dw offset(int_8) ; timer tick ! dw offset(int_9) ; keyboard attention ! dw offset(ignore) ; reserved ! dw offset(ignore) ; reserved com2 ! dw offset(ignore) ; reserved com1 ! dw offset(ignore) ; reserved hard disk attn. ! dw offset(int_e) ; floppy disk attn. ! dw offset(ignore) ; reserved parallel printer ! dw offset(int_10) ; video bios ! dw offset(int_11) ! dw offset(int_12) ! dw offset(int_13) ! dw offset(int_14) ! dw offset(int_15) ! dw offset(int_16) ! dw offset(int_17) ! dw offset(ignore) ! dw offset(int_19) ! dw offset(int_1a) ! dw offset(ignore) ! dw offset(ignore) ! dw offset(ignore) ! dw offset(int_1e) ;----------; ! entry 0ff23 ignore: hlt ; unexpected interrupts go here ;----------; ! entry 0fff0 ; hardware power reset entry power: jmp cold ; ...begins here on power up ;----------; ! entry 0fff5 ; Release date ! db '01/31/91' ; ...MM/DD/YY (not logical) ! entry 0fffe ! db 0fe ; Computer type (XT) ! db 0ff ; Checksum byte --- 196,705 ---- mov ax,[bx] ; fetch character into ax inc bx ; point to next character inc bx ; char = scan code + shift ! mov [0x1a],bx ; save position in head ! cmp bx,[0x82] ; buffer overflowed? jnz kbd_exit ! mov bx,[0x80] ; reset ! mov [0x1a],bx ; and correct head position jmps kbd_exit kbd_wt: cli ; no interrupts, critical code ! mov bx,[0x1a] ; point to buffer head ! cmp bx,[0x1c] ; equal buffer tail? mov ax,[bx] ; fetch (look ahead) sti ; enable interrupts pop bx pop ds ! retf 002 ; do iret, preserve flags kbd_sh: ! mov al,[0x17] ; read keyboard shift status jmps kbd_exit ! ; endp ;----------; ! .entry 0xe885 ; hardware keyboard interrupt ! ascii: ! .byte 0x00,0x37,0x2E,0x20, ; Scan -> Ascii. Sign bit set ! 0x2f,0x30,0x31,0x21, ; ...if further work needed ! 0x32,0x33,0x34,0x35, ! 0x22,0x36,0x38,0x3e, ! 0x11,0x17,0x05,0x12, ! 0x14,0x19,0x15,0x09, ! 0x0f,0x10,0x39,0x3a, ! 0x3b,0x84,0x01,0x13, ! 0x04,0x06,0x07,0x08, ! 0x0a,0x0b,0x0c,0x3f, ! 0x40,0x41,0x82,0x3c, ! 0x1a,0x18,0x03,0x16, ! 0x02,0x0e,0x0d,0x42, ! 0x43,0x44,0x81,0x3d, ! 0x88,0x2d,0xc0,0x23, ! 0x24,0x25,0x26,0x27, ! 0x28,0x29,0x2a,0x2b, ! 0x2c,0xa0,0x90 ! noalfa: ! .byte 0x32,0x36,0x2d,0xbb, ; Non-Alphabetic secondary ! 0xbc,0xbd,0xbe,0xbf, ; ...translation table ! 0xc0,0xc1,0xc2,0xc3, ! 0xc4,0x20,0x31,0x33, ! 0x34,0x35,0x37,0x38, ! 0x39,0x30,0x3d,0x1b, ! 0x08,0x5b,0x5d,0x0d, ! 0x5c,0x2a,0x09,0x3b, ! 0x27,0x60,0x2c,0x2e, ! 0x2f ! ctrlup: ! .byte 0x40,0x5e,0x5f,0xd4, ; CTRL uppercase secondary ! 0xd5,0xd6,0xd7,0xd8, ; ...translation table ! 0xd9,0xda,0xdb,0xdc, ; ...for non-ASCII control ! 0xdd,0x20,0x21,0x23, ! 0x24,0x25,0x26,0x2a, ! 0x28,0x29,0x2b,0x1b, ! 0x08,0x7b,0x7d,0x0d, ! 0x7c,0x05,0x8f,0x3a, ! 0x22,0x7e,0x3c,0x3e, ! 0x3f ! ctrllo: ! .byte 0x03,0x1e,0x1f,0xde, ; CTRL lowercase secondary ! 0xdf,0xe0,0xe1,0xe2, ; ...translation table ! 0xe3,0xe4,0xe5,0xe6, ; ...for non-ASCII control ! 0xe7,0x20,0x05,0x05, ! 0x05,0x05,0x05,0x05, ! 0x05,0x05,0x05,0x1b, ! 0x7f,0x1b,0x1d,0x0a, ! 0x1c,0xf2,0x05,0x05, ! 0x05,0x05,0x05,0x05, ! 0x05 ! altkey: ! .byte 0xf9,0xfd,0x02,0xe8, ; ALT key secondary ! 0xe9,0xea,0xeb,0xec, ; ...translation table ! 0xed,0xee,0xef,0xf0, ! 0xf1,0x20,0xf8,0xfa, ! 0xfb,0xfc,0xfe,0xff, ! 0x00,0x01,0x03,0x05, ! 0x05,0x05,0x05,0x05, ! 0x05,0x05,0x05,0x05, ! 0x05,0x05,0x05,0x05, ! 0x05 ! numpad: ! .ascii "789-456+1230." ; Keypad secondary tralsator ! numctr: ! .byte 0xf7,0x05,0x04,0x05, ; Numeric keypad CTRL sec. ! 0xf3,0x05,0xf4,0x05, ; ...translation table ! 0xf5,0x05,0xf6,0x05, ! 0x05 ! numupp: ! .byte 0xc7,0xc8,0xc9,0x2d, ; Numeric keypad SHIFT sec. ! 0xcb,0x05,0xcd,0x2b, ; ...translation table ! 0xcf,0xd0,0xd1,0xd2, ! 0xd3 ! .entry 0xe987 ! int_9: sti ; Key press hardware interrupt ! push ax ! push bx ! push cx ! push dx ! push si ! push di ! push ds ! push es ! cld ! mov ax,0x40 ! mov ds,ax ! in al,0x60 ; Read the scan code data ! push ax ; ...save it ! in al,0x61 ; Get control port status ! push ax ; ...save it ! or al,0x80 ; Set "latch" bit to ! out 0x61,al ; ...acknowledge data ! pop ax ; Restore control status ! out 0x61,al ; ...to enable keyboard ! pop ax ; ...restore scan code ! mov ah,al ; Save copy of scan code ! cmp al,0xff ; ...check for overrun ! jnz ky_01 ; ...no, OK ! jmp ky_bep ; Else beep bell on overrun ! ky_eoi: mov al,0x20 ; Send end_of_interrupt code ! out 0x20,al ; ...to 8259 interrupt chip ! ky_xit: pop es ; exit the interrupt ! pop ds ! pop di ! pop si ! pop dx ! pop cx ! pop bx ! pop ax ! iret ! ky_01: and al,0x7f ; Valid scan code, no break ! cmp al,0x46 ! jbe ky_02 ! jmp ky_ct8 ! ky_02: mov bx,ascii ; Table for ESC thru Scroll Lck seg cs ! xlat ; ...translate to Ascii ! or al,al ; Sign flags "Shift" type key ! js ky_flg ; ...shift,caps,num,scroll etc ! or ah,ah ; Invalid scan code? ! js ky_eoi ; ...exit if so ! jmps ky_asc ; Else normal character ! ky_flg: and al,0x7f ; Remove sign flag bit ! or ah,ah ; ...check scan code ! js ky_sup ; ...negative, key released ! cmp al,0x10 ; Is it a "toggle" type key? ! jae ky_tog ; ...yes ! or [0x17],al ; Else set bit in "flag" byte ! jmps ky_eoi ; ...and exit ! ky_tog: testb [0x17],4 ; Control key pressed? ! jnz ky_asc ; ...yes, skip ! test al,[0x18] ; Else check "CAPS, NUM, SCRL" ! jnz ky_eoi ; ...set, invalid, exit ! or [0x18],al ; Show set in "flag_1" byte ! xor [0x17],al ; ...flip bits in "flag" byte ! jmps ky_eoi ! ky_sup: cmp al,0x10 ; Released - is it "toggle" key ! jae ky_tup ; ...skip if so ! not al ; Else form two's complement ! and [0x17],al ; ...to do BIT_CLEAR "flags" ! cmp al,0xf7 ; ALT key release special case ! jnz ky_eoi ; ...no, exit ! mov al,[0x19] ; Else get ALT-keypad character ! mov ah,0 ; ...pretend null scan code ! mov [0x19],ah ; ...zero ALT-keypad character ! cmp al,ah ; Was there a valid ALT-keypad? ! jz ky_eoi ; ...no, ignore, exit ! jmp ky_nul ; Else stuff it in ASCII buffer ! ky_tup: not al ; Form complement of toggle key ! and [0x18],al ; ...to do BIT_CLEAR "flag_1" jmps ky_eoi ! ky_asc: testb [0x18],8 ; Scroll lock pressed? ! jz ky_nlk ; ...no ! cmp ah,0x45 ; Is this a NUM LOCK character? ! jz ky_03 ; ...no ! andb [0x18],0xf7 ; Else clear bits in "flag_1" ! ky_03: jmp ky_eoi ; ...and exit ! ky_nlk: testb [0x17],8 ; ALT key pressed? ! jnz ky_alt ; ...yes ! testb [0x17],4 ; CTRL key pressed? ! jnz ky_ctl ; ...yes ! testb [0x17],3 ; Either shift key pressed? ! jnz kshift ; ...yes ! ky_lc: cmp al,0x1a ; Alphabetic character? ! ja ky_lc1 ; ...no ! add al,0x60 ; Else add lower case base ! jmp ky_com ! ky_lc1: mov bx,noalfa ; Non-alphabetic character ! sub al,0x20 seg cs ! xlat ; ...do the xlate ! jmp ky_com ! ky_alt: cmp al,0x1a ; Control key pressed? ! ja ky_agn ; ...no, skip ! mov al,0 ; Else illegal key press ! jmp ky_bfr ! ky_agn: mov bx,altkey ; Load ALT key translation ! sub al,0x20 ; ...bias to printing char. seg cs ! xlat ; ...do the translation ! jmp ky_com ! ky_ctl: cmp ah,0x46 ; Scroll lock key? ! jnz ky_ct1 ; ...no, skip ! movb [0x71],0x80 ; Else CTRL-"Scroll" = break ! mov ax,[0x80] ; ...get key buffer start ! mov [0x1c],ax ; ...get key tail to start ! mov [0x1a],ax ; ...get key head to start ! int 0x1b ; Issue a "Break" interrupt ! sub ax,ax ! jmp ky_co2 ! ky_ct1: cmp ah,0x45 ; Num lock key? ! jnz ky_ct2 ; ...no, skip ! orb [0x18],8 ; Else show scroll lock ! mov al,0x20 ; ...send end_of_interrupt ! out 0x20,al ; ...to 8259 int. controller ! cmpb [0x49],7 ; Monochrome monitor? ! jz ky_pol ; ...yes, skip ! mov dx,0x3d8 ; Else reset mode ! mov al,[0x65] ; ...for the ! out dx,al ; ...CGA color card ! ky_pol: testb [0x18],8 ; Wait for him to type ! jnz ky_pol ; ...not yet ! jmp ky_xit ! ky_ct2: cmp ah,3 ; Is it a Control @ (null) ? ! jnz ky_ct3 ; ...no ! mov al,0 ; Else force a null ! ky_ct4: jmp ky_bfr ; ...save in buffer ! kshift: cmp ah,0x37 ; Print_Screen pressed? ! jnz ky_ct5 ! mov al,0x20 ; Yes, send end_of_interrupt ! out 0x20,al ; ...to 8259 interrupt chip ! int 5 ; Request print_screen service ! jmp ky_xit ; ...and exit key service ! ! ky_ct3: cmp al,0x1a ; Is it a control character? ! jbe ky_ct4 ; ...yes ! mov bx,ctrllo ; Else non-ascii control ! sub al,0x20 ; ...lower case seg cs ! xlat ; ...translation ! jmp ky_com ! ky_ct5: cmp al,0x1a ; Alphabetic char? ! ja ky_ct6 ; ...no ! add al,0x40 ; Yes, add base for alphabet ! jmp ky_com ! ky_ct6: mov bx,ctrlup ; Non-ascii control ! sub al,0x20 ; ...upper case seg cs ! xlat ; ...translation ! jmp ky_com ! ky_ct8: sub al,0x47 ; Keypad key, convert origin ! mov bl,[0x17] ; ...get "flag" byte ! test bl,8 ; Look for ALT keypad entry ! jnz kb_num ; ...do special entry thing ! test bl,4 ; CTRL key pressed? ! jnz ky_ctr ; ...skip if so ! test bl,0x20 ; Toggle "Num Lock" ? ! jz ky_ct9 ; ...no, continue ! test bl,3 ; Shift keys hit? ! jnz ky_cta ; ...no, check "INS" ! jmp ky_ctd ; Else xlat keypad char. ! ky_ct9: test bl,3 ; Shift keys hit? ! jz ky_cta ; ...no, check "INS" key ! jmp ky_ctd ; Else xlat keypad char. ! kb_num: or ah,ah ; ALT-keypad entry, scan code ! js ky_eo1 ; ...out of range ! testb [0x17],4 ; Else check CTRL state ! jz ky_pad ; ...not pressed, ALT keypad ! ky_pat: cmp ah,0x53 ; Patch for CTRL ALT - toggle ! jnz ky_pad ; ...not a DEL (reset) ! movw [0x72],0x1234 ; Ctrl-Alt-Del, set init flag ! jmp warm ; ...do a warm reboot ! ky_pad: mov bx,numpad ; Get keypad translation table seg cs ! xlat ; ...convert to number ! cmp al,'0' ; Is it a valid ASCII digit? ! jb ky_eo1 ; ...no, ignore it ! sub al,0x30 ; Else convert to number ! mov bl,al ; ...save a copy ! mov al,[0x19] ; Get partial ALT-keypad sum ! mov ah,0xa ; ...times 10 (decimal) ! mul ah ! add al,bl ; Add in new digit to sum ! mov [0x19],al ; ...save as new ALT entry ! ky_eo1: jmp ky_eoi ; End_of_interrupt, exit ! ky_ctr: or ah,ah ; Key released? ! js ky_eo1 ; ...ignore if so ! mov bx,numctr ; Else Numeric Keypad Control seg cs ! xlat ; ...secondary translate ! jmps ky_com ; ...and save it ! ky_cta: cmp ah,0xd2 ; Was "INS" key released? ! jnz ky_ctb ! andb [0x18],0x7f ; Yes, clear "INS" in "FLAG_1" ! jmps ky_eo1 ! ky_ctb: or ah,ah ; Key released? ! js ky_eo1 ; ...ignore if so ! cmp ah,0x52 ; Else check for "INS" press ! jnz ky_ctc ; ...not "INS" press ! testb [0x18],0x80 ; Was INS key in effect? ! jnz ky_eo1 ; ...yes, ignore ! xorb [0x17],0x80 ; Else tog "INS" in "FLAG" byte ! orb [0x18],0x80 ; ...set "INS" in "FLAG_1" byte ! ky_ctc: mov bx,numupp ; Numeric Keypad Upper Case seg cs ! xlat ; ...secondary translation ! jmps ky_com ! ky_ctd: or ah,ah ; Was the key released? ! js ky_eo1 ; ...yes, ignore ! mov bx,numpad ; Load translation table seg cs ! xlat ; ...do translate ! jmps ky_com ! ky_com: cmp al,5 ; Common entry, char in AL ! jz ky_eo2 ; ...Control E, ignore ! cmp al,4 ! ja ky_co1 ; Above Control D ! or al,0x80 ; Else set sign flag ! jmps ky_co2 ! ky_co1: test al,0x80 ; Is sign bit set? ! jz ky_co3 ; ...skip if so ! and al,0x7f ; Else mask sign off ! ky_co2: mov ah,al ; Save in high order byte ! mov al,0 ; ...set scan code to zero ! ky_co3: testb [0x17],0x40 ; Test for "CAPS LOCK" state ! jz ky_bfr ; ...no, skip ! testb [0x17],3 ; Test for SHIFT key ! jz ky_co4 ; ...skip if no shift ! cmp al,'A' ; Check for alphabetic key ! jb ky_bfr ; ...not SHIFT_able ! cmp al,'Z' ; Check for alphabetic key ! ja ky_bfr ; ...not SHIFT_able ! add al,0x20 ; Else do the shift ! jmps ky_bfr ! ky_co4: cmp al,'a' ; Check for alphabetic key ! jb ky_bfr ; ...not SHIFT_able ! cmp al,'z' ; Check for Alphabetic key ! ja ky_bfr ; ...not SHIFT_able ! sub al,0x20 ; Else do the shift ! ky_bfr: mov bx,[0x1c] ; BX = tail of buffer ! mov di,bx ; ...save it ! inc bx ; ...advance ! inc bx ; ...by word ! cmp bx,[0x82] ; End of buffer reached? ! jnz ky_chk ; ...no, skip ! mov bx,[0x80] ; Else BX = beginning of buffer ! ky_chk: cmp bx,[0x1a] ; BX = Buffer Head ? ! jnz ky_stf ; ...no, OK ! jmps ky_bep ; Else buffer overrun, beep ! ky_stf: mov [di],ax ; Stuff scan code, char in bfr ! mov [0x1c],bx ; ...and update bfr tail ! ky_eo2: jmp ky_eoi ! ky_bep: mov al,0x20 ; Keyboard beeper routine ! out 0x20,al ; ...send end_of_interrupt ! mov bx,0x80 ; Cycles in beep ! in al,0x61 ; ...get status ! push ax ; ...save copy ! ky_be1: and al,0xfc ; Mask off speaker bits ! out 0x61,al ; ...disable speaker ! ky_be2: mov cx,0x64 ; Constant for pitch ! ky_be3: loop ky_be3 ; ...delay, speaker off ! xor al,2 ! out 0x61,al ; Toggle speaker position ! test al,2 ; Full cycle done yet? ! jz ky_be2 ; ...no, do other half cycle ! dec bx ; Else show cycle sent ! jnz ky_be1 ; ...more cycles to send ! pop ax ! out 0x61,al ; Restore flags ! mov cx,0x32 ; Silence counter ! ky_be4: loop ky_be4 ; Send nothing for while ! jmp ky_xit ! ky_nul: mov ah,0x38 ; ALT key pressed, released ! jmps ky_bfr ; ...for no logical reason ! int_e: .byte 0,0,0xf4 ; ! .entry 0xefc7 ! int_1e: .byte 0,0,0,0,0,0, ; disk parm table ! 0,0,0,0,0 ! .entry 0xefd2 ! int_17: .byte 0xf,0,0x17,0xca,2,0 ; ! .entry 0xf065 ! int_10: .byte 0xf,0,0x10,0xca,2,0 ; ! .entry 0xf841 ! int_12: .byte 0xf,0,0x12,0xca,2,0 ; ! .entry 0xf84d ! int_11: .byte 0xf,0,0x11,0xca,2,0 ; ! .entry 0xf859 ! int_15: .byte 0xf,0,0x15,0xca,2,0 ; ! .entry 0xfe6e ! int_1a: .byte 0xf,0,0x1a,0xca,2,0 ; ! .entry 0xfea5 ; hardware clock interrupt ! int_8: .byte 0xf,0,8,0xcf,0,0,0 ;----------; ! ; initial interrupt vector offsets loaded by POST ! .entry 0xfef3 vectors: ! .word int_8, ; timer tick ! int_9, ; keyboard attention ! ignore, ; reserved ! ignore, ; reserved com2 ! ignore, ; reserved com1 ! ignore, ; reserved hard disk attn. ! int_e, ; floppy disk attn. ! ignore, ; reserved parallel printer ! int_10, ; video bios ! int_11, ! int_12, ! int_13, ! int_14, ! int_15, ! int_16, ! int_17, ! ignore, ! int_19, ! int_1a, ! ignore, ! ignore, ! ignore, ! int_1e ;----------; ! .entry 0xff23 ignore: hlt ; unexpected interrupts go here ;----------; ! .entry 0xfff0 ; hardware power reset entry power: jmp cold ; ...begins here on power up ;----------; ! .entry 0xfff5 ; Release date ! .ascii "01/31/91" ; ...MM/DD/YY ! .entry 0xfffe ! .byte 0xfe, ; Computer type (XT) ! 0xff ; Checksum byte Only in src: pcmbios.bin Only in src: pcmexit.c diff -c src/port.c src.new/port.c *** src/port.c Mon Apr 27 14:49:02 1992 --- src.new/port.c Wed May 6 10:33:31 1992 *************** *** 95,101 **** break; case 0x61: /* keyboard status */ break; ! default: pcmexit("reading unknown port 0x%x\n",port); break; } } --- 95,103 ---- break; case 0x61: /* keyboard status */ break; ! default: ! printf("warning: reading unknown port 0x%x\n",port); ! AL = 0xff; break; } } Only in src.new: rasm.c Only in src.new: rasm.h diff -c src/sim.h src.new/sim.h *** src/sim.h Fri May 1 23:34:28 1992 --- src.new/sim.h Wed May 6 14:18:11 1992 *************** *** 23,29 **** #define BIG_ENDIAN 1 #endif ! /*#define READ_TIME 1*/ extern unsigned char pc_mem[1024*1024]; /* pc memory */ --- 23,29 ---- #define BIG_ENDIAN 1 #endif ! /* #define READ_TIME 1 */ extern unsigned char pc_mem[1024*1024]; /* pc memory */ Only in src: tmp Only in src: vfprintf.c Only in src: vprintf.c diff -c src/window.c src.new/window.c *** src/window.c Tue Apr 28 09:57:16 1992 --- src.new/window.c Wed May 6 14:29:33 1992 *************** *** 162,168 **** char *boldfontfilename = "pcmbold"; char pfname[256]; ! static char header_msg[] = "PCM v0.5"; extern unsigned char *vidbase, *start_line; short pc_cursor_image[] = { --- 162,168 ---- char *boldfontfilename = "pcmbold"; char pfname[256]; ! static char header_msg[] = "PCM v0.5a"; extern unsigned char *vidbase, *start_line; short pc_cursor_image[] = {