*
* 6510.asm - 6510-Emulation (eigener Task)
*
* Copyright (C) 1994-1996 by Christian Bauer
*

*
* Anmerkungen:
* ------------
*
* Register d0/d1/a4 - WICHTIG:
*  - Der Emulator geht davon aus, daß die MSWs von d0 und d1 immer Null
*    sind. Denn dadurch kann das C64-RAM mittels (RAMPTR,d0.l) ohne
*    Vorzeichen indiziert angesprochen werden.
*  - Die Makros Read#?Zero#? und Read#?Ind#? gehen zusätlich davon aus,
*    daß nur das untere Byte von d0 Null ist, da diese Makros immer nur
*    am Anfang eines Befehls stehen und d0 vom Next-Makro noch gelöscht
*    ist
*  - Register a4 wird zur Near-Adressierung verwendet
*
* Speicherkonfigurationen:
*
* $01  $a000-$bfff  $d000-$dfff  $e000-$ffff
* -----------------------------------------------
*  0       RAM          RAM          RAM
*  1       RAM       Char-ROM        RAM
*  2       RAM       Char-ROM    Kernal-ROM
*  3    Basic-ROM    Char-ROM    Kernal-ROM
*  4       RAM          RAM          RAM
*  5       RAM          I/O          RAM
*  6       RAM          I/O      Kernal-ROM
*  7    Basic-ROM       I/O      Kernal-ROM
*
* Zugriff auf den C64-Speicher:
*  - Fast alle Speicherzugriffe laufen über die ReadByte/WriteByte-Makros,
*    die die eingestellte Speicherkonfiguration dadurch berücksichtigen,
*    daß die oberen 8 Adreßbits als Index in eine Sprungtabelle
*    (ReadWriteTab) dienen, die Zeiger auf die ReadByte*/WriteByte*-
*    Routinen enthalten, über die der tatsächliche Zugriff erfolgt.
*    Für jede der 8 Speicherkonfigurationen existiert jeweils eine solche
*    Tabelle Bei einer Änderung der Speicherkonfiguration (NewConfig)
*    wird der Zeiger auf die Tabelle (RWTAB) geändert.
*  - Das LESEN aus der Zero-Page geschieht immer direkt,
*    da dort keine Register liegen ($00/$01 werden auch im RAM abgelegt)
*  - Beim Schreiben in die Zero-Page wird nur auf $00/$01 getestet,
*    ansonsten direkt zugegriffen
*  - Der Stack wird immer direkt angesprochen
*  - Die ReadByte-/WriteByte-Routinen dürfen nur d0-d1/a0-a1 verändern
*
* Programmzähler:
*  - Aus Geschwindigkeitsgründen wird der PC durch einen 32-Bit-
*    Amiga-Zeiger repräsentiert und über diesen direkt auf den
*    Speicher zugegriffen (und nicht über ReadByte). Bei einem
*    Sprungbefehl wird aus dem 16-Bit Sprungziel und der aktuellen
*    Speicherkonfiguration die neue 32-Bit-Adresse berechnet,
*    indem ähnlich zur ReadWriteTab die oberen 8 Bit des Sprungziels
*    als Index in die JumpTab verwendet werden. Die darüber aufgerufenen
*    Routinen führen die Umrechnung durch.
*  - Durch die Art, wie das Hauptprogramm den Speicher anfordert,
*    entsprechen die unteren 16 Bit des 32-Bit-PCs immer der
*    16-Bit-C64-Adresse. Das erleichtert erheblich das Ablegen des
*    PC auf dem Stack, da dazu einfach nur die unteren 16 Bit
*    genommen werden müssen (ansonsten müßte man je nach RAM/ROM-
*    Bereich erst die jeweilige Basisadresse subtrahieren).
*  - Im RAM-Bereich $10000-$100ff wird der Opcode $d2 installiert,
*    der den PC auf $0000-$00ff umrechnet, falls ein Programm den
*    Wraparound macht
*  - Durch diese Art der PC-Verwaltung bestehen folgende Inkompatibilitäten:
*     - Ein Branch oder ein Hineinlaufen in einen anderen Speicherbereich
*       (z.B. RAM->ROM) funktioniert nicht. Das sollte allerdings kein
*       Problem darstellen.
*     - Ein Sprung in den I/O-Bereich ist z.Z. nicht möglich
*
* Condition-Codes:
*  - Die Emulation verwendet zwei Register, um die Prozessorflags zu
*    speichern: RCCR und RP.
*  - RCCR ist ein Abbild des 680x0-CCR und wird nach den entsprechenden
*    Operationen mit "move ccr,RCCR" gelesen. Von RCCR werden nur das N-
*    und das Z-Flag verwendet.
*  - Die einzigen Opcodes, die V ändern, sind ADC, SBC, CLV, PLP und RTI.
*    Darum wird das V-Flag nicht aus dem 680x0-V-Flag erzeugt, sondern
*    gegebenenfalls von Hand gesetzt.
*  - Im oberen Byte (Bit 8-15) von RP sind die 6510-Flags V,B,D und I
*    in der selben Anordnung wie beim 6510 gespeichert. Das untere Byte
*    enthält in Bit 0 das Carry-Flag in 6510-Interpretation (bei SBC und
*    CMP/CPX/CPY inverse Bedeutung zum 680x0), das bei den entsprechenden
*    Opcodes aus dem CCR gelesen (und ggf. invertiert) wird. Der Einfachheit
*    halber wird immer das ganze untere Byte von CCR gelesen, da nur Bit 0
*    interessant ist.
*
* Opcode-Ausführung:
*  - Es gibt keine Fetch-Decode-Schleife, sondern jede Opcode-Routine
*    enthält am Schluß den Code, der den nächsten Befehl ausführt
*    ("Next"-Makro).
*  - Die Verzweigung in die einzelnen Opcode-Routinen geschieht über
*    eine Sprungtabelle, die OpcodeTable.
*
* Zyklenzähler/Periodic/Interrupts:
*  - Die Variable CyclesLeft enthält die Anzahl Zyklen, die dem 6510 in
*    der augenblicklichen Rasterzeile noch zur Verfügung stehen.
*  - Ein Zeiger auf CyclesLeft steht in (CYCPTR) (wg. schnellerer
*    Adressierung).
*  - Nach jeder Opcode-Ausführung wird dieser Zähler um die Zyklenzahl
*    des gerade ausgeführten Befehls erniedrigt. Dazu wird dem Next-Makro
*    die Anzahl Zyklen übergeben. Unterschreitet der Zähler Null, wird
*    die Routine "Periodic" aufgerufen.
*  - In dieser Routine werden die Unterroutinen von VIC und CIA
*    ausgeführt, die die Aktionen für eine Rasterzeile durchführen
*    (VIC (Periodic6569): Eine Bildschirmzeile aufbauen, CIA
*    (Periodic6526): Timer zählen)
*  - In Periodic6569 wird der Zyklenzähler neu gesetzt (der Wert hängt
*    davon ab, ob eine Bad Line stattfand oder nicht)
*
* Interrupts:
*  - Die Haupt-Interruptquellen sind VIC und CIA, daher prüft der
*    Emulator das Auftreten eines Interrupts im Rahmen der Periodic-
*    Routine
*  - Es gibt folgende Interrupt-Möglichkeiten (Prioritäten):
*     - RESET, Sprung nach ($FFFC) oder 6510-Task beenden (RESETIsEXIT-Flag)
*     - NMI, Sprung nach ($FFFA)
*     - VIC-IRQ, I-Flag wird geprüft, Sprung nach ($FFFE)
*     - CIA-IRQ, I-Flag wird geprüft, Sprung nach ($FFFE)
*  - Die Aufteilung in VIC- und CIA-IRQ erleichtert die Handhabung, wenn
*    beide IRQs gleichzeitig auftreten
*  - Die einzige Möglichkeit, außerhalb des Periodic einen Interrupt
*    auszulösen, ist das Löschen des I-Flags, wenn ein IRQ ansteht.
*    Die Opcode-Routinen für PLP, RTI und CLI enthalten deswegen besondere
*    Abfragen, die ggf. in den Interrupt-Handler verzweigen.
*
* Erweiterungen:
*  - Über den Opcode $f2 sind die IEC-Routinen implementiert. Dem Opcode
*    folgt ein Byte, das die Nummer der auzurufenden Routine angibt.
*
* Inkompatibilitäten:
*  - ($ff),Y-Adressierung liest das zweite Byte der indirekten Adresse
*    aus $0100 statt $0000. Dies geschieht aus Geschwindigkeitsgründen,
*    der korrekte Code ist im Makro ReadAdrIndY auskommentiert.
*  - In der Verwaltung des PCs bestehen einige Ungenauigkeiten (siehe
*    Abschnitt "Programmzähler")
*  - RMW-Befehle sollten erst die Originaldaten und dann die geänderten
*    schreiben, aber das spielt nur eine Rolle für Register wie das
*    VIC-IRQFLAG-Register, das in 6569.asm deswegen speziell behandelt wird
*  - Zyklen werden nur für ganze Befehle gezählt, Extra-Zyklen für
*    Seitenüberschreitungen werden nicht berechnet (dies betrifft die
*    Adressierungsarten xxxx,X xxxx,Y (xx),Y und die Branch-Befehle)
*  - Der Kassettenschalter ist immer geschlossen
*  - RRA und ISB kennen keinen Dezimalmodus
*

		MACHINE	68020

		INCLUDE	"exec/types.i"
		INCLUDE	"exec/macros.i"
		INCLUDE	"exec/execbase.i"
		INCLUDE	"exec/nodes.i"
		INCLUDE	"dos/dos.i"
		INCLUDE	"dos/dostags.i"
		INCLUDE	"Frodo_rev.i"
CATCOMP_NUMBERS	= 1
		INCLUDE	"LocStrings.i"

		XREF	_SysBase
		XREF	_DOSBase
		XREF	_IntuitionBase

		XREF	GetString	;Strings.o
		XREF	TheLocale

		XDEF	TheRAM		;Main.asm
		XDEF	TheBasic
		XDEF	TheKernal
		XDEF	TheChar
		XDEF	TheColor
		XREF	MainTask
		XREF	Random
		XREF	ResetC64

		XREF	_InitDisplayFrom6510	;Display.c
		XREF	_ExitDisplayFrom6510
		XREF	_EmulToBack
		XREF	_EmulToFront

		XREF	ReadFrom6526A	;6526.asm
		XREF	ReadFrom6526B
		XREF	WriteTo6526A
		XREF	WriteTo6526B

		XREF	ReadFrom6569	;6569.asm
		XREF	WriteTo6569
		XREF	Periodic6569

		XREF	ReadFrom6581	;6581.asm
		XREF	WriteTo6581

		XREF	IECOut		;IEC.asm
		XREF	IECOutATN
		XREF	IECOutSec
		XREF	IECIn
		XREF	IECSetATN
		XREF	IECRelATN
		XREF	IECTurnaround
		XREF	IECRelease

		XDEF	Init6510
		XDEF	Reset6510
		XDEF	Start6510
		XDEF	Stop6510
		XDEF	_Pause6510
		XDEF	_Resume6510
		XDEF	_SAMReadByte
		XDEF	_SAMWriteByte
		XDEF	Localize6510
		XDEF	IntIsRESET
		XDEF	IntIsNMI
		XDEF	IntIsVICIRQ
		XDEF	IntIsCIAIRQ
		XDEF	NMIState
		XDEF	CyclesLeft
		XDEF	CPUTask
		XDEF	Peri6569Cont
		XDEF	Peri6526Cont
		XDEF	IsFrodoSC
		XDEF	_IsFrodoSC
		XDEF	_InvokeSAMSet

		NEAR	a4,-2
		XREF	_DATA_BAS_

		SECTION	"text",CODE

		FAR


**
** Definitionen
**

; Bitdefinitionen für RP (6510-Statusregister)
InterruptBit	= 10	;Interrupts abgeschaltet
InterruptMask	= $0400
DecimalBit	= 11	;Dezimalmodus
DecimalMask	= $0800
OverflowBit	= 14	;Arith. Überlauf
OverflowMask	= $4000

; Registerbelegung
RA		EQUR	d2	;A
RX		EQUR	d3	;X
RY		EQUR	d4	;Y
RS		EQUR	d5	;S (16-Bit, $01xx)
RCCR		EQUR	d6	;CCR, nur N und Z
RP		EQUR	d7	;Oberes Byte: 6510-Status ohne N,Z und C
				;Unteres Byte: Carry in 6510-Interpretation
