MILC logo

IndexVorigeVolgendeLeeg

MSX gericht programmeren
Genic Clubguide, 00-00-00


    
       M S X  G E R I C H T  P R O G R A M M E R E N
      ===============================================

TurboPascal  wordt   als  programmeertaal   door  veel  MSX- 
programmeurs  niet  echt  serieus genomen,  dit voornamelijk 
omdat  er door TurboPascal geen gebruik wordt gemaakt van de 
speciale  krachtige  eigenschappen  van  het  MSX  computer- 
systeem. TurboPascal  op een  PC kan,  en doet hetzelfde als 
TurboPascal  op een  MSX, trage  uitvoersnelheid en absoluut 
geen goede grafische ondersteuning.

Bovenstaande mag  waar zijn,  maar in TurboPascal zitten een 
aantal  functies waardoor  de programmeur  toch gebruik  kan 
maken  van  MSX  mogelijkheden.  Kennis  van  Machinetaal is 
overigens wel  een vereiste. Door op deze manier de snelheid 
van machinetaal te koppelen aan de overzichtelijke structuur 
van  TurboPascal kan een snel werkend, grafisch volledig, en 
vooral MSX waardig programma geschreven worden.

------------------------------------------------------------
absolute

addr(<variabele, functie of pointer>): pointer;

mem: array[0..$FFFF] of byte;

port: array[0..255] of byte;

bdos(func; parm);

bdos(func; parm): integer;

bdoshl(func; parm): integer;

inline(byte,byte..);
------------------------------------------------------------

Wanneer er achter de declaratie van een variabele "absolute" 
met  daarachter  een  adres  wordt  geplaatst,  dan  zal  de 
geheugen plaats waar die variabele opgeslagen wordt beginnen 
op het meegegeven adres. 

var width   : byte absolute $F3B1;

In bovenstaand  voorbeeld staat  de waarde  van de variabele 
"width"  op  adres  F3B1  hex,  op dat  adres slaat  het MSX 
systeem  de schermbreedte op. Indien nu de variabele "width" 
op bijvoorbeeld  25 wordt gezet, dan komt in het geheugen op 
adres F3B1 hex ook 25 te staan. 


Met de  variabele "mem"  wordt precies hetzelfde bereikt als 
met  "absolute", alleen  is het  nu niet mogelijk om met een 
variabele te  werken, de waarde wordt direct in het geheugen 
geplaatst. MEM is te vergelijken met PEEK en POKE samen. 

mem[$F3B1]:=25;  of  mem[$F3B1]:=width;

width:=mem[$F3B1];

In het  eerste voorbeeld wordt 25 in geheugenadres F3B1H ge- 
plaatst,  en in  het tweede  voorbeeld wordt  de inhoud  van 
geheugenadres F3B1 hex in de variabele "width" gezet.

De   variabele  "port"   is  te  vergelijken  met  de  BASIC 
commando's OUT en INP, met behulp hiervan is het mogelijk de 
MSX direct  aan te sturen. Een grondige kennis van de opbouw 
van  de computer is dan echter wel nodig, voor wie die (nog) 
niet bezit  is het  makkelijker om in machinetaal, en met de 
BIOS routines te werken. (zie verder) 

waarde:=port[$AA];

port[$AA]:=1;  of  port[$AA]:=waarde;

Het  eerste voorbeeld  leest een  byte uit poort AA hex, het 
tweede schrijft een waarde naar poort AA hex. 

Met  behulp  van de  functie "addr"  is het  mogelijk om  de 
adressen te  achterhalen waar  TurboPascal de  variabelen en 
procedures  opslaat. Dit is vooral handig om vanuit machine- 
taal routines in TurboPascal (zie verder) toch de variabelen 
en procedures te kunnen gebruiken. 

loop:=addr(print_screen);

writeln(addr(loop));

