; JRCONFIG.SYS v2.14 ; Set to 1 for bit-perfect assembly of .DSK version ; Set to 0 for bit-perfect assembly of .NRD version (offsets shown) SUPPORT_RAMDISK EQU 0 ; String macros BEL EQU 7 TAB EQU 9 LF EQU 10 CR EQU 13 ESC EQU 27 ; BIOS Data Area (BDA) offsets BDA_COM2_PORT EQU 02h BDA_BIOS_DATA_SEG EQU 0eh BDA_EQUIP_BITS EQU 10h BDA_MEM_SIZE_KB EQU 13h BDA_ADAP_MEM_SIZE EQU 15h BDA_KBD_SHIFT_FLAG EQU 17h BDA_ACTIVE_MODE EQU 49h BDA_VIDEO_FLAGS EQU 89h BDA_VIDEO_FLAGS2 EQU 8ah ; I/O Ports PORT_KEYBOARD_STORAGE EQU 0060h ; 8255 Port A PORT_NMI_MASK EQU 00a0h ; Bit 7 PORT_CRT_ADDRESS EQU 03d4h ; 6845 CRT controller PORT_CRT_DATA EQU 03d5h ; 6845 CRT controller PORT_VIDEO_PAGE EQU 03dfh ; b0-2: CRT, b3-5 CPU, b6-7 address mode _TEXT segment word public use16 'CODE' public _entry assume cs:_TEXT, ds:_TEXT, es:nothing org 0 public _sys_header _sys_header: dd -1 ; Link to next driver in chain (filled in by DOS) if SUPPORT_RAMDISK dw 6000h ; Block dev, IOCTL supported. else dw 8000h ; Char dev, no-output-until-busy support endif dw _strategy_entry dw _commands_entry if SUPPORT_RAMDISK db 1 ; Block dev: Number of logical drives else db 'JRCONF%%' ; Char dev: Device name endif _sys_table: dw _cmd0_driver_init ; [CB] Initialization dw _cmd1_media_check ; [ B] Media Check dw _cmd2_build_bios_param_block ; [ B] Build BPB dw _cmd3_ioctl_read ; [CB] IOCTL Read dw _cmd4_read ; [CB] Read dw _cmdn_completed ; [C ] Non-Destructive Read dw _cmdn_completed ; [C ] Input Status dw _cmdn_completed ; [C ] Flush Input Buffers dw _cmd5_write ; [CB] Write dw _cmd5_write ; [ B] Write w/ Verify dw _cmdn_completed ; [C ] Output Status dw _cmdn_completed ; [C ] Flush Output Buffers dw _cmdn_completed ; [CB] IOCTL Write _bios_param_block: _bpb_bytes_per_sector dw 128 _bpb_sec_per_unit db 1 _bpb_reserved_sectors dw 0 _bpb_fat_tables db 1 _bpb_rootdisk_entries dw 00010h _bpb_total_sectors dw 0 _bpb_media_desc_byte db 0f8h _bpb_secs_per_fat dw 0 _bpb_pointer dw offset _bios_param_block _prev_int09h dd 0 _prev_int10h_a dd 0 _prev_int10h_b dd 0 _prev_int10h_c dd 0 _prev_int20h dd 0 _prev_int21h dd 0 _prev_int27h dd 0 _sys_request dw 0 ; Saved DOS transaction pointer _sys_request_seg dw 0 _break_min dw 0 ; Top of resident program (segment) _video_start dw 0 ; Start of frame (segment) _video_end dw 0 ; End of frame (segment) _break_end dw 0 ; End of allocation (segment) _video_size dw 0400h ; In paragraphs (segment offset) _video_page db 7 ; A17-14 page translation _video_kb db 010h ; Video frame size in KB ; ---------------------------------------------------------- ; FUNC: _strategy_entry ; ; DESC: Entry point from DOS used to store the request block ; for all command requests to the device driver processed ; during _command_entry below. ; ; INPUTS: es:bx - Pointer to driver specific command block ; ; OUTPUTS: none ; ; CLOBBERS: none _strategy_entry proc far public mov cs:_sys_request_seg, es mov cs:_sys_request, bx retf _strategy_entry endp ; ---------------------------------------------------------- ; FUNC: _commands_entry ; ; DESC: Entry point from DOS used to process specific driver ; requests. This is done through a dispatch table ; above. Supporting dispatch functions are setup with ; the following entry registers: ; ; dx:cx - Far pointer to driver command line ; ds:bx - Command request block ; es:di - Break address of driver memory ; ; Dispatch functions are expected to re-enter this ; code via a short jump to _cmdn_completed. ; ; INPUTS: none - All information is command specific and ; passed via the _sys_request block ; ; OUTPUTS: none - All information is command specific and ; passed via the _sys_request block ; ; CLOBBERS: none _commands_entry proc far public push si push ax push cx push dx push di push bp push ds push es push bx lds bx, cs:_sys_request mov cx, word ptr ds:[bx + 012h] ; Command line offset mov dx, word ptr ds:[bx + 014h] ; Command line segment mov al, byte ptr ds:[bx + 2] ; Command code cbw mov si, _sys_table add si, ax add si, ax cmp al, 11 ja _command_unknown les di, ds:[bx + 00eh] ; First free address above driver push cs pop ds cld jmp ds:[si] _command_unknown: mov ax, 08103h ; Unknown error status jmp _command_exit _cmdn_completed: mov ah, 1 ; Driver done - no error _command_exit: lds bx, cs:_sys_request call _spin_status pop bx pop es pop ds pop bp pop di pop dx pop cx pop ax pop si retf _commands_entry endp _cmd3_ioctl_read: mov al, 080h mov ah, ds:_video_page stosw mov al, ds:_video_kb stosb _cmdn_io_completed: clc jmp _cmdn_completed _cmd1_media_check: lds bx, ds:_sys_request mov byte ptr ds:[bx + 00eh], 1 ; Block device not changed jmp _cmdn_completed _cmd2_build_bios_param_block: lds bx, ds:_sys_request mov word ptr ds:[bx + 012h], _bios_param_block mov word ptr ds:[bx + 014h], cs jmp _cmdn_completed ; On I/O entry: ; cx = bytes/sector count ; dx = starting sector number ; Memory map looks like this: ; [resident ][ region 1 ][ video frame ][ region 2 ] _cmd4_read: xor ax, ax ; copy direction: 0 = read jmp _cmd_io_setup _cmd5_write: mov al, 1 ; copy direction: 1 = write _cmd_io_setup: shl dx, 1 ; start sector * 128 (7 left shift minus shl dx, 1 ; 4 right shift for paragraph adjust shl dx, 1 add dx, ds:_break_min mov bx, dx ; bx = dx = starting paragraph shl cx, 1 ; sector count * 128 (7 left shift minus shl cx, 1 ; 4 right shift for paragraph adjust shl cx, 1 add bx, cx ; bx = ending paragraph ; If we're above the start of video frame, add size to start loc cmp dx, ds:_video_start jae _adjust_copy_offset ; If we're in lower region and not spilling into video frame, go cmp bx, ds:_video_start jbe _cmd_io_go ; Overlapping video frame, break into two transfers doing lower first mov cx, ds:_video_start sub cx, dx call _copy_io_block push cs ; Block copy may trample ds pop ds mov cx, bx sub cx, ds:_video_start xor dx, dx jmp _adjust_for_region_two _adjust_copy_offset: sub dx, ds:_video_start _adjust_for_region_two: add dx, ds:_video_end _cmd_io_go: call _copy_io_block jmp _cmdn_io_completed ; ---------------------------------------------------------- ; FUNC: _copy_io_block ; ; DESC: Copy a ram region specified in paragraphs/segment offsets ; with optional reversal of src/dst ; ; INPUTS: dx - starting source segment/paragraph ; es:di - Target byte pointer for copy ; cx - Number of paragraphs to copy ; ax - 1 reverse direction, 0 no reversal ; ; OUTPUTS: es:di - Advanced past copy length ; ; CLOBBERS: cx, dx, ds, si _copy_io_block proc near public shl cx, 1 ; cx = paragraphs w/ word movement = * 8 shl cx, 1 shl cx, 1 xor si, si mov ds, dx or ax, ax jz _copy_io_block_go _copy_io_block_swap_ptrs: push es pop ds mov es, dx xchg di, si _copy_io_block_go: rep movsw or ax, ax jz _copy_io_block_done _copy_io_block_swap_ptrs_back: push ds pop es mov di, si _copy_io_block_done: ret _copy_io_block endp ; ---------------------------------------------------------- ; FUNC: _int09h_handler ; ; DESC: Traps keyboard IRQ handler _int09h_handler proc far public in al, PORT_KEYBOARD_STORAGE jmp dword ptr cs:_prev_int09h _int09h_handler endp _int10h_handler_a proc far public push bp pushf call dword ptr cs:_prev_int10h_a pop bp iret _int10h_handler_a endp ; ---------------------------------------------------------- ; FUNC: _int10h_handler_b ; ; DESC: Traps for set video mode (ah=0) and chains the previous ; handler with bit 7 of the mode set to one. After, it ; clears the active video page ; ; A video frame size validity check is also performed _int10h_handler_b proc far public or ah, ah jz _int10h_b_set_mode jmp dword ptr cs:_prev_int10h_b _int10h_b_set_mode: push ax or al, 080h pushf call dword ptr cs:_prev_int10h_b call _reset_video_page pop ax test al, 080h jnz _int10h_b_done push ax push cx push di push es mov ch, cs:_screen_color mov cl, ' ' cmp al, 7 jz _int10h_b_cleanup cmp al, 4 jb _int10h_b_cleanup xor cx, cx _int10h_b_cleanup: call _memset_vpage pop es pop di pop cx pop ax _int10h_b_done: iret _int10h_handler_b endp _screen_color db 7 ; ---------------------------------------------------------- ; FUNC: _int10h_handler_c ; ; DESC: Installed by the '-n' option, this handler traps for ; set video mode (ah=0) and translates color modes (1 & 3) ; to black and white modes (0 & 2) respectively _int10h_handler_c proc far public or ah, ah jnz _int10h_c_done cmp al, 1 jne _int10h_c_check_three ; Mode 1 (40x25 Color) -> Mode 0 (40x25 BW) mov al, 0 jmp _int10h_c_done _int10h_c_check_three: cmp al, 3 jne _int10h_c_done ; Mode 3 (80x25 Color) -> Mode 1 (80x25 BW) mov al, 2 _int10h_c_done: jmp dword ptr cs:_prev_int10h_c _int10h_handler_c endp ; ---------------------------------------------------------- ; FUNC: _int12h_handler ; ; DESC: Traps BIOS get memory size call being made ; cartridge BASIC and limits the reported RAM ; size to 240KB. _int12h_handler proc far public sti push bp mov bp, sp mov bp, [bp + 4] mov ax, 00f0h cmp bp, 0e800h je _int12h_done push ds mov ax, 0040h mov ds, ax mov ax, ds:BDA_MEM_SIZE_KB pop ds _int12h_done: pop bp iret _int12h_handler endp ; ---------------------------------------------------------- ; FUNC: _int27h_handler ; ; DESC: Traps DOS calls to int 27 - DOS 1 terminate ; and stay resident ; ; The active video page is reset before the DOS ; program terminates. ; ; This handler is only installed when the video ; frame is not located at the top of 128KB (!=7) _int27h_handler proc far public call _reset_video_page jmp dword ptr cs:_prev_int27h _int27h_handler endp ; ---------------------------------------------------------- ; FUNC: _int20h_handler ; ; DESC: Traps DOS calls to int 20 - DOS 1 terminate program ; ; The active video page is reset before the DOS ; program terminates. ; ; This handler is only installed when the video ; frame is not located at the top of 128KB (!=7) _int20h_handler proc far public call _reset_video_page jmp dword ptr cs:_prev_int20h _int20h_handler endp ; ---------------------------------------------------------- ; FUNC: _int21h_handler ; ; DESC: Traps DOS calls to: ; ; Func 00h -> Terminate program ; Func 31h -> Terminate and Stay Resident ; Func 4ch -> Terminate with Return code ; ; The active video page is reset before the DOS ; program terminates. ; ; This handler is only installed when the video ; frame is not located at the top of 128KB (!=7) _int21h_handler proc far public cmp ah, 0 je _int21h_clear cmp ah, 31h je _int21h_clear cmp ah, 4ch jne _int21h_chain _int21h_clear: call _reset_video_page _int21h_chain: jmp dword ptr cs:_prev_int21h _int21h_handler endp ; ---------------------------------------------------------- ; FUNC: _int60h_handler ; ; DESC: Traps DOS multiplex interrupt to provide info ; to support utilities. _int60h_handler proc far public cmp ah, 0 jne _int60h_func1 _int60h_func0: mov cs:_sys_request, bx mov cs:_sys_request_seg, cx mov ax, _strategy_entry mov bx, _commands_entry mov cx, cs mov dx, offset _bpb_pointer jmp _int60h_done _int60h_func1: cmp ah, 1 jne _int60h_done cmp word ptr cs:_spinchar_offset, -1 jz _int60h_done mov cs:_spinchar_offset, bx _int60h_done: iret _int60h_handler endp ; ---------------------------------------------------------- ; FUNC: _reset_video_page ; ; DESC: This ensures the desired video page is set in ; both the CRT and CPU page registers by calling ; the original Jr BIOS. ; ; INPUTS: none ; ; OUTPUTS: none ; ; CLOBBERS: none _reset_video_page proc near public push ax push bx mov bl, cs:_video_page mov bh, bl ; bh=CRT page reg, bl=CPU page reg _reset_video_page_go: mov ax, 0583h ; Set CRT/CPU page reg int 10h pop bx pop ax ret _reset_video_page endp ; ---------------------------------------------------------- ; FUNC: _memset_vpage ; ; DESC: This clears the active video frame with a specified ; character ; ; INPUTS: cx - Character/attribute to set in page ; ; OUTPUTS: none ; ; CLOBBERS: ax, es, di _memset_vpage proc near public mov ax, cx mov cx, cs:_video_size cmp cx, 0800h jb _memset_vpage_go mov cx, 0800h _memset_vpage_go: shl cx, 1 ; cx = paragraphs w/ word movement = * 8 shl cx, 1 shl cx, 1 mov es, cs:_video_start xor di, di rep stosw ret _memset_vpage endp _cmd0_finalize: rep stosw pop di pop si pop cx rep movsw _loc_80: mov ch, cs:_screen_color mov cl, ' ' call _memset_vpage call _reset_video_page _loc_79: mov dx, _str_version mov ah, 9 int 21h cmp byte ptr cs:_cmdline_error, 0 je _cmd0_normal_exit mov dx, _str_error mov ah, 9 int 21h _cmd0_normal_exit: mov cx, ds:_break_end lds bx, ds:_sys_request mov byte ptr ds:[bx + 00dh], 1 ; Units installed mov word ptr ds:[bx + 00eh], 0 ; Top of memory offset mov word ptr ds:[bx + 010h], cx ; Top of memory segment mov word ptr ds:[bx + 012h], offset _bpb_pointer mov word ptr ds:[bx + 014h], cs jmp _cmdn_completed _spinchar_index dw 0 _spinchar_table: db '|' db '/' db '-' db '\' _spinchar_offset dw -1 ; ---------------------------------------------------------- ; FUNC: _spin_status ; ; DESC: If enabled, update a spinning character at a ; configurable location on the top row of the ; screen. The character updates/spins on each ; call to the driver which is usually disk access. ; ; INPUTS: ds:bx - Driver request block ; ; OUTPUTS: none ; ; CLOBBERS: ax, bx, ds _spin_status proc near public test word ptr cs:_spinchar_offset, 08000h jnz _spin_done mov ds:[bx + 3], ax ; Copy out status mov ax, 0b800h mov ds, ax mov ax, cs:_spinchar_index inc ax ; cmp ax, 4 ; fixup - open watcom encodes this more efficiently (w/ 1 byte arg) db 3dh, 04h, 00h jb _spin_draw mov ax, 0 _spin_draw: mov cs:_spinchar_index, ax mov bx, _spinchar_table add bx, ax mov al, cs:[bx] mov bx, cs:_spinchar_offset mov ds:[bx], al _spin_done: ret _spin_status endp _ramdisk_root: _root_filename db 'Low Ramd' _root_extension db 'isk' _root_attributes db 08h _root_reserved db 10 dup(0) _root_time dw 0c000h _root_date dw 00d81h _root_start_cluster dw 0 _root_size dd 0 _str_version: db 'JRCONFIG Version 2.14', CR, LF _str_copyright: db '(C) Copyright Larry Newcomb 1986', CR, LF _str_floppy_count: ; 0321 db 'Floppy Disks = 1', CR, LF STR_FLOPPY_COUNT EQU (_str_floppy_count + 15) _str_ramsize: ; 0333 db 'Top of DOS Ram = 128K ', CR, LF STR_RAM_SIZE EQU (_str_ramsize + 17) _data_47: db '$' _str_misc: db 'RSYNC', CR, LF, '$' _cmdline_error db 000h ; 0355 _str_error: ; 0356 db BEL, 'There was an error in the options list in CONFIG.SYS', BEL, CR, LF, '$' ; ********************************************************** ; ********************************************************** ; Marker for minimum part of device driver to remain in memory ; after driver exit. Also serves as starting location for any ; potential RAM disk. _end_resident_portion: ; ********************************************************** ; ********************************************************** _cmd0_driver_init proc near public mov ax, 0040h mov es, ax mov ax, es:BDA_ADAP_MEM_SIZE cmp ax, 0100h jb _cmd0_error_lowmem mov ax, es:BDA_MEM_SIZE_KB cmp ax, 0ffh ; >128K ja _jrconfig_init ; Progression for initial boot pass only call _proc_command_line ; Fixup ram size for next load mov ax, es:BDA_ADAP_MEM_SIZE mov es:BDA_MEM_SIZE_KB, ax ; Mask all interrupts but IRQ0 (timer clock) mov al, 0feh out 21h, al ; Get current video mode: al=mode, bh=active page mov ah, 0fh int 10h ; Clear video by scrolling entire screen up xor cx, cx mov dh, 24 dec ah mov dl, ah xor al, al mov bh, 7 mov ah, 6 int 10h ; Set cursor posiiton to 0, 0 xor bx, bx mov dx, bx mov ah, 2 int 10h ; Stuff floppy count into upper 2 bits of BDA equip list mov ax, 0040h mov es, ax mov al, cs:_floppy_count mov cl, 6 shl al, cl mov bx, BDA_EQUIP_BITS and byte ptr es:[bx], 3fh or byte ptr es:[bx], al ; System Bootstrap Loader (soft re-OS load & execute) int 19h ; does not return _cmd0_error_lowmem: mov dx, _str_error_mem jmp _cmd0_error_exit _jrconfig_init: mov al, 1 mov cs:_expanded_mem, al mov ax, 3509h ; IRQ1 Keyboard int 21h mov word ptr ds:_prev_int09h, bx mov word ptr ds:_prev_int09h + 2, es mov ax, 3510h ; BIOS Video Services int 21h mov word ptr ds:_prev_int10h_a, bx mov word ptr ds:_prev_int10h_a + 2, es mov ax, 3520h ; DOS Terminate Prog int 21h mov word ptr ds:_prev_int20h, bx mov word ptr ds:_prev_int20h + 2, es mov ax, 3521h ; DOS Service int 21h mov word ptr ds:_prev_int21h, bx mov word ptr ds:_prev_int21h + 2, es mov ax, 3527h ; DOS TSR Exit int 21h mov word ptr ds:_prev_int27h, bx mov word ptr ds:_prev_int27h + 2, es mov dx, _int10h_handler_a mov ax, 2510h int 21h _loc_31: call _proc_command_line _loc_48: mov al, ds:_video_kb cbw shl ax, cl mov ds:_video_size, ax mov ax, cs:_ramdisk_size mov bp, ax ; cmp ax, 0ffffh ; fixup - open watcom encodes this differently db 03dh, 0ffh, 0ffh jne _cartbasic_check ; If not specified (default 0ffffh), auto-compute max ; RAM disk size (in paragraphs) by subtracting from 128KB ; the video size and end of resident portion of the program ; (rounded up to nearest paragraph - _break_min) mov bp, 2000h mov ax, ds:_video_size add ax, 03ffh and ax, 0fc00h sub bp, ax sub bp, ds:_break_min _cartbasic_check: push ds mov ax, 0e800h mov ds, ax mov si, 6 lodsw cmp ax, 4205h ; 05h 'BASIC' jne _cartbasic_notfound lodsw cmp ax, 'SA' jne _cartbasic_notfound lodsw cmp ax, 'CI' _cartbasic_notfound: pop ds jne _size_ramdisk _cartbasic_found: mov si, 0052h mov dx, _int12h_handler mov ax, 2512h int 21h _size_ramdisk: ; bp = ram disk size in paragraphs mov dx, ds:_break_min mov es, dx add dx, bp add dx, 03ffh and dx, 0fc00h _loc_66: mov ds:_video_start, dx mov ax, dx ; Video page LSB is A14, paragraph is A4 mov cl, 10 ; Shift RD-end-paragraph down by 10 shr ax, cl mov ds:_video_page, al mov cl, 4 ; Get back to video page start KB shl al, cl ; Each page frame is 16KB, shift up by 2^4 add al, ds:_video_kb ; al = end video KB cmp al, 080h je _loc_67 jc _loc_68 jmp _error_allocation _loc_68: push es mov ax, 3510h int 21h mov word ptr cs:_prev_int10h_b, bx mov word ptr cs:_prev_int10h_b + 2, es mov dx, _int10h_handler_b mov ax, 2510h int 21h pop es mov dx, _int20h_handler mov ax, 2520h int 21h mov dx, _int27h_handler mov ax, 2527h int 21h mov dx, _int21h_handler mov ax, 2521h int 21h _loc_67: mov dx, _int09h_handler mov ax, 2509h int 21h mov dx, _int60h_handler mov ax, 2560h int 21h mov dx, ds:_video_start mov ax, ds:_video_size add ax, dx mov ds:_video_end, ax add ds:_break_end, ax mov bx, dx sub bx, ds:_break_min add bx, cs:_ramdisk_size_ext mov cl, 3 shr bx, cl mov ds:_bpb_total_sectors, bx inc bx and bl, 0feh mov si, bx shr bx, 1 add bx, si add bx, 7fh shl bx, 1 mov byte ptr ds:_bpb_secs_per_fat, bh xor bl, bl shr bx, 1 mov di, bx mov si, _ramdisk_root mov cx, 0010h push cx push si push di xor di, di mov ax, 0fff8h stosw xchg al, ah stosb xor ax, ax stosb mov cx, ds:_video_start sub cx, ds:_break_min shl cx, 1 shl cx, 1 shl cx, 1 sub cx, 2 cmp cx, 7ffdh jbe _loc_35 mov cx, 7ffdh _loc_35: jmp _cmd0_finalize _cmd0_driver_init endp _proc_command_line proc near public ; Compute minimum program break (minus ram disk) ; Round up to nearest page and adjust for program ; load point mov ax, _end_resident_portion _fixup_break: ; add ax, 0fh ; fixup - open watcom encodes this more efficiently (w/ 1 byte immediate) db 05h, 0fh, 00h mov cl, 4 shr ax, cl mov bx, cs add bx, ax mov ds:_break_min, bx push ds lds si, ds:_sys_request lds si, ds:[si + 012h] _proc_arg_next: ; On success, cl = arg letter (lower-case'd), bx = arg value call _get_next_arg mov al, cl or al, al jnz _proc_arg mov ax, 0040h mov ds, ax mov ax, ds:BDA_MEM_SIZE_KB call _update_ram_string call _update_floppycount_string pop ds _compute_ram_reservation: mov cl, 6 mov bx, cs:_ramdisk_size cmp bx, -1 je _proc_command_line_done shr bx, cl ; paragraphs(-4) -> KB(10) mov al, ds:_video_kb add al, 0fh and al, 0f0h ; round up to 16KB cbw sub dx, 50h sub dx, ax cmp bx, dx ja _loc_20 ; bx = ramdisk kb, ax = video kb add ax, bx sub ax, 080h shl ax, cl add ax, ds:_break_min jle _proc_command_line_done mov cs:_ramdisk_size_ext, ax mov ds:_break_end, ax sub cs:_ramdisk_size, ax _proc_command_line_done: ret _loc_20: jmp _cmd0_error_cleanup _proc_arg: ; ---------------------------------------------------------- ; -d will tell DOS how many floppy drives to control and to ; assign a drive letter for each one of them use /Dn ; option, where n is 1 to 4. _proc_arg_d: cmp al, 'd' jne _proc_arg_h mov al, bl dec al and al, 3 mov cs:_floppy_count, al jmp _proc_arg_next ; ---------------------------------------------------------- ; -h Is not designed for the average user. I use it for ; testing programs I want to put outside the DOS user ; area. /Hnnn will put nnn as the top of ram, regardless ; of how much ram you actually have; ie, /H512 will set ; the top of ram to 512KB. If you don't have that much ; ram, your system will probably crash. _proc_arg_h: cmp al, 'h' jne _proc_arg_l push es mov ax, 0040h mov es, ax mov word ptr es:BDA_MEM_SIZE_KB, bx mov word ptr es:BDA_ADAP_MEM_SIZE, bx pop es jmp _proc_arg_next ; ---------------------------------------------------------- ; -l Will check for additional RAM located above 640KB and ; allow DOS to use any memory it finds as conventional ; memory. It allows for a maximum of 736KB to be ; recognized (note: the PCjr "POST" or "colorbar" screen ; will always stop testing at 640KB even if the /L option ; is used). _proc_arg_l: cmp al, 'l' jne _proc_arg_s call _memory_check _proc_arg_l_done: jmp _proc_arg_next ; ---------------------------------------------------------- ; -s Sets the size of the ramdisk, use -sn where n is the number ; of K bytes you want the ramdisk to be. The ramdisk size may ; be a little larger than the value you put in, because of ; video page boundaries. The default size is 91K for DOS 2.1 ; and 79K for DOS 3.1. (10K is the smallest ramdisk you can ; have, because that is how much room is left on the video ; page where IBMDOS.COM is loaded with DOS 2.1, and this space ; can not be used for anything else anyway. With DOS 3.1 you ; get about 15K, because IBMDOS.COM is larger and video ram ; must be moved to a higher video page). There is no upper ; limit on the size of the ramdisk (other than the amount of ; RAM you have in your computer). _proc_arg_s: cmp byte ptr cs:_expanded_mem, 0 jz _skip_arg_s cmp al, 's' jne _proc_arg_f mov cl, 6 shl bx, cl mov cs:_ramdisk_size, bx _skip_arg_s: jmp _proc_arg_next ; ---------------------------------------------------------- ; -f Will set the screen color at boot time and when the mode is ; changed. Use -fnnn where nnn is from 0 to 255. _proc_arg_f: cmp al, 'f' jne _proc_arg_j mov cs:_screen_color, bl jmp _proc_arg_next ; ---------------------------------------------------------- ; -j Will put the address for the COM port on the motherboard ; into the BIOS data area for COM2. This will solve the ; problem that some communications programs have when using ; the COM port on the motherboard and an external modem. When ; you specify COM2, the program will now find it; and it will ; use the correct hardware interrupt. _proc_arg_j: cmp al, 'j' jne _proc_arg_m push ds mov ax, 0040h mov ds, ax mov word ptr ds:BDA_COM2_PORT, 02f8h pop ds jmp _proc_arg_next ; ---------------------------------------------------------- ; -m Will turn off the jr's internal speaker. If you run a ; program that turns the speaker back on, it will probably ; stay on. _proc_arg_m: cmp al, 'm' jne _proc_arg_n in al, 61h or al, 10h out 61h, al jmp _proc_arg_next ; ---------------------------------------------------------- ; -n Will prevent color modes for monochrome monitors. ; jrConfig will intercept a call to change to CO40 or ; CO80, and make a call for BW40 or BW80. It will have ; no effect on graphics modes. _proc_arg_n: cmp al, 'n' jne _proc_arg_g mov ax, 3510h int 21h mov word ptr cs:_prev_int10h_c, bx mov word ptr cs:_prev_int10h_c + 2, es mov dx, _int10h_handler_c push ds mov ax, cs mov ds, ax mov ax, 2510h int 21h pop ds _proc_arg_n_done: jmp _proc_arg_next ; ---------------------------------------------------------- ; -g Will read the time and date from a hardware clock ; and sets the time and date in DOS. Use /G0 for a ; jrCaptain and /G1 for the PCE jrRom-Clock. ; ; If /G0 assumes the jrCaptain clock chip is using ; address (37D hex - 893 decimal). If you have changed ; the jumper on the jrCaptain circuit board to set your ; clock chip at (27D hex 637 decimal) then use /G637. ; ; If your clock is at another address, use /Gnnn where ; nnn is the decimal address of the clock chip. If there ; is a problem reading the clock chip, jrConfig will beep ; and give the general error message about "thexoptions ; list in CONFIG.SYS". If you are sure that nothing is ; wrong with your clock chip, then it is either at ; another address or it is incompatible with jrConfig. _proc_arg_g: cmp al, 'g' jne _proc_arg_v cmp bl, 0 je _proc_arg_g_go mov cs:_rtc_io_address, bx _proc_arg_g_go: call _rtc_jrc_init jmp _proc_arg_next ; ---------------------------------------------------------- ; -v Will reserve video ram, where n is 4 to 96. Normally 16K is ; set aside for video ram, you can either decrease or increase ; this amount with this option. Using -v4 will reserve 4K for ; video, giving you an extra 12K of user ram, but you must not ; use any graphics modes or a program that uses text pages ; other than the first test page. If you are concerned about ; speed, you may not want to use this option with a value less ; than 16. The extra RAM that you get this way will be in the ; video page, and that will be in the first 128K. Any other ; device drivers and COMMAND.COM will load into this area. ; Unless you have some large device drivers, the regular DOS ; programs you run will start in this low RAM. Don't be fooled ; by the size of the files on the disk. JRCONFIG is over half ; initialization code, the resident portion is less than 2K. ; Only about 3K of COMMAND.COM will load into low memory, the ; rest is the transient portion that is at the top of DOS ; memory. High values are used for reserving ram to be used ; for high-res graphics (32K) or extra video pages. _proc_arg_v: cmp al, 'v' jne _proc_arg_t cmp bl, 60h ja _proc_arg_v_error and bl, 0feh jz _proc_arg_v_error mov cs:_video_kb, bl jmp _proc_arg_next ; ---------------------------------------------------------- ; -t Will set the video display mode, use -tn where n is: ; ; Alpha Modes ; 0 for 40 X 25 B/W (Default) ; 1 for 40 X 25 Color ; 2 for 80 X 25 B/W ; 3 for 80 X 25 Color _proc_arg_t: cmp al, 't' jne _proc_arg_c cmp bl, 2 jb _proc_arg_t_go cmp bl, 3 ja _proc_arg_t_go ; For 80 column text modes, update BDA push es mov ax, 0040h mov es, ax mov ax, es:BDA_EQUIP_BITS and al, 0cfh or al, 20h mov es:BDA_EQUIP_BITS, ax pop es _proc_arg_t_go: mov ah, 0 mov al, bl int 10h jmp _proc_arg_next ; ---------------------------------------------------------- ; -c Will turn on the keyboard click. _proc_arg_c: cmp al, 'c' jne _proc_arg_x mov ax, 0401h int 16h jmp _proc_arg_next ; ---------------------------------------------------------- ; -x Will set the proper step motor rate in DOS 3.x, this will ; make the disk quieter. Note: this will not take effect until ; after you see the initialization message. ; ; The default step rate for the PCjr is 13; which is the best ; rate for most 5.25 inch drives. If you want to make it some ; other value, use -xnn where nn is from 1 to 15. If you have ; a 3.5 inch drive that is noisy, using n = 14 may quiet it ; down; although it may make the 5.25 drive slightly noisier. ; You may need to experiment with different values for the ; best value for your combination of drives. If the step rate ; is set wrong for your drive it can become noisy and you may ; have read/write errors, so use this options carefully. Note, ; if you do not specify a step rate, the default value is ; used. _proc_arg_x: cmp al, 'x' jne _proc_arg_b and bl, 0fh cmp bl, 0 jz _loc_152 push ds push cx mov cl, 4 shl bl, cl mov ax, 0050h mov ds, ax mov al, ds:[22h] and al, 0fh or al, bl mov ds:[22h], al pop cx pop ds _loc_152: xor ax, ax int 13h jmp _proc_arg_next _proc_arg_v_error: jmp _proc_arg_error_jump nop ; ---------------------------------------------------------- ; -b Will move the screen n positions to the right, use -bn where ; n is from 1 to 7. ; Note: Both -a & -b MUST come after the -t option on the ; command line in CONFIG.SYS. If the -t option comes ; after either -a or -b, there effect will be cancelled. _proc_arg_b: cmp al, 'b' jne _proc_arg_a push ds push dx mov ax, 0040h mov ds, ax mov al, ds:BDA_VIDEO_FLAGS ; and bx, 7 ; fixup - open watcom encodes this more efficiently (w/ 1 byte immediate) db 81h, 0e3h, 07h, 00h cmp bl, 0 jne _proc_arg_b_save inc bx _proc_arg_b_save: sub ax, bx mov ds:BDA_VIDEO_FLAGS, al jmp _proc_arg_ab_go ; ---------------------------------------------------------- ; -a Will move the screen n positions to the left, use -an where ; n is from 1 to 7. _proc_arg_a: cmp al, 'a' jne _proc_arg_k push ds push dx mov ax, 0040h mov ds, ax mov al, ds:BDA_VIDEO_FLAGS ; and bx, 7 ; fixup - open watcom encodes this more efficiently (w/ 1 byte immediate) db 81h, 0e3h, 07h, 00h cmp bl, 0 jne _proc_arg_a_save inc bx _proc_arg_a_save: add ax, bx mov ds:BDA_VIDEO_FLAGS, al _proc_arg_ab_go: mov al, 2 ; Horizontal sync position mov dx, PORT_CRT_ADDRESS out dx, al mov al, ds:BDA_VIDEO_FLAGS inc dx ; Advance to data register out dx, al pop dx pop ds _proc_arg_ab_done: jmp _proc_arg_next ; ---------------------------------------------------------- ; -k Will set Caps-Lock (Note: If you have a keyboard with an ; indicator light for Caps-Lock, the light will not be turned ; on.) _proc_arg_k: cmp al, 'k' jne _proc_arg_w push es mov ax, 0040h mov es, ax mov bx, BDA_KBD_SHIFT_FLAG mov byte ptr es:[bx], 40h pop es jmp _proc_arg_next ; ---------------------------------------------------------- _proc_arg_error_jump: jmp _proc_arg_error nop ; ---------------------------------------------------------- ; -w Will put a clockwise spinning character in on the top ; row of your screen whenever the ramdisk is accessed. ; Use -wnn where nn is the column you want it to sppear ; in. _proc_arg_w: cmp al, 'w' jne _proc_arg_e cmp bl, 50h ja _proc_arg_error_jump mov bh, 0 rol bx, 1 mov cs:_spinchar_offset, bx jmp _proc_arg_next ; ---------------------------------------------------------- ; -e Will set the number of directory entries allowed on the ; ramdisk. The default is 16 entries. Use -en where: ; -e1 will allow 32 entries ; -e2 will allow 64 entries ; -e3 will allow 128 entries ; Each entry uses 32 bytes of the RAM reserved for the ; ramdisk. _proc_arg_e: cmp al, 'e' jne _proc_arg_y cmp bl, 3 ja _proc_arg_error cmp bl, 0 jz _proc_arg_e_skip mov cl, bl shl cs:_bpb_rootdisk_entries, cl _proc_arg_e_skip: jmp _proc_arg_next ; ---------------------------------------------------------- _proc_arg_error: mov byte ptr cs:_cmdline_error, 1 jmp _proc_arg_next ; ---------------------------------------------------------- ; -y Will install the PCE Keyboard Buffer routines if you ; have a Keyboard Buffer or Combo cartridge. ; ; These routines, available only on cartridges, replace ; the keyboard and floppy disk routines, and allow the ; keyboard to be used while the disk drive is being ; accessed. They can also increase the usual 15 ; character keyboard buffer provided by DOS to 47 ; characters. To use the 47 character buffer you must ; reserve space for the larger buffer in the first 64KB ; of RAM. When you use jrConfig without using the /S ; option the cartridges display and "Out of Range" ; message. The reason is that jrConfig has set aside all ; the memory in the first 128KB to improve performance ; (remember: the 47-character buffer must be in the first ; 64KB). ; ; The /Y option solves this problem. It installs either ; the JRSYNC or JRSYNCNP routines, allocates space for ; the 47 character buffer, and allows jrConfig to utilize ; the first 128KB of slow memory as it normally does. To ; install the 47 character buffer after jrConfig has run ; just type JRSYNC47 (you may wish to put that line in ; your AUTOEXEC.BAT file). ; ; Use /Yn where n is: ; ; 0 for version 1.2 ; 1 PCE Keyboard Buffer (or Combo) Cartridge w/ parity check ; 2 PCE Keyboard Buffer (or Combo) Cartridge w/o parity check ; 3 David Cox's Combo Cartridge with parity check ; 4 David Cox's Combo Cartridge without parity check ; ; If you have another version you may wish to try all the ; JRSYNC options. If the initialization message that ; jrConfig prints shows up then jrConfig has found the ; cartridge. If your computer locks up, you have an ; incompatible version. _proc_arg_y: cmp al, 'y' jne _proc_arg_error cmp bl, 4 ja _proc_arg_error push ds mov ax, 0ce00h _loc_174: add ax, 0200h cmp ax, 0f000h jnb _loc_173 mov ds, ax cmp word ptr ds:[008h], 'SR' jne _loc_174 cmp word ptr ds:[00ah], 'NY' jne _loc_174 jmp _loc_175 nop _loc_173: pop ds jmp _proc_arg_next _loc_175: mov cs:_data_48, ax mov byte ptr cs:_data_47, 'J' mov byte ptr cs:_data_43, bl push es push di push si xor ax, ax mov ds, ax out PORT_NMI_MASK, al pushf cli cmp byte ptr cs:_data_43, 0 jnz _loc_176 mov word ptr ds:[008h], 02e8h mov word ptr ds:[038h], 1dafh jmp _loc_177 nop _loc_176: cmp byte ptr cs:_data_43, 2 ja _loc_180 mov word ptr ds:[008h], 04b8h mov word ptr ds:[038h], 1f91h jmp _loc_177 nop _loc_180: mov word ptr ds:[008h], 0459h mov word ptr ds:[038h], 1f32h _loc_177: mov bx, cs:_data_48 mov word ptr ds:[00ah], bx mov word ptr ds:[03ah], bx mov bx, 004eh cmp word ptr ds:[bx], 0f000h call _sub_48 mov ax, cs:_break_min mov es, ax ; add ax, 40h ; fixup - open watcom encodes this more efficiently (w/ 1 byte immediate) db 05h, 40h, 00h mov cs:_break_min, ax mov word ptr es:[060h], 0 cmp byte ptr cs:_data_43, 2 jz _loc_178 cmp byte ptr cs:_data_43, 4 jz _loc_178 mov byte ptr es:[064h], 0 jmp _loc_179 nop _loc_178: mov byte ptr es:[064h], 0ffh _loc_179: mov ax, 0040h mov ds, ax mov ds:BDA_BIOS_DATA_SEG, es mov ax, 00dah mov es, ax mov ax, cs mov ds, ax mov si, _jrsync_table sub dx, dx _loc_182: lodsb mov ah, 0 xchg ax, cx lodsw xchg ax, di mov bx, cx repe cmpsb jnz _loc_181 sub di, bx xchg bx, cx rep movsb inc dx _loc_181: add si, cx add si, bx cmp si, _jrsync_table_end jb _loc_182 popf mov al, 080h out PORT_NMI_MASK, al pop si pop di pop es pop ds jmp _proc_arg_next _proc_command_line endp ; ---------------------------------------------------------- ; FUNC: _memory_check ; ; DESC: Simple check for any additional memory above that ; indicated in the BDA. A word write/read/verify is ; performed every paragraph until it either fails or ; reaches the CGA video window at b8000. The memory ; is cleared as the test progresses. The final ; detected value is placed back in the BDA. ; ; This is done on the first pass before the int 19h ; warm restart so that DOS can have access to the ; full expansion memory after the warm re-start. ; ; INPUTS: none ; ; OUTPUTS: none ; ; CLOBBERS: ax, bx, cx, dx _memory_check proc near public push es push ds push di mov bx, 0040h mov es, bx mov ax, es:[BDA_ADAP_MEM_SIZE] mov cl, 6 ; <<10 for KB, >>4 for segment shl ax, cl _memory_check_loop: xor bx, bx cmp ax, 0b800h ; stop @ CGA window je _memory_check_done mov ds, ax ; simple word write/read mov ds:[bx], ax mov cx, ds:[bx] cmp ax, cx jne _memory_check_done mov cx, 8 ; Clear the tested paragraph mov es, ax xor ax, ax xor di, di rep stosw mov ax, ds inc ax jmp _memory_check_loop _memory_check_done: mov cl, 6 ; <<4 to get to bytes, >>10 for KB shr ax, cl mov bx, 0040h mov es, bx mov es:[BDA_ADAP_MEM_SIZE], ax pop di pop ds pop es _memory_check endp ; This routine is related to jrSyncro Cartridge _sub_48 proc near public jz _loc_105 mov bx, 0102h _loc_105: cmp byte ptr cs:_data_43, 0 jz _loc_57 cmp byte ptr cs:_data_43, 2 ja _loc_58 mov word ptr ds:[bx - 2], 07b6h jmp _loc_59 nop _loc_58: mov word ptr ds:[bx - 2], 0757h jmp _loc_59 nop _loc_57: mov word ptr ds:[bx - 2], 05e0h _loc_59: mov ax, cs:_data_48 mov ds:[bx], ax ret _sub_48 endp _data_43 db 0 _data_48 dw 0e000h _jrsync_table: db 00ah db 0d1h db 00ch db 02eh db 08bh db 026h db 0d1h db 002h db 02eh db 08eh db 016h db 0d3h db 002h db 02eh db 08eh db 016h db 0d3h db 002h db 02eh db 08bh db 026h db 0d1h db 002h db 00ah db 022h db 015h db 036h db 08bh db 026h db 0d1h db 002h db 036h db 08eh db 016h db 0d3h db 002h db 02eh db 08eh db 016h db 0d3h db 002h db 02eh db 08bh db 026h db 0d1h db 002h db 008h db 0d1h db 031h db 0bch db 0d1h db 002h db 08eh db 016h db 0d3h db 002h db 08eh db 016h db 0d3h db 002h db 0bch db 0d1h db 002h db 004h db 05fh db 032h db 08ch db 0c4h db 08eh db 0d4h db 08ch db 0c5h db 08eh _jrsync_table_end: db 0d5h _cmd0_error_cleanup: pop dx _error_allocation: mov dx, _str_error_fatal _cmd0_error_exit: mov ah, 9 int 21h lds bx, ds:_sys_request mov byte ptr ds:[bx + 00dh], 0 mov word ptr ds:[bx + 00eh], _end_resident_portion mov word ptr ds:[bx + 010h], cs ; All versions return offset of 32 for this pointer which is a ; random offset into the BPB for all versions. Since this is ; an error return, maybe it's a status? /shrug - no clue mov word ptr ds:[bx + 012h], 32h mov word ptr ds:[bx + 014h], cs jmp _cmdn_completed ; ---------------------------------------------------------- ; FUNC: _get_next_arg ; ; DESC: Processes next argument in a command line pointed to by ; ds:si consuming the next argument by incrementing si. ; Command arguments follow -L or /L. The letter ; can be upper or lower case and the optional argument must ; be a decimal number. ; ; NOTE: On invalid argument, jumps directly to _proc_arg_error ; ; INPUTS: ds:si - Next character in string ; ; OUTPUTS: al - 0 on error, lower case letter on success ; bx - optional decimal value or zero if not present ; ds:si - Advances past argument consumed ; ; CLOBBERS: cx, dx _get_next_arg proc near public xor bx, bx mov cx, bx _find_arg: lodsb cmp al, ' ' je _find_arg cmp al, TAB je _find_arg cmp al, CR je _last_arg cmp al, '-' je _tolower_arg cmp al, '/' jne _find_arg _tolower_arg: lodsb or al, ' ' mov cl, al _todecimal_arg: lodsb sub al, '0' jb _invalid_arg cmp al, TAB ja _invalid_arg cbw xchg ax, bx mov dx, 10 mul dx add bx, ax jmp _todecimal_arg _invalid_arg: add al, '0' cmp al, ' ' jbe _last_arg cmp al, '-' jz _last_arg cmp al, '/' jz _last_arg pop ds jmp _proc_arg_error ; stack leak _last_arg: dec si ret _get_next_arg endp _expanded_mem db 0 ; 2nd pass w/ >=256KB confirmed _ramdisk_size_ext dw 0 ; Size above video frame (paragraphs) _ramdisk_size dw -1 ; Size below video frame (paragraphs) _str_error_fatal: db 'FATAL ERROR: Check Parameters in CONFIG.SYS', CR, LF, '$' _str_error_mem: db 'ERROR: Not enough memory. At least 256K is needed.', CR, LF, '$' ; Lower 2 bits (only) indicate installed floppy count minus one. ; This variable is eventually stuffed into the upper two bits ; of the first byte of the BDA equipment status bits. _floppy_count db 0 ; ---------------------------------------------------------- ; FUNC: _update_ram_string ; ; DESC: Modifies the ram size string to reflect detected amount ; of conventional memory ; ; INPUTS: ax - Size of RAM in KB ; ; OUTPUTS: none ; ; CLOBBERS: none _update_ram_string proc near public push ax push bx push cx push dx xor cx, cx mov bx, 10 _update_ram_todec: xor dx, dx div bx add dx, '0' push dx inc cx or ax, ax jnz _update_ram_todec mov bx, 0 _update_ram_copy: pop dx mov byte ptr cs:[STR_RAM_SIZE][bx], dl inc bx loop _update_ram_copy pop dx pop cx pop bx pop ax ret _update_ram_string endp ; ---------------------------------------------------------- ; FUNC: _update_floppycount_string ; ; DESC: Modifies the detected floppy count string to reflect ; the number of floppy drives in the BDA ; ; INPUTS: none ; ; OUTPUTS: none ; ; CLOBBERS: none _update_floppycount_string proc near public push ax push bx push cx push es mov ax, 040h mov es, ax mov bx, BDA_EQUIP_BITS mov al, es:[bx] mov cl, 6 shr al, cl and al, 3 add byte ptr cs:[STR_FLOPPY_COUNT], al pop es pop cx pop bx pop ax ret _update_floppycount_string endp ; ---------------------------------------------------------- ; FUNC: _rtc_jrc_init ; ; DESC: If detected, set DOS date and time from a ; jrCaptain RTC device ; ; INPUTS: none ; ; OUTPUTS: none ; ; CLOBBERS: ax _rtc_jrc_init proc near public xor ax, ax call _rtc_jrc_detect or al, al jz _rtc_jrc_init_go _rtc_jrc_init_error: mov byte ptr cs:_cmdline_error, 1 jmp _rtc_jrc_done _rtc_jrc_init_go: call _rtc_jrc_set or al, al jnz _rtc_jrc_init_error _rtc_jrc_done: ret _rtc_jrc_init endp ; ---------------------------------------------------------- ; FUNC: _rtc_jrc_set ; ; DESC: Set DOS date and time from a jrCaptain RTC device ; ; INPUTS: none ; ; OUTPUTS: none ; ; CLOBBERS: ax _rtc_jrc_set proc near public mov ah, 0ah call _rtc_io_read and al, 0c0h jnz _rtc_jrc_set_error _rtc_jrc_set_ready: mov ah, 0 call _rtc_io_read or al, al jnz _rtc_jrc_set_ready mov cx, 0 mov dx, cx mov ah, 2dh int 21h mov ah, 4 call _rtc_io_read call _to_bcd mov ch, al mov ah, 3 call _rtc_io_read call _to_bcd mov cl, al mov ah, 2 call _rtc_io_read call _to_bcd mov dh, al mov ah, 1 call _rtc_io_read call _to_bcd mov dl, al mov ah, 2dh int 21h ; set time or al, al jnz _rtc_jrc_set_error call _sub_45 call _sub_46 mov ah, 2bh int 21h ; set date or al, al jnz _rtc_jrc_set_error mov al, 0 ret _rtc_jrc_set_error: mov al, 1 ret _rtc_jrc_set endp ; ---------------------------------------------------------- ; FUNC: _to_bcd ; ; DESC: Convert value in al from hexidecimal value to binary ; coded decimal ; ; INPUTS: al - HEX value to convert ; ; OUTPUTS: al - BCD result ; ; CLOBBERS: none _to_bcd proc near public push cx mov ch, al mov cl, 4 shr al, cl mov cl, 10 mul cl and ch, 0fh add al, ch pop cx ret _to_bcd endp ; ---------------------------------------------------------- ; FUNC: _rtc_io_read ; ; DESC: Read a register value from a jrCaptain RTC ; ; INPUTS: ah - Register address to read ; ; OUTPUTS: al - Register value ; ; CLOBBERS: none _rtc_io_read proc near public push dx mov al, ah mov dx, cs:_rtc_io_address out dx, al inc dx inc dx in al, dx pop dx ret _rtc_io_read endp ; ---------------------------------------------------------- ; FUNC: _rtc_io_write ; ; DESC: Write a register value to a jrCaptain RTC ; ; INPUTS: ah - Register address to write ; al - Register value to write ; ; OUTPUTS: none ; ; CLOBBERS: none _rtc_io_write proc near public push dx xchg ah, al mov dx, cs:_rtc_io_address out dx, al inc dx inc dx mov al, ah out dx, al pop dx ret _rtc_io_write endp _sub_45 proc near public mov ah, 0fh call _rtc_io_read mov bh, al call _to_bcd mov ah, 0 mov dx, 0064h mul dx mov cx, ax mov ah, 0eh call _rtc_io_read mov bl, al call _to_bcd mov ah, 0 add cx, ax mov ah, 9 call _rtc_io_read mov dl, al mov ah, 7 call _rtc_io_read mov dh, al mov ah, 9 call _rtc_io_write cmp dl, dh jle _loc_158 inc cx mov al, 1 add al, bl daa mov bl, al mov al, 0 adc al, bh daa mov ah, 0fh call _rtc_io_write mov ah, 0eh mov al, bl call _rtc_io_write mov ax, cx ; and ax, 3 ; fixup - open watcom encodes this more efficiently (w/ 1 byte immediate) db 25h, 03h, 00h or ax, ax jnz _loc_158 mov ax, 0a01h call _rtc_io_write _loc_158: ret _sub_45 endp _sub_46 proc near public mov ah, 7 call _rtc_io_read mov bh, al call _to_bcd mov dh, al mov ah, 6 call _rtc_io_read mov bl, al call _to_bcd mov dl, al mov ah, 0ah call _rtc_io_read mov cs:_rtc_unknown, al and al, 1 jz _loc_155 cmp dx, 0301h jl _loc_155 jg _loc_156 mov al, 2 mov cs:_rtc_unknown, al jmp _loc_157 _loc_156: mov al, 0 mov cs:_rtc_unknown, al _loc_157: cmp dl, 1 jne _loc_165 dec dh mov al, bh sub al, 1 das mov bh, 0 mov bl, dh add bx, 04e7h mov bl, ds:[bx] mov bh, al mov al, bl call _to_bcd mov dl, al jmp _loc_166 _loc_165: dec dl mov al, bl sub al, 1 das mov bl, al _loc_166: mov ah, 7 mov al, bh call _rtc_io_write mov ah, 9 mov al, bh call _rtc_io_write mov ah, 6 mov al, bl call _rtc_io_write _loc_155: mov al, cs:_rtc_unknown and al, 2 jz _loc_167 cmp bx, 0228h jne _loc_168 inc dl jmp _loc_167 _loc_168: mov al, 0 mov cs:_rtc_unknown, al _loc_167: mov al, cs:_rtc_unknown mov ah, 0ah call _rtc_io_write ret _sub_46 endp ; ---------------------------------------------------------- ; FUNC: _rtc_jrc_detect ; ; DESC: I believe this attempts to detect and validate a jrCaptain ; RTC. I don't know anything about the hardware and this was ; from a disassembly. So guessing really ; ; INPUTS: none ; ; OUTPUTS: al - 1 on error, 0 on success ; ; CLOBBERS: ah _rtc_jrc_detect proc near public mov ah, 0 ; Read reg 0 -> al call _rtc_io_read mov bl, al and al, 0fh jnz _rtc_jrc_detect_fail cmp bl, 090h ja _rtc_jrc_detect_fail mov cx, 588 ; Arbitrary delay loop _rtc_jrc_detect_delay: loop _rtc_jrc_detect_delay mov ah, 0 ; Read reg 0 -> al call _rtc_io_read mov bh, al and al, 0fh jnz _rtc_jrc_detect_fail cmp bh, 090h ja _rtc_jrc_detect_fail cmp bh, bl je _rtc_jrc_detect_fail mov al, 0 ret _rtc_jrc_detect_fail: mov al, 1 ret _rtc_jrc_detect endp _rtc_unknown db 0 _rtc_io_address dw 0037dh _TEXT ends end