;                               X86IOPIX.ASM
.MODEL SMALL ; force Masm to make a .EXE
.STACK 040h
.CODE
.386
;****************************************************************************
;**                   EXEMPLE DE MODULE X86 POUR CpcALive                  **
;**                   AVEC INT‚GRATION DE COMMANDES RSX                    **
;****************************************************************************
; Assemblage: Ml X86IOPix.asm     -> cr‚e le fichier X86IOPix.exe
; Chargement dans l'‚mulateur, 3 solutions:
; 1- … partir de la ligne de commande Dos: ! X86IOPix.exe
; 2- … partir d'un fichier de commande CpcAlive: X86IOPix.exe
; 3- … partir de l'interpr‚teur basic du Cpc: |input,"X86IOPix.exe":call 0
; commandes … partir de l'interpr‚teur basic du Cpc:
; |OPIX,X,Y,pen   - OUTPUT PIXEL
; |IPIX,X,Y,@pen% - INPUT PIXEL
; |PALSET,@PAL(0) - SET PALETTE DEPUIS VARIABLE DIMENSIONN‚E
; |PALASK,@PAL(0) - CHARGER PALETTE DANS VARIABLE DIMENSIONN‚E
; |PALGREY        - CONVERTIR PALETTE EN NUANCES DE GRIS
; - initialiser la variable @pen% par pen%=0 pour |IPIX
; - X et Y sont relatifs au coin en haut … gauche de l'‚cran.
;****************************************************************************

START:          push cs
                pop ds
                mov dx,offset Mes
                mov ah,9
                int 021H
                mov ax,04C00h
                int 021h

Mes             db "Ce fichier est un module CpcAlive.",13,10
                db "This file is a CpcAlive module.",13,10
                db "http://cpcalive.com.",13,10,"$"

