UQLX is an software emulator emulating a Sinclair QL on UNIX and similar systems. It works by emulating the 68000 CPU and some hardware. It can handle original JS roms, Minerva roms and many nationalized roms. The focus is more on providing useful extensions than exact emulation of antique hardware. Nevertheless it works well enough even for most games.
UQLX is designed to cooperate neatly with the underlying OS, some of the features and possibilities are:
pty
device
Nearly any UNIX or similar system will do, provided you have gcc and X11 installed. UQLX even works with OS/2, however this port was not maintained for some time.
When I say gcc
, I mean it! You may try pgcc but you have been
warned.
Typically any improved c compiler couldn't optimize anything measurable.
Make sure you read the copyright notice carefully before you use, modify or distribute this product or parts of it.
The copyright notice can be found in the file `COPYRIGHT' -- if not
try to email me at rdzidlic@geocities.com
(1).
Several machines/OS versions are directly supported, others may need a little guessing. Even if your machine is in the list of supported types, you may consider using the section Compiling Preferences.
So far the supported machines/OS are:
If your machine is not yet supported, section Unsupported Machines.
To make it on Linux, type
./MK.all make install
other Unices make sure you use gnu-make (called eg gmake on Suns) and
make config # make make install
Do not delete the directory where you compiled it unless you know what you are doing.
If you build for Linux-x86 then -DUSE_VM
is enabled by default. This
means that for every new combination of ROMs a patch database must be built.
This happens automatically but can be rather irritating in some circumstances.
The name of the executable will be 'qm' resp. 'qm-aw', depending on the target and preferences.
If there are any complications like libraries not found, try section Compiling Preferences.
There are some other interesting targets,
make gui
will create a simple GUI for UQLX, only non-aw versions. A much better (nicer) GUI is
available from Jonathan Hudson's Homepage http://www.jrhudson.demon.co.uk
make xaw
Currently not supported.
Will build the qm-aw version. This version is a bit
slower (5-20% ) than the noaw
version. Also some features like
Fork_UQLX
will probably
never get implemented in the xaw
version.
make noaw
will always build the qm version, on most systems this executes a bit better
than the xaw
version
make tags
build emacs TAG table
make docs
will build `docs/uqlx.dvi' and `docs/uqlx.info'
As it turns out, it is always worth to check your gcc
configuration.
`gcc -v' will give you the name of specification file.
Recently SUN made some incompatible changes to Solaris, this results in compiling errors. Newer gcc is the best solution, otherwise patches are available from me. 'Recently' was sometimes around 1996 so this is a bit old news by now.
Some Linux/PC systems have not the correct CPU settings in this specification file. If your system is Linux and the CPU i486 or better, it is advisable to define '__i486__'. You can also do this easily by an addition to your `~/uqlx_cprefs':
BUILD_SPECIALFLAGS= -D__i486__
The REGP and AREGP compiling options are incompatible to profiling, use this to disable them. This also helps if your compiler exits with signal 11..
BUILD_SPECIALFLAGS= -DNO_REGP # or BUILD_SPECIALFLAGS= -DNO_AREGP
On the other hand if you are very confident about your gcc version you may
explicitly enable some trickier things like USE_AREGP
. Normally this
is enabled only for known well behaved gcc versions and matters only for
the ix86 architecture anyway.
Specifying compiler version may work like this:
make CC="gcc -V 2.7.2.3" config #compiles with gcc 2.7.2.3 (if installed) make CC="gcc272" config #another version of it..
are stored in the file `~/.uqlx_cprefs'
Following variables can be set:
PREFIX=/usr # install here DEF_CPU="-mcpu=i586" # use if automatic config didn't work DEF_CPU= -m68040 # old style def.. GENERIC_CPU=yes # don't do special optimizations for # eg Pentium, Cypress or V9 chips, compile generic code (as regarded by gcc..) # unless this or DEF_CPU set some CPU is guessed BUILD_SPECIALFLAGS= -Dxx # need some strange define flags ? LOCAL_LIBPATHS= -L /amd/hx/lib/X11/ LOCAL_INCLUDES= -I /usr/include/ DEBUG_FILES= xqlkey.c # use no optimization for this file(s) LOCAL_OPTFLAGS= -O2 -no-strength-reduce # xqlmouse.c and unixstuff.c don't follow this rule BUILD_SPECIALFLAGS= -DNO_REGP -DNO_AREGP # inhibit certain optimization # especially AREGP can break many gcc versions USE_XAW= yes # or no - not supported right now
The DEBUG_FILES
has no effect on certain special files, you have to change
the `Makefile' by hand.
Some compiling options which are considered generally useful but for some reasons may not be defined as default for your architecture. You may enable any of this options by adding '-Doption' to the BUILD_SPECIALFLAGS line as described in the previous section.
XSCREEN
IPDEV
QVFS
XVIS
U_NODDOT
DEBUG_ROM
So far there is special treatment for these CPUs/architectures:
SPARC
DEF_CPU
.
I would love to know how to guess this automagically!
ix86
HP-PA RISC
MIPS
m68k
For RISC CPUs defining global register variables is the easiest optimization, all I need to know is a list of register names and their typical usage - this simple trick often improves performance by >10%.
Try to make it, if this fails due to some library or includes not found try
section Compiling Preferences. Also see section Obscure BUILDFLAGS
If UQLX compiles fine, but doesn't execute properly than chances are good that
you have a really exotic CPU not yet known to me. In this case try to define
BIG_ENDIAN
and HOST_ALIGN
in `QL68000.h' to match your
CPU.
Contact me so that I can add support for your machines; I need the following information:
BUILDFLAGS
Usually it is not wise to change BUILDFLAGS
, but if you want to do it, here is
some info:
SERIAL
-NO_FIONREAD
if FIONREAD
is not supported. You should also
define NEWSERIAL
and NEWPTY
NEWSERIAL
NEWPTY
USE_IPC
XAW
target
and
compiling preferences.
DO_GRAB
SH_MEM
SH_MEM
.
This X
extension is not very well standardized and therefore good for all
kinds of trouble..
VM_SCR
USE_VM
BSD
NO_MEMMOVE if memmove() is missing, try this
NO_GETOPT .. getopt() .... Actually you would better get and compile
Debugging flags:
VTIME
TRACE
TRACE
DEBUG_ROM
make install
This will create the qm, qmin, qjs, qx, qxx, qxxx symlinks to the executable.
The links are created as specified by PREFIX
which can be environment
var or specified in `~/.uqlx_cprefs' - `/usr/local/bin' resp.
~/bin
is used as last resort.
The compilation directory should be preserved because thats where all symlinks point to :)
Upon first invocation qm
will attempt to create a `~/.uqlxrc'
file.
Some more caution must be used for systemwide installations, QDOS software does not expect concurrent access to files and thus all systemwide QDOS resources should be readonly. Beware, not many QDOS program's handle it gracefully if they encounter a readonly file.
Thus all filesystems except floppy and CD are created private per user by default
There are several configuration files, `~/.uqlxrc' is by far the most important one. It is used to configure QL filesystems, rom, ram and diverse other features.
The other configuration files are `~/.uqlx_cprefs' section Compiling Preferences, `Xql' used by the standard GUI and `Xqlaw', the qm-aw application defaults file. The later two should be copied to your application defaults directory, you will probably also want to change the button names.
uqlx looks for an options file `~/.uqlxrc' This file describes all other
settings uqlx requires; thus uqlx can exist in any directory as long as
`.uqlxrc' is setup properly.
The default name `~/.uqlxrc' can be overridden by specifying the -f
option at startup.
At first installation 'make install' will create a simple `~/.uqlxrc',
you may edit it by hand or use Jonathan Hudson's fantastic GUI. Get it from
http://www.jrhudson.demon.co.uk
The uqlx options file uses a KEY = VALUE
format. The '#
'
character can be used to start comments, rest of the line is not evaluated.
The keys available are:
SYSROM
SYSROM = js_rom
ROMDIR
ROMDIR = /ql/ROMS/
RAMTOP
RAMTOP = 4096
COLOUR
COLOUR = 1
XVID
XDEPTH
and XVIS_CLASS
.
See `xdpyinfo` for list of available visuals.
XVID = 0x24
XVIS_CLASS
XVIS_CLASS = StaticColor
XDEPTH
REAL_WHITE
SIZE_1
SIZE_2
SIZE_3
SIZE_1 = 640x400 SIZE_2 = 1024x768 SIZE_3 = 4096x4096
SER1
SER1 = /dev/ttyS0
SER2
SER1 = /dev/ttyS1
PRINT
PRINT = lpr -Pmy_printer
CPU_HOG
-h
option can be used to enforce
CPU_HOG mode.
Largely obsolete now as it may be toggled through GUI.
CPU_HOG = 1
FAST_START
FAST_START=1
ROMIMG
ROMIMG = tk2_rom,0xc000It is assumed that the ROM image can be found in the ROMDIR directory. The address should be specified in 'C' numeric format.
XKEY_ON
XKEY_SWITCH
XKEY_SWITCH = F16
DO_GRAB
DO_GRAB = 0
XKEY_ALT
XKEY_ALT = Mode_switch ## frequently this is Alt_R
STRICT_LOCK
STRICT_LOCK=1
DEVICE
DEVICE = QDOS_name, UNIX_pathname[, flags]
QDOS_name
is the name of the QDOS volume to be defined, eg FLP1
,
WIN6
, QXL1
. Currently RAMx
is the only name that
receives special attention. UQLX does not enforce any further
naming conventions, however most QDOS software requires a 3 chars
name length.
UNIX_pathname
refers to a file, directory or device used to
simulate the QDOS device.
The optional flags
field supports this options.
clean
qdos-fs
native
UNIX_pathname
is the name of a file or device in the
QDOS floppy disk or QXL.WIN formats; otherwise a Unix directory
is assumed.
qdos-like
qdos-fs
. Filenames are not case
sensitive and (sub)directory creation mimics SMSQ behaviour.
Devices may be removed from the device list by not supplying a unit (volume) number. This is useful if some devices that are defined by default, eg 'mdv','flp' are unused.
DEVICE = CD
Would remove the above default CDROM specification. Some device mapping and other options are supplied as default; in addition, the following defaults are also set.
SYSROM = jsrom ROMDIR = /ql/ RAMTOP = 4096 COLOUR = 1 PRINT = /usr/bin/lpr CPU_HOG = 1
Note that no additional ROM (tk2) is defined by default.
and here is the example of an actual .uqlxrc file. You will find more recent versions of it with every UQLX distribution.
SYSROM = js_rom # default ROM to use ROMIM = tk2_rom,0xc000 # extra ROM ROMDIR = ~/qm/romdir/ # ...search them here RAMTOP = 16384 DEVICE = MDV1,~/qm/qldata/ # this directory will be accessible as 'mdv1_' DEVICE = MDV2,~/qm/qlsoft/ DEVICE = FLP1,~/qm/DiskImage2,qdos-fs # 'flp1_' is the image of a real QL floppy.. DEVICE = FLP2,~/qm/DiskImage,qdos-fs DEVICE = FLP3,~/qm/DiskImage3,qdos-fs DEVICE = WIN1,~/ DEVICE = WIN2,/ DEVICE = WIN3,~/PiQ/ DEVICE = RAM1,/tmp/.ram1-%x/,clean # temporay dirs, cleared after exit DEVICE = RAM2,/tmp/.ram2-%x/,clean DEVICE = RAM3,/tmp/.ram3-%x/,clean DEVICE = RAM4,/tmp/.ram4-%x/,clean DEVICE = RAM5,/tmp/.ram5-%x/,clean DEVICE = RAM6,/tmp/.ram6-%x/,clean DEVICE = RAM7,/tmp/.ram7-%x/,clean DEVICE = RAM8,/tmp/.ram8-%x/,clean DEVICE = CD1 # devices we don't want DEVICE = MS1 COLOUR = 0 # simulate MONO, 1=COLOR monitor PRINT = lpr # printer spooler prog used by PRT port CPU_HOG = 0 # don't burn CPU power in QDOS scheduler loop FAST_START = 1 # skip ramtest
If compiled with -DUSE_VM
- currently Linux-x86 and SPARC, a patch
database must be built on first startup. This is usually done automatically.
UQLX often prints diagnostic messages to stdout
and stderr
, so
start it in its own xterm.
During startup, the emulator will attempt to boot from `mdv1_BOOT'
(Case sensitive !!) or read commands from the BOOT
device if one was
specified with the '-s
' or '-b
' option.
It appears that in Minerva 1.98 the name of the default BOOT
file
changed from `mdv1_BOOT' to `mdv1_boot'!! To keep compatibility
with other ROMS I would recommend a soft link like
ln -s BOOT boot # in mdv1_
`qm' is the recommended name for normal usage. A different name will be interpreted as
follows: if either 'min
' or 'js
' is part of the program name, qm
will attempt to use a `minerva_rom' resp `js_rom' for the
emulation, overriding any options or defaults.
Thus if you often need to switch between Minerva and JS roms, or even
want to have
both running at the same time, the
easiest way to manage is to arrange some soft links approximately
like this:
ln -s qm qjs ln -s qm qmin
If the program name contains an 'x
', 'SIZE_X' and `minerva_rom' will
OVERRIDE other defaults. Likewise, 'xx
' will trigger 'SIZE_XX' and 'xxx
'
'SIZE_XXX'. The current compiled in defaults for screen size are
SIZE_X = 632x400 SIZE_XX = 720x512 SIZE_XXX = 800x600
uqlx supports the following command line options; these override settings in `~/.uqlxrc.' Note that options in turn can be overridden by program name as described above.
qm [-r RAMTOP] [-i] [[-c][-m]] [-f file] [-h] [-o romname] [-s [string]] [-b [string]]
where:
-r RAMTOP
-c
-m
-g nXm
-f file
-h
-o romname
-s boot_cmd
boot_cmd
must be present, it defines a QDOS 'BOOT' device to be used,
see -b
option.
-b boot_cmd
boot_cmd
string on
read.
The boot_cmd
should be a string of the form
"10 lrun mdv1_progxx"
or similar; quoting newlines is tricky
and therefore only 1 line expressions are recommended. A QDOS newline
char is automatically appended to the string.
-i
Usually there are no special requirements for UQLX boot files, just remember to store it as `mdv1_BOOT' - case will be significant in the default installation.
There seems to be a problem with some versions of Ptr_gen
. If
your boot file fails with random errors near the place where it is loaded,
try inserting this after LRESPR Ptr_gen
:
PAUSE#2,1
This will not work with JS ROMS, use a for loop or similar to cause the delay there..
You may query the UNIX environment variables and the startup parameters of the emulator from your bootfile - section SuperBasic Extensions
The supplied GUI is intentionally very simple - it is supposed to compile and work on every system with X without requiring additional toolkits etc. Seems only the old Athena Widget set meets this requirement :-(
Resources are in `Xql', you may change button names, fonts or even use own graphics.
The GUI supports this actions:
Paste to keyboard Queue
Clone UQLX
ROM breakpoints
Redraw QL screen
XKeyLookup
XKEY_ON
in `~/.uqlxrc' resp. the key configured by XKEY_SWITCH
cpu hog
-h
or CPU_HOG
UQLX handles all signals, currently they will have this effect:
SIGINT
^C
will do a 'soft termination', cleaning up all
temporary files and directories.
SIGQUIT
^\
will cause an immediate exit, this is useful
in the unlikely case that SIGINT
fails due to some recursive error.
SIGABRT
Thanks to Tony Firshman, Minerva v1.89 is now PD and can be bundled with UQLX - it is `romdir/min.189'.
For various reasons you may run into some trouble when trying romimages other than the supplied js_rom or min.189. Roughly, the known causes are:
SBYTES <device><filename>,hex('400000'),48*1024
If you choose to work with a screen bigger than 512x256, there are a few important points.
Warning: it is possible to define screens bigger than the physical screen - make sure that you know how to move around by your virtual screen manager in this case. Beware that UQLX captures all key events.
The maximum useable screen size depends on available RAM and X server habits. If at all possible try to run UQLX with 8bit depth - see customisation. For 8bit depth the memory requirements will be approximately x*y*1.25 bytes + whatever the Xserver allocates. This can be quite a lot because UQLX uses backing store and shared memory when available, thus turning of this features in the Makefile or Xserver may improve performance for very big screen sizes by a factor of 2.
If you are an extremist, there are several window managers that will allow you to have rather big screen sizes, eg fvwm. The maximum I have tested so far is 8192x4096 with SunOS/Solaris. The theoretical limit is - because of Pointer Environment's bad habits that the screen must fit with all RAM into 16 MB
Pointer Environment is patched when activated to recognise the new screen parameters - there are 'cleaner' solutions, unfortunately with severe side effects. If you receive the warning "could not patch PE", you are in serious trouble..
Screen geometry may be slightly adapted to result in clean x-resolution/sd.linel ratio. Length of screen buffer must always be truncated nearest 32K boundary, therefore some screen sizes may result in a certain waste of memory.
Some of them work better than others, and some don't work at all. UQLX is slightly more demanding on them because it has to do keyboard grabbing and warps the mouse pointer. ICCM compliant wm's (those that don't grab events from clients) should be preferred where possible.
Enlightenment with gnome is reported to freeze (pretty old report by now).
Tested to work: olvwm, fvwm2, afterstep, windowmaker. Many of these have settings which can make a big improvement.
There are 2 points of concern when emulating a QDOS type keyboard under X11:
First, many window managers try to interpret key events that are meaningful for QDOS programs and invoke their own actions - this is almost always undesired. To resolve the conflict I have implemented keyboard grabbing. Unfortunately, due to a design flaw of the X11/XKB extension, keyboard grabbing doesn't work with many non-us keyboards. Typically some keys accessed by AltGr or similar do no longer give correct results in UQLX.
Best cure is do NOT use XKB. Despite what many national-howtos say Xkb is completely optional and only wastes resources. To disable it,add following lines in `/etc/XF86Config'
XkbDisable RightAlt ModeShift
You can then safely set DO_GRAB = 0
in the config file.
To get exactly the same bindings with or without Xkb you need to use
`~/.Xmodmap'. Create it in a xkb-enabled session like this:
xmodmap -pke >~/.Xmodmap
Second problem, there are often key combination for which both QDOS and X11 have meaningful interpretations and that are difficult to generate otherwise.
To resolve the problems, I have added a switch, switching this states:
The switch is bound to a key, F11 by default and in default state unless
configured otherwise See section About .uqlxrc files XKEY_SWITCH
. Switching
the keyboard mode can be also done using the GUI
To make life with XkB easier, it is also possible to define a special key that is interpreted as QDOS' Alt key by the emulator.
Be warned, that when the keyboard is ungrabbed, the X11 window manager may react strangely to some of your hotkeys. Perhaps the easiest way to avoid clashes in this case would be to redefine the 'meta' modifier to something completely unusual like F13.
Here is a short description what the xql_key() approximately does in case you want to mess around with it.
X itself is pretty straightforward but the code is a bit complicated for the reasons outlined above. Additionally I am trying to circumvent some problems with vendor specific keyboards. Eg some SUN keyboards return Keysyms like 'F35' instead of XK_Next - not even programs like Netscape or Xemacs can cope with it without being hacked (which is far easier with Xemacs btw). And don't even mention SGI keyboards and WIN95 X emulation to me ...
The result is a 3 level key-combination translation scheme:
X defines: 1) keycodes - each keyboard button has a number that is completely OS dependent This number is only useful to find out what KeySyms are associated with the button as I do in keycode_from_XKeycode() keycodes are used to see how X translates them - if the same result could be achieved with "less" modifiers, a QDOS translation is preferred. state - is a value indicating which modifiers are to be applied to the keycode. Unfortunately state is wrong when keyboard is grabbed and XKB being used. 2) keysyms - gives some portable name to keycodes and is to some extent in an 'unportable way' dependent on the modifiers (shift, ctrl, meta). The Keysym data type is an integer that is associated to the keysymname by XKeysymToString(). Keysyms associated with ASCII chars have the ASCII value of the char - some tests in the code are based on this. 3) XLookupString is basically the default ASCII/ISO value associated with the key combination described by the XEvent. Unfortunately XlookupString is no longer supported - it is not politically correct in the days of i18n. The advertised replacements for it are not only complete overkill for a QDOS emulator that understands less than the ISO-1 charset by definition - they would also increase the complexity of this 3 level translation scheme to ludicrous levels.
qm
can now be used to run QDOS programs as scripts. This feature
is not yet completed but I already used it in some cron
commands.
With the pty_
device and this facility QDOS will soon rival perl
as an extension language.
Both the -b
and -s
options can be used to pass a command string
that overrides the usual `mdv1_BOOT' actions.
-s
additionally inhibits any attempt to open an X window to display the
QL screen.
With the -s
option, screen IO will be redirected to fd 0 for input,
fd 1 for output. Piping input into UQLX is somewhat difficult, not only aren't
special codes (^C,break) working, also very strange things may happen at eof.
Currently piping input to Minerva doesn't work reliably.
Since it turns out that quoting SuperBasic characters or newlines can be extremely complex I would recommend passing only very simple command strings, something like
qm -s "10 lrun mdv1_prog"
should work without any problems with any shell, a single chr$(10) is appended to each command string.
There are a few SuperBasic extensions provided to pass arguments to scripts
and access environment variables, namely
getXargc
, getXarg$
and getXenv$
.
see section SuperBasic Extensions
Both QDOS/SMSQ diskimages and the UNIX host filesystem can be accessed, for configuration details see the `.uqlxrc' file.
It is also possible to use real QDOS floppies, but some care must be taken. Especially disk swaps will only be recognised when all files are closed.
There is no file locking for the UnixFS. QDOS diskimages and QXL.WIN files are locked before accessed, because the potential for damage is much greater. However not every Unix will support locking block devices - test this if you intend to run more than 1 emulators at a time.
File locking is mandatory ONLY when the mode (chmod(2)) of the file is set accordingly. This is what UQLX does by default - see customisation. However with the strict locking enabled some problems remain, eg if some another program opens the image file before UQLX. It seems file locking can never be done absolutely foolproof in Unix, the results may depend on the particular brand of Unix.
When UQLX fails to establish a lock for some reason it will proceed with a warning.
Readonly access is implemented for all types of filesystems simply by
respecting the UNIX file modes and returning ERR.RO
. In UnixFS this
is on a per file basis, whereas on floppy/QXL.WIN this controls the
whole volume. Most QDOS programs seem to ignore ERR.RO btw which can
be a problem.
The Unix Filesystem can be accessed both translated and untranslated. The translated version is used in the default configuration to host 'mdv1_' and some other devices.
The untranslated version is accessed as the uQVFSx Filesystem, see that section. The uQVFSx Filesystem is good if you want to access a Unix file of which you know the (Unix)filename or simply need very long pathnames. It can be also used to access raw and special devices, eg the /proc filesystem.
The UNIX FS Interface provides access to the underlying UNIX (or similar) host filesystem. Standard QDOS and most QDOS-FS II file operations are mapped to UNIX calls, full (sub-)directory access is provided.
This means that whatever filesystems are accessible from Unix (CD, MSDOS, Amiga partitions, ZIP drives ....) are accessible to QDOS programs.
The filenames are translated to a QDOS like syntax, `/' maps to `_'. Unfortunately this means, that in very rare situations a file may shadow some subdirectory. UNIX names are therefore supported as well, this looks like `mdv1_c68/INCLUDE/stdio_h'.(2)
The qdos-like
flag selects whether the filenames are case-sensitive
and whether (sub)directory creation will have Unix or SMSQ semantics.
Using the qdos-like
flag should be restricted to directories
reserved for UQLX. If programs other than UQLX create files with names
that are not distinguishable in case-insensitive mode the results
will be undefined.
The default Unix FS is case-sensitive which can be a real pain with SuperBasic, but works quite good with most other software. Beware that QDOS will attempt to boot from `mdv1_BOOT' !
Another lovely source of confusion is using SuperBasic symbols as filenames -- SB always remembers the case of the symbol when seen first time and converts to this case subsequently.
Thus
open#6,mdv1_BoOt open#4,mdv1_BOOT REM still accessing mdv1_BoOt !!
Data-type, -space and file version are stored in an one per directory
`.-UQLX-' file. This means that UNIX hard and soft links for QDOS
executables, as well as moving or copying them around by mv
will fail.
There are some utilities in the `utils' subdirectory that can be
used to manipulate the entries. Depending on the underlying Unix filesystem
there may be problems to create or access a file `.-UQLX-', so exotic
filesystems like 'umsdos' are only very limited QDOS compatible.
The UNIX directories are visible to QDOS like normal FileSystem II directories. Since QDOS doesn't use a distinct directory separator, this resulted in a rather complex algorithm for finding files, and in pathologic cases may result in certain files being shadowed.
The `.' and `..' directories are accessible just like that in QDOS but aren't listed in directories anymore.
QXL.WIN files are now supported as well as direct use of floppy/QXL.WIN devices.
Currently, disk swaps are only recognised when all files on that device are closed!
UQLX can use `DD' or `HD' diskimages.(3) It should be noted that UQLX does not yet work well with unusual floppy formats, even when the files are listed correctly caution is recommended.
Floppy-Diskimages can be taken by 'dd', although 'cat' usually works as well (and much faster on SUN). On SUNOS the exact syntax is
dd if=/dev/rfd0 of=DiskImagename
- unfortunately it does rarely work as easily on Solaris.
Man pages of `dd' or `tar' usually give good hints about the floppy names, one possible complication is Volume Management, refer to 'man vold'.
On Linux anything works, unless you have a very special floppy use /dev/fd0
as filename.
This program is now supplied in the `utils' subdirectory. It should be run before exchanging QXL.WIN filesystems images with SMSQ software, it will spot some potential compatibility problems and detect many types of filesystem damage.
UQLX now offers access to (almost) unlimited pathname lengths. So far I have tested pathnames up to 1017 bytes which appears to be some limit in Solaris, 4000 being the supposed limit of the current UQLX implementation. However you should be warned that TK2 and/or maybe some QDOS versions might mess up and fail to report ERR_NF when you are trying to access a long pathname that can't be opened.
The syntax has some similarities with QVFS (also many differences), and if practical
I intend to make it QVFS compatible in the future.
QVFS is a new filesystem (c) by Hans-Peter Recktenwald - see
http://www.snafu.de/~phpr/qhpqvfs.html
for more info.
To access a unix file through uQVFSx specify its full pathname in unix syntax. Sometimes uQVFSx will also replace '_' by '/' if it matches this way - this is only intended as an compatibility hack to make some antiqued programs work with it.
A leading '/' or 'XVFS_' is enforced to recognise an uQVFSx name.
Also, if for some reason you are not sure the filename is unique within QDOS devices, prefix it with 'XVFS_'
Examples:
view '/etc/motd' view 'XVFS_/etc/motd' view '/usr/include/sys/signal.h' view '/usr_include_sys_signal.h'
You should be able to do all file operations defined for normal UQLX filesystems except directory operations. Hoping that QVFS becomes stable and widely accepted, I will add directories etc.
For now, getting directories works like this:
copy 'pty_ls -a /usr/include' to con_ spl 'pty_ls -a /usr/lib',#1
Of course any options `ls' recognizes can be used, the -a
option is essential otherwise you could trigger a SPL
bug that
closes #1
in the 2nd example! See section pty device for details.
When this filesystem is used to access special files (devices), only a restricted
set of trap#3
commands will work for this file.
Here is a description of the TCP/IP
,pty
,ser
and
prt
devices.
The TCP/IP
features are described in the files `docs/socket.*' that
came with this UQLX distribution or here:
http://www.geocities.com/SiliconValley/rdzidlic/socket_main.html
pty
jt_program name
par1 ....
i
k
c
z
^Z
)as end of file
t
' (single quote,\')
'#name'
pty
I/O - thus if `mdv1_kant.tex' contains any non
ASCII codes a separate translation is required.
open#4,"ptyt_ispell -d #mdv1_kant.tex"
[n]>
[n]>>
[n]<
n
when given
A pty is a pseudo-terminal that enables you to run a program as if it were connected to a real tty. The terminal output of the program is is available as input from the connected QDOS channel, likewise output into the QDOS channel appears as input from its terminal to the program. The pty device works similarly as a pair of pipes, with the difference that the launched program believes to execute on a real terminal, and the same channel is used for i/o and error output.
examples:
open#6,pty_date REM get unix time and date input$#6,a$ REM should be same like QDOS date print a$:close#6
A bit more complicated example, 'pty_ls -al'
would do the same
easier.
10 open#6,pty_csh 20 print#6,"ls -al" 30 print#6,"exit" rem otherwise we can't detect the end! 40 repeat xx if eof(#6) :exit xx 50 input#6,a$:print a$ 60 end repeat xx 70 close#6
Connect to an NNTP server and post a test message. Most likely you will have to use another NNTP server and change the "From:" to contain a legal address.
100 PRINT "NNTP Posting software" 110 PRINT 120 OPEN#6,'pty_telnet rznews.rrze.uni-erlangen.de 119' 130 get_resp 140 get_resp 150 get_resp 160 get_resp 170 PRINT "** Connected **" 180 PRINT#6,"post" 190 get_resp 200 PRINT#6,"Newsgroups: alt.test" 210 PRINT#6,"Subject: test" 220 PRINT#6,"From: test@alt.test" 230 PRINT#6 240 PRINT#6,"test" 250 PRINT#6,"test" 260 PRINT#6,"test" 270 PRINT#6 280 PRINT#6,"." 290 PRINT#6 300 get_resp 310 PRINT#6,"quit" 315 REPeat xx:get_resp:IF EOF(#6) :EXIT xx 320 CLOSE#6 330 DEFine PROCedure get_resp 340 INPUT#6,c$:PRINT c$ 350 END DEFine 360 DEFine PROCedure sa 370 SAVE_O mdv1_script 380 END DEFine
If the pty driver (pty.c) compiles on your system; try setting the QTPI "Comm Dev" setting to 'pty_/bin/login' (or, better, "pty_/sbin/agetty -L -h 38400 -" on a Linux box). The pty device takes one parameter, the Unix command to run. If no command is given, it tries /bin/sh as a login shell. Usually it is not even necessary to give the full path of the command as above.
The pty code is taken from the 'emu' X Window terminal program; the original archive contains many clues on getting it to work on different platforms. You can find out about 'emu' from emu@pcs.com.
In this context, beware of an TK2
bug - SPL
may accidentally close a basic channel passed as #ch
if the channel returns an immediate EOF
as the pty
device can do
SPL 'pty_ls emptydir',#1 REM #1 gets closed! (-:
ser
npht_
bbaudrate
except for the _baudrate
, the options have the same meaning as in QDOS
where applicable.
O
E
M
S
H
I
R
Z
^Z
as EOF
C
Here is some documentation for ser
and pty
devices, originally
compiled by Jonathan Hudson
WARNING: this implementation is tested only on Linux, implementing it for
other OS/architectures may require nontrivial changes. The pty
drivers are also tested on Solaris.
Serial and pty (pseudo terminal drivers) are available for uqlx. Due
to the machine specific nature of these devices, some work may be
required to make them work on non-Linux systems. In particular, the
ioctl(..,FIONREAD,..)
call may not be supported.
The serial device (1 and 2) takes an extra parameter, the baud
rate. MT.BAUD
is also supported, but as it only works to 19200 baud,
it is not much use. The extended syntax is, for example:
ser2hr_b57600 (57600 baud)
The data transfer rate appears CPU bound, but 5100 cps TX and 4800 cps RX are achievable for QTPI/ZMODEM.
The serial device names should be specified in the `.uqlxrc' file, good choice for Linux is `/dev/ttyS0' and `/dev/ttyS1'.
The prt
device can be used for printing. The data sent to prt
is piped to the printer command specified in `.~/.uqlxrc' which may
be overridden or modified by providing additional arguments to the prt
device.
prt
ft_
add_options!
alt_command
add_options
alt_command
Data sent to the prt
device is piped to the specified filter.
If you have QDOS printer drivers for the printer in use, try to send your
output to lpr
. If this doesn't work, try following definition in
`.~/.uqlxrc':
PRINT = lpr -Praw
If your system doesn't have a -Praw
you can add it by editing `/etc/printcap' or as a quick hack, just defining
PRINT = cat >/dev/lp0
For this to work you will probably need to change `/dev/lp0' permissions. Obviously this should not be used together with a standard lpd..
Some care must be used when specifying printer/filter commands: when closing
the printer channel uqlx calls pclose
which waits until the command(s)
exits -- in this situation uqlx may appear to hang.
If this happens, kill the filter process from another xterm.
pty
channels have to loose
EOF.
It appears as if UQLX and/or X can get easily confused when Fork_UQLX
is applied while the mouse pointer/focus is in the UQLX window. This doesn't
seem to be a serious problem, as forking should be most useful when used
in scripts anyway.
Returns pid
for the parent process, 0
for its child.
An utterly useful example program is:
10 for i=1 to 4 20 print Fork_UQLX 30 end for i
qm -m -r 1024 arg1 arg2 arg3 PRINT getXargc => 4 (arg0=qm !)
for i=0 to getXargc-1 : PRINT i, getXarg$(i)
results in
0 /user80/rdzidlic/qm/qm 1 arg1 2 arg2 3 arg3 4 arg4 5 arg5
getXres
getYres
For a general overview of the Emulator see also Daniele's original QM.README.
QDOS memory is always in 68k format, that is big-endian. There are some possible ways access memory:
RW(),WW() read,write 16bit word RL(),WL() 32bit
w8 ReadHWByte(w32 addr); w8 ReadByte(w32 addr); w16 ReadWord(w32 addr); w32 ReadLong(w32 addr); void WriteByte(w32 addr,w8 d); void WriteWord(w32 addr,w16 d); void WriteLong(w32 addr,w32 d);This must be done only in a very controlled way, bad alignment or other errors may cause very hard to debug m68k exceptions
the pc
is a global variable used as program counter; it is somewhat special
in that it already has the base of QL memory, "theROM" added to it. Thus if you
need the QL-relative pc value ((long)pc-(long)theROM)
will do.
are an array of w32's, always stored in host format byte order.
reg[8]
,*(reg+8)
,aReg[0]
all refer to A0
byte and word access to registers is done using address calculation, thus
*(uw8*)((Ptr)reg+RBO) is d0.b *(uw16*)((Ptr)(reg+1)+RWO) is d1.w
A more complicated example is:
(w32)*(((w16*)((Ptr)reg+RWO+((displ>>10)&60))))+ aReg[code&7]+(w32)((w8)displ));
this will compute the the xx(An,Rn.w) address, code
, is the first instruction
word and displ
the extend instruction code.
It is recommended to compile with the `-ggdb3' option if you use gdb, this flag can be set eg by setting `LOCAL_OPTFLAGS'. Older gcc versions only support `-ggdb'
If you are interested in a certain file, set 'DEBUG_FILES = file.c'
in ~/.uqlx_cprefs so that this file is compiled for debugging.
If you think you might want to debug UQLX, but don't know what
exactly, you may need to compile without the '-fomit-frame-pointer',
otherwise bt
(backtrace) won't work.
To work with gdb
you should ensure that the `.gdbinit' file
supplied with UQLX is used.
start qm within gdb:
>gdb qm gdb>run
if you run into an exception,
gdb> call DbgInfo()
will give me an idea what is happening.
It is also possible to disable the ROM protection (See section GUI) to allow breakpoints in ROM, See section GUI
It is possible to activate normal QL debuggers from gdb
by typing
qldbg continue
This causes UQLX to generate a trap# $e
exception with the current
PC
as "breakpoint address"(usually this points 2 bytes before you
would expect!).
This is useful if you wish to see what happens after a certain UQLX
function (eg driver call) returns to normal 68K execution mode.
If you suspect a certain function or region of code of causing some trouble, email me the TRACE output with exact description of how it was generated (including modified tracetable and software used) - see next section.
I have added selective tracing, if you want to activate just add the
-DTRACE
in Makefile, recompile everything and customise tracetable in
trace.c to suit your needs.
For technical reasons all values are printed before the instruction
is executed. This means that "code" and "PC" are not sync.
Thus if you get output like this
DebugInfo: PC=48de, code=4eba, SupervisorMode: no USP=fffbc SSp=28480 A7=fffc8 Register Dump: Dn An 0 0 107 1 50000000 d88 2 0 8d2b 3 a0000000 186 4 0 ce8 5 df 8cee 6 1 ff068 7 0 fffc8 Trace : RI.MULT+4 DebugInfo: PC=48e2, code=48e7, SupervisorMode: no USP=fffbc SSp=28480 A7=fffbc Register Dump: Dn An 0 0 107 1 50000000 d88 2 0 8d2b 3 a0000000 186 4 0 ce8 5 df 8cee 6 1 ff068 7 0 fffbc
beware that code=48e7 belongs to PC=48de and to find the instruction; gdb> print table[0x48e7] however the program must have been started before this, otherwise 'table' would not have been initialised.
the supplied JS_ROM is original. The patching process is implemented in QL_configure.c and is designed to work for many js-similar ROMS without change.
The patches are:
Installing handlers is done by overwriting the ROM at a suitable address with a specific A-line opcode and modifying the emulators instruction table to call a specified handler function (instead of just initiating an A-line exception).
This handler function is then responsible to check that indeed it was called from a well defined location and not just by accident - this usually is a statement in the form
if((long)gPC-(long)theROM-2==EMUL_IPC_LOC) { if(IPC_Command()) rts(); else table[code=0x40e7](); } else { exception=4; extraFlag=true; nInst2=nInst; nInst=0; }
where EMUL_IPC_LOC
is the stored address of the patch. If it is indeed the location,
the handler function can access QL memory and registers using the techniques outlined
above, or if a special condition is not met proceed emulation as if there was no
patch at all - this technique is demonstrated in QL_hardware:QL_KeyTrans
Note that if there is an rts() in any routine, this will modify the emulators A7 and PC but not do any other action (as returning from the c-function itself). Thus you might write 'rts();rts();rts(); return;' and it may make perfectly sense, depending on the context of the patch.
this is perfectly possible, provided QDOS is an a state where it allows this particular request. A trap#0 call may be done as
savedA0=*aReg; QLtrap(1,0,20000l); printf("QDOS vars at %x, trap res=%d, RTOP=%d\n",aReg[0],reg[0],RTOP); *aReg=savedA0;
The 200000l is the instruction-count limit may be chosen arbitrarily - but must not be exceeded. Similarly, the following will do a vector call:
QLvector(0xd0,200000);
However not all vectors may be safely called, those that manipulate its return point may fail.
Following must be arranged:
The risk of encountering a context switch is reduced by switching off the 50Hz interrupts in such calls, often other precautions may be wise (clearing SV.POLM or entering SU mode)
are defined in QL_files.h and designed to serve every kind of filling systems attached to UQLX. Currently the code is very messy so don't bother to understand it.
This is stored in ~/.uqlxpatch
directory if the emulator was compiled with
-DUSE_VM
.
There is a checksum to identify a ROM (everything from 0 to 96K is checksummed)
and entries to mark from where this ROM accesses the QL HW registers.
The files must be writable! UQLX usually takes care of that, just don't
try neat tricks like 'umask 222'
.
This files are not meant to be user editable but can be deleted anytime - in fact this may be necessary if something went seriously wrong.
simple (nondir) devices like the printer "PRT" are handled in QL_driver.c The attempted approach is to have a single generic driver handling all simple device drivers which can then be written in C without detailed knowledge of how QDOS drivers actually work and without having to care about alignment and/or byte order problems when accessing QL memory.
To add a new driver, add an entry to the QL_driver.c:Drivers[]
table.
The definition should include the open/io/close routines and information
about name decoding.
The members of 'struct DRV':
ref
init
open_test
'name'
is a legal channel name
for this channel.
should return:
0
1
-1
open:
0
<>0 & reg[0]= QDOS_ERR set:
close
io
slot
The open
routine should malloc() a block of memory for each channel it
manages, it should return a pointer at this block via its second parameter.
Subsequent calls to dev.io and dev.close will receive this pointer as an argument
(observe the ** in the declaration!)
The driver should not attempt to store anything in the QDOS channel definition block!
is designed to ease the task of writing dev.io routines, very similar to QDOS io.serio vector. Calls that may block must be handled specifically. Also, be warned that most unix io calls can get interrupted by the SIGALRM used for emulating interrupts.
is an utility function similar to io.name.
int decode_name(char *name, struct NAME_PARS *ndescr, open_arg *parblk)
ndescr
parblk
open_arg
see examples.
There are a few extensions, most notably parse_nseparator
provides a way
to parse text delimited by 2 characters or one character and end of name.
Care should be taken not to take certain chars as delimiters and/or options that are differently mapped in Unix and QDOS, eg backtick and pound.
Also consider that for option letters and separators upper and lower case is not distinguished for alphabetic characters.
'PRT' is a simple example driver, if you want to study the channel
opening syntax consider the example 'bg'
bogus driver(#define TEST
in QL_driver.c)
An example call to open a 'bg' channel is:
open#4,'bg299F_119/999x333-string 1 ****xxx++++-,string====,,,,,,'
I have just started it so there is not yet any structure in it, just a few points that did strike me. Even with the best docs there are many gotcha's ;-)
The AltGr keys don't work even if I use the X11 lookup method.
Mode_switch
-- thus
an extra char "\255"
is inserted with each AltGr
key
How do I access Unix devices from UQLX?
This is the original README I received with Daniele's sources; refer to TECHREF for updates. Much of the information contained herein is more or less outdated.
A brief comment about the 68K emulator sources.
These are the sources (written in the C language) of the 68000 emulator which are used in my Sinclair QL emulator for Macintosh.
The sources are not complete: a few procedures are missing, as they are not portable and you should rewrite them according to the target platform. In particular all the parts regarding the hardware are missing (except for the clock register); in any case they are not part of the 68008 emulator, but specific of the QL emulator.
A 68000 instruction code is 16 bit long (eventually followed by other data or addressing mode specifications), so there are 65536 possible codes. The idea is to use the instruction code as an index in a table of functions' addresses, and to execute the corresponding function. The table is 65536 x 4 bytes long, i.e. 256K. Writing all the 65536 functions would be quite a long task, so I wrote only one function for each instruction type: for example there is only one function to emulate the MOVE.B instruction; the function's address is put in all the table's positions corresponding to the code (binary encoded) 0001xxxxxxxxxxxx, where x may be either 0 or 1, covering all the possible bit patterns. In this way the MOVE.B function is called for all the 0001xxxxxxxxxxxx instructions codes, like 0001000000000001 (MOVE.B D1,D0) or 0001110110111100 (MOVE.B #imm,d(A6,RN), where d, RN and imm are specified in the bytes following the instruction code). This generic MOVE.B function execute the right operation by first interpreting the bits marked x (in 0001xxxxxxxxxxxx); in the example to interpret the x bits means finding the address modes of the source and destination operands. This method allows for future optimizations: writing a greater number of more specialized functions results in better performance. In the MOVE.B example, we could write another function to emulate the 0001yyy000000xxx codes (MOVE.B Dx,Dy), which would speed up the execution of the MOVE.B instruction with registers as source and destination. Now this function (when it is called) knows already the source and destination addressing modes (registers), avoiding the overhead of the code-interpretation phase, as was the case with the generic MOVE.B function.
The instruction-code fetching loop (in the ExecuteLoop procedure), which looks up in the table the address of the corresponding function and executes it, was rewritten in assembly language: as this loop is executed hundred million times, it must be fully optimized.
The 68000's registers (Dn, An, PC, SR) are memorized in global variables.
Computing the flags during arithmetic operations is a problem: the C language doesn't allow a direct flags' control (for example an overflow caused by an addition can't be easily detected: the only way to detect it is by arguments like 'if the addends are positive and the result is less then an addend, then an overflow has occurred', etc.) and computing the flags leads to a large number of complicated tests, resulting in slower emulation.
Another problem are the read/write operations from/to the QL memory. I decided (although it is a slow method) that all these operations can't be performed directly, but only through the ReadByte/ReadWord/ReadLong/WriteByte/WriteWord/WriteLong functions. In this way these six functions can check the address and behave correctly depending on it; the following cases are possible: - QL's RAM: the standard case - QL's ROM: can only be read. Write operations have no effect. - QL's video memory: when writing to it the emulator must draw the corresponding pixels to a Macintosh window. This operation requires a fair amount of time. To speed it up a little the effective drawing operation is delayed as long as the modified bytes are adjacent to each other. So the final conversion may involve entire rows instead of single pixels. - QL's hardware: the hardware ports behaviour must be emulated. - any other address: writing has no effect, to avoid to randomly overwrite the Macintosh memory. This means that whatever the QL does, the Mac environment can't be corrupted; in other words these controls on each read/write operations result in a program which is very stable.
Exception processing: exceptions are caused by instructions (like TRAP or CHK), by the 50/60Hz interrupt (generated by a timer), by reading/writing words or long words to odd addresses, or by the trace bit when it is set. The exception is called by putting the desired exception number in the 'exception' variable (otherwise the variable is 0). The variable is not checked after each instruction, to avoid slowing down the instruction fetch&execute loop (ExecuteLoop). The loop counter (variable 'nInst', determining how many instructions have to be executed yet) is zeroed instead, causing the loop to be exited. The fact that the end of the loop was due to an exception and is not a normal loop termination is signalled by setting the 'extraFlag' variable to true; the old 'nInst' value is saved in 'nInst2', so that it will be restored when the loop will be re-entered after causing the exception. The exception calling process consists in the following steps (see the 68000 manual): - enter supervisor mode and save SR and PC on the stack - load the new PC from the 'exception handlers' list, located in low memory
Addressing modes: operands are fetched through the 'GetFromEA' (EA=Effective Address) functions and written to memory through the 'PutToEA' functions. Often a memory location is read and then written by the same instruction (i.e. it is modified). (eg: ADDQ.W #1,(A0): the word at the A0 address is read, incremented and written back). Using the two GetFromEA and PutToEA calls would be a waste, because the address decoding is performed twice; for this reason a ModifyAtEA function is provided, which do the same as GetFromEA but saves in global variables some information about the decoded address (Mac memory address, access type: ram/rom/video/ecc...). Then the RewriteEA function is used to rewrite data at the same address. RewriteEA takes advantage of the saved information. Addresses (like a value in an An register) are maintained as QL addresses, which are different from the real addresses: for example the QL address 0 doesn't correspond to the Mac address 0, because this part of memory is used by the Mac operating system. The read/write functions must relocate the address. The only exception to this rule is the program counter, which is an address in the Mac memory, to make the fetch&execute loop more efficient.
The types of int employed by the emulator are 8/16/32 bit signed and unsigned. They are defined (file QLtypes.h) with the names w8,w16,w32,uw8,uw16,uw32 (u means unsigned, w word, the number is the width expressed in bit). The definitions are based on the basic C types (char,int,short,long). Depending on the particular compiler and computer which is used, it might be necessary to modify these definitions. For example on the Mac an int is 32 bit, while on old 8086 systems an int is usually 16 bit.
The file ql68000Init.c contains the code to fill in the 256K function table. The functions which emulate the 68000 instructions are contained in two files, because a unique file would be too long. The first file contains the instructions with name beginning with a letter between a and o, the second between p and z, plus (at the end) the many variants of the shift instructions.
June, 4th 1995 Daniele Terdina
The 68000 processors are big endian, i.e. when they store in memory a word or a long they store the most significant byte first (in lower memory addresses). If you want to compile the emulator for little endian machines (like Intel processors), you must perform byte swapping when transferring word or long data between memory and registers. Luckily almost all the accesses to memory in the emulator code are performed by using the functions ReadByte, ReadWord, ReadLong, WriteByte, WriteWord, WriteLong, so it is sufficient to add byte swapping in this functions. However, there are also a few places where memory is accessed directly, and you should change the code. Some (but probably not all) of these places are: 1) all the accesses to immediate operands in the GetFromEA and similar functions 2) all 16 bit displacement, both in the GetFromEA-type functions and in jump or other particular instructions (e.g.: bra, jsr, stop) 3) all the other places where the program counter is used; in particular the instruction fetch and dispatch loop. I suggest that to save time the instruction code is not swapped at all: the swapping should be performed when filling the 256K emulator table instead, so that the code, although with the two bytes in reverse order, can directly be used as an index in the modified emulator table 4) all the optimized functions which access to partial registers. For example, when adding a byte to d0, the add_b_dn() function directly accesses the fourth byte in the chunk of memory containing the register values. On little endian processors this byte should be the first in the table instead of the fourth. Similar changes are needed for many other instructions which use only the byte or word lowest part of registers
Q: What is RamMap (in the read/write QL memory functions, in file QL68000_general.c)?
A: RamMap is an array. Each position represents a 32K memory chunk (so the array has 32 positions to cover the 68008's 1M addressing space). The value in the array represents the operations which are allowed on the corresponding memory chunk: bit 0=read permission bit 1=write permission bit 2=video memory bit 3=hardware register ie: ram has value 3, rom 1, unused addresses 0, video ram 7, hw registers 8.
Q: How do you manage the 50 hz interrupt of the 8049 and the Keyboard interrupt?
A: First: I don't emulate the keyboard interrupt. Anyway the keyboard is polled by QDOS every 50th of second via the IPC commands 1 (test IPC status) and 8 (read characters from the IPC keyboard buffer). As for the 50Hz interrupt, I have a timer which sets some variables every 20ms. These variables cause an interrupt 2 exception: pendingInterrupt=2; *((uw8*)theROM+0x280a0l)=16; extraFlag=true; nInst2=nInst; nInst=0; Before this, however, the routine checks if interrupt are enabled and if so set the interrupt mask (=8). It also disables further 50Hz interrupts. When the QDOS I2 handler is called, it reads from an hw register the interrupt mask and the value 8 tells it that the cause of the interrupt was the 50hz interrupt. When the QDOS handler has completed, it reenables the interrupts by writing to an hardware register.
Daniele Terdina e-mail: sistest@ictp.trieste.it Feedback is always welcome!
These are mainly interesting for me, but also intended to give new users some idea what to expect. Remember, these are the times with JSROM, you can get much better times with Minerva and/or Lightning
After trying around I implemented a method that may be considered reasonably precise. The preferred method is now this:
make bench1 # mainly CPU emulation make bench2 # mainly text output
I have again changed the details for bench1
so these are now old
results:
B1: 10 t=date 20 for i=1 to 2000:a=sin(1) 30 print date-t and B2: 10 t=date 15 cls 20 for i=1 to 1000:print i, 30 print date-t The Benchmarks also show how much effect some of the optimisations show; the old value is taken without the -DFASTLOOP optimisation. BENCHMARKS: | B1 | B2 Machine | old value | old value | new result | new result(s) --------------------------------------------------------------------- SPARC on remote | 4s | 9-15s display | | --------------------------------------------------------------------- Linux/i486DX-33,8MB,64k | 28s | 71s memory increased to 20MB| 20s | 49s ... 256Kcache/32MB| 19s | 53s --------------------------------------------------------------------- Linux/486DX2-66,12MB, | 19s | 35s no L2 cache | | --------------------------------------------------------------------- Linux/P133/32Mb/S3 | 4s | 9s Trio/1G Scsi | | --------------------------------------------------------------------- Linux/Cyrix 686 PR166 | 3.1s | 6.3s | 2.7 | 6.5s --------------------------------------------------------------------- Linux AMD 5x86 P75 UMC | | 256KB Cache, 16 MB | 8s | 19s --------------------------------------------------------------------- HP-9000/715-65/64MB | 7s | 15s --------------------------------------------------------------------- SGI MIPS R5000/64MB | 4s | 8s ---------------------------------------------------------------------
This document was generated on 22 October 2002 using texi2html 1.56k.