v0.91 sources and binaries from website

This commit is contained in:
Mark Aufflick 2011-10-18 14:51:02 +11:00
parent cf770f0a3d
commit f913d80b03
54 changed files with 4590 additions and 1833 deletions

View File

@ -1,4 +1,61 @@
Changes in KEGS v0.91 since v0.90 (12/06/04)
- Fixed serious bug in engine_c.c that could cause Finder file copies to
silently corrupt data.
- Virtual Modem support--modem appears on serial port, allows outgoing
and incoming connections.
- Sockets (and Virtual Modem) supported on Windows.
- Fixed various reset bugs (where pressing Ctrl-Reset would cause infinite
beeps, etc).
- Allow user to select ROM file from config panel if not found.
- Improved Mac OS X interface: Full Screen support and error dialogs.
- Better floppy support by always having 5.25" read nearest track regardless
of head position (supports Last Gladiator game bad crack by
emulating other emulators).
Changes in KEGS v0.90 since v0.89 (10/19/04)
- Make Keypad Joystick the default joystick emulation
- Fix timezone calculation on Mac OS X for central time zone.
- Fix handling of long paths in config panel, reported by David Scruffham.
- Always call joystick_init at startup.
- Fix F2 keymappings for X Windows, to fix some issue reported by
David Wilson.
- Fixed some documentation issues reported by David Wilson.
- Fixed a bug in joystick_driver.c reported by Doug Mitton.
- Add README.a2.compatibility to discuss known issues with programs.
Changes in KEGS v0.89 since v0.88 (10/17/04)
- Make old mouse button presses disappear after .5 seconds.
- Add Keypad Joystick, along with configuration menu choices to enable it.
The keypad numbers move the joystick to the indicated direction,
with chording allowing in-between values.
The keypad '0' is button 0 and keypad '1' is button 1.
- Also add jostick scaling factor and trim adjustment.
- Allow user to increase keyboard and mouse scan rate to 240Hz from 60Hz
for some better game response.
Changes in KEGS v0.88 since v0.87 (10/13/04)
- Add configuration setting to debug halt on code red halts. Also add
configuration mode (on by default) to shadow text page 2 on ROM 01,
which is an enhancement over a real IIgs.
- Handle mac binary header on images. Handle compressed .po images.
- Fix refresh rate to 59.923Hz from 60Hz so that exactly 17030 1MHz cycles
pass in one screen refresh period.
- Enhance trace-to-file function to also write out data values stored using
the Data_log info.
- Debugger adds memory move and memory compare functions.
- Support "floating bus" where reading certain $C0xx locations returns the
current video data. This allows Bob Bishop's split-screen demos to
run and enables Drol's between-level animations to work fully.
Changes in KEGS v0.87 since v0.86 (10/05/04)
- Remove all of Jonathan Kalbfeld's and Gilles Tschopp's contributions.
All of Solaris audio is removed.
- Fix config screen not drawing correctly if emulator was currently displaying
video page 2.
- Fix STP instruction.
- Fix mouse-joystick which was halving the Y dimension.
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

280
COPYING.txt Normal file
View File

@ -0,0 +1,280 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

View File

@ -4,8 +4,46 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>2mg</string>
<string>2MG</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>2mg.icns</string>
<key>CFBundleTypeName</key>
<string>Apple II 2MG Disk Image</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>a2mg</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>kegs</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>525.icns</string>
<key>CFBundleTypeName</key>
<string>KEGS Configuration File</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>kegs</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>KEGSMAC</string>
<key>CFBundleName</key>
<string>KEGSMAC</string>
<key>CFBundleIconFile</key>
<string>kegsicon.icns</string>
<key>CFBundleInfoDictionaryVersion</key>
@ -13,10 +51,14 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<string>KEGS</string>
<key>CFBundleVersion</key>
<string>0.1</string>
<key>CSResourcesFileMapped</key>
<true/>
<string>0.91</string>
<key>CFBundleShortVersionString</key>
<string>KEGSMAC version 0.91</string>
<key>CFBundleGetInfoString</key>
<string>KEGSMAC v0.91, Copyright 2004 Kent Dickey, http://kegs.sourceforge.net</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2004 Kent Dickey</string>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

Binary file not shown.

123
README.a2.compatibility.txt Normal file
View File

@ -0,0 +1,123 @@
# $Id: README.a2.compatibility,v 1.2 2004/10/18 18:17:21 kentd Exp $
Flobynoid: Must disable Fast Disk Emul (hit F7 to toggle it off) since
game's loader relies on the sector order on the disk (reads 8
sectors from the start without checking headers, assumes every other
physical sector is skipped due to decode delays).
Bard's Tale II GS: Doesn't recognize any save disk as a ProDOS disk.
It's detecting a "ProDOS" disk by checking for a string on block
0 at offset 0x15e. GSOS on system 6 has moved the string to 0x162,
so disks inited under GSOS will be detected as "Not a PRODOS disk".
Just make a copy of the Bard's Tale disk image to another file and
then mount that new image and remove all the files using the Finder.
Then rename the volume and you have a working save disk.
Robotron 2084:
Robot Battle:
These cracks use a "Fastloader" which is buggy.
It tries to JMP $F3D4 and expects to hit an RTS soon.
But on a IIgs it will access some illegal memory causing a code
yellow. You can just ignore the code yellow.
Beyond Castle Wolfenstein: Make sure your disk is writeable (not compressed!)
Breakout: Has trouble loading from the cracked copy.
From the BASIC prompt, do: "CALL -151" then "C083 N C083" then
"BLOAD INTBASIC" then run breakout. Then it runs fine.
Burgertime: This is a bad crack. Loader starts the game by writing
the game entry point into $0036/$0037, and then executing a BRK
instruction. The BRK handler on an old Apple II will try to write
out a message by calling through $0036/$0037, and this will start
the game. But on a IIgs, the ROM sets the $0036/$0037 vectors
back to the default, and so we crash into the monitor instead.
Here's a memory fix and a disk-image fix: From the crack screen,
press Shift-F6 (or middle mouse button) and in the KEGS debugger
window enter: "1d0a:ea 6c 36 0" and then "g". You can make
this fix to the disk image using a sector editor and change
Track $1E sector $09 offset $0A from "60 78 A9 03" to "EA 6C 36 00"
and write it back.
Caverns of Callisto: Requires old C600 ROM in slot 6 (Slot 6==Your Card).
Championship Loderunner: Requires disk to be writeable or else it starts
the level and then jumps immediately back to the title page.
Jeopardy: Disk must be writeable or else it displays "DISK ERROR" and
then crashes into the monitor.
Drol: Needs slot 6 set to "Your Card" from the IIgs control panel
(Ctrl-Cmd-ESC, then choose "Slots").
I found Drol hard, so here are some cheats. First, the standard cheat
for Drol is to have infinite lives, this cheat is to edit the disk
image:
Track $0B, Sector $0A, byte $22 to EA EA
Track $11, Sector $0A, byte $10 to EA EA
Track $17, Sector $09, byte $B2 to EA EA
I didn't create those cheats, I got it from textfiles.com.
My cheats are for the monsters to never kill you--just run right
through them.
While playing Drol, press Shift-F6 (or middle mouse button) to
enter the KEGS debugger, and then:
0/f28:18 18 # Monsters' missiles won't kill you
0/e05:90 0c # Monsters won't kill you
Continue emulation by type "g" and then enter.
Other things, like the bird, axes, swords still kill you.
To easily solve the third screen, move your man to the far right
side on the top level, so that you are directly above the woman
on the bottom row. Fly into the air "A" and then get to the KEGS
debugger, and type:
0/c:4
and then continue with "g". Now press "Z" and you will go all
the way down and land on the woman and end the level. It's
useful to have made the two above patches so that touching monsters
won't kill you.
Two more patches that only apply to level 3, and so most be made
in memory each time you enter level 3:
6cf3:18 18 18 # Axes won't kill you
6f70:38 38 # Swords/arrows won't kill you
The bird and the guy you can't kill will still kill you. These
cheats were enough to make the game easily playable.
In the game, your death is indicated by setting location $001E to
$FF. Setting breakpoints there can let you find other cheats.
Moon Patrol: Crashes into the monitor after completing checkpoint E.
To fix the Moon Patrol/Dung beetles version, from within KEGS:
BLOAD MOON PATROL
CALL -151
1E15:EA
919G
and it will work fine.
If you have the booting version that just has Moon Patrol on it,
then from any point after the crack screen is shown, enter the
KEGS debugger (Shift-F6 or middle moust button) and then enter:
0/1e15:ea
g
and then it will play fine.
The bug is that the code executes an instruction with opcode $02,
which is a NOP on 6502, but is a COP instruction to 65816. The
COP instruction acts like BRK and will crash. The patch just
makes it a real NOP.
Microbe: Crashes upon booting.
Code at $599E tries to pull a return address off of a location
beneath the stack pointer and jump to it, but it doesn't add 1
correctly so it jumps to $5917 when it meant to jump to $5918.
On a IIgs, this causes a BRK to be executed and the game to crash.
This can be patched in memory in two places:
0/599e:ba ca 9a 7d 00 01 48 98 7d 01 01 9d 01 01 60
0/6f1d:ba ca 9a 7d 00 01 48 98 7d 01 01 9d 01 01 60
The original byte sequence for both locations is:
00/599e: ba TSX
00/599f: 7d ff 00 ADC $00ff,X
00/59a2: 85 94 STA $94
00/59a4: 98 TYA
00/59a5: 7d 00 01 ADC $0100,X
00/59a8: 85 95 STA $95
00/59aa: 6c 94 00 JMP ($0094)
You can also patch the code onto the disk image. I found
the $599E version on Track $05, Sector $06, Byte $9E.
I found the $6F1D version on the image at Track $0C, Sector $00,
at byte $1D.

View File

@ -1,5 +1,4 @@
NOTE: The build process changed as of KEGS v0.70!
# $Id: README.compile,v 1.20 2004/10/18 04:05:14 kentd Exp $
General build instructions:
--------------------------
@ -39,8 +38,11 @@ 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.
The resulting executable is called "xkegs".
The build scripts assume 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,
@ -55,11 +57,12 @@ 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.
The build scripts assume 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
by runnning "xkegs -audio 1". It sounds horrible to me, but sounds do
come out.
Solaris SPARC build instructions:
@ -70,11 +73,12 @@ 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.
The build scripts assume 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".
by runnning "xkegs -audio 1".
Solaris x86 build instructions:
--------------------------------
@ -84,11 +88,12 @@ 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.
The build scripts assume 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".
by runnning "xkegs -audio 1".
HP-UX assembly-emulation instructions:
-------------------------------------
@ -100,14 +105,14 @@ 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".
This version is quite out of date and most likely does not compile any more.
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.
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.

View File

@ -1,18 +1,19 @@
KEGS: Kent's Emulated GS version 0.86
KEGS: Kent's Emulated GS version 0.91
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.
The Apple IIgs was the most powerful computer in the Apple II line.
It first was sold in 1986. An Apple IIgs has the capability to run almost all
Apple II, Apple IIe, and Apple IIc programs.
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.
serial port emulation through TCP/IP connections, 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
@ -20,49 +21,53 @@ 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.
I'd like to thank Chea Chee Keong who created KEGS32, the first Windows
port of KEGS. That version, which has a better Windows-interface but which
is based on older core code, is at http://www.geocities.com/akilgard/kegs2.
KEGS features:
-------------
Fast 65816 emulation:
About 80MHz on a P4 1.7GHz or a G4 1GHz.
About 80MHz on a Pentium 4 1.7GHz or a Mac 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.
Emulates all Apple IIgs and Apple II graphics modes, including border effects.
Can handle display changes at any time (superhires at the top, lores
at the bottom). Always does 60 full screen video updates per second.
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.
Limited SCC (serial port) emulation to enable PR#1/2 IN#1/2 and Virtual
Modem enables standard Apple terminal programs to telnet to any
internet address (or receive connections from another telnet).
KEGS by default emulates a 8MB Apple IIgs, but you can change this with
the "-mem" command line option.
KEGS by default emulates a 8MB Apple IIgs, but you can change this from
the Configuration Panel.
KEGS is so accurate, even the built-in ROM selftests pass (you must be in
2.8MHz speed mode to pass the self-tests).
2.8MHz speed mode to pass the self-tests and you must set the Configuration
Panel entry "Enable Text Page 2 shadow" to "Disabled on ROM 01" for ROM 01).
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
README.kegs.txt - you're here
README.compile.txt - Describes how to build KEGS
README.linux.rpm.txt - Describes how to install KEGS's RPM for Linux
README.win32.txt - Win32 special directions
README.mac.txt - Mac OS X special directions
README.a2.compatibility.txt - List of programs which need tweaking
src/INTERNALS.overview - description of how KEGS code works
src/INTERNALS.xdriver - Describes the xdriver.c routines for porting
src/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
KEGSMAC - the Mac OS X executable
kegswin.exe - the Windows executable
config.kegs - disk image configuration info
to_pro - Hard-to-use ProDOS volume creator
partls - Lists partitions on Apple-partitioned hard
drives or CD-ROMs
@ -71,9 +76,10 @@ Included files:
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.)
2) a ROM file called "ROM", "ROM.01" or "ROM.03" in the KEGS directory
(or in your home 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.
@ -87,10 +93,11 @@ or fc/0000 - ff/ffff from a ROM 03 GS, and put that in a file called
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.
The distribution comes with the full source code for all platforms in
the src/ directory, the Windows executable as kegswin.exe, and the Mac OS X
executable as KEGSMAC.
See the README.compile file for more info about compiling for Linux.
See the README.compile.txt 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
@ -98,50 +105,68 @@ 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).
with the Finder (or using the Terminal). You can also make the directory
Library/KEGS from your home directory, and then place config.kegs there
along with the ROM file. You do not need a starting config.kegs file
on a Mac--KEGS will offer to make it for you if it cannot find one.
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".
be run by the Terminal window on a Mac 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:
Configuration Panel:
-------------------
You enter the Configuration panel by pressing F4 at any time. You tell
KEGS what disk images to use through the Configuration panel. (If KEGS
couldn't find a ROM file, you will be forced into the Configuration
Panel mode until you select a valid ROM file).
To select a ROM file, select "ROM File Selection" and then select your
ROM file. If you were not forced into the panel at startup, the KEGS
found one and you can skip this step.
Disk Images
-----------
You tell KEGS what disk images to use through the Configuration panel.
The primary use of the Configuration Panel is to select disk images. To
change disk images being used, 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 images should be less than
32MB).
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.
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 locate your image files. To quickly
jump to a particular path, you can press Tab to toggle between entering
a path manually, and using the file 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.
only have partitions on direct devices you mount (or on a Mac, of .dmg
images of CDs). For instance, on a Mac, /dev/disk1 can sometimes be the
CDROM drive.
KEGS can handle "raw", .dsk, .po, 2IMG, 5.25" ".nib" images, some Mac
KEGS can handle "raw", .dsk, .po, 2IMG, 5.25" ".nib" images, most 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.
KEGS can open any image file compressed with gzip (with the extension ".gz")
automatically as a read-only disk 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
800K bytes long (819200 bytes). KEGS directs 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.
@ -150,21 +175,36 @@ 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.
host machine, you can use them by selecting them from the Configuration Panel.
You can also get Apple II programs in ".dsk" format from a variety of
sites on the internet, and these should all work on KEGS as well.
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).
you have a Unix-based 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.
GSOS has many HFS bugs when it is writing. Also avoid having KEGS access
an image which have mounted on your Mac at the same time (always unmount
it from your Mac before letting KEGS access it)!
If you do not have any disk mounted in s7d1, KEGS will jump into BASIC.
If you do not have any disk mounted in s7d1, KEGS will jump into the monitor.
To boot slot 6 (or slot 5), use the Apple IIgs Control Panel by pressing
Ctrl-Command-ESC.
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.
format is kinda simplistic, it's tricky for KEGS to write to it since KEGS
has more information than fits in that format). Just select your image,
like "disk.nib" in the kegs_conf file like any .dsk or .po image.
In addition to changing disks, you can also just "eject" and image by
moving the cursor to select that slot/drive and then press "E". The
emulated IIgs will immediately detect changes to s5d1 and s5d2.
Care should be taken when changing images in slot 7--KEGS does not notify
GSOS that images have changed (or been ejected), and so it's best to make
changes when GSOS is not running.
Key summary:
@ -180,8 +220,8 @@ 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).
F10: Attempt to change the a2vid_palette (only useful on 256-color displays)
F11: Full screen mode (only on Mac OS X).
F12: Alias of Pause/Break which is treated as Reset
F2, Alt_R, Meta_r, Menu, Print, Mode_switch, Option: Option key
@ -202,35 +242,15 @@ 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.
the debug window, and the occasional error dialogs on Mac OS X). Input to
the debug window is only acted upon when the emulation is stopped
(Shift-F6, middle mouse button, or hitting a breakpoint).
Quitting KEGS:
-------------
@ -240,6 +260,86 @@ 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.
Command/Option keys:
-------------------
If you have a keyboard with the special Windows keys, you can
use them as the command/option keys. For those without those keys,
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 (especially useful if your OS is intercepting some
Alt or Command key sequences).
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 or F6 (and also set Enable Text Page 2 shadow = Disabled for ROM 01).
Watch out for ctrl-shift-Break--it will likely kill an X Windows session.
Also note that the Unix olvwm X window manager interprets ctrl-F12 and will
not pass it on to KEGS--you'll need to use Break for reset in that case.
Full Screen mode (MAC OS X ONLY):
----------------
KEGS can run in full screen mode--which is especially useful when letting
small kids use KEGS (but it is not really a lock, so do not let a 2 year
old bang on the keyboard while running KEGS).
Full Screen mode is toggled with F11 (or Ctrl-F11, since Expose on a Mac
is intercepting F11). If KEGS stops in the debugger for any reason,
full screen mode is toggled off automatically.
Joystick Emulation (Mouse, Keypad, or real native joystick):
------------------
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.
You can also select from a "Keypad Joystick" or a real joystick from
the Configuration panel. Press return on the "Joystick Configuration"
entry, and then select between Mouse Joystick, Keypad Joystick, or one
of two native joysticks. The Keypad Joystick uses your keypad number
keys as a joystick, where keypad 7 means move to the upper left, and
keypad 3 means move to the lower right. Pressing multiple keys together
averages the results, allowing finer control than just 8 directions.
Also, joystick scaling is selectable here for games which require
a greater range of motion to work correctly, along with trim adjustment
which moves the centering point. Adjusting scaling usually means you
will need to adjust the trim as well.
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 will not
operate correctly. Try running ornery programs at 2.8MHz. 3200 pictures
generally only display correctly at 2.8MHz or sometimes 8.0MHz.
Debugging KEGS:
--------------
@ -272,6 +372,10 @@ type:
e1/0010B
The format is "bank/address" then "B", where the B must be in caps and
the address must use lower-case hex. For Apple IIe programs, just use a
bank of 0.
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
@ -296,27 +400,17 @@ watchpoints).
Frederic Devernay has written a nice help screen available in the
debugger when you type "h".
Useful locations for setting breakpoints:
0/3f0B - Break handler
0/c000B - Keyboard latch, programs read keys from this address
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.
There are others, but the Configuration panel provides a better way to
set them so they are no longer listed here.
-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.
@ -340,7 +434,6 @@ X-Windows/Linux options
-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
@ -348,40 +441,9 @@ X-Windows/Linux options
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:
-------------
Apple IIgs Control Panel:
------------------------
You can get to the Apple IIgs control panel (unless some application
has locked it out) using Ctrl-Command-ESC.
@ -453,18 +515,12 @@ 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.
The file "config.kegs" describes the images KEGS will use. Although you
can edit the file manually, in general you can use the Configuration Panel
to make all the changes you need. This information is for reference.
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 will boot s7d1 (unless you've changed that using the
Apple IIgs control panel), so you should put an image in that slot.
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
@ -544,14 +600,14 @@ 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
Sound output has an important 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
In all cases, 1MHz to KEGS is 1.024MHz. And 2.8MHz to KEGS is 2.56MHz
(trying to approximate the slowdown causes by memory refresh on a real
Apple IIgs). It's just easier to say 1MHz and 2.8MHz.
@ -673,7 +729,9 @@ useful for some games.
KEGS: What works:
-----------------
Basically, just about every Apple II program works.
Basically, just about every Apple II program works. See the file
README.a2.compatibility for directions on how to make certain games/programs
work.
KEGS is EXTREMELY compatible. But, I haven't tested everything. Let
me know if you find a program which is not working correctly.
@ -696,9 +754,6 @@ 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
@ -726,39 +781,70 @@ in the debug window. However, when sound restarts, it sometimes
If your display is not using shared memory, audio defaults to off unless
you override it with "-audio 1".
SCC emulation:
-------------
SCC (Serial Port) 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".
By default, slot 1 is emulated using a simple receive socket, and slot 2
emulates a Virtual Modem.
A Virtual Modem means KEGS acts as if a modem is on the serial port
allowing Apple II communcation programs to fully work, but connected to
internet-enabled sockets. KEGS emulates a "Hayes- Compatible" modem,
meaning it accepts "AT" commands. You can use KEGS to connect to free
telnet-BBSs, or run a BBS program on KEGS and become a telnet BBS yourself.
The two main AT commands are: ATDT for dialing out, and ATA for receiving
calls. To dial out, enter "ATDThostname", or for example,
"ATDTboycot.no-ip.com" (which is down at the moment, unfortunately).
You can also enter an IP address, like "ATDT127.0.0.1". On a Mac, to
create a telnet server to allow telnet connections (do not use over the
internet, but on a private network behind a firewall, this should be
fine), in a Terminal window type: "sudo /usr/libexec/telnetd -debug".
You must then enable telnet on port 23 through your Mac OS X Firewall in
the System Preferences->Sharing->Firewall page (just add port 23 as
open--you'll need to use the "New..." button and then select Other for
Port Name, and enter Port Number as 23). Then from KEGS in a
communications program, do "ATDT127.0.0.1", and then log-in to your Mac.
KEGS also accepts incoming "calls". Start KEGS, and initialize the
Virtual Modem with some AT command (ATZ resets all state, and is a useful
start). KEGS now has a socket port open, 6502 for slot 2, which you
can connect to using any telnet program. In a Terminal window, then
type "telnet 127.0.0.1 6502" and you will connect to KEGS. The Virtual
Modem then starts printing "RING" every 2 seconds until you answer with
"ATA". You are now connected. I have not tried BBS programs, but have
made connections with ProTERM.
On Windows XP SP2, when KEGS tries to open this incoming socket, you'll
need to enable it and click Unblock to the dialog that Windows pops up.
If you do not want incoming connections, you can block it instead.
Once connected, you can go back to talking to the Virtual Modem by
pressing + three times quickly (+++), and then not type anything for a second.
This goes back to the AT-command mode. You can now "ATH" to hang up, or
"ATO" to go back online.
On Windows, the socket code is very preliminary and there are problems
receiving connections.
KEGS also supports an older, simpler socket interface, which it defaults
to using on slot 1. 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 telnet. In another terminal 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.
to the emulated IIgs. You may want to go to the F4 Config Panel and set
"mask off high bit" for serial port accesses to make PR#1 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
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:
----------------
@ -875,7 +961,7 @@ 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.
the picture of a keg for the Mac icon.
Kent Dickey
kadickey@alumni.princeton.edu
@ -956,21 +1042,9 @@ 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).
lets you set through s7d11. ProDOS 8 can access disks up to s7d8, but GSOS
has no limit, so it's best to put HFS images past s7d8 in order to leave
more slots for ProDOS images.
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
@ -982,8 +1056,6 @@ 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.
DO NOT RUN KEGS AS ROOT. It is not designed for this and it's almost certain
problems will ensue.

9
README.md Normal file
View File