;UTILIS‚ PAR LE SYSTEME CpcAlive
org 0200h
                db 'X86CPC'             ; 0200h marque
                dw 1                    ; 0206h version
                dw offset X86Vec        ; 0208h adresse table vecteurs d'entr‚e
                dw 0                    ; 020Ah r‚serv‚
                dw 0                    ; 020Ch r‚serv‚
                dw 0                    ; 020Eh r‚serv‚
                dw offset MnemoTb       ; 0210h offset mn‚moniques
                db -1                   ; 0212h (*)re‡oit le num‚ro de module X86
                db -1                   ; 0213h num‚ro module compl‚ment ou num‚ro bloc banque Cpc
                db -1                   ; 0214h (*)re‡oit le num‚ro de la rom Z80 associ‚e
                db -1                   ; 0215h indicateur chargement banques Cpc ou module compl‚ment
                dw 0                    ; 0216h (*)1ere adresse Cpc ou module compl‚ment accessible
                                        ;       (0=aucune adresse accessible)
                db 0                    ; 0218h r‚serv‚
                dw 0                    ; 0219h (*)re‡oit le handle ems associ‚ au module
                dw 0                    ; 021Bh (*)re‡oit le num‚ro logique premiŠre page du module
                db 0                    ; 021Dh (*)re‡oit le nombre de pages allou‚es au module
                dw 0                    ; 021Eh adresse appel‚e … l'arrˆt de l'‚mulateur (0=pas d'appel)
                dw 0                    ; 0220h adresse appel‚e … la mise en veille de l'‚mulateur (0=pas d'appel)
                dw 0                    ; 0222h adresse appel‚e au retour de veille de l'‚mulateur (0=pas d'appel)
                dw 0                    ; 0224h adresse appel‚e au chargement du module (0=pas d'appel)
                dw 0                    ; 0226h r‚serv‚
                db 0                    ; 0228h (*)nombre de pages connect‚es
                                        ;       ou nombre de pages … connecter
                                        ;       ou nombre de pages … allouer (si<>0 au chargement du module)
                db 0100h-029h dup (0)   ; 0229h r‚serv‚

;(*) = valeurs g‚n‚r‚es par le systŠme

;*****************************************************************************

MnemoTb         db "PIXIN","I" or 080h          ; |PIXINI
                db "OPI","X" or 080h            ; |OPIX
                db "IPI","X" or 080h            ; |IPIX
                db "PALSE","T" or 080h          ; |PALSET
                db "PALAS","K" or 080h          ; |PALASK
                db "PALGRE","Y" or 080h         ; |PALGREY
                db 0

X86Vec          dw offset PixIni        ; 00 ** |PIXINI - INIT **
                dw offset OPix          ; 01 ** |OPIX,X,Y,PEN - SORTIE PIXEL A TRAVERS INT 010H **
                dw offset IPix          ; 02 ** |IPIX,X,Y,@PEN% - LECTURE PIXEL A TRAVERS INT 010H **
                dw offset PalSet        ; 03 ** |PALSET,@PAL(0) - SET PALETTE DEPUIS VARIABLE DIMENSIONN‚E **
                dw offset PalAsk        ; 04 ** |PALASK,@PAL(0) - CHARGER PALETTE DANS VARIABLE DIMENSIONN‚E **
                dw offset PalGrey       ; 05 ** |PALGREY - CONVERTIR PALETTE EN NUANCES DE GRIS **

                ;... 128 vecteurs maximum

; Valeurs de AH ou AX pour interruption 018H
; ** Lecture banque 0 Cpc (blocs 0,1,2,3) **
ReadAL=0        ; (AH) lire l'octet point‚ par SI et le mettre dans AL
ReadAH=0200h    ; (AX) lire l'octet point‚ par SI et le mettre dans AH
ReadBL=0201h    ; (AX) lire l'octet point‚ par SI et le mettre dans BL
ReadBH=0202h    ; (AX) lire l'octet point‚ par SI et le mettre dans BH
ReadCL=0203h    ; (AX) lire l'octet point‚ par SI et le mettre dans CL
ReadCH=0204h    ; (AX) lire l'octet point‚ par SI et le mettre dans CH
ReadDL=0205h    ; (AX) lire l'octet point‚ par SI et le mettre dans DL
ReadDH=0206h    ; (AX) lire l'octet point‚ par SI et le mettre dans DH
ReadAX=0207h    ; (AX) lire le mot point‚ par SI et le mettre dans AX
ReadBX=0208h    ; (AX) lire le mot point‚ par SI et le mettre dans BX
ReadCX=0209h    ; (AX) lire le mot point‚ par SI et le mettre dans CX
ReadDX=020Ah    ; (AX) lire le mot point‚ par SI et le mettre dans DX
ReadSI=020Bh    ; (AX) lire le mot point‚ par SI et le mettre dans SI
ReadDI=020Ch    ; (AX) lire le mot point‚ par SI et le mettre dans DI
ReadBP=020Dh    ; (AX) lire le mot point‚ par SI et le mettre dans BP
WriteAL=1       ; (AH) ‚crire la valeur de AL dans l'octet point‚ par DI
WriteBL=0301h   ; (AX) ‚crire la valeur de BL dans l'octet point‚ par DI
WriteBH=0302h   ; (AX) ‚crire la valeur de BH dans l'octet point‚ par DI
WriteCL=0303h   ; (AX) ‚crire la valeur de CL dans l'octet point‚ par DI
WriteCH=0304h   ; (AX) ‚crire la valeur de CH dans l'octet point‚ par DI
WriteDL=0305h   ; (AX) ‚crire la valeur de DL dans l'octet point‚ par DI
WriteDH=0306h   ; (AX) ‚crire la valeur de DH dans l'octet point‚ par DI
WriteBX=0308h   ; (AX) ‚crire la valeur de BX dans le mot point‚ par DI
WriteCX=0309h   ; (AX) ‚crire la valeur de CX dans le mot point‚ par DI
WriteDX=030Ah   ; (AX) ‚crire la valeur de DX dans le mot point‚ par DI
WriteBP=030Dh   ; (AX) ‚crire la valeur de BP dans le mot point‚ par DI

PixIni:
                pusha
                mov dx,offset IniMes
                mov ah,9
                int 021H
                popa
                stc                     ; carry="ok"
                RETF                    ; RETOUR VECTEUR (FAR)

IniMes          db " X86IOPix - 2014",13,10
                db "$"


; ** SORTIE PIXEL A TRAVERS INT 010H - |OPIX,X,Y,PEN **
; < conditions d'entr‚e RamCpc:[SI+0] = num‚ro de pinceau (pen)
;                       RamCpc:[SI+2] = y
;                       RamCpc:[SI+4] = x
OPix:
                mov ah,ReadAL           ; charger valeur RamCpc:[SI+0] dans AL
                int 018h                ; couleur demand‚e dans AL
                push ax                 ; sauve num‚ro de pinceau (pen)
                add si,2                ; pointe coordonn‚e Y dans RamCpc
                mov ax,ReadDX           ; charger valeur dans DX
                int 018h                ; coordonn‚e Y dans DX
                add si,2                ; pointe coordonn‚e X dans RamCpc
                mov ax,ReadCX           ; charger valeur dans CX
                int 018h                ; coordonn‚e X dans CX
                pop ax                  ; r‚cupŠre num‚ro de pinceau (pen)
                mov ah,0Ch              ; //BIOS//FONCTION 0CH = ECRIRE UN POINT GRAPHIQUE
                INT 010h                ; APPEL INTERRUPTION BIOS 010H
                RETF                    ; RETOUR VECTEUR (FAR)

; ** LECTURE PIXEL A TRAVERS INT 010H - |IPIX,X,Y,@PEN% **
; < conditions d'entr‚e RamCpc:[SI+2] = y
;                       RamCpc:[SI+4] = x
; > condition de sortie RamCpc:[SI+0] = num‚ro de pinceau (pen)
IPix:                
                push bx
                push di
                push si                 ; sauve pointeur adresse variable PEN
                add si,2                ; pointe coordonn‚e Y dans RamCpc
                mov ax,ReadDX           ; charger valeur dans DX
                int 018h                ; coordonn‚e Y dans DX
                add si,2                ; pointe coordonn‚e X dans RamCpc
                mov ax,ReadCX           ; charger valeur dans CX
                int 018h                ; coordonn‚e X dans CX
                mov ah,0Dh              ; //BIOS//FONCTION 0DH = LIRE UN POINT GRAPHIQUE
                INT 010h                ; APPEL INTERRUPTION BIOS 010H
                pop si                  ; r‚cupŠre pointeur adresse variable PEN
                push ax                 ; sauve num‚ro de pinceau (pen)
                mov ax,ReadDI           ; charger adresse variable PEN dans DI
                int 018h                ; adresse variable PEN dans DI
                pop bx                  ; r‚cupŠre num‚ro de pinceau (pen)
                xor bh,bh               ; raz poid fort num‚ro de pinceau (pen)
                mov ax,WriteBX          ; poser BX dans RamCpc:[DI+0]
                int 018h                ; poser num‚ro de pinceau (pen)
                pop di
                pop bx
                RETF                    ; RETOUR VECTEUR (FAR)

; ** |PALASK,@PAL(0) - CHARGER PALETTE DANS VARIABLE DIMENSIONN‚E **
PalAsk:
                pusha
                push es
                mov ax,ReadSI           ; charge l'adresse du 1er ‚l‚ment du tableau dans SI
                int 018h

                push si
                sub si,2
                mov ax,ReadCX           ; charger "nombre d'‚lements du tableau + 1" dans CX
                int 018h
                dec cx
                and ch,3                ; nombre d'‚lements du tableau 3*256 maxi
                pop di                  ; pointe 1er ‚l‚ment du tableau

                push cx
                mov ax,cx               ; nombre d'‚lements du tableau
                mov cx,3                ; diviseur
                xor dx,dx               ; ?
                div cx                  ; /3=nombre de couleurs … charger dans tampon
                mov cx,ax               ; r‚sultat dans cx

                push cs
                pop es                  ; segment tampon couleurs palette
                mov dx,offset Palette   ; offset tampon couleurs palette
                mov bx,0                ; premier index
                mov ax,01017h           ; //BIOS//FONCTION: LIRE CONTENU PLUSIEURS REGISTRES DE COULEUR DAC
                INT 010H                ; APPEL INTERRUPTION BIOS 010H
                pop cx                  ; recupŠre nombre d'‚lements du tableau

                mov si,offset Palette   ; offset tampon couleurs palette
PalAskCont:     mov al,cs:[si]          ; charge index couleur
                shl al,2                ; 64>255tons
                mov ah,WriteAL          ; ‚crire la valeur de AL dans l'octet point‚ par DI
                int 018h
                add di,2                ; 2 octets par ‚l‚ment pour le tableau destination
                inc si                  ; 1 octet par ‚l‚ment pour le tampon source
                loop PalAskCont         ; continuer si encore des ‚l‚ments
                pop es
                popa
                RETF                    ; RETOUR VECTEUR (FAR)

Palette         db 256*3 dup (0)        ; tampon couleurs palette (RVB)

; ** |PALSET,@PAL(0) - SET PALETTE DEPUIS VARIABLE DIMENSIONN‚E **
; remarque: le tableau doit avoir ‚t‚ d‚fini par l'instruction basic DEFINT
PalSet:
                pusha
                push es
                mov ax,ReadSI           ; charge l'adresse du 1er ‚l‚ment du tableau dans SI
                int 018h

                push si
                sub si,2
                mov ax,ReadCX           ; charger "nombre d'‚lements du tableau + 1" dans CX
                int 018h
                dec cx
                and ch,3                ; nombre d'‚lements du tableau 3*256 maxi
                pop si

                push cx
                mov di,offset Palette   ; offset tampon couleurs palette
PalSetCont:     mov ah,ReadAL           ; charger valeur RamCpc:[SI+0] dans AL
                int 018h                ; couleur demand‚e dans AL
                shr al,2                ; 255>64tons
                mov cs:[di],al          ; pose num‚ro de couleur dans tampon "Palette"
                add si,2                ; 2 octets par ‚l‚ment pour le tableau source
                inc di                  ; 1 octet par ‚l‚ment pour le tampon destination
                loop PalSetCont         ; continuer si encore des ‚l‚ments
                pop ax                  ; nombre d'‚lements du tableau
                mov cx,3                ; diviseur
                xor dx,dx               ; ?
                div cx                  ; /3=nombre de couleurs … red‚finir
                mov cx,ax               ; r‚sultat dans cx
                push cs
                pop es                  ; segment tampon couleurs palette
                mov dx,offset Palette   ; offset tampon couleurs palette
                mov bx,0                ; premier index
                mov ax,01012h           ; //BIOS//FONCTION: CHARGER PLUSIEURS REGISTRES DE COULEUR DAC
                INT 010H                ; APPEL INTERRUPTION BIOS 010H
                pop es
                popa
                RETF                    ; RETOUR VECTEUR (FAR)


; ** |PALGREY - CONVERTIR PALETTE EN NUANCES DE GRIS **
PalGrey:
                pusha
                mov bx,0                ; premier index
                mov cx,256              ; nombre de couleurs … traiter
                mov ax,0101Bh           ; //BIOS//FONCTION: Convertir plusieurs registres de
                                        ;                   couleur DAC en nuances de gris
                INT 010H                ; APPEL INTERRUPTION BIOS 010H
                popa
                RETF                    ; RETOUR VECTEUR (FAR)


end start
