├── .cvsignore
├── .project
├── BUGS
├── CHANGES
├── COPYRIGHT
├── Makefile
├── README
├── README.dg
├── README.mlh
├── TODO
├── VERSION
├── autodetect.c
├── autodetect.h
├── bios.c
├── bios.h
├── config.c
├── cpu.c
├── cpu.h
├── curses.c
├── debugger.c
├── debugger.h
├── disasm.h
├── dot.pcemurc
├── ems.c
├── ems
├── Makefile.patch
├── bios.c.patch
├── bios.h.patch
├── ems.doc
└── patch.script
├── fonts.dir
├── global.h
├── hardware.c
├── hardware.h
├── icon.h
├── instr.h
├── keytabs.h
├── log.dec
├── log.sun
├── main.c
├── mfs.c
├── mfs.h
├── mfs_link.h
├── mytypes.h
├── new.pcemurc
├── old.pcemurc
├── programs
├── Makefile
├── config.sys
├── dumpdisk.c
├── ekemm.asm
├── ekemm.sys
├── emufs.S
├── emufs.sys
├── lredir.c
├── lredir.readme
└── vga50.com
├── report.ps
├── vga.bdf
├── vga.c
├── vga.h
├── vga.pcf
├── vgahard.c
├── vgahard.h
├── video.c
├── video.h
├── xstuff.c
└── xstuff.h
/.cvsignore:
--------------------------------------------------------------------------------
1 | autodetect
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | pcemu
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/BUGS:
--------------------------------------------------------------------------------
1 |
2 |
3 | This is a current list of bugs/misfeatures (not counting programs
4 | which wouldn't run because of unimplemented functions/features)
5 |
6 |
7 | 1. keyb reverses keystrokes when they are typed quickly.
8 | Not sure if this is my emulator at fault or keyb - investigating it...
9 |
10 | 2. mfs.c has bugs in it. I've fixed a couple of the more obvious
11 | ones, but it occasinally crashes a bit when running xtree. (the
12 | logged drive had to be disconnected and reconnnected again to cure
13 | the problem)
14 |
15 | 3. MSDOS 5 dosshell program refuses to switch tasks - claiming there
16 | is insufficient disk space. MSDOS 6 dosshell has no problem with this.
17 | Both MSDOS 5 and MSDOS 6 cause an invalid opcode to be executed when
18 | run on a monochrome screen.
19 |
20 |
21 | 4. MSDOS very occasionally hangs with 'stack overflow' if network
22 | load is heavy and lots of keys are pressed at once.
23 |
24 | Increasing the 'stacks=' line in the config.sys file can help this
25 | problem.
26 |
27 |
28 | This list is almost certainly not complete.
29 |
30 |
--------------------------------------------------------------------------------
/CHANGES:
--------------------------------------------------------------------------------
1 | 1.2.1
2 | There was a initilisation bug in the ems code that would crash it
3 | reliably on startup. The EMS code has some interesting edge
4 | conditions on the Total_EMS_Handles variables, so the emu may segfault
5 | when an application uses EMS. Thanks to Moritz Barsnick and Fred
6 | Weigel.
7 |
8 | FreeDOS beta 5 wont run as it uses the 386 specific FS register. Beta
9 | 4 works fine.
10 |
11 | Added an example set of flags for Solaris and changed on_exit to
12 | atexit (Moritz Barsnick).
13 |
14 | Updated the README to reflect the new .pcemurc
15 |
16 | 1.01
17 |
18 | Speeded up BIOS printing by buffering write requests which occured within a
19 | short space of time. Result is a dramatic increase in speed (particularly
20 | for slow X terminals) when doing directory listings etc.
21 |
22 | Added kludge to support vga 50 line mode. This will be redone when/if font
23 | changes are fully supported. For now, it uses the same font, but simply
24 | changes the window size to accomodate the larger screen area. Switching to
25 | 50 line mode can either be accomplished by loading ansi.sys in the
26 | config.sys file and then using 'mode con lines=50', or by using the program
27 | 'vga50.com' in the programs directory. You can type 'mode co80' to return
28 | to the normal 80x25 display...
29 |
30 | Added ability to change compile time options via the Makefile
31 | Added support for a .pcemurc file to read various parameters at run time
32 |
33 | Added dumpdisk.{exe,c} for people without access to a Unix floppy disk so they
34 | can create a disk image
35 |
36 | Improved support for Sun type 4 keyboards. Made Meta equivalent to Alt key
37 |
38 | Added support for Int 0x10 function 0x1b which many programs call. A lot of
39 | the information it returns it a bit dubious, but it means ansi.sys no
40 | longer minds switching into 50 line mode
41 |
42 | Made control-break clear the keyboard buffer
43 |
44 | Altered the directory stuff in mfs.c to try to make it more portable
45 |
46 | Fixed silly bug where caps lock was being treated as shift lock.
47 |
48 | 1.00
49 |
50 | Initial release
51 |
52 |
53 |
--------------------------------------------------------------------------------
/COPYRIGHT:
--------------------------------------------------------------------------------
1 |
2 | All files, documentation etc with the exception of 'mfs.c',
3 | 'emufs.sys', 'emufs.S', 'lredir.exe', 'lredir.c' and 'lredir.readme'
4 | are Copyright (C) 1994 University of Bristol, England
5 |
6 | Permission is granted to use, copy, modify, and distribute this
7 | software and its documentation for any non-commercial purpose,
8 | provided that the above copyright notice appear in all copies and that
9 | both that copyright notice and this permission notice appear in the
10 | supporting documentation.
11 |
12 | BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
13 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
14 | WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
15 | PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND,
16 | EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
19 | PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
20 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
21 |
22 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
23 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
24 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
25 | DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
26 | DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
27 | (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
28 | INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
29 | THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
30 | OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 |
32 | ---------------------------------------------------------------------
33 |
34 | 'mfs.c', 'emufs.sys' and 'emufs.S' are covered by the following
35 | notice:
36 |
37 | Mach Operating System
38 | Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
39 | Copyright (c) 1991 IBM Corporation
40 | All Rights Reserved.
41 |
42 | Permission to use, copy, modify and distribute this software and its
43 | documentation is hereby granted, provided that both the copyright
44 | notice and this permission notice appear in all copies of the
45 | software, derivative works or modified versions, and any portions
46 | thereof, and that both notices appear in supporting documentation,
47 | and that the nema IBM not be used in advertising or publicity
48 | pertaining to distribution of the software without specific, written
49 | prior permission.
50 |
51 | CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
52 | CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
53 | ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
54 |
55 | Carnegie Mellon requests users of this software to return to
56 |
57 | Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
58 | School of Computer Science
59 | Carnegie Mellon University
60 | Pittsburgh PA 15213-3890
61 |
62 | any improvements or extensions that they make and grant Carnegie Mellon
63 | the rights to redistribute these changes.
64 |
65 | --------------------------------------------------------------------
66 |
67 | 'lredir' was written by Tim Bird (Tim_R_Bird@Novell.COM)
68 |
69 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #############################################################################
2 | # #
3 | # Third Year Project #
4 | # #
5 | # An IBM PC Emulator #
6 | # For Unix and X Windows #
7 | # #
8 | # By David Hedley #
9 | # #
10 | # #
11 | # This program is Copyrighted. Consult the file COPYRIGHT for more details #
12 | # #
13 | #############################################################################
14 |
15 | # Valid options are as follow:
16 | # -DINLINE_FUNCTIONS if your compiler support inline functions (most do)
17 | # -DDEBUG prints lots of debugging messages.
18 | # -DDEBUGGER compiles in the debugger
19 | # -DKBUK if you have a UK style 102 key keyboard
20 | # -DALIGNED_ACCESS if your computer requires words to be on even boundaries
21 | # -DBIGCASE If your compiler/computer can handle 256 case switches
22 | #
23 | # -D_HPUX_SOURCE If you are compiling on an HP
24 | # -DSOLARIS If you are using Solaris (only 2.3 has been tested)
25 | # -DSGI If you are using an SGI
26 | # -DRS6000 If you are using an RS6000
27 | # -DDISABLEX To disable the X output layer
28 | # -DDISABLECURSES To disable the curses output layer
29 | #
30 | # Note that when compiling on the RS6000 and SGI using the standard cc compiler
31 | # specifying -O2 to optimise the code results in the emulator crashing. I
32 | # believe this is due to compiler bugs (as the programs run OK without
33 | # optimisation). If anyone can shed light on what the problem is I would be
34 | # eternally grateful.
35 | #
36 | # Not specifying the following will mean the defaults are used. They can be
37 | # overridden in the .pcemurc file
38 | #
39 | # -DBOOT360 Boot from a 360k disk image file
40 | # -DBOOT720 Boot from a 720k disk image file
41 | # -DBOOT1_44 Boot from a 1.44Mb disk image file
42 | # -DBOOT1_2 Boot from a 1.2Mb disk image file
43 | #
44 | # -DBOOTFILE="xyz" Boot from disk image "xyz" (default "DriveA")
45 | # -DCURSORSPEED=n Set cursor flash speed to n frames per flash (default 30)
46 | # -DUPDATESPEED=n Set screen update speed to n frames per update (default 5)
47 | #
48 | # Including -fomit-frame-pointer should increase speed a little, but it has
49 | # been known to crash the emulator when running on certain machines (80x86
50 | # based PCs under Linux, and HPs running HPUX).
51 |
52 | # Linux settings
53 | CC = gcc
54 | OPTIONS = -DALIGNED_ACCESS -DBIGCASE -DINLINE_FUNCTIONS -DDISABLE_MFS
55 | XROOT = /usr/X11R6
56 | CFLAGS = -O2 -fomit-frame-pointer -fno-strength-reduce -Wall
57 | #CFLAGS = -ggdb
58 |
59 | # Solaris, thanks to Moritz Barnsnick
60 | #CC = gcc
61 | #OPTIONS = -DALIGNED_ACCESS -DBIGCASE -DSOLARIS -DINLINE_FUNCTIONS -DBOOT1_44
62 | #XROOT = /usr/openwin
63 | #CFLAGS = -O2 -Wall
64 |
65 | XLIBS = -lXext -lX11
66 | CURSESLIBS = -lncurses
67 |
68 | # Cross compiling to win32 settings
69 | #CC = i586-mingw32msvc-gcc
70 | #OPTIONS = -DALIGNED_ACCESS -DBIGCASE -DINLINE_FUNCTIONS -DDISABLE_MFS -DDISABLEX=1
71 | #XROOT = /usr/X11R6
72 | #CFLAGS = -O2 -fomit-frame-pointer -fno-strength-reduce -Wall
73 | #CFLAGS = -ggdb
74 |
75 | # You may need to add -N to the LFLAGS if you get sporadic segmentation
76 | # faults. So far I have only needed to do this when compiling under Linux
77 | # as Xlib seems to be mysteriously writing to its text segment
78 |
79 | LFLAGS = -g
80 |
81 | LIBRARIES = -L$(XROOT)/lib $(XLIBS) $(CURSESLIBS)
82 |
83 | XOFILES = xstuff.o
84 | CURSESOFILES = curses.o
85 |
86 | OFILES = main.o \
87 | cpu.o \
88 | bios.o \
89 | vga.o \
90 | vgahard.o \
91 | debugger.o \
92 | hardware.o \
93 | mfs.o \
94 | ems.o \
95 | video.o \
96 | config.o \
97 | $(XOFILES) $(CURSESOFILES)
98 |
99 | PROGNAME = pcemu
100 |
101 | GLOBAL_DEP = global.h \
102 | mytypes.h
103 |
104 | all: $(PROGNAME)
105 |
106 | cpu.o: $(GLOBAL_DEP) cpu.h instr.h debugger.h hardware.h
107 | ems.o: $(GLOBAL_DEP) cpu.h bios.h
108 | main.o: $(GLOBAL_DEP) bios.h hardware.h video.h
109 | bios.o: $(GLOBAL_DEP) bios.h cpu.h vga.h vgahard.h debugger.h hardware.h \
110 | keytabs.h mfs_link.h
111 | vga.o: $(GLOBAL_DEP) bios.h cpu.h vga.h vgahard.h hardware.h
112 | vgahard.o: $(GLOBAL_DEP) vgahard.h video.h hardware.h
113 | debugger.o: $(GLOBAL_DEP) cpu.h debugger.h disasm.h vgahard.h
114 | xstuff.o: $(GLOBAL_DEP) vgahard.h video.h icon.h hardware.h
115 | hardware.o: $(GLOBAL_DEP) cpu.h vgahard.h debugger.h hardware.h
116 | mfs.o: $(GLOBAL_DEP) cpu.h mfs.h mfs_link.h
117 | mytypes.h: autodetect.h
118 |
119 | autodetect.h: autodetect
120 | ./autodetect > autodetect.h
121 |
122 | .c.o:
123 | $(CC) $(CFLAGS) $(OPTIONS) -c $<
124 |
125 | $(PROGNAME): $(OFILES)
126 | $(CC) $(CFLAGS) -o $(PROGNAME) $(OFILES) $(LFLAGS) $(LIBRARIES)
127 |
128 | clean:
129 | rm -f $(PROGNAME) autodetect *.o *~
130 |
131 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 |
2 | PC Emulator for Unix and X Windows
3 |
4 | As the title suggests, this is a Unix/X windows program which is
5 | designed to emulate a standard 8086 based PC.
6 |
7 | In its current form it runs most text based programs. The programs I have
8 | tried and found to work are as follows:
9 |
10 | MSDOS 5.0 MSDOS 6.2
11 | WordPerfect 5.1 Borland C++ 2.0
12 | Turbo Debugger 2.51 Turbo Assembler 2.51
13 | BBCBasic 4.61 MSDOS QBasic
14 | MSDOS GWBASIC Virtually all program that came with MSDOS 5
15 | Hitchhiker's Guide to the Galaxy PC Magazine's ANSI.COM
16 | SemWare's QEdit 2.1 Norton Utils 4.50 Advanced Edition
17 | Norton Utils 6.0 Xtree Professional 1.1
18 | PowerMeter Utils Autoroute (ancient version)
19 | Minitab 8.0 Microsoft Diagnostics
20 |
21 | FreeDOS beta 4 (http://www.freedos.org/) works fine. Beta 5 seems to
22 | use the 386 instruction set and hence wont load.
23 |
24 | This is all the programs I could lay my hands on which were text based
25 | and could run on an 8086
26 |
27 | The emulator runs at about 8-10MHz 80286 speed on a Sun SparcStation
28 | 10/40 (without the -mviking flag) and at about 6MHz 8088 speed on a
29 | 33MHz 80486 box running Linux.
30 |
31 | I have included a Postscript representation of my project report. It's
32 | a bit out of date now, but it's the closest thing I've got to
33 | documentation! I'll do some kind of latex thing for the next
34 | release....
35 |
36 | The program rather hogs the cpu but unmapping the window (iconifying
37 | it) will put it to sleep.
38 |
39 | The most recent version of this program will always be in ftp.cs.bris.ac.uk
40 | currently in the directory /users/hedley
41 |
42 | INSTALLING THE EMULATOR
43 |
44 | Edit the Makefile to change the OPTIONS, CFLAGS and XROOT to be
45 | appropriate for your system (I am assuming you are using GNU GCC,
46 | although any ANSI C compiler should work just as well). Ensure you are
47 | using the best (speed) optimisations possible (e.g. -O2 -fomit-frame-poiner)
48 |
49 | Edit the file mytypes.h and ensure that the types for INT8, UINT8,
50 | INT16, UINT16 etc are correct. Hopefully nothing need be changed in
51 | this file, but you never can tell... I have assumed that 'char's are 8
52 | bit bytes, 'short's are 16 bit words and 'long's are 32 bit words. If
53 | your compiler treats these differently to the above then you will have
54 | to edit this header file.
55 |
56 | Type 'make' and go away and have a cup of tea! Compiling 'cpu.c' takes
57 | a while (and quite a bit of memory!).
58 |
59 | Get a floppy disk of the same size/type as you specified in the Makefile
60 | (i.e. if you chose -DBOOT720, then you'll need a 3.5" 720k disk). Install
61 | MSDOS on it. Copy the files 'config.sys', 'emufs.sys' and 'lredir.exe' from
62 | the 'programs' directory onto this floppy disk. Shove it in your Unix box
63 | and type cp /dev/fd0 DriveA This should create a 720k (or whatever) file
64 | which the emulator can boot from. If you do not have access to a Unix box
65 | with a floppy disk on it, then you can use the supplied 'dumpdisk' program
66 | to create a disk image. All you need is access to a PC. Simply put in a
67 | bootable MSDOS disk into the drive and type dumpdisk A (or dumpdisk B if in
68 | drive B). The program will copy the entire disk to a file called
69 | 'drivea'. You must then transfer it to your Unix box...
70 |
71 | You then need to convert the vga font (vga.bdf) into a font format
72 | your X server can understand (either SNF or PCF) using either
73 | 'bdftosnf' or 'bdftopcf' and install the resulting font file somewhere
74 | where your X server can find it. Then type 'mkfontdir' to rebuild the
75 | fonts.dir file and then type 'xset fp rehash' to tell your X server
76 | about the new font. If you type 'xlsfonts' you should see 'vga' as one
77 | of the fonts listed. If not, then something has gone wrong. I may or
78 | may not be able to help - it depends on your local setup. The emulator
79 | will run without the font as it uses the standard 8x16 X11 font -
80 | although most programs which use the extended character set will look
81 | pretty terrible. A warning will be displayed if the correct VGA font
82 | cannot be found. If you are using openwindows, you will have to type
83 | 'convertfont' and then 'bldfamily'
84 |
85 | You should now be in a position to run the emulator
86 |
87 | By default, the emulator requires the disk image called 'DriveA' to be in
88 | the current directory or else it will complain. If you don't like this,
89 | then you can change the file the emulator boots from by altering your
90 | .pcemurc file (see below) or by changing the default at compile time (by
91 | modifying the Makefile)
92 |
93 | Once run, the emulator should come up with the usual MSDOS banner and
94 | request the current date and time (which should already be
95 | correct). You can now run PC programs, mount Unix directories as
96 | drives etc. You will already have one drive redirection - drive C: is
97 | the Unix root directory. To mount further directories as drives, you
98 | must use the program 'lredir'. Consult the file 'lredir.readme' for
99 | instructions...
100 |
101 | The .pcemurc file
102 |
103 | At present this file allows a few things to be changed at run time. If this
104 | file is found (either in the current directory or in your home directory),
105 | then it is read and parsed and the values overwriting the equivalent
106 | compile time options.
107 |
108 | floppy
109 |
110 | where
111 | is 0 or 1 (A: or B:).
112 | is the disk image to use.
113 | , , specifies the geometry of the drive.
114 |
115 | For example, to load the FreeDOS beta4 mini boot image
116 | floppy 0 mini.bin 18 80 2
117 |
118 | harddrive
119 |
120 | where all the fields are as above for floppy.
121 |
122 | video
123 |
124 | where
125 | is currently one of curses or X.
126 |
127 | curses uses the curses library to run directly on the console. X pops
128 | up a seperate X window.
129 |
130 | updatespeed n
131 |
132 | where n is an integer > 0
133 | This is the rate at which the screen memory gets checked for changes (and
134 | hence the update speed at which the screen gets updated for non-BIOS
135 | writes). n is measured in internal interrupt ticks of which there are ~72.8
136 | per second (depends on the resolution of the system timer).
137 |
138 | cursorspeed n
139 |
140 | where n is an integer
141 | This specifies how fast the cursor should flash. Flashing the cursor can
142 | take a fair amount of bandwidth and so on slow/heavily loaded networks it
143 | may be best to slow down the cursor flashing. Setting n to 0 or less will
144 | disable cursor flashing - the cursor will be permanently on.
145 |
146 | An example .pcemurc file can be found in this directory in new.pcemurc.
147 |
148 | If you have problems compiling or running the emulator, then please contact
149 | me giving details of what went wrong (along with your computer type
150 | etc).
151 |
152 | Architectures tested:
153 |
154 | Computer OS Comments
155 | -----------------------------------------------------------------------------
156 | PC 486/33 Linux 0.99.14w Runs quite well. A bit pointless though :)
157 | Sun 3/60 SunOS 4.1.x Takes an age to compile and not really worth
158 | the effort...
159 | SparcStation 10 SunOS 4.1.3 Runs well. Takes > 20MB RAM to compile though
160 | HP 755/99 HPUX Runs OK (>25MB RAM to compile...)
161 | Sun 4 Solaris 2.3 Runs OK
162 | RS6000 ??? Had a few problems getting it to compile.
163 | Getting there slowly though.
164 | SGI Indigo IRIX 4.?.? Doesn't work if compiled with optimisation
165 | using the standard compiler. Haven't tried
166 | it using gcc yet...
167 |
168 | As you can see this list is quite small. The main limiting factor is the range
169 | of machines I have access to. If anyone else can get it running on other
170 | architectures then please contact me!
171 |
172 | Warning: This program is not secure! Do not make is suid or sgid anything
173 | unless you wish to compromise the security of your system!
174 |
175 | EMULATOR LIMITATIONS etc
176 |
177 | Some parts of the PC architecture are emulated better than others. The
178 | BIOS has been partly implemented - enough to get MSDOS to boot and to
179 | allow most programs to run. Anyhow, most decent programs bypass the
180 | BIOS for screen access. BIOS Disk calls for drive A have been mostly
181 | emulated, although formatting doesn't work.
182 |
183 | Some of the hardware has been emulated but not much. Timer interrupts
184 | are generated by the system but there is now way (at present) to
185 | reprogram the timer. The Programmable Interrupt Controller has been
186 | emulated in part to respond to the End Of Interrupt command and reads
187 | from and writes to the mask register should work OK.
188 |
189 | None of the VGA hardware has been emulated at present (apart from
190 | screen updating) although this will change in the near future. Mode
191 | changes must therefore be done through the BIOS.
192 |
193 | The keyboard has been mostly emulated. The program converts X11
194 | keysyms to raw PC scan codes and then generates an interrupt 9 as per
195 | usual. There is a BIOS routine which takes these scan codes and
196 | generates the correct BIOS ASCII/scan code pair. The keysyms used can
197 | be found in the module 'xstuff.c'. In the future these keysyms will be
198 | read in from a file at run time.
199 |
200 | THANKS
201 |
202 | Thanks go to the following:
203 |
204 | Andy Norman at HPLabs, Bristol (ange@hpl.hewlett-packard.co.uk) for the HP
205 | port.
206 | Dieter Becker (becker@med-in.uni-sb.de) for help with the Solaris port
207 | Klaas Esselink (esselin1@ksla.nl) for help with the RS6000 port
208 |
209 | Please report bugs/comments etc to me (hedley@cs.bris.ac.uk) and I'll
210 | do my best to sort them out (no guarantees though). After June 25th I
211 | will be leaving University and will not be able to check email very
212 | frequently - please be patient if you want a response - I will reply
213 | eventually.
214 |
215 | Have fun...
216 |
217 | David
218 |
219 |
220 |
221 |
--------------------------------------------------------------------------------
/README.dg:
--------------------------------------------------------------------------------
1 | This document contains minimal information about the changes I've made to
2 | David Hedley's PC Emulator. I found David Hedley's PC Emulator several
3 | years ago, and spent some time working on it. Unfortunately this was ages
4 | ago and I can barely remember what I did!
5 |
6 | The improvements I *can* remember:
7 |
8 | * A pop-up menu allowing disc mounting and dismounting.
9 | * Better floppy disc support (inc. the above).
10 | * More secure. No longer stores host function pointers in the
11 | target's memory space (!).
12 | * Various smoothings-out all over.
13 | * Other stuff I can't remember.
14 |
15 | There is hardly any documentation other than David Hedley's original
16 | documentation. This is from memory:
17 |
18 | The AUTOEJECT compile-time definition is of a command to execute when
19 | dismounting discs (I originally used a Sun with autoeject disc drives).
20 |
21 | Press any mouse button in the pcemu window to pop up the menu.
22 |
23 | Don't look in mfs.c, it's not pretty (it also doesn't work on the DEC
24 | Alpha).
25 |
26 | Most of my changes are commented. Some are not. One of these days I should
27 | get round to doing a proper diff against David Hedley's original source.
28 | If you really want to know, you can download the original version from my
29 | web site.
30 |
31 | I recently discovered that the EMS driver module was written by someone
32 | else. Perhaps if we get our act together a proper COPYRIGHT and AUTHORS
33 | file could be written.
34 |
35 | Um, I think that's the lot... as you might of guessed, this file was
36 | hacked up quickly while waiting for something to compile. I don't even
37 | know if it works properly. Have fun, and let me know what happens!
38 |
39 | David Given
40 | http://wiredsoc.ml.org/~dg
41 | dg@tao.co.uk
42 |
43 |
44 |
--------------------------------------------------------------------------------
/README.mlh:
--------------------------------------------------------------------------------
1 | In following with tradition, this document covers the changes since
2 | David Given's release.
3 |
4 | The video output layer was split, and a ncurses layer was added. You
5 | can now run directly on a terminal by adding the
6 |
7 | video curses
8 |
9 | line to your pcemurc. X is the default.
10 |
11 | A few of the missing 186 instructions were added so that FreeDOS could
12 | boot. Some were hooked in but not implemented (especially the mul
13 | instructions).
14 |
15 | The code was updated to compile cleanly against glibc 2.2.1. It has
16 | been tested under Debian 2.2-powerpc.
17 |
18 | Michael Hope
19 | michaelh@juju.net.nz
20 | 21 Jan 2001
21 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | Follows is the older list of things to do.
2 |
3 | Current list of things to do.
4 |
5 | Most of the below should be implemented in the next version due out in
6 | August/September.
7 |
8 |
9 | 1. Recode CPU module.
10 | Speed it up!
11 | Reduce/eliminate penalty for big endian machines.
12 | Possibly including lazy flag evaluation, although initial
13 | indications are that it is actually slower than
14 | calculating the flags after each instruction.
15 |
16 | 2. Finish BIOS
17 | Exactly how much of the BIOS remains to do is open to question
18 | - it seems a little pointless wasting time writing code
19 | for BIOS functions that no program ever uses The VGA BIOS will be
20 | extended/rewritten to allow for graphics modes when they
21 | are implemented.
22 |
23 | 3. Printer support
24 | Dunno quite what to do about this - could dump all printer
25 | output to a file I suppose.
26 |
27 | 4. VGA support
28 | Initially the CGA 640x200x2 320x200x4 and MCGA 320x200x256,
29 | but eventually all VGA modes should be supported (albeit slowly :)
30 | Support for different character sets...
31 | Chip level access should eventually be possible (kind of vital
32 | for the graphics modes). Dunno about some of the more
33 | esoteric CRTC options though....
34 |
35 | 5. Rewrite mfs.c
36 | mfs.c needs a complete rewrite/redesign as it has bugs in it
37 | and generates loads of warnings when compiling with the
38 | -Wall flag...
39 |
40 | 6. Chip level emulations...
41 | The timer chip should be properly emulated so that accuracy is
42 | not lost (irrespect of the resolution of the Unix system timer)
43 |
44 | 7. Sound support
45 | Should be possible to get the PC sound emulated OK (dunno
46 | about the sound cards though)
47 |
48 | 8. Idle time detector
49 | The emulator should try to detect when programs running under
50 | it are idle and consequently reduce the system load by
51 | going to sleep for a bit
52 |
53 | 9. Improved user interface
54 | Configuration files for boot drive, keyboard mappings etc
55 | Rewrite the X window module to allow for cutting/pasting etc
56 | Use Imake
57 |
58 |
59 | This list is not complete! - anything in particular you would like to
60 | see, then please mail me
61 |
62 | David
63 |
64 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 1.1.dg
2 |
3 | This is based on David Hedley's 1.01 release.
4 |
5 | --dg
6 |
7 |
--------------------------------------------------------------------------------
/autodetect.c:
--------------------------------------------------------------------------------
1 | /*
2 | * wordsize.c
3 | *
4 | * Produces a #include file that defines INT16, INT32 etc in a (hopefully)
5 | * portable manner.
6 | */
7 |
8 | #include
9 | #include
10 |
11 | struct {
12 | char *name;
13 | int size;
14 | } typearray[] = {
15 | {"char", sizeof(char)},
16 | {"short int", sizeof(short int)},
17 | {"int", sizeof(int)},
18 | {"long int", sizeof(long int)},
19 | {NULL, 0},
20 | };
21 |
22 | void dotype(int size)
23 | {
24 | int i = 0;
25 |
26 | while (typearray[i].name)
27 | {
28 | if ((typearray[i].size * 8) == size)
29 | {
30 | printf("typedef signed %s INT%d;\n", typearray[i].name, size);
31 | printf("typedef unsigned %s UINT%d;\n", typearray[i].name, size);
32 | return;
33 | }
34 | i++;
35 | }
36 |
37 | fprintf(stderr, "Could find a type of length %d\n", size);
38 | exit(1);
39 | }
40 |
41 | int main(int argc, char *argv[])
42 | {
43 | union {
44 | char c[4];
45 | int i;
46 | } endian;
47 |
48 | printf("/* Automatically created file --- do not edit */\n\n");
49 |
50 | dotype(8);
51 | dotype(16);
52 | dotype(32);
53 |
54 | endian.i = 0;
55 | endian.c[0] = 1;
56 | if (endian.i == 1)
57 | printf("#define PCEMU_LITTLE_ENDIAN\n");
58 | else
59 | printf("#define PCEMU_BIG_ENDIAN\n");
60 |
61 | return 0;
62 | }
63 |
--------------------------------------------------------------------------------
/autodetect.h:
--------------------------------------------------------------------------------
1 | /* Automatically created file --- do not edit */
2 |
3 | typedef signed char INT8;
4 | typedef unsigned char UINT8;
5 | typedef signed short int INT16;
6 | typedef unsigned short int UINT16;
7 | typedef signed int INT32;
8 | typedef unsigned int UINT32;
9 | #define PCEMU_BIG_ENDIAN
10 |
--------------------------------------------------------------------------------
/bios.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is BIOS.H It contains definitions for the BIOS functions */
16 |
17 |
18 | #ifndef BIOS_H
19 | #define BIOS_H
20 |
21 | #include "mytypes.h"
22 |
23 | #define BOOT
24 |
25 | void (*bios_routine[256])(void);
26 |
27 | void init_bios(void);
28 | void init_timer(void);
29 | void bios_off(void);
30 | void set_int(unsigned, BYTE *, unsigned, void (*routine)(void), BYTE *, unsigned);
31 |
32 | void int_ems(void);
33 | void EMS_Setup(void);
34 |
35 | void disable(void);
36 | void enable(void);
37 |
38 | void put_scancode(BYTE *code, int count);
39 |
40 | BYTE read_port60(void);
41 |
42 | void loc(void);
43 |
44 | char *set_boot_file(char *);
45 | char *set_boot_type(int);
46 |
47 | #define MAXHDISKS 2
48 | #define MAXFDISKS 2
49 |
50 | typedef struct
51 | {
52 | char *name;
53 | unsigned sectors;
54 | unsigned cylinders;
55 | unsigned heads;
56 | int fd;
57 | char removable;
58 | char mounted;
59 | } DiskTab;
60 |
61 | extern DiskTab fdisk[MAXFDISKS];
62 | extern DiskTab fdisk[MAXFDISKS];
63 |
64 | extern char *set_num_fdrives(int);
65 | extern char *set_num_hdrives(int);
66 | char *set_floppy_drive(int drive, char *device, int sectors, int cylinders, int heads);
67 | char *set_hard_drive(int drive, char *device, int sectors, int cylinders, int heads);
68 | void open_drive(DiskTab [], int drive);
69 | char *set_boot_drive(int);
70 |
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/config.c:
--------------------------------------------------------------------------------
1 | #include "global.h"
2 | #include "bios.h"
3 | #include "vgahard.h"
4 | #include "video.h"
5 | #include
6 |
7 | void check_error(const char *msg, int line)
8 | {
9 | if (msg)
10 | fprintf(stderr,"%s, line %d\n", msg, line);
11 | }
12 |
13 | void read_pcemurc(void)
14 | { /* This procedure is a bit of a hack :) - will be redone later */
15 | FILE *f1;
16 | char buffer[1024]; /* Maximum path length. Should really be a #define */
17 | char keyword[1024];
18 | char value[1024];
19 | int line = 0;
20 | int i;
21 |
22 | /* Try current directory first... */
23 |
24 | if ((f1 = fopen(".pcemurc","r")) == NULL)
25 | { /* Try home directory */
26 | sprintf(buffer,"%s/.pcemurc", getenv("HOME"));
27 | if ((f1 = fopen(buffer,"r")) == NULL)
28 | {
29 | printf("Warning: .pcemurc not found - using compile time defaults\n");
30 | return;
31 | }
32 | }
33 |
34 | /* This bit hacked by David Given to, er, improve... */
35 |
36 | while (fgets(buffer,sizeof buffer,f1) != NULL)
37 | {
38 | line++;
39 | i = 0; /* Strip leading spaces */
40 | while(buffer[i] == ' ')
41 | i++;
42 | strcpy(keyword, buffer+i);
43 |
44 | while(buffer[i] != ' ') /* Skip to end of keyword */
45 | i++;
46 | while(buffer[i] == ' ')
47 | i++;
48 | strcpy(value, buffer+i); /* Write value */
49 |
50 | i = 0; /* Trim keyword to one word */
51 | while(keyword[i] != ' ')
52 | i++;
53 | keyword[i] = '\0';
54 |
55 | i = 0; /* Strip out \n */
56 | while(value[i] != '\0')
57 | {
58 | if (value[i] == '\n')
59 | value[i] = '\0';
60 | i++;
61 | }
62 |
63 | if ((keyword[0] == '#') || (keyword[0] == ' ') || (keyword[0] == '\n'))
64 | continue;
65 |
66 | if (strcasecmp(keyword, "floppy") == 0)
67 | {
68 | int drive;
69 | char device[1024];
70 | int sectors;
71 | int cylinders;
72 | int heads;
73 |
74 | if (sscanf(value, "%d %s %d %d %d", &drive, device, §ors, &cylinders, &heads) == 5)
75 | check_error(set_floppy_drive(drive, device, sectors, cylinders, heads), line);
76 | else
77 | check_error("Syntax error in \"floppy\" directive", line);
78 | }
79 | else if (strcasecmp(keyword, "harddrive") == 0)
80 | {
81 | int drive;
82 | char device[1024];
83 | int sectors;
84 | int cylinders;
85 | int heads;
86 |
87 | if (sscanf(value, "%d %s %d %d %d", &drive, device, §ors, &cylinders, &heads) == 5)
88 | check_error(set_hard_drive(drive, device, sectors, cylinders, heads), line);
89 | else
90 | check_error("Syntax error in \"hard\" directive", line);
91 | }
92 | else if (strcasecmp(keyword, "numharddrives") == 0)
93 | check_error(set_num_hdrives(strtol(value, NULL, 10)), line);
94 | else if (strcasecmp(keyword, "numfloppydrives") == 0)
95 | check_error(set_num_fdrives(strtol(value, NULL, 10)), line);
96 | else if (strcasecmp(keyword,"updatespeed") == 0)
97 | check_error(set_update_rate(strtol(value, NULL,10)), line);
98 | else if (strcasecmp(keyword,"cursorspeed") == 0)
99 | check_error(set_cursor_rate(strtol(value, NULL,10)), line);
100 | /* else if (strcasecmp(keyword,"keymap") == 0)
101 | check_error(set_keymap(buffer), line);*/
102 | else if (strcasecmp(keyword, "video") == 0)
103 | check_error(set_video_mode(value), line);
104 | else
105 | check_error("Syntax error in .pcemu file", line);
106 | }
107 | fclose(f1);
108 | }
109 |
--------------------------------------------------------------------------------
/cpu.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is CPU.H it contains definitions for cpu.c */
16 |
17 |
18 | #ifndef CPU_H
19 | #define CPU_H
20 |
21 | #include "mytypes.h"
22 |
23 | enum {
24 | AX = 0,
25 | CX,
26 | DX,
27 | BX,
28 | SP,
29 | BP,
30 | SI,
31 | DI
32 | };
33 |
34 | enum {
35 | AL = 0,
36 | CL,
37 | DL,
38 | BL,
39 | AH,
40 | CH,
41 | DH,
42 | BH
43 | };
44 |
45 | enum {
46 | SPL = 8,
47 | SPH,
48 | BPL,
49 | BPH,
50 | SIL,
51 | SIH,
52 | DIL,
53 | DIH
54 | };
55 |
56 | enum {
57 | ES = 0,
58 | CS,
59 | SS,
60 | DS
61 | };
62 |
63 |
64 | /* parameter x = result, y = source 1, z = source 2 */
65 |
66 | #define SetCFB_Add(x,y) (CF = (BYTE)(x) < (BYTE)(y))
67 | #define SetCFW_Add(x,y) (CF = (WORD)(x) < (WORD)(y))
68 | #define SetCFB_Sub(y,z) (CF = (BYTE)(y) > (BYTE)(z))
69 | #define SetCFW_Sub(y,z) (CF = (WORD)(y) > (WORD)(z))
70 | #define SetZFB(x) (ZF = !(BYTE)(x))
71 | #define SetZFW(x) (ZF = !(WORD)(x))
72 | #define SetTF(x) (TF = (x))
73 | #define SetIF(x) (IF = (x))
74 | #define SetDF(x) (DF = (x))
75 | #define SetAF(x,y,z) (AF = ((x) ^ ((y) ^ (z))) & 0x10)
76 | #define SetPF(x) (PF = parity_table[(BYTE)(x)])
77 | #define SetOFW_Add(x,y,z) (OF = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000)
78 | #define SetOFB_Add(x,y,z) (OF = ((x) ^ (y)) & ((x) ^ (z)) & 0x80)
79 | #define SetOFW_Sub(x,y,z) (OF = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000)
80 | #define SetOFB_Sub(x,y,z) (OF = ((z) ^ (y)) & ((z) ^ (x)) & 0x80)
81 | #define SetSFW(x) (SF = (x) & 0x8000)
82 | #define SetSFB(x) (SF = (x) & 0x80)
83 |
84 |
85 | #define GetMemInc(Seg,Off) ((Seg)[(Off)++])
86 |
87 | #if defined(TEST) && defined(BSD386)
88 | # define SegToMemPtr(Seg) (sregs[Seg] == 0xa000 ? (BYTE *)0xe00a0000 : \
89 | sregs[Seg] == 0xb800 ? (BYTE *)0xe00b8000 : \
90 | &memory[sregs[Seg] << 4])
91 | #else
92 | # define SegToMemPtr(Seg) (&memory[sregs[Seg] << 4])
93 | #endif
94 |
95 |
96 | #define PutMemB(Seg,Off,x) ((Seg)[(WORD)(Off)] = (BYTE)(x))
97 | #define GetMemB(Seg,Off) ((BYTE)(Seg)[(WORD)(Off)])
98 |
99 | #define CalcAll()
100 |
101 | #define CompressFlags() (UINT32)(CF | (PF << 2) | (!(!AF) << 4) | (ZF << 6) \
102 | | (!(!SF) << 7) | (TF << 8) | (IF << 9) \
103 | | (DF << 10) | (!(!OF) << 11))
104 |
105 | #define ExpandFlags(f) \
106 | { \
107 | CF = (f) & 1; \
108 | PF = ((f) & 4) == 4; \
109 | AF = (f) & 16; \
110 | ZF = ((f) & 64) == 64; \
111 | SF = (f) & 128; \
112 | TF = ((f) & 256) == 256; \
113 | IF = ((f) & 512) == 512; \
114 | DF = ((f) & 1024) == 1024; \
115 | OF = (f) & 2048; \
116 | }
117 |
118 |
119 | /* ChangeE(x) changes x to little endian from the machine's natural endian
120 | format and back again. Obviously there is nothing to do for little-endian
121 | machines... */
122 |
123 | #if defined(PCEMU_LITTLE_ENDIAN)
124 | # define ChangeE(x) (WORD)(x)
125 | #else
126 | # define ChangeE(x) (WORD)(((x) << 8) | ((BYTE)((x) >> 8)))
127 | #endif
128 |
129 | #if defined(PCEMU_LITTLE_ENDIAN) && !defined(ALIGNED_ACCESS)
130 | # define ReadWord(x) (*(x))
131 | # define WriteWord(x,y) (*(x) = (y))
132 | # define CopyWord(x,y) (*x = *y)
133 | # define PutMemW(Seg,Off,x) (Seg[Off] = (BYTE)(x), Seg[(WORD)(Off)+1] = (BYTE)((x) >> 8))
134 | #if 0
135 | # define PutMemW(Seg,Off,x) (*(WORD *)((Seg)+(WORD)(Off)) = (WORD)(x))
136 | #endif
137 | /* dtrg. `possible pointer alignment problem, Lint says */
138 | # define GetMemW(Seg,Off) ((WORD)Seg[Off] + ((WORD)Seg[(WORD)(Off)+1] << 8))
139 | #if 0
140 | # define GetMemW(Seg,Off) (*(WORD *)((Seg)+(Off))) */
141 | #endif
142 | #else
143 | # define ReadWord(x) ((WORD)(*((BYTE *)(x))) + ((WORD)(*((BYTE *)(x)+1)) << 8))
144 | # define WriteWord(x,y) (*(BYTE *)(x) = (BYTE)(y), *((BYTE *)(x)+1) = (BYTE)((y) >> 8))
145 | # define CopyWord(x,y) (*(BYTE *)(x) = *(BYTE *)(y), *((BYTE *)(x)+1) = *((BYTE *)(y)+1))
146 | # define PutMemW(Seg,Off,x) (Seg[Off] = (BYTE)(x), Seg[(WORD)(Off)+1] = (BYTE)((x) >> 8))
147 | # define GetMemW(Seg,Off) ((WORD)Seg[Off] + ((WORD)Seg[(WORD)(Off)+1] << 8))
148 | #endif
149 |
150 | extern WORD wregs[8]; /* Always little-endian */
151 | extern BYTE *bregs[16]; /* Points to bytes within wregs[] */
152 | extern unsigned sregs[4]; /* Always native machine word order */
153 |
154 | extern unsigned ip; /* Always native machine word order */
155 |
156 | /* All the byte flags will either be 1 or 0 */
157 | extern BYTE CF, PF, ZF, TF, IF, DF;
158 |
159 | /* All the word flags may be either none-zero (true) or zero (false) */
160 | extern unsigned AF, OF, SF;
161 |
162 | extern BYTE *c_cs,*c_ds,*c_es,*c_ss,*c_stack;
163 |
164 | extern volatile int int_pending;
165 | extern volatile int int_blocked;
166 |
167 | #endif
168 |
--------------------------------------------------------------------------------
/curses.c:
--------------------------------------------------------------------------------
1 | #include "global.h"
2 |
3 | #include "vgahard.h"
4 | #include "hardware.h"
5 | #include "bios.h"
6 | #include "video.h"
7 |
8 | #include
9 |
10 | extern int mono;
11 |
12 | static WINDOW *scr;
13 |
14 | static void curses_end(void)
15 | {
16 | endwin();
17 | }
18 |
19 | static void curses_init(void)
20 | {
21 | mono = 1;
22 | scr = initscr();
23 | cbreak();
24 | noecho();
25 | nodelay(stdscr, TRUE);
26 | keypad(scr, TRUE);
27 |
28 | atexit(curses_end);
29 | }
30 |
31 | static void curses_flush(void)
32 | {
33 | refresh();
34 | }
35 |
36 | static void curses_put_cursor(unsigned x, unsigned y)
37 | {
38 | }
39 |
40 | static void curses_unput_cursor(void)
41 | {
42 | }
43 |
44 | static void curses_copy(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
45 | unsigned nx, unsigned ny)
46 | {
47 | /* Cant figure this out. Be evil. */
48 | int x, y;
49 |
50 | for (y=0; y<=y2-y1; y++) {
51 | for (x=0; x<=x2-x1; x++) {
52 | int at = mvinch(y1+y, x1+x);
53 | mvaddch(ny+y, nx+x, at);
54 | }
55 | }
56 | }
57 |
58 | static void curses_new_cursor(int st, int end)
59 | {
60 | }
61 |
62 | static void curses_window_size(unsigned width, unsigned height)
63 | {
64 | }
65 |
66 | static void curses_draw_line(unsigned x, unsigned y, const char *text, unsigned len, BYTE attr)
67 | {
68 | mvaddnstr(y, x, text, len);
69 | }
70 |
71 | static BYTE scan_table1[256 - 0x20] =
72 | {
73 | 0x39, 0x02,
74 | #ifdef KBUK /* double quotes, hash symbol */
75 | 0x03, 0x2b,
76 | #else
77 | 0x28, 0x04,
78 | #endif
79 | 0x05, 0x06, 0x08, 0x28,
80 | 0x0a, 0x0b, 0x09, 0x0d, 0x33, 0x0c, 0x34, 0x35,
81 | 0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
82 | 0x09, 0x0a, 0x27, 0x27, 0x33, 0x0d, 0x34, 0x35,
83 | #ifdef KBUK /* at symbol */
84 | 0x28,
85 | #else
86 | 0x03,
87 | #endif
88 | 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22,
89 | 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18,
90 | 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11,
91 | 0x2d, 0x15, 0x2c, 0x1a,
92 | #ifdef KBUK /* backslash */
93 | 0x56,
94 | #else
95 | 0x2b,
96 | #endif
97 | 0x1b, 0x07, 0x0c,
98 | 0x29, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22,
99 | 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18,
100 | 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11,
101 | 0x2d, 0x15, 0x2c, 0x1a,
102 | #ifdef KBUK /* vertical bar */
103 | 0x56,
104 | #else
105 | 0x2b,
106 | #endif
107 |
108 | 0x1b,
109 |
110 | #ifdef KBUK /* tilde */
111 | 0x2b,
112 | #else
113 | 0x29,
114 | #endif
115 | 0
116 | };
117 |
118 | static struct {
119 | int code;
120 | int scan;
121 | } basic_keys[] = {
122 | { 263, 0x0e },
123 | { 10, 0x1c },
124 | { 27, 0x01 },
125 | { 9, 0x0f }
126 | };
127 |
128 | static unsigned translate(int key)
129 | {
130 | int i;
131 | if (key >= 0x20 && key <= 0x20+sizeof(scan_table1))
132 | return (scan_table1[key - 0x20]);
133 | for (i=0; i<(sizeof(basic_keys)/sizeof(basic_keys[0])); i++) {
134 | if (basic_keys[i].code == key)
135 | return basic_keys[i].scan;
136 | }
137 | return 0;
138 | }
139 |
140 | static void curses_tick(void)
141 | {
142 | int got = getch();
143 |
144 | if (got != ERR) {
145 | int scan, count;
146 | char buffer[10];
147 |
148 | // printf("Got %u\n", got);
149 | if ((scan = translate(got)) != 0) {
150 | for (count = 0; scan; count++)
151 | {
152 | buffer[count] = scan & 0xff;
153 |
154 | scan >>= 8;
155 | }
156 |
157 | if (port60_buffer_ok(count))
158 | {
159 | D(printf("Returning %d scan code bytes\n",count););
160 | put_scancode(buffer, count);
161 | }
162 | }
163 | }
164 | }
165 |
166 | VIDEO_DRIVER curses_video = {
167 | "curses",
168 | curses_init,
169 | curses_end,
170 | curses_flush,
171 | curses_put_cursor,
172 | curses_unput_cursor,
173 | curses_copy,
174 | curses_new_cursor,
175 | curses_window_size,
176 | curses_draw_line,
177 | curses_tick
178 | };
179 |
--------------------------------------------------------------------------------
/debugger.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | #ifdef DEBUGGER
16 |
17 | #ifndef DEBUGGER_H
18 | #define DEBUGGER_H
19 |
20 | #define D_INT 0
21 | #define D_TRACE 1
22 |
23 | volatile int in_debug;
24 | void call_debugger(int);
25 | int debug_breakin(int);
26 | void print_regs(void);
27 |
28 | extern volatile int breakpoint;
29 | extern volatile int running;
30 | #endif
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/disasm.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | #ifdef DEBUGGER
16 |
17 | #ifndef DISASM_H
18 | #define DISASM_H
19 |
20 | #include "mytypes.h"
21 |
22 | static unsigned decode_br8(BYTE *, unsigned, char *);
23 | static unsigned decode_r8b(BYTE *, unsigned, char *);
24 | static unsigned decode_wr16(BYTE *, unsigned, char *);
25 | static unsigned decode_r16w(BYTE *, unsigned, char *);
26 | static unsigned decode_ald8(BYTE *, unsigned, char *);
27 | static unsigned decode_axd16(BYTE *, unsigned, char *);
28 | static unsigned decode_pushpopseg(BYTE *, unsigned, char *);
29 | static unsigned decode_databyte(BYTE *, unsigned, char *);
30 | static unsigned decode_wordreg(BYTE *, unsigned, char *);
31 | static unsigned decode_cond_jump(BYTE *, unsigned, char *);
32 | static unsigned decode_bd8(BYTE *, unsigned, char *);
33 | static unsigned decode_wd16(BYTE *, unsigned, char *);
34 | static unsigned decode_wd8(BYTE *, unsigned, char *);
35 | static unsigned decode_ws(BYTE *, unsigned, char *);
36 | static unsigned decode_sw(BYTE *, unsigned, char *);
37 | static unsigned decode_w(BYTE *, unsigned, char *);
38 | static unsigned decode_string(BYTE *, unsigned, char *);
39 | static unsigned decode_xchgax(BYTE *, unsigned, char *);
40 | static unsigned decode_far(BYTE *, unsigned, char *);
41 | static unsigned decode_almem(BYTE *, unsigned, char *);
42 | static unsigned decode_axmem(BYTE *, unsigned, char *);
43 | static unsigned decode_memal(BYTE *, unsigned, char *);
44 | static unsigned decode_memax(BYTE *, unsigned, char *);
45 | static unsigned decode_rd(BYTE *, unsigned, char *);
46 | static unsigned decode_d16(BYTE *, unsigned, char *);
47 | static unsigned decode_int3(BYTE *, unsigned, char *);
48 | static unsigned decode_d8(BYTE *, unsigned, char *);
49 | static unsigned decode_bbit1(BYTE *, unsigned, char *);
50 | static unsigned decode_wbit1(BYTE *, unsigned, char *);
51 | static unsigned decode_bbitcl(BYTE *, unsigned, char *);
52 | static unsigned decode_wbitcl(BYTE *, unsigned, char *);
53 | static unsigned decode_escape(BYTE *, unsigned, char *);
54 | static unsigned decode_disp(BYTE *, unsigned, char *);
55 | static unsigned decode_adjust(BYTE *, unsigned, char *);
56 | static unsigned decode_d8al(BYTE *, unsigned, char *);
57 | static unsigned decode_d8ax(BYTE *, unsigned, char *);
58 | static unsigned decode_axd8(BYTE *, unsigned, char *);
59 | static unsigned decode_disp16(BYTE *, unsigned, char *);
60 | static unsigned decode_far_ind(BYTE *, unsigned, char *);
61 | static unsigned decode_portdx(BYTE *, unsigned, char *);
62 | static unsigned decode_f6(BYTE *, unsigned, char *);
63 | static unsigned decode_f7(BYTE *, unsigned, char *);
64 | static unsigned decode_b(BYTE *, unsigned, char *);
65 | static unsigned decode_ff(BYTE *, unsigned, char *);
66 | static unsigned decode_bioscall(BYTE *, unsigned, char *);
67 |
68 | static char *byte_reg[] = { "al","cl","dl","bl","ah","ch","dh","bh" };
69 | static char *word_reg[] = { "ax","cx","dx","bx","sp","bp","si","di" };
70 | static char *seg_reg[] = { "es","cs","ss","ds" };
71 | static char *index_reg[] = { "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" };
72 | static char *nul_reg[] = { "??", "??", "??", "??", "??", "??", "??", "??" };
73 | static char *condition[] =
74 | {
75 | "o","no","b","ae","z","nz","be","a","s","ns","p","np","l","ge","le","g"
76 | };
77 |
78 | static char *itext[] =
79 | {
80 | "", "add", "push", "pop", "or", "adc", "sbb", "and",
81 | "es:", "daa", "sub", "cs:", "das", "xor", "ss:", "aaa", "cmp", "ds:",
82 | "aas", "inc", "dec", "j", "test", "xchg", "mov", "lea", "nop", "cbw",
83 | "cwd", "call", "wait", "pushf", "popf", "sahf", "lahf", "movs",
84 | "cmps", "stos", "lods", "scas", "ret", "les", "lds", "retf", "int",
85 | "into", "iret", "rol", "ror", "rcl", "rcr", "shl", "shr", "sar", "aam",
86 | "aad", "xlat", "esc", "loopne", "loope", "loop", "jcxz", "in", "out",
87 | "jmp", "lock", "repz", "repnz", "hlt", "cmc", "not", "neg", "mul", "imul",
88 | "div", "idiv", "clc", "stc", "cli", "sti", "cld", "std", "db", "???"
89 | };
90 |
91 | enum instructions
92 | {
93 | none, add, push, pop, or, adc, sbb, and, es, daa,
94 | sub, cs, das, xor, ss, aaa, cmp, ds, aas, inc, dec, jump, test, xchg,
95 | mov, lea, nop, cbw, cwd, call, wait, pushf, popf, sahf, lahf, movs,
96 | cmps, stos, lods, scas, ret, les, lds, retf, intr, into, iret, rol,
97 | ror, rcl, rcr, shl, shr, sar, aam, aad, xlat, esc, loopne, loope, loop,
98 | jcxz, in, out, jmp, lock, repz, repnz, hlt, cmc, not, neg, mul, imul,
99 | divide, idiv, clc, stc, cli, sti, cld, std, db, illegal
100 | };
101 |
102 |
103 | #define DF_PREFIX 1
104 | #define DF_NOSPACE 2
105 |
106 | static int table_8x[] = { add, or, adc, sbb, and, sub, xor, cmp };
107 | static int table_cx[] = { rol, ror, rcl, rcr };
108 | static int table_dx[] = { rol, ror, rcl, rcr, shl, shr, shl, sar };
109 | static int table_f67[] = { test, illegal, not, neg, mul, imul, divide, idiv };
110 | static int table_fe[] = { inc, dec, illegal, illegal, illegal, illegal, illegal, illegal };
111 | static int table_ff[] = { inc, dec, call, call, jmp, jmp, push, illegal };
112 |
113 | static struct Disasm
114 | {
115 | int text;
116 | unsigned (*type)(BYTE *, unsigned, char *);
117 | int flags;
118 | int *supp;
119 | } disasm_table[256] =
120 | {
121 | { add, decode_br8 }, /* 0x00 */
122 | { add, decode_wr16 }, /* 0x01 */
123 | { add, decode_r8b }, /* 0x02 */
124 | { add, decode_r16w }, /* 0x03 */
125 | { add, decode_ald8 }, /* 0x04 */
126 | { add, decode_axd16 }, /* 0x05 */
127 | { push,decode_pushpopseg }, /* 0x06 */
128 | { pop, decode_pushpopseg }, /* 0x07 */
129 | { or, decode_br8 }, /* 0x08 */
130 | { or, decode_wr16 }, /* 0x09 */
131 | { or, decode_r8b }, /* 0x0a */
132 | { or, decode_r16w }, /* 0x0b */
133 | { or, decode_ald8 }, /* 0x0c */
134 | { or, decode_axd16 }, /* 0x0d */
135 | { push,decode_pushpopseg }, /* 0x0e */
136 | { db, decode_databyte }, /* 0x0f */
137 | { adc, decode_br8 }, /* 0x10 */
138 | { adc, decode_wr16 }, /* 0x11 */
139 | { adc, decode_r8b }, /* 0x12 */
140 | { adc, decode_r16w }, /* 0x13 */
141 | { adc, decode_ald8 }, /* 0x14 */
142 | { adc, decode_axd16 }, /* 0x15 */
143 | { push,decode_pushpopseg }, /* 0x16 */
144 | { pop, decode_pushpopseg }, /* 0x17 */
145 | { sbb, decode_br8 }, /* 0x18 */
146 | { sbb, decode_wr16 }, /* 0x19 */
147 | { sbb, decode_r8b }, /* 0x1a */
148 | { sbb, decode_r16w }, /* 0x1b */
149 | { sbb, decode_ald8 }, /* 0x1c */
150 | { sbb, decode_axd16 }, /* 0x1d */
151 | { push,decode_pushpopseg }, /* 0x1e */
152 | { pop, decode_pushpopseg }, /* 0x1f */
153 | { and, decode_br8 }, /* 0x20 */
154 | { and, decode_wr16 }, /* 0x21 */
155 | { and, decode_r8b }, /* 0x22 */
156 | { and, decode_r16w }, /* 0x23 */
157 | { and, decode_ald8 }, /* 0x24 */
158 | { and, decode_axd16 }, /* 0x25 */
159 | { es, NULL, DF_PREFIX }, /* 0x26 */
160 | { daa }, /* 0x27 */
161 | { sub, decode_br8 }, /* 0x28 */
162 | { sub, decode_wr16 }, /* 0x29 */
163 | { sub, decode_r8b }, /* 0x2a */
164 | { sub, decode_r16w }, /* 0x2b */
165 | { sub, decode_ald8 }, /* 0x2c */
166 | { sub, decode_axd16 }, /* 0x2d */
167 | { cs, NULL, DF_PREFIX }, /* 0x2e */
168 | { das }, /* 0x2f */
169 | { xor, decode_br8 }, /* 0x30 */
170 | { xor, decode_wr16 }, /* 0x31 */
171 | { xor, decode_r8b }, /* 0x32 */
172 | { xor, decode_r16w }, /* 0x33 */
173 | { xor, decode_ald8 }, /* 0x34 */
174 | { xor, decode_axd16 }, /* 0x35 */
175 | { ss, NULL, DF_PREFIX }, /* 0x36 */
176 | { aaa }, /* 0x37 */
177 | { cmp, decode_br8 }, /* 0x38 */
178 | { cmp, decode_wr16 }, /* 0x39 */
179 | { cmp, decode_r8b }, /* 0x3a */
180 | { cmp, decode_r16w }, /* 0x3b */
181 | { cmp, decode_ald8 }, /* 0x3c */
182 | { cmp, decode_axd16 }, /* 0x3d */
183 | { ds, NULL, DF_PREFIX }, /* 0x3e */
184 | { aas }, /* 0x3f */
185 | { inc, decode_wordreg }, /* 0x40 */
186 | { inc, decode_wordreg }, /* 0x41 */
187 | { inc, decode_wordreg }, /* 0x42 */
188 | { inc, decode_wordreg }, /* 0x43 */
189 | { inc, decode_wordreg }, /* 0x44 */
190 | { inc, decode_wordreg }, /* 0x45 */
191 | { inc, decode_wordreg }, /* 0x46 */
192 | { inc, decode_wordreg }, /* 0x47 */
193 | { dec, decode_wordreg }, /* 0x48 */
194 | { dec, decode_wordreg }, /* 0x49 */
195 | { dec, decode_wordreg }, /* 0x4a */
196 | { dec, decode_wordreg }, /* 0x4b */
197 | { dec, decode_wordreg }, /* 0x4c */
198 | { dec, decode_wordreg }, /* 0x4d */
199 | { dec, decode_wordreg }, /* 0x4e */
200 | { dec, decode_wordreg }, /* 0x4f */
201 | { push,decode_wordreg }, /* 0x50 */
202 | { push,decode_wordreg }, /* 0x51 */
203 | { push,decode_wordreg }, /* 0x52 */
204 | { push,decode_wordreg }, /* 0x53 */
205 | { push,decode_wordreg }, /* 0x54 */
206 | { push,decode_wordreg }, /* 0x55 */
207 | { push,decode_wordreg }, /* 0x56 */
208 | { push,decode_wordreg }, /* 0x57 */
209 | { pop, decode_wordreg }, /* 0x58 */
210 | { pop, decode_wordreg }, /* 0x59 */
211 | { pop, decode_wordreg }, /* 0x5a */
212 | { pop, decode_wordreg }, /* 0x5b */
213 | { pop, decode_wordreg }, /* 0x5c */
214 | { pop, decode_wordreg }, /* 0x5d */
215 | { pop, decode_wordreg }, /* 0x5e */
216 | { pop, decode_wordreg }, /* 0x5f */
217 | { db, decode_databyte }, /* 0x60 */
218 | { db, decode_databyte }, /* 0x61 */
219 | { db, decode_databyte }, /* 0x62 */
220 | { db, decode_databyte }, /* 0x63 */
221 | { db, decode_databyte }, /* 0x64 */
222 | { db, decode_databyte }, /* 0x65 */
223 | { db, decode_databyte }, /* 0x66 */
224 | { db, decode_databyte }, /* 0x67 */
225 | { db, decode_databyte }, /* 0x68 */
226 | { db, decode_databyte }, /* 0x69 */
227 | { db, decode_databyte }, /* 0x6a */
228 | { db, decode_databyte }, /* 0x6b */
229 | { db, decode_databyte }, /* 0x6c */
230 | { db, decode_databyte }, /* 0x6d */
231 | { db, decode_databyte }, /* 0x6e */
232 | { db, decode_databyte }, /* 0x6f */
233 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x70 */
234 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x71 */
235 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x72 */
236 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x73 */
237 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x74 */
238 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x75 */
239 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x76 */
240 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x77 */
241 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x78 */
242 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x79 */
243 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x7a */
244 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x7b */
245 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x7c */
246 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x7d */
247 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x7e */
248 | { jump,decode_cond_jump, DF_NOSPACE }, /* 0x7f */
249 | { none,decode_bd8, 0, table_8x }, /* 0x80 */
250 | { none,decode_wd16,0, table_8x }, /* 0x81 */
251 | { db, decode_databyte }, /* 0x82 */
252 | { none,decode_wd8, 0, table_8x }, /* 0x83 */
253 | { test,decode_br8 }, /* 0x84 */
254 | { test,decode_wr16 }, /* 0x85 */
255 | { xchg,decode_br8 }, /* 0x86 */
256 | { xchg,decode_wr16 }, /* 0x87 */
257 | { mov, decode_br8 }, /* 0x88 */
258 | { mov, decode_wr16 }, /* 0x89 */
259 | { mov, decode_r8b }, /* 0x8a */
260 | { mov, decode_r16w }, /* 0x8b */
261 | { mov, decode_ws }, /* 0x8c */
262 | { lea, decode_r16w }, /* 0x8d */
263 | { mov, decode_sw }, /* 0x8e */
264 | { pop, decode_w }, /* 0x8f */
265 | { nop }, /* 0x90 */
266 | { xchg,decode_xchgax }, /* 0x91 */
267 | { xchg,decode_xchgax }, /* 0x92 */
268 | { xchg,decode_xchgax }, /* 0x93 */
269 | { xchg,decode_xchgax }, /* 0x94 */
270 | { xchg,decode_xchgax }, /* 0x95 */
271 | { xchg,decode_xchgax }, /* 0x96 */
272 | { xchg,decode_xchgax }, /* 0x97 */
273 | { cbw }, /* 0x98 */
274 | { cwd }, /* 0x99 */
275 | { call,decode_far }, /* 0x9a */
276 | { wait }, /* 0x9b */
277 | { pushf }, /* 0x9c */
278 | { popf }, /* 0x9d */
279 | { sahf }, /* 0x9e */
280 | { lahf }, /* 0x9f */
281 | { mov, decode_almem }, /* 0xa0 */
282 | { mov, decode_axmem }, /* 0xa1 */
283 | { mov, decode_memal }, /* 0xa2 */
284 | { mov, decode_memax }, /* 0xa3 */
285 | { movs,decode_string, DF_NOSPACE }, /* 0xa4 */
286 | { movs,decode_string, DF_NOSPACE }, /* 0xa5 */
287 | { cmps,decode_string, DF_NOSPACE }, /* 0xa6 */
288 | { cmps,decode_string, DF_NOSPACE }, /* 0xa7 */
289 | { test,decode_ald8, }, /* 0xa8 */
290 | { test,decode_axd16 }, /* 0xa9 */
291 | { stos,decode_string, DF_NOSPACE }, /* 0xaa */
292 | { stos,decode_string, DF_NOSPACE }, /* 0xab */
293 | { lods,decode_string, DF_NOSPACE }, /* 0xac */
294 | { lods,decode_string, DF_NOSPACE }, /* 0xad */
295 | { scas,decode_string, DF_NOSPACE }, /* 0xae */
296 | { scas,decode_string, DF_NOSPACE }, /* 0xaf */
297 | { mov, decode_rd }, /* 0xb0 */
298 | { mov, decode_rd }, /* 0xb1 */
299 | { mov, decode_rd }, /* 0xb2 */
300 | { mov, decode_rd }, /* 0xb3 */
301 | { mov, decode_rd }, /* 0xb4 */
302 | { mov, decode_rd }, /* 0xb5 */
303 | { mov, decode_rd }, /* 0xb6 */
304 | { mov, decode_rd }, /* 0xb7 */
305 | { mov, decode_rd }, /* 0xb8 */
306 | { mov, decode_rd }, /* 0xb9 */
307 | { mov, decode_rd }, /* 0xba */
308 | { mov, decode_rd }, /* 0xbb */
309 | { mov, decode_rd }, /* 0xbc */
310 | { mov, decode_rd }, /* 0xbd */
311 | { mov, decode_rd }, /* 0xbe */
312 | { mov, decode_rd }, /* 0xbf */
313 | { none,decode_bd8, 0, table_cx }, /* 0xc0 */
314 | { none,decode_wd8, 0, table_cx }, /* 0xc1 */
315 | { ret, decode_d16 }, /* 0xc2 */
316 | { ret }, /* 0xc3 */
317 | { les, decode_r16w }, /* 0xc4 */
318 | { lds, decode_r16w }, /* 0xc5 */
319 | { mov, decode_bd8 }, /* 0xc6 */
320 | { mov, decode_wd16 }, /* 0xc7 */
321 | { db, decode_databyte }, /* 0xc8 */
322 | { db, decode_databyte }, /* 0xc9 */
323 | { retf,decode_d16 }, /* 0xca */
324 | { retf }, /* 0xcb */
325 | { intr,decode_int3 }, /* 0xcc */
326 | { intr,decode_d8 }, /* 0xcd */
327 | { into }, /* 0xce */
328 | { iret }, /* 0xcf */
329 | { none,decode_bbit1, 0, table_dx }, /* 0xd0 */
330 | { none,decode_wbit1, 0, table_dx }, /* 0xd1 */
331 | { none,decode_bbitcl, 0, table_dx }, /* 0xd2 */
332 | { none,decode_wbitcl, 0, table_dx }, /* 0xd3 */
333 | { aam, decode_adjust }, /* 0xd4 */
334 | { aad, decode_adjust }, /* 0xd5 */
335 | { db, decode_databyte }, /* 0xd6 */
336 | { xlat }, /* 0xd7 */
337 | { esc, decode_escape }, /* 0xd8 */
338 | { esc, decode_escape }, /* 0xd9 */
339 | { esc, decode_escape }, /* 0xda */
340 | { esc, decode_escape }, /* 0xdb */
341 | { esc, decode_escape }, /* 0xdc */
342 | { esc, decode_escape }, /* 0xdd */
343 | { esc, decode_escape }, /* 0xde */
344 | { esc, decode_escape }, /* 0xdf */
345 | { loopne,decode_disp }, /* 0xe0 */
346 | { loope,decode_disp }, /* 0xe1 */
347 | { loop,decode_disp }, /* 0xe2 */
348 | { jcxz,decode_disp }, /* 0xe3 */
349 | { in, decode_ald8 }, /* 0xe4 */
350 | { in, decode_axd8 }, /* 0xe5 */
351 | { out, decode_d8al }, /* 0xe6 */
352 | { out, decode_d8ax }, /* 0xe7 */
353 | { call,decode_disp16 }, /* 0xe8 */
354 | { jmp, decode_disp16 }, /* 0xe9 */
355 | { jmp, decode_far }, /* 0xea */
356 | { jmp, decode_disp }, /* 0xeb */
357 | { in, decode_portdx }, /* 0xec */
358 | { in, decode_portdx }, /* 0xed */
359 | { out, decode_portdx }, /* 0xee */
360 | { out, decode_portdx }, /* 0xef */
361 | { lock,NULL, DF_PREFIX }, /* 0xf0 */
362 | { none,decode_bioscall, DF_NOSPACE }, /* 0xf1 */
363 | { repnz,NULL, DF_PREFIX }, /* 0xf2 */
364 | { repz,NULL, DF_PREFIX }, /* 0xf3 */
365 | { hlt }, /* 0xf4 */
366 | { cmc }, /* 0xf5 */
367 | { none,decode_f6, 0, table_f67 }, /* 0xf6 */
368 | { none,decode_f7, 0, table_f67 }, /* 0xf7 */
369 | { clc }, /* 0xf8 */
370 | { stc }, /* 0xf9 */
371 | { cli }, /* 0xfa */
372 | { sti }, /* 0xfb */
373 | { cld }, /* 0xfc */
374 | { std }, /* 0xfd */
375 | { none,decode_b, 0, table_fe }, /* 0xfe */
376 | { none,decode_ff,0, table_ff }, /* 0xff */
377 | };
378 |
379 | #endif
380 | #endif
381 |
--------------------------------------------------------------------------------
/dot.pcemurc:
--------------------------------------------------------------------------------
1 | # This is .pcemurc
2 | # At present only the following commands are recognised:
3 | # bootfile diskfile
4 | # boottype n (where n=360, 720, 144 or 12)
5 | # cursorspeed n
6 | # updatespeed n
7 | #
8 | # The following are the defaults (unless changed at compile time)
9 |
10 | # Note: see new.pcemurc. These options no longer work (25/1/01)
11 | bootfile DriveA
12 | boottype 144
13 | cursorspeed 30
14 | updatespeed 5
15 |
--------------------------------------------------------------------------------
/ems.c:
--------------------------------------------------------------------------------
1 | /* ems.c- Adds LIM-EMS 3.2 to the PC emulator
2 | Copyright 1994, Eric Korpela
3 | Permission is given to copy, modify and distribute this code
4 | provided that this copyright notice is not modified.
5 |
6 | BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
7 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
8 | WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
9 | PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND,
10 | EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
11 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
13 | PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
14 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
15 |
16 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
17 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
18 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
19 | DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
20 | DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
21 | (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
22 | INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
23 | THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
24 | OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
25 | */
26 | /* bug reports to */
27 | #include "global.h"
28 |
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #include "cpu.h"
38 | #include "vga.h"
39 | #include "bios.h"
40 | #include "debugger.h"
41 | #include "vgahard.h"
42 | #include "hardware.h"
43 |
44 | #define BIOS
45 | #define Total_EMS_Pages 1024
46 | #define Total_EMS_Handles 255
47 | #ifndef PAGEFRAME
48 | #define PAGEFRAME 0xe000
49 | #endif
50 |
51 |
52 | unsigned Unallocated_Pages, Free_EMS_Handles,
53 | Allocated_Pages[Total_EMS_Handles+1],
54 | EMS_Context_Pages[4], EMS_Context_Handles[4],
55 | Mapping_Context_Pages[Total_EMS_Handles+1][4],
56 | Mapping_Context_Handles[Total_EMS_Handles+1][4];
57 |
58 | BYTE Handle_Flag[Total_EMS_Handles+1];
59 |
60 | BYTE *EMS_Pointer[Total_EMS_Handles+1];
61 |
62 | void EMS_Setup(void)
63 | {
64 | unsigned tmp,tmp2;
65 | D(printf("In EMS setup\n"););
66 | Unallocated_Pages=Total_EMS_Pages;
67 | for (tmp=0;tmp<=Total_EMS_Handles;tmp++)
68 | {
69 | /* Added the =0. Was just for(tmp2;tmp2... Accident? dtrg */
70 | for (tmp2=0;tmp2<4;tmp2++)
71 | {
72 | Mapping_Context_Pages[tmp][tmp2]=0;
73 | Mapping_Context_Handles[tmp][tmp2]=0;
74 | }
75 | Handle_Flag[tmp]=0;
76 | Allocated_Pages[tmp]=0;
77 | Free_EMS_Handles=Total_EMS_Handles;
78 | }
79 | EMS_Pointer[0]=(BYTE *)malloc(0x04000*4);
80 | Allocated_Pages[0]=4;
81 | Handle_Flag[0]=1;
82 | }
83 |
84 | void EMS_Map(unsigned handle, unsigned logical_page, unsigned physical_page)
85 | {
86 | unsigned tmp,tmp1;
87 | BYTE *ptr0,*ptr1,*ptr2;
88 | D(printf("Mapping EMS handle=%04X, logical_page=%04X, physical_page=%1X\n"
89 | ,handle,logical_page,physical_page););
90 | if ((Allocated_Pages[handle]>logical_page) || (handle==0))
91 | {
92 | ptr0=&memory[(PAGEFRAME << 4) + physical_page * 0x04000 ];
93 | D(printf("Mapping Page to 0x%05X\n",(PAGEFRAME << 4) + physical_page * 0x04000););
94 | ptr2=EMS_Pointer[handle]+logical_page*0x04000;
95 | if ((EMS_Context_Handles[physical_page]!=0)&&((EMS_Context_Handles[physical_page]!=handle)||(EMS_Context_Pages[physical_page]!=logical_page)))
96 | {
97 | ptr1=EMS_Pointer[EMS_Context_Handles[physical_page]]
98 | +EMS_Context_Pages[physical_page]*0x04000;
99 | memcpy(ptr1,ptr0,0x04000);
100 | D(printf("EMS ptr0(0x%08X) ---> ptr1(0x%08X)\n",ptr0,ptr1););
101 | }
102 | if ((EMS_Context_Handles[physical_page]!=handle)||(EMS_Context_Pages[physical_page]!=logical_page))
103 | {
104 | D(printf("EMS ptr2(0x%08X) ---> ptr0(0x%08X)\n",ptr2,ptr0););
105 | memcpy(ptr0,ptr2,0x04000);
106 | }
107 | *bregs[AH]=0x00;
108 | } else *bregs[AH]=0x8A;
109 | EMS_Context_Handles[physical_page]=handle;
110 | EMS_Context_Pages[physical_page]=logical_page;
111 | tmp1=0;
112 | for (tmp=0;tmp<4;tmp++)
113 | if ((EMS_Context_Handles[tmp]==handle)
114 | &&(EMS_Context_Pages[tmp]==logical_page)&&(handle!=0)) tmp1++;
115 | if ((tmp1!=1)&&(handle!=0))
116 | printf("WARNING--Multiply mapped page: Handle 0x%02X, Page 0x%04X\n",handle,logical_page);
117 | }
118 |
119 | void int_ems(void)
120 | {
121 | unsigned tmp,tmp2,tmp3;
122 | D(printf("In INT 0x67 (EMS) AH = 0x%02X AL = 0x%02X\n",*bregs[AH],*bregs[AL]););
123 | CalcAll();
124 | switch(*bregs[AH])
125 | {
126 | case 0x40: *bregs[AH] = 0;
127 | break;
128 | case 0x41: wregs[BX] = ChangeE(PAGEFRAME);
129 | *bregs[AH] = 0x00;
130 | break;
131 | case 0x42: *bregs[AH] = 0x00;
132 | wregs[BX] = ChangeE((WORD)Unallocated_Pages);
133 | wregs[DX] = ChangeE((WORD)Total_EMS_Pages);
134 | break;
135 | case 0x43: tmp=ChangeE(wregs[BX]);
136 | if (tmp>Total_EMS_Pages) {*bregs[AH]=0x87;break;}
137 | if (tmp>Unallocated_Pages) {*bregs[AH]=0x88;break;}
138 | if (tmp==0) {*bregs[AH]=0x89;break;}
139 | if (Free_EMS_Handles==0) {*bregs[AH]=0x85;break;}
140 | for (tmp2=1;tmp23) {*bregs[AH]=0x8B;break;}
155 | EMS_Map(tmp,tmp2,tmp3);
156 | break;
157 | case 0x45: tmp=ChangeE(wregs[DX]);
158 | if (tmp==0)
159 | {
160 | printf("Warning--Attempt to unallocate handle 0x00\n");
161 | *bregs[AH]=0x83;
162 | }
163 | Handle_Flag[tmp]=0;
164 | Unallocated_Pages+=Allocated_Pages[tmp];
165 | Allocated_Pages[tmp]=0;
166 | free(EMS_Pointer[tmp]);
167 | Free_EMS_Handles++;
168 | *bregs[AH]=0x00;
169 | break;
170 | case 0x46: *bregs[AH]=0x00;
171 | *bregs[AL]=0x32;
172 | break;
173 | case 0x47: tmp=ChangeE(wregs[DX]);
174 | for (tmp2=0;tmp2<4;tmp2++)
175 | {
176 | Mapping_Context_Pages[tmp][tmp2]=EMS_Context_Pages[tmp2];
177 | Mapping_Context_Handles[tmp][tmp2]=EMS_Context_Handles[tmp2];
178 | }
179 | *bregs[AH]=0x00;
180 | break;
181 | case 0x48: tmp=ChangeE(wregs[DX]);
182 | for (tmp2=0;tmp2<4;tmp2++)
183 | {
184 | EMS_Map(Mapping_Context_Handles[tmp][tmp2],
185 | Mapping_Context_Pages[tmp][tmp2],tmp2);
186 | }
187 | *bregs[AH]=0x00;
188 | break;
189 | case 0x4b: wregs[BX]=ChangeE(Total_EMS_Handles-Free_EMS_Handles);
190 | *bregs[AH]=0x00;
191 | break;
192 | case 0x4c: tmp=ChangeE(wregs[DX]);
193 | wregs[BX]=ChangeE(Allocated_Pages[tmp]);
194 | *bregs[AH]=0x00;
195 | break;
196 | case 0x4d: tmp=Total_EMS_Handles-Free_EMS_Handles;
197 | tmp3=0;
198 | for (tmp2=1;tmp2 hardware.o mfs.o ems.o
5 | 79a80,84
6 | > ems.o: $(GLOBAL_DEP) cpu.h bios.h
7 | > cpu.s: $(GLOBAL_DEP) cpu.h instr.h debugger.h hardware.h
8 | >
9 | > .c.s:
10 | > $(CC) $(CFLAGS) $(OPTIONS) -S $<
11 |
--------------------------------------------------------------------------------
/ems/bios.c.patch:
--------------------------------------------------------------------------------
1 | 12a13
2 | > * Modifications for EMS, Copyright 1994, Eric Korpela *
3 | 40a42
4 | >
5 | 1117d1118
6 | <
7 | 1120a1122
8 | > EMS_Setup();
9 | 1176c1178
10 | <
11 | ---
12 | > set_int(0x4b, NULL, 0, int_67, afterint, sizeof afterint);
13 |
--------------------------------------------------------------------------------
/ems/bios.h.patch:
--------------------------------------------------------------------------------
1 | 12a13,14
2 | > * Modifications for EMS 3.2 Copyright 1994, Eric Korpela *
3 | > * *
4 | 29c31,32
5 | <
6 | ---
7 | > void int_67(void);
8 | > void EMS_Setup(void);
9 |
--------------------------------------------------------------------------------
/ems/ems.doc:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP SIGNED MESSAGE-----
2 |
3 | Installation of the EMS driver....
4 |
5 | Copy the files ems.c, patch.script and *.patch into the pcemu source
6 | directory. Execute the patch.script file. If you don't have "patch" on
7 | your machine you'll have to edit the source files manually. Remake the
8 | 'pcemu' executable.
9 |
10 | Copy the 'EKEMM.SYS' file to your boot drive/file. and add a line to
11 | your config.sys 'DEVICE=EKEMM.SYS'
12 |
13 | That's all there is to it. Report any problems to me.
14 | (korpela@ssl.berkeley.edu)
15 |
16 | There is no warantee expressed or implied in this software. Use at your own
17 | risk. See the files COPYRIGHT and ems.c for details.
18 |
19 | -----BEGIN PGP SIGNATURE-----
20 | Version: 2.6
21 |
22 | iQCVAgUBLj6fC+BZ/OT/DJLdAQHBCAP+IfVDyFHzI8qaQB1QeqXRVxjyMo9zWzje
23 | QXzyk3SU40oE/GfRdQm8YBotvY5IkH2gbHIkxDOzxRuErlihVqARBJVW1sRPiJWz
24 | PGQ1k2CRfUPKbwGegyjTmYXNaUx1CCmGMgA5doxOJU61Xfa5Z3vMYLHRFd3HXag4
25 | CxFtntwo6rM=
26 | =agEc
27 | -----END PGP SIGNATURE-----
28 |
--------------------------------------------------------------------------------
/ems/patch.script:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | patch Makefile
26 | #include
27 |
28 | #ifdef ME
29 | # include "uprotos.h"
30 | #endif
31 |
32 | #ifndef FALSE
33 | # define FALSE 0
34 | #endif
35 | #ifndef TRUE
36 | # define TRUE (!FALSE)
37 | #endif
38 |
39 | #define MEMORY_SIZE (1024*1024+65536)
40 |
41 | #ifdef INLINE_FUNCTIONS
42 | # define INLINE inline
43 | # define INLINE2 inline
44 | #else
45 | # define INLINE
46 | # define INLINE2
47 | #endif
48 |
49 | #ifdef DEBUG
50 | # define D(x) x
51 | #else
52 | # define D(x)
53 | #endif
54 |
55 | #ifdef DEBUG2
56 | # define D2(x) x
57 | #else
58 | # define D2(x)
59 | #endif
60 |
61 | #ifdef _HPUX_SOURCE
62 | #ifndef __hpux
63 | #define __hpux
64 | #endif
65 | #endif
66 |
67 | extern BYTE *memory;
68 | extern char *progname;
69 |
70 | void init_cpu(void);
71 | void execute(void);
72 | void exit_emu(void);
73 | void read_pcemurc(void);
74 |
75 | #endif
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/hardware.c:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is HARDWARE.C It contains stuff about the PC hardware (chips etc) */
16 |
17 | #include "global.h"
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include "hardware.h"
24 | #include "cpu.h"
25 | #include "vgahard.h"
26 |
27 | #ifdef DEBUGGER
28 | # include "debugger.h"
29 | #endif
30 |
31 | static struct itimerval timer;
32 |
33 | static volatile int disable_int;
34 | static volatile int timer_blocked = 1;
35 |
36 | #define PORT60SIZE 5
37 |
38 | static BYTE port60buffer[PORT60SIZE];
39 | static int port60start, port60end;
40 |
41 | static unsigned PIC_inservice;
42 | static unsigned PIC_irq;
43 | static unsigned PIC_mask = ~(PIC_TIMER|PIC_KEYBOARD);
44 |
45 | static unsigned timer_tmp;
46 |
47 | static unsigned VGA_status;
48 |
49 | static void PIC_interrupt(void)
50 | {
51 | if (PIC_inservice)
52 | {
53 | D2(printf("PIC still blocked\n"););
54 | return;
55 | }
56 |
57 | if (PIC_irq & ~PIC_mask & PIC_TIMER)
58 | {
59 | D2(printf("INTR: timer\n"););
60 | PIC_inservice = PIC_TIMER;
61 | PIC_irq &= ~PIC_TIMER;
62 | if (IF)
63 | int_pending = 8;
64 | else
65 | {
66 | D2(printf("INTR blocked: IF disabled\n"););
67 | int_blocked = 8;
68 | }
69 | }
70 | else if (PIC_irq & ~PIC_mask & PIC_KEYBOARD)
71 | {
72 | D2(printf("INTR: keyboard\n"););
73 | PIC_inservice = PIC_KEYBOARD;
74 | PIC_irq &= ~PIC_KEYBOARD;
75 | if (IF)
76 | int_pending = 9;
77 | else
78 | {
79 | D2(printf("INTR blocked: IF disabled\n"););
80 | int_blocked = 9;
81 | }
82 | }
83 | }
84 |
85 |
86 | static void PIC_flagint(unsigned interrupt)
87 | {
88 | disable();
89 | D2(printf("IRQ %02X\n", interrupt););
90 | PIC_irq |= interrupt;
91 | enable();
92 | }
93 |
94 |
95 | void PIC_EOI(void)
96 | {
97 | disable();
98 |
99 | if (PIC_inservice & PIC_KEYBOARD)
100 | {
101 | if (++port60start >= PORT60SIZE)
102 | port60start = 0;
103 |
104 | if (port60start != port60end)
105 | PIC_irq |= PIC_KEYBOARD;
106 | }
107 |
108 |
109 | PIC_inservice = 0;
110 | PIC_interrupt();
111 | enable();
112 | }
113 |
114 |
115 | int port60_buffer_ok(int count)
116 | {
117 | int tmp = port60end;
118 |
119 | for (; count > 0; count--)
120 | {
121 | if (++tmp >= PORT60SIZE)
122 | tmp = 0;
123 |
124 | if (tmp == port60start)
125 | return FALSE;
126 | }
127 |
128 | return TRUE;
129 | }
130 |
131 |
132 | void put_scancode(BYTE *code, int count)
133 | {
134 | for (; count > 0; count--)
135 | {
136 | port60buffer[port60end] = *code++;
137 |
138 | if (++port60end >= PORT60SIZE)
139 | port60end = 0;
140 | }
141 |
142 | PIC_flagint(PIC_KEYBOARD);
143 |
144 | D2(
145 | {
146 | int tmp;
147 |
148 | printf("INT9 signalled\n");
149 | printf("Port60 buffer: ");
150 |
151 | tmp = port60start;
152 | while (tmp != port60end)
153 | {
154 | printf("%02X ", port60buffer[tmp]);
155 | if (++tmp >= PORT60SIZE)
156 | tmp = 0;
157 | }
158 | printf("\n");
159 | }
160 | )
161 | }
162 |
163 |
164 | static BYTE read_port60(void)
165 | {
166 | BYTE ret;
167 | static BYTE lastread = 0;
168 |
169 | disable();
170 |
171 | if (port60start == port60end)
172 | ret = lastread;
173 | else
174 | lastread = ret = port60buffer[port60start];
175 |
176 | enable();
177 |
178 | return ret;
179 | }
180 |
181 | #define TIMER_MULT 4
182 |
183 | static volatile int int8_counter = TIMER_MULT;
184 |
185 | static int timer_handler(int sig)
186 | {
187 |
188 | #ifdef DEBUGGER
189 | if (in_debug)
190 | return 0;
191 | #endif
192 |
193 | if (disable_int)
194 | {
195 | D2(printf("Timer called when disabled\n"););
196 | timer_blocked++;
197 | return 0;
198 | }
199 |
200 | disable();
201 |
202 | vga_interrupt();
203 |
204 | timer_tmp++;
205 |
206 | if (--int8_counter == 0)
207 | {
208 | PIC_flagint(PIC_TIMER);
209 | int8_counter = TIMER_MULT;
210 | }
211 |
212 | PIC_interrupt();
213 |
214 | enable();
215 | return 0;
216 | }
217 |
218 |
219 | #ifndef SA_RESTART
220 | #define SA_RESTART 0
221 | #endif
222 |
223 | void init_timer(void)
224 | {
225 | struct sigaction sa;
226 |
227 | sa.sa_handler = (void *)timer_handler;
228 | sa.sa_flags = SA_RESTART;
229 | sigemptyset(&sa.sa_mask);
230 |
231 | sigaction(SIGALRM, &sa, NULL);
232 |
233 | timer.it_interval.tv_sec = timer.it_value.tv_sec = 0;
234 | timer.it_interval.tv_usec = timer.it_value.tv_usec =
235 | (long)(1000000.0 /((float)TIMER_MULT*TICKSPERSEC));
236 |
237 | D2(printf("Set timer to %ld microseconds\n", timer.it_interval.tv_usec););
238 | setitimer(ITIMER_REAL, &timer, NULL);
239 | }
240 |
241 |
242 | void stoptimer(void)
243 | {
244 | timer.it_interval.tv_sec = timer.it_value.tv_sec =
245 | timer.it_interval.tv_usec = timer.it_value.tv_usec = 0;
246 | setitimer(ITIMER_REAL, &timer, NULL);
247 | signal(SIGALRM, SIG_IGN);
248 | }
249 |
250 |
251 | void starttimer(void)
252 | {
253 | init_timer();
254 | }
255 |
256 |
257 | void disable(void)
258 | {
259 | if (disable_int == 0)
260 | timer_blocked = 0;
261 | disable_int++;
262 | }
263 |
264 |
265 | void enable(void)
266 | {
267 | if (disable_int > 0)
268 | disable_int--;
269 |
270 | if (disable_int == 0)
271 | while (timer_blocked > 0)
272 | {
273 | timer_blocked--;
274 | timer_handler(SIGALRM);
275 | }
276 | }
277 |
278 |
279 | static int PIT_toggle = 1;
280 |
281 | BYTE read_port(unsigned port)
282 | {
283 | BYTE val;
284 | static unsigned timer_tmp;
285 |
286 | switch(port)
287 | {
288 | case 0x21:
289 | val = PIC_mask;
290 | break;
291 | case 0x40:
292 | case 0x41:
293 | case 0x42:
294 | disable();
295 | if ((PIT_toggle = !PIT_toggle) == 0)
296 | val = timer_tmp & 0xff;
297 | else
298 | {
299 | val = (timer_tmp & 0xff00) >> 8;
300 | timer_tmp++;
301 | }
302 | enable();
303 | break;
304 | case 0x60:
305 | val = read_port60();
306 | break;
307 | case 0x61:
308 | val = 0xd0;
309 | break;
310 | case 0x3da:
311 | val = VGA_status;
312 | VGA_status ^= 0x9;
313 | break;
314 | case 0x2fd:
315 | val = 0xff;
316 | break;
317 | default:
318 | val = 0;
319 | break;
320 | }
321 |
322 | D(printf("Reading 0x%02X from port 0x%04X\n", val, port););
323 | return val;
324 | }
325 |
326 |
327 | void write_port(unsigned port, BYTE value)
328 | {
329 | switch(port)
330 | {
331 | case 0x20:
332 | if (value == 0x20)
333 | {
334 | PIC_EOI();
335 | return;
336 | }
337 | break;
338 | case 0x21:
339 | disable();
340 | PIC_mask = value;
341 | enable();
342 | break;
343 | case 0x43:
344 | PIT_toggle = 1;
345 | break;
346 | default:
347 | break;
348 | }
349 | D(printf("Writing 0x%02X to port 0x%04X\n", value, port););
350 |
351 | }
352 |
353 |
354 |
--------------------------------------------------------------------------------
/hardware.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | #ifndef HARDWARE_H
16 | #define HARDWARE_H
17 |
18 | #include "mytypes.h"
19 |
20 | #define PIC_TIMER 1
21 | #define PIC_KEYBOARD 2
22 |
23 | #define TICKSPERSEC (1193180.0/65536.0)
24 |
25 | int port60_buffer_ok(int);
26 | void put_scancode(BYTE *, int);
27 | void init_timer(void);
28 |
29 | void disable(void);
30 | void enable(void);
31 |
32 | void starttimer(void);
33 | void stoptimer(void);
34 |
35 | BYTE read_port(unsigned);
36 | void write_port(unsigned, BYTE);
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/icon.h:
--------------------------------------------------------------------------------
1 | #define icon_width 40
2 | #define icon_height 40
3 | static char icon_bits[] = {
4 | 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0xfe, 0x07,
5 | 0x00, 0x00, 0x00, 0x8e, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x1f, 0x00, 0x00,
6 | 0x00, 0x0e, 0x3c, 0x00, 0x00, 0x00, 0x0e, 0x78, 0x00, 0x00, 0x00, 0x0e,
7 | 0x78, 0x00, 0x00, 0x00, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x0e, 0xe0, 0x00,
8 | 0x00, 0x00, 0x0e, 0xe0, 0x00, 0x00, 0x00, 0x0e, 0xe0, 0x01, 0x00, 0x00,
9 | 0x0e, 0xe0, 0x01, 0x00, 0x00, 0x0e, 0xe0, 0x01, 0x00, 0x00, 0x0e, 0xc0,
10 | 0x03, 0x00, 0x00, 0x0e, 0xe0, 0x01, 0xfc, 0x0f, 0x0e, 0xe0, 0x01, 0xfe,
11 | 0x1f, 0x0e, 0xe0, 0x81, 0xff, 0x1f, 0x0e, 0xe0, 0xc0, 0x0f, 0x18, 0x0e,
12 | 0xe0, 0xe0, 0x03, 0x00, 0x0e, 0xf0, 0xe0, 0x01, 0x00, 0x0e, 0x78, 0xf0,
13 | 0x00, 0x00, 0x0e, 0x78, 0x78, 0x00, 0x00, 0x0e, 0x3c, 0x78, 0x00, 0x00,
14 | 0x0e, 0x1f, 0x38, 0x00, 0x00, 0x8e, 0x0f, 0x38, 0x00, 0x00, 0xfe, 0x07,
15 | 0x38, 0x00, 0x00, 0xfe, 0x03, 0x3c, 0x00, 0x00, 0xfe, 0x00, 0x38, 0x00,
16 | 0x00, 0x1e, 0x00, 0x38, 0x00, 0x00, 0x0e, 0x00, 0x38, 0x00, 0x00, 0x0e,
17 | 0x00, 0x78, 0x00, 0x00, 0x0e, 0x00, 0x78, 0x00, 0x00, 0x0e, 0x00, 0xf0,
18 | 0x00, 0x00, 0x0e, 0x00, 0xe0, 0x01, 0x00, 0x0e, 0x00, 0xe0, 0x03, 0x00,
19 | 0x0e, 0x00, 0xc0, 0x0f, 0x18, 0x0e, 0x00, 0x80, 0xff, 0x1f, 0x0e, 0x00,
20 | 0x00, 0xfe, 0x1f, 0x0e, 0x00, 0x00, 0xfc, 0x0f};
21 |
--------------------------------------------------------------------------------
/instr.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is INSTR.H It contains the functions corresponding to each individual
16 | instruction in the 80x86 set */
17 |
18 | #ifndef INSTR_H
19 | #define INSTR_H
20 |
21 | static INLINE2 void i_add_br8(void);
22 | static INLINE2 void i_add_wr16(void);
23 | static INLINE2 void i_add_r8b(void);
24 | static INLINE2 void i_add_r16w(void);
25 | static INLINE2 void i_add_ald8(void);
26 | static INLINE2 void i_add_axd16(void);
27 | static INLINE2 void i_push_es(void);
28 | static INLINE2 void i_pop_es(void);
29 | static INLINE2 void i_or_br8(void);
30 | static INLINE2 void i_or_r8b(void);
31 | static INLINE2 void i_or_wr16(void);
32 | static INLINE2 void i_or_r16w(void);
33 | static INLINE2 void i_or_ald8(void);
34 | static INLINE2 void i_or_axd16(void);
35 | static INLINE2 void i_push_cs(void);
36 | static INLINE2 void i_adc_br8(void);
37 | static INLINE2 void i_adc_wr16(void);
38 | static INLINE2 void i_adc_r8b(void);
39 | static INLINE2 void i_adc_r16w(void);
40 | static INLINE2 void i_adc_ald8(void);
41 | static INLINE2 void i_adc_axd16(void);
42 | static INLINE2 void i_push_ss(void);
43 | static INLINE2 void i_pop_ss(void);
44 | static INLINE2 void i_sbb_br8(void);
45 | static INLINE2 void i_sbb_wr16(void);
46 | static INLINE2 void i_sbb_r8b(void);
47 | static INLINE2 void i_sbb_r16w(void);
48 | static INLINE2 void i_sbb_ald8(void);
49 | static INLINE2 void i_sbb_axd16(void);
50 | static INLINE2 void i_push_ds(void);
51 | static INLINE2 void i_pop_ds(void);
52 | static INLINE2 void i_and_br8(void);
53 | static INLINE2 void i_and_r8b(void);
54 | static INLINE2 void i_and_wr16(void);
55 | static INLINE2 void i_and_r16w(void);
56 | static INLINE2 void i_and_ald8(void);
57 | static INLINE2 void i_and_axd16(void);
58 | static INLINE2 void i_es(void);
59 | static INLINE2 void i_daa(void);
60 | static INLINE2 void i_sub_br8(void);
61 | static INLINE2 void i_sub_wr16(void);
62 | static INLINE2 void i_sub_r8b(void);
63 | static INLINE2 void i_sub_r16w(void);
64 | static INLINE2 void i_sub_ald8(void);
65 | static INLINE2 void i_sub_axd16(void);
66 | static INLINE2 void i_cs(void);
67 | static INLINE2 void i_xor_br8(void);
68 | static INLINE2 void i_xor_r8b(void);
69 | static INLINE2 void i_xor_wr16(void);
70 | static INLINE2 void i_xor_r16w(void);
71 | static INLINE2 void i_xor_ald8(void);
72 | static INLINE2 void i_xor_axd16(void);
73 | static INLINE2 void i_ss(void);
74 | static INLINE2 void i_cmp_br8(void);
75 | static INLINE2 void i_cmp_wr16(void);
76 | static INLINE2 void i_cmp_r8b(void);
77 | static INLINE2 void i_cmp_r16w(void);
78 | static INLINE2 void i_cmp_ald8(void);
79 | static INLINE2 void i_cmp_axd16(void);
80 | static INLINE2 void i_ds(void);
81 | static INLINE2 void i_inc_ax(void);
82 | static INLINE2 void i_inc_cx(void);
83 | static INLINE2 void i_inc_dx(void);
84 | static INLINE2 void i_inc_bx(void);
85 | static INLINE2 void i_inc_sp(void);
86 | static INLINE2 void i_inc_bp(void);
87 | static INLINE2 void i_inc_si(void);
88 | static INLINE2 void i_inc_di(void);
89 | static INLINE2 void i_dec_ax(void);
90 | static INLINE2 void i_dec_cx(void);
91 | static INLINE2 void i_dec_dx(void);
92 | static INLINE2 void i_dec_bx(void);
93 | static INLINE2 void i_dec_sp(void);
94 | static INLINE2 void i_dec_bp(void);
95 | static INLINE2 void i_dec_si(void);
96 | static INLINE2 void i_dec_di(void);
97 | static INLINE2 void i_push_ax(void);
98 | static INLINE2 void i_push_cx(void);
99 | static INLINE2 void i_push_dx(void);
100 | static INLINE2 void i_push_bx(void);
101 | static INLINE2 void i_push_sp(void);
102 | static INLINE2 void i_push_bp(void);
103 | static INLINE2 void i_push_si(void);
104 | static INLINE2 void i_push_di(void);
105 | static INLINE2 void i_pop_ax(void);
106 | static INLINE2 void i_pop_cx(void);
107 | static INLINE2 void i_pop_dx(void);
108 | static INLINE2 void i_pop_bx(void);
109 | static INLINE2 void i_pop_sp(void);
110 | static INLINE2 void i_pop_bp(void);
111 | static INLINE2 void i_pop_si(void);
112 | static INLINE2 void i_pop_di(void);
113 | static INLINE2 void i_jo(void);
114 | static INLINE2 void i_jno(void);
115 | static INLINE2 void i_jb(void);
116 | static INLINE2 void i_jnb(void);
117 | static INLINE2 void i_jz(void);
118 | static INLINE2 void i_jnz(void);
119 | static INLINE2 void i_jbe(void);
120 | static INLINE2 void i_jnbe(void);
121 | static INLINE2 void i_js(void);
122 | static INLINE2 void i_jns(void);
123 | static INLINE2 void i_jp(void);
124 | static INLINE2 void i_jnp(void);
125 | static INLINE2 void i_jl(void);
126 | static INLINE2 void i_jnl(void);
127 | static INLINE2 void i_jle(void);
128 | static INLINE2 void i_jnle(void);
129 | static INLINE2 void i_80pre(void);
130 | static INLINE2 void i_81pre(void);
131 | static INLINE2 void i_83pre(void);
132 | static INLINE2 void i_test_br8(void);
133 | static INLINE2 void i_test_wr16(void);
134 | static INLINE2 void i_xchg_br8(void);
135 | static INLINE2 void i_xchg_wr16(void);
136 | static INLINE2 void i_mov_br8(void);
137 | static INLINE2 void i_mov_r8b(void);
138 | static INLINE2 void i_mov_wr16(void);
139 | static INLINE2 void i_mov_r16w(void);
140 | static INLINE2 void i_mov_wsreg(void);
141 | static INLINE2 void i_lea(void);
142 | static INLINE2 void i_mov_sregw(void);
143 | static INLINE2 void i_notdone(void);
144 | static INLINE2 void i_popw(void);
145 | static INLINE2 void i_nop(void);
146 | static INLINE2 void i_xchg_axcx(void);
147 | static INLINE2 void i_xchg_axdx(void);
148 | static INLINE2 void i_xchg_axbx(void);
149 | static INLINE2 void i_xchg_axsp(void);
150 | static INLINE2 void i_xchg_axbp(void);
151 | static INLINE2 void i_xchg_axsi(void);
152 | static INLINE2 void i_xchg_axdi(void);
153 | static INLINE2 void i_cbw(void);
154 | static INLINE2 void i_cwd(void);
155 | static INLINE2 void i_call_far(void);
156 | static INLINE2 void i_pushf(void);
157 | static INLINE2 void i_popf(void);
158 | static INLINE2 void i_sahf(void);
159 | static INLINE2 void i_lahf(void);
160 | static INLINE2 void i_mov_aldisp(void);
161 | static INLINE2 void i_mov_axdisp(void);
162 | static INLINE2 void i_mov_dispal(void);
163 | static INLINE2 void i_mov_dispax(void);
164 | static INLINE2 void i_movsb(void);
165 | static INLINE2 void i_movsw(void);
166 | static INLINE2 void i_cmpsb(void);
167 | static INLINE2 void i_cmpsw(void);
168 | static INLINE2 void i_test_ald8(void);
169 | static INLINE2 void i_test_axd16(void);
170 | static INLINE2 void i_stosb(void);
171 | static INLINE2 void i_stosw(void);
172 | static INLINE2 void i_lodsb(void);
173 | static INLINE2 void i_lodsw(void);
174 | static INLINE2 void i_scasb(void);
175 | static INLINE2 void i_scasw(void);
176 | static INLINE2 void i_mov_ald8(void);
177 | static INLINE2 void i_mov_cld8(void);
178 | static INLINE2 void i_mov_dld8(void);
179 | static INLINE2 void i_mov_bld8(void);
180 | static INLINE2 void i_mov_ahd8(void);
181 | static INLINE2 void i_mov_chd8(void);
182 | static INLINE2 void i_mov_dhd8(void);
183 | static INLINE2 void i_mov_bhd8(void);
184 | static INLINE2 void i_mov_axd16(void);
185 | static INLINE2 void i_mov_cxd16(void);
186 | static INLINE2 void i_mov_dxd16(void);
187 | static INLINE2 void i_mov_bxd16(void);
188 | static INLINE2 void i_mov_spd16(void);
189 | static INLINE2 void i_mov_bpd16(void);
190 | static INLINE2 void i_mov_sid16(void);
191 | static INLINE2 void i_mov_did16(void);
192 | static INLINE2 void i_ret_d16(void);
193 | static INLINE2 void i_ret(void);
194 | static INLINE2 void i_les_dw(void);
195 | static INLINE2 void i_lds_dw(void);
196 | static INLINE2 void i_mov_bd8(void);
197 | static INLINE2 void i_mov_wd16(void);
198 | static INLINE2 void i_retf_d16(void);
199 | static INLINE2 void i_retf(void);
200 | static INLINE2 void i_int3(void);
201 | static INLINE2 void i_int(void);
202 | static INLINE2 void i_into(void);
203 | static INLINE2 void i_iret(void);
204 | static INLINE2 void i_d0pre(void);
205 | static INLINE2 void i_d1pre(void);
206 | static INLINE2 void i_d2pre(void);
207 | static INLINE2 void i_d3pre(void);
208 | static INLINE2 void i_aam(void);
209 | static INLINE2 void i_aad(void);
210 | static INLINE2 void i_xlat(void);
211 | static INLINE2 void i_escape(void);
212 | static INLINE2 void i_loopne(void);
213 | static INLINE2 void i_loope(void);
214 | static INLINE2 void i_loop(void);
215 | static INLINE2 void i_jcxz(void);
216 | static INLINE2 void i_inal(void);
217 | static INLINE2 void i_inax(void);
218 | static INLINE2 void i_outal(void);
219 | static INLINE2 void i_outax(void);
220 | static INLINE2 void i_call_d16(void);
221 | static INLINE2 void i_jmp_d16(void);
222 | static INLINE2 void i_jmp_far(void);
223 | static INLINE2 void i_jmp_d8(void);
224 | static INLINE2 void i_inaldx(void);
225 | static INLINE2 void i_inaxdx(void);
226 | static INLINE2 void i_outdxal(void);
227 | static INLINE2 void i_outdxax(void);
228 | static INLINE2 void i_lock(void);
229 | static INLINE2 void i_repne(void);
230 | static INLINE2 void i_repe(void);
231 | static INLINE2 void i_hlt(void);
232 | static INLINE2 void i_cmc(void);
233 | static INLINE2 void i_f6pre(void);
234 | static INLINE2 void i_f7pre(void);
235 | static INLINE2 void i_clc(void);
236 | static INLINE2 void i_stc(void);
237 | static INLINE2 void i_cli(void);
238 | static INLINE2 void i_sti(void);
239 | static INLINE2 void i_cld(void);
240 | static INLINE2 void i_std(void);
241 | static INLINE2 void i_fepre(void);
242 | static INLINE2 void i_ffpre(void);
243 |
244 | static INLINE2 void i_wait(void);
245 | static INLINE2 void i_gobios(void);
246 |
247 | void (*instruction[256])(void) =
248 | {
249 | i_add_br8, /* 0x00 */
250 | i_add_wr16, /* 0x01 */
251 | i_add_r8b, /* 0x02 */
252 | i_add_r16w, /* 0x03 */
253 | i_add_ald8, /* 0x04 */
254 | i_add_axd16, /* 0x05 */
255 | i_push_es, /* 0x06 */
256 | i_pop_es, /* 0x07 */
257 | i_or_br8, /* 0x08 */
258 | i_or_wr16, /* 0x09 */
259 | i_or_r8b, /* 0x0a */
260 | i_or_r16w, /* 0x0b */
261 | i_or_ald8, /* 0x0c */
262 | i_or_axd16, /* 0x0d */
263 | i_push_cs, /* 0x0e */
264 | i_notdone,
265 | i_adc_br8, /* 0x10 */
266 | i_adc_wr16, /* 0x11 */
267 | i_adc_r8b, /* 0x12 */
268 | i_adc_r16w, /* 0x13 */
269 | i_adc_ald8, /* 0x14 */
270 | i_adc_axd16, /* 0x15 */
271 | i_push_ss, /* 0x16 */
272 | i_pop_ss, /* 0x17 */
273 | i_sbb_br8, /* 0x18 */
274 | i_sbb_wr16, /* 0x19 */
275 | i_sbb_r8b, /* 0x1a */
276 | i_sbb_r16w, /* 0x1b */
277 | i_sbb_ald8, /* 0x1c */
278 | i_sbb_axd16, /* 0x1d */
279 | i_push_ds, /* 0x1e */
280 | i_pop_ds, /* 0x1f */
281 | i_and_br8, /* 0x20 */
282 | i_and_wr16, /* 0x21 */
283 | i_and_r8b, /* 0x22 */
284 | i_and_r16w, /* 0x23 */
285 | i_and_ald8, /* 0x24 */
286 | i_and_axd16, /* 0x25 */
287 | i_es, /* 0x26 */
288 | i_daa, /* 0x27 */
289 | i_sub_br8, /* 0x28 */
290 | i_sub_wr16, /* 0x29 */
291 | i_sub_r8b, /* 0x2a */
292 | i_sub_r16w, /* 0x2b */
293 | i_sub_ald8, /* 0x2c */
294 | i_sub_axd16, /* 0x2d */
295 | i_cs, /* 0x2e */
296 | i_notdone,
297 | i_xor_br8, /* 0x30 */
298 | i_xor_wr16, /* 0x31 */
299 | i_xor_r8b, /* 0x32 */
300 | i_xor_r16w, /* 0x33 */
301 | i_xor_ald8, /* 0x34 */
302 | i_xor_axd16, /* 0x35 */
303 | i_ss, /* 0x36 */
304 | i_notdone,
305 | i_cmp_br8, /* 0x38 */
306 | i_cmp_wr16, /* 0x39 */
307 | i_cmp_r8b, /* 0x3a */
308 | i_cmp_r16w, /* 0x3b */
309 | i_cmp_ald8, /* 0x3c */
310 | i_cmp_axd16, /* 0x3d */
311 | i_ds, /* 0x3e */
312 | i_notdone,
313 | i_inc_ax, /* 0x40 */
314 | i_inc_cx, /* 0x41 */
315 | i_inc_dx, /* 0x42 */
316 | i_inc_bx, /* 0x43 */
317 | i_inc_sp, /* 0x44 */
318 | i_inc_bp, /* 0x45 */
319 | i_inc_si, /* 0x46 */
320 | i_inc_di, /* 0x47 */
321 | i_dec_ax, /* 0x48 */
322 | i_dec_cx, /* 0x49 */
323 | i_dec_dx, /* 0x4a */
324 | i_dec_bx, /* 0x4b */
325 | i_dec_sp, /* 0x4c */
326 | i_dec_bp, /* 0x4d */
327 | i_dec_si, /* 0x4e */
328 | i_dec_di, /* 0x4f */
329 | i_push_ax, /* 0x50 */
330 | i_push_cx, /* 0x51 */
331 | i_push_dx, /* 0x52 */
332 | i_push_bx, /* 0x53 */
333 | i_push_sp, /* 0x54 */
334 | i_push_bp, /* 0x55 */
335 | i_push_si, /* 0x56 */
336 | i_push_di, /* 0x57 */
337 | i_pop_ax, /* 0x58 */
338 | i_pop_cx, /* 0x59 */
339 | i_pop_dx, /* 0x5a */
340 | i_pop_bx, /* 0x5b */
341 | i_pop_sp, /* 0x5c */
342 | i_pop_bp, /* 0x5d */
343 | i_pop_si, /* 0x5e */
344 | i_pop_di, /* 0x5f */
345 | i_notdone,
346 | i_notdone,
347 | i_notdone,
348 | i_notdone,
349 | i_notdone,
350 | i_notdone,
351 | i_notdone,
352 | i_notdone,
353 | i_notdone,
354 | i_notdone,
355 | i_notdone,
356 | i_notdone,
357 | i_notdone,
358 | i_notdone,
359 | i_notdone,
360 | i_notdone,
361 | i_jo, /* 0x70 */
362 | i_jno, /* 0x71 */
363 | i_jb, /* 0x72 */
364 | i_jnb, /* 0x73 */
365 | i_jz, /* 0x74 */
366 | i_jnz, /* 0x75 */
367 | i_jbe, /* 0x76 */
368 | i_jnbe, /* 0x77 */
369 | i_js, /* 0x78 */
370 | i_jns, /* 0x79 */
371 | i_jp, /* 0x7a */
372 | i_jnp, /* 0x7b */
373 | i_jl, /* 0x7c */
374 | i_jnl, /* 0x7d */
375 | i_jle, /* 0x7e */
376 | i_jnle, /* 0x7f */
377 | i_80pre, /* 0x80 */
378 | i_81pre, /* 0x81 */
379 | i_notdone,
380 | i_83pre, /* 0x83 */
381 | i_test_br8, /* 0x84 */
382 | i_test_wr16, /* 0x85 */
383 | i_xchg_br8, /* 0x86 */
384 | i_xchg_wr16, /* 0x87 */
385 | i_mov_br8, /* 0x88 */
386 | i_mov_wr16, /* 0x89 */
387 | i_mov_r8b, /* 0x8a */
388 | i_mov_r16w, /* 0x8b */
389 | i_mov_wsreg, /* 0x8c */
390 | i_lea, /* 0x8d */
391 | i_mov_sregw, /* 0x8e */
392 | i_popw, /* 0x8f */
393 | i_nop, /* 0x90 */
394 | i_xchg_axcx, /* 0x91 */
395 | i_xchg_axdx, /* 0x92 */
396 | i_xchg_axbx, /* 0x93 */
397 | i_xchg_axsp, /* 0x94 */
398 | i_xchg_axbp, /* 0x95 */
399 | i_xchg_axsi, /* 0x97 */
400 | i_xchg_axdi, /* 0x97 */
401 | i_cbw, /* 0x98 */
402 | i_cwd, /* 0x99 */
403 | i_call_far, /* 0x9a */
404 | i_wait, /* 0x9b */
405 | i_pushf, /* 0x9c */
406 | i_popf, /* 0x9d */
407 | i_sahf, /* 0x9e */
408 | i_lahf, /* 0x9f */
409 | i_mov_aldisp, /* 0xa0 */
410 | i_mov_axdisp, /* 0xa1 */
411 | i_mov_dispal, /* 0xa2 */
412 | i_mov_dispax, /* 0xa3 */
413 | i_movsb, /* 0xa4 */
414 | i_movsw, /* 0xa5 */
415 | i_cmpsb, /* 0xa6 */
416 | i_cmpsw, /* 0xa7 */
417 | i_test_ald8, /* 0xa8 */
418 | i_test_axd16, /* 0xa9 */
419 | i_stosb, /* 0xaa */
420 | i_stosw, /* 0xab */
421 | i_lodsb, /* 0xac */
422 | i_lodsw, /* 0xad */
423 | i_scasb, /* 0xae */
424 | i_scasw, /* 0xaf */
425 | i_mov_ald8, /* 0xb0 */
426 | i_mov_cld8, /* 0xb1 */
427 | i_mov_dld8, /* 0xb2 */
428 | i_mov_bld8, /* 0xb3 */
429 | i_mov_ahd8, /* 0xb4 */
430 | i_mov_chd8, /* 0xb5 */
431 | i_mov_dhd8, /* 0xb6 */
432 | i_mov_bhd8, /* 0xb7 */
433 | i_mov_axd16, /* 0xb8 */
434 | i_mov_cxd16, /* 0xb9 */
435 | i_mov_dxd16, /* 0xba */
436 | i_mov_bxd16, /* 0xbb */
437 | i_mov_spd16, /* 0xbc */
438 | i_mov_bpd16, /* 0xbd */
439 | i_mov_sid16, /* 0xbe */
440 | i_mov_did16, /* 0xbf */
441 | i_notdone,
442 | i_notdone,
443 | i_ret_d16, /* 0xc2 */
444 | i_ret, /* 0xc3 */
445 | i_les_dw, /* 0xc4 */
446 | i_lds_dw, /* 0xc5 */
447 | i_mov_bd8, /* 0xc6 */
448 | i_mov_wd16, /* 0xc7 */
449 | i_notdone,
450 | i_notdone,
451 | i_retf_d16, /* 0xca */
452 | i_retf, /* 0xcb */
453 | i_int3, /* 0xcc */
454 | i_int, /* 0xcd */
455 | i_into, /* 0xce */
456 | i_iret, /* 0xcf */
457 | i_d0pre, /* 0xd0 */
458 | i_d1pre, /* 0xd1 */
459 | i_d2pre, /* 0xd2 */
460 | i_d3pre, /* 0xd3 */
461 | i_aam, /* 0xd4 */
462 | i_aad, /* 0xd5 */
463 | i_notdone,
464 | i_xlat, /* 0xd7 */
465 | i_escape, /* 0xd8 */
466 | i_escape, /* 0xd9 */
467 | i_escape, /* 0xda */
468 | i_escape, /* 0xdb */
469 | i_escape, /* 0xdc */
470 | i_escape, /* 0xdd */
471 | i_escape, /* 0xde */
472 | i_escape, /* 0xdf */
473 | i_loopne, /* 0xe0 */
474 | i_loope, /* 0xe1 */
475 | i_loop, /* 0xe2 */
476 | i_jcxz, /* 0xe3 */
477 | i_inal, /* 0xe4 */
478 | i_inax, /* 0xe5 */
479 | i_outal, /* 0xe6 */
480 | i_outax, /* 0xe7 */
481 | i_call_d16, /* 0xe8 */
482 | i_jmp_d16, /* 0xe9 */
483 | i_jmp_far, /* 0xea */
484 | i_jmp_d8, /* 0xeb */
485 | i_inaldx, /* 0xec */
486 | i_inaxdx, /* 0xed */
487 | i_outdxal, /* 0xee */
488 | i_outdxax, /* 0xef */
489 | i_lock, /* 0xf0 */
490 | i_gobios, /* 0xf1 */
491 | i_repne, /* 0xf2 */
492 | i_repe, /* 0xf3 */
493 | i_hlt, /* 0xf4 */
494 | i_cmc, /* 0xf5 */
495 | i_f6pre, /* 0xf6 */
496 | i_f7pre, /* 0xf7 */
497 | i_clc, /* 0xf8 */
498 | i_stc, /* 0xf9 */
499 | i_cli, /* 0xfa */
500 | i_sti, /* 0xfb */
501 | i_cld, /* 0xfc */
502 | i_std, /* 0xfd */
503 | i_fepre, /* 0xfe */
504 | i_ffpre /* 0xff */
505 | };
506 |
507 | #endif
508 |
--------------------------------------------------------------------------------
/keytabs.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | BYTE scan_unshifted[256] =
16 | {
17 | 0 ,0x1b, '1', '2', '3', '4', '5', '6',
18 | '7', '8', '9', '0', '-', '=',0x08,0x09,
19 | 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
20 | 'o', 'p', '[', ']',0x0d, 0 , 'a', 's',
21 | 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
22 | '\'','`', 0 ,
23 | #ifdef KBUK /* Keycode 0x2b */
24 | '#',
25 | #else
26 | '\\',
27 | #endif
28 | 'z', 'x', 'c', 'v',
29 | 'b', 'n', 'm', ',', '.', '/', 0 , '*',
30 | 0 , ' ', 0 , 0 , 0 , 0 , 0 , 0 ,
31 | 0 , 0 , 0 , 0 , 0 , 0 , 0 , '7',
32 | '8', '9', '-', '4', '5', '6', '+', '1',
33 | '2', '3', '0', '.', 0 , 0 , '\\'
34 | };
35 |
36 |
37 | BYTE scan_shift[256] =
38 | {
39 | 0 ,0x1b, '!',
40 | #ifdef KBUK /* Keycode 0x03 and 0x04 + shift */
41 | '"',0x9c,
42 | #else
43 | '@','#',
44 | #endif
45 | '$', '%', '^',
46 | '&', '*', '(', ')', '_', '+',0x08, 0 ,
47 | 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
48 | 'O', 'P', '{', '}',0x0d, 0 , 'A', 'S',
49 | 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
50 | #ifdef KBUK /* Keycode 0x28 and 0x29 + shift */
51 | '@',0xaa,
52 | #else
53 | '"','~',
54 | #endif
55 | 0 ,
56 | #ifdef KBUK
57 | '~',
58 | #else
59 | '|',
60 | #endif
61 | 'Z', 'X', 'C', 'V',
62 | 'B', 'N', 'M', '<', '>', '?', '/', '*',
63 | 0 , ' ', 0 , 0 , 0 , 0 , 0 , 0 ,
64 | 0 , 0 , 0 , 0 , 0 , 0 , 0 ,'7',
65 | '8', '9', '-', '4', '5', '6', '+', '1',
66 | '2', '3', '0', '.', 0 , 0 , '|'
67 | };
68 |
69 |
70 | BYTE scan_alt[256] =
71 | {
72 | 0x00,0x01,0x78,0x79,0x7a,0x7b,0x7c,0x7d,
73 | 0x7e,0x7f,0x80,0x81,0x82,0x83,0x0e,0xa5,
74 | 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
75 | 0x18,0x19,0x1a,0x1b,0x1c,0x00,0x1e,0x1f,
76 | 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
77 | 0x28,0x29,0x00,0x2b,0x2c,0x2d,0x2e,0x2f,
78 | 0x30,0x31,0x32,0x33,0x34,0x35,0xa4,0x37,
79 | 0x00,0x39,0x00,0x68,0x69,0x6a,0x6b,0x6c,
80 | 0x6d,0x6e,0x6f,0x70,0x71,0x00,0x00,0x97,
81 | 0x98,0x99,0x4a,0x9b,0x4c,0x9d,0x4e,0x9f,
82 | 0xa0,0xa1,0xa2,0xa3
83 | };
84 |
85 |
86 | BYTE scan_ctrl[256] =
87 | {
88 | 0 ,0x1b, 0 , 0 , 0 , 0 , 0 ,0x1e,
89 | 0 , 0 , 0 , 0 ,0x1f, 0 ,0x7f, 0 ,
90 | 17 , 23 , 5 , 18 , 20 , 25 , 21 , 9 ,
91 | 15 , 16 ,0x1b,0x1d,0x0a, 0 , 1 , 19 ,
92 | 4 , 6 , 7 , 8 , 10 , 11 , 12 , 0 ,
93 | 0 ,0x1c, 0 , 0 , 26 , 24 , 3 , 22 ,
94 | 2 , 14 , 13
95 | };
96 |
97 | BYTE scan_ctrl_high[] =
98 | {
99 | 0x95, 0x96, 0, 0, 0, 0x5e, 0x5f, 0x60, 0x61, 0x62,
100 | 0x63, 0x64, 0x65, 0x66, 0x67, 0, 0, 0x77, 0x8d, 0x84,
101 | 0x8e, 0x73, 0x8f, 0x74, 0x90, 0x75, 0x91, 0x76, 0x92, 0x93,
102 | 0, 0, 0, 0x89, 0x8a
103 | };
104 |
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is MAIN.C This is where everything begins... */
16 |
17 |
18 | #include "global.h"
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "bios.h"
26 | #include "vga.h"
27 | #include "video.h"
28 | #include "hardware.h"
29 | #include "vgahard.h"
30 |
31 | BYTE *memory;
32 | char *progname;
33 |
34 | void exit_emu(void)
35 | {
36 | disable();
37 | bios_off();
38 | vga_off();
39 | exit(0);
40 | }
41 |
42 | int main(int argc, char **argv)
43 | {
44 | progname = (progname = strrchr(argv[0],'/')) ? progname : argv[0];
45 |
46 | #ifndef BOOT
47 | FILE *f1;
48 | if (argc != 2)
49 | {
50 | fprintf(stderr,"Format: %s testfile\n",progname);
51 | exit(1);
52 | }
53 | #endif
54 | if (!(memory = (BYTE *)malloc(MEMORY_SIZE)))
55 | {
56 | fprintf(stderr,"Insufficient available memory\n");
57 | exit(1);
58 | }
59 | #ifdef BOOT
60 | memset(memory,0, MEMORY_SIZE);
61 | #else
62 | if (!(f1 = fopen(argv[1],"rb")))
63 | {
64 | fprintf(stderr,"Cannot open test file\n");
65 | exit(1);
66 | }
67 |
68 |
69 | fread(memory+0x800,1,MEMORY_SIZE-0x800,f1);
70 | fclose(f1);
71 | #endif
72 |
73 | read_pcemurc();
74 | disable();
75 |
76 | init_video();
77 | init_cpu();
78 | init_bios();
79 | init_vga();
80 | init_timer();
81 |
82 | enable();
83 |
84 | execute();
85 |
86 | /* NOT REACHED */
87 | return 0;
88 | }
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/mfs.h:
--------------------------------------------------------------------------------
1 | /*
2 | adapted from dos.h in the mach dos emulator for the linux dosemu dos
3 | emulator.
4 | Andrew.Tridgell@anu.edu.au 30th March 1993
5 | */
6 |
7 |
8 | /* ### Added by DH ### */
9 | #ifndef DOSEMU
10 | # define DOSEMU
11 | #endif
12 |
13 | #include /* for SEEK_END */
14 |
15 | /* ### End of addition ### */
16 |
17 | #ifdef DOSEMU
18 | /* definitions to make mach emu code compatible with dosemu */
19 |
20 | /* ### Commented out by DH ###
21 | * #include "emu.h"
22 | */
23 |
24 |
25 | #ifndef SOLARIS
26 | typedef unsigned char boolean_t;
27 | #endif
28 |
29 | /* ### Commented out by DH ###
30 | * #define d_namlen d_reclen
31 | */
32 |
33 | #ifndef MAX_DRIVE
34 | #define MAX_DRIVE 26
35 | #endif
36 |
37 | #define USE_DF_AND_AFS_STUFF
38 |
39 | /* ### Commented out by DH ###
40 | * #define VOLUMELABEL "Linux"
41 | * #define LINUX_RESOURCE "\\\\LINUX\\FS"
42 | */
43 |
44 | /* ### Added by DH ### */
45 |
46 | #include "mfs_link.h"
47 |
48 | #if !defined(__hpux) && !defined(SOLARIS) && !defined(SGI) && !defined(RS6000) && 0
49 | #define strerror(x) sys_errlist[x]
50 | #endif
51 |
52 | #ifdef RS6000
53 | #define strerror(x) mstrerror(x)
54 | #endif
55 |
56 | #define VOLUMELABEL "PCEmu"
57 | #define LINUX_RESOURCE "\\\\PCEMU\\FS"
58 |
59 | #define Write2Bytes(d,x) (*(BYTE *)(d) = (x) & 0xff, \
60 | *((BYTE *)(d)+1) = ((x) >> 8) & 0xff)
61 | #define Write4Bytes(d,x) (*(BYTE *)(d) = (x) & 0xff, \
62 | *((BYTE *)(d)+1) = ((x) >> 8) & 0xff, \
63 | *((BYTE *)(d)+2) = ((x) >> 16) & 0xff, \
64 | *((BYTE *)(d)+3) = ((x) >> 24) & 0xff)
65 |
66 | #define Read2Bytes(t,x) (t)(*(BYTE *)(x) + (*((BYTE *)(x) + 1) << 8))
67 | #define Read4Bytes(t,x) (t)(*(BYTE *)(x) + ((UINT32)*((BYTE *)(x) + 1) << 8) + \
68 | ((UINT32)*((BYTE *)(x) + 2) << 16) + \
69 | ((UINT32)*((BYTE *)(x) + 3) << 24))
70 |
71 | /* ### End of addition ### */
72 |
73 | /* ### Added by DH ### */
74 | #ifndef FALSE
75 | #define FALSE 0
76 | #endif
77 | #ifndef TRUE
78 | #define TRUE 1
79 | #endif
80 | /* ### End of addition ### */
81 |
82 | /* ### Commented out by DH
83 | * #define FALSE 0
84 | * #define TRUE 1
85 | */
86 |
87 | #define UNCHANGED 2
88 | #define REDIRECT 3
89 |
90 | #define us_debug_level 10
91 | #define Debug_Level_0 0
92 | #define dbg_fd stderr
93 |
94 | /* Some compilers cannot handle variable argument #defines
95 | #define d_Stub(arg1, s, a...) d_printf("MFS: "s, ##a)
96 | #define Debug0(args) d_Stub args
97 | #define Debug1(args) d_Stub args
98 | */
99 |
100 | #define Debug0(args)
101 | #define Debug1(args)
102 |
103 | typedef struct vm86_regs state_t;
104 |
105 | #define uesp esp
106 |
107 | /* ### Added '(&memory[ ... ])' to line below ### */
108 | #define Addr_8086(x,y) (&memory[(( ((x) & 0xffff) << 4) + ((y) & 0xffff))])
109 | #define Addr(s,x,y) Addr_8086(((s)->x), ((s)->y))
110 | #define MASK8(x) ((x) & 0xff)
111 | #define MASK16(x) ((x) & 0xffff)
112 | #define HIGH(x) MASK8((UINT32)(x) >> 8)
113 | #define LOW(x) MASK8((UINT32)(x))
114 | #undef WORD
115 | #define WORD(x) MASK16((UINT32)(x))
116 | #define SETHIGH(x,y) (*(x) = (*(x) & ~0xff00) | ((MASK8(y))<<8))
117 | #define SETLOW(x,y) (*(x) = (*(x) & ~0xff) | (MASK8(y)))
118 | #define SETWORD(x,y) (*(x) = (*(x) & ~0xffff) | (MASK16(y)))
119 | #endif
120 |
121 | /*
122 | * Copyright (c) 1991 Carnegie Mellon University
123 | * All Rights Reserved.
124 | *
125 | * Permission to use, copy, modify and distribute this software and its
126 | * documentation is hereby granted, provided that both the copyright
127 | * notice and this permission notice appear in all copies of the
128 | * software, derivative works or modified versions, and any portions
129 | * thereof, and that both notices appear in supporting documentation.
130 | *
131 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
132 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
133 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
134 | *
135 | * Carnegie Mellon requests users of this software to return to
136 | *
137 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
138 | * School of Computer Science
139 | * Carnegie Mellon University
140 | * Pittsburgh PA 15213-3890
141 | *
142 | * any improvements or extensions that they make and grant Carnegie Mellon
143 | * the rights to redistribute these changes.
144 | */
145 | /*
146 | *
147 | * Purpose:
148 | * V86 DOS disk emulation header file
149 | *
150 | * HISTORY:
151 | * $Log$
152 | * Revision 1.1 2001/01/22 01:35:32 michaelh
153 | * Initial revision
154 | *
155 | * Revision 1.1.1.1 2000/12/12 06:08:44 michaelh
156 | * Created.
157 | *
158 | * Revision 1.6 1994/01/25 20:02:44 root
159 | * Exchange stderr <-> stdout.
160 | *
161 | * Revision 1.5 1994/01/20 21:14:24 root
162 | * Indent.
163 | *
164 | * Revision 1.4 1994/01/19 17:51:14 root
165 | * Added CDS_FLAG_NOTNET = 0x80 for mfs.c
166 | *
167 | * Revision 1.3 1993/12/22 11:45:36 root
168 | * Fixes for ftruncate
169 | *
170 | * Revision 1.2 1993/11/17 22:29:33 root
171 | * *** empty log message ***
172 | *
173 | * Revision 1.1 1993/11/12 12:32:17 root
174 | * Initial revision
175 | *
176 | * Revision 1.1 1993/07/07 00:49:06 root
177 | * Initial revision
178 | *
179 | * Revision 1.3 1993/05/04 05:29:22 root
180 | * added console switching, new parse commands, and serial emulation
181 | *
182 | * Revision 1.2 1993/04/07 21:04:26 root
183 | * big move
184 | *
185 | * Revision 1.1 1993/04/05 17:25:13 root
186 | * Initial revision
187 | *
188 | * Revision 2.3 91/12/06 15:29:23 grm
189 | * Redefined sda_cur_psp, and added psp_parent_psp. The
190 | * psp_parent_psp was used to find out what the psp of the parent of
191 | * the command.com program was. It seems that it is undefined.
192 | * [91/12/06 grm]
193 | *
194 | * Revision 2.2 91/12/05 16:42:08 grm
195 | * Added sft_rel and _abs_cluster macros. Used to debug the
196 | * MS-Write network drive problem.
197 | * [91/12/04 grm]
198 | * Added constants for Dos 4+
199 | * [91/07/16 17:47:20 grm]
200 | *
201 | * Changed to allow for usage with Dos v4.01 and 5.00.
202 | * [91/06/28 18:53:42 grm]
203 | *
204 | * New Copyright
205 | * [91/05/28 15:12:28 grm]
206 | *
207 | * Added structures for the dos_general routines.
208 | * [91/04/30 13:43:58 grm]
209 | *
210 | * Structures and macros for the dos_fs.c
211 | * network redirector interface.
212 | * [91/04/30 13:36:42 grm]
213 | *
214 | * Name changed from dos_general.h to dos.h.
215 | * Added external declarations for dos_foo.c files.
216 | * [91/03/01 14:40:55 grm]
217 | *
218 | * Type works. Interrim changes.
219 | * [91/02/11 18:22:47 grm]
220 | *
221 | * Fancy dir.
222 | * [91/02/06 16:59:01 grm]
223 | *
224 | * Created.
225 | * [91/02/06 14:29:39 grm]
226 | *
227 | */
228 |
229 | #include
230 |
231 | /*
232 | * Dos error codes
233 | */
234 | /* MS-DOS version 2 error codes */
235 | #define FUNC_NUM_IVALID 0x01
236 | #define FILE_NOT_FOUND 0x02
237 | #define PATH_NOT_FOUND 0x03
238 | #define TOO_MANY_OPEN_FILES 0x04
239 | #define ACCESS_DENIED 0x05
240 | #define HANDLE_INVALID 0x06
241 | #define MEM_CB_DEST 0x07
242 | #define INSUF_MEM 0x08
243 | #define MEM_BLK_ADDR_IVALID 0x09
244 | #define ENV_INVALID 0x0a
245 | #define FORMAT_INVALID 0x0b
246 | #define ACCESS_CODE_INVALID 0x0c
247 | #define DATA_INVALID 0x0d
248 | #define UNKNOWN_UNIT 0x0e
249 | #define DISK_DRIVE_INVALID 0x0f
250 | #define ATT_REM_CUR_DIR 0x10
251 | #define NOT_SAME_DEV 0x11
252 | #define NO_MORE_FILES 0x12
253 | /* mappings to critical-error codes */
254 | #define WRITE_PROT_DISK 0x13
255 | #define UNKNOWN_UNIT_CERR 0x14
256 | #define DRIVE_NOT_READY 0x15
257 | #define UNKNOWN_COMMAND 0x16
258 | #define DATA_ERROR_CRC 0x17
259 | #define BAD_REQ_STRUCT_LEN 0x18
260 | #define SEEK_ERROR 0x19
261 | #define UNKNOWN_MEDIA_TYPE 0x1a
262 | #define SECTOR_NOT_FOUND 0x1b
263 | #define PRINTER_OUT_OF_PAPER 0x1c
264 | #define WRITE_FAULT 0x1d
265 | #define READ_FAULT 0x1e
266 | #define GENERAL_FAILURE 0x1f
267 |
268 | /* MS-DOS version 3 and later extended error codes */
269 | #define SHARING_VIOLATION 0x20
270 | #define FILE_LOCK_VIOLATION 0x21
271 | #define DISK_CHANGE_INVALID 0x22
272 | #define FCB_UNAVAILABLE 0x23
273 | #define SHARING_BUF_EXCEEDED 0x24
274 |
275 | #define NETWORK_NAME_NOT_FOUND 0x35
276 |
277 | #define FILE_ALREADY_EXISTS 0x50
278 |
279 | #define DUPLICATE_REDIR 0x55
280 |
281 | struct dir_ent {
282 | char name[8]; /* dos name and ext */
283 | char ext[3];
284 | u_short mode; /* unix st_mode value */
285 | long size; /* size of file */
286 | time_t time; /* st_mtime */
287 | struct dir_ent *next;
288 | };
289 |
290 | struct dos_name {
291 | char name[8];
292 | char ext[3];
293 | };
294 |
295 | typedef struct far_record {
296 | u_short offset;
297 | u_short segment;
298 | } far_t;
299 |
300 | #define DOSVER_31_33 1
301 | #define DOSVER_41 2
302 | #define DOSVER_50 3
303 | #define DOSVER_60 4
304 |
305 | typedef u_char *sdb_t;
306 |
307 | /* ### Changed all *(u_short *)... to Read2Bytes(u_short,...) ### */
308 | /* ### Changed all *(u_long *)... to Read4Bytes(u_long,...) ### */
309 | #define sdb_drive_letter(sdb) (*(u_char *)&sdb[sdb_drive_letter_off])
310 | #define sdb_template_name(sdb) ((char *)&sdb[sdb_template_name_off])
311 | #define sdb_template_ext(sdb) ((char *)&sdb[sdb_template_ext_off])
312 | #define sdb_attribute(sdb) (*(u_char *)&sdb[sdb_attribute_off])
313 | /* ### Split next definition into read (..._r) and write (..._w) ### */
314 | #define sdb_dir_entry_r(sdb) (Read2Bytes(u_short,&sdb[sdb_dir_entry_off]))
315 | #define sdb_dir_entry_w(sdb,x) (Write2Bytes(&sdb[sdb_dir_entry_off], x))
316 | #define sdb_p_cluster(sdb) (Read2Bytes(u_short,&sdb[sdb_p_cluster_off]))
317 | #define sdb_file_name(sdb) ((char *)&sdb[sdb_file_name_off])
318 | #define sdb_file_ext(sdb) ((char *)&sdb[sdb_file_ext_off])
319 | #define sdb_file_attr(sdb) (*(u_char *)&sdb[sdb_file_attr_off])
320 | #define sdb_file_time(sdb) (*(u_short *)&sdb[sdb_file_time_off])
321 | #define sdb_file_date(sdb) (*(u_short *)&sdb[sdb_file_date_off])
322 | #define sdb_file_st_cluster(sdb)(Read2Bytes(u_short,&sdb[sdb_file_st_cluster_off]))
323 | #define sdb_file_size(sdb,x) (Write4Bytes(&sdb[sdb_file_size_off],x))
324 |
325 | typedef u_char *sft_t;
326 |
327 | /* ### Split next definition into read (..._r) and write (..._w) ### */
328 | #define sft_handle_cnt_r(sft) (Read2Bytes(u_short,&sft[sft_handle_cnt_off]))
329 | #define sft_handle_cnt_w(sft,x) (Write2Bytes(&sft[sft_handle_cnt_off], x))
330 | /* ### Split next definition into read (..._r) and write (..._w) ### */
331 | #define sft_open_mode_r(sft) (Read2Bytes(u_short,&sft[sft_open_mode_off]))
332 | #define sft_open_mode_w(sft,x) (Write2Bytes(&sft[sft_open_mode_off],x))
333 | #define sft_attribute_byte(sft) (*(u_char *)&sft[sft_attribute_byte_off])
334 | /* ### Split next definition into read (..._r) and write (..._w) ### */
335 | #define sft_device_info_r(sft) (Read2Bytes(u_short,&sft[sft_device_info_off]))
336 | #define sft_device_info_w(sft,x) (Write2Bytes(&sft[sft_device_info_off], x))
337 | #define sft_dev_drive_ptr(sft,x) (Write4Bytes(&sft[sft_dev_drive_ptr_off], x))
338 | #define sft_start_cluster(sft) (Read2Bytes(u_short,&sft[sft_start_cluster_off]))
339 | #define sft_time(sft) (*(u_short *)&sft[sft_time_off])
340 | #define sft_date(sft) (*(u_short *)&sft[sft_date_off])
341 | /* ### Split next definition into read (..._r) and write (..._w) ### */
342 | #define sft_size_r(sft) (Read4Bytes(u_long,&sft[sft_size_off]))
343 | #define sft_size_w(sft, x) (Write4Bytes(&sft[sft_size_off], x))
344 | /* ### Split next definition into read (..._r) and write (..._w) ### */
345 | #define sft_position_r(sft) (Read4Bytes(u_long,&sft[sft_position_off]))
346 | #define sft_position_w(sft,x) (Write4Bytes(&sft[sft_position_off],x))
347 | #define sft_rel_cluster(sft) (Read2Bytes(u_short,&sft[sft_rel_cluster_off]))
348 | #define sft_abs_cluster(sft,x) (Write2Bytes(&sft[sft_abs_cluster_off], x))
349 | #define sft_directory_sector(sft,x) (Write2Bytes(&sft[sft_directory_sector_off],x))
350 | #define sft_directory_entry(sft) (*(u_char *)&sft[sft_directory_entry_off])
351 | #define sft_name(sft) ( (char *)&sft[sft_name_off])
352 | #define sft_ext(sft) ( (char *)&sft[sft_ext_off])
353 |
354 | /* ### Split next definition into read (..._r) and write (..._w) ### */
355 | #define sft_fd_r(sft) (Read2Bytes(u_short,&sft[sft_fd_off]))
356 | #define sft_fd_w(sft,x) (Write2Bytes(&sft[sft_fd_off], x))
357 |
358 | typedef u_char *cds_t;
359 |
360 | #define cds_current_path(cds) ((char *)&cds[cds_current_path_off])
361 | /* ### Split next definition into read (..._r) and write (..._w) ### */
362 | #define cds_flags_r(cds) (Read2Bytes(u_short,&cds[cds_flags_off]))
363 | #define cds_flags_w(cds,x) (Write2Bytes(&cds[cds_flags_off], x))
364 | #define cds_DBP_pointer(cds) (Read4Bytes(u_long,&cds[cds_DBP_pointer_off]))
365 | #define cds_cur_cluster(cds,x) (Write2Bytes(&cds[cds_cur_cluster_off],x))
366 | /* ### Split next difinition into read (..._r) and write (..._w) ### */
367 | #define cds_rootlen_r(cds) (Read2Bytes(u_short,&cds[cds_rootlen_off]))
368 | #define cds_rootlen_w(cds,x) (Write2Bytes(&cds[cds_rootlen_off], x))
369 | #define drive_cds(dd) ((cds_t)(((long)cds_base)+(cds_record_size*(dd))))
370 |
371 | #define CDS_FLAG_REMOTE 0x8000
372 | #define CDS_FLAG_READY 0x4000
373 | #define CDS_FLAG_NOTNET 0x0080
374 | #define CDS_FLAG_SUBST 0x1000
375 | #define CDS_DEFAULT_ROOT_LEN 2
376 |
377 | #define FAR(x) (Addr_8086(x.segment, x.offset))
378 |
379 | /* ### Commented out by DH ###
380 | * #define FARPTR(x) (Addr_8086((x)->segment, (x)->offset))
381 | */
382 |
383 | /* ### Added by DH ### */
384 | #define FARPTR(x) &memory[Read2Bytes(u_short, (x)) + \
385 | (Read2Bytes(u_short, (BYTE *)(x)+2) << 4)]
386 | /* ### End of addition ### */
387 |
388 | typedef u_short *psp_t;
389 |
390 | #define PSPPTR(x) (Addr_8086(x, 0))
391 |
392 | typedef u_char *sda_t;
393 |
394 | #define sda_current_dta(sda) ((char *)(FARPTR((far_t *)&sda[sda_current_dta_off])))
395 | #define sda_cur_psp(sda) (Read2Bytes(u_short,&sda[sda_cur_psp_off]))
396 | #define sda_filename1(sda) ((char *)&sda[sda_filename1_off])
397 | #define sda_filename2(sda) ((char *)&sda[sda_filename2_off])
398 | #define sda_sdb(sda) ((sdb_t )&sda[sda_sdb_off])
399 | #define sda_cds(sda) ((cds_t)(FARPTR((far_t *)&sda[sda_cds_off])))
400 | #define sda_search_attribute(sda) (*(u_char *)&sda[sda_search_attribute_off])
401 | #define sda_open_mode(sda) (*(u_char *)&sda[sda_open_mode_off])
402 | #define sda_rename_source(sda) ((sdb_t )&sda[sda_rename_source_off])
403 | #define sda_user_stack(sda) ((char *)(FARPTR((far_t *)&sda[sda_user_stack_off])))
404 |
405 | /*
406 | * Data for extended open/create operations, DOS 4 or greater:
407 | */
408 | #define sda_ext_act(sda) (Read2Bytes(u_short,&sda[sda_ext_act_off]))
409 | #define sda_ext_attr(sda) (Read2Bytes(u_short,&sda[sda_ext_attr_off]))
410 | #define sda_ext_mode(sda) (Read2Bytes(u_short,&sda[sda_ext_mode_off]))
411 |
412 | #define psp_parent_psp(psp) (Read2Bytes(u_short,&psp[0x16]))
413 | #define psp_handles(psp) ((char *)(FARPTR((far_t *)&psp[0x34])))
414 |
415 | #define lol_cdsfarptr(lol) (Read4Bytes(u_long,&lol[lol_cdsfarptr_off]))
416 | #define lol_last_drive(lol) (*(u_char *)&lol[lol_last_drive_off])
417 |
418 | typedef u_char *lol_t;
419 |
420 | #ifdef OLD_OBSOLETE
421 | typedef struct lol_record {
422 | u_char filler1[22];
423 | far_t cdsfarptr;
424 | u_char filler2[6];
425 | u_char last_drive;
426 | } *lol_t;
427 |
428 | #endif
429 |
430 | /* dos attribute byte flags */
431 | #define REGULAR_FILE 0x00
432 | #define READ_ONLY_FILE 0x01
433 | #define HIDDEN_FILE 0x02
434 | #define SYSTEM_FILE 0x04
435 | #define VOLUME_LABEL 0x08
436 | #define DIRECTORY 0x10
437 | #define ARCHIVE_NEEDED 0x20
438 |
439 | /* dos access mode constants */
440 | #define READ_ACC 0x00
441 | #define WRITE_ACC 0x01
442 | #define READ_WRITE_ACC 0x02
443 |
444 | #define COMPAT_MODE 0x00
445 | #define DENY_ALL 0x01
446 | #define DENY_WRITE 0x02
447 | #define DENY_READ 0x03
448 | #define DENY_ANY 0x40
449 |
450 | #define CHILD_INHERIT 0x00
451 | #define NO_INHERIT 0x01
452 |
453 | #define A_DRIVE 0x01
454 | #define B_DRIVE 0x02
455 | #define C_DRIVE 0x03
456 | #define D_DRIVE 0x04
457 |
458 | #define GET_REDIRECTION 2
459 | #define REDIRECT_DEVICE 3
460 | #define CANCEL_REDIRECTION 4
461 | #define EXTENDED_GET_REDIRECTION 5
462 |
--------------------------------------------------------------------------------
/mfs_link.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* Attempt to fix mfs. dtrg */
16 |
17 | /* #define u_long UINT32 */
18 |
19 | struct vm86_regs
20 | {
21 | INT16 eax, ebx, ecx, edx, esi, edi, ebp, esp;
22 | INT16 cs,ds,es,ss;
23 | INT16 eip;
24 | UINT16 eflags;
25 | };
26 |
27 | struct vm86_struct
28 | {
29 | struct vm86_regs regs;
30 | UINT32 flags;
31 | UINT32 screen_bitmap;
32 | };
33 |
34 | extern struct vm86_struct vm86s;
35 | extern unsigned char *memory;
36 |
37 | #define us unsigned short
38 |
39 | #ifndef BIOS
40 |
41 | #define LWORD(reg) (*((unsigned short *)®(reg)))
42 | #define HWORD(reg) (*((unsigned short *)®(reg) + 1))
43 |
44 | #define SEG_ADR(type, seg, reg) type(&memory[(LWORD(seg) << 4)+LWORD(e##reg)])
45 |
46 |
47 | #define REGS vm86s.regs
48 | #define REG(reg) (REGS.##reg)
49 |
50 | #define CF (1 << 0)
51 | #define TF (1 << 8)
52 | #define IF (1 << 9)
53 | #define NT 0
54 |
55 |
56 | #define IS_REDIRECTED(i) (memory[(i << 2)+2] != 0xf000)
57 |
58 | #define INTE7_SEG (memory[(0xe7 << 2)+2] + (memory[(0xe7 << 2)+3] << 8))
59 | #define INTE7_OFF (memory[0xe7 << 2] + (memory[(0xe7 << 2) + 1] << 8))
60 |
61 | #define error printf
62 |
63 | /* Some compilers cannot handle variable numbers of arguments in #defines
64 | #ifdef DEBUG
65 | # define d_printf(arg1, a...) printf(arg1, ##a)
66 | #else
67 | # define d_printf(arg1, a...)
68 | #endif
69 | */
70 |
71 | #endif
72 |
73 | int mfs_intentry(void);
74 | int mfs_redirector(void);
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/mytypes.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is MYTYPES.H It contains definitions for the basic types to ease
16 | portability */
17 |
18 |
19 | #ifndef MYTYPES_H
20 |
21 | #define MYTYPES_H
22 |
23 | /* When cross compiling, we can't use autodetect */
24 | #ifdef i386
25 | #define PCEMU_LITTLE_ENDIAN 1
26 | typedef signed char INT8;
27 | typedef unsigned char UINT8;
28 | typedef signed short INT16;
29 | typedef unsigned short UINT16;
30 | typedef signed int INT32;
31 | typedef unsigned int UINT32;
32 |
33 | #else
34 | #include "autodetect.h"
35 |
36 | #endif
37 |
38 | typedef UINT8 BYTE;
39 | typedef UINT16 WORD;
40 | typedef UINT32 DWORD;
41 |
42 | typedef BYTE Boolean;
43 |
44 | #endif
45 |
--------------------------------------------------------------------------------
/new.pcemurc:
--------------------------------------------------------------------------------
1 | # New-style pcemurc for a DEC Alpha. The floppy drive is on /dev/floppy,
2 | # surprise surprise. The other floppy drive is a minimal boot image.
3 | # Put this in ~/.pcemurc.
4 | # --dg
5 |
6 | floppy 0 /dev/floppy 18 80 2
7 | floppy 1 /user.jh/dg/lib/pcemu/bootimage 10 20 2
8 | updatespeed 10
9 | cursorspeed 35
10 |
--------------------------------------------------------------------------------
/old.pcemurc:
--------------------------------------------------------------------------------
1 | # This is .pcemurc
2 | # At present only the following commands are recognised:
3 | # bootfile diskfile
4 | # boottype n (where n=360, 720, 144 or 12)
5 | # cursorspeed n
6 | # updatespeed n
7 | #
8 | # The following are the defaults (unless changed at compile time)
9 |
10 | bootfile /dev/floppy
11 | boottype 144
12 | cursorspeed 30
13 | updatespeed 5
14 |
--------------------------------------------------------------------------------
/programs/Makefile:
--------------------------------------------------------------------------------
1 | AS86 = as86 -l
2 | LD86 = ld86 -0 -s
3 |
4 | all: emufs.sys
5 |
6 | %.sys: %.S
7 | $(AS86) -0 -o $*.o $< > $<.out
8 | $(LD86) -T 0 -s -o $*.tmp $*.o
9 | dd if=$*.tmp of=$@ bs=1 skip=32
10 | rm $*.tmp $*.o
11 |
12 | clean:
13 | rm -f emufs.sys *.o *.tmp *.out
14 |
--------------------------------------------------------------------------------
/programs/config.sys:
--------------------------------------------------------------------------------
1 | device=emufs.sys /
2 | stacks 9,512
3 |
--------------------------------------------------------------------------------
/programs/dumpdisk.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidgiven/pcemu/88061c7ad5efd5343bb42d97f14756881bc97e4e/programs/dumpdisk.c
--------------------------------------------------------------------------------
/programs/ekemm.asm:
--------------------------------------------------------------------------------
1 | name driver
2 | page 55,132
3 | title 'EKEMM --- EMS 3.2 Driver For Hedley's PCEMU'
4 |
5 | ;
6 | ;
7 | ;
8 | ; Based on a template (c) Ray Duncan, April 1985
9 | ; Changes Copyright 1994, Eric Korpela.
10 | ; There is no warantee expressed or implied in this software.
11 | ; See the file COPYRIGHT and ems.c for details.
12 |
13 | code segment public 'CODE'
14 |
15 | driver proc far
16 |
17 | assume cs:code,ds:code,es:code
18 |
19 | org 0
20 |
21 | Max_Cmd equ 16 ; MS-DOS command code maximum
22 |
23 | cr equ 0dh
24 | lf equ 0ah
25 | eom equ '$'
26 |
27 | page
28 | ;
29 | ; Device Driver Header
30 | ;
31 | Header dd -1 ; link to next device, -1=end of list
32 |
33 | dw 0C000h ; Device Attribute word
34 | dw Strat ; Device "Strategy" entry point
35 | dw Intr ; Device "Interrupt" entry point
36 | db 'EMMXXXX0' ; character device name
37 |
38 | ;
39 | ; Double-word pointer to Request Header
40 | ; Passed to Strategy routine by MS-DOS
41 | ;
42 |
43 | RH_Ptr dd ?
44 | page
45 | ;
46 | ; MS-DOS Command Codes dispatch table.
47 | ; The "Interrupt" Routine uses this table and the
48 | ; Command Code supplied in the Request Header to
49 | ; transfer to the appropriate driver subroutine.
50 |
51 | Dispatch:
52 | dw Init ; 0=initialize driver
53 | dw Media_Chk ; 1=media check on block device
54 | dw Build_Bpb ; 2=build BIOS parameter block
55 | dw IOCTL_Rd ; 3=I/O Control read
56 | dw Read ; 4=Read from Device
57 | dw ND_Read ; 5=non-destructive read
58 | dw Inp_Stat ; 6=return current input status
59 | dw Inp_Flush ; 7=flush device input buffers
60 | dw Write ; 8=write to device
61 | dw Write_Vfy ; 9=write with verify
62 | dw Outp_Stat ; 10=return current output status
63 | dw Outp_Flush ; 11=flush output buffers
64 | dw IOCTL_Wrt ; 12=I/O control write
65 | dw Dev_Open ; 13=Device Open
66 | dw Dev_Close ; 14=Device Close
67 | dw Rem_Media ; 15=removable media
68 | dw Out_Busy ; 16=output until busy
69 | page
70 | ;
71 | ; MS-DOS Request Header Structure Definition
72 | ;
73 | ; The first 13 bytes of all Request Headers are the same
74 | ; and are referred to as the "Static" part of the header.
75 | ; The number and meaning of the following bytes varies.
76 | ; In this "Struc" definition we show the Request Header
77 | ; contents for Read and Write calls.
78 | ;
79 | Request struc ; Request Header template structure
80 | ; begining of static portion
81 | Rlength db ? ; length of request header
82 | Unit db ? ; unit number for this request
83 | Command db ? ; request header's command code
84 | Status dw ? ; Driver's return status word
85 | ; bit 15 = Error
86 | ; bits 10-14 = Reserved
87 | ; bit 9 = Busy
88 | ; bit 8 = Done
89 | ; bits 0-7 = Error code if bit 15 = 1
90 | Reserve db 8 dup (?) ; reserved area
91 | ; end of Static Portion, the remainder in
92 | ; this example is for Read Write functions.
93 | Media db ? ; Media Descriptor byte
94 | Address dd ? ; Memory Address for Transfer
95 | Count dw ? ; byte/sector count value
96 | Sector dw ? ; Starting sector value
97 | Request ends ; end of request header template
98 | page
99 |
100 | ; Device Driver Strategy Routine
101 | ;
102 | ; Each time a request is made for this device, MS-DOS
103 | ; first calls the "Strategy Routine", then immediately
104 | ; calls the "Interrupt routine".
105 |
106 | ; The Strategy routine is passed the address of the
107 | ; Request Header in ES:BX, which it saves in a local
108 | ; variable and then returns to MS-DOS.
109 |
110 | Strat proc far
111 | ; save addresss of Request Header
112 | mov word ptr cs:[RH_Ptr],bx
113 | mov word ptr cs:[RH_Ptr+2],es
114 |
115 | ret ; back to MS-DOS
116 |
117 | Strat endp
118 | page
119 |
120 | ; Device Driver Interrupt Routine
121 |
122 | ; This entry point is called by MS-DOS immediately after
123 | ; the call to the "Strategy Routine", which saved the long
124 | ; address of the Request Header in the local variable "RH_Ptr".
125 |
126 | ; The "Interrupt Routine" uses the Command Code passed in
127 | ; the Request Header to transfer to the appropriate device
128 | ; handling routine. Each command code routine must place
129 | ; any necessary return information into the Request Header,
130 | ; then perform a near return with AX=Status.
131 |
132 | Intr proc far
133 |
134 | push ax ; save general registers
135 | push bx
136 | push cx
137 | push dx
138 | push ds
139 | push es
140 | push di
141 | push si
142 | push bp
143 |
144 | push cs ; make local data addressable
145 | pop ds
146 |
147 | les di,[RH_Ptr] ; let ES:DI = Request header
148 |
149 | ; get BX = command code
150 | mov bl,es:[di.Command]
151 | xor bh,bh
152 | cmp bx,Max_Cmd ; make sure it's legal.
153 | jle Intr1 ; jump if fuction code is OK
154 | mov ax,8003h ; set Error bit and "Unknown Command" code
155 | jmp Intr2
156 |
157 | Intr1: shl bx,1 ; form index to dispatch table
158 | ; and branch to driver routine.
159 | call word ptr [bx+Dispatch]
160 | ; should return AX = status.
161 | les di,[RH_Ptr] ; restore ES:DI = addr of Request header
162 |
163 | Intr2: or ax,0100h ; merge Done bit into status, and
164 | ; store into request header
165 | mov es:[di.Status],ax
166 |
167 | pop bp ; restore general registers.
168 | pop si
169 | pop di
170 | pop es
171 | pop ds
172 | pop dx
173 | pop cx
174 | pop bx
175 | pop ax
176 | ret ; back to MS-DOS
177 |
178 | page
179 |
180 | ;
181 | ; Command Code subroutines called by Interrupt Routine
182 | ;
183 | ; These routines are called with ES:DI pointing to the
184 | ; Request Header.
185 | ;
186 | ; They should return AX = 0 if function was completed
187 | ; successfully, or AX = 8000H + Error code if function failed.
188 | ;
189 |
190 | Write proc near ; Function 8 = write
191 | xor ax,ax
192 | ret
193 | Write endp
194 |
195 | Media_Chk equ Offset Write ; Function 1 = Media Check
196 |
197 | Build_Bpb equ Offset Write ; Function 2 = Build BPB
198 |
199 | IOCTL_Rd proc near ; Function 3 = I/O Control Read
200 |
201 | xor ax,ax
202 | mov es:[di.Count],ax
203 | mov al,0FFh
204 | ret
205 |
206 | IOCTL_Rd endp
207 |
208 | Read equ Offset IOCTL_Rd ; Function 4 = Read
209 |
210 | ND_Read equ Offset IOCTL_Rd ; Function 5 = Non-Destructive Read
211 |
212 | Inp_Stat equ Offset Write ; Function 6 = Input Status
213 |
214 | Inp_Flush equ Offset Write ; Function 7 = Input Flush
215 |
216 | Write_Vfy equ Offset Write ; Function 9 = Write with Verify
217 |
218 | Outp_Stat equ Offset IOCTL_Wrt ; Function 10 = Output Status
219 |
220 | Outp_Flush equ Offset Write ; Function 11 = Flush Output Buffers
221 |
222 | IOCTL_Wrt proc near ; Function 12 = I/O Control Write
223 | mov ax,0FFh
224 | ret
225 | IOCTL_Wrt endp
226 |
227 | Int67 proc far
228 | int 4Bh
229 | iret
230 | Int67 endp
231 | Dev_Open equ Offset Write ; Function 13 = Device Open
232 |
233 | Dev_Close equ Offset Write ; Function 14 = Device Close
234 |
235 | Rem_Media equ Offset Write ; Function 15 = Removable Media
236 |
237 | Out_Busy equ Offset Write ; Function 16 = Output until busy
238 |
239 | page
240 |
241 | ; The initialization code for the driver is called only
242 | ; once, when the driver is loaded. It is reasponsible for
243 | ; initializing the hardware, setting up any necessary
244 | ; interrupt vectors, and it must return the address
245 | ; of the first free memory after the driver to MS-DOS.
246 | ; If it is a block device driver, Init must also return the
247 | ; address of the BIOS parameter block pointer array; if all
248 | ; units are the same, all pointers can be to the same BPB.
249 | ; Only MS-DOS services 01-0CH and 30H can be called by the
250 | ; Initialization Function.
251 | ;
252 | ; In this example, Init returns its own address to the DOS as
253 | ; the start of free memory after the driver, so that the memory
254 | ; occupied by INIT will be reclaimed after it is finished
255 | ; with its work.
256 |
257 | Init proc near ; Function 0 = Initialize Driver
258 |
259 | push es ; save address of Request Header.
260 | push di
261 |
262 | mov ax,cs ; convert load address to ASCII.
263 | mov bx, offset DHaddr
264 | call hexasc
265 |
266 | mov ah,9 ; print sign-on message and
267 | mov dx,offset Ident ; the load address of the driver.
268 | int 21h
269 | push ds
270 | push dx
271 | mov al,67h
272 | mov dx,cs
273 | mov ds,dx
274 | mov dx,offset Int67
275 | mov ah,25h
276 | int 21h
277 |
278 | pop dx
279 | pop ds
280 | pop di ; restore Request Header addr.
281 | pop es
282 |
283 | ; set first usable memory address
284 | mov word ptr es:[di.Address],offset init
285 | mov word ptr es:[di.Address+2],cs
286 |
287 | xor ax,ax ; Return Status
288 | ret
289 |
290 | Init endp
291 |
292 | Ident db cr,lf,lf
293 | db 'EKEMS Device Driver 1.0'
294 | db cr,lf
295 | db 'Device Header at '
296 |
297 | DHaddr db 'XXXX:0000'
298 | db cr,lf,lf,eom
299 |
300 | Intr endp
301 |
302 | page
303 |
304 | ; HEXASC --- converts a binary 16 bit number into
305 | ; a "hexidecimal" ASCII string.
306 | ;
307 | ; Call with AX = value to convert
308 | ; DS:BX = address to store 4 character string
309 | ;
310 | ; Returns AX, BX destroyed, other registers preserved
311 |
312 | hexasc proc near
313 |
314 | push cx ; save registers.
315 | push dx
316 |
317 | mov dx,4 ; initialize character counter.
318 |
319 | hexasc1:
320 | mov cx,4 ; isolate next 4 bits.
321 | rol ax,cl
322 | mov cx,ax
323 | and cx,0fh
324 | add cx,'0' ; convert to ASCII.
325 | cmp cx,'9' ; is it 0-9?
326 | jbe hexasc2 ; yes, jump.
327 | ; add fudge factor for A-F.
328 | add cx,'A'-'9'-1
329 |
330 | hexasc2: ; store this character.
331 | mov [bx],cl
332 | inc bx ; bump string pointer.
333 |
334 | dec dx ; count characters converted.
335 | jnz hexasc1 ; loop, not four yet.
336 |
337 | pop dx ; restore registers.
338 | pop cx
339 | ret ; back to caller
340 |
341 | hexasc endp
342 |
343 | Driver endp
344 |
345 | code ends
346 |
347 | end
348 |
349 |
350 |
--------------------------------------------------------------------------------
/programs/ekemm.sys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidgiven/pcemu/88061c7ad5efd5343bb42d97f14756881bc97e4e/programs/ekemm.sys
--------------------------------------------------------------------------------
/programs/emufs.S:
--------------------------------------------------------------------------------
1 | !
2 | !
3 | ! Mach Operating System
4 | ! Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
5 | ! Copyright (c) 1991 IBM Corporation
6 | ! All Rights Reserved.
7 | !
8 | ! Permission to use, copy, modify and distribute this software and its
9 | ! documentation is hereby granted, provided that both the copyright
10 | ! notice and this permission notice appear in all copies of the
11 | ! software, derivative works or modified versions, and any portions
12 | ! thereof, and that both notices appear in supporting documentation,
13 | ! and that the nema IBM not be used in advertising or publicity
14 | ! pertaining to distribution of the software without specific, written
15 | ! prior permission.
16 | !
17 | ! CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
18 | ! CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
19 | ! ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
20 | !
21 | ! Carnegie Mellon requests users of this software to return to
22 | !
23 | ! Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
24 | ! School of Computer Science
25 | ! Carnegie Mellon University
26 | ! Pittsburgh PA 15213-3890
27 | !
28 | ! any improvements or extensions that they make and grant Carnegie Mellon
29 | ! the rights to redistribute these changes.
30 | !
31 | ! MACHFS.ASM MS-DOS device driver to interface mach file system
32 | ! with the dos server's monitor.
33 | !
34 | ! Version 1.1
35 | !
36 | ! Gerald Malan (grm) 4/5/1991
37 | !
38 | ! modified for the linux dos emulator by Andrew Tridgell 13/4/93
39 | ! translated into as86 form by Robert Sanders ('murrcan style date!) 4/13/93
40 | ! (I probably broke something, but it seems to work)
41 | !
42 | ! $Date$
43 | ! $Source$
44 | ! $Revision$
45 | ! $State$
46 | !
47 |
48 | ! Altered slightly to run under PCEMU - DH
49 | ! Additions/alterations are marked
50 |
51 | use16
52 |
53 | .text
54 | .bss
55 | .data
56 | .align 0
57 |
58 | .org 0
59 |
60 | MaxCmd = 12
61 | cr = 0xd
62 | lf = 0xa
63 | eom = '$' ! DOS end-of-string character (barf)
64 | Linuxfs = 0xe6 ! 0xe6 is Int for Mach Dos Server
65 | Mivec = (Linuxfs * 4) ! mem loc for the interrupt vector
66 |
67 | .globl _main
68 | _main:
69 |
70 | Header:
71 | .long -1 ! link to next device driver
72 | .word 0 ! attribute word for driver
73 | .word Strat ! ptr to strategy routine
74 | .word Intr ! ptr to interrupt service routine
75 | ! ### Line below changed by DH ###
76 | .ascii "PCEMU " ! logical-device name
77 |
78 | ! the Strat and Intr routines are entered with a "far call". I don't
79 | ! know how to tell as86 that asI would in Turbo Assembler, so Ijust
80 | ! explicitly "retf" at the end of their execution. careful!
81 |
82 | ! BPB from horse.mach.cs.cmu.edu
83 | Bpb: .word 0x200 ! Bytes per Sector
84 | .byte 4 ! Sectors per allocation unit
85 | .word 1 ! Number of reserved sectors
86 | .byte 2 ! Number of FATS
87 | .word 0x200 ! Max number of root entries
88 | .word 0xac21 ! Total number of sectors
89 | .byte 0xf8 ! Media Desc Byte
90 | .word 0x2b ! Num sec per FAT
91 | .word 0x23 ! Sectors per track
92 | .word 0xf ! Number of heads
93 | .word 0 ! Number of hidden sectors
94 | .word 0 ! High order word of hidden sectors
95 | .long 0 ! zero
96 | .long 0
97 | .long 0
98 | .long 0
99 | .long 0
100 | .long 0
101 | .long 0
102 | .long 0
103 |
104 | BPBptr: .word Bpb
105 |
106 | RHPtr: .long 0 ! ptr to request header
107 |
108 | InitDone: .word 0 ! 1 when initialisation is complete
109 |
110 | Dispatch:
111 |
112 | .word Init ! initialize driver
113 | .word MediaChk
114 | .word BuildBpb
115 | .word Dummy
116 | .word Read ! read
117 | .word Dummy
118 | .word Dummy
119 | .word Dummy
120 | .word Write ! write
121 | .word Write ! write with verify
122 | .word Dummy
123 | .word Dummy
124 | .word Dummy
125 |
126 | Strat:
127 | ! was...
128 | ! mov word ptr cs:[RHPtr],bx
129 | ! mov word ptr cs:[RHPtr+2],es
130 | seg cs
131 | mov [RHPtr], bx
132 | seg cs
133 | mov [RHPtr+2],es
134 | retf
135 |
136 |
137 | Intr:
138 | push ax
139 | push bx
140 | push cx
141 | push dx
142 | push ds
143 | push es
144 | push di
145 | push si
146 | push bp
147 |
148 | push cs
149 | pop ds
150 |
151 | les di,[RHPtr] ! let es:di = request header
152 |
153 | seg es
154 | movb bl,[di+2]
155 | xorb bh,bh
156 | cmp bx, #MaxCmd
157 | jle Intr1
158 | call Error
159 | jmp Intr2
160 |
161 | Intr1: shl bx,#1
162 |
163 | call [bx+Dispatch]
164 |
165 | les di,[RHPtr]
166 |
167 | Intr2: or ax,#0x100 ! Merge done bit with status
168 | seg es
169 | mov [di+3],ax
170 |
171 | pop bp
172 | pop si
173 | pop di
174 | pop es
175 | pop ds
176 | pop dx
177 | pop cx
178 | pop bx
179 | pop ax
180 | retf
181 |
182 | Dummy:
183 | call MFSini
184 | les di, [RHPtr]
185 | seg es
186 | mov bl, [di+2]
187 | mov bh, #3
188 |
189 | mov ax, #0x20
190 | int Linuxfs
191 |
192 | xor ax,ax
193 | ret
194 |
195 |
196 | MediaChk:
197 | call MFSini
198 | ! was...
199 | ! mov byte ptr es:[di+14],#-1 ! disk has changed
200 | ! mov word ptr es:[di+15], offset NoName
201 | ! mov word ptr es:[di+17], cs
202 | seg es
203 | movb [di+14],#-1 ! disk has changed
204 | seg es
205 | mov [di+15], #NoName
206 | seg es
207 | mov [di+17], cs
208 | xor ax,ax
209 | ret
210 |
211 |
212 | BuildBpb:
213 | call MFSini
214 | ! was...
215 | ! mov word ptr es:[di+18],offset Bpb
216 | ! mov word ptr es:[di+20],cs
217 | seg es
218 | mov [di+18], #Bpb
219 | seg es
220 | mov [di+20], cs
221 | xor ax,ax
222 | ret
223 |
224 |
225 | Read:
226 | call MFSini
227 | mov bx,#0x101
228 | mov ax,#0x20
229 | int Linuxfs
230 | xor ax,ax
231 | ret
232 |
233 |
234 | Write:
235 | call MFSini
236 | mov bx,#0x202
237 | mov ax,#0x20
238 | int Linuxfs
239 | xor ax,ax
240 | ret
241 |
242 |
243 | Error:
244 | mov ax,#0x8003
245 | ret
246 |
247 |
248 | MyIret:
249 | xor ax,ax
250 | iret
251 |
252 |
253 | MFSini:
254 | push es
255 | push di
256 |
257 | push cs
258 | pop ds
259 | mov ax,[InitDone]
260 | cmp ax,#0
261 | jne AlreadyDone
262 |
263 | mov ax, #0x3000
264 | int 0x21
265 | push ax
266 |
267 | mov ah, #0x52
268 | int 0x21
269 |
270 | mov ax, #0x5d06
271 | int 0x21
272 |
273 | pop cx
274 | push bx
275 | pop dx
276 | mov bx, #0x500
277 | mov ax,#0x20
278 | int Linuxfs
279 |
280 | push cs
281 | pop ds
282 | mov ax,#1
283 | mov [InitDone],ax
284 |
285 | AlreadyDone:
286 | pop di
287 | pop es
288 | ret
289 |
290 | ! ### Added by DH ###
291 |
292 | Old2f:
293 | nop
294 | nop
295 | nop
296 | nop
297 |
298 | Int2fHandler:
299 | cmp ah,#0x11
300 | jnz NotRedir
301 | push bp
302 | mov bp,sp
303 | push word ptr [bp+8]
304 | int #0xe8
305 | pop bp
306 | pop bp
307 | jz NotRedir
308 | sti
309 | retf #2
310 | NotRedir:
311 | seg cs
312 | jmp far [Old2f]
313 |
314 | InitRedir:
315 | cli
316 | push ds
317 | push es
318 | push ax
319 | xor ax,ax
320 | mov ds,ax
321 | les ax,[0x2f*4]
322 | seg cs
323 | mov [Old2f],ax
324 | seg cs
325 | mov [Old2f+2],es
326 | mov [0x2f*4],#Int2fHandler
327 | mov [0x2f*4+2], cs
328 | pop ax
329 | pop es
330 | pop ds
331 | sti
332 | ret
333 | ! ### End of addition
334 |
335 | Init:
336 | xor bx,bx
337 | push si
338 | mov si, #DirName
339 | movb [si], #0x24
340 | mov ax, #0x20
341 | int Linuxfs
342 | pop si
343 |
344 | cmp ax, #0
345 | jne MFSin
346 |
347 | MFSout:
348 | push cs
349 | pop ds
350 | mov ah, #9
351 | mov dx, #OutMess
352 | int 0x21
353 |
354 | ! was...
355 | ! mov byte ptr es:[di+13],#0 ! No units!!
356 | ! mov word ptr es:[di+18],offset BPBptr
357 | ! mov word ptr es:[di+20],cs
358 | ! ### Line below changed from #0 to #InitRedir
359 | ! mov word ptr es:[di+14],#InitRedir !Break addr = cs:InitRedir
360 | ! mov word ptr es:[di+16],cs
361 |
362 | seg es
363 | movb [di+13],#0 ! No units!!
364 | seg es
365 | mov [di+18], #BPBptr
366 | seg es
367 | mov [di+20],cs
368 | seg es
369 | mov [di+14],#InitRedir !Break addr = cs:InitRedir
370 | seg es
371 | mov [di+16],cs
372 |
373 | ret
374 |
375 | MFSin:
376 | ! ### Added by DH ###
377 | call InitRedir
378 | ! ### End of addition ###
379 | call MFSini
380 |
381 | seg es
382 | movb al, [di+22]
383 | add al, #0x41
384 |
385 | push di
386 | push cs
387 | pop ds
388 | mov di, #Mesage1
389 | movb [di],al
390 |
391 | mov ah, #9
392 | mov dx, #Mesage
393 | int 0x21
394 | pop di
395 |
396 | ! was...
397 | ! mov byte ptr es:[di+13],#1 ! Number of units
398 | ! mov word ptr es:[di+18],offset BPBptr
399 | ! mov word ptr es:[di+20],cs
400 | ! mov word ptr es:[di+14],offset Init
401 | ! mov word ptr es:[di+16],cs
402 |
403 | ! this is part of diff9
404 | ! seg es
405 | ! movb [di+13],#1 ! Number of units
406 |
407 | seg es
408 | mov [di+18], #BPBptr
409 | seg es
410 | mov [di+20],cs
411 | seg es
412 | mov [di+14], #Init
413 | seg es
414 | mov [di+16],cs
415 |
416 | xor ax,ax
417 |
418 | ret
419 |
420 | ! ### Next line altered slightly by DH
421 | Mesage: .ascii "[PC Emulator File System] drive "
422 | Mesage1:
423 | .ascii "A: is directory "
424 | DirName:
425 | .space 128
426 | .byte cr,lf,eom
427 |
428 | OutMess:
429 | .byte cr,lf,lf
430 | .ascii "Linux Dos Server not responding."
431 | .byte cr,lf
432 | .ascii "Installation aborted."
433 | .byte cr,lf,lf,eom
434 |
435 | NoName: .ascii "NO NAME"
436 | .byte 0
437 |
438 | end
439 |
440 |
441 |
--------------------------------------------------------------------------------
/programs/emufs.sys:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidgiven/pcemu/88061c7ad5efd5343bb42d97f14756881bc97e4e/programs/emufs.sys
--------------------------------------------------------------------------------
/programs/lredir.c:
--------------------------------------------------------------------------------
1 | /***********************************************
2 | * File: LREDIR.C
3 | * Program for Linux DOSEMU disk redirector functions
4 | * Written: 10/29/93 by Tim Bird
5 | *
6 | * (altered slightly by DH - changed 'LINUX\FS' to 'PCEMU\FS' in help message)
7 | *
8 | * NOTES:
9 | * LREDIR supports the following commands:
10 | * LREDIR drive filepath
11 | * redirects the indicated drive to the specified linux filepath
12 | * drive = the drive letter followed by a colon (ex. 'E:')
13 | * filepath has linux and a file path (ex. 'LINUX\USR\SRC')
14 | * LREDIR DEL drive
15 | * cancels redirection of the indicated drive
16 | * LREDIR
17 | * shows drives that are currently redirected (mapped)
18 | * LREDIR HELP or LREDIR ?
19 | * show usage information for LREDIR ???
20 | ***********************************************/
21 | #include /* for printf */
22 | #include /* for geninterrupt and MK_FP */
23 | #include
24 |
25 | typedef unsigned char uint8;
26 |
27 |
28 | typedef unsigned int uint16;
29 |
30 |
31 |
32 | #define CARRY_FLAG 1 /* carry bit in flags register */
33 |
34 | #define CC_SUCCESS 0
35 |
36 | #define DOS_GET_LIST_OF_LISTS 0x5200
37 | #define DOS_GET_SDA_POINTER 0x5D06
38 | #define DOS_GET_REDIRECTION 0x5F02
39 | #define DOS_REDIRECT_DEVICE 0x5F03
40 | #define DOS_CANCEL_REDIRECTION 0x5F04
41 |
42 |
43 | #define MAX_RESOURCE_STRING_LENGTH 36 /* 16 + 16 + 3 for slashes + 1 for NULL */
44 | #define MAX_RESOURCE_PATH_LENGTH 128 /* added to support Linux paths */
45 | #define MAX_DEVICE_STRING_LENGTH 5 /* enough for printer strings */
46 |
47 | #define REDIR_PRINTER_TYPE 3
48 | #define REDIR_DISK_TYPE 4
49 |
50 | #define READ_ONLY_DRIVE_ATTRIBUTE 1 /* same as NetWare Lite */
51 |
52 | #define KEYWORD_DEL "DELETE"
53 | #define KEYWORD_DEL_COMPARE_LENGTH 3
54 |
55 | #define DEFAULT_REDIR_PARAM 0
56 |
57 | #define DOS_HELPER_INT 0xE6
58 | #define DOS_HELPER_DOSEMU_CHECK 0x00
59 |
60 | /* returns non-zero major version number if DOSEMU is loaded */
61 | uint16 CheckForDOSEMU(void)
62 | {
63 |
64 | _AL = DOS_HELPER_DOSEMU_CHECK;
65 |
66 | geninterrupt(DOS_HELPER_INT);
67 |
68 | /* check for signature in AX */
69 | if (_AX == 0xaa55) {
70 |
71 | return (_BX);
72 |
73 | }
74 | else {
75 |
76 | return (0);
77 |
78 | }
79 |
80 | }
81 |
82 |
83 |
84 | char far *
85 | GetListOfLists()
86 | {
87 |
88 | char far *LOL;
89 |
90 |
91 |
92 | _AX = DOS_GET_LIST_OF_LISTS;
93 |
94 | geninterrupt(0x21);
95 |
96 | LOL = MK_FP(_ES, _BX);
97 |
98 | return (LOL);
99 |
100 | }
101 |
102 |
103 |
104 | char far *
105 | GetSDAPointer(void)
106 | {
107 |
108 | char far *SDA;
109 |
110 |
111 |
112 | _AX = DOS_GET_SDA_POINTER;
113 |
114 | asm {
115 |
116 | push ds
117 | int 0x21
118 | push ds
119 | pop es
120 | pop ds
121 | }
122 |
123 | SDA = MK_FP(_ES, _SI);
124 |
125 | return (SDA);
126 |
127 | }
128 |
129 |
130 |
131 | /********************************************
132 | * InitMFS - call Emulator to initialize MFS
133 | ********************************************/
134 | uint16 InitMFS(void)
135 | {
136 |
137 | uint16 ccode;
138 |
139 | char far *LOL;
140 |
141 |
142 | char far *SDA;
143 |
144 |
145 |
146 | LOL = GetListOfLists();
147 |
148 | SDA = GetSDAPointer();
149 |
150 |
151 | /* get DOS version into CX */
152 | _CL = _osmajor;
153 |
154 | _CH = _osminor;
155 |
156 |
157 | asm {
158 |
159 | push ds
160 | }
161 |
162 |
163 | _DX = FP_OFF(LOL);
164 |
165 | _ES = FP_SEG(LOL);
166 |
167 | _SI = FP_OFF(SDA);
168 |
169 | _DS = FP_SEG(SDA);
170 |
171 |
172 | _BX = 0x500;
173 |
174 | _AX = 0x20;
175 |
176 | geninterrupt(DOS_HELPER_INT);
177 |
178 |
179 | asm {
180 |
181 | pop ds
182 | }
183 |
184 | }
185 |
186 |
187 |
188 | /********************************************
189 | * RedirectDevice - redirect a device to a remote resource
190 | * ON ENTRY:
191 | * deviceStr has a string with the device name:
192 | * either disk or printer (ex. 'D:' or 'LPT1')
193 | * resourceStr has a string with the server and name of resource
194 | * (ex. 'TIM\TOOLS')
195 | * deviceType indicates the type of device being redirected
196 | * 3 = printer, 4 = disk
197 | * deviceParameter is a value to be saved with this redirection
198 | * which will be returned on GetRedirectionList
199 | * ON EXIT:
200 | * returns CC_SUCCESS if the operation was successful,
201 | * otherwise returns the DOS error code
202 | * NOTES:
203 | * deviceParameter is used in DOSEMU to return the drive attribute
204 | * It is not actually saved and returned as specified by the redirector
205 | * specification. This type of usage is common among commercial redirectors.
206 | ********************************************/
207 | uint16 RedirectDevice(char *deviceStr, char *resourceStr, uint8 deviceType,
208 | uint16 deviceParameter)
209 | {
210 |
211 | char slashedResourceStr[MAX_RESOURCE_PATH_LENGTH];
212 |
213 |
214 |
215 | /* prepend the resource string with slashes */
216 | strcpy(slashedResourceStr, "\\\\");
217 |
218 | strcat(slashedResourceStr, resourceStr);
219 |
220 |
221 | /* should verify strings before sending them down ??? */
222 | asm {
223 |
224 | push ds
225 | }
226 |
227 | _DS = FP_SEG(deviceStr);
228 |
229 | _SI = FP_OFF(deviceStr);
230 |
231 | _ES = FP_SEG(slashedResourceStr);
232 |
233 | _DI = FP_OFF(slashedResourceStr);
234 |
235 | _CX = deviceParameter;
236 |
237 | _BL = deviceType;
238 |
239 | _AX = DOS_REDIRECT_DEVICE;
240 |
241 | geninterrupt(0x21);
242 |
243 | asm {
244 |
245 | pop ds
246 | pushf
247 | pop dx
248 | }
249 |
250 | if (_DX & CARRY_FLAG) {
251 |
252 | return (_AX);
253 |
254 | }
255 | else {
256 |
257 | return (CC_SUCCESS);
258 |
259 | }
260 |
261 | }
262 |
263 |
264 |
265 | /********************************************
266 | * GetRedirection - get next entry from list of redirected devices
267 | * ON ENTRY:
268 | * redirIndex has the index of the next device to return
269 | * this should start at 0, and be incremented between calls
270 | * to retrieve all elements of the redirection list
271 | * ON EXIT:
272 | * returns CC_SUCCESS if the operation was successful, and
273 | * deviceStr has a string with the device name:
274 | * either disk or printer (ex. 'D:' or 'LPT1')
275 | * resourceStr has a string with the server and name of resource
276 | * (ex. 'TIM\TOOLS')
277 | * deviceType indicates the type of device which was redirected
278 | * 3 = printer, 4 = disk
279 | * deviceParameter has my rights to this resource
280 | * NOTES:
281 | *
282 | ********************************************/
283 | uint16 GetRedirection(uint16 redirIndex, char *deviceStr, char *resourceStr,
284 | uint8 * deviceType, uint16 * deviceParameter)
285 | {
286 |
287 | uint16 ccode;
288 |
289 | uint8 deviceTypeTemp;
290 |
291 | char slashedResourceStr[MAX_RESOURCE_PATH_LENGTH];
292 |
293 |
294 |
295 | asm {
296 |
297 | push ds
298 | }
299 |
300 | _DS = FP_SEG(deviceStr);
301 |
302 | _SI = FP_OFF(deviceStr);
303 |
304 | _ES = FP_SEG(slashedResourceStr);
305 |
306 | _DI = FP_OFF(slashedResourceStr);
307 |
308 | _BX = redirIndex;
309 |
310 | _AX = DOS_GET_REDIRECTION;
311 |
312 | asm {
313 |
314 | push bp
315 | int 21 h
316 | pop bp
317 | pushf
318 | pop dx /* get flags into DX */
319 | pop ds
320 | }
321 |
322 | ccode = _AX;
323 |
324 | deviceTypeTemp = _BL; /* save device type before C ruins it */
325 |
326 | *deviceType = deviceTypeTemp;
327 |
328 | *deviceParameter = _CX;
329 |
330 |
331 | /* copy back unslashed portion of resource string */
332 | if (_DX & CARRY_FLAG) {
333 |
334 | return (ccode);
335 |
336 | }
337 | else {
338 |
339 | /* eat the leading slashes */
340 | strcpy(resourceStr, slashedResourceStr + 2);
341 |
342 | return (CC_SUCCESS);
343 |
344 | }
345 |
346 | }
347 |
348 |
349 |
350 | /********************************************
351 | * CancelRedirection - delete a device mapped to a remote resource
352 | * ON ENTRY:
353 | * deviceStr has a string with the device name:
354 | * either disk or printer (ex. 'D:' or 'LPT1')
355 | * ON EXIT:
356 | * returns CC_SUCCESS if the operation was successful,
357 | * otherwise returns the DOS error code
358 | * NOTES:
359 | *
360 | ********************************************/
361 | uint16 CancelRedirection(char *deviceStr)
362 | {
363 |
364 | asm {
365 |
366 | push ds
367 | }
368 |
369 | _DS = FP_SEG(deviceStr);
370 |
371 | _SI = FP_OFF(deviceStr);
372 |
373 | _AX = DOS_CANCEL_REDIRECTION;
374 |
375 | geninterrupt(0x21);
376 |
377 | asm {
378 |
379 | pop ds
380 | pushf
381 | pop dx
382 | }
383 |
384 | if (_DX & CARRY_FLAG) {
385 |
386 | return (_AX);
387 |
388 | }
389 | else {
390 |
391 | return (CC_SUCCESS);
392 |
393 | }
394 |
395 | }
396 |
397 |
398 |
399 | /*************************************
400 | * ShowMyRedirections
401 | * show my current drive redirections
402 | * NOTES:
403 | * I show the read-only attribute for each drive
404 | * which is returned in deviceParam.
405 | *************************************/
406 | void
407 | ShowMyRedirections(void)
408 | {
409 |
410 |
411 | int driveCount;
412 |
413 |
414 | uint16 redirIndex, deviceParam, ccode;
415 |
416 | uint8 deviceType;
417 |
418 | char deviceStr[MAX_DEVICE_STRING_LENGTH];
419 |
420 |
421 | char resourceStr[MAX_RESOURCE_PATH_LENGTH];
422 |
423 |
424 |
425 | redirIndex = 0;
426 |
427 | driveCount = 0;
428 |
429 | ccode = GetRedirection(redirIndex, deviceStr, resourceStr,
430 | &deviceType, &deviceParam);
431 |
432 | while (ccode == CC_SUCCESS) {
433 |
434 | /* only print disk redirections here */
435 | if (deviceType == REDIR_DISK_TYPE) {
436 |
437 | if (driveCount == 0) {
438 |
439 | printf("Current Drive Redirections:\n");
440 |
441 | }
442 |
443 | driveCount++;
444 |
445 | printf("%-2s = %-20s ",
446 | deviceStr, resourceStr);
447 |
448 | /* read attribute is returned in the device parameter */
449 | if (deviceParam & 0x80) {
450 |
451 | printf("attrib = ");
452 |
453 | switch (deviceParam) {
454 |
455 | case READ_ONLY_DRIVE_ATTRIBUTE:
456 |
457 | printf("READ ONLY");
458 |
459 | break;
460 |
461 | default:
462 |
463 | printf("READ/WRITE");
464 |
465 | break;
466 |
467 |
468 | }
469 |
470 | }
471 |
472 | printf("\n");
473 |
474 | }
475 |
476 | redirIndex++;
477 |
478 | ccode = GetRedirection(redirIndex, deviceStr, resourceStr,
479 | &deviceType, &deviceParam);
480 |
481 | }
482 |
483 | if (driveCount == 0) {
484 |
485 | printf("No drives are currently redirected to Linux.\n");
486 |
487 | }
488 |
489 | }
490 |
491 |
492 |
493 | void
494 | DeleteDriveRedirection(char *deviceStr)
495 | {
496 |
497 | uint16 ccode;
498 |
499 |
500 | /* convert device string to upper case */
501 | strupr(deviceStr);
502 |
503 | ccode = CancelRedirection(deviceStr);
504 |
505 | if (ccode) {
506 |
507 | printf("Error %x canceling redirection on drive %s\n",
508 | ccode, deviceStr);
509 |
510 | }
511 | else {
512 |
513 | printf("Redirection for drive %s was deleted.\n", deviceStr);
514 |
515 | }
516 |
517 | }
518 |
519 |
520 |
521 | main(int argc, char **argv)
522 | {
523 |
524 | uint16 ccode;
525 |
526 | uint16 redirIndex, deviceParam;
527 |
528 | uint8 deviceType;
529 |
530 |
531 | char deviceStr[MAX_DEVICE_STRING_LENGTH];
532 |
533 |
534 | char resourceStr[MAX_RESOURCE_PATH_LENGTH];
535 |
536 |
537 |
538 | ccode = CheckForDOSEMU();
539 |
540 | if (ccode == 0) {
541 |
542 | printf("DOSEMU is not running. This program is intended for use\n");
543 |
544 | printf("only with the Linux DOS emulator.\n");
545 |
546 | exit(1);
547 |
548 | }
549 |
550 |
551 | /* initialize the MFS, just in case the user didn't run EMUFS.SYS */
552 | InitMFS();
553 |
554 |
555 | /* need to parse the command line */
556 | /* if no parameters, then just show current mappings */
557 | if (argc == 1) {
558 |
559 | ShowMyRedirections();
560 |
561 | exit(0);
562 |
563 | }
564 |
565 |
566 | if (strncmpi(argv[1], KEYWORD_DEL, KEYWORD_DEL_COMPARE_LENGTH) == 0) {
567 |
568 | DeleteDriveRedirection(argv[2]);
569 |
570 | exit(0);
571 |
572 | }
573 |
574 |
575 | if (strcmpi(argv[1], "HELP") == 0 || argv[1][0] == '?') {
576 |
577 | printf("Usage: LREDIR drive: PCEMU\\FS\\path [R]\n");
578 |
579 | printf(" redirect a drive to the Linux file system\n");
580 |
581 | printf(" if R is specified, the drive will be read-only.\n");
582 |
583 | printf(" LREDIR DEL drive:\n");
584 |
585 | printf(" delete a drive redirection\n");
586 |
587 | printf(" LREDIR\n");
588 |
589 | printf(" show current drive redirections\n");
590 |
591 | printf(" LREDIR HELP\n");
592 |
593 | printf(" show this help screen\n");
594 |
595 | exit(0);
596 |
597 | }
598 |
599 |
600 | /* assume the command is to redirect a drive */
601 | /* read the drive letter and resource string */
602 | strcpy(deviceStr, argv[1]);
603 |
604 | strcpy(resourceStr, argv[2]);
605 |
606 | deviceParam = DEFAULT_REDIR_PARAM;
607 |
608 | if (argc > 3) {
609 |
610 | if (toupper(argv[3][0]) == 'R') {
611 |
612 | deviceParam = 1;
613 |
614 | }
615 |
616 | }
617 |
618 |
619 | /* upper-case both strings */
620 | strupr(deviceStr);
621 |
622 | strupr(resourceStr);
623 |
624 |
625 | /* now actually redirect the drive */
626 | ccode = RedirectDevice(deviceStr, resourceStr, REDIR_DISK_TYPE,
627 | deviceParam);
628 |
629 | if (ccode) {
630 |
631 | printf("Error %x redirecting drive %s to %s\n",
632 | ccode, deviceStr, resourceStr);
633 |
634 | goto MainExit;
635 |
636 | }
637 |
638 | printf("Drive %s redirected to %s\n", deviceStr, resourceStr);
639 |
640 |
641 | MainExit:
642 | return (ccode);
643 |
644 | }
645 |
646 |
647 |
648 |
--------------------------------------------------------------------------------
/programs/lredir.readme:
--------------------------------------------------------------------------------
1 | From Tim Bird (Tim_R_Bird@Novell.COM) :
2 | (altered slightly by DH - changed 'LINUX\FS' to 'PCEMU\FS')
3 |
4 | LREDIR is a general purpose DOS redirection utility, specifically
5 | implemented for use with the Linux DOS emulator DOSEMU.
6 |
7 | In general, DOSEMU provides emulation of a DOS disk redirector via the
8 | MFS (Mach File System) module of the emulator. This support was originally
9 | derived from the redirector for the DOS emulator for Mach.
10 |
11 | DOS supports installable file systems by issueing callouts to a "redirector"
12 | on any functions it receives for files or drives that are registered
13 | with it as being non-local. The installable file system support is intended
14 | mainly for use by CD-ROM drivers and network clients, so that these file
15 | systems may be presented to the DOS user as additional drives. In DOSEMU,
16 | MFS uses this mechanism to present a section of the Linux file system to
17 | the DOS which is running in the emulator. This means that any subtree in
18 | the Linux file system may be redirected and designated as a drive letter
19 | under DOS for use in the emulator.
20 |
21 | In order for DOS to use redirected drives, it must be configured for
22 | additional drives. This is done by putting a "LASTDRIVE=Z" statement in
23 | the CONFIG.SYS that is used by the emulator upon loading DOS. You can set
24 | the LASTDRIVE to any letter of the alphabet. The default is F if none is
25 | specified, which means that DOS can only use letters A-F for drives. The
26 | example above configures all possible drive letters, A through Z, to be
27 | available for use by DOS (and is what I recommend). There is a slight
28 | memory penalty for configuring this many drives (about 1K of the
29 | conventional memory inside the emulator).
30 |
31 | To use LREDIR, MFS must first have been enabled using EMUFS.SYS. To do
32 | this, load EMUFS.SYS in your CONFIG.SYS, with a line like:
33 |
34 | device=C:\EMUFS.SYS /usr/src
35 |
36 | This will initialize the MFS redirector, and create one redirection
37 | automatically on the first available drive letter (usually D:). Although
38 | EMUFS.SYS can be loaded multiple times to get additional drives, I
39 | recommend that you only load it once, and use LREDIR to redirect more
40 | drives to other places in the Linux file system as needed.
41 |
42 | LREDIR can be used to create new redirections, get a list of the current
43 | redirections, or to delete a redirection. To create a new redirection,
44 | specify the drive letter to use, and the Linux file system path which
45 | will become the root of that drive. Since LREDIR is a general-purpose
46 | redirection utility, it has a generic syntax which allows it to be used
47 | with other redirectors besides MFS (like the NetWare Lite client, or
48 | DOS VLM NetWare client). The syntax is:
49 |
50 | LREDIR drive: server\volume\path
51 |
52 | For use with the Linux file system, we use PCEMU as the server name,
53 | FS as the volume name, and then specify a path from the root of the
54 | Linux file system as the location to redirect the drive to. For example:
55 |
56 | LREDIR F: PCEMU\FS\USR\SRC
57 |
58 | would create a new redirection for drive F:, where the contents of
59 | /usr/src would appear at the root of drive F:. Note that this establishes
60 | a root for drive F: which will be enforced by DOS. ie, drive F: cannot
61 | be used to access files in /usr or /usr/bin, because those Linux directories
62 | are not in the subtree under /usr/src.
63 |
64 | LREDIR allows you to redirect any drive available to DOS, including one
65 | that is currently a physical drive. This means that you can replace one of
66 | your startup drives with a redirection. When you delete the redirection,
67 | the physical drive will become visible again. This can be used so that
68 | the boot diskimage disappears, and is replaced by the mounted MSDOS
69 | file system in Linux, with the drive letter and root the same as before
70 | Linux was installed. For example on my system, I have a partition
71 | with a DOS file system on it. If I boot my machine with a DOS boot
72 | diskette, this partition is my C: drive in DOS. When I boot Linux, I mount
73 | this partition, using the msdos file system type, at location /dos/cdrive.
74 |
75 | For this to work right, you actually need two AUTOEXEC.BAT files, one on
76 | the boot diskimage, and one in the directory that will become the root
77 | of the redirected drive.
78 |
79 | In the AUTOEXEC.BAT in the boot diskimage I put the line:
80 |
81 | LREDIR C: PCEMU\FS\DOS\CDRIVE
82 |
83 | and when DOS runs in DOSEMU, it redirects drive C: to be replaced with
84 | the drive C: I booted from. Also, parsing of the AUTOEXEC.BAT file
85 | will continue with the AUTOEXEC.BAT (if any) on the redirected drive.
86 |
87 | People who use LREDIR in this way should be careful because COMMAND.COM
88 | will continue parsing the AUTOEXEC.BAT from the redirected drive at the
89 | same file offset where it left off in the AUTOEXEC.BAT on the original
90 | C: drive. For this reason, it is best to have the LREDIR command on the
91 | first line of the original (diskimage) AUTOEXEC.BAT, and have the line
92 | be identical in the AUTOEXEC.BAT on the redirected drive. Is this clear
93 | as mud?
94 |
95 |
--------------------------------------------------------------------------------
/programs/vga50.com:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidgiven/pcemu/88061c7ad5efd5343bb42d97f14756881bc97e4e/programs/vga50.com
--------------------------------------------------------------------------------
/vga.c:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is VGA.C It contains stuff about the VGA BIOS */
16 |
17 | #include "global.h"
18 |
19 | #include
20 | #include
21 |
22 | #include "vga.h"
23 | #include "bios.h"
24 | #include "cpu.h"
25 | #include "vgahard.h"
26 | #include "video.h"
27 | #include "hardware.h"
28 |
29 | #define MAXPAGES 8
30 |
31 | #define VIDEOFUNCTIONALITY 0x2000
32 |
33 | static BYTE *data_segment; /* pointer to 0040:0000 */
34 | static BYTE *screen_mem; /* pointer to screen memory */
35 |
36 | #define MAXMODE (sizeof defaults/sizeof defaults[0])
37 |
38 | static struct
39 | {
40 | int cs, ce;
41 | int sx, sy;
42 | int colours;
43 | int pages;
44 | int base;
45 | int text;
46 | } defaults[] =
47 | {
48 | { 6, 7, 40, 25, 16, 8, 0xb800, TRUE }, /* Mode 0x00 */
49 | { 6, 7, 40, 25, 16, 8, 0xb800, TRUE }, /* Mode 0x01 */
50 | { 6, 7, 80, 25, 16, 8, 0xb800, TRUE }, /* Mode 0x02 */
51 | { 6, 7, 80, 25, 16, 8, 0xb800, TRUE }, /* Mode 0x03 */
52 | { 0, 0, 320, 200, 4, 4, 0xb800, FALSE }, /* Mode 0x04 */
53 | { 0, 0, 320, 200, 4, 4, 0xb800, FALSE }, /* Mode 0x05 */
54 | { 0, 0, 640, 200, 2, 4, 0xb800, FALSE }, /* Mode 0x06 */
55 | { 11, 12, 80, 25, 2, 8, 0xb000, TRUE }, /* Mode 0x07 */
56 | { 0, 0, 0, 0, 0, 0, 0, FALSE }, /* Mode 0x08 */
57 | { 0, 0, 0, 0, 0, 0, 0, FALSE }, /* Mode 0x09 */
58 | { 0, 0, 0, 0, 0, 0, 0, FALSE }, /* Mode 0x0a */
59 | { 0, 0, 0, 0, 0, 0, 0, FALSE }, /* Mode 0x0b */
60 | { 0, 0, 0, 0, 0, 0, 0, FALSE }, /* Mode 0x0c */
61 | { 0, 0, 320, 200, 16, 8, 0xa000, FALSE },/* Mode 0x0d */
62 | { 0, 0, 640, 200, 16, 4, 0xa000, FALSE },/* Mode 0x0e */
63 | { 0, 0, 640, 350, 2, 2, 0xa000, FALSE }, /* Mode 0x0f */
64 | { 0, 0, 640, 350, 16, 2, 0xa000, FALSE },/* Mode 0x10 */
65 | { 0, 0, 640, 480, 2, 1, 0xa000, FALSE }, /* Mode 0x11 */
66 | { 0, 0, 640, 480, 16, 1, 0xa000, FALSE },/* Mode 0x12 */
67 | { 0, 0, 320, 200, 256, 1, 0xa000, FALSE },/* Mode 0x13 */
68 | };
69 |
70 | int mono; /* TRUE if on monochrome screen */
71 |
72 | /* Remember: screen height is stored one less than actual!!! */
73 |
74 | #define SetMode(m) PutMemB(data_segment, 0x49, m)
75 | #define GetMode() GetMemB(data_segment, 0x49)
76 | #define SetWidth(w) PutMemW(data_segment, 0x4a, w)
77 | #define GetWidth() GetMemW(data_segment, 0x4a)
78 | #define SetHeight(h) PutMemB(data_segment, 0x84, h)
79 | #define GetHeight() GetMemB(data_segment, 0x84)
80 | #define SetSize(s) PutMemW(data_segment, 0x4c, s)
81 | #define GetSize() GetMemW(data_segment, 0x4c)
82 | #define SetOffset(o) PutMemW(data_segment, 0x4e, o)
83 | #define GetOffset() GetMemW(data_segment, 0x4e)
84 | #define SetCx(page,cx) PutMemB(data_segment, 0x50+(page << 1), cx)
85 | #define GetCx(page) GetMemB(data_segment, 0x50+(page << 1))
86 | #define SetCy(page,cy) PutMemB(data_segment, 0x51+(page << 1), cy)
87 | #define GetCy(page) GetMemB(data_segment, 0x51+(page << 1))
88 | #define SetCs(s) PutMemB(data_segment, 0x61, s)
89 | #define GetCs() GetMemB(data_segment, 0x61)
90 | #define SetCe(s) PutMemB(data_segment, 0x60, s)
91 | #define GetCe() GetMemB(data_segment, 0x60)
92 | #define SetCp(cp) PutMemB(data_segment, 0x62, cp)
93 | #define GetCp() GetMemB(data_segment, 0x62)
94 | #define GetCRT() GetMemW(data_segment, 0x63)
95 | #define SetCRT(c) PutMemW(data_segment, 0x63, c)
96 | #define SetCharHeight(c) PutMemW(data_segment, 0x85, c)
97 | #define GetCharHeight() GetMemW(data_segment, 0x85)
98 |
99 | static int cur_emulate = TRUE;
100 | static int pages; /* Maximum number of pages */
101 |
102 | #define page_start(page) &screen_mem[GetSize()*(page)]
103 |
104 |
105 | static BYTE functionality[] =
106 | {
107 | 0xff, /* Modes 0->7 supported */
108 | 0x00, /* Modes 8->0x0f not supported yet */
109 | 0x00, /* Modes 0x10->0x13 not supported yet */
110 | 0,0,0,0, /* Reserved bytes */
111 | 0x04, /* Only 400 scan lines supported at the moment */
112 | 0x01, /* Character blocks */
113 | 0x01, /* Number of active character blocks */
114 | 0x04+0x08+0x16, /* Various functions */
115 | 0x04+0x08, /* ditto */
116 | 0,0, /* Reserved */
117 | 0x00, /* Various saved things */
118 | 0x00, /* Reserved */
119 | };
120 |
121 |
122 | static BYTE *get_offset(int page)
123 | {
124 | return &screen_mem[(GetSize() * page) + (2 * (GetCx(page) +
125 | GetCy(page)*GetWidth()))];
126 | }
127 |
128 |
129 | static void clearscr(int x1,int y1,int x2,int y2,int attr)
130 | {
131 | BYTE *scr = &screen_mem[GetOffset()];
132 | int x,y;
133 | unsigned width = GetWidth();
134 |
135 | for (y = y1; y <= y2; y++)
136 | {
137 | for (x = x1; x <= x2; x++)
138 | {
139 | scr[2*(x+y*width)] = ' ';
140 | scr[2*(x+y*width)+1] = (BYTE)attr;
141 | }
142 | }
143 | update_display();
144 | }
145 |
146 |
147 | static void scroll(int x1, int y1, int x2, int y2, int num, int attr)
148 | {
149 | int x,y;
150 | unsigned width = GetWidth();
151 | BYTE *scr;
152 |
153 | if (x1 > x2 || y1 > y2)
154 | return;
155 |
156 | scr = &screen_mem[GetOffset()];
157 |
158 | if (num == 0 || y2-y1 < abs(num))
159 | {
160 | clearscr(x1,y1,x2,y2, attr);
161 | return;
162 | }
163 |
164 | if (num > 0)
165 | {
166 | disable(); /* To prevent occasional screen glitch */
167 | for (y = y1; y <= y2-num; y++)
168 | for (x = x1; x <= x2; x++)
169 | {
170 | scr[2*(x+y*width)] = scr[2*(x+(y+num)*width)];
171 | scr[2*(x+y*width)+1] = scr[2*(x+(y+num)*width)+1];
172 | }
173 | y = y2-num+1;
174 | copy_text(x1,y1+num,x2,y2,x1,y1);
175 | enable();
176 | }
177 | else
178 | {
179 | num = -num;
180 | disable(); /* To prevent occasional screen glitch */
181 | for (y = y2-num; y >= y1; y--)
182 | for (x = x1; x <= x2; x++)
183 | {
184 | scr[2*(x+(y+num)*width)] = scr[2*(x+y*width)];
185 | scr[2*(x+(y+num)*width)+1] = scr[2*(x+y*width)+1];
186 | }
187 | y = y1;
188 | copy_text(x1,y1,x2,y2-num,x1,y1+num);
189 | enable();
190 | }
191 | clearscr(x1,y,x2,y+num-1,attr);
192 | }
193 |
194 |
195 | void set_cursor_type(unsigned start, unsigned end)
196 | {
197 | if (start == 0x20)
198 | set_cursor_height(0, -1);
199 | else
200 | {
201 | start &= 0x1f;
202 | end &= 0x1f;
203 |
204 | SetCs(start);
205 | SetCe(end);
206 | if (cur_emulate && GetMode() <= 3 && start <= 8 && end <= 8)
207 | {
208 | start = (GetCharHeight()*start)/8;
209 | end = (GetCharHeight()*end)/8;
210 | }
211 | set_cursor_height(start, end);
212 | }
213 | }
214 |
215 |
216 | static void set_mode(int mode)
217 | {
218 | if (mode < MAXMODE)
219 | {
220 | if (!mono || (defaults[mode].colours <= 2 && mono))
221 | {
222 | int i;
223 |
224 | if (!defaults[mode].text)
225 | return;
226 | SetMode(mode);
227 | SetWidth(defaults[mode].sx);
228 | SetHeight(defaults[mode].sy-1);
229 | SetSize(defaults[mode].sx * defaults[mode].sy * 2);
230 | SetCp(0);
231 | SetOffset(0);
232 | if (mode == 0x7)
233 | SetCRT(0x3b4);
234 | else
235 | SetCRT(0x3d4);
236 | pages = defaults[mode].pages;
237 | for (i = 0; i < pages; i++)
238 | {
239 | SetCx(i,0);
240 | SetCy(i,0);
241 | }
242 | SetCharHeight(16);
243 | set_cursor_type(defaults[mode].cs,defaults[mode].ce);
244 | move_cursor(0, 0);
245 | screen_mem = &memory[defaults[mode].base << 4];
246 | new_screen(GetWidth(), GetHeight()+1, screen_mem);
247 | }
248 | }
249 | }
250 |
251 |
252 | static void display_message(void)
253 | {
254 | static char message1[] =
255 | "PC Emulator v1.01alpha (C) 1994 University of Bristol";
256 | static char message2[] =
257 | "Please report comments, bugs etc to hedley@cs.bris.ac.uk";
258 | BYTE *mem = get_offset(0);
259 | int i;
260 |
261 | disable();
262 |
263 | for (i = 0; i < sizeof message1-1; i++)
264 | mem[i<<1] = message1[i];
265 |
266 | for (i = 0; i < sizeof message2-1; i++)
267 | mem[(i+80)<<1] = message2[i];
268 |
269 | SetCx(0, 0);
270 | SetCy(0, 4);
271 | move_cursor(GetCx(0),GetCy(0));
272 | enable();
273 |
274 | }
275 |
276 |
277 | static void fill_in_functionality(void)
278 | {
279 | WORD tmp = ChangeE(wregs[DI]);
280 | PutMemW(c_es, tmp, VIDEOFUNCTIONALITY);
281 | tmp += 2;
282 | PutMemW(c_es, tmp, 0xf000);
283 | tmp += 2;
284 | PutMemB(c_es, tmp, GetMode());
285 | tmp++;
286 | PutMemW(c_es, tmp, GetWidth());
287 | tmp += 2;
288 | PutMemW(c_es, tmp, GetSize());
289 | tmp += 2;
290 | PutMemW(c_es, tmp, GetSize() * GetCp());
291 | tmp += 2;
292 |
293 | PutMemB(c_es, tmp, GetCy(0));
294 | tmp++;
295 | PutMemB(c_es, tmp, GetCx(0));
296 | tmp++;
297 | PutMemB(c_es, tmp, GetCy(1));
298 | tmp++;
299 | PutMemB(c_es, tmp, GetCx(1));
300 | tmp++;
301 | PutMemB(c_es, tmp, GetCy(2));
302 | tmp++;
303 | PutMemB(c_es, tmp, GetCx(2));
304 | tmp++;
305 | PutMemB(c_es, tmp, GetCy(3));
306 | tmp++;
307 | PutMemB(c_es, tmp, GetCx(3));
308 | tmp++;
309 | PutMemB(c_es, tmp, GetCy(4));
310 | tmp++;
311 | PutMemB(c_es, tmp, GetCx(4));
312 | tmp++;
313 | PutMemB(c_es, tmp, GetCy(5));
314 | tmp++;
315 | PutMemB(c_es, tmp, GetCx(5));
316 | tmp++;
317 | PutMemB(c_es, tmp, GetCy(6));
318 | tmp++;
319 | PutMemB(c_es, tmp, GetCx(6));
320 | tmp++;
321 | PutMemB(c_es, tmp, GetCy(7));
322 | tmp++;
323 | PutMemB(c_es, tmp, GetCx(7));
324 | tmp++;
325 |
326 | PutMemB(c_es, tmp, GetCs());
327 | tmp++;
328 | PutMemB(c_es, tmp, GetCe());
329 | tmp++;
330 | PutMemB(c_es, tmp, GetCp());
331 | tmp++;
332 |
333 | PutMemW(c_es, tmp, GetCRT());
334 | tmp += 2;
335 |
336 | PutMemB(c_es, tmp, 0);
337 | tmp++;
338 | PutMemB(c_es, tmp, 0);
339 | tmp++;
340 |
341 | PutMemB(c_es, tmp, GetHeight()+1);
342 | tmp++;
343 | PutMemW(c_es, tmp, GetCharHeight());
344 | tmp += 2;
345 | PutMemB(c_es, tmp, mono ? 7 : 8);
346 | tmp++;
347 | PutMemB(c_es, tmp, 0);
348 | tmp++;
349 | PutMemW(c_es, tmp, mono ? 0 : 256);
350 | tmp += 2;
351 | PutMemB(c_es, tmp, defaults[GetMode()].pages);
352 | tmp++;
353 | PutMemB(c_es, tmp, 0x02);
354 | tmp++;
355 | PutMemB(c_es, tmp, 0);
356 | tmp++;
357 | PutMemB(c_es, tmp, 0);
358 | tmp++;
359 | PutMemB(c_es, tmp, mono ? 4 : 0);
360 | tmp++;
361 | PutMemW(c_es, tmp, 0);
362 | tmp += 2;
363 | PutMemB(c_es, tmp, 0);
364 | tmp++;
365 | PutMemB(c_es, tmp, 3);
366 | tmp++;
367 | PutMemB(c_es, tmp, 1);
368 | }
369 |
370 |
371 | void int_video(void)
372 | {
373 | unsigned page, al;
374 | unsigned height, width;
375 |
376 | D(printf("In Video. Function = %02X\n", *bregs[AH]););
377 |
378 | CalcAll();
379 | page = *bregs[BH];
380 | al = *bregs[AL];
381 | height = GetHeight();
382 | width = GetWidth()-1;
383 |
384 | switch(*bregs[AH])
385 | {
386 | case 0: /* Set mode */
387 | set_mode(al & 0x7f);
388 | if ((al & 0x80) == 0)
389 | clearscr(0,0,width, height, 0x07);
390 | break;
391 | case 1: /* Set cursor type */
392 | set_cursor_type(*bregs[CH], *bregs[CL]);
393 | break;
394 | case 2: /* Move cursor position */
395 | if (page < pages)
396 | {
397 | SetCx(page, *bregs[DL]);
398 | SetCy(page, *bregs[DH]);
399 | move_cursor(GetCx(page),GetCy(page));
400 | }
401 | break;
402 | case 3: /* Get cursor position */
403 | if (page < pages)
404 | {
405 | *bregs[CH] = GetCs();
406 | *bregs[CL] = GetCe();
407 | *bregs[DL] = GetCx(page);
408 | *bregs[DH] = GetCy(page);
409 | }
410 | break;
411 | case 4: /* Light pen (!) */
412 | *bregs[AH] = 0;
413 | wregs[BX] = wregs[CX] = wregs[DX] = 0;
414 | break;
415 | case 5: /* Set display page */
416 | if (al < pages)
417 | {
418 | SetCp(al);
419 | SetOffset(al*GetSize());
420 | new_screen(width+1, height+1, page_start(al));
421 | update_display();
422 | }
423 | break;
424 | case 6: /* Scroll down/clear window */
425 | scroll(*bregs[CL], *bregs[CH], *bregs[DL], *bregs[DH], al, *bregs[BH]);
426 | break;
427 | case 7: /* Scroll up/clear window */
428 | scroll(*bregs[CL], *bregs[CH], *bregs[DL], *bregs[DH], -al,*bregs[BH]);
429 | break;
430 | case 8: /* Read character and attribute at cursor */
431 | if (page < pages)
432 | {
433 | BYTE *pos = get_offset(page);
434 |
435 | *bregs[AL] = *pos++;
436 | *bregs[AH] = *pos;
437 | }
438 | break;
439 | case 9: /* Write character(s) and attribute(s) at cursor */
440 | if (page < pages)
441 | {
442 | BYTE *pos = get_offset(page);
443 | unsigned i, count;
444 |
445 | count = ChangeE(wregs[CX]);
446 | for (i = count; i > 0; i--)
447 | {
448 | *pos++ = al;
449 | *pos++ = *bregs[BL];
450 | }
451 | if (count > 1)
452 | update_display();
453 | else
454 | if (count == 1)
455 | displaychar();
456 | }
457 | break;
458 | case 0x0a: /* Write character at cursor */
459 | if (page < pages)
460 | {
461 | BYTE *pos = get_offset(page);
462 | unsigned i, count;
463 |
464 | count = ChangeE(wregs[CX]);
465 | for (i = count; i > 0; i--)
466 | *pos++ = al;
467 |
468 | if (count > 1)
469 | update_display();
470 | else
471 | if (count == 1)
472 | displaychar();
473 | }
474 | break;
475 |
476 | case 0x0b: /* Set palette/background/border */
477 | break;
478 | case 0x0e: /* Write character in teletype mode */
479 | if (page < pages)
480 | {
481 | BYTE *pos = get_offset(page);
482 | int x,y;
483 |
484 | x = GetCx(page);
485 | y = GetCy(page);
486 | switch(al)
487 | {
488 | case 0x0a: /* Line feed */
489 | y++;
490 | break;
491 | case 0x0d: /* Return */
492 | x = 0;
493 | break;
494 | case 0x8: /* Backspace */
495 | x--;
496 | break;
497 | case 0x7: /* Bell */
498 | fprintf(stderr,"\a");
499 | fflush(stderr);
500 | break;
501 | default:
502 | *pos = al;
503 | x++;
504 | displaychar();
505 | }
506 | if (x > width)
507 | {
508 | x = 0;
509 | y++;
510 | }
511 | if (x < 0)
512 | {
513 | x = width;
514 | y--;
515 | }
516 | if (y > height)
517 | {
518 | BYTE attr;
519 | y = height;
520 | attr = screen_mem[GetSize()*(page+1) -1];
521 | scroll(0,0,width,y,1,attr);
522 | }
523 | if (y < 0)
524 | {
525 | y = 0;
526 | scroll(0,0,width,height,-1,7);
527 | }
528 | SetCx(page,x);
529 | SetCy(page,y);
530 | move_cursor(x,y);
531 | }
532 | break;
533 | case 0x0f: /* Return information */
534 | *bregs[AL] = GetMode();
535 | *bregs[AH] = width+1;
536 | *bregs[BH] = GetCp();
537 | break;
538 | case 0x10: /* Colour/palette stuff... */
539 | break;
540 | case 0x11: /* Font stuff... */
541 | switch(*bregs[AL])
542 | {
543 | case 0x02: /* Load rom 8x8 font (set 50/42 lines) */
544 | case 0x12:
545 | height = 49;
546 | SetHeight(height);
547 | SetSize((width+1) * (height+1) * 2);
548 | new_screen(width+1, height+1, screen_mem);
549 | clearscr(0,0,width, height, 0x07);
550 | break;
551 | case 0x30: /* Get font information */
552 | switch(*bregs[BH])
553 | {
554 | default:
555 | wregs[CX] = ChangeE(16);
556 | *bregs[DL] = height;
557 | sregs[ES] = 0xf000;
558 | c_es = SegToMemPtr(ES);
559 | wregs[BP] = ChangeE(0);
560 | }
561 | break;
562 | default:
563 | printf("Unimplemented int 0x10 function 0x11 sub-function %02X\n",*bregs[AL]);
564 | #ifdef DEBUG
565 | loc();
566 | exit_emu();
567 | #endif
568 | break;
569 | }
570 | break;
571 | case 0x12: /* Display information */
572 | switch(*bregs[BL])
573 | {
574 | case 0x10: /* Get config info */
575 | *bregs[BH] = mono;
576 | *bregs[BL] = 3;
577 | wregs[CX] = ChangeE(0);
578 | break;
579 | case 0x30: /* Set scan lines */
580 | *bregs[AL] = 0x12;
581 | break;
582 | case 0x34: /* Enable/disable cursor emulation */
583 | cur_emulate = *bregs[AL] == 0;
584 | *bregs[AL] = 0x12;
585 | break;
586 | default:
587 | printf("Unimplemented int 10 function 0x12 sub-function 0x%02X\n",*bregs[BL]);
588 | #ifdef DEBUG
589 | loc();
590 | exit_emu();
591 | #endif
592 | break;
593 | }
594 | break;
595 | case 0x1a: /* Get/Set display combination */
596 | if (*bregs[AL] == 0)
597 | {
598 | *bregs[BL] = mono ? 7 : 8;
599 | *bregs[BH] = 0;
600 | *bregs[AL] = 0x1a;
601 | }
602 | break;
603 | case 0x1b: /* Get functionality/state information etc */
604 | fill_in_functionality();
605 | *bregs[AL] = 0x1b;
606 | break;
607 | case 0x30: /* ??? Called by MSD.EXE */
608 | case 0x4f: /* VESA functions... */
609 | case 0x6f: /* ??? Called by borland C */
610 | case 0xcc: /* ??? Called by Norton's disk edit */
611 | case 0xef: /* ??? Called by QBASIC.EXE */
612 | case 0xfa: /* ??? Called by MSD.EXE (Microsoft Diagonstics) */
613 | case 0xfe: /* ??? - but several programs call it. Appears to do nothing */
614 | case 0xff: /* ??? Called by WordPerfect 5.1 */
615 | break;
616 | default:
617 | printf("Unimplemented int 10 function: %02X. AL = %02X BL = %02X\n",
618 | *bregs[AH], *bregs[AL], *bregs[BL]);
619 | #ifdef DEBUG
620 | loc();
621 | exit_emu();
622 | #endif
623 | break;
624 | }
625 | }
626 |
627 | void init_vga(void)
628 | {
629 | int mode = mono ? 7 : 3;
630 | static BYTE afterint[] =
631 | {
632 | 0xfb, 0xca, 0x02, 0x00
633 | };
634 |
635 | init_hardware();
636 |
637 | screen_mem = &memory[defaults[mode].base << 4];
638 | data_segment = &memory[0x00400];
639 |
640 | memcpy(&memory[0xf0000+VIDEOFUNCTIONALITY], &functionality, sizeof functionality);
641 |
642 | set_mode(mode);
643 | clearscr(0,0,GetWidth()-1, GetHeight(), 0x07);
644 | set_int(0x10, NULL, 0, int_video, afterint, sizeof afterint);
645 | display_message();
646 | }
647 |
648 | void vga_off(void)
649 | {
650 | finish_hardware();
651 | }
652 |
--------------------------------------------------------------------------------
/vga.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is VGA.H It contains definitions for the VGA BIOS functions */
16 |
17 |
18 | #ifndef VGA_H
19 | #define VGA_H
20 |
21 | #define VIDEOMEM (256*1024)
22 |
23 | extern int mono;
24 |
25 | void init_vga(void);
26 | void vga_off(void);
27 |
28 | #endif
29 |
--------------------------------------------------------------------------------
/vga.pcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidgiven/pcemu/88061c7ad5efd5343bb42d97f14756881bc97e4e/vga.pcf
--------------------------------------------------------------------------------
/vgahard.c:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is VGA.C It contains stuff about the VGA hardware adapter */
16 |
17 | #include "global.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #include "vga.h"
25 | #include "vgahard.h"
26 | #include "video.h"
27 | #include "hardware.h"
28 |
29 | #ifndef CURSORSPEED
30 | #define CURSORSPEED 30
31 | #endif
32 |
33 | #ifndef UPDATESPEED
34 | #define UPDATESPEED 5
35 | #endif
36 |
37 | #define BUFFER_DELAY 5
38 |
39 | static BYTE *screen_mem; /* pointer to screen memory */
40 |
41 | extern int mono; /* TRUE if on monochrome screen */
42 |
43 | static unsigned cx,cy; /* cursor position */
44 | static int cs,ce; /* cursor start/end (height) */
45 | static int height, width; /* screen size */
46 |
47 | static volatile int busy = 0;
48 |
49 | static volatile int cursoron = FALSE;
50 |
51 | static unsigned tick_count;
52 | static unsigned chars_printed;
53 | static unsigned cursor_printed;
54 |
55 | static volatile int refresh_count = 1;
56 | static volatile int cursor_count = 1;
57 |
58 | static int refresh_speed = UPDATESPEED;
59 | static int cursor_speed = CURSORSPEED;
60 |
61 | static BYTE *disp_buffer;
62 | static BYTE *frame_buffer;
63 |
64 |
65 | static void toggle_cursor(void)
66 | {
67 | busy = TRUE;
68 | cursoron = !cursoron;
69 |
70 | if (cursoron)
71 | put_cursor(cx, cy);
72 | else
73 | unput_cursor();
74 |
75 | busy = FALSE;
76 | }
77 |
78 |
79 | static void blank_cursor(void)
80 | {
81 | if (cursoron)
82 | {
83 | cursoron = FALSE;
84 | unput_cursor();
85 | }
86 | }
87 |
88 |
89 | static void draw_cursor(void)
90 | {
91 | if (!cursoron)
92 | {
93 | if (cx < width && cy < height && ce > cs)
94 | {
95 | cursoron = TRUE;
96 | put_cursor(cx,cy);
97 | }
98 | }
99 | }
100 |
101 |
102 | void move_cursor(unsigned x, unsigned y)
103 | {
104 | static unsigned last_count;
105 |
106 | busy = TRUE;
107 | cx = x;
108 | cy = y;
109 |
110 | if (cursor_printed >= 1 && tick_count >= last_count &&
111 | tick_count < last_count+BUFFER_DELAY)
112 | {
113 | last_count = tick_count;
114 | }
115 | else
116 | {
117 | last_count = tick_count;
118 | cursor_printed++;
119 |
120 | blank_cursor();
121 | draw_cursor();
122 | }
123 |
124 | busy = FALSE;
125 | }
126 |
127 |
128 | void copy_text(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
129 | unsigned nx, unsigned ny)
130 | {
131 | unsigned w,h, bwidth, bheight;
132 | BYTE *src,*dest;
133 |
134 | busy = TRUE;
135 | blank_cursor();
136 | copy(x1,y1,x2,y2,nx,ny);
137 |
138 | bwidth = x2-x1+1;
139 | bheight = y2-y1+1;
140 |
141 | if ((ny > y1 && nx >= x1) || (ny >= y1 && nx < x1))
142 | {
143 | dest = &frame_buffer[2*((ny+bheight)*width+(nx+bwidth))];
144 | src = &frame_buffer[2*(y2*width+x2)];
145 |
146 | for (h = bheight; h > 0; h--)
147 | {
148 | for (w = 2*bwidth; w > 0; w--)
149 | *--dest = *--src;
150 |
151 | dest -= (width-bwidth);
152 | src -= (width-bwidth);
153 | }
154 | }
155 | else
156 | {
157 | dest = &frame_buffer[2*(ny*width+nx)];
158 | src = &frame_buffer[2*(y1*width+x1)];
159 |
160 | for (h = bheight; h > 0; h--)
161 | {
162 | for (w = 2*bwidth; w > 0; w--)
163 | *dest++ = *src++;
164 |
165 | dest += (width-bwidth);
166 | src += (width-bwidth);
167 | }
168 | }
169 |
170 | draw_cursor();
171 | busy = FALSE;
172 | }
173 |
174 |
175 | void set_cursor_height(int s, int e)
176 | {
177 | busy = TRUE;
178 | cs = s;
179 | ce = e;
180 | blank_cursor();
181 | new_cursor(s, e);
182 | draw_cursor();
183 | busy = FALSE;
184 | }
185 |
186 |
187 | void new_screen(unsigned w, unsigned h, BYTE *mem)
188 | {
189 | busy = TRUE;
190 |
191 | screen_mem = mem;
192 | if (width != w || height != h)
193 | {
194 | if (width != w)
195 | {
196 | if (disp_buffer)
197 | free(disp_buffer);
198 |
199 | width = w;
200 | disp_buffer = (BYTE *)malloc(width+1);
201 | disp_buffer[width] = '\0';
202 | }
203 |
204 | if (frame_buffer)
205 | free(frame_buffer);
206 |
207 | height = h;
208 | frame_buffer = (BYTE *)malloc(width*height*2+1);
209 | memset(frame_buffer, 0, width*height*2);
210 |
211 | window_size(width, height);
212 | }
213 | busy = FALSE;
214 | }
215 |
216 |
217 | void update_display(void)
218 | {
219 | register BYTE *scr = frame_buffer;
220 | register BYTE *mem = screen_mem;
221 | unsigned row,col,startcol;
222 | BYTE *end;
223 | BYTE *bufptr;
224 | BYTE attr;
225 |
226 | busy = TRUE;
227 |
228 | end = &scr[width*height*2];
229 | *end = mem[width*height*2]+1;
230 |
231 | for(;;)
232 | {
233 | while (*scr == *mem)
234 | {
235 | scr++;
236 | mem++;
237 | }
238 |
239 | if (scr == end)
240 | break;
241 |
242 | blank_cursor();
243 |
244 | col = (scr-frame_buffer) % (2*width);
245 | row = (scr-frame_buffer) / (2*width);
246 |
247 | bufptr = disp_buffer;
248 | startcol = col >> 1;
249 |
250 | if (col & 1)
251 | {
252 | attr = *mem;
253 | col--;
254 | scr--;
255 | mem--;
256 | }
257 | else
258 | attr = mem[1];
259 |
260 | do
261 | {
262 | *bufptr++ = (*scr++ = *mem) ? *mem : 0x20;
263 | *scr++ = attr;
264 | mem += 2;
265 | col += 2;
266 | } while((*scr != *mem || scr[1] != mem[1]) && mem[1] == attr &&
267 | col < 2*width);
268 |
269 | draw_line(startcol, row,(char *)disp_buffer, bufptr-disp_buffer, attr);
270 | }
271 |
272 | if (cursor_speed <= 0)
273 | draw_cursor();
274 | busy = FALSE;
275 | }
276 |
277 |
278 | static void update_displayline(unsigned line)
279 | {
280 | unsigned x, startcol;
281 | BYTE *scr, *buf, *mem, attr;
282 |
283 | mem = &screen_mem[line*width*2];
284 | scr = &frame_buffer[line*width*2];
285 |
286 | busy = TRUE;
287 | blank_cursor();
288 |
289 | x = 0;
290 | while (x < width)
291 | {
292 | buf = disp_buffer;
293 | attr = mem[1];
294 |
295 | startcol = x;
296 | do
297 | {
298 | *buf++ = (*scr++ = *mem) ? *mem : 0x20;
299 | mem++;
300 | *scr++ = *mem++;
301 | x++;
302 | } while (x < width && mem[1] == attr);
303 |
304 | draw_line(startcol, line, (char *)disp_buffer, buf-disp_buffer, attr);
305 | }
306 | draw_cursor();
307 | busy = FALSE;
308 | }
309 |
310 |
311 | void pcemu_refresh(void)
312 | {
313 | unsigned h;
314 |
315 | for (h = 0; h < height; h++)
316 | update_displayline(h);
317 | }
318 |
319 |
320 | void displaychar(void)
321 | {
322 | BYTE *mem;
323 | static unsigned last_count;
324 |
325 | if (chars_printed >= 1 && tick_count >= last_count &&
326 | tick_count < last_count+BUFFER_DELAY)
327 | {
328 | last_count = tick_count;
329 | return;
330 | }
331 |
332 | last_count = tick_count;
333 | chars_printed++;
334 |
335 | mem = &screen_mem[2*(cx+cy*width)];
336 |
337 | /* frame_buffer[2*(cx+cy*width)] = *mem;
338 | frame_buffer[2*(cx+cy*width)+1] = mem[1];
339 | */
340 |
341 | busy = TRUE;
342 | /* blank_cursor(); */
343 | update_display();
344 | /* draw_char(cx, cy, *mem, mem[1]); */
345 | busy = FALSE;
346 | }
347 |
348 |
349 | void init_hardware(void)
350 | {
351 | busy = TRUE;
352 | set_cursor_height(14,15);
353 | busy = FALSE;
354 | }
355 |
356 |
357 | void finish_hardware(void)
358 | {
359 | busy = TRUE;
360 | end_video();
361 | busy = FALSE;
362 | }
363 |
364 |
365 | void vga_interrupt(void)
366 | {
367 | tick_count++;
368 | if (!busy)
369 | {
370 | process_events();
371 | if (cursor_speed > 0 && --cursor_count == 0)
372 | {
373 | cursor_count = cursor_speed;
374 | toggle_cursor();
375 | }
376 | if (--refresh_count == 0)
377 | {
378 | refresh_count = refresh_speed;
379 | chars_printed = 0;
380 | cursor_printed = 0;
381 | update_display();
382 | flush_video();
383 | }
384 | }
385 | }
386 |
387 |
388 | char *set_update_rate(int frames)
389 | {
390 | if (frames > 0)
391 | {
392 | refresh_speed = frames;
393 | return NULL;
394 | }
395 |
396 | return "Invalid update speed";
397 | }
398 |
399 |
400 | char *set_cursor_rate(int frames)
401 | {
402 | cursor_speed = frames;
403 | return NULL;
404 | }
405 |
406 |
407 |
408 |
--------------------------------------------------------------------------------
/vgahard.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | /* This is VGAHARD.H It contains definitions for the VGA hardware */
16 |
17 |
18 | #ifndef VGAHARD_H
19 | #define VGAHARD_H
20 |
21 | #include "mytypes.h"
22 |
23 | void new_screen(unsigned, unsigned, BYTE *);
24 | void pcemu_refresh(void);
25 | void update_display(void);
26 | void displaychar(void);
27 | void move_cursor(unsigned, unsigned);
28 | void set_cursor_height(int, int);
29 | void init_hardware(void);
30 | void finish_hardware(void);
31 | void copy_text(unsigned, unsigned, unsigned, unsigned, unsigned, unsigned);
32 |
33 | void vga_interrupt(void);
34 |
35 | char *set_update_rate(int);
36 | char *set_cursor_rate(int);
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/video.c:
--------------------------------------------------------------------------------
1 | #include "global.h"
2 | #include "video.h"
3 | #include
4 |
5 | VIDEO_DRIVER *video_driver;
6 |
7 | void put_cursor(unsigned x, unsigned y)
8 | {
9 | video_driver->put_cursor(x, y);
10 | }
11 |
12 | void unput_cursor(void)
13 | {
14 | video_driver->unput_cursor();
15 | }
16 |
17 | extern VIDEO_DRIVER curses_video;
18 | extern VIDEO_DRIVER x_video;
19 |
20 | static VIDEO_DRIVER *modes[] = {
21 | #ifndef DISABLEX
22 | &x_video,
23 | #endif
24 | #ifndef DISABLECURSES
25 | &curses_video
26 | #endif
27 | };
28 |
29 | #define NUM_MODES (sizeof(modes)/sizeof(*modes))
30 |
31 | const char *set_video_mode(const char *mode)
32 | {
33 | int i;
34 | for (i=0; iname, mode)) {
36 | video_driver = modes[i];
37 | return NULL;
38 | }
39 | }
40 | return "Invalid video mode.";
41 | }
42 |
43 | void init_video(void)
44 | {
45 | if (video_driver == NULL)
46 | video_driver = modes[0];
47 | video_driver->init();
48 | }
49 |
50 | void copy(unsigned x1, unsigned y1, unsigned x2, unsigned y2, unsigned newx, unsigned newy)
51 | {
52 | video_driver->copy(x1, y1, x2, y2, newx, newy);
53 | }
54 |
55 | void new_cursor(int st, int end)
56 | {
57 | video_driver->new_cursor(st, end);
58 | }
59 |
60 | void window_size(unsigned width, unsigned height)
61 | {
62 | video_driver->window_size(width, height);
63 | }
64 |
65 | void draw_line(unsigned x, unsigned y, const char *text, unsigned len, BYTE attr)
66 | {
67 | video_driver->draw_line(x, y, text, len, attr);
68 | }
69 |
70 | void end_video(void)
71 | {
72 | video_driver->end();
73 | }
74 |
75 | void process_events(void)
76 | {
77 | video_driver->process_events();
78 | }
79 |
80 | void flush_video(void)
81 | {
82 | video_driver->flush();
83 | }
84 |
--------------------------------------------------------------------------------
/video.h:
--------------------------------------------------------------------------------
1 | /* Simple abstraction to the video driver.
2 | The video driver is already very simple.
3 | */
4 | #ifndef VIDEO_INCLUDE
5 | #define VIDEO_INCLUDE
6 |
7 | typedef struct
8 | {
9 | const char *name;
10 | void (*init)(void);
11 | void (*end)(void);
12 | void (*flush)(void);
13 | void (*put_cursor)(unsigned x, unsigned y);
14 | void (*unput_cursor)(void);
15 | void (*copy)(unsigned x1, unsigned y1, unsigned x2, unsigned y2, unsigned newx, unsigned newy);
16 | void (*new_cursor)(int st, int end);
17 | void (*window_size)(unsigned width, unsigned height);
18 | void (*draw_line)(unsigned x, unsigned y, const char *text, unsigned len, BYTE attr);
19 | void (*process_events)(void);
20 | } VIDEO_DRIVER;
21 |
22 | void put_cursor(unsigned x, unsigned y);
23 | void unput_cursor(void);
24 | void copy(unsigned x1, unsigned y1, unsigned x2, unsigned y2, unsigned newx, unsigned newy);
25 | void new_cursor(int st, int end);
26 | void window_size(unsigned width, unsigned height);
27 | void draw_line(unsigned x, unsigned y, const char *text, unsigned len, BYTE attr);
28 |
29 | extern VIDEO_DRIVER *video_driver;
30 |
31 | void init_video(void);
32 | void end_video(void);
33 | const char *set_video_mode(const char *mode);
34 | void process_events(void);
35 | void flush_video(void);
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/xstuff.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | * *
3 | * Third Year Project *
4 | * *
5 | * An IBM PC Emulator *
6 | * For Unix and X Windows *
7 | * *
8 | * By David Hedley *
9 | * *
10 | * *
11 | * This program is Copyrighted. Consult the file COPYRIGHT for more details *
12 | * *
13 | ****************************************************************************/
14 |
15 | #ifndef XSTUFF_H
16 | #define XSTUFF_H
17 |
18 | void start_X(void);
19 | void end_X(void);
20 | void process_Xevents(void);
21 | void flush_X(void);
22 |
23 | void copy(unsigned, unsigned, unsigned, unsigned, unsigned, unsigned);
24 | void draw_char(unsigned, unsigned, char, BYTE);
25 | void draw_line(unsigned, unsigned, char *, unsigned, BYTE);
26 | void clear_screen(void);
27 | void window_size(unsigned, unsigned);
28 |
29 | void new_cursor(int, int);
30 | void put_cursor(unsigned, unsigned);
31 | void unput_cursor(void);
32 |
33 | extern int graphics,blink;
34 | #endif
35 |
--------------------------------------------------------------------------------