Skip to content

Latest commit

 

History

History
497 lines (384 loc) · 22.7 KB

nogmaals_bdos_routines.md

File metadata and controls

497 lines (384 loc) · 22.7 KB
              N O G M A A L S   B D O S   R O U T I N E S 
      
          V O O R   P R E T T I G E   F I L E H A N D L I N G 
                                                               
      
      Op Sunrise  Special #4 staan twee artikelen met bijbehorende 
      listing  van mijn  hand over interfacing met de BDOS en disk 
      foutafhandeling onder  DOS1. Geen  commentaar was mijn deel. 
      Ik bedoel dat niemand die op dat moment even wat beter op de 
      hoogte  was dan  mijzelf zich goed genoeg voelde om mij mede 
      te delen dat er wat gevaren aan de routines kleven die ik in 
      de  artikelen  niet  genoemd  heb.  Ik  doel daarbij  op het 
      wisselen van  diskettes tijdens  het lezen  en schrijven van 
      komplete   files.  Lees   ook  het   artikel  op  de  vorige 
      submenu-optie.
      
      Ik heb de eerder gepubliceerde routines herschreven. Dat heb
      ik gedaan om de error handler te debuggen en omdat ik  tegen
      de beperkingen  van  de  routines  aangelopen  ben.  Om  het
      geheugen even op te frissen:
      
      - Er kon maar ��n file tegelijkertijd open zijn
      - De maximale handelbare filelengte was 64 kB
      
      Beide beperkingen zijn voor demo's en kleine utilities  niet
      erg vervelend, maar  ik  liep  er  tegen  aan  toen  ik  wat
      ingewikkelde file-akties moest uitvoeren op  meerdere  files
      tegelijkertijd. Het was dus tijd om het  nog  eens  over  te
      doen waarbij  beide  beperkingen  tot  het  verleden  zouden
      horen.
      
      Ik heb  mij  bij  de  ontwikkeling  van  de  routines  laten
      inspireren  door  de  ANSI-C  standaard.  De  namen  van  de
      routines  kloppen  niet  met   deze   standaard,   maar   de
      mogelijkheden komen redelijk overeen.
      
      Het doel van de routines is om 'dom' lees en schrijfwerk van
      en naar diskettes,  harddisks en wat je nog maar  meer  kunt
      verzinnen wat eenvoudiger te maken. Op zich is het interface
      van de BDOS naar de gebuiker goed (ook al is het al  zo  oud
      dat Fred Flintstone het zich nog goed kan herinneren),  maar
      tijdens praktisch gebruik stoot je toch  op  wat  zaken  die
      extra aandacht verdienen.
      
      Probeer je bv. een file van 1234 bytes in te lezen door  een 
      random access block read van &H4000 bytes te doen  dan  gaat 
      dat wel goed, maar de call komt terug met de BDOS error code 
      A = 1. Wat moet je daar nu mee? Is er wat fout gegaan of is
      dit juist  een teken  dat het  goed ging?  Als je er bij een 
      blockread  voor zorgt  dat er  niet voorbij  het End Of File 
      wordt gelezen,  dan krijg  je de  foutmelding ook niet en is 
      het 'probleem' opgelost. Zo zijn er nog veel meer dingen die 
      door   wat  simpele  testjes  te  doen,  het  leven  van  de 
      programmeur wat aangenamer kunnen maken.
      
      "Heeft die  sukkel nu eindelijk DOS2 al eens ontdekt?", hoor 
      ik  je zeggen.  Welnu, ik ben een waanzinnig voorstander van 
      DOS2, maar  ik vind het toch wat ver gaan om bij bv. spellen 
      en  demo's (die  niet uitsluitend  voor de  turbo R zijn) te 
      gaan eisen  dat je  DOS2 moet hebben. Daarom werken ook deze 
      routines   nog  gewoon   met  FCB's  en  zijn  file-handles, 
      environment strings en sub-directories niet ge�mplementeerd. 
      Dat wil  natuurlijk niet zeggen dat deze routines niet onder 
      DOS2 draaien.
      
      
                         D E   F U N K T I E S 
      
      Ik noem hier nu eerst even de funkties met hun aanroep  etc.
      waarna ik wat dieper op dit nieuwe ontwerp zal ingaan.
      
      ; BDOS fileshell routines for secure file loading and saving
      ; File: BDOSR2.ASM  V3.00
      ; By: Savage '94 (Fuzzy Logic)  Last update: 29-07-94
      
      ENASLT: EQU   &H24
      PRINTC: EQU   &HA2
      F##ERR: EQU   &HF323 ; Double pointer to error routine
      BDOS:   EQU   &HF37D
      VDPBF1: EQU   &HF3DF
      VDPBF2: EQU   &HFFE7-8
      
      ; Jumpvectors
              JP    FINSTL
              JP    FRESET
              JP    FOPEN
              JP    FBLKRD
              JP    FCREAT
              JP    FBLKWR
              JP    FCLOSE
              JP    FSEEK
              JP    GETDIR
              JP    CHNDSK
              JP    DRVSTP
      
      ; Install BDOS fileshell
      ; In : A  (See BIOS rout 24H)
      ;      A must contain the settings for PAGE 1 (SLOT/SUBSLOT)
      ; Out: Cy, on error
      FINSTL:
      
      Deze routine moet worden aangeroepen voordat van  de  andere
      routines gebruik gemaakt kan worden. In tegenstelling tot de
      oude situatie wordt de BDOS entry nu  niet  meer  afgebogen.
      Het aanroepen van FINSTL: heeft verder geen gevolgen voor de
      BDOS en andere  routines  zullen  dus  geen  last  van  deze
      installatie hebben.
      
      Bij  invoer  moeten  in  register  A  de  slot  en   subslot
      instellingen van  PAGE  1  staan.  Dit  is  nodig  omdat  de
      DISK-ROM tijdens de error handler vrolijk op PAGE  1  aktief
      staat en die moet door  de  error  handler  weer  verwijderd
      worden.
      
      
      ; Reset BDOS fileshell
      ; Out: Cy, on error
      FRESET:
      
      Deze routine moet als laatste aangeroepen worden voordat met
      iets anders begonnen wordt. In tegenstelling tot bij de oude
      situatie is het gebruik van de BDOS door andere  programma's
      die niet van deze routines gebruik maken tussen een  aanroep
      naar  FINSTL:  en  FRESET:  niet  langer   aan   beperkingen
      gebonden. In de oude situatie werd een eventueel openstaande
      file nog even gesloten. Nu wordt dat niet meer gedaan,  maar
      wordt alleen een waarschuwing gegeven  dat  er  nog  file(s)
      open staan.
      
      
      ;Set new 'disk error' handler and 'change disk' handler
      INIERR:
      
      Deze routine wordt door de diskroutines aangeroepen voor  ze
      daadwerkelijk fysiek met de  diskdrive  aan  de  slag  gaan.
      Binnen deze funktie worden  de  BDOS  error  handler  en  de
      'change drive' hook van de BDOS  afgebogen  naar  een  eigen
      routine. Nu hoor ik mensen al weer klagen dat dit  een  call
      naar de BDOS alleen maar trager maakt en die  mensen  hebben
      daarin wel gelijk. Deze vertraging is echter  zo  onmeetbaar
      klein dat het de moeite van de overpeinzing niet waard is.
      
      
      ;Reset disk handlers
      EXIERR:
      
      Deze routine wordt na een fysieke  aktie  met  de  diskdrive
      aangeroepen om de oude situatie van de BDOS error handler en
      drive hook te herstellen. Zodoende  zijn  deze  entries  bv.
      tussen een aanroep naar FOPEN: en FBLKRD:  niet  naar  eigen
      routines afgebogen.
      
      
      ; Open a file
      ; In : IX, Pointer to FCB
      ;      HL, Pointer to filenamestring (11 or 13 bytes long)
      ; Out: Cy, on error
      FOPEN:
      
      Bij aanroep van FOPEN: en FCREAT: hoeft  van  het  37  bytes
      lange FCB bij invoer niets ingevuld te zijn. In assembly kan
      dit FCB dus als volgt gedefinieerd worden.
      
      FCB:   DS   37
      
      In de filenamestring van 11 of 13 bytes  staat  de  filenaam
      van de file waar de aktie  op  uitgevoerd  moet  worden.  In
      assembly kan deze eenvoudig als volgt gedefinieerd worden.
      
      FLNAM1: DM   "filename","ext"
      FLNAM2: DM   "A:filename","ext"
      FLNAM2: DM   "b:FiLeNaMe","ExT"
      
      In het eerste geval wordt de huidige drive (0)  in  het  FCB
      ingevult worden. In het tweede geval wordt  specifiek  drive
      A: (1) in het FCB ingevuld en dat geldt ook voor B: (2). Een
      ongeldige driveletter resulteert in een "File not found"  of
      "Cannot create" error bij resp. FOPEN: en FCREAT: Het  maakt
      niet uit of  de  string  in  kleine  of  hoofdletters  wordt
      ingevuld.
      
      
      ; Read a block from the current fileposition
      ; In : IX, Pointer to valid FCB
      ;      DE, Blocklength
      ;      HL, Loadaddress (not between 0x4000 and 0x7FFF)
      ; Out: Cy, on physical load error
      ;      else, HL = the number of bytes actually read
      FBLKRD:
      
      FBLKRD: zet zelf het DMA adres en controleert daarna  of  de
      blokgrootte wel kan, door deze te vergelijken met de afstand
      tussen de filelengte en het random record nummer. Indien het
      blok niet past wordt de blokgrootte automatisch aangepast.
      
      
      ; Create a file
      ; In : IX, Pointer to FCB
      ;      HL, Pointer to filenamestring (11 or 13 bytes)
      ; Out: Cy, on error
      FCREAT:
      
      Zie ook FOPEN:
      
      
      ; Write fileblock
      ; In : IX, Pointer to valid FCB
      ;      DE, Blocklength
      ;      HL, Startaddress
      ; Out: Cy, on error (File will be closed and deleted)
      FBLKWR:
      
      De enige situatie waarin deze routine met een Cy terug  komt
      is als de gebruiker een (A)bort heeft  gegeven,  of  als  de
      disk vol is.
      
      
      ; Close file
      ; In : IX, Pointer to FCB
      ; Out: -
      FCLOSE:
      
      Alleen  files  waarin  geschreven  is  MOETEN  met   FCLOSE:
      afgesloten te worden.
      
      
      ; Fseek places the fileptr (random record number) on a
      ; specified position
      ; In : IX, Pointer to a valid FCB
      ;      HLDE, 32-bit offset value (HL = HIword)
      ;      A, 0 = Seek from the beginning of the file
      ;         1 = Seek from the current position (curr_pos +
      ,                                             offset)
      ;         2 = Seek from EOF (EOF - offset)
      ; Out: Cy, if the new offset is beyond EOF or A has an
      ;          invalid value
      FSEEK:
      
      FSEEK: controleert of de opgegeven offset wel binnen de file
      ligt en verandert (indien  dit  het  geval  is)  het  random
      record number in het opgegeven FCB. De routine behandelt  de
      ingevoerde offset altijd als een positief  getal.  Negatieve
      offsets leveren dus (meestal) een error op.
      
      
      ; Read dir from disk
      ; In : IX, Pointer to FCB
      ;      DE, Buffer for dir. (112*32+1 bytes)
      ;      HL, Directory search mask address
      ; Out: Cy, HI then no files found
      GETDIR:
      
      Vanaf register DE zal  de  directory  van  de  disk  in  het
      geheugen staan. Elke entry is 32 bytes lang en het einde kan
      gevonden worden door te checken op een filenaam die  met  de
      waarde 255 begint.
      
      
      ; CHNDSK Set new drive
      ;        Request for same drive as current one is ignored !!
      ; In: A, drive number (0=A: 1=B: etc.)
      CHNDSK:
      
      Zie ook de verklarende tekst verderop.
      
      
      ; Stop the diskdrive motor
      DRVSTP:
      
      Zie ook de verklarende tekst verderop
      
      
      ; BDOS error handler [system routine]
      ; In: nothing
      ; Out: nothing
      DSERPT: DW    ERRCDE          ;Pointer to error code
      ERRCDE:
      
      
      ; Standard disk error handler
      ; Request Abort or Retry input from the user
      ABORET:
      
      ; 5 byte disk error hook
      ; Out: A, "a" then abort disk action
      ;         "r" then retry last disk action
      ; Remark: This hook can be used to include a customized
      ;         error handler
      H.DERR: JP    ABORET
              DW    0
      
      
      ; Change disk query (hooked on &HF24F)
      ; [BDOS system routine]
      ; In : A, driveletter (in ASCII)
      CHDSKQ:
      
      Deze routine moet het terugkeeradres van de aanroepende CALL
      van de stack POPpen (de tweede POP AF in de listing)  om  te
      voorkomen dat de BDOS ook nog eens een tekst print.
      
       - Deze tekst wordt vervolgd in de volgende submenu-optie -
      
      
      
              - Dit is het tweede gedeelte van de tekst -
      
                        V E R V O L G   B D O S 
                                                 
      
                     D E   A A N P A S S I N G E N 
      
      Een hele belangrijke aanpassing vind ik  het  feit  dat  het
      BDOS  entry  point  of  &HF3DF  niet  langer  direkt   wordt
      afgetapt. Hierdoor zullen andere routines die niet  van  het
      bestaan van deze routines  afweten  er  ook  geen  last  van
      hebben.  Het  lijkt  mij  dat  deze  aanpassing  vooral   de
      betrouwbaarheid verhoogt. Daarnaast  worden  de  BDOS  error
      handler en de 'change drive' hook per funktie  ge�nstalleerd
      en aan het eind weer verwijderd. Samengevat is het hele BDOS
      systeem dus alleen afgetapt tijdens de executie van ��n  van
      deze routines. Dit is erg belangrijk als je  tussendoor  nog
      andere programma's hebt die ook van de BDOS  gebruik  maken,
      maar niet van deze routines.
      
      
                          L O S S E   F C B S 
      
      De andere belangrijke aanpassing is  het  feit  dat  nu  een
      eigen FCB aan de routines moet worden meegegeven. Dat  lijkt
      op het eerste gezicht een  nadeel  (meer  invoerparameters),
      maar het betekent wel dat er nu eenvoudig met meerdere files
      tegelijkertijd gewerkt kan worden.
      
      
                  M A X   F I L E L E N G T E   4 G B 
      
      Het feit dat de max. filelengte  waar  nu  mee  gewerkt  kan
      worden 4GB is, lijkt op het eerste  gezicht  overbodig.  Dat
      verandert echter op het moment dat je n�t eventjes wat  meer
      dan 64kB wilt saven. De oude routines laten je dan  hopeloos
      in de steek.
      
      
                  R A N D O M   F I L E   A C C E S S 
      
      Random file access is HEEL grappig. Wat sommige mensen  niet
      weten is dat random access op files niet alleen betekent dat
      je zomaar overal binnen de bestaande file mag  beginnen  met
      lezen of schrijven, maar dat er op een  random  access  file
      zowel lees als schrijfakties uitgevoerd mogen  worden.  Open
      bv,  een  bestaande  file  met  FOPEN:  en  niemand  zal  je
      weerhouden om als eerste aktie met FBLKWR: een blok geheugen
      in deze file te dumpen. Volkomen legaal, erg grappig en  (op
      PC's althans) een veel gebruikte methode om een harddisk als
      virtueel geheugen te gebruiken.
      
      
                   D E   R O U T I N E   F S E E K : 
      
      FSEEK: is een routine die in  ANSI-C  ongewijzigd  hetzelfde
      is. Het maakt het verplaatsen van het Random  Record  Number
      (ook  wel  filepointer  genoemd)  even  eenvoudig  als   het
      wijzigen van het DMA adres. Het nut blijkt bij een nog  door
      mij uit te brengen cruncher waarbij  ik  nadat  de  komplete
      file gecrunched en weggeschreven is, nog een header aan  het
      begin van de file moet invullen  waar  al  wel  ruimte  voor
      gereserveerd is.
      
      
                  D E   R O U T I N E   C H N D S K : 
      
      De  routine  CHNDSK:  in  de  oude  routines   is   volledig
      incompatible met de BDOS. Dat betekent  dat  een  diskwissel
      met deze routine niet aan de BDOS wordt doorgegeven en  vice
      versa. Nu is CHNDSK gewoon een aanroep van BDOS  funktie  14
      en werkt het wel goed.
      
      Hierbij moet opgemerkt worden dat  deze  BDOS  funktie  niet
      direkt bij aanroep om een  nieuwe  drivenummer  vraagt.  Dat
      gebeurt pas bij de volgende aktie op die drive. Let hier een
      beetje op i.v.m. spellen waar je niet te  pas  en  te  onpas
      change disk meldingen wilt hebben. Je kunt het dan beter  op
      de oude manier doen waarbij  het  drivenummer  in  de  FCB's
      altijd 0 is.
      
      Vb:
      
      ; Stel de huidige drive is A:
                LD   A,(&HFCC1)     ;BASIC ROM aktief
                CALL FINSTL
      
                LD   IX,FCB1
                LD   HL,FLNAM1
                CALL FOPEN          ;Open TEST.DAT op A:
                JP   C,FRESET       ;Sukkel voor de computer !!
      
                LD   A,1            ;Drive B: !!! (0 = A: etc.)
                CALL CHNDSK
      
                LD   IX,FCB2
                LD   HL,FLNAM2
                CALL FCREAT         ;Create TEST.CPY op B:
                JP   C,FRESET       ;Nog meer sukkels
                CALL FCLOSE
                JP   FRESET         ;Wat een enorme file nietwaar?
      
      FCB1:     DS   37             ;File op drive A:
      FCB2:     DS   37             ;File op drive B:
      
      FLNAM1:   DM   "a:test    ","dat"
      FLNAM2:   DM   "b:test    ","cpy"
      
      De call naar CHNDSK: heeft niet tot gevolg  dat  de  melding
      "Insert disk for drive ..." in beeld komt. Dat  gebeurt  pas
      binnen FCREAT:.  Wordt  dit  'programma'  twee  keer  achter
      elkaar opgestart dan wordt de tweede keer eerst om drive  A:
      gevraagd omdat tijdens het verlaten van het programma  drive
      B: nog ingesteld is.
      
      Deze manier van drivewisseling  is  echter  erg  leuk  omdat
      mensen met twee drives geen melding  op  hun  scherm  zullen
      krijgen omdat er gewoon  van  twee  drives  gebruik  gemaakt
      wordt. Deze routine is eenvoudig uit te breiden tot een (te)
      eenvoudig kopieerprogramma. Doordat de BDOS nu  konstant  op
      de hoogte is van diskwisselingen, mag WEL van disk gewisseld
      worden tijdens lees- en schrijfakties. De  totale  leesaktie
      moet natuurlijk wel op dezelfde disk  uitgevoerd  worden  en
      dat laatste geldt natuurlijk ook voor de schrijfaktie.
      
      
                  D E   R O U T I N E   D R V S T P : 
      
      DRVSTP: laat de drivemotor stoppen.  Hier  zijn  in  theorie
      meerdere manieren voor. Ikzelf heb lange tijd de entry in de
      BDOS zelf gebruikt omdat die onmiddellijk resultaat oplevert
      en relatief snel is. Meneer Stefan  Boer  deelde  me  laatst
      echter mede dat dit niet op alle MSX'en werkt  (zucht,  daar
      gaan we weer).  Het  blijkt  dat  bepaalde  knutselaars  een
      afwijkende DISK-ROM hebben waarbij die entry  op  een  ander
      adres terecht is gekomen. Ik ben nog nooit zo'n  ding  tegen
      het lijf gelopen, maar gezien het feit dat  veiligheid  voor
      alles gaat heb ik de routine dus maar weggeknikkerd.
      
      De vervanging die simpelweg 255 keer &HFD9F aanroept  is  de
      oudste oplossing om  de  drivemotor  te  laten  stoppen.  De
      andere methode waarbij eerst de 'motor delay counter'  op  1
      wordt gezet waarna eenmalig &HFD9F wordt aangeroepen  blijkt
      volgens sommige bronnen ook niet altijd te werken en dus heb
      ik ook die voorlopig overboord gezet.
      
      Er  is  mij  nu  wel  op  het  hart  gedrukt   dat   de   nu
      ge�mplementeerde routine de beste is omdat hij op ALLE  MSX-
      en werkt, maar ik heb um op mijn  SONY  eens  aan  het  werk
      gezet. Disassemblering van de routine op  &HFD9F  leert  mij
      dat  er  op  een  SONY  helemaal  geen  drive   stop   wordt
      aangeroepen en dat de drive volledig automatisch stopt  (dat
      was echter geen  nieuws).  Op  een  SONY  is  het  255  keer
      aanroepen  van  &HFD9F  dus  niets  meer   dan   een   domme
      vertraging. Kan iemand mij dan misschien vertellen wat er in
      hemelsnaam op een Philips  of  turbo R  gebeurt,  want  deze
      drivestop  lijkt me  een beetje  onzinnig. [Op  een turbo  R 
      stopt  de  drive  ook  automatisch,  alleen  op een  (!#$%&) 
      Philips is het �berhaupt nodig om de drive stop te zetten.]
      
      
               I N T E R R U P T S   A A N   E N   U I T 
      
      Tijdens een BDOS aanroep  bij  de  oude  routines  wordt  de
      V_BLANK interrupt volledig uitgezet. Dat  was  innertijd  om
      mensen die nog steeds een trage DISK-ROM in hun SONY  hebben
      van enige snelheid te voorzien. Nu zit dit er niet  meer  in
      om interruptproblemen bij bv. een aanroep naar BIOS  funktie
      &H9F te voorkomen.
      
      
                           T E N S L O T T E 
      
      Ik heb deze routines al redelijk stevig getest en ik heb tot
      op  dit  moment  nog  geen   gekke   onverklaarbare   dingen
      meegemaakt. Het aantal vernielde diskjes is ook  0,  en  dat
      blijft  hopelijk  ook   zo,   zolang   een   komplete   file
      schrijfaktie maar op ��n en dezelfde disk wordt  uitgevoerd.
      Diskwisselingen die hier tussendoor komen mogen dus wel  als
      je gebruik maakt van de 'change drive' routine omdat de BDOS
      er dan rekening mee houdt.
      
      Ik ben er persoonlijk wel happy mee. Beperkingen  worden  er
      niet meer opgelegd en andere routines die wel  van  de  BDOS
      gebruik maken,  maar  niet  van  deze  routines,  hebben  er
      ab-so-luut geen last van. Het is zelfs zo  dat  er  met  bv.
      FBLKRD: gelezen kan worden uit een file die niet met  FOPEN:
      geopend is. Dat alles in combinatie met een zeer  eenvoudige
      BDOS interfacing voor het lezen en schrijven van files maakt
      deze routines voor mij in ieder geval onmisbaar.
      
                                                 Alex van der Wal