initial commit

This commit is contained in:
Dagen Brock 2015-11-05 14:23:46 -06:00
commit c3c2db5eb5
388 changed files with 124326 additions and 0 deletions

1
.svn/entries Normal file
View File

@ -0,0 +1 @@
12

1
.svn/format Normal file
View File

@ -0,0 +1 @@
12

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
#!/usr/local/bin/perl -w
# $KmKId: make_inst,v 1.5 2002-11-07 08:18:16-08 kadickey Exp $
$is_c = shift;
$repl = shift;
$count = 0;
while(<>) {
$line = $_;
if(/^inst(..)_SYM(.*)$/) {
if($is_c eq "c") {
if($count > 0) {
printf("\tbreak;\n");
}
print "case 0x$1: $2\n";
$count++;
} else {
print "\t.align\t8\n";
print "inst" . "$1" . "_$repl" . "$2\n";
}
} elsif(/^(.*)_SYM(.*)$/) {
print "$1" . "_$repl" . "$2\n";
} else {
print $line;
}
}
# if(/^inst(..)_SYM (.*)$/) {
# print "OPCODE($1) /* $2 */\n";
# } else if(/^(

View File

@ -0,0 +1,241 @@
-----
Developing GSport
-----
David Schmidt (david__schmidt at users dot souceforge dot net)
-----
Developing GSport
Information, mostly concerning building, about various platforms:
* General Build Instructions
You need to build with a <<<make>>> utility.
There's a default Makefile, which should work for nearly any environment.
The Makefile includes a file called <<<vars>>> which defines the platform-
dependent variables. You need to make <<<vars>>> point to (or be) the appropriate
file for your machine.
* Win32
There is a different port of KEGS by Chea Chee Keong (akilgard) called
KEGS32. It was originally available from {{{http://web.archive.org/web/20071107082448/http://www.geocities.com/akilgard/kegs32/}http://www.geocities.com/akilgard/kegs32}},
but geocities has since closed.
The Win32 code in GSport is leveraged from KEGS32.
GSport can be compiled with {{{http://www.mingw.org/}Mingw}}
and {{{http://www.cygwin.com/}Cygwin}} as well as via standard Microsoft compiler suites.
In order to compile with Cygwin:
------------------
cd into the src/ directory
rm vars
ln -s vars_win32 vars
make
------------------
You need to have a ROM file (named
ROM, ROM.01, or ROM.03) in the same directory as the resulting executable.
To quit, either click the close box, or force quit the application.
You can also middle-click (if you have a 3-button mouse) or
Shift-F6 to get the debugger in the terminal window, and then type "q".
* Mac OS X
Use the <<<vars_mac>>> file:
-------------------------------------
cd into the src/ directory
rm vars; ln -s vars_mac vars
make
-------------------------------------
After the <<<make>>> has finished, it will create the application <<<GSport>>>.
* X86 Linux
Use the <<<vars_x86linux>>> file:
-------------------------------------
cd into the src/ directory
rm vars; ln -s vars_x86linux vars
make
-------------------------------------
The resulting executable is called <<<gsportx>>>.
The build scripts assume perl is in your path. If it is somewhere else,
you need to edit the "PERL = perl" line in the vars file and make it point
to the correct place.
For audio, GSport needs access to <<</dev/dsp>>>. If the permissions do not allow
GSport to access <<</dev/dsp>>>, it can fail with a cryptic error message. As root,
just do: <<<chmod 666 /dev/dsp>>> .
If you do not have the <<</dev/dsp>>> device, GSport will not start unless you
tell it to disable audio with the following command-line argument:
<<<./gsportx -audio 0>>>
* PowerPC Linux
Use the <<<vars_linuxppc>>> file:
-------------
cd into the src/ directory
rm vars; ln -s vars_linuxppc vars
make
---------
The build scripts assume perl is in your path. If it is somewhere else,
you need to edit the "PERL = perl" line in the vars file and make it point
to the correct place.
Audio is currently disabled by default, but you can try turning it on
by runnning the command: <<<gsportx -audio 1>>>. It sounds horrible, but sounds do
come out.
* Raspberry Pi
At first, you may want to update/upgrade your base OS:
* <<<sudo apt-get update>>>
* <<<sudo apt-get upgrade>>>
[]
Then, add a line with the value <<<snd-pcm-oss>>> to the <<</etc/modules>>> file and reboot to enable sound.
Change the permissions to the resulting device <<</dev/pcm>>> (after rebooting): <<<sudo chmod 666 /dev/pcm>>>
Depending on the version of your OS, the following packages may need to be installed:
* xfonts-base: <<<sudo apt-get install xfonts-base>>>
* libX11-dev: <<<sudo apt-get install libX11-dev>>>
* libxext-dev: <<<sudo apt-get install libxext-dev>>>
* libpcap-dev: <<<sudo apt-get install libpcap-dev>>>
[]
Use the <<<vars_pi>>> file for compilation:
-------------
cd into the src/ directory
rm vars; ln -s vars_pi vars
make
---------
The resulting executable is called <<<gsportx>>>.
* Solaris SPARC
Use the <<<vars_solaris>>> file:
-------------------------------------
cd into the src/ directory
rm vars; ln -s vars_solaris vars
make
-------------------------------------
The build scripts assume perl is in your path. If it is somewhere else,
you need to edit the "PERL = perl" line in the vars file and make it point
to the correct place.
Audio is currently disabled by default, but you can try turning it on
by runnning the command: <<<gsportx -audio 1>>>
* Solaris x86
Use the <<<vars_x86solaris>>> file:
-------------------------------------
cd into the src/ directory
rm vars; ln -s vars_x86solaris vars
make
-------------------------------------
The build scripts assume perl is in your path. If it is somewhere else,
you need to edit the "PERL = perl" line in the vars file and make it point
to the correct place.
Audio is currently disabled by default, but you can try turning it on
by runnning the command: <<<gsportx -audio 1>>>
* Other platforms - "C"
If you are porting to an X-windows and Unix-based machine, it should be
easy. Start with <<<vars_x86linux>>> if you are a little-endian machine, or
<<<vars_linuxppc>>> if you are big endian. Don't define <<<-DGSPORT_LITTLE_ENDIAN>>>
unless your processor is little-endian (Alpha, x86, Mac Intel). Mac PPC, Sun, MIPS,
HP, Motorola, and IBM Power are big-endian.
* Under Development - Autotools Integration
With the autotools branch, the following sequence will
execute the build from the main directory:
----------------
autoreconf
automake --add-missing
autoheader
autoconf
sh configure
make
----------------
* Extended {Capabilities} by Platform
All platforms have a common core of capabilities:
* Base IIgs emulation
* Ensoniq sound emulation
* Virtual serial ports mapped to real hardware or IP-emulated ports
* Text and graphical printers
[]
The table below notes where the various builds differ in the support they have in the
code base now for various extended capabilities.
Turning the "No" boxes into "Yes" are all opportunities for contributions!
*-----:------:------:------+
|| <<Platform>> || <<Ethernet>> || <<Drag/Drop Disks>> || <<Clipboard Paste>>
*-----:------:------:------+
Linux | No | No | No |
*-----:------:------:------+
Macintosh | No | No | Yes |
*-----:------:------:------+
Windows | Yes | Yes | Yes |
*-----:------:------:------+
[]
* Building Graphical Printer Support
Until graphical parallel printer support is generally integrated into all builds, the following work needs to be done:
* Install Simple DirectMedia Layer ({{{http://www.libsdl.org/}SDL}}) and Freetype in your build environment - you'll need to link to their libraries
* Add the <<<-DHAVE_SDL>>> option to your <<<CCOPTS>>> and add the same (perhaps to a new) <<<CPPOPTS>>> in your <<<vars>>> file
* Add something like <<<-I/usr/include/freetype2>>> and <<<-I/usr/include/SDL>>> options to your <<<CCOPTS>>> and add the same (perhaps for a new) <<<CPPOPTS>>> in your <<<vars>>> file to point to the SDL and Freetype include files
* Include SDL and Freetype libraries to <<<EXTRA_LIBS>>> in your <<<vars>>> file (i.e. <<<EXTRA_LIBS = -lSDL -lfreetype>>>)
* Include the Win32 common dialog library to <<<EXTRA_LIBS>>> as part of your final linkage if you're on Windows (i.e. <<<EXTRA_LIBS = -lSDL -lfreetype -lcomdlg32>>>)
* After building, you'll need the file <<<parallel.rom>>> in the same directory that <<<config.txt>>> is found
* You'll probably want a monospaced TrueType font file easily accessible to add as part of the GSport configuration
* Run through the emulated printer {{{./printer.html}configuration}} steps
[]

View File

@ -0,0 +1,76 @@
/*
make_inst.cmd:
Translation of the make_inst perl script and makefile to rexx for OS/2
8inst_s.h: instable.h
$(PERL) make_inst s 8 instable.h > 8inst_s.h
16inst_s.h: instable.h
$(PERL) make_inst s 16 instable.h > 16inst_s.h
8inst_c.h: instable.h
$(PERL) make_inst c 8 instable.h > 8inst_c.h
16inst_c.h: instable.h
$(PERL) make_inst c 16 instable.h > 16inst_c.h
*/
count = 0;
FileNameIn = "..\..\instable.h"
FileNameOut8s = "..\..\8inst_s.h"
FileNameOut8c = "..\..\8inst_c.h"
FileNameOut16s = "..\..\16inst_s.h"
FileNameOut16c = "..\..\16inst_c.h"
DEL FileNameOut8s
DEL FileNameOut8c
DEL FileNameOut16s
DEL FileNameOut16c
crud = STREAM(FileNameIn,"C","open read")
crud = STREAM(FileNameOut8s,"C","open write")
crud = STREAM(FileNameOut8c,"C","open write")
crud = STREAM(FileNameOut16s,"C","open write")
crud = STREAM(FileNameOut16c,"C","open write")
Do while (STREAM(FileNameIn,"S") = "READY")
line = LINEIN(FileNameIn);
SymPos = POS("_SYM",line)
if (SymPos > 0) Then
Do
if POS("inst",line) > 0 Then
Do
if (count > 0) Then
Do
crud = LINEOUT(FileNameOut8c," break;");
crud = LINEOUT(FileNameOut16c," break;");
End
newline = "case 0x"SUBSTR(line,SymPos-2,2)": "SUBSTR(line,SymPos+4)
crud = LINEOUT(FileNameOut8c, newline);
crud = LINEOUT(FileNameOut16c, newline);
count = count + 1;
End
Else
Do
crud = LINEOUT(FileNameOut8s,SUBSTR(line,1,SymPos)" . "8" . "SUBSTR(line,SymPos+4));
crud = LINEOUT(FileNameOut16s,SUBSTR(line,1,SymPos)" . "16" . "SUBSTR(line,SymPos+4));
End
End
Else
Do
crud = LINEOUT(FileNameOut8c,line);
crud = LINEOUT(FileNameOut8s,line);
crud = LINEOUT(FileNameOut16c,line);
crud = LINEOUT(FileNameOut16s,line);
End
End
say "Lines read: "Count
crud = STREAM(FileNameIn,"C","close")
crud = STREAM(FileNameOut8s,"C","close")
crud = STREAM(FileNameOut8c,"C","close")
crud = STREAM(FileNameOut16s,"C","close")
crud = STREAM(FileNameOut16c,"C","close")

View File

@ -0,0 +1,71 @@
/*
make_inst.cmd:
Translation of the make_size perl script and makefile to rexx for OS/2
size_c.h: size_tab.h
$(PERL) make_size c size_tab.h > size_c.h
size_s.h: size_tab.h
$(PERL) make_size s size_tab.h > size_s.h
8size_s.h: size_tab.h
$(PERL) make_size 8 size_tab.h > 8size_s.h
16size_s.h: size_tab.h
$(PERL) make_size 16 size_tab.h > 16size_s.h
*/
FileNameIn = "..\..\size_tab.h"
FileNameOuts = "..\..\size_s.h"
FileNameOutc = "..\..\size_c.h"
FileNameOut8 = "..\..\8size_s.h"
FileNameOut16 = "..\..\16size_s.h"
DEL FileNameOuts
DEL FileNameOutc
DEL FileNameOut8
DEL FileNameOut16
crud = STREAM(FileNameIn,"C","open read")
crud = STREAM(FileNameOuts,"C","open write")
crud = STREAM(FileNameOutc,"C","open write")
crud = STREAM(FileNameOut8,"C","open write")
crud = STREAM(FileNameOut16,"C","open write")
Do while (STREAM(FileNameIn,"S") = "READY")
line = LINEIN(FileNameIn);
SymPos = POS("_SYM",line)
if (SymPos > 0) Then
Do
newline = " .byte 0x"SUBSTR(line,SymPos+5,1)", /* "SUBSTR(line,SymPos-2,2)" */ "SUBSTR(line,SymPos+6)
crud = LINEOUT(FileNameOuts, newline);
newline = " 0x"SUBSTR(line,SymPos+5,1)", /* "SUBSTR(line,SymPos-2,2)" */ "SUBSTR(line,SymPos+6)
crud = LINEOUT(FileNameOutc, newline);
newline = " .word inst"SUBSTR(line,SymPos-2,2)" . 8 . /*"SUBSTR(line,SymPos+5,1)"*/ "SUBSTR(line,SymPos+6)
crud = LINEOUT(FileNameOut8, newline);
newline = " .word inst"SUBSTR(line,SymPos-2,2)" . 16 . /*"SUBSTR(line,SymPos+5,1)"*/ "SUBSTR(line,SymPos+6)
crud = LINEOUT(FileNameOut16, newline);
End
Else if (POS(".block",line) > 0) Then
Do
crud = LINEOUT(FileNameOuts, "");
crud = LINEOUT(FileNameOutc, "");
crud = LINEOUT(FileNameOut8, line);
crud = LINEOUT(FileNameOut16, line);
End
Else
Do
crud = LINEOUT(FileNameOuts, line);
crud = LINEOUT(FileNameOutc, line);
crud = LINEOUT(FileNameOut8, line);
crud = LINEOUT(FileNameOut16, line);
End
End
crud = STREAM(FileNameIn,"C","close")
crud = STREAM(FileNameOuts,"C","close")
crud = STREAM(FileNameOutc,"C","close")
crud = STREAM(FileNameOut8,"C","close")
crud = STREAM(FileNameOut16,"C","close")

View File

@ -0,0 +1,523 @@
/*-
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)bpf.h 7.1 (Berkeley) 5/7/91
*
* @(#) $Header$ (LBL)
*/
#ifndef BPF_MAJOR_VERSION
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER
#include <WinSock2.h>
typedef unsigned int u_int;
typedef unsigned char u_char;
typedef unsigned short u_short;
#endif
/* BSD style release date */
#define BPF_RELEASE 199606
typedef int bpf_int32;
typedef u_int bpf_u_int32;
/*
* Alignment macros. BPF_WORDALIGN rounds up to the next
* even multiple of BPF_ALIGNMENT.
*/
#ifndef __NetBSD__
#define BPF_ALIGNMENT sizeof(bpf_int32)
#else
#define BPF_ALIGNMENT sizeof(long)
#endif
#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
#define BPF_MAXINSNS 512
#define BPF_MAXBUFSIZE 0x8000
#define BPF_MINBUFSIZE 32
/*
* Structure for BIOCSETF.
*/
struct bpf_program {
u_int bf_len;
struct bpf_insn *bf_insns;
};
/*
* Struct returned by BIOCGSTATS.
*/
struct bpf_stat {
u_int bs_recv; /* number of packets received */
u_int bs_drop; /* number of packets dropped */
};
/*
* Struct return by BIOCVERSION. This represents the version number of
* the filter language described by the instruction encodings below.
* bpf understands a program iff kernel_major == filter_major &&
* kernel_minor >= filter_minor, that is, if the value returned by the
* running kernel has the same major number and a minor number equal
* equal to or less than the filter being downloaded. Otherwise, the
* results are undefined, meaning an error may be returned or packets
* may be accepted haphazardly.
* It has nothing to do with the source code version.
*/
struct bpf_version {
u_short bv_major;
u_short bv_minor;
};
/* Current version number of filter architecture. */
#define BPF_MAJOR_VERSION 1
#define BPF_MINOR_VERSION 1
/*
* BPF ioctls
*
* The first set is for compatibility with Sun's pcc style
* header files. If your using gcc, we assume that you
* have run fixincludes so the latter set should work.
*/
#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__)
#define BIOCGBLEN _IOR(B,102, u_int)
#define BIOCSBLEN _IOWR(B,102, u_int)
#define BIOCSETF _IOW(B,103, struct bpf_program)
#define BIOCFLUSH _IO(B,104)
#define BIOCPROMISC _IO(B,105)
#define BIOCGDLT _IOR(B,106, u_int)
#define BIOCGETIF _IOR(B,107, struct ifreq)
#define BIOCSETIF _IOW(B,108, struct ifreq)
#define BIOCSRTIMEOUT _IOW(B,109, struct timeval)
#define BIOCGRTIMEOUT _IOR(B,110, struct timeval)
#define BIOCGSTATS _IOR(B,111, struct bpf_stat)
#define BIOCIMMEDIATE _IOW(B,112, u_int)
#define BIOCVERSION _IOR(B,113, struct bpf_version)
#define BIOCSTCPF _IOW(B,114, struct bpf_program)
#define BIOCSUDPF _IOW(B,115, struct bpf_program)
#else
#define BIOCGBLEN _IOR('B',102, u_int)
#define BIOCSBLEN _IOWR('B',102, u_int)
#define BIOCSETF _IOW('B',103, struct bpf_program)
#define BIOCFLUSH _IO('B',104)
#define BIOCPROMISC _IO('B',105)
#define BIOCGDLT _IOR('B',106, u_int)
#define BIOCGETIF _IOR('B',107, struct ifreq)
#define BIOCSETIF _IOW('B',108, struct ifreq)
#define BIOCSRTIMEOUT _IOW('B',109, struct timeval)
#define BIOCGRTIMEOUT _IOR('B',110, struct timeval)
#define BIOCGSTATS _IOR('B',111, struct bpf_stat)
#define BIOCIMMEDIATE _IOW('B',112, u_int)
#define BIOCVERSION _IOR('B',113, struct bpf_version)
#define BIOCSTCPF _IOW('B',114, struct bpf_program)
#define BIOCSUDPF _IOW('B',115, struct bpf_program)
#endif
/*
* Structure prepended to each packet.
*/
struct bpf_hdr {
struct timeval bh_tstamp; /* time stamp */
bpf_u_int32 bh_caplen; /* length of captured portion */
bpf_u_int32 bh_datalen; /* original length of packet */
u_short bh_hdrlen; /* length of bpf header (this struct
plus alignment padding) */
};
/*
* Because the structure above is not a multiple of 4 bytes, some compilers
* will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
* Only the kernel needs to know about it; applications use bh_hdrlen.
*/
#if defined(KERNEL) || defined(_KERNEL)
#define SIZEOF_BPF_HDR 18
#endif
/*
* Data-link level type codes.
*/
/*
* These are the types that are the same on all platforms; on other
* platforms, a <net/bpf.h> should be supplied that defines the additional
* DLT_* codes appropriately for that platform (the BSDs, for example,
* should not just pick up this version of "bpf.h"; they should also define
* the additional DLT_* codes used by their kernels, as well as the values
* defined here - and, if the values they use for particular DLT_ types
* differ from those here, they should use their values, not the ones
* here).
*/
#define DLT_NULL 0 /* no link-layer encapsulation */
#define DLT_EN10MB 1 /* Ethernet (10Mb) */
#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
#define DLT_AX25 3 /* Amateur Radio AX.25 */
#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
#define DLT_CHAOS 5 /* Chaos */
#define DLT_IEEE802 6 /* IEEE 802 Networks */
#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
#define DLT_SLIP 8 /* Serial Line IP */
#define DLT_PPP 9 /* Point-to-point Protocol */
#define DLT_FDDI 10 /* FDDI */
/*
* These are values from the traditional libpcap "bpf.h".
* Ports of this to particular platforms should replace these definitions
* with the ones appropriate to that platform, if the values are
* different on that platform.
*/
#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */
#define DLT_RAW 12 /* raw IP */
/*
* These are values from BSD/OS's "bpf.h".
* These are not the same as the values from the traditional libpcap
* "bpf.h"; however, these values shouldn't be generated by any
* OS other than BSD/OS, so the correct values to use here are the
* BSD/OS values.
*
* Platforms that have already assigned these values to other
* DLT_ codes, however, should give these codes the values
* from that platform, so that programs that use these codes will
* continue to compile - even though they won't correctly read
* files of these types.
*/
#ifdef __NetBSD__
#ifndef DLT_SLIP_BSDOS
#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
#endif
#else
#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
#endif
#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
/*
* These values are defined by NetBSD; other platforms should refrain from
* using them for other purposes, so that NetBSD savefiles with link
* types of 50 or 51 can be read as this type on all platforms.
*/
#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
/*
* Values between 100 and 103 are used in capture file headers as
* link-layer types corresponding to DLT_ types that differ
* between platforms; don't use those values for new DLT_ new types.
*/
/*
* This value was defined by libpcap 0.5; platforms that have defined
* it with a different value should define it here with that value -
* a link type of 104 in a save file will be mapped to DLT_C_HDLC,
* whatever value that happens to be, so programs will correctly
* handle files with that link type regardless of the value of
* DLT_C_HDLC.
*
* The name DLT_C_HDLC was used by BSD/OS; we use that name for source
* compatibility with programs written for BSD/OS.
*
* libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
* for source compatibility with programs written for libpcap 0.5.
*/
#define DLT_C_HDLC 104 /* Cisco HDLC */
#define DLT_CHDLC DLT_C_HDLC
#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
/*
* 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
* except when it isn't. (I.e., sometimes it's just raw IP, and
* sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
* so that we don't have to worry about the link-layer header.)
*/
/*
* Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
* with other values.
* DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
* (DLCI, etc.).
*/
#define DLT_FRELAY 107
/*
* OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
* that the AF_ type in the link-layer header is in network byte order.
*
* OpenBSD defines it as 12, but that collides with DLT_RAW, so we
* define it as 108 here. If OpenBSD picks up this file, it should
* define DLT_LOOP as 12 in its version, as per the comment above -
* and should not use 108 as a DLT_ value.
*/
#define DLT_LOOP 108
/*
* Values between 109 and 112 are used in capture file headers as
* link-layer types corresponding to DLT_ types that might differ
* between platforms; don't use those values for new DLT_ types
* other than the corresponding DLT_ types.
*/
/*
* This is for Linux cooked sockets.
*/
#define DLT_LINUX_SLL 113
/*
* Apple LocalTalk hardware.
*/
#define DLT_LTALK 114
/*
* Acorn Econet.
*/
#define DLT_ECONET 115
/*
* Reserved for use with OpenBSD ipfilter.
*/
#define DLT_IPFILTER 116
/*
* Reserved for use in capture-file headers as a link-layer type
* corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD,
* but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it
* in capture-file headers.
*/
#define DLT_PFLOG 117
/*
* Registered for Cisco-internal use.
*/
#define DLT_CISCO_IOS 118
/*
* Reserved for 802.11 cards using the Prism II chips, with a link-layer
* header including Prism monitor mode information plus an 802.11
* header.
*/
#define DLT_PRISM_HEADER 119
/*
* Reserved for Aironet 802.11 cards, with an Aironet link-layer header
* (see Doug Ambrisko's FreeBSD patches).
*/
#define DLT_AIRONET_HEADER 120
/*
* Reserved for Siemens HiPath HDLC.
*/
#define DLT_HHDLC 121
/*
* This is for RFC 2625 IP-over-Fibre Channel.
*
* This is not for use with raw Fibre Channel, where the link-layer
* header starts with a Fibre Channel frame header; it's for IP-over-FC,
* where the link-layer header starts with an RFC 2625 Network_Header
* field.
*/
#define DLT_IP_OVER_FC 122
/*
* This is for Full Frontal ATM on Solaris with SunATM, with a
* pseudo-header followed by an AALn PDU.
*
* There may be other forms of Full Frontal ATM on other OSes,
* with different pseudo-headers.
*
* If ATM software returns a pseudo-header with VPI/VCI information
* (and, ideally, packet type information, e.g. signalling, ILMI,
* LANE, LLC-multiplexed traffic, etc.), it should not use
* DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
* and the like don't have to infer the presence or absence of a
* pseudo-header and the form of the pseudo-header.
*/
#define DLT_SUNATM 123 /* Solaris+SunATM */
/*
* Reserved as per request from Kent Dahlgren <kent@praesum.com>
* for private use.
*/
#define DLT_RIO 124 /* RapidIO */
#define DLT_PCI_EXP 125 /* PCI Express */
#define DLT_AURORA 126 /* Xilinx Aurora link layer */
/*
* For future use with 802.11 captures - defined by AbsoluteValue
* Systems to store a number of bits of link-layer information:
*
* http://www.shaftnet.org/~pizza/software/capturefrm.txt
*
* but could and arguably should also be used by non-AVS Linux
* 802.11 drivers and BSD drivers; that may happen in the future.
*/
#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus WLAN header */
/*
* Reserved for the TZSP encapsulation, as per request from
* Chris Waters <chris.waters@networkchemistry.com>
* TZSP is a generic encapsulation for any other link type,
* which includes a means to include meta-information
* with the packet, e.g. signal strength and channel
* for 802.11 packets.
*/
#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
/*
* BSD's ARCNET headers have the source host, destination host,
* and type at the beginning of the packet; that's what's handed
* up to userland via BPF.
*
* Linux's ARCNET headers, however, have a 2-byte offset field
* between the host IDs and the type; that's what's handed up
* to userland via PF_PACKET sockets.
*
* We therefore have to have separate DLT_ values for them.
*/
#define DLT_ARCNET_LINUX 129 /* ARCNET */
/*
* The instruction encodings.
*/
/* instruction classes */
#define BPF_CLASS(code) ((code) & 0x07)
#define BPF_LD 0x00
#define BPF_LDX 0x01
#define BPF_ST 0x02
#define BPF_STX 0x03
#define BPF_ALU 0x04
#define BPF_JMP 0x05
#define BPF_RET 0x06
#define BPF_MISC 0x07
/* ld/ldx fields */
#define BPF_SIZE(code) ((code) & 0x18)
#define BPF_W 0x00
#define BPF_H 0x08
#define BPF_B 0x10
#define BPF_MODE(code) ((code) & 0xe0)
#define BPF_IMM 0x00
#define BPF_ABS 0x20
#define BPF_IND 0x40
#define BPF_MEM 0x60
#define BPF_LEN 0x80
#define BPF_MSH 0xa0
/* alu/jmp fields */
#define BPF_OP(code) ((code) & 0xf0)
#define BPF_ADD 0x00
#define BPF_SUB 0x10
#define BPF_MUL 0x20
#define BPF_DIV 0x30
#define BPF_OR 0x40
#define BPF_AND 0x50
#define BPF_LSH 0x60
#define BPF_RSH 0x70
#define BPF_NEG 0x80
#define BPF_JA 0x00
#define BPF_JEQ 0x10
#define BPF_JGT 0x20
#define BPF_JGE 0x30
#define BPF_JSET 0x40
#define BPF_SRC(code) ((code) & 0x08)
#define BPF_K 0x00
#define BPF_X 0x08
/* ret - BPF_K and BPF_X also apply */
#define BPF_RVAL(code) ((code) & 0x18)
#define BPF_A 0x10
/* misc */
#define BPF_MISCOP(code) ((code) & 0xf8)
#define BPF_TAX 0x00
#define BPF_TXA 0x80
/*
* The instruction data structure.
*/
struct bpf_insn {
u_short code;
u_char jt;
u_char jf;
bpf_int32 k;
};
/*
* Macros for insn array initializers.
*/
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL))
/*
* Systems based on non-BSD kernels don't have ifnet's (or they don't mean
* anything if it is in <net/if.h>) and won't work like this.
*/
# if __STDC__
extern void bpf_tap(struct ifnet *, u_char *, u_int);
extern void bpf_mtap(struct ifnet *, struct mbuf *);
extern void bpfattach(struct ifnet *, u_int, u_int);
extern void bpfilterattach(int);
# else
extern void bpf_tap();
extern void bpf_mtap();
extern void bpfattach();
extern void bpfilterattach();
# endif /* __STDC__ */
#endif /* BSD && (_KERNEL || KERNEL) */
#if __STDC__ || defined(__cplusplus)
extern int bpf_validate(struct bpf_insn *, int);
extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
#else
extern int bpf_validate();
extern u_int bpf_filter();
#endif
/*
* Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
*/
#define BPF_MEMWORDS 16
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>152 85 356 240 0 0 1280 832 </string>
<key>IBEditorPositions</key>
<dict>
<key>29</key>
<string>69 252 182 44 0 0 1280 832 </string>
</dict>
<key>IBFramework Version</key>
<string>291.0</string>
<key>IBSystem Version</key>
<string>6R73</string>
<key>targetFramework</key>
<string>IBCarbonFramework</string>
</dict>
</plist>

View File

@ -0,0 +1,45 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
void show_simple_alert(char *str1, char *str2, char *str3, int num);
void x_dialog_create_kegs_conf(const char *str);
int x_show_alert(int is_fatal, const char *str);void update_window(void);
void mac_update_modifiers(word32 state);
void mac_warp_mouse(void);
void check_input_events(void);
void temp_run_application_event_loop(void);
int main(int argc, char *argv[]);
void x_update_color(int col_num, int red, int green, int blue, word32 rgb);
void x_update_physical_colormap(void);
void show_xcolor_array(void);
void xdriver_end(void);
void x_get_kimage(Kimage *kimage_ptr);
void dev_video_init(void);
void x_redraw_status_lines(void);
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height);
void x_push_done(void);
void x_auto_repeat_on(int must);
void x_auto_repeat_off(int must);
void x_hide_pointer(int do_hide);
void x_full_screen(int do_full);
void update_main_window_size(void);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,217 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="16inst_c.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="8inst_c.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="adb.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="defc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="defcomm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="defs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="defs_instr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="disas.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="gsportfont.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iwm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iwm_35_525.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="op_routs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="printer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="printer_charmaps.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="imagewriter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iw_charmaps.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="prodos.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="prodos_protos.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="protos.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="protos_engine_c.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="protos_macdriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="protos_macsnd_driver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="protos_windriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="protos_xdriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="scc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="size_c.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="sound.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="superhires.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="support.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="winresource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="tfe\protos_tfe.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win_keymap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="scc_llap.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="adb.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="clock.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="compile_time.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="config.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dis.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="engine_c.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="iwm.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="joystick_driver.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="moremem.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="paddles.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="scc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="scc_socket_driver.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="scc_windriver.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sim65816.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="smartport.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sound.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sound_driver.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="video.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win32snd_driver.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win_console.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win_generic.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="parallel.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="printer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="scc_imagewriter.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="imagewriter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="scc_llap.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="size_tab.h">
<Filter>Header Files</Filter>
</CustomBuild>
<CustomBuild Include="instable.h">
<Filter>Header Files</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="win32.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,20 @@
TARGET = gsportx
OBJECTS = $(OBJECTS1) xdriver.o
CC = gcc
CCOPTS = -O
OPTS = -DNDEBUG
SUFFIX =
NAME = gsportx
LDFLAGS =
LDOPTS = -z
LD = $(CC)
EXTRA_LIBS = -lXext -lX11 -lcl -lc
EXTRA_SPECIALS = Alib.h
AS = cc -Ae
PERL = perl
XOPTS = -DHPUX -I/usr/include/X11R5
XLIBS = -L/usr/lib/X11R5 -L/opt/audio/lib

View File

@ -0,0 +1,36 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2013-2014 by Peter Neubauer
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/** ELAP port of the AppleTalk Bridge **/
bool elap_init();
void elap_shutdown();
void elap_process();
struct packet_t;
void elap_enqueue_out(struct packet_t* packet);
struct packet_t* elap_dequeue_in();
struct ether_addr_t;
struct snap_discriminator_t;
void elap_send(const struct ether_addr_t* dest, const struct snap_discriminator_t* discriminator, size_t size, byte data[]);
const struct ether_addr_t* elap_get_mac();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
#!/bin/sh
cd target/site
perl -i.orig -p ../../removeMaven.re appletalk.html
perl -i.orig -p ../../removeMaven.re developing.html
perl -i.orig -p ../../removeMaven.re ethernet.html
perl -i.orig -p ../../removeMaven.re history.html
perl -i.orig -p ../../removeMaven.re index.html
perl -i.orig -p ../../removeMaven.re operating.html
perl -i.orig -p ../../removeMaven.re printer.html
rm *.orig
cd ../..

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -0,0 +1,117 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2013-2014 by Peter Neubauer
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6
static const word16 ETHER_MAX_SIZE = 0x5DC;
static const word16 ETHER_MIN_SIZE = 60;
static const byte SNAP_DSAP = 0xAA;
static const byte SNAP_SSAP = 0xAA;
static const byte SNAP_CONTROL = 0x03;
#define OUI_APPLETALK_1 0x08
#define OUI_APPLETALK_2 0x00
#define OUI_APPLETALK_3 0x07
#define TYPE_APPLETALK_1 0x80
#define TYPE_APPLETALK_2 0x9B
#define OUI_AARP_1 0x00
#define OUI_AARP_2 0x00
#define OUI_AARP_3 0x00
#define TYPE_AARP_1 0x80
#define TYPE_AARP_2 0xF3
static const byte AARP_HARDWARE_ETHER = 0x01;
static const word16 AARP_PROTOCOL_TYPE = 0x809B;
static const byte AARP_HW_ADDR_LEN = 6;
static const byte AARP_PROTOCOL_ADDR_LEN = 4;
enum AARP_FUNCTION
{
AARP_FUNCTION_REQUEST = 0x01,
AARP_FUNCTION_RESPONSE = 0x02,
AARP_FUNCTION_PROBE = 0x03
};
// reference C-4
static const long AARP_PROBE_INTERVAL = 200; /* milliseconds */
static const unsigned int AARP_PROBE_COUNT = 10;
// reference 2-9 and 3-9, optional and at developer discretion
static const long AARP_REQUEST_INTERVAL = 200; /* milliseconds */
static const unsigned int AARP_REQUEST_COUNT = 10;
#pragma pack(push, 1)
struct ether_addr_t
{
byte mac[ETHER_ADDR_LEN];
};
/* Ethernet 802.2/802.3/SNAP header */
struct ethernet_header_t
{
// 802.3 header
struct ether_addr_t dest;
struct ether_addr_t source;
word16 length;
};
struct snap_discriminator_t
{
byte oui[3];
byte type[2];
};
struct snap_header_t
{
// 802.2 header
byte dsap;
byte ssap;
byte control;
// SNAP header
struct snap_discriminator_t discriminator;
};
struct protocol_addr_t
{
byte zero; // Reference C-4 and 3-11: The protocol address is four bytes with the high byte zero.
struct at_addr_t addr;
};
struct aarp_header_t
{
word16 hardware_type;
word16 protocol_type;
byte hw_addr_len;
byte protocol_addr_len;
word16 function;
struct ether_addr_t source_hw_addr;
struct protocol_addr_t source_proto_addr;
struct ether_addr_t dest_hw_addr;
struct protocol_addr_t dest_proto_addr;
};
#pragma pack(pop)
static const struct ether_addr_t HW_APPLETALK_BROADCAST = {{ 0x09, 0x00, 0x07, 0xff, 0xff, 0xff }};
static const struct ether_addr_t HW_LOCAL_DEFAULT = {{0x02 /* unicast, locally administered */, 'A', '2', 'G', 'S', 0x00}};
//static const struct ether_addr_t HW_LOCAL = {{ 0x02 /* unicast, locally administered */, 0x00, 0x4c, 0x4f, 0x4f, 0x50 }};
static const struct ether_addr_t HW_ZERO = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
static const struct snap_discriminator_t SNAP_APPLETALK = {{ OUI_APPLETALK_1, OUI_APPLETALK_2, OUI_APPLETALK_3}, {TYPE_APPLETALK_1, TYPE_APPLETALK_2 }};
static const struct snap_discriminator_t SNAP_AARP = {{ OUI_AARP_1, OUI_AARP_2, OUI_AARP_3}, {TYPE_AARP_1, TYPE_AARP_2 }};

View File

@ -0,0 +1,327 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Various ASCII codepage to unicode maps
static const Bit16u cp437Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp737Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f,0x03a0,
0x03a1,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7,0x03a8,0x03a9,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7,0x03b8,
0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,0x03c0,0x03c1,0x03c3,0x03c2,0x03c4,0x03c5,0x03c6,0x03c7,0x03c8,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x03c9,0x03ac,0x03ad,0x03ae,0x03ca,0x03af,0x03cc,0x03cd,0x03cb,0x03ce,0x0386,0x0388,0x0389,0x038a,0x038c,0x038e,
0x038f,0x00b1,0x2265,0x2264,0x03aa,0x03ab,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp775Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x0106,0x00fc,0x00e9,0x0101,0x00e4,0x0123,0x00e5,0x0107,0x0142,0x0113,0x0156,0x0157,0x012b,0x0179,0x00c4,0x00c5,
0x00c9,0x00e6,0x00c6,0x014d,0x00f6,0x0122,0x00a2,0x015a,0x015b,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x00a4,
0x0100,0x012a,0x00f3,0x017b,0x017c,0x017a,0x201d,0x00a6,0x00a9,0x00ae,0x00ac,0x00bd,0x00bc,0x0141,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x0104,0x010c,0x0118,0x0116,0x2563,0x2551,0x2557,0x255d,0x012e,0x0160,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0172,0x016a,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x017d,
0x0105,0x010d,0x0119,0x0117,0x012f,0x0161,0x0173,0x016b,0x017e,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x00d3,0x00df,0x014c,0x0143,0x00f5,0x00d5,0x00b5,0x0144,0x0136,0x0137,0x013b,0x013c,0x0146,0x0112,0x0145,0x2019,
0x00ad,0x00b1,0x201c,0x00be,0x00b6,0x00a7,0x00f7,0x201e,0x00b0,0x2219,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp850Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x0192,
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
0x00f0,0x00d0,0x00ca,0x00cb,0x00c8,0x0131,0x00cd,0x00ce,0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580,
0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x00fe,0x00de,0x00da,0x00db,0x00d9,0x00fd,0x00dd,0x00af,0x00b4,
0x00ad,0x00b1,0x2017,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp852Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x016f,0x0107,0x00e7,0x0142,0x00eb,0x0150,0x0151,0x00ee,0x0179,0x00c4,0x0106,
0x00c9,0x0139,0x013a,0x00f4,0x00f6,0x013d,0x013e,0x015a,0x015b,0x00d6,0x00dc,0x0164,0x0165,0x0141,0x00d7,0x010d,
0x00e1,0x00ed,0x00f3,0x00fa,0x0104,0x0105,0x017d,0x017e,0x0118,0x0119,0x00ac,0x017a,0x010c,0x015f,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x011a,0x015e,0x2563,0x2551,0x2557,0x255d,0x017b,0x017c,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0102,0x0103,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
0x0111,0x0110,0x010e,0x00cb,0x010f,0x0147,0x00cd,0x00ce,0x011b,0x2518,0x250c,0x2588,0x2584,0x0162,0x016e,0x2580,
0x00d3,0x00df,0x00d4,0x0143,0x0144,0x0148,0x0160,0x0161,0x0154,0x00da,0x0155,0x0170,0x00fd,0x00dd,0x0163,0x00b4,
0x00ad,0x02dd,0x02db,0x02c7,0x02d8,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x02d9,0x0171,0x0158,0x0159,0x25a0,0x00a0
};
static const Bit16u cp855Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x0452,0x0402,0x0453,0x0403,0x0451,0x0401,0x0454,0x0404,0x0455,0x0405,0x0456,0x0406,0x0457,0x0407,0x0458,0x0408,
0x0459,0x0409,0x045a,0x040a,0x045b,0x040b,0x045c,0x040c,0x045e,0x040e,0x045f,0x040f,0x044e,0x042e,0x044a,0x042a,
0x0430,0x0410,0x0431,0x0411,0x0446,0x0426,0x0434,0x0414,0x0435,0x0415,0x0444,0x0424,0x0433,0x0413,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x0445,0x0425,0x0438,0x0418,0x2563,0x2551,0x2557,0x255d,0x0439,0x0419,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x043a,0x041a,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
0x043b,0x041b,0x043c,0x041c,0x043d,0x041d,0x043e,0x041e,0x043f,0x2518,0x250c,0x2588,0x2584,0x041f,0x044f,0x2580,
0x042f,0x0440,0x0420,0x0441,0x0421,0x0442,0x0422,0x0443,0x0423,0x0436,0x0416,0x0432,0x0412,0x044c,0x042c,0x2116,
0x00ad,0x044b,0x042b,0x0437,0x0417,0x0448,0x0428,0x044d,0x042d,0x0449,0x0429,0x0447,0x0427,0x00a7,0x25a0,0x00a0
};
static const Bit16u cp857Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x0131,0x00c4,0x00c5,
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x0130,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x015e,0x015f,
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x011e,0x011f,0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
0x00ba,0x00aa,0x00ca,0x00cb,0x00c8,0x0000,0x00cd,0x00ce,0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580,
0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x0000,0x00d7,0x00da,0x00db,0x00d9,0x00ec,0x00ff,0x00af,0x00b4,
0x00ad,0x00b1,0x0000,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp860Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00c7,0x00fc,0x00e9,0x00e2,0x00e3,0x00e0,0x00c1,0x00e7,0x00ea,0x00ca,0x00e8,0x00cd,0x00d4,0x00ec,0x00c3,0x00c2,
0x00c9,0x00c0,0x00c8,0x00f4,0x00f5,0x00f2,0x00da,0x00f9,0x00cc,0x00d5,0x00dc,0x00a2,0x00a3,0x00d9,0x20a7,0x00d3,
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x00d2,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp861Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00d0,0x00f0,0x00de,0x00c4,0x00c5,
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00fe,0x00fb,0x00dd,0x00fd,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192,
0x00e1,0x00ed,0x00f3,0x00fa,0x00c1,0x00cd,0x00d3,0x00da,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp862Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7,0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df,
0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7,0x05e8,0x05e9,0x05ea,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp863Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00c7,0x00fc,0x00e9,0x00e2,0x00c2,0x00e0,0x00b6,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x2017,0x00c0,0x00a7,
0x00c9,0x00c8,0x00ca,0x00f4,0x00cb,0x00cf,0x00fb,0x00f9,0x00a4,0x00d4,0x00dc,0x00a2,0x00a3,0x00d9,0x00db,0x0192,
0x00a6,0x00b4,0x00f3,0x00fa,0x00a8,0x00b8,0x00b3,0x00af,0x00ce,0x2310,0x00ac,0x00bd,0x00bc,0x00be,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp864Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x066a,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00b0,0x00b7,0x2219,0x221a,0x2592,0x2500,0x2502,0x253c,0x2524,0x252c,0x251c,0x2534,0x2510,0x250c,0x2514,0x2518,
0x03b2,0x221e,0x03c6,0x00b1,0x00bd,0x00bc,0x2248,0x00ab,0x00bb,0xfef7,0xfef8,0x0000,0x0000,0xfefb,0xfefc,0x0000,
0x00a0,0x00ad,0xfe82,0x00a3,0x00a4,0xfe84,0x0000,0x0000,0xfe8e,0xfe8f,0xfe95,0xfe99,0x060c,0xfe9d,0xfea1,0xfea5,
0x0660,0x0661,0x0662,0x0663,0x0664,0x0665,0x0666,0x0667,0x0668,0x0669,0xfed1,0x061b,0xfeb1,0xfeb5,0xfeb9,0x061f,
0x00a2,0xfe80,0xfe81,0xfe83,0xfe85,0xfeca,0xfe8b,0xfe8d,0xfe91,0xfe93,0xfe97,0xfe9b,0xfe9f,0xfea3,0xfea7,0xfea9,
0xfeab,0xfead,0xfeaf,0xfeb3,0xfeb7,0xfebb,0xfebf,0xfec1,0xfec5,0xfecb,0xfecf,0x00a6,0x00ac,0x00f7,0x00d7,0xfec9,
0x0640,0xfed3,0xfed7,0xfedb,0xfedf,0xfee3,0xfee7,0xfeeb,0xfeed,0xfeef,0xfef3,0xfebd,0xfecc,0xfece,0xfecd,0xfee1,
0xfe7d,0x0651,0xfee5,0xfee9,0xfeec,0xfef0,0xfef2,0xfed0,0xfed5,0xfef5,0xfef6,0xfedd,0xfed9,0xfef1,0x25a0,
};
static const Bit16u cp865Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192,
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00a4,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
};
static const Bit16u cp866Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f,
0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f,
0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f,
0x0401,0x0451,0x0404,0x0454,0x0407,0x0457,0x040e,0x045e,0x00b0,0x2219,0x00b7,0x221a,0x2116,0x00a4,0x25a0,0x00a0
};
CHARMAP charmap[] = {
{437, cp437Map},
{737, cp737Map},
{775, cp775Map},
{850, cp850Map},
{852, cp852Map},
{855, cp855Map},
{857, cp857Map},
{860, cp860Map},
{861, cp861Map},
{863, cp863Map},
{864, cp864Map},
{865, cp865Map},
{866, cp866Map},
{0, NULL},
};
static const Bit16u codepages[15] = {0, 437, 932, 850, 851, 853, 855, 860, 863, 865, 852, 857, 862, 864, 866};
// TODO: Implement all international charsets
static const Bit16u intCharSets[15][12] =
{
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // USA
{0x0023, 0x0024, 0x00e0, 0x00ba, 0x00e7, 0x00a7, 0x005e, 0x0060, 0x00e9, 0x00f9, 0x00e8, 0x00a8}, // France
{0x0023, 0x0024, 0x00a7, 0x00c4, 0x00d6, 0x00dc, 0x005e, 0x0060, 0x00e4, 0x00f6, 0x00fc, 0x00df}, // Germany
{0x00a3, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // UK
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x0040, 0x005b, 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e},
{0x0023, 0x0024, 0x00a7, 0x00c4, 0x0027, 0x0022, 0x00b6, 0x0060, 0x00a9, 0x00ae, 0x2020, 0x2122} // Legal
};

View File

@ -0,0 +1,555 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 - 2013 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ACTIVEIPHONE
#include <CoreGraphics/CGContext.h>
#include <CoreGraphics/CGBitmapContext.h>
#include <CoreFoundation/CFURL.h>
#else
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <Carbon/Carbon.h>
#define ENABLEQD
#endif
#include "stdio.h"
#include "defc.h"
#include "protos_macdriver.h"
word32 g_mac_shift_control_state = 0;
int macUsingCoreGraphics=0;
// Coregraphics context
CGContextRef offscreenContext = NULL;
char * bitmapData=NULL;
int bitmapByteCount;
int bitmapBytesPerRow;
#ifdef ENABLEQD
WindowRef g_main_window;
CGrafPtr mac_window_port;
#endif
char *g_clipboard = 0x00;
int g_clipboard_pos;
extern Kimage g_mainwin_kimage;
int g_use_shmem = 0;
extern int Verbose;
extern int g_video_act_width;
extern int g_video_act_height;
extern int g_video_act_margin_left;
extern int g_video_act_margin_right;
extern int g_video_act_margin_top;
extern int g_video_act_margin_bottom;
extern int g_screen_depth;
extern int g_force_depth;
int g_screen_mdepth = 0;
extern int g_send_sound_to_file;
//extern int g_quit_sim_now; // OG Not need anymore
extern int g_config_control_panel;
int g_auto_repeat_on = -1;
int g_x_shift_control_state = 0;
extern int Max_color_size;
extern word32 g_palette_8to1624[256];
extern word32 g_a2palette_8to1624[256];
int g_alt_left_up = 1;
int g_alt_right_up = 1;
extern word32 g_full_refresh_needed;
extern int g_border_sides_refresh_needed;
extern int g_border_special_refresh_needed;
extern int g_status_refresh_needed;
extern int g_lores_colors[];
extern int g_a2vid_palette;
extern int g_installed_full_superhires_colormap;
extern int g_screen_redraw_skip_amt;
extern word32 g_a2_screen_buffer_changed;
int g_upd_count = 0;
void
update_window(void)
{
// OG Not needed
/*
SetPortWindowPort(g_main_window);
PenNormal();
*/
g_full_refresh_needed = -1;
g_a2_screen_buffer_changed = -1;
g_status_refresh_needed = 1;
g_border_sides_refresh_needed = 1;
g_border_special_refresh_needed = 1;
g_upd_count++;
if(g_upd_count > 250) {
g_upd_count = 0;
}
}
void
mac_update_modifiers(word32 state)
{
#ifndef ACTIVEIPHONE
word32 state_xor;
int is_up;
state = state & (
cmdKey | controlKey |
shiftKey | alphaLock | optionKey
);
state_xor = g_mac_shift_control_state ^ state;
is_up = 0;
if(state_xor & controlKey) {
is_up = ((state & controlKey) == 0);
adb_physical_key_update(0x36, is_up);
}
if(state_xor & alphaLock) {
is_up = ((state & alphaLock) == 0);
adb_physical_key_update(0x39, is_up);
}
if(state_xor & shiftKey) {
is_up = ((state & shiftKey) == 0);
adb_physical_key_update(0x38, is_up);
}
if(state_xor & cmdKey) {
is_up = ((state & cmdKey) == 0);
adb_physical_key_update(0x37, is_up);
}
if(state_xor & optionKey) {
is_up = ((state & optionKey) == 0);
adb_physical_key_update(0x3a, is_up);
}
#endif
g_mac_shift_control_state = state;
}
void
x_update_color(int col_num, int red, int green, int blue, word32 rgb)
{
}
void
x_update_physical_colormap()
{
}
void
show_xcolor_array()
{
int i;
for(i = 0; i < 256; i++) {
printf("%02x: %08x\n", i, g_palette_8to1624[i]);
}
}
void
x_get_kimage(Kimage *kimage_ptr)
{
#ifdef ENABLEQD
PixMapHandle pixmap_handle;
GWorldPtr world;
Rect world_rect;
OSStatus err;
#endif
word32 *wptr;
byte *ptr;
int row_bytes;
int width;
int height;
int depth, mdepth;
int size;
width = kimage_ptr->width_req;
height = kimage_ptr->height;
depth = kimage_ptr->depth;
mdepth = kimage_ptr->mdepth;
size = 0;
if(depth == g_screen_depth)
{
if (!macUsingCoreGraphics)
{
#ifdef ENABLEQD
SetRect(&world_rect, 0, 0, width, height);
err = NewGWorld( &world, 0, &world_rect, NULL, NULL, 0);
pixmap_handle = GetGWorldPixMap(world);
err = LockPixels(pixmap_handle);
ptr = (byte *)GetPixBaseAddr(pixmap_handle);
row_bytes = ((*pixmap_handle)->rowBytes & 0x3fff);
kimage_ptr->width_act = row_bytes / (mdepth >> 3);
mac_printf("Got depth: %d, bitmap_ptr: %p, width: %d\n", depth, ptr, kimage_ptr->width_act);
mac_printf("pixmap->base: %08x, rowbytes: %08x, pixType:%08x\n",(int)(*pixmap_handle)->baseAddr,(*pixmap_handle)->rowBytes,(*pixmap_handle)->pixelType);
wptr = (word32 *)(*pixmap_handle);
mac_printf("wptr: %p=%08x %08x %08x %08x %08x %08x %08x %08x\n",wptr,wptr[0], wptr[1], wptr[2], wptr[3],wptr[4], wptr[5], wptr[6], wptr[7]);
kimage_ptr->dev_handle = pixmap_handle;
kimage_ptr->data_ptr = ptr;
#endif
}
else
{
kimage_ptr->width_act = width ;
size = height* kimage_ptr->width_act * mdepth >> 3;
ptr = (byte *)malloc(size);
if(ptr == 0) {
mac_printf("malloc for data fail, mdepth:%d\n", mdepth);
exit(2);
}
kimage_ptr->data_ptr = ptr;
kimage_ptr->dev_handle = (void *)-1;
}
}
else {
/* allocate buffers for video.c to draw into */
kimage_ptr->width_act = width ;
size = height* kimage_ptr->width_act * mdepth >> 3 ;
ptr = (byte *)malloc(size);
if(ptr == 0) {
mac_printf("malloc for data fail, mdepth:%d\n", mdepth);
exit(2);
}
kimage_ptr->data_ptr = ptr;
kimage_ptr->dev_handle = (void *)-1;
}
mac_printf("kim: %p, dev:%p data: %p, size: %08x\n", kimage_ptr,
kimage_ptr->dev_handle, kimage_ptr->data_ptr, size);
}
#ifdef ENABLEQD
PixMapHandle pixmap_backbuffer=NULL;
GWorldPtr backbuffer=NULL;
#endif
void
dev_video_init()
{
int lores_col;
int i;
printf("Preparing graphics system\n");
// OG Create backbuffer
if (!macUsingCoreGraphics)
{
#ifdef ENABLEQD
Rect r;
SetRect(&r, 0, 0, 704, 462);
QDErr err = NewGWorld( &backbuffer, 0, &r, NULL, NULL, 0);
pixmap_backbuffer = GetGWorldPixMap(backbuffer);
#endif
}
else
{
int pixelsWide = 704;
int pixelsHigh = 462;
bitmapBytesPerRow = (pixelsWide * 4);// 1
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
bitmapData = (char*)malloc( bitmapByteCount );// 3
if (bitmapData == NULL)
{
fprintf (stderr, "Memory not allocated!");
return ;
}
offscreenContext = CGBitmapContextCreate (bitmapData,// 4
pixelsWide,
pixelsHigh,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaNoneSkipLast);
if (offscreenContext== NULL)
{
free (bitmapData);// 5
fprintf (stderr, "Context not created!");
return ;
}
CGContextSetRGBFillColor (offscreenContext, 1, 0.5, 0.5, 1);
CGContextFillRect (offscreenContext, CGRectMake (0,0, 704, 462 ));
CGColorSpaceRelease( colorSpace );// 6
}
video_get_kimages();
if(g_screen_depth != 8) {
// Get g_mainwin_kimage
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth,
g_screen_mdepth);
}
for(i = 0; i < 256; i++) {
lores_col = g_lores_colors[i & 0xf];
video_update_color_raw(i, lores_col);
g_a2palette_8to1624[i] = g_palette_8to1624[i];
}
g_installed_full_superhires_colormap = 1;
fflush(stdout);
}
void
x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
int width, int height)
{
int i;
if (!macUsingCoreGraphics)
{
#ifdef ENABLEQD
PixMapHandle pixmap_handle;
Rect src_rect, dest_rect;
CGrafPtr window_port;
pixmap_handle = (PixMapHandle)kimage_ptr->dev_handle;
SetRect(&src_rect, srcx, srcy, srcx + width, srcy + height);
SetRect(&dest_rect, destx, desty, destx + width, desty + height);
#ifndef ACTIVEGSPLUGIN
SetPortWindowPort(g_main_window);
window_port = GetWindowPort(g_main_window);
CopyBits( (BitMap *)(*pixmap_handle),
GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect,
srcCopy, NULL);
#else // !ACTIVEGSPLUGIN
// OG Write to the back buffer instead of the display window
window_port = mac_window_port ;
SetGWorld(backbuffer,NULL);
CopyBits( (BitMap *)(*pixmap_handle),
GetPortBitMapForCopyBits(backbuffer), &src_rect, &dest_rect,
srcCopy, NULL);
#endif // ACTIVEGSPLUGIN
#endif
}
else
{
int wd = kimage_ptr->width_act * kimage_ptr->mdepth>>3;
int w = width *4;
char* ptrdest = bitmapData + bitmapBytesPerRow*desty + destx*4;
char* srcdest = (char*)kimage_ptr->data_ptr + wd*srcy + srcx*4;
for(i=0;i<height;i+=1)
{
memcpy(ptrdest,srcdest,w);
ptrdest += bitmapBytesPerRow;
srcdest += wd;
}
}
}
void
x_auto_repeat_on(int must)
{
}
void
x_auto_repeat_off(int must)
{
}
void
x_hide_pointer(int do_hide)
{
#ifdef ENABLEQD
if(do_hide) {
HideCursor();
} else {
ShowCursor();
}
#endif
}
void
update_main_window_size()
{
#ifdef ENABLEQD
Rect win_rect;
int width, height;
int left, excess_height;
int top, bottom;
GetPortBounds(GetWindowPort(g_main_window), &win_rect);
width = win_rect.right - win_rect.left;
height = win_rect.bottom - win_rect.top;
g_video_act_width = width;
g_video_act_height = height;
left = MAX(0, (width - A2_WINDOW_WIDTH) / 2);
left = MIN(left, BASE_MARGIN_LEFT);
g_video_act_margin_left = left;
g_video_act_margin_right = left;
excess_height = (height - A2_WINDOW_HEIGHT) / 2;
bottom = MAX(0, excess_height / 2); // No less than 0
bottom = MIN(BASE_MARGIN_BOTTOM, bottom); // No more than 30
g_video_act_margin_bottom = bottom;
excess_height -= bottom;
top = MAX(0, excess_height);
top = MIN(BASE_MARGIN_TOP, top);
g_video_act_margin_top = top;
#endif
}
// OG Adding release
void x_release_kimage(Kimage* kimage_ptr)
{
if (kimage_ptr->dev_handle == (void*)-1)
{
free(kimage_ptr->data_ptr);
kimage_ptr->data_ptr = NULL;
}
else
{
if (!macUsingCoreGraphics)
{
#ifdef ENABLEQD
UnlockPixels((PixMapHandle)kimage_ptr->dev_handle);
kimage_ptr->dev_handle = NULL;
DisposeGWorld((GWorldPtr)kimage_ptr->dev_handle2);
kimage_ptr->dev_handle2 = NULL;
#endif
}
}
}
// OG Addding ratio
int x_calc_ratio(float x,float y)
{
return 1;
}
void
clipboard_paste(void)
{
#define CHUNK_SIZE 1024
char buffer[CHUNK_SIZE];
int bufsize = 1;
void *expanding_buffer = 0x00;
if (g_clipboard)
{
g_clipboard_pos = 0;
free(g_clipboard);
g_clipboard = 0x00;
}
FILE *pipe = popen("pbpaste", "r");
if (pipe)
{
expanding_buffer = calloc(CHUNK_SIZE+1,1);
bufsize = CHUNK_SIZE;
while (!feof(pipe))
{
if (fgets(buffer, CHUNK_SIZE, pipe) != NULL)
{
while (strlen((char*)expanding_buffer) + strlen(buffer) > bufsize)
{
bufsize += CHUNK_SIZE + 1;
expanding_buffer = realloc(expanding_buffer, bufsize);
}
/* Skip the leading return character when this is the first line in the paste buffer */
if (strlen((char*)expanding_buffer) > 0)
strcat((char*)expanding_buffer,"\r");
strncat((char*)expanding_buffer,buffer,strlen(buffer));
g_clipboard = (char*)expanding_buffer;
}
}
}
}
int clipboard_get_char(void)
{
if (!g_clipboard)
return 0;
if (g_clipboard[g_clipboard_pos] == '\n')
g_clipboard_pos++;
if (g_clipboard[g_clipboard_pos] == '\0')
return 0;
return g_clipboard[g_clipboard_pos++] | 0x80;
}

View File

@ -0,0 +1,118 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <ctype.h>
#ifdef _WIN32
# include <winsock2.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <netdb.h>
#endif
#if defined(HPUX) || defined(__linux__) || defined(SOLARIS) || defined(MAC) || defined(__MACH__) || defined(_WIN32)
# define SCC_SOCKETS
#endif
/* my scc port 0 == channel A, port 1 = channel B */
// LLAP may have packets up to 603 bytes, and the buffers must be large enough to contain a single packet.
#define SCC_INBUF_SIZE 1024 /* must be a power of 2 */
#define SCC_OUTBUF_SIZE 1024 /* must be a power of 2 */
#define SCC_MODEM_MAX_CMD_STR 128
#ifndef SOCKET
# define SOCKET word32 /* for non-windows */
#endif
STRUCT(Scc) {
int port;
int state /* 0 == disconnected, 1 == real serial port, 2 == socket, 3 == LocalTalk */;
int accfd;
SOCKET sockfd;
int socket_state;
int rdwrfd;
void *host_handle;
void *host_handle2;
int host_aux1;
int read_called_this_vbl;
int write_called_this_vbl;
int mode;
int reg_ptr;
int reg[16];
int rx_queue_depth;
byte rx_queue[4];
unsigned int lad;
int in_rdptr;
int in_wrptr;
byte in_buf[SCC_INBUF_SIZE];
int out_rdptr;
int out_wrptr;
byte out_buf[SCC_OUTBUF_SIZE];
int br_is_zero;
int tx_buf_empty;
int wantint_rx;
int wantint_tx;
int wantint_zerocnt;
int did_int_rx_first;
int dcd;
int sdlc_eof;
int eom;
double br_dcycs;
double tx_dcycs;
double rx_dcycs;
int br_event_pending;
int rx_event_pending;
int tx_event_pending;
byte irq_pending;
int char_size;
int baud_rate;
double out_char_dcycs;
int socket_num_rings;
int socket_last_ring_dcycs;
word32 modem_mode;
int modem_dial_or_acc_mode;
int modem_plus_mode;
int modem_s0_val;
int telnet_mode;
int telnet_iac;
word32 telnet_local_mode[2];
word32 telnet_remote_mode[2];
word32 telnet_reqwill_mode[2];
word32 telnet_reqdo_mode[2];
int modem_cmd_len;
byte modem_cmd_str[SCC_MODEM_MAX_CMD_STR + 5];
};
#define SCCMODEM_NOECHO 0x0001
#define SCCMODEM_NOVERBOSE 0x0002

View File

@ -0,0 +1,66 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined (__OS2__)
# include <sys/ipc.h>
# include <sys/shm.h>
#endif
#define SOUND_SHM_SAMP_SIZE (32*1024)
#define SAMPLE_SIZE 2
#define NUM_CHANNELS 2
#define SAMPLE_CHAN_SIZE (SAMPLE_SIZE * NUM_CHANNELS)
STRUCT(Doc_reg) {
double dsamp_ev;
double dsamp_ev2;
double complete_dsamp;
int samps_left;
word32 cur_acc;
word32 cur_inc;
word32 cur_start;
word32 cur_end;
word32 cur_mask;
int size_bytes;
int event;
int running;
int has_irq_pending;
word32 freq;
word32 vol;
word32 waveptr;
word32 ctl;
word32 wavesize;
word32 last_samp_val;
};
/* prototypes for win32snd_driver.c functions */
void win32snd_init(word32 *);
void win32snd_shutdown();
void win32snd_shutdown();
void child_sound_init_win32();
int win32_send_audio(byte *ptr, int size);
/* Prototypes for macsnd_driver.c functions */
int mac_send_audio(byte *ptr, int in_size);
void child_sound_init_mac();
void macsnd_init(word32 *shmaddr);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,218 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This file is included by video.c */
void
SUPER_TYPE(byte *screen_data, int pixels_per_line, int y, int scan,
word32 ch_mask, int use_a2vid_palette, int mode_640)
{
word32 *palptr;
word32 mem_ptr;
byte val0;
int x1, x2;
byte *b_ptr;
word32 *img_ptr, *img_ptr2;
word32 tmp, tmp2;
word32 ch_tmp;
byte *slow_mem_ptr;
int shift_per;
word32 pal;
word32 pal_word;
word32 pix0, pix1, pix2, pix3;
word32 save_pix;
int offset, next_line_offset;
int dopr;
mem_ptr = 0xa0 * y + 0x12000;
tmp2 = 0;
tmp = 0;
shift_per = (1 << SHIFT_PER_CHANGE);
if(use_a2vid_palette) {
pal = (g_a2vid_palette & 0xf);
} else {
pal = (scan & 0xf);
}
if(SUPER_FILL) {
ch_mask = -1;
save_pix = 0;
}
if(use_a2vid_palette) {
palptr = &(g_a2vid_palette_remap[0]);
} else {
palptr = &(g_palette_8to1624[pal * 16]);
}
dopr = 0;
#if 0
if(y == 1) {
dopr = 1;
printf("superhires line %d has ch_mask: %08x\n", y, ch_mask);
}
#endif
for(x1 = 0; x1 < 0xa0; x1 += shift_per) {
CH_LOOP_A2_VID(ch_mask, ch_tmp);
pal_word = (pal << 28) + (pal << 20) + (pal << 12) +
(pal << 4);
if(mode_640 && !use_a2vid_palette) {
#ifdef GSPORT_LITTLE_ENDIAN
pal_word += 0x04000c08;
#else
pal_word += 0x080c0004;
#endif
}
slow_mem_ptr = &(g_slow_memory_ptr[mem_ptr + x1]);
offset = y*2*pixels_per_line + x1*4;
next_line_offset = pixels_per_line;
#if SUPER_PIXEL_SIZE == 16
offset *= 2;
next_line_offset *= 2;
#elif SUPER_PIXEL_SIZE == 32
offset *= 4;
next_line_offset *= 4;
#endif
b_ptr = &screen_data[offset];
img_ptr = (word32 *)b_ptr;
img_ptr2 = (word32 *)(b_ptr + next_line_offset);
if(mode_640) {
for(x2 = 0; x2 < shift_per; x2++) {
val0 = *slow_mem_ptr++;
pix0 = (val0 >> 6) & 0x3;
pix1 = (val0 >> 4) & 0x3;
pix2 = (val0 >> 2) & 0x3;
pix3 = val0 & 0x3;
if(use_a2vid_palette || (SUPER_PIXEL_SIZE > 8)){
pix0 = palptr[pix0+8];
pix1 = palptr[pix1+12];
pix2 = palptr[pix2+0];
pix3 = palptr[pix3+4];
}
#if SUPER_PIXEL_SIZE == 8
# ifdef GSPORT_LITTLE_ENDIAN
tmp = (pix3 << 24) + (pix2 << 16) +
(pix1 << 8) + pix0 + pal_word;
# else
tmp = (pix0 << 24) + (pix1 << 16) +
(pix2 << 8) + pix3 + pal_word;
# endif
*img_ptr++ = tmp; *img_ptr2++ = tmp;
#elif SUPER_PIXEL_SIZE == 16
# ifdef GSPORT_LITTLE_ENDIAN
tmp = (pix1 << 16) + pix0;
tmp2 = (pix3 << 16) + pix2;
# else
tmp = (pix0 << 16) + pix1;
tmp2 = (pix2 << 16) + pix3;
# endif
*img_ptr++ = tmp;
*img_ptr++ = tmp2;
*img_ptr2++ = tmp;
*img_ptr2++ = tmp2;
#else /* SUPER_PIXEL_SIZE == 32 */
*img_ptr++ = pix0;
*img_ptr++ = pix1;
*img_ptr++ = pix2;
*img_ptr++ = pix3;
*img_ptr2++ = pix0;
*img_ptr2++ = pix1;
*img_ptr2++ = pix2;
*img_ptr2++ = pix3;
#endif
#if 0
if(y == 1 && x1 == 0 && x2 == 0) {
printf("y==1,x1,x2=0, %02x = %08x %08x "
"%08x %08x, pal: %04x\n", val0,
pix0, pix1, pix2, pix3, pal);
printf("offset: %04x, nlo:%04x, ppl:"
"%04x, %d\n", offset,
next_line_offset,
pixels_per_line, SUPER_PIXEL_SIZE);
}
#endif
}
} else { /* 320 mode */
for(x2 = 0; x2 < shift_per; x2++) {
val0 = *slow_mem_ptr++;
pix0 = (val0 >> 4);
if(SUPER_FILL) {
if(pix0) {
save_pix = pix0;
} else {
pix0 = save_pix;
}
}
pix1 = (val0 & 0xf);
if(SUPER_FILL) {
if(pix1) {
save_pix = pix1;
} else {
pix1 = save_pix;
}
}
if(use_a2vid_palette || (SUPER_PIXEL_SIZE > 8)){
pix0 = palptr[pix0];
pix1 = palptr[pix1];
}
if(dopr && x1 == 0) {
printf("y:%d, x2:%d, val:%02x = %08x %08x\n", y, x2, val0, pix0, pix1);
}
#if SUPER_PIXEL_SIZE == 8
# ifdef GSPORT_LITTLE_ENDIAN
tmp = (pix1 << 24) + (pix1 << 16) +
(pix0 << 8) + pix0 + pal_word;
# else
tmp = (pix0 << 24) + (pix0 << 16) +
(pix1 << 8) + pix1 + pal_word;
# endif
*img_ptr++ = tmp; *img_ptr2++ = tmp;
#elif SUPER_PIXEL_SIZE == 16
tmp = (pix0 << 16) + pix0;
tmp2 = (pix1 << 16) + pix1;
*img_ptr++ = tmp;
*img_ptr++ = tmp2;
*img_ptr2++ = tmp;
*img_ptr2++ = tmp2;
#else /* SUPER_PIXEL_SIZE == 32 */
*img_ptr++ = pix0;
*img_ptr++ = pix0;
*img_ptr++ = pix1;
*img_ptr++ = pix1;
*img_ptr2++ = pix0;
*img_ptr2++ = pix0;
*img_ptr2++ = pix1;
*img_ptr2++ = pix1;
#endif
}
}
}
}

View File

@ -0,0 +1,76 @@
# GSport OS/2 makefile
TARGET = gsport.exe
OBJECTS1 = dirport.obj adb.obj clock.obj dis.obj engine_c.obj scc.obj \
iwm.obj joystick_driver.obj moremem.obj paddles.obj \
sim65816.obj smartport.obj sound.obj \
video.obj config.obj scc_socket_os2.obj os2driver.obj os2snd_driver.obj
{..\..}.c.obj:
@echo " Compile::C++ Compiler "
icc.exe /DTCPV40HDRS /DBSD_SELECT /Dinline= /I..\.. /Ss /Q /Ti /Gm /G4 /Ft- /C %s
{src\}.c.obj:
@echo " Compile::C++ Compiler "
icc.exe /DTCPV40HDRS /DBSD_SELECT /Dinline= /I..\.. /Ss /Q /Ti /Gm /G4 /Ft- /C %s
.c.obj:
@echo " Compile::C++ Compiler "
icc.exe /DTCPV40HDRS /DBSD_SELECT /Dinline= /I..\.. /Ss /Q /Ti /Gm /G4 /Ft- /C %s
$(TARGET): $(OBJECTS1)
@echo " Link::Linker "
icc.exe @<<
/B" /de /pmtype:pm /st:196608 "
/Fe$(TARGET)
so32dll.lib
tcp32dll.lib
$(OBJECTS1)
<<
rc gsportos2.rc $(TARGET)
echo done
clean:
- rm $(OBJECTS1)
- rm $(TARGET)
- rm gsportos2.res
- rm ../../size_s.h
- rm ../../size_c.h
- rm ../../8size_s.h
- rm ../../16size_s.h
- rm ../../8inst_s.h
- rm ../../8inst_c.h
- rm ../../16inst_s.h
- rm ../../16inst_c.h
../../size_c.h:
call make_size.cmd
../../8inst_c.h:
call make_inst.cmd
# dependency stuff
dirport.obj: src/dirport.c src/dirport.h
adb.obj: ../../adb.c ../../adb.h ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h
engine_c.obj: ../../engine_c.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../protos_engine_c.h ../../size_c.h ../../op_routs.h ../../defs_instr.h ../../8inst_c.h ../../16inst_c.h
clock.obj: ..\..\clock.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h
compile_time.obj: ../../compile_time.c
config.obj: ../../config.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../config.h
dis.obj: ../../dis.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../disas.h
scc.obj: ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../scc.h
scc_socket_driver.obj: ../../scc_socket_driver.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../scc.h
scc_socket_os2.obj: scc_socket_os2.c
iwm.obj: ../../iwm.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../iwm_35_525.h
joystick_driver.obj: ../../joystick_driver.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h
moremem.obj: ../../moremem.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h
paddles.obj: ../../paddles.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h
parallel.obj: ../../parallel.c ../../defc.h
printer.obj: ../../printer.cpp
sim65816.obj: ../../sim65816.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h
smartport.obj: ../../smartport.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h
sound.obj: ../../sound.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h
sound_driver.obj: ../../sound_driver.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../sound.h
video.obj: ../../video.c ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h ../../superhires.h ../../gsportfont.h
os2driver.obj: os2driver.c gsportos2.h ../../scc.c ../../defc.h ../../defcomm.h ../../iwm.h ../../protos.h
os2snd_driver.obj: os2snd_driver.c

View File

@ -0,0 +1,905 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "defc.h"
#include <ctype.h>
#include "prodos.h"
#include <errno.h>
#define DEF_DISK_SIZE (800*1024)
#define MAX_FILE_NAMES 51
char out_name[] = "POOF1";
int g_def_file_type = -1;
int g_def_aux_type = -1;
void make_legal_prodos_name(char *new_name, char *old_name);
int
main(int argc, char **argv)
{
char *files[MAX_FILE_NAMES];
char *name;
char *new_name_end;
int new_name_len;
struct stat stat_buf;
int in;
int in_size;
int ret;
ProDisk *disk;
char new_name[128];
byte in_buf[1024];
int disk_size;
int i;
int done;
int pos;
int size;
int num_files;
int file_type;
int aux_type;
disk_size = DEF_DISK_SIZE;
if(argc < 2) {
fprintf(stderr, "%s: {-[size in K]} {unix_files}\n",
argv[0]);
exit(1);
}
num_files = 0;
for(i = 1; i < argc; i++) {
if(argv[i][0] == '-') {
/* I smell a -size_in_K */
disk_size = strtoul(&(argv[i][1]), 0, 10) * 1024;
printf("disk_size: %d, 0x%x\n", disk_size, disk_size);
if(disk_size < 40*1024) {
printf("Too small!\n");
exit(1);
}
} else {
files[num_files] = argv[i];
num_files++;
if(num_files >= MAX_FILE_NAMES) {
printf("Too many filenames: %d\n", num_files);
exit(2);
}
}
}
disk = allocate_memdisk(out_name, disk_size);
format_memdisk(disk, out_name);
for(i = 0; i < num_files; i++) {
name = files[i];
in = open(name, O_RDONLY | O_BINARY);
if(in < 0) {
fprintf(stderr, "opening %s returned %d, errno: %d\n",
name, in, errno);
exit(1);
}
ret = fstat(in, &stat_buf);
if(ret != 0) {
fprintf(stderr, "fstat returned %d, errno: %d\n",
ret, errno);
}
in_size = stat_buf.st_size;
printf("in size: %d\n", in_size);
if(in_size > disk->disk_bytes_left) {
printf("File bigger than %d, too big!\n", disk_size);
exit(2);
}
make_legal_prodos_name(new_name, name);
new_name_len = strlen(new_name);
new_name_end = new_name + new_name_len;
file_type = g_def_file_type;
aux_type = g_def_aux_type;
while(g_def_file_type < 0) {
/* choose file type */
if(new_name_len >= 5) {
if(strcmp(new_name_end - 4, ".SHK") == 0) {
file_type = 0xe0;
aux_type = 0x8002;
break;
}
if(strcmp(new_name_end - 4, ".SDK") == 0) {
file_type = 0xe0;
aux_type = 0x8002;
break;
}
}
file_type = 0x04; /* TXT */
aux_type = 0;
break;
}
create_new_file(disk, 2, 1, new_name, file_type,
0, 0, 0, 0xc3, aux_type, 0, in_size);
done = 0;
pos = 0;
while(pos < in_size) {
size = 512;
if(pos + size > in_size) {
size = in_size - pos;
}
ret = read(in, in_buf, size);
if(ret != size || ret <= 0) {
fprintf(stderr, "read returned %d, errno: %d\n",
ret, errno);
exit(2);
}
ret = pro_write_file(disk, in_buf, pos, size);
if(ret != 0) {
printf("pro_write returned %d!\n", ret);
exit(3);
}
pos += size;
}
close_file(disk);
close(in);
}
flush_disk(disk);
return 0;
}
void
make_legal_prodos_name(char *new_name, char *old_name)
{
char *ptr;
int start_len, start_char;
int len;
int pos;
int c;
int j;
for(j = 0; j < 16; j++) {
/* make sure it ends with null == 15 + 1 */
new_name[j] = 0;
}
start_char = 0;
start_len = strlen(old_name);
len = 0;
ptr = &old_name[start_len - 1];
for(j = start_len - 1; j >= 0; j--) {
if(*ptr == '/' || *ptr == ':') {
break;
}
ptr--;
len++;
}
ptr++;
if(len <= 0) {
printf("Filename: %s has len: %d!\n", old_name, len);
exit(1);
}
printf("mid_name: %s, len:%d\n", ptr, len);
pos = 0;
for(j = 0; j < 15; j++) {
c = ptr[pos];
if(isalnum(c)) {
c = toupper(c);
} else if(c != 0) {
c = '.';
}
if(j == 0 && !isalpha(c)) {
c = 'A';
}
new_name[j] = c;
pos++;
if(pos == 7 && len > 15) {
pos = len - 8;
}
}
printf("new_name: %s\n", new_name);
}
void
flush_disk(ProDisk *disk)
{
disk_write_data(disk, 6, disk->bitmap_ptr,
disk->size_bitmap_blocks * 512);
close(disk->fd);
disk->fd = -1;
}
void
close_file(ProDisk *disk)
{
write_ind_block(disk);
write_master_ind_block(disk);
disk_write_data(disk, disk->dir_blk_num, &(disk->dir_blk_data[0]), 512);
disk->file_ptr = 0;
}
ProDisk *
allocate_memdisk(char *out_name, int size)
{
ProDisk *disk;
int out;
out = open(out_name, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0x1b6);
if(out < 0) {
fprintf(stderr, "opening %s returned %d, errno: %d\n",
out_name, out, errno);
exit(1);
}
disk = (ProDisk *)malloc(sizeof(ProDisk));
if(disk == 0) {
printf("allocate_memdisk failed, errno: %d\n", errno);
}
disk->fd = out;
disk->total_blocks = (size + 511) / 512;
disk->bitmap_ptr = 0;
disk->disk_bytes_left = 0;
disk->size_bitmap_blocks = 0;
disk->dir_blk_num = -1;
disk->ind_blk_num = -1;
disk->master_ind_blk_num = -1;
return disk;
}
void
format_memdisk(ProDisk *disk, char *name)
{
byte zero_buf[1024];
int total_blocks;
byte *bitmap_ptr;
Vol_hdr *vol_hdr;
Directory *dir;
int size_bitmap_bytes;
int size_bitmap_blocks;
int disk_blocks_left;
int i, j;
total_blocks = disk->total_blocks;
/* Zero out blocks 0 and 1 */
for(i = 0; i < 2*512; i++) {
zero_buf[i] = 0;
}
disk_write_data(disk, 0x00000, zero_buf, 2*512);
/* and make the image the right size */
disk_write_data(disk, total_blocks - 1, zero_buf, 512);
dir = disk_read_dir(disk, 2);
set_l2byte(&(dir->prev_blk), 0);
set_l2byte(&(dir->next_blk), 3);
vol_hdr = (Vol_hdr *)&(dir->file_entries[0]);
vol_hdr->storage_type_name_len = 0xf0 + strlen(name);
strncpy((char *)vol_hdr->vol_name, name, strlen(name));
vol_hdr->version = 0;
vol_hdr->min_version = 0;
vol_hdr->access = 0xc3;
vol_hdr->entry_length = 0x27;
vol_hdr->entries_per_block = 0x0d;
set_l2byte(&(vol_hdr->file_count), 0);
vol_hdr->entries_per_block = 0x0d;
set_l2byte(&(vol_hdr->bit_map), 6);
set_l2byte(&(vol_hdr->total_blocks), total_blocks);
for(i = 1; i < 13; i++) {
set_file_entry(&(dir->file_entries[i]), 0, "", 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0);
}
disk_write_dir(disk, 2);
for(i = 3; i < 6; i++) {
dir = disk_read_dir(disk, i);
set_l2byte(&(dir->prev_blk), i - 1);
set_l2byte(&(dir->next_blk), i + 1);
if(i == 5) {
set_l2byte(&(dir->next_blk), 0);
}
for(j = 0; j < 13; j++) {
set_file_entry(&(dir->file_entries[j]), 0, "", 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0);
}
disk_write_dir(disk, i);
}
size_bitmap_bytes = (total_blocks + 7)/ 8;
size_bitmap_blocks = (size_bitmap_bytes + 511)/ 512;
bitmap_ptr = (byte *)malloc(size_bitmap_blocks * 512);
for(i = 0; i < 6+size_bitmap_blocks; i++) {
set_bitmap_used(bitmap_ptr, i);
}
for(i = 6+size_bitmap_blocks; i < total_blocks; i++) {
set_bitmap_free(bitmap_ptr, i);
}
for(i = total_blocks; i < size_bitmap_blocks*512*8; i++) {
set_bitmap_used(bitmap_ptr, i);
}
disk_write_data(disk, 6, bitmap_ptr, size_bitmap_blocks * 512);
disk->bitmap_ptr = bitmap_ptr;
disk->size_bitmap_blocks = size_bitmap_blocks;
disk->bitmap_bytes = size_bitmap_blocks * 512;
disk->bitmap_cur_pos = 0;
disk_blocks_left = total_blocks - 6 - size_bitmap_blocks;
disk->disk_bytes_left = disk_blocks_left * 512;
}
void
disk_write_data(ProDisk *disk, int blk_num, byte *buf, int size)
{
int size_in_blocks;
int ret;
#if 0
printf("Writing blk %04x from buf: %08x, %03x\n", blk_num, buf, size);
#endif
size_in_blocks = size >> 9;
if(size_in_blocks * 512 != size) {
printf("disk_write: blk: %04x, buf: %08x, size: %08x\n",
blk_num, (word32)buf, size);
exit(1);
}
ret = lseek(disk->fd, 512*blk_num, SEEK_SET);
if(ret != 512*blk_num) {
printf("disk_write: seek: %d, errno: %d, blk: %04x, buf: "
"%08x, sz: %08x\n", ret, errno, blk_num,
(word32)buf, size);
exit(1);
}
ret = write(disk->fd, buf, size);
if(ret != size) {
printf("disk_write: write: %d, errno: %d, blk: %04x, buf: "
"%08x, sz: %08x\n", ret, errno, blk_num,
(word32)buf, size);
exit(1);
}
}
void
disk_read_data(ProDisk *disk, int blk_num, byte *buf, int size)
{
int size_in_blocks;
int ret;
int i;
size_in_blocks = size >> 9;
if(size_in_blocks * 512 != size) {
printf("disk_read: blk: %04x, buf: %08x, size: %08x\n",
blk_num, (word32)buf, size);
exit(1);
}
ret = lseek(disk->fd, 512*blk_num, SEEK_SET);
if(ret != 512*blk_num) {
printf("disk_read: seek: %d, errno: %d, blk: %04x, buf: "
"%08x, sz: %08x\n", ret, errno, blk_num,
(word32)buf, size);
exit(1);
}
ret = read(disk->fd, buf, size);
if(ret != size) {
printf("disk_read: read: %d, errno: %d, blk: %04x, buf: "
"%08x, sz: %08x\n", ret, errno, blk_num,
(word32)buf, size);
for(i = 0; i < size; i++) {
buf[i] = 0;
}
}
}
Directory *
disk_read_dir(ProDisk *disk, int blk_num)
{
disk_write_dir(disk, blk_num);
disk->dir_blk_num = blk_num;
disk_read_data(disk, blk_num, &(disk->dir_blk_data[0]), 512);
return (Directory *)&(disk->dir_blk_data[0]);
}
void
disk_write_dir(ProDisk *disk, int blk_num)
{
if(disk->dir_blk_num >= 0) {
if(disk->dir_blk_num != blk_num) {
printf("disk_write_dir: %04x != %04x\n",
disk->dir_blk_num, blk_num);
}
disk_write_data(disk, disk->dir_blk_num,
&(disk->dir_blk_data[0]), 512);
disk->dir_blk_num = -1;
}
}
void
create_new_file(ProDisk *disk, int dir_block, int storage_type, char *name,
int file_type, word32 creation_time, int version, int min_version,
int access, int aux_type, word32 last_mod, word32 eof)
{
Vol_hdr *vol_ptr;
int val;
Directory *dir_ptr;
File_entry *file_ptr;
int file_count;
int pos;
int last_pos;
int done;
int next_blk;
int name_len;
name_len = strlen(name);
dir_ptr = disk_read_dir(disk, dir_block);
next_blk = dir_block;
val = dir_ptr->file_entries[0].storage_type_name_len;
last_pos = 13;
pos = 0;
if(((val & 0xf0) == 0xf0) || ((val & 0xf0) == 0xe0)) {
/* vol dir or subdir header */
vol_ptr = (Vol_hdr *)&(dir_ptr->file_entries[0]);
file_count = get_l2byte(&(vol_ptr->file_count));
pos = 1;
last_pos = vol_ptr->entries_per_block;
} else {
printf("dir_block: %04x not subdir or voldir\n", dir_block);
exit(6);
}
vol_ptr = 0;
done = 0;
while(!done) {
file_ptr = &(dir_ptr->file_entries[pos]);
if(((file_ptr->storage_type_name_len) & 0xf0) == 0) {
/* Got it! */
file_ptr->storage_type_name_len =
(storage_type << 4) | name_len;
strncpy((char *)file_ptr->file_name, name, 15);
file_ptr->file_type = file_type;
set_l2byte(&(file_ptr->key_pointer),
find_next_free_block(disk));
set_l2byte(&(file_ptr->blocks_used), 0);
set_pro_time(&(file_ptr->creation_time),
creation_time);
file_ptr->version = version;
file_ptr->min_version = min_version;
file_ptr->access = access;
set_l2byte(&(file_ptr->aux_type), aux_type);
set_pro_time(&(file_ptr->last_mod), last_mod);
set_l2byte(&(file_ptr->header_pointer),
dir_block);
set_l3byte(&(file_ptr->eof), eof);
disk_write_dir(disk, next_blk);
dir_ptr = disk_read_dir(disk, dir_block);
vol_ptr = (Vol_hdr *)&(dir_ptr->file_entries[0]);
set_l2byte(&(vol_ptr->file_count), file_count+1);
disk_write_dir(disk, dir_block);
disk_read_dir(disk, next_blk);
/* re-read dir so that ptrs are set up right */
disk->file_ptr = file_ptr;
disk->file_open = 1;
disk->ind_blk_num = -1;
disk->master_ind_blk_num = -1;
done = 1;
break;
} else {
/* check to make sure name is unique */
if((file_ptr->storage_type_name_len & 0x0f)== name_len){
if(!memcmp(file_ptr->file_name, name,name_len)){
printf("Name %s already on disk!\n",
name);
exit(8);
}
}
pos++;
if(pos >= last_pos) {
/* Go to next block */
next_blk = get_l2byte(&(dir_ptr->next_blk));
if(next_blk) {
dir_ptr = disk_read_dir(disk, next_blk);
pos = 0;
} else {
printf("Top directory full!\n");
exit(2);
}
}
}
}
}
int
pro_write_file(ProDisk *disk, byte *in_buf, int pos, int size)
{
int block;
int i;
block = get_disk_block(disk, pos, 1);
if(block < 7) {
printf("pro_write_file, get_disk_block: %d\n", block);
exit(3);
}
if(size < 512) {
for(i = size; i < 512; i++) {
in_buf[i] = 0;
}
} else if(size > 512) {
printf("error, pro_write_file size: %d too big\n", size);
exit(4);
}
disk_write_data(disk, block, in_buf, 512);
return 0;
}
int
get_disk_block(ProDisk *disk, int pos, int create)
{
File_entry *file_ptr;
int storage_type;
word32 eof;
int lo, hi;
int offset;
int master_ind_block, ind_block;
int ret_block;
int key_block;
if(pos >= 128*256*512) {
printf("offset too big\n");
exit(3);
}
file_ptr = disk->file_ptr;
eof = get_l3byte(&(file_ptr->eof));
storage_type = (file_ptr->storage_type_name_len) >> 4;
key_block = get_l2byte(&(file_ptr->key_pointer));
if(storage_type == 1 && pos >= 512) {
/* make it sapling */
get_new_ind_block(disk);
inc_l2byte(&(file_ptr->blocks_used));
disk->ind_blk_data[0] = key_block & 0xff;
disk->ind_blk_data[0x100] = key_block >> 8;
key_block = disk->ind_blk_num;
set_l2byte(&(file_ptr->key_pointer), key_block);
file_ptr->storage_type_name_len += 0x10;
storage_type++;
}
if(storage_type == 2 && pos >= 256*512) {
/* make it tree */
get_new_master_ind_block(disk);
inc_l2byte(&(file_ptr->blocks_used));
disk->master_ind_blk_data[0] = key_block & 0xff;
disk->master_ind_blk_data[0x100] = key_block >> 8;
key_block = disk->master_ind_blk_num;
set_l2byte(&(file_ptr->key_pointer), key_block);
file_ptr->storage_type_name_len += 0x10;
storage_type++;
}
switch(storage_type) {
case 1:
if(pos >= 512) {
printf("Error1!\n");
exit(3);
}
ret_block = key_block;
if(ret_block == 0) {
ret_block = find_next_free_block(disk);
inc_l2byte(&(file_ptr->blocks_used));
set_l2byte(&(file_ptr->key_pointer), ret_block);
}
return ret_block;
case 2:
ind_block = key_block;
if(ind_block <= 0) {
printf("write failure, ind_block: %d!\n", ind_block);
exit(3);
}
offset = pos >> 9;
if(offset >= 256) {
printf("pos too big!\n");
exit(3);
}
lo = disk->ind_blk_data[offset];
hi = disk->ind_blk_data[offset + 0x100];
ret_block = hi*256 + lo;
if(ret_block == 0) {
/* Need to alloc a block for this guy */
ret_block = find_next_free_block(disk);
inc_l2byte(&(file_ptr->blocks_used));
disk->ind_blk_data[offset] = ret_block & 0xff;
disk->ind_blk_data[offset + 0x100] =
((ret_block >> 8) & 0xff);
}
return ret_block;
case 3:
/* tree */
master_ind_block = key_block;
if(master_ind_block <= 0) {
printf("write failure, master_ind_block: %d!\n",
master_ind_block);
exit(3);
}
offset = pos >> 17;
if(offset >= 128) {
printf("master too big!\n");
exit(4);
}
lo = disk->master_ind_blk_data[offset];
hi = disk->master_ind_blk_data[offset + 0x100];
ind_block = hi*256 + lo;
if(ind_block == 0) {
/* Need to alloc an ind block */
get_new_ind_block(disk);
ind_block = disk->ind_blk_num;
inc_l2byte(&(file_ptr->blocks_used));
disk->master_ind_blk_data[offset] = ind_block & 0xff;
disk->master_ind_blk_data[offset + 0x100] =
((ind_block >> 8) & 0xff);
}
offset = (pos >> 9) & 0xff;
lo = disk->ind_blk_data[offset];
hi = disk->ind_blk_data[offset + 0x100];
ret_block = hi*256 + lo;
if(ret_block == 0) {
/* Need to alloc a block for this guy */
ret_block = find_next_free_block(disk);
inc_l2byte(&(file_ptr->blocks_used));
disk->ind_blk_data[offset] = ret_block & 0xff;
disk->ind_blk_data[offset + 0x100] =
((ret_block >> 8) & 0xff);
}
return ret_block;
default:
printf("unknown storage type: %d\n", storage_type);
exit(4);
}
printf("Can't get here!\n");
exit(5);
}
void
get_new_ind_block(ProDisk *disk)
{
int ind_blk_num;
int i;
write_ind_block(disk);
ind_blk_num = find_next_free_block(disk);
for(i = 0; i < 512; i++) {
disk->ind_blk_data[i] = 0;
}
disk->ind_blk_num = ind_blk_num;
}
void
write_ind_block(ProDisk *disk)
{
int ind_blk_num;
ind_blk_num = disk->ind_blk_num;
if(ind_blk_num > 0) {
printf("Write ind block: %04x\n", ind_blk_num);
disk_write_data(disk, ind_blk_num, &(disk->ind_blk_data[0]),
512);
disk->ind_blk_num = -1;
}
}
void
get_new_master_ind_block(ProDisk *disk)
{
int master_ind_blk_num;
int i;
write_master_ind_block(disk);
master_ind_blk_num = find_next_free_block(disk);
for(i = 0; i < 512; i++) {
disk->master_ind_blk_data[i] = 0;
}
disk->master_ind_blk_num = master_ind_blk_num;
}
void
write_master_ind_block(ProDisk *disk)
{
int master_ind_blk_num;
master_ind_blk_num = disk->master_ind_blk_num;
if(master_ind_blk_num > 0) {
printf("Write master_ind block: %04x\n", master_ind_blk_num);
disk_write_data(disk, master_ind_blk_num,
&(disk->master_ind_blk_data[0]), 512);
disk->master_ind_blk_num = -1;
}
}
int
find_next_free_block(ProDisk *disk)
{
byte *bitmap_ptr;
int pos;
int bitmap_bytes;
int i, j;
word32 val;
bitmap_ptr = disk->bitmap_ptr;
bitmap_bytes = disk->bitmap_bytes;
pos = disk->bitmap_cur_pos;
for(i = pos; i < bitmap_bytes; i++) {
val = bitmap_ptr[i];
if(val == 0) {
continue;
}
for(j = 0; j < 8; j++) {
if(val & (0x80 >> j)) {
set_bitmap_used(bitmap_ptr, 8*i+j);
disk->bitmap_cur_pos = i;
return 8*i + j;
}
}
return -1;
}
return -1;
}
void
set_bitmap_used(byte *ptr, int i)
{
word32 offset, bit;
word32 val;
offset = i >> 3;
bit = i & 7;
val = ~(0x80 >> bit);
ptr[offset] &= val;
}
void
set_bitmap_free(byte *ptr, int i)
{
int offset, bit;
int val;
offset = i >> 3;
bit = i & 7;
val = (0x80 >> bit);
ptr[offset] |= val;
}
void
set_file_entry(File_entry *entry, int storage_type_name_len, char *file_name,
int file_type, int key_pointer, int blocks_used, int eof,
word32 creation_time, int version, int min_version, int access,
int aux_type, word32 last_mod, int header_pointer)
{
entry->storage_type_name_len = storage_type_name_len;
strncpy((char *)entry->file_name, file_name, 15);
entry->file_type = file_type;
set_l2byte(&(entry->key_pointer), key_pointer);
set_l2byte(&(entry->blocks_used), blocks_used);
set_l3byte(&(entry->eof), eof);
set_pro_time(&(entry->creation_time), creation_time);
entry->version = version;
entry->min_version = min_version;
entry->access = access;
set_l2byte(&(entry->aux_type), aux_type);
set_pro_time(&(entry->last_mod), last_mod);
set_l2byte(&(entry->aux_type), header_pointer);
}
void
set_l2byte(L2byte *ptr, int val)
{
ptr->low = (val & 0xff);
ptr->hi = ((val >> 8) & 0xff);
}
void
set_l3byte(L3byte *ptr, int val)
{
ptr->low = (val & 0xff);
ptr->hi = ((val >> 8) & 0xff);
ptr->higher = ((val >> 16) & 0xff);
}
void
set_pro_time(Pro_time *ptr, word32 val)
{
ptr->times[0] = ((val >> 24) & 0xff);
ptr->times[1] = ((val >> 16) & 0xff);
ptr->times[2] = ((val >> 8) & 0xff);
ptr->times[3] = ((val) & 0xff);
}
int
get_l2byte(L2byte *ptr)
{
int val;
val = ((ptr->hi) * 256) + ptr->low;
return val;
}
int
get_l3byte(L3byte *ptr)
{
int val;
val = ((ptr->higher) * 65536) + ((ptr->hi) * 256) + ptr->low;
return val;
}
void
inc_l2byte(L2byte *ptr)
{
set_l2byte(ptr, get_l2byte(ptr) + 1);
}

View File

@ -0,0 +1,148 @@
xdriver.c contains the routines for interfacing to X windows. The rest
of KEGS interacts with X windows only through xdriver.c routines.
Externally called routines are:
show_xcolor_array(): Debug routine, it does not need to do anything.
dev_video_init(): Called at startup, it should open up the
window and do other initialization.
update_physical_colormap(): Updates the X windows palette with the colors
from xcolor_a2vid_array[], which is maintained by
other xdriver routines.
update_status_line(): Call to update the internal array of chars
representing the status lines at the bottom of
the window. Does not draw the chars to the screen.
xdriver_end(): Shutdown routine
check_input_events(): Called up to 60 times a second (see video_update() in
video.c) to handle any X window events and get
keypresses.
On a mouse press, call update_mouse() with the
new x, y coordinates, and the status of the mouse
button.
If g_warp_pointer is set, constrain mouse within
the window.
On keypress, calls handle_keysym().
handle_keysym(): Takes X keysym, and converts to the appropriate
a2code using the a2_key_to_xsym[] lookup table.
The a2codes are the Apple // ADB keycodes.
Special work is done to handle shift and control
properly since Apple only has one keycode for both
shift and control keys. Then call
adb_physical_key_update() with the a2 keycode and
is_up = 1 if keyup, 0 = if key down.
In addition, this routine handles all the Function
keys doing special actions, which should be easy to
port.
x_refresh_ximage(): Redraws the window using the a2_line_* arrays.
Described in more detail below.
update_color_array(): Interface to the color map. Sets color[col_num]
of the internal colormap array to a2_color.
a2_color is the 12 bit apple color of the form:
(red << 8) + (green << 4) + (blue).
There are 16 palettes of 16 colors each, managed as
one 256-color colormap. See discussion of
g_a2vid_palette below.
x_auto_repeat_on(): The X routines turn off key repeat when the cursor
enters the graphics window automatically, and turn
it back on when the cursor leaves. But if the
debugger gets control due to a breakpoint, keyrepeat
would be left off. So the debugger calls this
routine to make sure key repeat is back on.
redraw_status_lines(): Draw the status lines from the g_status_buf[][] array
to the graphics window.
Externally referenced data:
g_use_shmem: Set by main() to enable/disable MIT-SHM for X.
Also used by sound routines to auto-turn-off sound
if not using MIT-SHM.
Bytes representing screen data:
byte *data_text[2]: Array of bytes for the lores and text pages 1 and 2.
Just 400*640 bytes.
byte *data_hires[2]: Array of bytes for the hires pages 1 and 2.
byte *data_superhires: Array of bytes for superhires screen.
byte *data_border_sides: Array of bytes representing the border sides.
Basically just A2_WINDOW_HEIGHT*EFF_BORDER_WIDTH bytes.
byte *data_border_special: Top and bottom border bytes.
(X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT + 2*8) *
(X_A2_WINDOW_WIDTH) bytes.
Handles used for X windows drawing:
XImage *ximage_hires[2]: Opaque handle to XImage object for hires page 1 and
page 2.
XImage *ximage_text[2]: Text pages 1 and 2.
XImage *ximage_superhires: Superhires graphics XImage
XImage *ximage_border_special: Top and bottom border XImage.
XImage *ximage_border_sides: Left and right sides (only one copy, it is
drawn at two different locations to be both sides).
Basic operation of xdriver:
--------------------------
X windows can push arrays of bytes to the screen through structures
called XImages. An XImage is a structure describing an offscreen bitmap.
For efficiency of page flipping, KEGS maintains separate bitmaps for the
two lores/text screens, the two hires screens, and the superhires screen.
It also maintains bitmaps for the border. For MIT-SHM to work, X
requires a unique XImage for each bitmap, and the bitmap must be allocated
within xdriver.c since it must be obtained through an shmat() call.
The X code also has non-MIT-SHM code which allocates the data_* buffers
just through malloc().
All bitmaps are 8-bits of Pseudo-color. The color arrays are managed
through the update_color_array() and update_physical_colormap() routines.
KEGS manages all 256 colors in the colormap as 16 palettes of 16 colors.
One of the palettes is reserved for the 16 lores colors, and is
indicated by the variable g_a2vid_palette. It defaults to 0xe.
Update_color_array() is called to update superhires colormap entries.
Update_color_array must not update colors corresponding to g_a2vid_palette.
Update_physical_colormap() pushes the color array managed by
update_color_array() to the screen, but first forces the lores colors into
the g_a2vid_palette palette. g_installed_full_superhires_colormap is
always false in KEGS for now. video.c calls update_color_array and changes
g_a2vid_palette. No xdriver routines gets notified when g_a2vid_palette
changes, so update_physical_colormap must handle the case where
g_a2vid_palette might have changed since it was last called.
x_redraw_ximage():
Routines in video.c are free to draw into the corresponding data_*
arrays to change any byte at any time. video.c manages remembering
which lines need to be redrawn and which parts of the screen are in
which video mode via the a2_line_* arrays.
KEGS divides the video screen up into 25 groups, corresponding to each
text line. Each of these groups consists of 16 sublines. 25*8 = 400 lines.
(video.c has already doubled the vertical resolution in all video modes).
KEGS can allow any group to be from any of the five screens it manages:
The two text/lores pages, the two hires pages, and the superhires screen.
For each group, KEGS keeps track of what part of it needs to be redrawn.
g_a2_screen_buffer_changed has a bit set for each group which has changed
since the last call to x_redraw_ximage(). The rightmost bit (bit 0)
corresponds to group 0. If g_a2_screen_buffer_changed == 0, no groups
need to be redrawn. x_redraw_ximage clears out g_a2_screen_buffer_changed
after drawing the screen.
For each group, a2_line_left_edge[] and a2_line_right_edge give the pixel
offsets of what should be redrawn. a2_line_xim[] gives the ximage handle
of what needs to be redrawn. KEGS always redraws 8 verticals of a group.
g_full_refresh_needed also has one bit set in it for each group, which
indicates overriding the a2_line_*_edge functions and redraw from 0 to
640 pixels of each group that needs to be redrawn. x_redraw_ximage()
interprets this information now using a simple algorithm: Skip over
groups which have not changed (using g_a2_screen_buffer_changed).
Save the ximage of this group, the left pixel and the right pixel.
Continue with the next group if it has changed. Widen the pixel region
and keep sucking up new groups to the same ximage. At group 25, or
when the ximage changes, call x_refresh_lines to redraw this large
rectangle from this ximage. x_refresh_lines() knows the ximage
corresponding to the border for the last group has to be handled
specially since the border group is not 640*400 pixels like the others.
Other porting info:
a2_key_to_xsym[][3] contains the mapping function from X keysyms to
a2 keycodes. The first element is the a2 keycode, the second element
is the unshifted X keysym, and the third element is the shifted keysym.
A port must make the conversion to a2 keycodes, and provide up and
down events.

View File

@ -0,0 +1,470 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ASM
.import get_mem_b0_16,code
.import get_mem_b0_8,code
.export op_routs_start,data
op_routs_start .word 0
#endif /* ASM */
#ifdef ASM
# define CMP_INDEX_REG_MEAT8(index_reg) \
extru ret0,31,8,ret0 ! \
ldi 0xff,scratch3 ! \
subi 0x100,ret0,ret0 ! \
add index_reg,ret0,ret0 ! \
extru ret0,23,1,scratch1 ! \
and ret0,scratch3,zero ! \
extru ret0,24,1,neg ! \
b dispatch ! \
dep scratch1,31,1,psr
# define CMP_INDEX_REG_MEAT16(index_reg) \
extru ret0,31,16,ret0 ! \
ldil l%0x10000,scratch2 ! \
zdepi -1,31,16,scratch3 ! \
sub scratch2,ret0,ret0 ! \
add index_reg,ret0,ret0 ! \
extru ret0,15,1,scratch1 ! \
and ret0,scratch3,zero ! \
extru ret0,16,1,neg ! \
b dispatch ! \
dep scratch1,31,1,psr
# define CMP_INDEX_REG_LOAD(new_label, index_reg) \
bb,>=,n psr,27,new_label ! \
bl get_mem_long_8,link ! \
nop ! \
CMP_INDEX_REG_MEAT8(index_reg) ! \
.label new_label ! \
bl get_mem_long_16,link ! \
nop ! \
CMP_INDEX_REG_MEAT16(index_reg)
#endif
#ifdef ASM
#define GET_DLOC_X_IND_WR() \
CYCLES_PLUS_1 ! \
add xreg,direct,scratch2 ! \
INC_KPC_2 ! \
add scratch2,arg0,arg0 ! \
bl get_mem_b0_direct_page_16,link ! \
extru arg0,31,16,arg0 ! \
copy ret0,arg0 ! \
extru,= direct,31,8,0 ! \
CYCLES_PLUS_1 ! \
dep dbank,15,8,arg0
#else /* C */
# define GET_DLOC_X_IND_WR() \
CYCLES_PLUS_1; \
INC_KPC_2; \
if(direct & 0xff) { \
CYCLES_PLUS_1; \
} \
arg = arg + xreg + direct; \
GET_MEMORY_DIRECT_PAGE16(arg & 0xffff, arg); \
arg = (dbank << 16) + arg;
#endif
#ifdef ASM
# define GET_DLOC_X_IND_ADDR() \
ldb 1(scratch1),arg0 ! \
GET_DLOC_X_IND_WR()
#else /* C */
# define GET_DLOC_X_IND_ADDR() \
GET_1BYTE_ARG; \
GET_DLOC_X_IND_WR()
#endif
#ifdef ASM
# define GET_DISP8_S_WR() \
CYCLES_PLUS_1 ! \
add stack,arg0,arg0 ! \
INC_KPC_2 ! \
extru arg0,31,16,arg0
#else /* C */
#define GET_DISP8_S_WR() \
CYCLES_PLUS_1; \
arg = (arg + stack) & 0xffff; \
INC_KPC_2;
#endif
#ifdef ASM
# define GET_DISP8_S_ADDR() \
ldb 1(scratch1),arg0 ! \
GET_DISP8_S_WR()
#else /* C */
# define GET_DISP8_S_ADDR() \
GET_1BYTE_ARG; \
GET_DISP8_S_WR()
#endif
#ifdef ASM
# define GET_DLOC_WR() \
INC_KPC_2 ! \
extru,= direct,31,8,0 ! \
CYCLES_PLUS_1 ! \
add direct,arg0,arg0 ! \
extru arg0,31,16,arg0
#else /* C */
# define GET_DLOC_WR() \
arg = (arg + direct) & 0xffff; \
if(direct & 0xff) { \
CYCLES_PLUS_1; \
} \
INC_KPC_2;
#endif
#ifdef ASM
# define GET_DLOC_ADDR() \
ldb 1(scratch1),arg0 ! \
GET_DLOC_WR()
#else /* C */
# define GET_DLOC_ADDR() \
GET_1BYTE_ARG; \
GET_DLOC_WR()
#endif
#ifdef ASM
# define GET_DLOC_L_IND_WR() \
INC_KPC_2 ! \
extru,= direct,31,8,0 ! \
CYCLES_PLUS_1 ! \
add direct,arg0,arg0 ! \
bl get_mem_b0_24,link ! \
extru arg0,31,16,arg0 ! \
copy ret0,arg0
#else /* C */
# define GET_DLOC_L_IND_WR() \
arg = (arg + direct) & 0xffff; \
if(direct & 0xff) { \
CYCLES_PLUS_1; \
} \
INC_KPC_2; \
GET_MEMORY24(arg, arg, 1);
#endif
#ifdef ASM
# define GET_DLOC_L_IND_ADDR() \
ldb 1(scratch1),arg0 ! \
GET_DLOC_L_IND_WR()
#else /* C */
# define GET_DLOC_L_IND_ADDR() \
GET_1BYTE_ARG; \
GET_DLOC_L_IND_WR()
#endif
#ifdef ASM
# define GET_DLOC_IND_Y_ADDR_FOR_WR() \
ldb 1(scratch1),arg0 ! \
CYCLES_PLUS_1 ! \
GET_DLOC_IND_Y_WR_SPECIAL()
#else /* C */
# define GET_DLOC_IND_Y_ADDR_FOR_WR() \
GET_1BYTE_ARG; \
if(direct & 0xff) { \
CYCLES_PLUS_1; \
} \
GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, tmp1); \
tmp1 += (dbank << 16); \
arg = tmp1 + yreg; \
CYCLES_PLUS_1; \
INC_KPC_2;
#endif
#ifdef ASM
# define GET_DLOC_IND_WR() \
extru,= direct,31,8,0 ! \
CYCLES_PLUS_1 ! \
INC_KPC_2 ! \
add direct,arg0,arg0 ! \
bl get_mem_b0_direct_page_16,link ! \
extru arg0,31,16,arg0 ! \
copy ret0,arg0 ! \
dep dbank,15,16,arg0
#else /* C */
# define GET_DLOC_IND_WR() \
INC_KPC_2; \
if(direct & 0xff) { \
CYCLES_PLUS_1; \
} \
GET_MEMORY_DIRECT_PAGE16((direct + arg) & 0xffff, arg); \
arg = (dbank << 16) + arg;
#endif
#ifdef ASM
# define GET_DLOC_IND_ADDR() \
ldb 1(scratch1),arg0 ! \
GET_DLOC_IND_WR()
#else
# define GET_DLOC_IND_ADDR() \
GET_1BYTE_ARG; \
GET_DLOC_IND_WR();
#endif
#ifdef ASM
#define GET_DLOC_INDEX_WR(index_reg) \
GET_DLOC_INDEX_WR_A(index_reg) ! GET_DLOC_INDEX_WR_B(index_reg)
#define GET_DLOC_INDEX_WR_A(index_reg) \
CYCLES_PLUS_1 ! \
add index_reg,direct,scratch2 ! \
extru direct,23,8,scratch1 ! \
INC_KPC_2 ! \
extru,= direct,31,8,0 ! \
CYCLES_PLUS_1 ! \
bb,>= psr,23,.+16 ! \
/* 4*/ add scratch2,arg0,arg0 ! \
/* 8*/ extru,<> direct,31,8,0 ! \
/*12*/ dep scratch1,23,8,arg0
/* GET_DLOC_INDeX_WR_B must be exactly one instruction! */
#define GET_DLOC_INDEX_WR_B(index_reg) \
/*16*/ extru arg0,31,16,arg0
#define GET_DLOC_Y_WR() \
GET_DLOC_INDEX_WR(yreg)
#define GET_DLOC_X_WR() \
GET_DLOC_INDEX_WR(xreg)
#define GET_DLOC_Y_ADDR() \
ldb 1(scratch1),arg0 ! \
GET_DLOC_Y_WR()
# define GET_DLOC_X_ADDR() \
ldb 1(scratch1),arg0 ! \
GET_DLOC_X_WR()
#else
# define GET_DLOC_INDEX_WR(index_reg) \
CYCLES_PLUS_1; \
arg = (arg & 0xff) + index_reg; \
INC_KPC_2; \
if(direct & 0xff) { \
CYCLES_PLUS_1; \
} \
if((psr & 0x100) && ((direct & 0xff) == 0)) { \
arg = (arg & 0xff); \
} \
arg = (arg + direct) & 0xffff;
# define GET_DLOC_X_WR() \
GET_DLOC_INDEX_WR(xreg)
# define GET_DLOC_Y_WR() \
GET_DLOC_INDEX_WR(yreg)
# define GET_DLOC_X_ADDR() \
GET_1BYTE_ARG; \
GET_DLOC_INDEX_WR(xreg)
# define GET_DLOC_Y_ADDR() \
GET_1BYTE_ARG; \
GET_DLOC_INDEX_WR(yreg)
#endif
#ifdef ASM
# define GET_DISP8_S_IND_Y_WR() \
add stack,arg0,arg0 ! \
bl get_mem_b0_16,link ! \
extru arg0,31,16,arg0 ! \
dep dbank,15,16,ret0 ! \
CYCLES_PLUS_2 ! \
add ret0,yreg,arg0 ! \
INC_KPC_2 ! \
extru arg0,31,24,arg0
# define GET_DISP8_S_IND_Y_ADDR() \
ldb 1(scratch1),arg0 ! \
GET_DISP8_S_IND_Y_WR()
#else /* C */
# define GET_DISP8_S_IND_Y_WR() \
arg = (stack + arg) & 0xffff; \
GET_MEMORY16(arg,arg,1); \
CYCLES_PLUS_2; \
arg += (dbank << 16); \
INC_KPC_2; \
arg = (arg + yreg) & 0xffffff;
# define GET_DISP8_S_IND_Y_ADDR() \
GET_1BYTE_ARG; \
GET_DISP8_S_IND_Y_WR()
#endif
#ifdef ASM
# define GET_DLOC_L_IND_Y_WR() \
extru,= direct,31,8,0 ! \
CYCLES_PLUS_1 ! \
INC_KPC_2 ! \
add direct,arg0,arg0 ! \
bl get_mem_b0_24,link ! \
extru arg0,31,16,arg0 ! \
add ret0,yreg,arg0 ! \
extru arg0,31,24,arg0
# define GET_DLOC_L_IND_Y_ADDR() \
ldb 1(scratch1),arg0 ! \
GET_DLOC_L_IND_Y_WR()
#else /* C */
# define GET_DLOC_L_IND_Y_WR() \
arg = (direct + arg) & 0xffff; \
if(direct & 0xff) { \
CYCLES_PLUS_1; \
} \
GET_MEMORY24(arg,arg,1); \
INC_KPC_2; \
arg = (arg + yreg) & 0xffffff;
# define GET_DLOC_L_IND_Y_ADDR() \
GET_1BYTE_ARG; \
GET_DLOC_L_IND_Y_WR()
#endif
#ifdef ASM
# define GET_ABS_ADDR() \
ldb 1(scratch1),arg0 ! \
ldb 2(scratch1),scratch1 ! \
CYCLES_PLUS_1 ! \
dep dbank,15,8,arg0 ! \
INC_KPC_3 ! \
dep scratch1,23,8,arg0
# define GET_LONG_ADDR() \
ldb 1(scratch1),arg0 ! \
ldb 2(scratch1),scratch2 ! \
CYCLES_PLUS_2 ! \
ldb 3(scratch1),scratch1 ! \
INC_KPC_4 ! \
dep scratch2,23,8,arg0 ! \
dep scratch1,15,8,arg0
#else /* C */
# define GET_ABS_ADDR() \
GET_2BYTE_ARG; \
CYCLES_PLUS_1; \
arg = arg + (dbank << 16); \
INC_KPC_3;
# define GET_LONG_ADDR() \
GET_3BYTE_ARG; \
CYCLES_PLUS_2; \
INC_KPC_4;
#endif
#ifdef ASM
#define GET_ABS_INDEX_ADDR_FOR_WR(index_reg) \
ldb 1(scratch1),arg0 ! \
copy index_reg,scratch3 ! \
ldb 2(scratch1),scratch2 ! \
dep dbank,15,8,scratch3 ! \
INC_KPC_3 ! \
dep scratch2,23,8,arg0 ! \
CYCLES_PLUS_2 ! \
add arg0,scratch3,arg0 ! \
extru arg0,31,24,arg0
#define GET_LONG_X_ADDR_FOR_WR() \
ldb 3(scratch1),scratch2 ! \
copy xreg,scratch3 ! \
ldb 1(scratch1),arg0 ! \
ldb 2(scratch1),scratch1 ! \
CYCLES_PLUS_2 ! \
dep scratch2,15,8,scratch3 ! \
INC_KPC_4 ! \
dep scratch1,23,8,arg0 ! \
add arg0,scratch3,arg0 ! \
extru arg0,31,24,arg0
#else /* C */
#define GET_ABS_INDEX_ADDR_FOR_WR(index_reg) \
GET_2BYTE_ARG; \
arg = arg + (dbank << 16); \
INC_KPC_3; \
CYCLES_PLUS_2; \
arg = (arg + index_reg) & 0xffffff;
#define GET_LONG_X_ADDR_FOR_WR() \
GET_3BYTE_ARG; \
INC_KPC_4; \
arg = (arg + xreg) & 0xffffff; \
CYCLES_PLUS_2;
#endif /* ASM */
#ifdef ASM
.export op_routs_end,data
op_routs_end .word 0
#define GET_DLOC_IND_Y_WR_SPECIAL() \
add direct,arg0,arg0 ! \
extru,= direct,31,8,0 ! \
CYCLES_PLUS_1 ! \
bl get_mem_b0_direct_page_16,link ! \
extru arg0,31,16,arg0 ! \
dep dbank,15,8,ret0 ! \
INC_KPC_2 ! \
add yreg,ret0,arg0 /* don't change this instr */
/* or add any after */
/* to preserve ret0 & arg0 */
/* cycle calc: if yreg is 16bit or carry into 2nd byte, inc cycle */
/* So, if y==16bit, add 1. If x==8bit, add 1 if carry */
get_dloc_ind_y_rd_8
stw link,STACK_SAVE_OP_LINK(sp)
GET_DLOC_IND_Y_WR_SPECIAL()
xor arg0,ret0,scratch1
extru,= psr,27,1,0
extru,= scratch1,23,8,0
CYCLES_PLUS_1
b get_mem_long_8
ldw STACK_SAVE_OP_LINK(sp),link
get_dloc_ind_y_rd_16
stw link,STACK_SAVE_OP_LINK(sp)
GET_DLOC_IND_Y_WR_SPECIAL()
xor arg0,ret0,scratch1
extru,= psr,27,1,0
extru,= scratch1,23,8,0
CYCLES_PLUS_1
b get_mem_long_16
ldw STACK_SAVE_OP_LINK(sp),link
#endif /* ASM */

View File

@ -0,0 +1,85 @@
/*
* This file is part of VICE, the Versatile Commodore Emulator.
* See README for copyright notice.
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA.
*
*/
#ifndef VICE_DIRPORT_H
#define VICE_DIRPORT_H
#define INCL_DOS
#include <os2.h>
#include <malloc.h>
#include <sys/stat.h>
#ifndef _A_VOLID
#define _A_VOLID 0
#endif
#ifndef _A_NORMAL
#define _A_NORMAL FILE_NORMAL
#endif
#ifndef _A_RDONLY
#define _A_RDONLY FILE_READONLY
#endif
#ifndef _A_HIDDEN
#define _A_HIDDEN FILE_HIDDEN
#endif
#ifndef _A_SYSTEM
#define _A_SYSTEM FILE_SYSTEM
#endif
#ifndef _A_SUBDIR
#define _A_SUBDIR FILE_DIRECTORY
#endif
#ifndef _A_ARCH
#define _A_ARCH FILE_ARCHIVED
#endif
#define _A_ANY FILE_NORMAL | FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED
#ifndef EPERM
#define EPERM EDOM // Operation not permitted = Domain Error
#endif
#define dirent _FILEFINDBUF3
#define d_name achName /* For struct dirent portability */
#define d_size cbFile
#define mkdir(name, mode) mkdir(name)
#ifndef WATCOM_COMPILE
#define S_ISDIR(mode) ((mode) & S_IFDIR)
typedef struct _DIR {
struct dirent buffer;
HDIR handle;
APIRET ulrc;
} DIR;
extern DIR *opendir(char *path);
extern struct dirent *readdir(DIR *dirp);
extern int closedir(DIR *dirp);
#endif
#endif /* DIRPORT__H */


View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="GSport">
<bannerLeft>
<name>GSport: an Apple IIgs Emulator</name>
</bannerLeft>
<bannerRight>
<name></name>
</bannerRight>
<body>
<links>
<item name="Download" href="http://sourceforge.net/projects/gsport/files"/>
<item name="Sourceforge Project Page" href="http://sourceforge.net/projects/gsport/"/>
</links>
<menu name="GSport">
<item name="Main" href="index.html"/>
<item name="Download" href="http://sourceforge.net/projects/gsport/files"/>
<item name="Operating" href="operating.html"/>
<item name="Developing" href="developing.html"/>
<item name="Emulated Appletalk" href="appletalk.html"/>
<item name="Emulated Ethernet" href="ethernet.html"/>
<item name="Emulated Printers" href="printer.html"/>
<item name="History" href="history.html"/>
</menu>
</body>
</project>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="tfesupp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\arch\win32\bittypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\arch\win32\bpf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\arch\win32\dirent-win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\arch\win32\ip6_misc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\arch\win32\pcap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\arch\win32\pcap-stdinc.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="tfe.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tfesupp.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tfearch.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,542 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../../defc.h"
#include "../../protos.h"
#define INCL_WIN
#define INCL_GPI
#include <os2.h> /* PM header file */
#include <string.h>
#include "gsportos2.h" /* Resource symbolic identifiers*/
HAB g_hab; /* PM anchor block handle */
PSZ pszErrMsg;
QMSG qmsg; /* Message from message queue */
HWND g_hwnd_frame = NULLHANDLE; /* Frame window handle */
HWND g_hwnd_client = NULLHANDLE; /* Client area window handle */
HMQ g_hmq; /* Message queue handle */
extern int Verbose;
extern int g_warp_pointer;
extern int g_screen_depth;
extern int g_force_depth;
int g_screen_mdepth = 0;
extern int g_quit_sim_now;
int g_use_shmem = 1;
int g_has_focus = 0;
int g_auto_repeat_on = -1;
extern Kimage g_mainwin_kimage;
int g_main_height = 0;
int g_win_capslock_down = 0;
extern int g_border_sides_refresh_needed;
extern int g_border_special_refresh_needed;
extern int g_status_refresh_needed;
extern int g_needfullrefreshfornextframe;
extern int g_lores_colors[];
extern int g_cur_a2_stat;
extern int g_a2vid_palette;
extern int g_installed_full_superhires_colormap;
extern int g_screen_redraw_skip_amt;
extern word32 g_a2_screen_buffer_changed;
BITMAPINFO2 *g_bmapinfo_ptr = 0;
volatile BITMAPINFOHEADER2 *g_bmaphdr_ptr = 0;
HDC g_hdc_screen, g_hdc_memory;
HPS g_hps_screen, g_hps_memory;
extern word32 g_palette_8to1624[256];
extern word32 g_a2palette_8to1624[256];
extern char *g_status_ptrs[MAX_STATUS_LINES];
VOID DispErrorMessage();
int
win_nonblock_read_stdin(int fd, char *bufptr, int len)
{
return 0;
}
void
x_dialog_create_gsport_conf(const char *str)
{
}
int
x_show_alert(int is_fatal, const char *str)
{
return 0;
}
int
main(int argc, char **argv)
{
DEVOPENSTRUC pszData;
ULONG flCreate; /* Window creation control flags*/
int height;
SIZEL sizel;
if ((g_hab = WinInitialize(0)) == 0L) /* Initialize PM */
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
if ((g_hmq = WinCreateMsgQueue( g_hab, 0 )) == 0L)/* Create a msg queue */
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
if (!WinRegisterClass( /* Register window class */
g_hab, /* Anchor block handle */
(PSZ)"MyWindow", /* Window class name */
(PFNWP)MyWindowProc, /* Address of window procedure */
CS_SIZEREDRAW, /* Class style */
0 /* No extra window words */
))
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
height = X_A2_WINDOW_HEIGHT + (MAX_STATUS_LINES*16);
g_main_height = height;
flCreate = FCF_STANDARD & /* Set frame control flags to */
~FCF_SHELLPOSITION; /* standard except for shell */
/* positioning. */
if ((g_hwnd_frame = WinCreateStdWindow(
HWND_DESKTOP, /* Desktop window is parent */
0, /* STD. window styles */
&flCreate, /* Frame control flag */
"MyWindow", /* Client window class name */
"", /* No window text */
0, /* No special class style */
(HMODULE)0L, /* Resource is in .EXE file */
ID_WINDOW, /* Frame window identifier */
&g_hwnd_client /* Client window handle */
)) == 0L)
os2_abort(HWND_DESKTOP, HWND_DESKTOP); /* Terminate the application */
WinSetWindowText(g_hwnd_frame, "GSport");
if (!WinSetWindowPos( g_hwnd_frame, /* Shows and activates frame */
HWND_TOP, /* window at position 100, 100, */
100, 100, X_A2_WINDOW_WIDTH, height, /* and size 200, 200. */
SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_SHOW
))
os2_abort(g_hwnd_frame, g_hwnd_client); /* Terminate the application */
g_hdc_screen = WinOpenWindowDC(g_hwnd_client);
sizel.cx = X_A2_WINDOW_WIDTH;
sizel.cy = height;
g_hps_screen = GpiCreatePS(g_hab,g_hdc_screen, &sizel, PU_PELS | GPIF_LONG | GPIA_ASSOC);
g_hdc_memory = DevOpenDC(g_hab, OD_MEMORY, "*", 4, (PDEVOPENDATA)&pszData, NULL);
g_hps_memory = GpiCreatePS(g_hab,g_hdc_memory, &sizel, PU_ARBITRARY | GPIT_MICRO | GPIA_ASSOC);
// Call gsportmain
return gsportmain(argc, argv);
}
/**************************************************************************
*
* Name : MyWindowProc
*
* Description: The window procedure associated with the client area in
* the standard frame window. It processes all messages
* either sent or posted to the client area, depending on
* the message command and parameters.
*
*************************************************************************/
MRESULT EXPENTRY MyWindowProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
HPS hps;
RECTL rcl;
switch( msg )
{
case WM_CREATE:
/*
* Window initialization is performed here in WM_CREATE processing
* WinLoadString loads strings from the resource file.
*/
break;
case WM_COMMAND:
/*
* When the user chooses option 1, 2, or 3 from the Options pull-
* down, the text string is set to 1, 2, or 3, and
* WinInvalidateRegion sends a WM_PAINT message.
* When Exit is chosen, the application posts itself a WM_CLOSE
* message.
*/
{
USHORT command; /* WM_COMMAND command value */
command = SHORT1FROMMP(mp1); /* Extract the command value */
switch (command)
{
case ID_EXITPROG:
WinPostMsg( hwnd, WM_CLOSE, (MPARAM)0, (MPARAM)0 );
break;
default:
return WinDefWindowProc( hwnd, msg, mp1, mp2 );
}
break;
}
case WM_ERASEBACKGROUND:
/*
* Return TRUE to request PM to paint the window background
* in SYSCLR_WINDOW.
*/
return (MRESULT)( TRUE );
case WM_PAINT:
/*
* Window contents are drawn here in WM_PAINT processing.
*/
hps = WinBeginPaint(hwnd, NULLHANDLE, &rcl);
WinEndPaint(hps);
g_needfullrefreshfornextframe = 1;
break;
case WM_CLOSE:
/*
* This is the place to put your termination routines
*/
WinPostMsg( hwnd, WM_QUIT, (MPARAM)0,(MPARAM)0 ); /* Cause termination*/
exit(0);
break;
default:
/*
* Everything else comes here. This call MUST exist
* in your window procedure.
*/
return WinDefWindowProc( hwnd, msg, mp1, mp2 );
}
return (MRESULT)FALSE;
} /* End of MyWindowProc */
void
check_input_events()
{
/*
* Get and dispatch messages from the application message queue
* until WinGetMsg returns FALSE, indicating a WM_QUIT message.
*/
while(WinPeekMsg(g_hab, &qmsg, g_hwnd_frame, 0, 0, PM_NOREMOVE)) {
if(WinGetMsg(g_hab, &qmsg, 0L, 0, 0) > 0) {
//TranslateMessage(&qmsg);
WinDispatchMsg(g_hab, &qmsg);
} else {
printf("GetMessage returned <= 0\n");
my_exit(2);
}
}
}
void
x_update_color(int col_num, int red, int green, int blue, word32 rgb)
{
}
void
x_update_physical_colormap()
{
}
void
show_xcolor_array()
{
}
void
xdriver_end()
{
printf("OS/2 driver_end\n");
}
void
x_get_kimage(Kimage *kimage_ptr)
{
byte *ptr;
int width;
int height;
int depth, mdepth;
int size;
width = kimage_ptr->width_req;
height = kimage_ptr->height;
depth = kimage_ptr->depth;
mdepth = kimage_ptr->mdepth;
size = 0;
if(depth == g_screen_depth) {
/* Use g_bmapinfo_ptr, adjusting width, height */
g_bmaphdr_ptr->cx = width;
g_bmaphdr_ptr->cy = height;
kimage_ptr->dev_handle = GpiCreateBitmap(
(HPS)g_hps_memory, (PBITMAPINFOHEADER2)g_bmaphdr_ptr,
0L, (PBYTE)kimage_ptr->data_ptr,
(PBITMAPINFO2)g_bmapinfo_ptr);
size = (width*height*mdepth) >> 3;
ptr = (byte *)malloc(size);
if(ptr == 0) {
printf("malloc for data failed, mdepth: %d\n", mdepth);
exit(2);
}
kimage_ptr->data_ptr = ptr;
} else {
/* allocate buffers for video.c to draw into */
size = (width*height*mdepth) >> 3;
ptr = (byte *)malloc(size);
if(ptr == 0) {
printf("malloc for data failed, mdepth: %d\n", mdepth);
exit(2);
}
kimage_ptr->data_ptr = ptr;
kimage_ptr->dev_handle = (void *)-1;
}
return;
}
void
dev_video_init()
{
int lores_col;
int i;
printf("Preparing graphics system\n");
g_screen_depth = 24;
g_screen_mdepth = 32;
g_bmapinfo_ptr = (BITMAPINFO2 *)malloc(sizeof(BITMAPINFOHEADER2));
g_bmaphdr_ptr = (BITMAPINFOHEADER2 *)g_bmapinfo_ptr;
g_bmaphdr_ptr->cbFix = sizeof(BITMAPINFOHEADER2);
g_bmaphdr_ptr->cx = A2_WINDOW_WIDTH;
g_bmaphdr_ptr->cy = A2_WINDOW_HEIGHT;
g_bmaphdr_ptr->cPlanes = 1;
g_bmaphdr_ptr->cBitCount = g_screen_mdepth;
g_bmaphdr_ptr->ulCompression = BCA_UNCOMP;
g_bmaphdr_ptr->cclrUsed = 0;
video_get_kimages();
if(g_screen_depth != 8) {
// Allocate g_mainwin_kimage
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth,
g_screen_mdepth);
}
for(i = 0; i < 256; i++) {
lores_col = g_lores_colors[i & 0xf];
video_update_color_raw(i, lores_col);
g_a2palette_8to1624[i] = g_palette_8to1624[i];
}
g_installed_full_superhires_colormap = 1;
printf("Done with dev_video_init\n");
fflush(stdout);
}
void
x_redraw_status_lines()
{
int line,len,height;
POINTL pt;
char *buf;
printf("x_redraw_status_lines() called\n");
/*
if (g_status_ptrs[0] != NULL)
{
height = 16;
pt.x = 5; pt.y = 0;
GpiSetColor( g_hps_screen, CLR_NEUTRAL );
GpiSetBackColor( g_hps_screen, CLR_BACKGROUND );
GpiSetBackMix( g_hps_screen, BM_OVERPAINT );
for (line = 0; line < MAX_STATUS_LINES; line++)
{
buf = g_status_ptrs[line];
if (buf != 0)
{
pt.y = height * (line+1);
len = strlen(buf);
GpiCharStringAt( g_hps_screen, &pt, (LONG)strlen( buf ), buf );
}
}
}
*/
}
void
x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy,
int width, int height)
{
RECTL rc;
POINTL pt[4];
HBITMAP hbmOld, hbmNew;
char *szString = "Hello, world!\0";
printf("x_push_kimage() called: Src: (%d,%d) Dest: (%d,%d) Width: %d Height: %d\n",srcx,srcy,destx,desty,width,height);
pt[0].x = destx; /* Target X1 */
pt[0].y = desty+(MAX_STATUS_LINES*16); /* Target Y1 */
pt[1].x = destx+width; /* Target X2 */
pt[1].y = desty+height+(MAX_STATUS_LINES*16); /* Target Y2: Translate up, make room for status border */
pt[2].x = srcx; /* Source X */
pt[2].y = srcy; /* Source Y */
pt[3].x = srcx+width;
pt[3].y = srcy+height;
if (width == 560)
{
/* Paint a known-good bitmap until we can figure out why images aren't showing up */
hbmNew = GpiLoadBitmap(g_hps_memory,NULLHANDLE,ID_BITMAP,560,400);
hbmOld = GpiSetBitmap(g_hps_memory, hbmNew);
GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE);
GpiSetBitmap(g_hps_memory, hbmOld);
GpiDeleteBitmap(hbmNew);
}
else
{
hbmOld = GpiSetBitmap(g_hps_memory, (HBITMAP)kimage_ptr->dev_handle);
GpiBitBlt(g_hps_screen,g_hps_memory,4L,pt,ROP_SRCCOPY, BBO_IGNORE);
GpiSetBitmap(g_hps_memory, hbmOld);
}
}
// OG Adding release
void x_release_kimage(Kimage* kimage_ptr)
{
if (kimage_ptr->dev_handle == (void*)-1)
{
free(kimage_ptr->data_ptr);
kimage_ptr->data_ptr = NULL;
}
else
{
}
}
void
x_push_done()
{
}
void
x_auto_repeat_on(int must)
{
}
void
x_auto_repeat_off(int must)
{
}
void
x_hide_pointer(int do_hide)
{
}
void
x_full_screen(int do_full)
{
return;
}
int x_calc_ratio(float ratiox,float ratioy)
{
return 0; // not stretched
}
/**************************************************************************/
/* DispErrorMsg -- report an error returned from an API service. */
/* */
/* The error message is displayed using a message box */
/* */
/**************************************************************************/
VOID DispErrorMessage()
{
PERRINFO pErrInfoBlk;
PSZ pszOffSet, pszErrMsg;
ERRORID ErrorId;
PCH ErrorStr;
ErrorId = WinGetLastError(g_hab);
if ((pErrInfoBlk = WinGetErrorInfo(g_hab)) != (PERRINFO)NULL)
{
pszOffSet = ((PSZ)pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
pszErrMsg = ((PSZ)pErrInfoBlk) + *((PULONG)pszOffSet);
WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */
g_hwnd_frame, /* Owner window is our frame */
pszErrMsg, /* PMWIN Error message */
"Error", /* Title bar message */
0, /* Message identifier */
MB_MOVEABLE | MB_CANCEL ); /* Flags */
WinFreeErrorInfo(pErrInfoBlk);
}
}
void
os2_abort(HWND g_hwnd_frame, HWND g_hwnd_client)
{
exit(-1);
}

View File

@ -0,0 +1,30 @@
#!/usr/local/bin/perl -w
# $KmKId: make_size,v 1.3 2002-11-07 08:18:16-08 kadickey Exp $
$repl = shift;
while(<>) {
$line = $_;
if(/\.word inst(..)_SYM\+(.)(.*)$/) {
if($repl eq "c") {
print "\t0x$2, /* $1 */ $3\n";
} elsif($repl eq "s") {
print "\t.byte 0x$2, /* $1 */ $3\n";
} else {
print "\t.word\tinst$1" . "_$repl" . "\t/*$2*/ $3\n";
}
} elsif (/\.block.*$/) {
if($repl eq "c") {
print "\n";
} elsif($repl eq "s") {
print "\n";
} else {
print $line;
}
} else {
print $line;
}
}
# if(/^inst(..)_SYM (.*)$/) {
# print "OPCODE($1) /* $2 */\n";
# } else if(/^(

View File

@ -0,0 +1,246 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "defc.h"
#include "sound.h"
# include <windows.h>
# include <mmsystem.h>
extern int Verbose;
extern int g_audio_rate;
unsigned int __stdcall child_sound_loop_win32(void *param);
void check_wave_error(int res, char *str);
#define NUM_WAVE_HEADERS 8
HWAVEOUT g_wave_handle = NULL; // OG Default value must be set
WAVEHDR g_wavehdr[NUM_WAVE_HEADERS];
extern int g_audio_enable;
extern word32 *g_sound_shm_addr;
extern int g_preferred_rate;
int g_win32snd_buflen = 0x1000;
void
win32snd_init(word32 *shmaddr)
{
printf("win32snd_init\n");
child_sound_loop(-1, -1, shmaddr);
return;
}
// OG Added global to free the dedicated win32 sound memory
byte *bptr = NULL;
// OG shut win32 sound resources
void
win32snd_shutdown()
{
if (g_wave_handle)
{
MMRESULT res = waveOutReset(g_wave_handle);
if (res!=MMSYSERR_NOERROR )
printf("waveOutReset Failed");
res = waveOutClose(g_wave_handle);
if (res!=MMSYSERR_NOERROR )
printf("waveOutClose Failed");
g_wave_handle=NULL;
}
// OG Free dedicated sound memory
if (bptr)
{
free(bptr);
bptr = NULL;
}
}
void CALLBACK
handle_wav_snd(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1,
DWORD dwParam2)
{
LPWAVEHDR lpwavehdr;
/* Only service "buffer done playing messages */
if(uMsg == WOM_DONE) {
lpwavehdr = (LPWAVEHDR)dwParam1;
if(lpwavehdr->dwFlags == (WHDR_DONE | WHDR_PREPARED)) {
lpwavehdr->dwUser = FALSE;
}
}
return;
}
void
check_wave_error(int res, char *str)
{
TCHAR buf[256];
if(res == MMSYSERR_NOERROR) {
return;
}
waveOutGetErrorText(res, &buf[0], sizeof(buf));
printf("%s: %s\n", str, buf);
exit(1);
}
void
child_sound_init_win32()
{
WAVEFORMATEX wavefmt;
WAVEOUTCAPS caps;
// OG Moved as global variable (to rename)
// byte *bptr;
int bits_per_sample, channels, block_align;
int blen;
int res;
int i;
memset(&wavefmt, 0, sizeof(WAVEFORMATEX));
wavefmt.wFormatTag = WAVE_FORMAT_PCM;
#ifndef UNDER_CE
bits_per_sample = 16;
wavefmt.nSamplesPerSec = g_audio_rate;
#else
bits_per_sample = 16;
wavefmt.nSamplesPerSec = 12000;
#endif
channels = 2;
wavefmt.wBitsPerSample = bits_per_sample;
wavefmt.nChannels = channels;
block_align = channels * (bits_per_sample / 8);
wavefmt.nBlockAlign = block_align;
wavefmt.nAvgBytesPerSec = block_align * g_audio_rate;
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt, 0, 0,
WAVE_FORMAT_QUERY);
if(res != MMSYSERR_NOERROR) {
printf("Cannot open audio device\n");
g_audio_enable = 0;
return;
}
res = waveOutOpen(&g_wave_handle, WAVE_MAPPER, &wavefmt,
(DWORD)handle_wav_snd, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
if(res != MMSYSERR_NOERROR) {
printf("Cannot register audio\n");
g_audio_enable = 0;
return;
}
g_audio_rate = wavefmt.nSamplesPerSec;
blen = (SOUND_SHM_SAMP_SIZE * 4 * 2) / NUM_WAVE_HEADERS;
g_win32snd_buflen = blen;
bptr = (byte*)malloc(blen * NUM_WAVE_HEADERS); // OG Added cast
if(bptr == NULL) {
printf("Unabled to allocate sound buffer\n");
exit(1);
}
for(i = 0; i < NUM_WAVE_HEADERS; i++) {
memset(&g_wavehdr[i], 0, sizeof(WAVEHDR));
g_wavehdr[i].dwUser = FALSE;
g_wavehdr[i].lpData = (LPSTR)&(bptr[i*blen]); // OG Added cast
g_wavehdr[i].dwBufferLength = blen;
g_wavehdr[i].dwFlags = 0;
g_wavehdr[i].dwLoops = 0;
res = waveOutPrepareHeader(g_wave_handle, &g_wavehdr[i],
sizeof(WAVEHDR));
check_wave_error(res, "waveOutPrepareHeader");
}
res = waveOutGetDevCaps((UINT)g_wave_handle, &caps, sizeof(caps));
check_wave_error(res, "waveOutGetDevCaps");
printf("Using %s\n", caps.szPname);
printf(" Bits per Sample = %d. Channels = %d\n",
wavefmt.wBitsPerSample, wavefmt.nChannels);
printf(" Sampling rate = %d, avg_bytes_per_sec = %d\n",
(int)wavefmt.nSamplesPerSec, (int)wavefmt.nAvgBytesPerSec);
set_audio_rate(g_audio_rate);
}
void
win32_send_audio2(byte *ptr, int size)
{
int found;
int res;
int i;
found = 0;
for(i = 0; i < NUM_WAVE_HEADERS; i++) {
if(g_wavehdr[i].dwUser == FALSE) {
found = 1;
break;
}
}
if(!found) {
/* all audio buffers busy, just get out */
return;
}
memcpy(g_wavehdr[i].lpData, ptr, size);
g_wavehdr[i].dwBufferLength = size;
g_wavehdr[i].dwUser = TRUE;
res = waveOutWrite(g_wave_handle, &g_wavehdr[i], sizeof(g_wavehdr));
check_wave_error(res, "waveOutWrite");
return;
}
int
win32_send_audio(byte *ptr, int in_size)
{
int size;
int tmpsize;
size = in_size;
while(size > 0) {
tmpsize = size;
if(size > g_win32snd_buflen) {
tmpsize = g_win32snd_buflen;
}
win32_send_audio2(ptr, tmpsize);
ptr += tmpsize;
size = size - tmpsize;
}
return in_size;
}

View File

@ -0,0 +1,169 @@
<?xml version="1.0" standalone="yes"?>
<object class="NSIBObjectData">
<string name="targetFramework">IBCarbonFramework</string>
<object name="rootObject" class="NSCustomObject" id="1">
<string name="customClass">NSApplication</string>
</object>
<array count="18" name="allObjects">
<object class="IBCarbonMenu" id="29">
<string name="title">main</string>
<array count="3" name="items">
<object class="IBCarbonMenuItem" id="185">
<string name="title">GSport</string>
<object name="submenu" class="IBCarbonMenu" id="184">
<string name="title">GSport</string>
<array count="3" name="items">
<object class="IBCarbonMenuItem" id="187">
<string name="title">About GSport</string>
<int name="keyEquivalentModifier">0</int>
<ostype name="command">abou</ostype>
</object>
<object class="IBCarbonMenuItem" id="199">
<boolean name="separator">TRUE</boolean>
</object>
<object class="IBCarbonMenuItem" id="198">
<string name="title">Quit</string>
<int name="keyEquivalentModifier">0</int>
<ostype name="command">quit</ostype>
</object>
</array>
<string name="name">_NSAppleMenu</string>
</object>
</object>
<object class="IBCarbonMenuItem" id="127">
<string name="title">File</string>
<object name="submenu" class="IBCarbonMenu" id="131">
<string name="title">File</string>
<array count="1" name="items">
<object class="IBCarbonMenuItem" id="200">
<string name="title">Configuration F4</string>
<int name="keyEquivalentModifier">0</int>
<ostype name="command">KCFG</ostype>
<string name="helpTagText">Enter GSport Configuration Panel</string>
</object>
</array>
</object>
</object>
<object class="IBCarbonMenuItem" id="192">
<string name="title">Window</string>
<object name="submenu" class="IBCarbonMenu" id="195">
<string name="title">Window</string>
<array count="6" name="items">
<object class="IBCarbonMenuItem" id="197">
<string name="title">Zoom Window</string>
<ostype name="command">zoom</ostype>
</object>
<object class="IBCarbonMenuItem" id="190">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Minimize Window</string>
<int name="keyEquivalentModifier">0</int>
<ostype name="command">mini</ostype>
</object>
<object class="IBCarbonMenuItem" id="191">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Minimize All Windows</string>
<int name="keyEquivalentModifier">0</int>
<ostype name="command">mina</ostype>
</object>
<object class="IBCarbonMenuItem" id="194">
<boolean name="separator">TRUE</boolean>
</object>
<object class="IBCarbonMenuItem" id="196">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Bring All to Front</string>
<ostype name="command">bfrt</ostype>
</object>
<object class="IBCarbonMenuItem" id="193">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Arrange in Front</string>
<int name="keyEquivalentModifier">1572864</int>
<ostype name="command">frnt</ostype>
</object>
</array>
<string name="name">_NSWindowsMenu</string>
</object>
</object>
</array>
<string name="name">_NSMainMenu</string>
</object>
<reference idRef="127"/>
<reference idRef="131"/>
<object class="IBCarbonMenuItem" id="153">
<string name="title">Window</string>
<object name="submenu" class="IBCarbonMenu">
<string name="title">Window</string>
<array count="5" name="items">
<object class="IBCarbonMenuItem">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Minimize Window</string>
<string name="keyEquivalent">m</string>
<ostype name="command">mini</ostype>
</object>
<object class="IBCarbonMenuItem">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Minimize All Windows</string>
<string name="keyEquivalent">m</string>
<int name="keyEquivalentModifier">1572864</int>
<ostype name="command">mini</ostype>
</object>
<object class="IBCarbonMenuItem">
<boolean name="separator">TRUE</boolean>
</object>
<object class="IBCarbonMenuItem">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Bring All to Front</string>
<ostype name="command">frnt</ostype>
</object>
<object class="IBCarbonMenuItem">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Bring in Front</string>
<int name="keyEquivalentModifier">1572864</int>
<ostype name="command">frnt</ostype>
</object>
</array>
<string name="name">_NSWindowsMenu</string>
</object>
</object>
<reference idRef="184"/>
<reference idRef="185"/>
<reference idRef="187"/>
<reference idRef="190"/>
<reference idRef="191"/>
<reference idRef="192"/>
<reference idRef="193"/>
<reference idRef="194"/>
<reference idRef="195"/>
<reference idRef="196"/>
<reference idRef="197"/>
<reference idRef="198"/>
<reference idRef="199"/>
<reference idRef="200"/>
</array>
<array count="18" name="allParents">
<reference idRef="1"/>
<reference idRef="29"/>
<reference idRef="127"/>
<reference idRef="29"/>
<reference idRef="185"/>
<reference idRef="29"/>
<reference idRef="184"/>
<reference idRef="195"/>
<reference idRef="195"/>
<reference idRef="29"/>
<reference idRef="195"/>
<reference idRef="195"/>
<reference idRef="192"/>
<reference idRef="195"/>
<reference idRef="195"/>
<reference idRef="184"/>
<reference idRef="184"/>
<reference idRef="131"/>
</array>
<dictionary count="2" name="nameTable">
<string>Files Owner</string>
<reference idRef="1"/>
<string>MenuBar</string>
<reference idRef="29"/>
</dictionary>
<unsigned_int name="nextObjectID">201</unsigned_int>
</object>

View File

@ -0,0 +1,2 @@
#!/bin/sh
mvn site

View File

@ -0,0 +1,27 @@
-----
GSport Project Page
-----
David Schmidt (david__schmidt at users dot souceforge dot net)
-----
GSport
GSport is a portable (in the programming sense) Apple IIgs emulator, based on the
KEGS cross-platform IIgs emulator by Kent Dickey.
The base emulator builds and runs on all of the same platforms that KEGS did, and
the new capabilities are being integrated as contributors have time and interest.
[images/gsport.png]
[images/download.png]
* Project Goals
The main goal for GSport is to provide a free, open ecosystem for the continuation
of cross-platform development of IIgs emulation.
Some interesting advances that initially spawned this project are Uthernet and printer support.
As those objectives are met, we will move on to the next objectives.
Do you have something that you wish a GS emulator did?
Submit a request {{{http://sourceforge.net/tracker/?group_id=315628&atid=1327836}here,}}
or better yet - dive in and {{{https://sourceforge.net/project/memberlist.php?group_id=315628}contribute!}}

View File

@ -0,0 +1,184 @@
# GSport central makefile - you need a 'vars' file linked/copied from a 'vars_xxx' template to build.
OBJECTS1 = adb.o clock.o config.o dis.o engine_c.o scc.o iwm.o \
joystick_driver.o moremem.o paddles.o parallel.o printer.o \
sim65816.o smartport.o sound.o sound_driver.o video.o \
scc_socket_driver.o imagewriter.o scc_imagewriter.o scc_llap.o
ATOBJ = atbridge/aarp.o atbridge/atbridge.o atbridge/elap.o atbridge/llap.o atbridge/port.o
PCAPOBJ = atbridge/pcap_delay.o
TFEOBJ = tfe/tfe.o tfe/tfearch.o tfe/tfesupp.o
include vars
.SUFFIXES: .dep .proto
AS = $(CC)
XLIBS = -L/usr/X11R6/lib
PERL = perl
all: $(TARGET)
clean:
- rm -f $(OBJECTS)
- rm -f $(TARGET)
- rm -f compile_time.o
- rm -f 8inst_c.h
- rm -f 16inst_c.h
- rm -rf ../GSport.app
- rm -rf ../GSportDmg
specials: 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s
specials_clean:
rm -f 8inst_s 16inst_s 8size 16size 8inst_c 16inst_c size_c size_s
# Mac builds:
gsportmac: $(OBJECTS) compile_time.o
$(CC) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o gsport $(EXTRA_LIBS)
mkdir -p ../GSport.app/Contents/Resources/English.lproj/main.nib
mkdir -p ../GSport.app/Contents/MacOS
mv gsport ../GSport.app/Contents/MacOS/GSport
echo "APPL????" > ../GSport.app/Contents/PkgInfo
cp -f arch/mac/Info.plist ../GSport.app/Contents/
cp -f arch/mac/info.nib ../GSport.app/Contents/Resources/English.lproj/main.nib
cp -f arch/mac/classes.nib ../GSport.app/Contents/Resources/English.lproj/main.nib
cp -f arch/mac/objects.xib ../GSport.app/Contents/Resources/English.lproj/main.nib
cp -f arch/mac/gsporticon.icns ../GSport.app/Contents/Resources/
cp -f arch/mac/525.icns ../GSport.app/Contents/Resources/
cp -f arch/mac/2mg.icns ../GSport.app/Contents/Resources/
touch '../GSport.app/Icon?'
rm -rf ../GSportDmg
mkdir ../GSportDmg
mkdir ../GSportDmg/GSport
cp ../COPYING.txt ../GSportDmg/GSport
cp -f parallel.rom ../GSportDmg/GSport
cp -f ../lib/NoBoot.po ../GSportDmg/GSport
mv ../GSport.app ../GSportDmg/GSport
cp -f ../config.template ../GSportDmg/GSport/config.txt
cp ../GSport.html ../GSportDmg/GSport/GSport.html
arch/mac/makedmg.sh .. GSportDmg GSport GSport 7
# Linux for X builds:
gsportx: $(OBJECTS) compile_time.o
$(LD) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(XLIBS) $(EXTRA_LIBS) -lX11
echo $(OBJECTS)
mv gsportx ..
cp -f ../config.template ../config.txt
# Linux framebuffer builds:
gsportfb: $(OBJECTS) compile_time.o
$(LD) $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(EXTRA_LIBS)
echo $(OBJECTS)
mv gsportfb ..
cp -f ../config.template ../config.txt
# Mingw32 (native windows) builds:
gsport.exe: $(OBJECTS) compile_time.o
g++ $(CCOPTS) $(LDOPTS) $(OBJECTS) compile_time.o $(LDFLAGS) -o $(NAME)$(SUFFIX) $(EXTRA_LIBS) -lwinmm -lgdi32 -ldsound -lcomctl32 -lws2_32 -lshell32
mkdir -p ../GSport.app/lib
cp -f gsport.exe ../GSport.app/GSport.exe
cp -f ../config.template ../GSport.app/config.txt
cp -f ../lib/*.ttf ../GSport.app/lib
cp -f ../lib/arch/win32/*.dll ../GSport.app
cp -f ../lib/NoBoot.po ../GSport.app
cp -f GSport.bat ../GSport.app/GSport.bat
cp -f parallel.rom ../GSport.app
cp -f ../COPYING.txt ../GSport.app
cp -f ../GSport.html ../GSport.app
8inst_c.h: instable.h
$(PERL) make_inst c 8 instable.h > 8inst_c.h
16inst_c.h: instable.h
$(PERL) make_inst c 16 instable.h > 16inst_c.h
size_c.h: size_tab.h
$(PERL) make_size c size_tab.h > size_c.h
engine_c.o: 8inst_c.h 16inst_c.h size_c.h
8inst_s.h: instable.h
$(PERL) make_inst s 8 instable.h > 8inst_s.h
16inst_s.h: instable.h
$(PERL) make_inst s 16 instable.h > 16inst_s.h
size_s.h: size_tab.h
$(PERL) make_size s size_tab.h > size_s.h
8size_s.h: size_tab.h
$(PERL) make_size 8 size_tab.h > 8size_s.h
16size_s.h: size_tab.h
$(PERL) make_size 16 size_tab.h > 16size_s.h
engine_s.o: 8inst_s.h 16inst_s.h 8size_s.h 16size_s.h size_s.h
.s.o:
$(AS) -c $(OPTS) -I. $*.s
.c.o:
$(CC) $(CCOPTS) $(XOPTS) -c $(OPTS) -I. -o $*.o $*.c
.cpp.o:
$(CC) $(CPPOPTS) $(XOPTS) -c $(OPTS) -I. $*.cpp
.cpp.O:
$(CC) $(CCOPTS) $(XOPTS) -c $(OPTS) -I. $*.c
partls: partls.c
cc $(CCOPTS) $(XOPTS) $(OPTS) -o partls partls.c
to_pro: prodos.h prodos_protos.h to_pro.c
cc $(CCOPTS) $(XOPTS) $(OPTS) -o to_pro to_pro.c
gsport32.o: win32.rc winresource.h
windres win32.rc -o gsport32.o
compile_time.o: $(OBJECTS)
# dependency stuff
adb.o: adb.c adb.h defc.h defcomm.h iwm.h protos.h
atbridge/aarp.o: defc.h atbridge/atbridge.h atbridge/port.h atbridge/elap.h atbridge/aarp.h atbridge/elap_defs.h
atbridge/atbridge.o: defc.h atbridge/atbridge.h atbridge/port.h atbridge/elap.h atbridge/llap.h atbridge/aarp.h
atbridge/elap.o: defc.h atbridge/atbridge.h atbridge/port.h atbridge/elap.h atbridge/aarp.h atbridge/elap_defs.h atbridge/pcap_delay.h
atbridge/llap.o: defc.h atbridge/atbridge.h atbridge/port.h atbridge/llap.h
atbridge/port.o: atbridge/atalk.h atbridge/port.h
atbridge/pcap_delay.o: atbridge/pcap_delay.h
engine_c.o: engine_c.c defc.h defcomm.h iwm.h protos.h protos_engine_c.h size_c.h op_routs.h defs_instr.h 8inst_c.h 16inst_c.h
clock.o: clock.c defc.h defcomm.h iwm.h protos.h
compile_time.o: compile_time.c
config.o: config.c defc.h defcomm.h iwm.h protos.h config.h
dis.o: dis.c defc.h defcomm.h iwm.h protos.h disas.h
scc.o: scc.c defc.h defcomm.h iwm.h protos.h scc.h
scc_llap.o: atbridge/atbridge.h atbridge/llap.h defc.h scc.h
scc_socket_driver.o: scc_socket_driver.c defc.h defcomm.h iwm.h protos.h scc.h
scc_windriver.o: scc_windriver.c defc.h defcomm.h iwm.h protos.h scc.h
scc_macdriver.o: scc_macdriver.c defc.h defcomm.h iwm.h protos.h scc.h
scc_imagewriter.o: scc_imagewriter.c defc.h defcomm.h protos.h scc.h
iwm.o: iwm.c defc.h defcomm.h iwm.h protos.h iwm_35_525.h
imagewriter.o: imagewriter.cpp
joystick_driver.o: joystick_driver.c defc.h defcomm.h iwm.h protos.h
moremem.o: moremem.c defc.h defcomm.h iwm.h protos.h
paddles.o: paddles.c defc.h defcomm.h iwm.h protos.h
parallel.o: parallel.c defc.h
printer.o: printer.cpp
sim65816.o: sim65816.c defc.h defcomm.h iwm.h protos.h
smartport.o: smartport.c defc.h defcomm.h iwm.h protos.h
sound.o: sound.c defc.h defcomm.h iwm.h protos.h sound.h
sound_driver.o: sound_driver.c defc.h defcomm.h iwm.h protos.h sound.h
video.o: video.c defc.h defcomm.h iwm.h protos.h superhires.h gsportfont.h
tfe.o: tfe/tfe.c tfe/tfe.h tfe/tfe_protos.h
tfearch.o: tfe/tfearch.c tfe/tfearch.h tfe/tfe_protos.h
tfesupp.o: tfe/tfesupp.c tfe/tfesupp.h tfe/tfe_protos.h
macdriver.o: macdriver.c defc.h defcomm.h iwm.h protos.h protos_macdriver.h
macdriver_console.o: macdriver_console.c defc.h defcomm.h iwm.h protos.h protos_macdriver.h
macdriver_generic.o: macdriver_generic.c defc.h defcomm.h iwm.h protos.h protos_macdriver.h
macsnd_driver.o: macsnd_driver.c defc.h defcomm.h iwm.h protos.h sound.h
windriver.o: windriver.c defc.h defcomm.h iwm.h protos.h protos_windriver.h winresource.h gsport32.o
win_console.o: win_console.c defc.h defcomm.h iwm.h protos.h protos_windriver.h winresource.h
win_generic.o: win_generic.c defc.h defcomm.h iwm.h protos.h protos_windriver.h winresource.h
win32snd_driver.o: win32snd_driver.c defc.h defcomm.h iwm.h protos.h sound.h

View File

@ -0,0 +1,239 @@
KEGS's Apple //gs IWM emulation routines.
The IWM code does 5.25" and 3.5" reads & writes, and updates the Unix disk
image on writes. It is also nearly cycle-accurate--Let me know if you
have a program which can detect it's not a real Apple II. There are
a few 5.25" features missing (No 1/4 or 1/2 tracks, no support for Unix nibble
images, limited disk switching), but what's there is pretty accurate.
The low-level code support 1/4 and 1/2 tracks--it's the arm movement
and image-handling routines which don't. And lack of Unix nibble images
are also due to lack of higher-level routines to make those features work.
How my disk emulation works: The routines have a nibblized image of each
track of each drive (two 5.25" and two 3.5" drives are supported) in memory.
The nibble images are declared as arrays, but it could be made to use
more dynamic memory allocation.
Each track's data format is a series of two-byte pairs. The first byte
of the pair is the number of bits in this disk byte, and the second byte
is the value. So a size of 8 is normal. A size of 10 means that there
are 2 sync bits written before this byte on the disk. So for 5.25" disk
accesses, 40 cycles need to pass in the simulator before providing a
valid nibble. Partial nibbles are correctly formed if a read happens
too early (this actually makes things slower, but is required if you
want to make nibble copiers work). Similarly, writing to the disk
watches timing carefully to write out the correct number of bits per
disk byte. These routines will definitely test out your emulator's cycle
counting ability.
If a long delay occurs between a read (or a write) the routines skips
the correct number of bits to return the correctly formed disk byte.
After a long delay, for efficiency, I always return a full disk byte,
instead of a partial one, even if the timing would put it in the middle
of a disk byte.
The arm stepping is really lame. I will clean it up soon.
Smartport support is sufficient to claim that there are no smartport
devices. This is necessary since the ROM tries to see if there are
smartport devices at power-on.
I tested my 5.25" drive routines on EDD, which could correctly measure
drive speed and other disk factors. I also nibble-copied some disks,
which also worked fine. I tested the 3.5" routines using Copy II+,
which successfully nibble-copied several disks.
Code description:
Most code is in iwm.c, with some defines in iwm.h, and some stuff in
iwm_35_525.h.
Code only supports DOS3.3 ordered 5.25" images now, and ProDOS-ordered 3.5"
images. Well, the code supports ProDOS-order 5.25" also, but has no
mechanism to tell it an image is prodos-order yet. :-)
Iwm state is encoded in the Iwm structure.
drive525[2]: Disk structure for each 5.25" disk
drive35[2]: Disk structure for each 3.5" disk
smarport[32]: Disk structure for each "smartport" device emulated
via slot 7 (this code not included)
motor_on: True if IWM motor_on signal (c0e9) is asserted. Some
drive is on.
motor_off: True if motor has been turned off in software, but the
1 second timeout has not expired yet.
motor_on35: True if 3.5" motor is on (controlled differently than
5.25" c0e9).
motor_off_vbl_count: VBL count to turn motor off.
head35, step_direction35: 3.5" controls, useless.
iwm_phase[4]: Has '1' for each 5.25" phase that is on.
iwm_mode: IWM mode register.
drive_select: 0 = drive 1, 1 = drive 2.
q6, q7: IWM q6, q7 registers.
enable2: Smartport /ENABLE2 asserted.
reset: Smartport /RESET asserted.
previous_write_val: Partial write value.
previous_write_bits: How many bits are valid in previous_write_val.
Each disk (3.5" and 5.25") is encoded in the Disk struct:
fd: Unix file descriptor. If < 0, no disk.
name_ptr: Unix file name for this disk.
image_start: offset from beginning of file for this partition.
image_size: size of this partition.
smartport: 1 if this is a smartport image, 0 if it is 5.25" or 3.5"
disk_525: 1 if this is a 5.25" image, 0 if it is 3.5"
drive: 0 = drive 1, 1 = drive 2.
cur_qtr_track: Current qtr track. So track 1 == qtr_track 4.
For 3.5", cur_qtr_track encodes the side also, so track 3
side 1 would be qtr_track 7.
prodos_order: True if Unix image is ProDOS order.
vol_num: DOS3.3 volume number to use. Always 254.
write_prot: True if disk is write protected.
write_through_to_unix: True if writes should be passed through to
the unix image. If this is false, you can write
to the image in memory, but it won't get reflected
into the Unix file. If you create a non-DOS3.3
or ProDOS format image, it automatically sets this
false.
disk_dirty: Some track has dirty data that need to be flushed.
just_ejected: Ejection flag.
dcycs_last_read: Cycle count of last disk data register access.
last_phase: Phase number last accessed.
nib_pos: Nibble offset ptr--points to a byte.
num_tracks: Number of tracks: 140 for 5.25" and 160 for 3.5"
track[MAX_TRACKS]: nibble image of all possible tracks.
Each track is represented by the Track structure:
track_dirty: Contains data that needs to be written back to
the Unix image file.
overflow_size: Count of overflow bits, used in writing.
track_len: Number of nibbles on this track.
dsk: Handy pointer to parent Disk structure.
nib_area[]: ptr to memory containing pairs of [size,data],
encoding disk data bytes.
pad1: If the structure is 32 bytes long, some array
indexing is done better by my compiler.
Externally callable routines:
iwm_init(): Init various data structures at simulation start.
iwm_reset(): Called at Apple //gs reset time.
iwm_vbl_update(): Called every VBL (60 Hz) period. Used to turn motor
off, and flush out dirty data.
g_vbl_count is the count of VBL ticks (so it counts
at 60 times a second).
iwm_read_c0ec(double dcycs): Optimized routine to handle reading $C0EC
faster. Exactly the same as read_iwm(0xc, dcycs);
read_iwm(loc, dcycs):
Read from 0xc0e0 + loc. Loc is between 0x0 and 0xf.
Dcycs is an artifact from my simulator. Dcycs is a
double holding the number of Apple //gs cycles since the
emulator started. Dcycs always counts at 1.024MHz. If
you are running at 2.5MHz, it increments by 0.4 every
"cycle". This is a very convenient timing strategy. It
also allows emulating the delay caused by synchronizing
the fast part of a real Apple //gs with slow memory,
which means my emulator knows that reading softswitches
takes longer than reading fast memory.
write_iwm(int loc, int val, double dcycs):
Write to 0xc0e0 + loc. Just like read_iwm, but write "val" into
loc.
Tricky routines:
IWM_READ_ROUT(): called by read_iwm() if q6,q7 = 0,0.
This is actually in the file iwm_35_525.h. This is so I
write the basic code once for 5.25" and 3.5" disk reads,
but then include the file with some macros set to create
the correct function optimized for 5.25" or 3.5"
accesses. The function for 5.25" is called
iwm_read_data_525, and iwm_read_data_35 for 3.5".
Returns next disk byte.
Takes three arguments: ptr to the Disk structure for
the active drive, fast_disk_emul, and dcycs. dcycs is
so that it can see how many cycles have passed since
the last read (stored in dsk->dcycs_last_read).
16.0 dcycs need to pass for an 8 bit nibble for 3.5"
accesses, and 32.0 dcycs for an 8 bit nibble for 5.25".
Fast_disk_emul == 1 says don't mess around with accuracy,
and always return the next fully-formed nibble.
There is a lot of complexity in this routine. All IWM
routines must skip over nibbles (stored as byte pairs in
dsk->nib_area[]) which have a size of 0 (special padding
trick, described later). It then determines how much
time has passed, and so how many bits are valid.
If too many bits have gone by (11 cycs is almost 3 5.25"
bit times, which is about the nibble valid time in
the Apple //gs IWM hardware latch), it tries to skip
to the correct position.
Handles IWM latch mode for 3.5" or 5.25" accesses. If a
partial read is indicated, it ensures that the high bit
is clear by shifting the nibble to the right
appropriately. Again, nib_area[] is an array of bytes,
which are treated as pairs. Byte 0 = size, byte 1 =
disk nibble.
IWM_WRITE_ROUT(): called by write_iwm() if q6,q7 = 1,1.
Similar to above. Handles async and sync mode writes.
Handles partial writes. Handles the ROM writing
0xff, 0x3f, 0xcf, 0xf3, 0xfc to be four 10-bit nibbles.
Routine disk_nib_out(dsk, val, bits_read) does the
actual work of merging the bits into the track image.
disk_nib_out(): called by IWM_WRITE_ROUTE() and iwm_nibblize_track_*().
Writes byte into nib_area[]. If size > 10, makes it 10.
If high order bit not set, it sets it (makes certain routines
in EDD happy).
overflow_size:
Writing to the disk creates some problems. I need to
maintain 2 things at all times on the track:
1) Constant number of bits for the entire track.
2) know where each synchronized byte starts on
the track.
If the track was just stored as raw bits, then correctly
simulating a delay of 300*4 cycles is tough, since it has to
be done by reading through all 300 bits on the track,
so that we keep in sync with where bytes really start.
But if you just store the bytes themselves, then sync
bytes look like every other byte. And if you now add
the size field, you have a situation where a track could
gain or lose bits when rewritten. Here's the case:
Assume the track contains: 10,ff 10,ff 10,ff 10,ff.
(That is 4 self-sync disk bytes of 10 bits each).
If we rewrite that area of the track with 'D5 AA 96 FF',
where each byte is 8 bits, we would have:
8,D5 8,AA, 8,96, 8,FF.
Looks OK, but we just lost 8 bits! The original 4 nibbles
were using 40 bits of space on the disk. Our new 4 nibbles
are using 32 bits. 8 bits are lost.
Solution: log these missing bits via overflow_size.
When writing, if overflow_size gets > 8, force out a 0,0
nibble. So sync bytes get written as:
10,FF 10,FF 10,FF 10,FF 0,0 10,FF 10,FF 10,FF 10,FF, 0,0.
So when they get re-written with 8,xx, we don't lose any
bytes on the disk.
Unfortunately, it doesn't quite work that easily, and bits
can still be lost when sync fields are partially overwritten.
This happens when all the 0,0's end up in a place on the
track where few overwrites occur, but other sync bytes
are being turned into 8,xx. So overflow_size goes negative,
saying we've got too much on the track.
The code prints an error when it gains more than 64 bits.
If someone can come up with a better scheme, I'd love to
hear it. A partial solution would be to have a routine
re-space the track to spread the needed 0,0's around
a little better when overflow_size gets too negative.
In iwm_nibblize_track_35(), the comments with hex numbers correspond
to the ROM 01 addresses which I disassembled to determine the checksum
algorithm. The code is not well written--it's basically hand-translated
65816 assembly code. I'll clean it up someday.
Much of the code is not well-optimized. I'll get to that someday, but
the speed has been adequate for me so far.

View File

@ -0,0 +1,37 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2013-2014 by Peter Neubauer
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
struct packet_t;
/** LLAP port of the AppleTalk Bridge **/
void llap_init();
void llap_shutdown();
/** Send one LLAP packet from the GS
*/
void llap_enqueue_in(double dcycs, size_t size, byte data[]);
/** Receive one LLAP packet from the world to the GS and return the size
*/
void llap_dequeue_out(double dcycs, size_t* size, byte* data[]);
void llap_enqueue_out(struct packet_t* packet);
struct packet_t* llap_dequeue_in();

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>2mg</string>
<string>2MG</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>2mg.icns</string>
<key>CFBundleTypeName</key>
<string>Apple II 2MG Disk Image</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>a2mg</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>gsport</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>525.icns</string>
<key>CFBundleTypeName</key>
<string>GSport Configuration File</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>gsport</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>GSport</string>
<key>CFBundleName</key>
<string>GSport</string>
<key>CFBundleIconFile</key>
<string>gsporticon.icns</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>GSport</string>
<key>CFBundleVersion</key>
<string>0.1</string>
<key>CFBundleShortVersionString</key>
<string>GSport version 0.1</string>
<key>CFBundleGetInfoString</key>
<string>GSport v0.1, Copyright 2010 GSport Contributors, http://gsport.sourceforge.net</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2010 GSport Contributors</string>
</dict>
</plist>

View File

@ -0,0 +1,153 @@
-----
GSport Printers
-----
David Schmidt (david__schmidt at users dot souceforge dot net)
-----
GSport Emulated Printers
There are two classes of printers emulated by GSport: an Epson LQ connected by a virtual serial card in slot 1,
and an Apple Imagewriter LQ or Imagewriter II attached to serial port 1.
Set up for common printing scenarios is detailed below:
* Emulated {{{./printer.html#Imagewriter}Imagewriter LQ/II}} - when you want to emulate an Imagewriter LQ or Imagewriter II specifically in slot 1
* Windows {{{./printer.html#Bitmap}Bitmap or Postscript}} (B&W) - when you want a graphical file saved on the host computer
* Direct to {{{./printer.html#Host}host printer}} - when you want a real, paper-based copy immediately (or, a Postscript file with an appropriate printer driver)
* {{{./printer.html#Text}Text File}} - when you want a file of plain text saved on the host computer
[]
When configuring the virtual printer (details below), these notes apply in all situations:
* The "Printer Timeout" setting configures how long until a form feed is automatically sent to the printer
(which forces the emulator to kick out a "page").
This value should be set to a value like 15 seconds or more for PR#1-type printing to work as you might expect.
If it is set to "Never", you must manually send a form feed, fill a page with text, or exit the emulator before output is saved.
This behavior is similar to modern laser/inkjet printers when they are used with Applesoft.
Most applications are good about sending form feeds at page end, so this issue doesn't usually come up.
* The Roman font is used in graphical printing by default, and the matching <<<lib/letgothl.ttf>>> is included in the distribution package.
Printing emulation won't work if no fonts at all are defined.
Any other mono-spaced TrueType font you have may also be used.
* Emulated {Imagewriter} LQ/II
In GSport's internal control panel:
[[]] Under "Serial Port Configuration" set Port 0 to "Virtual Imagewriter"
[images/printerI1.png]
[[]] Under "Virtual Imagewriter Configuration" you need to configure fonts. GSport comes with a fixed width font installed and pre-configured. Set any proportional font you wish to use. If you plan on using native Windows printer output or Postscript, set Multipage Files to "Yes". The default printer timeout of 2 seconds is fine if you are running the machine in 8Mhz or unlimited speed modes. Set it higher if you are running at 1Mhz or 2.8Mhz since the printer may time out while the computer is "thinking" during print jobs.
[images/printerI2.png]
[]
Printer DPI should be set to at least 720x720dpi for Imagewriter LQ resolution output (mostly GS/OS). Use 1440x1440dpi if you have a high resolution inkjet printer and plan on printing pure text documents. It also minimizes scaling artifacts when printing graphics.
Printer Type just changes the self ID string sent by the printer when the "ESC-?" command is sent. This is used by the driver included in GS/OS to determine what type of printer is connected and whether a color ribbon is installed. Set it to Imagewriter LQ in most cases.
<<Save your settings and restart GSport to apply your configuration changes!>>
(This will likely be fixed in a future release.)
In the native IIgs control panel:
[[]] Under "Slots", Slot 1 should be set to "Printer Port"
[[]] Under "Printer Port" leave everything at its default setting, but set baud rate to 19200. It is highly recommended that you install the QuickPort CDA and set the port speed to "57600". Since we are using the SCC emulation, the speed that data is transferred to the virtual printer is limited by the baud rate set by the emulated environment.
[]
8-bit and non-Printer Manager IIgs applications (like Printshop GS) should work without a problem after configuring them to print to an Imagewriter connected to slot 1. When printing text in programs like Appleworks, be sure to set page margins. By default, the emulator starts printing at the upper left hand corner of the virtual "page".
GS/OS requires configuration in the "DC Printer" control panel. Make sure you install the printer drivers from your GS/OS disk set. Set the port to "Printer" and type to "Imagewriter.LQ". If you have Harmonie, use its "Printer57.6" port driver as it greatly speeds up printing (the built in port driver appears to be hard coded to 19200 baud max). Do not use its "Printer.HAR" port driver as it sends junk text to the printer for some reason. Harmonie's "IWriterLQ.HAR" and "Imagewriter.HAR" drivers have been tested and are fully compatible with the printer emulator. They do not query the printer with ESC-?, so the setting of Printer Type in the GSport control panel doesn't matter with these. Both Harmonie and Pointless are highly recommended for the best quality output in GS/OS.
The printer emulator supports all Imagewriter II and LQ functions documented in Apple's official reference manuals. Mousetext and custom character definitions are NOT supported. This is consistent with a real Imagewriter LQ. Only the Imagewriter II supported those functions.
* Windows {Bitmap} or Postscript
To set up GSport to write .BMP or .PS files for each "page" produced, apply the following settings:
Enter the GS native control panel and set slot 1 to "Your Card", then save and exit the control panel.
You will need to reboot the emulated GS (with a cold boot - Ctrl-Alt-F12, etc.)
or restart GSport to have this change take effect, just like a real GS:
[images/printer0.png]
Press F4 to enter the text-based GSport menu and select the "Parallel Card Configuration" option.
By default, printer emulation is turned off. Enable it by setting "Parallel Card in Slot 1" to "On,"
and leave the "Parallel Output" option set to its default value, "Send full 8-bit data:"
[images/printer1.png]
Next, navigate back to the main menu and select the "Virtual Printer Configuration" option
and set "Printer Output Type" to either "Windows Bitmap" or "Postscript (B&W)" based on your preference:
[images/printer3.png]
Save the configuration, and printed output will be saved as files in GSport's current working directory.
* Direct to {Host} Printer
The "Direct to host printer" feature is only implemented on the Windows platform.
To set up GSport to send page-oriented output directly to your system's printer, apply the following settings:
Enter the GS native control panel and set slot 1 to "Your Card", then save and exit the control panel.
Note that you will need to restart GSport after all of the changes below are made, so don't restart just yet:
[images/printer0.png]
Press F4 to enter the text-based GSport menu and select the "Parallel Card Configuration" option.
By default, printer emulation is turned off. Enable it by setting "Parallel Card in Slot 1" to "On,"
and leave the "Parallel Output" option set to its default value, "Send full 8-bit data:"
[images/printer1.png]
Next, navigate back to the main menu and select the "Virtual Printer Configuration" option
and set "Printer Output Type" to "Direct to host printer:"
[images/printer6.png]
Save the configuration, and stop the GSport application altogether and restart it.
You should be presented with your system's default printer selection dialog box:
[images/printer7.png]
The printer you choose here will be the place that page-oriented output is sent, subject to the page ejection
timeouts discussed earlier.
Note that it is even possible to use a printer driver that itself produces PDF output instead of physical paper.
* {Text} File
Printing to a text file will bypass all printer emulation and simply append printed data to a file
named <<<printer.txt>>> in GSport's current working directory.
This is especially useful for text-based operations like Applesoft listings using the traditional
<<<PR#1:LIST:PR#0>>> command sequences.
Output from GSOS applications like TeachText are not actually textual in nature - they are graphical.
It would be more appropriate to use a different type of printer output in that situation.
To set up GSport to append printed text to a printer.txt file, apply the following settings:
Enter the GS native control panel and set slot 1 to "Your Card", then save and exit the control panel.
You will need to reboot the emulated GS (with a cold boot - Ctrl-Alt-F12, etc.)
or restart GSport to have this change take effect, just like a real GS:
[images/printer0.png]
Press F4 to enter the text-based GSport menu and select the "Parallel Card Configuration" option.
By default, printer emulation is turned off. Enable it by setting "Parallel Card in Slot 1" to "On."
Also change the "Parallel Output" option to "Mask off high bit:"
[images/printer4.png]
Next, navigate back to the main menu and select the "Virtual Printer Configuration" option
and set "Printer Output Type" to "Text file:"
[images/printer5.png]
Save the configuration, and printed output will be appended in the <<<printer.txt>>>
file in GSport's current working directory.

View File

@ -0,0 +1,46 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2014 by Peter Neubauer
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
This interface provides a thin, delay-loaded wrapper around the PCAP library so that
you may start GSport without intalling PCAP. Of course, some features that require
PCAP won't be available.
This wrapper provides a subset of the available PCAP APIs necessary for ATBridge.
Feel free to extend the wrapper.
*/
#ifdef WIN32
#include "../arch/win32/pcap.h"
#elif __linux__
#include <pcap.h>
#endif
bool pcapdelay_load();
bool pcapdelay_is_loaded();
void pcapdelay_unload();
void pcapdelay_freealldevs(pcap_if_t *);
pcap_t* pcapdelay_open_live(const char *, int, int, int, char *);
void pcapdelay_close(pcap_t *);
int pcapdelay_findalldevs(pcap_if_t **, char *);
int pcapdelay_datalink(pcap_t *);
int pcapdelay_setnonblock(pcap_t *, int, char *);
int pcapdelay_sendpacket(pcap_t *p, u_char *buf, int size);
const u_char* pcapdelay_next(pcap_t *, struct pcap_pkthdr *);
int pcapdelay_dispatch(pcap_t *, int, pcap_handler, u_char *);

View File

@ -0,0 +1,57 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by gsport32.rc
//
#define IDD_ABOUT_DIALOG 101
#define IDC_GSPORT32 102
#define IDR_TOOLBAR 103
#define IDD_DLG_DISKCONF 104
#define IDR_ACCEL 105
#define IDD_GSPORT32_KEY 106
#define ID_TOOLBAR 5000
#define ID_STATUSBAR 5001
#define IDC_EDIT_S5D1 10051
#define IDC_EDIT_S5D2 10052
#define IDC_EDIT_S6D1 10061
#define IDC_EDIT_S6D2 10062
#define IDC_EDIT_S7D1 10071
#define IDC_EDIT_S7D2 10072
#define IDC_BTN_S5D1 11051
#define IDC_BTN_S5D2 11052
#define IDC_BTN_S6D1 11061
#define IDC_BTN_S6D2 11062
#define IDC_BTN_S7D1 11071
#define IDC_BTN_S7D2 11072
#define ID_HELP_ABOUT 40001
#define ID_FILE_EXIT 40002
#define ID_FILE_DISK 40003
#define ID_FILE_SENDRESET 40004
#define ID_FILE_JOYSTICK 40005
#define ID_FILE_DEBUGSTAT 40006
#define ID_FILE_SENDREBOOT 40007
#define ID_FILE_FULLSCREEN 40012
#define ID_FILE_SPEED 40013
#define ID_HELP_KEY 40014
#define ID_SPEED_1MHZ 50001
#define ID_SPEED_2MHZ 50002
#define ID_SPEED_FMHZ 50003
#define IDD_SPEEDDIALOG 117
#define IDC_SLOW 1007
#define IDC_CUSTOM 1008
#define IDC_EDITCUSTOM 1009
#define IDC_NORMAL 1010
#define IDC_FASTEST 1011
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 111
#define _APS_NEXT_COMMAND_VALUE 40013
#define _APS_NEXT_CONTROL_VALUE 1003
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

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

View File

@ -0,0 +1,449 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 - 2012 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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; // OG change int to word32
extern int g_rom_version;
extern int g_config_gsport_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 int g_c033_data;
extern int g_c034_val;
byte g_bram[2][256];
byte *g_bram_ptr = &(g_bram[0][0]);
byte g_temp_boot_slot = 254;
byte g_orig_boot_slot = 0;
word32 g_clk_cur_time = 0xa0000000;
int g_clk_next_vbl_update = 0;
double
get_dtime()
{
#ifndef _WIN32
struct timeval tp1;
double dsec;
double dusec;
#endif
double dtime;
/* Routine used to return actual system time as a double */
/* No routine cares about the absolute value, only deltas--maybe */
/* take advantage of that in future to increase usec accuracy */
#ifdef _WIN32
dtime = timeGetTime() / 1000.0;
#else
# ifdef SOLARIS
gettimeofday(&tp1, (void *)0);
# else
gettimeofday(&tp1, (struct timezone *)0);
# endif
dsec = (double)tp1.tv_sec;
dusec = (double)tp1.tv_usec;
dtime = dsec + (dusec / (1000.0 * 1000.0));
#endif
return dtime;
}
int
micro_sleep(double dtime)
{
#ifndef _WIN32
struct timeval Timer;
int ret;
#endif
if(dtime <= 0.0) {
return 0;
}
if(dtime >= 1.0) {
halt_printf("micro_sleep called with %f!!\n", dtime);
return -1;
}
#if 0
printf("usleep: %f\n", dtime);
#endif
#ifdef _WIN32
Sleep((DWORD)(dtime * 1000));
#else
Timer.tv_sec = 0;
Timer.tv_usec = (dtime * 1000000.0);
if( (ret = select(0, 0, 0, 0, &Timer)) < 0) {
fprintf(stderr, "micro_sleep (select) ret: %d, errno: %d\n",
ret, errno);
return -1;
}
#endif
return 0;
}
void
clk_bram_zero()
{
int i, j;
/* zero out all bram */
for(i = 0; i < 2; i++) {
for(j = 0; j < 256; j++) {
g_bram[i][j] = 0;
}
}
g_bram_ptr = &(g_bram[0][0]);
}
void
clk_bram_set(int bram_num, int offset, int val)
{
g_bram[bram_num][offset] = val;
}
extern void x_clk_setup_bram_version();
void
clk_setup_bram_version()
{
x_clk_setup_bram_version();
}
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
clk_calculate_bram_checksum(void) {
int checksum = 0;
int i;
if (g_bram_ptr[251] == 0xff) {
// Only make the checksum valid if we have non-zeron data!
// Otherwise you have very valid zeroes, which confuses the GS firmware mightily.
for (i = 250; i >= 0; i--) {
checksum = (checksum & 0xFFFF) << 1;
checksum = (checksum & 0xFFFF)
+ g_bram_ptr[i]
+ ((int)g_bram_ptr[i + 1] << 8)
+ (checksum >> 16);
}
checksum &= 0xFFFF;
checksum += ((checksum ^ 0xAAAA) << 16);
#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
g_bram_ptr[252] = (checksum & 0xFF);
g_bram_ptr[253] = (checksum >> 8);
g_bram_ptr[254] = (checksum >> 16);
g_bram_ptr[255] = (checksum >> 24);
#else
g_bram_ptr[255] = (checksum & 0xFF);
g_bram_ptr[254] = (checksum >> 8);
g_bram_ptr[253] = (checksum >> 16);
g_bram_ptr[252] = (checksum >> 24);
#endif
}
}
void
update_cur_time()
{
struct tm *tm_ptr;
time_t cur_time;
unsigned int secs, secs2;
#ifdef UNDER_CE // OG Not supported on WIndows CE
/*
SYSTEMTIME stime;
FILETIME ftime;
GetLocalTime(&stime);
SystemTimeToFileTime(&stime,&ftime);
cur_time = ftime.dwLowDateTime;
*/
cur_time = time(0);
secs=0;
secs2=0;
#else
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 = (unsigned int)mktime(gmtime(&cur_time));
tm_ptr = localtime(&cur_time);
secs = (unsigned int)mktime(tm_ptr);
#ifdef MAC
/* Mac OS X's mktime function modifies the tm_ptr passed in for */
/* the CDT timezone and breaks this algorithm. So on a Mac, we */
/* will use the tm_ptr->gmtoff member to correct the time */
secs = secs + tm_ptr->tm_gmtoff;
#else
secs = (unsigned int)cur_time - (secs2 - secs);
if(tm_ptr->tm_isdst) {
/* adjust for daylight savings time */
secs += 3600;
}
#endif
#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 = 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;
int read;
int 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 */
if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)){
// Modify boot slot
g_c033_data = g_temp_boot_slot;
clk_calculate_bram_checksum();
} else {
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 */
if ((g_clk_reg1 == 0x28) && (g_temp_boot_slot != 254)) {
// Modify boot slot
g_bram_ptr[g_clk_reg1] = g_temp_boot_slot;
clk_calculate_bram_checksum();
} else {
g_bram_ptr[g_clk_reg1] = g_c033_data;
}
clk_printf("Writing BRAM loc %02x with %02x\n",
g_clk_reg1, g_c033_data);
g_config_gsport_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;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,458 @@
/*
* tfearch.c - TFE ("The final ethernet") emulation,
* architecture-dependant stuff
*
* Written by
* Spiro Trikaliotis <Spiro.Trikaliotis@gmx.de>
*
* This file is part of VICE, the Versatile Commodore Emulator.
* See README for copyright notice.
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA.
*
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "../atbridge/pcap_delay.h"
#include "tfesupp.h"
#include "../defc.h"
#include "protos_tfe.h"
/** #define TFE_DEBUG_ARCH 1 **/
/** #define TFE_DEBUG_PKTDUMP 1 **/
/* #define TFE_DEBUG_FRAMES - might be defined in TFE.H! */
#define TFE_DEBUG_WARN 1 /* this should not be deactivated */
/* ------------------------------------------------------------------------- */
/* variables needed */
//static log_t tfe_arch_log = LOG_ERR;
static pcap_if_t *TfePcapNextDev = NULL;
static pcap_if_t *TfePcapAlldevs = NULL;
static pcap_t *TfePcapFP = NULL;
static char TfePcapErrbuf[PCAP_ERRBUF_SIZE];
#ifdef TFE_DEBUG_PKTDUMP
static
void debug_output( const char *text, unsigned char *what, int count )
{
char buffer[256];
char *p = buffer;
char *pbuffer1 = what;
int len1 = count;
int i;
sprintf(buffer, "\n%s: length = %u\n", text, len1);
OutputDebugString(buffer);
do {
p = buffer;
for (i=0; (i<8) && len1>0; len1--, i++) {
sprintf( p, "%02x ", (unsigned int)(unsigned char)*pbuffer1++);
p += 3;
}
*(p-1) = '\n'; *p = 0;
OutputDebugString(buffer);
} while (len1>0);
}
#endif // #ifdef TFE_DEBUG_PKTDUMP
/*
These functions let the UI enumerate the available interfaces.
First, TfeEnumAdapterOpen() is used to start enumeration.
TfeEnumAdapter is then used to gather information for each adapter present
on the system, where:
ppname points to a pointer which will hold the name of the interface
ppdescription points to a pointer which will hold the description of the interface
For each of these parameters, new memory is allocated, so it has to be
freed with lib_free().
TfeEnumAdapterClose() must be used to stop processing.
Each function returns 1 on success, and 0 on failure.
TfeEnumAdapter() only fails if there is no more adpater; in this case,
*ppname and *ppdescription are not altered.
*/
int tfe_arch_enumadapter_open(void)
{
if (pcapdelay_findalldevs(&TfePcapAlldevs, TfePcapErrbuf) == -1)
{
#ifdef TFE_DEBUG_ARCH
log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen: pcap_findalldevs: '%s'", TfePcapErrbuf);
#endif
return 0;
}
if (!TfePcapAlldevs) {
#ifdef TFE_DEBUG_ARCH
log_message(tfe_arch_log, "ERROR in TfeEnumAdapterOpen, finding all pcap devices - "
"Do we have the necessary privilege rights?");
#endif
return 0;
}
TfePcapNextDev = TfePcapAlldevs;
return 1;
}
int tfe_arch_enumadapter(char **ppname, char **ppdescription)
{
if (!TfePcapNextDev || (TfePcapNextDev->name == NULL))
return 0;
*ppname = lib_stralloc(TfePcapNextDev->name);
if (TfePcapNextDev->description)
*ppdescription = lib_stralloc(TfePcapNextDev->description);
else
*ppdescription = lib_stralloc(TfePcapNextDev->name);
TfePcapNextDev = TfePcapNextDev->next;
return 1;
}
int tfe_arch_enumadapter_close(void)
{
if (TfePcapAlldevs) {
pcapdelay_freealldevs(TfePcapAlldevs);
TfePcapAlldevs = NULL;
}
return 1;
}
static
int TfePcapOpenAdapter(const char *interface_name)
{
pcap_if_t *TfePcapDevice = NULL;
if (!tfe_enumadapter_open()) {
return FALSE;
}
else {
/* look if we can find the specified adapter */
char *pname;
char *pdescription;
int found = FALSE;
if (interface_name) {
/* we have an interface name, try it */
TfePcapDevice = TfePcapAlldevs;
while (tfe_enumadapter(&pname, &pdescription)) {
if (strcmp(pname, interface_name)==0) {
found = TRUE;
}
lib_free(pname);
lib_free(pdescription);
if (found) break;
TfePcapDevice = TfePcapNextDev;
}
}
if (!found) {
/* just take the first adapter */
TfePcapDevice = TfePcapAlldevs;
}
}
TfePcapFP = pcapdelay_open_live(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf);
if ( TfePcapFP == NULL)
{
#ifdef TFE_DEBUG_ARCH
log_message(tfe_arch_log, "ERROR opening adapter: '%s'", TfePcapErrbuf);
#endif
tfe_enumadapter_close();
return FALSE;
}
if (pcapdelay_setnonblock(TfePcapFP, 1, TfePcapErrbuf)<0)
{
#ifdef TFE_DEBUG_ARCH
log_message(tfe_arch_log, "WARNING: Setting PCAP to non-blocking failed: '%s'", TfePcapErrbuf);
#endif
}
/* Check the link layer. We support only Ethernet for simplicity. */
if(pcapdelay_datalink(TfePcapFP) != DLT_EN10MB)
{
#ifdef TFE_DEBUG_ARCH
log_message(tfe_arch_log, "ERROR: TFE works only on Ethernet networks.");
#endif
tfe_enumadapter_close();
return FALSE;
}
tfe_enumadapter_close();
return TRUE;
}
/* ------------------------------------------------------------------------- */
/* the architecture-dependend functions */
int tfe_arch_init(void)
{
//tfe_arch_log = log_open("TFEARCH");
return 1;
}
void tfe_arch_pre_reset( void )
{
#ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_pre_reset()." );
#endif
}
void tfe_arch_post_reset( void )
{
#ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_post_reset()." );
#endif
}
int tfe_arch_activate(const char *interface_name)
{
#ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_activate()." );
#endif
if (!TfePcapOpenAdapter(interface_name)) {
return 0;
}
return 1;
}
void tfe_arch_deactivate( void )
{
#ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_deactivate()." );
#endif
}
void tfe_arch_set_mac( const unsigned char mac[6] )
{
#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES)
log_message( tfe_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
#endif
}
void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */
int bIA, /* individual address (IA) */
int bMulticast, /* multicast if address passes the hash filter */
int bCorrect, /* accept correct frames */
int bPromiscuous, /* promiscuous mode */
int bIAHash /* accept if IA passes the hash filter */
)
{
#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES)
log_message( tfe_arch_log, "tfe_arch_recv_ctl() called with the following parameters:" );
log_message( tfe_arch_log, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE" );
log_message( tfe_arch_log, "\tbIA = %s", bIA ? "TRUE" : "FALSE" );
log_message( tfe_arch_log, "\tbMulticast = %s", bMulticast ? "TRUE" : "FALSE" );
log_message( tfe_arch_log, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE" );
log_message( tfe_arch_log, "\tbPromiscuous = %s", bPromiscuous ? "TRUE" : "FALSE" );
log_message( tfe_arch_log, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE" );
#endif
}
void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver )
{
#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES)
log_message( tfe_arch_log, "tfe_arch_line_ctl() called with the following parameters:" );
log_message( tfe_arch_log, "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE" );
log_message( tfe_arch_log, "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE" );
#endif
}
typedef struct TFE_PCAP_INTERNAL_tag {
unsigned int len;
unsigned char *buffer;
} TFE_PCAP_INTERNAL;
/* Callback function invoked by libpcap for every incoming packet */
static
void TfePcapPacketHandler(unsigned char *param, const struct pcap_pkthdr *header, const unsigned char *pkt_data)
{
TFE_PCAP_INTERNAL *pinternal = (TFE_PCAP_INTERNAL*)param;
/* determine the count of bytes which has been returned,
* but make sure not to overrun the buffer
*/
if (header->caplen < pinternal->len)
pinternal->len = header->caplen;
memcpy(pinternal->buffer, pkt_data, pinternal->len);
}
/* the following function receives a frame.
If there's none, it returns a -1.
If there is one, it returns the length of the frame in bytes.
It copies the frame to *buffer and returns the number of copied
bytes as return value.
At most 'len' bytes are copied.
*/
static
int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal)
{
int ret = -1;
/* check if there is something to receive */
if (pcapdelay_dispatch(TfePcapFP, 1, (pcap_handler)TfePcapPacketHandler, (unsigned char*)pinternal)!=0) {
/* Something has been received */
ret = pinternal->len;
}
#ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_receive_frame() called, returns %d.", ret );
#endif
return ret;
}
void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */
int onecoll, /* ONECOLL: Terminate after just one collision */
int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */
int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */
int txlength, /* Frame length */
unsigned char *txframe /* Pointer to the frame to be transmitted */
)
{
#ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_transmit() called, with: "
"force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u",
force ? "TRUE" : "FALSE",
onecoll ? "TRUE" : "FALSE",
inhibit_crc ? "TRUE" : "FALSE",
tx_pad_dis ? "TRUE" : "FALSE",
txlength
);
#endif
#ifdef TFE_DEBUG_PKTDUMP
debug_output( "Transmit frame: ", txframe, txlength);
#endif // #ifdef TFE_DEBUG_PKTDUMP
if (pcapdelay_sendpacket(TfePcapFP, txframe, txlength) == -1) {
//log_message(tfe_arch_log, "WARNING! Could not send packet!");
}
}
/*
tfe_arch_receive()
This function checks if there was a frame received.
If so, it returns 1, else 0.
If there was no frame, none of the parameters is changed!
If there was a frame, the following actions are done:
- at maximum *plen byte are transferred into the buffer given by pbuffer
- *plen gets the length of the received frame, EVEN if this is more
than has been copied to pbuffer!
- if the dest. address was accepted by the hash filter, *phashed is set, else
cleared.
- if the dest. address was accepted by the hash filter, *phash_index is
set to the number of the rule leading to the acceptance
- if the receive was ok (good CRC and valid length), *prx_ok is set,
else cleared.
- if the dest. address was accepted because it's exactly our MAC address
(set by tfe_arch_set_mac()), *pcorrect_mac is set, else cleared.
- if the dest. address was accepted since it was a broadcast address,
*pbroadcast is set, else cleared.
- if the received frame had a crc error, *pcrc_error is set, else cleared
*/
int tfe_arch_receive(unsigned char *pbuffer , /* where to store a frame */
int *plen, /* IN: maximum length of frame to copy;
OUT: length of received frame
OUT can be bigger than IN if received frame was
longer than supplied buffer */
int *phashed, /* set if the dest. address is accepted by the hash filter */
int *phash_index, /* hash table index if hashed == TRUE */
int *prx_ok, /* set if good CRC and valid length */
int *pcorrect_mac, /* set if dest. address is exactly our IA */
int *pbroadcast, /* set if dest. address is a broadcast address */
int *pcrc_error /* set if received frame had a CRC error */
)
{
int len;
TFE_PCAP_INTERNAL internal = { *plen, pbuffer };
#ifdef TFE_DEBUG_ARCH
log_message( tfe_arch_log, "tfe_arch_receive() called, with *plen=%u.", *plen );
#endif
assert((*plen&1)==0);
len = tfe_arch_receive_frame(&internal);
if (len!=-1) {
#ifdef TFE_DEBUG_PKTDUMP
debug_output( "Received frame: ", internal.buffer, internal.len );
#endif // #ifdef TFE_DEBUG_PKTDUMP
if (len&1)
++len;
*plen = len;
/* we don't decide if this frame fits the needs;
* by setting all zero, we let tfe.c do the work
* for us
*/
*phashed =
*phash_index =
*pbroadcast =
*pcorrect_mac =
*pcrc_error = 0;
/* this frame has been received correctly */
*prx_ok = 1;
return 1;
}
return 0;
}

View File

@ -0,0 +1,744 @@
-----
Operating GSport
-----
David Schmidt (david__schmidt at users dot souceforge dot net)
-----
Operating GSport
* Getting a ROM file
The required ROM for GSport is not part of the distribution, as it is
not freely distributable. You must own a IIgs ROM (i.e. a IIgs machine) in
order to legally use a ROM file that you may find on the internet.
GSport can use the ROM image from either a ROM01 or ROM03 IIgs machine.
By default, that file should be named <<<rom>>> and be placed in the same folder as the GSport program/app.
The name and location are configurable options, but it will "just work" with the defaults.
* Running GSport
On all platforms except Windows and Mac, you must start GSport from a terminal
window. GSport will open a new window and use the window you started it from
as a "debug" window.
GSport will look in a number of places for two files it requires: <<<config.txt>>>
and <<<rom>>>. The suggested place for these files is right alongside the GSport
application itself.
Start GSport by Double-clicking the GSport icon on a Mac, or by running
the executable (<<<gsport.exe>>> on Windows, and <<<gsportx>>> on Linux).
GSport can be run from the Terminal window on a Mac as well (which enables access to
more debug information) by typing: <<<./GSport.app/Contents/MacOS/GSport>>> from the folder GSport is in.
This also enables the automatic mounting/booting feature by allowing you to specify a disk
image of your choice on that command line; for example: \
<<<./GSport.app/Contents/MacOS/GSport /path/to/my/disk.po>>>
Assuming all goes well, GSport will then boot up but probably not find any disk images.
Hit the "F4" key and see below for how to tell GSport what disk images to use.
Tip: Hitting "F8" locks the mouse in the window (and hides the host cursor)
until you hit "F8" again.
See the the {{{./developing.html}developing}} page for information about developing GSport and compiliing it for yourself.
* Configuration Panel
The Configuration panel is accessed by pressing the F4 key at any time.
(If GSport couldn't find a ROM file when it started, you will be forced
into the Configuration Panel mode until you select a valid ROM file).
To select a ROM file, select "ROM File Selection" and then select your
ROM file. If you were not forced into the panel at startup, then GSport
found one and it is working.
* Disk Images
The primary use of the Configuration Panel is to select disk images. To
change disk images being used, select "Disk Configuration". Each slot
and drive that can be loaded with an image is listed. "s5d1" means slot
5, drive 1. Slot 5 devices are 3.5" 800K disks, and slot 6 devices are
5.25" 140K disks. Slot 7 devices are virtual hard drives, and can be
any size at all (although ProDOS-formatted images should be less than
32MB).
Just use the arrow keys to navigate to the device entry to change, and
then select it by pressing the Enter or Return key.
A scrollable file selection
interface is presented, letting you locate your image files. To quickly
jump to a particular path, you can press Tab to toggle between entering
a path manually, and using the file selector. Press Return on ".."
entries to go up a directory level. When you find the image you want,
just press the Enter or Return key.
If the image has partitions that GSport supports, another selection
dialog will have you select which partition to mount. You will probably
only have partitions on direct devices you mount (or on a Mac, of .dmg
images of CDs). For instance, on a Mac, /dev/disk1 can sometimes be the
CDROM drive.
GSport can handle "raw", .dsk, .po, 2IMG, 5.25" ".nib" images, most Mac
Diskcopy images and partitioned images. The .dsk and .po formats you often
find on the web are really "raw" formats, and so they work fine. GSport uses
the host file permissions to encode the read/write status of the image.
GSport can open any image file compressed with gzip (with the extension ".gz")
automatically as a read-only disk image.
An image is the representation of an Apple IIgs disk, but in a file on
your computer. For 3.5" disks, for example, a raw image would be exactly
800K bytes long (819200 bytes). GSport directs the emulated GS accesses to
the image, and does the correct reads and writes of the Unix file instead.
If you do not have any disk mounted in s7d1, GSport will jump into the monitor.
To boot slot 6 (or slot 5), use the Apple IIgs Control Panel by pressing
Ctrl-Command-ESC.
Support for 5.25" nibblized images is read-only for now (since the
format is simplistic, it's tricky for GSport to write to it since GSport
has more information than fits in that format). Just select your image,
like "disk.nib" in the <<<config.txt>>> file like any .dsk or .po image.
In addition to changing disks, you can also just "eject" and image by
moving the cursor to select that slot/drive and then press "E". The
emulated IIgs will immediately detect changes to s5d1 and s5d2.
Care should be taken when changing images in slot 7--GSport does not notify
GSOS that images have changed (or been ejected), and so it's best to make
changes when GSOS is not running.
* Keyboard Summary
---
F1: Alias of Command
F2: Alias of Option
F3: Alias of ESC
F4: Configuration Panel
F5, Shift-Insert: Paste from clipboard (on Windows and Mac)
F6: Toggle through the 4 speeds: Unlimited, 1MHz, 2.8MHz, 8.0MHz
Shift-F6: Enter GSport debugger
F7: Toggle fast_disk_emul on/off
F8: Toggle pointer hiding on/off.
F9: Invert the sense of the joystick.
Shift-F9: Swap x and y joystick/paddle axes.
F10: Attempt to change the a2vid_palette (only useful on 256-color displays)
Shift-F10: Toggle visibility of the debug status lines (on Windows only)
F11: Full screen mode (on Mac OS X and Windows).
F12: Alias of Pause/Break which is treated as Reset
F2, Alt_R, Meta_r, Menu, Print, Mode_switch, Option: Option key
F1, Alt_L, Meta_L, Cancel, Scroll_lock, Command: Command key
Num_Lock: Keypad "Clear".
F12, Pause, Break: Reset
"Home": Alias for "=" on the keypad (since my Unix keyboard doesn't have an =).
---
* Using GSport
The host computer mouse is the Apple IIgs mouse and joystick by default.
By default, the host pointer is not constrained inside the window and
remains visible. Press F8 to hide the cursor and constrain the mouse. F8
again toggles out of constrain mode. When the GSOS desktop is running,
GSport hides the host cursor automatically and enables special tracking
which forces the emulated cursor to follow the host cursor. If this doesn't
work right under some program, just press F8 for better compatibility.
The middle mouse button or Shift-F6 causes GSport to stop emulation, and enter
the debugger. You can continue with "g" then return in the debug window.
You can also disassemble memory, etc. The section "Debugging GSport"
above describes the debugger interface a little more.
GSport has no pop-up menus or other interactive interfaces (other than
the debug window, and the occasional error dialogs on Mac OS X). Input to
the debug window is only acted upon when the emulation is stopped
(Shift-F6, middle mouse button, or hitting a breakpoint).
* Quitting GSport
Just close the main GSport window, and GSport will exit cleanly. Or you
can select Quit from the menu. Or enter ctrl-c in the debugger window.
Or press the middle-mouse button in the emulation window, and then type
"q" return in the debug window.
* Command/Option keys
If you have a keyboard with the special Windows keys, you can
use them as the command/option keys. For those without those keys,
there are several alternatives.
The following keys are Option (closed-apple) (not all keyboards have all
keys): F2, Meta_R, Alt_R, Cancel, Print_screen, Mode_switch, Option,
or the Windows key just to the right of the spacebar. The following keys are
Command (open-apple): F1, Meta_L, Alt_L, Menu, Scroll_lock, Command,
the Windows key left of the spacebar, and the Windows key on the far right
that looks like a pull-down menu. You can use F1 and F2 if you cannot make
anything else work (especially useful if your OS is intercepting some
Alt or Command key sequences).
Note that X Windows often has other things mapped to Meta- and Alt-
key sequences, so they often don't get passed through to GSport. So it's
best to use another key instead of Alt or Meta.
The joystick/paddle buttons are just the Command and Option keys.
* Reset
The reset key is Pause/Break or F12. You must hit it with Ctrl to get it to
take effect (just like a real Apple IIgs). Ctrl-Command-Reset
forces a reboot. Ctrl-Command-Option-Reset enters selftests.
Selftests will pass if you force speed to 2.8MHz using the middle
button or F6 (and also set Enable Text Page 2 shadow = Disabled for ROM 01).
Watch out for ctrl-shift-Break--it will likely kill an X Windows session.
Also note that the Unix olvwm X window manager interprets ctrl-F12 and will
not pass it on to GSport--you'll need to use Break for reset in that case.
* Full Screen mode (Mac OS X only)
GSport can run in full screen mode--which is especially useful when letting
small kids use GSport (but it is not really a lock, so do not let a 2 year
old bang on the keyboard while running GSport).
Full Screen mode is toggled with F11 (or Ctrl-F11, since Expose on a Mac
is intercepting F11). If GSport stops in the debugger for any reason,
full screen mode is toggled off automatically.
* Joystick Emulation (Mouse, Keypad, or real native joystick)
The default joystick is the mouse position. Upper left is 0,0. Lower right
is 255,255. Press Shift-F9 to swap the X and Y axes. Press F9 to reverse
the sense of both paddles (so 0 becomes 255, etc). Swapping and
reversing are convenient with paddle-based games like "Little Brick Out"
so that the mouse will be moving like the paddle on the screen. "Little
Brick Out" is on the DOS 3.3 master disk. The joystick does not work
properly if the pointer is constrained in the window.
You can also select from a "Keypad Joystick" or a real joystick from
the Configuration panel. Press return on the "Joystick Configuration"
entry, and then select between Mouse Joystick, Keypad Joystick, or one
of two native joysticks. The Keypad Joystick uses your keypad number
keys as a joystick, where keypad 7 means move to the upper left, and
keypad 3 means move to the lower right. Pressing multiple keys together
averages the results, allowing finer control than just 8 directions.
Also, joystick scaling is selectable here for games which require
a greater range of motion to work correctly, along with trim adjustment
which moves the centering point. Adjusting scaling usually means you
will need to adjust the trim as well.
The left mouse button is the mouse button for GSport. The right mouse
button (if you have it) or F6 toggles between four speed modes. Mode 0
(the default) means run as fast as possible. Mode 1 means run at 1MHz.
Mode 2 means run at 2.8MHz. Mode 3 means run at 8.0MHz (about the speed
of a ZipGS accelerator). Most Apple //e (or earlier) games need to be
run at 1MHz. Many Apple IIgs demos must run at 2.8MHz or they will not
operate correctly. Try running ornery programs at 2.8MHz. 3200 pictures
generally only display correctly at 2.8MHz or sometimes 8.0MHz.
* Debugging GSport
GSport by default now continues emulation even when it detects buggy programs
running. (Now I know why Appleworks GS always seemed to crash!).
GSport divides buggy programs into two severities: Code Yellow and Code Red.
The status is displayed in words in the text area under the emulation window.
If nothing's wrong, nothing is printed.
A Yellow bug is a mild bug where an Apple IIgs program merely read an
invalid location. Although completely harmless, it indicates the potential
for some Apple IIgs program bug which may become more severe shortly.
For instance, closing the "About This Apple IIgs" window in the Finder
causes a code yellow alert, but it seems quite harmless.
A Code Red bug is a more serious problem. The Apple IIgs program either
tried to write non-existent memory, entered an invalid system state, or
perhaps just tried to use an Apple IIgs feature which GSport does not implement
yet. Note that entering GSBUG tends to cause a Code Red alert always, so if
you intended to enter it, you can ignore it. My recommendation is to
save work immediately (to new files) and restart GSport if you get into the
Red mode.
GSport also supports breakpoints and watchpoints. In the debug window, you
set a breakpoint at an address by typing the address, followed by a 'B'
(it must be in caps). To set a breakpoint on the interrupt jump point,
type:
---
e1/0010B
---
The format is "bank/address" then "B", where the B must be in caps and
the address must use lower-case hex. For Apple IIe programs, just use a
bank of 0.
To list all breakpoints, just type 'B' with no number in front of it.
To delete a breakpoint, enter its address followed by 'D', so
---
e1/0010D
---
deletes the above breakpoint. The addresses work like the IIgs monitor:
once you change banks, you can use shortcut addresses:
---
e1/0010B
14B
---
will add breakpoints at e1/0010 and e1/0014.
This is a "transparent" breakpoint--memory is not changed. But any
read or write to that address will cause GSport to halt. So you can
set breakpoints on I/O addresses, or ROM, or whatever. Setting a breakpoint
slows GSport down somewhat, but only on accesses to the 256 byte "page"
the breakpoint is on. Breakpoints are not just instruction breakpoints,
they also cause GSport to halt on any data access, too (usually called
watchpoints).
Frederic Devernay has written a nice help screen available in the
debugger when you type "h".
Useful locations for setting breakpoints:
0/3f0B - Break handler
0/c000B - Keyboard latch, programs read keys from this address
* GSport command-line option summary
There are others, but the Configuration panel provides a better way to
set them so they are no longer listed here.
---
-skip: GSport will "skip" that many screen redraws between refreshes.
-skip 0 will do 60 frames per second, -skip 1 will do 30 fps,
-skip 5 will do 10 fps.
-audio [0/1]: Forces audio [off/on]. By default, audio is on unless
the X display is a remote machine or shared memory is off.
This switch can override the default. -audio 0 causes GSport to
not fork the background audio process, but Ensoniq emulation
is still 100% accurate, just the sound is not sent to the
workstation speaker. Audio defaults off on Linux for now.
-arate {num}: Forces audio sample rate to {num}. 44100 and 48000 are
usual, you can try 22050 to reduce GSport's overhead. On a reasonably
fast machine (>250MHz or so), you shouldn't need to mess with this.
-dhr140: Will use the old Double-hires color algorithm that results in
exactly 140 colors across the screen, as opposed to the blending
being done by default.
---
X-Windows/Linux options:
---
-15: GSport will only look for a 15-bit X-Window display.
-16: GSport will only look for a 16-bit X-Window display (not tested, probably
will get red colors wrong).
-24: GSport will only look for a 24-bit X-Window display.
-display {machine:0.0}: Same as setting the environment variable DISPLAY.
Sends X display to {machine:0.0}.
-noshm: GSport will not try to used shared memory for the X graphics display.
This will make GSport much slower on graphics-intensive tasks,
by as much as a factor of 10! By default, -noshm causes an
effective -skip of 3 which is 15 fps. You can override this
default by specifying a -skip explicitly.
---
* Apple IIgs Control Panel
You can get to the Apple IIgs control panel (unless some application
has locked it out) using Ctrl-Command-Esc.
* Details on config.txt and disk images
The file <<<config.txt>>> describes the images GSport will use. Although you
can edit the file manually, in general you can use the Configuration Panel
to make all the changes you need. This information is for reference.
GSport by default will boot s7d1 (unless you've changed that using the
Apple IIgs control panel), so you should put an image in that slot.
GSport, by default, runs the IWM (3.5" and 5.25" disks) emulation in an
"approximate" mode, called "fast_disk_emul". In this mode, GSport
emulates the hardware "faster" than real, meaning the data the code
being emulated expects is made available much faster than on a real
Apple IIgs, providing a nice speed boost. For instance, the 5.25"
drives run 10x the real speed usually. Almost everything will work
except for nibble copiers, which don't like the data coming this fast.
(Meaning, unless you're using a nibble copier, you shouldn't run into an
issue. All games/demos/etc run fine in this mode). To make nibble
copiers work, Press F7.
GSport can read in the ".nib" nibblized disk format, but as read-only mode. If
the emulated image is no longer ProDOS or DOS 3.3 standard, GSport will
automatically treat the image as "Not-write-through-to-Image" from then
on. This mode means GSport will continue to emulate the disk properly in
memory, but it cannot encode the changes in the standard .dsk or .nib
image format. It prints a message saying it has done so. However,
the "disk" in emulation is fully useable as long as GSport is running. A
standard reformatting will not cause an image to flip to not-write-
through-to-Image, but running things like a "drive-speed" test will cause
further changes not to propagate to the Unix file. You will need
to "eject" the image and re-insert it before writes will take effect.
In full accuracy mode (i.e., not fast_disk_emul), 5.25" drive accesses
force GSport to run at 1MHz, and 3.5" drive accesses force GSport to run at
2.8MHz.
* GSport Timing
GSport supports running at four speeds: 1MHz, 2.8MHz, 8.0MHz, and Unlimited.
Pressing the middle mouse button cycles between these modes. The 1MHz
and 2.8MHz speeds force GSport to run at exactly those speeds, providing
accurate reproduction of a real Apple IIgs.
GSport will always run at 1MHz at least. If it is unable to keep up,
it will extend the emulated time to maintain the illusion of running
at 1MHz. That is, it may do just 40 screen refreshes per real second,
instead of the usual 60. This happens rarely.
If you force GSport to run at 1MHz, it will strive to run at exactly
1MHz (well, really 1.024MHz). If it is running faster (almost always),
it will pause briefly several times a second to maintain the 1MHz speed. It
does this in a friendly way that makes time available to other tasks.
This makes older Apple II games very playable just like a
real Apple IIgs on slow speed. GSport is running at exactly the same
speed as an Apple //e when in 1MHz mode. The 1MHz mode you set
through the right mouse button overrides the "fast" mode you can access
through the control panel. But, 3.5" accesses will "speed up" to 2.8MHz
to enable that code to operate correctly while the 3.5" disk is being
accessed.
If you force GSport to run at 2.8MHz, GSport tries to run at exactly 2.8MHz. But
like a real unaccelerated Apple IIgs, if you set the control panel to
"slow", it will really be running at 1MHz. Accesses to 5.25" disk
automatically slow down to 1MHz, when running the IWM in accurate
mode (F7). GSport may not be able to keep up with some programs running
at 2.8MHz due to video and sound overheads on lower-end machines. If
that happens, it effectively runs slower by extending the emulated
"second", like in the 1MHz mode. You can tell this is happening
when Eff MHz in the status area falls below 2.8MHz. If GSport is running
faster than 2.8MHz, it takes small pauses to slow down, just like in
1MHz. Many Apple IIgs demos must be run at 2.8MHz. The built-in
selftests (cmd-option-ctrl-Reset) must run at 2.8MHz. Many Apple IIgs
action games are more playable at 2.8MHz.
The 8.0MHz setting means follow the ZipGS-selected speed, but don't go
faster than 8.0MHz. If your host computer cannot keep up, then the
emulated second will be extended. You can use the ZipGS control panel,
or ZIPPY.GS on the sample disk image to set the emulated ZipGS speed to
anything from 1MHz to 8MHz in .5MHz increments.
The Unlimited setting means run as fast as possible, whatever speed that
is (but always above 1MHz). Eff MHz gives you the current Apple IIgs
equivalent speed. Many games will be unplayable at the unlimited
setting. Setting the IIgs control panel speed to "slow" will slow down
to 1MHz.
Sound output has an important relationship to GSport timing. GSport must
play one second of sound per second of emulated time. Normally, this
works out exactly right. But as noted above, if GSport can't maintain the
needed speed, it extends the emulated second. If it extends the second
to 1.4 real seconds, that means GSport only produces 1.0 second of sound
data every 1.4 seconds--the sound breaks up!
In all cases, 1MHz to GSport is 1.024MHz. And 2.8MHz to GSport is 2.56MHz
(trying to approximate the slowdown causes by memory refresh on a real
Apple IIgs). It's just easier to say 1MHz and 2.8MHz.
* GSport: What Works
Basically, just about every Apple II program works.
Some old Apple II 5.25" games require the old C600 ROM image, and don't work
with the default Apple IIgs ROM. This is not GSport's fault--these games
don't run on a real Apple IIgs either. GSport has built-in the old Apple II
Disk PROM which you can enable by using the IIgs control panel to set
Slot 6 to "Your Card". This allows many more Apple II games to run, and
is the recommended setting.
The NinjaForce Megademo mostly works, but sometimes hangs in the BBS Demo.
Just skip that demo if it happens.
The California Demo hangs at startup unless you use the IIgs control panel
to boot from slot 5, and then do a ctrl-Open_Apple-Reset to boot--doing
the above lets it work fine. This seems to be a bug in the demo.
* GSport bugs
On a ROM03, GSport makes a patch to the ROM image (inside emulation, not
to the ROM file) to fix a bug in the ROM code. Both ROM01 and ROM03
are patched to enable use of more than 8MB of memory. It then patches the ROM
self-tests to make the ROM checksum pass. But other programs, like
the Apple IIgs Diagnostic Disk, will detect a ROM checksum mismatch.
Don't worry about it.
Sound breaks up if GSport is unable to keep up--it should only be happening
if you are trying to force GSport to run at 2.8MHz, but cannot due to
sound and video overhead.
* Sound emulation
GSport supports very accurate classic Apple II sound (clicking of the
speaker using $C030) and fairly accurate Ensoniq sound.
When GSport determines that no sound has been produced for more than
5 seconds, it turns off the sound calculation routines for a small
speedup. It describes that it has done this by saying "Pausing sound"
in the debug window. However, when sound restarts, it sometimes
"breaks-up" a little.
If your display is not using shared memory, audio defaults to off unless
you override it with "-audio 1".
* SCC (Serial Port) emulation
You may use the SCC ports as either a LocalTalk networking connection
or as traditional serial ports. GSport emulates the two serial ports on
a IIgs as being two Unix sockets. Port 1 (printer port) is at socket
address 6501, and port 2 (modem) is at socket address 6502.
By default, slot 1 is emulated using a simple receive socket, and slot 2
emulates a Virtual Modem.
A Virtual Modem means GSport acts as if a modem is on the serial port
allowing Apple II communcation programs to fully work, but connected to
internet-enabled sockets. GSport emulates a "Hayes- Compatible" modem,
meaning it accepts "AT" commands. You can use GSport to connect to free
telnet-BBSs, or run a BBS program on GSport and become a telnet BBS yourself.
The two main AT commands are: ATDT for dialing out, and ATA for receiving
calls. To dial out, enter "ATDThostname", or for example,
"ATDTboycot.no-ip.com" (which is down at the moment, unfortunately).
You can also enter an IP address, like "ATDT127.0.0.1". On a Mac, to
create a telnet server to allow telnet connections (do not use over the
internet, but on a private network behind a firewall, this should be
fine), in a Terminal window type: "sudo /usr/libexec/telnetd -debug".
You must then enable telnet on port 23 through your Mac OS X Firewall in
the System Preferences->Sharing->Firewall page (just add port 23 as
open--you'll need to use the "New..." button and then select Other for
Port Name, and enter Port Number as 23). Then from GSport in a
communications program, do "ATDT127.0.0.1", and then log-in to your Mac.
GSport also accepts incoming "calls". Start GSport, and initialize the
Virtual Modem with some AT command (ATZ resets all state, and is a useful
start). GSport now has a socket port open, 6502 for slot 2, which you
can connect to using any telnet program. In a Terminal window, then
type "telnet 127.0.0.1 6502" and you will connect to GSport. The Virtual
Modem then starts printing "RING" every 2 seconds until you answer with
"ATA". You are now connected.
On Windows XP SP2, when GSport tries to open this incoming socket, you'll
need to enable it and click Unblock to the dialog that Windows pops up.
If you do not want incoming connections, you can block it instead.
Once connected, you can go back to talking to the Virtual Modem by
pressing + three times quickly (+++), and then not type anything for a second.
This goes back to the AT-command mode. You can now "ATH" to hang up, or
"ATO" to go back online.
On Windows, the socket code is very preliminary and there are problems
receiving connections.
GSport also supports an older, simpler socket interface, which it defaults
to using on slot 1. In GSport, from APPLESOFT, if you PR#1, all output will
then be sent to socket port 6501. You can see it by connecting to the
port using telnet. In another terminal window, do: "telnet localhost 6501"
and then you will see all the output going to the "printer".
Under APPLESOFT, you can PR#1 and IN#1. This gets input from the
socket also. You can type in the telnet window, it will be sent on
to the emulated IIgs. You may want to go to the F4 Config Panel and set
"mask off high bit" for serial port accesses to make PR#1 work a little nicer.
You can "print" from BASIC by using something like PR#1 in GSport and
"telnet localhost 6501 | tee file.out" in another window.
* GSport status area
The status area is updated once each second. It displays internal
emulation information.
---
Line 1: (Emulation speed info)
dcycs: number of seconds since GSport was started
sim MHz: Effective speed of GSport instruction emulation, not counting
overhead for video or sound routines.
Eff MHz: Above, but with overhead accounted for. Eff MHz is the
speed of an equivalent true Apple IIgs. This is extremely
accurate.
sec: The number of real seconds that have passed during on of GSport's
emulated seconds. Should be 1.00 +/- .01. Under 1
means GSport is running a bit fast, over 1 means GSport is
running slow. When you force speed to 2.8MHz, if GSport
can't keep up, it extends sec, so you can see how slow
it's really going here.
vol: Apple IIgs main audio volume control, in hex, from 0-F.
pal: Super-hires palette that is unavailable. GSport needs one palette
for the standard Apple // graphics mode on an 8-bit display,
and it grabs the least-used palette. Defaults to 0xe.
You can try changing it with F10. If you change it to a
palette that is not least used, GSport changes it back in
one second. Any superhires lines using the unavailable
palette will have their colors mapped into the
closest-matching "lores" colors, to minimize visual
impact.
Limit: Prints which speed setting the user has requested: 1MHz, 2.8MHz,
or Unlimited.
Line 2: (Video and X info)
xfer: In hex, number of bytes transferred to the X screen per second.
xred_cs: Percentage of Unix processor cycles that were spent in the X
server (or other processes on the machine).
ch_in: Percentage of Unix processor cycles spent checking for X input Events.
ref_l: Percentage of Unix processor cycles spent scanning the Apple IIgs
memory for changes to the current display screen memory,
and copying those changes to internal XImage buffers.
ref_x: Percentage of Unix processor cycles spent sending those XImage buffers
to the X server. Very similar to xred_cs.
Line 3: (Interpreter overhead)
Ints: Number of Apple IIgs interrupts over the last second.
I/O: Rate of I/O through the fake smartport interface (hard drives).
Does not count 3.5" or 5.25" disk accesses.
BRK: Number of BRKs over the last second.
COP: Number of COPs over the last second.
Eng: Number of calls to the main instruction interpreter loop in the
last second. All "interrupts" or other special behavior
causes the main interpreter loop to exit. A high call
rate here indicates a lot of overhead. 12000-15000 is normal.
20000+ indicates some sort of problem.
act: Some instructions are handled by the main interpreter loop returning
special status "actions" to main event loop. This is the
number over the last second. Should be low.
hev: This tracks HALT_EVENTs. GSport returns to the main loop to recalc
effective speed whenever any speed-changing I/O location is
touched. See the code, mostly in moremem.c
esi: This counts the number of superhires scan-line interrupts
taken in the last second.
edi: This counts the number of Ensoniq "special events" over the last
second. A sound that stops playing always causes a GSport
event, even if it doesn't cause a IIgs interrupt.
Line 4: (Ensoniq DOC info)
snd1,2,3,4: Percentage of Unix processor cycles spent handling various
sound activities. snd1 is the total sum of all sound overhead.
st: Percentage of Unix cycles spent starting new Ensoniq oscillators.
est: Percentage of Unix cycles spent looking for 0 bytes in sounds.
x.yz: This final number is the average number of oscillators playing
over the last second. Up to 4.00 is low overhead, over
20.0 is high overhead.
Line 5: (Ensoniq DOC info)
snd_plays: Number of calls to a routine called sound_play, which
plays Ensoniq sounds. Always called at least 60 times per sec.
doc_ev: Number of Ensoniq (DOC) events in the last second. A sound
stopping is an event, but changing a parameter of a sound
while it is playing is also an event.
st_snd: Number of sounds that were started in the last second.
snd_parms: Number of times a sound parameter was changed while it
was playing.
Line 6: (IWM info)
For each IWM device, this line displays the current track (and side for
3.5" disks). If a disk is spinning, there will be an "*" next to the
track number. Only updated once a second, so the disk arm moving may
appear to jump by several tracks. "fast_disk_emul:1" shows that GSport
is using less accurate, but faster, IWM emulation. Press F7 to toggle
to accurate disk emulation.
---
* X Window (Linux) interface information
If GSport fails to start under Linux, first try the following options:
---
GSport -audio 0 -noshm
---
There may be a bug with drawing the border on x86 Linux with Shared Memory--
add the options "-noshm -skip 0" to fix this up (but lose some graphics
performance, sorry). Try GSport without these options first, but use
this as a workaround if necessary.
If you want the display to go somewhere different, make sure the shell
environment variable $DISPLAY is set, or give the command-line argument
"-display {foo}".
GSport also forks off a subprocess to help handle the sound if audio is
active. If GSport crashes in a unusual way (a core dump, for instance),
you may have to manually kill the subprocess. ("ps -ef| grep GSport;kill
xxxxx").
Geoff Weiss adds some notes for mounting disks/floppies/CDs under
Solaris 7 through Solaris 10:
To use a CDROM, insert the CD and let Volume Management mount it.
Edit <<<config.txt>>> and use the filesystem that shows up in the "df -k"
listing. The volume name of the CDROM must be included. For example,
a CDROM in an IDE drive would look like this:
---
/vol/dev/dsk/c1t0d0/ciscocd
---
A CDROM in a SCSI drive would look like this:
---
/vol/dev/dsk/c0t6d0/j1170_10804
---
To provide low-level ADB emulation, GSport turns off Unix key repeat when the
focus is in the GSport window. It should be turned back on every time
the pointer leaves the GSport window, but sometimes it doesn't. Re-running
GSport (and then quitting it quickly) should turn key-repeat back on,
or you can type 'xset r' in another terminal window.
Sometimes the converse is true--key repeat is "on" when the cursor is
in the GSport window. Moving the cursor out of the window and then
back in should solve it. This is sometimes noticeable when running
Wolfenstein 3D GS.
GSport uses a private color-map for its X-window in 8-bit mode. This
may cause colormap "flash" when your cursor enters the window.
* GSport details/troubleshooting
GSport will work on all platforms with a 15/16-bit, 24-bit, or 32-bit
color display. GSport also supports an 8-bit display on X windows only.
On all platforms, it autodetects the color depth--no color switching
is necessary as long as you're at a supported depth.
* Disk Image Details
Images loaded into slot 6 (drive 1 or 2) are assumed to be 140K
5.25" disks, which is usually have the extension ".dsk". Images
loaded into slot 5 (drive 1 or 2) are assumed to be 800K disk images
and can be in any supported imahe format (including partitions, if
you have 800K partitions). Images loaded into slot 7 (drives 1
through 32) can be in any format and can be any size up to 4GB.
GSport boots s7d1 by default. You can change this using the emulated IIgs
control panel, just like a real Apple IIgs. GSport emulates a IIgs with
two 5.25" drives in slot 6, two 3.5" drives in slot 5, and up to 32
"hard drives" in slot 7. However, the current Configuration Panel only
lets you set through s7d11. ProDOS 8 can access disks up to s7d8, but GSOS
has no limit, so it's best to put HFS images past s7d8 in order to leave
more slots for ProDOS images.
If you're trying to use a real host device (CD-ROM, or hard drive, or
floppy), you should make the permissions on the /dev/disk* files something
like (meaning, everyone should have read permission):
---
brw-r--r-- 1 root operator 14, 0 Jun 10 00:01 /dev/disk2
---
You can do this on a Mac with:
---
sudo chmod 644 /dev/disk2
---

View File

@ -0,0 +1,53 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* END_HDR */
/* xdriver.c */
int main(int argc, char **argv);
void x_dialog_create_gsport_conf(const char *str);
int x_show_alert(int is_fatal, const char *str);
void x_update_color(int col_num, int red, int green, int blue, word32 rgb);
void x_update_physical_colormap(void);
void show_xcolor_array(void);
int my_error_handler(Display *display, XErrorEvent *ev);
void xdriver_end(void);
void show_colormap(char *str, Colormap cmap, int index1, int index2, int index3);
void x_badpipe(int signum);
void dev_video_init(void);
Visual *x_try_find_visual(int depth, int screen_num, XVisualInfo **visual_list_ptr);
void x_set_mask_and_shift(word32 x_mask, word32 *mask_ptr, int *shift_left_ptr, int *shift_right_ptr);
int xhandle_shm_error(Display *display, XErrorEvent *event);
void x_get_kimage(Kimage *kimage_ptr);
int get_shm(Kimage *kimage_ptr);
void get_ximage(Kimage *kimage_ptr);
void x_redraw_status_lines(void);
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height);
void x_push_done(void);
int x_update_mouse(int raw_x, int raw_y, int button_states, int buttons_valid);
void check_input_events(void);
void x_hide_pointer(int do_hide);
void handle_keysym(XEvent *xev_in);
int x_keysym_to_a2code(int keysym, int is_up);
void x_update_modifier_state(int state);
void x_auto_repeat_on(int must);
void x_auto_repeat_off(int must);
void x_full_screen(int do_full);

View File

@ -0,0 +1,76 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// Various ASCII codepage to unicode maps
static const Bit16u cp437Map[256] = {
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
};
IWCHARMAP iwcharmap[] = {
{437, cp437Map},
{0, NULL},
};
static const Bit16u codepages[15] = {0, 437};
static const Bit16u intCharSets[8][10] =
{
{0x0023, 0x0040, 0x005b, 0x005c, 0x005d, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // USA
{0x00a3, 0x00a7, 0x00b0, 0x00e7, 0x00e9, 0x00f9, 0x00e0, 0x00f2, 0x00e8, 0x00ec}, // Italian
{0x0023, 0x0040, 0x00c6, 0x00d8, 0x00c5, 0x0060, 0x00e6, 0x00f8, 0x00e5, 0x007e}, // Danish
{0x00a3, 0x0040, 0x005b, 0x005c, 0x005d, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e}, // UK
{0x0023, 0x00a7, 0x00c4, 0x00d6, 0x00dc, 0x0060, 0x00e4, 0x00f6, 0x00fc, 0x00df}, // Germany
{0x0023, 0x0040, 0x00c4, 0x00d6, 0x00c5, 0x0060, 0x00e4, 0x00f6, 0x00e5, 0x007e}, // Swedish
{0x00a3, 0x00e0, 0x00b0, 0x00e7, 0x00a7, 0x0060, 0x00e9, 0x00f9, 0x00e8, 0x00a8}, // France
{0x00a3, 0x00a7, 0x00a1, 0x00d1, 0x00bf, 0x0060, 0x00b0, 0x00f1, 0x00e7, 0x007e}, // Spanish
};
/*
Paper size definitions. Units are Postscript points (1/72in).
This list is based on the options available in the GS/OS
Imagewriter LQ driver.
*/
static const Bit16u paperSizes[7][2] =
{
{612, 792}, //US Letter 8.5 x 11in
{612, 1008}, //US Legal 8.5 x 14in
{595, 842}, //ISO A4 210 x 297mm
{499, 709}, //ISO B5 176 x 250mm
{1071, 792}, //Wide Fanfold 14 x 11in
{792, 1224}, //Ledger/Tabloid 11 x 17in
{842, 1191}, // ISO A3 297 x 420mm
};

View File

@ -0,0 +1,279 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
.word inst00_SYM+1 /* brk */
.word inst01_SYM+1 /* ORA (Dloc,X) */
.word inst02_SYM+1 /* COP */
.word inst03_SYM+1 /* ORA Disp8,S */
.word inst04_SYM+1 /* TSB Dloc */
.word inst05_SYM+1 /* ORA Dloc */
.word inst06_SYM+1 /* ASL Dloc */
.word inst07_SYM+1 /* ORA [Dloc] */
.word inst08_SYM+0 /* PHP */
.word inst09_SYM+4 /* ORA #imm */
.word inst0a_SYM+0 /* ASL a */
.word inst0b_SYM+0 /* PHD */
.word inst0c_SYM+2 /* TSB abs */
.word inst0d_SYM+2 /* ORA abs */
.word inst0e_SYM+2 /* ASL abs */
.word inst0f_SYM+3 /* ORA long */
.word inst10_SYM+1 /* BPL disp8 */
.word inst11_SYM+1 /* ORA (),y */
.word inst12_SYM+1 /* ORA () */
.word inst13_SYM+1 /* ORA (disp8,s),y */
.word inst14_SYM+1 /* TRB Dloc */
.word inst15_SYM+1 /* ORA Dloc,x */
.word inst16_SYM+1 /* ASL Dloc,x */
.word inst17_SYM+1 /* ORA [],y */
.word inst18_SYM+0 /* clc */
.word inst19_SYM+2 /* ORA abs,y */
.word inst1a_SYM+0 /* INC a */
.word inst1b_SYM+0 /* TCS */
.word inst1c_SYM+2 /* TRB Abs */
.word inst1d_SYM+2 /* ORA Abs,X */
.word inst1e_SYM+2 /* ASL abs,x */
.word inst1f_SYM+3 /* ORA Long,x */
.word inst20_SYM+2 /* JSR abs */
.word inst21_SYM+1 /* AND (Dloc,X) */
.word inst22_SYM+3 /* JSL Abslong */
.word inst23_SYM+1 /* AND Disp8,S */
.word inst24_SYM+1 /* BIT Dloc */
.word inst25_SYM+1 /* AND Dloc */
.word inst26_SYM+1 /* ROL Dloc */
.word inst27_SYM+1 /* AND [Dloc] */
.word inst28_SYM+0 /* PLP */
.word inst29_SYM+4 /* AND #imm */
.word inst2a_SYM+0 /* ROL a */
.word inst2b_SYM+0 /* PLD */
.word inst2c_SYM+2 /* BIT abs */
.word inst2d_SYM+2 /* AND abs */
.word inst2e_SYM+2 /* ROL abs */
.word inst2f_SYM+3 /* AND long */
.word inst30_SYM+1 /* BMI disp8 */
.word inst31_SYM+1 /* AND (),y */
.word inst32_SYM+1 /* AND () */
.word inst33_SYM+1 /* AND (disp8,s),y */
.word inst34_SYM+1 /* BIT Dloc,X */
.word inst35_SYM+1 /* AND Dloc,x */
.word inst36_SYM+1 /* ROL Dloc,x */
.word inst37_SYM+1 /* AND [],y */
.word inst38_SYM+0 /* SEC */
.word inst39_SYM+2 /* AND abs,y */
.word inst3a_SYM+0 /* DEC a */
.word inst3b_SYM+0 /* TSC */
.word inst3c_SYM+2 /* BIT Abs,X */
.word inst3d_SYM+2 /* AND Abs,X */
.word inst3e_SYM+2 /* ROL abs,x */
.word inst3f_SYM+3 /* AND Long,x */
.word inst40_SYM+0 /* RTI */
.word inst41_SYM+1 /* EOR (Dloc,X) */
.word inst42_SYM+1 /* WDM */
.word inst43_SYM+1 /* EOR Disp8,S */
.word inst44_SYM+2 /* MVP I,J */
.word inst45_SYM+1 /* EOR Dloc */
.word inst46_SYM+1 /* LSR Dloc */
.word inst47_SYM+1 /* EOR [Dloc] */
.word inst48_SYM+0 /* PHA */
.word inst49_SYM+4 /* EOR #imm */
.word inst4a_SYM+0 /* LSR a */
.word inst4b_SYM+0 /* PHK */
.word inst4c_SYM+2 /* JMP abs */
.word inst4d_SYM+2 /* EOR abs */
.word inst4e_SYM+2 /* LSR abs */
.word inst4f_SYM+3 /* EOR long */
.word inst50_SYM+1 /* BVC disp8 */
.word inst51_SYM+1 /* EOR (),y */
.word inst52_SYM+1 /* EOR () */
.word inst53_SYM+1 /* EOR (disp8,s),y */
.word inst54_SYM+2 /* MVN I,J */
.word inst55_SYM+1 /* EOR Dloc,x */
.word inst56_SYM+1 /* LSR Dloc,x */
.word inst57_SYM+1 /* EOR [],y */
.word inst58_SYM+0 /* CLI */
.word inst59_SYM+2 /* EOR abs,y */
.word inst5a_SYM+0 /* PHY */
.word inst5b_SYM+0 /* TCD */
.word inst5c_SYM+3 /* JMP Long */
.word inst5d_SYM+2 /* EOR Abs,X */
.word inst5e_SYM+2 /* LSR abs,x */
.word inst5f_SYM+3 /* EOR Long,x */
.word inst60_SYM+0 /* RTS */
.word inst61_SYM+1 /* ADC (Dloc,X) */
.word inst62_SYM+2 /* PER DISP16 */
.word inst63_SYM+1 /* ADC Disp8,S */
.word inst64_SYM+1 /* STZ Dloc */
.word inst65_SYM+1 /* ADC Dloc */
.word inst66_SYM+1 /* ROR Dloc */
.word inst67_SYM+1 /* ADC [Dloc] */
.word inst68_SYM+0 /* PLA */
.word inst69_SYM+4 /* ADC #imm */
.word inst6a_SYM+0 /* ROR a */
.word inst6b_SYM+0 /* RTL */
.word inst6c_SYM+2 /* JMP (abs) */
.word inst6d_SYM+2 /* ADC abs */
.word inst6e_SYM+2 /* ROR abs */
.word inst6f_SYM+3 /* ADC long */
.word inst70_SYM+1 /* BVS disp8 */
.word inst71_SYM+1 /* ADC (),y */
.word inst72_SYM+1 /* ADC () */
.word inst73_SYM+1 /* ADC (disp8,s),y */
.word inst74_SYM+1 /* STZ Dloc,X */
.word inst75_SYM+1 /* ADC Dloc,x */
.word inst76_SYM+1 /* ROR Dloc,x */
.word inst77_SYM+1 /* ADC [],y */
.word inst78_SYM+0 /* SEI */
.word inst79_SYM+2 /* ADC abs,y */
.word inst7a_SYM+0 /* PLY */
.word inst7b_SYM+0 /* TDC */
.word inst7c_SYM+2 /* JMP (abs,x) */
.word inst7d_SYM+2 /* ADC Abs,X */
.word inst7e_SYM+2 /* ROR abs,x */
.word inst7f_SYM+3 /* ADC Long,x */
.word inst80_SYM+1 /* BRA Disp8 */
.word inst81_SYM+1 /* STA (Dloc,X) */
.word inst82_SYM+2 /* BRL DISP16 */
.word inst83_SYM+1 /* STA Disp8,S */
.word inst84_SYM+1 /* STY Dloc */
.word inst85_SYM+1 /* STA Dloc */
.word inst86_SYM+1 /* STX Dloc */
.word inst87_SYM+1 /* STA [Dloc] */
.word inst88_SYM+0 /* DEY */
.word inst89_SYM+4 /* BIT #imm */
.word inst8a_SYM+0 /* TXA */
.word inst8b_SYM+0 /* PHB */
.word inst8c_SYM+2 /* STY abs */
.word inst8d_SYM+2 /* STA abs */
.word inst8e_SYM+2 /* STX abs */
.word inst8f_SYM+3 /* STA long */
.word inst90_SYM+1 /* BCC disp8 */
.word inst91_SYM+1 /* STA (),y */
.word inst92_SYM+1 /* STA () */
.word inst93_SYM+1 /* STA (disp8,s),y */
.word inst94_SYM+1 /* STY Dloc,X */
.word inst95_SYM+1 /* STA Dloc,x */
.word inst96_SYM+1 /* STX Dloc,y */
.word inst97_SYM+1 /* STA [],y */
.word inst98_SYM+0 /* TYA */
.word inst99_SYM+2 /* STA abs,y */
.word inst9a_SYM+0 /* TXS */
.word inst9b_SYM+0 /* TXY */
.word inst9c_SYM+2 /* STX abs */
.word inst9d_SYM+2 /* STA Abs,X */
.word inst9e_SYM+2 /* STZ abs,x */
.word inst9f_SYM+3 /* STA Long,x */
.word insta0_SYM+5 /* LDY #imm */
.word insta1_SYM+1 /* LDA (Dloc,X) */
.word insta2_SYM+5 /* LDX #imm */
.word insta3_SYM+1 /* LDA Disp8,S */
.word insta4_SYM+1 /* LDY Dloc */
.word insta5_SYM+1 /* LDA Dloc */
.word insta6_SYM+1 /* LDX Dloc */
.word insta7_SYM+1 /* LDA [Dloc] */
.word insta8_SYM+0 /* TAY */
.word insta9_SYM+4 /* LDA #imm */
.word instaa_SYM+0 /* TAX */
.word instab_SYM+0 /* PLB */
.word instac_SYM+2 /* LDY abs */
.word instad_SYM+2 /* LDA abs */
.word instae_SYM+2 /* LDX abs */
.word instaf_SYM+3 /* LDA long */
.word instb0_SYM+1 /* BCS disp8 */
.word instb1_SYM+1 /* LDA (),y */
.word instb2_SYM+1 /* LDA () */
.word instb3_SYM+1 /* LDA (disp8,s),y */
.word instb4_SYM+1 /* LDY Dloc,X */
.word instb5_SYM+1 /* LDA Dloc,x */
.word instb6_SYM+1 /* LDX Dloc,y */
.word instb7_SYM+1 /* LDA [],y */
.word instb8_SYM+0 /* CLV */
.word instb9_SYM+2 /* LDA abs,y */
.word instba_SYM+0 /* TSX */
.word instbb_SYM+0 /* TYX */
.word instbc_SYM+2 /* LDY abs,x */
.word instbd_SYM+2 /* LDA Abs,X */
.word instbe_SYM+2 /* LDX abs,y */
.word instbf_SYM+3 /* LDA Long,x */
.word instc0_SYM+5 /* CPY #Imm */
.word instc1_SYM+1 /* CMP (Dloc,X) */
.word instc2_SYM+1 /* REP #8bit */
.word instc3_SYM+1 /* CMP Disp8,S */
.word instc4_SYM+1 /* CPY Dloc */
.word instc5_SYM+1 /* CMP Dloc */
.word instc6_SYM+1 /* DEC Dloc */
.word instc7_SYM+1 /* CMP [Dloc] */
.word instc8_SYM+0 /* INY */
.word instc9_SYM+4 /* CMP #imm */
.word instca_SYM+0 /* DEX */
.word instcb_SYM+0 /* WAI */
.word instcc_SYM+2 /* CPY abs */
.word instcd_SYM+2 /* CMP abs */
.word instce_SYM+2 /* DEC abs */
.word instcf_SYM+3 /* CMP long */
.word instd0_SYM+1 /* BNE disp8 */
.word instd1_SYM+1 /* CMP (),y */
.word instd2_SYM+1 /* CMP () */
.word instd3_SYM+1 /* CMP (disp8,s),y */
.word instd4_SYM+1 /* PEI Dloc */
.word instd5_SYM+1 /* CMP Dloc,x */
.word instd6_SYM+1 /* DEC Dloc,x */
.word instd7_SYM+1 /* CMP [],y */
.word instd8_SYM+0 /* CLD */
.word instd9_SYM+2 /* CMP abs,y */
.word instda_SYM+0 /* PHX */
.word instdb_SYM+0 /* STP */
.word instdc_SYM+2 /* JML (Abs) */
.word instdd_SYM+2 /* CMP Abs,X */
.word instde_SYM+2 /* DEC abs,x */
.word instdf_SYM+3 /* CMP Long,x */
.word inste0_SYM+5 /* CPX #Imm */
.word inste1_SYM+1 /* SBC (Dloc,X) */
.word inste2_SYM+1 /* SEP #8bit */
.word inste3_SYM+1 /* SBC Disp8,S */
.word inste4_SYM+1 /* CPX Dloc */
.word inste5_SYM+1 /* SBC Dloc */
.word inste6_SYM+1 /* INC Dloc */
.word inste7_SYM+1 /* SBC [Dloc] */
.word inste8_SYM+0 /* INX */
.word inste9_SYM+4 /* SBC #imm */
.word instea_SYM+0 /* NOP */
.word insteb_SYM+0 /* XBA */
.word instec_SYM+2 /* CPX abs */
.word insted_SYM+2 /* SBC abs */
.word instee_SYM+2 /* INC abs */
.word instef_SYM+3 /* SBC long */
.word instf0_SYM+1 /* BEQ disp8 */
.word instf1_SYM+1 /* SBC (),y */
.word instf2_SYM+1 /* SBC () */
.word instf3_SYM+1 /* SBC (disp8,s),y */
.word instf4_SYM+2 /* PEA Imm */
.word instf5_SYM+1 /* SBC Dloc,x */
.word instf6_SYM+1 /* INC Dloc,x */
.word instf7_SYM+1 /* SBC [],y */
.word instf8_SYM+0 /* SED */
.word instf9_SYM+2 /* SBC abs,y */
.word instfa_SYM+0 /* PLX */
.word instfb_SYM+0 /* XCE */
.word instfc_SYM+2 /* JSR (Abs,x) */
.word instfd_SYM+2 /* SBC Abs,X */
.word instfe_SYM+2 /* INC abs,x */
.word instff_SYM+3 /* SBC Long,x */
.block 4*16

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _BITTYPES_H
#define _BITTYPES_H
#ifndef HAVE_U_INT8_T
#if SIZEOF_CHAR == 1
typedef unsigned char u_int8_t;
typedef signed char int8_t;
#elif SIZEOF_INT == 1
typedef unsigned int u_int8_t;
typedef signed int int8_t;
#else /* XXX */
#error "there's no appropriate type for u_int8_t"
#endif
#define HAVE_U_INT8_T 1
#define HAVE_INT8_T 1
#endif /* HAVE_U_INT8_T */
#ifndef HAVE_U_INT16_T
#if SIZEOF_SHORT == 2
typedef unsigned short u_int16_t;
typedef signed short int16_t;
#elif SIZEOF_INT == 2
typedef unsigned int u_int16_t;
typedef signed int int16_t;
#elif SIZEOF_CHAR == 2
typedef unsigned char u_int16_t;
typedef signed char int16_t;
#else /* XXX */
#error "there's no appropriate type for u_int16_t"
#endif
#define HAVE_U_INT16_T 1
#define HAVE_INT16_T 1
#endif /* HAVE_U_INT16_T */
#ifndef HAVE_U_INT32_T
#if SIZEOF_INT == 4
typedef unsigned int u_int32_t;
typedef signed int int32_t;
#elif SIZEOF_LONG == 4
typedef unsigned long u_int32_t;
typedef signed long int32_t;
#elif SIZEOF_SHORT == 4
typedef unsigned short u_int32_t;
typedef signed short int32_t;
#else /* XXX */
#error "there's no appropriate type for u_int32_t"
#endif
#define HAVE_U_INT32_T 1
#define HAVE_INT32_T 1
#endif /* HAVE_U_INT32_T */
#endif /* _BITTYPES_H */

View File

@ -0,0 +1,17 @@
TARGET = gsportx
OBJECTS = $(OBJECTS1) $(TFEOBJ) $(ATOBJ) $(PCAPOBJ) xdriver.o
CC = gcc
CCOPTS = -O2 -Wall -fomit-frame-pointer -std=gnu99 -march=armv6
OPTS = -DGSPORT_LITTLE_ENDIAN -DHAVE_TFE -DTOGGLE_STATUS -DHAVE_ATBRIDGE
SUFFIX =
NAME = gsportx
LDFLAGS =
LDOPTS =
LD = g++
EXTRA_LIBS = -lXext
EXTRA_SPECIALS =
AS = cc
PERL = perl
XOPTS = -I/usr/X11R6/include

View File

@ -0,0 +1,18 @@
#
# There is some very useful information on compilation on the Mac, where we need
# to take a lot of things into account (bitness, OS level, endianness), here:
# http://www.kyngchaos.com/macosx/notes/universal64
#
CC = /usr/bin/g++-4.0
ARCH = -arch i386 -arch ppc
SDK = -isysroot /Developer/SDKs/MacOSX10.4u.sdk -isysroot /Developer/SDKs/MacOSX10.5.sdk
TARGET = gsportmac
OBJECTS = $(OBJECTS1) scc_macdriver.o macsnd_driver.o macdriver_generic.o macdriver_console.o
CCOPTS = -O2 -DMAC $(ARCH) $(SDK)
CPPOPTS = $(ARCH) $(SDK)
SUFFIX =
NAME = gsportmac
XOPTS = -Wall -fpascal-strings -mdynamic-no-pic
XLIBS =
LDOPTS = -I. -prebind -framework Carbon -framework Quicktime

View File

@ -0,0 +1,66 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "defcomm.h"
link .reg %r2
acc .reg %r3
xreg .reg %r4
yreg .reg %r5
stack .reg %r6
dbank .reg %r7
direct .reg %r8
neg .reg %r9
zero .reg %r10
psr .reg %r11
kpc .reg %r12
const_fd .reg %r13
instr .reg %r14
#if 0
cycles .reg %r13
kbank .reg %r14
#endif
page_info_ptr .reg %r15
inst_tab_ptr .reg %r16
fcycles_stop_ptr .reg %r17
addr_latch .reg %r18
scratch1 .reg %r19
scratch2 .reg %r20
scratch3 .reg %r21
scratch4 .reg %r22
;instr .reg %r23 ; arg3
fcycles .reg %fr12
fr_plus_1 .reg %fr13
fr_plus_2 .reg %fr14
fr_plus_3 .reg %fr15
fr_plus_x_m1 .reg %fr16
fcycles_stop .reg %fr17
fcycles_last_dcycs .reg %fr18
ftmp1 .reg %fr4
ftmp2 .reg %fr5
fscr1 .reg %fr6
#define LDC(val,reg) ldil L%val,reg ! ldo R%val(reg),reg

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,17 @@
TARGET = gsportx
OBJECTS = $(OBJECTS1) $(TFEOBJ) $(ATOBJ) $(PCAPOBJ) xdriver.o
CC = gcc
CCOPTS = -O2 -Wall -fomit-frame-pointer -std=gnu99 -march=i686 -DHAVE_TFE -DHAVE_ATBRIDGE -DTOGGLE_STATUS
OPTS = -DGSPORT_LITTLE_ENDIAN
SUFFIX =
NAME = gsportx
LDFLAGS =
LDOPTS =
LD = g++
EXTRA_LIBS = -lXext
EXTRA_SPECIALS =
AS = cc
PERL = perl
XOPTS = -I/usr/X11R6/include

View File

@ -0,0 +1,104 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*tfe.c*/
#ifndef _PROTOS_TFE_H
#define _PROTOS_TFE_H
#ifndef FALSE
#define FALSE 0
#define TRUE !FALSE
#endif
extern int tfe_enabled;
void tfe_init(void);
int tfe_resources_init(void);
int tfe_cmdline_options_init(void);
int set_tfe_interface(const char* name);
void get_disabled_state(int * param);
void tfe_reset(void);
void tfe_shutdown(void);
byte tfe_read(word16 addr);
void tfe_store(word16 addr, byte var);
/* Unused in this version of TFE, and generates complaints
int tfe_read_snapshot_module(struct snapshot_s *s);
int tfe_write_snapshot_module(struct snapshot_s *s);
*/
int tfe_enumadapter_open(void);
int tfe_enumadapter(char **ppname, char **ppdescription);
int tfe_enumadapter_close(void);
/*tfearch.c*/
int tfe_arch_init(void);
void tfe_arch_pre_reset(void);
void tfe_arch_post_reset(void);
int tfe_arch_activate(const char *interface_name);
void tfe_arch_deactivate(void);
void tfe_arch_set_mac(const byte mac[6]);
void tfe_arch_set_hashfilter(const int hash_mask[2]);
void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */
int bIA, /* individual address (IA) */
int bMulticast, /* multicast if address passes the hash filter */
int bCorrect, /* accept correct frames */
int bPromiscuous, /* promiscuous mode */
int bIAHash /* accept if IA passes the hash filter */
);
void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver);
void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */
int onecoll, /* ONECOLL: Terminate after just one collision */
int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */
int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */
int txlength, /* Frame length */
byte *txframe /* Pointer to the frame to be transmitted */
);
int tfe_arch_receive(byte *pbuffer , /* where to store a frame */
int *plen, /* IN: maximum length of frame to copy;
OUT: length of received frame
OUT can be bigger than IN if received frame was
longer than supplied buffer */
int *phashed, /* set if the dest. address is accepted by the hash filter */
int *phash_index, /* hash table index if hashed == TRUE */
int *prx_ok, /* set if good CRC and valid length */
int *pcorrect_mac, /* set if dest. address is exactly our IA */
int *pbroadcast, /* set if dest. address is a broadcast address */
int *pcrc_error /* set if received frame had a CRC error */
);
/*
This is a helper for tfe_receive() to determine if the received frame should be accepted
according to the settings.
This function is even allowed to be called in tfearch.c from tfe_arch_receive() if
necessary, which is the reason why its prototype is included here in tfearch.h.
*/
int tfe_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index,
int *pcorrect_mac, int *pbroadcast, int *pmulticast);
int tfe_arch_enumadapter_open(void);
int tfe_arch_enumadapter(char **ppname, char **ppdescription);
int tfe_arch_enumadapter_close(void);
#endif

View File

@ -0,0 +1,44 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define CONF_BUF_LEN 1024
#define COPY_BUF_SIZE 4096
#define CFG_PRINTF_BUFSIZE 2048
#define CFG_PATH_MAX 1024
#define CFG_NUM_SHOWENTS 16
#define CFGTYPE_MENU 1
#define CFGTYPE_INT 2
#define CFGTYPE_DISK 3
#define CFGTYPE_FUNC 4
#define CFGTYPE_FILE 5
#define CFGTYPE_STR 6
/* CFGTYPE limited to just 4 bits: 0-15 */
/* Cfg_menu, Cfg_dirent and Cfg_listhdr are defined in defc.h */
STRUCT(Cfg_defval) {
Cfg_menu *menuptr;
int intval;
char *strval;
};

View File

@ -0,0 +1,76 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
parallel.c
This file handles the Apple II Parallel Card emulation in slot 1. Its very
basic, but allows for future support of redirecting the output to a real
parallel port, files, and additional types of emulated printers.
*/
#include "defc.h"
#include "printer.h"
extern int g_parallel_out_masking;
extern word32 g_vbl_count;
extern int g_printer_timeout;
word32 printer_vbl_count = 0;
int port_block = 0;
byte parallel_read(word16 io_address)
{
//printf("parallel card status called at %x\n", io_address);
//since we only have a virtual printer, always return state as "Ready"
return 0xff;
}
void parallel_write(word16 io_address, byte val)
{
//Mask MSB if user has it set.
if(g_parallel_out_masking) {
val = val & 0x7f;
}
//printf("parallel card called at %x\n", io_address);
//send a byte to the virtual printer
//By default all output to $C090 gets sent to the printer
if (io_address == 0x00)
{
port_block = 1;
printer_loop(val);
printer_vbl_count = g_vbl_count+(g_printer_timeout*60);
port_block = 0;
}
return;
}
//This function handles the automatic timeout of the virtual printer if an
//application doesn't send a form feed at the end of the page. It also
//allows multipage mode Postscript and native printer documents to
//print somewhat how a regular application would.
void printer_update()
{
if (port_block != 1 && printer_vbl_count != 0 && g_vbl_count >= printer_vbl_count)
{
printf("Calling printer_update and flushing!\n");
printer_feed();
printer_vbl_count = 0;
}
return;
}

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\arch\win32\pcap.h" />
<ClInclude Include="aarp.h" />
<ClInclude Include="atalk.h" />
<ClInclude Include="atbridge.h" />
<ClInclude Include="elap.h" />
<ClInclude Include="elap_defs.h" />
<ClInclude Include="llap.h" />
<ClInclude Include="pcap_delay.h" />
<ClInclude Include="port.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="aarp.c" />
<ClCompile Include="atbridge.c" />
<ClCompile Include="elap.c" />
<ClCompile Include="llap.c" />
<ClCompile Include="pcap_delay.c" />
<ClCompile Include="port.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2C88133A-7CB8-4C03-AF4D-4ECFC6F8500B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>atbridge</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<CompileAs>Default</CompileAs>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<CompileAs>Default</CompileAs>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,274 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This file contains the Win32 COM1/COM2 calls */
#include "defc.h"
#include "scc.h"
#ifdef __CYGWIN__
#include <Windows.h>
#include <NspAPI.h>
#endif
#ifdef UNDER_CE
#define vsnprintf _vsnprintf
#endif
extern Scc scc_stat[2];
extern word32 g_c025_val;
#ifdef _WIN32
int
scc_serial_win_init(int port)
{
COMMTIMEOUTS commtimeouts;
TCHAR str_buf[8];
Scc *scc_ptr;
HANDLE host_handle;
int state;
int ret;
scc_ptr = &(scc_stat[port]);
scc_ptr->state = 0; /* mark as failed */
#ifdef UNICODE
wsprintf(&str_buf[0], _T("COM%d"), port+1);
#else
sprintf(&str_buf[0], "COM%d", port+1);
#endif
host_handle = CreateFile(&str_buf[0], GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
scc_ptr->host_handle = host_handle;
scc_ptr->host_handle2 = malloc(sizeof(DCB));
printf("scc_socket_init %d called, host_handle: %p\n", port,
host_handle);
if(host_handle == INVALID_HANDLE_VALUE) {
scc_ptr->host_handle = 0;
return 0;
}
scc_serial_win_change_params(port);
commtimeouts.ReadIntervalTimeout = MAXDWORD;
commtimeouts.ReadTotalTimeoutMultiplier = 0;
commtimeouts.ReadTotalTimeoutConstant = 0;
commtimeouts.WriteTotalTimeoutMultiplier = 0;
commtimeouts.WriteTotalTimeoutConstant = 10;
ret = SetCommTimeouts(host_handle, &commtimeouts);
if(ret == 0) {
printf("setcommtimeout ret: %d\n", ret);
}
state = 2; /* raw serial */
scc_ptr->state = state;
return state;
}
void
scc_serial_win_change_params(int port)
{
DCB *dcbptr;
HANDLE host_handle;
Scc *scc_ptr;
int ret;
scc_ptr = &(scc_stat[port]);
host_handle = scc_ptr->host_handle;
dcbptr = (DCB*)scc_ptr->host_handle2; // OG Added cast
if(host_handle == 0) {
return;
}
ret = GetCommState(host_handle, dcbptr);
if(ret == 0) {
printf("getcomm port%d ret: %d\n", port, ret);
}
#if 1
printf("dcb.baudrate: %d, bytesize:%d, stops:%d, parity:%d\n",
(int)dcbptr->BaudRate, (int)dcbptr->ByteSize,
(int)dcbptr->StopBits, (int)dcbptr->Parity);
printf("dcb.binary: %d, ctsflow: %d, dsrflow: %d, dtr: %d, dsr: %d\n",
(int)dcbptr->fBinary,
(int)dcbptr->fOutxCtsFlow,
(int)dcbptr->fOutxDsrFlow,
(int)dcbptr->fDtrControl,
(int)dcbptr->fDsrSensitivity);
printf("dcb.txonxoff:%d, outx:%d, inx: %d, null: %d, rts: %d\n",
(int)dcbptr->fTXContinueOnXoff,
(int)dcbptr->fOutX,
(int)dcbptr->fInX,
(int)dcbptr->fNull,
(int)dcbptr->fRtsControl);
printf("dcb.fAbortOnErr:%d, fParity:%d\n", (int)dcbptr->fAbortOnError,
(int)dcbptr->fParity);
#endif
dcbptr->fAbortOnError = 0;
dcbptr->BaudRate = scc_ptr->baud_rate;
dcbptr->ByteSize = scc_ptr->char_size;
dcbptr->StopBits = ONESTOPBIT;
switch((scc_ptr->reg[4] >> 2) & 0x3) {
case 2: // 1.5 stop bits
dcbptr->StopBits = ONE5STOPBITS;
break;
case 3: // 2 stop bits
dcbptr->StopBits = TWOSTOPBITS;
break;
}
dcbptr->Parity = NOPARITY;
switch((scc_ptr->reg[4]) & 0x3) {
case 1: // Odd parity
dcbptr->Parity = ODDPARITY;
break;
case 3: // Even parity
dcbptr->Parity = EVENPARITY;
break;
}
dcbptr->fNull = 0;
dcbptr->fDtrControl = DTR_CONTROL_ENABLE;
dcbptr->fDsrSensitivity = 0;
dcbptr->fOutxCtsFlow = 0;
dcbptr->fOutxDsrFlow = 0;
dcbptr->fParity = 0;
dcbptr->fInX = 0;
dcbptr->fOutX = 0;
dcbptr->fRtsControl = RTS_CONTROL_ENABLE;
ret = SetCommState(host_handle, dcbptr);
if(ret == 0) {
printf("SetCommState ret: %d, new baud: %d\n", ret,
(int)dcbptr->BaudRate);
}
}
void
scc_serial_win_fill_readbuf(int port, int space_left, double dcycs)
{
byte tmp_buf[256];
Scc *scc_ptr;
HANDLE host_handle;
DWORD bytes_read;
DWORD i;
int ret;
scc_ptr = &(scc_stat[port]);
host_handle = scc_ptr->host_handle;
if(host_handle == 0) {
return;
}
/* Try reading some bytes */
space_left = MIN(256, space_left);
ret = ReadFile(host_handle, tmp_buf, space_left, &bytes_read, NULL);
if(ret == 0) {
printf("ReadFile ret 0\n");
}
if(ret && (bytes_read > 0)) {
for(i = 0; i < bytes_read; i++) {
scc_add_to_readbuf(port, tmp_buf[i], dcycs);
}
}
}
void
scc_serial_win_empty_writebuf(int port)
{
Scc *scc_ptr;
HANDLE host_handle;
int rdptr;
int wrptr;
int done;
word32 err_code;
DWORD bytes_written;
int ret;
int len;
scc_ptr = &(scc_stat[port]);
//printf("win_empty_writebuf, host_handle: %d\n", scc_ptr->host_handle);
host_handle = scc_ptr->host_handle;
if(host_handle == 0) {
return;
}
/* Try writing some bytes */
done = 0;
while(!done) {
rdptr = scc_ptr->out_rdptr;
wrptr = scc_ptr->out_wrptr;
if(rdptr == wrptr) {
//printf("...rdptr == wrptr\n");
done = 1;
break;
}
len = wrptr - rdptr;
if(len < 0) {
len = SCC_OUTBUF_SIZE - rdptr;
}
if(len > 32) {
len = 32;
}
if(len <= 0) {
done = 1;
break;
}
bytes_written = 1;
ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len,
&bytes_written, NULL);
printf("WriteFile ret: %d, bytes_written:%d, len:%d\n", ret,
(int)bytes_written, len);
err_code = (word32)-1;
if(ret == 0) {
err_code = (word32)GetLastError();
printf("WriteFile ret:0, err_code: %08x\n", err_code);
}
if(ret == 0 || (bytes_written == 0)) {
done = 1;
break;
} else {
rdptr = rdptr + bytes_written;
if(rdptr >= SCC_OUTBUF_SIZE) {
rdptr = rdptr - SCC_OUTBUF_SIZE;
}
scc_ptr->out_rdptr = rdptr;
}
}
}
#endif

View File

@ -0,0 +1,7 @@
@REM
@REM Sorry, this is hopelessly tied to my environment...
@REM I hope folks don't really want to build the doc themselves.
@REM
call c:\dev\env
rmdir /q /s target
call mvn site

View File

@ -0,0 +1,48 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// $KmKId: protos_windriver.h,v 1.4 2004-03-23 17:27:26-05 kentd Exp $
/* END_HDR */
/* windriver.c */
int win_update_mouse(int x, int y, int button_states, int buttons_valid);
void win_event_mouse(int umsg,WPARAM wParam, LPARAM lParam);
void win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags);
void win_event_quit(HWND hwnd);
void win_event_redraw(void);
LRESULT CALLBACK win_event_handler(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam);
void inspect_file(LPTSTR lpstrFile);
int main(int argc, char **argv);
void check_input_events(void);
void x_update_color(int col_num, int red, int green, int blue, word32 rgb);
void x_update_physical_colormap(void);
void show_xcolor_array(void);
void xdriver_end(void);
void x_get_kimage(Kimage *kimage_ptr);
void dev_video_init(void);
void x_redraw_status_lines(void);
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height);
void x_push_done(void);
void x_auto_repeat_on(int must);
void x_auto_repeat_off(int must);
void x_hide_pointer(int do_hide);

View File

@ -0,0 +1,188 @@
/*
* This file is a consolidation of functions required for tfe
* emulation taken from the following files
*
* lib.c - Library functions.
* util.c - Miscellaneous utility functions.
* crc32.c
*
* Written by
* Andreas Boose <viceteam@t-online.de>
* Ettore Perazzoli <ettore@comm2000.it>
* Andreas Matthies <andreas.matthies@gmx.net>
* Tibor Biczo <crown@mail.matav.hu>
* Spiro Trikaliotis <Spiro.Trikaliotis@gmx.de>*
*
* This file is part of VICE, the Versatile Commodore Emulator.
* See README for copyright notice.
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA.
*
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef WIN32
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <commdlg.h>
#endif
#include "tfesupp.h"
// Lib Stuff
/* #define LIB_DEBUG*/
#ifdef LIB_DEBUG
#define LIB_DEBUG_SIZE 0x10000
#define LIB_DEBUG_GUARD 0x1000
#endif
#define CRC32_POLY 0xedb88320
static unsigned long crc32_table[256];
static int crc32_is_initialized = 0;
void lib_free(void *ptr)
{
#ifdef LIB_DEBUG
lib_debug_free(ptr, 1, 1);
#endif
#ifdef LIB_DEBUG
lib_debug_libc_free(ptr);
#else
free(ptr);
#endif
}
void *lib_malloc(size_t size)
{
#ifdef LIB_DEBUG
void *ptr = lib_debug_libc_malloc(size);
#else
void *ptr = malloc(size);
#endif
#ifndef __OS2__
if (ptr == NULL && size > 0)
exit(-1);
#endif
#ifdef LIB_DEBUG
lib_debug_alloc(ptr, size, 3);
#endif
return ptr;
}
/*-----------------------------------------------------------------------*/
/* Malloc enough space for `str', copy `str' into it and return its
address. */
char *lib_stralloc(const char *str)
{
size_t size;
char *ptr;
if (str == NULL)
exit(-1);
size = strlen(str) + 1;
ptr = (char *)lib_malloc(size);
memcpy(ptr, str, size);
return ptr;
}
/* Like realloc, but abort if not enough memory is available. */
void *lib_realloc(void *ptr, size_t size)
{
#ifdef LIB_DEBUG
void *new_ptr = lib_debug_libc_realloc(ptr, size);
#else
void *new_ptr = realloc(ptr, size);
#endif
#ifndef __OS2__
if (new_ptr == NULL)
exit(-1);
#endif
#ifdef LIB_DEBUG
lib_debug_free(ptr, 1, 0);
lib_debug_alloc(new_ptr, size, 1);
#endif
return new_ptr;
}
// Util Stuff
/* Set a new value to the dynamically allocated string *str.
Returns `-1' if nothing has to be done. */
int util_string_set(char **str, const char *new_value)
{
if (*str == NULL) {
if (new_value != NULL)
*str = lib_stralloc(new_value);
} else {
if (new_value == NULL) {
lib_free(*str);
*str = NULL;
} else {
/* Skip copy if src and dest are already the same. */
if (strcmp(*str, new_value) == 0)
return -1;
*str = (char *)lib_realloc(*str, strlen(new_value) + 1);
strcpy(*str, new_value);
}
}
return 0;
}
// crc32 Stuff
unsigned long crc32_buf(const char *buffer, unsigned int len)
{
int i, j;
unsigned long crc, c;
const char *p;
if (!crc32_is_initialized) {
for (i = 0; i < 256; i++) {
c = (unsigned long) i;
for (j = 0; j < 8; j++)
c = c & 1 ? CRC32_POLY ^ (c >> 1) : c >> 1;
crc32_table[i] = c;
}
crc32_is_initialized = 1;
}
crc = 0xffffffff;
for (p = buffer; len > 0; ++p, --len)
crc = (crc >> 8) ^ crc32_table[(crc ^ *p) & 0xff];
return ~crc;
}

View File

@ -0,0 +1,69 @@
-----
GSport History
-----
David Schmidt (david__schmidt at users dot souceforge dot net)
-----
GSport Release History
* Version 0.31 - 6/22/2014
New functionality:
* Added {{{./appletalk.html}AppleTalk}} networking emulation with bridging to EtherTalk
* Added clipboard text paste capability (OSX, Windows)
* Emulated serial ports are individually configurable as either
IP or passthrough to real hardware ports
* Added Imagewriter LQ printer emulation
[]
Bug fixes:
* IN#1 and IN#2 now trigger the incoming IP port to listen when
using IP simulated serial ports; previously, only PR#1 or PR#2
did
* Fixed crash when parallel.rom is missing
* Fix for real joysticks: unless the joystick is moving, gsport
sets the values to zero
[]
* Version 0.2a - 2/29/2012
New functionality:
* Added text-based virtual printer output for all platforms
* Added OSX drag/drop "installer" disk image (.dmg)
* Disk images will automatically mount and boot when specified as
the last argument on the command line, or when invoked from the
Windows shell (file->open as GSport.exe)
[]
Bug fixes:
* Win32: Added sound and native printer libraries, mistakenly omitted
* OSX: Fixed some "endianness" troubles with the fat binaries
[]
* Version 0.1 - 1/6/2011 released as interim build
New functionality:
* Added Uthernet support in slot 3. Code comes from the VICE emulator.
* Added virtual printer support in slot 1. Code comes from DOSBox emulator.
[]

View File

@ -0,0 +1,332 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2013-2014 by Peter Neubauer
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/** This module implements the LLAP port of the bridge. **/
#include <stdbool.h>
#include "../defc.h"
#include "atbridge.h"
#include "port.h"
#include "llap.h"
typedef enum {
LLAP_DDP_SHORT = 0x01,
LLAP_DDP_LONG = 0x02,
LLAP_ENQ = 0x81,
LLAP_ACK = 0x82,
LLAP_RTS = 0x84,
LLAP_CTS = 0x85
} LLAP_TYPES;
const unsigned int LLAP_PACKET_MAX = 603 /* bytes */;
const unsigned int LLAP_PACKET_MIN = 3 /* bytes */;
const double LLAP_IDG = 400 /* microseconds */;
const double LLAP_IFG = 200 /* microseconds */;
const double GAP_TOLERANCE = 4.0;
static struct packet_port_t llap_port;
typedef enum {
DIALOG_READY,
DIALOG_GOT_CTS,
DIALOG_WAIT_IDG
} DIALOG_STATE;
static DIALOG_STATE dialog_state;
static double dialog_end_dcycs;
static double last_frame_dcycs;
void llap_init()
{
dialog_state = DIALOG_READY;
last_frame_dcycs = 0;
port_init(&llap_port);
}
void llap_shutdown()
{
port_shutdown(&llap_port);
}
/** Queue one data packet out from the bridge's LLAP port and into the guest. **/
void llap_enqueue_out(struct packet_t* packet)
{
// Generate the RTS.
struct packet_t* rts = (struct packet_t*)malloc(sizeof(struct packet_t));
rts->source.network = packet->source.network;
rts->source.node = packet->source.node;
rts->dest.network = packet->dest.network;
rts->dest.node = packet->dest.node;
rts->size = 0;
rts->data = 0;
rts->type = LLAP_RTS;
enqueue_packet(&llap_port.out, rts);
// Enqueue the data.
enqueue_packet(&llap_port.out, packet);
}
struct packet_t* llap_dequeue_in()
{
return dequeue(&llap_port.in);
}
static void llap_dump_packet(size_t size, byte data[])
{
if (size < LLAP_PACKET_MIN)
atbridge_printf("LLAP short packet.\n");
else if (size > LLAP_PACKET_MAX)
atbridge_printf("LLAP long packet.\n");
else
{
at_node_t dest = data[0];
at_node_t source = data[1];
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
const char* typeName = 0;
switch (type)
{
case LLAP_DDP_SHORT:
typeName = "DDP (short)";
break;
case LLAP_DDP_LONG:
typeName = "DDP (long)";
break;
case LLAP_ENQ:
typeName = "lapENQ";
break;
case LLAP_ACK:
typeName = "lapACK";
break;
case LLAP_RTS:
typeName = "lapRTS";
break;
case LLAP_CTS:
typeName = "lapCTS";
break;
}
if (typeName)
atbridge_printf("LLAP[%d->%d] %s: %d bytes.\n", source, dest, typeName, size);
else
atbridge_printf("LLAP[%d->%d] %x: %d bytes.\n", source, dest, type, size);
/*for (size_t i = 0; i < size; i++)
atbridge_printf("%02x ", data[i]);
atbridge_printf("\n");*/
}
}
/** Reply to a control packet from the GS **/
static void llap_reply_control(at_node_t dest, at_node_t source, LLAP_TYPES type)
{
struct at_addr_t dest_addr = { 0, dest };
struct at_addr_t source_addr = { 0, source };
// Insert control packets at the head of the queue contrary to normal FIFO queue operation
// to ensure that control frames arrive in the intended order.
insert(&llap_port.out, dest_addr, source_addr, type, 0, 0);
}
/** Accept a data packet from the GS. **/
static void llap_handle_data(size_t size, byte data[])
{
at_node_t dest = data[0];
at_node_t source = data[1];
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
const size_t data_size = size - 3;
byte* data_copy = (byte*)malloc(data_size);
memcpy(data_copy, data + 3, data_size);
struct at_addr_t dest_addr = { 0, dest };
struct at_addr_t source_addr = { 0, source };
enqueue(&llap_port.in, dest_addr, source_addr, type, data_size, data_copy);
}
/** Accept a control packet from the GS. **/
static void llap_handle_control(size_t size, byte data[])
{
at_node_t dest = data[0];
at_node_t source = data[1];
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
struct at_addr_t addr = { atbridge_get_net(), dest };
switch (type)
{
case LLAP_ENQ:
// Require the GS to take a valid "client" address not known to be in use.
if (dest > 127 || dest == 0 || atbridge_address_used(&addr))
llap_reply_control(source, dest, LLAP_ACK);
break;
case LLAP_ACK:
break;
case LLAP_RTS:
if (dest != at_broadcast_node)
// The GS is trying to make a directed transmission. Provide the required RTS/CTS handshake.
// Note that broadcast packets do not require a CTS.
llap_reply_control(source, dest, LLAP_CTS);
break;
case LLAP_CTS:
// The GS sent a CTS. If the bridge has pending data, prepare to deliver the packet.
dialog_state = DIALOG_GOT_CTS;
break;
default:
break;
}
}
/** Occassionally, we receive an invalid packet from the GS. I'm unsure if this is due to a bug in GS/OS
or, more likely, a bug in the SCC emulation. Regardless, when such a thing does occur, discard the
current, corrupted dialog. Link errors are routine in real LocalTalk networks, and LocalTalk will recover.
**/
static void llap_reset_dialog()
{
dialog_state = DIALOG_READY;
last_frame_dcycs = 0;
// Discard packets until the queue is either empty or the next dialog starts (and dialogs begin with an RTS).
while (true)
{
struct packet_t* packet = queue_peek(&llap_port.out);
if (packet && (packet->type != LLAP_RTS))
{
packet = dequeue(&llap_port.out);
if (packet->data)
free(packet->data);
free(packet);
}
else
break;
}
}
/** Transfer (send) one LLAP packet from the GS. **/
void llap_enqueue_in(double dcycs, size_t size, byte data[])
{
atbridge_printf("<%0.0f> TX: ", dcycs);
llap_dump_packet(size, data);
if (size < LLAP_PACKET_MIN)
atbridge_printf("ATBridge: Dropping LLAP short packet.\n");
else if (size > LLAP_PACKET_MAX)
atbridge_printf("ATBridge: Dropping LLAP long packet.\n");
else
{
last_frame_dcycs = dcycs;
LLAP_TYPES type = (LLAP_TYPES)(data[2]);
switch (type)
{
case LLAP_DDP_SHORT:
case LLAP_DDP_LONG:
llap_handle_data(size, data);
break;
case LLAP_ENQ:
case LLAP_ACK:
case LLAP_RTS:
case LLAP_CTS:
llap_handle_control(size, data);
break;
default:
// Intentionally check for valid types and ingore packets with invalid types.
// Sometimes, the bridge gets invalid packets from the GS, which tends to break the bridge.
atbridge_printf("ATBridge: Dropping LLAP packet with invalid type.\n");
llap_reset_dialog();
}
}
}
/** Transfer (receive) one LLAP packet to the GS. **/
void llap_dequeue_out(double dcycs, size_t* size, byte* data[])
{
*size = 0;
// The LocalTalk protocol requires a minimum 400us gap between dialogs (called the IDG).
// If necessary, wait for the IDG.
if (dialog_state == DIALOG_WAIT_IDG)
{
if ((dcycs - dialog_end_dcycs) >= LLAP_IDG)
// The IDG is done.
dialog_state = DIALOG_READY;
else
// Continue waiting for the IDG.
return;
}
// The LocalTalk protocols requires a maximum 200us gap between frames within a dialog (called the IFG).
// If we exceed the IFG, the bridge must be stuck in an incomplete or corrupt dialog. In this case,
// discard the current dialog and try again.
if ((dialog_state != DIALOG_READY) && (last_frame_dcycs != 0) && ((dcycs - last_frame_dcycs) >= (GAP_TOLERANCE*LLAP_IFG)))
{
llap_reset_dialog();
atbridge_printf("ATBridge: Dialog reset due to IFG violation.\n");
}
struct packet_t* packet = queue_peek(&llap_port.out);
if ((dialog_state == DIALOG_READY) && (packet) && !(packet->type & 0x80) && (last_frame_dcycs != 0) && ((dcycs - last_frame_dcycs) >= (GAP_TOLERANCE*LLAP_IDG)))
{
llap_reset_dialog();
packet = queue_peek(&llap_port.out);
atbridge_printf("ATBridge: Dialog reset due to IDG violation.\n");
}
if (packet &&
((packet->type & 0x80) || /* Pass along control frames without waiting for a CTS. */
(!(packet->type & 0x80) && (packet->dest.node == at_broadcast_node) && (dialog_state == DIALOG_READY)) || /* Pass along broadcast frames, which don't wait for CTS frames. */
(!(packet->type & 0x80) && (packet->dest.node != at_broadcast_node) && (dialog_state == DIALOG_GOT_CTS)))) /* Pass along directed frames only after receiving a CTS handshake. */
{
dequeue(&llap_port.out);
// Prepend the LLAP header.
*size = packet->size + 3 + 2;
*data = (byte*)malloc(*size);
(*data)[0] = packet->dest.node;
(*data)[1] = packet->source.node;
(*data)[2] = packet->type;
// Insert the data into the new LLAP packet.
if (*size)
memcpy((*data) + 3, packet->data, packet->size);
// Fake a frame check sequence (FCS). Since our SCC emulation doesn't actually
// check the FCS, the value of the FCS doesn't matter.
(*data)[packet->size + 3 + 0] = 0xff;
(*data)[packet->size + 3 + 1] = 0xff;
atbridge_printf("<%0.0f> RX: ", dcycs);
llap_dump_packet(*size, *data);
if (packet->type & 0x80)
dialog_state = DIALOG_READY;
else
{
// This was the last packet in the dialog.
dialog_state = DIALOG_WAIT_IDG;
dialog_end_dcycs = dcycs;
}
last_frame_dcycs = dcycs;
free(packet->data);
free(packet);
}
}

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="llap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="atbridge.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="elap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\arch\win32\pcap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="port.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="aarp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="elap_defs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="atalk.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pcap_delay.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="llap.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="atbridge.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="elap.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="port.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="aarp.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pcap_delay.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,58 @@
//{{NO_DEPENDENCIES}}
// $Id: $
// Microsoft Developer Studio generated include file.
// Used by win32.rc
//
#define CREATEPROCESS_MANIFEST 1
#define IDD_ABOUT_DIALOG 101
#define IDC_GSPORT32 102
#define IDR_TOOLBAR 103
#define IDD_DLG_DISKCONF 104
#define IDR_ACCEL 105
#define IDD_GSPORT32_KEY 106
#define ID_TOOLBAR 5000
#define ID_STATUSBAR 5001
#define IDC_EDIT_S5D1 10051
#define IDC_EDIT_S5D2 10052
#define IDC_EDIT_S6D1 10061
#define IDC_EDIT_S6D2 10062
#define IDC_EDIT_S7D1 10071
#define IDC_EDIT_S7D2 10072
#define IDC_BTN_S5D1 11051
#define IDC_BTN_S5D2 11052
#define IDC_BTN_S6D1 11061
#define IDC_BTN_S6D2 11062
#define IDC_BTN_S7D1 11071
#define IDC_BTN_S7D2 11072
#define ID_HELP_ABOUT 40001
#define ID_FILE_EXIT 40002
#define ID_FILE_DISK 40003
#define ID_FILE_SENDRESET 40004
#define ID_FILE_JOYSTICK 40005
#define ID_FILE_DEBUGSTAT 40006
#define ID_FILE_FULLSCREEN 40012
#define ID_FILE_SPEED 40013
#define ID_HELP_KEY 40014
#define ID_FILE_SENDREBOOT 40007
#define ID_FILE_FLUSHPRINTER 40017
#define ID_SPEED_1MHZ 50001
#define ID_SPEED_2MHZ 50002
#define ID_SPEED_8MHZ 50003
#define ID_SPEED_FMHZ 50004
#define IDD_SPEEDDIALOG 117
#define IDC_SLOW 1007
#define IDC_CUSTOM 1008
#define IDC_EDITCUSTOM 1009
#define IDC_NORMAL 1010
#define IDC_FASTEST 1011
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 111
#define _APS_NEXT_COMMAND_VALUE 40013
#define _APS_NEXT_CONTROL_VALUE 1003
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -0,0 +1,48 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <os2.h>
#include "gsportos2.h"
ICON ID_WINDOW gsportos2.ico
BITMAP ID_BITMAP gsportos2.bmp
MENU ID_WINDOW PRELOAD
BEGIN
SUBMENU "~Options", ID_OPTIONS
BEGIN
MENUITEM "Option ~1\tCtrl+A", ID_OPTION1, MIS_TEXT
MENUITEM "Option ~2\tCtrl+B", ID_OPTION2, MIS_TEXT
MENUITEM "Option ~3\tCtrl+C", ID_OPTION3, MIS_TEXT
END
END
ACCELTABLE ID_WINDOW PRELOAD
BEGIN
VK_F3, ID_EXITPROG, VIRTUALKEY
END
STRINGTABLE PRELOAD
BEGIN
IDS_HELLO, "Hello"
END


View File

@ -0,0 +1,123 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define MAX_TRACKS (2*80)
#define MAX_C7_DISKS 32
#define NIB_LEN_525 0x1900 /* 51072 bits per track */
#define NIBS_FROM_ADDR_TO_DATA 20
#define DSK_TYPE_PRODOS 0
#define DSK_TYPE_DOS33 1
#define DSK_TYPE_NIB 2
typedef struct _Disk Disk;
STRUCT(Trk) {
Disk *dsk;
byte *nib_area;
int track_dirty;
int overflow_size;
int track_len;
int unix_pos;
int unix_len;
};
struct _Disk {
double dcycs_last_read;
char *name_ptr;
char *partition_name;
int partition_num;
FILE *file;
int force_size;
int image_start;
int image_size;
int smartport;
int disk_525;
int drive;
int cur_qtr_track;
int image_type;
int vol_num;
int write_prot;
int write_through_to_unix;
int disk_dirty;
int just_ejected;
int last_phase;
int nib_pos;
int num_tracks;
Trk *trks;
};
STRUCT(Iwm) {
Disk drive525[2];
Disk drive35[2];
Disk smartport[MAX_C7_DISKS];
int motor_on;
int motor_off;
int motor_off_vbl_count;
int motor_on35;
int head35;
int step_direction35;
int iwm_phase[4];
int iwm_mode;
int drive_select;
int q6;
int q7;
int enable2;
int reset;
word32 previous_write_val;
int previous_write_bits;
};
STRUCT(Driver_desc) {
word16 sig;
word16 blk_size;
word32 blk_count;
word16 dev_type;
word16 dev_id;
word32 data;
word16 drvr_count;
};
STRUCT(Part_map) {
word16 sig;
word16 sigpad;
word32 map_blk_cnt;
word32 phys_part_start;
word32 part_blk_cnt;
char part_name[32];
char part_type[32];
word32 data_start;
word32 data_cnt;
word32 part_status;
word32 log_boot_start;
word32 boot_size;
word32 boot_load;
word32 boot_load2;
word32 boot_entry;
word32 boot_entry2;
word32 boot_cksum;
char processor[16];
char junk[128];
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,6 @@
s@\<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"\>@<a href="http://sourceforge.net/projects/gsport"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=315628&amp;type=13" width="120" height="30" alt="Get GSport at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>@ig;s@\<img alt="Built by Maven" src="\./images/logos/maven-feather.png"\>\</img\>@<p>@ig;
s@href="http://sourceforge.net/projects/gsport/files/"@href="http://sourceforge.net/projects/gsport/files/" target\="_new"@ig;
s@\</body\>@\<!-- Piwik --\> \<script type\=\"text\/javascript\"\> var pkBaseURL \= \(\(\"https:\" \=\= document.location.protocol\) ? \"https:\/\/sourceforge.net\/apps\/piwik\/gsport\/\" : \"http:\/\/sourceforge.net\/apps\/piwik\/gsport\/\"\); document.write\(unescape\(\"%3Cscript src\='\" + pkBaseURL + \"piwik.js' type\='text\/javascript'%3E%3C\/script%3E\"\)\); \<\/script\>\<script type\=\"text\/javascript\"\> try { var piwikTracker \= Piwik.getTracker\(pkBaseURL + \"piwik.php\", 1\);piwikTracker.trackPageView\(\); piwikTracker.enableLinkTracking\(\);} catch\( err \) {} \<\/script\>\<noscript\>\<p\>\<img src\=\"http:\/\/sourceforge.net\/apps\/piwik\/gsport\/piwik.php?idsite\=1\" style\=\"border:0\" alt\=\"\"\/\>\<\/p\>\<\/noscript\>\<!-- End Piwik Tag --\>@ig;
s@<img src="images/download.png" alt="" />@<a href="http://sourceforge.net/projects/gsport/files/" target\="_new"><img src="images/download.png" /></a>@ig;
s@<img src="images/gsport.png" />@<a href="http://sourceforge.net/projects/gsport/files/" target\="_new"><img src="images/gsport.png" /></a>@ig;
s@\<img class="poweredBy" alt="Built by Maven" src="\./images/logos/maven-feather.png" \/\>@@ig;

View File

@ -0,0 +1,10 @@
cd target\site
perl -i.orig -p ..\..\removeMaven.re appletalk.html
perl -i.orig -p ..\..\removeMaven.re developing.html
perl -i.orig -p ..\..\removeMaven.re ethernet.html
perl -i.orig -p ..\..\removeMaven.re history.html
perl -i.orig -p ..\..\removeMaven.re index.html
perl -i.orig -p ..\..\removeMaven.re operating.html
perl -i.orig -p ..\..\removeMaven.re printer.html
erase *.orig
cd ..\..

View File

@ -0,0 +1,426 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2013-2014 by Peter Neubauer
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/** This module is the "heart" of the bridge and provides the connection between the ELAP and LLAP ports. **/
#include <stdbool.h>
#include "../defc.h"
#include <stddef.h>
#include <time.h>
#include "atbridge.h"
#include "port.h"
#include "elap.h"
#include "llap.h"
#include "aarp.h"
#ifdef WIN32
#include <winsock.h>
#elif __linux__
#include <netinet/in.h>
#endif
extern struct packet_port_t elap_port;
static bool diagnostics = false;
static bool sent_rtmp_request = false;
static struct at_addr_t local_address = { 0, 0 };
static const at_network_t NET_STARTUP_LOW = 0xFF00;
static const at_network_t NET_STARTUP_HIGH = 0xFFFE;
static const at_node_t NODE_STARTUP_LOW = 0x01;
static const at_node_t NODE_STARTUP_HIGH = 0xFE;
static void send_rtmp_request();
bool atbridge_init()
{
// If the GS reboots, we may try to reinitialize the bridge. If this is the case, keep the old address and AMT.
if (local_address.network == 0)
{
// Obtain a provisional node address and startup range network.
//
// This isn't correct for an extended network (like ELAP) but works adequately on small networks.
// The bridge should follow the complicated process on page 4-9 to obtain the network and node number.
srand((unsigned int)time(0));
local_address.network = (at_network_t)((double)rand()/RAND_MAX * (NET_STARTUP_HIGH - NET_STARTUP_LOW) + NET_STARTUP_LOW);
local_address.node = (at_node_t)((double)rand()/RAND_MAX + (NODE_STARTUP_HIGH - NODE_STARTUP_LOW) + 0x01);
aarp_init();
llap_init();
if (!elap_init())
{
atbridge_shutdown();
return false;
}
}
return true;
}
void atbridge_shutdown()
{
llap_shutdown();
elap_shutdown();
aarp_shutdown();
}
void atbridge_set_diagnostics(bool enabled)
{
diagnostics = enabled;
}
bool atbridge_get_diagnostics()
{
return diagnostics;
}
void atbridge_printf(const char *fmt, ...)
{
if (atbridge_get_diagnostics())
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
}
const struct at_addr_t* atbridge_get_addr()
{
return &local_address;
}
const at_network_t atbridge_get_net()
{
return local_address.network;
}
const at_node_t atbridge_get_node()
{
return local_address.node;
}
void atbridge_set_net(at_network_t net)
{
local_address.network = net;
}
void atbridge_set_node(at_node_t node)
{
local_address.node = node;
}
bool atbridge_address_used(const struct at_addr_t* addr)
{
if (!sent_rtmp_request)
send_rtmp_request();
return aarp_address_used(addr);
}
/* Calculate a DDP checksum, per Apple's documented algorithm in 4-17 of "Inside AppleTalk". */
static word16 get_checksum(size_t size, byte data[])
{
word16 cksum = 0;
for (unsigned int i = 0; i < size; i++)
{
cksum += data[i];
cksum = (cksum << 1) | ((cksum & 0x8000) >> 15); // roll left
}
if (cksum == 0)
cksum = 0xffff;
return cksum;
}
static void calculate_checksum(struct packet_t* packet)
{
if (packet && packet->data && (packet->size >= sizeof(struct DDP_LONG)) && (packet->type == LAP_DDP_LONG))
{
struct DDP_LONG* header = (struct DDP_LONG*)(packet->data);
header->checksum = htons(get_checksum(
packet->size - offsetof(struct DDP_LONG, dest_net),
(byte*)&header->dest_net));
}
}
/* Convert a long-form DDP header to a short-form header. This function only converts the headers. */
static word16 convert_ddp_header_to_short(const struct DDP_LONG* in, struct DDP_SHORT* out)
{
word16 size;
if (!in || !out)
return 0;
size = ((in->length[0] & 0x3) << 8) + (in->length[1]) - (sizeof(struct DDP_LONG) - sizeof(struct DDP_SHORT));
out->length[0] = (size >> 8) & 0x03;
out->length[1] = size & 0xff;
out->dest_socket = in->dest_socket;
out->source_socket = in->source_socket;
out->type = in->type;
return size;
}
/* Convert a short-form DDP header to a long-form header. ELAP requires long-form, but LLAP often uses short-form. */
/* This function only converts the headers. */
static word16 convert_ddp_header_to_long(const struct at_addr_t dest, const struct at_addr_t source, const struct DDP_SHORT* in, struct DDP_LONG* out)
{
word16 size;
if (!in || !out)
return 0;
size = ((in->length[0] & 0x3) << 8) + (in->length[1]) + (sizeof(struct DDP_LONG) - sizeof(struct DDP_SHORT));
out->length[0] = (size >> 8) & 0x03;
out->length[1] = size & 0xff;
out->checksum = 0x0000; /* 0x0000 == no checksum calculated, reference 4-17 */
if (dest.network)
out->dest_net = dest.network;
else
out->dest_net = atbridge_get_net();
out->dest_net = (at_network_t)htons(out->dest_net);
if (source.network)
out->source_net = source.network;
else
out->source_net = atbridge_get_net();
out->source_net = (at_network_t)htons(out->source_net);
out->dest_node = dest.node;
out->source_node = source.node;
out->dest_socket = in->dest_socket;
out->source_socket = in->source_socket;
out->type = in->type;
return size;
}
/* Convert a short-form DDP packet to a long-form packet. */
/* This function converts an entire packet, not just the header. */
static void convert_ddp_packet_to_long(struct packet_t* packet)
{
if (packet && (packet->type == LAP_DDP_SHORT) && packet->data && (packet->size >= sizeof(struct DDP_SHORT)))
{
struct DDP_SHORT* header_short = (struct DDP_SHORT*)packet->data;
const size_t payload_size = packet->size - sizeof(struct DDP_SHORT);
byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_LONG));
struct DDP_LONG* header_long = (struct DDP_LONG*)data;
const word16 size = convert_ddp_header_to_long(packet->dest, packet->source, header_short, header_long);
packet->dest.network = ntohs(header_long->dest_net);
packet->source.network = ntohs(header_long->source_net);
memcpy(data + sizeof(struct DDP_LONG), packet->data + sizeof(struct DDP_SHORT), payload_size);
packet->type = LAP_DDP_LONG;
packet->size = size;
// Replace the original short-form packet data.
free(packet->data);
packet->data = data;
calculate_checksum(packet);
}
}
/* Convert a long-form DDP packet to short-form. */
static void convert_ddp_packet_to_short(struct packet_t* packet)
{
if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
{
struct DDP_LONG* header_long = (struct DDP_LONG*)packet->data;
const size_t payload_size = packet->size - sizeof(struct DDP_LONG);
byte* data = (byte*)malloc(payload_size + sizeof(struct DDP_SHORT));
struct DDP_SHORT* header_short = (struct DDP_SHORT*)data;
const word16 size = convert_ddp_header_to_short(header_long, header_short);
memcpy(data + sizeof(struct DDP_SHORT), packet->data + sizeof(struct DDP_LONG), payload_size);
packet->type = LAP_DDP_SHORT;
packet->size = size;
free(packet->data);
packet->data = data;
}
}
/*static void convert_rtmp_to_extended(struct packet_t* packet)
{
if (packet && (packet->type == LAP_DDP_SHORT) && packet->data)
{
struct DDP_SHORT* header_short = (struct DDP_SHORT*)packet->data;
if (header_short->type != DDP_TYPE_RTMP || header_short->dest_socket != DDP_SOCKET_RTMP)
return;
struct rtmp_nonextended_data_t* in = (struct rtmp_nonextended_data_t*)(packet->data + sizeof(struct DDP_SHORT));
// Construct a new long-form DDP packet header.
size_t size = sizeof(struct DDP_LONG) + sizeof(struct rtmp_extended_data_t);
byte* data = (byte*)malloc(size);
struct DDP_LONG* header_long = (struct DDP_LONG*)data;
convert_ddp_header_to_long(packet->dest, packet->source, header_short, header_long);
struct rtmp_extended_data_t* out = (struct rtmp_extended_data_t*)(data + sizeof(struct DDP_LONG));
out->net = in->net;
out->id_length = in->id_length;
out->node = in->node;
// Copy the routing tuples.
struct rtmp_nonextended_tuple_t* in_tuple = (struct rtmp_nonextended_tuple_t*)(packet->data + sizeof(struct DDP_SHORT) + sizeof(struct rtmp_nonextended_data_t));
struct rtmp_extended_tuple_t* out_tuple = (struct rtmp_extended_tuple_t*)(data + size);
while ((byte*)in_tuple < (packet->data + packet->size))
{
size += sizeof(struct rtmp_extended_tuple_t);
realloc(data, size);
out_tuple->range_start = in_tuple->net;
out_tuple->distance = in_tuple->distance | 0x80;
out_tuple->range_end = in_tuple->net;
out_tuple->delimiter = RTMP_TUPLE_DELIMITER;
in_tuple++;
}
free(packet->data);
packet->data = data;
packet->size = size;
packet->type = LAP_DDP_LONG;
}
}*/
static void convert_rtmp_to_nonextended(struct packet_t* packet)
{
if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
{
struct DDP_LONG* header_long = (struct DDP_LONG*)packet->data;
if (header_long->type != DDP_TYPE_RTMP || header_long->dest_socket != DDP_SOCKET_RTMP)
return;
struct rtmp_extended_data_t* in = (struct rtmp_extended_data_t*)(packet->data + sizeof(struct DDP_LONG));
size_t size = sizeof(struct DDP_SHORT) + sizeof(struct rtmp_nonextended_response_t);
byte* data = (byte*)malloc(size);
struct DDP_SHORT* header_short = (struct DDP_SHORT*)data;
convert_ddp_header_to_short(header_long, header_short);
header_short->length[0] = (size >> 8) & 0x03;
header_short->length[1] = size & 0xff;
struct rtmp_nonextended_response_t* out = (struct rtmp_nonextended_response_t*)(data + sizeof(struct DDP_SHORT));
out->net = in->net;
out->id_length = in->id_length;
out->node = in->node;
/*rtmp_extended_tuple_t* in_tuple = (rtmp_extended_tuple_t*)(packet->data + sizeof(DDP_LONG) + sizeof(rtmp_extended_data_t));
rtmp_nonextended_tuple_t* out_tuple = (rtmp_nonextended_tuple_t*)(data + size);
while ((byte*)in_tuple < (packet->data + packet->size))
{
size += sizeof(rtmp_nonextended_tuple_t);
realloc(data, size);
out_tuple->net = in_tuple->range_start;
out_tuple->distance = in_tuple->distance & 0x7f;
in_tuple++;
}*/
free(packet->data);
packet->data = data;
packet->size = size;
packet->type = LAP_DDP_SHORT;
}
}
/* Learn our network number from RTMP packets. */
/* "Inside AppleTalk", section 4-8, describes this approach for non-extended networks.
Technically, we probably should be doing the more complicated extended network approach (also on 4-8),
but the easy approach using RTMP seems adequate for now. */
static void glean_net_from_rtmp(struct packet_t* packet)
{
if (packet && (packet->type == LAP_DDP_LONG) && packet->data)
{
struct DDP_LONG* header_long = (struct DDP_LONG*)packet->data;
if (header_long->type != DDP_TYPE_RTMP || header_long->dest_socket != DDP_SOCKET_RTMP)
return;
struct rtmp_extended_data_t* in = (struct rtmp_extended_data_t*)(packet->data + sizeof(struct DDP_LONG));
atbridge_set_net(ntohs(in->net));
}
}
static void send_rtmp_request()
{
struct packet_t* packet = (struct packet_t*)malloc(sizeof(struct packet_t));
packet->type = LAP_DDP_LONG;
packet->dest.network = atbridge_get_net();
packet->dest.node = 255;
packet->source.network = atbridge_get_net();
packet->source.node = atbridge_get_node();
packet->next = 0;
packet->size = sizeof(struct DDP_LONG) + sizeof(struct rtmp_request_t);
packet->data = (byte*)malloc(packet->size);
struct DDP_LONG* header = (struct DDP_LONG*)packet->data;
header->type = DDP_TYPE_RTMP_REQUEST;
header->source_net = htons(packet->source.network);
header->source_node = packet->source.node;
header->source_socket = DDP_SOCKET_RTMP;
header->dest_net = htons(packet->dest.network);
header->dest_node = packet->dest.node;
header->dest_socket = DDP_SOCKET_RTMP;
header->length[0] = (packet->size >> 8) & 0x03;
header->length[1] = packet->size & 0xff;
struct rtmp_request_t* request = (struct rtmp_request_t*)(packet->data + sizeof(struct DDP_LONG));
request->function = RTMP_FUNCTION_REQUEST;
calculate_checksum(packet);
elap_enqueue_out(packet);
sent_rtmp_request = true;
}
void atbridge_process()
{
elap_process();
//llap_process();
struct packet_t* packet = elap_dequeue_in();
if (packet)
{
glean_net_from_rtmp(packet);
convert_rtmp_to_nonextended(packet);
// The GS should understand long-form DDP, but converting to short-form ought to slightly improve performance (fewer bytes for the GS to process).
convert_ddp_packet_to_short(packet);
llap_enqueue_out(packet);
}
packet = llap_dequeue_in();
if (packet)
{
// ELAP does not support short-form DDP, so convert such packets to long-form.
convert_ddp_packet_to_long(packet);
elap_enqueue_out(packet);
}
}

View File

@ -0,0 +1,54 @@
/*
* This file is a consolidation of functions required for tfe
* emulation taken from the following files
*
* lib.h - Library functions.
* util.h - Miscellaneous utility functions.
* crc32.h
*
* Written by
* Andreas Boose <viceteam@t-online.de>
* Ettore Perazzoli <ettore@comm2000.it>
* Manfred Spraul <manfreds@colorfullife.com>
* Andreas Matthies <andreas.matthies@gmx.net>
* Tibor Biczo <crown@mail.matav.hu>
* Spiro Trikaliotis <Spiro.Trikaliotis@gmx.de>*
*
* This file is part of VICE, the Versatile Commodore Emulator.
* See README for copyright notice.
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA.
*
*/
#ifndef _TFESUPP_H
#define _TFESUPP_H
extern FILE* g_fh; // Filehandle for log file
extern void *lib_malloc(size_t size);
extern void *lib_realloc(void *p, size_t size);
extern void lib_free(void *ptr);
extern char *lib_stralloc(const char *str);
extern int util_string_set(char **str, const char *new_value);
extern unsigned long crc32_buf(const char *buffer, unsigned int len);
#define log_message(level,...) fprintf(stderr,__VA_ARGS__)
#endif

View File

@ -0,0 +1,835 @@
/*
* This file is part of VICE, the Versatile Commodore Emulator.
* See README for copyright notice.
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA.
*
*/
#include <stdio.h>
#include <string.h>
#include "dirport.h"
DIR *opendir (char *path)
{
APIRET ulrc;
ULONG cnt = 1;
DIR *dir;
char *name;
if (!(dir = (DIR*)calloc(1, sizeof(DIR)))) {
return NULL;
}
if (name = (char*)calloc(1, strlen(path) + 3)) {
strcat(strcpy(name, path),path[strlen(path) - 1] == '\\' ? "*" : "\\*");
dir->handle = HDIR_CREATE;
ulrc = DosFindFirst(name, &(dir->handle), _A_ANY, &(dir->buffer), sizeof(struct _FILEFINDBUF3), &cnt, FIL_STANDARD);
free(name);
}
if (!name || ulrc) {
DosFindClose (dir->handle);
free(dir);
dir = NULL;
}
return dir;
}
struct dirent *readdir (DIR *dir)
{
ULONG cnt = 1;
return DosFindNext (dir->handle, &(dir->buffer), sizeof(struct _FILEFINDBUF), &cnt) ? NULL : &(dir->buffer);
}
int closedir (DIR *dir)
{
APIRET ulrc = DosFindClose (dir->handle);
free(dir);
return (int)ulrc;
}
#ifndef HAVE_SNPRINTF
/*
* What follows is a portable snprintf routine, written by Mark Martinec.
* See: http://www.ijs.si/software/snprintf/
snprintf.c
- a portable implementation of snprintf,
including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf
snprintf is a routine to convert numeric and string arguments to
formatted strings. It is similar to sprintf(3) provided in a system's
C library, yet it requires an additional argument - the buffer size -
and it guarantees never to store anything beyond the given buffer,
regardless of the format or arguments to be formatted. Some newer
operating systems do provide snprintf in their C library, but many do
not or do provide an inadequate (slow or idiosyncratic) version, which
calls for a portable implementation of this routine.
Author
Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
Copyright © 1999, Mark Martinec
*/
#define PORTABLE_SNPRINTF_VERSION_MAJOR 2
#define PORTABLE_SNPRINTF_VERSION_MINOR 2
#if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF)
# if defined(NEED_SNPRINTF_ONLY)
# undef NEED_SNPRINTF_ONLY
# endif
# if !defined(PREFER_PORTABLE_SNPRINTF)
# define PREFER_PORTABLE_SNPRINTF
# endif
#endif
#if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE)
#define SOLARIS_COMPATIBLE
#endif
#if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
#define HPUX_COMPATIBLE
#endif
#if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE)
#define DIGITAL_UNIX_COMPATIBLE
#endif
#if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE)
#define PERL_COMPATIBLE
#endif
#if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE)
#define LINUX_COMPATIBLE
#endif
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <errno.h>
#ifdef isdigit
#undef isdigit
#endif
#define isdigit(c) ((c) >= '0' && (c) <= '9')
/* For copying strings longer or equal to 'breakeven_point'
* it is more efficient to call memcpy() than to do it inline.
* The value depends mostly on the processor architecture,
* but also on the compiler and its optimization capabilities.
* The value is not critical, some small value greater than zero
* will be just fine if you don't care to squeeze every drop
* of performance out of the code.
*
* Small values favor memcpy, large values favor inline code.
*/
#if defined(__alpha__) || defined(__alpha)
# define breakeven_point 2 /* AXP (DEC Alpha) - gcc or cc or egcs */
#endif
#if defined(__i386__) || defined(__i386)
# define breakeven_point 12 /* Intel Pentium/Linux - gcc 2.96 */
#endif
#if defined(__hppa)
# define breakeven_point 10 /* HP-PA - gcc */
#endif
#if defined(__sparc__) || defined(__sparc)
# define breakeven_point 33 /* Sun Sparc 5 - gcc 2.8.1 */
#endif
/* some other values of possible interest: */
/* #define breakeven_point 8 */ /* VAX 4000 - vaxc */
/* #define breakeven_point 19 */ /* VAX 4000 - gcc 2.7.0 */
#ifndef breakeven_point
# define breakeven_point 6 /* some reasonable one-size-fits-all value */
#endif
#define fast_memcpy(d,s,n) \
{ register size_t nn = (size_t)(n); \
if (nn >= breakeven_point) memcpy((d), (s), nn); \
else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
register char *dd; register const char *ss; \
for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
#define fast_memset(d,c,n) \
{ register size_t nn = (size_t)(n); \
if (nn >= breakeven_point) memset((d), (int)(c), nn); \
else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
register char *dd; register const int cc=(int)(c); \
for (dd=(d); nn>0; nn--) *dd++ = cc; } }
/* prototypes */
#if defined(NEED_ASPRINTF)
int asprintf (char **ptr, const char *fmt, /*args*/ ...);
#endif
#if defined(NEED_VASPRINTF)
int vasprintf (char **ptr, const char *fmt, va_list ap);
#endif
#if defined(NEED_ASNPRINTF)
int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...);
#endif
#if defined(NEED_VASNPRINTF)
int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap);
#endif
#if defined(HAVE_SNPRINTF)
/* declare our portable snprintf routine under name portable_snprintf */
/* declare our portable vsnprintf routine under name portable_vsnprintf */
#else
/* declare our portable routines under names snprintf and vsnprintf */
#define portable_snprintf snprintf
#if !defined(NEED_SNPRINTF_ONLY)
#define portable_vsnprintf vsnprintf
#endif
#endif
#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...);
#if !defined(NEED_SNPRINTF_ONLY)
int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap);
#endif
#endif
/* declarations */
static char credits[] = "\n\
@(#)snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>\n\
@(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\
@(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n";
#if defined(NEED_ASPRINTF)
int asprintf(char **ptr, const char *fmt, /*args*/ ...) {
va_list ap;
size_t str_m;
int str_l;
*ptr = NULL;
va_start(ap, fmt); /* measure the required size */
str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap);
va_end(ap);
assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */
*ptr = (char *) malloc(str_m = (size_t)str_l + 1);
if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
else {
int str_l2;
va_start(ap, fmt);
str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
va_end(ap);
assert(str_l2 == str_l);
}
return str_l;
}
#endif
#if defined(NEED_VASPRINTF)
int vasprintf(char **ptr, const char *fmt, va_list ap) {
size_t str_m;
int str_l;
*ptr = NULL;
{ va_list ap2;
va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */
str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/
va_end(ap2);
}
assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */
*ptr = (char *) malloc(str_m = (size_t)str_l + 1);
if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
else {
int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
assert(str_l2 == str_l);
}
return str_l;
}
#endif
#if defined(NEED_ASNPRINTF)
int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...) {
va_list ap;
int str_l;
*ptr = NULL;
va_start(ap, fmt); /* measure the required size */
str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap);
va_end(ap);
assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */
if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */
/* if str_m is 0, no buffer is allocated, just set *ptr to NULL */
if (str_m == 0) { /* not interested in resulting string, just return size */
} else {
*ptr = (char *) malloc(str_m);
if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
else {
int str_l2;
va_start(ap, fmt);
str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
va_end(ap);
assert(str_l2 == str_l);
}
}
return str_l;
}
#endif
#if defined(NEED_VASNPRINTF)
int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) {
int str_l;
*ptr = NULL;
{ va_list ap2;
va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */
str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/
va_end(ap2);
}
assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */
if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */
/* if str_m is 0, no buffer is allocated, just set *ptr to NULL */
if (str_m == 0) { /* not interested in resulting string, just return size */
} else {
*ptr = (char *) malloc(str_m);
if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
else {
int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
assert(str_l2 == str_l);
}
}
return str_l;
}
#endif
/*
* If the system does have snprintf and the portable routine is not
* specifically required, this module produces no code for snprintf/vsnprintf.
*/
#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
#if !defined(NEED_SNPRINTF_ONLY)
int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) {
va_list ap;
int str_l;
va_start(ap, fmt);
str_l = portable_vsnprintf(str, str_m, fmt, ap);
va_end(ap);
return str_l;
}
#endif
#if defined(NEED_SNPRINTF_ONLY)
int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) {
#else
int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
#endif
#if defined(NEED_SNPRINTF_ONLY)
va_list ap;
#endif
size_t str_l = 0;
const char *p = fmt;
/* In contrast with POSIX, the ISO C99 now says
* that str can be NULL and str_m can be 0.
* This is more useful than the old: if (str_m < 1) return -1; */
#if defined(NEED_SNPRINTF_ONLY)
va_start(ap, fmt);
#endif
if (!p) p = "";
while (*p) {
if (*p != '%') {
/* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */
/* but the following code achieves better performance for cases
* where format string is long and contains few conversions */
const char *q = strchr(p+1,'%');
size_t n = !q ? strlen(p) : (q-p);
if (str_l < str_m) {
size_t avail = str_m-str_l;
fast_memcpy(str+str_l, p, (n>avail?avail:n));
}
p += n; str_l += n;
} else {
const char *starting_p;
size_t min_field_width = 0, precision = 0;
int zero_padding = 0, precision_specified = 0, justify_left = 0;
int alternate_form = 0, force_sign = 0;
int space_for_positive = 1; /* If both the ' ' and '+' flags appear,
the ' ' flag should be ignored. */
char length_modifier = '\0'; /* allowed values: \0, h, l, L */
char tmp[32];/* temporary buffer for simple numeric->string conversion */
const char *str_arg; /* string address in case of string argument */
size_t str_arg_l; /* natural field width of arg without padding
and sign */
unsigned char uchar_arg;
/* unsigned char argument value - only defined for c conversion.
N.B. standard explicitly states the char argument for
the c conversion is unsigned */
size_t number_of_zeros_to_pad = 0;
/* number of zeros to be inserted for numeric conversions
as required by the precision or minimal field width */
size_t zero_padding_insertion_ind = 0;
/* index into tmp where zero padding is to be inserted */
char fmt_spec = '\0';
/* current conversion specifier character */
str_arg = credits;/* just to make compiler happy (defined but not used)*/
str_arg = NULL;
starting_p = p; p++; /* skip '%' */
/* parse flags */
while (*p == '0' || *p == '-' || *p == '+' ||
*p == ' ' || *p == '#' || *p == '\'') {
switch (*p) {
case '0': zero_padding = 1; break;
case '-': justify_left = 1; break;
case '+': force_sign = 1; space_for_positive = 0; break;
case ' ': force_sign = 1;
/* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */
#ifdef PERL_COMPATIBLE
/* ... but in Perl the last of ' ' and '+' applies */
space_for_positive = 1;
#endif
break;
case '#': alternate_form = 1; break;
case '\'': break;
}
p++;
}
/* If the '0' and '-' flags both appear, the '0' flag should be ignored. */
/* parse field width */
if (*p == '*') {
int j;
p++; j = va_arg(ap, int);
if (j >= 0) min_field_width = j;
else { min_field_width = -j; justify_left = 1; }
} else if (isdigit((int)(*p))) {
/* size_t could be wider than unsigned int;
make sure we treat argument like common implementations do */
unsigned int uj = *p++ - '0';
while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
min_field_width = uj;
}
/* parse precision */
if (*p == '.') {
p++; precision_specified = 1;
if (*p == '*') {
int j = va_arg(ap, int);
p++;
if (j >= 0) precision = j;
else {
precision_specified = 0; precision = 0;
/* NOTE:
* Solaris 2.6 man page claims that in this case the precision
* should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page
* claim that this case should be treated as unspecified precision,
* which is what we do here.
*/
}
} else if (isdigit((int)(*p))) {
/* size_t could be wider than unsigned int;
make sure we treat argument like common implementations do */
unsigned int uj = *p++ - '0';
while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
precision = uj;
}
}
/* parse 'h', 'l' and 'll' length modifiers */
if (*p == 'h' || *p == 'l') {
length_modifier = *p; p++;
if (length_modifier == 'l' && *p == 'l') { /* double l = long long */
#ifdef SNPRINTF_LONGLONG_SUPPORT
length_modifier = '2'; /* double l encoded as '2' */
#else
length_modifier = 'l'; /* treat it as a single 'l' */
#endif
p++;
}
}
fmt_spec = *p;
/* common synonyms: */
switch (fmt_spec) {
case 'i': fmt_spec = 'd'; break;
case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
default: break;
}
/* get parameter value, do initial processing */
switch (fmt_spec) {
case '%': /* % behaves similar to 's' regarding flags and field widths */
case 'c': /* c behaves similar to 's' regarding flags and field widths */
case 's':
length_modifier = '\0'; /* wint_t and wchar_t not supported */
/* the result of zero padding flag with non-numeric conversion specifier*/
/* is undefined. Solaris and HPUX 10 does zero padding in this case, */
/* Digital Unix and Linux does not. */
#if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
zero_padding = 0; /* turn zero padding off for string conversions */
#endif
str_arg_l = 1;
switch (fmt_spec) {
case '%':
str_arg = p; break;
case 'c': {
int j = va_arg(ap, int);
uchar_arg = (unsigned char) j; /* standard demands unsigned char */
str_arg = (const char *) &uchar_arg;
break;
}
case 's':
str_arg = va_arg(ap, const char *);
if (!str_arg) str_arg_l = 0;
/* make sure not to address string beyond the specified precision !!! */
else if (!precision_specified) str_arg_l = strlen(str_arg);
/* truncate string if necessary as requested by precision */
else if (precision == 0) str_arg_l = 0;
else {
/* memchr on HP does not like n > 2^31 !!! */
const char *q = memchr(str_arg, '\0',
precision <= 0x7fffffff ? precision : 0x7fffffff);
str_arg_l = !q ? precision : (q-str_arg);
}
break;
default: break;
}
break;
case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': {
/* NOTE: the u, o, x, X and p conversion specifiers imply
the value is unsigned; d implies a signed value */
int arg_sign = 0;
/* 0 if numeric argument is zero (or if pointer is NULL for 'p'),
+1 if greater than zero (or nonzero for unsigned arguments),
-1 if negative (unsigned argument is never negative) */
int int_arg = 0; unsigned int uint_arg = 0;
/* only defined for length modifier h, or for no length modifiers */
long int long_arg = 0; unsigned long int ulong_arg = 0;
/* only defined for length modifier l */
void *ptr_arg = NULL;
/* pointer argument value -only defined for p conversion */
#ifdef SNPRINTF_LONGLONG_SUPPORT
long long int long_long_arg = 0;
unsigned long long int ulong_long_arg = 0;
/* only defined for length modifier ll */
#endif
if (fmt_spec == 'p') {
/* HPUX 10: An l, h, ll or L before any other conversion character
* (other than d, i, u, o, x, or X) is ignored.
* Digital Unix:
* not specified, but seems to behave as HPUX does.
* Solaris: If an h, l, or L appears before any other conversion
* specifier (other than d, i, u, o, x, or X), the behavior
* is undefined. (Actually %hp converts only 16-bits of address
* and %llp treats address as 64-bit data which is incompatible
* with (void *) argument on a 32-bit system).
*/
#ifdef SOLARIS_COMPATIBLE
# ifdef SOLARIS_BUG_COMPATIBLE
/* keep length modifiers even if it represents 'll' */
# else
if (length_modifier == '2') length_modifier = '\0';
# endif
#else
length_modifier = '\0';
#endif
ptr_arg = va_arg(ap, void *);
if (ptr_arg != NULL) arg_sign = 1;
} else if (fmt_spec == 'd') { /* signed */
switch (length_modifier) {
case '\0':
case 'h':
/* It is non-portable to specify a second argument of char or short
* to va_arg, because arguments seen by the called function
* are not char or short. C converts char and short arguments
* to int before passing them to a function.
*/
int_arg = va_arg(ap, int);
if (int_arg > 0) arg_sign = 1;
else if (int_arg < 0) arg_sign = -1;
break;
case 'l':
long_arg = va_arg(ap, long int);
if (long_arg > 0) arg_sign = 1;
else if (long_arg < 0) arg_sign = -1;
break;
#ifdef SNPRINTF_LONGLONG_SUPPORT
case '2':
long_long_arg = va_arg(ap, long long int);
if (long_long_arg > 0) arg_sign = 1;
else if (long_long_arg < 0) arg_sign = -1;
break;
#endif
}
} else { /* unsigned */
switch (length_modifier) {
case '\0':
case 'h':
uint_arg = va_arg(ap, unsigned int);
if (uint_arg) arg_sign = 1;
break;
case 'l':
ulong_arg = va_arg(ap, unsigned long int);
if (ulong_arg) arg_sign = 1;
break;
#ifdef SNPRINTF_LONGLONG_SUPPORT
case '2':
ulong_long_arg = va_arg(ap, unsigned long long int);
if (ulong_long_arg) arg_sign = 1;
break;
#endif
}
}
str_arg = tmp; str_arg_l = 0;
/* NOTE:
* For d, i, u, o, x, and X conversions, if precision is specified,
* the '0' flag should be ignored. This is so with Solaris 2.6,
* Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
*/
#ifndef PERL_COMPATIBLE
if (precision_specified) zero_padding = 0;
#endif
if (fmt_spec == 'd') {
if (force_sign && arg_sign >= 0)
tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
/* leave negative numbers for sprintf to handle,
to avoid handling tricky cases like (short int)(-32768) */
#ifdef LINUX_COMPATIBLE
} else if (fmt_spec == 'p' && force_sign && arg_sign > 0) {
tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
#endif
} else if (alternate_form) {
if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') )
{ tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; }
/* alternate form should have no effect for p conversion, but ... */
#ifdef HPUX_COMPATIBLE
else if (fmt_spec == 'p'
/* HPUX 10: for an alternate form of p conversion,
* a nonzero result is prefixed by 0x. */
#ifndef HPUX_BUG_COMPATIBLE
/* Actually it uses 0x prefix even for a zero value. */
&& arg_sign != 0
#endif
) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; }
#endif
}
zero_padding_insertion_ind = str_arg_l;
if (!precision_specified) precision = 1; /* default precision is 1 */
if (precision == 0 && arg_sign == 0
#if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE)
&& fmt_spec != 'p'
/* HPUX 10 man page claims: With conversion character p the result of
* converting a zero value with a precision of zero is a null string.
* Actually HP returns all zeroes, and Linux returns "(nil)". */
#endif
) {
/* converted to null string */
/* When zero value is formatted with an explicit precision 0,
the resulting formatted string is empty (d, i, u, o, x, X, p). */
} else {
char f[5]; int f_l = 0;
f[f_l++] = '%'; /* construct a simple format string for sprintf */
if (!length_modifier) { }
else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; }
else f[f_l++] = length_modifier;
f[f_l++] = fmt_spec; f[f_l++] = '\0';
if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
else if (fmt_spec == 'd') { /* signed */
switch (length_modifier) {
case '\0':
case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break;
case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break;
#ifdef SNPRINTF_LONGLONG_SUPPORT
case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break;
#endif
}
} else { /* unsigned */
switch (length_modifier) {
case '\0':
case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break;
case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break;
#ifdef SNPRINTF_LONGLONG_SUPPORT
case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break;
#endif
}
}
/* include the optional minus sign and possible "0x"
in the region before the zero padding insertion point */
if (zero_padding_insertion_ind < str_arg_l &&
tmp[zero_padding_insertion_ind] == '-') {
zero_padding_insertion_ind++;
}
if (zero_padding_insertion_ind+1 < str_arg_l &&
tmp[zero_padding_insertion_ind] == '0' &&
(tmp[zero_padding_insertion_ind+1] == 'x' ||
tmp[zero_padding_insertion_ind+1] == 'X') ) {
zero_padding_insertion_ind += 2;
}
}
{ size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
if (alternate_form && fmt_spec == 'o'
#ifdef HPUX_COMPATIBLE /* ("%#.o",0) -> "" */
&& (str_arg_l > 0)
#endif
#ifdef DIGITAL_UNIX_BUG_COMPATIBLE /* ("%#o",0) -> "00" */
#else
/* unless zero is already the first character */
&& !(zero_padding_insertion_ind < str_arg_l
&& tmp[zero_padding_insertion_ind] == '0')
#endif
) { /* assure leading zero for alternate-form octal numbers */
if (!precision_specified || precision < num_of_digits+1) {
/* precision is increased to force the first character to be zero,
except if a zero value is formatted with an explicit precision
of zero */
precision = num_of_digits+1; precision_specified = 1;
}
}
/* zero padding to specified precision? */
if (num_of_digits < precision)
number_of_zeros_to_pad = precision - num_of_digits;
}
/* zero padding to specified minimal field width? */
if (!justify_left && zero_padding) {
int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
if (n > 0) number_of_zeros_to_pad += n;
}
break;
}
default: /* unrecognized conversion specifier, keep format string as-is*/
zero_padding = 0; /* turn zero padding off for non-numeric convers. */
#ifndef DIGITAL_UNIX_COMPATIBLE
justify_left = 1; min_field_width = 0; /* reset flags */
#endif
#if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE)
/* keep the entire format string unchanged */
str_arg = starting_p; str_arg_l = p - starting_p;
/* well, not exactly so for Linux, which does something inbetween,
* and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */
#else
/* discard the unrecognized conversion, just keep *
* the unrecognized conversion character */
str_arg = p; str_arg_l = 0;
#endif
if (*p) str_arg_l++; /* include invalid conversion specifier unchanged
if not at end-of-string */
break;
}
if (*p) p++; /* step over the just processed conversion specifier */
/* insert padding to the left as requested by min_field_width;
this does not include the zero padding in case of numerical conversions*/
if (!justify_left) { /* left padding with blank or zero */
int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
if (n > 0) {
if (str_l < str_m) {
size_t avail = str_m-str_l;
fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n));
}
str_l += n;
}
}
/* zero padding as requested by the precision or by the minimal field width
* for numeric conversions required? */
if (number_of_zeros_to_pad <= 0) {
/* will not copy first part of numeric right now, *
* force it to be copied later in its entirety */
zero_padding_insertion_ind = 0;
} else {
/* insert first part of numerics (sign or '0x') before zero padding */
int n = zero_padding_insertion_ind;
if (n > 0) {
if (str_l < str_m) {
size_t avail = str_m-str_l;
fast_memcpy(str+str_l, str_arg, (n>avail?avail:n));
}
str_l += n;
}
/* insert zero padding as requested by the precision or min field width */
n = number_of_zeros_to_pad;
if (n > 0) {
if (str_l < str_m) {
size_t avail = str_m-str_l;
fast_memset(str+str_l, '0', (n>avail?avail:n));
}
str_l += n;
}
}
/* insert formatted string
* (or as-is conversion specifier for unknown conversions) */
{ int n = str_arg_l - zero_padding_insertion_ind;
if (n > 0) {
if (str_l < str_m) {
size_t avail = str_m-str_l;
fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind,
(n>avail?avail:n));
}
str_l += n;
}
}
/* insert right padding */
if (justify_left) { /* right blank padding to the field width */
int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
if (n > 0) {
if (str_l < str_m) {
size_t avail = str_m-str_l;
fast_memset(str+str_l, ' ', (n>avail?avail:n));
}
str_l += n;
}
}
}
}
#if defined(NEED_SNPRINTF_ONLY)
va_end(ap);
#endif
if (str_m > 0) { /* make sure the string is null-terminated
even at the expense of overwriting the last character
(shouldn't happen, but just in case) */
str[str_l <= str_m-1 ? str_l : str_m-1] = '\0';
}
/* Return the number of characters formatted (excluding trailing null
* character), that is, the number of characters that would have been
* written to the buffer if it were large enough.
*
* The value of str_l should be returned, but str_l is of unsigned type
* size_t, and snprintf is int, possibly leading to an undetected
* integer overflow, resulting in a negative return value, which is illegal.
* Both XSH5 and ISO C99 (at least the draft) are silent on this issue.
* Should errno be set to EOVERFLOW and EOF returned in this case???
*/
return (int) str_l;
}
#endif
#endif /* ndef HAVE_SNPRINTF */
/*
Local Variables:
tab-width: 3
end:
*/

View File

@ -0,0 +1,440 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 - 2012 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "defc.h"
#include "sound.h"
#ifdef HPUX
# include <sys/audio.h>
#endif
#if defined(__linux__) || defined(OSS)
# include <sys/soundcard.h>
#endif
#ifndef WIN_SOUND /* Workaround - gcc in cygwin wasn't defining _WIN32 */
# include <sys/socket.h>
# include <netinet/in.h>
#endif
#ifndef UNDER_CE
#include <errno.h>
#endif
extern int Verbose;
extern int g_audio_rate;
int g_preferred_rate = 48000;
int g_audio_socket = -1;
int g_bytes_written = 0;
#define ZERO_BUF_SIZE 2048
word32 g_snd_zero_buf[ZERO_BUF_SIZE];
#define ZERO_PAUSE_SAFETY_SAMPS (g_audio_rate >> 5)
#define ZERO_PAUSE_NUM_SAMPS (4*g_audio_rate)
int g_zeroes_buffered = 0;
int g_zeroes_seen = 0;
int g_sound_paused = 0;
int g_childsnd_vbl = 0;
int g_childsnd_pos = 0;
word32 *g_childsnd_shm_addr = 0;
void child_sound_init_linux();
void child_sound_init_hpdev();
void child_sound_initWIN_SOUND();
void child_sound_init_mac();
void
reliable_buf_write(word32 *shm_addr, int pos, int size)
{
byte *ptr;
int ret;
if(size < 1 || pos < 0 || pos > SOUND_SHM_SAMP_SIZE ||
size > SOUND_SHM_SAMP_SIZE ||
(pos + size) > SOUND_SHM_SAMP_SIZE) {
printf("reliable_buf_write: pos: %04x, size: %04x\n",
pos, size);
exit(1);
}
ptr = (byte *)&(shm_addr[pos]);
size = size * 4;
while(size > 0) {
#ifdef WIN_SOUND
ret = win32_send_audio(ptr, size);
#else
# ifdef MAC
ret = mac_send_audio(ptr, size);
# else
ret = write(g_audio_socket, ptr, size);
# endif
#endif
if(ret < 0) {
printf("audio write, errno: %d\n", errno);
exit(1);
}
size = size - ret;
ptr += ret;
g_bytes_written += ret;
}
}
void
reliable_zero_write(int amt)
{
int len;
while(amt > 0) {
len = MIN(amt, ZERO_BUF_SIZE);
reliable_buf_write(g_snd_zero_buf, 0, len);
amt -= len;
}
}
void
child_sound_loop(int read_fd, int write_fd, word32 *shm_addr)
{
#ifdef HPUX
long status_return;
#endif
word32 tmp;
int ret;
doc_printf("Child pipe fd: %d\n", read_fd);
g_audio_rate = g_preferred_rate;
g_zeroes_buffered = 0;
g_zeroes_seen = 0;
g_sound_paused = 0;
g_childsnd_pos = 0;
g_childsnd_vbl = 0;
g_childsnd_shm_addr = shm_addr;
#ifdef HPUX
child_sound_init_hpdev();
#endif
#if defined(__linux__) || defined(OSS)
child_sound_init_linux();
#endif
#ifdef WIN_SOUND
child_sound_init_win32();
return;
#endif
#ifdef MAC
child_sound_init_mac();
return;
#endif
tmp = g_audio_rate;
ret = write(write_fd, &tmp, 4);
if(ret != 4) {
printf("Unable to send back audio rate to parent\n");
printf("ret: %d fd: %d, errno: %d\n", ret, write_fd, errno);
exit(1);
}
printf("Wrote to fd %d the audio rate\n", write_fd);
close(write_fd);
while(1) {
errno = 0;
ret = read(read_fd, (char*)&tmp, 4);
if(ret <= 0) {
printf("child dying from ret: %d, errno: %d\n",
ret, errno);
break;
}
child_sound_playit(tmp);
}
#ifdef HPUX
ioctl(g_audio_socket, AUDIO_DRAIN, 0);
#endif
close(g_audio_socket);
exit(0);
}
void
child_sound_playit(word32 tmp)
{
int size;
size = tmp & 0xffffff;
//printf("child_sound_playit: %08x\n", tmp);
if((tmp >> 24) == 0xa2) {
/* play sound here */
#if 0
g_childsnd_pos += g_zeroes_buffered;
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
}
#endif
if(g_zeroes_buffered) {
reliable_zero_write(g_zeroes_buffered);
}
g_zeroes_buffered = 0;
g_zeroes_seen = 0;
if((size + g_childsnd_pos) > SOUND_SHM_SAMP_SIZE) {
reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos,
SOUND_SHM_SAMP_SIZE - g_childsnd_pos);
size = (g_childsnd_pos + size) - SOUND_SHM_SAMP_SIZE;
g_childsnd_pos = 0;
}
reliable_buf_write(g_childsnd_shm_addr, g_childsnd_pos, size);
if(g_sound_paused) {
printf("Unpausing sound, zb: %d\n", g_zeroes_buffered);
g_sound_paused = 0;
}
} else if((tmp >> 24) == 0xa1) {
if(g_sound_paused) {
if(g_zeroes_buffered < ZERO_PAUSE_SAFETY_SAMPS) {
g_zeroes_buffered += size;
}
} else {
/* not paused, send it through */
g_zeroes_seen += size;
reliable_zero_write(size);
if(g_zeroes_seen >= ZERO_PAUSE_NUM_SAMPS) {
printf("Pausing sound\n");
g_sound_paused = 1;
}
}
} else {
printf("tmp received bad: %08x\n", tmp);
exit(3);
}
g_childsnd_pos += size;
while(g_childsnd_pos >= SOUND_SHM_SAMP_SIZE) {
g_childsnd_pos -= SOUND_SHM_SAMP_SIZE;
}
g_childsnd_vbl++;
if(g_childsnd_vbl >= 60) {
g_childsnd_vbl = 0;
#if 0
printf("sound bytes written: %06x\n", g_bytes_written);
printf("Sample samples[0]: %08x %08x %08x %08x\n",
g_childsnd_shm_addr[0], g_childsnd_shm_addr[1],
g_childsnd_shm_addr[2], g_childsnd_shm_addr[3]);
printf("Sample samples[100]: %08x %08x %08x %08x\n",
g_childsnd_shm_addr[100], g_childsnd_shm_addr[101],
g_childsnd_shm_addr[102], g_childsnd_shm_addr[103]);
#endif
g_bytes_written = 0;
}
}
#ifdef HPUX
void
child_sound_init_hpdev()
{
struct audio_describe audio_descr;
int output_channel;
char *str;
int speaker;
int ret;
int i;
g_audio_socket = open("/dev/audio", O_WRONLY, 0);
if(g_audio_socket < 0) {
printf("open /dev/audio failed, ret: %d, errno:%d\n",
g_audio_socket, errno);
exit(1);
}
ret = ioctl(g_audio_socket, AUDIO_DESCRIBE, &audio_descr);
if(ret < 0) {
printf("ioctl AUDIO_DESCRIBE failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
for(i = 0; i < audio_descr.nrates; i++) {
printf("Audio rate[%d] = %d\n", i,
audio_descr.sample_rate[i]);
}
ret = ioctl(g_audio_socket, AUDIO_SET_DATA_FORMAT,
AUDIO_FORMAT_LINEAR16BIT);
if(ret < 0) {
printf("ioctl AUDIO_SET_DATA_FORMAT failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
ret = ioctl(g_audio_socket, AUDIO_SET_CHANNELS, NUM_CHANNELS);
if(ret < 0) {
printf("ioctl AUDIO_SET_CHANNELS failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
ret = ioctl(g_audio_socket, AUDIO_SET_TXBUFSIZE, 16*1024);
if(ret < 0) {
printf("ioctl AUDIO_SET_TXBUFSIZE failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
ret = ioctl(g_audio_socket, AUDIO_SET_SAMPLE_RATE, g_audio_rate);
if(ret < 0) {
printf("ioctl AUDIO_SET_SAMPLE_RATE failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
ret = ioctl(g_audio_socket, AUDIO_GET_OUTPUT, &output_channel);
if(ret < 0) {
printf("ioctl AUDIO_GET_OUTPUT failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
speaker = 1;
str = getenv("SPEAKER");
if(str) {
if(str[0] != 'i' && str[0] != 'I') {
speaker = 0;
}
}
if(speaker) {
printf("Sending sound to internal speaker\n");
output_channel |= AUDIO_OUT_SPEAKER;
} else {
printf("Sending sound to external jack\n");
output_channel &= (~AUDIO_OUT_SPEAKER);
output_channel |= AUDIO_OUT_HEADPHONE;
}
ret = ioctl(g_audio_socket, AUDIO_SET_OUTPUT, output_channel);
if(ret < 0) {
printf("ioctl AUDIO_SET_OUTPUT failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
}
#endif /* HPUX */
#if defined(__linux__) || defined(OSS)
void
child_sound_init_linux()
{
int stereo;
int sample_size;
int rate;
int fragment;
int fmt;
int ret;
g_audio_socket = open("/dev/dsp", O_WRONLY, 0);
if(g_audio_socket < 0) {
printf("open /dev/dsp failed, ret: %d, errno:%d\n",
g_audio_socket, errno);
exit(1);
}
fragment = 0x00200009;
#if 0
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFRAGMENT, &fragment);
if(ret < 0) {
printf("ioctl SETFRAGEMNT failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
#endif
sample_size = 16;
ret = ioctl(g_audio_socket, SNDCTL_DSP_SAMPLESIZE, &sample_size);
if(ret < 0) {
printf("ioctl SNDCTL_DSP_SAMPLESIZE failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
fmt = AFMT_S16_LE;
#else
fmt = AFMT_S16_BE;
#endif
ret = ioctl(g_audio_socket, SNDCTL_DSP_SETFMT, &fmt);
if(ret < 0) {
printf("ioctl SNDCTL_DSP_SETFMT failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
stereo = 1;
ret = ioctl(g_audio_socket, SNDCTL_DSP_STEREO, &stereo);
if(ret < 0) {
printf("ioctl SNDCTL_DSP_STEREO failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
rate = g_audio_rate;
ret = ioctl(g_audio_socket, SNDCTL_DSP_SPEED, &rate);
if(ret < 0) {
printf("ioctl SNDCTL_DSP_SPEED failed, ret:%d, errno:%d\n",
ret, errno);
exit(1);
}
if(ret > 0) {
rate = ret; /* rate is returned value */
}
if(rate < 8000) {
printf("Audio rate of %d which is < 8000!\n", rate);
exit(1);
}
g_audio_rate = rate;
printf("Sound initialized\n");
}
#endif

View File

@ -0,0 +1,396 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2013-2014 by Peter Neubauer
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/** This module implements the ELAP port of the bridge. **/
#include <stdbool.h>
#include "../defc.h"
#include "atbridge.h"
#include "elap.h"
#include "port.h"
#include "aarp.h"
#include "elap_defs.h"
#include "pcap_delay.h"
#ifdef __CYGWIN__
#include <Windows.h>
#include <NspAPI.h>
#endif
#ifdef WIN32
#include <winsock.h>
#include <IPHlpApi.h>
#endif
#ifdef __linux__
#include <netinet/in.h>
#include <netpacket/packet.h>
#endif
extern int g_ethernet_interface;
static pcap_t* pcap_session;
static struct packet_port_t elap_port;
static struct ether_addr_t HW_LOCAL;
/*static void dump_device_list(pcap_if_t* devices)
{
int i = 0;
for(pcap_if_t* device = devices; device; device = device->next)
{
printf("%d. %s", ++i, device->name);
if (device->description)
printf(" (%s)\n", device->description);
else
printf(" (No description available)\n");
}
}*/
static void elap_clone_host_mac(pcap_if_t* device)
{
if (!device)
return;
#ifdef WIN32
////
// Extract the device GUID, which Windows uses to identify the device.
char* name = device->name;
while (name && *name != '{')
name++;
size_t guidLen = strlen(name);
////
// Find and copy the device MAC address.
ULONG size = sizeof(IP_ADAPTER_ADDRESSES) * 15;
IP_ADAPTER_ADDRESSES* addresses = malloc(size);
ULONG result = GetAdaptersAddresses(AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &size);
if (result == ERROR_BUFFER_OVERFLOW)
{
// The addresses buffer is too small. Allocate a bigger buffer.
free(addresses);
addresses = malloc(size);
result = GetAdaptersAddresses(AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &size);
}
if (result == NO_ERROR)
{
// Search for the desired adapter address.
IP_ADAPTER_ADDRESSES* current = addresses;
while (current)
{
if (current->PhysicalAddressLength == ETHER_ADDR_LEN && memcmp(current->AdapterName, name, guidLen) == 0)
{
memcpy(&HW_LOCAL.mac, &current->PhysicalAddress, sizeof(HW_LOCAL.mac));
break;
}
current = current->Next;
}
}
else
{
halt_printf("ATBridge: Failed to find host MAC address (%d).", result);
}
free(addresses);
#else
struct pcap_addr* address;
for (address = device->addresses; address != 0; address = address->next)
if (address->addr->sa_family == AF_PACKET)
{
struct sockaddr_ll* ll = (struct sockaddr_ll*)address->addr;
memcpy(&HW_LOCAL.mac, ll->sll_addr, sizeof(HW_LOCAL.mac));
}
#endif
}
const struct ether_addr_t* elap_get_mac()
{
return &HW_LOCAL;
}
bool elap_init()
{
port_init(&elap_port);
memcpy(&HW_LOCAL, &HW_LOCAL_DEFAULT, sizeof(HW_LOCAL));
pcap_if_t* device;
pcap_if_t* alldevs;
int i = 0;
char errbuf[PCAP_ERRBUF_SIZE];
// Load the PCAP library.
if (!pcapdelay_load())
{
halt_printf("ATBridge: PCAP not available.\n");
return false;
}
// Retrieve the device list.
if(pcapdelay_findalldevs(&alldevs, errbuf) == -1)
{
atbridge_printf("ATBridge: Error enumerating PCAP devices: %s\n", errbuf);
return false;
}
//dump_device_list(alldevs);
// Jump to the selected adapter.
for (device = alldevs, i = 0; i < g_ethernet_interface; device = device->next, i++);
if (!device)
{
halt_printf("ATBridge: PCAP device not found. Check interface number in settings.\n");
return false;
}
// Clone the MAC address of the underlying interface. In certain configurations (e.g. Windows with an MS Loopback
// interface), the interface, even in promiscous mode, filters foreign MAC addresses.
elap_clone_host_mac(device);
// Open the adapter,
if ((pcap_session = pcapdelay_open_live(device->name, // name of the device
65536, // portion of the packet to capture.
// 65536 grants that the whole packet will be captured on all the MACs.
1, // promiscuous mode (nonzero means promiscuous)
1, // read timeout
errbuf // error buffer
)) == NULL)
{
halt_printf("ATBridge: Unable to open the adapter. Pcap does not support %s.\n", device->name);
pcapdelay_freealldevs(alldevs);
return false;
}
// The device must support Ethernet because the bridge "speaks" EtherTalk.
if (pcapdelay_datalink(pcap_session) == DLT_EN10MB)
{
pcapdelay_setnonblock(pcap_session, 1, errbuf);
atbridge_printf("ATBridge: AppleTalk bridging using network device '%s' with Ethernet address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X.\n",
device->description, HW_LOCAL.mac[0], HW_LOCAL.mac[1], HW_LOCAL.mac[2], HW_LOCAL.mac[3], HW_LOCAL.mac[4], HW_LOCAL.mac[5]);
pcapdelay_freealldevs(alldevs);
return true;
}
else
{
pcapdelay_close(pcap_session);
pcap_session = 0;
halt_printf("ATBridge: Selected network device %s must support Ethernet.\n", device->description);
pcapdelay_freealldevs(alldevs);
return false;
}
}
void elap_shutdown()
{
port_shutdown(&elap_port);
if (pcap_session)
{
pcapdelay_close(pcap_session);
pcap_session = 0;
}
pcapdelay_unload();
}
void elap_enqueue_out(struct packet_t* packet)
{
enqueue_packet(&elap_port.out, packet);
}
struct packet_t* elap_dequeue_in()
{
return dequeue(&elap_port.in);
}
void elap_send(const struct ether_addr_t* dest, const struct snap_discriminator_t* discriminator, size_t size, byte data[])
{
if (pcap_session && dest && discriminator)
{
// Allocate heap space for the frame.
const size_t frame_size = sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t) + size;
u_char* frame_data;
size_t pad = 0;
if (frame_size < ETHER_MIN_SIZE)
pad = ETHER_MIN_SIZE - frame_size;
frame_data = (u_char*)malloc(frame_size + pad);
// Build the 802.3 header.
struct ethernet_header_t* ether = (struct ethernet_header_t*)frame_data;
memcpy(ether->dest.mac, dest, sizeof(ether->dest.mac));
memcpy(ether->source.mac, HW_LOCAL.mac, sizeof(ether->source.mac));
ether->length = htons(frame_size - sizeof(struct ethernet_header_t));
// Build the 802.2 header.
struct snap_header_t* snap = (struct snap_header_t*)(frame_data + sizeof(struct ethernet_header_t));
snap->dsap = SNAP_DSAP;
snap->ssap = SNAP_SSAP;
snap->control = SNAP_CONTROL;
memcpy(&snap->discriminator, discriminator, sizeof(snap->discriminator));
// Add the data payload.
struct snap_header_t* payload = (struct snap_header_t*)(frame_data + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t));
memcpy(payload, data, size);
// Add padding to meet minimum Ethernet frame size.
if (pad > 0)
memset(frame_data + frame_size, 0, pad);
pcapdelay_sendpacket(pcap_session, frame_data, frame_size + pad);
}
}
static bool elap_send_one_queued()
{
// Attempt to send one packet out the host network interface.
struct packet_t* packet = queue_peek(&elap_port.out);
if (packet)
{
// Find the MAC address.
const struct ether_addr_t* dest;
if (packet->dest.node == at_broadcast_node)
dest = &HW_APPLETALK_BROADCAST;
else
dest = aarp_request_hardware(&packet->dest);
// Send it.
if (dest)
{
elap_send(dest, &SNAP_APPLETALK, packet->size, packet->data);
dequeue(&elap_port.out);
free(packet->data);
free(packet);
}
else
{
// AARP does not have the needed hardware address. Give AARP time to obtain the address and keep the current packet.
if (!aarp_retry())
{
// However, if AARP has reached the retry limit, the packet is undeliverable. Discard the packet and move on.
atbridge_printf("ATBridge: AARP failed to find MAC address for network %d node %d. Dropping packet.\n", packet->dest.network, packet->dest.node);
aarp_retry_reset();
dequeue(&elap_port.out);
free(packet->data);
free(packet);
}
}
return true;
}
else
return false;
}
static void elap_send_all_queued()
{
while (elap_send_one_queued());
}
static bool elap_receive_one()
{
if (!pcap_session)
return false;
struct pcap_pkthdr header;
const u_char* packet = pcapdelay_next(pcap_session, &header);
if (packet)
{
// Receive and process one packet from the host network interface.
////
// Check the Ethernet 802.3 header.
const struct ethernet_header_t* ether = (struct ethernet_header_t*)packet;
if (header.len > sizeof(struct ethernet_header_t) &&
ntohs(ether->length) <= ETHER_MAX_SIZE &&
ntohs(ether->length) > sizeof(struct snap_header_t) &&
(memcmp(&ether->source, &HW_LOCAL, sizeof(ether->source)) != 0) && /* Ignore packets sent from our node. */
(memcmp(&ether->dest, &HW_LOCAL, sizeof(ether->dest)) == 0 || /* Accept packets destined for our node ... */
memcmp(&ether->dest, &HW_APPLETALK_BROADCAST, sizeof(ether->dest)) == 0 /* ... or for broadcast. */)
)
{
// Check the 802.2 SNAP header.
const struct snap_header_t* snap = (struct snap_header_t*)(packet + sizeof(struct ethernet_header_t));
if (snap->dsap == SNAP_DSAP &&
snap->ssap == SNAP_SSAP &&
snap->control == SNAP_CONTROL)
{
if (memcmp(&snap->discriminator, &SNAP_APPLETALK, sizeof(snap->discriminator)) == 0)
{
// Handle an AppleTalk packet.
const size_t payload_size = ntohs(ether->length) - sizeof(struct snap_header_t);
const u_char* payload = packet + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t);
byte* copy = (byte*)malloc(payload_size);
memcpy(copy, payload, payload_size);
// ELAP does not support short-form DDP, so this must be a long-form DDP packet.
struct at_addr_t source, dest;
if (payload_size >= sizeof(struct DDP_LONG))
{
// Extract the protocol address from the header.
//
// ELAP really shouldn't be looking at the header for the next level of the protocol stack,
// but this is a convenient place to glean addresses for the AMT, a process that needs both
// hardware and protocol addresses.
struct DDP_LONG* header = (struct DDP_LONG*)copy;
dest.network = (at_network_t)ntohs(header->dest_net);
source.network = (at_network_t)ntohs(header->source_net);
dest.node = header->dest_node;
source.node = header->source_node;
enqueue(&elap_port.in, dest, source, LAP_DDP_LONG, payload_size, copy);
aarp_glean(&source, &ether->source);
}
else
atbridge_printf("ATBridge: Dropping invalid short ELAP frame.\n");
}
else if (memcmp(&snap->discriminator, &SNAP_AARP, sizeof(snap->discriminator)) == 0)
{
// Handle an AARP packet.
struct aarp_header_t* aarp = (struct aarp_header_t*)(packet + sizeof(struct ethernet_header_t) + sizeof(struct snap_header_t));
aarp->dest_proto_addr.addr.network = ntohs(aarp->dest_proto_addr.addr.network);
aarp->source_proto_addr.addr.network = ntohs(aarp->source_proto_addr.addr.network);
aarp->function = ntohs(aarp->function);
aarp->hardware_type = ntohs(aarp->hardware_type);
aarp->protocol_type = ntohs(aarp->protocol_type);
aarp_handle_packet(aarp);
}
}
}
return true;
}
else
return false;
}
static void elap_receive_all()
{
while (elap_receive_one());
}
void elap_process()
{
elap_receive_all();
elap_send_all_queued();
}

View File

@ -0,0 +1,789 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 - 2012 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "defc.h"
extern int Verbose;
extern int Halt_on;
extern int g_rom_version;
extern int g_io_amt;
extern int g_highest_smartport_unit;
word32 g_cycs_in_io_read = 0;
extern Engine_reg engine;
extern Iwm iwm;
#define LEN_SMPT_LOG 16
STRUCT(Smpt_log) {
word32 start_addr;
int cmd;
int rts_addr;
int cmd_list;
int extras;
int unit;
int buf;
int blk;
};
Smpt_log g_smpt_log[LEN_SMPT_LOG];
int g_smpt_log_pos = 0;
void
smartport_error(void)
{
int pos;
int i;
pos = g_smpt_log_pos;
printf("Smartport log pos: %d\n", pos);
for(i = 0; i < LEN_SMPT_LOG; i++) {
pos--;
if(pos < 0) {
pos = LEN_SMPT_LOG - 1;
}
printf("%d:%d: t:%04x, cmd:%02x, rts:%04x, "
"cmd_l:%04x, x:%d, unit:%d, buf:%04x, blk:%04x\n",
i, pos,
g_smpt_log[pos].start_addr,
g_smpt_log[pos].cmd,
g_smpt_log[pos].rts_addr,
g_smpt_log[pos].cmd_list,
g_smpt_log[pos].extras,
g_smpt_log[pos].unit,
g_smpt_log[pos].buf,
g_smpt_log[pos].blk);
}
}
void
smartport_log(word32 start_addr, int cmd, int rts_addr, int cmd_list)
{
int pos;
pos = g_smpt_log_pos;
if(start_addr != 0) {
g_smpt_log[pos].start_addr = start_addr;
g_smpt_log[pos].cmd = cmd;
g_smpt_log[pos].rts_addr = rts_addr;
g_smpt_log[pos].cmd_list = cmd_list;
g_smpt_log[pos].extras = 0;
g_smpt_log[pos].unit = 0;
g_smpt_log[pos].buf = 0;
g_smpt_log[pos].blk = 0;
} else {
pos--;
if(pos < 0) {
pos = LEN_SMPT_LOG - 1;
}
g_smpt_log[pos].extras = 1;
g_smpt_log[pos].unit = cmd;
g_smpt_log[pos].buf = rts_addr;
g_smpt_log[pos].blk = cmd_list;
}
pos++;
if(pos >= LEN_SMPT_LOG) {
pos = 0;
}
g_smpt_log_pos = pos;
}
void
do_c70d(word32 arg0)
{
int cmd;
int cmd_list_lo, cmd_list_mid, cmd_list_hi;
int rts_lo, rts_hi;
word32 rts_addr;
word32 cmd_list;
int unit;
int param_cnt;
int status_ptr_lo, status_ptr_mid, status_ptr_hi;
int buf_ptr_lo, buf_ptr_hi;
int buf_ptr;
int block_lo, block_mid, block_hi;
int block;
word32 status_ptr;
int status_code;
int ctl_ptr_lo, ctl_ptr_hi;
int ctl_ptr;
int ctl_code;
int mask;
int stat_val;
int size;
int ret;
int ext;
int i;
set_memory_c(0x7f8, 0xc7, 0);
if((engine.psr & 0x100) == 0) {
disk_printf("c70d called in native mode!\n");
if((engine.psr & 0x30) != 0x30) {
halt_printf("c70d called native, psr: %03x!\n",
engine.psr);
}
}
engine.stack = ((engine.stack + 1) & 0xff) + 0x100;
rts_lo = get_memory_c(engine.stack, 0);
engine.stack = ((engine.stack + 1) & 0xff) + 0x100;
rts_hi = get_memory_c(engine.stack, 0);
rts_addr = (rts_lo + (256*rts_hi) + 1) & 0xffff;
disk_printf("rts_addr: %04x\n", rts_addr);
cmd = get_memory_c(rts_addr, 0);
cmd_list_lo = get_memory_c((rts_addr + 1) & 0xffff, 0);
cmd_list_mid = get_memory_c((rts_addr + 2) & 0xffff, 0);
cmd_list_hi = 0;
mask = 0xffff;
if(cmd & 0x40) {
/* extended */
mask = 0xffffff;
cmd_list_hi = get_memory_c((rts_addr + 3) & 0xffff, 0);
}
cmd_list = cmd_list_lo + (256*cmd_list_mid) + (65536*cmd_list_hi);
disk_printf("cmd: %02x, cmd_list: %06x\n", cmd, cmd_list);
param_cnt = get_memory_c(cmd_list, 0);
ext = 0;
if(cmd & 0x40) {
ext = 2;
}
smartport_log(0xc70d, cmd, rts_addr, cmd_list);
switch(cmd & 0x3f) {
case 0x00: /* Status == 0x00 and 0x40 */
if(param_cnt != 3) {
disk_printf("param_cnt %d is != 3!\n", param_cnt);
exit(8);
}
unit = get_memory_c((cmd_list+1) & mask, 0);
status_ptr_lo = get_memory_c((cmd_list+2) & mask, 0);
status_ptr_mid = get_memory_c((cmd_list+3) & mask, 0);
status_ptr_hi = 0;
if(cmd & 0x40) {
status_ptr_hi = get_memory_c((cmd_list+4) & mask, 0);
}
status_ptr = status_ptr_lo + (256*status_ptr_mid) +
(65536*status_ptr_hi);
if(cmd & 0x40) {
status_code = get_memory_c((cmd_list+6) & mask, 0);
} else {
status_code = get_memory_c((cmd_list+4) & mask, 0);
}
smartport_log(0, unit, status_ptr, status_code);
disk_printf("unit: %02x, status_ptr: %06x, code: %02x\n",
unit, status_ptr, status_code);
if(unit == 0 && status_code == 0) {
/* Smartport driver status */
/* see technotes/smpt/tn-smpt-002 */
set_memory_c(status_ptr, g_highest_smartport_unit+1, 0);
set_memory_c(status_ptr+1, 0xff, 0); /* interrupt stat*/
set_memory16_c(status_ptr+2, 0x0002, 0); /* vendor id */
set_memory16_c(status_ptr+4, 0x1000, 0); /* version */
set_memory16_c(status_ptr+6, 0x0000, 0);
engine.xreg = 8;
engine.yreg = 0;
engine.acc &= 0xff00;
engine.psr &= ~1;
engine.kpc = (rts_addr + 3 + ext) & mask;
return;
} else if(unit > 0 && status_code == 0) {
/* status for unit x */
if(unit > MAX_C7_DISKS || (!iwm.smartport[unit-1].file)){
stat_val = 0x80;
size = 0;
} else {
stat_val = 0xf8;
size = iwm.smartport[unit-1].image_size;
size = (size+511) / 512;
}
set_memory_c(status_ptr, stat_val, 0);
set_memory24_c(status_ptr +1, size, 0);
engine.xreg = 4;
if(cmd & 0x40) {
set_memory_c(status_ptr + 4,
(size >> 16) & 0xff, 0);
engine.xreg = 5;
}
engine.yreg = 0;
engine.acc &= 0xff00;
engine.psr &= ~1;
engine.kpc = (rts_addr + 3 + ext) & mask;
disk_printf("just finished unit %d, stat 0\n", unit);
return;
} else if(status_code == 3) {
if(unit > MAX_C7_DISKS || (!iwm.smartport[unit-1].file)){
stat_val = 0x80;
size = 0;
} else {
stat_val = 0xf8;
size = iwm.smartport[unit-1].image_size;
size = (size+511) / 512;
}
if(cmd & 0x40) {
disk_printf("extended for stat_code 3!\n");
}
/* DIB for unit 1 */
set_memory_c(status_ptr, stat_val, 0);
set_memory24_c(status_ptr +1, size, 0);
if(cmd & 0x40) {
set_memory_c(status_ptr + 4,
(size >> 24) & 0xff, 0);
status_ptr++;
}
set_memory_c(status_ptr +4, 4, 0);
for(i = 5; i < 21; i++) {
set_memory_c(status_ptr +i, 0x20, 0);
}
set_memory_c(status_ptr +5, 'K', 0);
set_memory_c(status_ptr +6, 'E', 0);
set_memory_c(status_ptr +7, 'G', 0);
set_memory_c(status_ptr +8, 'S', 0);
/* hard disk supporting extended calls */
set_memory16_c(status_ptr + 21, 0xa002, 0);
set_memory16_c(status_ptr + 23, 0x0000, 0);
if(cmd & 0x40) {
engine.xreg = 26;
} else {
engine.xreg = 25;
}
engine.yreg = 0;
engine.acc &= 0xff00;
engine.psr &= ~1;
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
disk_printf("Just finished unit %d, stat 3\n", unit);
if(unit == 0 || unit > MAX_C7_DISKS) {
engine.acc |= 0x28;
engine.psr |= 1;
}
return;
}
printf("cmd: 00, unknown unit/status code!\n");
break;
case 0x01: /* Read Block == 0x01 and 0x41 */
if(param_cnt != 3) {
halt_printf("param_cnt %d is != 3!\n", param_cnt);
return;
}
unit = get_memory_c((cmd_list+1) & mask, 0);
buf_ptr_lo = get_memory_c((cmd_list+2) & mask, 0);
buf_ptr_hi = get_memory_c((cmd_list+3) & mask, 0);
buf_ptr = buf_ptr_lo + (256*buf_ptr_hi);
if(cmd & 0x40) {
buf_ptr_lo = get_memory_c((cmd_list+4) & mask, 0);
buf_ptr_hi = get_memory_c((cmd_list+5) & mask, 0);
buf_ptr += ((buf_ptr_hi*256) + buf_ptr_lo)*65536;
cmd_list += 2;
}
block_lo = get_memory_c((cmd_list+4) & mask, 0);
block_mid = get_memory_c((cmd_list+5) & mask, 0);
block_hi = get_memory_c((cmd_list+6) & mask, 0);
block = ((block_hi*256) + block_mid)*256 + block_lo;
disk_printf("smartport read unit %d of block %04x into %04x\n",
unit, block, buf_ptr);
if(unit < 1 || unit > MAX_C7_DISKS) {
halt_printf("Unknown unit #: %d\n", unit);
}
smartport_log(0, unit - 1, buf_ptr, block);
ret = do_read_c7(unit - 1, buf_ptr, block);
engine.xreg = 0;
engine.yreg = 2;
engine.acc = (engine.acc & 0xff00) | (ret & 0xff);
engine.psr &= ~1;
if(ret != 0) {
engine.psr |= 1;
}
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
return;
break;
case 0x02: /* Write Block == 0x02 and 0x42 */
if(param_cnt != 3) {
halt_printf("param_cnt %d is != 3!\n", param_cnt);
return;
}
unit = get_memory_c((cmd_list+1) & mask, 0);
buf_ptr_lo = get_memory_c((cmd_list+2) & mask, 0);
buf_ptr_hi = get_memory_c((cmd_list+3) & mask, 0);
buf_ptr = buf_ptr_lo + (256*buf_ptr_hi);
if(cmd & 0x40) {
buf_ptr_lo = get_memory_c((cmd_list+4) & mask, 0);
buf_ptr_hi = get_memory_c((cmd_list+5) & mask, 0);
buf_ptr += ((buf_ptr_hi*256) + buf_ptr_lo)*65536;
cmd_list += 2;
}
block_lo = get_memory_c((cmd_list+4) & mask, 0);
block_mid = get_memory_c((cmd_list+5) & mask, 0);
block_hi = get_memory_c((cmd_list+6) & mask, 0);
block = ((block_hi*256) + block_mid)*256 + block_lo;
disk_printf("smartport write unit %d of block %04x from %04x\n",
unit, block, buf_ptr);
if(unit < 1 || unit > MAX_C7_DISKS) {
halt_printf("Unknown unit #: %d\n", unit);
}
smartport_log(0, unit - 1, buf_ptr, block);
ret = do_write_c7(unit - 1, buf_ptr, block);
engine.xreg = 0;
engine.yreg = 2;
engine.acc = (engine.acc & 0xff00) | (ret & 0xff);
engine.psr &= ~1;
if(ret != 0) {
engine.psr |= 1;
}
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
HALT_ON(HALT_ON_C70D_WRITES, "c70d Write done\n");
return;
break;
case 0x03: /* Format == 0x03 and 0x43 */
if(param_cnt != 1) {
halt_printf("param_cnt %d is != 1!\n", param_cnt);
return;
}
unit = get_memory_c((cmd_list+1) & mask, 0);
if(unit < 1 || unit > MAX_C7_DISKS) {
halt_printf("Unknown unit #: %d\n", unit);
}
smartport_log(0, unit - 1, 0, 0);
ret = do_format_c7(unit - 1);
engine.xreg = 0;
engine.yreg = 2;
engine.acc = (engine.acc & 0xff00) | (ret & 0xff);
engine.psr &= ~1;
if(ret != 0) {
engine.psr |= 1;
}
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
HALT_ON(HALT_ON_C70D_WRITES, "c70d Format done\n");
return;
break;
case 0x04: /* Control == 0x04 and 0x44 */
if(cmd == 0x44) {
halt_printf("smartport code 0x44 not supported\n");
}
if(param_cnt != 3) {
halt_printf("param_cnt %d is != 3!\n", param_cnt);
return;
}
unit = get_memory_c((cmd_list+1) & mask, 0);
ctl_ptr_lo = get_memory_c((cmd_list+2) & mask, 0);
ctl_ptr_hi = get_memory_c((cmd_list+3) & mask, 0);
ctl_ptr = (ctl_ptr_hi << 8) + ctl_ptr_lo;
if(cmd & 0x40) {
ctl_ptr_lo = get_memory_c((cmd_list+4) & mask, 0);
ctl_ptr_hi = get_memory_c((cmd_list+5) & mask, 0);
ctl_ptr += ((ctl_ptr_hi << 8) + ctl_ptr_lo) << 16;
cmd_list += 2;
}
ctl_code = get_memory_c((cmd_list +4) & mask, 0);
switch(ctl_code) {
case 0x00:
printf("Performing a reset on unit %d\n", unit);
break;
default:
halt_printf("control code: %02x unknown!\n", ctl_code);
}
engine.xreg = 0;
engine.yreg = 2;
engine.acc &= 0xff00;
engine.psr &= ~1;
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
return;
break;
default: /* Unknown command! */
/* set acc = 1, and set carry, and set kpc */
engine.xreg = (rts_addr) & 0xff;
engine.yreg = (rts_addr >> 8) & 0xff;
engine.acc = (engine.acc & 0xff00) + 0x01;
engine.psr |= 0x01; /* set carry */
engine.kpc = (rts_addr + 3 + ext) & 0xffff;
if(cmd != 0x4a && cmd != 0x48) {
/* Finder does 0x4a call before formatting disk */
/* Many things do 0x48 call to see online drives */
halt_printf("Just did smtport cmd:%02x rts_addr:%04x, "
"cmdlst:%06x\n", cmd, rts_addr, cmd_list);
}
return;
}
halt_printf("Unknown smtport cmd:%02x, cmd_list:%06x, rts_addr:%06x\n",
cmd, cmd_list, rts_addr);
}
void
do_c70a(word32 arg0)
{
int cmd, unit;
int buf_lo, buf_hi;
int blk_lo, blk_hi;
int blk, buf;
int prodos_unit;
int size;
int ret;
set_memory_c(0x7f8, 0xc7, 0);
cmd = get_memory_c((engine.direct + 0x42) & 0xffff, 0);
prodos_unit = get_memory_c((engine.direct + 0x43) & 0xffff, 0);
buf_lo = get_memory_c((engine.direct + 0x44) & 0xffff, 0);
buf_hi = get_memory_c((engine.direct + 0x45) & 0xffff, 0);
blk_lo = get_memory_c((engine.direct + 0x46) & 0xffff, 0);
blk_hi = get_memory_c((engine.direct + 0x47) & 0xffff, 0);
blk = (blk_hi << 8) + blk_lo;
buf = (buf_hi << 8) + buf_lo;
disk_printf("cmd: %02x, pro_unit: %02x, buf: %04x, blk: %04x\n",
cmd, prodos_unit, buf, blk);
if((prodos_unit & 0x7f) == 0x70) {
unit = 0 + (prodos_unit >> 7);
} else if((prodos_unit & 0x7f) == 0x40) {
unit = 2 + (prodos_unit >> 7);
} else {
halt_printf("Unknown prodos_unit: %d\n", prodos_unit);
return;
}
smartport_log(0xc70a, cmd, blk, buf);
engine.psr &= ~1; /* clear carry */
if(g_rom_version >= 3) {
engine.kpc = 0xc764;
} else {
engine.kpc = 0xc765;
}
ret = 0x27; /* I/O error */
if(cmd == 0x00) {
size = iwm.smartport[unit].image_size;
size = (size+511) / 512;
smartport_log(0, unit, size, 0);
ret = 0;
engine.xreg = size & 0xff;
engine.yreg = size >> 8;
} else if(cmd == 0x01) {
smartport_log(0, unit, buf, blk);
ret = do_read_c7(unit, buf, blk);
} else if(cmd == 0x02) {
smartport_log(0, unit, buf, blk);
ret = do_write_c7(unit, buf, blk);
} else if(cmd == 0x03) { /* format */
smartport_log(0, unit, buf, blk);
ret = do_format_c7(unit);
}
engine.acc = (engine.acc & 0xff00) | (ret & 0xff);
if(ret != 0) {
engine.psr |= 1;
}
return;
}
int
do_read_c7(int unit_num, word32 buf, int blk)
{
byte local_buf[0x200];
register word32 start_time;
register word32 end_time;
word32 val;
FILE *file;
int len;
int image_start;
int image_size;
int ret;
int i;
if(unit_num < 0 || unit_num > MAX_C7_DISKS) {
halt_printf("do_read_c7: unit_num: %d\n", unit_num);
smartport_error();
return 0x28;
}
file = iwm.smartport[unit_num].file;
image_start = iwm.smartport[unit_num].image_start;
image_size = iwm.smartport[unit_num].image_size;
if(!file) {
printf("c7_file is null!\n");
#if 0
if(blk != 2 && blk != 0) {
/* don't print error if only reading directory */
smartport_error();
halt_printf("Read unit:%02x blk:%04x\n", unit_num, blk);
}
#endif
return 0x2f;
}
ret = fseek(file, image_start + blk*0x200, SEEK_SET);
if(ret != 0) {
halt_printf("fseek errno: %d\n", errno);
smartport_error();
return 0x27;
}
if(image_start + blk*0x200 > image_start + image_size) {
halt_printf("Tried to read from pos %08x on disk, (blk:%04x)\n",
image_start + blk*0x200, blk);
smartport_error();
return 0x27;
}
len = fread(&local_buf[0], 1, 0x200, file);
if(len != 0x200) {
printf("fread returned %08x, errno:%d, blk:%04x, unit: %02x\n",
len, errno, blk, unit_num);
halt_printf("name: %s\n", iwm.smartport[unit_num].name_ptr);
smartport_error();
return 0x27;
}
g_io_amt += 0x200;
if(buf >= 0xfc0000) {
disk_printf("reading into ROM, just returning\n");
return 0;
}
GET_ITIMER(start_time);
for(i = 0; i < 0x200; i += 2) {
val = (local_buf[i+1] << 8) + local_buf[i];
set_memory16_c(buf + i, val, 0);
}
GET_ITIMER(end_time);
g_cycs_in_io_read += (end_time - start_time);
return 0;
}
int
do_write_c7(int unit_num, word32 buf, int blk)
{
word32 local_buf[0x200/4];
Disk *dsk;
word32 *ptr;
word32 val1, val2;
word32 val;
FILE *file;
int len;
int ret;
int image_start;
int image_size;
int i;
if(unit_num < 0 || unit_num > MAX_C7_DISKS) {
halt_printf("do_write_c7: unit_num: %d\n", unit_num);
smartport_error();
return 0x28;
}
dsk = &(iwm.smartport[unit_num]);
file = dsk->file;
image_start = dsk->image_start;
image_size = dsk->image_size;
if(!file) {
halt_printf("c7_file is null!\n");
smartport_error();
return 0x28;
}
ptr = &(local_buf[0]);
for(i = 0; i < 0x200; i += 4) {
val1 = get_memory16_c(buf + i, 0);
val2 = get_memory16_c(buf + i + 2, 0);
/* reorder the little-endian bytes to be big-endian */
#if defined(GSPORT_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
val = (val2 << 16) + val1;
#else
val = (val1 << 24) + ((val1 << 8) & 0xff0000) +
((val2 << 8) & 0xff00) + (val2 >> 8);
#endif
*ptr++ = val;
}
ret = fseek(file, image_start + blk*0x200, SEEK_SET);
if(ret != 0) {
halt_printf("fseek errno: %d\n", errno);
smartport_error();
return 0x27;
}
if(image_start + blk*0x200 > image_start + image_size) {
halt_printf("Tried to write to %08x\n", ret);
smartport_error();
return 0x27;
}
if(dsk->write_prot) {
printf("Write, but %s is write protected!\n", dsk->name_ptr);
return 0x2b;
}
if(dsk->write_through_to_unix == 0) {
halt_printf("Write to %s, but not wr_thru!\n", dsk->name_ptr);
return 0x00;
}
len = fwrite((byte *)&local_buf[0], 1, 0x200, file);
if(len != 0x200) {
halt_printf("fwrite ret %08x bytes, errno: %d\n", len, errno);
smartport_error();
return 0x27;
}
g_io_amt += 0x200;
return 0;
}
int
do_format_c7(int unit_num)
{
byte local_buf[0x1000];
Disk *dsk;
FILE *file;
int len;
int ret;
int sum;
int total;
int max;
int image_start;
int image_size;
int i;
if(unit_num < 0 || unit_num > MAX_C7_DISKS) {
halt_printf("do_format_c7: unit_num: %d\n", unit_num);
smartport_error();
return 0x28;
}
dsk = &(iwm.smartport[unit_num]);
file = dsk->file;
image_start = dsk->image_start;
image_size = dsk->image_size;
if(!file) {
halt_printf("c7_file is null!\n");
smartport_error();
return 0x28;
}
for(i = 0; i < 0x1000; i++) {
local_buf[i] = 0;
}
ret = fseek(file, image_start, SEEK_SET);
if(ret != 0) {
halt_printf("fseek errno: %d\n", errno);
smartport_error();
return 0x27;
}
if(dsk->write_prot) {
printf("Format, but %s is write protected!\n", dsk->name_ptr);
return 0x2b;
}
if(dsk->write_through_to_unix == 0) {
printf("Format of %s ignored\n", dsk->name_ptr);
return 0x00;
}
sum = 0;
total = image_size;
while(sum < total) {
max = MIN(0x1000, total-sum);
len = fwrite(&local_buf[0], 1, max, file);
if(len != max) {
halt_printf("write ret %08x, errno:%d\n", len, errno);
smartport_error();
return 0x27;
}
sum += len;
}
return 0;
}
extern byte g_bram[2][256];
extern byte* g_bram_ptr;
extern byte g_temp_boot_slot;
extern byte g_orig_boot_slot;
extern int g_config_gsport_update_needed;
void
do_c700(word32 ret)
{
disk_printf("do_c700 called, ret: %08x\n", ret);
if (g_temp_boot_slot != 254) {
// Booting from slot 7 - now is a good time to turn off the temp boot slot, if it was on.
g_temp_boot_slot = 254;
g_bram_ptr[40] = g_orig_boot_slot;
clk_calculate_bram_checksum();
g_config_gsport_update_needed = 1;
}
ret = do_read_c7(0, 0x800, 0);
set_memory_c(0x7f8, 7, 0);
set_memory16_c(0x42, 0x7001, 0);
set_memory16_c(0x44, 0x0800, 0);
set_memory16_c(0x46, 0x0000, 0);
engine.xreg = 0x70;
engine.kpc = 0x801;
if(ret != 0) {
printf("Failure reading boot disk in s7d1!\n");
engine.kpc = 0xff59; /* Jump to monitor, fix $36-$39 */
}
}

View File

@ -0,0 +1,230 @@
/*****************************************************************************
* dirent.h - dirent API for Microsoft Visual Studio
*
* Copyright (C) 2006 Toni Ronkko
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* ``Software''), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Dec 15, 2009, John Cunningham
* Added rewinddir member function
*
* Jan 18, 2008, Toni Ronkko
* Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
* between multi-byte and unicode representations. This makes the
* code simpler and also allows the code to be compiled under MingW. Thanks
* to Azriel Fasten for the suggestion.
*
* Mar 4, 2007, Toni Ronkko
* Bug fix: due to the strncpy_s() function this file only compiled in
* Visual Studio 2005. Using the new string functions only when the
* compiler version allows.
*
* Nov 2, 2006, Toni Ronkko
* Major update: removed support for Watcom C, MS-DOS and Turbo C to
* simplify the file, updated the code to compile cleanly on Visual
* Studio 2005 with both unicode and multi-byte character strings,
* removed rewinddir() as it had a bug.
*
* Aug 20, 2006, Toni Ronkko
* Removed all remarks about MSVC 1.0, which is antiqued now. Simplified
* comments by removing SGML tags.
*
* May 14 2002, Toni Ronkko
* Embedded the function definitions directly to the header so that no
* source modules need to be included in the Visual Studio project. Removed
* all the dependencies to other projects so that this very header can be
* used independently.
*
* May 28 1998, Toni Ronkko
* First version.
*****************************************************************************/
#ifndef DIRENT_H
#define DIRENT_H
#include <windows.h>
#include <string.h>
#include <assert.h>
typedef struct dirent
{
char d_name[MAX_PATH + 1]; /* current dir entry (multi-byte char string) */
WIN32_FIND_DATAA data; /* file attributes */
} dirent;
typedef struct DIR
{
dirent current; /* Current directory entry */
int cached; /* Indicates un-processed entry in memory */
HANDLE search_handle; /* File search handle */
char patt[MAX_PATH + 3]; /* search pattern (3 = pattern + "\\*\0") */
} DIR;
/* Forward declarations */
static DIR *opendir (const char *dirname);
static struct dirent *readdir (DIR *dirp);
static int closedir (DIR *dirp);
static void rewinddir(DIR* dirp);
/* Use the new safe string functions introduced in Visual Studio 2005 */
#if defined(_MSC_VER) && _MSC_VER >= 1400
# define STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE)
#else
# define STRNCPY(dest,src,size) strncpy((dest),(src),(size))
#endif
/*****************************************************************************
* Open directory stream DIRNAME for read and return a pointer to the
* internal working area that is used to retrieve individual directory
* entries.
*/
static DIR *opendir(const char *dirname)
{
DIR *dirp;
assert (dirname != NULL);
assert (strlen (dirname) < MAX_PATH);
/* construct new DIR structure */
dirp = (DIR*) malloc (sizeof (struct DIR));
if (dirp != NULL) {
char *p;
/* take directory name... */
STRNCPY (dirp->patt, dirname, sizeof(dirp->patt));
dirp->patt[MAX_PATH] = '\0';
/* ... and append search pattern to it */
p = strchr (dirp->patt, '\0');
if (dirp->patt < p && *(p-1) != '\\' && *(p-1) != ':') {
*p++ = '\\';
}
*p++ = '*';
*p = '\0';
/* open stream and retrieve first file */
dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data);
if (dirp->search_handle == INVALID_HANDLE_VALUE) {
/* invalid search pattern? */
free (dirp);
return NULL;
}
/* there is an un-processed directory entry in memory now */
dirp->cached = 1;
}
return dirp;
}
/*****************************************************************************
* Read a directory entry, and return a pointer to a dirent structure
* containing the name of the entry in d_name field. Individual directory
* entries returned by this very function include regular files,
* sub-directories, pseudo-directories "." and "..", but also volume labels,
* hidden files and system files may be returned.
*/
static struct dirent *readdir(DIR *dirp)
{
assert (dirp != NULL);
if (dirp->search_handle == INVALID_HANDLE_VALUE) {
/* directory stream was opened/rewound incorrectly or ended normally */
return NULL;
}
/* get next directory entry */
if (dirp->cached != 0) {
/* a valid directory entry already in memory */
dirp->cached = 0;
} else {
/* read next directory entry from disk */
if (FindNextFileA (dirp->search_handle, &dirp->current.data) == FALSE) {
/* the very last file has been processed or an error occured */
FindClose (dirp->search_handle);
dirp->search_handle = INVALID_HANDLE_VALUE;
return NULL;
}
}
/* copy as a multibyte character string */
STRNCPY ( dirp->current.d_name,
dirp->current.data.cFileName,
sizeof(dirp->current.d_name) );
dirp->current.d_name[MAX_PATH] = '\0';
return &dirp->current;
}
/*****************************************************************************
* Close directory stream opened by opendir() function. Close of the
* directory stream invalidates the DIR structure as well as any previously
* read directory entry.
*/
static int closedir(DIR *dirp)
{
assert (dirp != NULL);
/* release search handle */
if (dirp->search_handle != INVALID_HANDLE_VALUE) {
FindClose (dirp->search_handle);
dirp->search_handle = INVALID_HANDLE_VALUE;
}
/* release directory handle */
free (dirp);
return 0;
}
/*****************************************************************************
* Resets the position of the directory stream to which dirp refers to the
* beginning of the directory. It also causes the directory stream to refer
* to the current state of the corresponding directory, as a call to opendir()
* would have done. If dirp does not refer to a directory stream, the effect
* is undefined.
*/
static void rewinddir(DIR* dirp)
{
/* release search handle */
if (dirp->search_handle != INVALID_HANDLE_VALUE) {
FindClose (dirp->search_handle);
dirp->search_handle = INVALID_HANDLE_VALUE;
}
/* open new search handle and retrieve first file */
dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->current.data);
if (dirp->search_handle == INVALID_HANDLE_VALUE) {
/* invalid search pattern? */
free (dirp);
return;
}
/* there is an un-processed directory entry in memory now */
dirp->cached = 1;
}
#endif /*DIRENT_H*/

View File

@ -0,0 +1,281 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 - 2013 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "defc.h"
#ifdef __linux__
# include <linux/joystick.h>
# include <sys/time.h>
#endif
#ifdef _WIN32
# include <windows.h>
# include <mmsystem.h>
# include <time.h>
#endif
extern int g_joystick_native_type1; /* in paddles.c */
extern int g_joystick_native_type2; /* in paddles.c */
extern int g_joystick_native_type; /* in paddles.c */
extern int g_paddle_buttons;
extern int g_paddle_val[];
const char *g_joystick_dev = "/dev/input/js0"; /* default joystick dev file */
#define MAX_JOY_NAME 128
int g_joystick_native_fd = -1;
int g_joystick_num_axes = 0;
int g_joystick_num_buttons = 0;
#ifdef __linux__
# define JOYSTICK_DEFINED
void
joystick_init()
{
char joy_name[MAX_JOY_NAME];
int version;
int fd;
int i;
fd = open(g_joystick_dev, O_RDONLY | O_NONBLOCK);
if(fd < 0) {
printf("Unable to open joystick dev file: %s, errno: %d\n",
g_joystick_dev, errno);
printf("Defaulting to mouse joystick\n");
return;
}
strcpy(&joy_name[0], "Unknown Joystick");
version = 0x800;
ioctl(fd, JSIOCGNAME(MAX_JOY_NAME), &joy_name[0]);
ioctl(fd, JSIOCGAXES, &g_joystick_num_axes);
ioctl(fd, JSIOCGBUTTONS, &g_joystick_num_buttons);
ioctl(fd, JSIOCGVERSION, &version);
printf("Detected joystick: %s [%d axes, %d buttons vers: %08x]\n",
joy_name, g_joystick_num_axes, g_joystick_num_buttons,
version);
g_joystick_native_type1 = 1;
g_joystick_native_type2 = -1;
g_joystick_native_fd = fd;
for(i = 0; i < 4; i++) {
g_paddle_val[i] = 32767;
}
g_paddle_buttons = 0xc;
joystick_update(0.0);
}
/* joystick_update_linux() called from paddles.c. Update g_paddle_val[] */
/* and g_paddle_buttons with current information */
void
joystick_update(double dcycs)
{
struct js_event js; /* the linux joystick event record */
int mask;
int val;
int num;
int type;
int ret;
int len;
int i;
/* suck up to 20 events, then give up */
len = sizeof(struct js_event);
for(i = 0; i < 20; i++) {
ret = read(g_joystick_native_fd, &js, len);
if(ret != len) {
/* just get out */
break;
}
type = js.type & ~JS_EVENT_INIT;
val = js.value;
num = js.number & 3; /* clamp to 0-3 */
switch(type) {
case JS_EVENT_BUTTON:
mask = 1 << num;
if(val) {
val = mask;
}
g_paddle_buttons = (g_paddle_buttons & ~mask) | val;
break;
case JS_EVENT_AXIS:
/* val is -32767 to +32767 */
g_paddle_val[num] = val;
break;
}
}
// if(i > 0) {
// Note from Dave Schmenk: paddle_update_trigger_dcycles(dcycs) always has to be called to keep the triggers current.
paddle_update_trigger_dcycs(dcycs);
// }
}
void
joystick_update_buttons()
{
}
#endif /* LINUX */
#ifdef _WIN32
# define JOYSTICK_DEFINED
void
joystick_init()
{
JOYINFO info;
JOYCAPS joycap;
MMRESULT ret1, ret2;
int i;
// Check that there is a joystick device
if(joyGetNumDevs() <= 0) {
printf("No joystick hardware detected\n");
g_joystick_native_type1 = -1;
g_joystick_native_type2 = -1;
return;
}
g_joystick_native_type1 = -1;
g_joystick_native_type2 = -1;
// Check that at least joystick 1 or joystick 2 is available
ret1 = joyGetPos(JOYSTICKID1, &info);
ret2 = joyGetDevCaps(JOYSTICKID1, &joycap, sizeof(joycap));
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
g_joystick_native_type1 = JOYSTICKID1;
printf("Joystick #1 = %s\n", joycap.szPname);
g_joystick_native_type = JOYSTICKID1;
}
ret1 = joyGetPos(JOYSTICKID2, &info);
ret2 = joyGetDevCaps(JOYSTICKID2, &joycap, sizeof(joycap));
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
g_joystick_native_type2 = JOYSTICKID2;
printf("Joystick #2 = %s\n", joycap.szPname);
if(g_joystick_native_type < 0) {
g_joystick_native_type = JOYSTICKID2;
}
}
if (g_joystick_native_type1<0 && g_joystick_native_type2 <0) {
printf ("No joystick is attached\n");
return;
}
for(i = 0; i < 4; i++) {
g_paddle_val[i] = 32767;
}
g_paddle_buttons = 0xc;
joystick_update(0.0);
}
void
joystick_update(double dcycs)
{
JOYCAPS joycap;
JOYINFO info;
UINT id;
MMRESULT ret1, ret2;
id = g_joystick_native_type;
ret1 = joyGetDevCaps(id, &joycap, sizeof(joycap));
ret2 = joyGetPos(id, &info);
if(ret1 == JOYERR_NOERROR && ret2 == JOYERR_NOERROR) {
g_paddle_val[0] = (info.wXpos - joycap.wXmin) * 32768 /
(joycap.wXmax - joycap.wXmin);
g_paddle_val[1] = (info.wYpos - joycap.wYmin) * 32768 /
(joycap.wYmax - joycap.wYmin);
if(info.wButtons & JOY_BUTTON1) {
g_paddle_buttons = g_paddle_buttons | 1;
} else {
g_paddle_buttons = g_paddle_buttons & (~1);
}
if(info.wButtons & JOY_BUTTON2) {
g_paddle_buttons = g_paddle_buttons | 2;
} else {
g_paddle_buttons = g_paddle_buttons & (~2);
}
paddle_update_trigger_dcycs(dcycs);
}
}
void
joystick_update_buttons()
{
JOYINFOEX info;
UINT id;
id = g_joystick_native_type;
info.dwSize = sizeof(JOYINFOEX);
info.dwFlags = JOY_RETURNBUTTONS;
if(joyGetPosEx(id, &info) == JOYERR_NOERROR) {
if(info.dwButtons & JOY_BUTTON1) {
g_paddle_buttons = g_paddle_buttons | 1;
} else {
g_paddle_buttons = g_paddle_buttons & (~1);
}
if(info.dwButtons & JOY_BUTTON2) {
g_paddle_buttons = g_paddle_buttons | 2;
} else {
g_paddle_buttons = g_paddle_buttons & (~2);
}
}
}
#endif
#ifndef JOYSTICK_DEFINED
/* stubs for the routines */
void
joystick_init()
{
g_joystick_native_type1 = -1;
g_joystick_native_type2 = -1;
g_joystick_native_type = -1;
}
void
joystick_update(double dcycs)
{
int i;
for(i = 0; i < 4; i++) {
g_paddle_val[i] = 32767;
}
g_paddle_buttons = 0xc;
}
void
joystick_update_buttons()
{
}
// OG
void joystick_shut()
{
}
#endif

View File

@ -0,0 +1,47 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2013-2014 by Peter Neubauer
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
ATBridge is a limited function AppleTalk bridge that allows GSPort to connect to an
EtherTalk network. The bridge has two ports, one the emulated LocalTalk port and the
other an EtherTalk Phase II port.
Due to timing requirements of LocalTalk, it is not reasonable to transparently bridge
LLAP traffic to ELAP. For example, implementing the lapENQ/lapACK LLAP control packets
requires AARP queries on the ELAP port, which can't be reasonably done within the 200us
LLAP interframe gap. So, we must implement the local bridge functionality detailed
in "Inside AppleTalk", including AARP, RTMP, ZIP, and DDP routing.
**/
#include "atalk.h"
bool atbridge_init();
void atbridge_shutdown();
void atbridge_process();
void atbridge_set_diagnostics(bool enabled);
bool atbridge_get_diagnostics();
void atbridge_printf(const char *fmt, ...);
const struct at_addr_t* atbridge_get_addr();
const at_network_t atbridge_get_net();
const at_node_t atbridge_get_node();
void atbridge_set_net(at_network_t net);
void atbridge_set_node(at_node_t node);
bool atbridge_address_used(const struct at_addr_t* addr);

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: support.h,v 1.18 2009/05/27 09:15:41 qbix79 Exp $ */
#ifndef DOSBOX_SUPPORT_H
#define DOSBOX_SUPPORT_H
#include <string.h>
#include <string>
#include <ctype.h>
typedef signed Bits;
#if defined (_MSC_VER) /* MS Visual C++ */
#define strcasecmp(a,b) stricmp(a,b)
#define strncasecmp(a,b,n) _strnicmp(a,b,n)
#endif
#define safe_strncpy(a,b,n) do { strncpy((a),(b),(n)-1); (a)[(n)-1] = 0; } while (0)
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
void strreplace(char * str,char o,char n);
char *ltrim(char *str);
char *rtrim(char *str);
char *trim(char * str);
char * upcase(char * str);
char * lowcase(char * str);
bool ScanCMDBool(char * cmd,char const * const check);
char * ScanCMDRemain(char * cmd);
char * StripWord(char *&cmd);
bool IsDecWord(char * word);
bool IsHexWord(char * word);
Bits ConvDecWord(char * word);
Bits ConvHexWord(char * word);
void upcase(std::string &str);
void lowcase(std::string &str);
#endif

View File

@ -0,0 +1,20 @@
TARGET = gsportx
OBJECTS = engine_s.o $(OBJECTS1) sound_driver.o xdriver.o
CC = cc -Ae +DA1.1
CCOPTS = -O
OPTS = -DNDEBUG
SUFFIX =
NAME = gsportx
LDFLAGS =
LDOPTS = -z
LD = $(CC)
EXTRA_LIBS = -lXext -lX11 -lcl -lc
EXTRA_SPECIALS = 8inst_s 16inst_s 8size 16size size_s Alib.h
AS = cc -Ae
PERL = perl
XOPTS = -DHPUX -I/usr/include/X11R5
XLIBS = -L/usr/lib/X11R5 -L/opt/audio/lib

View File

@ -0,0 +1,557 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2013 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* fbdriver - Linux fullscreen framebuffer graphics driver
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <linux/input.h>
#include <termios.h>
#include <sys/mman.h>
#include "defc.h"
void quitEmulator();
extern int g_screen_depth;
extern word32 g_palette_8to1624[256];
extern word32 g_a2palette_8to1624[256];
extern word32 g_a2_screen_buffer_changed;
extern word32 g_c025_val;
#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) )
extern int g_video_act_margin_left;
extern int g_video_act_margin_right;
extern int g_video_act_margin_top;
extern int g_video_act_margin_bottom;
extern int g_lores_colors[];
extern int g_cur_a2_stat;
extern int g_a2vid_palette;
extern int g_installed_full_superhires_colormap;
extern int g_mouse_raw_x;
extern int g_mouse_raw_y;
extern word32 g_red_mask;
extern word32 g_green_mask;
extern word32 g_blue_mask;
extern int g_red_left_shift;
extern int g_green_left_shift;
extern int g_blue_left_shift;
extern int g_red_right_shift;
extern int g_green_right_shift;
extern int g_blue_right_shift;
extern Kimage g_mainwin_kimage;
int keycode_to_a2code[128] =
{
-1, // KEY_RESERVED
0x35, // KEY_ESC
0x12, // KEY_1
0x13, // KEY_2
0x14, // KEY_3
0x15, // KEY_4
0x17, // KEY_5
0x16, // KEY_6
0x1A, // KEY_7
0x1C, // KEY_8
0x19, // KEY_9
0x1D, // KEY_0
0x1B, // KEY_MINUS
0x18, // KEY_EQUAL
0x3B, // KEY_BACKSPACE0
0x30, // KEY_TAB
0x0C, // KEY_Q
0x0D, // KEY_W
0x0E, // KEY_E
0x0F, // KEY_R
0x11, // KEY_T
0x10, // KEY_Y
0x20, // KEY_U
0x22, // KEY_I
0x1F, // KEY_O
0x23, // KEY_P
0x21, // KEY_LEFTBRACE
0x1E, // KEY_RIGHTBRACE
0x24, // KEY_ENTER
0x36, // KEY_LEFTCTRL
0x00, // KEY_A
0x01, // KEY_S
0x02, // KEY_D
0x03, // KEY_F
0x05, // KEY_G
0x04, // KEY_H
0x26, // KEY_J
0x28, // KEY_K
0x25, // KEY_L
0x29, // KEY_SEMICOLON
0x27, // KEY_APOSTROPHE
0x32, // KEY_GRAVE
0x38, // KEY_LEFTSHIFT
0x2A, // KEY_BACKSLASH
0x06, // KEY_Z
0x07, // KEY_X
0x08, // KEY_C
0x09, // KEY_V
0x0B, // KEY_B
0x2D, // KEY_N
0x2E, // KEY_M
0x2B, // KEY_COMMA
0x2F, // KEY_DOT
0x2C, // KEY_SLASH
0x38, // KEY_RIGHTSHIFT
0x43, // KEY_KPASTERISK
0x37, // KEY_LEFTALT
0x31, // KEY_SPACE
0x39, // KEY_CAPSLOCK
0x7A, // KEY_F1
0x78, // KEY_F2
0x63, // KEY_F3
0x76, // KEY_F4
0x60, // KEY_F5
0x61, // KEY_F6
0x62, // KEY_F7
0x64, // KEY_F8
0x65, // KEY_F9
0x6D, // KEY_F10
0x47, // KEY_NUMLOCK
0x37, // KEY_SCROLLLOCK
0x59, // KEY_KP7
0x5B, // KEY_KP8
0x5C, // KEY_KP9
0x4E, // KEY_KPMINUS
0x56, // KEY_KP4
0x57, // KEY_KP5
0x58, // KEY_KP6
0x45, // KEY_KPPLUS
0x53, // KEY_KP1
0x54, // KEY_KP2
0x55, // KEY_KP3
0x52, // KEY_KP0
0x41, // KEY_KPDOT
-1,
-1, // KEY_ZENKAKUHANKAKU
-1, // KEY_102ND
0x67, // KEY_F11
0x6F, // KEY_F12
-1, // KEY_RO
-1, // KEY_KATAKANA
-1, // KEY_HIRAGANA
-1, // KEY_HENKAN
-1, // KEY_KATAKANAHIRAGANA
-1, // KEY_MUHENKAN
-1, // KEY_KPJPCOMMA
0x4C, // KEY_KPENTER
0x36, // KEY_RIGHTCTRL
0x4B, // KEY_KPSLASH
0x7F, // KEY_SYSRQ
0x37, // KEY_RIGHTALT
0x6E, // KEY_LINEFEED
0x73, // KEY_HOME
0x3E, // KEY_UP
0x74, // KEY_PAGEUP
0x3B, // KEY_LEFT
0x3C, // KEY_RIGHT
0x77, // KEY_END
0x3D, // KEY_DOWN
0x79, // KEY_PAGEDOWN
0x72, // KEY_INSERT
0x33, // KEY_DELETE
-1, // KEY_MACRO
-1, // KEY_MUTE
-1, // KEY_VOLUMEDOWN
-1, // KEY_VOLUMEUP
0x7F, // KEY_POWER /* SC System Power Down */
0x51, // KEY_KPEQUAL
0x4E, // KEY_KPPLUSMINUS
-1, // KEY_PAUSE
-1, // KEY_SCALE /* AL Compiz Scale (Expose) */
0x2B, // KEY_KPCOMMA
-1, // KEY_HANGEUL
-1, // KEY_HANJA
-1, // KEY_YEN
0x3A, // KEY_LEFTMETA
0x3A, // KEY_RIGHTMETA
-1 // KEY_COMPOSE
};
struct termios org_tio;
struct fb_var_screeninfo orig_vinfo;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
int pix_size, g_screen_mdepth, g_use_shmem = 1;
#define MOUSE_LBTN_DOWN 0x01
#define MOUSE_MBTN_DOWN 0x02
#define MOUSE_RBTN_DOWN 0x04
#define MOUSE_LBTN_UP 0x00
#define MOUSE_MBTN_UP 0x00
#define MOUSE_RBTN_UP 0x00
#define MOUSE_BTN_ACTIVE 0x07
#define UPDATE_INPUT_MOUSE 0x10
#define MAX_EVDEV 8
char *fb_ptr, g_inputstate = 0;
int evfd[MAX_EVDEV], evdevs, termfd, fbfd = 0;
/*
* Clean up
*/
void xdriver_end(void)
{
char c;
static char xexit = 0;
if (!xexit)
{
// cleanup
munmap(fb_ptr, finfo.smem_len);
ioctl(fbfd, FBIOPUT_VSCREENINFO, &orig_vinfo);
close(fbfd);
if (termfd > 0)
{
// Flush input
while (read(termfd, &c, 1) == 1);
ioctl(termfd, KDSETMODE, KD_TEXT);
tcsetattr(termfd, TCSANOW, &org_tio);
close(termfd);
}
fclose(stdout);
fclose(stderr);
while (evdevs--)
close(evfd[evdevs]);
xexit = 1;
}
}
/*
* Init framebuffer and input
*/
void dev_video_init(void)
{
int i;
char evdevname[20];
struct termios termio;
// Set graphics mode on console
if ((termfd = open("/dev/tty", O_RDWR)) < 0)
{
fprintf(stderr, "Error opening tty device.\n");
exit(-1);
}
// Save input settings.
tcgetattr(termfd, &termio); /* save current port settings */
memcpy(&org_tio, &termio, sizeof(struct termios));
ioctl(termfd, KDSETMODE, KD_GRAPHICS);
// Open the file for reading and writing
if ((fbfd = open("/dev/fb0", O_RDWR)) < 0)
{
fprintf(stderr, "Error opening framebuffer device.\n");
ioctl(termfd, KDSETMODE, KD_TEXT);
exit(-1);
}
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
{
fprintf(stderr, "Error reading variable screen information.\n");
ioctl(termfd, KDSETMODE, KD_TEXT);
exit(-1);
}
// Store for reset(copy vinfo to vinfo_orig)
memcpy(&orig_vinfo, &vinfo, sizeof(struct fb_var_screeninfo));
// Change variable info
//vinfo.bits_per_pixel = 8;
// Change resolution
vinfo.xres = 640;
vinfo.yres = 400;
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo))
{
fprintf(stderr, "Error setting variable screen information (640x400x8).\n");
ioctl(termfd, KDSETMODE, KD_TEXT);
exit(-1);
}
// Get fixed screen information
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
{
fprintf(stderr, "Error reading fixed screen information.\n");
ioctl(termfd, KDSETMODE, KD_TEXT);
exit(-1);
}
// map fb to user mem
fb_ptr = (char*)mmap(0,
finfo.smem_len,
PROT_READ|PROT_WRITE,
MAP_SHARED,
fbfd,
0);
if ((int)fb_ptr == -1)
{
printf("Failed to mmap framebuffer.\n");
ioctl(termfd, KDSETMODE, KD_TEXT);
exit (-1);
}
g_screen_depth = vinfo.bits_per_pixel;
g_screen_mdepth = g_screen_depth;
if (g_screen_depth > 8)
g_screen_mdepth = 16;
if (g_screen_depth > 16)
g_screen_mdepth = 32;
pix_size = g_screen_mdepth / 8;
if (vinfo.bits_per_pixel > 8)
{
g_red_mask = (1 << vinfo.red.length) - 1;
g_green_mask = (1 << vinfo.green.length) - 1;
g_blue_mask = (1 << vinfo.blue.length) - 1;
g_red_left_shift = vinfo.red.offset;
g_green_left_shift = vinfo.green.offset;
g_blue_left_shift = vinfo.blue.offset;
g_red_right_shift = 8 - vinfo.red.length;
g_green_right_shift = 8 - vinfo.green.length;
g_blue_right_shift = 8 - vinfo.blue.length;
}
video_get_kimages();
if (g_screen_depth > 8)
video_get_kimage(&g_mainwin_kimage, 0, g_screen_depth, g_screen_mdepth);
for (i = 0; i < 256; i++)
{
video_update_color_raw(i, g_lores_colors[i & 0xf]);
g_a2palette_8to1624[i] = g_palette_8to1624[i];
}
fclose(stdin);
freopen("gsport.log", "w+", stdout);
freopen("gsport.err", "w+", stderr);
termio.c_cflag = /*BAUDRATE | CRTSCTS |*/ CS8 | CLOCAL | CREAD;
termio.c_iflag = IGNPAR;
termio.c_oflag = 0;
termio.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */
termio.c_cc[VTIME] = 0; /* inter-character timer unused */
termio.c_cc[VMIN] = 0; /* non-blocking read */
tcsetattr(termfd, TCSANOW, &termio);
// Open input event devices
for (evdevs = 0; evdevs < MAX_EVDEV; evdevs++)
{
sprintf(evdevname, "/dev/input/event%c", evdevs + '0');
if ((evfd[evdevs] = open(evdevname, O_RDONLY|O_NONBLOCK)) < 0)
break;
}
g_video_act_margin_left = 0;
g_video_act_margin_right = 1;
g_video_act_margin_top = 0;
g_video_act_margin_bottom = 0;
}
/*
* Colormap
*/
__u16 cmapred[256], cmapgreen[256], cmapblue[256];
int cmapstart, cmaplen, cmapdirty = 0;
void x_update_color(int col_num, int red, int green, int blue, word32 rgb)
{
cmapred[col_num] = red | (red << 8);
cmapgreen[col_num] = green | (green << 8);
cmapblue[col_num] = blue | (blue << 8);
if (cmapdirty == 0)
{
cmapstart = col_num;
cmaplen = 1;
cmapdirty = 1;
}
else
{
if (col_num < cmapstart)
{
cmaplen += cmapstart - col_num;
cmapstart = col_num;
}
else if (col_num > cmapstart + cmaplen)
cmaplen = col_num - cmapstart + 1;
}
}
void x_update_physical_colormap(void)
{
struct fb_cmap fbcol;
if (cmapdirty)
{
cmapdirty = 0;
fbcol.start = cmapstart;
fbcol.len = cmaplen;
fbcol.red = cmapred;
fbcol.green = cmapgreen;
fbcol.blue = cmapblue;
fbcol.transp = NULL;
ioctl(fbfd, FBIOPUTCMAP, &fbcol);
}
}
void show_xcolor_array(void)
{
}
/*
* Screen update
*/
void x_get_kimage(Kimage *kimage_ptr)
{
kimage_ptr->data_ptr = (byte *)malloc(kimage_ptr->width_req * kimage_ptr->height * kimage_ptr->mdepth / 8);
}
void x_release_kimage(Kimage* kimage_ptr)
{
if (kimage_ptr->data_ptr)
if (kimage_ptr->width_req != 640 || kimage_ptr->height != 400)
free(kimage_ptr->data_ptr);
kimage_ptr->data_ptr = NULL;
}
void x_push_kimage(Kimage *kimage_ptr, int destx, int desty, int srcx, int srcy, int width, int height)
{
byte *src_ptr, *dst_ptr;
// Copy sub-image to framebuffer
dst_ptr = (byte *)fb_ptr + desty * finfo.line_length + destx * pix_size;
src_ptr = kimage_ptr->data_ptr + (srcy * kimage_ptr->width_act + srcx) * pix_size;
width *= pix_size;
while (height--)
{
memcpy(dst_ptr, src_ptr, width);
dst_ptr += finfo.line_length;
src_ptr += kimage_ptr->width_act * pix_size;
}
}
void x_push_done(void)
{
}
/*
* NOP routines
*/
void x_dialog_create_gsport_conf(const char *str)
{
// Just write the config file already...
config_write_config_gsport_file();
}
int x_show_alert(int is_fatal, const char *str)
{
// Not implemented yet
adb_all_keys_up();
clear_fatal_logs();
return 0;
}
void x_toggle_status_lines(void)
{
}
void x_redraw_status_lines(void)
{
}
void x_hide_pointer(int do_hide)
{
}
void x_auto_repeat_on(int must)
{
}
void x_full_screen(int do_full)
{
}
int x_calc_ratio(float x, float y)
{
return 1;
}
void clipboard_paste(void)
{
}
int clipboard_get_char(void)
{
return 0;
}
/*
* Input handling
*/
void check_input_events(void)
{
struct input_event ev;
int i;
for (i = 0; i < evdevs; i++)
// Check input events
while (read(evfd[i], &ev, sizeof(struct input_event)) == sizeof(struct input_event))
{
if (ev.type == EV_REL)
{
if (ev.code == REL_X)
{
g_mouse_raw_x += ev.value;
if (g_mouse_raw_x < 0)
g_mouse_raw_x = 0;
if (g_mouse_raw_x > 639)
g_mouse_raw_x = 639;
}
else // REL_Y
{
g_mouse_raw_y += ev.value;
if (g_mouse_raw_y < 0)
g_mouse_raw_y = 0;
if (g_mouse_raw_y > 399)
g_mouse_raw_y = 399;
}
g_inputstate |= UPDATE_INPUT_MOUSE;
}
else if (ev.type == EV_KEY)
{
if (ev.code < 128)
{
#if 0
if ((ev.code == KEY_F10) && SHIFT_DOWN)
{
//quitEmulator();
iwm_shut();
xdriver_end();
my_exit(1);
}
#endif
if (keycode_to_a2code[ev.code] >= 0)
adb_physical_key_update(keycode_to_a2code[ev.code], !ev.value);
}
else if (ev.code == BTN_LEFT)
{
g_inputstate = ev.value ? UPDATE_INPUT_MOUSE | MOUSE_LBTN_DOWN
: UPDATE_INPUT_MOUSE | MOUSE_LBTN_UP;
}
}
else if (ev.type == EV_SYN)
{
if (g_inputstate & UPDATE_INPUT_MOUSE)
update_mouse(g_mouse_raw_x, g_mouse_raw_y, g_inputstate & MOUSE_BTN_ACTIVE, MOUSE_BTN_ACTIVE);
g_inputstate &= ~UPDATE_INPUT_MOUSE;
}
}
}
static void sig_bye(int signo)
{
xdriver_end();
exit (-1);
}
/*
* Application entrypoint
*/
int main(int argc,char *argv[])
{
if (signal(SIGINT, sig_bye) == SIG_ERR)
exit(-1);
if (signal(SIGHUP, sig_bye) == SIG_ERR)
exit(-1);
gsportmain(argc, argv);
xdriver_end();
return 0;
}

View File

@ -0,0 +1,240 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 - 2013 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define WIN32_LEAN_AND_MEAN /* Tell windows we want less header gunk */
#define STRICT /* Tell Windows we want compile type checks */
#include <windows.h>
#include <Shlwapi.h>
#include "winresource.h"
#include "defc.h"
#include "protos_windriver.h"
extern void gsportinit(HWND _hwnd);
extern void gsportshut();
extern HWND g_hwnd_main;
extern char *g_status_ptrs[MAX_STATUS_LINES];
extern int g_win_status_debug;
extern int g_win_status_debug_request;
extern int g_win_fullscreen_state;
int
win_nonblock_read_stdin(int fd, char *bufptr, int len)
{
DWORD charsRead = 0;
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), bufptr, len, &charsRead, NULL);
if (charsRead == 0)
{
errno = EAGAIN;
return -1;
}
else
{
DWORD charsWritten = 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), bufptr, charsRead, &charsWritten, NULL);
return charsRead;
}
}
void get_cwd(LPTSTR buffer, int size)
{
HMODULE hSelf;
hSelf = GetModuleHandle(NULL);
GetModuleFileName(hSelf,buffer,size);
PathRemoveFileSpec(buffer);
printf("Local directory: [%s]\n",buffer);
}
void
x_dialog_create_gsport_conf(const char *str)
{
// Just write the config file already...
config_write_config_gsport_file();
}
int
x_show_alert(int is_fatal, const char *str)
{
return 0;
}
void get_default_window_size(LPSIZE size)
{
// Calculate the window client dimensions.
RECT rect;
rect.left = 0;
rect.top = 0;
rect.bottom = X_A2_WINDOW_HEIGHT;
if (g_win_status_debug)
rect.bottom += (MAX_STATUS_LINES * 16);
rect.right = X_A2_WINDOW_WIDTH;
// Calculate the window rectangle, which is the client area plus non-client area (e.g. frame and caption).
AdjustWindowRect(&rect, WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE);
// Return the window size.
size->cx = rect.right - rect.left;
size->cy = rect.bottom - rect.top;
}
void x_toggle_status_lines()
{
SIZE size;
if (!g_win_fullscreen_state)
{
g_win_status_debug = !g_win_status_debug;
g_win_status_debug_request = g_win_status_debug;
get_default_window_size(&size);
SetWindowPos(g_hwnd_main, NULL, 0, 0, size.cx, size.cy, SWP_NOMOVE | SWP_NOZORDER);
x_redraw_status_lines();
}
}
void x_show_console(int show)
{
HWND hWnd = GetConsoleWindow();
if (hWnd)
ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
if (g_hwnd_main)
SetFocus(g_hwnd_main);
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
return main(0,0);
}
int
main(int argc, char **argv)
{
// Hide the console initially to reduce window flashing. We'll show the console later if needed.
x_show_console(0);
// Register the window class.
WNDCLASS wndclass;
SIZE size;
RECT rect;
wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC)win_event_handler;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = GetModuleHandle(NULL);
wndclass.hIcon = LoadIcon(wndclass.hInstance, MAKEINTRESOURCE(IDC_GSPORT32));
wndclass.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = "gsport";
if(!RegisterClass(&wndclass)) {
printf("Registering window failed\n");
exit(1);
}
// Create the window.
get_default_window_size(&size);
HWND hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, "gsport", "GSport - Apple //gs Emulator",
WS_TILED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
size.cx, size.cy,
NULL, NULL, GetModuleHandle(NULL), NULL);
printf("g_hwnd_main = %p, height = %d\n", hwnd, size.cx);
GetWindowRect(hwnd, &rect);
printf("...rect is: %ld, %ld, %ld, %ld\n", rect.left, rect.top,
rect.right, rect.bottom);
// Enable non-blocking, character-at-a-time console I/O.
// win_nonblock_read_stdin() expects this behavior.
DWORD mode;
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
mode &= ~ENABLE_LINE_INPUT;
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
gsportinit(hwnd);
int ret = gsportmain(argc, argv);
UnregisterClass(wndclass.lpszClassName,GetModuleHandle(NULL));
gsportshut();
return ret;
}
void x_check_input_events()
{
MSG msg;
while(PeekMessage(&msg, g_hwnd_main, 0, 0, PM_NOREMOVE)) {
if(GetMessage(&msg, g_hwnd_main, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
printf("GetMessage returned <= 0\n");
my_exit(2);
}
}
}
void
x_redraw_status_lines()
{
COLORREF oldtextcolor, oldbkcolor;
char *buf;
int line;
int len;
int height;
int margin;
height = 16;
margin = 0;
if (g_win_status_debug)
{
HDC localdc = GetDC(g_hwnd_main);
oldtextcolor = SetTextColor(localdc, RGB(255, 255, 255));
oldbkcolor = SetBkColor(localdc, RGB(0, 0, 0));
for(line = 0; line < MAX_STATUS_LINES; line++) {
buf = g_status_ptrs[line];
if(buf != 0) {
len = strlen(buf);
TextOut(localdc, 10, X_A2_WINDOW_HEIGHT +
height*line + margin, buf, len);
}
}
SetTextColor(localdc, oldtextcolor);
SetBkColor(localdc, oldbkcolor);
ReleaseDC(g_hwnd_main,localdc);
}
}
int
x_calc_ratio(float ratiox,float ratioy)
{
return 0; // not stretched
}

View File

@ -0,0 +1,20 @@
TARGET = gsportx
OBJECTS = $(OBJECTS1) xdriver.o
CC = cc
CCOPTS = -O
OPTS = -DNDEBUG
SUFFIX =
NAME = gsportx
LDFLAGS =
LDOPTS =
LD = $(CC)
EXTRA_LIBS = -lXext -lX11 -lc
EXTRA_SPECIALS =
AS = cc
PERL = perl
XOPTS = -I/usr/X11R6/include
XLIBS = -L/usr/X11R6/lib

View File

@ -0,0 +1,20 @@
TARGET = gsportx
OBJECTS = $(OBJECTS1) xdriver.o
CC = gcc
CCOPTS = -O
OPTS = -DNDEBUG -DSOLARIS -DGSPORT_LITTLE_ENDIAN -DSOLARISSOUND
SUFFIX =
NAME = gsportx
LDFLAGS =
LDOPTS =
LD = $(CC)
EXTRA_LIBS = -lXext -lX11 -lsocket -lnsl
EXTRA_SPECIALS =
AS = cc
PERL = perl
XOPTS = -I/usr/X/include
XLIBS = -L/usr/X/lib

View File

@ -0,0 +1,312 @@
/*
GSport - an Apple //gs Emulator
Copyright (C) 2010 - 2014 by GSport contributors
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
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 2 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, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Copyright (C) 2002-2004 The DOSBox Team
*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//#include <dosbox.h>
//#include "config.h"
#if !defined __PRINTER_H
#define __PRINTER_H
#ifdef __cplusplus
#ifdef C_LIBPNG
#include <png.h>
#endif
#include <stdio.h>
#ifdef HAVE_SDL
#include "SDL.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#endif // HAVE_SDL
#if defined (WIN32)
#include <windows.h>
#include <winspool.h>
#endif
#define STYLE_PROP 0x01
#define STYLE_CONDENSED 0x02
#define STYLE_BOLD 0x04
#define STYLE_DOUBLESTRIKE 0x08
#define STYLE_DOUBLEWIDTH 0x10
#define STYLE_ITALICS 0x20
#define STYLE_UNDERLINE 0x40
#define STYLE_SUPERSCRIPT 0x80
#define STYLE_SUBSCRIPT 0x100
#define STYLE_STRIKETHROUGH 0x200
#define STYLE_OVERSCORE 0x400
#define STYLE_DOUBLEWIDTHONELINE 0x800
#define STYLE_DOUBLEHEIGHT 0x1000
#define SCORE_NONE 0x00
#define SCORE_SINGLE 0x01
#define SCORE_DOUBLE 0x02
#define SCORE_SINGLEBROKEN 0x05
#define SCORE_DOUBLEBROKEN 0x06
#define QUALITY_DRAFT 0x01
#define QUALITY_LQ 0x02
#define COLOR_BLACK 7<<5
typedef unsigned Bitu;
typedef signed Bits;
typedef unsigned char Bit8u;
typedef signed char Bit8s;
typedef unsigned short Bit16u;
typedef signed short Bit16s;
typedef unsigned long Bit32u;
typedef signed long Bit32s;
typedef double Real64;
#if defined(_MSC_VER)
typedef unsigned __int64 Bit64u;
typedef signed __int64 Bit64s;
#else
typedef unsigned long long int Bit64u;
typedef signed long long int Bit64s;
#endif
enum Typeface
{
roman = 0,
sansserif,
courier,
prestige,
script,
ocrb,
ocra,
orator,
orators,
scriptc,
romant,
sansserifh,
svbusaba = 30,
svjittra = 31
};
typedef struct {
Bitu codepage;
const Bit16u* map;
} CHARMAP;
class CPrinter {
public:
CPrinter (Bit16u dpi, Bit16u width, Bit16u height, char* output, bool multipageOutput);
virtual ~CPrinter();
// Process one character sent to virtual printer
void printChar(Bit8u ch);
// Hard Reset (like switching printer off and on)
void resetPrinterHard();
// Set Autofeed value
void setAutofeed(bool feed);
// Get Autofeed value
bool getAutofeed();
// True if printer is unable to process more data right now (do not use printChar)
bool isBusy();
// True if the last sent character was received
bool ack();
// Manual formfeed
void formFeed();
#ifdef HAVE_SDL
// Returns true if the current page is blank
bool isBlank();
#endif // HAVE_SDL
private:
// Resets the printer to the factory settings
void resetPrinter();
// Clears page. If save is true, saves the current page to a bitmap
void newPage(bool save, bool resetx);
// Closes a multipage document
void finishMultipage();
// Output current page
void outputPage();
#ifdef HAVE_SDL
// used to fill the color "sub-pallettes"
void FillPalette(Bit8u redmax, Bit8u greenmax, Bit8u bluemax, Bit8u colorID,
SDL_Palette* pal);
// Checks if given char belongs to a command and process it. If false, the character
// should be printed
bool processCommandChar(Bit8u ch);
// Reload font. Must be called after changing dpi, style or cpi
void updateFont();
// Blits the given glyph on the page surface. If add is true, the values of bitmap are
// added to the values of the pixels in the page
void blitGlyph(FT_Bitmap bitmap, Bit16u destx, Bit16u desty, bool add);
// Draws an anti-aliased line from (fromx, y) to (tox, y). If broken is true, gaps are included
void drawLine(Bitu fromx, Bitu tox, Bitu y, bool broken);
// Setup the bitGraph structure
void setupBitImage(Bit8u dens, Bit16u numCols);
// Process a character that is part of bit image. Must be called iff bitGraph.remBytes > 0.
void printBitGraph(Bit8u ch);
// Copies the codepage mapping from the constant array to CurMap
void selectCodepage(Bit16u cp);
// Prints out a byte using ASCII85 encoding (only outputs something every four bytes). When b>255, closes the ASCII85 string
void fprintASCII85(FILE* f, Bit16u b);
// Returns value of the num-th pixel (couting left-right, top-down) in a safe way
Bit8u getPixel(Bit32u num);
FT_Library FTlib; // FreeType2 library used to render the characters
SDL_Surface* page; // Surface representing the current page
FT_Face curFont; // The font currently used to render characters
Bit8u color;
Real64 curX, curY; // Position of the print head (in inch)
Bit16u dpi; // dpi of the page
Bit16u ESCCmd; // ESC-command that is currently processed
bool ESCSeen; // True if last read character was an ESC (0x1B)
bool FSSeen; // True if last read character was an FS (0x1C) (IBM commands)
Bit8u numParam, neededParam; // Numbers of parameters already read/needed to process command
Bit8u params[20]; // Buffer for the read params
Bit16u style; // Style of font (see STYLE_* constants)
Real64 cpi, actcpi; // CPI value set by program and the actual one (taking in account font types)
Bit8u score; // Score for lines (see SCORE_* constants)
Real64 topMargin, bottomMargin, rightMargin, leftMargin; // Margins of the page (in inch)
Real64 pageWidth, pageHeight; // Size of page (in inch)
Real64 defaultPageWidth, defaultPageHeight; // Default size of page (in inch)
Real64 lineSpacing; // Size of one line (in inch)
Real64 horiztabs[32]; // Stores the set horizontal tabs (in inch)
Bit8u numHorizTabs; // Number of configured tabs
Real64 verttabs[16]; // Stores the set vertical tabs (in inch)
Bit8u numVertTabs; // Number of configured tabs
Bit8u curCharTable; // Currently used char table und charset
Bit8u printQuality; // Print quality (see QUALITY_* constants)
Typeface LQtypeFace; // Typeface used in LQ printing mode
Real64 extraIntraSpace; // Extra space between two characters (set by program, in inch)
bool charRead; // True if a character was read since the printer was last initialized
bool autoFeed; // True if a LF should automatically added after a CR
bool printUpperContr; // True if the upper command characters should be printed
struct bitGraphicParams // Holds information about printing bit images
{
Bit16u horizDens, vertDens; // Density of image to print (in dpi)
bool adjacent; // Print adjacent pixels? (ignored)
Bit8u bytesColumn; // Bytes per column
Bit16u remBytes; // Bytes left to read before image is done
Bit8u column[6]; // Bytes of the current and last column
Bit8u readBytesColumn; // Bytes read so far for the current column
} bitGraph;
Bit8u densk, densl, densy, densz; // Image density modes used in ESC K/L/Y/Z commands
Bit16u curMap[256]; // Currently used ASCII => Unicode mapping
Bit16u charTables[4]; // Charactertables
Real64 definedUnit; // Unit used by some ESC/P2 commands (negative => use default)
bool multipoint; // If multipoint mode is enabled
Real64 multiPointSize; // Point size of font in multipoint mode
Real64 multicpi; // CPI used in multipoint mode
Real64 hmi; // Horizontal motion index (in inch; overrides CPI settings)
Bit16u numPrintAsChar; // Number of bytes to print as characters (even when normally control codes)
#if defined (WIN32)
HDC printerDC; // Win32 printer device
#endif
#endif // HAVE_SDL
Bit8u msb; // MSB mode
char* output; // Output method selected by user
void* outputHandle; // If not null, additional pages will be appended to the given handle
bool multipageOutput; // If true, all pages are combined to one file/print job etc. until the "eject page" button is pressed
Bit16u multiPageCounter; // Current page (when printing multipages)
Bit8u ASCII85Buffer[4]; // Buffer used in ASCII85 encoding
Bit8u ASCII85BufferPos; // Position in ASCII85 encode buffer
Bit8u ASCII85CurCol; // Columns printed so far in the current lines
};
#endif
//Interfaces to C code
#ifdef __cplusplus
extern "C"
{
#else
#include <stdbool.h>
typedef unsigned char Bit8u;
#endif
void printer_init(int pdpi, int pwidth, int pheight, char* poutput, bool mpage);
void printer_loop(Bit8u pchar);
void printer_close();
void printer_feed();
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More