;**********************************************************************;
;*                           A T O M   X M S                          *;
;*--------------------------------------------------------------------*;
;*    doel           : geeft de atom-in-pc de beschikking over        *;
;*                     het xms geheugen van de pc via OSBYTE #Fx      *;
;*--------------------------------------------------------------------*;
;*    auteur         : Roland Leurs                                   *;
;*                     The Atomic Development Studio                  *;
;*    ontwikkeld     : 7-12-95                                        *;
;*    laatste update :                                                *;
;*--------------------------------------------------------------------*;
;*    assembleren    : x6502 XMSDRV                                   *;
;*--------------------------------------------------------------------*;
;*    oproep         : XMSDRV                                         *;
;**********************************************************************;

work            equ     $90             ;zeer tijdelijke werkruimte

                org     $0C00-16

header          .dw     header+16, install
                .dw     0,0,0,0,0,0

old_osbyte      .dw     0
old_resvec      .dw     return
xms_pages       .db     0
cur_page        .db     0
command         .db     0
frame           .db     $40


                include macro.inc

;-----------------------------------------------------------------------
; osbyte entry
;-----------------------------------------------------------------------
                
xmsdrv          jmp     xmsdrv1
                .db     "XMS",$0D
xmsdrv1         cmp     #$F0            ;test op osbyte #F0
                bcc     _osbyte         ;indien lager naar oude routine
                sta     command         ;berg commando nummer op in werkruimte
                push_regs               ;save registers
                lda     command         ;haal commando terug
                and     #$0F            ;alleen laagste vier bits nodig
                asl     a               ;osbyte nummer naar index
                tax
                lda     osbyte_tab,x    ;zet sprongadres in werkruimte
                sta     work
                lda     osbyte_tab+1,x
                sta     work+1
xmsdrv2         osbyte  $0B             ;wacht op toestemming voor pc-comm
                bcc     xmsdrv2
                jmp     (work)          ;ga call uitvoeren

;-----------------------------------------------------------------------
; commando tabel
;-----------------------------------------------------------------------
                
osbyte_tab      .dw     versie, xmsldpg, xmsldpg, xmsldpg
                .dw     xmsframe, reserved, reserved, reserved
                .dw     reserved, reserved, reserved, reserved
                .dw     reserved, reserved, reserved, reserved

reserved        pop_regs                ;haal registers terug
_osbyte         jmp     (old_osbyte)    ;spring naar oude vector

;-----------------------------------------------------------------------
; osbyte commando subroutines
;-----------------------------------------------------------------------

atom2pc         lda     #$00            ;zet memory pointer
                sta     work            ;berg op in werkruimte
                lda     frame
                sta     work+1
atom2pc1        ldy     #0              ;clear index
atom2pc2        lda     (work),y        ;lees data
                jsr     zendbytevec     ;stuur naar pc
                iny                     ;verhoog index
                bne     atom2pc2        ;spring als datablok niet compleet
                inc     work+1          ;256 bytes verzonden, verhoog page
                lda     frame           ;test op einde frame
                clc
                adc     #$40
                cmp     work+1
                bne     atom2pc1        ;spring als niet alles over is
                rts

pc2atom         lda     #$00            ;zet memory pointer
                sta     work            ;berg op in werkruimte
                lda     frame
                sta     work+1
pc2atom1        ldy     #0              ;clear index
pc2atom2        jsr     leesbytevec     ;lees data van pc
                sta     (work),y        ;zet in geheugen
                iny                     ;verhoog index
                bne     pc2atom2        ;spring als datablok niet compleet
                inc     work+1          ;256 bytes verzonden, verhoog page
                lda     frame           ;test op einde frame
                clc
                adc     #$40
                cmp     work+1
                bne     pc2atom1        ;spring als niet alles over is
                rts

xms_error       write   error1          ;druk foutmelding af
                osbyte  $0A             ;wis semafoor
                ldx     #248            ;laat foutcode
                osbyte  $0C             ;genereer error 248

