                         MAPPER (2)

Dit artikel is een vervolg/reaktie op het artikel van Stefan 
Boer over mappergebruik in de Sunrise Special 6.

In zijn  artikel gaf  Stefan een oplossing voor het probleem 
van   mapper-aansturing,  in   de  vorm   van  een   routine 
(MAPPER.GEN) die  met zowel DOS1 als DOS2 goed werkt. Ik ben 
het  ermee  eens  dat  iedereen  zo'n routine  eigenlijk zou 
moeten gebruiken in zijn programma's.

Ook  werd er  gemeld dat  de eigen  mapperroutines van  DOS2 
eigenlijk precies hetzelfde zijn, maar dat die routines niet 
goed bruikbaar zijn omdat ze niet op een vast adres staan.
Hier  ben  ik  het  niet  mee  eens,  want er  is een  goede 
(standaard)   manier   om   achter   de   adressen  van   de 
mapperroutines  te komen.  Als die manier er toch is, is het 
volgens mij  beter om  die te gebruiken. MAPPER.GEN gebruikt 
namelijk  adressen die  net zo  min standaard  zijn als  het 
beginadres  van  de mapperroutines.  En het  gebruik van  de 
mapperroutines levert  geen snelheidsverlies  op, dus  er is 
(in dit geval) geen reden om je niet aan de MSX-standaard te 
houden.

                        MAPPER2.GEN

De  routine die  ik al  een tijd  gebruik, en  die ik nu heb 
hernoemd  tot  MAPPER2.GEN,  is  in  principe  hetzelfde als 
MAPPER.GEN. Er  is, naast  de verschillende routinetjes voor 
het  lezen/schrijven van de mapper, een initialisatieroutine 
die  1  keer aangeroepen  moet worden.  Als er  DOS2 mapper- 
routines  aanwezig   zijn,  worden  de  lees/schrijfroutines 
veranderd.

De   lees/schrijfroutines  heb  ik  (bijna)  uit  MAPPER.GEN 
overgenomen. Pas  sinds Stefans artikel weet ik namelijk dat 
ook onder DOS1 de mapper niet direkt gelezen mag worden.

Het  verschil zit  hem in  de initialisatieroutine: Er wordt 
niet  gecheckt  op  de  aanwezigheid  van  DOS2, maar  op de 
aanwezigheid van de mapperroutines. (Dit staat inderdaad los 
van elkaar. Blijkbaar is het in principe ook mogelijk dat er 
mapperroutines aanwezig zijn, terwijl DOS2 niet aanwezig is. 
Dit komt  echter nooit  voor voor  zover ik weet.) Ook is de 
manier waarop de routines ReadFx en WriteFx worden veranderd 
verschillend;   ze  worden   afgebogen  naar   de  officiele 
mapperroutines.

Ik zal  voordat ik  MAPPER2.GEN weergeef, eerst alle theorie 
bespreken.

                       EXTENDED BIOS

De  adressen van de mapperroutines staan in een jumptabel in 
het systeemgebied.  Deze jumptabel  staat niet  op een  vast 
adres,  maar dit  adres is  te verkrijgen  met een  extended 
BIOS-aanroep.

Eerst  moet  er  gekeken  worden  of  er  wel extended  BIOS 
aanwezig  is. Dit  is het  geval als  bit 0  van adres #FB20 
(HOKVLD) gezet is. (Deze stap is niet nodig voor programma's 
die  onder  MSX-DOS draaien;  daar is  altijd extended  BIOS 
aanwezig.)

Als er  extended BIOS  aanwezig is,  kunnen we  via een call 
naar  hook  #FFCA  (EXTBIO)  te  weten komen  of er  mapper- 
routines aanwezig zijn.
Zoals  bij alle  extended BIOS aanroepen, komt in register D 
het ID-nummer  van de  extended BIOS routines te staan en in 
register  E het  funktienummer. Het ID-nummer van de mapper- 
routines is 4.

Ik zal  hier voor de volledigheid even alle twee de extended 
BIOS-funkties  van  de  mapperroutines  geven,  alhoewel  we 
alleen nummer 2 nodig hebben.

1: Haal adres vam mapper variabelentabel op

In:  A = 0
     D = 4
     E = 1
Uit: A = slotcode van primaire mapper (FxxxSSPP)
     DE = gereserveerd
     HL = adres van mapper variabelentabel

2: Haal adres van jumptabel op

In:  A = 0
     D = 4
     E = 2
Uit: A = totaal aantal segmenten van 16K in primaire mapper
     B = slotcode van primaire mapper (FxxxSSPP)
     C = aantal vrije segmenten in primaire mapper
     DE = gereserveerd
     HL = adres van jumptabel van mapperroutines

