Showing preview only (2,641K chars total). Download the full file or copy to clipboard to get everything.
Repository: digarok/gsplus
Branch: main
Commit: 47389939d652
Files: 178
Total size: 2.5 MB
Directory structure:
gitextract_v8qf17it/
├── .gitignore
├── CLAUDE.md
├── LICENSE
├── README.md
├── TODO.md
├── gsplus/
│ ├── lib/
│ │ ├── 2mg.icns
│ │ ├── 525.icns
│ │ ├── MainMenu.nib
│ │ ├── kegsicon.icns
│ │ └── make_mac_icon
│ └── src/
│ ├── AppDelegate.swift
│ ├── Info.plist
│ ├── Kegs-Bridging-Header.h
│ ├── MainView.swift
│ ├── Makefile
│ ├── adb.c
│ ├── applesingle.c
│ ├── clock.c
│ ├── comp_swift
│ ├── compile_time.c
│ ├── config.c
│ ├── config.h
│ ├── cp_gsplus_libs
│ ├── debugger.c
│ ├── defc.h
│ ├── defcomm.h
│ ├── defs_instr.h
│ ├── dependency
│ ├── disas.h
│ ├── doc.c
│ ├── dyna_filt.c
│ ├── dyna_type.c
│ ├── dyna_validate.c
│ ├── dynapro.c
│ ├── engine.h
│ ├── engine_c.c
│ ├── instable.h
│ ├── iwm.c
│ ├── iwm.h
│ ├── joystick_driver.c
│ ├── kegs.icns
│ ├── kegsfont.h
│ ├── kegswin.sln
│ ├── kegswin.vcxproj
│ ├── ldvars
│ ├── macsnd_driver.c
│ ├── mockingboard.c
│ ├── moremem.c
│ ├── op_routs.h
│ ├── paddles.c
│ ├── protos.h
│ ├── protos_base.h
│ ├── protos_macdriver.h
│ ├── protos_macsnd_driver.h
│ ├── protos_pulseaudio_driver.h
│ ├── protos_windriver.h
│ ├── protos_xdriver.h
│ ├── pulseaudio_driver.c
│ ├── scc.c
│ ├── scc.h
│ ├── scc_socket_driver.c
│ ├── scc_unixdriver.c
│ ├── scc_windriver.c
│ ├── sim65816.c
│ ├── size_c.h
│ ├── smartport.c
│ ├── sound.c
│ ├── sound.h
│ ├── sound_driver.c
│ ├── style_check
│ ├── undeflate.c
│ ├── unshk.c
│ ├── vars
│ ├── vars_mac
│ ├── vars_mac_x
│ ├── vars_x86linux
│ ├── video.c
│ ├── voc.c
│ ├── win32snd_driver.c
│ ├── win_dirent.h
│ ├── windriver.c
│ ├── woz.c
│ └── xdriver.c
└── upstream/
├── KEGS.version
└── kegs/
├── config.kegs
├── doc/
│ ├── CHANGES.txt
│ ├── COPYING.txt
│ ├── INTERNALS.iwm.txt
│ ├── INTERNALS.overview.txt
│ ├── INTERNALS.video.txt
│ ├── INTERNALS.xdriver.txt
│ ├── README.ROM.files.txt
│ ├── README.a2.compatibility.txt
│ ├── README.compile.txt
│ ├── README.dynapro.txt
│ ├── README.kegs.txt
│ ├── README.linux.partitions.txt
│ ├── README.mac.txt
│ ├── README.serial.ports.txt
│ └── README.win32.txt
├── lib/
│ ├── 2mg.icns
│ ├── 525.icns
│ ├── MainMenu.nib
│ ├── kegsicon.icns
│ └── make_mac_icon
├── src/
│ ├── AppDelegate.swift
│ ├── Info.plist
│ ├── Kegs-Bridging-Header.h
│ ├── MainView.swift
│ ├── Makefile
│ ├── adb.c
│ ├── applesingle.c
│ ├── clock.c
│ ├── comp_swift
│ ├── compile_time.c
│ ├── config.c
│ ├── config.h
│ ├── cp_kegs_libs
│ ├── debugger.c
│ ├── defc.h
│ ├── defcomm.h
│ ├── defs_instr.h
│ ├── dependency
│ ├── disas.h
│ ├── doc.c
│ ├── dyna_filt.c
│ ├── dyna_type.c
│ ├── dyna_validate.c
│ ├── dynapro.c
│ ├── engine.h
│ ├── engine_c.c
│ ├── instable.h
│ ├── iwm.c
│ ├── iwm.h
│ ├── joystick_driver.c
│ ├── kegsfont.h
│ ├── kegswin.sln
│ ├── kegswin.vcxproj
│ ├── ldvars
│ ├── macsnd_driver.c
│ ├── mockingboard.c
│ ├── moremem.c
│ ├── op_routs.h
│ ├── paddles.c
│ ├── protos.h
│ ├── protos_base.h
│ ├── protos_macdriver.h
│ ├── protos_macsnd_driver.h
│ ├── protos_pulseaudio_driver.h
│ ├── protos_windriver.h
│ ├── protos_xdriver.h
│ ├── pulseaudio_driver.c
│ ├── scc.c
│ ├── scc.h
│ ├── scc_socket_driver.c
│ ├── scc_unixdriver.c
│ ├── scc_windriver.c
│ ├── sim65816.c
│ ├── size_c.h
│ ├── smartport.c
│ ├── sound.c
│ ├── sound.h
│ ├── sound_driver.c
│ ├── style_check
│ ├── undeflate.c
│ ├── unshk.c
│ ├── vars
│ ├── vars_mac
│ ├── vars_mac_x
│ ├── vars_x86linux
│ ├── video.c
│ ├── voc.c
│ ├── win32snd_driver.c
│ ├── win_dirent.h
│ ├── windriver.c
│ ├── woz.c
│ └── xdriver.c
└── xkegs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.o
================================================
FILE: CLAUDE.md
================================================
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
GSplus is a cross-platform Apple IIgs emulator based on KEGS (Kent's Emulated GS) by Kent Dickey. It emulates the 65816 CPU, all Apple IIgs graphics/sound modes, disk controllers, serial ports, and more. Licensed under GPLv3.
## Repository Structure
- `gsplus/src/` — Active source code and build files (this is where you build)
- `gsplus/lib/` — Icons, NIB files, and asset resources
- `upstream/kegs/` — Upstream KEGS tracked separately, merged to main when updated
- `upstream/kegs/doc/` — Comprehensive documentation (architecture internals, platform setup, compatibility)
The `upstream` branch tracks KEGS releases; `main` is the primary development branch.
## Build Commands
### macOS (default target)
```bash
cd gsplus/src
make -j 20
```
Produces `gsplus/KEGSMAC.app`. Requires Xcode with command-line tools installed.
### Linux (X11)
```bash
cd gsplus/src
rm vars; ln -s vars_x86linux vars
make -j 20
```
Produces `xkegs`. Requires `libX11-devel`, `libXext-devel`, `pulseaudio-libs-devel`.
### Windows
Open `gsplus/src/kegswin.vcxproj` in Visual Studio Community Edition and press F7.
### Clean
```bash
cd gsplus/src
make clean
```
## Architecture
### CPU & Core Loop
- `sim65816.c` — Main simulation loop, event scheduling, interrupt handling
- `engine_c.c` + `engine.h` — 65816 CPU instruction emulation (macro-heavy for performance)
- `defs_instr.h`, `instable.h`, `op_routs.h` — Instruction definitions, opcode table, operation macros
### Memory
- `moremem.c` — Memory management, page table fixup, I/O register reads/writes ($C000-$C0FF area)
- Page-table-based MMU for dynamic address mapping
### Video
- `video.c` — All Apple IIgs/II graphics mode rendering (text, lores, hires, super hires)
### Audio
- `sound.c` — Sound generation (mixing, output buffering)
- `doc.c` — Ensoniq DOC 32-voice synthesizer emulation
- `mockingboard.c` — Mockingboard A card (6522 VIA + AY-8913)
### Disk I/O
- `iwm.c` — IWM disk controller (5.25" and 3.5" drives, nibble-level accuracy)
- `smartport.c` — SmartPort controller for hard drive images
- `dynapro.c` — Host directory mounting as virtual ProDOS volumes
- `woz.c` — WOZ disk image format support
- `unshk.c`, `undeflate.c`, `applesingle.c` — Archive/compression format support
### Input
- `adb.c` — Apple Desktop Bus (keyboard, mouse)
- `scc.c` + `scc_socket_driver.c` — Serial Communications Controller with TCP/IP modem emulation
- `paddles.c`, `joystick_driver.c` — Game input
### Configuration & Debug
- `config.c` — Runtime configuration UI, disk mounting, settings persistence (`config.kegs`)
- `debugger.c` — Built-in 65816 debugger/monitor
### Platform Drivers
The emulator core is platform-independent. Platform-specific code is isolated in driver files:
| Component | macOS | Linux | Windows |
|-----------|-------|-------|---------|
| Display | `AppDelegate.swift` + `MainView.swift` | `xdriver.c` | `windriver.c` |
| Audio | `macsnd_driver.c` (CoreAudio) | `pulseaudio_driver.c` | `win32snd_driver.c` |
| Serial | `scc_unixdriver.c` | `scc_unixdriver.c` | `scc_windriver.c` |
### Key Headers
- `defc.h` — Global defines, structs, macros (included by nearly every .c file)
- `defcomm.h` — Shared defines for C and assembly
- `protos_base.h` — Function prototypes for all modules
## Build System Details
The Makefile includes `vars` (platform config) and `ldvars` (object file list). To change platforms, symlink the appropriate vars file (`vars_mac`, `vars_x86linux`, etc.) to `vars`. Swift files are compiled via the `comp_swift` wrapper script. The `dependency` file contains header dependency rules.
Compiler flags are set in `vars`: `-Wall -O2 -DMAC` for macOS. The `-DMAC` define selects macOS-specific code paths throughout the codebase.
## Runtime Requirements
The emulator needs an Apple IIgs ROM file to run. Demo disk images (`NUCLEUS03.gz`, `XMAS_DEMO.gz`) are included in `upstream/kegs/`. Configuration is stored in `config.kegs`.
## No Test Suite
There is no automated test infrastructure. Testing is done manually by running Apple IIgs software and ROM self-tests.
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. 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
them 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 prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. 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.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey 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;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU 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 that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
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.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
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.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
================================================
FILE: README.md
================================================
# gsplus
Cross-platform Apple IIgs emulator and tools based on KEGS
### About Branches
- KEGS latest is tracked in `./upstream` directory
- There is an upstream branch that is updated whenever there are new version and merged to main.
- This makes it easy to track kegs changes somewhat independently of the gsplus work.
================================================
FILE: TODO.md
================================================
# TODO
## Backlog
- [ ] Remove `#ifdef INCLUDE_RCSID_C` / `#endif` guards from header files and `#define`/`#undef INCLUDE_RCSID_C` from `sim65816.c` and `sound.c` in `gsplus/src/`. The `const char rcsid_` lines were already removed; these are the leftover scaffolding.
- [ ] Update Menubar titles for X/Win to match.. Mac build already updated to "GS+"
================================================
FILE: gsplus/lib/make_mac_icon
================================================
#!/usr/bin/perl -w
# Based on https://gist.github.com/ansarizafar/6fa64f44aa933794c4d6638eec32b9aa
# and https://github.com/retifrav/generate-iconset
# We need to create a directory of the icon in several scaled sizes,
# (the Mac command "sips" can do this), then run iconutil to form the
# .icns file.
# kegsicon.png created by Alex Lee
my $icondir;
my $img_file = "";
my $ext = ".png";
my $scale;
my $sz;
my $pixels;
my $scale_str;
if($#ARGV == 0) {
$img_file = shift;
if($img_file =~ /^.*\.(^\.*)$/) {
$ext = $1;
print "Set ext to $ext\n";
}
} else {
die "Usage: $0 image_file.jpg/.png"
}
$icondir = "./icon.iconset"; # Must have .iconset extension
if(-d $icondir) {
`rm -rf $icondir`;
}
`mkdir $icondir`;
for($scale = 1; $scale <= 2; $scale++) {
for($sz = 16; $sz <= 512; $sz = $sz * 2) {
if($sz == 64) {
next;
}
$pixels = $sz * $scale;
$scale_str = "";
if($scale == 2) {
$scale_str = '@2x';
}
@cmd = ("sips", "-z", $pixels, $pixels, $img_file,
"--matchTo",
"/System/Library/ColorSync/Profiles/sRGB\\ Profile.icc",
"--out", $icondir . "/" . "icon_" . $sz . "x" . $sz .
$scale_str . $ext);
print "cmd: @cmd\n";
`@cmd`;
}
}
print "Calling: iconutil -o kegs.icns -c icns $icondir";
`iconutil -o kegs.icns -c icns $icondir`;
`rm -rf $icondir`;
================================================
FILE: gsplus/src/AppDelegate.swift
================================================
/**********************************************************************/
/* GSplus - Apple //gs Emulator */
/* Based on KEGS by Kent Dickey */
/* Copyright 2002-2024 Kent Dickey */
/* Copyright 2025-2026 GSplus Contributors */
/* */
/* This code is covered by the GNU GPL v3 */
/* See the file COPYING.txt or https://www.gnu.org/licenses/ */
/**********************************************************************/
import Cocoa
let Context_draw = false
// Default: use safe draw function.
// If true, use NSGraphicsContext.current.data to try to write
// directly to screen memory (in a different ARGB format)
class Window_info {
var x_win : NSWindow? = nil
var mac_view : MainView? = nil
var kimage_ptr : UnsafeMutablePointer<Kimage>! = nil
var title : String = ""
var app_delegate : AppDelegate! = nil
var mac_a2_height : Int = 0
// init(_ new_is_main: Bool) {
// is_main = new_is_main
// }
func set_kimage(_ kimage_ptr : UnsafeMutablePointer<Kimage>!,
title: String, delegate: AppDelegate!) {
self.kimage_ptr = kimage_ptr
self.title = title
self.app_delegate = delegate
}
func create_window() {
let x_xpos = Int(video_get_x_xpos(kimage_ptr))
let x_ypos = Int(video_get_x_ypos(kimage_ptr))
let width = Int(video_get_x_width(kimage_ptr))
let height = Int(video_get_x_height(kimage_ptr))
let windowRect = NSRect(x: x_xpos, y: x_ypos, width: width,
height: height)
var window : NSWindow!
var view : MainView!
let style : NSWindow.StyleMask = [.titled, .closable,
.resizable]
window = NSWindow(contentRect: windowRect,
styleMask: style,
backing: .buffered, defer: false)
let viewRect = NSRect(x: 0, y: 0, width: windowRect.size.width,
height: windowRect.size.height)
print("About to init MainView");
view = MainView(frame: viewRect)
print("About to set kimage_ptr");
view.kimage_ptr = kimage_ptr;
print("About to call initialize");
view.initialize()
view.closed = false
window.delegate = app_delegate
window.contentView = view
window.makeKeyAndOrderFront(app_delegate)
window.acceptsMouseMovedEvents = true
window.title = title
window.showsToolbarButton = true
window.contentAspectRatio = NSSize(width: width, height: height)
video_set_active(kimage_ptr, Int32(1))
video_update_scale(kimage_ptr, Int32(width), Int32(height),
Int32(1))
x_win = window
mac_view = view
mac_a2_height = height;
window.makeKey()
}
func update() {
// Decide if window should be opened/closed (if it's the
// debugger window), and call mac_update_display() to update
let new_height = Int(video_get_a2_height(kimage_ptr))
let a2_active = video_get_active(kimage_ptr)
if let view = mac_view {
if(new_height != mac_a2_height) {
mac_resize_window()
}
if(a2_active == 0 && !view.closed) {
print("a2_active 0 on \(title), calling close")
x_win!.orderOut(x_win)
view.closed = true
} else if(a2_active != 0 && view.closed) {
print("Opening closed window \(title)")
view.closed = false
x_win!.orderFront(x_win)
x_win!.makeKey() // Move to front
} else if(a2_active != 0) {
view.mac_update_display()
}
if((a2_active != 0) && !view.closed) {
if(adb_get_copy_requested() != 0) {
view.do_copy_text(view);
}
}
} else {
if(a2_active != 0) {
print("Opening window \(title)")
create_window()
}
}
}
func mac_resize_window() {
let a2_height = Int(video_get_a2_height(kimage_ptr))
let a2_width = Int(video_get_a2_width(kimage_ptr))
let ratio = CGFloat(a2_height) / CGFloat(a2_width)
let cur_width = x_win!.frame.size.width
let new_height = cur_width * ratio // CGFloat
var newframe = x_win!.frame // NSRect
mac_a2_height = a2_height
newframe.size.height = new_height
x_win!.contentAspectRatio = NSSize(width: a2_width,
height: a2_height)
x_win!.setFrame(newframe, display: true, animate: true)
mac_view!.initialize()
// Must call initialize for the case where the
// status lines were enabled, we need more lines
// print("Call video_update_scale from mac_resize_window\n");
video_update_scale(kimage_ptr, Int32(x_win!.frame.width),
Int32(x_win!.frame.height), 0)
video_update_xpos_ypos(kimage_ptr, Int32(x_win!.frame.origin.x),
Int32(x_win!.frame.origin.y))
//print("Did mac_resize window to \(a2_width), \(a2_height)" +
// " frame:\(x_win!.frame.width), " +
// "\(x_win!.frame.height)" +
// " ratio:\(ratio)\n")
}
func update_window_size(width: Int, height: Int) {
// print("Call video_update_scale from update_window_size\n");
video_update_scale(kimage_ptr, Int32(width), Int32(height), 0);
}
}
@main
class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
static func main() {
let delegate = AppDelegate()
NSApplication.shared.delegate = delegate
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)
}
var mainwin_info = Window_info();
var debugwin_info = Window_info();
func find_win_info(_ window: NSWindow) -> Window_info {
if(mainwin_info.x_win == window) {
return mainwin_info
}
return debugwin_info
}
@objc func do_about(_:AnyObject) {
print("About")
if let ver_str = Bundle.main.infoDictionary?[
"CFBundleShortVersionString"] as? String {
NSApplication.shared.orderFrontStandardAboutPanel(
options: [.applicationVersion: ver_str,
.version: "", .applicationName: "GS+"])
}
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
// This is your first real entry point into the app
print("start!")
set_menu_for_kegs()
NSApp.activate(ignoringOtherApps: true) // Bring window to front
main_init()
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func applicationShouldTerminateAfterLastWindowClosed(
_ theApplication: NSApplication) -> Bool {
// Application will close if main window is closed
return true
}
func windowDidBecomeKey(_ notification: Notification) {
if let w = notification.object as? NSWindow {
if(w == mainwin_info.x_win) {
adb_mainwin_focus(Int32(1));
//print("Main window became KEY")
}
}
//print("DidbecomeKey")
// If window focus is changing, turn off key repeat
adb_kbd_repeat_off()
}
func windowDidResignKey(_ notification: Notification) {
//print("DidResignKey")
adb_kbd_repeat_off()
adb_mainwin_focus(Int32(0))
CGDisplayShowCursor(CGMainDisplayID())
}
func windowDidMove(_ notification: Notification) {
//print("DidMove")
if let w = notification.object as? NSWindow {
let win_info = find_win_info(w)
video_update_xpos_ypos(win_info.kimage_ptr,
Int32(w.frame.origin.x),
Int32(w.frame.origin.y))
}
}
func windowWillResize(_ window: NSWindow, to frameSize: NSSize)
-> NSSize {
// print("WILL RESIZE app \(frameSize)")
let width = Int(frameSize.width)
let height = Int(frameSize.height)
let win_info = find_win_info(window)
win_info.update_window_size(width: width, height: height)
return frameSize
}
func windowShouldClose(_ window: NSWindow) -> Bool {
print("windowShouldClose")
let win_info = find_win_info(window)
if(mainwin_info.x_win == window) {
// User has clicked the close box on the main emulator
// window. Just exit the app
NSApp.terminate(window)
return true // Let main window close
} else {
video_set_active(win_info.kimage_ptr, Int32(0))
win_info.update()
return false
}
}
func set_menu_for_kegs() {
let appname = "Kegs"
let menu = NSMenu(title: "MainMenu")
NSApp.mainMenu = menu
print("Installing my menu now")
// Add "Kegs" menu
let kegs = NSMenu(title: appname)
kegs.addItem(withTitle: "About \(appname)",
action: #selector(AppDelegate.do_about(_:)),
keyEquivalent: "")
kegs.addItem(NSMenuItem.separator())
let quit_item = NSMenuItem(title: "Quit \(appname)",
action: #selector(NSApplication.terminate(_:)),
keyEquivalent: "q")
quit_item.keyEquivalentModifierMask = [.option,
.command ]
kegs.addItem(quit_item)
let kegs_item = NSMenuItem()
kegs_item.title = appname
kegs_item.submenu = kegs
menu.addItem(kegs_item)
// Add "Edit" menu
let edit = NSMenu(title: "Edit")
edit.addItem(withTitle: "Copy Text Screen",
action: #selector(MainView.do_copy_text(_:)),
keyEquivalent: "")
edit.addItem(NSMenuItem.separator())
edit.addItem(withTitle: "Paste",
action: #selector(MainView.do_paste(_:)),
keyEquivalent: "")
let edit_item = NSMenuItem()
edit_item.title = "Edit"
edit_item.submenu = edit
menu.addItem(edit_item)
// Add "Config" menu
let config = NSMenu(title: "Config")
config.addItem(withTitle: "Configuration F4",
action: #selector(MainView.do_config(_:)),
keyEquivalent: "")
let config_item = NSMenuItem()
config_item.title = "Config"
config_item.submenu = config
menu.addItem(config_item)
show_menu(menu, depth: 0)
}
func show_menu(_ menu: NSMenu, depth: Int) {
if(depth >= -10) {
return // HACK: remove to see debug output!
}
print("menu at depth \(depth): \(menu.title)")
if(depth > 5) { // Prevent infinite recursion
return
}
for menuit in menu.items {
print("menuit: depth:\(depth) \(menuit.title)")
print(" keyeq:\(menuit.keyEquivalent)")
print(" modifiers:\(menuit.keyEquivalentModifierMask)")
print(" isSeparator:\(menuit.isSeparatorItem)")
if let sub = menuit.submenu {
show_menu(sub, depth: depth+1)
}
}
}
var mainWindow : NSWindow!
var mainwin_view : MainView!
func main_init() {
var kimage_ptr : UnsafeMutablePointer<Kimage>!
var rect = NSRect.zero
let argc = CommandLine.argc
let argv = CommandLine.unsafeArgv
parse_argv(argc, argv, 3);
rect.size.width = 2560
rect.size.height = 1440
if let screen = NSScreen.main {
rect = screen.frame
}
kegs_init(24, Int32(rect.size.width), Int32(rect.size.height),
Int32(1))
if(Context_draw) {
video_set_blue_mask(UInt32(0x0000ff))
video_set_green_mask(UInt32(0x00ff00))
video_set_red_mask(UInt32(0xff0000))
} else {
video_set_red_mask(UInt32(0x0000ff))
video_set_green_mask(UInt32(0x00ff00))
video_set_blue_mask(UInt32(0xff0000))
}
video_set_palette()
kimage_ptr = video_get_kimage(Int32(0))
mainwin_info.set_kimage(kimage_ptr, title: "GS+",
delegate: self)
kimage_ptr = video_get_kimage(Int32(1))
debugwin_info.set_kimage(kimage_ptr, title: "Debugger",
delegate: self)
mainwin_info.create_window()
NSApp.activate(ignoringOtherApps: true)
main_run_loop()
}
func main_run_loop() {
DispatchQueue.main.asyncAfter(deadline: .now() +
.milliseconds(1)) {
self.main_run_loop()
}
let ret = run_16ms()
if(ret != 0) {
exit(ret);
}
mainwin_info.update()
debugwin_info.update()
}
}
================================================
FILE: gsplus/src/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>18G103</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>KEGSMAC</string>
<key>CFBundleIconFile</key>
<string>kegs.icns</string>
<key>CFBundleIdentifier</key>
<string>com.provalid.Kegs</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Kegs</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.38</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>11A1027</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>19A547</string>
<key>DTSDKName</key>
<string>macosx10.15</string>
<key>DTXcode</key>
<string>1110</string>
<key>DTXcodeBuild</key>
<string>11A1027</string>
<key>LSMinimumSystemVersion</key>
<string>10.13</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2025 Kent Dickey. All rights reserved.</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
================================================
FILE: gsplus/src/Kegs-Bridging-Header.h
================================================
// $KmKId: Kegs-Bridging-Header.h,v 1.1 2019-10-14 22:33:09+00 kentd Exp $
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "defc.h"
================================================
FILE: gsplus/src/MainView.swift
================================================
// $KmKId: MainView.swift,v 1.42 2024-09-15 13:55:35+00 kentd Exp $
// Copyright 2019-2024 by Kent Dickey
// This code is covered by the GNU GPL v3
// See the file COPYING.txt or https://www.gnu.org/licenses/
//
import Cocoa
import CoreGraphics
import AudioToolbox
class MainView: NSView {
var bitmapContext : CGContext!
var bitmapData : UnsafeMutableRawPointer!
var rawData : UnsafeMutablePointer<UInt32>!
var current_flags : UInt = 0
var mouse_moved : Bool = false
var mac_warp_pointer : Int32 = 0
var mac_hide_pointer : Int32 = 0
var kimage_ptr : UnsafeMutablePointer<Kimage>!
var closed : Bool = false
var pixels_per_line = 640
var max_height = 600
let is_cmd = UInt(NSEvent.ModifierFlags.command.rawValue)
let is_control = UInt(NSEvent.ModifierFlags.control.rawValue)
let is_shift = NSEvent.ModifierFlags.shift.rawValue
let is_capslock = NSEvent.ModifierFlags.capsLock.rawValue
let is_option = NSEvent.ModifierFlags.option.rawValue
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
func windowDidResize(_ notification: Notification) {
print("DID RESIZE")
}
override func performKeyEquivalent(with event: NSEvent) -> Bool {
let keycode = event.keyCode
let is_repeat = event.isARepeat
let unicode_key = get_unicode_key_from_event(event)
// print(".performKeyEquiv keycode: \(keycode), is_repeat: " +
// "\(is_repeat)")
if(((current_flags & is_cmd) == 0) || is_repeat) {
// If CMD isn't being held down, just ignore this
return false
}
// Otherwise, manually do down, then up, for this key
adb_physical_key_update(kimage_ptr, Int32(keycode),
UInt32(unicode_key), 0);
adb_physical_key_update(kimage_ptr, Int32(keycode),
UInt32(unicode_key), 1);
return true
}
override var acceptsFirstResponder: Bool {
return true
}
func get_unicode_key_from_event(_ event: NSEvent) -> UInt32 {
var unicode_key = UInt32(0);
if let str = event.charactersIgnoringModifiers {
//print(" keydown unmod str: \(str), " +
// "code:\(event.keyCode)")
let arr_chars = Array(str.unicodeScalars)
//print(" arr_chars: \(arr_chars)")
if(arr_chars.count == 1) {
unicode_key = UInt32(arr_chars[0]);
//print("key1:\(unicode_key)")
}
}
return unicode_key
}
override func keyDown(with event: NSEvent) {
let keycode = event.keyCode
let is_repeat = event.isARepeat;
// print(".keyDown code: \(keycode), repeat: \(is_repeat)")
//if let str = event.characters {
// print(" keydown str: \(str), code:\(keycode)")
//}
let unicode_key = get_unicode_key_from_event(event)
if(is_repeat) {
// If we do CMD-E, then we never get a down for the E,
// but we will get repeat events for that E. Let's
// ignore those
return
}
adb_physical_key_update(kimage_ptr, Int32(keycode),
UInt32(unicode_key), 0);
}
override func keyUp(with event: NSEvent) {
let keycode = event.keyCode
// let is_repeat = event.isARepeat;
// print(".keyUp code: \(keycode), repeat: \(is_repeat)")
let unicode_key = get_unicode_key_from_event(event)
adb_physical_key_update(kimage_ptr, Int32(keycode),
UInt32(unicode_key), 1);
}
override func flagsChanged(with event: NSEvent) {
let flags = event.modifierFlags.rawValue &
(is_cmd | is_control | is_shift | is_capslock |
is_option)
var c025_val = UInt32(0);
if((flags & is_shift) != 0) {
c025_val |= 1;
}
if((flags & is_control) != 0) {
c025_val |= 2;
}
if((flags & is_capslock) != 0) {
c025_val |= 4;
}
if((flags & is_option) != 0) {
c025_val |= 0x40;
}
if((flags & is_cmd) != 0) {
c025_val |= 0x80;
}
adb_update_c025_mask(kimage_ptr, c025_val, UInt32(0xc7));
current_flags = flags
//print("flagsChanged: \(flags) and keycode: \(event.keyCode)")
}
override func acceptsFirstMouse(for event: NSEvent?) -> Bool {
// This is to let the first click when changing to this window
// through to the app, I probably don't want this.
return false
}
override func mouseMoved(with event: NSEvent) {
//let type = event.eventNumber
//print(" event type: \(type)")
mac_update_mouse(event: event, buttons_state:0, buttons_valid:0)
}
override func mouseDragged(with event: NSEvent) {
mac_update_mouse(event: event, buttons_state: 0,
buttons_valid: 0)
}
override func otherMouseDown(with event: NSEvent) {
mac_update_mouse(event: event, buttons_state:2, buttons_valid:2)
}
override func otherMouseUp(with event: NSEvent) {
mac_update_mouse(event: event, buttons_state:0, buttons_valid:2)
}
override func mouseEntered(with event: NSEvent) {
print("mouse entered")
}
override func rightMouseUp(with event: NSEvent) {
mac_update_mouse(event: event, buttons_state:0, buttons_valid:4)
}
override func rightMouseDown(with event: NSEvent) {
print("Right mouse down")
mac_update_mouse(event: event, buttons_state:4, buttons_valid:4)
}
override func mouseUp(with event: NSEvent) {
// print("Mouse up \(event.locationInWindow.x)," +
// "\(event.locationInWindow.y)")
mac_update_mouse(event: event, buttons_state:0, buttons_valid:1)
}
override func mouseDown(with event: NSEvent) {
//print("Mouse down \(event.locationInWindow.x)," +
// "\(event.locationInWindow.y)")
mac_update_mouse(event: event, buttons_state:1, buttons_valid:1)
}
func mac_update_mouse(event: NSEvent, buttons_state: Int,
buttons_valid: Int) {
var warp = Int32(0)
var x_width = 0
var y_height = 0
var x = Int32(0)
var y = Int32(0)
var do_delta = Int(0)
let hide = adb_get_hide_warp_info(kimage_ptr, &warp)
if(warp != mac_warp_pointer) {
mouse_moved = true
}
mac_warp_pointer = warp
if(mac_hide_pointer != hide) {
mac_hide_pointer(hide: hide)
}
mac_hide_pointer = hide
let location = event.locationInWindow
if(!Context_draw) {
// We're letting the Mac scale the window for us,
// so video_scale_mouse*() doesn't know the scale
// factor, so pass it in
x_width = Int(bounds.size.width);
y_height = Int(bounds.size.height);
}
let raw_x = location.x
let raw_y = bounds.size.height - 1 - location.y
// raw_y is 0 at the top of the window now
x = video_scale_mouse_x(kimage_ptr, Int32(raw_x),
Int32(x_width))
y = video_scale_mouse_y(kimage_ptr, Int32(raw_y),
Int32(y_height))
do_delta = 0;
if(mac_warp_pointer != 0) {
do_delta |= 0x1000; // x,y are deltas
x = Int32(event.deltaX)
y = Int32(event.deltaY)
}
let ret = adb_update_mouse(kimage_ptr, x, y,
Int32(buttons_state),
Int32(buttons_valid | do_delta))
if(ret != 0) {
mouse_moved = true
}
guard let win = window else {
return // No valid window
}
if(mouse_moved) {
var rect1 = NSRect.zero
// If warp, warp cursor to middle of window. Moving
// the cursor requires absolute screen coordinates,
// where y=0 is the top of the screen. We must convert
// window coords (where y=0 is the bottom of the win).
mouse_moved = false
let warp_x = CGFloat(video_unscale_mouse_x(kimage_ptr,
Int32(A2_WINDOW_WIDTH/2), Int32(x_width)))
let warp_y = CGFloat(video_unscale_mouse_y(kimage_ptr,
Int32(A2_WINDOW_HEIGHT/2), Int32(y_height)))
let scr_height = CGDisplayPixelsHigh(CGMainDisplayID());
rect1.origin.x = CGFloat(warp_x)
rect1.origin.y = bounds.size.height - 1 -
CGFloat(warp_y)
rect1.size.width = 1;
rect1.size.height = 0;
let screen_rect = win.convertToScreen(rect1)
let screen_rect_y = CGFloat(scr_height) -
screen_rect.origin.y
let cg_loc = CGPoint(x: screen_rect.origin.x,
y: CGFloat(screen_rect_y))
//print("scr_rect:\(screen_rect)")
if(warp != 0) {
// Warp to middle of the window
CGDisplayMoveCursorToPoint(CGMainDisplayID(),
cg_loc);
}
}
}
func mac_hide_pointer(hide: Int32) {
// print("Hide called: \(hide)")
if(hide != 0) {
CGDisplayHideCursor(CGMainDisplayID())
} else {
CGDisplayShowCursor(CGMainDisplayID())
}
}
func initialize() {
//let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)
print("Initialize view called")
// Get width,height from video.c to handle toggling status lines
let width = Int(video_get_a2_width(kimage_ptr))
let height = Int(video_get_a2_height(kimage_ptr))
//if let screen = NSScreen.main {
// let rect = screen.frame
// width = Int(rect.size.width)
// height = Int(rect.size.height)
//}
pixels_per_line = width
max_height = height
//print("pixels_per_line: \(pixels_per_line), " +
// "max_height: \(max_height)")
let color_space = CGDisplayCopyColorSpace(CGMainDisplayID())
//let colorSpace = CGColorSpaceCreateDeviceRGB()
bitmapContext = CGContext(data: nil, width: width,
height: height, bitsPerComponent: 8,
bytesPerRow: width * 4,
space: color_space,
bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue)
//CGImageAlphaInfo.noneSkipLast.rawValue
bitmapData = bitmapContext.data!
// Set the intial value of the data to black (0)
bitmapData.initializeMemory(as: UInt32.self, repeating: 0,
count: height * width)
rawData = bitmapData.bindMemory(to: UInt32.self,
capacity: height * width)
//print("Calling video_update_scale from MainViewinitialize()")
let x_width = Int(video_get_x_width(kimage_ptr))
let x_height = Int(video_get_x_height(kimage_ptr))
video_update_scale(kimage_ptr, Int32(x_width), Int32(x_height),
Int32(1))
if(Context_draw) {
video_set_alpha_mask(UInt32(0xff000000))
// Set video.c alpha mask, since 0 means transparent
}
}
override func draw(_ dirtyRect: NSRect) {
var rect : Change_rect
//super.draw(dirtyRect)
// Documentation says super.draw not needed...
// Draw the current image buffer to the screen
let context = NSGraphicsContext.current!.cgContext
if(!Context_draw) {
// Safe, simple drawing
let image = bitmapContext.makeImage()!
context.draw(image, in: bounds)
// The above call does the actual copy of
// data to the screen, and can take a while
//print("Draw, bounds:\(bounds), dirtyr:\(dirtyRect)")
} else {
// Unsafe, more direct drawing by peeking into
// NSGraphicsContext.current.data
if let data = context.data {
rect = Change_rect(x:0, y:0,
width:Int32(context.width),
height:Int32(context.height));
video_update_scale(kimage_ptr,
Int32(context.width),
Int32(context.height), Int32(0))
video_out_data_scaled(data, kimage_ptr,
Int32(context.bytesPerRow/4), &rect);
video_out_done(kimage_ptr);
print("Did out_data_scaled, rect:\(rect)");
}
}
}
@objc func do_config(_ : AnyObject) {
// Create a "virtual" F4 press
//print("do_config")
// Create a keydown for the F4 key (keycode:0x76)
adb_physical_key_update(kimage_ptr, Int32(0x76), 0, 0);
// and create a keyup for the F4 key (keycode:0x76)
adb_physical_key_update(kimage_ptr, Int32(0x76), 0, 1);
}
@objc func do_copy_text(_ : AnyObject) {
// print("do_copy");
//let text_buf_cstr = UnsafeMutablePointer<Int8>.allocate(
// capacity: 2100);
if let cstr = cfg_text_screen_str() {
let str = String(cString: cstr);
NSPasteboard.general.clearContents();
NSPasteboard.general.setString(str,
forType: NSPasteboard.PasteboardType.string);
}
}
@objc func do_paste(_ : AnyObject) {
// print("do_paste")
let general = NSPasteboard.general;
guard let str = general.string(forType: .string) else {
print("Cannot paste, nothing in clipboard");
return
}
//print("str: \(str)")
for raw_c in str.utf8 {
let c = UInt32(raw_c)
let ret = adb_paste_add_buf(c)
if(ret != 0) {
print("Paste too large!")
return;
}
}
}
func mac_update_display() {
var valid : Int32
var rect : Change_rect
var dirty_rect = NSRect.zero
if(Context_draw) {
// We just need to know if there are any changes,
// don't actually do the copies now
valid = video_out_query(kimage_ptr);
if(valid != 0) {
self.setNeedsDisplay(bounds)
print("Needs display");
}
return;
}
// Otherwise, update rawData in our Bitmap now
rect = Change_rect(x:0, y:0, width:0, height:0)
for i in 0..<MAX_CHANGE_RECTS { // MAX_CHANGE_RECTS
valid = video_out_data(rawData, kimage_ptr,
Int32(pixels_per_line), &rect, Int32(i))
if(valid == 0) {
break
}
dirty_rect.origin.x = CGFloat(rect.x)
dirty_rect.origin.y = bounds.size.height -
CGFloat(rect.y) - CGFloat(rect.height)
dirty_rect.size.width = CGFloat(rect.width)
dirty_rect.size.height = CGFloat(rect.height)
self.setNeedsDisplay(bounds)
// It's necessary to redraw the whole screen,
// there's no mechanism to just redraw part
// The coordinates would need transformation
// (since Mac 0,0 is the lower left corner)
//print("bounds: w:\(bounds.size.width) " +
// "h:\(bounds.size.height)\n")
//self.setNeedsDisplay(dirty_rect)
}
}
}
================================================
FILE: gsplus/src/Makefile
================================================
# $KmKId: makefile,v 1.48 2025-04-28 15:12:19+00 kentd Exp $
XOPTS_WIN = -Wall -fomit-frame-pointer -march=pentium
SWIFTOBJS = AppDelegate.o MainView.o
include vars
include ldvars
.SUFFIXES: .dep .proto
AS = $(CC)
XLIBS = -L/usr/X11/lib
PERL = perl
all: $(TARGET)
specials:
specials_clean:
clean:
rm -f *.o gsplus
# Mac builds:
gsplus: $(OBJECTS) $(OBJECTS1) compile_time.o $(SWIFTOBJS)
clang $(CCOPTS) $(LDOPTS) $(OBJECTS) $(OBJECTS1) $(SWIFTOBJS) \
compile_time.o $(LDFLAGS) -o gsplus $(EXTRA_LIBS) \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk \
-Xlinker -rpath -Xlinker @executable_path/../Frameworks \
-Xlinker -rpath -Xlinker /usr/lib/swift \
-Xlinker -no_deduplicate -fobjc-link-runtime \
-L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx \
-L/usr/lib/swift
mkdir -p ../GSplus.app/Contents/MacOS
mkdir -p ../GSplus.app/Contents/Frameworks
$(PERL) cp_gsplus_libs gsplus /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx ../GSplus.app/Contents/Frameworks
mv gsplus ../GSplus.app/Contents/MacOS/GSplus
echo "APPL????" > ../GSplus.app/Contents/PkgInfo
cp -f Info.plist ../GSplus.app/Contents/
$(PROJROOT)/lib/make_mac_icon $(PROJROOT)/lib/kegsicon.png
cp -f kegs.icns ../GSplus.app/Contents/Resources/
touch '../GSplus.app/Icon?'
#cp -f $(PROJROOT)/lib/2mg.icns ../GSplus.app/Contents/Resources/
#cp -f $(PROJROOT)/lib/525.icns ../GSplus.app/Contents/Resources/
# Linux for X builds:
gsplus-x: $(OBJECTS) $(OBJECTS1) compile_time.o
$(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) $(OBJECTS1) compile_time.o \
$(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) \
-lX11 -lXext
mv gsplus ..
# Cygwin for X builds:
gsplus.exe: $(OBJECTS) $(OBJECTS1) compile_time.o
$(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) $(OBJECTS1) compile_time.o \
$(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) \
-lXext -lX11 -lm
mv gsplus.exe ..
# Mingw32 (native windows) builds: (broken, doesn't work currently)
gspluswin.exe: $(OBJECTS) $(OBJECTS1) compile_time.o
$(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) $(OBJECTS1) compile_time.o \
$(LDFLAGS) -o $(NAME)$(SUFFIX) $(EXTRA_LIBS) \
-lwinmm -lgdi32 -ldsound -lcomctl32 -lws2_32
mv $(NAME)$(SUFFIX) ..
.s.o:
$(AS) -c $(OPTS) -I. $*.s
.c.o:
$(CC) $(CCOPTS) $(XOPTS) -c $(OPTS) -I. $*.c
.m.o:
$(CC) $(CCOPTS) $(XOPTS) -c $(OPTS) -I. $*.m
AppDelegate.o: AppDelegate.swift
sh ./comp_swift -c $(OPTS) -I. -primary-file $*.swift \
MainView.swift -o $*.o
MainView.o: MainView.swift
sh ./comp_swift -c $(OPTS) -I. -primary-file $*.swift \
AppDelegate.swift -o $*.o
win32.o: win32.rc
windres -o win32.o win32.rc
.c.proto:
$(KMKROOT)/bin/kmkproto $(XOPTS) $*.c > $*.proto
echo >> $*.proto
.m.proto:
$(KMKROOT)/bin/kmkproto $(XOPTS) $*.m > $*.proto
echo >> $*.proto
$(PROTO_OUT): $(PROTO_FILE_LIST) ldvars proto_vars
$(KMKROOT)/bin/kmkproto_head $(PROTO_OUT) tmp_protos.h
cat /dev/null $(PROTO_FILE_LIST) >> tmp_protos.h
rm -f $(PROTO_OUT)
mv tmp_protos.h $(PROTO_OUT)
kmk_cp_if_diff $(PROTO_OUT) ..
rm -f *.proto
compile_time.o: $(OBJECTS) $(OBJECTS1)
include dependency
================================================
FILE: gsplus/src/adb.c
================================================
/**********************************************************************/
/* GSplus - Apple //gs Emulator */
/* Based on KEGS by Kent Dickey */
/* Copyright 2002-2024 Kent Dickey */
/* Copyright 2025-2026 GSplus Contributors */
/* */
/* This code is covered by the GNU GPL v3 */
/* See the file COPYING.txt or https://www.gnu.org/licenses/ */
/**********************************************************************/
/* adb_mode bit 3 and bit 2 (faster repeats for arrows and space/del) not done*/
#include "defc.h"
extern int Verbose;
extern word32 g_vbl_count;
extern int g_num_lines_prev_superhires640;
extern int g_num_lines_prev_superhires;
extern int g_rom_version;
extern int g_fast_disk_emul_en;
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_config_control_panel;
extern int g_status_enable;
extern dword64 g_cur_dfcyc;
extern byte *g_slow_memory_ptr;
extern byte *g_memory_ptr;
extern word32 g_mem_size_total;
extern Kimage g_mainwin_kimage;
extern Kimage g_debugwin_kimage;
enum {
ADB_IDLE = 0,
ADB_IN_CMD,
ADB_SENDING_DATA,
};
#define ADB_C027_MOUSE_DATA 0x80
#define ADB_C027_MOUSE_INT 0x40
#define ADB_C027_DATA_VALID 0x20
#define ADB_C027_DATA_INT 0x10
#define ADB_C027_KBD_VALID 0x08
#define ADB_C027_KBD_INT 0x04
#define ADB_C027_MOUSE_COORD 0x02
#define ADB_C027_CMD_FULL 0x01
#define ADB_C027_NEG_MASK ( ~ ( \
ADB_C027_MOUSE_DATA | ADB_C027_DATA_VALID | \
ADB_C027_KBD_VALID | ADB_C027_MOUSE_COORD | \
ADB_C027_CMD_FULL))
int halt_on_all_c027 = 0;
word32 g_adb_repeat_delay = 45;
word32 g_adb_repeat_rate = 3;
word32 g_adb_repeat_info = 0x23;
word32 g_adb_char_set = 0x0;
word32 g_adb_layout_lang = 0x0;
word32 g_adb_interrupt_byte = 0;
int g_adb_state = ADB_IDLE;
word32 g_adb_cmd = (word32)-1;
int g_adb_cmd_len = 0;
int g_adb_cmd_so_far = 0;
word32 g_adb_cmd_data[16];
#define MAX_ADB_DATA_PEND 16
word32 g_adb_data[MAX_ADB_DATA_PEND];
int g_adb_data_pending = 0;
word32 g_c027_val = 0;
word32 g_c025_val = 0;
byte adb_memory[256];
word32 g_adb_mode = 0; /* mode set via set_modes, clear_modes */
int g_warp_pointer = 0;
int g_hide_pointer = 0;
int g_unhide_pointer = 0;
int g_adb_copy_requested = 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
STRUCT(Mouse_fifo) {
dword64 dfcyc;
int x;
int y;
int buttons;
};
Mouse_fifo g_mouse_fifo[ADB_MOUSE_FIFO] = { { 0, 0, 0, 0 } };
int g_adb_mouse_valid_data = 0;
int g_adb_mouse_coord = 0;
#define MAX_KBD_BUF 8
#define MAX_KBD_PASTE_BUF 32768
int g_adb_mainwin_has_focus = 1;
#if defined(__linux__) || defined(_WIN32)
int g_adb_swap_command_option = 1; // Default to swap on Linux/Win
#else
int g_adb_swap_command_option = 0;
#endif
int g_key_down = 0;
int g_hard_key_down = 0;
int g_a2code_down = 0;
int g_kbd_read_no_update = 0;
int g_kbd_chars_buffered = 0;
int g_kbd_buf[MAX_KBD_BUF];
int g_kbd_paste_rd_pos = 0;
int g_kbd_paste_wr_pos = 0;
byte g_kbd_paste_buf[MAX_KBD_PASTE_BUF];
word32 g_kbd_paste_last_key = 0;
word32 g_adb_repeat_vbl = 0;
int g_kbd_dev_addr = 2; /* ADB physical kbd addr */
int g_mouse_dev_addr = 3; /* ADB physical mouse addr */
int g_kbd_ctl_addr = 2; /* ADB microcontroller's kbd addr */
int g_mouse_ctl_addr = 3; /* ADB ucontroller's mouse addr*/
/* above are ucontroller's VIEW of where mouse/kbd */
/* are...if they are moved, mouse/keyboard funcs */
/* should stop (c025, c000, c024, etc). */
word32 g_virtual_key_up[4]; /* bitmask of all possible 128 a2codes */
/* indicates which keys are up=1 by bit */
int g_rawa2_to_a2code[128];
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) )
#define OPTION_DOWN ( (g_c025_val & 0x40) )
#define CMD_DOWN ( (g_c025_val & 0x80) )
#define MAX_ADB_KBD_REG3 16
int g_kbd_reg0_pos = 0;
int g_kbd_reg0_data[MAX_ADB_KBD_REG3];
int g_kbd_reg3_16bit = 0x602; /* also set in adb_reset()! */
int g_adb_init = 0;
/* Format: a2code, ascii if no shift, ascii if shift, ascii if ctl */
const int g_a2_key_to_ascii[][4] = {
{ 0x00, 'a', 'A', 0x01 },
{ 0x01, 's', 'S', 0x13 },
{ 0x02, 'd', 'D', 0x04 },
{ 0x03, 'f', 'F', 0x06 },
{ 0x04, 'h', 'H', 0x08 },
{ 0x05, 'g', 'G', 0x07 },
{ 0x06, 'z', 'Z', 0x1a },
{ 0x07, 'x', 'X', 0x18 },
{ 0x08, 'c', 'C', 0x03 },
{ 0x09, 'v', 'V', 0x16 },
{ 0x0a, -1, -1, -1 },
{ 0x0b, 'b', 'B', 0x02 },
{ 0x0c, 'q', 'Q', 0x11 },
{ 0x0d, 'w', 'W', 0x17 },
{ 0x0e, 'e', 'E', 0x05 },
{ 0x0f, 'r', 'R', 0x12 },
{ 0x10, 'y', 'Y', 0x19 },
{ 0x11, 't', 'T', 0x14 },
{ 0x12, '1', '!', -1 },
{ 0x13, '2', '@', 0x00 },
{ 0x14, '3', '#', -1 },
{ 0x15, '4', '$', -1 },
{ 0x16, '6', '^', 0x1e },
{ 0x17, '5', '%', -1 },
{ 0x18, '=', '+', -1 },
{ 0x19, '9', '(', -1 },
{ 0x1a, '7', '&', -1 },
{ 0x1b, '-', '_', 0x1f },
{ 0x1c, '8', '*', -1 },
{ 0x1d, '0', ')', -1 },
{ 0x1e, ']', '}', 0x1d },
{ 0x1f, 'o', 'O', 0x0f },
{ 0x20, 'u', 'U', 0x15 },
{ 0x21, '[', '{', 0x1b },
{ 0x22, 'i', 'I', 0x09 },
{ 0x23, 'p', 'P', 0x10 },
{ 0x24, 0x0d, 0x0d, -1 }, /* return */
{ 0x25, 'l', 'L', 0x0c },
{ 0x26, 'j', 'J', 0x0a },
{ 0x27, 0x27, '"', -1 }, /* single quote */
{ 0x28, 'k', 'K', 0x0b },
{ 0x29, ';', ':', -1 },
{ 0x2a, 0x5c, '|', 0x1c }, /* \, | */
{ 0x2b, ',', '<', -1 },
{ 0x2c, '/', '?', 0x7f },
{ 0x2d, 'n', 'N', 0x0e },
{ 0x2e, 'm', 'M', 0x0d },
{ 0x2f, '.', '>', -1 },
{ 0x30, 0x09, 0x09, -1 }, /* tab */
{ 0x31, ' ', ' ', -1 },
{ 0x32, '`', '~', -1 },
{ 0x33, 0x7f, 0x7f, -1 }, /* Delete */
{ 0x34, -1, -1, -1 },
{ 0x35, 0x1b, 0x1b, -1 }, /* Esc */
{ 0x36, 0x0200, 0x0200, -1 }, /* control */
{ 0x37, 0x8000, 0x8000, -1 }, /* Command */
{ 0x38, 0x0100, 0x0100, -1 }, /* shift */
{ 0x39, 0x0400, 0x0400, -1 }, /* caps lock */
{ 0x3a, 0x4000, 0x4000, -1 }, /* Option */
{ 0x3b, 0x08, 0x08, -1 }, /* left */
{ 0x3c, 0x15, 0x15, -1 }, /* right */
{ 0x3d, 0x0a, 0x0a, -1 }, /* down */
{ 0x3e, 0x0b, 0x0b, -1 }, /* up arrow */
{ 0x3f, -1, -1, -1 },
{ 0x40, -1, -1, -1 },
{ 0x41, 0x102e, 0x102c, -1 }, /* keypad . */
{ 0x42, -1, -1, -1 },
{ 0x43, 0x102a, 0x102a, -1 }, /* keypad * */
{ 0x44, -1, -1, -1 },
{ 0x45, 0x102b, 0x102b, -1 }, /* keypad + */
{ 0x46, -1, -1, -1 },
{ 0x47, 0x1018, 0x1018, -1 }, /* keypad Clear */
{ 0x48, -1, -1, -1 },
{ 0x49, -1, -1, -1 },
{ 0x4a, -1, -1, -1 },
{ 0x4b, 0x102f, 0x102f, -1 }, /* keypad / */
{ 0x4c, 0x100d, 0x100d, -1 }, /* keypad enter */
{ 0x4d, -1, -1, -1 },
{ 0x4e, 0x102d, 0x102d, -1 }, /* keypad - */
{ 0x4f, -1, -1, -1 },
{ 0x50, -1, -1, -1 },
{ 0x51, 0x103d, 0x103d, -1 }, /* keypad = */
{ 0x52, 0x1030, 0x1030, -1 }, /* keypad 0 */
{ 0x53, 0x1031, 0x1031, -1 }, /* keypad 1 */
{ 0x54, 0x1032, 0x1032, -1 }, /* keypad 2 */
{ 0x55, 0x1033, 0x1033, -1 }, /* keypad 3 */
{ 0x56, 0x1034, 0x1034, -1 }, /* keypad 4 */
{ 0x57, 0x1035, 0x1035, -1 }, /* keypad 5 */
{ 0x58, 0x1036, 0x1036, -1 }, /* keypad 6 */
{ 0x59, 0x1037, 0x1037, -1 }, /* keypad 7 */
{ 0x5a, 'a', 'A', 0x01 }, /* probably not necessary */
{ 0x5b, 0x1038, 0x1038, -1 }, /* keypad 8 */
{ 0x5c, 0x1039, 0x1039, -1 }, /* keypad 9 */
{ 0x5d, -1, -1, -1 },
{ 0x5e, -1, -1, -1 },
{ 0x5f, -1, -1, -1 },
{ 0x60, 0x8005, 0x1060, -1 }, /* F5 */
{ 0x61, 0x8006, 0x1061, -1 }, /* F6 */
{ 0x62, 0x8007, 0x1062, -1 }, /* F7 */
{ 0x63, 0x8003, 0x1063, -1 }, /* F3 */
{ 0x64, 0x8008, 0x1064, -1 }, /* F8 */
{ 0x65, 0x8009, 0x1065, -1 }, /* F9 */
{ 0x66, -1, -1, -1 },
{ 0x67, 0x800b, 0x1067, -1 }, /* F11 */
{ 0x68, -1, -1, -1 },
{ 0x69, 0x800d, 0x1069, -1 }, /* F13 */
{ 0x6a, -1, -1, -1 },
{ 0x6b, 0x800e, 0x106b, -1 }, /* F14 */
{ 0x6c, -1, -1, -1 },
{ 0x6d, 0x800a, 0x106d, -1 }, /* F10 */
{ 0x6e, 0x4000, 0x4000, -1 }, /* windows key alias to option */
{ 0x6f, 0x800c, 0x106f, -1 }, /* F12 */
{ 0x70, -1, -1, -1 },
{ 0x71, 0x800f, 0x1071, -1 }, /* F15 */
{ 0x72, 0x1072, 0x1072, -1 }, /* Help, insert */
{ 0x73, 0x1073, 0x1073, -1 }, /* Home */
{ 0x74, 0x1074, 0x1074, -1 }, /* Page up */
{ 0x75, 0x1075, 0x1075, -1 }, /* keypad delete */
{ 0x76, 0x8004, 0x1076, -1 }, /* F4 */
{ 0x77, 0x1077, 0x1077, -1 }, /* keypad end */
{ 0x78, 0x8002, 0x1078, -1 }, /* F2 */
{ 0x79, 0x1079, 0x1079, -1 }, /* keypad page down */
{ 0x7a, 0x8001, 0x107a, -1 }, /* F1 */
{ 0x7b, 0x08, 0x08, -1 }, /* left */ /* remapped to 0x3b */
{ 0x7c, 0x15, 0x15, -1 }, /* right */ /* remapped to 0x3c */
{ 0x7d, 0x0a, 0x0a, -1 }, /* down */ /* remapped to 0x3d */
{ 0x7e, 0x0b, 0x0b, -1 }, /* up arrow */ /* remapped to 0x3e */
{ 0x7f, -1, -1, -1 }, /* Reset */
};
int
adb_get_hide_warp_info(Kimage *kimage_ptr, int *warpptr)
{
if((kimage_ptr == &g_mainwin_kimage) && g_adb_mainwin_has_focus) {
*warpptr = g_warp_pointer;
return g_hide_pointer;
}
*warpptr = 0;
return 0;
}
int
adb_get_copy_requested()
{
int ret;
ret = g_adb_copy_requested;
g_adb_copy_requested = 0;
return ret;
}
void
adb_nonmain_check()
{
// Debug window active. Undo F8 pointer warping
g_warp_pointer = 0;
g_hide_pointer = 0;
}
void
adb_init()
{
int keycode;
int i;
if(g_adb_init) {
halt_printf("g_adb_init = %d!\n", g_adb_init);
}
g_adb_init = 1;
for(i = 0; i < 128; i++) {
keycode = g_a2_key_to_ascii[i][0];
if(keycode != i) {
printf("ADB keycode lost/skipped: i=%x: keycode=%x\n",
i, keycode);
my_exit(1);
}
g_rawa2_to_a2code[i] = -1;
}
g_c025_val = 0;
for(i = 0; i < 4; i++) {
g_virtual_key_up[i] = -1;
}
for(i = 0; i < 10; i++) {
g_keypad_key_is_down[i] = 0;
}
}
void
adb_reset()
{
g_c027_val = 0;
g_key_down = 0;
g_kbd_paste_rd_pos = 0;
g_kbd_paste_wr_pos = 0;
g_kbd_chars_buffered = 0;
g_kbd_dev_addr = 2;
g_mouse_dev_addr = 3;
g_kbd_ctl_addr = 2;
g_mouse_ctl_addr = 3;
adb_clear_data_int();
adb_clear_mouse_int();
adb_clear_kbd_srq();
g_adb_data_pending = 0;
g_adb_interrupt_byte = 0;
g_adb_state = ADB_IDLE;
g_adb_mouse_coord = 0;
g_adb_mouse_valid_data = 0;
g_kbd_reg0_pos = 0;
g_kbd_reg3_16bit = 0x602;
}
#define LEN_ADB_LOG 16
STRUCT(Adb_log) {
word32 addr;
int val;
int state;
};
Adb_log g_adb_log[LEN_ADB_LOG];
int g_adb_log_pos = 0;
void
adb_log(word32 addr, int val)
{
int pos;
pos = g_adb_log_pos;
g_adb_log[pos].addr = addr;
g_adb_log[pos].val = val;
g_adb_log[pos].state = g_adb_state;
pos++;
if(pos >= LEN_ADB_LOG) {
pos = 0;
}
g_adb_log_pos = pos;
}
void
show_adb_log(void)
{
int pos;
int i;
pos = g_adb_log_pos;
printf("ADB log pos: %d\n", pos);
for(i = 0; i < LEN_ADB_LOG; i++) {
pos--;
if(pos < 0) {
pos = LEN_ADB_LOG - 1;
}
printf("%d:%d: addr:%04x = %02x, st:%d\n", i, pos,
g_adb_log[pos].addr, g_adb_log[pos].val,
g_adb_log[pos].state);
}
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("g_adb_state: %d, g_adb_interrupt_byte: %02x\n",
g_adb_state, g_adb_interrupt_byte);
}
void
adb_error(void)
{
halt_printf("Adb Error\n");
show_adb_log();
}
void
adb_add_kbd_srq()
{
if(g_kbd_reg3_16bit & 0x200) {
/* generate SRQ */
g_adb_interrupt_byte |= 0x08;
add_irq(IRQ_PENDING_ADB_KBD_SRQ);
} else {
printf("Got keycode but no kbd SRQ!\n");
}
}
void
adb_clear_kbd_srq()
{
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));
}
void
adb_add_data_int()
{
if(g_c027_val & ADB_C027_DATA_INT) {
add_irq(IRQ_PENDING_ADB_DATA);
}
}
void
adb_add_mouse_int()
{
if(g_c027_val & ADB_C027_MOUSE_INT) {
add_irq(IRQ_PENDING_ADB_MOUSE);
}
}
void
adb_clear_data_int()
{
remove_irq(IRQ_PENDING_ADB_DATA);
}
void
adb_clear_mouse_int()
{
remove_irq(IRQ_PENDING_ADB_MOUSE);
}
void
adb_send_bytes(int num_bytes, word32 val0, word32 val1, word32 val2)
{
word32 val;
int shift_amount;
int i;
if((num_bytes >= 12) || (num_bytes >= MAX_ADB_DATA_PEND)) {
halt_printf("adb_send_bytes: %d is too many!\n", num_bytes);
}
g_adb_state = ADB_SENDING_DATA;
g_adb_data_pending = num_bytes;
adb_add_data_int();
for(i = 0; i < num_bytes; i++) {
if(i < 4) {
val = val0;
} else if(i < 8) {
val = val1;
} else {
val = val2;
}
shift_amount = 8*(3 - i);
g_adb_data[i] = (val >> shift_amount) & 0xff;
adb_printf("adb_send_bytes[%d] = %02x\n", i, g_adb_data[i]);
}
}
void
adb_send_1byte(word32 val)
{
if(g_adb_data_pending != 0) {
halt_printf("g_adb_data_pending: %d\n", g_adb_data_pending);
}
adb_send_bytes(1, val << 24, 0, 0);
}
void
adb_response_packet(int num_bytes, word32 val)
{
if(g_adb_data_pending != 0) {
halt_printf("adb_response_packet, but pending: %d\n",
g_adb_data_pending);
}
g_adb_state = ADB_IDLE;
g_adb_data_pending = num_bytes;
g_adb_data[0] = val & 0xff;
g_adb_data[1] = (val >> 8) & 0xff;
g_adb_data[2] = (val >> 16) & 0xff;
g_adb_data[3] = (val >> 24) & 0xff;
if(num_bytes) {
g_adb_interrupt_byte |= 0x80 + num_bytes - 1;
} else {
g_adb_interrupt_byte |= 0x80;
}
adb_printf("adb_response packet: %d: %08x\n",
num_bytes, val);
adb_add_data_int();
}
void
adb_kbd_reg0_data(int a2code, int is_up)
{
if(g_kbd_reg0_pos >= MAX_ADB_KBD_REG3) {
/* too many keys, toss */
halt_printf("Had to toss key: %02x, %d\n", a2code, is_up);
return;
}
g_kbd_reg0_data[g_kbd_reg0_pos] = a2code + (is_up << 7);
adb_printf("g_kbd_reg0_data[%d] = %02x\n", g_kbd_reg0_pos,
g_kbd_reg0_data[g_kbd_reg0_pos]);
g_kbd_reg0_pos++;
adb_add_kbd_srq();
}
void
adb_kbd_talk_reg0()
{
word32 val0, val1, reg;
int num_bytes, num;
int i;
num = 0;
val0 = g_kbd_reg0_data[0];
val1 = g_kbd_reg0_data[1];
num_bytes = 0;
if(g_kbd_reg0_pos > 0) {
num_bytes = 2;
num = 1;
if((val0 & 0x7f) == 0x7f) {
/* reset */
val1 = val0;
} else if(g_kbd_reg0_pos > 1) {
num = 2;
if((val1 & 0x7f) == 0x7f) {
/* If first byte some other key, don't */
/* put RESET next! */
num = 1;
val1 = 0xff;
}
} else {
val1 = 0xff;
}
}
if(num) {
for(i = num; i < g_kbd_reg0_pos; i++) {
g_kbd_reg0_data[i-1] = g_kbd_reg0_data[i];
}
g_kbd_reg0_pos -= num;
}
reg = (val0 << 8) + val1;
adb_printf("adb_kbd_talk0: %04x\n", reg);
adb_response_packet(num_bytes, reg);
if(g_kbd_reg0_pos == 0) {
adb_clear_kbd_srq();
}
}
void
adb_set_config(word32 val0, word32 val1, word32 val2)
{
int new_mouse;
int new_kbd;
int tmp1;
new_mouse = val0 >> 4;
new_kbd = val0 & 0xf;
if(new_mouse != g_mouse_ctl_addr) {
printf("ADB config: mouse from %x to %x!\n",
g_mouse_ctl_addr, new_mouse);
adb_error();
g_mouse_ctl_addr = new_mouse;
}
if(new_kbd != g_kbd_ctl_addr) {
printf("ADB config: kbd from %x to %x!\n",
g_kbd_ctl_addr, new_kbd);
adb_error();
g_kbd_ctl_addr = new_kbd;
}
if(val1) {
// Do nothing
}
tmp1 = val2 >> 4;
if(tmp1 == 4) {
g_adb_repeat_delay = 0;
} else if(tmp1 < 4) {
g_adb_repeat_delay = (tmp1 + 1) * 15;
} else {
halt_printf("Bad ADB repeat delay: %02x\n", tmp1);
}
tmp1 = val2 & 0xf;
if(g_rom_version >= 3) {
tmp1 = 9 - tmp1;
}
switch(tmp1) {
case 0:
g_adb_repeat_rate = 1;
break;
case 1:
g_adb_repeat_rate = 2;
break;
case 2:
g_adb_repeat_rate = 3;
break;
case 3:
g_adb_repeat_rate = 3;
break;
case 4:
g_adb_repeat_rate = 4;
break;
case 5:
g_adb_repeat_rate = 5;
break;
case 6:
g_adb_repeat_rate = 7;
break;
case 7:
g_adb_repeat_rate = 15;
break;
case 8:
/* I don't know what this should be, ROM 03 uses it */
g_adb_repeat_rate = 30;
break;
case 9:
/* I don't know what this should be, ROM 03 uses it */
g_adb_repeat_rate = 60;
break;
default:
halt_printf("Bad repeat rate: %02x\n", tmp1);
}
}
void
adb_set_new_mode(word32 val)
{
if(val & 0x03) {
printf("Disabling keyboard/mouse:%02x!\n", val);
}
if(val & 0xa2) {
halt_printf("ADB set mode: %02x!\n", val);
adb_error();
}
g_adb_mode = val;
}
int
adb_read_c026()
{
word32 ret;
int i;
ret = 0;
switch(g_adb_state) {
case ADB_IDLE:
ret = g_adb_interrupt_byte;
g_adb_interrupt_byte = 0;
if(g_irq_pending & IRQ_PENDING_ADB_KBD_SRQ) {
g_adb_interrupt_byte |= 0x08;
}
if(g_adb_data_pending == 0) {
if(ret & 0x80) {
halt_printf("read_c026: ret:%02x, pend:%d\n",
ret, g_adb_data_pending);
}
adb_clear_data_int();
}
if(g_adb_data_pending) {
if(g_adb_state != ADB_IN_CMD) {
g_adb_state = ADB_SENDING_DATA;
}
}
break;
case ADB_IN_CMD:
ret = 0;
break;
case ADB_SENDING_DATA:
ret = g_adb_data[0];
for(i = 1; i < g_adb_data_pending; i++) {
g_adb_data[i-1] = g_adb_data[i];
}
g_adb_data_pending--;
if(g_adb_data_pending <= 0) {
g_adb_data_pending = 0;
g_adb_state = ADB_IDLE;
adb_clear_data_int();
}
break;
default:
halt_printf("Bad ADB state: %d!\n", g_adb_state);
adb_clear_data_int();
break;
}
adb_printf("Reading c026. Returning %02x, st: %02x, pend: %d\n",
ret, g_adb_state, g_adb_data_pending);
adb_log(0xc026, ret);
return (ret & 0xff);
}
void
adb_write_c026(int val)
{
word32 tmp;
int dev;
adb_printf("Writing c026 with %02x\n", val);
adb_log(0x1c026, val);
switch(g_adb_state) {
case ADB_IDLE:
g_adb_cmd = val;
g_adb_cmd_so_far = 0;
g_adb_cmd_len = 0;
dev = val & 0xf;
switch(val) {
case 0x01: /* Abort */
adb_printf("Performing adb abort\n");
/* adb_abort() */
break;
case 0x03: /* Flush keyboard buffer */
adb_printf("Flushing adb keyboard buffer\n");
/* Do nothing */
break;
case 0x04: /* Set modes */
adb_printf("ADB set modes\n");
g_adb_state = ADB_IN_CMD;
g_adb_cmd_len = 1;
break;
case 0x05: /* Clear modes */
adb_printf("ADB clear modes\n");
g_adb_state = ADB_IN_CMD;
g_adb_cmd_len = 1;
break;
case 0x06: /* Set config */
adb_printf("ADB set config\n");
g_adb_state = ADB_IN_CMD;
g_adb_cmd_len = 3;
break;
case 0x07: /* Sync */
adb_printf("Performing sync cmd!\n");
g_adb_state = ADB_IN_CMD;
if(g_rom_version == 1) {
g_adb_cmd_len = 4;
} else {
g_adb_cmd_len = 8;
}
break;
case 0x08: /* Write mem */
adb_printf("Starting write_mem cmd\n");
g_adb_state = ADB_IN_CMD;
g_adb_cmd_len = 2;
break;
case 0x09: /* Read mem */
adb_printf("Performing read_mem cmd!\n");
g_adb_state = ADB_IN_CMD;
g_adb_cmd_len = 2;
break;
case 0x0a: /* Read modes byte */
printf("Performing read_modes cmd!\n");
/* set_halt(1); */
adb_send_1byte(g_adb_mode);
break;
case 0x0b: /* Read config bytes */
printf("Performing read_configs cmd!\n");
tmp = (g_mouse_ctl_addr << 20) +
(g_kbd_ctl_addr << 16) +
(g_adb_char_set << 12) +
(g_adb_layout_lang << 8) +
(g_adb_repeat_info << 0);
tmp = (0x82U << 24) + tmp;
adb_send_bytes(4, tmp, 0, 0);
break;
case 0x0d: /* Get Version */
adb_printf("Performing get_version cmd!\n");
val = 0;
if(g_rom_version == 1) {
/* ROM 01 = revision 5 */
val = 5;
} else {
/* ROM 03 checks for rev >= 6 */
val = 6;
}
adb_send_1byte(val);
break;
case 0x0e: /* Read avail char sets */
adb_printf("Performing read avail char sets cmd!\n");
adb_send_bytes(2, /* just 2 bytes */
0x08000000, /* number of ch sets=0x8 */
0, 0);
/* set_halt(1); */
break;
case 0x0f: /* Read avail kbd layouts */
adb_printf("Performing read avail kbd layouts cmd!\n");
adb_send_bytes(0x2, /* number of kbd layouts=0xa */
0x0a000000, 0, 0);
/* set_halt(1); */
break;
case 0x10: /* Reset */
printf("ADB reset, cmd 0x10\n");
do_reset();
break;
case 0x11: /* Send ADB keycodes */
adb_printf("Sending ADB keycodes\n");
g_adb_state = ADB_IN_CMD;
g_adb_cmd_len = 1;
break;
case 0x12: /* ADB cmd 12: ROM 03 only! */
if(g_rom_version >= 3) {
g_adb_state = ADB_IN_CMD;
g_adb_cmd_len = 2;
} else {
printf("ADB cmd 12, but not ROM 3!\n");
adb_error();
}
break;
case 0x13: /* ADB cmd 13: ROM 03 only! */
if(g_rom_version >= 3) {
g_adb_state = ADB_IN_CMD;
g_adb_cmd_len = 2;
} else {
printf("ADB cmd 13, but not ROM 3!\n");
adb_error();
}
break;
case 0x73: /* Disable SRQ device 3: mouse */
adb_printf("Disabling Mouse SRQ's (device 3)\n");
/* HACK HACK...should deal with SRQs on mouse */
break;
case 0xb0: case 0xb1: case 0xb2: case 0xb3:
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xb8: case 0xb9: case 0xba: case 0xbb:
case 0xbc: case 0xbd: case 0xbe: case 0xbf:
/* Listen dev x reg 3 */
adb_printf("Sending data to dev %x reg 3\n", dev);
g_adb_state = ADB_IN_CMD;
g_adb_cmd_len = 2;
break;
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb:
case 0xcc: case 0xcd: case 0xce: case 0xcf:
/* Talk dev x reg 0 */
adb_printf("Performing talk dev %x reg 0\n", dev);
if(dev == g_kbd_dev_addr) {
adb_kbd_talk_reg0();
} else {
printf("Unknown talk dev %x reg 0!\n", dev);
/* send no data, on SRQ, system polls devs */
/* so we don't want to send anything */
adb_error();
}
break;
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
case 0xfc: case 0xfd: case 0xfe: case 0xff:
/* Talk dev x reg 3 */
adb_printf("Performing talk dev %x reg 3\n", dev);
if(dev == g_kbd_dev_addr) {
adb_response_packet(2, g_kbd_reg3_16bit);
} else {
printf("Performing talk dev %x reg 3!!\n", dev);
adb_error();
}
break;
default:
halt_printf("ADB ucontroller cmd %02x unknown!\n", val);
/* The Gog's says ACS Demo 2 has a bug and writes to */
/* c026 */
break;
}
break;
case ADB_IN_CMD:
adb_printf("Setting byte %d of cmd %02x to %02x\n",
g_adb_cmd_so_far, g_adb_cmd, val);
g_adb_cmd_data[g_adb_cmd_so_far] = val;
g_adb_cmd_so_far++;
if(g_adb_cmd_so_far >= g_adb_cmd_len) {
adb_printf("Finished cmd %02x\n", g_adb_cmd);
do_adb_cmd();
}
break;
default:
printf("adb_state: %02x is unknown! Setting it to ADB_IDLE\n",
g_adb_state);
g_adb_state = ADB_IDLE;
adb_error();
halt_on_all_c027 = 1;
break;
}
return;
}
void
do_adb_cmd()
{
word32 val;
int dev, new_kbd, addr;
dev = g_adb_cmd & 0xf;
g_adb_state = ADB_IDLE;
switch(g_adb_cmd) {
case 0x04: /* Set modes */
adb_printf("Performing ADB set mode: OR'ing in %02x\n",
g_adb_cmd_data[0]);
val = g_adb_cmd_data[0] | g_adb_mode;
adb_set_new_mode(val);
break;
case 0x05: /* clear modes */
adb_printf("Performing ADB clear mode: AND'ing in ~%02x\n",
g_adb_cmd_data[0]);
val = g_adb_cmd_data[0];
val = g_adb_mode & (~val);
adb_set_new_mode(val);
break;
case 0x06: /* Set config */
adb_printf("Set ADB config to %02x %02x %02x\n",
g_adb_cmd_data[0], g_adb_cmd_data[1],g_adb_cmd_data[2]);
adb_set_config(g_adb_cmd_data[0], g_adb_cmd_data[1],
g_adb_cmd_data[2]);
break;
case 0x07: /* SYNC */
adb_printf("Performing ADB SYNC\n");
adb_printf("data: %02x %02x %02x %02x\n",
g_adb_cmd_data[0], g_adb_cmd_data[1], g_adb_cmd_data[2],
g_adb_cmd_data[3]);
adb_set_new_mode(g_adb_cmd_data[0]);
adb_set_config(g_adb_cmd_data[1], g_adb_cmd_data[2],
g_adb_cmd_data[3]);
if(g_rom_version >= 3) {
adb_printf(" and cmd12:%02x %02x cmd13:%02x %02x\n",
g_adb_cmd_data[4], g_adb_cmd_data[5],
g_adb_cmd_data[6], g_adb_cmd_data[7]);
}
break;
case 0x08: /* Write mem */
addr = g_adb_cmd_data[0];
val = g_adb_cmd_data[1];
write_adb_ram(addr, val);
break;
case 0x09: /* Read mem */
addr = (g_adb_cmd_data[1] << 8) + g_adb_cmd_data[0];
adb_printf("Performing mem read to addr %04x\n", addr);
adb_send_1byte(read_adb_ram(addr));
break;
case 0x11: /* Send ADB keycodes */
val = g_adb_cmd_data[0];
adb_printf("Performing send ADB keycodes: %02x\n", val);
adb_virtual_key_update(val & 0x7f, val >> 7);
break;
case 0x12: /* ADB cmd12 */
adb_printf("Performing ADB cmd 12\n");
adb_printf("data: %02x %02x\n", g_adb_cmd_data[0],
g_adb_cmd_data[1]);
break;
case 0x13: /* ADB cmd13 */
adb_printf("Performing ADB cmd 13\n");
adb_printf("data: %02x %02x\n", g_adb_cmd_data[0],
g_adb_cmd_data[1]);
break;
case 0xb0: case 0xb1: case 0xb2: case 0xb3:
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xb8: case 0xb9: case 0xba: case 0xbb:
case 0xbc: case 0xbd: case 0xbe: case 0xbf:
/* Listen dev x reg 3 */
if(dev == g_kbd_dev_addr) {
if(g_adb_cmd_data[1] == 0xfe) {
/* change keyboard addr? */
new_kbd = g_adb_cmd_data[0] & 0xf;
if(new_kbd != dev) {
printf("Moving kbd to dev %x!\n",
new_kbd);
adb_error();
}
g_kbd_dev_addr = new_kbd;
} else if(g_adb_cmd_data[1] != 1) {
/* see what new device handler id is */
printf("KBD listen to dev %x reg 3: 1:%02x\n",
dev, g_adb_cmd_data[1]);
adb_error();
}
if(g_adb_cmd_data[0] != (word32)g_kbd_dev_addr) {
/* see if app is trying to change addr */
printf("KBD listen to dev %x reg 3: 0:%02x!\n",
dev, g_adb_cmd_data[0]);
adb_error();
}
g_kbd_reg3_16bit = ((g_adb_cmd_data[0] & 0xf) << 12) +
(g_kbd_reg3_16bit & 0x0fff);
} else if(dev == g_mouse_dev_addr) {
if(g_adb_cmd_data[0] != (word32)dev) {
/* see if app is trying to change mouse addr */
printf("MOUS listen to dev %x reg3: 0:%02x!\n",
dev, g_adb_cmd_data[0]);
adb_error();
}
if(g_adb_cmd_data[1] != 1 && g_adb_cmd_data[1] != 2) {
/* see what new device handler id is */
printf("MOUS listen to dev %x reg 3: 1:%02x\n",
dev, g_adb_cmd_data[1]);
adb_error();
}
} else {
printf("Listen cmd to dev %x reg3????\n", dev);
printf("data0: %02x, data1: %02x ????\n",
g_adb_cmd_data[0], g_adb_cmd_data[1]);
adb_error();
}
break;
default:
printf("Doing adb_cmd %02x: UNKNOWN!\n", g_adb_cmd);
break;
}
}
int
adb_read_c027()
{
word32 ret;
if(halt_on_all_c027) {
halt_printf("halting on all c027 reads!\n");
}
if(g_c027_val & (~ADB_C027_NEG_MASK)) {
halt_printf("read_c027: g_c027_val: %02x\n", g_c027_val);
}
ret = (g_c027_val & ADB_C027_NEG_MASK);
if(g_adb_mouse_valid_data) {
ret |= ADB_C027_MOUSE_DATA;
}
if(g_adb_interrupt_byte != 0) {
ret |= ADB_C027_DATA_VALID;
} else if(g_adb_data_pending > 0) {
if((g_adb_state != ADB_IN_CMD)) {
ret |= ADB_C027_DATA_VALID;
}
}
if(g_adb_mouse_coord) {
ret |= ADB_C027_MOUSE_COORD;
}
#if 0
adb_printf("Read c027: %02x, int_byte: %02x, d_pend: %d\n",
ret, g_adb_interrupt_byte, g_adb_data_pending);
#endif
#if 0
adb_log(0xc027, ret);
#endif
return ret;
}
void
adb_write_c027(int val)
{
word32 old_val;
word32 new_int;
word32 old_int;
adb_printf("Writing c027 with %02x\n", val);
adb_log(0x1c027, val);
old_val = g_c027_val;
g_c027_val = (val & ADB_C027_NEG_MASK);
new_int = g_c027_val & ADB_C027_MOUSE_INT;
old_int = old_val & ADB_C027_MOUSE_INT;
if(!new_int && old_int) {
adb_clear_mouse_int();
}
new_int = g_c027_val & ADB_C027_DATA_INT;
old_int = old_val & ADB_C027_DATA_INT;
if(!new_int && old_int) {
/* ints were on, now off */
adb_clear_data_int();
}
if(g_c027_val & ADB_C027_KBD_INT) {
halt_printf("Can't support kbd interrupts!\n");
}
return;
}
int
read_adb_ram(word32 addr)
{
int val;
adb_printf("Reading adb ram addr: %02x\n", addr);
if(addr >= 0x100) {
if(addr >= 0x1000 && addr < 0x2000) {
/* ROM self-test checksum */
if(addr == 0x1400) {
val = 0x72;
} else if(addr == 0x1401) {
val = 0xf7;
} else {
val = 0;
}
} else {
printf("adb ram addr out of range: %04x!\n", addr);
val = 0;
}
} else {
val = adb_memory[addr];
if((addr == 0xb) && (g_rom_version == 1)) {
// read special key state byte for Out of This World
val = (g_c025_val >> 1) & 0x43;
val |= (g_c025_val << 2) & 0x4;
val |= (g_c025_val >> 2) & 0x10;
}
if((addr == 0xc) && (g_rom_version >= 3)) {
// read special key state byte for Out of This World
val = g_c025_val & 0xc7;
printf("val is %02x\n", val);
}
}
adb_printf("adb_ram returning %02x\n", val);
return val;
}
void
write_adb_ram(word32 addr, int val)
{
adb_printf("Writing adb_ram addr: %02x: %02x\n", addr, val);
if(addr >= 0x100) {
printf("write adb_ram addr: %02x: %02x!\n", addr, val);
adb_error();
} else {
adb_memory[addr] = val;
}
}
int
adb_get_keypad_xy(int get_y)
{
int x, y, key, 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;
}
}
// g_mouse_raw_x/y: Current position (in A2 coordinates) of mouse on host screen
// g_mouse_fifo[0].x/y: Current position (in A2 coords) of where we "want"
// mouse on the A2 screen.
// g_mouse_a2_x/y: last x,y returned through $c024 to software.
// So, reading $c024 return g_mouse_fifo[].x - g_mouse_a2_x.
// And, in simple cases, host mouse movement just sets g_mouse_fifo[0].x=raw_x
int
adb_update_mouse(Kimage *kimage_ptr, int x, int y, int button_states,
int buttons_valid)
{
dword64 dfcyc;
int button1_changed, mouse_moved, unhide, pos;
int i;
if(kimage_ptr != &g_mainwin_kimage) {
adb_nonmain_check();
}
dfcyc = g_cur_dfcyc;
unhide = (g_adb_mainwin_has_focus == 0);
if((buttons_valid >= 0) && (buttons_valid & 0x1000)) {
// x, y are really deltas
buttons_valid &= 0xfff;
x = g_mouse_raw_x + x;
y = g_mouse_raw_y + y;
g_mouse_raw_x = x;
g_mouse_raw_y = y;
} else {
g_mouse_raw_x = x;
g_mouse_raw_y = y;
// Clamp mouse to 0-639, 0-399 to make GSOS work nicely
if(x < 0) {
x = 0;
unhide = 1;
}
if(x >= 640) {
x = 639;
unhide = 1;
}
if(y < 0) {
y = 0;
unhide = 1;
}
if(y >= 400) {
y = 399;
unhide = 1;
}
}
g_unhide_pointer = unhide && !g_warp_pointer;
if(kimage_ptr != &g_mainwin_kimage) {
// In debugger window...just get out
return 0;
}
if(!g_warp_pointer) {
if(g_hide_pointer && g_unhide_pointer) {
/* cursor has left a2 window, show it */
g_hide_pointer = 0;
}
if((g_num_lines_prev_superhires == 200) &&
(g_num_lines_prev_superhires640 == 0) &&
((g_slow_memory_ptr[0x19d00] & 0x80) == 0)) {
// In 320-mode superhires, cut mouse range in half
x = x >> 1;
}
y = y >> 1;
}
mouse_compress_fifo(dfcyc);
#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[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[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, new x: %d, %d, a2:%d,%d\n", g_mouse_fifo[0].x,
g_mouse_fifo[0].y, g_mouse_a2_x, g_mouse_a2_y);
#endif
mouse_moved = (g_mouse_fifo[0].x != x) || (g_mouse_fifo[0].y != y);
g_mouse_fifo[0].x = x;
g_mouse_fifo[0].y = y;
g_mouse_fifo[0].dfcyc = dfcyc;
button1_changed = (buttons_valid & 1) &&
((button_states & 1) != (g_mouse_fifo[0].buttons & 1));
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[0].buttons & 2) &&
(buttons_valid & 2)) {
/* middle button pressed */
halt2_printf("Middle button pressed\n");
}
pos = g_mouse_fifo_pos;
if((pos < (ADB_MOUSE_FIFO - 2)) && button1_changed) {
/* copy delta to overflow, set overflow */
/* overflow ensures the mouse button state is precise at */
/* 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[i + 1] = g_mouse_fifo[i]; /* copy struct*/
}
g_mouse_fifo_pos = pos + 1;
}
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) &&
((g_adb_mode & 0x2) == 0)) {
g_adb_mouse_valid_data = 1;
adb_add_mouse_int();
}
}
return mouse_moved;
}
int
mouse_read_c024(dword64 dfcyc)
{
word32 ret, tool_start;
int em_active, target_x, target_y, delta_x, delta_y, a2_x, a2_y;
int mouse_button, clamped, pos;
if(((g_adb_mode & 0x2) != 0) || (g_mouse_dev_addr != g_mouse_ctl_addr)){
/* mouse is off, return 0, or mouse is not autopoll */
g_adb_mouse_valid_data = 0;
adb_clear_mouse_int();
return 0;
}
mouse_compress_fifo(dfcyc);
pos = g_mouse_fifo_pos;
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;
clamped = 0;
if(delta_x > 0x3f) {
delta_x = 0x3f;
clamped = 1;
} else if(delta_x < -0x3f) {
delta_x = -0x3f;
clamped = 1;
}
if(delta_y > 0x3f) {
delta_y = 0x3f;
clamped = 1;
} else if(delta_y < -0x3f) {
delta_y = -0x3f;
clamped = 1;
}
if(pos > 0) {
/* 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[pos - 1].buttons & 1;
}
}
if(g_adb_mouse_coord) {
/* y coord */
delta_x = 0; /* clear unneeded x delta */
} else {
delta_y = 0; /* clear unneeded y delta */
}
adb_printf(" pre a2_x:%02x,%02x,%02x,%02x\n",
g_slow_memory_ptr[0x100e9], g_slow_memory_ptr[0x100ea],
g_slow_memory_ptr[0x100eb], g_slow_memory_ptr[0x100ec]);
adb_printf(" pre a2_x:%02x,%02x,%02x,%02x\n",
g_slow_memory_ptr[0x10190], g_slow_memory_ptr[0x10192],
g_slow_memory_ptr[0x10191], g_slow_memory_ptr[0x10193]);
/* Update event manager internal state */
tool_start = (g_slow_memory_ptr[0x103ca] << 16) +
(g_slow_memory_ptr[0x103c9] << 8) +
g_slow_memory_ptr[0x103c8];
em_active = 0;
if((tool_start >= 0x20000) && (tool_start < (g_mem_size_total - 28)) ) {
/* seems to be valid ptr to addr of mem space for tools */
/* see if event manager appears to be active */
em_active = g_memory_ptr[tool_start + 6*4] +
(g_memory_ptr[tool_start + 6*4 + 1] << 8);
if(g_warp_pointer) {
em_active = 0;
}
}
//em_active = 0; // HACK!
a2_x = g_mouse_a2_x;
a2_y = g_mouse_a2_y;
if(em_active) {
if((!g_hide_pointer) && (g_num_lines_prev_superhires == 200) &&
!g_unhide_pointer) {
/* if super-hires and forcing tracking, then hide */
g_hide_pointer = 1;
}
if(g_adb_mouse_coord == 0) {
/* update x coord values */
g_slow_memory_ptr[0x47c] = a2_x & 0xff;
g_slow_memory_ptr[0x57c] = a2_x >> 8;
g_memory_ptr[0x47c] = a2_x & 0xff;
g_memory_ptr[0x57c] = a2_x >> 8;
g_slow_memory_ptr[0x10190] = a2_x & 0xff;
g_slow_memory_ptr[0x10192] = a2_x >> 8;
} else {
g_slow_memory_ptr[0x4fc] = a2_y & 0xff;
g_slow_memory_ptr[0x5fc] = a2_y >> 8;
g_memory_ptr[0x4fc] = a2_y & 0xff;
g_memory_ptr[0x5fc] = a2_y >> 8;
g_slow_memory_ptr[0x10191] = a2_y & 0xff;
g_slow_memory_ptr[0x10193] = a2_y >> 8;
}
} else {
if(g_hide_pointer && !g_warp_pointer) {
g_hide_pointer = 0;
}
}
ret = ((!mouse_button) << 7) + ((delta_x | delta_y) & 0x7f);
if(g_adb_mouse_coord) {
g_mouse_a2_button = mouse_button; /* y coord has button*/
} else {
ret |= 0x80; /* mouse button not down on x coord rd */
}
a2_x += delta_x;
a2_y += delta_y;
g_mouse_a2_x = a2_x;
g_mouse_a2_y = a2_y;
if(g_mouse_fifo_pos) {
if((target_x == a2_x) && (target_y == a2_y) &&
(g_mouse_a2_button == mouse_button)) {
g_mouse_fifo_pos--;
}
}
adb_printf("Rd c024, mouse is_y:%d, %02x, vbl:%08x, dfcyc:%016llx, em:"
"%d\n", g_adb_mouse_coord, ret, g_vbl_count, dfcyc, em_active);
adb_printf("...mouse targ_x:%d,%d delta_x,y:%d,%d fifo:%d, a2:%d,%d\n",
target_x, target_y, delta_x, delta_y, g_mouse_fifo_pos,
a2_x, a2_y);
adb_printf(" post a2_x:%02x,%02x,%02x,%02x\n",
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[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();
}
g_adb_mouse_coord = !g_adb_mouse_coord;
return ret;
}
void
mouse_compress_fifo(dword64 dfcyc)
{
dword64 ddelta;
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 */
ddelta = (500LL*1000) << 16;
for(pos = g_mouse_fifo_pos; pos >= 1; pos--) {
if((g_mouse_fifo[pos].dfcyc + ddelta) < dfcyc) {
/* 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_paste_update_state()
{
int rd_pos, wr_pos;
rd_pos = g_kbd_paste_rd_pos;
wr_pos = g_kbd_paste_wr_pos;
if(rd_pos >= wr_pos) {
g_kbd_paste_rd_pos = 0;
g_kbd_paste_wr_pos = 0;
return;
}
if(g_kbd_chars_buffered == 0) {
g_kbd_buf[0] = g_kbd_paste_buf[rd_pos];
g_kbd_paste_rd_pos = rd_pos + 1;
g_kbd_chars_buffered = 1;
}
}
int
adb_paste_add_buf(word32 key)
{
word32 last_key;
int pos;
// Applesoft reads $C000 to check for ctrl-C after each statement.
// So if we dropped all chars into g_kbd_buf[], we could end up
// losing chars due to multiple reads of $C000 without writes to $C010
// causing g_kbd_read_no_update to toss a paste char.
// Instead, have a separate buffer, and when g_kbd_chars_buffered==0,
// copy one paste char to g_kbd_buf[0]. This also solves a problem
// where Applesoft is doing: 10 GOTO 10 and it needs to see a Ctrl-C
// to stop--but a paste buffer is in the way.
// But, now pressing keys while a paste is pending causes those keys
// to take priority during the paste.
last_key = g_kbd_paste_last_key;
g_kbd_paste_last_key = key;
if(key == 10) { // \n, newline on Unix
key = 13; // \r, return
if(last_key == 13) {
key = 0; // CR, then LF--eat the LF
}
}
if((key == 0) || (key >= 0x80)) {
return 0; // Just skip these keys
}
pos = g_kbd_paste_wr_pos;
if(pos >= MAX_KBD_PASTE_BUF) {
return 1;
}
g_kbd_paste_buf[pos] = key | 0x80;
g_kbd_paste_wr_pos = pos + 1;
adb_paste_update_state();
return 0;
}
void
adb_key_event(int a2code, int is_up)
{
word32 special, vbl_count;
int key, hard_key, pos, tmp_ascii, ascii;
if(is_up) {
adb_printf("adb_key_event, key:%02x, is up, g_key_down: %02x\n",
a2code, g_key_down);
}
if(a2code < 0 || a2code > 0x7f) {
halt_printf("add_key_event: a2code: %04x!\n", a2code);
return;
}
if(!is_up && a2code == 0x35) {
/* ESC pressed, see if ctrl & cmd key down */
if(CTRL_DOWN && CMD_DOWN) {
/* Desk mgr int */
printf("Desk mgr int!\n");
g_adb_interrupt_byte |= 0x20;
adb_add_data_int();
}
}
/* convert key to ascii, if possible */
hard_key = 0;
if(g_a2_key_to_ascii[a2code][1] & 0xef00) {
/* special key */
} else {
/* we have ascii */
hard_key = 1;
}
pos = 1;
ascii = g_a2_key_to_ascii[a2code][1];
if(CAPS_LOCK_DOWN && (ascii >= 'a') && (ascii <= 'z')) {
pos = 2;
if(SHIFT_DOWN && (g_adb_mode & 0x40)) {
/* xor shift mode--capslock and shift == lowercase */
pos = 1;
}
} else if(SHIFT_DOWN) {
pos = 2;
}
ascii = g_a2_key_to_ascii[a2code][pos];
if(CTRL_DOWN) {
tmp_ascii = g_a2_key_to_ascii[a2code][3];
if(tmp_ascii >= 0) {
ascii = tmp_ascii;
}
}
key = (ascii & 0x7f) + 0x80;
special = (ascii >> 8) & 0xff;
if(ascii < 0) {
printf("ascii1: %d, a2code: %02x, pos: %d\n", ascii,a2code,pos);
ascii = 0;
special = 0;
}
if(!is_up) {
if(hard_key) {
g_kbd_buf[g_kbd_chars_buffered] = key;
g_kbd_chars_buffered++;
if(g_kbd_chars_buffered >= MAX_KBD_BUF) {
g_kbd_chars_buffered = MAX_KBD_BUF - 1;
}
g_key_down = 1;
g_a2code_down = a2code;
/* first key down, set up autorepeat */
vbl_count = g_vbl_count;
g_adb_repeat_vbl = vbl_count + g_adb_repeat_delay;
if(g_adb_repeat_delay == 0) {
g_key_down = 0;
}
g_hard_key_down = 1;
}
g_c025_val = g_c025_val | special;
adb_printf("new c025_or: %02x\n", g_c025_val);
} else {
if(hard_key && (a2code == g_a2code_down)) {
g_hard_key_down = 0;
/* Turn off repeat */
g_key_down = 0;
}
g_c025_val = g_c025_val & (~ special);
adb_printf("new c025_and: %02x\n", g_c025_val);
}
if(g_key_down) {
g_c025_val = g_c025_val & (~0x20);
} else {
/* If no hard key down, set update mod latch */
g_c025_val = g_c025_val | 0x20;
}
}
word32
adb_read_c000()
{
word32 vbl_count;
if( ((g_kbd_buf[0] & 0x80) == 0) && (g_key_down == 0)) {
/* nothing happening, just get out */
return g_kbd_buf[0];
}
if(g_kbd_buf[0] & 0x80) {
/* 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 %d times, tossing\n", g_kbd_buf[0],
g_kbd_read_no_update);
adb_access_c010();
}
} else {
vbl_count = g_vbl_count;
if(g_key_down && (vbl_count >= g_adb_repeat_vbl)) {
/* repeat the g_key_down */
g_c025_val |= 0x8;
adb_key_event(g_a2code_down, 0);
g_adb_repeat_vbl = vbl_count + g_adb_repeat_rate;
}
}
return g_kbd_buf[0];
}
word32
adb_access_c010()
{
int tmp;
int i;
g_kbd_read_no_update = 0;
tmp = g_kbd_buf[0] & 0x7f;
g_kbd_buf[0] = tmp;
tmp = tmp | (g_hard_key_down << 7);
if(g_kbd_chars_buffered) {
for(i = 1; i < g_kbd_chars_buffered; i++) {
g_kbd_buf[i - 1] = g_kbd_buf[i];
}
g_kbd_chars_buffered--;
if(g_kbd_chars_buffered == 0) {
adb_paste_update_state();
}
}
g_c025_val = g_c025_val & (~ (0x08));
return tmp;
}
word32
adb_read_c025()
{
return g_c025_val;
}
int
adb_is_cmd_key_down()
{
return CMD_DOWN;
}
int
adb_is_option_key_down()
{
return OPTION_DOWN;
}
void
adb_increment_speed()
{
const char *str;
g_limit_speed++;
if(g_limit_speed > 3) {
g_limit_speed = 0;
}
str = "";
switch(g_limit_speed) {
case 0:
str = "...as fast as possible!";
break;
case 1:
str = "...1.024MHz!";
break;
case 2:
str = "...2.8MHz!";
break;
case 3:
str = "...8.0MHz!";
break;
}
printf("Toggling g_limit_speed to %d%s\n", g_limit_speed, str);
}
void
adb_update_c025_mask(Kimage *kimage_ptr, word32 new_c025_val, word32 mask)
{
// Called by *driver.c host drivers to handle focus changes and
// capslock state (so if capslock is on, we leave the window, release
// capslock, then reenter the window, we update things properly).
if(kimage_ptr == &g_mainwin_kimage) {
g_c025_val = (g_c025_val & (~mask)) | new_c025_val;
} else {
kimage_ptr->c025_val = (kimage_ptr->c025_val & (~mask)) |
new_c025_val;
}
}
int
adb_ascii_to_a2code(int unicode_c, int a2code, int *shift_down_ptr)
{
int i;
switch(unicode_c) {
case 0x00a3: // British pound
unicode_c = '#';
break;
case 0x00e0: // a with left accent
unicode_c = '@';
break;
case 0x00b0: // degrees (French)
case 0x00c4: // A with umlaut (German, Swedish)
case 0x00a1: // ! upside down (Spanish)
case 0x00c6: // AE (Danish)
unicode_c = '[';
break;
case 0x00e7: // c with tail (French/Italian)
case 0x00d1: // N with ~ (Spanish)
case 0x00d6: // O with umlaut (German, Swedish)
case 0x00d8: // O with slash (Danish)
unicode_c = '\\';
break;
case 0x00a7: // ss like thing (French)
case 0x00dc: // U with umlaut
case 0x00bf: // ? upside down (Spanish)
case 0x00c5: // A with circle (Danish)
//case 0x00e9: // e with right accent (Italian)
unicode_c = ']';
break;
//case 0x0000: // u with left accent (Italian)
// unicode_c = '`';
// break;
case 0x00e4: // a with umlaut (german)
case 0x00e9: // e with accent (french)
case 0x0000: // ae (Danish)
unicode_c = '{';
break;
case 0x00f6: // o with umlaut (German/Swedish)
case 0x00f9: // u with left accent (French)
case 0x00f8: // o with slash (Danish)
case 0x00f1: // n with ~ (Spanish)
case 0x00f2: // o with ` (Italian)
unicode_c = '|';
break;
case 0x00e8: // e with ` (French, Italian)
case 0x00fc: // u with umlaut (German)
case 0x00e5: // a with circle (Danish/Swedish)
unicode_c = '}';
break;
case 0x00a8: // two high dots (French)
case 0x00ec: // i with ` (Italian)
case 0x00df: // german B thing (German)
unicode_c = '~';
break;
}
if(unicode_c > 0x7f) {
return a2code; // Use a2code instead
}
if((g_a2_key_to_ascii[a2code][1] & 0xf000) == 0x1000) { // Keypad
// Don't remap keypad keys, we need them for Keypad Joystick
if((unicode_c >= '0') && (unicode_c <= '9')) {
return a2code;
}
}
for(i = 0; i < 128; i++) {
if(g_a2_key_to_ascii[i][1] == unicode_c) { // Not-shifted
*shift_down_ptr = 0;
return g_a2_key_to_ascii[i][0];
}
if(g_a2_key_to_ascii[i][2] == unicode_c) { // Shifted
*shift_down_ptr = 1;
return g_a2_key_to_ascii[i][0];
}
}
return a2code; // Not found, use default a2code
}
void
adb_physical_key_update(Kimage *kimage_ptr, int raw_a2code, word32 unicode_c,
int is_up)
{
word32 restore_c025_val, restorek_c025_val;
int special, ascii_and_type, ascii, new_shift, a2code, other_a2code;
/* this routine called by xdriver to pass raw codes--handle */
/* ucontroller and ADB bus protocol issues here */
/* if autopoll on, pass it on through to c025,c000 regs */
/* else only put it in kbd reg 3, and pull SRQ if needed */
adb_printf("adb_phys_key_update: %02x, %d\n", raw_a2code, is_up);
if((raw_a2code < 0) || (raw_a2code > 0x7f)) {
halt_printf("raw_a2code: %04x!\n", raw_a2code);
return;
}
a2code = raw_a2code;
restore_c025_val = 0;
restorek_c025_val = 0;
if(unicode_c > 0) {
// To enable international keyboards, ignore a2code, look up
// what U.S. keycode would be and return that
new_shift = g_c025_val & 1;
a2code = adb_ascii_to_a2code(unicode_c, a2code, &new_shift);
if(a2code && ((g_c025_val & 1) != new_shift)) {
restore_c025_val = g_c025_val | 0x100;
restorek_c025_val = kimage_ptr->c025_val;
g_c025_val = (g_c025_val & -2) | new_shift;
kimage_ptr->c025_val = (kimage_ptr->c025_val & -2) |
new_shift;
}
if(!is_up) {
g_rawa2_to_a2code[raw_a2code & 0x7f] = a2code;
}
}
/* Remap 0x7b-0x7e to 0x3b-0x3e (arrow keys on new mac keyboards) */
if((a2code >= 0x7b) && (a2code <= 0x7e)) {
a2code = a2code - 0x40;
}
if(g_adb_swap_command_option) {
if(a2code == 0x37) { // Command?
a2code = 0x3a; // -> Option
} else if(a2code == 0x3a) { // Option?
a2code = 0x37; // -> Command
}
}
/* Now check for special keys (function keys, etc) */
ascii_and_type = g_a2_key_to_ascii[a2code][1];
special = 0;
if((ascii_and_type & 0xf000) == 0x8000) {
/* special function key */
special = ascii_and_type & 0xff;
switch(special) {
case 0x01: /* F1 - remap to cmd */
a2code = 0x37;
special = 0;
break;
case 0x02: /* F2 - remap to option */
a2code = 0x3a;
special = 0;
break;
case 0x03: /* F3 - remap to escape for OS/2 */
a2code = 0x35;
special = 0;
break;
case 0x0c: /* F12 - remap to reset */
a2code = 0x7f;
special = 0;
break;
default:
break;
}
}
/* Only process reset requests here */
if((is_up == 0) && (a2code == 0x7f) && CTRL_DOWN) {
/* Reset pressed! */
printf("Reset pressed since CTRL_DOWN: %d\n", CTRL_DOWN);
do_reset();
return;
}
if(special && !is_up) {
switch(special) {
case 0x04: /* F4 - Emulator config panel */
cfg_toggle_config_panel();
break;
case 0x05: /* F5 - Force Refresh */
g_status_enable = !g_status_enable;
// video_update() will call video_update_status_enable()
break;
case 0x06: /* F6 - emulator speed */
if(SHIFT_DOWN) {
halt2_printf("Shift-F6 pressed\n");
} else {
adb_increment_speed();
}
break;
case 0x07: /* F7 - toggle debugger window, SHIFT:fast disk */
if(SHIFT_DOWN) {
g_fast_disk_emul_en = !g_fast_disk_emul_en;
iwm_update_fast_disk_emul(g_fast_disk_emul_en);
printf("g_fast_disk_emul_en is now %d\n",
g_fast_disk_emul_en);
} else {
video_set_active(&g_debugwin_kimage,
!g_debugwin_kimage.active);
printf("Toggled debugger window to:%d\n",
g_debugwin_kimage.active);
}
break;
case 0x08: /* F8 - warp pointer */
g_warp_pointer = !g_warp_pointer;
g_hide_pointer = g_warp_pointer;
printf("New warp:%d, new hide:%d\n", g_warp_pointer,
g_hide_pointer);
break;
case 0x09: /* F9 - swap paddles */
if(CTRL_DOWN) {
g_adb_copy_requested = 1;
} else if(SHIFT_DOWN) {
g_swap_paddles = !g_swap_paddles;
printf("Swap paddles is now: %d\n",
g_swap_paddles);
} else {
g_invert_paddles = !g_invert_paddles;
printf("Invert paddles is now: %d\n",
g_invert_paddles);
}
break;
case 0x0a: /* F10 - nothing */
break;
case 0x0b: /* F11 - full screen */
break;
}
return;
}
if(kimage_ptr == &g_debugwin_kimage) {
debugger_key_event(kimage_ptr, a2code, is_up);
if(restore_c025_val) {
g_c025_val = restore_c025_val & 0xff; // Restore shift
kimage_ptr->c025_val = restorek_c025_val;
}
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;
}
}
}
adb_maybe_virtual_key_update(a2code, is_up);
other_a2code = g_rawa2_to_a2code[raw_a2code & 0x7f];
if((other_a2code >= 0) && is_up) {
adb_maybe_virtual_key_update(other_a2code, is_up);
g_rawa2_to_a2code[raw_a2code & 0x7f] = -1;
}
if(restore_c025_val) {
g_c025_val = restore_c025_val & 0xff; // Restore shift
}
}
void
adb_maybe_virtual_key_update(int a2code, int is_up)
{
int autopoll;
autopoll = 1;
if(g_adb_mode & 1) {
/* autopoll is explicitly off */
autopoll = 0;
}
if(g_kbd_dev_addr != g_kbd_ctl_addr) {
/* autopoll is off because ucontroller doesn't know kbd moved */
autopoll = 0;
}
if(g_config_control_panel) {
/* always do autopoll */
autopoll = 1;
}
if(is_up) {
if(!autopoll) {
/* no auto keys, generate SRQ! */
adb_kbd_reg0_data(a2code, is_up);
} else {
adb_virtual_key_update(a2code, is_up);
}
} else {
if(!autopoll) {
/* no auto keys, generate SRQ! */
adb_kbd_reg0_data(a2code, is_up);
} else {
/* was up, now down */
adb_virtual_key_update(a2code, is_up);
}
}
}
void
adb_virtual_key_update(int a2code, int is_up)
{
word32 mask;
int bitpos;
int i;
adb_printf("Virtual handle a2code: %02x, is_up: %d\n", a2code, is_up);
if(a2code < 0 || a2code > 0x7f) {
halt_printf("a2code: %04x!\n", a2code);
return;
}
i = (a2code >> 5) & 3;
bitpos = a2code & 0x1f;
mask = (1 << bitpos);
if(is_up) {
if(g_virtual_key_up[i] & mask) {
/* already up, do nothing */
} else {
g_virtual_key_up[i] |= mask;
adb_key_event(a2code, is_up);
}
} else {
if(g_virtual_key_up[i] & mask) {
g_virtual_key_up[i] &= (~mask);
adb_key_event(a2code, is_up);
}
}
}
#if 0
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);
}
}
}
}
#endif
void
adb_kbd_repeat_off()
{
g_key_down = 0;
}
void
adb_mainwin_focus(int has_focus)
{
g_adb_mainwin_has_focus = has_focus;
// printf("g_adb_mainwin_has_focus=%d\n", g_adb_mainwin_has_focus);
if(!has_focus) {
adb_nonmain_check();
}
}
================================================
FILE: gsplus/src/applesingle.c
================================================
/**********************************************************************/
/* GSplus - Apple //gs Emulator */
/* Based on KEGS by Kent Dickey */
/* Copyright 2021 Kent Dickey */
/* Copyright 2025-2026 GSplus Contributors */
/* */
/* This code is covered by the GNU GPL v3 */
/* See the file COPYING.txt or https://www.gnu.org/licenses/ */
/**********************************************************************/
// From Wikipedia AppleSingle_and_AppleDouble_formats):
// https://web.archive.org/web/20180311140826/http://kaiser-edv.de/
// documents/AppleSingle_AppleDouble.pdf
// All fields in an Applesingle file are in big-endian format
// ProDOS forked files are described in Technote tn-pdos-025.
#include "defc.h"
word32
applesingle_get_be32(const byte *bptr)
{
return (bptr[0] << 24) | (bptr[1] << 16) | (bptr[2] << 8) | bptr[3];
}
word32
applesingle_get_be16(const byte *bptr)
{
return (bptr[0] << 8) | bptr[1];
}
void
applesingle_set_be32(byte *bptr, word32 val)
{
bptr[3] = val;
bptr[2] = val >> 8;
bptr[1] = val >> 16;
bptr[0] = val >> 24;
}
void
applesingle_set_be16(byte *bptr, word32 val)
{
bptr[1] = val;
bptr[0] = val >> 8;
}
word32
applesingle_map_from_prodos(Disk *dsk, Dynapro_file *fileptr, int do_file_data)
{
byte *fptr, *bptr;
word32 data_size, resource_size, rounded_data_size, num_entries;
word32 rounded_resource_size, hdr_size, max_size, hdr_pos, data_pos;
word32 block, key_block, ret, good, has_finder_info, offset;
int level;
int i, j;
#if 0
printf("applesingle_map_from_prodos: %s do_file_data:%d\n",
fileptr->unix_path, do_file_data);
#endif
// First, handle mini directory describing the forks
key_block = fileptr->key_block;
ret = dynapro_map_one_file_block(dsk, fileptr, key_block, 1U << 30, 0);
if(ret == 0) {
printf(" dynapro_map_one_file_block ret 0, applesingle done\n");
return 0;
}
bptr = &(dsk->raw_data[key_block << 9]);
data_size = dynapro_get_word24(&bptr[5]);
resource_size = dynapro_get_word24(&bptr[0x100 + 5]);
has_finder_info = bptr[9] | bptr[27];
num_entries = 1; // ProDOS info always
if(has_finder_info) {
num_entries++;
}
rounded_data_size = data_size;
if(data_size) {
rounded_data_size = (data_size + 0x200) & -0x200;
num_entries++;
}
rounded_resource_size = resource_size;
if(resource_size) {
rounded_resource_size = (resource_size + 0x200) & -0x200;
num_entries++;
}
hdr_size = 256;
max_size = hdr_size + rounded_resource_size + rounded_data_size;
fileptr->buffer_ptr = 0;
fptr = 0;
if(do_file_data) {
fptr = calloc(1, max_size + 0x200);
#if 0
printf(" fptr:%p, max_size:%08x, res:%08x, data:%08x\n",
fptr, max_size, rounded_resource_size,
rounded_data_size);
#endif
}
// From now on, errors cannot return without free'ing fptr
good = 1;
if(resource_size) {
block = dynapro_get_word16(&bptr[0x100 + 1]);
level = bptr[0x100];
if(fptr) {
fileptr->buffer_ptr = fptr + 256;
}
ret = dynapro_map_file_blocks(dsk, fileptr, block, level, 0,
resource_size);
if(ret == 0) {
good = 0;
}
}
if(data_size) {
block = dynapro_get_word16(&bptr[1]);
level = bptr[0];
if(fptr) {
fileptr->buffer_ptr = fptr + 256 +
rounded_resource_size;
}
ret = dynapro_map_file_blocks(dsk, fileptr, block, level, 0,
data_size);
if(ret == 0) {
good = 0;
}
}
fileptr->buffer_ptr = 0;
// Now prepare the header
if(fptr) {
applesingle_set_be32(&fptr[0], 0x00051600); // Magic
applesingle_set_be32(&fptr[4], 0x00020000); // Version
applesingle_set_be16(&fptr[24], num_entries); // Version
hdr_pos = 26;
data_pos = 192;
// First do ProDOS entry
applesingle_set_be32(&fptr[hdr_pos + 0], 11); // ProDOS Info
applesingle_set_be32(&fptr[hdr_pos + 4], data_pos);
applesingle_set_be32(&fptr[hdr_pos + 8], 8);
applesingle_set_be16(&fptr[data_pos + 0], 0xc3);
applesingle_set_be16(&fptr[data_pos + 2], fileptr->file_type);
applesingle_set_be32(&fptr[data_pos + 4], fileptr->aux_type);
hdr_pos += 12;
data_pos += 8;
// Then do FinderInfo
if(has_finder_info) {
applesingle_set_be32(&fptr[hdr_pos + 0], 9); //Finder
applesingle_set_be32(&fptr[hdr_pos + 4], data_pos);
applesingle_set_be32(&fptr[hdr_pos + 8], 32);
for(i = 0; i < 2; i++) {
offset = bptr[9 + 18*i];
if(!offset) {
continue; // skip it
}
offset = ((offset - 1) & 1) * 8;
for(j = 0; j < 9; j++) {
fptr[data_pos + offset + j] =
bptr[10 + 18*i + j];
}
}
hdr_pos += 12;
data_pos += 32;
}
if(data_pos >= 256) {
printf("data_pos:%08x is too big\n", data_pos);
good = 0;
}
// First, do data fork
if(data_size) {
applesingle_set_be32(&fptr[hdr_pos + 0], 1); // Data
applesingle_set_be32(&fptr[hdr_pos + 4],
256 + rounded_resource_size);
applesingle_set_be32(&fptr[hdr_pos + 8], data_size);
hdr_pos += 12;
}
// Then do resource fork
if(resource_size) {
applesingle_set_be32(&fptr[hdr_pos + 0], 2); // Rsrc
applesingle_set_be32(&fptr[hdr_pos + 4], 256);
applesingle_set_be32(&fptr[hdr_pos + 8], resource_size);
hdr_pos += 12;
}
if(hdr_pos > 192) {
printf("hdr:%08x stomped on data\n", hdr_pos);
good = 0;
}
if(good) {
ret = dynapro_write_to_unix_file(fileptr->unix_path,
fptr, 256 + rounded_resource_size + data_size);
if(ret == 0) {
good = 0;
}
}
free(fptr);
}
// printf("applesingle_map_from_prodos done, good:%d\n", good);
return good;
}
word32
applesingle_from_unix(Disk *dsk, Dynapro_file *fileptr, byte *fptr,
dword64 dsize)
{
byte *bptr, *tptr;
word32 key_block, blocks_used, entry_id, blocks_out, offset, length;
word32 magic, version, hdr_pos, did_fork;
int num_entries;
int i;
// Return 0 if anything is wrong with the .applesingle file
// Otherwise, return (blocks_used << 16) | (key_block & 0xffff)
#if 0
printf("applesingle_from_unix %s, size:%08llx\n", fileptr->unix_path,
dsize);
#endif
key_block = fileptr->key_block;
bptr = &(dsk->raw_data[key_block << 9]);
if(dsize < 50) {
printf("Applesingle is too small\n");
return 0;
}
magic = applesingle_get_be32(&fptr[0]);
version = applesingle_get_be32(&fptr[4]);
num_entries = applesingle_get_be16(&fptr[24]);
if((magic != 0x00051600) || (version < 0x00020000)) {
printf("Bad Applesingle magic number is: %08x, vers:%08x\n",
magic, version);
return 0;
}
hdr_pos = 26;
blocks_used = 1;
did_fork = 0;
// printf(" num_entries:%d\n", num_entries);
for(i = 0; i < num_entries; i++) {
if((hdr_pos + 24) > dsize) {
printf("Applesingle header exceeds file size i:%d of "
"%d, hdr_pos:%04x dsize:%08llx\n", i,
num_entries, hdr_pos, dsize);
return 0;
}
entry_id = applesingle_get_be32(&fptr[hdr_pos + 0]);
offset = applesingle_get_be32(&fptr[hdr_pos + 4]);
length = applesingle_get_be32(&fptr[hdr_pos + 8]);
#if 0
printf(" header[%d] at +%04x: id:%d, offset:%08x, len:%08x\n",
i, hdr_pos, entry_id, offset, length);
#endif
if((offset + length) > dsize) {
printf("Applesingle entry_id:%d exceeds file size\n",
entry_id);
return 0;
}
switch(entry_id) {
case 1: // Data fork
case 2: // Resource fork
tptr = bptr;
if(entry_id == 2) { // Resource fork
tptr += 0x100;
}
#if 0
printf(" for entry_id %d, offset:%08x, length:%08x, "
"fptr:%p\n", entry_id, offset, length, fptr);
#endif
if(did_fork & (1 << entry_id)) {
printf("fork %d repeated!\n", entry_id);
return 0;
}
did_fork |= (1 << entry_id);
blocks_out = applesingle_make_prodos_fork(dsk,
fptr + offset, tptr, length);
if(blocks_out == 0) {
return 0;
}
blocks_used += (blocks_out >> 16);
break;
case 9: // Finder Info
if(length < 32) {
printf("Invalid Finder info, len:%d\n", length);
}
bptr[8] = 0x12;
bptr[8 + 18] = 0x12;
bptr[9] = 1;
bptr[9 + 18] = 2;
for(i = 0; i < 16; i++) {
bptr[10 + i] = fptr[offset + i];
bptr[10 + 18 + i] = fptr[offset + 16 + i];
}
break;
case 11: // ProDOS File Info
fileptr->file_type = fptr[offset + 3];
fileptr->aux_type = (fptr[offset + 6] << 8) |
fptr[offset + 7];
break;
default:
break; // Ignore it
}
hdr_pos += 12;
}
for(i = 1; i < 3; i++) {
if((did_fork >> i) & 1) {
continue;
}
// Create one block for this fork even though it's length==0
// i==1: no data fork; i==2: no resource fork
printf(" Doing dummy fork, i:%d, fptr:%p\n", i, fptr);
blocks_out = applesingle_make_prodos_fork(dsk, fptr,
bptr + ((i & 2) * 0x80), 0);
if(blocks_out == 0) {
return blocks_out;
}
blocks_used += (blocks_out >> 16);
}
fileptr->eof = 0x200;
return (blocks_used << 16) | key_block;
}
word32
applesingle_make_prodos_fork(Disk *dsk, byte *fptr, byte *tptr, word32 length)
{
word32 block, blocks_out, storage_type;
#if 0
printf("applesingle_make_prodos_fork: fptr:%p, tptr:%p, length:%08x\n",
fptr, tptr, length);
#endif
// Handle creating either a resource or data fork
block = dynapro_find_free_block(dsk);
if(block == 0) {
return 0;
}
blocks_out = dynapro_fork_from_unix(dsk, fptr, &storage_type, block,
length);
// printf(" dynapro_fork_from_unix ret: %08x, storage:%02x\n",
// blocks_out, storage_type);
tptr[0] = storage_type >> 4;
tptr[1] = blocks_out & 0xff; // key_block lo
tptr[2] = (blocks_out >> 8) & 0xff; // key_block hi
tptr[3] = (blocks_out >> 16) & 0xff; // blocks_used lo
tptr[4] = (blocks_out >> 24) & 0xff; // blocks_used hi
tptr[5] = length & 0xff; // eof lo
tptr[6] = (length >> 8) & 0xff; // eof mid
tptr[7] = (length >> 16) & 0xff; // eof hi
return blocks_out;
}
================================================
FILE: gsplus/src/clock.c
================================================
/**********************************************************************/
/* GSplus - Apple //gs Emulator */
/* Based on KEGS by Kent Dickey */
/* Copyright 2002-2022 Kent Dickey */
/* Copyright 2025-2026 GSplus Contributors */
/* */
/* This code is covered by the GNU GPL v3 */
/* See the file COPYING.txt or https://www.gnu.org/licenses/ */
/**********************************************************************/
#include "defc.h"
#include <time.h>
#ifdef _WIN32
# include <windows.h>
# include <mmsystem.h>
#else
# include <sys/time.h>
#endif
extern int Verbose;
extern word32 g_vbl_count;
extern int g_rom_version;
extern int g_config_kegs_update_needed;
#define CLK_IDLE 1
#define CLK_TIME 2
#define CLK_INTERNAL 3
#define CLK_BRAM1 4
#define CLK_BRAM2 5
int g_clk_mode = CLK_IDLE;
int g_clk_read = 0;
int g_clk_reg1 = 0;
extern word32 g_c033_data;
extern word32 g_c034_val;
byte g_bram[2][256];
byte *g_bram_ptr = &(g_bram[0][0]);
word32 g_clk_cur_time = 0xa0000000;
int g_clk_next_vbl_update = 0;
double
get_dtime()
{
#ifdef _WIN32
FILETIME filetime;
dword64 dlow, dhigh;
#else
struct timeval tp1;
double dsec;
double dusec;
#endif
double dtime;
/* Routine used to return actual system time as a double */
/* No routine cares about the absolute value, only deltas--maybe */
/* take advantage of that in future to increase usec accuracy */
#ifdef _WIN32
//dtime = timeGetTime() / 1000.0;
GetSystemTimePreciseAsFileTime(&filetime);
dlow = filetime.dwLowDateTime;
dhigh = filetime.dwHighDateTime;
dlow = (dhigh << 32) | dlow;
dtime = (double)dlow;
dtime = dtime / (1000*1000*10.0); // FILETIME is in 100ns incs
#else
# ifdef SOLARIS
gettimeofday(&tp1, (void *)0);
# else
gettimeofday(&tp1, (struct timezone *)0);
# endif
dsec = (double)tp1.tv_sec;
dusec = (double)tp1.tv_usec;
dtime = dsec + (dusec / (1000.0 * 1000.0));
#endif
return dtime;
}
int
micro_sleep(double dtime)
{
#ifndef _WIN32
struct timeval Timer;
int ret;
#endif
if(dtime <= 0.0) {
return 0;
}
if(dtime >= 1.0) {
halt_printf("micro_sleep called with %f!!\n", dtime);
return -1;
}
#if 0
printf("usleep: %f\n", dtime);
#endif
#ifdef _WIN32
Sleep((word32)(dtime * 1000));
#else
Timer.tv_sec = 0;
Timer.tv_usec = (dtime * 1000000.0);
if( (ret = select(0, 0, 0, 0, &Timer)) < 0) {
fprintf(stderr, "micro_sleep (select) ret: %d, errno: %d\n",
ret, errno);
return -1;
}
#endif
return 0;
}
void
clk_bram_zero()
{
int i, j;
/* zero out all bram */
for(i = 0; i < 2; i++) {
for(j = 0; j < 256; j++) {
g_bram[i][j] = 0;
}
}
g_bram_ptr = &(g_bram[0][0]);
}
void
clk_bram_set(int bram_num, int offset, int val)
{
if((bram_num < 0) || (bram_num > 2)) {
printf("bram_num %d out of range\n", bram_num);
return;
}
if((offset < 0) || (offset > 0x100)) {
printf("bram offset %05x out of range\n", offset);
return;
}
g_bram[bram_num][offset] = val;
}
void
clk_setup_bram_version()
{
if(g_rom_version < 3) {
g_bram_ptr = (&g_bram[0][0]); // ROM 01
} else {
g_bram_ptr = (&g_bram[1][0]); // ROM 03
}
}
void
clk_write_bram(FILE *fconf)
{
int i, j, k;
for(i = 0; i < 2; i++) {
fprintf(fconf, "\n");
for(j = 0; j < 256; j += 16) {
fprintf(fconf, "bram%d[%02x] =", 2*i + 1, j);
for(k = 0; k < 16; k++) {
fprintf(fconf, " %02x", g_bram[i][j+k]);
}
fprintf(fconf, "\n");
}
}
}
void
update_cur_time()
{
struct tm *tm_ptr;
time_t cur_time, secs, secs2;
cur_time = time(0);
/* Figure out the timezone (effectively) by diffing two times. */
/* this is probably not right for a few hours around daylight savings*/
/* time transition */
secs2 = mktime(gmtime(&cur_time));
tm_ptr = localtime(&cur_time);
secs = mktime(tm_ptr);
secs2 = secs2 - secs; // this is the timezone offset
#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 = cur_time - secs2;
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 */
/* So add in 66 years and 17 leap year days (1904 is a leap year) */
secs += ((66*365) + 17) * (24*3600);
g_clk_cur_time = (word32)secs;
clk_printf("Update g_clk_cur_time to %08x\n", g_clk_cur_time);
g_clk_next_vbl_update = g_vbl_count + 5;
}
/* clock_update called by sim65816 every VBL */
void
clock_update()
{
/* Nothing to do */
}
void
clock_update_if_needed()
{
int diff;
diff = g_clk_next_vbl_update - g_vbl_count;
if(diff < 0 || diff > 60) {
/* Been a while, re-read the clock */
update_cur_time();
}
}
void
clock_write_c034(word32 val)
{
g_c034_val = val & 0x7f;
if((val & 0x80) != 0) {
if((val & 0x20) == 0) {
printf("c034 write not last = 1\n");
/* set_halt(1); */
}
do_clock_data();
}
}
void
do_clock_data()
{
word32 mask, read, op;
clk_printf("In do_clock_data, g_clk_mode: %02x\n", g_clk_mode);
read = g_c034_val & 0x40;
switch(g_clk_mode) {
case CLK_IDLE:
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) {
case 0x0: /* Read/write seconds register */
g_clk_mode = CLK_TIME;
clock_update_if_needed();
break;
case 0x3: /* internal registers */
g_clk_mode = CLK_INTERNAL;
if(g_clk_reg1 & 0x2) {
/* extend BRAM read */
g_clk_mode = CLK_BRAM2;
g_clk_reg1 = (g_c033_data & 7) << 5;
}
break;
case 0x2: /* read/write ram 0x10-0x13 */
g_clk_mode = CLK_BRAM1;
g_clk_reg1 += 0x10;
break;
case 0x4: /* read/write ram 0x00-0x0f */
case 0x5: case 0x6: case 0x7:
g_clk_mode = CLK_BRAM1;
g_clk_reg1 = (g_c033_data >> 2) & 0xf;
break;
default:
halt_printf("Bad c033_data in CLK_IDLE: %02x\n",
g_c033_data);
}
} else {
printf("clk read from IDLE mode!\n");
/* set_halt(1); */
g_clk_mode = CLK_IDLE;
}
break;
case CLK_BRAM2:
if(!read) {
/* get more bits of bram addr */
if((g_c033_data & 0x83) == 0x00) {
/* more address bits */
g_clk_reg1 |= ((g_c033_data >> 2) & 0x1f);
g_clk_mode = CLK_BRAM1;
} else {
halt_printf("CLK_BRAM2: c033_data: %02x!\n",
g_c033_data);
g_clk_mode = CLK_IDLE;
}
} else {
halt_printf("CLK_BRAM2: clock read!\n");
g_clk_mode = CLK_IDLE;
}
break;
case CLK_BRAM1:
/* access battery ram addr g_clk_reg1 */
if(read) {
if(g_clk_read) {
/* Yup, read */
g_c033_data = g_bram_ptr[g_clk_reg1];
clk_printf("Reading BRAM loc %02x: %02x\n",
g_clk_reg1, g_c033_data);
} else {
halt_printf("CLK_BRAM1: said wr, now read\n");
}
} else {
if(g_clk_read) {
halt_printf("CLK_BRAM1: said rd, now write\n");
} else {
/* Yup, write */
clk_printf("Writing BRAM loc %02x with %02x\n",
g_clk_reg1, g_c033_data);
g_bram_ptr[g_clk_reg1] = g_c033_data;
g_config_kegs_update_needed = 1;
}
}
g_clk_mode = CLK_IDLE;
break;
case CLK_TIME:
if(read) {
if(g_clk_read == 0) {
halt_printf("Reading time, but in set mode!\n");
}
g_c033_data = (g_clk_cur_time >> (g_clk_reg1 * 8)) &
0xff;
clk_printf("Returning time byte %d: %02x\n",
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, g_c033_data);
mask = 0xff << (8 * g_clk_reg1);
g_clk_cur_time = (g_clk_cur_time & (~mask)) |
((g_c033_data & 0xff) << (8 * g_clk_reg1));
}
g_clk_mode = CLK_IDLE;
break;
case CLK_INTERNAL:
if(read) {
printf("Attempting to read internal reg %02x!\n",
g_clk_reg1);
} else {
switch(g_clk_reg1) {
case 0x0: /* test register */
if(g_c033_data & 0xc0) {
printf("Writing test reg: %02x!\n",
g_c033_data);
/* set_halt(1); */
}
break;
case 0x1: /* write protect reg */
clk_printf("Writing clk wr_protect: %02x\n",
g_c033_data);
if(g_c033_data & 0x80) {
printf("Stop, wr clk wr_prot: %02x\n",
g_c033_data);
/* set_halt(1); */
}
break;
default:
halt_printf("Writing int reg: %02x with %02x\n",
g_clk_reg1, g_c033_data);
}
}
g_clk_mode = CLK_IDLE;
break;
default:
halt_printf("clk mode: %d unknown!\n", g_clk_mode);
g_clk_mode = CLK_IDLE;
break;
}
}
================================================
FILE: gsplus/src/comp_swift
================================================
#!/bin/bash
# $KmKId: comp_swift,v 1.2 2020-12-11 22:58:32+00 kentd Exp $
echo "args are: " "$@"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -c \
-enable-objc-interop \
-sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk \
-swift-version 4 -Onone \
-serialize-debugging-options \
-import-objc-header Kegs-Bridging-Header.h \
-module-name Kegs \
"$@"
================================================
FILE: gsplus/src/compile_time.c
================================================
char g_compile_time[] = "Compiled: " __DATE__ " " __TIME__ ;
================================================
FILE: gsplus/src/config.c
================================================
/**********************************************************************/
/* GSplus - Apple //gs Emulator */
/* Based on KEGS by Kent Dickey */
/* Copyright 2002-2025 Kent Dickey */
/* Copyright 2025-2026 GSplus Contributors */
/* */
/* This code is covered by the GNU GPL v3 */
/* See the file COPYING.txt or https://www.gnu.org/licenses/ */
/**********************************************************************/
// g_cfg_slotdrive: 0: not doing file selection at all
// 1-0x7ff: doing file selection for given slot/drive
// 0xfff: doing file selection for ROM or charrom
#include "defc.h"
#include <stdarg.h>
#include "config.h"
#ifdef _WIN32
# include "win_dirent.h"
#else
# include <dirent.h>
#endif
extern int Verbose;
extern word32 g_vbl_count;
extern int g_track_bytes_35[];
extern int g_c031_disk35;
extern int g_cur_a2_stat;
extern byte *g_slow_memory_ptr;
extern byte *g_rom_fc_ff_ptr;
extern byte *g_rom_cards_ptr;
extern double g_cur_dcycs;
extern int g_rom_version;
extern word32 g_adb_repeat_vbl;
extern int g_adb_swap_command_option;
extern int g_limit_speed;
extern int g_zip_speed_mhz;
extern int g_force_depth;
int g_serial_cfg[2] = { 0, 1 }; // Slot 1=0=Real serial (printer?)
// Slot 2=1=Virt Modem
int g_serial_mask[2] = { 0, 0 };
char *g_serial_remote_ip[2] = { "", "" }; // cfg_init_menus will malloc()
int g_serial_remote_port[2] = { 9100, 9100 };
char *g_serial_device[2] = { "/dev/tty.USB.0", "/dev/tty.USB.1" };
// cfg_init_menus() will malloc() the above
int g_serial_win_device[2] = { 0, 0 }; // Disabled
int g_serial_modem_response_code = 10; // 10 - 2400
int g_serial_modem_allow_incoming = 0; // 1 for BBS'es
int g_serial_modem_init_telnet = 1; // 1 for BBS'es
extern word32 g_mem_size_base;
extern word32 g_mem_size_exp;
extern int g_video_line_update_interval;
extern int g_user_halt_bad;
extern int g_joystick_type;
extern int g_joystick_scale_factor_x;
extern int g_joystick_scale_factor_y;
extern int g_joystick_trim_amount_x;
extern int g_joystick_trim_amount_y;
extern int g_swap_paddles;
extern int g_invert_paddles;
extern int g_voc_enable;
extern int g_status_enable;
extern int g_mainwin_width;
extern int g_mainwin_height;
extern int g_mainwin_xpos;
extern int g_mainwin_ypos;
extern int g_screen_index[];
extern word32 g_full_refresh_needed;
extern word32 g_a2_screen_buffer_changed;
extern int g_key_down;
extern const char g_kegs_version_str[];
int g_config_control_panel = 0;
char g_config_kegs_name[1024] = { 0 };
char g_cfg_cwd_str[CFG_PATH_MAX] = { 0 };
int g_config_kegs_auto_update = 1;
int g_config_kegs_update_needed = 0;
int g_cfg_newdisk_select = 0;
int g_cfg_newdisk_blocks = 0;
int g_cfg_newdisk_blocks_default = 140*2;
int g_cfg_newdisk_type = 1;
int g_cfg_newdisk_type_default = 1;
word32 g_cfg_newdisk_slotdrive = 0;
const char *g_config_kegs_name_list[] = {
"config.kegs", "kegs_conf", ".config.kegs", 0
};
int g_highest_smartport_unit = -1;
int g_reparse_delay = 0;
int g_user_page2_shadow = 1;
char g_cfg_printf_buf[CFG_PRINTF_BUFSIZE];
char g_config_kegs_buf[CONF_BUF_LEN];
#define CFG_ERR_BUFSIZE 80
#define CFG_ERR_MAX 5
int g_cfg_err_pos = 0;
char g_cfg_err_bufs[CFG_ERR_MAX][CFG_ERR_BUFSIZE];
int g_cfg_curs_x = 0;
int g_cfg_curs_y = 0;
int g_cfg_curs_inv = 0;
int g_cfg_curs_mousetext = 0;
int g_cfg_screen_changed = 0;
byte g_cfg_screen[24][80];
#if defined(MAC) || defined(_WIN32)
int g_cfg_ignorecase = 1; // Ignore case in filenames
#else
int g_cfg_ignorecase = 0;
#endif
#define CFG_MAX_OPTS 34
#define CFG_OPT_MAXSTR 100
int g_cfg_opts_vals[CFG_MAX_OPTS];
char g_cfg_opts_str[CFG_PATH_MAX];
char g_cfg_opt_buf[CFG_OPT_MAXSTR];
char g_cfg_edit_buf[CFG_OPT_MAXSTR];
char *g_cfg_rom_path = "ROM"; // config_init_menus will malloc
char *g_cfg_charrom_path = "Undefined"; // config_init_menus will malloc
int g_cfg_charrom_pos = 0;
char *g_cfg_file_def_name = "Undefined";
char **g_cfg_file_strptr = 0;
int g_cfg_file_min_size = 1024;
int g_cfg_file_max_size = 2047*1024*1024;
int g_cfg_edit_type = 0;
void *g_cfg_edit_ptr = 0;
#define MAX_PARTITION_BLK_SIZE 65536
char *g_argv0_path = ".";
const char *g_kegs_default_paths[] = { "", "./", "${HOME}/",
"${HOME}/Library/KEGS/", "${0}/../", "${0}/",
"${0}/Contents/Resources/", 0 };
extern Cfg_menu g_cfg_main_menu[];
#define KNMP(a) &a, #a, 0
#define KNM(a) &a, #a
Cfg_menu g_cfg_disk_menu[] = {
{ "Disk Configuration", g_cfg_disk_menu, 0, 0, CFGTYPE_MENU },
{ "s5d1 = ", 0, 0, 0, CFGTYPE_DISK + 0x5000 },
{ "s5d2 = ", 0, 0, 0, CFGTYPE_DISK + 0x5010 },
{ "", 0, 0, 0, 0 },
{ "s6d1 = ", 0, 0, 0, CFGTYPE_DISK + 0x6000 },
{ "s6d2 = ", 0, 0, 0, CFGTYPE_DISK + 0x6010 },
{ "", 0, 0, 0, 0 },
{ "s7d1 = ", 0, 0, 0, CFGTYPE_DISK + 0x7000 },
{ "s7d2 = ", 0, 0, 0, CFGTYPE_DISK + 0x7010 },
{ "s7d3 = ", 0, 0, 0, CFGTYPE_DISK + 0x7020 },
{ "s7d4 = ", 0, 0, 0, CFGTYPE_DISK + 0x7030 },
{ "s7d5 = ", 0, 0, 0, CFGTYPE_DISK + 0x7040 },
{ "s7d6 = ", 0, 0, 0, CFGTYPE_DISK + 0x7050 },
{ "s7d7 = ", 0, 0, 0, CFGTYPE_DISK + 0x7060 },
{ "s7d8 = ", 0, 0, 0, CFGTYPE_DISK + 0x7070 },
{ "s7d9 = ", 0, 0, 0, CFGTYPE_DISK + 0x7080 },
{ "s7d10= ", 0, 0, 0, CFGTYPE_DISK + 0x7090 },
{ "s7d11= ", 0, 0, 0, CFGTYPE_DISK + 0x70a0 },
{ "s7d12= ", 0, 0, 0, CFGTYPE_DISK + 0x70b0 },
{ "", 0, 0, 0, 0 },
{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_newslot6_menu[] = {
{ "New 5.25\" disk image Configuration", g_cfg_newslot6_menu, 0, 0,
CFGTYPE_MENU },
{ "size,280,140KB", KNM(g_cfg_newdisk_blocks),
&g_cfg_newdisk_blocks_default, CFGTYPE_INT },
{ "Type,1,ProDOS/DOS 3.3,2,WOZ image,3,Dynamic ProDOS directory",
KNM(g_cfg_newdisk_type),
&g_cfg_newdisk_type_default, CFGTYPE_INT },
{ "", 0, 0, 0, 0 },
{ "Create and name the image", (void *)cfg_name_new_image, 0, 0, CFGTYPE_FUNC },
{ "", 0, 0, 0, 0 },
{ "Cancel, go back to Disk Config", g_cfg_disk_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_newslot5_menu[] = {
{ "New 3.5\" disk image Configuration", g_cfg_newslot5_menu, 0, 0,CFGTYPE_MENU},
{ "size,1600,800KB", KNM(g_cfg_newdisk_blocks),
&g_cfg_newdisk_blocks_default, CFGTYPE_INT },
{ "Type,1,ProDOS,2,WOZ image,3,Dynamic ProDOS directory",
KNM(g_cfg_newdisk_type),
&g_cfg_newdisk_type_default, CFGTYPE_INT },
{ "", 0, 0, 0, 0 },
{ "Create and name the image", (void *)cfg_name_new_image, 0, 0, CFGTYPE_FUNC },
{ "", 0, 0, 0, 0 },
{ "Cancel, go back to Disk Config", g_cfg_disk_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_newslot7_menu[] = {
{ "New Smartport disk image Configuration", g_cfg_newslot7_menu, 0, 0,
CFGTYPE_MENU},
{ "size,1600,800KB,3200,1600KB,16384,8MB,32768,16MB,65535,32MB",
KNM(g_cfg_newdisk_blocks), &g_cfg_newdisk_blocks_default,
CFGTYPE_INT },
{ "Type,1,ProDOS,3,Dynamic ProDOS directory", KNM(g_cfg_newdisk_type),
&g_cfg_newdisk_type_default, CFGTYPE_INT },
{ "", 0, 0, 0, 0 },
{ "Create and name the image", (void *)cfg_name_new_image, 0, 0, CFGTYPE_FUNC },
{ "", 0, 0, 0, 0 },
{ "Cancel, go back to Disk Config", g_cfg_disk_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_joystick_menu[] = {
{ "Joystick Configuration", g_cfg_joystick_menu, 0, 0, CFGTYPE_MENU },
{ "Joystick Emulation,0,Keypad Joystick,1,Mouse Joystick,2,Native Joystick 1,"
"3,Native Joystick 2", KNMP(g_joystick_type), CFGTYPE_INT },
{ "Joystick Scale X,0x100,Standard,0x119,+10%,0x133,+20%,"
"0x150,+30%,0xb0,-30%,0xcd,-20%,0xe7,-10%",
KNMP(g_joystick_scale_factor_x), CFGTYPE_INT },
{ "Joystick Scale Y,0x100,Standard,0x119,+10%,0x133,+20%,"
"0x150,+30%,0xb0,-30%,0xcd,-20%,0xe7,-10%",
KNMP(g_joystick_scale_factor_y), CFGTYPE_INT },
{ "Joystick Trim X", KNMP(g_joystick_trim_amount_x), CFGTYPE_INT },
{ "Joystick Trim Y", KNMP(g_joystick_trim_amount_y), CFGTYPE_INT },
{ "Swap Joystick X and Y,0,Normal operation,1,Paddle 1 and Paddle 0 swapped",
KNMP(g_swap_paddles), CFGTYPE_INT },
{ "Invert Joystick,0,Normal operation,1,Left becomes right and up becomes down",
KNMP(g_invert_paddles), CFGTYPE_INT },
{ "", 0, 0, 0, 0 },
{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_rom_menu[] = {
{ "ROM File Selection", g_cfg_rom_menu, 0, 0, CFGTYPE_MENU },
{ "ROM File", KNMP(g_cfg_rom_path), CFGTYPE_FILE },
{ "", 0, 0, 0, 0 },
{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_charrom_menu[] = {
{ "Character ROM File Selection", g_cfg_charrom_menu, 0, 0, CFGTYPE_MENU },
{ "Character ROM File", KNMP(g_cfg_charrom_path), CFGTYPE_FILE },
{ "Character Set,0,0x00 US Enhanced,1,0x01 US Un-enhanced,"
"2,0x02 Clinton Turner V1 Enhanced,3,0x03 ReActiveMicro Enhanced,"
"4,0x04 Dan Paymar Enhanced,5,0x05 Blippo Black Enhanced,"
"6,0x06 Byte Enhanced,7,0x07 Colossal Enhanced,"
"8,0x08 Count Enhanced,9,0x09 Flow Enhanced,"
"10,0x0a Gothic Enhanced,11,0x0b Outline Enhanced,"
"12,0x0c Pigfont Enhanced,13,0x0d Pinocchio Enhanced,"
"14,0x0e Slant Enhanced,15,0x0f Stop Enhanced,"
"16,0x10 Euro Un-Enhanced,17,0x11 Euro Enhanced,"
"18,0x12 Clinton Turner V2 Enhanced,19,0x13 Improved German Enhanced,"
"20,0x14 Improved German Un-Enhanced,21,0x15 Franch Canadian Enhanced,"
"22,0x16 French Canadian Un-Enhanced,23,0x17 Hebrew Enhanced,"
"24,0x18 Hebrew Un-Enhanced,25,0x19 Apple II+ Enhanced,"
"26,0x1a Apple II+ Un-Enhanced,27,0x1b Katakana Enhanced,"
"28,0x1c Cyrillic Enhanced,29,0x1d Greek Enhanced,"
"30,0x1e Esperanto Enhanced,31,0x1f Videx Enhanced",
KNMP(g_cfg_charrom_pos), CFGTYPE_INT },
{ "", 0, 0, 0, 0 },
{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_serial_menu[] = {
{ "Serial Port Configuration", g_cfg_serial_menu, 0, 0, CFGTYPE_MENU },
{ "Slot 1 (port 0) settings", 0, 0, 0, 0 },
{ " Main setting ,0,Use Real Device below,1,Use a virtual modem,"
"2,Use Remote IP below,3,Use incoming port 6501",
KNMP(g_serial_cfg[0]), CFGTYPE_INT },
{ " Status ", (void *)cfg_get_serial0_status, 0, 0, CFGTYPE_FUNC },
{ " Real Device ", KNMP(g_serial_device[0]), CFGTYPE_FILE },
{ " Windows Device,0,Disabled,1,COM1,2,COM2,3,COM3,4,COM4",
KNMP(g_serial_win_device[0]), CFGTYPE_INT },
{ " Remote IP ", KNMP(g_serial_remote_ip[0]), CFGTYPE_STR },
{ " Remote Port ", KNMP(g_serial_remote_port[0]), CFGTYPE_INT },
{ " Serial Mask ,0,Send full 8-bit data,1,Mask off high bit",
KNMP(g_serial_mask[0]), CFGTYPE_INT },
{ "", 0, 0, 0, 0 },
{ "Slot 2 (port 1) settings", 0, 0, 0, 0, },
{ " Main setting ,0,Use Real Device below,1,Use a virtual modem,"
"2,Use Remote IP below,3,Use incoming port 6502",
KNMP(g_serial_cfg[1]), CFGTYPE_INT },
{ " Status ", (void *)cfg_get_serial1_status, 0, 0, CFGTYPE_FUNC },
{ " Real Device ", KNMP(g_serial_device[1]), CFGTYPE_FILE },
{ " Windows Device,1,COM1,2,COM2,3,COM3,4,COM4",
KNMP(g_serial_win_device[1]), CFGTYPE_INT },
{ " Remote IP ", KNMP(g_serial_remote_ip[1]), CFGTYPE_STR },
{ " Remote Port ", KNMP(g_serial_remote_port[1]), CFGTYPE_INT },
{ " Serial Mask ,0,Send full 8-bit data,1,Mask off high bit",
KNMP(g_serial_mask[1]), CFGTYPE_INT },
{ "", 0, 0, 0, 0 },
{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_modem_menu[] = {
{ "Virtual Modem Configuration", g_cfg_modem_menu, 0, 0, CFGTYPE_MENU },
{ "Modem Speed Response Code ,5,5 - CONNECT 1200,10,10 - CONNECT 2400,"
"12,12 - CONNECT 9600 (HAYES/Warp6),"
"13,13 - CONNECT 9600 (USR/HST),"
"14,14 - CONNECT 19200 (HAYES/Warp6),"
"28,28 - CONNECT 38400 (HAYES/Warp6)",
KNMP(g_serial_modem_response_code), CFGTYPE_INT },
{ "Allow Modem incoming on 6501/6502 ,0,Outgoing only,"
"1,Incoming and outgoing (BBS)",
KNMP(g_serial_modem_allow_incoming), CFGTYPE_INT },
{ "Send Telnet Escape codes ,0,Disable Telnet,1,Send Telnet codes",
KNMP(g_serial_modem_init_telnet), CFGTYPE_INT },
{ "", 0, 0, 0, 0 },
{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_video_menu[] = {
{ "Force X-windows display depth", KNMP(g_force_depth), CFGTYPE_INT },
{ "Enable VOC,0,Disabled,1,Enabled", KNMP(g_voc_enable), CFGTYPE_INT },
{ "Default Main Window width", KNMP(g_mainwin_width), CFGTYPE_INT },
{ "Default Main Window height", KNMP(g_mainwin_height), CFGTYPE_INT },
{ "Main Window X position", KNMP(g_mainwin_xpos), CFGTYPE_INT },
{ "Main Window Y position", KNMP(g_mainwin_ypos), CFGTYPE_INT },
{ "3200 Color Enable,0,Auto (Full if fast enough),1,Full (Update every line),"
"8,Off (Update video every 8 lines)",
KNMP(g_video_line_update_interval), CFGTYPE_INT },
{ "Dump text screen to file", (void *)cfg_text_screen_dump, 0, 0, CFGTYPE_FUNC},
{ "", 0, 0, 0, 0 },
{ "Back to Main Config", g_cfg_main_menu, 0, 0, CFGTYPE_MENU },
{ 0, 0, 0, 0, 0 },
};
Cfg_menu g_cfg_main_menu[] = {
{ "KEGS Configuration", g_cfg_main_menu, 0, 0, CFGTYPE_MENU },
{ "Disk Configuration", g_cfg_disk_menu, 0, 0, CFGTYPE_MENU },
{ "Joystick Configuration", g_cfg_joystick_menu, 0, 0, CFGTYPE_MENU },
{ "ROM File Selection", g_cfg_rom_menu, 0, 0, CFGTYPE_MENU },
{ "Character ROM Selection", g_cfg_charrom_menu, 0, 0, CFGTYPE_MENU },
{ "Serial Port Configuration", g_cfg_serial_menu, 0, 0, CFGTYPE_MENU },
{ "Virtual Modem Configuration", g_cfg_modem_menu, 0, 0, CFGTYPE_MENU },
{ "Video Settings", g_cfg_video_menu, 0, 0, CFGTYPE_MENU },
{ "Auto-update config.kegs,0,Manual,1,Immediately",
KNMP(g_config_kegs_auto_update), CFGTYPE_INT },
{ "Speed,0,Unlimited,1,1.0MHz,2,2.8MHz,3,8.0MHz (Zip)",
KNMP(g_limit_speed), CFGTYPE_INT },
{ "ZipGS Speed,8,8MHz,16,16MHz,32,32MHz,64,64MHz,128,128MHz",
KNMP(g_zip_speed_mhz), CFGTYPE_INT },
{ "Expansion Mem Size,0,0MB,0x100000,1MB,0x200000,2MB,0x300000,3MB,"
"0x400000,4MB,0x600000,6MB,0x800000,8MB,0xa00000,10MB,0xc00000,12MB,"
"0xe00000,14MB", KNMP(g_mem_size_exp), CFGTYPE_INT },
{ "Show Status lines,0,Disabled,1,Enabled", KNMP(g_status_enable), CFGTYPE_INT},
{ "Code Red Halts,0,Do not stop on bad accesses,1,Enter debugger on bad "
"accesses", KNMP(g_user_halt_bad), CFGTYPE_INT },
{ "Enable Text Page 2 Shadow,0,Disabled on ROM 01 (matches real hardware),"
"1,Enabled on ROM 01 and 03",
KNMP(g_user_page2_shadow), CFGTYPE_INT },
{ "Swap Command/Option keys,0,Disabled,1,Swapped",
KNMP(g_adb_swap_command_option), CFGTYPE_INT },
{ "", 0, 0, 0, 0 },
{ "Save changes to config.kegs", (void *)config_write_config_kegs_file, 0, 0,
CFGTYPE_FUNC },
{ "", 0, 0, 0, 0 },
{ "Exit Config (or press F4)", (void *)cfg_exit, 0, 0, CFGTYPE_FUNC },
{ 0, 0, 0, 0, 0 },
};
#define CFG_MAX_DEFVALS 128
Cfg_defval g_cfg_defvals[CFG_MAX_DEFVALS];
int g_cfg_defval_index = 0;
word32 g_cfg_slotdrive = 0;
int g_cfg_select_partition = -1;
char g_cfg_tmp_path[CFG_PATH_MAX];
char g_cfg_file_path[CFG_PATH_MAX];
char g_cfg_file_cachedpath[CFG_PATH_MAX];
char g_cfg_file_cachedreal[CFG_PATH_MAX];
char g_cfg_file_curpath[CFG_PATH_MAX];
char g_cfg_file_shortened[CFG_PATH_MAX];
char g_cfg_file_match[CFG_PATH_MAX];
char g_cfg_part_path[CFG_PATH_MAX];
int g_cfg_partition_is_zip = 0;
Cfg_listhdr g_cfg_dirlist = { 0 };
Cfg_listhdr g_cfg_partitionlist = { 0 };
int g_cfg_file_pathfield = 0;
const char *g_kegs_rom_names[] = { "ROM", "ROM", "ROM.01", "ROM.03",
"APPLE2GS.ROM", "APPLE2GS.ROM2", "xgs.rom", "XGS.ROM", "Rom03gd",
"342-0077-b", // MAME ROM.01
0 };
/* First entry is special--it will be overwritten by g_cfg_rom_path */
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
};
byte g_rom_c700[256] = {
//0xa2, 0x20, 0xa2, 0x00, 0xa2, 0x03, 0xc9, 0x3c, // For Apple //e
0xa2, 0x20, 0xa2, 0x00, 0xa2, 0x03, 0xc9, 0x00,
//^^= LDX #$20; LDY #$00, LDX #$03 CMP #$3c
0x80, 0x0c, 0x18, 0xb8, 0x70, 0x38, 0xb8, 0x42,
//^^= BRA $c716; CLC; CLV; BVS $c746 (SEC); CLV; WDM $c7,$00
0xc7, 0x00, 0x60, 0x00, 0x00, 0xea, 0xe2, 0x41,
//^^= ...; RTS..............; NOP; SEP #$41
0x70, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//^^= BVS $c70f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// So does WDM $c7,$00 with psr.v=1 for $c700; v=0,c=0 for $c70a,
// and v=0,c=1 for $c70d
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, 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, 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, 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,
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, 0x80, 0x00, 0x00, 0xbf, 0x0a
};
Cfg_menu *g_menuptr = 0;
int g_menu_line = 1;
int g_menu_inc = 1;
int g_menu_max_line = 1;
int g_menu_redraw_needed = 1;
#define MAX_CFG_ARGV_OVERRIDES 64
int g_cfg_argv_num_overrides = 0;
char *g_cfg_argv_overrides[MAX_CFG_ARGV_OVERRIDES];
int
config_add_argv_override(const char *str1, const char *str2)
{
const char *equal_ptr;
char *str;
int ret, pos, len;
// Handle things like "rom=rompath" and "rom", "rompath"
// Look through str1, see if there is '=', if so ignore str2
equal_ptr = strchr(str1, '=');
ret = 1;
if(equal_ptr) { // str1 has '=' in it
ret = 0; // Don't eat up str2 argument
str = kegs_malloc_str(str1);
} else {
// We need to form a new string of str1, =, str2
len = (int)(strlen(str1) + strlen(str2) + 2);
str = malloc(len);
cfg_strncpy(str, str1, len);
cfg_strlcat(str, "=", len);
cfg_strlcat(str, str2, len);
}
pos = g_cfg_argv_num_overrides++;
if(pos >= MAX_CFG_ARGV_OVERRIDES) {
g_cfg_argv_num_overrides = MAX_CFG_ARGV_OVERRIDES;
fatal_printf("MAX_CFG_ARGV_OVERRIDES overflow\n");
my_exit(5);
return ret;
}
g_cfg_argv_overrides[pos] = str;
printf("Added config override %d, %s\n", pos, str);
return ret;
}
void
config_set_config_kegs_name(const char *str1)
{
int maxlen;
// Command line override "-cfg cfg_file"
g_config_kegs_name[0] = 0;
maxlen = (int)sizeof(g_config_kegs_name);
cfg_strncpy(&g_config_kegs_name[0], str1, maxlen);
}
void
config_init_menus(Cfg_menu *menuptr)
{
void *voidptr;
const char *name_str;
Cfg_defval *defptr;
char **str_ptr;
char *str;
int type, pos, val;
if(menuptr[0].defptr != 0) {
return;
}
menuptr[0].defptr = (void *)1;
pos = 0;
while(pos < 100) {
type = menuptr->cfgtype;
voidptr = menuptr->ptr;
name_str = menuptr->name_str;
if(menuptr->str == 0) {
break;
}
if(name_str != 0) {
defptr = &(g_cfg_defvals[g_cfg_defval_index++]);
if(g_cfg_defval_index >= CFG_MAX_DEFVALS) {
fatal_printf("CFG_MAX_DEFVAL overflow\n");
my_exit(5);
return;
}
defptr->menuptr = menuptr;
defptr->intval = 0;
defptr->strval = 0;
switch(type) {
case CFGTYPE_INT:
val = *((int *)voidptr);
defptr->intval = val;
menuptr->defptr = &(defptr->intval);
break;
case CFGTYPE_FILE:
case CFGTYPE_STR:
str_ptr = (char **)menuptr->ptr;
str = *str_ptr;
// We need to malloc this string since all
// string values must be dynamically alloced
defptr->strval = str; // this can have a copy
*str_ptr = kegs_malloc_str(str);
menuptr->defptr = &(defptr->strval);
break;
default:
fatal_printf("name_str is %p = %s, but type: "
"%d\n", name_str, name_str, type);
my_exit(5);
return;
}
}
if(type == CFGTYPE_MENU) {
config_init_menus((Cfg_menu *)voidptr);
}
pos++;
menuptr++;
}
}
void
config_init()
{
config_init_menus(g_cfg_main_menu);
// Find the config.kegs file
if(g_config_kegs_name[0] == 0) {
cfg_find_config_kegs_file();
}
config_parse_config_kegs_file();
}
void
cfg_find_config_kegs_file()
{
const char **path_ptr;
int maxlen, fd;
g_config_kegs_name[0] = 0;
maxlen = sizeof(g_config_kegs_name);
fd = 0;
if(!config_setup_kegs_file(&g_config_kegs_name[0], maxlen,
&g_config_kegs_name_list[0])) {
// Try to create config.kegs
fd = -1;
path_ptr = &g_kegs_default_paths[0];
while(*path_ptr) {
config_expand_path(&g_config_kegs_name[0], *path_ptr,
maxlen);
cfg_strlcat(&g_config_kegs_name[0], "config.kegs",
maxlen);
printf("Trying to create %s\n", &g_config_kegs_name[0]);
fd = open(&g_config_kegs_name[0],
O_CREAT | O_TRUNC | O_WRONLY, 0x1b6);
close(fd);
if(fd >= 0) {
break;
}
path_ptr++;
}
}
if(fd < 0) {
fatal_printf("Could not create config.kegs!\n");
my_exit(2);
}
}
int
config_setup_kegs_file(char *outname, int maxlen, const char **name_ptr)
{
struct stat stat_buf;
const char **path_ptr, **cur_name_ptr;
mode_t fmt;
int ret, len;
outname[0] = 0;
path_ptr = &g_kegs_default_paths[0]; // Array of strings
while(*path_ptr) {
len = config_expand_path(outname, *path_ptr, maxlen);
if(len != (int)strlen(outname)) {
printf("config_expand_path ret %d, but strlen:%d!\n",
len, (int)strlen(outname));
}
cur_name_ptr = name_ptr;
while(*cur_name_ptr && (len < maxlen)) {
outname[len] = 0;
cfg_strlcat(outname, *cur_name_ptr, maxlen);
// printf("Doing stat on %s\n", outname);
ret = cfg_stat(outname, &stat_buf, 0);
if(ret == 0) {
fmt = stat_buf.st_mode & S_IFMT;
if(fmt != S_IFDIR) {
/* got it! */
return 1;
}
}
cur_name_ptr++;
}
path_ptr++;
}
return 0;
}
int
config_expand_path(char *out_ptr, const char *in_ptr, int maxlen)
{
char name_buf[256];
char *tmp_ptr;
int name_len, in_char, state, pos;
out_ptr[0] = 0;
pos = 0;
name_len = 0;
state = 0;
/* See if in_ptr has ${} notation, replace with getenv or argv0 */
while(pos < (maxlen - 1)) {
in_char = *in_ptr++;
out_ptr[pos++] = in_char;
out_ptr[pos] = 0;
if(in_char == 0) {
return pos - 1;
}
if(state == 0) {
/* No $ seen yet, look for it */
if(in_char == '$') {
state = 1;
}
} else if(state == 1) {
/* See if next char is '{' (dummy }) */
if(in_char == '{') { /* add dummy } */
state = 2;
name_len = 0;
pos -= 2;
out_ptr[pos] = 0;
} else {
state = 0;
}
} else if(state == 2) {
/* fill name_buf ... dummy '{' */
pos--;
out_ptr[pos] = 0;
if(in_char == '}') {
name_buf[name_len] = 0;
/* got token, now look it up */
tmp_ptr = "";
if(!strncmp("0", name_buf, 128)) {
/* Replace ${0} with g_argv0_path */
tmp_ptr = g_argv0_path;
} else {
tmp_ptr = getenv(name_buf);
if(tmp_ptr == 0) {
tmp_ptr = "";
}
}
pos = cfg_strlcat(out_ptr, tmp_ptr, maxlen);
state = 0;
} else {
name_buf[name_len++] = in_char;
if(name_len >= 250) {
name_len--;
}
}
}
}
return pos;
}
char *
cfg_exit(int get_status)
{
/* printf("In cfg exit\n"); */
if(get_status) {
return 0;
}
cfg_toggle_config_panel();
return 0;
}
void
cfg_err_vprintf(const char *pre_str, const char *fmt, va_list ap)
{
char *bufptr;
int pos, len, bufsize;
pos = g_cfg_err_pos;
if(pos >= CFG_ERR_MAX) {
pos = CFG_ERR_MAX - 1;
}
bufptr = &g_cfg_err_bufs[pos][0];
len = 0;
bufsize = CFG_ERR_BUFSIZE;
if(pre_str && *pre_str) {
cfg_strncpy(bufptr, pre_str, CFG_ERR_BUFSIZE);
cfg_strlcat(bufptr, " error: ", CFG_ERR_BUFSIZE);
len = (int)strlen(bufptr);
bufsize = CFG_ERR_BUFSIZE - len;
}
if(bufsize > 0) {
vsnprintf(&bufptr[len], bufsize, fmt, ap);
}
fputs(bufptr, stderr);
g_cfg_err_pos = pos + 1;
}
void
cfg_err_printf(const char *pre_str, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
cfg_err_vprintf(pre_str, fmt, ap);
va_end(ap);
}
void
cfg_toggle_config_panel()
{
int panel;
panel = !g_config_control_panel;
if(g_rom_version < 0) {
panel = 1; /* Stay in config mode */
}
if(panel != g_config_control_panel) {
cfg_set_config_panel(panel);
}
}
void
cfg_set_config_panel(int panel)
{
int i;
g_config_control_panel = panel;
if(panel) {
// Entering configuration panel
video_force_reparse();
cfg_printf("Entering config_control_panel\n");
for(i = 0; i < 20; i++) {
// Toss any queued-up keypresses
if(adb_read_c000() & 0x80) {
(void)adb_access_c010();
}
}
// HACK: Force adb keyboard (and probably mouse) to "normal"...
cfg_home();
g_menu_line = 1;
g_menu_inc = 1;
g_menu_redraw_needed = 1;
g_cfg_slotdrive = 0;
g_cfg_newdisk_select = 0;
g_cfg_select_partition = -1;
} else {
// Leave config panel, go back to A2 emulation
video_force_reparse();
}
g_full_refresh_needed = -1;
g_a2_screen_buffer_changed = -1;
g_adb_repeat_vbl = g_vbl_count + 60;
}
char *
cfg_text_screen_dump(int get_status)
{
FILE *ofile;
char *bufptr;
char *filename;
if(get_status) {
return 0;
}
filename = "kegs.screen.dump";
printf("Writing text screen to the file %s\n", filename);
ofile = fopen(filename, "w");
if(ofile == 0) {
fatal_printf("Could not write to file %s, (%d)\n", filename,
errno);
return 0;
}
bufptr = cfg_text_screen_str();
fputs(bufptr, ofile);
fclose(ofile);
return 0;
}
char g_text_screen_buf[2100] = { 0 };
char *
cfg_text_screen_str()
{
char *bufptr;
int pos, start_pos, c, offset;
int i, j;
// bufptr must be at least (81*24)+2 characters
bufptr = &g_text_screen_buf[0];
pos = 0;
for(i = 0; i < 24; i++) {
start_pos = pos;
for(j = 0; j < 40; j++) {
offset = g_screen_index[i] + j;
if(g_cur_a2_stat & ALL_STAT_VID80) {
c = g_slow_memory_ptr[0x10400 + offset] & 0x7f;
if(c < 0x20) {
c += 0x40;
}
bufptr[pos++] = c;
}
c = g_slow_memory_ptr[0x0400 + offset] & 0x7f;
if(c < 0x20) {
c += 0x40;
}
if(c == 0x7f) {
c = ' ';
}
bufptr[pos++] = c;
}
while((pos > start_pos) && (bufptr[pos-1] == ' ')) {
/* try to strip out trailing spaces */
pos--;
}
bufptr[pos++] = '\n';
bufptr[pos] = 0;
}
return bufptr;
}
char *
cfg_get_serial0_status(int get_status)
{
return scc_get_serial_status(get_status, 0);
}
char *
cfg_get_serial1_status(int get_status)
{
return scc_get_serial_status(get_status, 1);
}
char *
cfg_get_current_copy_selection()
{
return &g_text_screen_buf[0];
}
void
config_vbl_update(int doit_3_persec)
{
if(doit_3_persec) {
if(g_config_kegs_auto_update && g_config_kegs_update_needed) {
(void)config_write_config_kegs_file(0);
}
}
return;
}
void
cfg_file_update_rom(const char *str)
{
cfg_file_update_ptr(&g_cfg_rom_path, str, 1);
}
void
cfg_file_update_ptr(char **strptr, const char *str, int need_update)
{
char *newstr;
int remote_changed, serial_changed;
int i;
// Update whatever g_cfg_file_strptr points to. If changing
// ROM path or Charrom, then do the proper updates
newstr = kegs_malloc_str(str);
if(!strptr) {
return;
}
if(*strptr) {
free(*strptr);
}
*strptr = newstr;
if(strptr == &(g_cfg_rom_path)) {
printf("Updated ROM file\n");
load_roms_init_memory();
do_reset();
}
if(strptr == &(g_cfg_charrom_path)) {
printf("Updated Char ROM file\n");
cfg_load_charrom();
}
for(i = 0; i < 2; i++) {
remote_changed = 0;
serial_changed = 0;
if(strptr == &g_serial_remote_ip[i]) {
remote_changed = 1;
}
if(strptr == &g_serial_device[i]) {
serial_changed = 1;
}
if(remote_changed || serial_changed) {
scc_config_changed(i, 0, remote_changed,
serial_changed);
}
}
if(need_update) {
g_config_kegs_update_needed = 1;
printf("Set g_config_kegs_update_needed = 1\n");
}
}
void
cfg_int_update(int *iptr, int new_val)
{
int old_val, cfg_changed, remote_changed, serial_changed;
int i;
// Called to handle an integer being changed in the F4 config menus
// where it's value may need special handling
old_val = *iptr;
*iptr = new_val;
if(old_val == new_val) {
return;
}
if(iptr == &g_cfg_charrom_pos) {
cfg_load_charrom();
}
for(i = 0; i < 2; i++) {
remote_changed = 0;
serial_changed = 0;
cfg_changed = 0;
if(iptr == &g_serial_cfg[i]) {
cfg_changed = 1;
}
if(iptr == &g_serial_remote_port[i]) {
remote_changed = 1;
}
if(iptr == &g_serial_win_device[i]) {
serial_changed = 1;
}
if(cfg_changed || remote_changed || serial_changed) {
scc_config_changed(i, cfg_changed, remote_changed,
serial_changed);
}
}
}
void
cfg_load_charrom()
{
byte buffer[4096];
dword64 dsize, dret;
word32 upos;
int fd;
printf("Loading character ROM from: %s\n", g_cfg_charrom_path);
fd = open(g_cfg_charrom_path, O_RDONLY | O_BINARY);
if(fd < 0) {
printf("Cannot open %s\n", g_cfg_charrom_path);
return;
}
dsize = cfg_get_fd_size(fd);
upos = g_cfg_charrom_pos * 0x1000U;
if(dsize < (upos + 0x1000)) {
g_cfg_charrom_pos = 0;
return;
}
dret = cfg_read_from_fd(fd, &buffer[0], upos, 4096);
if(dret != 0) {
prepare_a2_romx_font(&buffer[0]);
}
}
void
config_load_roms()
{
struct stat stat_buf;
const char **names_ptr;
int more_than_8mb, changed_rom, len, fd, ret;
int i;
g_rom_version = -1;
/* set first entry of g_kegs_rom_names[] to g_cfg_rom_path so that */
/* it becomes the first place searched. */
g_kegs_rom_names[0] = g_cfg_rom_path;
ret = config_setup_kegs_file(&g_cfg_tmp_path[0], CFG_PATH_MAX,
&g_kegs_rom_names[0]);
if(ret == 0) {
// Just get out, let config interface select ROM
g_config_control_panel = 1;
printf("No ROM, set g_config_control_panel=1\n");
return;
}
printf("Found ROM at path: %s\n", g_cfg_tmp_path);
fd = open(&g_cfg_tmp_path[0], O_RDONLY | O_BINARY);
if(fd < 0) {
fatal_printf("Open ROM file %s failed:%d, errno:%d\n",
&g_cfg_tmp_path[0], fd, errno);
g_config_control_panel = 1;
return;
}
ret = fstat(fd, &stat_buf);
if(ret != 0) {
fatal_printf("fstat returned %d on fd %d, errno: %d\n",
ret, fd, errno);
g_config_control_panel = 1;
return;
}
len = (int)stat_buf.st_size;
memset(&g_rom_fc_ff_ptr[0], 0, 4*65536);
/* Clear banks fc-ff to 0 */
if(len == 32*1024) { // Apple //e
g_rom_version = 0;
g_mem_size_base = 128*1024;
ret = (int)read(fd, &g_rom_fc_ff_ptr[3*65536 + 32768], len);
} else if(len == 128*1024) {
g_rom_version = 1;
g_mem_size_base = 128*1024;
ret = (int)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 = (int)read(fd, &g_rom_fc_ff_ptr[0], len);
} else {
fatal_printf("The ROM size should be 128K or 256K, this file "
"is %d bytes\n", len);
g_config_control_panel = 1;
return;
}
printf("Read: %d bytes of ROM\n", ret);
if(ret != len) {
fatal_printf("errno: %d\n", errno);
g_config_control_panel = 1;
return;
}
close(fd);
memset(&g_rom_cards_ptr[0], 0, 256*16);
for(i = 0; i < 256; i++) {
// Place HD PROM in slot 7
g_rom_cards_ptr[0x700 + i] = g_rom_c700[i];
// g_rom_cards_ptr[0x500 + i] = g_rom_c700[i];
}
/* initialize c600 rom to be diffs from the real ROM, to build-in */
/* Apple II compatibility without distributing ROMs */
if(g_rom_version == 0) { // Apple //e
for(i = 0; i < 256; i++) {
// Place Disk II PROM in slot 6
g_rom_cards_ptr[0x600 + i] = g_rom_fc_ff_ptr[0x38600+i];
}
} else {
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;
}
ret = config_setup_kegs_file(&g_cfg_tmp_path[0], CFG_PATH_MAX,
names_ptr);
if(ret != 0) {
fd = open(&(g_cfg_tmp_path[0]), O_RDONLY | O_BINARY);
if(fd < 0) {
fatal_printf("Open card ROM file %s failed: %d "
"err:%d\n", &g_cfg_tmp_path[0], fd,
errno);
continue;
}
len = 256;
ret = (int)read(fd, &g_rom_cards_ptr[i*0x100], len);
if(ret != len) {
fatal_printf("While reading card ROM %s, file "
"is too short. (%d) Expected %d bytes, "
"read %d bytes\n", errno, len, ret);
continue;
}
close(fd);
}
}
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;
}
}
}
void
config_parse_config_kegs_file()
{
char *bufptr;
const char *str;
dword64 dsize;
int fd, pos, start, size, last_c, line, ret, c, maxlen;
int i;
printf("Parsing config.kegs file: %s\n", g_config_kegs_name);
clk_bram_zero();
g_highest_smartport_unit = -1;
cfg_get_base_path(&g_cfg_cwd_str[0], g_config_kegs_name, 0);
if(g_cfg_cwd_str[0] != 0) {
ret = chdir(&g_cfg_cwd_str[0]);
if(ret != 0) {
printf("chdir to %s, errno:%d\n", g_cfg_cwd_str, errno);
}
// Do basename(g_config_kegs_name)--on it's own buffer
str = cfg_str_basename(g_config_kegs_name);
maxlen = sizeof(g_config_kegs_name);
cfg_strncpy(&g_config_kegs_name[0], str, maxlen);
}
// In any case, copy the current directory path to g_cfg_cwd_str
(void)!getcwd(&g_cfg_cwd_str[0], CFG_PATH_MAX);
printf("CWD is now: %s\n", &g_cfg_cwd_str[0]);
fd = open(g_config_kegs_name, O_RDONLY | O_BINARY);
dsize = 0;
if(fd >= 0) {
dsize = cfg_get_fd_size(fd);
}
if((fd < 0) || (dsize >= (1 << 30))) {
fatal_printf("cannot open config.kegs at %s, or it is too "
"large! Stopping!\n", g_config_kegs_name);
my_exit(3);
return;
}
size = (int)dsize;
bufptr = malloc(size + 2);
ret = (int)cfg_read_from_fd(fd, (byte *)bufptr, 0, size);
close(fd);
if(ret != size) {
free(bufptr);
fatal_printf("Could not read config.kegs at %s\n",
g_config_kegs_name);
my_exit(3);
return;
}
bufptr[size] = 0; // Ensure it's null terminated
line = 0;
pos = 0;
last_c = 0;
while(pos < size) {
line++;
if((bufptr[pos] == '\n') && (last_c == '\r')) {
// CR,LF, just eat the LF
pos++;
}
start = pos;
while(pos < size) {
c = bufptr[pos];
if((c == 0) || (c == '\n') || (c == '\r')) {
last_c = c;
bufptr[pos] = 0;
break;
}
pos++;
}
cfg_parse_one_line(&bufptr[start], line);
pos++;
}
free(bufptr);
// And now do command line argument overrides
for(i = 0; i < g_cfg_argv_num_overrides; i++) {
printf("Doing override %d, %s\n", i, g_cfg_argv_overrides[i]);
cfg_parse_one_line(g_cfg_argv_overrides[i], 1001 + i);
g_config_kegs_update_needed = 1;
}
}
void
cfg_parse_one_line(char *buf, int line)
{
Cfg_menu *menuptr;
Cfg_defval *defptr;
int *iptr;
const char *nameptr;
int pos, num_equals, type, val, c, len;
int i;
// warning: modifies memory of bufptr (turns spaces to nulls)
if(line) { // Avoid unused parameter warning
}
len = (int)strlen(buf);
if(len <= 1) { // Not a valid line, just get out
return;
}
// printf("disk_conf[%d]: %s\n", line, buf);
if(buf[0] == '#') {
iwm_printf("Skipping comment\n");
return;
}
pos = 0;
while((pos < len) && (buf[pos] == ' ' || buf[pos] == '\t') ) {
pos++; // Eat whitespace
}
if(pos >= len) {
return; // blank line
}
if((pos + 5) < len) {
c = buf[pos+1]; // Slot number
if((buf[pos] == 's') && (buf[pos+2] == 'd') &&
(c >= '5' && c <= '7')) {
// looks like s5d1 through s7d15, parse that
cfg_parse_sxdx(buf, pos, len);
return;
}
}
// parse buf from pos into option, "=" and then "rest"
if(strncmp(&buf[pos], "bram", 4) == 0) {
cfg_parse_bram(buf, pos+4, len);
return;
}
// find "name" as first contiguous string
//printf("...parse_option: line %d, %s (%s) len:%d\n", line, buf,
// &buf[pos], len);
nameptr = &buf[pos];
while(pos < len) {
c = buf[pos];
if((c == 0) || (c == ' ') || (c == '\t') || (c == '\n') ||
(c == '=')) {
break;
}
pos++;
}
buf[pos] = 0;
if(strcmp(nameptr, "rom") == 0) {
// Translate argument of "-rom" to "g_cfg_rom_path"
nameptr = "g_cfg_rom_path";
}
pos++;
// Eat up all whitespace and '='
num_equals = 0;
while(pos < len) {
c = buf[pos];
if((c == '=') && (num_equals == 0)) {
pos++;
num_equals++;
} else if(c == ' ' || c == '\t') {
pos++;
} else {
break;
}
}
/* Look up nameptr to find type */
type = -1;
defptr = 0;
menuptr = 0;
for(i = 0; i < g_cfg_defval_index; i++) {
defptr = &(g_cfg_defvals[i]);
menuptr = defptr->menuptr;
if(strcmp(menuptr->name_str, nameptr) == 0) {
type = menuptr->cfgtype;
break;
}
}
switch(type) {
case CFGTYPE_INT:
/* use strtol */
val = (int)strtol(&buf[pos], 0, 0);
iptr = (int *)menuptr->ptr;
cfg_int_update(iptr, val);
break;
case CFGTYPE_FILE:
case CFGTYPE_STR:
cfg_file_update_ptr(menuptr->ptr, &buf[pos], 0);
break;
default:
printf("Config file variable %s is unknown type: %d\n",
nameptr, type);
}
}
void
cfg_parse_bram(char *buf, int pos, int len)
{
word32 val;
int bram_num, offset;
// Format: "bram1[00] = xx yy..." or "bram3[00] = xx yy ..."
// pos = position just after "bram"
if((len < (pos+5)) || (buf[pos+1] != '[') || (buf[pos+4] != ']')) {
fatal_printf("While reading config.kegs, found malformed bram "
"statement: %s\n", buf);
return;
}
bram_num = buf[pos] - '0';
if((bram_num != 1) && (bram_num != 3)) {
fatal_printf("While reading config.kegs, found bad bram "
"num: %s\n", buf);
return;
}
bram_num = bram_num >> 1; // turn 3->1 and 1->0
offset = (int)strtoul(&(buf[pos+2]), 0, 16);
pos += 5;
while(pos < len) {
if((buf[pos] == ' ') || (buf[pos] == '\t') ||
(buf[pos] == 0x0a) || (buf[pos] == 0x0d) ||
(buf[pos] == '=')) {
pos++;
continue;
}
val = (word32)strtoul(&buf[pos], 0, 16); // As hex
clk_bram_set(bram_num, offset, val);
offset++;
pos += 2;
}
}
void
cfg_parse_sxdx(char *buf, int pos, int len)
{
char *name_ptr, *partition_name;
word32 dynamic_blocks;
int part_num, ejected, slot, drive, c;
slot = buf[pos+1] - '0';
drive = buf[pos+3] - '0';
/* skip over slot, drive */
pos += 4;
if((buf[pos] >= '0') && (buf[pos] <= '9')) {
// Second digit of drive is valid
drive = (drive * 10) + buf[pos] - '0';
pos++;
}
drive--; // make sxd1 mean index 0
while((pos < len) && ((buf[pos] == ' ') || (buf[pos] == '\t') ||
(buf[pos] == '=')) ) {
pos++;
}
ejected = 0;
if(buf[pos] == '#') { // disk is ejected, but read info anyway
ejected = 1;
pos++;
}
partition_name = 0;
part_num = -1;
dynamic_blocks = 0;
if(buf[pos] == ':') { // yup, it's got a partition name!
pos++;
partition_name = &buf[pos];
while((pos < len) && (buf[pos] != ':')) {
pos++;
}
buf[pos] = 0; /* null terminate partition name */
pos++;
}
c = buf[pos];
if((c == ';') || (c == '@')) {
pos++;
// ; - partition number; @ - Dynamic ProDOS dir size
part_num = 0;
while((pos < len) && (buf[pos] != ':')) {
part_num = (10*part_num) + buf[pos] - '0';
pos++;
}
pos++;
if(c == '@') { // Dynamic ProDOS directory
dynamic_blocks = part_num * 2;
part_num = -1;
}
}
/* Get filename */
name_ptr = &(buf[pos]);
if((pos >= len) || (name_ptr[0] == 0)) {
return;
}
insert_disk(slot, drive, name_ptr, ejected, partition_name,
part_num, dynamic_blocks);
}
void
config_generate_config_kegs_name(char *outstr, int maxlen, Disk *dsk,
int with_extras)
{
char *str;
str = outstr;
if(with_extras) {
if(dsk->fd < 0) {
snprintf(str, maxlen - (str - outstr), "#");
str = &outstr[strlen(outstr)];
}
if(dsk->dynapro_blocks) {
snprintf(str, maxlen - (str - outstr), "@%d:",
(dsk->dynapro_blocks + 1) / 2);
str = &outstr[strlen(outstr)];
} else if(dsk->partition_name != 0) {
snprintf(str, maxlen - (str - outstr), ":%s:",
dsk->partition_name);
str = &outstr[strlen(outstr)];
} else if(dsk->partition_num >= 0) {
snprintf(str, maxlen - (str - outstr), ";%d:",
dsk->partition_num);
str = &outstr[strlen(outstr)];
}
}
snprintf(str, maxlen - (str - outstr), "%s", dsk->name_ptr);
}
char *
config_write_config_kegs_file(int get_status)
{
FILE *fconf;
Disk *dsk;
Cfg_defval *defptr;
Cfg_menu *menuptr;
char *curstr, *defstr;
int defval, curval, type, slot, drive;
int i;
if(get_status) {
return 0;
}
printf("Writing config.kegs file to %s\n", g_config_kegs_name);
fconf = fopen(g_config_kegs_name, "w+");
if(fconf == 0) {
halt_printf("cannot open %s! Stopping!\n", g_config_kegs_name);
return 0;
}
fprintf(fconf, "# KEGS configuration file version %s\n",
g_kegs_version_str);
for(i = 0; i < MAX_C7_DISKS + 4; i++) {
slot = 7;
drive = i - 4;
if(i < 4) {
slot = (i >> 1) + 5;
drive = i & 1;
}
if(drive == 0) {
fprintf(fconf, "\n"); /* an extra blank line */
}
dsk = iwm_get_dsk_from_slot_drive(slot, drive);
if(dsk->name_ptr == 0 && (i > 4)) {
/* No disk, not even ejected--just skip */
continue;
}
fprintf(fconf, "s%dd%d = ", slot, drive + 1);
if(dsk->name_ptr == 0) {
fprintf(fconf, "\n");
continue;
}
config_generate_config_kegs_name(&g_cfg_tmp_path[0],
CFG_PATH_MAX, dsk, 1);
fprintf(fconf, "%s\n", &g_cfg_tmp_path[0]);
}
fprintf(fconf, "\n");
/* See if any variables are different than their default */
for(i = 0; i < g_cfg_defval_index; i++) {
defptr = &(g_cfg_defvals[i]);
menuptr = defptr->menuptr;
defval = defptr->intval;
type = menuptr->cfgtype;
if(type == CFGTYPE_INT) {
curval = *((int *)menuptr->ptr);
if(curval != defval) {
fprintf(fconf, "%s = %d\n", menuptr->name_str,
curval);
}
}
if((type == CFGTYPE_FILE) || (type == CFGTYPE_STR)) {
curstr = *((char **)menuptr->ptr);
defstr = *((char **)menuptr->defptr);
if(strcmp(curstr, defstr) != 0) {
fprintf(fconf, "%s = %s\n", menuptr->name_str,
curstr);
}
}
}
fprintf(fconf, "\n");
/* write bram state */
clk_write_bram(fconf);
fclose(fconf);
g_config_kegs_update_needed = 0;
return 0;
}
void
insert_disk(int slot, int drive, const char *name, int ejected,
const char *partition_name, int part_num, word32 dynamic_blocks)
{
byte buf_2img[512];
Disk *dsk;
char *name_ptr, *part_ptr;
dword64 dsize, dunix_pos, exp_dsize, dtmp;
word32 len_bits, save_ftrack;
int image_type, part_len, ret, locked, len, is_po, name_len;
int i;
g_config_kegs_update_needed = 1;
if((slot < 5) || (slot > 7)) {
fatal_printf("Invalid slot for insertiing disk: %d\n", slot);
return;
}
if(drive < 0 || ((slot == 7) && (drive >= MAX_C7_DISKS)) ||
((slot < 7) && (drive > 1))) {
fatal_printf("Invalid drive for inserting disk: %d\n", drive);
return;
}
dsk = iwm_get_dsk_from_slot_drive(slot, drive);
#if 1
printf("Inserting disk %s (%s or %d) in slot %d, drive: %d, "
"dyna_blocks:%d\n", name, partition_name, part_num, slot, drive,
dynamic_blocks);
#endif
// DO NOT change dsk->just_ejected. If a disk was just ejected, then
// leave it alone. Otherwise, if we are a newly inserted disk,
// it should already be 0, so leave it alone
//dsk->just_ejected = 1;
if(dsk->fd >= 0) {
iwm_eject_disk(dsk);
}
/* Before opening, make sure no other mounted disk has this name */
/* If so, unmount it */
if(!ejected) {
for(i = 0; i < 2; i++) {
iwm_eject_named_disk(5, i, name, partition_name);
iwm_eject_named_disk(6, i, name, partition_name);
}
for(i = 0; i < MAX_C7_DISKS; i++) {
iwm_eject_named_disk(7, i, name, partition_name);
}
}
/* free old name_ptr, partition_name */
free(dsk->name_ptr);
free(dsk->partition_name);
dsk->name_ptr = 0;
dsk->partition_name = 0;
name_ptr = kegs_malloc_str(name);
dsk->name_ptr = name_ptr;
name_len = (int)strlen(dsk->name_ptr);
part_len = 0;
part_ptr = 0;
if(partition_name != 0) {
part_ptr = kegs_malloc_str(partition_name);
part_len = (int)strlen(part_ptr);
dsk->partition_name = part_ptr;
}
dsk->partition_num = part_num;
dsk->dynapro_blocks = dynamic_blocks;
iwm_printf("Opening up disk image named: %s\n", name_ptr);
if(ejected) {
/* just get out of here */
dsk->fd = -1;
return;
}
dsk->fd = -1;
dsk->raw_data = 0;
dsk->image_type = 0;
dsk->dimage_start = 0;
dsk->dimage_size = 0;
dsk->write_prot = 0;
dsk->write_through_to_unix = 1;
image_type = 0;
locked = 0;
if(dynamic_blocks) {
ret = dynapro_mount(dsk, name_ptr, dynamic_blocks);
if(ret < 0) {
iwm_eject_disk(dsk);
return;
}
image_type = DSK_TYPE_DYNAPRO;
printf("After dynapro_mount, write_through:%d\n",
dsk->write_through_to_unix);
}
if((partition_name != 0) || (part_num >= 0)) {
ret = cfg_partition_find_by_name_or_num(dsk, partition_name,
part_num);
printf("partition %s (num %d) mounted, wr_prot: %d, ret:%d\n",
partition_name, part_num, dsk->write_prot, ret);
if(ret < 0) {
iwm_eject_disk(dsk);
return;
}
locked = dsk->write_prot;
if(dsk->raw_data) {
// .zip file or something similar. Do name matching on
// partition name
name_len = part_len;
name_ptr = part_ptr;
locked = 1;
}
}
if((name_len > 3) && !image_type &&
!cfgcasecmp(".gz", &name_ptr[name_len - 3])) {
// it's gzip'ed, try to gunzip it to dsk->raw_data
undeflate_gzip(dsk, name_ptr);
locked = 1;
dsk->dimage_start = 0;
dsk->dimage_size = dsk->raw_dsize;
name_len -= 3; // So .dsk, .po look for correct chars
}
if((name_len > 4) && !image_type &&
!cfgcasecmp(".bz2", &name_ptr[name_len - 4])) {
// it's bzip2'ed, try to bunzip2 it to dsk->raw_data
config_file_to_pipe(dsk, "bunzip2", name_ptr);
locked = 1;
// Reduce name_len by 4 so that subsequent compares for .po
// look at the correct chars
name_len -= 4;
}
if((name_len > 4) && !image_type &&
!cfgcasecmp(&name_ptr[name_len - 4], ".sdk")) {
// it's a ShrinkIt archive with a disk image in it
unshk(dsk, name_ptr);
locked = 1;
image_type = DSK_TYPE_PRODOS;
printf("dsk->fd:%d dsk->raw_data:%p, raw_dsize:%lld\n", dsk->fd,
dsk->raw_data, dsk->raw_dsize);
dsk->dimage_start = 0;
dsk->dimage_size = dsk->raw_dsize;
}
if((name_len > 4) && !image_type && dsk->disk_525 &&
!cfgcasecmp(".nib", &name_ptr[name_len-4])) {
// Old, obsolete .nib 5.25" nibblized format. Support is
// read-only
image_type = DSK_TYPE_NIB;
locked = 1;
}
if((dsk->fd < 0) && !locked && !dynamic_blocks) {
dsk->fd = open(name_ptr, O_RDWR | O_BINARY, 0x1b6);
}
if((dsk->fd < 0) && !dynamic_blocks) {
printf("Trying to open %s read-only, errno: %d\n", name_ptr,
errno);
dsk->fd = open(name_ptr, O_RDONLY | O_BINARY, 0x1b6);
locked = 2;
}
iwm_printf("open returned: %d\n", dsk->fd);
if((dsk->fd < 0) && !dynamic_blocks) {
fatal_printf("Disk image %s does not exist!\n", name_ptr);
free(dsk->raw_data);
return;
}
//printf("Checking if it's woz, name_ptr:%s. %d vs %d\n", name_ptr,
// name_len, (int)strlen(name_ptr));
if((name_len > 4) && !image_type &&
!cfgcasecmp(&name_ptr[name_len - 4], ".woz")) {
// it's a WOZ applesauce disk image
image_type = DSK_TYPE_WOZ;
printf("It is woz!\n");
}
if(locked) {
dsk->write_prot = locked;
}
save_ftrack = dsk->cur_frac_track; /* save arm position */
/* See if it is in 2IMG format */
if(dsk->raw_data) {
// Just do a copy from raw_data
for(i = 0; i < 512; i++) {
buf_2img[i] = dsk->raw_data[i];
}
dsize = dsk->raw_dsize;
if(!dsk->dynapro_info_ptr) {
dsk->write_through_to_unix = 0;
}
} else {
ret = (int)read(dsk->fd, (char *)&buf_2img[0], 512);
dsize = cfg_get_fd_size(dsk->fd);
}
#if 0
/* Try to guess that there is a Mac Binary header of 128 bytes */
/* See if image size & 0xfff = 0x080 which indicates extra 128 bytes */
if(((dsize & 0xfff) == 0x080) && (dsize < (801*1024)) && !image_type) {
printf("Assuming Mac Binary header on %s\n", dsk->name_ptr);
dsk->dimage_start += 0x80;
dsize -= 0x80;
}
#endif
dsk->dimage_size = dsize;
if(!image_type && (buf_2img[0] == '2') && (buf_2img[1] == 'I') &&
(buf_2img[2] == 'M') && (buf_2img[3] == 'G')) {
/* It's a 2IMG disk */
printf("Image named %s is in 2IMG format\n", dsk->name_ptr);
image_type = DSK_TYPE_PRODOS;
if(buf_2img[12] == 0) {
printf("2IMG is in DOS 3.3 sector order\n");
image_type = DSK_TYPE_DOS33;
}
if(buf_2img[19] & 0x80) {
/* disk is locked */
printf("2IMG is write protected\n");
if(dsk->write_prot == 0) {
dsk->write_prot = 1;
}
}
if((buf_2img[17] & 1) && (dsk->image_type == DSK_TYPE_DOS33)) {
dsk->vol_num = buf_2img[16];
printf("Setting DOS 3.3 vol num to %d\n", dsk->vol_num);
}
// Some 2IMG archives have the size byte reversed
dsize = (buf_2img[31] << 24) + (buf_2img[30] << 16) +
(buf_2img[29] << 8) + buf_2img[28];
dunix_pos = (buf_2img[27] << 24) + (buf_2img[26] << 16) +
(buf_2img[25] << 8) + buf_2img[24];
if(dsize == 0x800c00) {
// Byte reversed 0x0c8000
dsize = 0x0c8000;
}
if(dsize == 0) {
/* Sweet-16 makes some images with size == 0 */
/* Example: Prosel from */
/* www.whatisthe2gs.apple2.org.za/the_ring/ */
if(buf_2img[12] == 1) {
/* then get the size from 0x14 in blocks */
dsize = (buf_2img[23] << 24) +
(buf_2img[22] << 16) +
(buf_2img[21] << 8) + buf_2img[20];
dsize = dsize * 512; /* it was blocks */
}
}
dsk->dimage_start = dunix_pos;
dsk->dimage_size = dsize;
}
exp_dsize = 800*1024;
dsk->fbit_mult = 256;
if(dsk->disk_525) {
exp_dsize = 140*1024;
dsk->fbit_mult = 128;
}
if(!image_type) {
/* See if it might be the Mac diskcopy format */
dtmp = cfg_detect_dc42(&buf_2img[0], dsize, exp_dsize, slot);
if(dtmp != 0) {
// It's diskcopy 4.2
printf("Image named %s is in Mac diskcopy format\n",
dsk->name_ptr);
dsk->dimage_start += 0x54;
dsk->dimage_size = dtmp;
image_type = DSK_TYPE_PRODOS; /* ProDOS */
}
}
if(!image_type) {
/* Assume raw image */
dsk->dimage_size = dsize;
image_type = DSK_TYPE_PRODOS;
is_po = (name_len > 3) &&
!cfgcasecmp(".po", &name_ptr[name_len-3]);
if(dsk->disk_525) {
image_type = DSK_TYPE_DOS33;
if(is_po) {
image_type = DSK_TYPE_PRODOS;
}
}
}
dsk->image_type = image_type;
dsk->disk_dirty = 0;
dsk->cur_fbit_pos = 0;
dsk
gitextract_v8qf17it/
├── .gitignore
├── CLAUDE.md
├── LICENSE
├── README.md
├── TODO.md
├── gsplus/
│ ├── lib/
│ │ ├── 2mg.icns
│ │ ├── 525.icns
│ │ ├── MainMenu.nib
│ │ ├── kegsicon.icns
│ │ └── make_mac_icon
│ └── src/
│ ├── AppDelegate.swift
│ ├── Info.plist
│ ├── Kegs-Bridging-Header.h
│ ├── MainView.swift
│ ├── Makefile
│ ├── adb.c
│ ├── applesingle.c
│ ├── clock.c
│ ├── comp_swift
│ ├── compile_time.c
│ ├── config.c
│ ├── config.h
│ ├── cp_gsplus_libs
│ ├── debugger.c
│ ├── defc.h
│ ├── defcomm.h
│ ├── defs_instr.h
│ ├── dependency
│ ├── disas.h
│ ├── doc.c
│ ├── dyna_filt.c
│ ├── dyna_type.c
│ ├── dyna_validate.c
│ ├── dynapro.c
│ ├── engine.h
│ ├── engine_c.c
│ ├── instable.h
│ ├── iwm.c
│ ├── iwm.h
│ ├── joystick_driver.c
│ ├── kegs.icns
│ ├── kegsfont.h
│ ├── kegswin.sln
│ ├── kegswin.vcxproj
│ ├── ldvars
│ ├── macsnd_driver.c
│ ├── mockingboard.c
│ ├── moremem.c
│ ├── op_routs.h
│ ├── paddles.c
│ ├── protos.h
│ ├── protos_base.h
│ ├── protos_macdriver.h
│ ├── protos_macsnd_driver.h
│ ├── protos_pulseaudio_driver.h
│ ├── protos_windriver.h
│ ├── protos_xdriver.h
│ ├── pulseaudio_driver.c
│ ├── scc.c
│ ├── scc.h
│ ├── scc_socket_driver.c
│ ├── scc_unixdriver.c
│ ├── scc_windriver.c
│ ├── sim65816.c
│ ├── size_c.h
│ ├── smartport.c
│ ├── sound.c
│ ├── sound.h
│ ├── sound_driver.c
│ ├── style_check
│ ├── undeflate.c
│ ├── unshk.c
│ ├── vars
│ ├── vars_mac
│ ├── vars_mac_x
│ ├── vars_x86linux
│ ├── video.c
│ ├── voc.c
│ ├── win32snd_driver.c
│ ├── win_dirent.h
│ ├── windriver.c
│ ├── woz.c
│ └── xdriver.c
└── upstream/
├── KEGS.version
└── kegs/
├── config.kegs
├── doc/
│ ├── CHANGES.txt
│ ├── COPYING.txt
│ ├── INTERNALS.iwm.txt
│ ├── INTERNALS.overview.txt
│ ├── INTERNALS.video.txt
│ ├── INTERNALS.xdriver.txt
│ ├── README.ROM.files.txt
│ ├── README.a2.compatibility.txt
│ ├── README.compile.txt
│ ├── README.dynapro.txt
│ ├── README.kegs.txt
│ ├── README.linux.partitions.txt
│ ├── README.mac.txt
│ ├── README.serial.ports.txt
│ └── README.win32.txt
├── lib/
│ ├── 2mg.icns
│ ├── 525.icns
│ ├── MainMenu.nib
│ ├── kegsicon.icns
│ └── make_mac_icon
├── src/
│ ├── AppDelegate.swift
│ ├── Info.plist
│ ├── Kegs-Bridging-Header.h
│ ├── MainView.swift
│ ├── Makefile
│ ├── adb.c
│ ├── applesingle.c
│ ├── clock.c
│ ├── comp_swift
│ ├── compile_time.c
│ ├── config.c
│ ├── config.h
│ ├── cp_kegs_libs
│ ├── debugger.c
│ ├── defc.h
│ ├── defcomm.h
│ ├── defs_instr.h
│ ├── dependency
│ ├── disas.h
│ ├── doc.c
│ ├── dyna_filt.c
│ ├── dyna_type.c
│ ├── dyna_validate.c
│ ├── dynapro.c
│ ├── engine.h
│ ├── engine_c.c
│ ├── instable.h
│ ├── iwm.c
│ ├── iwm.h
│ ├── joystick_driver.c
│ ├── kegsfont.h
│ ├── kegswin.sln
│ ├── kegswin.vcxproj
│ ├── ldvars
│ ├── macsnd_driver.c
│ ├── mockingboard.c
│ ├── moremem.c
│ ├── op_routs.h
│ ├── paddles.c
│ ├── protos.h
│ ├── protos_base.h
│ ├── protos_macdriver.h
│ ├── protos_macsnd_driver.h
│ ├── protos_pulseaudio_driver.h
│ ├── protos_windriver.h
│ ├── protos_xdriver.h
│ ├── pulseaudio_driver.c
│ ├── scc.c
│ ├── scc.h
│ ├── scc_socket_driver.c
│ ├── scc_unixdriver.c
│ ├── scc_windriver.c
│ ├── sim65816.c
│ ├── size_c.h
│ ├── smartport.c
│ ├── sound.c
│ ├── sound.h
│ ├── sound_driver.c
│ ├── style_check
│ ├── undeflate.c
│ ├── unshk.c
│ ├── vars
│ ├── vars_mac
│ ├── vars_mac_x
│ ├── vars_x86linux
│ ├── video.c
│ ├── voc.c
│ ├── win32snd_driver.c
│ ├── win_dirent.h
│ ├── windriver.c
│ ├── woz.c
│ └── xdriver.c
└── xkegs
SYMBOL INDEX (1754 symbols across 84 files)
FILE: gsplus/src/adb.c
function STRUCT (line 99) | STRUCT(Mouse_fifo) {
function adb_get_hide_warp_info (line 311) | int
function adb_get_copy_requested (line 322) | int
function adb_nonmain_check (line 332) | void
function adb_init (line 340) | void
function adb_reset (line 372) | void
function STRUCT (line 403) | STRUCT(Adb_log) {
function adb_log (line 412) | void
function show_adb_log (line 428) | void
function adb_error (line 452) | void
function adb_add_kbd_srq (line 462) | void
function adb_clear_kbd_srq (line 474) | void
function adb_add_data_int (line 483) | void
function adb_add_mouse_int (line 491) | void
function adb_clear_data_int (line 499) | void
function adb_clear_mouse_int (line 505) | void
function adb_send_bytes (line 512) | void
function adb_send_1byte (line 543) | void
function adb_response_packet (line 554) | void
function adb_kbd_reg0_data (line 581) | void
function adb_kbd_talk_reg0 (line 600) | void
function adb_set_config (line 648) | void
function adb_set_new_mode (line 727) | void
function adb_read_c026 (line 743) | int
function adb_write_c026 (line 799) | void
function do_adb_cmd (line 997) | void
function adb_read_c027 (line 1129) | int
function adb_write_c027 (line 1171) | void
function read_adb_ram (line 1205) | int
function write_adb_ram (line 1245) | void
function adb_get_keypad_xy (line 1259) | int
function adb_update_mouse (line 1299) | int
function mouse_read_c024 (line 1434) | int
function mouse_compress_fifo (line 1585) | void
function adb_paste_update_state (line 1610) | void
function adb_paste_add_buf (line 1629) | int
function adb_key_event (line 1667) | void
function word32 (line 1772) | word32
function word32 (line 1802) | word32
function word32 (line 1829) | word32
function adb_is_cmd_key_down (line 1835) | int
function adb_is_option_key_down (line 1841) | int
function adb_increment_speed (line 1847) | void
function adb_update_c025_mask (line 1875) | void
function adb_ascii_to_a2code (line 1889) | int
function adb_physical_key_update (line 1971) | void
function adb_maybe_virtual_key_update (line 2161) | void
function adb_virtual_key_update (line 2198) | void
function adb_all_keys_up (line 2232) | void
function adb_kbd_repeat_off (line 2250) | void
function adb_mainwin_focus (line 2256) | void
FILE: gsplus/src/applesingle.c
function word32 (line 19) | word32
function word32 (line 25) | word32
function applesingle_set_be32 (line 31) | void
function applesingle_set_be16 (line 40) | void
function word32 (line 47) | word32
function word32 (line 211) | word32
function word32 (line 333) | word32
FILE: gsplus/src/clock.c
function get_dtime (line 44) | double
function micro_sleep (line 87) | int
function clk_bram_zero (line 121) | void
function clk_bram_set (line 135) | void
function clk_setup_bram_version (line 149) | void
function clk_write_bram (line 159) | void
function update_cur_time (line 176) | void
function clock_update (line 218) | void
function clock_update_if_needed (line 224) | void
function clock_write_c034 (line 236) | void
function do_clock_data (line 250) | void
FILE: gsplus/src/config.c
function config_add_argv_override (line 512) | int
function config_set_config_kegs_name (line 547) | void
function config_init_menus (line 558) | void
function config_init (line 621) | void
function cfg_find_config_kegs_file (line 634) | void
function config_setup_kegs_file (line 670) | int
function config_expand_path (line 709) | int
function cfg_err_vprintf (line 789) | void
function cfg_err_printf (line 816) | void
function cfg_toggle_config_panel (line 826) | void
function cfg_set_config_panel (line 840) | void
function config_vbl_update (line 963) | void
function cfg_file_update_rom (line 974) | void
function cfg_file_update_ptr (line 980) | void
function cfg_int_update (line 1027) | void
function cfg_load_charrom (line 1065) | void
function config_load_roms (line 1091) | void
function config_parse_config_kegs_file (line 1309) | void
function cfg_parse_one_line (line 1397) | void
function cfg_parse_bram (line 1511) | void
function cfg_parse_sxdx (line 1549) | void
function config_generate_config_kegs_name (line 1618) | void
function insert_disk (line 1735) | void
function dword64 (line 2105) | dword64
function dword64 (line 2150) | dword64
function dword64 (line 2166) | dword64
function dword64 (line 2201) | dword64
function cfg_partition_maybe_add_dotdot (line 2214) | int
function cfg_partition_name_check (line 2227) | int
function cfg_partition_read_block (line 2247) | int
function cfg_partition_find_by_name_or_num (line 2257) | int
function cfg_partition_make_list_from_name (line 2344) | int
function cfg_partition_make_list (line 2360) | int
function cfg_maybe_insert_disk (line 2453) | int
function cfg_insert_disk_dynapro (line 2472) | void
function cfg_stat (line 2490) | int
function word32 (line 2521) | word32
function word32 (line 2527) | word32
function dword64 (line 2533) | dword64
function word32 (line 2546) | word32
function word32 (line 2555) | word32
function cfg_set_le32 (line 2564) | void
function config_file_to_pipe (line 2573) | void
function cfg_htab_vtab (line 2659) | void
function cfg_home (line 2674) | void
function cfg_cleol (line 2685) | void
function cfg_putchar (line 2696) | void
function cfg_printf (line 2743) | void
function cfg_print_dnum (line 2763) | void
function cfg_get_disk_name (line 2795) | int
function cfg_get_disk_locked (line 2814) | int
function cfg_parse_menu (line 2836) | void
function cfg_get_base_path (line 3095) | void
function cfg_dup_existing_image (line 3204) | void
function cfg_dup_image_selected (line 3213) | void
function cfg_validate_image (line 3292) | void
function cfg_toggle_lock_disk (line 3302) | void
function cfg_create_new_image_act (line 3312) | int
function cfg_create_new_image (line 3352) | void
function cfg_file_init (line 3387) | void
function cfg_free_alldirents (line 3430) | void
function cfg_file_add_dirent_unique (line 3452) | void
function cfg_file_add_dirent (line 3478) | void
function cfg_dirent_sortfn (line 3514) | int
function cfg_str_match (line 3527) | int
function cfg_str_match_maybecase (line 3533) | int
function cfgcasecmp (line 3560) | int
function cfg_strlcat (line 3566) | int
function cfg_file_readdir (line 3669) | void
function cfg_fix_topent (line 3851) | void
function cfg_file_draw (line 3876) | void
function cfg_partition_select_all (line 4011) | void
function cfg_partition_selected (line 4047) | void
function cfg_file_selected (line 4095) | void
function cfg_file_handle_key (line 4184) | void
function cfg_draw_menu (line 4286) | void
function cfg_newdisk_pick_menu (line 4394) | void
function cfg_control_panel_update (line 4418) | int
function cfg_edit_mode_key (line 4435) | void
function cfg_control_panel_update1 (line 4470) | int
FILE: gsplus/src/config.h
function STRUCT (line 32) | STRUCT(Cfg_defval) {
FILE: gsplus/src/debugger.c
function STRUCT (line 22) | STRUCT(Debug_entry) {
function debugger_init (line 101) | void
function check_breakpoints (line 117) | void
function debug_hit_bp (line 142) | void
function debugger_run_16ms (line 195) | int
function dbg_log_info (line 209) | void
function debugger_update_list_kpc (line 226) | void
function debugger_key_event (line 232) | void
function debugger_page_updown (line 312) | void
function debugger_redraw_screen (line 338) | void
function debug_draw_debug_line (line 402) | void
function debugger_help (line 454) | void
function dbg_help_show_strs (line 510) | void
function do_debug_cmd (line 614) | void
function word32 (line 869) | word32
function show_one_toolset (line 881) | void
function show_toolset_tables (line 902) | void
function word32 (line 934) | word32
function debug_help (line 1013) | void
function debug_bp (line 1020) | void
function debug_bp_set (line 1028) | void
function debug_bp_clear (line 1034) | void
function debug_bp_clear_all (line 1040) | void
function debug_bp_setclr (line 1053) | void
function debug_soundfile (line 1087) | void
function debug_logpc (line 1097) | void
function debug_logpc_on (line 1107) | void
function debug_logpc_off (line 1118) | void
function debug_logpc_out_data (line 1129) | void
function Data_log (line 1179) | Data_log *
function debug_logpc_save (line 1204) | void
function set_bp (line 1324) | void
function show_bp (line 1344) | void
function delete_bp (line 1379) | void
function debug_iwm (line 1411) | void
function debug_iwm_check (line 1420) | void
function do_blank (line 1429) | int
function do_go (line 1477) | void
function do_step (line 1486) | void
function xam_mem (line 1507) | void
function show_hex_mem (line 1514) | void
function do_debug_list (line 1553) | void
function dis_do_memmove (line 1578) | void
function dis_do_pattern_search (line 1595) | void
function dis_do_compare (line 1634) | void
function do_debug_load (line 1735) | void
function debug_get_view_line (line 1995) | int
function debug_add_output_line (line 2013) | int
function debug_add_output_string (line 2073) | void
function debug_add_output_chars (line 2093) | void
function dbg_printf (line 2127) | int
function dbg_vprintf (line 2139) | int
function halt_printf (line 2149) | void
function halt2_printf (line 2161) | void
FILE: gsplus/src/defc.h
type byte (line 18) | typedef unsigned char byte;
type word16 (line 19) | typedef unsigned short word16;
type word32 (line 20) | typedef unsigned int word32;
type dword64 (line 22) | typedef unsigned __int64 dword64;
type dword64 (line 24) | typedef unsigned long long dword64;
type stat (line 79) | struct stat
function STRUCT (line 94) | STRUCT(Pc_log) {
function STRUCT (line 104) | STRUCT(Data_log) {
function STRUCT (line 112) | STRUCT(Event) {
function STRUCT (line 118) | STRUCT(Fplus) {
function STRUCT (line 123) | STRUCT(Engine_reg) {
function STRUCT (line 139) | STRUCT(Break_point) {
function STRUCT (line 145) | STRUCT(Change_rect) {
function STRUCT (line 153) | STRUCT(Kimage) {
type byte (line 179) | typedef byte *Pg_info;
function STRUCT (line 180) | STRUCT(Page_info) {
function STRUCT (line 184) | STRUCT(Cfg_menu) {
function STRUCT (line 192) | STRUCT(Cfg_dirent) {
function STRUCT (line 201) | STRUCT(Cfg_listhdr) {
function STRUCT (line 215) | STRUCT(Dbg_longcmd) {
function STRUCT (line 222) | STRUCT(Emustate_intlist) {
function STRUCT (line 227) | STRUCT(Emustate_dword64list) {
function STRUCT (line 232) | STRUCT(Emustate_word32list) {
function STRUCT (line 237) | STRUCT(Lzw_state) {
FILE: gsplus/src/doc.c
function doc_init (line 67) | void
function doc_reset (line 96) | void
function doc_play (line 119) | int
function doc_handle_event (line 244) | void
function doc_sound_end (line 256) | void
function doc_add_sound_irq (line 338) | void
function doc_remove_sound_irq (line 360) | void
function doc_start_sound2 (line 430) | void
function doc_start_sound (line 439) | void
function doc_wave_end_estimate2 (line 506) | void
function doc_wave_end_estimate (line 515) | void
function doc_remove_sound_event (line 581) | void
function doc_write_ctl_reg (line 591) | void
function doc_recalc_sound_parms (line 680) | void
function doc_read_c03c (line 714) | int
function doc_read_c03d (line 720) | int
function doc_write_c03c (line 812) | void
function doc_write_c03d (line 829) | void
function doc_show_ensoniq_state (line 994) | void
FILE: gsplus/src/dyna_type.c
function STRUCT (line 16) | STRUCT(Dynatype_extensions) {
function STRUCT (line 37) | STRUCT(Dynatype_types) {
function word32 (line 57) | word32
function word32 (line 76) | word32
function word32 (line 110) | word32
function dynatype_get_extension (line 187) | int
function dynatype_comma_arg (line 211) | int
function dynatype_fix_unix_name (line 268) | void
FILE: gsplus/src/dyna_validate.c
function word32 (line 16) | word32
function dynapro_validate_init_freeblks (line 72) | void
function word32 (line 96) | word32
function word32 (line 118) | word32
function word32 (line 186) | word32
function word32 (line 254) | word32
function dynapro_validate_disk (line 390) | int
function dynapro_validate_any_image (line 425) | void
FILE: gsplus/src/dynapro.c
function word32 (line 100) | word32
function word32 (line 106) | word32
function word32 (line 112) | word32
function dynapro_set_word24 (line 118) | void
function dynapro_set_word32 (line 127) | void
function dynapro_set_word16 (line 137) | void
function dynapro_error (line 145) | void
function Dynapro_file (line 160) | Dynapro_file *
function dynapro_free_file (line 169) | void
function dynapro_free_recursive_file (line 193) | void
function dynapro_free_dynapro_info (line 209) | void
function word32 (line 225) | word32
function word32 (line 254) | word32
function byte (line 275) | byte *
function dynapro_join_path_and_file (line 311) | void
function word32 (line 327) | word32
function word32 (line 424) | word32
function word32 (line 519) | word32
function dynapro_fix_damaged_entry (line 539) | void
function dynapro_try_fix_damage (line 555) | void
function dynapro_try_fix_damaged_disk (line 573) | void
function dynapro_new_unix_path (line 599) | void
function Dynapro_file (line 613) | Dynapro_file *
function dynapro_handle_write_dir (line 831) | void
function word32 (line 876) | word32
function dynapro_handle_write_file (line 906) | void
function dynapro_handle_changed_entry (line 917) | void
function word32 (line 943) | word32
function dynapro_unmap_file (line 967) | void
function dynapro_unlink_file (line 1015) | void
function dynapro_erase_free_entry (line 1057) | void
function dynapro_erase_free_dir (line 1074) | void
function dynapro_mark_damaged (line 1103) | void
function dynapro_write (line 1127) | int
function dynapro_debug_update (line 1196) | void
function dynapro_debug_map (line 1209) | void
function dynapro_debug_recursive_file_map (line 1241) | void
function word32 (line 1269) | word32
function dynapro_create_prodos_name (line 1294) | int
function Dynapro_file (line 1490) | Dynapro_file *
function dynapro_create_dir (line 1558) | int
function word32 (line 1703) | word32
function word32 (line 1839) | word32
function word32 (line 1936) | word32
function word32 (line 1986) | word32
function word32 (line 2044) | word32
function word32 (line 2107) | word32
function word32 (line 2151) | word32
function word32 (line 2197) | word32
function word32 (line 2233) | word32
function dynapro_mount (line 2263) | int
FILE: gsplus/src/engine.h
function ENGINE_TYPE (line 13) | int
FILE: gsplus/src/engine_c.c
function word32 (line 328) | word32
function word32 (line 351) | word32
function word32 (line 375) | word32
function set_memory8_io_stub (line 404) | void
function set_memory16_pieces_stub (line 462) | void
function set_memory24_pieces_stub (line 482) | void
function word32 (line 510) | word32
function word32 (line 527) | word32
function word32 (line 534) | word32
function set_memory_c (line 542) | void
function set_memory16_c (line 558) | void
function set_memory24_c (line 574) | void
function word32 (line 582) | word32
function word32 (line 635) | word32
function fixed_memory_ptrs_init (line 682) | void
function word32 (line 705) | word32
function engine_recalc_events (line 749) | void
function set_halt_act (line 756) | void
function clr_halt_act (line 773) | void
function word32 (line 779) | word32
function enter_engine (line 930) | int
FILE: gsplus/src/iwm.c
function iwm_init_drive (line 105) | void
function iwm_init (line 159) | void
function iwm_reset (line 190) | void
function disk_set_num_tracks (line 212) | void
function word32 (line 222) | word32
function draw_iwm_status (line 237) | void
function iwm_flush_cur_disk (line 267) | void
function iwm_flush_disk_to_unix (line 276) | void
function iwm_vbl_update (line 317) | void
function iwm_update_fast_disk_emul (line 347) | void
function iwm_show_stats (line 355) | void
function Disk (line 391) | Disk *
function Disk (line 407) | Disk *
function iwm_move_to_ftrack (line 629) | void
function iwm_move_to_qtr_track (line 722) | void
function iwm525_update_phases (line 743) | void
function iwm525_update_head (line 777) | void
function iwm_read_status35 (line 907) | int
function iwm_do_action35 (line 1015) | void
function read_iwm (line 1089) | int
function write_iwm (line 1171) | void
function iwm_read_enable2 (line 1245) | int
function iwm_read_enable2_handshake (line 1254) | int
function iwm_write_enable2 (line 1271) | void
function word32 (line 1280) | word32
function word32 (line 1334) | word32
function dword64 (line 1403) | dword64
function dword64 (line 1418) | dword64
function word32 (line 1476) | word32
function word32 (line 1488) | word32
function dword64 (line 1504) | dword64
function iwm_calc_forced_sync_0s (line 1534) | int
function word32 (line 1573) | word32
function iwm_write_data (line 1737) | void
function iwm_start_write (line 1805) | void
function iwm_start_write_act (line 1822) | int
function iwm_write_data35 (line 1899) | void
function iwm_write_end (line 1908) | void
function iwm_write_one_nib (line 1981) | void
function iwm_recalc_sync_from (line 2012) | void
function sector_to_partial_nib (line 2126) | void
function disk_unnib_4x4 (line 2163) | int
function iwm_denib_track525 (line 2175) | int
function iwm_denib_track35 (line 2404) | int
function iwm_track_to_unix (line 2721) | int
function show_hex_data (line 2799) | void
function iwm_check_nibblization (line 2814) | void
function disk_check_nibblization (line 2837) | void
function disk_unix_to_nib (line 2901) | void
function iwm_nibblize_track_nib525 (line 3009) | void
function iwm_nibblize_track_525 (line 3038) | void
function iwm_nibblize_track_35 (line 3118) | void
function disk_4x4_nib_out (line 3339) | void
function disk_nib_out (line 3346) | void
function disk_nib_end_track (line 3357) | void
function word32 (line 3368) | word32
function Disk (line 3459) | Disk *
function iwm_toggle_lock (line 3485) | void
function iwm_eject_named_disk (line 3508) | void
function iwm_eject_disk_by_num (line 3534) | void
function iwm_eject_disk (line 3544) | void
function iwm_show_track (line 3625) | void
function iwm_show_a_track (line 3674) | void
function dummy1 (line 3742) | void
function dummy2 (line 3748) | void
FILE: gsplus/src/iwm.h
function STRUCT (line 63) | STRUCT(Trk) {
function STRUCT (line 72) | STRUCT(Woz_info) {
type Dynapro_map (line 86) | typedef struct Dynapro_map_st Dynapro_map;
function STRUCT (line 88) | STRUCT(Dynapro_file) {
type Dynapro_map_st (line 110) | struct Dynapro_map_st {
function STRUCT (line 116) | STRUCT(Dynapro_info) {
function STRUCT (line 123) | STRUCT(Disk) {
function STRUCT (line 157) | STRUCT(Iwm) {
function STRUCT (line 175) | STRUCT(Driver_desc) {
function STRUCT (line 185) | STRUCT(Part_map) {
FILE: gsplus/src/joystick_driver.c
function joystick_init (line 42) | void
function joystick_update (line 80) | void
function joystick_update_buttons (line 118) | void
function joystick_init (line 129) | void
function joystick_update (line 172) | void
function joystick_update_buttons (line 203) | void
function hid_device_callback (line 247) | void
function hid_get_int_property (line 307) | int
function joystick_init (line 325) | void
function joystick_update (line 388) | void
function joystick_update_buttons (line 408) | void
function joystick_init (line 419) | void
function joystick_update (line 427) | void
function joystick_update_buttons (line 447) | void
function joystick_callback_init (line 456) | void
function joystick_callback_update (line 462) | void
FILE: gsplus/src/macsnd_driver.c
function OSStatus (line 54) | static OSStatus
function mac_send_audio (line 143) | int
function macsnd_init (line 169) | void
FILE: gsplus/src/mockingboard.c
function mock_ay8913_reset (line 28) | void
function mockingboard_reset (line 51) | void
function mock_show_pair (line 80) | void
function mock_update_timers (line 104) | void
function mockingboard_event (line 269) | void
function word32 (line 280) | word32
function mockingboard_write (line 290) | void
function word32 (line 300) | word32
function mock_6522_write (line 379) | void
function word32 (line 513) | word32
function mock_ay8913_reg_read (line 540) | void
function mock_ay8913_reg_write (line 566) | void
function mock_ay8913_control_update (line 616) | void
function mockingboard_show (line 648) | void
FILE: gsplus/src/moremem.c
function fixup_brks (line 144) | void
function fixup_hires_on (line 173) | void
function fixup_bank0_2000_4000 (line 184) | void
function fixup_bank0_0400_0800 (line 232) | void
function fixup_any_bank_any_page (line 272) | void
function fixup_intcx (line 290) | void
function fixup_st80col (line 363) | void
function fixup_altzp (line 385) | void
function fixup_page2 (line 409) | void
function fixup_ramrd (line 422) | void
function fixup_ramwrt (line 466) | void
function fixup_lc (line 550) | void
function set_statereg (line 601) | void
function fixup_shadow_txt1 (line 647) | void
function fixup_shadow_txt2 (line 664) | void
function fixup_shadow_hires1 (line 697) | void
function fixup_shadow_hires2 (line 715) | void
function fixup_shadow_shr (line 746) | void
function fixup_shadow_iolc (line 774) | void
function update_shadow_reg (line 803) | void
function fixup_shadow_all_banks (line 848) | void
function setup_pageinfo (line 875) | void
function show_bankptrs_bank0rdwr (line 930) | void
function show_bankptrs (line 940) | void
function show_addr (line 965) | void
function word32 (line 988) | word32
function word32 (line 1000) | word32
function io_write (line 1459) | void
function word32 (line 2115) | word32
function slinky_devsel_write (line 2133) | void
function word32 (line 2151) | word32
function word32 (line 2176) | word32
function in_vblank (line 2220) | int
function read_vid_counters (line 2242) | int
FILE: gsplus/src/paddles.c
function paddle_fixup_joystick_type (line 38) | void
function paddle_trigger (line 56) | void
function paddle_trigger_mouse (line 77) | void
function paddle_trigger_keypad (line 103) | void
function paddle_update_trigger_dcycs (line 120) | void
function read_paddles (line 168) | int
function paddle_update_buttons (line 182) | void
FILE: gsplus/src/protos_base.h
type stat (line 186) | struct stat
FILE: gsplus/src/protos_windriver.h
type dirent (line 38) | struct dirent
type stat (line 40) | struct stat
FILE: gsplus/src/pulseaudio_driver.c
function pulse_audio_send_audio (line 50) | int
function pulse_audio_main_events (line 76) | void
function pulse_audio_write_to_stream (line 125) | void
function pulse_audio_start_stream (line 215) | int
function pulse_audio_do_init (line 255) | int
function pulse_audio_init (line 324) | int
function pulse_audio_shutdown (line 358) | void
FILE: gsplus/src/scc.c
function scc_init (line 58) | void
function scc_reset (line 105) | void
function scc_hard_reset_port (line 135) | void
function scc_reset_port (line 164) | void
function scc_regen_clocks (line 195) | void
function scc_port_close (line 343) | void
function scc_port_open (line 360) | void
function scc_is_port_closed (line 380) | int
function scc_config_changed (line 441) | void
function scc_update (line 471) | void
function scc_try_to_empty_writebuf (line 490) | void
function scc_try_fill_readbuf (line 518) | void
function scc_do_event (line 560) | void
function show_scc_state (line 589) | void
function word32 (line 643) | word32
function scc_write_reg (line 734) | void
function word32 (line 961) | word32
function scc_write_data (line 994) | void
function word32 (line 1014) | word32
function scc_maybe_br_event (line 1046) | void
function scc_evaluate_ints (line 1083) | void
function scc_maybe_rx_event (line 1132) | void
function scc_maybe_rx_int (line 1169) | void
function scc_clr_rx_int (line 1191) | void
function scc_handle_tx_event (line 1198) | void
function scc_maybe_tx_event (line 1214) | void
function scc_clr_tx_int (line 1236) | void
function scc_set_zerocnt_int (line 1243) | void
function scc_clr_zerocnt_int (line 1256) | void
function scc_add_to_readbuf (line 1263) | void
function scc_add_to_readbufv (line 1299) | void
function scc_transmit (line 1322) | void
function scc_add_to_writebuf (line 1359) | void
FILE: gsplus/src/scc.h
function STRUCT (line 44) | STRUCT(Scc) {
FILE: gsplus/src/scc_socket_driver.c
type socklen_t (line 33) | typedef int socklen_t;
function scc_socket_open (line 54) | void
function scc_socket_close (line 103) | void
function scc_socket_close_extended (line 152) | void
function scc_socket_maybe_open (line 171) | void
function scc_socket_open_incoming (line 198) | void
function scc_socket_open_outgoing (line 293) | void
function scc_socket_make_nonblock (line 378) | void
function scc_accept_socket (line 417) | void
function scc_socket_telnet_reqs (line 488) | void
function scc_socket_fill_readbuf (line 516) | void
function scc_socket_recvd_char (line 561) | void
function scc_socket_empty_writebuf (line 734) | void
function scc_socket_modem_write (line 867) | void
function scc_socket_do_cmd_str (line 932) | void
function scc_socket_send_modem_code (line 1130) | void
function scc_socket_modem_connect (line 1171) | void
function scc_socket_modem_do_ring (line 1181) | void
function scc_socket_do_answer (line 1213) | void
FILE: gsplus/src/scc_unixdriver.c
function scc_serial_unix_open (line 25) | void
function scc_serial_unix_close (line 49) | void
function scc_serial_unix_change_params (line 64) | void
function scc_serial_unix_fill_readbuf (line 137) | void
function scc_serial_unix_empty_writebuf (line 176) | void
FILE: gsplus/src/scc_windriver.c
function scc_serial_win_open (line 21) | void
function scc_serial_win_close (line 63) | void
function scc_serial_win_change_params (line 80) | void
function scc_serial_win_fill_readbuf (line 162) | void
function scc_serial_win_empty_writebuf (line 194) | void
FILE: gsplus/src/sim65816.c
function sim_get_force_depth (line 153) | int
function sim_get_use_shmem (line 159) | int
function sim_set_use_shmem (line 165) | void
function word32 (line 176) | word32
function toolbox_debug_c (line 194) | void
function show_toolbox_log (line 220) | void
function word32 (line 246) | word32
function set_memory_io (line 300) | void
function show_regs_act (line 346) | void
function show_regs (line 368) | void
function my_exit (line 374) | void
function do_reset (line 382) | void
function byte (line 431) | byte *
function memory_ptr_init (line 455) | void
function parse_argv (line 484) | int
function kegs_init (line 650) | int
function load_roms_init_memory (line 695) | void
function initialize_events (line 720) | void
function check_for_one_event_type (line 737) | void
function add_event_entry (line 761) | void
function dword64 (line 820) | dword64
function add_event_stop (line 853) | void
function add_event_doc (line 859) | void
function add_event_scc (line 871) | void
function add_event_vbl (line 881) | void
function add_event_vid_upd (line 890) | void
function add_event_mockingboard (line 900) | void
function add_event_scan_int (line 911) | void
function dword64 (line 937) | dword64
function dword64 (line 943) | dword64
function remove_event_mockingboard (line 949) | void
function show_all_events (line 955) | void
function show_pmhz (line 1004) | void
function setup_zip_speeds (line 1012) | void
function run_16ms (line 1043) | int
function run_a2_one_vbl (line 1094) | int
function add_irq (line 1281) | void
function remove_irq (line 1292) | void
function take_irq (line 1298) | void
function show_dtime_array (line 1361) | void
function update_60hz (line 1390) | void
function do_vbl_int (line 1687) | void
function do_scan_int (line 1698) | void
function check_scan_line_int (line 1749) | void
function check_for_new_scan_int (line 1792) | void
function scb_changed (line 1801) | void
function init_reg (line 1811) | void
function handle_action (line 1825) | void
function do_break (line 1859) | void
function do_cop (line 1868) | void
function do_wdm (line 1875) | void
function do_wai (line 1917) | void
function do_stp (line 1923) | void
function do_wdm_emulator_id (line 1935) | void
function size_fail (line 1997) | void
function fatal_printf (line 2003) | int
function kegs_vprintf (line 2020) | int
function dword64 (line 2044) | dword64
function clear_fatal_logs (line 2069) | void
function dword64 (line 2094) | dword64
FILE: gsplus/src/smartport.c
function STRUCT (line 25) | STRUCT(Smpt_log) {
function smartport_error (line 39) | void
function smartport_log (line 65) | void
function do_c70d (line 97) | void
function do_c70a (line 449) | void
function do_read_c7 (line 519) | int
function do_write_c7 (line 599) | int
function smartport_memory_write (line 681) | int
function do_format_c7 (line 700) | int
function do_c700 (line 782) | void
FILE: gsplus/src/sound.c
function sound_init (line 164) | void
function sound_set_audio_rate (line 171) | void
function sound_reset (line 185) | void
function sound_shutdown (line 192) | void
function sound_update (line 198) | void
function sound_file_start (line 209) | void
function sound_file_open (line 220) | void
function sound_file_close (line 252) | void
function send_sound_to_file (line 272) | void
function show_c030_state (line 314) | void
function show_c030_samps (line 320) | void
function sound_play_c030 (line 348) | int
function sound_play (line 548) | void
function sound_mock_envelope (line 755) | void
function sound_mock_noise (line 833) | void
function sound_mock_play (line 890) | void
function word32 (line 978) | word32
function sound_write_c030 (line 985) | void
FILE: gsplus/src/sound.h
function STRUCT (line 25) | STRUCT(Doc_reg) {
function STRUCT (line 51) | STRUCT(Mos6522) {
function STRUCT (line 67) | STRUCT(Ay8913) {
function STRUCT (line 77) | STRUCT(Mock_pair) {
function STRUCT (line 82) | STRUCT(Mockingboard) {
FILE: gsplus/src/sound_driver.c
function snddrv_init (line 67) | void
function sound_child_fork (line 127) | void
function parent_sound_get_sample_rate (line 216) | void
function snddrv_shutdown (line 243) | void
function snddrv_send_sound (line 260) | void
function child_sound_playit (line 296) | void
function reliable_buf_write (line 363) | void
function reliable_zero_write (line 395) | void
function child_send_samples (line 408) | int
function child_sound_loop (line 429) | void
function child_sound_init_linux (line 477) | int
FILE: gsplus/src/undeflate.c
function show_bits (line 71) | void
function show_huftb (line 82) | void
function undeflate_init_len_dist_tab (line 121) | void
function undeflate_init_bit_rev_tab (line 151) | void
function word32 (line 170) | word32
function word32 (line 189) | word32
function byte (line 218) | byte *
function undeflate_add_tab_code (line 268) | void
function word32 (line 313) | word32 *
function word32 (line 366) | word32 *
function undeflate_free_tables (line 380) | void
function undeflate_check_bit_reverse (line 389) | void
function word32 (line 421) | word32 *
function word32 (line 466) | word32 *
function byte (line 664) | byte *
function byte (line 868) | byte *
function undeflate_gzip (line 971) | void
function byte (line 1011) | byte *
function undeflate_zipfile (line 1076) | int
function undeflate_zipfile_search (line 1161) | int
function undeflate_zipfile_make_list (line 1192) | int
FILE: gsplus/src/unshk.c
function word32 (line 18) | word32
function word32 (line 32) | word32
function word32 (line 39) | word32
function unshk_unrle (line 64) | int
function unshk_lzw_clear (line 97) | void
function byte (line 112) | byte *
function unshk_data (line 207) | void
function unshk_parse_header (line 337) | void
function unshk (line 458) | void
function unshk_dsk_raw_data (line 505) | void
FILE: gsplus/src/video.c
function STRUCT (line 125) | STRUCT(Video_all_stat) {
function STRUCT (line 134) | STRUCT(Video_filt_stat) {
function video_set_red_mask (line 272) | void
function video_set_green_mask (line 279) | void
function video_set_blue_mask (line 286) | void
function video_set_alpha_mask (line 293) | void
function video_set_mask_and_shift (line 300) | void
function video_set_palette (line 334) | void
function video_set_redraw_skip_amt (line 345) | void
function Kimage (line 354) | Kimage *
function video_get_x_refresh_needed (line 377) | int
function video_set_x_refresh_needed (line 389) | void
function video_get_active (line 395) | int
function video_set_active (line 401) | void
function video_init (line 410) | void
function video_clamp (line 518) | int
function video_init_kimage (line 531) | void
function show_a2_line_stuff (line 599) | void
function video_reset (line 631) | void
function video_update (line 659) | void
function word32 (line 707) | word32
function change_display_mode (line 747) | void
function video_add_new_all_stat (line 757) | void
function STRUCT (line 795) | STRUCT(Border_changes) {
function change_border_color (line 803) | void
function update_border_info (line 821) | void
function update_border_line (line 907) | void
function video_border_pixel_write (line 1015) | void
function word32 (line 1055) | word32
function video_update_edges (line 1078) | void
function redraw_changed_text (line 1090) | void
function redraw_changed_string (line 1156) | void
function redraw_changed_gr (line 1250) | void
function video_hgr_line_segment (line 1343) | void
function redraw_changed_hgr (line 1437) | void
function video_rebuild_super_hires_palette (line 1494) | int
function word32 (line 1570) | word32
function redraw_changed_super_hires_bank (line 1651) | void
function redraw_changed_super_hires (line 1700) | void
function video_copy_changed2 (line 1725) | void
function video_update_event_line (line 1745) | void
function video_force_reparse (line 1764) | void
function video_update_through_line (line 1786) | void
function video_do_partial_line (line 1888) | void
function video_refresh_line (line 1933) | void
function prepare_a2_font (line 1977) | void
function prepare_a2_romx_font (line 2008) | void
function video_add_rect (line 2034) | void
function video_add_a2_rect (line 2054) | void
function video_form_change_rects (line 2074) | void
function video_get_a2_width (line 2179) | int
function video_get_x_width (line 2185) | int
function video_get_a2_height (line 2191) | int
function video_get_x_height (line 2197) | int
function video_get_x_xpos (line 2203) | int
function video_get_x_ypos (line 2209) | int
function video_update_xpos_ypos (line 2215) | void
function video_change_aspect_needed (line 2229) | int
function video_update_status_enable (line 2251) | void
function video_out_query (line 2278) | int
function video_out_done (line 2293) | void
function video_out_data (line 2301) | int
function video_out_data_intscaled (line 2373) | int
function video_out_data_scaled (line 2428) | int
function word32 (line 2539) | word32
function video_update_scale (line 2572) | void
function video_scale_mouse_x (line 2668) | int
function video_scale_mouse_y (line 2684) | int
function video_unscale_mouse_x (line 2700) | int
function video_unscale_mouse_y (line 2716) | int
function video_update_color_raw (line 2732) | void
function video_update_status_line (line 2760) | void
function video_draw_a2_string (line 2806) | void
function video_show_debug_info (line 2828) | void
function word32 (line 2840) | word32
function word32 (line 2860) | word32
function word32 (line 2869) | word32
FILE: gsplus/src/voc.c
function word32 (line 30) | word32
function voc_devsel_write (line 70) | void
function voc_iosel_c300_write (line 158) | void
function voc_reset (line 166) | void
function word32 (line 178) | word32
function voc_update_interlace (line 199) | void
FILE: gsplus/src/win32snd_driver.c
function win32snd_init (line 51) | void
function win32snd_shutdown (line 58) | void
function handle_wav_snd (line 65) | void CALLBACK
function check_wave_error (line 93) | void
function child_sound_init_win32 (line 107) | void
function win32snd_set_playing (line 185) | void
function win32_send_audio2 (line 204) | void
function win32_send_audio (line 280) | int
FILE: gsplus/src/win_dirent.h
type mode_t (line 15) | typedef unsigned short mode_t;
type dirent (line 17) | struct dirent {
type DIR_t (line 21) | struct DIR_t {
type DIR (line 27) | typedef struct DIR_t DIR;
type dirent (line 30) | struct dirent
FILE: gsplus/src/windriver.c
type Window_info (line 29) | typedef struct windowinfo {
function win_nonblock_read_stdin (line 181) | int
function Window_info (line 199) | Window_info *
function win_hide_pointer (line 211) | void
function win_update_mouse (line 218) | int
function win_event_mouse (line 245) | void
function win_event_key (line 282) | void
function win_event_redraw (line 343) | void
function win_event_destroy (line 355) | void
function win_event_move (line 379) | void
function win_event_size (line 397) | void
function win_event_minmaxinfo (line 423) | void
function win_event_focus (line 455) | void
function LRESULT (line 493) | LRESULT CALLBACK
function main (line 583) | int
function check_input_events (line 630) | void
function win_video_init (line 675) | void
function win_init_window (line 716) | void
function win_create_window (line 747) | void
function xdriver_end (line 842) | void
function win_resize_window (line 848) | void
function x_update_display (line 877) | void
function x_hide_pointer (line 936) | void
function opendir_int (line 946) | int
function DIR (line 989) | DIR *
type dirent (line 1013) | struct dirent
function closedir (line 1045) | int
function lstat (line 1055) | int
function ftruncate (line 1061) | int
FILE: gsplus/src/woz.c
function woz_crc_init (line 22) | void
function word32 (line 44) | word32
function woz_rewrite_crc (line 64) | void
function woz_rewrite_lock (line 86) | void
function woz_check_file (line 104) | void
function woz_parse_meta (line 161) | void
function woz_parse_info (line 190) | void
function woz_parse_tmap (line 239) | void
function woz_parse_trks (line 264) | void
function woz_add_track (line 280) | int
function woz_parse_header (line 388) | int
function Woz_info (line 450) | Woz_info *
function woz_reopen (line 490) | int
function woz_open (line 597) | int
function byte (line 662) | byte *
function byte (line 674) | byte *
function woz_append_chunk (line 687) | int
function byte (line 732) | byte *
function Woz_info (line 773) | Woz_info *
function woz_new (line 960) | int
function woz_maybe_reparse (line 991) | void
function woz_set_reparse (line 1004) | void
function woz_reparse_woz (line 1017) | void
function woz_remove_a_track (line 1054) | void
function word32 (line 1067) | word32
FILE: gsplus/src/xdriver.c
type Window_info (line 38) | typedef struct windowinfo {
function main (line 223) | int
function my_error_handler (line 261) | int
function xdriver_end (line 272) | void
function x_try_xset_r (line 282) | void
function x_badpipe (line 291) | void
function kegs_x_io_error_handler (line 300) | int
function x_video_get_mdepth (line 309) | int
function x_try_find_visual (line 371) | int
function x_video_init (line 444) | void
function x_init_window (line 524) | void
function x_create_window (line 570) | void
function xhandle_shm_error (line 652) | int
function x_allocate_window_data (line 659) | void
function get_shm (line 675) | void
function get_ximage (line 762) | void
function x_set_size_hints (line 810) | void
function x_resize_window (line 848) | void
function x_update_display (line 868) | void
function Window_info (line 939) | Window_info *
function x_send_copy_data (line 963) | void
function x_handle_copy (line 972) | void
function x_handle_targets (line 989) | void
function x_request_paste_data (line 1006) | void
function x_handle_paste (line 1018) | void
function x_update_mouse (line 1058) | int
function x_input_events (line 1085) | void
function x_hide_pointer (line 1325) | void
function x_handle_keysym (line 1335) | void
function x_keysym_to_a2code (line 1442) | int
function x_update_modifier_state (line 1467) | void
function x_auto_repeat_on (line 1485) | void
function x_auto_repeat_off (line 1496) | void
function x_full_screen (line 1507) | void
FILE: upstream/kegs/src/adb.c
function STRUCT (line 103) | STRUCT(Mouse_fifo) {
function adb_get_hide_warp_info (line 315) | int
function adb_get_copy_requested (line 326) | int
function adb_nonmain_check (line 336) | void
function adb_init (line 344) | void
function adb_reset (line 376) | void
function STRUCT (line 407) | STRUCT(Adb_log) {
function adb_log (line 416) | void
function show_adb_log (line 432) | void
function adb_error (line 456) | void
function adb_add_kbd_srq (line 466) | void
function adb_clear_kbd_srq (line 478) | void
function adb_add_data_int (line 487) | void
function adb_add_mouse_int (line 495) | void
function adb_clear_data_int (line 503) | void
function adb_clear_mouse_int (line 509) | void
function adb_send_bytes (line 516) | void
function adb_send_1byte (line 547) | void
function adb_response_packet (line 558) | void
function adb_kbd_reg0_data (line 585) | void
function adb_kbd_talk_reg0 (line 604) | void
function adb_set_config (line 652) | void
function adb_set_new_mode (line 731) | void
function adb_read_c026 (line 747) | int
function adb_write_c026 (line 803) | void
function do_adb_cmd (line 1001) | void
function adb_read_c027 (line 1133) | int
function adb_write_c027 (line 1175) | void
function read_adb_ram (line 1209) | int
function write_adb_ram (line 1249) | void
function adb_get_keypad_xy (line 1263) | int
function adb_update_mouse (line 1303) | int
function mouse_read_c024 (line 1438) | int
function mouse_compress_fifo (line 1589) | void
function adb_paste_update_state (line 1614) | void
function adb_paste_add_buf (line 1633) | int
function adb_key_event (line 1671) | void
function word32 (line 1776) | word32
function word32 (line 1806) | word32
function word32 (line 1833) | word32
function adb_is_cmd_key_down (line 1839) | int
function adb_is_option_key_down (line 1845) | int
function adb_increment_speed (line 1851) | void
function adb_update_c025_mask (line 1879) | void
function adb_ascii_to_a2code (line 1893) | int
function adb_physical_key_update (line 1975) | void
function adb_maybe_virtual_key_update (line 2165) | void
function adb_virtual_key_update (line 2202) | void
function adb_all_keys_up (line 2236) | void
function adb_kbd_repeat_off (line 2254) | void
function adb_mainwin_focus (line 2260) | void
FILE: upstream/kegs/src/applesingle.c
function word32 (line 23) | word32
function word32 (line 29) | word32
function applesingle_set_be32 (line 35) | void
function applesingle_set_be16 (line 44) | void
function word32 (line 51) | word32
function word32 (line 215) | word32
function word32 (line 337) | word32
FILE: upstream/kegs/src/clock.c
function get_dtime (line 48) | double
function micro_sleep (line 91) | int
function clk_bram_zero (line 125) | void
function clk_bram_set (line 139) | void
function clk_setup_bram_version (line 153) | void
function clk_write_bram (line 163) | void
function update_cur_time (line 180) | void
function clock_update (line 222) | void
function clock_update_if_needed (line 228) | void
function clock_write_c034 (line 240) | void
function do_clock_data (line 254) | void
FILE: upstream/kegs/src/config.c
function config_add_argv_override (line 516) | int
function config_set_config_kegs_name (line 551) | void
function config_init_menus (line 562) | void
function config_init (line 625) | void
function cfg_find_config_kegs_file (line 638) | void
function config_setup_kegs_file (line 674) | int
function config_expand_path (line 713) | int
function cfg_err_vprintf (line 793) | void
function cfg_err_printf (line 820) | void
function cfg_toggle_config_panel (line 830) | void
function cfg_set_config_panel (line 844) | void
function config_vbl_update (line 967) | void
function cfg_file_update_rom (line 978) | void
function cfg_file_update_ptr (line 984) | void
function cfg_int_update (line 1031) | void
function cfg_load_charrom (line 1069) | void
function config_load_roms (line 1095) | void
function config_parse_config_kegs_file (line 1313) | void
function cfg_parse_one_line (line 1401) | void
function cfg_parse_bram (line 1515) | void
function cfg_parse_sxdx (line 1553) | void
function config_generate_config_kegs_name (line 1622) | void
function insert_disk (line 1739) | void
function dword64 (line 2109) | dword64
function dword64 (line 2154) | dword64
function dword64 (line 2170) | dword64
function dword64 (line 2205) | dword64
function cfg_partition_maybe_add_dotdot (line 2218) | int
function cfg_partition_name_check (line 2231) | int
function cfg_partition_read_block (line 2251) | int
function cfg_partition_find_by_name_or_num (line 2261) | int
function cfg_partition_make_list_from_name (line 2348) | int
function cfg_partition_make_list (line 2364) | int
function cfg_maybe_insert_disk (line 2457) | int
function cfg_insert_disk_dynapro (line 2476) | void
function cfg_stat (line 2494) | int
function word32 (line 2525) | word32
function word32 (line 2531) | word32
function dword64 (line 2537) | dword64
function word32 (line 2550) | word32
function word32 (line 2559) | word32
function cfg_set_le32 (line 2568) | void
function config_file_to_pipe (line 2577) | void
function cfg_htab_vtab (line 2663) | void
function cfg_home (line 2678) | void
function cfg_cleol (line 2689) | void
function cfg_putchar (line 2700) | void
function cfg_printf (line 2747) | void
function cfg_print_dnum (line 2767) | void
function cfg_get_disk_name (line 2799) | int
function cfg_get_disk_locked (line 2818) | int
function cfg_parse_menu (line 2840) | void
function cfg_get_base_path (line 3099) | void
function cfg_dup_existing_image (line 3208) | void
function cfg_dup_image_selected (line 3217) | void
function cfg_validate_image (line 3296) | void
function cfg_toggle_lock_disk (line 3306) | void
function cfg_create_new_image_act (line 3316) | int
function cfg_create_new_image (line 3356) | void
function cfg_file_init (line 3391) | void
function cfg_free_alldirents (line 3434) | void
function cfg_file_add_dirent_unique (line 3456) | void
function cfg_file_add_dirent (line 3482) | void
function cfg_dirent_sortfn (line 3518) | int
function cfg_str_match (line 3531) | int
function cfg_str_match_maybecase (line 3537) | int
function cfgcasecmp (line 3564) | int
function cfg_strlcat (line 3570) | int
function cfg_file_readdir (line 3673) | void
function cfg_fix_topent (line 3855) | void
function cfg_file_draw (line 3880) | void
function cfg_partition_select_all (line 4015) | void
function cfg_partition_selected (line 4051) | void
function cfg_file_selected (line 4099) | void
function cfg_file_handle_key (line 4188) | void
function cfg_draw_menu (line 4290) | void
function cfg_newdisk_pick_menu (line 4398) | void
function cfg_control_panel_update (line 4422) | int
function cfg_edit_mode_key (line 4439) | void
function cfg_control_panel_update1 (line 4474) | int
FILE: upstream/kegs/src/config.h
function STRUCT (line 35) | STRUCT(Cfg_defval) {
FILE: upstream/kegs/src/debugger.c
function STRUCT (line 26) | STRUCT(Debug_entry) {
function debugger_init (line 105) | void
function check_breakpoints (line 121) | void
function debug_hit_bp (line 146) | void
function debugger_run_16ms (line 199) | int
function dbg_log_info (line 213) | void
function debugger_update_list_kpc (line 230) | void
function debugger_key_event (line 236) | void
function debugger_page_updown (line 316) | void
function debugger_redraw_screen (line 342) | void
function debug_draw_debug_line (line 406) | void
function debugger_help (line 458) | void
function dbg_help_show_strs (line 514) | void
function do_debug_cmd (line 618) | void
function word32 (line 873) | word32
function show_one_toolset (line 885) | void
function show_toolset_tables (line 906) | void
function word32 (line 938) | word32
function debug_help (line 1017) | void
function debug_bp (line 1024) | void
function debug_bp_set (line 1032) | void
function debug_bp_clear (line 1038) | void
function debug_bp_clear_all (line 1044) | void
function debug_bp_setclr (line 1057) | void
function debug_soundfile (line 1091) | void
function debug_logpc (line 1101) | void
function debug_logpc_on (line 1111) | void
function debug_logpc_off (line 1122) | void
function debug_logpc_out_data (line 1133) | void
function Data_log (line 1183) | Data_log *
function debug_logpc_save (line 1208) | void
function set_bp (line 1328) | void
function show_bp (line 1348) | void
function delete_bp (line 1383) | void
function debug_iwm (line 1415) | void
function debug_iwm_check (line 1424) | void
function do_blank (line 1433) | int
function do_go (line 1481) | void
function do_step (line 1490) | void
function xam_mem (line 1511) | void
function show_hex_mem (line 1518) | void
function do_debug_list (line 1557) | void
function dis_do_memmove (line 1582) | void
function dis_do_pattern_search (line 1599) | void
function dis_do_compare (line 1638) | void
function do_debug_load (line 1739) | void
function debug_get_view_line (line 1999) | int
function debug_add_output_line (line 2017) | int
function debug_add_output_string (line 2077) | void
function debug_add_output_chars (line 2097) | void
function dbg_printf (line 2131) | int
function dbg_vprintf (line 2143) | int
function halt_printf (line 2153) | void
function halt2_printf (line 2165) | void
FILE: upstream/kegs/src/defc.h
type byte (line 21) | typedef unsigned char byte;
type word16 (line 22) | typedef unsigned short word16;
type word32 (line 23) | typedef unsigned int word32;
type dword64 (line 25) | typedef unsigned __int64 dword64;
type dword64 (line 27) | typedef unsigned long long dword64;
type stat (line 82) | struct stat
function STRUCT (line 97) | STRUCT(Pc_log) {
function STRUCT (line 107) | STRUCT(Data_log) {
function STRUCT (line 115) | STRUCT(Event) {
function STRUCT (line 121) | STRUCT(Fplus) {
function STRUCT (line 126) | STRUCT(Engine_reg) {
function STRUCT (line 142) | STRUCT(Break_point) {
function STRUCT (line 148) | STRUCT(Change_rect) {
function STRUCT (line 156) | STRUCT(Kimage) {
type byte (line 182) | typedef byte *Pg_info;
function STRUCT (line 183) | STRUCT(Page_info) {
function STRUCT (line 187) | STRUCT(Cfg_menu) {
function STRUCT (line 195) | STRUCT(Cfg_dirent) {
function STRUCT (line 204) | STRUCT(Cfg_listhdr) {
function STRUCT (line 218) | STRUCT(Dbg_longcmd) {
function STRUCT (line 225) | STRUCT(Emustate_intlist) {
function STRUCT (line 230) | STRUCT(Emustate_dword64list) {
function STRUCT (line 235) | STRUCT(Emustate_word32list) {
function STRUCT (line 240) | STRUCT(Lzw_state) {
FILE: upstream/kegs/src/doc.c
function doc_init (line 71) | void
function doc_reset (line 100) | void
function doc_play (line 123) | int
function doc_handle_event (line 248) | void
function doc_sound_end (line 260) | void
function doc_add_sound_irq (line 342) | void
function doc_remove_sound_irq (line 364) | void
function doc_start_sound2 (line 434) | void
function doc_start_sound (line 443) | void
function doc_wave_end_estimate2 (line 510) | void
function doc_wave_end_estimate (line 519) | void
function doc_remove_sound_event (line 585) | void
function doc_write_ctl_reg (line 595) | void
function doc_recalc_sound_parms (line 684) | void
function doc_read_c03c (line 718) | int
function doc_read_c03d (line 724) | int
function doc_write_c03c (line 816) | void
function doc_write_c03d (line 833) | void
function doc_show_ensoniq_state (line 998) | void
FILE: upstream/kegs/src/dyna_type.c
function STRUCT (line 20) | STRUCT(Dynatype_extensions) {
function STRUCT (line 41) | STRUCT(Dynatype_types) {
function word32 (line 61) | word32
function word32 (line 80) | word32
function word32 (line 114) | word32
function dynatype_get_extension (line 191) | int
function dynatype_comma_arg (line 215) | int
function dynatype_fix_unix_name (line 272) | void
FILE: upstream/kegs/src/dyna_validate.c
function word32 (line 20) | word32
function dynapro_validate_init_freeblks (line 76) | void
function word32 (line 100) | word32
function word32 (line 122) | word32
function word32 (line 190) | word32
function word32 (line 258) | word32
function dynapro_validate_disk (line 394) | int
function dynapro_validate_any_image (line 429) | void
FILE: upstream/kegs/src/dynapro.c
function word32 (line 104) | word32
function word32 (line 110) | word32
function word32 (line 116) | word32
function dynapro_set_word24 (line 122) | void
function dynapro_set_word32 (line 131) | void
function dynapro_set_word16 (line 141) | void
function dynapro_error (line 149) | void
function Dynapro_file (line 164) | Dynapro_file *
function dynapro_free_file (line 173) | void
function dynapro_free_recursive_file (line 197) | void
function dynapro_free_dynapro_info (line 213) | void
function word32 (line 229) | word32
function word32 (line 258) | word32
function byte (line 279) | byte *
function dynapro_join_path_and_file (line 315) | void
function word32 (line 331) | word32
function word32 (line 428) | word32
function word32 (line 523) | word32
function dynapro_fix_damaged_entry (line 543) | void
function dynapro_try_fix_damage (line 559) | void
function dynapro_try_fix_damaged_disk (line 577) | void
function dynapro_new_unix_path (line 603) | void
function Dynapro_file (line 617) | Dynapro_file *
function dynapro_handle_write_dir (line 835) | void
function word32 (line 880) | word32
function dynapro_handle_write_file (line 910) | void
function dynapro_handle_changed_entry (line 921) | void
function word32 (line 947) | word32
function dynapro_unmap_file (line 971) | void
function dynapro_unlink_file (line 1019) | void
function dynapro_erase_free_entry (line 1061) | void
function dynapro_erase_free_dir (line 1078) | void
function dynapro_mark_damaged (line 1107) | void
function dynapro_write (line 1131) | int
function dynapro_debug_update (line 1200) | void
function dynapro_debug_map (line 1213) | void
function dynapro_debug_recursive_file_map (line 1245) | void
function word32 (line 1273) | word32
function dynapro_create_prodos_name (line 1298) | int
function Dynapro_file (line 1494) | Dynapro_file *
function dynapro_create_dir (line 1562) | int
function word32 (line 1707) | word32
function word32 (line 1843) | word32
function word32 (line 1940) | word32
function word32 (line 1990) | word32
function word32 (line 2048) | word32
function word32 (line 2111) | word32
function word32 (line 2155) | word32
function word32 (line 2201) | word32
function word32 (line 2237) | word32
function dynapro_mount (line 2267) | int
FILE: upstream/kegs/src/engine.h
function ENGINE_TYPE (line 15) | int
FILE: upstream/kegs/src/engine_c.c
function word32 (line 332) | word32
function word32 (line 355) | word32
function word32 (line 379) | word32
function set_memory8_io_stub (line 408) | void
function set_memory16_pieces_stub (line 466) | void
function set_memory24_pieces_stub (line 486) | void
function word32 (line 514) | word32
function word32 (line 531) | word32
function word32 (line 538) | word32
function set_memory_c (line 546) | void
function set_memory16_c (line 562) | void
function set_memory24_c (line 578) | void
function word32 (line 586) | word32
function word32 (line 639) | word32
function fixed_memory_ptrs_init (line 686) | void
function word32 (line 709) | word32
function engine_recalc_events (line 753) | void
function set_halt_act (line 760) | void
function clr_halt_act (line 777) | void
function word32 (line 783) | word32
function enter_engine (line 934) | int
FILE: upstream/kegs/src/iwm.c
function iwm_init_drive (line 109) | void
function iwm_init (line 163) | void
function iwm_reset (line 194) | void
function disk_set_num_tracks (line 216) | void
function word32 (line 226) | word32
function draw_iwm_status (line 241) | void
function iwm_flush_cur_disk (line 271) | void
function iwm_flush_disk_to_unix (line 280) | void
function iwm_vbl_update (line 321) | void
function iwm_update_fast_disk_emul (line 351) | void
function iwm_show_stats (line 359) | void
function Disk (line 395) | Disk *
function Disk (line 411) | Disk *
function iwm_move_to_ftrack (line 633) | void
function iwm_move_to_qtr_track (line 726) | void
function iwm525_update_phases (line 747) | void
function iwm525_update_head (line 781) | void
function iwm_read_status35 (line 911) | int
function iwm_do_action35 (line 1019) | void
function read_iwm (line 1093) | int
function write_iwm (line 1175) | void
function iwm_read_enable2 (line 1249) | int
function iwm_read_enable2_handshake (line 1258) | int
function iwm_write_enable2 (line 1275) | void
function word32 (line 1284) | word32
function word32 (line 1338) | word32
function dword64 (line 1407) | dword64
function dword64 (line 1422) | dword64
function word32 (line 1480) | word32
function word32 (line 1492) | word32
function dword64 (line 1508) | dword64
function iwm_calc_forced_sync_0s (line 1538) | int
function word32 (line 1577) | word32
function iwm_write_data (line 1741) | void
function iwm_start_write (line 1809) | void
function iwm_start_write_act (line 1826) | int
function iwm_write_data35 (line 1903) | void
function iwm_write_end (line 1912) | void
function iwm_write_one_nib (line 1985) | void
function iwm_recalc_sync_from (line 2016) | void
function sector_to_partial_nib (line 2130) | void
function disk_unnib_4x4 (line 2167) | int
function iwm_denib_track525 (line 2179) | int
function iwm_denib_track35 (line 2408) | int
function iwm_track_to_unix (line 2725) | int
function show_hex_data (line 2803) | void
function iwm_check_nibblization (line 2818) | void
function disk_check_nibblization (line 2841) | void
function disk_unix_to_nib (line 2905) | void
function iwm_nibblize_track_nib525 (line 3013) | void
function iwm_nibblize_track_525 (line 3042) | void
function iwm_nibblize_track_35 (line 3122) | void
function disk_4x4_nib_out (line 3343) | void
function disk_nib_out (line 3350) | void
function disk_nib_end_track (line 3361) | void
function word32 (line 3372) | word32
function Disk (line 3463) | Disk *
function iwm_toggle_lock (line 3489) | void
function iwm_eject_named_disk (line 3512) | void
function iwm_eject_disk_by_num (line 3538) | void
function iwm_eject_disk (line 3548) | void
function iwm_show_track (line 3629) | void
function iwm_show_a_track (line 3678) | void
function dummy1 (line 3746) | void
function dummy2 (line 3752) | void
FILE: upstream/kegs/src/iwm.h
function STRUCT (line 66) | STRUCT(Trk) {
function STRUCT (line 75) | STRUCT(Woz_info) {
type Dynapro_map (line 89) | typedef struct Dynapro_map_st Dynapro_map;
function STRUCT (line 91) | STRUCT(Dynapro_file) {
type Dynapro_map_st (line 113) | struct Dynapro_map_st {
function STRUCT (line 119) | STRUCT(Dynapro_info) {
function STRUCT (line 126) | STRUCT(Disk) {
function STRUCT (line 160) | STRUCT(Iwm) {
function STRUCT (line 178) | STRUCT(Driver_desc) {
function STRUCT (line 188) | STRUCT(Part_map) {
FILE: upstream/kegs/src/joystick_driver.c
function joystick_init (line 46) | void
function joystick_update (line 84) | void
function joystick_update_buttons (line 122) | void
function joystick_init (line 133) | void
function joystick_update (line 176) | void
function joystick_update_buttons (line 207) | void
function hid_device_callback (line 251) | void
function hid_get_int_property (line 311) | int
function joystick_init (line 329) | void
function joystick_update (line 392) | void
function joystick_update_buttons (line 412) | void
function joystick_init (line 423) | void
function joystick_update (line 431) | void
function joystick_update_buttons (line 451) | void
function joystick_callback_init (line 460) | void
function joystick_callback_update (line 466) | void
FILE: upstream/kegs/src/macsnd_driver.c
function OSStatus (line 58) | static OSStatus
function mac_send_audio (line 147) | int
function macsnd_init (line 173) | void
FILE: upstream/kegs/src/mockingboard.c
function mock_ay8913_reset (line 32) | void
function mockingboard_reset (line 55) | void
function mock_show_pair (line 84) | void
function mock_update_timers (line 108) | void
function mockingboard_event (line 273) | void
function word32 (line 284) | word32
function mockingboard_write (line 294) | void
function word32 (line 304) | word32
function mock_6522_write (line 383) | void
function word32 (line 517) | word32
function mock_ay8913_reg_read (line 544) | void
function mock_ay8913_reg_write (line 570) | void
function mock_ay8913_control_update (line 620) | void
function mockingboard_show (line 652) | void
FILE: upstream/kegs/src/moremem.c
function fixup_brks (line 148) | void
function fixup_hires_on (line 177) | void
function fixup_bank0_2000_4000 (line 188) | void
function fixup_bank0_0400_0800 (line 236) | void
function fixup_any_bank_any_page (line 276) | void
function fixup_intcx (line 294) | void
function fixup_st80col (line 367) | void
function fixup_altzp (line 389) | void
function fixup_page2 (line 413) | void
function fixup_ramrd (line 426) | void
function fixup_ramwrt (line 470) | void
function fixup_lc (line 554) | void
function set_statereg (line 605) | void
function fixup_shadow_txt1 (line 651) | void
function fixup_shadow_txt2 (line 668) | void
function fixup_shadow_hires1 (line 701) | void
function fixup_shadow_hires2 (line 719) | void
function fixup_shadow_shr (line 750) | void
function fixup_shadow_iolc (line 778) | void
function update_shadow_reg (line 807) | void
function fixup_shadow_all_banks (line 852) | void
function setup_pageinfo (line 879) | void
function show_bankptrs_bank0rdwr (line 934) | void
function show_bankptrs (line 944) | void
function show_addr (line 969) | void
function word32 (line 992) | word32
function word32 (line 1004) | word32
function io_write (line 1463) | void
function word32 (line 2119) | word32
function slinky_devsel_write (line 2137) | void
function word32 (line 2155) | word32
function word32 (line 2180) | word32
function in_vblank (line 2224) | int
function read_vid_counters (line 2246) | int
FILE: upstream/kegs/src/paddles.c
function paddle_fixup_joystick_type (line 42) | void
function paddle_trigger (line 60) | void
function paddle_trigger_mouse (line 81) | void
function paddle_trigger_keypad (line 107) | void
function paddle_update_trigger_dcycs (line 124) | void
function read_paddles (line 172) | int
function paddle_update_buttons (line 186) | void
FILE: upstream/kegs/src/protos_base.h
type stat (line 189) | struct stat
FILE: upstream/kegs/src/protos_windriver.h
type dirent (line 40) | struct dirent
type stat (line 42) | struct stat
FILE: upstream/kegs/src/pulseaudio_driver.c
function pulse_audio_send_audio (line 54) | int
function pulse_audio_main_events (line 80) | void
function pulse_audio_write_to_stream (line 129) | void
function pulse_audio_start_stream (line 219) | int
function pulse_audio_do_init (line 259) | int
function pulse_audio_init (line 328) | int
function pulse_audio_shutdown (line 362) | void
FILE: upstream/kegs/src/scc.c
function scc_init (line 62) | void
function scc_reset (line 109) | void
function scc_hard_reset_port (line 139) | void
function scc_reset_port (line 168) | void
function scc_regen_clocks (line 199) | void
function scc_port_close (line 347) | void
function scc_port_open (line 364) | void
function scc_is_port_closed (line 384) | int
function scc_config_changed (line 445) | void
function scc_update (line 475) | void
function scc_try_to_empty_writebuf (line 494) | void
function scc_try_fill_readbuf (line 522) | void
function scc_do_event (line 564) | void
function show_scc_state (line 593) | void
function word32 (line 647) | word32
function scc_write_reg (line 738) | void
function word32 (line 965) | word32
function scc_write_data (line 998) | void
function word32 (line 1018) | word32
function scc_maybe_br_event (line 1050) | void
function scc_evaluate_ints (line 1087) | void
function scc_maybe_rx_event (line 1136) | void
function scc_maybe_rx_int (line 1173) | void
function scc_clr_rx_int (line 1195) | void
function scc_handle_tx_event (line 1202) | void
function scc_maybe_tx_event (line 1218) | void
function scc_clr_tx_int (line 1240) | void
function scc_set_zerocnt_int (line 1247) | void
function scc_clr_zerocnt_int (line 1260) | void
function scc_add_to_readbuf (line 1267) | void
function scc_add_to_readbufv (line 1303) | void
function scc_transmit (line 1326) | void
function scc_add_to_writebuf (line 1363) | void
FILE: upstream/kegs/src/scc.h
function STRUCT (line 47) | STRUCT(Scc) {
FILE: upstream/kegs/src/scc_socket_driver.c
type socklen_t (line 37) | typedef int socklen_t;
function scc_socket_open (line 58) | void
function scc_socket_close (line 107) | void
function scc_socket_close_extended (line 156) | void
function scc_socket_maybe_open (line 175) | void
function scc_socket_open_incoming (line 202) | void
function scc_socket_open_outgoing (line 297) | void
function scc_socket_make_nonblock (line 382) | void
function scc_accept_socket (line 421) | void
function scc_socket_telnet_reqs (line 492) | void
function scc_socket_fill_readbuf (line 520) | void
function scc_socket_recvd_char (line 565) | void
function scc_socket_empty_writebuf (line 738) | void
function scc_socket_modem_write (line 871) | void
function scc_socket_do_cmd_str (line 936) | void
function scc_socket_send_modem_code (line 1134) | void
function scc_socket_modem_connect (line 1175) | void
function scc_socket_modem_do_ring (line 1185) | void
function scc_socket_do_answer (line 1217) | void
FILE: upstream/kegs/src/scc_unixdriver.c
function scc_serial_unix_open (line 29) | void
function scc_serial_unix_close (line 53) | void
function scc_serial_unix_change_params (line 68) | void
function scc_serial_unix_fill_readbuf (line 141) | void
function scc_serial_unix_empty_writebuf (line 180) | void
FILE: upstream/kegs/src/scc_windriver.c
function scc_serial_win_open (line 25) | void
function scc_serial_win_close (line 67) | void
function scc_serial_win_change_params (line 84) | void
function scc_serial_win_fill_readbuf (line 166) | void
function scc_serial_win_empty_writebuf (line 198) | void
FILE: upstream/kegs/src/sim65816.c
function sim_get_force_depth (line 157) | int
function sim_get_use_shmem (line 163) | int
function sim_set_use_shmem (line 169) | void
function word32 (line 180) | word32
function toolbox_debug_c (line 198) | void
function show_toolbox_log (line 224) | void
function word32 (line 250) | word32
function set_memory_io (line 304) | void
function show_regs_act (line 350) | void
function show_regs (line 372) | void
function my_exit (line 378) | void
function do_reset (line 386) | void
function byte (line 435) | byte *
function memory_ptr_init (line 459) | void
function parse_argv (line 488) | int
function kegs_init (line 654) | int
function load_roms_init_memory (line 699) | void
function initialize_events (line 724) | void
function check_for_one_event_type (line 741) | void
function add_event_entry (line 765) | void
function dword64 (line 824) | dword64
function add_event_stop (line 857) | void
function add_event_doc (line 863) | void
function add_event_scc (line 875) | void
function add_event_vbl (line 885) | void
function add_event_vid_upd (line 894) | void
function add_event_mockingboard (line 904) | void
function add_event_scan_int (line 915) | void
function dword64 (line 941) | dword64
function dword64 (line 947) | dword64
function remove_event_mockingboard (line 953) | void
function show_all_events (line 959) | void
function show_pmhz (line 1008) | void
function setup_zip_speeds (line 1016) | void
function run_16ms (line 1047) | int
function run_a2_one_vbl (line 1098) | int
function add_irq (line 1285) | void
function remove_irq (line 1296) | void
function take_irq (line 1302) | void
function show_dtime_array (line 1365) | void
function update_60hz (line 1394) | void
function do_vbl_int (line 1691) | void
function do_scan_int (line 1702) | void
function check_scan_line_int (line 1753) | void
function check_for_new_scan_int (line 1796) | void
function scb_changed (line 1805) | void
function init_reg (line 1815) | void
function handle_action (line 1829) | void
function do_break (line 1863) | void
function do_cop (line 1872) | void
function do_wdm (line 1879) | void
function do_wai (line 1921) | void
function do_stp (line 1927) | void
function do_wdm_emulator_id (line 1939) | void
function size_fail (line 2001) | void
function fatal_printf (line 2007) | int
function kegs_vprintf (line 2024) | int
function dword64 (line 2048) | dword64
function clear_fatal_logs (line 2073) | void
function dword64 (line 2098) | dword64
FILE: upstream/kegs/src/smartport.c
function STRUCT (line 29) | STRUCT(Smpt_log) {
function smartport_error (line 43) | void
function smartport_log (line 69) | void
function do_c70d (line 101) | void
function do_c70a (line 453) | void
function do_read_c7 (line 523) | int
function do_write_c7 (line 603) | int
function smartport_memory_write (line 685) | int
function do_format_c7 (line 704) | int
function do_c700 (line 786) | void
FILE: upstream/kegs/src/sound.c
function sound_init (line 168) | void
function sound_set_audio_rate (line 175) | void
function sound_reset (line 189) | void
function sound_shutdown (line 196) | void
function sound_update (line 202) | void
function sound_file_start (line 213) | void
function sound_file_open (line 224) | void
function sound_file_close (line 256) | void
function send_sound_to_file (line 276) | void
function show_c030_state (line 318) | void
function show_c030_samps (line 324) | void
function sound_play_c030 (line 352) | int
function sound_play (line 552) | void
function sound_mock_envelope (line 759) | void
function sound_mock_noise (line 837) | void
function sound_mock_play (line 894) | void
function word32 (line 982) | word32
function sound_write_c030 (line 989) | void
FILE: upstream/kegs/src/sound.h
function STRUCT (line 28) | STRUCT(Doc_reg) {
function STRUCT (line 54) | STRUCT(Mos6522) {
function STRUCT (line 70) | STRUCT(Ay8913) {
function STRUCT (line 80) | STRUCT(Mock_pair) {
function STRUCT (line 85) | STRUCT(Mockingboard) {
FILE: upstream/kegs/src/sound_driver.c
function snddrv_init (line 71) | void
function sound_child_fork (line 131) | void
function parent_sound_get_sample_rate (line 220) | void
function snddrv_shutdown (line 247) | void
function snddrv_send_sound (line 264) | void
function child_sound_playit (line 300) | void
function reliable_buf_write (line 367) | void
function reliable_zero_write (line 399) | void
function child_send_samples (line 412) | int
function child_sound_loop (line 433) | void
function child_sound_init_linux (line 481) | int
FILE: upstream/kegs/src/undeflate.c
function show_bits (line 75) | void
function show_huftb (line 86) | void
function undeflate_init_len_dist_tab (line 125) | void
function undeflate_init_bit_rev_tab (line 155) | void
function word32 (line 174) | word32
function word32 (line 193) | word32
function byte (line 222) | byte *
function undeflate_add_tab_code (line 272) | void
function word32 (line 317) | word32 *
function word32 (line 370) | word32 *
function undeflate_free_tables (line 384) | void
function undeflate_check_bit_reverse (line 393) | void
function word32 (line 425) | word32 *
function word32 (line 470) | word32 *
function byte (line 668) | byte *
function byte (line 872) | byte *
function undeflate_gzip (line 975) | void
function byte (line 1015) | byte *
function undeflate_zipfile (line 1080) | int
function undeflate_zipfile_search (line 1165) | int
function undeflate_zipfile_make_list (line 1196) | int
FILE: upstream/kegs/src/unshk.c
function word32 (line 22) | word32
function word32 (line 36) | word32
function word32 (line 43) | word32
function unshk_unrle (line 68) | int
function unshk_lzw_clear (line 101) | void
function byte (line 116) | byte *
function unshk_data (line 211) | void
function unshk_parse_header (line 341) | void
function unshk (line 462) | void
function unshk_dsk_raw_data (line 509) | void
FILE: upstream/kegs/src/video.c
function STRUCT (line 129) | STRUCT(Video_all_stat) {
function STRUCT (line 138) | STRUCT(Video_filt_stat) {
function video_set_red_mask (line 276) | void
function video_set_green_mask (line 283) | void
function video_set_blue_mask (line 290) | void
function video_set_alpha_mask (line 297) | void
function video_set_mask_and_shift (line 304) | void
function video_set_palette (line 338) | void
function video_set_redraw_skip_amt (line 349) | void
function Kimage (line 358) | Kimage *
function video_get_x_refresh_needed (line 381) | int
function video_set_x_refresh_needed (line 393) | void
function video_get_active (line 399) | int
function video_set_active (line 405) | void
function video_init (line 414) | void
function video_clamp (line 522) | int
function video_init_kimage (line 535) | void
function show_a2_line_stuff (line 603) | void
function video_reset (line 635) | void
function video_update (line 663) | void
function word32 (line 711) | word32
function change_display_mode (line 751) | void
function video_add_new_all_stat (line 761) | void
function STRUCT (line 799) | STRUCT(Border_changes) {
function change_border_color (line 807) | void
function update_border_info (line 825) | void
function update_border_line (line 911) | void
function video_border_pixel_write (line 1019) | void
function word32 (line 1059) | word32
function video_update_edges (line 1082) | void
function redraw_changed_text (line 1094) | void
function redraw_changed_string (line 1160) | void
function redraw_changed_gr (line 1254) | void
function video_hgr_line_segment (line 1347) | void
function redraw_changed_hgr (line 1441) | void
function video_rebuild_super_hires_palette (line 1498) | int
function word32 (line 1574) | word32
function redraw_changed_super_hires_bank (line 1655) | void
function redraw_changed_super_hires (line 1704) | void
function video_copy_changed2 (line 1729) | void
function video_update_event_line (line 1749) | void
function video_force_reparse (line 1768) | void
function video_update_through_line (line 1790) | void
function video_do_partial_line (line 1892) | void
function video_refresh_line (line 1937) | void
function prepare_a2_font (line 1981) | void
function prepare_a2_romx_font (line 2012) | void
function video_add_rect (line 2038) | void
function video_add_a2_rect (line 2058) | void
function video_form_change_rects (line 2078) | void
function video_get_a2_width (line 2183) | int
function video_get_x_width (line 2189) | int
function video_get_a2_height (line 2195) | int
function video_get_x_height (line 2201) | int
function video_get_x_xpos (line 2207) | int
function video_get_x_ypos (line 2213) | int
function video_update_xpos_ypos (line 2219) | void
function video_change_aspect_needed (line 2233) | int
function video_update_status_enable (line 2255) | void
function video_out_query (line 2282) | int
function video_out_done (line 2297) | void
function video_out_data (line 2305) | int
function video_out_data_intscaled (line 2377) | int
function video_out_data_scaled (line 2432) | int
function word32 (line 2543) | word32
function video_update_scale (line 2576) | void
function video_scale_mouse_x (line 2672) | int
function video_scale_mouse_y (line 2688) | int
function video_unscale_mouse_x (line 2704) | int
function video_unscale_mouse_y (line 2720) | int
function video_update_color_raw (line 2736) | void
function video_update_status_line (line 2764) | void
function video_draw_a2_string (line 2810) | void
function video_show_debug_info (line 2832) | void
function word32 (line 2844) | word32
function word32 (line 2864) | word32
function word32 (line 2873) | word32
FILE: upstream/kegs/src/voc.c
function word32 (line 34) | word32
function voc_devsel_write (line 74) | void
function voc_iosel_c300_write (line 162) | void
function voc_reset (line 170) | void
function word32 (line 182) | word32
function voc_update_interlace (line 203) | void
FILE: upstream/kegs/src/win32snd_driver.c
function win32snd_init (line 55) | void
function win32snd_shutdown (line 62) | void
function handle_wav_snd (line 69) | void CALLBACK
function check_wave_error (line 97) | void
function child_sound_init_win32 (line 111) | void
function win32snd_set_playing (line 189) | void
function win32_send_audio2 (line 208) | void
function win32_send_audio (line 284) | int
FILE: upstream/kegs/src/win_dirent.h
type mode_t (line 18) | typedef unsigned short mode_t;
type dirent (line 20) | struct dirent {
type DIR_t (line 24) | struct DIR_t {
type DIR (line 30) | typedef struct DIR_t DIR;
type dirent (line 33) | struct dirent
FILE: upstream/kegs/src/windriver.c
type Window_info (line 33) | typedef struct windowinfo {
function win_nonblock_read_stdin (line 185) | int
function Window_info (line 203) | Window_info *
function win_hide_pointer (line 215) | void
function win_update_mouse (line 222) | int
function win_event_mouse (line 249) | void
function win_event_key (line 286) | void
function win_event_redraw (line 347) | void
function win_event_destroy (line 359) | void
function win_event_move (line 383) | void
function win_event_size (line 401) | void
function win_event_minmaxinfo (line 427) | void
function win_event_focus (line 459) | void
function LRESULT (line 497) | LRESULT CALLBACK
function main (line 587) | int
function check_input_events (line 634) | void
function win_video_init (line 679) | void
function win_init_window (line 720) | void
function win_create_window (line 751) | void
function xdriver_end (line 846) | void
function win_resize_window (line 852) | void
function x_update_display (line 881) | void
function x_hide_pointer (line 940) | void
function opendir_int (line 950) | int
function DIR (line 993) | DIR *
type dirent (line 1017) | struct dirent
function closedir (line 1049) | int
function lstat (line 1059) | int
function ftruncate (line 1065) | int
FILE: upstream/kegs/src/woz.c
function woz_crc_init (line 26) | void
function word32 (line 48) | word32
function woz_rewrite_crc (line 68) | void
function woz_rewrite_lock (line 90) | void
function woz_check_file (line 108) | void
function woz_parse_meta (line 165) | void
function woz_parse_info (line 194) | void
function woz_parse_tmap (line 243) | void
function woz_parse_trks (line 268) | void
function woz_add_track (line 284) | int
function woz_parse_header (line 392) | int
function Woz_info (line 454) | Woz_info *
function woz_reopen (line 494) | int
function woz_open (line 601) | int
function byte (line 666) | byte *
function byte (line 678) | byte *
function woz_append_chunk (line 691) | int
function byte (line 736) | byte *
function Woz_info (line 777) | Woz_info *
function woz_new (line 964) | int
function woz_maybe_reparse (line 995) | void
function woz_set_reparse (line 1008) | void
function woz_reparse_woz (line 1021) | void
function woz_remove_a_track (line 1058) | void
function word32 (line 1071) | word32
FILE: upstream/kegs/src/xdriver.c
type Window_info (line 42) | typedef struct windowinfo {
function main (line 227) | int
function my_error_handler (line 265) | int
function xdriver_end (line 276) | void
function x_try_xset_r (line 286) | void
function x_badpipe (line 295) | void
function kegs_x_io_error_handler (line 304) | int
function x_video_get_mdepth (line 313) | int
function x_try_find_visual (line 375) | int
function x_video_init (line 448) | void
function x_init_window (line 528) | void
function x_create_window (line 574) | void
function xhandle_shm_error (line 656) | int
function x_allocate_window_data (line 663) | void
function get_shm (line 679) | void
function get_ximage (line 766) | void
function x_set_size_hints (line 814) | void
function x_resize_window (line 852) | void
function x_update_display (line 872) | void
function Window_info (line 943) | Window_info *
function x_send_copy_data (line 967) | void
function x_handle_copy (line 976) | void
function x_handle_targets (line 993) | void
function x_request_paste_data (line 1010) | void
function x_handle_paste (line 1022) | void
function x_update_mouse (line 1062) | int
function x_input_events (line 1089) | void
function x_hide_pointer (line 1329) | void
function x_handle_keysym (line 1339) | void
function x_keysym_to_a2code (line 1446) | int
function x_update_modifier_state (line 1471) | void
function x_auto_repeat_on (line 1489) | void
function x_auto_repeat_off (line 1500) | void
function x_full_screen (line 1511) | void
Condensed preview — 178 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,892K chars).
[
{
"path": ".gitignore",
"chars": 5,
"preview": "*.o\n\n"
},
{
"path": "CLAUDE.md",
"chars": 4212,
"preview": "# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## "
},
{
"path": "LICENSE",
"chars": 35149,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "README.md",
"chars": 324,
"preview": "# gsplus\nCross-platform Apple IIgs emulator and tools based on KEGS\n\n\n### About Branches\n- KEGS latest is tracked in `./"
},
{
"path": "TODO.md",
"chars": 356,
"preview": "# TODO\n\n## Backlog\n\n- [ ] Remove `#ifdef INCLUDE_RCSID_C` / `#endif` guards from header files and `#define`/`#undef INCL"
},
{
"path": "gsplus/lib/make_mac_icon",
"chars": 1301,
"preview": "#!/usr/bin/perl -w\n\n# Based on https://gist.github.com/ansarizafar/6fa64f44aa933794c4d6638eec32b9aa\n# and https://github"
},
{
"path": "gsplus/src/AppDelegate.swift",
"chars": 11069,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/Info.plist",
"chars": 1492,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "gsplus/src/Kegs-Bridging-Header.h",
"chars": 193,
"preview": "// $KmKId: Kegs-Bridging-Header.h,v 1.1 2019-10-14 22:33:09+00 kentd Exp $\n// Use this file to import your target's pub"
},
{
"path": "gsplus/src/MainView.swift",
"chars": 12939,
"preview": "// $KmKId: MainView.swift,v 1.42 2024-09-15 13:55:35+00 kentd Exp $\n\n//\tCopyright 2019-2024 by Kent Dickey\n//\tThis code "
},
{
"path": "gsplus/src/Makefile",
"chars": 3231,
"preview": "# $KmKId: makefile,v 1.48 2025-04-28 15:12:19+00 kentd Exp $\n\nXOPTS_WIN = -Wall -fomit-frame-pointer -march=pentium\n\nSWI"
},
{
"path": "gsplus/src/adb.c",
"chars": 53248,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/applesingle.c",
"chars": 9874,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/clock.c",
"chars": 8776,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/comp_swift",
"chars": 466,
"preview": "#!/bin/bash\n# $KmKId: comp_swift,v 1.2 2020-12-11 22:58:32+00 kentd Exp $\n\necho \"args are: \" \"$@\"\n/Applications/Xcode.ap"
},
{
"path": "gsplus/src/compile_time.c",
"chars": 62,
"preview": "char g_compile_time[] = \"Compiled: \" __DATE__ \" \" __TIME__ ;\n\n"
},
{
"path": "gsplus/src/config.c",
"chars": 113616,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/config.h",
"chars": 1158,
"preview": "#ifdef INCLUDE_RCSID_C\n#endif\n\n/**********************************************************************/\n/* "
},
{
"path": "gsplus/src/cp_gsplus_libs",
"chars": 952,
"preview": "#!/usr/bin/perl -w\n# $KmKId: cp_kegs_libs,v 1.2 2021-02-09 00:35:48+00 kentd Exp $\n\nuse strict;\nuse English;\n\nif($#ARGV "
},
{
"path": "gsplus/src/debugger.c",
"chars": 50114,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/defc.h",
"chars": 8415,
"preview": "#ifdef INCLUDE_RCSID_C\n#endif\n\n/**********************************************************************/\n/* "
},
{
"path": "gsplus/src/defcomm.h",
"chars": 4599,
"preview": "#ifdef INCLUDE_RCSID_C\nconst char rcsdif_defcomm_h[] = \"@(#)$KmKId: defcomm.h,v 1.109 2023-11-12 15:29:41+00 kentd Exp $"
},
{
"path": "gsplus/src/defs_instr.h",
"chars": 15849,
"preview": "// $KmKId: defs_instr.h,v 1.70 2023-11-05 16:22:26+00 kentd Exp $\n\n/****************************************************"
},
{
"path": "gsplus/src/dependency",
"chars": 2282,
"preview": "adb.o: adb.c defc.h defcomm.h iwm.h protos.h protos_base.h\nengine_c.o: engine_c.c defc.h defcomm.h iwm.h protos.h protos"
},
{
"path": "gsplus/src/disas.h",
"chars": 8441,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/doc.c",
"chars": 26216,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/dyna_filt.c",
"chars": 841,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/dyna_type.c",
"chars": 7763,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/dyna_validate.c",
"chars": 11697,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/dynapro.c",
"chars": 62001,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/engine.h",
"chars": 2189,
"preview": "// \"@(#)$KmKId: engine.h,v 1.9 2023-09-11 12:55:16+00 kentd Exp $\"\n\n/***************************************************"
},
{
"path": "gsplus/src/engine_c.c",
"chars": 23543,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/instable.h",
"chars": 24828,
"preview": "// \"@(#)$KmKId: instable.h,v 1.121 2023-11-12 15:31:14+00 kentd Exp $\"\n\n/***********************************************"
},
{
"path": "gsplus/src/iwm.c",
"chars": 93127,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/iwm.h",
"chars": 5341,
"preview": "#ifdef INCLUDE_RCSID_C\n#endif\n\n/**********************************************************************/\n/* "
},
{
"path": "gsplus/src/joystick_driver.c",
"chars": 12257,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/kegsfont.h",
"chars": 20806,
"preview": "/* $KmKId: kegsfont.h,v 1.1 2002-11-10 03:31:51-05 kadickey Exp $ */\n\n/* char 0x00 (raw 0x40) */\n\t{ 0xc7, 0xbb, 0xab, 0"
},
{
"path": "gsplus/src/kegswin.sln",
"chars": 1436,
"preview": "\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio Version 17\r\nVisualStudioVersion = 17.0.3"
},
{
"path": "gsplus/src/kegswin.vcxproj",
"chars": 8152,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/ms"
},
{
"path": "gsplus/src/ldvars",
"chars": 343,
"preview": "OBJECTS = adb.o engine_c.o clock.o config.o debugger.o scc.o scc_socket_driver.o scc_windriver.o scc_unixdriver.o iwm.o "
},
{
"path": "gsplus/src/macsnd_driver.c",
"chars": 8083,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/mockingboard.c",
"chars": 19896,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/moremem.c",
"chars": 57171,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/op_routs.h",
"chars": 3270,
"preview": "// $KmKId: op_routs.h,v 1.47 2023-11-05 16:21:51+00 kentd Exp $\n\n/******************************************************"
},
{
"path": "gsplus/src/paddles.c",
"chars": 4581,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/protos.h",
"chars": 714,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/protos_base.h",
"chars": 41287,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/protos_macdriver.h",
"chars": 2088,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/protos_macsnd_driver.h",
"chars": 766,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/protos_pulseaudio_driver.h",
"chars": 977,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/protos_windriver.h",
"chars": 2508,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/protos_xdriver.h",
"chars": 2321,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/pulseaudio_driver.c",
"chars": 9483,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/scc.c",
"chars": 31382,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/scc.h",
"chars": 2707,
"preview": "#ifdef INCLUDE_RCSID_C\n#endif\n\n/**********************************************************************/\n/* "
},
{
"path": "gsplus/src/scc_socket_driver.c",
"chars": 30518,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/scc_unixdriver.c",
"chars": 4787,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/scc_windriver.c",
"chars": 6112,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/sim65816.c",
"chars": 47603,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/size_c.h",
"chars": 8363,
"preview": "// \"@(#)$KmKId: size_c.h,v 1.2 2023-11-12 15:32:17+00 kentd Exp $\"\n/****************************************************"
},
{
"path": "gsplus/src/smartport.c",
"chars": 21060,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/sound.c",
"chars": 26030,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/sound.h",
"chars": 2466,
"preview": "#ifdef INCLUDE_RCSID_C\n#endif\n\n/**********************************************************************/\n/* "
},
{
"path": "gsplus/src/sound_driver.c",
"chars": 11952,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/style_check",
"chars": 2977,
"preview": "#!/usr/bin/perl -w\n# $KmKId: style_check,v 1.1 2020-06-14 02:52:13+00 kentd Exp $\n\n# Perl script to check for coding con"
},
{
"path": "gsplus/src/undeflate.c",
"chars": 37529,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/unshk.c",
"chars": 14917,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/vars",
"chars": 101,
"preview": "TARGET = gsplus\nOBJECTS1 = macsnd_driver.o\nCCOPTS = -Wall -O2 -DMAC\nSUFFIX =\nNAME = gsplus\n\nXOPTS =\n\n"
},
{
"path": "gsplus/src/vars_mac",
"chars": 101,
"preview": "TARGET = gsplus\nOBJECTS1 = macsnd_driver.o\nCCOPTS = -Wall -O2 -DMAC\nSUFFIX =\nNAME = gsplus\n\nXOPTS =\n\n"
},
{
"path": "gsplus/src/vars_mac_x",
"chars": 222,
"preview": "TARGET = gsplus\nOBJECTS1 = macsnd_driver.o xdriver.o\nCCOPTS = -O2 -DMAC -Wall -I/usr/X11/include\nSUFFIX =\nNAME = gsplus\n"
},
{
"path": "gsplus/src/vars_x86linux",
"chars": 212,
"preview": "TARGET = gsplus\nOBJECTS1 = pulseaudio_driver.o xdriver.o\nCCOPTS = -O2 -Wall -fomit-frame-pointer -DPULSE_AUDIO\nNAME = gs"
},
{
"path": "gsplus/src/video.c",
"chars": 75967,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/voc.c",
"chars": 5938,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/win32snd_driver.c",
"chars": 7957,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/win_dirent.h",
"chars": 1042,
"preview": "#ifdef INCLUDE_RCSID_C\n#endif\n\n/**********************************************************************/\n/* "
},
{
"path": "gsplus/src/windriver.c",
"chars": 26259,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/woz.c",
"chars": 27752,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "gsplus/src/xdriver.c",
"chars": 37857,
"preview": "/**********************************************************************/\n/* GSplus - Apple //gs Emula"
},
{
"path": "upstream/KEGS.version",
"chars": 10,
"preview": "kegs.1.38\n"
},
{
"path": "upstream/kegs/config.kegs",
"chars": 135,
"preview": "# KEGS configuration file version 1.07\n\ns5d1 = XMAS_DEMO.gz\ns5d2 =\n\ns6d1 = #dos33.dsk\ns6d2 = \n\ns7d1 = NUCLEUS03.gz\n\ng_li"
},
{
"path": "upstream/kegs/doc/CHANGES.txt",
"chars": 37461,
"preview": "\nChanges in KEGS v1.38 since v1.35 (04/29/25)\n- Improve serial port handling so BBS'es like GBBS and Warp6 run.\n- Fix a "
},
{
"path": "upstream/kegs/doc/COPYING.txt",
"chars": 35150,
"preview": "\n GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free"
},
{
"path": "upstream/kegs/doc/INTERNALS.iwm.txt",
"chars": 10859,
"preview": "// $Id: INTERNALS.iwm.txt,v 1.3 2021/10/03 19:44:15 kentd Exp $\n\nKEGS's Apple IIgs IWM emulation routines.\n\nThe IWM code"
},
{
"path": "upstream/kegs/doc/INTERNALS.overview.txt",
"chars": 4125,
"preview": "\nKEGS Internals\n--------------\n\nThe INTERNALS* files describe the internal structure of KEGS and how\nit works. It is me"
},
{
"path": "upstream/kegs/doc/INTERNALS.video.txt",
"chars": 2967,
"preview": "\nThe video.c code in KEGS is responsible for handling the Apple IIgs video\nmodes.\n\nA detailed description of how Apple I"
},
{
"path": "upstream/kegs/doc/INTERNALS.xdriver.txt",
"chars": 7563,
"preview": "\nxdriver.c contains the routines for interfacing to X windows. The rest\nof KEGS interacts with X windows only through x"
},
{
"path": "upstream/kegs/doc/README.ROM.files.txt",
"chars": 3625,
"preview": "\nPlace a ROM, ROM.01 or ROM.03 file in your home directory, or in the\ndirectory you run KEGS from, or in the directory y"
},
{
"path": "upstream/kegs/doc/README.a2.compatibility.txt",
"chars": 7033,
"preview": "# $Id: README.a2.compatibility.txt,v 1.6 2021/06/26 16:54:23 kentd Exp $\n\nBard's Tale II GS: Problem: Doesn't recognize "
},
{
"path": "upstream/kegs/doc/README.compile.txt",
"chars": 5120,
"preview": "# $Id: README.compile.txt,v 1.26 2023/06/14 02:56:10 kentd Exp $\n\nGeneral build instructions:\n--------------------------"
},
{
"path": "upstream/kegs/doc/README.dynapro.txt",
"chars": 4604,
"preview": "\nDYNAPRO \n-------\n\nDynapro is a KEGS feature where an emulated disk (140KB 5.25\" in slot 6, 800KB\n3.5\" in slot 5, or any"
},
{
"path": "upstream/kegs/doc/README.kegs.txt",
"chars": 43864,
"preview": "\nKEGS: Kent's Emulated GS version 1.34\nhttp://kegs.sourceforge.net/\n\nWhat is this?\n-------------\n\nKEGS is an Apple IIgs "
},
{
"path": "upstream/kegs/doc/README.linux.partitions.txt",
"chars": 13324,
"preview": "[ This info provided by Mike Thomas <phoenyx@texas.net> ]\n[ Updated 10/30/2003 by Kent: This file mentions editing \"kegs"
},
{
"path": "upstream/kegs/doc/README.mac.txt",
"chars": 2701,
"preview": "\nMAC OS X port of KEGS (KEGSMAC): http://kegs.sourceforge.net\n----------------------------------------------------------"
},
{
"path": "upstream/kegs/doc/README.serial.ports.txt",
"chars": 6097,
"preview": "\nKEGS documentation: Serial Ports\n\nSCC (Serial Port) emulation:\n---------------------------\n\nKEGS emulates the two seria"
},
{
"path": "upstream/kegs/doc/README.win32.txt",
"chars": 1976,
"preview": "\nHow to compile KEGS for Windows\n-------------------------------\n\nGo to the src/ directory in the KEGS release, and doub"
},
{
"path": "upstream/kegs/lib/make_mac_icon",
"chars": 1301,
"preview": "#!/usr/bin/perl -w\n\n# Based on https://gist.github.com/ansarizafar/6fa64f44aa933794c4d6638eec32b9aa\n# and https://github"
},
{
"path": "upstream/kegs/src/AppDelegate.swift",
"chars": 10648,
"preview": "// $KmKId: AppDelegate.swift,v 1.32 2024-09-15 13:55:35+00 kentd Exp $\n\n//\tCopyright 2019-2024 by Kent Dickey\n//\tThis co"
},
{
"path": "upstream/kegs/src/Info.plist",
"chars": 1545,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "upstream/kegs/src/Kegs-Bridging-Header.h",
"chars": 193,
"preview": "// $KmKId: Kegs-Bridging-Header.h,v 1.1 2019-10-14 22:33:09+00 kentd Exp $\n// Use this file to import your target's pub"
},
{
"path": "upstream/kegs/src/MainView.swift",
"chars": 12939,
"preview": "// $KmKId: MainView.swift,v 1.42 2024-09-15 13:55:35+00 kentd Exp $\n\n//\tCopyright 2019-2024 by Kent Dickey\n//\tThis code "
},
{
"path": "upstream/kegs/src/Makefile",
"chars": 3373,
"preview": "# $KmKId: makefile,v 1.48 2025-04-28 15:12:19+00 kentd Exp $\n\nXOPTS_WIN = -Wall -fomit-frame-pointer -march=pentium\n\nSWI"
},
{
"path": "upstream/kegs/src/adb.c",
"chars": 53220,
"preview": "const char rcsid_adb_c[] = \"@(#)$KmKId: adb.c,v 1.116 2024-09-15 13:56:12+00 kentd Exp $\";\n\n/***************************"
},
{
"path": "upstream/kegs/src/applesingle.c",
"chars": 9854,
"preview": "const char rcsid_applesing_c[] = \"@(#)$KmKId: applesingle.c,v 1.5 2021-12-19 04:14:31+00 kentd Exp $\";\n\n/***************"
},
{
"path": "upstream/kegs/src/clock.c",
"chars": 8751,
"preview": "const char rcsid_clock_c[] = \"@(#)$KmKId: clock.c,v 1.40 2023-09-23 17:51:22+00 kentd Exp $\";\n\n/************************"
},
{
"path": "upstream/kegs/src/comp_swift",
"chars": 466,
"preview": "#!/bin/bash\n# $KmKId: comp_swift,v 1.2 2020-12-11 22:58:32+00 kentd Exp $\n\necho \"args are: \" \"$@\"\n/Applications/Xcode.ap"
},
{
"path": "upstream/kegs/src/compile_time.c",
"chars": 174,
"preview": "\nconst char rcsid_compile_time_c[] = \"@(#)$KmKId: compile_time.c,v 1.2 2002-11-14 06:02:44+00 kadickey Exp $\";\n\nchar g_c"
},
{
"path": "upstream/kegs/src/config.c",
"chars": 113594,
"preview": "const char rcsid_config_c[] = \"@(#)$KmKId: config.c,v 1.169 2025-01-11 23:42:49+00 kentd Exp $\";\n\n/*********************"
},
{
"path": "upstream/kegs/src/config.h",
"chars": 1134,
"preview": "#ifdef INCLUDE_RCSID_C\nconst char rcsid_config_h[] = \"@(#)$KmKId: config.h,v 1.12 2023-08-28 01:59:55+00 kentd Exp $\";\n#"
},
{
"path": "upstream/kegs/src/cp_kegs_libs",
"chars": 952,
"preview": "#!/usr/bin/perl -w\n# $KmKId: cp_kegs_libs,v 1.2 2021-02-09 00:35:48+00 kentd Exp $\n\nuse strict;\nuse English;\n\nif($#ARGV "
},
{
"path": "upstream/kegs/src/debugger.c",
"chars": 50095,
"preview": "const char rcsid_debugger_c[] = \"@(#)$KmKId: debugger.c,v 1.60 2023-09-11 12:55:28+00 kentd Exp $\";\n\n/******************"
},
{
"path": "upstream/kegs/src/defc.h",
"chars": 8388,
"preview": "#ifdef INCLUDE_RCSID_C\nconst char rcsid_defc_h[] = \"@(#)$KmKId: defc.h,v 1.142 2024-09-15 13:56:12+00 kentd Exp $\";\n#end"
},
{
"path": "upstream/kegs/src/defcomm.h",
"chars": 4479,
"preview": "#ifdef INCLUDE_RCSID_C\nconst char rcsdif_defcomm_h[] = \"@(#)$KmKId: defcomm.h,v 1.109 2023-11-12 15:29:41+00 kentd Exp $"
},
{
"path": "upstream/kegs/src/defs_instr.h",
"chars": 15729,
"preview": "// $KmKId: defs_instr.h,v 1.70 2023-11-05 16:22:26+00 kentd Exp $\n\n/****************************************************"
},
{
"path": "upstream/kegs/src/dependency",
"chars": 2282,
"preview": "adb.o: adb.c defc.h defcomm.h iwm.h protos.h protos_base.h\nengine_c.o: engine_c.c defc.h defcomm.h iwm.h protos.h protos"
},
{
"path": "upstream/kegs/src/disas.h",
"chars": 8416,
"preview": "const char rcsid_disas_h[] = \"@(#)$KmKId: disas.h,v 1.12 2020-06-17 02:25:23+00 kentd Exp $\";\n\n/************************"
},
{
"path": "upstream/kegs/src/doc.c",
"chars": 26186,
"preview": "const char rcsid_doc_c[] = \"@(#)$KmKId: doc.c,v 1.2 2023-06-05 18:59:51+00 kentd Exp $\";\n\n/*****************************"
},
{
"path": "upstream/kegs/src/dyna_filt.c",
"chars": 818,
"preview": "const char rcsid_dynafilt_c[] = \"@(#)$KmKId: dyna_filt.c,v 1.1 2021-08-09 03:13:55+00 kentd Exp $\";\n\n/******************"
},
{
"path": "upstream/kegs/src/dyna_type.c",
"chars": 7744,
"preview": "const char rcsid_dynatype_c[] = \"@(#)$KmKId: dyna_type.c,v 1.9 2023-05-19 13:52:30+00 kentd Exp $\";\n\n/******************"
},
{
"path": "upstream/kegs/src/dyna_validate.c",
"chars": 11687,
"preview": "const char rcsid_dyna_validate_c[] = \"@(#)$KmKId: dyna_validate.c,v 1.8 2023-05-21 20:06:24+00 kentd Exp $\";\n\n/*********"
},
{
"path": "upstream/kegs/src/dynapro.c",
"chars": 61980,
"preview": "const char rcsid_dynapro_c[] = \"@(#)$KmKId: dynapro.c,v 1.49 2023-09-23 17:53:24+00 kentd Exp $\";\n\n/********************"
},
{
"path": "upstream/kegs/src/engine.h",
"chars": 2069,
"preview": "// \"@(#)$KmKId: engine.h,v 1.9 2023-09-11 12:55:16+00 kentd Exp $\"\n\n/***************************************************"
},
{
"path": "upstream/kegs/src/engine_c.c",
"chars": 23524,
"preview": "const char rcsid_engine_c_c[] = \"@(#)$KmKId: engine_c.c,v 1.99 2025-04-27 18:54:08+00 kentd Exp $\";\n\n/******************"
},
{
"path": "upstream/kegs/src/instable.h",
"chars": 24708,
"preview": "// \"@(#)$KmKId: instable.h,v 1.121 2023-11-12 15:31:14+00 kentd Exp $\"\n\n/***********************************************"
},
{
"path": "upstream/kegs/src/iwm.c",
"chars": 93099,
"preview": "const char rcsid_iwm_c[] = \"@(#)$KmKId: iwm.c,v 1.207 2023-09-26 02:59:52+00 kentd Exp $\";\n\n/***************************"
},
{
"path": "upstream/kegs/src/iwm.h",
"chars": 5311,
"preview": "#ifdef INCLUDE_RCSID_C\nconst char rcsid_iwm_h[] = \"@(#)$KmKId: iwm.h,v 1.46 2023-09-23 17:53:09+00 kentd Exp $\";\n#endif\n"
},
{
"path": "upstream/kegs/src/joystick_driver.c",
"chars": 12252,
"preview": "const char rcsid_joystick_driver_c[] = \"@(#)$KmKId: joystick_driver.c,v 1.23 2023-09-26 02:59:00+00 kentd Exp $\";\n\n/****"
},
{
"path": "upstream/kegs/src/kegsfont.h",
"chars": 20806,
"preview": "/* $KmKId: kegsfont.h,v 1.1 2002-11-10 03:31:51-05 kadickey Exp $ */\n\n/* char 0x00 (raw 0x40) */\n\t{ 0xc7, 0xbb, 0xab, 0"
},
{
"path": "upstream/kegs/src/kegswin.sln",
"chars": 1436,
"preview": "\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio Version 17\r\nVisualStudioVersion = 17.0.3"
},
{
"path": "upstream/kegs/src/kegswin.vcxproj",
"chars": 8152,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/ms"
},
{
"path": "upstream/kegs/src/ldvars",
"chars": 343,
"preview": "OBJECTS = adb.o engine_c.o clock.o config.o debugger.o scc.o scc_socket_driver.o scc_windriver.o scc_unixdriver.o iwm.o "
},
{
"path": "upstream/kegs/src/macsnd_driver.c",
"chars": 8074,
"preview": "const char rcsid_macsnd_driver_c[] = \"@(#)$KmKId: macsnd_driver.c,v 1.20 2022-04-03 13:38:47+00 kentd Exp $\";\n\n/********"
},
{
"path": "upstream/kegs/src/mockingboard.c",
"chars": 19885,
"preview": "const char rcsid_mockingboard_c[] = \"@(#)$KmKId: mockingboard.c,v 1.26 2023-06-13 16:54:18+00 kentd Exp $\";\n\n/**********"
},
{
"path": "upstream/kegs/src/moremem.c",
"chars": 57151,
"preview": "const char rcsid_moremem_c[] = \"@(#)$KmKId: moremem.c,v 1.306 2024-09-15 13:56:12+00 kentd Exp $\";\n\n/*******************"
},
{
"path": "upstream/kegs/src/op_routs.h",
"chars": 3150,
"preview": "// $KmKId: op_routs.h,v 1.47 2023-11-05 16:21:51+00 kentd Exp $\n\n/******************************************************"
},
{
"path": "upstream/kegs/src/paddles.c",
"chars": 4560,
"preview": "const char rcsid_paddles_c[] = \"@(#)$KmKId: paddles.c,v 1.21 2023-05-19 13:52:54+00 kentd Exp $\";\n\n/********************"
},
{
"path": "upstream/kegs/src/protos.h",
"chars": 691,
"preview": "/************************************************************************/\n/*\t\t\tKEGS: Apple //gs Emulator\t\t\t*/\n/*\t\t\tCopy"
},
{
"path": "upstream/kegs/src/protos_base.h",
"chars": 41274,
"preview": "/************************************************************************/\n/*\t\t\tKEGS: Apple //gs Emulator\t\t\t*/\n/*\t\t\tCopy"
},
{
"path": "upstream/kegs/src/protos_macdriver.h",
"chars": 2078,
"preview": "/************************************************************************/\n/*\t\t\tKEGS: Apple //gs Emulator\t\t\t*/\n/*\t\t\tCopy"
},
{
"path": "upstream/kegs/src/protos_macsnd_driver.h",
"chars": 769,
"preview": "/************************************************************************/\n/*\t\t\tKEGS: Apple //gs Emulator\t\t\t*/\n/*\t\t\tCopy"
},
{
"path": "upstream/kegs/src/protos_pulseaudio_driver.h",
"chars": 988,
"preview": "/************************************************************************/\n/*\t\t\tKEGS: Apple //gs Emulator\t\t\t*/\n/*\t\t\tCopy"
},
{
"path": "upstream/kegs/src/protos_windriver.h",
"chars": 2388,
"preview": "/************************************************************************/\n/*\t\t\tKEGS: Apple //gs Emulator\t\t\t*/\n/*\t\t\tCopy"
},
{
"path": "upstream/kegs/src/protos_xdriver.h",
"chars": 2307,
"preview": "/************************************************************************/\n/*\t\t\tKEGS: Apple //gs Emulator\t\t\t*/\n/*\t\t\tCopy"
},
{
"path": "upstream/kegs/src/pulseaudio_driver.c",
"chars": 9482,
"preview": "const char rcsid_pulseaudio_driver_c[] = \"@(#)$KmKId: pulseaudio_driver.c,v 1.10 2021-12-16 22:41:59+00 kentd Exp $\";\n\n/"
},
{
"path": "upstream/kegs/src/scc.c",
"chars": 31353,
"preview": "const char rcsid_scc_c[] = \"@(#)$KmKId: scc.c,v 1.74 2025-04-29 22:17:05+00 kentd Exp $\";\n\n/****************************"
},
{
"path": "upstream/kegs/src/scc.h",
"chars": 2677,
"preview": "#ifdef INCLUDE_RCSID_C\nconst char rcsid_scc_h[] = \"@(#)$KmKId: scc.h,v 1.27 2025-01-11 18:45:06+00 kentd Exp $\";\n#endif\n"
},
{
"path": "upstream/kegs/src/scc_socket_driver.c",
"chars": 30517,
"preview": "const char rcsid_scc_socket_driver_c[] = \"@(#)$KmKId: scc_socket_driver.c,v 1.37 2025-04-29 22:17:38+00 kentd Exp $\";\n\n/"
},
{
"path": "upstream/kegs/src/scc_unixdriver.c",
"chars": 4778,
"preview": "const char rcsid_scc_macdriver_c[] = \"@(#)$KmKId: scc_unixdriver.c,v 1.4 2025-01-07 16:45:35+00 kentd Exp $\";\n\n/********"
},
{
"path": "upstream/kegs/src/scc_windriver.c",
"chars": 6103,
"preview": "const char rcsid_scc_windriver_c[] = \"@(#)$KmKId: scc_windriver.c,v 1.13 2023-08-28 18:11:05+00 kentd Exp $\";\n\n/********"
},
{
"path": "upstream/kegs/src/sim65816.c",
"chars": 47585,
"preview": "const char rcsid_sim65816_c[] = \"@(#)$KmKId: sim65816.c,v 1.491 2025-04-27 18:03:43+00 kentd Exp $\";\n\n/*****************"
},
{
"path": "upstream/kegs/src/size_c.h",
"chars": 8243,
"preview": "// \"@(#)$KmKId: size_c.h,v 1.2 2023-11-12 15:32:17+00 kentd Exp $\"\n/****************************************************"
},
{
"path": "upstream/kegs/src/smartport.c",
"chars": 21043,
"preview": "const char rcsid_smartport_c[] = \"@(#)$KmKId: smartport.c,v 1.61 2024-09-15 13:53:46+00 kentd Exp $\";\n\n/****************"
},
{
"path": "upstream/kegs/src/sound.c",
"chars": 26006,
"preview": "const char rcsid_sound_c[] = \"@(#)$KmKId: sound.c,v 1.155 2023-08-19 17:45:33+00 kentd Exp $\";\n\n/***********************"
},
{
"path": "upstream/kegs/src/sound.h",
"chars": 2440,
"preview": "#ifdef INCLUDE_RCSID_C\nconst char rcsid_sound_h[] = \"@(#)$KmKId: sound.h,v 1.31 2023-05-04 19:35:29+00 kentd Exp $\";\n#en"
},
{
"path": "upstream/kegs/src/sound_driver.c",
"chars": 11941,
"preview": "const char rcsid_sound_driver_c[] = \"@(#)$KmKId: sound_driver.c,v 1.32 2023-06-05 18:41:09+00 kentd Exp $\";\n\n/**********"
},
{
"path": "upstream/kegs/src/style_check",
"chars": 2977,
"preview": "#!/usr/bin/perl -w\n# $KmKId: style_check,v 1.1 2020-06-14 02:52:13+00 kentd Exp $\n\n# Perl script to check for coding con"
},
{
"path": "upstream/kegs/src/undeflate.c",
"chars": 37512,
"preview": "const char rcsid_undeflate_c[] = \"@(#)$KmKId: undeflate.c,v 1.20 2023-09-26 00:20:53+00 kentd Exp $\";\n\n/****************"
},
{
"path": "upstream/kegs/src/unshk.c",
"chars": 14892,
"preview": "const char rcsid_unshk_c[] = \"@(#)$KmKId: unshk.c,v 1.14 2023-05-19 13:57:52+00 kentd Exp $\";\n\n/************************"
},
{
"path": "upstream/kegs/src/vars",
"chars": 104,
"preview": "\nTARGET = kegsmac\nOBJECTS1 = macsnd_driver.o\nCCOPTS = -Wall -O2 -DMAC\nSUFFIX =\nNAME = kegsmac\n\nXOPTS =\n\n"
},
{
"path": "upstream/kegs/src/vars_mac",
"chars": 104,
"preview": "\nTARGET = kegsmac\nOBJECTS1 = macsnd_driver.o\nCCOPTS = -Wall -O2 -DMAC\nSUFFIX =\nNAME = kegsmac\n\nXOPTS =\n\n"
},
{
"path": "upstream/kegs/src/vars_mac_x",
"chars": 221,
"preview": "\nTARGET = xkegs\nOBJECTS1 = macsnd_driver.o xdriver.o\nCCOPTS = -O2 -DMAC -Wall -I/usr/X11/include\nSUFFIX =\nNAME = xkegs\n\n"
},
{
"path": "upstream/kegs/src/vars_x86linux",
"chars": 211,
"preview": "\nTARGET = xkegs\nOBJECTS1 = pulseaudio_driver.o xdriver.o\nCCOPTS = -O2 -Wall -fomit-frame-pointer -DPULSE_AUDIO\nNAME = xk"
},
{
"path": "upstream/kegs/src/video.c",
"chars": 75943,
"preview": "const char rcsid_video_c[] = \"@(#)$KmKId: video.c,v 1.213 2025-04-27 18:03:43+00 kentd Exp $\";\n\n/***********************"
},
{
"path": "upstream/kegs/src/voc.c",
"chars": 5909,
"preview": "const char rcsid_voc_c[] = \"@(#)$KmKId: voc.c,v 1.12 2023-09-23 17:52:44+00 kentd Exp $\";\n\n/****************************"
},
{
"path": "upstream/kegs/src/win32snd_driver.c",
"chars": 7952,
"preview": "const char rcsid_win32snd_driver_c[] = \"@(#)$KmKId: win32snd_driver.c,v 1.12 2023-05-19 14:01:33+00 kentd Exp $\";\n\n/****"
},
{
"path": "upstream/kegs/src/win_dirent.h",
"chars": 1025,
"preview": "#ifdef INCLUDE_RCSID_C\nconst char rcsid_kegswin_dirent_h[] = \"@(#)$KmKId: win_dirent.h,v 1.2 2022-02-11 04:13:45+00 kent"
},
{
"path": "upstream/kegs/src/windriver.c",
"chars": 26242,
"preview": "const char rcsid_windriver_c[] = \"@(#)$KmKId: windriver.c,v 1.26 2024-09-15 13:55:35+00 kentd Exp $\";\n\n/****************"
},
{
"path": "upstream/kegs/src/woz.c",
"chars": 27723,
"preview": "const char rcsid_woz_c[] = \"@(#)$KmKId: woz.c,v 1.34 2025-01-07 16:45:35+00 kentd Exp $\";\n\n/****************************"
},
{
"path": "upstream/kegs/src/xdriver.c",
"chars": 37837,
"preview": "const char rcsid_xdriver_c[] = \"@(#)$KmKId: xdriver.c,v 1.244 2025-01-07 16:40:09+00 kentd Exp $\";\n\n/*******************"
}
]
// ... and 10 more files (download for full content)
About this extraction
This page contains the full source code of the digarok/gsplus GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 178 files (2.5 MB), approximately 660.5k tokens, and a symbol index with 1754 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.