Skip to content

Latest commit

 

History

History
403 lines (323 loc) · 17.9 KB

easy_bdos.md

File metadata and controls

403 lines (323 loc) · 17.9 KB
                           E A S Y   B D O S 
                                              
      
      Opm: Ik ga er in dit  artikel  van  uit  dat  de  lezer  een
           behoorlijke kennis van de BDOS bezit.
      
      Het  aansturen  van  een  diskdrive  is  een   zeer   lastig
      karweitje. Zelfs ervaren programmeurs zullen meerdere  malen
      verwensingen aan bepaalde chipfabrikanten maken tijdens  het
      schrijven  van  software  om  een  FDC   (Floppy   Diskdrive
      Controller) aan te sturen. Dat is ��n van de redenen  waarom
      de BDOS standaard in MSX zit. De BDOS maakt elke kennis  van
      FDC's overbodig voor het aansturen  van  een  diskdrive.  De
      BDOS software schept als het ware een interface van en  naar
      de gebruiker dat vele malen eenvoudiger is  dan  het  direkt
      aansturen van  de FDC.  (Nvdr: en het werkt ook nog op bijna 
      alle computers.)
      
      We zijn de ontwerpers van de BDOS dan  ook  eeuwig  dankbaar
      voor deze vriendelijke geste, maar er schort nog het ��n  en
      ander  aan  dit  'gebruikersvriendelijke'   interface.   Het
      schrijven van een goede routine om  een  file  van  disk  te
      laden is nl. niet zo eenvoudig als de BDOS  doet  vermoeden.
      Om dit te bewijzen zal ik eerst maar een voorbeeld geven van
      de meest eenvoudige methode om een file te laden.
      
      Stel we  willen  een  MoonBlaster  muziekstuk  inladen.  Een
      dergelijke file is praktisch altijd kleiner  dan  16 kB. Met
      deze kennis kan dan de volgende routine geschreven worden.
      
      LD_MBM: LD   C,15
              LD   DE,FCB
              CALL &HF37D          ; Open file om eruit te lezen
              INC  A               ; If A=255, then error
              JR   Z,NO_OK         ; Fout tijdens openen file
              LD   HL,0
              LD   (FCB+12),HL     ; Zet start(lees)blok op 0
              INC  HL
              LD   (FCB+14),HL     ; Zet recordlengte op 1
              LD   C,26
              LD   DE,MUSADR
              CALL &HF37D          ; Leesadres van file is MUSADR
              LD   C,39
              LD   DE,FCB
              LD   HL,&H4000       ; Lees max. 16kB
              CALL &HF37D          ; Lees blok
              DEC  A               ; A=1, then error
              JR   NZ,NO_OK
      OK:          :
                   :
              RET
      
      NO_OK:       :
                   :
              RET
      
      FCB:    DB   0
              DM   "MB_MUSIC","MBM"
              DW   0,0
              DW   0,0,0,0,0,0,0,0
              DW   0,0
              DB   0
      
      Na   de   bestudering   van   dit   'programma'   valt    de
      foutafhandeling  van  de  feitelijke  laadaktie  (C=39)  op.
      Indien de BDOS hier een foutmelding geeft  is  de  laadaktie
      goed? Dit komt omdat we probeerden 16 kB in te laden terwijl
      we weten dat de file per  definitie  kleiner  dan  16kB  is.
      Zelfs de BDOS  zal  niet  voorbij  het  eind  van  een  file
      proberen te lezen en geeft dientengevolge  een  foutmelding.
      
      Deze routine rammelt werkelijk aan alle kanten en  kan  veel
      beter geschreven worden. Dit kan door de recordlengte gelijk
      te maken aan de bestandslengte. Na het openen  van  de  file
      staat  de  bestandslengte  in  het  FCB.  Door  deze  in  de
      recordlengte te kopi�ren en daarna  bij  de  laadaktie  niet
      16 kB in te lezen, maar 1 record gaat het wel goed.
      
      Dit soort routines heeft verder als nadeel dat  ze  absoluut
      niet universeel inzetbaar zijn. Voor het laden van muziek en
      andere data gaat het wel, maar  om  graphics  behoorlijk  te
      laden moet meer uit de kast gehaald worden. Het  zou  er  op
      neerkomen dat er voor elke soort te laden  file  een  aparte
      routine  zou  moeten  komen  met  eigen  error  handling.  U
      begrijpt, dit levert enorme listings  op  met  routines  die
      toch heel erg veel op elkaar lijken.
      
      Wat ik hiermee probeer aan te  tonen  is  dat  de  BDOS  een
      uiterst noodzakelijk stukje software is, maar dat er bij het
      gebruik toch nog wat haken en  ogen  aan  zitten.  Naast  de
      normale  BDOS  error  handling  (BDOS  uitvoer  via  het   A
      register) is er nl. ook nog de error pointer  hook  die  bij
      ernstige diskdrive fouten aangeroepen  wordt.  Probeer  maar
      eens een file te cre�ren met  de  diskdrive  protect  schuif
      open. Uw machinetaal programma zal zonder pardon naar  BASIC
      terugkeren (een verbijsterde programmeur achterlatend).
      
      
                K A N   H E T   E E N V O U D I G E R ? 
      
      Natuurlijk, is dan mijn antwoord. Praktisch is gebleken  dat
      het goede gebruik van de BDOS helemaal niet zo eenvoudig  is
      als de makers doen geloven. Wat we nodig hebben is  software
      die een nieuw interface tussen de diskdrive en de  gebruiker
      vormt waardoor de gebruiker absoluut geen kennis van de BDOS
      meer nodig heeft. Het enige waar de gebruiker  zich  nog  om
      hoeft te bekommeren is dat hij ervoor  moet  zorgen  dat  de
      gegevens op de juiste plaats terecht komen.
      
      Laten we eerst maar eens gaan kijken wat deze software  moet
      doen. Praktisch blijkt dat 95% van alle BDOS gebruik beperkt
      blijft tot het laden of  bewaren  van  gegevens.  Het  heeft
      praktisch dus ook  weinig  zin  om  onze  nieuwe  besturings
      software iets anders te kunnen laten doen.
      
      Foutmeldings uitvoer van de routines kan  beter  met  de  Cy
      flag gedaan worden dan met het A  register  (zoals  de  BDOS
      doet). Dit  komt  omdat  via  de  Cy  flag  onmiddelijk  een
      spronginstruktie  gedaan  kan  worden  terwijl  met  het   A
      register eerst een flag zet instruktie gedaan moet worden.
      
      
                  E A S Y   B D O S   F U N C T I E S 
      
      De nu te beschrijven routines zijn terug  te  vinden  in  de
      file  EASYBDOS.ASC  die  op  deze  disk  te  vinden  is.  De
      verzameling routines heet de fileshell omdat ze nl. als  een
      schil om de BDOS heen  zitten.
      
      De routines laten nog te wensen over. Zo kan er maar 1  file
      tegelijkertijd open staan, terwijl de BDOS er veel meer  kan
      hebben. Het toevoegen van een dergelijke optie zou  voor  de
      gemiddelde programmeur echter  weinig  problemen  op  moeten
      leveren. Ik kan me  voorstellen  dat  FOPEN  en  FCREAT  een
      nummer in het A register teruggeven die dan bij resp. FBLKRD
      en FBLKWR weer meegegeven moeten worden.  Elk  nummer  staat
      dan voor een bepaald FCB waarvan het adres dan wel  door  de
      routines berekent kan worden. Let er daarbij wel op  dat  de
      variabele FSTAT dan niet meer naar behoren funktioneert, dus
      ook dit moet dan aangepast worden.
      
      Een  andere beperking  is die dat de maximale lengte van een 
      te  lezen  file  65535  bytes is.  Deze beperking  is echter 
      redelijk  eenvoudig  op  te  lossen.  Het  gebruik van  deze 
      routines is in eerste instantie ook alleen maar bedoeld voor 
      demo's en kleine utilities. Voor het wat serieuzere werk zal 
      ik deze twee beperkingen er nog wel eens uit halen.
      
      
      F I L E S H E L L   I N S T A L L 
      Name: FINSTL
      In  : A, (see BIOS routine &H24)
      Out : Cy, on error
      
      Deze   routine   installeert   de   software.   Naast    het
      initialiseren  van  enkele  systeemvariabelen   buigt   deze
      routine de BDOS pointer error hook af zodat bij een ernstige
      fout niet meteen naar BASIC gesprongen wordt.  Elke  aanroep
      die vanaf nu rechtstreeks naar de BDOS  gemaakt  wordt,  zal
      afgevangen worden zodat de error handling ook dan actief is.
      A moet bij invoer de slot en  subslot  waarden  van  page  1
      bevatten. Het programma zou dit  ook  zelf  wel  uit  kunnen
      zoeken, maar dat gaat hier wat ver.
      
      Heb je bv. de BASIC ROM nog 'aan' staan, dan is  de  aanroep
      als volgt:
      
      LD   A,(&HFCC1)              ; Slot en subslot van MAIN-ROM
      CALL FINSTL
      RET  C                       ; Error
      
      Is de BASIC ROM vervangen  door  RAM  geheugen,  dan  is  de
      aanroep:
      
      LD   A,(&HF342)              ; Slot en subslot van MAIN-RAM
      CALL FINSTL
      RET  C
      
      Indien  FINSTL  niet  uitgevoerd  wordt  zal   elke   andere
      fileshell routine aanroep onmiddelijk een foutmelding  terug
      geven.
      
      
      F I L E S H E L L   R E S E T 
      Name: FRESET
      In  : nothing
      Out : Cy, on error
      
      Met FRESET kan  de  fileshell  software  weer  van  de  BDOS
      verwijderd worden. De BDOS wordt  niet  langer  afgetapt  en
      error handling wordt niet meer gedaan.  Indien  er  nog  een
      schrijf  file  open  staat  wordt  deze  eerst   automatisch
      gesloten.
      
      
      O P E N   F I L E 
      Name: FOPEN
      In : HL, filename address
      OUt: Cy, on error
      
      FOPEN moet aangeroepen worden wanneer een file gelezen  moet
      worden (net als bij de BDOS overigens). HL moet  bij  invoer
      wijzen naar de filenaam. Dit ziet er als volgt uit:
      
              LD   HL,MBMNME
              CALL FOPEN
              RET  C
                :
                :
      
      MBMNME: DM   "MB_MUSIC","MBM"
      
      De filenaam MOET 11 karakters lang zijn. Indien de naam niet
      8 karakters lang is  moet  de  naam  met  spaties  aangevuld
      worden. Ditzelfde geldt ook voor de extensie.
      
      
      F I L E B L O C K   R E A D 
      Name: FBLKRD
      In  : DE, blocklength
            HL, load address
      Out : Cy, on error
            A , ="r" if file is loaded.
      
      FBLKRD leest een blok  van  een  geopende  file.  Indien  de
      blocklengte groter is dan de (resterende) filelengte past de
      routine deze automatisch aan. HL  mag  alle  waarden  hebben
      behalve het adresgebied tussen &H4000 en  &H8000  (page  1).
      Deze beperking wordt door het MSX systeem opgelegt.  Sommige
      programmeurs schijnen dit nog steeds niet te  weten.  Indien
      de file helemaal geladen is staat bij uitvoer  het  karakter
      "r" in register A (De r van 'ready'). Willen we nu een  file
      laden die groter is dan 16 kB in blokken van 16 kB dan  gaat
      dat bv. als volgt:
      
              LD   A,1
      LOOP:   OUT  (&HFE),A        ; Zet memory mapper
              PUSH AF
              LD   DE,&H4000       ; Lees max. 16kB blok
              LD   HL,&H8000       ; Vanaf adres &H8000
              CALL FBLKRD
              EX   AF,AF           ; Bewaar uitvoer
              POP  AF
              INC  A               ; Volgende memory map. pagina
              EX   AF,AF           ; Haal uitvoer weer op
              RET  C               ; Error
              CP   "r"             ; Klaar met laden
              RET  Z
              EX   AF,AF
              JR   LOOP
      
      
      C R E A T E   F I L E 
      Name: FCREAT
      In  : HL, filename address (See FOPEN)
      Out : Cy, on error
      
      Met FCREAT kan een nieuwe file gemaakt worden (net  als  bij
      de BDOS).
      
      
      F I L E B L O C K   W R I T E 
      Name: FBLKWR
      In  : DE, blocklength
            HL, startaddress
      Out : Cy, on error
      
      Deze routine werkt in principe net  zo  als  de  block  laad
      routine, met het verschil dat de file  automatisch  gesloten
      wordt na het optreden van een foutmelding.
      
              LD   DE,&H1000       ; Schrijf 4kB
              LD   HL,&H8000       ; Vanaf adres &H8000
              CALL FBLKWR
              RET  C               ; Fout opgetreden
              LD   DE,&H1000
              LD   HL,&HB000
              CALL FBLKWR
              RET  C
              CALL FCLOSE          ; Sluit file indien klaar
              XOR  A               ; Maak Cy laag
              RET
      
      
      C L O S E   F I L E 
      Name: FCLOSE
      In  : Nothing
      Out : Nothing
      
      Deze routine doet niets meer dan het aanroepen van het  BDOS
      close commando en is nodig om een net aangemaakte file af te
      sluiten.
      
      
      C H A N G E   D I S C 
      Name: CHNDSK
      In  : A
      Out : Nothing
      
      Change disk  is een  extraatje. Indien  A bij  aanroep 0  is 
      wordt  de boodschap "Insert source disk" op het scherm gezet 
      en in alle andere gevallen "Insert destination disk". Daarna 
      wordt gewacht tot de spatiebalk ingedrukt wordt. Indien twee 
      keer achter  elkaar een source disk aangevraagd wordt zal de 
      routine meteen terug springen zonder een tekst op het scherm 
      te zetten.
      
      
      De nu volgende routines zijn niet voor de gebruiker bedoeld,
      maar ik noem ze toch maar even.
      
      INTOFF:
      Deze routine zet de VDP interrupt (50/60 Hz) generator  uit.
      Hierdoor gaat het laden (vooral op trage Sony's) sneller.
      
      INTON:
      Laat zich raden.
      
      FBDOS:
      Dit is de routine waar elke  BDOS  aanroep  na  aanroep  van
      FINSTL naar toe springt.
      
      ERRCDE:
      Dit is de routine waar naartoe gesprongen wordt bij een BDOS
      error handling via de pointer hook. Deze routine  heeft  een
      'Abort, Retry' optie  ingebouwd  en  voorkomt  dat  bij  een
      dergelijke fout naar  BASIC  gesprongen  wordt.  De  routine
      wordt bv. aangeroepen wanneer de disk uit de  drive  gehaald
      wordt tijdens bv. een laadaktie.
      
                          !!! WAARSCHUWING !!!
      
      Net als enkele belankrijke  variabelen  (vanaf  PG1SET)  mag
      deze routine niet op page 1 gemapt worden. Zet deze  routine
      bij voorkeur op page 3 (vanaf &HC000).
      
      Bij  een abort  wordt de stack hersteld en worden de slot en 
      subslot instellingen  van page 1 hersteld naar de waarde die 
      bij FINSTL opgegeven is. Dit moet omdat de BDOS ROM zich nl. 
      op PAGE 1 nesteld tijdens disk akties. Hierna wordt de stack 
      hersteld  en geeft de routine een standaard BDOS error terug 
      (A=1).  Met  deze  methode  wordt  terugspringen  naar BASIC 
      voorkomen.
      
      Bij een Retry wordt het C register  1  gemaakt  waardoor  de
      BDOS de disk aktie zal proberen te herhalen!
      
      PRTERR:
      Deze routine wordt gebruikt door alle fileshell routines  om
      foutmeldingen op het scherm te zetten. Invoer gaat via het A
      register waar het foutnummer in staat.  Deze  methode  zorgt
      ervoor  dat  de  feitelijke  fileshell  routines  korter  en
      overzichtelijker worden.
      
      
      Als  laatste  zijn  er  dan  nog  de  fileshell  variabelen.
      Vanaf PG1SET mogen de variabelen niet meer op PAGE 1  gemapt
      zijn. Zet deze dus het liefst vanaf adres &HC000.
      
      FSTAT:
      Hierin staat de fileshell status. De opbouw is als volgt:
      Bit 0, hoog, dan is FINSTL uitgevoerd (fileshell aktief)
      Bit 1, hoog, dan is de huidige file open voor lezen
      Bit 2, hoog, dan is de huidige file open voor schrijven
      (Bit 1 en 2 kunnen dus nooit gelijktijdig hoog zijn)
      
      CURDRV:
      Huidige drive.
      255, dan is CHNDSK nog nooit aangeroepen
      0  , dan is de huidige disk de 'source disc'
      1  , dan is de huidige disk de 'desination disc'
      
      FLELEN:
      Het aantal nog te LEZEN bytes van een open file.
      
      _##ERR:
      Bewaarplaats van de oude BDOS error double pointer
      
      OLDDOS:
      Bewaarplaats van oude BDOS aanroep hook
      
      PG1SET:
      Bewaarplaats van bij FINSTL opgegeven slot instellingen
      
      SP_SAV:
      Bewaarplaats voor StackPointer register
      
      FCB:
      Het FCB
      
      
      Dat  is  het dan.  Probeer de  listing eens  uit. De  minste 
      problemen  zullen  optreden  als  de complete  listing vanaf 
      &HC000 begint.  Lees ook eens het artikel over de BDOS error 
      handling  om wat  gedetailleerdere informatie te krijgen. Ik 
      zou   zeggen,   klieder  naar   hartelust  in   het  gegeven 
      programmeervoer en  haal de twee eerder genoemde beperkingen 
      er  zelf  eens  uit. Let  vooral op  hoe snel  het met  deze 
      routines  mogelijk is  om complete  laad of save routines in 
      elkaar te gooien en hoe klein deze dan zijn. Tot de volgende 
      preek.
      
                                                 Alex van der Wal