Eigenlijk  hoeft A niet per se 0 te zijn, maar dit vormt een 
goede  manier  om te  kijken of  de mapperroutines  aanwezig 
zijn. Als die niet aanwezig zijn, (dus er hangt geen routine 
aan  #FFCA  die  reageert  als  D=4,)  zullen  de  registers 
namelijk niet veranderd worden.
De funkties  van de mapperroutines geven in A altijd waarden 
terug  die van 0 verschillen. Als A dus na aanroep van #FFCA 
gelijk aan  0 is, zijn er geen mapperroutines aanwezig en in 
alle andere gevallen wel.

Hieronder is de inhoud van jumptabel weergegeven, voor zover 
die  voor ons  van belang is. Mensen die geinteresseerd zijn 
in de  rest verwijs  ik door  naar de tekstfile DOS2PROG.TXT 
die op deze disk staat.
(Dit is  ook de  tekstfile waar  ik al deze wijsheid over de 
mapperroutines vandaan heb.)

adres   naam     funktie   
+18H    PUT_P0   schakel segment in page 0 (z. WriteFC)
+1BH    GET_P0   geef huidig segmentnr. in page 0 (z. ReadFC)
+1EH    PUT_P1   schakel segment in page 1 (z. WriteFD)
+21H    GET_P1   geef huidig segmentnr. in page 1 (z. ReadFD)
+24H    PUT_P2   schakel segment in page 2 (z. WriteFE)
+27H    GET_P2   geef huidig segmentnr. in page 2 (z. ReadFE)
+2AH    PUT_P3   Doet niets, omdat page 3 nooit veranderd mag
                 worden.
+2DH    GET_P3   geef huidig segmentnr. in page 3 (z. ReadFF)

Als  de  mapperroutines  aanwezig zijn,  worden de  routines 
ReadFx en WriteFx afgebogen naar de mapperroutines; er wordt 
bij de subroutines een JP-instruktie neergezet.
(Deze  JP  verwijst niet  naar de  jumptabel, maar  naar het 
adres dat  in de jumptabel staat. De JP-instruktie die in de 
jumptabel  staat,  wordt  gewoon  gekopieerd  naar de  goede 
plek.)



; MAPPER2.GEN
; Standaard mapperroutines
; Werken onder DOS1 & DOS2
; Gebruiken DOS2 mapperroutines indien aanwezig
; Niet rechtstreeks de mapper aansturen, alles
; via deze routines doen!!!

; Voor eerste gebruik InitMapRouts aanroepen!

; Door Roderik Muit/Stefan Boer
; Sunrise Special #8
; (c) Stichting Sunrise 1994


; Init mapper routines
; 1 * aanroepen voor gebruik van Read/Write routines!

InitMapRouts:     LD    A,(#FB20)         ; Niet nodig onder
                  RRCA                    ;  MSX-DOS
                  RET   NC                ; Geen EXTBIOS

                  XOR   A
                  LD    DE,0402H          ; ID/funktienr
                  CALL  #FFCA
                  OR    A
                  RET   Z                 ; Geen maprouts

                  LD    BC,18H
                  ADD   HL,BC             ; Jumpadres PUT_P0
                  LD    DE,WriteFC        ; Kopieer jumps
                  LD    C,3
                  LDIR
                  LD    DE,ReadFC
                  LD    C,3
                  LDIR
                  LD    DE,WriteFD
                  LD    C,3
                  LDIR
                  LD    DE,ReadFD
                  LD    C,3
                  LDIR
                  LD    DE,WriteFE
                  LD    C,3
                  LDIR
                  LD    DE,ReadFE
                  LD    C,3
                  LDIR
                  LD    DE,WriteFF
                  LD    C,3
                  LDIR
                  LD    DE,ReadFF
                  LD    C,3
                  LDIR
                  RET 


; Routines voor schrijven mapper (als DOS2 niet aanwezig)
; In : A = segmentnummer
; Uit: -
; Verandert: - (Ook niet als afgebogen naar DOS2 routines)
; Net als bij DOS2 heeft WriteFF geen effekt. Page 3 mag 
; namelijk nooit geschakeld worden.

WriteFC:          LD    (StoreFC),A
                  OUT   (#FC),A
                  RET

WriteFD:          LD    (StoreFD),A
                  OUT   (#FD),A
                  RET

WriteFE:          LD    (StoreFE),A
                  OUT   (#FE),A
WriteFF:          RET
                  DW    0

; DW 0 is nodig omdat er 3 bytes tussen WriteFF en ReadFC 
; moeten zitten. (Je kan diskussieren over het nut van 
; het afbuigen van WriteFF, maargoed.)


; Routines voor lezen mapper
; In : -
; Uit: A = segmentnummer
; Alle andere registers blijven bewaard (ook als afgebogen 
;  naar DOS2 routines)

ReadFC:           LD    A,(StoreFC)
                  RET

ReadFD:           LD    A,(StoreFD)
                  RET

ReadFE:           LD    A,(StoreFE)
                  RET

ReadFF:           LD    A,(StoreFF)
                  RET

; ruimte voor opslag onder DOS1

StoreFF:          DB    0
StoreFE:          DB    1
StoreFD:          DB    2
StoreFC:          DB    3



                       EEN OPMERKING

Nog even  een opmerking n.a.v. de extended BIOS.
Deze heeft verder niets met het artikel te maken...

In Sunrise Special 7 las ik een artikel van Erik Maas waarin 
hij  schreef  dat  hij  ook  zat met  het feit  dat hij  een 
jumptabel  kwijt moest,  maar daar geen vast adres voor had. 
Hij moest  kunnen aangeven of zijn RS232-driver aanwezig is, 
en waar de jumptabel staat. Als oplossing heeft hij een paar 
systeemvariabelen  gebruikt  die  voor  de  cassetterecorder 
gebruikt worden.

Het is  wel een  goede oplosing maar dit kan natuurlijk niet 
door  iedereen gedaan  worden die uitbreidingen wil maken en 
jumptabellen  kwijt  wil.  Daarvoor  hebben  we  niet genoeg 
ongebruikte systeemvariabelen.
Een  andere oplossing  is het afbuigen van de hook EXTBIO en 
daar een  routine aan  hangen die  op een  bepaald ID-nummer 
reageert.
Dit is  onder andere  gedaan door  MemMan, die  de waarde 77 
(ASCII waarde van M) voor zichzelf heeft gereserveerd.

Het  is  niet  mijn  bedoeling  dit  hele onderwerp  te gaan 
uitdiepen, dus ik laat het bij deze opmerking...

                                               Roderik Muit.