xmsdrvend       pha                     ;save accu
                osbyte  $0A             ;wis semafoor
                pla                     ;herstel accu
return          rts                     ;einde xms osbyte

;-----------------------------------------------------------------------
; osbyte commando subroutines
;-----------------------------------------------------------------------
; functie 0: versie opvragen                            versie
;   -invoer:  geen
;   -uitvoer: A=aantal xms pagina's
;             X=versienummer
;             Y=releasenummer
;
; functie 1: pagina voorzetten                          xmsldpg
;   -invoer:  Y=pagina nummer
;   -uitvoer: geen
; opmerking: bij dit commando wordt de huidige
;            pagina niet opgeslagen in xmsgeheugen
;
; functie 2: pagina voorzetten                          xmsldpg
;   -invoer:  Y=pagina nummer
;   -uitvoer: geen
; opmerking: bij dit commando wordt de nieuwe
;            pagina niet gelezen in het atomgeheugen
;
; functie 3: pagina voorzetten                          xmsldpg
;   -invoer:  Y=pagina nummer
;   -uitvoer: geen
; opmerking: de huidige pagina wordt opgeslagen in
;            het xms geheugen en de nieuwe pagina
;            wordt in het atomgeheugen gelezen
;
; functie 4: paginaframe instellen/opvragen
;   -invoer:  Y=hoge byte paginaframe
;   -uitvoer: Y=hoge byte paginaframe
; opmerking: het paginaframe is 16 kb groot en kan liggen tussen
;            #2000-#9FFF; de parameter voor deze functie ligt in
;            het bereik #20...#60. Bij een ongeldige parameter wordt
;            de functie niet uitgevoerd, alleen wordt het huidige
;            frame teruggemeld. Na een reset staat het frame op #4000.
;
; functie 5: xms geheugen wegschrijven
;   -invoer:  X=pointer naar parameterblok in zeropage
;   -uitvoer: X=errorcode  (0=geen fout)
; opmerking: het parameterblok bevat de volgende gegevens:
;            X+0 beginadres: paginanummer
;            X+1 beginadres: offset in pagina
;            X+3 eindadres: paginanummer
;            X+4 eindadres: offset in pagina
;            X+6 pointer naar filenaam
;
; functie 6: xms geheugen van disk lezen
;   -invoer:  X=pointer naar parameterblok in zeropage
;   -uitvoer: X=errorcode  (0=geen fout)
; opmerking: het parameterblok bevat de volgende gegevens:
;            X+0 loadadres: paginanummer
;            X+1 loadadres: offset in pagina
;            X+3 pointer naar filenaam
;
;-----------------------------------------------------------------------

versie          pop_regs                ;er staan nog registers op stack
                pccom   $4B             ;roep int 61h aan
                zendbyte $0             ;geef commando $00 aan xms driver
                leesbyte                ;lees versienummer
                tax                     ;zet in x-register
                leesbyte                ;lees release nummer
                tay                     ;zet in y-register
                leesbyte                ;lees aantal xms pagina's
                jmp     xmsdrvend       ;einde call

xmsldpg         pla                     ;haal nieuw paginanummer van stack
                pha                     ;maar ook weer bewaren
                cmp     xms_pages       ;vergelijk met aantal pages
                beq     xmsldpg1        ;spring indien hoogste pagina
                bcs     xms_error       ;spring indien niet geldig
xmsldpg1        pccom   $4B             ;roep int 61h aan
                lda     command         ;stuur functie nummer
                and     #000000011b     ;maak er iets moois van
                jsr     zendbytevec     ;stuur naar pc
                lda     command         ;laadt commandonummer
                and     #000000001b     ;pagina schrijven?
                beq     xmsldpg2        ;nee, dan overslaan
                lda     cur_page        ;stuur huidig paginanummer naar pc
                jsr     zendbytevec
                jsr     atom2pc         ;stuur pagina naar pc