RWTAB		EQUR	a2	;Zeiger auf ReadByte/WriteByte-Sprungtabelle
				;256*8*8+RWTAB zeigt auf JumpTab
CYCPTR		EQUR	a3	;Zeiger auf CyclesLeft
RAMPTR		EQUR	a5	;Zeiger auf C64-RAM
RPC		EQUR	a6	;PC (32-Bit Amiga-Adresse, untere 16 Bit
				;    stimmen mit C64-PC überein)


**
** Emulation vorbereiten (Sprungtabellen aufbauen)
**

; ReadWriteTabs aufbauen
Init6510	lea	ReadWriteTab0,a0	;Alle mit RAM vorbelegen
		move.w	#256*8-1,d0
1$		move.l	#ReadByteRAM,(a0)+
		move.l	#WriteByteRAM,(a0)+
		dbra	d0,1$

		move.l	#WriteBytePage0,ReadWriteTab0+4 ;Zeropage immer speziell
		move.l	#WriteBytePage0,ReadWriteTab1+4
		move.l	#WriteBytePage0,ReadWriteTab2+4
		move.l	#WriteBytePage0,ReadWriteTab3+4
		move.l	#WriteBytePage0,ReadWriteTab4+4
		move.l	#WriteBytePage0,ReadWriteTab5+4
		move.l	#WriteBytePage0,ReadWriteTab6+4
		move.l	#WriteBytePage0,ReadWriteTab7+4

		lea	ReadWriteTab3+160*8,a0	;Basic-ROM
		moveq	#31,d0
21$		move.l	#ReadByteBasic,(a0)+
		addq.l	#4,a0
		dbra	d0,21$

		lea	ReadWriteTab7+160*8,a0
		moveq	#31,d0
22$		move.l	#ReadByteBasic,(a0)+
		addq.l	#4,a0
		dbra	d0,22$

		lea	ReadWriteTab2+224*8,a0	;Kernal-ROM
		moveq	#31,d0
31$		move.l	#ReadByteKernal,(a0)+
		addq.l	#4,a0
		dbra	d0,31$

		lea	ReadWriteTab3+224*8,a0
		moveq	#31,d0
32$		move.l	#ReadByteKernal,(a0)+
		addq.l	#4,a0
		dbra	d0,32$

		lea	ReadWriteTab6+224*8,a0
		moveq	#31,d0
33$		move.l	#ReadByteKernal,(a0)+
		addq.l	#4,a0
		dbra	d0,33$

		lea	ReadWriteTab7+224*8,a0
		moveq	#31,d0
34$		move.l	#ReadByteKernal,(a0)+
		addq.l	#4,a0
		dbra	d0,34$

		lea	ReadWriteTab5+208*8,a0	;I/O-Bereich
		bsr	InitIOPages

		lea	ReadWriteTab6+208*8,a0
		bsr	InitIOPages

		lea	ReadWriteTab7+208*8,a0
		bsr	InitIOPages

		lea	ReadWriteTab1+208*8,a0	;Char-ROM
		moveq	#15,d0
41$		move.l	#ReadByteChar,(a0)+
		addq.l	#4,a0
		dbra	d0,41$

		lea	ReadWriteTab2+208*8,a0
		moveq	#15,d0
42$		move.l	#ReadByteChar,(a0)+
		addq.l	#4,a0
		dbra	d0,42$

		lea	ReadWriteTab3+208*8,a0
		moveq	#15,d0
43$		move.l	#ReadByteChar,(a0)+
		addq.l	#4,a0
		dbra	d0,43$

; JumpTabs aufbauen
		lea	JumpTab0,a0		;Alle mit RAM vorbelegen
		move.w	#256*8-1,d0
6$		move.l	#JumpToRAM,(a0)+
		addq.l	#4,a0
		dbra	d0,6$

		lea	JumpTab3+160*8,a0	;Basic-ROM
		moveq	#31,d0
71$		move.l	#JumpToBasic,(a0)+
		addq.l	#4,a0
		dbra	d0,71$

		lea	JumpTab7+160*8,a0
		moveq	#31,d0
72$		move.l	#JumpToBasic,(a0)+
		addq.l	#4,a0
		dbra	d0,72$

		lea	JumpTab2+224*8,a0	;Kernal-ROM
		moveq	#31,d0
81$		move.l	#JumpToKernal,(a0)+
		addq.l	#4,a0
		dbra	d0,81$

		lea	JumpTab3+224*8,a0
		moveq	#31,d0
82$		move.l	#JumpToKernal,(a0)+
		addq.l	#4,a0
		dbra	d0,82$

		lea	JumpTab6+224*8,a0
		moveq	#31,d0
83$		move.l	#JumpToKernal,(a0)+
		addq.l	#4,a0
		dbra	d0,83$

		lea	JumpTab7+224*8,a0
		moveq	#31,d0
84$		move.l	#JumpToKernal,(a0)+
		addq.l	#4,a0
		dbra	d0,84$

		lea	JumpTab1+208*8,a0	;Char-ROM
		moveq	#15,d0
85$		move.l	#JumpToChar,(a0)+
		addq.l	#4,a0
		dbra	d0,85$

		lea	JumpTab2+208*8,a0
		moveq	#15,d0
86$		move.l	#JumpToChar,(a0)+
		addq.l	#4,a0
		dbra	d0,86$

		lea	JumpTab3+208*8,a0
		moveq	#15,d0
87$		move.l	#JumpToChar,(a0)+
		addq.l	#4,a0
		dbra	d0,87$

		lea	JumpTab5+208*8,a0	;I/O-Bereich
		moveq	#15,d0
88$		move.l	#JumpToIO,(a0)+
		addq.l	#4,a0
		dbra	d0,88$

		lea	JumpTab6+208*8,a0
		moveq	#15,d0
89$		move.l	#JumpToIO,(a0)+
		addq.l	#4,a0
		dbra	d0,89$

		lea	JumpTab7+208*8,a0
		moveq	#15,d0
810$		move.l	#JumpToIO,(a0)+
		addq.l	#4,a0
		dbra	d0,810$
		rts

InitIOPages	move.l	#ReadByteVIC,(a0)+
		move.l	#WriteByteVIC,(a0)+
		move.l	#ReadByteVIC,(a0)+
		move.l	#WriteByteVIC,(a0)+
		move.l	#ReadByteVIC,(a0)+
		move.l	#WriteByteVIC,(a0)+
		move.l	#ReadByteVIC,(a0)+
		move.l	#WriteByteVIC,(a0)+
		move.l	#ReadByteSID,(a0)+
		move.l	#WriteByteSID,(a0)+
		move.l	#ReadByteSID,(a0)+
		move.l	#WriteByteSID,(a0)+
		move.l	#ReadByteSID,(a0)+
		move.l	#WriteByteSID,(a0)+
		move.l	#ReadByteSID,(a0)+
		move.l	#WriteByteSID,(a0)+
		move.l	#ReadByteColor,(a0)+
		move.l	#WriteByteColor,(a0)+
		move.l	#ReadByteColor,(a0)+
		move.l	#WriteByteColor,(a0)+
		move.l	#ReadByteColor,(a0)+
		move.l	#WriteByteColor,(a0)+
		move.l	#ReadByteColor,(a0)+
		move.l	#WriteByteColor,(a0)+
		move.l	#ReadByteCIA1,(a0)+
		move.l	#WriteByteCIA1,(a0)+
		move.l	#ReadByteCIA2,(a0)+
		move.l	#WriteByteCIA2,(a0)+
		move.l	#ReadByteUndef,(a0)+
		move.l	#WriteByteUndef,(a0)+
		move.l	#ReadByteUndef,(a0)+
		move.l	#WriteByteUndef,(a0)
		rts


**
** 6510 zurücksetzen
**

Reset6510	st.b	IntIsRESET
		rts


**
** 6510-Task starten
** Rückgabe: d0#0 = Fehler
**

; Signale einrichten
Start6510	move.l	_SysBase,a6
		moveq	#-1,d0
		JSRLIB	AllocSignal
		move.b	d0,ReadySig
		moveq	#0,d1
		bset	d0,d1
		move.l	d1,ReadySet

		moveq	#-1,d0
		JSRLIB	AllocSignal
		move.b	d0,InvokeSAMSig
		moveq	#0,d1
		bset	d0,d1
		move.l	d1,InvokeSAMSet

; Task starten
		move.l	_DOSBase,a6
		move.l	#ProcTags,d1
		JSRLIB	CreateNewProc
		move.l	d0,CPUProc
		beq	1$

; Auf Signal warten
		move.l	_SysBase,a6
		move.l	ReadySet,d0
		JSRLIB	Wait
		moveq	#0,d0		;Alles OK
		rts

; Fehler aufgetreten
1$		moveq	#-1,d0
		rts


**
** 6510-Task stoppen
**

; Task stoppen
Stop6510	move.l	_SysBase,a6
		tst.l	CPUProc
		beq	1$
		st.b	RESETIsEXIT	;EXIT-Reset auslösen
		st.b	IntIsRESET
		move.l	ReadySet,d0
		JSRLIB	Wait

; Signale freigeben
1$		move.b	InvokeSAMSig,d0
		JSRLIB	FreeSignal

		move.b	ReadySig,d0
		JMPLIB	FreeSignal


**
** 6510-Task anhalten, Zustand sichern
**

_Pause6510	move.l	a6,-(sp)
		move.l	_SysBase,a6
		st.b	RESETIsPause	;Pause-Reset auslösen
		st.b	IntIsRESET
		move.l	ReadySet,d0
		JSRLIB	Wait
		move.l	(sp)+,a6
		rts


**
** 6510-Task fortsetzen, Zustand übernehmen
**

_Resume6510	move.l	a6,-(sp)
		move.l	_SysBase,a6
		move.l	CPUTask,a1	;Continue-Signal schicken
		move.l	ContinueSet,d0
		JSRLIB	Signal
		move.l	(sp)+,a6
		rts


**
** Byte lesen (für SAM)
**

_SAMReadByte	moveq	#0,d0
		move.w	6(sp),d0
		movem.l	d2/a4/RAMPTR,-(sp)
		lea	_DATA_BAS_,a4
		lea	32766(a4),a4
		move.l	TheRAM,RAMPTR
		move.l	d0,d1
		lsr.w	#8,d1
		move.b	_SAMMemConfig,d2
		and.w	#7,d2
		move.l	(ConfigTab,d2.w*4),a0
		move.l	(a0,d1.w*8),a0
		jsr	(a0)
		movem.l	(sp)+,d2/a4/RAMPTR
		rts


**
** Byte schreiben (für SAM)
**

_SAMWriteByte	moveq	#0,d0
		move.w	6(sp),d0
		move.l	8(sp),d1
		cmp.w	#$d000,d0
		blo	1$
		movem.l	d2/a4/RAMPTR/RPC,-(sp)
		lea	_DATA_BAS_,a4
		lea	32766(a4),a4
		move.l	TheRAM,RAMPTR
		lea	RequestStream+16,RPC	;Dummy für WriteTo6526, das bei Zugriff auf das ICR den Opcode prüft
		move.l	d0,a1
		lsr.w	#8,d0
		move.b	_SAMMemConfig,d2
		and.w	#7,d2
		move.l	(ConfigTab,d2.w*4),a0
		move.l	(4,a0,d0.w*8),a0
		jsr	(a0)
		movem.l	(sp)+,d2/a4/RAMPTR/RPC
		rts
1$		move.l	TheRAM,a0
		move.b	d1,(a0,d0.l)
		rts


**
** Strings in Datenstrukturen lokalisieren
**

GetStr		MACRO	;Label
		lea	TheLocale,a0
		move.l	#\1,d0
		jsr	GetString
		ENDM

Localize6510	GetStr	MSG_REQTITLE
		move.l	d0,IllegalOpReq+8
		move.l	d0,JumpToIOReq+8

		GetStr	MSG_REQGADS6
		move.l	d0,IllegalOpReq+16

		GetStr	MSG_REQGADS4
		move.l	d0,JumpToIOReq+16

		GetStr	MSG_ILLEGALOP
		move.l	d0,IllegalOpReq+12

		GetStr	MSG_JUMPTOIO
		move.l	d0,JumpToIOReq+12
		rts


