        TITLE   'INI - RxDOS Initialize'
        PAGE 59, 132
        .LALL

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  INI - RxDOS Initialize                                       ;
        ;...............................................................;

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Real Time Dos                                                ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  This material  was created as a published version  of a DOS  ;
        ;  equivalent product.   This program  logically  functions in  ;
        ;  the same way as  MSDOS functions and it  is  internal  data  ;
        ;  structure compliant with MSDOS 6.0                           ;
        ;                                                               ;
        ;  This product is distributed  AS IS and contains no warranty  ;
        ;  whatsoever,   including  warranty  of   merchantability  or  ;
        ;  fitness for a particular purpose.                            ;
        ;                                                               ;
        ;                                                               ;
        ;  (c) Copyright 1990, 1997. Api Software and Mike Podanoffsky  ;
        ;      All Rights Reserved Worldwide.                           ;
        ;                                                               ;
        ;  This product is protected under copyright laws and  may not  ;
        ;  be reproduced  in whole  or in part, in any form  or media,  ;
        ;  included but not limited to source listing, facsimile, data  ;
        ;  transmission, cd-rom, or  floppy disk without the expressed  ;
        ;  written consent of the author.                               ;
        ;                                                               ;
        ;  License  for  distribution  for commercial  use  or  resale  ;
        ;  required from:                                               ;
        ;                                                               ;
        ;  Api Software                                                 ;
        ;  12 South Walker Street                                       ;
        ;  Lowell,  MA   01851                                          ;
        ;                                                               ;
        ;  internet: mikep@world.std.com                                ;
        ;                                                               ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;  Compile with MASM 5.1                                        ;
        ;...............................................................;

        include rxdosmac.asm
        include rxdosdef.asm

RxDOS   SEGMENT PUBLIC 'CODE'
        assume cs:RxDOS, ds:RxDOS, es:RxDOS, ss:RxDOS

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  INI - RxDOS Initialize                                       ;
        ;...............................................................;

        public RxDOS_initialize
        public RxDOS_LineEditorBuffers

        public LogTraceBlockDevRequest
        public LogTraceBlockDevReturn
        public LogTraceCharDevRequest
        public LogTraceCharDevReturn
        public LogTraceInt21Calls

        extrn _RxDOS_bNumBlockDev               : byte
        extrn _RxDOS_BufferList                 : near
        extrn _RxDOS_CurrentDrive               : byte
        extrn _RxDOS_BootDrive                  : byte

        extrn _RxDOS_CommandShell               : near
        extrn _RxDOS_Buffers                    : dword
        extrn _RxDOS_bLastDrive                 : byte
        extrn _RxDOS_bSwitchChar                : byte
        extrn _RxDOS_bCtrlBreakCheck            : byte
        extrn _RxDOS_MaxMemory                  : word
        extrn _RxDOS_NULLDev                    : dword
        extrn _RxDOS_pCDS                       : dword
        extrn _RxDOS_pDPB                       : dword
        extrn _RxDOS_pFT                        : dword
        extrn _RxDOS_pStartMemBlock             : word

        extrn _RxDOS_CurrentSeg                 : word
        extrn _RxDOS_SharedBuffer               : near
        extrn _RxDOS_pDTA                       : near
        extrn _RxDOS_CurrentPSP                 : near
        extrn _RxDOS_pCONdriver                 : near
        extrn _RxDOS_pCLOCKdriver               : near

        extrn _RxDOS_UserCodePage               : near
        extrn _RxDOS_SystemCodePage             : near
        extrn _RxDOS_CurrCountryInfo            : near
        extrn _RetCallersStackFrame             : near

        extrn RxDOS_StackTop                    : near
        extrn RxDOS_StackTemp                   : near
        extrn RxDOS_start                       : near

        extrn _CallDOS                          : far
        extrn _Interrupt_20                     : near
        extrn _Interrupt_21                     : near
        extrn _Interrupt_23                     : near
        extrn _Interrupt_24                     : near
        extrn _Interrupt_25                     : near
        extrn _Interrupt_26                     : near
        extrn _Interrupt_27                     : near
        extrn _Interrupt_28                     : near
        extrn _Interrupt_2a                     : near
        extrn _Interrupt_2f                     : near
        extrn _IRet                             : near

        extrn maxBlockDevices                   : near
        extrn FindAvailableSFTHandle            : near
        extrn checkforDeviceType                : near
        extrn checkforDeviceName                : near
        extrn stdDeviceAssignTable              : near

        extrn scanDirectory                     : near
        extrn initdiskAccess                    : near
        extrn lowerCase                         : near
        extrn upperCase                         : near
        extrn CopyString                        : near
        extrn readLine                          : near
        extrn _initializeMemoryBlock            : near
        extrn SDAExtendedSwapArea               : near
        extrn initReqBlock                      : near

        extrn RxDOS_USA_DefaultUpperCaseFunction : far

     ;  extrn msgUnknownCommandinConfig         : near
     ;  extrn _RxDOS_ConfigKeywords             : near

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Line Editor Buffer Pool                                      ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Init code space is used to hold interim buffers.             ;
        ;                                                               ;
        ;                                                               ;
        ;...............................................................;

RxDOS_LineEditorBuffers dw  ( RxDOS_EndOfInitCode - $ ) / sizeLINEEDITOR_BUFFERPOOL

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  CONFIG Statement Types                                       ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  WARNING: These values cannot be changed without also         ;
        ;  changing the dispatch table.                                 ;
        ;                                                               ;
        ;...............................................................;

CONFIGTYPE_ENDOFARGS    equ 0000h                       ; last entry
CONFIGTYPE_DOS          equ 0001h                       ; dos = umb, high
CONFIGTYPE_NUMLOCK      equ 0002h                       ; numlock = on | off
CONFIGTYPE_BREAK        equ 0003h                       ; break = on | off
CONFIGTYPE_SET          equ 0004h                       ; set

CONFIGTYPE_COUNTRY      equ 0005h                       ; contry = 
CONFIGTYPE_DEVICE       equ 0006h                       ; device devicename [ options ]
CONFIGTYPE_DEVICEHIGH   equ 0007h                       ; devicehigh devicename [ options ]
CONFIGTYPE_DRIVPARAM    equ 0008h                       ; driveparam
CONFIGTYPE_MULTITRACK   equ 0009h                       ; multitrack
CONFIGTYPE_SWITCHES     equ 0010h                       ; switches

CONFIGTYPE_BUFFERS      equ 0011h                       ; buffers =
CONFIGTYPE_FILES        equ 0012h                       ; files =
CONFIGTYPE_FCBS         equ 0013h                       ; fcbs = x [, y ]
CONFIGTYPE_LASTDRIVE    equ 0014h                       ; lastdrive = x
CONFIGTYPE_SHELL        equ 0015h                       ; shell specifypath
CONFIGTYPE_STACKS       equ 0016h                       ; stacks

CONFIGTYPE_INSTALL      equ 0017h                       ; install progname
CONFIGTYPE_INSTALLHIGH  equ 0018h                       ; installhigh progname

CONFIGTYPE_MENUDEFAULT  equ 0019h                       ; blockname [, timeout ]
CONFIGTYPE_MENUITEM     equ 001Ah                       ; itemname [, text ]
CONFIGTYPE_MENUCOLOR    equ 001Bh                       ; x [, y]
CONFIGTYPE_SUBMENU      equ 001Ch                       ; itemname [, text ]
CONFIGTYPE_INCLUDE      equ 001Dh                       ; itemname
CONFIGTYPE_MENUBLOCK    equ 001Eh                       ; [...]

CONFIGTYPE_SWITCHCHAR   equ 0020h                       ; char
CONFIGTYPE_COMMENTS     equ 0021h                       ; comments
CONFIGTYPE_REM          equ 0022h                       ; remarks

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  CONFIG Flags And Options                                     ;
        ;...............................................................;

CONFIGFLAG_ENABLED      equ 0001h
CONFIGFLAG_PROCESSED    equ 0002h

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  CONFIGSTMT structure                                         ;
        ;...............................................................;

        CONFIGSTMT struc

cStmtType               dw ?                    ; config statement type
cStmtName               db ?                    ; statement starts here

        CONFIGSTMT ends

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  CONFIGLINE Buffer                                            ;
        ;...............................................................;

        CONFIGLINE struc

configType              dw ?                    ; config statement type
configLength            dw ?                    ; config line length
configFlags             dw ?                    ; config statement line number
configLineNumber        dw ?                    ; config statement line number
configStatement         db ?                    ; statement starts here

        CONFIGLINE ends

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Config File Processing                                       ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  This module reads the entire  Config.sys  file from  a par-  ;
        ;  tially initialized system.  It expects  minimally  buffers,  ;
        ;  CDS, and other  DOS  data  structures.   Config  processing  ;
        ;  happens in two phases:  pass one gathers facts and pass two  ;
        ;  reconfigures data structures and loads drivers.              ;
        ;                                                               ;
        ;  Returns:                                                     ;
        ;  ds/es   both will point to ss                                ;
        ;  ax      current drive                                        ;
        ;...............................................................;

configProcessing:

        Entry
        ddef  _configStatements, es, di
        ddef  _configNextLine, es, di

        def  _comment    , ';'                          ; default comment character
        def  _charsread
        def  _linenumber , 0000
        def  _dosFlags,    0000

        defbytes _diskAccess, sizeDISKACCESS
        defbytes _linebuffer, 255

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  find/ open config.sys 
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        setDS cs
        setES cs
        xor dx, dx
        mov al, byte ptr [ _RxDOS_CurrentDrive ]        ; startup drive
        mov di, offset _RxDOS_ConfigFile                ; search config file
        call scanDirectory                              ; open config.sys
        ifc configProcessing_Return                     ; if none found -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  find/ open config.sys 
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        push word ptr es:[ deFileSize. _low  ][ si ]
        push word ptr es:[ deFileSize. _high ][ si ]

        setES ss
        lea bx, _diskAccess [ bp ]                      ; build access control block
        call initdiskAccess                             ; [ax] is drive, [dx] is cluster

        pop word ptr ss:[ diskAcFileSize. _high ][ bx ]
        pop word ptr ss:[ diskAcFileSize. _low  ][ bx ]

configProcessing_12:
        getdarg es, di, _configNextLine
        mov word ptr es:[ configType   ][ di ], CONFIGTYPE_ENDOFARGS
        mov word ptr es:[ configLength ][ di ], 0000

        setES ss
        mov cx, 254
        lea di, offset _linebuffer [ bp ]
        lea bx, _diskAccess [ bp ]                      ; build access control block
        call readLine                                   ; read a line
        ifz configProcessing_36                         ; at end, reconfigure system -->

        inc word ptr [ _linenumber ][ bp ]              ; lines read

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  strip trailing newline
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     ;  lea di, offset _linebuffer [ bp - 1 ]
     ;  add di, cx
     ;  cmp byte ptr ss:[ di ], 0Ah                     ; trailing newline?
     ;  jne short configProcessing_14                   ; no -->
     ;  mov byte ptr ss:[ di ], 0                       ; change to null
     ;  dec cx

configProcessing_14:
        lea di, offset _linebuffer [ bp ]

        getarg ax, _comment                             ; parse out comments
        call configRemoveComments                       ; remove comments
        jz configProcessing_12                          ; if nothing left on line -->
        mov word ptr [ _charsread ][ bp ], cx           ; characters read

        setES ss
        cmp byte ptr ss:[ di ], ':'                     ; comment line ?
        jz configProcessing_12                          ; yes, ignore -->
        cmp byte ptr ss:[ di ], '['                     ; block item specifier ?
        jz configProcessing_16                          ; yes -->

        mov si, offset _RxDOS_ConfigKeywords
        call _findCommand
        jnc configProcessing_20

      ; typeout msgUnknownCommandinConfig
        jmp configProcessing_12

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  [ blockitem_name ]
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
configProcessing_16:
        inc di
        call _skipSpaces                                ; skip any leading spaces

        push di
        call _scanToEndofName                           ; find terminating space
        mov byte ptr ss:[ di ], 0                       ; set a terminator

        pop di
        mov dx, CONFIGTYPE_MENUBLOCK                    ; menu block 

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  go save statement
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
configProcessing_20:
        cmp dx, CONFIGTYPE_REM                          ; remark statement ?
        jz configProcessing_12                          ; ignore -->

        cmp dx, CONFIGTYPE_COMMENTS                     ; if comment, go process
        jz configProcessing_26                          ; process comment -->

        lea si, offset _linebuffer [ bp ]
        getarg cx, _charsread
        sub cx, di
        add cx, si                                      ; length difference to remember
        mov si, di                                      ; source pointer

        getdarg es, di, _configNextLine
        mov word ptr es:[ configType   ][ di ], dx      ; save type

        mov ax, word ptr [ _linenumber ][ bp ]          ; get line number
        mov word ptr es:[ configLineNumber ][ di ], ax

        mov word ptr es:[ configLength ][ di ], cx
        add word ptr es:[ configLength ][ di ], (size CONFIGLINE)

     ; copy statement

        lea di, offset [ configStatement   ][ di ]      ; offset to statement
        rep movsb
        
        xor ax, ax
        stosb                                           ; null terminate

        mov di, word ptr [ _configNextLine ][ bp ]
        add di, word ptr es:[ configLength  ][ di ]     ; advance beyond type
        mov word ptr [ _configNextLine ][ bp ], di
        jmp configProcessing_12

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  process menu
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
configProcessing_26:
        call _skipSpaces                                ; skip any leading spaces

        mov ax, word ptr es:[ di ]                      ; get comment character
        cmp ah, ' ' + 1                                 ; space or other control ?
        jnc configProcessing_28                         ; no -->
        mov ah, 0