Het eerste  voorbeeld kent  het beginadres  van de procedure 
"print_screen"  toe  aan  de variabele  loop. In  het tweede 
voorbeeld  wordt het  adres van  de variabele  "loop" op het 
scherm geschreven. 


Met voorgaande  functies is  het mogelijk  meer met  het ge- 
heugen te werken dan normaal onder TurboPascal, maar daarmee 
is  er  nog  geen  echt  MSX  programma  gemaakt. Om  de MSX 
volledig  te  besturen  is het  noodzakelijk machinetaal  te 
kunnen  gebruiken binnen  TurboPascal, de procedure "inline" 
maakt dat mogelijk. 

Na "inline"  staan tussen  haakjes een  aantal getallen, ge- 
scheiden door komma's. Deze getallen zijn de machinecode, en 
kunnen  bijvoorbeeld met behulp van een assembler geschreven 
worden. De  machinecode wordt  in het  geheugen gezet, en de 
program  counter (PC) wordt gelijk gemaakt aan het adres van 
het eerste  getal. Met  andere woorden,  de getallen  vormen 
samen ‚‚n machinetaal routine die direct aangeroepen wordt. 

De  getallen mogen  direct worden  ingevoerd, maar het mogen 
ook variabelen  zijn. Nu  het mogelijk  is om machinetaal te 
gebruiken  kunnen  we  om te  beginnen twee  routines maken, 
waarin  we opzoeken  in welke slots de BIOS, en de MSX2-BIOS 
zitten, en deze daarna aanroepen. 

------------------------------------------------------------
Onderstaande staat ook als losse file (BIOS.INC) op disk.

var  regA,regBC,regDE,regHL,regF,regIX,regIY : integer;

procedure store;
begin
 inline($3a/regA/$ed/$4b/regBC/$ed/$5b/regDE/
 $2a/regHL/$dd/$2a/regIX/$fd/$2a/regIY);
end;

procedure restore;
begin
 inline($32/regA/$ed/$43/regBC/$ed/$53/regDE/
 $22/regHL/$dd/$22/regIX/$fd/$22/regIY);
end;

procedure msxbios(entry:integer);
begin
  inline(
    $F5/$C5/$D5/$E5/$DD/$E5/$FD/$E5/$3A/regA/$ED/$4B/
    regBC/$ED/$5B/regDE/$2A/regHL/$DD/$2A/entry/$FD/
    $2A/$C0/$FC/$CD/$1C/$00/$32/regA/$ED/$43/regBC/$ED/
    $53/regDE/$22/regHL/$DD/$22/regIX/$FD/$22/regIY/
    $F5/$E1/$22/regF/$AF/$32/regA+1/$32/regF+1/$FD/
    $E1/$DD/$E1/$E1/$D1/$C1/$F1/$FB)
end;

procedure msx2bios(entry:integer);
begin
  inline(
    $F5/$C5/$D5/$E5/$DD/$E5/$FD/$E5/$3A/regA/$ED/$4B/
    regBC/$ED/$5B/regDE/$2A/regHL/$DD/$2A/entry/$FD/
    $2A/$F7/$FA/$CD/$1C/$00/$32/regA/$ED/$43/regBC/$ED/
    $53/regDE/$22/regHL/$DD/$22/regIX/$FD/$22/regIY/
    $F5/$E1/$22/regF/$AF/$32/regA+1/$32/regF+1/$FD/
    $E1/$DD/$E1/$E1/$D1/$C1/$F1/$FB)
end;
------------------------------------------------------------

In de eerste regel worden variabelen gedeclareerd die gelijk 
zijn aan de registers van de Z80, voor het aanroepen van een 
routine  kunnen  deze  worden  ingevuld,  en  na  de aanroep 
gelezen.

Als  de variabelen  gevuld zijn staan de waarden nog niet in 
de  echte  registers, hiervoor  is de  routine "store",  bij 
aanroep plaatst "store" alle variabelen in de registers.