**
** 6510-Emulator
**
** Register:
**  d0: Scratch (Oberes Wort muß IMMER Null sein!)
**  d1: Scratch (Oberes Wort muß IMMER Null sein!)
**  a4: Zeiger auf Variablen
**

		NEAR

*
* Makros für Speicherzugriffe und Adreßberechnungen
*

; Ein C64-Byte lesen
; -> d0.w: Adresse
; <- d0.b: Byte
ReadByte	MACRO	;[Ziel] (wird ein Ziel angegeben, ist das CCR gültig)
		cmp.w	#$a000,d0	;Unterhalb von $a000 ist nur Speicher
		blo	\@1$
		move.w	d0,d1
		lsr.w	#8,d1
		move.l	(RWTAB,d1.l*8),a0
		jsr	(a0)
	IFGE	NARG-1
		move.b	d0,\1
	ENDC
		bra	\@2$
\@1$
	IFGE	NARG-1
		move.b	(RAMPTR,d0.l),\1
	ELSE
		move.b	(RAMPTR,d0.l),d0
	ENDC
\@2$
		ENDM

; Ein C64-Wort lesen (Als Makro schneller)
; -> d0.w: Adresse
; <- d0.w: Wort (Bytefolge korrigiert)
ReadWord	MACRO
		move.l	d2,RegStore
		move.l	d0,d2		;Adresse merken
		ReadByte d1
		move.l	d2,d0		;Adresse zurückholen
		addq.w	#1,d0		;Nächstes Byte
		move.b	d1,d2		;Lo-Byte merken
		ReadByte
		lsl.w	#8,d0		;Hi-Byte richtig schieben
		move.b	d2,d0		;Lo-Byte dazunehmen
		move.l	RegStore,d2
		ENDM

; Ein C64-Byte schreiben
; -> d0.w: Adresse (16 bit)
; -> d1.b: Byte
; Adresse steht dann in a1
WriteByte	MACRO
		cmp.w	#$d000,d0	;Unterhalb von $d000 ist nur Speicher
		blo	\@1$
		move.l	d0,a1
		lsr.w	#8,d0
		move.l	(4,RWTAB,d0.l*8),a0
		jsr	(a0)
		bra	\@2$
\@1$		move.b	d1,(RAMPTR,d0.l)
		cmp.b	#2,d0
		bhs	\@2$
		NewConfig
\@2$
		ENDM

; Ein C64-Wort am PC lesen und PC erhöhen
ReadPCWord	MACRO
		move.w	(RPC)+,d0
		rol.w	#8,d0
		ENDM

; Relative Adressierung
ReadByteRel	MACRO
		move.b	(RPC)+,d0
		ext.w	d0
		ENDM

; Absolute Adressierung
ReadAdrAbs	MACRO
		ReadPCWord
		ENDM

ReadByteAbs	MACRO	;[Ziel] (wird ein Ziel angegeben, ist das CCR gültig)
		ReadAdrAbs
		ReadByte \1
		ENDM

; Indirekte Adressierung
ReadAdrInd	MACRO
		ReadPCWord
		move.l	d2,RegStore
		move.l	d0,d2		;Adresse merken
		ReadByte d1
		move.l	d2,d0		;Adresse zurückholen
		addq.b	#1,d0		;Nächstes Byte OHNE Page-Crossing
		move.b	d1,d2		;Lo-Byte merken
		ReadByte
		lsl.w	#8,d0		;Hi-Byte richtig schieben
		move.b	d2,d0		;Lo-Byte dazunehmen
		move.l	RegStore,d2
		ENDM

; Zero-Page Adressierung
ReadAdrZero	MACRO
		move.b	(RPC)+,d0
		ENDM

ReadByteZero	MACRO	;Ziel (CCR ist gültig)
		ReadAdrZero
		move.b	(RAMPTR,d0.l),\1
		ENDM

; Absolut,X
ReadAdrAbsX	MACRO
		ReadPCWord
		add.w	RX,d0
		ENDM

ReadByteAbsX	MACRO	;[Ziel] (wird ein Ziel angegeben, ist das CCR gültig)
		ReadAdrAbsX
		ReadByte \1
		ENDM

; Absolut,Y
ReadAdrAbsY	MACRO
		ReadPCWord
		add.w	RY,d0
		ENDM

ReadByteAbsY	MACRO	;[Ziel] (wird ein Ziel angegeben, ist das CCR gültig)
		ReadAdrAbsY
		ReadByte \1
		ENDM

; Zero-Page,X
ReadAdrZeroX	MACRO
		move.b	(RPC)+,d0
		add.b	RX,d0
		ENDM

ReadByteZeroX	MACRO	;Ziel (CCR ist gültig)
		ReadAdrZeroX
		move.b	(RAMPTR,d0.l),\1
		ENDM

; Zero-Page,Y
ReadAdrZeroY	MACRO
		move.b	(RPC)+,d0
		add.b	RY,d0
		ENDM

ReadByteZeroY	MACRO	;Ziel (CCR ist gültig)
		ReadAdrZeroY
		move.b	(RAMPTR,d0.l),\1
		ENDM

; (Ind,X)
ReadAdrIndX	MACRO
		move.b	(RPC)+,d0
		add.b	RX,d0
		move.b	(RAMPTR,d0.l),d1	;LSB lesen
		addq.b	#1,d0
		move.b	(RAMPTR,d0.l),d0	;MSB lesen
		lsl.w	#8,d0
		move.b	d1,d0			;LSB einfügen
		ENDM

ReadByteIndX	MACRO	;[Ziel] (wird ein Ziel angegeben, ist das CCR gültig)
		ReadAdrIndX
		ReadByte \1
		ENDM

; (Ind),Y
ReadAdrIndY	MACRO
		move.b	(RPC)+,d0

;(Korrekt)	move.b	(RAMPTR,d0.l),d1	;LSB lesen
;		addq.b	#1,d0
;		move.b	(RAMPTR,d0.l),d0	;MSB lesen
;		lsl.w	#8,d0
;		move.b	d1,d0			;LSB einfügen

		move.w	(RAMPTR,d0.l),d0	;(Abgekürzt)
		rol.w	#8,d0			;Geht bei ($ff),y schief

		add.w	RY,d0
		ENDM

ReadByteIndY	MACRO	;[Ziel] (wird ein Ziel angegeben, ist das CCR gültig)
		ReadAdrIndY
		ReadByte \1
		ENDM

; Ein Byte auf den Stapel schieben
PushByte	MACRO	;Quelle
		move.b	\1,(RAMPTR,RS.l)
		subq.b	#1,RS
		ENDM

; PC auf Stack schieben
PushPC		MACRO
		move.w	RPC,d0
		move.w	d0,d1
		lsr.w	#8,d0
		PushByte d0
		PushByte d1
		ENDM

; PC+1 auf den Stack schieben
PushPCPlus1	MACRO
		move.w	RPC,d0
		addq.w	#1,d0
		move.w	d0,d1
		lsr.w	#8,d0
		PushByte	d0
		PushByte	d1
		ENDM

; Status auf Stack schieben
PushP		MACRO	;Break-Bit
		move.w	RP,d0		;6510-Status holen
		lsr.w	#8,d0
		and.b	#$4c,d0		;V,D,I behalten
	IFEQ	\1
		or.b	#$20,d0		;1-Bit setzen
	ELSE
		or.b	#$30,d0		;B und 1-Bit setzen
	ENDC
		tst.b	RP		;C dazunehmen
		beq	\@1$
		or.b	#$01,d0
\@1$		btst	#3,RCCR		;N dazunehmen
		beq	\@2$
		or.b	#$80,d0
\@2$		btst	#2,RCCR		;Z dazunehmen
		beq	\@3$
		or.b	#$02,d0
\@3$		PushByte d0
		ENDM

; Ein Byte vom Stapel lesen
PopByte		MACRO	;Ziel (CCR ist gültig)
		addq.b	#1,RS
		move.b	(RAMPTR,RS.l),\1
		ENDM

; Status vom Stack holen
PopP		MACRO
		PopByte	d0
		move	ccr,RCCR
		and.b	#$08,RCCR	;N holen
		move.b	d0,RP
		and.b	#$4c,RP		;V,D,I behalten
		lsl.w	#8,RP
		btst	#1,d0		;Z holen
		beq	\@1$
		or.b	#$04,RCCR
\@1$		btst	#0,d0		;C holen
		sne	RP
		ENDM

; PC setzen
; -> d0.w: 16-Bit-Adresse
; <- RPC.l: Amiga-Adresse
Jump		MACRO
		move.w	d0,d1
		lsr.w	#8,d1
		move.l	(256*8*8,RWTAB,d1.l*8),a0 ;JumpTab
		jsr	(a0)
		ENDM

; Nächsten Befehl ausführen
Next		MACRO	;Zyklenzahl
	IFNE	\1
		subq.w	#\1,(CYCPTR)	;Anzahl Zyklen abziehen
		bmi	Periodic	;Alle verbraucht: Periodic
	ENDC

		moveq	#0,d0
		move.b	(RPC)+,d0	;Opcode lesen
		move.l	(OpcodeTable,d0.l*4),a0 ;Zeiger auf die Opcode-Routine holen
		jmp	(a0)		;Routine aufrufen
		ENDM

; Speicherkonfiguration anpassen
NewConfig	MACRO
	;!!	move.b	(RAMPTR),d0	;Gelesenes PR richtig berechnen
	;	move.b	d0,d1
	;	not.b	d1
	;	and.b	1(RAMPTR),d0
	;	and.b	#%00010111,d1	;Eingabepins
	;	or.b	d1,d0
	;	move.b	d0,1(RAMPTR)

		move.b	(RAMPTR),d0	;Zustand der Ausgabepins lesen
		not.b	d0		;Eingabepins sind 1
		or.b	1(RAMPTR),d0
		and.w	#7,d0		;Relevante Bits maskieren
		move.l	(ConfigTab,d0.l*4),RWTAB
		ENDM

; Ein C64-Byte in die Zero-Page schreiben und nächsten Befehl ausführen.
; Prüfen, ob sich die Speicherkonfiguration geändert hat.
; -> d0.w: Adresse (16 bit)
; -> Arg1: Byte
WriteZeroNext	MACRO	;Register, Zyklenzahl
		move.b	\1,(RAMPTR,d0.l)
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\2
		ENDM


*
* Initialisierung
*

; Near-Adressierung initialisieren
CPUTaskProc	lea	_DATA_BAS_,a4
		lea	32766(a4),a4

; Task ermitteln
		move.l	_SysBase,a6
		sub.l	a1,a1
		JSRLIB	FindTask
		move.l	d0,CPUTask

; Continue-Signal holen
		moveq	#-1,d0
		JSRLIB	AllocSignal
		move.b	d0,ContinueSig
		moveq	#0,d1
		bset	d0,d1
		move.l	d1,ContinueSet

; Grafik initialisieren
		jsr	_InitDisplayFrom6510

; Signal an den Emulator schicken
		move.l	_SysBase,a6
		move.l	MainTask,a1
		move.l	ReadySet,d0
		JSRLIB	Signal

; Variablen initilisieren
		clr.l	Interrupt
		clr.b	RESETIsEXIT
		clr.b	RESETIsPause
		clr.b	NMIState
		move.w	#63,CyclesLeft

; RAM mit Einschaltmuster initialisieren
		move.l	TheRAM,a0
		move.w	#511,d1
3$		moveq	#63,d0
1$		clr.b	(a0)+		;Abwechselnd 64 Bytes $00
		dbra	d0,1$
		moveq	#63,d0
2$		st	(a0)+		;Und 64 Bytes $ff
		dbra	d0,2$
		dbra	d1,3$

; Farb-RAM mit Zufallswerten initialisieren
		move.l	TheColor,a2
		move.w	#$03ff,d2
4$		jsr	Random
		move.b	d0,(a2)+
		dbra	d2,4$

; Speicherkonfiguration initialisieren
		move.l	TheRAM,RAMPTR
		move.b	#$00,(RAMPTR)	;Port auf Eingabe
		NewConfig

; Register setzen
		moveq	#0,d0
		moveq	#0,d1
		moveq	#0,RA
		moveq	#0,RX
		moveq	#0,RY
		move.l	#$01ff,RS
		moveq	#0,RCCR
		move.l	#InterruptMask,RP
		lea	CyclesLeft,CYCPTR

; Reset-Vektor lesen, PC setzen und ersten Befehl ausführen
		move.w	#$fffc,d0
		ReadWord
		Jump
		Next	0

; Unbekannten Opcode entdeckt: Requester darstellen
IllegalOp	subq.w	#1,RPC			;PC korrigieren
		movem.l	a2-a6,-(sp)

		and.w	#$00ff,d0		;Opcode
		move.w	d0,RequestStream
		move.l	RPC,d0			;und PC anzeigen
		move.w	d0,RequestStream+2

		jsr	_EmulToBack

		move.l	_IntuitionBase,a6
		sub.l	a0,a0
		lea	IllegalOpReq,a1
		move.l	a0,a2
		lea	RequestStream,a3
		JSRLIB	EasyRequestArgs

		move.l	d0,-(sp)
		jsr	_EmulToFront
		move.l	(sp)+,d0

		movem.l	(sp)+,a2-a6

		tst.l	d0			;Resetten?
		beq	1$

		jsr	ResetC64		;Ja
		moveq	#0,d0
		moveq	#0,d1
		bra	HandleRESET

1$		move.l	a6,-(sp)		;Nein, SAM aufrufen
		move.l	_SysBase,a6
		move.l	MainTask,a1		;Den Haupttask benachrichtigen
		move.l	InvokeSAMSet,d0
		JSRLIB	Signal
		move.l	(sp)+,a6
		bsr	Pause			;In Pause-Zustand gehen
		clr.b	IntIsRESET
		clr.b	RESETIsPause
		moveq	#0,d0
		moveq	#0,d1
		NewConfig
		move.w	_RPC,d0
		Jump
		Next	0


*
* Speicherzugriff Lesen
*

; Lesen aus dem RAM
ReadByteRAM	move.b	(RAMPTR,d0.l),d0
		rts

; Lesen aus dem Basic-ROM
ReadByteBasic	and.w	#$1fff,d0
		move.l	TheBasic,a0
		move.b	(a0,d0.l),d0
		rts

; Lesen aus einem VIC-Register
ReadByteVIC	and.w	#$3f,d0
		bra	ReadFrom6569

; Lesen aus einem SID-Register
ReadByteSID	and.w	#$1f,d0
		bra	ReadFrom6581

; Lesen aus dem Farb-RAM
ReadByteColor	and.w	#$03ff,d0
		move.l	TheColor,a0
		move.b	(a0,d0.l),d1
		and.b	#$0f,d1

		move.l	d1,-(sp)
		jsr	Random		;Oberes Nibble ist Zufallswert
		and.b	#$f0,d0
		move.l	(sp)+,d1

		or.b	d1,d0
		rts

; Lesen aus einem CIA 1-Register
ReadByteCIA1	and.w	#$0f,d0
		bra	ReadFrom6526A

; Lesen aus einem CIA 2-Register
ReadByteCIA2	and.w	#$0f,d0
		bra	ReadFrom6526B

; Lesen einer offenen Adresse
ReadByteUndef	cmp.l	#$dfa0,d0
		bhs	1$
		jsr	Random		;Zufallswert
		moveq	#0,d1		;MSW löschen
		rts

; $dfa0-$dfff: Emulator-Identifikation
1$		cmp.w	#$dfff,d0	;$dfff liest abwechselnd $55/$aa
		bne	2$
		move.b	DFFFByte,d0
		not.b	DFFFByte
		rts

2$		cmp.w	#$dffe,d0	;$dffe liest "F" (Frodo-Kennung)
		bne	3$
		moveq	#'F',d0
		rts

3$		cmp.w	#$dffd,d0	;$dffd: Version
		bne	4$
		move.b	#VERSION,d0
		rts

4$		cmp.w	#$dffc,d0	;$dffc: Revision
		bne	5$
		move.b	#REVISION<<4,d0
		rts

5$		sub.w	#$dfa0,d0	;$dfa0-$dffb: ID-String
		move.b	IDString(pc,d0.w),d0
		rts

; Lesen aus dem Kernal-ROM
ReadByteKernal	and.w	#$1fff,d0
		move.l	TheKernal,a0
		move.b	(a0,d0.l),d0
		rts

; Lesen aus dem Char-ROM
ReadByteChar	and.w	#$0fff,d0
		move.l	TheChar,a0
		move.b	(a0,d0.l),d0
		rts


*
* Speicherzugriff Schreiben
* In a1 steht die 16-Bit-Adresse
*

; Schreiben in Seite 0
WriteBytePage0	move.l	a1,d0
		move.b	d1,(RAMPTR,d0.l)
		cmp.b	#2,d0
		bhs	1$
		NewConfig
1$		rts

; Schreiben ins RAM
WriteByteRAM	move.b	d1,(RAMPTR,a1.l)
		rts

; Schreiben in ein VIC-Register
WriteByteVIC	move.l	a1,d0
		and.w	#$3f,d0
		bra	WriteTo6569

; Schreiben in ein SID-Register
WriteByteSID	move.l	a1,d0
		and.w	#$1f,d0
		bra	WriteTo6581

; Schreiben ins Farb-RAM
WriteByteColor	move.l	a1,d0
		and.w	#$03ff,d0
		move.l	TheColor,a0
		move.b	d1,(a0,d0.l)
		rts

; Schreiben in ein CIA 1-Register
WriteByteCIA1	move.l	a1,d0
		and.w	#$0f,d0
		bra	WriteTo6526A

; Schreiben in ein CIA 2-Register
WriteByteCIA2	move.l	a1,d0
		and.w	#$0f,d0
		bra	WriteTo6526B

; Schreiben an einer offenen Adresse
WriteByteUndef	rts


*
* Sprungbefehle
*

; Sprung ins RAM
JumpToRAM	lea	(RAMPTR,d0.l),RPC
		rts

; Sprung ins Basic-ROM
JumpToBasic	move.l	TheBasic,RPC
		and.w	#$1fff,d0
		add.l	d0,RPC
		rts

; Sprung ins Kernal-ROM
JumpToKernal	move.l	TheKernal,RPC
		and.w	#$1fff,d0
		add.l	d0,RPC
		rts

; Sprung ins Char-ROM (warum sollte jemand sowas tun? Aber egal.)
JumpToChar	move.l	TheChar,RPC
		and.w	#$0fff,d0
		add.l	d0,RPC
		rts

; Sprung in den I/O-Bereich (in VIC-Register wird ab und zu gerne gesprungen,
;  $de00 und das Farb-RAM sind auch sehr beliebt :-)
JumpToIO	movem.l	a2-a6,-(sp)

		move.w	d0,RequestStream	;PC anzeigen

		jsr	_EmulToBack

		move.l	_IntuitionBase,a6
		sub.l	a0,a0
		lea	JumpToIOReq,a1
		move.l	a0,a2
		lea	RequestStream,a3
		JSRLIB	EasyRequestArgs

		jsr	_EmulToFront

		movem.l	(sp)+,a2-a6

		jsr	ResetC64
		moveq	#0,d0			;MSWs von d0 und d1
		moveq	#0,d1			; müssen Null sein

		addq.l	#4,sp			;Rücksprungadresse löschen
		bra	HandleRESET


**
** Opcode-Routinen
**

*
* Interrupts handhaben
*

; Art des Interrupt feststellen (Priorität)
HandleInt	tst.b	IntIsRESET
		bne	HandleRESET
		tst.b	IntIsNMI
		bne	HandleNMI
		tst.w	IntIsIRQ
		bne	HandleIRQ

; Kein Interrupt, nächsten Befehl ausführen
HandleIntDone	Next	0

; IRQ: Interrupt-Bit testen, nach ($fffe) springen
HandleIRQ	btst	#InterruptBit,RP
		beq	IRQDoIt
		Next	0

IRQDoIt		PushPC
		PushP	0

		or.w	#InterruptMask,RP
		move.w	#$fffe,d0	;IRQ-Vektor
		ReadWord
		Jump
		Next	7

; NMI: Nach ($fffa) springen
HandleNMI	clr.b	IntIsNMI	;Simuliert einen flankengetriggerten Eingang

		PushPC
		PushP	0

		or.w	#InterruptMask,RP
		move.w	#$fffa,d0	;NMI-Vektor
		ReadWord
		Jump
		Next	7

; RESET: Emulator beenden, anhalten oder nach ($fffc) springen
HandleRESET	tst.b	RESETIsEXIT	;Beenden?
		bne	HandleEXIT
		tst.b	RESETIsPause	;Pause?
		bne	HandlePause

		clr.l	Interrupt	;Nein, RESET
		clr.b	NMIState

		cmp.l	#$c3c2cd38,$8004(RAMPTR)
		bne	1$
		cmp.b	#$30,$8008(RAMPTR)
		bne	1$
		clr.b	$8004(RAMPTR)	;CBM80 löschen, wenn vorhanden

1$		move.b	#$00,(RAMPTR)	;Speicherkonfiguration initialisieren (Port auf Eingabe)
		NewConfig

		move.w	#$fffc,d0	;RESET-Vektor
		ReadWord
		Jump
		Next	0

; EXIT: Signal an den Emulator schicken
HandleEXIT	jsr	_ExitDisplayFrom6510	;Grafik aufräumen

		move.l	_SysBase,a6

		moveq	#0,d0
		move.b	ContinueSig,d0
		JSRLIB	FreeSignal

		JSRLIB	Forbid
		move.l	MainTask,a1
		move.l	ReadySet,d0
		JSRLIB	Signal
		moveq	#0,d0
		rts

; Pause: Signal an den Emulator schicken und dann selbst auf
;  ein Signal warten, Zustand retten und wiederherstellen
HandlePause	bsr	Pause
		moveq	#0,d0
		moveq	#0,d1
		NewConfig
		move.w	_RPC,d0
		Jump
		Next	0

Pause		clr.b	IntIsRESET
		clr.b	RESETIsPause

		move.b	RA,_RA		;Register für SAM bereitstellen
		move.b	RX,_RX
		move.b	RY,_RY
		move.w	RP,d0
		lsr.w	#8,d0
		and.b	#$5c,d0		;V, B, D, I
		or.b	#$20,d0		;1-Bit setzen
		tst.b	RP		;C dazunehmen
		beq	1$
		or.b	#$01,d0
1$		btst	#3,RCCR		;N dazunehmen
		beq	2$
		or.b	#$80,d0
2$		btst	#2,RCCR		;Z dazunehmen
		beq	3$
		or.b	#$02,d0
3$		move.b	d0,_RP

		move.b	(RAMPTR),_RDDR
		move.b	1(RAMPTR),d0
		and.b	#$3f,d0
		move.b	d0,_RPR

		move.b	(RAMPTR),d0
		not.b	d0
		or.b	1(RAMPTR),d0
		and.b	#$07,d0
		move.b	d0,_SAMMemConfig

		move.w	RPC,_RPC
		move.w	RS,_RS

		move.l	_SysBase,a6
		move.l	MainTask,a1
		move.l	ReadySet,d0
		JSRLIB	Signal
		move.l	ContinueSet,d0
		JSRLIB	Wait

		move.l	TheRAM,RAMPTR
		lea	CyclesLeft,CYCPTR
		moveq	#0,RA		;Register von SAM lesen
		move.b	_RA,RA
		moveq	#0,RX
		move.b	_RX,RX
		moveq	#0,RY
		move.b	_RY,RY

		moveq	#0,RCCR
		btst	#7,_RP		;N holen
		beq	4$
		or.b	#$08,RCCR
4$		btst	#1,_RP		;Z holen
		beq	5$
		or.b	#$04,RCCR
5$
		moveq	#0,RP
		move.b	_RP,RP
		and.b	#$4c,RP		;V,D,I behalten
		lsl.w	#8,RP
		btst	#0,_RP		;C holen
		sne	RP

		move.l	#$0100,RS
		move.b	_RS+1,RS
		move.b	_RDDR,(RAMPTR)
		move.b	_RPR,1(RAMPTR)
		rts


*
* Opcodes
*

; Laden
LoadA		MACRO	;Quelle, Zyklenzahl
		move.b	\1,RA
		move	ccr,RCCR
		Next	\2
		ENDM

LoadX		MACRO	;Quelle, Zyklenzahl
		move.b	\1,RX
		move	ccr,RCCR
		Next	\2
		ENDM

LoadY		MACRO	;Quelle, Zyklenzahl
		move.b	\1,RY
		move	ccr,RCCR
		Next	\2
		ENDM

LoadAX		MACRO	;Quelle, Zyklenzahl
		move.b	\1,RA
		move.b	RA,RX
		move	ccr,RCCR
		Next	\2
		ENDM

LDAImm		LoadA	(RPC)+,2

LDAZero		ReadAdrZero
		LoadA	(RAMPTR,d0.l),3

LDAZeroX	ReadAdrZeroX
		LoadA	(RAMPTR,d0.l),4

LDAAbs		ReadByteAbs RA
		move	ccr,RCCR
		Next	4

LDAAbsX		ReadByteAbsX RA
		move	ccr,RCCR
		Next	4

LDAAbsY		ReadByteAbsY RA
		move	ccr,RCCR
		Next	4

LDAIndX		ReadByteIndX RA
		move	ccr,RCCR
		Next	6

LDAIndY		ReadByteIndY RA
		move	ccr,RCCR
		Next	5

LDXImm		LoadX	(RPC)+,2

LDXZero		ReadAdrZero
		LoadX	(RAMPTR,d0.l),3

LDXZeroY	ReadAdrZeroY
		LoadX	(RAMPTR,d0.l),4

LDXAbs		ReadByteAbs RX
		move	ccr,RCCR
		Next	4

LDXAbsY		ReadByteAbsY RX
		move	ccr,RCCR
		Next	4

LDYImm		LoadY	(RPC)+,2

LDYZero		ReadAdrZero
		LoadY	(RAMPTR,d0.l),3

LDYZeroX	ReadAdrZeroX
		LoadY	(RAMPTR,d0.l),4

LDYAbs		ReadByteAbs RY
		move	ccr,RCCR
		Next	4

LDYAbsX		ReadByteAbsX RY
		move	ccr,RCCR
		Next	4

LAXZero		ReadAdrZero
		LoadAX	(RAMPTR,d0.l),3

LAXZeroY	ReadAdrZeroY
		LoadAX	(RAMPTR,d0.l),4

LAXAbs		ReadByteAbs RA
		move.b	RA,RX
		move	ccr,RCCR
		Next	4

LAXAbsY		ReadByteAbsY RA
		move.b	RA,RX
		move	ccr,RCCR
		Next	4

LAXIndX		ReadByteIndX RA
		move.b	RA,RX
		move	ccr,RCCR
		Next	6

LAXIndY		ReadByteIndY RA
		move.b	RA,RX
		move	ccr,RCCR
		Next	5

; Speichern
StoreA		MACRO	;Zyklenzahl
		move.b	RA,d1
		WriteByte
		Next	\1
		ENDM

StoreAX		MACRO	;Zyklenzahl
		move.b	RA,d1
		and.b	RX,d1
		WriteByte
		Next	\1
		ENDM

STAZero		ReadAdrZero
		WriteZeroNext	RA,3

STAZeroX	ReadAdrZeroX
		WriteZeroNext	RA,4

STAAbs		ReadAdrAbs
		StoreA	4

STAAbsX		ReadAdrAbsX
		StoreA	5

STAAbsY		ReadAdrAbsY
		StoreA	5

STAIndX		ReadAdrIndX
		StoreA	6

STAIndY		ReadAdrIndY
		StoreA	6

STXZero		ReadAdrZero
		WriteZeroNext	RX,3

STXZeroY	ReadAdrZeroY
		WriteZeroNext	RX,4

STXAbs		ReadAdrAbs
		move.b	RX,d1
		WriteByte
		Next	4

STYZero		ReadAdrZero
		WriteZeroNext	RY,3

STYZeroX	ReadAdrZeroX
		WriteZeroNext	RY,4

STYAbs		ReadAdrAbs
		move.b	RY,d1
		WriteByte
		Next	4

SAXZero		ReadAdrZero
		StoreAX	3

SAXZeroY	ReadAdrZeroY
		StoreAX	4

SAXAbs		ReadAdrAbs
		StoreAX	4

SAXIndX		ReadAdrIndX
		StoreAX	6

; Datentransport zwischen Registern
TAX		move.b	RA,RX
		move	ccr,RCCR
		Next	2

TAY		move.b	RA,RY
		move	ccr,RCCR
		Next	2

TXA		move.b	RX,RA
		move	ccr,RCCR
		Next	2

TYA		move.b	RY,RA
		move	ccr,RCCR
		Next	2

TXS		move.b	RX,RS
		Next	2

TSX		move.b	RS,RX
		move	ccr,RCCR
		Next	2

; Stack
PHA		PushByte RA
		Next	3

PLA		PopByte	RA
		move	ccr,RCCR
		Next	4

PHP		PushP	1		;Break-Flag setzen
		Next	3

PLP		PopP
		tst.w	IntIsIRQ	;Steht ein IRQ an?
		beq	1$
		btst	#InterruptBit,RP ;Ja, I-Flag gelöscht?
		beq	HandleIRQ	;Ja, Interrupt auslösen
1$		Next	4

; Vergleiche
CompareA	MACRO	;Quelle, Zyklenzahl
		cmp.b	\1,RA
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		Next	\2
		ENDM

CMPImm		CompareA	(RPC)+,2

CMPZero		ReadAdrZero
		CompareA	(RAMPTR,d0.l),3

CMPZeroX	ReadAdrZeroX
		CompareA	(RAMPTR,d0.l),4

CMPAbs		ReadByteAbs
		CompareA	d0,4

CMPAbsX		ReadByteAbsX
		CompareA	d0,4

CMPAbsY		ReadByteAbsY
		CompareA	d0,4

CMPIndX		ReadByteIndX
		CompareA	d0,6

CMPIndY		ReadByteIndY
		CompareA	d0,5

CPXImm		cmp.b	(RPC)+,RX
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		Next	2

CPXZero		ReadAdrZero
		cmp.b	(RAMPTR,d0.l),RX
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		Next	3

CPXAbs		ReadByteAbs
		cmp.b	d0,RX
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		Next	4

CPYImm		cmp.b	(RPC)+,RY
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		Next	2

CPYZero		ReadAdrZero
		cmp.b	(RAMPTR,d0.l),RY
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		Next	3

CPYAbs		ReadByteAbs
		cmp.b	d0,RY
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		Next	4

; Arithmetische Operationen
AdcA		MACRO	;Zyklenzahl
		and.w	#~OverflowMask,RP
		btst	#DecimalBit,RP
		bne	\@2$

		add.b	RP,RP		;Carry -> X
		addx.b	d0,RA
		scs	RP		;Carry holen
		bvc	\@1$		;Overflow holen
		or.w	#OverflowMask,RP
\@1$		tst.b	RA		;N und Z holen (wegen addx)
		move	ccr,RCCR
		Next	\1

\@2$		bsr	AdcDec
		Next	\1
		ENDM

AdcDec		move.b	d0,TMPS		;Dezimalmodus
		move.b	RA,TMPA

		clr.b	RCCR

		move.b	RA,d1		;Unteres Nybble berechnen
		and.b	#$0f,d0
		and.b	#$0f,d1
		add.b	RP,RP		;Carry -> X
		addx.b	d0,d1		; -> d1

		cmp.b	#10,d1		;BCD-Fixup für das untere Nybble
		blo	2$
		addq.b	#6,d1
2$		move.b	d1,TMPAL

		move.b	TMPS,d0		;Oberes Nybble berechnen
		lsr.b	#4,d0
		lsr.b	#4,RA
		add.b	d0,RA
		cmp.b	#$10,d1
		blo	1$
		addq.b	#1,RA		; -> d2
1$
		move.b	TMPS,d0		;Z holen (wie im Binärmodus)
		move.b	TMPA,d1
		add.b	RP,RP		;Carry -> X
		addx.b	d0,d1
		tst.b	d1		;Wegen addx
		bne	6$
		or.b	#$04,RCCR
6$
		btst	#3,RA		;N berechnen
		beq	4$
		or.b	#$08,RCCR
4$
		move.b	RA,d0		;V berechnen
		lsl.b	#4,d0
		move.b	TMPA,d1
		eor.b	d1,d0
		bpl	5$
		move.b	TMPS,d0
		eor.b	d1,d0
		bmi	5$
		or.w	#OverflowMask,RP
5$
		cmp.b	#10,RA		;BCD-Fixup für das obere Nybble
		blo	3$
		addq.b	#6,RA
3$
		cmp.b	#$10,RA		;Carry holen
		shs	RP

		move.b	TMPAL,d0	;Ergebnis zusammensetzen
		and.b	#$0f,d0
		lsl.b	#4,RA
		or.b	d0,RA
		rts

ADCImm		move.b	(RPC)+,d0
		AdcA	2

ADCZero		ReadByteZero	d0
		AdcA	3

ADCZeroX	ReadByteZeroX	d0
		AdcA	4

ADCAbs		ReadByteAbs
		AdcA	4

ADCAbsX		ReadByteAbsX
		AdcA	4

ADCAbsY		ReadByteAbsY
		AdcA	4

ADCIndX		ReadByteIndX
		AdcA	6

ADCIndY		ReadByteIndY
		AdcA	5

SbcA		MACRO	;Zyklenzahl
		not.b	RP
		and.w	#~OverflowMask,RP
		btst	#DecimalBit,RP
		bne	\@2$

		add.b	RP,RP		;Inverses Carry -> X
		subx.b	d0,RA
		scc	RP		;Inverses Carry holen
		bvc	\@1$		;Overflow holen
		or.w	#OverflowMask,RP
\@1$		tst.b	RA
		move	ccr,RCCR	;N und Z holen (wegen subx)
		Next	\1

\@2$		bsr	SbcDec
		Next	\1
		ENDM

SbcDec		move.b	d0,TMPS		;Dezimalmodus
		move.b	RA,TMPA

		and.b	#$0f,d0		;Unteres Nybble berechnen
		and.b	#$0f,RA
		add.b	RP,RP		;Inverses Carry -> X
		subx.b	d0,RA
		move	ccr,d1
		bcc	1$		;BCD-Fixup
		subq.b	#6,RA
		st	d1
1$		and.b	#$0f,RA
		move.b	RA,TMPAL

		move.b	TMPS,d0		;Oberes Nybble berechnen
		move.b	TMPA,RA
		and.b	#$f0,d0
		and.b	#$f0,RA
		sub.b	d0,RA
		bcc	2$		;BCD-Fixup
		and.b	#$f0,RA
		sub.b	#$60,RA
		btst	#0,d1
		beq	3$
		sub.b	#$10,RA
		bra	3$
2$		and.b	#$f0,RA
		btst	#0,d1
		beq	3$
		sub.b	#$10,RA
		bcc	3$
		sub.b	#$60,RA
3$		or.b	TMPAL,RA	;Ergebnis zusammenbauen

		add.b	RP,RP		;Inverses Carry -> X
		move.b	TMPS,d0		;Flags berechnen (wie im Binärmodus)
		move.b	TMPA,d1
		subx.b	d0,d1		;Flags berechnen
		scc	RP		;Inverses Carry holen
		bvc	4$		;Overflow holen
		or.w	#OverflowMask,RP
4$		tst.b	d1		;N und Z holen (wegen subx)
		move	ccr,RCCR
		rts

SBCImm		move.b	(RPC)+,d0
		SbcA	2

SBCZero		ReadByteZero	d0
		SbcA	3

SBCZeroX	ReadByteZeroX	d0
		SbcA	4

SBCAbs		ReadByteAbs
		SbcA	4

SBCAbsX		ReadByteAbsX
		SbcA	4

SBCAbsY		ReadByteAbsY
		SbcA	4

SBCIndX		ReadByteIndX
		SbcA	6

SBCIndY		ReadByteIndY
		SbcA	5

Increment	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		addq.b	#1,d1
		move	ccr,RCCR
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

IncrementZero	MACRO	;Zyklenzahl
		addq.b	#1,(RAMPTR,d0.l)
		move	ccr,RCCR
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

INCZero		ReadAdrZero
		IncrementZero	5

INCZeroX	ReadAdrZeroX
		IncrementZero	6

INCAbs		ReadAdrAbs
		Increment	6

INCAbsX		ReadAdrAbsX
		Increment	7

Decrement	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		subq.b	#1,d1
		move	ccr,RCCR
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

DecrementZero	MACRO	;Zyklenzahl
		subq.b	#1,(RAMPTR,d0.l)
		move	ccr,RCCR
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

DECZero		ReadAdrZero
		DecrementZero	5
		
DECZeroX	ReadAdrZeroX
		DecrementZero	6

DECAbs		ReadAdrAbs
		Decrement	6