configProcessing_28:
        storarg _comment, ax                            ; save comment character(s)
        jmp configProcessing_12                         ; continue

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  process menu
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
configProcessing_36:
        getdarg es, di, _configStatements
        call configMenu

        getdarg es, di, _configStatements
        call removeUnusedBlocks

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  reconfigure system
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        getdarg es, di, _configStatements

        call processSwitchChar                          ; SwitchChar = 
        call processNumLock                             ; NumLock = on | off
        call processDOS                                 ; dos =
        storarg _dosFlags, ax                           ; save flags
        call RxDOSini_MemorySubSystem                   ; re-initialize memory subsystem

        call processBuffers                             ; buffers =
        call processFCBS                                ; fcbs =
        call processFiles                               ; files = 
        call processStack                               ; stacks =

        call processLastDrive                           ; lastdrive =
        call processDrivParam                           ; drivparam = 
        call processMultiTrack                          ; multitrack = 

        call processBreak                               ; break = on | off
        call processCountry                             ; country = 
        call processSwitches                            ; switches =
        call processShell                               ; shell =

        getdarg es, di, _configStatements
        call processDevice                              ; device devicename [ options ]

        getarg ax, _dosFlags                            ; option flags
        call RxDOSini_LinkUpperMemory                   ; attempt link upper memory

        getdarg es, di, _configStatements
        call processDeviceHigh                          ; device devicename [ options ]

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
configProcessing_Return:

        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Unsupported Commands                                 ;
        ;...............................................................;

RxDOSini_LinkUpperMemory:

processCountry:
processDrivParam:
processMultiTrack:
processSwitches:

        ret                                             ; ignores entire line

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Break Statement                                      ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processBreak:

        Entry
        ddef _ConfigStatements, es, di
        def  _break, _OFF                               ; 0 is off; 1 is on.

processBreak_08:
        mov ax, CONFIGTYPE_BREAK
        call _findStatementType                         ; find statement type
        jc processBreak_24                              ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        call ConfigPrompt                               ; check for ?= or F8 case
        jc processBreak_12                              ; ignore statement -->
        
        mov si, offset _RxDOS_ConfigOnOff
        call _findCommand                               ; locate on or off
        jc processBreak_12                              ; if none of the above -->
        storarg _break, dx                              ; else ok to save

processBreak_12:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processBreak_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processBreak_24:
        getarg ax, _break                               ; get break
        mov byte ptr [ _RxDOS_bCtrlBreakCheck ], al

        getdarg es, di, _ConfigStatements               ; 
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Buffer Statements                                    ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processBuffers:

        Entry
        ddef _ConfigStatements, es, di
        ddef _buffers, 0, DEFAULT_BUFFERS

processBuffers_08:
        mov ax, CONFIGTYPE_BUFFERS
        call _findStatementType                         ; find statement type
        jc processBuffers_24                            ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        call ConfigPrompt                               ; check for ?= or F8 case
        jc processBuffers_16                            ; ignore statement -->
        
        mov cx, 1
        mov dx, CONFIGMAX_BUFFERS
        call _getNumber
        jc processBuffers_16                            ; if beyond range -->
        mov word ptr [ _buffers. _low  ][ bp ], ax      ; else ok to save

        mov cx, 0
        mov dx, ax                                      ; highest cannot exceed prev number
        call _getNumber
        jc processBuffers_16                            ; if beyond range -->
        mov word ptr [ _buffers. _high ][ bp ], ax      ; else ok to save

processBuffers_16:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processBuffers_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processBuffers_24:
        getdarg dx, ax, _buffers
        mov word ptr [ _RxDOS_Buffers. _low  ], ax
        mov word ptr [ _RxDOS_Buffers. _high ], dx
        call RxDOSini_CCBSubSystem                      ; reconfigure

        getdarg es, di, _ConfigStatements               ; 
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Device Statement(s)                                  ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processDevice:
        mov ax, CONFIGTYPE_DEVICE
        jmp processAnyDevice

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process DeviceHigh Statement(s)                              ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processDeviceHigh:

        Entry
        ddef _ConfigStatements, es, di
        def  _memorystrategy

        Int21 GetAllocationStrategy                     ; get current allocation scheme
        storarg _memorystrategy, ax

        mov bx, _MEM_FIRSTFIT_HIGH
        Int21 SetAllocationStrategy

        mov ax, CONFIGTYPE_DEVICEHIGH
        getdarg es, di, _ConfigStatements
        call processAnyDevice

        getarg bx, _memorystrategy
        Int21 SetAllocationStrategy
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Common Device Load                                           ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processAnyDevice:

        Entry
        def  _type, ax
        def  _SegAddress
        def  _SegSize, -1

        ddef _ptrInitCommandLine
        ddef _ConfigStatements, es, di
        ddef _CurrentStatement
        ddef _ExecBlock
        ddef _strategy
        ddef _interrupt
        ddef _loadSize

        defbytes reqBlock, sizeINITReqHeader
        defbytes _devicename, 128
        defbytes _arguments, 128

processAnyDevice_08:
        getarg ax, _type
        call _findStatementType                         ; find statement type
        ifc processAnyDevice_24                         ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        stordarg _CurrentStatement, es, di              ; current statement at '='
        call ConfigPrompt                               ; check for ?= or F8 case
        ifc processAnyDevice_66                         ; if ignore -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  allocate memory, load device and initialize
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        mov ax, DEVICEINIT * 256
        lea di, offset reqBlock [ bp ]
        call initReqBlock                               ; initialize request block

        mov bx, 0FFFFh
        Int21 AllocateMemory                            ; get largest available memory block
        storarg _SegSize, bx                            ; store size of segment
        Int21 AllocateMemory                            ; else allocate largets available
        ifc processAnyDevice_66                         ; if can't, should display an error message -->

        mov word ptr [ _ExecBlock. loverSegLoadAddress ][ bp ], ax
        mov word ptr [ _ExecBlock. loverRelocFactor    ][ bp ], ax
        storarg _SegAddress, ax                         ; store address of segment

        add ax, word ptr [ _SegSize ][ bp ]             ; add alloc size to segment (max size)
        dec ax                                          ; protection
        mov word ptr [ reqBlock. irEndAddress. _segment ][ bp ], ax
        mov word ptr [ reqBlock. irEndAddress. _pointer ][ bp ], 0000

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  scan command line parsing out extra characters at the start of name
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        push ds
        push es
        getdarg ds, si, _CurrentStatement               ; current statement at '='

processAnyDevice_16:
        lodsb
        or al, al
        ifz processAnyDevice_64                         ; if no name, can't load
        cmp al, '='
        jz processAnyDevice_16                          ; skip = -->
        cmp al, '?'
        jz processAnyDevice_16                          ; skip ? -->
        cmp al, ' '
        jz processAnyDevice_16                          ; skip space  -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  copy device name and path
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        lea bx, offset _devicename [ bp ]
        dec si
        push si

processAnyDevice_20:
        lodsb
        or al, al
        jz processAnyDevice_22
        cmp al, ' '
        jz processAnyDevice_22

        mov byte ptr ss:[ bx ], al
        inc bx
        jmp processAnyDevice_20

processAnyDevice_22:
        mov byte ptr ss:[ bx ], 00

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  copy entire line to arguments
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        pop si
        lea bx, offset _arguments [ bp ]
        mov word ptr [ reqBlock. irParamAddress. _segment ][ bp ], ss
        mov word ptr [ reqBlock. irParamAddress. _pointer ][ bp ], bx

processAnyDevice_26:
        lodsb
        or al, al
        jz processAnyDevice_28                          ; if end of filename -->

        mov byte ptr ss:[ bx ], al
        inc bx
        jmp processAnyDevice_26

processAnyDevice_28:
        mov byte ptr ss:[ bx ], controlM
        mov byte ptr ss:[ bx + 1 ], controlM

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  load program
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        mov ax, ss
        mov es, ax
        mov ds, ax
        lea bx, offset _ExecBlock [ bp ]                ; address of exec block
        lea dx, offset _devicename [ bp ]               ; address of device name
        Int21 ExecuteProgram, 03h                       ; load overlay
        stordarg _loadSize, bx, cx                      ; load size
        jnc processAnyDevice_32                         ; if succesful -->

        mov si, offset RxDOSmsg_CouldNotLoadDriver
        call RxDOSIni_TypeMessage                       ; say couldn't load ...

        lea si, offset _devicename [ bp ]               ; address of device name
        call RxDOSIni_TypeMessage                       ; ... say which driver
        jmp processAnyDevice_60                         ; go release memory when load failed -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  call device init
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

processAnyDevice_32:
        xor bx, bx
        getarg es, _SegAddress
        mov ax, word ptr es:[ devStrategy  ][ bx ]
        stordarg _strategy, es, ax

        mov ax, word ptr es:[ devInterrupt ][ bx ]
        stordarg _interrupt, es, ax

        setES ss
        lea bx, offset reqBlock [ bp ]
        mov word ptr [ reqBlock. rhStatus ][ bp ], OP_DONE

        mov al, byte ptr [ _RxDOS_bNumBlockDev ]
        mov byte ptr [ reqBlock. irDriveNumber ][ bp ], al
        mov byte ptr [ reqBlock. irUnits       ][ bp ], 00

        push bp
        mov ds, word ptr [ _strategy. _segment ][ bp ]
        call dword ptr [ _strategy ][ bp ]              ; strategy

        pop bp
        push bp
        lea bx, offset reqBlock [ bp ]
        mov ds, word ptr [ _strategy. _segment ][ bp ]
        call dword ptr [ _interrupt ][ bp ]             ; interrupt
        pop bp

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  free up any extra memory
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        setDS ss
        getarg es, _SegAddress
        test word ptr [ reqBlock. rhStatus ][ bp ], OP_ERROR
        jnz processAnyDevice_60                         ; if error -->

     ; compute actual size (in bx:cx)

        mov bx, word ptr [ reqBlock. irEndAddress. _pointer ][ bp ]
        add bx, (sizePARAGRAPH - 1)                     ; round up to nearest para boundary

        shr bx, 1
        shr bx, 1
        shr bx, 1
        shr bx, 1                                       ; end para
        add bx, word ptr [ reqBlock. irEndAddress. _segment ][ bp ]
        sub bx, word ptr [ _SegAddress ][ bp ]          ; paragraph size
        jc processAnyDevice_60                          ; no size, go free-up -->
        jz processAnyDevice_60                          ; no size, go free-up -->

        Int21 ModifyAllocatedMemory                     ; free memory to given size

     ; is driver a file system or blocked device ?

        test word ptr es:[ devAttributes ], DEV_CHAR    ; is it a character device ?
        jnz processAnyDevice_56                         ; yes -->

        mov dx, es                                      ; driver address (segment)
        mov cl, byte ptr [ reqBlock. irUnits ][ bp ]    ; get # device units
        call InitializeAttachedFileSystem

        mov cl, byte ptr [ reqBlock. irUnits ][ bp ]
        add byte ptr [ _RxDOS_bNumBlockDev ], cl

processAnyDevice_56:
        mov bx, word ptr [ _RxDOS_NULLDev. _segment ]
        mov ax, word ptr [ _RxDOS_NULLDev. _pointer ]
        mov word ptr es:[ devLink. _segment ], bx
        mov word ptr es:[ devLink. _pointer ], ax

        mov word ptr [ _RxDOS_NULLDev. _segment ], es
        mov word ptr [ _RxDOS_NULLDev. _pointer ], 0000
        jmp short processAnyDevice_64

processAnyDevice_60:
        getarg es, _SegAddress
        Int21 FreeAllocatedMemory                       ; if error while loading

processAnyDevice_64:
        pop es
        pop ds

processAnyDevice_66:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processAnyDevice_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processAnyDevice_24:
        getdarg es, di, _ConfigStatements               ; return
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process DOS Statement                                        ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processDOS:

        Entry
        ddef _ConfigStatements, es, di
        def  _DOS, 0000                                 ; no UMB, no HMA

