mirror of https://github.com/aufflick/kegs.git
v0.86 sources and binaries (earliest available on website)
This commit is contained in:
commit
cf770f0a3d
|
@ -0,0 +1,410 @@
|
|||
|
||||
Changes in KEGS v0.86 since v0.85 (03/23/04)
|
||||
- Add patch for Solaris sound by Jonathan Kalbfeld.
|
||||
- Fix so that F4 enters config panel even while running Prosel-16
|
||||
- Major mouse pointer changes, based on some ideas from Geoff Weiss.
|
||||
The GSOS mouse now exactly tracks the host pointer automatically.
|
||||
- Fixed an accidental debug halt when Prosel-16 disables the keyboard/mouse.
|
||||
|
||||
Changes in KEGS v0.85 since v0.84 (01/09/04)
|
||||
- Fix some minor 65816 bank-crossing bugs.
|
||||
- Add -noignhalt to allow user to stop on code red halts.
|
||||
- Fix Win32 capslock problem as reported by Edward Moore
|
||||
- Fixed DreamVoir app on the sample image (it was corrupt)
|
||||
|
||||
Changes in KEGS v0.84 since v0.83 (11/21/03)
|
||||
- Add new speed, 8.0MHz directly using right-clicking or F6.
|
||||
- Sim speed and Video update interval added to Config panel.
|
||||
- Various cycle timing bugs in engine_c.c fixed.
|
||||
- Add Config Panel entry to mask serial output to 7-bit, to enable PR#2 to
|
||||
work better with an external telnet.
|
||||
- In Config Panel file selection, typing a letter jumps to the first file
|
||||
beginning with that letter.
|
||||
- Fixed various serial socket bugs. Now you can disconnect a telnet session
|
||||
and start a new one, and a Linux hang is fixed.
|
||||
- Default GS memory size increased to 8MB.
|
||||
- Small fix to double-hires color table.
|
||||
- X windows can now send displays to other-endian X servers.
|
||||
|
||||
Changes in KEGS v0.83 since v0.82 (11/19/03)
|
||||
- Add Memory Size to config panel, with support for up to 14MB of memory
|
||||
(Geoff Weiss)
|
||||
- Add $C04F EMUBYTE support which Bernie II the Rescue defined. (Geoff Weiss)
|
||||
- Fix $CFFF code red's reported by David Wilson.
|
||||
- Add smartport $C70A Format routine (David Wilson).
|
||||
|
||||
Changes in KEGS v0.82 since v0.81 (11/06/03)
|
||||
- Fix superhires display glitch introduced in v0.81.
|
||||
- Improved border handling--XMAS demo looks great.
|
||||
- Fix some X build problems introduced in v0.81.
|
||||
|
||||
Changes in KEGS v0.81 since v0.80 (11/04/03)
|
||||
- Code Red/Yellow warnings about emulation stability
|
||||
- Windows file browsing fixes
|
||||
- Built-in C600 ROM for Apple II 5.25" game compatibility
|
||||
- Turns key repeat back on when exiting from X-windows version
|
||||
- Windows F8 captures the cursor
|
||||
|
||||
Changes in KEGS v0.80 since v0.71 (10/31/03)
|
||||
- Configuration Panel means no more hand-editing configuration files
|
||||
- All emulator state is now saved in "config.kegs"
|
||||
- 3200 color pictures! Video system much improved for display accuracy.
|
||||
- F8 Pointer grabbing works on Mac
|
||||
- ZipGS emulation
|
||||
|
||||
Changes in KEGS v0.71 since v0.70 (11/20/02)
|
||||
- Improved double-hires colors a lot. -dhr140 is no longer the default
|
||||
- Airheart relies on the PC going from 0xffff to 0x0000, so I undid the
|
||||
change from KEGS v0.54 which allowed PC to overflow to 0x10000.
|
||||
This slows KEGS down by about 5%.
|
||||
- Fixed X shared memory bug in KEGS v0.70 with fix from Jonathan Stark.
|
||||
|
||||
Changes in KEGS v0.70 since v0.60 (11/18/02)
|
||||
- New buttons: Middle button is enter-debugger, and right button changes speed
|
||||
- New function key mapping (see README.kegs)
|
||||
- Mac OS X port
|
||||
- Win32 port
|
||||
- Centralized much of what had been "xdriver.c" code into video.c, to move
|
||||
true platform-specific stuff into the various *driver.c codes.
|
||||
Kimage struct tracks video display buffers in a dev-independent way.
|
||||
From video.c, the calls to the platform code start with "x_" mostly.
|
||||
Code in video.c cleaned up somewhat.
|
||||
Borders are now always in native buffer format, while text/hires/
|
||||
and superhires are in 8-bit buffers and translated to native later.
|
||||
- Mac and Windows sound are all done in one process--no child sound process.
|
||||
- Revamped key press handling and mouse clicks--all is now handled in
|
||||
adb.c for a consistent user interface. Now KEGS implements the
|
||||
same function keys on all platforms. See README.kegs for fn key maps.
|
||||
- I copied the debugger help from Frederic Devernay's KEGS-SDL port.
|
||||
- Fixed an old IWM bug causing bad nibblization due to using uninit vars.
|
||||
- Gilles Tschopp workaround to use corrupted 2IMG files (from KEGS-OSX).
|
||||
- Gilles Tschopp provided code to zero //gs memory at startup (from KEGS-OSX)
|
||||
- Simple code to try to use Mac Diskcopy format disks
|
||||
- Ignore writes to 0xc0a8
|
||||
- Search in $HOME and the launch directory (for mac) for kegs_conf/ROM
|
||||
- Remove font65.sim file by integrating it into kegsfont.h.
|
||||
- "-bw" option forces black and white hires mode.
|
||||
|
||||
|
||||
Changes in KEGS v0.60 since v0.59 (10/03/00)
|
||||
- The 16-bit colors were still wrong due to another coding error. It would
|
||||
be much easier to get this right if I had a 16-bit color display...
|
||||
A user says it works now.
|
||||
|
||||
Changes in KEGS v0.59 since v0.58 (7/07/00)
|
||||
- Added support for multiple paths to the default files and also multiple
|
||||
names for many default files. This should make the .rpm distribution
|
||||
work better.
|
||||
- Add another keycode to mean break according to mic@research.nj.nec.com.
|
||||
- Add support for various ROMs to get plugged into slot 1-7.
|
||||
- Fix code so that it should compile on 64-bit platforms.
|
||||
|
||||
Changes in KEGS v0.58 since v0.57 (2/08/00)
|
||||
- Setting the execute bit on the disk image no longer means no-write-thru.
|
||||
Too many new users were getting confused by this.
|
||||
- Fixed another bug with Apple //e bank switching created by v0.56
|
||||
Reported by phoenyx.
|
||||
- Add command line option "-v" to turn on some verbose debugging flags.
|
||||
- Fixed potential core-dump bug with non-8 bit visuals.
|
||||
- Fixed double-lo-res color problem.
|
||||
- The X driver should work with any visual depth display now and get the
|
||||
colors right. Ian Schmidt reported his 16-bit card had bad colors.
|
||||
|
||||
Changes in KEGS v0.57 since v0.56 (12/27/99)
|
||||
- Another try at making timezone stuff work across all Unix variants.
|
||||
Let me know if the time in the Apple //gs control panel doesn't
|
||||
match your real local time.
|
||||
- Fix a bug created in v0.56 where the fast //e bank switch code had a typo.
|
||||
This prevented ZBasic from working correctly.
|
||||
|
||||
Changes in KEGS v0.56 since v0.55 (10/31/99)
|
||||
- Faster Apple //e bank switch emulation.
|
||||
- Simplified number of global variables for various softswitches.
|
||||
- Fixed a bug which made 3.5" and 5.25" disk access much slower than necessary.
|
||||
- Improved scan-line interrupt accuracy (lets MEGADEMO run).
|
||||
- Improved sound interrupt accuracy (was hoping this would fix some sound
|
||||
issues, but it doesn't seem to help).
|
||||
- Add Mode_switch as an alias for the Option key
|
||||
- I noticed the //gs self-tests were broken again--fixed.
|
||||
|
||||
Changes in KEGS v0.55 since v0.54 (10/19/99)
|
||||
- In LOG_PC debug aid, add cycles to the trace
|
||||
- Fix MEGADEMO bug where 3.5" disks weren't properly ejected. Needed to
|
||||
look at iwm.motor_on35 not iwm.motor_on.
|
||||
- Temp fix for MEGADEMO to not halt if shadow-in-all-banks is on in $c036.
|
||||
- Another MEGADEMO fix to not take a scan-line int if the SCB was cleared
|
||||
right before the raster got to this line.
|
||||
- Fix bug in smartport.c that was causing core dumps if you tried to init
|
||||
a disk is s7dx.
|
||||
|
||||
Changes in KEGS v0.54 since v0.53 (10/10/99)
|
||||
- Add support for Out Of This World's direct reading of ADB RAM loc 0xb to
|
||||
get key status. This lets shift/control work in OOTW.
|
||||
- Code simplification to get rid of most set_halt() calls and use halt_printf.
|
||||
- Speed improvement: track kpc (merged kbank and pc in one 32 bit variable)
|
||||
which makes the inner loop faster. This does make KEGS not
|
||||
accurately model a 65816 code crossing bank boundaries, but just
|
||||
about every other emulator gets it wrong, and the speed improvement
|
||||
is 5-10%. And I don't know of any code which relies on it
|
||||
working correctly.
|
||||
- Fix to allow better GS/OS compatibility: after each smartport call,
|
||||
set 0x7f8 = 0xc7.
|
||||
- Fixed ZipGS emulation bug where KEGS was not re-locking Zip at the right
|
||||
time, which made double-hires not work after booting GS/OS.
|
||||
|
||||
Changes in KEGS v0.53 since v0.52 (8/3/99)
|
||||
- Move all the "fcycles" timing calculations to use double instead of float.
|
||||
- Fix display shadowing bug reported by "phoenyx" which caused the text
|
||||
display to not always be updated correctly with funny bank switching.
|
||||
- Added the "Home" key as an alias for the '=' on the keypad.
|
||||
- Changed the way X modifiers are interpreted to increase compatibility of
|
||||
Caps Lock to more X servers.
|
||||
- Add -dhr140 option to use old double-hires color mode that results in
|
||||
exactly 140 horizontal pixels with no bleeding. It's set default
|
||||
to "on" for now while I work out double-hires colors.
|
||||
- Started adding some ZipGS compatibility--control panels run, but all
|
||||
the controls are effectively ignored by KEGS.
|
||||
|
||||
Changes in KEGS v0.52 since v0.51 (6/27/99)
|
||||
- Small speed-up of interpreter loop to avoid checking the global variable
|
||||
"halt_sim" after every instruction.
|
||||
- Smartport fixes to avoid halts when the SCSI CD player NDA is installed.
|
||||
- Fix to autodetect X visual depth (it didn't work at all in v0.51).
|
||||
- Fix to HP binary--KEGS v0.51 hit an HP linker bug which caused the
|
||||
executable to not run correctly. (It didn't obey an assembly-
|
||||
language alignment command correctly). Re-ordering the object
|
||||
list works around the problem.
|
||||
|
||||
Changes in KEGS v0.51 since v0.50 (6/1/99)
|
||||
- Fixed many bugs that crept into scanline interrupts over the last few months.
|
||||
- RAM size is now settable on the commandline: -mem 0x400000 will use
|
||||
a 4MB expansion RAM card (giving you 4.25MB of memory with ROM 01).
|
||||
- VBL time used to be a variable (which was wrong)--it's now always the
|
||||
same number of cycles.
|
||||
- Typo preventing joystick_driver.c from compiling fixed.
|
||||
- Auto senses X visual depth, searching for 8 bit, then 15 bit, then 24,
|
||||
then 16 bit visuals. Can still override this with commandline.
|
||||
|
||||
Changes in KEGS v0.50 since v0.49 (5/31/99)
|
||||
- Added Linux joystick support with code provided by Jonathan Stark.
|
||||
Activate with "-joystick" command line option.
|
||||
- Small improvements in s7 device handling. If you have no s7 devices or no
|
||||
bootable devices, KEGS launches Applesoft.
|
||||
- Bug fix in scan-line interrupts--they were occurring at the wrong time
|
||||
previously.
|
||||
- Rewrote double-hires color routines. They're still not quite right,
|
||||
but it's a lot better than it used to be.
|
||||
|
||||
Changes in KEGS v0.49 since v0.48 (5/3/99)
|
||||
- Fixed a key-repeat bug in v0.48 caused usually with shift-key sequences.
|
||||
- Fixed bug where GNO would not work with ROM 03. ROM area at $C071-$C07F
|
||||
is different from ROM 01.
|
||||
- Ian Schmidt pointed out a special Ensoniq case where an oscillator in
|
||||
one-shot mode can cause it's partner to start if it is in swap mode.
|
||||
- Integrated in Geoff Weiss's Solaris x86 ports. I might have broken it
|
||||
making a few last-minute changes...
|
||||
|
||||
Changes in KEGS v0.48 since v0.47 (4/13/99)
|
||||
- Even better ADB key repeat--key rollover works more like a real Apple //gs.
|
||||
- IWM fix: some "smarport" modes were being activated sometimes during
|
||||
normal 3.5" accesses, resulting in some games not loading correctly.
|
||||
- Some fixes to serial port emulation to handle programs writing to
|
||||
the serial port in MIDI mode when the chars will not be consumed.
|
||||
- Smartport fix to set zero-page locations $42-$47, needed by some poorly-
|
||||
written game loaders
|
||||
- The "oscilloscope" effect in some sound-demos now shows the sounds
|
||||
being played.
|
||||
|
||||
Changes in KEGS v0.47 since v0.46 (4/7/99)
|
||||
- ADB fix #1: reading $c010 should give key-down status better
|
||||
- ADB fix #2: key repeat was stopping if modifier key pressed
|
||||
- ADB fix #3: The game "Pirates" was crashing on startup due to a small bug.
|
||||
- Bard's Tale 2 was freezing on startup due to a bug in the WAI instruction.
|
||||
- Major serial port rewrite. Diversi-Tune now runs and sound OK (but there
|
||||
are some small problems) and serial port emulation is better.
|
||||
|
||||
Changes in KEGS v0.46 since v0.45 (3/21/99)
|
||||
- Fix for undefined var in engine_c.c. Oops.
|
||||
- Fix for old bug in engine_c.c causing KEGS to sometimes misinterpret
|
||||
instructions which cross page boundaries. Was causing Thexder not
|
||||
to work, at least.
|
||||
|
||||
Changes in KEGS v0.45 since v0.44 (3/20/99)
|
||||
- Fix for COP instruction in engine_c.c. Pointed out by Kelvin Sherlock.
|
||||
- Major fixes to Ensoniq emulation, SynthLab sounds much better.
|
||||
- Fix to iwm.c to deal with corrupt 2IMG archives a little better.
|
||||
|
||||
Changes in KEGS v0.44 since v0.43 (2/23/99)
|
||||
- -audio 0 option would often cause programs to hang. Bug was that the
|
||||
audio rate was defaulting to '0' which confused KEGS.
|
||||
- Made keycode 0x072 be the XK_Break key for XFree86
|
||||
|
||||
Changes in KEGS v0.43 since v0.42 (2/19/99)
|
||||
- Support .nib 5.25" format as read-only
|
||||
- Faster 3.5" nibblization routines (should make startup faster)
|
||||
- Fixed a very-old 3.5" disk writing bug that made bit-copiers not work
|
||||
|
||||
Changes in KEGS v0.42 since v0.41 (2/1/99)
|
||||
- Include <errno.h> to fix Linux compile problem
|
||||
- Fix relative branch timing bug that was making IWM emulation flaky
|
||||
(backward branches should count as 3 cycles if to the same page,
|
||||
and 4 if to a different page in emulation mode. Bug always counted
|
||||
them as 4)
|
||||
- Gave up on fast 5.25" writes--KEGS always slows to 1MHz for 5.25"
|
||||
writes since the timing and kludges just got too annoying.
|
||||
- add "-arate 22050" option to change audio sample rate on the command-line.
|
||||
Slower audio rates can hit more audio bugs (I'm working on them).
|
||||
- fixed little-endian bug in smartport.c and partls.c
|
||||
- fixed side border redraw bug that would sometimes leave super-hires
|
||||
images on the right-side border.
|
||||
|
||||
Changes in KEGS v0.41 since v0.40 (1/19/99)
|
||||
- Fixed bug where fill-line mode would not always redraw the screen correctly
|
||||
- Changed some // comments to /* */ to help David Wilson's Solaris port
|
||||
- Fixed little-endian bugs in smartport.c preventing mounting of
|
||||
parititioned disks. Fix submitted by Jonathan Stark.
|
||||
- Christopher Neufeld noted that fast space/delete option in the control
|
||||
panel caused KEGS to hit breakpoints. I fixed this and fast arrows and
|
||||
fast mouse options (they are now just ignored).
|
||||
- Solaris port by David Wilson now provides a Makefile_solaris
|
||||
|
||||
Changes in KEGS v0.40 since v0.39 (10/25/98)
|
||||
- 15 and 24 bit depth displays now supported (though somewhat slower than
|
||||
8 bit displays). But Super-hires displays now show 256
|
||||
simultaneous colors on a 16- or 24-bit X display.
|
||||
Select a 15-bit display with the cmd line option "-15" and
|
||||
a 24-bit display with "-24". Otherwise, KEGS defaults to looking
|
||||
for an 8-bit display, and fails if it cannot find one.
|
||||
- Some border fixes--border colors now update correctly when palette
|
||||
changes occur (like via F10).
|
||||
- Alias F1 to ESC for OS/2.
|
||||
|
||||
Changes in KEGS v0.39 since v0.38 (9/13/98)
|
||||
- OS/2 port by Tschopp Gilles
|
||||
- handle cr&lf better in disk_conf
|
||||
- Drive letters work and are not confused with partition names, so
|
||||
s7d1 = D:\images\cd:1 will open partition 1 correctly.
|
||||
- KEGS no longer uses system() to do file copies, it does it all
|
||||
using POSIX calls.
|
||||
- Unix-specific socket calls moved from scc.c to scc_driver.h
|
||||
- Default X handler re-installed properly now for better debug
|
||||
- Nasty core dump bug found and fixed by Tschopp Gilles in disk switch code
|
||||
|
||||
Changes in KEGS v0.38 since v0.37 (7/28/98)
|
||||
- IWM bugs:
|
||||
- fast_disk_emul off under GS/OS caused I/O errors.
|
||||
KEGS was always slowing down to 1MHz when 5.25" drive was on, when
|
||||
it should have been obeying the $C036 register.
|
||||
- bug in IWM on little-endian processors
|
||||
- disk ejection should now work, but a beta user claimed some bugs on
|
||||
x86 Linux.
|
||||
- 2IMG support, but only lightly tested.
|
||||
- Removed some internal breaks on access to $C0B0 for tool033.
|
||||
- Modulae also stumbled into some breakpoints by writing to $C02F,
|
||||
which does nothing.
|
||||
- Screen refresh simplified (for me) by redrawing the screen while
|
||||
raster is on first scan-line, rather than line 200.
|
||||
However, a side effect is some of the graphics during the XMAS DEMO
|
||||
look a bit choppier.
|
||||
- More SCC fixes to avoid breakpoints under GNO.
|
||||
- Start support for sound under Linux, but it sounds horrible right now.
|
||||
Any Linux sound gurus want to help out?
|
||||
- Fixed possible array-overrun bug in video.c around border effects.
|
||||
Maybe shared memory works under x86 Linux now?
|
||||
- Made changes for OS/2 port to fopen() text files. From Blue Neon.
|
||||
|
||||
|
||||
Changes in KEGS v0.37 since v0.36 (7/13/98)
|
||||
- Linux PPC port completed and functional. KEGS has been tested to
|
||||
run quite well and quite fast on a 240MHz 604e running
|
||||
MkLinux pre-DR3.
|
||||
- Change LITTLE_ENDIAN define to KEGS_LITTLE_ENDIAN since Linux
|
||||
always defines LITTLE_ENDIAN as a silly macro.
|
||||
- Dumb bug in IWM 3.5" routines could cause core dumps if disk arm moved
|
||||
from outer track to inner track very quickly.
|
||||
- Deleted some breakpoints that some Second Sight searching code would hit.
|
||||
- Ignore some SCC reset commands GNO would use that caused KEGS to stop.
|
||||
- Handle odd partitions better--some //gs formatted Zips had a blocksize
|
||||
of 0, which defaults to 512 now.
|
||||
- Handle some keysyms better to avoid MkLinux bug with keysym 0.
|
||||
|
||||
Changes in KEGS v0.36 since v0.35 (5/30/98)
|
||||
|
||||
- Linux x86 port completed and functional with help from Karl Pfleger
|
||||
- Linux clock fixes--should handle daylight savings better on Linux
|
||||
- LITTLE_ENDIAN defines
|
||||
- Start making fixes for NeXTStep due to Eric Sunshine
|
||||
- Fixed bug in HP asm code with I/O fetches--caused //gs selftests to fail
|
||||
and a bug in scc.c was also causing self-tests to fail.
|
||||
|
||||
Changes in KEGS v0.35 since v0.34 (5/17/98)
|
||||
|
||||
- engine_c.c fully implemented--KEGS now has a version completely written
|
||||
in C, and now portable to other Unix machines.
|
||||
- KEGS got another 5% faster with more tweaks to the asm dispatch loop.
|
||||
|
||||
Changes in KEGS v0.34 since v0.33
|
||||
|
||||
- KEGS is 10-15% faster due to finally implementing a planned recoding
|
||||
of the dispatch loop.
|
||||
|
||||
Changes in KEGS v0.33 since v0.32 (5/7/98)
|
||||
|
||||
- Fixed bug in engine_s.s that prevented compiling on pre-10.20 systems.
|
||||
- ADB mouse interrupts work now. Fixed "bug" where GSHK would think
|
||||
mouse button was depressed at startup. (GS/OS is looking at mouse
|
||||
button 1 status, which accidentally was reading as down).
|
||||
- ADB emulation of read char_sets and read_kbd_layouts now matches a real
|
||||
//gs.
|
||||
- optimization to allow dereferencing page_info[] even if BANK_IO is set,
|
||||
to get a small speed improvement in engines_s:dispatch().
|
||||
- SCC logs are 'Z' at the disas prompt.
|
||||
- Tool decoded is 'T' at the disas prompt.
|
||||
- SCC changes to support slot 1 == port 6501 and slot 2 == port 6502,
|
||||
with limited interrupt support. Most serial tasks won't work still,
|
||||
but some do. PR#1/2 and IN#1/2 work fine. getty under GNO doesn't.
|
||||
- -audio [0/1] forces audio off/on. This just stops the sound playing--
|
||||
internally all Ensoniq interrupts/etc are fully emulated. If display
|
||||
is not using shared memory (i.e., it's remote), audio defaults to off.
|
||||
(but can be forced on with -audio 1).
|
||||
- -display {foo} sends X display to {foo}.
|
||||
|
||||
Changes in KEGS v0.32 since v0.31 (10/23/97)
|
||||
|
||||
- Faster dispatch loop, for a 10-15% overall performance improvement
|
||||
- Fixed sound bug where Oversampler would make KEGS halt (Oversampler
|
||||
said turn on 128 oscillators, and KEGS tried to...)
|
||||
- Fixed bug where KEGS would not work on 24-bit displays due to a typo.
|
||||
- Added frame skipping support (-skip n) and auto frame skipping if you
|
||||
are not using shared memory (like displaying KEGS to a remote machine).
|
||||
- Added -noshm support for forcing off shared memory, so you can see how
|
||||
much it helps.
|
||||
|
||||
Changes in KEGS v0.31 since v0.30 (9/23/97)
|
||||
|
||||
- New mouse handling--Press F8 to hide X windows cursor and constrain
|
||||
cursor inside window. Makes using the mouse much easier.
|
||||
F8 toggles back to normal.
|
||||
- Add revision to status area.
|
||||
- Remove "slow memory" calculation. KEGS was emulating slowing down to
|
||||
1MHz to write to slow memory (bank $E0 or $E1). But true //gs
|
||||
accelerators have a smarter trick, so I just removed it from
|
||||
KEGS. KEGS still slows down for I/O reads and writes.
|
||||
This eliminates the confusing 40MHz speed numbers you'd sometimes get.
|
||||
KEGS can also now run faster when it would have slowed down to
|
||||
1MHz before.
|
||||
- Turn off accurate IWM emulation be default, for much faster emulation.
|
||||
Bit copiers won't work by default now. Toggle accurate IWM
|
||||
with F7. Accurate IWM forces 1MHz speed for 5.25" and 2.5MHz for
|
||||
3.5", but less accurate IWM runs as fast as possible.
|
||||
- Add optional size to s7dx entries in disk_conf, to allow using /dev/rfloppy.
|
||||
- Allow mounting partitions by number, instead of just by name, since some
|
||||
Mac-formatted Zip disks don't have partition names.
|
||||
- Add -ignbadacc to ignore bad memory accesses.
|
||||
- Increase MAX_C030_TIMES. Otherwise, fast workstations could generate too
|
||||
many clicks per VBL, causing an assertion to fail.
|
||||
- Small speed increase detecting changes in the superhires screen.
|
||||
- Alt_L is now Open-Apple, and Alt_R is Closed-Apple.
|
||||
- KEGS now uses just one private colormap, so xwd can get screendumps.
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>KEGSMAC</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>kegsicon.icns</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.1</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
APPL????
|
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
IBClasses = ();
|
||||
IBVersion = 1;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>152 85 356 240 0 0 1280 832 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>29</key>
|
||||
<string>69 252 182 44 0 0 1280 832 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>291.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6R73</string>
|
||||
<key>targetFramework</key>
|
||||
<string>IBCarbonFramework</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,169 @@
|
|||
<?xml version="1.0" standalone="yes"?>
|
||||
<object class="NSIBObjectData">
|
||||
<string name="targetFramework">IBCarbonFramework</string>
|
||||
<object name="rootObject" class="NSCustomObject" id="1">
|
||||
<string name="customClass">NSApplication</string>
|
||||
</object>
|
||||
<array count="18" name="allObjects">
|
||||
<object class="IBCarbonMenu" id="29">
|
||||
<string name="title">main</string>
|
||||
<array count="3" name="items">
|
||||
<object class="IBCarbonMenuItem" id="185">
|
||||
<string name="title">KEGSMAC</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="184">
|
||||
<string name="title">KEGSMAC</string>
|
||||
<array count="3" name="items">
|
||||
<object class="IBCarbonMenuItem" id="187">
|
||||
<string name="title">About KEGSMAC</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">abou</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="199">
|
||||
<boolean name="separator">TRUE</boolean>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="198">
|
||||
<string name="title">Quit</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">quit</ostype>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSAppleMenu</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="127">
|
||||
<string name="title">File</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="131">
|
||||
<string name="title">File</string>
|
||||
<array count="1" name="items">
|
||||
<object class="IBCarbonMenuItem" id="200">
|
||||
<string name="title">Configuration F4</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">KCFG</ostype>
|
||||
<string name="helpTagText">Enter KEGS Configuration Panel</string>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="192">
|
||||
<string name="title">Window</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="195">
|
||||
<string name="title">Window</string>
|
||||
<array count="6" name="items">
|
||||
<object class="IBCarbonMenuItem" id="197">
|
||||
<string name="title">Zoom Window</string>
|
||||
<ostype name="command">zoom</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="190">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Minimize Window</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">mini</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="191">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Minimize All Windows</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">mina</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="194">
|
||||
<boolean name="separator">TRUE</boolean>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="196">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Bring All to Front</string>
|
||||
<ostype name="command">bfrt</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="193">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Arrange in Front</string>
|
||||
<int name="keyEquivalentModifier">1572864</int>
|
||||
<ostype name="command">frnt</ostype>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSWindowsMenu</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSMainMenu</string>
|
||||
</object>
|
||||
<reference idRef="127"/>
|
||||
<reference idRef="131"/>
|
||||
<object class="IBCarbonMenuItem" id="153">
|
||||
<string name="title">Window</string>
|
||||
<object name="submenu" class="IBCarbonMenu">
|
||||
<string name="title">Window</string>
|
||||
<array count="5" name="items">
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Minimize Window</string>
|
||||
<string name="keyEquivalent">m</string>
|
||||
<ostype name="command">mini</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Minimize All Windows</string>
|
||||
<string name="keyEquivalent">m</string>
|
||||
<int name="keyEquivalentModifier">1572864</int>
|
||||
<ostype name="command">mini</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="separator">TRUE</boolean>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Bring All to Front</string>
|
||||
<ostype name="command">frnt</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Bring in Front</string>
|
||||
<int name="keyEquivalentModifier">1572864</int>
|
||||
<ostype name="command">frnt</ostype>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSWindowsMenu</string>
|
||||
</object>
|
||||
</object>
|
||||
<reference idRef="184"/>
|
||||
<reference idRef="185"/>
|
||||
<reference idRef="187"/>
|
||||
<reference idRef="190"/>
|
||||
<reference idRef="191"/>
|
||||
<reference idRef="192"/>
|
||||
<reference idRef="193"/>
|
||||
<reference idRef="194"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="196"/>
|
||||
<reference idRef="197"/>
|
||||
<reference idRef="198"/>
|
||||
<reference idRef="199"/>
|
||||
<reference idRef="200"/>
|
||||
</array>
|
||||
<array count="18" name="allParents">
|
||||
<reference idRef="1"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="127"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="185"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="184"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="192"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="184"/>
|
||||
<reference idRef="184"/>
|
||||
<reference idRef="131"/>
|
||||
</array>
|
||||
<dictionary count="2" name="nameTable">
|
||||
<string>Files Owner</string>
|
||||
<reference idRef="1"/>
|
||||
<string>MenuBar</string>
|
||||
<reference idRef="29"/>
|
||||
</dictionary>
|
||||
<unsigned_int name="nextObjectID">201</unsigned_int>
|
||||
</object>
|
Binary file not shown.
|
@ -0,0 +1,113 @@
|
|||
|
||||
NOTE: The build process changed as of KEGS v0.70!
|
||||
|
||||
General build instructions:
|
||||
--------------------------
|
||||
|
||||
You need to build with a make utility. I've only tested GNU make.
|
||||
There's a default Makefile, which should work for nearly any environment.
|
||||
The Makefile includes a file called "vars" which defines the platform-
|
||||
dependent variables. You need to make vars point to the appropriate
|
||||
file for your machine.
|
||||
|
||||
This makes my maintenance of the diverse platforms a bit easier.
|
||||
|
||||
WIN32 build instructions:
|
||||
------------------------
|
||||
|
||||
See the file README.win32 for build instructions and other information
|
||||
for Microsoft Windows.
|
||||
|
||||
|
||||
Mac OS X build instructions (the default):
|
||||
------------------------------------------
|
||||
|
||||
KEGS is easy to compile. Just cd to the src directory and type "make".
|
||||
KEGS requires perl to be in your path (or just edit the vars file to give
|
||||
the full path to wherever you installed perl). Perl version 4 or 5 is
|
||||
fine.
|
||||
|
||||
After the "make" has finished, it will create the application KEGSMAC.
|
||||
|
||||
To run, see README.mac.
|
||||
|
||||
X86 Linux build instructions:
|
||||
----------------------------
|
||||
|
||||
Use the vars_x86linux file with:
|
||||
|
||||
rm vars; ln -s vars_x86linux vars
|
||||
make
|
||||
|
||||
KEGS assumes perl is in your path. If it is somewhere else, you need to edit
|
||||
the "PERL = perl" line in the vars file and make it point to the correct place.
|
||||
|
||||
For audio, KEGS needs access to /dev/dsp. If the permissions do not allow
|
||||
KEGS to access /dev/dsp, it can fail with a cryptic error message. As root,
|
||||
just do: "chmod 666 /dev/dsp".
|
||||
|
||||
|
||||
PowerPC Linux build instructions:
|
||||
----------------------------
|
||||
|
||||
Use the vars_linuxppc vars file by:
|
||||
|
||||
rm vars; ln -s vars_linuxppc vars
|
||||
make
|
||||
|
||||
KEGS assumes perl is in your path. If it is somewhere else, you need to edit
|
||||
the "PERL = perl" line in the vars file and make it point to the correct place.
|
||||
|
||||
Audio is currently disabled by default, but you can try turning it on
|
||||
by runnning "kegs -audio 1". It sounds horrible to me, but sounds do
|
||||
come out.
|
||||
|
||||
Solaris SPARC build instructions:
|
||||
--------------------------------
|
||||
|
||||
Use the vars_solaris vars file by:
|
||||
|
||||
rm vars; ln -s vars_solaris vars
|
||||
make
|
||||
|
||||
KEGS assumes perl is in your path. If it is somewhere else, you need to edit
|
||||
the "PERL = perl" line in the vars file and make it point to the correct place.
|
||||
|
||||
Audio is currently disabled by default, but you can try turning it on
|
||||
by runnning "kegs -audio 1".
|
||||
|
||||
Solaris x86 build instructions:
|
||||
--------------------------------
|
||||
|
||||
Use the vars_x86solaris vars file by:
|
||||
|
||||
rm vars; ln -s vars_x86solaris vars
|
||||
make
|
||||
|
||||
KEGS assumes perl is in your path. If it is somewhere else, you need to edit
|
||||
the "PERL = perl" line in the vars file and make it point to the correct place.
|
||||
|
||||
Audio is currently disabled by default, but you can try turning it on
|
||||
by runnning "kegs -audio 1".
|
||||
|
||||
HP-UX assembly-emulation instructions:
|
||||
-------------------------------------
|
||||
|
||||
Use the vars_hp vars file by:
|
||||
|
||||
rm vars; ln -s vars_hp vars
|
||||
|
||||
Edit the Makefile, and remove "engine_c.o" from the "OBJECTS1=" line at
|
||||
the top. Then just type "make".
|
||||
|
||||
|
||||
Other platform "C" build instructions:
|
||||
-------------------------------------
|
||||
|
||||
I don't know--you tell me. If you are porting to an X-windows and
|
||||
Unix-based machine, it should be easy. Start with vars_x86linux if
|
||||
you are a little-endian machine, or vars_linuxppc if you are big
|
||||
endian. Don't define -DKEGS_LITTLE_ENDIAN unless your processor is
|
||||
little-endian (x86, Alpha). Mac, Sun, MIPS, HP, Motorola, and IBM are
|
||||
big-endian.
|
||||
|
|
@ -0,0 +1,989 @@
|
|||
|
||||
KEGS: Kent's Emulated GS version 0.86
|
||||
http://kegs.sourceforge.net/
|
||||
|
||||
What is this?
|
||||
-------------
|
||||
|
||||
KEGS is an Apple IIgs emulator for Mac OS X, Linux, and Win32.
|
||||
The Apple IIgs was the last released computer in the Apple II line.
|
||||
It first was sold in 1986.
|
||||
|
||||
KEGS supports all Apple IIgs graphics modes (which include all Apple //e
|
||||
modes), plus plays all Apple IIgs sounds accurately. It supports
|
||||
limited serial port emulation through sockets, or can use real serial ports
|
||||
on Windows and Mac OS X.
|
||||
|
||||
The ROMs and GS/OS (the Apple IIgs operating system) are not included
|
||||
with KEGS since they are not freely distributable. KEGS is a little
|
||||
user-hostile now, so if something doesn't work, let me know what went
|
||||
wrong, and I'll try to help you out. See my email address at the end of
|
||||
this file.
|
||||
|
||||
KEGS features:
|
||||
-------------
|
||||
|
||||
Fast 65816 emulation:
|
||||
About 80MHz on a P4 1.7GHz or a G4 1GHz.
|
||||
Emulates low-level 5.25" and 3.5" drive accesses (even nibble-copiers work!).
|
||||
Emulates classic Apple II sound and 32-voice Ensoniq sound.
|
||||
All sound is played in 16-bit stereo at 48KHz (44100 on a Mac).
|
||||
Emulates all Apple IIgs graphics modes, including border effects.
|
||||
Can handle mixed-displays (superhires at the top, lores at the bottom).
|
||||
Always does 60 full screen video updates per second.
|
||||
Even supports 3200-color pictures.
|
||||
Mouse and joystick support.
|
||||
Emulates all Apple IIgs memory "tricks" for full compatibility.
|
||||
Low-level ADB keyboard and mouse emulation enables Wolfenstein 3D to run.
|
||||
Clock chip emulation makes the host time available to the Apple IIgs.
|
||||
Emulated battery RAM remembers control panel settings.
|
||||
Limited SCC (serial port) emulation to enable PR#1/2 IN#1/2 and other
|
||||
serial programs to work.
|
||||
|
||||
KEGS by default emulates a 8MB Apple IIgs, but you can change this with
|
||||
the "-mem" command line option.
|
||||
|
||||
KEGS is so accurate, even the built-in ROM selftests pass (you must be in
|
||||
2.8MHz speed mode to pass the self-tests).
|
||||
|
||||
Release info:
|
||||
------------
|
||||
|
||||
Included files:
|
||||
CHANGES - Description of changes since last release
|
||||
README.kegs - you're here
|
||||
README.compile - Describes how to build KEGS
|
||||
README.linux.rpm - Describes how to install KEGS's RPM for Linux
|
||||
README.win32 - Win32 special directions
|
||||
README.mac - Mac OS X special directions
|
||||
INTERNALS.overview - description of how KEGS code works
|
||||
INTERNALS.xdriver - Describes the xdriver.c routines for porting
|
||||
INTERNALS.iwm - Describes the internal 3.5" and 5.25" disk
|
||||
handling routines
|
||||
kegs - the executable, for HP-UX 10.20+
|
||||
kegs.spec - The Linux spec file for making an RPM
|
||||
kegs_conf - disk image configuration info
|
||||
to_pro - Hard-to-use ProDOS volume creator
|
||||
partls - Lists partitions on Apple-partitioned hard
|
||||
drives or CD-ROMs
|
||||
src/ - All the source code, with a Makefile
|
||||
|
||||
You need to provide:
|
||||
|
||||
1) Patience.
|
||||
2) a ROM file called "ROM", "ROM.01" or "ROM.03" in the KEGS directory.
|
||||
It can be either from a ROM 01 (131072 bytes long) or from a
|
||||
ROM 03 machine (262144 bytes long.)
|
||||
3) A disk image to boot. This can be either "raw" format or 2IMG.
|
||||
See discussion below. GS/OS would be best.
|
||||
|
||||
Getting ROMs
|
||||
------------
|
||||
|
||||
You need a copy of the memory from fe/0000 - ff/ffff from a ROM 01 GS
|
||||
or fc/0000 - ff/ffff from a ROM 03 GS, and put that in a file called
|
||||
"ROM". I'll eventually write detailed instructions on how to do this.
|
||||
|
||||
Running KEGS:
|
||||
------------
|
||||
|
||||
The distribution comes in 3 parts: a source-only distribution (kegs.xxx.tar.gz),
|
||||
along with two binary distributions for Mac and Windows.
|
||||
|
||||
See the README.compile file for more info about compiling for Linux.
|
||||
|
||||
On all platforms except the Mac, you must start KEGS from a terminal
|
||||
window. KEGS will open a new window and use the window you started it from
|
||||
as a "debug" window.
|
||||
|
||||
On a MAC, you need to place the "config.kegs" file someplace where KEGS
|
||||
can find it. The simplest place is in your home directory, so copy it there
|
||||
with the Finder (or using the Terminal).
|
||||
|
||||
Start kegs by Double-clicking the KEGSMAC icon on a MAC, or by running
|
||||
the executable (kegswin on Windows, and kegs on Linux). KEGSMAC can
|
||||
be run by the Terminal window as well (which enables access to more debug
|
||||
information) by typing: "./KEGSMAC.app/Contents/MacOS/KEGSMAC".
|
||||
|
||||
Assuming all goes well, KEGS will then boot up but probably not find any
|
||||
disk images. See below for how to tell KEGS what disk images to use.
|
||||
Tip: Hitting "F8" locks the mouse in the window (and hides the host cursor)
|
||||
until you hit "F8" again.
|
||||
|
||||
Disk Images:
|
||||
-----------
|
||||
|
||||
You tell KEGS what disk images to use through the Configuration panel.
|
||||
|
||||
You enter the Configuration panel by pressing F4 at any time. Then select,
|
||||
"Disk Configuration". Each slot and drive that can be loaded with an image
|
||||
is listed. "s5d1" means slot 5, drive 1. Slot 5 devices are 3.5" 800K disks,
|
||||
and slot 6 devices are 5.25" 140K disks. Slot 7 devices are virtual hard
|
||||
drives, and can be any size at all (although ProDOS-formatted drives
|
||||
should be less than 32MB).
|
||||
|
||||
Just use the arrow keys to navigate to the device entry to change,
|
||||
and then select it by pressing Return. A scrollable file selection
|
||||
interface is presented, letting you located your image files. To
|
||||
save navigation, you can press Tab to toggle between entering a path
|
||||
manually, and using the selector. Press Return on ".." entries to go up
|
||||
a directory level. When you find the image you want, just press Return.
|
||||
|
||||
If the image has partitions that KEGS supports, another selection
|
||||
dialog will have you select which partition to mount. You will probably
|
||||
only have partitions on direct devices you mount. For instance, on a
|
||||
Mac, /dev/disk1 is usually the CDROM drive.
|
||||
|
||||
KEGS can handle "raw", .dsk, .po, 2IMG, 5.25" ".nib" images, some Mac
|
||||
Diskcopy images and partitioned images. The .dsk and .po formats you often
|
||||
find on the web are really "raw" formats, and so they work fine. KEGS uses
|
||||
the host file permissions to encode the read/write status of the image.
|
||||
|
||||
An image is the representation of an Apple IIgs disk, but in a file on
|
||||
your computer. For 3.5" disks, for example, a raw image would be exactly
|
||||
800K bytes long (819200 bytes). KEGS intercepts the emulated GS accesses to
|
||||
the image, and does the correct reads and writes of the Unix file instead.
|
||||
|
||||
To do "useful" things with KEGS, you need to get a bootable disk image.
|
||||
You can go to http://www.info.apple.com/support/oldersoftwarelist.html and
|
||||
get Apple IIgs System 6. Unfortunately, Apple now only has .sea files which
|
||||
are executable files for Macintosh only. You need a macintosh to execute
|
||||
those programs, which creates Disk Copy image files with no special extensions
|
||||
(and with spaces in the names). Once you get those files back to your
|
||||
host machine, you can use them by listing them in kegs_conf.
|
||||
|
||||
KEGS also supports partitioned devices. For instance, if you have a CD-ROM
|
||||
on your computer, just pop an Apple II CD in, and KEGS can mount it, if
|
||||
you have a Unix-base system (Linux, any Unix, and Mac OS X).
|
||||
|
||||
If you're on a Mac, be careful letting KEGS use your HFS partitions--
|
||||
GSOS has many HFS bugs when it is writing.
|
||||
|
||||
If you do not have any disk mounted in s7d1, KEGS will jump into BASIC.
|
||||
|
||||
Support for 5.25" nibblized images is read-only for now (since the
|
||||
format is kinda simplistic, it's tricky for KEGS to write to it).
|
||||
Just mount your image, like "disk.nib" in the kegs_conf file like
|
||||
any .dsk or .po image.
|
||||
|
||||
|
||||
Key summary:
|
||||
-----------
|
||||
|
||||
F1: Alias of Command
|
||||
F2: Alias of Option
|
||||
F3: Alias of ESC for OS/2 compatibility.
|
||||
F4: Configuration Panel
|
||||
F6: Toggle through the 4 speeds: Unlimited, 1MHz, 2.8MHz, 8.0MHz
|
||||
Shift-F6: Enter KEGS debugger
|
||||
F7: Toggle fast_disk_emul on/off
|
||||
F8: Toggle pointer hiding on/off.
|
||||
F9: Invert the sense of the joystick.
|
||||
Shift-F9: Swap x and y joystick/paddle axes.
|
||||
F10: Attempt to change the a2vid_palette (only useful on 8-bit color display)
|
||||
F11: Full screen mode (does not do anything yet).
|
||||
F12: Alias of Pause/Break which is treated as Reset
|
||||
|
||||
F2, Alt_R, Meta_r, Menu, Print, Mode_switch, Option: Option key
|
||||
F1, Alt_L, Meta_L, Cancel, Scroll_lock, Command: Command key
|
||||
Num_Lock: Keypad "Clear".
|
||||
F12, Pause, Break: Reset
|
||||
|
||||
"Home": Alias for "=" on the keypad (since my Unix keyboard doesn't have an =).
|
||||
|
||||
Using KEGS:
|
||||
----------
|
||||
|
||||
The host computer mouse is the Apple IIgs mouse and joystick by default.
|
||||
By default, the host pointer is not constrained inside the window and
|
||||
remains visible. Press F8 to hide the cursor and constrain the mouse. F8
|
||||
again toggles out of constrain mode. When the GSOS desktop is running,
|
||||
KEGS hides the host cursor automatically and enables special tracking
|
||||
which forces the emulated cursor to follow the host cursor. If this doesn't
|
||||
work right under some program, just press F8 for better compatibility.
|
||||
|
||||
The default joystick is the mouse position. Upper left is 0,0. Lower right
|
||||
is 255,255. Press Shift-F9 to swap the X and Y axes. Press F9 to reverse
|
||||
the sense of both paddles (so 0 becomes 255, etc). Swapping and
|
||||
reversing are convenient with paddle-based games like "Little Brick Out"
|
||||
so that the mouse will be moving like the paddle on the screen. "Little
|
||||
Brick Out" is on the DOS 3.3 master disk. The joystick does not work
|
||||
properly if the pointer is constrained in the window.
|
||||
|
||||
If you have a real joystick on Linux, start KEGS with "-joystick" and
|
||||
you should be able to use it. Real joysticks should also work on Windows.
|
||||
|
||||
The left mouse button is the mouse button for KEGS. The right mouse
|
||||
button (if you have it) or F6 toggles between four speed modes. Mode 0
|
||||
(the default) means run as fast as possible. Mode 1 means run at 1MHz.
|
||||
Mode 2 means run at 2.8MHz. Mode 3 means run at 8.0MHz (about the speed
|
||||
of a ZipGS accelerator). Most Apple //e (or earlier) games need to be
|
||||
run at 1MHz. Many Apple IIgs demos must run at 2.8MHz or they crash. Try
|
||||
running ornery programs at 2.8MHz. 3200 pictures generally only display
|
||||
correctly at 2.8MHz or sometimes 8.0MHz.
|
||||
|
||||
The middle mouse button or Shift-F6 causes KEGS to stop emulation, and enter
|
||||
the debugger. You can continue with "g" then return in the debug window.
|
||||
You can also disassemble memory, etc. The section "Debugging KEGS"
|
||||
above describes the debugger interface a little more.
|
||||
|
||||
KEGS has no pop-up menus or other interactive interfaces (other than
|
||||
the debug window). Input to the debug window is only acted upon when
|
||||
the emulation is stopped by hitting a breakpoint or pressing the right-most
|
||||
mouse button.
|
||||
|
||||
Quitting KEGS:
|
||||
-------------
|
||||
|
||||
Just close the main KEGS window, and KEGS will exit cleanly. Or you
|
||||
can select Quit from the menu. Or enter ctrl-c in the debugger window.
|
||||
Or press the middle-mouse button in the emulation window, and then type
|
||||
"q" return in the debug window.
|
||||
|
||||
|
||||
Debugging KEGS:
|
||||
--------------
|
||||
|
||||
KEGS by default now continues emulation even when it detects buggy programs
|
||||
running. (Now I know why Appleworks GS always seemed to crash!).
|
||||
|
||||
KEGS divides buggy programs into two severities: Code Yellow and Code Red.
|
||||
The status is displayed in words in the text area under the emulation window.
|
||||
If nothing's wrong, nothing is printed.
|
||||
|
||||
A Yellow bug is a mild bug where an Apple IIgs program merely read an
|
||||
invalid location. Although completely harmless, it indicates the potential
|
||||
for some Apple IIgs program bug which may become more severe shortly.
|
||||
For instance, closing the "About This Apple IIgs" window in the Finder
|
||||
causes a code yellow alert, but it seems quite harmless.
|
||||
|
||||
A Code Red bug is a more serious problem. The Apple IIgs program either
|
||||
tried to write non-existent memory, entered an invalid system state, or
|
||||
perhaps just tried to use an Apple IIgs feature which KEGS does not implement
|
||||
yet. Note that entering GSBUG tends to cause a Code Red alert always, so if
|
||||
you intended to enter it, you can ignore it. My recommendation is to
|
||||
save work immediately (to new files) and restart KEGS if you get into the
|
||||
Red mode.
|
||||
|
||||
KEGS also supports breakpoints and watchpoints. In the debug window, you
|
||||
set a breakpoint at an address by typing the address, followed by a 'B'
|
||||
(it must be in caps). To set a breakpoint on the interrupt jump point,
|
||||
type:
|
||||
|
||||
e1/0010B
|
||||
|
||||
To list all breakpoints, just type 'B' with no number in front of it.
|
||||
To delete a breakpoint, enter its address followed by 'D', so
|
||||
|
||||
e1/0010D
|
||||
|
||||
deletes the above breakpoint. The addresses work like the IIgs monitor:
|
||||
once you change banks, you can use shortcut addresses:
|
||||
|
||||
e1/0010B
|
||||
14B
|
||||
|
||||
will add breakpoints at e1/0010 and e1/0014.
|
||||
|
||||
This is a "transparent" breakpoint--memory is not changed. But any
|
||||
read or write to that address will cause KEGS to halt. So you can
|
||||
set breakpoints on I/O addresses, or ROM, or whatever. Setting a breakpoint
|
||||
slows KEGS down somewhat, but only on accesses to the 256 byte "page"
|
||||
the breakpoint is on. Breakpoints are not just instruction breakpoints,
|
||||
they also cause KEGS to halt on any data access, too (usually called
|
||||
watchpoints).
|
||||
|
||||
Frederic Devernay has written a nice help screen available in the
|
||||
debugger when you type "h".
|
||||
|
||||
KEGS command-line option summary:
|
||||
--------------------------------
|
||||
|
||||
-mem {mem_amt}: KEGS will use mem_amt as the amount of expansion RAM in
|
||||
the IIgs. This memory is in addition to the 256KB on a ROM 01
|
||||
motherboard, or 1MB on a ROM 03. The memory is in bytes,
|
||||
and it will be rounded down to the nearest 64KB. "-mem 0x800000"
|
||||
will use 8MB of expansion RAM (the default).
|
||||
-badrd: Causes KEGS to halt on any access to invalid memory addresses.
|
||||
Useful for debugging. By default, KEGS allows reads to invalid
|
||||
memory since the Finder does some (especially when you open the
|
||||
About window, and then close it). But KEGS warns you about these
|
||||
accesses in the debug window. In general, these warnings
|
||||
indicate buggy programs. If the warnings get severe, it's
|
||||
a good sign you should quit KEGS and start over before the
|
||||
emulated program crashes. -badrd would be the default for KEGS
|
||||
if it wasn't for the Finder's About window's problem.
|
||||
-ignbadacc: Causes KEGS to allow reads & writes to invalid memory
|
||||
addresses without printing any warnings. Useful for running
|
||||
extremely buggy programs so you don't have to see all the warning
|
||||
messages scroll by.
|
||||
-skip: KEGS will "skip" that many screen redraws between refreshes.
|
||||
-skip 0 will do 60 frames per second, -skip 1 will do 30 fps,
|
||||
-skip 5 will do 10 fps.
|
||||
-audio [0/1]: Forces audio [off/on]. By default, audio is on unless
|
||||
the X display is a remote machine or shared memory is off.
|
||||
This switch can override the default. -audio 0 causes KEGS to
|
||||
not fork the background audio process, but Ensoniq emulation
|
||||
is still 100% accurate, just the sound is not sent to the
|
||||
workstation speaker. Audio defaults off on Linux for now.
|
||||
-arate {num}: Forces audio sample rate to {num}. 44100 and 48000 are
|
||||
usual, you can try 22050 to reduce KEGS's overhead. On a reasonably
|
||||
fast machine (>250MHz or so), you shouldn't need to mess with this.
|
||||
-dhr140: Will use the old Double-hires color algorithm that results in
|
||||
exactly 140 colors across the screen, as opposed to the blending
|
||||
being done by default.
|
||||
|
||||
X-Windows/Linux options
|
||||
-15: KEGS will only look for a 15-bit X-Window display.
|
||||
-16: KEGS will only look for a 16-bit X-Window display (not tested, probably
|
||||
will get red colors wrong).
|
||||
-24: KEGS will only look for a 24-bit X-Window display.
|
||||
-display {machine:0.0}: Same as setting the environment variable DISPLAY.
|
||||
Sends X display to {machine:0.0}.
|
||||
-joystick: Will use /dev/js0 as the joystick.
|
||||
-noshm: KEGS will not try to used shared memory for the X graphics display.
|
||||
This will make KEGS much slower on graphics-intensive tasks,
|
||||
by as much as a factor of 10! By default, -noshm causes an
|
||||
effective -skip of 3 which is 15 fps. You can override this
|
||||
default by specifying a -skip explicitly.
|
||||
|
||||
|
||||
Command/Option keys:
|
||||
-------------------
|
||||
|
||||
If you have a workstation keyboard with the new Windows keys, you can
|
||||
use them as the command/option keys. This is what I use. Since many people
|
||||
don't have the PC keyboard, there are several alternatives.
|
||||
|
||||
The following keys are Option (closed-apple) (not all keyboards have all
|
||||
keys): F2, Meta_R, Alt_R, Cancel, Print_screen, Mode_switch, Option,
|
||||
or the Windows key just to the right of the spacebar. The following keys are
|
||||
Command (open-apple): F1, Meta_L, Alt_L, Menu, Scroll_lock, Command,
|
||||
the Windows key left of the spacebar, and the Windows key on the far right
|
||||
that looks like a pull-down menu. You can use F1 and F2 if you cannot make
|
||||
anything else work.
|
||||
|
||||
If you can't get any of these to work on your machine, let me know.
|
||||
Note that X Windows often has other things mapped to Meta- and Alt-
|
||||
key sequences, so they often don't get passed through to KEGS. So it's
|
||||
best to use another key instead of Alt or Meta.
|
||||
|
||||
The joystick/paddle buttons are just the Command and Option keys.
|
||||
|
||||
Reset:
|
||||
-----
|
||||
|
||||
The reset key is Pause/Break or F12. You must hit it with Ctrl to get it to
|
||||
take effect (just like a real Apple IIgs). Ctrl-Command-Reset
|
||||
forces a reboot. Ctrl-Command-Option-Reset enters selftests.
|
||||
Selftests will pass if you force speed to 2.8MHz using the middle
|
||||
button. Watch out for ctrl-shift-Break--it will likely kill your
|
||||
X Windows session.
|
||||
|
||||
Control Panel:
|
||||
-------------
|
||||
|
||||
You can get to the Apple IIgs control panel (unless some application
|
||||
has locked it out) using Ctrl-Command-ESC.
|
||||
|
||||
|
||||
How to use "to_pro":
|
||||
-------------------
|
||||
|
||||
This lame utility serves two purposes: It "formats" large disk images,
|
||||
and lets you move files from Unix into the simulator. It does this
|
||||
by taking the files you provide, and putting them onto Unix file called
|
||||
"POOF1" that is an image in ProDOS format.
|
||||
|
||||
So, if you have a wolfdemo.bxy file from an FTP site, you can get it
|
||||
into the emulator by:
|
||||
|
||||
to_pro -800 wolfdemo.bxy
|
||||
|
||||
which creates an 800K Unix file called "POOF1". POOF1 is now an
|
||||
image that can be loaded into KEGS, and when you catalog it, it will
|
||||
have wolfdemo.bxy on it.
|
||||
|
||||
To create a 4MB image:
|
||||
|
||||
to_pro -4096 wolfdemo.bxy
|
||||
|
||||
which puts wolfdemo.bxy on a much larger image.
|
||||
|
||||
I don't know what happens if the file, wolfdemo.bxy, is bigger than
|
||||
the image...it probably crashes.
|
||||
|
||||
Even if you want to format a "blank" image, you have to put something in it.
|
||||
Like:
|
||||
|
||||
echo "This is a lame utility" > foo
|
||||
to_pro -16384 foo
|
||||
|
||||
...creates a 16MB POOF1 with the file foo on it. Just delete foo
|
||||
from within KEGS.
|
||||
|
||||
See? I told you it was a lame utility!
|
||||
|
||||
to_pro can handle up to 51 files at a time--for example:
|
||||
|
||||
to_pro -32000 *.shk
|
||||
|
||||
...would put all *.shk files in the current Unix directory into a 31.25MB
|
||||
image called POOF1.
|
||||
|
||||
To_pro tries to truncate Unix filenames to the 15 character ProDOS
|
||||
limit, and converts all punctuation to dots. I've tested it enough
|
||||
that it has worked for my purposes.
|
||||
|
||||
The algorithm to_pro uses to create a disk volume is possibly suspect.
|
||||
I recommend reformatting any images again inside KEGS (using GS/OS, for
|
||||
instance) just to make sure the directory structure is good. To_pro
|
||||
is intended to put files into images quickly and easily, and then to
|
||||
copy the files off of those images onto images formatted from within
|
||||
KEGS by an Apple IIgs OS.
|
||||
|
||||
Since ProDOS cannot handle > 32MB images, make sure you run to_pro with
|
||||
arguments under 32767. I personally haven't tried a partition bigger
|
||||
than 30000K (about 2.5MB short of the maximum). Well, you can use bigger
|
||||
images if you format them HFS, but I don't trust the GS/OS HFS driver.
|
||||
|
||||
To_pro automatically sets the ProDOS filetype of files ending in ".shk"
|
||||
to $E0.
|
||||
|
||||
Details on config.kegs and disk images
|
||||
--------------------------------------
|
||||
|
||||
The file "config.kegs" describes the images KEGS will use. The sample
|
||||
file has all the lines commented out with '#' to show sample uses.
|
||||
Remember, KEGS will boot s7d1 (unless you've changed that using the
|
||||
Apple IIgs control panel), so you must put an image in that slot.
|
||||
|
||||
Changing disks in slot 7 does not work, but you can move around
|
||||
disks in slots 5 and 6. This allows you to "eject" disks and change them.
|
||||
This is especially useful for multi-disk 5.25" programs.
|
||||
|
||||
KEGS uses the Unix permissions on raw disk images to decide how to load
|
||||
it into the emulator. If the file is unreadable, it cannot load the
|
||||
image (duh).
|
||||
|
||||
KEGS, by default, runs the IWM (3.5" and 5.25" disks) emulation in an
|
||||
"approximate" mode, called "fast_disk_emul". In this mode, KEGS
|
||||
emulates the hardware "faster" than real, meaning the data the code
|
||||
being emulated expects is made available much faster than on a real
|
||||
Apple IIgs, providing a nice speed boost. For instance, the 5.25"
|
||||
drives run 10x the real speed usually. Almost everything will work
|
||||
except for nibble copiers, which don't like the data coming this fast.
|
||||
(Meaning, unless you're using a nibble copier, you shouldn't run into an
|
||||
issue. All games/demos/etc run fine in this mode). To make nibble
|
||||
copiers work, Press F7.
|
||||
|
||||
KEGS can read in the ".nib" nibblized disk format, but as read-only mode. If
|
||||
the emulated image is no longer ProDOS or DOS 3.3 standard, KEGS will
|
||||
automatically treat the image as "Not-write-through-to-Image" from then
|
||||
on. This mode means KEGS will continue to emulate the disk properly in
|
||||
memory, but it cannot encode the changes in the standard .dsk or .nib
|
||||
image format. It prints a message saying it has done so. However,
|
||||
the "disk" in emulation is fully useable as long as KEGS is running. A
|
||||
standard reformatting will not cause an image to flip to not-write-
|
||||
through-to-Image, but running things like a "drive-speed" test will cause
|
||||
further changes not to propagate to the Unix file. You will need
|
||||
to "eject" the image and re-insert it before writes will take effect.
|
||||
|
||||
In full accuracy mode (i.e., not fast_disk_emul), 5.25" drive accesses
|
||||
force KEGS to run at 1MHz, and 3.5" drive accesses force KEGS to run at
|
||||
2.5MHz.
|
||||
|
||||
KEGS Timing:
|
||||
-----------
|
||||
|
||||
KEGS supports running at four speeds: 1MHz, 2.8MHz, 8.0MHz, and Unlimited.
|
||||
Pressing the middle mouse button cycles between these modes. The 1MHz
|
||||
and 2.8MHz speeds force KEGS to run at exactly those speeds, providing
|
||||
accurate reproduction of a real Apple IIgs.
|
||||
|
||||
KEGS will always run at 1MHz at least. If it is unable to keep up,
|
||||
it will extend the emulated time to maintain the illusion of running
|
||||
at 1MHz. That is, it may do just 40 screen refreshes per real second,
|
||||
instead of the usual 60. This happens rarely.
|
||||
|
||||
If you force KEGS to run at 1MHz, it will strive to run at exactly
|
||||
1MHz (well, really 1.024MHz). If it is running faster (almost always),
|
||||
it will pause briefly several times a second to maintain the 1MHz speed. It
|
||||
does this in a friendly way that makes time available to other tasks.
|
||||
This makes older Apple II games very playable just like a
|
||||
real Apple IIgs on slow speed. KEGS is running at exactly the same
|
||||
speed as an Apple //e when in 1MHz mode. The 1MHz mode you set
|
||||
through the right mouse button overrides the "fast" mode you can access
|
||||
through the control panel. But, 3.5" accesses will "speed up" to 2.8MHz
|
||||
to enable that code to operate correctly while the 3.5" disk is being
|
||||
accessed.
|
||||
|
||||
If you force KEGS to run at 2.8MHz, KEGS tries to run at exactly 2.8MHz. But
|
||||
like a real unaccelerated Apple IIgs, if you set the control panel to
|
||||
"slow", it will really be running at 1MHz. Accesses to 5.25" disk
|
||||
automatically slow down to 1MHz, when running the IWM in accurate
|
||||
mode (F7). KEGS may not be able to keep up with some programs running
|
||||
at 2.8MHz due to video and sound overheads on lower-end machines. If
|
||||
that happens, it effectively runs slower by extending the emulated
|
||||
"second", like in the 1MHz mode. You can tell this is happening
|
||||
when Eff MHz in the status area falls below 2.5MHz. If KEGS is running
|
||||
faster than 2.8MHz, it takes small pauses to slow down, just like in
|
||||
1MHz. Many Apple IIgs demos must be run at 2.8MHz. The built-in
|
||||
selftests (cmd-option-ctrl-Reset) must run at 2.8MHz. Many Apple IIgs
|
||||
action games are more playable at 2.8MHz.
|
||||
|
||||
The 8.0MHz setting means follow the ZipGS-selected speed, but don't go
|
||||
faster than 8.0MHz. If your host computer cannot keep up, then the
|
||||
emulated second will be extended. You can use the ZipGS control panel,
|
||||
or ZIPPY.GS on the sample disk image to set the emulated ZipGS speed to
|
||||
anything from 1MHz to 8MHz in .5MHz increments.
|
||||
|
||||
The Unlimited setting means run as fast as possible, whatever speed that
|
||||
is (but always above 1MHz). Eff MHz gives you the current Apple IIgs
|
||||
equivalent speed. Many games will be unplayable at the unlimited
|
||||
setting. Setting the IIgs control panel speed to "slow" will slow down
|
||||
to 1MHz.
|
||||
|
||||
Sound output has an interesting relationship to KEGS timing. KEGS must
|
||||
play one second of sound per second of emulated time. Normally, this
|
||||
works out exactly right. But as noted above, if KEGS can't maintain the
|
||||
needed speed, it extends the emulated second. If it extends the second
|
||||
to 1.4 real seconds, that means KEGS only produces 1.0 second of sound
|
||||
data every 1.4 seconds--the sound breaks up!
|
||||
|
||||
In all cases, 1MHz to KEGS is 1.024MHz. And 2.8MHz to KEGS is 2.52MHz
|
||||
(trying to approximate the slowdown causes by memory refresh on a real
|
||||
Apple IIgs). It's just easier to say 1MHz and 2.8MHz.
|
||||
|
||||
|
||||
KEGS SAMPLE_DISK:
|
||||
----------------
|
||||
|
||||
I'm providing a sample disk of freely available utilities/programs to
|
||||
demonstrate a little of what KEGS can do. I'm also including my simple
|
||||
changes to a benchmark called "SPEEDTEST" to make it run under ProDOS and
|
||||
time itself automatically. The SAMPLE_DISK is not bootable since I'm
|
||||
not sure if I can distribute PRODOS (the OS).
|
||||
|
||||
|
||||
SPEEDTEST:
|
||||
---------
|
||||
|
||||
In the folder "SPEEDTEST", there are two BASIC programs. OLD.SPEEDTEST
|
||||
is the old, unmodified DOS 3.3 emulator benchmark by Clayten Hamacher.
|
||||
It does not run properly under ProDOS 8. My modified version is
|
||||
SPEED.PRO, meaning converted to ProDOS. I made few modifications, other
|
||||
than to make the benchmarks time themselves.
|
||||
|
||||
To run, just say "RUN SPEED.PRO". To run benchmarks, press "B". If
|
||||
you say "A)ll tests", make sure you have a 5.25" disk image in s6d1!
|
||||
(A blank 140K image will work fine).
|
||||
|
||||
This modified SPEED.PRO can run on ANY Apple IIgs emulator (or on the real
|
||||
thing).
|
||||
|
||||
GSOS7, GSOS5, BYE.SYSTEM:
|
||||
------------------------
|
||||
|
||||
These are handy utilities I use on my s7d1 boot disk. Get a GS/OS 6.x
|
||||
bootable disk image. (See GSOS.INFO file for how to get GS/OS).
|
||||
Remove "PRODOS" from that disk's root directory, and copy GSOS7 to
|
||||
the root directory. Then copy SYSTEM/P8 to PRODOS. Then move
|
||||
BASIC.System into SYSTEM/. Then copy BYE.SYSTEM to the root directory,
|
||||
then move BASIC.SYSTEM back to the root directory.
|
||||
|
||||
What all this means is that now the root directory of your system disk
|
||||
is: GSOS7, (other stuff), PRODOS, BYE.SYSTEM, and BASIC.SYSTEM.
|
||||
When you boot, ProDOS will boot (this is PRODOS 8) and will search
|
||||
for the first *.SYSTEM file, and run it. BYE.SYSTEM just does a BYE
|
||||
command, which puts you in the PRODOS 8 textual launcher.
|
||||
If you now select GSOS7 (the first entry, already highlighted, just
|
||||
hit return), it will boot GSOS on slot 7. (Use GSOS5 to boot slot5).
|
||||
Or, just move down and select BASIC.SYSTEM to go to BASIC. A very simple
|
||||
program launcher!?
|
||||
|
||||
Note that I didn't write GSOS5 or GSOS7--I just made a one byte hack
|
||||
to the default GS/OS launcher. No real wizardry is going on here.
|
||||
|
||||
|
||||
SHRINKIT3.4, GSHK1.1:
|
||||
--------------------
|
||||
|
||||
Useful for unpacking .SHK files you can download off of the net.
|
||||
Always use GSHK (GS/OS version of ShrinkIt) for GS programs since
|
||||
they may have resource forks. It's also faster. GSHK must be run from GS/OS.
|
||||
|
||||
LISTV2.0:
|
||||
--------
|
||||
|
||||
ProDOS 8 text file lister, useful for viewing text files.
|
||||
|
||||
Wolfenstein3D:
|
||||
------
|
||||
|
||||
Wolfenstein 3D for the Apple IIgs. No kidding! Must be run from GS/OS.
|
||||
|
||||
SOUND22:
|
||||
-------
|
||||
|
||||
Cool little ProDOS 8 program (SOUND.EDITOR) that plays hi-fidelity
|
||||
(relatively) through the old Apple II speaker. This is included as a
|
||||
demonstration of how accurate KEGS sound emulation is.
|
||||
|
||||
Sound.Smith.95:
|
||||
--------------
|
||||
|
||||
GS/OS application that plays SoundSmith songs, which are spreadsheet music,
|
||||
like MODs. I included some sample songs--FILE.11, FILE.16, FILE.17, and
|
||||
SPACE.HARRIER. Enjoy!
|
||||
|
||||
SOLITAIRE:
|
||||
---------
|
||||
|
||||
Klondike. I like the interface on this game.
|
||||
|
||||
CAT.DOCTOR:
|
||||
----------
|
||||
|
||||
From Prosel8 (which is now public domain), this utility is very handy for
|
||||
sorting directories (among other things). Useful for arranging GSOS7,
|
||||
and BYE.SYSTEM mentioned above.
|
||||
|
||||
BGSOUND:
|
||||
-------
|
||||
|
||||
This CDA lets you play Soundsmith songs in the background while other
|
||||
applications are running. Very handy for playing Solitaire with some music.
|
||||
|
||||
DOCVu.CDA:
|
||||
---------
|
||||
|
||||
This CDA shows the current DOC contents in real-time. It has neat visual
|
||||
effects while playing Soundsmith songs.
|
||||
|
||||
Zippy.gs
|
||||
--------
|
||||
|
||||
Very useful ProDOS 8 program by Andy McFadden for setting ZipGS parameters.
|
||||
In KEGS, you'll want to use this to change the Zip speed to less than
|
||||
100% to make the "Unlimited" speed become limited to 7.5MHz, which is
|
||||
useful for some games.
|
||||
|
||||
|
||||
KEGS: What works:
|
||||
-----------------
|
||||
|
||||
Basically, just about every Apple II program works.
|
||||
|
||||
KEGS is EXTREMELY compatible. But, I haven't tested everything. Let
|
||||
me know if you find a program which is not working correctly.
|
||||
|
||||
Some old Apple II 5.25" games require the old C600 ROM image, and don't work
|
||||
with the default Apple IIgs ROM. This is not KEGS's fault--these games
|
||||
don't run on a real Apple IIgs either. KEGS has built-in the old Apple II
|
||||
Disk PROM which you can enable by using the IIgs control panel to set
|
||||
Slot 6 to "Your Card". This allows many more Apple II games to run, and
|
||||
is the recommended setting.
|
||||
|
||||
The NinjaForce Megademo mostly works, but sometimes hangs in the BBS Demo.
|
||||
Just skip that demo if it happens.
|
||||
|
||||
The California Demo hangs at startup unless you use the IIgs control panel
|
||||
to boot from slot 5, and then do a ctrl-Open_Apple-Reset to boot--doing
|
||||
the above lets it work fine. This seems to be a bug in the demo.
|
||||
|
||||
|
||||
KEGS bugs:
|
||||
---------
|
||||
|
||||
KEGS's serial port emulation is very limited now, and only for
|
||||
adventurous souls.
|
||||
|
||||
On a ROM03, KEGS makes a patch to the ROM image (inside emulation, not
|
||||
to the Unix file) to fix a bug in the ROM code. Both ROM01 and ROM03
|
||||
are patched to enable use of more than 8MB of memory. I then patch the ROM
|
||||
self-tests to make the ROM checksum pass. But other programs, like
|
||||
the Apple IIgs Diagnostic Disk, will detect a ROM checksum mismatch.
|
||||
Don't worry about it.
|
||||
|
||||
Sound breaks up if KEGS is unable to keep up--it should only be happening
|
||||
if you are trying to force KEGS to run at 2.8MHz, but cannot due to
|
||||
sound and video overhead.
|
||||
|
||||
|
||||
Sound emulation:
|
||||
---------------
|
||||
|
||||
KEGS supports very accurate classic Apple II sound (clicking of the
|
||||
speaker using $C030) and fairly accurate Ensoniq sound.
|
||||
|
||||
When KEGS determines that no sound has been produced for more than
|
||||
5 seconds, it turns off the sound calculation routines for a small
|
||||
speedup. It describes that it has done this by saying "Pausing sound"
|
||||
in the debug window. However, when sound restarts, it sometimes
|
||||
"breaks-up" a little. I will work on fixes for this.
|
||||
|
||||
If your display is not using shared memory, audio defaults to off unless
|
||||
you override it with "-audio 1".
|
||||
|
||||
SCC emulation:
|
||||
-------------
|
||||
|
||||
KEGS emulates the two serial ports on a IIgs as being two Unix sockets.
|
||||
Port 1 (printer port) is at socket address 6501, and port 2 (modem)
|
||||
is at socket address 6502.
|
||||
|
||||
In KEGS, from APPLESOFT, if you PR#1, all output will then be sent to
|
||||
socket port 6501. You can see it by connecting to the port using
|
||||
any method you like, but a simple, easy way is to use telnet. In
|
||||
another Unix window, do: "telnet localhost 6501" and then you
|
||||
will see all the output going to the "printer".
|
||||
|
||||
Under APPLESOFT, you can PR#1 and IN#1. This gets input from the
|
||||
socket also. You can type in the telnet window, it will be sent on
|
||||
to the emulated IIgs. Telnet on Unix defaults to "line mode" which
|
||||
buffers keys you type until you hit return. This can be a bit distracting,
|
||||
and can be disabled by hitting Ctrl-] and then "mode char". This
|
||||
causes a few {{ chars to show up in KEGS--just ignore this for now.
|
||||
You may want to go to the F4 Config Panel and set "mask off high bit"
|
||||
for serial port accesses to make PR#2 work a little nicer.
|
||||
|
||||
That's about it. Proterm and Appleworks GS can talk to the modem port
|
||||
fine, but it's limited in its usefulness. I have printed from
|
||||
Printshop, but it's a bit pointless since it's sending out Imagewriter
|
||||
printer codes which doesn't look like anything. You can "print" from
|
||||
BASIC by using something like PR#1 in KEGS and
|
||||
"telnet localhost 6501 | tee file.out" in another window.
|
||||
|
||||
Feel free to let me know what doesn't work, but a lot is known not
|
||||
to work. GNO's tty interface may work, but I'm having problems
|
||||
testing it.
|
||||
|
||||
|
||||
KEGS status area:
|
||||
----------------
|
||||
|
||||
The status area is updated once each second. It displays info I am
|
||||
(or was at some time) interested in seeing.
|
||||
|
||||
Line 1: (Emulation speed info)
|
||||
dcycs: number of seconds since KEGS was started
|
||||
sim MHz: Effective speed of KEGS instruction emulation, not counting
|
||||
overhead for video or sound routines.
|
||||
Eff MHz: Above, but with overhead accounted for. Eff MHz is the
|
||||
speed of an equivalent true Apple IIgs. This is extremely
|
||||
accurate.
|
||||
sec: The number of real seconds that have passed during on of KEGS's
|
||||
emulated seconds. Should be 1.00 +/- .01. Under 1
|
||||
means KEGS is running a bit fast, over 1 means KEGS is
|
||||
running slow. When you force speed to 2.5MHz, if KEGS
|
||||
can't keep up, it extends sec, so you can see how slow
|
||||
it's really going here.
|
||||
vol: Apple IIgs main audio volume control, in hex, from 0-F.
|
||||
pal: Super-hires palette that is unavailable. KEGS needs one palette
|
||||
for the standard Apple // graphics mode on an 8-bit display,
|
||||
and it grabs the least-used palette. Defaults to 0xe.
|
||||
You can try changing it with F10. If you change it to a
|
||||
palette that is not least used, KEGS changes it back in
|
||||
one second. Any superhires lines using the unavailable
|
||||
palette will have their colors mapped into the
|
||||
closest-matching "lores" colors, to minimize visual
|
||||
impact.
|
||||
Limit: Prints which speed setting the user has requested: 1MHz, 2.8MHz,
|
||||
or Unlimited.
|
||||
|
||||
Line 2: (Video and X info)
|
||||
xfer: In hex, number of bytes transferred to the X screen per second.
|
||||
xred_cs: Percentage of Unix processor cycles that were spent in the X
|
||||
server (or other processes on the machine).
|
||||
ch_in: Percentage of Unix processor cycles spent checking for X input Events.
|
||||
ref_l: Percentage of Unix processor cycles spent scanning the Apple IIgs
|
||||
memory for changes to the current display screen memory,
|
||||
and copying those changes to internal XImage buffers.
|
||||
ref_x: Percentage of Unix processor cycles spent sending those XImage buffers
|
||||
to the X server. Very similar to xred_cs.
|
||||
|
||||
Line 3: (Interpreter overhead)
|
||||
Ints: Number of Apple IIgs interrupts over the last second.
|
||||
I/O: Rate of I/O through the fake smartport interface (hard drives).
|
||||
Does not count 3.5" or 5.25" disk accesses.
|
||||
BRK: Number of BRKs over the last second.
|
||||
COP: Number of COPs over the last second.
|
||||
Eng: Number of calls to the main instruction interpreter loop in the
|
||||
last second. All "interrupts" or other special behavior
|
||||
causes the main interpreter loop to exit. A high call
|
||||
rate here indicates a lot of overhead. 12000-15000 is normal.
|
||||
20000+ indicates some sort of problem.
|
||||
act: Some instructions are handled by the main interpreter loop returning
|
||||
special status "actions" to main event loop. This is the
|
||||
number over the last second. Should be low.
|
||||
hev: This tracks HALT_EVENTs. KEGS returns to the main loop to recalc
|
||||
effective speed whenever any speed-changing I/O location is
|
||||
touched. See the code, mostly in moremem.c
|
||||
esi: This counts the number of superhires scan-line interrupts
|
||||
taken in the last second.
|
||||
edi: This counts the number of Ensoniq "special events" over the last
|
||||
second. A sound that stops playing always causes a KEGS
|
||||
event, even if it doesn't cause a IIgs interrupt.
|
||||
|
||||
Line 4: (Ensoniq DOC info)
|
||||
snd1,2,3,4: Percentage of Unix processor cycles spent handling various
|
||||
sound activities. snd1 is the total sum of all sound overhead.
|
||||
st: Percentage of Unix cycles spent starting new Ensoniq oscillators.
|
||||
est: Percentage of Unix cycles spent looking for 0 bytes in sounds.
|
||||
x.yz: This final number is the average number of oscillators playing
|
||||
over the last second. Up to 4.00 is low overhead, over
|
||||
20.0 is high overhead.
|
||||
|
||||
Line 5: (Ensoniq DOC info)
|
||||
snd_plays: Number of calls to a routine called sound_play, which
|
||||
plays Ensoniq sounds. Always called at least 60 times per sec.
|
||||
doc_ev: Number of Ensoniq (DOC) events in the last second. A sound
|
||||
stopping is an event, but changing a parameter of a sound
|
||||
while it is playing is also an event.
|
||||
st_snd: Number of sounds that were started in the last second.
|
||||
snd_parms: Number of times a sound parameter was changed while it
|
||||
was playing.
|
||||
|
||||
Line 6: (IWM info)
|
||||
For each IWM device, this line displays the current track (and side for
|
||||
3.5" disks). If a disk is spinning, there will be an "*" next to the
|
||||
track number. Only updated once a second, so the disk arm moving may
|
||||
appear to jump by several tracks. "fast_disk_emul:1" shows that KEGS
|
||||
is using less accurate, but faster, IWM emulation. Press F7 to toggle
|
||||
to accurate disk emulation.
|
||||
|
||||
|
||||
Documentation To-Do:
|
||||
-------------------
|
||||
|
||||
Describe the tracing and breakpoint debug features.
|
||||
Describe the debug interface.
|
||||
Describe how the code works.
|
||||
Describe more of what's known to work.
|
||||
Describe my changes to SPEEDTEST.
|
||||
|
||||
KEGS To-Do:
|
||||
----------
|
||||
|
||||
Better serial port emulation (printing, comm)
|
||||
Better nibblized images.
|
||||
Fix the Ensoniq bugs to make sound more accurate.
|
||||
|
||||
-------------------
|
||||
|
||||
If you have any problems/questions/etc., just let me know.
|
||||
|
||||
Special thanks to Jeff Smoot of climbingwashington.com for letting me use
|
||||
the picture of a keg in the Mac icon.
|
||||
|
||||
Kent Dickey
|
||||
kadickey@alumni.princeton.edu
|
||||
|
||||
|
||||
X Window (Linux) interface information:
|
||||
--------------------------------------------
|
||||
|
||||
Every version of Linux is different. Supporting this is very difficult
|
||||
especially since I do not run Linux myself.
|
||||
|
||||
If KEGS fails to start, try the following options:
|
||||
|
||||
kegs -audio 0 -noshm
|
||||
|
||||
There may be a bug with drawing the border on x86 Linux with Shared Memory--
|
||||
add the options "-noshm -skip 0" to fix this up (but lose some graphics
|
||||
performance, sorry). Try KEGS without these options first, but use
|
||||
this as a workaround if necessary.
|
||||
|
||||
If you want the display to go somewhere different, make sure the shell
|
||||
environment variable $DISPLAY is set, or give the command-line argument
|
||||
"-display {foo}".
|
||||
|
||||
KEGS also forks off a subprocess to help handle the sound if audio is
|
||||
active. If KEGS crashes in a unusual way (a core dump, for instance),
|
||||
you may have to manually kill the subprocess. ("ps -ef| grep kegs;kill
|
||||
xxxxx").
|
||||
|
||||
User geoff@gwlink.net adds some notes for mounting disks/floppies/CDs under
|
||||
Solaris:
|
||||
|
||||
To use a CDROM, insert the CD and let Volume Management mount it.
|
||||
Edit kegs_conf and use the filesystem that shows up in the "df -k"
|
||||
listing. The volume name of the CDROM must be included. For example,
|
||||
a CDROM in an IDE drive would look like this:
|
||||
|
||||
/vol/dev/dsk/c1t0d0/ciscocd
|
||||
|
||||
A CDROM in a SCSI drive would look like this:
|
||||
|
||||
/vol/dev/dsk/c0t6d0/j1170_10804
|
||||
|
||||
To provide low-level ADB emulation, KEGS turns off Unix key repeat when the
|
||||
focus is in the KEGS window. It should be turned back on every time
|
||||
the pointer leaves the KEGS window, but sometimes it doesn't. Re-running
|
||||
KEGS (and then quitting it quickly) should turn key-repeat back on,
|
||||
or you can type 'xset r' in another terminal window.
|
||||
|
||||
Sometimes the converse is true--key repeat is "on" when the cursor is
|
||||
in the KEGS window. Moving the cursor out of the window and then
|
||||
back in should solve it. This is sometimes noticeable when running
|
||||
Wolfenstein 3D GS. I haven't spent much time debugging the problem.
|
||||
I think it may be the X Server.
|
||||
|
||||
KEGS uses a private color-map for its X-window in 8-bit mode. This
|
||||
may cause colormap "flash" when your cursor enters the window.
|
||||
|
||||
KEGS details/troubleshooting
|
||||
----------------------------
|
||||
|
||||
KEGS will work on all platforms with a 15/16-bit, 24-bit, or 32-bit
|
||||
color display. KEGS also supports an 8-bit display on X windows only.
|
||||
On all platforms, it autodetects the color depth--no color switching
|
||||
is necessary as long as you're at a supported depth.
|
||||
|
||||
|
||||
Disk Image Details
|
||||
|
||||
Images loaded into slot 6 (drive 1 or 2) are assumed to be 140K
|
||||
5.25" disks, which is usually have the extension ".dsk". Images
|
||||
loaded into slot 5 (drive 1 or 2) are assumed to be 800K disk images
|
||||
and can be in any supported imahe format (including partitions, if
|
||||
you have 800K partitions). Images loaded into slot 7 (drives 1
|
||||
through 32) can be in any format and can be any size up to 4GB.
|
||||
|
||||
KEGS boots s7d1 by default. You can change this using the emulated IIgs
|
||||
control panel, just like a real Apple IIgs. KEGS emulates a IIgs with
|
||||
two 5.25" drives in slot 6, two 3.5" drives in slot 5, and up to 32
|
||||
"hard drives" in slot 7. However, the current Configuration Panel only
|
||||
lets you set through s7d11.
|
||||
|
||||
Config.kegs file
|
||||
----------------
|
||||
|
||||
KEGS saves your preferences and disk image names in the file config.kegs.
|
||||
KEGS searches for this file in the directory KEGS was started in, in
|
||||
your home directory, or in the Resources directory (on a Mac) of the app.
|
||||
It needs to find one someplace, so putting it in your home directory is
|
||||
usually the easiest.
|
||||
|
||||
The config.kegs file is a simple text file. You need to quit KEGS before
|
||||
editing the file. The BRAM data is also kept in this file, with separate
|
||||
BRAM contents for ROM 01 and ROM 03 (so if you switch ROM versions, you
|
||||
don't lose all your BRAM preferences).
|
||||
|
||||
If you're trying to use a real host device (CD-ROM, or hard drive, or
|
||||
floppy), you should make the permissions on the /dev/disk* files something
|
||||
like (meaning, everyone should have read permission):
|
||||
|
||||
brw-r--r-- 1 root operator 14, 0 Jun 10 00:01 /dev/disk2
|
||||
|
||||
You can do this on a Mac with:
|
||||
|
||||
sudo chmod 644 /dev/disk2
|
||||
|
||||
Running KEGS as root is NOT recommended.
|
||||
|
||||
The s6d* and s5d* drives support disk swapping and disk ejecting, but
|
||||
the s7d* drives do not.
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
[ This info provided by Mike Thomas <phoenyx@texas.net> ]
|
||||
[ Updated 10/30/2003 by Kent: This file mentions editing "kegs.conf" to ]
|
||||
[ mount images--this is now replaced by the built-in Configuration Panel. ]
|
||||
|
||||
Setup and configuration for x86 Linux:
|
||||
--------------------------------------
|
||||
|
||||
KEGS is very easy to setup on your Linux box, but not foolproof. First
|
||||
you will need to decide where it will live. When doing this you will
|
||||
have to take into consideration any users of your machine. It really
|
||||
doesn't matter where it goes but it should have it's own directory and
|
||||
any supplied sub-directories should be there. You may decide to use the
|
||||
/usr/local path where most systems recommend you install applications.
|
||||
Again, this is entirely up to you. On my system I have a separate
|
||||
partition for KEGS and all the miscellaneous files I've accumulated for
|
||||
it. This makes it easy for me to reinstall the system should the need
|
||||
arise. Since I fool around with a large variety of software and OS's
|
||||
this happens more often than it would for normal users.
|
||||
|
||||
Once you have put the files into the proper place you will need to
|
||||
compile it. You should not need to be 'root' to do this part. The file
|
||||
README.compile explains the steps required for this. Basically all you
|
||||
should need to do is set the vars link to point to the file
|
||||
vars_x86linux. You will want to check the file and make sure it is
|
||||
accurate for your system. On my Redhat 6.0 system the default compile
|
||||
setup works fine. I use the pentium GCC compiler instead of the
|
||||
supplied EGCS since it seems to build better binaries. I do not
|
||||
recommend using optimization levels higher than 2. Once you have
|
||||
successfully built the binaries you will need to copy them to the KEGS
|
||||
directory. At a minimum copy the file kegs and to_pro.
|
||||
|
||||
Ok, now that you have the binaries you're almost ready. You will need a
|
||||
copy of the IIgs rom placed in the KEGS directory. It should be named
|
||||
ROM. You will also need some disk images. This is the hardest part.
|
||||
You will need to create an HD image to work with. Kent mentions an easy
|
||||
way in his readme. From the shell type this:
|
||||
|
||||
echo "testfile" > testfile
|
||||
to_pro -16384 testfile
|
||||
|
||||
If you're using bash try this:
|
||||
|
||||
echo "testfile" > testfile
|
||||
./to_pro -16384 testfile
|
||||
|
||||
This should create a 16 megabyte HD image. This image will NOT be properly
|
||||
formatted to boot a system. The block zero is not properly setup. There is no
|
||||
easy way to fix this with the current KEGS/Linux system. There seems to be a
|
||||
problem formating HD files for Prodos using KEGS. The system will easily erase
|
||||
them but this doesn't help you. One solution is to make the primary boot drive
|
||||
use a disk partition. This is more involved and will be explained later.
|
||||
Another solution is to have access to the utility Block.Warden or some other
|
||||
P8 block utility. What you need to do is copy the boot blocks (blocks 0 and 1)
|
||||
from any bootable disk to the HD image. With that done you can now install
|
||||
GS/OS.
|
||||
|
||||
Make sure you set the proper file permissions on files needed by KEGS. You
|
||||
will not be able to properly use it while logged on as root. KEGS uses the
|
||||
file permissions to test if it should write the image to disk or the memory
|
||||
image. As root, KEGS will never write the image since it thinks root
|
||||
always has execute privilege. The main files which you will need read/write
|
||||
access to are bram.data.1 and disk_conf. I suggest you have read access to all
|
||||
the other files in the directory.
|
||||
|
||||
Once you've got all the proper permissions set, log onto the system with your
|
||||
normal account. Start up X and a shell and cd to the KEGS directory. Assuming
|
||||
you have the disk images for GS/OS edit your disk_conf file so it looks
|
||||
similar to this:
|
||||
|
||||
# boot from install disk
|
||||
s7d1 = /usr/local/fst/gsos1
|
||||
|
||||
# our HD image
|
||||
# you should rename POOF1 file created with to_pro
|
||||
# I use *.hdv to be compatible with other utilities
|
||||
s7d2 = /usr/local/fst/boot.hdv
|
||||
|
||||
# other GSOS images
|
||||
s7d3 = /usr/local/fst/gsos2
|
||||
...
|
||||
|
||||
If you include all the GSOS images this way you will have a simple setup.
|
||||
Execute KEGS. For now go with the simplest command line possible. Since the
|
||||
newer versions support auto detect on video resolutions this should be the
|
||||
command kegs by itself. Hopefully you will boot into the emulator. If so,
|
||||
install GSOS and you're ready to go.
|
||||
|
||||
|
||||
Sound
|
||||
-----
|
||||
|
||||
Kent says sound doesn't work under Linux. This is partially true and much
|
||||
depends on the sound system you have installed. I have been successful with
|
||||
sound on both Soundblaster and Soundpro systems. For long compositions the
|
||||
sound may break up but it is functional for games and system sounds.
|
||||
|
||||
|
||||
System Video Setup
|
||||
------------------
|
||||
|
||||
This is rather personal and based upon system hardware so I'll just give you my
|
||||
thoughts and setup info on this. My normal X system is configured
|
||||
@ 1152x864 15bpp due to constraints in the X server for my video system. I
|
||||
have custom configured it to boot into this mode and then I change to 800x600
|
||||
by using the CTRL+ALT+(keypad)PLUS sequence when I use KEGS. This makes the
|
||||
system much easier to read.
|
||||
|
||||
|
||||
KEGS and disk partitions
|
||||
------------------------
|
||||
|
||||
Kent mentions using partitions in his readme file but doesn't go into much
|
||||
details. I suspect this is mostly for accessing CD-roms. But it also works
|
||||
well for HFS and Prodos formatted partitions also. Linux can also handle HFS
|
||||
partitions but not Prodos. To accomplish this you will need some free space on
|
||||
your hard disk to create the partitions. You should not attempt this unless you
|
||||
know what you are doing. You have been warned!
|
||||
|
||||
This task is not easy, nor is it supported by Kent. This was done and tested
|
||||
on my own system so I know it works. You will need the HFS support utilities
|
||||
for Linux. These are available on several Linux software sites. The primary
|
||||
need for these utilities is to change an ext2fs partition to an HFS partition.
|
||||
You can also use them to format the HFS volumes and copy files to and from
|
||||
the partition. Newer versions of the Linux kernel support HFS file systems but
|
||||
you will still need the utilities to create the original volume.
|
||||
|
||||
You must decide how you want to divide this partition. You can use it all for
|
||||
HFS or you can create Prodos volumes and HFS volumes. There are pros and cons
|
||||
for using Prodos partitions instead of files. The pros, it is a little faster
|
||||
than using an HD file. It is a real Prodos partition, formatted by KEGS. The
|
||||
cons, It must be backed up by using software on the emulator. You can't just
|
||||
copy the HD file to another drive.
|
||||
|
||||
You must weigh these pros and cons and decide for yourself. Of course you
|
||||
are not limited to using partitions. I have a mix of partitions and files
|
||||
which works quite well. I like the P8 partitions for holding my boot system
|
||||
and applications. I back them up with GSHK to an HFS volume which I can then
|
||||
transfer to another drive if I need even more security.
|
||||
|
||||
If you decide to use the whole partition for HFS then all you need to do is
|
||||
run the HFS utilities and setup the HFS volume. Read the documentation which
|
||||
comes with the utility package and follow it faithfully.
|
||||
|
||||
If you want to use P8 and HFS partitions you have some more work to do. If
|
||||
you have never worked with low level partitions or are worried about destroying
|
||||
your HD then you should probably forget this. For this to work you will have
|
||||
to change the partition table on your HD. This can and most likely will ruin
|
||||
any data you already have on there. I can not state this enough. Back up any
|
||||
important data on the hard drive! It is possible to change the partitions in
|
||||
Linux and not destroy the system. I have done this on mine but I also used
|
||||
the last defined partition to make the changes and designed the system for
|
||||
change should it be necessary.
|
||||
|
||||
For those of you who know how to handle this, take the partition you have
|
||||
decided to use for KEGS and divide it into at least one 32 meg partition.
|
||||
More is better but you will have to use the emulator to back up any drives
|
||||
setup this way since Linux can't access a Prodos partition (yet). I have setup
|
||||
4 32 meg P8 partitions and several smaller HFS partitions of about 96 megs.
|
||||
The reason I use smaller HFS partitions is because HFS isn't real efficient
|
||||
with larger drives, but that's another story. The reason for the separate
|
||||
HFS partitions is so Linux can mount the HFS volumes like any other file system.
|
||||
I find this works quite easily for accessing files instead of using the HFS
|
||||
utilities. Just my opinion though. For P8 utilities you will still need to
|
||||
use the HFS utility and configure the drive as an HFS volume. This lets KEGS
|
||||
read the partition when it loads the partition the first time. KEGS doesn't
|
||||
like the Linux file system.
|
||||
|
||||
Ok, everybody got their partitions defined? You want to use the HFS tools
|
||||
and setup all the partitions (P8 and HFS) as HFS volumes. Next you will have
|
||||
to setup the HFS partitions. No, I'm not repeating myself. This is not the same
|
||||
thing as the low level partitions. HFS volumes have their own partition table.
|
||||
For our purposes the table will only hold one partition on each whole volume.
|
||||
The utility will give you the block count when you setup the partitions,
|
||||
write it down so you don't forget. After you have the volume partition setup
|
||||
you can format the drive. Yeah I know you made a Prodos partition but it
|
||||
doesn't hurt anything and KEGS will be able to read the partition when it
|
||||
boots up.
|
||||
|
||||
Well, I think I covered everything needed to set them up. Now you will need to
|
||||
edit the /etc/fstab file. Make sure there are no references to the original
|
||||
partition. If you want to access the HFS volumes you will need to add them to
|
||||
this file. You will also need to make sure that your Linux can understand the
|
||||
HFS format. Most newer kernels will as long as you've compiled it into the
|
||||
kernel or set it up as a module. KEGS doesn't need these entries to access
|
||||
the volumes, they are just here for your convenience. In fact, if you don't
|
||||
need Linux access I suggest you either leave them out or set them up as
|
||||
NOAUTO and mount them only when needed. Unmount them when finished to avoid
|
||||
any potential problems also. Do not give Linux access to any P8 partitions.
|
||||
For one thing it can't recognize them and most likely will give you problems
|
||||
when you boot the system. For safety's sake the only partition I have listed
|
||||
in my /etc/fstab is a volume called transfer. You must set the filetype to HFS
|
||||
so Linux doesn't complain about the partitions if you mount them.
|
||||
|
||||
Ok, all partitions are defined, the /etc/fstab is setup correct, now you need
|
||||
to change the permissions on the device files associated with the partitions.
|
||||
This allows you to access the files as a normal user. (Thanks Kent, guess I
|
||||
got too involved and forgot it should be treated like the CD). You will need
|
||||
to reboot to ensure the system sees the new partitions and has the correct
|
||||
/dev/hd?# device files. If you setup the partitions with fdisk you should know
|
||||
the correct hd info to select the files. For the sake of example let's assume
|
||||
the device is HDB and the partitions numbers are 1,2,3. From the shell,
|
||||
|
||||
cd /dev
|
||||
chmod 666 /dev/hdb1
|
||||
chmod 666 /dev/hdb2
|
||||
chmod 666 /dev/hdb3
|
||||
|
||||
After you start KEGS you can format the Prodos partitions. If you use the
|
||||
method mentioned earlier for installing GS/OS you will want to quit the
|
||||
installer and run the advanced disk utilities on the utilities disk, then
|
||||
quit back to the installer program or reboot.
|
||||
|
||||
Now I know this all sounds like a lot of trouble but (IMHO) it's worth it. For
|
||||
one thing, KEGS will format a Prodos partition without problems (unlike an HD
|
||||
file image) which makes a great boot system. And with GS/OS 6.01 you can access
|
||||
large HFS volumes for storage and GS applications. You can also download from
|
||||
the net to the HFS volume (if it's mounted) and avoid the trouble of copying
|
||||
files to an image with to_pro. Not to mention the fact that the newest GNO
|
||||
works with HFS drives.
|
||||
|
||||
One more note, if you use HFS you will need to patch the HFS fst. There is a
|
||||
one byte bug which mis-calculates HFS block sizes and WILL trash your HFS
|
||||
drive. The patch is at several places on the net or ask someone in one of
|
||||
the comp.sys.apple2 news groups.
|
||||
|
||||
Miscellanea
|
||||
-----------
|
||||
|
||||
To ease access to the KEGS binary, make an executable script which contains
|
||||
any command line parms you need. Then put this script somewhere in the path
|
||||
so you can execute it from any shell. Depending on the desktop you use you
|
||||
may want to setup links for editing the disk_conf file also. With GNO/ME you
|
||||
can launch KEGS without the shell but I don't recommend this since you won't
|
||||
know what happened when it dies. With KDE you can set up the launcher to use
|
||||
a shell, this is much better but until you have your setup stable you will
|
||||
want to use a regular terminal so you can keep track of what's going on. Like
|
||||
GNO/ME, the KDE shell will close as soon as KEGS quits with an error.
|
||||
|
||||
|
||||
Thanks
|
||||
------
|
||||
|
||||
I hope this info helps you enjoy KEGS. Many thanks to Kent for creating this
|
||||
fine emulator and for putting up with me bugging him with 'bug' reports. Many
|
||||
of these weren't actually bugs but were my own fault due to lack of knowledge
|
||||
about *nix systems. But Kent was prompt in fixing the ones which truly were
|
||||
bugs. Thanks to him I can now play my favorite game, Questron 2 (gs version)
|
||||
which requires a player disk in slot 5. I know no other emulator which can
|
||||
actually play this game.
|
||||
|
||||
Mike Thomas
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
MAC OS X port of KEGS (KEGSMAC): http://kegs.sourceforge.net
|
||||
-------------------------------------------------------------
|
||||
|
||||
There is a different port of KEGS to Mac OS X called KEGS-OSX.
|
||||
You can get it from http://casags.net/.
|
||||
|
||||
This port is not leveraged from KEGS-OSX (which is based on SDL).
|
||||
|
||||
This is a Mac OS X Carbon port. It will not work on Mac OS 9.
|
||||
|
||||
Everything pretty much works, but 8-bit color doesn't work. Make sure your
|
||||
Mac is set to Thousands or Millions of colors.
|
||||
|
||||
Usage:
|
||||
-----
|
||||
|
||||
Like most other KEGS versions, KEGSMAC is usually run from a Terminal
|
||||
window. Just type "./KEGSMAC.app/Contents/MacOS/KEGSMAC" in the directory
|
||||
you installed/compiled it in. You need to have a ROM file (named
|
||||
ROM, ROM.01, or ROM.03) and a config.kegs in the same directory or in your
|
||||
home directory (read the README--these files are searched for in various
|
||||
places).
|
||||
|
||||
KEGSMAC can also be run from the Finder, but if you do this, there
|
||||
will be no debug window at all. This is not well tested, yet.
|
||||
|
||||
To quit, either click the window close box, or select Quit from the menu.
|
||||
You can also middle-click (if you have a 3-button mouse) or
|
||||
Shift-F6 to get the debugger in the terminal window, and then type "q".
|
||||
|
||||
Compile directions
|
||||
------------------
|
||||
|
||||
In order to compile,
|
||||
|
||||
1) cd into the src/ directory
|
||||
2) copy vars_mac to vars
|
||||
3) run make
|
||||
|
||||
You can contact me at kadickey@alumni.princeton.edu
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
WIN32 port of KEGS (KEGSWIN)
|
||||
----------------------------
|
||||
|
||||
There is a different port of KEGS by akilgard called KEGS32.
|
||||
You can get it from http://www.geocities.com/akilgard/kegs32.
|
||||
This port is leveraged from KEGS32, but mostly a rewrite (perhaps
|
||||
for the worse). The joystick code was taken without too many
|
||||
modifications.
|
||||
|
||||
This port is alpha quality. Seriously. Don't expect much.
|
||||
|
||||
This is a bare-bones Win32 port. It was compiled with Mingw2.0,
|
||||
which you can download at: http://www.mingw.org/. I also had
|
||||
previously installed cygwin at http://www.cygwin.com/. Installing
|
||||
these two beasts is a bit of a pain, so I'll eventually write up
|
||||
directions (I hope).
|
||||
|
||||
Sound works, the mouse works, and a joystick might work (ported
|
||||
from KEGS32). The user-interface is just like every other KEGS
|
||||
version (i.e., bad), so you can just read the standard README file.
|
||||
|
||||
Only tested on a 32-bit graphics display, although I think 16-bit and
|
||||
24-bit will work. 8-bit definitely does not work. There are many
|
||||
other bugs I just haven't had time to list yet.
|
||||
|
||||
Usage:
|
||||
-----
|
||||
|
||||
Like most other KEGS versions, KEGSWIN must be run from a terminal
|
||||
window (command.com is fine). Just type "KEGSWIN" in the directory
|
||||
you installed/compiled it in. You need to have a ROM file (named
|
||||
ROM, ROM.01, or ROM.03) and a kegs_conf in the same directory (or
|
||||
read the README--these files are searched for in various places).
|
||||
|
||||
To quit, either click the close box, or force quit the application.
|
||||
You can also middle-click (if you have a 3-button mouse) or
|
||||
Shift-F6 to get the debugger in the terminal window, and then type "q".
|
||||
|
||||
Compile directions
|
||||
------------------
|
||||
|
||||
In order to compile,
|
||||
|
||||
1) cd into the src/ directory
|
||||
2) rm vars
|
||||
3) ln -s vars_win32 vars
|
||||
3) ./make_win
|
||||
|
||||
|
||||
You can contact me at kadickey@alumni.princeton.edu
|
|
@ -0,0 +1,11 @@
|
|||
# KEGS configuration file version 0.80
|
||||
|
||||
s5d1 = XMAS_DEMO
|
||||
s5d2 =
|
||||
|
||||
s6d1 = #dos33.dsk
|
||||
s6d2 =
|
||||
|
||||
s7d1 = NUCLEUS03
|
||||
|
||||
|
Binary file not shown.
|
@ -0,0 +1,239 @@
|
|||
|
||||
KEGS's Apple //gs IWM emulation routines.
|
||||
|
||||
The IWM code does 5.25" and 3.5" reads & writes, and updates the Unix disk
|
||||
image on writes. It is also nearly cycle-accurate--Let me know if you
|
||||
have a program which can detect it's not a real Apple II. There are
|
||||
a few 5.25" features missing (No 1/4 or 1/2 tracks, no support for Unix nibble
|
||||
images, limited disk switching), but what's there is pretty accurate.
|
||||
The low-level code support 1/4 and 1/2 tracks--it's the arm movement
|
||||
and image-handling routines which don't. And lack of Unix nibble images
|
||||
are also due to lack of higher-level routines to make those features work.
|
||||
|
||||
How my disk emulation works: The routines have a nibblized image of each
|
||||
track of each drive (two 5.25" and two 3.5" drives are supported) in memory.
|
||||
The nibble images are declared as arrays, but it could be made to use
|
||||
more dynamic memory allocation.
|
||||
|
||||
Each track's data format is a series of two-byte pairs. The first byte
|
||||
of the pair is the number of bits in this disk byte, and the second byte
|
||||
is the value. So a size of 8 is normal. A size of 10 means that there
|
||||
are 2 sync bits written before this byte on the disk. So for 5.25" disk
|
||||
accesses, 40 cycles need to pass in the simulator before providing a
|
||||
valid nibble. Partial nibbles are correctly formed if a read happens
|
||||
too early (this actually makes things slower, but is required if you
|
||||
want to make nibble copiers work). Similarly, writing to the disk
|
||||
watches timing carefully to write out the correct number of bits per
|
||||
disk byte. These routines will definitely test out your emulator's cycle
|
||||
counting ability.
|
||||
|
||||
If a long delay occurs between a read (or a write) the routines skips
|
||||
the correct number of bits to return the correctly formed disk byte.
|
||||
After a long delay, for efficiency, I always return a full disk byte,
|
||||
instead of a partial one, even if the timing would put it in the middle
|
||||
of a disk byte.
|
||||
|
||||
The arm stepping is really lame. I will clean it up soon.
|
||||
|
||||
Smartport support is sufficient to claim that there are no smartport
|
||||
devices. This is necessary since the ROM tries to see if there are
|
||||
smartport devices at power-on.
|
||||
|
||||
I tested my 5.25" drive routines on EDD, which could correctly measure
|
||||
drive speed and other disk factors. I also nibble-copied some disks,
|
||||
which also worked fine. I tested the 3.5" routines using Copy II+,
|
||||
which successfully nibble-copied several disks.
|
||||
|
||||
|
||||
Code description:
|
||||
|
||||
Most code is in iwm.c, with some defines in iwm.h, and some stuff in
|
||||
iwm_35_525.h.
|
||||
|
||||
Code only supports DOS3.3 ordered 5.25" images now, and ProDOS-ordered 3.5"
|
||||
images. Well, the code supports ProDOS-order 5.25" also, but has no
|
||||
mechanism to tell it an image is prodos-order yet. :-)
|
||||
|
||||
Iwm state is encoded in the Iwm structure.
|
||||
|
||||
drive525[2]: Disk structure for each 5.25" disk
|
||||
drive35[2]: Disk structure for each 3.5" disk
|
||||
smarport[32]: Disk structure for each "smartport" device emulated
|
||||
via slot 7 (this code not included)
|
||||
motor_on: True if IWM motor_on signal (c0e9) is asserted. Some
|
||||
drive is on.
|
||||
motor_off: True if motor has been turned off in software, but the
|
||||
1 second timeout has not expired yet.
|
||||
motor_on35: True if 3.5" motor is on (controlled differently than
|
||||
5.25" c0e9).
|
||||
motor_off_vbl_count: VBL count to turn motor off.
|
||||
head35, step_direction35: 3.5" controls, useless.
|
||||
iwm_phase[4]: Has '1' for each 5.25" phase that is on.
|
||||
iwm_mode: IWM mode register.
|
||||
drive_select: 0 = drive 1, 1 = drive 2.
|
||||
q6, q7: IWM q6, q7 registers.
|
||||
enable2: Smartport /ENABLE2 asserted.
|
||||
reset: Smartport /RESET asserted.
|
||||
previous_write_val: Partial write value.
|
||||
previous_write_bits: How many bits are valid in previous_write_val.
|
||||
|
||||
Each disk (3.5" and 5.25") is encoded in the Disk struct:
|
||||
fd: Unix file descriptor. If < 0, no disk.
|
||||
name_ptr: Unix file name for this disk.
|
||||
image_start: offset from beginning of file for this partition.
|
||||
image_size: size of this partition.
|
||||
smartport: 1 if this is a smartport image, 0 if it is 5.25" or 3.5"
|
||||
disk_525: 1 if this is a 5.25" image, 0 if it is 3.5"
|
||||
drive: 0 = drive 1, 1 = drive 2.
|
||||
cur_qtr_track: Current qtr track. So track 1 == qtr_track 4.
|
||||
For 3.5", cur_qtr_track encodes the side also, so track 3
|
||||
side 1 would be qtr_track 7.
|
||||
prodos_order: True if Unix image is ProDOS order.
|
||||
vol_num: DOS3.3 volume number to use. Always 254.
|
||||
write_prot: True if disk is write protected.
|
||||
write_through_to_unix: True if writes should be passed through to
|
||||
the unix image. If this is false, you can write
|
||||
to the image in memory, but it won't get reflected
|
||||
into the Unix file. If you create a non-DOS3.3
|
||||
or ProDOS format image, it automatically sets this
|
||||
false.
|
||||
disk_dirty: Some track has dirty data that need to be flushed.
|
||||
just_ejected: Ejection flag.
|
||||
dcycs_last_read: Cycle count of last disk data register access.
|
||||
last_phase: Phase number last accessed.
|
||||
nib_pos: Nibble offset ptr--points to a byte.
|
||||
num_tracks: Number of tracks: 140 for 5.25" and 160 for 3.5"
|
||||
track[MAX_TRACKS]: nibble image of all possible tracks.
|
||||
|
||||
Each track is represented by the Track structure:
|
||||
track_dirty: Contains data that needs to be written back to
|
||||
the Unix image file.
|
||||
overflow_size: Count of overflow bits, used in writing.
|
||||
track_len: Number of nibbles on this track.
|
||||
dsk: Handy pointer to parent Disk structure.
|
||||
nib_area[]: ptr to memory containing pairs of [size,data],
|
||||
encoding disk data bytes.
|
||||
pad1: If the structure is 32 bytes long, some array
|
||||
indexing is done better by my compiler.
|
||||
|
||||
|
||||
Externally callable routines:
|
||||
iwm_init(): Init various data structures at simulation start.
|
||||
iwm_reset(): Called at Apple //gs reset time.
|
||||
iwm_vbl_update(): Called every VBL (60 Hz) period. Used to turn motor
|
||||
off, and flush out dirty data.
|
||||
g_vbl_count is the count of VBL ticks (so it counts
|
||||
at 60 times a second).
|
||||
iwm_read_c0ec(double dcycs): Optimized routine to handle reading $C0EC
|
||||
faster. Exactly the same as read_iwm(0xc, dcycs);
|
||||
read_iwm(loc, dcycs):
|
||||
Read from 0xc0e0 + loc. Loc is between 0x0 and 0xf.
|
||||
Dcycs is an artifact from my simulator. Dcycs is a
|
||||
double holding the number of Apple //gs cycles since the
|
||||
emulator started. Dcycs always counts at 1.024MHz. If
|
||||
you are running at 2.5MHz, it increments by 0.4 every
|
||||
"cycle". This is a very convenient timing strategy. It
|
||||
also allows emulating the delay caused by synchronizing
|
||||
the fast part of a real Apple //gs with slow memory,
|
||||
which means my emulator knows that reading softswitches
|
||||
takes longer than reading fast memory.
|
||||
write_iwm(int loc, int val, double dcycs):
|
||||
Write to 0xc0e0 + loc. Just like read_iwm, but write "val" into
|
||||
loc.
|
||||
|
||||
|
||||
Tricky routines:
|
||||
|
||||
IWM_READ_ROUT(): called by read_iwm() if q6,q7 = 0,0.
|
||||
This is actually in the file iwm_35_525.h. This is so I
|
||||
write the basic code once for 5.25" and 3.5" disk reads,
|
||||
but then include the file with some macros set to create
|
||||
the correct function optimized for 5.25" or 3.5"
|
||||
accesses. The function for 5.25" is called
|
||||
iwm_read_data_525, and iwm_read_data_35 for 3.5".
|
||||
Returns next disk byte.
|
||||
Takes three arguments: ptr to the Disk structure for
|
||||
the active drive, fast_disk_emul, and dcycs. dcycs is
|
||||
so that it can see how many cycles have passed since
|
||||
the last read (stored in dsk->dcycs_last_read).
|
||||
16.0 dcycs need to pass for an 8 bit nibble for 3.5"
|
||||
accesses, and 32.0 dcycs for an 8 bit nibble for 5.25".
|
||||
Fast_disk_emul == 1 says don't mess around with accuracy,
|
||||
and always return the next fully-formed nibble.
|
||||
There is a lot of complexity in this routine. All IWM
|
||||
routines must skip over nibbles (stored as byte pairs in
|
||||
dsk->nib_area[]) which have a size of 0 (special padding
|
||||
trick, described later). It then determines how much
|
||||
time has passed, and so how many bits are valid.
|
||||
If too many bits have gone by (11 cycs is almost 3 5.25"
|
||||
bit times, which is about the nibble valid time in
|
||||
the Apple //gs IWM hardware latch), it tries to skip
|
||||
to the correct position.
|
||||
Handles IWM latch mode for 3.5" or 5.25" accesses. If a
|
||||
partial read is indicated, it ensures that the high bit
|
||||
is clear by shifting the nibble to the right
|
||||
appropriately. Again, nib_area[] is an array of bytes,
|
||||
which are treated as pairs. Byte 0 = size, byte 1 =
|
||||
disk nibble.
|
||||
|
||||
IWM_WRITE_ROUT(): called by write_iwm() if q6,q7 = 1,1.
|
||||
Similar to above. Handles async and sync mode writes.
|
||||
Handles partial writes. Handles the ROM writing
|
||||
0xff, 0x3f, 0xcf, 0xf3, 0xfc to be four 10-bit nibbles.
|
||||
Routine disk_nib_out(dsk, val, bits_read) does the
|
||||
actual work of merging the bits into the track image.
|
||||
|
||||
disk_nib_out(): called by IWM_WRITE_ROUTE() and iwm_nibblize_track_*().
|
||||
Writes byte into nib_area[]. If size > 10, makes it 10.
|
||||
If high order bit not set, it sets it (makes certain routines
|
||||
in EDD happy).
|
||||
|
||||
overflow_size:
|
||||
Writing to the disk creates some problems. I need to
|
||||
maintain 2 things at all times on the track:
|
||||
1) Constant number of bits for the entire track.
|
||||
2) know where each synchronized byte starts on
|
||||
the track.
|
||||
If the track was just stored as raw bits, then correctly
|
||||
simulating a delay of 300*4 cycles is tough, since it has to
|
||||
be done by reading through all 300 bits on the track,
|
||||
so that we keep in sync with where bytes really start.
|
||||
But if you just store the bytes themselves, then sync
|
||||
bytes look like every other byte. And if you now add
|
||||
the size field, you have a situation where a track could
|
||||
gain or lose bits when rewritten. Here's the case:
|
||||
Assume the track contains: 10,ff 10,ff 10,ff 10,ff.
|
||||
(That is 4 self-sync disk bytes of 10 bits each).
|
||||
If we rewrite that area of the track with 'D5 AA 96 FF',
|
||||
where each byte is 8 bits, we would have:
|
||||
8,D5 8,AA, 8,96, 8,FF.
|
||||
Looks OK, but we just lost 8 bits! The original 4 nibbles
|
||||
were using 40 bits of space on the disk. Our new 4 nibbles
|
||||
are using 32 bits. 8 bits are lost.
|
||||
Solution: log these missing bits via overflow_size.
|
||||
When writing, if overflow_size gets > 8, force out a 0,0
|
||||
nibble. So sync bytes get written as:
|
||||
10,FF 10,FF 10,FF 10,FF 0,0 10,FF 10,FF 10,FF 10,FF, 0,0.
|
||||
So when they get re-written with 8,xx, we don't lose any
|
||||
bytes on the disk.
|
||||
|
||||
Unfortunately, it doesn't quite work that easily, and bits
|
||||
can still be lost when sync fields are partially overwritten.
|
||||
This happens when all the 0,0's end up in a place on the
|
||||
track where few overwrites occur, but other sync bytes
|
||||
are being turned into 8,xx. So overflow_size goes negative,
|
||||
saying we've got too much on the track.
|
||||
The code prints an error when it gains more than 64 bits.
|
||||
If someone can come up with a better scheme, I'd love to
|
||||
hear it. A partial solution would be to have a routine
|
||||
re-space the track to spread the needed 0,0's around
|
||||
a little better when overflow_size gets too negative.
|
||||
|
||||
|
||||
In iwm_nibblize_track_35(), the comments with hex numbers correspond
|
||||
to the ROM 01 addresses which I disassembled to determine the checksum
|
||||
algorithm. The code is not well written--it's basically hand-translated
|
||||
65816 assembly code. I'll clean it up someday.
|
||||
|
||||
Much of the code is not well-optimized. I'll get to that someday, but
|
||||
the speed has been adequate for me so far.
|
|
@ -0,0 +1,96 @@
|
|||
|
||||
KEGS Internals
|
||||
--------------
|
||||
|
||||
The INTERNALS* files describe the internal structure of KEGS and how
|
||||
it works. It is meant to be useful to those who would attempt to
|
||||
port KEGS to non-Unix platforms, or just want to know how KEGS works.
|
||||
|
||||
Documentation files:
|
||||
--------------------
|
||||
|
||||
INTERNALS.overview: Provides overview of KEGS's file structure
|
||||
|
||||
|
||||
KEGS SOURCE FILES:
|
||||
-----------------
|
||||
|
||||
adb.c: ADB emulation routines. This includes keyboard, mouse, and
|
||||
joystick.
|
||||
adb.h: Defines for ADB routines.
|
||||
clock.c: Clock, BRAM, and some timing routines.
|
||||
compile_time.c: Trick file to put the time you compiled in g_compile_time[].
|
||||
defc.h: Global defines included by all .c files. Useful trick
|
||||
to avoid complex multi-level include problems.
|
||||
defs.h: Global defines included by all .s files (assembly language).
|
||||
defcomm.h: Global defines included by all files (must be assembly and
|
||||
C safe, such as #defines).
|
||||
defs_instr.h: C and assembly definitions for various addressing modes
|
||||
and for some repeated instructions (like LDA, STA, etc).
|
||||
dis.c: Disassembler and debugger interface. The debugger interface
|
||||
is similar to the Apple // monitor, but has many
|
||||
more commands.
|
||||
disas.h: Tables for disassembling 65816 instructions. Not very
|
||||
efficient, but it works.
|
||||
engine_c.c: C main instruction dispatch loop.
|
||||
engine_s.s: Assembly main instruction dispatch loop.
|
||||
instable.h: Instruction table. It is C and assembly-safe through
|
||||
the make_inst script. make_inst turns instable.h into
|
||||
8inst_c and 16inst_c, which are both valid C code.
|
||||
iwm.c: IWM routines for 5.25" and 3.5" disks. See INTERNALS.iwm
|
||||
iwm.h: IWM defines
|
||||
iwm_35_525.h: File for reading and writing a disk byte, which is included
|
||||
in iwm.c twice, once for 5.25" and again for 3.5".
|
||||
Forcing out compile-time constants this way makes it
|
||||
faster.
|
||||
moremem.c: Awful name--this file contains the page table change
|
||||
routines (fixup_*) and io_read() and io_write() to
|
||||
emulate all $C000 I/O accesses.
|
||||
op_routs.h: More macros for 65816 emulation.
|
||||
protos.h: Prototypes for all C functions. Auto-generated through
|
||||
the "cproto" program (not included).
|
||||
protos_xdriver.h: Prototypes for functions in xdriver.c.
|
||||
scc.c: Serial chip emulation.
|
||||
scc_driver.h: Unix-specific socket routines, stubbed out if you're not
|
||||
on Linux or HP-UX.
|
||||
scc.h: Defines for scc.c.
|
||||
sim65816.c: main() is here along with many other housekeeping
|
||||
functions, such as events, and interrupts.
|
||||
The main loop of KEGS is run_prog().
|
||||
size_tab.h: Used by assembly for a jump table (make_size script
|
||||
turns it into 8size_s and 16size_s) and by both C and
|
||||
assembly to get the size of instructions.
|
||||
smartport.c: Smartport emulation, emulates s7dx devices.
|
||||
sound.c: Sound emulation. Builds sound samples, but does not
|
||||
send sound to output device.
|
||||
sound.h: Header file for sound.c.
|
||||
sound_driver.c: Sound driver routines. Takes samples generated by sound.c
|
||||
and sends them to the correct output device. Supports
|
||||
HP Alib, HP /dev/audio, and Linux /dev/dsp currently.
|
||||
superhires.h: "macro" routine used by video.c so that I could write
|
||||
one generic superhires routine, but then include it
|
||||
multiple times to get optimized 320 vs 640 mode routines.
|
||||
video.c: Display routines. Builds 8 bit video buffers in a
|
||||
device independent way. Functions here know nothing
|
||||
about X windows.
|
||||
xdriver.c: X windows driver routines. Takes buffers from video.c
|
||||
and sends them on to X windows. Get keypresses from
|
||||
X and sends them to adb.c.
|
||||
|
||||
Porting Advice:
|
||||
--------------
|
||||
|
||||
To a non-unix platform, disabling scc emulation would be a good start.
|
||||
Just make sure you get the dummy stub routines in scc_driver.h.
|
||||
|
||||
If you don't have gettimeofday(), clock.c will need to modified with
|
||||
whatever timer facilities are available. A high-resolution clock works
|
||||
best, but even a low-resolution clock will work.
|
||||
|
||||
Modify sound_driver.c to get it to compile, if necessary. Always run with
|
||||
"-audio 0" to turn audio off. No routines in sound_driver.c will get
|
||||
called if you run with -audio 0.
|
||||
|
||||
Replace xdriver.c with new routines for whatever platform you are porting to.
|
||||
See INTERNALS.xdriver for more information.
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
|
||||
xdriver.c contains the routines for interfacing to X windows. The rest
|
||||
of KEGS interacts with X windows only through xdriver.c routines.
|
||||
|
||||
Externally called routines are:
|
||||
show_xcolor_array(): Debug routine, it does not need to do anything.
|
||||
dev_video_init(): Called at startup, it should open up the
|
||||
window and do other initialization.
|
||||
update_physical_colormap(): Updates the X windows palette with the colors
|
||||
from xcolor_a2vid_array[], which is maintained by
|
||||
other xdriver routines.
|
||||
update_status_line(): Call to update the internal array of chars
|
||||
representing the status lines at the bottom of
|
||||
the window. Does not draw the chars to the screen.
|
||||
xdriver_end(): Shutdown routine
|
||||
check_input_events(): Called up to 60 times a second (see video_update() in
|
||||
video.c) to handle any X window events and get
|
||||
keypresses.
|
||||
On a mouse press, call update_mouse() with the
|
||||
new x, y coordinates, and the status of the mouse
|
||||
button.
|
||||
If g_warp_pointer is set, constrain mouse within
|
||||
the window.
|
||||
On keypress, calls handle_keysym().
|
||||
handle_keysym(): Takes X keysym, and converts to the appropriate
|
||||
a2code using the a2_key_to_xsym[] lookup table.
|
||||
The a2codes are the Apple // ADB keycodes.
|
||||
Special work is done to handle shift and control
|
||||
properly since Apple only has one keycode for both
|
||||
shift and control keys. Then call
|
||||
adb_physical_key_update() with the a2 keycode and
|
||||
is_up = 1 if keyup, 0 = if key down.
|
||||
In addition, this routine handles all the Function
|
||||
keys doing special actions, which should be easy to
|
||||
port.
|
||||
x_refresh_ximage(): Redraws the window using the a2_line_* arrays.
|
||||
Described in more detail below.
|
||||
update_color_array(): Interface to the color map. Sets color[col_num]
|
||||
of the internal colormap array to a2_color.
|
||||
a2_color is the 12 bit apple color of the form:
|
||||
(red << 8) + (green << 4) + (blue).
|
||||
There are 16 palettes of 16 colors each, managed as
|
||||
one 256-color colormap. See discussion of
|
||||
g_a2vid_palette below.
|
||||
x_auto_repeat_on(): The X routines turn off key repeat when the cursor
|
||||
enters the graphics window automatically, and turn
|
||||
it back on when the cursor leaves. But if the
|
||||
debugger gets control due to a breakpoint, keyrepeat
|
||||
would be left off. So the debugger calls this
|
||||
routine to make sure key repeat is back on.
|
||||
redraw_status_lines(): Draw the status lines from the g_status_buf[][] array
|
||||
to the graphics window.
|
||||
|
||||
Externally referenced data:
|
||||
|
||||
g_use_shmem: Set by main() to enable/disable MIT-SHM for X.
|
||||
Also used by sound routines to auto-turn-off sound
|
||||
if not using MIT-SHM.
|
||||
|
||||
Bytes representing screen data:
|
||||
byte *data_text[2]: Array of bytes for the lores and text pages 1 and 2.
|
||||
Just 400*640 bytes.
|
||||
byte *data_hires[2]: Array of bytes for the hires pages 1 and 2.
|
||||
byte *data_superhires: Array of bytes for superhires screen.
|
||||
byte *data_border_sides: Array of bytes representing the border sides.
|
||||
Basically just A2_WINDOW_HEIGHT*EFF_BORDER_WIDTH bytes.
|
||||
byte *data_border_special: Top and bottom border bytes.
|
||||
(X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT + 2*8) *
|
||||
(X_A2_WINDOW_WIDTH) bytes.
|
||||
|
||||
Handles used for X windows drawing:
|
||||
XImage *ximage_hires[2]: Opaque handle to XImage object for hires page 1 and
|
||||
page 2.
|
||||
XImage *ximage_text[2]: Text pages 1 and 2.
|
||||
XImage *ximage_superhires: Superhires graphics XImage
|
||||
XImage *ximage_border_special: Top and bottom border XImage.
|
||||
XImage *ximage_border_sides: Left and right sides (only one copy, it is
|
||||
drawn at two different locations to be both sides).
|
||||
|
||||
Basic operation of xdriver:
|
||||
--------------------------
|
||||
|
||||
X windows can push arrays of bytes to the screen through structures
|
||||
called XImages. An XImage is a structure describing an offscreen bitmap.
|
||||
For efficiency of page flipping, KEGS maintains separate bitmaps for the
|
||||
two lores/text screens, the two hires screens, and the superhires screen.
|
||||
It also maintains bitmaps for the border. For MIT-SHM to work, X
|
||||
requires a unique XImage for each bitmap, and the bitmap must be allocated
|
||||
within xdriver.c since it must be obtained through an shmat() call.
|
||||
The X code also has non-MIT-SHM code which allocates the data_* buffers
|
||||
just through malloc().
|
||||
|
||||
All bitmaps are 8-bits of Pseudo-color. The color arrays are managed
|
||||
through the update_color_array() and update_physical_colormap() routines.
|
||||
KEGS manages all 256 colors in the colormap as 16 palettes of 16 colors.
|
||||
One of the palettes is reserved for the 16 lores colors, and is
|
||||
indicated by the variable g_a2vid_palette. It defaults to 0xe.
|
||||
Update_color_array() is called to update superhires colormap entries.
|
||||
Update_color_array must not update colors corresponding to g_a2vid_palette.
|
||||
Update_physical_colormap() pushes the color array managed by
|
||||
update_color_array() to the screen, but first forces the lores colors into
|
||||
the g_a2vid_palette palette. g_installed_full_superhires_colormap is
|
||||
always false in KEGS for now. video.c calls update_color_array and changes
|
||||
g_a2vid_palette. No xdriver routines gets notified when g_a2vid_palette
|
||||
changes, so update_physical_colormap must handle the case where
|
||||
g_a2vid_palette might have changed since it was last called.
|
||||
|
||||
x_redraw_ximage():
|
||||
Routines in video.c are free to draw into the corresponding data_*
|
||||
arrays to change any byte at any time. video.c manages remembering
|
||||
which lines need to be redrawn and which parts of the screen are in
|
||||
which video mode via the a2_line_* arrays.
|
||||
|
||||
KEGS divides the video screen up into 25 groups, corresponding to each
|
||||
text line. Each of these groups consists of 16 sublines. 25*8 = 400 lines.
|
||||
(video.c has already doubled the vertical resolution in all video modes).
|
||||
KEGS can allow any group to be from any of the five screens it manages:
|
||||
The two text/lores pages, the two hires pages, and the superhires screen.
|
||||
For each group, KEGS keeps track of what part of it needs to be redrawn.
|
||||
g_a2_screen_buffer_changed has a bit set for each group which has changed
|
||||
since the last call to x_redraw_ximage(). The rightmost bit (bit 0)
|
||||
corresponds to group 0. If g_a2_screen_buffer_changed == 0, no groups
|
||||
need to be redrawn. x_redraw_ximage clears out g_a2_screen_buffer_changed
|
||||
after drawing the screen.
|
||||
|
||||
For each group, a2_line_left_edge[] and a2_line_right_edge give the pixel
|
||||
offsets of what should be redrawn. a2_line_xim[] gives the ximage handle
|
||||
of what needs to be redrawn. KEGS always redraws 8 verticals of a group.
|
||||
g_full_refresh_needed also has one bit set in it for each group, which
|
||||
indicates overriding the a2_line_*_edge functions and redraw from 0 to
|
||||
640 pixels of each group that needs to be redrawn. x_redraw_ximage()
|
||||
interprets this information now using a simple algorithm: Skip over
|
||||
groups which have not changed (using g_a2_screen_buffer_changed).
|
||||
Save the ximage of this group, the left pixel and the right pixel.
|
||||
Continue with the next group if it has changed. Widen the pixel region
|
||||
and keep sucking up new groups to the same ximage. At group 25, or
|
||||
when the ximage changes, call x_refresh_lines to redraw this large
|
||||
rectangle from this ximage. x_refresh_lines() knows the ximage
|
||||
corresponding to the border for the last group has to be handled
|
||||
specially since the border group is not 640*400 pixels like the others.
|
||||
|
||||
Other porting info:
|
||||
a2_key_to_xsym[][3] contains the mapping function from X keysyms to
|
||||
a2 keycodes. The first element is the a2 keycode, the second element
|
||||
is the unshifted X keysym, and the third element is the shifted keysym.
|
||||
A port must make the conversion to a2 keycodes, and provide up and
|
||||
down events.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>KEGSMAC</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>kegsicon.icns</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.1</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
Binary file not shown.
|
@ -0,0 +1,123 @@
|
|||
# $Id: release_makefile_base,v 1.15 2003/11/21 20:00:42 kentd Exp $
|
||||
|
||||
OBJECTS1 = adb.o clock.o config.o dis.o engine_c.o scc.o iwm.o \
|
||||
joystick_driver.o moremem.o paddles.o sim65816.o smartport.o \
|
||||
sound.o sound_driver.o video.o scc_socket_driver.o scc_windriver.o \
|
||||
scc_macdriver.o
|
||||
|
||||
include vars
|
||||
|
||||
.SUFFIXES: .dep .proto
|
||||
|
||||
AS = $(CC)
|
||||
|
||||
XLIBS = -L/usr/X11R6/lib
|
||||
PERL = perl
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
specials: 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s
|
||||
|
||||
specials_clean:
|
||||
rm -f 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s
|
||||
|
||||
|
||||
# Mac builds:
|
||||
kegsmac: $(OBJECTS) compile_time.o
|
||||
$(CC) $(CCOPTS) $(LDOPTS) -arch ppc $(OBJECTS) compile_time.o $(LDFLAGS) -o kegsmac $(EXTRA_LIBS) -prebind -framework Carbon
|
||||
mkdir -p ../KEGSMAC.app/Contents/Resources/English.lproj/main.nib
|
||||
mkdir -p ../KEGSMAC.app/Contents/MacOS
|
||||
mv kegsmac ../KEGSMAC.app/Contents/MacOS/KEGSMAC
|
||||
echo "APPL????" > ../KEGSMAC.app/Contents/PkgInfo
|
||||
cp -f Info.plist ../KEGSMAC.app/Contents/
|
||||
cp -f InfoPlist.strings ../KEGSMAC.app/Contents/Resources/English.lproj/
|
||||
cp -f info.nib ../KEGSMAC.app/Contents/Resources/English.lproj/main.nib
|
||||
cp -f classes.nib ../KEGSMAC.app/Contents/Resources/English.lproj/main.nib
|
||||
cp -f objects.xib ../KEGSMAC.app/Contents/Resources/English.lproj/main.nib
|
||||
cp -f kegsicon.icns ../KEGSMAC.app/Contents/Resources/
|
||||
touch '../KEGSMAC.app/Icon?'
|
||||
|
||||
# Linux for X builds:
|
||||
xkegs: $(OBJECTS) compile_time.o
|
||||
$(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) -lX11
|
||||
mv xkegs ..
|
||||
|
||||
# Cygwin for X builds:
|
||||
kegs.exe: $(OBJECTS) compile_time.o
|
||||
$(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) -lXext -lX11 -lm
|
||||
mv kegs.exe ..
|
||||
|
||||
# Mingw32 (native windows) builds:
|
||||
kegswin.exe: $(OBJECTS) compile_time.o
|
||||
$(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(EXTRA_LIBS) -lwinmm -lgdi32 -ldsound -lcomctl32
|
||||
mv $(NAME)$(SUFFIX) ..
|
||||
|
||||
|
||||
8inst_c.h: instable.h
|
||||
$(PERL) make_inst c 8 instable.h > 8inst_c.h
|
||||
|
||||
16inst_c.h: instable.h
|
||||
$(PERL) make_inst c 16 instable.h > 16inst_c.h
|
||||
|
||||
size_c.h: size_tab.h
|
||||
$(PERL) make_size c size_tab.h > size_c.h
|
||||
|
||||
engine_c.o: 8inst_c.h 16inst_c.h size_c.h
|
||||
|
||||
8inst_s.h: instable.h
|
||||
$(PERL) make_inst s 8 instable.h > 8inst_s.h
|
||||
|
||||
16inst_s.h: instable.h
|
||||
$(PERL) make_inst s 16 instable.h > 16inst_s.h
|
||||
|
||||
size_s.h: size_tab.h
|
||||
$(PERL) make_size s size_tab.h > size_s.h
|
||||
|
||||
8size_s.h: size_tab.h
|
||||
$(PERL) make_size 8 size_tab.h > 8size_s.h
|
||||
|
||||
16size_s.h: size_tab.h
|
||||
$(PERL) make_size 16 size_tab.h > 16size_s.h
|
||||
|
||||
engine_s.o: 8inst_s.h 16inst_s.h 8size_s.h 16size_s.h size_s.h
|
||||
|
||||
.s.o:
|
||||
$(AS) -c $(OPTS) -I. $*.s
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CCOPTS) $(XOPTS) -c $(OPTS) -I. $*.c
|
||||
|
||||
partls: partls.c
|
||||
cc $(CCOPTS) $(XOPTS) $(OPTS) -o partls partls.c
|
||||
|
||||
to_pro: prodos.h prodos_protos.h to_pro.c
|
||||
cc $(CCOPTS) $(XOPTS) $(OPTS) -o to_pro to_pro.c
|
||||
|
||||
|
||||
compile_time.o: $(OBJECTS)
|
||||
|
||||
|
||||
# dependency stuff
|
||||
adb.o: adb.c adb.h defc.h defcomm.h iwm.h protos.h
|
||||
engine_c.o: engine_c.c defc.h defcomm.h iwm.h protos.h protos_engine_c.h size_c.h op_routs.h defs_instr.h 8inst_c.h 16inst_c.h
|
||||
clock.o: clock.c defc.h defcomm.h iwm.h protos.h
|
||||
compile_time.o: compile_time.c
|
||||
config.o: config.c defc.h defcomm.h iwm.h protos.h config.h
|
||||
dis.o: dis.c defc.h defcomm.h iwm.h protos.h disas.h
|
||||
scc.o: scc.c defc.h defcomm.h iwm.h protos.h scc.h
|
||||
scc_socket_driver.o: scc_socket_driver.c defc.h defcomm.h iwm.h protos.h scc.h
|
||||
scc_windriver.o: scc_windriver.c defc.h defcomm.h iwm.h protos.h scc.h
|
||||
scc_macdriver.o: scc_macdriver.c defc.h defcomm.h iwm.h protos.h scc.h
|
||||
iwm.o: iwm.c defc.h defcomm.h iwm.h protos.h iwm_35_525.h
|
||||
joystick_driver.o: joystick_driver.c defc.h defcomm.h iwm.h protos.h
|
||||
moremem.o: moremem.c defc.h defcomm.h iwm.h protos.h
|
||||
paddles.o: paddles.c defc.h defcomm.h iwm.h protos.h
|
||||
sim65816.o: sim65816.c defc.h defcomm.h iwm.h protos.h
|
||||
smartport.o: smartport.c defc.h defcomm.h iwm.h protos.h
|
||||
sound.o: sound.c defc.h defcomm.h iwm.h protos.h sound.h
|
||||
sound_driver.o: sound_driver.c defc.h defcomm.h iwm.h protos.h sound.h
|
||||
video.o: video.c defc.h defcomm.h iwm.h protos.h superhires.h kegsfont.h
|
||||
macdriver.o: macdriver.c defc.h defcomm.h iwm.h protos.h protos_macdriver.h
|
||||
macsnd_driver.o: macsnd_driver.c defc.h defcomm.h iwm.h protos.h sound.h
|
||||
windriver.o: windriver.c defc.h defcomm.h iwm.h protos.h protos_windriver.h winresource.h
|
||||
win32snd_driver.o: win32snd_driver.c defc.h defcomm.h iwm.h protos.h sound.h
|
|
@ -0,0 +1,160 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_adb_h[] = "@(#)$KmKId: adb.h,v 1.9 2002-11-19 03:10:38-05 kadickey Exp $";
|
||||
|
||||
#include "defc.h"
|
||||
|
||||
/* Format: a2code, ascii if no shift, ascii if shift, ascii if ctl */
|
||||
const int a2_key_to_ascii[][4] = {
|
||||
{ 0x00, 'a', 'A', 0x01 },
|
||||
{ 0x01, 's', 'S', 0x13 },
|
||||
{ 0x02, 'd', 'D', 0x04 },
|
||||
{ 0x03, 'f', 'F', 0x06 },
|
||||
{ 0x04, 'h', 'H', 0x08 },
|
||||
{ 0x05, 'g', 'G', 0x07 },
|
||||
{ 0x06, 'z', 'Z', 0x1a },
|
||||
{ 0x07, 'x', 'X', 0x18 },
|
||||
|
||||
{ 0x08, 'c', 'C', 0x03 },
|
||||
{ 0x09, 'v', 'V', 0x16 },
|
||||
{ 0x0a, -1, -1, -1 },
|
||||
{ 0x0b, 'b', 'B', 0x02 },
|
||||
{ 0x0c, 'q', 'Q', 0x11 },
|
||||
{ 0x0d, 'w', 'W', 0x17 },
|
||||
{ 0x0e, 'e', 'E', 0x05 },
|
||||
{ 0x0f, 'r', 'R', 0x12 },
|
||||
|
||||
{ 0x10, 'y', 'Y', 0x19 },
|
||||
{ 0x11, 't', 'T', 0x14 },
|
||||
{ 0x12, '1', '!', -1 },
|
||||
{ 0x13, '2', '@', 0x00 },
|
||||
{ 0x14, '3', '#', -1 },
|
||||
{ 0x15, '4', '$', -1 },
|
||||
{ 0x16, '6', '^', 0x1e },
|
||||
{ 0x17, '5', '%', -1 },
|
||||
|
||||
{ 0x18, '=', '+', -1 },
|
||||
{ 0x19, '9', '(', -1 },
|
||||
{ 0x1a, '7', '&', -1 },
|
||||
{ 0x1b, '-', '_', 0x1f },
|
||||
{ 0x1c, '8', '*', -1 },
|
||||
{ 0x1d, '0', ')', -1 },
|
||||
{ 0x1e, ']', '}', 0x1d },
|
||||
{ 0x1f, 'o', 'O', 0x0f },
|
||||
|
||||
{ 0x20, 'u', 'U', 0x15 },
|
||||
{ 0x21, '[', '{', 0x1b },
|
||||
{ 0x22, 'i', 'I', 0x09 },
|
||||
{ 0x23, 'p', 'P', 0x10 },
|
||||
{ 0x24, 0x0d, 0x0d, -1 }, /* return */
|
||||
{ 0x25, 'l', 'L', 0x0c },
|
||||
{ 0x26, 'j', 'J', 0x0a },
|
||||
{ 0x27, 0x27, '"', -1 }, /* single quote */
|
||||
|
||||
{ 0x28, 'k', 'K', 0x0b },
|
||||
{ 0x29, ';', ':', -1 },
|
||||
{ 0x2a, 0x5c, '|', 0x1c }, /* \, | */
|
||||
{ 0x2b, ',', '<', -1 },
|
||||
{ 0x2c, '/', '?', 0x7f },
|
||||
{ 0x2d, 'n', 'N', 0x0e },
|
||||
{ 0x2e, 'm', 'M', 0x0d },
|
||||
{ 0x2f, '.', '>', -1 },
|
||||
|
||||
{ 0x30, 0x09, 0x09, -1 }, /* tab */
|
||||
{ 0x31, ' ', ' ', -1 },
|
||||
{ 0x32, '`', '~', -1 },
|
||||
{ 0x33, 0x7f, 0x7f, -1 }, /* Delete */
|
||||
{ 0x34, -1, -1, -1 },
|
||||
{ 0x35, 0x1b, 0x1b, -1 }, /* Esc */
|
||||
{ 0x36, 0x0200, 0x0200, -1 }, /* control */
|
||||
{ 0x37, 0x8000, 0x8000, -1 }, /* Command */
|
||||
|
||||
{ 0x38, 0x0100, 0x0100, -1 }, /* shift */
|
||||
{ 0x39, 0x0400, 0x0400, -1 }, /* caps lock */
|
||||
{ 0x3a, 0x4000, 0x4000, -1 }, /* Option */
|
||||
{ 0x3b, 0x08, 0x08, -1 }, /* left */
|
||||
{ 0x3c, 0x15, 0x15, -1 }, /* right */
|
||||
{ 0x3d, 0x0a, 0x0a, -1 }, /* down */
|
||||
{ 0x3e, 0x0b, 0x0b, -1 }, /* up arrow */
|
||||
{ 0x3f, -1, -1, -1 },
|
||||
|
||||
{ 0x40, -1, -1, -1 },
|
||||
{ 0x41, 0x102e, 0x102e, -1 }, /* keypad . */
|
||||
{ 0x42, -1, -1, -1 },
|
||||
{ 0x43, 0x102a, 0x102a, -1 }, /* keypad * */
|
||||
{ 0x44, -1, -1, -1 },
|
||||
{ 0x45, 0x102b, 0x102b, -1 }, /* keypad + */
|
||||
{ 0x46, -1, -1, -1 },
|
||||
{ 0x47, 0x1018, 0x1018, -1 }, /* keypad Clear */
|
||||
|
||||
{ 0x48, -1, -1, -1 },
|
||||
{ 0x49, -1, -1, -1 },
|
||||
{ 0x4a, -1, -1, -1 },
|
||||
{ 0x4b, 0x102f, 0x102f, -1 }, /* keypad / */
|
||||
{ 0x4c, 0x100d, 0x100d, -1 }, /* keypad enter */
|
||||
{ 0x4d, -1, -1, -1 },
|
||||
{ 0x4e, 0x102d, 0x102d, -1 }, /* keypad - */
|
||||
{ 0x4f, -1, -1, -1 },
|
||||
|
||||
{ 0x50, -1, -1, -1 },
|
||||
{ 0x51, 0x103d, 0x103d, -1 }, /* keypad = */
|
||||
{ 0x52, 0x1030, 0x1030, -1 }, /* keypad 0 */
|
||||
{ 0x53, 0x1031, 0x1031, -1 }, /* keypad 1 */
|
||||
{ 0x54, 0x1032, 0x1032, -1 }, /* keypad 2 */
|
||||
{ 0x55, 0x1033, 0x1033, -1 }, /* keypad 3 */
|
||||
{ 0x56, 0x1034, 0x1034, -1 }, /* keypad 4 */
|
||||
{ 0x57, 0x1035, 0x1035, -1 }, /* keypad 5 */
|
||||
|
||||
{ 0x58, 0x1036, 0x1036, -1 }, /* keypad 6 */
|
||||
{ 0x59, 0x1037, 0x1037, -1 }, /* keypad 7 */
|
||||
{ 0x5a, -1, -1, -1 },
|
||||
{ 0x5b, 0x1038, 0x1038, -1 }, /* keypad 8 */
|
||||
{ 0x5c, 0x1039, 0x1039, -1 }, /* keypad 9 */
|
||||
{ 0x5d, -1, -1, -1 },
|
||||
{ 0x5e, -1, -1, -1 },
|
||||
{ 0x5f, -1, -1, -1 },
|
||||
|
||||
{ 0x60, 0x8005, 0x1060, -1 }, /* F5 */
|
||||
{ 0x61, 0x8006, 0x1061, -1 }, /* F6 */
|
||||
{ 0x62, 0x8007, 0x1062, -1 }, /* F7 */
|
||||
{ 0x63, 0x8003, 0x1063, -1 }, /* F3 */
|
||||
{ 0x64, 0x8008, 0x1064, -1 }, /* F8 */
|
||||
{ 0x65, 0x8009, 0x1065, -1 }, /* F9 */
|
||||
{ 0x66, -1, -1, -1 },
|
||||
{ 0x67, 0x800b, 0x1067, -1 }, /* F11 */
|
||||
|
||||
{ 0x68, -1, -1, -1 },
|
||||
{ 0x69, 0x800d, 0x1069, -1 }, /* F13 */
|
||||
{ 0x6a, -1, -1, -1 },
|
||||
{ 0x6b, 0x800e, 0x106b, -1 }, /* F14 */
|
||||
{ 0x6c, -1, -1, -1 },
|
||||
{ 0x6d, 0x800a, 0x106d, -1 }, /* F10 */
|
||||
{ 0x6e, -1, -1, -1 },
|
||||
{ 0x6f, 0x800c, 0x106f, -1 }, /* F12 */
|
||||
|
||||
{ 0x70, -1, -1, -1 },
|
||||
{ 0x71, 0x800f, 0x1071, -1 }, /* F15 */
|
||||
{ 0x72, 0x1072, 0x1072, -1 }, /* Help, insert */
|
||||
{ 0x73, 0x1073, 0x1073, -1 }, /* Home */
|
||||
{ 0x74, 0x1074, 0x1074, -1 }, /* Page up */
|
||||
{ 0x75, 0x1075, 0x1075, -1 }, /* keypad delete */
|
||||
{ 0x76, 0x8004, 0x1076, -1 }, /* F4 */
|
||||
{ 0x77, 0x1077, 0x1077, -1 }, /* keypad end */
|
||||
|
||||
{ 0x78, 0x8002, 0x1078, -1 }, /* F2 */
|
||||
{ 0x79, 0x1079, 0x1079, -1 }, /* keypad page down */
|
||||
{ 0x7a, 0x8001, 0x107a, -1 }, /* F1 */
|
||||
{ 0x7b, 0x08, 0x08, -1 }, /* left */ /* remapped to 0x3b */
|
||||
{ 0x7c, 0x15, 0x15, -1 }, /* right */ /* remapped to 0x3c */
|
||||
{ 0x7d, 0x0a, 0x0a, -1 }, /* down */ /* remapped to 0x3d */
|
||||
{ 0x7e, 0x0b, 0x0b, -1 }, /* up arrow */ /* remapped to 0x3e */
|
||||
{ 0x7f, -1, -1, -1 }, /* Reset */
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
IBClasses = ();
|
||||
IBVersion = 1;
|
||||
}
|
|
@ -0,0 +1,392 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_clock_c[] = "@(#)$KmKId: clock.c,v 1.29 2003-10-17 15:07:35-04 kentd Exp $";
|
||||
|
||||
#include "defc.h"
|
||||
#include <time.h>
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
# include <mmsystem.h>
|
||||
#else
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
extern int Verbose;
|
||||
extern int g_vbl_count;
|
||||
extern int g_rom_version;
|
||||
extern int g_config_kegs_update_needed;
|
||||
|
||||
#define CLK_IDLE 1
|
||||
#define CLK_TIME 2
|
||||
#define CLK_INTERNAL 3
|
||||
#define CLK_BRAM1 4
|
||||
#define CLK_BRAM2 5
|
||||
|
||||
int g_clk_mode = CLK_IDLE;
|
||||
int g_clk_read = 0;
|
||||
int g_clk_reg1 = 0;
|
||||
|
||||
word32 c033_data = 0;
|
||||
word32 c034_val = 0;
|
||||
|
||||
byte g_bram[2][256];
|
||||
byte *g_bram_ptr = &(g_bram[0][0]);
|
||||
|
||||
word32 g_clk_cur_time = 0xa0000000;
|
||||
int g_clk_next_vbl_update = 0;
|
||||
|
||||
double
|
||||
get_dtime()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
struct timeval tp1;
|
||||
double dsec;
|
||||
double dusec;
|
||||
#endif
|
||||
double dtime;
|
||||
|
||||
/* Routine used to return actual system time as a double */
|
||||
/* No routine cares about the absolute value, only deltas--maybe */
|
||||
/* take advantage of that in future to increase usec accuracy */
|
||||
|
||||
#ifdef _WIN32
|
||||
dtime = timeGetTime() / 1000.0;
|
||||
#else
|
||||
|
||||
# ifdef SOLARIS
|
||||
gettimeofday(&tp1, (void *)0);
|
||||
# else
|
||||
gettimeofday(&tp1, (struct timezone *)0);
|
||||
# endif
|
||||
|
||||
dsec = (double)tp1.tv_sec;
|
||||
dusec = (double)tp1.tv_usec;
|
||||
|
||||
dtime = dsec + (dusec / (1000.0 * 1000.0));
|
||||
#endif
|
||||
|
||||
return dtime;
|
||||
}
|
||||
|
||||
int
|
||||
micro_sleep(double dtime)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
struct timeval Timer;
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
if(dtime <= 0.0) {
|
||||
return 0;
|
||||
}
|
||||
if(dtime >= 1.0) {
|
||||
halt_printf("micro_sleep called with %f!!\n", dtime);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("usleep: %f\n", dtime);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
Sleep(dtime * 1000);
|
||||
#else
|
||||
Timer.tv_sec = 0;
|
||||
Timer.tv_usec = (dtime * 1000000.0);
|
||||
if( (ret = select(0, 0, 0, 0, &Timer)) < 0) {
|
||||
fprintf(stderr, "micro_sleep (select) ret: %d, errno: %d\n",
|
||||
ret, errno);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
clk_bram_zero()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* zero out all bram */
|
||||
for(i = 0; i < 2; i++) {
|
||||
for(j = 0; j < 256; j++) {
|
||||
g_bram[i][j] = 0;
|
||||
}
|
||||
}
|
||||
g_bram_ptr = &(g_bram[0][0]);
|
||||
}
|
||||
|
||||
void
|
||||
clk_bram_set(int bram_num, int offset, int val)
|
||||
{
|
||||
g_bram[bram_num][offset] = val;
|
||||
}
|
||||
|
||||
void
|
||||
clk_setup_bram_version()
|
||||
{
|
||||
if(g_rom_version < 3) {
|
||||
g_bram_ptr = (&g_bram[0][0]); // ROM 01
|
||||
} else {
|
||||
g_bram_ptr = (&g_bram[1][0]); // ROM 03
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clk_write_bram(FILE *fconf)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
for(i = 0; i < 2; i++) {
|
||||
fprintf(fconf, "\n");
|
||||
for(j = 0; j < 256; j += 16) {
|
||||
fprintf(fconf, "bram%d[%02x] =", 2*i + 1, j);
|
||||
for(k = 0; k < 16; k++) {
|
||||
fprintf(fconf, " %02x", g_bram[i][j+k]);
|
||||
}
|
||||
fprintf(fconf, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
update_cur_time()
|
||||
{
|
||||
struct tm *tm_ptr;
|
||||
time_t cur_time;
|
||||
unsigned int secs, secs2;
|
||||
|
||||
cur_time = time(0);
|
||||
|
||||
/* Figure out the timezone (effectively) by diffing two times. */
|
||||
/* this is probably not right for a few hours around daylight savings*/
|
||||
/* time transition */
|
||||
secs2 = mktime(gmtime(&cur_time));
|
||||
tm_ptr = localtime(&cur_time);
|
||||
secs = mktime(tm_ptr);
|
||||
|
||||
secs = (unsigned int)cur_time - (secs2 - secs);
|
||||
|
||||
if(tm_ptr->tm_isdst) {
|
||||
/* adjust for daylight savings time */
|
||||
secs += 3600;
|
||||
}
|
||||
|
||||
/* add in secs to make date based on Apple Jan 1, 1904 instead of */
|
||||
/* Unix's Jan 1, 1970 */
|
||||
/* So add in 66 years and 17 leap year days (1904 is a leap year) */
|
||||
secs += ((66*365) + 17) * (24*3600);
|
||||
|
||||
g_clk_cur_time = secs;
|
||||
|
||||
clk_printf("Update g_clk_cur_time to %08x\n", g_clk_cur_time);
|
||||
g_clk_next_vbl_update = g_vbl_count + 5;
|
||||
}
|
||||
|
||||
/* clock_update called by sim65816 every VBL */
|
||||
void
|
||||
clock_update()
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
void
|
||||
clock_update_if_needed()
|
||||
{
|
||||
int diff;
|
||||
|
||||
diff = g_clk_next_vbl_update - g_vbl_count;
|
||||
if(diff < 0 || diff > 60) {
|
||||
/* Been a while, re-read the clock */
|
||||
update_cur_time();
|
||||
}
|
||||
}
|
||||
|
||||
word32
|
||||
clock_read_c033()
|
||||
{
|
||||
return c033_data;
|
||||
}
|
||||
|
||||
word32
|
||||
clock_read_c034()
|
||||
{
|
||||
return c034_val;
|
||||
}
|
||||
|
||||
void
|
||||
clock_write_c033(word32 val)
|
||||
{
|
||||
c033_data = val;
|
||||
}
|
||||
|
||||
void
|
||||
clock_write_c034(word32 val)
|
||||
{
|
||||
c034_val = val & 0x7f;
|
||||
if((val & 0x80) != 0) {
|
||||
if((val & 0x20) == 0) {
|
||||
printf("c034 write not last = 1\n");
|
||||
/* set_halt(1); */
|
||||
}
|
||||
do_clock_data();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
do_clock_data()
|
||||
{
|
||||
word32 mask;
|
||||
int read;
|
||||
int op;
|
||||
|
||||
clk_printf("In do_clock_data, g_clk_mode: %02x\n", g_clk_mode);
|
||||
|
||||
read = c034_val & 0x40;
|
||||
switch(g_clk_mode) {
|
||||
case CLK_IDLE:
|
||||
g_clk_read = (c033_data >> 7) & 1;
|
||||
g_clk_reg1 = (c033_data >> 2) & 3;
|
||||
op = (c033_data >> 4) & 7;
|
||||
if(!read) {
|
||||
/* write */
|
||||
switch(op) {
|
||||
case 0x0: /* Read/write seconds register */
|
||||
g_clk_mode = CLK_TIME;
|
||||
clock_update_if_needed();
|
||||
break;
|
||||
case 0x3: /* internal registers */
|
||||
g_clk_mode = CLK_INTERNAL;
|
||||
if(g_clk_reg1 & 0x2) {
|
||||
/* extend BRAM read */
|
||||
g_clk_mode = CLK_BRAM2;
|
||||
g_clk_reg1 = (c033_data & 7) << 5;
|
||||
}
|
||||
break;
|
||||
case 0x2: /* read/write ram 0x10-0x13 */
|
||||
g_clk_mode = CLK_BRAM1;
|
||||
g_clk_reg1 += 0x10;
|
||||
break;
|
||||
case 0x4: /* read/write ram 0x00-0x0f */
|
||||
case 0x5: case 0x6: case 0x7:
|
||||
g_clk_mode = CLK_BRAM1;
|
||||
g_clk_reg1 = (c033_data >> 2) & 0xf;
|
||||
break;
|
||||
default:
|
||||
halt_printf("Bad c033_data in CLK_IDLE: %02x\n",
|
||||
c033_data);
|
||||
}
|
||||
} else {
|
||||
printf("clk read from IDLE mode!\n");
|
||||
/* set_halt(1); */
|
||||
g_clk_mode = CLK_IDLE;
|
||||
}
|
||||
break;
|
||||
case CLK_BRAM2:
|
||||
if(!read) {
|
||||
/* get more bits of bram addr */
|
||||
if((c033_data & 0x83) == 0x00) {
|
||||
/* more address bits */
|
||||
g_clk_reg1 |= ((c033_data >> 2) & 0x1f);
|
||||
g_clk_mode = CLK_BRAM1;
|
||||
} else {
|
||||
halt_printf("CLK_BRAM2: c033_data: %02x!\n",
|
||||
c033_data);
|
||||
g_clk_mode = CLK_IDLE;
|
||||
}
|
||||
} else {
|
||||
halt_printf("CLK_BRAM2: clock read!\n");
|
||||
g_clk_mode = CLK_IDLE;
|
||||
}
|
||||
break;
|
||||
case CLK_BRAM1:
|
||||
/* access battery ram addr g_clk_reg1 */
|
||||
if(read) {
|
||||
if(g_clk_read) {
|
||||
/* Yup, read */
|
||||
c033_data = g_bram_ptr[g_clk_reg1];
|
||||
clk_printf("Reading BRAM loc %02x: %02x\n",
|
||||
g_clk_reg1, c033_data);
|
||||
} else {
|
||||
halt_printf("CLK_BRAM1: said wr, now read\n");
|
||||
}
|
||||
} else {
|
||||
if(g_clk_read) {
|
||||
halt_printf("CLK_BRAM1: said rd, now write\n");
|
||||
} else {
|
||||
/* Yup, write */
|
||||
clk_printf("Writing BRAM loc %02x with %02x\n",
|
||||
g_clk_reg1, c033_data);
|
||||
g_bram_ptr[g_clk_reg1] = c033_data;
|
||||
g_config_kegs_update_needed = 1;
|
||||
}
|
||||
}
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
case CLK_TIME:
|
||||
if(read) {
|
||||
if(g_clk_read == 0) {
|
||||
halt_printf("Reading time, but in set mode!\n");
|
||||
}
|
||||
c033_data = (g_clk_cur_time >> (g_clk_reg1 * 8)) & 0xff;
|
||||
clk_printf("Returning time byte %d: %02x\n",
|
||||
g_clk_reg1, c033_data);
|
||||
} else {
|
||||
/* Write */
|
||||
if(g_clk_read) {
|
||||
halt_printf("Write time, but in read mode!\n");
|
||||
}
|
||||
clk_printf("Writing TIME loc %d with %02x\n",
|
||||
g_clk_reg1, c033_data);
|
||||
mask = 0xff << (8 * g_clk_reg1);
|
||||
|
||||
g_clk_cur_time = (g_clk_cur_time & (~mask)) |
|
||||
((c033_data & 0xff) << (8 *g_clk_reg1));
|
||||
}
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
case CLK_INTERNAL:
|
||||
if(read) {
|
||||
printf("Attempting to read internal reg %02x!\n",
|
||||
g_clk_reg1);
|
||||
} else {
|
||||
switch(g_clk_reg1) {
|
||||
case 0x0: /* test register */
|
||||
if(c033_data & 0xc0) {
|
||||
printf("Writing test reg: %02x!\n",
|
||||
c033_data);
|
||||
/* set_halt(1); */
|
||||
}
|
||||
break;
|
||||
case 0x1: /* write protect reg */
|
||||
clk_printf("Writing clk wr_protect: %02x\n",
|
||||
c033_data);
|
||||
if(c033_data & 0x80) {
|
||||
printf("Stop, wr clk wr_prot: %02x\n",
|
||||
c033_data);
|
||||
/* set_halt(1); */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
halt_printf("Writing int reg: %02x with %02x\n",
|
||||
g_clk_reg1, c033_data);
|
||||
}
|
||||
}
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
default:
|
||||
halt_printf("clk mode: %d unknown!\n", g_clk_mode);
|
||||
g_clk_mode = CLK_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
const char rcsid_compile_time_c[] = "@(#)$KmKId: compile_time.c,v 1.2 2002-11-14 01:02:44-05 kadickey Exp $";
|
||||
|
||||
char g_compile_time[] = "Compiled: " __DATE__ " " __TIME__ ;
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,34 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2003 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_C
|
||||
const char rcsid_config_h[] = "@(#)$KmKId: config.h,v 1.8 2003-10-17 15:09:58-04 kentd Exp $";
|
||||
#endif
|
||||
|
||||
#define CONF_BUF_LEN 1024
|
||||
#define COPY_BUF_SIZE 4096
|
||||
#define CFG_PRINTF_BUFSIZE 2048
|
||||
|
||||
#define CFG_PATH_MAX 1024
|
||||
|
||||
#define CFG_NUM_SHOWENTS 16
|
||||
|
||||
#define CFGTYPE_MENU 1
|
||||
#define CFGTYPE_INT 2
|
||||
#define CFGTYPE_DISK 3
|
||||
#define CFGTYPE_FUNC 4
|
||||
/* CFGTYPE limited to just 4 bits: 0-15 */
|
||||
|
||||
/* Cfg_menu, Cfg_dirent and Cfg_listhdr are defined in defc.h */
|
||||
|
||||
STRUCT(Cfg_defval) {
|
||||
Cfg_menu *menuptr;
|
||||
int intval;
|
||||
};
|
|
@ -0,0 +1,265 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_C
|
||||
const char rcsid_defc_h[] = "@(#)$KmKId: defc.h,v 1.91 2003-11-03 01:29:38-05 kentd Exp $";
|
||||
#endif
|
||||
|
||||
#include "defcomm.h"
|
||||
|
||||
#define STRUCT(a) typedef struct _ ## a a; struct _ ## a
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word16;
|
||||
typedef unsigned int word32;
|
||||
#if _MSC_VER
|
||||
typedef unsigned __int64 word64;
|
||||
#else
|
||||
typedef unsigned long long word64;
|
||||
#endif
|
||||
|
||||
void U_STACK_TRACE();
|
||||
|
||||
/* 28MHz crystal, plus every 65th 1MHz cycle is stretched 140ns */
|
||||
#define CYCS_28_MHZ (28636360)
|
||||
#define DCYCS_28_MHZ (1.0*CYCS_28_MHZ)
|
||||
#define CYCS_3_5_MHZ (CYCS_28_MHZ/8)
|
||||
#define DCYCS_1_MHZ ((DCYCS_28_MHZ/28.0)*(65.0*7/(65.0*7+1.0)))
|
||||
#define CYCS_1_MHZ ((int)DCYCS_1_MHZ)
|
||||
|
||||
#define DCYCS_IN_16MS_RAW (DCYCS_1_MHZ / 60.0)
|
||||
#define DCYCS_IN_16MS ((double)((int)DCYCS_IN_16MS_RAW))
|
||||
#define DRECIP_DCYCS_IN_16MS (1.0 / (DCYCS_IN_16MS))
|
||||
|
||||
#ifdef KEGS_LITTLE_ENDIAN
|
||||
# define BIGEND(a) ((((a) >> 24) & 0xff) + \
|
||||
(((a) >> 8) & 0xff00) + \
|
||||
(((a) << 8) & 0xff0000) + \
|
||||
(((a) << 24) & 0xff000000))
|
||||
# define GET_BE_WORD16(a) ((((a) >> 8) & 0xff) + (((a) << 8) & 0xff00))
|
||||
# define GET_BE_WORD32(a) (BIGEND(a))
|
||||
#else
|
||||
# define BIGEND(a) (a)
|
||||
# define GET_BE_WORD16(a) (a)
|
||||
# define GET_BE_WORD32(a) (a)
|
||||
#endif
|
||||
|
||||
#define MAXNUM_HEX_PER_LINE 32
|
||||
|
||||
#ifdef __NeXT__
|
||||
# include <libc.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <unistd.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef HPUX
|
||||
# include <machine/inline.h> /* for GET_ITIMER */
|
||||
#endif
|
||||
|
||||
#ifdef SOLARIS
|
||||
# include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
/* work around some Windows junk */
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
STRUCT(Pc_log) {
|
||||
double dcycs;
|
||||
word32 dbank_kpc;
|
||||
word32 instr;
|
||||
word32 psr_acc;
|
||||
word32 xreg_yreg;
|
||||
word32 stack_direct;
|
||||
word32 pad;
|
||||
};
|
||||
|
||||
STRUCT(Event) {
|
||||
double dcycs;
|
||||
int type;
|
||||
Event *next;
|
||||
};
|
||||
|
||||
STRUCT(Fplus) {
|
||||
double plus_1;
|
||||
double plus_2;
|
||||
double plus_3;
|
||||
double plus_x_minus_1;
|
||||
};
|
||||
|
||||
STRUCT(Engine_reg) {
|
||||
double fcycles;
|
||||
word32 kpc;
|
||||
word32 acc;
|
||||
|
||||
word32 xreg;
|
||||
word32 yreg;
|
||||
|
||||
word32 stack;
|
||||
word32 dbank;
|
||||
|
||||
word32 direct;
|
||||
word32 psr;
|
||||
Fplus *fplus_ptr;
|
||||
};
|
||||
|
||||
STRUCT(Kimage) {
|
||||
void *dev_handle;
|
||||
void *dev_handle2;
|
||||
byte *data_ptr;
|
||||
int width_req;
|
||||
int width_act;
|
||||
int height;
|
||||
int depth;
|
||||
int mdepth;
|
||||
int aux_info;
|
||||
};
|
||||
|
||||
typedef byte *Pg_info;
|
||||
STRUCT(Page_info) {
|
||||
Pg_info rd_wr;
|
||||
};
|
||||
|
||||
STRUCT(Cfg_menu) {
|
||||
const char *str;
|
||||
void *ptr;
|
||||
const char *name_str;
|
||||
void *defptr;
|
||||
int cfgtype;
|
||||
};
|
||||
|
||||
STRUCT(Cfg_dirent) {
|
||||
char *name;
|
||||
int is_dir;
|
||||
int size;
|
||||
int image_start;
|
||||
int part_num;
|
||||
};
|
||||
|
||||
STRUCT(Cfg_listhdr) {
|
||||
Cfg_dirent *direntptr;
|
||||
int max;
|
||||
int last;
|
||||
int invalid;
|
||||
|
||||
int curent;
|
||||
int topent;
|
||||
|
||||
int num_to_show;
|
||||
};
|
||||
|
||||
#ifdef __LP64__
|
||||
# define PTR2WORD(a) ((unsigned long)(a))
|
||||
#else
|
||||
# define PTR2WORD(a) ((unsigned int)(a))
|
||||
#endif
|
||||
|
||||
|
||||
#define ALTZP (statereg & 0x80)
|
||||
#define PAGE2 (statereg & 0x40)
|
||||
#define RAMRD (statereg & 0x20)
|
||||
#define RAMWRT (statereg & 0x10)
|
||||
#define RDROM (statereg & 0x08)
|
||||
#define LCBANK2 (statereg & 0x04)
|
||||
#define ROMB (statereg & 0x02)
|
||||
#define INTCX (statereg & 0x01)
|
||||
|
||||
#define EXTRU(val, pos, len) \
|
||||
( ( (len) >= (pos) + 1) ? ((val) >> (31-(pos))) : \
|
||||
(((val) >> (31-(pos)) ) & ( (1<<(len) ) - 1) ) )
|
||||
|
||||
#define DEP1(val, pos, old_val) \
|
||||
(((old_val) & ~(1 << (31 - (pos))) ) | \
|
||||
( ((val) & 1) << (31 - (pos))) )
|
||||
|
||||
#define set_halt(val) \
|
||||
if(val) { set_halt_act(val); }
|
||||
|
||||
#define clear_halt() \
|
||||
clr_halt_act()
|
||||
|
||||
#define GET_PAGE_INFO_RD(page) \
|
||||
(page_info_rd_wr[page].rd_wr)
|
||||
|
||||
#define GET_PAGE_INFO_WR(page) \
|
||||
(page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr)
|
||||
|
||||
#define SET_PAGE_INFO_RD(page,val) \
|
||||
;page_info_rd_wr[page].rd_wr = (Pg_info)val;
|
||||
|
||||
#define SET_PAGE_INFO_WR(page,val) \
|
||||
;page_info_rd_wr[0x10000 + PAGE_INFO_PAD_SIZE + (page)].rd_wr = \
|
||||
(Pg_info)val;
|
||||
|
||||
#define VERBOSE_DISK 0x001
|
||||
#define VERBOSE_IRQ 0x002
|
||||
#define VERBOSE_CLK 0x004
|
||||
#define VERBOSE_SHADOW 0x008
|
||||
#define VERBOSE_IWM 0x010
|
||||
#define VERBOSE_DOC 0x020
|
||||
#define VERBOSE_ADB 0x040
|
||||
#define VERBOSE_SCC 0x080
|
||||
#define VERBOSE_TEST 0x100
|
||||
#define VERBOSE_VIDEO 0x200
|
||||
#define VERBOSE_MAC 0x400
|
||||
|
||||
#ifdef NO_VERB
|
||||
# define DO_VERBOSE 0
|
||||
#else
|
||||
# define DO_VERBOSE 1
|
||||
#endif
|
||||
|
||||
#define disk_printf if(DO_VERBOSE && (Verbose & VERBOSE_DISK)) printf
|
||||
#define irq_printf if(DO_VERBOSE && (Verbose & VERBOSE_IRQ)) printf
|
||||
#define clk_printf if(DO_VERBOSE && (Verbose & VERBOSE_CLK)) printf
|
||||
#define shadow_printf if(DO_VERBOSE && (Verbose & VERBOSE_SHADOW)) printf
|
||||
#define iwm_printf if(DO_VERBOSE && (Verbose & VERBOSE_IWM)) printf
|
||||
#define doc_printf if(DO_VERBOSE && (Verbose & VERBOSE_DOC)) printf
|
||||
#define adb_printf if(DO_VERBOSE && (Verbose & VERBOSE_ADB)) printf
|
||||
#define scc_printf if(DO_VERBOSE && (Verbose & VERBOSE_SCC)) printf
|
||||
#define test_printf if(DO_VERBOSE && (Verbose & VERBOSE_TEST)) printf
|
||||
#define vid_printf if(DO_VERBOSE && (Verbose & VERBOSE_VIDEO)) printf
|
||||
#define mac_printf if(DO_VERBOSE && (Verbose & VERBOSE_MAC)) printf
|
||||
|
||||
|
||||
#define HALT_ON_SCAN_INT 0x001
|
||||
#define HALT_ON_IRQ 0x002
|
||||
#define HALT_ON_SHADOW_REG 0x004
|
||||
#define HALT_ON_C70D_WRITES 0x008
|
||||
|
||||
#define HALT_ON(a, msg) \
|
||||
if(Halt_on & a) { \
|
||||
halt_printf(msg); \
|
||||
}
|
||||
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) (((a) < (b)) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#define GET_ITIMER(dest) dest = get_itimer();
|
||||
|
||||
#include "iwm.h"
|
||||
#include "protos.h"
|
|
@ -0,0 +1,200 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_C
|
||||
const char rcsdif_defcomm_h[] = "@(#)$KmKId: defcomm.h,v 1.93 2002-11-19 03:10:38-05 kadickey Exp $";
|
||||
#endif
|
||||
|
||||
#define USE_XIMAGE_CHANGED
|
||||
|
||||
#if 0
|
||||
# define CHECK_BREAKPOINTS
|
||||
#endif
|
||||
|
||||
#define SHIFT_PER_CHANGE 3
|
||||
#define CHANGE_SHIFT (5 + SHIFT_PER_CHANGE)
|
||||
|
||||
#define SLOW_MEM_CH_SIZE (0x10000 >> CHANGE_SHIFT)
|
||||
|
||||
#define MAXNUM_HEX_PER_LINE 32
|
||||
|
||||
/* Different Joystick defines */
|
||||
#define JOYSTICK_MOUSE 1
|
||||
#define JOYSTICK_LINUX 2
|
||||
#define JOYSTICK_KEYPAD 3
|
||||
#define JOYSTICK_WIN32_1 4
|
||||
#define JOYSTICK_WIN32_2 5
|
||||
|
||||
|
||||
#define HALT_EVENT 0x10
|
||||
|
||||
#define MAX_BREAK_POINTS 0x20
|
||||
|
||||
#define MAX_BP_INDEX 0x100
|
||||
#define MAX_BP_PER_INDEX 3 /* 4 word32s total = 16 bytes */
|
||||
#define SIZE_BREAKPT_ENTRY_BITS 4 /* 16 bytes = 4 bits */
|
||||
|
||||
/* Warning--next defines used by asm! */
|
||||
#define PAGE_INFO_PAD_SIZE 0x800
|
||||
#define PAGE_INFO_WR_OFFSET 0x10000+PAGE_INFO_PAD_SIZE
|
||||
|
||||
#define BANK_IO_BIT 31
|
||||
#define BANK_SHADOW_BIT 30
|
||||
#define BANK_SHADOW2_BIT 29
|
||||
#define BANK_IO2_BIT 28
|
||||
#define BANK_BREAK_BIT 27
|
||||
#define BANK_BREAK (1 << (31 - BANK_BREAK_BIT))
|
||||
#define BANK_IO2_TMP (1 << (31 - BANK_IO2_BIT))
|
||||
#define BANK_IO_TMP (1 << (31 - BANK_IO_BIT))
|
||||
#define BANK_SHADOW (1 << (31 - BANK_SHADOW_BIT))
|
||||
#define BANK_SHADOW2 (1 << (31 - BANK_SHADOW2_BIT))
|
||||
#define SET_BANK_IO \
|
||||
(&g_dummy_memory1_ptr[BANK_IO_TMP | BANK_IO2_TMP])
|
||||
|
||||
#define BANK_BAD_MEM (&g_dummy_memory1_ptr[0xff])
|
||||
|
||||
|
||||
#define LEN_FIFO_BUF 160
|
||||
#define LEN_KBD_BUF 160
|
||||
|
||||
#define FIFO_OK 0x1
|
||||
#define FIFO_INIT 0x2
|
||||
#define FIFO_END 0x3
|
||||
#define FIFO_40COLS 0x4
|
||||
#define FIFO_80COLS 0x5
|
||||
#define FIFO_SENDCHAR 0x6
|
||||
#define FIFO_SENDKEY 0x7
|
||||
#define FIFO_REFRESH 0x8
|
||||
|
||||
#define B_OP_SIZE 2
|
||||
#define B_OP_D_SIZE 5
|
||||
#define B_OP_DTYPE 12
|
||||
#define SIZE_OP_DTYPE 7
|
||||
|
||||
|
||||
|
||||
#define ENGINE_FCYCLES 0x00
|
||||
#define ENGINE_REG_KPC 0x08
|
||||
#define ENGINE_REG_ACC 0x0c
|
||||
#define ENGINE_REG_XREG 0x10
|
||||
#define ENGINE_REG_YREG 0x14
|
||||
#define ENGINE_REG_STACK 0x18
|
||||
#define ENGINE_REG_DBANK 0x1c
|
||||
#define ENGINE_REG_DIRECT 0x20
|
||||
#define ENGINE_REG_PSR 0x24
|
||||
#define ENGINE_FPLUS_PTR 0x28
|
||||
|
||||
#define LOG_PC_DCYCS 0x00
|
||||
#define LOG_PC_DBANK_KPC 0x08
|
||||
#define LOG_PC_INSTR 0x0c
|
||||
#define LOG_PC_PSR_ACC 0x10
|
||||
#define LOG_PC_XREG_YREG 0x14
|
||||
#define LOG_PC_STACK_DIRECT 0x18
|
||||
#define LOG_PC_PAD 0x1c
|
||||
|
||||
#define LOG_PC_SIZE 0x20
|
||||
|
||||
|
||||
#define FPLUS_PLUS_1 0x00
|
||||
#define FPLUS_PLUS_2 0x08
|
||||
#define FPLUS_PLUS_3 0x10
|
||||
#define FPLUS_PLUS_X_M1 0x18
|
||||
|
||||
#define RET_BREAK 0x1
|
||||
#define RET_COP 0x2
|
||||
#define RET_WDM 0x3
|
||||
#define RET_MVP 0x4
|
||||
#define RET_MVN 0x5
|
||||
#define RET_WAI 0x6
|
||||
#define RET_STP 0x7
|
||||
#define RET_ADD_DEC_8 0x8
|
||||
#define RET_ADD_DEC_16 0x9
|
||||
#define RET_C700 0xa
|
||||
#define RET_C70A 0xb
|
||||
#define RET_C70D 0xc
|
||||
#define RET_IRQ 0xd
|
||||
|
||||
|
||||
#define MODE_BORDER 0
|
||||
#define MODE_TEXT 1
|
||||
#define MODE_GR 2
|
||||
#define MODE_HGR 3
|
||||
#define MODE_SUPER_HIRES 4
|
||||
|
||||
#define BIT_ALL_STAT_TEXT 0
|
||||
#define BIT_ALL_STAT_VID80 1
|
||||
#define BIT_ALL_STAT_ST80 2
|
||||
#define BIT_ALL_STAT_COLOR_C021 3
|
||||
#define BIT_ALL_STAT_MIX_T_GR 4
|
||||
#define BIT_ALL_STAT_DIS_COLOR_DHIRES 5 /* special val, c029 */
|
||||
#define BIT_ALL_STAT_PAGE2 6 /* special val, statereg */
|
||||
#define BIT_ALL_STAT_SUPER_HIRES 7 /* special, c029 */
|
||||
#define BIT_ALL_STAT_HIRES 8
|
||||
#define BIT_ALL_STAT_ANNUNC3 9
|
||||
#define BIT_ALL_STAT_BG_COLOR 10 /* 4 bits */
|
||||
#define BIT_ALL_STAT_TEXT_COLOR 14 /* 4 bits */
|
||||
/* Text must be just above */
|
||||
/* bg to match c022 reg */
|
||||
#define BIT_ALL_STAT_ALTCHARSET 18
|
||||
#define BIT_ALL_STAT_FLASH_STATE 19
|
||||
#define BIT_ALL_STAT_A2VID_PALETTE 20 /* 4 bits */
|
||||
|
||||
#define ALL_STAT_SUPER_HIRES (1 << (BIT_ALL_STAT_SUPER_HIRES))
|
||||
#define ALL_STAT_TEXT (1 << (BIT_ALL_STAT_TEXT))
|
||||
#define ALL_STAT_VID80 (1 << (BIT_ALL_STAT_VID80))
|
||||
#define ALL_STAT_PAGE2 (1 << (BIT_ALL_STAT_PAGE2))
|
||||
#define ALL_STAT_ST80 (1 << (BIT_ALL_STAT_ST80))
|
||||
#define ALL_STAT_COLOR_C021 (1 << (BIT_ALL_STAT_COLOR_C021))
|
||||
#define ALL_STAT_DIS_COLOR_DHIRES (1 << (BIT_ALL_STAT_DIS_COLOR_DHIRES))
|
||||
#define ALL_STAT_MIX_T_GR (1 << (BIT_ALL_STAT_MIX_T_GR))
|
||||
#define ALL_STAT_HIRES (1 << (BIT_ALL_STAT_HIRES))
|
||||
#define ALL_STAT_ANNUNC3 (1 << (BIT_ALL_STAT_ANNUNC3))
|
||||
#define ALL_STAT_TEXT_COLOR (0xf << (BIT_ALL_STAT_TEXT_COLOR))
|
||||
#define ALL_STAT_BG_COLOR (0xf << (BIT_ALL_STAT_BG_COLOR))
|
||||
#define ALL_STAT_ALTCHARSET (1 << (BIT_ALL_STAT_ALTCHARSET))
|
||||
#define ALL_STAT_FLASH_STATE (1 << (BIT_ALL_STAT_FLASH_STATE))
|
||||
#define ALL_STAT_A2VID_PALETTE (0xf << (BIT_ALL_STAT_A2VID_PALETTE))
|
||||
|
||||
#define BORDER_WIDTH 32
|
||||
|
||||
#define EFF_BORDER_WIDTH (BORDER_WIDTH + (640-560))
|
||||
|
||||
/* BASE_MARGIN_BOTTOM+MARGIN_TOP must equal 62. There are 262 scan lines */
|
||||
/* at 60Hz (15.7KHz line rate) and so we just make 62 border lines */
|
||||
#define BASE_MARGIN_TOP 32
|
||||
#define BASE_MARGIN_BOTTOM 30
|
||||
#define BASE_MARGIN_LEFT BORDER_WIDTH
|
||||
#define BASE_MARGIN_RIGHT BORDER_WIDTH
|
||||
|
||||
#define A2_WINDOW_WIDTH 640
|
||||
#define A2_WINDOW_HEIGHT 400
|
||||
|
||||
#define X_A2_WINDOW_WIDTH (A2_WINDOW_WIDTH + BASE_MARGIN_LEFT + \
|
||||
BASE_MARGIN_RIGHT)
|
||||
#define X_A2_WINDOW_HEIGHT (A2_WINDOW_HEIGHT + BASE_MARGIN_TOP + \
|
||||
BASE_MARGIN_BOTTOM)
|
||||
|
||||
#define MAX_STATUS_LINES 7
|
||||
#define STATUS_LINE_LENGTH 88
|
||||
|
||||
#define BASE_WINDOW_WIDTH (X_A2_WINDOW_WIDTH)
|
||||
|
||||
|
||||
#define A2_BORDER_COLOR_NUM 0xfe
|
||||
|
||||
#if 0
|
||||
#define A2_TEXT_COLOR_ALT_NUM 0x01
|
||||
#define A2_BG_COLOR_ALT_NUM 0x00
|
||||
#define A2_TEXT_COLOR_PRIM_NUM 0x02
|
||||
#define A2_BG_COLOR_PRIM_NUM 0x00
|
||||
#define A2_TEXT_COLOR_FLASH_NUM 0x0c
|
||||
#define A2_BG_COLOR_FLASH_NUM 0x08
|
||||
#endif
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_S
|
||||
.data
|
||||
.export rcsdif_defs_h,data
|
||||
rcsdif_defs_h
|
||||
.stringz "@(#)$KmKId: defs.h,v 1.22 2002-11-19 03:10:38-05 kadickey Exp $"
|
||||
.code
|
||||
#endif
|
||||
|
||||
#include "defcomm.h"
|
||||
|
||||
link .reg %r2
|
||||
acc .reg %r3
|
||||
xreg .reg %r4
|
||||
yreg .reg %r5
|
||||
stack .reg %r6
|
||||
dbank .reg %r7
|
||||
direct .reg %r8
|
||||
neg .reg %r9
|
||||
zero .reg %r10
|
||||
psr .reg %r11
|
||||
kpc .reg %r12
|
||||
const_fd .reg %r13
|
||||
instr .reg %r14
|
||||
#if 0
|
||||
cycles .reg %r13
|
||||
kbank .reg %r14
|
||||
#endif
|
||||
|
||||
page_info_ptr .reg %r15
|
||||
inst_tab_ptr .reg %r16
|
||||
fcycles_stop_ptr .reg %r17
|
||||
addr_latch .reg %r18
|
||||
|
||||
scratch1 .reg %r19
|
||||
scratch2 .reg %r20
|
||||
scratch3 .reg %r21
|
||||
scratch4 .reg %r22
|
||||
;instr .reg %r23 ; arg3
|
||||
|
||||
fcycles .reg %fr12
|
||||
fr_plus_1 .reg %fr13
|
||||
fr_plus_2 .reg %fr14
|
||||
fr_plus_3 .reg %fr15
|
||||
fr_plus_x_m1 .reg %fr16
|
||||
fcycles_stop .reg %fr17
|
||||
fcycles_last_dcycs .reg %fr18
|
||||
|
||||
ftmp1 .reg %fr4
|
||||
ftmp2 .reg %fr5
|
||||
fscr1 .reg %fr6
|
||||
|
||||
#define LDC(val,reg) ldil L%val,reg ! ldo R%val(reg),reg
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,210 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_disas_h[] = "@(#)$KmKId: disas.h,v 1.10 2002-11-19 03:10:38-05 kadickey Exp $";
|
||||
|
||||
enum {
|
||||
ABS = 1,
|
||||
ABSX,
|
||||
ABSY,
|
||||
ABSLONG,
|
||||
ABSIND,
|
||||
ABSXIND,
|
||||
IMPLY,
|
||||
ACCUM,
|
||||
IMMED,
|
||||
JUST8,
|
||||
DLOC,
|
||||
DLOCX,
|
||||
DLOCY,
|
||||
LONG,
|
||||
LONGX,
|
||||
DLOCIND,
|
||||
DLOCINDY,
|
||||
DLOCXIND,
|
||||
DLOCBRAK,
|
||||
DLOCBRAKY,
|
||||
DISP8,
|
||||
DISP8S,
|
||||
DISP8SINDY,
|
||||
DISP16,
|
||||
MVPMVN,
|
||||
REPVAL,
|
||||
SEPVAL
|
||||
};
|
||||
|
||||
|
||||
const char * const disas_opcodes[256] = {
|
||||
"BRK", "ORA", "COP", "ORA", "TSB", "ORA", "ASL", "ORA", /* 00-07 */
|
||||
"PHP", "ORA", "ASL", "PHD", "TSB", "ORA", "ASL", "ORA", /* 08-0f */
|
||||
"BPL", "ORA", "ORA", "ORA", "TRB", "ORA", "ASL", "ORA", /* 10-17 */
|
||||
"CLC", "ORA", "INC", "TCS", "TRB", "ORA", "ASL", "ORA", /* 18-1f */
|
||||
"JSR", "AND", "JSL", "AND", "BIT", "AND", "ROL", "AND", /* 20-27 */
|
||||
"PLP", "AND", "ROL", "PLD", "BIT", "AND", "ROL", "AND", /* 28-2f */
|
||||
"BMI", "AND", "AND", "AND", "BIT", "AND", "ROL", "AND", /* 30-37 */
|
||||
"SEC", "AND", "DEC", "TSC", "BIT", "AND", "ROL", "AND", /* 38-3f */
|
||||
"RTI", "EOR", "WDM", "EOR", "MVP", "EOR", "LSR", "EOR", /* 40-47 */
|
||||
"PHA", "EOR", "LSR", "PHK", "JMP", "EOR", "LSR", "EOR", /* 48-4f */
|
||||
"BVC", "EOR", "EOR", "EOR", "MVN", "EOR", "LSR", "EOR", /* 50-57 */
|
||||
"CLI", "EOR", "PHY", "TCD", "JMP", "EOR", "LSR", "EOR", /* 58-5f */
|
||||
"RTS", "ADC", "PER", "ADC", "STZ", "ADC", "ROR", "ADC", /* 60-67 */
|
||||
"PLA", "ADC", "ROR", "RTL", "JMP", "ADC", "ROR", "ADC", /* 68-6f */
|
||||
"BVS", "ADC", "ADC", "ADC", "STZ", "ADC", "ROR", "ADC", /* 70-77 */
|
||||
"SEI", "ADC", "PLY", "TDC", "JMP", "ADC", "ROR", "ADC", /* 78-7f */
|
||||
"BRA", "STA", "BRL", "STA", "STY", "STA", "STX", "STA", /* 80-87 */
|
||||
"DEY", "BIT", "TXA", "PHB", "STY", "STA", "STX", "STA", /* 88-8f */
|
||||
"BCC", "STA", "STA", "STA", "STY", "STA", "STX", "STA", /* 90-97 */
|
||||
"TYA", "STA", "TXS", "TXY", "STZ", "STA", "STZ", "STA", /* 98-9f */
|
||||
"LDY", "LDA", "LDX", "LDA", "LDY", "LDA", "LDX", "LDA", /* a0-a7 */
|
||||
"TAY", "LDA", "TAX", "PLB", "LDY", "LDA", "LDX", "LDA", /* a8-af */
|
||||
"BCS", "LDA", "LDA", "LDA", "LDY", "LDA", "LDX", "LDA", /* b0-b7 */
|
||||
"CLV", "LDA", "TSX", "TYX", "LDY", "LDA", "LDX", "LDA", /* b8-bf */
|
||||
"CPY", "CMP", "REP", "CMP", "CPY", "CMP", "DEC", "CMP", /* c0-c7 */
|
||||
"INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "CMP", /* c8-cf */
|
||||
"BNE", "CMP", "CMP", "CMP", "PEI", "CMP", "DEC", "CMP", /* d0-d7 */
|
||||
"CLD", "CMP", "PHX", "STP", "JML", "CMP", "DEC", "CMP", /* d8-df */
|
||||
"CPX", "SBC", "SEP", "SBC", "CPX", "SBC", "INC", "SBC", /* e0-e7 */
|
||||
"INX", "SBC", "NOP", "XBA", "CPX", "SBC", "INC", "SBC", /* e8-ef */
|
||||
"BEQ", "SBC", "SBC", "SBC", "PEA", "SBC", "INC", "SBC", /* f0-f7 */
|
||||
"SED", "SBC", "PLX", "XCE", "JSR", "SBC", "INC", "SBC", /* f8-ff */
|
||||
};
|
||||
|
||||
|
||||
const word32 disas_types[256] = {
|
||||
JUST8+0x100, DLOCXIND+0x100, /* 00-01 */
|
||||
JUST8+0x100, DISP8S+0x100, /* 02-03 */
|
||||
DLOC+0x100, DLOC+0x100, /* 04-05 */
|
||||
DLOC+0x100, DLOCBRAK+0x100, /* 06-07 */
|
||||
IMPLY+0x000, IMMED+0x400, /* 08-9 */
|
||||
ACCUM+0x000, IMPLY+0x000, /* 0a-b */
|
||||
ABS+0x200, ABS+0x200, /* c-d */
|
||||
ABS+0x200, LONG+0x300, /* e-f */
|
||||
DISP8+0x100, DLOCINDY+0x100, /* 10-11 */
|
||||
DLOCIND+0x100, DISP8SINDY+0x100, /* 12-13 */
|
||||
DLOC+0x100, DLOCX+0x100, /* 14-15 */
|
||||
DLOCX+0x100, DLOCBRAKY+0x100, /* 16-17 */
|
||||
IMPLY+0x000, ABSY+0x200, /* 18-19 */
|
||||
ACCUM+0x000, IMPLY+0x000, /* 1a-1b */
|
||||
ABS+0x200, ABSX+0x200, /* 1c-1d */
|
||||
ABSX+0x200, LONGX+0x300, /* 1e-1f */
|
||||
ABS+0x200, DLOCXIND+0x100, /* 20-21 */
|
||||
ABSLONG+0x300, DISP8S+0x100, /* 22-23 */
|
||||
DLOC+0x100, DLOC+0x100, /* 24-25 */
|
||||
DLOC+0x100, DLOCBRAK+0x100, /* 26-27 */
|
||||
IMPLY+0x000, IMMED+0x400, /* 28-29 */
|
||||
ACCUM+0x000, IMPLY+0x000, /* 2a-2b */
|
||||
ABS+0x200, ABS+0x200, /* 2c-2d */
|
||||
ABS+0x200, LONG+0x300, /* 2e-2f */
|
||||
DISP8+0x100, DLOCINDY+0x100, /* 30-31 */
|
||||
DLOCIND+0x100, DISP8SINDY+0x100, /* 32-33 */
|
||||
DLOCX+0x100, DLOCX+0x100, /* 34-35 */
|
||||
DLOCX+0x100, DLOCBRAKY+0x100, /* 36-37 */
|
||||
IMPLY+0x000, ABSY+0x200, /* 38-39 */
|
||||
ACCUM+0x000, IMPLY+0x000, /* 3a-3b */
|
||||
ABSX+0x200, ABSX+0x200, /* 3c-3d */
|
||||
ABSX+0x200, LONGX+0x300, /* 3e-3f */
|
||||
IMPLY+0x000, DLOCXIND+0x100, /* 40-41 */
|
||||
JUST8+0x100, DISP8S+0x100, /* 42-43 */
|
||||
MVPMVN+0x200, DLOC+0x100, /* 44-45 */
|
||||
DLOC+0x100, DLOCBRAK+0x100, /* 46-47 */
|
||||
IMPLY+0x000, IMMED+0x400, /* 48-49 */
|
||||
ACCUM+0x000, IMPLY+0x000, /* 4a-4b */
|
||||
ABS+0x200, ABS+0x200, /* 4c-4d */
|
||||
ABS+0x200, LONG+0x300, /* 4e-4f */
|
||||
DISP8+0x100, DLOCINDY+0x100, /* 50-51 */
|
||||
DLOCIND+0x100, DISP8SINDY+0x100, /* 52-53 */
|
||||
MVPMVN+0x200, DLOCX+0x100, /* 54-55 */
|
||||
DLOCX+0x100, DLOCBRAKY+0x100, /* 56-57 */
|
||||
IMPLY+0x000, ABSY+0x200, /* 58-59 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* 5a-5b */
|
||||
LONG+0x300, ABSX+0x200, /* 5c-5d */
|
||||
ABSX+0x200, LONGX+0x300, /* 5e-5f */
|
||||
IMPLY+0x000, DLOCXIND+0x100, /* 60-61 */
|
||||
DISP16+0x200, DISP8S+0x100, /* 62-63 */
|
||||
DLOC+0x100, DLOC+0x100, /* 64-65 */
|
||||
DLOC+0x100, DLOCBRAK+0x100, /* 66-67 */
|
||||
IMPLY+0x000, IMMED+0x400, /* 68-69 */
|
||||
ACCUM+0x000, IMPLY+0x000, /* 6a-6b */
|
||||
ABSIND+0x200, ABS+0x200, /* 6c-6d */
|
||||
ABS+0x200, LONG+0x300, /* 6e-6f */
|
||||
DISP8+0x100, DLOCINDY+0x100, /* 70-71 */
|
||||
DLOCIND+0x100, DISP8SINDY+0x100, /* 72-73 */
|
||||
DLOCX+0x100, DLOCX+0x100, /* 74-75 */
|
||||
DLOCX+0x100, DLOCBRAKY+0x100, /* 76-77 */
|
||||
IMPLY+0x000, ABSY+0x200, /* 78-79 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* 7a-7b */
|
||||
ABSXIND+0x200, ABSX+0x200, /* 7c-7d */
|
||||
ABSX+0x200, LONGX+0x300, /* 7e-7f */
|
||||
DISP8+0x100, DLOCXIND+0x100, /* 80-81 */
|
||||
DISP16+0x200, DISP8S+0x100, /* 82-83 */
|
||||
DLOC+0x100, DLOC+0x100, /* 84-85 */
|
||||
DLOC+0x100, DLOCBRAK+0x100, /* 86-87 */
|
||||
IMPLY+0x000, IMMED+0x400, /* 88-89 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* 8a-8b */
|
||||
ABS+0x200, ABS+0x200, /* 8c-8d */
|
||||
ABS+0x200, LONG+0x300, /* 8e-8f */
|
||||
DISP8+0x100, DLOCINDY+0x100, /* 90-91 */
|
||||
DLOCIND+0x100, DISP8SINDY+0x100, /* 92-93 */
|
||||
DLOCX+0x100, DLOCX+0x100, /* 94-95 */
|
||||
DLOCY+0x100, DLOCBRAKY+0x100, /* 96-97 */
|
||||
IMPLY+0x000, ABSY+0x200, /* 98-99 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* 9a-9b */
|
||||
ABS+0x200, ABSX+0x200, /* 9c-9d */
|
||||
ABSX+0x200, LONGX+0x300, /* 9e-9f */
|
||||
IMMED+0x500, DLOCXIND+0x100, /* a0-a1 */
|
||||
IMMED+0x500, DISP8S+0x100, /* a2-a3 */
|
||||
DLOC+0x100, DLOC+0x100, /* a4-a5 */
|
||||
DLOC+0x100, DLOCBRAK+0x100, /* a6-a7 */
|
||||
IMPLY+0x000, IMMED+0x400, /* a8-a9 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* aa-ab */
|
||||
ABS+0x200, ABS+0x200, /* ac-ad */
|
||||
ABS+0x200, LONG+0x300, /* ae-af */
|
||||
DISP8+0x100, DLOCINDY+0x100, /* b0-b1 */
|
||||
DLOCIND+0x100, DISP8SINDY+0x100, /* b2-b3 */
|
||||
DLOCX+0x100, DLOCX+0x100, /* b4-b5 */
|
||||
DLOCY+0x100, DLOCBRAKY+0x100, /* b6-b7 */
|
||||
IMPLY+0x000, ABSY+0x200, /* b8-b9 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* ba-bb */
|
||||
ABSX+0x200, ABSX+0x200, /* bc-bd */
|
||||
ABSY+0x200, LONGX+0x300, /* be-bf */
|
||||
IMMED+0x500, DLOCXIND+0x100, /* c0-c1 */
|
||||
REPVAL+0x100, DISP8S+0x100, /* c2-c3 */
|
||||
DLOC+0x100, DLOC+0x100, /* c4-c5 */
|
||||
DLOC+0x100, DLOCBRAK+0x100, /* c6-c7 */
|
||||
IMPLY+0x000, IMMED+0x400, /* c8-c9 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* ca-cb */
|
||||
ABS+0x200, ABS+0x200, /* cc-cd */
|
||||
ABS+0x200, LONG+0x300, /* ce-cf */
|
||||
DISP8+0x100, DLOCINDY+0x100, /* d0-d1 */
|
||||
DLOCIND+0x100, DISP8SINDY+0x100, /* d2-d3 */
|
||||
DLOC+0x100, DLOCX+0x100, /* d4-d5 */
|
||||
DLOCX+0x100, DLOCBRAKY+0x100, /* d6-d7 */
|
||||
IMPLY+0x000, ABSY+0x200, /* d8-d9 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* da-db */
|
||||
ABSIND+0x200, ABSX+0x200, /* dc-dd */
|
||||
ABSX+0x200, LONGX+0x300, /* de-df */
|
||||
IMMED+0x500, DLOCXIND+0x100, /* e0-e1 */
|
||||
SEPVAL+0x100, DISP8S+0x100, /* e2-e3 */
|
||||
DLOC+0x100, DLOC+0x100, /* e4-e5 */
|
||||
DLOC+0x100, DLOCBRAK+0x100, /* e6-e7 */
|
||||
IMPLY+0x000, IMMED+0x400, /* e8-e9 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* ea-eb */
|
||||
ABS+0x200, ABS+0x200, /* ec-ed */
|
||||
ABS+0x200, LONG+0x300, /* ee-ef */
|
||||
DISP8+0x100, DLOCINDY+0x100, /* f0-f1 */
|
||||
DLOCIND+0x100, DISP8SINDY+0x100, /* f2-f3 */
|
||||
IMMED+0x200, DLOCX+0x100, /* f4-f5 */
|
||||
DLOCX+0x100, DLOCBRAKY+0x100, /* f6-f7 */
|
||||
IMPLY+0x000, ABSY+0x200, /* f8-f9 */
|
||||
IMPLY+0x000, IMPLY+0x000, /* fa-fb */
|
||||
ABSXIND+0x200, ABSX+0x200, /* fc-fd */
|
||||
ABSX+0x200, LONGX+0x300, /* fe-ff */
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>152 85 356 240 0 0 1280 832 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>29</key>
|
||||
<string>69 252 182 44 0 0 1280 832 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>291.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6R73</string>
|
||||
<key>targetFramework</key>
|
||||
<string>IBCarbonFramework</string>
|
||||
</dict>
|
||||
</plist>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,116 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_C
|
||||
const char rcsid_iwm_h[] = "@(#)$KmKId: iwm.h,v 1.13 2003-07-08 23:29:48-04 kentd Exp $";
|
||||
#endif
|
||||
|
||||
#define MAX_TRACKS (2*80)
|
||||
#define MAX_C7_DISKS 32
|
||||
|
||||
#define NIB_LEN_525 0x1900 /* 51072 bits per track */
|
||||
#define NIBS_FROM_ADDR_TO_DATA 20
|
||||
|
||||
#define DSK_TYPE_PRODOS 0
|
||||
#define DSK_TYPE_DOS33 1
|
||||
#define DSK_TYPE_NIB 2
|
||||
|
||||
typedef struct _Disk Disk;
|
||||
|
||||
STRUCT(Track) {
|
||||
Disk *dsk;
|
||||
byte *nib_area;
|
||||
int track_dirty;
|
||||
int overflow_size;
|
||||
int track_len;
|
||||
int unix_pos;
|
||||
int unix_len;
|
||||
};
|
||||
|
||||
struct _Disk {
|
||||
double dcycs_last_read;
|
||||
char *name_ptr;
|
||||
char *partition_name;
|
||||
int partition_num;
|
||||
int fd;
|
||||
int force_size;
|
||||
int image_start;
|
||||
int image_size;
|
||||
int smartport;
|
||||
int disk_525;
|
||||
int drive;
|
||||
int cur_qtr_track;
|
||||
int image_type;
|
||||
int vol_num;
|
||||
int write_prot;
|
||||
int write_through_to_unix;
|
||||
int disk_dirty;
|
||||
int just_ejected;
|
||||
int last_phase;
|
||||
int nib_pos;
|
||||
int num_tracks;
|
||||
Track tracks[MAX_TRACKS];
|
||||
};
|
||||
|
||||
|
||||
STRUCT(Iwm) {
|
||||
Disk drive525[2];
|
||||
Disk drive35[2];
|
||||
Disk smartport[MAX_C7_DISKS];
|
||||
int motor_on;
|
||||
int motor_off;
|
||||
int motor_off_vbl_count;
|
||||
int motor_on35;
|
||||
int head35;
|
||||
int step_direction35;
|
||||
int iwm_phase[4];
|
||||
int iwm_mode;
|
||||
int drive_select;
|
||||
int q6;
|
||||
int q7;
|
||||
int enable2;
|
||||
int reset;
|
||||
|
||||
word32 previous_write_val;
|
||||
int previous_write_bits;
|
||||
};
|
||||
|
||||
|
||||
STRUCT(Driver_desc) {
|
||||
word16 sig;
|
||||
word16 blk_size;
|
||||
word32 blk_count;
|
||||
word16 dev_type;
|
||||
word16 dev_id;
|
||||
word32 data;
|
||||
word16 drvr_count;
|
||||
};
|
||||
|
||||
STRUCT(Part_map) {
|
||||
word16 sig;
|
||||
word16 sigpad;
|
||||
word32 map_blk_cnt;
|
||||
word32 phys_part_start;
|
||||
word32 part_blk_cnt;
|
||||
char part_name[32];
|
||||
char part_type[32];
|
||||
word32 data_start;
|
||||
word32 data_cnt;
|
||||
word32 part_status;
|
||||
word32 log_boot_start;
|
||||
word32 boot_size;
|
||||
word32 boot_load;
|
||||
word32 boot_load2;
|
||||
word32 boot_entry;
|
||||
word32 boot_entry2;
|
||||
word32 boot_cksum;
|
||||
char processor[16];
|
||||
char junk[128];
|
||||
};
|
|
@ -0,0 +1,310 @@
|
|||
|
||||
#ifdef INCLUDE_IWM_RCSID_C
|
||||
const char rcsdif_iwm_35_525_h[] = "@(#)$KmKId: iwm_35_525.h,v 1.9 2002-11-14 01:03:16-05 kadickey Exp $";
|
||||
#endif
|
||||
|
||||
int
|
||||
IWM_READ_ROUT (Disk *dsk, int fast_disk_emul, double dcycs)
|
||||
{
|
||||
Track *trk;
|
||||
double dcycs_last_read;
|
||||
int pos;
|
||||
int pos2;
|
||||
int size;
|
||||
int next_size;
|
||||
int qtr_track;
|
||||
int skip_nibs;
|
||||
int track_len;
|
||||
byte ret;
|
||||
int shift;
|
||||
int skip;
|
||||
int cycs_this_nib;
|
||||
int cycs_passed;
|
||||
double dcycs_this_nib;
|
||||
double dcycs_next_nib;
|
||||
double dcycs_passed;
|
||||
double track_dcycs;
|
||||
double dtmp;
|
||||
|
||||
iwm.previous_write_bits = 0;
|
||||
|
||||
qtr_track = dsk->cur_qtr_track;
|
||||
|
||||
trk = &(dsk->tracks[qtr_track]);
|
||||
track_len = trk->track_len;
|
||||
|
||||
dcycs_last_read = dsk->dcycs_last_read;
|
||||
dcycs_passed = dcycs - dcycs_last_read;
|
||||
|
||||
pos = dsk->nib_pos;
|
||||
if(pos >= track_len) {
|
||||
/* Arm may have moved from inner 3.5 track to outer one, */
|
||||
/* and so must make pos fit on smaller sized track */
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
cycs_passed = (int)dcycs_passed;
|
||||
|
||||
if(track_len == 0) {
|
||||
return (cycs_passed & 0x7f) + 0x80;
|
||||
}
|
||||
size = trk->nib_area[pos];
|
||||
|
||||
while(size == 0) {
|
||||
pos += 2;
|
||||
if(pos >= track_len) {
|
||||
pos = 0;
|
||||
}
|
||||
size = trk->nib_area[pos];
|
||||
}
|
||||
|
||||
cycs_this_nib = size * (2 * IWM_CYC_MULT);
|
||||
dcycs_this_nib = (double)cycs_this_nib;
|
||||
|
||||
if(fast_disk_emul) {
|
||||
cycs_passed = cycs_this_nib;
|
||||
dcycs_passed = dcycs_this_nib;
|
||||
|
||||
/* pull a trick to make disk motor-on test pass ($bd34 RWTS) */
|
||||
/* if this would be a sync byte, and we didn't just do this */
|
||||
/* then don't return whole byte */
|
||||
/* BUT, don't do this if g_fast_disk_unnib, since it will */
|
||||
/* cause the dsk->unix routines to break */
|
||||
if(size > 8 && !g_fast_disk_unnib && (g_iwm_fake_fast == 0)) {
|
||||
cycs_passed = cycs_passed >> 1;
|
||||
dcycs_passed = dcycs_passed * 0.5;
|
||||
g_iwm_fake_fast = 1;
|
||||
} else {
|
||||
g_iwm_fake_fast = 0;
|
||||
}
|
||||
}
|
||||
|
||||
skip = 0;
|
||||
if(cycs_passed >= (cycs_this_nib + 11)) {
|
||||
/* skip some bits? */
|
||||
skip = 1;
|
||||
if(iwm.iwm_mode & 1) {
|
||||
/* latch mode */
|
||||
|
||||
pos2 = pos + 2;
|
||||
if(pos2 >= track_len) {
|
||||
pos2 = 0;
|
||||
}
|
||||
next_size = trk->nib_area[pos2];
|
||||
while(next_size == 0) {
|
||||
pos2 += 2;
|
||||
if(pos2 >= track_len) {
|
||||
pos2 = 0;
|
||||
}
|
||||
next_size = trk->nib_area[pos2];
|
||||
}
|
||||
|
||||
dcycs_next_nib = next_size * (2 * IWM_CYC_MULT);
|
||||
|
||||
if(dcycs_passed < (dcycs_this_nib + dcycs_next_nib)) {
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(skip) {
|
||||
iwm_printf("skip since cycs_passed: %f, cycs_this_nib: %f\n",
|
||||
dcycs_passed, dcycs_this_nib);
|
||||
|
||||
track_dcycs = IWM_CYC_MULT * (track_len * 8);
|
||||
|
||||
if(dcycs_passed >= track_dcycs) {
|
||||
dtmp = (int)(dcycs_passed / track_dcycs);
|
||||
dcycs_passed = dcycs_passed -
|
||||
(dtmp * track_dcycs);
|
||||
dcycs_last_read += (dtmp * track_dcycs);
|
||||
}
|
||||
|
||||
if(dcycs_passed >= track_dcycs || dcycs_passed < 0.0) {
|
||||
dcycs_passed = 0.0;
|
||||
}
|
||||
|
||||
cycs_passed = (int)dcycs_passed;
|
||||
|
||||
skip_nibs = ((word32)cycs_passed) >> (4 + IWM_DISK_525);
|
||||
|
||||
pos += skip_nibs * 2;
|
||||
while(pos >= track_len) {
|
||||
pos -= track_len;
|
||||
}
|
||||
|
||||
dcycs_last_read += (skip_nibs * 16 * IWM_CYC_MULT);
|
||||
|
||||
dsk->dcycs_last_read = dcycs_last_read;
|
||||
|
||||
size = trk->nib_area[pos];
|
||||
dcycs_passed = dcycs - dcycs_last_read;
|
||||
if(dcycs_passed < 0.0 || dcycs_passed > 64.0) {
|
||||
halt_printf("skip, last_read:%f, dcycs:%f, dcyc_p:%f\n",
|
||||
dcycs_last_read, dcycs, dcycs_passed);
|
||||
}
|
||||
|
||||
while(size == 0) {
|
||||
pos += 2;
|
||||
if(pos >= track_len) {
|
||||
pos = 0;
|
||||
}
|
||||
size = trk->nib_area[pos];
|
||||
}
|
||||
|
||||
cycs_this_nib = size * (2 * IWM_CYC_MULT);
|
||||
cycs_passed = (int)dcycs_passed;
|
||||
dcycs_this_nib = cycs_this_nib;
|
||||
}
|
||||
|
||||
if(cycs_passed < cycs_this_nib) {
|
||||
/* partial */
|
||||
#if 0
|
||||
iwm_printf("Disk partial, %f < %f, size: %d\n",
|
||||
dcycs_passed, dcycs_this_nib, size);
|
||||
#endif
|
||||
shift = (cycs_passed) >> (1 + IWM_DISK_525);
|
||||
ret = trk->nib_area[pos+1] >> (size - shift);
|
||||
if(ret & 0x80) {
|
||||
halt_printf("Bad shift in partial read: %02x, but "
|
||||
"c_pass:%f, this_nib:%f, shift: %d, size: %d\n",
|
||||
ret, dcycs_passed, dcycs_this_nib, shift, size);
|
||||
}
|
||||
} else {
|
||||
/* whole thing */
|
||||
ret = trk->nib_area[pos+1];
|
||||
pos += 2;
|
||||
if(pos >= track_len) {
|
||||
pos = 0;
|
||||
}
|
||||
if(!fast_disk_emul) {
|
||||
dsk->dcycs_last_read = dcycs_last_read + dcycs_this_nib;
|
||||
}
|
||||
}
|
||||
|
||||
dsk->nib_pos = pos;
|
||||
if(pos < 0 || pos > track_len) {
|
||||
halt_printf("I just set nib_pos: %d!\n", pos);
|
||||
}
|
||||
|
||||
#if 0
|
||||
iwm_printf("Disk read, returning: %02x\n", ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
IWM_WRITE_ROUT (Disk *dsk, word32 val, int fast_disk_emul, double dcycs)
|
||||
{
|
||||
double dcycs_last_read;
|
||||
word32 bits_read;
|
||||
word32 mask;
|
||||
word32 prev_val;
|
||||
double dcycs_this_nib;
|
||||
double dcycs_passed;
|
||||
int sdiff;
|
||||
int prev_bits;
|
||||
|
||||
if(dsk->fd < 0) {
|
||||
halt_printf("Tried to write to type: %d, drive: %d, fd: %d!\n",
|
||||
IWM_DISK_525, dsk->drive, dsk->fd);
|
||||
return;
|
||||
}
|
||||
|
||||
dcycs_last_read = dsk->dcycs_last_read;
|
||||
|
||||
dcycs_passed = dcycs - dcycs_last_read;
|
||||
|
||||
prev_val = iwm.previous_write_val;
|
||||
prev_bits = iwm.previous_write_bits;
|
||||
mask = 0x100;
|
||||
iwm_printf("Iwm write: prev: %x,%d, new:%02x\n", prev_val, prev_bits,
|
||||
val);
|
||||
|
||||
if(IWM_DISK_525) {
|
||||
/* Activate slow write emulation mode */
|
||||
g_dcycs_end_emul_wr = dcycs + 64.0;
|
||||
if(!g_slow_525_emul_wr) {
|
||||
set_halt(HALT_EVENT);
|
||||
g_slow_525_emul_wr = 1;
|
||||
}
|
||||
} else {
|
||||
/* disable slow writes on 3.5" drives */
|
||||
if(g_slow_525_emul_wr) {
|
||||
set_halt(HALT_EVENT);
|
||||
printf("HACK3: g_slow_525_emul_wr set to 0\n");
|
||||
g_slow_525_emul_wr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(iwm.iwm_mode & 2) {
|
||||
/* async mode = 3.5" default */
|
||||
bits_read = 8;
|
||||
} else {
|
||||
/* sync mode, 5.25" drives */
|
||||
bits_read = ((int)dcycs_passed) >> (1 + IWM_DISK_525);
|
||||
if(bits_read < 8) {
|
||||
bits_read = 8;
|
||||
}
|
||||
}
|
||||
|
||||
if(fast_disk_emul) {
|
||||
bits_read = 8;
|
||||
}
|
||||
|
||||
dcycs_this_nib = bits_read * (2 * IWM_CYC_MULT);
|
||||
|
||||
if(fast_disk_emul) {
|
||||
dcycs_passed = dcycs_this_nib;
|
||||
}
|
||||
|
||||
if(prev_bits > 0) {
|
||||
while((prev_val & 0x80) == 0 && bits_read > 0) {
|
||||
/* previous byte needs some bits */
|
||||
mask = mask >> 1;
|
||||
prev_val = (prev_val << 1) + ((val & mask) !=0);
|
||||
prev_bits++;
|
||||
bits_read--;
|
||||
}
|
||||
}
|
||||
|
||||
val = val & (mask - 1);
|
||||
if(prev_bits) {
|
||||
/* force out prev_val if it had many bits before */
|
||||
/* this prevents writes of 0 from messing us up */
|
||||
if(((prev_val & 0x80) == 0) && (prev_bits < 10)) {
|
||||
/* special case: we still don't have enough to go */
|
||||
iwm_printf("iwm_write: zip2: %02x, %d, left:%02x,%d\n",
|
||||
prev_val, prev_bits, val,bits_read);
|
||||
val = prev_val;
|
||||
bits_read = prev_bits;
|
||||
} else {
|
||||
iwm_printf("iwm_write: prev: %02x, %d, left:%02x, %d\n",
|
||||
prev_val, prev_bits, val, bits_read);
|
||||
disk_nib_out(dsk, prev_val, prev_bits);
|
||||
}
|
||||
} else if(val & 0x80) {
|
||||
iwm_printf("iwm_write: new: %02x, %d\n", val,bits_read);
|
||||
disk_nib_out(dsk, val, bits_read);
|
||||
bits_read = 0;
|
||||
} else {
|
||||
iwm_printf("iwm_write: zip: %02x, %d, left:%02x,%d\n",
|
||||
prev_val, prev_bits, val,bits_read);
|
||||
}
|
||||
|
||||
iwm.previous_write_val = val;
|
||||
iwm.previous_write_bits = bits_read;
|
||||
if(bits_read < 0) {
|
||||
halt_printf("iwm, bits_rd:%d, val:%08x, prev:%02x, prevb:%d\n",
|
||||
bits_read, val, prev_val, prev_bits);
|
||||
}
|
||||
|
||||
sdiff = dcycs - dcycs_last_read;
|
||||
if(sdiff < (dcycs_this_nib) || (sdiff > (2*dcycs_this_nib)) ) {
|
||||
dsk->dcycs_last_read = dcycs;
|
||||
} else {
|
||||
dsk->dcycs_last_read = dcycs_last_read + dcycs_this_nib;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_joystick_driver_c[] = "@(#)$KmKId: joystick_driver.c,v 1.7 2002-11-19 03:09:59-05 kadickey Exp $";
|
||||
|
||||
#include "defc.h"
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef __linux__
|
||||
# include <linux/joystick.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
# include <mmsystem.h>
|
||||
#endif
|
||||
|
||||
extern int g_joystick_type; /* in paddles.c */
|
||||
extern int g_paddle_button[];
|
||||
extern int g_paddle_val[];
|
||||
|
||||
|
||||
const char *g_joystick_dev = "/dev/js0"; /* default joystick dev file */
|
||||
#define MAX_JOY_NAME 128
|
||||
|
||||
int g_joystick_fd = -1;
|
||||
int g_joystick_num_axes = 0;
|
||||
int g_joystick_num_buttons = 0;
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
void
|
||||
joystick_init()
|
||||
{
|
||||
char joy_name[MAX_JOY_NAME];
|
||||
int version;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
fd = open(g_joystick_dev, O_RDONLY | O_NONBLOCK);
|
||||
if(fd < 0) {
|
||||
printf("Unable to open joystick dev file: %s, errno: %d\n",
|
||||
g_joystick_dev, errno);
|
||||
printf("Defaulting to mouse joystick\n");
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(&joy_name[0], "Unknown Joystick");
|
||||
version = 0x800;
|
||||
|
||||
ioctl(fd, JSIOCGNAME(MAX_JOY_NAME), &joy_name[0]);
|
||||
ioctl(fd, JSIOCGAXES, &g_joystick_num_axes);
|
||||
ioctl(fd, JSIOCGBUTTONS, &g_joystick_num_buttons);
|
||||
ioctl(fd, JSIOCGVERSION, &version);
|
||||
|
||||
printf("Detected joystick: %s [%d axes, %d buttons vers: %08x]\n",
|
||||
joy_name, g_joystick_num_axes, g_joystick_num_buttons,
|
||||
version);
|
||||
|
||||
g_joystick_type = JOYSTICK_LINUX;
|
||||
g_joystick_fd = fd;
|
||||
for(i = 0; i < 4; i++) {
|
||||
g_paddle_val[i] = 280;
|
||||
g_paddle_button[i] = 1;
|
||||
}
|
||||
|
||||
joystick_update();
|
||||
}
|
||||
|
||||
/* joystick_update_linux() called from paddles.c. Update g_paddle_val[] */
|
||||
/* and g_paddle_button[] arrays with current information */
|
||||
void
|
||||
joystick_update()
|
||||
{
|
||||
struct js_event js; /* the linux joystick event record */
|
||||
int val;
|
||||
int num;
|
||||
int type;
|
||||
int ret;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
/* suck up to 20 events, then give up */
|
||||
len = sizeof(struct js_event);
|
||||
for(i = 0; i < 20; i++) {
|
||||
ret = read(g_joystick_fd, &js, len);
|
||||
if(ret != len) {
|
||||
/* just get out */
|
||||
return;
|
||||
}
|
||||
type = js.type & ~JS_EVENT_INIT;
|
||||
val = js.value;
|
||||
num = js.number & 3; /* clamp to 0-3 */
|
||||
switch(type) {
|
||||
case JS_EVENT_BUTTON:
|
||||
g_paddle_button[num] = val;
|
||||
break;
|
||||
case JS_EVENT_AXIS:
|
||||
/* val is -32767 to +32767, convert to 0->280 */
|
||||
/* want just 255, but go a little over for robustness*/
|
||||
g_paddle_val[num] = ((val + 32767) * 9) >> 11;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update_button()
|
||||
{
|
||||
}
|
||||
|
||||
#else /* !__linux__ */
|
||||
|
||||
# ifdef _WIN32
|
||||
void
|
||||
joystick_init()
|
||||
{
|
||||
JOYINFO info;
|
||||
JOYCAPS joycap;
|
||||
MMRESULT ret1, ret2;
|
||||
int i;
|
||||
|
||||
// Check that there is a joystick device
|
||||
if(joyGetNumDevs() <= 0) {
|
||||
printf("--No joystick hardware detected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that at least joystick 1 or joystick 2 is available
|
||||
ret1 = joyGetPos(JOYSTICKID1, &info);
|
||||
ret2 = joyGetDevCaps(JOYSTICKID1, &joycap, sizeof(joycap));
|
||||
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
|
||||
g_joystick_type = JOYSTICK_WIN32_1;
|
||||
printf("--Joystick #1 = %s\n", joycap.szPname);
|
||||
} else {
|
||||
ret1 = joyGetPos(JOYSTICKID2, &info);
|
||||
ret2 = joyGetDevCaps(JOYSTICKID2, &joycap, sizeof(joycap));
|
||||
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
|
||||
g_joystick_type = JOYSTICK_WIN32_2;
|
||||
printf("--Joystick #2 = %s\n", joycap.szPname);
|
||||
} else {
|
||||
printf("No joysticks found...\n");
|
||||
g_joystick_type = JOYSTICK_MOUSE;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
g_paddle_val[i] = 280;
|
||||
g_paddle_button[i] = 1;
|
||||
}
|
||||
|
||||
joystick_update();
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update()
|
||||
{
|
||||
JOYCAPS joycap;
|
||||
JOYINFO info;
|
||||
UINT id;
|
||||
MMRESULT ret1, ret2;
|
||||
|
||||
id = JOYSTICKID1;
|
||||
if(g_joystick_type == JOYSTICK_WIN32_2) {
|
||||
id = JOYSTICKID2;
|
||||
}
|
||||
|
||||
ret1 = joyGetDevCaps(id, &joycap, sizeof(joycap));
|
||||
ret2 = joyGetPos(id, &info);
|
||||
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
|
||||
g_paddle_val[0] = (info.wXpos - joycap.wXmin) * 280 /
|
||||
(joycap.wXmax - joycap.wXmin);
|
||||
g_paddle_val[1] = (info.wYpos - joycap.wYmin) * 280 /
|
||||
(joycap.wYmax - joycap.wYmin);
|
||||
g_paddle_button[0] = ((info.wButtons & JOY_BUTTON1) ? 1 : 0);
|
||||
g_paddle_button[1] = ((info.wButtons & JOY_BUTTON2) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update_button()
|
||||
{
|
||||
JOYINFOEX info;
|
||||
UINT id;
|
||||
|
||||
id = JOYSTICKID1;
|
||||
if(g_joystick_type == JOYSTICK_WIN32_2) {
|
||||
id = JOYSTICKID2;
|
||||
}
|
||||
|
||||
info.dwSize = sizeof(JOYINFOEX);
|
||||
info.dwFlags = JOY_RETURNBUTTONS;
|
||||
if(joyGetPosEx(id, &info) == JOYERR_NOERROR) {
|
||||
g_paddle_button[0] = ((info.dwButtons & JOY_BUTTON1) ? 1 : 0);
|
||||
g_paddle_button[1] = ((info.dwButtons & JOY_BUTTON2) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
# else
|
||||
|
||||
/* stubs for the routines */
|
||||
void
|
||||
joystick_init()
|
||||
{
|
||||
printf("No joy with joystick\n");
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
joystick_update_button()
|
||||
{
|
||||
}
|
||||
|
||||
# endif /* !WIN32 */
|
||||
#endif
|
|
@ -0,0 +1,514 @@
|
|||
/* $KmKId: kegsfont.h,v 1.1 2002-11-10 03:31:51-05 kadickey Exp $ */
|
||||
|
||||
/* char 0x00 (raw 0x40) */
|
||||
{ 0xc7, 0xbb, 0xab, 0xa3, 0xa7, 0xbf, 0xc3, 0xff },
|
||||
/* char 0x01 (raw 0x41) */
|
||||
{ 0xef, 0xd7, 0xbb, 0xbb, 0x83, 0xbb, 0xbb, 0xff },
|
||||
/* char 0x02 (raw 0x42) */
|
||||
{ 0x87, 0xbb, 0xbb, 0x87, 0xbb, 0xbb, 0x87, 0xff },
|
||||
/* char 0x03 (raw 0x43) */
|
||||
{ 0xc7, 0xbb, 0xbf, 0xbf, 0xbf, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x04 (raw 0x44) */
|
||||
{ 0x87, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x87, 0xff },
|
||||
/* char 0x05 (raw 0x45) */
|
||||
{ 0x83, 0xbf, 0xbf, 0x87, 0xbf, 0xbf, 0x83, 0xff },
|
||||
/* char 0x06 (raw 0x46) */
|
||||
{ 0x83, 0xbf, 0xbf, 0x87, 0xbf, 0xbf, 0xbf, 0xff },
|
||||
/* char 0x07 (raw 0x47) */
|
||||
{ 0xc3, 0xbf, 0xbf, 0xbf, 0xb3, 0xbb, 0xc3, 0xff },
|
||||
/* char 0x08 (raw 0x48) */
|
||||
{ 0xbb, 0xbb, 0xbb, 0x83, 0xbb, 0xbb, 0xbb, 0xff },
|
||||
/* char 0x09 (raw 0x49) */
|
||||
{ 0xc7, 0xef, 0xef, 0xef, 0xef, 0xef, 0xc7, 0xff },
|
||||
/* char 0x0a (raw 0x4a) */
|
||||
{ 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x0b (raw 0x4b) */
|
||||
{ 0xbb, 0xb7, 0xaf, 0x9f, 0xaf, 0xb7, 0xbb, 0xff },
|
||||
/* char 0x0c (raw 0x4c) */
|
||||
{ 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x83, 0xff },
|
||||
/* char 0x0d (raw 0x4d) */
|
||||
{ 0xbb, 0x93, 0xab, 0xab, 0xbb, 0xbb, 0xbb, 0xff },
|
||||
/* char 0x0e (raw 0x4e) */
|
||||
{ 0xbb, 0xbb, 0x9b, 0xab, 0xb3, 0xbb, 0xbb, 0xff },
|
||||
/* char 0x0f (raw 0x4f) */
|
||||
{ 0xc7, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x10 (raw 0x50) */
|
||||
{ 0x87, 0xbb, 0xbb, 0x87, 0xbf, 0xbf, 0xbf, 0xff },
|
||||
/* char 0x11 (raw 0x51) */
|
||||
{ 0xc7, 0xbb, 0xbb, 0xbb, 0xab, 0xb7, 0xcb, 0xff },
|
||||
/* char 0x12 (raw 0x52) */
|
||||
{ 0x87, 0xbb, 0xbb, 0x87, 0xaf, 0xb7, 0xbb, 0xff },
|
||||
/* char 0x13 (raw 0x53) */
|
||||
{ 0xc7, 0xbb, 0xbf, 0xc7, 0xfb, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x14 (raw 0x54) */
|
||||
{ 0x83, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xff },
|
||||
/* char 0x15 (raw 0x55) */
|
||||
{ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x16 (raw 0x56) */
|
||||
{ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xd7, 0xef, 0xff },
|
||||
/* char 0x17 (raw 0x57) */
|
||||
{ 0xbb, 0xbb, 0xbb, 0xab, 0xab, 0x93, 0xbb, 0xff },
|
||||
/* char 0x18 (raw 0x58) */
|
||||
{ 0xbb, 0xbb, 0xd7, 0xef, 0xd7, 0xbb, 0xbb, 0xff },
|
||||
/* char 0x19 (raw 0x59) */
|
||||
{ 0xbb, 0xbb, 0xd7, 0xef, 0xef, 0xef, 0xef, 0xff },
|
||||
/* char 0x1a (raw 0x5a) */
|
||||
{ 0x83, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x83, 0xff },
|
||||
/* char 0x1b (raw 0x5b) */
|
||||
{ 0x83, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x83, 0xff },
|
||||
/* char 0x1c (raw 0x5c) */
|
||||
{ 0xff, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xff, 0xff },
|
||||
/* char 0x1d (raw 0x5d) */
|
||||
{ 0x83, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0x83, 0xff },
|
||||
/* char 0x1e (raw 0x5e) */
|
||||
{ 0xff, 0xff, 0xef, 0xd7, 0xbb, 0xff, 0xff, 0xff },
|
||||
/* char 0x1f (raw 0x5f) */
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01 },
|
||||
/* char 0x20 (raw 0x20) */
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
/* char 0x21 (raw 0x21) */
|
||||
{ 0xef, 0xef, 0xef, 0xef, 0xef, 0xff, 0xef, 0xff },
|
||||
/* char 0x22 (raw 0x22) */
|
||||
{ 0xd7, 0xd7, 0xd7, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
/* char 0x23 (raw 0x23) */
|
||||
{ 0xd7, 0xd7, 0x83, 0xd7, 0x83, 0xd7, 0xd7, 0xff },
|
||||
/* char 0x24 (raw 0x24) */
|
||||
{ 0xef, 0xc3, 0xaf, 0xc7, 0xeb, 0x87, 0xef, 0xff },
|
||||
/* char 0x25 (raw 0x25) */
|
||||
{ 0x9f, 0x9b, 0xf7, 0xef, 0xdf, 0xb3, 0xf3, 0xff },
|
||||
/* char 0x26 (raw 0x26) */
|
||||
{ 0xdf, 0xaf, 0xaf, 0xdf, 0xab, 0xb7, 0xcb, 0xff },
|
||||
/* char 0x27 (raw 0x27) */
|
||||
{ 0xef, 0xef, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
/* char 0x28 (raw 0x28) */
|
||||
{ 0xef, 0xdf, 0xbf, 0xbf, 0xbf, 0xdf, 0xef, 0xff },
|
||||
/* char 0x29 (raw 0x29) */
|
||||
{ 0xef, 0xf7, 0xfb, 0xfb, 0xfb, 0xf7, 0xef, 0xff },
|
||||
/* char 0x2a (raw 0x2a) */
|
||||
{ 0xef, 0xab, 0xc7, 0xef, 0xc7, 0xab, 0xef, 0xff },
|
||||
/* char 0x2b (raw 0x2b) */
|
||||
{ 0xff, 0xef, 0xef, 0x83, 0xef, 0xef, 0xff, 0xff },
|
||||
/* char 0x2c (raw 0x2c) */
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xef, 0xef, 0xdf, 0xff },
|
||||
/* char 0x2d (raw 0x2d) */
|
||||
{ 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff },
|
||||
/* char 0x2e (raw 0x2e) */
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff },
|
||||
/* char 0x2f (raw 0x2f) */
|
||||
{ 0xff, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0xff, 0xff },
|
||||
/* char 0x30 (raw 0x30) */
|
||||
{ 0xc7, 0xbb, 0xb3, 0xab, 0x9b, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x31 (raw 0x31) */
|
||||
{ 0xef, 0xcf, 0xef, 0xef, 0xef, 0xef, 0xc7, 0xff },
|
||||
/* char 0x32 (raw 0x32) */
|
||||
{ 0xc7, 0xbb, 0xfb, 0xe7, 0xdf, 0xbf, 0x83, 0xff },
|
||||
/* char 0x33 (raw 0x33) */
|
||||
{ 0x83, 0xfb, 0xf7, 0xe7, 0xfb, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x34 (raw 0x34) */
|
||||
{ 0xf7, 0xe7, 0xd7, 0xb7, 0x83, 0xf7, 0xf7, 0xff },
|
||||
/* char 0x35 (raw 0x35) */
|
||||
{ 0x83, 0xbf, 0x87, 0xfb, 0xfb, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x36 (raw 0x36) */
|
||||
{ 0xe3, 0xdf, 0xbf, 0x87, 0xbb, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x37 (raw 0x37) */
|
||||
{ 0x83, 0xfb, 0xf7, 0xef, 0xdf, 0xdf, 0xdf, 0xff },
|
||||
/* char 0x38 (raw 0x38) */
|
||||
{ 0xc7, 0xbb, 0xbb, 0xc7, 0xbb, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x39 (raw 0x39) */
|
||||
{ 0xc7, 0xbb, 0xbb, 0xc3, 0xfb, 0xf7, 0x8f, 0xff },
|
||||
/* char 0x3a (raw 0x3a) */
|
||||
{ 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xff, 0xff },
|
||||
/* char 0x3b (raw 0x3b) */
|
||||
{ 0xff, 0xff, 0xef, 0xff, 0xef, 0xef, 0xdf, 0xff },
|
||||
/* char 0x3c (raw 0x3c) */
|
||||
{ 0xf7, 0xef, 0xdf, 0xbf, 0xdf, 0xef, 0xf7, 0xff },
|
||||
/* char 0x3d (raw 0x3d) */
|
||||
{ 0xff, 0xff, 0x83, 0xff, 0x83, 0xff, 0xff, 0xff },
|
||||
/* char 0x3e (raw 0x3e) */
|
||||
{ 0xdf, 0xef, 0xf7, 0xfb, 0xf7, 0xef, 0xdf, 0xff },
|
||||
/* char 0x3f (raw 0x3f) */
|
||||
{ 0xc7, 0xbb, 0xf7, 0xef, 0xef, 0xff, 0xef, 0xff },
|
||||
/* char 0x40 (raw 0x14) */
|
||||
{ 0x08, 0x10, 0x6c, 0xfe, 0xfc, 0xfc, 0x7e, 0x6c },
|
||||
/* char 0x41 (raw 0x11) */
|
||||
{ 0x08, 0x10, 0x6c, 0x82, 0x84, 0x84, 0x52, 0x6c },
|
||||
/* char 0x42 (raw 0xf5) */
|
||||
{ 0x00, 0x00, 0x40, 0x60, 0x70, 0x78, 0x6c, 0x42 },
|
||||
/* char 0x43 (raw 0x82) */
|
||||
{ 0xfe, 0x44, 0x28, 0x10, 0x10, 0x28, 0x54, 0xfe },
|
||||
/* char 0x44 (raw 0xeb) */
|
||||
{ 0x00, 0x02, 0x04, 0x88, 0x50, 0x20, 0x20, 0x00 },
|
||||
/* char 0x45 (raw 0xe4) */
|
||||
{ 0xfe, 0xfc, 0xfa, 0x36, 0xae, 0xde, 0xde, 0xfe },
|
||||
/* char 0x46 (raw 0xec) */
|
||||
{ 0xfc, 0xfc, 0xfc, 0xdc, 0x9c, 0x00, 0x9e, 0xde },
|
||||
/* char 0x47 (raw 0xed) */
|
||||
{ 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xfe },
|
||||
/* char 0x48 (raw 0xee) */
|
||||
{ 0x10, 0x20, 0x40, 0xfe, 0x40, 0x20, 0x10, 0x00 },
|
||||
/* char 0x49 (raw 0xe9) */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54 },
|
||||
/* char 0x4a (raw 0xef) */
|
||||
{ 0x10, 0x10, 0x10, 0x10, 0x92, 0x54, 0x38, 0x10 },
|
||||
/* char 0x4b (raw 0xf0) */
|
||||
{ 0x10, 0x38, 0x54, 0x92, 0x10, 0x10, 0x10, 0x10 },
|
||||
/* char 0x4c (raw 0xf1) */
|
||||
{ 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* char 0x4d (raw 0xf7) */
|
||||
{ 0x02, 0x02, 0x02, 0x22, 0x62, 0xfe, 0x60, 0x20 },
|
||||
/* char 0x4e (raw 0xf6) */
|
||||
{ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc },
|
||||
/* char 0x4f (raw 0xaf) */
|
||||
{ 0xc8, 0x18, 0x38, 0x7e, 0x38, 0x18, 0x08, 0xf6 },
|
||||
/* char 0x50 (raw 0xb8) */
|
||||
{ 0x26, 0x30, 0x38, 0xfc, 0x38, 0x30, 0x20, 0xde },
|
||||
/* char 0x51 (raw 0xce) */
|
||||
{ 0x02, 0x12, 0x10, 0xfe, 0x7c, 0x38, 0x12, 0x02 },
|
||||
/* char 0x52 (raw 0xe5) */
|
||||
{ 0x02, 0x12, 0x38, 0x7c, 0xfe, 0x10, 0x12, 0x02 },
|
||||
/* char 0x53 (raw 0xea) */
|
||||
{ 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* char 0x54 (raw 0xe6) */
|
||||
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xfe },
|
||||
/* char 0x55 (raw 0xe8) */
|
||||
{ 0x10, 0x08, 0x04, 0xfe, 0x04, 0x08, 0x10, 0x00 },
|
||||
/* char 0x56 (raw 0xd7) */
|
||||
{ 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa },
|
||||
/* char 0x57 (raw 0xe3) */
|
||||
{ 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54, 0xaa, 0x54 },
|
||||
/* char 0x58 (raw 0xf4) */
|
||||
{ 0x00, 0x7c, 0x82, 0x80, 0x80, 0x80, 0xfe, 0x00 },
|
||||
/* char 0x59 (raw 0xe7) */
|
||||
{ 0x00, 0x00, 0xfc, 0x02, 0x02, 0x02, 0xfe, 0x00 },
|
||||
/* char 0x5a (raw 0xf3) */
|
||||
{ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 },
|
||||
/* char 0x5b (raw 0xd2) */
|
||||
{ 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00 },
|
||||
/* char 0x5c (raw 0xc7) */
|
||||
{ 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe },
|
||||
/* char 0x5d (raw 0xd4) */
|
||||
{ 0x28, 0x28, 0xee, 0x00, 0xee, 0x28, 0x28, 0x00 },
|
||||
/* char 0x5e (raw 0xdf) */
|
||||
{ 0xfe, 0x02, 0x02, 0x32, 0x32, 0x02, 0x02, 0xfe },
|
||||
/* char 0x5f (raw 0xd1) */
|
||||
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
|
||||
/* char 0x60 (raw 0x60) */
|
||||
{ 0xdf, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
/* char 0x61 (raw 0x61) */
|
||||
{ 0xff, 0xff, 0xc7, 0xfb, 0xc3, 0xbb, 0xc3, 0xff },
|
||||
/* char 0x62 (raw 0x62) */
|
||||
{ 0xbf, 0xbf, 0x87, 0xbb, 0xbb, 0xbb, 0x87, 0xff },
|
||||
/* char 0x63 (raw 0x63) */
|
||||
{ 0xff, 0xff, 0xc3, 0xbf, 0xbf, 0xbf, 0xc3, 0xff },
|
||||
/* char 0x64 (raw 0x64) */
|
||||
{ 0xfb, 0xfb, 0xc3, 0xbb, 0xbb, 0xbb, 0xc3, 0xff },
|
||||
/* char 0x65 (raw 0x65) */
|
||||
{ 0xff, 0xff, 0xc7, 0xbb, 0x83, 0xbf, 0xc3, 0xff },
|
||||
/* char 0x66 (raw 0x66) */
|
||||
{ 0xe7, 0xdb, 0xdf, 0x87, 0xdf, 0xdf, 0xdf, 0xff },
|
||||
/* char 0x67 (raw 0x67) */
|
||||
{ 0xff, 0xff, 0xc7, 0xbb, 0xbb, 0xc3, 0xfb, 0xc7 },
|
||||
/* char 0x68 (raw 0x68) */
|
||||
{ 0xbf, 0xbf, 0x87, 0xbb, 0xbb, 0xbb, 0xbb, 0xff },
|
||||
/* char 0x69 (raw 0x69) */
|
||||
{ 0xef, 0xff, 0xcf, 0xef, 0xef, 0xef, 0xc7, 0xff },
|
||||
/* char 0x6a (raw 0x6a) */
|
||||
{ 0xf7, 0xff, 0xe7, 0xf7, 0xf7, 0xf7, 0xb7, 0xcf },
|
||||
/* char 0x6b (raw 0x6b) */
|
||||
{ 0xbf, 0xbf, 0xbb, 0xb7, 0x8f, 0xb7, 0xbb, 0xff },
|
||||
/* char 0x6c (raw 0x6c) */
|
||||
{ 0xcf, 0xef, 0xef, 0xef, 0xef, 0xef, 0xc7, 0xff },
|
||||
/* char 0x6d (raw 0x6d) */
|
||||
{ 0xff, 0xff, 0x93, 0xab, 0xab, 0xab, 0xbb, 0xff },
|
||||
/* char 0x6e (raw 0x6e) */
|
||||
{ 0xff, 0xff, 0x87, 0xbb, 0xbb, 0xbb, 0xbb, 0xff },
|
||||
/* char 0x6f (raw 0x6f) */
|
||||
{ 0xff, 0xff, 0xc7, 0xbb, 0xbb, 0xbb, 0xc7, 0xff },
|
||||
/* char 0x70 (raw 0x70) */
|
||||
{ 0xff, 0xff, 0x87, 0xbb, 0xbb, 0x87, 0xbf, 0xbf },
|
||||
/* char 0x71 (raw 0x71) */
|
||||
{ 0xff, 0xff, 0xc3, 0xbb, 0xbb, 0xc3, 0xfb, 0xfb },
|
||||
/* char 0x72 (raw 0x72) */
|
||||
{ 0xff, 0xff, 0xa3, 0x9f, 0xbf, 0xbf, 0xbf, 0xff },
|
||||
/* char 0x73 (raw 0x73) */
|
||||
{ 0xff, 0xff, 0xc3, 0xbf, 0xc7, 0xfb, 0x87, 0xff },
|
||||
/* char 0x74 (raw 0x74) */
|
||||
{ 0xdf, 0xdf, 0x87, 0xdf, 0xdf, 0xdb, 0xe7, 0xff },
|
||||
/* char 0x75 (raw 0x75) */
|
||||
{ 0xff, 0xff, 0xbb, 0xbb, 0xbb, 0xb3, 0xcb, 0xff },
|
||||
/* char 0x76 (raw 0x76) */
|
||||
{ 0xff, 0xff, 0xbb, 0xbb, 0xbb, 0xd7, 0xef, 0xff },
|
||||
/* char 0x77 (raw 0x77) */
|
||||
{ 0xff, 0xff, 0xbb, 0xbb, 0xab, 0xab, 0x93, 0xff },
|
||||
/* char 0x78 (raw 0x78) */
|
||||
{ 0xff, 0xff, 0xbb, 0xd7, 0xef, 0xd7, 0xbb, 0xff },
|
||||
/* char 0x79 (raw 0x79) */
|
||||
{ 0xff, 0xff, 0xbb, 0xbb, 0xbb, 0xc3, 0xfb, 0xc7 },
|
||||
/* char 0x7a (raw 0x7a) */
|
||||
{ 0xff, 0xff, 0x83, 0xf7, 0xef, 0xdf, 0x83, 0xff },
|
||||
/* char 0x7b (raw 0x7b) */
|
||||
{ 0xe3, 0xcf, 0xcf, 0x9f, 0xcf, 0xcf, 0xe3, 0xff },
|
||||
/* char 0x7c (raw 0x7c) */
|
||||
{ 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef },
|
||||
/* char 0x7d (raw 0x7d) */
|
||||
{ 0x8f, 0xe7, 0xe7, 0xf3, 0xe7, 0xe7, 0x8f, 0xff },
|
||||
/* char 0x7e (raw 0x7e) */
|
||||
{ 0xcb, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
/* char 0x7f (raw 0x7f) */
|
||||
{ 0xff, 0xab, 0xd7, 0xab, 0xd7, 0xab, 0xff, 0xff },
|
||||
/* char 0x80 (raw 0x40) */
|
||||
{ 0x38, 0x44, 0x54, 0x5c, 0x58, 0x40, 0x3c, 0x00 },
|
||||
/* char 0x81 (raw 0x41) */
|
||||
{ 0x10, 0x28, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x00 },
|
||||
/* char 0x82 (raw 0x42) */
|
||||
{ 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x78, 0x00 },
|
||||
/* char 0x83 (raw 0x43) */
|
||||
{ 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00 },
|
||||
/* char 0x84 (raw 0x44) */
|
||||
{ 0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x00 },
|
||||
/* char 0x85 (raw 0x45) */
|
||||
{ 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x7c, 0x00 },
|
||||
/* char 0x86 (raw 0x46) */
|
||||
{ 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x40, 0x00 },
|
||||
/* char 0x87 (raw 0x47) */
|
||||
{ 0x3c, 0x40, 0x40, 0x40, 0x4c, 0x44, 0x3c, 0x00 },
|
||||
/* char 0x88 (raw 0x48) */
|
||||
{ 0x44, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0x00 },
|
||||
/* char 0x89 (raw 0x49) */
|
||||
{ 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 },
|
||||
/* char 0x8a (raw 0x4a) */
|
||||
{ 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00 },
|
||||
/* char 0x8b (raw 0x4b) */
|
||||
{ 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00 },
|
||||
/* char 0x8c (raw 0x4c) */
|
||||
{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c, 0x00 },
|
||||
/* char 0x8d (raw 0x4d) */
|
||||
{ 0x44, 0x6c, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00 },
|
||||
/* char 0x8e (raw 0x4e) */
|
||||
{ 0x44, 0x44, 0x64, 0x54, 0x4c, 0x44, 0x44, 0x00 },
|
||||
/* char 0x8f (raw 0x4f) */
|
||||
{ 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 },
|
||||
/* char 0x90 (raw 0x50) */
|
||||
{ 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00 },
|
||||
/* char 0x91 (raw 0x51) */
|
||||
{ 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00 },
|
||||
/* char 0x92 (raw 0x52) */
|
||||
{ 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00 },
|
||||
/* char 0x93 (raw 0x53) */
|
||||
{ 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00 },
|
||||
/* char 0x94 (raw 0x54) */
|
||||
{ 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 },
|
||||
/* char 0x95 (raw 0x55) */
|
||||
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 },
|
||||
/* char 0x96 (raw 0x56) */
|
||||
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 },
|
||||
/* char 0x97 (raw 0x57) */
|
||||
{ 0x44, 0x44, 0x44, 0x54, 0x54, 0x6c, 0x44, 0x00 },
|
||||
/* char 0x98 (raw 0x58) */
|
||||
{ 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00 },
|
||||
/* char 0x99 (raw 0x59) */
|
||||
{ 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00 },
|
||||
/* char 0x9a (raw 0x5a) */
|
||||
{ 0x7c, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7c, 0x00 },
|
||||
/* char 0x9b (raw 0x5b) */
|
||||
{ 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x00 },
|
||||
/* char 0x9c (raw 0x5c) */
|
||||
{ 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00 },
|
||||
/* char 0x9d (raw 0x5d) */
|
||||
{ 0x7c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00 },
|
||||
/* char 0x9e (raw 0x5e) */
|
||||
{ 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00 },
|
||||
/* char 0x9f (raw 0x5f) */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe },
|
||||
/* char 0xa0 (raw 0x20) */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* char 0xa1 (raw 0x21) */
|
||||
{ 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00 },
|
||||
/* char 0xa2 (raw 0x22) */
|
||||
{ 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* char 0xa3 (raw 0x23) */
|
||||
{ 0x28, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x28, 0x00 },
|
||||
/* char 0xa4 (raw 0x24) */
|
||||
{ 0x10, 0x3c, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00 },
|
||||
/* char 0xa5 (raw 0x25) */
|
||||
{ 0x60, 0x64, 0x08, 0x10, 0x20, 0x4c, 0x0c, 0x00 },
|
||||
/* char 0xa6 (raw 0x26) */
|
||||
{ 0x20, 0x50, 0x50, 0x20, 0x54, 0x48, 0x34, 0x00 },
|
||||
/* char 0xa7 (raw 0x27) */
|
||||
{ 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* char 0xa8 (raw 0x28) */
|
||||
{ 0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00 },
|
||||
/* char 0xa9 (raw 0x29) */
|
||||
{ 0x10, 0x08, 0x04, 0x04, 0x04, 0x08, 0x10, 0x00 },
|
||||
/* char 0xaa (raw 0x2a) */
|
||||
{ 0x10, 0x54, 0x38, 0x10, 0x38, 0x54, 0x10, 0x00 },
|
||||
/* char 0xab (raw 0x2b) */
|
||||
{ 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00 },
|
||||
/* char 0xac (raw 0x2c) */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00 },
|
||||
/* char 0xad (raw 0x2d) */
|
||||
{ 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* char 0xae (raw 0x2e) */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 },
|
||||
/* char 0xaf (raw 0x2f) */
|
||||
{ 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00 },
|
||||
/* char 0xb0 (raw 0x30) */
|
||||
{ 0x38, 0x44, 0x4c, 0x54, 0x64, 0x44, 0x38, 0x00 },
|
||||
/* char 0xb1 (raw 0x31) */
|
||||
{ 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 },
|
||||
/* char 0xb2 (raw 0x32) */
|
||||
{ 0x38, 0x44, 0x04, 0x18, 0x20, 0x40, 0x7c, 0x00 },
|
||||
/* char 0xb3 (raw 0x33) */
|
||||
{ 0x7c, 0x04, 0x08, 0x18, 0x04, 0x44, 0x38, 0x00 },
|
||||
/* char 0xb4 (raw 0x34) */
|
||||
{ 0x08, 0x18, 0x28, 0x48, 0x7c, 0x08, 0x08, 0x00 },
|
||||
/* char 0xb5 (raw 0x35) */
|
||||
{ 0x7c, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00 },
|
||||
/* char 0xb6 (raw 0x36) */
|
||||
{ 0x1c, 0x20, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00 },
|
||||
/* char 0xb7 (raw 0x37) */
|
||||
{ 0x7c, 0x04, 0x08, 0x10, 0x20, 0x20, 0x20, 0x00 },
|
||||
/* char 0xb8 (raw 0x38) */
|
||||
{ 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00 },
|
||||
/* char 0xb9 (raw 0x39) */
|
||||
{ 0x38, 0x44, 0x44, 0x3c, 0x04, 0x08, 0x70, 0x00 },
|
||||
/* char 0xba (raw 0x3a) */
|
||||
{ 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00 },
|
||||
/* char 0xbb (raw 0x3b) */
|
||||
{ 0x00, 0x00, 0x10, 0x00, 0x10, 0x10, 0x20, 0x00 },
|
||||
/* char 0xbc (raw 0x3c) */
|
||||
{ 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00 },
|
||||
/* char 0xbd (raw 0x3d) */
|
||||
{ 0x00, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00 },
|
||||
/* char 0xbe (raw 0x3e) */
|
||||
{ 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00 },
|
||||
/* char 0xbf (raw 0x3f) */
|
||||
{ 0x38, 0x44, 0x08, 0x10, 0x10, 0x00, 0x10, 0x00 },
|
||||
/* char 0xc0 (raw 0x40) */
|
||||
{ 0x38, 0x44, 0x54, 0x5c, 0x58, 0x40, 0x3c, 0x00 },
|
||||
/* char 0xc1 (raw 0x41) */
|
||||
{ 0x10, 0x28, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x00 },
|
||||
/* char 0xc2 (raw 0x42) */
|
||||
{ 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x78, 0x00 },
|
||||
/* char 0xc3 (raw 0x43) */
|
||||
{ 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00 },
|
||||
/* char 0xc4 (raw 0x44) */
|
||||
{ 0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x00 },
|
||||
/* char 0xc5 (raw 0x45) */
|
||||
{ 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x7c, 0x00 },
|
||||
/* char 0xc6 (raw 0x46) */
|
||||
{ 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x40, 0x00 },
|
||||
/* char 0xc7 (raw 0x47) */
|
||||
{ 0x3c, 0x40, 0x40, 0x40, 0x4c, 0x44, 0x3c, 0x00 },
|
||||
/* char 0xc8 (raw 0x48) */
|
||||
{ 0x44, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0x00 },
|
||||
/* char 0xc9 (raw 0x49) */
|
||||
{ 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 },
|
||||
/* char 0xca (raw 0x4a) */
|
||||
{ 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00 },
|
||||
/* char 0xcb (raw 0x4b) */
|
||||
{ 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00 },
|
||||
/* char 0xcc (raw 0x4c) */
|
||||
{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c, 0x00 },
|
||||
/* char 0xcd (raw 0x4d) */
|
||||
{ 0x44, 0x6c, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00 },
|
||||
/* char 0xce (raw 0x4e) */
|
||||
{ 0x44, 0x44, 0x64, 0x54, 0x4c, 0x44, 0x44, 0x00 },
|
||||
/* char 0xcf (raw 0x4f) */
|
||||
{ 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 },
|
||||
/* char 0xd0 (raw 0x50) */
|
||||
{ 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00 },
|
||||
/* char 0xd1 (raw 0x51) */
|
||||
{ 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00 },
|
||||
/* char 0xd2 (raw 0x52) */
|
||||
{ 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00 },
|
||||
/* char 0xd3 (raw 0x53) */
|
||||
{ 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00 },
|
||||
/* char 0xd4 (raw 0x54) */
|
||||
{ 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 },
|
||||
/* char 0xd5 (raw 0x55) */
|
||||
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 },
|
||||
/* char 0xd6 (raw 0x56) */
|
||||
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 },
|
||||
/* char 0xd7 (raw 0x57) */
|
||||
{ 0x44, 0x44, 0x44, 0x54, 0x54, 0x6c, 0x44, 0x00 },
|
||||
/* char 0xd8 (raw 0x58) */
|
||||
{ 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00 },
|
||||
/* char 0xd9 (raw 0x59) */
|
||||
{ 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00 },
|
||||
/* char 0xda (raw 0x5a) */
|
||||
{ 0x7c, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7c, 0x00 },
|
||||
/* char 0xdb (raw 0x5b) */
|
||||
{ 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x00 },
|
||||
/* char 0xdc (raw 0x5c) */
|
||||
{ 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00 },
|
||||
/* char 0xdd (raw 0x5d) */
|
||||
{ 0x7c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00 },
|
||||
/* char 0xde (raw 0x5e) */
|
||||
{ 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00 },
|
||||
/* char 0xdf (raw 0x5f) */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe },
|
||||
/* char 0xe0 (raw 0x60) */
|
||||
{ 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* char 0xe1 (raw 0x61) */
|
||||
{ 0x00, 0x00, 0x38, 0x04, 0x3c, 0x44, 0x3c, 0x00 },
|
||||
/* char 0xe2 (raw 0x62) */
|
||||
{ 0x40, 0x40, 0x78, 0x44, 0x44, 0x44, 0x78, 0x00 },
|
||||
/* char 0xe3 (raw 0x63) */
|
||||
{ 0x00, 0x00, 0x3c, 0x40, 0x40, 0x40, 0x3c, 0x00 },
|
||||
/* char 0xe4 (raw 0x64) */
|
||||
{ 0x04, 0x04, 0x3c, 0x44, 0x44, 0x44, 0x3c, 0x00 },
|
||||
/* char 0xe5 (raw 0x65) */
|
||||
{ 0x00, 0x00, 0x38, 0x44, 0x7c, 0x40, 0x3c, 0x00 },
|
||||
/* char 0xe6 (raw 0x66) */
|
||||
{ 0x18, 0x24, 0x20, 0x78, 0x20, 0x20, 0x20, 0x00 },
|
||||
/* char 0xe7 (raw 0x67) */
|
||||
{ 0x00, 0x00, 0x38, 0x44, 0x44, 0x3c, 0x04, 0x38 },
|
||||
/* char 0xe8 (raw 0x68) */
|
||||
{ 0x40, 0x40, 0x78, 0x44, 0x44, 0x44, 0x44, 0x00 },
|
||||
/* char 0xe9 (raw 0x69) */
|
||||
{ 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00 },
|
||||
/* char 0xea (raw 0x6a) */
|
||||
{ 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x48, 0x30 },
|
||||
/* char 0xeb (raw 0x6b) */
|
||||
{ 0x40, 0x40, 0x44, 0x48, 0x70, 0x48, 0x44, 0x00 },
|
||||
/* char 0xec (raw 0x6c) */
|
||||
{ 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 },
|
||||
/* char 0xed (raw 0x6d) */
|
||||
{ 0x00, 0x00, 0x6c, 0x54, 0x54, 0x54, 0x44, 0x00 },
|
||||
/* char 0xee (raw 0x6e) */
|
||||
{ 0x00, 0x00, 0x78, 0x44, 0x44, 0x44, 0x44, 0x00 },
|
||||
/* char 0xef (raw 0x6f) */
|
||||
{ 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00 },
|
||||
/* char 0xf0 (raw 0x70) */
|
||||
{ 0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40 },
|
||||
/* char 0xf1 (raw 0x71) */
|
||||
{ 0x00, 0x00, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x04 },
|
||||
/* char 0xf2 (raw 0x72) */
|
||||
{ 0x00, 0x00, 0x5c, 0x60, 0x40, 0x40, 0x40, 0x00 },
|
||||
/* char 0xf3 (raw 0x73) */
|
||||
{ 0x00, 0x00, 0x3c, 0x40, 0x38, 0x04, 0x78, 0x00 },
|
||||
/* char 0xf4 (raw 0x74) */
|
||||
{ 0x20, 0x20, 0x78, 0x20, 0x20, 0x24, 0x18, 0x00 },
|
||||
/* char 0xf5 (raw 0x75) */
|
||||
{ 0x00, 0x00, 0x44, 0x44, 0x44, 0x4c, 0x34, 0x00 },
|
||||
/* char 0xf6 (raw 0x76) */
|
||||
{ 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 },
|
||||
/* char 0xf7 (raw 0x77) */
|
||||
{ 0x00, 0x00, 0x44, 0x44, 0x54, 0x54, 0x6c, 0x00 },
|
||||
/* char 0xf8 (raw 0x78) */
|
||||
{ 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00 },
|
||||
/* char 0xf9 (raw 0x79) */
|
||||
{ 0x00, 0x00, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x38 },
|
||||
/* char 0xfa (raw 0x7a) */
|
||||
{ 0x00, 0x00, 0x7c, 0x08, 0x10, 0x20, 0x7c, 0x00 },
|
||||
/* char 0xfb (raw 0x7b) */
|
||||
{ 0x1c, 0x30, 0x30, 0x60, 0x30, 0x30, 0x1c, 0x00 },
|
||||
/* char 0xfc (raw 0x7c) */
|
||||
{ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
|
||||
/* char 0xfd (raw 0x7d) */
|
||||
{ 0x70, 0x18, 0x18, 0x0c, 0x18, 0x18, 0x70, 0x00 },
|
||||
/* char 0xfe (raw 0x7e) */
|
||||
{ 0x34, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* char 0xff (raw 0x7f) */
|
||||
{ 0x00, 0x54, 0x28, 0x54, 0x28, 0x54, 0x00, 0x00 },
|
Binary file not shown.
|
@ -0,0 +1,955 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_macdriver_c[] = "@(#)$KmKId: macdriver.c,v 1.19 2004-03-23 17:27:56-05 kentd Exp $";
|
||||
|
||||
// Quartz: CreateCGContextForPort vs QDBeginCGContext
|
||||
|
||||
// Use CGDisplayMoveCursorToPoint(kCGDirectMainDisplay) to warp pointer
|
||||
// Use CGPointMake to get a point
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include "defc.h"
|
||||
#include "protos_macdriver.h"
|
||||
|
||||
#define MAX_STATUS_LINES 7
|
||||
#define X_LINE_LENGTH 88
|
||||
#define MAX_MAC_ARGS 128
|
||||
|
||||
WindowRef g_main_window;
|
||||
int g_quit_seen = 0;
|
||||
EventHandlerUPP g_quit_handler_UPP;
|
||||
EventHandlerUPP g_dummy_event_handler_UPP;
|
||||
RgnHandle g_event_rgnhandle = 0;
|
||||
int g_ignore_next_click = 0;
|
||||
int g_mainwin_active = 0;
|
||||
GDHandle g_gdhandle = 0;
|
||||
int g_mac_mouse_x = 0;
|
||||
int g_mac_mouse_y = 0;
|
||||
|
||||
FMFontFamily g_status_font_family;
|
||||
|
||||
extern Kimage g_mainwin_kimage;
|
||||
|
||||
int g_mac_argc = 0;
|
||||
char *g_mac_argv[MAX_MAC_ARGS];
|
||||
word32 g_mac_shift_control_state = 0;
|
||||
extern char g_argv0_path[];
|
||||
|
||||
extern word32 g_red_mask;
|
||||
extern word32 g_green_mask;
|
||||
extern word32 g_blue_mask;
|
||||
extern int g_red_left_shift;
|
||||
extern int g_green_left_shift;
|
||||
extern int g_blue_left_shift;
|
||||
extern int g_red_right_shift;
|
||||
extern int g_green_right_shift;
|
||||
extern int g_blue_right_shift;
|
||||
|
||||
int g_use_shmem = 0;
|
||||
|
||||
extern int Verbose;
|
||||
|
||||
extern int g_warp_pointer;
|
||||
extern int g_screen_depth;
|
||||
extern int g_force_depth;
|
||||
int g_screen_mdepth = 0;
|
||||
|
||||
extern int g_send_sound_to_file;
|
||||
|
||||
extern int g_quit_sim_now;
|
||||
extern int g_config_control_panel;
|
||||
|
||||
int g_auto_repeat_on = -1;
|
||||
int g_x_shift_control_state = 0;
|
||||
|
||||
|
||||
extern int Max_color_size;
|
||||
|
||||
extern word32 g_palette_8to1624[256];
|
||||
extern word32 g_a2palette_8to1624[256];
|
||||
|
||||
int g_alt_left_up = 1;
|
||||
int g_alt_right_up = 1;
|
||||
|
||||
extern word32 g_full_refresh_needed;
|
||||
|
||||
extern int g_border_sides_refresh_needed;
|
||||
extern int g_border_special_refresh_needed;
|
||||
extern int g_status_refresh_needed;
|
||||
|
||||
extern int g_lores_colors[];
|
||||
|
||||
extern int g_a2vid_palette;
|
||||
|
||||
extern int g_installed_full_superhires_colormap;
|
||||
|
||||
extern int g_screen_redraw_skip_amt;
|
||||
|
||||
extern word32 g_a2_screen_buffer_changed;
|
||||
extern char *g_status_ptrs[MAX_STATUS_LINES];
|
||||
extern const char g_kegs_version_str[];
|
||||
|
||||
#if 0
|
||||
char g_printf_buf[4096];
|
||||
int g_debug_file_fd = -1;
|
||||
|
||||
/* HACK to debug startup issues when launched from Finder */
|
||||
int
|
||||
printf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vsnprintf(g_printf_buf, 4090, fmt, ap);
|
||||
|
||||
if(g_debug_file_fd < 0) {
|
||||
g_debug_file_fd = open("/tmp/kegs.out",
|
||||
O_CREAT | O_WRONLY | O_TRUNC, 0x1b6);
|
||||
fprintf(stdout, "g_debug_file_fd = %d, %d\n", g_debug_file_fd,
|
||||
errno);
|
||||
}
|
||||
write(1, g_printf_buf, strlen(g_printf_buf));
|
||||
write(g_debug_file_fd, g_printf_buf, strlen(g_printf_buf));
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
pascal OSStatus
|
||||
quit_event_handler(EventHandlerCallRef call_ref, EventRef event, void *ignore)
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
err = CallNextEventHandler(call_ref, event);
|
||||
if(err == noErr) {
|
||||
g_quit_seen = 1;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void
|
||||
show_alert(const char *str1, const char *str2, const char *str3, int num)
|
||||
{
|
||||
char buf[256];
|
||||
DialogRef alert;
|
||||
DialogItemIndex out_item_hit;
|
||||
CFStringRef cfstrref;
|
||||
|
||||
if(num != 0) {
|
||||
snprintf(buf, 250, "%s%s%s: %d", str1, str2, str3, num);
|
||||
} else {
|
||||
snprintf(buf, 250, "%s%s%s", str1, str2, str3);
|
||||
}
|
||||
|
||||
cfstrref = CFStringCreateWithCString(NULL, buf,
|
||||
kCFStringEncodingMacRoman);
|
||||
|
||||
CreateStandardAlert(kAlertStopAlert, cfstrref, CFSTR("Click OK"),
|
||||
NULL, &alert);
|
||||
RunStandardAlert(alert, NULL, &out_item_hit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
pascal OSStatus
|
||||
my_cmd_handler( EventHandlerCallRef handlerRef, EventRef event, void *userdata)
|
||||
{
|
||||
OSStatus osresult;
|
||||
HICommand command;
|
||||
word32 command_id;
|
||||
|
||||
osresult = eventNotHandledErr;
|
||||
|
||||
GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL,
|
||||
sizeof(HICommand), NULL, &command);
|
||||
|
||||
command_id = (word32)command.commandID;
|
||||
switch(command_id) {
|
||||
case 'Kbep':
|
||||
SysBeep(10);
|
||||
osresult = noErr;
|
||||
break;
|
||||
case 'abou':
|
||||
show_alert("KEGSMAC v", g_kegs_version_str,
|
||||
", Copyright 2004 Kent Dickey\n"
|
||||
"Latest version at http://kegs.sourceforge.net/\n", 0);
|
||||
osresult = noErr;
|
||||
break;
|
||||
case 'KCFG':
|
||||
g_config_control_panel = !g_config_control_panel;
|
||||
osresult = noErr;
|
||||
break;
|
||||
case 'quit':
|
||||
break;
|
||||
case 'swin':
|
||||
/* not sure what this is, but Panther sends it */
|
||||
break;
|
||||
default:
|
||||
printf("commandID %08x unknown\n", command_id);
|
||||
SysBeep(90);
|
||||
break;
|
||||
}
|
||||
return osresult;
|
||||
}
|
||||
|
||||
int g_upd_count = 0;
|
||||
|
||||
void
|
||||
update_window(void)
|
||||
{
|
||||
SetPortWindowPort(g_main_window);
|
||||
|
||||
PenNormal();
|
||||
|
||||
g_full_refresh_needed = -1;
|
||||
g_a2_screen_buffer_changed = -1;
|
||||
g_status_refresh_needed = 1;
|
||||
g_border_sides_refresh_needed = 1;
|
||||
g_border_special_refresh_needed = 1;
|
||||
|
||||
g_upd_count++;
|
||||
if(g_upd_count > 250) {
|
||||
g_upd_count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct char_int_un {
|
||||
union {
|
||||
char c[4];
|
||||
UInt32 uint;
|
||||
} u;
|
||||
char c2[2];
|
||||
};
|
||||
|
||||
typedef struct char_int_un Char_int;
|
||||
|
||||
int g_event_count = 0;
|
||||
|
||||
void
|
||||
show_event(UInt32 event_class, UInt32 event_kind, int handled)
|
||||
{
|
||||
Char_int char_int;
|
||||
|
||||
if(handled == 0 && event_class != 'cgs ') {
|
||||
char_int.c2[0] = 0;
|
||||
char_int.u.uint = event_class;
|
||||
printf("Event %d: %08x = %s, %d\n", g_event_count,
|
||||
(int)event_class, &(char_int.u.c[0]), (int)event_kind);
|
||||
}
|
||||
g_event_count++;
|
||||
}
|
||||
|
||||
pascal OSStatus
|
||||
my_win_handler(EventHandlerCallRef handlerRef, EventRef event, void *userdata)
|
||||
{
|
||||
OSStatus os_result;
|
||||
UInt32 event_kind;
|
||||
|
||||
os_result = eventNotHandledErr;
|
||||
|
||||
// SysBeep(1);
|
||||
|
||||
event_kind = GetEventKind(event);
|
||||
// show_alert("win handler", event_kind);
|
||||
if(event_kind == kEventWindowDrawContent) {
|
||||
update_window();
|
||||
} if(event_kind == kEventWindowClose) {
|
||||
g_quit_sim_now = 1;
|
||||
g_quit_seen = 1;
|
||||
my_exit(0);
|
||||
} else {
|
||||
show_event(GetEventClass(event), event_kind, 0);
|
||||
update_window();
|
||||
}
|
||||
|
||||
return os_result;
|
||||
}
|
||||
|
||||
|
||||
pascal OSStatus
|
||||
dummy_event_handler(EventHandlerCallRef call_ref, EventRef in_event,
|
||||
void *ignore)
|
||||
{
|
||||
OSStatus err;
|
||||
EventHandlerRef installed_handler;
|
||||
EventTypeSpec event_spec = { kEventClassApplication, kEventAppQuit };
|
||||
|
||||
// From http://developer.apple.com/qa/qa2001/qa1061.html
|
||||
// Trick to move main event queue to use ReceiveNextEvent in an event
|
||||
// handler called by RunApplicationEventLoop
|
||||
|
||||
err = InstallApplicationEventHandler(g_quit_handler_UPP, 1, &event_spec,
|
||||
NULL, &installed_handler);
|
||||
|
||||
kegsmain(g_mac_argc, g_mac_argv);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
void
|
||||
mac_update_modifiers(word32 state)
|
||||
{
|
||||
word32 state_xor;
|
||||
int is_up;
|
||||
|
||||
state = state & (cmdKey | shiftKey | alphaLock | optionKey |
|
||||
controlKey);
|
||||
state_xor = g_mac_shift_control_state ^ state;
|
||||
is_up = 0;
|
||||
if(state_xor & controlKey) {
|
||||
is_up = ((state & controlKey) == 0);
|
||||
adb_physical_key_update(0x36, is_up);
|
||||
}
|
||||
if(state_xor & alphaLock) {
|
||||
is_up = ((state & alphaLock) == 0);
|
||||
adb_physical_key_update(0x39, is_up);
|
||||
}
|
||||
if(state_xor & shiftKey) {
|
||||
is_up = ((state & shiftKey) == 0);
|
||||
adb_physical_key_update(0x38, is_up);
|
||||
}
|
||||
if(state_xor & cmdKey) {
|
||||
is_up = ((state & cmdKey) == 0);
|
||||
adb_physical_key_update(0x37, is_up);
|
||||
}
|
||||
if(state_xor & optionKey) {
|
||||
is_up = ((state & optionKey) == 0);
|
||||
adb_physical_key_update(0x3a, is_up);
|
||||
}
|
||||
|
||||
g_mac_shift_control_state = state;
|
||||
}
|
||||
|
||||
void
|
||||
mac_warp_mouse()
|
||||
{
|
||||
Rect port_rect;
|
||||
Point win_origin_pt;
|
||||
CGPoint cgpoint;
|
||||
CGDisplayErr cg_err;
|
||||
|
||||
GetPortBounds(GetWindowPort(g_main_window), &port_rect);
|
||||
SetPt(&win_origin_pt, port_rect.left, port_rect.top);
|
||||
LocalToGlobal(&win_origin_pt);
|
||||
|
||||
cgpoint = CGPointMake( (float)(win_origin_pt.h + X_A2_WINDOW_WIDTH/2),
|
||||
(float)(win_origin_pt.v + X_A2_WINDOW_HEIGHT/2));
|
||||
cg_err = CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
|
||||
}
|
||||
|
||||
void
|
||||
check_input_events()
|
||||
{
|
||||
OSStatus err;
|
||||
EventTargetRef target;
|
||||
EventRef event;
|
||||
UInt32 event_class, event_kind;
|
||||
byte mac_keycode;
|
||||
UInt32 keycode;
|
||||
UInt32 modifiers;
|
||||
Point mouse_point, mouse_delta_point;
|
||||
WindowRef window_ref;
|
||||
int button, button_state;
|
||||
EventMouseButton mouse_button;
|
||||
int handled;
|
||||
int mouse_events;
|
||||
int is_up;
|
||||
int in_win;
|
||||
int ignore;
|
||||
|
||||
if(g_quit_seen) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
SetPortWindowPort(g_main_window);
|
||||
|
||||
mouse_events = 0;
|
||||
target = GetEventDispatcherTarget();
|
||||
while(1) {
|
||||
err = ReceiveNextEvent(0, NULL, kEventDurationNoWait,
|
||||
true, &event);
|
||||
|
||||
if(err == eventLoopTimedOutErr) {
|
||||
break;
|
||||
}
|
||||
if(err != noErr) {
|
||||
printf("err: %d\n", (int)err);
|
||||
break;
|
||||
}
|
||||
|
||||
event_class = GetEventClass(event);
|
||||
event_kind = GetEventKind(event);
|
||||
handled = 0;
|
||||
switch(event_class) {
|
||||
case kEventClassKeyboard:
|
||||
handled = 1;
|
||||
keycode = 0;
|
||||
modifiers = 0;
|
||||
GetEventParameter(event, kEventParamKeyMacCharCodes,
|
||||
typeChar, NULL, sizeof(byte), NULL,
|
||||
&mac_keycode);
|
||||
GetEventParameter(event, kEventParamKeyCode,
|
||||
typeUInt32, NULL, sizeof(UInt32), NULL,
|
||||
&keycode);
|
||||
GetEventParameter(event, kEventParamKeyModifiers,
|
||||
typeUInt32, NULL, sizeof(UInt32), NULL,
|
||||
&modifiers);
|
||||
|
||||
mac_update_modifiers((word32)modifiers);
|
||||
|
||||
// Key up/down event
|
||||
is_up = -1;
|
||||
switch(event_kind) {
|
||||
case kEventRawKeyDown:
|
||||
is_up = 0;
|
||||
//printf("key down: %02x, %08x\n",
|
||||
// (int)mac_keycode, (int)keycode);
|
||||
break;
|
||||
case kEventRawKeyUp:
|
||||
is_up = 1;
|
||||
//printf("key up: %02x, %08x\n",
|
||||
// (int)mac_keycode, (int)keycode);
|
||||
break;
|
||||
case kEventRawKeyModifiersChanged:
|
||||
is_up = -1;
|
||||
//printf("key xxx: %08x\n", (int)modifiers);
|
||||
break;
|
||||
}
|
||||
if(is_up >= 0) {
|
||||
adb_physical_key_update((int)keycode, is_up);
|
||||
}
|
||||
break;
|
||||
case kEventClassMouse:
|
||||
handled = 2;
|
||||
mouse_events++;
|
||||
GetEventParameter(event, kEventParamMouseLocation,
|
||||
typeQDPoint, NULL, sizeof(Point), NULL,
|
||||
&mouse_point);
|
||||
GetWindowRegion(g_main_window, kWindowContentRgn,
|
||||
g_event_rgnhandle);
|
||||
in_win = PtInRgn(mouse_point, g_event_rgnhandle);
|
||||
// in_win = 1 if it was in the contect region of window
|
||||
err = GetEventParameter(event, kEventParamMouseDelta,
|
||||
typeQDPoint, NULL, sizeof(Point), NULL,
|
||||
&mouse_delta_point);
|
||||
button = 0;
|
||||
button_state = -1;
|
||||
switch(event_kind) {
|
||||
case kEventMouseDown:
|
||||
button_state = 7;
|
||||
handled = 3;
|
||||
break;
|
||||
case kEventMouseUp:
|
||||
button_state = 0;
|
||||
handled = 3;
|
||||
break;
|
||||
}
|
||||
if(button_state >= 0) {
|
||||
GetEventParameter(event, kEventParamMouseButton,
|
||||
typeMouseButton, NULL,
|
||||
sizeof(EventMouseButton), NULL,
|
||||
&mouse_button);
|
||||
button = mouse_button;
|
||||
if(button > 1) {
|
||||
button = 4 - button;
|
||||
button = 1 << button;
|
||||
}
|
||||
ignore = (button_state != 0) &&
|
||||
(!in_win || g_ignore_next_click);
|
||||
ignore = ignore || !g_mainwin_active;
|
||||
if(ignore) {
|
||||
// Outside of A2 window, ignore clicks
|
||||
button = 0;
|
||||
}
|
||||
if(button_state == 0) {
|
||||
g_ignore_next_click = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GlobalToLocal(&mouse_point);
|
||||
|
||||
if(g_warp_pointer) {
|
||||
if(err == 0) {
|
||||
g_mac_mouse_x += mouse_delta_point.h;
|
||||
g_mac_mouse_y += mouse_delta_point.v;
|
||||
}
|
||||
mac_warp_mouse();
|
||||
} else {
|
||||
g_mac_mouse_x = mouse_point.h -BASE_MARGIN_LEFT;
|
||||
g_mac_mouse_y = mouse_point.v -BASE_MARGIN_TOP;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("Mouse %d at: %d,%d button:%d, button_st:%d\n",
|
||||
mouse_events, g_mac_mouse_x, g_mac_mouse_y,
|
||||
button, button_state);
|
||||
printf("Mouse deltas: err:%d, %d,%d\n", (int)err,
|
||||
mouse_delta_point.h, mouse_delta_point.v);
|
||||
#endif
|
||||
|
||||
update_mouse(g_mac_mouse_x, g_mac_mouse_y,
|
||||
button_state, button & 7);
|
||||
if(g_warp_pointer) {
|
||||
g_mac_mouse_x = A2_WINDOW_WIDTH/2;
|
||||
g_mac_mouse_y = A2_WINDOW_HEIGHT/2;
|
||||
update_mouse(g_mac_mouse_x, g_mac_mouse_y,0,-1);
|
||||
}
|
||||
break;
|
||||
case kEventClassApplication:
|
||||
switch(event_kind) {
|
||||
case kEventAppActivated:
|
||||
handled = 1;
|
||||
g_mainwin_active = 1;
|
||||
window_ref = 0;
|
||||
GetEventParameter(event, kEventParamWindowRef,
|
||||
typeWindowRef, NULL, sizeof(WindowRef),
|
||||
NULL, &window_ref);
|
||||
if(window_ref == g_main_window) {
|
||||
g_ignore_next_click = 1;
|
||||
}
|
||||
break;
|
||||
case kEventAppDeactivated:
|
||||
handled = 1;
|
||||
g_mainwin_active = 0;
|
||||
g_ignore_next_click = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
show_event(event_class, event_kind, handled);
|
||||
if(handled != 1) {
|
||||
(void)SendEventToEventTarget(event, target);
|
||||
}
|
||||
ReleaseEvent(event);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
temp_run_application_event_loop(void)
|
||||
{
|
||||
OSStatus err;
|
||||
EventRef dummy_event;
|
||||
EventHandlerRef install_handler;
|
||||
EventTypeSpec event_spec = { 'KWIN', 'KWIN' };
|
||||
|
||||
// Create UPP for dummy_event_handler and for quit_event_handler
|
||||
err = noErr;
|
||||
dummy_event = 0;
|
||||
|
||||
g_dummy_event_handler_UPP = NewEventHandlerUPP(dummy_event_handler);
|
||||
g_quit_handler_UPP = NewEventHandlerUPP(quit_event_handler);
|
||||
if((g_dummy_event_handler_UPP == 0) || (g_quit_handler_UPP == 0)) {
|
||||
err = memFullErr;
|
||||
}
|
||||
|
||||
if(err == noErr) {
|
||||
err = InstallApplicationEventHandler(g_dummy_event_handler_UPP,
|
||||
1, &event_spec, 0, &install_handler);
|
||||
if(err == noErr) {
|
||||
err = MacCreateEvent(NULL, 'KWIN', 'KWIN',
|
||||
GetCurrentEventTime(), kEventAttributeNone,
|
||||
&dummy_event);
|
||||
if(err == noErr) {
|
||||
err = PostEventToQueue(GetMainEventQueue(),
|
||||
dummy_event, kEventPriorityHigh);
|
||||
}
|
||||
if(err == noErr) {
|
||||
RunApplicationEventLoop();
|
||||
}
|
||||
|
||||
(void)RemoveEventHandler(install_handler);
|
||||
}
|
||||
}
|
||||
|
||||
if(dummy_event != NULL) {
|
||||
ReleaseEvent(dummy_event);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
ProcessSerialNumber my_psn;
|
||||
IBNibRef nibRef;
|
||||
EventHandlerUPP handlerUPP;
|
||||
EventTypeSpec cmd_event[3];
|
||||
#if 0
|
||||
MenuBarHandle mbar_handle;
|
||||
MenuRef menu_ref;
|
||||
#endif
|
||||
Rect win_rect;
|
||||
OSStatus err;
|
||||
char *argptr;
|
||||
int slash_cnt;
|
||||
int i;
|
||||
|
||||
/* Prepare argv0 */
|
||||
slash_cnt = 0;
|
||||
argptr = argv[0];
|
||||
for(i = strlen(argptr); i >= 0; i--) {
|
||||
if(argptr[i] == '/') {
|
||||
slash_cnt++;
|
||||
if(slash_cnt == 3) {
|
||||
strncpy(&(g_argv0_path[0]), argptr, i);
|
||||
g_argv0_path[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("g_argv0_path is %s\n", g_argv0_path);
|
||||
|
||||
g_mac_argv[0] = argv[0];
|
||||
g_mac_argc = 1;
|
||||
i = 1;
|
||||
while((i < argc) && (g_mac_argc < MAX_MAC_ARGS)) {
|
||||
if(!strncmp(argv[i], "-psn", 4)) {
|
||||
/* skip this argument */
|
||||
} else {
|
||||
g_mac_argv[g_mac_argc++] = argv[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
InitCursor();
|
||||
g_event_rgnhandle = NewRgn();
|
||||
g_status_font_family = FMGetFontFamilyFromName("\pCourier");
|
||||
SetRect(&win_rect, 0, 0, X_A2_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT +
|
||||
MAX_STATUS_LINES*16 + 8);
|
||||
OffsetRect(&win_rect, 64, 50);
|
||||
|
||||
// Create a Nib reference passing the name of the nib file
|
||||
// CreateNibReference only searches into the application bundle.
|
||||
err = CreateNibReference(CFSTR("main"), &nibRef);
|
||||
require_noerr( err, CantGetNibRef );
|
||||
|
||||
// Once the nib reference is created, set the menu bar.
|
||||
err = SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
|
||||
require_noerr( err, CantSetMenuBar );
|
||||
|
||||
|
||||
#if 0
|
||||
mbar_handle = GetMenuBar();
|
||||
SetMenuBar(mbar_handle);
|
||||
printf("mbar_handle: %p\n", mbar_handle);
|
||||
|
||||
menu_ref = NewMenu(1, "\pTest");
|
||||
printf("menu_ref: %p\n", menu_ref);
|
||||
AppendMenu(menu_ref, "\pTest item 1");
|
||||
InsertMenu(menu_ref, 0);
|
||||
// ShowMenuBar(); // Don't call ShowMenuBar: it prevents menubar update!
|
||||
DrawMenuBar();
|
||||
InvalMenuBar();
|
||||
#endif
|
||||
|
||||
err = CreateNewWindow(kDocumentWindowClass,
|
||||
kWindowStandardDocumentAttributes |
|
||||
kWindowStandardHandlerAttribute,
|
||||
&win_rect, &g_main_window);
|
||||
|
||||
//printf("CreateNewWindow ret: %d, g_main_window: %p\n", (int)err,
|
||||
// g_main_window);
|
||||
|
||||
err = SetWindowTitleWithCFString(g_main_window, CFSTR("KEGSMAC"));
|
||||
|
||||
// We don't need the nib reference anymore.
|
||||
DisposeNibReference(nibRef);
|
||||
|
||||
SysBeep(120);
|
||||
|
||||
handlerUPP = NewEventHandlerUPP( my_cmd_handler );
|
||||
|
||||
cmd_event[0].eventClass = kEventClassCommand;
|
||||
cmd_event[0].eventKind = kEventProcessCommand;
|
||||
InstallWindowEventHandler(g_main_window, handlerUPP, 1, &cmd_event[0],
|
||||
(void *)g_main_window, NULL);
|
||||
|
||||
handlerUPP = NewEventHandlerUPP(my_win_handler);
|
||||
cmd_event[0].eventClass = kEventClassWindow;
|
||||
cmd_event[0].eventKind = kEventWindowDrawContent;
|
||||
cmd_event[1].eventClass = kEventClassWindow;
|
||||
cmd_event[1].eventKind = kEventWindowUpdate;
|
||||
cmd_event[2].eventClass = kEventClassWindow;
|
||||
cmd_event[2].eventKind = kEventWindowClose;
|
||||
err = InstallWindowEventHandler(g_main_window, handlerUPP, 3,
|
||||
&cmd_event[0], (void *)g_main_window, NULL);
|
||||
require_noerr(err, CantCreateWindow);
|
||||
|
||||
// Get screen depth
|
||||
g_gdhandle = GetGDevice();
|
||||
g_screen_mdepth = (**((**g_gdhandle).gdPMap)).pixelSize;
|
||||
|
||||
g_screen_depth = g_screen_mdepth;
|
||||
|
||||
//printf("g_screen_depth = %d, depth: %d, bytes: %d\n", g_screen_depth,
|
||||
// (**g_gdhandle).gdCCDepth, (**g_gdhandle).gdCCBytes);
|
||||
|
||||
if(g_screen_depth > 16) {
|
||||
/* 32-bit display */
|
||||
g_red_mask = 0xff;
|
||||
g_green_mask = 0xff;
|
||||
g_blue_mask = 0xff;
|
||||
g_red_left_shift = 16;
|
||||
g_green_left_shift = 8;
|
||||
g_blue_left_shift = 0;
|
||||
g_red_right_shift = 0;
|
||||
g_green_right_shift = 0;
|
||||
g_blue_right_shift = 0;
|
||||
} else if(g_screen_depth > 8) {
|
||||
/* 16-bit display */
|
||||
g_red_mask = 0x1f;
|
||||
g_green_mask = 0x1f;
|
||||
g_blue_mask = 0x1f;
|
||||
g_red_left_shift = 10;
|
||||
g_green_left_shift = 5;
|
||||
g_blue_left_shift = 0;
|
||||
g_red_right_shift = 3;
|
||||
g_green_right_shift = 3;
|
||||
g_blue_right_shift = 3;
|
||||
}
|
||||
|
||||
// show_alert("About to show window", (int)g_main_window);
|
||||
update_window();
|
||||
|
||||
// The window was created hidden so show it.
|
||||
ShowWindow( g_main_window );
|
||||
BringToFront( g_main_window );
|
||||
update_window();
|
||||
|
||||
// Make us pop to the front a different way
|
||||
err = GetCurrentProcess(&my_psn);
|
||||
if(err == noErr) {
|
||||
(void)SetFrontProcess(&my_psn);
|
||||
}
|
||||
|
||||
// Call the event loop
|
||||
temp_run_application_event_loop();
|
||||
|
||||
CantCreateWindow:
|
||||
CantSetMenuBar:
|
||||
CantGetNibRef:
|
||||
show_alert("ending", "", "error code", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_update_color(int col_num, int red, int green, int blue, word32 rgb)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_update_physical_colormap()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
show_xcolor_array()
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
printf("%02x: %08x\n", i, g_palette_8to1624[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xdriver_end()
|
||||
{
|
||||
|
||||
printf("xdriver_end\n");
|
||||
}
|
||||
|
||||
void
|
||||
x_get_kimage(Kimage *kimage_ptr)
|
||||
{
|
||||
PixMapHandle pixmap_handle;
|
||||
GWorldPtr world;
|
||||
Rect world_rect;
|
||||
OSStatus err;
|
||||
word32 *wptr;
|
||||
byte *ptr;
|
||||
int row_bytes;
|
||||
int width;
|
||||
int height;
|
||||
int depth, mdepth;
|
||||
int size;
|
||||
|
||||
width = kimage_ptr->width_req;
|
||||
height = kimage_ptr->height;
|
||||
depth = kimage_ptr->depth;
|
||||
mdepth = kimage_ptr->mdepth;
|
||||
|
||||
size = 0;
|
||||
if(depth == g_screen_depth) {
|
||||
SetRect(&world_rect, 0, 0, width, height);
|
||||
err = NewGWorld( &world, 0, &world_rect, NULL, NULL, 0);
|
||||
pixmap_handle = GetGWorldPixMap(world);
|
||||
err = LockPixels(pixmap_handle);
|
||||
ptr = (byte *)GetPixBaseAddr(pixmap_handle);
|
||||
row_bytes = ((*pixmap_handle)->rowBytes & 0x3fff);
|
||||
kimage_ptr->width_act = row_bytes / (mdepth >> 3);
|
||||
mac_printf("Got depth: %d, bitmap_ptr: %p, width: %d\n", depth,
|
||||
ptr, kimage_ptr->width_act);
|
||||
mac_printf("pixmap->base: %08x, rowbytes: %08x, pixType:%08x\n",
|
||||
(int)(*pixmap_handle)->baseAddr,
|
||||
(*pixmap_handle)->rowBytes,
|
||||
(*pixmap_handle)->pixelType);
|
||||
wptr = (word32 *)(*pixmap_handle);
|
||||
mac_printf("wptr: %p=%08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
wptr,
|
||||
wptr[0], wptr[1], wptr[2], wptr[3],
|
||||
wptr[4], wptr[5], wptr[6], wptr[7]);
|
||||
kimage_ptr->dev_handle = pixmap_handle;
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
} else {
|
||||
|
||||
/* allocate buffers for video.c to draw into */
|
||||
|
||||
size = (width*height*mdepth) >> 3;
|
||||
ptr = (byte *)malloc(size);
|
||||
|
||||
if(ptr == 0) {
|
||||
mac_printf("malloc for data fail, mdepth:%d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
|
||||
kimage_ptr->dev_handle = (void *)-1;
|
||||
}
|
||||
|
||||
mac_printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr,
|
||||
kimage_ptr->dev_handle, kimage_ptr->data_ptr, size);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
dev_video_init()
|
||||
{
|
||||
int lores_col;
|
||||
int i;
|
||||
|
||||
printf("Preparing graphics system\n");
|
||||
|
||||
video_get_kimages();
|
||||
|
||||
if(g_screen_depth != 8) {
|
||||
// Get g_mainwin_kimage
|
||||
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth,
|
||||
g_screen_mdepth);
|
||||
}
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
lores_col = g_lores_colors[i & 0xf];
|
||||
video_update_color_raw(i, lores_col);
|
||||
g_a2palette_8to1624[i] = g_palette_8to1624[i];
|
||||
}
|
||||
|
||||
g_installed_full_superhires_colormap = 1;
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_redraw_status_lines()
|
||||
{
|
||||
Rect rect;
|
||||
Pattern white_pattern;
|
||||
char tmp_buf[256];
|
||||
char *buf;
|
||||
int len;
|
||||
int line;
|
||||
int height;
|
||||
int margin;
|
||||
|
||||
SetPortWindowPort(g_main_window);
|
||||
PenNormal();
|
||||
height = 16;
|
||||
margin = 0;
|
||||
TextFont(g_status_font_family);
|
||||
TextFace(normal);
|
||||
TextSize(12);
|
||||
|
||||
SetRect(&rect, 0, X_A2_WINDOW_HEIGHT + margin, X_A2_WINDOW_WIDTH,
|
||||
X_A2_WINDOW_HEIGHT + margin + MAX_STATUS_LINES*height);
|
||||
GetQDGlobalsWhite(&white_pattern);
|
||||
FillRect(&rect, &white_pattern);
|
||||
|
||||
for(line = 0; line < MAX_STATUS_LINES; line++) {
|
||||
buf = g_status_ptrs[line];
|
||||
if(buf == 0) {
|
||||
/* skip it */
|
||||
continue;
|
||||
}
|
||||
MoveTo(10, X_A2_WINDOW_HEIGHT + height*line + margin + height);
|
||||
len = MIN(250, strlen(buf));
|
||||
strncpy(&tmp_buf[1], buf, len);
|
||||
tmp_buf[0] = len;
|
||||
DrawString(&tmp_buf[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
|
||||
int width, int height)
|
||||
{
|
||||
PixMapHandle pixmap_handle;
|
||||
Rect src_rect, dest_rect;
|
||||
CGrafPtr window_port;
|
||||
|
||||
SetPortWindowPort(g_main_window);
|
||||
|
||||
pixmap_handle = kimage_ptr->dev_handle;
|
||||
window_port = GetWindowPort(g_main_window);
|
||||
SetRect(&src_rect, srcx, srcy, srcx + width, srcy + height);
|
||||
SetRect(&dest_rect, destx, desty, destx + width, desty + height);
|
||||
|
||||
CopyBits( (BitMap *)(*pixmap_handle),
|
||||
GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect,
|
||||
srcCopy, NULL);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
x_push_done()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
x_auto_repeat_on(int must)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
x_auto_repeat_off(int must)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
x_hide_pointer(int do_hide)
|
||||
{
|
||||
if(do_hide) {
|
||||
HideCursor();
|
||||
} else {
|
||||
ShowCursor();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_macsnd_driver_c[] = "@(#)$KmKId: macsnd_driver.c,v 1.4 2003-10-17 15:57:40-04 kentd Exp $";
|
||||
|
||||
#include "defc.h"
|
||||
#include "sound.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MACSND_REBUF_SIZE (64*1024)
|
||||
#define MACSND_QUANTA 512
|
||||
/* MACSND_QUANTA must be >= 128 and a power of 2 */
|
||||
|
||||
word32 g_macsnd_rebuf[MACSND_REBUF_SIZE];
|
||||
volatile word32 *g_macsnd_rebuf_ptr;
|
||||
volatile word32 *g_macsnd_rebuf_cur;
|
||||
volatile int g_macsnd_playing = 0;
|
||||
|
||||
extern int Verbose;
|
||||
|
||||
extern int g_audio_rate;
|
||||
extern word32 *g_sound_shm_addr;
|
||||
extern int g_sound_size;
|
||||
|
||||
|
||||
SndChannelPtr g_snd_channel_ptr;
|
||||
ExtSoundHeader g_snd_hdr;
|
||||
SndCommand g_snd_cmd;
|
||||
|
||||
void
|
||||
mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd)
|
||||
{
|
||||
OSStatus err;
|
||||
int samps;
|
||||
|
||||
// This is an interrupt routine--no printf, etc!
|
||||
|
||||
samps = g_macsnd_rebuf_ptr - g_macsnd_rebuf_cur;
|
||||
if(samps < 0) {
|
||||
samps += MACSND_REBUF_SIZE;
|
||||
}
|
||||
|
||||
samps = samps & -(MACSND_QUANTA); // quantize to 1024 samples
|
||||
if(g_macsnd_rebuf_cur + samps > &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
|
||||
samps = &(g_macsnd_rebuf[MACSND_REBUF_SIZE]) -
|
||||
g_macsnd_rebuf_cur;
|
||||
}
|
||||
if(samps > 0) {
|
||||
g_macsnd_playing = 1;
|
||||
g_snd_hdr.numFrames = samps;
|
||||
g_snd_hdr.loopEnd = samps;
|
||||
g_snd_hdr.samplePtr = (byte *)g_macsnd_rebuf_cur;
|
||||
|
||||
g_snd_cmd.cmd = bufferCmd;
|
||||
g_snd_cmd.param1 = 0;
|
||||
g_snd_cmd.param2 = (long) &g_snd_hdr;
|
||||
|
||||
g_macsnd_rebuf_cur += samps;
|
||||
if(g_macsnd_rebuf_cur >= &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
|
||||
g_macsnd_rebuf_cur -= MACSND_REBUF_SIZE;
|
||||
}
|
||||
|
||||
err = SndDoImmediate(g_snd_channel_ptr, &g_snd_cmd);
|
||||
|
||||
// And set-up callback
|
||||
g_snd_cmd.cmd = callBackCmd;
|
||||
g_snd_cmd.param1 = 0;
|
||||
g_snd_cmd.param2 = 0;
|
||||
err = SndDoCommand(g_snd_channel_ptr, &g_snd_cmd, TRUE);
|
||||
} else {
|
||||
g_macsnd_playing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mac_send_audio(byte *ptr, int in_size)
|
||||
{
|
||||
SndCommand snd_cmd = {0};
|
||||
word32 *wptr, *macptr;
|
||||
word32 *eptr;
|
||||
int samps;
|
||||
int i;
|
||||
|
||||
samps = in_size / 4;
|
||||
wptr = (word32 *)ptr;
|
||||
macptr = (word32 *)g_macsnd_rebuf_ptr;
|
||||
eptr = &g_macsnd_rebuf[MACSND_REBUF_SIZE];
|
||||
for(i = 0; i < samps; i++) {
|
||||
*macptr++ = *wptr++;
|
||||
if(macptr >= eptr) {
|
||||
macptr = &g_macsnd_rebuf[0];
|
||||
}
|
||||
}
|
||||
|
||||
g_macsnd_rebuf_ptr = macptr;
|
||||
|
||||
if(!g_macsnd_playing) {
|
||||
mac_snd_callback(g_snd_channel_ptr, &snd_cmd);
|
||||
}
|
||||
|
||||
return in_size;
|
||||
}
|
||||
|
||||
void
|
||||
child_sound_init_mac()
|
||||
{
|
||||
OSStatus err;
|
||||
|
||||
mac_printf("In mac child\n");
|
||||
fflush(stdout);
|
||||
mac_printf("pid: %d\n", getpid());
|
||||
fflush(stdout);
|
||||
|
||||
//return;
|
||||
|
||||
//g_snd_channel_ptr = 0;
|
||||
err = SndNewChannel(&g_snd_channel_ptr, sampledSynth, initStereo,
|
||||
NewSndCallBackUPP(mac_snd_callback));
|
||||
mac_printf("SndNewChannel ret: %d\n", (int)err);
|
||||
fflush(stdout);
|
||||
|
||||
memset(&g_snd_hdr, 0, sizeof(g_snd_hdr));
|
||||
g_snd_hdr.sampleSize = 16;
|
||||
g_snd_hdr.numChannels = 2;
|
||||
g_audio_rate = 44100;
|
||||
g_snd_hdr.sampleRate = g_audio_rate << 16;
|
||||
g_snd_hdr.numFrames = 0; // will be set in mac_send_audio
|
||||
g_snd_hdr.encode = extSH;
|
||||
g_snd_hdr.baseFrequency = 0;
|
||||
g_snd_hdr.samplePtr = 0;
|
||||
|
||||
set_audio_rate(g_audio_rate);
|
||||
|
||||
mac_printf("End of child_sound_init_mac\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void
|
||||
macsnd_init(word32 *shmaddr)
|
||||
{
|
||||
g_macsnd_rebuf_cur = &g_macsnd_rebuf[0];
|
||||
g_macsnd_rebuf_ptr = &g_macsnd_rebuf[0];
|
||||
mac_printf("macsnd_init called\n");
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/local/bin/perl -w
|
||||
|
||||
# $KmKId: make_inst,v 1.5 2002-11-07 08:18:16-08 kadickey Exp $
|
||||
|
||||
$is_c = shift;
|
||||
$repl = shift;
|
||||
|
||||
$count = 0;
|
||||
|
||||
while(<>) {
|
||||
$line = $_;
|
||||
if(/^inst(..)_SYM(.*)$/) {
|
||||
if($is_c eq "c") {
|
||||
if($count > 0) {
|
||||
printf("\tbreak;\n");
|
||||
}
|
||||
print "case 0x$1: $2\n";
|
||||
$count++;
|
||||
} else {
|
||||
print "\t.align\t8\n";
|
||||
print "inst" . "$1" . "_$repl" . "$2\n";
|
||||
}
|
||||
} elsif(/^(.*)_SYM(.*)$/) {
|
||||
print "$1" . "_$repl" . "$2\n";
|
||||
} else {
|
||||
print $line;
|
||||
}
|
||||
}
|
||||
# if(/^inst(..)_SYM (.*)$/) {
|
||||
# print "OPCODE($1) /* $2 */\n";
|
||||
# } else if(/^(
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/local/bin/perl -w
|
||||
# $KmKId: make_size,v 1.3 2002-11-07 08:18:16-08 kadickey Exp $
|
||||
|
||||
$repl = shift;
|
||||
|
||||
while(<>) {
|
||||
$line = $_;
|
||||
if(/\.word inst(..)_SYM\+(.)(.*)$/) {
|
||||
if($repl eq "c") {
|
||||
print "\t0x$2, /* $1 */ $3\n";
|
||||
} elsif($repl eq "s") {
|
||||
print "\t.byte 0x$2, /* $1 */ $3\n";
|
||||
} else {
|
||||
print "\t.word\tinst$1" . "_$repl" . "\t/*$2*/ $3\n";
|
||||
}
|
||||
} elsif (/\.block.*$/) {
|
||||
if($repl eq "c") {
|
||||
print "\n";
|
||||
} elsif($repl eq "s") {
|
||||
print "\n";
|
||||
} else {
|
||||
print $line;
|
||||
}
|
||||
} else {
|
||||
print $line;
|
||||
}
|
||||
}
|
||||
# if(/^inst(..)_SYM (.*)$/) {
|
||||
# print "OPCODE($1) /* $2 */\n";
|
||||
# } else if(/^(
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
export PATH="/mingw/bin:${PATH}"
|
||||
make
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,169 @@
|
|||
<?xml version="1.0" standalone="yes"?>
|
||||
<object class="NSIBObjectData">
|
||||
<string name="targetFramework">IBCarbonFramework</string>
|
||||
<object name="rootObject" class="NSCustomObject" id="1">
|
||||
<string name="customClass">NSApplication</string>
|
||||
</object>
|
||||
<array count="18" name="allObjects">
|
||||
<object class="IBCarbonMenu" id="29">
|
||||
<string name="title">main</string>
|
||||
<array count="3" name="items">
|
||||
<object class="IBCarbonMenuItem" id="185">
|
||||
<string name="title">KEGSMAC</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="184">
|
||||
<string name="title">KEGSMAC</string>
|
||||
<array count="3" name="items">
|
||||
<object class="IBCarbonMenuItem" id="187">
|
||||
<string name="title">About KEGSMAC</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">abou</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="199">
|
||||
<boolean name="separator">TRUE</boolean>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="198">
|
||||
<string name="title">Quit</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">quit</ostype>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSAppleMenu</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="127">
|
||||
<string name="title">File</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="131">
|
||||
<string name="title">File</string>
|
||||
<array count="1" name="items">
|
||||
<object class="IBCarbonMenuItem" id="200">
|
||||
<string name="title">Configuration F4</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">KCFG</ostype>
|
||||
<string name="helpTagText">Enter KEGS Configuration Panel</string>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="192">
|
||||
<string name="title">Window</string>
|
||||
<object name="submenu" class="IBCarbonMenu" id="195">
|
||||
<string name="title">Window</string>
|
||||
<array count="6" name="items">
|
||||
<object class="IBCarbonMenuItem" id="197">
|
||||
<string name="title">Zoom Window</string>
|
||||
<ostype name="command">zoom</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="190">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Minimize Window</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">mini</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="191">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Minimize All Windows</string>
|
||||
<int name="keyEquivalentModifier">0</int>
|
||||
<ostype name="command">mina</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="194">
|
||||
<boolean name="separator">TRUE</boolean>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="196">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Bring All to Front</string>
|
||||
<ostype name="command">bfrt</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem" id="193">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Arrange in Front</string>
|
||||
<int name="keyEquivalentModifier">1572864</int>
|
||||
<ostype name="command">frnt</ostype>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSWindowsMenu</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSMainMenu</string>
|
||||
</object>
|
||||
<reference idRef="127"/>
|
||||
<reference idRef="131"/>
|
||||
<object class="IBCarbonMenuItem" id="153">
|
||||
<string name="title">Window</string>
|
||||
<object name="submenu" class="IBCarbonMenu">
|
||||
<string name="title">Window</string>
|
||||
<array count="5" name="items">
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Minimize Window</string>
|
||||
<string name="keyEquivalent">m</string>
|
||||
<ostype name="command">mini</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Minimize All Windows</string>
|
||||
<string name="keyEquivalent">m</string>
|
||||
<int name="keyEquivalentModifier">1572864</int>
|
||||
<ostype name="command">mini</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="separator">TRUE</boolean>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Bring All to Front</string>
|
||||
<ostype name="command">frnt</ostype>
|
||||
</object>
|
||||
<object class="IBCarbonMenuItem">
|
||||
<boolean name="dynamic">TRUE</boolean>
|
||||
<string name="title">Bring in Front</string>
|
||||
<int name="keyEquivalentModifier">1572864</int>
|
||||
<ostype name="command">frnt</ostype>
|
||||
</object>
|
||||
</array>
|
||||
<string name="name">_NSWindowsMenu</string>
|
||||
</object>
|
||||
</object>
|
||||
<reference idRef="184"/>
|
||||
<reference idRef="185"/>
|
||||
<reference idRef="187"/>
|
||||
<reference idRef="190"/>
|
||||
<reference idRef="191"/>
|
||||
<reference idRef="192"/>
|
||||
<reference idRef="193"/>
|
||||
<reference idRef="194"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="196"/>
|
||||
<reference idRef="197"/>
|
||||
<reference idRef="198"/>
|
||||
<reference idRef="199"/>
|
||||
<reference idRef="200"/>
|
||||
</array>
|
||||
<array count="18" name="allParents">
|
||||
<reference idRef="1"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="127"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="185"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="184"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="29"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="192"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="195"/>
|
||||
<reference idRef="184"/>
|
||||
<reference idRef="184"/>
|
||||
<reference idRef="131"/>
|
||||
</array>
|
||||
<dictionary count="2" name="nameTable">
|
||||
<string>Files Owner</string>
|
||||
<reference idRef="1"/>
|
||||
<string>MenuBar</string>
|
||||
<reference idRef="29"/>
|
||||
</dictionary>
|
||||
<unsigned_int name="nextObjectID">201</unsigned_int>
|
||||
</object>
|
|
@ -0,0 +1,466 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef ASM
|
||||
# ifdef INCLUDE_RCSID_S
|
||||
.data
|
||||
.export rcsdif_op_routs_h,data
|
||||
rcsdif_op_routs_h
|
||||
.stringz "@(#)$KmKId: op_routs.h,v 1.40 2004-01-10 15:49:46-05 kentd Exp $"
|
||||
.code
|
||||
# endif
|
||||
|
||||
.import get_mem_b0_16,code
|
||||
.import get_mem_b0_8,code
|
||||
|
||||
.export op_routs_start,data
|
||||
op_routs_start .word 0
|
||||
#endif /* ASM */
|
||||
|
||||
#ifdef ASM
|
||||
# define CMP_INDEX_REG_MEAT8(index_reg) \
|
||||
extru ret0,31,8,ret0 ! \
|
||||
ldi 0xff,scratch3 ! \
|
||||
subi 0x100,ret0,ret0 ! \
|
||||
add index_reg,ret0,ret0 ! \
|
||||
extru ret0,23,1,scratch1 ! \
|
||||
and ret0,scratch3,zero ! \
|
||||
extru ret0,24,1,neg ! \
|
||||
b dispatch ! \
|
||||
dep scratch1,31,1,psr
|
||||
|
||||
# define CMP_INDEX_REG_MEAT16(index_reg) \
|
||||
extru ret0,31,16,ret0 ! \
|
||||
ldil l%0x10000,scratch2 ! \
|
||||
zdepi -1,31,16,scratch3 ! \
|
||||
sub scratch2,ret0,ret0 ! \
|
||||
add index_reg,ret0,ret0 ! \
|
||||
extru ret0,15,1,scratch1 ! \
|
||||
and ret0,scratch3,zero ! \
|
||||
extru ret0,16,1,neg ! \
|
||||
b dispatch ! \
|
||||
dep scratch1,31,1,psr
|
||||
|
||||
# define CMP_INDEX_REG_LOAD(new_label, index_reg) \
|
||||
bb,>=,n psr,27,new_label ! \
|
||||
bl get_mem_long_8,link ! \
|
||||
nop ! \
|
||||
CMP_INDEX_REG_MEAT8(index_reg) ! \
|
||||
.label new_label ! \
|
||||
bl get_mem_long_16,link ! \
|
||||
nop ! \
|
||||
CMP_INDEX_REG_MEAT16(index_reg)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
#define GET_DLOC_X_IND_WR() \
|
||||
CYCLES_PLUS_1 ! \
|
||||
add xreg,direct,scratch2 ! \
|
||||
INC_KPC_2 ! \
|
||||
add scratch2,arg0,arg0 ! \
|
||||
bl get_mem_b0_direct_page_16,link ! \
|
||||
extru arg0,31,16,arg0 ! \
|
||||
copy ret0,arg0 ! \
|
||||
extru,= direct,31,8,0 ! \
|
||||
CYCLES_PLUS_1 ! \
|
||||
dep dbank,15,8,arg0
|
||||
#else /* C */
|
||||
# define GET_DLOC_X_IND_WR() \
|
||||
CYCLES_PLUS_1; \
|
||||
INC_KPC_2; \
|
||||
if(direct & 0xff) { \
|
||||
CYCLES_PLUS_1; \
|
||||
} \
|
||||
arg = arg + xreg + direct; \
|
||||
GET_MEMORY_DIRECT_PAGE16(arg & 0xffff, arg); \
|
||||
arg = (dbank << 16) + arg;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DLOC_X_IND_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
GET_DLOC_X_IND_WR()
|
||||
#else /* C */
|
||||
# define GET_DLOC_X_IND_ADDR() \
|
||||
GET_1BYTE_ARG; \
|
||||
GET_DLOC_X_IND_WR()
|
||||
#endif
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DISP8_S_WR() \
|
||||
CYCLES_PLUS_1 ! \
|
||||
add stack,arg0,arg0 ! \
|
||||
INC_KPC_2 ! \
|
||||
extru arg0,31,16,arg0
|
||||
#else /* C */
|
||||
#define GET_DISP8_S_WR() \
|
||||
CYCLES_PLUS_1; \
|
||||
arg = (arg + stack) & 0xffff; \
|
||||
INC_KPC_2;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DISP8_S_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
GET_DISP8_S_WR()
|
||||
#else /* C */
|
||||
# define GET_DISP8_S_ADDR() \
|
||||
GET_1BYTE_ARG; \
|
||||
GET_DISP8_S_WR()
|
||||
#endif
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DLOC_WR() \
|
||||
INC_KPC_2 ! \
|
||||
extru,= direct,31,8,0 ! \
|
||||
CYCLES_PLUS_1 ! \
|
||||
add direct,arg0,arg0 ! \
|
||||
extru arg0,31,16,arg0
|
||||
#else /* C */
|
||||
# define GET_DLOC_WR() \
|
||||
arg = (arg + direct) & 0xffff; \
|
||||
if(direct & 0xff) { \
|
||||
CYCLES_PLUS_1; \
|
||||
} \
|
||||
INC_KPC_2;
|
||||
#endif
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DLOC_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
GET_DLOC_WR()
|
||||
#else /* C */
|
||||
# define GET_DLOC_ADDR() \
|
||||
GET_1BYTE_ARG; \
|
||||
GET_DLOC_WR()
|
||||
#endif
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DLOC_L_IND_WR() \
|
||||
INC_KPC_2 ! \
|
||||
extru,= direct,31,8,0 ! \
|
||||
CYCLES_PLUS_1 ! \
|
||||
add direct,arg0,arg0 ! \
|
||||
bl get_mem_b0_24,link ! \
|
||||
extru arg0,31,16,arg0 ! \
|
||||
copy ret0,arg0
|
||||
#else /* C */
|
||||
# define GET_DLOC_L_IND_WR() \
|
||||
arg = (arg + direct) & 0xffff; \
|
||||
if(direct & 0xff) { \
|
||||
CYCLES_PLUS_1; \
|
||||
} \
|
||||
INC_KPC_2; \
|
||||
GET_MEMORY24(arg, arg, 1);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DLOC_L_IND_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
GET_DLOC_L_IND_WR()
|
||||
#else /* C */
|
||||
# define GET_DLOC_L_IND_ADDR() \
|
||||
GET_1BYTE_ARG; \
|
||||
GET_DLOC_L_IND_WR()
|
||||
#endif
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DLOC_IND_Y_ADDR_FOR_WR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
CYCLES_PLUS_1 ! \
|
||||
GET_DLOC_IND_Y_WR_SPECIAL()
|
||||
#else /* C */
|
||||
# define GET_DLOC_IND_Y_ADDR_FOR_WR() \
|
||||
GET_1BYTE_ARG; \
|
||||
if(direct & 0xff) { \
|
||||
CYCLES_PLUS_1; \
|
||||
} \
|
||||
GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, tmp1); \
|
||||
tmp1 += (dbank << 16); \
|
||||
arg = tmp1 + yreg; \
|
||||
CYCLES_PLUS_1; \
|
||||
INC_KPC_2;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DLOC_IND_WR() \
|
||||
extru,= direct,31,8,0 ! \
|
||||
CYCLES_PLUS_1 ! \
|
||||
INC_KPC_2 ! \
|
||||
add direct,arg0,arg0 ! \
|
||||
bl get_mem_b0_direct_page_16,link ! \
|
||||
extru arg0,31,16,arg0 ! \
|
||||
copy ret0,arg0 ! \
|
||||
dep dbank,15,16,arg0
|
||||
#else /* C */
|
||||
# define GET_DLOC_IND_WR() \
|
||||
INC_KPC_2; \
|
||||
if(direct & 0xff) { \
|
||||
CYCLES_PLUS_1; \
|
||||
} \
|
||||
GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, arg); \
|
||||
arg = (dbank << 16) + arg;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DLOC_IND_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
GET_DLOC_IND_WR()
|
||||
#else
|
||||
# define GET_DLOC_IND_ADDR() \
|
||||
GET_1BYTE_ARG; \
|
||||
GET_DLOC_IND_WR();
|
||||
#endif
|
||||
|
||||
#ifdef ASM
|
||||
#define GET_DLOC_INDEX_WR(index_reg) \
|
||||
GET_DLOC_INDEX_WR_A(index_reg) ! GET_DLOC_INDEX_WR_B(index_reg)
|
||||
|
||||
#define GET_DLOC_INDEX_WR_A(index_reg) \
|
||||
CYCLES_PLUS_1 ! \
|
||||
add index_reg,direct,scratch2 ! \
|
||||
extru direct,23,8,scratch1 ! \
|
||||
INC_KPC_2 ! \
|
||||
extru,= direct,31,8,0 ! \
|
||||
CYCLES_PLUS_1 ! \
|
||||
bb,>= psr,23,.+16 ! \
|
||||
/* 4*/ add scratch2,arg0,arg0 ! \
|
||||
/* 8*/ extru,<> direct,31,8,0 ! \
|
||||
/*12*/ dep scratch1,23,8,arg0
|
||||
|
||||
/* GET_DLOC_INDeX_WR_B must be exactly one instruction! */
|
||||
#define GET_DLOC_INDEX_WR_B(index_reg) \
|
||||
/*16*/ extru arg0,31,16,arg0
|
||||
|
||||
#define GET_DLOC_Y_WR() \
|
||||
GET_DLOC_INDEX_WR(yreg)
|
||||
|
||||
#define GET_DLOC_X_WR() \
|
||||
GET_DLOC_INDEX_WR(xreg)
|
||||
|
||||
#define GET_DLOC_Y_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
GET_DLOC_Y_WR()
|
||||
|
||||
# define GET_DLOC_X_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
GET_DLOC_X_WR()
|
||||
|
||||
#else
|
||||
# define GET_DLOC_INDEX_WR(index_reg) \
|
||||
CYCLES_PLUS_1; \
|
||||
arg = (arg & 0xff) + index_reg; \
|
||||
INC_KPC_2; \
|
||||
if(direct & 0xff) { \
|
||||
CYCLES_PLUS_1; \
|
||||
} \
|
||||
if((psr & 0x100) && ((direct & 0xff) == 0)) { \
|
||||
arg = (arg & 0xff); \
|
||||
} \
|
||||
arg = (arg + direct) & 0xffff;
|
||||
|
||||
# define GET_DLOC_X_WR() \
|
||||
GET_DLOC_INDEX_WR(xreg)
|
||||
# define GET_DLOC_Y_WR() \
|
||||
GET_DLOC_INDEX_WR(yreg)
|
||||
|
||||
# define GET_DLOC_X_ADDR() \
|
||||
GET_1BYTE_ARG; \
|
||||
GET_DLOC_INDEX_WR(xreg)
|
||||
|
||||
# define GET_DLOC_Y_ADDR() \
|
||||
GET_1BYTE_ARG; \
|
||||
GET_DLOC_INDEX_WR(yreg)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DISP8_S_IND_Y_WR() \
|
||||
add stack,arg0,arg0 ! \
|
||||
bl get_mem_b0_16,link ! \
|
||||
extru arg0,31,16,arg0 ! \
|
||||
dep dbank,15,16,ret0 ! \
|
||||
CYCLES_PLUS_2 ! \
|
||||
add ret0,yreg,arg0 ! \
|
||||
INC_KPC_2 ! \
|
||||
extru arg0,31,24,arg0
|
||||
|
||||
# define GET_DISP8_S_IND_Y_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
GET_DISP8_S_IND_Y_WR()
|
||||
#else /* C */
|
||||
|
||||
# define GET_DISP8_S_IND_Y_WR() \
|
||||
arg = (stack + arg) & 0xffff; \
|
||||
GET_MEMORY16(arg,arg,1); \
|
||||
CYCLES_PLUS_2; \
|
||||
arg += (dbank << 16); \
|
||||
INC_KPC_2; \
|
||||
arg = (arg + yreg) & 0xffffff;
|
||||
|
||||
# define GET_DISP8_S_IND_Y_ADDR() \
|
||||
GET_1BYTE_ARG; \
|
||||
GET_DISP8_S_IND_Y_WR()
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_DLOC_L_IND_Y_WR() \
|
||||
extru,= direct,31,8,0 ! \
|
||||
CYCLES_PLUS_1 ! \
|
||||
INC_KPC_2 ! \
|
||||
add direct,arg0,arg0 ! \
|
||||
bl get_mem_b0_24,link ! \
|
||||
extru arg0,31,16,arg0 ! \
|
||||
add ret0,yreg,arg0 ! \
|
||||
extru arg0,31,24,arg0
|
||||
|
||||
# define GET_DLOC_L_IND_Y_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
GET_DLOC_L_IND_Y_WR()
|
||||
#else /* C */
|
||||
|
||||
# define GET_DLOC_L_IND_Y_WR() \
|
||||
arg = (direct + arg) & 0xffff; \
|
||||
if(direct & 0xff) { \
|
||||
CYCLES_PLUS_1; \
|
||||
} \
|
||||
GET_MEMORY24(arg,arg,1); \
|
||||
INC_KPC_2; \
|
||||
arg = (arg + yreg) & 0xffffff;
|
||||
|
||||
# define GET_DLOC_L_IND_Y_ADDR() \
|
||||
GET_1BYTE_ARG; \
|
||||
GET_DLOC_L_IND_Y_WR()
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
# define GET_ABS_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
ldb 2(scratch1),scratch1 ! \
|
||||
CYCLES_PLUS_1 ! \
|
||||
dep dbank,15,8,arg0 ! \
|
||||
INC_KPC_3 ! \
|
||||
dep scratch1,23,8,arg0
|
||||
|
||||
# define GET_LONG_ADDR() \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
ldb 2(scratch1),scratch2 ! \
|
||||
CYCLES_PLUS_2 ! \
|
||||
ldb 3(scratch1),scratch1 ! \
|
||||
INC_KPC_4 ! \
|
||||
dep scratch2,23,8,arg0 ! \
|
||||
dep scratch1,15,8,arg0
|
||||
#else /* C */
|
||||
|
||||
# define GET_ABS_ADDR() \
|
||||
GET_2BYTE_ARG; \
|
||||
CYCLES_PLUS_1; \
|
||||
arg = arg + (dbank << 16); \
|
||||
INC_KPC_3;
|
||||
|
||||
# define GET_LONG_ADDR() \
|
||||
GET_3BYTE_ARG; \
|
||||
CYCLES_PLUS_2; \
|
||||
INC_KPC_4;
|
||||
#endif
|
||||
|
||||
#ifdef ASM
|
||||
#define GET_ABS_INDEX_ADDR_FOR_WR(index_reg) \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
copy index_reg,scratch3 ! \
|
||||
ldb 2(scratch1),scratch2 ! \
|
||||
dep dbank,15,8,scratch3 ! \
|
||||
INC_KPC_3 ! \
|
||||
dep scratch2,23,8,arg0 ! \
|
||||
CYCLES_PLUS_2 ! \
|
||||
add arg0,scratch3,arg0 ! \
|
||||
extru arg0,31,24,arg0
|
||||
|
||||
#define GET_LONG_X_ADDR_FOR_WR() \
|
||||
ldb 3(scratch1),scratch2 ! \
|
||||
copy xreg,scratch3 ! \
|
||||
ldb 1(scratch1),arg0 ! \
|
||||
ldb 2(scratch1),scratch1 ! \
|
||||
CYCLES_PLUS_2 ! \
|
||||
dep scratch2,15,8,scratch3 ! \
|
||||
INC_KPC_4 ! \
|
||||
dep scratch1,23,8,arg0 ! \
|
||||
add arg0,scratch3,arg0 ! \
|
||||
extru arg0,31,24,arg0
|
||||
#else /* C */
|
||||
|
||||
#define GET_ABS_INDEX_ADDR_FOR_WR(index_reg) \
|
||||
GET_2BYTE_ARG; \
|
||||
arg = arg + (dbank << 16); \
|
||||
INC_KPC_3; \
|
||||
CYCLES_PLUS_2; \
|
||||
arg = (arg + index_reg) & 0xffffff;
|
||||
|
||||
#define GET_LONG_X_ADDR_FOR_WR() \
|
||||
GET_3BYTE_ARG; \
|
||||
INC_KPC_4; \
|
||||
arg = (arg + xreg) & 0xffffff; \
|
||||
CYCLES_PLUS_2;
|
||||
|
||||
#endif /* ASM */
|
||||
|
||||
|
||||
#ifdef ASM
|
||||
.export op_routs_end,data
|
||||
op_routs_end .word 0
|
||||
|
||||
|
||||
#define GET_DLOC_IND_Y_WR_SPECIAL() \
|
||||
add direct,arg0,arg0 ! \
|
||||
extru,= direct,31,8,0 ! \
|
||||
CYCLES_PLUS_1 ! \
|
||||
bl get_mem_b0_direct_page_16,link ! \
|
||||
extru arg0,31,16,arg0 ! \
|
||||
dep dbank,15,8,ret0 ! \
|
||||
INC_KPC_2 ! \
|
||||
add yreg,ret0,arg0 /* don't change this instr */
|
||||
/* or add any after */
|
||||
/* to preserve ret0 & arg0 */
|
||||
|
||||
|
||||
/* cycle calc: if yreg is 16bit or carry into 2nd byte, inc cycle */
|
||||
/* So, if y==16bit, add 1. If x==8bit, add 1 if carry */
|
||||
get_dloc_ind_y_rd_8
|
||||
stw link,STACK_SAVE_OP_LINK(sp)
|
||||
GET_DLOC_IND_Y_WR_SPECIAL()
|
||||
xor arg0,ret0,scratch1
|
||||
extru,= psr,27,1,0
|
||||
extru,= scratch1,23,8,0
|
||||
CYCLES_PLUS_1
|
||||
b get_mem_long_8
|
||||
ldw STACK_SAVE_OP_LINK(sp),link
|
||||
|
||||
get_dloc_ind_y_rd_16
|
||||
stw link,STACK_SAVE_OP_LINK(sp)
|
||||
GET_DLOC_IND_Y_WR_SPECIAL()
|
||||
xor arg0,ret0,scratch1
|
||||
extru,= psr,27,1,0
|
||||
extru,= scratch1,23,8,0
|
||||
CYCLES_PLUS_1
|
||||
b get_mem_long_16
|
||||
ldw STACK_SAVE_OP_LINK(sp),link
|
||||
|
||||
|
||||
|
||||
#endif /* ASM */
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_paddles_c[] = "@(#)$KmKId: paddles.c,v 1.7 2004-03-23 17:28:06-05 kentd Exp $";
|
||||
|
||||
#include "defc.h"
|
||||
|
||||
extern int g_mouse_fifo_x[]; /* from adb.c */
|
||||
extern int g_mouse_fifo_y[];
|
||||
|
||||
double g_paddle_trig_dcycs = 0.0;
|
||||
int g_swap_paddles = 0;
|
||||
int g_invert_paddles = 0;
|
||||
|
||||
int g_joystick_type = JOYSTICK_MOUSE;
|
||||
|
||||
int g_paddle_button[4] = { 0, 0, 0, 0 };
|
||||
/* g_paddle_button[0] = button 0, etc */
|
||||
|
||||
int g_paddle_val[4] = { 0, 0, 0, 0 };
|
||||
/* g_paddle_val[0]: Joystick X coord, [1]:Y coord */
|
||||
|
||||
|
||||
void
|
||||
paddle_trigger(double dcycs)
|
||||
{
|
||||
/* Called by read/write to $c070 */
|
||||
g_paddle_trig_dcycs = dcycs;
|
||||
|
||||
/* Determine what all the paddle values are right now */
|
||||
|
||||
switch(g_joystick_type) {
|
||||
case JOYSTICK_MOUSE:
|
||||
paddle_trigger_mouse(dcycs);
|
||||
break;
|
||||
case JOYSTICK_LINUX:
|
||||
case JOYSTICK_WIN32_1:
|
||||
case JOYSTICK_WIN32_2:
|
||||
joystick_update();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
paddle_trigger_mouse(double dcycs)
|
||||
{
|
||||
int val_x;
|
||||
int val_y;
|
||||
|
||||
val_x = 0;
|
||||
/* mous_phys_x is 0->560, convert that to 0-255 cyc */
|
||||
/* so, mult by 117 then divide by 256 */
|
||||
if(g_mouse_fifo_x[0] > BASE_MARGIN_LEFT) {
|
||||
val_x = (g_mouse_fifo_x[0] - BASE_MARGIN_LEFT) * 117;
|
||||
val_x = val_x >> 8;
|
||||
}
|
||||
|
||||
/* mous_phys_y is 0->384, convert that to 0-255 cyc */
|
||||
/* so, mult by 170 then divide by 256 (shift right by 8) */
|
||||
val_y = 0;
|
||||
if(g_mouse_fifo_y[0] > BASE_MARGIN_TOP) {
|
||||
val_y = ((g_mouse_fifo_y[0] - BASE_MARGIN_TOP) * 170) >> 8;
|
||||
}
|
||||
|
||||
if(val_x > 280) {
|
||||
val_x = 280;
|
||||
}
|
||||
if(val_y > 280) {
|
||||
val_y = 280;
|
||||
}
|
||||
|
||||
g_paddle_val[0] = val_x;
|
||||
g_paddle_val[1] = val_y;
|
||||
g_paddle_val[2] = 255;
|
||||
g_paddle_val[3] = 255;
|
||||
g_paddle_button[2] = 1;
|
||||
g_paddle_button[3] = 1;
|
||||
}
|
||||
|
||||
int
|
||||
read_paddles(int paddle, double dcycs)
|
||||
{
|
||||
double trig_dcycs;
|
||||
int val;
|
||||
|
||||
/* This routine is called by any read to $c064-$c067 */
|
||||
if(g_swap_paddles) {
|
||||
paddle = paddle ^ 1;
|
||||
}
|
||||
|
||||
paddle = paddle & 3;
|
||||
|
||||
val = g_paddle_val[paddle];
|
||||
|
||||
if(g_invert_paddles) {
|
||||
val = 255 - val;
|
||||
}
|
||||
|
||||
/* convert 0->255 into 0->2816.0 cycles (the paddle delay const) */
|
||||
trig_dcycs = g_paddle_trig_dcycs + (val * 11.0);
|
||||
|
||||
if(dcycs < trig_dcycs) {
|
||||
return 0x80;
|
||||
} else {
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
|
||||
#include "defc.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#define BUF_SIZE 65536
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
void
|
||||
read_block(int fd, char *buf, int blk, int blk_size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = lseek(fd, blk * blk_size, SEEK_SET);
|
||||
if(ret != blk * blk_size) {
|
||||
printf("lseek: %d, errno: %d\n", ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read(fd, buf, blk_size);
|
||||
if(ret != blk_size) {
|
||||
printf("ret: %d, errno: %d\n", ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
Driver_desc *driver_desc_ptr;
|
||||
Part_map *part_map_ptr;
|
||||
double dsize;
|
||||
int fd;
|
||||
int block_size;
|
||||
word32 sig;
|
||||
word32 map_blk_cnt;
|
||||
word32 phys_part_start;
|
||||
word32 part_blk_cnt;
|
||||
word32 data_start;
|
||||
word32 data_cnt;
|
||||
int map_blocks;
|
||||
int cur;
|
||||
int long_form;
|
||||
int last_arg;
|
||||
int i;
|
||||
|
||||
/* parse args */
|
||||
long_form = 0;
|
||||
last_arg = 1;
|
||||
for(i = 1; i < argc; i++) {
|
||||
if(!strcmp("-l", argv[i])) {
|
||||
long_form = 1;
|
||||
} else {
|
||||
last_arg = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fd = open(argv[last_arg], O_RDONLY | O_BINARY, 0x1b6);
|
||||
if(fd < 0) {
|
||||
printf("open %s, ret: %d, errno:%d\n", argv[last_arg],fd,errno);
|
||||
exit(1);
|
||||
}
|
||||
if(long_form) {
|
||||
printf("fd: %d\n", fd);
|
||||
}
|
||||
|
||||
block_size = 512;
|
||||
read_block(fd, buf, 0, block_size);
|
||||
|
||||
driver_desc_ptr = (Driver_desc *)buf;
|
||||
sig = GET_BE_WORD16(driver_desc_ptr->sig);
|
||||
block_size = GET_BE_WORD16(driver_desc_ptr->blk_size);
|
||||
if(long_form) {
|
||||
printf("sig: %04x, blksize: %04x\n", sig, block_size);
|
||||
}
|
||||
if(block_size == 0) {
|
||||
block_size = 512;
|
||||
}
|
||||
|
||||
if(sig == 0x4552 && block_size >= 0x200) {
|
||||
if(long_form) {
|
||||
printf("good!\n");
|
||||
}
|
||||
} else {
|
||||
printf("bad sig:%04x or block_size:%04x!\n", sig, block_size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
map_blocks = 1;
|
||||
cur = 0;
|
||||
while(cur < map_blocks) {
|
||||
read_block(fd, buf, cur + 1, block_size);
|
||||
part_map_ptr = (Part_map *)buf;
|
||||
sig = GET_BE_WORD16(part_map_ptr->sig);
|
||||
map_blk_cnt = GET_BE_WORD32(part_map_ptr->map_blk_cnt);
|
||||
phys_part_start = GET_BE_WORD32(part_map_ptr->phys_part_start);
|
||||
part_blk_cnt = GET_BE_WORD32(part_map_ptr->part_blk_cnt);
|
||||
data_start = GET_BE_WORD32(part_map_ptr->data_start);
|
||||
data_cnt = GET_BE_WORD32(part_map_ptr->data_cnt);
|
||||
|
||||
if(cur == 0) {
|
||||
map_blocks = MIN(100, map_blk_cnt);
|
||||
}
|
||||
|
||||
if(long_form) {
|
||||
printf("%2d: sig: %04x, map_blk_cnt: %d, "
|
||||
"phys_part_start: %08x, part_blk_cnt: %08x\n",
|
||||
cur, sig, map_blk_cnt, phys_part_start,
|
||||
part_blk_cnt);
|
||||
printf(" part_name: %s, part_type: %s\n",
|
||||
part_map_ptr->part_name,
|
||||
part_map_ptr->part_type);
|
||||
printf(" data_start:%08x, data_cnt:%08x status:%08x\n",
|
||||
GET_BE_WORD32(part_map_ptr->data_start),
|
||||
GET_BE_WORD32(part_map_ptr->data_cnt),
|
||||
GET_BE_WORD32(part_map_ptr->part_status));
|
||||
printf(" processor: %s\n", part_map_ptr->processor);
|
||||
} else {
|
||||
dsize = (double)GET_BE_WORD32(part_map_ptr->data_cnt);
|
||||
printf("%2d:%-20s size=%6.2fMB type=%s\n", cur,
|
||||
part_map_ptr->part_name,
|
||||
(dsize/(1024.0*2.0)),
|
||||
part_map_ptr->part_type);
|
||||
}
|
||||
|
||||
cur++;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/****************************************************************/
|
||||
/* Apple //gs emulator */
|
||||
/* Copyright 1996 Kent Dickey */
|
||||
/* */
|
||||
/* This code may not be used in a commercial product */
|
||||
/* without prior written permission of the author. */
|
||||
/* */
|
||||
/* You may freely distribute this code. */
|
||||
/* */
|
||||
/* You can contact the author at kentd@cup.hp.com. */
|
||||
/* HP has nothing to do with this software. */
|
||||
/****************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_C
|
||||
const char rcsid_defc_h[] = "@(#)$Id: prodos.h,v 1.4 2002/11/19 07:49:31 kadickey Exp $";
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct l2byte_st L2byte;
|
||||
struct l2byte_st {
|
||||
byte low;
|
||||
byte hi;
|
||||
};
|
||||
|
||||
typedef struct l3byte_st L3byte;
|
||||
struct l3byte_st {
|
||||
byte low;
|
||||
byte hi;
|
||||
byte higher;
|
||||
};
|
||||
|
||||
typedef L2byte Block;
|
||||
|
||||
typedef struct pro_time_st Pro_time;
|
||||
struct pro_time_st {
|
||||
byte times[4];
|
||||
};
|
||||
|
||||
typedef struct file_entry_st File_entry;
|
||||
struct file_entry_st {
|
||||
byte storage_type_name_len;
|
||||
byte file_name[15];
|
||||
/* 0x10 */
|
||||
byte file_type;
|
||||
Block key_pointer;
|
||||
/* 0x13 */
|
||||
L2byte blocks_used;
|
||||
/* 0x15 */
|
||||
L3byte eof;
|
||||
/* 0x18 */
|
||||
Pro_time creation_time;
|
||||
/* 0x1c */
|
||||
byte version;
|
||||
byte min_version;
|
||||
/* 0x1e */
|
||||
byte access;
|
||||
/* 0x1f */
|
||||
L2byte aux_type;
|
||||
/* 0x21 */
|
||||
Pro_time last_mod;
|
||||
/* 0x25 */
|
||||
Block header_pointer;
|
||||
};
|
||||
|
||||
STRUCT(Vol_hdr) {
|
||||
/* 0x4 */
|
||||
byte storage_type_name_len;
|
||||
/* 0x5 */
|
||||
byte vol_name[15];
|
||||
/* 0x14 */
|
||||
byte res1[8];
|
||||
/* 0x1c */
|
||||
Pro_time creation_time;
|
||||
/* 0x20 */
|
||||
byte version;
|
||||
byte min_version;
|
||||
byte access;
|
||||
byte entry_length;
|
||||
/* 0x24 */
|
||||
byte entries_per_block;
|
||||
L2byte file_count;
|
||||
/* 0x27 */
|
||||
Block bit_map;
|
||||
/* 0x29 */
|
||||
L2byte total_blocks;
|
||||
};
|
||||
|
||||
typedef struct directory_st Directory;
|
||||
struct directory_st {
|
||||
Block prev_blk;
|
||||
Block next_blk;
|
||||
File_entry file_entries[13];
|
||||
};
|
||||
|
||||
STRUCT(ProDisk) {
|
||||
int fd;
|
||||
int total_blocks;
|
||||
int size_bitmap_blocks;
|
||||
int disk_bytes_left;
|
||||
|
||||
int bitmap_bytes;
|
||||
int bitmap_cur_pos;
|
||||
byte *bitmap_ptr;
|
||||
|
||||
int file_open;
|
||||
File_entry *file_ptr;
|
||||
int dir_blk_num;
|
||||
int ind_blk_num;
|
||||
int master_ind_blk_num;
|
||||
byte dir_blk_data[512];
|
||||
byte ind_blk_data[512];
|
||||
byte master_ind_blk_data[512];
|
||||
};
|
||||
|
||||
|
||||
#include "prodos_protos.h"
|
|
@ -0,0 +1,46 @@
|
|||
/****************************************************************/
|
||||
/* Apple //gs emulator */
|
||||
/* Copyright 1996 Kent Dickey */
|
||||
/* */
|
||||
/* This code may not be used in a commercial product */
|
||||
/* without prior written permission of the author. */
|
||||
/* */
|
||||
/* You may freely distribute this code. */
|
||||
/* */
|
||||
/* You can contact the author at kentd@cup.hp.com. */
|
||||
/* HP has nothing to do with this software. */
|
||||
/****************************************************************/
|
||||
|
||||
const char rcsid_prodos_protos_h[] = "@(#)$Id: prodos_protos.h,v 1.4 2002/11/19 07:49:31 kadickey Exp $";
|
||||
|
||||
/* to_pro.c */
|
||||
void flush_disk(ProDisk *disk);
|
||||
void close_file(ProDisk *disk);
|
||||
ProDisk *allocate_memdisk(char *out_name, int size);
|
||||
void format_memdisk(ProDisk *ptr, char *name);
|
||||
void disk_write_data(ProDisk *disk, int blk_num, byte *buf, int size);
|
||||
void disk_read_data(ProDisk *disk, int blk_num, byte *buf, int size);
|
||||
Directory *disk_read_dir(ProDisk *disk, int blk_num);
|
||||
void disk_write_dir(ProDisk *disk, int blk_num);
|
||||
void create_new_file(ProDisk *disk, int dir_block, int storage_type,
|
||||
char *name, int file_type, word32 creation_time, int version,
|
||||
int min_version, int access, int aux_type, word32 last_mod, word32 eof);
|
||||
int pro_write_file(ProDisk *disk, byte *in_buf, int pos, int size);
|
||||
int get_disk_block(ProDisk *disk, int pos, int create);
|
||||
void get_new_ind_block(ProDisk *disk);
|
||||
void write_ind_block(ProDisk *disk);
|
||||
void get_new_master_ind_block(ProDisk *disk);
|
||||
void write_master_ind_block(ProDisk *disk);
|
||||
int find_next_free_block(ProDisk *disk);
|
||||
void set_bitmap_used(byte *ptr, int i);
|
||||
void set_bitmap_free(byte *ptr, int i);
|
||||
void set_file_entry(File_entry *entry, int storage_type_name_len,
|
||||
char *file_name, int file_type, int key_pointer, int blocks_used,
|
||||
int eof, word32 creation, int version, int min_version, int access,
|
||||
int aux_type, word32 last_mod, int header_pointer);
|
||||
void set_l2byte(L2byte *ptr, int val);
|
||||
void set_l3byte(L3byte *ptr, int val);
|
||||
void set_pro_time(Pro_time *ptr, word32 val);
|
||||
int get_l2byte(L2byte *ptr);
|
||||
int get_l3byte(L3byte *ptr);
|
||||
void inc_l2byte(L2byte *ptr);
|
|
@ -0,0 +1,495 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_C
|
||||
const char rcsid_protos_h[] = "@(#)$KmKId: protos.h,v 1.173 2004-03-23 17:26:19-05 kentd Exp $";
|
||||
#endif
|
||||
|
||||
/* xdriver.c and macdriver.c and windriver.c */
|
||||
void update_color_array(int col_num, int a2_color);
|
||||
void set_border_color(int val);
|
||||
void x_update_physical_colormap(void);
|
||||
void show_xcolor_array(void);
|
||||
void x_auto_repeat_on(int must);
|
||||
void install_text_colormap(void);
|
||||
void set_border_color(int val);
|
||||
void draw_status(int line_num, const char *string1);
|
||||
void xdriver_end(void);
|
||||
void dev_video_init(void);
|
||||
void x_update_color(int col_num, int red, int green, int blue, word32 rgb);
|
||||
void redraw_border(void);
|
||||
void check_input_events(void);
|
||||
void x_redraw_status_lines(void);
|
||||
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height);
|
||||
void x_push_done();
|
||||
void x_hide_pointer(int);
|
||||
void x_get_kimage(Kimage *kimage_ptr);
|
||||
|
||||
/* test65.c */
|
||||
void do_gen_test(int got_num, int base_seed);
|
||||
|
||||
|
||||
/* engine.s and engine_c.c */
|
||||
void fixed_memory_ptrs_init();
|
||||
word32 get_itimer(void);
|
||||
|
||||
word32 get_memory_c(word32 addr, int cycs);
|
||||
word32 get_memory16_c(word32 addr, int cycs);
|
||||
word32 get_memory24_c(word32 addr, int cycs);
|
||||
|
||||
int get_memory_asm(word32 addr, int cycs);
|
||||
int get_memory16_asm(word32 addr, int cycs);
|
||||
int get_memory16_asm_fail(word32 addr, int cycs);
|
||||
int get_memory_act_stub_asm(word32 addr, int cycs);
|
||||
int get_memory16_act_stub_asm(word32 addr, int cycs);
|
||||
|
||||
void set_memory_c(word32 addr, word32 val, int cycs);
|
||||
void set_memory16_c(word32 addr, word32 val, int cycs);
|
||||
|
||||
int enter_engine(Engine_reg *ptr);
|
||||
void clr_halt_act(void);
|
||||
void set_halt_act(int val);
|
||||
|
||||
/* special scc_macdriver.c prototypes */
|
||||
int scc_serial_mac_init(int port);
|
||||
void scc_serial_mac_change_params(int port);
|
||||
void scc_serial_mac_fill_readbuf(int port, double dcycs);
|
||||
void scc_serial_mac_empty_writebuf(int port);
|
||||
|
||||
/* special scc_windriver.c prototypes */
|
||||
int scc_serial_win_init(int port);
|
||||
void scc_serial_win_change_params(int port);
|
||||
void scc_serial_win_fill_readbuf(int port, double dcycs);
|
||||
void scc_serial_win_empty_writebuf(int port);
|
||||
|
||||
/* special joystick_driver.c prototypes */
|
||||
void joystick_init(void);
|
||||
void joystick_update(void);
|
||||
void joystick_update_button(void);
|
||||
|
||||
|
||||
/* END_HDR */
|
||||
|
||||
/* adb.c */
|
||||
void adb_init(void);
|
||||
void adb_reset(void);
|
||||
void adb_log(word32 addr, int val);
|
||||
void show_adb_log(void);
|
||||
void adb_error(void);
|
||||
void adb_add_kbd_srq(void);
|
||||
void adb_clear_kbd_srq(void);
|
||||
void adb_add_data_int(void);
|
||||
void adb_add_mouse_int(void);
|
||||
void adb_clear_data_int(void);
|
||||
void adb_clear_mouse_int(void);
|
||||
void adb_send_bytes(int num_bytes, word32 val0, word32 val1, word32 val2);
|
||||
void adb_send_1byte(word32 val);
|
||||
void adb_response_packet(int num_bytes, word32 val);
|
||||
void adb_kbd_reg0_data(int a2code, int is_up);
|
||||
void adb_kbd_talk_reg0(void);
|
||||
void adb_set_config(word32 val0, word32 val1, word32 val2);
|
||||
void adb_set_new_mode(word32 val);
|
||||
int adb_read_c026(void);
|
||||
void adb_write_c026(int val);
|
||||
void do_adb_cmd(void);
|
||||
int adb_read_c027(void);
|
||||
void adb_write_c027(int val);
|
||||
int read_adb_ram(word32 addr);
|
||||
void write_adb_ram(word32 addr, int val);
|
||||
int update_mouse(int x, int y, int button_states, int buttons_valid);
|
||||
int mouse_read_c024(double dcycs);
|
||||
void adb_key_event(int a2code, int is_up);
|
||||
word32 adb_read_c000(void);
|
||||
word32 adb_access_c010(void);
|
||||
word32 adb_read_c025(void);
|
||||
int adb_is_cmd_key_down(void);
|
||||
int adb_is_option_key_down(void);
|
||||
void adb_increment_speed(void);
|
||||
void adb_physical_key_update(int a2code, int is_up);
|
||||
void adb_virtual_key_update(int a2code, int is_up);
|
||||
void adb_kbd_repeat_off(void);
|
||||
|
||||
|
||||
/* clock.c */
|
||||
double get_dtime(void);
|
||||
int micro_sleep(double dtime);
|
||||
void clk_bram_zero(void);
|
||||
void clk_bram_set(int bram_num, int offset, int val);
|
||||
void clk_setup_bram_version(void);
|
||||
void clk_write_bram(FILE *fconf);
|
||||
void update_cur_time(void);
|
||||
void clock_update(void);
|
||||
void clock_update_if_needed(void);
|
||||
word32 clock_read_c033(void);
|
||||
word32 clock_read_c034(void);
|
||||
void clock_write_c033(word32 val);
|
||||
void clock_write_c034(word32 val);
|
||||
void do_clock_data(void);
|
||||
|
||||
|
||||
/* compile_time.c */
|
||||
|
||||
|
||||
/* config.c */
|
||||
void config_init_menus(Cfg_menu *menuptr);
|
||||
void config_init(void);
|
||||
void cfg_exit(void);
|
||||
void cfg_text_screen_dump(void);
|
||||
void config_vbl_update(int doit_3_persec);
|
||||
void config_parse_option(char *buf, int pos, int len, int line);
|
||||
void config_parse_bram(char *buf, int pos, int len);
|
||||
void config_parse_config_kegs_file(void);
|
||||
Disk *cfg_get_dsk_from_slot_drive(int slot, int drive);
|
||||
void config_generate_config_kegs_name(char *outstr, int maxlen, Disk *dsk, int with_extras);
|
||||
void config_write_config_kegs_file(void);
|
||||
void insert_disk(int slot, int drive, const char *name, int ejected, int force_size, const char *partition_name, int part_num);
|
||||
void eject_named_disk(Disk *dsk, const char *name, const char *partition_name);
|
||||
void eject_disk_by_num(int slot, int drive);
|
||||
void eject_disk(Disk *dsk);
|
||||
int cfg_get_fd_size(int fd);
|
||||
int cfg_partition_read_block(int fd, void *buf, int blk, int blk_size);
|
||||
int cfg_partition_find_by_name_or_num(int fd, const char *partnamestr, int part_num, Disk *dsk);
|
||||
int cfg_partition_make_list(int fd);
|
||||
int cfg_maybe_insert_disk(int slot, int drive, const char *namestr);
|
||||
int cfg_stat(char *path, struct stat *sb);
|
||||
void cfg_htab_vtab(int x, int y);
|
||||
void cfg_home(void);
|
||||
void cfg_cleol(void);
|
||||
void cfg_putchar(int c);
|
||||
void cfg_printf(const char *fmt, ...);
|
||||
void cfg_print_num(int num, int max_len);
|
||||
void cfg_get_disk_name(char *outstr, int maxlen, int type_ext, int with_extras);
|
||||
void cfg_parse_menu(Cfg_menu *menu_ptr, int menu_pos, int highlight_pos, int change);
|
||||
void cfg_get_base_path(char *pathptr, const char *inptr, int go_up);
|
||||
void cfg_file_init(void);
|
||||
void cfg_free_alldirents(Cfg_listhdr *listhdrptr);
|
||||
void cfg_file_add_dirent(Cfg_listhdr *listhdrptr, const char *nameptr, int is_dir, int size, int image_start, int part_num);
|
||||
int cfg_dirent_sortfn(const void *obj1, const void *obj2);
|
||||
int cfg_str_match(const char *str1, const char *str2, int len);
|
||||
void cfg_file_readdir(const char *pathptr);
|
||||
char *cfg_shorten_filename(const char *in_ptr, int maxlen);
|
||||
void cfg_fix_topent(Cfg_listhdr *listhdrptr);
|
||||
void cfg_file_draw(void);
|
||||
void cfg_partition_selected(void);
|
||||
void cfg_file_selected(void);
|
||||
void cfg_file_handle_key(int key);
|
||||
void config_control_panel(void);
|
||||
|
||||
|
||||
/* dis.c */
|
||||
int get_num(void);
|
||||
void debugger_help(void);
|
||||
void do_debug_intfc(void);
|
||||
word32 dis_get_memory_ptr(word32 addr);
|
||||
void show_one_toolset(FILE *toolfile, int toolnum, word32 addr);
|
||||
void show_toolset_tables(word32 a2bank, word32 addr);
|
||||
void set_bp(word32 addr);
|
||||
void show_bp(void);
|
||||
void delete_bp(word32 addr);
|
||||
void do_blank(void);
|
||||
void do_go(void);
|
||||
void do_step(void);
|
||||
void xam_mem(int count);
|
||||
void show_hex_mem(int startbank, word32 start, int endbank, word32 end, int count);
|
||||
int read_line(char *buf, int len);
|
||||
void do_debug_list(void);
|
||||
void load_roms(void);
|
||||
void do_debug_unix(void);
|
||||
void do_debug_load(void);
|
||||
int do_dis(FILE *outfile, word32 kpc, int accsize, int xsize, int op_provided, word32 instr);
|
||||
void show_line(FILE *outfile, word32 kaddr, word32 operand, int size, char *string);
|
||||
void halt_printf(const char *fmt, ...);
|
||||
void halt2_printf(const char *fmt, ...);
|
||||
|
||||
|
||||
/* scc.c */
|
||||
void scc_init(void);
|
||||
void scc_reset(void);
|
||||
void scc_hard_reset_port(int port);
|
||||
void scc_reset_port(int port);
|
||||
void scc_regen_clocks(int port);
|
||||
void scc_port_init(int port);
|
||||
void scc_try_to_empty_writebuf(int port);
|
||||
void scc_try_fill_readbuf(int port, double dcycs);
|
||||
void scc_update(double dcycs);
|
||||
void do_scc_event(int type, double dcycs);
|
||||
void show_scc_state(void);
|
||||
void scc_log(int regnum, word32 val, double dcycs);
|
||||
void show_scc_log(void);
|
||||
word32 scc_read_reg(int port, double dcycs);
|
||||
void scc_write_reg(int port, word32 val, double dcycs);
|
||||
void scc_maybe_br_event(int port, double dcycs);
|
||||
void scc_evaluate_ints(int port);
|
||||
void scc_maybe_rx_event(int port, double dcycs);
|
||||
void scc_maybe_rx_int(int port, double dcycs);
|
||||
void scc_clr_rx_int(int port);
|
||||
void scc_handle_tx_event(int port, double dcycs);
|
||||
void scc_maybe_tx_event(int port, double dcycs);
|
||||
void scc_clr_tx_int(int port);
|
||||
void scc_set_zerocnt_int(int port);
|
||||
void scc_clr_zerocnt_int(int port);
|
||||
void scc_add_to_readbuf(int port, word32 val, double dcycs);
|
||||
void scc_add_to_writebuf(int port, word32 val, double dcycs);
|
||||
word32 scc_read_data(int port, double dcycs);
|
||||
void scc_write_data(int port, word32 val, double dcycs);
|
||||
|
||||
|
||||
/* scc_socket_driver.c */
|
||||
void scc_socket_init(int port);
|
||||
void scc_socket_change_params(int port);
|
||||
void scc_accept_socket(int port);
|
||||
void scc_socket_fill_readbuf(int port, double dcycs);
|
||||
void scc_socket_empty_writebuf(int port);
|
||||
|
||||
|
||||
/* scc_windriver.c */
|
||||
|
||||
|
||||
/* scc_macdriver.c */
|
||||
|
||||
|
||||
/* iwm.c */
|
||||
void iwm_init_drive(Disk *dsk, int smartport, int drive, int disk_525);
|
||||
void iwm_init(void);
|
||||
void iwm_reset(void);
|
||||
void draw_iwm_status(int line, char *buf);
|
||||
void iwm_flush_disk_to_unix(Disk *dsk);
|
||||
void iwm_vbl_update(int doit_3_persec);
|
||||
void iwm_show_stats(void);
|
||||
void iwm_touch_switches(int loc, double dcycs);
|
||||
void iwm_move_to_track(Disk *dsk, int new_track);
|
||||
void iwm525_phase_change(int drive, int phase);
|
||||
int iwm_read_status35(double dcycs);
|
||||
void iwm_do_action35(double dcycs);
|
||||
void iwm_set_apple35_sel(int newval);
|
||||
int iwm_read_c0ec(double dcycs);
|
||||
int read_iwm(int loc, double dcycs);
|
||||
void write_iwm(int loc, int val, double dcycs);
|
||||
int iwm_read_enable2(double dcycs);
|
||||
int iwm_read_enable2_handshake(double dcycs);
|
||||
void iwm_write_enable2(int val, double dcycs);
|
||||
int iwm_read_data(Disk *dsk, int fast_disk_emul, double dcycs);
|
||||
void iwm_write_data(Disk *dsk, word32 val, int fast_disk_emul, double dcycs);
|
||||
void sector_to_partial_nib(byte *in, byte *nib_ptr);
|
||||
int disk_unnib_4x4(Disk *dsk);
|
||||
int iwm_denib_track525(Disk *dsk, Track *trk, int qtr_track, byte *outbuf);
|
||||
int iwm_denib_track35(Disk *dsk, Track *trk, int qtr_track, byte *outbuf);
|
||||
int disk_track_to_unix(Disk *dsk, int qtr_track, byte *outbuf);
|
||||
void show_hex_data(byte *buf, int count);
|
||||
void disk_check_nibblization(Disk *dsk, int qtr_track, byte *buf, int size);
|
||||
void disk_unix_to_nib(Disk *dsk, int qtr_track, int unix_pos, int unix_len, int nib_len);
|
||||
void iwm_nibblize_track_nib525(Disk *dsk, Track *trk, byte *track_buf, int qtr_track);
|
||||
void iwm_nibblize_track_525(Disk *dsk, Track *trk, byte *track_buf, int qtr_track);
|
||||
void iwm_nibblize_track_35(Disk *dsk, Track *trk, byte *track_buf, int qtr_track);
|
||||
void disk_4x4_nib_out(Disk *dsk, word32 val);
|
||||
void disk_nib_out(Disk *dsk, byte val, int size);
|
||||
void disk_nib_end_track(Disk *dsk);
|
||||
void iwm_show_track(int slot_drive, int track);
|
||||
void iwm_show_a_track(Track *trk);
|
||||
|
||||
|
||||
/* joystick_driver.c */
|
||||
|
||||
|
||||
/* moremem.c */
|
||||
void fixup_brks(void);
|
||||
void fixup_hires_on(void);
|
||||
void fixup_bank0_2000_4000(void);
|
||||
void fixup_bank0_0400_0800(void);
|
||||
void fixup_any_bank_any_page(int start_page, int num_pages, byte *mem0rd, byte *mem0wr);
|
||||
void fixup_intcx(void);
|
||||
void fixup_wrdefram(int new_wrdefram);
|
||||
void fixup_st80col(double dcycs);
|
||||
void fixup_altzp(void);
|
||||
void fixup_page2(double dcycs);
|
||||
void fixup_ramrd(void);
|
||||
void fixup_ramwrt(void);
|
||||
void fixup_lcbank2(void);
|
||||
void fixup_rdrom(void);
|
||||
void set_statereg(double dcycs, int val);
|
||||
void fixup_shadow_txt1(void);
|
||||
void fixup_shadow_txt2(void);
|
||||
void fixup_shadow_hires1(void);
|
||||
void fixup_shadow_hires2(void);
|
||||
void fixup_shadow_shr(void);
|
||||
void fixup_shadow_iolc(void);
|
||||
void update_shadow_reg(int val);
|
||||
void fixup_shadow_all_banks(void);
|
||||
void setup_pageinfo(void);
|
||||
void show_bankptrs_bank0rdwr(void);
|
||||
void show_bankptrs(int bnk);
|
||||
void show_addr(byte *ptr);
|
||||
int io_read(word32 loc, double *cyc_ptr);
|
||||
void io_write(word32 loc, int val, double *cyc_ptr);
|
||||
word32 get_lines_since_vbl(double dcycs);
|
||||
int in_vblank(double dcycs);
|
||||
int read_vid_counters(int loc, double dcycs);
|
||||
|
||||
|
||||
/* paddles.c */
|
||||
void paddle_trigger(double dcycs);
|
||||
void paddle_trigger_mouse(double dcycs);
|
||||
int read_paddles(int paddle, double dcycs);
|
||||
|
||||
|
||||
/* sim65816.c */
|
||||
void show_pc_log(void);
|
||||
word32 toolbox_debug_4byte(word32 addr);
|
||||
void toolbox_debug_c(word32 xreg, word32 stack, double *cyc_ptr);
|
||||
void show_toolbox_log(void);
|
||||
word32 get_memory_io(word32 loc, double *cyc_ptr);
|
||||
void set_memory_io(word32 loc, int val, double *cyc_ptr);
|
||||
void show_regs_act(Engine_reg *eptr);
|
||||
void show_regs(void);
|
||||
void my_exit(int ret);
|
||||
void do_reset(void);
|
||||
void check_engine_asm_defines(void);
|
||||
byte *memalloc_align(int size, int skip_amt);
|
||||
void memory_ptr_init(void);
|
||||
int kegsmain(int argc, char **argv);
|
||||
void kegs_expand_path(char *out_ptr, const char *in_ptr, int maxlen);
|
||||
void setup_kegs_file(char *outname, int maxlen, int ok_if_missing, const char **name_ptr);
|
||||
void initialize_events(void);
|
||||
void check_for_one_event_type(int type);
|
||||
void add_event_entry(double dcycs, int type);
|
||||
double remove_event_entry(int type);
|
||||
void add_event_stop(double dcycs);
|
||||
void add_event_doc(double dcycs, int osc);
|
||||
void add_event_scc(double dcycs, int type);
|
||||
void add_event_vbl(void);
|
||||
void add_event_vid_upd(int line);
|
||||
double remove_event_doc(int osc);
|
||||
double remove_event_scc(int type);
|
||||
void show_all_events(void);
|
||||
void show_pmhz(void);
|
||||
void setup_zip_speeds(void);
|
||||
void run_prog(void);
|
||||
void add_irq(void);
|
||||
void remove_irq(void);
|
||||
void take_irq(int is_it_brk);
|
||||
void show_dtime_array(void);
|
||||
void update_60hz(double dcycs, double dtime_now);
|
||||
void do_vbl_int(void);
|
||||
void do_scan_int(double dcycs, int line);
|
||||
void check_scan_line_int(double dcycs, int cur_video_line);
|
||||
void check_for_new_scan_int(double dcycs);
|
||||
void init_reg(void);
|
||||
void handle_action(word32 ret);
|
||||
void do_break(word32 ret);
|
||||
void do_cop(word32 ret);
|
||||
void do_wdm(word32 arg);
|
||||
void do_wai(void);
|
||||
void do_stp(void);
|
||||
void size_fail(int val, word32 v1, word32 v2);
|
||||
|
||||
|
||||
/* smartport.c */
|
||||
void smartport_error(void);
|
||||
void smartport_log(word32 start_addr, int cmd, int rts_addr, int cmd_list);
|
||||
void do_c70d(word32 arg0);
|
||||
void do_c70a(word32 arg0);
|
||||
int do_read_c7(int unit_num, word32 buf, int blk);
|
||||
int do_write_c7(int unit_num, word32 buf, int blk);
|
||||
int do_format_c7(int unit_num);
|
||||
void do_c700(word32 ret);
|
||||
|
||||
|
||||
/* sound.c */
|
||||
void doc_log_rout(char *msg, int osc, double dsamps, int etc);
|
||||
void show_doc_log(void);
|
||||
void sound_init(void);
|
||||
void sound_init_general(void);
|
||||
void parent_sound_get_sample_rate(int read_fd);
|
||||
void set_audio_rate(int rate);
|
||||
void sound_reset(double dcycs);
|
||||
void sound_shutdown(void);
|
||||
void sound_update(double dcycs);
|
||||
void open_sound_file(void);
|
||||
void close_sound_file(void);
|
||||
void check_for_range(word32 *addr, int num_samps, int offset);
|
||||
void send_sound_to_file(word32 *addr, int shm_pos, int num_samps);
|
||||
void send_sound(int real_samps, int size);
|
||||
void show_c030_state(void);
|
||||
void show_c030_samps(int *outptr, int num);
|
||||
void sound_play(double dsamps);
|
||||
void doc_handle_event(int osc, double dcycs);
|
||||
void doc_sound_end(int osc, int can_repeat, double eff_dsamps, double dsamps);
|
||||
void add_sound_irq(int osc);
|
||||
void remove_sound_irq(int osc, int must);
|
||||
void start_sound(int osc, double eff_dsamps, double dsamps);
|
||||
void wave_end_estimate(int osc, double eff_dsamps, double dsamps);
|
||||
void remove_sound_event(int osc);
|
||||
void doc_write_ctl_reg(int osc, int val, double dsamps);
|
||||
void doc_recalc_sound_parms(int osc, double eff_dcycs, double dsamps);
|
||||
int doc_read_c030(double dcycs);
|
||||
int doc_read_c03c(double dcycs);
|
||||
int doc_read_c03d(double dcycs);
|
||||
void doc_write_c03c(int val, double dcycs);
|
||||
void doc_write_c03d(int val, double dcycs);
|
||||
void doc_write_c03e(int val);
|
||||
void doc_write_c03f(int val);
|
||||
void doc_show_ensoniq_state(int osc);
|
||||
|
||||
|
||||
/* sound_driver.c */
|
||||
void reliable_buf_write(word32 *shm_addr, int pos, int size);
|
||||
void reliable_zero_write(int amt);
|
||||
void child_sound_loop(int read_fd, int write_fd, word32 *shm_addr);
|
||||
void child_sound_playit(word32 tmp);
|
||||
|
||||
|
||||
/* video.c */
|
||||
void video_init(void);
|
||||
void show_a2_line_stuff(void);
|
||||
void video_reset(void);
|
||||
void video_update(void);
|
||||
int video_all_stat_to_line_stat(int line, int new_all_stat);
|
||||
int *video_update_kimage_ptr(int line, int new_stat);
|
||||
void change_a2vid_palette(int new_palette);
|
||||
void check_a2vid_palette(void);
|
||||
void change_display_mode(double dcycs);
|
||||
void video_update_all_stat_through_line(int line);
|
||||
void change_border_color(double dcycs, int val);
|
||||
void update_border_info(void);
|
||||
void update_border_line(int st_line_offset, int end_line_offset, int color);
|
||||
void video_border_pixel_write(Kimage *kimage_ptr, int starty, int num_lines, word32 val, int st_off, int end_off);
|
||||
void redraw_changed_text_40(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, int pixels_per_line);
|
||||
void redraw_changed_text_80(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int altcharset, int bg_val, int fg_val, int pixels_per_line);
|
||||
void redraw_changed_gr(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line);
|
||||
void redraw_changed_dbl_gr(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line);
|
||||
void redraw_changed_hires(int start_offset, int start_line, int num_lines, int color, int reparse, byte *screen_data, int pixels_per_line);
|
||||
void redraw_changed_hires_bw(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line);
|
||||
void redraw_changed_hires_color(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line);
|
||||
void redraw_changed_dbl_hires(int start_offset, int start_line, int num_lines, int color, int reparse, byte *screen_data, int pixels_per_line);
|
||||
void redraw_changed_dbl_hires_bw(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line);
|
||||
void redraw_changed_dbl_hires_color(int start_offset, int start_line, int num_lines, int reparse, byte *screen_data, int pixels_per_line);
|
||||
int video_rebuild_super_hires_palette(word32 scan_info, int line, int reparse);
|
||||
void redraw_changed_super_hires(int start_offset, int start_line, int num_lines, int in_reparse, byte *screen_data);
|
||||
void display_screen(void);
|
||||
void video_update_event_line(int line);
|
||||
void video_update_through_line(int line);
|
||||
void video_refresh_lines(int st_line, int num_lines, int must_reparse);
|
||||
void refresh_border(void);
|
||||
void end_screen(void);
|
||||
void read_a2_font(void);
|
||||
void video_get_kimage(Kimage *kimage_ptr, int extend_info, int depth, int mdepth);
|
||||
void video_get_kimages(void);
|
||||
void video_convert_kimage_depth(Kimage *kim_in, Kimage *kim_out, int startx, int starty, int width, int height);
|
||||
void video_push_lines(Kimage *kimage_ptr, int start_line, int end_line, int left_pix, int right_pix);
|
||||
void video_push_border_sides_lines(int src_x, int dest_x, int width, int start_line, int end_line);
|
||||
void video_push_border_sides(void);
|
||||
void video_push_border_special(void);
|
||||
void video_push_kimages(void);
|
||||
void video_update_color_raw(int col_num, int a2_color);
|
||||
void video_update_color_array(int col_num, int a2_color);
|
||||
void video_update_colormap(void);
|
||||
void video_update_status_line(int line, const char *string);
|
||||
void video_show_debug_info(void);
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_C
|
||||
const char rcsid_protos_engine_c_h[] = "@(#)$KmKId: protos_engine_c.h,v 1.10 2004-01-10 15:50:02-05 kentd Exp $";
|
||||
#endif
|
||||
|
||||
/* END_HDR */
|
||||
|
||||
/* engine_c.c */
|
||||
void check_breakpoints(word32 addr);
|
||||
word32 get_memory8_io_stub(word32 addr, byte *stat, double *fcycs_ptr, double fplus_x_m1);
|
||||
word32 get_memory16_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr, Fplus *fplus_ptr, int in_bank);
|
||||
word32 get_memory24_pieces_stub(word32 addr, byte *stat, double *fcycs_ptr, Fplus *fplus_ptr, int in_bank);
|
||||
void set_memory8_io_stub(word32 addr, word32 val, byte *stat, double *fcycs_ptr, double fplus_x_m1);
|
||||
void set_memory16_pieces_stub(word32 addr, word32 val, double *fcycs_ptr, Fplus *fplus_ptr, int in_bank);
|
||||
void set_memory24_pieces_stub(word32 addr, word32 val, double *fcycs_ptr, Fplus *fplus_ptr, int in_bank);
|
||||
word32 get_memory_c(word32 addr, int cycs);
|
||||
word32 get_memory16_c(word32 addr, int cycs);
|
||||
word32 get_memory24_c(word32 addr, int cycs);
|
||||
void set_memory_c(word32 addr, word32 val, int cycs);
|
||||
void set_memory16_c(word32 addr, word32 val, int cycs);
|
||||
void set_memory24_c(word32 addr, word32 val, int cycs);
|
||||
word32 do_adc_sbc8(word32 in1, word32 in2, word32 psr, int sub);
|
||||
word32 do_adc_sbc16(word32 in1, word32 in2, word32 psr, int sub);
|
||||
void fixed_memory_ptrs_init(void);
|
||||
word32 get_itimer(void);
|
||||
void set_halt_act(int val);
|
||||
void clr_halt_act(void);
|
||||
word32 get_remaining_operands(word32 addr, word32 opcode, word32 psr, Fplus *fplus_ptr);
|
||||
int enter_engine(Engine_reg *engine_ptr);
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_protos_mac_h[] = "@(#)$KmKId: protos_macdriver.h,v 1.6 2004-03-23 17:27:31-05 kentd Exp $";
|
||||
|
||||
/* END_HDR */
|
||||
|
||||
/* macdriver.c */
|
||||
pascal OSStatus quit_event_handler(EventHandlerCallRef call_ref, EventRef event, void *ignore);
|
||||
void show_alert(const char *str1, const char *str2, const char *str3, int num);
|
||||
pascal OSStatus my_cmd_handler(EventHandlerCallRef handlerRef, EventRef event, void *userdata);
|
||||
void update_window(void);
|
||||
void show_event(UInt32 event_class, UInt32 event_kind, int handled);
|
||||
pascal OSStatus my_win_handler(EventHandlerCallRef handlerRef, EventRef event, void *userdata);
|
||||
pascal OSStatus dummy_event_handler(EventHandlerCallRef call_ref, EventRef in_event, void *ignore);
|
||||
void mac_update_modifiers(word32 state);
|
||||
void mac_warp_mouse(void);
|
||||
void check_input_events(void);
|
||||
void temp_run_application_event_loop(void);
|
||||
int main(int argc, char *argv[]);
|
||||
void x_update_color(int col_num, int red, int green, int blue, word32 rgb);
|
||||
void x_update_physical_colormap(void);
|
||||
void show_xcolor_array(void);
|
||||
void xdriver_end(void);
|
||||
void x_get_kimage(Kimage *kimage_ptr);
|
||||
void dev_video_init(void);
|
||||
void x_redraw_status_lines(void);
|
||||
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height);
|
||||
void x_push_done(void);
|
||||
void x_auto_repeat_on(int must);
|
||||
void x_auto_repeat_off(int must);
|
||||
void x_hide_pointer(int do_hide);
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2003 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_protos_macsnd_driver_h[] = "@(#)$KmKId: protos_macsnd_driver.h,v 1.2 2003-11-19 19:57:02-05 kentd Exp $";
|
||||
|
||||
/* END_HDR */
|
||||
|
||||
/* macsnd_driver.c */
|
||||
void mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd);
|
||||
int mac_send_audio(byte *ptr, int in_size);
|
||||
void child_sound_init_mac(void);
|
||||
void macsnd_init(word32 *shmaddr);
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
// $KmKId: protos_windriver.h,v 1.4 2004-03-23 17:27:26-05 kentd Exp $
|
||||
|
||||
/* END_HDR */
|
||||
|
||||
/* windriver.c */
|
||||
int win_update_mouse(int x, int y, int button_states, int buttons_valid);
|
||||
void win_event_mouse(WPARAM wParam, LPARAM lParam);
|
||||
void win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags);
|
||||
void win_event_quit(HWND hwnd);
|
||||
void win_event_redraw(void);
|
||||
LRESULT CALLBACK win_event_handler(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam);
|
||||
int main(int argc, char **argv);
|
||||
void check_input_events(void);
|
||||
void x_update_color(int col_num, int red, int green, int blue, word32 rgb);
|
||||
void x_update_physical_colormap(void);
|
||||
void show_xcolor_array(void);
|
||||
void xdriver_end(void);
|
||||
void x_get_kimage(Kimage *kimage_ptr);
|
||||
void dev_video_init(void);
|
||||
void x_redraw_status_lines(void);
|
||||
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height);
|
||||
void x_push_done(void);
|
||||
void x_auto_repeat_on(int must);
|
||||
void x_auto_repeat_off(int must);
|
||||
void x_hide_pointer(int do_hide);
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_protos_x_h[] = "@(#)$KmKId: protos_xdriver.h,v 1.18 2002-11-19 03:10:38-05 kadickey Exp $";
|
||||
|
||||
/* END_HDR */
|
||||
|
||||
/* xdriver.c */
|
||||
int main(int argc, char **argv);
|
||||
void x_update_physical_colormap(void);
|
||||
void show_xcolor_array(void);
|
||||
int my_error_handler(Display *display, XErrorEvent *ev);
|
||||
void xdriver_end(void);
|
||||
void show_colormap(char *str, Colormap cmap, int index1, int index2, int index3);
|
||||
void dev_video_init(void);
|
||||
Visual *x_try_find_visual(int depth, int screen_num, XVisualInfo **visual_list_ptr);
|
||||
void x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, int *shift_right_ptr);
|
||||
int xhandle_shm_error(Display *display, XErrorEvent *event);
|
||||
int get_shm(Kimage *kimage_ptr);
|
||||
void get_ximage(Kimage *kimage_ptr);
|
||||
void update_status_line(int line, const char *string);
|
||||
void redraw_status_lines(void);
|
||||
void check_input_events(void);
|
||||
void handle_keysym(XEvent *xev_in);
|
||||
int x_keysym_to_a2code(int keysym, int is_up);
|
||||
void x_update_modifier_state(int state);
|
||||
void x_auto_repeat_on(int must);
|
||||
void x_auto_repeat_off(int must);
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_C
|
||||
const char rcsid_scc_h[] = "@(#)$KmKId: scc.h,v 1.12 2003-11-21 00:27:00-05 kentd Exp $";
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <winsock.h>
|
||||
#else
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#if defined(HPUX) || defined(__linux__) || defined(SOLARIS) || defined(MAC) || defined(__MACH__)
|
||||
# define SCC_SOCKETS
|
||||
#endif
|
||||
|
||||
|
||||
/* my scc port 0 == channel A, port 1 = channel B */
|
||||
|
||||
#define SCC_INBUF_SIZE 4096 /* must be a power of 2 */
|
||||
#define SCC_OUTBUF_SIZE 4096 /* must be a power of 2 */
|
||||
|
||||
STRUCT(Scc) {
|
||||
int port;
|
||||
int state;
|
||||
int accfd;
|
||||
int rdwrfd;
|
||||
void *host_handle;
|
||||
void *host_handle2;
|
||||
int host_aux1;
|
||||
int read_called_this_vbl;
|
||||
int write_called_this_vbl;
|
||||
|
||||
int mode;
|
||||
int reg_ptr;
|
||||
int reg[16];
|
||||
|
||||
int rx_queue_depth;
|
||||
byte rx_queue[4];
|
||||
|
||||
int in_rdptr;
|
||||
int in_wrptr;
|
||||
byte in_buf[SCC_INBUF_SIZE];
|
||||
|
||||
int out_rdptr;
|
||||
int out_wrptr;
|
||||
byte out_buf[SCC_OUTBUF_SIZE];
|
||||
|
||||
int br_is_zero;
|
||||
int tx_buf_empty;
|
||||
int wantint_rx;
|
||||
int wantint_tx;
|
||||
int wantint_zerocnt;
|
||||
int int_pending_rx;
|
||||
int int_pending_tx;
|
||||
int int_pending_zerocnt;
|
||||
|
||||
double br_dcycs;
|
||||
double tx_dcycs;
|
||||
double rx_dcycs;
|
||||
|
||||
int br_event_pending;
|
||||
int rx_event_pending;
|
||||
int tx_event_pending;
|
||||
|
||||
int char_size;
|
||||
int baud_rate;
|
||||
};
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_scc_macdriver_c[] = "@(#)$KmKId: scc_macdriver.c,v 1.3 2003-11-03 01:52:49-05 kentd Exp $";
|
||||
|
||||
/* This file contains the Mac serial calls */
|
||||
|
||||
#include "defc.h"
|
||||
#include "scc.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <termios.h>
|
||||
#endif
|
||||
|
||||
extern Scc scc_stat[2];
|
||||
extern word32 g_c025_val;
|
||||
|
||||
#ifdef MAC
|
||||
int
|
||||
scc_serial_mac_init(int port)
|
||||
{
|
||||
char str_buf[1024];
|
||||
Scc *scc_ptr;
|
||||
int state;
|
||||
int fd;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
scc_ptr->state = 0; /* mark as uninitialized */
|
||||
|
||||
sprintf(&str_buf[0], "/dev/tty.USA19QW11P1.1");
|
||||
/* HACK: fix this... */
|
||||
|
||||
fd = open(&str_buf[0], O_RDWR | O_NONBLOCK);
|
||||
|
||||
scc_ptr->host_handle = (void *)fd;
|
||||
scc_ptr->host_handle2 = 0;
|
||||
|
||||
printf("scc_serial_mac_init %d called, fd: %d\n", port, fd);
|
||||
|
||||
if(fd < 0) {
|
||||
scc_ptr->host_handle = (void *)-1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
scc_serial_mac_change_params(port);
|
||||
|
||||
state = 2; /* raw serial */
|
||||
scc_ptr->state = state;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_mac_change_params(int port)
|
||||
{
|
||||
struct termios termios_buf;
|
||||
Scc *scc_ptr;
|
||||
int fd;
|
||||
int csz;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
fd = (int)scc_ptr->host_handle;
|
||||
printf("scc_serial_mac_change_parms port: %d, fd: %d\n", port, fd);
|
||||
if(fd <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = tcgetattr(fd, &termios_buf);
|
||||
if(ret != 0) {
|
||||
printf("tcgetattr port%d ret: %d\n", port, ret);
|
||||
}
|
||||
|
||||
#if 1
|
||||
printf("baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n",
|
||||
(int)termios_buf.c_ispeed, (int)termios_buf.c_iflag,
|
||||
(int)termios_buf.c_oflag, (int)termios_buf.c_cflag,
|
||||
(int)termios_buf.c_lflag);
|
||||
#endif
|
||||
|
||||
memset(&termios_buf, 0, sizeof(struct termios));
|
||||
cfmakeraw(&termios_buf);
|
||||
cfsetspeed(&termios_buf, scc_ptr->baud_rate);
|
||||
|
||||
csz = scc_ptr->char_size;
|
||||
termios_buf.c_cflag = CREAD | CLOCAL;
|
||||
termios_buf.c_cflag |= (csz == 5) ? CS5 :
|
||||
(csz == 6) ? CS6 :
|
||||
(csz == 7) ? CS7 :
|
||||
CS8;
|
||||
switch((scc_ptr->reg[4] >> 2) & 0x3) {
|
||||
case 2: // 1.5 stop bits
|
||||
termios_buf.c_cflag |= CSTOPB; /* no 1.5 stop bit setting.*/
|
||||
break;
|
||||
case 3: // 2 stop bits
|
||||
termios_buf.c_cflag |= CSTOPB;
|
||||
break;
|
||||
}
|
||||
|
||||
switch((scc_ptr->reg[4]) & 0x3) {
|
||||
case 1: // Odd parity
|
||||
termios_buf.c_cflag |= (PARENB | PARODD);
|
||||
break;
|
||||
case 3: // Even parity
|
||||
termios_buf.c_cflag |= PARENB;
|
||||
break;
|
||||
}
|
||||
|
||||
/* always enabled DTR and RTS control */
|
||||
termios_buf.c_cflag |= CDTR_IFLOW | CRTS_IFLOW;
|
||||
|
||||
printf("fd: %d, baudrate: %d, iflag:%x, oflag:%x, cflag:%x, lflag:%x\n",
|
||||
fd, (int)termios_buf.c_ispeed, (int)termios_buf.c_iflag,
|
||||
(int)termios_buf.c_oflag, (int)termios_buf.c_cflag,
|
||||
(int)termios_buf.c_lflag);
|
||||
ret = tcsetattr(fd, TCSANOW, &termios_buf);
|
||||
if(ret != 0) {
|
||||
printf("tcsetattr ret: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_mac_fill_readbuf(int port, double dcycs)
|
||||
{
|
||||
byte tmp_buf[256];
|
||||
Scc *scc_ptr;
|
||||
int fd;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
fd = (int)scc_ptr->host_handle;
|
||||
if(fd <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try reading some bytes */
|
||||
ret = read(fd, tmp_buf, 256);
|
||||
|
||||
if(ret > 0) {
|
||||
for(i = 0; i < ret; i++) {
|
||||
scc_add_to_readbuf(port, tmp_buf[i], dcycs);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_mac_empty_writebuf(int port)
|
||||
{
|
||||
Scc *scc_ptr;
|
||||
int fd;
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int done;
|
||||
int ret;
|
||||
int len;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
fd = (int)scc_ptr->host_handle;
|
||||
if(fd <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try writing some bytes */
|
||||
done = 0;
|
||||
while(!done) {
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr) {
|
||||
//printf("...rdptr == wrptr\n");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
len = wrptr - rdptr;
|
||||
if(len < 0) {
|
||||
len = SCC_OUTBUF_SIZE - rdptr;
|
||||
}
|
||||
if(len > 32) {
|
||||
len = 32;
|
||||
}
|
||||
if(len <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
ret = write(fd, &(scc_ptr->out_buf[rdptr]), len);
|
||||
|
||||
if(ret <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
rdptr = rdptr + ret;
|
||||
if(rdptr >= SCC_OUTBUF_SIZE) {
|
||||
rdptr = rdptr - SCC_OUTBUF_SIZE;
|
||||
}
|
||||
scc_ptr->out_rdptr = rdptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* MAC */
|
|
@ -0,0 +1,255 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_scc_socket_driver_c[] = "@(#)$KmKId: scc_socket_driver.c,v 1.4 2003-11-20 23:43:41-05 kentd Exp $";
|
||||
|
||||
/* This file contains the Unix socket calls */
|
||||
|
||||
#include "defc.h"
|
||||
#include "scc.h"
|
||||
#include <signal.h>
|
||||
|
||||
extern Scc scc_stat[2];
|
||||
|
||||
void
|
||||
scc_socket_init(int port)
|
||||
{
|
||||
#ifdef SCC_SOCKETS
|
||||
Scc *scc_ptr;
|
||||
struct sockaddr_in sa_in;
|
||||
int on;
|
||||
int flags;
|
||||
int ret;
|
||||
int sockfd;
|
||||
int inc;
|
||||
|
||||
inc = 0;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
scc_ptr->state = -1; /* mark as failed for now */
|
||||
scc_ptr->host_aux1 = sizeof(struct sockaddr_in);
|
||||
scc_ptr->host_handle = malloc(scc_ptr->host_aux1);
|
||||
memset(scc_ptr->host_handle, 0, scc_ptr->host_aux1);
|
||||
|
||||
while(1) {
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sockfd < 0) {
|
||||
printf("socket ret: %d, errno: %d\n", sockfd, errno);
|
||||
return;
|
||||
}
|
||||
/* printf("socket ret: %d\n", sockfd); */
|
||||
|
||||
on = 1;
|
||||
ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&on, sizeof(on));
|
||||
if(ret < 0) {
|
||||
printf("setsockopt REUSEADDR ret: %d, err:%d\n",
|
||||
ret, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&sa_in, 0, sizeof(sa_in));
|
||||
sa_in.sin_family = AF_INET;
|
||||
sa_in.sin_port = htons(6501 + port + inc);
|
||||
sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
ret = bind(sockfd, (struct sockaddr *)&sa_in, sizeof(sa_in));
|
||||
|
||||
if(ret < 0) {
|
||||
printf("bind ret: %d, errno: %d\n", ret, errno);
|
||||
inc++;
|
||||
close(sockfd);
|
||||
printf("Trying next port: %d\n", 6501 + port + inc);
|
||||
if(inc >= 10) {
|
||||
printf("Too many retries, quitting\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("SCC port %d is at unix port %d\n", port, 6501 + port + inc);
|
||||
|
||||
ret = listen(sockfd, 1);
|
||||
|
||||
flags = fcntl(sockfd, F_GETFL, 0);
|
||||
if(flags == -1) {
|
||||
printf("fcntl GETFL ret: %d, errno: %d\n", flags, errno);
|
||||
return;
|
||||
}
|
||||
ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
||||
if(ret == -1) {
|
||||
printf("fcntl SETFL ret: %d, errno: %d\n", ret, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
scc_ptr->accfd = sockfd;
|
||||
scc_ptr->state = 1; /* successful socket */
|
||||
#endif /* SCC_SOCKETS */
|
||||
}
|
||||
|
||||
void
|
||||
scc_socket_change_params(int port)
|
||||
{
|
||||
#ifdef SCC_SOCKETS
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
scc_accept_socket(int port)
|
||||
{
|
||||
#ifdef SCC_SOCKETS
|
||||
Scc *scc_ptr;
|
||||
int flags;
|
||||
int rdwrfd;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
if(scc_ptr->rdwrfd <= 0) {
|
||||
rdwrfd = accept(scc_ptr->accfd, scc_ptr->host_handle,
|
||||
&(scc_ptr->host_aux1));
|
||||
if(rdwrfd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* For Linux, we need to set O_NONBLOCK on the rdwrfd */
|
||||
flags = fcntl(rdwrfd, F_GETFL, 0);
|
||||
if(flags == -1) {
|
||||
printf("fcntl GETFL ret: %d, errno: %d\n", flags,errno);
|
||||
return;
|
||||
}
|
||||
ret = fcntl(rdwrfd, F_SETFL, flags | O_NONBLOCK);
|
||||
if(ret == -1) {
|
||||
printf("fcntl SETFL ret: %d, errno: %d\n", ret, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
scc_ptr->rdwrfd = rdwrfd;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
scc_socket_fill_readbuf(int port, double dcycs)
|
||||
{
|
||||
#ifdef SCC_SOCKETS
|
||||
byte tmp_buf[256];
|
||||
Scc *scc_ptr;
|
||||
int rdwrfd;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
/* Accept socket if not already open */
|
||||
scc_accept_socket(port);
|
||||
|
||||
rdwrfd = scc_ptr->rdwrfd;
|
||||
if(rdwrfd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try reading some bytes */
|
||||
ret = read(rdwrfd, tmp_buf, 256);
|
||||
if(ret > 0) {
|
||||
for(i = 0; i < ret; i++) {
|
||||
if(tmp_buf[i] == 0) {
|
||||
/* Skip null chars */
|
||||
continue;
|
||||
}
|
||||
scc_add_to_readbuf(port, tmp_buf[i], dcycs);
|
||||
}
|
||||
} else if(ret == 0) {
|
||||
/* assume socket close */
|
||||
close(rdwrfd);
|
||||
scc_ptr->rdwrfd = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
scc_socket_empty_writebuf(int port)
|
||||
{
|
||||
#ifdef SCC_SOCKETS
|
||||
struct sigaction newact, oldact;
|
||||
Scc *scc_ptr;
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int rdwrfd;
|
||||
int done;
|
||||
int ret;
|
||||
int len;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
scc_accept_socket(port);
|
||||
|
||||
rdwrfd = scc_ptr->rdwrfd;
|
||||
if(rdwrfd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try writing some bytes */
|
||||
done = 0;
|
||||
while(!done) {
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
len = wrptr - rdptr;
|
||||
if(len < 0) {
|
||||
len = SCC_OUTBUF_SIZE - rdptr;
|
||||
}
|
||||
if(len > 32) {
|
||||
len = 32;
|
||||
}
|
||||
if(len <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* ignore SIGPIPE around writes to the socket, so we can */
|
||||
/* catch a closed socket and prepare to re-accept a new */
|
||||
/* connection. Otherwise, SIGPIPE kills KEGS */
|
||||
sigemptyset(&newact.sa_mask);
|
||||
newact.sa_handler = SIG_IGN;
|
||||
newact.sa_flags = 0;
|
||||
sigaction(SIGPIPE, &newact, &oldact);
|
||||
|
||||
ret = write(rdwrfd, &(scc_ptr->out_buf[rdptr]), len);
|
||||
|
||||
sigaction(SIGPIPE, &oldact, 0);
|
||||
/* restore previous SIGPIPE behavior */
|
||||
|
||||
if(ret == 0) {
|
||||
done = 1; /* give up for now */
|
||||
break;
|
||||
} else if(ret < 0) {
|
||||
/* assume socket is dead */
|
||||
close(rdwrfd);
|
||||
scc_ptr->rdwrfd = -1;
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
rdptr = rdptr + ret;
|
||||
if(rdptr >= SCC_OUTBUF_SIZE) {
|
||||
rdptr = rdptr - SCC_OUTBUF_SIZE;
|
||||
}
|
||||
scc_ptr->out_rdptr = rdptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_scc_windriver_c[] = "@(#)$KmKId: scc_windriver.c,v 1.3 2003-09-20 15:05:15-04 kentd Exp $";
|
||||
|
||||
/* This file contains the Win32 COM1/COM2 calls */
|
||||
|
||||
#include "defc.h"
|
||||
#include "scc.h"
|
||||
|
||||
extern Scc scc_stat[2];
|
||||
extern word32 g_c025_val;
|
||||
|
||||
#ifdef _WIN32
|
||||
int
|
||||
scc_serial_win_init(int port)
|
||||
{
|
||||
COMMTIMEOUTS commtimeouts;
|
||||
char str_buf[8];
|
||||
Scc *scc_ptr;
|
||||
HANDLE host_handle;
|
||||
int state;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
scc_ptr->state = 0; /* mark as failed */
|
||||
|
||||
sprintf(&str_buf[0], "COM%d", port+1);
|
||||
|
||||
host_handle = CreateFile(&str_buf[0], GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
scc_ptr->host_handle = host_handle;
|
||||
scc_ptr->host_handle2 = malloc(sizeof(DCB));
|
||||
|
||||
printf("scc_socket_init %d called, host_handle: %p\n", port,
|
||||
host_handle);
|
||||
|
||||
if(host_handle == INVALID_HANDLE_VALUE) {
|
||||
scc_ptr->host_handle = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
scc_serial_win_change_params(port);
|
||||
|
||||
|
||||
commtimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
commtimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
commtimeouts.ReadTotalTimeoutConstant = 0;
|
||||
commtimeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
commtimeouts.WriteTotalTimeoutConstant = 10;
|
||||
ret = SetCommTimeouts(host_handle, &commtimeouts);
|
||||
if(ret == 0) {
|
||||
printf("setcommtimeout ret: %d\n", ret);
|
||||
}
|
||||
|
||||
state = 2; /* raw serial */
|
||||
scc_ptr->state = state;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_win_change_params(int port)
|
||||
{
|
||||
DCB *dcbptr;
|
||||
HANDLE host_handle;
|
||||
Scc *scc_ptr;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
host_handle = scc_ptr->host_handle;
|
||||
dcbptr = scc_ptr->host_handle2;
|
||||
if(host_handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = GetCommState(host_handle, dcbptr);
|
||||
if(ret == 0) {
|
||||
printf("getcomm port%d ret: %d\n", port, ret);
|
||||
}
|
||||
|
||||
#if 1
|
||||
printf("dcb.baudrate: %d, bytesize:%d, stops:%d, parity:%d\n",
|
||||
(int)dcbptr->BaudRate, (int)dcbptr->ByteSize,
|
||||
(int)dcbptr->StopBits, (int)dcbptr->Parity);
|
||||
printf("dcb.binary: %d, ctsflow: %d, dsrflow: %d, dtr: %d, dsr: %d\n",
|
||||
(int)dcbptr->fBinary,
|
||||
(int)dcbptr->fOutxCtsFlow,
|
||||
(int)dcbptr->fOutxDsrFlow,
|
||||
(int)dcbptr->fDtrControl,
|
||||
(int)dcbptr->fDsrSensitivity);
|
||||
printf("dcb.txonxoff:%d, outx:%d, inx: %d, null: %d, rts: %d\n",
|
||||
(int)dcbptr->fTXContinueOnXoff,
|
||||
(int)dcbptr->fOutX,
|
||||
(int)dcbptr->fInX,
|
||||
(int)dcbptr->fNull,
|
||||
(int)dcbptr->fRtsControl);
|
||||
printf("dcb.fAbortOnErr:%d, fParity:%d\n", (int)dcbptr->fAbortOnError,
|
||||
(int)dcbptr->fParity);
|
||||
#endif
|
||||
|
||||
dcbptr->fAbortOnError = 0;
|
||||
|
||||
dcbptr->BaudRate = scc_ptr->baud_rate;
|
||||
dcbptr->ByteSize = scc_ptr->char_size;
|
||||
dcbptr->StopBits = ONESTOPBIT;
|
||||
switch((scc_ptr->reg[4] >> 2) & 0x3) {
|
||||
case 2: // 1.5 stop bits
|
||||
dcbptr->StopBits = ONE5STOPBITS;
|
||||
break;
|
||||
case 3: // 2 stop bits
|
||||
dcbptr->StopBits = TWOSTOPBITS;
|
||||
break;
|
||||
}
|
||||
|
||||
dcbptr->Parity = NOPARITY;
|
||||
switch((scc_ptr->reg[4]) & 0x3) {
|
||||
case 1: // Odd parity
|
||||
dcbptr->Parity = ODDPARITY;
|
||||
break;
|
||||
case 3: // Even parity
|
||||
dcbptr->Parity = EVENPARITY;
|
||||
break;
|
||||
}
|
||||
|
||||
dcbptr->fNull = 0;
|
||||
dcbptr->fDtrControl = DTR_CONTROL_ENABLE;
|
||||
dcbptr->fDsrSensitivity = 0;
|
||||
dcbptr->fOutxCtsFlow = 0;
|
||||
dcbptr->fOutxDsrFlow = 0;
|
||||
dcbptr->fParity = 0;
|
||||
dcbptr->fInX = 0;
|
||||
dcbptr->fOutX = 0;
|
||||
dcbptr->fRtsControl = RTS_CONTROL_ENABLE;
|
||||
|
||||
ret = SetCommState(host_handle, dcbptr);
|
||||
if(ret == 0) {
|
||||
printf("SetCommState ret: %d, new baud: %d\n", ret,
|
||||
(int)dcbptr->BaudRate);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_win_fill_readbuf(int port, double dcycs)
|
||||
{
|
||||
byte tmp_buf[256];
|
||||
Scc *scc_ptr;
|
||||
HANDLE host_handle;
|
||||
DWORD bytes_read;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
host_handle = scc_ptr->host_handle;
|
||||
if(host_handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try reading some bytes */
|
||||
ret = ReadFile(host_handle, tmp_buf, 256, &bytes_read, NULL);
|
||||
|
||||
if(ret == 0) {
|
||||
printf("ReadFile ret 0\n");
|
||||
}
|
||||
|
||||
if(ret && (bytes_read > 0)) {
|
||||
for(i = 0; i < bytes_read; i++) {
|
||||
scc_add_to_readbuf(port, tmp_buf[i], dcycs);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
scc_serial_win_empty_writebuf(int port)
|
||||
{
|
||||
Scc *scc_ptr;
|
||||
HANDLE host_handle;
|
||||
int rdptr;
|
||||
int wrptr;
|
||||
int done;
|
||||
word32 err_code;
|
||||
DWORD bytes_written;
|
||||
int ret;
|
||||
int len;
|
||||
|
||||
scc_ptr = &(scc_stat[port]);
|
||||
|
||||
//printf("win_empty_writebuf, host_handle: %d\n", scc_ptr->host_handle);
|
||||
host_handle = scc_ptr->host_handle;
|
||||
if(host_handle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try writing some bytes */
|
||||
done = 0;
|
||||
while(!done) {
|
||||
rdptr = scc_ptr->out_rdptr;
|
||||
wrptr = scc_ptr->out_wrptr;
|
||||
if(rdptr == wrptr) {
|
||||
//printf("...rdptr == wrptr\n");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
len = wrptr - rdptr;
|
||||
if(len < 0) {
|
||||
len = SCC_OUTBUF_SIZE - rdptr;
|
||||
}
|
||||
if(len > 32) {
|
||||
len = 32;
|
||||
}
|
||||
if(len <= 0) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
bytes_written = 1;
|
||||
ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len,
|
||||
&bytes_written, NULL);
|
||||
printf("WriteFile ret: %d, bytes_written:%d, len:%d\n", ret,
|
||||
(int)bytes_written, len);
|
||||
|
||||
err_code = (word32)-1;
|
||||
if(ret == 0) {
|
||||
err_code = (word32)GetLastError();
|
||||
printf("WriteFile ret:0, err_code: %08x\n", err_code);
|
||||
}
|
||||
|
||||
if(ret == 0 || (bytes_written == 0)) {
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
rdptr = rdptr + bytes_written;
|
||||
if(rdptr >= SCC_OUTBUF_SIZE) {
|
||||
rdptr = rdptr - SCC_OUTBUF_SIZE;
|
||||
}
|
||||
scc_ptr->out_rdptr = rdptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,274 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_S
|
||||
.stringz "@(#)$KmKId: size_tab.h,v 1.13 2002-11-19 03:10:38-05 kadickey Exp $"
|
||||
#else
|
||||
|
||||
.word inst00_SYM+1 /* brk */
|
||||
.word inst01_SYM+1 /* ORA (Dloc,X) */
|
||||
.word inst02_SYM+1 /* COP */
|
||||
.word inst03_SYM+1 /* ORA Disp8,S */
|
||||
.word inst04_SYM+1 /* TSB Dloc */
|
||||
.word inst05_SYM+1 /* ORA Dloc */
|
||||
.word inst06_SYM+1 /* ASL Dloc */
|
||||
.word inst07_SYM+1 /* ORA [Dloc] */
|
||||
.word inst08_SYM+0 /* PHP */
|
||||
.word inst09_SYM+4 /* ORA #imm */
|
||||
.word inst0a_SYM+0 /* ASL a */
|
||||
.word inst0b_SYM+0 /* PHD */
|
||||
.word inst0c_SYM+2 /* TSB abs */
|
||||
.word inst0d_SYM+2 /* ORA abs */
|
||||
.word inst0e_SYM+2 /* ASL abs */
|
||||
.word inst0f_SYM+3 /* ORA long */
|
||||
.word inst10_SYM+1 /* BPL disp8 */
|
||||
.word inst11_SYM+1 /* ORA (),y */
|
||||
.word inst12_SYM+1 /* ORA () */
|
||||
.word inst13_SYM+1 /* ORA (disp8,s),y */
|
||||
.word inst14_SYM+1 /* TRB Dloc */
|
||||
.word inst15_SYM+1 /* ORA Dloc,x */
|
||||
.word inst16_SYM+1 /* ASL Dloc,x */
|
||||
.word inst17_SYM+1 /* ORA [],y */
|
||||
.word inst18_SYM+0 /* clc */
|
||||
.word inst19_SYM+2 /* ORA abs,y */
|
||||
.word inst1a_SYM+0 /* INC a */
|
||||
.word inst1b_SYM+0 /* TCS */
|
||||
.word inst1c_SYM+2 /* TRB Abs */
|
||||
.word inst1d_SYM+2 /* ORA Abs,X */
|
||||
.word inst1e_SYM+2 /* ASL abs,x */
|
||||
.word inst1f_SYM+3 /* ORA Long,x */
|
||||
.word inst20_SYM+2 /* JSR abs */
|
||||
.word inst21_SYM+1 /* AND (Dloc,X) */
|
||||
.word inst22_SYM+3 /* JSL Abslong */
|
||||
.word inst23_SYM+1 /* AND Disp8,S */
|
||||
.word inst24_SYM+1 /* BIT Dloc */
|
||||
.word inst25_SYM+1 /* AND Dloc */
|
||||
.word inst26_SYM+1 /* ROL Dloc */
|
||||
.word inst27_SYM+1 /* AND [Dloc] */
|
||||
.word inst28_SYM+0 /* PLP */
|
||||
.word inst29_SYM+4 /* AND #imm */
|
||||
.word inst2a_SYM+0 /* ROL a */
|
||||
.word inst2b_SYM+0 /* PLD */
|
||||
.word inst2c_SYM+2 /* BIT abs */
|
||||
.word inst2d_SYM+2 /* AND abs */
|
||||
.word inst2e_SYM+2 /* ROL abs */
|
||||
.word inst2f_SYM+3 /* AND long */
|
||||
.word inst30_SYM+1 /* BMI disp8 */
|
||||
.word inst31_SYM+1 /* AND (),y */
|
||||
.word inst32_SYM+1 /* AND () */
|
||||
.word inst33_SYM+1 /* AND (disp8,s),y */
|
||||
.word inst34_SYM+1 /* BIT Dloc,X */
|
||||
.word inst35_SYM+1 /* AND Dloc,x */
|
||||
.word inst36_SYM+1 /* ROL Dloc,x */
|
||||
.word inst37_SYM+1 /* AND [],y */
|
||||
.word inst38_SYM+0 /* SEC */
|
||||
.word inst39_SYM+2 /* AND abs,y */
|
||||
.word inst3a_SYM+0 /* DEC a */
|
||||
.word inst3b_SYM+0 /* TSC */
|
||||
.word inst3c_SYM+2 /* BIT Abs,X */
|
||||
.word inst3d_SYM+2 /* AND Abs,X */
|
||||
.word inst3e_SYM+2 /* ROL abs,x */
|
||||
.word inst3f_SYM+3 /* AND Long,x */
|
||||
.word inst40_SYM+0 /* RTI */
|
||||
.word inst41_SYM+1 /* EOR (Dloc,X) */
|
||||
.word inst42_SYM+1 /* WDM */
|
||||
.word inst43_SYM+1 /* EOR Disp8,S */
|
||||
.word inst44_SYM+2 /* MVP I,J */
|
||||
.word inst45_SYM+1 /* EOR Dloc */
|
||||
.word inst46_SYM+1 /* LSR Dloc */
|
||||
.word inst47_SYM+1 /* EOR [Dloc] */
|
||||
.word inst48_SYM+0 /* PHA */
|
||||
.word inst49_SYM+4 /* EOR #imm */
|
||||
.word inst4a_SYM+0 /* LSR a */
|
||||
.word inst4b_SYM+0 /* PHK */
|
||||
.word inst4c_SYM+2 /* JMP abs */
|
||||
.word inst4d_SYM+2 /* EOR abs */
|
||||
.word inst4e_SYM+2 /* LSR abs */
|
||||
.word inst4f_SYM+3 /* EOR long */
|
||||
.word inst50_SYM+1 /* BVC disp8 */
|
||||
.word inst51_SYM+1 /* EOR (),y */
|
||||
.word inst52_SYM+1 /* EOR () */
|
||||
.word inst53_SYM+1 /* EOR (disp8,s),y */
|
||||
.word inst54_SYM+2 /* MVN I,J */
|
||||
.word inst55_SYM+1 /* EOR Dloc,x */
|
||||
.word inst56_SYM+1 /* LSR Dloc,x */
|
||||
.word inst57_SYM+1 /* EOR [],y */
|
||||
.word inst58_SYM+0 /* CLI */
|
||||
.word inst59_SYM+2 /* EOR abs,y */
|
||||
.word inst5a_SYM+0 /* PHY */
|
||||
.word inst5b_SYM+0 /* TCD */
|
||||
.word inst5c_SYM+3 /* JMP Long */
|
||||
.word inst5d_SYM+2 /* EOR Abs,X */
|
||||
.word inst5e_SYM+2 /* LSR abs,x */
|
||||
.word inst5f_SYM+3 /* EOR Long,x */
|
||||
.word inst60_SYM+0 /* RTS */
|
||||
.word inst61_SYM+1 /* ADC (Dloc,X) */
|
||||
.word inst62_SYM+2 /* PER DISP16 */
|
||||
.word inst63_SYM+1 /* ADC Disp8,S */
|
||||
.word inst64_SYM+1 /* STZ Dloc */
|
||||
.word inst65_SYM+1 /* ADC Dloc */
|
||||
.word inst66_SYM+1 /* ROR Dloc */
|
||||
.word inst67_SYM+1 /* ADC [Dloc] */
|
||||
.word inst68_SYM+0 /* PLA */
|
||||
.word inst69_SYM+4 /* ADC #imm */
|
||||
.word inst6a_SYM+0 /* ROR a */
|
||||
.word inst6b_SYM+0 /* RTL */
|
||||
.word inst6c_SYM+2 /* JMP (abs) */
|
||||
.word inst6d_SYM+2 /* ADC abs */
|
||||
.word inst6e_SYM+2 /* ROR abs */
|
||||
.word inst6f_SYM+3 /* ADC long */
|
||||
.word inst70_SYM+1 /* BVS disp8 */
|
||||
.word inst71_SYM+1 /* ADC (),y */
|
||||
.word inst72_SYM+1 /* ADC () */
|
||||
.word inst73_SYM+1 /* ADC (disp8,s),y */
|
||||
.word inst74_SYM+1 /* STZ Dloc,X */
|
||||
.word inst75_SYM+1 /* ADC Dloc,x */
|
||||
.word inst76_SYM+1 /* ROR Dloc,x */
|
||||
.word inst77_SYM+1 /* ADC [],y */
|
||||
.word inst78_SYM+0 /* SEI */
|
||||
.word inst79_SYM+2 /* ADC abs,y */
|
||||
.word inst7a_SYM+0 /* PLY */
|
||||
.word inst7b_SYM+0 /* TDC */
|
||||
.word inst7c_SYM+2 /* JMP (abs,x) */
|
||||
.word inst7d_SYM+2 /* ADC Abs,X */
|
||||
.word inst7e_SYM+2 /* ROR abs,x */
|
||||
.word inst7f_SYM+3 /* ADC Long,x */
|
||||
.word inst80_SYM+1 /* BRA Disp8 */
|
||||
.word inst81_SYM+1 /* STA (Dloc,X) */
|
||||
.word inst82_SYM+2 /* BRL DISP16 */
|
||||
.word inst83_SYM+1 /* STA Disp8,S */
|
||||
.word inst84_SYM+1 /* STY Dloc */
|
||||
.word inst85_SYM+1 /* STA Dloc */
|
||||
.word inst86_SYM+1 /* STX Dloc */
|
||||
.word inst87_SYM+1 /* STA [Dloc] */
|
||||
.word inst88_SYM+0 /* DEY */
|
||||
.word inst89_SYM+4 /* BIT #imm */
|
||||
.word inst8a_SYM+0 /* TXA */
|
||||
.word inst8b_SYM+0 /* PHB */
|
||||
.word inst8c_SYM+2 /* STY abs */
|
||||
.word inst8d_SYM+2 /* STA abs */
|
||||
.word inst8e_SYM+2 /* STX abs */
|
||||
.word inst8f_SYM+3 /* STA long */
|
||||
.word inst90_SYM+1 /* BCC disp8 */
|
||||
.word inst91_SYM+1 /* STA (),y */
|
||||
.word inst92_SYM+1 /* STA () */
|
||||
.word inst93_SYM+1 /* STA (disp8,s),y */
|
||||
.word inst94_SYM+1 /* STY Dloc,X */
|
||||
.word inst95_SYM+1 /* STA Dloc,x */
|
||||
.word inst96_SYM+1 /* STX Dloc,y */
|
||||
.word inst97_SYM+1 /* STA [],y */
|
||||
.word inst98_SYM+0 /* TYA */
|
||||
.word inst99_SYM+2 /* STA abs,y */
|
||||
.word inst9a_SYM+0 /* TXS */
|
||||
.word inst9b_SYM+0 /* TXY */
|
||||
.word inst9c_SYM+2 /* STX abs */
|
||||
.word inst9d_SYM+2 /* STA Abs,X */
|
||||
.word inst9e_SYM+2 /* STZ abs,x */
|
||||
.word inst9f_SYM+3 /* STA Long,x */
|
||||
.word insta0_SYM+5 /* LDY #imm */
|
||||
.word insta1_SYM+1 /* LDA (Dloc,X) */
|
||||
.word insta2_SYM+5 /* LDX #imm */
|
||||
.word insta3_SYM+1 /* LDA Disp8,S */
|
||||
.word insta4_SYM+1 /* LDY Dloc */
|
||||
.word insta5_SYM+1 /* LDA Dloc */
|
||||
.word insta6_SYM+1 /* LDX Dloc */
|
||||
.word insta7_SYM+1 /* LDA [Dloc] */
|
||||
.word insta8_SYM+0 /* TAY */
|
||||
.word insta9_SYM+4 /* LDA #imm */
|
||||
.word instaa_SYM+0 /* TAX */
|
||||
.word instab_SYM+0 /* PLB */
|
||||
.word instac_SYM+2 /* LDY abs */
|
||||
.word instad_SYM+2 /* LDA abs */
|
||||
.word instae_SYM+2 /* LDX abs */
|
||||
.word instaf_SYM+3 /* LDA long */
|
||||
.word instb0_SYM+1 /* BCS disp8 */
|
||||
.word instb1_SYM+1 /* LDA (),y */
|
||||
.word instb2_SYM+1 /* LDA () */
|
||||
.word instb3_SYM+1 /* LDA (disp8,s),y */
|
||||
.word instb4_SYM+1 /* LDY Dloc,X */
|
||||
.word instb5_SYM+1 /* LDA Dloc,x */
|
||||
.word instb6_SYM+1 /* LDX Dloc,y */
|
||||
.word instb7_SYM+1 /* LDA [],y */
|
||||
.word instb8_SYM+0 /* CLV */
|
||||
.word instb9_SYM+2 /* LDA abs,y */
|
||||
.word instba_SYM+0 /* TSX */
|
||||
.word instbb_SYM+0 /* TYX */
|
||||
.word instbc_SYM+2 /* LDY abs,x */
|
||||
.word instbd_SYM+2 /* LDA Abs,X */
|
||||
.word instbe_SYM+2 /* LDX abs,y */
|
||||
.word instbf_SYM+3 /* LDA Long,x */
|
||||
.word instc0_SYM+5 /* CPY #Imm */
|
||||
.word instc1_SYM+1 /* CMP (Dloc,X) */
|
||||
.word instc2_SYM+1 /* REP #8bit */
|
||||
.word instc3_SYM+1 /* CMP Disp8,S */
|
||||
.word instc4_SYM+1 /* CPY Dloc */
|
||||
.word instc5_SYM+1 /* CMP Dloc */
|
||||
.word instc6_SYM+1 /* DEC Dloc */
|
||||
.word instc7_SYM+1 /* CMP [Dloc] */
|
||||
.word instc8_SYM+0 /* INY */
|
||||
.word instc9_SYM+4 /* CMP #imm */
|
||||
.word instca_SYM+0 /* DEX */
|
||||
.word instcb_SYM+0 /* WAI */
|
||||
.word instcc_SYM+2 /* CPY abs */
|
||||
.word instcd_SYM+2 /* CMP abs */
|
||||
.word instce_SYM+2 /* DEC abs */
|
||||
.word instcf_SYM+3 /* CMP long */
|
||||
.word instd0_SYM+1 /* BNE disp8 */
|
||||
.word instd1_SYM+1 /* CMP (),y */
|
||||
.word instd2_SYM+1 /* CMP () */
|
||||
.word instd3_SYM+1 /* CMP (disp8,s),y */
|
||||
.word instd4_SYM+1 /* PEI Dloc */
|
||||
.word instd5_SYM+1 /* CMP Dloc,x */
|
||||
.word instd6_SYM+1 /* DEC Dloc,x */
|
||||
.word instd7_SYM+1 /* CMP [],y */
|
||||
.word instd8_SYM+0 /* CLD */
|
||||
.word instd9_SYM+2 /* CMP abs,y */
|
||||
.word instda_SYM+0 /* PHX */
|
||||
.word instdb_SYM+0 /* STP */
|
||||
.word instdc_SYM+2 /* JML (Abs) */
|
||||
.word instdd_SYM+2 /* CMP Abs,X */
|
||||
.word instde_SYM+2 /* DEC abs,x */
|
||||
.word instdf_SYM+3 /* CMP Long,x */
|
||||
.word inste0_SYM+5 /* CPX #Imm */
|
||||
.word inste1_SYM+1 /* SBC (Dloc,X) */
|
||||
.word inste2_SYM+1 /* SEP #8bit */
|
||||
.word inste3_SYM+1 /* SBC Disp8,S */
|
||||
.word inste4_SYM+1 /* CPX Dloc */
|
||||
.word inste5_SYM+1 /* SBC Dloc */
|
||||
.word inste6_SYM+1 /* INC Dloc */
|
||||
.word inste7_SYM+1 /* SBC [Dloc] */
|
||||
.word inste8_SYM+0 /* INX */
|
||||
.word inste9_SYM+4 /* SBC #imm */
|
||||
.word instea_SYM+0 /* NOP */
|
||||
.word insteb_SYM+0 /* XBA */
|
||||
.word instec_SYM+2 /* CPX abs */
|
||||
.word insted_SYM+2 /* SBC abs */
|
||||
.word instee_SYM+2 /* INC abs */
|
||||
.word instef_SYM+3 /* SBC long */
|
||||
.word instf0_SYM+1 /* BEQ disp8 */
|
||||
.word instf1_SYM+1 /* SBC (),y */
|
||||
.word instf2_SYM+1 /* SBC () */
|
||||
.word instf3_SYM+1 /* SBC (disp8,s),y */
|
||||
.word instf4_SYM+2 /* PEA Imm */
|
||||
.word instf5_SYM+1 /* SBC Dloc,x */
|
||||
.word instf6_SYM+1 /* INC Dloc,x */
|
||||
.word instf7_SYM+1 /* SBC [],y */
|
||||
.word instf8_SYM+0 /* SED */
|
||||
.word instf9_SYM+2 /* SBC abs,y */
|
||||
.word instfa_SYM+0 /* PLX */
|
||||
.word instfb_SYM+0 /* XCE */
|
||||
.word instfc_SYM+2 /* JSR (Abs,x) */
|
||||
.word instfd_SYM+2 /* SBC Abs,X */
|
||||
.word instfe_SYM+2 /* INC abs,x */
|
||||
.word instff_SYM+3 /* SBC Long,x */
|
||||
|
||||
.block 4*16
|
||||
|
||||
#endif
|
|
@ -0,0 +1,783 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_smartport_c[] = "@(#)$KmKId: smartport.c,v 1.29 2003-11-17 15:44:44-05 kentd Exp $";
|
||||
|
||||
#include "defc.h"
|
||||
|
||||
extern int Verbose;
|
||||
extern int Halt_on;
|
||||
extern int g_rom_version;
|
||||
extern int g_io_amt;
|
||||
extern int g_highest_smartport_unit;
|
||||
|
||||
int g_cycs_in_io_read = 0;
|
||||
|
||||
extern Engine_reg engine;
|
||||
|
||||
extern Iwm iwm;
|
||||
|
||||
#define LEN_SMPT_LOG 16
|
||||
STRUCT(Smpt_log) {
|
||||
word32 start_addr;
|
||||
int cmd;
|
||||
int rts_addr;
|
||||
int cmd_list;
|
||||
int extras;
|
||||
int unit;
|
||||
int buf;
|
||||
int blk;
|
||||
};
|
||||
|
||||
Smpt_log g_smpt_log[LEN_SMPT_LOG];
|
||||
int g_smpt_log_pos = 0;
|
||||
|
||||
void
|
||||
smartport_error(void)
|
||||
{
|
||||
int pos;
|
||||
int i;
|
||||
|
||||
pos = g_smpt_log_pos;
|
||||
printf("Smartport log pos: %d\n", pos);
|
||||
for(i = 0; i < LEN_SMPT_LOG; i++) {
|
||||
pos--;
|
||||
if(pos < 0) {
|
||||
pos = LEN_SMPT_LOG - 1;
|
||||
}
|
||||
printf("%d:%d: t:%04x, cmd:%02x, rts:%04x, "
|
||||
"cmd_l:%04x, x:%d, unit:%d, buf:%04x, blk:%04x\n",
|
||||
i, pos,
|
||||
g_smpt_log[pos].start_addr,
|
||||
g_smpt_log[pos].cmd,
|
||||
g_smpt_log[pos].rts_addr,
|
||||
g_smpt_log[pos].cmd_list,
|
||||
g_smpt_log[pos].extras,
|
||||
g_smpt_log[pos].unit,
|
||||
g_smpt_log[pos].buf,
|
||||
g_smpt_log[pos].blk);
|
||||
}
|
||||
}
|
||||
void
|
||||
smartport_log(word32 start_addr, int cmd, int rts_addr, int cmd_list)
|
||||
{
|
||||
int pos;
|
||||
|
||||
pos = g_smpt_log_pos;
|
||||
if(start_addr != 0) {
|
||||
g_smpt_log[pos].start_addr = start_addr;
|
||||
g_smpt_log[pos].cmd = cmd;
|
||||
g_smpt_log[pos].rts_addr = rts_addr;
|
||||
g_smpt_log[pos].cmd_list = cmd_list;
|
||||
g_smpt_log[pos].extras = 0;
|
||||
g_smpt_log[pos].unit = 0;
|
||||
g_smpt_log[pos].buf = 0;
|
||||
g_smpt_log[pos].blk = 0;
|
||||
} else {
|
||||
pos--;
|
||||
if(pos < 0) {
|
||||
pos = LEN_SMPT_LOG - 1;
|
||||
}
|
||||
g_smpt_log[pos].extras = 1;
|
||||
g_smpt_log[pos].unit = cmd;
|
||||
g_smpt_log[pos].buf = rts_addr;
|
||||
g_smpt_log[pos].blk = cmd_list;
|
||||
}
|
||||
pos++;
|
||||
if(pos >= LEN_SMPT_LOG) {
|
||||
pos = 0;
|
||||
}
|
||||
g_smpt_log_pos = pos;
|
||||
}
|
||||
|
||||
void
|
||||
do_c70d(word32 arg0)
|
||||
{
|
||||
int cmd;
|
||||
int cmd_list_lo, cmd_list_mid, cmd_list_hi;
|
||||
int rts_lo, rts_hi;
|
||||
word32 rts_addr;
|
||||
word32 cmd_list;
|
||||
int unit;
|
||||
int param_cnt;
|
||||
int status_ptr_lo, status_ptr_mid, status_ptr_hi;
|
||||
int buf_ptr_lo, buf_ptr_hi;
|
||||
int buf_ptr;
|
||||
int block_lo, block_mid, block_hi;
|
||||
int block;
|
||||
word32 status_ptr;
|
||||
int status_code;
|
||||
int ctl_ptr_lo, ctl_ptr_hi;
|
||||
int ctl_ptr;
|
||||
int ctl_code;
|
||||
int mask;
|
||||
int stat_val;
|
||||
int size;
|
||||
int ret;
|
||||
int ext;
|
||||
int i;
|
||||
|
||||
set_memory_c(0x7f8, 0xc7, 0);
|
||||
|
||||
if((engine.psr & 0x100) == 0) {
|
||||
disk_printf("c70d called in native mode!\n");
|
||||
if((engine.psr & 0x30) != 0x30) {
|
||||
halt_printf("c70d called native, psr: %03x!\n",
|
||||
engine.psr);
|
||||
}
|
||||
}
|
||||
|
||||
engine.stack = ((engine.stack + 1) & 0xff) + 0x100;
|
||||
rts_lo = get_memory_c(engine.stack, 0);
|
||||
engine.stack = ((engine.stack + 1) & 0xff) + 0x100;
|
||||
rts_hi = get_memory_c(engine.stack, 0);
|
||||
rts_addr = (rts_lo + (256*rts_hi) + 1) & 0xffff;
|
||||
disk_printf("rts_addr: %04x\n", rts_addr);
|
||||
|
||||
cmd = get_memory_c(rts_addr, 0);
|
||||
cmd_list_lo = get_memory_c((rts_addr + 1) & 0xffff, 0);
|
||||
cmd_list_mid = get_memory_c((rts_addr + 2) & 0xffff, 0);
|
||||
cmd_list_hi = 0;
|
||||
mask = 0xffff;
|
||||
if(cmd & 0x40) {
|
||||
/* extended */
|
||||
mask = 0xffffff;
|
||||
cmd_list_hi = get_memory_c((rts_addr + 3) & 0xffff, 0);
|
||||
}
|
||||
|
||||
cmd_list = cmd_list_lo + (256*cmd_list_mid) + (65536*cmd_list_hi);
|
||||
|
||||
disk_printf("cmd: %02x, cmd_list: %06x\n", cmd, cmd_list);
|
||||
param_cnt = get_memory_c(cmd_list, 0);
|
||||
|
||||
ext = 0;
|
||||
if(cmd & 0x40) {
|
||||
ext = 2;
|
||||
}
|
||||
|
||||
smartport_log(0xc70d, cmd, rts_addr, cmd_list);
|
||||
|
||||
switch(cmd & 0x3f) {
|
||||
case 0x00: /* Status == 0x00 and 0x40 */
|
||||
if(param_cnt != 3) {
|
||||
disk_printf("param_cnt %d is != 3!\n", param_cnt);
|
||||
exit(8);
|
||||
}
|
||||
unit = get_memory_c((cmd_list+1) & mask, 0);
|
||||
status_ptr_lo = get_memory_c((cmd_list+2) & mask, 0);
|
||||
status_ptr_mid = get_memory_c((cmd_list+3) & mask, 0);
|
||||
status_ptr_hi = 0;
|
||||
if(cmd & 0x40) {
|
||||
status_ptr_hi = get_memory_c((cmd_list+4) & mask, 0);
|
||||
}
|
||||
|
||||
status_ptr = status_ptr_lo + (256*status_ptr_mid) +
|
||||
(65536*status_ptr_hi);
|
||||
if(cmd & 0x40) {
|
||||
status_code = get_memory_c((cmd_list+6) & mask, 0);
|
||||
} else {
|
||||
status_code = get_memory_c((cmd_list+4) & mask, 0);
|
||||
}
|
||||
|
||||
smartport_log(0, unit, status_ptr, status_code);
|
||||
|
||||
disk_printf("unit: %02x, status_ptr: %06x, code: %02x\n",
|
||||
unit, status_ptr, status_code);
|
||||
if(unit == 0 && status_code == 0) {
|
||||
/* Smartport driver status */
|
||||
/* see technotes/smpt/tn-smpt-002 */
|
||||
set_memory_c(status_ptr, g_highest_smartport_unit+1, 0);
|
||||
set_memory_c(status_ptr+1, 0xff, 0); /* interrupt stat*/
|
||||
set_memory_c(status_ptr+2, 0x02, 0); /* vendor id */
|
||||
set_memory_c(status_ptr+3, 0x00, 0); /* vendor id */
|
||||
set_memory_c(status_ptr+4, 0x00, 0); /* version lo */
|
||||
set_memory_c(status_ptr+5, 0x10, 0); /* version hi */
|
||||
set_memory_c(status_ptr+6, 0x00, 0);
|
||||
set_memory_c(status_ptr+7, 0x00, 0);
|
||||
|
||||
engine.xreg = 8;
|
||||
engine.yreg = 0;
|
||||
engine.acc &= 0xff00;
|
||||
engine.psr &= ~1;
|
||||
engine.kpc = (rts_addr + 3 + ext) & mask;
|
||||
return;
|
||||
} else if(unit > 0 && status_code == 0) {
|
||||
/* status for unit x */
|
||||
if(unit > MAX_C7_DISKS || iwm.smartport[unit-1].fd < 0){
|
||||
stat_val = 0x80;
|
||||
size = 0;
|
||||
} else {
|
||||
stat_val = 0xf8;
|
||||
size = iwm.smartport[unit-1].image_size;
|
||||
size = (size+511) / 512;
|
||||
}
|
||||
set_memory_c(status_ptr, stat_val, 0);
|
||||
set_memory_c(status_ptr +1, size & 0xff, 0);
|
||||
set_memory_c(status_ptr +2, (size >> 8) & 0xff, 0);
|
||||
set_memory_c(status_ptr +3, (size >> 16) & 0xff, 0);
|
||||
engine.xreg = 4;
|
||||
if(cmd & 0x40) {
|
||||
set_memory_c(status_ptr + 4,
|
||||
(size >> 16) & 0xff, 0);
|
||||
engine.xreg = 5;
|
||||
}
|
||||
engine.yreg = 0;
|
||||
engine.acc &= 0xff00;
|
||||
engine.psr &= ~1;
|
||||
engine.kpc = (rts_addr + 3 + ext) & mask;
|
||||
|
||||
disk_printf("just finished unit %d, stat 0\n", unit);
|
||||
return;
|
||||
} else if(status_code == 3) {
|
||||
if(unit > MAX_C7_DISKS || iwm.smartport[unit-1].fd < 0){
|
||||
stat_val = 0x80;
|
||||
size = 0;
|
||||
} else {
|
||||
stat_val = 0xf8;
|
||||
size = iwm.smartport[unit-1].image_size;
|
||||
size = (size+511) / 512;
|
||||
}
|
||||
if(cmd & 0x40) {
|
||||
disk_printf("extended for stat_code 3!\n");
|
||||
}
|
||||
/* DIB for unit 1 */
|
||||
set_memory_c(status_ptr, stat_val, 0);
|
||||
set_memory_c(status_ptr +1, size & 0xff, 0);
|
||||
set_memory_c(status_ptr +2, (size >> 8) & 0xff, 0);
|
||||
set_memory_c(status_ptr +3, (size >> 16) & 0xff, 0);
|
||||
if(cmd & 0x40) {
|
||||
set_memory_c(status_ptr + 4,
|
||||
(size >> 24) & 0xff, 0);
|
||||
status_ptr++;
|
||||
}
|
||||
set_memory_c(status_ptr +4, 4, 0);
|
||||
for(i = 5; i < 21; i++) {
|
||||
set_memory_c(status_ptr +i, 0x20, 0);
|
||||
}
|
||||
set_memory_c(status_ptr +5, 'K', 0);
|
||||
set_memory_c(status_ptr +6, 'E', 0);
|
||||
set_memory_c(status_ptr +7, 'G', 0);
|
||||
set_memory_c(status_ptr +8, 'S', 0);
|
||||
|
||||
/* hard disk supporting extended calls */
|
||||
set_memory_c(status_ptr + 21, 0x02, 0);
|
||||
set_memory_c(status_ptr + 22, 0xa0, 0);
|
||||
|
||||
set_memory_c(status_ptr + 23, 0x00, 0);
|
||||
set_memory_c(status_ptr + 24, 0x00, 0);
|
||||
|
||||
if(cmd & 0x40) {
|
||||
engine.xreg = 26;
|
||||
} else {
|
||||
engine.xreg = 25;
|
||||
}
|
||||
engine.yreg = 0;
|
||||
engine.acc &= 0xff00;
|
||||
engine.psr &= ~1;
|
||||
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
|
||||
|
||||
disk_printf("Just finished unit %d, stat 3\n", unit);
|
||||
if(unit == 0 || unit > MAX_C7_DISKS) {
|
||||
engine.acc |= 0x28;
|
||||
engine.psr |= 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
printf("cmd: 00, unknown unit/status code!\n");
|
||||
break;
|
||||
case 0x01: /* Read Block == 0x01 and 0x41 */
|
||||
if(param_cnt != 3) {
|
||||
halt_printf("param_cnt %d is != 3!\n", param_cnt);
|
||||
return;
|
||||
}
|
||||
unit = get_memory_c((cmd_list+1) & mask, 0);
|
||||
buf_ptr_lo = get_memory_c((cmd_list+2) & mask, 0);
|
||||
buf_ptr_hi = get_memory_c((cmd_list+3) & mask, 0);
|
||||
|
||||
buf_ptr = buf_ptr_lo + (256*buf_ptr_hi);
|
||||
if(cmd & 0x40) {
|
||||
buf_ptr_lo = get_memory_c((cmd_list+4) & mask, 0);
|
||||
buf_ptr_hi = get_memory_c((cmd_list+5) & mask, 0);
|
||||
buf_ptr += ((buf_ptr_hi*256) + buf_ptr_lo)*65536;
|
||||
cmd_list += 2;
|
||||
}
|
||||
block_lo = get_memory_c((cmd_list+4) & mask, 0);
|
||||
block_mid = get_memory_c((cmd_list+5) & mask, 0);
|
||||
block_hi = get_memory_c((cmd_list+6) & mask, 0);
|
||||
block = ((block_hi*256) + block_mid)*256 + block_lo;
|
||||
disk_printf("smartport read unit %d of block %04x into %04x\n",
|
||||
unit, block, buf_ptr);
|
||||
if(unit < 1 || unit > MAX_C7_DISKS) {
|
||||
halt_printf("Unknown unit #: %d\n", unit);
|
||||
}
|
||||
|
||||
smartport_log(0, unit - 1, buf_ptr, block);
|
||||
|
||||
ret = do_read_c7(unit - 1, buf_ptr, block);
|
||||
engine.xreg = 0;
|
||||
engine.yreg = 2;
|
||||
engine.acc = (engine.acc & 0xff00) | (ret & 0xff);
|
||||
engine.psr &= ~1;
|
||||
if(ret != 0) {
|
||||
engine.psr |= 1;
|
||||
}
|
||||
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
|
||||
|
||||
return;
|
||||
break;
|
||||
case 0x02: /* Write Block == 0x02 and 0x42 */
|
||||
if(param_cnt != 3) {
|
||||
halt_printf("param_cnt %d is != 3!\n", param_cnt);
|
||||
return;
|
||||
}
|
||||
unit = get_memory_c((cmd_list+1) & mask, 0);
|
||||
buf_ptr_lo = get_memory_c((cmd_list+2) & mask, 0);
|
||||
buf_ptr_hi = get_memory_c((cmd_list+3) & mask, 0);
|
||||
|
||||
buf_ptr = buf_ptr_lo + (256*buf_ptr_hi);
|
||||
if(cmd & 0x40) {
|
||||
buf_ptr_lo = get_memory_c((cmd_list+4) & mask, 0);
|
||||
buf_ptr_hi = get_memory_c((cmd_list+5) & mask, 0);
|
||||
buf_ptr += ((buf_ptr_hi*256) + buf_ptr_lo)*65536;
|
||||
cmd_list += 2;
|
||||
}
|
||||
block_lo = get_memory_c((cmd_list+4) & mask, 0);
|
||||
block_mid = get_memory_c((cmd_list+5) & mask, 0);
|
||||
block_hi = get_memory_c((cmd_list+6) & mask, 0);
|
||||
block = ((block_hi*256) + block_mid)*256 + block_lo;
|
||||
disk_printf("smartport write unit %d of block %04x from %04x\n",
|
||||
unit, block, buf_ptr);
|
||||
if(unit < 1 || unit > MAX_C7_DISKS) {
|
||||
halt_printf("Unknown unit #: %d\n", unit);
|
||||
}
|
||||
|
||||
smartport_log(0, unit - 1, buf_ptr, block);
|
||||
|
||||
ret = do_write_c7(unit - 1, buf_ptr, block);
|
||||
engine.xreg = 0;
|
||||
engine.yreg = 2;
|
||||
engine.acc = (engine.acc & 0xff00) | (ret & 0xff);
|
||||
engine.psr &= ~1;
|
||||
if(ret != 0) {
|
||||
engine.psr |= 1;
|
||||
}
|
||||
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
|
||||
|
||||
HALT_ON(HALT_ON_C70D_WRITES, "c70d Write done\n");
|
||||
return;
|
||||
break;
|
||||
case 0x03: /* Format == 0x03 and 0x43 */
|
||||
if(param_cnt != 1) {
|
||||
halt_printf("param_cnt %d is != 1!\n", param_cnt);
|
||||
return;
|
||||
}
|
||||
unit = get_memory_c((cmd_list+1) & mask, 0);
|
||||
|
||||
if(unit < 1 || unit > MAX_C7_DISKS) {
|
||||
halt_printf("Unknown unit #: %d\n", unit);
|
||||
}
|
||||
|
||||
smartport_log(0, unit - 1, 0, 0);
|
||||
|
||||
ret = do_format_c7(unit - 1);
|
||||
engine.xreg = 0;
|
||||
engine.yreg = 2;
|
||||
engine.acc = (engine.acc & 0xff00) | (ret & 0xff);
|
||||
engine.psr &= ~1;
|
||||
if(ret != 0) {
|
||||
engine.psr |= 1;
|
||||
}
|
||||
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
|
||||
|
||||
HALT_ON(HALT_ON_C70D_WRITES, "c70d Format done\n");
|
||||
return;
|
||||
break;
|
||||
case 0x04: /* Control == 0x04 and 0x44 */
|
||||
if(cmd == 0x44) {
|
||||
halt_printf("smartport code 0x44 not supported\n");
|
||||
}
|
||||
if(param_cnt != 3) {
|
||||
halt_printf("param_cnt %d is != 3!\n", param_cnt);
|
||||
return;
|
||||
}
|
||||
unit = get_memory_c((cmd_list+1) & mask, 0);
|
||||
ctl_ptr_lo = get_memory_c((cmd_list+2) & mask, 0);
|
||||
ctl_ptr_hi = get_memory_c((cmd_list+3) & mask, 0);
|
||||
|
||||
ctl_ptr = (ctl_ptr_hi << 8) + ctl_ptr_lo;
|
||||
if(cmd & 0x40) {
|
||||
ctl_ptr_lo = get_memory_c((cmd_list+4) & mask, 0);
|
||||
ctl_ptr_hi = get_memory_c((cmd_list+5) & mask, 0);
|
||||
ctl_ptr += ((ctl_ptr_hi << 8) + ctl_ptr_lo) << 16;
|
||||
cmd_list += 2;
|
||||
}
|
||||
|
||||
ctl_code = get_memory_c((cmd_list +4) & mask, 0);
|
||||
|
||||
switch(ctl_code) {
|
||||
case 0x00:
|
||||
printf("Performing a reset on unit %d\n", unit);
|
||||
break;
|
||||
default:
|
||||
halt_printf("control code: %02x unknown!\n", ctl_code);
|
||||
}
|
||||
|
||||
engine.xreg = 0;
|
||||
engine.yreg = 2;
|
||||
engine.acc &= 0xff00;
|
||||
engine.psr &= ~1;
|
||||
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
|
||||
return;
|
||||
break;
|
||||
default: /* Unknown command! */
|
||||
/* set acc = 1, and set carry, and set kpc */
|
||||
engine.xreg = (rts_addr) & 0xff;
|
||||
engine.yreg = (rts_addr >> 8) & 0xff;
|
||||
engine.acc = (engine.acc & 0xff00) + 0x01;
|
||||
engine.psr |= 0x01; /* set carry */
|
||||
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
|
||||
if(cmd != 0x4a && cmd != 0x48) {
|
||||
/* Finder does 0x4a call before formatting disk */
|
||||
/* Many things do 0x48 call to see online drives */
|
||||
halt_printf("Just did smtport cmd:%02x rts_addr:%04x, "
|
||||
"cmdlst:%06x\n", cmd, rts_addr, cmd_list);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
halt_printf("Unknown smtport cmd:%02x, cmd_list:%06x, rts_addr:%06x\n",
|
||||
cmd, cmd_list, rts_addr);
|
||||
}
|
||||
|
||||
void
|
||||
do_c70a(word32 arg0)
|
||||
{
|
||||
int cmd, unit;
|
||||
int buf_lo, buf_hi;
|
||||
int blk_lo, blk_hi;
|
||||
int blk, buf;
|
||||
int prodos_unit;
|
||||
int size;
|
||||
int ret;
|
||||
|
||||
set_memory_c(0x7f8, 0xc7, 0);
|
||||
|
||||
cmd = get_memory_c((engine.direct + 0x42) & 0xffff, 0);
|
||||
prodos_unit = get_memory_c((engine.direct + 0x43) & 0xffff, 0);
|
||||
buf_lo = get_memory_c((engine.direct + 0x44) & 0xffff, 0);
|
||||
buf_hi = get_memory_c((engine.direct + 0x45) & 0xffff, 0);
|
||||
blk_lo = get_memory_c((engine.direct + 0x46) & 0xffff, 0);
|
||||
blk_hi = get_memory_c((engine.direct + 0x47) & 0xffff, 0);
|
||||
|
||||
blk = (blk_hi << 8) + blk_lo;
|
||||
buf = (buf_hi << 8) + buf_lo;
|
||||
disk_printf("cmd: %02x, pro_unit: %02x, buf: %04x, blk: %04x\n",
|
||||
cmd, prodos_unit, buf, blk);
|
||||
|
||||
if((prodos_unit & 0x7f) == 0x70) {
|
||||
unit = 0 + (prodos_unit >> 7);
|
||||
} else if((prodos_unit & 0x7f) == 0x40) {
|
||||
unit = 2 + (prodos_unit >> 7);
|
||||
} else {
|
||||
halt_printf("Unknown prodos_unit: %d\n", prodos_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
smartport_log(0xc70a, cmd, blk, buf);
|
||||
|
||||
engine.psr &= ~1; /* clear carry */
|
||||
if(g_rom_version >= 3) {
|
||||
engine.kpc = 0xc764;
|
||||
} else {
|
||||
engine.kpc = 0xc765;
|
||||
}
|
||||
|
||||
ret = 0x27; /* I/O error */
|
||||
if(cmd == 0x00) {
|
||||
size = iwm.smartport[unit].image_size;
|
||||
size = (size+511) / 512;
|
||||
|
||||
smartport_log(0, unit, size, 0);
|
||||
|
||||
ret = 0;
|
||||
engine.xreg = size & 0xff;
|
||||
engine.yreg = size >> 8;
|
||||
} else if(cmd == 0x01) {
|
||||
smartport_log(0, unit, buf, blk);
|
||||
ret = do_read_c7(unit, buf, blk);
|
||||
} else if(cmd == 0x02) {
|
||||
smartport_log(0, unit, buf, blk);
|
||||
ret = do_write_c7(unit, buf, blk);
|
||||
} else if(cmd == 0x03) { /* format */
|
||||
smartport_log(0, unit, buf, blk);
|
||||
ret = do_format_c7(unit);
|
||||
}
|
||||
|
||||
engine.acc = (engine.acc & 0xff00) | (ret & 0xff);
|
||||
if(ret != 0) {
|
||||
engine.psr |= 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
do_read_c7(int unit_num, word32 buf, int blk)
|
||||
{
|
||||
byte local_buf[0x200];
|
||||
register word32 start_time;
|
||||
register word32 end_time;
|
||||
word32 val;
|
||||
int len;
|
||||
int fd;
|
||||
int image_start;
|
||||
int image_size;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if(unit_num < 0 || unit_num > MAX_C7_DISKS) {
|
||||
halt_printf("do_read_c7: unit_num: %d\n", unit_num);
|
||||
smartport_error();
|
||||
return 0x28;
|
||||
}
|
||||
|
||||
fd = iwm.smartport[unit_num].fd;
|
||||
image_start = iwm.smartport[unit_num].image_start;
|
||||
image_size = iwm.smartport[unit_num].image_size;
|
||||
if(fd < 0) {
|
||||
printf("c7_fd == %d!\n", fd);
|
||||
#if 0
|
||||
if(blk != 2 && blk != 0) {
|
||||
/* don't print error if only reading directory */
|
||||
smartport_error();
|
||||
halt_printf("Read unit:%02x blk:%04x\n", unit_num, blk);
|
||||
}
|
||||
#endif
|
||||
return 0x2f;
|
||||
}
|
||||
|
||||
ret = lseek(fd, image_start + blk*0x200, SEEK_SET);
|
||||
if(ret != image_start + blk*0x200) {
|
||||
halt_printf("lseek returned %08x, errno: %d\n", ret, errno);
|
||||
smartport_error();
|
||||
return 0x27;
|
||||
}
|
||||
|
||||
if(ret >= image_start + image_size) {
|
||||
halt_printf("Tried to read from pos %08x on disk, (blk:%04x)\n",
|
||||
ret, blk);
|
||||
smartport_error();
|
||||
return 0x27;
|
||||
}
|
||||
|
||||
len = read(fd, &local_buf[0], 0x200);
|
||||
if(len != 0x200) {
|
||||
printf("read returned %08x, errno:%d, blk:%04x, unit: %02x\n",
|
||||
len, errno, blk, unit_num);
|
||||
halt_printf("name: %s\n", iwm.smartport[unit_num].name_ptr);
|
||||
smartport_error();
|
||||
return 0x27;
|
||||
}
|
||||
|
||||
g_io_amt += 0x200;
|
||||
|
||||
if(buf >= 0xfc0000) {
|
||||
disk_printf("reading into ROM, just returning\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
GET_ITIMER(start_time);
|
||||
|
||||
for(i = 0; i < 0x200; i += 2) {
|
||||
val = (local_buf[i+1] << 8) + local_buf[i];
|
||||
set_memory16_c(buf + i, val, 0);
|
||||
}
|
||||
|
||||
GET_ITIMER(end_time);
|
||||
|
||||
g_cycs_in_io_read += (end_time - start_time);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
do_write_c7(int unit_num, word32 buf, int blk)
|
||||
{
|
||||
word32 local_buf[0x200/4];
|
||||
Disk *dsk;
|
||||
word32 *ptr;
|
||||
word32 val1, val2;
|
||||
word32 val;
|
||||
int len;
|
||||
int ret;
|
||||
int fd;
|
||||
int image_start;
|
||||
int image_size;
|
||||
int i;
|
||||
|
||||
if(unit_num < 0 || unit_num > MAX_C7_DISKS) {
|
||||
halt_printf("do_write_c7: unit_num: %d\n", unit_num);
|
||||
smartport_error();
|
||||
return 0x28;
|
||||
}
|
||||
|
||||
dsk = &(iwm.smartport[unit_num]);
|
||||
fd = dsk->fd;
|
||||
image_start = dsk->image_start;
|
||||
image_size = dsk->image_size;
|
||||
if(fd < 0) {
|
||||
halt_printf("c7_fd == %d!\n", fd);
|
||||
smartport_error();
|
||||
return 0x28;
|
||||
}
|
||||
|
||||
ptr = &(local_buf[0]);
|
||||
for(i = 0; i < 0x200; i += 4) {
|
||||
val1 = get_memory16_c(buf + i, 0);
|
||||
val2 = get_memory16_c(buf + i + 2, 0);
|
||||
/* reorder the little-endian bytes to be big-endian */
|
||||
#ifdef KEGS_LITTLE_ENDIAN
|
||||
val = (val2 << 16) + val1;
|
||||
#else
|
||||
val = (val1 << 24) + ((val1 << 8) & 0xff0000) +
|
||||
((val2 << 8) & 0xff00) + (val2 >> 8);
|
||||
#endif
|
||||
*ptr++ = val;
|
||||
}
|
||||
|
||||
ret = lseek(fd, image_start + blk*0x200, SEEK_SET);
|
||||
if(ret != image_start + blk*0x200) {
|
||||
halt_printf("lseek returned %08x, errno: %d\n", ret, errno);
|
||||
smartport_error();
|
||||
return 0x27;
|
||||
}
|
||||
|
||||
if(ret >= image_start + image_size) {
|
||||
halt_printf("Tried to write to %08x\n", ret);
|
||||
smartport_error();
|
||||
return 0x27;
|
||||
}
|
||||
|
||||
if(dsk->write_prot) {
|
||||
printf("Write, but %s is write protected!\n", dsk->name_ptr);
|
||||
return 0x2b;
|
||||
}
|
||||
|
||||
if(dsk->write_through_to_unix == 0) {
|
||||
halt_printf("Write to %s, but not wr_thru!\n", dsk->name_ptr);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
len = write(fd, (byte *)&local_buf[0], 0x200);
|
||||
if(len != 0x200) {
|
||||
halt_printf("write ret %08x bytes, errno: %d\n", len, errno);
|
||||
smartport_error();
|
||||
return 0x27;
|
||||
}
|
||||
|
||||
g_io_amt += 0x200;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
do_format_c7(int unit_num)
|
||||
{
|
||||
byte local_buf[0x1000];
|
||||
Disk *dsk;
|
||||
int len;
|
||||
int ret;
|
||||
int sum;
|
||||
int total;
|
||||
int max;
|
||||
int image_start;
|
||||
int image_size;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
if(unit_num < 0 || unit_num > MAX_C7_DISKS) {
|
||||
halt_printf("do_format_c7: unit_num: %d\n", unit_num);
|
||||
smartport_error();
|
||||
return 0x28;
|
||||
}
|
||||
|
||||
dsk = &(iwm.smartport[unit_num]);
|
||||
fd = dsk->fd;
|
||||
image_start = dsk->image_start;
|
||||
image_size = dsk->image_size;
|
||||
if(fd < 0) {
|
||||
halt_printf("c7_fd == %d!\n", fd);
|
||||
smartport_error();
|
||||
return 0x28;
|
||||
}
|
||||
|
||||
for(i = 0; i < 0x1000; i++) {
|
||||
local_buf[i] = 0;
|
||||
}
|
||||
|
||||
ret = lseek(fd, image_start, SEEK_SET);
|
||||
if(ret != image_start) {
|
||||
halt_printf("lseek returned %08x, errno: %d\n", ret, errno);
|
||||
smartport_error();
|
||||
return 0x27;
|
||||
}
|
||||
|
||||
if(dsk->write_prot) {
|
||||
printf("Format, but %s is write protected!\n", dsk->name_ptr);
|
||||
return 0x2b;
|
||||
}
|
||||
|
||||
if(dsk->write_through_to_unix == 0) {
|
||||
printf("Format of %s ignored\n", dsk->name_ptr);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
sum = 0;
|
||||
total = image_size;
|
||||
|
||||
while(sum < total) {
|
||||
max = MIN(0x1000, total-sum);
|
||||
len = write(fd, &local_buf[0], max);
|
||||
if(len != max) {
|
||||
halt_printf("write ret %08x, errno:%d\n", len, errno);
|
||||
smartport_error();
|
||||
return 0x27;
|
||||
}
|
||||
sum += len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
do_c700(word32 ret)
|
||||
{
|
||||
disk_printf("do_c700 called, ret: %08x\n", ret);
|
||||
|
||||
ret = do_read_c7(0, 0x800, 0);
|
||||
|
||||
set_memory_c(0x7f8, 7, 0);
|
||||
set_memory_c(0x42, 0x01, 0);
|
||||
set_memory_c(0x43, 0x70, 0);
|
||||
set_memory_c(0x44, 0x0, 0);
|
||||
set_memory_c(0x45, 0x8, 0);
|
||||
set_memory_c(0x46, 0x0, 0);
|
||||
set_memory_c(0x47, 0x0, 0);
|
||||
engine.xreg = 0x70;
|
||||
engine.kpc = 0x801;
|
||||
|
||||
if(ret != 0) {
|
||||
printf("Failure reading boot disk in s7d1!\n");
|
||||
engine.kpc = 0xe000;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,60 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef INCLUDE_RCSID_C
|
||||
const char rcsid_sound_h[] = "@(#)$KmKId: sound.h,v 1.17 2003-11-21 15:15:57-05 kentd Exp $";
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && !defined(__CYGWIN__)
|
||||
# include <sys/ipc.h>
|
||||
# include <sys/shm.h>
|
||||
#endif
|
||||
|
||||
#define SOUND_SHM_SAMP_SIZE (32*1024)
|
||||
|
||||
#define SAMPLE_SIZE 2
|
||||
#define NUM_CHANNELS 2
|
||||
#define SAMPLE_CHAN_SIZE (SAMPLE_SIZE * NUM_CHANNELS)
|
||||
|
||||
STRUCT(Doc_reg) {
|
||||
double dsamp_ev;
|
||||
double dsamp_ev2;
|
||||
double complete_dsamp;
|
||||
int samps_left;
|
||||
word32 cur_acc;
|
||||
word32 cur_inc;
|
||||
word32 cur_start;
|
||||
word32 cur_end;
|
||||
word32 cur_mask;
|
||||
int size_bytes;
|
||||
int event;
|
||||
int running;
|
||||
int has_irq_pending;
|
||||
word32 freq;
|
||||
word32 vol;
|
||||
word32 waveptr;
|
||||
word32 ctl;
|
||||
word32 wavesize;
|
||||
word32 last_samp_val;
|
||||
};
|
||||
|
||||
/* prototypes for win32snd_driver.c functions */
|
||||
void win32snd_init(word32 *);
|
||||
void win32snd_shutdown();
|
||||
void win32snd_shutdown();
|
||||
void child_sound_init_win32();
|
||||
int win32_send_audio(byte *ptr, int size);
|
||||
|
||||
|
||||
/* Prototypes for macsnd_driver.c functions */
|
||||
int mac_send_audio(byte *ptr, int in_size);
|
||||
void child_sound_init_mac();
|
||||
void macsnd_init(word32 *shmaddr);
|
||||
|
|
@ -0,0 +1,469 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_sound_driver_c[] = "@(#)$KmKId: sound_driver.c,v 1.16 2004-03-22 19:08:08-05 kentd Exp $";
|
||||
|
||||
#include "defc.h"
|
||||
#include "sound.h"
|
||||
|
||||
#ifdef HPUX
|
||||
# include <sys/audio.h>
|
||||
#endif
|
||||
|
||||
#ifdef SOLARIS
|
||||
# include <sys/audioio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(OSS)
|
||||
# include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
extern int Verbose;
|
||||
extern int g_use_alib;
|
||||
|
||||
extern int g_audio_rate;
|
||||
|
||||
int g_preferred_rate = 48000;
|
||||
int g_audio_socket = -1;
|
||||
int g_bytes_written = 0;
|
||||
|
||||
#define ZERO_BUF_SIZE 2048
|
||||
|
||||
word32 g_snd_zero_buf[ZERO_BUF_SIZE];
|
||||
|
||||
#define ZERO_PAUSE_SAFETY_SAMPS (g_audio_rate >> 5)
|
||||
#define ZERO_PAUSE_NUM_SAMPS (4*g_audio_rate)
|
||||
|
||||
int g_zeroes_buffered = 0;
|
||||
int g_zeroes_seen = 0;
|
||||
int g_sound_paused = 0;
|
||||
int g_childsnd_vbl = 0;
|
||||
int g_childsnd_pos = 0;
|
||||
word32 *g_childsnd_shm_addr = 0;
|
||||
|
||||
void child_sound_init_linux();
|
||||
void child_sound_init_hpdev();
|
||||
void child_sound_init_solaris();
|
||||
void child_sound_init_win32();
|
||||
void child_sound_init_mac();
|
||||
|
||||
void
|
||||
reliable_buf_write(word32 *shm_addr, int pos, int size)
|
||||
{
|
||||
byte *ptr;
|
||||
int ret;
|
||||
|
||||
if(size < 1 || pos < 0 || pos > SOUND_SHM_SAMP_SIZE ||
|
||||
size > SOUND_SHM_SAMP_SIZE ||
|
||||
(pos + size) > SOUND_SHM_SAMP_SIZE) {
|
||||
printf("reliable_buf_write: pos: %04x, size: %04x\n",
|
||||
pos, size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ptr = (byte *)&(shm_addr[pos]);
|
||||
size = size * 4;
|
||||
|
||||
while(size > 0) {
|
||||
#ifdef _WIN32
|
||||
ret = win32_send_audio(ptr, size);
|
||||
#else
|
||||
# ifdef MAC
|
||||
ret = mac_send_audio(ptr, size);
|
||||
# else
|
||||
ret = write(g_audio_socket, ptr, size);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if(ret < 0) {
|
||||
printf("audio write, errno: %d\n", errno);
|
||||
exit(1);
|
||||
}
|
||||
size = size - ret;
|
||||
ptr += ret;
|
||||
g_bytes_written += ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
reliable_zero_write(int amt)
|
||||
{
|
||||
int len;
|
||||
|
||||
while(amt > 0) {
|
||||
len = MIN(amt, ZERO_BUF_SIZE);
|
||||
reliable_buf_write(g_snd_zero_buf, 0, len);
|
||||
amt -= len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
child_sound_loop(int read_fd, int write_fd, word32 *shm_addr)
|
||||
{
|
||||
#ifdef HPUX
|
||||
long status_return;
|
||||
#endif
|
||||
word32 tmp;
|
||||
int ret;
|
||||
|
||||
doc_printf("Child pipe fd: %d\n", read_fd);
|
||||
|
||||
g_audio_rate = g_preferred_rate;
|
||||
|
||||
g_zeroes_buffered = 0;
|
||||
g_zeroes_seen = 0;
|
||||
g_sound_paused = 0;
|
||||
|
||||
g_childsnd_pos = 0;
|
||||
g_childsnd_vbl = 0;
|
||||
g_childsnd_shm_addr = shm_addr;
|
||||
|
||||
#ifdef HPUX
|
||||
child_sound_init_hpdev();
|
||||
#endif
|
||||
#ifdef SOLARIS
|
||||
child_sound_init_solaris();
|
||||
#endif
|
||||
#if defined(__linux__) || defined(OSS)
|
||||
child_sound_init_linux();
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
child_sound_init_win32();
|
||||
return;
|
||||
#endif
|
||||
#ifdef MAC
|
||||
child_sound_init_mac();
|
||||
return;
|
||||
#endif
|
||||
|
||||
tmp = g_audio_rate;
|
||||
ret = write(write_fd, &tmp, 4);
|
||||
if(ret != 4) {
|
||||
printf("Unable to send back audio rate to parent\n");
|
||||
printf("ret: %d fd: %d, errno: %d\n", ret, write_fd, errno);
|
||||
exit(1);
|
||||
}
|
||||
printf("Wrote to fd %d the audio rate\n", write_fd);
|
||||
|
||||
close(write_fd);
|
||||
|
||||
while(1) {
|
||||
errno = 0;
|
||||
ret = read(read_fd, &tmp, 4);
|
||||
if(ret <= 0) {
|
||||
printf("child dying from ret: %d, errno: %d\n",
|
||||
ret, errno);
|
||||
break;
|
||||
}
|
||||
|
||||
child_sound_playit(tmp);
|
||||
}
|
||||
|
||||
#ifdef HPUX
|
||||
ioctl(g_audio_socket, AUDIO_DRAIN, 0);
|
||||
#endif
|
||||
close(g_audio_socket);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
child_sound_playit(word32 tmp)
|
||||
{
|
||||
int size;
|
||||
|
||||
size = tmp & 0xffffff;
|
||||
|
||||
//printf("child_sound_playit: %08x\n", tmp);
|
||||
|
||||
if((tmp >> 24) == 0xa2) {
|
||||
/* play sound here */
|
||||
|
||||
|
||||
#if 0
|
||||
g_childsnd_pos += g_zeroes_buffered;
|
||||
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
|
||||
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(g_zeroes_buffered) {
|
||||
reliable_zero_write(g_zeroes_buffered);
|
||||
}
|
||||
|
||||
g_zeroes_buffered = 0;
|
||||
g_zeroes_seen = 0;
|
||||
|
||||
if((size + g_childsnd_pos) > SOUND_SHM_SAMP_SIZE) {
|
||||
reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos,
|
||||
SOUND_SHM_SAMP_SIZE - g_childsnd_pos);
|
||||
size = (g_childsnd_pos + size) - SOUND_SHM_SAMP_SIZE;
|
||||
g_childsnd_pos = 0;
|
||||
}
|
||||
|
||||
reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos, size);
|
||||
|
||||
if(g_sound_paused) {
|
||||
printf("Unpausing sound, zb: %d\n", g_zeroes_buffered);
|
||||
g_sound_paused = 0;
|
||||
}
|
||||
|
||||
} else if((tmp >> 24) == 0xa1) {
|
||||
if(g_sound_paused) {
|
||||
if(g_zeroes_buffered < ZERO_PAUSE_SAFETY_SAMPS) {
|
||||
g_zeroes_buffered += size;
|
||||
}
|
||||
} else {
|
||||
/* not paused, send it through */
|
||||
g_zeroes_seen += size;
|
||||
|
||||
reliable_zero_write(size);
|
||||
|
||||
if(g_zeroes_seen >= ZERO_PAUSE_NUM_SAMPS) {
|
||||
printf("Pausing sound\n");
|
||||
g_sound_paused = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("tmp received bad: %08x\n", tmp);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
g_childsnd_pos += size;
|
||||
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
|
||||
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
|
||||
}
|
||||
|
||||
g_childsnd_vbl++;
|
||||
if(g_childsnd_vbl >= 60) {
|
||||
g_childsnd_vbl = 0;
|
||||
#if 0
|
||||
printf("sound bytes written: %06x\n", g_bytes_written);
|
||||
printf("Sample samples[0]: %08x %08x %08x %08x\n",
|
||||
g_childsnd_shm_addr[0], g_childsnd_shm_addr[1],
|
||||
g_childsnd_shm_addr[2], g_childsnd_shm_addr[3]);
|
||||
printf("Sample samples[100]: %08x %08x %08x %08x\n",
|
||||
g_childsnd_shm_addr[100], g_childsnd_shm_addr[101],
|
||||
g_childsnd_shm_addr[102], g_childsnd_shm_addr[103]);
|
||||
#endif
|
||||
g_bytes_written = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HPUX
|
||||
void
|
||||
child_sound_init_hpdev()
|
||||
{
|
||||
struct audio_describe audio_descr;
|
||||
int output_channel;
|
||||
char *str;
|
||||
int speaker;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
g_audio_socket = open("/dev/audio", O_WRONLY, 0);
|
||||
if(g_audio_socket < 0) {
|
||||
printf("open /dev/audio failed, ret: %d, errno:%d\n",
|
||||
g_audio_socket, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_DESCRIBE, &audio_descr);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_DESCRIBE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i = 0; i < audio_descr.nrates; i++) {
|
||||
printf("Audio rate[%d] = %d\n", i,
|
||||
audio_descr.sample_rate[i]);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_DATA_FORMAT,
|
||||
AUDIO_FORMAT_LINEAR16BIT);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_DATA_FORMAT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_CHANNELS, NUM_CHANNELS);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_CHANNELS failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_TXBUFSIZE, 16*1024);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_TXBUFSIZE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_SAMPLE_RATE, g_audio_rate);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_SAMPLE_RATE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_GET_OUTPUT, &output_channel);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_GET_OUTPUT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
speaker = 1;
|
||||
str = getenv("SPEAKER");
|
||||
if(str) {
|
||||
if(str[0] != 'i' && str[0] != 'I') {
|
||||
speaker = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(speaker) {
|
||||
printf("Sending sound to internal speaker\n");
|
||||
output_channel |= AUDIO_OUT_SPEAKER;
|
||||
} else {
|
||||
printf("Sending sound to external jack\n");
|
||||
output_channel &= (~AUDIO_OUT_SPEAKER);
|
||||
output_channel |= AUDIO_OUT_HEADPHONE;
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_SET_OUTPUT, output_channel);
|
||||
if(ret < 0) {
|
||||
printf("ioctl AUDIO_SET_OUTPUT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif /* HPUX */
|
||||
|
||||
#ifdef SOLARIS
|
||||
void
|
||||
child_sound_init_solaris()
|
||||
{
|
||||
struct audio_info audioi;
|
||||
int ret;
|
||||
|
||||
g_audio_socket = open("/dev/audio", O_WRONLY, 0);
|
||||
if(g_audio_socket < 0) {
|
||||
printf("open /dev/audio failed, ret: %d, errno:%d\n",
|
||||
g_audio_socket, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ioctl(g_audio_socket, AUDIO_GETINFO, &audioi);
|
||||
if(ret < 0) {
|
||||
printf("ioctl audio getinfo ret: %d, errno:%d\n", ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
audioi.play.sample_rate = g_preferred_rate;
|
||||
audioi.play.encoding = AUDIO_ENCODING_LINEAR;
|
||||
audioi.play.precision = 16;
|
||||
audioi.play.channels = 2;
|
||||
ret = ioctl(g_audio_socket, AUDIO_SETINFO, &audioi);
|
||||
if(ret < 0) {
|
||||
printf("ioctl audio setinfo ret: %d, errno:%d\n", ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif /* SOLARIS */
|
||||
|
||||
#if defined(__linux__) || defined(OSS)
|
||||
void
|
||||
child_sound_init_linux()
|
||||
{
|
||||
int stereo;
|
||||
int sample_size;
|
||||
int rate;
|
||||
int fragment;
|
||||
int fmt;
|
||||
int ret;
|
||||
|
||||
g_audio_socket = open("/dev/dsp", O_WRONLY, 0);
|
||||
if(g_audio_socket < 0) {
|
||||
printf("open /dev/dsp failed, ret: %d, errno:%d\n",
|
||||
g_audio_socket, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fragment = 0x00200009;
|
||||
#if 0
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFRAGMENT, &fragment);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SETFRAGEMNT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
sample_size = 16;
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SAMPLESIZE, &sample_size);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_SAMPLESIZE failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef KEGS_LITTLE_ENDIAN
|
||||
fmt = AFMT_S16_LE;
|
||||
#else
|
||||
fmt = AFMT_S16_BE;
|
||||
#endif
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFMT, &fmt);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_SETFMT failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
stereo = 1;
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_STEREO, &stereo);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_STEREO failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rate = g_audio_rate;
|
||||
ret = ioctl(g_audio_socket, SNDCTL_DSP_SPEED, &rate);
|
||||
if(ret < 0) {
|
||||
printf("ioctl SNDCTL_DSP_SPEED failed, ret:%d, errno:%d\n",
|
||||
ret, errno);
|
||||
exit(1);
|
||||
}
|
||||
if(ret > 0) {
|
||||
rate = ret; /* rate is returned value */
|
||||
}
|
||||
if(rate < 8000) {
|
||||
printf("Audio rate of %d which is < 8000!\n", rate);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_audio_rate = rate;
|
||||
|
||||
printf("Sound initialized\n");
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,204 @@
|
|||
|
||||
/* This file is included by video.c */
|
||||
|
||||
#ifndef SUPERHIRES_INCLUDED
|
||||
const char rcsid_superhires_h[] = "@(#)$KmKId: superhires.h,v 1.9 2003-10-29 02:02:59-05 kentd Exp $";
|
||||
# define SUPERHIRES_INCLUDED
|
||||
#endif
|
||||
|
||||
void
|
||||
SUPER_TYPE(byte *screen_data, int pixels_per_line, int y, int scan,
|
||||
word32 ch_mask, int use_a2vid_palette, int mode_640)
|
||||
{
|
||||
word32 *palptr;
|
||||
word32 mem_ptr;
|
||||
byte val0;
|
||||
int x1, x2;
|
||||
byte *b_ptr;
|
||||
word32 *img_ptr, *img_ptr2;
|
||||
word32 tmp, tmp2;
|
||||
word32 ch_tmp;
|
||||
byte *slow_mem_ptr;
|
||||
int shift_per;
|
||||
word32 pal;
|
||||
word32 pal_word;
|
||||
word32 pix0, pix1, pix2, pix3;
|
||||
word32 save_pix;
|
||||
int offset, next_line_offset;
|
||||
int dopr;
|
||||
|
||||
mem_ptr = 0xa0 * y + 0x12000;
|
||||
tmp2 = 0;
|
||||
tmp = 0;
|
||||
|
||||
shift_per = (1 << SHIFT_PER_CHANGE);
|
||||
if(use_a2vid_palette) {
|
||||
pal = (g_a2vid_palette & 0xf);
|
||||
} else {
|
||||
pal = (scan & 0xf);
|
||||
}
|
||||
|
||||
if(SUPER_FILL) {
|
||||
ch_mask = -1;
|
||||
save_pix = 0;
|
||||
}
|
||||
|
||||
if(use_a2vid_palette) {
|
||||
palptr = &(g_a2vid_palette_remap[0]);
|
||||
} else {
|
||||
palptr = &(g_palette_8to1624[pal * 16]);
|
||||
}
|
||||
|
||||
dopr = 0;
|
||||
#if 0
|
||||
if(y == 1) {
|
||||
dopr = 1;
|
||||
printf("superhires line %d has ch_mask: %08x\n", y, ch_mask);
|
||||
}
|
||||
#endif
|
||||
for(x1 = 0; x1 < 0xa0; x1 += shift_per) {
|
||||
|
||||
CH_LOOP_A2_VID(ch_mask, ch_tmp);
|
||||
|
||||
pal_word = (pal << 28) + (pal << 20) + (pal << 12) +
|
||||
(pal << 4);
|
||||
|
||||
if(mode_640 && !use_a2vid_palette) {
|
||||
#ifdef KEGS_LITTLE_ENDIAN
|
||||
pal_word += 0x04000c08;
|
||||
#else
|
||||
pal_word += 0x080c0004;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
|
||||
offset = y*2*pixels_per_line + x1*4;
|
||||
next_line_offset = pixels_per_line;
|
||||
#if SUPER_PIXEL_SIZE == 16
|
||||
offset *= 2;
|
||||
next_line_offset *= 2;
|
||||
#elif SUPER_PIXEL_SIZE == 32
|
||||
offset *= 4;
|
||||
next_line_offset *= 4;
|
||||
#endif
|
||||
b_ptr = &screen_data[offset];
|
||||
img_ptr = (word32 *)b_ptr;
|
||||
img_ptr2 = (word32 *)(b_ptr + next_line_offset);
|
||||
|
||||
if(mode_640) {
|
||||
for(x2 = 0; x2 < shift_per; x2++) {
|
||||
val0 = *slow_mem_ptr++;
|
||||
|
||||
pix0 = (val0 >> 6) & 0x3;
|
||||
pix1 = (val0 >> 4) & 0x3;
|
||||
pix2 = (val0 >> 2) & 0x3;
|
||||
pix3 = val0 & 0x3;
|
||||
if(use_a2vid_palette || (SUPER_PIXEL_SIZE > 8)){
|
||||
pix0 = palptr[pix0+8];
|
||||
pix1 = palptr[pix1+12];
|
||||
pix2 = palptr[pix2+0];
|
||||
pix3 = palptr[pix3+4];
|
||||
}
|
||||
#if SUPER_PIXEL_SIZE == 8
|
||||
# ifdef KEGS_LITTLE_ENDIAN
|
||||
tmp = (pix3 << 24) + (pix2 << 16) +
|
||||
(pix1 << 8) + pix0 + pal_word;
|
||||
# else
|
||||
tmp = (pix0 << 24) + (pix1 << 16) +
|
||||
(pix2 << 8) + pix3 + pal_word;
|
||||
# endif
|
||||
*img_ptr++ = tmp; *img_ptr2++ = tmp;
|
||||
#elif SUPER_PIXEL_SIZE == 16
|
||||
# ifdef KEGS_LITTLE_ENDIAN
|
||||
tmp = (pix1 << 16) + pix0;
|
||||
tmp2 = (pix3 << 16) + pix2;
|
||||
# else
|
||||
tmp = (pix0 << 16) + pix1;
|
||||
tmp2 = (pix2 << 16) + pix3;
|
||||
# endif
|
||||
*img_ptr++ = tmp;
|
||||
*img_ptr++ = tmp2;
|
||||
*img_ptr2++ = tmp;
|
||||
*img_ptr2++ = tmp2;
|
||||
#else /* SUPER_PIXEL_SIZE == 32 */
|
||||
*img_ptr++ = pix0;
|
||||
*img_ptr++ = pix1;
|
||||
*img_ptr++ = pix2;
|
||||
*img_ptr++ = pix3;
|
||||
*img_ptr2++ = pix0;
|
||||
*img_ptr2++ = pix1;
|
||||
*img_ptr2++ = pix2;
|
||||
*img_ptr2++ = pix3;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if(y == 1 && x1 == 0 && x2 == 0) {
|
||||
printf("y==1,x1,x2=0, %02x = %08x %08x "
|
||||
"%08x %08x, pal: %04x\n", val0,
|
||||
pix0, pix1, pix2, pix3, pal);
|
||||
printf("offset: %04x, nlo:%04x, ppl:"
|
||||
"%04x, %d\n", offset,
|
||||
next_line_offset,
|
||||
pixels_per_line, SUPER_PIXEL_SIZE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} else { /* 320 mode */
|
||||
for(x2 = 0; x2 < shift_per; x2++) {
|
||||
val0 = *slow_mem_ptr++;
|
||||
pix0 = (val0 >> 4);
|
||||
if(SUPER_FILL) {
|
||||
if(pix0) {
|
||||
save_pix = pix0;
|
||||
} else {
|
||||
pix0 = save_pix;
|
||||
}
|
||||
}
|
||||
pix1 = (val0 & 0xf);
|
||||
if(SUPER_FILL) {
|
||||
if(pix1) {
|
||||
save_pix = pix1;
|
||||
} else {
|
||||
pix1 = save_pix;
|
||||
}
|
||||
}
|
||||
if(use_a2vid_palette || (SUPER_PIXEL_SIZE > 8)){
|
||||
pix0 = palptr[pix0];
|
||||
pix1 = palptr[pix1];
|
||||
}
|
||||
if(dopr && x1 == 0) {
|
||||
printf("y:%d, x2:%d, val:%02x = %08x %08x\n", y, x2, val0, pix0, pix1);
|
||||
}
|
||||
#if SUPER_PIXEL_SIZE == 8
|
||||
# ifdef KEGS_LITTLE_ENDIAN
|
||||
tmp = (pix1 << 24) + (pix1 << 16) +
|
||||
(pix0 << 8) + pix0 + pal_word;
|
||||
# else
|
||||
tmp = (pix0 << 24) + (pix0 << 16) +
|
||||
(pix1 << 8) + pix1 + pal_word;
|
||||
# endif
|
||||
*img_ptr++ = tmp; *img_ptr2++ = tmp;
|
||||
#elif SUPER_PIXEL_SIZE == 16
|
||||
tmp = (pix0 << 16) + pix0;
|
||||
tmp2 = (pix1 << 16) + pix1;
|
||||
*img_ptr++ = tmp;
|
||||
*img_ptr++ = tmp2;
|
||||
*img_ptr2++ = tmp;
|
||||
*img_ptr2++ = tmp2;
|
||||
#else /* SUPER_PIXEL_SIZE == 32 */
|
||||
*img_ptr++ = pix0;
|
||||
*img_ptr++ = pix0;
|
||||
*img_ptr++ = pix1;
|
||||
*img_ptr++ = pix1;
|
||||
*img_ptr2++ = pix0;
|
||||
*img_ptr2++ = pix0;
|
||||
*img_ptr2++ = pix1;
|
||||
*img_ptr2++ = pix1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,897 @@
|
|||
/****************************************************************/
|
||||
/* Apple //gs emulator */
|
||||
/* Copyright 1996 Kent Dickey */
|
||||
/* */
|
||||
/* This code may not be used in a commercial product */
|
||||
/* without prior written permission of the author. */
|
||||
/* */
|
||||
/* You may freely distribute this code. */
|
||||
/* */
|
||||
/* You can contact the author at kentd@cup.hp.com. */
|
||||
/* HP has nothing to do with this software. */
|
||||
/****************************************************************/
|
||||
|
||||
#include "defc.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#include "prodos.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#define DEF_DISK_SIZE (800*1024)
|
||||
#define MAX_FILE_NAMES 51
|
||||
|
||||
char out_name[] = "POOF1";
|
||||
|
||||
int g_def_file_type = -1;
|
||||
int g_def_aux_type = -1;
|
||||
|
||||
void make_legal_prodos_name(char *new_name, char *old_name);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *files[MAX_FILE_NAMES];
|
||||
char *name;
|
||||
char *new_name_end;
|
||||
int new_name_len;
|
||||
struct stat stat_buf;
|
||||
int in;
|
||||
int in_size;
|
||||
int ret;
|
||||
ProDisk *disk;
|
||||
char new_name[128];
|
||||
byte in_buf[1024];
|
||||
int disk_size;
|
||||
int i;
|
||||
int done;
|
||||
int pos;
|
||||
int size;
|
||||
int num_files;
|
||||
int file_type;
|
||||
int aux_type;
|
||||
|
||||
disk_size = DEF_DISK_SIZE;
|
||||
if(argc < 2) {
|
||||
fprintf(stderr, "%s: {-[size in K]} {unix_files}\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
num_files = 0;
|
||||
for(i = 1; i < argc; i++) {
|
||||
if(argv[i][0] == '-') {
|
||||
/* I smell a -size_in_K */
|
||||
disk_size = strtoul(&(argv[i][1]), 0, 10) * 1024;
|
||||
printf("disk_size: %d, 0x%x\n", disk_size, disk_size);
|
||||
if(disk_size < 40*1024) {
|
||||
printf("Too small!\n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
files[num_files] = argv[i];
|
||||
num_files++;
|
||||
if(num_files >= MAX_FILE_NAMES) {
|
||||
printf("Too many filenames: %d\n", num_files);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disk = allocate_memdisk(out_name, disk_size);
|
||||
format_memdisk(disk, out_name);
|
||||
|
||||
for(i = 0; i < num_files; i++) {
|
||||
name = files[i];
|
||||
in = open(name, O_RDONLY | O_BINARY);
|
||||
if(in < 0) {
|
||||
fprintf(stderr, "opening %s returned %d, errno: %d\n",
|
||||
name, in, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = fstat(in, &stat_buf);
|
||||
if(ret != 0) {
|
||||
fprintf(stderr, "fstat returned %d, errno: %d\n",
|
||||
ret, errno);
|
||||
}
|
||||
|
||||
in_size = stat_buf.st_size;
|
||||
printf("in size: %d\n", in_size);
|
||||
|
||||
if(in_size > disk->disk_bytes_left) {
|
||||
printf("File bigger than %d, too big!\n", disk_size);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
make_legal_prodos_name(new_name, name);
|
||||
|
||||
new_name_len = strlen(new_name);
|
||||
new_name_end = new_name + new_name_len;
|
||||
|
||||
file_type = g_def_file_type;
|
||||
aux_type = g_def_aux_type;
|
||||
while(g_def_file_type < 0) {
|
||||
/* choose file type */
|
||||
if(new_name_len >= 5) {
|
||||
if(strcmp(new_name_end - 4, ".SHK") == 0) {
|
||||
file_type = 0xe0;
|
||||
aux_type = 0x8002;
|
||||
break;
|
||||
}
|
||||
if(strcmp(new_name_end - 4, ".SDK") == 0) {
|
||||
file_type = 0xe0;
|
||||
aux_type = 0x8002;
|
||||
break;
|
||||
}
|
||||
}
|
||||
file_type = 0x04; /* TXT */
|
||||
aux_type = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
create_new_file(disk, 2, 1, new_name, file_type,
|
||||
0, 0, 0, 0xc3, aux_type, 0, in_size);
|
||||
|
||||
|
||||
done = 0;
|
||||
pos = 0;
|
||||
while(pos < in_size) {
|
||||
size = 512;
|
||||
if(pos + size > in_size) {
|
||||
size = in_size - pos;
|
||||
}
|
||||
ret = read(in, in_buf, size);
|
||||
if(ret != size || ret <= 0) {
|
||||
fprintf(stderr, "read returned %d, errno: %d\n",
|
||||
ret, errno);
|
||||
exit(2);
|
||||
}
|
||||
ret = pro_write_file(disk, in_buf, pos, size);
|
||||
if(ret != 0) {
|
||||
printf("pro_write returned %d!\n", ret);
|
||||
exit(3);
|
||||
}
|
||||
pos += size;
|
||||
}
|
||||
|
||||
close_file(disk);
|
||||
|
||||
close(in);
|
||||
}
|
||||
|
||||
flush_disk(disk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
make_legal_prodos_name(char *new_name, char *old_name)
|
||||
{
|
||||
char *ptr;
|
||||
int start_len, start_char;
|
||||
int len;
|
||||
int pos;
|
||||
int c;
|
||||
int j;
|
||||
|
||||
for(j = 0; j < 16; j++) {
|
||||
/* make sure it ends with null == 15 + 1 */
|
||||
new_name[j] = 0;
|
||||
}
|
||||
|
||||
start_char = 0;
|
||||
start_len = strlen(old_name);
|
||||
len = 0;
|
||||
ptr = &old_name[start_len - 1];
|
||||
for(j = start_len - 1; j >= 0; j--) {
|
||||
if(*ptr == '/' || *ptr == ':') {
|
||||
break;
|
||||
}
|
||||
ptr--;
|
||||
len++;
|
||||
}
|
||||
ptr++;
|
||||
|
||||
if(len <= 0) {
|
||||
printf("Filename: %s has len: %d!\n", old_name, len);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("mid_name: %s, len:%d\n", ptr, len);
|
||||
|
||||
pos = 0;
|
||||
for(j = 0; j < 15; j++) {
|
||||
c = ptr[pos];
|
||||
if(isalnum(c)) {
|
||||
c = toupper(c);
|
||||
} else if(c != 0) {
|
||||
c = '.';
|
||||
}
|
||||
|
||||
if(j == 0 && !isalpha(c)) {
|
||||
c = 'A';
|
||||
}
|
||||
|
||||
new_name[j] = c;
|
||||
|
||||
pos++;
|
||||
if(pos == 7 && len > 15) {
|
||||
pos = len - 8;
|
||||
}
|
||||
}
|
||||
|
||||
printf("new_name: %s\n", new_name);
|
||||
}
|
||||
|
||||
void
|
||||
flush_disk(ProDisk *disk)
|
||||
{
|
||||
disk_write_data(disk, 6, disk->bitmap_ptr,
|
||||
disk->size_bitmap_blocks * 512);
|
||||
close(disk->fd);
|
||||
disk->fd = -1;
|
||||
}
|
||||
|
||||
void
|
||||
close_file(ProDisk *disk)
|
||||
{
|
||||
write_ind_block(disk);
|
||||
write_master_ind_block(disk);
|
||||
disk_write_data(disk, disk->dir_blk_num, &(disk->dir_blk_data[0]), 512);
|
||||
disk->file_ptr = 0;
|
||||
}
|
||||
|
||||
ProDisk *
|
||||
allocate_memdisk(char *out_name, int size)
|
||||
{
|
||||
ProDisk *disk;
|
||||
int out;
|
||||
|
||||
out = open(out_name, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0x1b6);
|
||||
if(out < 0) {
|
||||
fprintf(stderr, "opening %s returned %d, errno: %d\n",
|
||||
out_name, out, errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
disk = (ProDisk *)malloc(sizeof(ProDisk));
|
||||
if(disk == 0) {
|
||||
printf("allocate_memdisk failed, errno: %d\n", errno);
|
||||
}
|
||||
|
||||
disk->fd = out;
|
||||
disk->total_blocks = (size + 511) / 512;
|
||||
disk->bitmap_ptr = 0;
|
||||
disk->disk_bytes_left = 0;
|
||||
disk->size_bitmap_blocks = 0;
|
||||
disk->dir_blk_num = -1;
|
||||
disk->ind_blk_num = -1;
|
||||
disk->master_ind_blk_num = -1;
|
||||
|
||||
return disk;
|
||||
}
|
||||
|
||||
void
|
||||
format_memdisk(ProDisk *disk, char *name)
|
||||
{
|
||||
byte zero_buf[1024];
|
||||
int total_blocks;
|
||||
byte *bitmap_ptr;
|
||||
Vol_hdr *vol_hdr;
|
||||
Directory *dir;
|
||||
int size_bitmap_bytes;
|
||||
int size_bitmap_blocks;
|
||||
int disk_blocks_left;
|
||||
int i, j;
|
||||
|
||||
total_blocks = disk->total_blocks;
|
||||
|
||||
/* Zero out blocks 0 and 1 */
|
||||
for(i = 0; i < 2*512; i++) {
|
||||
zero_buf[i] = 0;
|
||||
}
|
||||
disk_write_data(disk, 0x00000, zero_buf, 2*512);
|
||||
|
||||
/* and make the image the right size */
|
||||
disk_write_data(disk, total_blocks - 1, zero_buf, 512);
|
||||
|
||||
dir = disk_read_dir(disk, 2);
|
||||
set_l2byte(&(dir->prev_blk), 0);
|
||||
set_l2byte(&(dir->next_blk), 3);
|
||||
vol_hdr = (Vol_hdr *)&(dir->file_entries[0]);
|
||||
vol_hdr->storage_type_name_len = 0xf0 + strlen(name);
|
||||
strncpy((char *)vol_hdr->vol_name, name, strlen(name));
|
||||
vol_hdr->version = 0;
|
||||
vol_hdr->min_version = 0;
|
||||
vol_hdr->access = 0xc3;
|
||||
vol_hdr->entry_length = 0x27;
|
||||
vol_hdr->entries_per_block = 0x0d;
|
||||
set_l2byte(&(vol_hdr->file_count), 0);
|
||||
vol_hdr->entries_per_block = 0x0d;
|
||||
set_l2byte(&(vol_hdr->bit_map), 6);
|
||||
set_l2byte(&(vol_hdr->total_blocks), total_blocks);
|
||||
for(i = 1; i < 13; i++) {
|
||||
set_file_entry(&(dir->file_entries[i]), 0, "", 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
disk_write_dir(disk, 2);
|
||||
|
||||
|
||||
for(i = 3; i < 6; i++) {
|
||||
dir = disk_read_dir(disk, i);
|
||||
set_l2byte(&(dir->prev_blk), i - 1);
|
||||
set_l2byte(&(dir->next_blk), i + 1);
|
||||
if(i == 5) {
|
||||
set_l2byte(&(dir->next_blk), 0);
|
||||
}
|
||||
for(j = 0; j < 13; j++) {
|
||||
set_file_entry(&(dir->file_entries[j]), 0, "", 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
disk_write_dir(disk, i);
|
||||
}
|
||||
|
||||
size_bitmap_bytes = (total_blocks + 7)/ 8;
|
||||
size_bitmap_blocks = (size_bitmap_bytes + 511)/ 512;
|
||||
bitmap_ptr = (byte *)malloc(size_bitmap_blocks * 512);
|
||||
for(i = 0; i < 6+size_bitmap_blocks; i++) {
|
||||
set_bitmap_used(bitmap_ptr, i);
|
||||
}
|
||||
for(i = 6+size_bitmap_blocks; i < total_blocks; i++) {
|
||||
set_bitmap_free(bitmap_ptr, i);
|
||||
}
|
||||
for(i = total_blocks; i < size_bitmap_blocks*512*8; i++) {
|
||||
set_bitmap_used(bitmap_ptr, i);
|
||||
}
|
||||
|
||||
disk_write_data(disk, 6, bitmap_ptr, size_bitmap_blocks * 512);
|
||||
disk->bitmap_ptr = bitmap_ptr;
|
||||
disk->size_bitmap_blocks = size_bitmap_blocks;
|
||||
disk->bitmap_bytes = size_bitmap_blocks * 512;
|
||||
disk->bitmap_cur_pos = 0;
|
||||
|
||||
disk_blocks_left = total_blocks - 6 - size_bitmap_blocks;
|
||||
disk->disk_bytes_left = disk_blocks_left * 512;
|
||||
}
|
||||
|
||||
void
|
||||
disk_write_data(ProDisk *disk, int blk_num, byte *buf, int size)
|
||||
{
|
||||
int size_in_blocks;
|
||||
int ret;
|
||||
|
||||
#if 0
|
||||
printf("Writing blk %04x from buf: %08x, %03x\n", blk_num, buf, size);
|
||||
#endif
|
||||
|
||||
size_in_blocks = size >> 9;
|
||||
if(size_in_blocks * 512 != size) {
|
||||
printf("disk_write: blk: %04x, buf: %08x, size: %08x\n",
|
||||
blk_num, (word32)buf, size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = lseek(disk->fd, 512*blk_num, SEEK_SET);
|
||||
if(ret != 512*blk_num) {
|
||||
printf("disk_write: seek: %d, errno: %d, blk: %04x, buf: "
|
||||
"%08x, sz: %08x\n", ret, errno, blk_num,
|
||||
(word32)buf, size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = write(disk->fd, buf, size);
|
||||
if(ret != size) {
|
||||
printf("disk_write: write: %d, errno: %d, blk: %04x, buf: "
|
||||
"%08x, sz: %08x\n", ret, errno, blk_num,
|
||||
(word32)buf, size);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
disk_read_data(ProDisk *disk, int blk_num, byte *buf, int size)
|
||||
{
|
||||
int size_in_blocks;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
size_in_blocks = size >> 9;
|
||||
if(size_in_blocks * 512 != size) {
|
||||
printf("disk_read: blk: %04x, buf: %08x, size: %08x\n",
|
||||
blk_num, (word32)buf, size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = lseek(disk->fd, 512*blk_num, SEEK_SET);
|
||||
if(ret != 512*blk_num) {
|
||||
printf("disk_read: seek: %d, errno: %d, blk: %04x, buf: "
|
||||
"%08x, sz: %08x\n", ret, errno, blk_num,
|
||||
(word32)buf, size);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = read(disk->fd, buf, size);
|
||||
if(ret != size) {
|
||||
printf("disk_read: read: %d, errno: %d, blk: %04x, buf: "
|
||||
"%08x, sz: %08x\n", ret, errno, blk_num,
|
||||
(word32)buf, size);
|
||||
for(i = 0; i < size; i++) {
|
||||
buf[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Directory *
|
||||
disk_read_dir(ProDisk *disk, int blk_num)
|
||||
{
|
||||
disk_write_dir(disk, blk_num);
|
||||
|
||||
disk->dir_blk_num = blk_num;
|
||||
disk_read_data(disk, blk_num, &(disk->dir_blk_data[0]), 512);
|
||||
|
||||
return (Directory *)&(disk->dir_blk_data[0]);
|
||||
}
|
||||
|
||||
void
|
||||
disk_write_dir(ProDisk *disk, int blk_num)
|
||||
{
|
||||
if(disk->dir_blk_num >= 0) {
|
||||
if(disk->dir_blk_num != blk_num) {
|
||||
printf("disk_write_dir: %04x != %04x\n",
|
||||
disk->dir_blk_num, blk_num);
|
||||
}
|
||||
disk_write_data(disk, disk->dir_blk_num,
|
||||
&(disk->dir_blk_data[0]), 512);
|
||||
disk->dir_blk_num = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
create_new_file(ProDisk *disk, int dir_block, int storage_type, char *name,
|
||||
int file_type, word32 creation_time, int version, int min_version,
|
||||
int access, int aux_type, word32 last_mod, word32 eof)
|
||||
{
|
||||
Vol_hdr *vol_ptr;
|
||||
int val;
|
||||
Directory *dir_ptr;
|
||||
File_entry *file_ptr;
|
||||
int file_count;
|
||||
int pos;
|
||||
int last_pos;
|
||||
int done;
|
||||
int next_blk;
|
||||
int name_len;
|
||||
|
||||
name_len = strlen(name);
|
||||
dir_ptr = disk_read_dir(disk, dir_block);
|
||||
next_blk = dir_block;
|
||||
val = dir_ptr->file_entries[0].storage_type_name_len;
|
||||
last_pos = 13;
|
||||
pos = 0;
|
||||
if(((val & 0xf0) == 0xf0) || ((val & 0xf0) == 0xe0)) {
|
||||
/* vol dir or subdir header */
|
||||
vol_ptr = (Vol_hdr *)&(dir_ptr->file_entries[0]);
|
||||
file_count = get_l2byte(&(vol_ptr->file_count));
|
||||
pos = 1;
|
||||
last_pos = vol_ptr->entries_per_block;
|
||||
} else {
|
||||
printf("dir_block: %04x not subdir or voldir\n", dir_block);
|
||||
exit(6);
|
||||
}
|
||||
|
||||
vol_ptr = 0;
|
||||
|
||||
done = 0;
|
||||
while(!done) {
|
||||
file_ptr = &(dir_ptr->file_entries[pos]);
|
||||
if(((file_ptr->storage_type_name_len) & 0xf0) == 0) {
|
||||
/* Got it! */
|
||||
file_ptr->storage_type_name_len =
|
||||
(storage_type << 4) | name_len;
|
||||
strncpy((char *)file_ptr->file_name, name, 15);
|
||||
file_ptr->file_type = file_type;
|
||||
set_l2byte(&(file_ptr->key_pointer),
|
||||
find_next_free_block(disk));
|
||||
set_l2byte(&(file_ptr->blocks_used), 0);
|
||||
set_pro_time(&(file_ptr->creation_time),
|
||||
creation_time);
|
||||
file_ptr->version = version;
|
||||
file_ptr->min_version = min_version;
|
||||
file_ptr->access = access;
|
||||
set_l2byte(&(file_ptr->aux_type), aux_type);
|
||||
set_pro_time(&(file_ptr->last_mod), last_mod);
|
||||
set_l2byte(&(file_ptr->header_pointer),
|
||||
dir_block);
|
||||
set_l3byte(&(file_ptr->eof), eof);
|
||||
disk_write_dir(disk, next_blk);
|
||||
|
||||
dir_ptr = disk_read_dir(disk, dir_block);
|
||||
vol_ptr = (Vol_hdr *)&(dir_ptr->file_entries[0]);
|
||||
set_l2byte(&(vol_ptr->file_count), file_count+1);
|
||||
disk_write_dir(disk, dir_block);
|
||||
|
||||
disk_read_dir(disk, next_blk);
|
||||
/* re-read dir so that ptrs are set up right */
|
||||
disk->file_ptr = file_ptr;
|
||||
disk->file_open = 1;
|
||||
disk->ind_blk_num = -1;
|
||||
disk->master_ind_blk_num = -1;
|
||||
done = 1;
|
||||
break;
|
||||
} else {
|
||||
/* check to make sure name is unique */
|
||||
if((file_ptr->storage_type_name_len & 0x0f)== name_len){
|
||||
if(!memcmp(file_ptr->file_name, name,name_len)){
|
||||
printf("Name %s already on disk!\n",
|
||||
name);
|
||||
exit(8);
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
if(pos >= last_pos) {
|
||||
/* Go to next block */
|
||||
next_blk = get_l2byte(&(dir_ptr->next_blk));
|
||||
if(next_blk) {
|
||||
dir_ptr = disk_read_dir(disk, next_blk);
|
||||
pos = 0;
|
||||
} else {
|
||||
printf("Top directory full!\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pro_write_file(ProDisk *disk, byte *in_buf, int pos, int size)
|
||||
{
|
||||
int block;
|
||||
int i;
|
||||
|
||||
block = get_disk_block(disk, pos, 1);
|
||||
if(block < 7) {
|
||||
printf("pro_write_file, get_disk_block: %d\n", block);
|
||||
exit(3);
|
||||
}
|
||||
if(size < 512) {
|
||||
for(i = size; i < 512; i++) {
|
||||
in_buf[i] = 0;
|
||||
}
|
||||
} else if(size > 512) {
|
||||
printf("error, pro_write_file size: %d too big\n", size);
|
||||
exit(4);
|
||||
}
|
||||
|
||||
disk_write_data(disk, block, in_buf, 512);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
get_disk_block(ProDisk *disk, int pos, int create)
|
||||
{
|
||||
File_entry *file_ptr;
|
||||
int storage_type;
|
||||
word32 eof;
|
||||
int lo, hi;
|
||||
int offset;
|
||||
int master_ind_block, ind_block;
|
||||
int ret_block;
|
||||
int key_block;
|
||||
|
||||
if(pos >= 128*256*512) {
|
||||
printf("offset too big\n");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
file_ptr = disk->file_ptr;
|
||||
|
||||
eof = get_l3byte(&(file_ptr->eof));
|
||||
storage_type = (file_ptr->storage_type_name_len) >> 4;
|
||||
|
||||
key_block = get_l2byte(&(file_ptr->key_pointer));
|
||||
|
||||
if(storage_type == 1 && pos >= 512) {
|
||||
/* make it sapling */
|
||||
get_new_ind_block(disk);
|
||||
inc_l2byte(&(file_ptr->blocks_used));
|
||||
disk->ind_blk_data[0] = key_block & 0xff;
|
||||
disk->ind_blk_data[0x100] = key_block >> 8;
|
||||
key_block = disk->ind_blk_num;
|
||||
set_l2byte(&(file_ptr->key_pointer), key_block);
|
||||
file_ptr->storage_type_name_len += 0x10;
|
||||
storage_type++;
|
||||
}
|
||||
if(storage_type == 2 && pos >= 256*512) {
|
||||
/* make it tree */
|
||||
get_new_master_ind_block(disk);
|
||||
inc_l2byte(&(file_ptr->blocks_used));
|
||||
disk->master_ind_blk_data[0] = key_block & 0xff;
|
||||
disk->master_ind_blk_data[0x100] = key_block >> 8;
|
||||
key_block = disk->master_ind_blk_num;
|
||||
set_l2byte(&(file_ptr->key_pointer), key_block);
|
||||
file_ptr->storage_type_name_len += 0x10;
|
||||
storage_type++;
|
||||
}
|
||||
|
||||
switch(storage_type) {
|
||||
case 1:
|
||||
if(pos >= 512) {
|
||||
printf("Error1!\n");
|
||||
exit(3);
|
||||
}
|
||||
ret_block = key_block;
|
||||
if(ret_block == 0) {
|
||||
ret_block = find_next_free_block(disk);
|
||||
inc_l2byte(&(file_ptr->blocks_used));
|
||||
set_l2byte(&(file_ptr->key_pointer), ret_block);
|
||||
}
|
||||
return ret_block;
|
||||
case 2:
|
||||
ind_block = key_block;
|
||||
if(ind_block <= 0) {
|
||||
printf("write failure, ind_block: %d!\n", ind_block);
|
||||
exit(3);
|
||||
}
|
||||
offset = pos >> 9;
|
||||
if(offset >= 256) {
|
||||
printf("pos too big!\n");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
lo = disk->ind_blk_data[offset];
|
||||
hi = disk->ind_blk_data[offset + 0x100];
|
||||
ret_block = hi*256 + lo;
|
||||
if(ret_block == 0) {
|
||||
/* Need to alloc a block for this guy */
|
||||
ret_block = find_next_free_block(disk);
|
||||
inc_l2byte(&(file_ptr->blocks_used));
|
||||
disk->ind_blk_data[offset] = ret_block & 0xff;
|
||||
disk->ind_blk_data[offset + 0x100] =
|
||||
((ret_block >> 8) & 0xff);
|
||||
}
|
||||
return ret_block;
|
||||
case 3:
|
||||
/* tree */
|
||||
master_ind_block = key_block;
|
||||
if(master_ind_block <= 0) {
|
||||
printf("write failure, master_ind_block: %d!\n",
|
||||
master_ind_block);
|
||||
exit(3);
|
||||
}
|
||||
offset = pos >> 17;
|
||||
if(offset >= 128) {
|
||||
printf("master too big!\n");
|
||||
exit(4);
|
||||
}
|
||||
lo = disk->master_ind_blk_data[offset];
|
||||
hi = disk->master_ind_blk_data[offset + 0x100];
|
||||
ind_block = hi*256 + lo;
|
||||
if(ind_block == 0) {
|
||||
/* Need to alloc an ind block */
|
||||
get_new_ind_block(disk);
|
||||
ind_block = disk->ind_blk_num;
|
||||
inc_l2byte(&(file_ptr->blocks_used));
|
||||
disk->master_ind_blk_data[offset] = ind_block & 0xff;
|
||||
disk->master_ind_blk_data[offset + 0x100] =
|
||||
((ind_block >> 8) & 0xff);
|
||||
}
|
||||
|
||||
offset = (pos >> 9) & 0xff;
|
||||
lo = disk->ind_blk_data[offset];
|
||||
hi = disk->ind_blk_data[offset + 0x100];
|
||||
ret_block = hi*256 + lo;
|
||||
|
||||
if(ret_block == 0) {
|
||||
/* Need to alloc a block for this guy */
|
||||
ret_block = find_next_free_block(disk);
|
||||
inc_l2byte(&(file_ptr->blocks_used));
|
||||
disk->ind_blk_data[offset] = ret_block & 0xff;
|
||||
disk->ind_blk_data[offset + 0x100] =
|
||||
((ret_block >> 8) & 0xff);
|
||||
}
|
||||
return ret_block;
|
||||
default:
|
||||
printf("unknown storage type: %d\n", storage_type);
|
||||
exit(4);
|
||||
}
|
||||
|
||||
printf("Can't get here!\n");
|
||||
exit(5);
|
||||
}
|
||||
|
||||
void
|
||||
get_new_ind_block(ProDisk *disk)
|
||||
{
|
||||
int ind_blk_num;
|
||||
int i;
|
||||
|
||||
write_ind_block(disk);
|
||||
|
||||
ind_blk_num = find_next_free_block(disk);
|
||||
for(i = 0; i < 512; i++) {
|
||||
disk->ind_blk_data[i] = 0;
|
||||
}
|
||||
|
||||
disk->ind_blk_num = ind_blk_num;
|
||||
}
|
||||
|
||||
void
|
||||
write_ind_block(ProDisk *disk)
|
||||
{
|
||||
int ind_blk_num;
|
||||
|
||||
ind_blk_num = disk->ind_blk_num;
|
||||
if(ind_blk_num > 0) {
|
||||
printf("Write ind block: %04x\n", ind_blk_num);
|
||||
disk_write_data(disk, ind_blk_num, &(disk->ind_blk_data[0]),
|
||||
512);
|
||||
disk->ind_blk_num = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
get_new_master_ind_block(ProDisk *disk)
|
||||
{
|
||||
int master_ind_blk_num;
|
||||
int i;
|
||||
|
||||
write_master_ind_block(disk);
|
||||
|
||||
master_ind_blk_num = find_next_free_block(disk);
|
||||
for(i = 0; i < 512; i++) {
|
||||
disk->master_ind_blk_data[i] = 0;
|
||||
}
|
||||
|
||||
disk->master_ind_blk_num = master_ind_blk_num;
|
||||
}
|
||||
|
||||
void
|
||||
write_master_ind_block(ProDisk *disk)
|
||||
{
|
||||
int master_ind_blk_num;
|
||||
|
||||
master_ind_blk_num = disk->master_ind_blk_num;
|
||||
if(master_ind_blk_num > 0) {
|
||||
printf("Write master_ind block: %04x\n", master_ind_blk_num);
|
||||
disk_write_data(disk, master_ind_blk_num,
|
||||
&(disk->master_ind_blk_data[0]), 512);
|
||||
disk->master_ind_blk_num = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
find_next_free_block(ProDisk *disk)
|
||||
{
|
||||
byte *bitmap_ptr;
|
||||
int pos;
|
||||
int bitmap_bytes;
|
||||
int i, j;
|
||||
word32 val;
|
||||
|
||||
bitmap_ptr = disk->bitmap_ptr;
|
||||
bitmap_bytes = disk->bitmap_bytes;
|
||||
pos = disk->bitmap_cur_pos;
|
||||
|
||||
for(i = pos; i < bitmap_bytes; i++) {
|
||||
val = bitmap_ptr[i];
|
||||
if(val == 0) {
|
||||
continue;
|
||||
}
|
||||
for(j = 0; j < 8; j++) {
|
||||
if(val & (0x80 >> j)) {
|
||||
set_bitmap_used(bitmap_ptr, 8*i+j);
|
||||
disk->bitmap_cur_pos = i;
|
||||
return 8*i + j;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
set_bitmap_used(byte *ptr, int i)
|
||||
{
|
||||
word32 offset, bit;
|
||||
word32 val;
|
||||
|
||||
offset = i >> 3;
|
||||
bit = i & 7;
|
||||
|
||||
val = ~(0x80 >> bit);
|
||||
ptr[offset] &= val;
|
||||
}
|
||||
|
||||
void
|
||||
set_bitmap_free(byte *ptr, int i)
|
||||
{
|
||||
int offset, bit;
|
||||
int val;
|
||||
|
||||
offset = i >> 3;
|
||||
bit = i & 7;
|
||||
|
||||
val = (0x80 >> bit);
|
||||
ptr[offset] |= val;
|
||||
}
|
||||
|
||||
void
|
||||
set_file_entry(File_entry *entry, int storage_type_name_len, char *file_name,
|
||||
int file_type, int key_pointer, int blocks_used, int eof,
|
||||
word32 creation_time, int version, int min_version, int access,
|
||||
int aux_type, word32 last_mod, int header_pointer)
|
||||
{
|
||||
|
||||
entry->storage_type_name_len = storage_type_name_len;
|
||||
strncpy((char *)entry->file_name, file_name, 15);
|
||||
entry->file_type = file_type;
|
||||
set_l2byte(&(entry->key_pointer), key_pointer);
|
||||
set_l2byte(&(entry->blocks_used), blocks_used);
|
||||
set_l3byte(&(entry->eof), eof);
|
||||
set_pro_time(&(entry->creation_time), creation_time);
|
||||
entry->version = version;
|
||||
entry->min_version = min_version;
|
||||
entry->access = access;
|
||||
set_l2byte(&(entry->aux_type), aux_type);
|
||||
set_pro_time(&(entry->last_mod), last_mod);
|
||||
set_l2byte(&(entry->aux_type), header_pointer);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
set_l2byte(L2byte *ptr, int val)
|
||||
{
|
||||
ptr->low = (val & 0xff);
|
||||
ptr->hi = ((val >> 8) & 0xff);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
set_l3byte(L3byte *ptr, int val)
|
||||
{
|
||||
ptr->low = (val & 0xff);
|
||||
ptr->hi = ((val >> 8) & 0xff);
|
||||
ptr->higher = ((val >> 16) & 0xff);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
set_pro_time(Pro_time *ptr, word32 val)
|
||||
{
|
||||
ptr->times[0] = ((val >> 24) & 0xff);
|
||||
ptr->times[1] = ((val >> 16) & 0xff);
|
||||
ptr->times[2] = ((val >> 8) & 0xff);
|
||||
ptr->times[3] = ((val) & 0xff);
|
||||
}
|
||||
|
||||
int
|
||||
get_l2byte(L2byte *ptr)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = ((ptr->hi) * 256) + ptr->low;
|
||||
return val;
|
||||
}
|
||||
|
||||
int
|
||||
get_l3byte(L3byte *ptr)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = ((ptr->higher) * 65536) + ((ptr->hi) * 256) + ptr->low;
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
inc_l2byte(L2byte *ptr)
|
||||
{
|
||||
set_l2byte(ptr, get_l2byte(ptr) + 1);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
TARGET = xkegs
|
||||
OBJECTS = $(OBJECTS1) xdriver.o
|
||||
CC = gcc
|
||||
CCOPTS = -O
|
||||
OPTS = -DNDEBUG
|
||||
SUFFIX =
|
||||
NAME = xkegs
|
||||
LDFLAGS =
|
||||
LDOPTS = -z
|
||||
LD = $(CC)
|
||||
EXTRA_LIBS = -lXext -lX11 -lcl -lc
|
||||
EXTRA_SPECIALS = Alib.h
|
||||
|
||||
AS = cc -Ae
|
||||
PERL = perl
|
||||
|
||||
XOPTS = -DHPUX -I/usr/include/X11R5
|
||||
XLIBS = -L/usr/lib/X11R5 -L/opt/audio/lib
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
TARGET = xkegs
|
||||
OBJECTS = engine_s.o $(OBJECTS1) sound_driver.o xdriver.o
|
||||
CC = cc -Ae +DA1.1
|
||||
CCOPTS = -O
|
||||
OPTS = -DNDEBUG
|
||||
SUFFIX =
|
||||
NAME = xkegs
|
||||
LDFLAGS =
|
||||
LDOPTS = -z
|
||||
LD = $(CC)
|
||||
EXTRA_LIBS = -lXext -lX11 -lcl -lc
|
||||
EXTRA_SPECIALS = 8inst_s 16inst_s 8size 16size size_s Alib.h
|
||||
|
||||
AS = cc -Ae
|
||||
PERL = perl
|
||||
|
||||
XOPTS = -DHPUX -I/usr/include/X11R5
|
||||
XLIBS = -L/usr/lib/X11R5 -L/opt/audio/lib
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
TARGET = xkegs
|
||||
OBJECTS = $(OBJECTS1) xdriver.o
|
||||
CC = cc
|
||||
CCOPTS = -O
|
||||
OPTS = -DNDEBUG
|
||||
SUFFIX =
|
||||
NAME = xkegs
|
||||
LDFLAGS =
|
||||
LDOPTS =
|
||||
LD = $(CC)
|
||||
EXTRA_LIBS = -lXext -lX11 -lc
|
||||
EXTRA_SPECIALS =
|
||||
|
||||
AS = cc
|
||||
PERL = perl
|
||||
|
||||
XOPTS = -I/usr/X11R6/include
|
||||
XLIBS = -L/usr/X11R6/lib
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
TARGET = kegsmac
|
||||
OBJECTS = $(OBJECTS1) macsnd_driver.o macdriver.o
|
||||
CCOPTS = -O2 -DMAC
|
||||
SUFFIX =
|
||||
NAME = kegsmac
|
||||
|
||||
XOPTS = -Wall -fpascal-strings -mdynamic-no-pic -arch ppc
|
||||
XLIBS =
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
TARGET = xkegs
|
||||
OBJECTS = $(OBJECTS1) xdriver.o
|
||||
CC = cc
|
||||
CCOPTS = -O
|
||||
OPTS = -DNDEBUG -DSOLARIS
|
||||
SUFFIX =
|
||||
NAME = xkegs
|
||||
LDFLAGS =
|
||||
LDOPTS =
|
||||
LD = $(CC)
|
||||
EXTRA_LIBS = -lXext -lX11 -lsocket -lnsl
|
||||
EXTRA_SPECIALS =
|
||||
|
||||
AS = cc
|
||||
PERL = perl
|
||||
|
||||
XOPTS = -I/usr/X/include
|
||||
XLIBS = -L/usr/X/lib
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
TARGET = kegswin.exe
|
||||
OBJECTS = $(OBJECTS1) win32snd_driver.o windriver.o
|
||||
CCOPTS = -O2 -DKEGS_LITTLE_ENDIAN
|
||||
SUFFIX = ".exe"
|
||||
NAME = kegswin
|
||||
|
||||
XOPTS = -Wall -fomit-frame-pointer -march=pentium
|
||||
XLIBS =
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
TARGET = xkegs
|
||||
OBJECTS = $(OBJECTS1) xdriver.o
|
||||
CC = cc
|
||||
CCOPTS = -O2 -Wall -fomit-frame-pointer -march=pentium
|
||||
OPTS = -DKEGS_LITTLE_ENDIAN
|
||||
SUFFIX =
|
||||
NAME = xkegs
|
||||
LDFLAGS =
|
||||
LDOPTS =
|
||||
LD = $(CC)
|
||||
EXTRA_LIBS = -lXext
|
||||
EXTRA_SPECIALS =
|
||||
|
||||
AS = cc
|
||||
PERL = perl
|
||||
|
||||
XOPTS = -I/usr/X11R6/include
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
TARGET = xkegs
|
||||
OBJECTS = $(OBJECTS1) xdriver.o
|
||||
CC = gcc
|
||||
CCOPTS = -O
|
||||
OPTS = -DNDEBUG -DSOLARIS -DKEGS_LITTLE_ENDIAN -DOSS
|
||||
SUFFIX =
|
||||
NAME = xkegs
|
||||
LDFLAGS =
|
||||
LDOPTS =
|
||||
LD = $(CC)
|
||||
EXTRA_LIBS = -lXext -lX11 -lsocket -lnsl
|
||||
EXTRA_SPECIALS =
|
||||
|
||||
AS = cc
|
||||
PERL = perl
|
||||
|
||||
XOPTS = -I/usr/X/include
|
||||
XLIBS = -L/usr/X/lib
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,109 @@
|
|||
#include <windows.h>
|
||||
#include "winresource.h"
|
||||
|
||||
// $Id: $
|
||||
|
||||
#ifndef IDC_STATIC
|
||||
#define IDC_STATIC (-1)
|
||||
#endif
|
||||
|
||||
IDD_DLG_DISKCONF DIALOGEX 0, 0, 268, 182
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Disk Configuration"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,150,161,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,203,161,50,14
|
||||
LTEXT "S5D1",IDC_STATIC,19,46,19,8
|
||||
EDITTEXT IDC_EDIT_S5D1,43,42,156,14,ES_AUTOHSCROLL,
|
||||
WS_EX_ACCEPTFILES
|
||||
PUSHBUTTON "Browse",IDC_BTN_S5D1,203,42,50,14
|
||||
LTEXT "S5D2",IDC_STATIC,19,62,19,8
|
||||
EDITTEXT IDC_EDIT_S5D2,43,60,155,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "Browse",IDC_BTN_S5D2,203,60,50,14
|
||||
LTEXT "S6D1",IDC_STATIC,19,80,19,8
|
||||
EDITTEXT IDC_EDIT_S6D1,43,77,156,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "Browse",IDC_BTN_S6D1,203,77,50,14
|
||||
LTEXT "S6D2",IDC_STATIC,19,98,19,8
|
||||
EDITTEXT IDC_EDIT_S6D2,43,95,156,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "Browse",IDC_BTN_S6D2,203,96,50,14
|
||||
LTEXT "S7D1",IDC_STATIC,19,118,19,8
|
||||
EDITTEXT IDC_EDIT_S7D1,43,115,155,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "Browse",IDC_BTN_S7D1,203,115,50,14
|
||||
LTEXT "S7D2",IDC_STATIC,19,137,19,8
|
||||
EDITTEXT IDC_EDIT_S7D2,43,135,155,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "Browse",IDC_BTN_S7D2,203,135,50,14
|
||||
GROUPBOX "Disk settings",IDC_STATIC,7,7,254,148
|
||||
LTEXT "Configure your disk images for each drive. Disk image formats supported\nare *.2MG,*.PO and *.DSK. ",
|
||||
IDC_STATIC,19,20,234,16
|
||||
END
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
IDC_KEGS32 MENU DISCARDABLE
|
||||
BEGIN
|
||||
POPUP "&Emulator"
|
||||
BEGIN
|
||||
MENUITEM "&Set Disk Configuration\tALT-F1", ID_FILE_DISK
|
||||
MENUITEM "Send CTRL Open-Apple Reset\tCTRL-ALT-BREAK",
|
||||
ID_FILE_SENDRESET
|
||||
MENUITEM "Toggle &Joystick", ID_FILE_JOYSTICK
|
||||
MENUITEM "Toggle Debug Statistics", ID_FILE_DEBUGSTAT
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "E&xit\tALT-F4", ID_FILE_EXIT
|
||||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&About", ID_HELP_ABOUT
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Bitmap
|
||||
//
|
||||
|
||||
IDR_TOOLBAR BITMAP DISCARDABLE "wintoolbar.bmp"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Accelerator
|
||||
//
|
||||
|
||||
IDR_ACCEL ACCELERATORS DISCARDABLE
|
||||
BEGIN
|
||||
VK_F1, ID_FILE_DISK, VIRTKEY, ALT, NOINVERT
|
||||
VK_F4, ID_FILE_EXIT, VIRTKEY, ALT, NOINVERT
|
||||
END
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDC_KEGS32 ICON DISCARDABLE "win32.ico"
|
||||
KEGS32_ICON ICON DISCARDABLE "win32.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_ABOUT_DIALOG DIALOG DISCARDABLE 0, 0, 207, 82
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "About"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,78,61,50,14
|
||||
LTEXT "KEGS32: GS Emulator.\nBased on KEGS by Kent Dickey\nWindows Port by Chea Chee Keong\n\nThis software is free for non-commercial use.",
|
||||
IDC_STATIC,38,7,162,45,NOT WS_GROUP
|
||||
ICON "KEGS32_ICON",IDC_STATIC,7,7,21,20,0
|
||||
END
|
||||
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_win32snd_driver_c[] = "@(#)$KmKId: win32snd_driver.c,v 1.5 2002-11-19 03:09:59-05 kadickey Exp $";
|
||||
|
||||
#include "defc.h"
|
||||
#include "sound.h"
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
# include <windows.h>
|
||||
# include <mmsystem.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
extern int Verbose;
|
||||
|
||||
extern int g_audio_rate;
|
||||
|
||||
unsigned int __stdcall child_sound_loop_win32(void *param);
|
||||
void check_wave_error(int res, char *str);
|
||||
|
||||
#define NUM_WAVE_HEADERS 8
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
HWAVEOUT g_wave_handle;
|
||||
WAVEHDR g_wavehdr[NUM_WAVE_HEADERS];
|
||||
#endif
|
||||
|
||||
extern int g_audio_enable;
|
||||
extern word32 *g_sound_shm_addr;
|
||||
extern int g_preferred_rate;
|
||||
|
||||
int g_win32snd_buflen = 0x1000;
|
||||
|
||||
void
|
||||
win32snd_init(word32 *shmaddr)
|
||||
{
|
||||
printf("win32snd_init\n");
|
||||
child_sound_loop(-1, -1, shmaddr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
win32snd_shutdown()
|
||||
{
|
||||
/* hmm */
|
||||
|
||||
}
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
|
||||
void CALLBACK
|
||||
handle_wav_snd(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1,
|
||||
DWORD dwParam2)
|
||||
{
|
||||
LPWAVEHDR lpwavehdr;
|
||||
|
||||
/* Only service "buffer done playing messages */
|
||||
if(uMsg == WOM_DONE) {
|
||||
lpwavehdr = (LPWAVEHDR)dwParam1;
|
||||
if(lpwavehdr->dwFlags == (WHDR_DONE | WHDR_PREPARED)) {
|
||||
lpwavehdr->dwUser = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
void
|
||||
check_wave_error(int res, char *str)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
if(res == MMSYSERR_NOERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
waveOutGetErrorText(res, &buf[0], sizeof(buf));
|
||||
printf("%s: %s\n", str, buf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
child_sound_init_win32()
|
||||
{
|
||||
WAVEFORMATEX wavefmt;
|
||||
WAVEOUTCAPS caps;
|
||||
byte *bptr;
|
||||
int bits_per_sample, channels, block_align;
|
||||
int blen;
|
||||
int res;
|
||||
int i;
|
||||
|
||||
memset(&wavefmt, 0, sizeof(WAVEFORMATEX));
|
||||
|
||||
wavefmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||
bits_per_sample = 16;
|
||||
channels = 2;
|
||||
wavefmt.wBitsPerSample = bits_per_sample;
|
||||
wavefmt.nChannels = channels;
|
||||
wavefmt.nSamplesPerSec = g_audio_rate;
|
||||
block_align = channels * (bits_per_sample / 8);
|
||||
wavefmt.nBlockAlign = block_align;
|
||||
wavefmt.nAvgBytesPerSec = block_align * g_audio_rate;
|
||||
|
||||
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, 0, 0,
|
||||
WAVE_FORMAT_QUERY);
|
||||
|
||||
if(res != MMSYSERR_NOERROR) {
|
||||
printf("Cannot open audio device\n");
|
||||
g_audio_enable = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt,
|
||||
(DWORD)handle_wav_snd, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
|
||||
|
||||
if(res != MMSYSERR_NOERROR) {
|
||||
printf("Cannot register audio\n");
|
||||
g_audio_enable = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
g_audio_rate = wavefmt.nSamplesPerSec;
|
||||
|
||||
blen = (SOUND_SHM_SAMP_SIZE * 4 * 2) / NUM_WAVE_HEADERS;
|
||||
g_win32snd_buflen = blen;
|
||||
bptr = malloc(blen * NUM_WAVE_HEADERS);
|
||||
if(bptr == NULL) {
|
||||
printf("Unabled to allocate sound buffer\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i = 0; i < NUM_WAVE_HEADERS; i++) {
|
||||
memset(&g_wavehdr[i], 0, sizeof(WAVEHDR));
|
||||
g_wavehdr[i].dwUser = FALSE;
|
||||
g_wavehdr[i].lpData = &(bptr[i*blen]);
|
||||
g_wavehdr[i].dwBufferLength = blen;
|
||||
g_wavehdr[i].dwFlags = 0;
|
||||
g_wavehdr[i].dwLoops = 0;
|
||||
res = waveOutPrepareHeader(g_wave_handle, &g_wavehdr[i],
|
||||
sizeof(WAVEHDR));
|
||||
check_wave_error(res, "waveOutPrepareHeader");
|
||||
}
|
||||
|
||||
res = waveOutGetDevCaps((UINT)g_wave_handle, &caps, sizeof(caps));
|
||||
check_wave_error(res, "waveOutGetDevCaps");
|
||||
printf("Using %s\n", caps.szPname);
|
||||
printf(" Bits per Sample = %d. Channels = %d\n",
|
||||
wavefmt.wBitsPerSample, wavefmt.nChannels);
|
||||
printf(" Sampling rate = %d, avg_bytes_per_sec = %d\n",
|
||||
(int)wavefmt.nSamplesPerSec, (int)wavefmt.nAvgBytesPerSec);
|
||||
|
||||
set_audio_rate(g_audio_rate);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
win32_send_audio2(byte *ptr, int size)
|
||||
{
|
||||
int found;
|
||||
int res;
|
||||
int i;
|
||||
|
||||
found = 0;
|
||||
for(i = 0; i < NUM_WAVE_HEADERS; i++) {
|
||||
if(g_wavehdr[i].dwUser == FALSE) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
/* all audio buffers busy, just get out */
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(g_wavehdr[i].lpData, ptr, size);
|
||||
g_wavehdr[i].dwBufferLength = size;
|
||||
g_wavehdr[i].dwUser = TRUE;
|
||||
|
||||
res = waveOutWrite(g_wave_handle, &g_wavehdr[i], sizeof(g_wavehdr));
|
||||
check_wave_error(res, "waveOutWrite");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
win32_send_audio(byte *ptr, int in_size)
|
||||
{
|
||||
int size;
|
||||
int tmpsize;
|
||||
|
||||
size = in_size;
|
||||
while(size > 0) {
|
||||
tmpsize = size;
|
||||
if(size > g_win32snd_buflen) {
|
||||
tmpsize = g_win32snd_buflen;
|
||||
}
|
||||
win32_send_audio2(ptr, tmpsize);
|
||||
ptr += tmpsize;
|
||||
size = size - tmpsize;
|
||||
}
|
||||
|
||||
return in_size;
|
||||
}
|
||||
|
||||
#endif /* __CYGWIN */
|
|
@ -0,0 +1,637 @@
|
|||
/************************************************************************/
|
||||
/* KEGS: Apple //gs Emulator */
|
||||
/* Copyright 2002 by Kent Dickey */
|
||||
/* */
|
||||
/* This code is covered by the GNU GPL */
|
||||
/* */
|
||||
/* The KEGS web page is kegs.sourceforge.net */
|
||||
/* You may contact the author at: kadickey@alumni.princeton.edu */
|
||||
/************************************************************************/
|
||||
|
||||
const char rcsid_windriver_c[] = "@(#)$KmKId: windriver.c,v 1.8 2004-03-23 17:25:37-05 kentd Exp $";
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN /* Tell windows we want less header gunk */
|
||||
#define STRICT /* Tell Windows we want compile type checks */
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <mmsystem.h>
|
||||
#include <winsock.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
#include "defc.h"
|
||||
#include "protos_windriver.h"
|
||||
|
||||
extern int Verbose;
|
||||
|
||||
extern int g_warp_pointer;
|
||||
extern int g_screen_depth;
|
||||
extern int g_force_depth;
|
||||
int g_screen_mdepth = 0;
|
||||
|
||||
extern int g_quit_sim_now;
|
||||
|
||||
int g_use_shmem = 1;
|
||||
int g_has_focus = 0;
|
||||
int g_auto_repeat_on = -1;
|
||||
|
||||
extern Kimage g_mainwin_kimage;
|
||||
|
||||
HDC g_main_dc;
|
||||
HDC g_main_cdc;
|
||||
int g_main_height = 0;
|
||||
|
||||
int g_win_capslock_down = 0;
|
||||
|
||||
extern word32 g_palette_8to1624[256];
|
||||
extern word32 g_a2palette_8to1624[256];
|
||||
|
||||
extern word32 g_full_refresh_needed;
|
||||
|
||||
extern int g_border_sides_refresh_needed;
|
||||
extern int g_border_special_refresh_needed;
|
||||
extern int g_status_refresh_needed;
|
||||
|
||||
extern int g_lores_colors[];
|
||||
extern int g_cur_a2_stat;
|
||||
|
||||
extern int g_a2vid_palette;
|
||||
|
||||
extern int g_installed_full_superhires_colormap;
|
||||
|
||||
extern int g_screen_redraw_skip_amt;
|
||||
|
||||
extern word32 g_a2_screen_buffer_changed;
|
||||
|
||||
HWND g_hwnd_main;
|
||||
BITMAPINFO *g_bmapinfo_ptr = 0;
|
||||
volatile BITMAPINFOHEADER *g_bmaphdr_ptr = 0;
|
||||
|
||||
int g_num_a2_keycodes = 0;
|
||||
|
||||
extern char *g_status_ptrs[MAX_STATUS_LINES];
|
||||
|
||||
int g_win_button_states = 0;
|
||||
|
||||
|
||||
/* this table is used to search for the Windows VK_* in col 1 or 2 */
|
||||
/* flags bit 8 is or'ed into the VK, so we can distinguish keypad keys */
|
||||
/* regardless of numlock */
|
||||
int g_a2_key_to_wsym[][3] = {
|
||||
{ 0x35, VK_ESCAPE, 0 },
|
||||
{ 0x7a, VK_F1, 0 },
|
||||
{ 0x7b, VK_F2, 0 },
|
||||
{ 0x63, VK_F3, 0 },
|
||||
{ 0x76, VK_F4, 0 },
|
||||
{ 0x60, VK_F5, 0 },
|
||||
{ 0x61, VK_F6, 0 },
|
||||
{ 0x62, VK_F7, 0 },
|
||||
{ 0x64, VK_F8, 0 },
|
||||
{ 0x65, VK_F9, 0 },
|
||||
{ 0x6d, VK_F10, 0 },
|
||||
{ 0x67, VK_F11, 0 },
|
||||
{ 0x6f, VK_F12, 0 },
|
||||
{ 0x69, VK_F13, 0 },
|
||||
{ 0x6b, VK_F14, 0 },
|
||||
{ 0x71, VK_F15, 0 },
|
||||
{ 0x7f, VK_PAUSE, VK_CANCEL+0x100 },
|
||||
|
||||
{ 0x32, 0xc0, 0 }, /* '`' */
|
||||
{ 0x12, '1', 0 },
|
||||
{ 0x13, '2', 0 },
|
||||
{ 0x14, '3', 0 },
|
||||
{ 0x15, '4', 0 },
|
||||
{ 0x17, '5', 0 },
|
||||
{ 0x16, '6', 0 },
|
||||
{ 0x1a, '7', 0 },
|
||||
{ 0x1c, '8', 0 },
|
||||
{ 0x19, '9', 0 },
|
||||
{ 0x1d, '0', 0 },
|
||||
{ 0x1b, 0xbd, 0 }, /* '-' */
|
||||
{ 0x18, 0xbb, 0 }, /* '=' */
|
||||
{ 0x33, VK_BACK, 0 }, /* backspace */
|
||||
{ 0x72, VK_INSERT+0x100, 0 }, /* Insert key */
|
||||
/* { 0x73, XK_Home, 0 }, alias VK_HOME to be KP_Equal! */
|
||||
{ 0x74, VK_PRIOR+0x100, 0 }, /* pageup */
|
||||
{ 0x47, VK_NUMLOCK, VK_NUMLOCK+0x100 }, /* clear */
|
||||
{ 0x51, VK_HOME+0x100, 0 }, /* KP_equal is HOME key */
|
||||
{ 0x4b, VK_DIVIDE, VK_DIVIDE+0x100 },
|
||||
{ 0x43, VK_MULTIPLY, VK_MULTIPLY+0x100 },
|
||||
|
||||
{ 0x30, VK_TAB, 0 },
|
||||
{ 0x0c, 'Q', 0 },
|
||||
{ 0x0d, 'W', 0 },
|
||||
{ 0x0e, 'E', 0 },
|
||||
{ 0x0f, 'R', 0 },
|
||||
{ 0x11, 'T', 0 },
|
||||
{ 0x10, 'Y', 0 },
|
||||
{ 0x20, 'U', 0 },
|
||||
{ 0x22, 'I', 0 },
|
||||
{ 0x1f, 'O', 0 },
|
||||
{ 0x23, 'P', 0 },
|
||||
{ 0x21, 0xdb, 0 }, /* [ */
|
||||
{ 0x1e, 0xdd, 0 }, /* ] */
|
||||
{ 0x2a, 0xdc, 0 }, /* backslash, bar */
|
||||
{ 0x75, VK_DELETE+0x100, 0 },
|
||||
{ 0x77, VK_END+0x100, VK_END },
|
||||
{ 0x79, VK_NEXT+0x100, 0 },
|
||||
{ 0x59, VK_NUMPAD7, VK_HOME },
|
||||
{ 0x5b, VK_NUMPAD8, VK_UP },
|
||||
{ 0x5c, VK_NUMPAD9, VK_PRIOR },
|
||||
{ 0x4e, VK_SUBTRACT, VK_SUBTRACT+0x100 },
|
||||
|
||||
// { 0x39, VK_CAPITAL, 0 }, // Handled specially!
|
||||
{ 0x00, 'A', 0 },
|
||||
{ 0x01, 'S', 0 },
|
||||
{ 0x02, 'D', 0 },
|
||||
{ 0x03, 'F', 0 },
|
||||
{ 0x05, 'G', 0 },
|
||||
{ 0x04, 'H', 0 },
|
||||
{ 0x26, 'J', 0 },
|
||||
{ 0x28, 'K', 0 },
|
||||
{ 0x25, 'L', 0 },
|
||||
{ 0x29, 0xba, 0 }, /* ; */
|
||||
{ 0x27, 0xde, 0 }, /* single quote */
|
||||
{ 0x24, VK_RETURN, 0 },
|
||||
{ 0x56, VK_NUMPAD4, VK_LEFT },
|
||||
{ 0x57, VK_NUMPAD5, VK_CLEAR },
|
||||
{ 0x58, VK_NUMPAD6, VK_RIGHT },
|
||||
{ 0x45, VK_ADD, 0 },
|
||||
|
||||
{ 0x38, VK_SHIFT, 0 },
|
||||
{ 0x06, 'Z', 0 },
|
||||
{ 0x07, 'X', 0 },
|
||||
{ 0x08, 'C', 0 },
|
||||
{ 0x09, 'V', 0 },
|
||||
{ 0x0b, 'B', 0 },
|
||||
{ 0x2d, 'N', 0 },
|
||||
{ 0x2e, 'M', 0 },
|
||||
{ 0x2b, 0xbc, 0 }, /* , */
|
||||
{ 0x2f, 0xbe, 0 }, /* . */
|
||||
{ 0x2c, 0xbf, 0 }, /* / */
|
||||
{ 0x3e, VK_UP+0x100, 0 },
|
||||
{ 0x53, VK_NUMPAD1, VK_END },
|
||||
{ 0x54, VK_NUMPAD2, VK_DOWN },
|
||||
{ 0x55, VK_NUMPAD3, VK_NEXT },
|
||||
|
||||
{ 0x36, VK_CONTROL, VK_CONTROL+0x100 },
|
||||
{ 0x3a, VK_SNAPSHOT+0x100, VK_MENU+0x100 },/* Opt=prntscrn or alt-r */
|
||||
{ 0x37, VK_SCROLL, VK_MENU }, /* Command=scr_lock or alt-l */
|
||||
{ 0x31, ' ', 0 },
|
||||
{ 0x3b, VK_LEFT+0x100, 0 },
|
||||
{ 0x3d, VK_DOWN+0x100, 0 },
|
||||
{ 0x3c, VK_RIGHT+0x100, 0 },
|
||||
{ 0x52, VK_NUMPAD0, VK_INSERT },
|
||||
{ 0x41, VK_DECIMAL, VK_DECIMAL },
|
||||
{ 0x4c, VK_RETURN+0x100, 0 },
|
||||
{ -1, -1, -1 }
|
||||
};
|
||||
|
||||
int
|
||||
win_update_mouse(int x, int y, int button_states, int buttons_valid)
|
||||
{
|
||||
int buttons_changed;
|
||||
|
||||
buttons_changed = ((g_win_button_states & buttons_valid) !=
|
||||
button_states);
|
||||
g_win_button_states = (g_win_button_states & ~buttons_valid) |
|
||||
(button_states & buttons_valid);
|
||||
if(g_warp_pointer && (x == A2_WINDOW_WIDTH/2) &&
|
||||
(y == A2_WINDOW_HEIGHT/2) && (!buttons_changed) ) {
|
||||
/* tell adb routs to recenter but ignore this motion */
|
||||
update_mouse(x, y, 0, -1);
|
||||
return 0;
|
||||
}
|
||||
return update_mouse(x, y, button_states, buttons_valid & 7);
|
||||
}
|
||||
|
||||
void
|
||||
win_event_mouse(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
POINT pt;
|
||||
word32 flags;
|
||||
int buttons;
|
||||
int x, y;
|
||||
int motion;
|
||||
|
||||
flags = wParam;
|
||||
x = LOWORD(lParam) - BASE_MARGIN_LEFT;
|
||||
y = HIWORD(lParam) - BASE_MARGIN_TOP;
|
||||
|
||||
buttons = (flags & 1) +
|
||||
(((flags >> 1) & 1) << 2) +
|
||||
(((flags >> 4) & 1) << 1);
|
||||
#if 0
|
||||
printf("Mouse at %d, %d fl: %08x, but: %d\n", x, y, flags, buttons);
|
||||
#endif
|
||||
motion = win_update_mouse(x, y, buttons, 7);
|
||||
|
||||
if(motion && g_warp_pointer) {
|
||||
/* move mouse to center of screen */
|
||||
pt.x = BASE_MARGIN_LEFT + A2_WINDOW_WIDTH/2;
|
||||
pt.y = BASE_MARGIN_TOP + A2_WINDOW_HEIGHT/2;
|
||||
ClientToScreen(g_hwnd_main, &pt);
|
||||
SetCursorPos(pt.x, pt.y);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags)
|
||||
{
|
||||
word32 vk;
|
||||
int a2code;
|
||||
int is_up;
|
||||
int capslock_down;
|
||||
int i;
|
||||
|
||||
if((flags & 0x4000) && down) {
|
||||
/* auto-repeating, just ignore it */
|
||||
return;
|
||||
}
|
||||
|
||||
vk = raw_vk + (flags & 0x100);
|
||||
#if 0
|
||||
printf("Key event, vk=%04x, down:%d, repeat: %d, flags: %08x\n",
|
||||
vk, down, repeat, flags);
|
||||
#endif
|
||||
|
||||
/* remap a few keys here.. sigh */
|
||||
if((vk & 0xff) == VK_APPS) {
|
||||
/* remap to command */
|
||||
vk = VK_MENU;
|
||||
}
|
||||
|
||||
if((vk & 0xff) == VK_CAPITAL) {
|
||||
// Windows gives us up-and-down events of the actual key
|
||||
// Use GetKeyState to get the true toggle state, and pass
|
||||
// that on to the adb interface
|
||||
capslock_down = GetKeyState(VK_CAPITAL) & 0x01;
|
||||
if(capslock_down != g_win_capslock_down) {
|
||||
g_win_capslock_down = capslock_down;
|
||||
adb_physical_key_update(0x39, !capslock_down);
|
||||
}
|
||||
|
||||
return; // Do no more processing!
|
||||
}
|
||||
|
||||
/* search a2key_to_wsym to find wsym in col 1 or 2 */
|
||||
i = 0;
|
||||
is_up = !down;
|
||||
for(i = g_num_a2_keycodes-1; i >= 0; i--) {
|
||||
a2code = g_a2_key_to_wsym[i][0];
|
||||
if((vk == g_a2_key_to_wsym[i][1]) ||
|
||||
(vk == g_a2_key_to_wsym[i][2])) {
|
||||
vid_printf("Found vk:%04x = %02x\n", vk, a2code);
|
||||
adb_physical_key_update(a2code, is_up);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("VK: %04x unknown\n", vk);
|
||||
}
|
||||
|
||||
void
|
||||
win_event_quit(HWND hwnd)
|
||||
{
|
||||
g_quit_sim_now = 1;
|
||||
my_exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
win_event_redraw()
|
||||
{
|
||||
g_full_refresh_needed = -1;
|
||||
g_a2_screen_buffer_changed = -1;
|
||||
g_status_refresh_needed = 1;
|
||||
g_border_sides_refresh_needed = 1;
|
||||
g_border_special_refresh_needed = 1;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
win_event_handler(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(umsg) {
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONUP:
|
||||
win_event_mouse(wParam, lParam);
|
||||
return 0;
|
||||
case WM_PAINT:
|
||||
win_event_redraw();
|
||||
break;
|
||||
}
|
||||
switch(umsg) {
|
||||
HANDLE_MSG(hwnd, WM_KEYUP, win_event_key);
|
||||
HANDLE_MSG(hwnd, WM_KEYDOWN, win_event_key);
|
||||
HANDLE_MSG(hwnd, WM_SYSKEYUP, win_event_key);
|
||||
HANDLE_MSG(hwnd, WM_SYSKEYDOWN, win_event_key);
|
||||
HANDLE_MSG(hwnd, WM_DESTROY, win_event_quit);
|
||||
}
|
||||
|
||||
#if 0
|
||||
switch(umsg) {
|
||||
case WM_NCACTIVATE:
|
||||
case WM_NCHITTEST:
|
||||
case WM_NCMOUSEMOVE:
|
||||
case WM_SETCURSOR:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_CONTEXTMENU:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_PAINT:
|
||||
|
||||
break;
|
||||
default:
|
||||
printf("Got umsg2: %d\n", umsg);
|
||||
}
|
||||
#endif
|
||||
|
||||
return DefWindowProc(hwnd, umsg, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
WNDCLASS wndclass;
|
||||
RECT rect;
|
||||
int height;
|
||||
|
||||
InitCommonControls();
|
||||
|
||||
wndclass.style = 0;
|
||||
wndclass.lpfnWndProc = (WNDPROC)win_event_handler;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = 0;
|
||||
wndclass.hInstance = GetModuleHandle(NULL);
|
||||
wndclass.hIcon = LoadIcon((HINSTANCE)NULL, IDI_APPLICATION);
|
||||
wndclass.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
|
||||
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||
wndclass.lpszMenuName = NULL;
|
||||
wndclass.lpszClassName = "kegswin";
|
||||
|
||||
// Register the window
|
||||
if(!RegisterClass(&wndclass)) {
|
||||
printf("Registering window failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES * 16) + 32;
|
||||
g_main_height = height;
|
||||
|
||||
g_hwnd_main = CreateWindow("kegswin", "KEGSWIN - Apple //gs Emulator",
|
||||
WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
X_A2_WINDOW_WIDTH, height,
|
||||
NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
|
||||
printf("g_hwnd_main = %p, height = %d\n", g_hwnd_main, height);
|
||||
GetWindowRect(g_hwnd_main, &rect);
|
||||
printf("...rect is: %ld, %ld, %ld, %ld\n", rect.left, rect.top,
|
||||
rect.right, rect.bottom);
|
||||
|
||||
g_main_dc = GetDC(g_hwnd_main);
|
||||
|
||||
SetTextColor(g_main_dc, 0);
|
||||
SetBkColor(g_main_dc, 0xffffff);
|
||||
|
||||
g_main_cdc = CreateCompatibleDC(g_main_dc);
|
||||
|
||||
g_screen_depth = 24;
|
||||
g_screen_mdepth = 32;
|
||||
|
||||
|
||||
// Call kegsmain
|
||||
return kegsmain(argc, argv);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
check_input_events()
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
while(PeekMessage(&msg, g_hwnd_main, 0, 0, PM_NOREMOVE)) {
|
||||
if(GetMessage(&msg, g_hwnd_main, 0, 0) > 0) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
} else {
|
||||
printf("GetMessage returned <= 0\n");
|
||||
my_exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_update_color(int col_num, int red, int green, int blue, word32 rgb)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
x_update_physical_colormap()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
show_xcolor_array()
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
printf("%02x: %08x\n", i, g_palette_8to1624[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xdriver_end()
|
||||
{
|
||||
printf("xdriver_end\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_get_kimage(Kimage *kimage_ptr)
|
||||
{
|
||||
byte *ptr;
|
||||
int width;
|
||||
int height;
|
||||
int depth, mdepth;
|
||||
int size;
|
||||
|
||||
width = kimage_ptr->width_req;
|
||||
height = kimage_ptr->height;
|
||||
depth = kimage_ptr->depth;
|
||||
mdepth = kimage_ptr->mdepth;
|
||||
|
||||
size = 0;
|
||||
if(depth == g_screen_depth) {
|
||||
/* Use g_bmapinfo_ptr, adjusting width, height */
|
||||
g_bmaphdr_ptr->biWidth = width;
|
||||
g_bmaphdr_ptr->biHeight = -height;
|
||||
kimage_ptr->dev_handle = CreateDIBSection(g_main_dc,
|
||||
g_bmapinfo_ptr, DIB_RGB_COLORS,
|
||||
(VOID **)&(kimage_ptr->data_ptr), NULL, 0);
|
||||
} else {
|
||||
/* allocate buffers for video.c to draw into */
|
||||
|
||||
size = (width*height*mdepth) >> 3;
|
||||
ptr = (byte *)malloc(size);
|
||||
|
||||
if(ptr == 0) {
|
||||
printf("malloc for data failed, mdepth: %d\n", mdepth);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
kimage_ptr->data_ptr = ptr;
|
||||
|
||||
kimage_ptr->dev_handle = (void *)-1;
|
||||
|
||||
}
|
||||
printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr,
|
||||
kimage_ptr->dev_handle, kimage_ptr->data_ptr, size);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dev_video_init()
|
||||
{
|
||||
int extra_size;
|
||||
int lores_col;
|
||||
int a2code;
|
||||
int i;
|
||||
|
||||
printf("Preparing graphics system\n");
|
||||
|
||||
g_num_a2_keycodes = 0;
|
||||
for(i = 0; i < 0x7f; i++) {
|
||||
a2code = g_a2_key_to_wsym[i][0];
|
||||
if(a2code < 0) {
|
||||
g_num_a2_keycodes = i;
|
||||
}
|
||||
}
|
||||
|
||||
g_screen_depth = 24;
|
||||
g_screen_mdepth = 32;
|
||||
|
||||
extra_size = sizeof(RGBQUAD);
|
||||
if(g_screen_depth == 8) {
|
||||
extra_size = 256 * sizeof(RGBQUAD);
|
||||
}
|
||||
g_bmapinfo_ptr = (BITMAPINFO *)GlobalAlloc(GPTR,
|
||||
sizeof(BITMAPINFOHEADER) + extra_size);
|
||||
|
||||
g_bmaphdr_ptr = (BITMAPINFOHEADER *)g_bmapinfo_ptr;
|
||||
g_bmaphdr_ptr->biSize = sizeof(BITMAPINFOHEADER);
|
||||
g_bmaphdr_ptr->biWidth = A2_WINDOW_WIDTH;
|
||||
g_bmaphdr_ptr->biHeight = -A2_WINDOW_HEIGHT;
|
||||
g_bmaphdr_ptr->biPlanes = 1;
|
||||
g_bmaphdr_ptr->biBitCount = g_screen_mdepth;
|
||||
g_bmaphdr_ptr->biCompression = BI_RGB;
|
||||
g_bmaphdr_ptr->biClrUsed = 0;
|
||||
|
||||
video_get_kimages();
|
||||
|
||||
if(g_screen_depth != 8) {
|
||||
// Allocate g_mainwin_kimage
|
||||
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth,
|
||||
g_screen_mdepth);
|
||||
}
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
lores_col = g_lores_colors[i & 0xf];
|
||||
video_update_color_raw(i, lores_col);
|
||||
g_a2palette_8to1624[i] = g_palette_8to1624[i];
|
||||
}
|
||||
|
||||
g_installed_full_superhires_colormap = 1;
|
||||
|
||||
ShowWindow(g_hwnd_main, SW_SHOWDEFAULT);
|
||||
UpdateWindow(g_hwnd_main);
|
||||
|
||||
printf("Done with dev_video_init\n");
|
||||
fflush(stdout);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
x_redraw_status_lines()
|
||||
{
|
||||
COLORREF oldtextcolor, oldbkcolor;
|
||||
char *buf;
|
||||
int line;
|
||||
int len;
|
||||
int height;
|
||||
int margin;
|
||||
|
||||
height = 16;
|
||||
margin = 0;
|
||||
|
||||
oldtextcolor = SetTextColor(g_main_dc, 0);
|
||||
oldbkcolor = SetBkColor(g_main_dc, 0xffffff);
|
||||
for(line = 0; line < MAX_STATUS_LINES; line++) {
|
||||
buf = g_status_ptrs[line];
|
||||
if(buf != 0) {
|
||||
len = strlen(buf);
|
||||
TextOut(g_main_dc, 10, X_A2_WINDOW_HEIGHT +
|
||||
height*line + margin, buf, len);
|
||||
}
|
||||
}
|
||||
SetTextColor(g_main_dc, oldtextcolor);
|
||||
SetBkColor(g_main_dc, oldbkcolor);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
|
||||
int width, int height)
|
||||
{
|
||||
void *bitm_old;
|
||||
POINT point;
|
||||
|
||||
point.x = 0;
|
||||
point.y = 0;
|
||||
ClientToScreen(g_hwnd_main, &point);
|
||||
bitm_old = SelectObject(g_main_cdc, kimage_ptr->dev_handle);
|
||||
|
||||
BitBlt(g_main_dc, destx, desty, width, height,
|
||||
g_main_cdc, srcx, srcy, SRCCOPY);
|
||||
|
||||
SelectObject(g_main_cdc, bitm_old);
|
||||
}
|
||||
|
||||
void
|
||||
x_push_done()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
x_auto_repeat_on(int must)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
x_auto_repeat_off(int must)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
x_hide_pointer(int do_hide)
|
||||
{
|
||||
if(do_hide) {
|
||||
ShowCursor(0);
|
||||
} else {
|
||||
ShowCursor(1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// $Id: $
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by win32.rc
|
||||
//
|
||||
#define IDD_ABOUT_DIALOG 101
|
||||
#define IDC_KEGS32 102
|
||||
#define IDR_TOOLBAR 103
|
||||
#define IDD_DLG_DISKCONF 104
|
||||
#define IDR_ACCEL 105
|
||||
#define ID_TOOLBAR 5000
|
||||
#define ID_STATUSBAR 5001
|
||||
#define IDC_EDIT_S5D1 10051
|
||||
#define IDC_EDIT_S5D2 10052
|
||||
#define IDC_EDIT_S6D1 10061
|
||||
#define IDC_EDIT_S6D2 10062
|
||||
#define IDC_EDIT_S7D1 10071
|
||||
#define IDC_EDIT_S7D2 10072
|
||||
#define IDC_BTN_S5D1 11051
|
||||
#define IDC_BTN_S5D2 11052
|
||||
#define IDC_BTN_S6D1 11061
|
||||
#define IDC_BTN_S6D2 11062
|
||||
#define IDC_BTN_S7D1 11071
|
||||
#define IDC_BTN_S7D2 11072
|
||||
#define ID_HELP_ABOUT 40001
|
||||
#define ID_FILE_EXIT 40002
|
||||
#define ID_FILE_DISK 40003
|
||||
#define ID_FILE_SENDRESET 40004
|
||||
#define ID_FILE_JOYSTICK 40005
|
||||
#define ID_FILE_DEBUGSTAT 40006
|
||||
#define ID_FILE_FULLSCREEN 40012
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 111
|
||||
#define _APS_NEXT_COMMAND_VALUE 40013
|
||||
#define _APS_NEXT_CONTROL_VALUE 1003
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue