home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 10
/
aminetcdnumber101996.iso
/
Aminet
/
misc
/
emu
/
Frodo.lha
/
Frodo
/
src
/
6526SC.asm
< prev
next >
Wrap
Assembly Source File
|
1995-12-12
|
27KB
|
1,456 lines
*
* 6526SC.asm - Einzelzyklus-CIA-Emulation
*
* Copyright (C) 1994-1995 by Christian Bauer
*
*
* Anmerkungen:
* ------------
*
* Funktionsweise/Periodic:
* - Für jeden Zyklus wird vom 6510-Task die Routine Periodic6526
* aufgerufen, die die Timer herunterzählt, ggf. Interrupts auslöst
* und einen Zyklus der CPU ausführt
*
* Timer/Latches:
* - Die Bytefolge im Register-File ist gegenüber dem echten 6526 umgekehrt,
* das wird aber bei den WriteTo6526- und ReadFrom6526-Routinen wieder
* ausgeglichen
*
* TOD-Clocks:
* - Die TODs werden synchron mit dem VBlank gezählt. Es wird also ein
* 50Hz-Eingangssignal simuliert.
*
* Zyklenzähler:
* - Periodic6526 erhöht auch den einen Langwort-Zyklenzähler, der von der
* 6510- und 6569-Emulation benutzt wird
*
* Tastaturabfrage:
* - Das Feld KeyMatrix enthält für jede Taste entsprechend der C64-
* Tastaturmatrix ein Bit (0: Taste gedrückt, 1: Taste nicht gedrückt)
* - Bei Lesezugriffen aus CIA-A, Port B werden entsprechend der aktiven
* (ausgewählten) Zeilen der Tastatur die entsprechenden Bits aus der
* Tastaturmatrix zusammengestellt
* - Die Help-Taste löst einen NMI aus (Restore), F10 einen RESET
*
* Joystickabfrage:
* - Die Joysticks werden im VBlank abgefragt, wenn auch die TODs
* gezählt werden
*
* Lightpen:
* - Bei jedem Schreibzugriff auf PRB/DDRB von CIA-A wird geprüft, ob die
* Lightpen-Leitung (Bit 4) einen Übergang 1->0 macht. In diesem Fall
* wird der VIC informiert
*
* Inkompatibilitäten:
* - Die TOD-Clock sollte bei einem Lesezugriff nicht angehalten,
* sondern gelatcht werden
* - Das Starten eines Timers sollte drei Zyklen verzögert werden, das
* Stoppen zwei Zyklen
*
MACHINE 68020
XREF ShowPrefs ;Main.asm
XREF ResetC64
XREF _ciaaprb
XREF _ciaaddrb
XREF IntIsNMI ;6510SC.asm
NREF IntIsIRQ
NREF IntIsCIAIRQ
NREF FirstIRQCycle
XREF FirstNMICycle
XREF NMIState
XREF ChangedVA ;6569SC.asm
XREF TriggerLightpen
XREF CycleCounter
XREF IECIsOpen ;IEC.asm
XDEF Reset6526
XDEF _GetCIA1Dump
XDEF _GetCIA2Dump
XDEF ReadFrom6526A
XDEF ReadFrom6526B
XDEF WriteTo6526A
XDEF WriteTo6526B
XDEF Periodic6526
XDEF ChangedKeys
XDEF CountTODs
XDEF _KeyPressed
XDEF CIACycles ;Prefs
XDEF Joystick1On
XDEF Joystick2On
XDEF JoystickSwap
XDEF KeyboardYZ
NEAR a4,-2
SECTION "text",CODE
FAR
**
** Definitionen
**
Cycles = 1
; CIA-Register
PRA = 0
PRB = 1
DDRA = 2
DDRB = 3
TAHI = 4 ;Timer-Wert A
TALO = 5 ;Achtung: Umgekehrte Bytefolge!
TBHI = 6 ;Timer-Wert B
TBLO = 7
TOD10THS = 8
TODSEC = 9
TODMIN = 10
TODHR = 11
SDR = 12
ICR = 13 ;Interrupt-Data
CRA = 14
CRB = 15
; Zusätzliche Register
LTCHA = 16 ;Timer-Latch A
LTCHB = 18 ;Timer-Latch B
INTMASK = 20 ;Interrupt-Enable
TODHALT = 21 ;TOD zwecks Beschreiben/Auslesen gestoppt
ALM10THS = 22 ;Alarmzeit
ALMSEC = 23
ALMMIN = 24
ALMHR = 25
TODDIV = 26 ;TOD-Frequenzteiler
TACNTPHI2 = 27 ;Timer A läuft und zählt Phi2
TBCNTPHI2 = 28 ;Timer B läuft und zählt Phi2
TBCNTTA = 29 ;Timer B läuft und zählt Unterläufe von Timer A
PREVLP = 30 ;Voriger Zustand der Lightpen-Leitung (nur CIA-A)
**
** CIAs zurücksetzen
**
FAR
; CIA-A
Reset6526 lea Registers1,a0
clr.l (a0)
clr.l 4(a0)
clr.l 8(a0)
clr.l 12(a0)
move.w #-1,TAHI(a0) ;Timer auf -1
move.w #-1,TBHI(a0)
move.w #$0001,LTCHA(a0) ;Latches auf 1
move.w #$0001,LTCHB(a0)
clr.b INTMASK(a0) ;Interrupts abschalten
clr.b TODHALT(a0) ;TOD läuft
clr.l ALM10THS(a0) ;Alarmzeit auf 00:00:00.0
clr.w TACNTPHI2(a0) ;Beide Timer anhalten
move.b #$10,PREVLP(a0) ;Lightpen-Leitung ist High
move.b #$ff,Joystick1 ;Joystick inaktiv
move.b #$ff,Joystick2
move.b #$ff,Joystick2Key
; CIA-B
lea Registers2,a0
clr.l (a0)
clr.l 4(a0)
clr.l 8(a0)
clr.l 12(a0)
move.w #-1,TAHI(a0) ;Timer auf -1
move.w #-1,TBHI(a0)
move.w #$0001,LTCHA(a0) ;Latches auf 1
move.w #$0001,LTCHB(a0)
clr.b INTMASK(a0) ;Interrupts abschalten
clr.b TODHALT(a0) ;TOD läuft
clr.l ALM10THS(a0) ;Alarmzeit auf 00:00:00.0
clr.w TACNTPHI2(a0) ;Beide Timer anhalten
; Zyklenzähler zurücksetzen
clr.l CycleCounter
; Tastaturmatrix löschen
moveq #-1,d0
move.l d0,KeyMatrix
move.l d0,KeyMatrix+4
; VIC-Bank 0 einstellen
moveq #0,d0
bra ChangedVA
**
** CIA-Status in Datenstruktur schreiben
**
_GetCIA1Dump lea Registers1,a0
bra GetCIADump
_GetCIA2Dump lea Registers2,a0
GetCIADump move.l 4(sp),a1
move.l (a0),(a1)+
move.b TALO(a0),(a1)+ ;Wegen umgekehrter Bytefolge
move.b TAHI(a0),(a1)+
move.b TBLO(a0),(a1)+
move.b TBHI(a0),(a1)+
move.l TOD10THS(a0),(a1)+
move.l SDR(a0),(a1)+
move.b LTCHA+1(a0),(a1)+
move.b LTCHA(a0),(a1)+
move.b LTCHB+1(a0),(a1)+
move.b LTCHB(a0),(a1)+
move.l ALM10THS(a0),(a1)+
move.b INTMASK(a0),(a1)
rts
**
** Tastaturbelegung geändert, Y und Z sortieren
**
ChangedKeys tst.w KeyboardYZ
bne 1$
move.l #$00010004,KeyPatch1
move.l #$00030001,KeyPatch2
rts
1$ move.l #$00030001,KeyPatch1
move.l #$00010004,KeyPatch2
rts
**
** In ein CIA-A-Register schreiben
** d0.w: Registernummer ($00-$0f)
** d1.b: Byte
**
NEAR
WriteTo6526A lea Registers1,a0
move.l WriteTabA(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
WriteTabA dc.l WrNormal
dc.l WrAPRB
dc.l WrNormal
dc.l WrADDRB
dc.l WrTALO
dc.l WrTAHI
dc.l WrTBLO
dc.l WrTBHI
dc.l WrTOD10THS
dc.l WrTODSEC
dc.l WrTODMIN
dc.l WrTODHR
dc.l WrNormal
dc.l WrAICR
dc.l WrCRA
dc.l WrCRB
WrNormal move.b d1,(a0,d0.w)
rts
WrAPRB move.b d1,PRB(a0)
bra CheckLP
WrADDRB move.b d1,DDRB(a0)
CheckLP move.b DDRB(a0),d0 ;Lightpen-Leitung
not.b d0
or.b PRB(a0),d0
and.b #$10,d0
cmp.b PREVLP(a0),d0 ;Änderung?
beq 1$
move.b d0,PREVLP(a0) ;Ja, negative Flanke?
bne 1$
bra TriggerLightpen ;Ja, LP triggern
1$ rts
WrTALO move.b d1,LTCHA+1(a0)
rts
WrTAHI move.b d1,LTCHA(a0)
btst #0,CRA(a0) ;Timer A gestoppt?
bne 1$
move.w LTCHA(a0),TAHI(a0) ;Ja, Timer laden
1$ rts
WrTBLO move.b d1,LTCHB+1(a0)
rts
WrTBHI move.b d1,LTCHB(a0)
btst #0,CRB(a0) ;Timer B gestoppt?
bne 1$
move.w LTCHB(a0),TBHI(a0) ;Ja, Timer laden
1$ rts
WrTOD10THS and.b #$0f,d1
clr.b TODHALT(a0) ;TOD weiterlaufen lassen
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TOD10THS(a0)
rts
1$ move.b d1,ALM10THS(a0)
rts
WrTODSEC and.b #$7f,d1
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TODSEC(a0)
rts
1$ move.b d1,ALMSEC(a0)
rts
WrTODMIN and.b #$7f,d1
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TODMIN(a0)
rts
1$ move.b d1,ALMMIN(a0)
rts
WrTODHR and.b #$9f,d1
st.b TODHALT(a0) ;TOD anhalten
btst #7,CRB(a0) ;Alarm-Zeit schreiben?
bne 1$
move.b d1,TODHR(a0)
rts
1$ move.b d1,ALMHR(a0)
rts
WrAICR bclr #7,d1 ;S/C-Bit löschen
bne 1$ ;War es gesetzt?
not.b d1 ;Nein, Bits zum Löschen negieren
and.b d1,INTMASK(a0) ;Und Bits löschen
bra 2$
1$ or.b d1,INTMASK(a0) ;Bits setzen
2$
move.b ICR(a0),d0 ;Anstehende Interrupts erlaubt?
and.b INTMASK(a0),d0
and.b #$1f,d0
beq 3$
or.b #$80,ICR(a0) ;Ja, IRQ auslösen
tst.w IntIsIRQ
bne 4$
move.l CycleCounter,FirstIRQCycle
4$ st.b IntIsCIAIRQ
rts
3$ and.b #$7f,ICR(a0) ;Nein, IRQ zurücknehmen
clr.b IntIsCIAIRQ
rts
WrCRA bclr #4,d1 ;Force load?
beq 1$
move.w LTCHA(a0),TAHI(a0) ;Ja, Timer laden
1$ move.b d1,CRA(a0)
and.b #$21,d1 ;Läuft der Timer und zählt er Phi2?
cmp.b #$01,d1
seq.b TACNTPHI2(a0) ;Ja, Flag setzen
rts
WrCRB bclr #4,d1 ;Force load?
beq 1$
move.w LTCHB(a0),TBHI(a0) ;Ja, Timer laden
1$ move.b d1,CRB(a0)
and.b #$61,d1 ;Läuft der Timer und zählt er Phi2?
cmp.b #$01,d1
seq.b TBCNTPHI2(a0) ;Ja, Flag setzen
cmp.b #$41,d1 ;Läuft er und zählt Unterläuft von Timer A?
seq.b TBCNTTA(a0) ;Ja, Flag setzen
rts
**
** In ein CIA-B-Register schreiben
** d0.w: Registernummer ($00-$0f)
** d1.b: Byte
**
WriteTo6526B lea Registers2,a0
move.l WriteTabB(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
WriteTabB dc.l WrBPRA
dc.l WrNormal
dc.l WrBDDRA
dc.l WrNormal
dc.l WrTALO
dc.l WrTAHI
dc.l WrTBLO
dc.l WrTBHI
dc.l WrTOD10THS
dc.l WrTODSEC
dc.l WrTODMIN
dc.l WrTODHR
dc.l WrNormal
dc.l WrBICR
dc.l WrCRA
dc.l WrCRB
WrBPRA move.b d1,PRA(a0) ;Floppy/VA
tst.b IECIsOpen ;Wenn IEC aktiv ist, Port setzen
beq WrBNewVA
move.b d1,_ciaaprb
bra WrBNewVA
WrBDDRA move.b d1,DDRA(a0) ;Floppy/VA
tst.b IECIsOpen ;Wenn IEC aktiv ist, DDR setzen
beq WrBNewVA
move.b d1,_ciaaddrb
WrBNewVA move.b DDRA(a0),d0 ;VA extrahieren
not.b d0
or.b PRA(a0),d0
not.b d0
and.b #$03,d0
bra ChangedVA ;Und dem VIC mitteilen
WrBICR bclr #7,d1 ;S/C-Bit löschen
bne 1$ ;War es gesetzt?
not.b d1 ;Nein, Bits zum Löschen negieren
and.b d1,INTMASK(a0) ;Und Bits löschen
bra 2$
1$ or.b d1,INTMASK(a0) ;Bits setzen
2$
move.b ICR(a0),d0 ;Anstehende Interrupts erlaubt?
and.b INTMASK(a0),d0
and.b #$1f,d0
beq 3$
or.b #$80,ICR(a0) ;Ja, NMI auslösen
tst.b NMIState
bne 4$
move.l CycleCounter,FirstNMICycle
st.b NMIState
st.b IntIsNMI
4$ rts
3$ and.b #$7f,ICR(a0) ;Nein, NMI zurücknehmen
clr.b NMIState
rts
**
** Aus einem CIA-A-Register lesen
** d0.w: Registernummer ($00-$0f)
** Rückgabe: d0.b: Byte
**
ReadFrom6526A lea Registers1,a0
move.l ReadTabA(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
ReadTabA dc.l RdAPRA
dc.l RdAPRB
dc.l RdNormal
dc.l RdNormal
dc.l RdTALO
dc.l RdTAHI
dc.l RdTBLO
dc.l RdTBHI
dc.l RdTOD10THS
dc.l RdNormal
dc.l RdNormal
dc.l RdTODHR
dc.l RdNormal
dc.l RdAICR
dc.l RdNormal
dc.l RdNormal
RdNormal move.b (a0,d0.w),d0
rts
RdAPRA move.b DDRA(a0),d0
not.b d0
or.b PRA(a0),d0
and.b Joystick2,d0
rts
RdAPRB lea KeyMatrix,a1
move.b PRA(a0),d1 ;Tastaturabfrage
move.b #$ff,d0 ;Alle aktiven Reihen dazuANDen
lsr.b #1,d1
bcs 1$
and.b (a1),d0
1$ lsr.b #1,d1
bcs 2$
and.b 1(a1),d0
2$ lsr.b #1,d1
bcs 3$
and.b 2(a1),d0
3$ lsr.b #1,d1
bcs 4$
and.b 3(a1),d0
4$ lsr.b #1,d1
bcs 5$
and.b 4(a1),d0
5$ lsr.b #1,d1
bcs 6$
and.b 5(a1),d0
6$ lsr.b #1,d1
bcs 7$
and.b 6(a1),d0
7$ lsr.b #1,d1
bcs 8$
and.b 7(a1),d0
8$ and.b Joystick1,d0
move.b DDRB(a0),d1
not.b d1
or.b PRB(a0),d1
and.b d1,d0
rts
RdTALO move.b TALO(a0),d0 ;Weil die Timer im Registerfile
rts ;als big-endian gespeichert sind
RdTAHI move.b TAHI(a0),d0
rts
RdTBLO move.b TBLO(a0),d0
rts
RdTBHI move.b TBHI(a0),d0
rts
RdTOD10THS move.b TOD10THS(a0),d0
clr.b TODHALT(a0) ;TOD weiterlaufen lassen
rts
RdTODHR st.b TODHALT(a0) ;TOD anhalten
move.b TODHR(a0),d0
rts
RdAICR move.b ICR(a0),d0 ;ICR beim Lesen löschen
clr.b ICR(a0)
clr.b IntIsCIAIRQ ;IRQ zurücknehmen
rts
**
** Aus einem CIA-B-Register lesen
** d0.w: Registernummer ($00-$0f)
** Rückgabe: d0.b: Byte
**
ReadFrom6526B lea Registers2,a0
move.l ReadTabB(pc,d0.w*4),a1
jmp (a1)
CNOP 0,4
ReadTabB dc.l RdBPRA
dc.l RdBPRB
dc.l RdNormal
dc.l RdNormal
dc.l RdTALO
dc.l RdTAHI
dc.l RdTBLO
dc.l RdTBHI
dc.l RdTOD10THS
dc.l RdNormal
dc.l RdNormal
dc.l RdTODHR
dc.l RdNormal
dc.l RdBICR
dc.l RdNormal
dc.l RdNormal
RdBPRA move.b DDRA(a0),d0 ;Floppy/VA
not.b d0
or.b PRA(a0),d0
tst.b IECIsOpen ;Wenn IEC aktiv ist, davon lesen
beq 1$
and.b #$03,d0
move.b _ciaaprb,d1
and.b #$fc,d1
or.b d1,d0
1$ rts
RdBPRB move.b DDRB(a0),d0 ;Userport
not.b d0 ;Eingabebits immer 1
or.b PRB(a0),d0
rts
RdBICR move.b ICR(a0),d0 ;ICR beim Lesen löschen
clr.b ICR(a0)
clr.b NMIState ;NMI zurücknehmen
rts
**
** Wird jede Rasterzeile einmal aufgerufen
**
*
* CIA-A
* d1: ICR
* d2: INTMASK
*
Periodic6526 lea Registers1,a0
move.b ICR(a0),d1
move.b INTMASK(a0),d2
*
* Timer A
*
tst.b TACNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaATADone
subq.w #Cycles,TAHI(a0) ;Ja, herabzählen
bcc CiaATADone ;Unterlauf?
or.b #$01,d1 ;Ja, IRQ-Bit setzen
btst #0,d2 ;IRQ freigegeben?
beq CiaATANoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
tst.w IntIsIRQ ;IRQ schon ausgelöst?
bne 1$
move.l CycleCounter,FirstIRQCycle ;Nein, Zyklus merken
1$ st.b IntIsCIAIRQ ; und IRQ auslösen
CiaATANoIRQ move.w LTCHA(a0),TAHI(a0) ;Zähler neu laden
btst #3,CRA(a0) ;One-Shot?
beq 1$
and.b #$fe,CRA(a0) ;Ja, Zähler stoppen
clr.b TACNTPHI2(a0)
1$ tst.b TBCNTTA(a0) ;Läuft Timer B und zählt er
beq CiaATADone ; Unterläufe von Timer A?
subq.w #1,TBHI(a0) ;Ja, Timer B runterzählen
bcs CiaATBUnderflow ;Untergelaufen?
CiaATADone
*
* Timer B
*
tst.b TBCNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaATBDone
subq.w #Cycles,TBHI(a0) ;Ja, herabzählen
bcc CiaATBDone ;Unterlauf?
CiaATBUnderflow or.b #$02,d1 ;Ja, IRQ-Bit setzen
btst #1,d2 ;IRQ freigegeben?
beq CiaATBNoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
tst.w IntIsIRQ ;IRQ schon ausgelöst?
bne 1$
move.l CycleCounter,FirstIRQCycle ;Nein, Zyklus merken
1$ st.b IntIsCIAIRQ ; und IRQ auslösen
CiaATBNoIRQ move.w LTCHB(a0),TBHI(a0) ;Zähler neu laden
btst #3,CRB(a0) ;One-Shot?
beq CiaATBDone
and.b #$fe,CRB(a0) ;Ja, Zähler stoppen
clr.b TBCNTPHI2(a0)
clr.b TBCNTTA(a0)
CiaATBDone
*
* ICR zurückschreiben
*
move.b d1,ICR(a0)
*
* CIA-B
* d1: ICR
* d2: INTMASK
*
lea Registers2,a0
move.b ICR(a0),d1
move.b INTMASK(a0),d2
*
* Timer A
*
tst.b TACNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaBTADone
subq.w #Cycles,TAHI(a0) ;Ja, herabzählen
bcc CiaBTADone ;Unterlauf?
or.b #$01,d1 ;Ja, IRQ-Bit setzen
btst #0,d2 ;IRQ freigegeben?
beq CiaBTANoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
tst.b NMIState ;NMI schon ausgelöst?
bne 1$
move.l CycleCounter,FirstNMICycle ;Nein, Zyklus merken
st.b NMIState ;und NMI auslösen
st.b IntIsNMI
1$
CiaBTANoIRQ move.w LTCHA(a0),TAHI(a0) ;Zähler neu laden
btst #3,CRA(a0) ;One-Shot?
beq 1$
and.b #$fe,CRA(a0) ;Ja, Zähler stoppen
clr.b TACNTPHI2(a0)
1$ tst.b TBCNTTA(a0) ;Läuft Timer B und zählt er
beq CiaBTADone ; Unterläufe von Timer A?
subq.w #1,TBHI(a0) ;Ja, Timer B runterzählen
bcs CiaBTBUnderflow ;Untergelaufen?
CiaBTADone
*
* Timer B
*
tst.b TBCNTPHI2(a0) ;Wird Phi2 gezählt?
beq CiaBTBDone
subq.w #Cycles,TBHI(a0) ;Ja, herabzählen
bcc CiaBTBDone ;Unterlauf?
CiaBTBUnderflow or.b #$02,d1 ;Ja, IRQ-Bit setzen
btst #1,d2 ;IRQ freigegeben?
beq CiaBTBNoIRQ
or.b #$80,d1 ;Ja, IR-Bit setzen
tst.b NMIState ;NMI schon ausgelöst?
bne 1$
move.l CycleCounter,FirstNMICycle
st.b NMIState ;und NMI auslösen
st.b IntIsNMI
1$
CiaBTBNoIRQ move.w LTCHB(a0),TBHI(a0) ;Zähler neu laden
btst #3,CRB(a0) ;One-Shot?
beq CiaBTBDone
and.b #$fe,CRB(a0) ;Ja, Zähler stoppen
clr.b TBCNTPHI2(a0)
clr.b TBCNTTA(a0)
CiaBTBDone
*
* ICR zurückschreiben
*
move.b d1,ICR(a0)
*
* 6510-Zyklus ausführen und Zyklenzähler erhöhen
*
jsr (a6)
addq.l #1,CycleCounter
rts
**
** TODs zählen
**
*
* CIA-A
*
CountTODs lea Registers1,a0
subq.b #1,TODDIV(a0) ;Frequenzteiler herabzählen
bpl CiaATODNop
btst #7,CRA(a0) ;Untergelaufen,
beq CiaATOD60Hz ; je nach 50/60Hz-Flag neu laden
move.b #4,TODDIV(a0)
bra CiaATODLoaded
CiaATOD60Hz move.b #5,TODDIV(a0)
CiaATODLoaded move #0,ccr ;X löschen
move.b #1,d0 ;1/10 Sekunden erhöhen
move.b TOD10THS(a0),d1
abcd d0,d1
move.b d1,TOD10THS(a0)
cmp.b #$10,d1 ;Über 10?
blo CiaATODDone
clr.b TOD10THS(a0) ;Ja, 1/10 Sekunden auf Null setzen
move #0,ccr ;und Sekunden erhöhen
move.b #1,d0
move.b TODSEC(a0),d1
abcd d0,d1
move.b d1,TODSEC(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaATODDone
clr.b TODSEC(a0) ;Ja, Sekunden auf Null setzen
move #0,ccr ;und Minuten erhöhen
move.b #1,d0
move.b TODMIN(a0),d1
abcd d0,d1
move.b d1,TODMIN(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaATODDone
clr.b TODMIN(a0) ;Ja, Minuten auf Null setzen
move #0,ccr ;und Stunden erhöhen
move.b #1,d0
move.b TODHR(a0),d1
and.b #$1f,d1 ;AM/PM ausmaskieren
abcd d0,d1
and.b #$80,TODHR(a0) ;Stunden schreiben, AM/PM lassen
or.b d1,TODHR(a0)
cmp.b #$12,d1 ;Über 12?
blo CiaATODDone
and.b #$1f,TODHR(a0) ;Ja, Stunden auf Null setzen
eor.b #$80,TODHR(a0) ;und AM/PM umdrehen
CiaATODDone move.l TOD10THS(a0),d0 ;Alarmzeit erreicht?
cmp.l ALM10THS(a0),d0
bne CiaATODNop
move.b ICR(a0),d0 ;Ja, IRQ-Bit setzen
or.b #$04,d0
btst #2,INTMASK(a0) ;IRQ freigegeben?
beq CiaATODNoIRQ
or.b #$80,d0 ;Ja, IR-Bit setzen
tst.w IntIsIRQ ;IRQ schon ausgelöst?
bne 1$
move.l CycleCounter,FirstIRQCycle ;Nein, Zyklus merken
1$ st.b IntIsCIAIRQ ;und IRQ auslösen
CiaATODNoIRQ move.b d0,ICR(a0)
CiaATODNop
*
* CIA-B
*
lea Registers2,a0
subq.b #1,TODDIV(a0) ;Frequenzteiler herabzählen
bpl CiaBTODNop
btst #7,CRA(a0) ;Untergelaufen,
beq CiaBTOD60Hz ; je nach 50/60Hz-Flag neu laden
move.b #4,TODDIV(a0)
bra CiaBTODLoaded
CiaBTOD60Hz move.b #5,TODDIV(a0)
CiaBTODLoaded move #0,ccr ;X löschen
move.b #1,d0 ;1/10 Sekunden erhöhen
move.b TOD10THS(a0),d1
abcd d0,d1
move.b d1,TOD10THS(a0)
cmp.b #$10,d1 ;Über 10?
blo CiaBTODDone
clr.b TOD10THS(a0) ;Ja, 1/10 Sekunden auf Null setzen
move #0,ccr ;und Sekunden erhöhen
move.b #1,d0
move.b TODSEC(a0),d1
abcd d0,d1
move.b d1,TODSEC(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaBTODDone
clr.b TODSEC(a0) ;Ja, Sekunden auf Null setzen
move #0,ccr ;und Minuten erhöhen
move.b #1,d0
move.b TODMIN(a0),d1
abcd d0,d1
move.b d1,TODMIN(a0)
cmp.b #$60,d1 ;Über 60?
blo CiaBTODDone
clr.b TODMIN(a0) ;Ja, Minuten auf Null setzen
move #0,ccr ;und Stunden erhöhen
move.b #1,d0
move.b TODHR(a0),d1
and.b #$1f,d1 ;AM/PM ausmaskieren
abcd d0,d1
and.b #$80,TODHR(a0) ;Stunden schreiben, AM/PM lassen
or.b d1,TODHR(a0)
cmp.b #$12,d1 ;Über 12?
blo CiaBTODDone
and.b #$1f,TODHR(a0) ;Ja, Stunden auf Null setzen
eor.b #$80,TODHR(a0) ;und AM/PM umdrehen
CiaBTODDone move.l TOD10THS(a0),d0 ;Alarmzeit erreicht?
cmp.l ALM10THS(a0),d0
bne CiaBTODNop
move.b ICR(a0),d0 ;Ja, IRQ-Bit setzen
or.b #$04,d0
btst #2,INTMASK(a0) ;IRQ freigegeben?
beq CiaBTODNoIRQ
or.b #$80,d0 ;Ja, IR-Bit setzen
tst.b NMIState ;NMI schon ausgelöst?
bne 1$
move.l CycleCounter,FirstNMICycle ;Nein, Zyklus merken
st.b NMIState ;und NMI auslösen
st.b IntIsNMI
1$
CiaBTODNoIRQ move.b d0,ICR(a0)
CiaBTODNop
*
* Joystickabfrage
*
lea Registers1,a0
; Port 1
move.b #$ff,d2 ;Vorgabe: Joystick inaktiv
tst.w Joystick1On(pc)
beq 15$
btst #6,$bfe001 ;Feuerknopf
bne 11$
bclr #4,d2
11$ move.w $dff00a,d0
btst #1,d0 ;Rechts
beq 12$
bclr #3,d2
12$ btst #9,d0 ;Links
beq 13$
bclr #2,d2
13$ move.w d0,d1
add.w d0,d0
eor.w d1,d0
btst #1,d0 ;Runter
beq 14$
bclr #1,d2
14$ btst #9,d0 ;Hoch
beq 15$
bclr #0,d2
15$ move.b d2,Joystick1
; Port 2
move.b Joystick2Key,d2 ;Vorgabe: Zehnerblock-Emulation
tst.w Joystick2On(pc)
beq 25$
btst #7,$bfe001 ;Feuerknopf
bne 21$
bclr #4,d2
21$ move.w $dff00c,d0
btst #1,d0 ;Rechts
beq 22$
bclr #3,d2
22$ btst #9,d0 ;Links
beq 23$
bclr #2,d2
23$ move.w d0,d1
add.w d0,d0
eor.w d1,d0
btst #1,d0 ;Runter
beq 24$
bclr #1,d2
24$ btst #9,d0 ;Hoch
beq 25$
bclr #0,d2
25$ move.b d2,Joystick2
; Joysticks vertauschen?
tst.w JoystickSwap(pc)
beq 30$
move.b Joystick1,d0
move.b Joystick2,Joystick1
move.b d0,Joystick2
30$ rts
**
** Taste wurde gedrückt
**
FAR
_KeyPressed move.l 4(sp),d0
lea KeyMatrix,a0
bclr #7,d0 ;KeyUp/KeyDown
bne KeyUp
cmp.b #$40,d0
bhs KeyDownSpecial
and.w #$003f,d0 ;$00..$3f
cmp.b #$0f,d0 ;Joystick-Emulation
beq KeyDownJoyFire
cmp.b #$1d,d0
beq KeyDownJoyDL
cmp.b #$1e,d0
beq KeyDownJoyDown
cmp.b #$1f,d0
beq KeyDownJoyDR
cmp.b #$2d,d0
beq KeyDownJoyLeft
cmp.b #$2e,d0
beq KeyDownJoyFire
cmp.b #$2f,d0
beq KeyDownJoyRight
cmp.b #$3d,d0
beq KeyDownJoyUL
cmp.b #$3e,d0
beq KeyDownJoyUp
cmp.b #$3f,d0
beq KeyDownJoyUR
movem.w KeyTable(pc,d0.w*4),d0/d1
bclr d1,(a0,d0.w)
rts
KeyUp cmp.b #$40,d0
bhs KeyUpSpecial
and.w #$003f,d0 ;$00..$3f
cmp.b #$0f,d0 ;Joystick-Emulation
beq KeyUpJoyFire
cmp.b #$1d,d0
beq KeyUpJoyDL
cmp.b #$1e,d0
beq KeyUpJoyDown
cmp.b #$1f,d0
beq KeyUpJoyDR
cmp.b #$2d,d0
beq KeyUpJoyLeft
cmp.b #$2e,d0
beq KeyUpJoyFire
cmp.b #$2f,d0
beq KeyUpJoyRight
cmp.b #$3d,d0
beq KeyUpJoyUL
cmp.b #$3e,d0
beq KeyUpJoyUp
cmp.b #$3f,d0
beq KeyUpJoyUR
movem.w KeyTable(pc,d0.w*4),d0/d1
bset d1,(a0,d0.w)
KeyNOP rts
KeyDownSpecial sub.b #$40,d0
cmp.b #$20,d0
bhs KeyDownMod
and.w #$1f,d0 ;$40..$5f
jmp ([KeyDownSpecTab,pc,d0.w*4])
KeyDownMod sub.b #$20,d0
cmp.b #$08,d0
bhs KeyNOP
and.w #$07,d0 ;$60..$67
cmp.w #$07,d0 ;Amiga rechts ignorieren
beq 1$
movem.w KeyModTable(pc,d0.w*4),d0/d1
bclr d1,(a0,d0.w)
1$ rts
KeyUpSpecial sub.b #$40,d0
cmp.b #$20,d0
bhs KeyUpMod
and.w #$1f,d0 ;$40..$5f
jmp ([KeyUpSpecTab,pc,d0.w*4])
KeyUpMod sub.b #$20,d0
cmp.b #$08,d0
bhs KeyNOP
and.w #$07,d0 ;$60..$67
cmp.w #$07,d0 ;Amiga rechts ignorieren
beq 1$
movem.w KeyModTable(pc,d0.w*4),d0/d1
bset d1,(a0,d0.w)
1$ rts
KeySpaceD bclr #4,7(a0)
rts
KeySpaceU bset #4,7(a0)
rts
KeyBackD bclr #0,(a0)
rts
KeyBackU bset #0,(a0)
rts
KeyEnterD
KeyReturnD bclr #1,(a0)
rts
KeyEnterU
KeyReturnU bset #1,(a0)
rts
KeyEscD bclr #7,7(a0)
rts
KeyEscU bset #7,7(a0)
rts
KeyDeleteD bclr #3,6(a0)
rts
KeyDeleteU bset #3,6(a0)
rts
KeyUpD bclr #4,6(a0)
bclr #7,(a0)
rts
KeyUpU bset #4,6(a0)
bset #7,(a0)
rts
KeyDownD bclr #7,(a0)
rts
KeyDownU bset #7,(a0)
rts
KeyRightD bclr #2,(a0)
rts
KeyRightU bset #2,(a0)
rts
KeyLeftD bclr #4,6(a0)
bclr #2,(a0)
rts
KeyLeftU bset #4,6(a0)
bset #2,(a0)
rts
KeyF1D bclr #4,(a0)
rts
KeyF1U bset #4,(a0)
rts
KeyF3D bclr #5,(a0)
rts
KeyF3U bset #5,(a0)
rts
KeyF5D bclr #6,(a0)
rts
KeyF5U bset #6,(a0)
rts
KeyF7D bclr #3,(a0)
rts
KeyF7U bset #3,(a0)
rts
KeyF2D bclr #4,6(a0)
bclr #4,(a0)
rts
KeyF2U bset #4,6(a0)
bset #4,(a0)
rts
KeyF4D bclr #4,6(a0)
bclr #5,(a0)
rts
KeyF4U bset #4,6(a0)
bset #5,(a0)
rts
KeyF6D bclr #4,6(a0)
bclr #6,(a0)
rts
KeyF6U bset #4,6(a0)
bset #6,(a0)
rts
KeyF8D bclr #4,6(a0)
bclr #3,(a0)
rts
KeyF8U bset #4,6(a0)
bset #3,(a0)
rts
KeyF10D jmp ResetC64
KeyNKPlusD bclr #0,5(a0) ;+
rts
KeyNKPlusU bset #0,5(a0)
rts
KeyNKMinusD bclr #3,5(a0) ;-
rts
KeyNKMinusU bset #3,5(a0)
rts
KeyNKAsterD tst.w KeyboardYZ
bne 1$
bclr #1,6(a0) ;*
rts
1$ bclr #5,6(a0) ;=
rts
KeyNKAsterU tst.w KeyboardYZ
bne 1$
bset #1,6(a0)
rts
1$ bset #5,6(a0)
rts
KeyNKSlashD tst.w KeyboardYZ
bne 1$
bclr #7,6(a0) ;/
rts
1$ bclr #6,6(a0) ;^
rts
KeyNKSlashU tst.w KeyboardYZ
bne 1$
bset #7,6(a0)
rts
1$ bset #6,6(a0)
rts
KeyNKLeftParD bclr #4,6(a0) ;[
bclr #5,5(a0)
rts
KeyNKLeftParU bset #4,6(a0)
bset #5,5(a0)
rts
KeyNKRightParD bclr #4,6(a0) ;]
bclr #2,6(a0)
rts
KeyNKRightParU bset #4,6(a0)
bset #2,6(a0)
rts
KeyHelpD tst.b NMIState ;NMI schon ausgelöst?
bne 1$
move.l CycleCounter,FirstNMICycle ;Nein, Zyklus merken
st.b IntIsNMI ; und NMI auslösen
1$ rts
; Joystick-Emulation
KeyDownJoyUp bclr #0,Joystick2Key
rts
KeyDownJoyDown bclr #1,Joystick2Key
rts
KeyDownJoyLeft bclr #2,Joystick2Key
rts
KeyDownJoyRight bclr #3,Joystick2Key
rts
KeyDownJoyUL bclr #0,Joystick2Key
bclr #2,Joystick2Key
rts
KeyDownJoyUR bclr #0,Joystick2Key
bclr #3,Joystick2Key
rts
KeyDownJoyDL bclr #1,Joystick2Key
bclr #2,Joystick2Key
rts
KeyDownJoyDR bclr #1,Joystick2Key
bclr #3,Joystick2Key
rts
KeyDownJoyFire bclr #4,Joystick2Key
rts
KeyUpJoyUp bset #0,Joystick2Key
rts
KeyUpJoyDown bset #1,Joystick2Key
rts
KeyUpJoyLeft bset #2,Joystick2Key
rts
KeyUpJoyRight bset #3,Joystick2Key
rts
KeyUpJoyUL bset #0,Joystick2Key
bset #2,Joystick2Key
rts
KeyUpJoyUR bset #0,Joystick2Key
bset #3,Joystick2Key
rts
KeyUpJoyDL bset #1,Joystick2Key
bset #2,Joystick2Key
rts
KeyUpJoyDR bset #1,Joystick2Key
bset #3,Joystick2Key
rts
KeyUpJoyFire bset #4,Joystick2Key
rts
**
** Datenbereich
**
CNOP 0,4
Registers1 ds.b 32 ;CIA-A-Register
Registers2 ds.b 32 ;CIA-B-Register
; Prefs
CIACycles dc.w 0 ;Unbenutzt
Joystick1On dc.w 0 ;Joystick an Port 1 wird abgefragt
Joystick2On dc.w 0 ;Joystick an Port 2 wird abgefragt
JoystickSwap dc.w 0 ;Joysticks vertauschen
KeyboardYZ dc.w 0 ;Amerikanische Tastaturbelegung
Joystick1 dc.b 0 ;Joystick 1 AND-Wert
Joystick2 dc.b 0 ;Joystick 2 AND-Wert
Joystick2Key dc.b 0 ;Joystick 2 AND-Wert für Emulation über Zehnerblock
; Tastaturübersetzungstabelle:
; Für jeden Amiga-RawKey Spalte und Zeile in der KeyMatrix
CNOP 0,4
KeyTable dc.w 7,1 ;` -> <-
dc.w 7,0 ;1
dc.w 7,3 ;2
dc.w 1,0 ;3
dc.w 1,3 ;4
dc.w 2,0 ;5
dc.w 2,3 ;6
dc.w 3,0 ;7
dc.w 3,3 ;8
dc.w 4,0 ;9
dc.w 4,3 ;0
dc.w 5,0 ;ß -> +
dc.w 5,3 ;´ -> -
dc.w 6,0 ;\ -> £
dc.w 0,0
dc.w 4,3 ;NP 0
dc.w 7,6 ;Q
dc.w 1,1 ;W
dc.w 1,6 ;E
dc.w 2,1 ;R
dc.w 2,6 ;T
KeyPatch1 dc.w 1,4 ;Y -> Z
dc.w 3,6 ;U
dc.w 4,1 ;I
dc.w 4,6 ;O
dc.w 5,1 ;P
dc.w 5,6 ;ü -> @
dc.w 6,1 ;+ -> *
dc.w 0,0
dc.w 7,0 ;NP 1
dc.w 7,3 ;NP 2
dc.w 1,0 ;NP 3
dc.w 1,2 ;A
dc.w 1,5 ;S
dc.w 2,2 ;D
dc.w 2,5 ;F
dc.w 3,2 ;G
dc.w 3,5 ;H
dc.w 4,2 ;J
dc.w 4,5 ;K
dc.w 5,2 ;L
dc.w 5,5 ;ö -> :
dc.w 6,2 ;ä -> ;
dc.w 6,5 ;# -> =
dc.w 0,0
dc.w 1,3 ;NP 4
dc.w 2,0 ;NP 5
dc.w 2,3 ;NP 6
dc.w 6,6 ;< -> ^
KeyPatch2 dc.w 3,1 ;Z -> Y
dc.w 2,7 ;X
dc.w 2,4 ;C
dc.w 3,7 ;V
dc.w 3,4 ;B
dc.w 4,7 ;N
dc.w 4,4 ;M
dc.w 5,7 ;,
dc.w 5,4 ;.
dc.w 6,7 ;- -> /
dc.w 0,0
dc.w 5,4 ;NP .
dc.w 3,0 ;NP 7
dc.w 3,3 ;NP 8
dc.w 4,0 ;NP 9
KeyDownSpecTab dc.l KeySpaceD
dc.l KeyBackD
dc.l KeyNOP
dc.l KeyEnterD
dc.l KeyReturnD
dc.l KeyEscD
dc.l KeyDeleteD
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNKMinusD
dc.l KeyNOP
dc.l KeyUpD
dc.l KeyDownD
dc.l KeyRightD
dc.l KeyLeftD
dc.l KeyF1D
dc.l KeyF2D
dc.l KeyF3D
dc.l KeyF4D
dc.l KeyF5D
dc.l KeyF6D
dc.l KeyF7D
dc.l KeyF8D
dc.l KeyNOP
dc.l KeyF10D
dc.l KeyNKLeftParD
dc.l KeyNKRightParD
dc.l KeyNKSlashD
dc.l KeyNKAsterD
dc.l KeyNKPlusD
dc.l KeyHelpD
KeyUpSpecTab dc.l KeySpaceU
dc.l KeyBackU
dc.l KeyNOP
dc.l KeyEnterU
dc.l KeyReturnU
dc.l KeyEscU
dc.l KeyDeleteU
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNKMinusU
dc.l KeyNOP
dc.l KeyUpU
dc.l KeyDownU
dc.l KeyRightU
dc.l KeyLeftU
dc.l KeyF1U
dc.l KeyF2U
dc.l KeyF3U
dc.l KeyF4U
dc.l KeyF5U
dc.l KeyF6U
dc.l KeyF7U
dc.l KeyF8U
dc.l KeyNOP
dc.l KeyNOP
dc.l KeyNKLeftParU
dc.l KeyNKRightParU
dc.l KeyNKSlashU
dc.l KeyNKAsterU
dc.l KeyNKPlusU
dc.l KeyNOP
KeyModTable dc.w 1,7 ;Shift left
dc.w 6,4 ;Shift right
dc.w 1,7 ;Caps lock -> Shift left
dc.w 7,2 ;Control
dc.w 7,5 ;Alt left -> C=
dc.w 7,5 ;Alt right -> C=
dc.w 7,5 ;Amiga left -> C=
dc.w 0,0 ;Amiga right
; Bit 7 6 5 4 3 2 1 0
; 0 CUD F5 F3 F1 F7 CLR RET DEL
; 1 SHL E S Z 4 A W 3
; 2 X T F C 6 D R 5
; 3 V U H B 8 G Y 7
; 4 N O K M 0 J I 9
; 5 , @ : . - L P +
; 6 / ^ = SHR HOM ; * £
; 7 R/S Q C= SPC 2 CTL <- 1
KeyMatrix ds.b 8 ;C64-Tastaturmatrix pro Taste ein Bit
;0: Taste gedrückt
END