DECAbsX		ReadAdrAbsX
		Decrement	7

INX		addq.b	#1,RX
		move	ccr,RCCR
		Next	2

DEX		subq.b	#1,RX
		move	ccr,RCCR
		Next	2

INY		addq.b	#1,RY
		move	ccr,RCCR
		Next	2

DEY		subq.b	#1,RY
		move	ccr,RCCR
		Next	2

; Logische Operationen
AndA		MACRO	;Quelle, Zyklenzahl
		and.b	\1,RA
		move	ccr,RCCR
		Next	\2
		ENDM

ANDImm		AndA	(RPC)+,2

ANDZero		ReadAdrZero
		AndA	(RAMPTR,d0.l),3

ANDZeroX	ReadAdrZeroX
		AndA	(RAMPTR,d0.l),4

ANDAbs		ReadByteAbs
		AndA	d0,4

ANDAbsX		ReadByteAbsX
		AndA	d0,4

ANDAbsY		ReadByteAbsY
		AndA	d0,4

ANDIndX		ReadByteIndX
		AndA	d0,6

ANDIndY		ReadByteIndY
		AndA	d0,5

OrA		MACRO	;Quelle, Zyklenzahl
		or.b	\1,RA
		move	ccr,RCCR
		Next	\2
		ENDM

ORAImm		OrA	(RPC)+,2

ORAZero		ReadAdrZero
		OrA	(RAMPTR,d0.l),3

ORAZeroX	ReadAdrZeroX
		OrA	(RAMPTR,d0.l),4

ORAAbs		ReadByteAbs
		OrA	d0,4

ORAAbsX		ReadByteAbsX
		OrA	d0,4

ORAAbsY		ReadByteAbsY
		OrA	d0,4

ORAIndX		ReadByteIndX
		OrA	d0,6

ORAIndY		ReadByteIndY
		OrA	d0,5