xmsldpg2        pla                     ;haal nieuw paginanummer van stack
                pha                     ;blijven bewaren
                sta     cur_page        ;berg op in page register
                lda     command         ;laadt commandonummer
                and     #00000010b      ;pagina lezen?
                beq     xmsldend        ;nee, dan overslaan
                lda     cur_page        ;haal pagina nummer op
                jsr     zendbytevec     ;stuur naar pc
                jsr     pc2atom         ;lees nieuwe pagina
xmsldend        pop_regs                ;alle registers herstellen
                jmp     xmsdrvend       ;einde routine

xmsframe        pla                     ;haal registers van stack
                pla
                pla
                cpy     #$20            ;test op geldigheid van parameter
                bmi     getframe        ;spring indien kleiner
                cpy     #$61            ;frame mag liggen tussen 20...60
                bpl     getframe
                sty     frame           ;geldige waarde; stel frame in
getframe        ldy     frame           ;laad huidig frame
                jmp     xmsdrvend       ;einde routine
                                                            
;xmssave         pccom   $4B             ;oproep int 61
;                zendbyte $4             ;stuur commandonummer op
;                lda     cur_page        ;stuur huidig paginanummer naar pc
;                jsr     zendbytevec
;                jsr     atom2pc         ;huidige pagina oversturen
;                ldy     #6              ;set teller
;xmssave1        lda     0,x             ;stuur adressen naar pc
;                jsr     zendbytevec
;                inx                     ;verhoog index
;                dey                     ;verlaag pointer
;                bne     xmssave1        ;spring indien niet alles over is
;                lda     0,x             ;zet adres van filenaam in werkruimte
;                sta     work
;                lda     1,x
;                sta     work+1
;xmssave2        lda     (work),y        ;lees karakter van filenaam
;                jsr     zendbytevec     ;stuur naar pc
;                cmp     #$0D            ;einde naam?
;                beq     xmssave3        ;ja, spring
;                iny                     ;verhoog pointer
;                bne     xmssave2        ;spring voor volgend karakter
;                lda     #0              ;jictgt filenaam langer dan 256 char
;xmssave3        leesbyte                ;lees errorcode
;                jmp     xmsdrvend       ;einde save commando
;
;xmsload         pccom   $4B             ;aanroep int 61
;                zendbyte $5             ;functienummer doorgeven
;                ldy     #3              ;set teller
;xmsload1        lda     0,x             ;stuur adressen naar pc
;                jsr     zendbytevec
;                inx                     ;verhoog index
;                dey                     ;verlaag pointer
;                bne     xmsload1        ;spring indien niet alles over is
;                lda     0,x             ;zet adres van filenaam in werkruimte
;                sta     work
;                lda     1,x
;                sta     work+1
;xmsload2        lda     (work),y        ;lees karakter van filenaam
;                jsr     zendbytevec     ;stuur naar pc
;                cmp     #$0D            ;einde naam?
;                beq     xmsload3        ;ja, spring
;                iny                     ;verhoog pointer
;                bne     xmsload2        ;spring voor volgend karakter
;                lda     #0              ;jictgt filenaam langer dan 256 char
;xmsload3        leesbyte                ;lees errorcode
;                lda     cur_page        ;update huidige pagina
;                jsr     zendbytevec
;                jsr     pc2atom         ;binnenhalen die zooi
;                jmp     xmsdrvend       ;einde save commando

;-----------------------------------------------------------------------
; initialisatie
;-----------------------------------------------------------------------

init            ldy     #$01
                ldx     #$87            ;alvorens de xms-driver aan te roepen
init1           pccom   $5B             ;eerst onderzoeken of de driver
                zendbyte $03            ;geladen is
                txa
                jsr     zendbytevec
                zendbyte $01
                zendbyte $00
                zendbyte $00
                leesbyte                ;lees segment van INT 61 handler
                sta     work,y          ;berg op in werkruimte
                dex                     ;verlaag pc geheugenpointer
                dey                     ;verlaag teller
                bpl     init1           ;doe dit twee keer
                pccom   $5B             ;vraag inhoud van INT 61 handler op
                zendbyte $03
                zendbyte $06
                zendbyte $01
                lda     work
                jsr     zendbytevec
                lda     work+1
                jsr     zendbytevec
                leesbyte                ;lees resultaat
                cmp     #'N'            ;controleer byte
                beq     init2
                jmp     geen_xms_drv    ;spring indien geen driver aanwezig