@ -0,0 +1,9 @@
KEGS - Kent's Emulated GS
=========================
Kegs is an Apple //gs emulator for Mac OS X, Win32, Linux and Unix/X11
The latest version on the main KEGS home page is v0.91 which doesn't work on Intel Macs. In fact, only
small build changes are required, so I have forked the code to Github with my changes.
Original homepage with useful info on how to get it running is here: (http://kegs.sourceforge.net/)[http://kegs.sourceforge.net/]

View File

@ -2,13 +2,13 @@
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.
There is a different port of KEGS by Chea Chee Keong (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). I am grateful for Chea for doing the windows port since I
did not know any Windows programming.
This port is alpha quality. Seriously. Don't expect much.
This port is alpha quality. 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
@ -49,3 +49,4 @@ In order to compile,
You can contact me at kadickey@alumni.princeton.edu

Binary file not shown.

BIN
src/2mg.icns Normal file

Binary file not shown.

BIN
src/525.icns Normal file

Binary file not shown.

View File

@ -4,8 +4,46 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>2mg</string>
<string>2MG</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>2mg.icns</string>
<key>CFBundleTypeName</key>
<string>Apple II 2MG Disk Image</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>a2mg</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>kegs</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>525.icns</string>
<key>CFBundleTypeName</key>
<string>KEGS Configuration File</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>kegs</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>KEGSMAC</string>
<key>CFBundleName</key>
<string>KEGSMAC</string>
<key>CFBundleIconFile</key>
<string>kegsicon.icns</string>
<key>CFBundleInfoDictionaryVersion</key>
@ -13,10 +51,14 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<string>KEGS</string>
<key>CFBundleVersion</key>
<string>0.1</string>
<key>CSResourcesFileMapped</key>
<true/>
<string>0.91</string>
<key>CFBundleShortVersionString</key>
<string>KEGSMAC version 0.91</string>
<key>CFBundleGetInfoString</key>
<string>KEGSMAC v0.91, Copyright 2004 Kent Dickey, http://kegs.sourceforge.net</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2004 Kent Dickey</string>
</dict>
</plist>

Binary file not shown.

View File

@ -1,4 +1,4 @@
# $Id: release_makefile_base,v 1.15 2003/11/21 20:00:42 kentd Exp $
# $Id: release_makefile_base,v 1.15 2003/11/21 20:00:42 kentd Exp kentd $
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 \
@ -24,17 +24,18 @@ specials_clean:
# Mac builds:
kegsmac: $(OBJECTS) compile_time.o
$(CC) $(CCOPTS) $(LDOPTS) -arch ppc $(OBJECTS) compile_time.o $(LDFLAGS) -o kegsmac $(EXTRA_LIBS) -prebind -framework Carbon
$(CC) $(CCOPTS) $(LDOPTS) -arch ppc $(OBJECTS) compile_time.o $(LDFLAGS) -o kegsmac $(EXTRA_LIBS) -prebind -framework Carbon -framework Quicktime
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/
cp -f 525.icns ../KEGSMAC.app/Contents/Resources/
cp -f 2mg.icns ../KEGSMAC.app/Contents/Resources/
touch '../KEGSMAC.app/Icon?'
# Linux for X builds:
@ -49,7 +50,7 @@ kegs.exe: $(OBJECTS) compile_time.o
# 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
$(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(EXTRA_LIBS) -lwinmm -lgdi32 -ldsound -lcomctl32 -lws2_32
mv $(NAME)$(SUFFIX) ..

259
src/adb.c
View File

@ -8,12 +8,14 @@
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_adb_c[] = "@(#)$KmKId: adb.c,v 1.63 2004-03-23 18:46:25-05 kentd Exp $";
const char rcsid_adb_c[] = "@(#)$KmKId: adb.c,v 1.73 2004-11-14 14:05:33-05 kentd Exp $";
/* adb_mode bit 3 and bit 2 (faster repeats for arrows and space/del) not done*/
#include "adb.h"
int g_fullscreen = 0;
extern int Verbose;
extern word32 g_vbl_count;
extern int g_num_lines_prev_superhires640;
@ -21,11 +23,14 @@ extern int g_num_lines_prev_superhires;
extern int g_rom_version;
extern int g_fast_disk_emul;
extern int g_limit_speed;
extern int g_irq_pending;
extern int g_swap_paddles;
extern int g_invert_paddles;
extern int g_joystick_type;
extern int g_a2vid_palette;
extern int g_config_control_panel;
extern word32 g_cfg_vbl_count;
extern double g_cur_dcycs;
extern byte *g_slow_memory_ptr;
extern byte *g_memory_ptr;
@ -84,17 +89,23 @@ int g_warp_pointer = 0;
int g_hide_pointer = 0;
int g_unhide_pointer = 0;
int g_mouse_a2_x = 0;
int g_mouse_a2_y = 0;
int g_mouse_a2_button = 0;
int g_mouse_fifo_pos = 0;
int g_mouse_raw_x = 0;
int g_mouse_raw_y = 0;
#define ADB_MOUSE_FIFO 8
int g_mouse_fifo_x[ADB_MOUSE_FIFO] = { 0 };
int g_mouse_fifo_y[ADB_MOUSE_FIFO] = { 0 };
int g_mouse_fifo_buttons[ADB_MOUSE_FIFO] = { 0 };
STRUCT(Mouse_fifo) {
double dcycs;
int x;
int y;
int buttons;
};
Mouse_fifo g_mouse_fifo[ADB_MOUSE_FIFO] = { { 0, 0, 0, 0 } };
int g_mouse_warp_x = 0;
int g_mouse_warp_y = 0;
@ -102,11 +113,6 @@ int g_mouse_warp_y = 0;
int g_adb_mouse_valid_data = 0;
int g_adb_mouse_coord = 0;
int g_adb_data_int_sent = 0;
int g_adb_mouse_int_sent = 0;
int g_adb_kbd_srq_sent = 0;
#define MAX_KBD_BUF 8
int g_key_down = 0;
@ -129,6 +135,10 @@ int g_mouse_ctl_addr = 3; /* ADB ucontroller's mouse addr*/
word32 g_virtual_key_up[4]; /* bitmask of all possible 128 a2codes */
/* indicates which keys are up=1 by bit */
int g_keypad_key_is_down[10] = { 0 };/* List from 0-9 of which keypad */
/* keys are currently pressed */
#define SHIFT_DOWN ( (g_c025_val & 0x01) )
#define CTRL_DOWN ( (g_c025_val & 0x02) )
#define CAPS_LOCK_DOWN ( (g_c025_val & 0x04) )
@ -171,6 +181,10 @@ adb_init()
g_virtual_key_up[i] = -1;
}
for(i = 0; i < 10; i++) {
g_keypad_key_is_down[i] = 0;
}
adb_reset();
}
@ -189,9 +203,9 @@ adb_reset()
g_kbd_ctl_addr = 2;
g_mouse_ctl_addr = 3;
g_adb_data_int_sent = 0;
g_adb_mouse_int_sent = 0;
g_adb_kbd_srq_sent = 0;
adb_clear_data_int();
adb_clear_mouse_int();
adb_clear_kbd_srq();
g_adb_data_pending = 0;
g_adb_interrupt_byte = 0;
@ -201,6 +215,7 @@ adb_reset()
g_kbd_reg0_pos = 0;
g_kbd_reg3_16bit = 0x602;
}
@ -250,8 +265,6 @@ show_adb_log(void)
printf("kbd: dev: %x, ctl: %x; mouse: dev: %x, ctl: %x\n",
g_kbd_dev_addr, g_kbd_ctl_addr,
g_mouse_dev_addr, g_mouse_ctl_addr);
printf("adb_data_int_sent: %d, adb_kbd_srq_sent: %d, mouse_int: %d\n",
g_adb_data_int_sent, g_adb_kbd_srq_sent, g_adb_mouse_int_sent);
printf("g_adb_state: %d, g_adb_interrupt_byte: %02x\n",
g_adb_state, g_adb_interrupt_byte);
}
@ -271,11 +284,8 @@ adb_add_kbd_srq()
{
if(g_kbd_reg3_16bit & 0x200) {
/* generate SRQ */
g_adb_interrupt_byte |= 0x08;;
if(!g_adb_kbd_srq_sent) {
g_adb_kbd_srq_sent = 1;
add_irq();
}
g_adb_interrupt_byte |= 0x08;
add_irq(IRQ_PENDING_ADB_KBD_SRQ);
} else {
printf("Got keycode but no kbd SRQ!\n");
}
@ -284,10 +294,7 @@ adb_add_kbd_srq()
void
adb_clear_kbd_srq()
{
if(g_adb_kbd_srq_sent) {
remove_irq();
g_adb_kbd_srq_sent = 0;
}
remove_irq(IRQ_PENDING_ADB_KBD_SRQ);
/* kbd SRQ's are the only ones to handle now, so just clean it out */
g_adb_interrupt_byte &= (~(0x08));
@ -297,10 +304,7 @@ void
adb_add_data_int()
{
if(g_c027_val & ADB_C027_DATA_INT) {
if(!g_adb_data_int_sent) {
g_adb_data_int_sent = 1;
add_irq();
}
add_irq(IRQ_PENDING_ADB_DATA);
}
}
@ -308,31 +312,20 @@ void
adb_add_mouse_int()
{
if(g_c027_val & ADB_C027_MOUSE_INT) {
if(!g_adb_mouse_int_sent) {
/* printf("Mouse int sent\n"); */
g_adb_mouse_int_sent = 1;
add_irq();
}
add_irq(IRQ_PENDING_ADB_MOUSE);
}
}
void
adb_clear_data_int()
{
if(g_adb_data_int_sent) {
remove_irq();
g_adb_data_int_sent = 0;
}
remove_irq(IRQ_PENDING_ADB_DATA);
}
void
adb_clear_mouse_int()
{
if(g_adb_mouse_int_sent) {
remove_irq();
g_adb_mouse_int_sent = 0;
/* printf("Mouse int clear, button: %d\n", g_mouse_a2_button);*/
}
remove_irq(IRQ_PENDING_ADB_MOUSE);
}
@ -580,7 +573,7 @@ adb_read_c026()
case ADB_IDLE:
ret = g_adb_interrupt_byte;
g_adb_interrupt_byte = 0;
if(g_adb_kbd_srq_sent) {
if(g_irq_pending & IRQ_PENDING_ADB_KBD_SRQ) {
g_adb_interrupt_byte |= 0x08;
}
if(g_adb_data_pending == 0) {
@ -1087,15 +1080,57 @@ write_adb_ram(word32 addr, int val)
}
}
int
adb_get_keypad_xy(int get_y)
{
int x, y;
int key;
int num_keys;
int i, j;
key = 1;
num_keys = 0;
x = 0;
y = 0;
for(i = 0; i < 3; i++) {
for(j = 0; j < 3; j++) {
if(g_keypad_key_is_down[key]) {
num_keys++;
x = x + (j - 1)*32768;
y = y + (1 - i)*32768;
}
key++;
}
}
if(num_keys == 0) {
num_keys = 1;
}
adb_printf("get_xy=%d, num_keys: %d, x:%d, y:%d\n", get_y,
num_keys, x, y);
if(get_y) {
return y / num_keys;
} else {
return x / num_keys;
}
}
int
update_mouse(int x, int y, int button_states, int buttons_valid)
{
double dcycs;
int button1_changed;
int mouse_moved;
int unhide;
int pos;
int i;
dcycs = g_cur_dcycs;
g_mouse_raw_x = x;
g_mouse_raw_y = y;
unhide = 0;
if(x < 0) {
x = 0;
@ -1132,47 +1167,50 @@ update_mouse(int x, int y, int button_states, int buttons_valid)
y = y >> 1;
}
mouse_compress_fifo(dcycs);
#if 0
printf("Update Mouse called with buttons:%d x,y:%d,%d, fifo:%d,%d, "
" a2: %d,%d\n", buttons_valid, x, y,
g_mouse_fifo_x[0], g_mouse_fifo_y[0],
g_mouse_fifo[0].x, g_mouse_fifo[0].y,
g_mouse_a2_x, g_mouse_a2_y);
#endif
if((buttons_valid < 0) && g_warp_pointer) {
/* Warping the pointer causes it to jump here...this is not */
/* real motion, just update info and get out */
g_mouse_a2_x += (x - g_mouse_fifo_x[0]);
g_mouse_a2_y += (y - g_mouse_fifo_y[0]);
g_mouse_fifo_x[0] = x;
g_mouse_fifo_y[0] = y;
g_mouse_a2_x += (x - g_mouse_fifo[0].x);
g_mouse_a2_y += (y - g_mouse_fifo[0].y);
g_mouse_fifo[0].x = x;
g_mouse_fifo[0].y = y;
return 0;
}
#if 0
printf("...real move, warp: %d, %d, new x: %d, %d, a2:%d,%d\n",
g_mouse_warp_x, g_mouse_warp_y, g_mouse_fifo_x[0],
g_mouse_fifo_y[0], g_mouse_a2_x, g_mouse_a2_y);
g_mouse_warp_x, g_mouse_warp_y, g_mouse_fifo[0].x,
g_mouse_fifo[0].y, g_mouse_a2_x, g_mouse_a2_y);
#endif
mouse_moved = (g_mouse_fifo_x[0] != x) || (g_mouse_fifo_y[0] != y);
mouse_moved = (g_mouse_fifo[0].x != x) || (g_mouse_fifo[0].y != y);
g_mouse_a2_x += g_mouse_warp_x;
g_mouse_a2_y += g_mouse_warp_y;
g_mouse_fifo_x[0] = x;
g_mouse_fifo_y[0] = y;
g_mouse_fifo[0].x = x;
g_mouse_fifo[0].y = y;
g_mouse_fifo[0].dcycs = dcycs;
g_mouse_warp_x = 0;
g_mouse_warp_y = 0;
button1_changed = (buttons_valid & 1) &&
((button_states & 1) != (g_mouse_fifo_buttons[0] & 1));
((button_states & 1) != (g_mouse_fifo[0].buttons & 1));
if((button_states & 4) && !(g_mouse_fifo_buttons[0] & 4) &&
if((button_states & 4) && !(g_mouse_fifo[0].buttons & 4) &&
(buttons_valid & 4)) {
/* right button pressed */
adb_increment_speed();
}
if((button_states & 2) && !(g_mouse_fifo_buttons[0] & 2) &&
if((button_states & 2) && !(g_mouse_fifo[0].buttons & 2) &&
(buttons_valid & 2)) {
/* middle button pressed */
halt2_printf("Middle button pressed\n");
@ -1185,15 +1223,13 @@ update_mouse(int x, int y, int button_states, int buttons_valid)
/* button up/down times. Using a mouse event list where */
/* deltas accumulate until a button change would work, too */
for(i = pos; i >= 0; i--) {
g_mouse_fifo_x[i + 1] = g_mouse_fifo_x[i];
g_mouse_fifo_y[i + 1] = g_mouse_fifo_y[i];
g_mouse_fifo_buttons[i + 1] = g_mouse_fifo_buttons[i]&1;
g_mouse_fifo[i + 1] = g_mouse_fifo[i]; /* copy struct*/
}
g_mouse_fifo_pos = pos + 1;
}
g_mouse_fifo_buttons[0] = (button_states & buttons_valid) |
(g_mouse_fifo_buttons[0] & ~buttons_valid);
g_mouse_fifo[0].buttons = (button_states & buttons_valid) |
(g_mouse_fifo[0].buttons & ~buttons_valid);
if(mouse_moved || button1_changed) {
if( (g_mouse_ctl_addr == g_mouse_dev_addr) &&
@ -1226,10 +1262,12 @@ mouse_read_c024(double dcycs)
return 0;
}
mouse_compress_fifo(dcycs);
pos = g_mouse_fifo_pos;
target_x = g_mouse_fifo_x[pos];
target_y = g_mouse_fifo_y[pos];
mouse_button = (g_mouse_fifo_buttons[pos] & 1);
target_x = g_mouse_fifo[pos].x;
target_y = g_mouse_fifo[pos].y;
mouse_button = (g_mouse_fifo[pos].buttons & 1);
delta_x = target_x - g_mouse_a2_x;
delta_y = target_y - g_mouse_a2_y;
@ -1253,7 +1291,7 @@ mouse_read_c024(double dcycs)
/* peek into next entry's button info if we are not clamped */
/* and we're returning the y-coord */
if(!clamped && g_adb_mouse_coord) {
mouse_button = g_mouse_fifo_buttons[pos - 1] & 1;
mouse_button = g_mouse_fifo[pos - 1].buttons & 1;
}
}
@ -1351,9 +1389,9 @@ mouse_read_c024(double dcycs)
g_slow_memory_ptr[0x10190], g_slow_memory_ptr[0x10192],
g_slow_memory_ptr[0x10191], g_slow_memory_ptr[0x10193]);
if((g_mouse_fifo_pos == 0) && (g_mouse_fifo_x[0] == a2_x) &&
(g_mouse_fifo_y[0] == a2_y) &&
((g_mouse_fifo_buttons[0] & 1) == g_mouse_a2_button)) {
if((g_mouse_fifo_pos == 0) && (g_mouse_fifo[0].x == a2_x) &&
(g_mouse_fifo[0].y == a2_y) &&
((g_mouse_fifo[0].buttons & 1) == g_mouse_a2_button)) {
g_adb_mouse_valid_data = 0;
adb_clear_mouse_int();
}
@ -1362,6 +1400,29 @@ mouse_read_c024(double dcycs)
return ret;
}
void
mouse_compress_fifo(double dcycs)
{
int pos;
/* The mouse fifo exists so that fast button changes don't get lost */
/* if the emulator lags behind the mouse events */
/* But the FIFO means really old mouse events are saved if */
/* the emulated code isn't looking at the mouse registers */
/* This routine compresses all mouse events > 0.5 seconds old */
for(pos = g_mouse_fifo_pos; pos >= 1; pos--) {
if(g_mouse_fifo[pos].dcycs < (dcycs - 500*1000.0)) {
/* Remove this entry */
adb_printf("Old mouse FIFO pos %d removed\n", pos);
g_mouse_fifo_pos = pos - 1;
continue;
}
/* Else, stop searching the FIFO */
break;
}
}
void
adb_key_event(int a2code, int is_up)
{
@ -1489,7 +1550,8 @@ adb_read_c000()
/* got one */
if((g_kbd_read_no_update++ > 5) && (g_kbd_chars_buffered > 1)) {
/* read 5 times, keys pending, let's move it along */
printf("Read %02x 3 times, tossing\n", g_kbd_buf[0]);
printf("Read %02x %d times, tossing\n", g_kbd_buf[0],
g_kbd_read_no_update);
adb_access_c010();
}
} else {
@ -1583,7 +1645,8 @@ adb_physical_key_update(int a2code, int is_up)
{
int autopoll;
int special;
int tmp;
int ascii_and_type;
int ascii;
/* this routine called by xdriver to pass raw codes--handle */
/* ucontroller and ADB bus protocol issues here */
@ -1599,17 +1662,17 @@ adb_physical_key_update(int a2code, int is_up)
return;
}
/* Remap 0x7b-0x7e to 0x3b-0x3e (arrow keys on new mac keyboards */
/* Remap 0x7b-0x7e to 0x3b-0x3e (arrow keys on new mac keyboards) */
if(a2code >= 0x7b && a2code <= 0x7e) {
a2code = a2code - 0x40;
}
/* Now check for special keys (function keys, etc) */
tmp = a2_key_to_ascii[a2code][1];
ascii_and_type = a2_key_to_ascii[a2code][1];
special = 0;
if((tmp & 0xf000) == 0x8000) {
if((ascii_and_type & 0xf000) == 0x8000) {
/* special function key */
special = tmp & 0xff;
special = ascii_and_type & 0xff;
switch(special) {
case 0x01: /* F1 - remap to cmd */
a2code = 0x37;
@ -1643,7 +1706,7 @@ adb_physical_key_update(int a2code, int is_up)
if(special && !is_up) {
switch(special) {
case 0x04: /* F4 - Emulator config panel */
g_config_control_panel = !g_config_control_panel;
cfg_toggle_config_panel();
break;
case 0x06: /* F6 - emulator speed */
if(SHIFT_DOWN) {
@ -1679,13 +1742,38 @@ adb_physical_key_update(int a2code, int is_up)
change_a2vid_palette((g_a2vid_palette + 1) & 0xf);
break;
case 0x0b: /* F11 - full screen */
/* g_fullscreen = !g_fullscreen; */
/* x_full_screen(g_full_screen); */
g_fullscreen = !g_fullscreen;
x_full_screen(g_fullscreen);
break;
}
return;
}
/* Handle Keypad Joystick here partly...if keypad key pressed */
/* while in Keypad Joystick mode, do not pass it on as a key press */
if((ascii_and_type & 0xff00) == 0x1000) {
/* Keep track of keypad number keys being up or down even */
/* if joystick mode isn't keypad. This avoid funny cases */
/* if joystick mode is changed while a key is pressed */
ascii = ascii_and_type & 0xff;
if(ascii > 0x30 && ascii <= 0x39) {
g_keypad_key_is_down[ascii - 0x30] = !is_up;
}
if(g_joystick_type == 0) {
/* If Joystick type is keypad, then do not let these */
/* keypress pass on further, except for cmd/opt */
if(ascii == 0x30) {
/* remap '0' to cmd */
a2code = 0x37;
} else if(ascii == 0x2e || ascii == 0x2c) {
/* remap '.' and ',' to option */
a2code = 0x3a;
} else {
/* Just ignore it in this mode */
return;
}
}
}
autopoll = 1;
if(g_adb_mode & 1) {
@ -1753,6 +1841,23 @@ adb_virtual_key_update(int a2code, int is_up)
}
}
void
adb_all_keys_up()
{
word32 mask;
int i, j;
for(i = 0; i < 4; i++) {
for(j = 0; j < 32; j++) {
mask = 1 << j;
if((g_virtual_key_up[i] & mask) == 0) {
/* create key-up event */
adb_physical_key_update(i*32 + j, 1);
}
}
}
}
void
adb_kbd_repeat_off()
{

View File

@ -8,7 +8,7 @@
/* 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 $";
const char rcsid_adb_h[] = "@(#)$KmKId: adb.h,v 1.11 2004-10-13 23:30:33-04 kentd Exp $";
#include "defc.h"
@ -87,7 +87,7 @@ const int a2_key_to_ascii[][4] = {
{ 0x3f, -1, -1, -1 },
{ 0x40, -1, -1, -1 },
{ 0x41, 0x102e, 0x102e, -1 }, /* keypad . */
{ 0x41, 0x102e, 0x102c, -1 }, /* keypad . */
{ 0x42, -1, -1, -1 },
{ 0x43, 0x102a, 0x102a, -1 }, /* keypad * */
{ 0x44, -1, -1, -1 },
@ -115,7 +115,7 @@ const int a2_key_to_ascii[][4] = {
{ 0x58, 0x1036, 0x1036, -1 }, /* keypad 6 */
{ 0x59, 0x1037, 0x1037, -1 }, /* keypad 7 */
{ 0x5a, -1, -1, -1 },
{ 0x5a, 'a', 'A', 0x01 }, /* probably not necessary */
{ 0x5b, 0x1038, 0x1038, -1 }, /* keypad 8 */
{ 0x5c, 0x1039, 0x1039, -1 }, /* keypad 9 */
{ 0x5d, -1, -1, -1 },
@ -137,7 +137,7 @@ const int a2_key_to_ascii[][4] = {
{ 0x6b, 0x800e, 0x106b, -1 }, /* F14 */
{ 0x6c, -1, -1, -1 },
{ 0x6d, 0x800a, 0x106d, -1 }, /* F10 */
{ 0x6e, -1, -1, -1 },
{ 0x6e, 0x4000, 0x4000, -1 }, /* windows key alias to option */
{ 0x6f, 0x800c, 0x106f, -1 }, /* F12 */
{ 0x70, -1, -1, -1 },

View File

@ -8,7 +8,7 @@
/* 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 $";
const char rcsid_clock_c[] = "@(#)$KmKId: clock.c,v 1.31 2004-10-19 17:32:07-04 kentd Exp $";
#include "defc.h"
#include <time.h>
@ -34,8 +34,8 @@ int g_clk_mode = CLK_IDLE;
int g_clk_read = 0;
int g_clk_reg1 = 0;
word32 c033_data = 0;
word32 c034_val = 0;
extern int g_c033_data;
extern int g_c034_val;
byte g_bram[2][256];
byte *g_bram_ptr = &(g_bram[0][0]);
@ -173,12 +173,19 @@ update_cur_time()
tm_ptr = localtime(&cur_time);
secs = mktime(tm_ptr);
#ifdef MAC
/* Mac OS X's mktime function modifies the tm_ptr passed in for */
/* the CDT timezone and breaks this algorithm. So on a Mac, we */
/* will use the tm_ptr->gmtoff member to correct the time */
secs = secs + tm_ptr->tm_gmtoff;
#else
secs = (unsigned int)cur_time - (secs2 - secs);
if(tm_ptr->tm_isdst) {
/* adjust for daylight savings time */
secs += 3600;
}
#endif
/* add in secs to make date based on Apple Jan 1, 1904 instead of */
/* Unix's Jan 1, 1970 */
@ -210,28 +217,10 @@ clock_update_if_needed()
}
}
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;
g_c034_val = val & 0x7f;
if((val & 0x80) != 0) {
if((val & 0x20) == 0) {
printf("c034 write not last = 1\n");
@ -251,12 +240,12 @@ do_clock_data()
clk_printf("In do_clock_data, g_clk_mode: %02x\n", g_clk_mode);
read = c034_val & 0x40;
read = g_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;
g_clk_read = (g_c033_data >> 7) & 1;
g_clk_reg1 = (g_c033_data >> 2) & 3;
op = (g_c033_data >> 4) & 7;
if(!read) {
/* write */
switch(op) {
@ -269,7 +258,7 @@ do_clock_data()
if(g_clk_reg1 & 0x2) {
/* extend BRAM read */
g_clk_mode = CLK_BRAM2;
g_clk_reg1 = (c033_data & 7) << 5;
g_clk_reg1 = (g_c033_data & 7) << 5;
}
break;
case 0x2: /* read/write ram 0x10-0x13 */
@ -279,11 +268,11 @@ do_clock_data()
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;
g_clk_reg1 = (g_c033_data >> 2) & 0xf;
break;
default:
halt_printf("Bad c033_data in CLK_IDLE: %02x\n",
c033_data);
g_c033_data);
}
} else {
printf("clk read from IDLE mode!\n");
@ -294,13 +283,13 @@ do_clock_data()
case CLK_BRAM2:
if(!read) {
/* get more bits of bram addr */
if((c033_data & 0x83) == 0x00) {
if((g_c033_data & 0x83) == 0x00) {
/* more address bits */
g_clk_reg1 |= ((c033_data >> 2) & 0x1f);
g_clk_reg1 |= ((g_c033_data >> 2) & 0x1f);
g_clk_mode = CLK_BRAM1;
} else {
halt_printf("CLK_BRAM2: c033_data: %02x!\n",
c033_data);
g_c033_data);
g_clk_mode = CLK_IDLE;
}
} else {
@ -313,9 +302,9 @@ do_clock_data()
if(read) {
if(g_clk_read) {
/* Yup, read */
c033_data = g_bram_ptr[g_clk_reg1];
g_c033_data = g_bram_ptr[g_clk_reg1];
clk_printf("Reading BRAM loc %02x: %02x\n",
g_clk_reg1, c033_data);
g_clk_reg1, g_c033_data);
} else {
halt_printf("CLK_BRAM1: said wr, now read\n");
}
@ -325,8 +314,8 @@ do_clock_data()
} 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_clk_reg1, g_c033_data);
g_bram_ptr[g_clk_reg1] = g_c033_data;
g_config_kegs_update_needed = 1;
}
}
@ -337,20 +326,21 @@ do_clock_data()
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;
g_c033_data = (g_clk_cur_time >> (g_clk_reg1 * 8)) &
0xff;
clk_printf("Returning time byte %d: %02x\n",
g_clk_reg1, c033_data);
g_clk_reg1, g_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);
g_clk_reg1, g_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_c033_data & 0xff) << (8 * g_clk_reg1));
}
g_clk_mode = CLK_IDLE;
break;
@ -361,24 +351,24 @@ do_clock_data()
} else {
switch(g_clk_reg1) {
case 0x0: /* test register */
if(c033_data & 0xc0) {
if(g_c033_data & 0xc0) {
printf("Writing test reg: %02x!\n",
c033_data);
g_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) {
g_c033_data);
if(g_c033_data & 0x80) {
printf("Stop, wr clk wr_prot: %02x\n",
c033_data);
g_c033_data);
/* set_halt(1); */
}
break;
default:
halt_printf("Writing int reg: %02x with %02x\n",
g_clk_reg1, c033_data);
g_clk_reg1, g_c033_data);
}
}
g_clk_mode = CLK_IDLE;

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/************************************************************************/
/* KEGS: Apple //gs Emulator */
/* Copyright 2003 by Kent Dickey */
/* Copyright 2003-2004 by Kent Dickey */
/* */
/* This code is covered by the GNU GPL */
/* */
@ -9,7 +9,7 @@
/************************************************************************/
#ifdef INCLUDE_RCSID_C
const char rcsid_config_h[] = "@(#)$KmKId: config.h,v 1.8 2003-10-17 15:09:58-04 kentd Exp $";
const char rcsid_config_h[] = "@(#)$KmKId: config.h,v 1.9 2004-11-12 23:10:28-05 kentd Exp $";
#endif
#define CONF_BUF_LEN 1024
@ -24,6 +24,7 @@ const char rcsid_config_h[] = "@(#)$KmKId: config.h,v 1.8 2003-10-17 15:09:58-04
#define CFGTYPE_INT 2
#define CFGTYPE_DISK 3
#define CFGTYPE_FUNC 4
#define CFGTYPE_FILE 5
/* CFGTYPE limited to just 4 bits: 0-15 */
/* Cfg_menu, Cfg_dirent and Cfg_listhdr are defined in defc.h */
@ -31,4 +32,5 @@ const char rcsid_config_h[] = "@(#)$KmKId: config.h,v 1.8 2003-10-17 15:09:58-04
STRUCT(Cfg_defval) {
Cfg_menu *menuptr;
int intval;
char *strval;
};

View File

@ -9,7 +9,7 @@
/************************************************************************/
#ifdef INCLUDE_RCSID_C
const char rcsid_defc_h[] = "@(#)$KmKId: defc.h,v 1.91 2003-11-03 01:29:38-05 kentd Exp $";
const char rcsid_defc_h[] = "@(#)$KmKId: defc.h,v 1.100 2004-11-09 02:02:07-05 kentd Exp $";
#endif
#include "defcomm.h"
@ -34,7 +34,10 @@ void U_STACK_TRACE();
#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_RAW (DCYCS_1_MHZ / 60.0) */
#define DCYCS_IN_16MS_RAW (262.0 * 65.0)
/* Use precisely 17030 instead of forcing 60 Hz since this is the number of */
/* 1MHz cycles per screen */
#define DCYCS_IN_16MS ((double)((int)DCYCS_IN_16MS_RAW))
#define DRECIP_DCYCS_IN_16MS (1.0 / (DCYCS_IN_16MS))
@ -70,6 +73,7 @@ void U_STACK_TRACE();
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#ifdef HPUX
# include <machine/inline.h> /* for GET_ITIMER */
#endif
@ -93,6 +97,13 @@ STRUCT(Pc_log) {
word32 pad;
};
STRUCT(Data_log) {
double dcycs;
word32 addr;
word32 val;
word32 size;
};
STRUCT(Event) {
double dcycs;
int type;
@ -167,6 +178,21 @@ STRUCT(Cfg_listhdr) {
int num_to_show;
};
STRUCT(Emustate_intlist) {
const char *str;
int *iptr;
};
STRUCT(Emustate_dbllist) {
const char *str;
double *dptr;
};
STRUCT(Emustate_word32list) {
const char *str;
word32 *wptr;
};
#ifdef __LP64__
# define PTR2WORD(a) ((unsigned long)(a))
#else
@ -174,14 +200,38 @@ STRUCT(Cfg_listhdr) {
#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 ALTZP (g_c068_statereg & 0x80)
/* #define PAGE2 (g_c068_statereg & 0x40) */
#define RAMRD (g_c068_statereg & 0x20)
#define RAMWRT (g_c068_statereg & 0x10)
#define RDROM (g_c068_statereg & 0x08)
#define LCBANK2 (g_c068_statereg & 0x04)
#define ROMB (g_c068_statereg & 0x02)
#define INTCX (g_c068_statereg & 0x01)
#define C041_EN_25SEC_INTS 0x10
#define C041_EN_VBL_INTS 0x08
#define C041_EN_SWITCH_INTS 0x04
#define C041_EN_MOVE_INTS 0x02
#define C041_EN_MOUSE 0x01
/* WARNING: SCC1 and SCC0 interrupts must be in this order for scc.c */
/* This order matches the SCC hardware */
#define IRQ_PENDING_SCC1_ZEROCNT 0x00001
#define IRQ_PENDING_SCC1_TX 0x00002
#define IRQ_PENDING_SCC1_RX 0x00004
#define IRQ_PENDING_SCC0_ZEROCNT 0x00008
#define IRQ_PENDING_SCC0_TX 0x00010
#define IRQ_PENDING_SCC0_RX 0x00020
#define IRQ_PENDING_C023_SCAN 0x00100
#define IRQ_PENDING_C023_1SEC 0x00200
#define IRQ_PENDING_C046_25SEC 0x00400
#define IRQ_PENDING_C046_VBL 0x00800
#define IRQ_PENDING_ADB_KBD_SRQ 0x01000
#define IRQ_PENDING_ADB_DATA 0x02000
#define IRQ_PENDING_ADB_MOUSE 0x04000
#define IRQ_PENDING_DOC 0x08000
#define EXTRU(val, pos, len) \
( ( (len) >= (pos) + 1) ? ((val) >> (31-(pos))) : \

View File

@ -9,11 +9,9 @@
/************************************************************************/
#ifdef INCLUDE_RCSID_C
const char rcsdif_defcomm_h[] = "@(#)$KmKId: defcomm.h,v 1.93 2002-11-19 03:10:38-05 kadickey Exp $";
const char rcsdif_defcomm_h[] = "@(#)$KmKId: defcomm.h,v 1.94 2004-10-13 21:53:44-04 kentd Exp $";
#endif
#define USE_XIMAGE_CHANGED
#if 0
# define CHECK_BREAKPOINTS
#endif
@ -61,25 +59,6 @@ const char rcsdif_defcomm_h[] = "@(#)$KmKId: defcomm.h,v 1.93 2002-11-19 03:10:3
#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
@ -189,12 +168,3 @@ const char rcsdif_defcomm_h[] = "@(#)$KmKId: defcomm.h,v 1.93 2002-11-19 03:10:3
#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

366
src/dis.c
View File

@ -8,7 +8,7 @@
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_dis_c[] = "@(#)$KmKId: dis.c,v 1.90 2003-11-18 17:35:30-05 kentd Exp $";
const char rcsid_dis_c[] = "@(#)$KmKId: dis.c,v 1.103 2004-11-24 16:41:41-05 kentd Exp $";
#include <stdio.h>
#include "defc.h"
@ -20,19 +20,16 @@ const char rcsid_dis_c[] = "@(#)$KmKId: dis.c,v 1.90 2003-11-18 17:35:30-05 kent
extern byte *g_memory_ptr;
extern byte *g_slow_memory_ptr;
extern byte *g_rom_fc_ff_ptr;
extern byte *g_rom_cards_ptr;
extern word32 g_mem_size_base, g_mem_size_exp;
extern int halt_sim;
extern int enter_debug;
extern int statereg;
extern int g_c068_statereg;
extern word32 stop_run_at;
extern int stop_on_c03x;
extern int Verbose;
extern int Halt_on;
extern int g_rom_version;
extern int g_testing_enabled;
extern int g_fullscreen;
extern int g_config_control_panel;
int g_num_breakpoints = 0;
word32 g_breakpts[MAX_BREAK_POINTS];
@ -48,8 +45,9 @@ int g_stepping = 0;
word32 list_kpc;
int hex_line_len;
word32 a1,a2,a3,a4;
int a1bank, a2bank, a3bank, a4bank;
word32 a1,a2,a3;
word32 g_a4, g_a4bank;
int a1bank, a2bank, a3bank;
char *line_ptr;
int mode,old_mode;
int got_num;
@ -154,9 +152,11 @@ do_debug_intfc()
int done;
int ret_val;
g_config_control_panel = 1;
hex_line_len = 0x10;
a1 = 0; a2 = 0; a3 = 0; a4 = 0;
a1bank = 0; a2bank = 0; a3bank = 0; a4bank = 0;
a1 = 0; a2 = 0; a3 = 0; g_a4 = 0;
a1bank = 0; a2bank = 0; a3bank = 0; g_a4bank = 0;
list_kpc = engine.kpc;
g_stepping = 0;
mode = 0; old_mode = 0;
@ -164,6 +164,8 @@ do_debug_intfc()
stop_run_at = -1;
x_auto_repeat_on(0);
g_fullscreen = 0;
x_full_screen(0);
if(g_quit_sim_now) {
printf("Exiting immediately\n");
@ -229,10 +231,14 @@ do_debug_intfc()
}
break;
case 'v':
video_show_debug_info();
if(got_num) {
dis_do_compare();
} else {
video_show_debug_info();
}
break;
case 'V':
printf("g_irq_pending: %d\n", g_irq_pending);
printf("g_irq_pending: %05x\n", g_irq_pending);
printf("Setting Verbose ^= %04x\n", a1);
Verbose ^= a1;
printf("Verbose is now: %04x\n", Verbose);
@ -256,8 +262,13 @@ do_debug_intfc()
if(engine.psr & 0x100) {
engine.psr |= 0x30;
}
} else {
dis_do_memmove();
}
break;
case 'p':
dis_do_pattern_search();
break;
case 'x':
if(old_mode == '=') {
if(!a1) {
@ -361,6 +372,10 @@ do_debug_intfc()
}
do_blank();
break;
case '<':
g_a4 = a2;
g_a4bank = a2bank;
break;
case 0x05: /* ctrl-e */
show_regs();
break;
@ -383,10 +398,6 @@ do_debug_intfc()
case 'w':
read_line(w_buff, W_BUF_LEN);
break;
case 'X':
stop_on_c03x = !stop_on_c03x;
printf("stop_on_c03x set to %d\n",stop_on_c03x);
break;
default:
printf("\nUnrecognized command: %s\n",linebuf);
*line_ptr = 0;
@ -437,7 +448,7 @@ show_toolset_tables(word32 a2bank, word32 addr)
addr = (a2bank << 16) + (addr & 0xffff);
toolfile = fopen("tool_set_info", "wt");
toolfile = fopen("tool_set_info", "w");
if(toolfile == 0) {
fprintf(stderr, "fopen of tool_set_info failed: %d\n", errno);
exit(2);
@ -573,10 +584,14 @@ do_blank()
void
do_go()
{
/* also called by do_step */
g_config_control_panel = 0;
clear_halt();
run_prog();
show_regs();
g_config_control_panel = 1;
}
void
@ -585,11 +600,8 @@ do_step()
int size;
int size_mem_imm, size_x_imm;
clear_halt();
do_go();
run_prog();
show_regs();
size_mem_imm = 2;
if(engine.psr & 0x20) {
size_mem_imm = 1;
@ -651,26 +663,59 @@ show_hex_mem(int startbank, word32 start, int endbank, word32 end, int count)
int
read_line(char *buf, int len)
{
int space_left;
int ret;
int space_left;
int ret;
#ifndef _WIN32
int flags, flags_save;
/* Unix */
flags = fcntl(0, F_GETFL, 0);
flags_save = flags;
if(flags == -1) {
return 0;
}
ret = fcntl(0, F_SETFL, flags | O_NONBLOCK);
if(ret == -1) {
return 0;
}
#endif
space_left = len;
ret = 0;
buf[0] = 0;
ret = 0;
while(space_left > 0) {
ret = read(0,buf,1);
#ifdef _WIN32
ret = win_nonblock_read_stdin(0, buf, 1);
#else
/* Unix */
ret = read(0, buf, 1);
#endif
if(ret <= 0) {
printf("read <= 0\n");
return(len-space_left);
micro_sleep(15.0/60.0);
if(errno == EAGAIN) {
/* it would block, so no chars--do update */
video_update();
ret = 0;
continue;
}
printf("read ret %d, errno: %d\n", ret, errno);
if(errno == EAGAIN || errno == EINTR) {
ret = 0;
continue;
}
break;
}
space_left -= ret;
if(buf[ret-1] == 0x0a) {
return(len-space_left);
break;
}
buf = &buf[ret];
}
return(len-space_left);
#ifndef _WIN32
(void)fcntl(0, F_SETFL, flags_save);
#endif
return (len-space_left);
}
void
@ -684,7 +729,7 @@ do_debug_list()
list_kpc = (a2bank << 16) + (a2 & 0xffff);
}
printf("%d=m %d=x %d=LCBANK\n", (engine.psr >> 5)&1,
(engine.psr >> 4) & 1, (statereg & 0x4) >> 2);
(engine.psr >> 4) & 1, (g_c068_statereg & 0x4) >> 2);
size_mem_imm = 2;
if(engine.psr & 0x20) {
@ -701,242 +746,45 @@ do_debug_list()
}
}
const char *g_kegs_rom_names[] = { "ROM", "ROM.01", "ROM.03", 0 };
void
dis_do_memmove()
{
word32 val;
const char *g_kegs_c1rom_names[] = { 0 };
const char *g_kegs_c2rom_names[] = { 0 };
const char *g_kegs_c3rom_names[] = { 0 };
const char *g_kegs_c4rom_names[] = { 0 };
const char *g_kegs_c5rom_names[] = { 0 };
const char *g_kegs_c6rom_names[] = { "c600.rom", "controller.rom", "disk.rom",
"DISK.ROM", "diskII.prom", 0 };
const char *g_kegs_c7rom_names[] = { 0 };
const char **g_kegs_rom_card_list[8] = {
0, g_kegs_c1rom_names,
g_kegs_c2rom_names, g_kegs_c3rom_names,
g_kegs_c4rom_names, g_kegs_c5rom_names,
g_kegs_c6rom_names, g_kegs_c7rom_names };
byte g_rom_c600_rom01_diffs[256] = {
0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xe2, 0x00,
0xd0, 0x50, 0x0f, 0x77, 0x5b, 0xb9, 0xc3, 0xb1,
0xb1, 0xf8, 0xcb, 0x4e, 0xb8, 0x60, 0xc7, 0x2e,
0xfc, 0xe0, 0xbf, 0x1f, 0x66, 0x37, 0x4a, 0x70,
0x55, 0x2c, 0x3c, 0xfc, 0xc2, 0xa5, 0x08, 0x29,
0xac, 0x21, 0xcc, 0x09, 0x55, 0x03, 0x17, 0x35,
0x4e, 0xe2, 0x0c, 0xe9, 0x3f, 0x9d, 0xc2, 0x06,
0x18, 0x88, 0x0d, 0x58, 0x57, 0x6d, 0x83, 0x8c,
0x22, 0xd3, 0x4f, 0x0a, 0xe5, 0xb7, 0x9f, 0x7d,
0x2c, 0x3e, 0xae, 0x7f, 0x24, 0x78, 0xfd, 0xd0,
0xb5, 0xd6, 0xe5, 0x26, 0x85, 0x3d, 0x8d, 0xc9,
0x79, 0x0c, 0x75, 0xec, 0x98, 0xcc, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00,
0x00, 0x00, 0x00, 0x39, 0x00, 0x35, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00,
0x6c, 0x44, 0xce, 0x4c, 0x01, 0x08, 0x00, 0x00
};
printf("Memory move from %02x/%04x.%04x to %02x/%04x\n", a1bank, a1, a2, g_a4bank, g_a4);
while(a1 <= (a2 & 0xffff)) {
val = get_memory_c((a1bank << 16) + a1, 0);
set_memory_c((g_a4bank << 16) + g_a4, val, 0);
a1++;
g_a4++;
}
a1 = a1 & 0xffff;
g_a4 = g_a4 & 0xffff;
}
void
load_roms()
dis_do_pattern_search()
{
char name_buf[256];
struct stat stat_buf;
const char **names_ptr;
int more_than_8mb;
int changed_rom;
int len;
int fd;
int ret;
int i;
printf("Memory pattern search for %04x in %02x/%04x.%04x\n", g_a4, a1bank, a1, a2);
}
g_rom_version = 0;
setup_kegs_file(&name_buf[0], (int)sizeof(name_buf), 0,
&g_kegs_rom_names[0]);
fd = open(name_buf, O_RDONLY | O_BINARY);
if(fd < 0) {
printf("Open ROM file %s failed:%d, errno:%d\n", name_buf, fd,
errno);
my_exit(-3);
}
void
dis_do_compare()
{
word32 val1, val2;
ret = fstat(fd, &stat_buf);
if(ret != 0) {
fprintf(stderr, "fstat returned %d on fd %d, errno: %d\n",
ret, fd, errno);
my_exit(2);
}
len = stat_buf.st_size;
if(len == 128*1024) {
g_rom_version = 1;
g_mem_size_base = 256*1024;
ret = read(fd, &g_rom_fc_ff_ptr[2*65536], len);
} else if(len == 256*1024) {
g_rom_version = 3;
g_mem_size_base = 1024*1024;
ret = read(fd, &g_rom_fc_ff_ptr[0], len);
} else {
fprintf(stderr, "ROM size %d not 128K or 256K\n", len);
my_exit(4);
}
printf("Read: %d bytes of ROM\n", ret);
if(ret != len) {
printf("errno: %d\n", errno);
my_exit(-3);
}
close(fd);
memset(&g_rom_cards_ptr[0], 0, 256*16);
/* initialize c600 rom to be diffs from the real ROM, to build-in */
/* Apple II compatibility without distributing ROMs */
for(i = 0; i < 256; i++) {
g_rom_cards_ptr[0x600 + i] = g_rom_fc_ff_ptr[0x3c600 + i] ^
g_rom_c600_rom01_diffs[i];
}
if(g_rom_version >= 3) {
/* some patches */
g_rom_cards_ptr[0x61b] ^= 0x40;
g_rom_cards_ptr[0x61c] ^= 0x33;
g_rom_cards_ptr[0x632] ^= 0xc0;
g_rom_cards_ptr[0x633] ^= 0x33;
}
for(i = 1; i < 8; i++) {
names_ptr = g_kegs_rom_card_list[i];
if(names_ptr == 0) {
continue;
}
if(*names_ptr == 0) {
continue;
}
setup_kegs_file(&name_buf[0], (int)sizeof(name_buf), 1,
names_ptr);
if(name_buf[0] != 0) {
fd = open(name_buf, O_RDONLY | O_BINARY);
if(fd < 0) {
printf("Open card ROM file %s failed: %d "
"err:%d\n", name_buf, fd, errno);
my_exit(-3);
}
len = 256;
ret = read(fd, &g_rom_cards_ptr[i*0x100], len);
if(ret != len) {
printf("errno: %d, expected %d, got %d\n",
errno, len, ret);
my_exit(-3);
}
close(fd);
printf("Memory Compare from %02x/%04x.%04x with %02x/%04x\n", a1bank, a1, a2, g_a4bank, g_a4);
while(a1 <= (a2 & 0xffff)) {
val1 = get_memory_c((a1bank << 16) + a1, 0);
val2 = get_memory_c((g_a4bank << 16) + g_a4, 0);
if(val1 != val2) {
printf("%02x/%04x: %02x vs %02x\n", a1bank, a1, val1, val2);
}
a1++;
g_a4++;
}
more_than_8mb = (g_mem_size_exp > 0x800000);
/* Only do the patch if users wants more than 8MB of expansion mem */
changed_rom = 0;
if(g_rom_version == 1) {
/* make some patches to ROM 01 */
#if 0
/* 1: Patch ROM selftest to not do speed test */
printf("Patching out speed test failures from ROM 01\n");
g_rom_fc_ff_ptr[0x3785a] = 0x18;
changed_rom = 1;
#endif
#if 0
/* 2: Patch ROM selftests not to do tests 2,4 */
/* 0 = skip, 1 = do it, test 1 is bit 0 of LSByte */
g_rom_fc_ff_ptr[0x371e9] = 0xf5;
g_rom_fc_ff_ptr[0x371ea] = 0xff;
changed_rom = 1;
#endif
if(more_than_8mb) {
/* Geoff Weiss patch to use up to 14MB of RAM */
g_rom_fc_ff_ptr[0x30302] = 0xdf;
g_rom_fc_ff_ptr[0x30314] = 0xdf;
g_rom_fc_ff_ptr[0x3031c] = 0x00;
changed_rom = 1;
}
/* Patch ROM selftest to not do ROM cksum if any changes*/
if(changed_rom) {
g_rom_fc_ff_ptr[0x37a06] = 0x18;
g_rom_fc_ff_ptr[0x37a07] = 0x18;
}
} else if(g_rom_version == 3) {
/* patch ROM 03 */
printf("Patching ROM 03 smartport bug\n");
/* 1: Patch Smartport code to fix a stupid bug */
/* that causes it to write the IWM status reg into c036, */
/* which is the system speed reg...it's "safe" since */
/* IWM status reg bit 4 must be 0 (7MHz)..., otherwise */
/* it might have turned on shadowing in all banks! */
g_rom_fc_ff_ptr[0x357c9] = 0x00;
changed_rom = 1;
#if 0
/* patch ROM 03 to not to speed test */
/* skip fast speed test */
g_rom_fc_ff_ptr[0x36ad7] = 0x18;
g_rom_fc_ff_ptr[0x36ad8] = 0x18;
changed_rom = 1;
#endif
#if 0
/* skip slow speed test */
g_rom_fc_ff_ptr[0x36ae7] = 0x18;
g_rom_fc_ff_ptr[0x36ae8] = 0x6b;
changed_rom = 1;
#endif
#if 0
/* 4: Patch ROM 03 selftests not to do tests 1-4 */
g_rom_fc_ff_ptr[0x364a9] = 0xf0;
g_rom_fc_ff_ptr[0x364aa] = 0xff;
changed_rom = 1;
#endif
/* ROM tests are in ff/6403-642x, where 6403 = addr of */
/* test 1, etc. */
if(more_than_8mb) {
/* Geoff Weiss patch to use up to 14MB of RAM */
g_rom_fc_ff_ptr[0x30b] = 0xdf;
g_rom_fc_ff_ptr[0x31d] = 0xdf;
g_rom_fc_ff_ptr[0x325] = 0x00;
changed_rom = 1;
}
if(changed_rom) {
/* patch ROM 03 selftest to not do ROM cksum */
g_rom_fc_ff_ptr[0x36cb0] = 0x18;
g_rom_fc_ff_ptr[0x36cb1] = 0x18;
}
}
a1 = a1 & 0xffff;
g_a4 = g_a4 & 0xffff;
}
void

View File

@ -8,7 +8,7 @@
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_engine_c_c[] = "@(#)$KmKId: engine_c.c,v 1.51 2004-01-10 15:50:15-05 kentd Exp $";
const char rcsid_engine_c_c[] = "@(#)$KmKId: engine_c.c,v 1.57 2004-12-03 23:51:01-05 kentd Exp $";
#include "defc.h"
#include "protos_engine_c.h"
@ -28,8 +28,10 @@ const char rcsid_engine_c_c[] = "@(#)$KmKId: engine_c.c,v 1.51 2004-01-10 15:50:
extern int halt_sim;
extern int g_code_red;
extern int g_ignore_halts;
extern int g_user_halt_bad;
extern double g_fcycles_stop;
extern double g_last_vbl_dcycs;
extern double g_cur_dcycs;
extern int g_wait_pending;
extern int g_irq_pending;
extern int g_testing;
@ -44,9 +46,13 @@ extern byte *g_dummy_memory1_ptr;
extern int g_num_breakpoints;
extern word32 g_breakpts[];
extern Pc_log *log_pc_ptr;
extern Pc_log *log_pc_start_ptr;
extern Pc_log *log_pc_end_ptr;
extern Pc_log *g_log_pc_ptr;
extern Pc_log *g_log_pc_start_ptr;
extern Pc_log *g_log_pc_end_ptr;
extern Data_log *g_log_data_ptr;
extern Data_log *g_log_data_start_ptr;
extern Data_log *g_log_data_end_ptr;
int size_tab[] = {
#include "size_c.h"
@ -75,8 +81,9 @@ int bogus[] = {
#define FCYCLES_ROUND fcycles = (int)(fcycles + fplus_x_m1);
#define LOG_PC_MACRO() \
tmp_pc_ptr = log_pc_ptr++; \
#ifdef LOG_PC
# define LOG_PC_MACRO() \
tmp_pc_ptr = g_log_pc_ptr++; \
tmp_pc_ptr->dbank_kpc = (dbank << 24) + kpc; \
tmp_pc_ptr->instr = (opcode << 24) + arg_ptr[1] + \
(arg_ptr[2] << 8) + (arg_ptr[3] << 16); \
@ -85,11 +92,28 @@ int bogus[] = {
tmp_pc_ptr->xreg_yreg = (xreg << 16) + yreg; \
tmp_pc_ptr->stack_direct = (stack << 16) + direct; \
tmp_pc_ptr->dcycs = fcycles + g_last_vbl_dcycs - fplus_2; \
if(log_pc_ptr >= log_pc_end_ptr) { \
if(g_log_pc_ptr >= g_log_pc_end_ptr) { \
/*halt2_printf("log_pc oflow %f\n", tmp_pc_ptr->dcycs);*/ \
log_pc_ptr = log_pc_start_ptr; \
g_log_pc_ptr = g_log_pc_start_ptr; \
}
# define LOG_DATA_MACRO(in_addr, in_val, in_size) \
g_log_data_ptr->dcycs = fcycles + g_last_vbl_dcycs; \
g_log_data_ptr->addr = in_addr; \
g_log_data_ptr->val = in_val; \
g_log_data_ptr->size = in_size; \
g_log_data_ptr++; \
if(g_log_data_ptr >= g_log_data_end_ptr) { \
g_log_data_ptr = g_log_data_start_ptr; \
}
#else
# define LOG_PC_MACRO()
# define LOG_DATA_MACRO(addr, val, size)
/* Just do nothing */
#endif
#define GET_1BYTE_ARG arg = arg_ptr[1];
#define GET_2BYTE_ARG arg = arg_ptr[1] + (arg_ptr[2] << 8);
#define GET_3BYTE_ARG arg = arg_ptr[1] + (arg_ptr[2] << 8) + (arg_ptr[3]<<16);
@ -270,6 +294,7 @@ extern word32 slow_mem_changed[];
}
#define SET_MEMORY8(addr, val) \
LOG_DATA_MACRO(addr, val, 8); \
CYCLES_PLUS_1; \
stat = GET_PAGE_INFO_WR(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
@ -284,17 +309,15 @@ extern word32 slow_mem_changed[];
}
#define SET_MEMORY16(addr, val, in_bank) \
LOG_DATA_MACRO(addr, val, 16); \
stat = GET_PAGE_INFO_WR(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
ptr = stat - wstat + ((addr) & 0xff); \
if((wstat) || (((addr) & 0xff) == 0xff)) { \
if((wstat) || (((addr) & 0xff) == 0xff)) { \
fcycles_tmp1 = fcycles; \
set_memory16_pieces_stub((addr), (val), \
&fcycles_tmp1, fplus_ptr, in_bank); \
&fcycles_tmp1, fplus_1, fplus_x_m1, in_bank); \
fcycles = fcycles_tmp1; \
} else { \
CYCLES_PLUS_2; \
@ -303,6 +326,7 @@ extern word32 slow_mem_changed[];
}
#define SET_MEMORY24(addr, val, in_bank) \
LOG_DATA_MACRO(addr, val, 24); \
stat = GET_PAGE_INFO_WR(((addr) >> 8) & 0xffff); \
wstat = PTR2WORD(stat) & 0xff; \
ptr = stat - wstat + ((addr) & 0xff); \
@ -326,7 +350,7 @@ check_breakpoints(word32 addr)
count = g_num_breakpoints;
for(i = 0; i < count; i++) {
if(g_breakpts[i] == addr) {
if((g_breakpts[i] & 0xffffff) == addr) {
halt2_printf("Hit breakpoint at %06x\n", addr);
}
}
@ -464,19 +488,15 @@ set_memory8_io_stub(word32 addr, word32 val, byte *stat, double *fcycs_ptr,
void
set_memory16_pieces_stub(word32 addr, word32 val, double *fcycs_ptr,
Fplus *fplus_ptr, int in_bank)
double fplus_1, double fplus_x_m1, int in_bank)
{
byte *ptr;
byte *stat;
double fcycles, fcycles_tmp1;
double fplus_1;
double fplus_x_m1;
word32 addrp1;
word32 wstat;
fcycles = *fcycs_ptr;
fplus_1 = fplus_ptr->plus_1;
fplus_x_m1 = fplus_ptr->plus_x_minus_1;
SET_MEMORY8(addr, val);
addrp1 = addr + 1;
if(in_bank) {
@ -536,14 +556,6 @@ get_memory_c(word32 addr, int cycs)
GET_MEMORY8(addr, ret);
return ret;
}
#if 0
stat = page_info[(addr>>8) & 0xffff].rd;
ptr = (byte *)((stat & 0xffffff00) | (addr & 0xff));
if(stat & (1 << (31 -BANK_IO_BIT))) {
return get_memory_io(addr, &in_fcycles);
}
return *ptr;
#endif
word32
get_memory16_c(word32 addr, int cycs)
@ -576,16 +588,27 @@ set_memory_c(word32 addr, word32 val, int cycs)
double fplus_x_m1;
word32 wstat;
fcycles = 0;
fcycles = g_cur_dcycs - g_last_vbl_dcycs;
fplus_1 = 0;
fplus_x_m1 = 0;
SET_MEMORY8(addr, val);
}
void
set_memory16_c(word32 addr, word32 val, int cycs)
{
set_memory_c(addr, val, 0);
set_memory_c(addr + 1, val >> 8, 0);
byte *stat;
byte *ptr;
double fcycles, fcycles_tmp1;
double fplus_1, fplus_2;
double fplus_x_m1;
word32 wstat;
fcycles = g_cur_dcycs - g_last_vbl_dcycs;
fplus_1 = 0;
fplus_2 = 0;
fplus_x_m1 = 0;
SET_MEMORY16(addr, val, 0);
}
void
@ -706,10 +729,10 @@ fixed_memory_ptrs_init()
/* set g_slow_memory_ptr, g_rom_fc_ff_ptr, g_dummy_memory1_ptr, */
/* and rom_cards_ptr */
g_slow_memory_ptr = memalloc_align(128*1024, 0);
g_dummy_memory1_ptr = memalloc_align(256, 1024);
g_rom_fc_ff_ptr = memalloc_align(256*1024, 1024);
g_rom_cards_ptr = memalloc_align(16*256, 1024);
g_slow_memory_ptr = memalloc_align(128*1024, 0, 0);
g_dummy_memory1_ptr = memalloc_align(256, 1024, 0);
g_rom_fc_ff_ptr = memalloc_align(256*1024, 512, 0);
g_rom_cards_ptr = memalloc_align(16*256, 256, 0);
#if 0
printf("g_memory_ptr: %08x, dummy_mem: %08x, slow_mem_ptr: %08x\n",
@ -757,7 +780,7 @@ get_itimer()
void
set_halt_act(int val)
{
if(val == 1 && g_ignore_halts) {
if(val == 1 && g_ignore_halts && !g_user_halt_bad) {
g_code_red++;
} else {
halt_sim |= val;
@ -938,9 +961,7 @@ recalc_accsize:
FETCH_OPCODE;
#ifdef LOG_PC
LOG_PC_MACRO();
#endif
switch(opcode) {
default:
@ -957,9 +978,7 @@ recalc_accsize:
} else {
while(fcycles <= g_fcycles_stop) {
FETCH_OPCODE;
#ifdef LOG_PC
LOG_PC_MACRO();
#endif
switch(opcode) {
default:

View File

@ -10,7 +10,7 @@
#ifdef ASM
# ifdef INCLUDE_RCSID_S
.stringz "@(#)$KmKId: instable.h,v 1.103 2004-01-10 15:50:50-05 kentd Exp $"
.stringz "@(#)$KmKId: instable.h,v 1.104 2004-10-05 20:12:08-04 kentd Exp $"
# endif
#endif
@ -2353,9 +2353,8 @@ instdb_SYM /* STP */
b dispatch_done
depi RET_STP,3,4,ret0
#else
GET_1BYTE_ARG;
CYCLES_PLUS_1
FINISH(RET_STP, arg);
CYCLES_FINISH
FINISH(RET_STP, 0);
#endif
instdc_SYM /* JML (Abs) */

167
src/iwm.c
View File

@ -8,14 +8,13 @@
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_iwm_c[] = "@(#)$KmKId: iwm.c,v 1.111 2003-11-03 22:14:10-05 kentd Exp $";
const char rcsid_iwm_c[] = "@(#)$KmKId: iwm.c,v 1.119 2004-11-21 17:44:14-05 kentd Exp $";
#include "defc.h"
extern int Verbose;
extern int g_vbl_count;
extern int speed_fast;
extern word32 g_slot_motor_detect;
extern int g_c036_val_speed;
const byte phys_to_dos_sec[] = {
0x00, 0x07, 0x0e, 0x06, 0x0d, 0x05, 0x0c, 0x04,
@ -72,8 +71,8 @@ int from_disk_byte_valid = 0;
Iwm iwm;
int g_apple35_sel = 0;
int head_35 = 0;
extern int g_c031_disk35;
int g_iwm_motor_on = 0;
int g_check_nibblization = 0;
@ -87,11 +86,6 @@ void iwm_write_data_525(Disk *dsk, word32 val, int fast_disk_emul,double dcycs);
void
iwm_init_drive(Disk *dsk, int smartport, int drive, int disk_525)
{
int num_tracks;
int i;
num_tracks = MAX_TRACKS;
dsk->dcycs_last_read = 0.0;
dsk->name_ptr = 0;
dsk->partition_name = 0;
@ -113,15 +107,31 @@ iwm_init_drive(Disk *dsk, int smartport, int drive, int disk_525)
dsk->last_phase = 0;
dsk->nib_pos = 0;
dsk->num_tracks = 0;
dsk->trks = 0;
}
void
disk_set_num_tracks(Disk *dsk, int num_tracks)
{
int i;
if(dsk->trks != 0) {
/* This should not be necessary! */
free(dsk->trks);
halt_printf("Needed to free dsk->trks: %p\n", dsk->trks);
}
dsk->num_tracks = num_tracks;
dsk->trks = (Trk *)malloc(num_tracks * sizeof(Trk));
for(i = 0; i < num_tracks; i++) {
dsk->tracks[i].dsk = dsk;
dsk->tracks[i].nib_area = 0;
dsk->tracks[i].track_dirty = 0;
dsk->tracks[i].overflow_size = 0;
dsk->tracks[i].track_len = 0;
dsk->tracks[i].unix_pos = -1;
dsk->tracks[i].unix_len = -1;
dsk->trks[i].dsk = dsk;
dsk->trks[i].nib_area = 0;
dsk->trks[i].track_dirty = 0;
dsk->trks[i].overflow_size = 0;
dsk->trks[i].track_len = 0;
dsk->trks[i].unix_pos = -1;
dsk->trks[i].unix_len = -1;
}
}
@ -179,21 +189,23 @@ iwm_reset()
iwm.previous_write_bits = 0;
g_iwm_motor_on = 0;
g_apple35_sel = 0;
g_c031_disk35 = 0;
}
void
draw_iwm_status(int line, char *buf)
{
char *flag[2][2];
int apple35_sel;
flag[0][0] = " ";
flag[0][1] = " ";
flag[1][0] = " ";
flag[1][1] = " ";
apple35_sel = (g_c031_disk35 >> 6) & 1;
if(g_iwm_motor_on) {
flag[g_apple35_sel][iwm.drive_select] = "*";
flag[apple35_sel][iwm.drive_select] = "*";
}
sprintf(buf, "s6d1:%2d%s s6d2:%2d%s s5d1:%2d/%d%s "
@ -204,12 +216,12 @@ draw_iwm_status(int line, char *buf)
iwm.drive35[0].cur_qtr_track & 1, flag[1][0],
iwm.drive35[1].cur_qtr_track >> 1,
iwm.drive35[1].cur_qtr_track & 1, flag[1][1],
g_fast_disk_emul, g_slow_525_emul_wr,
(speed_fast << 7) + g_slot_motor_detect);
g_fast_disk_emul, g_slow_525_emul_wr, g_c036_val_speed);
video_update_status_line(line, buf);
}
void
iwm_flush_disk_to_unix(Disk *dsk)
{
@ -253,8 +265,8 @@ iwm_flush_disk_to_unix(Disk *dsk)
num_dirty++;
/* Write it out */
unix_pos = dsk->tracks[j].unix_pos;
unix_len = dsk->tracks[j].unix_len;
unix_pos = dsk->trks[j].unix_pos;
unix_len = dsk->trks[j].unix_len;
if(unix_pos < 0 || unix_len < 0x1000) {
halt_printf("Disk:%s trk:%d, unix_pos:%08x, len:%08x\n",
dsk->name_ptr, j, unix_pos, unix_len);
@ -303,7 +315,7 @@ iwm_vbl_update(int doit_3_persec)
}
motor_on = iwm.motor_on;
if(g_apple35_sel) {
if(g_c031_disk35 & 0x40) {
motor_on = iwm.motor_on35;
}
@ -327,11 +339,11 @@ iwm_show_stats()
{
printf("IWM stats: q7,q6: %d, %d, reset,enable2: %d,%d, mode: %02x\n",
iwm.q7, iwm.q6, iwm.reset, iwm.enable2, iwm.iwm_mode);
printf("motor: %d,%d, motor35:%d drive: %d, on: %d, head35: %d "
printf("motor: %d,%d, motor35:%d drive: %d, c031:%02x "
"phs: %d %d %d %d\n",
iwm.motor_on, iwm.motor_off, g_iwm_motor_on,
iwm.drive_select, g_apple35_sel,
head_35, iwm.iwm_phase[0], iwm.iwm_phase[1], iwm.iwm_phase[2],
iwm.drive_select, g_c031_disk35,
iwm.iwm_phase[0], iwm.iwm_phase[1], iwm.iwm_phase[2],
iwm.iwm_phase[3]);
printf("iwm.drive525[0].fd: %d, [1].fd: %d\n",
iwm.drive525[0].fd, iwm.drive525[1].fd);
@ -355,7 +367,7 @@ iwm_touch_switches(int loc, double dcycs)
on = loc & 1;
drive = iwm.drive_select;
phase = loc >> 1;
if(g_apple35_sel) {
if(g_c031_disk35 & 0x40) {
dsk = &(iwm.drive35[drive]);
} else {
dsk = &(iwm.drive525[drive]);
@ -366,9 +378,12 @@ iwm_touch_switches(int loc, double dcycs)
/* phase adjustments. See if motor is on */
iwm.iwm_phase[phase] = on;
iwm_printf("Iwm phase %d=%d, all phases: %d %d %d %d (%f)\n",
phase, on, iwm.iwm_phase[0], iwm.iwm_phase[1],
iwm.iwm_phase[2], iwm.iwm_phase[3], dcycs);
if(iwm.motor_on) {
if(g_apple35_sel) {
if(g_c031_disk35 & 0x40) {
if(phase == 3 && on) {
iwm_do_action35(dcycs);
}
@ -527,7 +542,7 @@ iwm525_phase_change(int drive, int phase)
last_phase = 0;
}
if(qtr_track > 4*34) {
printf("Disk arm moved past track 0x21, moving it back\n");
printf("Disk arm moved past track 34, moving it back\n");
qtr_track = 4*34;
last_phase = 0;
}
@ -536,9 +551,9 @@ iwm525_phase_change(int drive, int phase)
dsk->last_phase = last_phase;
iwm_printf("Moving drive to qtr track: %04x, %d, %d, %d, "
"%d %d %d %d\n",
qtr_track, phase, delta, last_phase, iwm.iwm_phase[0],
iwm_printf("Moving drive to qtr track: %04x (trk:%d.%02d), %d, %d, %d, "
"%d %d %d %d\n", qtr_track, qtr_track>>2, 25*(qtr_track & 3),
phase, delta, last_phase, iwm.iwm_phase[0],
iwm.iwm_phase[1], iwm.iwm_phase[2], iwm.iwm_phase[3]);
/* sanity check stepping algorithm */
@ -564,7 +579,7 @@ iwm_read_status35(double dcycs)
if(iwm.motor_on) {
/* Read status */
state = (iwm.iwm_phase[1] << 3) + (iwm.iwm_phase[0] << 2) +
(head_35 << 1) + iwm.iwm_phase[2];
((g_c031_disk35 >> 6) & 2) + iwm.iwm_phase[2];
iwm_printf("Iwm status read state: %02x\n", state);
@ -666,7 +681,7 @@ iwm_do_action35(double dcycs)
if(iwm.motor_on) {
/* Perform action */
state = (iwm.iwm_phase[1] << 3) + (iwm.iwm_phase[0] << 2) +
(head_35 << 1) + iwm.iwm_phase[2];
((g_c031_disk35 >> 6) & 2) + iwm.iwm_phase[2];
switch(state) {
case 0x00: /* Set step direction inward */
/* towards higher tracks */
@ -715,17 +730,6 @@ iwm_do_action35(double dcycs)
}
}
void
iwm_set_apple35_sel(int newval)
{
if(g_apple35_sel != newval) {
/* Handle speed changes */
set_halt(HALT_EVENT);
}
g_apple35_sel = newval;
}
int
iwm_read_c0ec(double dcycs)
{
@ -736,7 +740,7 @@ iwm_read_c0ec(double dcycs)
if(iwm.q7 == 0 && iwm.enable2 == 0 && iwm.motor_on) {
drive = iwm.drive_select;
if(g_apple35_sel) {
if(g_c031_disk35 & 0x40) {
dsk = &(iwm.drive35[drive]);
return iwm_read_data_35(dsk, g_fast_disk_emul, dcycs);
} else {
@ -773,7 +777,7 @@ read_iwm(int loc, double dcycs)
state = (iwm.q7 << 1) + iwm.q6;
drive = iwm.drive_select;
if(g_apple35_sel) {
if(g_c031_disk35 & 0x40) {
dsk = &(iwm.drive35[drive]);
} else {
dsk = &(iwm.drive525[drive]);
@ -806,7 +810,7 @@ read_iwm(int loc, double dcycs)
iwm_printf("Read status under enable2: 1\n");
status = 1;
} else {
if(g_apple35_sel) {
if(g_c031_disk35 & 0x40) {
status = iwm_read_status35(dcycs);
} else {
status = dsk->write_prot;
@ -868,7 +872,7 @@ write_iwm(int loc, int val, double dcycs)
state = (iwm.q7 << 1) + iwm.q6;
drive = iwm.drive_select;
fast_writes = g_fast_disk_emul;
if(g_apple35_sel) {
if(g_c031_disk35 & 0x40) {
dsk = &(iwm.drive35[drive]);
} else {
dsk = &(iwm.drive525[drive]);
@ -899,8 +903,11 @@ write_iwm(int loc, int val, double dcycs)
if(iwm.enable2) {
iwm_write_enable2(val, dcycs);
} else {
#if 0
// Flobynoid writes to 0xc0e9 causing these messages...
printf("Write iwm1, st: %02x, loc: %x: %02x\n",
state, loc, val);
#endif
}
}
return;
@ -915,10 +922,7 @@ write_iwm(int loc, int val, double dcycs)
return;
}
halt_printf("Got to end of write_iwm, loc:%02x, val: %02x\n", loc, val);
return;
}
@ -1064,7 +1068,7 @@ disk_unnib_4x4(Disk *dsk)
}
int
iwm_denib_track525(Disk *dsk, Track *trk, int qtr_track, byte *outbuf)
iwm_denib_track525(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf)
{
byte aux_buf[0x80];
byte *buf;
@ -1274,7 +1278,7 @@ 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)
iwm_denib_track35(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf)
{
word32 buf_c00[0x100];
word32 buf_d00[0x100];
@ -1601,17 +1605,14 @@ iwm_denib_track35(Disk *dsk, Track *trk, int qtr_track, byte *outbuf)
int
disk_track_to_unix(Disk *dsk, int qtr_track, byte *outbuf)
{
Track *trk;
Trk *trk;
int disk_525;
disk_525 = dsk->disk_525;
trk = &(dsk->tracks[qtr_track]);
trk = &(dsk->trks[qtr_track]);
if(trk->track_len == 0 || trk->track_dirty == 0) {
#if 0
printf("disk_track_to_unix: dirty: %d\n", trk->track_dirty);
#endif
return 0;
}
@ -1652,7 +1653,7 @@ void
disk_check_nibblization(Disk *dsk, int qtr_track, byte *buf, int size)
{
byte buffer[0x3000];
Track *trk;
Trk *trk;
int ret, ret2;
int i;
@ -1665,7 +1666,7 @@ disk_check_nibblization(Disk *dsk, int qtr_track, byte *buf, int size)
buffer[i] = 0;
}
trk = &(dsk->tracks[qtr_track]);
trk = &(dsk->trks[qtr_track]);
if(dsk->disk_525) {
ret = iwm_denib_track525(dsk, trk, qtr_track, &(buffer[0]));
@ -1688,7 +1689,7 @@ disk_check_nibblization(Disk *dsk, int qtr_track, byte *buf, int size)
ret, ret2, qtr_track);
show_hex_data(buf, 0x1000);
show_hex_data(buffer, 0x1000);
iwm_show_a_track(&(dsk->tracks[qtr_track]));
iwm_show_a_track(&(dsk->trks[qtr_track]));
exit(2);
}
@ -1702,7 +1703,7 @@ disk_unix_to_nib(Disk *dsk, int qtr_track, int unix_pos, int unix_len,
int nib_len)
{
byte track_buf[TRACK_BUF_LEN];
Track *trk;
Trk *trk;
int must_clear_track;
int ret;
int len;
@ -1763,7 +1764,7 @@ disk_unix_to_nib(Disk *dsk, int qtr_track, int unix_pos, int unix_len,
dsk->nib_pos = 0; /* for consistency */
trk = &(dsk->tracks[qtr_track]);
trk = &(dsk->trks[qtr_track]);
trk->track_dirty = 0;
trk->overflow_size = 0;
trk->track_len = 2*nib_len;
@ -1784,7 +1785,7 @@ disk_unix_to_nib(Disk *dsk, int qtr_track, int unix_pos, int unix_len,
}
void
iwm_nibblize_track_nib525(Disk *dsk, Track *trk, byte *track_buf, int qtr_track)
iwm_nibblize_track_nib525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track)
{
byte *nib_ptr;
byte *trk_ptr;
@ -1803,7 +1804,7 @@ 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)
iwm_nibblize_track_525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track)
{
byte partial_nib_buf[0x300];
word32 *word_ptr;
@ -1895,7 +1896,7 @@ 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)
iwm_nibblize_track_35(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track)
{
int phys_to_log_sec[16];
word32 buf_c00[0x100];
@ -2150,7 +2151,7 @@ disk_4x4_nib_out(Disk *dsk, word32 val)
void
disk_nib_out(Disk *dsk, byte val, int size)
{
Track *trk;
Trk *trk;
int pos;
int old_size;
int track_len;
@ -2160,9 +2161,12 @@ disk_nib_out(Disk *dsk, byte val, int size)
qtr_track = dsk->cur_qtr_track;
trk = &(dsk->tracks[qtr_track]);
track_len = trk->track_len;
track_len = 0;
trk = 0;
if(dsk->trks != 0) {
trk = &(dsk->trks[qtr_track]);
track_len = trk->track_len;
}
if(track_len <= 10) {
printf("Writing to an invalid qtr track: %02x!\n", qtr_track);
@ -2234,7 +2238,7 @@ disk_nib_end_track(Disk *dsk)
dsk->nib_pos = 0;
qtr_track = dsk->cur_qtr_track;
dsk->tracks[qtr_track].track_dirty = 0;
dsk->trks[qtr_track].track_dirty = 0;
dsk->disk_dirty = 0;
}
@ -2243,14 +2247,14 @@ void
iwm_show_track(int slot_drive, int track)
{
Disk *dsk;
Track *trk;
Trk *trk;
int drive;
int sel35;
int qtr_track;
if(slot_drive < 0) {
drive = iwm.drive_select;
sel35 = g_apple35_sel;
sel35 = (g_c031_disk35 >> 6) & 1;
} else {
drive = slot_drive & 1;
sel35 = !((slot_drive >> 1) & 1);
@ -2267,22 +2271,25 @@ iwm_show_track(int slot_drive, int track)
} else {
qtr_track = track;
}
trk = &(dsk->tracks[qtr_track]);
if(dsk->trks == 0) {
return;
}
trk = &(dsk->trks[qtr_track]);
if(trk->track_len <= 0) {
printf("Track_len: %d\n", trk->track_len);
printf("No track for type: %d, drive: %d, qtrk: %02x\n",
g_apple35_sel, drive, qtr_track);
printf("No track for type: %d, drive: %d, qtrk: 0x%02x\n",
sel35, drive, qtr_track);
return;
}
printf("Current drive: %d, q_track: %02x\n", drive, qtr_track);
printf("Current drive: %d, q_track: 0x%02x\n", drive, qtr_track);
iwm_show_a_track(trk);
}
void
iwm_show_a_track(Track *trk)
iwm_show_a_track(Trk *trk)
{
int sum;
int len;

View File

@ -9,7 +9,7 @@
/************************************************************************/
#ifdef INCLUDE_RCSID_C
const char rcsid_iwm_h[] = "@(#)$KmKId: iwm.h,v 1.13 2003-07-08 23:29:48-04 kentd Exp $";
const char rcsid_iwm_h[] = "@(#)$KmKId: iwm.h,v 1.14 2004-10-20 17:29:38-04 kentd Exp $";
#endif
#define MAX_TRACKS (2*80)
@ -24,7 +24,7 @@ const char rcsid_iwm_h[] = "@(#)$KmKId: iwm.h,v 1.13 2003-07-08 23:29:48-04 kent
typedef struct _Disk Disk;
STRUCT(Track) {
STRUCT(Trk) {
Disk *dsk;
byte *nib_area;
int track_dirty;
@ -56,7 +56,7 @@ struct _Disk {
int last_phase;
int nib_pos;
int num_tracks;
Track tracks[MAX_TRACKS];
Trk *trks;
};

View File

@ -1,12 +1,12 @@
#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 $";
const char rcsdif_iwm_35_525_h[] = "@(#)$KmKId: iwm_35_525.h,v 1.14 2004-12-01 19:45:02-05 kentd Exp $";
#endif
int
IWM_READ_ROUT (Disk *dsk, int fast_disk_emul, double dcycs)
{
Track *trk;
Trk *trk;
double dcycs_last_read;
int pos;
int pos2;
@ -30,12 +30,28 @@ IWM_READ_ROUT (Disk *dsk, int fast_disk_emul, double dcycs)
qtr_track = dsk->cur_qtr_track;
trk = &(dsk->tracks[qtr_track]);
track_len = trk->track_len;
#if IWM_DISK_525
qtr_track = qtr_track & -4; /* round to nearest whole trk! */
#endif
trk = 0;
track_len = 0;
if(dsk->trks) {
trk = &(dsk->trks[qtr_track]);
track_len = trk->track_len;
}
dcycs_last_read = dsk->dcycs_last_read;
dcycs_passed = dcycs - dcycs_last_read;
cycs_passed = (int)dcycs_passed;
if(track_len == 0) {
ret = (cycs_passed & 0x7f) + 0x80;
iwm_printf("Reading c0ec, track_len 0, returning %02x\n", ret);
return ret;
}
pos = dsk->nib_pos;
if(pos >= track_len) {
/* Arm may have moved from inner 3.5 track to outer one, */
@ -43,11 +59,6 @@ IWM_READ_ROUT (Disk *dsk, int fast_disk_emul, double dcycs)
pos = 0;
}
cycs_passed = (int)dcycs_passed;
if(track_len == 0) {
return (cycs_passed & 0x7f) + 0x80;
}
size = trk->nib_area[pos];
while(size == 0) {
@ -207,9 +218,9 @@ IWM_WRITE_ROUT (Disk *dsk, word32 val, int fast_disk_emul, double dcycs)
int sdiff;
int prev_bits;
if(dsk->fd < 0) {
if(dsk->fd < 0 || dsk->trks == 0) {
halt_printf("Tried to write to type: %d, drive: %d, fd: %d!\n",
IWM_DISK_525, dsk->drive, dsk->fd);
IWM_DISK_525, dsk->drive, dsk->fd, dsk->trks);
return;
}

View File

@ -8,7 +8,7 @@
/* 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 $";
const char rcsid_joystick_driver_c[] = "@(#)$KmKId: joystick_driver.c,v 1.12 2004-10-17 21:28:48-04 kentd Exp $";
#include "defc.h"
#include <sys/time.h>
@ -22,20 +22,23 @@ const char rcsid_joystick_driver_c[] = "@(#)$KmKId: joystick_driver.c,v 1.7 2002
# include <mmsystem.h>
#endif
extern int g_joystick_type; /* in paddles.c */
extern int g_paddle_button[];
extern int g_joystick_native_type1; /* in paddles.c */
extern int g_joystick_native_type2; /* in paddles.c */
extern int g_joystick_native_type; /* in paddles.c */
extern int g_paddle_buttons;
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_native_fd = -1;
int g_joystick_num_axes = 0;
int g_joystick_num_buttons = 0;
#ifdef __linux__
# define JOYSTICK_DEFINED
void
joystick_init()
{
@ -64,22 +67,24 @@ joystick_init()
joy_name, g_joystick_num_axes, g_joystick_num_buttons,
version);
g_joystick_type = JOYSTICK_LINUX;
g_joystick_fd = fd;
g_joystick_native_type1 = 1;
g_joystick_native_type2 = -1;
g_joystick_native_fd = fd;
for(i = 0; i < 4; i++) {
g_paddle_val[i] = 280;
g_paddle_button[i] = 1;
g_paddle_val[i] = 32767;
}
g_paddle_buttons = 0xc;
joystick_update();
joystick_update(0.0);
}
/* joystick_update_linux() called from paddles.c. Update g_paddle_val[] */
/* and g_paddle_button[] arrays with current information */
/* and g_paddle_buttons with current information */
void
joystick_update()
joystick_update(double dcycs)
{
struct js_event js; /* the linux joystick event record */
int mask;
int val;
int num;
int type;
@ -90,35 +95,42 @@ joystick_update()
/* 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);
ret = read(g_joystick_native_fd, &js, len);
if(ret != len) {
/* just get out */
return;
break;
}
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;
mask = 1 << num;
if(val) {
val = mask;
}
g_paddle_buttons = (g_paddle_buttons & ~mask) | 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;
/* val is -32767 to +32767 */
g_paddle_val[num] = val;
break;
}
}
if(i > 0) {
paddle_update_trigger_dcycs(dcycs);
}
}
void
joystick_update_button()
joystick_update_buttons()
{
}
#endif /* LINUX */
#else /* !__linux__ */
# ifdef _WIN32
#ifdef _WIN32
# define JOYSTICK_DEFINED
void
joystick_init()
{
@ -129,99 +141,120 @@ joystick_init()
// Check that there is a joystick device
if(joyGetNumDevs() <= 0) {
printf("--No joystick hardware detected\n");
printf("No joystick hardware detected\n");
g_joystick_native_type1 = -1;
g_joystick_native_type2 = -1;
return;
}
g_joystick_native_type1 = -1;
g_joystick_native_type2 = -1;
// 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;
g_joystick_native_type1 = JOYSTICKID1;
printf("Joystick #1 = %s\n", joycap.szPname);
g_joystick_native_type = JOYSTICKID1;
}
ret1 = joyGetPos(JOYSTICKID2, &info);
ret2 = joyGetDevCaps(JOYSTICKID2, &joycap, sizeof(joycap));
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
g_joystick_native_type2 = JOYSTICKID2;
printf("Joystick #2 = %s\n", joycap.szPname);
if(g_joystick_native_type < 0) {
g_joystick_native_type = JOYSTICKID2;
}
}
for(i = 0; i < 4; i++) {
g_paddle_val[i] = 280;
g_paddle_button[i] = 1;
g_paddle_val[i] = 32767;
}
g_paddle_buttons = 0xc;
joystick_update();
joystick_update(0.0);
}
void
joystick_update()
joystick_update(double dcycs)
{
JOYCAPS joycap;
JOYINFO info;
UINT id;
MMRESULT ret1, ret2;
id = JOYSTICKID1;
if(g_joystick_type == JOYSTICK_WIN32_2) {
id = JOYSTICKID2;
}
id = g_joystick_native_type;
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 /
g_paddle_val[0] = (info.wXpos - joycap.wXmin) * 32768 /
(joycap.wXmax - joycap.wXmin);
g_paddle_val[1] = (info.wYpos - joycap.wYmin) * 280 /
g_paddle_val[1] = (info.wYpos - joycap.wYmin) * 32768 /
(joycap.wYmax - joycap.wYmin);
g_paddle_button[0] = ((info.wButtons & JOY_BUTTON1) ? 1 : 0);
g_paddle_button[1] = ((info.wButtons & JOY_BUTTON2) ? 1 : 0);
if(info.wButtons & JOY_BUTTON1) {
g_paddle_buttons = g_paddle_buttons | 1;
} else {
g_paddle_buttons = g_paddle_buttons & (~1);
}
if(info.wButtons & JOY_BUTTON2) {
g_paddle_buttons = g_paddle_buttons | 2;
} else {
g_paddle_buttons = g_paddle_buttons & (~2);
}
paddle_update_trigger_dcycs(dcycs);
}
}
void
joystick_update_button()
joystick_update_buttons()
{
JOYINFOEX info;
UINT id;
id = JOYSTICKID1;
if(g_joystick_type == JOYSTICK_WIN32_2) {
id = JOYSTICKID2;
}
id = g_joystick_native_type;
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);
if(info.dwButtons & JOY_BUTTON1) {
g_paddle_buttons = g_paddle_buttons | 1;
} else {
g_paddle_buttons = g_paddle_buttons & (~1);
}
if(info.dwButtons & JOY_BUTTON2) {
g_paddle_buttons = g_paddle_buttons | 2;
} else {
g_paddle_buttons = g_paddle_buttons & (~2);
}
}
}
# else
#endif
#ifndef JOYSTICK_DEFINED
/* stubs for the routines */
void
joystick_init()
{
printf("No joy with joystick\n");
g_joystick_native_type1 = -1;
g_joystick_native_type2 = -1;
g_joystick_native_type = -1;
}
void
joystick_update()
joystick_update(double dcycs)
{
int i;
for(i = 0; i < 4; i++) {
g_paddle_val[i] = 32767;
}
g_paddle_buttons = 0xc;
}
void
joystick_update_button()
joystick_update_buttons()
{
}
# endif /* !WIN32 */
#endif

View File

@ -1,6 +1,6 @@
/************************************************************************/
/* KEGS: Apple //gs Emulator */
/* Copyright 2002 by Kent Dickey */
/* Copyright 2002-2004 by Kent Dickey */
/* */
/* This code is covered by the GNU GPL */
/* */
@ -8,7 +8,7 @@
/* 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 $";
const char rcsid_macdriver_c[] = "@(#)$KmKId: macdriver.c,v 1.24 2004-11-14 10:23:29-05 kentd Exp $";
// Quartz: CreateCGContextForPort vs QDBeginCGContext
@ -16,6 +16,7 @@ const char rcsid_macdriver_c[] = "@(#)$KmKId: macdriver.c,v 1.19 2004-03-23 17:2
// Use CGPointMake to get a point
#include <Carbon/Carbon.h>
#include <Quicktime/Quicktime.h>
#include "defc.h"
#include "protos_macdriver.h"
@ -25,6 +26,9 @@ const char rcsid_macdriver_c[] = "@(#)$KmKId: macdriver.c,v 1.19 2004-03-23 17:2
#define MAX_MAC_ARGS 128
WindowRef g_main_window;
WindowRef g_main_window_saved;
Rect g_main_window_saved_rect;
Ptr g_mac_fullscreen_state = 0;
int g_quit_seen = 0;
EventHandlerUPP g_quit_handler_UPP;
EventHandlerUPP g_dummy_event_handler_UPP;
@ -32,6 +36,7 @@ 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;
@ -43,6 +48,8 @@ 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 char *g_fatal_log_strs[];
extern int g_fatal_log;
extern word32 g_red_mask;
extern word32 g_green_mask;
@ -68,6 +75,13 @@ extern int g_send_sound_to_file;
extern int g_quit_sim_now;
extern int g_config_control_panel;
extern int g_video_act_width;
extern int g_video_act_height;
extern int g_video_act_margin_left;
extern int g_video_act_margin_right;
extern int g_video_act_margin_top;
extern int g_video_act_margin_bottom;
int g_auto_repeat_on = -1;
int g_x_shift_control_state = 0;
@ -99,8 +113,7 @@ 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;
extern int g_debug_file_fd;
/* HACK to debug startup issues when launched from Finder */
int
@ -110,7 +123,6 @@ printf(const char *fmt, ...)
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",
@ -118,8 +130,7 @@ printf(const char *fmt, ...)
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));
ret = kegs_vprintf(fmt, ap);
va_end(ap);
@ -140,27 +151,103 @@ quit_event_handler(EventHandlerCallRef call_ref, EventRef event, void *ignore)
}
void
show_alert(const char *str1, const char *str2, const char *str3, int num)
show_simple_alert(char *str1, char *str2, char *str3, int num)
{
char buf[256];
DialogRef alert;
DialogItemIndex out_item_hit;
CFStringRef cfstrref;
g_fatal_log_strs[0] = kegs_malloc_str(str1);
g_fatal_log_strs[1] = kegs_malloc_str(str2);
g_fatal_log_strs[2] = kegs_malloc_str(str3);
g_fatal_log = 3;
if(num != 0) {
snprintf(buf, 250, "%s%s%s: %d", str1, str2, str3, num);
} else {
snprintf(buf, 250, "%s%s%s", str1, str2, str3);
snprintf(buf, 250, ": %d", num);
g_fatal_log_strs[g_fatal_log++] = kegs_malloc_str(buf);
}
cfstrref = CFStringCreateWithCString(NULL, buf,
kCFStringEncodingMacRoman);
CreateStandardAlert(kAlertStopAlert, cfstrref, CFSTR("Click OK"),
NULL, &alert);
RunStandardAlert(alert, NULL, &out_item_hit);
x_show_alert(0, 0);
}
void
x_dialog_create_kegs_conf(const char *str)
{
char *path;
char tmp_buf[512];
int ret;
ret = x_show_alert(1, str);
if(ret) {
// Create empty file
path = "~/Library/KEGS";
snprintf(tmp_buf, 500, "mkdir -p %s", path);
system(tmp_buf);
snprintf(tmp_buf, 500, "touch %s/%s", path, str);
system(tmp_buf);
}
}
int
x_show_alert(int is_fatal, const char *str)
{
DialogRef alert;
DialogItemIndex out_item_hit;
CFStringRef cfstrref, cfstrref2;
CFStringRef okstrref;
AlertStdCFStringAlertParamRec alert_param;
OSStatus osstat;
char *bufptr, *buf2ptr;
int sum, len;
int i;
/* The dialog eats all events--including key-up events */
/* Call adb_all_keys_up() to prevent annoying key-repeat problems */
/* for instance, a key-down causes a dialog to appear--and the */
/* eats the key-up event...then as soon as the dialog goes, adb.c */
/* auto-repeat will repeat the key, and the dialog re-appears...*/
adb_all_keys_up();
sum = 20;
for(i = 0; i < g_fatal_log; i++) {
sum += strlen(g_fatal_log_strs[i]);
}
bufptr = malloc(sum);
buf2ptr = bufptr;
for(i = 0; i < g_fatal_log; i++) {
len = strlen(g_fatal_log_strs[i]);
len = MIN(len, sum);
len = MAX(len, 0);
memcpy(bufptr, g_fatal_log_strs[i], MIN(len, sum));
bufptr += len;
bufptr[0] = 0;
sum = sum - len;
}
cfstrref = CFStringCreateWithCString(NULL, buf2ptr,
kCFStringEncodingMacRoman);
printf("buf2ptr: :%s:\n", buf2ptr);
osstat = GetStandardAlertDefaultParams(&alert_param,
kStdCFStringAlertVersionOne);
if(str) {
// Provide an extra option--create a file
cfstrref2 = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
CFSTR("Create ~/Library/KEGS/%s"), str);
alert_param.otherText = cfstrref2;
}
okstrref = CFSTR("Click OK to continue");
if(is_fatal) {
okstrref = CFSTR("Clock OK to exit KEGS");
}
CreateStandardAlert(kAlertStopAlert, cfstrref, okstrref,
&alert_param, &alert);
out_item_hit = -1;
RunStandardAlert(alert, NULL, &out_item_hit);
printf("out_item_hit: %d\n", out_item_hit);
free(buf2ptr);
clear_fatal_logs(); /* free the fatal_log string memory */
return (out_item_hit >= 3);
}
pascal OSStatus
@ -182,13 +269,13 @@ my_cmd_handler( EventHandlerCallRef handlerRef, EventRef event, void *userdata)
osresult = noErr;
break;
case 'abou':
show_alert("KEGSMAC v", g_kegs_version_str,
show_simple_alert("KEGSMAC v", (char *)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;
cfg_toggle_config_panel();
osresult = noErr;
break;
case 'quit':
@ -386,7 +473,7 @@ check_input_events()
break;
}
if(err != noErr) {
printf("err: %d\n", (int)err);
printf("ReceiveNextEvent err: %d\n", (int)err);
break;
}
@ -488,8 +575,10 @@ check_input_events()
}
mac_warp_mouse();
} else {
g_mac_mouse_x = mouse_point.h -BASE_MARGIN_LEFT;
g_mac_mouse_y = mouse_point.v -BASE_MARGIN_TOP;
g_mac_mouse_x = mouse_point.h -
g_video_act_margin_left;
g_mac_mouse_y = mouse_point.v -
g_video_act_margin_top;
}
#if 0
@ -723,6 +812,8 @@ main(int argc, char* argv[])
}
// show_alert("About to show window", (int)g_main_window);
update_main_window_size();
update_window();
// The window was created hidden so show it.
@ -742,7 +833,7 @@ main(int argc, char* argv[])
CantCreateWindow:
CantSetMenuBar:
CantGetNibRef:
show_alert("ending", "", "error code", err);
show_simple_alert("ending", "", "error code", err);
return err;
}
@ -773,6 +864,9 @@ xdriver_end()
{
printf("xdriver_end\n");
if(g_fatal_log >= 0) {
x_show_alert(1, 0);
}
}
void
@ -932,6 +1026,12 @@ x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
void
x_push_done()
{
CGrafPtr window_port;
SetPortWindowPort(g_main_window);
window_port = GetWindowPort(g_main_window);
QDFlushPortBuffer(window_port, 0);
}
void
@ -953,3 +1053,73 @@ x_hide_pointer(int do_hide)
ShowCursor();
}
}
void
x_full_screen(int do_full)
{
WindowRef new_window;
short width, height;
OSErr ret;
width = 640;
height = 480;
if(do_full && (g_mac_fullscreen_state == 0)) {
g_main_window_saved = g_main_window;
GetWindowBounds(g_main_window, kWindowContentRgn,
&g_main_window_saved_rect);
ret = BeginFullScreen(&g_mac_fullscreen_state, 0,
&width, &height, &new_window, 0, 0);
printf("Ret beginfullscreen: %d\n", (int)ret);
printf("New width: %d, new height: %d\n", width, height);
if(ret == noErr) {
g_main_window = new_window;
} else {
g_mac_fullscreen_state = 0;
}
} else if(!do_full && (g_mac_fullscreen_state != 0)) {
ret = EndFullScreen(g_mac_fullscreen_state, 0);
printf("ret endfullscreen: %d\n", (int)ret);
g_main_window = g_main_window_saved;
g_mac_fullscreen_state = 0;
//InitCursor();
SetWindowBounds(g_main_window, kWindowContentRgn,
&g_main_window_saved_rect);
}
update_main_window_size();
ShowWindow(g_main_window);
BringToFront(g_main_window);
update_window();
}
void
update_main_window_size()
{
Rect win_rect;
int width, height;
int left, excess_height;
int top, bottom;
GetPortBounds(GetWindowPort(g_main_window), &win_rect);
width = win_rect.right - win_rect.left;
height = win_rect.bottom - win_rect.top;
g_video_act_width = width;
g_video_act_height = height;
left = MAX(0, (width - A2_WINDOW_WIDTH) / 2);
left = MIN(left, BASE_MARGIN_LEFT);
g_video_act_margin_left = left;
g_video_act_margin_right = left;
excess_height = (height - A2_WINDOW_HEIGHT) / 2;
bottom = MAX(0, excess_height / 2); // No less than 0
bottom = MIN(BASE_MARGIN_BOTTOM, bottom); // No more than 30
g_video_act_margin_bottom = bottom;
excess_height -= bottom;
top = MAX(0, excess_height);
top = MIN(BASE_MARGIN_TOP, top);
g_video_act_margin_top = top;
}

File diff suppressed because it is too large Load Diff

View File

@ -8,25 +8,52 @@
/* 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 $";
const char rcsid_paddles_c[] = "@(#)$KmKId: paddles.c,v 1.14 2004-10-19 14:52:36-04 kentd Exp $";
#include "defc.h"
extern int g_mouse_fifo_x[]; /* from adb.c */
extern int g_mouse_fifo_y[];
extern int g_mouse_raw_x; /* from adb.c */
extern int g_mouse_raw_y;
double g_paddle_trig_dcycs = 0.0;
int g_swap_paddles = 0;
int g_invert_paddles = 0;
int g_joystick_scale_factor_x = 0x100;
int g_joystick_scale_factor_y = 0x100;
int g_joystick_trim_amount_x = 0;
int g_joystick_trim_amount_y = 0;
int g_joystick_type = JOYSTICK_MOUSE;
int g_joystick_type = 0; /* 0 = Keypad Joystick */
int g_joystick_native_type1 = -1;
int g_joystick_native_type2 = -1;
int g_joystick_native_type = -1;
int g_paddle_button[4] = { 0, 0, 0, 0 };
/* g_paddle_button[0] = button 0, etc */
extern int g_paddle_buttons;
int g_paddle_val[4] = { 0, 0, 0, 0 };
/* g_paddle_val[0]: Joystick X coord, [1]:Y coord */
double g_paddle_dcycs[4] = { 0.0, 0.0, 0.0, 0.0 };
/* g_paddle_dcycs are the dcycs the paddle goes to 0 */
void
paddle_fixup_joystick_type()
{
/* If g_joystick_type points to an illegal value, change it */
if(g_joystick_type == 2) {
g_joystick_native_type = g_joystick_native_type1;
if(g_joystick_native_type1 < 0) {
g_joystick_type = 0;
}
}
if(g_joystick_type == 3) {
g_joystick_native_type = g_joystick_native_type2;
if(g_joystick_native_type2 < 0) {
g_joystick_type = 0;
}
}
}
void
paddle_trigger(double dcycs)
@ -35,75 +62,117 @@ paddle_trigger(double dcycs)
g_paddle_trig_dcycs = dcycs;
/* Determine what all the paddle values are right now */
paddle_fixup_joystick_type();
switch(g_joystick_type) {
case JOYSTICK_MOUSE:
case 0: /* Keypad Joystick */
paddle_trigger_keypad(dcycs);
break;
case 1: /* Mouse Joystick */
paddle_trigger_mouse(dcycs);
break;
case JOYSTICK_LINUX:
case JOYSTICK_WIN32_1:
case JOYSTICK_WIN32_2:
joystick_update();
default:
joystick_update(dcycs);
}
}
void
paddle_trigger_mouse(double dcycs)
{
int val_x;
int val_y;
int val_x, val_y;
int mouse_x, mouse_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;
}
mouse_x = g_mouse_raw_x;
mouse_y = g_mouse_raw_y;
/* mous_phys_x is 0->560, convert that to -32768 to + 32767 cyc */
/* So subtract 280 then mult by 117 */
val_x = (mouse_x - 280) * 117;
if(val_x > 280) {
val_x = 280;
}
if(val_y > 280) {
val_y = 280;
}
/* mous_phys_y is 0->384, convert that to -32768 to + 32767 cyc */
/* so subtract 192 then mult by 180 to overscale it a bit */
val_y = (mouse_y - 192) * 180;
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;
g_paddle_val[2] = 32767;
g_paddle_val[3] = 32767;
g_paddle_buttons |= 0xc;
paddle_update_trigger_dcycs(dcycs);
}
int
read_paddles(int paddle, double dcycs)
void
paddle_trigger_keypad(double dcycs)
{
int get_y;
int val_x, val_y;
val_x = adb_get_keypad_xy(get_y=0);
val_y = adb_get_keypad_xy(get_y=1);
/* val_x and val_y are already scale -32768 to +32768 */
g_paddle_val[0] = val_x;
g_paddle_val[1] = val_y;
g_paddle_val[2] = 32767;
g_paddle_val[3] = 32767;
g_paddle_buttons |= 0xc;
paddle_update_trigger_dcycs(dcycs);
}
void
paddle_update_trigger_dcycs(double dcycs)
{
double trig_dcycs;
int val;
int paddle_num;
int scale, trim;
int i;
/* This routine is called by any read to $c064-$c067 */
if(g_swap_paddles) {
paddle = paddle ^ 1;
for(i = 0; i < 4; i++) {
paddle_num = i;
if(g_swap_paddles) {
paddle_num = i ^ 1;
}
val = g_paddle_val[paddle_num];
if(g_invert_paddles) {
val = -val;
}
/* convert -32768 to +32768 into 0->2816.0 cycles (the */
/* paddle delay const) */
/* First multiply by the scale factor to adjust range */
if(paddle_num & 1) {
scale = g_joystick_scale_factor_y;
trim = g_joystick_trim_amount_y;
} else {
scale = g_joystick_scale_factor_x;
trim = g_joystick_trim_amount_x;
}
#if 0
if(i == 0) {
printf("val was %04x(%d) * scale %03x = %d\n",
val, val, scale, (val*scale)>>16);
}
#endif
val = val * scale >> 16;
/* Val is now from -128 to + 128 since scale is */
/* 256=1.0, 128 = 0.5 */
val = val + 128 + trim;
if(val >= 255) {
val = 280; /* increase range */
}
trig_dcycs = dcycs + (val * 11.04);
g_paddle_dcycs[i] = trig_dcycs;
}
}
paddle = paddle & 3;
int
read_paddles(double dcycs, int paddle)
{
double trig_dcycs;
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);
trig_dcycs = g_paddle_dcycs[paddle & 3];
if(dcycs < trig_dcycs) {
return 0x80;
@ -112,3 +181,9 @@ read_paddles(int paddle, double dcycs)
}
}
void
paddle_update_buttons()
{
paddle_fixup_joystick_type();
joystick_update_buttons();
}

View File

@ -9,10 +9,13 @@
/************************************************************************/
#ifdef INCLUDE_RCSID_C
const char rcsid_protos_h[] = "@(#)$KmKId: protos.h,v 1.173 2004-03-23 17:26:19-05 kentd Exp $";
const char rcsid_protos_h[] = "@(#)$KmKId: protos.h,v 1.188 2004-12-06 19:08:34-05 kentd Exp $";
#endif
/* xdriver.c and macdriver.c and windriver.c */
int x_show_alert(int is_fatal, const char *str);
int win_nonblock_read_stdin(int fd, char *bufptr, int len);
void x_dialog_create_kegs_conf(const char *str);
void update_color_array(int col_num, int a2_color);
void set_border_color(int val);
void x_update_physical_colormap(void);
@ -31,6 +34,7 @@ void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
void x_push_done();
void x_hide_pointer(int);
void x_get_kimage(Kimage *kimage_ptr);
void x_full_screen(int do_full);
/* test65.c */
void do_gen_test(int got_num, int base_seed);
@ -52,6 +56,7 @@ 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);
void set_memory24_c(word32 addr, word32 val, int cycs);
int enter_engine(Engine_reg *ptr);
void clr_halt_act(void);
@ -60,19 +65,19 @@ 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_fill_readbuf(int port, int space_left, 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_fill_readbuf(int port, int space_left, 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);
void joystick_update(double dcycs);
void joystick_update_buttons(void);
/* END_HDR */
@ -103,8 +108,10 @@ 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 adb_get_keypad_xy(int get_y);
int update_mouse(int x, int y, int button_states, int buttons_valid);
int mouse_read_c024(double dcycs);
void mouse_compress_fifo(double dcycs);
void adb_key_event(int a2code, int is_up);
word32 adb_read_c000(void);
word32 adb_access_c010(void);
@ -114,6 +121,7 @@ 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_all_keys_up(void);
void adb_kbd_repeat_off(void);
@ -127,9 +135,6 @@ 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);
@ -141,10 +146,12 @@ void do_clock_data(void);
void config_init_menus(Cfg_menu *menuptr);
void config_init(void);
void cfg_exit(void);
void cfg_toggle_config_panel(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_load_roms(void);
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);
@ -166,7 +173,7 @@ 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_parse_menu(Cfg_menu *menuptr, 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);
@ -178,6 +185,7 @@ 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_update_ptr(char *str);
void cfg_file_selected(void);
void cfg_file_handle_key(int key);
void config_control_panel(void);
@ -200,7 +208,9 @@ 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 dis_do_memmove(void);
void dis_do_pattern_search(void);
void dis_do_compare(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);
@ -216,7 +226,7 @@ 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_to_empty_writebuf(int port, double dcycs);
void scc_try_fill_readbuf(int port, double dcycs);
void scc_update(double dcycs);
void do_scc_event(int type, double dcycs);
@ -236,6 +246,8 @@ 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_readbufv(int port, double dcycs, const char *fmt, ...);
void scc_transmit(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);
@ -243,10 +255,23 @@ void scc_write_data(int port, word32 val, double dcycs);
/* scc_socket_driver.c */
void scc_socket_init(int port);
void scc_socket_maybe_open_incoming(int port, double dcycs);
void scc_socket_open_outgoing(int port, double dcycs);
void scc_socket_make_nonblock(int port, double dcycs);
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);
void scc_socket_close(int port, int full_close, double dcycs);
void scc_accept_socket(int port, double dcycs);
void scc_socket_telnet_reqs(int port, double dcycs);
void scc_socket_fill_readbuf(int port, int space_left, double dcycs);
void scc_socket_recvd_char(int port, int c, double dcycs);
void scc_socket_empty_writebuf(int port, double dcycs);
void scc_socket_modem_write(int port, int c, double dcycs);
void scc_socket_do_cmd_str(int port, double dcycs);
void scc_socket_send_modem_code(int port, int code, double dcycs);
void scc_socket_modem_hangup(int port, double dcycs);
void scc_socket_modem_connect(int port, double dcycs);
void scc_socket_modem_do_ring(int port, double dcycs);
void scc_socket_do_answer(int port, double dcycs);
/* scc_windriver.c */
@ -257,6 +282,7 @@ void scc_socket_empty_writebuf(int port);
/* iwm.c */
void iwm_init_drive(Disk *dsk, int smartport, int drive, int disk_525);
void disk_set_num_tracks(Disk *dsk, int num_tracks);
void iwm_init(void);
void iwm_reset(void);
void draw_iwm_status(int line, char *buf);
@ -268,7 +294,6 @@ 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);
@ -279,20 +304,20 @@ 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 iwm_denib_track525(Disk *dsk, Trk *trk, int qtr_track, byte *outbuf);
int iwm_denib_track35(Disk *dsk, Trk *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 iwm_nibblize_track_nib525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track);
void iwm_nibblize_track_525(Disk *dsk, Trk *trk, byte *track_buf, int qtr_track);
void iwm_nibblize_track_35(Disk *dsk, Trk *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);
void iwm_show_a_track(Trk *trk);
/* joystick_driver.c */
@ -334,9 +359,13 @@ int read_vid_counters(int loc, double dcycs);
/* paddles.c */
void paddle_fixup_joystick_type(void);
void paddle_trigger(double dcycs);
void paddle_trigger_mouse(double dcycs);
int read_paddles(int paddle, double dcycs);
void paddle_trigger_keypad(double dcycs);
void paddle_update_trigger_dcycs(double dcycs);
int read_paddles(double dcycs, int paddle);
void paddle_update_buttons(void);
/* sim65816.c */
@ -351,11 +380,12 @@ 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);
byte *memalloc_align(int size, int skip_amt, void **alloc_ptr);
void memory_ptr_init(void);
int kegsmain(int argc, char **argv);
void load_roms_init_memory(void);
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 setup_kegs_file(char *outname, int maxlen, int ok_if_missing, int can_create_file, const char **name_ptr);
void initialize_events(void);
void check_for_one_event_type(int type);
void add_event_entry(double dcycs, int type);
@ -371,8 +401,8 @@ 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 add_irq(word32 irq_mask);
void remove_irq(word32 irq_mask);
void take_irq(int is_it_brk);
void show_dtime_array(void);
void update_60hz(double dcycs, double dtime_now);
@ -388,6 +418,11 @@ void do_wdm(word32 arg);
void do_wai(void);
void do_stp(void);
void size_fail(int val, word32 v1, word32 v2);
int fatal_printf(const char *fmt, ...);
int kegs_vprintf(const char *fmt, va_list ap);
void must_write(int fd, char *bufptr, int len);
void clear_fatal_logs(void);
char *kegs_malloc_str(char *in_str);
/* smartport.c */
@ -433,8 +468,6 @@ 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);
@ -474,6 +507,7 @@ 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_check_input_events(void);
void video_update_through_line(int line);
void video_refresh_lines(int st_line, int num_lines, int must_reparse);
void refresh_border(void);
@ -492,4 +526,5 @@ 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);
word32 float_bus(double dcycs);

View File

@ -9,7 +9,7 @@
/************************************************************************/
#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 $";
const char rcsid_protos_engine_c_h[] = "@(#)$KmKId: protos_engine_c.h,v 1.11 2004-10-11 22:48:16-04 kentd Exp $";
#endif
/* END_HDR */
@ -20,7 +20,7 @@ word32 get_memory8_io_stub(word32 addr, byte *stat, double *fcycs_ptr, double fp
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_memory16_pieces_stub(word32 addr, word32 val, double *fcycs_ptr, double fplus_1, double fplus_x_m1, 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);

View File

@ -8,13 +8,15 @@
/* 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 $";
const char rcsid_protos_mac_h[] = "@(#)$KmKId: protos_macdriver.h,v 1.11 2004-11-14 10:24:03-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);
void show_simple_alert(char *str1, char *str2, char *str3, int num);
void x_dialog_create_kegs_conf(const char *str);
int x_show_alert(int is_fatal, const char *str);
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);
@ -37,4 +39,6 @@ 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);
void x_full_screen(int do_full);
void update_main_window_size(void);

View File

@ -8,29 +8,38 @@
/* 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 $";
const char rcsid_protos_x_h[] = "@(#)$KmKId: protos_xdriver.h,v 1.19 2004-11-15 16:24:13-05 kentd Exp $";
/* END_HDR */
/* xdriver.c */
int main(int argc, char **argv);
void x_dialog_create_kegs_conf(const char *str);
int x_show_alert(int is_fatal, const char *str);
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);
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 x_badpipe(int signum);
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);
void x_get_kimage(Kimage *kimage_ptr);
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 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);
int x_update_mouse(int raw_x, int raw_y, int button_states, int buttons_valid);
void check_input_events(void);
void x_hide_pointer(int do_hide);
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);
void x_full_screen(int do_full);

208
src/scc.c
View File

@ -8,7 +8,7 @@
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_scc_c[] = "@(#)$KmKId: scc.c,v 1.38 2003-11-20 23:50:32-05 kentd Exp $";
const char rcsid_scc_c[] = "@(#)$KmKId: scc.c,v 1.44 2004-12-03 17:33:40-05 kentd Exp $";
#include "defc.h"
@ -17,9 +17,10 @@ extern int g_code_yellow;
extern double g_cur_dcycs;
extern int g_raw_serial;
extern int g_serial_out_masking;
extern int g_irq_pending;
/* my scc port 0 == channel A = slot 1 */
/* port 1 == channel B = slot 2 */
/* my scc port 0 == channel A = slot 1 = c039/c03b */
/* port 1 == channel B = slot 2 = c038/c03a */
#include "scc.h"
#define SCC_R14_DPLL_SOURCE_BRG 0x100
@ -45,23 +46,39 @@ void
scc_init()
{
Scc *scc_ptr;
int i;
int i, j;
for(i = 0; i < 2; i++) {
scc_ptr = &(scc_stat[i]);
scc_ptr->accfd = -1;
scc_ptr->sockfd = -1;
scc_ptr->socket_state = -1;
scc_ptr->rdwrfd = -1;
scc_ptr->state = 0;
scc_ptr->host_handle = 0;
scc_ptr->host_handle2 = 0;
scc_ptr->int_pending_rx = 0;
scc_ptr->int_pending_tx = 0;
scc_ptr->int_pending_zerocnt = 0;
scc_ptr->br_event_pending = 0;
scc_ptr->rx_event_pending = 0;
scc_ptr->tx_event_pending = 0;
scc_ptr->char_size = 8;
scc_ptr->baud_rate = 9600;
scc_ptr->telnet_mode = 0;
scc_ptr->telnet_iac = 0;
scc_ptr->out_char_dcycs = 0.0;
scc_ptr->socket_num_rings = 0;
scc_ptr->socket_last_ring_dcycs = 0;
scc_ptr->modem_mode = 0;
scc_ptr->modem_dial_or_acc_mode = 0;
scc_ptr->modem_plus_mode = 0;
scc_ptr->modem_s0_val = 0;
scc_ptr->modem_cmd_len = 0;
scc_ptr->modem_cmd_str[0] = 0;
for(j = 0; j < 2; j++) {
scc_ptr->telnet_local_mode[j] = 0;
scc_ptr->telnet_remote_mode[j] = 0;
scc_ptr->telnet_reqwill_mode[j] = 0;
scc_ptr->telnet_reqdo_mode[j] = 0;
}
}
scc_reset();
@ -83,6 +100,7 @@ scc_reset()
scc_ptr->in_wrptr = 0;
scc_ptr->out_rdptr = 0;
scc_ptr->out_wrptr = 0;
scc_ptr->dcd = 0;
scc_ptr->wantint_rx = 0;
scc_ptr->wantint_tx = 0;
scc_ptr->wantint_zerocnt = 0;
@ -308,7 +326,7 @@ scc_port_init(int port)
}
void
scc_try_to_empty_writebuf(int port)
scc_try_to_empty_writebuf(int port, double dcycs)
{
Scc *scc_ptr;
int state;
@ -329,7 +347,7 @@ scc_try_to_empty_writebuf(int port)
scc_serial_win_empty_writebuf(port);
#endif
} else if(state == 1) {
scc_socket_empty_writebuf(port);
scc_socket_empty_writebuf(port, dcycs);
}
}
@ -337,10 +355,22 @@ void
scc_try_fill_readbuf(int port, double dcycs)
{
Scc *scc_ptr;
int space_used, space_left;
int state;
scc_ptr = &(scc_stat[port]);
state = scc_ptr->state;
space_used = scc_ptr->in_wrptr - scc_ptr->in_rdptr;
if(space_used < 0) {
space_used += SCC_INBUF_SIZE;
}
space_left = (7*SCC_INBUF_SIZE/8) - space_used;
if(space_left < 1) {
/* Buffer is pretty full, don't try to get more */
return;
}
#if 0
if(scc_ptr->read_called_this_vbl) {
return;
@ -351,13 +381,13 @@ scc_try_fill_readbuf(int port, double dcycs)
if(state == 2) {
#if defined(MAC)
scc_serial_mac_fill_readbuf(port, dcycs);
scc_serial_mac_fill_readbuf(port, space_left, dcycs);
#endif
#if defined(_WIN32)
scc_serial_win_fill_readbuf(port, dcycs);
scc_serial_win_fill_readbuf(port, space_left, dcycs);
#endif
} else if(state == 1) {
scc_socket_fill_readbuf(port, dcycs);
scc_socket_fill_readbuf(port, space_left, dcycs);
}
}
@ -370,8 +400,8 @@ scc_update(double dcycs)
scc_stat[0].read_called_this_vbl = 0;
scc_stat[1].read_called_this_vbl = 0;
scc_try_to_empty_writebuf(0);
scc_try_to_empty_writebuf(1);
scc_try_to_empty_writebuf(0, dcycs);
scc_try_to_empty_writebuf(1, dcycs);
scc_try_fill_readbuf(0, dcycs);
scc_try_fill_readbuf(1, dcycs);
@ -423,6 +453,9 @@ show_scc_state()
scc_ptr->reg[j], scc_ptr->reg[j+1],
scc_ptr->reg[j+2], scc_ptr->reg[j+3]);
}
printf("state: %d, accfd: %d, rdwrfd: %d, host:%p, host2:%p\n",
scc_ptr->state, scc_ptr->accfd, scc_ptr->rdwrfd,
scc_ptr->host_handle, scc_ptr->host_handle2);
printf("in_rdptr: %04x, in_wr:%04x, out_rd:%04x, out_wr:%04x\n",
scc_ptr->in_rdptr, scc_ptr->in_wrptr,
scc_ptr->out_rdptr, scc_ptr->out_wrptr);
@ -430,9 +463,6 @@ show_scc_state()
scc_ptr->rx_queue_depth, scc_ptr->rx_queue[0],
scc_ptr->rx_queue[1], scc_ptr->rx_queue[2],
scc_ptr->rx_queue[3]);
printf("int_pendings: rx:%d, tx:%d, zc:%d\n",
scc_ptr->int_pending_rx, scc_ptr->int_pending_tx,
scc_ptr->int_pending_zerocnt);
printf("want_ints: rx:%d, tx:%d, zc:%d\n",
scc_ptr->wantint_rx, scc_ptr->wantint_tx,
scc_ptr->wantint_zerocnt);
@ -446,6 +476,18 @@ show_scc_state()
printf("char_size: %d, baud_rate: %d, mode: %d\n",
scc_ptr->char_size, scc_ptr->baud_rate,
scc_ptr->mode);
printf("modem_dial_mode:%d, telnet_mode:%d iac:%d, "
"modem_cmd_len:%d\n", scc_ptr->modem_dial_or_acc_mode,
scc_ptr->telnet_mode, scc_ptr->telnet_iac,
scc_ptr->modem_cmd_len);
printf("telnet_loc_modes:%08x %08x, telnet_rem_motes:"
"%08x %08x\n", scc_ptr->telnet_local_mode[0],
scc_ptr->telnet_local_mode[1],
scc_ptr->telnet_remote_mode[0],
scc_ptr->telnet_remote_mode[1]);
printf("modem_mode:%08x plus_mode: %d, out_char_dcycs: %f\n",
scc_ptr->modem_mode, scc_ptr->modem_plus_mode,
scc_ptr->out_char_dcycs);
}
}
@ -518,7 +560,11 @@ scc_read_reg(int port, double dcycs)
switch(regnum) {
case 0:
case 4:
ret = 0x68; /* 0x44 = no dcd, no cts,0x6c = dcd ok, cts ok*/
ret = 0x60; /* 0x44 = no dcd, no cts,0x6c = dcd ok, cts ok*/
if(scc_ptr->dcd) {
ret |= 0x08;
}
ret |= 0x8; /* HACK HACK */
if(scc_ptr->rx_queue_depth) {
ret |= 0x01;
}
@ -559,12 +605,7 @@ scc_read_reg(int port, double dcycs)
case 3:
case 7:
if(port == 0) {
ret = (scc_stat[1].int_pending_zerocnt) |
(scc_stat[1].int_pending_tx << 1) |
(scc_stat[1].int_pending_rx << 2) |
(scc_stat[0].int_pending_zerocnt << 3) |
(scc_stat[0].int_pending_tx << 4) |
(scc_stat[0].int_pending_rx << 5);
ret = (g_irq_pending & 0x3f);
} else {
ret = 0;
}
@ -608,6 +649,7 @@ scc_write_reg(int port, word32 val, double dcycs)
Scc *scc_ptr;
word32 old_val;
word32 changed_bits;
word32 irq_mask;
int regnum;
int mode;
int tmp1;
@ -654,11 +696,16 @@ scc_write_reg(int port, word32 val, double dcycs)
case 0x6: /* reset rr1 bits */
break;
case 0x7: /* reset highest pri int pending */
if(scc_ptr->int_pending_rx) {
irq_mask = g_irq_pending;
if(port == 0) {
/* Move SCC0 ints into SCC1 positions */
irq_mask = irq_mask >> 3;
}
if(irq_mask & IRQ_PENDING_SCC1_RX) {
scc_clr_rx_int(port);
} else if(scc_ptr->int_pending_tx) {
} else if(irq_mask & IRQ_PENDING_SCC1_TX) {
scc_clr_tx_int(port);
} else if(scc_ptr->int_pending_zerocnt) {
} else if(irq_mask & IRQ_PENDING_SCC1_ZEROCNT) {
scc_clr_zerocnt_int(port);
}
break;
@ -673,7 +720,7 @@ scc_write_reg(int port, word32 val, double dcycs)
break;
case 0x1: /* reset rx crc */
case 0x2: /* reset tx crc */
halt_printf("Wr c03%x to wr0 of %02x!\n", 8+port, val);
printf("Wr c03%x to wr0 of %02x!\n", 8+port, val);
break;
case 0x3: /* reset tx underrun/eom latch */
/* if no extern status pending, or being reset now */
@ -850,34 +897,48 @@ void
scc_evaluate_ints(int port)
{
Scc *scc_ptr;
word32 irq_add_mask, irq_remove_mask;
int mie;
scc_ptr = &(scc_stat[port]);
mie = scc_stat[0].reg[9] & 0x8; /* Master int en */
if(mie && scc_ptr->wantint_rx && !scc_ptr->int_pending_rx) {
scc_ptr->int_pending_rx = 1;
add_irq();
if(!mie) {
/* There can be no interrupts if MIE=0 */
remove_irq(IRQ_PENDING_SCC1_RX | IRQ_PENDING_SCC1_TX |
IRQ_PENDING_SCC1_ZEROCNT |
IRQ_PENDING_SCC0_RX | IRQ_PENDING_SCC0_TX |
IRQ_PENDING_SCC0_ZEROCNT);
return;
}
if(scc_ptr->int_pending_rx && (!mie || !scc_ptr->wantint_rx)) {
scc_ptr->int_pending_rx = 0;
remove_irq();
irq_add_mask = 0;
irq_remove_mask = 0;
if(scc_ptr->wantint_rx) {
irq_add_mask |= IRQ_PENDING_SCC1_RX;
} else {
irq_remove_mask |= IRQ_PENDING_SCC1_RX;
}
if(mie && scc_ptr->wantint_tx && !scc_ptr->int_pending_tx) {
scc_ptr->int_pending_tx = 1;
add_irq();
if(scc_ptr->wantint_tx) {
irq_add_mask |= IRQ_PENDING_SCC1_TX;
} else {
irq_remove_mask |= IRQ_PENDING_SCC1_TX;
}
if(scc_ptr->int_pending_tx && (!mie || !scc_ptr->wantint_tx)) {
scc_ptr->int_pending_tx = 0;
remove_irq();
if(scc_ptr->wantint_zerocnt) {
irq_add_mask |= IRQ_PENDING_SCC1_ZEROCNT;
} else {
irq_remove_mask |= IRQ_PENDING_SCC1_ZEROCNT;
}
if(mie && scc_ptr->wantint_zerocnt && !scc_ptr->int_pending_zerocnt) {
scc_ptr->int_pending_zerocnt = 1;
add_irq();
if(port == 0) {
/* Port 1 is in bits 0-2 and port 0 is in bits 3-5 */
irq_add_mask = irq_add_mask << 3;
irq_remove_mask = irq_remove_mask << 3;
}
if(scc_ptr->int_pending_zerocnt && (!mie || !scc_ptr->wantint_zerocnt)){
scc_ptr->int_pending_zerocnt = 0;
remove_irq();
if(irq_add_mask) {
add_irq(irq_add_mask);
}
if(irq_remove_mask) {
remove_irq(irq_remove_mask);
}
}
@ -1044,11 +1105,33 @@ scc_add_to_readbuf(int port, word32 val, double dcycs)
}
void
scc_add_to_writebuf(int port, word32 val, double dcycs)
scc_add_to_readbufv(int port, double dcycs, const char *fmt, ...)
{
va_list ap;
char *bufptr;
int ret, len, c;
int i;
va_start(ap, fmt);
bufptr = malloc(4096);
bufptr[0] = 0;
ret = vsnprintf(bufptr, 4090, fmt, ap);
len = strlen(bufptr);
for(i = 0; i < len; i++) {
c = bufptr[i];
if(c == 0x0a) {
scc_add_to_readbuf(port, 0x0d, dcycs);
}
scc_add_to_readbuf(port, c, dcycs);
}
va_end(ap);
}
void
scc_transmit(int port, word32 val, double dcycs)
{
Scc *scc_ptr;
int out_wrptr;
int out_wrptr_next;
int out_rdptr;
scc_ptr = &(scc_stat[port]);
@ -1081,6 +1164,31 @@ scc_add_to_writebuf(int port, word32 val, double dcycs)
val = val & 0x7f;
}
scc_add_to_writebuf(port, val, dcycs);
}
void
scc_add_to_writebuf(int port, word32 val, double dcycs)
{
Scc *scc_ptr;
int out_wrptr;
int out_wrptr_next;
int out_rdptr;
scc_ptr = &(scc_stat[port]);
/* See if port initialized, if not, do so now */
if(scc_ptr->state == 0) {
scc_port_init(port);
}
if(scc_ptr->state < 0) {
/* No working serial port, just toss it and go */
return;
}
out_wrptr = scc_ptr->out_wrptr;
out_rdptr = scc_ptr->out_rdptr;
out_wrptr_next = (out_wrptr + 1) & (SCC_OUTBUF_SIZE - 1);
if(out_wrptr_next != out_rdptr) {
scc_ptr->out_buf[out_wrptr] = val;
@ -1144,9 +1252,9 @@ scc_write_data(int port, word32 val, double dcycs)
/* local loopback! */
scc_add_to_readbuf(port, val, dcycs);
} else {
scc_add_to_writebuf(port, val, dcycs);
scc_transmit(port, val, dcycs);
}
scc_try_to_empty_writebuf(port);
scc_try_to_empty_writebuf(port, dcycs);
scc_maybe_tx_event(port, dcycs);
}

View File

@ -9,30 +9,41 @@
/************************************************************************/
#ifdef INCLUDE_RCSID_C
const char rcsid_scc_h[] = "@(#)$KmKId: scc.h,v 1.12 2003-11-21 00:27:00-05 kentd Exp $";
const char rcsid_scc_h[] = "@(#)$KmKId: scc.h,v 1.17 2004-12-03 14:03:12-05 kentd Exp $";
#endif
#include <ctype.h>
#ifdef _WIN32
# include <winsock.h>
# include <winsock2.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <netdb.h>
#endif
#if defined(HPUX) || defined(__linux__) || defined(SOLARIS) || defined(MAC) || defined(__MACH__)
#if defined(HPUX) || defined(__linux__) || defined(SOLARIS) || defined(MAC) || defined(__MACH__) || defined(_WIN32)
# 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 */
#define SCC_INBUF_SIZE 512 /* must be a power of 2 */
#define SCC_OUTBUF_SIZE 512 /* must be a power of 2 */
#define SCC_MODEM_MAX_CMD_STR 128
#ifndef SOCKET
# define SOCKET word32 /* for non-windows */
#endif
STRUCT(Scc) {
int port;
int state;
int accfd;
SOCKET sockfd;
int socket_state;
int rdwrfd;
void *host_handle;
void *host_handle2;
@ -60,9 +71,7 @@ STRUCT(Scc) {
int wantint_rx;
int wantint_tx;
int wantint_zerocnt;
int int_pending_rx;
int int_pending_tx;
int int_pending_zerocnt;
int dcd;
double br_dcycs;
double tx_dcycs;
@ -74,5 +83,24 @@ STRUCT(Scc) {
int char_size;
int baud_rate;
double out_char_dcycs;
int socket_num_rings;
int socket_last_ring_dcycs;
word32 modem_mode;
int modem_dial_or_acc_mode;
int modem_plus_mode;
int modem_s0_val;
int telnet_mode;
int telnet_iac;
word32 telnet_local_mode[2];
word32 telnet_remote_mode[2];
word32 telnet_reqwill_mode[2];
word32 telnet_reqdo_mode[2];
int modem_cmd_len;
byte modem_cmd_str[SCC_MODEM_MAX_CMD_STR + 5];
};
#define SCCMODEM_NOECHO 0x0001
#define SCCMODEM_NOVERBOSE 0x0002

View File

@ -8,7 +8,7 @@
/* 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 $";
const char rcsid_scc_macdriver_c[] = "@(#)$KmKId: scc_macdriver.c,v 1.5 2004-11-25 13:32:51-05 kentd Exp $";
/* This file contains the Mac serial calls */
@ -35,7 +35,8 @@ scc_serial_mac_init(int port)
scc_ptr->state = 0; /* mark as uninitialized */
sprintf(&str_buf[0], "/dev/tty.USA19QW11P1.1");
/*sprintf(&str_buf[0], "/dev/tty.USA19QW11P1.1"); */
sprintf(&str_buf[0], "/dev/tty.USA19H181P1.1");
/* HACK: fix this... */
fd = open(&str_buf[0], O_RDWR | O_NONBLOCK);
@ -129,7 +130,7 @@ scc_serial_mac_change_params(int port)
}
void
scc_serial_mac_fill_readbuf(int port, double dcycs)
scc_serial_mac_fill_readbuf(int port, int space_left, double dcycs)
{
byte tmp_buf[256];
Scc *scc_ptr;
@ -145,7 +146,8 @@ scc_serial_mac_fill_readbuf(int port, double dcycs)
}
/* Try reading some bytes */
ret = read(fd, tmp_buf, 256);
space_left = MIN(space_left, 256);
ret = read(fd, tmp_buf, space_left);
if(ret > 0) {
for(i = 0; i < ret; i++) {

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
/* 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 $";
const char rcsid_scc_windriver_c[] = "@(#)$KmKId: scc_windriver.c,v 1.4 2004-11-19 02:00:46-05 kentd Exp $";
/* This file contains the Win32 COM1/COM2 calls */
@ -151,7 +151,7 @@ scc_serial_win_change_params(int port)
}
void
scc_serial_win_fill_readbuf(int port, double dcycs)
scc_serial_win_fill_readbuf(int port, int space_left, double dcycs)
{
byte tmp_buf[256];
Scc *scc_ptr;
@ -168,7 +168,8 @@ scc_serial_win_fill_readbuf(int port, double dcycs)
}
/* Try reading some bytes */
ret = ReadFile(host_handle, tmp_buf, 256, &bytes_read, NULL);
space_left = MIN(256, space_left);
ret = ReadFile(host_handle, tmp_buf, space_left, &bytes_read, NULL);
if(ret == 0) {
printf("ReadFile ret 0\n");

View File

@ -8,7 +8,7 @@
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_sim65816_c[] = "@(#)$KmKId: sim65816.c,v 1.346 2004-03-23 17:26:10-05 kentd Exp $";
const char rcsid_sim65816_c[] = "@(#)$KmKId: sim65816.c,v 1.367 2004-11-22 02:39:26-05 kentd Exp $";
#include <math.h>
@ -16,13 +16,16 @@ const char rcsid_sim65816_c[] = "@(#)$KmKId: sim65816.c,v 1.346 2004-03-23 17:26
#include "defc.h"
#undef INCLUDE_RCSID_C
#define PC_LOG_LEN (8*1024)
char g_argv0_path[256] = "./";
const char *g_kegs_default_paths[] = { "", "./", "${HOME}/",
"${HOME}/Library/KEGS/",
"${0}/Contents/Resources/", "/usr/local/lib/",
"/usr/local/kegs/", "/usr/local/lib/kegs/", "/usr/share/kegs/",
"/usr/share/", "/var/lib/", "/usr/lib/", "/lib/", "/etc/",
"/etc/kegs/", "${0}/", 0 };
"/var/lib/", "/usr/lib/kegs/", "${0}/", 0 };
#define MAX_EVENTS 64
@ -38,26 +41,18 @@ const char *g_kegs_default_paths[] = { "", "./", "${HOME}/",
extern int g_stepping;
extern int statereg;
extern int g_c068_statereg;
extern int g_cur_a2_stat;
extern int wrdefram;
extern int int_crom[8];
extern int g_c08x_wrdefram;
extern int g_c02d_int_crom;
extern int shadow_text;
extern int shadow_reg;
extern int speed_fast;
extern word32 g_slot_motor_detect;
extern int g_c035_shadow_reg;
extern int g_c036_val_speed;
extern int g_c023_val;
extern int c023_1sec_int_irq_pending;
extern int c023_scan_int_irq_pending;
extern int c041_en_25sec_ints;
extern int c041_en_vbl_ints;
extern int g_c041_val;
extern int g_c046_val;
extern int c046_25sec_irq_pend;
extern int c046_vbl_irq_pending;
extern int g_zipgs_reg_c059;
extern int g_zipgs_reg_c05a;
extern int g_zipgs_reg_c05b;
@ -71,9 +66,6 @@ extern int defs_instr_end_16;
extern int op_routs_start;
extern int op_routs_end;
extern int updated_mod_latch;
extern int capslock_key_down;
Engine_reg engine;
extern word32 table8[];
extern word32 table16[];
@ -83,7 +75,7 @@ extern byte doc_ram[];
extern int g_iwm_motor_on;
extern int g_fast_disk_emul;
extern int g_slow_525_emul_wr;
extern int g_apple35_sel;
extern int g_c031_disk35;
extern int g_config_control_panel;
extern int g_audio_enable;
@ -94,7 +86,8 @@ void U_STACK_TRACE();
double g_fcycles_stop = 0.0;
int halt_sim = 0;
int enter_debug = 0;
int g_rom_version = 0;
int g_rom_version = -1;
int g_user_halt_bad = 0;
int g_halt_on_bad_read = 0;
int g_ignore_bad_acc = 1;
int g_ignore_halts = 1;
@ -102,15 +95,12 @@ int g_code_red = 0;
int g_code_yellow = 0;
int g_use_alib = 0;
int g_raw_serial = 1;
int g_iw2_emul = 0;
int g_serial_out_masking = 0;
int g_serial_modem[2] = { 0, 1 };
int g_config_iwm_vbl_count = 0;
const char g_kegs_version_str[] = "0.86";
#if 0
const double g_drecip_cycles_in_16ms = (1.0/(DCYCS_IN_16MS));
const double g_dcycles_in_16ms = DCYCS_IN_16MS;
#endif
const char g_kegs_version_str[] = "0.91";
#define START_DCYCS (0.0)
@ -122,7 +112,8 @@ double g_dadjcycs = 0.0;
int g_wait_pending = 0;
int g_irq_pending = 0;
int g_stp_pending = 0;
extern int g_irq_pending;
int g_num_irq = 0;
int g_num_brk = 0;
@ -137,6 +128,11 @@ int g_engine_doc_int = 0;
int g_testing = 0;
int g_testing_enabled = 0;
#define MAX_FATAL_LOGS 20
int g_debug_file_fd = -1;
int g_fatal_log = -1;
char *g_fatal_log_strs[MAX_FATAL_LOGS];
word32 stop_run_at;
@ -161,25 +157,28 @@ byte *g_dummy_memory1_ptr = 0;
byte *g_rom_fc_ff_ptr = 0;
byte *g_rom_cards_ptr = 0;
void *g_memory_alloc_ptr = 0; /* for freeing memory area */
Page_info page_info_rd_wr[2*65536 + PAGE_INFO_PAD_SIZE];
int kbd_in_end = 0;
byte kbd_in_buf[LEN_KBD_BUF];
Pc_log g_pc_log_array[PC_LOG_LEN + 2];
Data_log g_data_log_array[PC_LOG_LEN + 2];
Pc_log *g_log_pc_ptr = &(g_pc_log_array[0]);
Pc_log *g_log_pc_start_ptr = &(g_pc_log_array[0]);
Pc_log *g_log_pc_end_ptr = &(g_pc_log_array[PC_LOG_LEN]);
#define PC_LOG_LEN (8*1024)
Pc_log pc_log_array[PC_LOG_LEN + 2];
Pc_log *log_pc_ptr = &(pc_log_array[0]);
Pc_log *log_pc_start_ptr = &(pc_log_array[0]);
Pc_log *log_pc_end_ptr = &(pc_log_array[PC_LOG_LEN]);
Data_log *g_log_data_ptr = &(g_data_log_array[0]);
Data_log *g_log_data_start_ptr = &(g_data_log_array[0]);
Data_log *g_log_data_end_ptr = &(g_data_log_array[PC_LOG_LEN]);
void
show_pc_log()
{
FILE *pcfile;
Pc_log *log_pc_ptr;
Data_log *log_data_ptr;
double dcycs;
double start_dcycs;
word32 instr;
@ -188,23 +187,52 @@ show_pc_log()
word32 stack, direct;
word32 dbank;
word32 kpc;
int data_wrap;
int accsize, xsize;
int num;
int i;
pcfile = fopen("pc_log_out", "wt");
pcfile = fopen("pc_log_out", "w");
if(pcfile == 0) {
fprintf(stderr,"fopen failed...errno: %d\n", errno);
exit(2);
}
log_pc_ptr = g_log_pc_ptr;
log_data_ptr = g_log_data_ptr;
#if 0
fprintf(pcfile, "current pc_log_ptr: %p, start: %p, end: %p\n",
log_pc_ptr, log_pc_start_ptr, log_pc_end_ptr);
#endif
start_dcycs = log_pc_ptr->dcycs;
dcycs = start_dcycs;
data_wrap = 0;
/* find first data entry */
while(data_wrap < 2 && (log_data_ptr->dcycs < dcycs)) {
log_data_ptr++;
if(log_data_ptr >= g_log_data_end_ptr) {
log_data_ptr = g_log_data_start_ptr;
data_wrap++;
}
}
fprintf(pcfile, "start_dcycs: %9.2f\n", start_dcycs);
for(i = 0; i < PC_LOG_LEN; i++) {
dcycs = log_pc_ptr->dcycs;
while((data_wrap < 2) && (log_data_ptr->dcycs <= dcycs) &&
(log_data_ptr->dcycs >= start_dcycs)) {
fprintf(pcfile, "DATA set %06x = %06x (%d) %9.2f\n",
log_data_ptr->addr, log_data_ptr->val,
log_data_ptr->size,
log_data_ptr->dcycs - start_dcycs);
log_data_ptr++;
if(log_data_ptr >= g_log_data_end_ptr) {
log_data_ptr = g_log_data_start_ptr;
data_wrap++;
}
}
dbank = (log_pc_ptr->dbank_kpc >> 24) & 0xff;
kpc = log_pc_ptr->dbank_kpc & 0xffffff;
instr = log_pc_ptr->instr;
@ -214,9 +242,8 @@ show_pc_log()
yreg = log_pc_ptr->xreg_yreg & 0xffff;;
stack = (log_pc_ptr->stack_direct >> 16) & 0xffff;;
direct = log_pc_ptr->stack_direct & 0xffff;;
dcycs = log_pc_ptr->dcycs;
num = log_pc_ptr - log_pc_start_ptr;
num = log_pc_ptr - g_log_pc_start_ptr;
accsize = 2;
xsize = 2;
@ -234,8 +261,8 @@ show_pc_log()
do_dis(pcfile, kpc, accsize, xsize, 1, instr);
log_pc_ptr++;
if(log_pc_ptr >= log_pc_end_ptr) {
log_pc_ptr = log_pc_start_ptr;
if(log_pc_ptr >= g_log_pc_end_ptr) {
log_pc_ptr = g_log_pc_start_ptr;
}
}
@ -380,7 +407,7 @@ get_memory_io(word32 loc, double *cyc_ptr)
}
g_code_yellow++;
if(g_ignore_bad_acc) {
if(g_ignore_bad_acc && !g_user_halt_bad) {
/* print no message, just get out. User doesn't want */
/* to be bothered by buggy programs */
return 0;
@ -389,7 +416,7 @@ get_memory_io(word32 loc, double *cyc_ptr)
printf("get_memory_io for addr: %06x\n", loc);
printf("stat for addr: %06x = %p\n", loc,
GET_PAGE_INFO_RD((loc >> 8) & 0xffff));
set_halt(g_halt_on_bad_read);
set_halt(g_halt_on_bad_read | g_user_halt_bad);
return 0;
}
@ -498,7 +525,7 @@ set_memory_io(word32 loc, int val, double *cyc_ptr)
return;
}
if(g_ignore_bad_acc) {
if(g_ignore_bad_acc && !g_user_halt_bad) {
/* print no message, just get out. User doesn't want */
/* to be bothered by buggy programs */
return;
@ -579,15 +606,14 @@ my_exit(int ret)
void
do_reset()
{
int i;
statereg = 0x08 + 0x04 + 0x01; /* rdrom, lcbank2, intcx */
g_c068_statereg = 0x08 + 0x04 + 0x01; /* rdrom, lcbank2, intcx */
g_c035_shadow_reg = 0;
wrdefram = 1;
for(i = 1; i < 7; i++) {
int_crom[i] = 0;
}
int_crom[7] = 0;
g_c08x_wrdefram = 1;
g_c02d_int_crom = 0;
g_c023_val = 0;
g_c041_val = 0;
engine.psr = (engine.psr | 0x134) & ~(0x08);
engine.stack = 0x100 + (engine.stack & 0xff);
@ -596,6 +622,7 @@ do_reset()
engine.xreg &= 0xff;
engine.yreg &= 0xff;
g_wait_pending = 0;
g_stp_pending = 0;
video_reset();
@ -606,6 +633,8 @@ do_reset()
setup_pageinfo();
change_display_mode(g_cur_dcycs);
g_irq_pending = 0;
engine.kpc = get_memory16_c(0x00fffc, 0);
g_stepping = 0;
@ -665,14 +694,18 @@ check_engine_asm_defines()
}
byte *
memalloc_align(int size, int skip_amt)
memalloc_align(int size, int skip_amt, void **alloc_ptr)
{
byte *bptr;
word32 addr;
word32 offset;
skip_amt = MAX(256, skip_amt);
bptr = malloc(size + skip_amt);
bptr = calloc(size + skip_amt, 1);
if(alloc_ptr) {
/* Save allocation address */
*alloc_ptr = bptr;
}
addr = PTR2WORD(bptr) & 0xff;
@ -681,11 +714,7 @@ memalloc_align(int size, int skip_amt)
offset = ((addr + skip_amt - 1) & (~0xff)) - addr;
bptr += offset;
/* Gilles Tschopp recommended zeroing memory, this is a good idea */
memset(bptr, 0, size);
return bptr;
return (bptr + offset);
}
void
@ -693,9 +722,15 @@ memory_ptr_init()
{
word32 mem_size;
/* This routine may be called several times--each time the ROM file */
/* changes this will be called */
mem_size = MIN(0xdf0000, g_mem_size_base + g_mem_size_exp);
g_mem_size_total = mem_size;
g_memory_ptr = memalloc_align(mem_size, 3*1024);
if(g_memory_alloc_ptr) {
free(g_memory_alloc_ptr);
g_memory_alloc_ptr = 0;
}
g_memory_ptr = memalloc_align(mem_size, 256, &g_memory_alloc_ptr);
printf("RAM size is 0 - %06x (%.2fMB)\n", mem_size,
(double)mem_size/(1024.0*1024.0));
@ -807,8 +842,7 @@ kegsmain(int argc, char **argv)
printf("Not using X shared memory\n");
g_use_shmem = 0;
} else if(!strcmp("-joystick", argv[i])) {
printf("Trying to use joystick\n");
joystick_init();
printf("Ignoring -joystick option\n");
} else if(!strcmp("-dhr140", argv[i])) {
printf("Using simple dhires color map\n");
g_use_dhr140 = 1;
@ -854,8 +888,7 @@ kegsmain(int argc, char **argv)
iwm_init();
config_init();
load_roms();
memory_ptr_init();
load_roms_init_memory();
init_reg();
clear_halt();
@ -870,8 +903,11 @@ kegsmain(int argc, char **argv)
sound_init();
scc_init();
clk_setup_bram_version(); /* load_roms must be called first! */
adb_init();
joystick_init();
if(g_rom_version >= 3) {
g_c036_val_speed |= 0x40; /* set power-on bit */
}
do_reset();
g_stepping = 0;
@ -884,6 +920,27 @@ kegsmain(int argc, char **argv)
return 0;
}
void
load_roms_init_memory()
{
config_load_roms();
memory_ptr_init();
clk_setup_bram_version(); /* Must be after config_load_roms */
if(g_rom_version >= 3) {
g_c036_val_speed |= 0x40; /* set power-on bit */
} else {
g_c036_val_speed &= (~0x40); /* clear the bit */
}
do_reset();
/* if user booted ROM 01, switches to ROM 03, then switches back */
/* to ROM 01, then the reset routines call to Tool $0102 looks */
/* at uninitialized $e1/15fe and if it is negative it will JMP */
/* through $e1/1688 which ROM 03 left pointing to fc/0199 */
/* So set e1/15fe = 0 */
set_memory16_c(0xe115fe, 0, 0);
}
void
kegs_expand_path(char *out_ptr, const char *in_ptr, int maxlen)
{
@ -952,7 +1009,7 @@ 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)
int can_create_file, const char **name_ptr)
{
char local_path[256];
struct stat stat_buf;
@ -984,20 +1041,41 @@ setup_kegs_file(char *outname, int maxlen, int ok_if_missing,
path_ptr++;
}
if(ok_if_missing) {
outname[0] = 0;
outname[0] = 0;
if(ok_if_missing > 0) {
return;
}
/* couldn't find it, print out all the attempts */
path_ptr = save_path_ptr;
printf("Could not find %s in any of these directories:\n", *name_ptr);
fatal_printf("Could not find required file \"%s\" in any of these "
"directories:\n", *name_ptr);
while(*path_ptr) {
printf(" %s\n", *path_ptr++);
fatal_printf(" %s\n", *path_ptr++);
}
if(can_create_file) {
// Ask user if it's OK to create the file
x_dialog_create_kegs_conf(*name_ptr);
can_create_file = 0;
// But clear out the fatal_printfs first
clear_fatal_logs();
setup_kegs_file(outname, maxlen, ok_if_missing,
can_create_file, name_ptr);
// It's one-level of recursion--it cannot loop since we
// clear can_create_file.
// If it returns, then there was succes and we should get out
return;
} else if(ok_if_missing) {
/* Just show an alert and return if ok_if_missing < 0 */
x_show_alert(0, 0);
return;
}
system("pwd");
exit(2);
my_exit(2);
}
Event g_event_list[MAX_EVENTS];
@ -1248,14 +1326,11 @@ Fplus g_recip_projected_pmhz_fast;
Fplus g_recip_projected_pmhz_zip;
Fplus g_recip_projected_pmhz_unl;
Fplus *g_cur_fplus_ptr = 0;
void
show_pmhz()
{
printf("Pmhz: %f, plus_1: %f, fast: %d, limit: %d\n",
g_projected_pmhz, g_cur_fplus_ptr->plus_1, speed_fast,
g_limit_speed);
printf("Pmhz: %f, c036:%02x, limit: %d\n",
g_projected_pmhz, g_c036_val_speed, g_limit_speed);
}
@ -1329,12 +1404,15 @@ run_prog()
zip_speed_0tof = g_zipgs_reg_c05a & 0xf0;
setup_zip_speeds();
if(g_cur_fplus_ptr == 0) {
if(engine.fplus_ptr == 0) {
g_recip_projected_pmhz_unl = g_recip_projected_pmhz_slow;
}
while(1) {
fflush(stdout);
if(g_config_control_panel) {
config_control_panel();
}
if(g_irq_pending && !(engine.psr & 0x4)) {
irq_printf("taking an irq!\n");
@ -1344,11 +1422,11 @@ run_prog()
motor_on = g_iwm_motor_on;
limit_speed = g_limit_speed;
apple35_sel = g_apple35_sel;
apple35_sel = g_c031_disk35 & 0x40;
zip_en = ((g_zipgs_reg_c05b & 0x10) == 0);
zip_follow_cps = ((g_zipgs_reg_c059 & 0x8) != 0);
zip_speed_0tof_new = g_zipgs_reg_c05a & 0xf0;
fast = speed_fast || (zip_en && !zip_follow_cps);
fast = (g_c036_val_speed & 0x80) || (zip_en && !zip_follow_cps);
if(zip_speed_0tof_new != zip_speed_0tof) {
zip_speed_0tof = zip_speed_0tof_new;
@ -1356,7 +1434,7 @@ run_prog()
}
iwm_1 = motor_on && !apple35_sel &&
(g_slot_motor_detect & 0x4) &&
(g_c036_val_speed & 0x4) &&
(g_slow_525_emul_wr || !g_fast_disk_emul);
iwm_25 = (motor_on && apple35_sel) && !g_fast_disk_emul;
faster_than_28 = fast && (!iwm_1 && !iwm_25) && zip_en &&
@ -1381,7 +1459,6 @@ run_prog()
fplus_ptr = &g_recip_projected_pmhz_slow;
}
g_cur_fplus_ptr = fplus_ptr;
engine.fplus_ptr = fplus_ptr;
this_type = g_event_start.next->type;
@ -1514,9 +1591,6 @@ run_prog()
if(g_stepping) {
break;
}
if(g_config_control_panel) {
config_control_panel();
}
}
if(!g_testing) {
@ -1527,19 +1601,20 @@ run_prog()
}
void
add_irq()
add_irq(word32 irq_mask)
{
g_irq_pending++;
if(g_irq_pending & irq_mask) {
/* Already requested, just get out */
return;
}
g_irq_pending |= irq_mask;
set_halt(HALT_EVENT);
}
void
remove_irq()
remove_irq(word32 irq_mask)
{
g_irq_pending--;
if(g_irq_pending < 0) {
halt_printf("remove_irq: g_irq_pending: %d\n", g_irq_pending);
}
g_irq_pending = g_irq_pending & (~irq_mask);
}
void
@ -1559,10 +1634,6 @@ take_irq(int is_it_brk)
g_wait_pending = 0;
}
if(g_irq_pending < 0) {
halt_printf("g_irq_pending: %d!\n", g_irq_pending);
}
if(engine.psr & 0x100) {
/* Emulation */
set_memory_c(engine.stack, (engine.kpc >> 8) & 0xff, 0);
@ -1577,7 +1648,7 @@ take_irq(int is_it_brk)
engine.stack = ((engine.stack -1) & 0xff) + 0x100;
va = 0xfffffe;
if(shadow_reg & 0x40) {
if(g_c035_shadow_reg & 0x40) {
/* I/O shadowing off...use ram locs */
va = 0x00fffe;
}
@ -1599,13 +1670,13 @@ take_irq(int is_it_brk)
if(is_it_brk) {
/* break */
va = 0xffffe6;
if(shadow_reg & 0x40) {
if(g_c035_shadow_reg & 0x40) {
va = 0xffe6;
}
} else {
/* irq */
va = 0xffffee;
if(shadow_reg & 0x40) {
if(g_c035_shadow_reg & 0x40) {
va = 0xffee;
}
}
@ -1967,19 +2038,18 @@ update_60hz(double dcycs, double dtime_now)
g_dtime_eff_pmhz_array[prev_vbl_index] = eff_pmhz;
if(c041_en_vbl_ints) {
if(g_c041_val & C041_EN_VBL_INTS) {
add_event_vbl();
}
g_25sec_cntr++;
if(g_25sec_cntr >= 16) {
g_25sec_cntr = 0;
if(c041_en_25sec_ints && !c046_25sec_irq_pend) {
if(g_c041_val & C041_EN_25SEC_INTS) {
add_irq(IRQ_PENDING_C046_25SEC);
g_c046_val |= 0x10;
c046_25sec_irq_pend = 1;
add_irq();
irq_printf("Setting c046 .25 sec int to 1, "
"g_irq_pend: %d\n", g_irq_pending);
irq_printf("Setting c046 .25 sec int, g_irq_pend:%d\n",
g_irq_pending);
}
}
@ -1988,10 +2058,9 @@ update_60hz(double dcycs, double dtime_now)
g_1sec_cntr = 0;
tmp = g_c023_val;
tmp |= 0x40; /* set 1sec int */
if((tmp & 0x04) && !c023_1sec_int_irq_pending) {
c023_1sec_int_irq_pending = 1;
if(tmp & 0x04) {
tmp |= 0x80;
add_irq();
add_irq(IRQ_PENDING_C023_1SEC);
irq_printf("Setting c023 to %02x irq_pend: %d\n",
tmp, g_irq_pending);
}
@ -2017,16 +2086,15 @@ update_60hz(double dcycs, double dtime_now)
sound_update(dcycs);
clock_update();
scc_update(dcycs);
joystick_update_button();
paddle_update_buttons();
}
void
do_vbl_int()
{
if(c041_en_vbl_ints && !c046_vbl_irq_pending) {
if(g_c041_val & C041_EN_VBL_INTS) {
g_c046_val |= 0x08;
c046_vbl_irq_pending = 1;
add_irq();
add_irq(IRQ_PENDING_C046_VBL);
irq_printf("Setting c046 vbl_int_status to 1, irq_pend: %d\n",
g_irq_pending);
}
@ -2045,12 +2113,12 @@ do_scan_int(double dcycs, int line)
}
/* make sure scan int is still enabled for this line */
if(g_slow_memory_ptr[0x19d00 + line] & 0x40) {
if((g_slow_memory_ptr[0x19d00 + line] & 0x40) &&
(g_cur_a2_stat & ALL_STAT_SUPER_HIRES)) {
/* valid interrupt, do it */
c023_val |= 0xa0; /* vgc_int and scan_int */
if((c023_val & 0x02) && !c023_scan_int_irq_pending) {
add_irq();
c023_scan_int_irq_pending = 1;
if(c023_val & 0x02) {
add_irq(IRQ_PENDING_C023_SCAN);
irq_printf("Setting c023 to %02x, irq_pend: %d\n",
c023_val, g_irq_pending);
}
@ -2063,7 +2131,6 @@ do_scan_int(double dcycs, int line)
}
}
void
check_scan_line_int(double dcycs, int cur_video_line)
{
@ -2128,6 +2195,7 @@ init_reg()
engine.stack = 0x1ff;
engine.direct = 0;
engine.psr = 0x134;
engine.fplus_ptr = 0;
}
@ -2174,6 +2242,9 @@ handle_action(word32 ret)
case RET_WDM:
do_wdm(ret & 0xff);
break;
case RET_STP:
do_stp();
break;
default:
halt_printf("Unknown special action: %08x!\n", ret);
}
@ -2274,7 +2345,11 @@ do_wai()
void
do_stp()
{
halt_printf("Hit do_stp at addr: %06x\n", engine.kpc);
if(!g_stp_pending) {
g_stp_pending = 1;
halt_printf("Hit STP instruction at: %06x, press RESET to "
"continue\n", engine.kpc);
}
}
void
@ -2283,3 +2358,86 @@ size_fail(int val, word32 v1, word32 v2)
halt_printf("Size failure, val: %08x, %08x %08x\n", val, v1, v2);
}
int
fatal_printf(const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
if(g_fatal_log < 0) {
g_fatal_log = 0;
}
ret = kegs_vprintf(fmt, ap);
va_end(ap);
return ret;
}
int
kegs_vprintf(const char *fmt, va_list ap)
{
char *bufptr, *buf2ptr;
int len;
int ret;
bufptr = malloc(4096);
ret = vsnprintf(bufptr, 4090, fmt, ap);
len = strlen(bufptr);
if(g_fatal_log >= 0 && g_fatal_log < MAX_FATAL_LOGS) {
buf2ptr = malloc(len+1);
memcpy(buf2ptr, bufptr, len+1);
g_fatal_log_strs[g_fatal_log++] = buf2ptr;
}
must_write(1, bufptr, len);
if(g_debug_file_fd >= 0) {
must_write(g_debug_file_fd, bufptr, len);
}
free(bufptr);
return ret;
}
void
must_write(int fd, char *bufptr, int len)
{
int ret;
while(len > 0) {
ret = write(fd, bufptr, len);
if(ret >= 0) {
len -= ret;
bufptr += ret;
} else if(errno != EAGAIN && errno != EINTR) {
return; // just get out
}
}
}
void
clear_fatal_logs()
{
int i;
for(i = 0; i < g_fatal_log; i++) {
free(g_fatal_log_strs[i]);
g_fatal_log_strs[i] = 0;
}
g_fatal_log = -1;
}
char *
kegs_malloc_str(char *in_str)
{
char *str;
int len;
len = strlen(in_str) + 1;
str = malloc(len);
memcpy(str, in_str, len);
return str;
}

View File

@ -8,7 +8,7 @@
/* 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 $";
const char rcsid_smartport_c[] = "@(#)$KmKId: smartport.c,v 1.31 2004-11-12 23:10:50-05 kentd Exp $";
#include "defc.h"
@ -195,12 +195,9 @@ do_c70d(word32 arg0)
/* 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);
set_memory16_c(status_ptr+2, 0x0002, 0); /* vendor id */
set_memory16_c(status_ptr+4, 0x1000, 0); /* version */
set_memory16_c(status_ptr+6, 0x0000, 0);
engine.xreg = 8;
engine.yreg = 0;
@ -219,9 +216,7 @@ do_c70d(word32 arg0)
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);
set_memory24_c(status_ptr +1, size, 0);
engine.xreg = 4;
if(cmd & 0x40) {
set_memory_c(status_ptr + 4,
@ -249,9 +244,7 @@ do_c70d(word32 arg0)
}
/* 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);
set_memory24_c(status_ptr +1, size, 0);
if(cmd & 0x40) {
set_memory_c(status_ptr + 4,
(size >> 24) & 0xff, 0);
@ -267,11 +260,8 @@ do_c70d(word32 arg0)
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);
set_memory16_c(status_ptr + 21, 0xa002, 0);
set_memory16_c(status_ptr + 23, 0x0000, 0);
if(cmd & 0x40) {
engine.xreg = 26;
@ -766,18 +756,15 @@ do_c700(word32 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);
set_memory16_c(0x42, 0x7001, 0);
set_memory16_c(0x44, 0x0800, 0);
set_memory16_c(0x46, 0x0000, 0);
engine.xreg = 0x70;
engine.kpc = 0x801;
if(ret != 0) {
printf("Failure reading boot disk in s7d1!\n");
engine.kpc = 0xe000;
engine.kpc = 0xff59; /* Jump to monitor, fix $36-$39 */
}
}

View File

@ -8,7 +8,7 @@
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_sound_c[] = "@(#)$KmKId: sound.c,v 1.103 2003-10-17 15:07:47-04 kentd Exp $";
const char rcsid_sound_c[] = "@(#)$KmKId: sound.c,v 1.108 2004-10-31 00:56:07-04 kentd Exp $";
#include "defc.h"
@ -25,6 +25,7 @@ extern int g_use_shmem;
extern word32 g_vbl_count;
extern int g_preferred_rate;
extern int g_c03ef_doc_ptr;
extern double g_last_vbl_dcycs;
@ -34,7 +35,6 @@ byte doc_ram[0x10000 + 16];
word32 doc_sound_ctl = 0;
word32 doc_saved_val = 0;
word32 doc_ptr = 0;
int g_doc_num_osc_en = 1;
double g_dcycs_per_doc_update = 1.0;
double g_dupd_per_dcyc = 1.0;
@ -154,7 +154,7 @@ show_doc_log(void)
int pos;
int i;
docfile = fopen("doc_log_out", "wt");
docfile = fopen("doc_log_out", "w");
if(docfile == 0) {
printf("fopen failed, errno: %d\n", errno);
return;
@ -397,10 +397,12 @@ sound_reset(double dcycs)
halt_printf("reset: has_irq[%02x] = %d\n", i,
g_doc_regs[i].has_irq_pending);
}
g_doc_regs[i].has_irq_pending = 0;
}
if(g_num_osc_interrupting) {
halt_printf("reset: num_osc_int:%d\n", g_num_osc_interrupting);
}
g_num_osc_interrupting = 0;
g_doc_num_osc_en = 1;
UPDATE_G_DCYCS_PER_DOC_UPDATE(1);
@ -1212,7 +1214,7 @@ add_sound_irq(int osc)
g_doc_regs[osc].has_irq_pending = num_osc_interrupting;
g_num_osc_interrupting = num_osc_interrupting;
add_irq();
add_irq(IRQ_PENDING_DOC);
if(num_osc_interrupting == 1) {
doc_reg_e0 = 0x00 + (osc << 1);
}
@ -1238,7 +1240,9 @@ remove_sound_irq(int osc, int must)
g_num_osc_interrupting--;
g_doc_regs[osc].has_irq_pending = 0;
DOC_LOG("rem_irq", osc, g_cur_dcycs * g_dsamps_per_dcyc, 0);
remove_irq();
if(g_num_osc_interrupting == 0) {
remove_irq(IRQ_PENDING_DOC);
}
first = 0x40 | (doc_reg_e0 >> 1);
/* if none found, then def = no ints */
@ -1641,13 +1645,13 @@ doc_read_c03d(double dcycs)
if(doc_sound_ctl & 0x40) {
/* Read RAM */
doc_saved_val = doc_ram[doc_ptr];
doc_saved_val = doc_ram[g_c03ef_doc_ptr];
} else {
/* Read DOC */
doc_saved_val = 0;
osc = doc_ptr & 0x1f;
type = (doc_ptr >> 5) & 0x7;
osc = g_c03ef_doc_ptr & 0x1f;
type = (g_c03ef_doc_ptr >> 5) & 0x7;
rptr = &(g_doc_regs[osc]);
switch(type) {
@ -1698,24 +1702,24 @@ doc_read_c03d(double dcycs)
default:
doc_saved_val = 0;
halt_printf("Reading bad doc_reg[%04x]: %02x\n",
doc_ptr, doc_saved_val);
g_c03ef_doc_ptr, doc_saved_val);
}
break;
default:
doc_saved_val = 0;
halt_printf("Reading bad doc_reg[%04x]: %02x\n",
doc_ptr, doc_saved_val);
g_c03ef_doc_ptr, doc_saved_val);
}
}
doc_printf("read c03d, doc_ptr: %04x, ret: %02x, saved: %02x\n",
doc_ptr, ret, doc_saved_val);
g_c03ef_doc_ptr, ret, doc_saved_val);
DOC_LOG("read c03d", -1, dsamps, (doc_ptr << 16) +
DOC_LOG("read c03d", -1, dsamps, (g_c03ef_doc_ptr << 16) +
(doc_saved_val << 8) + ret);
if(doc_sound_ctl & 0x20) {
doc_ptr = (doc_ptr + 1) & 0xffff;
g_c03ef_doc_ptr = (g_c03ef_doc_ptr + 1) & 0xffff;
}
@ -1758,17 +1762,17 @@ doc_write_c03d(int val, double dcycs)
dsamps = dcycs * g_dsamps_per_dcyc;
eff_dsamps = dsamps;
doc_printf("write c03d, doc_ptr: %04x, val: %02x\n",
doc_ptr, val);
g_c03ef_doc_ptr, val);
DOC_LOG("write c03d", -1, dsamps, (doc_ptr << 16) + val);
DOC_LOG("write c03d", -1, dsamps, (g_c03ef_doc_ptr << 16) + val);
if(doc_sound_ctl & 0x40) {
/* RAM */
doc_ram[doc_ptr] = val;
doc_ram[g_c03ef_doc_ptr] = val;
} else {
/* DOC */
osc = doc_ptr & 0x1f;
type = (doc_ptr >> 5) & 0x7;
osc = g_c03ef_doc_ptr & 0x1f;
type = (g_c03ef_doc_ptr >> 5) & 0x7;
rptr = &(g_doc_regs[osc]);
ctl = rptr->ctl;
@ -1777,7 +1781,7 @@ doc_write_c03d(int val, double dcycs)
if(type < 2 || type == 4 || type == 6) {
halt_printf("Osc %d is running, old ctl: %02x, "
"but write reg %02x=%02x\n",
osc, ctl, doc_ptr & 0xff, val);
osc, ctl, g_c03ef_doc_ptr & 0xff, val);
}
}
#endif
@ -1901,35 +1905,23 @@ doc_write_c03d(int val, double dcycs)
/* and apparently TaskForce, OOTW, etc */
/* writes to e2-ff, for no apparent reason */
doc_printf("Writing doc 0x%x with %02x\n",
doc_ptr, val);
g_c03ef_doc_ptr, val);
break;
}
break;
default:
halt_printf("Writing %02x into bad doc_reg[%04x]\n",
val, doc_ptr);
val, g_c03ef_doc_ptr);
}
}
if(doc_sound_ctl & 0x20) {
doc_ptr = (doc_ptr + 1) & 0xffff;
g_c03ef_doc_ptr = (g_c03ef_doc_ptr + 1) & 0xffff;
}
doc_saved_val = val;
}
void
doc_write_c03e(int val)
{
doc_ptr = (doc_ptr & 0xff00) + val;
}
void
doc_write_c03f(int val)
{
doc_ptr = (doc_ptr & 0xff) + (val << 8);
}
void
doc_show_ensoniq_state(int osc)
{
@ -1939,8 +1931,8 @@ doc_show_ensoniq_state(int osc)
printf("Ensoniq state\n");
printf("c03c doc_sound_ctl: %02x, doc_saved_val: %02x\n",
doc_sound_ctl, doc_saved_val);
printf("doc_ptr: %04x, num_osc_en: %02x, e0: %02x\n", doc_ptr,
g_doc_num_osc_en, doc_reg_e0);
printf("doc_ptr: %04x, num_osc_en: %02x, e0: %02x\n",
g_c03ef_doc_ptr, g_doc_num_osc_en, doc_reg_e0);
for(i = 0; i < 32; i += 8) {
printf("irqp: %02x: %04x %04x %04x %04x %04x %04x %04x %04x\n",

View File

@ -8,7 +8,7 @@
/* 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 $";
const char rcsid_sound_driver_c[] = "@(#)$KmKId: sound_driver.c,v 1.17 2004-09-21 10:37:15-04 kentd Exp $";
#include "defc.h"
#include "sound.h"
@ -17,10 +17,6 @@ const char rcsid_sound_driver_c[] = "@(#)$KmKId: sound_driver.c,v 1.16 2004-03-2
# include <sys/audio.h>
#endif
#ifdef SOLARIS
# include <sys/audioio.h>
#endif
#if defined(__linux__) || defined(OSS)
# include <sys/soundcard.h>
#endif
@ -33,7 +29,6 @@ const char rcsid_sound_driver_c[] = "@(#)$KmKId: sound_driver.c,v 1.16 2004-03-2
extern int Verbose;
extern int g_use_alib;
extern int g_audio_rate;
@ -57,7 +52,6 @@ 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();
@ -137,9 +131,6 @@ child_sound_loop(int read_fd, int write_fd, word32 *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
@ -360,37 +351,6 @@ child_sound_init_hpdev()
}
#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()

View File

@ -3,7 +3,7 @@ TARGET = xkegs
OBJECTS = $(OBJECTS1) xdriver.o
CC = gcc
CCOPTS = -O
OPTS = -DNDEBUG -DSOLARIS -DKEGS_LITTLE_ENDIAN -DOSS
OPTS = -DNDEBUG -DSOLARIS -DKEGS_LITTLE_ENDIAN -DSOLARISSOUND
SUFFIX =
NAME = xkegs
LDFLAGS =

View File

@ -8,7 +8,7 @@
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_video_c[] = "@(#)$KmKId: video.c,v 1.125 2004-03-23 17:25:50-05 kentd Exp $";
const char rcsid_video_c[] = "@(#)$KmKId: video.c,v 1.135 2004-11-12 23:09:44-05 kentd Exp $";
#include <time.h>
@ -41,12 +41,11 @@ extern byte *g_slow_memory_ptr;
extern int g_screen_depth;
extern int g_screen_mdepth;
extern int statereg;
extern double g_cur_dcycs;
extern int g_line_ref_amt;
extern int g_border_color;
extern int g_c034_val;
extern int g_config_control_panel;
typedef byte Change;
@ -72,6 +71,15 @@ Kimage g_mainwin_kimage;
extern double g_last_vbl_dcycs;
double g_video_dcycs_check_input = 0.0;
int g_video_extra_check_inputs = 0;
int g_video_act_margin_left = BASE_MARGIN_LEFT;
int g_video_act_margin_right = BASE_MARGIN_RIGHT;
int g_video_act_margin_top = BASE_MARGIN_TOP;
int g_video_act_margin_bottom = BASE_MARGIN_BOTTOM;
int g_video_act_width = X_A2_WINDOW_WIDTH;
int g_video_act_height = X_A2_WINDOW_HEIGHT;
int g_need_redraw = 1;
int g_palette_change_summary = 0;
word32 g_palette_change_cnt[16];
@ -98,6 +106,7 @@ int g_expanded_col_2[16];
int g_cur_a2_stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 |
(0xf << BIT_ALL_STAT_TEXT_COLOR);
extern int g_save_cur_a2_stat; /* from config.c */
int g_a2vid_palette = 0xe;
int g_installed_full_superhires_colormap = 0;
@ -445,8 +454,6 @@ video_init()
video_reset();
display_screen();
vid_printf("Done with display_screen\n");
fflush(stdout);
}
@ -463,7 +470,8 @@ show_a2_line_stuff()
g_a2_line_right_edge[i]);
}
printf("new_a2_stat_cur_line: %d\n", g_new_a2_stat_cur_line);
printf("new_a2_stat_cur_line: %d, cur_a2_stat:%04x\n",
g_new_a2_stat_cur_line, g_cur_a2_stat);
for(i = 0; i < 200; i++) {
printf("cur_all[%d]: %03x new_all: %03x\n", i,
g_a2_cur_all_stat[i], g_a2_new_all_stat[i]);
@ -476,13 +484,20 @@ int g_flash_count = 0;
void
video_reset()
{
int stat;
int i;
g_installed_full_superhires_colormap = (g_screen_depth != 8);
g_cur_a2_stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 |
(0xf << BIT_ALL_STAT_TEXT_COLOR);
stat = ALL_STAT_TEXT | ALL_STAT_ANNUNC3 |
(0xf << BIT_ALL_STAT_TEXT_COLOR);
if(g_use_bw_hires) {
g_cur_a2_stat |= ALL_STAT_COLOR_C021;
stat |= ALL_STAT_COLOR_C021;
}
if(g_config_control_panel) {
/* Don't update cur_a2_stat when in configuration panel */
g_save_cur_a2_stat = stat;
} else {
g_cur_a2_stat = stat;
}
g_palette_change_summary = 0;
@ -502,17 +517,11 @@ word32 g_cycs_in_check_input = 0;
void
video_update()
{
register word32 start_time;
register word32 end_time;
int did_video;
update_border_info();
GET_ITIMER(start_time);
check_input_events();
GET_ITIMER(end_time);
g_cycs_in_check_input += (end_time - start_time);
video_check_input_events();
g_screen_redraw_skip_count--;
did_video = 0;
@ -536,8 +545,7 @@ video_update()
if(did_video) {
g_new_a2_stat_cur_line = 0;
g_a2_new_all_stat[0] = (g_cur_a2_stat & (~ALL_STAT_PAGE2)) +
PAGE2;
g_a2_new_all_stat[0] = g_cur_a2_stat;
g_vid_update_last_line = 0;
video_update_through_line(0);
}
@ -740,8 +748,7 @@ change_display_mode(double dcycs)
video_update_all_stat_through_line(tmp_line);
if(line < 200) {
g_a2_new_all_stat[line] =
(g_cur_a2_stat & (~ALL_STAT_PAGE2)) + PAGE2;
g_a2_new_all_stat[line] = g_cur_a2_stat;
}
/* otherwise, g_cur_a2_stat is covered at the end of vbl */
}
@ -813,12 +820,12 @@ update_border_info()
color_now = g_vbl_border_color;
dlines_per_dcyc = (double)(262.0 / DCYCS_IN_16MS);
dlines_per_dcyc = (double)(1.0 / 65.0);
limit = g_num_border_changes;
if(g_border_last_vbl_changes || limit) {
/* add a dummy entry */
g_border_changes[limit].fcycs = DCYCS_IN_16MS + 21.0;
g_border_changes[limit].val = g_border_color;
g_border_changes[limit].val = (g_c034_val & 0xf);
limit++;
}
last_line_offset = (-1 << 8) + 44;
@ -826,7 +833,7 @@ update_border_info()
dcycs = g_border_changes[i].fcycs;
dline = dcycs * dlines_per_dcyc;
new_line = (int)dline;
dcyc_line_start = (double)new_line * (DCYCS_IN_16MS/262.0);
dcyc_line_start = (double)new_line * 65.0;
offset = ((int)(dcycs - dcyc_line_start)) & 0xff;
/* here comes the tricky part */
@ -880,7 +887,7 @@ update_border_info()
}
g_num_border_changes = 0;
g_vbl_border_color = g_border_color;
g_vbl_border_color = (g_c034_val & 0xf);
}
void
@ -943,8 +950,8 @@ update_border_line(int st_line_offset, int end_line_offset, int color)
right = MIN(4, end_offset - 44);
video_border_pixel_write(&g_kimage_border_sides,
2*line, 2, val,
32 + (left * EFF_BORDER_WIDTH/4),
32 + (right * EFF_BORDER_WIDTH/4));
BORDER_WIDTH + (left * EFF_BORDER_WIDTH/4),
BORDER_WIDTH + (right * EFF_BORDER_WIDTH/4));
g_border_sides_refresh_needed = 1;
}
}
@ -2638,6 +2645,26 @@ video_update_event_line(int line)
add_event_vid_upd(1); /* add event for new screen */
}
}
if(g_video_extra_check_inputs) {
if(g_video_dcycs_check_input < g_cur_dcycs) {
video_check_input_events();
}
}
}
void
video_check_input_events()
{
word32 start_time, end_time;
g_video_dcycs_check_input = g_cur_dcycs + 4000.0;
GET_ITIMER(start_time);
check_input_events();
GET_ITIMER(end_time);
g_cycs_in_check_input += (end_time - start_time);
}
void
@ -2654,7 +2681,7 @@ video_update_through_line(int line)
int i;
#if 0
vid_printf("\nvideo_upd for line %d, lines: %06x\n\n", line,
vid_printf("\nvideo_upd for line %d, lines: %06x\n", line,
get_lines_since_vbl(g_cur_dcycs));
#endif
@ -3062,9 +3089,8 @@ video_push_lines(Kimage *kimage_ptr, int start_line, int end_line, int left_pix,
g_refresh_bytes_xfer += 2*(end_line - start_line) *
(right_pix - left_pix);
x_push_kimage(kimage_ptr, BASE_MARGIN_LEFT + left_pix,
BASE_MARGIN_TOP + srcy, left_pix, srcy,
x_push_kimage(kimage_ptr, g_video_act_margin_left + left_pix,
g_video_act_margin_top + srcy, left_pix, srcy,
(right_pix - left_pix), 2*(end_line - start_line));
}
@ -3087,8 +3113,30 @@ video_push_border_sides_lines(int src_x, int dest_x, int width, int start_line,
g_refresh_bytes_xfer += 2 * (end_line - start_line) * width;
srcy = 2 * start_line;
x_push_kimage(kimage_ptr, dest_x, BASE_MARGIN_TOP + srcy,
// Adjust dext_x to accound for changed margins
dest_x = dest_x + g_video_act_margin_left - BASE_MARGIN_LEFT;
if(dest_x < BASE_MARGIN_LEFT) {
src_x = src_x + g_video_act_margin_left - BASE_MARGIN_LEFT;
// Don't adjust src_x if doing right border
}
if(dest_x < 0) {
width = width + dest_x;
src_x = src_x - dest_x;
dest_x = 0;
}
if(src_x < 0) {
width = width + src_x;
dest_x = dest_x - src_x;
src_x = 0;
}
if(dest_x + width > g_video_act_width) {
width = g_video_act_width - dest_x;
}
if(width > 0) {
x_push_kimage(kimage_ptr, dest_x, g_video_act_margin_top + srcy,
src_x, srcy, width, 2*(end_line - start_line));
}
}
void
@ -3134,18 +3182,39 @@ video_push_border_special()
{
Kimage *kimage_ptr;
int width, height;
width = X_A2_WINDOW_WIDTH;
height = BASE_MARGIN_TOP;
int src_x, src_y;
int dest_x, dest_y;
kimage_ptr = &g_kimage_border_special;
width = g_video_act_width;
g_refresh_bytes_xfer += width * (BASE_MARGIN_TOP + BASE_MARGIN_BOTTOM);
x_push_kimage(kimage_ptr, 0, BASE_MARGIN_TOP + A2_WINDOW_HEIGHT,
0, 0, width, BASE_MARGIN_BOTTOM);
x_push_kimage(kimage_ptr, 0, 0,
0, BASE_MARGIN_BOTTOM, width, BASE_MARGIN_TOP);
// First do bottom border: dest_x from 0 to 640+MARGIN_LEFT+MARGIN_RIGHT
// and dest_y of BASE_MARGIN_BOTTOM starting at TOP+A2_HEIGHT
// src_x is dest_x, and src_y is 0.
dest_y = g_video_act_margin_top + A2_WINDOW_HEIGHT;
height = g_video_act_margin_bottom;
src_y = BASE_MARGIN_BOTTOM - height;
dest_x = 0;
src_x = BASE_MARGIN_LEFT - g_video_act_margin_left;
if(width > 0 && height > 0) {
x_push_kimage(kimage_ptr, dest_x, dest_y, src_x, src_y,
width, height);
}
// Then fix top border: dest_x from 0 to 640+LEFT+RIGHT and
// dest_y from 0 to TOP. src_x is dest_x, but src_y is
// BOTTOM to BOTTOM+TOP
// Just use src_x and dest_x from earlier.
height = g_video_act_margin_top;
dest_y = 0;
src_y = BASE_MARGIN_BOTTOM;
if(width > 0 && height > 0) {
x_push_kimage(kimage_ptr, dest_x, dest_y, src_x, src_y,
width, height);
}
}
void
@ -3352,3 +3421,70 @@ video_show_debug_info()
printf("lines since vbl: %06x\n", tmp1);
printf("Last line updated: %d\n", g_vid_update_last_line);
}
word32
float_bus(double dcycs)
{
word32 val;
int lines_since_vbl;
int line, eff_line, line24;
int all_stat;
int byte_offset;
int hires, page2;
int addr;
lines_since_vbl = get_lines_since_vbl(dcycs);
/* For floating bus, model hires style: Visible lines 0-191 are simply the */
/* data being displayed at that time. Lines 192-255 are lines 0 - 63 again */
/* and lines 256-261 are lines 58-63 again */
/* For each line, figure out starting byte at -25 mod 128 bytes from this */
/* line's start */
/* This emulates an Apple II style floating bus. A reall IIgs does not */
/* drive anything meaningful during the 25 horizontal blanking lines, */
/* nor during veritical blanking. The data seems to be 0 or related to */
/* the instruction fetches on a real IIgs during blankings */
line = lines_since_vbl >> 8;
byte_offset = lines_since_vbl & 0xff;
/* byte offset is from 0 to 65, where the visible screen is drawn */
/* from 25 to 65 */
eff_line = line;
if(line >= 192) {
eff_line = line - 192;
if(line >= 256) {
eff_line = line - 262 + 64;
}
}
all_stat = g_cur_a2_stat;
hires = all_stat & ALL_STAT_HIRES;
if((all_stat & ALL_STAT_MIX_T_GR) && (line >= 160)) {
hires = 0;
}
page2 = EXTRU(all_stat, 31 - BIT_ALL_STAT_PAGE2, 1);
if(all_stat & ALL_STAT_ST80) {
page2 = 0;
}
line24 = (eff_line >> 3) & 0x1f;
addr = g_screen_index[line24] & 0x3ff;
addr = (addr & 0x380) + (((addr & 0x7f) - 25 + byte_offset) & 0x7f);
if(hires) {
addr = 0x2000 + addr + ((eff_line & 7) << 10) + (page2 << 13);
} else {
addr = 0x400 + addr + (page2 << 10);
}
val = g_slow_memory_ptr[addr];
if(byte_offset < 10) {
/* Bob Bishop's sample program seems to get confused by */
/* these bytes--so mask some off to prevent seeing some */
val = 0;
}
#if 0
printf("For %04x (%d) addr=%04x, val=%02x, dcycs:%9.2f\n",
lines_since_vbl, eff_line, addr, val, dcycs - g_last_vbl_dcycs);
#endif
return val;
}

View File

@ -8,7 +8,10 @@
/* 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 $";
const char rcsid_windriver_c[] = "@(#)$KmKId: windriver.c,v 1.11 2004-11-24 16:43:46-05 kentd Exp $";
/* Based on code from Chea Chee Keong from KEGS32, which is available at */
/* http://www.geocities.com/akilgard/kegs32 */
#define WIN32_LEAN_AND_MEAN /* Tell windows we want less header gunk */
#define STRICT /* Tell Windows we want compile type checks */
@ -187,6 +190,34 @@ int g_a2_key_to_wsym[][3] = {
{ -1, -1, -1 }
};
int
win_nonblock_read_stdin(int fd, char *bufptr, int len)
{
HANDLE oshandle;
DWORD dwret;
int ret;
errno = EAGAIN;
oshandle = (HANDLE)_get_osfhandle(fd); // get stdin handle
dwret = WaitForSingleObject(oshandle, 1); // wait 1msec for data
ret = -1;
if(dwret == WAIT_OBJECT_0) {
ret = read(fd, bufptr, len);
}
return ret;
}
void
x_dialog_create_kegs_conf(const char *str)
{
}
int
x_show_alert(int is_fatal, const char *str)
{
return 0;
}
int
win_update_mouse(int x, int y, int button_states, int buttons_valid)
{
@ -635,3 +666,9 @@ x_hide_pointer(int do_hide)
ShowCursor(1);
}
}
void
x_full_screen(int do_full)
{
return;
}

View File

@ -8,7 +8,7 @@
/* You may contact the author at: kadickey@alumni.princeton.edu */
/************************************************************************/
const char rcsid_xdriver_c[] = "@(#)$KmKId: xdriver.c,v 1.181 2004-03-23 17:25:25-05 kentd Exp $";
const char rcsid_xdriver_c[] = "@(#)$KmKId: xdriver.c,v 1.187 2004-11-15 16:24:19-05 kentd Exp $";
# if !defined(__CYGWIN__) && !defined(__POWERPC__)
/* No shared memory on Cygwin */
@ -136,7 +136,7 @@ int g_num_a2_keycodes = 0;
int a2_key_to_xsym[][3] = {
{ 0x35, XK_Escape, 0 },
{ 0x7a, XK_F1, 0 },
{ 0x7b, XK_F2, 0 },
{ 0x78, XK_F2, 0 },
{ 0x63, XK_F3, 0 },
{ 0x76, XK_F4, 0 },
{ 0x60, XK_F5, 0 },
@ -165,7 +165,7 @@ int a2_key_to_xsym[][3] = {
{ 0x1b, '-', '_' },
{ 0x18, '=', '+' },
{ 0x33, XK_BackSpace, 0 },
{ 0x72, XK_Insert, 0 }, /* Help? */
{ 0x72, XK_Insert, XK_Help }, /* Help? */
/* { 0x73, XK_Home, 0 }, alias XK_Home to be XK_KP_Equal! */
{ 0x74, XK_Page_Up, 0 },
{ 0x47, XK_Num_Lock, XK_Clear }, /* Clear */
@ -248,6 +248,23 @@ main(int argc, char **argv)
return kegsmain(argc, argv);
}
void
x_dialog_create_kegs_conf(const char *str)
{
/* do nothing -- not implemented yet */
return;
}
int
x_show_alert(int is_fatal, const char *str)
{
/* Not implemented yet */
adb_all_keys_up();
clear_fatal_logs();
return 0;
}
#define MAKE_2(val) ( (val << 8) + val)
@ -1160,15 +1177,23 @@ handle_keysym(XEvent *xev_in)
switch(keysym) {
case XK_Alt_R:
case XK_Meta_R:
case XK_Super_R:
case XK_Mode_switch:
case XK_Cancel:
keysym = XK_Print; /* option */
break;
case XK_Alt_L:
case XK_Meta_L:
case XK_Super_L:
case XK_Menu:
keysym = XK_Scroll_Lock; /* cmd */
break;
case 0x1000003:
if(keycode == 0x3c) {
/* enter key on Mac OS X laptop--make it option */
keysym = XK_Print;
}
break;
case NoSymbol:
switch(keycode) {
/* 94-95 are for my PC101 kbd + windows keys on HPUX */
@ -1196,6 +1221,7 @@ handle_keysym(XEvent *xev_in)
keysym = XK_Scroll_Lock;
break;
case 0x0048:
case 0x0076: /* Windows menu key on Mac OS X */
/* menu windows == option */
keysym = XK_Print;
break;
@ -1304,3 +1330,9 @@ x_auto_repeat_off(int must)
adb_kbd_repeat_off();
}
}
void
x_full_screen(int do_full)
{
return;
}