EorA		MACRO	;Zyklenzahl
		eor.b	d0,RA		;eor.b (ea),RA geht nicht
		move	ccr,RCCR	;(Warum nicht, Motorola ?) :-(
		Next	\1
		ENDM

EORImm		move.b	(RPC)+,d0
		EorA	2

EORZero		ReadByteZero d0
		EorA	3

EORZeroX	ReadByteZeroX d0
		EorA	4

EORAbs		ReadByteAbs
		EorA	4

EORAbsX		ReadByteAbsX
		EorA	4

EORAbsY		ReadByteAbsY
		EorA	4

EORIndX		ReadByteIndX
		EorA	6

EORIndY		ReadByteIndY
		EorA	5

BitTest		MACRO	;Zyklenzahl
		clr.b	RCCR
		and.w	#~OverflowMask,RP

		tst.b	d0		;Bit 7 -> N
		bpl	\@1$
		or.b	#$08,RCCR
\@1$
		btst	#6,d0		;Bit 6 -> V
		beq	\@2$
		or.w	#OverflowMask,RP
\@2$
		and.b	RA,d0		;A AND M -> Z
		bne	\@3$
		or.b	#$04,RCCR
\@3$		Next	\1
		ENDM

BITZero		ReadByteZero	d0
		BitTest	3

BITAbs		ReadByteAbs
		BitTest	4

; Verschiebungen
ShiftLeft	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		add.b	d1,d1
		scs	RP		;Carry holen
		move	ccr,RCCR
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

ShiftLeftZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		add.b	d1,d1
		scs	RP		;Carry holen
		move.b	d1,(a0)
		move	ccr,RCCR
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

ASLA		add.b	RA,RA
		move	ccr,RCCR
		scs	RP		;Carry holen
		Next	2

ASLZero		ReadAdrZero
		ShiftLeftZero	5

ASLZeroX	ReadAdrZeroX
		ShiftLeftZero	6

ASLAbs		ReadAdrAbs
		ShiftLeft	6

ASLAbsX		ReadAdrAbsX
		ShiftLeft	7

ShiftRight	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		lsr.b	#1,d1
		scs	RP		;Carry holen
		move	ccr,RCCR
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

ShiftRightZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		lsr.b	#1,d1
		scs	RP		;Carry holen
		move.b	d1,(a0)
		move	ccr,RCCR
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

LSRA		lsr.b	#1,RA
		move	ccr,RCCR
		scs	RP		;Carry holen
		Next	2

LSRZero		ReadAdrZero
		ShiftRightZero	5

LSRZeroX	ReadAdrZeroX
		ShiftRightZero	6

LSRAbs		ReadAdrAbs
		ShiftRight	6

LSRAbsX		ReadAdrAbsX
		ShiftRight	7

RotateLeft	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		add.b	RP,RP		;Carry -> X
		roxl.b	#1,d1
		scs	RP		;Carry holen
		move	ccr,RCCR
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

RotateLeftZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		add.b	RP,RP		;Carry -> X
		roxl.b	#1,d1
		scs	RP		;Carry holen
		move.b	d1,(a0)
		move	ccr,RCCR
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

ROLA		add.b	RP,RP		;Carry -> X
		roxl.b	#1,RA
		move	ccr,RCCR
		scs	RP		;Carry holen
		Next	2

ROLZero		ReadAdrZero
		RotateLeftZero	5

ROLZeroX	ReadAdrZeroX
		RotateLeftZero	6

ROLAbs		ReadAdrAbs
		RotateLeft	6

ROLAbsX		ReadAdrAbsX
		RotateLeft	7

RotateRight	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		add.b	RP,RP		;Carry -> X
		roxr.b	#1,d1
		scs	RP		;Carry holen
		move	ccr,RCCR
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

RotateRightZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		add.b	RP,RP		;Carry -> X
		roxr.b	#1,d1
		scs	RP		;Carry holen
		move.b	d1,(a0)
		move	ccr,RCCR
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

RORA		add.b	RP,RP		;Carry -> X
		roxr.b	#1,RA
		move	ccr,RCCR
		scs	RP		;Carry holen
		Next	2

RORZero		ReadAdrZero
		RotateRightZero	5

RORZeroX	ReadAdrZeroX
		RotateRightZero	6

RORAbs		ReadAdrAbs
		RotateRight	6

RORAbsX		ReadAdrAbsX
		RotateRight	7

; Sprünge/Verzweigungen
JMPAbs		ReadAdrAbs
		Jump
		Next	3

JMPInd		ReadAdrInd
		Jump
		Next	5

JSRAbs		PushPCPlus1
		ReadAdrAbs
		Jump
		Next	6

RTSImpl		PopByte	d1		;LSB
		PopByte	d0		;MSB
		lsl.w	#8,d0		;schieben
		move.b	d1,d0		;LSB dazunehmen
		addq.w	#1,d0		;Adresse um eins erhöhen
		Jump
		Next	6

RTIImpl		PopP
		PopByte	d1		;LSB
		PopByte	d0		;MSB
		lsl.w	#8,d0		;schieben
		move.b	d1,d0		;LSB dazunehmen
		Jump
		tst.w	IntIsIRQ	;Steht ein IRQ an?
		beq	1$
		btst	#InterruptBit,RP ;Ja, I-Flag gelöscht?
		beq	HandleIRQ	;Ja, Interrupt auslösen
1$		Next	6

BRK		PushPC
		PushP	1
		or.w	#InterruptMask,RP
		move.w	#$fffe,d0	;IRQ-Vektor
		ReadWord
		Jump
		Next	7

Branch		MACRO
		ReadByteRel
		move.l	RPC,d1
		add.w	d0,d1
		move.l	d1,RPC
		moveq	#0,d1
		Next	3
		ENDM

BVCRel		btst	#OverflowBit,RP
		bne	BVCNot
		Branch
BVCNot		addq.l	#1,RPC
		Next	2

BVSRel		btst	#OverflowBit,RP
		beq	BVSNot
		Branch
BVSNot		addq.l	#1,RPC
		Next	2

BEQRel		btst	#2,RCCR
		beq	BEQNot
		Branch
BEQNot		addq.l	#1,RPC
		Next	2

BNERel		btst	#2,RCCR
		bne	BNENot
		Branch
BNENot		addq.l	#1,RPC
		Next	2

BPLRel		btst	#3,RCCR
		bne	BPLNot
		Branch
BPLNot		addq.l	#1,RPC
		Next	2

BMIRel		btst	#3,RCCR
		beq	BMINot
		Branch
BMINot		addq.l	#1,RPC
		Next	2

BCCRel		tst.b	RP
		bne	BCCNot
		Branch
BCCNot		addq.l	#1,RPC
		Next	2

BCSRel		tst.b	RP
		beq	BCSNot
		Branch
BCSNot		addq.l	#1,RPC
		Next	2

; Statusregister
SEI		or.w	#InterruptMask,RP
		Next	2

CLI		and.w	#~InterruptMask,RP
		tst.w	IntIsIRQ	;Steht ein IRQ an?
		bne	HandleIRQ	;Ja, auslösen
		Next	2

CLC		clr.b	RP
		Next	2

SEC		st.b	RP
		Next	2

SED		or.w	#DecimalMask,RP
		Next	2

CLD		and.w	#~DecimalMask,RP
		Next	2

CLV		and.w	#~OverflowMask,RP
		Next	2

*
* Periodic: Wird über den Opcode-Fetch aufgerufen,
*  wenn der Zyklenzähler unterläuft
* Sitzt hier in der Mitte, um kurze Branches ausnutzen zu können
*

; VIC und CIA aufrufen
Periodic	lea	RegStore+20,a0
		movem.w	d2-d7,-(a0)	;Gerade Anzahl von Registern
		movem.l	RWTAB/RPC,-(a0)
		bra	Periodic6569	;Springt nach Periodic6526 und hierher zurück
Peri6526Cont	lea	_DATA_BAS_,a4
		lea	32766(a4),a4
		movem.l	RegStore,RWTAB/RPC
		movem.w	RegStore+8,d2-d7
		move.l	TheRAM,RAMPTR
		lea	CyclesLeft,CYCPTR
		moveq	#0,d0
		moveq	#0,d1

; Interrupt aufgetreten?
		tst.l	Interrupt
		bne	HandleInt

; Nein, Nächsten Befehl ausführen
		Next	0


; Leerbefehle
NOPImpl		Next	2

NOPZero		addq.w	#1,RPC
		Next	3

NOPZeroX	addq.w	#1,RPC
		Next	4

NOPAbsX
NOPAbs		addq.w	#2,RPC
		Next	4

; ASL/ORA-Gruppe
ShLeftOr	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		add.b	d1,d1
		scs	RP		;Carry holen
		or.b	d1,RA
		move	ccr,RCCR
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

ShLeftOrZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		add.b	d1,d1
		scs	RP		;Carry holen
		or.b	d1,RA
		move	ccr,RCCR
		move.b	d1,(a0)
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

SLOZero		ReadAdrZero
		ShLeftOrZero	5

SLOZeroX	ReadAdrZeroX
		ShLeftOrZero	6

SLOAbs		ReadAdrAbs
		ShLeftOr	6

SLOAbsX		ReadAdrAbsX
		ShLeftOr	7

SLOAbsY		ReadAdrAbsY
		ShLeftOr	7

SLOIndX		ReadAdrIndX
		ShLeftOr	8

SLOIndY		ReadAdrIndY
		ShLeftOr	8

; ROL/AND-Gruppe
RoLeftAnd	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		add.b	RP,RP		;Carry -> X
		roxl.b	#1,d1
		scs	RP		;Carry holen
		and.b	d1,RA
		move	ccr,RCCR	;N und Z holen
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

RoLeftAndZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		add.b	RP,RP		;Carry -> X
		roxl.b	#1,d1
		scs	RP		;Carry holen
		and.b	d1,RA
		move	ccr,RCCR	;N und Z holen
		move.b	d1,(a0)
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

RLAZero		ReadAdrZero
		RoLeftAndZero	5

RLAZeroX	ReadAdrZeroX
		RoLeftAndZero	6

RLAAbs		ReadAdrAbs
		RoLeftAnd	6

RLAAbsX		ReadAdrAbsX
		RoLeftAnd	7

RLAAbsY		ReadAdrAbsY
		RoLeftAnd	7

RLAIndX		ReadAdrIndX
		RoLeftAnd	8

RLAIndY		ReadAdrIndY
		RoLeftAnd	8

; LSR/EOR-Gruppe
ShRightEor	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		lsr.b	#1,d1
		scs	RP		;Carry holen
		eor.b	d1,RA
		move	ccr,RCCR
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

ShRightEorZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		lsr.b	#1,d1
		scs	RP		;Carry holen
		eor.b	d1,RA
		move	ccr,RCCR
		move.b	d1,(a0)
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

SREZero		ReadAdrZero
		ShRightEorZero	5

SREZeroX	ReadAdrZeroX
		ShRightEorZero	6

SREAbs		ReadAdrAbs
		ShRightEor	6

SREAbsX		ReadAdrAbsX
		ShRightEor	7

SREAbsY		ReadAdrAbsY
		ShRightEor	7

SREIndX		ReadAdrIndX
		ShRightEor	8

SREIndY		ReadAdrIndY
		ShRightEor	8

; ROR/ADC-Gruppe
RoRightAdc	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		add.b	RP,RP		;Carry -> X
		roxr.b	#1,d1
		scs	RP		;Carry holen
		addx.b	d1,RA
		bvc	\@2$		;Overflow holen
		or.w	#OverflowMask,RP
		bra	\@3$
\@2$		and.w	#~OverflowMask,RP
\@3$		tst.b	RA
		move	ccr,RCCR	;N und Z holen
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

RoRightAdcZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		add.b	RP,RP		;Carry -> X
		roxr.b	#1,d1
		addx.b	d1,RA
		scs	RP		;Carry holen
		bvc	\@2$		;Overflow holen
		or.w	#OverflowMask,RP
		bra	\@3$
\@2$		and.w	#~OverflowMask,RP
\@3$		tst.b	RA
		move	ccr,RCCR	;N und Z holen
		move.b	d1,(a0)
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

RRAZero		ReadAdrZero
		RoRightAdcZero	5

RRAZeroX	ReadAdrZeroX
		RoRightAdcZero	6

RRAAbs		ReadAdrAbs
		RoRightAdc	6

RRAAbsX		ReadAdrAbsX
		RoRightAdc	7

RRAAbsY		ReadAdrAbsY
		RoRightAdc	7

RRAIndX		ReadAdrIndX
		RoRightAdc	8

RRAIndY		ReadAdrIndY
		RoRightAdc	8

; DEC/CMP-Gruppe
DecCompare	MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		subq.b	#1,d1
		cmp.b	d1,RA
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

DecCompareZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		subq.b	#1,d1
		cmp.b	d1,RA
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		move.b	d1,(a0)
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

DCPZero		ReadAdrZero
		DecCompareZero	5

DCPZeroX	ReadAdrZeroX
		DecCompareZero	6

DCPAbs		ReadAdrAbs
		DecCompare	6

DCPAbsX		ReadAdrAbsX
		DecCompare	7

DCPAbsY		ReadAdrAbsY
		DecCompare	7

DCPIndX		ReadAdrIndX
		DecCompare	8

DCPIndY		ReadAdrIndY
		DecCompare	8

; INC/SBC-Gruppe
IncSbc		MACRO	;Zyklenzahl
		move.l	d0,-(sp)
		ReadByte d1
		addq.b	#1,d1
		not.b	RP
		add.b	RP,RP		;Inverses Carry -> X
		subx.b	d1,RA
		scc	RP		;Inverses Carry holen
		bvc	\@2$		;Overflow holen
		or.w	#OverflowMask,RP
		bra	\@3$
\@2$		and.w	#~OverflowMask,RP
\@3$		tst.b	RA		;N und Z holen
		move	ccr,RCCR
		move.l	(sp)+,d0
		WriteByte
		Next	\1
		ENDM

IncSbcZero	MACRO	;Zyklenzahl
		lea	(RAMPTR,d0.l),a0
		move.b	(a0),d1
		addq.b	#1,d1
		not.b	RP
		add.b	RP,RP		;Inverses Carry -> X
		subx.b	d1,RA
		scc	RP		;Inverses Carry holen
		bvc	\@2$		;Overflow holen
		or.w	#OverflowMask,RP
		bra	\@3$
\@2$		and.w	#~OverflowMask,RP
\@3$		tst.b	RA		;N und Z holen
		move	ccr,RCCR
		move.b	d1,(a0)
		cmp.b	#2,d0
		bhs	\@1$
		NewConfig
\@1$		Next	\1
		ENDM

ISBZero		ReadAdrZero
		IncSbcZero	5

ISBZeroX	ReadAdrZeroX
		IncSbcZero	6

ISBAbs		ReadAdrAbs
		IncSbc	6

ISBAbsX		ReadAdrAbsX
		IncSbc	7

ISBAbsY		ReadAdrAbsY
		IncSbc	7

ISBIndX		ReadAdrIndX
		IncSbc	8

ISBIndY		ReadAdrIndY
		IncSbc	8

; Komplexe (undokumentierte) Funktionen
ANCImm		and.b	(RPC)+,RA	;??? ($0b, $2b)
		move	ccr,RCCR
		smi.b	RP		;N -> C (??)
		Next	2

ASRImm		and.b	(RPC)+,RA
		lsr.b	#1,RA
		move	ccr,RCCR
		scs	RP		;Carry holen
		Next	2

ARRImm		and.b	(RPC)+,RA
		add.b	RP,RP		;Carry -> X
		roxr.b	#1,RA
		move	ccr,RCCR
		scs	RP		;Carry holen
		Next	2

ANEImm		or.b	#$ee,RA
		and.b	(RPC)+,RA
		and.b	RX,RA
		move	ccr,RCCR
		Next	2

LXAImm		and.b	(RPC)+,RA
		move.b	RA,RX
		move	ccr,RCCR
		Next	2

LASAbsY		ReadByteAbsY		;??? ($bb)
		and.b	RS,d0
		move.b	d0,RX
		move.b	d0,RA
		move	ccr,RCCR
		Next	4

SHAAbsY		ReadPCWord
		move.w	d0,d1
		lsr.w	#8,d1
		addq.b	#1,d1
		and.b	RX,d1
		and.b	RA,d1
		add.w	RY,d0
		WriteByte
		Next	5

SHAIndY		moveq	#0,d0
		move.b	(RPC)+,d0
		move.w	(RAMPTR,d0.l),d0	;(Abgekürzt)
		rol.w	#8,d0			;Geht bei ($ff),y schief
		move.w	d0,d1
		lsr.w	#8,d1
		addq.b	#1,d1
		and.b	RX,d1
		and.b	RA,d1
		add.w	RY,d0
		WriteByte
		Next	6

SHXAbsY		ReadPCWord
		move.w	d0,d1
		lsr.w	#8,d1
		addq.b	#1,d1
		and.b	RY,d1
		add.w	RY,d0
		WriteByte
		Next	5

SHYAbsX		ReadPCWord
		move.w	d0,d1
		lsr.w	#8,d1
		addq.b	#1,d1
		and.b	RX,d1
		add.w	RX,d0
		WriteByte
		Next	5

SHSAbsY		move.b	RA,RS
		and.b	RX,RS
		ReadPCWord
		move.w	d0,d1
		lsr.w	#8,d1
		addq.b	#1,d1
		and.b	RS,d1
		WriteByte
		Next	5

SBXImm		and.b	RA,RX
		sub.b	(RPC)+,RX
		move	ccr,RCCR
		scc	RP		;Inverses Carry holen
		Next	2

*
* Erweiterte Opcodes
*

; $d2
OpWrap		move.l	RPC,d1		;Wraparound nach $100xx?
		sub.l	RAMPTR,d1
		swap	d1
		cmp.w	#1,d1
		bne	IllegalOp
		sub.l	#$10001,RPC	;Ja, zu $00xx umleiten
		moveq	#0,d1
		Next	0

; $f2 $xx
OpIEC		move.b	(RPC)+,d0	;Selektor holen
		beq	OpIECOut
		cmp.b	#1,d0
		beq	OpIECOutATN
		cmp.b	#2,d0
		beq	OpIECOutSec
		cmp.b	#3,d0
		beq	OpIECIn
		cmp.b	#4,d0
		beq	OpIECSetATN
		cmp.b	#5,d0
		beq	OpIECRelATN
		cmp.b	#6,d0
		beq	OpIECTurnaround
		cmp.b	#7,d0
		beq	OpIECRelease
		bra	IllegalOp

OpIECOut	move.b	$95(RAMPTR),d0	;Auszugebendes Byte holen
		move.b	$a3(RAMPTR),d1	;EOI-Flag holen
		bsr	IECOut
		bra	IECSetST

OpIECOutATN	move.b	$95(RAMPTR),d0	;Auszugebendes Byte holen
		bsr	IECOutATN
		bra	IECSetST

OpIECOutSec	move.b	$95(RAMPTR),d0	;Auszugebendes Byte holen
		bsr	IECOutSec
		bra	IECSetST

OpIECIn		bsr	IECIn
		move.b	d1,RA		;Byte in den Akku
		move	ccr,RCCR	;Flags entsprechend setzen
		bra	IECSetST

OpIECSetATN	bsr	IECSetATN
		moveq	#0,d0		;MSWs von d0 und d1 löschen
		moveq	#0,d1
		move.w	#$edfb,d0	;Nach $edfb springen
		Jump
		Next	0

OpIECRelATN	bsr	IECRelATN
		bra	IECReturn

OpIECTurnaround	bsr	IECTurnaround
		bra	IECReturn

OpIECRelease	bsr	IECRelease
		bra	IECReturn

IECSetST	or.b	d0,$90(RAMPTR)	;Status setzen
		clr.b	RP		;Carry löschen
IECReturn	moveq	#0,d0		;MSWs von d0 und d1 löschen
		moveq	#0,d1
		bra	RTSImpl		;RTS ausführen


**
** Konstanten
**

*
* Opcode Dispatch Table
* "*" bezeichnet einen undokumentierten Opcode
*

		CNOP	0,4
OpcodeTable	dc.l	BRK		;$00
		dc.l	ORAIndX
		dc.l	IllegalOp
		dc.l	SLOIndX		;*
		dc.l	NOPZero		;*
		dc.l	ORAZero
		dc.l	ASLZero
		dc.l	SLOZero		;*

		dc.l	PHP		;$08
		dc.l	ORAImm
		dc.l	ASLA
		dc.l	ANCImm		;*
		dc.l	NOPAbs		;*
		dc.l	ORAAbs
		dc.l	ASLAbs
		dc.l	SLOAbs		;*

		dc.l	BPLRel		;$10
		dc.l	ORAIndY
		dc.l	IllegalOp
		dc.l	SLOIndY		;*
		dc.l	NOPZeroX	;*
		dc.l	ORAZeroX
		dc.l	ASLZeroX
		dc.l	SLOZeroX	;*

		dc.l	CLC		;$18
		dc.l	ORAAbsY
		dc.l	NOPImpl		;*
		dc.l	SLOAbsY		;*
		dc.l	NOPAbsX		;*
		dc.l	ORAAbsX
		dc.l	ASLAbsX
		dc.l	SLOAbsX

		dc.l	JSRAbs		;$20
		dc.l	ANDIndX
		dc.l	IllegalOp
		dc.l	RLAIndX		;*
		dc.l	BITZero
		dc.l	ANDZero
		dc.l	ROLZero
		dc.l	RLAZero		;*

		dc.l	PLP		;$28
		dc.l	ANDImm
		dc.l	ROLA
		dc.l	ANCImm		;*
		dc.l	BITAbs
		dc.l	ANDAbs
		dc.l	ROLAbs
		dc.l	RLAAbs		;*

		dc.l	BMIRel		;$30
		dc.l	ANDIndY
		dc.l	IllegalOp
		dc.l	RLAIndY		;*
		dc.l	NOPZeroX	;*
		dc.l	ANDZeroX
		dc.l	ROLZeroX
		dc.l	RLAZeroX	;*

		dc.l	SEC		;$38
		dc.l	ANDAbsY
		dc.l	NOPImpl		;*
		dc.l	RLAAbsY		;*
		dc.l	NOPAbsX		;*
		dc.l	ANDAbsX
		dc.l	ROLAbsX
		dc.l	RLAAbsX		;*

		dc.l	RTIImpl		;$40
		dc.l	EORIndX
		dc.l	IllegalOp
		dc.l	SREIndX		;*
		dc.l	NOPZero		;*
		dc.l	EORZero
		dc.l	LSRZero
		dc.l	SREZero		;*

		dc.l	PHA		;$48
		dc.l	EORImm
		dc.l	LSRA
		dc.l	ASRImm		;*
		dc.l	JMPAbs
		dc.l	EORAbs
		dc.l	LSRAbs
		dc.l	SREAbs		;*

		dc.l	BVCRel		;$50
		dc.l	EORIndY
		dc.l	IllegalOp
		dc.l	SREIndY		;*
		dc.l	NOPZeroX	;*
		dc.l	EORZeroX
		dc.l	LSRZeroX
		dc.l	SREZeroX	;*

		dc.l	CLI		;$58
		dc.l	EORAbsY
		dc.l	NOPImpl		;*
		dc.l	SREAbsY		;*
		dc.l	NOPAbsX		;*
		dc.l	EORAbsX
		dc.l	LSRAbsX
		dc.l	SREAbsX		;*

		dc.l	RTSImpl		;$60
		dc.l	ADCIndX
		dc.l	IllegalOp
		dc.l	RRAIndX		;*
		dc.l	NOPZero		;*
		dc.l	ADCZero
		dc.l	RORZero
		dc.l	RRAZero		;*

		dc.l	PLA		;$68
		dc.l	ADCImm
		dc.l	RORA
		dc.l	ARRImm		;*
		dc.l	JMPInd
		dc.l	ADCAbs
		dc.l	RORAbs
		dc.l	RRAAbs		;*

		dc.l	BVSRel		;$70
		dc.l	ADCIndY
		dc.l	IllegalOp
		dc.l	RRAIndY		;*
		dc.l	NOPZeroX	;*
		dc.l	ADCZeroX
		dc.l	RORZeroX
		dc.l	RRAZeroX	;*

		dc.l	SEI		;$78
		dc.l	ADCAbsY
		dc.l	NOPImpl		;*
		dc.l	RRAAbsY		;*
		dc.l	NOPAbsX		;*
		dc.l	ADCAbsX
		dc.l	RORAbsX
		dc.l	RRAAbsX		;*

		dc.l	NOPZero		;* $80
		dc.l	STAIndX
		dc.l	NOPZero		;*
		dc.l	SAXIndX		;*
		dc.l	STYZero
		dc.l	STAZero
		dc.l	STXZero
		dc.l	SAXZero		;*

		dc.l	DEY		;$88
		dc.l	NOPZero		;*
		dc.l	TXA
		dc.l	ANEImm		;*
		dc.l	STYAbs
		dc.l	STAAbs
		dc.l	STXAbs
		dc.l	SAXAbs		;*

		dc.l	BCCRel		;$90
		dc.l	STAIndY
		dc.l	IllegalOp
		dc.l	SHAIndY		;*
		dc.l	STYZeroX
		dc.l	STAZeroX
		dc.l	STXZeroY
		dc.l	SAXZeroY	;*

		dc.l	TYA		;$98
		dc.l	STAAbsY
		dc.l	TXS
		dc.l	SHSAbsY		;*
		dc.l	SHYAbsX		;*
		dc.l	STAAbsX
		dc.l	SHXAbsY		;*
		dc.l	SHAAbsY		;*

		dc.l	LDYImm		;$a0
		dc.l	LDAIndX
		dc.l	LDXImm
		dc.l	LAXIndX		;*
		dc.l	LDYZero
		dc.l	LDAZero
		dc.l	LDXZero
		dc.l	LAXZero		;*

		dc.l	TAY		;$a8
		dc.l	LDAImm
		dc.l	TAX
		dc.l	LXAImm		;*
		dc.l	LDYAbs
		dc.l	LDAAbs
		dc.l	LDXAbs
		dc.l	LAXAbs		;*

		dc.l	BCSRel		;$b0
		dc.l	LDAIndY
		dc.l	IllegalOp
		dc.l	LAXIndY		;*
		dc.l	LDYZeroX
		dc.l	LDAZeroX
		dc.l	LDXZeroY
		dc.l	LAXZeroY	;*

		dc.l	CLV		;$b8
		dc.l	LDAAbsY
		dc.l	TSX
		dc.l	LASAbsY		;*
		dc.l	LDYAbsX
		dc.l	LDAAbsX
		dc.l	LDXAbsY
		dc.l	LAXAbsY		;*

		dc.l	CPYImm		;$c0
		dc.l	CMPIndX
		dc.l	NOPZero		;*
		dc.l	DCPIndX		;*
		dc.l	CPYZero
		dc.l	CMPZero
		dc.l	DECZero
		dc.l	DCPZero		;*

		dc.l	INY		;$c8
		dc.l	CMPImm
		dc.l	DEX
		dc.l	SBXImm		;*
		dc.l	CPYAbs
		dc.l	CMPAbs
		dc.l	DECAbs
		dc.l	DCPAbs		;*

		dc.l	BNERel		;$d0
		dc.l	CMPIndY
		dc.l	OpWrap
		dc.l	DCPIndY		;*
		dc.l	NOPZeroX	;*
		dc.l	CMPZeroX
		dc.l	DECZeroX
		dc.l	DCPZeroX	;*

		dc.l	CLD		;$d8
		dc.l	CMPAbsY
		dc.l	NOPImpl		;*
		dc.l	DCPAbsY		;*
		dc.l	NOPAbsX		;*
		dc.l	CMPAbsX
		dc.l	DECAbsX
		dc.l	DCPAbsX		;*

		dc.l	CPXImm		;$e0
		dc.l	SBCIndX
		dc.l	NOPZero		;*
		dc.l	ISBIndX		;*
		dc.l	CPXZero
		dc.l	SBCZero
		dc.l	INCZero
		dc.l	ISBZero		;*

		dc.l	INX		;$e8
		dc.l	SBCImm
		dc.l	NOPImpl
		dc.l	SBCImm		;*
		dc.l	CPXAbs
		dc.l	SBCAbs
		dc.l	INCAbs
		dc.l	ISBAbs		;*

		dc.l	BEQRel		;$f0
		dc.l	SBCIndY
		dc.l	OpIEC		;Patch
		dc.l	ISBIndY		;*
		dc.l	NOPZeroX	;*
		dc.l	SBCZeroX
		dc.l	INCZeroX
		dc.l	ISBZeroX	;*

		dc.l	SED		;$f8
		dc.l	SBCAbsY
		dc.l	NOPImpl		;*
		dc.l	ISBAbsY		;*
		dc.l	NOPAbsX		;*
		dc.l	SBCAbsX
		dc.l	INCAbsX
		dc.l	ISBAbsX		;*


*
* Speicherkonfigurationstabelle
*

; Diese Tabelle enthält für alle 8 Speicherkonfigurationen
; die Zeiger auf die zugehörigen Read- und WriteTabs
		CNOP	0,4
ConfigTab	dc.l	ReadWriteTab0
		dc.l	ReadWriteTab1
		dc.l	ReadWriteTab2
		dc.l	ReadWriteTab3
		dc.l	ReadWriteTab4
		dc.l	ReadWriteTab5
		dc.l	ReadWriteTab6
		dc.l	ReadWriteTab7


*
* Sonstige Konstanten
*

; Taglist für CreateNewProc
ProcTags	dc.l	NP_Entry,CPUTaskProc
		dc.l	NP_Name,CPUTaskName
		dc.l	NP_Priority,-1
		dc.l	0

; Strings
CPUTaskName	dc.b	"6510",0

IDString	dc.b	"FRODO V2.3",13
		dc.b	"(C)1994-1996 CHRISTIAN BAUER",0
		ds.b	64	;Muß mind. 92 Zeichen lang sein

; Flag: Dies ist nicht Frodo SC
		CNOP	0,4
_IsFrodoSC
IsFrodoSC	dc.w	0


**
** Initialisierte Daten
**

		SECTION	"DATA",DATA

; Requester
IllegalOpReq	dc.l	20,0,0,0,0
JumpToIOReq	dc.l	20,0,0,0,0

; Emulator-Kennung
DFFFByte	dc.b	$55	;Wechselt bei jedem Lesen zwischen $55 und $aa


**
** Nicht initialisierte Daten
**

		SECTION	"BSS",BSS

; Sprungtabellen für Speicherzugriff: Zwei Einträge pro Seite (Lesen/Schreiben)
; Eine Tabelle für jede der 8 Speicherkonfigurationen
ReadWriteTab0	ds.l	512
ReadWriteTab1	ds.l	512
ReadWriteTab2	ds.l	512
ReadWriteTab3	ds.l	512
ReadWriteTab4	ds.l	512
ReadWriteTab5	ds.l	512
ReadWriteTab6	ds.l	512
ReadWriteTab7	ds.l	512

; Sprungtabellen für Sprungbefehle: Einen Eintrag pro Seite (8 Bytes, nur
;   die ersten 4 Bytes benutzt)
JumpTab0	ds.l	512
JumpTab1	ds.l	512
JumpTab2	ds.l	512
JumpTab3	ds.l	512
JumpTab4	ds.l	512
JumpTab5	ds.l	512
JumpTab6	ds.l	512
JumpTab7	ds.l	512


		SECTION	"__MERGED",BSS

; 6510-Task
		CNOP	0,4
CPUProc		ds.l	1	;Prozess-Handle
		XDEF	_CPUTask
_CPUTask
CPUTask		ds.l	1	;Task des Prozesses
ReadySet	ds.l	1	;Signal des Hauptprogramms
_InvokeSAMSet
InvokeSAMSet	ds.l	1	;Signal -> Hauptprogramm: SAM aufrufen
ContinueSet	ds.l	1	;Signal des CPU-Tasks
ReadySig	ds.b	1
InvokeSAMSig	ds.b	1
ContinueSig	ds.b	1

; Interrupt-Flags. Bei einem Interrupt wird eins dieser Flags gesetzt.
; Das bewirkt, daß nach dem nächsten Periodic der 6510-Task in die
; Routine "HandleInt" springt. Dort werden diese Flags ausgewertet und
; entsprechend verzweigt.
		CNOP	0,4
Interrupt			;Zusammenfassung als Langwort
IntIsRESET	ds.b	1	;RESET aufgetreten, 6510 beenden oder Pause
IntIsNMI	ds.b	1	;NMI aufgetreten
IntIsIRQ			;Zusammenfassung als Wort
IntIsVICIRQ	ds.b	1	;IRQ durch VIC aufgetreten
IntIsCIAIRQ	ds.b	1	;IRQ durch CIA-A aufgetreten

RESETIsEXIT	ds.b	1	;Zur Unterscheidung von RESET und EXIT
RESETIsPause	ds.b	1	;Zur Unterscheidung von RESET und Pause

NMIState	ds.b	1	;Aktueller Zustand der NMI-Leitung (für Flankentriggerung)

; Zwischenspeicher für Adc/Sbc im Dezimalmodus
TMPS		ds.b	1
TMPA		ds.b	1
TMPAL		ds.b	1

; Anzahl zur Verfügung stehender CPU-Zyklen bis zum nächsten Periodic
		CNOP	0,2
CyclesLeft	ds.w	1

; Speicherzeiger (außer bei TheChar stimmt bei allen das untere Wort
; mit der tatsächlichen C64-Adresse überein, also
;  TheRAM   : xxxx0000
;  TheBasic : xxxxa000
;  TheKernal: xxxxe000
;  TheColor : xxxxd800
		CNOP	0,4
TheRAM		ds.l	1	;Zeiger auf C64-RAM (64K)
TheBasic	ds.l	1	;Zeiger auf Basic-ROM
TheKernal	ds.l	1	;Zeiger auf Kernal-ROM
TheChar		ds.l	1	;Zeiger auf Char-ROM
TheColor	ds.l	1	;Zeiger auf Farb-RAM

; Zwischenspeicher für Register bei Periodic/ReadWord/ReadAdrInd
RegStore	ds.l	5

; Argumente für Requester
RequestStream	ds.l	16

; Registerinhalte für SAM, nur gültig innerhalb von Pause6510/Resume6510
		XDEF	_RA
_RA		ds.b	1
		XDEF	_RX
_RX		ds.b	1
		XDEF	_RY
_RY		ds.b	1
		XDEF	_RP
_RP		ds.b	1
		XDEF	_RPR
_RPR		ds.b	1
		XDEF	_RDDR
_RDDR		ds.b	1
		XDEF	_RPC
_RPC		ds.w	1
		XDEF	_RS
_RS		ds.w	1

		XDEF	_SAMMemConfig
_SAMMemConfig	ds.b	1	;CHAREN, LORAM, HIRAM

		END
