Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

A Tiny Operating System in PBDOS

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • A Tiny Operating System in PBDOS

    'i have trouble posting this program, apparently it has too many
    'lines to be loaded in one part.
    'so i try to post it in three parts now.
    '
    '[CODE]
    'simple operating system in powerbasic for dos
    '
    'runs in real mode and is to some extend compatible to dos
    'by implementing often used dos functions to get dos
    'applications to run.
    '
    'supports a floppy disk and root directory.
    'does not have file access functions for application programs.
    'cannot call basic code from an isr. would have
    'to convert the disk functions to assembler for that.
    '
    'will run pbdos, assembler, turbo pascal, turbo-c and ms-c programs.
    'i could print "hello world" in these languages and run some games.
    'will not run quickbasic programs.
    '
    'intended as a sample, not all functions are tested completely
    '
    'use with the bootloader already posted in this forum:
    'http://.]

  • #2
    '
    Code:
    '**************************************************************************
    'this ISR will be called for operating system functions by our application
    'program
    
    SUB ISR () PRIVATE
    
    'define areas to store data in CS
    SaveDS_PB:
      ! dw 0
    SaveSS_PB:
      ! dw 0
    SaveSP_PB:
      ! dw 0
    DSappl:
      ! dw 0
    Terminate_flag:
      ! dw 0
    Carry_flag:
      ! dw 0
    dta_seg:
      ! dw 0
    dta_off:
      ! dw 0
    setstrat:
      ! dw 0
    pspseg:
      ! dw 0
    extkey:
      ! dw 0
    maxmem:
      ! dw 0
    
    OS_ISR:
    
      ! push bp
      ! push si
      ! push di
      ! push ds
      ! push es
      ! push dx
      ! push cx
      ! push bx
      ! push ax
      ! clc                           ; clear carry as default
      ! pushf                         ; save the flags register
      ! cli                           ; suspend all maskable interrupts
    
      ! mov bp,sp                     ; access variables on stack with bp
    
      ! mov Word Ptr CS :DSappl, DS    ; save application's DS register
    
      ! mov Word Ptr CS:Terminate_flag,0
      ! mov Word Ptr CS:Carry_flag,0
    
    $if %testout
    'display ah,al,bl,cl on com1
    ! db &H60 ;pusha
    ! push sp
    ! pushf
    ! push es
    ! push ds
    ! push cx
    ! push bx
    ! push ax
    ! mov al,ah
    ! mov ah,01
    ! mov dx,0
    ! int &H14 ;ah
    ! pop ax
    ! mov ah,01
    ! mov dx,0
    ! int &H14 ;al
    ! pop bx
    ! mov al,bl
    ! mov ah,01
    ! mov dx,0
    ! int &H14 ;bl
    ! pop cx
    ! mov al,cl
    ! mov ah,01
    ! mov dx,0
    ! int &H14 ;cl
    ! pop ds
    ! pop es
    ! popf
    ! pop sp
    ! db &H61 ;popa
    $endif
    
    
    'the jump table
    ! cmp ah,00
    ! jne na1
    ! jmp caseH00H4C
    na1:
    ! cmp ah,&H4C
    ! jne na2
    ! jmp caseH00H4C
    na2:
    ! cmp ah,01
    ! jne na3
    ! jmp caseH01H07H08
    na3:
    ! cmp ah,02
    ! jne na4
    ! jmp caseH02
    na4:
    ! cmp ah,07
    ! jne na5 
    ! jmp caseH01H07H08
    na5:
    ! cmp ah,08
    ! jne na5b 
    ! jmp caseH01H07H08
    na5b:
    ! cmp ah,09
    ! jne na6
    ! jmp caseH09
    na6:
    ! cmp ah,&H0A
    ! jne na7
    ! jmp caseH0A
    na7:
    ! cmp ah,&H0B
    ! jne na8
    ! jmp caseH0B
    na8:
    ! cmp ah,&H1A
    ! jne na9
    ! jmp caseH1A
    na9:
    ! cmp ah,&H2F
    ! jne na10
    ! jmp caseH2F
    na10:
    ! cmp ah,&H30
    ! jne na11
    ! jmp caseH30
    na11:
    ! cmp ah,&H25
    ! jne na12
    ! jmp caseH25
    na12:
    ! cmp ah,&H33
    ! jne na13
    ! jmp caseH33
    na13:
    ! cmp ah,&H35
    ! jne na14
    ! jmp caseH35
    na14:
    ! cmp ah,&H2B
    ! jne na15
    ! jmp caseH2B
    na15:
    ! cmp ah,&H40
    ! jne na16
    ! jmp caseH40
    na16:
    ! cmp ah,&H44
    ! jne na17
    ! jmp caseH44
    na17:
    ! cmp ah,&H3E
    ! jne na18
    ! jmp caseH3E
    na18:
    ! cmp ah,&H49
    ! jne na19
    ! jmp caseH49
    na19:
    ! cmp ah,&H4A
    ! jne na20
    ! jmp caseH4A
    na20:
    ! cmp ah,&H58
    ! jne na21
    ! jmp caseH58
    na21:
    ! cmp ah,&H62
    ! jne na22
    ! jmp caseH62
    na22:
    ! cmp ah,&H19
    ! jne na23
    ! jmp caseH19
    na23:
    ! cmp ah,&H0C
    ! jne na24
    ! jmp caseH01H07H08
    na24:
    ! cmp ah,&H3F
    ! jne na25
    ! jmp caseH3F
    na25:
    ! jmp caseelse
    'end of table
    
    	caseH00H4C: 'terminate
    		! mov Word Ptr CS:Terminate_flag,1
    		! jmp end21h
            caseH01H07H08: 'input character
                    ! mov bx,word ptr cs:extkey
                    ! cmp bx,0 ;is extended key stored?
                    ! je  noextkey ;0 if no ext value stored
                    ! mov al,bl
    		! mov word ptr ss:[bp+2],ax ;return value in cs:extkey
                    ! mov word ptr cs:extkey,0  ;clear
                    ! jmp end21h
                    noextkey:
                    ! push ax
                    ! mov ah,00
                    ! int &H16
                    ! cmp al,0 ;extended key?
                    ! jne noextkey2
                    ! xchg al,ah ;put key value into al and clear ah
                    ! mov word ptr cs:extkey,ax ;store extended key for next call
                    ! mov al,0 ;signal extended key by returning zero
                    ! mov word ptr ss:[bp+2],ax
    		! jmp end21h ;no echo of extended key
                    noextkey2:
                    'scancode in ah
                    ! mov word ptr ss:[bp+2],ax
                    ! pop cx ;former ax - 01 with echo?
                    ! cmp ch,&H01
                    ! je h01cont
    		! jmp end21h
                    h01cont:
                    ! mov ah,&H0E ;should interpret backspace
                    ! int &H10    ;echo key
                    ! jmp end21h
            caseH02: 'output character
                    ! mov bx,dx
                    ! mov es:[bx],dx
                    ! mov cx,1
                    ! jmp fromH02 ;jmp into &H09
    		! jmp end21h
            caseH09: 'output string
                    'does not interpret LF chars etc.
                    'do instr for $
    		! mov es,word ptr cs:dsappl
                    ! cld
                    ! mov di,dx ;string in es:di for scas
                    ! mov al,36 ;'$'
                    ! mov cx,500 ;test up to 500 bytes
            ! repne  scasb
              	! jcxz endh09
    		! mov cx,di ;offset of next(!) char in di
                    ! sub cx,dx ;minus start offset
                    ! dec cx ;exclude $ sign
    
    		fromH02: ';jmp here from &H02
    		'input: es:dx = buffer, cx = nr. of chars to print
    		'does not save registers except bp+cx
    		! push bp
    		! push cx
    		! push word ptr cs:dsappl
    		! pop es
    		! push es   ;ds=es=segment
    		! push dx   ;offset
    		! push cx   ;next int 10 destroys cx
    
    		! mov ax,&H0300   ;bios function code
    		! xor bh,bh       ;page number 0
    		! int &H10        ;cursor pos/line returned in dx
                    		  'so dx is filled
    		! mov ax,&H1301 ;bios function code
    		! mov bx,&H0007 ;attribute
    		! pop cx       ;nr of characters
    		! pop bp       ;buffer offset
    		! pop es       ;buffer segment
    		! int &H10
    		! pop cx
    		! pop bp
    		endH09:
    		! jmp end21h
            caseH0A: 'buffered input
                    ! mov bx,dx ;to use ds:bx
                    ! mov cl,byte ptr ds:[bx] ;read max chars
                    ! dec cx ;allow one minus max - for CR
                    ! inc bx
                    ! push bx ;save nr of chars read at this address below
                    ! inc bx
                    ! cld
                    ! push cx
                    H0Aloop:
    		! mov ah,00 ;should allow type ahead though
                    ! int &H16
                    ! cmp al,0 ;extended?
                    ! jne noextoa
                    ! mov byte ptr ds:[bx],al
                    ! inc bx
                    ! mov al,ah
                    noextoa:
                    ! mov byte ptr ds:[bx],al
                    ! inc bx
                    ! cmp al,13 ;CR?
                    ! je crfound
    		! mov ah,&H0E ;should do editing
                    ! int &H10    ;echo key
                    ! loop H0Aloop
                    'if user enters max chars we stop - no bell
                    ! mov byte ptr ds:[bx],13 ;enter CR as last char
                    ! inc cx ;adjust
                    crfound:
                    ! mov bx,cx ;is -1 for CR
                    ! pop cx ;restore max chars
                    ! sub cx,bx ;number of chars read
                    ! pop bx
                    ! mov byte ptr ds:[bx],cl ;store chars read
    		! jmp end21h
            caseH0B: 'check input status
    		! mov ah,01
                    ! int &H16
                    ! mov ax,&H0B00
                    ! jz nochar
                    ! mov ax,&H0BFF
                    nochar:
                    ! mov word ptr ss:[bp+2],ax
    		! jmp end21h
            caseH19: 'current disk
    		! mov word ptr ss:[bp+2],&H1900 ;return 0
    		! jmp end21h
            caseH1A: 'set DTA address
                    ! mov ax,word ptr CS:dsappl
            	! mov word ptr CS :DTA_SEG,AX
            	! mov word ptr CS :DTA_OFF,DX
    		! jmp end21h
            caseH2F: 'get DTA address
                    ! mov ax,word ptr CS :DTA_SEG
    		! mov word ptr ss:[bp+10],ax ;return in es
                    ! mov ax,word ptr CS :DTA_OFF
            	! mov word ptr ss:[bp+4],ax ;return in bx
    		! jmp end21h
      	caseH30: 'DOS version
    		! mov word ptr ss:[BP+2],&H1E03 ;return 3.30 in ax
    		! jmp end21h
    	caseH25: 'set int address
    		'calculate vector address
    		! xor bh,bh
    		! shl bx,1  ;bx * 4 = int-nr * 4 = offset in vector table
                    ! shl bx,1
                    ! xor cx,cx
                    ! mov es,cx    ;es=0 now
                    ! mov word ptr es:[bx],dx
    		! mov dx,word ptr cs:dsappl
                    ! mov word ptr es:[bx+2],dx
    		! jmp end21h
    	caseH33: 'ctrl-break check
            	! mov dl,0
                    ! mov word ptr ss:[BP+8],dx	;claim its turned off
    		! jmp end21h
            caseH35: 'get interrupt
    		! mov ah,0   ;int-nr * 4 = position in vector table
    		! shl ax,1   ;ax * 4
                    ! shl ax,1
    		! mov si,ax
                    ! xor ax,ax
                    ! mov es,ax
    		! mov bx,word ptr es:[si]   ;read offset
    		! mov cx,word ptr es:[si+2] ;read segment
    		! mov word ptr ss:[bp+4],bx
    		! mov es,cx       ;es=new segment
    		! mov word ptr ss:[bp+10],es
    		! jmp end21h
            caseH2B: 'set system date
    		! mov Word Ptr SS:[BP+2],&H2BFF    ;return FF - wrong date
                    ! mov Word Ptr CS:Carry_flag,1   ;have that set after poping regs
                    ! jmp end21h
            caseH3E: 'release memory
                    'clear carry - ok
    		! jmp end21h
            caseH3F: 'input file - just keyboard here
                    ! cmp bx,0   ;keyboard?
                    ! je keyb3f  ;yes
    		! mov Word Ptr SS:[BP+2],5  ;access denied
                    ! mov Word Ptr CS:Carry_flag,1   ;have that set after poping regs
                    ! jmp end21h ;no, exit
                    keyb3f:
                    ' max chars in cx
                    ! mov bx,dx ;to use ds:bx
                    ! cld
                    H3Floop:
    		! mov ah,00
                    ! int &H16
                    ! cmp al,0 ;extended?
                    ! jne noext3F
                    ! mov byte ptr ds:[bx],al
                    ! inc bx
                    ! mov al,ah
                    noext3F:
                    ! mov byte ptr ds:[bx],al
                    ! inc bx
                    ! mov ah,&H0E ;should do editing
                    ! int &H10    ;echo key
                    ! cmp al,13 ;CR? - assume cooked mode
                    ! je crfound3F
                    ! loop H3Floop
                    'if user enters max chars add return
                    ! mov byte ptr ds:[bx],13
                    ! inc bx
                    crfound3F:
                    ! mov byte ptr ds:[bx],10 ;LF
                    ! inc bx
                    ! mov byte ptr ds:[bx],0 ;terminate byte
    
                    ! sub bx,dx ;bx counted the chars except terminate byte
                    ! mov word ptr ss:[bp+2],bx ;return chars read in ax
    		! jmp end21h
    
    	caseH40: 'write file
            	! cmp bx,1 ;'write to screen?
                    ! jne endH40
    		'input: es:dx = buffer, cx = nr. of chars to print
    		'does not save registers except bp+cx
    		! push bp
    		! push cx
    		! push word ptr cs:dsappl
    		! pop es
    		! push es   ;ds=es=segment
    		! push dx   ;offset
    		! push cx   ;next int 10 destroys cx
    
    		! mov ax,&H0300   ;bios function code
    		! xor bh,bh       ;page number 0
    		! int &H10        ;cursor pos/line returned in dx
                    		  'so dx is filled
    		! mov ax,&H1301 ;bios function code
    		! mov bx,&H0007 ;attribute
    		! pop cx       ;nr of characters
    		! pop bp       ;buffer offset
    		! pop es       ;buffer segment
    		! int &H10
    		! pop cx
    		! pop bp
                    ! mov word ptr ss:[bp+2],cx ;return bytes written in ax
    		endH40:
    		! jmp end21h
    	caseH44: 'try to fake IOCtrl
                    ! cmp bx,2
                    ! ja nH44_1
                     ! mov word ptr ss:[bp+4],&H80D3 ;for bx<3
                    ! jmp endH44
                    nH44_1:
                    ! cmp bx,3
                    ! jne nH44_2
                     ! mov word ptr ss:[bp+4],&H80C0  ;for bx=3
                    ! jmp endH44
                    nH44_2:
                    ! cmp bx,4
                    ! jne nH44_3
                     ! mov word ptr ss:[bp+4],&HA0C0  ;for bx=4
                    ! jmp endH44
                    nH44_3:
                     ! mov word ptr ss:[bp+4],&H0040  ;for bx=else
    		endH44:
    		! jmp end21h
            caseH49: 'release memory
                    'clear carry - ok
    		! jmp end21h
            caseH4A: 'modify memory
                    ! cmp bx,&HFFFF ;request for max memory - return available
                    ! jne endH4A
                    ! mov bx,word ptr cs:maxmem
                    ! mov word ptr ss:[bp+4],bx ;return available memory in bx
                    ! mov Word Ptr CS:Carry_flag,1   ;have that set after poping regs
    		endH4A:
    		! jmp end21h
            caseH58: 'set allocation strategy
                    ! cmp al,0 ;get strategy?
                    ! jne setH58
                    ! mov ax,word ptr CS:setstrat
                    ! mov word ptr ss:[BP+2],ax ;return in ax
                    ! jmp endH58
                    setH58: ';set strategy in bx
                    ! mov CS:setstrat,bx   ; save strategy
                    ! mov word ptr ss:[BP+2],bx     ;return strategy set
                    endH58:
    		! jmp end21h
    	caseH62: 'get PSP address
                    ! mov ax,word ptr cs :pspseg
                    ! mov word ptr ss:[bp+4],ax
    		! jmp end21h
          	caseelse:
                    ! mov Word Ptr CS:Carry_flag,1   ;have that set after poping regs
    
    end21h:
    
      ! popf               ; restore the flags register
      ! pop ax
      ! pop bx
      ! pop cx
      ! pop dx
      ! pop es
      ! pop ds
      ! pop di
      ! pop si
      ! pop bp
      ! sti                ; re-enable maskable interrupt processing
    
      ! cmp Word Ptr CS:Terminate_flag,1
      ! je return_to_pb    ; program has terminated, go to shell
    
      ! cmp Word Ptr CS:Carry_flag,0
      ! je do_iret     ;do not set carry
      ! stc		   ;already set by cmp though
    do_iret:
    
    $if %testout
    'display ah,al,bl,carry on com1
    ! db &H60 ;pusha
    ! push sp
    ! push es
    ! push ds
    ! pushf
    ! push bx
    ! push ax
    ! mov al,&HAA ;separation char
    ! mov ah,01
    ! mov dx,0
    ! int &H14 ;ah
    ! pop ax
    ! push ax
    ! mov al,ah
    ! mov ah,01
    ! mov dx,0
    ! int &H14 ;ah
    ! pop ax
    ! mov ah,01
    ! mov dx,0
    ! int &H14 ;al
    ! pop bx
    ! mov al,bl
    ! mov ah,01
    ! mov dx,0
    ! int &H14 ;bl
    ! pop ax ;popf-flags in ax
    ! pushf
    ! and ax,&H0001 ;clear all but carry
    ! mov ah,01
    ! mov dx,0
    ! int &H14 ;carry
    ! popf
    ! pop ds
    ! pop es
    ! pop sp
    ! db &H61 ;popa
    $endif
    
      ! iret               ; return from our interrupt handler
    
    return_to_pb:
      ! mov SP, Word Ptr CS:SaveSP_PB ; restore the original stack segment
      ! mov SS, Word Ptr CS:SaveSS_PB ; and stack pointer before restoring the registers
      ! mov DS, Word Ptr CS:SaveDS_PB ; restore PowerBASIC data segment
      goto theshell
    END SUB
    
    'add third part here ----------------------------------------
    '

    ------------------


    [This message has been edited by Georg Potthast (edited August 24, 2006).]

    Comment


    • #3
      '
      Code:
      'This is the third part of this OS code. Add to part two.
      '
      '**************************************************************************
      doexecute: 'run program loaded at programloadseg
      'will not run compressed exe files
      
        ! mov Word Ptr CS:SaveSS_PB, SS    ; save current stack segment
        ! mov Word Ptr CS:SaveSP_PB, SP    ; save current stack pointer
      
      'is it an exe or com program?
      def seg = programloadseg
      tmp??=peeki(0)
      def seg
      if tmp?? <> &H5A4D then 'no "MZ" -> com program was loaded:
      
      !        cli                             ; for stack adjustments
      !        mov     ax, programloadseg      ;programloadseg to ax -> es
      !        mov     es, ax
      
      !        mov     ax, es                  ;programloadseg to ax, then sub 10h
      !        sub     ax, &H10                ;to point es,ds,ss to psp seg
      !        mov     es, ax
      !        mov     ds, ax
      !        mov     ss, ax
      !        xor     sp, sp                  ;set sp to 0
      !        push    es                      ;set CS to PSP seg
      !        mov     ax,&H100                ;set ip to 100h - org100h
      !        push    ax
      !        sti
      !        retf                            ; jump to cs:ip pushed on stack above
      
      else 'exe program
      
      RelocateEXE:
      !        cli                             ; for stack adjustments
      !        mov     ax, programloadseg      ; programloadseg to ax -> es,ds
      !        mov     es, ax
      !        mov     ds, ax
      
      !        add     ax, ds:[&H08]           ; add header size to programloadseg
      !                                        ; to get start of load module
      !        mov     cx, ds:[&H06]           ; cx = number of reloc items
      !        mov     bx, ds:[&H18]           ; bx = offset of first reloc item in file
      
      !        jcxz    RelocationDone          ; cx = nr of reloc items - can be 0
      
      ReloCycle:
      !        mov     di, ds:[bx]             ; di = item offset
      !        mov     dx, ds:[bx+2]           ; dx = item seg (rel)
      !        add     dx, ax                  ; dx = item seg (abs)
      !                                        ; add load module start to item seg (rel)
      !        push    ds
      !        mov     ds, dx                  ; ds = dx  absolute item seg in dx
      !        add     ds:[di], ax             ; write (!) load module start to
      !                                        ; item seg/off address
      !        pop     ds                      ; restore ds
      
      !        add     bx, 4                   ; point to next entry - seg/off is 4 byte long
      !        loop    ReloCycle               ; decrement cx automatically and
      !                                        ; ends when cx=0
      
      RelocationDone:
      !        mov     bx, ax                  ; move start of load module to bx
      !        add     bx, ds:[&H0E]           ; add offset(displacment) of stack module
      !        mov     ss, bx                  ; set ss for EXE
      !        mov     sp, ds:[&H10]           ; set sp for EXE from header
      
      !        add     ax, ds:[&H16]           ; add offset of code module to load module and
      !        push    ax                      ; put exe prog's cs in stack for retf below
      !        mov     bx, ds:[&H14]           ; move ip value from header into ax and
      !        push    bx                      ; put exe prog's ip in stack for retf below
      
      !        mov     ax, es                  ; es = programloadseg here
      !        sub     ax,&H10                 ; get psp seg
      !        mov     ds,ax                   ; ds+es have to point to psp seg on
      !        mov     es,ax                   ; exe program load
      !        xor     ax,ax                   ; 0 like dos - current drive should be
      !                                        ; in FCB1 and/or FCB2
      !        xor bp,bp                       ; bp 0 like dos
      !        xor bx,bx                       ; could indicate load memory size - 0 here like dos
      !        xor dx,dx                       ; shall be 0
      !        sti
      !        retf                            ; jump to cs:ip pushed on stack above
      
      end if 'com/exe
      
      return
      
      '************************************************************************
      'this function reads one sector into a string variable
      'the No. of multiple sectors possible to read depends on the bios and
      'is not implemented here
      'call with disk?=0 for floppy A:
      '
      function readsector(byval sec_nr??,dat$,disk?)
      
      nr_of_secs?=1 'fixed to one sector here
      
      if sec_nr??=1 then 'bootsector - values not filled
        cylinder??=0
        head?=0
        bpb.bootsector.Sectorsize=512
      else 'any other sector
        'convert sector # to CHS
        para??=bpb.bootsector.SectorsPerTrack * bpb.bootsector.Heads
        cylinder??=sec_nr??\para??
        sec_nr??=sec_nr??-(para??*cylinder??)
        head?=sec_nr??\bpb.bootsector.SectorsPerTrack
        sec_nr??=sec_nr??-(bpb.bootsector.SectorsPerTrack*head?) +1
      end if
      
      tmp$=string$(bpb.bootsector.Sectorsize,0) 'clear
      
      for retries% = 1 to 5
       reg 1 , &H200 + nr_of_secs?
       reg 4 , disk? + head?*256
       reg 3 , (sec_nr?? AND &H3F) + (cylinder??\256*64 + (cylinder?? AND 255)) * 256
       reg 9 , strseg(tmp$)
       reg 2 , strptr(tmp$)
       call interrupt &H13
       'check for error and retry
       if (reg(0) AND &H0001) = 0 then exit for 'carry not set
       tmp%=reg(1)
       shift right tmp%,8 'get AH
       print "Int13 Error: " hex$(tmp%)
       reg 1 ,&H0000   'reset drive
       call interrupt &H13
       delay 0.1
      next retries%
      
      dat$=tmp$ 'return data read
      readsector=0 'clear
      if retries%>4 then readsector=tmp% 'return bios error code
      
      end function
      
      '*******************************************************************
      function getfirstcluster??(progname$)
      
      'read root directory
      rootsectors?=bpb.bootsector.Directoryentries*32/bpb.bootsector.SectorSize
      dat$=""
      tmp$=string$(bpb.bootsector.Sectorsize,0) 'buffer for sector
      for i=0 to rootsectors?-1 'read single sectors
        call readsector(rootoffset??+i,tmp$,drivenr?)
        dat$=dat$+tmp$
      next i
      
      'make directory entry name
      extension$="" 'clear
      tmp%=instr(progname$,".")
      if tmp%>0 then
       dirname$=mid$(progname$,1,tmp%-1)   'get name part left of dot
       extension$=mid$(progname$,tmp%+1,3) 'get file extension
      else
       dirname$=progname$
      end if
      dirname$=dirname$+string$(8-len(dirname$),32) 'fill with blanks up to 8
      dirname$=dirname$+extension$
      if len(extension$)<3 then
         dirname$=dirname$+string$(3-len(extension$),32) 'fill up to 3
      end if
      
      namepos%=instr(dat$,ucase$(dirname$))
      if namepos%>0 then
      	firstcluster??=cvwrd(mid$(dat$,namepos%+&H1A,2))
      else
      	firstcluster??=0 'not found
      end if
      
      getfirstcluster??=firstcluster?? 'return value
      
      end function
      
      '************************************************************
      function fill_filechain%(firstcluster??,filechain??())
      
      'read fat
      dat$=""
      tmp$=string$(bpb.bootsector.Sectorsize,0) 'buffer for sector
      for i=0 to bpb.bootsector.SectorsPerFAT-1
        call readsector(fatoffset??+i,tmp$,drivenr?)
        dat$=dat$+tmp$
      next i
      
      'now follow cluster chain in fat
      for i=1 to 512 'up to 512 clusters allowed
      
       filechain??(i)=firstcluster??
       firstclusterpos??=firstcluster??*3\2
       nextcluster??=cvwrd(mid$(dat$,firstclusterpos??+1,2))
      
       if (firstcluster?? mod 2) = 0 then 'uneven
         nextcluster??=nextcluster?? AND &H0FFF
       else 'even
         shift right nextcluster??,4
       end if
       'mark end of chain with 65535
       if nextcluster??=&H0FFF then filechain??(i+1)=65535 : exit for
      
       firstcluster??=nextcluster??
      next i
      
      fill_filechain% = i 'return number of clusters found
      
      end function
      
      '***********************************************************************
      function showdir()
      
      'read root directory
      rootsectors?=bpb.bootsector.Directoryentries*32/bpb.bootsector.SectorSize
      dat$=""
      tmp$=string$(bpb.bootsector.Sectorsize,0) 'buffer for sector
      for i=0 to rootsectors?-1 'read single sectors
        call readsector(rootoffset??+i,tmp$,drivenr?)
        dat$=dat$+tmp$
      next i
      
      'show files and directories
      for i=1 to 8000 step 32 'up to 250 files
        tmp$=mid$(dat$,i,11)
        if mid$(dat$,i,1) = chr$(0) then exit for 'end of list
        if mid$(dat$,i,1) <> chr$(&HE5) and mid$(dat$,i,1) <> chr$(0) then
          print tmp$,
          print cvdwd(mid$(dat$,i+&H1C,4))
        end if
      next i
      
      end function
      '

      ------------------


      [This message has been edited by Georg Potthast (edited August 24, 2006).]

      Comment

      Working...
      X