processDOS_08:
        mov ax, CONFIGTYPE_DOS
        call _findStatementType                         ; find statement type
        jc processDOS_24                                ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        call ConfigPrompt                               ; check for ?= or F8 case
        jc processDOS_12                                ; ignore statement -->

processDOS_10:
        mov si, offset _RxDOS_ConfigDOSOptions
        call _findCommand                               ; locate options like high and umb
        jc processDOS_12                                ; if none of the above -->
        or word ptr [ _DOS ][ bp ], dx                  ; or options

        call _nextArgument                              ; point to next argument
        jnc processDOS_10                               ; go porcess -->

processDOS_12:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processDOS_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processDOS_24:
        getarg ax, _DOS                                 ; get DOS
        getdarg es, di, _ConfigStatements               ; 
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process FCBS Statement(s)                                    ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processFCBS:

        Entry
        ddef _ConfigStatements, es, di
        ddef _FCBS, 0, DEFAULT_FCBS

processFCBS_08:
        mov ax, CONFIGTYPE_FCBS
        call _findStatementType                         ; find statement type
        jc processFCBS_24                              ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        call ConfigPrompt                               ; check for ?= or F8 case
        jc processFCBS_16                               ; if ignore -->

        mov cx, 1
        mov dx, CONFIGMAX_FCBS_X
        call _getNumber
        jc processFCBS_16                              ; if beyond range -->
        mov word ptr [ _FCBS. _low  ][ bp ], ax        ; else ok to save

        mov cx, 0
        mov dx, CONFIGMAX_FCBS_Y
        call _getNumber
        jc processFCBS_16                              ; if beyond range -->
        mov word ptr [ _FCBS. _high ][ bp ], ax        ; else ok to save

processFCBS_16:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processFCBS_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processFCBS_24:
        getdarg dx, ax, _FCBS                           ; return FCBS
        getdarg es, di, _ConfigStatements               ; 
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Files Statement(s)                                   ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processFiles:

        Entry
        ddef _ConfigStatements, es, di
        def _files, DEFAULT_FILES
        def  _fcbs, ax 

processFiles_08:
        mov ax, CONFIGTYPE_FILES
        call _findStatementType                         ; find statement type
        jc processFiles_24                              ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        call ConfigPrompt                               ; check for ?= or F8 case
        jc processFiles_12                              ; if ignore -->

        mov cx, 1
        mov dx, CONFIGMAX_FILES
        call _getNumber
        jc processFiles_12                              ; if beyond range -->
        storarg _files, ax                              ; else ok to save

processFiles_12:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processFiles_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processFiles_24:
        getarg ax, _files                               ; return files
        add ax, word ptr [ _fcbs ][ bp ]
        call RxDOSini_SFTSubSystem                      ; init SFTs

        getdarg es, di, _ConfigStatements               ; 
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Last Drive                                           ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processLastDrive:

        Entry
        ddef _ConfigStatements, es, di
        def  _LastDrive, DEFAULT_LASTDRIVE   

processLastDrive_08:
        mov ax, CONFIGTYPE_LASTDRIVE
        call _findStatementType                         ; find statement type
        jc processLastDrive_24                          ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        call ConfigPrompt                               ; check for ?= or F8 case
        jc processLastDrive_12                          ; if ignore -->

        xor ax, ax
        mov al, byte ptr es:[ di ]
        call upperCase
        cmp al, 'A'
        jc processLastDrive_12
        cmp al, 'Z'+1
        jnc processLastDrive_12
        storarg _LastDrive, ax

processLastDrive_12:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processLastDrive_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processLastDrive_24:
        getarg ax, _LastDrive                           ; get last drive info, if any
        and ax, 1Fh
        mov byte ptr [ _RxDOS_bLastDrive ], al          ; save in DOS

        call RxDOSini_DPBSubSystem                      ; (order important)
        call RxDOSini_CDSSubSystem                      ; init drives/current dirs

        getdarg es, di, _ConfigStatements               ; 
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process NumLock Statement                                    ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processNumLock:

        Entry
        ddef _ConfigStatements, es, di
        def  _numlock, -1                               ; 0 is off; 1 is on.

processNumLock_08:
        mov ax, CONFIGTYPE_NUMLOCK
        call _findStatementType                         ; find statement type
        jc processNumLock_24                            ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        call ConfigPrompt                               ; check for ?= or F8 case
        jc processNumLock_12                            ; if ignore -->

        mov si, offset _RxDOS_ConfigOnOff
        call _findCommand                               ; locate on or off
        jc processNumLock_12                            ; if none of the above -->
        storarg _numlock, dx                            ; else ok to save

processNumLock_12:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processNumLock_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processNumLock_24:
        push es
        getarg ax, _numlock                             ; get numlock
        cmp ax, -1                                      ; any change ?
        jz processNumLock_46                            ; if no change -->

        mov bx, 40h
        mov es, bx                                      ; BIOS communications area
        mov bx, offset _BIOS_KeyboardFlags              ; keyboard status flags
        or ax, ax                                       ; set num lock ?
        jnz processNumLock_32                           ; if set -->

        and byte ptr es:[ bx ], NOT ( _BIOS_KB_NumLock )
        jmp short processNumLock_46

processNumLock_32:
        or byte ptr es:[ bx ], _BIOS_KB_NumLock

processNumLock_46:
        pop es
        getdarg es, di, _ConfigStatements
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Shell Statement                                      ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processShell:

        Entry
        ddef _ConfigStatements, es, di

processShell_08:
        mov ax, CONFIGTYPE_SHELL
        call _findStatementType                         ; find statement type
        jc processShell_24                              ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        call ConfigPrompt                               ; check for ?= or F8 case
        jc processShell_12                              ; if ignore -->

        push es
        push di
        push ds
        mov bx, offset _RxDOSini_CommandShell
        push bx
        call CopyString

processShell_12:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processShell_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processShell_24:
        getdarg es, di, _ConfigStatements               ; 
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Stack Statement(s)                                   ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processStack:

        Entry
        ddef _ConfigStatements, es, di
        ddef _stacks, 0, DEFAULT_STACKS

processStack_08:
        mov ax, CONFIGTYPE_STACKS
        call _findStatementType                         ; find statement type
        jc processStack_24                              ; if no more -->

        push es
        push di
        lea di, offset [ configStatement ][ di ]
        call ConfigPrompt                               ; check for ?= or F8 case
        jc processStack_16                              ; if ignore -->

        mov cx, CONFIGMIN_STACKS_X
        mov dx, CONFIGMAX_STACKS_X
        call _getNumber
        jc processStack_16                              ; if beyond range -->
        mov word ptr [ _stacks. _low  ][ bp ], ax       ; else ok to save

        mov cx, CONFIGMIN_STACKS_Y
        mov dx, CONFIGMAX_STACKS_Y
        call _getNumber
        jc processStack_16                              ; if beyond range -->
        mov word ptr [ _stacks. _high ][ bp ], ax       ; else ok to save

processStack_16:
        pop di
        pop es
        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processStack_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processStack_24:
        getdarg dx, ax, _stacks                         ; return stacks
        getdarg es, di, _ConfigStatements               ; 
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Switch Char                                          ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  es:di  start of statements in saved config buffer            ;
        ;...............................................................;

processSwitchChar:

        Entry
        ddef _ConfigStatements, es, di
        def  _SwitchChar, '/'

processSwitchChar_08:
        mov ax, CONFIGTYPE_SWITCHCHAR
        call _findStatementType                         ; find statement type
        jc processSwitchChar_24                         ; if no more -->

        xor ax, ax
        mov al, byte ptr es:[ configStatement ][ di ]
        storarg _SwitchChar, ax                         ; save last drive info

        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_PROCESSED
        add di, word ptr es:[ configLength ][ di ]
        jmp processSwitchChar_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processSwitchChar_24:
        getarg ax, _SwitchChar                          ; get last drive info, if any
        mov byte ptr [ _RxDOS_bSwitchChar ], al

        getdarg es, di, _ConfigStatements               ; 
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Remove Comments, Leading Blanks, Blank Lines                 ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  ax     comment character(s)                                  ;
        ;  cx     current line count                                    ;
        ;  ss:di  line read from disk                                   ;
        ;                                                               ;
        ;  This reads through blocks and changes each block to a REM    ;
        ;  block that was not selected as a menu option.                ;
        ;...............................................................;

configRemoveComments:

        call _skipSpaces

        push di                                         ; save buffer pointer
        cmp ah, 0                                       ; double character comments ?
        jnz configRemoveComments_12                     ; yes -->
        
configRemoveComments_06:
        cmp al, byte ptr ss:[ di ]                      ; is it comment character ?
        jz configRemoveComments_20                      ; yes -->
        inc di
        loop configRemoveComments_06
        jmp short configRemoveComments_20

configRemoveComments_12:
        cmp ax, word ptr ss:[ di ]                      ; is it comment character ?
        jz configRemoveComments_20                      ; yes -->
        inc di
        loop configRemoveComments_12

configRemoveComments_20:
        mov cx, di
        pop di
        sub cx, di                                      ; new length
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Find Statement Type                                          ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  ax     config item type                                      ;
        ;  es:di  configure table.                                      ;
        ;...............................................................;

_findStatementType:
        cmp word ptr es:[ configType ][ di ], CONFIGTYPE_ENDOFARGS
        jnz _findStatementType_08
        stc
        ret

_findStatementType_08:
        cmp ax, word ptr es:[ configType ][ di ]        ; is it menu type ?
        jnz _findStatementType_12                       ; if not, goto next -->
        or di, di
        ret

_findStatementType_12:
        add di, word ptr es:[ configLength ][ di ]
        jmp _findStatementType
        
        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Config Statement Prompt                                      ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  ax     statement type                                        ;
        ;  es:di  pointer to first non-space after keyword              ;
        ;...............................................................;

ConfigPrompt:

        Entry
        ddef _configTextPtr, es, di

        cmp word ptr es:[ di ], '=?'                    ; is it ?= 
        jz ConfigPrompt_12                              ; yes, go prompt -->
        cmp word ptr cs:[ F8_PromptRequired ], 0000     ; F8_prompt required ?
        jz ConfigPrompt_24                              ; no, go skip = if set -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
;  prompt statement
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
ConfigPrompt_12:

        push ds
        setDS cs
        mov dx, offset msgProcessCommandYesNo
        Int21 DisplayString

ConfigPrompt_16:
        xor ax, ax
        int 16h

        call upperCase
        cmp al, 'Y'                                     ; check for Yes
        jz ConfigPrompt_20                              ; 
        cmp al, 'N'                                     ; check for No
        jnz ConfigPrompt_16

ConfigPrompt_20:
        mov dl, al
        Int21 DisplayOutput                             ; echo character

        mov dx, offset msgNewLine
        Int21 DisplayString

        pop ds
        getdarg es, di, _configTextPtr
        cmp al, 'N'                                     ; if No
        stc                                             ; set carry if No
        jz ConfigPrompt_36                              ; exit -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
;  Skip ? and ?= and any spaces which follow
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
ConfigPrompt_24:
        cmp word ptr es:[ di ], '=?'                    ; '?=' in prompt ?
        jnz ConfigPrompt_26                             ; no -->
        inc di                                          ; skip over question mark

ConfigPrompt_26:
        cmp byte ptr es:[ di ], '='                     ; '=' in prompt ?
        jnz ConfigPrompt_28                             ; no -->
        inc di                                          ; skip over equal sign

ConfigPrompt_28:
        cmp byte ptr es:[ di ], ' ' + 1                 ; space follows ?
        jnz ConfigPrompt_32                             ; no, return -->
        inc di                                          ; skip over equal sign
        jmp ConfigPrompt_28                             ; loop through all spaces -->

ConfigPrompt_32:
        clc                                             ; clear carry

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
;  Skip ? and ?= if 
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
ConfigPrompt_36:
        Return
        
        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Skip To Next Argument                                        ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Usage:                                                       ;
        ;  es:di   points to line buffer                                ;
        ;...............................................................;

_nextArgument:

        cmp byte ptr es:[ di ], ' '                     ; ignore spaces
        jz _nextArgument_06
        cmp byte ptr es:[ di ], '='                     ; ignore equal signs
        jz _nextArgument_06
        cmp byte ptr es:[ di ], ','                     ; ignore commas
        jnz _nextArgument_08

_nextArgument_06:
        inc di
        jmp _nextArgument

_nextArgument_08:
        cmp byte ptr es:[ di ], ' '                     ; carry means end of line
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Process Menus                                                ;
        ;...............................................................;

configMenu:
        Entry
        ddef _ConfigStatements, es, di

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  identify all common components as enabled.
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

