            SECTION         text,CODE


            XREF            _VBL
            XREF            _EtatLigneClav
            XREF            _PlaySound


_ReadPPI:   LSR.W           #8,D0
            AND.W           #3,D0
            BNE.S           RdPortB
            MOVE.B          _portA,D0
            AND.B            MaskPortA,D0
            RTS

RdPortB:    SUBQ.B          #1,D0
            BNE.S           RdPortC
            MOVE.B          _VBL,D0
            OR.B            _Constructeur,D0
            OR.B            #$50,D0             ; 50Hz + imp. busy
            AND.B           MaskPortB,D0
            RTS

RdPortC:    SUBQ.B          #1,D0
            BNE.S           FinRd
            MOVE.B          ModePSG,D0
            LSL.B           #6,D0
            OR.B            _ligneClav,D0
            AND.B           MaskPortC,D0
            RTS

FinRd:      MOVE.B          #$FF,D0
            RTS


_WritePPI:  LSR.W           #8,D0
            LEA             _TabRegsPSG,A0
            AND.W           #3,D0
            BNE.S           WrPortB
            ;
            ; Vérifie si autorisation d'écrire dans port A
            ;
            MOVE.B          MaskPortA,D0
            NOT.B           D0
            BEQ.W           FinWr
            MOVE.B          D1,_portA
            MOVE.B          ModePSG,D1
            SUBQ.B          #1,D1
            BNE.S           PsgMode2
            RTS

WrPortB:    SUBQ.B          #1,D0
            BNE.S           WrPortC
            ;
            ; Interdit d'écrire sur le port B.
            ;
            RTS

WrPortC:    SUBQ.B          #1,D0
            BNE.W           WrPortCTRL
            
            ;
            ; Vérifie si autorisation d'écrire dans port C
            ;
            MOVE.B          MaskPortC,D0
            NOT.B           D0
            BEQ.S           FinWr

            ;
            ; Vérifie autorisation écrire partie faible port C
            ;
            BTST            #0,D0
            BEQ.S           WrPortC_2

            MOVE.B          D1,D0
            AND.W           #$0F,D0
            MOVE.B          D0,_ligneClav

WrPortC_2:  LSR.B           #6,D1
            MOVE.B          D1,ModePSG
            SUBQ.B          #1,D1
            BNE.S           PsgMode2
            MOVE.B          numReg,D0
            CMP.B           #14,D0
            BNE.S           FinPsgMode1
            LEA             _EtatLigneClav,A0
            MOVE.B          _ligneClav,D0
FinPsgMode1:
            MOVE.B          0(A0,D0.W),_portA
            RTS

PsgMode2:   SUBQ.B          #1,D1
            BNE.S           PsgMode3
            TST.B           _IsSound
            BEQ.S           FinPsgMode2
            MOVE.B          numReg,D0
            MOVE.B          _portA,0(A0,D0.W)
            MOVEM.L         D0-D1/A1,-(A7)
            BSR.W           _PlaySound
            MOVEM.L         (A7)+,D0-D1/A1
FinPsgMode2:
            RTS

PsgMode3:   SUBQ.B          #1,D1
            BNE.S           FinWr
            MOVE.B          _portA,numReg

FinWr:      RTS


WrPortCTRL: BTST            #7,D1
            BEQ.S           WrBitPortC
            AND.W           #$1F,D1
            LEA             TabMask,A0
            MOVE.W          D1,D0
            ADD.W           D1,D1
            ADD.W           D1,D0
            MOVE.B          0(A0,D0.W),MaskPortA
            MOVE.B          1(A0,D0.W),MaskPortB
            MOVE.B          2(A0,D0.W),MaskPortC
            RTS
          
WrBitPortC:
            RTS


            SECTION         data,DATA


_portA:     DC.L            0

MaskPortA:  DC.L            0
MaskPortB:  DC.L            0
MaskPortC:  DC.L            0

_ligneClav: DC.L            0

ModePSG:    DC.L            0

numReg:     DC.L            0

_IsSound:   DC.L            0

_Constructeur:
            DC.B            $0E,0,0,0        ; Amstrad


;
; Tableau des masques pour les ports A, B, et C en fonction des bits 
; 0, 1, 3, 4 du port de contrôle. (le bit 2 n'est pas pris en compte)
; Un bit à 1 signifie que le bit correspondant du port est en entrée, 
; un bit à 0 signifie que le bit correspondant du port est en sortie.
; Rem. Le port C est divisé en 2 groupes de 4 bits, pour les ports A et
; B, c'est le port en entier qui est programmé en entrée ou en sortie.
;
TabMask:    DC.B            $00,$00,$00     ; 0
            DC.B            $00,$00,$0F     ; 1
            DC.B            $00,$FF,$00     ; 2
            DC.B            $00,$FF,$0F     ; 3
            DC.B            $00,$00,$00     ; 4
            DC.B            $00,$00,$0F     ; 5
            DC.B            $00,$FF,$00     ; 6
            DC.B            $00,$FF,$0F     ; 7
            DC.B            $00,$00,$F0     ; 8
            DC.B            $00,$00,$FF     ; 9
            DC.B            $00,$FF,$F0     ; 10
            DC.B            $00,$FF,$FF     ; 11
            DC.B            $00,$00,$F0     ; 12
            DC.B            $00,$00,$FF     ; 13
            DC.B            $00,$FF,$F0     ; 14
            DC.B            $00,$FF,$FF     ; 15
            DC.B            $FF,$00,$00     ; 16
            DC.B            $FF,$00,$0F     ; 17
            DC.B            $FF,$FF,$00     ; 18
            DC.B            $FF,$FF,$0F     ; 19
            DC.B            $FF,$00,$00     ; 20
            DC.B            $FF,$00,$0F     ; 21
            DC.B            $FF,$FF,$00     ; 22
            DC.B            $FF,$FF,$0F     ; 23
            DC.B            $FF,$00,$F0     ; 24
            DC.B            $FF,$00,$FF     ; 25
            DC.B            $FF,$FF,$F0     ; 26
            DC.B            $FF,$FF,$FF     ; 27
            DC.B            $FF,$00,$F0     ; 28
            DC.B            $FF,$00,$FF     ; 29
            DC.B            $FF,$FF,$F0     ; 30
            DC.B            $FF,$FF,$FF     ; 31

            SECTION         udata,BSS


_TabRegsPSG:
            DS.B            16


            XDEF            _ReadPPI
            XDEF            _WritePPI
            XDEF            _TabRegsPSG
            XDEF            _Constructeur
            XDEF            _portA
            XDEF            _IsSound
            END
