changeset 142:c0b31cf2c7cd trunk

[svn] Atari XL SAP. This compiles anything but cleanly, but somehow still works. No one will notice anyway, though. What percentage of the population listens to Atari XL music? I don't have an answer to that, but I'd guess that Audacious' SAP plugin will be used by approximately 2 people.
author asheldon
date Sun, 29 Oct 2006 01:08:30 -0700
parents 6d1f65117180
children e8f34254bc18
files ChangeLog src/sap/Makefile src/sap/doc/CHANGES src/sap/doc/COMPILATION src/sap/doc/CREDITS src/sap/doc/README src/sap/doc/README.audacious src/sap/doc/TODO src/sap/fileinfo.c src/sap/fileinfo.h src/sap/sap_plug.c src/sap/sap_plug.h src/sap/sapfile.c src/sap/sapfile.h src/sap/saplib/Makefile src/sap/saplib/legal.txt src/sap/saplib/pokey.png src/sap/saplib/pokey0.cpp src/sap/saplib/pokey1.cpp src/sap/saplib/pokeyNamespace.h src/sap/saplib/sapCpu.cpp src/sap/saplib/sapEngine.cpp src/sap/saplib/sapGlobals.h src/sap/saplib/sapLib.h src/sap/saplib/sapPokey.cpp src/sap/scripts/gen_symbols src/sap/syms src/sap/version.h
diffstat 28 files changed, 4548 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Oct 29 01:38:56 2006 -0700
+++ b/ChangeLog	Sun Oct 29 01:08:30 2006 -0700
@@ -1,3 +1,12 @@
+2006-10-29 08:38:56 +0000  Aaron Sheldon <asheldon@uiuc.edu>
+  revision [282]
+  The comment probably ought to say 'enable' since that's what the command 
+  does
+  
+  trunk/configure.ac |    2 +-
+  1 file changed, 1 insertion(+), 1 deletion(-)
+
+
 2006-10-29 08:23:08 +0000  William Pitcock <nenolod@nenolod.net>
   revision [280]
   - mplayer should be disabled by default due to the fact that it's only 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/Makefile	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,29 @@