configMenu_04:
        mov ax, CONFIGTYPE_MENUBLOCK
        mov bx, offset Config_CommonSelector
        call _findConfigMenuStatement                   ; identify common components
        jc configMenu_08                                ; if none left -->

        or word ptr es:[ configFlags ][ di ], CONFIGFLAG_ENABLED
        add di, word ptr es:[ configLength ][ di ]
        jmp configMenu_04

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  search for menu starter
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

configMenu_08:
        mov ax, CONFIGTYPE_MENUBLOCK
        mov bx, offset Config_MenuSelector
        getdarg es, di, _ConfigStatements
        call _findConfigMenuStatement
        jc configMenu_68

     ; ...

configMenu_68:
        Return

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Remove Unused Blocks                                         ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  ES:DI  Configure Table.                                      ;
        ;                                                               ;
        ;  This reads through blocks and changes each block to a REM    ;
        ;  block that was not selected as a menu option.                ;
        ;...............................................................;

removeUnusedBlocks:
        mov ax, CONFIGTYPE_MENUBLOCK
        call _findStatementType                         ; find start of block
        jc removeUnusedBlocks_32                        ; if none left -->

removeUnusedBlocks_08:
        test word ptr es:[ configFlags ][ di ], CONFIGFLAG_ENABLED
        jz removeUnusedBlocks_12                        ; if disabled, delete -->
        add di, word ptr es:[ configLength ][ di ]
        jmp removeUnusedBlocks                          ; if enabled, we'll keep ->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  remove disabled blocks
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
removeUnusedBlocks_12:
        mov word ptr es:[ configType ][ di ], CONFIGTYPE_REM
        add di, word ptr es:[ configLength ][ di ]

        cmp word ptr es:[ configType ][ di ], CONFIGTYPE_ENDOFARGS
        jz removeUnusedBlocks_32                        ; if none left -->
        cmp word ptr es:[ configType ][ di ], CONFIGTYPE_MENUBLOCK
        jz removeUnusedBlocks_08                        ; if next block -->
        jmp removeUnusedBlocks_12                       ; go remove -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
removeUnusedBlocks_32:
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Find Menu Statement                                          ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  ax     config item type                                      ;
        ;  bx     menu name                                             ;
        ;  es:di  configure table.                                      ;
        ;...............................................................;

_findConfigMenuStatement:

        cmp word ptr es:[ configType ][ di ], CONFIGTYPE_ENDOFARGS
        jnz _findConfigMenuStatement_08
        stc
        ret

_findConfigMenuStatement_08:
        cmp ax, word ptr es:[ configType ][ di ]        ; is it menu type ?
        jnz _findConfigMenuStatement_32                 ; if not, goto next -->

        push di
        push bx
        push ax
        lea di, offset [ configStatement ][ di ]
        
_findConfigMenuStatement_12:
        mov al, byte ptr [ bx ]                         ; get character
        call upperCase                                  ; upper case

        mov ah, al
        mov al, byte ptr es:[ di ]
        call upperCase                                  ; upper case

        inc bx
        inc di
        cmp ah, al                                      ; compare strings
        jnz _findConfigMenuStatement_28                 ; if not equal -->

        or al, al                                       ; both null terminators ?
        jnz _findConfigMenuStatement_12                 ; not yet -->

        pop ax
        pop bx
        pop di
        or di, di
        ret

_findConfigMenuStatement_28:
        pop ax
        pop bx
        pop di

_findConfigMenuStatement_32:
        add di, word ptr es:[ configLength ][ di ]
        jmp _findConfigMenuStatement
        
        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Get Number                                                   ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Input:                                                       ;
        ;  cx      min acceptable number                                ;
        ;  dx      max acceptable number                                ;
        ;  es:di   points to line buffer                                ;
        ;                                                               ;
        ;  Returns:                                                     ;
        ;  ax      number, if any                                       ;
        ;  di      pointer to argument past command                     ;
        ;  cy      not a number                                         ;
        ;...............................................................;

_getNumber:
        push cx
        xor ax, ax

_getNumber_08:
        cmp byte ptr es:[ di ], '0'                     ; valid digit ?
        jc  _getNumber_26                               ; no longer -->
        cmp byte ptr es:[ di ], '9' +  1                ; valid digit ?
        jnc _getNumber_26                               ; no longer -->

        mov cx, ax
        add ax, ax                                      ; 2
        add ax, ax                                      ; 4
        add ax, cx                                      ; 5
        add ax, ax                                      ; 10

        mov cl, byte ptr es:[ di ]                      ; get digit
        and cx, 15
        add ax, cx

        inc di
        jmp _getNumber_08

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  check for error
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_getNumber_26:
        pop cx
        or ax, ax
        pushf                                           ; save current status
        cmp ax, cx                                      ; is it at least as large as ...
        jc _getNumber_32                                ; no -->
        cmp ax, dx                                      ; is it greater than ...
        jle _getNumber_36                               ; if within range -->

_getNumber_32:
        popf
        stc
        pushf                                           ; change status

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  skip to next argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_getNumber_36:
        cmp byte ptr es:[ di ], ' '
        jc _getNumber_48                                ; if control character 
        jz _getNumber_38                                ; if space -->

        cmp byte ptr es:[ di ], ':'                     ; ignore colons
        jz _getNumber_38
        cmp byte ptr es:[ di ], '='                     ; ignore equal signs
        jz _getNumber_38
        cmp byte ptr es:[ di ], ','                     ; ignore commas
        jnz _getNumber_48

_getNumber_38:
        inc di
        jmp _getNumber_36

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  return
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_getNumber_48:
        popf
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Find Command                                                 ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Input:                                                       ;
        ;  es:di   points to line buffer                                ;
        ;  cs:si   table to search                                      ;
        ;                                                               ;
        ;  Returns:                                                     ;
        ;  dx      command type                                         ;
        ;  di      pointer to argument past command                     ;
        ;  cy      command not found                                    ;
        ;...............................................................;

_findCommand:
        cmp word ptr cs:[ si ], -1
        jnz _findCommand_12                             ; if not end of table ->
        cmp word ptr cs:[ si + 2 ], 0
        jz _findCommand_Error                           ; if end -->

_findCommand_12:
        push word ptr cs:[ cStmtType ][ si ]            ; if item matches
        lea si, offset cStmtName [ si ]                 ; skip to name

        xor bx, bx

_findCommand_18:
        mov al, byte ptr es:[ di + bx ]                 ; get character
        call lowerCase                                  ; lower case character
        cmp al, byte ptr cs:[ si + bx ]                 ; this command ?
        jnz _findCommand_32                             ; not this command -->

        inc bx
        cmp byte ptr cs:[ si + bx ], 0                  ; end of string ?
        jnz _findCommand_18                             ; not yet -->

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  if command match is made, skip to next argument
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        add di, bx                                      ; offset

_findCommand_22:
        cmp byte ptr es:[ di ], 0
        jz  _findCommand_26
        cmp byte ptr es:[ di ], ' ' + 1                 ; skip spaces
        jnc _findCommand_26

        inc di
        jmp _findCommand_22

_findCommand_26:
        pop dx                                          ; statement type
        or dx, dx
        ret

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  if not a match, try next command in table
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_findCommand_32:
        inc si                                          ; increment past 
        cmp byte ptr cs:[ si - 1 ], 0                   ; end of string ?
        jnz _findCommand_32                             ; loop -->

        pop ax                                          ; ignore saved stmt type
        jmp _findCommand                                ; continue -->

_findCommand_Error:
        stc
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Skip Leading Spaces                                          ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Usage:                                                       ;
        ;  ss:di   points to line buffer                                ;
        ;...............................................................;

_skipSpaces:
        cmp byte ptr ss:[ di ], 0
        jz  _skipSpaces_08
        cmp byte ptr ss:[ di ], ' ' + 1
        jnc _skipSpaces_08

        inc di
        jmp _skipSpaces

_skipSpaces_08:
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Skip To Next Space                                           ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Usage:                                                       ;
        ;  ss:di   points to line buffer                                ;
        ;...............................................................;

_scanToEndofName:
        cmp byte ptr ss:[ di ], 0
        jz  _scanToEndofName_08

        mov al, byte ptr ss:[ di ]
        cmp al, ' ' + 1
        jc _scanToEndofName_08
        call upperCase
        cmp al, 'Z' + 1
        jnc _scanToEndofName_08

        inc di
        jmp _scanToEndofName

_scanToEndofName_08:
        cmp byte ptr ss:[ di ], 0
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  RxDOS Memory Subsystem Initialize                            ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  No Parameters Required.                                      ;
        ;                                                               ;
        ;  The memory subsystem used by RxDOS is initialized.  All      ;
        ;  previous memory allocations are lost.                        ;
        ;                                                               ;
        ;...............................................................;

RxDOSini_MemorySubSystem:

        saveSegments
        mov ax, 40h
        mov es, ax                                      ; BIOS communications area

        xor bx, bx
        mov ax, word ptr es:[ _BIOS_Memory ][ bx ]
        shl ax, 1                                       ; multiply * 64k
        shl ax, 1                                       ;
        shl ax, 1                                       ;
        shl ax, 1                                       ;
        shl ax, 1                                       ;
        shl ax, 1                                       ; max segment
        sub ax, word ptr [ _RxDOS_pStartMemBlock ]      ; available memory
        dec ax                                          ; adjust for mem header
        push ax

        mov bx, _RxDOS_PARENT_SIGNATURE                 ; system block
        mov es, word ptr [ _RxDOS_pStartMemBlock ]      ; available memory
        call _initializeMemoryBlock                     ; initialize memory block.

        mov ax, word ptr es:[ _memAlloc ]
        mov word ptr es:[ _memAlloc ], 0000             ; original now is allocate 1 block
        mov byte ptr es:[ _memSignature ], _RxDOS_MEMSIGNATURE

        dec ax
        mov dx, es
        inc dx
        mov es, dx                                      ; where to allocate next
        xor bx, bx                                      ; system block
        call _initializeMemoryBlock                     ; initialize memory block.
        mov byte ptr es:[ _memSignature ], _RxDOS_ENDSIGNATURE

        pop ax                                          ; memory available
        restoreSegments
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Sub Allocate System Space                                    ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Input:                                                       ;
        ;   ax     space in bytes to sub allocate                       ;
        ;                                                               ;
        ;  Output:                                                      ;
        ;   es:di  pointer to allocated space                           ;
        ;   ax     space in bytes allocated                             ;
        ;   cx     (same as ax)                                         ;
        ;...............................................................;

AllocateSystemSpace:

        push bx
        push ax                                         ; save bytes to allocate
        xor di, di

        add ax, (sizeMEMBLOCK) - 1                      ; round up to next block
        shr ax, 1
        shr ax, 1
        shr ax, 1
        shr ax, 1                                       ; create para address

        mov es, word ptr [ _RxDOS_pStartMemBlock ]      ; get start sys memory
        mov bx, es
        add bx, word ptr es:[ _memAlloc ][ di ]         ; point to end segment
        add word ptr es:[ _memAlloc ][ di ], ax         ; add new allocation bytes
        mov dx, word ptr es:[ _memAlloc ][ di ]

        inc bx
        mov es, bx                                      ; point to free segment
        sub ax, word ptr es:[ _memAlloc ][ di ]         ; get free segments
        neg ax

        inc dx
        add dx, word ptr [ _RxDOS_pStartMemBlock ]      ; get start sys memory
        mov es, dx                                      ; where new allocation

        push bx                                         ; segment address available
        xor bx, bx
        call _initializeMemoryBlock                     ; puts end block at es:bx
        mov byte ptr es:[ _memSignature ][ di ], _RxDOS_ENDSIGNATURE

        pop es                                          ; segment address available
        pop cx                                          ; space allocated ( bytes )
        push cx                                         ; save
        xor di, di
        clearMemory                                     ; clear area

        pop cx                                          ; space allocated ( bytes )
        pop bx                                          ; original bx
        xor di, di
        mov ax, cx
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  RxDOS Disk Parameter Blocks SubSystem Initialize             ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  No Parameters Required.                                      ;
        ;...............................................................;

RxDOSini_DPBSubSystem:

        push ds
        setDS cs
        setES cs

        mov al, sizeDPB
        mul byte ptr [ _RxDOS_bLastDrive ]              ; number of logical devices
        call AllocateSystemSpace                        ; allocate dpb's for all 26 devices.

        mov word ptr [ _RxDOS_pDPB. _pointer ], di 
        mov word ptr [ _RxDOS_pDPB. _segment ], es

        xor ax, ax
        xor cx, cx
        mov cl, byte ptr [ _RxDOS_bLastDrive ]
        setDS es                                        ; point to PDB area

    ; values are defaults w/o special meaning 
    ; actual values are assigned later by calling driver

RxDOS_DPBinit_12:
        mov byte ptr [ _dpbDrive            ][ di ], al
        mov byte ptr [ _dpbUnit             ][ di ], al
        mov word ptr [ _dpbBytesPerSector   ][ di ], 512
        mov byte ptr [ _dpbClusterSizeMask  ][ di ], 0FEh
        mov byte ptr [ _dpbClusterSizeShift ][ di ], 0
        mov word ptr [ _dpbFirstFAT         ][ di ], 0001
        mov byte ptr [ _dpbNumCopiesFAT     ][ di ], 2
        mov word ptr [ _dpbMaxAllocRootDir  ][ di ], 64
        mov word ptr [ _dpbFirstDataSector  ][ di ], 9
        mov word ptr [ _dpbMaxClusterNumber ][ di ], 352

        mov word ptr [ _dpbSectorsPerFat    ][ di ], 2
        mov word ptr [ _dpbFirstDirSector   ][ di ], 5
        mov word ptr [ _dpbptrDeviceDriver. _segment ][ di ], NULL
        mov word ptr [ _dpbptrDeviceDriver. _pointer ][ di ], NULL
        mov byte ptr [ _dpbMediaDescriptor  ][ di ], 0
        mov byte ptr [ _dpbAccessFlag       ][ di ], -1 ; UNACCESSED

        lea bx, sizeDPB [ di ]                          ; current ptr + size DPB
        mov word ptr [ _dpbNextDPB. _segment ][ di ], ds
        mov word ptr [ _dpbNextDPB. _pointer ][ di ], bx
        mov word ptr [ _dpbNextFree          ][ di ], 0000
        mov word ptr [ _dpbFreeCount         ][ di ], -1

        inc ax
        mov di, bx
        loop RxDOS_DPBinit_12

    ;  set end marker at last DPB

        mov word ptr [ _dpbNextDPB. _segment - sizeDPB ][ di ], -1
        mov word ptr [ _dpbNextDPB. _pointer - sizeDPB ][ di ], -1

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  loop through DPB's and assign drivers
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        setES cs
        mov bx, offset _RxDOS_NULLDev                   ; get start of chain
        mov ax, sizeDPB
        mul byte ptr cs:[ _RxDOS_bNumBlockDev ]
        add ax, word ptr cs:[ _RxDOS_pDPB. _pointer ] 
        mov di, ax                                      ; points nth + 1 entry

RxDOS_DPBinit_08:
        cmp bx, -1                                      ; end of list ?
        jz RxDOS_DPBinit_22                             ; if end of list -->

        test word ptr es:[ devAttributes ][ bx ], ( DEV_CHAR )
        jnz RxDOS_DPBinit_14                            ; if a character device -->

        xor cx, cx
        mov cl, byte ptr es:[ devUnits ][ bx ]          ; # logical devices

RxDOS_DPBinit_10:
        sub di, sizeDPB
        mov word ptr [ _dpbptrDeviceDriver. _segment ][ di ], es
        mov word ptr [ _dpbptrDeviceDriver. _pointer ][ di ], bx
        loop RxDOS_DPBinit_10

RxDOS_DPBinit_14:
        les bx, dword ptr es:[ devLink ][ bx ]
        jmp RxDOS_DPBinit_08                            ; go to next ->

RxDOS_DPBinit_22:
        pop ds
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  RxDOS Disk Parameter Blocks SubSystem Initialize             ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  No Parameters Required.                                      ;
        ;...............................................................;

RxDOSini_CDSSubSystem:

        setDS cs
        mov al, sizeCDS
        mul byte ptr [ _RxDOS_bLastDrive ]              ; ax contains offset to current drive
        call AllocateSystemSpace
        mov word ptr [ _RxDOS_pCDS. _segment ], es
        mov word ptr [ _RxDOS_pCDS. _pointer ], di

        mov al, 'A'
        xor cx, cx
        mov cl, byte ptr [ _RxDOS_bLastDrive ]
        lds di, dword ptr [ _RxDOS_pCDS ]

RxDOS_CDSinit_04:
        mov byte ptr es:[ _cdsActualDirectory ][ di ], al
        mov byte ptr es:[ _cdsActualDirectory + 1 ][ di ], ':'
        mov byte ptr es:[ _cdsActualDirectory + 2 ][ di ], '\'
        mov byte ptr es:[ _cdsActualDirectory + 3 ][ di ], 0
        mov byte ptr es:[ _cdsNonSubstOffset ][ di ], 3


        inc al
        add di, sizeCDS
        loop RxDOS_CDSinit_04

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  init DPB values for each CDS
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        setDS cs
        xor cx, cx
        les di, dword ptr [ _RxDOS_pCDS ]
        mov ax, word ptr [ _RxDOS_pDPB. _pointer ] 
        mov dx, word ptr [ _RxDOS_pDPB. _segment ]
        mov cl, byte ptr [ _RxDOS_bNumBlockDev ]

RxDOS_CDSinit_06:
        or word ptr es:[ _cdsFlags ][ di ], _CDS_PHYSICALDRIVE
        mov word ptr es:[ _cdsPtrToDPB. _pointer ][ di ], ax
        mov word ptr es:[ _cdsPtrToDPB. _segment ][ di ], dx
        add ax, sizeDPB
        add di, sizeCDS
        loop RxDOS_CDSinit_06

        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  RxDOS Disk Parameter Blocks SubSystem Initialize             ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  ax  number of files to initialize.                           ;
        ;...............................................................;

RxDOSini_SFTSubSystem:

        setDS cs
        push ax                                         ; files
        mov cx, sizeSFT
        mul cx                                          ; total bytes for SFT's
        add cx, sizeFT

        call AllocateSystemSpace
        mov word ptr [ _RxDOS_pFT. _segment ], es 
        mov word ptr [ _RxDOS_pFT. _pointer ], di

        mov word ptr es:[ nextFTPointer. _pointer ], -1
        pop word ptr es:[ numberSFTEntries ][ di ]

        call RxDOSini_StdInStdOutDrivers                ; initialize drivers
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  RxDOS Disk Parameter Blocks SubSystem Initialize             ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  ax  number of cache buffers to initialize.                   ;
        ;...............................................................;

RxDOSini_CCBSubSystem:

        push ax                                         ; buffers
        mov cx, sizeCCB
        mul cx                                          ; total bytes for cache blocks

        call AllocateSystemSpace
        mov word ptr [ _RxDOS_BufferList. _segment ], es
        mov word ptr [ _RxDOS_BufferList. _pointer ], di

        pop cx                                          ; # buffers
        dec cx                                          ; no like last one
        mov dx, -1                                      ; previous

RxDOS_CCBinit_10:
        lea ax, offset sizeCCB [ di ]
        mov word ptr es:[ ccbNext ][ di ], ax           ; next
        mov word ptr es:[ ccbPrev ][ di ], dx           ; previous
        mov byte ptr es:[ ccbDrive ][ di ], -1          ; unitialized

        mov dx, di                                      ; current becomes previous
        mov di, ax                                      ; go to next
        loop RxDOS_CCBinit_10                           ; go to next -->

        mov di, dx                                      ; at end set end marker
        mov word ptr es:[ ccbNext ][ di ], -1
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  RxDOS Disk Parameter Blocks SubSystem Initialize             ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  ax  number of cache buffers to initialize.                   ;
        ;...............................................................;

RxDOSini_StdInStdOutDrivers:

        mov ax, ( DEV_STDINPUT + DEV_STDOUTPUT )
        call checkforDeviceType
        jc RxDOS_DRIVERinit_10

        mov word ptr [ _RxDOS_pCONdriver. _pointer ], bx
        mov word ptr [ _RxDOS_pCONdriver. _segment ], es

RxDOS_DRIVERinit_10:
        mov ax, ( DEV_CLOCK )
        call checkforDeviceType
        jc RxDOS_DRIVERinit_12

        mov word ptr [ _RxDOS_pCLOCKdriver. _pointer ], bx
        mov word ptr [ _RxDOS_pCLOCKdriver. _segment ], es

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  allocate STDIN, STDOUT, STDERR, STDAUX, STDPRN
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

RxDOS_DRIVERinit_12:
        setDS cs
        mov di, offset stdDeviceAssignTable

RxDOS_DRIVERinit_14:
        setES ds
        call checkforDeviceName                         ; locate device
        jc RxDOS_DRIVERinit_22                          ; if can't be located -->

        push bx
        push es                                         ; save pointer to driver
        call FindAvailableSFTHandle                     ; allocate an available SFT entry (es:bx)
        jc RxDOS_DRIVERinit_22                          ; if can't be located -->
        mov word ptr [ stdIOHandle ][ di ], ax          ; save handle assigned

        mov ax, word ptr [ stdDevInfo ][ di ]
        mov word ptr es:[ sftDevInfo ][ bx ], ax        ; sets mode, sets mode to Ascii

        push di
        push bx
        mov cx, sizeFnName

RxDOS_DRIVERinit_16:
        mov al, byte ptr [ stdDriverName ][ di ]        ; copy name
        mov byte ptr es:[ sftFileName ][ bx ], al
        inc bx
        inc di
        loop RxDOS_DRIVERinit_16

        pop bx
        pop di
        pop word ptr es:[ sftDCB. _segment ][ bx ]
        pop word ptr es:[ sftDCB. _pointer ][ bx ]

RxDOS_DRIVERinit_22:
        add di, sizeStdRedirec
        cmp word ptr [ di ], -1
        jnz RxDOS_DRIVERinit_14

        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Initialize Attached File System                              ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  cl  number of blocked devices                                ;
        ;  dx  device address                                           ;
        ;...............................................................;

InitializeAttachedFileSystem:

        xor ch, ch
        or cx, cx                                       ; any devices declared ?
        jz Init_AttachedFileSystem_16                   ; none -->

        saveSegments di, si

        mov ax, sizeCDS
        mul byte ptr [ _RxDOS_bNumBlockDev ]            ; offset into CDS

        les di, dword ptr [ _RxDOS_pCDS ]
        add di, ax                                      ; pointer to first CDS

        mov ax, sizeDPB
        mul byte ptr [ _RxDOS_bNumBlockDev ]            ; offset into DPB
        lds si, dword ptr [ _RxDOS_pDPB ]               ; starting DPB address in ds: si
        add si, ax                                      ; offset to drive
        xor ax, ax                                      ; logical unit

Init_AttachedFileSystem_08:
        or word ptr es:[ _cdsFlags ][ di ], _CDS_PHYSICALDRIVE
        mov word ptr es:[ _cdsPtrToDPB. _pointer ][ di ], si
        mov word ptr es:[ _cdsPtrToDPB. _segment ][ di ], ds

        mov byte ptr [ _dpbUnit                      ][ si ], al
        mov byte ptr [ _dpbAccessFlag                ][ si ], -1    ; never used before
        mov word ptr [ _dpbptrDeviceDriver. _segment ][ si ], dx    ; driver segment
        mov word ptr [ _dpbptrDeviceDriver. _pointer ][ si ], 0000

        inc ax
        add si, sizeDPB
        add di, sizeCDS
        loop Init_AttachedFileSystem_08

        restoreSegments si, di

Init_AttachedFileSystem_16:
        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  CONFIG Switches                                              ;
        ;...............................................................;

F5_SkipConfigProcessing dw 0000                 ; non-zero if skipping
F8_PromptRequired       dw 0000                 ; non-zero if prompt required

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Config.sys keywords                                          ;
        ;...............................................................;

 IFDEF RxDOS_DEBUG
_RxDOS_ConfigFile:      db 'CONFIG  TST', 0             ; if debug mode

 ELSE
_RxDOS_ConfigFile:      db 'CONFIG  SYS', 0             ; if production

 ENDIF
_RxDOS_ConfigKeywords:  dw CONFIGTYPE_BREAK             ; on | off
                        db 'break', 0

                        dw CONFIGTYPE_BUFFERS           ; n
                        db 'buffers', 0

                        dw CONFIGTYPE_COUNTRY           ; option
                        db 'country', 0

                        dw CONFIGTYPE_COMMENTS          ; option
                        db 'comments', 0

                        dw CONFIGTYPE_DEVICE            ; path and switches
                        db 'devicehigh', 0

                        dw CONFIGTYPE_DEVICE            ; path and switches
                        db 'device', 0

                        dw CONFIGTYPE_DOS               ; umb, high, low, ...
                        db 'dos', 0

                        dw CONFIGTYPE_DRIVPARAM         ; options
                        db 'drivparm', 0

                        dw CONFIGTYPE_FCBS              ; x, y
                        db 'fcbs', 0

                        dw CONFIGTYPE_FILES             ; n
                        db 'files', 0

                        dw CONFIGTYPE_INCLUDE           ; section name
                        db 'include', 0

                        dw CONFIGTYPE_INSTALLHIGH       ; program name and cmd line
                        db 'installhigh', 0

                        dw CONFIGTYPE_INSTALL           ; program name and cmd line
                        db 'install', 0

                        dw CONFIGTYPE_LASTDRIVE         ; letter
                        db 'lastdrive', 0

                        dw CONFIGTYPE_MENUCOLOR         ; = x, y
                        db 'menucolor', 0

                        dw CONFIGTYPE_MENUDEFAULT       ; section name. timeout
                        db 'menudefault', 0

                        dw CONFIGTYPE_MENUITEM          ; section name [, comment ]
                        db 'menuitem', 0

                        dw CONFIGTYPE_MULTITRACK        ; unsupported
                        db 'multitrack', 0

                        dw CONFIGTYPE_NUMLOCK           ; on, off
                        db 'numlock', 0

                        dw CONFIGTYPE_REM               ; always !
                        db 'rem', 0

                        dw CONFIGTYPE_SET               ; always !
                        db 'set', 0

                        dw CONFIGTYPE_SHELL             ; path and switches
                        db 'shell', 0

                        dw CONFIGTYPE_STACKS            ; x, y
                        db 'stacks', 0

                        dw CONFIGTYPE_SUBMENU           ; menu section [, comment ]
                        db 'submenu', 0

                        dw CONFIGTYPE_SWITCHCHAR        ; char
                        db 'switchar', 0

                        dw CONFIGTYPE_SWITCHES          ; not supported
                        db 'switches', 0

                        dw -1, 0

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  True/ False Table                                            ;
        ;...............................................................;

_RxDOS_ConfigTrueFalse: dw TRUE                         ; not really a command
                        db 'true', 0

                        dw FALSE                        ; not really a command
                        db 'false', 0

                        dw -1, 0

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  DOS options                                                  ;
        ;...............................................................;

_RxDOS_ConfigDOSOptions:dw 1                            ; not really a command
                        db 'umb', 0  

                        dw -1                           ; not really a command
                        db 'noumb', 0

                        dw 2                            ; not really a command
                        db 'high', 0

                        dw -2                           ; not really a command
                        db 'low', 0

                        dw -1, 0

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Numlock options                                              ;
        ;...............................................................;

_RxDOS_ConfigOnOff:     dw _ON                          ; not really a command
                        db 'on', 0

                        dw _OFF                         ; not really a command
                        db 'off', 0

                        dw -1, 0

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Error Messages                                               ;
        ;...............................................................;

msgUnknownCommandinConfig: db 'Unrecognized command in config.sys', '$', 0
msgProcessCommandYesNo:    db ' [y,n]?', '$', 0
msgNewLine:                db ('M' - 40h), ('J' - 40h), '$', 0

Config_MenuSelector:       db 'MENU', 0
Config_CommonSelector:     db 'COMMON', 0

 IFDEF RxDOS_DEBUG

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Debug Init                                                   ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Called when in debug mode.                                   ;
        ;                                                               ;
        ;...............................................................;

DebugInit:

        Entry 
        def _floppyDrives
        def _fixedDrives
        defbytes _execBlock, sizeEXEC

        mov cx, cs
        mov ax, offset RxDOS_EndOfInitCode
        add ax, PARAGRAPH - 1
        shr ax, 1
        shr ax, 1
        shr ax, 1
        shr ax, 1
        add cx, ax                                      ; low address available
        mov word ptr ss:[ _RxDOS_pStartMemBlock ], cx   ; until relocation

        mov ax, 40h
        mov es, ax                                      ; BIOS communications area

        xor bx, bx
        mov ax, word ptr es:[ _BIOS_Memory ][ bx ]
        shl ax, 1                                       ; multiply * 64k
        shl ax, 1                                       ;
        shl ax, 1                                       ;
        shl ax, 1                                       ;
        shl ax, 1                                       ;
        shl ax, 1                                       ; max segment
        mov word ptr [ _RxDOS_MaxMemory ], ax           ; memory available

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  driver link
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        currSegment ds

        mov ax, 5200h                                   ; normally this will get done 
        int 21h                                         ; by driver init calls.

        xor di, di
        mov ax, word ptr es:[ _RxDOS_NULLDev. _pointer ][ di ]
        mov dx, word ptr es:[ _RxDOS_NULLDev. _segment ][ di ]
        mov word ptr [ _RxDOS_NULLDev. _pointer ], ax
        mov word ptr [ _RxDOS_NULLDev. _segment ], dx

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  this code should move to IO.SYS
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        call maxBlockDevices 
        mov byte ptr [ _RxDOS_bNumBlockDev ], cl        ; number of block devices

        int 11h                                         ; read hardware configuration

        shr ax, 1                                       ; floppy bit
        shr ax, 1                                       ; math coprocessor
        shr ax, 1                                       ; memory (xt only)
        shr ax, 1                                       ;
        shr ax, 1                                       ; video mode bits
        shr ax, 1                                       ;
        and ax, 0003h
        inc ax
        mov word ptr [ _floppyDrives ][ bp ], ax        ; number of floppy disks
        mov byte ptr [ _RxDOS_CurrentDrive ], 0         ; default to drive A:

        xor bx, bx
        mov ax, 40h
        mov es, ax
        mov al, byte ptr es:[ _BIOS_NumFixedDrives ][ bx ]
        mov word ptr [ _fixedDrives ][ bp ], ax         ; number of fixed drives
        or ax, ax                                       ; any fixed drives ?
        jz _DebugInit_06                                ; none -->
        mov byte ptr [ _RxDOS_CurrentDrive ], 2         ; else default to drive c:

_DebugInit_06:
        add ax, 2                                       ; offset start of fixed by floppy disks
        cmp ax, (DEFAULT_LASTDRIVE AND 1Fh)             ; max dev less than LASTDRIVE ?
        jg _DebugInit_08                                ; no, use available devices -->
        mov ax, (DEFAULT_LASTDRIVE AND 1Fh)             ; use LASTDRIVE

_DebugInit_08:
        cmp al, byte ptr [ _RxDOS_bNumBlockDev ]        ; compare w/ # block devices
        jnc _DebugInit_12                               ; if at least as many block devices -->
        mov al, byte ptr [ _RxDOS_bNumBlockDev ]        ; compare w/ # block devices

_DebugInit_12:
        mov byte ptr [ _RxDOS_bLastDrive ], al          ; number of logical devices

        mov al, byte ptr [ _RxDOS_CurrentDrive ]        ; get current drive
        inc al
        mov byte ptr [ _RxDOS_BootDrive ], al           ; boot drive 

        Return
 ENDIF

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Relocate Data Segment Low                                    ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  DX       where to relocate DS:                               ;
        ;                                                               ;
        ;  At the start of the program, the Data Segment is located at  ;
        ;  the low end of the current CS:.   The  Data  Segment  space  ;
        ;  begins at 0000 and ends at 'SDAExtendedSwapArea'             ;
        ;...............................................................;

relocateDataSegmentLow:

   IFDEF RELOCDATASEG
        ret                                             ; never execute

        mov es, dx                                      ; destination segment
        mov cx, offset SDAExtendedSwapArea              ; size

        xor di, di
        xor si, si
        shr cx, 1                                       ; words
        rep movsw                                       ; copy

    ; stack also moves with data segment

        mov ss, dx                                      ; but offset remains intact
        mov ds, dx                                      ; but offset remains intact
        mov word ptr [ _RxDOS_CurrentSeg ], ds          ; Current Segment.
   ENDIF

        ret

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Initialize                                                   ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  Expects from rxdosbio.sys:                                   ;
        ;                                                               ;
        ;  DL       unit code of startup disk                           ;
        ;  ES:DI    points to SYSINIT block                             ;
        ;...............................................................;

RxDOS_initialize:

        cli                                             ; disable interrupts
        cld                                             ; set direction
        mov ax, cs
        mov ds, ax
        mov ss, ax
        mov sp, offset RxDOS_StackTemp                  ; use temp stack
        mov word ptr [ _RxDOS_CurrentSeg ], ss          ; Current Segment.

        sti

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  initialize data segment
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        Entry 
        defbytes _execBlock, sizeEXEC
        ddef _InitBlockPtr, es, di

 IFDEF RxDOS_DEBUG
        call DebugInit

        mov dl, 02h
        mov dh, dl
        and dx, 807Fh                                   ; save offset, hard drive bit
        rol dh, 1                                       ; hard drive 
        rol dh, 1                                       ; A: or C:
        add dl, dh                                      ; rxdos drive number
        mov byte ptr [ _RxDOS_CurrentDrive ], dl        ; default to drive A:

 ELSE
        mov dl, byte ptr es:[ initBootDrive ][ di ]
        mov dh, dl
        and dx, 807Fh                                   ; save offset, hard drive bit
        rol dh, 1                                       ; hard drive 
        rol dh, 1                                       ; A: or C:
        add dl, dh                                      ; rxdos drive number
        mov byte ptr [ _RxDOS_CurrentDrive ], dl        ; default to drive A:

        inc dl
        mov byte ptr [ _RxDOS_BootDrive ], dl           ; boot drive 

        mov cl, byte ptr es:[ initTotalDrives ][ di ]   ; number of block devices
        mov byte ptr [ _RxDOS_bNumBlockDev ], cl        ; number of block devices
        mov byte ptr [ _RxDOS_bLastDrive ], cl          ; number of logical devices

        mov cx, 4
        mov ax, offset RxDOS_EndOfInitCode
        add ax, PARAGRAPH - 1                           ; adjust to next para boundary
        shr ax, cl
        mov cx, cs
        add cx, ax
        mov word ptr ss:[ _RxDOS_pStartMemBlock ], cx   ; allocate from here

        mov cx, 6
        mov ax, word ptr es:[ initMemParagraphs ][ di ] ; available memory size
        shl ax, cl                                      ; convert to segment address form
        mov word ptr [ _RxDOS_MaxMemory ], ax           ; memory available

        mov ax, word ptr es:[ initDeviceChain. _pointer ][ di ]
        mov dx, word ptr es:[ initDeviceChain. _segment ][ di ]
        mov word ptr [ _RxDOS_NULLDev. _pointer ], ax
        mov word ptr [ _RxDOS_NULLDev. _segment ], dx
 ENDIF
        
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  set interrupt vectors for int 21, 22, ... 28, 2f, 30
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        xor ax, ax
        mov ds, ax
        mov bx, ( 21h * 4 )                             ; int 21h
        mov word ptr _pointer [ bx ], offset _Interrupt_21
        mov word ptr _segment [ bx ], cs

        mov bx, ( 20h * 4 )                             ; int 20h
        mov word ptr _pointer [ bx ], offset _Interrupt_20
        mov word ptr _segment [ bx ], cs

        mov bx, ( 23h * 4 )                             ; int 23h
        mov word ptr _pointer [ bx ], offset _Interrupt_23
        mov word ptr _segment [ bx ], cs

        mov bx, ( 24h * 4 )                             ; int 24h
        mov word ptr _pointer [ bx ], offset _Interrupt_24
        mov word ptr _segment [ bx ], cs

        mov bx, ( 25h * 4 )                             ; int 25h
        mov word ptr _pointer [ bx ], offset _Interrupt_25
        mov word ptr _segment [ bx ], cs

        mov bx, ( 26h * 4 )                             ; int 26h
        mov word ptr _pointer [ bx ], offset _Interrupt_26
        mov word ptr _segment [ bx ], cs

        mov bx, ( 27h * 4 )                             ; int 27h
        mov word ptr _pointer [ bx ], offset _Interrupt_27
        mov word ptr _segment [ bx ], cs

        mov bx, ( 28h * 4 )                             ; int 28h
        mov word ptr _pointer [ bx ], offset _Interrupt_28
        mov word ptr _segment [ bx ], cs

        mov bx, ( 2Ah * 4 )                             ; int 2ah
        mov word ptr _pointer [ bx ], offset _Interrupt_2a
        mov word ptr _segment [ bx ], cs

 IFNDEF RxDOS_DEBUG
        mov bx, ( 2fh * 4 )                             ; int 2fh
        mov word ptr _pointer [ bx ], offset _Interrupt_2f
        mov word ptr _segment [ bx ], cs
 ENDIF

        mov bx, ( 30h * 4 )                             ; jmp far 30h
        mov byte ptr [ bx ], 0EAh                       ; jmp far
        mov word ptr (1 + _pointer)[ bx ], offset _CallDOS
        mov word ptr (1 + _segment)[ bx ], cs

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  this code should move to IO.SYS
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        setDS cs
        call maxBlockDevices 
        mov byte ptr [ _RxDOS_bNumBlockDev ], cl        ; number of block devices

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  initialized Environment Size
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        mov ax, offset _RxDOS_SharedBuffer
        mov word ptr [ _RxDOS_pDTA. _pointer ], ax
        mov word ptr [ _RxDOS_pDTA. _segment ], ds

        mov word ptr [ _RxDOS_CurrentPSP      ], 0000

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  relocate data segment low
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        mov dx, word ptr [ _RxDOS_pStartMemBlock ]      ; where to relocate ds
        call relocateDataSegmentLow

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  initialize memory and other buffers
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        call RxDOSini_MemorySubSystem
        call RxDOSini_DPBSubSystem
        call RxDOSini_CDSSubSystem

        mov ax, DEFAULT_FILES
        call RxDOSini_SFTSubSystem                      ; open CON, AUX, PRN.

        mov ax, DEFAULT_BUFFERS
        call RxDOSini_CCBSubSystem

        mov word ptr [ _RxDOS_UserCodePage   ], DEFAULT_CODEPAGE
        mov word ptr [ _RxDOS_SystemCodePage ], DEFAULT_CODEPAGE

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  if TRACE Build
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 IFDEF RxDOS_TRACEBUILD
;       push ds
;       push es
;       setDS  cs
;
;       xor cx, cx
;       mov dx, offset TraceFile
;       inc word ptr [ _InsideLoggingCall ]             ; disable tracing
;       Int21 CreateFile                                ; create tracefile
;       mov word ptr [ TraceFile_Handle ], bx           ; trace file handle
;       dec word ptr [ _InsideLoggingCall ]             ; restore tracing
;
;       xor ax, ax
;       mov es, ax
;       mov bx, ( 29h * 4 )                             ; int 29h
;       mov ax, word ptr es:[ _pointer ][ bx ]          ; get original int 29 vector
;       mov dx, word ptr es:[ _segment ][ bx ]
;       mov word ptr [ OriginalInt29. _pointer ], ax    ; save original int29 vector
;       mov word ptr [ OriginalInt29. _segment ], dx
;
;       mov word ptr es:[ _pointer ][ bx ], offset _Trace_Interrupt_29
;       mov word ptr es:[ _segment ][ bx ], cs
;
;       pop es
;       pop ds

 ENDIF

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  parse CONFIG.SYS file
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        xor di, di
        mov ax, word ptr [ _RxDOS_MaxMemory ]           ; available memory 
        sub ax, 64 * ( 1024 / 16 )                      ; segments 
        mov es, ax

        call configProcessing                           ; process config.sys file
        call RxDOSini_StdInStdOutDrivers                ; initialize drivers

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  fixup country info segment address
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        mov word ptr ss:[ _RxDOS_CurrCountryInfo. intlCaseMap. _segment ], cs

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  parse command line
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        setDS cs
        setES ss

        lea di, offset _execBlock [ bp ]
        clearMemory sizeEXEC                            ; clear load exec block

        mov al, ' '
        mov cx, 128
        mov di, offset _RxDOSini_CommandShell
        cmp byte ptr es:[ di ], 0                       ; starts with a null character ?
        jz RxDOS_init_36                                ; yes, go do default -->

        cmp byte ptr es:[ di ], al                      ; starts with a space ?
        jnz RxDOS_init_14                               ; no -->
        repz scasb                                      ; scan for first non-space
        or cx, cx                                       ; zero here would mean all spaces
        jz RxDOS_init_36                                ; yes, go do default -->
        dec di                                          ; adj address 

RxDOS_init_14:
        push cx                                         ; save start address
        push di                                         ; save start address
        repnz scasb                                     ; scan for space delimiter
        or cx, cx                                       ; zero means no space delimeter
        jz RxDOS_init_24                                ; no arguments passed -->

        push cx
        dec di                                          ; adj address 
        mov si, di
        mov di, offset _RxDOSini_CommandTail            ; command tail copy
        mov word ptr ss:[ _execBlock. lexecCommandTail. _segment ][ bp ], ss
        mov word ptr ss:[ _execBlock. lexecCommandTail. _pointer ][ bp ], di

        inc di                                          ; store address

RxDOS_init_18:
        lodsb 
        stosb                                           ; copy rest of line
        or al, al                                       ; null terminator ?
        jz RxDOS_init_20                                ; no more than required -->
        loop RxDOS_init_18                              ; no more than required -->

RxDOS_init_20:
        mov ax, di
        sub ax, offset (_RxDOSini_CommandTail + 2)
        mov byte ptr [ _RxDOSini_CommandTail ], al      ; command tail length
        pop cx
        inc cx
        inc cx

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  load rxdoscmd.Com and transfer control
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

RxDOS_init_24:
        pop si                                          ; start of command area
        pop ax
        dec cx
        sub ax, cx
        xchg cx, ax     
        mov di, offset _RxDOS_CommandShell
        rep movsb                                       ; copy shell command/ command line arguments

        lea bx, offset _execBlock [ bp ]                ; exec block address      
        mov dx, offset _RxDOS_CommandShell
        Int21 ExecuteProgram, 00                        ; go execute program
        jnc RxDOS_init_68                               ; only expect to be here if error

RxDOS_init_36:
        lea bx, offset _execBlock [ bp ]                ; exec block address      
        mov dx, offset _RxDOSini_DefaultShell
        Int21 ExecuteProgram, 00                        ; go execute program

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Display Error Message and STOP
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        push cs
        pop ds
        mov si, offset RxDOSmsg_CouldNotFindShell
        cmp ax, errFileNotFound
        jz  RxDOS_init_62

        mov si, offset RxDOSmsg_InvalidPathShell
        cmp ax, errPathNotFound
        jz  RxDOS_init_62

        mov si, offset RxDOSmsg_ArenaTrashedShell
        cmp ax, errArenaTrashed
        jz  RxDOS_init_62

        mov si, offset RxDOSmsg_NotEnoughMemoryShell

RxDOS_init_62:
        call RxDOSIni_TypeMessage

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Wait for CTRL+ALT+DEL
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

RxDOS_init_68:
        xor ax, ax
        int 16h                                         ; this allows CTRL+ALT+DEL
        jmp RxDOS_init_68                               ; return not expected

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ;  Type Message                                                 ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ;  ds:si    points to message                                   ;
        ;...............................................................;

RxDOSIni_TypeMessage:

        lodsb
        or al, al
        jnz RxDOSIni_TypeMessage_08
        ret

RxDOSIni_TypeMessage_08:
        int 29h                                         ; display message
        jmp RxDOSIni_TypeMessage

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Error Message
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

RxDOSmsg_CouldNotFindShell:
                        db 0Dh, 0Ah, 'Could not find command shell', 0

RxDOSmsg_InvalidPathShell:
                        db 0Dh, 0Ah, 'Invalid Path: Shell command line probably contains wrong path', 0

RxDOSmsg_ArenaTrashedShell:
                        db 0Dh, 0Ah, 'Arena trashed detected while loading command shell', 0

RxDOSmsg_NotEnoughMemoryShell:
                        db 0Dh, 0Ah, 'Not enough memory to load command shell', 0

RxDOSmsg_CouldNotLoadDriver:
                        db 0Dh, 0Ah, 'Could not load: ', 0

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Shell Name
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

                       even

_RxDOSini_CommandShell: db 128 dup(0)                   ; command shell
_RxDOSini_CommandTail:  db 128 dup(0)                   ; command tail 

 IFNDEF RxDOS_DEBUG
_RxDOSini_DefaultShell: db 'rxdoscmd.exe', 0
                        db (128 - ($-_RxDOSini_DefaultShell)) dup (?)

 ELSE
_RxDOSini_DefaultShell: db 'c:/rxdos/rxdoscmd.exe', 0
                        db (128 - ($-_RxDOSini_DefaultShell)) dup (?)

 ENDIF

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; Trace                                                         ;
        ;...............................................................;

 IFDEF RxDOS_TRACEBUILD

_InsideLoggingCall:     dw 0
OriginalInt29:          dd 0

TraceFile_Handle:       dw 0
TraceFile:              db 'TRACE.FIL', 0

_LoggingDriverCalls:    db 0Dh, 0Ah, 'Driver Call - ', 0
_LoggingDriverReturns:  db 0Dh, 0Ah, 'Driver Returns - ', 0
_LoggingInt21Call:      db 0Dh, 0Ah, 'Int21 Call - ', 0

 ENDIF

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; Trace                                                         ;
        ;...............................................................;

 IFDEF RxDOS_TRACEBUILD

 _Trace_Interrupt_29:
        sti                                             ; restore interrupts
        saveAllRegisters









        pushf                                           ; call int 29
        call dword ptr cs:[ OriginalInt29 ]

        restoreAllRegisters
        iret
 ENDIF

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; Log Trace Block Dev Request                                   ;
        ; Log Trace Char Dev Request                                    ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ; Input:                                                        ;
        ;  es:bx  pointer to buffer                                     ;
        ;  stack  interrupt address                                     ;
        ;...............................................................;

LogTraceBlockDevRequest:
LogTraceCharDevRequest:

 IFDEF RxDOS_TRACEBUILD
        Entry 2
        darg  _interrupt
        ddef  _packet, es, bx

        saveAllRegisters
        mov bx, offset _LoggingDriverCalls
        call LogDisplayMessage

        mov cl, ':'
        mov ax, word ptr [ _interrupt. _segment ][ bp ]
        call LogDisplayAddress

        mov cl, ' '
        mov ax, word ptr [ _interrupt. _pointer ][ bp ]
        call LogDisplayAddress

        mov al, '{'
        int 29h

        getdarg es, bx, _packet
        mov cl, byte ptr es:[ bx ]                      ; get length
        call LogTraceDisplayBytes                       ; byte dump

        mov al, '}'
        int 29h

        restoreAllRegisters
        Return
 ENDIF

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; LogTraceBlockDevRequest                                       ;
        ; LogTraceCharDevRequest                                        ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ; Input:                                                        ;
        ;  es:bx  pointer to display message                            ;
        ;...............................................................;

LogTraceBlockDevReturn:
LogTraceCharDevReturn:

 IFDEF RxDOS_TRACEBUILD
        Entry
        ddef  _packet, es, bx

        saveAllRegisters
        mov bx, offset _LoggingDriverReturns
        call LogDisplayMessage

        mov al, '{'
        call logCharacter

        getdarg es, bx, _packet
        mov cl, byte ptr es:[ bx ]                      ; get length
        call LogTraceDisplayBytes                       ; byte dump

        mov al, '}'
        call logCharacter

        restoreAllRegisters
        Return
 ENDIF

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; Log Trace Int21 Calls                                         ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ; Input:                                                        ;
        ;  registers                                                    ;
        ;...............................................................;

LogTraceInt21Calls:

 IFDEF RxDOS_TRACEBUILD

        cmp word ptr cs:[ _InsideLoggingCall ], 0
        jnz LogTraceInt21Calls_20
        inc word ptr [ _InsideLoggingCall ]             ; disable tracing

        saveAllRegisters
        mov bx, offset _LoggingInt21Call
        call LogDisplayMessage

        RetCallersStackFrame es, bx
        mov cl, ' '
        mov ax, word ptr es:[ _AX ][ bx ]
        call LogDisplayAddress

        mov cl, ' '
        mov ax, word ptr es:[ _BX ][ bx ]
        call LogDisplayAddress

        mov cl, ' '
        mov ax, word ptr es:[ _CX ][ bx ]
        call LogDisplayAddress

        mov cl, ' '
        mov ax, word ptr es:[ _DX ][ bx ]
        call LogDisplayAddress

        mov cl, ' '
        mov ax, word ptr es:[ _SI ][ bx ]
        call LogDisplayAddress

        mov cl, ' '
        mov ax, word ptr es:[ _DI ][ bx ]
        call LogDisplayAddress

        mov cl, ' '
        mov ax, word ptr es:[ _DataSegment  ][ bx ]
        call LogDisplayAddress

        mov cl, ' '
        mov ax, word ptr es:[ _ExtraSegment ][ bx ]
        call LogDisplayAddress
        dec word ptr cs:[ _InsideLoggingCall ]   

LogTraceInt21Calls_20:
        restoreAllRegisters
        ret
 ENDIF
        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; Log Display Message                                           ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ; Input:                                                        ;
        ;  cs:bx  pointer to null terminated message                    ;
        ;...............................................................;

LogDisplayMessage:

 IFDEF RxDOS_TRACEBUILD
        
        mov al, byte ptr cs:[ bx ]
        or al, al
        jz logDisplayMessage_08

        inc bx
        call logCharacter
        jmp logDisplayMessage

logDisplayMessage_08:
        ret

 ENDIF

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; Log Display Address                                           ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ; Input:                                                        ;
        ;  ax     address to display                                    ;
        ;  cl     character to display at end                           ;
        ;...............................................................;

LogDisplayAddress:

 IFDEF RxDOS_TRACEBUILD

        push ax
        mov al, ah
        call logDisplayByte                             ; display top byte

        pop ax
        call logDisplayByte                             ; display lower byte

        mov al, cl
        call logCharacter
        ret
 ENDIF

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; Log Display Byte Stream                                       ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ; Input:                                                        ;
        ;  es:bx  address of byte stream                                ;
        ;  cx     byte count                                            ;
        ;...............................................................;

LogTraceDisplayBytes:

 IFDEF RxDOS_TRACEBUILD

        mov ch, 0
        mov al, byte ptr es:[ bx ]
        call logDisplayByte                             ; display byte

        mov al, ' ' 
        call logCharacter                               ; space 

        inc bx
        loop logTraceDisplayBytes

        ret
 ENDIF
        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; Log Display Byte                                              ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ; Input:                                                        ;
        ;  al     byte to display                                       ;
        ;...............................................................;

logDisplayByte:

 IFDEF RxDOS_TRACEBUILD

        push ax
        shr al, 1
        shr al, 1
        shr al, 1
        shr al, 1
        call logDisplayByte_20

        pop ax

logDisplayByte_20:
        and al, 15
        or al, '0'
        cmp al, '9' + 1
        jc logDisplayByte_22
        add al, 'A' - '9' - 1

logDisplayByte_22:
        call logCharacter
        ret
 ENDIF

        ;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
        ; Log Display Byte                                              ;
        ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
        ;                                                               ;
        ; Input:                                                        ;
        ;  al     character to display                                  ;
        ;...............................................................;

logCharacter:

 IFDEF RxDOS_TRACEBUILD

        int 29h
        ret
 ENDIF

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  United States
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

_RxDOSini_COUNTRY_Info:
_RxDOSini_COUNTRY_UNITEDSTATES:

        dw sizeCOUNTRYINFO                              ; size of record
        dw COUNTRY_UNITEDSTATES                         ; country code
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_MMDDYY                                  ; date format
        db '$', 0, 0, 0, 0                              ; currency format
        dw ','                                          ; thousands separator
        dw '.'                                          ; decimal separator
        dw '-'                                          ; date separator
        dw ':'                                          ; time separator
        db CURRENCY_BEFORE                              ; currency bit field
        db 2                                            ; currency places
        db TIME_12HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction                                
        dw ','                                          ; data separator
        db 10 dup(0)                                    ; reserved
                                               
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Canadian-French
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; size of record
        dw COUNTRY_CANADIANFRENCH                       ; country code
        dw CODEPAGE_CANADIANFRENCH                      ; code page
        dw DATE_DDMMYY                                  ; date format
        db '$', 0, 0, 0, 0                              ; currency format
        dw ' '                                          ; thousands separator
        dw ','                                          ; decimal separator
        dw '-'                                          ; date separator
        dw ':'                                          ; time separator
        db CURRENCY_BEFORE                              ; currency bit field
        db 2                                            ; currency places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction                                
        dw ';'                                          ; data separator
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Latin America
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; size of record
        dw COUNTRY_LATINAMERICA                         ; country code
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db '$', 0, 0, 0, 0                              ; currency format
        dw ','                                          ; thousands separator
        dw '.'                                          ; decimal separator
        dw '/'                                          ; date separator
        dw ':'                                          ; time separator
        db CURRENCY_BEFORE                              ; currency bit field
        db 2                                            ; currency places
        db TIME_12HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction                                
        dw ','                                          ; data separator
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Russia                                              country code:   7
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_RUSSIA                               ; country
        dw CODEPAGE_CYRILLIC                            ; code page
        dw DATE_DDMMYY                                  ; date format
        db 20h, 0E0h, 0E3h, 0A1h, 2Eh                   ; 
        dw ' '                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Russia                                              country code:   7
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_RUSSIA                               ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'r','u', 'b', '.', 0                         ; rub.
        dw ' '                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Russia                                              country code:   7
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_RUSSIA                               ; country
        dw CODEPAGE_MULTILINGUAL                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'r','u', 'b', '.', 0                         ; rub.
        dw ' '                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Russia                                              country code:   7
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_RUSSIA                               ; country
        dw CODEPAGE_SLAVIC_II                           ; code page
        dw DATE_DDMMYY                                  ; date format
        db 20h, 0E1h, 0E7h, 0A2h, 2Eh                   ; 
        dw ' '                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Russia                                              country code:   7
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_RUSSIA                               ; country
        dw CODEPAGE_SLAVIC                              ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'r','u', 'b', '.', 0                         ; rub.
        dw ' '                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Netherlands                                         country code:  31
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_NETHERLANDS                          ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 9Fh, 0, 0, 0, 0                              ; 
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '-'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Belgium                                             country code:  32
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_BELGIUM                              ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'B', 'F', 0, 0, 0                            ; BF
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  France                                              country code:  33
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; size of record
        dw COUNTRY_FRANCE                               ; country code
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'F', 0, 0, 0, 0                              ; currency
        dw ' '                                          ; thousands separator
        dw ','                                          ; decimal separator
        dw '.'                                          ; date separator
        dw ':'                                          ; time separator
        db CURRENCY_AFTER + CURRENCY_SPACEBETWEEN       ; currency bit field
        db 2                                            ; currency places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction                                
        dw ';'                                          ; data separator
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Spain                                               country code:  34
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_SPAIN                                ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 9Eh, 0, 0, 0, 0                              ; 
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 0                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Spain                                               country code:  34
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_SPAIN                                ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'P', 't', 's', 0, 0                          ; Pts..
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 0                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Hungary                                             country code:  36
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_HUNGARY                              ; country
        dw CODEPAGE_SLAVIC                              ; code page
        dw DATE_YYMMDD                                  ; date format
        db 'F', 't', 0, 0, 0                            ; Ft
        dw ' '                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '-'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_BEFORE                              ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Serbia/ Yugoslavia                                  country code:  38
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_SERBIA_YUGOSLAVIA                    ; country
        dw CODEPAGE_SLAVIC                              ; code page
        dw DATE_YYMMDD                                  ; date format
        db 'D', 'i', 'n', 0, 0                          ; currency: Din
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '-'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Italy                                               country code:  39
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_ITALY                                ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'L', '.', 0, 0, 0                            ; 'L.'
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '/'                                          ; date sep
        dw '.'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 0                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Switzerland                                         country code:  41
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_SWITZERLAND                          ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'F', 'r', '.', 0, 0                          ; Fr.
        dw "'"                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '.'                                          ; date sep
        dw ','                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  The Czech Republic                                  country code:  42
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_CZECHREPUBLIC                        ; country
        dw CODEPAGE_SLAVIC                              ; code page
        dw DATE_YYMMDD                                  ; date format
        db 4Bh, 9Fh, 73h, 0, 0                          ; K.s
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '-'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  United Kingdom (Great Britain)                      country code:  44
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; size of record
        dw COUNTRY_UNITEDKINGDOM                        ; country code
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 9Ch, 0, 0, 0, 0                              ; currency
        dw ','                                          ; thousands separator
        dw '.'                                          ; decimal separator
        dw '/'                                          ; date separator
        dw ':'                                          ; time separator
        db CURRENCY_BEFORE                              ; currency bit field
        db 2                                            ; currency places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction                                
        dw ','                                          ; data separator
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Denmark                                             country code:  45
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_DENMARK                              ; country
        dw CODEPAGE_NORDIC                              ; code page
        dw DATE_DDMMYY                                  ; date format
        db 6Bh, 72h, 0h, 0h, 0                          ; kr...
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '-'                                          ; date sep
        dw '.'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Sweden                                              country code:  46
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_SWEDEN                               ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'K', 'r', 0, 0, 0                            ; Kr
        dw ' '                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '-'                                          ; date sep
        dw '.'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Norway                                              country code:  47
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_NORWAY                               ; country
        dw CODEPAGE_NORDIC                              ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'K', 'r', 0, 0, 0                            ; Kr
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '.'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Poland                                              country code:  48
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_POLAND                               ; country
        dw CODEPAGE_SLAVIC                              ; code page
        dw DATE_YYMMDD                                  ; date format
        db 5Ah, 88h, 0, 0, 0                            ; Z.
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '-'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_BEFORE                              ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Germany                                             country code:  49
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_GERMANY                              ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'D', 'M', 0, 0, 0                            ; DM   
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '.'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_BEFORE                              ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Brazil                                              country code:  55
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_BRAZIL                               ; country
        dw CODEPAGE_MULTILINGUAL                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'C', 'r', '$', 0, 0                          ; Cr$
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_BEFORE                              ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  International English                               country code:  61
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_INTERNATIONAL_ENGLISH                ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db '$', 0, 0, 0, 0                              ; $
        dw ','                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '-'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_BEFORE                              ; currency format
        db 2                                            ; decimal places
        db TIME_12HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Japan                                               country code:  81
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_JAPAN                                ; country
        dw CODEPAGE_JAPAN                               ; code page
        dw DATE_YYMMDD                                  ; date format
        db 5Ch, 0, 0, 0, 0                              ; Y
        dw ','                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '-'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_BEFORE                              ; currency format
        db 0                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Korea                                               country code:  82
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_KOREA                                ; country
        dw CODEPAGE_KOREA                               ; code page
        dw DATE_YYMMDD                                  ; date format
        db 5Ch, 0, 0, 0, 0                              ; Y
        dw ','                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '.'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_BEFORE                              ; currency format
        db 0                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  China                                               country code:  86
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_CHINA                                ; country
        dw CODEPAGE_CHINA                               ; code page
        dw DATE_YYMMDD                                  ; date format
        db 5Ch, 0, 0, 0, 0                              ; Y
        dw ','                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '-'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_BEFORE                              ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Taiwan                                              country code:  88
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_TAIWAN                               ; country
        dw CODEPAGE_TAIWAN                              ; code page
        dw DATE_YYMMDD                                  ; date format
        db 'N', 'T', '$', 0, 0                          ; NT$
        dw ','                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_BEFORE                              ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Turkey                                              country code:  90
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_TURKEY                               ; country
        dw CODEPAGE_MULTILINGUAL                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'T', 'L', 0, 0, 0                            ; TL
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db 04                                           ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Turkey                                              country code:  90
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_TURKEY                               ; country
        dw CODEPAGE_TURKEY                              ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'T', 'L', 0, 0, 0                            ; TL
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db 04                                           ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Portugal                                            country code: 351
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_PORTUGAL                             ; country
        dw CODEPAGE_PORTUGAL                            ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'E', 's', 'c', '.', 0                        ; Esc.
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '-'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Iceland                                             country code: 354
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_ICELAND                              ; country
        dw CODEPAGE_ICELAND                             ; code page
        dw DATE_DDMMYY                                  ; date format
        db 0A5h, 4Bh, 72h, 0, 0                         ; %Kr..
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '.'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Iceland                                             country code: 354
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_ICELAND                              ; country
        dw CODEPAGE_ICELAND                             ; code page
        dw DATE_DDMMYY                                  ; date format
        db 0A5h, 4Bh, 72h, 0, 0                         ; %Kr..
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '.'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Finland                                             country code: 358
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_FINLAND                              ; country
        dw CODEPAGE_UNITEDSTATES                        ; code page
        dw DATE_DDMMYY                                  ; date format
        db 'm', 'k', 0, 0, 0                            ; mk
        dw ' '                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '.'                                          ; date sep
        dw '.'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Middle East/Saudi Arabia                            country code: 785
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_MIDDLEEAST                           ; country
        dw CODEPAGE_MIDDLEEAST                          ; code page
        dw DATE_DDMMYY                                  ; date format
        db 0A4h, 0, 0, 0, 0                             ; 
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 3                                            ; decimal places
        db TIME_12HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Middle East/Saudi Arabia                            country code: 785
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_MIDDLEEAST                           ; country
        dw CODEPAGE_MIDDLEEAST                          ; code page
        dw DATE_DDMMYY                                  ; date format
        db 0CFh, 0, 0, 0, 0                             ; 
        dw '.'                                          ; thousands sep
        dw ','                                          ; decimal sep
        dw '/'                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN + CURRENCY_AFTER       ; currency format
        db 3                                            ; decimal places
        db TIME_12HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ';'                                          ; data sep
        db 10 dup(0)                                    ; reserved

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  Israel                                              country code: 972
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        dw sizeCOUNTRYINFO                              ; length
        dw COUNTRY_ISRAEL                               ; country
        dw CODEPAGE_MIDDLEEAST                          ; code page
        dw DATE_DDMMYY                                  ; date format
        db 99h, 0, 0, 0, 0                              ; 
        dw ','                                          ; thousands sep
        dw '.'                                          ; decimal sep
        dw ' '                                          ; date sep
        dw ':'                                          ; time sep
        db CURRENCY_SPACEBETWEEN                        ; currency format
        db 2                                            ; decimal places
        db TIME_24HOUR                                  ; time format
        dd RxDOS_USA_DefaultUpperCaseFunction
        dw ','                                          ; data sep
        db 10 dup(0)                                    ; reserved

_RxDOSini_ENDCOUNTRY_Info:
        dw -1                                           ; end of country info

RxDOS_EndOfInitCode     equ $
RxDOS_EndOfInitCodePara equ ($+sizePARAGRAPH-1)/sizePARAGRAPH

RxDOS   ENDS
        END