Met  de procedure "msxbios" en "msx2bios" is het mogelijk om 
elke BIOS  routine uit  te voeren, zorg er wel voor dat alle 
registers  vooraf goed zijn ingevuld, en met "store" naar de 
echte Z80 registers geschreven zijn.

Als de  BIOS routine getallen via registers terug geeft, dan 
staan  deze getallen  alleen in de echte Z80 registers, niet 
in de  variabelen. De  procedure "restore"  plaatst alle Z80 
registers  in de  variabelen, zodat deze direct te gebruiken 
zijn. Het is natuurlijk net zo gemakkelijk om de procedure's 
"store"  en   "restore"  in   de  procedures   "msxbios"  en 
"msx2bios"  te plaatsen, maar ze staan hier los omdat ze ook 
nodig zijn bij de BDOS functie aanroep.

In elke  MSX computer  met diskdrive  zit naast  een BIOS en 
MSX2BIOS  ook nog  een BDOS, deze "BIOS" zorgt ervoor dat de 
computer de diskdrives kan gebruiken. Alle MSX computers met 
diskdrive hebben  de gewone  BDOS, wie  onder MSX-DOS2 werkt 
heeft  in plaats van die gewone BDOS de nieuwe DOS2-BDOS. De 
nieuwe functies  uit die  BDOS zijn  ook te gebruiken vanuit 
TurboPascal.

------------------------------------------------------------
type st8 = string[8];

function date:st8;
var     inv  : st8;
        inv1 : st8;
begin
 bdos($2a);
 restore;
 str(lo(regDE),inv);
 if lo(regDE) < 10 then insert('0',inv,1);
 str(hi(regDE),inv1);
 if hi(regDE) < 10 then insert('0',inv1,1);
 inv:=inv+'-'+inv1+'-';
 str(regHL,inv1);
 inv:=inv+copy(inv1,3,2);
 date:=inv;
end;
-------------------------------------------------------------

Er  is ‚‚n  procedure en  twee functies  om de  BDOS aan  te 
roepen. Het makkelijkst is om gewoon met de procedure "bdos" 
te werken en alle registers via de variabelen door te geven, 
behalve het  C register, wat altijd wordt gebruikt om aan de 
geven welke functie uitgevoerd moet worden, register C wordt 
tussen haakjes achter de procedure geplaatst.

Eventueel  is   het  ook   mogelijk  de  functie  "bdos"  te 
gebruiken,  in dat geval wordt register DE als waarde van de 
functie  teruggegeven.   Het  is  ook  mogelijk  de  functie 
"bdoshl"  te gebruiken, in dat geval wordt niet register DE, 
maar register HL als waarde van de functie teruggegeven.

In  bovenstaand  voorbeeld  wordt  gebruik  gemaakt  van  de 
procedure "bdos"  om de huidige datum uit te lezen. Er wordt 
gebruik gemaakt van de BDOS functie "GET DATE". (2A hex)

GET DATE (2AH)

Parameters:  C = 2AH (_GDATE)
Results   : HL = Year 1980...2079
             D = Month (1=Jan...12=Dec)
             E = Date (1...31)
             A = Day of week (0=Sun...6=Sat)
 
 
                                               Misha van Tol

------------------------------------------------------------
LITERATUUR


Alle BDOS en 2.20 BDOS routines staan oa.in;

Programme Reference Manual 1
Programme Reference Manual 2, beide van HSH.


Alle MSX1 BIOS routines staan oa. in;

MSX-HANDBOEK voor gevorderden
Kluwer Technische Boeken
ISBN 90 201 1925 7


Alle MSX1 BIOS en MSX2 BIOS routines staan oa. in;

MSX2 BASIC met monitorgegevens
Kluwer Technische Boeken
ISBN 90 201 1961 3

Msx Computer Magazine
BIOS-tabelen


    

Index

Vorige

Volgende