+include ../../mk/rules.mk
+include ../../mk/init.mk
+
+OBJECTIVE_LIBS = libsapplug$(SHARED_SUFFIX)
+
+SAPLIB = saplib/pokey0.o saplib/pokey1.o saplib/sapCpu.o saplib/sapEngine.o saplib/sapPokey.o
+
+LINKER_FLAGS = -shared -Wl,-soname -Wl,$(TARGET) \
+	-Wl,-retain-symbols-file -Wl,syms
+
+TARGET = libsapplug.so
+
+LIBDIR = $(plugindir)/$(INPUT_PLUGIN_DIR) $(SAPLIB)
+
+LIBADD += $(GTK_LIBS)
+
+SOURCES = fileinfo.c sapfile.c sap_plug.c
+
+CFLAGS   += $(GTK_CFLAGS) $(LINKER_FLAGS) -I../../intl -I../..
+CXXFLAGS += $(GTK_CFLAGS) $(LINKER_FLAGS) -I../../intl -I../..
+
+OBJECTS = ${SOURCES:.c=.o} $(SAPLIB)
+
+all: library 
+
+library: 
+	cd saplib && make 
+
+include ../../mk/objective.mk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/doc/CHANGES	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,24 @@
+0.1  - first release (nothing works except "play" :))
+
+0.2  - added vis_plugin hooks (spectrum analyzer works now) ;-)
+     - some fixes 
+    
+0.3  - compiler optimizations
+     - Fixed some compiler warnings in saplib
+     - Makefile has install target now :)
+     - Made saplib-exported routines callable from within C code.
+     - No sapPlaySong on SAP load (sapEngine.cpp), caller should initialize song
+     - Corrected title display 
+     - Can skip to subsongs if they exist.
+     - File info box
+     - Can edit and write SAP tags 
+     - sourcetree reorganisation :)
+     - fixed compilation problems with gcc 3.x 
+     - should compile on FreeBSD
+
+0.3f - merged a fix from Miloslaw Smyk for a bug with Crossfade output plugin 
+       (song played twice as fast after some time, not seen using OSS output)
+       
+0.31 - fix for segfault crash with file info (ctrl+3)
+     - works on FreeBSD out of the box
+     
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/doc/COMPILATION	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,40 @@
+COMPILATION REQUIREMENTS
+------------------------
+
+To compile the plugin you need:
+
+ - gcc/g++ and at least libc6 2.1.x with POSIX pthreads 
+   and a linux or *BSD system
+
+     TESTED:
+     linux/x86 (gcc 2.95.2 and glibc 2.1.3) - compiles cleanly, works OK
+     linux/x86 (gcc 2.95.4 and glibc 2.2.5) - compiles cleanly, works OK
+     linux/alpha (gcc 3.2.2 and glibc 2.2.5) - compiles cleanly, works OK 
+
+ - xmms (of course :)), libxmms,libxmms-devel
+    
+     TESTED:
+     xmms 1.2.7 - OK
+     REPORTED:
+     xmms 1.2.8 - OK
+     
+ - gtk,gtk-devel, glib,glib-devel 
+    
+     TESTED:
+     gtk+ 1.2.10 glib 1.2.10 - OK
+     REPORTED
+     gtk+ 1.2.8 glib 1.2.8 - OK
+
+    
+COMPILATION INSTRUCTIONS
+------------------------
+
+NOTE: Since I cannot have access to as many platforms as linux runs on, I need the 
+information about copilation issues on different machines/oses/architectures. 
+Just compile it! If it fails drop me a line with info on your system, 
+compiler and glibc versions.
+If it compiles OK, and you use something different than the software / platform
+mentioned above as TESTED, I need the info even more. Please be helpful ;)
+
+To compile just do a 'make && make install' in the plugin source dir.
+That's it. Enjoy! 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/doc/CREDITS	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,16 @@
+AUTHORS
+-------
+Michal Szwaczko (mikey@scene.pl) 
+
+This plugin wouldn't be possible without the work of
+Adam 'SoTe' Bienias. Adam wrote saplib, a portable POKEY+6502 emulator library
+that is used extensively by the plugin. Thanks Adam!.
+
+CONTRIBUTORS
+------------
+Azbest (azbest@plasma.ath.cx) - bugreports, FTP space.
+Miloslaw Smyk (thorgal@wfmh.org.pl) - bugfix for Crossfade output plugin.
+Mattias Fenner (informix@web.de) - bugreports, XMMS pluginpack maintainer.
+Daniel Kozminski (dely@scene.pl) - media support :)
+
+[This space is for you]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/doc/README	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,43 @@
+SAPPLUG - an XMMS plugin for POKEY tunes
+----------------------------------------
+
+Sapplug is a POKEY tunes player plugin for X Multimedia System (xmms)
+This is a beta release, after first alpha versions seem to work fine.
+
+This, however means that it's still a work-in-progress software, some
+features are missing. If you find some bugs - firs look in TODO list 
+to check if I am already working on them, same with new features requests.
+
+!!! Check TODO before sending me hate-mail. !!!
+
+USAGE
+-----
+
+Just fire up xmms as you would normally and load some SAP tunes. 
+In case of not being able to play check in the preferences if 
+the plugin is installed and active!!! 
+Do not hesitate to mail me if you have problems compiling the plugin,
+hovewer, due to limited amount of time, I will not be able to answer any
+mail concerning general use of xmms or general plugin installation.
+Report problems with *compiling* or *using* *this* plugin !!!
+
+Some notes:
+
+The seekbar is used to switch subsongs within a multi-song SAP.
+Just click on it and the player plays next subsong!
+The number of songs in a SAP file is displayed in the main xmms window
+as X kHz (where X is the number of songs within the SAP file)
+This info is also available in the sapfile info box.
+
+File info box is brought up when you click "View file info" in XMMS :)
+It gives you general information about SAP file and presents so called
+SAP tag. It's a set of name, author and date of the song, similar to an mp3 tag.
+You can also edit this SAP tag, i.e. change author, name or date of the song.
+Click "Save" and the new tag gets written to the file. Also, you can remove 
+the tag from the SAPfile by clicking "Remove Tag" 
+
+Enjoy!!
+-- 
+mikey
+New Generation // WireLabs
+<mikey@scene.pl>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/doc/README.audacious	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,7 @@
+Audacious sapplug-xmms Port 0.31
+
+Copyright (c) 2006 Aaron Sheldon
+
+This is a port of sapplug-xmms, an atari SAP music player.
+
+Refer to the README for more information
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/doc/TODO	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,5 @@
+TODO list for SAP plugin.
+
+- Make plugin jump to next song in playlist when finished 
+- Seek within a song 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/fileinfo.c	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,328 @@
+/*
+ * SAP xmms plug-in. 
+ * Copyright 2002/2003 by Michal 'Mikey' Szwaczko <mikey@scene.pl>
+ *
+ * SAP Library ver. 1.56 by Adam Bienias
+ *
+ * This is free software. You can modify it and distribute it under the terms
+ * of the GNU General Public License. The verbatim text of the license can 
+ * be found in file named COPYING in the source directory.
+ *
+ * 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 THE AUTHORS 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.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <gtk/gtk.h>
+#include <audacious/util.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "version.h"
+#include "fileinfo.h"
+#include "saplib/sapLib.h"
+
+static void fail (gchar *error) {
+
+	gchar *errorstring;
+
+	    errorstring = g_strdup_printf("An error occured:\n%s", error);
+	    xmms_show_message("Error!",errorstring,	"Ok", FALSE, NULL, NULL);
+	    g_free(errorstring);
+	    return;
+}
+
+
+static void write_tag (GtkWidget *w , gpointer data) { 
+
+
+	gchar *author, *title, *date, *tmpfn, *original_filename;
+        FILE *outf; 
+	
+	int ofd;
+ 
+	/* tags taken from info_box (edited or not) */
+	author = gtk_entry_get_text(GTK_ENTRY(performer_entry));
+	title = gtk_entry_get_text(GTK_ENTRY(title_entry));
+	date = gtk_entry_get_text(GTK_ENTRY(date_entry));
+	original_filename = gtk_entry_get_text(GTK_ENTRY(filename_entry));
+ 
+	// prepare tmp file
+	tmpfn = g_strdup_printf("/tmp/sapplugXXXXXX");
+
+	if ((ofd = mkstemp( tmpfn )) < 0 ) {
+	
+		fail("Can't make tempfile");
+		g_free(tmpfn);
+		return;
+	
+	}
+
+	if ((outf = fdopen(ofd,"wb")) == NULL ) {
+
+		g_free(tmpfn);
+		fail("Cant write to file");
+		close(ofd);
+		return;
+	
+	}
+
+	/* start writing header */ 
+	
+	fprintf(outf,"SAP\r\n");
+
+	if (strlen(author) != 0) 
+	
+	    fprintf(outf, "AUTHOR \"%s\"\r\n",author);
+	
+	if (strlen(title) != 0) 
+	
+	    fprintf(outf,"NAME \"%s\"\r\n",title);
+	
+	if (strlen(date) != 0) 
+	
+	    fprintf(outf,"DATE \"%s\"\r\n",date);
+ 
+	/* save original songtype */
+	    
+	fprintf(outf,"TYPE %c\r\n",type_h);
+ 
+	/* save original TAGS */
+	
+	if (is_stereo == 1) 
+		
+	    fprintf(outf,"STEREO\r\n");
+
+	if (fastplay != -1) 
+	
+	    fprintf(outf,"FASTPLAY %d\r\n",fastplay);    
+
+	if (songs != -1) 
+	    
+	    fprintf(outf,"SONGS %d\r\n",songs);
+
+	if (defsong != -1)  
+	
+	    fprintf(outf,"DEFSONG %d\r\n",defsong);
+
+	if (ini_address != -1) 
+	
+	    fprintf(outf,"INIT %.4X\r\n",ini_address);
+
+	if (msx_address != -1) 
+	
+	    fprintf(outf,"MUSIC %.4X\r\n",msx_address);
+
+	if (plr_address != -1) 
+	
+	    fprintf(outf,"PLAYER %.4X\r\n",plr_address);
+	
+	/* header written - now append original SAP data */
+
+	fwrite(&buffer+headersize, 1, filesize-headersize,outf);
+	fclose(outf);
+	
+	/* and rename it */
+	if (rename(tmpfn,original_filename) < 0) {
+   
+		remove(tmpfn);
+		g_free(tmpfn);
+		fail("Failed to write!");
+		return;
+	}
+  
+	remove(tmpfn);
+	g_free(tmpfn);
+	gtk_widget_destroy(window);
+
+}
+
+static void remove_tag (void) {
+
+    gtk_entry_set_text(GTK_ENTRY(performer_entry),"");	
+    gtk_entry_set_text(GTK_ENTRY(title_entry),"");
+    gtk_entry_set_text(GTK_ENTRY(date_entry),"");
+
+}
+
+void sap_file_info_box(char *filename) {
+
+	gchar *tmp;
+	gchar *info_text;
+	
+	static GtkWidget *info_frame, *info_box, *sap_info_label;
+	static GtkWidget *tag_frame;
+
+	GtkWidget *hbox, *label, *filename_hbox, *vbox, *left_vbox;
+	GtkWidget *table, *bbox, *cancel_button;
+	GtkWidget *save_button, *remove_button;
+
+	
+	if (filename != NULL) {
+	
+	    /* dig info from the sapfile */
+	    if ((load_sap(filename)) < 0) return;		
+
+		if (!window) {
+
+		    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+		    gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
+		    gtk_signal_connect(GTK_OBJECT(window), "destroy", 
+				       GTK_SIGNAL_FUNC(gtk_widget_destroyed), &window);
+		    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+		    vbox = gtk_vbox_new(FALSE, 10);
+		    gtk_container_add(GTK_CONTAINER(window), vbox);
+
+		    filename_hbox = gtk_hbox_new(FALSE, 5);
+		    gtk_box_pack_start(GTK_BOX(vbox), filename_hbox, FALSE, TRUE, 0);
+		
+		    label = gtk_label_new("Filename:");
+		    gtk_box_pack_start(GTK_BOX(filename_hbox), label, FALSE, TRUE, 0);
+		    filename_entry = gtk_entry_new();
+		    gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE);
+		    gtk_box_pack_start(GTK_BOX(filename_hbox), filename_entry,TRUE, TRUE, 0);
+
+		    hbox = gtk_hbox_new(FALSE, 10);
+		    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+		
+		    left_vbox = gtk_vbox_new(FALSE, 10);
+		    gtk_box_pack_start(GTK_BOX(hbox), left_vbox, FALSE, FALSE, 0);
+
+		    tag_frame = gtk_frame_new("SAP Tag:");
+		    gtk_box_pack_start(GTK_BOX(left_vbox), tag_frame, FALSE, FALSE, 0);
+
+		    table = gtk_table_new(5, 5, FALSE);
+		    gtk_container_set_border_width(GTK_CONTAINER(table), 5);
+		    gtk_container_add(GTK_CONTAINER(tag_frame), table);
+		
+		    label = gtk_label_new("Title:");
+		    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+		    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
+				 GTK_FILL, GTK_FILL, 5, 5);
+		
+		    title_entry = gtk_entry_new();
+		    gtk_table_attach(GTK_TABLE(table), title_entry, 1, 4, 0, 1,
+				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+
+		    label = gtk_label_new("Artist:");
+		    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+		    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
+				 GTK_FILL, GTK_FILL, 5, 5);
+		
+		    performer_entry = gtk_entry_new();
+		    gtk_table_attach(GTK_TABLE(table), performer_entry, 1, 4, 1, 2,
+				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+
+		    label = gtk_label_new("Date:");
+		    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+		    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5,
+				 GTK_FILL, GTK_FILL, 5, 5);
+
+		    date_entry = gtk_entry_new();
+		    gtk_table_attach(GTK_TABLE(table), date_entry, 1, 2, 4, 5,
+				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
+				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
+		
+
+		    bbox = gtk_hbutton_box_new(); 
+		    gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox),
+					  GTK_BUTTONBOX_END);
+		    gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
+		    gtk_box_pack_start(GTK_BOX(left_vbox), bbox, FALSE, FALSE, 0);
+		
+		    save_button = gtk_button_new_with_label("Save");
+		    gtk_signal_connect(GTK_OBJECT(save_button), "clicked", 
+				   GTK_SIGNAL_FUNC(write_tag), NULL);
+		    
+		    GTK_WIDGET_SET_FLAGS(save_button, GTK_CAN_DEFAULT);
+		    
+		    gtk_box_pack_start(GTK_BOX(bbox), save_button, TRUE, TRUE, 0);
+		    gtk_widget_grab_default(save_button);
+
+		    remove_button = gtk_button_new_with_label("Remove Tag");
+		    gtk_signal_connect_object(GTK_OBJECT(remove_button),
+					  "clicked", 
+					  GTK_SIGNAL_FUNC(remove_tag), NULL);
+		
+		    GTK_WIDGET_SET_FLAGS(remove_button, GTK_CAN_DEFAULT);
+		    gtk_box_pack_start(GTK_BOX(bbox),remove_button, TRUE, TRUE, 0);
+
+		    cancel_button = gtk_button_new_with_label("Cancel");
+		    gtk_signal_connect_object(GTK_OBJECT(cancel_button),
+					  "clicked", 
+					  GTK_SIGNAL_FUNC(gtk_widget_destroy),
+					  GTK_OBJECT(window));
+		    GTK_WIDGET_SET_FLAGS(cancel_button, GTK_CAN_DEFAULT);
+		    gtk_box_pack_start(GTK_BOX(bbox),cancel_button, TRUE, TRUE, 0);
+
+		    /* info frame */
+		    info_frame = gtk_frame_new("SAP Info:");
+		    gtk_box_pack_start(GTK_BOX(hbox), info_frame, FALSE, FALSE, 0);
+
+		    info_box = gtk_vbox_new(FALSE, 5);
+		    gtk_container_add(GTK_CONTAINER(info_frame), info_box);
+		    gtk_container_set_border_width(GTK_CONTAINER(info_box), 5);
+		    gtk_box_set_spacing(GTK_BOX(info_box), 0);
+
+		    sap_info_label = gtk_label_new("");
+		    gtk_misc_set_alignment(GTK_MISC(sap_info_label), 0, 0);
+		    gtk_label_set_justify(GTK_LABEL(sap_info_label),
+				      GTK_JUSTIFY_LEFT);
+		    gtk_box_pack_start(GTK_BOX(info_box), sap_info_label, FALSE,
+				   FALSE, 0);
+		    /* end info frame */
+	
+		    gtk_widget_show_all(window);
+		    
+		} else
+		    
+		    gdk_window_raise(window->window);
+		    gtk_widget_set_sensitive(tag_frame, TRUE);	
+	
+		    /* window drawn and displayed ... now - the code 
+
+    		    clear up entries */
+		    remove_tag();
+
+		    /* show filename in the entrybox */
+		    gtk_entry_set_text(GTK_ENTRY(filename_entry),filename);
+		    /* and in the window title ... */
+		    tmp = g_strdup_printf("File Info - [%s]", g_basename(filename));
+		    gtk_window_set_title(GTK_WINDOW(window), tmp);
+
+		    /* fill up entries with what we dug out from the sapfile */
+		    gtk_entry_set_text(GTK_ENTRY(performer_entry),author);
+		    gtk_entry_set_position(GTK_ENTRY(performer_entry),0);	
+		    gtk_entry_set_text(GTK_ENTRY(title_entry),name);
+		    gtk_entry_set_position(GTK_ENTRY(title_entry),0);	
+		    gtk_entry_set_text(GTK_ENTRY(date_entry),date);
+		    gtk_entry_set_position(GTK_ENTRY(date_entry),0);
+		    /* fill in sap_info_frame; */
+		    info_text = g_strdup_printf(
+				"Type: %s\nStereo: %s\nSpeed: %d / Frame\nSongs: %d\n\nSize: %ld\n",
+				
+				    type,
+				    (is_stereo > 0) ? "Yes" : "No",
+				    times_per_frame,
+				    (songs > 0) ? songs : 1,
+				    filesize );
+
+		    gtk_label_set_text(GTK_LABEL(sap_info_label),info_text);
+
+		    /* cleanup */
+		    g_free(info_text);
+    		    g_free(tmp);
+
+        } 
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/fileinfo.h	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,43 @@
+/*
+ * SAP xmms plug-in. 
+ * Copyright 2002/2003 by Michal 'Mikey' Szwaczko <mikey@scene.pl>
+ *
+ * SAP Library ver. 1.56 by Adam Bienias
+ *
+ * This is free software. You can modify it and distribute it under the terms
+ * of the GNU General Public License. The verbatim text of the license can 
+ * be found in file named COPYING in the source directory.
+ *
+ * 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 THE AUTHORS 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.
+ *
+ */
+
+static GtkWidget *title_entry,  *performer_entry;
+static GtkWidget *date_entry;
+static GtkWidget *filename_entry;
+static GtkWidget *window = NULL;
+
+extern int load_sap (char *);
+extern unsigned char buffer;
+
+extern long filesize;
+extern int headersize;    
+extern char author[];
+extern char name[];
+extern char date[];
+extern int is_stereo;
+extern int fastplay;
+extern char type_h; /* type as seen in SAP header; */
+extern char type[]; /* type in ascii; */
+extern int plr_address;
+extern int msx_address;
+extern int ini_address;
+extern int songs;
+extern int defsong; 
+extern int times_per_frame;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/sap_plug.c	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,194 @@
+/*
+ * SAP xmms plug-in. 
+ * Copyright 2002/2003 by Michal 'Mikey' Szwaczko <mikey@scene.pl>
+ *
+ * SAP Library ver. 1.56 by Adam Bienias
+ *
+ * This is free software. You can modify it and distribute it under the terms
+ * of the GNU General Public License. The verbatim text of the license can 
+ * be found in file named COPYING in the source directory.
+ *
+ * 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 THE AUTHORS 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.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <audacious/util.h>
+#include <audacious/plugin.h>
+#include <glib.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "sap_plug.h"
+#include "version.h"
+
+InputPlugin sap_ip = {
+
+	NULL,
+	NULL,
+	"SAP Plugin " VERSION, 
+	NULL, 
+	sap_about, 
+	NULL,
+	sap_is_our_file,
+	NULL,
+	sap_play_file,
+	sap_stop,
+	sap_pause,
+	sap_seek,
+	NULL,
+	sap_get_time,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,  
+	sap_file_info_box, 
+	NULL
+};
+
+InputPlugin *get_iplugin_info (void) { 
+    return &sap_ip; 
+}
+
+static int sap_is_our_file (char *filename) {
+
+	char *ext;
+
+	ext = strrchr(filename, '.');
+	
+	if (ext)
+	{
+		if (!strcmp(ext, ".SAP"))
+			return 1;
+		if (!strcmp(ext, ".sap"))
+			return 1;
+	}
+
+	return 0;
+}
+
+static void *play_loop (void *arg) {
+
+	int datasize = N_RENDER << 2; 
+ 
+	while (going) {
+	
+	    sapRenderBuffer(play_buf,N_RENDER);
+	    /* for spectrum analyser */
+	    sap_ip.add_vis_pcm(sap_ip.output->written_time(), FMT_S16_NE, 2, N_RENDER, play_buf);
+	
+		while (sap_ip.output->buffer_free() < ( N_RENDER << 2 ) && going)
+		
+			xmms_usleep(30000);
+
+		if (going) 
+		
+			sap_ip.output->write_audio(play_buf, datasize);
+
+		
+	}
+	
+	sap_ip.output->buffer_free();
+	sap_ip.output->buffer_free();
+	pthread_exit(NULL);
+
+}
+		
+static void sap_play_file (char *filename) {
+	
+	GString *titstr;
+
+    	if ((currentFile = sapLoadMusicFile(filename)) == NULL) return;
+
+	/* for tunes */
+	tunes = currentFile->numOfSongs;
+
+	if (tunes < 0) tunes = 1;
+
+	/* we always start with 1st tune */
+	currentSong = 0;
+
+	sapPlaySong(currentSong);
+	
+ 	going = TRUE;
+	audio_error = FALSE;
+
+		if (sap_ip.output->open_audio(FMT_S16_LE, OUTPUT_FREQ, 2) == 0) {
+	
+			audio_error = TRUE;
+			going = FALSE;
+	
+			return;
+		}
+	/* delete '.sap' from filename to display */
+	titstr = g_string_new(g_basename(filename));
+	g_string_truncate(titstr,titstr->len - 4);
+
+	sap_ip.set_info(titstr->str, tunes, tunes*1024, OUTPUT_FREQ, 2);
+
+	g_string_free(titstr,TRUE);
+	
+	pthread_create(&play_thread, NULL, play_loop, NULL);
+	
+
+}
+
+static void sap_stop (void) {
+
+	if (going) {
+	
+		going = FALSE;
+		pthread_join(play_thread, NULL);
+		sap_ip.output->close_audio();
+	}
+}
+
+static void sap_seek(int time) {
+
+       if (currentSong != tunes) {          
+        
+		 currentSong = (currentSong+1) % currentFile->numOfSongs;
+		 sapPlaySong(currentSong);
+	         sap_ip.output->flush(currentSong * 1000);
+       
+       }
+}
+
+static void sap_pause(short paused) {
+
+    sap_ip.output->pause(paused);
+	
+}
+
+static int sap_get_time(void) {
+
+    return sap_ip.output->output_time();
+}
+
+static void sap_about (void) {
+
+	static GtkWidget *aboutbox;
+
+	if (aboutbox != NULL)
+		return;
+	
+	aboutbox = xmms_show_message(
+		"About SAP Plugin",
+		"SAP Player plug-in v"VERSION"\nby Michal Szwaczko <mikey@scene.pl>\n SAP library ver "SAP_VER" by Adam Bienias\n\n"
+		"Get more POKEY sound from ASMA at:\n[http://asma.musichall.cz]\n\nEnjoy!",
+		"Ok", FALSE, NULL, NULL);
+
+	gtk_signal_connect(GTK_OBJECT(aboutbox), "destroy",
+			   GTK_SIGNAL_FUNC(gtk_widget_destroyed), &aboutbox);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/sap_plug.h	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,47 @@
+/*
+ * SAP xmms plug-in. 
+ * Copyright 2002/2003 by Michal 'Mikey' Szwaczko <mikey@scene.pl>
+ *
+ * SAP Library ver. 1.56 by Adam Bienias
+ *
+ * This is free software. You can modify it and distribute it under the terms
+ * of the GNU General Public License. The verbatim text of the license can 
+ * be found in file named COPYING in the source directory.
+ *
+ * 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 THE AUTHORS 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.
+ *
+ */
+#include "saplib/sapLib.h"
+
+/* Default frequency */
+#define OUTPUT_FREQ 44100
+/* how many samples per one saprender() */
+#define N_RENDER 1024 
+
+/* functions */
+static int sap_is_our_file (char *);
+static void sap_play_file(gchar *);
+static void sap_stop(void);
+static void sap_pause(short);
+static void sap_seek(int);
+static int sap_get_time(void);
+static void sap_about(void);
+
+extern void sap_file_info_box(char *);
+
+static gboolean going;
+static gboolean audio_error;
+static pthread_t play_thread;
+
+int currentSong;
+static int tunes;
+
+sapMUSICstrc *currentFile;
+
+signed short play_buf[N_RENDER << 2];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/sapfile.c	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,364 @@
+/*
+ * SAP xmms plug-in. 
+ * Copyright 2002/2003 by Michal 'Mikey' Szwaczko <mikey@scene.pl>
+ *
+ * SAP Library ver. 1.56 by Adam Bienias
+ *
+ * This is free software. You can modify it and distribute it under the terms
+ * of the GNU General Public License. The verbatim text of the license can 
+ * be found in file named COPYING in the source directory.
+ *
+ * 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 THE AUTHORS 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.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "version.h"
+#include "sapfile.h"
+
+int load_sap (char *fname) {
+
+        struct stat st; 
+        int i, k;
+
+        FILE *f;
+
+	/* flush static buffers */
+
+        memset(author, 0, 2048);
+        memset(name, 0, 2048);
+        memset(date, 0, 2048);
+        memset(type, 0, 20);
+        
+        /* get filesize */
+
+        if (stat(fname, &st) < 0) 
+	    
+	    return -1;
+        
+	filesize = st.st_size;
+    
+        /* open & read file into buffer */
+
+        f = fopen(fname, "rb");
+
+        if ( !f ) 
+	    
+	    return -1;
+
+        fread(buffer, 1, filesize, f);
+	
+        fclose(f);
+    
+        /* check if it is a sap file */
+    
+        if (strncmp(buffer, "SAP", 3) != 0 ) 
+	    
+	    return -1;
+    
+        /* set headersize */
+    
+        for (i = 0; i < filesize; i++) {
+	
+	      if (buffer[i] == '\xFF' ) {
+	           
+	    	    headersize = i;
+	            break;
+    	      }
+	      
+    	      if (buffer[i] != '\xFF' && i == filesize-1) 
+	    
+		    return -1;
+       }
+     
+        /* sanity checking done - parse the info tags 
+           please someone rewrite this !!! :)
+	   this code sux0r ... */
+    
+        /* check for author */
+	
+        k = 0;
+	
+	for (i = 0;i < headersize; i++) {
+	
+	     if (strncmp(buffer + i, "AUTHOR", 6) == 0 )  { 
+	
+		    i = i + 8;
+
+    		    while (buffer[i] != '"' && buffer[i] != 0x0D && buffer[i] != 0x0A) {
+        
+			author[k] = buffer[i];
+		        k++; i++;
+                    }
+	    	    break;
+            }
+	    /* notfound */
+	    sprintf(author, "%s", "");
+        }
+    
+        /* check for name */
+	
+	k = 0;
+	
+        for (i = 0;i < headersize; i++) {
+	
+	     if ( strncmp(buffer + i, "NAME", 4) == 0 )  { 
+
+		    i = i + 6;
+		    
+    		    while (buffer[i] != '"' && buffer[i] != 0x0D && buffer[i] != 0x0A) {
+
+		        name[k] = buffer[i];
+		        k++; i++;
+    		    }
+		    break;
+             }
+	    /* notfound */
+	    sprintf(name, "%s", "");
+        }
+
+	/* check for date */
+	
+	k = 0;
+	
+        for(i = 0;i < headersize; i++) {
+	
+	     if (strncmp(buffer + i, "DATE", 4) == 0 )  {
+	      
+		    i = i + 6;
+
+	            while (buffer[i] != '"' && buffer[i] != 0x0D && buffer[i] != 0x0A) {
+        
+			date[k] = buffer[i];
+		        k++; i++;
+                    }
+		    break;
+             }
+	    /* notfound */
+	    sprintf(date, "%s", "");
+	}
+
+
+        /* check for stereo */
+	
+	for (i = 0; i < headersize; i++) {
+	
+	      if (strncmp(buffer + i, "STEREO", 6) == 0 )  { 
+
+			is_stereo = 1;
+			break;
+              }
+	    /* notfound */
+	    is_stereo = -1;
+	}
+
+        /* check fastplay; */
+	
+        for (i = 0; i < headersize; i++) {
+
+	      if (strncmp(buffer + i, "FASTPLAY", 8) == 0 )  { 
+
+			k = strtol(&buffer[i + 1 + 8], NULL, 10);
+
+			if ( k == 0 || k > 312 ) 
+			 
+			     /* illegal fastplay value */
+			     return -1;
+			
+			else 
+
+			     fastplay = k;
+
+				switch (k) {
+				
+				    case 156:
+		
+					  times_per_frame = 2;
+					  break;
+		    		    
+				    case 104:
+			                    
+				          times_per_frame = 3;
+			                  break;
+					  
+			            case 78:
+				    
+			                  times_per_frame = 4;
+					  break;
+					  
+			       }
+		break;
+              }
+	    /* notfound */
+	    fastplay = -1;
+	    times_per_frame = 1;
+        }
+
+        /* check songs */
+        for (i = 0; i < headersize; i++) {
+
+	      if (strncmp(buffer + i, "SONGS", 5) == 0)  { 
+
+			k = strtol(&buffer[i + 1 + 5], NULL, 10);
+
+			if ( (k == 0) || (k > 0xffff) ) 
+				 /* illegal songs value */
+				 return -1;
+			else 
+			
+				 songs = k;
+				 break;
+              }
+	    /* notfound */
+	    songs = -1;
+        }
+	
+        /* check defsong */
+        for (i = 0;i < headersize; i++) {
+
+	      if (strncmp(buffer + i, "DEFSONG", 7) == 0 )  { 
+
+			k = strtol(&buffer[i + 1 + 7], NULL, 10);
+
+			if ( (k < 0) || (k > 0xffff) ) 
+				 /* illegal defsong value */
+				 return -1;
+			
+			else 
+			
+				 defsong = k;
+				 break;
+              }
+	    /* notfound */
+	    defsong = -1;
+        }
+
+	
+	/* check songtype */
+        for (i = 0;i < headersize; i++) {
+
+	     if (strncmp(buffer + i, "TYPE", 4) == 0 )  { 
+
+		    i = i + 5;
+		   
+		    if (buffer[i] == 'B') {
+			      /* SAP documentation says
+			       "any player" */
+			      sprintf(type, "Standard");
+			      type_h = 'B';
+	    		      break;
+	            }
+	     
+	    	    if (buffer[i] == 'S') {
+	       
+	         	      sprintf(type, "SoftSynth");
+			      type_h = 'S';
+			      break;
+	    	    }
+		    
+	    	    if (buffer[i] == 'D') {
+		
+			      sprintf(type, "DigiSynth");
+			      type_h = 'D';
+			      break;
+	    	    }
+		    
+        	    if (buffer[i] == 'C') {
+		    
+			      sprintf(type, "CMC Synth");
+			      type_h= 'C';
+			      break;
+	            }
+		    
+		    if (buffer[i] == 'M') {
+			      /* unsupported (?) */
+			      sprintf(type, "M-Type");
+			      type_h = 'M';
+			      break;
+		    }	    	    
+		    
+		    if (buffer[i] == 'R') {
+			      /* this is unsupported - perhaps we */
+			      /* should return -1 as for now */
+			      sprintf(type, "Regs");
+			      type_h = 'R';
+			      break;
+	    	    }	     
+		/* unsupported songtype */
+		return -1;
+              }
+	/* no type specified */
+	if (i == headersize - 1) return -1;
+      
+      }
+
+        /* msx_address */
+        for (i = 0;i < headersize; i++) {
+
+	      if (strncmp(buffer + i, "MUSIC", 5) == 0 )  { 
+
+			k = strtol(&buffer[i + 1 + 5], NULL, 16);
+
+			if ( (k == 0) || (k > 0xffff) ) 
+				 /* illegal address */
+				 return -1;
+			else 
+			
+				 msx_address = k;
+				 break;
+              }
+	    /* notfound */
+	    msx_address = -1;
+        }
+
+         /* ini address */
+         for (i = 0;i < headersize; i++) {
+
+	      if (strncmp(buffer + i, "INIT", 4) == 0 )  { 
+
+			k = strtol(&buffer[i + 1 + 4], NULL, 16);
+
+			if ( (k == 0) || (k > 0xffff) ) 
+				 /* illegal address */
+				 return -1;
+			else 
+			
+				 ini_address = k;
+				 break;
+              }
+	    /* notfound */
+	    ini_address = -1;
+        }
+	 /* player */
+         for (i = 0; i < headersize; i++) {
+
+	      if (strncmp(buffer + i,"PLAYER", 6) == 0 )  { 
+
+			k = strtol(&buffer[i + 1 + 6], NULL, 16);
+
+			if ( (k == 0) || (k > 0xffff) ) 
+				 /* illegal */
+				 return -1;
+			else 
+			
+				 plr_address = k;
+				 break;
+              }
+	    /* notfound */
+	    plr_address = -1;
+        }
+
+     return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/sapfile.h	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,39 @@
+/*
+ * SAP xmms plug-in. 
+ * Copyright 2002/2003 by Michal 'Mikey' Szwaczko <mikey@scene.pl>
+ *
+ * SAP Library ver. 1.56 by Adam Bienias
+ *
+ * This is free software. You can modify it and distribute it under the terms
+ * of the GNU General Public License. The verbatim text of the license can 
+ * be found in file named COPYING in the source directory.
+ *
+ * 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 THE AUTHORS 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.
+ *
+ */
+
+char buffer[0x10000]; 
+
+char author[2048];
+char name[2048];
+char date[2048];
+char type[20]; /* type in ascii */
+char type_h; /* type as seen in SAP header; */
+
+long filesize;
+
+int headersize;    
+int is_stereo;
+int fastplay;
+int plr_address;
+int msx_address;
+int ini_address;
+int songs;
+int defsong; 
+int times_per_frame; /* times per frame */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/Makefile	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,14 @@
+CXX= g++ --no-exceptions 
+
+CXXFLAGS=-Wall -fPIC -fpic -O2 -ffast-math \
+	 -funroll-all-loops \
+	 -fno-strength-reduce -finline-functions \
+	 -fomit-frame-pointer 
+
+SRCS= pokey0.cpp pokey1.cpp sapCpu.cpp sapEngine.cpp sapPokey.cpp
+OBJS= pokey0.o pokey1.o sapCpu.o sapEngine.o sapPokey.o  
+
+all:$(OBJS)
+
+clean:
+	rm -f *.o core
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/legal.txt	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,11 @@
+
+   Disclaimer.
+ 
+I, Adam Bienias, author of the SAP Library, I'm not responsible
+for any kind of hardware or software damage caused by this library.
+Use it on your risk. SAP Library is distributed as FREEWARE but
+any changes in the library must be approved by me. If You use SAP
+Library in Your program, then You must include information about
+SAP library: "SAP Library ver.x.xx by Adam Bienias".
+
+ For contact send email to: adam@nautilus.com.pl
Binary file src/sap/saplib/pokey.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/pokey0.cpp	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,132 @@
+#include <ctype.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sapGlobals.h"
+
+#define NAMESPACENAME			POKEY0_NAMESPACE
+#define POKEY_INIT_FUNC			void pokeyInit0( void )
+#define POKEY_RESET_FUNC		void pokeyReset0( void )
+#define POKEY_UPDATESOUND_FUNC		void pokeyUpdateSound0( int n )
+#define POKEY_UPDATECOUNT_FUNC		void pokeyUpdateSoundCounters0( void )
+#define POKEY_WRITE_FUNC		void pokeyWriteByte0( short unsigned int address, BYTE value )
+#define POKEY_WRITE_2FUNC(a,v)		pokeyWriteByte0(a,v)
+
+#include "pokeyNamespace.h"
+
+bool *generateIRQ0 = &POKEY0_NAMESPACE::generateIRQ0;
+
+POKEY_WRITE_FUNC
+{
+	address&=0x0F;
+
+	switch( address )
+	{
+		case 0x00:
+			divideByN_Latch[0] = value;
+			SetupChannels01;
+			break;
+		case 0x01:
+			audioControl_Latch[0] = value;
+			audioControl_Latch2[0] = value&15;
+			audioControl_Latch_Digi[0] = (value>>4)&1 ? 15:0;
+			Channel0Distortion = channelsDistorionTable0[ (value>>4)&15 ];
+			if( !(value&0x10) )
+				SetupChannels01;
+			break;
+		case 0x02:
+			divideByN_Latch[1] = value;
+			SetupChannels01;
+			break;
+		case 0x03:
+			audioControl_Latch[1] = value;
+			audioControl_Latch2[1] = value&15;
+			audioControl_Latch_Digi[1] = (value>>4)&1 ? 15:0;
+			Channel1Distortion = channelsDistorionTable1[ (value>>4)&15 ];
+			if( !(value&0x10) )
+				SetupChannels01;
+			break;
+		case 0x04:
+			divideByN_Latch[2] = value;
+			SetupChannels23;
+			break;
+		case 0x05:
+			audioControl_Latch[2] = value;
+			audioControl_Latch2[2] = value&15;
+			audioControl_Latch_Digi[2] = (value>>4)&1 ? 15:0;
+			Channel2Distortion = channelsDistorionTable2[ (value>>4)&15 ];
+			if( !(value&0x10) )
+				SetupChannels23;
+			break;
+		case 0x06:
+			divideByN_Latch[3] = value;
+			SetupChannels23;
+			break;
+		case 0x07:
+			audioControl_Latch[3] = value;
+			audioControl_Latch2[3] = value&15;
+			audioControl_Latch_Digi[3] = (value>>4)&1 ? 15:0;
+			Channel3Distortion = channelsDistorionTable3[ (value>>4)&15 ];
+			if( !(value&0x10) )
+				SetupChannels23;
+			break;
+		case 0x08:
+		{
+			BYTE prevAUDCTL;
+			prevAUDCTL = AUDCTL;
+			AUDCTL = value;
+			pcc1564 = value & 1 ? 112:28;
+
+			noiseAND = AUDCTL & 128 ? 0x1FF:0x1FFFF;
+
+			switch_J3_Q_stateAND[0] = AUDCTL&4 ? 15:0;
+			switch_J3_Q_stateAND[1] = AUDCTL&2 ? 15:0;
+
+			SetupChannels01;
+			SetupChannels23;
+
+			if( (prevAUDCTL^AUDCTL)&0x10 )
+				divideByN[1] = 2;
+			if( (prevAUDCTL^AUDCTL)&0x8 )
+				divideByN[3] = 2;
+
+			break;
+		}
+		case 0x0D:
+			break;
+		case 0x0E:
+			// najpierw czyscimy status przerwan IRQ_ST. Tam gdzie we wpisywanej wartosci jest 0,
+			// status tego przerwania jest zerowany
+			IRQ_ST = IRQ_ST&value;
+			IRQ_EN = value;
+			// teraz sprawdzamy czy musimy ustawic linie IRQ
+			IRQ_line = ((IRQ_ST&IRQ_EN)!=0x00) ? 0x01:0x00;
+			break;
+		case 0x0F:
+			break;
+	}
+}
+
+void pokeyGenerateCheckIRQline( void )
+{
+	if( ((cpuFlag_I&1)==0) && IRQ_line )
+	{
+		BYTE fl,lsb,msb;
+		atariMem[0x100 + cpuReg_S] = (cpuReg_PC>>8)&0xFF; cpuReg_S--;
+		atariMem[0x100 + cpuReg_S] = cpuReg_PC&0xFF; cpuReg_S--;
+		atariMem[0x100 + cpuReg_S] = fl = cpuGetFlags(); cpuReg_S--;
+		lsb = atariMem[0xFFFE]; msb = atariMem[0xFFFF];
+		cpuReg_PC = ((WORD)lsb) + ((WORD)msb)*256;
+	}
+}
+
+void pokeyGenerateIRQ( BYTE irqMask )
+{
+	IRQ_ST |= irqMask;
+	IRQ_line = ((IRQ_ST&IRQ_EN)!=0x00) ? 0x01:0x00;
+	pokeyGenerateCheckIRQline();
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/pokey1.cpp	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,102 @@
+#include <ctype.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sapGlobals.h"
+
+#define NAMESPACENAME			POKEY1_NAMESPACE
+#define POKEY_INIT_FUNC			void pokeyInit1( void )
+#define POKEY_RESET_FUNC		void pokeyReset1( void )
+#define POKEY_UPDATESOUND_FUNC		void pokeyUpdateSound1( int n )
+#define POKEY_UPDATECOUNT_FUNC		void pokeyUpdateSoundCounters1( void )
+#define POKEY_WRITE_FUNC		void pokeyWriteByte1( short unsigned int address, BYTE value )
+#define POKEY_WRITE_2FUNC(a,v)		pokeyWriteByte1(a,v)
+
+#include "pokeyNamespace.h"
+
+POKEY_WRITE_FUNC
+{
+	address&=0x0F;
+
+	switch( address )
+	{
+		case 0x00:
+			divideByN_Latch[0] = value;
+			SetupChannels01;
+			break;
+		case 0x01:
+			audioControl_Latch[0] = value;
+			audioControl_Latch2[0] = value&15;
+			audioControl_Latch_Digi[0] = (value>>4)&1 ? 15:0;
+			Channel0Distortion = channelsDistorionTable0[ (value>>4)&15 ];
+			if( !(value&0x10) )
+				SetupChannels01;
+			break;
+		case 0x02:
+			divideByN_Latch[1] = value;
+			SetupChannels01;
+			break;
+		case 0x03:
+			audioControl_Latch[1] = value;
+			audioControl_Latch2[1] = value&15;
+			audioControl_Latch_Digi[1] = (value>>4)&1 ? 15:0;
+			Channel1Distortion = channelsDistorionTable1[ (value>>4)&15 ];
+			if( !(value&0x10) )
+				SetupChannels01;
+			break;
+		case 0x04:
+			divideByN_Latch[2] = value;
+			SetupChannels23;
+			break;
+		case 0x05:
+			audioControl_Latch[2] = value;
+			audioControl_Latch2[2] = value&15;
+			audioControl_Latch_Digi[2] = (value>>4)&1 ? 15:0;
+			Channel2Distortion = channelsDistorionTable2[ (value>>4)&15 ];
+			if( !(value&0x10) )
+				SetupChannels23;
+			break;
+		case 0x06:
+			divideByN_Latch[3] = value;
+			SetupChannels23;
+			break;
+		case 0x07:
+			audioControl_Latch[3] = value;
+			audioControl_Latch2[3] = value&15;
+			audioControl_Latch_Digi[3] = (value>>4)&1 ? 15:0;
+			Channel3Distortion = channelsDistorionTable3[ (value>>4)&15 ];
+			if( !(value&0x10) )
+				SetupChannels23;
+			break;
+		case 0x08:
+		{
+			BYTE prevAUDCTL;
+			prevAUDCTL = AUDCTL;
+			AUDCTL = value;
+			pcc1564 = value & 1 ? 112:28;
+
+			noiseAND = AUDCTL & 128 ? 0x1FF:0x1FFFF;
+
+			switch_J3_Q_stateAND[0] = AUDCTL&4 ? 15:0;
+			switch_J3_Q_stateAND[1] = AUDCTL&2 ? 15:0;
+
+			SetupChannels01;
+			SetupChannels23;
+
+			if( (prevAUDCTL^AUDCTL)&0x10 )
+				divideByN[1] = 2;
+			if( (prevAUDCTL^AUDCTL)&0x8 )
+				divideByN[3] = 2;
+
+			break;
+		}
+		case 0x0D:
+			break;
+		case 0x0E:
+			break;
+		case 0x0F:
+			break;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/pokeyNamespace.h	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,665 @@
+// This is very funny piece of code :)). This is a "fake" pokey template.
+
+namespace NAMESPACENAME {
+
+BYTE IRQ_EN;
+BYTE IRQ_ST;
+BYTE IRQ_line;
+bool generateIRQ0;
+
+const double cutFreq = 24000.0 / 44100.0; // cutoff frequency = 20000, sampling frequency = 44100
+const int samplerRate = 0x2836D6; // (1773447 / 44100) * 65536;
+const int samplerRateOver = 0xA0DB5/2; // (1773447 / 176400) * 65536;
+
+//const double cutFreq2 = 26000.0 / 1773447.0; // cutoff frequency = 20000, sampling frequency = 44100
+const double cutFreq2 = 28000.0 / 176400; // cutoff frequency = 20000, sampling frequency = 44100
+
+const int cutFreq2i = 650;
+
+#define MAKESAMPLE\
+	{\
+		ss-=0x10000;\
+		if( ss<0 )\
+		{\
+			ss += samplerRateOver;\
+			DWORD pomd; int pomi;\
+			pomd  = ((DWORD*)&switch_J3_Q_state[0])[0];\
+			pomd &= ((DWORD*)&switch_J3_Q_stateAND[0])[0];\
+			pomd ^= ((DWORD*)&signal_state_out[0])[0];\
+			pomd &= ((DWORD*)&freq_sequre[0])[0];\
+			pomd |= ((DWORD*)&audioControl_Latch_Digi[0])[0];\
+			pomd &= ((DWORD*)&audioControl_Latch2[0])[0];\
+			pomd = pomd + (pomd>>16);\
+			pomi = (int)( pomd + (pomd>>8) ) & 255;\
+			oldValI = oldValI + ((cutFreq2i*((pomi<<12) - oldValI))>>12);\
+			delay++; if( (delay&7)==0 )\
+			{\
+				pomi = oldValI>>3;\
+				if( pomi<-16384 ) pomi = -16384; else if( pomi>32767 ) pomi = 32767;\
+				sndBuf[sndBufPtr] = (WORD)pomi;\
+				sndBufPtr = (sndBufPtr+sampleStep)&16383;\
+			}\
+		}\
+	}
+
+int sndBufPtrUpp;
+
+int oldValI = 0;
+double oldVal=0.0;
+int delay = 0;
+
+BYTE AUDCTL;
+int pcc1564,noiseAND,pokeyClockCounter64k;
+
+DWORD pokeyClockCounter;
+DWORD poly4Counter,poly5Counter,poly4_5Counter;
+
+BYTE poly17[0x20000];
+BYTE poly4_b[36000]; // minimum size is 312*114+15
+BYTE poly5_b[36000]; // minimum size is 312*114+31
+BYTE poly4_5_b[37000]; // minimum size is 312*114+465
+
+BYTE poly4[15] = {
+15, 15, 15, 15, 0, 0, 0, 15, 0, 0, 15, 15, 0, 15, 0
+};
+
+BYTE poly5[31] = {
+15, 15, 15, 15, 0, 15, 15, 0, 15, 0, 0, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, 0, 0, 15, 0, 0, 0, 15, 0, 15, 0
+};
+
+int divideByN[4];
+int divideByN_Latch[4];
+int divideByN_Latch2[4];
+BYTE switch_J2_signal_Q[4];
+BYTE signal_state_out[4];
+BYTE switch_J3_Q_state[4];
+BYTE switch_J3_Q_stateAND[4];
+BYTE audioControl_Latch[4];
+BYTE audioControl_Latch2[4];
+BYTE audioControl_Latch_Digi[4];
+BYTE freq_sequre[4];
+
+void (*Channel0Distortion)(void);
+void (*Channel1Distortion)(void);
+void (*Channel2Distortion)(void);
+void (*Channel3Distortion)(void);
+
+//---
+void channel0_0( void )
+{
+	if( poly5_b[ poly5Counter + pokeyClockCounter ]!=0 )
+		signal_state_out[0] = poly17[ pokeyClockCounter & noiseAND ];
+}
+void channel0_2( void )
+{
+	signal_state_out[0] = signal_state_out[0] ^ poly5_b[ poly5Counter + pokeyClockCounter ];
+}
+void channel0_4( void )
+{
+	if( poly5_b[ poly5Counter + pokeyClockCounter ]!=0 )
+		signal_state_out[0] = poly4_b[ poly4Counter + pokeyClockCounter ];
+}
+void channel0_8( void )
+{
+	signal_state_out[0] = poly17[ pokeyClockCounter & noiseAND ];
+}
+void channel0_A( void )
+{
+	signal_state_out[0] = signal_state_out[0] ^ 15;
+}
+void channel0_C( void )
+{
+	signal_state_out[0] = poly4_b[ pokeyClockCounter + poly4Counter ];
+}
+//---
+void channel1_0( void )
+{
+	if( poly5_b[ poly5Counter + pokeyClockCounter ]!=0 )
+		signal_state_out[1] = poly17[ pokeyClockCounter & noiseAND ];
+}
+void channel1_2( void )
+{
+	signal_state_out[1] = signal_state_out[1] ^ poly5_b[ poly5Counter + pokeyClockCounter ];
+}
+void channel1_4( void )
+{
+	if( poly5_b[ poly5Counter + pokeyClockCounter ]!=0 )
+		signal_state_out[1] = poly4_b[ poly4Counter + pokeyClockCounter ];
+}
+void channel1_8( void )
+{
+	signal_state_out[1] = poly17[ pokeyClockCounter & noiseAND ];
+}
+void channel1_A( void )
+{
+	signal_state_out[1] = signal_state_out[1] ^ 15;
+}
+void channel1_C( void )
+{
+	signal_state_out[1] = poly4_b[ pokeyClockCounter + poly4Counter ];
+}
+//---
+void channel2_0( void )
+{
+	if( poly5_b[ poly5Counter + pokeyClockCounter ]!=0 )
+		signal_state_out[2] = poly17[ pokeyClockCounter & noiseAND ];
+}
+void channel2_2( void )
+{
+	signal_state_out[2] = signal_state_out[2] ^ poly5_b[ poly5Counter + pokeyClockCounter ];
+}
+void channel2_4( void )
+{
+	if( poly5_b[ poly5Counter + pokeyClockCounter ]!=0 )
+		signal_state_out[2] = poly4_b[ poly4Counter + pokeyClockCounter ];
+}
+void channel2_8( void )
+{
+	signal_state_out[2] = poly17[ pokeyClockCounter & noiseAND ];
+}
+void channel2_A( void )
+{
+	signal_state_out[2] = signal_state_out[2] ^ 15;
+}
+void channel2_C( void )
+{
+	signal_state_out[2] = poly4_b[ pokeyClockCounter + poly4Counter ];
+}
+//---
+void channel3_0( void )
+{
+	if( poly5_b[ poly5Counter + pokeyClockCounter ]!=0 )
+		signal_state_out[3] = poly17[ pokeyClockCounter & noiseAND ];
+}
+void channel3_2( void )
+{
+	signal_state_out[3] = signal_state_out[3] ^ poly5_b[ poly5Counter + pokeyClockCounter ];
+}
+void channel3_4( void )
+{
+	if( poly5_b[ poly5Counter + pokeyClockCounter ]!=0 )
+		signal_state_out[3] = poly4_b[ poly4Counter + pokeyClockCounter ];
+}
+void channel3_8( void )
+{
+	signal_state_out[3] = poly17[ pokeyClockCounter & noiseAND ];
+}
+void channel3_A( void )
+{
+	signal_state_out[3] = signal_state_out[3] ^ 15;
+}
+void channel3_C( void )
+{
+	signal_state_out[3] = poly4_b[ pokeyClockCounter + poly4Counter ];
+}
+
+void channel0_1( void )
+{
+	signal_state_out[0] = 15;
+}
+void channel1_1( void )
+{
+	signal_state_out[1] = 15;
+}
+void channel2_1( void )
+{
+	signal_state_out[2] = 15;
+}
+void channel3_1( void )
+{
+	signal_state_out[3] = 15;
+}
+
+typedef void (*funcPoint)(void);
+funcPoint channelsDistorionTable0[16]=
+	{ &channel0_0, &channel0_1, &channel0_2, &channel0_1, &channel0_4, &channel0_1, &channel0_2, &channel0_1, &channel0_8, &channel0_1, &channel0_A, &channel0_1, &channel0_C, &channel0_1, &channel0_A, &channel0_1 };
+funcPoint channelsDistorionTable1[16]=
+	{ &channel1_0, &channel1_1, &channel1_2, &channel1_1, &channel1_4, &channel1_1, &channel1_2, &channel1_1, &channel1_8, &channel1_1, &channel1_A, &channel1_1, &channel1_C, &channel1_1, &channel1_A, &channel1_1 };
+funcPoint channelsDistorionTable2[16]=
+	{ &channel2_0, &channel2_1, &channel2_2, &channel2_1, &channel2_4, &channel2_1, &channel2_2, &channel2_1, &channel2_8, &channel2_1, &channel2_A, &channel2_1, &channel2_C, &channel2_1, &channel2_A, &channel2_1 };
+funcPoint channelsDistorionTable3[16]=
+	{ &channel3_0, &channel3_1, &channel3_2, &channel3_1, &channel3_4, &channel3_1, &channel3_2, &channel3_1, &channel3_8, &channel3_1, &channel3_A, &channel3_1, &channel3_C, &channel3_1, &channel3_A, &channel3_1 };
+
+void pus_zero( int n )
+{
+unsigned int i;
+unsigned int ch;
+DWORD pp;
+int ss;
+
+	pp = pokeyClockCounter + (pcc1564 - pokeyClockCounter64k);
+	ss = sndBufPtrUpp; 
+
+	i = n;
+	do
+	{
+		pokeyClockCounter++;
+		if( pokeyClockCounter>=pp )
+		{
+			pp = pokeyClockCounter + pcc1564;
+			ch = 0; { if( --divideByN[ch]==0 ) { generateIRQ0=true; divideByN[ch] = divideByN_Latch2[ch]; Channel0Distortion(); } }
+			ch = 1; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel1Distortion(); } }
+			ch = 2; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel2Distortion(); switch_J3_Q_state[0] = signal_state_out[0]; } }
+			ch = 3; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel3Distortion(); switch_J3_Q_state[1] = signal_state_out[1]; } }
+		}
+		MAKESAMPLE
+	} while(--i);
+	sndBufPtrUpp = ss;
+	pokeyClockCounter64k = pcc1564 + pokeyClockCounter - pp ;
+
+}
+
+void pus_2h( int n )
+{
+unsigned int i;
+unsigned int ch;
+DWORD pp; int ss;
+
+	pp = pokeyClockCounter + (pcc1564 - pokeyClockCounter64k);
+	ss = sndBufPtrUpp; 
+	i = n;
+	do
+	{
+		pokeyClockCounter++;
+		if( pokeyClockCounter>=pp )
+		{
+			pp = pokeyClockCounter + pcc1564;
+			ch = 0; { if( --divideByN[ch]==0 ) { generateIRQ0=true; divideByN[ch] = divideByN_Latch2[ch]; Channel0Distortion(); } }
+			ch = 1; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel1Distortion(); } }
+			ch = 3; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel3Distortion(); switch_J3_Q_state[1] = signal_state_out[1]; } }
+		}
+		ch = 2; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel2Distortion(); switch_J3_Q_state[0] = signal_state_out[0]; } }
+		MAKESAMPLE
+	} while(--i);
+	sndBufPtrUpp = ss;
+	pokeyClockCounter64k = pcc1564 + pokeyClockCounter - pp ;
+}
+
+void pus_23h( int n )
+{
+unsigned int i;
+unsigned int ch;
+DWORD pp; 
+int ss;
+
+	pp = pokeyClockCounter + (pcc1564 - pokeyClockCounter64k);
+	ss = sndBufPtrUpp; 
+	i = n;
+	do
+	{
+		pokeyClockCounter++;
+		if( pokeyClockCounter>=pp )
+		{
+			pp = pokeyClockCounter + pcc1564;
+			ch = 0; { if( --divideByN[ch]==0 ) { generateIRQ0=true; divideByN[ch] = divideByN_Latch2[ch]; Channel0Distortion(); } }
+			ch = 1; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel1Distortion(); } }
+		}
+		ch = 2; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel2Distortion(); switch_J3_Q_state[0] = signal_state_out[0]; } }
+		ch = 3; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel3Distortion(); switch_J3_Q_state[1] = signal_state_out[1]; } }
+		MAKESAMPLE
+	} while(--i);
+	sndBufPtrUpp = ss;
+	pokeyClockCounter64k = pcc1564 + pokeyClockCounter - pp ;
+}
+
+void pus_0h( int n )
+{
+unsigned int i;
+unsigned int ch;
+DWORD pp;
+int ss;
+
+	pp = pokeyClockCounter + (pcc1564 - pokeyClockCounter64k);
+	ss = sndBufPtrUpp; 
+	i = n;
+	do
+	{
+		pokeyClockCounter++;
+		ch = 0; { if( --divideByN[ch]==0 ) { generateIRQ0=true; divideByN[ch] = divideByN_Latch2[ch]; Channel0Distortion(); } }
+		if( pokeyClockCounter>=pp )
+		{
+			pp = pokeyClockCounter + pcc1564;
+			ch = 1; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel1Distortion(); } }
+			ch = 2; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel2Distortion(); switch_J3_Q_state[0] = signal_state_out[0]; } }
+			ch = 3; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel3Distortion(); switch_J3_Q_state[1] = signal_state_out[1]; } }
+		}
+		MAKESAMPLE
+	} while(--i);
+	sndBufPtrUpp = ss;
+	pokeyClockCounter64k = pcc1564 + pokeyClockCounter - pp ;
+}
+
+void pus_01h( int n )
+{
+unsigned int i;
+unsigned int ch;
+DWORD  pp;
+int ss;
+
+	pp = pokeyClockCounter + (pcc1564 - pokeyClockCounter64k);
+	ss = sndBufPtrUpp; 
+	i = n;
+	do
+	{
+		pokeyClockCounter++;
+		ch = 0; { if( --divideByN[ch]==0 ) { generateIRQ0=true; divideByN[ch] = divideByN_Latch2[ch]; Channel0Distortion(); } }
+		ch = 1; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel1Distortion(); } }
+		if( pokeyClockCounter>=pp )
+		{
+			pp = pokeyClockCounter + pcc1564;
+			ch = 2; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel2Distortion(); switch_J3_Q_state[0] = signal_state_out[0]; } }
+			ch = 3; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel3Distortion(); switch_J3_Q_state[1] = signal_state_out[1]; } }
+		}
+		MAKESAMPLE
+	} while(--i);
+	sndBufPtrUpp = ss;
+	pokeyClockCounter64k = pcc1564 + pokeyClockCounter - pp ;
+
+}
+
+void pus_02h( int n )
+{
+unsigned int i;
+unsigned int ch;
+DWORD pp; 
+int ss;
+
+	pp = pokeyClockCounter + (pcc1564 - pokeyClockCounter64k);
+	ss = sndBufPtrUpp; 
+	i = n;
+	do
+	{
+		pokeyClockCounter++;
+		ch = 0; { if( --divideByN[ch]==0 ) { generateIRQ0=true; divideByN[ch] = divideByN_Latch2[ch]; Channel0Distortion(); } }
+		if( pokeyClockCounter>=pp )
+		{
+			pp = pokeyClockCounter + pcc1564;
+			ch = 1; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel1Distortion(); } }
+			ch = 3; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel3Distortion(); switch_J3_Q_state[1] = signal_state_out[1]; } }
+		}
+		ch = 2; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel2Distortion(); switch_J3_Q_state[0] = signal_state_out[0]; } }
+		MAKESAMPLE
+	} while(--i);
+	sndBufPtrUpp = ss;
+	pokeyClockCounter64k = pcc1564 + pokeyClockCounter - pp ;
+}
+
+void pus_012h( int n )
+{
+unsigned int i;
+unsigned int ch;
+DWORD pp;
+int ss;
+
+	pp = pokeyClockCounter + (pcc1564 - pokeyClockCounter64k);
+	ss = sndBufPtrUpp; 
+	i = n;
+	do
+	{
+		pokeyClockCounter++;
+		ch = 0; { if( --divideByN[ch]==0 ) { generateIRQ0=true; divideByN[ch] = divideByN_Latch2[ch]; Channel0Distortion(); } }
+		ch = 1; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel1Distortion(); } }
+		if( pokeyClockCounter>=pp )
+		{
+			pp = pokeyClockCounter + pcc1564;
+			ch = 3; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel3Distortion(); switch_J3_Q_state[1] = signal_state_out[1]; } }
+		}
+		ch = 2; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel2Distortion(); switch_J3_Q_state[0] = signal_state_out[0]; } }
+		MAKESAMPLE
+	} while(--i);
+	sndBufPtrUpp = ss;
+	pokeyClockCounter64k = pcc1564 + pokeyClockCounter - pp ;
+}
+
+void pus_023h( int n )
+{
+unsigned int i;
+unsigned int ch;
+DWORD  pp;
+int ss;
+
+	pp = pokeyClockCounter + (pcc1564 - pokeyClockCounter64k);
+	ss = sndBufPtrUpp; 
+	i = n;
+	do
+	{
+		pokeyClockCounter++;
+		ch = 0; { if( --divideByN[ch]==0 ) { generateIRQ0=true; divideByN[ch] = divideByN_Latch2[ch]; Channel0Distortion(); } }
+		if( pokeyClockCounter>=pp )
+		{
+			pp = pokeyClockCounter + pcc1564;
+			ch = 1; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel1Distortion(); } }
+		}
+		ch = 2; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel2Distortion(); switch_J3_Q_state[0] = signal_state_out[0]; } }
+		ch = 3; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel3Distortion(); switch_J3_Q_state[1] = signal_state_out[1]; } }
+		MAKESAMPLE
+	} while(--i);
+	sndBufPtrUpp = ss;
+	pokeyClockCounter64k = pcc1564 + pokeyClockCounter - pp ;
+}
+
+void pus_0123h( int n )
+{
+unsigned int i;
+unsigned int ch;
+int ss;
+
+	ss = sndBufPtrUpp; 
+	i = n;
+	do
+	{
+		pokeyClockCounter++;
+		ch = 0; { if( --divideByN[ch]==0 ) { generateIRQ0=true; divideByN[ch] = divideByN_Latch2[ch]; Channel0Distortion(); } }
+		ch = 1; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel1Distortion(); } }
+		ch = 2; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel2Distortion(); switch_J3_Q_state[0] = signal_state_out[0]; } }
+		ch = 3; { if( --divideByN[ch]==0 ) { divideByN[ch] = divideByN_Latch2[ch]; Channel3Distortion(); switch_J3_Q_state[1] = signal_state_out[1]; } }
+		MAKESAMPLE
+	} while(--i);
+	sndBufPtrUpp = ss;
+}
+
+typedef void (*funcPoint2)(int n);
+
+funcPoint2 channelsGeneration[16]={
+	&pus_zero,	&pus_zero,	&pus_zero,	&pus_zero,
+	&pus_2h,	&pus_23h,	&pus_2h,	&pus_23h,
+	&pus_0h,	&pus_0h,	&pus_01h,	&pus_01h,
+	&pus_02h,	&pus_023h,	&pus_012h,	&pus_0123h
+};
+
+}; // end of namespace POKEY_NAMESPACE
+
+using namespace NAMESPACENAME;
+
+POKEY_INIT_FUNC
+{
+unsigned int i;
+DWORD pol;
+BYTE old;
+
+	pol = 0x1FFFF;
+	for( i=0; i<0x20000; i++ )
+	{
+		poly17[i] = (BYTE)(pol&1 ? 15:0);
+		pol = pol | (((pol&1) ^ ((pol>>5)&1)) << 17);
+		pol>>=1;
+	}
+
+	for( i=0; i<sizeof(poly4_b); i++ ) // this table repeats after 15
+		poly4_b[i] = poly4[i % 15];
+
+	for( i=0; i<sizeof(poly5_b); i++ ) // this table repeats after 31
+		poly5_b[i] = poly5[i % 31];
+
+	old = 0;
+	for( i=0; i<sizeof(poly4_5_b); i++ ) // this table repeats after 465
+	{
+		if( poly5[i % 31] )
+			old = poly4[i % 15];
+		poly4_5_b[i] = old;
+	}
+
+}
+
+POKEY_RESET_FUNC
+{
+int i;
+
+	IRQ_EN		= 0x00;
+	IRQ_ST		= 0x00;
+	IRQ_line	= 0x00;
+
+	poly4Counter = 0;
+	poly5Counter = 0;
+	poly4_5Counter = 0;
+	pokeyClockCounter = 0;
+	pokeyClockCounter64k = 0;
+	pcc1564 = 28;
+	oldValI = 0;
+	oldVal	=0.0;
+
+	for( i=0; i<4; i++ )
+	{
+		divideByN[i] = 1;
+		divideByN_Latch[i] = 0;
+		divideByN_Latch2[i] = 0;
+		switch_J2_signal_Q[i] = 0;
+		signal_state_out[i] = 0;
+		switch_J3_Q_state[i] = 0;
+		switch_J3_Q_stateAND[i] = 0;
+		audioControl_Latch[i] = 0;
+		audioControl_Latch2[i] = 0;
+		audioControl_Latch_Digi[i] = 0;
+		freq_sequre[i] = 0;
+	}
+
+	for( i=0; i<16; i++ )
+		POKEY_WRITE_2FUNC( 0xD200+i, 0 );
+	AUDCTL = 0;
+	POKEY_WRITE_2FUNC( 0xD208, 0x28 );
+
+	sndBufPtrUpp = 0;
+	delay = 0;
+
+}
+
+POKEY_UPDATESOUND_FUNC
+{
+
+	channelsGeneration[ (AUDCTL>>3)&15 ](n);
+
+}
+
+
+POKEY_UPDATECOUNT_FUNC
+{
+
+	pokeyClockCounter = pokeyClockCounter & 0x7FFFFFFF;
+	poly4Counter = (int)(((DWORD)(poly4Counter+pokeyClockCounter)) % 15) - pokeyClockCounter;
+	poly5Counter = (int)(((DWORD)(poly5Counter+pokeyClockCounter)) % 31) - pokeyClockCounter;
+	poly4_5Counter = (int)(((DWORD)(poly4_5Counter+pokeyClockCounter)) % 465) - pokeyClockCounter;
+
+}
+
+#undef SetupChannels01
+#undef SetupChannels23
+
+#define SetupChannels01\
+			switch( AUDCTL&0x50 )\
+			{\
+				case 0x00:\
+					divideByN_Latch2[0] = divideByN_Latch[0]+1;\
+					if( ((audioControl_Latch[0]&0xA0)==0xA0) && (divideByN_Latch2[0]<3) )\
+						freq_sequre[0] = 0;\
+					else\
+						freq_sequre[0] = 15;\
+					divideByN_Latch2[1] = divideByN_Latch[1]+1;\
+					if( ((audioControl_Latch[1]&0xA0)==0xA0) && (divideByN_Latch2[1]<3) )\
+						freq_sequre[1] = 0;\
+					else\
+						freq_sequre[1] = 15;\
+					break;\
+				case 0x10:\
+					divideByN_Latch2[0] = divideByN_Latch[0]+1;\
+					if( ((audioControl_Latch[0]&0xA0)==0xA0) && (divideByN_Latch2[0]<3) )\
+						freq_sequre[0] = 0;\
+					else\
+						freq_sequre[0] = 15;\
+					divideByN_Latch2[1] = divideByN_Latch[1]*256+divideByN_Latch2[0];\
+					if( ((audioControl_Latch[1]&0xA0)==0xA0) && (divideByN_Latch2[1]<3) )\
+						freq_sequre[1] = 0;\
+					else\
+						freq_sequre[1] = 15;\
+					break;\
+				case 0x40:\
+					divideByN_Latch2[0] = divideByN_Latch[0]+4;\
+					if( ((audioControl_Latch[0]&0xA0)==0xA0) && (divideByN_Latch2[0]<0x50) )\
+						freq_sequre[0] = 0;\
+					else\
+						freq_sequre[0] = 15;\
+					divideByN_Latch2[1] = divideByN_Latch[1]+1;\
+					if( ((audioControl_Latch[1]&0xA0)==0xA0) && (divideByN_Latch2[1]<3) )\
+						freq_sequre[1] = 0;\
+					else\
+						freq_sequre[1] = 15;\
+					break;\
+				case 0x50:\
+					divideByN_Latch2[0] = divideByN_Latch[0]+7;\
+					freq_sequre[0] = 0;\
+					divideByN_Latch2[1] = divideByN_Latch[1]*256+divideByN_Latch2[0];\
+					if( ((audioControl_Latch[1]&0xA0)==0xA0) && (divideByN_Latch2[1]<0x50) )\
+						freq_sequre[1] = 0;\
+					else\
+						freq_sequre[1] = 15;\
+					break;\
+			}
+
+#define SetupChannels23\
+			switch( AUDCTL&0x28 )\
+			{\
+				case 0x00:\
+					divideByN_Latch2[2] = divideByN_Latch[2]+1;\
+					if( ((audioControl_Latch[2]&0xA0)==0xA0) && (divideByN_Latch2[2]<3) )\
+						freq_sequre[2] = 0;\
+					else\
+						freq_sequre[2] = 15;\
+					divideByN_Latch2[3] = divideByN_Latch[3]+1;\
+					if( ((audioControl_Latch[3]&0xA0)==0xA0) && (divideByN_Latch2[3]<3) )\
+						freq_sequre[3] = 0;\
+					else\
+						freq_sequre[3] = 15;\
+					break;\
+				case 0x08:\
+					divideByN_Latch2[2] = divideByN_Latch[2]+1;\
+					if( ((audioControl_Latch[2]&0xA0)==0xA0) && (divideByN_Latch2[2]<3) )\
+						freq_sequre[2] = 0;\
+					else\
+						freq_sequre[2] = 15;\
+					divideByN_Latch2[3] = divideByN_Latch[3]*256+divideByN_Latch2[2];\
+					if( ((audioControl_Latch[3]&0xA0)==0xA0) && (divideByN_Latch2[3]<3) )\
+						freq_sequre[3] = 0;\
+					else\
+						freq_sequre[3] = 15;\
+					break;\
+				case 0x20:\
+					divideByN_Latch2[2] = divideByN_Latch[2]+4;\
+					if( ((audioControl_Latch[2]&0xA0)==0xA0) && (divideByN_Latch2[2]<0x50) )\
+						freq_sequre[2] = 0;\
+					else\
+						freq_sequre[2] = 15;\
+					divideByN_Latch2[3] = divideByN_Latch[3]+1;\
+					if( ((audioControl_Latch[3]&0xA0)==0xA0) && (divideByN_Latch2[3]<3) )\
+						freq_sequre[3] = 0;\
+					else\
+						freq_sequre[3] = 15;\
+					break;\
+				case 0x28:\
+					divideByN_Latch2[2] = divideByN_Latch[2]+7;\
+					freq_sequre[2] = 0;\
+					divideByN_Latch2[3] = divideByN_Latch[3]*256+divideByN_Latch2[2];\
+					if( ((audioControl_Latch[3]&0xA0)==0xA0) && (divideByN_Latch2[3]<0x50) )\
+						freq_sequre[3] = 0;\
+					else\
+						freq_sequre[3] = 15;\
+					break;\
+			}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/sapCpu.cpp	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,1581 @@
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sapGlobals.h"
+
+void cpuInit( void )
+{
+	cpuReg_PC = 0xFFFF;
+	cpuReg_S = 0xFF;
+	cpuReg_A = 0x00;
+	cpuReg_X = 0x00;
+	cpuReg_Y = 0x00;
+	cpuSetFlags( 0x20 );
+}
+
+
+void cpuSetFlags( BYTE flags )
+{
+	cpuFlag_N = flags;
+	cpuFlag_V = (flags>>6)&1;
+	cpuFlag_B = (flags>>4)&1;
+	cpuFlag_D = (flags>>3)&1;
+	cpuFlag_I = (flags>>2)&1;
+	cpuFlag_Z = (flags&2)==0 ? 1:0;
+	cpuFlag_C = flags&1;
+}
+
+
+BYTE cpuGetFlags( void )
+{
+BYTE flags;
+
+	flags = (cpuFlag_N&0x80) | ((cpuFlag_V&1)<<6) | 0x20 | ((cpuFlag_B&1)<<4) | ((cpuFlag_D&1)<<3) | ((cpuFlag_I&1)<<2) | (cpuFlag_Z==0 ? 2:0) | (cpuFlag_C&1);
+	return flags;
+}
+
+#define CPY		{\
+					cB ^= 255;\
+					int cpuIntValue2;\
+					cpuIntValue2 = ((int)cpuReg_Y) + ((int)cB) + 1;\
+					cpuFlag_N = cpuFlag_Z = (BYTE)cpuIntValue2; cpuFlag_C = (BYTE)(cpuIntValue2>>8);\
+					cpuFlag_V = (( ((cpuReg_Y^cB)^0x80) & (cpuReg_Y^cpuIntValue2) & 0x80))&0x80 ? 1:0;\
+				}
+#define CMP		{\
+					cB ^= 255;\
+					int cpuIntValue2;\
+					cpuIntValue2 = ((int)cpuReg_A) + ((int)cB) + 1;\
+					cpuFlag_N = cpuFlag_Z = (BYTE)cpuIntValue2; cpuFlag_C = (BYTE)(cpuIntValue2>>8);\
+					cpuFlag_V = (( ((cpuReg_A^cB)^0x80) & (cpuReg_A^cpuIntValue2) & 0x80))&0x80 ? 1:0;\
+				}
+#define CPX		{\
+					cB ^= 255;\
+					int cpuIntValue2;\
+					cpuIntValue2 = ((int)cpuReg_X) + ((int)cB) + 1;\
+					cpuFlag_N = cpuFlag_Z = (BYTE)cpuIntValue2; cpuFlag_C = (BYTE)(cpuIntValue2>>8);\
+					cpuFlag_V = (( ((cpuReg_X^cB)^0x80) & (cpuReg_X^cpuIntValue2) & 0x80))&0x80 ? 1:0;\
+				}
+
+#define DECCMP	{\
+					cB--;\
+					int cpuIntValue2;\
+					cpuIntValue2 = ((int)cpuReg_A) + ((int)cB^255) + 1;\
+					cpuFlag_N = cpuFlag_Z = (BYTE)cpuIntValue2; cpuFlag_C = (BYTE)(cpuIntValue2>>8);\
+					cpuFlag_V = (( ((cpuReg_A^cB^255)^0x80) & (cpuReg_A^cpuIntValue2) & 0x80))&0x80 ? 1:0;\
+				}
+#define DEC		{ cB--; cpuFlag_N = cpuFlag_Z = cB; }
+#define INC		{ cB++; cpuFlag_N = cpuFlag_Z = cB; }
+#define	AND		{ cpuReg_A &= cB; cpuFlag_N = cpuFlag_Z = cpuReg_A; }
+#define	ASL		{ cpuFlag_C = cB>>7; cB<<=1; cpuFlag_N = cpuFlag_Z = cB; }
+#define	EOR		{ cpuReg_A ^= cB; cpuFlag_N = cpuFlag_Z = cpuReg_A; }
+#define	ORA		{ cpuReg_A |= cB; cpuFlag_N = cpuFlag_Z = cpuReg_A; }
+#define ADC		{\
+					if( cpuFlag_D&1 )\
+					{\
+						BYTE al,ah;\
+						al = (cpuReg_A & 0x0f) + (cB & 0x0f) + (cpuFlag_C&1);\
+						if (al > 9) al += 6;\
+						ah = ((cpuReg_A >> 4)&0x0F) + ((cB >> 4)&0x0F); if (al > 0x0f) ah++;\
+						cpuFlag_N = cpuFlag_Z =  cpuReg_A + cB + (cpuFlag_C&1);\
+						cpuFlag_V = (((ah << 4) ^ cpuReg_A) & 0x80) && !((cpuReg_A ^ cB) & 0x80) ? 1:0;\
+						if (ah > 9) ah += 6; cpuFlag_C = (ah > 0x0f) ? 1:0; cpuReg_A = (ah << 4) | (al & 0x0f);\
+					}\
+					else\
+					{\
+						WORD te;\
+						te = cpuReg_A + cB + (cpuFlag_C&1);\
+						cpuFlag_C = (BYTE)(te>>8);\
+						cpuFlag_V = (( ((cpuReg_A^cB)^0x80) & (cpuReg_A^te) & 0x80)) ? 1:0;\
+						cpuFlag_N = cpuFlag_Z = cpuReg_A = (BYTE)te;\
+					}\
+				}
+#define SBC		{\
+					if( cpuFlag_D&1 )\
+					{\
+						BYTE al,ah; unsigned int tmp; tmp = (DWORD)cpuReg_A - (DWORD)cB - (WORD)((cpuFlag_C&1)^1);\
+						al = (cpuReg_A & 0x0f) - (cB & 0x0f) - ((cpuFlag_C&1)^1);\
+						ah = ((cpuReg_A >> 4)&0x0F) - ((cB >> 4)&0x0F); if (al & 0x10) { al -= 6; ah--; } if (ah & 0x10) ah -= 6;\
+						cpuFlag_C = (tmp < (unsigned int)0x100) ? 1:0; cpuFlag_N = cpuFlag_Z = (BYTE)tmp;\
+						cpuFlag_V = (((cpuReg_A ^ tmp) & 0x80) && ((cpuReg_A ^ cB) & 0x80) ) ? 1:0;\
+						cpuReg_A = (ah << 4) | (al & 0x0f);\
+					}\
+					else\
+					{\
+						WORD te;\
+						te = cpuReg_A + (cB^255) + (cpuFlag_C&1);\
+						cpuFlag_C = (BYTE)(te>>8);\
+						cpuFlag_V = (( ((cpuReg_A^cB^255)^0x80) & (cpuReg_A^te) & 0x80)) ? 1:0;\
+						cpuFlag_N = cpuFlag_Z = cpuReg_A = (BYTE)te;\
+					}\
+				}
+#define INCSBC	{\
+					cB++;\
+					if( cpuFlag_D&1 )\
+					{\
+						BYTE al,ah; unsigned int tmp; tmp = (DWORD)cpuReg_A - (DWORD)cB - (WORD)((cpuFlag_C&1)^1);\
+						al = (cpuReg_A & 0x0f) - (cB & 0x0f) - ((cpuFlag_C&1)^1);\
+						ah = ((cpuReg_A >> 4)&0x0F) - ((cB >> 4)&0x0F); if (al & 0x10) { al -= 6; ah--; } if (ah & 0x10) ah -= 6;\
+						cpuFlag_C = (tmp < (unsigned int)0x100) ? 1:0; cpuFlag_N = cpuFlag_Z = (BYTE)tmp;\
+						cpuFlag_V = (((cpuReg_A ^ tmp) & 0x80) && ((cpuReg_A ^ cB) & 0x80) ) ? 1:0;\
+						cpuReg_A = (ah << 4) | (al & 0x0f);\
+					}\
+					else\
+					{\
+						WORD te;\
+						te = cpuReg_A + (cB^255) + (cpuFlag_C&1);\
+						cpuFlag_C = (BYTE)(te>>8);\
+						cpuFlag_V = (( ((cpuReg_A^cB^255)^0x80) & (cpuReg_A^te) & 0x80)) ? 1:0;\
+						cpuFlag_N = cpuFlag_Z = cpuReg_A = (BYTE)te;\
+					}\
+				}
+
+#define ROL		{ BYTE cFlag; cFlag = cB>>7; cB = (cB<<1) + (cpuFlag_C&1); cpuFlag_C = cFlag; cpuFlag_N = cpuFlag_Z = cB; }
+#define ROR		{ BYTE cFlag; cFlag = cB; cB = (cB>>1) + (cpuFlag_C<<7); cpuFlag_C = cFlag; cpuFlag_N = cpuFlag_Z = cB; }
+#define LSR		{ cpuFlag_C = cB; cB>>=1; cpuFlag_N = cpuFlag_Z = cB; }
+#define	ASLORA	{ cpuFlag_C = cB>>7; cB<<=1; cpuReg_A |= cB; cpuFlag_N = cpuFlag_Z = cpuReg_A; }
+#define	ROLAND	{ BYTE cFlag; cFlag = cB>>7; cB = (cB<<1) + (cpuFlag_C&1); cpuFlag_C = cFlag; cpuReg_A &= cB; cpuFlag_N = cpuFlag_Z = cpuReg_A; }
+#define LSREOR	{ cpuFlag_C = cB; cB>>=1; cpuReg_A ^= cB; cpuFlag_N = cpuFlag_Z = cpuReg_A; }
+#define RORADC	{\
+					BYTE cC = cB; cB = (cB>>1) + (cpuFlag_C<<7); cpuFlag_C = cC;\
+					if( cpuFlag_D&1 )\
+					{\
+						BYTE al,ah;\
+						al = (cpuReg_A & 0x0f) + (cB & 0x0f) + (cpuFlag_C&1);\
+						if (al > 9) al += 6;\
+						ah = ((cpuReg_A >> 4)&0x0F) + ((cB >> 4)&0x0F); if (al > 0x0f) ah++;\
+						cpuFlag_N = cpuFlag_Z =  cpuReg_A + cB + (cpuFlag_C&1);\
+						cpuFlag_V = (((ah << 4) ^ cpuReg_A) & 0x80) && !((cpuReg_A ^ cB) & 0x80) ? 1:0;\
+						if (ah > 9) ah += 6; cpuFlag_C = (ah > 0x0f) ? 1:0; cpuReg_A = (ah << 4) | (al & 0x0f);\
+					}\
+					else\
+					{\
+						WORD te;\
+						te = cpuReg_A + cB + (cpuFlag_C&1);\
+						cpuFlag_C = (BYTE)(te>>8);\
+						cpuFlag_V = (( ((cpuReg_A^cB)^0x80) & (cpuReg_A^te) & 0x80)) ? 1:0;\
+						cpuFlag_N = cpuFlag_Z = cpuReg_A = (BYTE)te;\
+					}\
+				}
+
+#define CondJump( a ) cpuReg_PC += (a) ? (WORD)(signed short int)(signed char)atariMem[cpuReg_PC+1]+2:2;
+
+//-------
+
+#define FREDDIEWRITEBYTE(ad,val)\
+	{\
+		if( (ad&0xFF00)==0xD200 )\
+		{\
+			if( isStereo==false )\
+				pokeyWriteByte0( ad, val );\
+			else if( (ad&0x10)==0 )\
+				pokeyWriteByte0( ad, val );\
+			else\
+				pokeyWriteByte1( ad, val );\
+		}\
+		else if( ad==0xD40A )\
+			holded = true;\
+		else atariMem[ad] = val;\
+	}
+
+#define Load_IMD(a)		BYTE cB; {																							cB = atariMem[cpuReg_PC+1]; cpuReg_PC+=2; a; }
+#define Load_ZP(a)		BYTE cB; { BYTE cA=atariMem[cpuReg_PC+1];															cB = atariMem[cA];	cpuReg_PC+=2; a; }
+#define Load_ZPX(a)		BYTE cB; { BYTE cA=atariMem[cpuReg_PC+1]+cpuReg_X;													cB = atariMem[cA];	cpuReg_PC+=2; a; }
+#define Load_ZPY(a)		BYTE cB; { BYTE cA=atariMem[cpuReg_PC+1]+cpuReg_Y;													cB = atariMem[cA];	cpuReg_PC+=2; a; }
+#define Load_ABS(a)		BYTE cB; { WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0];											cB = freddieReadByte(cWA); cpuReg_PC+=3; a; }
+#define Load_ABSX(a)	BYTE cB; { WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0] + (WORD)cpuReg_X;							cB = freddieReadByte(cWA); cpuReg_PC+=3; a; }
+#define Load_ABSY(a)	BYTE cB; { WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0] + (WORD)cpuReg_Y;							cB = freddieReadByte(cWA); cpuReg_PC+=3; a; }
+#define Load_PreX(a)	BYTE cB; { BYTE cA=(atariMem[cpuReg_PC+1]+cpuReg_X)&255; WORD cWA = ((WORD*)&atariMem[cA])[0];		cB = freddieReadByte(cWA); cpuReg_PC+=2; a; }
+#define Load_PostY(a)	BYTE cB; { BYTE cA=atariMem[cpuReg_PC+1]; WORD cWA = ((WORD*)&atariMem[cA])[0] + (WORD)cpuReg_Y;	cB = freddieReadByte(cWA); cpuReg_PC+=2; a; }
+
+#define LoadReg_IMD(a)		{																							a = cpuFlag_N = cpuFlag_Z = atariMem[cpuReg_PC+1]; cpuReg_PC+=2; }
+#define LoadReg_ZP(a)		{ BYTE cA=atariMem[cpuReg_PC+1];															a = cpuFlag_N = cpuFlag_Z = atariMem[cA];	cpuReg_PC+=2; }
+#define LoadReg_ZPX(a)		{ BYTE cA=atariMem[cpuReg_PC+1]+cpuReg_X;													a = cpuFlag_N = cpuFlag_Z = atariMem[cA];	cpuReg_PC+=2; }
+#define LoadReg_ZPY(a)		{ BYTE cA=atariMem[cpuReg_PC+1]+cpuReg_Y;													a = cpuFlag_N = cpuFlag_Z = atariMem[cA];	cpuReg_PC+=2; }
+#define LoadReg_ABS(a)		{ WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0];											a = cpuFlag_N = cpuFlag_Z = freddieReadByte(cWA); cpuReg_PC+=3; }
+#define LoadReg_ABSX(a)		{ WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0] + (WORD)cpuReg_X;							a = cpuFlag_N = cpuFlag_Z = freddieReadByte(cWA); cpuReg_PC+=3; }
+#define LoadReg_ABSY(a)		{ WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0] + (WORD)cpuReg_Y;							a = cpuFlag_N = cpuFlag_Z = freddieReadByte(cWA); cpuReg_PC+=3; }
+#define LoadReg_PreX(a)		{ BYTE cA=(atariMem[cpuReg_PC+1]+cpuReg_X)&255; WORD cWA = ((WORD*)&atariMem[cA])[0];		a = cpuFlag_N = cpuFlag_Z = freddieReadByte(cWA); cpuReg_PC+=2; }
+#define LoadReg_PostY(a)	{ BYTE cA=atariMem[cpuReg_PC+1]; WORD cWA = ((WORD*)&atariMem[cA])[0] + (WORD)cpuReg_Y;		a = cpuFlag_N = cpuFlag_Z = freddieReadByte(cWA); cpuReg_PC+=2; }
+
+#define Modify_ZP(a)	BYTE cB; { BYTE cA=atariMem[cpuReg_PC+1];															cB = atariMem[cA];	cpuReg_PC+=2; a; atariMem[cA] = cB; }
+#define Modify_ZPX(a)	BYTE cB; { BYTE cA=atariMem[cpuReg_PC+1]+cpuReg_X;													cB = atariMem[cA];	cpuReg_PC+=2; a; atariMem[cA] = cB; }
+#define Modify_ABS(a)	BYTE cB; { WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0];											cB = freddieReadByte(cWA); cpuReg_PC+=3; a; FREDDIEWRITEBYTE(cWA,cB); }
+#define Modify_ABSX(a)	BYTE cB; { WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0] + (WORD)cpuReg_X;							cB = freddieReadByte(cWA); cpuReg_PC+=3; a; FREDDIEWRITEBYTE(cWA,cB); }
+#define Modify_ABSY(a)	BYTE cB; { WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0] + (WORD)cpuReg_Y;							cB = freddieReadByte(cWA); cpuReg_PC+=3; a; FREDDIEWRITEBYTE(cWA,cB); }
+#define Modify_PreX(a)	BYTE cB; { BYTE cA=(atariMem[cpuReg_PC+1]+cpuReg_X)&255; WORD cWA = ((WORD*)&atariMem[cA])[0];		cB = freddieReadByte(cWA); cpuReg_PC+=2; a; FREDDIEWRITEBYTE(cWA,cB); }
+#define Modify_PostY(a)	BYTE cB; { BYTE cA=atariMem[cpuReg_PC+1]; WORD cWA = ((WORD*)&atariMem[cA])[0] + (WORD)cpuReg_Y;	cB = freddieReadByte(cWA); cpuReg_PC+=2; a; FREDDIEWRITEBYTE(cWA,cB); }
+
+#define Store_ZP(a)		{ BYTE cA=atariMem[cpuReg_PC+1];															cpuReg_PC+=2;	atariMem[cA] = a; }
+#define Store_ZPX(a)	{ BYTE cA=atariMem[cpuReg_PC+1]+cpuReg_X;													cpuReg_PC+=2;	atariMem[cA] = a; }
+#define Store_ABS(a)	{ WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0];											cpuReg_PC+=3;	FREDDIEWRITEBYTE(cWA,a); }
+#define Store_ABSX(a)	{ WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0] + (WORD)cpuReg_X;							cpuReg_PC+=3;	FREDDIEWRITEBYTE(cWA,a); }
+#define Store_ABSY(a)	{ WORD cWA = ((WORD*)&atariMem[cpuReg_PC+1])[0] + (WORD)cpuReg_Y;							cpuReg_PC+=3;	FREDDIEWRITEBYTE(cWA,a); }
+#define Store_PreX(a)	{ BYTE cA=(atariMem[cpuReg_PC+1]+cpuReg_X)&255; WORD cWA = ((WORD*)&atariMem[cA])[0];		cpuReg_PC+=2;	FREDDIEWRITEBYTE(cWA,a); }
+#define Store_PostY(a)	{ BYTE cA=atariMem[cpuReg_PC+1]; WORD cWA = ((WORD*)&atariMem[cA])[0] + (WORD)cpuReg_Y;		cpuReg_PC+=2;	FREDDIEWRITEBYTE(cWA,a); }
+
+int opcode_0x00(bool &holded)	/* 0x00 - BRK				7 cycles	*/
+{
+	cpuReg_PC++;
+	return 20;
+}
+int opcode_0x01(bool &holded)	/* 0x01 - ORA (,X)			6 cycles	*/
+{
+	Load_PreX( ORA );
+	return 6;
+}
+int opcode_0x02(bool &holded)	/* 0x02 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0x03(bool &holded)	/* 0x03 - ASL:ORA (,X)		8 cycles	*/
+{
+	Modify_PreX( ASLORA );
+	return 8;
+}
+int opcode_0x04(bool &holded)	/* 0x04 - NOP2				3 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x05(bool &holded)	/* 0x05 - ORA ZP			3 cycles	*/
+{
+	Load_ZP( ORA );
+	return 3;
+}
+int opcode_0x06(bool &holded)	/* 0x06 - ASL ZP			5 cycles	*/
+{
+	Modify_ZP( ASL )
+	return 5;
+}
+int opcode_0x07(bool &holded)	/* 0x07 - ASL:ORA ZP		5 cycles	*/
+{
+	Modify_ZP( ASLORA )
+	return 5;
+}
+int opcode_0x08(bool &holded)	/* 0x08 - PHP				3 cycles	*/
+{
+BYTE te;
+	cpuReg_PC++;
+	te = (cpuFlag_N&0x80) | ((cpuFlag_V&1)<<6) | 0x20 | ((cpuFlag_B&1)<<4) | ((cpuFlag_D&1)<<3) | ((cpuFlag_I&1)<<2) | (cpuFlag_Z==0 ? 2:0) | (cpuFlag_C&1);
+	atariMem[0x100 + cpuReg_S] = te; cpuReg_S--;
+	return 3;
+}
+int opcode_0x09(bool &holded)	/* 0x09 - ORA #				2 cycles	*/
+{
+	Load_IMD( ORA );
+	return 2;
+}
+int opcode_0x0A(bool &holded)	/* 0x0A - ASL @				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_C = cpuReg_A>>7; cpuReg_A<<=1; cpuFlag_N = cpuFlag_Z = cpuReg_A;
+	return 2;
+}
+int opcode_0x0B(bool &holded)	/* 0x0B - ????							*/
+{
+	return 20;
+}
+int opcode_0x0C(bool &holded)	/* 0x0C - NOP3				4 cycles	*/
+{
+	cpuReg_PC+=3;
+	return 4;
+}
+int opcode_0x0D(bool &holded)	/* 0x0D - ORA ABS			4 cycles	*/
+{
+	Load_ABS( ORA );
+	return 4;
+}
+int opcode_0x0E(bool &holded)	/* 0x0E - ASL ABS			6 cycles	*/
+{
+	Modify_ABS( ASL );
+	return 6;
+}
+int opcode_0x0F(bool &holded)	/* 0x0F - ASL:ORA ABS		6 cycles	*/
+{
+	Modify_ABS( ASLORA );
+	return 6;
+}
+int opcode_0x10(bool &holded)	/* 0x10 - BPL				2-4 cycles	*/
+{
+	CondJump( (cpuFlag_N&0x80)==0 );
+	return 3;
+}
+int opcode_0x11(bool &holded)	/* 0x11 - ORA (),Y			5,6 cycles	*/
+{
+	Load_PostY( ORA );
+	return 5;
+}
+int opcode_0x12(bool &holded)	/* 0x12 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0x13(bool &holded)	/* 0x13 - ASL:ORA (),Y		8 cycles	*/
+{
+	Modify_PostY( ASLORA );
+	return 8;
+}
+int opcode_0x14(bool &holded)	/* 0x14 - NOP2							*/
+{
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x15(bool &holded)	/* 0x15 - ORA ZP,X			4 cycles	*/
+{
+	Load_ZPX( ORA );
+	return 4;
+}
+int opcode_0x16(bool &holded)	/* 0x16 - ASL ZP,X			6 cycles	*/
+{
+	Modify_ZPX( ASL );
+	return 6;
+}
+int opcode_0x17(bool &holded)	/* 0x17 - ASL:ORA ZP,X		6 cycles	*/
+{
+	Modify_ZPX( ASLORA );
+	return 6;
+}
+int opcode_0x18(bool &holded)	/* 0x18 - CLC				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_C = 0;
+	return 2;
+}
+int opcode_0x19(bool &holded)	/* 0x19 - ORA ABS,Y			4,5 cycles	*/
+{
+	Load_ABSY( ORA );
+	return 4;
+}
+int opcode_0x1A(bool &holded)	/* 0x1A - NOP1				2 cycles	*/
+{
+	cpuReg_PC++;
+	return 2;
+}
+int opcode_0x1B(bool &holded)	/* 0x1B - ASL:ORA ABS,Y		7 cycles	*/
+{
+	Modify_ABSY( ASLORA );
+	return 7;
+}
+int opcode_0x1C(bool &holded)	/* 0x1C - NOP3				7 cycles	*/
+{
+	cpuReg_PC+=3;
+	return 7;
+}
+int opcode_0x1D(bool &holded)	/* 0x1D - ORA ABS,X			4,5 cycles	*/
+{
+	Load_ABSX( ORA );
+	return 4;
+}
+int opcode_0x1E(bool &holded)	/* 0x1E - ASL ABS,X			7 cycles	*/
+{
+	Modify_ABSX( ASL );
+	return 7;
+}
+int opcode_0x1F(bool &holded)	/* 0x1F - ASL:ORA ABS,X		7 cycles	*/
+{
+	Modify_ABSX( ASLORA );
+	return 7;
+}
+int opcode_0x20(bool &holded)	/* 0x20 - JSR ABS			6 cycles	*/
+{
+	cpuReg_PC+=2;
+	atariMem[0x100 + cpuReg_S] = (cpuReg_PC>>8)&0xFF; cpuReg_S--;
+	atariMem[0x100 + cpuReg_S] = cpuReg_PC&0xFF; cpuReg_S--;
+	cpuReg_PC = ((WORD*)&atariMem[cpuReg_PC-1])[0];
+	return 6;
+}
+int opcode_0x21(bool &holded)	/* 0x21 - AND (,X)			6 cycles	*/
+{
+	Load_PreX( AND );
+	return 6;
+}
+int opcode_0x22(bool &holded)	/* 0x22 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0x23(bool &holded)	/* 0x23 - ROL:AND (,X)		8 cycles	*/
+{
+	Modify_PreX( ROLAND );
+	return 8;
+}
+int opcode_0x24(bool &holded)	/* 0x24 - BIT ZP			3 cycles	*/
+{
+BYTE cb;
+	cb = atariMem[cpuReg_PC+1];
+	cpuFlag_Z = cb&cpuReg_A; cpuFlag_N = cb; cpuFlag_V = cb>>6;
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x25(bool &holded)	/* 0x25 - AND ZP			3 cycles	*/
+{
+	Load_ZP( AND );
+	return 3;
+}
+int opcode_0x26(bool &holded)	/* 0x26 - ROL ZP			5 cycles	*/
+{
+	Modify_ZP( ROL );
+	return 5;
+}
+int opcode_0x27(bool &holded)	/* 0x27 - ROL:AND ZP		5 cycles	*/
+{
+	Modify_ZP( ROLAND );
+	return 5;
+}
+int opcode_0x28(bool &holded)	/* 0x28 - PLP				4 cycles	*/
+{
+BYTE te;
+	cpuReg_PC++; cpuReg_S++; te = atariMem[0x100 + cpuReg_S];
+	cpuFlag_N = te; cpuFlag_V = (te>>6)&1; cpuFlag_B = (te>>4)&1; cpuFlag_D = (te>>3)&1; cpuFlag_I = (te>>2)&1; cpuFlag_Z = (te&2)^2; cpuFlag_C = te&1;
+	pokeyGenerateCheckIRQline();
+	return 4;
+}
+int opcode_0x29(bool &holded)	/* 0x29 - AND #				2 cycles	*/
+{
+	Load_IMD( AND );
+	return 2;
+}
+int opcode_0x2A(bool &holded)	/* 0x2A - ROL @				2 cycles	*/
+{
+BYTE cC;
+	cpuReg_PC++;
+	cC = cpuReg_A>>7; cpuReg_A = (cpuReg_A<<1) + (cpuFlag_C&1); cpuFlag_C = cC; cpuFlag_N = cpuFlag_Z = cpuReg_A;
+	return 2;
+}
+int opcode_0x2B(bool &holded)	/* 0x2B - ????							*/
+{
+	return 20;
+}
+int opcode_0x2C(bool &holded)	/* 0x2C - BIT ABS			4 cycles	*/
+{
+BYTE cb;
+	cb = atariMem[((WORD*)&atariMem[cpuReg_PC+1])[0]];
+	cpuFlag_Z = cb&cpuReg_A; cpuFlag_N = cb; cpuFlag_V = cb>>6;
+	cpuReg_PC+=3;
+	return 4;
+}
+int opcode_0x2D(bool &holded)	/* 0x2D - AND ABS			4 cycles	*/
+{
+	Load_ABS( AND );
+	return 4;
+}
+int opcode_0x2E(bool &holded)	/* 0x2E - ROL ABS			6 cycles	*/
+{
+	Modify_ABS( ROL );
+	return 6;
+}
+int opcode_0x2F(bool &holded)	/* 0x2F - ROL:AND ABS		6 cycles	*/
+{
+	Modify_ABS( ROLAND );
+	return 6;
+}
+int opcode_0x30(bool &holded)	/* 0x30 - BMI				2-4 cycles	*/
+{
+	CondJump( (cpuFlag_N&0x80) );
+	return 2;
+}
+int opcode_0x31(bool &holded)	/* 0x31 - AND (),Y			5,6 cycles	*/
+{
+	Load_PostY( AND );
+	return 5;
+}
+int opcode_0x32(bool &holded)	/* 0x32 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0x33(bool &holded)	/* 0x33 - ROL:AND (),Y		8 cycles	*/
+{
+	Modify_PostY( ROLAND );
+	return 8;
+}
+int opcode_0x34(bool &holded)	/* 0x34 - NOP2						*/
+{
+	cpuReg_PC+=2;
+	return 8;
+}
+int opcode_0x35(bool &holded)	/* 0x35 - AND ZP,X			4 cycles	*/
+{
+	Load_ZPX( AND );
+	return 4;
+}
+int opcode_0x36(bool &holded)	/* 0x36 - ROL ZP,X			6 cycles	*/
+{
+	Modify_ZPX( ROL );
+	return 6;
+}
+int opcode_0x37(bool &holded)	/* 0x37 - ROL:AND ZP,X		6 cycles	*/
+{
+	Modify_ZPX( ROLAND );
+	return 6;
+}
+int opcode_0x38(bool &holded)	/* 0x38 - SEC				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_C = 1;
+	return 2;
+}
+int opcode_0x39(bool &holded)	/* 0x39 - AND ABS,Y			4,5 cycles	*/
+{
+	Load_ABSY( AND );
+	return 4;
+}
+int opcode_0x3A(bool &holded)	/* 0x3A - NOP1						*/
+{
+	cpuReg_PC++;
+	return 2;
+}
+int opcode_0x3B(bool &holded)	/* 0x3B - ROL:AND ABS,Y		7 cycles	*/
+{
+	Modify_ABSY( ROLAND );
+	return 7;
+}
+int opcode_0x3C(bool &holded)	/* 0x3C - NOP3						*/
+{
+	cpuReg_PC+=3;
+	return 4;
+}
+int opcode_0x3D(bool &holded)	/* 0x3D - AND ABS,X			4,5 cycles	*/
+{
+	Load_ABSX( AND );
+	return 4;
+}
+int opcode_0x3E(bool &holded)	/* 0x3E - ROL ABS,X			7 cycles	*/
+{
+	Modify_ABSX( ROL );
+	return 7;
+}
+int opcode_0x3F(bool &holded)	/* 0x3F - ROL:AND ABS,X		7 cycles	*/
+{
+	Modify_ABSX( ROLAND );
+	return 7;
+}
+int opcode_0x40(bool &holded)	/* 0x40 - RTI				6 cycles	*/
+{
+BYTE te;
+	cpuReg_PC++;
+	cpuReg_S++; te = atariMem[0x100 + cpuReg_S];
+	cpuFlag_N = te; cpuFlag_V = (te>>6)&1; cpuFlag_B = (te>>4)&1; cpuFlag_D = (te>>3)&1; cpuFlag_I = (te>>2)&1; cpuFlag_Z = (te&2)^2; cpuFlag_C = te&1;
+	cpuReg_S++; cpuReg_PC =  (WORD)atariMem[0x100 + cpuReg_S];
+	cpuReg_S++; cpuReg_PC+= ((WORD)atariMem[0x100 + cpuReg_S])*256;
+	return 6;
+}
+int opcode_0x41(bool &holded)	/* 0x41 - EOR (,X)			6 cycles	*/
+{
+	Load_PreX( EOR );
+	return 6;
+}
+int opcode_0x42(bool &holded)	/* 0x42 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0x43(bool &holded)	/* 0x43 - LSR:EOR (,X)		8 cycles	*/
+{
+	Modify_PreX( LSREOR );
+	return 8;
+}
+int opcode_0x44(bool &holded)	/* 0x44 - NOP2				3 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x45(bool &holded)	/* 0x45 - EOR ZP			3 cycles	*/
+{
+	Load_ZP( EOR );
+	return 3;
+}
+int opcode_0x46(bool &holded)	/* 0x46 - LSR ZP			5 cycles	*/
+{
+	Modify_ZP( LSR );
+	return 5;
+}
+int opcode_0x47(bool &holded)	/* 0x47 - LSR:EOR ZP		5 cycles	*/
+{
+	Modify_ZP( LSREOR );
+	return 5;
+}
+int opcode_0x48(bool &holded)	/* 0x48 - PHA				3 cycles	*/
+{
+	cpuReg_PC++;
+	atariMem[0x100 + cpuReg_S] = cpuReg_A; cpuReg_S--;
+	return 3;
+}
+int opcode_0x49(bool &holded)	/* 0x49 - EOR #				2 cycles	*/
+{
+	Load_IMD( EOR );
+	return 2;
+}
+int opcode_0x4A(bool &holded)	/* 0x4A - LSR @				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_C = cpuReg_A; cpuReg_A>>=1; cpuFlag_N = cpuFlag_Z = cpuReg_A;
+	return 2;
+}
+int opcode_0x4B(bool &holded)	/* 0x4B - ????							*/
+{
+	cpuReg_PC--;
+	return 20;
+}
+int opcode_0x4C(bool &holded)	/* 0x4C - JMP				3 cycles	*/
+{
+	cpuReg_PC = ((WORD*)&atariMem[cpuReg_PC+1])[0];
+	return 3;
+}
+int opcode_0x4D(bool &holded)	/* 0x4D - EOR ABS			4 cycles	*/
+{
+	Load_ABS( EOR );
+	return 4;
+}
+int opcode_0x4E(bool &holded)	/* 0x4E - LSR ABS			6 cycles	*/
+{
+	Modify_ABS( LSR );
+	return 6;
+}
+int opcode_0x4F(bool &holded)	/* 0x4F - LSR:EOR ABS		6 cycles	*/
+{
+	Modify_ABS( LSREOR );
+	return 6;
+}
+
+int opcode_0x50(bool &holded)	/* 0x50 - BVC				2-4 cycles	*/
+{
+	CondJump( (cpuFlag_V&1)==0 );
+	return 2;
+}
+
+int opcode_0x51(bool &holded)	/* 0x51 - EOR (),Y			5 cycles	*/
+{
+	Load_PostY( EOR );
+	return 5;
+}
+int opcode_0x52(bool &holded)	/* 0x52 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0x53(bool &holded)	/* 0x53 - LSR:EOR (),Y		8 cycles	*/
+{
+	Modify_PostY( LSREOR );
+	return 8;
+}
+int opcode_0x54(bool &holded)	/* 0x54 - NOP2							*/
+{
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x55(bool &holded)	/* 0x55 - EOR ZP,X			4 cycles	*/
+{
+	Load_ZPX( EOR );
+	return 4;
+}
+int opcode_0x56(bool &holded)	/* 0x56 - LSR ZP,X			6 cycles	*/
+{
+	Modify_ZPX( LSR );
+	return 6;
+}
+int opcode_0x57(bool &holded)	/* 0x57 - LSR:EOR ZP,X			6 cycles	*/
+{
+	Modify_ZPX( LSREOR );
+	return 6;
+}
+int opcode_0x58(bool &holded)	/* 0x58 - CLI				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_I = 0;
+	pokeyGenerateCheckIRQline();
+	return 2;
+}
+int opcode_0x59(bool &holded)	/* 0x59 - EOR ABS,Y			4,5 cycles	*/
+{
+	Load_ABSY( EOR );
+	return 4;
+}
+int opcode_0x5A(bool &holded)	/* 0x5A - NOP1				2 cycles	*/
+{
+	cpuReg_PC++;
+	return 2;
+}
+int opcode_0x5B(bool &holded)	/* 0x5B - LSR:EOR ABS,Y		7 cycles	*/
+{
+	Modify_ABSY( EOR );
+	return 7;
+}
+int opcode_0x5C(bool &holded)	/* 0x5C - NOP3				7 cycles	*/
+{
+	cpuReg_PC+=3;
+	return 7;
+}
+int opcode_0x5D(bool &holded)	/* 0x5D - EOR ABS,X			4,5 cycles	*/
+{
+	Load_ABSX( EOR );
+	return 4;
+}
+int opcode_0x5E(bool &holded)	/* 0x5E - LSR ABS,X			7 cycles	*/
+{
+	Modify_ABSX( EOR );
+	return 7;
+}
+int opcode_0x5F(bool &holded)	/* 0x5F - LSR:EOR ABS,X		7 cycles	*/
+{
+	Modify_ABSX( LSREOR );
+	return 7;
+}
+
+int opcode_0x60(bool &holded)	/* 0x60 - RTS				6 cycles	*/
+{
+	cpuReg_S++; cpuReg_PC =  (WORD)atariMem[0x100 + cpuReg_S];
+	cpuReg_S++; cpuReg_PC+= ((WORD)atariMem[0x100 + cpuReg_S])*256 + 1;
+	return 6;
+}
+int opcode_0x61(bool &holded)	/* 0x61 - ADC (,X)			6 cycles	*/
+{
+	Load_PreX( ADC );
+	return 6;
+}
+int opcode_0x62(bool &holded)	/* 0x62 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0x63(bool &holded)	/* 0x63 - ROR:ADC (,X)		8 cycles	*/
+{
+	Modify_PreX( RORADC );
+	return 8;
+}
+int opcode_0x64(bool &holded)	/* 0x64 - NOP2				3 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x65(bool &holded)	/* 0x65 - ADC ZP			3 cycles	*/
+{
+	Load_ZP( ADC );
+	return 3;
+}
+int opcode_0x66(bool &holded)	/* 0x66 - ROR ZP			5 cycles	*/
+{
+	Modify_ZP( ROR );
+	return 5;
+}
+int opcode_0x67(bool &holded)	/* 0x67 - ROR:ADC ZP		5 cycles	*/
+{
+	Modify_ZP( RORADC );
+	return 5;
+}
+int opcode_0x68(bool &holded)	/* 0x68 - PLA				4 cycles	*/
+{			
+	cpuReg_PC++;
+	cpuReg_S++; cpuFlag_N = cpuFlag_Z = cpuReg_A = atariMem[0x100 + cpuReg_S];
+	return 4;
+}
+int opcode_0x69(bool &holded)	/* 0x69 - ADC #				2 cycles	*/
+{
+	Load_IMD( ADC );
+	return 2;
+}
+int opcode_0x6A(bool &holded)	/* 0x6A - ROR @				2 cycles	*/
+{
+BYTE cC;
+	cpuReg_PC++;
+	cC = cpuReg_A; cpuReg_A = (cpuReg_A>>1) + (cpuFlag_C<<7); cpuFlag_C = cC; cpuFlag_N = cpuFlag_Z = cpuReg_A;
+	return 2;
+}
+int opcode_0x6B(bool &holded)	/* 0x6B - ????							*/
+{
+	return 20;
+}
+int opcode_0x6C(bool &holded)	/* 0x6C - JMP ( )			6 cycles	*/
+{
+	WORD wA = ((WORD*)&atariMem[cpuReg_PC+1])[0];
+	wA = ((WORD*)&atariMem[wA])[0];
+	cpuReg_PC = wA;
+	return 6;
+}
+int opcode_0x6D(bool &holded)	/* 0x6D - ADC ABS			4 cycles	*/
+{
+	Load_ABS( ADC );
+	return 4;
+}
+int opcode_0x6E(bool &holded)	/* 0x6E - ROR ABS			6 cycles	*/
+{
+	Modify_ABS( ROR );
+	return 6;
+}
+int opcode_0x6F(bool &holded)	/* 0x6F - ROR:ADC ABS		6 cycles	*/
+{
+	Modify_ABS( RORADC );
+	return 6;
+}
+int opcode_0x70(bool &holded)	/* 0x70 - BVS				2-4 cycles	*/
+{
+	CondJump( (cpuFlag_V&1) );
+	return 2;
+}
+int opcode_0x71(bool &holded)	/* 0x71 - ADC ( ),Y			5,6 cycles	*/
+{
+	Load_PostY( ADC );
+	return 5;
+}
+int opcode_0x72(bool &holded)	/* 0x72 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0x73(bool &holded)	/* 0x73 - ROR:ADC ( ),Y		8 cycles	*/
+{
+	Modify_PostY( RORADC );
+	return 8;
+}
+int opcode_0x74(bool &holded)	/* 0x74 - NOP2				4 cycles	*/
+{
+	return 4;
+}
+int opcode_0x75(bool &holded)	/* 0x75 - ADC ZP,X			4 cycles	*/
+{
+	Load_ZPX( ADC );
+	return 4;
+}
+int opcode_0x76(bool &holded)	/* 0x76 - ROR ZP,X			6 cycles	*/
+{
+	Modify_ZPX( ROR );
+	return 6;
+}
+int opcode_0x77(bool &holded)	/* 0x77 - ROR:ADC ZP,X		6 cycles	*/
+{
+	Modify_ZPX( RORADC );
+	return 6;
+}
+int opcode_0x78(bool &holded)	/* 0x78 - SEI				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_I = 1;
+	return 2;
+}
+int opcode_0x79(bool &holded)	/* 0x79 - ADC ABS,Y			4,5 cycles	*/
+{
+	Load_ABSY( ADC );
+	return 4;
+}
+int opcode_0x7A(bool &holded)	/* 0x7A - NOP1				2 cycles	*/
+{
+	cpuReg_PC++;
+	return 2;
+}
+int opcode_0x7B(bool &holded)	/* 0x7B - ROR:ADC ABS,Y		6 cycles	*/
+{
+	Modify_ABSY( RORADC );
+	return 6;
+}
+int opcode_0x7C(bool &holded)	/* 0x7C - NOP3				7 cycles	*/
+{
+	cpuReg_PC+=3;
+	return 7;
+}
+int opcode_0x7D(bool &holded)	/* 0x7D - ADC ABS,X			4,5 cycles	*/
+{
+	Load_ABSX( ADC );
+	return 4;
+}
+int opcode_0x7E(bool &holded)	/* 0x7E - ROR ABS,X			7 cycles	*/
+{
+	Modify_ABSX( ROR );
+	return 7;
+}
+int opcode_0x7F(bool &holded)	/* 0x7F - ROR:ADC ABS,X		7 cycles	*/
+{
+	Modify_ABSX( RORADC );
+	return 7;
+}
+
+int opcode_0x80(bool &holded)	/* 0x80 - NOP2				2 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 2;
+}
+int opcode_0x81(bool &holded)	/* 0x81 - STA ( ,X)			6 cycles	*/
+{
+	Store_PreX( cpuReg_A );
+	return 6;
+}
+int opcode_0x82(bool &holded)	/* 0x82 - NOP2				2 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 2;
+}
+int opcode_0x83(bool &holded)	/* 0x83 - STORE(A&X)	(,X)	6 cycles	*/
+{
+	Store_PreX( (cpuReg_A&cpuReg_X) );
+	return 6;
+}
+int opcode_0x84(bool &holded)	/* 0x84 - STY ZP				3 cycles	*/
+{
+	atariMem[atariMem[cpuReg_PC+1]] = cpuReg_Y;
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x85(bool &holded)	/* 0x85 - STA ZP				3 cycles	*/
+{
+	atariMem[atariMem[cpuReg_PC+1]] = cpuReg_A;
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x86(bool &holded)	/* 0x86 - STX ZP				3 cycles	*/
+{
+	atariMem[atariMem[cpuReg_PC+1]] = cpuReg_X;
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x87(bool &holded)	/* 0x87 - STORE(A&X)	ZP		3 cycles	*/
+{
+	atariMem[atariMem[cpuReg_PC+1]] = cpuReg_A&cpuReg_X;
+	cpuReg_PC+=2;
+	return 3;
+}
+int opcode_0x88(bool &holded)	/* 0x88 - DEY				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuReg_Y--;
+	cpuFlag_N = cpuFlag_Z = cpuReg_Y;
+	return 2;
+}
+int opcode_0x89(bool &holded)	/* 0x89 - NOP2				2 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 2;
+}
+int opcode_0x8A(bool &holded)	/* 0x8A - TXA				2 cycles	*/
+{
+	cpuReg_PC+=1;
+	cpuFlag_N = cpuFlag_Z = cpuReg_A = cpuReg_X;
+	return 2;
+}
+int opcode_0x8B(bool &holded)	/* 0x8B - TXA:AND #			2 cycles	*/
+{
+	cpuReg_A = cpuReg_X;
+	cpuFlag_N = cpuFlag_Z = cpuReg_A = cpuReg_A & atariMem[cpuReg_PC+1];
+	cpuReg_PC+=2;
+	return 2;
+}
+int opcode_0x8C(bool &holded)	/* 0x8C - STY ABS			4 cycles	*/
+{
+	Store_ABS( cpuReg_Y );
+	return 4;
+}
+int opcode_0x8D(bool &holded)	/* 0x8D - STA ABS			4 cycles	*/
+{
+	Store_ABS( cpuReg_A );
+	return 4;
+}
+int opcode_0x8E(bool &holded)	/* 0x8E - STX ABS			4 cycles	*/
+{
+	Store_ABS( cpuReg_X );
+	return 4;
+}
+int opcode_0x8F(bool &holded)	/* 0x8F - STORE(A&X)	ABS		4 cycles	*/
+{
+	Store_ABS( (cpuReg_A&cpuReg_X) );
+	return 4;
+}
+int opcode_0x90(bool &holded)	/* 0x90 - BCC				2-4 cycles	*/
+{
+	CondJump( (cpuFlag_C&1)==0 );
+	return 2;
+}
+int opcode_0x91(bool &holded)	/* 0x91 - STA ( ),Y			6 cycles	*/
+{
+	Store_PostY( cpuReg_A );
+	return 6;
+}
+int opcode_0x92(bool &holded)	/* 0x92 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0x93(bool &holded)	/* 0x93 - STORE(A&X)	(),Y	4,5 cycles	*/
+{
+	Store_PostY( (cpuReg_A&cpuReg_X) );
+	return 6;
+}
+int opcode_0x94(bool &holded)	/* 0x94 - STY ZP,X			4 cycles	*/
+{
+	atariMem[(atariMem[cpuReg_PC+1]+cpuReg_X)&0xFF] = cpuReg_Y;
+	cpuReg_PC+=2;
+	return 4;
+}
+int opcode_0x95(bool &holded)	/* 0x95 - STA ZP,X			4 cycles	*/
+{
+	atariMem[(atariMem[cpuReg_PC+1]+cpuReg_X)&0xFF] = cpuReg_A;
+	cpuReg_PC+=2;
+	return 4;
+}
+int opcode_0x96(bool &holded)	/* 0x96 - STX ZP,Y			4 cycles	*/
+{
+	atariMem[(atariMem[cpuReg_PC+1]+cpuReg_Y)&0xFF] = cpuReg_X;
+	cpuReg_PC+=2;
+	return 4;
+}
+int opcode_0x97(bool &holded)	/* 0x97 - STORE(A&X)	ZP,Y	4 cycles	*/
+{
+	atariMem[(atariMem[cpuReg_PC+1]+cpuReg_Y)&0xFF] = cpuReg_X&cpuReg_A;
+	cpuReg_PC+=2;
+	return 4;
+}
+int opcode_0x98(bool &holded)	/* 0x98 - TYA				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_N = cpuFlag_Z = cpuReg_A = cpuReg_Y;
+	return 2;
+}
+int opcode_0x99(bool &holded)	/* 0x99 - STA ABS,Y			5 cycles	*/
+{
+	Store_ABSY( cpuReg_A );
+	return 5;
+}
+int opcode_0x9A(bool &holded)	/* 0x9A - TXS				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuReg_S = cpuReg_X;
+	return 2;
+}
+int opcode_0x9B(bool &holded)	/* 0x9B - ????							*/
+{
+	return 20;
+}
+int opcode_0x9C(bool &holded)	/* 0x9C - ????							*/
+{
+	return 20;
+}
+int opcode_0x9D(bool &holded)	/* 0x9D - STA ABS,X			5 cycles	*/
+{
+	Store_ABSX( cpuReg_A );
+	return 5;
+}
+int opcode_0x9E(bool &holded)	/* 0x9E - ????							*/
+{
+	return 20;
+}
+int opcode_0x9F(bool &holded)	/* 0x9F - ????							*/
+{
+	return 20;
+}
+int opcode_0xA0(bool &holded)	/* 0xA0 - LDY #				2 cycles	*/
+{
+	LoadReg_IMD( cpuReg_Y );
+	return 2;
+}
+int opcode_0xA1(bool &holded)	/* 0xA1 - LDA (,X)			6 cycles	*/
+{
+	LoadReg_PreX( cpuReg_A );
+	return 6;
+}
+int opcode_0xA2(bool &holded)	/* 0xA2 - LDX #				2 cycles	*/
+{
+	LoadReg_IMD( cpuReg_X );
+	return 2;
+}
+int opcode_0xA3(bool &holded)	/* 0xA3 - LDA:TAX (,X)		6 cycles	*/
+{
+	LoadReg_IMD( cpuReg_A );
+	cpuReg_X = cpuReg_A;
+	return 6;
+}
+int opcode_0xA4(bool &holded)	/* 0xA4 - LDY ZP				3 cycles	*/
+{
+	LoadReg_ZP( cpuReg_Y );
+	return 3;
+}
+int opcode_0xA5(bool &holded)	/* 0xA5 - LDA ZP				3 cycles	*/
+{
+	LoadReg_ZP( cpuReg_A );
+	return 3;
+}
+int opcode_0xA6(bool &holded)	/* 0xA6 - LDX ZP				3 cycles	*/
+{
+	LoadReg_ZP( cpuReg_X );
+	return 3;
+}
+int opcode_0xA7(bool &holded)	/* 0xA7 - LDA:TAX ZP			3 cycles	*/
+{
+	LoadReg_ZP( cpuReg_A );
+	cpuReg_X = cpuReg_A;
+	return 3;
+}
+int opcode_0xA8(bool &holded)	/* 0xA8 - TAY				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_N = cpuFlag_Z = cpuReg_Y = cpuReg_A;
+	return 2;
+}
+int opcode_0xA9(bool &holded)	/* 0xA9 - LDA #				2 cycles	*/
+{
+	LoadReg_IMD( cpuReg_A );
+	return 2;
+}
+int opcode_0xAA(bool &holded)	/* 0xAA - TAX				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_N = cpuFlag_Z = cpuReg_X = cpuReg_A;
+	return 2;
+}
+int opcode_0xAB(bool &holded)	/* 0xAB - AND #:TAX			2 cycles	*/
+{
+	cpuFlag_N = cpuFlag_Z = cpuReg_A = cpuReg_X = cpuReg_A & atariMem[cpuReg_PC+1];
+	cpuReg_PC+=2;
+	return 2;
+}
+int opcode_0xAC(bool &holded)	/* 0xAC - LDY ABS			4 cycles	*/
+{
+	LoadReg_ABS( cpuReg_Y );
+	return 4;
+}
+int opcode_0xAD(bool &holded)	/* 0xAD - LDA ABS			4 cycles	*/
+{
+	LoadReg_ABS( cpuReg_A );
+	return 4;
+}
+int opcode_0xAE(bool &holded)	/* 0xAE - LDX ABS			4 cycles	*/
+{
+	LoadReg_ABS( cpuReg_X );
+	return 4;
+}
+int opcode_0xAF(bool &holded)	/* 0xAF - LDA:TAX ABS		4 cycles	*/
+{
+	LoadReg_ABS( cpuReg_A );
+	cpuReg_X = cpuReg_A;
+	return 4;
+}
+int opcode_0xB0(bool &holded)	/* 0xB0 - BCS				2-4 cycles	*/
+{
+	CondJump( (cpuFlag_C&1) );
+	return 2;
+}
+int opcode_0xB1(bool &holded)	/* 0xB1 - LDA ( ),Y			5,6 cycles	*/
+{
+	LoadReg_PostY( cpuReg_A );
+	return 5;
+}
+int opcode_0xB2(bool &holded)	/* 0xB2 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0xB3(bool &holded)	/* 0xB3 - LDA:TAX ( ),Y		5,6 cycles	*/
+{
+	LoadReg_PostY( cpuReg_A );
+	cpuReg_X = cpuReg_A;
+	return 5;
+}
+int opcode_0xB4(bool &holded)	/* 0xB4 - LDY ZP,X			4 cycles	*/
+{
+	LoadReg_ZPX( cpuReg_Y );
+	return 4;
+}
+int opcode_0xB5(bool &holded)	/* 0xB5 - LDA ZP,X			4 cycles	*/
+{
+	LoadReg_ZPX( cpuReg_A );
+	return 4;
+}
+int opcode_0xB6(bool &holded)	/* 0xB6 - LDX ZP,Y			4 cycles	*/
+{
+	LoadReg_ZPY( cpuReg_X );
+	return 4;
+}
+int opcode_0xB7(bool &holded)	/* 0xB7 - LDA:TAX ZP,Y		4 cycles	*/
+{
+	LoadReg_ZPY( cpuReg_X );
+	cpuReg_A = cpuReg_X;
+	return 4;
+}
+int opcode_0xB8(bool &holded)	/* 0xB8 - CLV				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_V = 0;
+	return 2;
+}
+int opcode_0xB9(bool &holded)	/* 0xB9 - LDA ABS,Y			4,5 cycles	*/
+{
+	LoadReg_ABSY( cpuReg_A );
+	return 4;
+}
+int opcode_0xBA(bool &holded)	/* 0xBA - TSX				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_N = cpuFlag_Z = cpuReg_X = cpuReg_S;
+	return 2;
+}
+int opcode_0xBB(bool &holded)	/* 0xBB - ????							*/
+{
+	return 20;
+}
+int opcode_0xBC(bool &holded)	/* 0xBC - LDY ABS,X			4,5 cycles	*/
+{
+	LoadReg_ABSX( cpuReg_Y );
+	return 4;
+}
+int opcode_0xBD(bool &holded)	/* 0xBD - LDA ABS,X			4,5 cycles	*/
+{
+	LoadReg_ABSX( cpuReg_A );
+	return 4;
+}
+int opcode_0xBE(bool &holded)	/* 0xBE - LDX ABS,Y			4,5 cycles	*/
+{
+	LoadReg_ABSY( cpuReg_X );
+	return 4;
+}
+int opcode_0xBF(bool &holded)	/* 0xBF - LDA:TAX ABS,Y		4,5 cycles	*/
+{
+	LoadReg_ABSY( cpuReg_X );
+	cpuReg_A = cpuReg_X;
+	return 4;
+}
+int opcode_0xC0(bool &holded)	/* 0xC0 - CPY #				2 cycles	*/
+{
+	Load_IMD( CPY );
+	return 2;
+}
+int opcode_0xC1(bool &holded)	/* 0xC1 - CMP (,X)			6 cycles	*/
+{
+	Load_PreX( CMP );
+	return 6;
+}
+int opcode_0xC2(bool &holded)	/* 0xC2 - NOP2				2 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 2;
+}
+int opcode_0xC3(bool &holded)	/* 0xC3 - DEC:CMP (,X)		8 cycles	*/
+{
+	Modify_PreX( DECCMP );
+	return 8;
+}
+int opcode_0xC4(bool &holded)	/* 0xC4 - CPY ZP				3 cycles	*/
+{
+	Load_ZP( CPY );
+	return 3;
+}
+int opcode_0xC5(bool &holded)	/* 0xC5 - CMP ZP				3 cycles	*/
+{
+	Load_ZP( CMP );
+	return 3; 
+}
+int opcode_0xC6(bool &holded)	/* 0xC6 - DEC ZP				5 cycles	*/
+{
+	Modify_ZP( DEC );
+	return 5;
+}
+int opcode_0xC7(bool &holded)	/* 0xC7 - DEC:CMP ZP			5 cycles	*/
+{
+	Modify_ZP( DECCMP );
+	return 8;
+}
+int opcode_0xC8(bool &holded)	/* 0xC8 - INY				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_N = cpuFlag_Z = cpuReg_Y = cpuReg_Y+1;
+	return 2;
+}
+int opcode_0xC9(bool &holded)	/* 0xC9 - CMP #				2 cycles	*/
+{
+	Load_IMD( CMP );
+	return 2;
+}
+int opcode_0xCA(bool &holded)	/* 0xCA - DEX				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_N = cpuFlag_Z = cpuReg_X = cpuReg_X-1;
+	return 2;
+}
+int opcode_0xCB(bool &holded)	/* 0xCB - ????							*/
+{
+	return 20;
+}
+int opcode_0xCC(bool &holded)	/* 0xCC - CPY ABS			4 cycles	*/
+{
+	Load_ABS( CPY );
+	return 4;
+}
+int opcode_0xCD(bool &holded)	/* 0xCD - CMP ABS			4 cycles	*/
+{
+	Load_ABS( CMP );
+	return 4;
+}
+int opcode_0xCE(bool &holded)	/* 0xCE - DEC ABS			6 cycles	*/
+{
+	Modify_ABS( DEC );
+	return 6;
+}
+int opcode_0xCF(bool &holded)	/* 0xCF - DEC:CMP ABS		6 cycles	*/
+{
+	Modify_ABS( DECCMP );
+	return 6;
+}
+int opcode_0xD0(bool &holded)	/* 0xD0 - BNE				2-4 cycles	*/
+{
+	CondJump( cpuFlag_Z );
+	return 2;
+}
+int opcode_0xD1(bool &holded)	/* 0xD1 - CMP (),Y			5,6 cycles	*/
+{
+	Load_PostY( CMP );
+	return 5;
+}
+int opcode_0xD2(bool &holded)	/* 0xD2 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0xD3(bool &holded)	/* 0xD3 - DEC:CMP (),Y			8 cycles	*/
+{
+	Modify_PostY( DECCMP );
+	return 8;
+}
+int opcode_0xD4(bool &holded)	/* 0xD4 - NOP2				4 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 4;
+}
+int opcode_0xD5(bool &holded)	/* 0xD5 - CMP ZP,X			4 cycles	*/
+{
+	Load_ZPX( CMP );
+	return 4;
+}
+int opcode_0xD6(bool &holded)	/* 0xD6 - DEC ZP,X			6 cycles	*/
+{
+	Modify_ZPX( DEC );
+	return 6;
+}
+int opcode_0xD7(bool &holded)	/* 0xD7 - DEC:CMP ZP,X		6 cycles	*/
+{
+	Modify_ZPX( DECCMP );
+	return 6;
+}
+int opcode_0xD8(bool &holded)	/* 0xD8 - CLD				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_D = 0;
+	return 2;
+}
+int opcode_0xD9(bool &holded)	/* 0xD9 - CMP ABS,Y			4,5 cycles	*/
+{			
+	Load_ABSY( CMP );
+	return 4;
+}
+int opcode_0xDA(bool &holded)	/* 0xDA - NOP1				2 cycles	*/
+{
+	cpuReg_PC++;
+	return 2;
+}
+int opcode_0xDB(bool &holded)	/* 0xDB - DEC:CMP ABS,Y		7 cycles	*/
+{
+	Modify_ABSY( DECCMP );
+	return 7;
+}
+int opcode_0xDC(bool &holded)	/* 0xDC - NOP3				4 cycles	*/
+{
+	cpuReg_PC+=3;
+	return 4;
+}
+int opcode_0xDD(bool &holded)	/* 0xDD - CMP ABS,X			4,5 cycles	*/
+{
+	Load_ABSX( CMP );
+	return 4;
+}
+int opcode_0xDE(bool &holded)	/* 0xDE - DEC ABS,X			7 cycles	*/
+{
+	Modify_ABSX( DEC );
+	return 7;
+}
+int opcode_0xDF(bool &holded)	/* 0xDF - DEC:CMP ABS,X		7 cycles	*/
+{			
+	Modify_ABSX( DECCMP );
+	return 7;
+}
+int opcode_0xE0(bool &holded)	/* 0xE0 - CPX #				2 cycles	*/
+{
+	Load_IMD( CPX );
+	return 2;
+}
+int opcode_0xE1(bool &holded)	/* 0xE1 - SBC (,X)			6 cycles	*/
+{
+	Load_PreX( SBC );
+	return 6;
+}
+int opcode_0xE2(bool &holded)	/* 0xE2 - NOP2				2 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 2;
+}
+int opcode_0xE3(bool &holded)	/* 0xE3 - INC:SBC (,X)		8 cycles	*/
+{
+	Modify_PreX( INCSBC );
+	return 8;
+}
+int opcode_0xE4(bool &holded)	/* 0xE4 - CPX ZP				3 cycles	*/
+{
+	Load_ZP( CPX );
+	return 3;
+}
+int opcode_0xE5(bool &holded)	/* 0xE5 - SBC ZP				3 cycles	*/
+{
+	Load_ZP( SBC );
+	return 3;
+}
+int opcode_0xE6(bool &holded)	/* 0xE6 - INC ZP				5 cycles	*/
+{
+	Modify_ZP( INC );
+	return 5;
+}
+int opcode_0xE7(bool &holded)	/* 0xE7 - INC:SBC ZP			5 cycles	*/
+{
+	Modify_ZP( INCSBC );
+	return 5;
+}
+int opcode_0xE8(bool &holded)	/* 0xE8 - INX				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_N = cpuFlag_Z = cpuReg_X = cpuReg_X+1;
+	return 2;
+}
+int opcode_0xE9(bool &holded)	/* 0xE9 - SBC #				2 cycles	*/
+{
+	Load_IMD( SBC );
+	return 2;
+}
+int opcode_0xEA(bool &holded)	/* 0xEA - NOP				2 cycles	*/
+{
+	cpuReg_PC++;
+	return 2;
+}
+int opcode_0xEB(bool &holded)	/* 0xEB - ????							*/
+{
+	return 20;
+}
+int opcode_0xEC(bool &holded)	/* 0xEC - CPX ABS			4 cycles	*/
+{
+	Load_ABS( CPX );
+	return 4;
+}
+int opcode_0xED(bool &holded)	/* 0xED - SBC ABS			4 cycles	*/
+{
+	Load_ABS( SBC );
+	return 4;
+}
+int opcode_0xEE(bool &holded)	/* 0xEE - INC ABS			6 cycles	*/
+{
+	Modify_ABS( INC );
+	return 6;
+}
+int opcode_0xEF(bool &holded)	/* 0xEF - INC:SBC ABS		6 cycles	*/
+{
+	Modify_ABS( INCSBC );
+	return 6;
+}
+int opcode_0xF0(bool &holded)	/* 0xF0 - BEQ				2-4 cycles	*/
+{
+	CondJump( (cpuFlag_Z==0) );
+	return 2;
+}
+int opcode_0xF1(bool &holded)	/* 0xF1 - SBC (),Y			5,6 cycles	*/
+{
+	Load_PostY( SBC );
+	return 5;
+}
+int opcode_0xF2(bool &holded)	/* 0xF2 - ...				hang		*/
+{
+	return 20;
+}
+int opcode_0xF3(bool &holded)	/* 0xF3 - INC:SBC (),Y			8 cycles	*/
+{
+	Modify_PostY( INCSBC );
+	return 8;
+}
+int opcode_0xF4(bool &holded)	/* 0xF4 - NOP2				4 cycles	*/
+{
+	cpuReg_PC+=2;
+	return 4;
+}
+int opcode_0xF5(bool &holded)	/* 0xF5 - SBC ZP,X			4 cycles	*/
+{
+	Load_ZPX( SBC );
+	return 4;
+}
+int opcode_0xF6(bool &holded)	/* 0xF6 - INC ZP,X			6 cycles	*/
+{
+	Modify_ZPX( INC );
+	return 6;
+}
+int opcode_0xF7(bool &holded)	/* 0xF7 - INC:SBC ZP,X		6 cycles	*/
+{
+	Modify_ZPX( INCSBC );
+	return 6;
+}
+int opcode_0xF8(bool &holded)	/* 0xF8 - SED				2 cycles	*/
+{
+	cpuReg_PC++;
+	cpuFlag_D = 1;
+	return 2;
+}
+int opcode_0xF9(bool &holded)	/* 0xF9 - SBC ABS,Y			4,5 cycles	*/
+{
+	Load_ABSY( SBC );
+	return 4;
+}
+int opcode_0xFA(bool &holded)	/* 0xFA - NOP1				2 cycles	*/
+{
+	cpuReg_PC++;
+	return 2;
+}
+int opcode_0xFB(bool &holded)	/* 0xFB - INC:SBC ABS,Y		7 cycles	*/
+{
+	Modify_ABSY( INCSBC );
+	return 7;
+}
+int opcode_0xFC(bool &holded)	/* 0xDC - NOP3				4 cycles	*/
+{
+	cpuReg_PC+=3;
+	return 4;
+}
+int opcode_0xFD(bool &holded)	/* 0xFD - SBC ABS,X			4,5 cycles	*/
+{
+	Load_ABSX( SBC );
+	return 4;
+}
+int opcode_0xFE(bool &holded)	/* 0xFE - INC ABS,X			7 cycles	*/
+{
+	Modify_ABSX( INC );
+	return 7;
+}
+int opcode_0xFF(bool &holded)	/* 0xDF - INC:SBC ABS,X		7 cycles	*/
+{
+	Modify_ABSX( INCSBC );
+	return 7;
+}
+
+opcodeFunc opcodes_0x00_0xFF[256]={
+	&opcode_0x00, &opcode_0x01, &opcode_0x02, &opcode_0x03, &opcode_0x04, &opcode_0x05, &opcode_0x06, &opcode_0x07,
+	&opcode_0x08, &opcode_0x09, &opcode_0x0A, &opcode_0x0B, &opcode_0x0C, &opcode_0x0D, &opcode_0x0E, &opcode_0x0F,
+	&opcode_0x10, &opcode_0x11, &opcode_0x12, &opcode_0x13, &opcode_0x14, &opcode_0x15, &opcode_0x16, &opcode_0x17,
+	&opcode_0x18, &opcode_0x19, &opcode_0x1A, &opcode_0x1B, &opcode_0x1C, &opcode_0x1D, &opcode_0x1E, &opcode_0x1F,
+	&opcode_0x20, &opcode_0x21, &opcode_0x22, &opcode_0x23, &opcode_0x24, &opcode_0x25, &opcode_0x26, &opcode_0x27,
+	&opcode_0x28, &opcode_0x29, &opcode_0x2A, &opcode_0x2B, &opcode_0x2C, &opcode_0x2D, &opcode_0x2E, &opcode_0x2F,
+	&opcode_0x30, &opcode_0x31, &opcode_0x32, &opcode_0x33, &opcode_0x34, &opcode_0x35, &opcode_0x36, &opcode_0x37,
+	&opcode_0x38, &opcode_0x39, &opcode_0x3A, &opcode_0x2B, &opcode_0x3C, &opcode_0x3D, &opcode_0x3E, &opcode_0x3F,
+	&opcode_0x40, &opcode_0x41, &opcode_0x42, &opcode_0x43, &opcode_0x44, &opcode_0x45, &opcode_0x46, &opcode_0x47,
+	&opcode_0x48, &opcode_0x49, &opcode_0x4A, &opcode_0x4B, &opcode_0x4C, &opcode_0x4D, &opcode_0x4E, &opcode_0x4F,
+	&opcode_0x50, &opcode_0x51, &opcode_0x52, &opcode_0x53, &opcode_0x54, &opcode_0x55, &opcode_0x56, &opcode_0x57,
+	&opcode_0x58, &opcode_0x59, &opcode_0x5A, &opcode_0x5B, &opcode_0x5C, &opcode_0x5D, &opcode_0x5E, &opcode_0x5F,
+	&opcode_0x60, &opcode_0x61, &opcode_0x62, &opcode_0x63, &opcode_0x64, &opcode_0x65, &opcode_0x66, &opcode_0x67,
+	&opcode_0x68, &opcode_0x69, &opcode_0x6A, &opcode_0x6B, &opcode_0x6C, &opcode_0x6D, &opcode_0x6E, &opcode_0x6F,
+	&opcode_0x70, &opcode_0x71, &opcode_0x72, &opcode_0x73, &opcode_0x74, &opcode_0x75, &opcode_0x76, &opcode_0x77,
+	&opcode_0x78, &opcode_0x79, &opcode_0x7A, &opcode_0x7B, &opcode_0x7C, &opcode_0x7D, &opcode_0x7E, &opcode_0x7F,
+	&opcode_0x80, &opcode_0x81, &opcode_0x82, &opcode_0x83, &opcode_0x84, &opcode_0x85, &opcode_0x86, &opcode_0x87,
+	&opcode_0x88, &opcode_0x89, &opcode_0x8A, &opcode_0x8B, &opcode_0x8C, &opcode_0x8D, &opcode_0x8E, &opcode_0x8F,
+	&opcode_0x90, &opcode_0x91, &opcode_0x92, &opcode_0x93, &opcode_0x94, &opcode_0x95, &opcode_0x96, &opcode_0x97,
+	&opcode_0x98, &opcode_0x99, &opcode_0x9A, &opcode_0x9B, &opcode_0x9C, &opcode_0x9D, &opcode_0x9E, &opcode_0x9F,
+	&opcode_0xA0, &opcode_0xA1, &opcode_0xA2, &opcode_0xA3, &opcode_0xA4, &opcode_0xA5, &opcode_0xA6, &opcode_0xA7,
+	&opcode_0xA8, &opcode_0xA9, &opcode_0xAA, &opcode_0xAB, &opcode_0xAC, &opcode_0xAD, &opcode_0xAE, &opcode_0xAF,
+	&opcode_0xB0, &opcode_0xB1, &opcode_0xB2, &opcode_0xB3, &opcode_0xB4, &opcode_0xB5, &opcode_0xB6, &opcode_0xB7,
+	&opcode_0xB8, &opcode_0xB9, &opcode_0xBA, &opcode_0xBB, &opcode_0xBC, &opcode_0xBD, &opcode_0xBE, &opcode_0xBF,
+	&opcode_0xC0, &opcode_0xC1, &opcode_0xC2, &opcode_0xC3, &opcode_0xC4, &opcode_0xC5, &opcode_0xC6, &opcode_0xC7,
+	&opcode_0xC8, &opcode_0xC9, &opcode_0xCA, &opcode_0xCB, &opcode_0xCC, &opcode_0xCD, &opcode_0xCE, &opcode_0xCF,
+	&opcode_0xD0, &opcode_0xD1, &opcode_0xD2, &opcode_0xD3, &opcode_0xD4, &opcode_0xD5, &opcode_0xD6, &opcode_0xD7,
+	&opcode_0xD8, &opcode_0xD9, &opcode_0xDA, &opcode_0xDB, &opcode_0xDC, &opcode_0xDD, &opcode_0xDE, &opcode_0xDF,
+	&opcode_0xE0, &opcode_0xE1, &opcode_0xE2, &opcode_0xE3, &opcode_0xE4, &opcode_0xE5, &opcode_0xE6, &opcode_0xE7,
+	&opcode_0xE8, &opcode_0xE9, &opcode_0xEA, &opcode_0xEB, &opcode_0xEC, &opcode_0xED, &opcode_0xEE, &opcode_0xEF,
+	&opcode_0xF0, &opcode_0xF1, &opcode_0xF2, &opcode_0xF3, &opcode_0xF4, &opcode_0xF5, &opcode_0xF6, &opcode_0xF7,
+	&opcode_0xF8, &opcode_0xF9, &opcode_0xFA, &opcode_0xFB, &opcode_0xFC, &opcode_0xFD, &opcode_0xFE, &opcode_0xFF,
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/sapEngine.cpp	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,657 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define __MAIN_DECLARATIONS__
+
+#include "sapGlobals.h"
+
+#include "sapLib.h"
+
+namespace _SAP_internals_ {
+
+void playerCallSubroutine( WORD address );
+void playerProcessOneFrame( void );
+
+volatile int prSbp;
+volatile int musicAddress,playerAddress,playerInit,playerType,defSong,fastPlay;
+volatile BOOL fileLoadStatus=FALSE;
+
+char inputBuffer[65536];
+char commentBuffer[65536];
+
+sapMUSICstrc currentMusic;
+
+BYTE emulEmptyLine[]={
+	1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,	0,  0,	0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  1,  0,  0,
+	0,  1,  0,  0,  0,  1,  0,  0,  0,  1,  0,  0,  0,  1,  0,  0,	0,  1,  0,  0,  0,  1,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
+	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	0,  0,	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 	0,  0 
+};
+
+}
+
+using namespace _SAP_internals_;
+
+sapMUSICstrc *sapLoadMusicFile( char *fname )
+{
+BOOL formatKnown,binaryFile; int i;
+int numOfSongs;
+
+	fileLoadStatus = FALSE;
+	if( fname==NULL )
+		return NULL;
+
+	cpuInit( );
+	pokeyInit( );
+	pokeyReset( );
+	prSbp = 0;
+	sndBufPtr = 0;
+	memset( sndBuf, 0, sizeof(sndBuf) );
+	commentBuffer[0] = 0;
+	memset( atariMem, 0, sizeof(atariMem) );
+	atariMem[0x0000] = 0xFF; // CMC bug.
+	atariMem[0xFEFF] = 0xFF; // CMC bug.
+//	atariMem[0xFFFE] = 0xFF; // CMC bug.
+//	atariMem[0xFFFF] = 0xFF; // CMC bug.
+
+	isStereo = false;
+	sampleStep = 1;
+	formatKnown = FALSE; binaryFile = FALSE;
+	musicAddress = playerAddress = playerType = numOfSongs = defSong = fastPlay = -1;
+	FILE *inpf;
+	inpf = fopen( fname, "rb" );
+	if( inpf!=NULL )
+	{
+		BYTE blkHead[4]; WORD blkBegin = 0,blkEnd = 0; int blk;
+
+		blk = 0; i = 0;
+		while( 1 )
+		{
+			int val; val = fgetc( inpf );
+			if( formatKnown==FALSE )
+			{
+				if( (val==EOF) || (i>=4) )
+				{
+					// error
+					break;
+				}
+				if( (val==0x0A) || (val==0x0D) )
+				{
+					inputBuffer[i] = 0;
+					if( strcmp( inputBuffer, "SAP" )!=0 )
+					{
+						// error
+						break;
+					}
+					// headerID is OK
+					i = 0;
+					formatKnown = TRUE;
+					continue;;
+				}
+				inputBuffer[i++] = (char)val;
+			}
+			else if( binaryFile==FALSE )
+			{
+				if( val==EOF )
+				{
+					// error
+					break;
+				}
+				if( val==0xFF )
+				{
+					if( i!=0 )
+					{
+						// error. There wasn't EOL in this line
+						break;
+					}
+					// so this is the end of header
+					binaryFile = TRUE;
+					blkHead[blk++] = (BYTE)val;
+					continue;
+				}
+				if( (val==0x0A) || (val==0x0D) )
+				{
+					if( i==0 )
+						continue;
+					inputBuffer[i++] = 0;
+					char *codes[]={ "PLAYER", "MUSIC", "INIT", "TYPE", "SONGS", "DEFSONG", "FASTPLAY", "STEREO", "TIME", NULL };
+					int j,k,a;
+					for( j=0;; j++ )
+					{
+						if( codes[j]==NULL )
+							break;
+						k = 0;
+						while( 1 )
+						{
+							if( k>=i )
+							{
+								// not this code
+								i = 0;
+								break;
+							}
+							if( (codes[j][k]==0) && ((inputBuffer[k]==' ') || (inputBuffer[k]==0)) )
+							{
+								// found
+								switch( j )
+								{
+									case 0: // player address
+										a = strtol( &inputBuffer[k], NULL, 16 );
+										if( (a==0) || (a>0xFFFF) )
+										{
+											// error
+											i = 0;
+											goto cont;
+										}
+										playerAddress = a;
+										i = 0;
+										goto cont;
+										break;
+									case 1: // music address
+										a = strtol( &inputBuffer[k], NULL, 16 );
+										if( (a==0) || (a>0xFFFF) )
+										{
+											// error
+											i = 0;
+											goto cont;
+										}
+										musicAddress = a;
+										i = 0;
+										goto cont;
+										break;
+									case 2: // binary player init
+										a = strtol( &inputBuffer[k], NULL, 16 );
+										if( (a==0) || (a>0xFFFF) )
+										{
+											// error
+											i = 0;
+											goto cont;
+										}
+										playerInit = a;
+										i = 0;
+										goto cont;
+										break;
+									case 3: // player type
+										while( inputBuffer[k]!=0 )
+										{
+											if( (inputBuffer[k]=='B') || (inputBuffer[k]=='b') )
+											{
+												playerType = 'b';
+												break;
+											}
+											if( (inputBuffer[k]=='C') || (inputBuffer[k]=='c') )
+											{
+												playerType = 'c';
+												break;
+											}
+											if( (inputBuffer[k]=='D') || (inputBuffer[k]=='d') )
+											{
+												playerType = 'd';
+												break;
+											}
+											if( (inputBuffer[k]=='S') || (inputBuffer[k]=='s') )
+											{
+												playerType = 's';
+												break;
+											}
+											if( !isspace(inputBuffer[k]) )
+											{
+												i = 0;
+												goto cont;
+											}
+											k++;
+										}
+										i = 0;
+										goto cont;
+										break;
+									case 4: // num of songs
+										a = strtol( &inputBuffer[k], NULL, 10 );
+										if( (a==0) || (a>0xFFFF) )
+										{
+											// error
+											i = 0;
+											goto cont;
+										}
+										numOfSongs = a;
+										sprintf( &commentBuffer[ strlen(commentBuffer) ], "Number of songs = %d\n", numOfSongs );
+										i = 0;
+										goto cont;
+										break;
+									case 5: // default songs
+										a = strtol( &inputBuffer[k], NULL, 10 );
+										if( (a==0) || (a>0xFFFF) )
+										{
+											// error
+											i = 0;
+											goto cont;
+										}
+										defSong = a;
+										i = 0;
+										goto cont;
+										break;
+									case 6: // fastPlay
+										a = strtol( &inputBuffer[k], NULL, 10 );
+										if( (a==0) || (a>0xFFFF) )
+										{
+											// error
+											i = 0;
+											goto cont;
+										}
+										fastPlay = a;
+										i = 0;
+										goto cont;
+										break;
+									case 7: // Stereo
+										isStereo = true;
+										sampleStep = 2;
+										sprintf( &commentBuffer[ strlen(commentBuffer) ], "In Stereo!\n" );
+										i = 0;
+										goto cont;
+										break;
+									case 8: // Time
+									{
+										int min,sec;
+										min = sec = -1;
+										sscanf( &inputBuffer[k], "%d:%d", &min, &sec );
+										if( min==-1 || sec==-1 )
+										{
+											i = 0;
+											goto cont;
+										}
+										sprintf( &commentBuffer[ strlen(commentBuffer) ], "Time in sec %d\n", min*60+sec );
+										i = 0;
+										goto cont;
+										break;
+									}
+								}
+								i = 0;
+								goto cont;
+							}
+							if( codes[j][k]==0 )
+								break; // not this code
+							if( codes[j][k]!=inputBuffer[k] )
+								break; // not this code
+							k++;
+						}
+					}
+					sprintf( &commentBuffer[ strlen(commentBuffer) ], "%s\n", inputBuffer );
+					// not found
+					i = 0;
+					continue;
+				}
+				inputBuffer[i++] = (char)val;
+			}
+			else if( binaryFile==TRUE )
+			{
+				if( val==EOF )
+				{
+					if( blk==0 )
+					{
+						fileLoadStatus = TRUE;
+						break; // OK
+					}
+					// error
+					break;
+				}
+				if( blk<4 )
+				{
+					blkHead[blk++] = (BYTE)val;
+					if( blk==2 )
+					{
+						if( (blkHead[0]&blkHead[1])==255 )
+							blk = 0;
+					}
+					if( blk==4 )
+					{
+						blkBegin = ((WORD)blkHead[0]) + ((WORD)blkHead[1])*256;
+						blkEnd = ((WORD)blkHead[2]) + ((WORD)blkHead[3])*256;
+					}
+				}
+				else
+				{
+					atariMem[blkBegin] = (BYTE)val;
+					if( blkBegin==blkEnd )
+					{
+						blk = 0;
+					}
+					blkBegin++;
+				}
+			}
+			cont:;
+
+		}
+		fclose( inpf );
+
+	}
+	if( playerType==-1 )
+		return NULL;
+	fileLoadStatus = TRUE;
+	
+	currentMusic.defSong			= defSong;
+	currentMusic.numOfSongs			= numOfSongs;
+	
+
+	currentMusic.commentBuffer		= &commentBuffer[0];
+	currentMusic.currentTimeIn50Sec	= 0;
+
+//	sapPlaySong( defSong );
+	return &currentMusic;
+}
+
+
+void sapPlaySong( int numOfSong )
+{
+
+	if( fileLoadStatus==FALSE )
+		return;
+
+	if( numOfSong==-1 )
+		numOfSong = 0;
+	numOfSong &= 0xFF;
+	numOfSong = numOfSong % currentMusic.numOfSongs;
+
+	sndBufPtr = prSbp = 0;
+	switch( playerType )
+	{
+		case 'c':
+			if( (playerAddress==-1) || (musicAddress==-1) )
+			{
+				fileLoadStatus = FALSE;
+				break;
+			}
+			cpuReg_S = 0xFF;
+			cpuReg_A = 0x70;
+			cpuReg_X = (musicAddress&0xFF);
+			cpuReg_Y = (musicAddress>>8)&0xFF;
+			playerCallSubroutine( playerAddress+3 );
+			cpuReg_S = 0xFF;
+			cpuReg_A = 0x00;
+			cpuReg_X = numOfSong;
+			playerCallSubroutine( playerAddress+3 );
+			break;
+		case 'b':
+		case 'm':
+			if( (playerInit==-1) || (playerAddress==-1) )
+			{
+				fileLoadStatus = FALSE;
+				break;
+			}
+			cpuReg_S = 0xFF;
+			cpuReg_A = numOfSong;
+			playerCallSubroutine( playerInit );
+			break;
+		case 'd':
+			if( (playerInit==-1) || (playerAddress==-1) )
+			{
+				fileLoadStatus = FALSE;
+				break;
+			}
+			cpuReg_S = 0xFF;
+			cpuReg_PC = 0xFFFF;
+			cpuReg_PC--;
+			atariMem[0x100 + cpuReg_S] = (cpuReg_PC>>8)&0xFF; cpuReg_S--;
+			atariMem[0x100 + cpuReg_S] = cpuReg_PC&0xFF; cpuReg_S--;
+			cpuReg_PC = playerInit;
+			cpuReg_A = numOfSong;
+			cpuReg_X = 0;
+			cpuReg_Y = 0;
+			cpuSetFlags( 0x20 );
+			break;
+		case 's':
+			if( (playerInit==-1) || (playerAddress==-1) )
+			{
+				fileLoadStatus = FALSE;
+				break;
+			}
+			cpuReg_S = 0xFF;
+			cpuReg_PC = playerInit;
+			cpuReg_A = 0;
+			cpuReg_X = 0;
+			cpuReg_Y = 0;
+			cpuSetFlags( 0x20 );
+			break;
+	}
+}
+
+
+void _SAP_internals_::playerCallSubroutine( WORD address )
+{
+int i,k;
+
+	cpuReg_PC = 0xFFFF;
+	cpuReg_PC--;
+	atariMem[0x100 + cpuReg_S] = (cpuReg_PC>>8)&0xFF; cpuReg_S--;
+	atariMem[0x100 + cpuReg_S] = cpuReg_PC&0xFF; cpuReg_S--;
+	cpuReg_PC = address;
+	k = 0;
+	bool holded;
+	while(k<1000000)
+	{
+		BYTE opcode = atariMem[ cpuReg_PC ];
+		i =  opcodes_0x00_0xFF[opcode](holded);
+		k+=i;
+		if( i>10 )
+			return;
+		if( cpuReg_PC==0xFFFF )
+			break;
+	}
+	k++;
+}
+
+extern bool *generateIRQ0;
+int numsPerFrame;
+
+void _SAP_internals_::playerProcessOneFrame( void )
+{
+int ilp = 0;
+BYTE oldFlags = 0,oldA = 0,oldX = 0,oldY = 0,oldS = 0;
+WORD oldPC = 0;
+BOOL notRestored = 0;
+bool holded;
+int	cycleInLine,lineInFrame;
+
+	numsPerFrame = 0;
+
+	if( playerType=='d' )
+	{
+		oldFlags = cpuGetFlags();
+		oldA = cpuReg_A;
+		oldX = cpuReg_X;
+		oldY = cpuReg_Y;
+		oldPC = cpuReg_PC;
+		oldS = cpuReg_S;
+		notRestored = TRUE;
+	}
+	if( playerType=='s' )
+	{
+
+	}
+
+	if( playerType!='s' )
+	{
+		cpuReg_S = 0x8F;
+		cpuReg_PC = 0xFFFF;
+		cpuReg_PC--;
+		atariMem[0x100 + cpuReg_S] = (cpuReg_PC>>8)&0xFF; cpuReg_S--;
+		atariMem[0x100 + cpuReg_S] = cpuReg_PC&0xFF; cpuReg_S--;
+	}
+
+	switch( playerType )
+	{
+		case 'c':
+			cpuReg_PC = playerAddress+6;
+			break;
+		case 'b':
+		case 'd':
+		case 'm':
+			cpuReg_PC = playerAddress;
+			break;
+	}
+	cycleInLine = 0;
+	if( fastPlay!=-1 )
+		lineInFrame = 0;
+	else if( playerType=='s' )
+		lineInFrame = 0;
+	else
+		lineInFrame = 248;
+	holded = false;
+	pokeyUpdateSoundCounters();
+
+	while(1)
+	{
+		if( cpuReg_PC!=0xFFFF )
+		{
+			BYTE opcode = atariMem[ cpuReg_PC ];
+			ilp =  opcodes_0x00_0xFF[opcode](holded);
+			if( ilp>10 )
+				return; // not supported instruction has been executed
+			if( (playerType=='b') || (playerType=='c') )
+				ilp = 1;
+		}
+		else
+		{
+			if( playerType=='d' )
+			{
+				if( notRestored==TRUE )
+				{
+					notRestored = FALSE;
+					cpuReg_PC = oldPC;
+					cpuReg_A = oldA;
+					cpuReg_X = oldX;
+					cpuReg_Y = oldY;
+					cpuSetFlags( oldFlags );
+					cpuReg_S = oldS;
+				}
+			}
+			else
+			{
+				do {
+					pokeyUpdateSound(114);
+					lineInFrame++;
+					currentMusic.currentTimeIn50Sec++;
+					if( fastPlay!=-1 )
+					{
+						if( lineInFrame==fastPlay )
+						{
+							pokeyUpdateSoundCounters();
+							goto bre;
+						}
+					}
+					else
+					{
+						if( lineInFrame==248 )
+						{
+							pokeyUpdateSoundCounters();
+							goto bre;
+						}
+						if( lineInFrame==312 )
+						{
+							lineInFrame=0;
+							pokeyUpdateSoundCounters();
+						}
+					}
+				} while(1);
+			}
+		}
+	again:
+		for(;ilp>0;ilp--)
+		{
+			if( cycleInLine>=103-9 )
+			{
+				if( cycleInLine==103-9 )
+				{
+					if( holded )
+					{
+						ilp = 0;
+						holded = false;
+					}
+				}
+				if( cycleInLine==113-9 )
+				{
+					pokeyUpdateSound(114);
+					cycleInLine = -1;
+					lineInFrame++;
+					currentMusic.currentTimeIn50Sec++;
+					if( fastPlay!=-1 )
+					{
+						if( lineInFrame==fastPlay )
+						{
+							pokeyUpdateSoundCounters();
+							goto bre;
+						}
+					}
+					else if( playerType=='s' )
+					{
+						if( lineInFrame==78 )
+						{
+							pokeyUpdateSoundCounters();
+							atariMem[0x45]--;
+							if( atariMem[0x45]==0 )
+								atariMem[0xB07B]++;
+							goto bre;
+						}
+					}
+					else
+					{
+						if( lineInFrame==248 )
+						{
+							pokeyUpdateSoundCounters();
+							goto bre;
+						}
+						if( lineInFrame==312 )
+						{
+							lineInFrame=0;
+							pokeyUpdateSoundCounters();
+						}
+					}
+					ANTIC_VCOUNT_D40B = (BYTE)(lineInFrame / 2);
+				}
+			}
+			cycleInLine++;
+		}
+		if( holded )
+		{
+			ilp=114-9;
+			goto again;
+		}
+		if( generateIRQ0[0] )
+		{
+			generateIRQ0[0] = false;
+			pokeyGenerateIRQ(1);
+			numsPerFrame++;
+		}
+	}
+	bre:;
+}
+
+
+void sapRenderBuffer( short int *buffer, int number_of_samples )
+{
+int i;
+	
+	if( fileLoadStatus==FALSE )
+		return;
+
+	i = 0;
+	number_of_samples *= sampleStep;
+	while( i<number_of_samples )
+	{
+		if( prSbp==sndBufPtr )
+			playerProcessOneFrame();
+		for( ;prSbp!=sndBufPtr; prSbp=(prSbp+1)&16383 )
+		{
+			if( isStereo )
+				buffer[i] = sndBuf[prSbp&16383];
+			else
+			{
+				buffer[i*2+0] = sndBuf[prSbp&16383];
+				buffer[i*2+1] = sndBuf[prSbp&16383];
+			}
+			if( i>=number_of_samples )
+				break;
+			i++;
+		}
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/sapGlobals.h	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,89 @@
+#ifdef __MAIN_DECLARATIONS__
+#define axeEXTERN
+#else
+#define axeEXTERN extern
+#endif
+
+#ifndef BYTE
+#define BYTE unsigned char
+#endif
+#ifndef WORD
+#define WORD unsigned short int
+#endif
+#ifndef DWORD
+#define DWORD unsigned long int
+#endif
+#ifndef BOOL
+#define BOOL int
+#endif
+#define TRUE 1
+#define FALSE 0
+
+axeEXTERN bool	isStereo;
+axeEXTERN int	sampleStep;
+
+extern void pokeyGenerateCheckIRQline(void);
+extern void pokeyGenerateIRQ( BYTE irqMask );
+
+axeEXTERN BYTE	atariMem[ 0x10000 ];
+axeEXTERN WORD	sndBuf[16384];
+axeEXTERN int	sndBufPtr;
+
+axeEXTERN BYTE	ANTIC_VCOUNT_D40B;
+
+axeEXTERN WORD cpuReg_PC;
+axeEXTERN BYTE cpuFlag_N,cpuFlag_Z,cpuFlag_C,cpuFlag_D,cpuFlag_B,cpuFlag_I,cpuFlag_V,cpuReg_A,cpuReg_X,cpuReg_Y,cpuReg_S;
+// cpuFlag_N is valid only in last bit-7
+// cpuFlag_Z is set if whole cpuFlag_Z is not zero
+// cpuFlag_C is valid only in first bit-0
+// cpuFlag_D is valid only in first bit-0
+// cpuFlag_B is valid only in first bit-0
+// cpuFlag_I is valid only in first bit-0
+// cpuFlag_V is valid only in first bit-0
+
+
+extern void cpuInit( void );
+extern int cpuExecuteOneOpcode( void );
+extern BYTE cpuGetFlags( void );
+extern void cpuSetFlags( BYTE flags );
+
+extern void pokeyInit( void );
+extern void pokeyReset( void );
+extern BYTE pokeyReadByte( short unsigned int address );
+extern void pokeyWriteByte0( short unsigned int address, BYTE value );
+extern void pokeyWriteByte1( short unsigned int address, BYTE value );
+extern void pokeyUpdateSound( int n );
+extern void pokeyUpdateSoundCounters( void );
+
+inline BYTE freddieReadByte( WORD ad )
+{
+	if( (ad&0xF800)==0xD000 )
+	{
+		if( (ad&0xFF00)==0xD200 )
+		{
+			return pokeyReadByte( ad );
+		}
+		if( (ad&0xFF0F)==0xD40B )
+			return ANTIC_VCOUNT_D40B;
+	}
+	return atariMem[ad];
+}
+inline BYTE freddieCPUReadByte( WORD ad )
+{
+	return atariMem[ad];
+}
+
+inline void freddieWriteByte( WORD ad, BYTE val )
+{
+	if( (ad&0xFF00)==0xD200 )
+	{
+		if( ((ad&0x10)==0) || (isStereo==false) ) pokeyWriteByte0( ad, val );
+		else pokeyWriteByte1( ad, val );
+		return;
+	}
+	atariMem[ad] = val;
+}
+
+typedef int (*opcodeFunc)(bool &holded);
+
+extern opcodeFunc opcodes_0x00_0xFF[256];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/sapLib.h	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,19 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+	int		numOfSongs;
+	int		defSong; 
+	char	*commentBuffer;
+	int		currentTimeIn50Sec;
+} sapMUSICstrc;
+
+sapMUSICstrc *sapLoadMusicFile( char *fname );
+void sapPlaySong( int numOfSong );
+void sapRenderBuffer( short int *buffer, int number_of_samples );
+
+#ifdef __cplusplus
+}
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/saplib/sapPokey.cpp	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,64 @@
+#include <ctype.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sapGlobals.h"
+
+extern void pokeyInit0( void );
+extern void pokeyInit1( void );
+extern void pokeyReset0( void );
+extern void pokeyReset1( void );
+extern void pokeyUpdateSound0( int n );
+extern void pokeyUpdateSound1( int n );
+extern void pokeyUpdateSoundCounters0( void );
+extern void pokeyUpdateSoundCounters1( void );
+
+void pokeyInit( void )
+{
+	pokeyInit0();
+	pokeyInit1();
+}
+void pokeyReset( void )
+{
+	pokeyReset0();
+	pokeyReset1();
+}
+
+void pokeyUpdateSound( int n )
+{
+int oldBufPtr = sndBufPtr;
+	pokeyUpdateSound0( n );
+	if( isStereo )
+	{
+		sndBufPtr = (oldBufPtr+1)&16383;
+		pokeyUpdateSound1( n );
+		sndBufPtr = (sndBufPtr-1)&16383;
+	}
+}
+
+void pokeyUpdateSoundCounters( void )
+{
+	pokeyUpdateSoundCounters0();
+	pokeyUpdateSoundCounters1();
+}
+
+BYTE pokeyReadByte( short unsigned int address)
+{
+BYTE retVal;
+
+	switch( address&0x0F )
+	{
+		case 0x09:
+			return 0xFF;
+		case 0x0A:
+			retVal = (BYTE)((255*rand())/RAND_MAX);
+			return retVal;
+		case 0x0E:
+			return 0xFF;
+		case 0x0F:
+			return 0xFF;
+	}
+	return 0xFF;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/scripts/gen_symbols	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,4 @@
+#! /bin/sh
+/usr/bin/nm -B  $1      | sed -n -e 's/^.*[ 	]\([ABCDGISTW][ABCDGISTW]*\)[ 	][ 	]*\(\)\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2\3 \3/p' | sed 's/.* //' | sort | uniq > symbols        
+egrep -e "get_.plugin_info" "symbols" > syms
+rm -f symbols
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/syms	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,1 @@
+get_iplugin_info
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sap/version.h	Sun Oct 29 01:08:30 2006 -0700
@@ -0,0 +1,21 @@
+/*
+ * SAP xmms plug-in. 
+ * Copyright 2002/2003 by Michal 'Mikey' Szwaczko <mikey@scene.pl>
+ *
+ * SAP Library ver. 1.56 by Adam Bienias
+ *
+ * This is free software. You can modify it and distribute it under the terms
+ * of the GNU General Public License. The verbatim text of the license can 
+ * be found in file named COPYING in the source directory.
+ *
+ * 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 THE AUTHORS 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.
+ *
+ */
+#define VERSION "0.3F"
+#define SAP_VER "1.56"