init2           pccom   $5B             ;vraag inhoud van INT 61 handler op
                zendbyte $03
                zendbyte $07
                zendbyte $01
                lda     work
                jsr     zendbytevec
                lda     work+1
                jsr     zendbytevec
                leesbyte                ;lees resultaat
                cmp     #'B'            ;controleer byte
                beq     init3           ;spring indien driver aanwezig is
                jmp     geen_xms_drv
init3           lda     #$40            ;paginaframe op #4000 zetten
                sta     frame
                lda     #0              ;@=0
                sta     $321
                write   msg1            ;druk tekst af
                pccom   $4B             ;roep int 61h aan
                zendbyte $0             ;geef commando $00 aan xms driver
                leesbyte                ;lees versienummer
                tax                     ;zet in x-register
                leesbyte                ;lees release nummer
                tay                     ;zet in y-register
                leesbyte                ;lees aantal xms pagina's
                sta     xms_pages       ;berg op in werkruimte
                write   msg2            ;print tekst
                txa                     ;versienummer naar accu
                jsr     prtnibble       ;druk versienummer af
                lda     #'.'            ;print puntje
                jsr     $FFF4
                tya                     ;release nummer naar accu
                jsr     prthex          ;afdrukken
                write   msg3            ;volgende tekst afdrukken
                lda     xms_pages       ;druk aantal pagina's af
                jsr     prthex
                write   msg4            ;volgende tekst afdrukken
                clc                     ;wis carry voor optelling
                lda     xms_pages       ;bereken xms omvang in kb
                adc     #1
                sta     $16
                lda     #0
                adc     #0
                sta     $25
                lda     #0
                sta     $34
                sta     $43
                ldx     #4              ;laadt teller
mul16           asl     $16             ;vermenigvuldig met 2
                rol     $25
                dex                     ;verlaag teller
                bne     mul16           ;vier keer doen
                jsr     prtdec          ;druk xms omvang in kb af
                write   msg5            ;druk laatste tekst af
                lda     $220            ;bewaar oude osbyte vector
                sta     old_osbyte
                lda     $221
                sta     old_osbyte+1
                lda     #<xmsdrv        ;zet nieuwe vector
                sta     $220
                lda     #>xmsdrv
                sta     $221
                lda     #8              ;@=8
                sta     $321
                jmp     (old_resvec)    ;einde routine

;-----------------------------------------------------------------------
; meldingen
;-----------------------------------------------------------------------

msg1            .db 13,10,"Wacht op PC XMS driver . . .",0
msg2            .db 13,17,4,"Atom XMS driver v",0
msg3            .db "i - (c) 1995,96 Roland Leurs"
                .db 13,10,"Beschikbaar XMS geheugen: #",0
msg4            .db " pages ( ",17,14,0
msg5            .db 17,4," ) kb",17,2,13,10,0

error1          .db "Ongeldig XMS pagina nummer",10,13,0
error2          .db 17,4,"ATOM XMS is niet geladen !",10,13,7,17,2,0

;-----------------------------------------------------------------------
; installatie
;-----------------------------------------------------------------------
geen_xms_drv    write   error2          ;druk foutmelding af
                jmp     (old_resvec)    ;einde routine

install         lda     $4FA            ;test of al een reset-ext gebruikt is
                cmp     #$4C
                bne     install1
                lda     $4FB            ;sla oude vector op
                sta     old_resvec
                lda     $4FC
                sta     old_resvec+1
install1        lda     #<init          ;zet resetvector naar initroutine
                sta     $4FB
                lda     #>init
                sta     $4FC
                lda     #$4C            ;enable extended reset routine
                sta     $4FA
                pccom   $5B             ;stel reset type in
                zendbyte $5C
                zendbyte $3             ;type 3: driver init
                pccom   $5B             ;reset de Atom
                zendbyte $5D
