MILC logo

IndexVorigeVolgendeLeeg

128kB VRAM gebruiken in ML
Genic Clubguide, 00-00-00


    
Nvdr.  De  nu  volgende  tekst  is  ook  te  vinden  op   de
BBS-Waterland en is geschreven door Ramon van der Winkel die
GENIC toestemming heeft gegeven voor deze publicatie.

Aan de publicatie van dit artikel hebben meegewerkt:

Ramon van der Winkel  (De schrijver van het artikel)
Rudy Oppers           (De man van de modem)
Alex van der Wal      (Initiatiefnemer & editor)


       G E B R U I K   1 2 8 K B   V R A M   I N   M L
      =================================================

In deze tekstfile wordt uiteengezet hoe  het  volledige  128
Kilobytes van het video RAM van de MSX te gebruiken is.

Het VRAM is, net zoals bij een memory mapper,  onderverdeeld
in pagina's van 16  kilobytes.  In  totaal  zijn  er  dus  8
pagina's die met maar 1 pagina  tegelijk  aan  te  schakelen
zijn.

Om een pagina en een adres daarbinnen te kiezen,  moeten  we
een aantal waardes achter elkaar op de commando poort van de
VDP zetten, waarna we  via  de  datapoort  het  VRAM  kunnen
uitlezen of schrijven.

De commando poort is standaard poort 099h en de datapoort is
standaard 098h. Deze twee poorten zijn ook via adres 0006 en
0007 van de mainrom te vinden (voor de commando poort er een
bij optellen), maar het zijn nu al weet ik hoeveel jaar lang
dezelfde poorten geweest, dus  rechtstreeks  gebruik  zonder
controle kan geen kwaad.

We kunnen de data-transfer altijd maar een kant tegelijk  op
doen. Het is dus niet mogelijk  om  10  bytes  te  lezen  en
daarna, zonder opnieuw te adresseren, 21 bytes te  schrijven
en dan meteen er maar weer 5 te lezen. We geven met  bit  10
van het adres op of we willen schrijven. Raar bit,  die  bit
10,  maar  dat  is  heeleenvoudig  te  verklaren:  Omdat  er
pagina's zijn van 16 kilobytes (16384 bytes,  4000h)  kunnen
we nooit meer als 16 Kilobytes in een keer verplaatsen.  Dus
als we willen schrijven, dan OR-en we 40h bij  het  MSB  van
het adres en versturen we dit naar de vdp, anders kunnen  we
lezen.

Stel, we willen  vanaf  pagina  5,  adres  2BF5  lezen,  dan
versturen we de volgende reeks codes door  de  vdp  commando
poort (99h): 05h, 8Eh, 0F5h, 2Bh. Willen we  schrijven,  dan
wordt de reeks: 05h, 8Eh, 0F5h, 6Bh. 6Bh is dus 2Bh or 40h.

De 8E die je in allebij de reeksen ziet staan,  is  voor  de
vdp  een  aanduiding  dat  we  register  #14  (0Eh)   willen
schrijven (or 80h). Dit is een  standaard  methode  voor  de
vdp. Wat we dan doen, is  eerst  de  data  op  door  de  vdp
commando poort sturen en daarna het register nummer OR  80h.
In dit geval moeten we na de pagina in de data-byte  (eerste
code) ook nog eens het adres erachteraan  sturen  (derde  en
vierde code).

Het is mogelijk om van de ene pagina door te schrijven  naar
de volgende. Na iedere byte die gelezen  of  geschreven  is,
wordt het adres automatisch  verhoogd.  Na  adres  3FFFh  in
bijvoorbeeld pagina 2, komt meteen adres 0000h in pagina  3.
Wat er na pagina 7, adres 3FFFh gebeurd weet  ik  niet,  dat
heb ik nog nooit geprobeerd.

Tijd voor een universele routine, waarbij we in A het pagina
nummer opgeven en in HL het adres, waarbij bit 10  al  gezet
moet zijn als we willen schrijven:

VRMADR: DI                    DI
        OUT (099H),A   of:    LD C,099H
        LD A,08Eh             OUT (C),A
        OUT (099H),A          LD A,08EH
        LD A,L                OUT (C),A
        OUT (099H),A          OUT (C),L
        LD A,H                OUT (C),H
        OUT (099H),A

Nu willen we data gaan transporteren. Dat doen we via de VDP
datapoort. Nadat we het adres geschreven  hebben,  staat  de
datapoort klaar om tekens te ontvangen  of  versturen  (ligt
aan bit 10 van het adres). Door poort 098h te lezen, krijgen
we de data binnen, door hem te schrijven gaat het  naar  het
VRAM.

Nu hebben we echter nog een probleem:  Timing.  Ik  heb  net
daarboven twee routines naast elkaar  gezet.  Waarschijnlijk
zal de linker wel werken  en  de  rechter  niet  zondermeer.
Waarom niet zou je zeggen? Als data op de  bus  van  de  vdp
zetten, dan heeft die tijd nodig om deze er vanaf te  halen.
Sturen we de data nu zo snel dat de geen tijd  genoeg  heeft
om hem er vanaf te halen, dan werkt het simpelweg niet.  Dit
geld  overigens  alleen  voor  de  commando  poort,  bij  de
datapoort kunnen we  net  zo  snel  data  versturen  als  we
willen.

