mirror of
https://github.com/digarok/gsplus.git
synced 2024-12-26 18:29:53 +00:00
initial commit
This commit is contained in:
commit
c3c2db5eb5
1
.svn/entries
Normal file
1
.svn/entries
Normal file
@ -0,0 +1 @@
|
||||
12
|
1
.svn/format
Normal file
1
.svn/format
Normal file
@ -0,0 +1 @@
|
||||
12
|
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
2747
.svn/pristine/01/0190f9cacdcea788a99a6b1a2cc5a79e7e8756f8.svn-base
Normal file
2747
.svn/pristine/01/0190f9cacdcea788a99a6b1a2cc5a79e7e8756f8.svn-base
Normal file
File diff suppressed because it is too large
Load Diff
3690
.svn/pristine/01/01e3186a4175a133c07354aef7060327cc3fc059.svn-base
Normal file
3690
.svn/pristine/01/01e3186a4175a133c07354aef7060327cc3fc059.svn-base
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,31 @@
|
||||
#!/usr/local/bin/perl -w
|
||||
|
||||
# $KmKId: make_inst,v 1.5 2002-11-07 08:18:16-08 kadickey Exp $
|
||||
|
||||
$is_c = shift;
|
||||
$repl = shift;
|
||||
|
||||
$count = 0;
|
||||
|
||||
while(<>) {
|
||||
$line = $_;
|
||||
if(/^inst(..)_SYM(.*)$/) {
|
||||
if($is_c eq "c") {
|
||||
if($count > 0) {
|
||||
printf("\tbreak;\n");
|
||||
}
|
||||
print "case 0x$1: $2\n";
|
||||
$count++;
|
||||
} else {
|
||||
print "\t.align\t8\n";
|
||||
print "inst" . "$1" . "_$repl" . "$2\n";
|
||||
}
|
||||
} elsif(/^(.*)_SYM(.*)$/) {
|
||||
print "$1" . "_$repl" . "$2\n";
|
||||
} else {
|
||||
print $line;
|
||||
}
|
||||
}
|
||||
# if(/^inst(..)_SYM (.*)$/) {
|
||||
# print "OPCODE($1) /* $2 */\n";
|
||||
# } else if(/^(
|
@ -0,0 +1,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
|
||||
|
||||
[]
|
@ -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")
|
@ -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")
|
@ -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
|
1417
.svn/pristine/0c/0cd133a7d03f17f2d60eed4203aff0c5c8341793.svn-base
Normal file
1417
.svn/pristine/0c/0cd133a7d03f17f2d60eed4203aff0c5c8341793.svn-base
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>152 85 356 240 0 0 1280 832 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>29</key>
|
||||
<string>69 252 182 44 0 0 1280 832 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>291.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6R73</string>
|
||||
<key>targetFramework</key>
|
||||
<string>IBCarbonFramework</string>
|
||||
</dict>
|
||||
</plist>
|
@ -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);
|
||||
|
2481
.svn/pristine/14/1408da0d0e94d5e5aa72beec8016b87cb340b17b.svn-base
Normal file
2481
.svn/pristine/14/1408da0d0e94d5e5aa72beec8016b87cb340b17b.svn-base
Normal file
File diff suppressed because it is too large
Load Diff
@ -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>
|
@ -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
|
||||
|
@ -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();
|
2605
.svn/pristine/16/168f48f79384fef9512b62b92360fc5cd0fee82e.svn-base
Normal file
2605
.svn/pristine/16/168f48f79384fef9512b62b92360fc5cd0fee82e.svn-base
Normal file
File diff suppressed because it is too large
Load Diff
@ -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 |
@ -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 }};
|
@ -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
|
||||
};
|
@ -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;
|
||||
}
|
@ -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
|
@ -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);
|
2075
.svn/pristine/1f/1fb8ac3a618f69519a244dd4c4aced112023c296.svn-base
Normal file
2075
.svn/pristine/1f/1fb8ac3a618f69519a244dd4c4aced112023c296.svn-base
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
|
||||
xdriver.c contains the routines for interfacing to X windows. The rest
|
||||
of KEGS interacts with X windows only through xdriver.c routines.
|
||||
|
||||
Externally called routines are:
|
||||
show_xcolor_array(): Debug routine, it does not need to do anything.
|
||||
dev_video_init(): Called at startup, it should open up the
|
||||
window and do other initialization.
|
||||
update_physical_colormap(): Updates the X windows palette with the colors
|
||||
from xcolor_a2vid_array[], which is maintained by
|
||||
other xdriver routines.
|
||||
update_status_line(): Call to update the internal array of chars
|
||||
representing the status lines at the bottom of
|
||||
the window. Does not draw the chars to the screen.
|
||||
xdriver_end(): Shutdown routine
|
||||
check_input_events(): Called up to 60 times a second (see video_update() in
|
||||
video.c) to handle any X window events and get
|
||||
keypresses.
|
||||
On a mouse press, call update_mouse() with the
|
||||
new x, y coordinates, and the status of the mouse
|
||||
button.
|
||||
If g_warp_pointer is set, constrain mouse within
|
||||
the window.
|
||||
On keypress, calls handle_keysym().
|
||||
handle_keysym(): Takes X keysym, and converts to the appropriate
|
||||
a2code using the a2_key_to_xsym[] lookup table.
|
||||
The a2codes are the Apple // ADB keycodes.
|
||||
Special work is done to handle shift and control
|
||||
properly since Apple only has one keycode for both
|
||||
shift and control keys. Then call
|
||||
adb_physical_key_update() with the a2 keycode and
|
||||
is_up = 1 if keyup, 0 = if key down.
|
||||
In addition, this routine handles all the Function
|
||||
keys doing special actions, which should be easy to
|
||||
port.
|
||||
x_refresh_ximage(): Redraws the window using the a2_line_* arrays.
|
||||
Described in more detail below.
|
||||
update_color_array(): Interface to the color map. Sets color[col_num]
|
||||
of the internal colormap array to a2_color.
|
||||
a2_color is the 12 bit apple color of the form:
|
||||
(red << 8) + (green << 4) + (blue).
|
||||
There are 16 palettes of 16 colors each, managed as
|
||||
one 256-color colormap. See discussion of
|
||||
g_a2vid_palette below.
|
||||
x_auto_repeat_on(): The X routines turn off key repeat when the cursor
|
||||
enters the graphics window automatically, and turn
|
||||
it back on when the cursor leaves. But if the
|
||||
debugger gets control due to a breakpoint, keyrepeat
|
||||
would be left off. So the debugger calls this
|
||||
routine to make sure key repeat is back on.
|
||||
redraw_status_lines(): Draw the status lines from the g_status_buf[][] array
|
||||
to the graphics window.
|
||||
|
||||
Externally referenced data:
|
||||
|
||||
g_use_shmem: Set by main() to enable/disable MIT-SHM for X.
|
||||
Also used by sound routines to auto-turn-off sound
|
||||
if not using MIT-SHM.
|
||||
|
||||
Bytes representing screen data:
|
||||
byte *data_text[2]: Array of bytes for the lores and text pages 1 and 2.
|
||||
Just 400*640 bytes.
|
||||
byte *data_hires[2]: Array of bytes for the hires pages 1 and 2.
|
||||
byte *data_superhires: Array of bytes for superhires screen.
|
||||
byte *data_border_sides: Array of bytes representing the border sides.
|
||||
Basically just A2_WINDOW_HEIGHT*EFF_BORDER_WIDTH bytes.
|
||||
byte *data_border_special: Top and bottom border bytes.
|
||||
(X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT + 2*8) *
|
||||
(X_A2_WINDOW_WIDTH) bytes.
|
||||
|
||||
Handles used for X windows drawing:
|
||||
XImage *ximage_hires[2]: Opaque handle to XImage object for hires page 1 and
|
||||
page 2.
|
||||
XImage *ximage_text[2]: Text pages 1 and 2.
|
||||
XImage *ximage_superhires: Superhires graphics XImage
|
||||
XImage *ximage_border_special: Top and bottom border XImage.
|
||||
XImage *ximage_border_sides: Left and right sides (only one copy, it is
|
||||
drawn at two different locations to be both sides).
|
||||
|
||||
Basic operation of xdriver:
|
||||
--------------------------
|
||||
|
||||
X windows can push arrays of bytes to the screen through structures
|
||||
called XImages. An XImage is a structure describing an offscreen bitmap.
|
||||
For efficiency of page flipping, KEGS maintains separate bitmaps for the
|
||||
two lores/text screens, the two hires screens, and the superhires screen.
|
||||
It also maintains bitmaps for the border. For MIT-SHM to work, X
|
||||
requires a unique XImage for each bitmap, and the bitmap must be allocated
|
||||
within xdriver.c since it must be obtained through an shmat() call.
|
||||
The X code also has non-MIT-SHM code which allocates the data_* buffers
|
||||
just through malloc().
|
||||
|
||||
All bitmaps are 8-bits of Pseudo-color. The color arrays are managed
|
||||
through the update_color_array() and update_physical_colormap() routines.
|
||||
KEGS manages all 256 colors in the colormap as 16 palettes of 16 colors.
|
||||
One of the palettes is reserved for the 16 lores colors, and is
|
||||
indicated by the variable g_a2vid_palette. It defaults to 0xe.
|
||||
Update_color_array() is called to update superhires colormap entries.
|
||||
Update_color_array must not update colors corresponding to g_a2vid_palette.
|
||||
Update_physical_colormap() pushes the color array managed by
|
||||
update_color_array() to the screen, but first forces the lores colors into
|
||||
the g_a2vid_palette palette. g_installed_full_superhires_colormap is
|
||||
always false in KEGS for now. video.c calls update_color_array and changes
|
||||
g_a2vid_palette. No xdriver routines gets notified when g_a2vid_palette
|
||||
changes, so update_physical_colormap must handle the case where
|
||||
g_a2vid_palette might have changed since it was last called.
|
||||
|
||||
x_redraw_ximage():
|
||||
Routines in video.c are free to draw into the corresponding data_*
|
||||
arrays to change any byte at any time. video.c manages remembering
|
||||
which lines need to be redrawn and which parts of the screen are in
|
||||
which video mode via the a2_line_* arrays.
|
||||
|
||||
KEGS divides the video screen up into 25 groups, corresponding to each
|
||||
text line. Each of these groups consists of 16 sublines. 25*8 = 400 lines.
|
||||
(video.c has already doubled the vertical resolution in all video modes).
|
||||
KEGS can allow any group to be from any of the five screens it manages:
|
||||
The two text/lores pages, the two hires pages, and the superhires screen.
|
||||
For each group, KEGS keeps track of what part of it needs to be redrawn.
|
||||
g_a2_screen_buffer_changed has a bit set for each group which has changed
|
||||
since the last call to x_redraw_ximage(). The rightmost bit (bit 0)
|
||||
corresponds to group 0. If g_a2_screen_buffer_changed == 0, no groups
|
||||
need to be redrawn. x_redraw_ximage clears out g_a2_screen_buffer_changed
|
||||
after drawing the screen.
|
||||
|
||||
For each group, a2_line_left_edge[] and a2_line_right_edge give the pixel
|
||||
offsets of what should be redrawn. a2_line_xim[] gives the ximage handle
|
||||
of what needs to be redrawn. KEGS always redraws 8 verticals of a group.
|
||||
g_full_refresh_needed also has one bit set in it for each group, which
|
||||
indicates overriding the a2_line_*_edge functions and redraw from 0 to
|
||||
640 pixels of each group that needs to be redrawn. x_redraw_ximage()
|
||||
interprets this information now using a simple algorithm: Skip over
|
||||
groups which have not changed (using g_a2_screen_buffer_changed).
|
||||
Save the ximage of this group, the left pixel and the right pixel.
|
||||
Continue with the next group if it has changed. Widen the pixel region
|
||||
and keep sucking up new groups to the same ximage. At group 25, or
|
||||
when the ximage changes, call x_refresh_lines to redraw this large
|
||||
rectangle from this ximage. x_refresh_lines() knows the ximage
|
||||
corresponding to the border for the last group has to be handled
|
||||
specially since the border group is not 640*400 pixels like the others.
|
||||
|
||||
Other porting info:
|
||||
a2_key_to_xsym[][3] contains the mapping function from X keysyms to
|
||||
a2 keycodes. The first element is the a2 keycode, the second element
|
||||
is the unshifted X keysym, and the third element is the shifted keysym.
|
||||
A port must make the conversion to a2 keycodes, and provide up and
|
||||
down events.
|
||||
|
@ -0,0 +1,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 */
|
||||
|
@ -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 */
|
||||
|
@ -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>
|
@ -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>
|
@ -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);
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#!/usr/local/bin/perl -w
|
||||
# $KmKId: make_size,v 1.3 2002-11-07 08:18:16-08 kadickey Exp $
|
||||
|
||||
$repl = shift;
|
||||
|
||||
while(<>) {
|
||||
$line = $_;
|
||||
if(/\.word inst(..)_SYM\+(.)(.*)$/) {
|
||||
if($repl eq "c") {
|
||||
print "\t0x$2, /* $1 */ $3\n";
|
||||
} elsif($repl eq "s") {
|
||||
print "\t.byte 0x$2, /* $1 */ $3\n";
|
||||
} else {
|
||||
print "\t.word\tinst$1" . "_$repl" . "\t/*$2*/ $3\n";
|
||||
}
|
||||
} elsif (/\.block.*$/) {
|
||||
if($repl eq "c") {
|
||||
print "\n";
|
||||
} elsif($repl eq "s") {
|
||||
print "\n";
|
||||
} else {
|
||||
print $line;
|
||||
}
|
||||
} else {
|
||||
print $line;
|
||||
}
|
||||
}
|
||||
# if(/^inst(..)_SYM (.*)$/) {
|
||||
# print "OPCODE($1) /* $2 */\n";
|
||||
# } else if(/^(
|
@ -0,0 +1,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;
|
||||
}
|
@ -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>
|
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
mvn site
|
@ -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!}}
|
@ -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
|
@ -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.
|
Binary file not shown.
@ -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();
|
@ -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>
|
@ -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.
|
@ -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 *);
|
@ -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
|
@ -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
|
@ -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 |
@ -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;
|
||||
}
|
@ -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
|
||||
---
|
@ -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);
|
@ -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
|
||||
};
|
Binary file not shown.
@ -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 |
@ -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 */
|
@ -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
|
@ -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
|
@ -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 |
Binary file not shown.
Binary file not shown.
@ -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
|
@ -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
|
@ -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;
|
||||
};
|
@ -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;
|
||||
}
|
@ -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>
|
@ -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
|
@ -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
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
[]
|
@ -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);
|
||||
}
|
||||
}
|
@ -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>
|
@ -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
|
@ -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
|
||||
|
@ -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 |
@ -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&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;
|
@ -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 ..\..
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
@ -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:
|
||||
*/
|
@ -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
|
@ -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, ¤t->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(ðer->source, &HW_LOCAL, sizeof(ether->source)) != 0) && /* Ignore packets sent from our node. */
|
||||
(memcmp(ðer->dest, &HW_LOCAL, sizeof(ether->dest)) == 0 || /* Accept packets destined for our node ... */
|
||||
memcmp(ðer->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, ðer->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();
|
||||
}
|
@ -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 */
|
||||
}
|
||||
}
|
@ -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*/
|
@ -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
|
@ -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);
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user