Een NOP tussen alle outs in de rechter  routine  zou  genoeg
moeten zijn, anders twee keer een EX (SP),HL of  twee  stack
operaties ofzo. Het is mij opgevallen dat als je wilt  lezen
van het VRAM, je twee EX (SP),HL 's of een PUSH en  een  POP
achter de adressering van  de  linker  routine  moet  zetten
(daar blijf ik voorlopig maar bij). In het  voorbeeld  staat
een PUSH en een POP.

Nu dan twee routines die een deel van het VRAM naar het  RAM
kunnen verplaatsen en de andere kant op. In register B  moet
het aantal  bytes  staan,  wat  in  blokken  van  256  bytes
verstuurd  gaat  worden.  Een  kleine  modificatie  in  deze
routine en je kan iedere hoeveelheid bytes vanplaatsen. Voor
de verplaatsing van en  naar  het  VRAM  heb  ik  even  twee
routines gemaakt, zodat bit 10 van het adres niet meer gezet
hoeft te worden en omdat er bij de het lezen met IN's en bij
het schrijven met OUT's moet worden gewerkt:


;
; TOVRAM - Verplaats B blokken van 256 bytes vanaf pagina A
;          en adres HL naar het VRAM, vanaf RAM, adres DE
;
TOVRAM:    DI               ;Voorkom ander vram gebruik
           OUT (099H),A     ;Pagina
           LD A,08EH        ;VDP #14 <- Pagina
           OUT (099H),A
           LD A,L           ;Adres LSB
           OUT (099H),A
           LD A,H           ;Adres MSB
           AND 03FH         ;Maximaal 16K en wis bit 10
           OR 40H           ;Zet bit 10 voor schrijven
           OUT (099H),A
           PUSH DE          ;Adres naar HL voor OTIR
           POP HL
           LD E,B           ;Aantal blokken
           LD C,098H        ;VDP datapoort voor OTIR
TOVLUS:    LD B,0           ;Aantal bytes voor OTIR
           OTIR             ;Verplaats de data
           DEC E            ;Nog meer blokken?
           JR NZ,TOVLUS     ;Ja!
           RET

;
; FRMVRM - Verplaats B blokken van 256 bytes vanuit het ram
;          vanaf adres DE naar het vram, pagina A adres HL
;
FRMVRM:    DI               ;Voorkom ander vram gebruik
           OUT (099H),A     ;Pagina
           LD A,08EH        ;VDP#14 <- Pagina
           OUT (099H),A
           LD A,L           ;Adres LSB
           OUT (099H),A
           LD A,H           ;Adres MSB
           AND 03FH         ;Maximaal 16K, wis bit 10
           OUT (099H),A
           PUSH DE          ;Adres naar HL voor INIR
           POP HL           ; maar ook meteen delay
           LD E,B           ;Aantal blokken
           LD C,098H        ;VDP datapoort voor INIR
FRVLUS     LD B,0           ;256 bytes per verplaatsing
           INIR             ;Lees uit het vram
           DEC E            ;Nog meer blokken?
           JR NZ,TOVLUS     ;Ja
           RET

Ik hoop dat deze gegevens een beetje te gebruiken zijn.  Het
adresseren van de videochip en het verplaatsen van een  naar
het VRAM kan natuurlijk ook met de MAINROM, maar dan moet je
de routines daar een beetje gaan misleiden om bij de  2e  64
kB te kunnen komen. Dit kan door op adres 0FAF6h de waarde 0
voor de 1e 64K en de waarde 1 voor de 2e 64K neer te  zetten
en daarna NSETRD en NSETWR aan te roepen. Dit komt  ongeveer
overeen met set pagina ,0 en set page ,1 op  screen  8.  Het
adres bevat in ieder geval de 'active page'. Op adres 0FAF5h
staat de 'diplay page', maar dat is verder niet zinnig om te
weten.

Kijk voor het gebruik van meer dan  16  kilobytes  vram  wel
even hoeveel VRAM er aanwezig is. Dit kan door op  pagina  3
en 7 op adres 0000h bijvoorbeeld de waarde 3 in pagina 3  en
daarna de waarde 7 in pagina 7 te schrijven. Als  er  daarna
in pagina 3 een 7 staat, dan is er  dus  maar  64  Kilobytes
aanwezig. Ook kan je  naar  adres  0FAFCh  kijken.  De  MSX2
SUBROM heeft daar al neergezet  hoeveel  VRAM  die  gevonden
heeft. Ik geloof dat bit 4 daar  gezet  is  als  er  128  kB
aanwezig is en bit 2 als  er  64  kB  aanwezig  is.  Het  is
natuurlijk gewoon uit te proberen: Voor screen 0 tot en  met
4 is maar 16 Kilobyte nodig, voor screen  5  en  6  maar  64
kilobyte en voor de rest minimaal 128. Door  bijvoorbeeld  2
op 0FAFCh te poken en dan SCREEN 8 in te typen, dan zal  dat
waarschijnlijk niet werken.  Het  is  ook  handig  voor  een
RAMdisk programma bijvoorbeeld, om de originele  waarde  van
dit adres op te slaan en er 0 ofzo neer  te  zetten  als  de
RAMdisk het VRAM benut. Dan kan ten eerste er geen data meer
verminkt worden door  een  screen  commando  en  ten  tweede
kunnen andere 'nette' programma's aan adres 0FAFCh zien  dat
het VRAM al in gebruik is.

Veel plezier ermee,

                                       Ramon van der Winkel


(Nvdr. deze technieken worden toegepast bij de  SCREEN  5/12
superimpose routine. U kunt daar dus meteen  een  toepassing
bekijken.)

    

Index

Vorige

Volgende