; ****************************************************************************
; FDISK2.ASM (FDISK2.COM) //// MSDOS 5.0-6.22 Hard Disk Partitioning Utility
; 	     by Erdogan Tan				  (for MSDOS/WINDOWS)
; ****************************************************************************
; Last Update: 22/12/2022 (Previous: 28/01/2019)
; ----------------------------------------------------------------------------
; Beginning: 06/11/2018
; ----------------------------------------------------------------------------
; Assembler: NASM version 2.11
; ----------------------------------------------------------------------------
; Source Code Reference: MSDOS 6.0 FDISK.EXE source code (in C language).
; ----------------------------------------------------------------------------
; This FDISK (Version 2) source code has been written by using disassembled
;      FDISK.COM source code of IBM PC-DOS 7.0 (1996).
; ****************************************************************************
; nasm fdisk2.s -l fdisk2.txt -o FDISK2.COM
; ============================================================================
;
; ... Retro DOS v3.0 (and Retro DOS v4.0) FDISK utility ... by Erdogan Tan ...

; ---------------------------------------------------------------------------
; -	This file is generated by The Interactive Disassembler (IDA)	    -
; -	Copyright (c) 2010 by Hex-Rays SA, <support@hex-rays.com>	    -
; -			 Licensed to: Freeware version			    -
; ---------------------------------------------------------------------------
;
; Input	MD5   :	60ADAF7E26AAC0C3FD48E6F4E2774E73

; File Name   :	D:\Documents and Settings\Erdošan Tan\Desktop\FDISK70.COM
; Format      :	MS-DOS executable (EXE)
; Base Address:	0h Range: 0h-11CE0h Loaded length: E210h
; Entry	Point :	0:6CAA

; Input	MD5   :	B4080FCD526BEB3060C00FCC3FF4E9CC

; File Name   :	D:\Documents and Settings\Erdošan Tan\Desktop\FDISK.COM
; Format      :	MS-DOS COM-file
; Base Address:	0h Range: 100h-1702h Loaded length: 1602h

; ============================================================================

; (IBM PC-DOS) FDISK.COM (1996) has been unpacked by using UNP.EXE (1997)
; (unpacking program); then, FDISK70.COM (EXE file) has been disassembled
; by using IDA Pro Free (2010) program.

; ============================================================================

	[BITS 16]
	[ORG 100h]

start:
	jmp	short _astart

	dw	2018
	dw	01A1h

	db	0
; ----------------------------------------------------------------------------

;db '<R>                           PC DOS Version 7.0 '
;db 6,'0104',6
;db '<R>                         Fixed Disk Setup Program '
;db 6,'0104',6
;db '<R>                Copyright (c) IBM Corporation 1983 - 1994',0

; ----------------------------------------------------------------------------

;MBR_ADDR:	dw	MBR
buffer:		dw	end_of_file+2

current_partition:
p_status:	db	0
start_head:	db	0
start_cyl_sec:	dw	0
partition_type:	db	0
end_head:	db	0
end_cyl_sec:	dw	0
start_lba_lw:	dw	0
start_lba_hw:	dw	0
sectors_lba_lw:	dw	0
sectors_lba_hw:	dw	0

pt_start_cyl:	dw	0
pt_end_cyl:	dw	0
pt_cylinders:	dw	0
file_system:	db	1
cpartition_number:
		db	0
partition:	db	0
drive:		db	80h ; 0
disk_number:	db	'1' ; 0
wait_for_input:	db	0
max_avl_cylinders: 
		dw	0
next_start_cylinder: 
		dw	0
cylinders:	dw	0
start_cyl:	dw	0
active_part_input:
		db	0
active_partition:
		db	0

; ----------------------------------------------------------------------------
; CRT0 - Modified and simplified for Assembly language
; ----------------------------------------------------------------------------
; 						  (by Erdogan Tan, 06/11/2018)

_astart:
		mov	ah,30h
		int	21h   ; DOS - GET DOS VERSION
			      ; Return: AL = major ver. num. (00h for DOS 1.x)

		;mov	word [_dosvermajor],ax	

		;cmp	al,5	; MSDOS 5.0 or next versions are needed
				; for (correct) running this program. 
		;jnb	short setup

		; 14/11/2018
		cmp	al,3	; MSDOS 3.3 check
		ja	short setup_2
		je	short setup_1

_wrong_version:
		; 'Incorrect dos version!' msg writing code may be put here.
		mov	si,incorrect_dos_version ; ('Incorrect DOS version!')
		call	print_msg 

		xor	ax,ax
		push	es
		push	ax
		retf		; DOS 1.0 exit program (int 20h at psp:0)	
setup_1:
		; 14/11/2018
		cmp	ah,30	; MSDOS 3.30 (3.3) ? (at least) 
   		jb	short _wrong_version
		je	short _correct_version ; Proper version for now...
					 ; .. but, 'Incorrect DOS version' msg
					 ; is waiting at next stage!
					 ; (in 'preload_messages' procedure)
;setup:
setup_2:
		cmp	al,7	; MS-DOS/PC-DOS version 5.0 to 7.1 is proper
		jb	short _correct_version
		ja	short _wrong_version
		cmp	ah,10
		ja	short _wrong_version  

_correct_version:

		; 14/12/2018
		; (clear bss)	
		mov	cx,dataoffset_end_2
		mov	di,bss_start
		sub	cx,di
		inc	cx
		shr	cx,1
		xor	ax, ax		
		rep	stosw
		
		;call	clear_screen

		; process command line (and environment)
		;call	_setenvp
		;call	_setargv ; crack command line

		;;push	word [environ]				
		;push	word [_argv]
		;push	word [_argc]

		call	_main
		;push	ax
		;call	_exit

		;int	20h
_exit:
_exit_:		; 10/12/2018
DOSEXIT:	; 19/11/2018	
		;pop	ax
		mov	ah,4Ch
		int	21h	; DOS -	2+ - QUIT WITH EXIT CODE (EXIT)
				; AL = exit code

; ----------------------------------------------------------------------------

int23h:		; 14/11/2018

		iret

; ----------------------------------------------------------------------------

; ----------------------------------------------------------------------------
; main.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 06/11/2018)

;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SOURCE FILE NAME: FDISK                                     */
;/*                                                             */
;/* DESCRIPTIVE NAME: FIXED DISK PARTITIONING UTILITY           */
;/*                                                             */
;/* FUNCTION:                                                   */
;/*     Allows creation and deletion of DOS related partitions  */
;/*     on fixed disk devices 80-86h (int 13h BIOS defined,     */
;/*     DOS). Also allows display of all partitions, and will   */
;/*     allow a partition to be marked active (bootable). The   */
;/*     user will be prompted for action thru a full screen     */
;/*     interface. The user can also create, delete and display */
;/*     logical DOS drives within a EXTENDED DOS Partition. If a*/
;/*     regular DOS partition is created, the beginning of the  */
;/*     partition will be scanned to insure a contiguous area of*/
;/*     good sectors on the disk large enough to satisfy the    */
;/*     DOS system requirements. If a bad spot is found, the    */
;/*     start of the partition will be moved out until a good   */
;/*     area is located                                         */
;/*                                                             */
;/* NOTES: The program will work by setting up a logical image  */
;/*        of all relevant disk information at initilization    */
;/*        time. All operations will be performed on this       */
;/*        logical image, thus reducing disk accesses to only   */
;/*        those required to initially set up the logical image,*/
;/*        and to write the changed information at the end. The */
;/*        user will be informed if there is a problem writing  */
;/*        the logical image back to the disk.                  */
;/*                                                             */
;/*        FDISK will interface with the partition table in the */
;/*        master boot record as defined in the PC-DOS technical*/
;/*        reference manual. It will also create and manage the */
;/*        EXTENDED DOS partition architecture as defined in the*/
;/*        PC-DOS 3.30 functional spec (CP/DOS spec dcr pending)*/
;/*                                                             */
;/* ENTRY POINTS: MAIN                                          */
;/*    LINKAGE: [d:] [path] FDISK                               */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*              Fixed Disk Master Boot Record                  */
;/*              EXTENDED Partition Volume Boot Records         */
;/*   Note: Both of the above are physical data structures on   */
;/*         the surface of the disk                             */
;/*                                                             */
;/* P.S. - To whoever winds up maintaining this, I will         */
;/*        apoligize in advance. I had just learned 'C' when    */
;/*        writing this, so out of ignorance of the finer points*/
;/*        of the langauge I did a lot of things by brute force.*/
;/*        Hope this doesn't mess you up too much - MT 5/20/86  */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: MAIN                                       */
;/*                                                             */
;/* DESCRIPTIVE NAME: Main control routine                      */
;/*                                                             */
;/* FUNCTION: Main will handle call routines to handle the      */
;/*           setup of the video for the full screen interface, */
;/*           get physical data on the drive characteristics,   */
;/*           initilize all data fields with the current status */
;/*           of the disk partitioning information. Before the  */
;/*           program is terminated, the video is reset to the  */
;/*           mode it was in previous to the routine entry. It  */
;/*           will also handle the case of an improper setup    */
;/*                                                             */
;/* NOTES: FDISK requires at least 1 hardfile to operate        */
;/*                                                             */
;/* ENTRY POINTS: main();                                       */
;/*      LINKAGE:                                               */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: Return Code = 0                                */
;/*                                                             */
;/* EXIT-ERROR: Return Code =  1                                */
;/*                                                             */
;/* EFFECTS: Sets up status variables, sets up video for full   */
;/*          screen interface, and then restores the video mode */
;/*          before exiting program                             */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      init_video_information                                 */
;/*      get_disk_information                                   */
;/*      check_valid_environment                                */
;/*      do_main_menu                                           */
;/*      init_partition_tables                                  */
;/*      reset_video_information                                */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*       DosExit                                               */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/


;/*  */
;/**************************************************************************/
;/*                                                                        */
;/*   UTILITY NAME:         FDISK.com                                      */
;/*   SOURCE FILE NAME:     FDISK.c                                        */
;/*   STATUS:               FDISK utility, DOS 3.3			   */
;/*   CHANGE HISTORY:       UPDATED        5-29-87     DOS4.0       DRM    */
;/*   SYNTAX (Command line)                                                */
;/*                                                                        */
;/*     [d:][path]FDISK                                                    */
;/*                                                                        */
;/*     or                                                                 */
;/*                                                                        */
;/*     [d:][path]FDISK d [/PRI:m | /EXT:n | /LOG:o | /Q | /STATUS | /MBR] */
;/*                                                                        */
;/*         d:      Drive to load FDISK utility from                       */
;/*                                                                        */
;/*         path    path to the directory on specified drive to            */
;/*                 load FDISK from                                        */
;/*                                                                        */
;/*         d       Drive (1 or 2) that FDISK should operate on            */
;/*                                                                        */
;/*         /PRI:m  Size of Primary DOS partition to create in K           */
;/*                                                                        */
;/*         /EXT:n  Size of Extended DOS partition to create in K          */
;/*                                                                        */
;/*         /LOG:o  Size of Logical drive to create in K in the            */
;/*                 extended partition                                     */
;/*                                                                        */
;/*         /Q      This suppresses the reboot screen and returns          */
;/*                 FDISK to DOS even if partitions have changed.          */
;/*                                                                        */
;/*         /STATUS This gives a display of the data portion of the        */
;/*                 Change Current Fixed Disk Drive menu.                  */
;/*                                                                        */
;/*   UTILITY FUNCTION:                                                    */
;/*     Allows you to create, set up, display, afnd delete the             */
;/*     DOS partitions on a fixed disk.                                    */
;/*                                                                        */
;/* PSEUDOCODE:                                                            */
;/*                                                                        */
;/*      Disable CTRL-break                                                */
;/*      IF Preload_messages and get_yes_no_values                         */
;/*          IF Parse Command Line                                         */
;/*              IF no switches set                                        */
;/*                  IF Valid Environment                                  */
;/*                      Change video information                          */
;/*                      IF Get disk information                           */
;/*                          Initialize tables                             */
;/*                          IF status_flag == TRUE                        */
;/*                              display current drive information         */
;/*                          else                                          */
;/*                              display main menu                         */
;/*                              write information to disk                 */
;/*                              IF reboot_flag == TRUE                    */
;/*                                  reboot                                */
;/*                              else                                      */
;/*                                  reset video mode                      */
;/*                              ENDIF  reboot flag                        */
;/*                          ENDIF  status flag                            */
;/*                      ENDIF  get disk info                              */
;/*                  ENDIF  valid environment                              */
;/*              else                                                      */
;/*                  IF all flags == FALSE                                 */
;/*                      display error message                             */
;/*                  else                                                  */
;/*                      IF get_disk_info                                  */
;/*                          IF drive number not valid                     */
;/*                              display error message                     */
;/*                          else                                          */
;/*                              init_partition_tables                     */
;/*                              IF PRIMARY flag == true                   */
;/*                                  find available free space             */
;/*                                  IF asking for too much                */
;/*                                      reset ask to available space      */
;/*                                  else                                  */
;/*                                      change request to cylinders       */
;/*                                  ENDIF                                 */
;/*                                  make the partition                    */
;/*                              ENDIF                                     */
;/*                              IF EXTENDED flag == true                  */
;/*                                  find available free space             */
;/*                                  IF asking for too much                */
;/*                                      reset ask to available space      */
;/*                                  else                                  */
;/*                                      change request to cylinders       */
;/*                                  ENDIF                                 */
;/*                                  make the partition                    */
;/*                              ENDIF                                     */
;/*                              IF LOGICAL flag == true                   */
;/*                                  find available free space in extended */
;/*                                  IF asking for too much                */
;/*                                      reset ask to available space      */
;/*                                  else                                  */
;/*                                      change request to cylinders       */
;/*                                  ENDIF                                 */
;/*                                  make the partition                    */
;/*                              ENDIF                                     */
;/*                              Write information to disk                 */
;/*                          ENDIF                                         */
;/*                      ENDIF                                             */
;/*                  ENDIF                                                 */
;/*              ENDIF                                                     */
;/*          ENDIF                                                         */
;/*      ENDIF                                                             */
;/*      IF no PRIMARY on disk 1 and /Q switch                             */
;/*          exit errorlevel 1                                             */
;/*      else                                                              */
;/*          IF no switches set and /Q option                              */
;/*              exit errorlevel 2                                         */
;/*          else                                                          */
;/*              exit errorlevel 0                                         */
;/*          ENDIF                                                         */
;/*      ENDIF                                                             */
;/*                                                                        */
;/**************************************************************************/
;/*  */

; 24/11/2018

; void main(argc,argv)

	; int	argc;
	; char	*argv[];  

_main:
		;push	bp
		;mov	bp,sp

		;argv	equ 6 		; [bp+6]
		;argc	equ 4		; [bp+4]

		       ; Return Address = [bp+2]

	      ;	unsigned   i;  		; [bp-6] 
	      ;	char       temp; 	; [bp-4]
	      ;	unsigned   input;	; [bp-2]

;	;/* DISABLE CNTL-BREAK HERE */
;	;/* Gets defines from signal.h */
;
;		signal( (int) SIGINT, SIG_IGN ); /* AN000 */

		mov	dx,int23h
		mov	ax,2523h
				; DOS -	SET INTERRUPT VECTOR
		int	21h	; AL = interrupt number
			; DS:DX	= new vector to	be used	for specified interrupt

;	no_fatal_error = TRUE;

		mov	byte [no_fatal_error],1

		; 13/11/2018
		call	preload_messages

		;or	al,al
		;jz	_main_33

		jc	_main_33

		call	get_yes_no_values

		;or	al,al
		;jnz	_main_01

		; 14/11/2018
		;;jnc	_main_01
		;;jmp	short _main_33
		;jmp	short _main_01

; ----------------------------------------------------------------------------

;int23h:
;		iret

; ----------------------------------------------------------------------------

_main_01:
;	;/* Parse the command line for syntax and switches */

	; if(parse_command_line(argc,argv))     

		;push	word [bp+argv]
		;push	word [bp+argc]

		call 	parse_command_line

		;pop	bx
		;pop	bx

		;or	al,al
		;jz	_main_33	; [parse_good] = 0

		jc	_main_33

;	;/* check to see if switches were set */

;	if ((primary_flag == FALSE) && (extended_flag == FALSE) &&
;           (logical_flag == FALSE) && (disk_flag == FALSE) && (mbr_flag == FALSE))

		cmp	byte [primary_flag],0
		jne	short _main_04 ; _main_11
		cmp	byte [extended_flag],0
		jne	short _main_04 ; _main_11
		cmp	byte [logical_flag],0
		jne	short _main_04 ; _main_11
		cmp	byte [disk_flag],0
		jne	short _main_05 ; _main_14
		cmp	byte [mbr_flag],0
		jne	short _main_05 ; _main_14

		mov	byte [reboot_flag],0

;	;/* See if running evironment is ok (Got hardfile, no network)

		call	check_valid_environment

		;or	al,al
		;jnz	short _main_02
		;jmp	_main_33

		jnc	short _main_02
		jmp	_main_33
_main_02:
;	;/* Get and save screen mode information */

		call	init_video_information

		;mov	ax,79
		;push	ax	 ; Bottom Rigth Column (79)  
		;mov	ax,24
		;push	ax	 ; Bottom Row (24)
		;sub	ax,ax ; 0
		;push	ax	 ; Top Left Column (0)	
		;push	ax	 ; Top Row (0)
		;
		;call	clear_screen
		;
		;add	sp,8	; 15/11/2018

		; Clear screen (clear whole video page)
		call	CLS	; 16/11/2018

;	;/* Get disk size information */

		; for (i=0; i < u(MAX_HDISK); i++)
                ;     good_disk[i] = TRUE;

		;mov	word [_i],0
		xor	bx,bx
_main_03:
		;mov	bx,[_i]
		mov	byte [good_disk+bx],1 ; TRUE
		;inc	word [_i]
		;inc	bx
		inc	bl
		;cmp	word [_i],8
		cmp	bl,8
		jb	short _main_03

		; if (get_disk_info())

		call	get_disk_info

		;or	al,al
		;jz	short _main_07

		jc	short _main_07

;	;/* build memory model of partitions */

		call	init_partition_tables
		mov	byte [cur_disk],0

		;if (status_flag == TRUE)
		cmp	byte [status_flag],1 ; TRUE
		jne	short _main_06  ; else

		call	change_current_drive
		;jmp	short _main_07
		; 19/11/2018
		jmp	_main_33
_main_04:
		jmp	_main_11
_main_05:
		jmp	_main_14	
_main_06:

;	;/* Go do main screen */
		call	do_main_menu
		call	write_info_to_disk
_main_07:
		; if (!status_flag)
		cmp	byte [status_flag],0 ; FALSE
		je	short _main_08
		jmp	_main_33
_main_08:
		cmp	byte [reboot_flag],0
		je	short _main_09
		call	reboot_system

		; DOSEXIT((unsigned) 0,(unsigned) 0); 
		sub	ax,ax
		;push	ax
		;push	ax
		call	DOSEXIT
_main_09:
		cmp	byte [no_fatal_error],0
		jne	short _main_10
		jmp	_main_33
_main_10:
;	 ;/* Nearly done, go reset screen mode */

		call	reset_video_information
		jmp	_main_33
; else

; if ((((primary_flag == FALSE) && (extended_flag == FALSE) &&
;        (logical_flag == FALSE)) || (disk_flag == FALSE)) && (mbr_flag == FALSE))
; display_msg((int)8,(int)DosStdEr,(int)nosubcnt,(int)nosubptr,c(noinput),c(Utility_Msg_Class))	

_main_11:
		cmp	byte [disk_flag],0
		jne	short _main_14

		cmp	byte [mbr_flag],0
		jne	short _main_14

_main_12:	; 14/11/2018
		;jmp	short_main_37		

		mov	al,-1
		push	ax
		sub	al,al
		push	ax
		sub	ax,ax
		push	ax
		push	ax
		mov	ax,2
		push	ax
		mov	ax,8
_main_13:
		push	ax
		call	display_msg
		add	sp,12
		jmp	_main_33

;_main_37:
		; Temporary - 10/11/2018
		;mov	ax,10
		;call	print_parse_error_msg
		;jmp	_main_33

; ----------------------------------------------------------------------------

_main_14:
		mov	byte [reboot_flag],0  ; FALSE

;	;/* Get disk size information */

		; for (i=0; i < u(MAX_HDISK); i++)
                ;     good_disk[i] = TRUE;

		;mov	word [_i],0
		xor	bx,bx
_main_15:
		;mov	bx,[_i]
		mov	byte [good_disk+bx],1 ; TRUE
		;inc	word [_i]
		;inc	bx
		inc	bl
		;cmp	word [_i],8
		cmp	bl,8
		jb	short _main_15

		; if (get_disk_info())

		call	get_disk_info

		;or	al,al
		;jz	short _main_33

		;jc	short _main_33
		jc	_main_33

_main_16:
		mov	al,[cur_disk_buff]
		cbw	; ah = 0
		inc	ax
		mov	cl,[number_of_drives]
		sub	ch,ch

; if (number_of_drives < (cur_disk_buff+1))
; display_msg((int)8,(int)DosStdEr,(int)nosubcnt,(int)nosubptr,c(noinput),c(Utility_Msg_Class));

		cmp	ax,cx
		jg	short _main_12

; else
;	if(mbr_flag == TRUE)  

		cmp	byte [mbr_flag],1
		jne	short _main_22

; if(!read_boot_record(0,0,0,1))
; display_msg((int)11,(int)DosStdEr,(int)nosubcnt,(int)nosubptr,c(noinput),c(Utility_Msg_Class));

		mov	al,1
		; ah = 0
		push	ax
		sub	al,al ; al = 0
		push	ax
		push	ax
		;sub	ax,ax ; ah = 0
		push	ax
		call	read_boot_record
		;add	sp,8  ; 22/12/2018
		
		;or	al,al
		;jnz	short _main_18
		
		jnc	short _main_18
; else  
_main_17:
		; 19/11/2018
		;mov	al,-1
		; 11/12/2018
		xor	ax,ax ; 0
		dec	al ; -1
		push	ax
		;sub	al,al
		inc	al ; 0
		push	ax
		;sub	ax,ax
		push	ax
		push	ax
		;mov	ax,2
		mov	al,2 ; 11/12/2018
		push	ax
		;mov	ax,11
		mov	al,11
		jmp	short _main_13

_main_18:
;	if((boot_record[0x1FE]==0x55) && (boot_record[0x1FF]==0xAA)) 

		;cmp	byte [boot_record+1FEh],55h
		;jne	short _main_19
		;cmp	[boot_record+1FFh],0AAh
		;jne	short _main_19

		;mov	cx,1FFh ; 10/11/2018
		mov	cx,1BDh
 
		cmp	word [boot_record+1FEh],0AA55h
		;jne	short _main_19
		je	short _main_19 ; 10/11/2018

		; for(i=0; i<=0x1BD; i++)
                ;    boot_record[i] = master_boot_record[0][i]; 

		;;mov	cx,1BDh
		;mov	cl,0BDh ; 10/11/2018
		mov	cl,0FFh
_main_19:
		;mov	word [_i],0
		xor	bx,bx
_main_20:
		;mov	bx,[_i]
		mov     al,[master_boot_record+bx]
		mov	[boot_record+bx],al
		;inc	word [_i]
		inc	bx
		;cmp	word [_i],cx
		cmp	bx,cx
		jbe	short _main_20

		; 15/12/2018
		;sub	al,al ; disk 0
		sub	ax,ax
		push	ax 
		;sub	ax,ax ; cylinder 0
		push	ax
		call	write_boot_record
		;pop	bx
		;pop	bx ; 22/12/2018
		
		;or	al,al
		;jz	short _main_17
		
		jc	short _main_17

		jmp	_main_33
_main_21:
;	else
        	; for(i=0; i<=0x1FF; i++)
                ;    boot_record[i] = master_boot_record[0][i];        

		mov	cx,1FFh
		jmp	short _main_19

_main_22:
;	;/* build memory model of partitions */

		call	init_partition_tables

;	;/* set cur_disk to current disk */

		mov	al,[cur_disk_buff]
		mov	[cur_disk],al

		DOS12	equ  1	; FAT12 PARTITION ID
		DOS16	equ  4	; FAT16 PARTITION (<=32MB) ID
		DOSNEW	equ  6	; FAT16 BIG PARTITION (<32MB) ID
	
		;DOS16BIG equ 6	; FAT16 BIG PARTITION (>32MB) ID

		EXTENDED equ 5	; EXTENDED DOS PARTITION ID

;	;/* If /PRI: was specified, create primary partition */
;	;/* check to see if a primary partition already exists */

		cmp	byte [primary_flag],1
		jne	short _main_25

;	if ( (primary_flag == TRUE)  && 
;          ( (!find_partition_type(uc(DOS12))) &&
;            (!find_partition_type(uc(DOS16))) &&
;            (!find_partition_type(uc(DOSNEW))) ) )

		mov	al,DOS12 ; 1
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short _main_25
		jnc	short _main_25

		mov	al,DOS16 ; 4
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short _main_25
		jnc	short _main_25

		mov	al,DOSNEW ; 6
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short _main_25
		jnc	short _main_25

		xor	al,al ; 14/01/2019
		;push	ax
		; AL = 0
		call	find_part_free_space
		;pop	bx

;	temp = find_part_free_space((char) PRIMARY);
;	if (primary_buff >= free_space[temp].mbytes_unused)

		mov	[_temp],al
		;mov	al,22
		;imul	byte [_temp]
		mov	bl,22
		mul	bl
		mov	bx,ax
		mov	ax,[primary_buff]
		; 13/01/2019
		cmp	[free_space.mbytes_unused+bx],ax
		ja	short _main_23
		mov	ax,[free_space.space+bx]
		jmp	short _main_24
_main_23:
;else
;	input = (unsigned)mbytes_to_cylinders(primary_buff,cur_disk_buff);

		mov	al,[cur_disk_buff]
		push	ax
		push	word [primary_buff]
		call	mbytes_to_cylinders
		;pop	bx
		;pop	bx
_main_24:
;	make_partition(input,temp,uc(ACTIVE),(char)PRIMARY);

		mov	[_input],ax
		sub	al,al ; 0 	
		push	ax	      ; mp_type - PRIMARY -			
		mov	al,80h
		push	ax	      ; mp_bootable - bootable, active -  	
		mov	al,[_temp]	
		push	ax	      ;	mp_free_ptr (byte)
		push	word [_input] ; mp_size (word)
		call	make_partition
		;add	sp,8
_main_25:

; /* If /EXT: was specified, create extended partition */
; /* Check and see if there is a primary partition before you create an extended */

		cmp	byte [extended_flag],1
		jne	short _main_29

;	if ( (extended_flag == TRUE) && 
;	   ( (cur_disk >= c(1)) ||
;	     (find_partition_type(uc(DOS12))) ||
;	     (find_partition_type(uc(DOS16))) ||
;	     (find_partition_type(uc(DOSNEW))) ) ) 

		cmp	byte [cur_disk],1
		jge	short _main_26

		mov	al,DOS12 ; 1
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short _main_26
		jnc	short _main_26

		mov	al,DOS16 ; 4
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short _main_26
		jnc	short _main_26

		mov	al,DOSNEW ; 6
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short _main_29
		jc	short _main_29

_main_26:
;	;/* Make sure there isn't an extended already there */
;	if (!find_partition_type(uc(EXTENDED))) 
  
		mov	al,EXTENDED ; 5
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short _main_29
		jnc	short _main_29

	; temp = find_part_free_space((char) EXTENDED);
	
		mov	al,EXTENDED ; 5
		;push	ax
		call	find_part_free_space
		;pop	bx
		
		mov	[_temp],al
		;mov	al,22
		;imul	byte [_temp]
		mov	bl,22
		mul	bl
		mov	bx,ax
;
; if (extended_buff >= free_space[temp].mbytes_unused)
;	input = free_space[temp].space;
; else
; 	input = (unsigned)mbytes_to_cylinders(extended_buff,cur_disk_buff);
; 
		mov	ax,[extended_buff]
		; 13/01/2019
		cmp	[free_space.mbytes_unused+bx],ax
		ja	short _main_27
		mov	ax,[free_space.space+bx]
		jmp	short _main_28
_main_27:
		mov	al,[cur_disk_buff]
		push	ax
		push	word [extended_buff]
		call	mbytes_to_cylinders
		;pop	bx
		;pop	bx
_main_28:
;	make_partition(input,temp,(unsigned char) NUL,(char) EXTENDED)

		mov	[_input],ax
		mov	al,EXTENDED ; 5
		push	ax		; mp_type (byte) - EXTENDED -
		sub	al,al ; 0
		push	ax		; mp_bootable (byte) - not bootable -
		mov	al,[_temp]
		push	ax		; mp_free_ptr (byte)
		push	word [_input]	; mp_size (word)
		call	make_partition
		;add	sp,8

_main_29:
;	;/* If /LOG: was specified, create logical partition */
;
;	   if ( (logical_flag == TRUE) &&
;	        (find_partition_type(uc(EXTENDED))) )

		cmp	byte [logical_flag],1 ; TRUE
		jne	short _main_32
		mov	al,EXTENDED ; 5
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al, al
		;jz	short _main_32
		jc	short _main_32

		; temp = find_ext_free_space();
    		
		call	find_ext_free_space
		mov	[_temp],al
		;mov	al,22
		;imul	byte [_temp]
		mov	bl,22
		mul	bl
		mov	bx,ax
;
; if (logical_buff >= free_space[temp].mbytes_unused)
;	input = free_space[temp].space;
; else
;	input = (unsigned)mbytes_to_cylinders(logical_buff,cur_disk_buff);
;
		mov	ax,[logical_buff]
		; 13/01/2019
		cmp	[free_space.mbytes_unused+bx],ax
		ja	short _main_30
		mov	ax,[free_space.space+bx]
		jmp	short _main_31
_main_30:
		mov	al,[cur_disk_buff]
		push	ax
		push	word [logical_buff]
		call	mbytes_to_cylinders
		;pop	bx
		;pop	bx
_main_31:
		;mov	[_input],ax

		; make_volume(input,temp);  

		;mov	al,[_temp]
		;push	ax
		mov	bl,[_temp]
		push	bx
		;push	word [_input]
		push	ax
		call	make_volume
		;pop	bx
		;pop	bx
_main_32:
		call	write_info_to_disk
_main_33:
		mov	byte [cur_disk],0

;  if ( (quiet_flag == TRUE) &&
;	(!find_partition_type(uc(DOS12))) &&
;	(!find_partition_type(uc(DOS16))) &&
;	(!find_partition_type(uc(DOSNEW))) )  

		cmp	byte [quiet_flag],1
		;jne	short _main_34
		jne	short _main_35

		mov	al,DOS12 ; 1
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short _main_34
		jnc	short _main_34
		
		mov	al,DOS16 ; 4
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short _main_34
		jnc	short _main_34
		
		mov	al,DOSNEW ; 6
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short _main_34
		jnc	short _main_34

		; exit(ERR_LEVEL_1);
		mov	ax,1
		jmp	short _main_36
_main_34:
;  else
	; if ((quiet_flag == TRUE) && 
	;     (primary_flag == FALSE) && 
	;     (extended_flag == FALSE) && 
	;     (logical_flag == FALSE))   

		;cmp	byte [quiet_flag],1
		;jne	short _main_35

		cmp	byte [primary_flag],0
		jne	short _main_35
		cmp	byte [extended_flag],0
		jne	short _main_35
		cmp	byte [logical_flag],0
		jne	short _main_35

		; exit(ERR_LEVEL_2);
		mov	ax,2
		jmp	short _main_36
_main_35:
	; else	
		; exit(ERR_LEVEL_0);
		sub	ax,ax
_main_36:
		;push	ax
		;call	_exit
		;pop	bx
		
		;mov	sp,bp
		;pop	bp

		retn	; Return to '_astart:', '_exit:' address.

; ----------------------------------------------------------------------------
; Microsoft (Optimizing) C 6.0 - STDARGV.ASM
; ----------------------------------------------------------------------------
; Modified for NASM syntax & single C/D/S segment (by Erdogan Tan, 07/11/2018)

;*****************************************************************************
;stdargv.asm - standard & wildcard _setargv routine
;
;	Copyright (c) 1985-1990, Microsoft Corporation.  All rights reserved.
;
;Purpose:
;	processes program command line, with or without wildcard expansion
;
;*****************************************************************************

;_setargv, __setargv - set up "argc" and "argv" for C programs
;
;Purpose:
;	Gets the command line from the PSP and moves the information
;	to its place on the stack.
;
;	SIDE EFFECTS:
;		Allocates space on the stack for the argument strings
;		and a list of pointers to them.
;	ASSUMPTIONS:
;		Under DOS 2, there is no argv[0] string, so we store a null
;		char ('\0').
;
;		Under DOS 3 and later, the argv[0] string is found in the
;		environment segment, after the double null that terminates
;		that segment and after a word of value 1.  The rest of the
;		command line is found in the Program Segment Prefix at
;		offset 81H, and is terminated by a 0DH.  This command "tail"
;		cannot be greater than 126 bytes in length.
;
;		Quote marks and backslashes are treated specially.  A quoted
;		string is passed as a single argument, not including the
;		opening and closing quote characters.  A quote may be imbedded
;		in a string by placing an odd number of backslashes (`\')
;		before it.  Each pair of backslashes which precedes a quote
;		results in a single backslash in the resultant string.
;		An even number of backslashes followed by a quote results in
;		half that many backslashes, and the quote begins or ends the
;		quoted part of the string as is appropriate.  Backslashes not
;		followed by a quote are treated normally.
;
;		[""] ==> []
;		[\"] ==> ["]
;		[" \" "] == [ " ]
;		[" \\"] == [ \]
;		[" \\ "] == [ \\ ]
;		[" \\\" "] == [ \" ]
;		etc.
;		["one two three"] ==> [one two three]
;		[one" two "three] ==> [one two three]
;		[o"ne two t"hree] ==> [one two three]
;		["one \"two\" three"] ==> [one "two" three]
;		["x\\\"x"] ==> [x\"x]
;
;Entry:
;
;Exit:
;	"argv" points to a null-terminated list of pointers to ASCIZ
;	strings, each of which is an argument from the command line.
;	"argc" is the number of arguments.  The strings are copied from
;	the Program Segment Prefix into space allocated on the stack.
;	The list of pointers is also located on the stack.
;
;Uses:
;	All registers except DS, SS, and BP are modified
;	Note especially that SI and DI are NOT preserved!
;
;Exceptions:
;
;*****************************************************************************

;_setargv:
;		DOS_envp equ 2Ch	
;
;		pop	word [retadr]	; get return address (offset)
;
;; Check and store DOS version. This is done here because it cannot be done
;; in CRT0.ASM (Windows replaces CRT0.ASM with their own code) and _setargv()
;; is the only other place in the startup code where the DOS version number
;; needed.
;
;		;mov	ah,30h
;		;int	21h ; DOS - GET DOS VERSION
;			 ; Return: AL = major version number (00h for DOS 1.x)
;		;mov	word [_dosvermajor],ax	
;		;mov	dx,1	 ; dx = number of bytes in argv[0] if DOS 2.x
;		;cmp	al,2
;		;jz	short dos_two
;
;		;mov	es,[_psp]
;	
;		; get environment segment
;		;mov	es,[es:DOS_envp] ; [es:2Ch]
;		;mov	[_pgmptr+2],es	; set global variable "_pgmptr"
;
;		mov	ax,[DOS_envp]	; [2Ch] 
;		mov	[_pgmptr+2],ax
;
;		; Erdogan Tan - 07/11/2018
;		mov	bx,ds ; *
;		mov	es,ax
;
;		xor	ax,ax
;		cwd
;		mov	cx,8000h
;		xor	di,di;		; scan from beginning of environment
;find_env_end:
;		repne scasb
;		scasb
;		jnz	short find_env_end
;		inc	di;		; skip count word (always 0x0001)
;		inc	di
;		mov	[_pgmptr], di	; set global variable "_pgmptr"
;		mov	cx,0FFFFh
;		repne scasb
;		not	cx
;		mov	dx,cx;		; DX=number of bytes in argv[0]
;dos_two:
;		mov	di,1;		; always start with one argument
;		mov	si,81h
;
;		;mov	ds,[_psp]
;arg100:
;
;;*	Count the command tail arguments
;;*
;;
;;	DI will count the number of arguments
;;	DX will count the number of bytes needed for the arguments
;;		(not including the null terminators)
;
;arg110:
;		lodsb
;		cmp	al,' '	; 20h	; C_BLANK  ; space chr
;		jz	short arg110
;		cmp	al,9	; TAB	; C_TAB
;		jz	short arg110	
;
;		;DELIM	arg400;		
;
;		cmp	al,0Dh	;  CR	; ENTER
;		jz	short arg400
;		or	al,al	; 0 = ASCIIZ string terminator (ZERO chr)
;		jz	short arg400
;
; ----------------------------------------------------------------------------
; psdata.inc (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; 10/11/2018

;*******************************************************************
; Parser include file
;*******************************************************************

;**** Equation field
;-------- Character code definition

; version.inc (	ifndef DBCS)
DB_SPACE EQU 2020h
DB_SP_HI EQU 20h
DB_SP_LO EQU 20h

_$P_DBSP1	   equ	DB_SP_HI	; 1st byte of DBCS blank
_$P_DBSP2	   equ	DB_SP_LO	; 2nd byte of DBCS blank
_$P_Period	   equ	"."             ;
_$P_Slash	   equ	"/"             ;
_$P_Space	   equ	" "             ; SBCS blank
_$P_Comma	   equ	","             ;
_$P_Switch	   equ	"/"             ;
_$P_Keyword	   equ	"="             ;
_$P_Colon	   equ	":"             ;
_$P_Plus 	   equ	"+"             ;
_$P_Minus	   equ	"-"             ;
_$P_Rparen	   equ	")"             ;
_$P_Lparen	   equ	"("             ;
;_$P_SQuote	   equ  "'"		; Deleted
_$P_DQuote	   equ	'"'             ;
_$P_NULL 	   equ	0		;
_$P_TAB		   equ	9		;
_$P_CR		   equ	0Dh		;
_$P_LF		   equ	0Ah		;
_$P_ASCII80	   equ	80h		; ASCII 80h character code

;-------- Masks
_$P_Make_Lower	   equ	20h		; make lower case character
_$P_Make_Upper	   equ	0FFh-_$P_Make_Lower ; make upper case character

;-------- DOS function call related equs

_$P_DOS_Get_CDI	   equ	3800h		; get country dependent information
					; by this call, following information
struc _$P_CDI	; _$P_CDI		; is returned.
.DateF:	   resw 1			;
.Money:	   resb	5			;
.1000:	   resb	2			;
.Dec:	   resb 2			;
.DateS:	   resb 2			;
.TimeS:	   resb	2			;
	   resb 1			;
	   resb 1			;
.TimeF:	   resb 1			;
	   resw	2			;
	   resb 2			;
	   resb	5			;
.size:
endstruc

_$P_Date_MDY	   equ	0		;
_$P_Date_DMY	   equ	1		;
_$P_Date_YMD	   equ	2		;
;-------------
_$P_DOS_GetEV	   equ	6300h		; get DBCS EV call
					; DS:SI will points to DBCS EV
;-------------
_$P_DOS_Get_TBL	   equ	65h		; get uppercase table call
					; following parameters are set
					; to get casemap table.
_$P_DOSTBL_Def	   equ	-1		; get default
_$P_DOSTBL_BL	   equ	5		; buffer length for Tbl pointer
_$P_DOSTBL_File	   equ	4		; get file uppercase table
_$P_DOSTBL_Char	   equ	2		; get character uppercase table
					; By this call following information
					; is returned.
struc _$P_DOS_TBL
.InfoID:   resb 1			; information id for the table
.Off:	   resw 1			; offset address of the table
.Seg:	   resw 1			; segment address of the table
.size:
endstruc

; ----------------------------------------------------------------------------------
; PARMS 	LABEL	BYTE
;		DW	PARMSX
;		DB	2		; NUMBER OF STRINGS (0, 1, 2)
;		DB	length		; LENGTH OF THE NEXT LIST, 0 IF NONE
;		DB	" .. "		; EXTRA DELIMITER LIST,
;					; TYPICAL ARE ";", "="
;					; "," & WHITESPACE ALWAYS
;		DB	length		; LENGTH OF THE NEXT LIST, 0 IF NONE
;		DB	" .. "		; EXTRA END OF LINE LIST, CR, LF OR 0 ALWAYS
; ----------------------------------------------------------------------------------

;-------------------------------- PARMS block structure
struc _$P_PARMS	; _$P_PARMS_Blk
.PARMSX_Address:  resw 1		; Address of PARMSX
.Num_Extra:	  resb 1		; Number of extra stuff
.Len_Extra_Delim: resb 1		; Length of extra delimiter
.size:
endstruc

_$P_Len_PARMS	   equ	4		;
_$P_I_Use_Default   equ	0		; no extra stuff specified
_$P_I_Have_Delim    equ	1		; extra delimiter specified
_$P_I_Have_EOL	   equ	2		; extra EOL specified

; ----------------------------------------------------------------------------------
; PARMSX	LABEL	BYTE
;		DB	minp,maxp	; MIN, MAX POSITIONAL OPERANDS ALLOWED
;		DW	CONTROL 	; DESCRIPTION OF POSITIONAL 1
;		:			; REPEATS maxp-1 TIMES
;		DB	maxs		; # OF SWITCHES
;		DW	CONTROL 	; DESCRIPTION OF SWITCH 1
;		:			; REPEATS maxs-1 TIMES
;		DB	maxk		; # OF KEYWORD
;		DW	CONTROL 	; DESCRIPTION OF KEYWORD 1
;		:			; REPEATS maxk-1 TIMES
; ----------------------------------------------------------------------------------

;-------------------------------- PARMSX block structure
struc _$P_PARMSX ; _$P_PARMSX_Blk		;
.MinP:	      resb 1			; Minimum positional number
.Maxp:	      resb 1			; Maximum positional number
.1st_Control: resw 1			; Address of the 1st CONTROL block
.size:
endstruc

;--------------------------------------------------------------------------------------------
; << Control field definition  >>
;
;CONTROL   LABEL   BYTE
;	   DW	   MATCH_FLAGS	   ; CONTROLS TYPE MATCHED
;				   ; 8000H=NUMERIC VALUE, (VALUE LIST WILL BE CHECKED)
;				   ; 4000H=SIGNED NUMERIC VALUE (VALUE LIST WILL BE CHECKED)
;				   ; 2000H=SIMPLE STRING(VALUE LIST WILL BE CHECKED)
;				   ; 1000H=DATE STRING (VALUE LIST WON'T BE CHECKED)
;				   ; 0800H=TIME STRING (VALUE LIST WON'T BE CHECKED)
;				   ; 0400H=COMPLEX LIST (VALUE LIST WON'T BE CHECKED)
;				   ; 0200H=FILE SPEC (VALUE LIST WON'T BE CHECKED)
;				   ; 0100H=DRIVE ONLY (VALUE LIST WON'T BE CHECKED)
;				   ; 0080H=QUOTED STRING (VALUE LIST WON'T BE CHECKED)
;				   ; 0010H=IGNORE ":" AT END IN MATCH
;				   ; 0002H=REPEATS ALLOWED
;				   ; 0001H=OPTIONAL
;	   DW	   FUNCTION_FLAGS
;				   ; 0001H=CAP RESULT BY FILE TABLE
;				   ; 0002H=CAP RESULT BY CHAR TABLE
;				   ; 0010H=REMOVE ":" AT END
;				   ; 0020H=colon is not necessary for switch
;	   DW	   RESULT	   ; RESULT BUFFER
;	   DW	   VALUES	   ; VALUE LISTS
;	   DB	   nid		   ; NUMBER OF KEYWORD/SWITCH SYNONYMS IN FOLLOWING LIST
;	   DB	   "...",0         ; IF n >0, KEYWORD 1
;	   :
;
;Note:
;    - The MATCH_FLAG is bit significant. You can set, for example, TIME bit and
;      DATE bit simalteniously.
;
;      The parser examins each bit along with the following priority.
;
;      COMPLEX -> DATE -> TIME -> NUMERIC VAL -> SIGNED NUMERIC VAL -> DRIVE ->
;      FILE SPEC -> SIMPLE STRING.
;
;
;    - When the FUNCTION_FLAG is 0001 or 0002, the STRING pointed to by a pointer
;      in the result buffer is capitalized.
;
;    - Match_Flags 0001H and 0002H have meaning only for the positional.
;
;
;    - The "...",0 (bottom most line) does require '=' or '/'. When you need a
;      switch, for example, '/A', then STRING points to;
;
;			DB    1 	; number of following synonyms
;			DB   '/A',0
;
;      When you need a keyword, for example, 'CODEPAGE=', then "...",0 will be;
;
;			DB    1 	; number of following synonyms
;			DB   'CODEPAGE=',0
;
;
;    - "..." must consist of upper case characters only because the parser
;      performs pattern matching after converting input to upper case (by
;      using the current country upper case table)
;
;
;    - One "..." can contain only one switch or keyword. If you need, for
;      example /A and /B, the format will be;
;
;			DB    2 	; number of following synonyms
;			DB    '/A',0
;			DB    '/B',0
;--------------------------------------------------------------------------------------------

;**** Match_Flags

_$P_Num_Val	   equ	8000h		; Numeric Value
_$P_SNum_Val	   equ	4000h		; Signed numeric value
_$P_Simple_S	   equ	2000h		; Simple string
_$P_Date_S	   equ	1000h		; Date string
_$P_Time_S	   equ	0800h		; Time string
_$P_Cmpx_S	   equ	0400h		; Complex string
_$P_File_Spc	   equ	0200h		; File Spec
_$P_Drv_Only	   equ	0100h		; Drive Only
_$P_Qu_String	   equ	0080h		; Quoted string
_$P_Ig_Colon	   equ	0010h		; Ignore colon at end in match
_$P_Repeat	   equ	0002h		; Repeat allowed
_$P_Optional	   equ	0001h		; Optional

;**** Function flags

_$P_CAP_File	   equ	0001h		; CAP result by file table
_$P_CAP_Char	   equ	0002h		; CAP result by character table
_$P_Rm_Colon	   equ	0010h		; Remove ":" at the end
_$P_colon_is_not_necessary equ 0020h	; /+10 and /+:10

;-------------------------------- Control block structure
struc _$P_Control_Blk ; _$P_Control_Blk
.Match_Flag:	resw 1		; Controls type matched
.Function_Flag: resw 1		; Function should be taken
.Result_Buf:	resw 1		; Result buffer address
.Value_List:	resw 1		; Value list address
.nid:		resb 1		; # of keyword/SW synonyms
.KeyorSW:	resb 1		; keyword or sw
.size:
endstruc

; -------------------------------------------------------------------------------
; << Value List Definition >>
;
;VALUES 	LABEL	BYTE
;		DB	nval		; NUMBER OF VALUE DEFINITIONS (0 - 3)
;	     +-
;	     |	DB	nrng		; NUMBER OF RANGES
;	     | +DB	ITEM_TAG	; RETURN VALUE IF RANGE MATCHED
;	     | +DD	X,Y		; RANGE OF VALUES
;	     |	:
;	     |	DB	nnval		; NUMBER OF CHOICES
;	     | +DB	ITEM_TAG	; RETURN VALUE IF NUMBER CHOICE MATCHED
;	     | +DD	VALUE		; SPECIFIC CHOICE IF NUMBER
;	     |	:
;	     |	DB	nstrval 	; NUMBER OF CHOICES
;	     | +DB	ITEM_TAG	; RETURN VALUE IF STRING CHOICE MATCHED
;	     | +DW	STRING		; SPECIFIC CHOICE IF STING
;	     +-	:
;
;STRING 	DB	"...",0		; ASCIIZ STRING IMAGE
;
;Note:
;    - ITEM_TAG must not be 0FFH, which will be used in the result buffer
;      when no choice lists are provided.
;
;    - STRING must consist of upper case characters only because the parser
;      performs pattern matching after converting input to upper case (by
;      using the current country upper case table)
; -------------------------------------------------------------------------------

_$P_nval_None	   equ	0		; no value list ID
_$P_nval_Range	   equ	1		; range list ID
_$P_nval_Value	   equ	2		; value list ID
_$P_nval_String	   equ	3		; string list ID
_$P_Len_Range	   equ	9		; Length of a range choice(two DD plus one DB)
_$P_Len_Value	   equ	5		; Length of a value choice(one DD plus one DB)
_$P_Len_String	   equ	3		; Length of a string choice(one DW plus one DB)
_$P_No_nrng	   equ	0		; (tm07) no nrng. nnval must not be 0.

struc _$P_Val_List ; _$P_Val_List
.NumofList: resb 1		; number of following choice
.Val_XL:    resw 1		; lower word of value
.Val_XH:    resw 1		; higher word of value
.Val_YL:    resw 1		; lower word of another value
.Val_YH:    resw 1		; higher word of another value
.size:
endstruc

;----------------------------------------------------------------------------------------------------------------
; << Result Buffer Definition  >>
;
;RESULT 	LABEL	BYTE			; BELOW FILLED IN FOR DEFAULTS
;		DB	type			; TYPE RETURNED: 0=RESERVED,
;						;	1=NUMBER, 2=LIST INDEX,
;						;	3=STRING, 4=COMPLEX,
;						;	5=FILESPEC, 6=DRIVE
;						;	7=DATE, 8=TIME
;						;	9=QUOTED STRING
;		DB	ITEM_TAG		; MATCHED ITEM TAG
;
;		dw	synonym@		; es:@ points to found SYNONYM if provided.
;
;            +-
;	    | DD	n			; VALUE IF NUMBER
;	    | or
;	    |	DW	i			; INDEX (OFFSET) INTO VALUE LIST
;	    |					; (ES presents Segment address)
;	    | or
;	    |	DD	STRING			; OFFSET OF STRING VALUE
;	    | or
;	    |	DB	drv			; DRIVE NUMBER (1-A, 2-B,..., 26-Z)
;	    | or
;	    |	DW	YEAR	   ;(1980-2099)	IN CASE OF DATE
;	    |	DB	MONTH	   ;(1-12)	Note: Range check is not performed.
;	    |	DB	DATE	   ;(1-31)	      0 is filled when the corresponding field was not specified.
;	    | or
;	    |	DB	HOUR	   ;(0-23)	IN CASE OF TIME
;	    |	DB	MINUTES    ;(0-59)	Note: Range check is not performed .
;	    |	DB	SECONDS    ;(0-59)	      0 is filled when the corresponding field was not specified.
;	    |	DB	HUNDREDTHS ;(0-99)
;	    +-
;
;Note: ITEM_TAG is 0FFH when the caller does not specify the choice list.
;
;      YEAR: If the input value for the year is less than 100, parser
;	     adds 1900 to it. For example, when 87 is input to parser for
;	     the year value, he returns 1987.
;----------------------------------------------------------------------------------------------------------------

;-------------------------------- Result block structure
struc _$P_Result ; _$P_Result_Blk
.Type:	      resb 1		; Type returned
.Item_Tag:    resb 1		; Matched item tag
.SYNONYM_Ptr: resw 1		; pointer to Synonym list returned
.Picked_Val:  resb 4		; value
.size:
endstruc

;--------------------------------
;**** values for the type field in the result block

_$P_EOL		   equ	0		; End of line
_$P_Number	   equ	1		; Number
_$P_List_Idx	   equ	2		; List Index
_$P_String	   equ	3		; String
_$P_Complex	   equ	4		; Complex
_$P_File_Spec	   equ	5		; File Spec
_$P_Drive	   equ	6		; Drive
_$P_Date_F	   equ	7		; Date
_$P_Time_F	   equ	8		; Time
_$P_Quoted_String   equ	9		; Quoted String

_$P_No_Tag	   equ	0FFH		; No ITEM_TAG found

;**** Return code
;
; following return code will be returned in the AX register.

_$P_No_Error	   equ	0		; No error
_$P_Too_Many	   equ	1		; Too many operands
_$P_Op_Missing	   equ	2		; Required operand missing
_$P_Not_In_SW	   equ	3		; Not in switch list provided
_$P_Not_In_Key	   equ	4		; Not in keyword list provided
_$P_Out_Of_Range   equ	6		; Out of range specified
_$P_Not_In_Val	   equ	7		; Not in value list provided
_$P_Not_In_Str	   equ	8		; Not in string list provided
_$P_Syntax	   equ	9		; Syntax error
_$P_RC_EOL	   equ	-1		; End of command line

_$P_equ		   equ	01h		; "=" packed in string buffet
_$P_Neg		   equ	02h		; Negative value
_$P_Time12	   equ	04h		; set when PM is specified
_$P_Key_Cmp	   equ	08h		; set when keyword compare
_$P_SW_Cmp	   equ	10h		; set when switch compare
_$P_Extra	   equ	20h		; set when extra delimiter found
_$P_SW		   equ	40h		; set when switch found (tm08)
_$P_Signed	   equ	80h		; signed numeric specified

_$P_NeedToBeRead    equ	0FFFFh		;

; delimiter parsing
_$P_colon_period    equ	01		; check for colon & period
_$P_period_only	   equ	02		; check only for period

_$P_error_filespec  equ	01		; mask to set flag

;***********************************************************************

; ----------------------------------------------------------------------------
; fdparse.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 07/11/2018)

;/*  */
;/******************************************************************************/
;/*Routine name:  PARSE_COMMAND_LINE                                           */
;/******************************************************************************/
;/*                                                                            */
;/*Description:   Sets up flags, preloads messages, and parses the command     */
;/*               line for switchs.                                            */
;/*                                                                            */
;/*Called Procedures:                                                          */
;/*                                                                            */
;/*Change History: Created        5/30/87         DRM                          */
;/*                                                                            */
;/*Input: None                                                                 */
;/*                                                                            */
;/*Output: None                                                                */
;/*                                                                            */
;/******************************************************************************/

;char parse_command_line(argc,argv)

;char *argv[];  ; [bp+6]                 ;/* array of pointer arguments */
;int  argc;	; [bp+4]

parse_command_line:
	
	;char	cmd_line[128];  ; [bp-86h]
        ;char	finished;	; [bp-6]
        ;int	i;		; [bp-4]
        ;char	parse_good;	; [bp-2]
        ;char	far *cmdline;	; [bp-8Ah]

		;%define cmd_line   bp-134
		;%define finished   bp-6
		;%define i	    bp-4
		;%define parse_good bp-2
		;%define cmdlineptr bp-138

		; 11/11/2018
		%define cmd_line   bp-128

		;push	bp
		mov	bp,sp
		
		;sub	sp,138 ; 11/11/2018

		sub	sp,128 ; 11/11/2018		
		
		;push	si

		call	parse_init
		;mov	byte [parse_good],1 ; TRUE ; 11/11/2018

		; Get PSP address
		;mov	ah,62h
		;int	21h
			; Return:
			; BX = segment address of current process
		;mov	word [cmdlineptr],81h
		;;mov	[cmdlineptr+2],bx
		;mov	[cmdlineptr+2],ds
		mov	si,81h	; command tail offset

		;mov	word [i],0
		lea	di,[cmd_line]
		jmp	short pcmdl_2	
pcmdl_1:
		;mov	al,[es:bx]
		;mov	si,[i]
		;mov	byte [si+cmd_line],al
		;inc	word [cmdlineptr]
		;inc	byte [i]		
		stosb
pcmdl_2:
		;les	bx,[cmdlineptr]
		lodsb
		;cmp	byte [es:bx],0Dh
		cmp	al,0Dh
		jne	short pcmdl_1
		;mov	si,[i]
		;mov	byte [si+cmd_line],0Dh
		xor	ah,ah	
		;;inc	word [i]
		;inc	byte [i]
		;mov	si,[i]
		;mov	byte [si+cmd_line],0
		stosw
		
		;lea	ax,[si+1] ; ?
		;mov	[i],ax

		;sub	di,cmd_line+1

		lea	si,[cmd_line]
		sub	cx,cx
		;sub	dx,dx
		mov	di,p_p
		;mov	[Parse_Ptr],si
		;mov	word [finished],0
		;mov	[finished],cx ; 0 ; 11/11/2018
pcmdl_3:
		mov	[Parse_Ptr],si
		call	parse
			; AX = Error Code (0 = No error) ; 14/11/2018
		;and	ax,ax
		;jnz	short pcmdl_5
		jc	short pcmdl_5

		cmp	dx,p_buff
		jne	short pcmdl_4
		call	check_disk_validity
		;jmp	short pcmdl_7
		jmp	short pcmdl_3 ; 11/11/2018
pcmdl_4:
		cmp	dx,sp_buff
		;jne	short pcmdl_7
		jne	short pcmdl_3 ; 11/11/2018
		call	process_switch
		;jmp	short pcmdl_7
		jmp	short pcmdl_3 ; 11/11/2018
pcmdl_5:
		cmp	ax,0FFFFh ; -1
		;je	short pcmdl_6	; Empty command tail (CR after file name). 
		je	short pcmdl_8 ; 11/11/2018		

		; 14/11/2018
		;jmp	short _pcmdl_10

		;mov	al,2
		;push	ax
		;mov	ax,2
		;push	ax
		;push	word [regs_x_ax]  ; push word [_$P_RC]

		;Parse_msg(regs.x.ax,STDERR,Parse_err_class); 
		mov	dx,2
		push	dx	 ;Message_Type	; PARSE_ERR_CLASS = 2
		push	dx	 ;Handle	; STDERR = 2
		push	ax 	 ;Msg_Num       ; Error Number = [_$P_RC]
		call	Parse_msg
		add	sp,6

;_pcmdl_10:
		; TEMPORARY
		; Erdogan Tan - 10/11/2018
		;call	print_parse_error_msg ; (*)

		;mov	byte [parse_good],0 ; FALSE ; 11/11/2018

		;sub	al,al
		; AL = 0 (*)
		;jmp	short pcmdl_9 ; 11/11/2018

		;sub	ah,ah
		stc
		jmp	short pcmdl_9 ; 11/11/2018
		
pcmdl_6:
		;;mov	byte [finished],1
		;jmp	short pcmdl_8
pcmdl_7:
		;cmp	byte [finished],0
		;je	short pcmdl_3
pcmdl_8:
		;mov	al,[parse_good] ; 11/11/2018

		;xor	ax,ax
		xor	al,al ; clc
		inc	al ; 1	; 11/11/2018
pcmdl_9:
		;cmp	al,1	; 11/11/2018

		;pop	si
		
		mov	sp,bp
		;pop	bp
		
		retn

;/*  */
;/******************************************************************************/
;/*Routine name:  INIT_PARSE                                                   */
;/******************************************************************************/
;/*                                                                            */
;/*Description:   Sets up ALL VALUES AND STRUCTS FOR PARSER.                   */
;/*                                                                            */
;/*Called Procedures:                                                          */
;/*                                                                            */
;/*Change History: Created        6/15/87         DRM                          */
;/*                                                                            */
;/*Input: None                                                                 */
;/*                                                                            */
;/*Output: None                                                                */
;/*                                                                            */
;/******************************************************************************/

;void parse_init()

parse_init:	; 10/11/2018
		;sub	al,al
		sub	ax,ax
		mov	[primary_flag],al
		mov	[extended_flag],al
		mov	[logical_flag],al
		mov	[disk_flag],al
		mov	[quiet_flag],al
		mov	[status_flag],al
		mov	[mbr_flag],al
		mov	word [p_p_p_parmxs_ptr],p_px ; /* Address of extended parm list */
		mov	byte [p_p_p_extra_delim],';'
		;mov	al,1
		inc	al
		mov	[p_p_p_num_extra],al
		mov	[p_p_p_len_extra_delim],al
		mov	[p_px_p_maxp],al ; /* 1 maximum positionals */	
		mov	word [p_px_p_con1_ptr],p_con ; /* pointer to next control blk */
		mov	byte [p_px_p_maxs],5	; /* number of switches */
		mov	word [p_px_p_swi1_ptr],p_swi1 ; /* pointer to next control blk */
		mov	word [p_px_p_swi2_ptr],p_swi2 ; /* pointer to next control blk */
		mov	word [p_px_p_swi3_ptr],p_swi3
		mov	word [p_px_p_swi4_ptr],p_swi4
		mov	word [p_px_p_swi5_ptr],p_swi5
		;mov	al,[NOVAL]	 ; /* no keywords */
		;sub	al,al ; 0
		dec	al
		mov	[p_px_p_maxk],al
		;mov	word [p_con],8001h	; /* DRIVE NUMBER 1 OR 2 optional */
		mov	word [p_con_p_match_flag],8001h
		mov	word [p_con_p_buff1_ptr],p_buff
		mov	word [p_con_p_val1_ptr],p_val
		sub	al,al ; 0
		mov	[p_px_p_minp],al	; /* 1 required positional */
		mov	[p_con_nid],al
		;mov	word [p_swi1],8000h	; /* Optional (switch) */
		mov	word [p_swi1_sp_match_flag],8000h
		;sub	ax,ax
		mov	[p_con_p_function_flag],ax ; /* DO NOTHING FOR FUNCTION FLAG */
		mov	[p_swi1_sp_function_flag],ax ; /* DO NOTHING FOR FUNCTION FLAG */
		mov	word [p_swi1_sp_buff1_ptr],sp_buff
		mov	word [p_swi1_sp_val1_ptr],sp_val
		mov	byte [p_swi1_sp_nid],3	; /* 3 switches allowed */

		;mov	ax,PRI	; "/PRI"	; /* /a switch */
		;push	ax
		;mov	ax,p_swi1_sp_switch1
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx
		mov	si,PRI
		mov	di,p_swi1_sp_switch1
		;mov	cx,5  ; db '/PRI',0
		;rep	movsb		
		movsw
		movsw
		movsb

		;mov	ax,EXT	; "/EXT"	; /* /a switch */
		;push	ax
		;mov	ax,p_swi1_sp_switch2
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx
		mov	si,EXT
		mov	di,p_swi1_sp_switch2
		;mov	cx,5  ; db '/EXT',0
		;mov	cl,5
		;rep	movsb	
		movsw
		movsw	
		movsb

		;mov	ax,LOG	; "/LOG"	; /* /a switch */
		;push	ax
		;mov	ax,p_swi1_sp_switch3
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx
		mov	si,LOG
		mov	di,p_swi1_sp_switch3
		;mov	cx,5  ; db '/LOG',0
		;mov	cl,5
		;rep	movsb	
		movsw
		movsw
		movsb

		;mov	[p_swi2],1		; /* Optional (switch) */
		mov	word [p_swi2_sp_match_flag],1
		mov	word [p_swi2_sp_function_flag],0
		mov	word [p_swi2_sp_buff1_ptr],sp_buff
		;mov	ax,[NOVAL]
		xor	ax,ax ; 0
		mov	[p_swi2_sp_val1_ptr],ax
		mov	byte [p_swi2_sp_nid],1	; /* 1 switch allowed */

		;mov	ax,QUIET ; "/Q"		; /* /a switch */
		;push	ax
		;mov	ax,p_swi2_sp_switch4
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx
		mov	si,QUIET
		mov	di,p_swi2_sp_switch4
		;mov	cx,3  ; db '/Q',0
		;mov	cl,3
		;rep	movsb
		movsw
		movsb

		sub	ax,ax ; 0
		;mov	word [p_swi3],1
		mov	[p_swi3_sp_match_flag],ax
		mov	[p_swi3_sp_function_flag],ax ; 0
		mov	word [p_swi3_sp_buff1_ptr],sp_buff
		;mov	ax,[NOVAL]
		mov	[p_swi3_sp_val1_ptr],ax ; 0
		mov	byte [p_swi3_sp_nid],1

		;mov	ax,STATUS ; "/STATUS"
		;push	ax
		;mov	ax,p_swi3_sp_switch5
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx
		mov	si,STATUS
		mov	di,p_swi3_sp_switch5
		;mov	cx,8  ; db '/STATUS',0
		;mov	cl,8
		;rep	movsb
		mov	cx,4
		rep	movsw

		sub	ax,ax
		;mov	[p_swi4],ax
		mov	[p_swi4_sp_match_flag],ax
		mov	[p_swi4_sp_function_flag],ax
		mov	word [p_swi4_sp_buff1_ptr],sp_buff
		;mov	ax,[NOVAL]
		mov	[p_swi4_sp_val1_ptr],ax
		mov	byte [p_swi4_sp_nid],1
		
		;mov	ax,OPTIONS ; "/?"
		;push	ax
		;mov	ax,p_swi4_sp_switch6
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx
		mov	si,OPTIONS
		mov	di,p_swi4_sp_switch6
		;mov	cx,3  ; db '/?',0
		;mov	cl,3
		;rep	movsb
		movsw	
		movsb	

		mov	ax,1
		;mov	word [p_swi5],1
		;mov	[p_swi5],ax
		mov	[p_swi5_sp_match_flag],ax
		dec	al ; dec ax ; 0
		mov	[p_swi5_sp_function_flag],ax ; 0
		mov	word [p_swi5_sp_buff1_ptr],sp_buff
		;mov	ax,[NOVAL]
		mov	[p_swi5_sp_val1_ptr],ax
		mov	byte [p_swi5_sp_nid],1

		;mov	ax,MBR	; "/MBR"
		;push	ax
		;mov	ax,p_swi5_sp_switch7
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx
		mov	si,MBR
		mov	di,p_swi5_sp_switch7
		;mov	cx,5  ; db '/MBR',0
		;mov	cl,5
		;rep	movsb	
		movsw
		movsw
		movsb
		
		xor	ax,ax
		mov	word [p_val_p_high_range],8
		mov	word [p_val_p_high_range+2],ax ; 0
		;mov	al,1
		inc	al
		;mov	[p_val],al		; /* Number of values items returned */
		mov	[p_val_p_values],al
		mov	[p_val_p_range],al	; /* Number of ranges */
		mov	[p_val_p_range_one],al	; /* range number one */
		;mov	[sp_val],al		
		mov	[sp_val_p_values],al
		mov	[sp_val_p_range],al
		mov	[sp_val_p_range_one],al
		;mov	ax,1
		cwd
		mov	[p_val_p_low_range],ax	; /* low value for range */
		mov	[p_val_p_low_range+2],dx ; /* high value for range */
		mov	[sp_val_p_low_range],ax	; /* low value for range */
		mov	[sp_val_p_low_range+2],dx ; /* high value for range */
		mov	word [sp_val_p_high_range],8064  ; /* max disk size=7.875GB=8064MB */
		mov	word [sp_val_p_high_range+2],dx ; 0
		retn

; ----------------------------------------------------------------------------
; strcpy - (c library function) Modified by Erdogan Tan for Assembly language
; ----------------------------------------------------------------------------
; 10/11/2018

;strcpy:
		;%define source	     bp+6  ; word	
		;%define destination bp+4  ; word
		;
		;push	bp
		;mov	bp,sp
		;mov	dx,di
		;mov	bx,si
		;mov	si,[source] ; [bp+6]
		;mov	di,si
		;mov	ax,ds
		;mov	es,ax
		;xor	ax,ax
		;mov	cx,0FFFFh ; 65535
		;repne scasb
		;not	cx
		;mov	di,[destination] ; [bp+4]
		;mov	ax,di
		;test	al,1
		;jz	short strcpy_0
		;movsb
		;dec	cx
;strcpy_0:
		;shr	cx,1
		;rep movsw
		;adc	cx,cx
		;rep movsb
		;mov	si,bx
		;mov	di,dx
		;pop	bp
		;retn

; ----------------------------------------------------------------------------
; PARSE - Modified by Erdogan Tan for Assembly language - 07/11/2018	
; ----------------------------------------------------------------------------

; _parse.asm (MSDOS 6.0, 1991)
;-------------------------------------------------------------------
;
;       MODULE:         _parse
;
;       PURPOSE:        Supplies an interface between C programs and
;                       the DOS 3.30 parser
;
;       CALLING FORMAT:
;                       parse(&inregs,&outregs);
;
;       DATE:           5-21-87
;
;-------------------------------------------------------------------

parse:
		call	SysParse
	
		cmp	ax,1 ; Error Code (If > 0)
		cmc	; cf = 1 if AX > 0
		retn

; ----------------------------------------------------------------------------
; parse.asm (MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified for NASM and COM file (by Erdogan Tan, 08/11/2018)

;*****************************************************************************
; SysParse;
;
;  Function : Parser Entry
;
;  Input: DS:SI -> command line
;	  ES:DI -> parameter block
;	  psdata_seg -> psdata.inc
;	  CX = operand ordinal
;
;	  Note:  ES is the segment containing all the control blocks defined
;		 by the caller, except for the DOS COMMAND line parms, which
;		 is in DS.
;
;  Output: CY = 1   error of caller, means invalid parameter block or
;		    invalid value list. But this parser does NOT implement
;		    this feature. Therefore CY always zero.
;
;	   CY = 0   AX = return code
;		    BL = terminated delimiter code
;		    CX = new operand ordinal
;		    SI = set past scaned operand
;		    DX = selected result buffer
;
; Use:	_$P_Skip_Delim, _$P_Chk_EOL, _$P_Chk_Delim, _$P_Chk_DBCS
;	_$P_Chk_Swtch, _$P_Chk_Pos_Control, _$P_Chk_Key_Control
;	_$P_Chk_Sw_Control, _$P_Fill_Result
;
; Vars: _$P_Ordinal(RW), _$P_RC(RW), _$P_SI_Save(RW), _$P_DX(R), _$P_Terminator(R)
;	_$P_SaveSI_Cmpx(W), _$P_Flags(RW), _$P_Found_SYNONYM(R), _$P_Save_EOB(W)
;
;*****************************************************************************

SysParse:
		xor	dx,dx ; 09/11/2018

		;mov	word [_$P_Flags],0	; Clear all internal flags
		mov	[_$P_Flags],dx		

		cld
		mov	[_$P_ordinal],cx	; save operand ordinal
		;mov	word [_$P_RC],0	;_$P_No_Error
		;mov	byte [_$P_RC],0		; Assume no error
		mov	[_$P_RC],dx	
		;mov	word [_$P_Found_SYNONYM],0 ; initalize synonym pointer
		mov	[_$P_Found_SYNONYM],dx
		;mov	word [_$P_DX],0
		mov	[_$P_DX],dx

		call	_$P_Skip_Delim		; Move si to 1st non white space
		jnc	short _$P_Start		; If EOL is not encountered, do parse

		mov	ax,0FFFFh ; _$P_RC_EOL	; set exit code to -1
		push	bx
						; Get the PARMSX address to
		;mov	bx,[es:di] ; [es:di+_$P_PARMSX_Address]
		mov	bx,[di]
						; check ORDINAL to see if the minimum
		;cmp	cl,[es:bx] ; [es:bx+_$P_MinP]
		cmp	cl,[bx]
		jnb	short _$P_Fin		; positional found.
		mov	ax,2 ; _$P_Op_Missing ; If no, set exit code to missing operand
_$P_Fin:
		pop	bx
		jmp	_$P_Single_Exit		; return to the caller

_$P_Start:			;  save ptr to command line for later use by complex,
		mov	[_$P_SaveSI_Cmpx],si 	; quoted string or file spec.
		push	bx
		push	di
		push	bp
		;lea	bx,[_$P_STRING_BUF]  ; set buffer to copy from command string
		mov	bx,_$P_STRING_BUF
						; extra delimiter encountered ?
		test	byte [_$P_Flags2],20h ;_$P_Extra
		jnz	short _$P_Pack_End	; if yes, no need to copy
_$P_Pack_Loop:
		lodsb				; Pick a operand from buffer
		call	_$P_Chk_Switch		; Check switch character
		jc	short _$P_Pack_End_BY_EOL 
					    ; if carry set found delimiter type slash,
					    ; need backup si, else continue
		call	_$P_Chk_EOL		; Check EOL character
		jz	short _$P_Pack_End_BY_EOL ; need backup si

		call	_$P_Chk_Delim		; Check delimiter
		jnz	short _$P_PL01		; If no, process next byte

		test	byte [_$P_Flags2],20h ;_$P_Extra ; If yes and white spec,
		jnz	short _$P_Pack_End_backup_si ; then

		call	_$P_Skip_Delim		; skip subsequent white space,too
		jmp	short _$P_Pack_End	; finish copy by placing NUL at end

_$P_Pack_End_backup_si:
		test	byte [_$P_Flags2],41h ;_$P_SW+_$P_equ
		jz	short _$P_Pack_End
		dec	si
		jmp	short _$P_Pack_End

_$P_PL01:
		mov	[bx],al			; move byte to STRING_BUF
		cmp	al,'='			; if it is equal character,
		jne	short _$P_PL00		; then
		or	byte [_$P_Flags2],1 ;_$P_equ ; remember it in flag
_$P_PL00:
		inc	bx			; ready to see next byte
		call	_$P_Chk_DBCS		; was it 1st byte of DBCS ?
		jnc	short _$P_Pack_Loop	; if no, process to next byte
		lodsb				; if yes, store
		mov	[bx],al			;    2nd byte of DBCS
		inc	bx			; update pointer
		jmp	short _$P_Pack_Loop	; process to next byte

_$P_Pack_End_BY_EOL:
		dec	si			; backup si pointer
_$P_Pack_End:
		mov	[_$P_SI_Save],si	; save next pointer, SI	
		mov	byte [bx],0 ; _$P_NULL	; put NULL at the end
		mov	[_$P_Save_EOB],bx ; keep the address for later use of complex	
		;mov	bx,[es:di] ; [es:di+_$P_PARMSX_Address] ; get PARMSX address
		mov	bx,[di]
		;lea	si,[_$P_STRING_BUF]
		mov	si,_$P_STRING_BUF
		cmp	byte [si],'/' ;_$P_Switch ; the operand begins w/ switch char?
		je	short _$P_SW_Manager	; if yes, process as switch

		cmp	byte [si],'"' ;_$P_DQuote ; is it a string?
		je	short _$P_Positional_Manager ; if so, process as one!
						; the operand includes equal char?
		test	byte [_$P_Flags2],1 ;_$P_equ 
		jnz	short _$P_Key_manager	; if yes, process as keyword	

_$P_Positional_Manager:				; else process as positional
		;mov	al,[es:bx+1] ; es:[bx]._$P_MaxP ; get maxp
		mov	al,[bx+1]
		xor	ah,ah			; ax = maxp
		cmp	[_$P_ordinal],ax	; too many positional?	
		jnb	short _$P_Too_Many_Error ; if yes, set exit code to too many
		mov	ax,[_$P_ordinal]	; see what the current ordinal
		shl	ax,1			; ax = ax*2
		inc	bx			; add '2' to
		inc	bx			;  BX reg
					; now bx points to 1st CONTROL
		add	bx,ax		; now bx points to specified CONTROL address
		;mov	bx,[es:bx]	; now bx points to specified CONTROL itself
		mov	bx,[bx]
		call	_$P_Chk_Pos_Control	; Do process for positional
		jmp	short _$P_Return_to_Caller ; and return to the caller

_$P_Too_Many_Error:
		;mov	word [_$P_RC],1 ;_$P_Too_Many ; set exit code
		mov	byte [_$P_RC],1
		jmp	short _$P_Return_to_Caller ; and return to the caller
	
; ----------------------------------------------------------------------------

_$P_SW_Key_Mgr_sub:
		;mov	al,[es:bx+1] ; [es:bx+_$P_MaxP] ; get maxp
		mov	al,[bx+1]
		xor	ah,ah			; ax = maxp
		inc	ax
		shl	ax,1			; ax = (ax+1)*2
		add	bx,ax			; now bx points to maxs
		retn

; ----------------------------------------------------------------------------

_$P_SW_Manager:
		call	_$P_SW_Key_Mgr_sub  ; repetitive portion as subroutine
		;mov	cl,[es:bx]
		mov	cl,[bx]
		xor	ch,ch			; cx = maxs
		;or	cx,cx
		;jz	short _$P_SW_Not_Found 
		jcxz	_$P_SW_Not_Found	; at least one switch?
		inc	bx		; now bx points to 1st CONTROL address

_$P_SW_Mgr_Loop:
		push	bx
		;mov	bx,[es:bx]	   ; bx points to Switch CONTROL itself
		mov	bx,[bx]
		call	_$P_Chk_SW_Control	; do process for switch
		pop	bx		; if the CONTROL is for the switch, exit
		jnc	short _$P_Return_to_Caller
		inc	bx			;  add 2 to BX reg
		inc	bx		   ; else bx points to the next CONTROL
		loop	_$P_SW_Mgr_Loop		; and loop

_$P_SW_Not_Found:
		;mov	word [_$P_RC],3 ;_$P_Not_In_SW
		mov	byte [_$P_RC],3	    ; here no CONTROL for the switch has
		jmp	short _$P_Return_to_Caller ; not been found, means error.

_$P_Key_manager:
		call	_$P_SW_Key_Mgr_sub  ; repetitive portion as subroutine	
		;mov	al,[es:bx]
		mov	al,[bx]
		xor	ah,ah			; ax = maxs
		shl	ax,1
		inc	ax			; ax = ax*2+1
		add	bx,ax			; now bx points to maxk
		;mov	cl,[es:bx]
		mov	cl,[bx]
		xor	ch,ch			; cx = maxk
		jcxz	_$P_Key_Not_Found	; at least one keyword?
		inc	bx			; now bx points to 1st CONTROL

_$P_Key_Mgr_Loop:
		push	bx
		;mov	bx,[es:bx]	   ; bx points to keyword CONTROL itself
		mov	bx,[bx]
		call	_$P_Chk_Key_Control	; do process for keyword
		pop	bx		; if the CONTROL is for the keyword, exit
		jnc	short _$P_Return_to_Caller
		inc	bx			; add '2' to BX reg
		inc	bx		; else bx points to the next CONTROL
		loop	_$P_Key_Mgr_Loop	; and loop

_$P_Key_Not_Found:
		;mov	word [_$P_RC],4 ;_$P_Not_In_Key
					   ; here no CONTROL for the keyword has
		mov	byte [_$P_RC],4	 	; not been found, means error.

_$P_Return_to_Caller:
		pop	bp
		pop	di
		pop	bx
		mov	cx,[_$P_ordinal]	; return next ordinal
		mov	ax,[_$P_RC]		; return exit code
		mov	si,[_$P_SI_Save]	; return next operand pointer	
		mov	dx,[_$P_DX]		; return result buffer address
		mov	bl,[_$P_Terminator]	; return delimiter code found

_$P_Single_Exit:
		clc
		retn

;***********************************************************************
;
; _$P_Skip_Delim;
;
; Function: Skip delimiters specified in the PARMS list, white space
;	    and comma.
;
; Input:    DS:SI -> Command String
;	    ES:DI -> Parameter List
;
; Output:   CY = 1 if the end of line encounterd
;	    CY = 0 then SI move to 1st non-delimiter character
;	    AL = Last examineed character
;
; Use:	    _$P_Chk_EOL, _$P_Chk_Delim,
;
; Vars:     _$P_Flags(R)
;
;***********************************************************************

_$P_Skip_Delim:
_$P_Skip_Delim_Loop:
		lodsb
		call	_$P_Chk_EOL	; is it EOL character?
		jz	short _$P_Skip_Delim_CY ; if yes, exit w/ CY on

		call	_$P_Chk_Delim	; is it one of delimiters?
		jnz	short _$P_Skip_Delim_NCY ; if no, exit w/ CY off
					; extra delim or comma found? 
		test	byte [_$P_Flags2],20h ;_$P_Extra
		jz	short _$P_Skip_Delim_Loop ; if no, loop
					
		test	byte [_$P_Flags2],41h ;_$P_SW+_$P_equ ; /x or xxx=zzz
		jz	short _$P_Exit_At_Extra ; no switch, no keyword

		dec	si		; backup si for next call
		jmp	short _$P_Exit_At_Extra ; else exit w/ CY off

_$P_Skip_Delim_CY:
		stc			; indicate EOL
		jmp	short _$P_Skip_Delim_Exit

_$P_Skip_Delim_NCY:
		clc			; indicate non delim

_$P_Skip_Delim_Exit:			; in this case, need
		dec	si		; backup index pointer
		retn

_$P_Exit_At_Extra:
		clc			; indicate extra delim
		retn

;***********************************************************************
;
; _$P_Chk_EOL;
;
; Function: Check if AL is one of End of Line characters.
;
; Input:    AL = character code
;	    ES:DI -> Parameter List
;
; Output:   ZF = 1 if one of End of Line characters
;
;***********************************************************************

_$P_Chk_EOL:
		push	bx
		push	cx

		cmp	al,0Dh ;_$P_CR	; Carriage return?
		je	short _$P_Chk_EOL_Exit
		
		cmp	al,0 ;_$P_NULL	; zero?
		je	short _$P_Chk_EOL_Exit
		
		cmp	al,0Ah ;_$P_LF	; Line feed?
		je	short _$P_Chk_EOL_Exit
		
		;cmp	byte [es:di+_$Pp_num_extra],_$P_I_Have_EOL
		;cmp	byte [es:di+2],2 ; EOL character specified?
		cmp	byte [di+2],2 ; 09/11/2018
		jb	short _$P_Chk_EOL_Exit
		
		xor	bx,bx
		;mov	bl,[es:di+_$P_p_len_extra_delim]
		;mov	bl,[es:di+3]	; get length of delimiter list
		mov	bl,[di+3]
		add	bx,4 ;_$P_Len_PARMS ; skip it
					  ; No extra EOL character?
		;cmp	byte [es:bx+di],0 ;_$P_I_Use_Default
		cmp	byte [bx+di],0
		je	short _$P_Chk_EOL_NZ
		xor	cx,cx
		;mov	cl,[es:bx+di]	; Get number of extra character
		mov	cl,[bx+di]
_$P_Chk_EOL_Loop:
		inc	bx
		;cmp	al,[es:bx+di]	; Check extra EOL character
		cmp	al,[bx+di]
		je	short _$P_Chk_EOL_Exit
		loop	_$P_Chk_EOL_Loop
_$P_Chk_EOL_NZ:
		cmp	al,0Dh ; _$P_CR	; reset ZF
_$P_Chk_EOL_Exit:
		pop	cx
		pop	bx
		retn

;***********************************************************************
;
; _$P_Chk_Delim;
;
; Function: Check if AL is one of delimiter characters.
;	    if AL+[si] is DBCS blank, it is replaced with two SBCS
;	    blanks.
;
; Input:    AL = character code
;	    DS:SI -> Next Character
;	    ES:DI -> Parameter List
;
; Output:   ZF = 1 if one of delimiter characters
;	    SI points to the next character
; Vars:  _$P_Terminator(W), _$P_Flags(W)
;
;***********************************************************************

_$P_Chk_Delim:
		push	bx
		push	cx
					; Assume terminated by space
		mov	byte [_$P_Terminator],' ' ;_$P_Space  
		and	byte [_$P_Flags2],~20h ; not 20h ; 0FFh-_$P_Extra 
		cmp	al,' '	;_$P_Space	; Space?
		je	short _$P_Chk_Delim_Exit
		cmp	al,9	;_$P_TAB		; TAB?
		je	short _$P_Chk_Delim_Exit
		cmp	al,','	;_$P_Comma	; Comma?
		je	short _$P_Chk_Delim_Exit0
_$P_Chk_Delim00:
		cmp	al,' '	;_$P_DBSP1	; 1st byte of DBCS Space?
		jne	short _$P_Chk_Delim01
		cmp	byte [si],' ' ;_$P_DBSP2	; 2nd byte of DBCS Space?
		jne	short _$P_Chk_Delim01
		mov	al,' '
		inc	si			; make si point to next character
		cmp	al,al			; Set ZF
		jmp	short _$P_Chk_Delim_Exit

_$P_Chk_Delim01:
		;cmp	byte [es:di+_$Pp_num_extra],_$P_I_Have_Delim
		;cmp	byte [es:di+2],1	;delimiter character specified?
		cmp	byte [di+2],1 ; 09/11/2018
		jb	short _$P_Chk_Delim_Exit
		xor	cx,cx
		;mov	cl,[es:di+_$P_p_len_extra_delim]
		;mov	cl,[es:di+3]		; get length of delimiter list
		mov	cl,[di+3]
		jcxz	_$P_Chk_Delim_NZ
		mov	bx,3 ;_$P_Len_PARMS-1	; set bx to 1st extra delimiter

_$P_Chk_Delim_Loop:
		inc	bx
		;cmp	al,[es:bx+di]		; Check extra Delim character
		cmp	al,[bx+di]
		je	short _$P_Chk_Delim_Exit0
		loop	_$P_Chk_Delim_Loop	; examine all extra delimiter

_$P_Chk_Delim_NZ:
		cmp	al,' '	;_$P_Space	; reset ZF

_$P_Chk_Delim_Exit:
		pop	cx
		pop	bx
		retn

_$P_Chk_Delim_Exit0:
		mov	[_$P_Terminator],al	; keep terminated delimiter
		test	byte [_$P_Flags2],1 ;_$P_Equ ; if terminating a key=
		jnz	short _$P_No_Set_Extra	; then do not set the EXTRA bit
					; flag terminated extra delimiter or comma
		or	byte [_$P_Flags2],20h ;_$P_Extra
_$P_No_Set_Extra:
		cmp	al,al			; set ZF
		jmp	short _$P_Chk_Delim_Exit

;***********************************************************************
;
; _$P_Chk_Switch;
;
; Function: Check if AL is the switch character not in first position of
;	    _$P_STRING_BUF
;
; Input:    AL = character code
;	    BX = current pointer within _$P_String_Buf
;	    SI = next char on command line (following the one in AL)
;
; Output:   CF = 1 (set) if AL is switch character, and not in first
;		 position, and has no chance of being part of a date string,
;		 i.e. should be treated as a delimiter.

;	    CF = 0 (reset, cleared) if AL is not a switch char, is in the first
;		 position, or is a slash but may be part of a date string, i.e.
;		 should not be treated as a delimiter.
;
; Vars:  _$P_Terminator(W)
;
; Use:	 _$P_0099
;
;***********************************************************************

_$P_Chk_Switch:
		;lea	bp,[_$P_STRING_BUF]
			; BP = OFFSET of _$P_String_Buf even in group addressing
		mov	bp,_$P_STRING_BUF
		cmp	bx,bp			; if not first char
		je	short _$P_STRUC_L2	; then
		cmp	al,'/'	;_$P_Switch	; otherwise see if a slash
		jne	short _$P_STRUC_L5	; not a switch char
						; not in first position and is slash, 
		stc				; now see if might be in date string
		push	ax			; save input char
		mov	al,[bx-1]		; AL = char before the current char
		call	_$P_0099		; return carry set if not numeric
		jc	short _$P_STRUC_L7
		mov	al,[si]			; AL = char after the current char
		call	_$P_0099		; return carry set if not numeric
_$P_STRUC_L7:
		pop	ax			; restore AL to input char
		retn				; DateSw
_$P_STRUC_L5:
		clc				; not a slash
		retn
_$P_STRUC_L2:
		cmp	al,'/' ;_$P_Switch
		jne	short _$P_STRUC_L12
					; could be valid switch, first char and is slash	
		or	byte [_$P_Flags2],40h ;_$P_Flags2,_$P_SW
_$P_STRUC_L12:
		clc				; CF=0 indicating first char
_$P_STRUC_L1:					;is first char in the buffer, ZF=0
		retn

;**************************************************************************
;
; _$P_Chk_DBCS:
;
;  Function: Check if a specified byte is in ranges of the DBCS lead bytes
;
;  Input:
;	  AL	= Code to be examineed
;
;  Output:
;	  If CF is on then a lead byte of DBCS
;
; Use: INT 21h w/AH=63
;
; Vars:  _$P_DBCSEV_Seg(RW), _$P_DBCSEV_Off(RW)
;
;***************************************************************************

_$P_Chk_DBCS:
		push	ds
		push	si
		push	bx

		cmp	word [_$P_DBCSEV_SEG],0	; ALREADY SET ?
		jne	short _$P_DBCS00

		push	ax
		push	ds
		push	cx
		push	dx
		push	di
		push	bp
		push	es
		xor	si,si
		mov	ds,si
		mov	ax,6300h ; _$P_DOS_GetEV	; GET DBCS EV CALL
		int	21h	; GET DOUBLE BYTE CHARACTER SET LEAD TABLE
		mov	bx,ds
		or	bx,bx
		pop	es
		pop	bp
		pop	di
		pop	dx
		pop	cx
		pop	ds
		pop	ax
		jz	short _$P_NON_DBCS
_$P_DBCS02:
		mov	[_$P_DBCSEV_OFF],si	; save EV offset
		mov	[_$P_DBCSEV_SEG],bx	; save EV segment
_$P_DBCS00:
		;lds	si, dword ptr cs:_$P_DBCSEV_OFF
		lds	si,[_$P_DBCSEV_OFF]	; load EV offset and segment
_$P_DBCS_LOOP:
		cmp	word [si],0		; zero vector?
		je	short _$P_NON_DBCS	; then exit
		cmp	al,[si]			
		jb	short _$P_DBCS01	; Check if AL is in
		cmp	al,[si+1]		;   range of
		ja	short _$P_DBCS01	;      the vector
		stc				; if yes, indicate DBCS and exit
		jmp	short _$P_DBCS_EXIT
_$P_DBCS01:
		inc	si			; add '2' to
		inc	si			;  SI reg
		jmp	short _$P_DBCS_LOOP	; loop until zero vector found
_$P_NON_DBCS:
		clc				; indicate SBCS
_$P_DBCS_EXIT:
		pop	bx
		pop	si
		pop	ds
		retn

;***********************************************************************
;
; _$P_Chk_Pos_Control
;
; Function: Parse CONTROL block for a positional
;
; Input:     ES:BX -> CONTROL block
;	     psdata_seg:SI -> _$P_STRING_BUF
;
; Output:    None
;
; Use:	 _$P_Fill_Result, _$P_Check_Match_Flags
;
; Vars: _$P_Ordinal(W), _$P_RC(W)
;
;***********************************************************************

_$P_Chk_Pos_Control:
		push	ax
		;mov	ax,[es:bx] ; [es:bx+_$P_Match_Flag]
		mov	ax,[bx] ; 09/11/2018
		test	ax,2 ;_$P_Repeat		; repeat allowed?
		jnz	short _$P_CPC00		; then do not increment ORDINAL
		;inc	word [_$P_ordinal]
		inc	byte [_$P_ordinal]	; update the ordinal
_$P_CPC00:
		cmp	byte [si],0 ;_$P_NULL	; no data?
		jne	short _$P_CPC01
		test	ax,1 ;_$P_Optional	; yes, then is it optional?
		jnz	short _$P_CPC02
		;mov	word [_$P_RC],2		; no, then error
		mov	byte [_$P_RC],2 ;_$P_Op_Missing
		jmp	short _$P_CPC_Exit
_$P_CPC02:
		push	ax
		;mov	al,_$P_String		;if it is optional return NULL
		;mov	ah,_$P_No_Tag
		mov	ax,0FF03h
		call	_$P_Fill_Result
		pop	ax
		jmp	short _$P_CPC_Exit
_$P_CPC01:
		call	_$P_Check_Match_Flags
_$P_CPC_Exit:
		pop	ax
		retn

;***********************************************************************
;
; _$P_Chk_Key_Control
;
; Function: Parse CONTROL block for a keyword
;
; Input:     ES:BX -> CONTROL block
;	     psdata_seg:SI -> _$P_STRING_BUF
;
; Output:    CY = 1 : not match
;
; Use:	 _$P_Fill_Result, _$P_Search_KEYorSW, _$P_Check_Match_Flags
;
; Vars: _$P_RC(W), _$P_SaveSI_Cmpx(W), _$P_KEYorSW_Ptr(R), _$P_Flags(W)
;
;***********************************************************************

_$P_Chk_Key_Control:
;IF	KeySW					; (Check if keyword is supported)
;		or	psdata_seg:_$P_Flags2,_$P_Key_Cmp 
;					; Indicate keyword for later string comparison
;		call	_$P_Search_KEYorSW 	; Search the keyword in the CONTROL block
;		jc	_$P_Chk_Key_Err0   	;  not found, then try next CONTROL
;
;		and	psdata_seg:_$P_Flags2,0ffh-_$P_Key_Cmp ; reset the indicator previously set
;
;		push	ax			      ; keyword=
;		mov	ax,psdata_seg:_$P_KEYorSW_Ptr ; ^       ^
;		sub	ax,si			; SI	KEYorSW
;		add	psdata_seg:_$P_SaveSI_Cmpx,ax ; update for complex, quoted or file spec.
;		pop	ax
;
;		mov	si,psdata_seg:_$P_KEYorSW_Ptr ; set si just after equal char
;		cmp	byte ptr psdata_seg:[si],_$P_NULL ; any data after equal?
;		je	_$P_Chk_Key_Err1 	; if no, syntax error
;
;		call	_$P_Check_Match_Flags	; else, process match flags
;		clc				
;		jmp	short _$P_Chk_Key_Exit
;
;_$P_Chk_Key_Err0:
;		stc				; not found in keyword synonym list
;		jmp	short _$P_Chk_Key_Exit
;
;_$P_Chk_Key_Err1:
;		mov	psdata_seg:_$P_RC,_$P_Syntax ; no parameter is not specified after "="
;_$P_Chk_Key_ErrExit:
;		push	ax
;		mov	al,_$P_String		; set
;		mov	ah,_$P_No_Tag		;    result
;		call	_$P_Fill_Result		; 	 buffer
;		pop	ax			
;		clc
;$_P_Chk_Key_Exit:
;		retn
;ELSE						; (of IF KeySW)
		stc				;   this logic works when the KeySW
		retn				;   is reset.
;ENDIF						; (of KeySW)

;***********************************************************************
;
; _$P_Search_KEYorSW:
;
; Function: Seach specified keyword or switch from CONTROL
;
; Input:     ES:BX -> CONTROL block
;	     psdata_seg:SI -> _$P_STRING_BUF
;
; Output:    CY = 1 : not match
;
; Use:	 _$P_String_Comp, _$P_MoveBP_NUL, _$P_Found_SYNONYM
;
;***********************************************************************

_$P_Search_KEYorSW:
		push	bp
		push	cx
		;mov	cl,[es:bx+8] ; [es:bx+_$P_nid] ; Get synonym count
		mov	cl,[bx+8] ; 09/11/2018
		xor	ch,ch
		jcxz	_$P_KEYorSW_Not_Found
		;lea	bp,es:[bx]._$P_KEYorSW	; BP points to the 1st synonym
		;lea	bp,[bx+_$P_KEYorSW]
		lea	bp,[bx+9]
_$P_KEYorSW_Loop:
		call	_$P_String_Comp
		jnb	short _$P_KEYorSW_Found
		call	_$P_MoveBP_NUL
		loop	_$P_KEYorSW_Loop
_$P_KEYorSW_Not_Found:
		stc
		jmp	short _$P_KEYorSW_Exit
_$P_KEYorSW_Found:
		mov	[_$P_Found_SYNONYM],bp
		clc
_$P_KEYorSW_Exit:
		pop	cx
		pop	bp
		retn

;***********************************************************************
; _$P_MoveBP_NUL
;***********************************************************************

_$P_MoveBP_NUL:	; 09/11/2018
		;cmp	byte [es:bp],0 ;_$P_NULL ; Increment BP that points
		cmp	byte [bp],0  ; (SS = CS = DS = ES)		
		jz	short _$P_MBP_Exit	; to the synomym list
		inc	bp			; until
		jmp	short _$P_MoveBP_NUL	; NULL encountered.
_$P_MBP_Exit:
		inc	bp			; bp points to next to NULL
		retn

;***********************************************************************
;
; _$P_Chk_SW_Control
;
; Function: Parse CONTROL block for a switch
;
; Input:     ES:BX -> CONTROL block
;	     psdata_seg:SI -> _$P_STRING_BUF
;
; Output:    CY = 1 : not match
;
; Use:	 _$P_Fill_Result, _$P_Search_KEYorSW, _$P_Check_Match_Flags
;
; Vars:  _$P_SaveSI_Cmpx(W), _$P_KEYorSW_Ptr(R), _$P_Flags(W)
;
;**********************************************************************

_$P_Chk_SW_Control:
;IF	SwSW					; (Check if switch is supported)
		or	byte [_$P_Flags2],10h	;_$P_Sw_Cmp
					; Indicate switch for later string comparison
		call	_$P_Search_KEYorSW ; Search the switch in the CONTROL block
		jc	short _$P_Chk_SW_Err0 ; not found, then try next CONTROL
					; reset the indicator previously set
		and	byte [_$P_Flags2],~10h ; not 10h  ; 0EFh ; 0FFh-_$P_Sw_Cmp

		push	ax			; /switch:
		mov	ax,[_$P_KEYorSW_Ptr]	; ^       ^
		sub	ax,si			; SI  KEYorSW
		add	[_$P_SaveSI_Cmpx],ax	; update for complex list
		pop	ax
		mov	si,[_$P_KEYorSW_Ptr]	; set si at the end or colon
		cmp	byte [si],0 ;_$P_NULL	; any data after colon
		jne	short _$P_CSW00		; if yes, process match flags
						; if no, the switch terminated by colon?
		cmp	byte [si-1],':' ;_$P_Colon 
		jne	short _$P_Chk_if_data_required ; if yes,
		;mov	word [_$P_RC],9 ; _$P_Syntax ; return syntax error
		mov	byte [_$P_RC],9		
		jmp	short _$P_Chk_SW_Exit

_$P_Chk_if_data_required:			; no data, no colon
						; should have data? 
		;cmp	word [es:bx++_$P_Match_Flag],0 ; zero match flag means 
		cmp	word [bx],0		      ; switch followed by nothing is OK
		je	short _$P_Chk_SW_Exit	; match flags not zero 
						;    so should have something 
						;       if optional bit is not on
		;test	es:[bx]._$P_Match_Flag,_$P_Optional
		;test	word [es:bx],1 ;_$P_Optional ; see if no value is valid
		test	word [bx],1
		jnz	short _$P_Chk_SW_Exit

		;mov	word [_$P_RC],2	;_$P_Op_Missing ; return required operand missing
		mov	byte [_$P_RC],2
		jmp	short _$P_Chk_SW_Exit
_$P_CSW00:
		call	_$P_Check_Match_Flags	; process match flag
		clc				; indicate match
		jmp	short _$P_Chk_SW_Single_Exit
_$P_Chk_SW_Err0:
		stc				; not found in switch synonym list
		retn
_$P_Chk_SW_Exit:
		push	ax
		;mov	al,_$P_String
		;mov	ah,_$P_No_Tag
		mov	ax,0FF03h
		call	_$P_Fill_Result		; set result buffer
		pop	ax
		clc
_$P_Chk_SW_Single_Exit:
		retn
;ELSE						;(of IF KeySW)
;		stc				;  this logic works when the KeySW
;		retn				;  is reset.
;ENDIF						;(of KeySW)

;***********************************************************************
;
; _$P_Fill_Result
;
; Function: Fill the result buffer
;
; Input:    AH = Item tag
;	    AL = type
;		  AL = 1: CX,DX has 32bit number (CX = high)
;		  AL = 2: DX has index(offset) into value list
;		  AL = 6: DL has driver # (1-A, 2-B, ... , 26 - Z)
;		  AL = 7: DX has year, CL has month and CH has date
;		  AL = 8: DL has hours, DH has minutes, CL has seconds,
;			  amd CH has hundredths
;		  AL = else: psdata_seg:SI points to returned string buffer
;	    ES:BX -> CONTROL block
;
; Output:   None
;
; Use:	_$P_Do_CAPS_String, _$P_Remove_Colon, _$P_Found_SYNONYM
;
; Vars: _$P_DX(W)
;
;***********************************************************************

_$P_Fill_Result:		; 09/11/2018
		push	di
		;mov	di,[es:bx+_$P_Result_Buf] ; di points to result buffer
		;mov	di,[es:bx+4]
		mov	di,[bx+4]
		mov	[_$P_DX],di		; set returned result address
		;mov	[es:di],al ;[es:di+_$P_Type]	; store type
		;mov	[es:di+1],ah ;[es:di+_$P_Item_Tag] ; store item tag
		;mov	[es:di],ax
		mov	[di],ax
		push	ax
		mov	ax,[_$P_Found_SYNONYM]	; if yes,
		;mov	[es:di+_$P_SYNONYM_Ptr],ax
		;mov	[es:di+2],ax		; then set it to the result
		mov	[di+2],ax
		pop	ax
_$P_RLT04:
		cmp	al,1 ;_$P_Number		; if number
		jne	short _$P_RLT00
_$P_RLT02:
		;mov	word ptr es:[di]._$P_Picked_Val,dx
		;mov	[es:di+4],dx		; then store 32bit number
		mov	[di+4],dx
		;mov	word ptr es:[di+2]._$P_Picked_Val,cx
		;mov	[es:di+6],cx
		mov	[di+6],cx
		jmp	short _$P_RLT_Exit
_$P_RLT00:
		cmp	al,2 ;_$P_List_Idx	; if list index
		jne	short _$P_RLT01
		;mov	[es:di+4],dx		; then store list index
		mov	[di+4],dx
		jmp	short _$P_RLT_Exit
_$P_RLT01:
		cmp	al,7 ;_$P_Date_F		; Date format?
		je	short _$P_RLT02
		cmp	al,8 ;_$P_Time_F		; Time format?
		je	short _$P_RLT02
		cmp	al,6 ;_$P_Drive		; drive format?
		jne	short _$P_RLT03
		;mov	byte ptr es:[di]._$P_Picked_Val,dl
		;mov	[es:di+4],dl		; store drive number
		mov	[di+4],dl
		jmp	short _$P_RLT_Exit
_$P_RLT03:
		cmp	al,4 ;_$P_Complex	; complex format?
		jne	short _$P_RLT05
		mov	ax,[_$P_SaveSI_Cmpx]	; then get pointer in command buffer
		inc	ax			; skip left Parentheses
		;mov	[es:di+_$P_Picked_Val],ax
		mov	[di+4],ax		; store offset
		;mov	[es:di+_$P_Picked_Val+2],ds
		mov	[di+6],ds		; store segment
		jmp	short _$P_RLT_Exit
_$P_RLT05:
		;mov	[es:di+_$P_Picked_Val],si
		mov	[di+4],si		; store offset of STRING_BUF
		;mov	word [es:di+_$P_Picked_Val+2],Psdata_Seg
		mov	[di+6],cs		; store segment of STRING_BUF
		push	ax
		;test	byte [es:bx+_$P_Function_Flag],_$P_CAP_File
		test	byte [bx+2],1		; need CAPS by file table?
		jz	short _$P_RLT_CAP00
		mov	al,4 ;_$P_DOSTBL_File	; use file upper case table
		jmp	short _$P_RLT_CAP02
_$P_RLT_CAP00:
		;test	byte [es:bx+_$P_Function_Flag],_$P_CAP_Char
		test	byte [bx+2],2		; need CAPS by char table?
		jz	short _$P_RLT_CAP01
		mov	al,2 ;_$P_DOSTBL_Char	; use character upper case table
_$P_RLT_CAP02:
		call	_$P_Do_CAPS_String	; process CAPS along the table
_$P_RLT_CAP01:
		pop	ax
		;test	byte [es:bx+_$P_Function_Flag],_$P_Rm_Colon
		test	byte [bx+2],10h		; removing colon at end?
		jz	short _$P_RLT_Exit
		call	_$P_Remove_Colon	; then process it.	
_$P_RLT_Exit:
		pop	di
		retn

;***********************************************************************
;
; _$P_Check_Match_Flags
;
; Function:  Check the match_flags and make the exit code and set the
;	     result buffer
;
;	    Check for types in this order:
;		Complex
;		Date
;		Time
;		Drive
;		Filespec
;		Quoted String
;		Simple String
;
; Input:     psdata_seg:SI -> _$P_STRING_BUF
;	     ES:BX -> CONTROL block
;
; Output:    None
;
; Use:	     _$P_Value, P$_SValue, _$P_Simple_String, _$P_Date_Format
;	     _$P_Time_Format, _$P_Complex_Format, _$P_File_Foemat
;	     _$P_Drive_Format
;
;***********************************************************************

_$P_Check_Match_Flags:
		mov	byte [_$P_err_flag],0 ;_$P_NULL	
						; clear filespec error flag.
		push	ax
		;mov	ax,[es:bx] ; [es:bx+_$P_Match_Flag] 
		mov	ax,[bx]			; load match flag(16bit) to ax
		or	ax,ax			; test ax for zero
		jnz	short _$P_Mat
		push	ax
		push	bx
		push	dx
		push	di
		;mov	word [_$P_RC],9
		mov	byte [_$P_RC],9 ;_$P_Syntax
		;mov	ah,_$P_No_Tag ; 0FFh
		;mov	al,_$P_String ; 03h
		mov	ax,0FF03h
		call	_$P_Fill_Result
		pop	di
		pop	dx
		pop	bx
		pop	ax
		;jmp	short _$P_Bridge
		jmp	short _$P_Match_Exit
_$P_Mat:
		test	ax,1000h ;_$P_Date_S	; Date string	
		jz	short _$P_Match01
		;mov	word [_$P_RC],0
		mov	byte [_$P_RC],0 ;_$P_No_Error ; assume no error
		call	_$P_Date_Format
		;cmp	word [_$P_RC],9
		cmp	byte [_$P_RC],9 ;_$P_Syntax ; if error, examine the next type
		;jne	short _$P_Bridge
		jne	short _$P_Match_Exit
_$P_Match01:
;		jmp	short _$P_Match03		
;_$P_Bridge:
;		jmp	short _$P_Match_Exit
_$P_Match03:
		test	ax,8000h ;_$P_Num_Val	; Numeric value
		jz	short _$P_Match04
		;mov	word [_$P_RC],0
		mov	byte [_$P_RC],0 ;_$P_No_Error ; assume no error
		call	_$P_Value		; do process
		;cmp	word [_$P_RC],9
		cmp	byte [_$P_RC],9		; if error, examine the next type
		jne	short _$P_Match_Exit
_$P_Match04:
		test	ax,4000h ;_$P_SNum_Val	; Signed numeric value
		jz	short _$P_Match05
		;mov	word [_$P_RC],0
		mov	byte [_$P_RC],0 ;_$P_No_Error ; assume no error
		call	_$P_SValue		; do process
		;cmp	word [_$P_RC],9
		cmp	byte [_$P_RC],9 ;_$P_Syntax ; if error, examine the next type
		jne	short _$P_Match_Exit
_$P_Match05:
		test	ax,2000h ;_$P_Simple_S	; Signed numeric value
		jz	short _$P_Match_Exit
		;mov	word [_$P_RC],0		; assume no error
		mov	byte [_$P_RC],0 ;_$P_No_Error
		call	_$P_Simple_String	; do process
_$P_Match_Exit:
		cmp	byte [_$P_err_flag],1 ;_$P_error_filespec ; bad filespec?
		jne	short _$P_Match2_Exit	; no, continue
		;cmp	word [_$P_RC],0
		cmp	byte [_$P_RC],0 ;_$P_No_Error ; check for other errors?
		jne	short _$P_Match2_Exit	; no, continue
		;mov	word [_$P_RC],9
		mov	byte [_$P_RC],9 ;_$P_Syntax ; set error flag
_$P_Match2_Exit:
		pop	ax
		retn

;***********************************************************************
;
; _$P_Remove_Colon;
;
; Function: Remove colon at end
;
; Input:    psdata_seg:SI points to string buffer to be examined
;
; Output:   None
;
; Use:	_$P_Chk_DBCS
;
;***********************************************************************

_$P_Remove_Colon:
		push	ax
		push	si
_$P_RCOL_Loop:
		mov	al,[si]			; get character
		or	al,al			; end of string?
		jz	short _$P_RCOL_Exit	; if yes, just exit
		cmp	al,':'			; is it colon?
		jne	short _$P_RCOL00
		cmp	byte [si+1],0 ;_$P_NULL	; if so, next is NULL?
		jne	short _$P_RCOL00	; no, then next char	
		mov	byte [si],0		; yes, remove colon
		jmp	short _$P_RCOL_Exit	; and exit.
_$P_RCOL00:
		call	_$P_Chk_DBCS		; if not colon, then check if
		jnc	short _$P_RCOL01	; DBCS leading byte.
		inc	si			; if yes, skip trailing byte
_$P_RCOL01:
		inc	si			; si points to next byte
		jmp	short _$P_RCOL_Loop	; loop until NULL encountered
_$P_RCOL_Exit:
		pop	si
		pop	ax
		retn

;***********************************************************************
;
; _$P_Do_CAPS_String;
;
; Function: Perform capitalization along with the file case map table
;	    or character case map table.
;
; Input:    AL = 2 : Use character table
;	    AL = 4 : Use file table
;	    psdata_seg:SI points to string buffer to be capitalized
;
; Output:   None
;
; Use:	_$P_Do_CAPS_Char, _$P_Chk_DBCS
;
;***********************************************************************

_$P_Do_CAPS_String:
		push	si
		push	dx
		mov	dl,al			; save info id
_$P_DCS_Loop:
		mov	al,[si]			; load character and
		call	_$P_Chk_DBCS		; check if DBCS leading byte
		jc	short _$P_DCS00		; if yes, do not need CAPS
		or	al,al			; end of string?
		jz	short _$P_DCS_Exit	; then exit.
		call	_$P_Do_CAPS_Char	; Here a SBCS char need to be CAPS
		mov	[si],al			; stored upper case char to buffer
		jmp	short _$P_DCS01		; process nexit
_$P_DCS00:
		inc	si			; skip DBCS leading and trailing byte
_$P_DCS01:
		inc	si			; si point to next byte
		jmp	short _$P_DCS_Loop	; loop until NULL encountered
_$P_DCS_Exit:
		pop	dx
		pop	si
		retn

;***********************************************************************
;
; _$P_Do_CAPS_Char;
;
; Function: Perform capitalization along with the file case map table
;	    or character case map table.
;
; Input:    DL = 2 : Use character table
;	    DL = 4 : Use file table
;	    AL = character to be capitalized
;
; Output:   None
;
; Use:	INT 21h /w AH=65h
;
;***********************************************************************

_$P_Do_CAPS_Char:
		cmp	al,80h	;_$P_ASCII80 ; need upper case table?
		jnb	short _$P_DCC_Go ; if no,
		cmp	al,'a'		 ;   check if  "a" <= AL <= "z"
		jb	short _$P_CAPS_Ret
		cmp	al,'z'
		ja	short _$P_CAPS_Ret ;   if yes, make CAPS	
		and	al,0DFh ;_$P_Make_Upper	;   else do nothing.
		retn
_$P_DCC_Go:
		push	bx
		push	es
		push	di
		;lea	di,[_$P_Char_CAP_Ptr]
		mov	di,_$P_Char_CAP_Ptr
_$P_DCC00:
		cmp	[di],dl		; already got table address?
		je	short _$P_DCC01	; if no,

;In this next section, ES will be used to pass a 5 byte workarea to INT 21h,
; the GET COUNTYRY INFO call. 

		push	ax
		push	cx
		push	dx
		;push	cs
		;pop	es
				; ES:DI = pointer to output buffer
		xchg	ax,dx
		mov	ah,65h ;_$P_DOS_Get_TBL
				; Get Extended Country Information
		mov	bx,-1 ; 0FFFFh ; _$P_DOSTBL_Def ; get active CON
		mov	cx,5 ;_$P_DOSTBL_BL ; buffer length
		mov	dx,bx ; -1 ; get for default code page
		int	21h	; COUNTRY-DEPENDENT FILENAME CAPITALIZATION
				; AL = function	- (02h or 04h)
		pop	dx
		pop	cx
		pop	ax
_$P_DCC01:
				  ; [ES:DI] = country id (02h or 04h)
		les	bx,[di+1] ; [ES:DI+1] = pointer to uppercase table
		inc	bx	; add 2 to bx reg
		inc	bx	; to skip length field	
		sub	al,80h	; make char to index
		;xlat	byte ptr es:[bx]
		es		; segment prefix (xlat byte ptr es:[bx])
		xlat		; perform case map
		pop	di
		pop	es
		pop	bx
_$P_CAPS_Ret:
		retn

;***********************************************************************
;
; _$P_Value / _$P_SValue
;
; Function:  Make 32bit value from psdata_seg:SI and see value list
;	     and make result buffer.
;	     _$P_SValue is an entry point for the signed value
;	     and this will simply call _$P_Value after the handling
;	     of the sign character, "+" or "-"
;
; Input:     psdata_seg:SI -> _$P_STRING_BUF
;	     ES:BX -> CONTROL block
;
; Output:    None
;
; Use:	_$P_Fill_Result, _$P_Check_OVF
;
; Vars: _$P_RC(W), _$P_Flags(RW)
;
;***********************************************************************

_$P_SValue:				; when signed value here
		push	ax
		or	byte [_$P_Flags2],80h	; indicate a signed numeric
					; 0FFh - _$P_Neg
		and	byte [_$P_Flags2],~2 ; not 2 ; assume positive value
		mov	al,[si]		; get sign
		cmp	al,'+' ;_$P_Plus
		je	short _$P_SVal00
		cmp	al,'-'
		jne	short _$P_Sval01 ; else	
		or	byte [_$P_Flags2],2 ;_$P_Neg ; set this is negative value
_$P_SVal00:
		inc	si		; skip sign char
_$P_Sval01:
		call	_$P_Value	; and process value
		pop	ax
		retn

; ----------------------------------------------------------------------------

_$P_Value:
		push	ax
		push	cx
		push	dx
		push	si
		xor	cx,cx		; cx = higher 16 bits
		xor	dx,dx		; dx = lower 16 bits
		push	bx		; save control pointer
_$P_Value_Loop:
		mov	al,[si]		; get character
		or	al,al		; end of line?
		jz	short _$P_Value00
		call	_$P_0099	; make asc(0..9) to bin(0..9)
		jc	short _$P_Value_Err0 ; error, exit
		xor	ah,ah
		mov	bp,ax		; save binary number
		call	_$P_Value_sub1	; 2*x
		mov	bx,dx		; save low(2*x)
		mov	ax,cx		; save high(2*x)
		call	_$P_Value_sub1  ; 4*x
		call	_$P_Value_sub1	; 8*x
		add	dx,bx		; 10*x
		adc	cx,ax		; 32bit ADD
		call	_$P_Value_sub2	; Overflow occurred?
		add	dx,bp		; Add the current one degree decimal
		adc	cx,0		; if carry, add 1 to high 16bit	
		call	_$P_Value_sub2	; Overflow occurred?
		inc	si
		jmp	short _$P_Value_Loop
_$P_Value_sub1:
		shl	dx,1		; to have 2*x
		rcl	cx,1		; shift left w/ carry
_$P_Value_sub2:
		call	_$P_Check_OVF	; Overflow occurred?
		jc	short _$P_Value_sub2_err ; then error, exit
		retn
_$P_Value_sub2_err:
		inc	sp		; skip return address on top of stack
		inc	sp
_$P_Value_Err0:
		pop	bx		; retore control pointer
		jmp	_$P_Value_Err	; Bridge
_$P_Value00:
		pop	bx
		test	byte [_$P_Flags2],2 ;_$P_Neg ;   here cx,dx = 32bit value
		jz	short _$P_Value01 ; was it negative?
		not	cx		; +
		not	dx		; |- Make 2's complemeny
		add	dx,1		; |
		adc	cx,0		; +
_$P_Value01:				; / nval = 0
		;mov	si,es:[bx]._$P_Value_List
		;mov	si,[es:bx+6]	; si points to value list
		mov	si,[bx+6]
		;mov	al,[es:si]	; get nval
		mov	al,[si]
		cmp	al,0 ;_$P_nval_None ; no value list?
		jne	short _$P_Value02
		;mov	al,_$P_Number	; Set type
		;mov	ah,_$P_No_Tag	; No ITEM_TAG set
		mov	ax,0FF01h
		jmp	_$P_Value_Exit
_$P_Value02:
		inc	si
		;mov	al,[es:si]	; al = number of range
		mov	al,[si]
		cmp	al,0 ;_$P_No_nrng
		je	short _$P_Value03
		inc	si		; si points to 1st item_tag
_$P_Val02_Loop:
		test	byte [_$P_Flags2],80h ;_$P_Signed
		jnz	short _$P_Val02_Sign
		;cmp	cx,[es:si+_$P_Val_XH]
		;cmp	cx,[es:si+3]	; comp cx with XH
		cmp	cx,[si+3]
		jb	short _$P_Val02_Next
		ja	short _$P_Val_In
		;cmp	dx,[es:si+_$P_Val_XL]
		;cmp	dx,[es:si+1]	; comp dx with XL
		cmp	dx,[si+1]
		jb	short _$P_Val02_Next
_$P_Val_In:
		;cmp	cx,[es:si+_$P_Val_YH]
		;cmp	cx,[es:si+7]	; comp cx with YH
		cmp	cx,[si+7]
		ja	short _$P_Val02_Next
		jb	short _$P_Val_Found
		;cmp	dx,[es:si+_$P_Val_YL]	
		;cmp	dx,[es:si+5]	; comp dx with YL
		cmp	dx,[si+5]
		ja	short _$P_Val02_Next
		jmp	short _$P_Val_Found
_$P_Val02_Sign:
		;cmp	cx,[es:si+_$P_Val_XH]
		;cmp	cx,[es:si+3]	; comp cx with XH
		cmp	cx,[si+3]
		jl	short _$P_Val02_Next
		jg	short _$P_SVal_In
		;cmp	dx,[es:si+_$P_Val_XL]
		;cmp	dx,[es:si+1]	; comp dx with XL
		cmp	dx,[si+1]
		jl	short _$P_Val02_Next
_$P_SVal_In:
		;cmp	cx,[es:si+_$P_Val_YH]
		;cmp	cx,[es:si+7]	; comp cx with YH
		cmp	cx,[si+7]
		jg	short _$P_Val02_Next
		jl	short _$P_Val_Found
		;cmp	dx,[es:si+_$P_Val_YL]
		;cmp	dx,[es:si+5]	; comp dx with YL
		cmp	dx,[si+5]
		jg	short _$P_Val02_Next
		jmp	short _$P_Val_Found
_$P_Val02_Next:
		add	si,9 ;_$P_Len_Range 
		dec	al		; loop nrng times in AL
		jnz	short _$P_Val02_Loop
				; / Not found
		;mov	word [_$P_RC],6	;_$P_Out_of_Range
		mov	byte [_$P_RC],6
		;mov	al,_$P_Number	;
		;mov	ah,_$P_No_Tag	; No ITEM_TAG set
		mov	ax,0FF01h
		jmp	short _$P_Value_Exit
_$P_Val_Found:
		mov	al,1 ;_$P_Number
		;mov	ah,[es:si]	; found ITEM_TAG set
		mov	ah,[si]
		jmp	short _$P_Value_Exit
_$P_Value03:				; / nval = 2
		mov	ah,9 ;_$P_Len_Range 
		mul	ah		; Skip nrng field
		inc	ax
		add	si,ax		; si points to nnval
		;mov	al,[es:si]	; get nnval
		mov	al,[si]
		inc	si		; si points to 1st item_tag
_$P_Val03_Loop:
		;cmp	cx,[es:si+_$P_Val_XH]
		;cmp	cx,[es:si+3]	; comp cx with XH
		cmp	cx,[si+3]
		jne	short _$P_Val03_Next
		;cmp	dx,[es:si+_$P_Val_XL]
		;cmp	dx,[es:si+1]	; comp dx with XL
		cmp	dx,[si+1]
		je	short _$P_Val_Found
_$P_Val03_Next:
		add	si,5 ;_$P_Len_Value ; points to next value choice
		dec	al		; loop nval times in AL
		jnz	short _$P_Val03_Loop ; / Not found
				; / Not found
		;mov	word [_$P_RC],7 ;_$P_Not_in_Val
		mov	byte [_$P_RC],7
		;mov	al,_$P_Number	;
		;mov	ah,_$P_No_Tag	; No ITEM_TAG set
		mov	ax,0FF01h
		jmp	short _$P_Value_Exit
_$P_Value_Err:				; / nval = 3 or else
		;mov	word [_$P_RC],9 ;_$P_Syntax
		mov	byte [_$P_RC],9
		;mov	al,_$P_String	; Set type
		;mov	ah,_$P_No_Tag	; No ITEM_TAG set
		mov	ax,0FF03h
_$P_Value_Exit:
		call	_$P_Fill_Result
		pop	si
		pop	dx
		pop	cx
		pop	ax
		retn

;***********************************************************************
;
; _$P_Check_OVF
;
; Function:  Check if overflow is occurred with consideration of
;	     signed or un-signed numeric value
;
; Input:     Flag register
;
; Output:    CY = 1  :	Overflow
;
; Vars:     _$P_Flags(R)
;
;***********************************************************************

_$P_Check_OVF:
		pushf
		test	byte [_$P_Flags2],2 ;_$P_Neg ; is it negative value ?
		jnz	short _$P_COVF	; if no, check overflow
		popf			; by the CY bit
		retn
_$P_COVF:
		popf			; else,
		jo	short _$P_COVF00 ; check overflow by the OF
		clc			; indicate it with CY bit
		retn			; CY=0 means no overflow
_$P_COVF00:
		stc			; and CY=1 means overflow
		retn

;***********************************************************************
;
; _$P_0099;
;
; Function:  Make ASCII 0-9 to Binary 0-9
;
; Input:     AL = character code
;
; Output:    CY = 1 : AL is not number
;	     CY = 0 : AL contains binary value
;
;***********************************************************************

_$P_0099:
		cmp	al, '0'
		jb	short _$P_0099Err	; must be 0 =< al =< 9
		cmp	al, '9'
		ja	short _$P_0099Err	; must be 0 =< al =< 9

		sub	al, '0'			; make char -> bin
		clc				; indicate no error
		retn
_$P_0099Err:
		stc				; indicate error
		retn

; 10/11/2018

;***********************************************************************
;
; _$P_Simple_String
;
; Function:  See value list for the simple string
;	     and make result buffer.
;
; Input:     psdata_seg:SI -> _$P_STRING_BUF
;	     ES:BX -> CONTROL block
;
; Output:    None
;
; Use:	_$P_Fill_Result, _$P_String_Comp
;
; Vars: _$P_RC(W)
;
;***********************************************************************

_$P_Simple_String:
		push	ax
		push	bx
		push	dx
		push	di
		;mov	di,es:[bx]._$P_Value_List
		;mov	di,[es:bx+6]	; di points to value list
		mov	di,[bx+6]
		;mov	al,[es:di]	; get nval
		mov	al,[di]
		or	al,al		; no value list?
		jnz	short _$P_Sim01	; then
		mov	ah,0FFh ;_$P_No_Tag ; No ITEM_TAG set
		jmp	short _$P_Sim_Exit ; and set result buffer
_$P_Sim01:
		;mov	word [_$P_RC],9	;_$P_Syntax
		mov	byte [_$P_RC],9
		mov	ah,0FFh		; No ITEM_TAG set
_$P_Sim_Exit:
		mov	al,3 ;_$P_String	; Set type
		call	_$P_Fill_Result
		pop	di
		pop	dx
		pop	bx
		pop	ax
		retn

;***********************************************************************
;
; _$P_String_Comp:
;
; Function:  Compare two string
;
; Input:     psdata_seg:SI -> 1st string
;	     ES:BP -> 2nd string  (Must be upper case)
;	     ES:BX -> CONTROL block
;
; Output:    CY = 1 if not match
;
; Use:	_$P_Chk_DBCS, _$P_Do_CAPS_Char
;
; Vars: _$P_KEYor_SW_Ptr(W), _$P_Flags(R). _$P_KEYorSW_Ptr
;
;***********************************************************************

_$P_String_Comp:
		push	ax
		push	bp
		push	dx
		push	si
		mov	dl,2 ;_$P_DOSTBL_Char ; use character case map table
_$P_SCOM_Loop:
		mov	al,[si]		; get command character
		call	_$P_Chk_DBCS	; DBCS?
		jc	short _$P_SCOM00 ; yes
		call	_$P_Do_CAPS_Char ; else, upper case map before comparison	
		test	byte [_$P_Flags2],8 ;_$P_Key_Cmp ; keyword search ?
		jz	short _$P_SCOM04
		cmp	al,'=' ;_$P_Keyword ; "=" is delimiter
		jne	short _$P_SCOM03 ;IF "=" on command line 
				 ; AND (bp+1=> char after the "=" in synonym list)
		;cmp	byte [es:bp+1],0 ;_$P_NULL ; at end of keyword string 
		cmp	byte [bp+1],0		  ; in the control block THEN
		jne	short _$P_SCOM_Differ
		jmp	short _$P_SCOM05 ; keyword found in synonym list	
_$P_SCOM04:
		test	byte [_$P_Flags2],10h ;_$P_SW_Cmp ; switch search ?
		jz	short _$P_SCOM03
		cmp	al,':' ;_$P_Colon ; ":" is delimiter, at end of switch on command line
		jne	short _$P_SCOM03 ; continue compares
		;cmp	byte [es:bp],0 ;_$P_NULL ; IF at end of switch on command AND
		cmp	byte [bp],0	; at end of switch string in the control block THEN
		jne	short _$P_SCOM_Differ
_$P_SCOM05:				; found a match
		inc	si		; si points to just after "=" or ":"
		jmp	short _$P_SCOM_Same ; exit
_$P_SCOM03:
		;cmp	al,[es:bp]	; compare operand w/ a synonym
		cmp	al,[bp]	
		jne	short _$P_SCOM_Differ0 ; if different, check ignore colon option
		or	al,al		; end of line
		jz	short _$P_SCOM_Same ; if so, exit
		inc	si		; update operand pointer
		inc	bp		; and synonym pointer
		jmp	short _$P_SCOM01 ; loop until NULL or "=" or ":" found in case
_$P_SCOM00:
		;cmp	al,[es:bp]	; Here al is DBCS leading byte
		cmp	al,[bp]		; compare leading byte
		jne	short _$P_SCOM_Differ ; if not match, say different
		inc	si		; else, load next byte
		mov	al,[si]		; and
		inc	bp
		;cmp	al,[es:bp+0]	; compare 2nd byte
		cmp	al,[bp]
		jnz	short _$P_SCOM_Differ ; if not match, say different, too
		inc	si		; else update operand pointer
		inc	bp		; and synonym pointer
_$P_SCOM01:
		jmp	short _$P_SCOM_Loop ; loop until NULL or "=" or "/" found in case
_$P_SCOM_Differ0:
		test	byte [_$P_Flags2],40h ;_$P_SW
		jz	short _$P_not_applicable
		;test	es:[bx]._$P_Function_Flag,_$P_colon_is_not_necessary
		;test	word [es:bx+2],20h
		test	word [bx+2],20h
		jz	short _$P_not_applicable
		;cmp	byte [es:bp],0 ;_$P_NULL
		cmp	byte [bp],0
		je	short _$P_SCOM_Same
_$P_not_applicable:
		;test	es:[bx]._$P_Match_Flag,_$P_Ig_Colon
		;test	word [es:bx],10h ; ignore colon option specified?	
		test	word [bx],10h
		jz	short _$P_SCOM_Differ ; if no, say different.
		cmp	al,':' ;_$P_Colon ; End up with ":" and	
		jne	short _$P_SCOM02 ; subseqently	
		;cmp	byte [es:bp+0],0 ; NULL?
		cmp	byte [bp],0
		jne	short _$P_SCOM_Differ ; if no, say different
		jmp	short _$P_SCOM_Same ; else, say same
_$P_SCOM02:
		cmp	al,0 ;_$P_NULL	;end up NULL and :
		jne	short _$P_SCOM_Differ
		;cmp	byte [es:bp],':' ;_$P_Colon 
		cmp	byte [bp],':'	; if no, say different
		je	short _$P_SCOM_Same ; else, say same
_$P_SCOM_Differ:
		stc			; indicate not found
		jmp	short _$P_SCOM_Exit
_$P_SCOM_Same:
		mov	[_$P_KEYorSW_Ptr],si ; for later use by keyword or switch
		clc			; indicate found
_$P_SCOM_Exit:
		pop	si
		pop	dx
		pop	bp
		pop	ax
		retn

;***********************************************************************
;
; _$P_Date_Format
;
; Function:  Convert a date string to DOS date format for int 21h
;	     with format validation.
;
; Input:     psdata_seg:SI -> _$P_STRING_BUF
;	     ES:BX -> CONTROL block
;
; Output:    None
;
; Use:	_$P_Fill_Result, _$P_Set_CDI, _$P_Get_DecNum
;
; Vars: _$P_RC(W), _$P_1st_Val(RW), _$P_2nd_Val(RW), _$P_3rd_Val(RW)
;
;***********************************************************************

_$P_Date_Format:
		push	ax
		push	cx
		push	dx
		push	si
		push	bx
		push	si
		call	_$P_Set_CDI ; set country dependent information before process
		pop	si
		xor	ax, ax
		mov	[_$P_1st_Val],ax ; set initial value	
		mov	[_$P_2nd_Val],ax
		mov	[_$P_3rd_Val],ax
		call	_$P_Get_DecNum	; get 1st number
		;jc	short _$P_DateF_Err0
		jc	short _$P_DateF_Error
		mov	[_$P_1st_Val],ax
		or	bl,bl		; end of line?
		jz	short _$P_DateF_YMD
		call	_$P_Get_DecNum	; get 2nd number
		jc	short _$P_DateF_Error
		mov	[_$P_2nd_Val],ax
		or	bl,bl		; end of line ?
		jz	short _$P_DateF_YMD
		call	_$P_Get_DecNum	; get 3rd number	
_$P_DateF_Err0:				; Bridge	
		jc	short _$P_DateF_Error
		mov	[_$P_3rd_Val],ax
		or	bl,bl
		jnz	short _$P_DateF_Error
_$P_DateF_YMD:
		;mov	bx,[_$P_Country_Info+_$P_CDI_DateF]
		mov	bx,[_$P_Country_Info] ; get date format
		cmp	bx,2	; _$P_Date_YMD
		je	short _$P_DateF00
		mov	ax,[_$P_1st_Val]
		or	ah,ah
		jnz	short _$P_DateF_Error
		mov	cl,al		; set month
		mov	ax,[_$P_2nd_Val]
		or	ah,ah		; if overflow, error.
		jnz	short _$P_DateF_Error
		mov	ch,al		; set date
		mov	dx,[_$P_3rd_Val] ; set year
		cmp	bx,1 ;_$P_Date_DMY ; from here format = MDY
		jne	short _$P_DateF01 ; if it is DMY
		xchg	ch,cl		;  then swap M <-> D
_$P_DateF01:
		jmp	short _$P_DateF02
_$P_DateF00:				; / here format = YMD
		mov	dx,[_$P_1st_Val] ; set year	
		mov	ax,[_$P_2nd_Val]
		or	ah,ah		; if overflow, error
		jnz	short _$P_DateF_Error
		mov	cl,al		; set month
		mov	ax,[_$P_3rd_Val]
		or	ah,ah		; if overflow, error
		jnz	short _$P_DateF_Error
		mov	ch,al		; set date
_$P_DateF02:
		cmp	dx,100		; year is less that 100?
		jnb	short _$P_DateF03
		add	dx,1900		; set year 19xx
_$P_DateF03:
		pop	bx
		pop	si
		;mov	ah,_$P_No_Tag
		;mov	al,_$P_Date_F
		mov	ax,0FF07h	; set results buffer to date
		call	_$P_Fill_Result
		jmp	short _$P_Date_Format_Exit
_$P_DateF_Error:
		pop	bx		; recover CONTROL block
		pop	si		; recover string pointer
		;mov	ah,_$P_No_Tag	
		;mov	al,_$P_Date_F
		mov	ax,0FF03h	; set results buffer to string
		call	_$P_Fill_Result
		;mov	word [_$P_RC],9 ;_$P_Syntax
		mov	byte [_$P_RC],9 ; indicate syntax error
_$P_Date_Format_Exit:
		pop	dx
		pop	cx
		pop	ax
		retn

;***********************************************************************
;
; _$P_Set_CDI:
;
; Function: Read CDI from DOS if it has not been read yet
;
; Input:    None
;
; Output:   psdata_seg:SI -> CDI
;
; Use:	INT 21h w/ AH = 38h
;
;***********************************************************************

_$P_Set_CDI:
		;lea	si,[_$P_Country_Info]
		mov	si,_$P_Country_Info
		;cmp	word [cs:si+_$P_CDI_DateF],_$P_NeedToBeRead
		cmp	word [si],0FFFFh ; -1 ; already read?
		jne	short _$P_Set_CDI_Exit ; then do nothing
					;else read CDI thru DOS
		push	ds
		push	dx
		push	ax
		;push	cs
		;pop	ds
		mov	ax,3800h ; _$P_DOS_Get_CDI ; get country information
		mov	dx,si ; set offset of CDI in local data area
		int	21h	; GET COUNTRY-DEPENDENT INFORMATION
				; get current-country info
				; DS:DX	-> buffer for returned info
		pop	ax
		pop	dx
		pop	ds
_$P_Set_CDI_Exit:
		retn

;***********************************************************************
;
; _$P_Get_DecNum:
;
; Function:  Read a chracter code from psdata_seg:SI until specified delimiter
;	     or NULL encountered. And make a decimal number.
;
; Input:     psdata_seg:SI -> _$P_STRING_BUF
;
; Output:    BL = delimiter code or NULL
;	     AX = Decimal number
;	     SI advanced to the next number
;	     CY = 1 : Syntax error, AL = Latest examined number
;
; Use:	_$P_0099
;
;***********************************************************************

_$P_Get_DecNum:
		push	cx
		push	dx
		xor	cx,cx		; cx will have final value
_$P_GetNum_Loop:
		mov	al,[si]		; load character
		or	al,al		; end of line?
		jz	short _$P_GetNum00 ; if yes, exit
		cmp	byte [_$P_Got_Time],0   ; is this numeric in a time field?
		je	short _$P_Do_Date_Delims ; no, go check out Date delimiters

; Determine which delimiter(s) to check for. Colon & period or period only
 
		cmp	bl,1 ;_$P_colon_period	; Time
		jne	short _$P_Do_Time_Delim1 ; only check for period
		cmp	al,':' ;_$P_Colon	; Is this a valid delimiter?
		je	short _$P_GetNum01	; yes, exit
_$P_Do_Time_Delim1:
		cmp	al,'.' ;_$P_Period	; Is this a valid delimiter?
		je	short _$P_GetNum01	; yes, exit
		jmp	short _$P_Neither_Delims
_$P_Do_Date_Delims:
;Regardless of the date delimiter character specified in the country
;dependent information, check for the presence of any one of these
;three field delimiters: "-", "/", or ".".
		cmp	al,'-' ;_$P_Minus	; is this a date delimiter character?
		je	short _$P_GetNum01	; if yes, exit
		cmp	al,'/' ;_$P_Slash	; is this a date delimiter character?	
		je	short _$P_GetNum01	; if yes, exit
		cmp	al,'.' ;_$P_Period	; is this a date delimiter character?
		je	short _$P_GetNum01	; if yes, exit
_$P_Neither_Delims:
		call	_$P_0099		; convert it to binary
		jc	short _$P_GetNum_Exit	; if error exit
		mov	ah,0
		xchg	ax,cx
		mov	dx,10
		mul	dx			; ax = ax*10
		or	dx,dx			; overflow
		jnz	short _$P_GetNum02	; then exit
		add	ax,cx
		jc	short _$P_GetNum_Exit
		xchg	ax,cx
		inc	si
		jmp	short _$P_GetNum_Loop
_$P_GetNum00:
		mov	bl,al		; set bl to NULL
_$P_GetNum03:
		clc			; indicate no error
		jmp	short _$P_GetNum_Exit
_$P_GetNum01:
		inc	si
		jmp	short _$P_GetNum03
_$P_GetNum02:
		stc			; indicate error
_$P_GetNum_Exit:
		xchg	ax,cx		; return value
		pop	dx
		pop	cx
		retn

; ----------------------------------------------------------------------------
; messages.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 13/11/2018)

;/*  */
;/******************************************************************************/
;/*Routine name:  PRELOAD_MESSAGES                                             */
;/******************************************************************************/
;/*                                                                            */
;/*Description:   Preloads messages for Display_Msg and returns error code     */
;/*               if incorrect DOS version, insuffient memory, or unable to    */
;/*               to find messages.                                            */
;/*                                                                            */
;/*Called Procedures:    sysloadmsg                                            */
;/*                      display_msg                                           */
;/*                                                                            */
;/*Change History: Created        5/30/87         DRM                          */
;/*                                                                            */
;/*Input: None                                                                 */
;/*                                                                            */
;/*Output: None                                                                */
;/*                                                                            */
;/******************************************************************************/

;char preload_messages()

;BEGIN
;
;char message_flag;
;
;     /* load all messages for FDISK */
;     message_flag = c(TRUE);
;     sysloadmsg(&regs,&regs);  		     /* load the messages */
;
;     if ((regs.x.cflag & CARRY_FLAG) == CARRY_FLAG) /* If msg load problem */
;       BEGIN
;        sysdispmsg(&regs,&regs); 		     /* write the error message */
;        message_flag = FALSE;
;       END
;     return(message_flag);
;
;END

preload_messages:

	;%define message_flag bp-2

		;push	bp
		;mov	bp,sp
		;sub	sp,2
		;;mov	[bp-2],1
		;mov	[message_flag],1
		;mov	ax,regs ;regs_x_ax
		;push	ax
		;push	ax
		;call	sysloadmsg
		;pop	bx
		;pop	bx

		call	SYSLOADMSG ; 14/11/2018

		;mov	al,[regs_x_cflag]
		;and	al,1
		;cmp	al,1
		;jne	short preloadmsg_ret
		; 14/11/2018
		jnc	short preloadmsg_1

		;mov	ax,regs ;regs_x_ax
		;push	ax
		;push	ax
		;call	sysdispmsg
		;pop	bx
		;pop	bx
		;;mov	[bp-2],0
		;mov	[message_flag],0

		; 14/11/2018
		call	SYSDISPMSG 

		;sub	ax,ax
		;jmp	short preloadmsg_2
		stc	
preloadmsg_1:
		retn
;preloadmsg_1:
		; 14/11/2018
		;;mov	ax,1
		;xor	ax,ax
		;inc	al
		retn
;preloadmsg_2:
		;;;mov	al,[bp-2]
		;;mov	al,[message_flag]
		;;mov	sp,bp
		;;pop	bp
		;;retn
		
		; 13/11/2018
		;cmp	al,1	
		;retn

;sysloadmsg:
;		call	_sysloadmsg
;		retn

; _msgret.asm (MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------
; 14/11/2018

;_sysloadmsg:
;
;	%define inregs  bp+8
;	%define outregs bp+10
;
;		push	bp
;		mov	bp,sp
;		push	di
;		push	si
;		mov	di,[inregs] 
;		mov	ax,[di+10] ; regs.x.di
;		push	ax
;		mov	ax,[di]	   ; regs.x.ax	
;		mov	bx,[di+2]  ; regs.x.bx	
;		mov	cx,[di+4]  ; regs.x.cx	
;		mov	dx,[di+6]  ; regs.x.dx	
;		mov	si,[di+8]  ; regs.x.si	
;		pop	di
;		push	bp
;		call	SYSLOADMSG
;		pop	bp
;		push	di
;		mov	di,[outregs]
;		mov	[di],ax	   ; regs.x.ax	
;		mov	[di+2],bx  ; regs.x.bx
;		mov	[di+4],cx  ; regs.x.cx		
;		mov	[di+6],dx  ; regs.x.dx	
;		mov	[di+8],si  ; regs.x.si	
;		lahf
;		mov	al,ah
;		mov	[di+12],ax ; regs.x_cflag
;		pop	ax
;		mov	[di+10],ax ; regs.x.di	
;		pop	si
;		pop	di
;		mov	sp,bp
;		pop	bp
;		retf

SYSLOADMSG:

		;push	ax
		;push	bx
		;push	dx
		;push	es
		;push	di
		xor	cx,cx
		mov	es,cx
		xor	di,di
		mov	ax,122Eh
		mov	dl,0
		int	2Fh	; Multiplex - DOS 3+ internal -	GET OR SET ERROR TABLE ADDRESSES
				; DL = subfunction - get standard DOS error table (errors 00h-12h,50h-5Bh)
				; Return: ES:DI	-> error table
		mov	[$M_EXT_COMMAND+2],es
		mov	[$M_EXT_COMMAND],di
		mov	ax,122Eh
		mov	dl,2
		int	2Fh	; Multiplex - DOS 3+ internal -	GET OR SET ERROR TABLE ADDRESSES
				; DL = subfunction - get parameter error table (errors 00h-0Ah)
				; ES:DI	-> error table
		mov	[$M_PARSE_COMMAND+2],es
		mov	[$M_PARSE_COMMAND],di
		mov	ax,122Eh
		mov	dl,4
		int	2Fh	; Multiplex - DOS 3+ internal -	GET OR SET ERROR TABLE ADDRESSES
				; DL = subfunction - get critical/SHARE	error table (errors 13h-2Bh)
				; ES:DI	-> error table
		mov	[$M_CRIT_COMMAND+2],es
		mov	[$M_CRIT_COMMAND],di
		mov	ax,122Eh
		mov	dl,6
		int	2Fh	; Multiplex - DOS 3+ internal -	GET OR SET ERROR TABLE ADDRESSES
				; DL = subfunction - get ??? error table
				; ES:DI	-> error table
		mov	[$M_EXT_FILE+2],es
		mov	[$M_EXT_FILE],di
		;call	_$M_CLS_1
		push	cs ; *
		pop	es ; *
		mov	di,CLASS_1_msg_tbl ; 14/11/2018 ; *
		mov	[$M_EXT_ERR_ADDRS+2],es
		mov	[$M_EXT_ERR_ADDRS],di
		mov	[$M_CRIT_ADDRS+2],es
		mov	[$M_CRIT_ADDRS],di
		;call	_$M_CLS_2
		mov	di,CLASS_2_msg_tbl ; 14/11/2018
		mov	[$M_PARSE_ADDRS+2],es
		mov	[$M_PARSE_ADDRS],di
		mov	ax,122Eh
		mov	dl,8
		int	2Fh	; Multiplex - DOS 3+ internal -	GET OR SET ERROR TABLE ADDRESSES
				; DL = subfunction - get ??? error table
				; Return: ES:DI	-> error table
		mov	[$M_DISK_PROC_ADDR+2],es
		mov	[$M_DISK_PROC_ADDR],di
		;mov	word [$M_CRLF],0A0Dh
		;mov	byte [$M_BUF_TERM],'$'
		;mov	word [$M_MSG_NUM],0
		;mov	[$M_DIVISOR],10
		;call	_$M_CLS_A
		push	ds ; *
		pop	es ; *
		mov	di,CLASS_A_msg_tbl ; 14/11/2018 ; *
		mov	[$M_CLASS_A_ADDRS+2],es
		mov	[$M_CLASS_A_ADDRS],di
		;call	_$M_CLS_B
		mov	di,CLASS_B_msg_tbl ; 14/11/2018
		mov	[$M_CLASS_B_ADDRS+2],es
		mov	[$M_CLASS_B_ADDRS],di

		call	_$M_GET_DBCS_VEC
		call	_$M_CHECKSTDIN
		call	_$M_CHECKSTDOUT

		;push	cx
		call	_$M_VERSION_CHECK
		;jc	short $MIF20
		;pop	cx
		;pop	di
		;pop	es
		;pop	dx
		;pop	bx
		;pop	ax
		;;retf

		retn	 
;$MIF20:
		;add	sp,12
		;stc
		;;retf
		;retn

; msgserver.asm (MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------
; 14/11/2018

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Proc Name:	$M_VERSION_CHECK
;;
;;  Function:	Determine if DOS version is within allowable limits
;;
;;  Inputs:	None
;;
;;  Outputs:	CARRY_FLAG = 1 if Incorrect DOS version
;;		Registers set for SYSDISPMSG
;;		CARRY_FLAG = 0 if Correct DOS version
;;
;;  Regs Changed: AX
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_VERSION_CHECK:
		mov	ah,30h
		int	21h ; DOS - GET DOS VERSION
			; Return: AL = major version number
			;		(00h for DOS 1.x)
		cmp	al,5		; IF DOS_MAJOR is correct
		jb	short $MIF27
		clc			; Clear the carry flag
		retn
$MIF27:
		mov	bx,2		; Standard Error			
		mov	ax,1		; Set message # 1		
		;mov	cx,0 ; NO_REPLACE ; No replacable parms
		xor	cx,cx
		;MOV	DL,NO_INPUT
	    	;MOV	DH,UTILITY_MSG_CLASS
					; No input	
		mov	dx,0FF00h	; Utility class message
		stc			; Set Carry Flag
		retn			; Return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Proc Name:	$M_GET_DBCS_VEC
;;
;;  Function:	Get the DBCS vector and save it for later use
;;
;;  Inputs:	None
;;
;;  Outputs:	None
;;
;;  Regs Changed:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_GET_DBCS_VEC:
		;push	ax	; Save registers
		;push	si
		push	ds ; *
		mov	ax,6300h ; DOS function to get DBSC environment	
				 ; Get environment pointer
		int	21h	; DOS - 3.2+ only
			    	; GET DOUBLE BYTE CHARACTER SET LEAD TABLE
		;push	ds
		;pop	es
		mov	ax,ds
		pop	ds ; *
		jc	short $MIF23

		mov	[$M_DBCS_VEC],si    ; Save DBCS Vector
		;mov	[$M_DBCS_VEC+2],es
		mov	[$M_DBCS_VEC+2],ax
$MIF23:
		;pop	si	; restore registers
		;pop	ax
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Proc Name:	$M_CHECKSTDIN
;;
;;  Function:
;;
;;  Inputs:	None
;;
;;  Outputs:
;;
;;  Regs Changed:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_CHECKSTDIN:
	mov	ax,4400h	; Get info using IOCTL
	;mov	bx,0  ; STDIN	 
	sub	bx,bx ; STDIN = 0
	;cwd
	xor	dx,dx ; 19/11/2018
	int	21h	; DOS -	2+ - IOCTL - GET DEVICE	INFORMATION
			; BX = file or device handle
	and	dh,1		; clear top 7 bits
	or	dh,1 ; $M_CRIT_ERR_MASK	 ; Turn on bit
	mov	ax,4401h ; Set info using IOCTL
	int	21h	; DOS -	2+ - IOCTL - SET DEVICE	INFORMATION
			; BX = device handle, (DH = 0)
			; DL = device information to set 
			;	(bits 0-7 from	function 0)
	retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Proc Name:	$M_CHECKSTDOUT
;;
;;  Function:
;;
;;  Inputs:	None
;;
;;  Outputs:
;;
;;  Regs Changed:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_CHECKSTDOUT:

	mov	ax,4400h	; Get info using IOCTL
	mov	bx,1  ; STDOUT	 
	;cwd
	xor	dx,dx ; 19/11/2018
	int	21h	; DOS -	2+ - IOCTL - GET DEVICE	INFORMATION
			; BX = file or device handle
	and	dh,1		; clear top 7 bits
	or	dh,1 ; $M_CRIT_ERR_MASK	 ; Turn on bit
	mov	ax,4401h ; Set info using IOCTL
	int	21h	; DOS -	2+ - IOCTL - SET DEVICE	INFORMATION
			; BX = device handle, (DH = 0)
			; DL = device information to set 
			;	(bits 0-7 from	function 0)
	retn
		
; messages.c (FDISK, MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------	

;/*  */
;/*---------------------------------------------------------------------------*/
;/*                                                                           */
;/*    Subroutine Name: display_msg                                           */
;/*                                                                           */
;/*    Subroutine Function:                                                   */
;/*       Display the requested message to the standard output device         */
;/*                                                                           */
;/*    Input:                                                                 */
;/*        (1) Number of the message to be displayed (see FDISK.SKL)          */
;/*        (2) Number of substitution parameters (%1,%2)                      */
;/*        (3) Offset of sublist control block                                */
;/*        (4) Message Class, 0=no input, 1=input via INT 21 AH=1             */
;/*                                                                           */
;/*    Output:                                                                */
;/*        The message is written to the standard output device.  If input    */
;/*        was requested, the character code of the key pressed is returned   */
;/*        in regs.x.ax.                                                      */
;/*                                                                           */
;/*    Normal exit: Message written to handle                                 */
;/*                                                                           */
;/*    Error exit: None                                                       */
;/*                                                                           */
;/*    Internal References:                                                   */
;/*              None                                                         */
;/*                                                                           */
;/*    External References:                                                   */
;/*              Sysdispmsg (module _msgret.sal)                              */
;/*                                                                           */
;/*---------------------------------------------------------------------------*/

;void display_msg(msgnum,msghan,msgparms,msgsub,msginput,msgclass)
;int   msgnum;                         /*;AN000; message number              */
;int   msghan;                         /*;AN000; output device               */
;int   msgparms;                       /*;AN000; number of substitution parms*/
;int   *msgsub;                        /*;AN000; offset of sublist           */
;char  msginput;                       /*;AN000; 0=no input, else input func */
;char  msgclass;                       /*;AN014; 0=no input, else input func */
;
;BEGIN
;	regs.x.ax = u(msgnum);             /*;AN000; set registers           */
;	regs.x.bx = u(msghan);             /*;AN000;                         */
;	regs.x.cx = u(msgparms);           /*;AN000;                         */
;	regs.h.dh = uc(msgclass);          /*;AN014;                         */
;	regs.h.dl = uc(msginput);          /*;AN000;                         */
;	regs.x.si = u(msgsub);             /*;AN000;                         */
;	sysdispmsg(&regs,&regs);           /*;AN000;  write the messages     */
;
;	return;                            /*;AN000;                         */
;END

display_msg:

	%define msgnum	 bp+4
	%define	msghan	 bp+6
	%define	msgparms bp+8
	%define	msgsub	 bp+10
	%define	msginput bp+12
	%define	msgclass bp+14

		push	bp
		mov	bp,sp

		;mov	ax,[msgnum]
		;mov	[regs_x_ax],ax
		;mov	ax,[msghan]
		;mov	[regs_x_bx],ax
		;mov	ax,[msgparms]
		;mov	[regs_x_cx],ax
		;mov	al,[msgclass]
		;mov	[regs_x_dx+1],al
		;mov	al,[msginput]
		;mov	[regs_x_dx],al
		;mov	ax,[msgsub]
		;mov	[regs_x_si],ax
		;mov	ax,regs ; regs_x_ax
		;push	ax ; outregs
		;push	ax ; inregs
		;call	sysdispmsg
		;pop	bx
		;pop	bx

		;mov	sp,bp
		;pop	bp
		;retn

		push	di ; *
		push	si ; **

		mov	ax,[msgnum] ; ***
		mov	bx,[msghan] ; ***	
		mov	cx,[msgparms] ; ***
		mov	dh,[msgclass] ; ***
		mov	dl,[msginput] ; ***
		mov	si,[msgsub] ; ***

		call	SYSDISPMSG ; 13/11/2018 ; * ; ** ; ***

		pop	si ; **
		pop	di ; *
		
		mov	sp,bp
		pop	bp
		
		retn

;sysdispmsg:
;		call	_sysdispmsg
;		retn

; _msgret.asm (MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------

;_sysdispmsg:
;
;	;%define inregs  bp+8
;	;%define outregs bp+10
;
;		push	bp
;		mov	bp,sp
;		push	di
;		push	si
;		mov	di,[inregs]
;		mov	ax,[di+10] ; regs.x.di
;		push	ax
;		mov	ax,[di]	   ; regs.x.ax	
;		mov	bx,[di+2]  ; regs.x.bx	
;		mov	cx,[di+4]  ; regs.x.cx	
;		mov	dx,[di+6]  ; regs.x.dx	
;		mov	si,[di+8]  ; regs.x.si	
;		pop	di
;		push	bp
;		call	SYSDISPMSG ; far call -> near call
;		pop	bp
;		push	di
;		mov	di,[outregs]
;		mov	[di],ax	   ; regs.x.ax	
;		mov	[di+2],bx  ; regs.x.bx
;		mov	[di+4],cx  ; regs.x.cx		
;		mov	[di+6],dx  ; regs.x.dx	
;		mov	[di+8],si  ; regs.x.si		
;		lahf
;		mov	al,ah
;		mov	[di+12],ax ; regs.x_cflag		
;		pop	ax
;		mov	[di+10],ax ; regs.x.di	
;		pop	si
;		pop	di
;		mov	sp,bp
;		pop	bp
;		retf

;/*  */
;/******************************************************************************/
;/*Routine name:  GET_YES_NO_VALUES                                            */
;/******************************************************************************/
;/*                                                                            */
;/*Description:   Uses SYSGETMSG to get the translated values for Y and N      */
;/*               for display purposes.                                        */
;/*                                                                            */
;/*Called Procedures:    sysgetmsg                                             */
;/*                      sysdispmsg                                            */
;/*                                                                            */
;/*Change History: Created        5/11/88         DRM                          */
;/*                                                                            */
;/*Input: None                                                                 */
;/*                                                                            */
;/*Output: None                                                                */
;/*                                                                            */
;/******************************************************************************/

;char get_yes_no_values()

;BEGIN
;
;char           message_flag;
;char far       *msg_buff;
;
;     message_flag = c(TRUE);
;
;     /* do sysgetmsg for 'Y' */
;     regs.x.ax = YesMsg;
;     regs.h.dh = uc(utility_msg_class);
;     sysgetmsg(&regs,&segregs,&regs);
;
;     FP_OFF(msg_buff) = regs.x.si;
;     FP_SEG(msg_buff) = segregs.ds;
;
;     Yes = *msg_buff;
;
;     if ((regs.x.cflag & CARRY_FLAG) != CARRY_FLAG)  /* If msg load problem */
;          BEGIN
;          /* do sysgetmsg for 'N' */
;          regs.x.ax = NoMsg;
;          regs.h.dh = uc(utility_msg_class);
;          sysgetmsg(&regs,&segregs,&regs);
;
;          FP_OFF(msg_buff) = regs.x.si;
;          FP_SEG(msg_buff) = segregs.ds;
;
;          No = *msg_buff;
;
;          END
;
;     if ((regs.x.cflag & CARRY_FLAG) == CARRY_FLAG)  /* If msg load problem */
;       BEGIN
;        sysdispmsg(&regs,&regs);		/* write the error message */
;        message_flag = FALSE;
;       END
;
;     return(message_flag);
;
;END

;get_yes_no_values:
;
;		;YesMsg	equ 9
;		;NoMsg	equ 10
;
;	%define message_flag bp-6 ; word
;	%define _msg_buf     bp-4 ; dword
;
;		push	bp
;		mov	bp,sp
;		sub	sp,6
;		mov	byte [message_flag],1
;		mov	[regs_x_ax],9 ; YesMsg
;		mov	byte [regs_x_dx+1],0FFh ; 255 ; UTILITY_MSG_CLASS
;		mov	ax,regs ; regs_x_ax
;		push	ax
;		mov	cx,segregs ; segregs_es
;		push	cx
;		push	ax
;		call	sysgetmsg
;		add	sp,6
;		mov	ax,[regs_x_si]
;		mov	[_msg_buf],ax
;		mov	ax,[segregs_ds]
;		mov	[_msg_buf+2],ax
;		les	bx,[_msg_buf]
;		mov	al,[es:bx]
;		mov	[Yes],al
;		mov	al,[regs_x_cflag]
;		and	al,1
;		cmp	al,1
;		je	short gynv_1 ; *
;		mov	[regs_x_ax],10 ; NoMsg
;		mov	byte [regs_x_dx+1],0FFh ; 255 ; UTILITY_MSG_CLASS
;		mov	ax,regs ; regs_x_ax
;		push	ax ; outregs
;		mov	cx,segregs ; segregs_es
;		push	cx
;		push	ax ; inregs
;		call	sysgetmsg
;		add	sp,6
;		mov	ax,[regs_x_si]
;		mov	[_msg_buf],ax
;		mov	ax,[segregs_ds]
;		mov	[_msg_buf+2],ax
;		les	bx,[_msg_buf]
;		mov	al,[es:bx]
;		mov	[No],al
;;gynv_1:
;		mov	al,[regs_x_cflag]
;		and	al,1
;		cmp	al,1
;		jne	short gynv_2
;gynv_1: ; 13/11/2018 ; *				
;		mov	ax,regs ; regs_x_ax
;		push	ax ; outregs
;		push	ax ; inregs
;		call	sysdispmsg
;		pop	bx
;		pop	bx
;		mov	byte [message_flag],0
;gynv_2:
;		mov	al,[message_flag]
;		mov	sp,bp
;		pop	bp
;		retn

get_yes_no_values:

		;YesMsg	equ 9
		;NoMsg	equ 10

	;%define message_flag bp-6 ; word
	;%define _msg_buf     bp-4 ; dword

		;push	bp
		;mov	bp,sp
		;sub	sp,6
		;mov	byte [message_flag],1

		mov	ax,9 ; YesMsg
		mov	dh,0FFh ; 255 ; UTILITY_MSG_CLASS
		call	SYSGETMSG
		jc	short gynv_1
		
		;or	cx,cx
		;jz	short gynv_1

		;; DS:SI = Message address
		;mov	al,[SI]
		;; ES:DI = Message address
		mov	al,[ES:DI]		
		mov	[Yes],al

		mov	ax,10 ; NoMsg
		mov	dh,0FFh ; 255 ; UTILITY_MSG_CLASS
		call	SYSGETMSG
		jc	short gynv_1

		;or	cx,cx
		;jz	short gynv_1

		;; DS:SI = Message address
		;mov	al,[SI]
		;; ES:DI = Message address
		mov	al,[ES:DI]		
		mov	[No],al
		jmp	short gynv_2
gynv_1:
		; 14/11/2018
		mov	byte [Yes],'Y'
		mov	byte [No],'N'
		
		;call	SYSDISPMSG
		;mov	byte [message_flag],0
gynv_2:
		;mov	al,[message_flag]
		;mov	sp,bp
		;pop	bp

		retn

;sysgetmsg:
;		call	_sysgetmsg
;		retn

; _msgret.asm (MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------

;_sysgetmsg:
;
;	%define inregs  bp+8
;	%define _seg_	bp+10
;	%define outregs bp+12
;
;		push	bp
;		mov	bp,sp
;		push	di
;		push	si
;		mov	di,[inregs] 
;		mov	ax,[di+10] ; regs.x.di
;		push	ax
;		mov	ax,[di]	   ; regs.x.ax	
;		mov	bx,[di+2]  ; regs.x.bx	
;		mov	cx,[di+4]  ; regs.x.cx	
;		mov	dx,[di+6]  ; regs.x.dx	
;		mov	si,[di+8]  ; regs.x.si	
;		pop	di
;		push	bp
;		call	SYSGETMSG  ; far call -> near call
;		pop	bp
;		push	di
;		mov	di,[_seg_] ; segregs
;		;push	ax
;		mov	[di],es	   ; segregs_es	
;		mov	[di+6],ds  ; segregs_ds	
;		;pop	ax
;		pop	di
;		push	di
;		mov	di,[outregs]
;		mov	[di],ax	   ; regs.x.ax	
;		mov	[di+2],bx  ; regs.x.bx
;		mov	[di+4],cx  ; regs.x.cx		
;		mov	[di+6],dx  ; regs.x.dx	
;		mov	[di+8],si  ; regs.x.si	
;		lahf
;		mov	al,ah
;		mov	[di+12],ax ; regs.x_cflag
;		pop	ax
;		mov	[di+10],ax ; regs.x.di	
;		pop	si
;		pop	di
;		mov	sp,bp
;		pop	bp
;		retf

; msgserv.asm (MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Proc Name:	SYSGETMSG
;;
;;  Function:	The GET service returns the segment, offset and size of the
;;		message text to the caller based on a message number.
;;		The GET function will not display the message thus assumes
;;		caller will handle replaceable parameters.
;;
;;  Inputs:
;;
;;  Outputs:
;;
;;  Psuedocode:
;;		Call $M_GET_MSG_ADDRESS
;;		IF MSG_NUM exists THEN
;;		   Set DS:SI = MSG_TXT_PTR + 1
;;		   CARRY_FLAG = 0
;;		ELSE
;;		   CARRY_FLAG = 1
;;		ENDIF
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SYSGETMSG:
		;push	ax		; Save changed regs
		;push	es
		;push	di

		push	bp

		call	_$M_GET_MSG_ADDRESS ; Scan thru classes to find message
		;jc	short $MIF31

		cmp	cx,1 ; 13/11/2018
					; Return message in ES:DI
		;;cmp	dh,0FFh ; UTILITY_MSG_CLASS
		;;clc
		;;je	short $MIF32
		;;push	es
		;;pop	ds
		;;jmp	short $MEN32
$MIF32:
		;push	es
		;pop	ds
$MEN32:
		;mov	si,di		; Return message in DS:SI	
$MIF31:
		pop	bp		; Restore changed regs

		;pop	di
		;pop	es
		;pop	ax
		;retf

		retn ; 13/11/2018

; ----------------------------------------------------------------------------
; fdparse.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 11/11/2018)

;/*  */
;/******************************************************************************/
;/*Routine name:  CHECK_DISK_VALIDITY                                          */
;/******************************************************************************/
;/*                                                                            */
;/*Description:   Checks the return buffer from parse for the positional       */
;/*               value to be equal to 0 or 1.                                 */
;/*                                                                            */
;/*Called Procedures:                                                          */
;/*                                                                            */
;/*Change History: Created        6/18/87         DRM                          */
;/*                                                                            */
;/*Input: None                                                                 */
;/*                                                                            */
;/*Output: None                                                                */
;/*                                                                            */
;/******************************************************************************/

;void check_disk_validity()

;BEGIN
;	disk_flag = (FLAG)TRUE;
;       cur_disk_buff = ((char)p_buff.p_value - 1);
;       return;
;END    

check_disk_validity:
		mov	byte [disk_flag],1
		mov	al,[p_buff_p_value]
		dec	al
		mov	[cur_disk_buff],al
		retn

;/*  */
;/******************************************************************************/
;/*Routine name:  PROCESS_SWITCH                                               */
;/******************************************************************************/
;/*                                                                            */
;/*Description:   This function looks at the return buffer of the parse and    */
;/*               determins the switch, places value in buffer, and sets       */
;/*               flag for specific switch.                                    */
;/*                                                                            */
;/*Called Procedures:                                                          */
;/*                                                                            */
;/*Change History: Created        6/18/87         DRM                          */
;/*                                                                            */
;/*Input: None                                                                 */
;/*                                                                            */
;/*Output: None                                                                */
;/*                                                                            */
;/******************************************************************************/

;void process_switch()

process_switch:
		mov	ax,[sp_buff_p_synonym] ; 11/11/2018
		mov	cl,1 ; TRUE

	; if (sp_buff.p_synonym == (unsigned)p_swi1.sp_switch1)
        ;    BEGIN
        ;     primary_flag = (FLAG)TRUE;
        ;     primary_buff = (unsigned)sp_buff.p_value;
        ;    END

		;cmp	word [sp_buff_p_synonym],p_swi1_sp_switch1
		cmp	ax,p_swi1_sp_switch1
		jne	short psw1
		;mov	byte [primary_flag],1
		mov	[primary_flag],cl
		mov	ax,[sp_buff_p_value]
		mov	[primary_buff],ax
psw1:

	; if (sp_buff.p_synonym == (unsigned)p_swi1.sp_switch2)
        ;    BEGIN
        ;     extended_flag = (FLAG)TRUE;
        ;     extended_buff = (unsigned)sp_buff.p_value;
        ;    END               

		;cmp	word [sp_buff_p_synonym],p_swi1_sp_switch2
		cmp	ax,p_swi1_sp_switch2
		jne	short psw2
		;mov	byte [extended_flag],1
		mov	[extended_flag],cl
		mov	ax,[sp_buff_p_value]
		mov	[extended_buff],ax
psw2:
		;cmp	word [sp_buff_p_synonym],p_swi1_sp_switch3
		cmp	ax,p_swi1_sp_switch3
		jne	short psw3
		;mov	byte [logical_flag],1
		mov	[logical_flag],cl
		mov	ax,[sp_buff_p_value]
		mov	[logical_buff],ax
psw3:
		;cmp	word [sp_buff_p_synonym],p_swi2_sp_switch4
		cmp	ax,p_swi2_sp_switch4
		jne	short psw4
		;mov	byte [quiet_flag],1
		mov	[quiet_flag],cl
psw4:
		;cmp	word [sp_buff_p_synonym],p_swi3_sp_switch5
		cmp	ax,p_swi3_sp_switch5
		jne	short psw5
		;mov	byte [status_flag],1
		mov	[status_flag],cl
psw5:
		;cmp	word [sp_buff_p_synonym],p_swi4_sp_switch6
		cmp	ax,p_swi4_sp_switch6
		jne	short psw6
		call	DisplayOptionsExit ; Print options then exit
		; 16/11/2018
		sub	ax,ax ; sub al,al
		jmp	_exit
psw6:

	; if (sp_buff.p_synonym == (unsigned)p_swi5.sp_switch7)
        ;    BEGIN
        ;     mbr_flag = (FLAG)TRUE;
        ;    END

		;cmp	word [sp_buff_p_synonym],p_swi5_sp_switch7
		cmp	ax,p_swi5_sp_switch7
		jne	short psw7
		;mov	byte [mbr_flag],1
		mov	[mbr_flag],cl
psw7:
		retn

; 12/11/2018

;/************************************************************************/ 
;/* DisplayOptionsExit           - Displays the options help message     */
;/*                                lines onto standard output, and then  */
;/*                                exits the program so the user can     */
;/*                                retry the command.                    */
;/*                                                                      */
;/*      Inputs  : MSG_OPTIONS_FIRST - #defined with the number of the   */
;/*                                    first message line to output.     */
;/*                MSG_OPTIONS_LAST  - #defined with the number of the   */
;/*                                    last message line to output.      */
;/*                                                                      */
;/*      Outputs : Options help lines as defined in FDISK.SKL            */
;/*                Exits to DOS                                          */
;/*                                                                      */
;/*      Date    : 04/23/90  c-PaulB                                     */
;/*      Version : DOS 5.00                                              */
;/************************************************************************/

;void DisplayOptionsExit()

;BEGIN
;	int	iMsgNbr;
;
;	/*
;	 * Display each of the options message lines.
;	 * Parse_message can't be used because it tries to display
;	 * the text of an offending command.
;	 */
;
;	for (iMsgNbr = MSG_OPTIONS_FIRST;     /* defined in parse.h */
;		iMsgNbr <= MSG_OPTIONS_LAST;
;		iMsgNbr++)
;	BEGIN
;	regs.x.ax = iMsgNbr;             /* message #     */
;       regs.x.bx = STDOUT;              /* output handle */
;       regs.x.cx = SUBCNT0;             /* # of subs     */
;       regs.h.dl = No_Input;            /* input flag    */
;       regs.h.dh = UTILITY_MSG_CLASS;   /* message class */
;       regs.x.si = 0;                   /* sub list ptr  */
;       sysdispmsg(&regs,&regs);
;	END
;
;	/*
;	 * Exit the program so the user can retry the command.
;	 */
;
;	exit(ERR_LEVEL_0);
;
;END

DisplayOptionsExit:
		; 14/11/2018 - Temporary
		cmp	byte [quiet_flag],0
		jna	short DisplayOptions

		call	print_fdisk_program_msg
		jmp	short DisplayOptions_exit
	
DisplayOptions:
		MSG_OPTIONS_FIRST equ 300
		MSG_OPTIONS_LAST  equ 302
		
		;STDOUT	 equ 1
		;SUBCNT0 equ 0	
		;No_Input equ 0
		;UTILITY_MSG_CLASS equ 0FFh
	
		%define iMsgNbr bp-2

		;push	bp
		mov	bp,sp
		sub	sp,2
		mov	word [iMsgNbr],MSG_OPTIONS_FIRST ; 300
displaynextopsrow:
		mov	ax,[iMsgNbr]		    ; /* message # */
		;mov	[regs_x_ax],ax
		;mov	word [regs_x_bx],1
		mov	bx,1  ; STDOUT		    ; /* output handle */
		;mov	word [regs_x_cx],0
		sub	cx,cx	; 0 ; SUBCNT0	    ; /* # of subs */
		;mov	byte [regs_x_dx],0
		sub	dl,dl ; 0 ; No_Input 	    ; /* input flag */
		;mov	byte [regs_x_dx+1],0FFh
		mov	dh,0FFh ; UTILITY_MSG_CLASS ; /* message class */
		;mov	word [regs_x_si],0
		sub	si,si ; 0		    ; /* sub list ptr */
		
		;mov	ax,[regs_x_ax]
		;push	ax ; outregs
		;push	ax ; inregs
		;call	sysdispmsg
		;pop	bx
		;pop	bx

		call	SYSDISPMSG  ; (msgserv.asm, MSDOS 6.0, 1991)
		
		inc	word [iMsgNbr]
		cmp	word [iMsgNbr],MSG_OPTIONS_LAST ; 302
		jle	short displaynextopsrow
		
		;sub	ax,ax
		;push	ax
		;call	_exit
		;pop	bx

		mov	sp,bp
		;pop	bp
DisplayOptions_exit:	; 16/11/2018
		retn
;DisplayOptions_exit:
;		sub	ax,ax
;		jmp	_exit

; ----------------------------------------------------------------------------
; msgserv.asm (MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for NASM (by Erdogan Tan, 12/11/2018)

; sysmsg.inc (MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------

; SYSDISPMSG and SYSGETMSG Equates

FALSE	equ 0		  ;;
TRUE	equ 1 ; NOT FALSE ;;    List message services and flags

; Control Characters For Message Skeleton file

NULL			EQU	00H    ;; Null
BELL			EQU	07H    ;; Bell
TAB			EQU	09H    ;; Tab
LF			EQU	0AH    ;; Line Feed
HOME			EQU	0BH    ;; Home
FORMFD			EQU	0CH    ;; Form Feed
CR			EQU	0DH    ;; Carriage Return
COLON			EQU	3AH    ;; Colon

MSG_SER_CLASS		EQU	00H    ;; Message Service Class (reserved)
EXT_ERR_CLASS		EQU	01H    ;; DOS Extended error class
PARSE_ERR_CLASS 	EQU	02H    ;; Parse error class
UTILITY_MSG_CLASS	EQU	0FFH   ;; Utility message class

NO_HANDLE		EQU	0FFFFH ;; No handle specified
				       ;; (Use DOS functions 01H-09H only)

NO_REPLACE		EQU	0000H  ;; No replacable parameters


; SUBLIST Equates

  Sublist_Length	EQU	11     ;; Length of sublist structure
  Reserved		EQU	0      ;; Reserved byte field

  Left_Align		EQU	0      ;;00xxxxxx
  Right_Align		EQU	80h    ;;10xxxxxx

  Char_type		EQU	0      ;;axxx0000 - Character type
  Char_Field_Char	EQU	0      ;;a0000000
  Char_Field_ASCIIZ	EQU	10h    ;;a0010000

  Unsgn_Bin_Type	EQU	01h    ;;axxx0001 - Unsigned Binary to Decimal character
  Unsgn_Bin_Byte	EQU	11h    ;;a0010001
  Unsgn_Bin_Word	EQU	21h    ;;a0100001
  Unsgn_Bin_DWord	EQU	31h    ;;a0110001

  Sgn_Bin_Type		EQU	02h    ;;axxx0010 - Signed Binary to Decimal character
  Sgn_Bin_Byte		EQU	12h    ;;a0010010
  Sgn_Bin_Word		EQU	22h    ;;a0100010
  Sgn_Bin_DWord 	EQU	32h    ;;a0110010

  Bin_Hex_Type		EQU	03h    ;;axxx0011 - Unsigned Binary to Hexidecimal character
  Bin_Hex_Byte		EQU	13h    ;;a0010011
  Bin_Hex_Word		EQU	23h    ;;a0100011
  Bin_Hex_DWord 	EQU	33h    ;;a0110011

  Date_Type		EQU	04h    ;;axxx0100 - Date to character using current country format
  Date_MD		EQU	14h    ;;a0010100
  Date_MDY_2		EQU	24h    ;;a0100100
  Date_MDY_4		EQU	34h    ;;a0110100

  Time_Cty_Type 	EQU	05h    ;;axxx0101 - Time to character using current country format
  Time_HHMM_Cty 	EQU	05h    ;;a0000101
  Time_HHMMSS_Cty	EQU	15h    ;;a0010101
  Time_HHMMSSHH_Cty	EQU	25h    ;;a0100101

  Time_24_Type		EQU	06h    ;;axxx0110 - Time to character using 24 hour format
  Time_HHMM_24		EQU	06h    ;;a0000110
  Time_HHMMSS_24	EQU	16h    ;;a0010110
  Time_HHMMSSHH_24	EQU	26h    ;;a0100110

  $M_EXTPAR_Type	EQU	08h    ;;axxx1000 - Special case for extended parse replace format

NO_INPUT		EQU	00H    ;; No input characters
DOS_KEYB_INP		EQU	01H    ;; DOS INT 21H - AH=01H := Keyboard Input
DOS_DIR_CON_INP 	EQU	07H    ;; DOS INT 21H - AH=07H := Direct Console Input Without Echo
DOS_CON_INP		EQU	08H    ;; DOS INT 21H - AH=08H := Console Input Without Echo (Check CTL-BK)
DOS_BUF_KEYB_INP	EQU	0AH    ;; DOS INT 21H - AH=0AH := Buffered Keyboard Input
DOS_CLR_KEYB_BUF	EQU	0CH    ;; DOS INT 21H - AH=0CH := Clear keyboard buffer
DOS_WRITE_HANDLE	EQU	40H    ;; DOS INT 21H - AH=40H := Write to a DOS handle
DOS_DISP_STRING 	EQU	09H    ;; DOS INT 21H - AH=09H := Display $ terminated string
DOS_DISP_CHAR		EQU	02H    ;; DOS INT 21H - AH=02H := Display Character
LOWEST_4CH_VERSION	EQU	0002H  ;; First DOS version to allow AH = 4CH Exit (VERSION 2.00)

DOS_GET_DBCS_INFO	EQU   6300H    ;; DOS INT 21H - AX=6507H := Get DBCS Vector Table
DOS_GET_EXT_ERROR	EQU	59H    ;; DOS INT 21H - AH=59H := Get Extended Error
DOS_GET_EXT_ERROR_BX	EQU	00H    ;; DOS INT 21H - BX=0000H := Version 0

DOS_EXTENDED_OPEN	EQU   6C00H    ;AN003; DOS INT 21H - AX=6C00H := Extended Open
NO_CRIT_OPEN		EQU   2000H    ;AN003; Extended Open Mode bit
NOT_EX_FAIL_EX_OPEN	EQU   0101H    ;AN003; Extended Open Flag
DOS_LSEEK_FILE		EQU   4200H    ;AN003; DOS INT 21H - AX=4200H := LSEEK file
DOS_READ_BYTE		EQU	3FH    ;AN003; DOS INT 21H - AH=3FH   := Read byte block
DOS_CLOSE_FILE		EQU	3EH    ;AN003; DOS INT 21H - AH=3EH   := Close file handle

IFSFUNC_INSTALL_CHECK	EQU   0500H    ;AN006; IFSFUNC Installation Check
IFS_GET_ERR_TEXT	EQU   0502H    ;AN006; IFSFUNC Get Extended Error Text
IFSFUNC_INSTALLED	EQU    0FFH    ;AN006; Return code if IFSFUNC is installed

EXT_ERR_39		EQU	39     ;; Insufficent Disk Space EXTENDED ERROR (changed from hex to decimal - eg d201)
ERROR_CLASS_39		EQU	01H    ;;   Error Class = 1
ACTION_39		EQU	04H    ;;   Suggested Action = 4
LOCUS_39		EQU	01H    ;;   Locus = 1

DOS_GET_COUNTRY 	EQU	38H    ;; DOS INT 21H - AH=38H := Get Country Dependant Information
DOS_GET_VERSION 	EQU	30H    ;; DOS INT 21H - AH=30H := Get DOS Version number
DOS_IOCTL_GET_INFO	EQU	4400H  ;; DOS INT 21H - AH=4400H := I/O control for devices
DOS_IOCTL_SET_INFO	EQU	4401H  ;; DOS INT 21H - AH=4401H := I/O control for devices
DOS_GET_EXT_PARSE_ADD	EQU	122EH  ;; DOS INT 2FH - AX=122EH := Get Extended/Parse error address
DOS_GET_EXTENDED	EQU	00     ;; DOS INT 2FH - AX=122EH - DL=00 := Get Extended address
DOS_GET_PARSE		EQU	02     ;; DOS INT 2FH - AX=122EH - DL=02 := Get Parse address
DOS_GET_CRITICAL	EQU	04     ;; DOS INT 2FH - AX=122EH - DL=04 := Get Critical address
DOS_GET_FILE		EQU	06     ;; DOS INT 2FH - AX=122EH - DL=06 := Get File system dependant
DOS_GET_ADDR		EQU	08     ;; DOS INT 2FH - AX=122EH - DL=08 := Get Address of READ_DISK_PROC
DOS_SET_ADDR		EQU	09     ;; DOS INT 2FH - AX=122EH - DL=09 := Set Address of READ_DISK_PROC
LOW_NIB_MASK		EQU	0FH    ;; Mask out the high byte
DOS_CLR_KEYB_BUF_MASK	EQU	0C0H   ;; Check if high nibble is C Hex
$M_CON_INP		EQU	-1     ;; If DOS INT 21H Function 06H - DL := 0FFH for input
$M_CRIT_LO		EQU	19     ;; First Extended Error considered CRITICAL
$M_CRIT_HI		EQU	39     ;; Last Extended Error considered CRITICAL (EG - D191)
$M_AM			EQU	"a"    ;; Time format AM indicator
$M_PM			EQU	"p"    ;; Time format PM indicator
$M_NEG_SIGN		EQU	"-"    ;; Signed decimal number format negative indicator
$M_DEF_TIME_FORM	EQU	 1     ;; Default Time format - 24 hour
$M_DEF_DATE_FORM	EQU	 0     ;; Default Time format - 0 := USA format
$M_DEF_TIME_SEP 	EQU	":"    ;; Default Time separator - ":"
$M_DEF_DATE_SEP 	EQU	"-"    ;; Default Time separator - "-"
$M_DEF_DECI_SEP 	EQU	"."    ;; Default Time hundreds separator - "."
$M_TIMEDATE_PAD 	EQU	"0"    ;; Time/Date PAD character - "0" (ie 12:03p)
$M_MAX_2_YEAR		EQU	99     ;; Maximum 2 digit year
$M_SINGLE_CHAR		EQU	1      ;; A single character is this long      ^
$M_SPECIAL_CASE 	EQU	30H    ;; Special case for replacable parameters %0
$M_UNLIM_W		EQU	0      ;; Unlimited width character
$M_COMMA		EQU	","    ;; Default Thousand separate
$M_CR_LF		EQU	0A0DH  ;; Default CR/LF
$M_SPACE_HYP		EQU	"- "   ;; Default Space/Hyphan
$M_SPACE		EQU	" "    ;; Default Space
$M_NULL 		EQU	0      ;; Null
$M_FIRST_THOU		EQU	3      ;; Location of first thousand separator
$M_SECOND_THOU		EQU	6      ;; Location of second thousand separator
$M_THIRD_THOU		EQU	9      ;; Location of third thousand separator
$M_BASE10		EQU	10     ;; Base 10 for arthmetic
$M_BASE16		EQU	16     ;; Base 16 for arthmetic
$M_CLASS_NOT_EXIST	EQU	 0     ;; Does class exist?
$M_TERMINATING_FLAG	EQU	-1     ;; Is there any more classes?
$M_ADDR_SZ_NEAR 	EQU	2      ;; Size to increment if NEAR
$M_ADDR_SZ_FAR		EQU	4      ;; Size to increment if FAR
;$M_SL			EQU   DS:[SI]  ;; Refer to SUBLIST as $M_SL
%define	$M_SL [SI] ; 13/11/2018	
$M_NO_HANDLE		EQU	-1     ;; No handle flag
$M_TEMP_BUF_SZ		EQU	64     ;; Size of temporary buffer	 ;AN003;
$M_NEXT_DBCS_VECTOR	EQU	2      ;; Amount to increment to get next vector
$M_DBCS_TERM		EQU    0000    ;; DBCS vector table terminating flag
$M_SPECIAL_MSG_NUM	EQU    0FFFFH  ;; Special generic message number
$M_CRLF_SIZE		EQU    2       ;; Size of the CR LF message
$M_NO_CRLF_MASK 	EQU  10000000B ;; Mask to supress CR LF
$M_ONE_REPLACE		EQU    1       ;; Indicate one replacement
$M_CRIT_ERR_MASK	EQU  00000001B ;; Mask to allow EOF/EOI Crit error
				       ;;
$M_ALIGN_MASK		EQU  10000000b ;; Mask for align
$M_TYPE_MASK		EQU  00001111b ;; Mask for types
$M_SIZE_MASK		EQU  00110000b ;; Mask for types
$M_TIME_MASK		EQU  00000001b ;; Mask for TIME
$M_DATE_MASK		EQU  00010000b ;; Mask for TIME
$M_BYTE 		EQU  00010000b ;; BYTE indicator
$M_WORD 		EQU  00100000b ;; WORD indicator
$M_DWORD		EQU  00110000b ;; DWORD indicator

; Standard reserved DOS handles

_STDIN			EQU	0000H  ;; Standard Input device handle
_STDOUT			EQU	0001H  ;; Standard Output device handle
_STDERR			EQU	0002H  ;; Standard Error Output device handle
_STDAUX			EQU	0003H  ;; Standard Auxiliary device handle
_STDPRN			EQU	0004H  ;; Standard Printer device handle

; msghan.inc (MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------

; VALUES FOR THE MSG_DESC CONTROL BLOCK
ONE_SUBS       EQU   1		   	; ONE VARIABLE FIELD IN MESSAGE
TWO_SUBS       EQU   2		   	; TWO VARIABLE FIELDS IN MESSAGE
THREE_SUBS     EQU   3		   	; THREE VARIABLE FIELDS IN MESSAGE
CLASS_1        EQU   EXT_ERR_CLASS 	; CLASS 1 (DOS EXTENDED ERRORS)
CLASS_2        EQU   PARSE_ERR_CLASS 	; CLASS 2 (PARSE ERRORS)
CLASS_A        EQU   UTILITY_MSG_CLASS	; CLASS A TYPE MESSAGE

;THIS MESSAGE DESCRIPTOR CONTROL BLOCK IS GENERATED, ONE PER MESSAGE,
;TO DEFINE THE SEVERAL PARAMETERS THAT ARE EXPECTED TO BE PASSED IN
;CERTAIN REGISTERS WHEN THE SYSDISPMSG FUNCTION IS TO BE INVOKED.

struc MSG_DESC
.MSG_NUM :	resw	0	   	; MESSAGE NUMBER (TO AX)
.MSG_HANDLE:	resw	_STDOUT	   	; HANDLE OF OUTPUT DEVICE (TO BX)
.MSG_SUBLIST:	resw	0	   	; POINTER TO SUBLIST (TO SI)
.MSG_COUNT:	resw	0	   	; SUBSTITUTION COUNT (TO CX)
.MSG_CLASS:	resw	CLASS_A << 8	; MESSAGE CLASS (IN HIGH BYTE, TO DH)
.size:				   	; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL)
endstruc

; VALUES FOR THE SUBLIST CONTROL BLOCK
PC_ID_0        EQU   0		   ; ID OF " - " TRAILER TO MESSAGE
PC_ID_1        EQU   1		   ; ID OF PERCENT VARIABLE FIELD
PC_ID_2        EQU   2		   ; ID OF PERCENT VARIABLE FIELD
PC_ID_3        EQU   3		   ; ID OF PERCENT VARIABLE FIELD
MAX_0	       EQU   0		   ; MAXIMUM WIDTH OF STRING FIELD (0=NO LIMIT)
MIN_1	       EQU   1		   ; MINIMUM WIDTH OF STRING FIELD
PAD_BLK        EQU   " "           ; CHAR FOR PAD FIELD
FILL_OFF       EQU   0		   ; TO BE REPLACED WITH ACTUAL OFFSET
FILL_SEG       EQU   0		   ; TO BE REPLACED WITH ACTUAL SEG ID

struc SUBLIST
.SUB_SIZE:	resb 1 ;11	; SUBLIST SIZE (POINTER TO NEXT SUBLIST)
.SUB_RES:	resb 1 ;0	; RESERVED
				; NEXT FIELD IS TO BE USED AS A DOUBLE WORD
.SUB_VALUE:	resw 1 ;0	; TIME, DATE, OR PTR TO DATA ITEM
.SUB_VALUE_SEG:	resw 1 ;0	; SEG ID OF PTR
				; (ABOVE FIELD MUST BE FILLED AT EXECUTION TIME
				; IF THIS IS A .COM FILE)
.SUB_ID:	resb 1 ;0	; N OF %N
.SUB_FLAGS:	resb 1 ;0	; DATA TYPE FLAGS
.SUB_MAX_WIDTH:	resb 1 ;MAX_0	; MAXIMUM FIELD WIDTH (0=UNLIMITED)
.SUB_MIN_WIDTH:	resb 1 ;0	; MINIMUM FIELD WIDTH
.SUB_PAD_CHAR:	resb 1 ;PAD_BLK ; CHARACTER FOR PAD FIELD
.size:				; CAN BE " ", "0" OR ",".
endstruc			; "," CAUSES INSERTION OF THE ACTIVE
				; THOUSANDS SEPARATOR BETWEEN EVERY 3 DIGITS.

;		  BITS DEFINED FOR SUB_FLAGS ABOVE
;			FORMAT = A0SSTTTT
;				 ++ + +--- FIELD TYPE
;				 || +--- DATA VARIABLE SIZE
;				 |+--- RESERVED, MUST BE ZERO
;				 +--- ALIGNMENT INDICATOR
;SF_BITS     RECORD F_ALIGN:1,F_RES:1=0,F_SIZE:2,F_TYPE:4

;		F_ALIGN FIELD, ALIGNMENT INDICATOR
SF_LEFT 	  EQU	0	   ;AN000;LEFT ALIGN
SF_RIGHT	  EQU	1	   ;AN000;RIGHT ALIGN

;		F_RES FIELD, RESERVED, SHOULD BE ZERO

;		F_TYPE FIELD, FIELD TYPE
SF_CHAR 	  EQU	0000B	   ;AN000;TYPE IS CHARACTER
;		F_SIZE FIELD,
SF_CH		  EQU	00B	   ;AN000;SINGLE CHARACTER
SF_ASCIIZ	  EQU	01B	   ;AN000;ASCIIZ STRING

;		F_TYPE FIELD, FIELD TYPE
SF_UN_BD	  EQU	0001B	   ;AN000;UNSIGNED BINARY TO DECIMAL CHARACTER
;		F_SIZE FIELD,
SF_BYTE 	  EQU	01B	   ;AN000;DATA IS BYTE SIZED
SF_WORD 	  EQU	10B	   ;AN000;DATA IS WORD SIZED
SF_DWORD	  EQU	11B	   ;AN000;DATA IS DOUBLE WORD SIZED

;		F_TYPE FIELD, FIELD TYPE
SF_SIN_BD	  EQU	0010B	   ;AN000;SIGNED BINARY TO DECIMAL CHARACTER
;		F_SIZE FIELD,
;SF_BYTE	  EQU	01B	   ;DATA IS BYTE SIZED
;SF_WORD	  EQU	10B	   ;DATA IS WORD SIZED
;SF_DWORD	  EQU	11B	   ;DATA IS DOUBLE WORD SIZED

;		F_TYPE FIELD, FIELD TYPE
SF_UN_BH	  EQU	0011B	   ;AN000;UNSIGNED BINARY TO HEXADECIMAL CHARACTER
;		F_SIZE FIELD,
;SF_BYTE	  EQU	01B	   ;DATA IS BYTE SIZED
;SF_WORD	  EQU	10B	   ;DATA IS WORD SIZED
;SF_DWORD	  EQU	11B	   ;DATA IS DOUBLE WORD SIZED

;		F_TYPE FIELD, FIELD TYPE
SF_DATE 	  EQU	0100B	   ;AN000;DATE TO CHARACTER,
				   ; USING CURRENT COUNTRY FORMAT
				   ;SUB_VALUE HIGH=YEAR
				   ;SUB_VALUE LOW=MMDD
;		F_SIZE FIELD,
SF_MD		  EQU	01B	   ;AN000;MONTH AND DAY ONLY
SF_MDY2 	  EQU	10B	   ;AN000;MONTH,DAY AND YEAR (2 DIGITS)
SF_MDY4 	  EQU	11B	   ;AN000;MONTH,DAY AND YEAR (4 DIGITS)

;		F_TYPE FIELD, FIELD TYPE
SF_TIME_12	  EQU	0101B	   ;AN000;TIME TO CHARACTER, 12 HOUR FORMAT
				   ; USING CURRENT COUNTRY FORMAT
				   ;SUB_VALUE HIGH=HHMM
				   ;SUB_VALUE LOW=SSHH
;		F_SIZE FIELD,
SF_HHMM 	  EQU	00B	   ;AN000;HH:MM (ACTIVE TIME FORMAT)
SF_HHMMSS	  EQU	01B	   ;AN000;HH:MM:SS (ACTIVE TIME FORMAT)
SF_HHMMSSHH	  EQU	10B	   ;AN000;HH:MM:SS:HH

;		F_TYPE FIELD, FIELD TYPE
SF_TIME_24	  EQU	0110B	   ;AN000;TIME TO CHARACTER, 24 HOUR FORMAT
				   ; USING CURRENT COUNTRY FORMAT
				   ;SUB_VALUE HIGH=HHMM
				   ;SUB_VALUE LOW=SSHH
;		F_SIZE FIELD,
;SF_HHMM	  EQU	00B	   ;HH:MM (ACTIVE TIME FORMAT)
;SF_HHMMSS	  EQU	01B	   ;HH:MM:SS (ACTIVE TIME FORMAT)
;SF_HHMMSSHH	  EQU	10B	   ;HH:MM:SS:HH

;		THE NEXT GROUP ARE ALL CLASS "1" MESSAGES

;		PUBLIC MSGNUM_EXTERR;AN000;
;MSGNUM_EXTERR  MSG_DESC <,STDERR,,,CLASS_1 SHL 8> ; ALL EXTENDED DOS ERRORS
;				   ; ERROR NUMBER WILL NEED TO BE FILLED IN

;		THE NEXT GROUP ARE ALL CLASS "2" MESSAGES

;		PUBLIC MSGNUM_PARSE ; SO PARSE DRIVER CAN FIND IT
;MSGNUM_PARSE   MSG_DESC <,STDERR,,,CLASS_2 SHL 8> ; ALL PARSING ERRORS
;				   ; ERROR NUMBER WILL NEED TO BE FILLED IN

;		THE NEXT GROUP ARE ALL CLASS "A" MESSAGES
;		THESE ARE THE "CANNED" MESSAGES ALWAYS PRESENT

;		PUBLIC MSGNUM_VER   ;
;MSGNUM_VER	MSG_DESC <1,STDERR> ; "Incorrect DOS Version"

; msgserv.asm (MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  Proc Name:	SYSDISPMSG
;;
;;  Function:	The DISPLAY service will output a defined message to a handle
;;		requested by the caller. It also provides function to display
;;		messages when handles are not applicable (ie. DOS function calls
;;		00h to 0Ah) Replaceable parameters are allowed and are
;;		defined previous to entry.
;;
;;		It is assumes that a PRELOAD function has already determined
;;		the addressibilty internally to the message retriever services.
;;  Inputs:
;;
;;  Outputs:
;;
;;  Psuedocode:
;;		Save registers needed later
;;		Get address of the message requested
;;		IF Message number exists THEN
;;		  IF replacable parameters were specified THEN
;;		     Display message with replacable parms
;;		  ELSE
;;		     Display string without replacable parms
;;		  ENDIF
;;		  IF character input was requested THEN
;;		     Wait for character input
;;		  ENDIF
;;		  Clear CARRY FLAG
;;		ELSE
;;		   Set CARRY FLAG
;;		ENDIF
;;		Return
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Input:
; AX = MSG_DESC.MSG_NUM		; MESSAGE NUMBER
; BX = MSG_DESC.MSG_HANDLE	; HANDLE OF OUTPUT DEVICE
; CX = MSG_DESC.MSG_COUNT	; SUBSTITUTION COUNT
; SI = MSG_DESC.MSG_SUBLIST	; POINTER TO SUBLIST
; DH = MSG_DESC.MSG_CLASS	; MESSAGE CLASS
; DL = 0

SYSDISPMSG:
		push	es	; Save registers and values needed later
		push	bp
		;push	dx		

		mov	bp,cx		; Use BP to hold replace count

		mov	[$M_HANDLE],bx	; Save handle
		mov	[$M_CLASS],dh	; Save class

		; Get address of the message requested
		call	_$M_GET_MSG_ADDRESS

		cmp	cx,1		; Was message found?
		;jb	short $MEN94	; NO
		jb	short $MIF104 	; CF = 1
				
					; YES, Message address in ES:DI

		; Test if replacable parameters were specified
		or	bp,bp		; Were replacable parameters requested		
		jnz	short $MIF94

		; Display string without replacable parms
		call	_$M_DISPLAY_STRING ; No, great . . . Display message
		jmp	short $MEN94
$MIF94:
		; Display message with replacable parms		
		call	_$M_DISPLAY_MESSAGE
$MEN94:
		;pop	dx		; Get Input/Class request
		jc	short $MIF104

		mov	dh,[$M_CLASS]	; Restore class

		call	_$M_ADD_CRLF	; Check if we need to add the CR LF chars.
$MIF104:
		pop	bp
		pop	es

		;retf
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_GET_MSG_ADDRESS
;;
;;	FUNCTION:  To scan thru classes to return pointer to the message header
;;	INPUTS:    Access to $M_RES_ADDRESSES
;;	OUTPUTS:   IF CX = 0 THEN Message was not found
;;		   IF CX > 1 THEN ES:DI points to the specified message
;;	REGS CHANGED: ES,DI,CX
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_GET_MSG_ADDRESS:
		push	si
		push	bx
		xor	si,si		; Use SI as an index
		xor	cx,cx		; Use CX as an size
$MDO36:
		cmp	dh,0FFh	 ; UTILITY_MSG_CLASS ; Were utility messages requested?
		jne	short $MIF37	; No,
		les	di,[$M_CLASS_A_ADDRS+si] ; Yes, get address of class	
		mov	bx,es
		jmp	short $MEN37
$MIF37:
		test	dh,2	; PARSE_ERR_CLASS ; Were parse errors requested?
		jz	short $MIF39	; No, extended errors were specified
						 ; Yes
		les	di,[$M_PARSE_COMMAND+si] ; Get address of class
		mov	bx,es
		jmp	short $MEN37
$MIF39:
		cmp	ax,13h ; $M_CRIT_LO	; Is this a critical error?
		jb	short $MIF41	; No,
		cmp	ax,27h ; $M_CRIT_HI
		ja	short $MIF41	; No,
						; Yes, (extended errors considered critical)
		les	di,[$M_CRIT_ADDRS+si]	; Get address of class
		mov	bx,es
		jmp	short $MEN37
$MIF41:					; Extended Errors
		les	di,[$M_EXT_ERR_ADDRS+si] ; Get address of class
		mov	bx,es
$MEN37:
		cmp	bx,0FFFFh ; $M_TERMINATING_FLAG	; Are we finished all classes?
		jne	short $MIF46	; No,
						; Yes,
		cmp	dh,0FFh	; UTILITY_MSG_CLASS ; Was it a UTILITY class?
		jne	short $MIF47	; No,
		stc				; Yes, set the carry flag
		;jmp	short $MEN47
		jmp	short $MEN36 ; 13/11/2018
		
$MIF47:
		mov	[$M_MSG_NUM],ax		; Save message number
		mov	ax,0FFFFh ; $M_SPECIAL_MSG_NUM	; Set special message number
		mov	bp,1  ; $M_ONE_REPLACE	; Set one replace in message
		xor	si,si			; Reset the SI index to start again
		clc
$MEN47:
		;jmp	short $MEN46
		jmp	short $MIF49 ; 13/11/2018
$MIF46:
		cmp	bx,0 ; $M_CLASS_NOT_EXIST ; Does this class exist?	
		je	short $MIF51	; No,
						; Yes,	
		call	_$M_FIND_SPECIFIED_MSG	; Try to find the message 
$MIF51:
		add	si,4 ; $M_ADDR_SZ_FAR	; Get next class
		clc
;$MEN46:
		;jc	short $MEN36
$MIF49: ; 13/11/2018
		or	cx,cx			; Was the message found?
		;jnz	short $MEN36		; Yes,
		;jmp	short $MDO36
		jz	short $MDO36 ; 13/11/2018 ; No,
$MEN36:
		pushf	 ; not necessary ; * 	; Save the flag state
		cmp	dh,1 ; EXT_ERR_CLASS	; Was an extended error requested?
		jne	short $MIF56
		push	dx		; Save all needed registers
		push	bp
		push	cx
		push	es
		push	di
		push	ax
		mov	ax,0500h	; Check if IFSFUNC is installed
		int	2Fh	; Multiplex - DOS 3+ CRITICAL ERROR HANDLER - INSTALLATION CHECK
				; Return: AL = 00h not installed, OK to	install
				; 01h not installed, can't install
				; FFh installed
		cmp	al,0FFh		; Is it installed?
		pop	ax		; Restore msg number
		;jne	short $MIF57	; No,
		jb	short $MEN58 ; 13/11/2018 ; cf = 1
					; Yes,
		xchg	ax, bx		; BX is the extended error number
		mov	ax,0502h	; AX is the multiplex number
					; Call IFSFUNC	
		int	2Fh	; Multiplex - DOS 3+ CRITICAL ERROR HANDLER -
		;jmp	short $MEN57
;$MIF57:
;		stc
;$MEN57:				; Was there an update?
		jnc	short $MIF60	; No,
$MEN58: ; 13/11/2018		
		pop	di		; Restore old pointer
		pop	es
		pop	cx
		jmp	short $MEN60
$MIF60:
		add	sp,6		; Throw away old pointer
		call	_$M_SET_LEN_IN_CX ; Get the length of the ASCIIZ string
$MEN60:
		pop	bp		; Restore other Regs
		pop	dx
$MIF56:
;		jmp	short _$M_POPF
;_$M_MYRET:
;		iret

		; 12/11/2018

		popf		; * ; not necessary

		pop	bx 	; *
		pop	si	; *
		retn		; *

;_$M_POPF:				; Restore the flag state
		;push	cs
		;call	_$M_MYRET
		;pop	bx
		;pop	si

		;;retf
		;retn

;_$M_MYRET:	iret
		
; ----------------------------------------------------------------------------
		
				; Get the length of the ASCIIZ string
_$M_SET_LEN_IN_CX:			;
		push	di		; Save position
		push	ax		;
		mov	cx,-1		; Set CX for decrements
		xor	al,al		; Prepare compare register
		repne scasb		; Scan for zero
		not	cx		; Change decrement into number
		dec	cx		; Don't include the zero
		pop	ax		;
		pop	di		; Restore position
		retn			;

; ----------------------------------------------------------------------------

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_FIND_SPECIFIED_MSG
;;
;;	FUNCTION:  To scan thru message headers until message is found
;;	INPUTS:    ES:DI points to beginning of msg headers
;;		   CX contains the number of messages in class
;;		   DH contains the message class
;;	OUPUTS:    IF CX = 0 THEN Message was not found
;;		   IF CX > 1 THEN ES:DI points to header of specified message
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_FIND_SPECIFIED_MSG:
		cmp	bx,1		; Do we have an address to CALL?
		jne	short $MIF64
					; Do we have an address to CALL?
		cmp	word [$M_DISK_PROC_ADDR], -1 ; 0FFFFh
		je	short $MIF64
					; Yes
				; Are we displaying a default Ext Err?
		cmp	ax,0FFFFh ; $M_SPECIAL_MSG_NUM
		jne	short $MIF65	 ;No

		push	ax		; Reset the special message number
		mov	ax,[$M_MSG_NUM] ; Get the old message number
				 ; Call the READ_DISK_PROC to get error text	
		call	far [$M_DISK_PROC_ADDR]
		pop	ax		; Reset the special message number
		jmp	short $MEN65
$MIF65:
		;CALL	DWORD PTR $M_RT.$M_DISK_PROC_ADDR
					; Call the READ_DISK_PROC to get error text 
		call	far [$M_DISK_PROC_ADDR]
$MEN65:
		;jmp	short $MEN64
		jnc	short $MIF88	; *
		; cf = 1
		jmp	short $MDO76	; *	
$MIF64:
		xor	cx,cx		; CX = 0 will allow us to
		cmp	dh,0FFh ; UTILITY_MSG_CLASS
		je	short $MIF69
		;MOV	CL,BYTE PTR ES:[DI].$M_NUM_CLS_MSG 
		mov	cl,[es:di+3]	; Get number of messages in class
		jmp	short $MEN69
$MIF69:
		;CMP	BYTE PTR ES:[DI].$M_CLASS_ID,DH
		cmp	[es:di],dh	; Check if class still exists at
		jne	short $MEN69
					; pointer (hopefully)
		;MOV	CL,BYTE PTR ES:[DI].$M_NUM_CLS_MSG
		mov	cl,[es:di+3]	; Get number of messages in class
$MEN69:
					;  go on to the next class
		add	di,4 ; $M_CLASS_ID_SZ ; Point past the class header
		;stc			; Flag that we haven't found anything yet
		
		;jmp	short $MDO76 	; *
;$MEN64:
		;;jnc	short $MIF86	; Have we found anything yet?
		
		;jnc	short $MIF88	; *	
		
		;;clc			; No, reset carry
$MDO76:
		or	cx,cx		; Do we have any to check?
		;jz	short $MEN76	; No, return with CX = 0
		
		jz	short $MIF91 	; *
		
		;cmp	dh,0FFh	; UTILITY_MSG_CLASS
		;je	short $MIF78

		;;CMP	AX,WORD PTR ES:[DI].$M_NUM
		;cmp	ax,[es:di]	; Is this the message requested?
		;jmp	short $MEN78
;$MIF78:
		cmp	ax,[es:di]	; Is this the message requested?
;$MEN78:
		;jne	short $MIF76
		;jmp	short $MSR76
		je	short $MSR77	; *
;$MIF76:
		dec	cx		; No, well do we have more to check?	
		;jz	short $MEN76
		jz	short $MIF91	; * ; No, return with CX = 0	
		add	di,4		    ; Yes, skip past msg header
		jmp	short $MDO76
;$MEN76:
		;stc
		;jmp	short $MIF86	; *
;$MSR76:
;		jc	short $MIF86
$MSR77: 				; *
		;cmp	dh,0FFh
		;clc
		;jnz	short $+2  ; $MIF87
;$MIF87:
		;ADD	DI,WORD PTR ES:[DI].$M_TXT_PTR
		add	di,[es:di+2]	; Prepare ES:DI pointing to the message
;$MIF86:
;		jc	short $MIF91	; Did we find the message?
$MIF88:					; *
		xor	ch,ch
		mov	cl,[es:di]	; Move size into CX
		inc	di		; Increment past length
$MIF91:
		mov	byte [$M_SIZE],0 ; Reset variable	
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_DISPLAY_MESSAGE
;;
;;	FUNCTION:  Will display or write entire message (with replacable parameters)
;;	INPUTS:    ES:DI points to beginning of message
;;		   DS:SI points to first sublist structure in chain
;;		   BX contains the handle to write to (if applicable)
;;		   CX contains the length of string to write (before substitutions)
;;		   BP contains the count of replacables
;;
;;	OUTPUTS:
;;	REGS USED: All
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_DISPLAY_MESSAGE:
					; Note: DS:SI -> message
$MDO165:
		xor	dx,dx		; Set size = 0
		or	cx,cx
		jz	short $MEN167

		;mov	ah,"%" ; 25h	; Prepare to scan for %
	    	;mov	al,0
		mov	ax,2500h

$MDO167:				; Scan through string until %
		cmp	[es:di],ah	; Is this character NOT a %
		jne	short $MLL168	; No,
		cmp	[es:di+1],ah	; Is the next character also a %
		je	short $MLL168	; Yes,
		cmp	al,ah		; Was the character before a %
		jne	short $MEN167	; No, GREAT found it
$MLL168:
		mov	al,[es:di]	; Yes, (to any of the above)
		call	_$M_IS_IT_DBCS	; Is this character the first part of a DBCS?
		jnc	short $MIF169	; No,
					; Yes,
		inc	di		; Increment past second part
$MIF169:
		inc	di		; Next character in string
		inc	dx		; Size = Size + 1
		
		;dec	cx		; Decrement total size
		;jnz	short $MDO167		
		
		loop	$MDO167		
					; Exit scan if we're at the end of the line
$MEN167:
		push	si		; Save beginning of sublists
		xchg	cx,dx		; Get size of message to display (tot sz in DX)
		or	bp,bp		; Do we have any replacables to do?
		jz	short $MSR175	; No,
					; Yes,
		dec	bp		; Decrement number of replacables

	; Search through sublists to find applicable one

		cmp	word [$M_MSG_NUM],0 ;$M_NULL ; Is this an Extended/Parse case
		jne	short $MSR175	; No,	
$MDO175:				; Yes,
		;MOV	AL,$M_SL.$M_S_ID
		mov	al,[si+6] ; $M_S_ID ; Get ID byte
		add	al,'0'		; Convert to ASCII
		cmp	al,[es:di+1]	; Is this the right sublist?
		jne	short $MIF175	; No,
		jmp	short $MSR175	; Yes,
$MIF175:
		cmp	al,'0' ; $M_SPECIAL_CASE ; Does this sublist have ID = 0
		jne	short $MLL178	; No,
					; Yes,
		or	dx,dx		; Are we at the end of the message?
		jz	short $MEN175	; No,
$MLL178:
		add	si,[si]
		jmp	short $MDO175
$MEN175:
		;CMP	$M_RT.$M_CLASS,UTILITY_MSG_CLASS
		cmp	byte [$M_CLASS],0FFh ; Is it a utility message?
		jne	short $MIF180	; No,
					; Yes,
		inc	dx		; Remember to display CR,LF
		inc	dx		;   at the end of the message
		dec	cx		; Adjust message length
		dec	cx
		dec	di		; Adjust ending address of message
		dec	di
		jmp	short $MSR175
$MIF180:
		mov	dx,-1		; Set special case

	; Prepare and display this part of message
$MSR175:
		push	di		; Save pointer to replace number
		sub	di,cx		; Determine beginning of string
		call	_$M_DISPLAY_STRING ; Display string until % (or end)
		pop	di		; Get back pointer to replace number
		pop	cx		; Clean up stack in case error
		jnc	short $MXL3
					; Fail if carry was set
		jmp	$MEN165
$MXL3:
		push	cx
		mov	cx,dx		; Get the size of the rest of the message
		;CMP	$M_SL.$M_S_ID,$M_SPECIAL_CASE-30H
		cmp	byte [si+6],0	; Is this the %0 case?
		je	short $MIF187	; Yes,
					; No,
		or	cx,cx		; Are we finished the whole message?
		jz	short $MIF188	; Yes
					; No,
		dec	cx		; Decrement total size (%)
		dec	cx		; Decrement total size (#)
		inc	di		; Go past %
		inc	di		; Go past replace number
		jmp	short $MEN188	; (Note this will not leave because INC)
$MIF188:
		pop	si		; Get back pointer to beginning of SUBLISTs
$MEN188:				; 
		jmp	short $MEN187	; (Note this will not leave because INC)
$MIF187:
		or	cx,cx		; Are we finished the whole message?
		jnz	short $MIF192	; No,
		pop	si
		jmp	short $MEN187
$MIF192:
		cmp	cx,-1 ; 0FFFFh	; Are we at the end of the message?
		jne	short $MIF194	; No,
		xor	cx,cx
$MIF194:
		or	di,di		; Turn ZF off
$MEN187:
		jz	short $MEN165
		push	bp		; Save the replace count
		push	di
		push	es
		push	cx		; Save size of the rest of the message
		xor	cx,cx		; Reset CX used for character count

	; Determine what action is required on parameter

		;CMP	$M_RT.$M_MSG_NUM,$M_NULL
		cmp	word [$M_MSG_NUM],0  ; Is this an Extended/Parse case
		jne	short $MIF199
		
		;TEST	BYTE PTR $M_SL.$M_S_FLAG,NOT Char_Type AND $M_TYPE_MASK
		test	byte [si+7],0Fh
		jnz	short $MIF200

	; Character type requested

		;LES	DI,DWORD PTR $M_SL.$M_S_VALUE
		les	di,[si+2]	; Load pointer to replacing parameter
		call	_$M_CHAR_REPLACE
		jmp	short $MIF202
$MIF200:
		;TEST	BYTE PTR $M_SL.$M_S_FLAG,NOT Sgn_Bin_Type AND $M_TYPE_MASK
		test	byte [si+7],0Dh
		jz	short $MLL202

		;TEST	BYTE PTR $M_SL.$M_S_FLAG,NOT Unsgn_Bin_Type AND $M_TYPE_MASK
		test	byte [si+7],0Eh
		jz	short $MLL202

		;TEST 	BYTE PTR $M_SL.$M_S_FLAG,NOT Bin_Hex_Type AND $M_TYPE_MASK
		test	byte [si+7],0Ch
		jnz	short $MIF202

	; Numeric type requested
$MLL202:
		;LES	DI,DWORD PTR $M_SL.$M_S_VALUE
		les	di,[si+2]
		call	_$M_BIN2ASC_REPLACE
		;jmp	short $+2
$MIF202:
	; With the replace information of the Stack, display the replaceable field

		call	_$M_DISPLAY_REPLACE	; Display the replace
		jmp	short $MEN199
$MIF199:
	; None of the above - Extended/Parse replace

		call	_$M_EXT_PAR_REPLACE
$MEN199:
	; We must go back and complete the message after the replacable parameter
	;   if there is any left

		jc	short $MIF211 ; IF there was an error displaying then EXIT
		pop	cx	; Get size of the rest of the message
		pop	es	; Get address of the rest of the message
		pop	di
		pop	bp	; Get replacment count
		pop	si	; ELSE get address of first sublist structure
		jmp	short $MEN211
$MIF211:
		add	sp,10	; Clean up stack if error
		stc
		jmp	short $MEN165
$MEN211:
		;CMP	$M_RT.$M_MSG_NUM,$M_NULL
		cmp	word [$M_MSG_NUM],0 ; Is this an Extended/Parse case
		jne	short $MEN165 
		;jb	short $MEN165
				; Go back and display the rest of the message
		jmp	_$M_DISPLAY_MESSAGE
$MEN165:
		mov	word [$M_MSG_NUM],0 ; Reset message number to null
		retn			    ; then Return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_EXT_PAR_REPLACE
;;
;;	FUNCTION:
;;	INPUTS:
;;	OUPUTS:
;;
;;	REGS USED:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_EXT_PAR_REPLACE:
		xor	dx,dx		; Prepare for get binary value (HIGH)
		mov	ax,[$M_MSG_NUM]	; Prepare for get binary value (LOW)
		mov	word [$M_DIVISOR],10 ; Set default divisor
		call	_$M_CONVERT2ASC
		; cx = number of characters
		; bx = 0
$MDO215:
		pop	ax		; Get character in register
					; Move char into the buffer
		mov	[$M_TEMP_BUF+bx],al ; "$$$$$$$"
		inc	bx		; Increase buffer count
		cmp	bx,64 ; $M_TEMP_BUF_SZ	; Is buffer full?
		jne	short $MIF216
					; Yes,
		call	_$M_FLUSH_BUF	; Flush the buffer
		; bx = 0
$MIF216:
		dec	cl		; Have we completed replace?
		jnz	short $MDO215	; No, get next char from stack
		mov	ax,0A0Dh ; $M_CR_LF ; Move char into the buffer	
		mov	[$M_TEMP_BUF+bx],ax ; "$$$$$$$"
		inc	bx		; Increase buffer count
		inc	bx
		call	_$M_FLUSH_BUF	; Flush the buffer
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_DISPLAY_REPLACE
;;
;;	FUNCTION:
;;	INPUTS:
;;	OUPUTS:
;;
;;	REGS USED:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_DISPLAY_REPLACE:
		xor	bx,bx
			 ; Is this the special case (convert to ASCII)
		;CMP	$M_SL.$M_S_ID,$M_SPECIAL_CASE-30H
		cmp	byte [si+6],0
		jnz	short $MIF276
		;MOV	WORD PTR $M_RT.$M_TEMP_BUF[BX],$M_SPACE_HYP
		mov	word [$M_TEMP_BUF+bx],2D20h ; Move in a " -"
		inc	bx		; Increment count
		inc	bx
		mov	byte [$M_TEMP_BUF+bx],' ' ; Move in a " "
		inc	bx		; Increment count
				; Write out " - " to prepare for special case	
		call	_$M_FLUSH_BUF 
$MIF276:
		pop	bp		; Remember the return address
		xor	bx,bx	; Use BX for buffer count
		xor	dx,dx	; Use DX for count of parms taken off the stack
		;MOV	$M_RT.$M_SIZE,CL
		mov	[$M_SIZE],cl	; Save size to later clear stack
		;MOV	AL,BYTE PTR $M_SL.$M_S_MINW
		mov	al,[si+9]	; Get the minimum width
		cmp	al,cl		; Do we need pad chars added?
		jbe	short $MIF278	; No,
					; Yes,
		sub	al,cl		; Calculate how many pad chars are needed.
		mov	dh,al		; Save the number of pad characters
		;TEST	BYTE PTR $M_SL.$M_S_FLAG,Right_Align
		test	byte [si+7],80h	; Was replaceable parm to be right aligned?
		jz	short $MIF278	; No,
$MDO280:
		mov	al,[si+0Ah]	; Yes,
		mov	[$M_TEMP_BUF+bx],al ; Begin filling buffer with pad chars
		inc	bx
		cmp	bx,64		; Is buffer full?
		jne	short $MIF281
		call	_$M_FLUSH_BUF	; Flush the buffer
$MIF281:
		dec	dh		; Have we filled with enough pad chars?
		jnz	short $MDO280	; No, next pad character
$MIF278:
		;CMP	BYTE PTR $M_SL.$M_S_MAXW,$M_UNLIM_W
		cmp	byte [si+8],0	; Is maximum width unlimited?
		jz	short $MIF286	; Yes,
		cmp	[si+8],cl	; Will we exceed maximum width?
		jnb	short $MIF286	; No,
					; Yes,
		sub	cl,[si+8]	; Calculate how many extra chars	
		mov	dl,cl		; Remember how many chars to pop off
		;MOV	CL,BYTE PTR $M_SL.$M_S_MAXW
		mov	cl,[si+8]	; Set new string length
$MIF286:
		or	cx, cx
		jz	short $MIF290
$MDO291:				; Begin filling buffer with string
		;TEST	BYTE PTR $M_SL.$M_S_FLAG,NOT Char_Type AND $M_TYPE_MASK
		test	byte [si+7],0Fh
		jnz	short $MIF292
		;TEST	$M_SL.$M_S_FLAG,Char_field_ASCIIZ AND $M_SIZE_MASK
		test	byte [si+7],10h	; Is this replace a ASCIIZ string?
		jz	short $MIF292
					; Yes,
		mov	al,[es:di]	; Get first character from string
		inc	di		; Next character in string
		jmp	short $MEN292
$MIF292:
		pop	ax		; Get character in register
$MEN292:
		mov	[$M_TEMP_BUF+bx],al ; Move char into the buffer
		inc	bx		; Increase buffer count
		cmp	bx,64		; Is buffer full?
		jnz	short $MIF295
		call	_$M_FLUSH_BUF	; Flush the buffer
$MIF295:
		dec	cl		; Have we completed replace?
		jnz	short $MDO291
$MIF290:
		;TEST	BYTE PTR $M_SL.$M_S_FLAG,Right_Align
		test	byte [si+7],80h ; Was replaceable parm to be left aligned?
		jnz	short $MIF299	; No, (right aligned)
					; Yes,
		or	dh,dh		; Do we need pad chars added?	
		jz	short $MIF299
$MDO301:
		;MOV	AL,BYTE PTR $M_SL.$M_S_PAD
		mov	al,[si+0Ah]	; Begin filling buffer with pad chars
		mov	[$M_TEMP_BUF+bx],al ; Move in a pad char
		inc	bx
		cmp	bx,64		; Is buffer full?
		jnz	short $MIF302
		call	_$M_FLUSH_BUF	; Flush the buffer
$MIF302:
		dec	dh		; Have we filled with enough pad chars?
		jnz	short $MDO301
$MIF299:
		;TEST	BYTE PTR $M_SL.$M_S_FLAG,NOT Char_Type AND $M_TYPE_MASK
		test	byte [si+7],0Fh
		jnz	short $MIF307
		;TEST	$M_SL.$M_S_FLAG,Char_field_ASCIIZ AND $M_SIZE_MASK	
		test	byte [si+7],10h	; Is this replace a ASCIIZ string?
		;jz	short $MIF307
		;jmp	short $MEN307
		jnz	short $MEN307
$MIF307:
		or	dl,dl
		jz	short $MEN307
$MDO310:				; Clean Up stack using spare variable
		pop	word [$M_RETURN_ADDR]
		dec	dl		; Are we done?
		jnz	short $MDO310
$MEN307:
		call	_$M_FLUSH_BUF	; Flush the buffer for the final time
		push	bp		; Restore the return address
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_FLUSH_BUFFER
;;
;;	FUNCTION: Display the contents of the temporary buffer
;;	INPUTS: DI contains the number of bytes to display
;;	OUTPUTS: BX reset to zero
;;
;;	REGS USED:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_FLUSH_BUF:
		push	cx		; Save changed regs
		push	es
		push	di
		push	ds
		pop	es		; Set ES pointing to buffer
		mov	cx,bx		; Set number of bytes to display
		xor	bx,bx		; Reset buffer counter
		;LEA	DI,$M_RT.$M_TEMP_BUF
		lea	di,[$M_TEMP_BUF] ; Reset buffer location pointer
		call	_$M_DISPLAY_STRING ; Display the buffer
		jc	short $MIF314	; Error?
		pop	di		; No, Restore changed regs
		pop	es
		pop	cx
		retn
$MIF314:				; Yes,
		add	sp,6		; Fix stack
		stc			; Set cf to indicate Error
		retn			; Return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_CHAR_REPLACE
;;
;;	FUNCTION: Will prepare a single char or ASCIIZ string for replace
;;	INPUTS: DS:SI points at corresponding SUBLIST
;;		ES:DI contains the VALUE from SUBLIST
;;	OUTPUTS: CX contains number of characters on stack
;;		 Top of stack  --> Last character
;;					. . .
;;		 Bot of stack  --> First character
;;
;;	OTHER REGS Revised: AX
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_CHAR_REPLACE:
		pop	bp		; Save return address
		;TEST	$M_SL.$M_S_FLAG,NOT Char_Field_Char AND $M_SIZE_MASK
		test	byte [si+7],30h ; Was Character specified?	
		jnz	short $MDO321
		mov	al,[es:di]	; Get the character
		push	ax		; Put it on the stack
		inc	cx		; Increase the count
		call	_$M_IS_IT_DBCS	; Is this the first byte of a DB character
		jnc	short $MIF318	; No,
					; Yes,
		mov	al,[es:di+1]	; Get the next character
		push	ax		; Put it on the stack
		clc
$MIF318:				; No, it was an ASCIIZ string
		jmp	short $MEN317
$MDO321:
		mov	al,[es:di]	; Get the character
		or	al,al		; Is it the NULL?
		jz	short $MEN321
		inc	di		; Next character
		inc	cx		; Increment the count
		jmp	short $MDO321
$MEN321:
		sub	di,cx		; Set DI at the beginning of the string
$MEN317:
		push	bp		; Restore return address
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_BIN2ASC_REPLACE
;;
;;	FUNCTION: Convert a signed or unsigned binary number to an ASCII string
;;		  and prepare to display
;;	INPUTS: DS:SI points at corresponding SUBLIST
;;		ES:DI contains the VALUE from SUBLIST
;;	OUTPUTS: CX contains number of characters on stack
;;		 Top of stack  --> Last character
;;					. . .
;;		 Bot of stack  --> First character
;;	OTHER REGS Revised: BX,DX,AX
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_BIN2ASC_REPLACE:
		pop	bp		; Save return address
		xor	ax,ax		; Prepare for get binary value (LOW)
		;xor	dx,dx
		cwd			; Prepare for get binary value (HIGH)
		;MOV	$M_RT.$M_DIVISOR,$M_BASE16
		mov	word [$M_DIVISOR],16 ; Set default divisor
		xor	bx,bx		; Use BX as the NEG flag (if applicable)
		;TEST	$M_SL.$M_S_FLAG,NOT $M_BYTE AND $M_SIZE_MASK
		test	byte [si+7],20h ; Was BYTE specified?
		jnz	short $MIF325	; No,
					; Yes,
		mov	al,[es:di]	; Setup byte in AL
		;TEST	$M_SL.$M_S_FLAG,NOT Sgn_Bin_Type AND $M_TYPE_MASK
		test	byte [si+7],0Dh ; Was Signed binary specified?
		jnz	short $MIF326	; No,
					; Yes,
		test	al,80h		; Is this number negative?
		jz	short $MIF327	; No,
					; Yes,	
		inc	bx		; Remember that it was negative		
		and	al,7Fh		; Make it positive
$MIF327:
		;MOV	$M_RT.$M_DIVISOR,$M_BASE10
		mov	word [$M_DIVISOR],10
$MIF326:
		;TEST	$M_SL.$M_S_FLAG,NOT Unsgn_Bin_Type AND $M_TYPE_MASK
		test	byte [si+7],0Eh	; Was Unsigned binary specified?
		jnz	short $MIF330	; No,
		mov	word [$M_DIVISOR],10 ; Yes,
$MIF330:
		jmp	short $MIF345
$MIF325:
		;TEST	$M_SL.$M_S_FLAG,NOT $M_WORD AND $M_SIZE_MASK
		test	byte [si+7],10h	; Was WORD specified?
		jnz	short $MIF333	; No,
					; Yes,
		mov	ax,[es:di]	; Setup byte in AX
		;TEST	$M_SL.$M_S_FLAG,NOT Sgn_Bin_Type AND $M_TYPE_MASK
		test	byte [si+7],0Dh	; Was Signed binary specified?
		jnz	short $MIF334	; No,
					; Yes,
		test	ah,80h		; Is this number negative?
		jz	short $MIF335
		inc	bx		; Remember that it was negative
		and	ah,7Fh		; Make it positive
$MIF335:
		mov	word [$M_DIVISOR],10
$MIF334:
		;TEST	$M_SL.$M_S_FLAG,NOT Unsgn_Bin_Type AND $M_TYPE_MASK
		test	byte [si+7],0Eh	; Was Unsigned binary specified?
		;jnz	short $MIF338	; No,
		jnz	short $MIF345	
				; Yes,
		; MOV	$M_RT.$M_DIVISOR,$M_BASE10
		mov	word [$M_DIVISOR],10
$MIF338:
		jmp	short $MIF345
$MIF333:
		mov	ax,[es:di]	; Setup Double word in DX:AX
		mov	dx,[es:di+2]
		;TEST	$M_SL.$M_S_FLAG,NOT Sgn_Bin_Type AND $M_TYPE_MASK
		test	byte [si+7],0Dh ; Was Signed binary specified?
		jnz	short $MIF341	; No,
					; Yes,
		test	dh,80h		; Is this number negative?
		jz	short $MIF342	; No,
					; yes,
		inc	bx		; Remember that it was negative		
		and	dh,7Fh		; Make it positive
$MIF342:
		mov	word [$M_DIVISOR],10
$MIF341:
		;TEST	$M_SL.$M_S_FLAG,NOT Unsgn_Bin_Type AND $M_TYPE_MASK
		test	byte [si+7],0Eh ; Was Unsigned binary specified?
		jnz	short $MIF345	; No,
					; Yes,
		mov	word [$M_DIVISOR],10
$MIF345:
		; Thousand separator bit ? 
		; (This code portion is not existing in MSDOS 6.0 files.)
		test	byte [si+7],40h ; Reserved bit (for MSDOS 6.0 sublist)
		jz	short $MIF346
		push	ax
		push	dx
		mov	ah,38h
		xor	al,al
		lea	dx,[$M_TEMP_BUF]
		int	21h	; DOS -	2+ - GET COUNTRY-DEPENDENT INFORMATION
				; get current-country info ; (*)
				; DS:DX	-> buffer for returned info
		jnc	short $MEN325
		mov	byte [$M_THOU_SEPARA],',' ; [$M_TEMP_BUF+7]
$MEN325:
			;DOS Country Info (DOS 3.0+) (*)
			
		      ;Offset  Size  Description
			;00    word  Date and time format
			;	0 = month day year, hh:mm:ss (USA)
			;	1 = day month year, hh:mm:ss (Europe)
			;	2 = year month day, hh:mm:ss (Japan)
			;02  5 bytes ASCIIZ currency symbol
			;07  2 bytes ASCIIZ thousands separator
			;09  2 bytes ASCIIZ decimal separator
			;0B  2 bytes ASCIIZ date separator
			;0D  2 bytes ASCIIZ time separator
			;0F    byte  Currency symbol format
			;	0 = symbol leads, without space
			;	1 = symbol follows, without space
			;	2 = symbol leads, one space
			;	3 = symbol follows, one space
			;	4 = symbol replace decimal separator
			;10    byte  Number of digits after decimal
			;11    byte  Time format
			;	Bit 0 = 0 12 hour clock
			;	      = 1 24 hour clock
			;12    dword Case map call address
			;16  2 bytes ASCIIZ data list separator
			;18  10 bytes Reserved

		mov	al,[si+10] ; get sublist pad_char
		mov	di,ax	; save pad_char
		pop	dx
		pop	ax
		mov	byte [si+10],',' ; set pad_char to ',' for using thous. sep.
		call	_$M_CONVERT2ASC
		mov	ax,di	; restore pad_char 
		mov	[si+10],al
		jmp	short $MIF347
$MIF346:			; Default number displaying (without thous. sep.)
		call	_$M_CONVERT2ASC
$MIF347:
		or	bx,bx		; Was number negative?
		jz	short $MIF349	; No,
					; Yes,
		mov	dx,'-'		; Put "-" on the stack with the number
		push	dx
$MIF349:
		push	bp		; Restore return address
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_CONVERT2ASC
;;
;;	FUNCTION: Convert a binary number to a ASCII string
;;	INPUTS: DX:AX contains the number to be converted
;;		$M_RT_DIVISOR contains the divisor
;;	OUTPUTS: CX contains the number of characters
;;		Top of stack  --> Last character
;;				     . . .
;;		Bot of stack  --> First character
;;	REGS USED:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

		; CX = 0
_$M_CONVERT2ASC:
		pop	word [$M_RETURN_ADDR]	; Save Return Address
		xor	bx,bx		; Use BX as a swapping register
		xchg	ax,bx		; Initialize - Low Word in BX
		xchg	ax,dx		;            - High Word in AX
$MDO145:				; DO UNTIL Low Word becomes zero
		div	word [$M_DIVISOR] ; Divide High Word by divisor
		xchg	ax,bx		; Setup to divide Low Word using remainder
					;   and save reduced High Word in BX
		div	word [$M_DIVISOR] ; Divide Low Word by divisor
		cmp	dx,9		; Make a digit of the remainder	
		jbe	short $MIF146	; IF 10 to 15,
		add	dl,37h ; '7'	;    Make A to F ASCII
		jmp	short $MEN146
$MIF146:				; IF 0 to 9,
		add	dl,'0'		;    Make 0 to 9 ASCII
$MEN146:
		push	dx		; Save the digit on the stack
		inc	cx		; Count that digit
		or	ax,ax		; Are we done?
		jnz	short $MLL149
		or	bx,bx		; AX and BX must be ZERO!!
		jz	short $MEN145
$MLL149:
		cmp	cx,3		; Are we at the first thousands mark
		jne	short $MIF150	; No,
					; Yes,
		;CMP	$M_SL.$M_S_PAD,$M_COMMA
		cmp	byte [si+10],',' ; Is the pad character a comma?
		jne	short $MIF151	; No,
					; Yes,
		push	word [$M_THOU_SEPARA] ; Insert a thousand separator
		inc	cx
$MIF151:
		jmp	short $MEN150
$MIF150:
		cmp	cx,7		; Are we at the second thousands mark
		jne	short $MIF154
					; Yes,
		cmp	byte [si+10],','  ; Is the pad character a comma?
		jne	short $MIF155
					; Yes,
		push	word [$M_THOU_SEPARA] ; Insert a thousand separator
		inc	cx
$MIF155:
		jmp	short $MEN150
$MIF154:
		cmp	cx,11		; Are we at the third thousands mark
		jne	short $MEN150	; No,
					; Yes,
		cmp	byte [si+10],',' ; Is the pad character a comma?
		jnz	short $MEN150	; No,
					; Yes,
		push	word [$M_THOU_SEPARA] ; Insert a thousand separator
		inc	cx
$MEN150:
		xchg	ax,bx		; Setup to divide the reduced High Word
					;   and Revised Low Word
		xor	dx,dx		; Reset remainder
		jmp	short $MDO145	; NEXT
$MEN145:
		xor	ax,ax		; Reset remainder
		;xor	dx,dx
		cwd			; Reset remainder
		push	word [$M_RETURN_ADDR] ;	Restore Return Address
		retn			; Return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 
;;
;;	PROC NAME: $M_DISPLAY_STRING
;;
;;	FUNCTION:  Will display or write string
;;	INPUTS:    ES:DI points to beginning of message
;;		   CX contains the length of string to write (if applicable)
;;	OUTPUTS:   None
;;	REGS Revised: None
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_DISPLAY_STRING:
		push	ax
		push	bx
		push	dx
		;MOV	BX,$M_RT.$M_HANDLE
		mov	bx,[$M_HANDLE]	; Retrieve handle
		cmp	bx,0FFFFh ; -1	; Was there a handle specified?
		;jne	short $MIF107
		je	short $MIF107 ; * ; No, display $ terminated string
		;call	_$M_DISPLAY_$_STRING
		;;jmp	short $MEN107
;$MIF107:
		call	_$M_DISPLAY_H_STRING ; Yes, display string to handle	
		jnc	short $MIF110 ; *  ; Was there an error?
$MEN107:
		;jnc	short $MIF110
					; Yes,
		mov	ah,59h		; Get extended error
		mov	bx,0
		int	21h	; DOS -	3+ - GET EXTENDED ERROR	CODE
				; BX = version code (0000h for DOS 3.x)
		xor	ah,ah		; Clear AH
		jmp	short $MEN111 ; *
		;add	sp,6
		;stc
		;;jmp	short $MIF112
		;retn ; *
;$MIF110:
		;cmp	bx,0FFFFh ; -1
		;je	short $MIF112
$MIF110: ; *
		; BX <> -1
		cmp	ax,cx		; Was it ALL written?
		je	short $MIF112	; Yes
					; No,
		call	_$M_GET_EXT_ERR_39 ; Set Extended error
$MEN111: ; *		
		add	sp,6		; Clean up stack
		stc			; Flag that there was an error
		retn ; *

$MIF107: ; *
		; BX = -1	; Display $ terminated string
		call	_$M_DISPLAY_$_STRING ; *
		;jc	short $MEN107	     ; *	
$MIF112:
		;jc	short $MIF117
		pop	dx		; Restore regs
		pop	bx
		pop	ax
$MIF117:
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_DISPLAY_$_STRING
;;
;;	FUNCTION:  Will display a $ terminated string
;;	INPUTS:    ES:DI points to beginning of message text (not the length)
;;	OUPUTS:    None
;;	REGS USED: AX,DX
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_DISPLAY_$_STRING:
		push	ds
		push	es
		pop	ds

		cmp	cx,1		; Is this a single character?
		jne	short $MIF119	; No,

		mov	ah,2
		mov	dl,[es:di]
		int	21h	; DOS -	DISPLAY	OUTPUT
				; DL = character to send to standard output
		pop	ds
		mov	al,dl
		call	_$M_IS_IT_DBCS
		push	ds
		push	es
		pop	ds
		;jnc	short $MIF120
		jnc	short $MEN119 ; *
		mov	dl,[es:di+1]
		int	21h		; DOS -
		clc
;$MIF120:
		jmp	short $MEN119
$MIF119:
		;mov	ah,2		; DOS Function to display CHARACTER
;$MDO123:
		or	cx,cx		; Are there any left to display?
		jz	short $MEN119	; No, (CF=0 ; *) 
				
		mov	ah,2 ; *
					; Yes,	
$MDO123: ; *
		mov	dl,[es:di] 	; Get the character
		int	21h	; DOS -	DISPLAY	OUTPUT
				; DL = character to send to standard output
		inc	di		; Set pointer to next character
		loop	$MDO123
$MEN119:
		;clc	; *
		pop	ds
		; cf = 0
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Scan_ctrlZ : This routine looks through the string to be printed and 
; truncates it at the Ctrl-Z if any present.
;
;	ENTRY:	ds:dx = String to be displayed
;		cx = number of chars to be displayed
;
;	EXIT:	cx = number of chars to be displayed
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Scan_CtrlZ:
		push	di
		push	ax
		push	es
		push	bx
		mov	di,dx
		push	ds
		pop	es		; es:di points at string
		mov	bx,cx		; save current count
		mov	al,1Ah
		cld
		repne scasb		; find first Ctrl-Z
		jnz	short noCtrlZ	; no CtrlZ found in string
		sub	bx,cx		; bx = new count to display
		dec	bx
noCtrlZ:
		mov	cx,bx		; cx = actual display count
		pop	bx
		pop	es
		pop	ax
		pop	di
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_DISPLAY_H_STRING
;;
;;	FUNCTION:  Will display a string to a specified handle
;;	INPUTS:    ES:DI points to beginning of message
;;		   CX contains the number of bytes to write
;;		   BX contains the handle to write to
;;	OUPUTS:    None
;;	REGS USED: AX,DX
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_DISPLAY_H_STRING:
		xor	ax,ax		; Set number of bytes written to 0
		or	cx,cx		; For performance, don't write if not necessary
		jz	short $MIF127	; Any chars to write?
		push	ds		; Yes,
		push	es
		pop	ds		; Set DS to segment of message text
					; DOS function to write to a handle
		mov	ah,40h ; DOS_WRITE_HANDLE
		mov	dx,di		; Pointer to data to write
		cmp	cx,1		; Is this a single character?
		jne	short $MIF128
					; Yes,
		int	21h	; DOS -	2+ - WRITE TO FILE WITH	HANDLE
				; BX = file handle, CX = number	of bytes to write,
				; DS:DX -> buffer
		pop	ds		; Restore DS
		push	ax
		mov	al,[es:di]	; Get the character
		call	_$M_IS_IT_DBCS	; Is this the first byte of a DB character
		pop	ax
		push	ds
		push	es		; Set DS to segment of message text
		pop	ds
		jnc	short $MIF129
		clc			; Clear the DBCS indicator		
		mov	ah,40h		; DOS function to write to a handle
		inc	dx		; Point to next character
		int	21h	; DOS -	2+ - WRITE TO FILE WITH	HANDLE
				; BX = file handle, CX = number	of bytes to write, 
				; DS:DX -> buffer
$MIF129:

; If the single char happened to be a Ctrl-Z, the dos write would return
; 0 chars written making the caller think there was an error writing. To 
; avoid this, we check if the single char was a Ctrl-Z and if so, return that
; the char was written, thus fooling the caller.

		pushf			 ; save flags
		cmp	byte [es:di],1Ah ; is char a Ctrl-Z?
		jne	short $MEN129	 ; no, continue
		mov	ax,cx		 ; yes, fake as if it was written
$MEN129:
		;jmp	short _$M_Popf
		popf	; *		 ; restore flags
		jmp	short $MEN128
;_$M_Mret:
;		iret
;_$M_Popf:
		;push	cs
		;call	_$M_Mret
		;jmp	short $MEN128
$MIF128:

; Prescan the string looking for Ctrl-Z. We terminate the message the moment 
; we hit a Ctrl-Z. cx will contain the number of characters to be printed.

		push	bp
		push	cx
		call	Scan_CtrlZ	; cx = count without Ctrl-Z
		mov	bp,cx		; store no ^Z count in bp 
		pop	cx		; get old count back
				; Write String at DS:SI to handle
		int	21h	; DOS -
		jc	short m_cnt_ok	;error, return with carry set
chk_count:				;no error, adjust return count

; If we are writing to con and there is a Ctrl-Z in the string, the
; return count will be much less and if this returns to the caller we can get
; spurious error messages. We check here if the count returned is same as
; original count or same as the count if we stop at Ctrl-Z. In the second
; case, we fake it as if all bytes have been written. If the return count
; does not match either count, then we had some other disk error (such as
; insufficient disk space) and we pass it through

		cmp	cx,ax		; have all bytes been written?
		je	short m_cnt_ok	; there was an error writing
		cmp	bp,ax		; count = Ctrl-Z count?
		clc			; no error either way
		jne	short m_cnt_ok	; no, pass it through
		mov	ax,cx		; return old count
m_cnt_ok:
		pop	bp
$MEN128:
		pop	ds
$MIF127:
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_GET_EXT_ERR_39
;;
;;	FUNCTION:  Will set registers for extended error #39
;;	INPUTS:    None
;;	OUPUTS:    AX,BX,CX set
;;	REGS USED:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_GET_EXT_ERR_39:
		mov	ax,39
					; Bug!? 12/11/2018 (Erdogan Tan)
		;MOV	BX,(ERROR_CLASS_39 SHR 8) + ACTION_39  ;!?
						; BH = 1, BL = 4 ; !?
		;MOV	BX,(ERROR_CLASS_39 SHL 8) + ACTION_39
		;mov	bx,4
		mov	bx,0104h ; * BugFix
		;MOV	CH,LOCUS_39
		mov	ch,1
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_ADD_CRLF
;;
;;	FUNCTION:  Will decide whether to display a CRLF
;;	INPUTS:    DX contains the Input/Class requested
;;	OUTPUTS:   None
;;	REGS Revised: CX,ES,DI
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_ADD_CRLF:				; Is it a utility message? 
		cmp	dh,0FFh ; UTILITY_MSG_CLASS
		je	short $MIF135	; Yes,
					; No,
		test	dh,80h ; $M_NO_CRLF_MASK ; Are we to supress the CR LF?
		jnz	short $MIF135 ; Yes,
				      ; No,	
		push	ds
		pop	es		; Set ES to data segment
		;lea	di,[$M_CRLF]
		mov	di,$M_CRLF	; Point at CRLF message
		mov	cx,2		; Set the message size
		call	_$M_DISPLAY_STRING ; Display the CRLF
$MIF135:
		retn

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;	PROC NAME: $M_IS_IT_DBCS
;;
;;	FUNCTION:  Will decide whether character is Single or Double Byte
;;	INPUTS:    AL contains the byte to be checked
;;	OUPUTS:    Carry flag = 0 if byte is NOT in DBCS range
;;		   Carry flag = 1 if byte IS in DBCS range
;;	REGS USED: All restored
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_$M_IS_IT_DBCS:
		push	es		; Save ES, DI registers
		push	di
		;LES	DI,$M_RT.$M_DBCS_VEC
		les	di,[$M_DBCS_VEC] ; 15/11/2018
		or	di,di		; Was the DBCS vector set?
		jz	short $MIF138
$MDO139:
		;CMP	WORD PTR ES:[DI],$M_DBCS_TERM
		cmp	word [es:di],0	; Is this the terminating flag?
		;clc
		je	short $MIF138	; Yes,
					; No,
		cmp	al,[es:di]	; Does the character fall in the DBCS range?
		jb	short $MIF141
		cmp	al,[es:di+1]	; Does the character fall in the DBCS range?
		ja	short $MIF141
		stc			; Yes, Set carry flag
		; Bug!: Never returns with cf = 1 ; 12/11/2018 (Erdogan Tan) ; *
		jmp	short $MIF138 ; * BugFix
$MIF141:
		inc	di		; Go to next vector
		inc	di
		jmp	short $MDO139
$MIF138:
		pop	di
		pop	es
		retn

; ----------------------------------------------------------------------------

;_$M_CLS_A:	; proc far
		;push	cs
		;pop	es
		;lea	di,[CLASS_A_msg_tbl]
		;mov	di,CLASS_A_msg_tbl
		;add	cx,278
		;;retf
		;retn

; ----------------------------------------------------------------------------

;_$M_CLS_B:	; proc far
		;push	cs
		;pop	es
		;lea	di,[CLASS_B_msg_tbl]
		;mov	di,CLASS_B_msg_tbl
		;add	cx,189
		;;retf
		;retn

; ----------------------------------------------------------------------------

;_$M_CLS_1:	;proc far
		;push	cs
		;pop	es
		;lea	di,[CLASS_1_msg_tbl]
		;mov	di,CLASS_1_msg_tbl
		;add	cx,32
		;;retf
		;retn

; ----------------------------------------------------------------------------

;_$M_CLS_2:	;proc far
		;push	cs
		;pop	es
		;lea	di,[CLASS_2_msg_tbl]
		;mov	di,CLASS_2_msg_tbl
		;add	cx,29
		;;retf
		;retn

; ----------------------------------------------------------------------------

; ----------------------------------------------------------------------------
; fdparse.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 14/11/2018)

;/************************************************************************/
;/* Parse_Message                - This routine will print only those    */
;/*                                messages that require 1 replaceable   */
;/*                                parm.                                 */
;/*                                                                      */
;/*      Inputs  : Msg_Num       - number of applicable message          */
;/*                Handle        - display type                          */
;/*                Message_Type  - type of message to display            */
;/*                Replace_Parm  - pointer to parm to replace            */
;/*                                                                      */
;/*      Outputs : message                                               */
;/*                                                                      */
;/*      Date    : 03/28/88                                              */
;/*      Version : DOS 4.00                                              */
;/************************************************************************/

;void Parse_msg(Msg_Num,Handle,Message_Type) 

	;int             Msg_Num;
	;int             Handle;
	;unsigned char   Message_Type; 

Parse_msg:
	; char    far *Cmd_Ptr; 

	;%define _Cmd_Ptr    bp-4
	%define Msg_Num      bp+4
	%define	Handle       bp+6
	%define	Message_Type bp+8

		push	bp
		mov	bp,sp
		;sub	sp,4
		;sub	sp-2 ; *
		;mov	ax,segregs_es
		;push	ax
		;call	segread ; segread(&segregs);  
		;pop	bx

		;FP_SEG(Cmd_Ptr) = segregs.ds;
		;FP_OFF(Cmd_Ptr) = regs.x.si;
		;*Cmd_Ptr        = '\0';

		;;mov	ax,[segregs_ds]
		;;mov	[_Cmd_Ptr+2],ax
		;mov	[_Cmd_Ptr+2],ds
		;;mov	ax,[regs_x_si]
		;;mov	[_Cmd_Ptr],ax
		;mov	[_Cmd_Ptr],si
		;les	bx,[_Cmd_Ptr]
		;mov	byte [es:bx],0
		;mov	bx,sp ; *
		;mov	byte [bx],0 ; *
		mov	byte [si],0

		;FP_SEG(sublistp[0].value) = segregs.ds;
		;FP_OFF(sublistp[0].value) = Parse_Ptr;     

		;mov	ax,[segregs_ds]
		;mov	[sublistp_value_seg],ax
		mov	[sublistp_value_seg],ds ; [sublistp_value+2]
		mov	ax,[Parse_Ptr]
		mov	[sublistp_value],ax

		;sublistp[0].size      = Sublist_Length;
		;sublistp[0].reserved  = Reserved;
		;sublistp[0].id        = 0;
		;sublistp[0].flags     = Char_Field_ASCIIZ+Left_Align;
		;sublistp[0].max_width = 80;
		;sublistp[0].min_width = 01;
		;sublistp[0].pad_char  = Blank;

		mov	byte [sublistp_size],11
		mov	byte [sublistp_flags],10h ; Char_Field_ASCIIZ+Left_Align
		mov	byte [sublistp_max_width],80
		mov	byte [sublistp_min_width],1
		mov	byte [sublistp_pad_char], ' '

		;regs.x.ax = Msg_Num;
		;regs.x.bx = Handle;
		;regs.x.cx = SubCnt1;
		;regs.h.dl = No_Input;
		;regs.h.dh = Message_Type;
		;regs.x.si = (unsigned int)&sublistp[0];   

		;mov	ax,[Msg_Num]
		;mov	[regs_x_ax],ax
		;mov	ax,[Handle]
		;mov	[regs_x_bx],ax
		;mov	[regs_x_cx],1
		sub	al,al ; 0
		mov	[sublistp_res],al ; 0
		mov	[sublistp_id],al ; 0
		;mov	[regs_x_dx],al
		;mov	al,[Message_Type]
		;mov	[regs_x_dx+1],al
		;mov	word [regs_x_si],sublistp_size
		;mov	ax,regs ; regs_x_ax
		;push	ax
		;push	ax
		;call	sysdispmsg  ; sysdispmsg(&regs,&regs);
		;pop	bx
		;pop	bx

		push	di ; *
		push	si ; **

		mov	ax,[Msg_Num]	  ; ***
		mov	bx,[Handle]	  ; ***
		mov	cx,1 ; SubCnt1	  ; ***   
		mov	dh,[Message_Type] ; ***
		;mov	dl,0 ; No_Input   ; ***
		sub	dl,dl
		mov	si,sublistp_size  ; ***

		call	SYSDISPMSG ; *, **, ***

		pop	si ; **
		pop	di ; *

		mov	sp,bp
		pop	bp
		retn	; return;

; ----------------------------------------------------------------------------
; fdisk.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 15/11/2018)

;/*  */
; ----------------------------------------------------------------------------
;char check_valid_environment()

check_valid_environment:
			; /* See if the net is there */
		mov	ax,0B800h ; NETWORK - INSTALLATION CHECK
		int	2Fh
			;Return:
			;  AL = status
			;	00h -> not installed
			;	>00h -> installed
			;  BX = installed component flags (test in this order!)
			;	bit 6   server
			;	bit 2   messenger
			;	bit 7   receiver
			;	bit 3   redirector
			;	bit 1   LANPUP (LANtastic 4.0)
		
		; /* See if server is loaded, otherwise okay */
		and	al,al
		jz	short cve_true ; not installed, ok

		test	bl,40h  ; bit 6, server
		jz	short cve_true ; not server running, ok
		
		; Error ! 
		; (FDISK must not be used in a network while the server is running.)
		;mov	al,0FFh
		mov	ax,0FFh ; msgclass = 0FFh, UTILTY_MSG_CLASS
		push	ax
		sub	al,al ; 0
		mov	[no_fatal_error],al ; FALSE
		push	ax	; msginput = 0, (noinput)
		;sub	ax,ax
		push	ax	; msgsub = 0,  (nosubptr)
		push	ax	; msgparms = 0, (nosubcnt)
		mov	al,2	; msghan = 2, STDERR (DosStdEr)
		push	ax
		mov	al,4	; msgnum = 4, "Cannot FDISK with network loaded"
		push	ax

		call	display_msg
		add	sp,12
cve_false:
		;sub	al,al ; 0
		stc
cve_true:
		retn
;cve_true:
		;mov	al,1
		;;clc	
		;retn

; ----------------------------------------------------------------------------
; video.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 15/11/2018)

;/*  */
;/*                                                                         */
;/***************************************************************************/
;/* Initializes the screen and stores the lower right hand corner           */
;/* of the screen in the global variable LowerRightHandCorner. This         */
;/* is which is used for screen clears. If the screen is in graphics mode,  */
;/* it is changed to BW 40x25. This procedure is only called once at program*/
;/* start. Also saves the current screen                                    */
;/***************************************************************************/
;/*                                                                         */

init_video_information:
		mov	byte [mono_flag],0 ; FALSE

		; /* Get the current video state */
		mov	ah,0Fh
		int	10h
		
		; /* Save the mode and display page */
		mov	[video_mode],al
		mov	[display_page],bh

		; get_video_attribute();
		call	get_video_attribute

		; if (status_flag == FALSE)
		cmp	byte [status_flag],0
		jne	short ivi_3

		; /* assume color mode */
		mov	al,3

		; /* See if we are in MONOCHROME mode */
		cmp	byte [video_mode],7  ; Text 80x25 chars	Monochrome
		je	short ivi_1
			; Graphics 640x350 Monochrome
		cmp	byte [video_mode],0Fh
		jne	short ivi_2

ivi_1:		; /* Nope,set to BW80x25*/
		mov	al,2	; Text 80x25 chars Greyscale
		mov	byte [mono_flag],1
ivi_2:
		; /* go set the new mode */
		;mov	ah,0
		sub	ah,ah
		int	10h
		
		; /* Set the display page */
		mov	ah,5
		;mov	al,0
		sub	al,al
		int	10h
ivi_3:
		retn

;/*  */
;/***************************************************************************/
;/* Resets the video mode to the original value 			    */
;/***************************************************************************/

;void reset_video_information()

reset_video_information:
		;  /* Do this if we are not using the /STATUS switch */
		; if (status_flag == FALSE)
		
		cmp	byte [status_flag],0
		jne	short rvi_ret

		; /* Clear display with colors that were present when FDISK was invoked */
		mov	bh,[video_attribute]
		;sub	cx,cx ; cl = start (upper left) column
			      ; ch = start (top) row				
		;mov	dl,24 ; dl = end (lower right) column
		;mov	dh,79 ; dh = end (bottom) row
		;mov	al,0  ; lines
		;mov	ah,6 ; SCROLL_UP ; BIOS scroll up function
		;	 		 ; BIOS video call
		;int	10h	; - VIDEO - SCROLL PAGE	UP
				; AL = number of lines to scroll window	
				;	(0 = blank whole window)
				; BH = attributes to be	used on	blanked	lines
				; CH,CL	= row,column of	upper left corner of window to scroll
				; DH,DL	= row,column of	lower right corner of window

		call	RVI_CLS ; 16/11/2018
		
		; /* Reset the video mode */
		xor	ah,ah ; 0 ; SET MODE
		mov	al,[video_mode]
		int	10h

		; /* Set the page */
		mov	ah,5
		mov	al,[display_page]
		int	10h
rvi_ret:
		retn

; ============================================================================
;  CLS (clear screen, clear whole video page)
; ============================================================================
; 16/11/2018

CLS:
		call	CLS_ATTRIBUTE ; Set cls (scroll) page attribute in bh		
RVI_CLS:
		; INPUT: bh = Page (blanked line) attributes

		sub	cx,cx ; cl = start (upper left) column
			      ; ch = start (top) row			
		mov	dl,79 ; dl = end (lower right) column
		mov	dh,24 ; dh = end (bottom) row	
		mov	al,0  ; lines
		mov	ah,6 ; SCROLL_UP ; BIOS scroll up function
			 		 ; BIOS video call
		int	10h	; - VIDEO - SCROLL PAGE	UP
				; AL = number of lines to scroll window	
				;	(0 = blank whole window)
				; BH = attributes to be	used on	blanked	lines
				; CH,CL	= row,column of	upper left corner of window to scroll
				; DH,DL	= row,column of	lower right corner of window
		retn

; cls_attribute
; ----------------------------------------------------------------------------
; 16/11/2018

CLS_ATTRIBUTE:
		cmp	byte [status_flag],1
		jne	short clscr_1

		mov	bh,[video_attribute]
		jmp	short clscr_3
clscr_1:
		cmp	byte [mono_flag],1
		jne	short clscr_2
		mov	bh,7	; GRAY_ON_BLACK
		jmp	short clscr_3
clscr_2:
		mov	bh,17h	; WHITE_ON_BLUE
clscr_3:
		retn


;/*****************************************************************************/
;/*Routine name:  GET_VIDEO_ATTRIBUTE                                         */
;/*****************************************************************************/
;/*                                                                           */
;/*Description:   This routine will invoke interrupt 10 function 08h to       */
;/*               get the current attributes at the cursor position in order  */
;/*               to restore the correct colors when returning out of FDISK.  */
;/*                                                                           */
;/*Called Procedures:    none                                                 */
;/*                                                                           */
;/*                                                                           */
;/*Change History: Created        3/11/88         DRM                         */
;/*                                                                           */
;/*Input: None                                                                */
;/*                                                                           */
;/*Output: None                                                               */
;/*                                                                           */
;/*****************************************************************************/

;void get_video_attribute()

get_video_attribute:	; /* Get current attributes */
		mov	ah,8 ; CURRENT_VIDEO_ATTRIBUTE
		mov	bh,[display_page]
		int	10h
		mov	[video_attribute],ah ; 16/11/2018
		retn

;/*  */
; ============================================================================
;  CLEAR SCREEN
; ============================================================================
; 15/11/2018

;void clear_screen(TopRow,LeftCol,BotRow,RightCol)

;unsigned     TopRow;
;unsigned     LeftCol;
;unsigned     BotRow;
;unsigned     RightCol;

;BEGIN

;char    attribute;
;char    *attribute_ptr = &attribute;

;	if (status_flag == TRUE)
;		attribute = video_attribute;
;	else
;		{
;  		if (mono_flag == TRUE) 
;      		attribute = GRAY_ON_BLACK;
;   		else
;       	attribute = WHITE_ON_BLUE;
;		}
;  VIOSCROLLUP(TopRow,LeftCol,BotRow,RightCol,u(0),attribute_ptr,u(0));
;  return;
;END

clear_screen: ; (clear_screen_down, clear screen rows)

		%define	TopRow   bp+4
		%define LeftCol  bp+6
		%define BotRow   bp+8
		%define	RightCol bp+10	

		push	bp
		mov	bp,sp

		push	bx
		push	cx
		push	dx
		;push	si
		;push	di
		;push	ds
		;push	es
		;push	ss
		;push	bp

;		cmp	byte [status_flag],1
;		jne	short clscr_1
;
;		mov	bh,[video_attribute]
;		jmp	short clscr_3
;clscr_1:
;		cmp	byte [mono_flag],1
;		jne	short clscr_2
;		mov	bh,7	; GRAY_ON_BLACK
;		jmp	short clscr_3
;clscr_2:
;		mov	bh,17h	; WHITE_ON_BLUE

		call	CLS_ATTRIBUTE ; 16/11/2018
		
		; bh = Attribute for erased lines
;clscr_3:
		sub	al,al ; # of lines to scroll (0 = whole window)
		
		; ... VIOSCROLLUP ...

; video.asm (MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------
; 15/11/2018 - Modified for NASM syntax & FDISK subroutines (by Erdogan Tan)

; ============================================================================
; void VideoScrollUp( int StartRow, int StartCol, int EndRow, int EndCol,
;                     int Lines, int Attrib )
; ============================================================================

VideoScrollUp:
VIOSCROLLUP:
		; bh =  Attribute for erased lines
		; al =  # of lines to scroll
	
		;;mov	al,[Lines]	 ; # of lines to scroll

		;cmp	al,25
		;jg 	short vioscrollup_1

		mov	dl,[RightCol]	 ; Put ending column in DL
	
		;cmp	dl,80
		;jg 	short vioscrollup_1

		mov	dh,[BotRow]	 ; Put ending row in DH

		;cmp	dh,25
		;jg 	short vioscrollup_1

		mov	ch,[TopRow]	 ; Put starting row in CH
		mov	cl,[LeftCol]	 ; Put starting column in CL

		;;mov	bh,[Attrib]	 ; Attribute for erased lines
	
		mov	AH,6 ; SCROLL_UP ; BIOS scroll up function
			 		 ; BIOS video call
		int	10h	; - VIDEO - SCROLL PAGE	UP
				; AL = number of lines to scroll window	
				;	(0 = blank whole window)
				; BH = attributes to be	used on	blanked	lines
				; CH,CL	= row,column of	upper left corner of window to scroll
				; DH,DL	= row,column of	lower right corner of window
;		sub	ax,ax ; 0
;		jmp	short vioscrollup_2
;vioscrollup_1:
;		mov	ax,2
;vioscrollup_2:
		;pop	bp
		;pop	ss
		;pop	es
		;pop	ds
		;pop	di
		;pop	si
		pop	dx
		pop	cx
		pop	bx
		mov	sp,bp
		pop	bp
		;retn	12
		retn	8	; return and clean stack

; ----------------------------------------------------------------------------
; int13.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 16/11/2018)

;/*  */
; ----------------------------------------------------------------------------
;char get_disk_info()
;BEGIN
;   unsigned char   i;
;   /* Initialize values */
;   number_of_drives = uc(0);
;   for (i=uc(0); i < uc(MAX_HDISK); i++)
;     BEGIN
;        total_disk[i] = u(0);
;        total_mbytes[i] = f(0);
;        max_sector[i] = uc(0);
;        max_head[i] = u(0);
;     END
;   /* See how many drives there are */
;   if (get_drive_parameters(uc(0x80)))
;      BEGIN
;        /* Get the drive parameters for all drives */
;        for (i = uc(0); i < number_of_drives;i++)
;           BEGIN
;            if (get_drive_parameters(uc(0x80)+i))
;              BEGIN
;                /* Save drive parameters */
;                max_sector[i] = ((unsigned char)(regs.h.cl & 0x3F));
;                max_head[i] = ((unsigned)(regs.h.dh +1));
;                total_disk[i] = ((((unsigned)(regs.h.cl & 0xc0)) << 2) | regs.h.ch) + 1;
;                total_mbytes[i] = cylinders_to_mbytes(total_disk[i],i);
;              END
;           else
;              BEGIN
;               good_disk[i] = FALSE;
;               return(FALSE);
;              END
;          END
;       return(TRUE);
;      END
;   else
;      /* No drives present */
;      BEGIN
;        no_fatal_error = FALSE;
;        return(FALSE);
;      END
;END

get_disk_info:
		;%define _i_ bp-2

		;push	bp
		;mov	bp,sp

		;sub	sp,2
		;xor	ax,ax ; [_i_] = 0 ; 19/11/2018
		;push	ax

		xor	bp,bp ; [_i_] = 0

		;push	si

		; /* Initialize values */

		;sub	al,al
		sub	ax,ax ; 19/11/2018	
		mov	[number_of_drives],al ; 0

		;mov	[_i_],al ; 0
		xor	bx,bx ; 0
		;jmp	short gdi_2
gdi_1:
		;mov	bl,[_i_]
		;sub	bh,bh
		mov	[max_sector+bx],bh ; 0
		;sub	ax,ax
		;shl	bx,1
		shl	bl,1 ; 19/11/2018
		mov	[total_disk+bx],ax ; 0
		mov	[total_mbytes+bx],ax ; 0
		mov	[max_head+bx],ax ; 0
		;inc	byte [_i]
		shr	bl,1 ; 19/11/2018
		inc	bl
gdi_2:
		;cmp	byte [_i_],8 ; MAX_HDISK
		cmp	bl,8 ; Max. 8 hard disks
		jb	short gdi_1

		; /* See how many drives there are */

		;mov	al,80h
		;push	ax
		mov	dl,80h
		call	get_drive_parameters
		;pop	bx
		;or	al,al
		;jz	short gdi_7 ; AL = 0 -> Error, no hard disks present

		; AL = 1 -> 1 or 2 or more hard disks present

		; /* Get the drive parameters for all drives */

		;mov	byte [_i_],0
		;sub	bp,bp ; [_i_] = 0
		;jmp	short gdi_4

		; 14/12/2018
		cmp	al,1
		jnb	short gdi_4 ; bp = 0
	
		; cf = 1 ; *
;gdi_7:
		;/* No drives present */

		;sub	al,al
		mov	[no_fatal_error],al ; 0 ; FALSE
;gdi_8:
		;stc ; *
;gdi_9:
		;pop	si
		;mov	sp,bp
		;pop	bp
	
		retn

gdi_3:
		;inc	byte [_i_]
		inc	bp
;gdi_4:
		;mov	al,[_i_]
		;mov	dl,[_i_]
		mov	dx,bp ; [_i_]
		;cmp	[number_of_drives],al
		;cmp	[number_of_drives],dl
		;jbe	short gdi_6
		cmp	dl,[number_of_drives]
		;jnb	short gdi_6
		jnb	short gdi_5 ; cf=0, success return (14/12/2018)
		;add	al,80h
		add	dl,80h
		;push	ax
		call	get_drive_parameters
		;pop	bx
		;or	al,al
		;jz	short gdi_5
		; 14/12/2018
		cmp	al,1
		;jb	short gdi_5
		jb	short gdi_6 ; cf=1, error return (14/12/2018)	
gdi_4: 			; 14/12/2018		
		; /* Save drive parameters */

		;mov	al,[regs_x_cx]
		mov	al,cl
		and	al,3Fh
		;mov	bl,[_i_]
		;sub	bh,bh
		mov	bx,bp ; 17/11/2018
		mov	[max_sector+bx],al
		;mov	al,[regs_x_dx+1]
		mov	al,dh
		sub	ah,ah
		inc	ax
		;shl	bx,1
		;shl	bl,1 ; 19/11/2018
		;mov	[max_head+bx],ax  ; Heads (<= 256)	  	

		; 19/11/2018
		mov	si,bx  ; Drive number (0 to 7)
		shl	si,1
		mov	[max_head+si],ax  ; Heads (<= 256)	

		;mov	al,[regs_x_cx]
		mov	al,cl ; 19/11/2018
		and	ax,0C0h
		shl	ax,1
		shl	ax,1
		;mov	cl,[regs_x_cx+1]
		;sub	ch,ch
		;or	ax,cx
		mov	al,ch
		inc	ax
		;mov	[total_disk+bx],ax ; cylinders (<= 1024)
		mov	[total_disk+si],ax ; 19/11/2018	
	
		;mov	cl,[_i_]
		;;sub	ch,ch
		;mov	cx,bp ; [_i_]
		;push	cx
		;push	ax
		;mov	si,bx ; 19/11/2018
		;;mov	bl,[_i]
		;;xor	bh,bh
		;mov	bx,bp  ; Disk/Drive number (0 to 7) 
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		mov	[total_mbytes+si],ax
		jmp	short gdi_3
;gdi_5:
		; cf = 1  ; 14/12/2018
		;;sub	al,al
		;;mov	bl,[_i_]
		;;sub	bh,bh
		;; ss = ds ; 19/11/2018
		;;mov	bx,bp ; [_i_]
		;;;mov	[good_disk+bx],al ; 0 ; FALSE
		;mov	[good_disk+bp],al ; 19/11/2018
		;;jmp	short gdi_8
		; 14/12/2018
		;stc
		;retn
;gdi_6:
gdi_5:
		; cf = 0 ; 14/12/2018
		mov	al,1
		;jmp	short gdi_8
		; 14/12/2018
		;clc ; *
		;jmp	short gdi_9
gdi_6:
		retn
;gdi_7:
;		;/* No drives present */
;
;		;sub	al,al
;		mov	[no_fatal_error],al ; 0 ; FALSE
;gdi_8:
;		stc ; *
;gdi_9:
;		;pop	si
;		
;		;mov	sp,bp
;		;pop	bp
;		
;		retn


;/*  */
; ----------------------------------------------------------------------------
;char get_drive_parameters(drive)
;
;unsigned char   drive;
;
;BEGIN
;    /* See how many drives there are */
;    regs.h.ah = uc(DISK_INFO);
;    regs.h.dl = drive;
;    DiskIo(&regs,&regs,&segregs);
;
;    /* See if any drives exist */
;    if ((regs.h.dl == uc(0)) || ((regs.x.cflag & 1) == u(1)))
;       BEGIN
;        display(error_1);
;        return(FALSE);
;       END
;    else
;       BEGIN
;        /* Save the number of drives */
;        number_of_drives = regs.h.dl;
;        if (number_of_drives > MAX_HDISK)
;            number_of_drives = MAX_HDISK;
;        return(TRUE);
;       END
;END

get_drive_parameters:
		;push	bp
		;mov	bp,sp

		;push	es
		;push	di

		;mov	dl,[bp+4] ; hard disk drive number (80h = C:)
		mov	ah,8 ; Return Disk parameters
		int	13h
			; AL = 0
			; CF = 1, Error
			;	AH = Error Code (>0)
			; CF = 0, NO error
			;	AH = 0
			; 	CH = Lower 8 bits of last cylinder number 
			;	CL = Sector number (bit 0 to bit 6) 
			;	     and High two bits of last cylinder number
			;	     (bits 7 and bit 8)
			;	DH = Last head number	
			;	DL = Number of hard disk drives
			; ES:DI = BIOS DPT address (Ref: AMIBIOS guide, 1993)	
		lahf

		push	ds
		pop	es

		;cmp	dl,0
		or	dl,dl
		jz	short gdprm_1

		and	ah,1 ; check cf
		jz	short gdprm_2
gdprm_1:
		; 22/12/2022
		; clear screen (black background)
		mov	bh, 7
		call	RVI_CLS
		mov	byte [mono_flag],1

		;push	word [error_1_seg]
		push	ds ; 17/11/2018
		push	word [error_1_off]
		call	display
		;pop	bx ; 19/11/2018 (!*!*)
		;pop	bx

		;sub	al,al
		sub	ax,ax ; 0
		;jmp	short gdprm_4
			; CF = 0, AL = 0 
		retn
gdprm_2:
		cmp	dl,8
		jbe	short gdprm_3
		mov	dl,8
gdprm_3:
		mov	[number_of_drives],dl
		;mov	al,1
		xor	ax,ax ; 14/12/2018
		inc	al  ; CF = 0, AL = 1	
gdprm_4:
		;pop	di
		;pop	es

		;;mov	sp,bp
		;pop	bp

		retn

; ----------------------------------------------------------------------------
;
;;; Temporary: 19/11/2018
;display:
;		pop	ax ; return address
;		pop	si ; offset error_1_msg
;		pop	bx ; segment	
;		;mov	si, error_1_msg
;		push	ax 
;		jmp	print_msg
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;error_1_msg:
;		db	0Dh,0Ah
;		db	'No fixed disks present!'
;		db	0Dh,0Ah,0
;error_1_off:
;		dw 	error_1_msg
;
; ----------------------------------------------------------------------------

; ----------------------------------------------------------------------------
; convert.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 16/11/2018)

;/*  */
;/*******************************************************************************/
;/*Routine name:  CYLINDERS_TO_MBYTES                                           */
;/*******************************************************************************/
;/*                                                                             */
;/*Description:   This routine will take input of cylinders and convert         */
;/*               it to MBytes.                                                 */
;/*                                                                             */
;/*                                                                             */
;/*Called Procedures:                                                           */
;/*                                                                             */
;/*                                                                             */
;/*Change History: Created        5/16/87         DRM                           */
;/*                                                                             */
;/*Input: Cylinders_in                                                          */
;/*                                                                             */
;/*Output: MBytes_out                                                           */
;/*                                                                             */
;/*                                                                             */
;/*                                                                             */
;/*******************************************************************************/

;XFLOAT	   cylinders_to_mbytes(cylinders_in,which_disk)
;
;unsigned	cylinders_in;
;char		which_disk;
;
;BEGIN
;
;unsigned	 mbytes_out;
;/*C34 unsigned long    number_of_bytes; */
;unsigned long	 number_of_sectors;
;unsigned long	 number_of_tracks;
;unsigned long	 bytes_in_one_sector;
;
;     bytes_in_one_sector = BYTES_PER_SECTOR;
;     number_of_tracks = (ul(cylinders_in) * ul(max_head[which_disk]));
;     number_of_sectors = (number_of_tracks * ul(max_sector[which_disk]));
;/*C34 number_of_bytes = (ul(number_of_sectors) * ul(bytes_in_one_sector)); */
;/*C34 mbytes_out =  f(number_of_bytes / ONE_MEG);                          */
;/*C34 if ((number_of_bytes % ONE_MEG) >= (ONE_MEG / 2)) mbytes_out++;      */
;     mbytes_out = numsecs_to_mbytes(number_of_sectors);                 /*C34*/
;     return(mbytes_out);
;
;END

cylinders_to_mbytes:

		; INPUT: BX = Disk/Drive number (0 to 7)
		;	 AX = Cylinders (Total or partition's cylinder count)	

		;push	bp
		;mov	bp,sp
		
		;mov	al,[bp+6] ; Disk/Drive number (0 to 7)
		;cbw
		;mov	bx,ax
		
		;mov	bl,[bp+6]
		;xor	bh,bh

		;shl	bx,1
		shl	bl,1  ; word index	

		;mov	cx,ax
		;mov	ax,[max_head+bx]
		;mul	word [bp+4]
		mov	dx,[max_head+bx]
		mul	dx
			; dx:ax = Number of tracks (cylinders*heads)

		;mov	bx,cx
		;shr	bx,1 ; byte index
		shr	bl,1 ; 11/12/2018
		mov	cl,[max_sector+bx]
		sub	ch,ch
		;sub	bx,bx ; 0
		sub	bl,bl ; 11/12/2018
		push	bx ; yh - multiplier_hw
		push	cx ; yl - multiplier_lw
		push	dx ; xh - multiplicand_hw
		push	ax ; xl - multiplicand_lw
		call	mul32
			; dx:ax = Number of sectors 
		;push	dx
		;push	ax
		call	numsecs_to_mbytes
			; AX = disk capacity as mega bytes
		;pop	bx
		;pop	bx

		;mov	sp,bp
		;pop	bp

		retn

; ----------------------------------------------------------------------------

;XFLOAT	   numsecs_to_mbytes(numsecs)
;unsigned  long numsecs;
;{
;
;unsigned long	 bytes_in_one_sector;
;/*C34 unsigned long    number_of_bytes; */
;unsigned         sectors_in_one_meg;					/*C34*/
;unsigned	 mbytes_out;
;
;     bytes_in_one_sector = BYTES_PER_SECTOR;
;/*C34 number_of_bytes = (numsecs * ul(bytes_in_one_sector));        */
;/*C34 mbytes_out =  f((number_of_bytes + ul(ONE_MEG/2)) / ONE_MEG); */
;     sectors_in_one_meg = u(ONE_MEG / bytes_in_one_sector);            /*C34*/
;     mbytes_out = f((numsecs + ul(sectors_in_one_meg/2)) / sectors_in_one_meg)
;									/*C34*/
;     return(mbytes_out);
;}

numsecs_to_mbytes:
		; INPUT: DX:AX = Sector count (32 bit)
		;   OUT:    AX = Mega bytes	
		;push	bp
		;mov	bp,sp
		;mov	ax,[bp+4] ; sector count lw
		;mov	dx,[bp+6] ; sector count hw

	;sectors_in_one_meg = u(ONE_MEG / bytes_in_one_sector);
	;mbytes_out = f((numsecs + ul(sectors_in_one_meg/2)) / sectors_in_one_meg)

		add	ax,1024 ; round up
		adc	dx,0
			; DX:AX = (X kilo byte)*2 sectors
		mov	cl,11 ; / 2048
		call	shr32
			; (X kilo bytes)*2 / 2048 = X/1024 mega bytes
		;mov	sp,bp
		;pop	bp
		retn

; ----------------------------------------------------------------------------

;unsigned  mbytes_to_percent(mbytes_used, total_cap)
;unsigned  mbytes_used;
;XFLOAT    total_cap;
;
;BEGIN
;
;unsigned      percentage_out;
;
;unsigned long large_number;
;
;	if (mbytes_used) {
;		large_number = ( mbytes_used * 100L ) +total_cap/2;
;		percentage_out = (unsigned) (large_number/total_cap);
;		if (percentage_out > u(100)) percentage_out = u(100);
;	}
;	else percentage_out = 0;
;    	return(percentage_out);
;END

mbytes_to_percent:
		; 21/11/2018

	;%define percent    bp-2
	%define partmbytes  bp+4  ; mbytes_used
	%define	totalmbytes bp+6  ; total_cap	

		push	bp
		mov	bp,sp
		;xor	bx,bx ; 0
		;push	bx
		
		;if (mbytes_used) {

		;cmp	word [partmbytes],0
		;je	short mtp_0

		mov	ax,[partmbytes]
		or	ax,ax
		jz	short mtp_0

		;large_number = ( mbytes_used * 100L ) +total_cap/2;

		;mov	ax,[totalmbytes]
		;sub	dx,dx
		;push	dx ; divisor_hw = 0
		;push	ax ; divisor_lw
		;;;push	ax ;* divisor (16 bit)
		mov	cx,[totalmbytes] ; divisor (16 bit)
		;mov	ax,100
		;mul	word [partmbytes] ; X
		mov	dx,100
		mul	dx		

		;mov	cx,[totalmbytes]
		;shr	cx,1
		;add	ax,cx
		
		;;;mov	bx,[totalmbytes]  ; Y
		mov	bx,cx
		shr	bx,1 ; 1/2 Y
		add	ax,bx ; ((100*X)/Y)+(0.5)*Y/Y
		adc	dx,0
		
		;percentage_out = (unsigned) (large_number/total_cap);

		;;;pop	cx ;* 21/11/2018 - divisor (16 bit)
		;push	dx ; dividend_hw
		;push	ax ; dividend_lw
		;call	div32

		; dx:ax = dividend (32 bit)
		; cx = divisor (16 bit)
		call	div32
		;mov	[percent],ax

		;if (percentage_out > u(100)) percentage_out = u(100);

		cmp	ax,100
		jbe	short mtp_0
		;mov	word [percent],100
		mov	ax,100
		;jmp	short mtp_1
mtp_0:
		;mov	word [percent],0
mtp_1:
		;mov	ax,[percent]
		;mov	sp,bp
		pop	bp

		retn	4 ; 06/01/2019

; ----------------------------------------------------------------------------

; 26/11/2018

;/*  */
;/*******************************************************************************/
;/*Routine name:  CYLINDERS_TO_PERCENT                                          */
;/*******************************************************************************/
;/*                                                                             */
;/*Description:   This routine will take input of cylinders and convert         */
;/*               it to Percent.                                                */
;/*                                                                             */
;/*                                                                             */
;/*Called Procedures:                                                           */
;/*                                                                             */
;/*                                                                             */
;/*Change History: Created        5/16/87         DRM                           */
;/*                                                                             */
;/*Input: Cylinders_in                                                          */
;/*                                                                             */
;/*Output: percent_out                                                          */
;/*                                                                             */
;/*                                                                             */
;/*******************************************************************************/

;unsigned  cylinders_to_percent(cylinders_in,total_cylinders)
;
;unsigned      cylinders_in;
;unsigned      total_cylinders;
;
;BEGIN
;
;unsigned      percentage_out;
;
;/* SR; 9/26/89; Changed from double to unsigned long */
;unsigned long large_number;
;
;    /* This is the same as (cyl_in / tot_cyl) * 100 to get the percentage */
;    /* because * 100 is really 100/1 which is (cyl_in*100)/(tot_cyl*1).   */
;
;	 /* SR; 9/26/89; Check for cylinders_in = 0 because round off errors
;		may cause total_cylinders = 1 but cylinders_in = 0 */
;    if (cylinders_in == 0)
;	 percentage_out = 0;
;    else if (total_cylinders == 0)
;            percentage_out = 0;
;         else
;            BEGIN
;	       /* SR; 9/26/89; Changed double to unsigned long */
;	       large_number = (unsigned long)(ul(cylinders_in) * 100l);
;	       percentage_out = u(large_number / total_cylinders);
;            END
;    /* this should round up to the next percent if more than .5 percent */
;
;	 /* SR; 9/26/89; Need type cast to long or results truncated */
;    if ((((long)cylinders_in * 100l) % total_cylinders) >= (total_cylinders / 2))
;       percentage_out++;
;    if (percentage_out > u(100)) percentage_out = u(100);
;    return(percentage_out);
;END

cylinders_to_percent:
		; 26/11/2018
		; INPUT:
		;	bx = Number of cylinders (of partition) -dividend-
		;	cx = Total cylinders -divisor-
		; OUTPUT:
		;	ax = Percentage
		;
		; Modified registers: ax,bx,cx,dx	

		;;%define percentage_out bp-6
		;;%define percentage_out bp-2 ; **
		;%define cylinders_in	bp+4
		;%define total_cylinders bp+6

		;push	bp
		;mov	bp,sp
		;;sub	sp,6
		xor	ax,ax ; 26/11/2018 ; **
		;push	ax

		;  if (cylinders_in == 0)
		;	 percentage_out = 0;
		;  else if (total_cylinders == 0)
		;           percentage_out = 0;
		;       else

		;cmp	word [cylinders_in],0
		;cmp	[cylinders_in],ax ; 0
		;ja	short ctpc_2
		;mov	bx,[cylinders_in]
		or	bx,bx
		; 11/12/2018
		;jnz	short ctpc_2
		jz	short ctpc_6 ; ax = 0 = percentage_out 
ctpc_1:
		;;mov	word [percentage_out],0
		;;mov	[percentage_out],ax ; 0
		;;jmp	short ctpc_3
		; 11/12/2018
		;jmp	short ctpc_6 ; ax = 0 = percentage_out
ctpc_2:
		;cmp	word [total_cylinders],0
		;je	short ctpc_1	
	
		;mov	cx,[total_cylinders]
		or	cx,cx
		; 11/12/2018
		;jz	short ctpc_1
			; cx = Divisor
		jz	short ctpc_6

		;large_number = (unsigned long)(ul(cylinders_in) * 100l);
		;percentage_out = u(large_number / total_cylinders);
		
		;mov	ax,[total_cylinders]
		;sub	dx,dx
		;push	dx
		;push	ax
 
		mov	ax,100
		;mul	word [cylinders_in] ; 100*cylinders_in
		mul	bx ; [cylinders_in] 

		;push	dx
		;push	ax
			; dx:ax = Dividend

		call	div32	 ; 100*cylinders_in / total_cylinders
			; DX:AX = Quotient
			; BX = Remainder

		;mov	[percentage_out],ax
		
		; ax = percentage_out	
ctpc_3:

	;    if ((((long)cylinders_in * 100l) % total_cylinders) >= (total_cylinders / 2))
	;       percentage_out++;
	;    if (percentage_out > u(100)) percentage_out = u(100);
	;    return(percentage_out);

		;mov	ax,[total_cylinders]
		;sub	dx,dx
		;push	dx
		;push	ax
		;mov	ax,100
		;mul	word [cylinders_in]

		;push	dx
		;push	ax
		;call	_mod32

		;mov	cx,[total_cylinders]
		shr	cx,1	; total_cylinders/2
		;sub	bx,bx
		;cmp	dx,bx	; Remainder
		;jl	short ctpc_5
		;jg	short ctpc_4
		;cmp	ax,cx
		;jb	short ctpc_5
		cmp	bx,cx	; is remainder >= total_cylinders/2 ?
		jb	short ctpc_5 ; No. 
ctpc_4:
		;inc	word [percentage_out] ; Yes, (x.5)% --> (x+1)%
		inc	ax
ctpc_5:
		;cmp	word [percentage_out],100
		cmp	ax,100
		jbe	short ctpc_6
		;mov	word [percentage_out],100  ;  max. 100% (no 101%)
		mov	ax,100
ctpc_6:
		;;mov	ax,[percentage_out]
		;pop	ax ; [percentage_out]
		;;mov	sp,bp
		;pop	bp
		retn

; ----------------------------------------------------------------------------

; 32 bit multiplication (Microsoft C 6.0 runtime library, MSDOS 6.0, 1991)
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 16/11/2018)

mul32:
	%define MULTIPLICAND_L	bp+4  ; xl
	%define MULTIPLICAND_H	bp+6  ; xh
	%define MULTIPLIER_L	bp+8  ; yl
	%define MULTIPLIER_H	bp+10 ; yh

		push	bp
		mov	bp,sp
		mov	ax,[MULTIPLICAND_H] ; yh
		mov	cx,[MULTIPLIER_H]   ; xh
		or	cx,ax
		mov	cx,[MULTIPLIER_L]   ; yl
		jnz	short mul32_1
mul32_0:
		mov	ax,[MULTIPLICAND_L] ; xl
		mul	cx ; xl*yl
		pop	bp
		retn	8
mul32_1:
		push	bx
		mul	cx ; xh*yl
		mov	bx,ax ; (xh*yl)
		mov	ax,[MULTIPLICAND_L] ; xl 
		mul	word [MULTIPLIER_H] ; yh
		add	bx,ax ; (xh*yl)+(xl*yh)
		mov	ax,[MULTIPLICAND_L] ; xl
		mul	cx ; xl*yl
		add	dx,bx ; (H(xl*yl)+(xh*yl)+(xl*yh))
			      ; ax = L(xl*yl)	
		pop	bx
		pop	bp
		retn	8
			; 132*9
			; yl = 32, yh = 1
			; xl = 9, xh = 0
			; xh*yl = 0, xl*yh = 9
			; 32*9 = 288, H(xl*yl) = 2, L(xl*yl) = 88 (AA)
			; 2+9 = 11 (BB)
			; 132*9 = 1188 (BBAA)

; 32 bit shift (Microsoft C 6.0 runtime library, MSDOS 6.0, 1991)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 16/11/2018)

shr32:
		;xor	ch,ch
		;jcxz	short shr32_1
shr32_0:
		shr	dx,1
		rcr	ax,1
		;loop	shr32_0
		dec	cl
		jnz	short shr32_0
shr32_1:
		retn

; 32 bit division (Microsoft C 6.0 runtime library, MSDOS 6.0, 1991)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 21/11/2018)

;	%define dividend_lw bp+4
;	%define dividend_hw bp+6
;	%define divisor_lw  bp+8
;	%define divisor_hw  bp+10
;
;		push	bp
;		mov	bp,sp
;		push	bx
;		push	si
;		mov	ax,[divisor_hw]
;		or	ax,ax
;		jnz	short div32_0
;		mov	cx,[divisor_lw]
;		mov	ax,[dividend_hw]
;		xor	dx,dx
;		div	cx
;		mov	bx,ax
;		mov	ax,[dividend_lw]
;		div	cx
;		mov	dx,bx
;		jmp	short div32_4
;div32_0:
;		mov	cx,ax
;		mov	bx,[divisor_lw]
;		mov	dx,[dividend_hw]
;		mov	ax,[dividend_lw]
;div32_1:
;		shr	cx,1
;		rcr	bx,1
;		shr	dx,1
;		rcr	ax,1
;		or	cx,cx
;		jnz	short div32_1
;		div	bx
;		mov	si,ax
;		mul	word [divisor_hw]
;		xchg	ax,cx
;		mov	ax,[divisor_lw]
;		mul	si
;		add	dx,cx
;		jc	short div32_2
;		cmp	dx,[dividend_hw]
;		ja	short div32_2
;		jb	short div32_3
;		cmp	ax,[dividend_lw]
;		jbe	short div32_3
;div32_2:
;		dec	si
;div32_3:
;		xor	dx,dx
;		xchg	ax,si
;div32_4:
;		pop	si
;		pop	bx
;		pop	bp
;		retn	8

; 11/12/2018
div32:
		; 21/11/2018
		; DX:AX = Dividend
		; CX = Divisor

		mov	bx,ax  ; dividend_lw	
		mov	ax,dx  ; dividend_hw
		xor	dx,dx
		div	cx	
		xchg	bx,ax
		div	cx
		;mov	dx,bx
		xchg	dx,bx

		; DX:AX = Quotient
		; BX = Remainder 

		retn

; Remainder after 32 bit signed division (Microsoft C 6.0 runtime library)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 26/11/2018)

;;Note: This subroutine is not needed for assembly language programming
;; because, remainder is ready after a 32 bit division in dx (for 32/16 div)
;; or bx (for 32/32 division, div32) register.
; (as above!!) 

;_mod32:
;	%define _dividend_lw_ bp+4
;	%define _dividend_hw_ bp+6
;	%define _divisor_lw_  bp+8
;	%define _divisor_hw_  bp+10	
;
;		push	bp
;		mov	bp,sp
;		push	bx
;		push	di
;		xor	di,di
;		mov	ax,[_dividend_hw_]
;		or	ax,ax
;		jge	short _mod32_0
;		inc	di
;		mov	dx,[_dividend_lw_]
;		neg	ax
;		neg	dx
;		sbb	ax,0
;		mov	[_dividend_hw_],ax
;		mov	[_dividend_lw_],dx
;_mod32_0:
;		mov	ax,[_divisor_hw_]
;		or	ax,ax
;		jge	short _mod32_1
;		mov	dx,[_divisor_lw_]
;		neg	ax
;		neg	dx
;		sbb	ax,0
;		mov	[_divisor_hw_],ax
;		mov	[_divisor_lw_],dx
;_mod32_1:
;		or	ax,ax
;		jnz	short _mod32_2
;		mov	cx,[_divisor_lw_]
;		mov	ax,[_dividend_hw_]
;		xor	dx,dx
;		div	cx
;		mov	ax,[_dividend_lw_]
;		div	cx
;		mov	ax,dx
;		xor	dx,dx
;		dec	di
;		jns	short _mod32_6
;		jmp	short _mod32_7
;_mod32_2:
;		mov	bx,ax
;		mov	cx,[_divisor_lw_]
;		mov	dx,[_dividend_hw_]
;		mov	ax,[_dividend_lw_]
;_mod32_3:
;		shr	bx,1
;		rcr	cx,1
;		shr	dx,1
;		rcr	ax,1
;		or	bx,bx
;		jnz	short _mod32_3
;		div	cx
;		mov	cx,ax
;		mul	[_divisor_hw_]
;		xchg	ax,cx
;		mul	[_divisor_lw_]
;		add	dx,cx
;		jb	short _mod32_4
;		cmp	dx,[_dividend_hw_]
;		ja	short _mod32_4
;		jb	short _mod32_5
;		cmp	ax,[_dividend_lw_]
;		jbe	short _mod32_5
;_mod32_4:
;		sub	ax,[_divisor_lw_]
;		sbb	dx,[_divisor_hw_]
;_mod32_5:
;		sub	ax,[_dividend_lw_]
;		sbb	dx,[_dividend_hw_]
;		dec	di
;		jns	short _mod32_7
;_mod32_6:
;		neg	dx
;		neg	ax
;		sbb	dx,0
;_mod32_7:
;		; DX:AX = Remainder
;		pop	di
;		pop	bx
;		pop	bp
;		retn	8

;=============================================================================
;DOSEXIT (doscall.h, MSDOS 6.0, 1991) & 
;=============================================================================

; doscall.h (doscall.h, fdisk, MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------
;/***	DosExit - Exit a program
; *
; *	This call is issued when a thread completes its execution.
; *	The current thread is ended.
; */
;
;extern void far pascal DOSEXIT (
;	unsigned,			/* 0=end current thread, 1=end all */
;	unsigned );			/* Result Code to save for DosCwait */

; dos.asm (MSDOS 6.0, lib\common, 1991)
;*--------------------------------------------------------------------------*
;*                                                                          *
;*  DosExit(ec);                                                            *
;*                                                                          *
;*  Terminate program                                                       *
;*                                                                          *
;*--------------------------------------------------------------------------*

;cProc DosExit, <FAR, PUBLIC>
;ParmW   ec
;cBegin
;        mov     al,byte ptr ec
;        mov     ah,4Ch
;        int     21h
;cEnd


; DOSEXIT (IBM PC-DOS 7.0, FDISK, segment 2, 005DFh)
; ----------------------------------------------------------------------------

;DOSEXIT:	;proc near (Erdogan Tan)	; proc far (Original)
;
;%define ret_code bp+4 ; bp+6 ; word
;%define end_op	  bp+6 ; bp+8 ; word
;
;		push	bp
;		mov	bp,sp
;		push	bx
;		push	cx
;		push	dx
;		push	si
;		push	di
;		push	ds
;		push	es
;		push	ss
;		push	bp
;		mov	ax,[end_op]
;		cmp	ax,1
;		jg	short dosexit_0
;		mov	ax,[ret_code]
;		mov	ah,4Ch
;		int	21h		; DOS -	2+ - QUIT WITH EXIT CODE (EXIT)
;					; AL = exit code
;		xor	ax, ax
;dosexit_0:
;		pop	bp
;		pop	ss
;		pop	es
;		pop	ds
;		pop	di
;		pop	si
;		pop	dx
;		pop	cx
;		pop	bx
;		mov	sp,bp
;		pop	bp
;		;retf	4
;		retn	4

; ----------------------------------------------------------------------------
; display.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 16/11/2018)
			
;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: DISPLAY                                    */
;/*                                                             */
;/* DESCRIPTIVE NAME: Display full screen interface messages    */
;/*                                                             */
;/* FUNCTION: Displays messages and handles control characters  */
;/*                                                             */
;/* NOTES:                                                      */
;/*  FDISK MESSAGES                                             */
;/* Portions of the screen that are handled in the msg are      */
;/* indicated on the listing of the screen with the message     */
;/* name given.  If the text message is defined in another      */
;/* screen, then the name is followed by a "#" character        */
;/*                                                             */
;/* NOTE TO TRANSLATORS The characters inside the <> and the [] */
;/* are control characters and should not be translated.  The   */
;/* Control characters are defined as follows:                  */
;/*                                                             */
;/* <H> - Highlight the following text                          */
;/* <R> - Regular text                                          */
;/* <B> - Blink the following text                              */
;/* <O> - Turn blinking off                                     */
;/* <Y> - Print YES character, as set by define                 */
;/* <N> - Print NO character, as set by define                  */
;/* <W> - Sound the beep                                        */
;/* <S> - Save cursor position for later use                    */
;/* <I> - Insert character from insert[] string. This string    */
;/*       must be set up prior to displaying the message. The   */
;/*       first <I> will insert Insert[0], the second           */
;/*       insert[1], etc....This will move the cursor one       */
;/*       position. The insert[] string will be initialized     */
;/*                                                             */
;/* Multiple control characters can be between the <>.          */
;/*                                                             */
;/* The ^####^indicates Row and column for the text and has the */
;/* format of [rrcc] where the numbers are decimal and zero     */
;/* based (first row/col is 00.  The numbers are in decimal,    */
;/* and must be 2 characters, which means rows/cols 0-9 should  */
;/* be listed as 00-09.  For example, the 5th row, 3rd column   */
;/* on the screen would be listed as ^0402^.                    */
;/*                                                             */
;/* The column number is always the column desired.  The row    */
;/* number is an offset from the previous row.  For example, if */
;/* the text just printed is on row 6, and the next text should */
;/* be printed 2 rows down in column 0, then the control strin  */
;/* would be ^0201^.  The first row specified in the message is */
;/* assumed to be based off of row 0, it would actually specify */
;/* the actual row for the start of the msg to be printed.      */
;/*                                                             */
;/* ENTRY POINTS: display(*message_name);                       */
;/*      LINKAGE: Near call                                     */
;/*                                                             */
;/* INPUT: char *message_name                                   */
;/*                                                             */
;/* EXIT-NORMAL:                                                */
;/*                                                             */
;/* EXIT-ERROR:                                                 */
;/*                                                             */
;/* EFFECTS:                                                    */
;/* input_row changed if <S> control character in message       */
;/* input_col changed if <S> control character in message       */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/* viowrtcharstratt();                                         */
;/******************** END OF SPECIFICATIONS ********************/
;/*  */

;void display(s)
;
;char far *s;
;
;BEGIN
;       unsigned      row;
;       unsigned      col;
;       char          attribute;
;       char far      *attribute_ptr = &attribute;
;       unsigned      insert_count;
;
;       /* Initialize row and col, and index into array */
;       row = u(0);							/* AC000 */
;       col = u(0);							/* AC000 */
;       insert_count = u(0);						/* AC000 */
;       /* check for a request to display a null string */
;       if (*s == c('\0'))						/* AC000 */
;          BEGIN
;           /* Message string error */
;           insert[0] = c('1');						/* AC000 */
;           display(debug_msg);
;          END
;       else
;          BEGIN
;           /* There is data there, lets go handle it */
;
;			  if (status_flag == TRUE )
;				attribute = video_attribute;
;			  else
;           			attribute = c(0x00);			/* AC000 */
;
;           /* Go until end of string */
;           while (*s != c('\0'))                                       /* AC000 */
;              BEGIN
;
;               /* Check for any imbedded control strings */
;               switch (*s)
;                  BEGIN
;                   /* Check for control characters */
;                   case '<':
;			BEGIN
;                         s++;
;                         while ( (*s != c('>')) && (*s != c('\0')) ) /* AC000 */
;			      BEGIN
;                             	switch (*s++)
;				     BEGIN
;					case 'H': if (status_flag == FALSE)
;						     {				
;						       if (mono_flag == TRUE)				     /* AN006 */
;                                                      	  attribute = (attribute & 0x80) | HIWHITE_ON_BLACK; /* AN006 */
;                                                      else						     /* AN006 */
;                                                      	  attribute = (attribute & 0x80) | HIWHITE_ON_BLUE;  /* AC006 */
;						     }
;						  else
;						       attribute = (attribute & 0x80) | video_attribute;
;						       break;
;					case 'R': if (status_flag == FALSE)
;						     {				
;						       if (mono_flag == TRUE)				  /* AN006 */
;                                                         attribute = (attribute & 0x80) | GRAY_ON_BLACK; /* AN006 */
;                                                      else						  /* AN006 */
;							  attribute = (attribute & 0x80) | WHITE_ON_BLUE; /* AC006 */
;						     }
;						  else
;						       attribute = (attribute & 0x80) | video_attribute;
;						       break;
;					case 'B': attribute |= 0x80;
;                                                 break;
;					case 'O': attribute &= 0x7F;
;                                                 break;
;					case 'W': DOSBEEP(u(900),u(400)); /* AC000 */
;                                                 break;
;					case 'I': if (status_flag == TRUE)
;						    attribute = video_attribute;
;						  else
;						    BEGIN
;							/* display next element in the array */
;                                                  	if ((mono_flag == TRUE) && (attribute == c(0x00)))  /* AN006 */
;                                                      	   attribute = c(GRAY_ON_BLACK);		    /* AN006 */
;                                                  	if ((mono_flag == FALSE) && (attribute == c(0x00))) /* AN006 */
;                                                      	   attribute = c(WHITE_ON_BLUE);		    /* AC006 */
;						    END
;              					  VIOWRTCHARSTRATT(pinsert+insert_count++,u(1),row,col++,attribute_ptr,u(0));
;                                                 break;
;					case 'Y':                                                          /* AC011 */
;                                                 BEGIN
;                                                   /* display YES character in next location */
;                                                   if ((mono_flag == TRUE) && (attribute == c(0x00)))      /* AN006 */
;                                                      attribute = c(GRAY_ON_BLACK);                       /* AN006 */
;                                                   if ((mono_flag == FALSE) && (attribute == c(0x00)))     /* AN006 */
;                                                      attribute = c(WHITE_ON_BLUE);                       /* AC006 */
;                                                   VIOWRTCHARSTRATT(&Yes,u(1),row,col++,attribute_ptr,u(0)); /* AC000 */
;                                                   break;
;                                                 END
;					case 'N':                                                          /* AC011 */
;                                                 BEGIN
;                                                   /* display NO character in next location */
;                                                   if ((mono_flag == TRUE) && (attribute == c(0x00)))      /* AN006 */
;                                                      attribute = c(GRAY_ON_BLACK);                       /* AN006 */
;                                                   if ((mono_flag == FALSE) && (attribute == c(0x00)))     /* AN006 */
;                                                      attribute = c(WHITE_ON_BLUE);                       /* AC006 */
;                                                   VIOWRTCHARSTRATT(&No,u(1),row,col++,attribute_ptr,u(0)); /* AC000 */
;                                                   break;
;                                                 END
;					case 'S':
;                                                 BEGIN
;                                                   input_row = row;
;                                                   input_col = col;
;                                                   break;
;                                                 END
;					case 'C':
;                                                 BEGIN
;                                                   /* Clear from current position to end of line */
;                                                   clear_screen(row,col,row,u(79)); /* AC000 */
;                                                   break;
;                                                 END
;					case '\0':
;                                                 BEGIN
;                                                   /* Message string error - string ended in the middle of control string*/
;                                                   insert[0] = c('7');	/* AC000 */
;                                                   display(debug_msg);
;                                                   break;
;						  END
;					default:
;                                                 BEGIN
;                                                   /* Message string error - no valid control char found */
;                                                   insert[0] = c('6');	/* AC000 */
;                                                   display(debug_msg);
;                                                   break;
;                                                 END
;				   END /* Switch */
;			     END /* While */
;			     /* Get the pointer past the '>' */
;                            s++;
;                            break;
;                        END /* control characters */
;
;                   /* Check for row,col */
;                   case '':                                           /* AC000 */
;			BEGIN
;			     s++;
;                            /* determine the row to put the message on */
;                            if ( !isdigit(*s) )
;				BEGIN
;				   /* Message string error */
;                                  insert[0] = c('2');                  /* AC000 */
;                                  display(debug_msg);
;				END
; 			     else
;				BEGIN
;                                  row = row+((unsigned)(((*s++ - '0')*10)));
;                                  if ( !isdigit(*s) )
;                                     BEGIN
;                                       /* Message string error */
;                                       insert[0] = c('2');               /* AC000 */
;                                       display(debug_msg);
;                                     END
;                                  else
;                                     BEGIN
;                                       row = row+((unsigned)(*s++ - '0'));
;                                       /* determine the col to put the message on */
;                                       if ( !isdigit(*s) )
;                                          BEGIN
;                                            /* Message string error */
;                                            insert[0] = c('3');          /* AC000 */
;                                            display(debug_msg);
;                                          END
;					else
;                                          BEGIN
;                                            col = ((unsigned)(*s++ - '0'));
;                                            if ( !isdigit(*s) )
;                                               BEGIN
;                                                 /* Message string error */
;                                                 insert[0] = c('3');      /* AC000 */
;                                                 display(debug_msg);
;                                               END
;					     else
;                                                BEGIN
;                                                 col = ((unsigned)((col* 10) + (*s++ - '0')));
;                                                 if (*s++ != c(''))      /* AC000 */
;                                                    BEGIN
;                                                      /* Message string error */
;                                                      insert[0] = c('4');  /* AC000 */
;                                                      display(debug_msg);
;                                                    END /* 2nd sq bracket */
;                                                 END /* 2nd digit col */
;                                               END /* 1st digit col */
;                                           END /* 2nd digit row */
;                                       END /* 1st digit row */
;                              		break;
;				END
;                   /* Handle anything else */
;                   default:
;			BEGIN
;			   /* See if attribute set to anything */
;                          if ((mono_flag == FALSE) && (attribute == c(0x00)))	/* AN006 */
;			      attribute = c(WHITE_ON_BLUE);			/* AC006 */
;			   if ((mono_flag == TRUE) && (attribute == c(0x00)))	/* AN006 */
;			      attribute = c(GRAY_ON_BLACK);			/* AN006 */
;		   ;#ifdef DBCS    /* MSKK01 07/18/89 */
;		   ;       VIOWRTCHARSTRATT(s,u(1),row,col++,attribute_ptr,u(0)); /* AC000 */
;			   if (IsDBCSLeadByte( (unsigned char)*s ))
;			      VIOWRTCHARSTRATT(++s,u(1),row,col++,attribute_ptr,u(0)); /* AC000 */
;			   s++;
;		   ;#else
;                          VIOWRTCHARSTRATT(s++,u(1),row,col++,attribute_ptr,u(0)); /* AC000 */
;		   ;#endif
;                          break;
;                       END
;                  END
;              END /* End of string check */
;          END /* No characters in string check */
;       return;
;
;END

; 19/11/2018

display:
		%define	col 	      bp-12 ; word
		%define	insert_count  bp-10 ; word
		%define attribute_ptr bp-8  ; dword
		%define	row 	      bp-4  ; word
		%define attribute     bp-2  ; word

		%define _s_ 	      bp+4  ; arg_0, dword

		push	bp
		mov	bp,sp
		sub	sp,12

		lea	ax,[attribute]
		mov	[attribute_ptr],ax
		mov	[attribute_ptr+2],ss

		;/* Initialize row and col, and index into array */
		sub	ax,ax ; 0
		mov	[row],ax
		mov	[col],ax
		mov	[insert_count],ax

		mov	[attribute],al ; 0 ; 19/11/2018
		
		;/* check for a request to display a null string */
		
		;if (*s == c('\0')) 
		les	bx,[_s_]
		cmp	byte [es:bx],0
		jne	short display_1
		;/* Message string error */
		mov	byte [insert],'1'
		;push	word [debug_msg_seg]
		push	ds ; 17/11/2018
		push	word [debug_msg_off]
		call	display
		;pop	bx	; 19/11/2018 ; (!*!*)
		;pop	bx
		jmp	display_43
display_1:
		;/* There is data there, lets go handle it */

		;if (status_flag == TRUE )
		; 	attribute = video_attribute;

		cmp	byte [status_flag],1 ; TRUE
		jne	short display_2
		mov	al,[video_attribute]
		mov	[attribute],al
		jmp	short display_3 ; 19/11/2018
;display_2:
;		;else
;		;	attribute = c(0x00);
;
;		;mov	byte [attribute],0 ; 19/11/2018
;display_3:
display_2:	;/* Go until end of string */

		; while (*s != c('\0')) 
		les	bx,[_s_]
		;cmp	byte [es:bx],0
		;jne	short display_4
display_3:
		; 19/11/2018
		mov	al,[es:bx]
		or	al,al
		jnz	short display_4		
		jmp	display_43
display_4:
		;/* Check for any imbedded control strings */
		
		;switch (*s)
		
		; /* Check for control characters */
		;mov	al,[es:bx]
		;cbw
		;sub	ax,6
		xor	ah,ah
		sub	al,6 ; Check for char 06h (ACK)
		jnz	short sc_default ; default : 
		jmp	display_36 ; case '': 
sc_default:
		;sub	ax,'6' ; '<' (3Ch)
		sub	al,'6' ; 19/11/2018
		jz	short display_7  ; case '<':

		;/* Handle anything else */
;default:
		;/* See if attribute set to anything */
		cmp	byte [mono_flag],0 ; FALSE
		jne	short display_5
			;&&
		cmp	byte [attribute],0
		;jne	short display_5
		jne	short display_6 ; 19/11/2018
		mov	byte [attribute],17h ; WHITE_ON_BLUE
;display_5:
		cmp	byte [mono_flag],1 ; TRUE
		jne	short display_6
			;&&
display_5: ; 19/11/2018
		cmp	byte [attribute],0
		jne	short display_6
		mov	byte [attribute],7 ; GRAY_ON_BLACK
display_6:
		;VIOWRTCHARSTRATT(s++,u(1),row,col++,attribute_ptr,u(0))
		push	es
		push	bx
		inc	word [_s_]
		mov	ax,1
		push	ax
		push	word [row]
		push	word [col]			
		;inc	word [col]
		inc	byte [col]
		;push	ss ; 17/11/2018
		push	word [attribute_ptr+2]	; segment
		push	word [attribute_ptr]	; offset
		; 19/11/2018
		;sub	ax,ax ; 0
		;push	ax
		call	VIOWRTCHARSTRATT
		;jmp	short display_3
		jmp	short display_2 ; 19/11/2018
display_7:
;case '<':
		;s++;
		inc	word [_s_]
sc_break:
		;while ( (*s != c('>')) && (*s != c('\0')) ) /* AC000 */

		les	bx,[_s_]
		mov	al,[es:bx]
		;cmp	byte ptr [es:bx],'>'
		cmp	al,'>'
		jne	short display_8 ; &&
		jmp	display_35
display_8:
		;cmp	byte [es:bx], 0
		;jne	short display_9
		and	al,al	; cmp al,0
		jnz	short display_9
		jmp	display_35
display_9:
		;switch (*s++)
		inc	word [_s_]
		;mov	al,[es:bx] ; 19/11/2018
		;cbw
		;cmp	ax,'Y'
		cmp	al,'Y'
		jne	short display_10
		jmp	case_Y  ; case 'Y'
display_10:
		ja	short display_17
		; 19/11/2018
		;or	al,al
		;jnz	short display_11
		;jmp	case_0  ; case '\0'
display_11:
		sub	al,'B'
		jnz	short display_12
		jmp	display_25  ; case 'B'
display_12:
		; AL > 0 and AL < 'Y'-'B'
		dec	al ; AL = 1 ('C'-'B') ?
		jnz	short display_13
		jmp	case_C	; case 'C'
display_13:	
		sub	al,5 ; AL = 5 ('H'-'C') ?
		jz	short display_19 ; case 'H'
		dec	al
		jnz	short display_14
		jmp	case_I ; case 'I'
display_14:
		sub	al,5 ; AL = 5 ('N'-'I') ?
		jnz	short display_15
		jmp	case_N	; case 'N'
display_15:
		dec	al   ; 'O' ?
		jz	short display_26  ; case 'O'
		sub	al,3 ; 'R' ?
		jz	short display_23  ; case 'R'	
		dec	al
		jnz	short display_16
		jmp	case_S  ; case 'S'
display_16:
		sub	al,4  ; 'W' ?
		jz	short case_W ; case 'W'
display_17:
;default:
		;/* Message string error - no valid control char found */
		mov	byte [insert],'6'
display_18:
		;push	word [debug_msg_seg]
		push	ds ; 17/11/2018 
		push	word [debug_msg_off]
		call	display
		;pop	bx	; 19/11/2018 ; (!*!*)
		;pop	bx
		jmp	short sc_break
display_19:
;case 'H':	;if (status_flag == FALSE)
		cmp	byte [status_flag],0
		jne	short display_22
		cmp	byte [mono_flag],1
		jne	short display_20
		;attribute = (attribute & 0x80) | HIWHITE_ON_BLACK;
		mov	al,[attribute]
		and	al,8Fh
		or	al,0Fh ; HIWHITE_ON_BLACK
		jmp	short display_21
display_20:
		mov	al,[attribute]
		;attribute = (attribute & 0x80) | WHITE_ON_BLUE;
		and	al,9Fh
		or	al,1Fh ; WHITE_ON_BLUE
display_21:
		mov	byte [attribute],al
		jmp	sc_break
display_22:	
		;(status_flag == TRUE)
		;attribute = (attribute & 0x80) | video_attribute;
		mov	al,[attribute]
		and	al,80h
		or	al,[video_attribute]
		jmp	short display_21
display_23:
;case 'R':
		;if (status_flag == FALSE)
		cmp	byte [status_flag],0
		jne	short display_22
		;if (mono_flag == TRUE) 
		cmp	byte [mono_flag],1
		jne	short display_24
		;attribute = (attribute & 0x80) | GRAY_ON_BLACK
		mov	al,[attribute]
		and	al,87h
		or	al,7  ; GRAY_ON_BLACK
		jmp	short display_21
display_24:
		;attribute = (attribute & 0x80) | WHITE_ON_BLUE;
		mov	al,[attribute]
		and	al,97h
		or	al,17h	; WHITE_ON_BLUE
		jmp	short display_21
display_25:
; case 'B':	;attribute |= 0x80;
		or	byte [attribute],80h
		jmp	sc_break
display_26:
;case 'O':	;attribute &= 0x7F;
		and	byte [attribute],7Fh
		jmp	sc_break
case_W:
		;DOSBEEP(u(900),u(400))
		;mov	ax,900
		;push	ax
		;mov	ax,400
		;push	ax
		call	DOSBEEP  ; 01/01/2019
		jmp	sc_break
case_I:
		;if (status_flag == TRUE)
		cmp	byte [status_flag],1
		jne	short display_27
				;attribute = video_attribute;
		mov	al,[video_attribute]
		mov	[attribute],al
		jmp	short display_29

display_27:
		;(status_flag == FALSE)

		;/* display next element in the array */

		;if ((mono_flag == TRUE) &&
		cmp	byte [mono_flag],1
		jne	short display_28
		; (attribute == c(0x00)))
		cmp	byte [attribute],0
		;jne	short display_28
		jne	short display_29 ; 17/11/2018
		;attribute = c(GRAY_ON_BLACK);      
		mov	byte [attribute],7 ; GRAY_ON_BLACK
		jmp	short display_29 ; 17/11/2018
;display_28:
;		;if ((mono_flag == FALSE) &&
;		cmp	byte [mono_flag],0
;		jne	short display_29
display_28: ; 17/11/2018
		;(attribute == c(0x00)))
		cmp	byte [attribute],0
		jne	short display_29
		;attribute = c(WHITE_ON_BLUE);
		mov	byte [attribute],17h ; WHITE_ON_BLUE
display_29:
		;VIOWRTCHARSTRATT(pinsert+insert_count++,u(1),row,col++,attribute_ptr,u(0));	

		; pinsert+insert_count++
		mov	ax,[insert_count]
		inc	word [insert_count]
		add	ax,[pinsert]
		jmp	short display_34
case_Y:
		;/* display YES character in next location */

		cmp	byte [mono_flag],1 ; TRUE
		jne	short display_30
			; &&
		cmp	byte [attribute],0
		;jne	short display_30
		jne	short display_31 ; 17/11/2018
		;if ((mono_flag == TRUE) && (attribute == c(0x00))) 
		mov	byte [attribute],7 ;attribute = c(GRAY_ON_BLACK);
;display_30:	
;		;if ((mono_flag == FALSE) && (attribute == c(0x00)))
;		cmp	byte [mono_flag],0  ; FALSE
;		jne	short display_31
			; &&
display_30: ; 17/11/2018
		cmp	byte [attribute],0
		jne	short display_31
		mov	byte [attribute], 17h ;attribute = c(WHITE_ON_BLUE);
display_31:
		;VIOWRTCHARSTRATT(&Yes,u(1),row,col++,attribute_ptr,u(0));

		mov	ax,Yes	; &YES, offset Yes
		jmp	short display_34
case_N:
		;/* display NO character in next location */

		cmp	byte [mono_flag],1 ; TRUE
		jne	short display_32
			; &&
		cmp	byte [attribute],0
		;jne	short display_32
		jne	short display_33 ; 17/11/2018
		;if ((mono_flag == TRUE) && (attribute == c(0x00))) 
		mov	byte [attribute],7 ;attribute = c(GRAY_ON_BLACK);
;display_32:
;		;if ((mono_flag == FALSE) && (attribute == c(0x00))) 
;		cmp	byte [mono_flag],0 ; FALSE
;		jne	short display_33
			; &&
display_32: ; 17/11/2018	
		cmp	byte [attribute],0
		jne	short display_33
		mov	byte [attribute],17h ;attribute = c(WHITE_ON_BLUE);
display_33:
		mov	ax,No	; &NO, offset No

		;VIOWRTCHARSTRATT(&No,u(1),row,col++,attribute_ptr,u(0));
display_34:
		;VIOWRTCHARSTRATT(pinsert+insert_count++,u(1),row,col++,attribute_ptr,u(0));
		;VIOWRTCHARSTRATT(&Yes,u(1),row,col++,attribute_ptr,u(0));

		; String address (far) to be written
		push	ds
		push	ax ; pinsert+insert_count++ (display_29) or &YES (display_31)
			   ; or &NO (display_33)
		; Length of string	
		mov	ax,1
		push	ax
		; Starting row position for output
		push	word [row]
		; Starting column position for output
		push	word [col]
		;inc	word [col]
		inc	byte [col]
		; Attribute address (far) to be replicated
		push	word [attribute_ptr+2] ; segment
		push	word [attribute_ptr] ; offset
		; Video handle (!is not used!)
		;sub	ax,ax
		;push	ax
		call	VIOWRTCHARSTRATT
		jmp	sc_break
case_S:
;case 'S':
		mov	ax,[row]
		mov	[input_row],ax
		mov	ax,[col]
		mov	[input_col],ax
		jmp	sc_break
case_C:
;case 'C':
		; /* Clear from current position to end of line */
		
		;clear_screen(row,col,row,u(79)); 
		mov	ax,79
		push	ax
		push	word [row]
		push	word [col]
		push	word [row]
		call	clear_screen ; clear_screen_down
		;add	sp,8
		jmp	sc_break
;case_0:	
;;case '\0': 
;	;/* Message string error - string ended in the middle of control string*/
;		mov	byte [insert],'7'
;		jmp	display_18
display_35:
		; /* Get the pointer past the '>' */
		;s++;
		inc	word [_s_]
		;break;
		;jmp	display_3
		jmp	display_2 ; 19/11/2018
		;END /* control characters */
display_36:	
		;/* Check for row,col */
;case '':
		;s++;
		inc	word [_s_]

		;/* determine the row to put the message on */

		;if ( !isdigit(*s) )
		mov	bx,[_s_]
		mov	al,[es:bx]
		;cbw
		mov	bx,ax
		test	byte [isdigit+bx],4
		jz	short display_37
		
		;row = row+((unsigned)(((*s++ - '0')*10)));
		;mov	bx,[_s_]
		inc	word [_s_]
		;mov	al,10
		;imul	byte [es:bx]
		sub	al,'0' ; 19/11/2018
		mov	bl,10
		mul	bl 
		;sub	ax,480 ; 1E0h (10*ASC('0'))
		add	[row],ax
		
		;if ( !isdigit(*s) )
		mov	bx,[_s_]
		mov	al,[es:bx] ; **
		;cbw	
		xor	ah,ah ; 19/11/2018
		mov	bx,ax
		test	byte [isdigit+bx],4
		jnz	short display_38
display_37:
		;/* Message string error */
		mov	byte [insert],'2'
		jmp	short display_40
display_38:
		;row = row+((unsigned)(*s++ - '0'));
		;mov	bx,[_s_] ; **
		inc	word [_s_]
		;mov	al,[es:bx] ; **
		;;cbw
		;;sub	ax,'0'
		sub	al,'0'
		;xor	ah,ah
		add	[row],ax
		
		;/* determine the col to put the message on */

		;if ( !isdigit(*s) )
		mov	bx,[_s_]
		mov	al,[es:bx] ; **
		;cbw
		mov	bx,ax
		test	byte [isdigit+bx],4
		jz	short display_39

		;col = ((uns/igned)(*s++ - '0'));
		;mov	bx,[_s_] ; **
		inc	word [_s_]
		;mov	al,[es:bx]
		;;cbw
		;;sub	ax,'0'
		sub	al,'0' ; **
		;xor	ah,ah
		mov	[col],ax
		
		;if ( !isdigit(*s) )
		mov	bx,[_s_]
		mov	al,[es:bx]
		;cbw
		mov	bx,ax ; *
		test	byte [isdigit+bx],4
		jnz	short display_41
display_39:	
		;/* Message string error */
		mov	byte [insert],'3'
display_40:
		;push	word [debug_msg_seg]
		push	ds ; 17/11/2018
		push	word [debug_msg_off]
		call	display
		;pop	bx ; 19/11/2018 ; (!*!*)
		;pop	bx
		;jmp	display_3
		jmp	display_2 ; 19/11/2018
display_41:
		;col = ((unsigned)((col* 10) + (*s++ - '0')));
		;mov	ax,10
		;mul	word [col]
		; 19/11/2018
		mov	al,10
		mul	byte [col]
		;mov	bx,[_s_]
		inc	word [_s_]
		;mov	cx,ax ; 19/11/2018
		;mov	al,[es:bx]
		;;cbw
		;;add	cx,ax
		;;sub	cx,'0'
		;sub	al,'0'
		;xor	ah,ah
		;add	cx,ax
		; 19/11/2018
		sub	bl,'0' ; *
		;add	cx,bx ; *
		;mov	[col],cx
		add	ax,bx ; *
		mov	[col],ax

		;if (*s++ != c('')) 
		mov	bx,[_s_]
		inc	word [_s_]
		cmp	byte [es:bx],6
		jne	short display_42
		;jmp	display_3
		jmp	display_2 ; 19/11/2018
display_42:
		;/* Message string error */
		mov	byte [insert],'4'
		jmp	short display_40
display_43:
		mov	sp,bp
		pop	bp
		;retn
		retn	4 ; 19/11/2018 (!*!*)

; video.asm (MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------
; 17/11/2018 - Modified for NASM syntax & FDISK subroutines (by Erdogan Tan)

; doscall.h (FDISK, MSDOS 6.0, 1991)

;/***	VioWrtCharStrAtt - Write Character String With Attribute
; *
; *	Write a character string with repeated attribute to the display
; */

;extern unsigned far pascal VIOWRTCHARSTRATT (
;	char far *,			/* String to be written */
;	unsigned,			/* Length of string */
;	unsigned,			/* Starting position for output (row) */
;	unsigned,			/* Starting position for output (col) */
;	char far *,			/* Attribute to be replicated */
;	unsigned );			/* Vio Handle */

; ============================================================================
; Write string (with specified attribute) at specified cursor position
; ============================================================================
; Disassembled from (PCDOS 7.0) FDISK.COM (Segment 3, Offset 00C3h)
; Modified for NASM syntax & FDISK (v2) subroutines (by Erdogan Tan)
; 17/11/2018

VIOWRTCHARSTRATT:  ; near procedure  (it was FAR proc in original FDISK.COM)	

	;%define _hnd-	bp+4  ; word   ; Vio Handle (!is not used!)
	 	
	%define _atr_	bp+4  ; bp+6  ; dword  ; Attribute ptr
	%define _col_	bp+8  ; bp+10 ; word   ; Column 
	%define _row_	bp+10 ; bp+12 ; word   ; Row	
	%define	_cnt_	bp+12 ; bp+14 ; word   ; Count
	%define _str_	bp+14 ; bp+16 ; dword  ; String ptr

		push	bp
		mov	bp,sp

		push	bx
		push	cx
		push	dx
		push	si
		push	di
		push	ds
		;push	es
		;push	ss
		;push	bp

		sub	bh,bh		; Video page 0
		;sub	ax,ax
		;mov	dx,[_col_]	; Put screen column in DL
		mov	dl,[_col_]

		cmp	dl,80		; Column limit check
		;jg	short viowchratt_2
		jnb	short viowchratt_2 ; 10/12/2018
		;mov	ax,[_row_]
		;cmp	al,25		; Row limit check
		mov	dh,[_row_]
		cmp	dh,25
		;jg	short viowchratt_2
		jnb	short viowchratt_2 ; 10/12/2018
		
		; Set cursor to Row,Col
		;mov	dh,al		; Put screen row in DH
		mov	ah,2		; BIOS set cursor function
		
		;push	bx
		;push	cx
		;push	dx
		;push	si
		;push	di
		;push	ds
		;push	es
		;push	ss
		;push	bp
				; - VIDEO - SET	CURSOR POSITION
		int	10h	; DH,DL	= row, column (0,0 = upper left)
				; BH = page number
		;pop	bp
		;pop	ss
		;pop	es
		;pop	ds
		;pop	di
		;pop	si
		;pop	dx
		;pop	cx
		;pop	bx

		lds	si,[_atr_]
		mov	bl,[si] 	; Attribute or color of character
		lds	si,[_str_]
		mov	di,[_cnt_] 	; String length (count of string characters)
viowchratt_0:
		;mov	al,[si] 	; ASCII code of character to be written
		lodsb	; 17/11/2017

		mov	ah,9 		; Function: Write character or attribute 
					;           at current cursor position
		mov	cx,1		; Number of repetitions
		
		;push	bx
		;push	cx
		;push	dx
		;push	si
		;push	di
		;push	ds
		;push	es
		;push	ss
		;push	bp
				; - VIDEO - WRITE ATTRIBUTES/CHARACTERS	AT CURSOR POSITION
		int	10h	; AL = character, BH = display page
				; BL = attributes of character (alpha modes) or	color (graphics	modes)
				; CX = number of times to write	character
		;pop	bp
		;pop	ss
		;pop	es
		;pop	ds
		;pop	di
		;pop	si
		;pop	dx
		;pop	cx
		;pop	bx
		
		;inc	si		; next char (ptr) ; 17/11/2017
		dec	di		; decrease count
		inc	dl		; next column
		cmp	dl,80		; column limit check
		jne	short viowchratt_1 ; ok
		inc	dh		; next row (and)
		mov	dl,0		; column 0
		cmp	dh,25		; Check row limit
		jne	short viowchratt_1 ; ok
		mov	ax,1		; Error 1 (string could not be written completely)
		jmp	short viowchratt_3
		;nop
viowchratt_1:
		mov	ah,2		; BIOS set cursor function

		;push	bx
		;push	cx
		;push	dx
		;push	si
		;push	di
		;push	ds
		;push	es
		;push	ss
		;push	bp
		
		int	10h	; - VIDEO - SET	CURSOR POSITION
				; DH,DL	= row, column (0,0 = upper left)
				; BH = page number
		;pop	bp
		;pop	ss
		;pop	es
		;pop	ds
		;pop	di
		;pop	si
		;pop	dx
		;pop	cx
		;pop	bx
		
		cmp	di,0	; is countdown completed?
		jne	short viowchratt_0 ; No
				; Yes	
		sub	ax,ax	; OK (successful, string written completely)

		jmp	short viowchratt_3 ; 17/11/2018 
viowchratt_2:
		mov	ax,2	; Error 2 (invalid column or row value)
viowchratt_3:
		;pop	bp
		;pop	ss
		;pop	es
		pop	ds
		pop	di
		pop	si
		pop	dx
		pop	cx
		pop	bx
		mov	sp,bp
		pop	bp
		;retn	16	; ? (with video handle) ?
		retn	14	; (without video handle)

; DOSBEEP (IBM PC-DOS 7.0 FDISK.COM)
; ----------------------------------------------------------------------------
; 17/11/2018 - Modified for NASM syntax & FDISK subroutines (by Erdogan Tan)

; ============================================================================
; DOSBEEP
; ============================================================================
; Disassembled from (PCDOS 7.0) FDISK.COM (Segment 2, Offset 0000h)
; Modified for NASM syntax & FDISK (v2) subroutines (by Erdogan Tan)
; 17/11/2018 

; doscall.h (FDISK, MSDOS 6.0, 1991)

;/***	DosBeep - Generate Sound From Speaker */
;
;extern unsigned far pascal DOSBEEP (
;	unsigned,			/* Hertz (25H-7FFFH) */
;	unsigned );			/* Length of sound  in ms */

DOSBEEP:	; near procedure (it was FAR proc in original FDISK.COM)	

	%define	duration  bp+4 ; bp+6 (far return) ; word
	%define frequency bp+6 ; bp+8 (far return) ; word

		;push	bp
		;mov	bp,sp
		
		push	bx
		push	cx
		push	dx
		
		;push	si
		;push	di
		;push	ds
		;push	es
		;push	ss
		;push	bp

		; 01/01/2019 (same frequency and duration for all DOSBEEPs)
		mov	bx,900 ; frequency
		mov	cx,400 ; duration	

		; set mode control register

		mov	al,0B6h ; 10-11-011-0b
				;  10b - timer counter 2
				;  11b - write LSB then MSB
				; 011b - mode 3 - generate square wave
				;   0b - binary counter

		out	43h,al	; Timer	8253-5 (AT: 8254.2).

		mov	dx,12h 	 ; 18
		mov	ax,2970h ; 10608
			; DX:AX = 122970h ; 1190256 (!?)
				; Note: This dividend value was/is 1193180 commonly

		; 01/01/2019 (900 Hertz and 400 milliseconds for all DOSBEEPs)

		;mov	cx,[frequency]	; value of frequency into CX
		;mov	bx,37	; Minimum 37 Hz
		;cmp	cx,bx
		;jl	short dosbeep_3 ; not a proper value (very low)
		;mov	bx,32767 ; Maximum 32767 Hz
		;cmp	cx,bx
		;jg	short dosbeep_3 ; not a proper value (very high)

		;div	cx
		div	bx	; 01/01/2019
		out	42h,al	; counter 2 divisor, LSB
		mov	al,ah
		out	42h,al	; counter 2 divisor, MSB

		; turn the sound on

		in	al,61h  ; read PPI port
				
				; PC/XT	PPI port B bits:
				; 0: Tmr 2 gate	--> OR	03H=spkr ON
				; 1: Tmr 2 data	-|  AND	0FCh=spkr OFF
				; 3: 1=read high switches
				; 4: 0=enable RAM parity checking
				; 5: 0=enable I/O channel check
				; 6: 0=hold keyboard clock low
				; 7: 0=enable kbrd

		mov	ah,al	; save PPI port bits/status

		or	al,3	; set bits 0 and 1 of port 61h to 1
		out	61h,al	; turn speaker and timer 2 clock on

		;mov	cx,[duration] ; value of the duration into CX
dosbeep_1:
		mov	bx,196  ; factor to convert milliseconds to loop count
				; (196 may be experimental, depending on CPU speed)
dosbeep_2:
		dec	bx
		jnz	short dosbeep_2  
				; delay depends on countdown start value and CPU speed 
		loop	dosbeep_1

		mov	al,ah	; restore port 61h bits/status
		out	61h,al	; (turn off speaker, restore frq)

		sub	ax,ax ; 0
;		jmp	short dosbeep_4  ; OK
;		;nop
;dosbeep_3:
;		mov	ax,2	; Error (invalid freq values)
dosbeep_4:
		;pop	bp
		;pop	ss
		;pop	es
		;pop	ds
		;pop	di
		;pop	si
		
		pop	dx
		pop	cx
		pop	bx

		;mov	sp,bp
		;pop	bp
		;retf	4
		;retn	4	; return and clean stack

		retn	; 01/01/2019

; ----------------------------------------------------------------------------
; fdisk.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 20/11/2018)

; 26/11/2018
; hdisk.h ; MSDOS 6.0, 1991
;/***************************************************************************/
;/* Hard disk partition record																*/
;/***************************************************************************/
;
;struct	Part
;{
;   unsigned char  BootIndicator;   /* If 80h means this is boot partition */
;   unsigned char  StartHead;	    /* Partition starting head based 0     */
;   unsigned char  StartSector;	    /* Partition starting sector based 1   */
;   unsigned char  StartCylinder;   /* Partion starting track based 0      */
;   	
;   unsigned char  SystemIndicator; /* Partition type signature field      */
;   unsigned char  EndHead; 	    /* Partition ending head based 0       */
;   unsigned char  EndSector;	    /* Partition ending sector based 1     */
;   unsigned char  EndCylinder;	    /* Partition ending track based 0      */
;   
;   unsigned long  RelativeSector;  /* Physcial starting sector based 0    */
;   unsigned long  TotalSectors;    /* Total physical sectors in partition */
;};


; 23/11/2018

; Partition Table Entry Structure (at offset 1BEh in MasterBoot sector)

struc pt_entry	; partition
.boot_ind: 	resb 1	; Active (bootable, 80h) or not (0)
.start_head:	resb 1	; Beginning head
.start_sector:	resb 1	; Beginning sector (6 bits, bits 0 to 5)
			; and high 2 bits of beginning cylinder
.start_cyl:	resb 1  ; Low 8 bits of beginning cylinder (total 10 bits)
.sys_id:	resb 1	; Partition (File System) ID (Type)
.end_head:	resb 1	; Ending head
.end_sector:	resb 1	; Ending sector (6 bits, bits 0 to 5)
			; and high 2 bits of ending cylinder
.end_cyl:	resb 1  ; Low 8 bits of ending cylinder (total 10 bits)
.rel_sec:	resd 1	; First sector relative to start of disk
.num_sec:	resd 1	; Number of sectors in partition
.entry_size:
endstruc

	; FDISK Partition Data (46 bytes)

struc pt_data	; partition_data
.boot_ind:	resb 1	; Active (Bootable) partition indicator
.start_head:	resb 1	; Start head (0 to 255)
.start_sector:	resb 1	; Start sector (1 to 63)
.start_cyl:	resw 1	; Start cylinder (0 to 1023)
.sys_id:	resb 1	; System (Partition, File System) ID
.end_head:	resb 1	; End head (0 to 255)
.end_sector:	resb 1	; End sector (1 to 63)	
.end_cyl:	resw 1	; End cylinder (0 to 1023)
.rec_sec_lw:	resw 1	; Beginning sector (LBA) of partition (low 16 bits)
.rel_sec_hw:	resw 1	; High 16 bits of beginning sector address	
.num_sec_lw:	resw 1	; Partition size in sectors (low 16 bits)
.num_sec_hw:	resw 1	; High 16 bits of sector count
.not_used:	resb 1	; (This struc byte is) not used in current FDISK
.changed:	resb 1	; Partition data changed flag
.mbytes_used:	resw 1	; Partition size in megabytes
.percent_used:	resw 1	; Percentage of total disk capacity (for partition)
.vol_label:	resb 12 ; Volume label
.system:	resb 9	; Partition (File System) name for partition ID 
.drive_letter:	resb 1	; Logical DOS drive letter (C,D,...)
.size:	; = 46 bytes
endstruc

;/*  */
;void init_partition_tables()
;BEGIN
;
;unsigned i;
;unsigned char j;
;/*C00 unsigned k;       */
;/*C00 unsigned l;       */
;unsigned partition_location;
;char temp;
;char more_drives_exist;
;char num_logical_drives;
;/*C00 unsigned insert;  */
;unsigned index;
;unsigned char active_primary_count;                                     /*C32*/
;unsigned char pri_part;                                                 /*C32*/
;
;	/* initialize first drive found to "C" */
;	next_letter = c(SEA);						/* AC000 */
;
;	/* initialize primary partition count */
;/*C32   primary_partition_count = 0; */
;
;	/* Look at both disks */
;	for (j = uc(0); j < number_of_drives; j++)                      /* AC000 */
;	   BEGIN
;
;	    /* initialize variables */                                  /*C32*/
;	    primary_partition_count = 0;                                /*C32*/
;	    active_primary_count = 0;                                   /*C32*/
;	    pri_part = 0xFF;                                            /*C32*/
;
;	    /* Initialize the cur_disk field to the drive in question so */
;	    /* that the calls to the partition information routines will work */
;	    cur_disk = ((char)(j));
;
;	    /* Read in the master boot record and see if it was okay */
;	    if (read_boot_record(u(0),j,uc(0),uc(1)))                  /* AC000 */
;	       BEGIN
;
;		/* See if there was a valid boot record there */
;		if ((boot_record[510] == uc(0x55)) && (boot_record[511] == uc(0xAA))) /* AC000 */
;		   BEGIN
;
;		    /* What was on the disk is a valid boot record, so save it */
;		    for (i=u(0);i < u(BYTES_PER_SECTOR); i++)           /* AC000 */
;		       BEGIN
;			master_boot_record[j][i] = boot_record[i];
;		       END
;		   END
;		/* We've now got a copy of the master boot record saved. Now we need */
;		/* to translate what in the boot record to the area that it's going  */
;		/* to be worked on (part_table) */
;
;		/* Read in the data from the master boot record partition entries*/
;		for (i=u(0); i < u(4); i++)                             /* AC000 */
;		   BEGIN
;		    index = i*16;
;
;		    /* Get boot ind */
;		    part_table[j][i].boot_ind = master_boot_record[j][0x1BE+index];
;
;		    /* Start head */
;		    part_table[j][i].start_head = master_boot_record[j][0x1BF+index];
;
;		    /* Start sector - unscramble it from INT 13 format*/
;		    part_table[j][i].start_sector= (master_boot_record[j][0x1C0+index] & 0x3F);
;
;		    /* Start cyl - unscramble it from INT 13 format*/
;		    part_table[j][i].start_cyl= ((((unsigned)master_boot_record[j][0x1C0+index]) & 0x00C0) << 2)
;						+ ((unsigned)master_boot_record[j][0x1C1+index]);
;
;		    /* System id */
;		    part_table[j][i].sys_id = master_boot_record[j][0x1C2+index];
;
;		    /* End head */
;		    part_table[j][i].end_head = master_boot_record[j][0x1C3+index];
;
;		    /* End sector - unscramble it from INT 13 format*/
;		    part_table[j][i].end_sector= (master_boot_record[j][0x1C4+index] & 0x3F);
;
;		    /* End cyl - unscramble it from INT 13 format*/
;		    part_table[j][i].end_cyl= ((((unsigned)master_boot_record[j][0x1C4+index]) & 0x00C0) << 2)
;						+ ((unsigned)master_boot_record[j][0x1C5+index]);
;
;		    /* Relative sectors */
;
;		    part_table[j][i].rel_sec =
;		       ((unsigned long)master_boot_record[j][0x1C9+index]) << 24;
;
;		    part_table[j][i].rel_sec = part_table[j][i].rel_sec +
;		       (((unsigned long)master_boot_record[j][0x1C8+index]) << 16);
;
;		    part_table[j][i].rel_sec = part_table[j][i].rel_sec +
;		       (((unsigned long)master_boot_record[j][0x1C7+index]) << 8);
;
;		    part_table[j][i].rel_sec = part_table[j][i].rel_sec +
;		       ((unsigned long)master_boot_record[j][0x1C6+index]);
;
;		    /* Number of sectors */
;		    part_table[j][i].num_sec =
;		       ((unsigned long)master_boot_record[j][0x1CD+index]) << 24;
;
;		    part_table[j][i].num_sec = part_table[j][i].num_sec +
;		       (((unsigned long)master_boot_record[j][0x1CC+index]) << 16);
;
;		    part_table[j][i].num_sec = part_table[j][i].num_sec +
;		       (((unsigned long)master_boot_record[j][0x1CB+index]) << 8);
;
;		    part_table[j][i].num_sec = part_table[j][i].num_sec +
;		       ((unsigned long)master_boot_record[j][0x1CA+index]);
;
;		    part_table[j][i].mbytes_used = (unsigned)
;		       numsecs_to_mbytes(part_table[j][i].num_sec);
;
;		    part_table[j][i].percent_used =
;		       mbytes_to_percent(part_table[j][i].mbytes_used,total_mbytes[cur_disk]);
;
;		    /* Set drive letter */
;		    if ( (part_table[j][i].sys_id == DOS12) ||  /* AN000 */
;			 (part_table[j][i].sys_id == DOS16) ||  /* AN000 */
;			 (part_table[j][i].sys_id == DOSNEW)   ) /* AN000 */
;		       {
;/*C32                  part_table[j][i].drive_letter = next_letter++;*/  /* AN000 */
;			part_table[j][i].drive_letter = c(' ');         /*C32*/ /* AN000 */
;			if ((primary_partition_count == 0) ||           /*C32*/
;			    ((part_table[j][i].boot_ind == 0x80) &&     /*C32*/
;			     (active_primary_count == 0)))              /*C32*/
;			    pri_part = c(i);                            /*C32*/
;			if (part_table[j][i].boot_ind == 0x80)          /*C32*/
;			    active_primary_count++;                     /*C32*/
;			primary_partition_count++; /*Keep track of partition number */
;		       }
;
;		    /* Set changed flag */
;		    part_table[j][i].changed = FALSE;
;		   END
;		if (pri_part != 0xFF)                                   /*C32*/
;		   {                                                    /*C32*/
;		    part_table[j][pri_part].drive_letter = next_letter++; /*C32*/
;		    get_volume(j,pri_part);                             
;		   }                                                    /*C32*/
;	       END
;	    else
;	       BEGIN
;		return;
;	       END
;	   END
;
;	/* Look at both disks */
;	for (j = uc(0); j < number_of_drives; j++)                     /* AC000 */
;	   BEGIN
;
;	    /* Initialize the cur_disk field to the drive in question so */
;	    /* that the calls to the partition information routines will work */
;	    cur_disk = ((char)(j));
;
;	    /* Read in the master boot record and see if it was okay */
;	    if (read_boot_record(u(0),j,uc(0),uc(1)))                  /* AC000 */
;	       BEGIN
;		/* Now, go read in extended partition info */
;		if (find_partition_type(uc(EXTENDED)))                 /* AC000 */
;		   BEGIN
;		    /* Initialize the array to zero's - include one dummy entry */
;		    for (i=u(0); i < u(24); i++)                       /* AC000 */
;		       BEGIN
;			ext_table[j][i].boot_ind = uc(0);              /* AC000 */
;			ext_table[j][i].start_head = uc(0);            /* AC000 */
;			ext_table[j][i].start_sector = uc(0);          /* AC000 */
;			ext_table[j][i].start_cyl = u(0);              /* AC000 */
;			ext_table[j][i].sys_id = uc(0);                /* AC000 */
;			ext_table[j][i].end_head = uc(0);              /* AC000 */
;			ext_table[j][i].end_sector = uc(0);            /* AC000 */
;			ext_table[j][i].end_cyl = u(0);                /* AC000 */
;			ext_table[j][i].rel_sec = ul(0);               /* AC000 */
;			ext_table[j][i].num_sec = ul(0);               /* AC000 */
;			ext_table[j][i].mbytes_used = f(0);            /* AN000 */
;			ext_table[j][i].percent_used = u(0);           /* AN000 */
;			ext_table[j][i].changed = FALSE;
;			ext_table[j][i].drive_letter = NUL;            /* AN000 */
;
;			strcpy(ext_table[cur_disk][i].system,NUL);     /* AN000 */
;			strcpy(ext_table[cur_disk][i].vol_label,NUL);  /* AN000 */
;
;		       END
;
;		    /* Find where the first extended boot record is */
;		    temp = find_partition_location(uc(EXTENDED));      /* AC000 */
;		    partition_location = part_table[j][temp].start_cyl;
;
;		    /* Go find extended boot records as long as there are more of them */
;		    more_drives_exist = TRUE;
;
;		    /* Init the number of logical drives, for a array index */
;		    num_logical_drives = c(0);                        /* AC000 */
;
;		    while (more_drives_exist)
;		       BEGIN
;		       /* Assume we won't find another logical drive */
;		       more_drives_exist = FALSE;
;
;			 /*Read in the extended boot record */
;			 if (read_boot_record(partition_location,
;					      j,
;					      uc(0),
;					      uc(1)))   /* AC000 */
;			    BEGIN
;			     load_logical_drive(num_logical_drives,j);
;
;
;			     /* find the next logical drive */
;			     for (i = u(0); i < u(4); i++)            /* AC000 */
;				BEGIN
;				 index = i*16;
;				 /* See if a sys id byte of extended exists */
;				 if (boot_record[0x1C2+index] == uc(EXTENDED))   /* AC000 */
;				    BEGIN
;				     /* Found another drive, now get its location */
;				     partition_location= (((((unsigned)(boot_record[0x1C0 + index])) & 0x00C0) << 2));
;				     partition_location = partition_location + ((unsigned)(boot_record[0x1C1+index]));
;
;				     /* Indicate we found another one */
;				     more_drives_exist = TRUE;
;
;				     /* Up the count of found ones */
;				     /* SR; 9/28/89; The count should be
;					incremented only if there is a
;					logical drive defined */
;				     if (ext_table[j][num_logical_drives].sys_id != 0)
;					 num_logical_drives++;
;				     break;
;				    END
;				END
;			    END
;		       END
;		   END
;	       END
;	   END
;
;	/* Look at all disks */                                         /*C32*/
;	for (j = uc(0); j < number_of_drives; j++)                      /*C32*/
;	   BEGIN                                                        /*C32*/
;									/*C32*/
;	    /* Look at all active primary partitions */                 /*C32*/
;	    for (i=u(0); i < u(4); i++)                                 /*C32*/
;	       BEGIN                                                    /*C32*/
;		/* Set drive letter */                                  /*C32*/
;		if (((part_table[j][i].sys_id == DOS12) ||              /*C32*/	/* AN000 */
;		     (part_table[j][i].sys_id == DOS16) ||              /*C32*/	/* AN000 */
;		     (part_table[j][i].sys_id == DOSNEW)) &&            /*C32*/	/* AN000 */
;		    (part_table[j][i].boot_ind == 0x80))                /*C32*/	/* AN000 */
;		   {                                                    /*C32*/
;		    if (part_table[j][i].drive_letter == c(' '))        /*C32*/
;		       {                                                /*C32*/
;			part_table[j][i].drive_letter = next_letter++;  /*C32*/	/* AN000 */
;			get_volume(j,i);                                /*C32*/
;		       }                                                /*C32*/
;		   }                                                    /*C32*/
;	       END                                                      /*C32*/
;									/*C32*/
;	    /* Look at all non-active primary partitions */             /*C32*/
;	    for (i=u(0); i < u(4); i++)                                 /*C32*/
;	       BEGIN                                                    /*C32*/
;		/* Set drive letter */                                  /*C32*/
;		if (((part_table[j][i].sys_id == DOS12) ||              /*C32*/	/* AN000 */
;		     (part_table[j][i].sys_id == DOS16) ||              /*C32*/	/* AN000 */
;		     (part_table[j][i].sys_id == DOSNEW)) &&            /*C32*/	/* AN000 */
;		    (part_table[j][i].boot_ind != 0x80))                /*C32*/	/* AN000 */
;		   {                                                    /*C32*/
;		    if (part_table[j][i].drive_letter == c(' '))        /*C32*/
;		       {                                                /*C32*/
;			part_table[j][i].drive_letter = next_letter++;  /*C32*/	/* AN000 */
;			get_volume(j,i);                                /*C32*/
;		       }                                                /*C32*/
;		   }                                                    /*C32*/
;	       END                                                      /*C32*/
;	   END                                                          /*C32*/
;
;	return;
;END

init_partition_tables:
		; 23/11/2018

	%define pt_num_sec_lw	     bp-22 ; word, unsigned int
	%define pt_num_sec_hw	     bp-20 ; word, unsigned int
	%define pt_rel_sec_temp_lw   bp-18 ; word, unsigned int
	%define pt_rel_sec_temp_hw   bp-16 ; word, unsigned int
	; 15/12/2018
	;%define more_drives_exist   bp-14 ; byte, unsigned int
	%define char_j		     bp-12 ; byte, char
	%define	unsigned_i	     bp-10 ; word, unsigned int
	%define active_primary_count bp-8  ; byte, unsigned char
	%define num_logical_drives   bp-6  ; byte, char	
	%define partition_location   bp-4  ; word, unsigned int	
	%define char_pri_part        bp-2  ; word, unsigned char

		; 14/12/2018
	;%define ext_part_num	     bp-24 ; byte, char
		; 15/12/2018
	%define ext_part_num	     bp-14 ; byte, char

		;push	bp
		mov	bp,sp
		;;;sub	sp,26
		;;sub	sp,22 ; 20/11/2018
		;sub	sp,24 ; 14/12/2018
		sub	sp,22 ; 15/12/2018 

		;push	di
		;push	si

		;/* initialize first drive found to "C" */
		mov	byte [next_letter],'C'
ipt_for1_0:
		;/* Look at both disks */
		;for (j = uc(0); j < number_of_drives; j++)
		
		; 11/12/2018
		;mov	byte [char_j],0
		;jmp	ipt_for1_1
		xor	ax,ax
		mov	[char_j],ax ; 0
ipt_for1_next:
		;/* initialize variables */ 
		mov	byte [primary_partition_count],0
		mov	byte [char_pri_part],0FFh
	;/* Initialize the cur_disk field to the drive in question so */
	;/* that the calls to the partition information routines will work */
		mov	[cur_disk],al
	;/* Read in the master boot record and see if it was okay */
	;if (read_boot_record(u(0),j,uc(0),uc(1)))
		;mov	cl,1
		mov	cx,1 ; 11/12/2018
		push	cx ; uc(1)
		sub	cl,cl
		mov	[active_primary_count],cl
		push	cx ; uc(0)
		push	ax ; j
		sub	ax,ax
		push	ax ; u(0)
		call	read_boot_record
		;add	sp,8	; 22/12/2018
		;or	al,al
		;jnz	short ipt_1
		jnc	short ipt_1 ; 27/11/2018
		jmp	ipt_26
ipt_1:
	;/* See if there was a valid boot record there */
	;if ((boot_record[510] == uc(0x55)) && (boot_record[511] == uc(0xAA)))
		;cmp	byte [boot_record+1FEh],55h
		;jne	short ipt_3
		;cmp	byte [boot_record+1FFh],0AAh
		;jne	short ipt_3
		;mov	word [unsigned_i],0

		; 14/12/2018
		mov	bx,[char_j]
		mov	dx,bx	; Disk/Drive number (0 to 7)
		shl	bx,9	; * 512 ; FDISK MBR offset

		; 23/11/2018
		cmp	word [boot_record+1FEh],0AA55h
		jne	short ipt_3
;ipt_2:
	;/* What was on the disk is a valid boot record, so save it */
	; for (i=u(0);i < u(BYTES_PER_SECTOR); i++)
	;     master_boot_record[j][i] = boot_record[i];

		;mov	bx,[unsigned_i]
		;mov	al,[boot_record+bx]
		;mov	cl,9
		;mov	dl,[char_j]
		;sub	dh,dh
		;mov	si,dx
		;shl	si,cl
		;mov	[master_boot_record+bx+si],al
		;inc	word [unsigned_i]
		;cmp	word [unsigned_i],512
		;jb	short ipt_2

		; 20/11/2018
		;mov	bl,[char_j] ; Drive number (0 to 7)
		;xor	bh,bh
		; 14/12/2018
		;mov	bx,[char_j] ; 11/12/2018
		;mov	dx,bx ; 21/11/2018	
		;shl	bx,9 ; * 512
		
		lea	di,[master_boot_record+bx] ; mbr 0 to mbr 7
		mov	si,boot_record
		mov	cx,256
		rep	movsw
ipt_3:
	;/* We've now got a copy of the master boot record saved. Now we need */
	;/* to translate what in the boot record to the area that it's going  */
	;/* to be worked on (part_table) */

		mov	word [unsigned_i],0
ipt_4:
   		; index = i*16;
		;
		; /* Get boot ind */
		; part_table[j][i].boot_ind = master_boot_record[j][0x1BE+index];

		;mov	al,[char_j] ; drive number 
		;sub	ah,ah
		;mov	cl,9
		;mov	dx,ax
		;shl	ax,cl

		; 21/11/2018	
		; bx = drive number * 512
		mov	cl,4
		;mov	bx,[unsigned_i]
		;shl	bx,cl
		;add	bx,ax
		; 14/12/2018
		mov	ax,[unsigned_i] ; partition (partition table entry) number
		;shl	ax,cl
		shl	al,cl ; 16*PartitionTableEntryNum	
		add	bx,ax ; MasterBoot Offset (for drive) + PT Entry offset
		;mov	al,[master_boot_record+1BEh+bx] ; Partition Table Entry address
		lea	si,[master_boot_record+1BEh+bx] ; 1BEh = Partition Table offset 
		lodsb 
		;xor	ah,ah
		mov	cx,ax
		;mov	ax,dx ; Drive Number (0 to 7)
		;shl	ax,1
		;shl	ax,1  ; Drive Number * 4
		mov	al,dl
		shl	al,1
		shl	al,1
		;add	ax,[unsigned_i] ; partition index number
		add	al,[unsigned_i]
		;mov	si,46
		;mul	si
		;mov	si,ax
		;mov	di,46 ; FDISK partition data/parameters (structure) size
		;mul	di
		mov	ah,46
		mul	ah
		mov	di,ax
		;mov	[part_table_boot_ind+si],cl
		mov	[part_table_boot_ind+di],cl

		;/* Start head */
		;mov	al,[master_boot_record+1BFh+bx]
		lodsb
		;mov	[part_table_start_head+si],al
		mov	[part_table_start_head+di],al

		;/* Start sector - unscramble it from INT 13 format*/
		;mov	al,[master_boot_record+1C0h+bx]
		;mov	cx,ax
		lodsb
		mov	cl,al
		and	al,3Fh
		;mov	[part_table_start_sector+si],al
		mov	[part_table_start_sector+di],al

		;/* Start cylinder - unscramble it from INT 13 format*/
		;mov	al,[master_boot_record+1C1h+bx]
		lodsb
		;sub	ah,ah
		;and	cx,0C0h
		; 11/12/2018
		;and	cl,0C0h 
		; ch = 0
		shl	cx,1
		shl	cx,1  ; 000000??00000000b ; high two bits
		;add	cx,ax
		mov	cl,al ; low 8 bits of cylinder
		;mov	[part_table_start_cyl+si],cx
		mov	[part_table_start_cyl+di],cx

		;/* System id */
		;mov	al,[master_boot_record+1C2h+bx]
		lodsb
		;mov	[part_table_sys_id+si],al
		mov	[part_table_sys_id+di],al

		;/* End head */
		;mov	al,[master_boot_record+1C3h+bx]
		lodsb
		;mov	[part_table_end_head+si],al
		mov	[part_table_end_head+di],al

		;/* End sector - unscramble it from INT 13 format*/
		;mov	al,[master_boot_record+1C4h+bx]
		lodsb
		;mov	cx,ax
		mov	cl,al
		and	al,3Fh
		;mov	[part_table_end_sector+si],al
		mov	[part_table_end_sector+di],al

		;/* End cylinder - unscramble it from INT 13 format*/
		;mov	al,[master_boot_record+1C5h+bx]
		lodsb
		and	cx,0C0h
		shl	cx,1
		shl	cx,1  ; 000000??00000000b ; high two bits	
		;add	cx,ax
		mov	cl,al ; low 8 bits of cylinder
		;mov	[part_table_end_cyl+si],cx
		mov	[part_table_end_cyl+di],cx

		;/* Relative sectors */

		;mov	al,[master_boot_record+1C9h+bx]
		;mov	ah,al
		;sub	al,al
		;sub	cx,cx
		;mov	[part_table_rec_sec_lw+si],cx
		;mov	[part_table_rel_sec_hw+si],ax
		;mov	dl,[master_boot_record+1C8h+bx]
		;sub	dh,dh
		;sub	di,di
		;add	cx,di
		;adc	ax,dx
		;mov	[part_table_rec_sec_lw+si],cx
		;mov	[part_table_rel_sec_hw+si],ax
		;mov	dx,ax
		;mov	al,[master_boot_record+1C7h+bx]
		;sub	ah,ah
		;mov	di,dx
		;;sub	dx,dx
		;mov	[pt_rel_sec_temp_lw],cx
		;mov	[pt_rel_sec_temp_hw],di
		;mov	cl,8
		;mov	di,bx
		;call	shl32
		;add	ax,[pt_rel_sec_temp_lw]
		;adc	dx,[pt_rel_sec_temp_hw]
		;mov	[part_table_rec_sec_lw+si],ax
		;mov	[part_table_rel_sec_hw+si],dx
		;mov	cl,[master_boot_record+1C6h+di]
		;sub	ch,ch
		;add	ax,cx
		;adc	dx,0

		; 21/11/2018
		lodsw	; mov ax,[master_boot_record+1C6h+bx]
		;mov	dx,ax ; *
		mov	[part_table_rel_sec_lw+di],ax ; 06/01/2019

		lodsw ; ** ; mov ax,[master_boot_record+1C8h+bx]; 
		;xchg	ax,dx
		; DX:AX = part_table_rel_sec (32 bit LBA value)
				
		;mov	[part_table_rel_sec_lw+si],ax
		;mov	[part_table_rel_sec_hw+si],dx

		; 06/01/2019
		mov	[part_table_rel_sec_hw+di],ax ; high word ; **

		;/* Number of sectors */

		;mov	al,[master_boot_record+1CDh+di]
		;mov	ah,al
		;sub	al,al
		;sub	cx,cx
		;mov	[part_table_num_sec_lw+si],cx
		;mov	[part_table_num_sec_hw+si],ax
		;mov	dl,[master_boot_record+1CCh+di]
		;sub	dh,dh
		;sub	bx,bx
		;add	cx,bx
		;adc	ax,dx
		;mov	[part_table_num_sec_lw+si],cx
		;mov	[part_table_num_sec_hw+si],ax
		;mov	dx,ax
		;mov	al,[master_boot_record+1CBh+di]
		;sub	ah,ah
		;mov	bx,dx
		;sub	dx,dx
		;mov	[pt_num_sec_lw],cx
		;mov	[pt_num_sec_hw],bx
		;mov	cl,8
		;call	shl32
		;add	ax,[pt_num_sec_lw]
		;adc	dx,[pt_num_sec_hw]
		;mov	[part_table_num_sec_lw+si],ax
		;mov	[part_table_num_sec_hw+si],dx
		;mov	cl,[master_boot_record+1CAh+di]
		;sub	ch,ch
		;add	ax,cx
		;adc	dx,0

		lodsw	; mov ax,[master_boot_record+1CAh+bx]
		mov	dx,ax ; ***

		lodsw	; mov ax,[master_boot_record+1CCh+bx]
		xchg	ax,dx ; ****
		; DX:AX = part_table_num_sec (32 bit LBA value)
		
		;mov	[part_table_num_sec_lw+si],ax
		;mov	[part_table_num_sec_hw+si],dx

		mov	[part_table_num_sec_lw+di],ax ; low word  ; ***
		mov	[part_table_num_sec_hw+di],dx ; high word ; ****		

	;part_table[j][i].mbytes_used = (unsigned)
	;  numsecs_to_mbytes(part_table[j][i].num_sec);

		;push	dx ; ****
		;;push	word [part_table_num_sec_lw+si]
		;push	ax ; ***
		;call	numsecs_to_mbytes
		;pop	bx
		;pop	bx

		call	numsecs_to_mbytes ; 21/11/2018

		;mov	[part_table_mbytes_used+si],ax
		mov	[part_table_mbytes_used+di],ax ; =*=

	; part_table[j][i].percent_used =
	;   mbytes_to_percent(part_table[j][i].mbytes_used,total_mbytes[cur_disk]);

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		; 14/12/2018
		xor	bh,bh
		mov	bl,[cur_disk]
		shl	bx,1
		push	word [total_mbytes+bx]
		;;push	word [part_table_mbytes_used+si]
		;push	word [part_table_mbytes_used+di]
		push	ax ; =*= ; 14/12/2018
		call	mbytes_to_percent
		;pop	bx ; 06/01/2019
		;pop	bx
		;mov	[part_table_percent_used+si],ax
		mov	[part_table_percent_used+di],ax

		;/* Set drive letter */

		;if ( (part_table[j][i].sys_id == DOS12) ||
		;     (part_table[j][i].sys_id == DOS16) ||
		;     (part_table[j][i].sys_id == DOSNEW)   )
		;       {

		;cmp	byte [part_table_sys_id+si],1 ; DOS12
		;je	short ipt_5
		;cmp	byte [part_table_sys_id+si],4 ; DOS16
		;je	short ipt_5
		;cmp	byte [part_table_sys_id+si],6 ; DOSNEW
		;jne	short ipt_9

		; 22/11/2018
		mov	al,[char_j] ; Drive number (0 to 7)
		;sub	ah,ah
		shl	al,1
		shl	al,1
		add	al,[unsigned_i] ; PT entry number (0 to 3)
		; ax = partition index (0 to 31)
		mov	cl,46 ; Partition data (structure) size
		mul	cl
		mov	bx,ax ; Partition data offset 

		mov	al,[part_table_sys_id+di] ; 06/01/2019

		;cmp	byte [part_table_sys_id+di],1 ; FAT12
		cmp	al,1
		je	short ipt_5
		;cmp	byte [part_table_sys_id+di],4 ; FAT16
		cmp	al,4
		je	short ipt_5
		;cmp	byte [part_table_sys_id+di],6 ; FAT16 big
		cmp	al,6
		jne	short ipt_9
ipt_5:
		;mov	al,[char_j] ; Drive number (0 to 7)
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[unsigned_i] ; PT entry number (0 to 3)
		; ax = partition index (0 to 31) 
		;mov	cx,46 ; Partition data (structure) size
		;mul	cx
		;mov	bx,ax ; Partition data offset
		
		;part_table[j][i].drive_letter = c(' ');  
		mov	byte [part_table_drive_letter+bx],' '

		;if ((primary_partition_count == 0) ||
		;   ((part_table[j][i].boot_ind == 0x80) &&
		;     (active_primary_count == 0)))
		;	pri_part = c(i);
		;	if (part_table[j][i].boot_ind == 0x80)
		;	   active_primary_count++;
		;	primary_partition_count++; /*Keep track of partition number */
		;	}

		cmp	byte [primary_partition_count],0
		je	short ipt_6
		cmp	byte [part_table_boot_ind+bx],80h
		;jne	short ipt_7
		jne	short ipt_8 ; 22/11/2018
		cmp	byte [active_primary_count],0
		;jne	short ipt_7
		ja	short ipt_7
ipt_6:
		mov	al,[unsigned_i]
		mov	[char_pri_part],al
ipt_7:
		; 22/11/2018
		;mov	al,[char_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[unsigned_i]
		;mul	cx
		;mov	bx,ax

		;cmp	byte [part_table_boot_ind+bx],80h
		;jne	short ipt_8

		inc	byte [active_primary_count]
ipt_8:
		inc	byte [primary_partition_count]
ipt_9:
		;mov	al,[char_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[unsigned_i]
		;mov	cx,46 ; Partition data (structure) size	
		;mul	cx
		;mov	bx,ax
	
		;/* Set changed flag */
		mov	byte [part_table_changed+bx],0
	
		;inc	word [unsigned_i]
		inc	byte [unsigned_i]
		;cmp	word [unsigned_i],4
		cmp	byte [unsigned_i],4
		jnb	short ipt_10

		; 22/11/2018
		;mov	bl,[char_j] ; Drive number (0 to 7)
		;xor	bh,bh

		; 11/12/2018
		mov	bx,[char_j]
	
		mov	dx,bx	; 21/11/2018	
		shl	bx,9	; Drive number * 512

		jmp	ipt_4
ipt_10:
		; 23/11/2018
		;if (pri_part != 0xFF) 
		cmp	byte [char_pri_part],0FFh
		je	short ipt_11

	;part_table[j][pri_part].drive_letter = next_letter++;
	;get_volume(j,pri_part);

		mov	al,[char_j] ; Disk/Drive number (0 to 7)
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		mov	cl,[char_pri_part]
		;sub	ch,ch
		;add	ax,cx
		add	al,cl
		;mov	bx,46 ; Partition data (structure) size	
		;imul	bx
		mov	bl,46
		mul	bl
		mov	bx,ax
		mov	al,[next_letter]
		inc	byte [next_letter]
		mov	[part_table_drive_letter+bx],al

		; 14/12/2018
		;push	cx
		mov	ah,cl  ; Partition number
		mov	al,[char_j] ; Disk/Drive number
		;push	ax
		call	get_volume
		;pop	bx
		;pop	bx
ipt_11:
		inc	byte [char_j]
ipt_for1_1:
		;/* Look at both disks */

		mov	al,[char_j] ; Drive number (0 to 7)
		cmp	[number_of_drives],al
		jna	short ipt_for2_0
		jmp	ipt_for1_next
ipt_for2_0:
		; 23/11/2018
		; Initializing logical dos drives (in extended partitions)

		;mov	byte [char_j],0
		;jmp	short ipt_for2_1
		; 11/12/2018
		xor	ax,ax
		mov	[char_j],al ; 0
		jmp	short ipt_for2_next
ipt_12:
		;inc	word [unsigned_i]
		inc	byte [unsigned_i] ; Partition number (0 to 3)
ipt_in_while_for_1:
		;cmp	word [unsigned_i],4
		cmp	byte [unsigned_i],4 ; Partition number (0 to 3)
		; 15/12/2018
		;jb	short ipt_in_while_for_next
		;jmp	ipt_while_more_drives_exist
		jnb	short ipt_while_end
		
ipt_in_while_for_next:
		;    /* See if a sys id byte of extended exists */
		;    if (boot_record[0x1C2+index] == uc(EXTENDED))
		;	BEGIN
		;	  /* Found another drive, now get its location */
		;	  partition_location = (((((unsigned)(boot_record[0x1C0 + index])) & 0x00C0) << 2));
		;	  partition_location = partition_location + ((unsigned)(boot_record[0x1C1+index]));

		mov	cl,4
		mov	bx,[unsigned_i] ; Partition number (0 to 3)
		;shl	bx,cl ; 16 * PTE number ; (= Partition Table offset from 1BEh. 0,16,32,48,64)
		shl	bl,cl
		cmp	byte [boot_record+1C2h+bx],5 ; System ID, EXTENDED 
		jne	short ipt_12
		mov	al,[boot_record+1C0h+bx] ; Partition Table Offset + sector byte
		and	ax,0C0h  ; Bit 6 and 7 are cylinder bits 8 and 9
		shl	ax,1
		shl	ax,1 ; (bits 8 and 9)
		;mov	cl,[boot_record+1C1h+bx] ; Partition Table Offset + cylinder (low) byte
		;sub	ch,ch
		;add	ax,cx
		mov	al,[boot_record+1C1h+bx] ; 23/11/2018
		mov	[partition_location],ax ; start cylinder 

		;	  /* Indicate we found another one */
		;	  more_drives_exist = TRUE;

		; 15/12/2018
		;mov	byte [more_drives_exist],1 ; TRUE

		;mov	al,[num_logical_drives]
		;cbw
		;mov	cx,ax
		;mov	cl,[num_logical_drives] ; 0 to 23

		;	  /* Up the count of found ones */
		;	  /* SR; 9/28/89; The count should be incremented 
		;	     only if there is a logical drive defined */
		;	  if (ext_table[j][num_logical_drives].sys_id != 0)
		;	     num_logical_drives++;
		;	     break;

		mov	al,24 ; 24 logical drives per disk (and 1 extended partition per disk)
		mul	byte [char_j] ; Disk/Drive number (0 to 7)
		;add	ax,cx
		;add	al,cl ; Logical partition index
		add	al,[num_logical_drives] ; 19/12/2018
		;mov	cx,46
		;imul	cx
		mov	cl,46 ; Logical partition data (structure) size
		mul	cl
		mov	bx,ax ; Logical partition data address
		cmp	byte [ext_table_sys_id+bx],0  ; System ID
		jne	short ipt_13
		;jmp	ipt_while_more_drives_exist
		jmp	ipt_in_while ; 15/12/2018
ipt_13:
		inc	byte [num_logical_drives]

		;jmp	ipt_while_more_drives_exist
		jmp	ipt_in_while ; 15/12/2018

ipt_while_end:
		inc	byte [char_j]
ipt_for2_1:
	;/* Initialize the cur_disk field to the drive in question so */
	;/* that the calls to the partition information routines will work */
		mov	al,[char_j]
		cmp	[number_of_drives],al
		ja	short ipt_for2_next
		jmp	ipt_16
ipt_for2_next:
		mov	[cur_disk],al
		; ah = 0 ; 11/12/2018

	;/* Read in the master boot record and see if it was okay */
	; if (read_boot_record(u(0),j,uc(0),uc(1)))    
		;mov	cl,1
		; 11/12/2018
		xor 	cx,cx
		inc	cl ; 1
		push	cx
		;sub	cl,cl
		dec	cl ; 0
		push	cx
		push	ax
		;sub	ax,ax
		sub	al,al ; 11/12/2018
		push	ax
		call	read_boot_record
		;add	sp,8	; 22/12/2018
		;or	al,al
		;jz	short ipt_while_end
		jc	short ipt_while_end ; 27/11/2018
	
	;/* Now, go read in extended partition info */
	; if (find_partition_type(uc(EXTENDED)))      
		mov	al,EXTENDED ; 5
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short ipt_while_end
		jc	short ipt_while_end ; 24/11/2018

		; 14/12/2018
		;mov	[ext_part_num],cl ; 0 to 3 
		mov	al,cl ; 15/12/2018

	;/* Initialize the array to zero's - include one dummy entry */
	; for (i=u(0); i < u(24); i++)
	;     BEGIN
	;	ext_table[j][i].boot_ind = uc(0);
	;	ext_table[j][i].start_head = uc(0);
	;	ext_table[j][i].start_sector = uc(0);
	;	ext_table[j][i].start_cyl = u(0);
	;	ext_table[j][i].sys_id = uc(0);
	;	ext_table[j][i].end_head = uc(0);
	;	ext_table[j][i].end_sector = uc(0);
	;	ext_table[j][i].end_cyl = u(0);
	;	ext_table[j][i].rel_sec = ul(0);
	;	ext_table[j][i].num_sec = ul(0);
	;	ext_table[j][i].mbytes_used = f(0);
	;	ext_table[j][i].percent_used = u(0);
	;	ext_table[j][i].changed = FALSE;
	;	ext_table[j][i].drive_letter = NUL;
	;
	;	strcpy(ext_table[cur_disk][i].system,NUL);
	;	strcpy(ext_table[cur_disk][i].vol_label,NUL);
	;     END

		;;mov	word [unsigned_i],0
		;mov	byte [unsigned_i],0
ipt_14:
;		mov	al,24 ; 24 logical drives
;		mul	byte [char_j] ; Disk/Driver number (0 to 7)
;		;add	ax,[unsigned_i]
;		add	al,[unsigned_i] ; 23/11/2018
;		;mov	cx,46
;		mov	cl,46
;		;mul	cx
;		mul	cl
;		mov	bx,ax ; Logical disk drive -partition- data offset
;		;sub	al,al ; 0
;		sub	ax,ax ; 0
;		mov	[ext_table_boot_ind+bx],al
;		mov	[ext_table_start_head+bx],al
;		mov	[ext_table_start_sector+bx],al
;		;mov	[ext_table_start_cyl+bx],0
;		mov	[ext_table_start_cyl+bx],ax
;		mov	[ext_table_sys_id+bx],al
;		mov	[ext_table_end_head+bx],al
;		mov	[ext_table_end_sector+bx],al
;		;mov	[ext_table_end_cyl+bx],0
;		mov	[ext_table_end_cyl+bx],ax
;		;sub	ax,ax ; 0
;		mov	[ext_table_rel_sec_hw+bx],ax
;		mov	[ext_table_rel_sec_lw+bx],ax
;		mov	[ext_table_num_sec_hw+bx],ax
;		mov	[ext_table_num_sec_lw+bx],ax
;		mov	[ext_table_mbytes_used+bx],ax
;		mov	[ext_table_percent_used+bx],ax
;		sub	al,al
;		mov	[ext_table_changed+bx],al
;		mov	[ext_table_drive_letter+bx],al
;		;sub	ax,ax ; 0
;		;push	ax ; NUL
;		mov	al,24
;		;imul	byte [cur_disk]
;		mul	byte [cur_disk] ; 23/11/2018
;		;add	ax,[unsigned_i] ; Current logical drive index (0 to 23)
;		add	al,[unsigned_i]
;		;mul	cx
;		mul	cl ; cl = 46
;		;;;mov	dx,ax ; *
;		;add	ax,ext_table_system ; Partition (File System) ID address
;		;push	ax
;		;call	strcpy
;		;pop	bx
;		;pop	bx
;		
;		; 23/11/2018 - clear Volume Name field (12 bytes)
;		mov	di,ext_table_vol_label 
;		add	di,ax
;		;sub	al,al
;		sub	ax,ax ; 0
;		;mov	cl,6 ; 6 words, 12 bytes
;		;;ch = 0
;		;rep	stosw
;		; System ID field -9 bytes- is just after Volume Name field
;		; ! Clear Volume Name and System ID fields. (21 bytes) !	
;		mov	cl,10 ; 10 words
;		rep	stosw
;		stosb	      ; +1 bytes = 12+9 bytes		
;		
;		;sub	ax,ax ; 0
;		;push	ax ; NUL
;		;mov	al,24
;		;;imul	byte [cur_disk]
;		;mul	byte [cur_disk]
;		;;add	ax,[unsigned_i]
;		;add	al,[unsigned_i]
;		;;mov	cx,46
;		;;mul	cx
;		;mov	cl,46
;		;mul	cl
;		;;;mov	ax,dx ; *
;		;add	ax,ext_table_vol_label ; Volume name address
;		
;		;push	ax
;		;call	strcpy
;		;pop	bx
;		;pop	bx
;
;		;; 23/11/2018 - clear Partition (File System) ID field (9 bytes)
;		;;mov	di,ext_table_system
;		;;add	di,ax ; (Already) System ID field is just after Volume Name field
;		;;;sub	ax,ax
;		;mov	cl,9 ; 9 bytes
;		;;ch = 0
;		;rep	stosb
;
;		;inc	word [unsigned_i]
;		inc	byte [unsigned_i]
;		;cmp	word [unsigned_i],24
;		cmp	byte [unsigned_i],24
;		jnb	short ipt_15
;		jmp	ipt_14

		; 14/12/2018
		; (bss -extended partition data area- already has been cleared)
		;		
		;; 23/11/2018
		;; Clear Logical Drive/Partition data area for current disk
		;mov	di,ext_table_boot_ind ; Start of logical drives data
		;mov	al,24
		;mul	byte [cur_disk]
		;mov	cl,46
		;mul	cl
		;; ax =  offset from ext_table_boot_ind
		;add	di,ax ; Start of logical drives data (for current disk)
		;
		;xor	ax,ax ; 0
		;mov	cx,(24*46)/2 ; 24 logical drives per extended partition (per disk) 
		;rep	stosw	; clear 552 words instead of 1104 bytes

ipt_15:
	;/* Find where the first extended boot record is */
	; temp = find_partition_location(uc(EXTENDED));
	; partition_location = part_table[j][temp].start_cyl;
		
		; 14/12/2018
		;mov	al,5 ; EXTENDED
		;;push	ax
		;call	find_partition_location
		;;pop	bx

		;mov	al,[ext_part_num] ; 14/12/2018
		; 15/12/2018
		; AL = Partition number of extended partition (in MBR)

		; 24/11/2018
			 ; AL = Partition number (0 to 3)
			 ; 	or AL =	0FFh (not found)
			 ; BX = Partition data (structure) offset ; =*=
		;cbw
		; ax = partition number (0 to 3) of extended partition
		mov	cl,[char_j] ; Disk number (0 to 7)
		;sub	ch,ch
		;shl	cx,1
		;shl	cx,1
		shl	cl,1
		shl	cl,1 ; 4 * disk number (every disk/MBR has 4 partition table entries) 
		;add	ax,cx ; Partition index in FDISK partitions data
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax ; Partition data (structure) offset -of extended partition-
 
		mov	ax,[part_table_start_cyl+bx]
		mov	[partition_location],ax ; start cylinder of extended partition

	;/* Go find extended boot records as long as there are more of them */
	; 	more_drives_exist = TRUE;
	;
	;/* Init the number of logical drives, for a array index */
	; 	num_logical_drives = c(0);

		;mov	byte [more_drives_exist],1  ; TRUE
		mov	byte [num_logical_drives],0

		; 15/12/2018
		;jmp	short ipt_in_while ; 23/11/2018

; 15/12/2018
;ipt_while_more_drives_exist:
;
;	;while (more_drives_exist)
;	;	BEGIN
;	;	/* Assume we won't find another logical drive */
;	;	more_drives_exist = FALSE;
;
;		cmp	byte [more_drives_exist],0
;		jne	short ipt_in_while
;		jmp	ipt_while_end

ipt_in_while:
		; 15/12/2018
		;mov	byte [more_drives_exist],0

	;	/*Read in the extended boot record */
	;	if (read_boot_record(partition_location,j,uc(0),uc(1)))
	;	BEGIN
	;	   load_logical_drive(num_logical_drives,j);

		;mov	al,1
		mov	ax,1 ; 11/12/2018
		push	ax
		sub	al,al ; 0
		push	ax
		mov	al,[char_j] ; Disk number (0 to 7)
		push	ax
		push	word [partition_location]
		call	read_boot_record
		;add	sp,8	; 22/12/2018
		;or	al,al
		;jz	short ipt_while_more_drives_exist
		;jc	short ipt_while_more_drives_exist ; 27/11/2018
		jc	short ipt_while_end
		;
		mov	al,[char_j]
		push	ax
		mov	al,[num_logical_drives]
		push	ax
		call	load_logical_drive
		;pop	bx ; 06/01/2019
		;pop	bx
ipt_in_while_for:
		;  /* find the next logical drive */
		;  for (i = u(0); i < u(4); i++)
		;      BEGIN
		;      index = i*16;

		;mov	word [unsigned_i],0
		mov	byte [unsigned_i],0 ; Partition number (0 to 3)
		;jmp	ipt_in_while_for_1
		; 14/12/2018
		jmp	ipt_in_while_for_next
ipt_16:
		; 23/11/2018
		; Set drive letters and volume names

		mov	byte [char_j],0
		jmp	short ipt_22
ipt_17:
		;inc	word [unsigned_i]
		inc	byte [unsigned_i]
ipt_18:
		;cmp	word [unsigned_i],4
		cmp	byte [unsigned_i],4
		jnb	short ipt_21
ipt_19:		
		; 23/11/2018
		;/* Look at all non-active primary partitions */  

		mov	al,[char_j] ; Disk number
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1 ; 4 partition table entries per disk/MBR
		;add	ax,[unsigned_i]
		add	al,[unsigned_i]
		;mov	cx,46
		;mul	cx
		mov	cl,46 ; Partition data (structure) size
		mul	cl
		mov	bx,ax ; Partition data address
		cmp	byte [part_table_sys_id+bx],1 ; DOS12
		je	short ipt_20
		cmp	byte [part_table_sys_id+bx],4 ; DOS16
		je	short ipt_20
		cmp	byte [part_table_sys_id+bx],6 ; DOSNEW
		jne	short ipt_17
ipt_20:
		;mov	al,[char_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[unsigned_i]
		;mul	cx
		;mov	bx,ax
		cmp	byte [part_table_boot_ind+bx],80h
		je	short ipt_17
		cmp	byte [part_table_drive_letter+bx],' '
		jne	short ipt_17
		mov	al,[next_letter]
		inc	byte [next_letter]
		mov	[part_table_drive_letter+bx],al
		
		; 14/12/2018
		;push	word [unsigned_i]
		mov	ah,[unsigned_i] ; Partition number		
		mov	al,[char_j] ; Disk number
		;push	ax
		call	get_volume
		;pop	bx
		;pop	bx
		jmp	short ipt_17
ipt_21:
		inc	byte [char_j]
ipt_22:
		; 23/11/2018
		;/* Look at all active primary partitions */

		;mov	al,[char_j]
		mov	al,[number_of_drives]
		;cmp	byte [number_of_drives],al
		;jbe	short ipt_26
		cmp	al,[char_j]
		jna	short ipt_26 ; 10/12/2018
		;mov	word [unsigned_i],0
		mov	byte [unsigned_i],0
ipt_23:
		mov	al,[char_j] ; Disk number (0 to 7)
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1 ; 4 partition entries in a MBR
		;add	ax,[unsigned_i]
		add	al,[unsigned_i] ; Partition index (for current disk)
		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax	; Partition data offset
		cmp	byte [part_table_sys_id+bx],1 ; DOS12 (FAT12)
		je	short ipt_24
		cmp	byte [part_table_sys_id+bx],4 ; DOS16 (FAT16)
		je	short ipt_24
		cmp	byte [part_table_sys_id+bx],6 ; DOSNEW (FAT16 big)
		jne	short ipt_25
ipt_24:
		;mov	al,[char_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[unsigned_i]
		;mul	cx
		;mov	bx,ax

		cmp	byte [part_table_boot_ind+bx],80h ; ACTIVE ?
		jne	short ipt_25
		cmp	byte [part_table_drive_letter+bx],' '
		jne	short ipt_25
		mov	al,[next_letter]
		inc	byte [next_letter]
		mov	[part_table_drive_letter+bx],al
		; 14/12/2018
		;push	word [unsigned_i]
		mov	ah,[unsigned_i] ; Partition number		
		mov	al,[char_j] ; Disk number
		;push	ax
		call	get_volume
		;pop	bx
		;pop	bx
ipt_25:
		;inc	word [unsigned_i]
		inc	byte [unsigned_i]
		;cmp	word [unsigned_i],4
		cmp	byte [unsigned_i],4
		jb	short ipt_23
		;mov	word [unsigned_i],0
		mov	byte [unsigned_i],0
		;jmp	ipt_18
		jmp	ipt_19 ; 23/11/2018
ipt_26:
		; 23/11/2018
		;pop	si
		;pop	di
		mov	sp,bp
		;pop	bp
		retn

; ----------------------------------------------------------------------------

; convert.c (FDISK, MSDOS 6.0, 1991)

;numsecs_to_mbytes:
;		; INPUT: DX:AX = Sector count (32 bit)	
;		;push	bp
;		;mov	bp,sp
;		;mov	ax,[bp+4] ; sector count lw
;		;mov	dx,[bp+6] ; sector count hw
;
;	;sectors_in_one_meg = u(ONE_MEG / bytes_in_one_sector);
;	;mbytes_out = f((numsecs + ul(sectors_in_one_meg/2)) / sectors_in_one_meg)
;
;		add	ax,1024 ; round up
;		adc	dx,0
;			; DX:AX = (X kilo byte)*2 sectors
;		mov	cl,11 ; / 2048
;		call	shr32
;			; (X kilo bytes)*2 / 2048 = X/1024 mega bytes
;		;mov	sp,bp
;		;pop	bp
;		retn

; ----------------------------------------------------------------------------

; convert.c (FDISK, MSDOS 6.0, 1991)

;mbytes_to_percent:
;		; 21/11/2018
;
;	;%define percent    bp-2
;	%define partmbytes  bp+4  ; mbytes_used
;	%define	totalmbytes bp+6  ; total_cap	
;
;		push	bp
;		mov	bp,sp
;		;xor	bx,bx ; 0
;		;push	bx
;		
;		;if (mbytes_used) {
;
;		;cmp	word [partmbytes],0
;		;je	short mtp_0
;		mov	ax,[partmbytes]
;		or	ax,ax
;		jz	short mtp_0
;
;		;large_number = ( mbytes_used * 100L ) +total_cap/2;
;
;		;mov	ax,[totalmbytes]
;		;sub	dx,dx
;		;push	dx ; divisor_hw = 0
;		;push	ax ; divisor_lw
;		;;;push	ax ;* divisor (16 bit)
;		mov	cx,[totalmbytes] ; divisor (16 bit)
;		;mov	ax,100
;		;mul	word [partmbytes] ; X
;		mov	dx,100
;		mul	dx		
;
;		;mov	cx,[totalmbytes]
;		;shr	cx,1
;		;add	ax,cx
;		
;		;;;mov	bx,[totalmbytes]  ; Y
;		mov	bx,cx
;		shr	bx,1 ; 1/2 Y
;		add	ax,bx ; ((100*X)/Y)+(0.5)*Y/Y
;		adc	dx,0
;		
;		;percentage_out = (unsigned) (large_number/total_cap);
;
;		;;;pop	cx ;* 21/11/2018 - divisor (16 bit)
;		;push	dx ; dividend_hw
;		;push	ax ; dividend_lw
;		;call	div32
;
;		; dx:ax = dividend (32 bit)
;		; cx = divisor (16 bit)
;		call	div32
;		;mov	[percent],ax
;
;		;if (percentage_out > u(100)) percentage_out = u(100);
;
;		cmp	ax,100
;		jbe	short mtp_0
;		;mov	word [percent],100
;		mov	ax,100
;		;jmp	short mtp_1
;mtp_0:
;		;mov	word [percent],0
;mtp_1:
;		;mov	ax,[percent]
;		;mov	sp,bp
;		pop	bp
;
;		retn	

; ----------------------------------------------------------------------------

;div32:
;	%define dividend_lw bp+4
;	%define dividend_hw bp+6
;	%define divisor_lw  bp+8
;	%define divisor_hw  bp+10
;
;		push	bp
;		mov	bp,sp
;		push	bx
;		push	si
;		mov	ax,[divisor_hw]
;		or	ax,ax
;		jnz	short div32_0
;		mov	cx,[divisor_lw]
;		mov	ax,[dividend_hw]
;		xor	dx,dx
;		div	cx
;		mov	bx,ax
;		mov	ax,[dividend_lw]
;		div	cx
;		mov	dx,bx
;		jmp	short div32_4
;div32_0:
;		mov	cx,ax
;		mov	bx,[divisor_lw]
;		mov	dx,[dividend_hw]
;		mov	ax,[dividend_lw]
;div32_1:
;		shr	cx,1
;		rcr	bx,1
;		shr	dx,1
;		rcr	ax,1
;		or	cx,cx
;		jnz	short div32_1
;		div	bx
;		mov	si,ax
;		mul	word [divisor_hw]
;		xchg	ax,cx
;		mov	ax,[divisor_lw]
;		mul	si
;		add	dx,cx
;		jc	short div32_2
;		cmp	dx,[dividend_hw]
;		ja	short div32_2
;		jb	short div32_3
;		cmp	ax,[dividend_lw]
;		jbe	short div32_3
;div32_2:
;		dec	si
;div32_3:
;		xor	dx,dx
;		xchg	ax,si
;div32_4:
;		pop	si
;		pop	bx
;		pop	bp
;		retn	8

;		mov	cx,[divisor_lw]
;		mov	ax,[dividend_hw]
;		xor	dx,dx
;		div	cx
;		mov	bx,ax
;		mov	ax,[dividend_lw]
;		div	cx
;		mov	dx,bx
;		jmp	short div32_4
;
;div32:
;		; 21/11/2018
;		; DX:AX = Dividend
;		; CX = Divisor
;
;		mov	bx,ax  ; dividend_lw	
;		mov	ax,dx  ; dividend_hw
;		xor	dx,dx
;		div	cx	
;		xchg	bx,ax
;		div	cx
;		;mov	dx,bx
;		xchg	dx,bx
;
;		; DX:AX = Quotient
;		; BX = Remainder
;
;		retn

; ----------------------------------------------------------------------------
; fdisk.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 23/11/2018)

;/*  */
;void get_volume(j,i)                                                    
;									/*C21*/
;unsigned char j;                                                        
;unsigned i;                                                             
;									/*C21*/
;BEGIN                                                                   
;									/*C21*/
;char     volume_label[13];                                              
;unsigned k;                                                             
;unsigned length;                                                        
;									/*C21*/
;    /* See if the disk has already been formated */                     
;    if (check_format(part_table[j][i].drive_letter) == TRUE )           
;       BEGIN                                                            
;	/* get volume and system info */                                
;									/*C21*/
;	for (k = u(0); k < u(12); k++)                                  
;	   BEGIN                                                        
;	    part_table[j][i].vol_label[k]=u(0);                         
;	   END                                                          
;									/*C21*/
;	for (k = u(0); k < u(9); k++)                                   
;	   BEGIN                                                        
;	    part_table[j][i].system[k]=u(0);                            
;	   END                                                          
;									/*C21*/
;	get_volume_string(part_table[j][i].drive_letter,&volume_label[0]);
;									/*C21*/
;	for (k = u(0); k < strlen(volume_label); k++)                   
;	   BEGIN                                                        
;	    part_table[j][i].vol_label[k]=volume_label[k];              
;	   END                                                          
;									/*C21*/
;	/* Now try to get it using GET MEDIA ID */                      
;	if (get_fs_and_vol(part_table[j][i].drive_letter))              
;	   BEGIN                                                        
;	    for (k=u(0); k < u(8); k++)                                 
;	       BEGIN                                                    
;		if (dx_buff.file_system[k] != ' ')                      
;		    length = k+1;                                       
;	       END                                                      
;	    strncpy(part_table[j][i].system,&dx_buff.file_system[0],u(length));
;	   END                                                          
;	else                                                            
;	   BEGIN                                                        
;	    if (part_table[j][i].num_sec > (unsigned long)FAT16_SIZE)   
;		strcpy(part_table[j][i].system,FAT16);                  
;	    else                                                        
;		strcpy(part_table[j][i].system,FAT12);                  
;	   END                                                          
;       END                                                              
;    else                                                                
;       BEGIN                                                            
;	/* set up to no file system or volume label */                  
;	strcpy(part_table[j][i].vol_label,NOVOLUME);                    
;	strcpy(part_table[j][i].system,NOFORMAT);                       
;      END                                                              
;   return;                                                             
;END 

;NOTE: 'get_volume' is not compatible with MSDOS 3.3 (and Retro DOS v3.0)
;	(23/11/2018 - Erdogan Tan)
; Solution: For MSDOS 3.3 or Retro DOS v3.0, this FDISK code must be modified
; to exclude volume name in partition table (displaying, deleting) procedures.

get_volume:

	;%define _k_	    bp-18 ; unsigned integer (word)
	;%define vol_label  bp-16 ; char volume_label(13) ; 13 bytes
	;%define _length_   bp-2  ; unsigned integer (word)	 

	%define vol_label   bp-14 ; char volume_label(13) ; 13 bytes ; *****

	;%define j_disk	    bp+4  ; unsigned char (byte)	
	;%define i_partition bp+6  ; unsigned integer (word)

		; 14/12/2018
		; INPUT:
		;   AL = Disk/Drive number (0 to 7)
		;   AH = Partition number (0 to 3)		

		push	bp
		mov	bp,sp
		;sub	sp,18
		sub	sp,14 ; *****
		;push	si
		;push	di ; *
		
		; 14/12/2018
		;mov	al,[j_disk] ; Disk number (0 to 7)
		; AL = Disk number		

		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[i_partition] ; Partition number (0 to 3)

		shl	al,1
		shl	al,1
		
		;14/12/2018		
		;add	al,[i_partition]
		add	al,ah  ; ah = Partition number

		;mov	cx,46
		;mul	cx
		mov	cx,46
		mul	cl
		;mov	bx,ax
		mov	si,ax ; ** ; 12/12/2018

		;mov	al,[part_table_drive_letter+bx]
		mov	al,[part_table_drive_letter+si]
		; 24/11/2018
		;push	ax
		call	check_format
		;pop	bx
		;dec	al
		;jz	short gv_1

		jnc	short gv_1
		jmp	gv_11
gv_1:
		;mov	word [_k_],0
gv_2:
;		;mov	al,[j_disk]
;		;sub	ah,ah
;		;shl	ax,1
;		;shl	ax,1
;		;add	ax,[i_partition]
;		;mov	cx,46
;		;mul	cx
;		;mov	si,ax ; ** ; 12/12/2018
;		mov	bx,[_k_]
;		mov	byte [part_table_vol_label+bx+si],0
;		;inc	word [_k_]
;		inc	byte [_k_]
;		;cmp	word [_k_],12
;		cmp	byte [_k_],12
;		jb	short gv_2
;		;mov	word [_k_],0
;		mov	byte [_k_],0

;		; 23/11/2018
;		xor	ax,ax
;		mov	di,part_table_vol_label ; *
;		add	di,si ; ** ; 12/12/2018
;		;mov	cx,6
;		mov	cl,6
;		rep	stosw

		; 23/11/2018
		xor	ax,ax
		mov	di,part_table_vol_label ; *
		add	di,si ; ** ; 12/12/2018
			; clear 12+9 bytes vol_label & system fields
		;mov	cl,10
		mov	cx,10 ; 17/12/2018 (ch>0)
		rep	stosw ; clear 20 bytes
		stosb	      ; and then clear +1 byte (total 21 bytes) 		
gv_3:
;		;mov	al,[j_disk]
;		;;sub	ah,ah
;		;;shl	ax,1
;		;;shl	ax,1
;		;shl	al,1
;		;shl	al,1
;		;;add	ax,[i_partition]
;		;add	al,[i_partition]
;		;;;mov	cl,46
;		;mul	cx
;		;mov	si,ax ; ** ; 12/12/2018
;		mov	bx,[_k_]
;		mov	byte [part_table_system+bx+si],0
;		inc	word [_k_]
;		cmp	word [_k_],9
;		jb	short gv_3

;		; 23/11/2018
;		;xor	ax,ax
;		;mov	di,part_table_system ; *
;		;add	di,si ; ** ; 12/12/2018
;		  ; part_table_system is just after
;		  ; part_table_volume_label
;		  ; (di already points to part_table_system+si)	
;		;mov	cx,9
;		mov	cl,9
;		rep	stosb

	;get_volume_string(part_table[j][i].drive_letter,&volume_label[0])

		lea	ax,[vol_label]
		push	ax

		;mov	al,[j_disk]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[i_partition]
		;mov	cx,46
		;mul	cx
		;mov	bx,ax
		;mov	si,ax ; ** ; 12/12/2018

		;mov	al,[part_table_drive_letter+bx]
		mov	al,[part_table_drive_letter+si]
		push	ax
		call	get_volume_string
		;pop	bx ; 05/01/2019
		;pop	bx

		;;mov	word [_k_],0
		;mov	byte [_k_],0
		;jmp	short gv_5
;gv_4:
		;mov	si,[_k_]
		;mov	al,[vol_label+si]
		;mov	cx,ax
		;mov	al,[j_disk]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[i_partition]
		;mov	bx,46
		;mul	bx
		;mov	bx,ax
		;mov	[part_table_vol_label+bx+si],cl
		;inc	word [_k_]
;gv_5:
		;lea	ax,[vol_label]
		;push	ax
		;call	strlen
		;pop	bx
		;cmp	ax,[_k_]
		;ja	short gv_4

		; 23/11/2018
		; Copy/Move volume name to partition data field
		mov	di,si ; ** ; 12/12/2018
		add	di,part_table_vol_label
		push	si ; ** ; 12/12/2018
		lea	si,[vol_label]
		;call	strlen
		; cx = string length (except terminating zero)
		;jcxz	gv_5
		;;cmp	cx,12
		;;ja	short gv_4
		;mov	cx,12
;gv_4:
		;rep	movsb
;gv_5:
		; 05/01/2019
		mov	cl,12
gv_4:
		lodsb
		and	al,al
		jz	short gv_5
		stosb
		;jmp	short gv_4
		loop	gv_4
gv_5:
		;mov	al,[j_disk]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[i_partition]
		;mov	cx,46
		;mul	cx
		;mov	bx,ax
		;;pop	dx ; **
		;;pop	bx,dx ; **

		pop	di ; ** ; 12/12/2018

		;mov	bx,di ; **
		;mov	al,[part_table_drive_letter+bx]
		mov	al,[part_table_drive_letter+di] ; 12/12/2018
		;push	ax
		call	get_fs_and_vol
		;pop	bx
		;or	al,al
		;jz	short gv_8
		jc	short gv_8 ; 24/11/2018

		;mov	word [_k_],0
		xor	bx,bx ; *****
gv_6:
		;mov	bx,[_k_] ; *****
		cmp	byte [dx_buff_file_system+bx],' '
		je	short gv_7
		;lea	ax,[bx+1]
		;mov	[_length_],ax
		lea	cx,[bx+1] ; *****
gv_7:
		;inc	word [_k_]
		;inc	byte [_k_]
		inc	bl ; *****
		;cmp	word [_k_],8
		;cmp	byte [_k_],8
		cmp	bl,8 ; *****
		jb	short gv_6

;		push	word [_length_] ; n
;		mov	ax,dx_buff_file_system
;		push	ax  		; src	
;
;		mov	al,[j_disk]
;		;sub	ah,ah
;		;shl	ax,1
;		;shl	ax,1
;		;add	ax,[i_partition]
;		shl	al,1
;		shl	al,1
;		add	al,[i_partition]
;		
;		;mov	cx,46
;		;mul	cx
;		mov	cl,46
;		mul	cl
;
;		mov	dx,ax ; ***	
;
;		add	ax,part_table_system
;		push	ax		 ; dest
;
;		call	strncpy  ; strncpy (dest,src,n)
;		add	sp,6
;		jmp	short gv_13

		; 23/11/2018
;		mov	ah,46
;		mul	ah
;		;mov	dx,ax ; **
		
		;mov	cx,[_length_] ; *****
		;jcxz	short gv_8

		mov	si,dx_buff_file_system
		;mov	di,ax
		; 12/12/2018
		;mov	di,dx ; **
		; DI = Partition data/structure offset
		add	di,part_table_system
		call	strncpy
			; cx = 0
		jmp	short gv_13
gv_8:
		;mov	al,[j_disk]
		;sub	ah,ah
		;;shl	ax,1
		;;shl	ax,1
		;;add	ax,[i_partition]
		;shl	al,1
		;shl	al,1
		;add	al,[i_partition]
		
		;;mov	cx,46
		;;mul	cx
		;mov	cl,46
		;mul	cl
		;mov	bx,ax

		; 12/12/2018
		;mov	bx,dx; **
	
		; DI = Partition data/structure offset ; **
		
		mov	ax,FAT16 ; "FAT16   " ; !*!

		;cmp	word [part_table_num_sec_hw+bx],0
		cmp	word [part_table_num_sec_hw+di],0
		;jne	short gv_9
		ja	short gv_9
		;cmp	word [part_table_num_sec_lw+bx],32680
		cmp	word [part_table_num_sec_lw+di],32680
		;jbe	short gv_10
		ja	short gv_9 ; !*!
		mov	ax,FAT12 ; "FAT12   " ; !*!
gv_9:
		;;mov	ax,FAT16 ; "FAT16   " ; !*!
		;push	ax
		;add	bx,part_table_system
		;push	bx

		; 12/12/2018
		mov	si,ax	; strcpy, source
		;mov	di,bx	; strcpy, destination	
		add	di,part_table_system

		jmp	short gv_12
gv_10:
		;mov	ax,FAT12 ; "FAT12   "
		;push	ax
		;mov	al,[j_disk]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,[i_partition]
		;mul	cx
		;add	ax,part_table_system
		;push	ax
		;jmp	short gv_12
gv_11:
		push	si ; ** ; 12/12/2018

		;mov	ax,NOVOLUME
		;push	ax
			
		; 05/01/2019			
		;mov	si,NOVOLUME ; ****

;		mov	al,[j_disk]
;		;sub	ah,ah
;		;shl	ax,1
;		;shl	ax,1
;		;add	ax,[i_partition]
;		shl	al,1
;		shl	al,1
;		add	al,[i_partition]
;		
;		;mov	cx,46
;		;mul	cx
;		mov	cl,46
;		mul	cl
;
;		;;mov	cx,ax
;		;mov	si,ax
;		;add	ax,part_table_vol_label
;		;push	ax
;		;;mov	si,cx
;		;call	strcpy
;		;pop	bx
;		;pop	bx
;	
;		;mov	dx,ax ; **
		
		;mov	di,dx ; ** ; ****
		
		pop	di ; ** ; 12/12/2018

		; 05/01/2019
		;add	di,part_table_vol_label
		
		; 05/01/2019
		;call	strcpy 

		mov	byte [di+part_table_vol_label],0 ; NOVOLUME
	
		;mov	ax,UNKNOWN ; "UNKNOWN "
		;push	ax

		mov	si,UNKNOWN ; ****	
		
		;add	si,part_table_system
		;push	si
		
		;mov	di,dx ; ** ; ****
		add	di,part_table_system ; 05/01/2019
gv_12:
		call	strcpy
		;pop	bx
		;pop	bx
gv_13:
		;pop	di ; *
		;pop	si
		mov	sp,bp
		pop	bp
		retn

; strlen (Microsoft C 6.0 runtime library, MSDOS 6.0, 1991)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 23/11/2018)

; Get (ASCIIZ) string length (except terminating null/zero character)

;strlen
;------
;size_t strlen ( const char * str );
;Get string length
;Returns the length of the C string str.

;The length of a C string is determined by the terminating null-character: 
;A C string is as long as the number of characters between the beginning 
;of the string and the terminating null character 
;(without including the terminating null character itself).
 
strlen:	
		;push	bp
		;mov	bp,sp
		;mov	dx,di
		;mov	ax,ds
		;mov	es,ax
		;mov	di,[bp+4] ; String address
		; 23/11/2018	
		mov	di,si ; String address
		;xor	ax,ax
		xor	al,al
		mov	cx,65535 ; 0FFFFh
		repne scasb
		not	cx
		dec	cx ; except terminating null character
		;xchg	ax,cx
		;mov	di,dx
		;pop	bp
		; cx = string length
		retn

; strncpy (Microsoft C 6.0 runtime library, MSDOS 6.0, 1991)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 23/11/2018)

; char *strncpy(char *dest, const char *src, size_t n)

;strncpy
;-------
;char * strncpy ( char * destination, const char * source, size_t num );
;Copy characters from string
;Copies the first num characters of source to destination. 
;If the end of the source C string (which is signaled by a null-character)
;is found before num characters have been copied, destination is padded with zeros
;until a total of num characters have been written to it.
;
;No null-character is implicitly appended at the end of destination if 
;source is longer than num. Thus, in this case, 
;destination shall not be considered a null terminated C string
;(reading it as such would overflow).
;destination and source shall not overlap 
;(see memmove for a safer alternative when overlapping).

strncpy:
	;%define _dest_	bp+4 ; word ; destination address pointer
	;%define _src	bp+6 ; word ; source address pointer 	
	;%define _n_	bp+8 ; word ; length (n characters/bytes)

		;push	bp
		;mov	bp,sp
		;;push	di
		;;;push	si
		;;push	ds
		;;pop	es
		;mov	di,[_dest_]
		;mov	si,[_src_]
		;mov	bx,di
		;mov	cx,[_n_]
		;jcxz	short strncpy_2
strncpy_0:
		lodsb
		or	al,al
		jz	short strncpy_1
		stosb
		loop	strncpy_0
		retn ; 11/12/2018
;strncpy_1:
		;xor	al,al
strncpy_1: ; 23/11/2018
		rep	stosb
strncpy_2:
		;mov	ax,bx
		;pop	si
		;pop	di
		;mov	sp,bp
		;pop	bp
		retn

; strcpy (Microsoft C 6.0 runtime library, MSDOS 6.0, 1991)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 23/11/2018)

;strcpy
;------
;char * strcpy ( char * destination, const char * source );
;Copy string
;Copies the C string pointed by source into the array pointed by destination, 
; including the terminating null character (and stopping at that point).
;
;To avoid overflows, the size of the array pointed by destination shall be 
;long enough to contain the same C string as source 
;(including the terminating null character), and should not overlap
;in memory with source.

strcpy:
	;%define _destination_ bp+4 ; word
	;%define _source_      bp+6 ; word

		;push	bp
		;mov	bp,sp
		;mov	dx,di
		;mov	bx,si
		;mov	si,[_source_]
		;mov	di,si
		;mov	ax,ds
		;mov	es,ax
		;xor	ax,ax
		;xor	al,al
		;mov	cx,65535 ; 0FFFFh
		;repne scasb
		;not	cx
		;mov	di,[_destination_]
		;mov	ax,di
		;test	al,1
		;jz	short strcpy_0
		;movsb
		;dec	cx
;strcpy_0:
		;shr	cx,1
		;rep movsw
		;adc	cx,cx
		;rep movsb
		;mov	si,bx
		;mov	di,dx
		;pop	bp
		;retn
strcpy_1:
		; 23/11/2018
		lodsb
		stosb
		and	al,al
		jnz	short strcpy_1
strcpy_2:
		retn

; ----------------------------------------------------------------------------
; convert.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 24/11/2018)
	
;/*  */
;/*******************************************************************************/
;/*Routine name:  CHECK_FORMAT                                                  */
;/*******************************************************************************/
;/*                                                                             */
;/*Description:   This routine will invoke INT21 44h (Block Generic IOCTL       */
;/*               Subfunction) call to see if the drive has been previously     */
;/*               formatted by using a undocumented call.                       */
;/*                                                                             */
;/*Called Procedures:                                                           */
;/*                                                                             */
;/*Change History: Created        2/07/88         DRM                           */
;/*                                                                             */
;/*Input: input_drive                                                           */
;/*                                                                             */
;/*Output: pointer to dx register                                               */
;/*                                                                             */
;/*******************************************************************************/

;FLAG check_format(input_drive)                                          /*AN002*/
;
;         char input_drive;                                              /*AN002*/
;
;BEGIN                                                                   /*AN002*/
;
;         char formatted;                                                /*AN002*/
;
;/*C32    if (input_drive <= 'Z') */                                     /*C30*/
;         if ((input_drive >= 'C') && (input_drive <= 'Z'))              /*C32*/
;         {                                                              /*C30*/
;         /* Set up registers for Generic IOCTL INT21 (44h) check media */
;         regs.x.ax = u(GENERIC_IOCTL);                                  /*AN002*/
;         regs.h.bh = uc(ZERO);                                          /*AN002*/
;         regs.h.bl = (((unsigned char)input_drive - 'A') + 1);          /*AN002*/
;         regs.x.cx = u(SPECIAL_FUNCTION);                               /*AN002*/
;         regs.x.dx = (unsigned)&disk_access;                            /*AN002*/
;         segread(&segregs);                                             /*AN002*/
;         intdosx(&regs,&regs,&segregs);                                 /*AN002*/
;
;         /* see if buffer returned good or not */
;         if (disk_access.dac_access_flag == ZERO)                       /*AN002*/
;            formatted = FALSE;                                          /*AN002*/
;         else                                                           /*AN002*/
;            formatted = TRUE;                                           /*AN002*/
;         }                                                              /*C30*/
;         else                                                           /*C30*/
;            formatted = FALSE;                                          /*C30*/
;
;          return(formatted);                                            /*AN002*/
;
;END                                                                     /*AN002*/


;INT 21H, Function 44H, Sub function 0DH 
;I/O Ctrl --> generic I/O control for block devices

;Call with: 
;	AH = 44H
;	AL = 0DH
;	BL = drive code (0 =default, 1=A,2=B, etc.)
;	CH = category (major) code:
;		08H = disk drive
;		48H = FAT32 disk drive
;	CL = function (minor) code:
;		40H = Set Drive Parameters
;		41H = Write Track
;		42H = Format and Verify Track
;		46H = Set Volume Serial Number	
;		47H = Set Access Flag 
;		60H = Get Device Parameters
;		61H = Read Track
;		62H = Verify track
;		66H = Get Volume Serial Number
;		67H = Get Access Flag
;
;	DS: DX = segment: offset of parameter block 
;
;Returns: 
;	If function successful
;	   Carry flag = clear
;	   And if called with CL = 60H or 61H
;	   DS: DX = segment: offset of parameter block
;
;	If function unsuccessful 
;	   Carry flag = set
;	   AX = error code
;
;Comments:
;	This sub function provides a general-purpose mechanism for communication 
;	between application programs and block-device drivers. Allows a program 
;	to inspect or change device parameters for a logical drive and to read, 
;	write, format, and verify disk tracks in a hardware-independent manner.
;
;Format of parameter block for functions 47h, 67h:
;
;Offset  Size    Description
; 00h    BYTE    special-function field (must be zero)
; 01h    BYTE    disk-access flag, nonzero if access allowed by driver
;
;Format of parameter block for functions 46h, 66h:
;
;Offset  Size    Description
; 00h    WORD    (call) info level (should be 0000h)
; 02h    DWORD   disk serial number (binary)
; 06h  11 BYTEs   volume label or "NO NAME    "
; 11h   8 BYTEs   filesystem type "FAT12   " or "FAT16   "
;
;(generally CL=66h only, but MS-DOS 5.0 will write the
;given filesystem type to the disk)

check_format:
;	%define formatted   bp-2
;	%define input_drive bp+4
;
;		push	bp
;		mov	bp,sp
;		sub	sp,2
;		cmp	byte [input_drive],'C'
;		jl	short chkf_1
;		cmp	byte [input_drive],'Z'
;		jg	byte short chkf_1
;		mov	byte [dac_access_flag],0
;		mov	word [regs_x_ax],440Dh
;		mov	byte [regs_x_bx+1],0 ; bh
;		mov	al,[input_drive]
;		sub	al,40h
;		mov	[regs_x_bx],al ; bl
;		mov	word [regs_x_cx],867h
;		mov	word [regs_x_dx],disk_access
;		mov	ax,segregs ;segregs_es
;		push	ax
;		call	segread
;		pop	bx
;		mov	ax,segregs ;segregs_es
;		push	ax
;		mov	ax,regs	;regs_x_ax
;		push	ax
;		push	ax
;		call	intdosx
;		add	sp,6
;		cmp	byte [dac_access_flag],0
;		jz	short chkf_1
;		mov	byte [formatted],1
;		jmp	short chkf_2
;chkf_1:
;		mov	byte [formatted],0
;chkf_2:
;		mov	al,[formatted]
;		mov	sp,bp
;		pop	bp
;		retn

		; 24/11/2018
		;xor	bh,bh
		;mov	bl,al ; [input_drive]
		;xor	al,al
		; 17/12/2018
		xor	ah,ah
		mov	bx,ax ; al = [input_drive]
		xor	al,al
		mov	[dac_access_flag],al ; 0
		cmp	bl,'C'
		jb	short chkf_2
		cmp	bl,'Z'
		ja	short chkf_1
		sub	bl,40h
		mov	cx,0867h
		push	dx ; * DX is in use by the caller
		mov	dx,disk_access
		mov	ax,440Dh
		int	21h
		pop	dx ; * 
		mov	al,[dac_access_flag]
chkf_1:
		cmp	al,1
			; cf = 1 -> not formatted (AL=0)
			; cf = 0 -> formatted (AL>0)
chkf_2:
		retn

;/*  */
;/*******************************************************************************/
;/*Routine name:  GET_VOLUME_STRING                                             */
;/*******************************************************************************/
;/*                                                                             */
;/*Description:   This routine will invoke INT21 4Eh (Find First Matching File) */
;/*               and return the disk volume label.                             */
;/*                                                                             */
;/*Called Procedures:                                                           */
;/*                                                                             */
;/*Change History: Created        6/01/87         DRM                           */
;/*                                                                             */
;/*Input: input_drive                                                           */
;/*                                                                             */
;/*Output: volume_out                                                           */
;/*                                                                             */
;/*******************************************************************************/

;void get_volume_string(input_drive,vol_label_addr)                     /*AN000*/
;        char input_drive;                                              /*AN000*/
;        char *vol_label_addr;                                          /*AN000*/
;BEGIN                                                                  /*AN000*/
;
;         char  first_string[13];                                       /*AC000*/
;         char  find_first_buffer[50];                                  /*AN000*/
;         unsigned i,j;                                                 /*AC000*/
;
;         /* clear out any garbage in volume label field */
;         for (i = u(0); i < u(12); i++)                                /*AN015*/
;             BEGIN                                                     /*AN015*/
;                 vol_label_addr[i] = u(0);                             /*AN015*/
;             END                                                       /*AN015*/
;
;         /* Point the DTA to our buffer so we can get the FindFirst output */
;         regs.h.ah = uc(0x1A);                                         /*AN000*/
;         regs.x.dx = (unsigned)&find_first_buffer[0];                  /*AN000*/
;         segread(&segregs);
;         intdosx(&regs,&regs,&segregs);                                /*AN000*/
;
;         /* Find the first volume id */
;         first_string[0] = input_drive;       /* Find the vol label - AN000*/
;         first_string[1] = (char) '\0';
;         strcat(first_string,FILE_NAME);                               /*AN000*/
;         regs.h.ah = uc(FIND_FIRST_MATCH);                             /*AN000*/
;         regs.x.cx = u(VOL_LABEL);                                     /*AN000*/
;         regs.x.dx = (unsigned)&first_string[0];                       /*AN000*/
;         intdos(&regs,&regs);                                		/*AN000*/
;
;/* AC000 The following is modified to take care of "." in the middle of the */
;/*name */
;
;         if ((regs.x.cflag & CARRY_FLAG) != CARRY_FLAG)                /*AN000*/
;           BEGIN                                                       /*AN000*/
;           for (i=j=u(0); i < strlen (&find_first_buffer[30]) ; i++)   /*AN000*/
;               BEGIN                                                   /*AN000*/
;               if (find_first_buffer[30+i] != PERIOD)                  /*AN003*/
;                       vol_label_addr[i-j] = find_first_buffer[30+i];  /*AN000*/
;               else                                                    /*AN000*/
;                       j = u(1);                                       /*AN000*/
;               END                                                     /*AN000*/
;           END                                                         /*AN000*/
;         return;                                                       /*AN000*/
;END                                                                    /*AN000*/

; ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ S U B	R O U T	I N E ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ

; Attributes: bp-based frame

get_volume_string:

	;;%define first_string	  bp-68  ; char first_string[13];
	;%define first_string	  bp-70  ; 24/11/2018 (db 'C:\????????.???',0)
	;%define _jj_		  bp-54	 ; unsigned j;	
	;%define _ii_		  bp-52	 ; unsigned i;
	;%define find_first_buffer bp-50	 ; char find_first_buffer[50];
	;%define _input_drive_	  bp+4 ; char input_drive;
	;%define vol_label_addr	  bp+6 ; char *vol_label_addr;

		; 17/12/2018
	%define first_string	  bp-60  ; (db 'C:\????????.???',0)
	%define find_first_buffer bp-44	 ; char find_first_buffer[44];
	%define _input_drive_	  bp+4 ; char input_drive;
	%define vol_label_addr	  bp+6 ; char *vol_label_addr;

		push	bp
		mov	bp,sp
		;sub	sp,68
		;sub	sp,70	; 24/11/2018

		sub	sp,60	; 17/12/2018

		; 12/12/2018
		;push	di
		push	si ; * SI is in use by the caller

		;/* clear out any garbage in volume label field */
		;mov	word [_ii_],0
gvs_1:
		;mov	bx,[_ii_]
		;mov	si,[vol_label_addr]
		;mov	byte [bx+si],0
		;inc	byte [_ii_]
		;cmp	byte [_ii_],12
		;jb	short gvs_1

		mov	di,[vol_label_addr]
		; 05/01/2019
		mov	cx,6
		xor	ax,ax
		rep	stosw

		;/* Point the DTA to our buffer 
		;   so we can get the FindFirst output */

		;mov	byte [regs_x_ax+1],1Ah
		;lea	ax,[find_first_buffer]
		;mov	[regs_x_dx],ax
		;mov	ax,segregs ;segregs_es
		;push	ax
		;call	segread
		;pop	bx
		;mov	ax,segregs ;segregs_es
		;push	ax
		;mov	ax,regs	;regs_x_ax
		;push	ax
		;push	ax
		;call	intdosx
		;add	sp,6

		mov	ah,1Ah  ; Set DTA address
		lea	dx,[find_first_buffer]
		int	21h		

		;/* Find the first volume id */

		mov	al,[_input_drive_]
		;mov	[first_string],al
		;mov	byte [first_string+1],0
		
		;mov	ax,FILE_NAME ; ":\????????.???"
		;push	ax
		;lea	ax,[first_string]
		;push	ax
		;call	strcat
		;pop	bx
		;pop	bx

		lea	di,[first_string]
		stosb    ; al = 'C' (or 'D' ...)

		mov	si,FILE_NAME ; ":\????????.???"
;starcat_loop:
		;lodsb
		;stosb
		;or	al,al
		;jnz	short starcat_loop

		;mov	cx,15 ; db ':\????????.???',0
		mov	cl,15
		rep	movsb			
			; [first_string] = 'C:\????????.???',0

		; Find First Matching File
		; (Find Volume Name)

		;mov	byte [regs_x_ax+1],4Eh
		;mov	word [regs_x_cx],8
		;lea	ax,[first_string]
		;mov	[regs_x_dx],ax
		;mov	ax,regs_x_ax
		;push	ax
		;push	ax
		;call	intdos
		;pop	bx
		;pop	bx
		;mov	al,[regs_x_cflag]
		;and	al,1
		;cmp	al,1
		;je	short gvs_5

		mov	ah,4Eh  ; Find First File
		;mov	cx,8 ; attribute (volume name)
		mov	cl,8
		lea	dx,[first_string]  ; ASCIIZ file name address
		int	21h
		jc	short gvs_5
		
		; take care of "." in the middle of the name */

		;sub	ax,ax
		;mov	[_jj_],ax
		;;mov	[_ii_],ax
		;mov	[_ii_],al

		; 24/11/2018
		;lea	ax,[find_first_buffer+30]
		;push	ax
		;call	strlen
		;pop	bx

		lea	si,[find_first_buffer+30]
		call	strlen	; /**/
			; CX = string length (except terminating null)
		; 17/12/2018 (lodsb,stosb,loop)
		;xor	si,si ; mov word [_ii_],0
		;xor	dx,dx ; mov word [_jj_],0
		mov	di,[vol_label_addr]
 		;jmp	short gvs_4
		jmp	short gvs_3 
gvs_2:
		;mov	byte [_jj_],1
		;mov	dl,1	 ; 17/12/2018
;gvs_3:
		;inc	byte [_ii_]
		;inc	si ; 17/12/2018
;gvs_4:
		;lea	ax,[find_first_buffer+30]
		;push	ax
		;call	strlen
		;pop	bx
		
		;cmp	ax,[_ii_]
		;cmp	al,[_ii_]
		;cmp	cx,[_ii_] ; /**/

		;cmp	cx,si
		;jbe	short gvs_5  ; jna

		; 17/12/2018
		;cmp	si,cx
		;jnb	short gvs_5 ; 12/12/2018

		;mov	si,[_ii_]
		;cmp	byte [si+find_first_buffer+30],'.'
		;je	short gvs_2
		;mov	al,[si+find_first_buffer+30]
gvs_3:		
		; 17/12/2018
		lodsb
		cmp	al,'.'
		je	short gvs_4
		
		;mov	bx,si
		;sub	bx,[_jj_]
		;sub	bx,dx
		;mov	si,[vol_label_addr]
		;mov	[bx+si],al
		;add	bx,di
		;mov	[bx],al

		; 05/01/2019
		stosb
gvs_4:	
		loop	gvs_3 ; 17/12/2018
gvs_5:
		pop	si ; * ; 12/12/2018
		;pop	di
		mov	sp,bp
		pop	bp
		retn	4 ; 05/01/2019

;/*  */
;/*******************************************************************************/
;/*Routine name:  GET_FS_AND_VOL                                                */
;/*******************************************************************************/
;/*                                                                             */
;/*Description:   This routine will invoke INT21 44h (Block Generic IOCTL       */
;/*               Subfunction) call to get volume label and file system type.   */
;/*                                                                             */
;/*Called Procedures:                                                           */
;/*                                                                             */
;/*Change History: Created        6/01/87         DRM                           */
;/*                                                                             */
;/*Input: input_drive                                                           */
;/*                                                                             */
;/*Output: pointer to dx register                                               */
;/*                                                                             */
;/*******************************************************************************/
;
;FLAG get_fs_and_vol(input_drive)                                        /*AN000*/
;
;         char input_drive;                                              /*AN000*/
;
;BEGIN                                                                   /*AN000*/
;
;         char output;
;
;         /* Set up registers for Generic IOCTL INT21 (44h) get media ID */
;         regs.x.ax = u(GENERIC_IOCTL);                                  /*AN000*/
;         regs.h.bh = uc(ZERO);                                          /*AN000*/
;         regs.h.bl = (((unsigned char)input_drive - 'A') + 1);          /*AN000*/
;         regs.x.cx = u(GET_MEDIA_ID);                                   /*AN000*/
;         regs.x.dx = (unsigned)&dx_buff;                                /*AN000*/
;         segread(&segregs);
;         intdosx(&regs,&regs,&segregs);                                 /*AN000*/
;
;         /* see if carry flag was zero or one */
;         if ((regs.x.cflag & CARRY_FLAG) == CARRY_FLAG)                 /*AN000*/
;            output = FALSE;                                             /*AN000*/
;         else                                                           /*AN000*/
;            output = TRUE;                                              /*AN000*/
;
;         return(output);                                                /*AN000*/
;                                                                        /*AN000*/
;END

get_fs_and_vol:
	;%define _output_     bp-2  ; char
	;%define _inputdrive_ bp+4  ; char

		;push	bp
		;mov	bp,sp
		;;sub	sp,2
		;xor	bx,bx	; mov word [_output_],0
		;push	bx
		
		;push	dx ; 12/12/2018	

		mov	bl,al ; 05/01/2019

		;mov	[regs_x_ax],440Dh
		mov	ax,440Dh ; IOCTL - Generic Block Device Request

		;mov	byte [regs_x_bx+1],0 ; bh

		;mov	al,[_inputdrive_] ; [bp+4]
		;sub	al,40h
		;mov	[regs_x_bx],al ; bl

		;xor	bh,bh
		;mov	bl,[_inputdrive_] ; [bp+4]

		sub	bl,40h ; drive number (0 = default, 1 = 'A', 3 = 'C' ..)
		
		;mov	word [regs_x_cx],866h
		;mov	word [regs_x_dx],dx_buff
		
		;mov	ax,segregs ; segregs_es
		;push	ax
		;call	segread
		;pop	bx
		;mov	ax,segregs ; segregs_es
		;push	ax
		;mov	ax,regs ; regs_x_ax
		;push	ax
		;push	ax
		;call	intdosx
		;add	sp,6

		mov	cx,0866h   ; Get fs name and volume serial number
		mov	dx,dx_buff ; buffer
		int	21h

		;mov	al,[regs_x_cflag]
		;and	al,1
		;cmp	al,1
		;jne	short gfsv_1
		;mov	word [_output_],0 ; [bp-2]

		jnc	short gfsv_1
		sub	ax,ax		
		jmp	short gvsv_2
gfsv_1:
		;mov	byte [_output_],1
		mov	ax,1
gvsv_2:
		;mov	al,[_output_]

		;pop 	dx ; 12/12/2018

		cmp	al,1 	
		;mov	sp,bp
		;pop	bp
			; CF = 1 -> Error
			; CF = 0 -> OK (fs name is in dx_buffer)
		retn

; strcat (Microsoft C 6.0 runtime library, MSDOS 6.0, 1991)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 24/11/2018)

;strcat
;------
;char * strcat ( char * destination, const char * source );
;Concatenate strings
;Appends a copy of the source string to the destination string. 
;The terminating null character in destination is overwritten by 
;the first character of source, and a null-character is included at 
;the end of the new string formed by the concatenation of both in destination.
;
;Destination and source shall not overlap.

;strcat:
;	%define _destination_	bp+4
;	%define _source_	bp+6
;
;		push	bp
;		mov	bp,sp
;		mov	dx,di
;		mov	bx,si
;		mov	ax,ds
;		mov	es,ax
;		mov	di,[_destination_]
;		xor	ax,ax
;		mov	cx,65535 ; 0FFFFh
;		repne scasb
;		lea	si,[di-1]
;		mov	di,[_source_]
;		mov	cx,65535 ; 0FFFFh
;		repne scasb
;		not	cx
;		sub	di,cx
;		xchg	di,si
;		mov	ax,[_destination_]
;		test	si,1
;		jz	short strcat_0
;		movsb
;		dec	cx
;strcat_0:
;		shr	cx,1
;		rep movsw
;		adc	cx,cx
;		rep movsb
;		mov	si,bx
;		mov	di,dx
;		pop	bp
;		retn

; ----------------------------------------------------------------------------
; partinfo.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 24/11/2018)

;/*  */
;char find_partition_type(type)
;
;unsigned char type;
;
;BEGIN
; char  i;
;
;/*  Look at all four partition entries for system id byte that matches */
; for (i = c(0); i < c(4);i++)                                   /*AC000*/
;    BEGIN
;
;     /* if we find a match, do a TRUE return */
;     if (part_table[cur_disk][i].sys_id == type)
;        BEGIN
;         return(TRUE);
;         break;
;        END
;    END
; /* Did not find one, return FALSE */
; return(FALSE);
;END

find_partition_type:
		; 14/12/2018
		; INPUT:
		;   AL = Partition type (File system ID)
		;   [current_disk] = Current disk/drive number

		; Modified registers: ax,bx,cx ; 24/01/2019

		; 24/11/2018
		xor	cx,cx
		jmp	short fpt_2
fpt_1:
		inc	cl
		cmp	cl,4
		jnb	short fpt_3
fpt_2:
		;xor	ah,ah
		push	ax  ; al = Requested partition ID

		mov	al,[cur_disk] ; disk number (0 to 7)
		shl	al,1
		shl	al,1 ; 4 partition (table entries) per disk
		add	al,cl ; Partition number (0 to 3)
		mov	bl,46
		mul	bl
		mov	bx,ax

		pop	ax 

		cmp	[part_table_sys_id+bx],al
		jne	short fpt_1

		;mov	al,1
			; cl < 4
		retn
fpt_3:
		;sub	al,al ; 0
		stc
			; cl = 4
		retn

; ----------------------------------------------------------------------------

;/*  */
;char find_partition_location(type)
;
;unsigned char type;
;
;BEGIN
; char  i;
;
;/*  Look at all four partition entries for system id byte that matches */
; for (i = c(0); i < c(4);i++)                                   /*AC000*/
;    BEGIN
;
;    /* if we find a match, do a TRUE return */
;     if (part_table[cur_disk][i].sys_id == type)
;        BEGIN
;         return(i);
;         break;
;        END
;    END
; /* Did not find one, return */
; return(c(NOT_FOUND));                                          /*AC000*/
;END

;find_partition_location:
;		; 24/11/2018
;		xor	cx,cx
;		jmp	short fpl_2
;fpl_1:
;		inc	cl
;		cmp	cl,4
;		jnb	short fpl_3
;fpl_2:
;		;xor	ah,ah
;		push	ax  ; al = Requested partition ID
;
;		mov	al,[cur_disk] ; disk number (0 to 7)
;		shl	al,1
;		shl	al,1 ; 4 partition (table entries) per disk
;		add	al,cl ; Partition number (0 to 3)
;		mov	bl,46
;		mul	bl
;		mov	bx,ax
;
;		pop	ax 
;
;		cmp	[part_table_sys_id+bx],al
;		jne	short fpl_1
;
;		mov	al,cl
;		retn
;fpl_3:
;		mov	al,0FFh
;		;stc
;		retn

; 14/12/2018 
; [ No need to find_partition_location for FDISK2.COM ..
; .. because 'find_partition_type' returns with partition number in CL. ]

;find_partition_location:
		;call	find_partition_type
		;jc	short fpl_1
		;
		;mov	al,cl ; Partition number (0 to 3)
		;retn
;fpl_1:
		;mov	al,0FFh
		;retn

; ----------------------------------------------------------------------------
; fdisk.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 25/11/2018)		
		
; 25/11/2018

;/*  */
;void load_logical_drive(point,drive)
;
;char   point;
;unsigned char   drive;
;
;BEGIN
;
;char        volume_label[13];                                           	/* AC000 */
;unsigned    ext_part_num;                                               	/* AN000 */
;unsigned    i;
;/*C00 unsigned j; */                                                       	/* AN000 */
;unsigned    k;                                                          	/* AN000 */
;unsigned    length;                                                     	/* AN000 */
;unsigned    index;
;/*C00 unsigned dx_pointer; */                                               	/* AN000 */
;unsigned    partition_location;                                         	/* AN000 */
;
;	/* Check to see if anything is there */
;	if ((boot_record[510] == uc(0x55)) && (boot_record[511] == uc(0xAA)))	/* AC000 */
;	    BEGIN
;	    /* The boot record is there - read in the logical drive if it is there */
;	    for (i = u(0); i < u(4); i++)                               /* AC000 */
;		BEGIN
;
;		index = i*16;
;		/* See if it is a defined extended drive*/
;		if ((boot_record[0x1C2 + index] != uc(0)) && (boot_record[0x1C2 + index] != uc(EXTENDED))) 
;		    BEGIN
;		    /* Get boot ind */
;		    ext_table[drive][point].boot_ind = boot_record[0x1BE + index];
;
;		    /* Start head */
;		    ext_table[drive][point].start_head = boot_record[0x1BF + index];
;
;		    /* Start sector - unscramble it from INT 13 format*/
;		    ext_table[drive][point].start_sector= (boot_record[0x1C0 + index] & 0x3F);
;
;		    /* Start cyl - unscramble it from INT 13 format*/
;		    ext_table[drive][point].start_cyl= ((((unsigned)boot_record[0x1C0+index]) & 0x00C0) << 2)
;						+ ((unsigned)boot_record[0x1C1+index]);
;
;		    /* System id */
;		    ext_table[drive][point].sys_id = boot_record[0x1C2+index];
;
;		    /* End head */
;		    ext_table[drive][point].end_head = boot_record[0x1C3+index];
;
;		    /* End sector - unscramble it from INT 13 format*/
;		    ext_table[drive][point].end_sector= (boot_record[0x1C4+index] & 0x3F);
;
;		    /* End cyl - unscramble it from INT 13 format*/
;		    ext_table[drive][point].end_cyl= ((((unsigned)boot_record[0x1C4+index]) & 0x00C0) << 2)
;						+ ((unsigned)boot_record[0x1C5+index]);
;
;		    /* Relative sectors */
;		    ext_table[drive][point].rel_sec =
;			((unsigned long)boot_record[0x1C9+index]) << 24;
;
;		    ext_table[drive][point].rel_sec =
;			ext_table[drive][point].rel_sec+(((unsigned long)boot_record[0x1C8+index]) << 16);
;
;		    ext_table[drive][point].rel_sec =
;			ext_table[drive][point].rel_sec + (((unsigned long)boot_record[0x1C7+index]) << 8);
;
;		    ext_table[drive][point].rel_sec =
;			ext_table[drive][point].rel_sec + ((unsigned long)boot_record[0x1C6+index]);
;
;		    /* Number of sectors */
;		    ext_table[drive][point].num_sec =
;			((unsigned long)boot_record[0x1CD+index]) << 24;
;
;		    ext_table[drive][point].num_sec =
;			ext_table[drive][point].num_sec+(((unsigned long)boot_record[0x1CC+index]) << 16);
;
;		    ext_table[drive][point].num_sec =
;			ext_table[drive][point].num_sec + (((unsigned long)boot_record[0x1CB+index]) << 8);
;
;		    ext_table[drive][point].num_sec =
;			ext_table[drive][point].num_sec + ((unsigned long)boot_record[0x1CA+index]);
;
;		    ext_table[drive][point].mbytes_used =
;			cylinders_to_mbytes(((ext_table[drive][point].end_cyl - ext_table[drive][point].start_cyl)+1),
;					      cur_disk);                /* AN004 */
;
;		    ext_part_num = find_partition_location(uc(EXTENDED));
;
;		    ext_table[drive][point].percent_used =
;			cylinders_to_percent(((ext_table[drive][point].end_cyl-ext_table[drive][point].start_cyl)+1),
;			((part_table[drive][ext_part_num].end_cyl-part_table[drive][ext_part_num].start_cyl)+1));
;
;		    ext_table[drive][point].drive_letter = next_letter++;                   /* AN000 */
;
;		    partition_location = ext_table[drive][point].start_cyl;
;
;		    if (read_boot_record(ext_table[drive][point].start_cyl,
;					 drive,
;					 ext_table[drive][point].start_head,
;					 ext_table[drive][point].start_sector));
;			 BEGIN                                                             /* AN000 */
;			 /* See if the disk has already been formated */
;			 if (check_format(ext_table[drive][point].drive_letter) == TRUE )       /* AN002 */
;			     BEGIN                                                         /* AN000 */
;			     /* get volume and system info */
;
;			     /* AC000 Just for cleaning up purposes */
;
;			     for (k = u(0); k < u(12); k++)                                     /* AC000 */
;				 BEGIN                                                          /* AC000 */
;				     ext_table[drive][point].vol_label[k]=u(0);                 /* AC000 */
;				 END                                                            /* AC000 */
;
;			     for (k = u(0); k < u(9); k++)                                      /* AC000 */
;				 BEGIN                                                          /* AC000 */
;				     ext_table[drive][point].system[k]=u(0);                    /* AC000 */
;				 END                                                            /* AC000 */
;
;			     get_volume_string(ext_table[drive][point].drive_letter,&volume_label[0]);
;
;			      for (k = u(0); k < strlen(volume_label); k++)                     /* AC000 AC015 */
;				   BEGIN                                                        /* AC000 AC015 */
;				     ext_table[drive][point].vol_label[k]=volume_label[k];      /* AC000 AC015 */
;				   END                                                          /* AC000 AC015 */
;
;			     /* Now try to get it using GET MEDIA ID function */
;			     if (get_fs_and_vol(ext_table[drive][point].drive_letter))     /* AN000 */
;
;				BEGIN                                                      /* AN000 */
;				/* AC000 Just use more conceptually simple logic */
;				for (k=u(0); k < u(8); k++)                                     /* AC000 */
;
;				    BEGIN                                                       /* AC000 */
;				      if (dx_buff.file_system[k] != ' ')                        /* AC000 */
;						length = k+1;                                   /* AC000 */
;				    END                                                         /* AC000 */
;
;				strncpy(ext_table[drive][point].system,&dx_buff.file_system[0],u(length));
;				END                                                        /* AN000 */
;
;			      else                                                         /* AN000 */
;
;				BEGIN                                                      /* AN000 */
;				if (ext_table[drive][point].num_sec > (unsigned long)FAT16_SIZE) /* AN000 */
;				    strcpy(ext_table[drive][point].system,FAT16);          /* AN000 */
;				else
;				    strcpy(ext_table[drive][point].system,FAT12);          /* AN000 */
;				END                                                        /* AN000 */
;			     END                                                           /* AN000 */
;			 else                                                              /* AN000 */
;			     BEGIN                                                         /* AN000 */
;			     /* set up array to say no file system or volume label */
;			     strcpy(ext_table[drive][point].vol_label,NOVOLUME);           /* AN000 */
;			     strcpy(ext_table[drive][point].system,NOFORMAT);              /* AN000 */
;			     END                                                           /* AN000 */
;
;			 regs.x.dx = u(0);
;			 regs.x.ax = NETWORK_IOCTL;
;			 regs.h.bl = ((ext_table[drive][point].drive_letter - 'A') + 1);
;			 intdos(&regs,&regs);
;			 if (regs.x.dx & 0x1000) strcpy(ext_table[drive][point].vol_label,REMOTE);
;			 END
;		    read_boot_record(ext_table[drive][point].start_cyl,
;				     drive,
;				     uc(0),
;				     uc(1));						/* AN000 */
;		    END
;		END
;	    END
;
;	return;
;
;END

load_logical_drive:

	;;%define tempnumsec_lw bp-34
	;;%define tempnumsec_hw bp-32
	;;%define temprelsec_lw bp-30
	;;%define temprelsec_hw bp-28
	;;%define _int_k        bp-26
	;%define _int_i	        bp-24
	;;%define _int_index_   bp-22
	;%define _char_vol_label_ bp-20 ; char volume_label[13]
	;;%define ext_part_num  bp-6
	;;%define _int_length_  bp-4
	;;;%define _partition_location_ bp-2 ; not used!
	;%define _bx_	        bp-2 ; **

	;%define _point_	bp+4
	%define numlogdrvs	bp+4  ; 14/12/2018
	%define _drive_		bp+6

	%define _char_vol_label_ bp-18 ; char volume_label[13]
	%define _int_i	         bp-4
	%define _bx_	         bp-2 ; **

		push	bp
		mov	bp,sp
		;sub	sp,34
		sub	sp,18 ; 26/11/2018
		
		; 15/12/2018
		;push	di
		;push	si

		;cmp	byte [boot_record+1FEh],55h
		;jne	short lld_1
		;cmp	byte [boot_record+1FFh],0AAh
		;je	short lld_for1
		cmp	word [boot_record+1FEh],0AA55h
		je	short lld_for1		
lld_1:
		jmp	lld_17
lld_for1:
		;mov	word [_int_i],0
		; 15/12/2018
		;jmp	lld_for1_1
		xor	bx,bx		
		mov	[_int_i],bx ; 0
		;jmp	lld_for1_next
		jmp	lld_for1_if

lld_2:
		;;mov	al,[numlogdrvs]
		;;cbw
		;;mov	cx,ax
		;;mov	cl,al
		;mov	cl,[numlogdrvs] ; 14/12/2018
		;mov	al,24
		;mul	byte [_drive_] 
		;;add	ax,cx
		;add	al,cl
		;;mov	cx,46
		;;;imul	cx
		;;mul	cx
		;mov	cx,46
		;mul	cl
		;mov	bx,ax ; *
		
		;mov	[_bx_],ax ; **

		; 15/12/2018
		; bx = [_bx_]
		
		mov	byte [ext_table_drive_letter+bx],' '
lld_3:
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	[_drive_]
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax ; *
		
		xor	ch,ch ; 11/12/2018

		; Read logical DOS drive's boot sector

	;if (read_boot_record(ext_table[drive][point].start_cyl,
	;		 drive,
	;		 ext_table[drive][point].start_head,
	;		 ext_table[drive][point].start_sector));

		; 15/12/2018	
		; ??? - What for we read this boot sector ?
		; (There is not any error check or any bs parameter
		; using after this boot sector reading !?)

		mov	ax,[ext_table_start_cyl+bx]
		;mov	[_partition_location_],ax ; not used!
		mov	cl,[ext_table_start_sector+bx]
		push	cx
		mov	cl,[ext_table_start_head+bx]
		push	cx
		mov	cl,[_drive_]
		push	cx
		push	ax
		call	read_boot_record
		;add	sp,8 ; 22/12/2018

lld_for1_if_chk_format:
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	[_drive_]
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		mov	bx,[_bx_] ; **		

		mov	al,[ext_table_drive_letter+bx]
		;push	ax
		call	check_format
		;pop	bx
		;dec	al
		;jz	short lld_for1_if_chk_format_true
		jnc	short lld_for1_if_chk_format_true ; 27/11/2018
		jmp	lld_for1_if_chk_format_false

lld_for1_if_chk_format_true:

		;for (k = u(0); k < u(12); k++)
		;    BEGIN
		;	ext_table[drive][point].vol_label[k]=u(0);
		;    END

		;mov	word [_int_k],0
lld_4:
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	[_drive_]
		;add	ax,cx
		;mov	cx,46
		;mul	cx
		;mov	si,ax
		
		;mov	si,[_bx_] ; **

		;mov	bx,[_int_k]
		;mov	byte [ext_table_vol_label+bx+si],0
		;inc	byte [_int_k]
		;cmp	byte [_int_k],12
		;jb	short lld_4

		; 26/11/2018

		;mov	cx,12
		mov	cx,21 ; 12+9  ; +**+
		mov	di,[_bx_]
		add	di,ext_table_vol_label
		xor	al,al
		rep	stosb

		; for (k = u(0); k < u(9); k++)
		;     BEGIN
		;	ext_table[drive][point].system[k]=u(0);
		;     END

		;mov	byte [_int_k],0
lld_5:
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	[_drive_]
		;add	ax,cx
		;mov	cx,46
		;mul	cx
		;mov	si,ax

		;mov	si,[_bx_] ; **

		;mov	bx,[_int_k]
		;mov	byte [ext_table_system+bx+si],0
		;inc	byte [_int_k]
		;cmp	byte [_int_k],9
		;jb	short lld_5

		; 26/11/2018
		;mov	cx,9 ; +**+
		;mov	di,[_bx_]
		;add	di,ext_table_system
		;xor	al,al
		;rep	stosb

		;get_volume_string(ext_table[drive][point].drive_letter,&volume_label[0]);
		
		lea	ax,[_char_vol_label_]
		push	ax
				
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	[_drive_]
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax
		
		mov	bx,[_bx_] ; **
		
		mov	al,[ext_table_drive_letter+bx]
		push	ax
		call	get_volume_string
		;pop	bx  ; 05/01/2019
		;pop	bx

		;for (k = u(0); k < strlen(volume_label); k++)
		;    BEGIN
		;	ext_table[drive][point].vol_label[k]=volume_label[k];
		;    END 

		;mov	byte [_int_k],0
		;jmp	short lld_7
lld_6:
		;mov	si,[_int_k]
		;mov	al,[si+_char_vol_label_]
		;;mov	cx,ax
		;;mov	cl,al

		;;mov	al,[numlogdrvs]
		;;cbw
		;;mov	dx,ax
		;;mov	al,24
		;;mul	byte [_drive_]
		;;add	ax,dx
		;;mov	bx,46
		;;mul	bx
		;;mov	bx,ax

		;mov	bx,[_bx_] ; **

		;;mov	byte [ext_table_vol_label+bx+si],cl
		;mov	byte [ext_table_vol_label+bx+si],al

		;inc	byte [_int_k]
lld_7:
		;; 26/11/2018
		;;lea	ax,[_char_vol_label_]  ; char volume_label[13];
		;;push	ax

		;lea	si,[_char_vol_label_]
		;call	strlen
		;;pop	bx
		;;cmp	ax,[_int_k]
		;cmp	cx,[_int_k]
		;ja	short lld_6

		;;mov	al,[numlogdrvs]
		;;cbw
		;;mov	cx,ax
		;;mov	al,24
		;;mul	byte [_drive_]
		;;add	ax,cx
		;;mov	cx,46
		;;imul	cx
		;;mov	bx,ax
				
		lea	si,[_char_vol_label_]
		mov	di,[_bx_] ; **
		add	di,ext_table_vol_label
		call	strcpy	; 26/11/2018
		
		mov	bx,[_bx_] ; **

		mov	al,[ext_table_drive_letter+bx]
		;push	ax
		call	get_fs_and_vol
		;pop	bx
		;or	al,al
		;jz	short lld_10
		jc	short lld_10 ; 26/11/2018

		;for (k=u(0); k < u(8); k++)
		;    BEGIN
		;     if (dx_buff.file_system[k] != ' ')
		;	 length = k+1;
		;    END
		;
		; strncpy(ext_table[drive][point].system,&dx_buff.file_system[0],u(length));

		; 26/11/2018
		;mov	byte [_int_k],0
		xor	bx,bx
		xor	cx,cx
lld_8:
		;mov	bx,[_int_k]
		cmp	byte [dx_buff_file_system+bx],' '
		je	short lld_9
		;lea	ax,[bx+1]
		;mov	[_int_length_],ax
		inc	cl
lld_9:
		;inc	byte [_int_k]
		inc	bl
		;cmp	byte [_int_k],8
		cmp	bl,8
		jb	short lld_8
		
		;push	word [_int_length_]
		;mov	cx,[_int_length_] ; copy length for strncpy ; 26/11/2018
		
		;mov	ax,dx_buff_file_system
		;push	ax
		
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	[_drive_]
		;add	ax,cx
		;mov	cx,46
		;imul	cx

		; 26/11/2018

		;mov	ax,[_bx_] ; **

		;add	ax,ext_table_system
		;push	ax
		;call	strncpy
		;add	sp,6

		mov	si,dx_buff_file_system  ; source
		mov	di,[_bx_]
		add	di,ext_table_system	; destination
			;cx = number of characters to be copied
		call	strncpy

		jmp	short lld_14

lld_10:
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	[_drive_]
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		; 26/11/2018
		;mov	bx,[_bx_] ; **
		mov	di,[_bx_] ; **
		; 14/12/2018
		add	di,ext_table_system

		mov	si,extFAT16 ; 14/12/2018
		;cmp	word [ext_table_num_sec_hw+bx],0
		cmp	word [ext_table_num_sec_hw+di],0
		;jnz	short lld_11
		jnz	short lld_13 ; 14/12/2018
		;cmp	word [ext_table_num_sec_lw+bx],32680
		cmp	word [ext_table_num_sec_lw+di],32680
		;jbe	short lld_12
		; 14/12/2018
		ja	short lld_13
		mov	si,extFAT12
		jmp	short lld_13	
; 14/12/2018
;lld_11:	
;		;mov	ax,extFAT16 ; "FAT16   "
;		;push	ax
;		;add	bx,ext_table_system
;		;push	bx
;
;		mov	si,extFAT16
;		
;		;add	di,ext_table_system
;		
;		jmp	short lld_13
;
;lld_12:
;		;mov	ax,extFAT12 ; "FAT12   "
;		;push	ax
;
;		;mov	al,[numlogdrvs]
;		;cbw
;		;mov	cx,ax
;		;mov	al,24
;		;mul	[_drive_]
;		;add	ax,cx
;		;mov	cx,46
;		;imul	cx
;		
;		; 26/11/2018
;		;mov	ax,[_bx_] ; **
;
;		;add	ax,ext_table_system
;		;push	ax
;
;		mov	si,extFAT12
;		
;		;mov	di,[_bx_] ; **
;		;add	di,ext_table_system
;
;		jmp	short lld_13

lld_for1_if_chk_format_false:
		;mov	ax,extNOVOLUME
		;push	ax

		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	byte [_drive_]
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	cx,ax

		; 26/11/2018
		;mov	ax,[_bx_] ; **
		;mov	si,ax
		;add	ax,ext_table_vol_label
		;push	ax
		;;mov	si,cx
		;call	strcpy
		;pop	bx
		;pop	bx

		; 05/01/2019
		;mov	si,extNOVOLUME
		mov	di,[_bx_] ; **
		;add	di,ext_table_vol_label
		;call	strcpy

		mov	byte [di+ext_table_vol_label],0 ; extNOVOLUME
		
		;mov	ax,extUNKNOWN ;	"UNKNOWN "
		;push	ax

		;add	si,ext_table_system
		;push	si

		mov	si,extUNKNOWN
		;mov	di,[_bx_] ; **
		; 05/01/2019
		add	di,ext_table_system ; =*
lld_13:
		call	strcpy
		;pop	bx
		;pop	bx
lld_14:
		;mov	word [regs_x_dx],0
		;mov	word [regs_x_ax],4409h
		
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	[_drive_]
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		; 26/11/2018

		;mov	bx,[_bx_] ; **

		;mov	al,[ext_table_drive_letter+bx]
		;sub	al,40h
		;mov	[regs_x_bx],al
		;mov	ax,regs ; regs_x_ax
		;push	ax
		;push	ax
		;;mov	si,bx
		;mov	di,bx ; 26/11/2018 ; **
		;call	intdos
		;pop	bx
		;pop	bx
		;test	byte [regs_x_dx+1],10h
		;jz	short lld_15

		; 14/12/2018
		mov	di,[_bx_] ; **

		; DOS 3.1+ - IOCTL - CHECK IF BLOCK DEVICE REMOTE
		mov	ax,4409h
		mov	bl,[ext_table_drive_letter+di] ; **
		sub	bl,40h
		int	21h
		test	dh,10h ; DX bit 12, 'Drive is Remote' flag
		jz	short lld_15
			; Note: DX = 0800h (MSDOS) or 
			;	DX = 4800h (WINDOWS 95) --> RAM Drive
		
		; ah = 0 ?

		;push	word [REMOTE]
		;add	si,ext_table_vol_label
		;push	si

		mov	si,[REMOTE]

		;mov	di,[_bx_] ; ** ; 14/12/2018

		add	di,ext_table_vol_label ; **

		call	strcpy
		;pop	bx
		;pop	bx

		; ah = 0 ?
lld_15:
		;read_boot_record(ext_table[drive][point].start_cyl,
		;		     drive,
		;		     uc(0),
		;		     uc(1));              

		;mov	al,1
		mov	ax,1 ; 11/12/2018 (ah = 0)
		push	ax
		sub	al,al ; 0
		push	ax
		mov	al,[_drive_]
		push	ax
		
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	byte [_drive_]
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax
		
		mov	bx,[_bx_] ; **

		push	word [ext_table_start_cyl+bx]
		call	read_boot_record
		;add	sp,8 ; 22/12/2018

lld_for1_if_false:
		inc	byte [_int_i]
lld_for1_1:
		cmp	byte [_int_i],4
		jb	short lld_for1_next
		jmp	lld_17

lld_for1_next:
		mov	cl,4
		mov	bx,[_int_i]
		shl	bx,cl ; * 16
		; 26/11/2018
		;mov	[_int_index_],bx ; index = i*16;
lld_for1_if:
	;if ((boot_record[0x1C2 + index] != uc(0)) && 
	;	(boot_record[0x1C2 + index] != uc(EXTENDED))) 

		;cmp	byte [boot_record+1C2h+bx],0 
		;je	short lld_for1_if_false
		;cmp	byte [boot_record+1C2h+bx],EXTENDED ; 5
		;je	short lld_for1_if_false

		;mov	al,[boot_record+1C2h+bx]  ; Partition ID
		;or	al,al
		;jz	short lld_for1_if_false
		;cmp	al,EXTENDED ; 5
		;je	short lld_for1_if_false

		; 15/12/2018
		; Here we are checking partition 0 to 3 of
		; (extended partition table of) extended volume.
		; (Partition 1,2 and 3 must have a ZERO or 
		; EXTENDED DOS partition ID while Partition 0 has a
		; valid DOS partition ID.)
		; [Otherwise, previous logical dos partition data 
		; would be overwritten, but logical drive letter 
		; would be changed to next letter!?]

		; (For valid scheme: If there are 2 or more Logical 
		; DOS partitions.. partition -table entry- 0 must 
		; have DOS partition ID; partition 1 must have 
		; Extended DOS partition ID; partition 3 and 4 
		; must be empty in the extended partition table of 
		; the first -extended volume- logical dos partition.)

		; (It seem as Extended DOS partition construction logic 
		; is defective. Instead of this defective construction,
		; it would be better if extended partition -boot sector- table
		; would have same construction with masterboot partition table.)
		; [Erdogan Tan, 15/12/2018]		
	
		mov	dl,[boot_record+1C2h+bx]  ; Partition ID ; /**/	
		or	dl,dl
		jz	short lld_for1_if_false
		cmp	dl,EXTENDED ; 5
		je	short lld_for1_if_false

lld_for1_if_true:
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,24
		;mov	dx,ax
		;mov	al,[_drive_]
		;sub	ah,ah
		;mov	si,dx
		;mov	di,46
		;mov	bx,ax
		;mul	cx
		;add	ax,si
		;imul	di
		;mov	si,ax

		; 15/12/2018
		;mov	cl,[numlogdrvs] ; Logical drive index
		mov	al,24
		mul	byte [_drive_] 
		;;add	ax,cx
		;add	al,cl
		add	al,[numlogdrvs] ; 19/12/2018
		mov	cx,46
		mul	cl
		mov	si,ax ; ** ; (([_drive_]*24)+[_numlogdrvs])*46
		
		mov	[_bx_],ax

		; 14/12/2018
		;mov	[ext_table_sys_id+si],al ; /**/
		; 15/12/2018
		mov	[ext_table_sys_id+si],dl ; /**/		

		;/* Get boot ind */
		;ext_table[drive][point].boot_ind = boot_record[0x1BE + index];
		;mov	di,[_int_index_]
		;mov	al,[boot_record+1BEh+di]
		mov	al,[boot_record+1BEh+bx]
		mov	[ext_table_boot_ind+si],al

		;/* Start head */
		;ext_table[drive][point].start_head = boot_record[0x1BF + index];
		;mov	al,[boot_record+1BFh+di]
		mov	al,[boot_record+1BFh+bx]
		mov	[ext_table_start_head+si],al

		;/* Start sector - unscramble it from INT 13 format*/
		;ext_table[drive][point].start_sector= (boot_record[0x1C0 + index] & 0x3F);
		;mov	al,[boot_record+1C0h+di]
		mov	al,[boot_record+1C0h+bx]
		;mov	cx,ax
		mov	cl,al ; 15/12/2018
		and	al,3Fh
		mov	[ext_table_start_sector+si],al
    		;/* Start cyl - unscramble it from INT 13 format*/
		;  ext_table[drive][point].start_cyl= ((((unsigned)boot_record[0x1C0+index]) & 0x00C0) << 2)
		;	+ ((unsigned)boot_record[0x1C1+index]);
		;and	cx,0C0h
		and	cl,0C0h ; 15/12/2018
		shl	cx,1
		shl	cx,1
		;;mov	al,[boot_record+1C1h+di]
		;mov	al,[boot_record+1C1h+bx]
		;;sub	ah,ah
		;;add	cx,ax
		;mov	cl,al
		mov	cl,[boot_record+1C1h+bx] ; 15/12/2018
		mov	[ext_table_start_cyl+si],cx

		;/* System id */
		;ext_table[drive][point].sys_id = boot_record[0x1C2+index];
		;mov	al,[boot_record+1C2h+di]
		; 14/12/2018
		;mov	al,[boot_record+1C2h+bx]
		;mov	[ext_table_sys_id+si],al ; /**/

		;/* End head */
		;ext_table[drive][point].end_head = boot_record[0x1C3+index];
		;mov	al,[boot_record+1C3h+di]
		mov	al,[boot_record+1C3h+bx]
		mov	[ext_table_end_head+si],al

		;/* End sector - unscramble it from INT 13 format*/
		;ext_table[drive][point].end_sector= (boot_record[0x1C4+index] & 0x3F);
		;mov	al,[boot_record+1C4h+di]
		mov	al,[boot_record+1C4h+bx]
		;mov	cx,ax
		mov	cl,al
		and	al,3Fh
		mov	[ext_table_end_sector+si],al
		;/* End cyl - unscramble it from INT 13 format*/
		;ext_table[drive][point].end_cyl= ((((unsigned)boot_record[0x1C4+index]) & 0x00C0) << 2)
		;	+ ((unsigned)boot_record[0x1C5+index]);
		and	cx,0C0h
		shl	cx,1
		shl	cx,1
		;;mov	al,[boot_record+1C5h+di]
		;mov	al,[boot_record+1C5h+bx]
		;;add	cx,ax
		;mov	cl,al
		mov	cl,[boot_record+1C5h+bx] ; 15/12/2018
		mov	[ext_table_end_cyl+si],cx

		;/* Relative sectors */
		;ext_table[drive][point].rel_sec = ((unsigned long)boot_record[0x1C9+index]) << 24;
		;ext_table[drive][point].rel_sec =
		;    ext_table[drive][point].rel_sec+(((unsigned long)boot_record[0x1C8+index]) << 16);
		;ext_table[drive][point].rel_sec =
		;    ext_table[drive][point].rel_sec+(((unsigned long)boot_record[0x1C7+index]) << 8);
		;ext_table[drive][point].rel_sec =
		;    ext_table[drive][point].rel_sec+((unsigned long)boot_record[0x1C6+index]);

		;mov	al,[boot_record+1C9h+di]
		;mov	ah,al
		;sub	al,al
		;sub	cx,cx
		;mov	[ext_table_rel_sec_lw+si],cx
		;mov	[ext_table_rel_sec_hw+si],ax
		;mov	dl,[boot_record+1C8h+di]
		;sub	dh,dh
		;sub	di,di
		;add	cx,di
		;adc	ax,dx
		;mov	[ext_table_rel_sec_lw+si],cx
		;mov	[ext_table_rel_sec_hw+si],ax
		;mov	di,[_int_index_]
		;mov	dx,ax
		;mov	al,[boot_record+1C7h+di]
		;sub	ah,ah
		;mov	di,dx
		;sub	dx,dx
		;mov	[temprelsec_lw],cx
		;mov	[temprelsec_hw],di
		;mov	cl,8
		;mov	di,bx
		;call	shl32
		;add	ax,[temprelsec_lw]
		;adc	dx,[temprelsec_hw]
		;mov	[ext_table_rel_sec_lw+si], ax
		;mov	[ext_table_rel_sec_hw+si], dx
		;mov	bx,[_int_index_]
		;mov	cl,[boot_record+1C6h+bx]
		;sub	ch,ch
		;add	ax,cx
		;adc	dx,0
		;mov	[ext_table_rel_sec_lw+si],ax
		;mov	[ext_table_rel_sec_hw+si],dx

		; 26/11/2018
		;mov	ax,[boot_record+1C6h+di]
		;mov	dx,[boot_record+1C8h+di]
		mov	ax,[boot_record+1C6h+bx]
		mov	dx,[boot_record+1C8h+bx]
		mov	[ext_table_rel_sec_lw+si],ax
		mov	[ext_table_rel_sec_hw+si],dx

		;/* Number of sectors */
		;ext_table[drive][point].num_sec = ((unsigned long)boot_record[0x1CD+index]) << 24;
		;ext_table[drive][point].num_sec =
		;    ext_table[drive][point].num_sec+(((unsigned long)boot_record[0x1CC+index]) << 16);
		;ext_table[drive][point].num_sec =
		;    ext_table[drive][point].num_sec+(((unsigned long)boot_record[0x1CB+index]) << 8);
		;ext_table[drive][point].num_sec =
		;    ext_table[drive][point].num_sec + ((unsigned long)boot_record[0x1CA+index]);

		;mov	al,[boot_record+1CDh+bx]
		;mov	ah,al
		;sub	al,al
		;sub	cx,cx
		;mov	[ext_table_num_sec_lw+si],cx
		;mov	[ext_table_num_sec_hw+si],ax
		;mov	dl,[boot_record+1CCh+bx]
		;sub	dh,dh
		;sub	bx,bx
		;add	cx,bx
		;adc	ax,dx
		;mov	[ext_table_num_sec_lw+si],cx
		;mov	[ext_table_num_sec_hw+si],ax
		;mov	bx,[_int_index_]
		;mov	dx,ax
		;mov	al,[boot_record+1CBh+bx]
		;sub	ah,ah
		;mov	bx,dx
		;sub	dx,dx
		;mov	[tempnumsec_lw],cx
		;mov	[tempnumsec_hw],bx
		;mov	cl,8
		;call	shl32
		;add	ax,[tempnumsec_lw]
		;adc	dx,[tempnumsec_hw]
		;mov	[ext_table_num_sec_lw+si],ax
		;mov	[ext_table_num_sec_hw+si],dx
		;mov	bx,[_int_index_]
		;mov	cl,[boot_record+1CAh+bx]
		;sub	ch,ch
		;add	ax,cx
		;adc	dx,0
		;mov	[ext_table_num_sec_lw+si],ax
		;mov	[ext_table_num_sec_hw+si],dx

		; 26/11/2018
		;mov	ax,[boot_record+1CAh+di]
		;mov	dx,[boot_record+1CCh+di]
		mov	ax,[boot_record+1CAh+bx]
		mov	dx,[boot_record+1CCh+bx]
		mov	[ext_table_num_sec_lw+si],ax
		mov	[ext_table_num_sec_hw+si],dx

	;ext_table[drive][point].mbytes_used =
	; cylinders_to_mbytes(((ext_table[drive][point].end_cyl - ext_table[drive][point].start_cyl)+1),
	; 			cur_disk);

		mov	di,bx ; [_int_index_] ; ****
			; bh = 0

		;mov	al,[cur_disk]
		;push	ax
		
		mov	bl,[cur_disk]
		;xor	bh,bh ; 0
			;bx = Disk drive Number 0 to 7

		mov	ax,[ext_table_end_cyl+si]
		sub	ax,[ext_table_start_cyl+si]
		inc	ax
			; ax = number of cylinders (partition size in cylinders)
		;push	ax
		call	cylinders_to_mbytes
			; ax = partition size in megabytes
		;pop	bx
		;pop	bx
		mov	[ext_table_mbytes_used+si],ax

		; 14/12/2018
		;mov	al,5 ; EXTENDED
		;;push	ax
		;call	find_partition_location
		;;pop	bx
		;	; al = partition number (0 to 3) or 0FFh (not found)

		; 26/11/2018	
		;cbw
		;mov	[ext_part_num],ax
		
		; 14/12/2018
		; get partition entry number of extended dos partion
 		; 	(on current disk/drive)
		mov	al,5
		call	find_partition_type
		; CL = partition number (index), 0 to 3 or 4 (not found)

		;mov	ax,di ; [_drive_] ; Drive number (0 to 7)
		;shl	ax,1
		;shl	ax,1
		;add	ax,[ext_part_num]

		; 14/12/2018
		mov	al,[_drive_]
		shl	al,1
		shl	al,1
		add	al,cl ; Partition (entry) number (0 to 3)
		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		
		;mov	ax,[part_table_end_cyl+bx]
		;sub	ax,[part_table_start_cyl+bx]
		;inc	ax
		;push	ax

		mov	cx,[part_table_end_cyl+bx]
		sub	cx,[part_table_start_cyl+bx]
		inc	cx 
			; cx = Total cylinders (of extended partition)
		
		;mov	ax,[ext_table_end_cyl+si]
		;;sub	ax,[ext_table_start_cyl+si]
		;inc	ax
		;push	ax
		
		mov	bx,[ext_table_end_cyl+si]
		sub	bx,[ext_table_start_cyl+si]
		inc	bx
			; bx = Number of logical drive/partition cylinders 

		call	cylinders_to_percent   ; (100*bx/cx)%
		;pop	bx
		;pop	bx
		mov	[ext_table_percent_used+si],ax ; percentage (<=100)
		
		;mov	bx,[_int_index_]
		;mov	bx,di ; [_int_index_] ; ****

		; 26/11/2018

		;cmp	byte [boot_record+1C2h+bx],1
		;je	short lld_16
		;cmp	byte [boot_record+1C2h+bx],4
		;je	short lld_16
		;cmp	byte [boot_record+1C2h+bx],6
		;je	short lld_16

		;mov	al,[bx+boot_record+1C2h] ; Partition/System ID	
		mov	al,[di+boot_record+1C2h] ; ****	

		; 15/12/2018
		mov	bx,[_bx_] ; **

		cmp	al,DOS12  ; 1		
		je	short lld_16
		cmp	al,DOS16  ; 4
		je	short lld_16
		cmp	al,DOSNEW ; 6 
		je	short lld_16

		jmp	lld_2
lld_16:
		;mov	al,[numlogdrvs]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;mul	[_drive_]
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		; 15/12/2018
		;mov	bx,[_bx_] ; **

		mov	al,[next_letter]
		inc	byte [next_letter]
		mov	[ext_table_drive_letter+bx],al
		jmp	lld_3
lld_17:
		; 15/12/2018
		;pop	si
		;pop	di
		
		mov	sp,bp
		pop	bp
		retn	4 ; 06/01/2019

; ----------------------------------------------------------------------------
; int13.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 26/11/2018)

;/*  */
;char read_boot_record(cylinder,which_disk,which_head,which_sector) /* AC000 */
;
;unsigned        cylinder;
;unsigned char   which_disk;
;unsigned char   which_head;					  /* AN000 */
;unsigned char   which_sector;					  /* AN000 */
;
;BEGIN
;
;   char far *buffer_pointer = boot_record;
;
;   /* Setup read, always on a cylinder boundary */
;   regs.h.ah = uc(READ_DISK);                                    /* AC000 */
;   regs.h.al = uc(1);                                            /* AC000 */
;   regs.h.dh = which_head;                                       /* AC000 */
;   regs.h.cl = which_sector;                                     /* AC000 */
;
;   /* Specify the disk */
;   regs.h.dl = which_disk + 0x80;
;
;   /* Need to scramble CX so that sectors and cyl's are in INT 13 format */
;
;   if (cylinder > u(255))                                        /* AC000 */
;      BEGIN
;       regs.h.cl = regs.h.cl | ((char)((cylinder /256) << 6));
;      END
;   regs.h.ch = (unsigned char)(cylinder & 0xFF);
;
;   /* Point at the place to write the boot record */
;   regs.x.bx = FP_OFF(buffer_pointer);
;   segregs.es = FP_SEG(buffer_pointer);
;
;   /* read in the boot record */
;   DiskIo(&regs,&regs,&segregs);			         /* AC000 */
;   /* Check for error reading it */
;   if ((regs.x.cflag & 1) != u(1))                              /* AC000 */
;      BEGIN
;       return(TRUE);
;      END
;   else
;      BEGIN
;       /* Tell user there was an error */
;       good_disk[which_disk] = FALSE;
;       clear_screen(u(0),u(0),u(24),u(79));			 /* AC000 */
;       return(FALSE);
;      END
;END

read_boot_record:
		; 26/11/2018
	
	;%define rbs_buffer   bp-4  ; word
	;%define rbs_segment  bp-2  ; word
	%define rbs_cylinder bp+4  ; word
	%define rbs_disk     bp+6  ; byte
	%define rbs_head     bp+8  ; byte
	%define rbs_sector   bp+10 ; byte

		; Modified registers: ax,bx,cx,dx

		push	bp
		mov	bp,sp
		;sub	sp,4 ; 11/12/2018

		;mov	word [rbs_buffer],boot_record
		;mov	[rbs_segment],ds
		
		mov	bx,boot_record
		;push	ds
		;pop	es
	
		;mov	byte [regs_x_ax+1],2 ; read
		;mov	byte [regs_x_ax],1   ; 1 sector
	
		;mov	al,[rbs_head]
		;mov	[regs_x_dx+1],al
		mov	dh,[rbs_head]	; Head (0 to 255)		

		;mov	al,[rbs_sector]
		;mov	[regs_x_cx], al
		mov	cl,[rbs_sector]	; Sector (1 to 63)	

		;mov	al,[rbs_disk]
		;add	al,80h
		;mov	[regs_x_dx],al
		mov	dl,[rbs_disk]
		add	dl,80h	; Hard disk drive number (80h to 87h)	

		;cmp	word [rbs_cylinder],255
		;jbe	short read_bs_1
		
		mov	ax,[rbs_cylinder] ; Cylinder (0 to 1023)
		mov	ch,al  ; cylinder (low 8 bits)
		cmp	ax,255
		jbe	short read_bs_1
		
		shr	ax,1
		shr	ax,1
		and	al,0C0h		 ; bits 8 and 9 of cylinder
		;or	[regs_x_cx],al	 ; -->
		or	cl,al		 ; bits 6 and 7 of sector
read_bs_1:
		;mov	al,[rbs_cylinder]
		;mov	[regs_x_cx+1],al
		
		;mov	ax,[rbs_buffer]
		;mov	[regs_x_bx],ax
		;mov	ax,[rbs_segment]
		;mov	[segregs_es],ax
		
		;mov	ax,segregs ;segregs_es
		;push	ax
		;mov	ax,regs	   ; regs_x_ax
		;push	ax
		;push	ax
		;call	DiskIo
		;add	sp,6
		;mov	al,[regs_x_cflag]
		;and	al,1
		;cmp	al,1
		;je	short read_bs_2
		;mov	al,1
		;jmp	short read_bs_3

		mov	ax,0201h	; Read 1 sector (CHS read)
		int	13h
		jc	short read_bs_2

		mov	al,1 ; TRUE
		jmp	short read_bs_3
read_bs_2:
		; 11/12/2018
		;mov	bl,[rbs_disk]
		;sub	bh,bh
		mov	bx,[rbs_disk]

		mov	[good_disk+bx],bh ; 0

		;mov	ax,79
		;push	ax	 ; Bottom Rigth Column (79)  
		;mov	ax,24
		;push	ax	 ; Bottom Row (24)
		;sub	ax,ax ; 0
		;push	ax	 ; Top Left Column (0)	
		;push	ax	 ; Top Row (0)
		;
		;call	clear_screen

		; Clear screen (clear whole video page)
		call	CLS

		sub	al,al ; FALSE
		stc	; cf = 1  (error!)
read_bs_3:
		;mov	sp,bp ; 11/12/2018
		pop	bp
		;retn
		retn	8 ; 22/12/2018

; ---------------------------------------------------------------------------

;/*  */
;void DiskIo(InRegs,OutRegs,SegRegs)
;union   REGS    *InRegs;
;union   REGS    *OutRegs;
;struct  SREGS   *SegRegs;
;
;BEGIN
;   int86x((int)DISK,InRegs,OutRegs,SegRegs);		/* AC000 */
;   return;
;
;END

;DiskIo:
;	%define _InRegs_  bp+4
;	%define _OutRegs_ bp+6
;	%define _SegRegs_ bp+8
;
;		push	bp
;		mov	bp,sp
;		push	word [_SegRegs_]
;		push	word [_OutRegs_]
;		push	word [_InRegs_]
;		mov	ax,13h
;		push	ax
;		call	int86x
;		mov	sp,bp
;		pop	bp
;		retn

; int86x (Microsoft C 6.0 runtime library, MSDOS 6.0, 1991)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 26/11/2018)

;int86x:
;
;	%define call_int	bp-16 ; dword
;	%define int_opcode	bp-12 ; word
;	%define retf_opcode_1	bp-10 ; byte
;	%define inc_sp_opcode	bp-9  ; byte	
;	%define retf_opcode_2	bp-8  ; byte
;
;	%define _disk_int_	bp+4  ; word
;	%define _in_regs_	bp+6  ; word
;	%define _out_regs_	bp+8  ; word
;	%define _seg_regs_	bp+10  ;word
;
;		push	bp
;		mov	bp,sp
;		push	si
;		push	di
;		push	ds
;		sub	sp,10
;		mov	byte [int_opcode],0CDh
;		mov	ax,[_disk_int_]
;		mov	byte ptr [int_opcode+1],al
;		cmp	al,25h
;		je	short int86x_25h_26h
;		cmp	al,26h
;		je	short int86x_25h_26h
;		mov	byte [retf_opcode_1],0CBh ; RETF
;		jmp	short int86x_dos_func
;int86x_25h_26h:
;		mov	byte [retf_opcode_2],0CBh ; RETF
;		mov	byte [inc_sp_opcode],44h  ; INC SP
;		mov	byte [retf_opcode_1],44h  ; INC SP
;int86x_dos_func:
;		mov	[call_int+2],ss
;		lea	ax,[int_opcode]
;		mov	[call_int],ax
;		mov	di,[_in_regs_]
;		mov	ax,[di]
;		mov	bx,[di+2]
;		mov	cx,[di+4]
;		mov	dx,[di+6]
;		mov	si,[di+8]
;		push	word [di+10]
;		mov	di,[_seg_regs_]
;		mov	es,[di]
;		mov	ds,[di+6]
;		pop	di
;		push	bp
;		call	far [call_int]
;		pop	bp
;		cld
;		push	di
;		push	ds
;		push	ss
;		pop	ds
;		mov	di,[_seg_regs_]
;		mov	[di],es
;		pop	word [di+6]
;		mov	di,[_out_regs_]
;		mov	[di],ax
;		mov	[di+2],bx
;		mov	[di+4],cx
;		mov	[di+6],dx
;		mov	[di+8],si
;		pop	word [di+10]
;		jc	short int86x_dos_func_err
;		xor	si,si
;		jmp	short int86x_retn
;int86x_dos_func_err:
;		call	int86_err_conv
;		mov	si,1
;		mov	ax,[di]
;int86x_retn:
;		mov	[di+12],si
;		add	sp,10
;		pop	ds
;		pop	di
;		pop	si
;		mov	sp,bp
;		pop	bp
;		retn

; ---------------------------------------------------------------------------

;int86_err_conv:
;		xor	ah,ah
;		call	error_conversion
;		retn

; ---------------------------------------------------------------------------

;error_conversion:
;		mov	[_doserrno],al
;		or	ah,ah
;		jnz	short errconv_5
;		cmp	[_dosvermajor],3
;		jb	short errconv_1
;		cmp	al,22h
;		jnb	short errconv_2
;		cmp	al,20h
;		jb	short errconv_1
;		mov	al,5
;		jmp	short errconv_3
;errconv_1:
;		cmp	al,13h
;		jbe	short errconv_3
;errconv_2:
;		mov	al,13h
;errconv_3:
;		mov	bx,err_conv_tbl
;		xlat
;errconv_4:
;		cbw
;		mov	[errno],ax
;		retn
;errconv_5:
;		mov	al,ah
;		jmp	short errconv_4

; ----------------------------------------------------------------------------
; vdisplay.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 27/11/2018)

;/******************************************************************************/
;/*Routine name:  CHANGE_CURRENT_DRIVE                                         */
;/******************************************************************************/
;/*                                                                            */
;/*Description:   This routine will change the current drive for FDISK         */
;/*               to any valid drive (up to 7). It will also display a        */
;/*               menu with disk information on all disks available for        */
;/*               the system be FDISKed.                                       */
;/*                                                                            */
;/*Called Procedures:    Display                                               */
;/*                      Find_part_free_space                                  */
;/*                      Sort_Ext_Table                                        */
;/*                      Get_Num_Input                                         */
;/*                      Clear_Screen                                          */
;/*                                                                            */
;/*Change History: Created        1/06/89         DRM                          */
;/*                                                                            */
;/*Input:  None                                                                */
;/*                                                                            */
;/*Output: None                                                                */
;/*                                                                            */
;/******************************************************************************/
;
;void change_current_drive()                                         /* BN000 */
;
;BEGIN                                                               /* BN000 */
;
;    unsigned    i;                                                  /* BN000 */
;/*C00 unsigned    j;    */                                          /* BN000 */
;    unsigned    k;                                                  /* BN000 */
;/*C32 char        drive_letter;         */                          /* BN000 */
;/*C32 char        primary_drive_letter; */                          /* BN000 */
;    char        drive_num;                                          /* BN000 */
;    char        temp;                                               /* BN000 */
;/*C11 char        temp1; */                                         /* BN000 */
;    unsigned    temp1;                                                  /*C11*/
;    unsigned    mbytes_free;                                            /*C11*/
;    unsigned    percent_used;                                           /*C11*/
;    unsigned    insert_offset;                                      /* BN000 */
;    unsigned    input;                                              /* BN000 */
;    char        max_input;                                          /* BN000 */
;/*C00 char        blanks[9]; */                                     /* BN000 */
;
;    /* Initialize some variables */
;    insert_offset = 0;                                              /* BN000 */
;    drive_num = c(0);                                               /* BN000 */
;/*C32  primary_drive_letter = c(SEA); */                            /* BN000 */
;
;   /* get the current drive letters */                                 /*C32*/
;   get_letters();                                                      /*C32*/
;
;    /* Clear the whole screen for display */
;    clear_screen(u(0),u(0),u(24),u(79));                            /* BN000 */
;
;    /* initialize all the inserts to blanks */
;/*C19  memset(insert,c(' '),(31*15)); */                            /* BN000 */
;    memset(insert,c(' '),(32*15));                                      /*C19*/
;
;    /* Save current disk */
;    temp = cur_disk;                                                /* BN000 */
;
;    /* Display the heading */
;    if (status_flag == FALSE)                                       /* BN000 */
;        display(menu_47);                                           /* BN000 */
;    else                                                            /* BN000 */
;        display(menu_54);                                           /* BN000 */
;
;    /* Figure out which drive letter the extended partitions begin with  */
;/*C32  drive_letter = (c(SEA) + primary_partition_count); */        /* BN000 */
;
;    /* Get the drive information in ascending order and put into array */
;    for (i=u(0); i < u(number_of_drives); i++)                      /* BN000 */
;
;        BEGIN                                                       /* BN000 */
;
;        /* find freespace on current drive and display drive information */
;        cur_disk = c(i);                                            /* BN000 */
;/*C11   temp1 = find_part_free_space(PRIMARY); */                   /* BN000 */
;        temp1 = part_table[cur_disk][0].mbytes_used +                   /*C11*/
;                part_table[cur_disk][1].mbytes_used +                   /*C11*/
;                part_table[cur_disk][2].mbytes_used +                   /*C11*/
;                part_table[cur_disk][3].mbytes_used;                    /*C11*/
;        if (temp1 < total_mbytes[cur_disk])                             /*C11*/
;            mbytes_free = total_mbytes[cur_disk] - temp1;               /*C11*/
;        else                                                            /*C11*/
;            mbytes_free = u(0);                                         /*C11*/
;        temp1 = part_table[cur_disk][0].percent_used +                  /*C11*/
;                part_table[cur_disk][1].percent_used +                  /*C11*/
;                part_table[cur_disk][2].percent_used +                  /*C11*/
;                part_table[cur_disk][3].percent_used;                   /*C11*/
;        if (temp1 < u(100))                                             /*C11*/
;            percent_used = temp1;                                       /*C11*/
;        else                                                            /*C11*/
;            percent_used = u(100);                                      /*C11*/
;        insert_offset += sprintf(&insert[insert_offset],"%1.0d%c%c%4.0d%4.0d%3.0d%%",
;            (cur_disk + 1),
;            ' ',
;            ' ',
;            total_mbytes[cur_disk],
;/*C11       free_space[temp1].mbytes_unused,               */
;/*C11       (u(100) - free_space[temp1].percent_unused));  */       /* BN000 */
;            mbytes_free,                                                /*C11*/
;            percent_used);                                              /*C11*/
;        drive_num++;                                                /* BN000 */
;
;        /* Sort the partitions */
;        sort_part_table(c(4));                                      /* BN000 */
;        /* Now look at the partitions in order */
;        for (k=u(0); k < u(4); k++)                                 /* BN000 */
;            BEGIN                                                   /* BN000 */
;            /* see if there is a primary partition */
;            if( (part_table[cur_disk][sort[k]].sys_id == DOSNEW) ||
;                (part_table[cur_disk][sort[k]].sys_id == DOS16) ||
;                (part_table[cur_disk][sort[k]].sys_id == DOS12) )
;                BEGIN                                               /* BN000 */
;                insert_offset += sprintf(&insert[insert_offset],"%c%c%c%4.0d%8c",
;                    ' ',
;/*C32               c(primary_drive_letter),               */
;/*C32               (drive_letter == c(' ') ) ? ' ' : ':', */
;                    part_table[cur_disk][sort[k]].drive_letter,         /*C32*/
;                    (part_table[cur_disk][sort[k]].drive_letter == c(' ') ) ? ' ' : ':',
;                    part_table[cur_disk][sort[k]].mbytes_used,
;                    ' ');                                           /* BN000 */
;                    drive_num++;                                    /* BN000 */
;/*C32               primary_drive_letter++; */                      /* BN000 */
;                END                                                 /* BN000 */
;            END                                                     /* BN000 */
;
;        /* loop thru the partitions, only print stuff if it is there */
;
;        /* Get the drives in order by location on disk */
;        sort_ext_table(c(23));                                      /* BN000 */
;
;        for (k=u(0); k < u(23); k++)                                /* BN000 */
;            BEGIN                                                   /* BN000 */
;            /* if last drive letter was Z, print spaces */
;/*C32       if ((drive_letter > c('Z')) ) */
;/*C32            drive_letter = c(' ');   */                        /* BN000 */
;            /* If it has a size, print it */
;            if ( (ext_table[cur_disk][sort[k]].mbytes_used != u(0)) ||
;                 (ext_table[cur_disk][sort[k]].percent_used != u(0)) ) /* BN000 */
;
;                BEGIN
;                insert_offset += sprintf(&insert[insert_offset],"%c%c%c%4.0d%8c",
;                    ' ',
;/*C32               drive_letter, */
;/*C32               (drive_letter == c(' ') ) ? ' ' : ':', */
;                    ext_table[cur_disk][sort[k]].drive_letter,          /*C32*/
;                    (ext_table[cur_disk][sort[k]].drive_letter == c(' ') ) ? ' ' : ':', /*C32*/
;                    ext_table[cur_disk][sort[k]].mbytes_used,
;                    ' ');                                           /* BN000 */
;                    drive_num++;                                    /* BN000 */
;/*C32               drive_letter++; */                              /* BN000 */
;                END                                                 /* BN000 */
;            END                                                     /* BN000 */
;        END                                                         /* BN000 */
;
;    /* Display the column of drives */
;    BEGIN                                                           /* BN000 */
;
;    if ( drive_num > 0 )                                            /* BN000 */
;        BEGIN                                                       /* BN000 */
;        pinsert = &insert[0];                                       /* BN000 */
;        display(menu_48);                                           /* BN000 */
;        END                                                         /* BN000 */
;
;    if ( drive_num > 8 )                                            /* BN000 */
;        BEGIN                                                       /* BN000 */
;        pinsert = &insert[8*15];                                    /* BN000 */
;        display(menu_49);                                           /* BN000 */
;        END                                                         /* BN000 */
;
;    if ( drive_num > 16 )                                           /* BN000 */
;        BEGIN                                                       /* BN000 */
;        pinsert = &insert[16*15];                                   /* BN000 */
;        display(menu_50);                                           /* BN000 */
;        END                                                         /* BN000 */
;
;    if ( drive_num > 24 )                                           /* BN000 */
;        BEGIN                                                       /* BN000 */
;        pinsert = &insert[24*15];                                   /* BN000 */
;        display(menu_51);                                           /* BN000 */
;        END                                                         /* BN000 */
;    pinsert = &insert[0];                                           /* BN000 */
;    END                                                             /* BN000 */
;
;   /* display Mbytes = line */
;   display(menu_52);                                               /* BN000 */
;
;    /* reset current disk back to original */
;    cur_disk = temp;                                                /* BN000 */
;
;    if (status_flag == FALSE)                                       /* BN000 */
;        BEGIN
;        /* Display prompt of which disk */
;        sprintf(insert,"%1.0d%1.0d",number_of_drives,(cur_disk+1)); /* BN000 */
;        display(menu_53);                                           /* BN000 */
;
;        /* ESC line at bottom of screen */
;        display(menu_11);                                           /* BN000 */
;
;        max_input = c(number_of_drives);                            /* BN000 */
;
;        valid_input = (FLAG)FALSE;                                  /* BN000 */
;
;       /* Get the input from screen */
;        while (!valid_input)                                        /* BN000 */
;            BEGIN                                                   /* BN000 */
;            input = get_num_input(c(cur_disk+1),max_input,input_row,input_col);
;            clear_screen(u(21),u(0),u(23),u(79));                   /* BN000 */
;
;           /* set current disk to zero base */
;           if (input != u(ESC)) cur_disk = c(input-'1');           /* BN000 */
;            END                                                     /* BN000 */
;
;        /* clear the screen before going back to main menu */
;        clear_screen(u(0),u(0),u(24),u(79));                        /* BN000 */
;        END                                                         /* BN000 */
;    return;                                                         /* BN000 */
;END                                                                 /* BN000 */

usp: dw 0

change_current_drive:
				; 12/12/2018
	%define _k		bp-16 ; bp-20 ; unsigned int
	%define _insert_offset	bp-14 ; bp-18 ; unsigned int
	%define _i		bp-12 ; bp-16 ; unsigned int
	%define _drive_num	bp-10 ; bp-14 ; char
	%define _temp_		bp-8  ; bp-10 ; char
	%define _mbytes_free	bp-6  ; bp-8  ; unsigned int
	%define _max_input	bp-4  ; bp-6  ; unsigned int
	;%define _percent_used	bp-4  ;	bp-4  ; unsigned int
	%define _input_		bp-2  ; bp-2  ; unsigned int

		push	bp
		mov	bp,sp
		;sub	sp,20
		sub	sp,16 ; 12/12/2018
		push	si

		;/* Initialize some variables */
		;mov	word [_drive_num],0
		xor	ax,ax ; 0
		mov	[_drive_num],ax ; 0		
		mov	[_insert_offset],ax ; 0

		;/* get the current drive letters */ 
		call	get_letters
		
		;/* Clear the whole screen for display */
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax ; 0
		;mov	[_insert_offset],ax
		;push	ax
		;push	ax
		;call	clear_screen
		;;add	sp,8

		; Clear screen (clear whole video page)
		call	CLS

		;/* initialize all the inserts to blanks */
		;memset(insert,c(' '),(32*15));            

		;mov	ax,480
		;push	ax
		;mov	ax,' '
		;push	ax
		;mov	ax,insert
		;push	ax
		;call	memset
		;add	sp,6

		; 01/12/2018
		; memset shortcut
		mov	al,' '
		mov	cx,480
		mov	di,insert
		;push	ds
		;pop	es
		rep	stosb

		;/* Save current disk */
		mov	al,[cur_disk]
		mov	[_temp_],al

		;/* Display the heading */
		;if (status_flag == FALSE)
		;   display(menu_47);
		;else
		;   display(menu_54);

		cmp	byte [status_flag],0
		jne	short ccd_1
		;push	word [menu_47_segment]
		push	ds
		push	word [menu_47_offset]
		jmp	short ccd_2
ccd_1:
		;push	word [menu_54_segment]
		push	ds
		push	word [menu_54_offset]
ccd_2:
		call	display
		;pop	bx
		;pop	bx

	;/* Get the drive information in ascending order and put into array */
	;for (i=u(0); i < u(number_of_drives); i++)  

		mov	word [_i],0
		jmp	ccd_20
ccd_3:
		mov	word [_mbytes_free],0
ccd_4:
	;temp1 = part_table[cur_disk][0].percent_used +
	;        part_table[cur_disk][1].percent_used +
	;        part_table[cur_disk][2].percent_used +
	;        part_table[cur_disk][3].percent_used;
	;if (temp1 < u(100))
	;   percent_used = temp1;
	;else
	;   percent_used = u(100);

		;mov	al,[cur_disk]
		;cbw
		;;imul	cx
		;mul	cx ; 184, 4*46
		;mov	bx,ax
		;mov	ax,[part_table_percent_used+bx]
		;add	ax,[pt_part4_percent_used+bx]
		;add	ax,[pt_part3_percent_used+bx]
		;add	ax,[pt_part2_percent_used+bx]

		; 27/11/2018 (si from ccd_20)
		mov	ax,[part_table_percent_used+si] ; +***
		add	ax,[pt_part4_percent_used+si]
		add	ax,[pt_part3_percent_used+si]
		add	ax,[pt_part2_percent_used+si]
		
		;cmp	ax,100
		;jnb	short ccd_5
		;mov	[_percent_used],ax
		;jmp	short ccd_6
		
		; 09/12/2018
		cmp	ax,100
		jna	short ccd_5
		mov	ax,100
ccd_5:
		;mov	word [_percent_used],100
		; 12/12/2018
		;mov	[_percent_used],ax ; 09/12/2018	
ccd_6:
	;insert_offset += sprintf(&insert[insert_offset],"%1.0d%c%c%4.0d%4.0d%3.0d%%",
	;    (cur_disk + 1),' ',' ',total_mbytes[cur_disk],mbytes_free,percent_used);                                              /*C11*/
	;drive_num++;

		;push	word [_percent_used]
		push	ax ; 12/12/2018 
		push	word [_mbytes_free]
		mov	al,[cur_disk]
		cbw
		;mov	bx,ax
		;shl	bx,1
		; 27/11/2018 (bx from ccd_21)
		push	word [total_mbytes+bx] ; ++***
		;mov	cx,' '
		mov	cl,' ' ; 01/12/2018
		push	cx
		push	cx
		inc	ax
		push	ax
		mov	ax,cd_pt_row_format ; "%1.0d%c%c%4.1d%4.1d%3.1d%%"
		push	ax
		mov	ax,[_insert_offset]
		add	ax,insert
		push	ax
		call	sprintf
		add	sp,16
		add	[_insert_offset],ax
		inc	byte [_drive_num]

		;/* Sort the partitions */
		;sort_part_table(c(4));
		;mov	al,4
		;push	ax
		mov	cl,4 ; 12/12/2018
		call	sort_part_table
		;pop	bx

		;/* Now look at the partitions in order */
		;for (k=u(0); k < u(4); k++)

		mov	word [_k],0
		jmp	short ccd_10
ccd_7:
		; 28/11/2018
		; al = ' ', ah = 0
		cmp	byte [part_table_drive_letter+bx],' '
		je	short ccd_8
		;mov	ax,':'
		mov	al,':'
ccd_8:
		push	ax
		mov	al,[part_table_drive_letter+bx]
		;cbw
		push	ax
		;mov	ax,' '
		mov	al,' '
		push	ax
		mov	ax,drv_mb_row_format ; "%c%c%c%4.1d%8c"
		push	ax
		mov	ax,[_insert_offset]
		add	ax,insert
		push	ax
		call	sprintf
		add	sp,14
		add	[_insert_offset],ax

		inc	byte [_drive_num]
ccd_9:
		inc	byte [_k]
;ccd_10:
		cmp	byte [_k],4
		jnb	short ccd_13
ccd_10: 			; 09/12/2018

		;/* see if there is a primary partition */
		;if( (part_table[cur_disk][sort[k]].sys_id == DOSNEW) ||
		;    (part_table[cur_disk][sort[k]].sys_id == DOS16) ||
		;    (part_table[cur_disk][sort[k]].sys_id == DOS12) )

		; 28/11/2018

		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	cx,ax
		mov	cl,[cur_disk]
		;xor	ch,ch
		; 01/12/2018
		shl	cl,1
		shl	cl,1

		mov	bx,[_k]
		mov	al,[sort+bx] ; 07/12/2018

		;cbw
		;add	ax,cx
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl

		mov	bx,ax ;+++**

		cmp	byte [part_table_sys_id+bx],DOSNEW ; 6
		je	short ccd_11
		cmp	byte [part_table_sys_id+bx],DOS16  ; 4
		je	short ccd_11
		cmp	byte [part_table_sys_id+bx],DOS12  ; 1
		jne	short ccd_9
ccd_11:
	;insert_offset += sprintf(&insert[insert_offset],"%c%c%c%4.0d%8c",
	;	' ',part_table[cur_disk][sort[k]].drive_letter,
	;	(part_table[cur_disk][sort[k]].drive_letter == c(' ') ) ? ' ' : ':',
	;	part_table[cur_disk][sort[k]].mbytes_used,' '); 
	; drive_num++;

		mov	ax,' '
		push	ax

		; 28/11/2018
		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	bx,[_k]
		;mov	cx,ax
		;mov	al,[sort+bx] ; 07/12/2018
		;cbw
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax ; +++**
		
		push	word [part_table_mbytes_used+bx]
		;cmp	byte [part_table_drive_letter+bx],' '
		;;je	short ccd_12
		;jmp	short ccd_7
		;je	short ccd_8
		jmp	short ccd_7
;ccd_12:
		;mov	ax,' ' ; 28/11/2018
		;jmp	short ccd_8
ccd_13:
		;/* Get the drives in order by location on disk */
		;sort_ext_table(c(23));   

		;mov	al,23
		;push	ax
		mov	cl,23 ; 12/12/2018
		call	sort_ext_table
		;pop	bx

		;for (k=u(0); k < u(23); k++)

		mov	byte [_k],0
		jmp	short ccd_17
ccd_14:
		; 01/12/2018
		;mov	ax,':'

		; al = ' ', ah = 0
		cmp	byte [ext_table_drive_letter+bx],' '
		je	short ccd_15
		;mov	ax,':'
		mov	al,':'
ccd_15:
		push	ax
		mov	al,[ext_table_drive_letter+bx]
		;cbw
		push	ax
		;mov	ax,' '
		mov	al,' '
		push	ax
		mov	ax,cdrv_mb_format ; "%c%c%c%4.1d%8c"
		push	ax
		mov	ax,[_insert_offset]
		add	ax,insert
		push	ax
		call	sprintf
		add	sp,14
		add	[_insert_offset],ax

		inc	byte [_drive_num]
ccd_16:
		inc	byte [_k]
;ccd_17:
		cmp	byte [_k],23
		jnb	short ccd_19
ccd_17: 		; 13/12/2018
		;/* If it has a size, print it */
		;if ( (ext_table[cur_disk][sort[k]].mbytes_used != u(0)) ||
		;     (ext_table[cur_disk][sort[k]].percent_used != u(0)) )

		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk] ; 0 to 7
		mov	bx,[_k]
		mov	cx,ax ; ah = 0 (ax<=168)
		mov	al,[sort+bx] ; 07/12/2018
		;cbw
		;add	ax,cx
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax ; +++**+
		cmp	word [ext_table_mbytes_used+bx],0
		jne	short ccd_18
		cmp	word [ext_table_percent_used+bx],0
		je	short ccd_16
ccd_18:
	;insert_offset += sprintf(&insert[insert_offset],"%c%c%c%4.0d%8c",' ',
	;   ext_table[cur_disk][sort[k]].drive_letter,
	;   (ext_table[cur_disk][sort[k]].drive_letter == c(' ') ) ? ' ' : ':',
	;   ext_table[cur_disk][sort[k]].mbytes_used,' ');
	;drive_num++;

		mov	ax,' '
		push	ax
		
		; 01/12/2018

		;mov	al,24
		;;imul	byte [cur_disk]
		;mul	byte [cur_disk]
		;mov	bx,[_k]
		;mov	cx,ax
		;mov	al,[sort+bx] ; 07/12/2018
		;cbw
		;add	ax,cx
		;mov	cx,46
		;;imul	cx
		;mul	cx
		;mov	bx,ax ; +++**+
		
		push	word [ext_table_mbytes_used+bx]
		;cmp	byte [ext_table_drive_letter+bx],' '
		;jne	short ccd_14
		;mov	ax,' '
		;jmp	short ccd_15
		jmp	short ccd_14 ; 01/12/2018
ccd_19:
		inc	byte [_i]
ccd_20:
	;/* find freespace on current drive and display drive information */
		;cur_disk = c(i);
		;mov	al,[number_of_drives]
		;sub	ah,ah
		;;cmp	ax,[_i]
		;cmp	al,[_i] ; 01/12/2018
		;jbe	short ccd_22
		;mov	al,[_i]
		;mov	[cur_disk],al

		; 10/12/2018
		;mov	al,[_i]
		;sub	ah,ah
		mov	ax,[_i] ; 12/12/2018
		cmp	al,[number_of_drives]
		jnb	short ccd_22

		mov	[cur_disk],al	

	;temp1 = part_table[cur_disk][0].mbytes_used +
	;        part_table[cur_disk][1].mbytes_used +
	;        part_table[cur_disk][2].mbytes_used +
	;        part_table[cur_disk][3].mbytes_used;

	;if (temp1 < total_mbytes[cur_disk])
	;   mbytes_free = total_mbytes[cur_disk] - temp1
	;else
	;   mbytes_free = u(0);

		;cbw
		mov	cx,184 ; 4*46
		mov	bx,ax  ; [cur_disk], 0 to 7
		;imul	cx
		;mul	cx
		mul	cl
		mov	si,ax
		mov	ax,[part_table_mbytes_used+si] ; +***
		add	ax,[pt_part4_mbytes_used+si]
		add	ax,[pt_part3_mbytes_used+si]
		add	ax,[pt_part2_mbytes_used+si]
		shl	bx,1
		cmp	ax,[total_mbytes+bx]
		jb	short ccd_21
		jmp	ccd_3
ccd_21:
		sub	ax,[total_mbytes+bx] ; ++***
		neg	ax
		mov	[_mbytes_free],ax
		jmp	ccd_4
ccd_22:
		;/* Display the column of drives */
	
		;if ( drive_num > 0 )
		;     BEGIN
		;     pinsert = &insert[0];
		;     display(menu_48);
		;     END

		cmp	byte [_drive_num],0
		;jle	short ccd_23
		jna	short ccd_26 ; 01/12/2018
		
		mov	word [pinsert],insert

		;push	word [menu_48_segment]
		push	ds
		push	word [menu_48_offset]
		call	display
		;pop	bx
		;pop	bx
ccd_23:
		;if ( drive_num > 8 )
		;     BEGIN
		;     pinsert = &insert[8*15];
		;     display(menu_49);
		;     END             

		cmp	byte [_drive_num],8
		;jle	short ccd_24
		jna	short ccd_26 ; 01/12/2018

		mov	word [pinsert],insert+120

		;push	word [menu_49_segment]
		push	ds
		push	word [menu_49_offset]
		call	display
		;pop	bx
		;pop	bx
ccd_24:
		;if ( drive_num > 16 )
		;     BEGIN
		;     pinsert = &insert[16*15];
		;     display(menu_50);
		;     END

		cmp	byte [_drive_num],16
		;jle	short ccd_25
		jna	short ccd_26 ; 01/12/2018

		mov	word [pinsert],insert+240

		;push	word [menu_50_segment]
		push	ds
		push	word [menu_50_offset]
		call	display
		;pop	bx
		;pop	bx
ccd_25:
		;if ( drive_num > 24 )
		;     BEGIN
		;     pinsert = &insert[24*15];
		;     display(menu_51);
		;     END
		;pinsert = &insert[0];  

		cmp	byte [_drive_num],24
		;jle	short ccd_26
		jna	short ccd_26 ; 01/12/2018

		mov	word [pinsert],insert+360

		;push	word [menu_51_segment]
		push	ds
		push	word [menu_51_offset]
		call	display
		;pop	bx
		;pop	bx
ccd_26:
		mov	word [pinsert],insert

		;/* display Mbytes = line */
		;display(menu_52);
		;push	word [menu_52_segment]
		push	ds
		push	word [menu_52_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* reset current disk back to original */
		;cur_disk = temp;  
		mov	al,[_temp_]
		mov	[cur_disk],al

		;if (status_flag == FALSE)  
		cmp	byte [status_flag],0
		jne	short ccd_30 ; 09/12/2018
ccd_27:
		;/* Display prompt of which disk */
		;sprintf(insert,"%1.0d%1.0d",number_of_drives,(cur_disk+1));
		;display(menu_53); 

		;cbw
		;inc	ax
		sub	ah,ah
		inc	al  ; [cur_disk] + 1
		push	ax
		mov	al,[number_of_drives]
		;sub	ah,ah
		push	ax
		mov	ax,cdrive_format ; "%1.0d%1.0d"
		push	ax
		mov	ax,insert
		push	ax
		call	sprintf
		add	sp,8

		;push	word [menu_53_segment]
		push	ds
		push	word [menu_53_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* ESC line at bottom of screen */
		;display(menu_11);                            
		
		;;push	word [menu_11_segment]
		;push	ds
		;push	word [menu_11_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_11 ; 31/12/2018

		;max_input = c(number_of_drives);
		mov	al,[number_of_drives]
		mov	[_max_input],al
		;valid_input = (FLAG)FALSE;
		mov	byte [valid_input],0
ccd_28:
		;/* Get the input from screen */
	;input = get_num_input(c(cur_disk+1),max_input,input_row,input_col);

		push	word [input_col]
		push	word [input_row]
		mov	al,[_max_input]
		push	ax
		mov	al,[cur_disk]
		inc	al
		push	ax
		call	get_num_input
		;add	sp,8 ; 15/12/2018
		;cbw	 ; *-* 
		mov	[_input_],ax ;*-*

		;clear_screen(u(21),u(0),u(23),u(79));

		mov	ax,79	; Right Column = 79
		push	ax	
		mov	ax,23	; Bottom Row = 23
		push	ax	
		sub	ax,ax	; Left Column = 0
		push	ax	
		mov	ax,21	; Top Row = 21
		push	ax
		call	clear_screen  ; (clear_screen_down, clear screen rows)
		;add	sp,8

		;/* set current disk to zero base */
		;if (input != u(ESC)) cur_disk = c(input-'1');

		;cmp	word [_input_],1Bh ; *-*
		cmp	byte [_input_],1Bh  ; ESC
		je	short ccd_29
		mov	al,[_input_]
		sub	al,'1'
		mov	[cur_disk],al
ccd_29:
		;/* Get the input from screen */
		;while (!valid_input)

		cmp	byte [valid_input],0
		je	short ccd_28

		;/* clear the screen before going back to main menu */
		;clear_screen(u(0),u(0),u(24),u(79)); 

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		; Clear screen (clear whole video page)
		call	CLS
ccd_30:

;;temporary - 13/12/2018
;push cs
;pop ds
;mov si,insert
;mov ah,4Eh
;mov bx,7
;lccd1:
;lodsb
;and al,al
;jz short lccd2
;int 10h
;jmp short lccd1
;lccd2:
;xor ax,ax
;int 16h	
		pop	si
		mov	sp,bp
		pop	bp
		retn

; memset function (Microsoft C 6.0 runtime library)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 01/12/2018)

; http://www.cplusplus.com/reference/cstring/memset/
;
;function	;<cstring>
;memset:
;
;void * memset ( void * ptr, int value, size_t num );
;
;Fill block of memory
;Sets the first num bytes of the block of memory pointed by ptr to the specified value 
;	(interpreted as an unsigned char).
;
;Parameters:
;	ptr:	Pointer to the block of memory to fill.
;	value:	Value to be set. The value is passed as an int, 
;		but the function fills the block of memory using 
;		the unsigned char conversion of this value.
;	num:	Number of bytes to be set to the value.
;		size_t is an unsigned integral type.
;
;Return Value:
;	ptr is returned.

;memset:
;	%define	_ptr	bp+4
;	%define	_value	bp+6
;	%define _num	bp+8
;
;		push	bp
;		mov	bp,sp
;		mov	dx,di
;		mov	ax,ds
;		mov	es,ax
;		mov	di,[_ptr]
;		mov	bx,di
;		mov	cx,[_num]
;		jcxz	short memset_2
;		mov	al,[_value]
;		mov	ah,al
;		test	di,1
;		jz	short metset_1
;		stosb
;		dec	cx
;metset_1:
;		shr	cx,1
;		rep stosw
;		adc	cx,cx
;		rep stosb
;memset_2:
;		mov	di,dx
;		xchg	ax,bx
;		pop	bp
;		retn

; sprintf function (Microsoft C 6.0 runtime library)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 01/12/2018)

; http://www.cplusplus.com/reference/cstdio/sprintf/
;
;function	;<cstdio>
;sprintf:
;
;int sprintf ( char * str, const char * format, ... );
;
;Write formatted data to string
; Composes a string with the same text that would be printed if 
; format was used on printf, but instead of being printed, 
; the content is stored as a C string in the buffer pointed by str.
;
;Parameters:
;	str:	Pointer to a buffer where the resulting C-string is stored.
;		The buffer should be large enough to contain the resulting string.
;	format:	C string that contains a format string that follows 
;		the same specifications as format in printf (see printf for details).
;
;	... (additional arguments)
;
;		Depending on the format string, the function may expect 
;		a sequence of additional arguments, each containing a value 
;		to be used to replace a format specifier in the format string 
;		(or a pointer to a storage location, for n).
;		There should be at least as many of these arguments 
;		as the number of values specified in the format specifiers. 
;		Additional arguments are ignored by the function.
;Return Value:
;	On success, the total number of characters written is returned. 
;	This count does not include the additional null-character 
;	automatically appended at the end of the string.
;	On failure, a negative number is returned.

; sprintf and _doprnt from PORTABLE C Compiler (8086.zip,1983-1987)
; ----------------------------------------------------------------------------
;			   8086/nlib86/stdio/doprnt.c  ; 1982	 
;			   8086/nlib86/stdio/sprintf.c ; 1982
;
; https://www.tuhs.org/Archive/Applications/Portable_CC/  
; (01/12/2018)
;
;Index of /Archive/Applications/Portable_CC
;
;  Name           Last modified	   Size    Description
;----------     ----------------  ------- -------------
;286.zip	2002-08-09 12:38   169K	 
;8086.zip	2002-08-09 12:38   1.3M	 ; **this**
;16032.zip	2002-08-09 12:39   305K	 
;68000.zip	2002-08-09 12:40   504K	 
;README		2002-08-10 10:10    145
;	 
;Apache/2.4.18 (Ubuntu) Server at www.tuhs.org Port 443

;
; https://www.tuhs.org/Archive/Applications/Portable_CC/README
;
; Al Kossow sent in these versions of the portable C compiler for the 8086,
; Z8000, and 68000 done by MIT's Laboratory for Computer Science. Enjoy.
;

; stdio.h
;---------
;
;#define	BUFSIZ	512
;#define	_NFILE	20
;# ifndef FILE
;extern	struct	_iobuf {
;	char	*_ptr;
;	int	_cnt;
;	char	*_base;
;	char	_flag;
;	char	_file;
;} _iob[_NFILE];
;# endif
;
;#define _IOREAD  01	; 01h
;#define _IOWRT	  02	; 02h	
;#define _IONBF	  04	; 04h
;#define _IOMYBUF 010	; 08h
;#define _IOEOF	  020	; 10h
;#define _IOERR	  040	; 20h
;#define _IOSTRG  0100	; 40h

;#define NULL	0
;#define FILE	struct _iobuf
;#define EOF	(-1)
;
;#define stdin	(&_iob[0])
;#define stdout	(&_iob[1])
;#define stderr	(&_iob[2])
;#define getc(p)   (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))
;#define getchar() getc(stdin)
;#define putc(x,p) (--(p)->_cnt>=0? ((int)(*(p)->_ptr++=(unsigned)(x))):_flsbuf((unsigned)(x),p))
;#define putchar(x) putc(x,stdout)
;#define feof(p)   (((p)->_flag&_IOEOF)!=0)
;#define ferror(p) (((p)->_flag&_IOERR)!=0)
;#define fileno(p) (p)->_file
;
;FILE	*fopen();
;FILE	*freopen();
;FILE	*fdopen();
;long	ftell();
;char	*fgets();


; sprintf.c
;-----------
; 
;#include	<stdio.h>
;
;char *sprintf(str, fmt, args)
;char *str, *fmt;
;{
;	struct _iobuf _strbuf;
;
;	_strbuf._flag = _IOWRT+_IOSTRG;
;	_strbuf._ptr = str;
;	_strbuf._cnt = 32767;
;	_doprnt(fmt, &args, &_strbuf);
;	putc('\0', &_strbuf);
;	return(str);
;}

; SPRINTF.C (VCCRT2.ZIP) - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; Microsoft(R) Visual C++ Version 1.0 Run-Time Library Sources (1993)
;
; Downloaded From : The Programmer's Corner (www.pcorner.com) - 01/12/2018 -

;/****************************************************************************
;#ifndef _COUNT_
;*int sprintf(string, format, ...) - print formatted data to string
;#else
;*int _snprintf(string, cnt, format, ...) - print formatted data to string
;#endif
;*
;*Purpose:
;*   Prints formatted data to the using the format string to
;*   format data and getting as many arguments as called for
;*   Sets up a FILE so file i/o operations can be used, make string look
;*   like a huge buffer to it, but _flsbuf will refuse to flush it if it
;*   fills up.  Appends '\0' to make it a true string.
;*   _output does the real work here
;*
;*   Allocate the 'fake' _iob[] entryit statically instead of on
;*   the stack so that other routines can assume that _iob[] entries are in
;*   are in DGROUP and, thus, are near.
;*
;#ifdef _COUNT_
;*   The _snprintf() flavor takes a count argument that is
;*   the max number of bytes that should be written to the
;*   user's buffer.
;#endif
;*
;*   Multi-thread: (1) Since there is no stream, this routine must never try
;*   to get the stream lock (i.e., there is no stream lock either). (2)
;*   Also, since there is only one staticly allocated 'fake' iob, we must
;*   lock/unlock to prevent collisions.
;*
;*Entry:
;*   char *string - pointer to place to put output
;#ifdef _COUNT_
;*   size_t count - max number of bytes to put in buffer
;#endif
;*   char *format - format string to control data format/number of arguments
;*   followed by list of arguments, number and type controlled by
;*   format string
;*
;*Exit:
;*   returns number of characters printed
;*
;*Exceptions:
;*
;****************************************************************************/

;#ifndef _COUNT_
;
;int 
;sprintf (char *string, const char *format, ...)
;
;#else
;
;int 
;_snprintf (char *string, size_t count, const char *format, ...)
;
;#endif
;
;{
;   static FILE _NEAR_ str;
;   REG1 FILE _NEAR_ *outfile = &str;
;   va_list arglist;
;   REG2 int retval;
;
;   va_start(arglist, format);
;
;   assert(string != NULL);
;   assert(format != NULL);
;
;   outfile->_flag = _IOWRT|_IOSTRG;
;   outfile->_ptr = outfile->_base = string;
;#ifndef _COUNT_
;   outfile->_cnt = MAXSTR;
;#else
;   outfile->_cnt = count;
;#endif
;
;   retval = _output(outfile,format,arglist);
;
;   putc('\0',outfile); /* no-lock version */
;
;   return(retval);
;}

; NASM structure format of _strbuf (_iobuf structure)
struc	_strbuf
._ptr:	resw 1	; pointer ; char *_ptr;
._cnt:	resw 1	; integer ; int	 _cnt;
._base: resw 1 	; pointer ; char *_base;
._flag:	resb 1  ; char    ; char _flag;
._file: resb 1  ; char    ; char _file;	
.size:
endstruc

;; IBM PC-DOS 7.0 FDISK.COM (!unpacked!) segment 0 (code segment), Offset 70BEh. 

sprintf:

	%define _printf_buff	bp+4
	%define _printf_format	bp+6
	%define _printf_arg	bp+8

		push	bp
		mov	bp,sp
		;sub	sp,2 ; ?

		push	di ; *
		push	si ; **

	; _strbuf._flag = _IOWRT+_IOSTRG;
	; _strbuf._ptr = str;
	; _strbuf._cnt = 32767;

		; 13/12/2018
		;mov	byte [_strbuf_flag],42h ; _IOWRT + _IOSTRG
	
		mov	ax,[_printf_buff] ; insert + x

		;mov	[_strbuf_base],ax

		;mov	si,strbuf ; _strbuf_ptr
		;mov	[si],ax
		;mov	word [_strbuf_cnt],32767

		; 13/12/2018
		mov	[outbuf_ptr],ax
		;mov	cx,insert+800
		;sub	cx,ax
		;mov	[outbuf_cnt],cx
		
		; 17/12/2018
		; ( 'number_in_msg' procedure -buffer- fixup)
		cmp	ax,insert
		jnb	short sprintf_buf_set_2
sprintf_buf_set_1:
		;mov	cx,32
		mov	cx,4
		jmp	short sprintf_buf_set_3
sprintf_buf_set_2:
		mov	cx,insert+800
		cmp	ax,cx
		jnb	short sprintf_buf_set_1
		sub	cx,ax
sprintf_buf_set_3:
		mov	[outbuf_cnt],cx
		 		
		; _doprnt(fmt, &args, &_strbuf); ; Portable C Compiler

		; retval = _output(outfile,format,arglist); ; Microsoft C Compiler

		lea	ax,[_printf_arg] 
		push	ax
		push	word [_printf_format]
		;mov	ax,si ; 13/12/2018
		;push	ax
		;call	_doprnt
		call	_output ; 02/12/2018
		;add	sp,6		
		add	sp,4 ; 13/12/2018

		;mov	di,ax

		; 13/12/2018
		push	ax ; ***
		mov	al,0
		call	putc
	
		; putc('\0', &_strbuf);
		; putc('\0',outfile); /* no-lock version */

;#define putc(x,p) (--(p)->_cnt>=0? ((int)(*(p)->_ptr++=(unsigned)(x))):_flsbuf((unsigned)(x),p))

;#define putc(_c,_stream)  (--(_stream)->_cnt >= 0 \
;    ? 0xff & (*(_stream)->_ptr++ = (char)(_c)) :  _flsbuf((_c),(_stream)))

		;dec	word [_strbuf_cnt]
		;js	short sprintf_0
		;mov	bx,[_strbuf_ptr]
		;inc	word [_strbuf_ptr]
		;mov	byte [bx],0
		;jmp	short sprintf_1
		;;nop
		;;align 2
;sprintf_0:
		;push	si ; p = &_strbuf
		;sub	ax,ax ; 0
		;push	ax ; x = 0
		;call	_flsbuf
		;add	sp,4
;sprintf_1:
		;mov	ax,di ; return(retval);
		pop	ax ; *** ; 13/12/2018

		pop	si ; **
		pop	di ; *

		;mov	sp,bp
		pop	bp
		retn

;***
;stdio.inc - Definitions and declarations needed by the STDIO functions
;	     written in assembler.
;
;	Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
;
;Purpose:
;	Analog of STDIO.H and FILE2.H for assembler routines.
;
;*******************************************************************************

; Miscellaneous constants

;BUFSIZ		equ	200h
;EOF		equ	0FFFFh

; Element structure for _iob array

;_iobuf	struc
;
;if sizeD				; far data
;	_ptr		dd	?
;	_cnt		dw	?
;	_base		dd	?
;	_flag		db	?
;	_file		db	?
;
;else					; near data
;	_ptr		dw	?
;	_cnt		dw	?
;	_base		dw	?
;	_flag		db	?
;	_file		db	?
;endif
;
;_iobuf	ends

; Size of _iob element (i.e., size of stream structure)

;if sizeD				; far data
;
;_STREAMSZ	equ	12
;
;else					; near data
;
;_STREAMSZ	equ	8
;
;endif

; Element structure for _iob2 array
;
;_iobuf2 struc
;
;	_flag2		db     ?
;	_charbuf	db     ?
;	_bufsiz 	dw     ?
;	_tmpnum 	dw     ?
;
;if sizeD
;	_padding	db     6 dup (?)
;else
;	_padding	db     2 dup (?)
;endif
;
;_iobuf2 ends

; Standard streams
;
;stdin		equ	dataOFFSET _iob
;stdout		equ	dataOFFSET _iob + _STREAMSZ
;stderr		equ	dataOFFSET _iob + 2 * _STREAMSZ
;stdaux		equ	dataOFFSET _iob + 3 * _STREAMSZ
;stdprn		equ	dataOFFSET _iob + 4 * _STREAMSZ

;; Flags
;
;_IOREAD 	equ	01h
;_IOWRT		equ	02h
;
;_IOFBF		equ	0h
;_IOLBF		equ	040h
;_IONBF		equ	04h
;
;_IOMYBUF	equ	08h
;_IOEOF		equ	010h
;_IOERR		equ	020h
;_IOSTRG 	equ	040h
;_IORW		equ	080h
;
;_IOYOURBUF	equ	01h
;_IOFEOF 	equ	08h
;_IOFLRTN	equ	10h
;_IOCTRLZ	equ	20h
;_IOCOMMIT	equ	40h

; _FLSBUF.ASM (VCCRT2.ZIP) - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; Microsoft(R) Visual C++ Version 1.0 Run-Time Library Sources (1993)
;
; Downloaded From : The Programmer's Corner (www.pcorner.com) - 01/12/2018 -

;***
;_flsbuf.asm - flush buffer and output character.
;
;	Copyright (c) 1985-1992, Microsoft Corporation.  All rights reserved.
;
;Purpose:
;	defines _flsbuf() - flush a file buffer and output a character.
;	If no buffer, make one.
;
;*******************************************************************************
;
;--- C VERSION OF ROUTINE
;
; #include <stdio.h>
; #include <register.h>
; #include <file2.h>
; #include <assertm.h>
; #include <malloc.h>
; #include <msdos.h>
; #include <internal.h>
; #include <dos.h>
; #ifdef MTHREAD
; #include <os2dll.h>
; #endif
;
; int cdecl _LOAD_DS
; _flsbuf (ch, str)
; int ch;
; FILE *str;
; {
;     REG1 FILE _NEAR_ *stream;
;     FILE2 _NEAR_ *stream2;
;     REG2 int charcount;
;     REG3 int written;
;     int fh;
;
;     assert(str,"str==NULL");
;
;     /* Init file handle and pointers */
;     stream = (FILE _NEAR_ *) FP_OFF(str);
;     fh = fileno(stream);
;     stream2 = &(_iob2_(stream));
;
;     if (!inuse(stream) || stream->_flag & _IOSTRG) {
;	  stream->_flag |= _IOERR;
;	  return(-1);
;     }
;
;     if (stream->_flag & _IOREAD) {
;	  stream->_flag |= _IOERR;
;	  stream->_cnt = 0;
;	  return(-1);
;     }
;
;     stream->_flag |= _IOWRT;
;     stream->_flag &= ~_IOEOF;
;     written = charcount = stream->_cnt = 0;
;
;     /* Get a buffer for this stream, if necessary. */
;     if (!anybuf2(stream,stream2)) {
;
;	  /* Do NOT get a buffer if (1) stream is stdout/stderr, and
;	     (2) stream is NOT a tty.
;	     [If stdout/stderr is a tty, we do NOT set up single char buffering.
;	     This is so that later temporary buffering will not be thwarted
;	     by the _IONBF bit being set (see _stbuf/_ftbuf usage).]
;	  */
; #ifdef  OS2
;	  if (!( ((stream==stdout) || (stream==stderr))
; #else
;	  if (!( ((stream==stdout) || (stream==stderr) || (stream==stdprn))
; #endif
;		  && (isatty(fh)) ))
;
;		      _getbuf(stream);
;
;	  } /* end !anybuf() */
;
;     /* If big buffer is assigned to stream... */
;     if (bigbuf2(stream,stream2)) {
;	  assert(stream->_ptr - stream->_base >= 0, "inconsistent IOB fields");
;
;	  charcount = stream->_ptr - stream->_base;
;	  stream->_ptr = stream->_base + 1;
;	  stream->_cnt = stream2->_bufsiz - 1;
;
;	  if (charcount > 0)
;	      written = _write(fh, stream->_base, charcount);
;	  else
;	      if (_osfile[fh] & FAPPEND)
;		  _lseek(fh,0L,SEEK_END);
;
;	  *stream->_base = ch;
;	  }
;
;     /* Perform single character output (either _IONBF or no buffering) */
;     else {
;	  charcount = 1;
;	  written = _write(fh, &ch, charcount);
;	  }
;
;     /* See if the write() was successful. */
;     if (written != charcount) {
;	  stream->_flag |= _IOERR;
;	  return(-1);
;	  }
;
;     return(ch & 0xff);
; }
;
;
;--- END OF C VERSION
;

;msdos.inc - MS-DOS definitions for C runtime
;----------------------------------------------
; __osfile flag values for DOS file handles
;
;FOPEN	 equ	01H		; file handle open
;FEOFLAG equ	02H		; end of file has been encountered
;FCRLF	 equ	04H		; CR-LF across read buffer (in text mode)
;FPIPE	 equ	08H		; file handle refers to a pipe
;FRDONLY equ	10H		; file handle associated with read only file
;FAPPEND equ	20H		; file handle opened O_APPEND
;FDEV	 equ	40H		; file handle refers to device
;FTEXT	 equ	80H		; file handle is in text mode

;; IBM PC-DOS 7.0 FDISK.COM (!unpacked!) segment 0 (code segment), Offset 7654h. 

;*******************************************************************************
;int _flsbuf(ch, stream) - flush buffer and output character.
;
;Purpose:
;	flush a buffer if this stream has one. if not, try to get one. put the
;	next output char (ch) into the buffer (or output it immediately if this
;	stream can't have a buffer). called only from putc. intended for use
;	only within library.
;
;	[NOTE 1: It is valid for this module to assign a value directly to
;	_flag2 instead of simply twiddling bits in the case where we are
;	initializing an i/o buffer.]
;
;	[NOTE 2: Multi-thread - It is assumed that the caller has aquired
;	the stream lock.]
;
;	[NOTE 3: The code depends on _iob[] and _iob2[] being near arrays of
;	the total size and element size.]
;
;Entry:
;	FILE *stream - stream to flish and write on
;	char ch - character to output.
;
;Exit:
;	returns -1 if FILE is actually a string, or if can't write ch to
;	unbuffered file, or if we flush a buffer but the number of chars
;	written doesn't agree with buffer size.  Otherwise returns ch.
;	all fields in FILE struct can be affected except _file.
;
;Uses:	ax, bx, cx, dx
;
;Exceptions:
;
;*******************************************************************************

; 14/12/2018 (no need to _flshbuf for FDISK2.COM)

;_flsbuf:
;
;	%define _c_	bp+4
;	%define _strm_	bp+6
;
;		push	bp
;		mov	bp,sp
;		push	si
;		push	di
;
;	; Set:
;	;	si = stream (= _iob entry)
;	;	al = stream->_flag
;
;		mov	si,[_strm_]
;		mov	al,[si+6]    ; [_strbuf_flag]
;
;	;**
;	; Check that either _IOWRT or _IORW is set, and _IOSTRG is not set.
;
;		test	al,82h ; _IOWRT OR _IORW 
;		jz	short flsbuf_4 ; reterror
;		test	al,40h ; _IOSTRG
;		jnz	short flsbuf_4 ; reterorr
;;**
;; Set the _cnt field to 0. This isn't need in the case of a 'big' buffer and
;; is overwritten in that case. However, it is needed in all other cases and
;; this is the cheapest place to do it.
;
;		mov	word [si+2],0 ; [si]._cnt ; reset _cnt field to 0
;;**
;; Check that _IOREAD is not set or, if it is, then so is _IOEOF. Note that
;; _IOREAD and IOEOF both being set implies switching from read to write at
;; end-of-file, which is allowed by ANSI. Note that resetting the _cnt and
;; _ptr fields amounts to doing an fflush() on the stream in this case. Note
;; also that the _cnt field has to be reset to 0 for the error path as well
;; (i.e., _IOREAD set but _IOEOF not set) as well as the non-error path.
;
;		test	al,1	; _IOREAD
;		jz	short flsbuf_1 ; set_flag
;		test	al,10h	; _IOEOF ; ; at end-of-file?
;		jz	short flsbuf_4 ; reterror ; no, go do error return
;		mov	cx,[si+4]      ; [si]._base
;				       ; reset _ptr field to _base field
;		mov	[si],cx	;[si]._ptr 
;
;		and	al,~1 ; NOT _IOREAD ; clear _IOREAD bit
;flsbuf_1:
;		;**
;		; Set _IOWRT and clear _IOEOF
;;set_flag:
;		or	al,2	; _IOWRT
;		and	al,~10h ; NOT _IOEOF
;		mov	[si+6],al ; [si]._flag
;	;**
;	; Set:
;	;	di = _iob2 entry (aka stream2)
;	;	bx = stream->_file (= file handle)
;
;		mov	di,si
;		;sub	di,STDIN ; _iob
;		sub	di,_iob	; 07/12/2018
;		add	di,_iob2	; di = stream2 corresponding to stream
;		xor	bx,bx
;		mov	bl,[si+7] ; [si]._file	; bx = file handle for stream
;	;**
;	; Test the buffering flags and branch accordingly
;
;		test	al,8 ; _IOMYBUF
;		jnz	short flsbuf_6 ; bigbuf
;		test	al,4 ; _IONBF
;		jnz	short flsbuf_3 ; singlechar
;
;		test	byte [di],1 ; test [di]._flag2,_IOYOURBUF
;		jnz	short flsbuf_6 ; bigbuf
;	;**
;	; No buffering is in place at all. Check to see if the stream is stdout,
;	; stderr or, in DOS only, stdprn. If it is and if it is attached to a device,
;	; go do single character output. Otherwise, go try to buffer it.
;
;		cmp	si,STDOUT
;		je	short flsbuf_2	; testdev
;		cmp	si,STDERR
;		je	short flsbuf_2	; testdev
;		cmp	si,STDPRN
;		jne	short flsbuf_5	; dogetbuf
;flsbuf_2:
;;testdev:
;		;test	byte ptr [bx + dataOFFSET _osfile],FDEV
;		test	byte [bx+_osfile],40h ; FDEV
;		jz	short flsbuf_5	; dogetbuf
;flsbuf_3:
;;try_again:	;if (iop->_flag&_IONBF) {
;		;	c1 = c;
;		;	rn = 1;
;		;	n = write(fileno(iop), &c1, rn);
;		;	iop->_cnt = 0;
;	;**
;	; Single character output (either _IONBF or no buffering at all).
;singlechar:
;		mov	cx,1	 ; rn
;		push	cx
;		lea	di,[_c_] ; &c1 ; [char] ; ss:di = address of char
;		push	di
;		push	bx	 ; fileno(iop)
;		call	_write	 ; write(handle,&char,1)
;		add	sp,6
;		mov	cx,1	 ; rn	; set cx = 1 = number of chars...
;			; ax = n
;		jmp	short flsbuf_8  ; doret
;					; ...that should have been written
;flsbuf_4:
;	;**
;	; Set up a return of -1 to indicate that an error has occurred and jump
;	; to done. Set the error flag on the stream.
;;reterorr:
;		mov	ax,-1	; return -1 to indicate error
;		;or	[si]._flag,_IOERR ; set error flag
;		or	byte [si+6],20h ; iop->_flag |= _IOERR
;		jmp	short flsbuf_10	; done ; return(EOF) 
;flsbuf_5:
;	;**
;	; The stream is unbuffered, try to buffer it. Then, check the buffering
;	; flags again and branch accordingly.
;;dogetbuf:
;		push	bx		; save file handle
;		;push	si	; 09/12/2018
;		call	_getbuf 	; _getbuf(stream)
;		;pop	bx		; clean off arg
;		pop	bx		; restore file handle
;
;		;test	[si]._flag,_IOMYBUF ; did we get a 'big' buffer?
;		;jz	short singlechar    ; no, single char buffering
;
;		test	byte [si+6],8	; _IOMYBUF
;		jz	short flsbuf_3	; try_again
;flsbuf_6:
;	;**
;	; The stream has a 'big' buffer. Empty it with a write().
;; bigbuf:
;		mov	cx,[si]   ; [si]._ptr
;		mov	dx,[si+4] ; [si]._base	
;		sub	cx,dx	  ; cx = number of chars in stream buffer
;		inc	dx
;		mov	[si],dx	  ; [si]._ptr ; set _ptr to _base + 1
;		mov	dx,[di+2] ; [di]._bufsiz 	
;		dec	dx		
;		mov	[si+2],	dx ; [si]._cnt ; set _cnt to _bufsiz - 1
;		jcxz	flsbuf_9 ; dolseek ; no chars in buffer to write
;
;		push	cx	; save count
;
;		push	cx	; push args
;		push	word [si+4] ; [si]._base
;		push	bx
;		call	_write
;		add	sp,6	; clean off args
;
;		pop	cx	; restore count
;flsbuf_7:
;		;**
;		; Place 'char' in the stream buffer
;;bufchar:
;		mov	di,[si+4] ; [si]._base
;		mov	dx,[_c_]  ; [char]
;		mov	[di],dl
;flsbuf_8:
;		;if (rn != n) {
;		;	iop->_flag |= _IOERR;
;		;	return(EOF);
;		;}
;		;return(c);
;	;**
;	; Test the results of the call to write() (i.e., compare ax and cx). If
;	; successful, return char. Otherwise, return -1.
;
;		cmp	ax,cx ; ax = n, cx = rn
;		jne	short flsbuf_4  ; != ; reterror
;
;		;return(c);	
;		xor	ax,ax
;		mov	al,[_c_] ; [char]
;		jmp	short flsbuf_10 ; done
;flsbuf_9:
;	;**
;	; There are no characters in the stream buffer. If the FAPPEND bit is set
;	; in the _osfile entry, position the file pointer at the end of the file.
;;dolseek:
;		xor	ax,ax		; needed for both branchings below
;		;test	byte ptr [bx + dataOFFSET _osfile],FAPPEND
;		test	byte [bx+_osfile],20h
;		jz	short flsbuf_7 ; bufchar
;		
;		mov	cx,2	; SEEK_END
;		push	cx		; push args
;		push	ax		; note that ax is 0
;		push	ax
;		push	bx
;		call	_lseek		; _lseek(handle,0L,SEEK_END)
;		add	sp,8
;		xor	ax,ax
;		mov	cx,ax		; set ax = cx = 0
;		;jmp	short bufchar
;		jmp	short flsbuf_7
;flsbuf_10:
;;done:
;		pop	di
;		pop	si
;		pop	bp
;		retn

; OUTPUT.ASM (VCCRT2.ZIP) - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; Microsoft(R) Visual C++ Version 1.0 Run-Time Library Sources (1993)
;
; Downloaded From : The Programmer's Corner (www.pcorner.com) - 01/12/2018 -

; 06/12/2018

;***
;output.asm - formatted output for printf, etc.
;
;	Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
;
;Purpose:
;	defines _output() for formatted output by *printf.
;	if CPRFLAG is defined, defines cprintf instead.
;
;******************************************************************************

; size of conversion buffer (ANSI-specified minimum is 509)
BUFSIZE 	equ	512		; size of buffer for conversions

; flag definitions for flag 1
FL_SIGN 	equ	01h		; put plus/minus sign in front
FL_SIGNSP	equ	02h		; put space/minus sign in front
FL_LEFT 	equ	04h		; left justify
FL_LEADZERO	equ	08h		; pad with leading zeros
FL_LONG 	equ	10h		; long value given (def: short)
FL_FAR		equ	20h		; far pointer given (def: model dep.)
FL_SIGNED	equ	40h		; signed data given (def: unsigned)
FL_ALTERNATE	equ	80h		; alternate form requested

; flag definitions for flag 2
FL_NEGATIVE	equ	01h		; value is negative
FL_FORCEOCTAL	equ	02h		; force 0 in front (for octals only)
FL_LONGDOUBLE	equ	04h		; long double value given
FL_SHORT	equ	08h		; short value given
FL_NEAR 	equ	10h		; near ptr given (useful only for %p)

; possible state values
ST_NORMAL	equ	0		; normal state -- just output char
ST_PERCENT	equ	1		; just read percent sign
ST_FLAG 	equ	2		; just read flag character
ST_WIDTH	equ	3		; just read width specification char
ST_DOT		equ	4		; just read dot
ST_PRECIS	equ	5		; just read precision spec. char
ST_SIZE 	equ	6		; just read size specification char
ST_TYPE 	equ	7		; just read type specification

; define character type values
CH_OTHER	equ	0		; character with no special meaning
CH_PERCENT	equ	1		; '%'
CH_DOT		equ	2		; '.'
CH_STAR 	equ	3		; '*'
CH_ZERO 	equ	4		; '0'
CH_DIGIT	equ	5		; '1'..'9'
CH_FLAG 	equ	6		; ' ', '+', '-', '#'
CH_SIZE 	equ	7		; 'h', 'l', 'L', 'N', 'F'
CH_TYPE 	equ	8		; type specification character

;*******************************************************************************
;int _output(stream, format, argptr) - formatted output (used internally only)
;
;Purpose:
;	_output performs printf-style output onto a stream.  It is called
;	by printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to do the
;	dirty work.  In multi-thread situations, _output assumes that
;	the given stream is already locked.
;
;	Algorithm:
;	   The format string is parsed by using a finite-state machine
;	   based on the current state and the current character read
;	   from the format string.  Thus, looping is on a per-character
;	   basis, not a per conversion specifier basis.  Once the format
;	   specifying character is read, output is performed.
;
;Entry:
;	FILE *stream	-    stream for output
;	char *format	-    printf-style format string
;	void *argptr	-    pointer to the list of subsidiary arguments
;
;Exit:
;	If no output error occurs, returns the number of characters written
;	If an I/O error occurs, -1 is returned.
;
;Uses:
;	Performs I/O on the given stream by using the assembly
;	equivalent of getc/_getc_lk macros.
;
;*******************************************************************************

;jump table based on current state
jumptable:	dw normal_state
		dw percent_state
		dw flag_state
		dw width_state
		dw dot_state
		dw precis_state
		dw size_state
		dw type_state

;cProc	output, <NEAR>, <>	      ; static, near routine
;        parmDP  format
;    ifdef _WINDOWS
;        parmD   arglist
;    else
;        parmDP  arglist
;    endif
;
;else		; defining normal _output routine
;
;cProc	_output, <PUBLIC>, <>
;	parmDP	stream
;	parmDP	format
;	parmDP  arglist
;
;endif ;CPRFLAG
;
;; define local variables manually (ick!) -- because we need stack checking
;
;ifdef _WINDOWS
;    if    sizeC
;	BASE equ <(bp-2)>
;    else
;	BASE equ <bp>
;    endif ;sizeC
;else
;	BASE equ <bp>
;endif ;_WINDOWS
;
;hexadd		equ	byte ptr [BASE-1]	  ; offset to add when hex converting
;char		equ	byte ptr [BASE-2]	  ; character just read
;flags		equ	word ptr [BASE-4]	  ; flag word (byte equates below)
;flags2		equ	byte ptr [BASE-3]	  ; flag byte 2
;flags1		equ	byte ptr [BASE-4]	  ; flag byte 1
;state		equ	byte ptr [BASE-5]	  ; state we're in
;radix		equ	byte ptr [BASE-6]	  ; radix to convert by
;charsout	equ	word ptr [BASE-8]	  ; chars written so far
;fldwidth	equ	word ptr [BASE-10]	  ; selected width
;precision	equ	word ptr [BASE-12]	  ; selected precision
;prefix		equ	byte ptr [BASE-14]	  ; up to two-byte prefix
;prfxlen 	equ	word ptr [BASE-16]	  ; length of prefix
;capexp		equ	word ptr [BASE-18]	  ; capital exponent?
;buffer		equ	byte ptr [BASE-20-BUFSIZE]; buffer for conversions
;
;LOCALDATSIZE	equ	20+BUFSIZE	; amount of local data
;
; begin procedure
;
;cBegin _output

LOCALDATSIZE	equ	20+BUFSIZE	; Visual C++ Version 1.0 Run-Time Library
					; OUTPUT.ASM

; IBM PC-DOS 7.0 FDISK.COM Segment 0 (Code Segment), Offset 7744h

_output:

	;%define output_buff bp-369	; IBM PC-DOS 7.0 FDISK.COM
	%define output_buff  bp-532	; Visual C++ Version 1.0 Run-Time Library
					; OUTPUT.ASM
	%define capexp	  bp-18
	%define prfxlen   bp-16
	%define prefix	  bp-14
	%define precision bp-12
	%define fldwidth  bp-10
	%define charsout  bp-8
	%define radix	  bp-6
	%define state	  bp-5
	%define flags	  bp-4
	%define char	  bp-2
	%define hexadd	  bp-1

	;%define stream	  bp+4	
	;%define format	  bp+6
	;%define arglist  bp+8

	; 13/12/2018
	%define format	bp+4
	%define arglist	bp+6
	
		push	bp
		mov	bp,sp
		
		;mov	ax,369 ; PC-DOS 7.0 FDISK.COM
		mov	ax,LOCALDATSIZE ; 532
		call	_chkstk		; allocate local data
		
		push	si
		push	di
		xor	ax,ax ; 0
		mov	[charsout],ax	; charsout = 0
		mov	[state],al	; state = 0

		; beginning of main loop	
loopagain:

;if sizeD
;	les	si, format
;	lods	byte ptr es:[si]
;else
;	mov	si, format
;	lodsb
;endif
		mov	si,[format]
		lodsb
		mov	[format],si
		mov	[char],al	; char = *format++
		or	al,al		; char == '\0'?
		jz	short output_done ; yes - end loop
		cmp	word [charsout],0 ; charsout < 0
		jge	short output_loopok ; no - don't end loop
output_done:
		mov	ax,[charsout]	; return chars written
		jmp	output_return

output_loopok:
		mov	bx,lookuptable	; bx points to lookup table
		sub	al,' ' ; 20h	; al = char - ' '
		cmp	al,'X'		; beyond end of table?
		ja	short output_main1 ; yes, make it other char
		xlat			; al = lookuptable[al]
		and	al,0Fh		; keep low nybble -- al has char class
		jmp	short output_main2

output_main1:
		mov	al,0  ; CH_OTHER ; not in table, must be other
output_main2:
		mov	cl,3
		shl	al,cl		; al *= 8
		add	al,[state]	; al += state
		xlat			; al = lookuptable[al]
		inc	cl		; cl = 4
		shr	al,cl		; al >>= 4
		mov	[state],al	; save new state	
		cbw			; zero ah (al < 80h)
	
	; ax now has the state # (recall ah = 0) -- now we
	; use this to index into a jump table and go to
	; correct code for the current state

		mov	bx,ax
		shl	bx,1		; index words (bx = state #)
		;jmp	jumptable[bx]
		;jmp	far [cs:bx+jumptable]
		jmp	word [bx+jumptable] ; jump to correct state code

normal_state:
		; normal state - just output the character involved
		mov	dl,[char]
		mov	cx,1
		call	outpad
		jmp	short loopagain

percent_state:
		; just read the percent character
		xor	ax,ax ; 0
		mov	[prfxlen],ax	; prfxlen = 0
		mov	[fldwidth],ax	; fldwidth = 0
		mov	[capexp],ax	; capexp = 0
;if sizeD
;	mov	flags, FL_FAR		; large data -- default far ptrs
;else
;	mov	flags, ax		; small data -- default near ptrs
;endif
		mov	[flags],ax	; flags = 0
		dec	ax
		mov	[precision],ax	; precision = -1 (default)
		jmp	short loopagain	; end of state code

flag_state:
		; just read a flag, so set the flag bits accordingly
		mov	al,[char]
		cmp	al,'-'
		jne	short fl1
doprnt_case_minus:
		;or	flags1,FL_LEFT
		or	byte [flags],4	; FL_LEFT
					; char=='-' => left justify
		jmp	short loopagain
fl1:
		cmp	al,'+'
		jne	short fl2	
doprnt_case_plus:
		;or	flags1,FL_SIGN
		or	byte [flags],1	; FL_SIGN
					; char=='+' => force sign indicator
		jmp	short loopagain
fl2:
		cmp	al,' '		; FL_SIGNSP 
		jnz	short fl3
doprnt_case_space:
		;or	flags1,FL_SIGNSP
		or	byte [flags],2	; char==' ' => as above, 
					; but space not +
		jmp	loopagain	; end of state
fl3:
		cmp	al,'#'		 
		jnz	short fl4
doprnt_case_sharp:
		;or	flags1,FL_ALTERNATE
		or	byte [flags],80h ; FL_ALTERNATE 
					; char=='#' => alternate form
		jmp	loopagain
fl4:
		;or	flags1,FL_LEADZERO
		or	byte [flags],8	; FL_LEADZERO
		jmp	loopagain	; char=='0' => pade with leading zeros
width_state:
		; just read a width specifier -- set width value
		mov	cl,[char]
		cmp	cl,'*'		; char == '*'
		jne	short widthdigit ; no - must be a digit
		; char == '*' means get width from argument list	
		call	getwordarg	; AX = word argument	
		or	ax,ax		; ax < 0
		jns	short storewidth ; no - do normal
		neg	ax		; ANSI: neg width means - flags
		;or	flags1, FL_LEFT
		or	byte [flags],4	;FL_LEFT ; and positive width
		jmp	short storewidth
widthdigit:
		; we just read a digit to add to the stored width value
		sub	cl,'0'
		xor	ch,ch		; dx = value of digit
		mov	ax,[fldwidth]
		mov	bx,10
		mul	bx
		add	ax,cx		; fldwidth = 10*fldwidth + (digit-'0')
storewidth:
		mov	[fldwidth],ax
		jmp	loopagain

dot_state:
		; We just read the dot -- char must == '.'
		; and all we need to do is zero the precision.
		mov	word [precision],0	; zero precision, no longer default
		jmp	loopagain

precis_state:
		; just read a precision specifier -- set precision value
		mov	cl,[char]
		cmp	cl,'*'		; char == '*'
		jne	short precisdigit ; no - must be a digit
		; char == '*' means get precision from argument list
		call	getwordarg	; AX = word argument
		or	ax,ax		; ax < 0
		jns	short storeprecis ; no - do normal
		mov	ax,0FFFFh ; -1	; ANSI: neg precis. means default value	
		jmp	short storeprecis

precisdigit:
		; we just read a digit to add to the stored precision value
		sub	cl,'0'
		xor	ch,ch
		mov	ax,[precision]
		mov	bx,10
		mul	bx
		add	ax,cx	; precision = 10*precision + (digit-'0')
storeprecis:
		mov	[precision],ax	; store precision
		jmp	loopagain

size_state:
		; just read a size specifier -- set the flags based on it
		mov	al,[char]
		cmp	al,'l'
		jne	short sz1
		;or	byte [flags1],FL_LONG
		or	byte [flags],10h ; FL_LONG
				; char=='l' or 'L' => long value given
		jmp	short szret
sz1:
		cmp	al,'F'		
		jne	short sz2
		;or 	byte [flags1],FL_FAR
		or	byte [flags],20h ; FL_FAR
					; char=='F' => far ptr given
		jmp	short szret
sz2:
		cmp	al,'N'
		jnz	short sz3
		;or	byte [flags2],FL_NEAR
		or	byte [flags+1],10h ; FL_NEAR
					; char=='N' => near ptr given	
		jmp	short szret
sz3:
		cmp	al,'L'
		jnz	short sz4
		;or	byte [flags2],FL_LONGDOUBLE
		or	byte [flags+1],4 ; FL_LONGDOUBLE
					; char=='L' => long double given	
		jmp	short szret
sz4:
		; at this point we must have h given
		;or	byte [flags2], FL_SHORT
		or	byte [flags+1],8 ; FL_SHORT
szret:					; char=='h' => short value given
		jmp	loopagain

type_state:
	; OK, we just read the type specifier character, so we now actually
	; have to format and 'print' the output. We do this with the
	; equivalent of a big switch statement to routines that formats the
	; correct input and set ES:DI to point to the text to print
	; and CX to the length of this output. Common code later on
	; then takes care of right/left justifying it. Note that many of
	; the cases share code; in particular all integer formatting is
	; done in one place.

		mov	al,[char]
		cmp	al,'d'
		jne	short t1
		;jmp	doprnt_case_i_d
		jmp	type_d
t1:
		cmp	al,'i'
		jne	short t2
		;jmp	doprnt_case_i_d
		jmp	type_i
t2:
		cmp	al,'u'
		jne	short t3
		jmp	type_u
t3:
		cmp	al,'X'
		jne	short t4
		jmp	type_bigx
t4:
		cmp	al,'x'
		jne	short t5
		jmp	type_x
t5:
		cmp	al,'o'
		jne	short t6
		jmp	type_o
t6:
		cmp	al,'c'
		je	short type_c
		cmp	al,'s'
		je	short type_s
		cmp	al,'n'
		je	short type_n
		cmp	al,'p'
		je	short type_p
		cmp	al,'E'
		je	short bigeg
		cmp	al,'G'
		je	short bigeg

	; only possible remaining type is 'e', 'f', 'g' -- go to it
		jmp	type_efg	;'e', 'f', 'g' same destination	
bigeg:
		jmp	type_bigeg

	; Now we do case by case output formatting
type_c:
		; character output
		call	getwordarg	; AX = word argument
		;lea	di,[bp-369] ;  PC-DOS 7.0 FDISK.COM
		lea	di,[output_buff]
		push	ss
		pop	es		; es:di points to buffer	
		stosb
		dec	di		; mov es:[di],al
		mov	cx,1		; length of 1
		jmp	justify		; goto general justify/output
type_s:
	; string output -- must handle both far and near
	; we have to know how much of the string to print -- rule is
	; all of it if precision is default, min(precision, length) if
	; precision given. We do it simply as one computation here
	; because default precision stored as -1, which we treat
	; as 65535, the longest possible string length.
	; a null ptr is printed as '(null)'

		call	getptrarg	; read pointer into es:di
		or	di,di		; di == 0?
		jnz	short s2	; no - a normal string	
		mov	ax,es
		or	ax,ax		; es == 0?
		jnz	short s2	; no - a normal string	

		push	ds
		pop	es
		mov	di,nullstring ;	"(null)"  ; es:di points to '(null)'
		mov	cx,[nullstrlen]	; cx has the length
		jmp	justify		; go to justify routine
s2:
		push	di		; save di
		mov	cx,[precision]	; how much of string to scan
		jcxz	s3		; precision == 0; print nothing
		xor	al,al		; scan for '\0'
		repne scasb		; scan string - zero flag set if found
		jnz	short s3	; no - we scanned exactly precision bytes	
		dec	di		; yes - point to the null byte
s3:
		; di now points just beyond last byte to print
		pop	cx		; cx has old di
		sub	di,cx		; di has count of bytes
		xchg	cx,di		; di restored, cx has count of bytes
		jmp	justify		; goto justify/output
type_n:
		; store count of characters written so far into int/long
		; pointed to by pointer argument.
		; NOTHING IS OUTPUT

		call	getptrarg	; read ptr into es:di
		mov	ax,[charsout]	; ax = number of characters written
		stosw
		;test	byte [flags1],FL_LONG
		test	byte [flags],10h ; FL_LONG ; a long value?
		jz	short n1	; no - just a short
		xor	ax,ax		; clear ax
		stosw			; store high word (0)
n1:
		jmp	loopagain	; skip output, go straight to loop top
type_p:
		; write a pointer -- this is complicated by the fact that
		; the pointer could be 2 bytes or 4 bytes on the stack,
		; and that we can output in seg:off or off form.

		;test	byte [flags1],FL_FAR | FL_LONG
		test	byte [flags],30h ; FL_FAR | FL_LONG
		jnz	short p4byte	; 4 or 2 bytes on stack?	
		call	getwordarg	; get 2 byte ptr in AX
		jmp	short pshortfmt	; read 2 bytes implies short format
p4byte:
		call	getlongarg	; get 4 byte ptr into DX:AX

		;test	byte [flags2],FL_SHORT| FL_NEAR
		test	byte [flags+1],18h ; specified short format?
		jnz	short pshortfmt	; yes - goto short format

		; output xxxx:yyyy

		;mov byte [heaxadd], 'A' - '9' - 1
		mov	byte [hexadd],7 ; use uppercase hex	
		mov	cx,16		; radix 16
		push	ss
		pop	es		; es point to segment with buffer
		push	dx		; save segment
		xor	dx,dx		; no high word
		;lea	di,[bp-361]	; IBM PC-DOS 7.0 FDISK.COM
		;lea	di,buffer[8]	; point to end of offset spot in buffer
		lea	di,[output_buff+8]
		mov	si,4		; 4 digit output
		call	convert		; convert and place in buffer

		mov	cx,16		; radix 16 again
		;lea	di,[bp-366]	; IBM PC-DOS 7.0 FDISK.COM
		;lea	di,buffer[3]	; point to end of segment spot in buffer
		lea	di,[output_buff+3]
		pop	ax		; ax has segment
		xor	dx,dx		; no high word
		mov	si,4		; 4 digit output again
		call	convert		; convert again

		;mov	byte [bp-365],':'
		;mov	buffer[4], ':'	; put colon in middle
		mov	byte [output_buff+4],':'
		mov	cx,9		; 9 character output
		jmp	short p1	; skip near ptr code	
pshortfmt:
		;  output xxxx:yyyy

		;mov	byte [hexadd],'A' - '9' - 1 ; use uppercase hex
		mov	byte [hexadd],7
		mov	cx,16		; radix 16
		push	ss
		pop	es		; es point to segment with buffer
		xor	dx,dx		; no high word
		;lea	di,[bp-366]
		;lea	di,buffer[3]	
		lea	di,[output_buff+3] ; point to end of 4 byte buffer
		mov	si,4		; 4 character output format
		call	convert		; convert it into buffer
		mov	cx,4		; 4 character text length
p1:
		;lea	di,[bp+369]
		;lea	di, buffer	; di points to buffer, cx has length
		lea	di,[output_buff]
		jmp	justify		; justify and output
type_bigeg:
		;inc	word [capexp]	; capitalize exponent
		inc	byte [capexp]
type_efg:
		; floating point conversion -- this is relatively easy
		; because cfltcvt does the work for us

		;or	flags1, FL_SIGNED ; this is a signed conversion
		or	byte [flags],40h
		mov	al,[char]
		or	al,20h		; convert to lower case
		cbw			; ax has format char is lower case
		mov	si,ax
		cmp	word [precision],0
		jg	short f2	; precision > 0, no adjustment	
		je	short f1	; precision = 0
		mov	word [precision],6 ; precision < 0, make it 6 (default)
		jmp	short f2
f1:
		;cmp	ax,'g'
		cmp	al,'g'
		jne	short f2
		mov	word [precision],1
f2:
		;lea	di,[bp+369]	; PC--DOS 7.0 FDISK.COM
		;lea	di,buffer	; ss:di points to buffer
		lea	di,[output_buff]

		push	word [capexp]
		push	word [precision]

		push	si		; si has format character
;if sizeD
;	push	ss
;else
;ifdef _WINDOWS			; buffer in ss
;	push	ss
;endif
;endif
		push	di		; push pointer to buffer
;
;if sizeD
;	push	word ptr (arglist[2])
;else
;ifdef _WINDOWS			; args in ss
;	push	ss
;endif
;endif
		push	word [arglist]	; push arglist

		;test	flags2,FL_LONGDOUBLE
		test	byte [flags+1],4 ; FL_LONGDOUBLE
		jz	short f3
		;call	_cldcvt
		; 14/12/2018
		call	word [_cldcvt]	; do long double conversion
		add	word [arglist],10  ; go to next argument 
					   ; (long double is 10 bytes)
		jmp	short f4
f3:
		;call	_cfltcvt
		; 14/12/2018
		call	word [_cfltcvt]	; do float conversion	
		add	word [arglist],8 ; go to next argument 
					; (double is 8 bytes)
f4:
;if sizeD
;	add	sp, 14
;else
;ifdef _WINDOWS
;	add	sp, 14
;else
		add	sp,10		; pop arguments
;endif
		;test	flags1,FL_ALTERNATE	; alternate form?
		test	byte [flags],80h ; FL_ALTERNATE
		jz	short f5
		cmp	word [precision],0 ; precision == 0?
		jne	short f5	; no - skip decimal forcing
	
	; '#' flag and precision == 0 => need to stick in a decimal point
;if sizeD
;	push	ss
;else
;	ifdef _WINDOWS
;		push	ss
;	endif
;endif
		push	di		; push pointer to buffer
		;call	_forcdecpt	; force decimal point
		; 14/12/2018
		call	word [_forcdecpt]
;if sizeD
;	add	sp, 4
;else
;	ifdef _WINDOWS
;		add	sp, 4
;	else
		add	sp,2		; restore stack
;	endif				
;endif

f5:
		cmp	si,'g'		; g format?
		jne	short f6	; no - skip zero cropping
		
		;test	flags,FL_ALTERNATE ; '#' given
		test	word [flags],80h
		jnz	short f6	; yes - skip zero cropping

		; 'g' format and no '#' flag => crop trailing zeros
;if sizeD
;	push	ss
;else
;	ifdef _WINDOWS
;		push	ss
;	endif
;endif
		push	di		; push pointer to buffer
		;call	_cropzeros ; crop zeros if g fmt and not alternate form
		; 14/12/2018
		call	word [_cropzeros]
;if sizeD
;	add	sp, 4
;else
;	ifdef _WINDOWS
;		add	sp, 4
;	else
		add	sp,2
;	endif
;endif					; restore stack

f6:
		push	ss
		pop	es		; es:di points to text to output
		cmp	byte [es:di], '-' ; are we negative?
		jne	short f7	; no -- skip it
		inc	di		; go beyond negative sign
		;or	flags2,FL_NEGATIVE ; record negative number
		or	byte [flags+1],1
f7:
		; now we must find length of buffer to output
		mov	cx,0FFFFh
		push	di
		mov	al,0		; scan for null byte
		repne scasb	; do the scan -- now di point just after null byte
		dec	di		; di points to null byte
		pop	cx		; cx has old di
		sub	di,cx		; di has length of string
		xchg	cx,di		; cx has length, di restored
		jmp	justify		; done -- justify/output it
type_d:		
		;'d' and 'i' and synonymns
doprnt_case_i_d:
type_i:		; signed decimal output
		;or	flags1, FL_SIGNED
		or	byte [flags],40h
type_u:	
		; unsigned decimal output
		mov	byte [radix],10
		jmp	short int_out	; go to common int formatting
type_bigx:
		; unsigned hex output, with ABCDEF
		;mov	hexadd,'A' - '9' - 1	; hex conversion constant, uppercase
		mov	byte [hexadd],7
		jmp	short dohex
type_x:
		; unsigned hex output, with abcdef
		;mov	hexadd,'a' - '9' - 1	; hex conversion constant, lowercase
		mov	byte [hexadd],27h

dohex:		
		;test	flags1,FL_ALTERNATE ; alternate form?
		test	byte [flags],80h
		jz	short hex1		; no -- skip alternate formatting
		mov	word [prfxlen],2	; yes, store 2-byte hex prefix
		mov	byte [prefix],'0'
		;mov	dl,'x'-'a'+'9'+1
		mov	dl,51h
		add	dl,[hexadd]
		mov	byte [prefix+1],dl	; byte 2: 'x' or 'X' as appropriate
hex1:
		mov	byte [radix],16
		jmp	short int_out
type_o:
		; unsigned octal output
		;test	flags1,FL_ALTERNATE	; alternate form?
		test	byte [flags],80h
		jz	short oct1		; no - skip alternate formatting
		;or	flags2,FL_FORCEOCTAL	; force leading zero
		or	byte [flags+1],2
oct1:
		mov	byte [radix],8

int_out:
	; Here is the common integer formatting routine.
	; Note that shorts and ints are the same, so we ignore FL_SHORT

; 1.  Read argument from arglist; if a word, extend into long as appropriate
		;test	flags1,FL_LONG		; read long word?
		test	byte [flags],10h
		jz	short int1		; no - read short word
		call	getlongarg		; read long word into dx:ax
		jmp	short int3
int1:
		call	getwordarg		; read short word into ax
		;test	flags1,FL_SIGNED	; signed argument?
		test	byte [flags],40h
		jz	short int2		; no - goto zeroextend
		cwd				; sign extend ax -> dx:ax
		jmp	short int3
int2:
		xor	dx, dx

; 2.  If signed and negative, make it positive and remember the negative sign
int3:
		;test	flags1,FL_SIGNED	; signed argument?
		test	byte [flags],40h
		jz	short int4		; no - skip this
		or	dx,dx			; dx:ax < 0?
		jge	short int4		; no - skip this
		;or	flags2,FL_NEGATIVE	; remember negative sign
		or	byte [flags+1],1
		neg	ax
		adc	dx, 0
		neg	dx			; dx:ax = -dx:ax

; 3.  Check the precision value for default; non-default turns off 0 flag (ANSI)
int4:
		cmp	word [precision],0	; precision < 0 (default)
		jge	short int5		; no - go turn off zero flag
		mov	word [precision],1	; default precision = 1
		jmp	short int6		; don't turn off zero flag
int5:
		;and	flags1, (NOT FL_LEADZERO) AND 0FFh ; (~FL_LEADZERO) & 0FFh
		and	byte [flags],0F7h ; turn off zero flags when explicit precision

; 4.  Check if data is zero, if so, turn off hex prefix
int6:
		mov	bx,ax
		or	bx,dx			; dx:ax == 0?
		jnz	short int7		; no - skip this
		mov	word [prfxlen],0	; kill hex prefix for zero data

; 5.  Convert data into ASCII characters
int7:
		;lea	di,[bp-21]	 ; IBM PC-DOS 7.0 FDISK.COM
		;lea	di,buffer[BUFSIZE-1]
		lea	di,[output_buff+BUFSIZE-1] ; [output_buf+511] = [bp-(532-511)]
		push	ss
		pop	es			; es:di points at end of buffer
		mov	cl,[radix]
		xor	ch,ch			; cx = radix
		mov	si,[precision]		; si = precision
		call	convert			; Convert that sucker:
						; cx has length, es:di points to digits
; 6.  Force a leading 0 if FL_FORCEOCTAL set
		;test	flags2,FL_FORCEOCTAL	; FORCEOCTAL flags set?
		test	byte  [flags+1],2
		jz	short int8		; nope - don't do it
		jcxz	addzero			; if printing no digits, add a zero
		cmp	byte [es:di],'0'	; first digit already a 0?
		je	short int8		; yep - don't do it
addzero:
		dec	di			; move back a digit
		mov	byte [es:di],'0'	; add in a zero
		inc	cx			; increase number of bytes displayed
; 7.  Jump to general justify/output procedure
int8:
		;;jmp	short $+2
		;jmp	short justify

justify:
; here we justify and output the results

; Find any prefix that we need to stick on -- note that hex prefixes
; have already been done.

		mov	ax,1 ; 07/12/2018

		;test	flags1,FL_SIGNED	; is this a signed conversion?	
		test	byte [flags],40h
		jz	short just3		; if not, no sign prefix
		;test	flags2,FL_NEGATIVE	; a negative number?
		;test	byte [flags+1],1
		test	[flags+1],al ; 1
		jz	short just1		; no - skip
		mov	byte [prefix], '-'	; prefix is '-'
		;mov	word [prfxlen],1	; prefix length = 1
		mov	[prfxlen],ax
		jmp	short just3
just1:
		;test	flags1,FL_SIGN		; forcing sign?
		;test	byte [flags],1
		test	[flags],al ; 1
		jz	short just2
		;mov	prefix[0],'+'		; prefix is '+' (can't be negative)
		mov	byte [prefix],'+'
		;mov	word [prfxlen],1	; prefix length = 1
		mov	[prfxlen],ax
		jmp	short just3		; skip next test ('+' overrides ' ')
just2:
		;test	flags1,FL_SIGNSP	; forcing sign with blank?
		test	byte [flags],2
		jz	short just3
		;mov	prefix[0],' '		; prefix is ' ' (can't be negative)
		mov	byte [prefix],' '
		;mov	word [prfxlen],1	; prefix length = 1
		mov	[prfxlen],ax
just3:
		mov	ax,[fldwidth]		; subtract length of text
		sub	ax,cx			; ax = width - textlen - prfxlen
		sub	ax,[prfxlen]
		jge	short just4		; ax < 0? skip next
		xor	ax,ax			; yes - ax = 0

; ax now has amount of padding, it's just a question of where to put it
; es:di points to output string, cx is length

just4:
		push	es
		push	di
		push	cx			; save these for now...

		;test	flags1,FL_LEFT OR FL_LEADZERO ; left justify or lead zero?
		test	byte [flags],0Ch ; FL_LEFT | FL_LEADZERO
		jnz	short just5
		mov	cx,ax
		mov	dl,' '
		call	outpad
just5:
		push	ax			; save pad count
		push	ss
		pop	es
		lea	di,[prefix]		; es:di points to prefix
		mov	cx,[prfxlen]		; length of prefix
		call	outch			; write prefix
		pop	ax			; recover pad count

		;test	flags1,FL_LEADZERO	; use leading zeros?
		test	byte [flags],8
		jz	short just6		; no - don't put padding now
		;test	flags1,FL_LEFT		; left justifying?
		test	byte [flags],4
		jnz	short just6		; yes - skip ('-' overrides '0')

		mov	cx,ax			; amount of padding
		mov	dl,'0'			; pad with zeros
		call	outpad			; write the zero padding
just6:
		pop	cx	
		pop	di
		pop	es			; recover pointer to text

		push	ax			; save pad count
		call	outch			; output the text
		pop	ax			; recover pad count

		;test	flags1,FL_LEFT		; left justify?
		test	byte [flags],4
		jz	short just7		; no - don't put padding now
		
		mov	cx,ax			; amount of padding
		mov	dl,' '			; pad with spaces
		call	outpad

; Now, everything has been output, just go back to start of loop.

just7:
		jmp	loopagain

; 07/12/2018
; PC-DOS 7.0 FDISK.COM segment 0, offset 7C13h

output_return:
		pop	di
		pop	si
		mov	sp,bp
		pop	bp
		retn

; ------------------------------------------------------ ;
; END OF MAIN PROCEDURE -- NOW WE HAVE LOCAL SUBROUTINES ;
; USED BY THE MAIN PROCEDURE.				 ;
; ------------------------------------------------------ ;

; 07/12/2018
; PC-DOS 7.0 FDISK.COM segment 0, offset 7B4Eh

; ----------------------------------------------------------------------------

; Read a word argument from the argument list
; Bumps arglist by 2 bytes
;   PARAMETERS: none
;   RETURNS:	word read in AX
;   TRASHES:	ES, SI

;getwordarg:
;if sizeD
;	les	si, arglist
;	lods	word ptr es:[si]	; ax = *arglist++
;else
;	mov	si, arglist
;	lodsw				; ax = *arglist++
;endif
;	mov	word ptr (arglist), si	; store arglist back
;	retn				; return near

getwordarg:
		;mov	si,[bp+8]
		mov	si,[arglist]	; (%define arglist bp+8)
		lodsw			; ax = *arglist++
		;mov	[bp+8],si
		mov	[arglist],si	; store arglist back
		retn			; return near

; ----------------------------------------------------------------------------

; Read a long argument from the argument list
; Bumps arglist by 4 bytes
;   PARAMETERS: none
;   RETURNS:	long read in DX:AX
;   TRASHES:	ES, SI

;getlongarg:
;if sizeD
;	les	si, arglist
;	lods	word ptr es:[si]	; ax = *arglist++  (LSW)
;	mov	dx, ax			; dx = LSW
;	lods	word ptr es:[si]	; ax = *arglist++  (MSW)
;	xchg	dx, ax			; ax = LSW, dx = MSW
;else
;	mov	si, arglist
;	lodsw				; ax = *arglist++  (LSW)
;	mov	dx, ax			; dx = LSW
;	lodsw				; ax = *arglist++  (MSW)
;	xchg	dx, ax			; ax = LSW, dx = MSW
;endif
;	mov	word ptr (arglist), si	; store arglist back
;	retn				; return near

getlongarg:
		;mov	si,[bp+8]
		mov	si,[arglist]	; (%define arglist bp+8)
		lodsw			; ax = *arglist++  (LSW)
		mov	dx,ax		; dx = LSW
		lodsw			; ax = *arglist++  (MSW)
		xchg	ax,dx		; ax = LSW, dx = MSW
		;mov	[bp+8],si
		mov	[arglist],si	; store arglist back
		retn			; return near

; ----------------------------------------------------------------------------

; Read a pointer from the argument list into es:di
; Size of pointer read depends on FL_FAR flag, if near, then
; ds is used as segment.
; Note that we don't need to check FL_NEAR, because in C/L models,
; near ptrs are passed as far, and in S/M models near is default
; anyway.
;
;   PARAMETERS: none
;   RETURNS:	ES:DI holds pointer read
;   TRASHES:	AX, DX

getptrarg:
		;test	flags1, FL_FAR	; a far pointer
		test	byte [bp-4],20h
		jz	short rp1	; no - goto near pointer code
		call	getlongarg	; read far pointer into dx:ax
		mov	es,dx
		mov	di,ax		; put far pointer into es:di
		retn
rp1:
		call	getwordarg	; read near pointer into ax
		mov	di,ax
		or	ax,ax		; read NULL ptr?
		jnz	short rp2	; no - store ds
		mov	es,ax		; make long NULL ptr (ax = 0)
		retn
rp2:
		push	ds
		pop	es		; put near pointer into es:di
		retn

; ----------------------------------------------------------------------------

;  Put a character on the output string -- this is the
;  equivalent of putc_lk(c, f)
;    PARAMETERS: AL = character to write
;    RETURNS:	 AX == -1: error, AX == 0: no error
;    TRASHED:	 BX

;putc: ; 13/12/2018

;ifdef CPRFLAG		; put on console instead of to stream
;
;	cbw				; sign-extend char to AX
;	push	es			; save es
;	push	cx
;	push	dx			; save cx and dx
;	push	ax			; parameter: char to write
;	callcrt _putch			; normal put console character
;	add	sp, 2			; restore stack
;	pop	dx
;	pop	cx			; restore cx, dx
;	pop	es			; restore es
;	cmp	ax, -1			; error
;	je	putchret		; yes - return -1 already in ax
;	xor	ax, ax			; no - return 0
;
;putchret:
;	retn
;
;else ; not CPRFLAG  -  now do normal stream output

		;13/12/2018
		;cbw

;if sizeD
;	push	es			; save es
;	push	di			; save di
;	les	bx, stream		; es:bx is file *
;	dec	es:[bx]._cnt		; --f->_cnt
;	js	flush			; out of buffer, must flush
;	mov	di, word ptr es:[bx]._ptr
;	inc	word ptr es:[bx]._ptr
;	mov	es, word ptr es:[bx+2]._ptr ; es:di = *f->_ptr++
;	stosb				; mov es:[di],al - store byte
;noerrret:
;	xor	ax, ax			; no error
;putcret:
;	pop	di
;	pop	es			; restore di, es
;	retn				; return
;
;flush:
;	push	cx
;	push	dx			; save cx and dx
;	push	es
;	push	bx			; push FILE *
;	push	ax			; character to write
;	callcrt _flsbuf 		; call _flsbuf(f, c)
;	add	sp, 6
;	pop	dx
;	pop	cx			; restore cx and dx
;	cmp	ax,-1			; check for an error
;	jne	noerrret		; no error, go clear ax and return
;	jmp	short putcret		; return with ax = -1
;
;else ; not DataSize

		; 13/12/2018
		;push	di
		;;mov	bx,[bp+4]
		;mov	bx,[stream]	; (%define stream bp+4)
		;			; bx is FILE *
		;;dec	[bx]._cnt	; dec f->_cnt
		;;dec	word [bx+_strbuf._cnt]
		;dec	word [bx+2]
		;js	short flush
		;;mov	di,[bx]._ptr
		;;inc	[bx]._ptr	; di = f->_ptr++
		;mov	di,[bx]
		;inc	word [bx]	; [bx+_strbuf.ptr] = _strbuf_ptr 	
		;mov	[di],al		; store byte to write
;noerrret:
		;xor	ax, ax		; no error
;putcret:
		;pop	di		; restore di
		;retn			; return
;flush:
		;push	es
		;push	cx
		;push	dx		; save es, cx and dx
		;push	bx		; push file *
		;push	ax		; character to write
		;call	_flsbuf		; call _flsbuf(f, c)
		;add	sp,4		
		;pop	dx
		;pop	cx
		;pop	es		; restore es, cx and dx
		;cmp	ax,-1		; check for an error
		;jnz	short noerrret	; no error, go clear ax and return
		;jmp	short putcret	; return with ax = -1

putc:
		; 13/12/2018
		; AL = character to be written
		dec	word [outbuf_cnt]
		jns	short putc_1 
		; Write count was ZERO (end of buffer)
putc_0:		
		inc	word [outbuf_cnt]
		xor	al,al ; 0 (end)
		stc
		; zf = 1 and cf = 1
		retn
putc_1:	
		push	es
		;push	di
		push	ds
		pop	es
		mov	di,[outbuf_ptr]
		stosb
		mov	[outbuf_ptr],di
		;pop	di
		pop	es
		or	al,al ; cf = 0, zf = 1 if al = 0
		retn

; ----------------------------------------------------------------------------

;  Output a character string:
;  Put a (NOT zero-terminated) string of character on the output
;  stream, and increment the charsout variable
;    PARAMETERS:  ES:DI points to string to output
;		  CX specifies count of characters to output
;    RETURNS:	  none
;    TRASHES:	  AX, BX, CX, SI, ES
;    NOTES:	  The DI is used to accumulate possible error returns from
;		  the calls to putc. However, it is also saved and restored.

outch:
		jcxz	outchret	; no characters to write - return
		mov	si,di		; DS:SI points to string
		;add	[bp-8],	cx
		;add	charsout,cx	; increase count of characters out
		add	[charsout],cx	; (%define charsout bp-8)
		; 13/12/2018
		;push	di
		;xor	di,di
out1:
		;;lods	byte ptr es:[si] ; al = next char to write, inc si
		es
		lodsb
		call	putc		; write that character
		;or	di,ax		; or the return value into di
		jc	short out2 ; 13/12/2018
		jz	short outchret ; 13/12/2018	
		loop	out1		; write another character if more
		;or	di,di		; did an error occur?
		;pop	di		; restore di
		;jz	short outchret	; no, return
		retn	; 13/12/2018
out2:
		;mov	word [bp-8],0FFFFh
		;mov	charsout,-1	; yes - signal error, then return
		mov	word [charsout],-1
outchret:
		retn

; ----------------------------------------------------------------------------

; Output a string of identical characters for padding
;   PARAMETERS:   DL = character to write, CX = count of character to write
;   RETURNS:	  none
;   TRASHES:	  AX, BX, CX
;   NOTES:	  The DI is used to accumulate possible error returns from
;		  the calls to putc. However, it is also saved and restored.

outpad:
		jcxz	outpadret	; no character to write -- return
		; 13/12/2018
		;add	[bp-8],cx
		;add	charsout,cx	; increase count of chars written
		add	[charsout],cx	; (%define charsout bp-8)
		; 13/12/2018
		;push	di
		;xor	di,di		; clear di
		mov	al,dl ; 13/12/2018
outpad1:
		;mov	al,dl		; al = char to write
		call	putc		; write that character
		;or	di,ax		; or the return value into di
		jc	short outpad2 ; 13/12/2018 
		loop	outpad1		; write another character if more
		
		;or	di,di		; did an error occur?
		;pop	di		; restore di
		;jz	short outpadret	; no - return

		retn	; 13/12/2018
outpad2:
		;mov	word [bp-8],0FFFFh
		;mov	charsout,-1	; yes - signal error
		mov	word [charsout],-1
outpadret:
		retn

; ----------------------------------------------------------------------------

; Convert a unsigned long to a character string.
;   PARAMETERS: DX:AX is number to convert
;		CX is radix to convert with
;		ES:DI points to where to store LAST digit
;		SI is min digits to store (pad with zero until this length)
;   (N.B. Converting 0 with SI==0 gives blank result: this is correct
;    and ANSI mandated)
;
;   RETURNS:	ES:DI points to first digit
;		CX is length of digit string
;
;   TRASHES:	AX, BX, DX, DI, SI
;
;
;   This algorithm does a 32 bit divided by 16 bit division to
;   get 32 bit quotient and 16 bit remainder like this (lifted from xtoa.asm):
;
;	   h/r	:  (h%r:l)/r
;      --------------
;   r  )   h	:   l
;	 r(h/r)
;	 ------------
;	  h%r	:   l
;	 r((h%r:l)/r)
;	 ------------
;		((h%r):l)%r  (REMAINDER)

convert:
		std			; store string in reverse
		push	di		; save di
		xchg	ax,bx		; dx = h, bx = l
conv1:
		or	si,si		; si == 0?
		jg	short conv2	; count > 0 => keep converting
		or	bx,bx		; l == 0?
		jnz	short conv2	; l != 0 => keep converting
		or	dx,dx		; h == 0?
		;jnz	short conv2	; h != 0 => keep converting	
		;jmp	short conv4	; stop converting (h:l==0, count<=0);
		jz	short conv4	
conv2:
		xchg	ax,dx		; ax = h, bx = l
		xor	dx,dx		; ax = h, bx = l, dx = 0
		div	cx		; ax = h/r, dx = h%r, bx = l
		xchg	ax,bx		; dx = h%r, ax = l, bx = h/r
		div	cx		; ax = (h%r:l)/r, dx = (h%r:l)%r, bx = h/r
					; bx:ax = (h:l)/r, dx = (h:l)%r
		xchg	ax,dx		; bx:dx = (h:l)/r, ax = (h:l)%r
		xchg	dx,bx		; dx:bx = (h:l)/r, ax = (h:l)%r

; now al has x%r, which is the numeric value of the digit -- now convert to ASCII

		add	al,'0'
		cmp	al,'9'		; a normal digit?
		jbe	short conv3	; yes, store it
		;add	al,[bp-1]
		;add	al,hexadd	; no, convert to hex
		add	al,[hexadd]	; (%define hexadd bp-1)
conv3:
		stosb			; *(es:di) = al, --di
		mov	ax,dx		; ax:bx = (h:l)/r
		dec	si		; stored a digit, subtract from count
		jmp	short conv1
	
	; OK, we're done -- set up the return values
conv4:
		pop	cx		; cx has orginal di
		sub	cx,di		; subtract di now, get string length
		inc	di		; point to first digit
		cld			; must keep direction flag cleared
		retn

;return to user
;
;output_return:
;	pop	di
;	pop	si			; pop register variables
;	mov	sp,bp
;	pop	bp
;	retn

; ----------------------------------------------------------------------------

; 07/12/2018 

;***
;chkstk.asm - C stack checking routine
;
;	Copyright (c) 1985-1992 Microsoft Corporation, All Rights Reserved
;
;Purpose:
;	Provides support for automatic stack checking in C procedures
;	when stack checking is enabled.
;
;*******************************************************************************

;***
;_chkstk - check stack upon procedure entry
;
;Purpose:
;	Provide stack checking on procedure entry.
;
;	[LLIBCDLL.LIB NOTE: Unlike other LLIBCDLL routines, DS != DGROUP
;	when chkstk() is called.]
;
;Entry:
;	AX = size of local frame
;
;Exit:
;	SP = new stackframe if successful
;
;Uses:
;	AX, BX, CX, DX
;
;Exceptions:
;	Gives out of memory error and aborts if there is not enough
;	stack space for the routine.
;
;*******************************************************************************

_chkstk:
		pop	cx		; get return offset
		mov	bx,sp		; bx = current SP
		sub	bx,ax		; bx = new position
		jc	short OMerr
		;cmp	bx,[_STKHQQ]	; SP - AX : _STKHQQ (for heap/stack)
		cmp	bx,[end_of_bss]
		jb	short OMerr	; error - out of memory
		mov	sp,bx
		jmp	cx		; return to cx
OMerr:
		;push	cx
		;xor	ax,ax
		;jmp	_amsg_exit	; give stack overflow and die
		; 14/12/2018
		push	ds
		push	word [stackerror_msg_off]
		call	display
		;pop	bx
		;pop	bx
		mov	al,255
		jmp	_exit

; ----------------------------------------------------------------------------
; tdisplay.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 07/12/2018)

;void get_letters()                                                   /*C32*/
;BEGIN                                                                /*C32*/
;                                                                     /*C32*/
;unsigned char i,j;                                                   /*C32*/
;unsigned char active_primary_count;                                  /*C32*/
;unsigned char pri_part;                                              /*C32*/
;                                                                     /*C32*/
;    /* initialize next letter */                                     /*C32*/
;    next_letter = c(SEA);                                            /*C32*/
;                                                                     /*C32*/
;    /* get primary DOS partition letters on all drives */            /*C32*/
;    for (j = uc(0); j < number_of_drives; j++)                       /*C32*/
;       BEGIN                                                         /*C32*/
;        /* initialize variables */                                   /*C32*/
;        primary_partition_count = 0;                                 /*C32*/
;        active_primary_count = 0;                                    /*C32*/
;        pri_part = 0xFF;                                             /*C32*/
;                                                                     /*C32*/
;        /* Look at all partitions */                                 /*C32*/
;        for (i=u(0); i < u(4); i++)                                  /*C32*/
;           BEGIN                                                     /*C32*/
;            /* Compute e letter */                                   /*C32*/
;            if ( (part_table[j][i].sys_id == DOS12) ||               /*C32*/
;                 (part_table[j][i].sys_id == DOS16) ||               /*C32*/
;                 (part_table[j][i].sys_id == DOSNEW)   )             /*C32*/
;               BEGIN                                                 /*C32*/
;                part_table[j][i].drive_letter = c(' ');              /*C32*/
;                if ((primary_partition_count == 0) ||                /*C32*/
;                    ((part_table[j][i].boot_ind == 0x80) &&          /*C32*/
;                     (active_primary_count == 0)))                   /*C32*/
;                    pri_part = c(i);                                 /*C32*/
;                if (part_table[j][i].boot_ind == 0x80)               /*C32*/
;                    active_primary_count++;                          /*C32*/
;                primary_partition_count++;                           /*C32*/
;               END                                                   /*C32*/
;           END                                                       /*C32*/
;        if ((pri_part != 0xFF) && (next_letter <= c('Z')))           /*C32*/
;            part_table[j][pri_part].drive_letter = next_letter++;    /*C32*/
;       END                                                           /*C32*/
;                                                                     /*C32*/
;    /* get logical DOS drive letters on all drives */                /*C32*/
;    for (j = uc(0); j < number_of_drives; j++)                       /*C32*/
;       BEGIN                                                         /*C32*/
;       /* Look at all partitions */                                  /*C32*/
;        for (i=u(0); i < u(23); i++)                                 /*C32*/
;           BEGIN                                                     /*C32*/
;            /* Set drive letter */                                   /*C32*/
;            if ( (ext_table[j][i].sys_id == DOS12) ||                /*C32*/
;                 (ext_table[j][i].sys_id == DOS16) ||                /*C32*/
;                 (ext_table[j][i].sys_id == DOSNEW)   )              /*C32*/
;                if (next_letter <= c('Z'))                           /*C32*/
;                    ext_table[j][i].drive_letter = next_letter++;    /*C32*/
;                else                                                 /*C32*/
;                    ext_table[j][i].drive_letter = c(' ');           /*C32*/
;           END                                                       /*C32*/
;       END                                                           /*C32*/
;                                                                     /*C32*/
;    /* get enhdisk partition letters on all drives */                /*C32*/
;    for (j = uc(0); j < number_of_drives; j++)                       /*C32*/
;       BEGIN                                                         /*C32*/
;        /* Look at all active primary partitions */                  /*C32*/
;        for (i=u(0); i < u(4); i++)                                  /*C32*/
;           BEGIN                                                     /*C32*/
;            /* Set drive letter */                                   /*C32*/
;            if (((part_table[j][i].sys_id == DOS12) ||               /*C32*/
;                 (part_table[j][i].sys_id == DOS16) ||               /*C32*/
;                 (part_table[j][i].sys_id == DOSNEW)) &&             /*C32*/
;                (part_table[j][i].boot_ind == 0x80))                 /*C32*/
;                if ((part_table[j][i].drive_letter == c(' ')) &&     /*C32*/
;                    (next_letter <= c('Z')))                         /*C32*/
;                    part_table[j][i].drive_letter = next_letter++;   /*C32*/
;           END                                                       /*C32*/
;        /* Look at all non-active primary partitions */              /*C32*/
;        for (i=u(0); i < u(4); i++)                                  /*C32*/
;           BEGIN                                                     /*C32*/
;            /* Set drive letter */                                   /*C32*/
;            if (((part_table[j][i].sys_id == DOS12) ||               /*C32*/
;                 (part_table[j][i].sys_id == DOS16) ||               /*C32*/
;                 (part_table[j][i].sys_id == DOSNEW)) &&             /*C32*/
;                (part_table[j][i].boot_ind != 0x80))                 /*C32*/
;                if ((part_table[j][i].drive_letter == c(' ')) &&     /*C32*/
;                    (next_letter <= c('Z')))                         /*C32*/
;                    part_table[j][i].drive_letter = next_letter++;   /*C32*/
;           END                                                       /*C32*/
;       END                                                           /*C32*/
;                                                                     /*C32*/
;    return;                                                          /*C32*/
;                                                                     /*C32*/
;END  

get_letters:

	%define gdl_j		bp-8
	%define gdl_i		bp-6
	%define a_primary_count	bp-4
	%define p_part		bp-2

		push	bp
		mov	bp,sp
		sub	sp,8

		;/* initialize next letter */ 
		mov	byte [next_letter],'C'

		;/* get primary DOS partition letters on all drives */
		;mov	word [gdl_j],0
		mov	byte [gdl_j],0
		mov	cl,46  ; *CL* ; 07/12/2018
		jmp	gdl_10
gdl_1:
		;/* Compute a letter */  
		mov	al,[gdl_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;;add	ax,cx
		;add	al,cl
		;mov	cx,46
		;imul	cx
		add	al,[gdl_i]
		;mov	cl,46  ; *CL*
		mul	cl
		mov	bx,ax

		cmp	byte [part_table_sys_id+bx],1 ; DOS12  ; FAT12	
		je	short gdl_2
		cmp	byte [part_table_sys_id+bx],4 ; DOS16  ; FAT16
		je	short gdl_2
		cmp	byte [part_table_sys_id+bx],6 ; DOSNEW ; FAT16 big
		jne	short gdl_6
gdl_2:
		;mov	al,[gdl_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		;part_table[j][i].drive_letter = c(' '); 
		mov	byte [part_table_drive_letter+bx],' '

		; Only one primary dos partition per disk !

		;if ((primary_partition_count == 0) ||
                ;   ((part_table[j][i].boot_ind == 0x80) &&
                ;   (active_primary_count == 0)))
                ;   pri_part = c(i);                 

		cmp	byte [primary_partition_count],0
		jna	short gdl_3
		cmp	byte [part_table_boot_ind+bx],80h
		jne	short gdl_4
		cmp	byte [a_primary_count],0 ;active_primary_count
		ja	short gdl_4
gdl_3:
		; Only one primary dos partition per disk !
		mov	al,[gdl_i]
		mov	[p_part],al	; primary_part
gdl_4:
		;mov	al,[gdl_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		;if (part_table[j][i].boot_ind == 0x80)
                ;    active_primary_count++;
                ;primary_partition_count++;            

		cmp	byte [part_table_boot_ind+bx],80h
		jne	short gdl_5
		inc	byte [a_primary_count]
gdl_5:
		inc	byte [primary_partition_count]
gdl_6:
		inc	byte [gdl_i]
gdl_7:
		;/* Look at all partitions */
		;for (i=u(0); i < u(4); i++)

		; if i < 4 -- NEXT -- 
		cmp	byte [gdl_i],4
		;jnb	short gdl_8
		;jmp	gdl_1
		jb	short gdl_1 ; next
gdl_8:
		;if ((pri_part != 0xFF) && (next_letter <= c('Z')))
		;   part_table[j][pri_part].drive_letter = next_letter++;

		cmp	byte [p_part],0FFh
		je	short gdl_9
		cmp	byte [next_letter],'Z'
		jg	short gdl_9

		mov	al,[gdl_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;mov	cl,[p_part]
		;sub	ch,ch
		;add	ax,cx
		;add	al,cl
		;;mov	cx,46
		;mov	cl,46
		;imul	cx
		;mul	cl
		add	al,[p_part]
		mul	cl ; CL = 46 ; *CL*
		mov	bx,ax
		mov	al,[next_letter]
		mov	[part_table_drive_letter+bx],al
		inc	byte [next_letter]
gdl_9:
		inc	byte [gdl_j]
gdl_10:
		;/* get primary DOS partition letters on all drives */
		;for (j = uc(0); j < number_of_drives; j++) 
		mov	al,[number_of_drives]
		cmp	[gdl_j],al
		jnb	short gdl_11

		;/* initialize variables */
		;primary_partition_count = 0;
		;active_primary_count = 0;
		;pri_part = 0xFF;     
		mov	byte [primary_partition_count],0
		mov	byte [p_part],0FFh
		sub	al,al ; 0
		mov	[a_primary_count],al

		;/* Look at all partitions */  ; For next disk/drive
		mov	[gdl_i],al ; 0
		jmp	short gdl_7
gdl_11:		
		;/* get logical DOS drive letters on all drives */
		mov	byte [gdl_j],0
		jmp	short gdl_17
gdl_12:
		;mov	al,24
		;mul	byte [gdl_j]
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mul	cl
		;mov	bx,ax

		;ext_table[j][i].drive_letter = c(' ');  
		mov	byte [ext_table_drive_letter+bx],' '
gdl_13:	
		inc	byte [gdl_i]
gdl_14:
		;/* Look at all partitions */
        	;for (i=u(0); i < u(23); i++) 

		; if i < 23 ;  -- NEXT --
		cmp	byte [gdl_i],23
		jnb	short gdl_16

		mov	al,24
		mul	byte [gdl_j]
			; ax < 192
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;add	ax,cx
		add	al,[gdl_i]
		;mov	cx,46
		;imul	cx
		mul	cl ; CL = 46 ; *CL*
		mov	bx,ax

		;/* Set drive letter */ 

		cmp	byte [ext_table_sys_id+bx],1 ; DOS12
		je	short gdl_15
		cmp	byte [ext_table_sys_id+bx],4 ; DOS16
		je	short gdl_15
		cmp	byte [ext_table_sys_id+bx],6 ; DOSNEW ; FAT16 big
		jne	short gdl_13
gdl_15:
		;if (next_letter <= c('Z'))
                ;   ext_table[j][i].drive_letter = next_letter++;
                ;else
                ;   ext_table[j][i].drive_letter = c(' ');    

		cmp	byte [next_letter],'Z'
		jg	short gdl_12

		;mov	al,24
		;mul	[gdl_j]
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		mov	al,[next_letter]
		mov	[ext_table_drive_letter+bx],al
		inc	byte [next_letter]
		jmp	short gdl_13
gdl_16:
		inc	byte [gdl_j]
gdl_17:
		;/* get logical DOS drive letters on all drives */
    		;for (j = uc(0); j < number_of_drives; j++)    
		
		mov	al,[number_of_drives]
		cmp	[gdl_j],al
		jnb	short gdl_18
		
		;/* Look at all partitions */
		mov	byte [gdl_i],0
		jmp	short gdl_14
gdl_18:
		;/* get enhdisk partition letters on all drives */   	
		mov	byte [gdl_j],0
		jmp	short gdl_23
gdl_19:
		inc	byte [gdl_i]  ; next partition
gdl_20:
		;/* Look at all non-active primary partitions */
        	;for (i=u(0); i < u(4); i++)    

		cmp	byte [gdl_i],4
		jnb	short gdl_22

		mov	al,[gdl_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;add	ax,cx
		add	al,[gdl_i]
		;mov	cx,46
		;imul	cx
		;mov	bx,ax
		mul	cl ; CL = 46 ; *CL*
		mov	bx,ax

		;/* Set drive letter */
		;if (((part_table[j][i].sys_id == DOS12) ||
                ;   (part_table[j][i].sys_id == DOS16) ||
                ;   (part_table[j][i].sys_id == DOSNEW)) &&
                ;   (part_table[j][i].boot_ind != 0x80))       

		cmp	byte [part_table_sys_id+bx],1 ; DOS12	
		je	short gdl_21
		cmp	byte [part_table_sys_id+bx],4 ; DOS16
		je	short gdl_21
		cmp	byte [part_table_sys_id+bx],6 ; DOSNEW ; FAT16 big
		jne	short gdl_19
gdl_21:
		;mov	al,[gdl_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		;if ((part_table[j][i].drive_letter == c(' ')) &&
                ;   (next_letter <= c('Z')))
                ;   part_table[j][i].drive_letter = next_letter++;

		cmp	byte [part_table_boot_ind+bx],80h
		je	short gdl_19

		cmp	byte [part_table_drive_letter+bx],' '
		jne	short gdl_19
		cmp	byte [next_letter],'Z'
		jg	short gdl_19

		mov	al,[next_letter]
		mov	[part_table_drive_letter+bx],al
		inc	byte [next_letter]
		jmp	short gdl_19
gdl_22:
		inc	byte [gdl_j]
gdl_23:
		;/* get enhdisk partition letters on all drives */   
		;for (j = uc(0); j < number_of_drives; j++)

		mov	al,[number_of_drives]
		cmp	[gdl_j],al
		jnb	short gdl_27

		;/* Look at all active primary partitions */
      		;for (i=u(0); i < u(4); i++)     
		mov	byte [gdl_i],0
gdl_24:
		mov	al,[gdl_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;add	ax,cx
		add	al,[gdl_i]
		;mov	cx,46
		;imul	cx
		mul	cl ; CL = 46 ; *CL*
		mov	bx,ax

		;/* Set drive letter */
            
		;if (((part_table[j][i].sys_id == DOS12) ||
                ;   (part_table[j][i].sys_id == DOS16) ||
                ;   (part_table[j][i].sys_id == DOSNEW)) && 
                ; (part_table[j][i].boot_ind == 0x80))    

		cmp	byte [part_table_sys_id+bx],1 ; DOS12  ; FAT12	
		je	short gdl_25
		cmp	byte [part_table_sys_id+bx],4 ; DOS16  ; FAT16
		je	short gdl_25
		cmp	byte [part_table_sys_id+bx],6 ; DOSNEW ; FAT16 big
		jne	short gdl_26
gdl_25:
		;mov	al,[gdl_j]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;mov	cl,[gdl_i]
		;sub	ch,ch
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		cmp	byte [part_table_boot_ind+bx],80h
		jne	short gdl_26

		;if ((part_table[j][i].drive_letter == c(' ')) &&
                ;    (next_letter <= c('Z')))
                ;    part_table[j][i].drive_letter = next_letter++; 

		cmp	byte [part_table_drive_letter+bx],' '
		jne	short gdl_26
		cmp	byte [next_letter],'Z'
		jg	short gdl_26
		mov	al,[next_letter]
		mov	[part_table_drive_letter+bx],al
		inc	byte [next_letter]
gdl_26:
		inc	byte [gdl_i]
		cmp	byte [gdl_i],4
		jb	short gdl_24 ; next disk/drive

		;/* Look at all non-active primary partitions */ 
		mov	byte [gdl_i],0
		jmp	gdl_20
gdl_27:
		mov	sp,bp
		pop	bp
		retn

; ----------------------------------------------------------------------------
; space.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 07/12/2018)

;void sort_part_table(size)
;
;char size;
;
;BEGIN
;
;char  changed;
;char  temp;
;char   i;
;
;       /* Init the sorting parameters */
;       for (i=c(0); i < size; i++)                               /* AC000 */
;          BEGIN
;           sort[i] = i;
;          END
;
;       /* Do a bubble sort */
;       changed = TRUE;
;
;       /* Sort until we don't do a swap */
;       while (changed)
;
;          BEGIN
;           changed = FALSE;
;           for (i=c(1); i < size; i++)                           /* AC000 */
;              BEGIN
;
;               /* Does the partition entry start before the previous one, or */
;               /* is it empty (0 ENTRY). If empty, it automatically gets shoved */
;               /* to the front, if the previous entry isn't also empty */
;
;               if ((part_table[cur_disk][sort[i]].end_cyl < part_table[cur_disk][sort[i-1]].end_cyl)
;                  || ((part_table[cur_disk][sort[i]].num_sec == ul(0))
;                  &&  (part_table[cur_disk][sort[i-1]].num_sec != ul(0))))  /* AC000 */
;
;                  BEGIN
;                   /* Swap the order indicators */
;                   temp = sort[i-1];
;                   sort[i-1] = sort[i];
;                   sort[i] = temp;
;
;                /* printf("\nI-1 =%d\n",part_table[cur_disk][sort[i-1]].start_cyl);*/
;                /* printf("I =%d\n",part_table[cur_disk][sort[i]].start_cyl);*/
;                /* printf("Sort[i-1] = %d\n",sort[i-1]);*/
;                /* printf("Sort[i] = %d\n",sort[i]); */
;                /* wait_for_ESC(); */
;
;                   /* indicate we did a swap */
;                   changed = TRUE;
;                  END
;              END
;          END
;       return;
;END

sort_part_table:
				     ; 12/12/2018	
	;%define sort_changed	bp-6    ; ch
	;%define sort_i		bp-4    ; bx
	;%define sort_temp	bp-2    ; ah
	;%define sort_count	bp+4    ; cl

		; 12/12/2018
		;push	bp
		;mov	bp,sp
		;sub	sp,6
		
		;push	di
		;push	si

		; CL = sort count ; 12/12/2018

		;/* Init the sorting parameters */
		;for (i=c(0); i < size; i++)     
		
		;mov	word [sort_i],0
		xor	bx,bx ; 0 ; 12/12/2018
		jmp	short sortpt_2
sortpt_1:
		;mov	al,[sort_i]
		;cbw
		
		;mov	ax,[sort_i] ; 12/12/2018
		;mov	bx,ax
		
		;mov	[bx+sort],al
		mov	[bx+sort],bl ; 12/12/2018		

		;inc	byte [sort_i]
		inc	bl ; 12/12/2018
sortpt_2:
		;mov	al,[sort_count] ; size
		;cmp	[sort_i],al	; i < size
		;jl	short sortpt_1
		
		; 12/12/2018
		; CL = sort count
		cmp	bl,cl
		jl	short sortpt_1

		;/* Do a bubble sort */
		;changed = TRUE;

		;mov	byte [sort_changed],1
		jmp	short sortpt_4 ; 07/12/2018
sortpt_3:
		;/* Sort until we don't do a swap */
        	;while (changed)

		;cmp	byte [sort_changed],0
		;;jne	short sortpt_4
		;;jmp	sortpt_8
		;jna	short sortpt_8 ; 07/12/2018
		; 12/12/2018
		or	ch,ch ; sort changed ?
		jz	short sortpt_8 ; no.
sortpt_4:
		;changed = FALSE;
            	;for (i=c(1); i < size; i++) 

		;mov	byte [sort_changed],0
		xor	ch,ch	; 12/12/2018
		
		;mov	byte [sort_i],1
		mov	bl,1 ; 12/12/2018

		mov	dl,46 ; *DL*  ; 07/12/2018
		jmp	short sortpt_6
sortpt_5:
		;inc	byte [sort_i]
		inc	bl ; 12/12/2018
sortpt_6:
		;mov	al,[sort_count] ; size
		;cmp	[sort_i],al	; i < size
		;jge	short sortpt_3

		; 12/12/2018
		; CL = sort count
		cmp	bl,cl
		jge	short sortpt_3

		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	cx,ax

		;mov	cl,[cur_disk] ; 07/12/2018
		;shl	cl,1
		;shl	cl,1	; 4 partitions per disk

		; 12/12/2018
		mov	dh,[cur_disk]
		shl	dh,1
		shl	dh,1
		
		;mov	al,[sort_i]
		;cbw
		;mov	bx,ax

		;mov	bx,[sort_i] ; 12/12/2018

		;mov	al,[bx+sort]
		;cbw
		;add	ax,cx

		mov	al,[bx+sort] ; 07/12/2018
		;add	al,cl ; skip partitions of previous drive (other drives)
		add	al,dh ; 12/12/2018

		;mov	si,46
		;imul	si
		;mov	dl,46 ; *DL*
		mul	dl

		;mov	di,ax
		;mov	ax,[part_table_end_cyl+di]
		;mov	dx,ax
		mov	si,ax

		;mov	ax,[part_table_end_cyl+si]
		;mov	di,ax
		mov	di,[part_table_end_cyl+si] ; **DI** ; 07/12/2018

		mov	al,[bx+sort-1]

		;cbw
		;add	ax,cx
		;add	al,cl
		;mov	cx,dx
		;imul	si

		; DH = [cur_disk]
		add	al,dh ; 12/12/2018
		mul	dl ; *DL* ; = 46
		;mov	bx,ax

		xchg	di,ax ; **DI** 12/12/2018

	;/* Does the partition entry start before the previous one, or */
	;/* is it empty (0 ENTRY). If empty, it automatically gets shoved */
	;/* to the front, if the previous entry isn't also empty */
	;
	;if ((part_table[cur_disk][sort[i]].end_cyl < part_table[cur_disk][sort[i-1]].end_cyl)
	;   || ((part_table[cur_disk][sort[i]].num_sec == ul(0))
	;   &&  (part_table[cur_disk][sort[i-1]].num_sec != ul(0))))

		;cmp	[part_table_end_cyl+bx],cx
		;cmp	[part_table_end_cyl+bx],di ; **XCHG**
		cmp	[part_table_end_cyl+di],ax ; **XCHG** ; 12/12/2018
		ja	short sortpt_7 ; pt[cur_disk][sort[i]].end_cyl < pt[cur_disk][sort[i-1]].end_cyl

		;mov	ax,[part_table_num_sec_hw+di]
		mov	ax,[part_table_num_sec_hw+si] ; part_table[cur_disk][sort[i]].num_sec
		;or	ax,[part_table_num_sec_lw+di]
		or	ax,[part_table_num_sec_lw+si]
		jnz	short sortpt_5
		;mov	ax,[part_table_num_sec_hw+bx] ; part_table[cur_disk][sort[i-1]].num_sec
		mov	ax,[part_table_num_sec_hw+di] ; **XCHG** ; 12/12/2018
		;or	ax,[part_table_num_sec_lw+bx]
		or	ax,[part_table_num_sec_lw+di] ; **XCHG** ; 12/12/2018
		jz	short sortpt_5
sortpt_7:
		;/* Swap the order indicators */
                ;temp = sort[i-1];
                ;sort[i-1] = sort[i];
                ;sort[i] = temp;

		;mov	al,[sort_i]
		;cbw
		;mov	bx,ax
		
		; 12/12/2018
		;mov	bx,[sort_i] ; 07/12/2018

		;mov	al,[bx+sort-1]
		;mov	[sort_temp],al
		;mov	al,[bx+sort]
		;mov	[bx+sort-1],al
		;mov	al,[sort_temp]
		;mov	[bx+sort],al

		; 12/12/2018
		mov	ax,[bx+sort-1] ; 12/12/2018
		xchg	ah,al
		mov	[bx+sort-1],ax

		;mov	byte [sort_changed],1
		mov	ch,1 ; 12/12/2018
		jmp	short sortpt_5
sortpt_8:
		;pop	si
		;pop	di
		
		;mov	sp,bp ; 12/12/2018
		;pop	bp
		
		retn


; 08/12/2018

;void sort_ext_table(size)
;
;char size;
;
;BEGIN
;
;char  changed;
;char  temp;
;char i;
;
;       /* Init the sorting parameters */
;
;       for (i=c(0); i < size; i++)			/* AC000 */
;          BEGIN
;           sort[i] = i;
;          END
;
;       /* Do a bubble sort */
;       changed = TRUE;
;
;       /* Sort until we don't do a swap */
;       while (changed)
;
;          BEGIN
;           changed = FALSE;
;           for (i=c(1); i < size; i++)			/* AC000 */
;              BEGIN
;
;               if (ext_table[cur_disk][sort[i]].start_cyl < ext_table[cur_disk][sort[i-1]].start_cyl)
;                  BEGIN
;
;                   temp = sort[i-1];
;                   sort[i-1] = sort[i];
;                   sort[i] = temp;
;                   /* indicate we did a swap */
;                   changed = TRUE;
;                  END
;              END
;          END
;       return;
;END

sort_ext_table:	

	;;%define swptemp2      bp-10
	;;%define swptemp1      bp-8

	;%define sortex_changed bp-6  ; ch
	;%define sortex_i       bp-4  ; bx
	;%define sortex_temp    bp-2  ; ah

	;%define sortex_count   bp+4  ; cl

		; 12/12/2018
		;push	bp
		;mov	bp,sp
		;;sub	sp,10
		;sub	sp,6 ; 08/12/2018
		
		;push	di
		;push	si

		; CL = sort count ; 12/12/2018

		;/* Init the sorting parameters */
		;for (i=c(0); i < size; i++)
	
		;mov	word [sortex_i],0
		xor	bx,bx ; 0 ; 12/12/2018
		jmp	short sortept_2
sortept_1:
		;;mov	al,[sortex_i]
		;;cbw
		; 12/12/2018
		;mov	ax,[sortex_i]
		;mov	bx,ax
		;mov	[bx+sort],al
		
		;mov	bx,[sortex_i]
		mov	[bx+sort],bl ; 12/12/2018

		;inc	byte [sortex_i]
		inc	bl ; 12/12/2018
sortept_2:
		;mov	al,[sortex_count] ; size
		;cmp	[sortex_i],al ; if i < size
		;jl	short sortept_1 ; then ..

		; 12/12/2018
		; CL = sort count
		cmp	bl,cl
		jb	short sortept_1 ; 04/01/2019 

		;/* Do a bubble sort */
		;changed = TRUE;

		;mov	byte [sortex_changed],1
		jmp	short sortept_4
sortept_3:
		;/* Sort until we don't do a swap */
		;while (changed)

		;cmp	byte [sortex_changed],0
		;je	short sortept_7
		
		; 12/12/2018
		or	ch,ch ; sort changed ?
		jz	short sortept_7 ; no.
sortept_4:
		;changed = FALSE;
		;for (i=c(1); i < size; i++)	

		;mov	byte [sortex_changed],0
		xor	ch,ch	; 12/12/2018
		
		;mov	byte [sortex_i],1
		mov	bl,1 ; 12/12/2018

		mov	dl,46 ; ***DI*** ; 08/12/2018
		jmp	short sortept_6
sortept_5:
		;inc	byte [sortex_i]
		inc	bl ; 12/12/2018
sortept_6:
		;mov	al,[sortex_count] ; size
		;cmp	[sortex_i],al
		;jge	short sortept_3

		; 12/12/2018
		; CL = sort count
		cmp	bl,cl
		jge	short sortept_3

		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]

		;mov	cx,ax  ; skip logical drives on previous disk(s)
		; cl = [current_disk]*24, ch = 0

		; 12/12/2018
		mov	dh,al
		; dh = [current_disk]*24	

		;mov	al,[sortex_i]
		;cbw
		;mov	bx,ax
		
		;mov	bx,[sortex_i]		

		;mov	al,[bx+sort]
		;mov	dx,ax
		;cbw
		;add	ax,cx

		mov	al,[bx+sort]
		;add	al,cl  ; ([current_disk]*24) + [sort[i]] 		
		add	al,dh  ; 12/12/2018 

		;mov	si,ax

		;mov	al,[bx+sort-1]
		;mov	di,46
		;mov	[swptemp1],ax
		;mov	ax,si
		;mov	[swptemp2],dx
		;imul	di
		;mov	si,ax

		;mov	dl,46 ; ***DI***
		mul	dl
		mov	si,ax

		;mov	ax,[ext_table_start_cyl+si] ; ept[cur_disk][sort[i]].start_cyl
		;mov	dx,ax
		;mov	al,[swptemp1]
		;cbw
		;add	ax,cx
	
		mov	di,[ext_table_start_cyl+si] ; ept[cur_disk][sort[i]].start_cyl
		
		mov	al,[bx+sort-1]
		
		; ah = 0
		;add	al,cl ; ; ([current_disk]*24) + [sort[i-i]] 
		;mov	cx,dx
		;imul	di
		
		add	al,dh ; 12/12/2018
		mul	dl ; 46
		mov	si,ax
		
;if (ext_table[cur_disk][sort[i]].start_cyl < ext_table[cur_disk][sort[i-1]].start_cyl)

		;cmp	[ext_table_start_cyl+si],cx
		cmp	[ext_table_start_cyl+si],di ; ept[cur_disk][sort[i-1]].start_cyl
		jna	short sortept_5

		;ept[cur_disk][sort[i]].start_cyl < ept[cur_disk][sort[i-1]].start_cyl

		;/* Swap the order indicators */
		;;mov	al,[swptemp1]
		;mov	al,[bx+sort-1]
		;mov	[sortex_temp],al
		;;mov	al,[swptemp2]
		;mov	al,[bx+sort]	
		;mov	[bx+sort-1],al
		;mov	al,[sortex_temp]
		;mov	[bx+sort],al
		
		; 12/12/2018
		mov	ax,[bx+sort-1] ; 12/12/2018
		xchg	ah,al
		mov	[bx+sort-1],ax

		;mov	byte [sortex_changed],1
		mov	ch,1 ; 12/12/2018
		jmp	short sortept_5
sortept_7:
		;pop	si
		;pop	di
		
		;mov	sp,bp ; 12/12/2018
		;pop	bp
		
		retn

; ----------------------------------------------------------------------------
; IBM PC-DOS 7.0 FDISK.COM, Segment 0, Offset 0014h

; 07/12/2018
;_fptrap:
;		retn

; CRT0FP.ASM - Microsoft Visual C++ Version 1.0

;***
;_fptrap - trap for missing floating-point software
;
;Purpose:
;	Catches these cases of incomplete f.p. software linked into a program.
;
;	(1) 87.LIB chosen, but no coprocessor present;
;	    (i.e., emulator not linked)
;
;	(2) "%e", "%f", and "%g" i/o conversion formats specified, but
;	    not all conversion software has been linked in, because the
;	    program did not use any floating-point variables or expressions.
;
;Entry:
;	None.
;
;Exit:
;	None.
;
;Uses:
;	AX.
;
;Exceptions:
;	Transfers control to _amsg_exit which ...
;	- Writes error message to standard error:  "floating point not loaded";
;	- Terminates the program by calling _exit().
;*******************************************************************************

;labelNP <PUBLIC,_fptrap>
;
;ifdef	_LOAD_DGROUP
;;	 push	 ds		; no need to save ds since program will dying
;	mov	ax, DGROUP
;	mov	ds, ax
;endif	;_LOAD_DGROUP
;
;	mov	ax,_RT_FLOAT	; issue floating point not loaded
;	jmp	_amsg_exit	;   and die

; 14/12/2018
_fptrap:
	; 14/12/2018
	pop	cx  ; return address
	push	ds
	push	word [fperror_msg_off]
	call	display
	;pop	bx
	;pop	bx
	mov	al,255
	jmp	_exit

; CRT0.ASM (VCCRT2.ZIP) - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; Microsoft(R) Visual C++ Version 1.0 Run-Time Library Sources (1993)
; ----------------------------------------------------------------------------
; Modified and simplified for NASM syntax and com (single segment) file
;						 (by Erdogan Tan, 07/12/2018)

;***
;_amsg_exit, _cintDIV - Fast exit fatal errors
;
;Purpose:
;	Exit the program with error code of 255 and appropriate error
;	message.  cintDIV is used for integer divide by zero, amsg_exit
;	is for other run time errors.
;
;ifdef _FATALHOOK
;	Weak extern call through _fatalexit was added so programs
;	may be notified of imminent termination (e.g., PWB).
;endif
;
;Entry:
;	AX	= error message number (amsg_exit only).
;
;Exit:
;	calls exit() [cintDIV] or indirect through _aexit_rtn [amg_exit].
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************

; 14/12/2018 (no need to _cintDIV and _agsm_exit for FDISK2.COM)

;; IBM PC-DOS 7.0 FDISK.COM, Segment 0, Offset 66D2h
;
;		_aDBdoswp equ 0D6D6h
;_cintDIV:
;
;		;mov	ax,[cs:_dataseg] ; DGROUP
;		;mov	ds,ax	
;	
;		push	cs	; 07/12/2018
;		pop	ds
;	
;		mov	ax,3 ; _RT_INTDIV ; Integer divide by zero interrupt
;		mov	word [_aexit_rtn],_exit ; call high-level exit()
;				; to cause file buffer flushing
;_amsg_exit:
;		push	ax		; message number for _NMSG_WRITE
;
;		call	_FF_MSGBANNER	; run-time error message banner
;		call	_NMSG_WRITE	; write error message to stdout
;
;		cmp	word [_aDBswpflg],_aDBdoswp  ; Aware debugger as parent?
;		jne	short _@FF		     ; No -- skip
;		pop	ax
;		push	ax
;		call	_aDBrterr	; Yes -- report a runtime error
;_@FF:
;		mov	ax,255
;		push	ax
;
;		call	word [_aexit_rtn] ; _exit(255) ordinarily
;					; (or exit(255) for div by 0)
;					; NEAR routine pointer

;;_dataseg: dw	seg DGROUP ; for EXE file
;_dataseg:  dw  0   ; for COM file

; ----------------------------------------------------------------------------
; IBM PC-DOS 7.0 FDISK.COM, Segment 0, Offset 0016h
;_FF_MSGBANNER:
;		retn

; ----------------------------------------------------------------------------
; IBM PC-DOS 7.0 FDISK.COM, Segment 0, Offset 0017h
;_NMSG_WRITE:
;		retn

; ----------------------------------------------------------------------------
; IBM PC-DOS 7.0 FDISK.COM, Segment 0, Offset 6D61h
;_aDBretaddr:
;		retn

; LSEEK.ASM (VCCRT1.ZIP) - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; Downloaded From : The Programmer's Corner (www.pcorner.com) - 01/12/2018 -

; Modified and simplified for NASM syntax by Erdogan Tan (07/12/2018)

;***
;long _lseek(fh,pos,mthd) - move the file pointer
;
;Purpose:
;	Moves the file pointer associated with fh to a new position.
;	The new position is pos bytes (pos may be negative) away
;	from the origin specified by mthd.
;
;	If mthd == SEEK_SET, the origin in the beginning of file
;	If mthd == SEEK_CUR, the origin is the current file pointer position
;	If mthd == SEEK_END, the origin is the end of the file
;
;ifdef _QWIN
;	Note:  Can't seek on QWIN file handles!
;endif
;
;Entry:
;	int fh - file handle to move file pointer on
;	long pos - position to move to, relative to origin
;	int mthd - specifies the origin pos is relative to (see above)
;
;Exit:
;	returns the offset, in bytes, of the new position from the beginning
;	of the file.
;	returns -1L (and sets errno) if fails.
;	Note that seeking beyond the end of the file is not an error.
;	(although seeking before the beginning is.)
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************

; 14/12/2018 (no need to _lseek for FDISK2.COM)

;; IBM PC-DOS 7.0 FDISK.COM, Segment 0, Offset 7C74h
;
;_lseek:
;
;	%define loword	bp-4
;	%define hiword	bp-2
;
;	%define fh	bp+4
;	%define	pos	bp+6
;	%define pos2	bp+8
;	%define mthd	bp+10
;
;		push	bp
;		mov	bp,sp
;		sub	sp,4
;		
;		mov	bx,[fh]		; file handle
;		; make sure handle is in OS file handle range
;		cmp	bx,_nfile
;		jb	short handle_ok
;
;	; _dosret must set DX:AX to -1L
;		;mov	ax,EBADF shl 8 + 0 ; file handle is out of range
;		mov	ax,900h
;		jmp	short seterr
;handle_ok:
;
;; negative offset - due to a DOS idiosyncracy, we have to check here to see
;; if the seek would move us to a location prior to the beginning of the
;; file, and, if so, return an error.
;
;		test	word [pos+2],8000h ; negative offset ?
;		jz	short doit	; not negative; just do lseek
;
;		cmp	byte [mthd],0	; byte 0 relative?
;		je	short negative	; yes, error
;
;		xor	cx,cx		; no, find current position
;		mov	dx,cx		; 0L
;		mov	ax,4201h ; mov ax,DOS_lseek shl 8 + 1
;		int	21h	; DOS -	2+ - MOVE FILE READ/WRITE POINTER (LSEEK)
;				; AL = method: offset from present location
;		jc	short errexit	; if error
;		test	byte [mthd],2
;		jnz	short findeof	; mthd is 2
;					; mthd is 1
;		add	ax,[pos]	; low word
;		adc	dx,[pos+2]	; hi word
;		jns	short doit	; net position is not negative; do lseek
;negative:				; net position is negative, return
;		;mov	ax,EINVAL shl 8 + 0 ; invalid value error
;		mov	ax,1600h
;seterr:
;		stc
;		jmp	short errexit
;findeof:				; mthd is relative to end of file
;		mov	[hiword],dx	; save present position (dx:ax)
;		mov	[loword],ax
;		mov	dx,cx		; 0L - cx is still zero from previous call
;		mov	ax,4202h ; mov	ax,DOS_lseek shl 8 + 2 ; find eof position
;		int	21h	; DOS -	2+ - MOVE FILE READ/WRITE POINTER (LSEEK)
;				; AL = method: offset from end of file
;		add	ax,[pos]	; low word
;		adc	dx,[pos+2]	; hi word
;		jns	short doit	; if non-negative, just do lseek
;
;	; net position would be negative, seek back to original location, then fail
;
;		mov	cx,[hiword]	; original offset
;		mov	dx,[loword]
;		;mov	ax,DOS_lseek shl 8 + 0 ; from beginning of file
;		mov	ax,4200h	; go back
;		int	21h	; DOS -	2+ - MOVE FILE READ/WRITE POINTER (LSEEK)
;				; AL = method: offset from beginning of	file
;		jmp	short negative
;
;	; seek to the specified location
;	; bx = file handle
;doit:
;		mov	dx,[pos]	; low(pos)
;		mov	cx,[pos+2]	; high(pos)
;		mov	al,[mthd]	; method
;		mov	ah,42h	; move file ptr
;		int	21h	; DOS -	2+ - MOVE FILE READ/WRITE POINTER (LSEEK)
;				; AL = method:
;				; 0-from beginnig,1-from current,2-from	end
;		jb	short errexit
;		;and	__osfile[bx],NOT FEOFLAG ; clear ^z flag if lseek succeeds
;		and	byte [_osfile+bx],~2 ; not 2
;errexit:
;		;jmp	__dosretax
;		;jmp	short _dosretax
;		;jmp	short DOSerror ; **errexit**

; ----------------------------------------------------------------------------

;***
;dosret.asm - map DOS error number to standard C (XENIX) error numbers; returns
;
;	Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
;
;Purpose:
;	Maps the standard DOS error number to C (XENIX) error number and
;	returns.  Used at the end of many runtime routines.
;
;*******************************************************************************

; 14/12/2018 (no need to _dosreto,_dosretax,Doseror,DOSnoerror for FDISK2.COM)

;;_dosret0:
;;		jc	short DOSerror	; set errors
;;
;;ret_0:
;;		xor	ax,ax		; clear errors
;;		mov	sp,bp
;;		pop	bp
;;		retn
;;_dosreturn:
;;		jnc	short ret_0
;;		push	ax
;;		call	maperror
;;		pop	ax	; set errno and return original DOS error	
;;		xor	ah,ah	; make sure ah is 0
;;		mov	sp,bp
;;		pop	bp
;;		retn
;
;_dosretax:
;		jnc	short DOSnoerror ; no errors	
;
;DOSerror:				; **errexit**
;		call	maperror 	; map error to standard C error	
;		mov	ax,-1		; return DX:AX = -1L
;		cwd
;DOSnoerror:
;		mov	sp,bp
;		pop	bp
;		retn

; ----------------------------------------------------------------------------
;_maperror - map DOS errors to standard XENIX errors

; 14/12/2018 (no need to _maperror for FDISK2.COM)

;_maperror:
;		xor	ah,ah	 ; clear ah
;		;call	maperror ; map the error	
;		;retn
;
;; XENIX error translation can be overridden - AH = new XENIX error code
;
;maperror:
;		mov	byte [_doserrno],al ; save dos error
;		or	ah,ah	; xenix error code override?	
;		jnz	short mapover ; yes, map the override values
;
;		cmp	byte [_dosvermajor],3 ; is this version 3.0 ?
;		jb	short chk2	; no, compare to 2.0 max error
;
;		;cmp	al,E_maxerr3	; yes, compare to 3.0 max error
;		cmp	al,22h
;		jnb	short maxerr2	; set bad error value
;		;cmp	al,E_sharerr	; is this a legit 3.0 error ?
;		cmp	al,20h
;		jb	short chk2	; no, see if 2.0 error
;
;; we get here only if we have an error value larger than is legit for
;; 2.0 (19), and is inrange for 3.0. Currently we only support the sharing
;; and locking violation errors for 3.0, but this will probably change in
;; the future. We will always map sharing and locking violations to EACCES
;; Xenix errors.
;		;mov	al,E_access	; yes, set for access error
;		mov	al,5
;		jmp	short inrange	; map it
;chk2:
;		;cmp	al,E_maxerr2	; no, compare to 2.0 max error
;		cmp	al,13h
;		jbe	short inrange	; error value ok
;maxerr2:
;		;mov	al,E_maxerr2	; error value bad, default to max error
;		mov	al,13h
;inrange:
;		;mov	bx,errtab
;		mov	bx,err_conv_tbl
;		xlat
;mapsave:
;		cbw
;		mov	[errno],ax
;		retn
;mapover:
;		mov	al,ah
;		jmp	short mapsave

; _GETBUF.ASM (VCCRT2.ZIP) - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; Modified and simplified for NASM syntax by Erdogan Tan (09/12/2018)

;***
;_getbuf() - Allocate a buffer and init stream data bases
;
;Purpose:
;	Allocates a buffer for a stream and inits the stream data bases.
;
;	[NOTE  1: This routine assumes the caller has already checked to make
;	sure the stream needs a buffer.
;
;	[NOTE 2: Multi-thread - Assumes caller has acquired stream lock, if
;	needed.]
;
;	[NOTE 3: The code now assumes that _iob[] and _iob2[] are near arrays
;	of the same element size.]
;
;Entry:
;	FILE *stream = stream to allocate a buffer for
;
;Exit:
;	void
;
;Exceptions:
;
;*******************************************************************************

; 14/12/2018 (no need to _getbuf for FDISK2.COM)

;_getbuf:
;	;%define gb_stream bp+4
;
;	; INPUT-> si = offset stream data address [ _getbuf(stream) ]
;
;		;push	bp
;		;mov	bp,sp
;		;push	si	
;
;		;mov	si,[gb_stream]
;
;		;mov	ax,BUFSIZ
;		mov	ax,512
;		push	ax
;		call	malloc		; malloc(BUFSIZ)
;		pop	cx		; clean off arg
;;**
;; Set:
;;	bx = _iob2 entry (aka stream2)
;; Note that by doing it here/now, we don't have to save/restore bx or di.
;
;		mov	bx,si
;		sub	bx,_iob
;		add	bx,_iob2
;;**
;; Now, check the return from malloc(). If it worked, installed the newly
;; malloc-ed buffer. Otherwise, install single character buffering.
;
;;if sizeD
;;		or	dx,dx		; NULL return?
;;else
;		or	ax,ax		; NULL return?
;;endif
;		jz	short _singlechar ;   yes, install single char buffer
;;**
;; Set stream->_flag and stream2->_bufsiz fields. Then, branch to code
;; to set other stream fields.
;
;		;or	[si]._flag,_IOMYBUF
;		or	byte [si+6],8
;		;mov	[bx]._bufsiz,BUFSIZ
;		mov	word [bx+2],512
;		jmp	short setfields
;_singlechar:
;		;or	[si]._flag,_IONBF
;		or	byte [si+6],4
;		;mov	[bx]._bufsiz,1
;		mov	word [bx+2],1
;;if sizeD
;;		mov	dx,ds
;;endif
;		;lea	ax,[bx]._charbuf
;		lea	ax,[bx+1]
;;**
;; Set the _ptr, _base and _cnt fields of stream. Note that, on entry, ax
;; (dx:ax in large data models) is a pointer to new stream buffer.
;
;setfields:
;
;;if sizeD
;;		mov	word ptr [si]._ptr + 2,dx
;;		mov	word ptr [si]._ptr,ax
;;		mov	word ptr [si]._base + 2,dx
;;		mov	word ptr [si]._base,ax
;;else
;		;mov	word ptr [si]._ptr,ax
;		mov	[si],ax
;		;mov	word ptr [si]._base,ax
;		mov	[si+4],ax
;;endif
;		;mov	word ptr [si]._cnt,0
;		mov     word [si+2],0
;done:
;		;pop	si
;		;pop	bp
;		retn

; NMALLOC.ASM (VCCRT1.ZIP) - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; Modified and simplified for NASM syntax by Erdogan Tan (09/12/2018)

; 14/12/2018 (no need to malloc,_nmalloc for FDISK2.COM)

;malloc:
;		;jmp	_nmalloc

;***
;void near *_nmalloc(size) - allocate a memory block in the near heap
;
;Purpose:
;	Allocates a memory block of at least size bytes in the near heap.
;	The block will be aligned for the storage of any type of object.
;
;	[NOTE: This routine assumes that the near heap is already
;	initialized (at startup).]
;
;	[MTHREAD NOTE: Multi-thread libraries do NOT support the
;	?varstck.obj functionality.  Thus, _STKHQQ can be referenced
;	directly (i.e., without using the tid data table).
;
;Entry:
;	unsigned size - size of memory block desired
;
;	CRTDLL:  ds:bx = near heap descriptor
;
;Exit:
;	returns pointer to allocated space or NULL if fails
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************

;_nmalloc:
;
;	%define incr	bp+4
;
;		push	bp
;		mov	bp,sp
;		push	si
;		push	di
;		mov	cx,[incr]	; cx = request block size
;		cmp	cx,0FFE8h ; _HEAP_MAXREQ ; cx > max. legal request size ?
;		ja	short error_rtn	; nope, try to get the memory
;
;; Try to get the requested block from the heap
;; cx = size
;getmem:
;		mov	bx,_nheap_desc	; ds:bx = heap descriptor
;		call	_searchseg	; get block
;		jnc	short ndone	; if success, we're all done
;
;; Did not find a suitable block in the heap.
;; Try to grow the heap.
;; cx = size, ds:bx = heap descriptor
;
;		call	_growseg	; try to grow the segment
;		jc	short error_rtn ; if error, return NULL
;
;; We successfully grew the heap. Try the search again.
;; (Rover pointer should be in a place that makes this search efficient.)
;; cx = size, ds:bx = heap descriptor
;
;		call	_searchseg	; search the heap segment
;		jnc	short ndone	; if success, take good return
;; Error return
;error_rtn:
;		xor	ax, ax
;		cwd
;		;jmp	short $+2
;; Common exit
;; (dx:ax = return value)
;ndone:
;		pop	di
;		pop	si
;		pop	bp
;		retn

; HEAP.INC
;
; --- Heap segment descriptor ---
;
; [***NOTE*** Some heap routines make assumptions about the layout of the
; heap descriptor. If this descriptor changes, some routines may break.]
;

; 09/12/2018

;struc _heap_seg_desc
; .checksum:	resw 1	; checksum area
; .flags:	resw 1	; flags word
; .segsize:	resw 1	; size of segment
; .start:	resw 1	; offset of first heap entry
; .rover:	resw 1	; rover offset
; .last:	resw 1	; offset to end-of-heap marker
; .nextseg:	resd 1	; far pointer to next _heap_seg_desc
; .prevseg:	resd 1	; far pointer to previous _heap_seg_desc
; .size:
;endstruc

; SEARCHSG.ASM - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------

;***
; _searchseg - Search a heap segment
;
;Purpose:
;
; This routine scans through the supplied heap segment looking for a
; block big enough to satisfy the size request. Contiguous free blocks
; are coalesced as necessary.
;
; The search is done in two parts:
;
;	(1) First, we search from the current rover pointer to the end
;	of the heap segment.
;
;	(2) Second, we search from the start of the heap segment to the
;	rover pointer (being careful to overlap so that all free blocks
;	are coalesced as much as possible).
;
;Entry:
;	cx = requested size
;	     [If requested size = _HEAP_COALESCE, then we simply coalesce
;	     the heap segment and return with carry set]
;	ds:bx = address of heap descriptor
;
;Exit:
;	Success:
;		carry = clear
;		dx:ax = address of block
;	Failure:
;		carry = set
;
;Uses:
;	ax, dx, si, di
;
;Preserved:
;	ds:bx, cx
;
;Exceptions:
;	If we detect an inconsistent heap, we return NULL and set errno
;	to ***???***.
;
;*******************************************************************************

; 14/12/2018 (no need to _searchseg for FDISK2.COM)
;
;_searchseg:
;		inc	cx
;		and	cl,0FEh ; ~1 ; not 1 ; round size up to even number

; first_pass -
; On the first pass through the heap, we will search from the current
; rover pointer to the end of the heap. Set the 'end-of-search' pointer
; such that the search will not end until we encounter the _HEAP_END flag.
;
; Entry:
;			BX = heap descriptor
;			CX = requested size
;
; Exit Paths:
;		check_block
;			SI = pointer where the heap search should start
;			DI = 0 (pointer to last free block examinted)
;			BX = pointer to _HEAP_END (where search should end)
;			CX = requested size
;			TOS = heap descriptor

;first_pass:
;		push	bx		; save heap descriptor
;		cld			; go forward when loading
;		;mov	si,[bx].rover	; si = pointer to start of search
;		mov	si,[bx+8]
;		;mov	bx,[bx].last	; bx = pointer to end-of-heap marker
;		mov	bx,[bx+10]
;		xor	di,di		; zero out di
;		jmp	short check_block ; jump into loop

; next_pass -
; We have completed a pass through the heap.
;	(1) Update .last pointer if necessary.	The only way this could happen
;	is if we coalesced the last block with one before it.  Thus, we only
;	need a pointer to the last free block we examined to determine if
;	.last must be updated.
;	(3) Determine which pass has been completed by checking the lower
;	order bit of the end-of-search pointer.
;	(3) If we just finished the second pass, return an error.
;	(4) Else, start up a heap search from the start of the heap to the
;	rover pointer. Use rover - 1 as the value of the end-of-search pointer
;	since it works are well as rover does and it makes it easy to
;	determine which pass we have completed.
;
; Entry:
;			BX = end-of-search pointer = pointer to end-of-heap
;			     marker (after first pass) or rover - 1 (after
;			     second pass)
;			CX = requested size
;			DI = 0 or pointer to last free block examined + 2
;			TOS = heap descriptor
;
; Exit Paths:
;		failure1 (end of search, block not found)
;			TOS = heap descriptor
;		failure2 (end of search, block not found)
;			BX = heap descriptor
;		check_block (start up the second heap search)
;			SI = pointer where the heap search should start
;			DI = 0 (pointer to last free block examinted)
;			BX = end-of-search pointer = rover - 1
;			CX = requested size
;			TOS = heap descriptor

;next_pass:
;		mov	ax,bx		; ax = end-of-search pointer
;		pop	bx		; bx = heap descriptor

; see if we need another pass through the heap

;check_pass:
;		test	al,1		; test low order bit on eos pointer
;		jnz	short failure2	; bit was set, we're done

; set up for second pass through the heap

;		push	bx			; save heap descriptor
;		;mov	si,[bx].start		; si = start search ptr = start
;		mov	si,[bx+6]
;		;mov	bx,[bx].rover		; bx = end-of-search ptr = rover
;		mov	bx,[bx+8]
;		cmp	bx,si			; start == rover ??
;		je	short failure1		; if so, no need to try another pass
;		dec	bx			; end-of-search pointer = rover - 1
;		xor	di,di			; zero out di
;
;		jmp	short check_block	; jump into loop

; ---------- Start of segment search loop ----------
;
; The following registers are not changed by any code in the segment
; search loop:
;			BX = end of search pointer
;			CX = requested size
;			TOS = heap descriptor
;
; next_block -
; See if we're at the end of the segment search loop. If not, move
; on to the next block.
;
; Entry:
;			AX = header of last block examined (not free)
;			SI = pointer to last block examined (not free) + 2
;			DI = 0 or pointer to last free block examined + 2
;
; Exit Paths:
;		next_pass (first pass through heap failed)
;			DI = 0 or pointer to last free block examined + 2
;
;		check_block (info for next block is loaded into AX and SI)
;			AX = header for (new) block to be checked
;			SI = pointer to (new) block to be checked + 2
;			DI = 0 or pointer to last free block examined + 2

;EVEN

;align 2
;
;next_block:
;		lea	dx,[si-2]	; get current ptr
;		cmp	dx,bx		; current ptr >= end-of-search ptr ?
;		jae	short next_pass	; yes, done with this pass
;
;		add	si,ax		; bump pointer to next block
;		jc	short heap_toast ; *** inconsistent heap ***
;		;fall thru

; check_block -
; Check to see if the current block is free.
;
; Entry:
;			SI = pointer to current block
;			DI = 0 or pointer to last free block examined + 2
;
; Exit Paths:
;		next_block (if current block is not free)
;			AX = current block (not free) header
;			SI = pointer to current block + 2
;			DI = 0 or pointer to last free block examined + 2
;		coal_loop (if current block is free)
;			AX = current block (free) header
;			SI, DI = pointers to current block + 2
;

;check_block:
;		lodsw			; ax = get the first block header
;		test	al,1		; is it free?
;		jz	short next_block ; no, go try the next block
;		mov	di,si
;	;fall thru

; coal_loop -
; Check to see if current block is big enough. If not, try to
; coalesce proceeding free block with the current block. Loop until we get
; get a big enough block or cannot coalesce anymore.
;
; Entry:
;			AX = current block header
;			SI, DI = pointers to current block + 2
;
; Exit Paths:
;		blockfound (current block is big enough)
;			AX = size of current block
;			SI, DI = pointers to current block + 2
;		next_block (failure)
;			DX = size of current block
;			DI = pointer to current block + 2
;			AX = header of next block (not free)
;			SI = pointer to next block (not free) + 2

;;EVEN
;
;coal_loop:
;		dec	ax		; subtract free flag
;		cmp	ax,cx		; is it big enough?
;		jae	short blockfound ;   yep, go finish up
;		add	si,ax		; point to header of next block
;		jc	short heap_toast ; *** inconsistent heap ***
;		mov	dx,ax		; save size of original block in DX
;		lodsw			; get header of next block into AX
;		test	al,1		; is it free?
;		jz	short next_block ;   no, go try the next block
;		add	ax,dx		; coalesce
;		add	ax,2		; add in header space
;		mov	si,di		; reset SI to block + 2
;		mov	[si-2],ax	; update block size
;		jmp	short coal_loop

; ---------- End of segment search loop ----------

; heap_toast -
; We detected an internal consistency error in the heap.
; Set errno and return an error to the user.

;heap_toast:
;		mov	ax,ax  ; place where we can place a breakpoint for now...
;		; fall thru for now

; failure1, failure2 -
; We could not find a big enough block in the heap.
;
;    (1) Set the rover pointer to the beginning of the heap since
;	 the rover block may have been coalesced (i.e., the rover
;	 pointer may no longer point to valid memory).
;
;	*** I THINK THIS IS WHAT THE OLD HEAP IS DOING.
;	*** DO WE WANT TO DO THIS OR CAN WE SOMEHOW MOVE THE
;	*** ROVER BACK TO THE MERGED BLOCK, IF NECESSARY.
;
;    (2) Return carry set to caller.
;
; Entry:
;		failure1
;			TOS = heap descriptor
;
;		failure2
;			BX = heap descriptor
;			CX = requested size
;
; Exit Paths:
;		Return to caller (via done)
;			Carry = set
;			DS:BX = heap descriptor
;			CX = requested size

;failure1:
;		pop	bx		; bx = heap descriptor
;failure2:
;		;mov	ax,[bx].start	; set rover = start
;		mov	ax,[bx+6]
;		;mov	[bx].rover,ax
;		mov	[bx+8],ax
;		stc			; carry set = error
;		jmp	short _done

; blockfound -
; Found a block that fullfills the caller's request.
;	(1) Transform the block found into an allocated block that
;	exactly satisfies the allocation request (in CX) and a leftover,
;	free block.
;	(2) Update the rover and end pointers, as needed.
;	(3) Return pointer to the allocated block to the caller.
;
; Entry:
;			AX = size of (free) block (AX >= CX)
;			SI, DI = pointers to block + 2
;			CX = requested size
;			ZF = 1 iff the block is an exact fit (i.e., AX == CX)
;			     0 otherwise
;			TOS = heap descriptor
;
; Exit Paths:
;		Return to caller
;			Carry = clear
;			DX:AX = pointer to allocated block
;			DS:BX = heap descriptor
;			CX = requested size

;blockfound:
;		pop	bx		; get heap descriptor
;
;		mov	[si-2],cx	; update header
;		je	short set_rover	; jump if block size = request size
;
;		add	di,cx		; point to leftover piece
;		sub	ax,cx		; compute header for leftover piece
;		dec	ax		; as a free block
;		mov	[di],ax 	; make it a free block
;		sub	di,cx		; update rover
;set_rover:
;		add	di,cx		; point to leftover piece
;set_rover1:
;		;mov	[bx].rover,di	; update rover
;		mov	[bx+8],di
;		mov	ax,si		; return pointer to allocated block
;		mov	dx,ds
;		clc			; carry clear = success
;; Common exit
;_done:
;		retn			; explicit return

; HEAP.INC

; _heap_seg_desc.flags bit offsets

;_HEAP_MODIFY	equ	01h		; heap segment size can be modified
;_HEAP_FREE	equ	02h		; heap segment may be freed up to OS
;_HEAP_NEAR	equ	04h		; heap segment is part of the near heap
;_HEAP_BASED	equ	08h		; heap segment is part of the based heap

; --- General Use Heap Constants ---

;_HEAP_END	equ	0FFFEh		; End-of-heap flag
;_HEAP_COALESCE	equ	0FFFEh		; Coalesce segment value
;_HEAP_GROWSEG	equ	2000h		; Default heap seg growth increment (8K)
;;_HEAP_MAXREQ	equ	0FFFCh - (_heap_seg_desc.size)	; Max heap request size
;_HEAP_MAXREQ	equ	0FFFCh - 14h ; 0FFE8h
;;_HEAP_MINSEG	equ	((_heap_seg_desc.size) + 4) ; Min size heap segment
;_HEAP_MINSEG	equ	20+4		; Min size heap segment

; GROWSEG.ASM - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------

;***
; _growseg - Grow a heap segment
;
;Purpose:
;	Grow a heap segment to increase the amount of space
;	available for allocations.
;
;	Notes:
;	(1) The caller has already determined that the block size cannot
;	be allocated in the current heap and heap segment growth is necessary.
;	(2) The size argument is the block allocation size requested
;	by the user.  The supplied size is NOT the heap increment.
;	(that size is determined by this routine).
;
;Entry:
;	ds:bx = heap segment descriptor
;	cx = size of block requested
;
;Exit:
;	Success:
;		carry = clear
;	Failure:
;		carry = set
;
;Uses:
;	es
;
;Preserves:
;	cx, di
;
;*******************************************************************************

; 14/12/2018 (no need to _growseg for FDISK2.COM)

;_growseg:
;		push	cx		; save caller's cx
;		push	di		; save caller's di

; First, see if it is legal to grow this segment.
; ds:bx = heap descriptor

;		;test	byte ptr [bx].flags,_HEAP_MODIFY
;		test	byte [bx+2],1
;		jz	short grow_error_rtn ; return error if modify bit clear

; Calculate how much we need to grow the segment by to satisfy the user's
; request.
; cx = size of block requested

;		call	_findlast	; si = pointer to last heap entry
;		mov	di,si		; save pointer in di for later use
;		mov	ax,[si] 	; length of last entry
;		test	al,1		; is it free ??
;		jz	short grow_calc_length ; no
;		sub	cx,ax		; reduce requested length by free size
;		dec	cx		; adjust for inc' below (only one dec
;					; because free bit is set...)
;grow_calc_length:
;		inc	cx
;		inc	cx		; add header field to size
;
;		;mov	si,[bx].segsize ; si = current size of segment
;		mov     si,[bx+4]
;		or	si,si		; already 64 Kb ??
;		jz	short grow_error_rtn ; yep, go return an error
;		add	cx,si		; cx = desired new size of segment
;					; (not yet rounded by _amblksiz)
;		jnc	short grow_size_ok ; legal segment size

; Special code to handle case of cx = 0 (i.e., requested new segment size is
; exactly 64 K). This amounts to taking a shortcut to calling _incseg.

;		xor	ax,ax		; set newsize request to 64 Kb
;		mov	dx,0FFF0h	; indicate paragraph increment
;		jcxz	grow3		; shortcut!
;		jmp	short grow_error_rtn

;	; Determine the optimal heap increment size.
;grow_size_ok:
;		push	ss		; es = DGROUP
;		pop	es

;		;mov	ax,[es:_amblksiz] ; get increment size
;	;;*** OPTIMIZATION: CODE WILL WORK WITHOUT THE FOLLOWING 2 INSTRUCTIONS
;		;;cmp	ax,_HEAP_GROWSEG ; compare to default increment
;		;cmp     ax,2000h
;		;je	short grow1	; if equal, use the default
;		;;fall thru
;
;		mov	ax,2000h ; 09/12/2018

; Compute the heap segment increment size.
; That is, 2**N, where 2**N >= _amblksiz > 2**(N-1).
; Test the values 2**(N-1), in descending order, until one is found that
; is less than _amblksiz.  Then, shift the value left to get 2**N.
; ax = _amblksiz

;		mov	dx,8000h	; start by testing 2**15
;grow_next_size:
;		cmp	dx,ax		; is current 2**(N-1) smaller?
;		jb	short grow0	;  yep, dx = 2**(N-1)
;		shr	dx,1		; di = next lower power of 2
;		jnz	short grow_next_size ; try again...
;		jmp	short grow_paragraph ; use increment size = paragraph

; --- grow ---
; Try to grow the segment.
;  (1) First, try to grow the segment by the optimal size
;      (rounded up to an _amblksiz boundary).
;  (2) If that fails, try to grow by just enough to fullfill the request
;      (rounded up to a paragraph boundary).
;
;  [NOTE: We will try to grow the segment twice AT MOST.]
;
; cx = grow size necessary to fulfill caller's request
; si = current size of heap segment
; dx = 2**(N-1)

;;grow0:
;;		cmp	dx,08h			; will increment be < paragraph ??
;;		jb	short grow_paragraph	; yes, use paragraph increment
;;		shl	dx,1			; dx = 2**N (if 0, that's ok)
;;		mov	ax,dx			; ax = (power of 2)
;;

;		; ax = heap seg increment size
;grow1:
;		dec	ax			; ax = (power of 2) - 1
;		mov	dx,ax			; save for later
;		add	ax,cx			; round up to next highest multiple
;						; of (power of 2)
;		jnc	short grow2		; overflow ??
;		xor	ax,ax			; yes, grow to max seg size (0 = 64kb)
;grow2:
;		not	dx			; make ((power of 2) - 1) a mask
;		and	ax,dx			; ax is now rounded up
;grow3:
;		push	dx			; save increment mask
;		call	_incseg 		; *** try to grow the segment ***
;		pop	dx			; restore increment mask
;		jnc	short grow_good_rtn	; Good return on success
;
;		cmp	dx,0FFF0h		; error, was increment == paragraph ??
;		je	short grow_error_rtn	; yes, no more we can do (return error)
;
;grow_paragraph:				; try an increment size of a paragraph
;		mov	ax,10h			; ax = paragraph size
;		jmp	short grow1		; try again

;  --- Error Return ---

;grow_error_rtn:
;		stc				; carry set = error
;		jmp	short grow_done		; return the error

; --- Good Return ---
;
; We successfully grew the heap segment.
; Link the new free block into the heap and update pointers, _HEAP_END, etc.
; ax = new segment size
; ds:bx = heap descriptor
; di = pointer to previous last heap entry

;grow_good_rtn:
;		mov	dx,ax			; dx = new size
;		;sub	dx,[bx].segsize 	; dx = segment increment
;		sub	dx,[bx+4]
;		;mov	[bx].segsize,ax 	; update segment size field
;		mov     [bx+4],ax
;
;		;mov	[bx].rover,di		; rover = previous last entry (in di)
;		mov	[bx+8],di
;
;		;mov	si,[bx].last		; si = pointer to old _HEAP_END
;		mov	si,[bx+10]
;		dec	dx			; dx = length of block marked free
;		mov	[si],dx 		; put length of new block in heap
;
;		inc	dx			; dx = length of new block + header
;		add	si,dx			; si = points to new end of heap
;		;mov	[si],_HEAP_END		; mark new end of heap
;		mov     word [si],0FFFEh
;		;mov	[bx].last,si		; update .last pointer
;		mov	[bx+10],si
;	
;	;fall thru (not that the carry flag was cleared by the add above!)

; Common Return
; ax = return value

;grow_done:
;		pop	di			; restore caller's di
;		pop	cx			; restore caller's cx
;		retn

; _incseg - Increment the segment
;
;Purpose:
;	This routine issues the OS call that actually grows/shrinks the
;	heap segment.
;
;	NOTE: This routine is meant for internal use only.
;
;	DOS NOTE: The 'segsize' value in the near heap descriptor
;	indicates the top of the heap, NOT the current size of DGROUP.
;	Thus, we must check the REAL size of DGROUP to see if we
;	really need to grow the heap (_asizds).   Also, growing
;	the near heap must be based on the _psp segment, not DGROUP
;
;ifdef	_WINDOWS
;	WINDOWS NOTE:  Do to a Windows restriction/bug, you should not
;	grow a segment to exactly 64K in standard mode.
;endif
;
;Entry:
;	ax = new segment size (0 indicates a segment size of 64 Kb)
;	     [***NOTE***: This value MUST be rounded up to a paragraph
;	     boundary by the caller.]
;	ds:bx = heap descriptor
;Exit:
;	Success:
;		carry = clear
;		ax = new segment size (0 indicates a segment size of 64 Kb)
;	Failure:
;		carry = set
;
;Preserves:
;	ds:bx, cx, di
;
;Uses:
;	ax, dx, si, es
;
;Exceptions:
;
;*******************************************************************************

;_incseg:
;		mov	dx,ax		; save requested size
;
;; --- Special near heap code ---
;;
;; Growing:  We don't have to issue a call if there's room between heap and
;; _asizds.
;;
;; Shrinking:  If the new size is less than the current size, issue the call to
;; shrink the segment.  Also, if the new size is EQUAL to the current size,
;; issue the call since we want to free up unused DGROUP above the heap but
;; below _asizds.  [Note: _Minseg() has already determined that an OS call is
;; necessary in this case.]
;
;		;test	byte ptr [bx].flags,_HEAP_NEAR ; near heap descriptor ?
;		test	byte [bx+2],4
;		jz	short do_oscall1 ; nope
;
;		dec	dx		; dx = new segsize - 1
;		;mov	si,[bx].segsize ; get current segment size
;		mov	si, [bx+4]
;		dec	si		; cx = current segsize - 1
;		cmp	dx,si		; are we shrinking the segment ??
;		jbe	short do_oscall	; yes, issue the system call
;
;		cmp	[bx-2],dx	; _asizds > current segsize ??
;		jae	short incseg_ok	; yup, no need to issue system call
;do_oscall:
;		inc	dx			; nope, restore dx
;
;; Issue the system call
;; ax = dx = desired size

;do_oscall1:
;		push	bx		; save heap descriptor
;		push	cx		; save cx value
;		mov	si,ds		; es = si = heap segment
;		mov	es,si
;		mov	cl,4		; cl = shift count
;		shr	ax,cl		; ax = paragraph count
;		jnz	short do_oscall2 ; if ax != 0, use it
;		mov	ax,1000h	; if ax == 0, set it to 1000h
;					; paragraphs (i.e., 64 KB)
;do_oscall2:
;		;test	byte ptr [bx].flags,_HEAP_NEAR ; near heap descriptor ?
;		test    byte [bx+2],4
;		jz	short do_oscall3 ; nope, issue the system call
;
;		; use _psp segment, not DGROUP
;		add	ax,si		; yes, add in DGROUP seg
;		mov	bx,[_psp]	; PSP base
;		sub	ax,bx		; subtract PSP base
;		mov	es,bx		; es = PSP base
;do_oscall3:				; ax = new size (para) / es = heap seg
;		mov	bx,ax		; bx = new segment size (para)
;		;callos	setmem		; set the heap segment size
;
;		mov	ah,4Ah
;		int	21h	; DOS - 2+ - ADJUST MEMORY BLOCK SIZE (SETBLOCK)
;				; ES = segment address of block to change
;				; BX = new size in paragraphs
;		pop	cx		; restore cx
;		pop	bx		; restore heap descriptor
;		jc	short incseg_done ; error - carry is set
;		;fall thru
;
;; --- Good return ---
;
;		mov	ax,dx			; return size
;		;test	byte ptr [bx].flags,_HEAP_NEAR ; near heap descriptor ?
;		test	byte [bx+2],4
;		jz	short incseg_ok	; nope, return
;
;		; Near heap so update _asizds.
;		; Use offset from _nheap_desc so DLL will work
;		dec	dx			; dx = dgroup - 1
;		mov	[bx-2],dx		; update _asizds
;incseg_ok:				; ax = new seg size
;		clc				; carry clear on success
;		jmp	short incseg_done	; common return
;
;; --- Error return ---
;
;incseg_err:
;		;stc				; carry set on error
;
;; --- Common return ---
;
;incseg_done:
;		retn

;***
; _findlast - Find the last entry in a heap descriptor segment
;
;Purpose:
;	Given a heap descriptor, return a pointer to the last
;	entry in that heap segment.
;
;Entry:
;	ds:bx = heap segment descriptor
;
;Exit:
;	si = pointer to header of last entry in that segment
;
;Uses:
;	ax
;
;Preserves:
;	bx, cx, dx, di, ds, es
;
;Exceptions:
;
;*******************************************************************************

; 14/12/2018 (no need to _findlast for FDISK2.COM)

;_findlast:
;		push	di		; save caller's di
;
;		;mov	si,[bx].rover	; si = rover pointer
;		mov	si,[bx+8]
;		;cmp	si,[bx].last	; does .rover = .last?
;		cmp	si,[bx+10]
;		jne	short lastloop	; no, go begin search
;		;mov	si,[bx].start	; yes, must begin search at .start
;		mov	si,[bx+6]
;lastloop:
;		lodsw			; ax = size of heap entry
;		;cmp	ax,_HEAP_END	; end of heap ?
;		cmp     ax,0FFFEh
;		je	short lastdone	; yup, finish up
;		mov	di,si		; save current pointer
;		;and	al,not 1	; nope, mask off free/use bit
;		and	al,0FEh
;		add	si,ax		; si = pointer to next entry
;		;jc	heaptoast	; *** error, heap is toasty... ***
;		jmp	short lastloop	; try next one
;lastdone:				; found the end
;		dec	di
;		dec	di		; back up saved pointer to header
;		mov	si,di		; si = pointer to last heap entry header
;
;		pop	di		; restore caller's di
;		retn

; ----------------------------------------------------------------------------
; input.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 09/12/2018)

;char get_num_input(input_default,max_num,row,col)
;
;char      max_num;
;unsigned  row;
;unsigned  col;
;char	   input_default;
;
;BEGIN
;
;    char  input;
;
;    /* SR;9/25/89; Initialize this on entry */
;    char  default_used = FALSE;
;    char  input_value;
;
;    char            attribute;
;    char far        *attribute_ptr = &attribute;
;    char far *input_ptr = &input;
;
;    if (mono_flag == TRUE)
;       attribute = HIWHITE_ON_BLACK; /*C09*/
;    else
;       attribute = HIWHITE_ON_BLUE;  /*C09*/
;
;    /* print default entry if there is one */
;    if (input_default != c(NUL))                                 /* AC000 */
;
;       BEGIN
;        default_used = TRUE;
;        /* position the cursor */
;        VIOSETCURPOS(row,col,u(0));                              /* AC000 */
;
;        /* Display the default character */
;
;        input = c(input_default+'0');
;        VIOWRTCHARSTRATT(input_ptr,u(1),row,col,attribute_ptr,u(0));
;       END
;
;    /* Assume bad input */
;    valid_input = FALSE;
;
;    /* Loop until we get good stuff */
;    while (valid_input == FALSE)
;        BEGIN
;
;        /* position the cursor */
;        VIOSETCURPOS(row,col,u(0));                             /* AC000 */
;
;        /* Flush the keyboard buffer and get the next pressed key */
;        input = get_char_input();
;
;        /* Do world trade get country information */
;        input = dos_upper(input);                          /* AN000 */
;
;        /* Go handle different inputs */
;        switch(input)
;           BEGIN
;            case ESC:
;                BEGIN
;                 valid_input = TRUE;
;                 break;
;                END
;
;            case CR:
;                BEGIN
;                /* Set the input to the default if there is one there */
;                if (default_used)
;                    BEGIN
;                     if (input_default != c(NUL))
;                        BEGIN
;                         input_value = input_default+'0';
;                        END
;                     else
;                        BEGIN
;                         /* Make the enter look like a blank for error message */
;                         input_value = c(' ');                 /* AC000 */
;                        END
;                    END
;                /* See if it is digit and less or equal to max */
;                if ( (isdigit(input_value))         &&
;                     (input_value <= (max_num+'0')) &&
;                     (input_value != c('0')) )
;                    BEGIN
;                     valid_input = TRUE;
;                     input = input_value;
;                    END
;                else
;                    BEGIN
;                    if (isdigit(input_value))
;                       BEGIN
;                        /* Setup error message */
;                        insert[0] = input_value;
;                        insert[1] = c('1');                    /* AC000 */
;                        insert[2] = c('-');                    /* AC000 */
;                        insert[3] = max_num+'0';
;                        display(error_23);
;                       END
;                    else
;                       BEGIN
;                        insert[0] = c('1');                    /* AC000 */
;                        insert[1] = c('-');                    /* AC000 */
;                        insert[2] = max_num+'0';
;                        display(error_31);
;                       END
;                    END
;                break;
;                END
;
;            default:
;               BEGIN
;                /* SR; 10/2/89; If Ctrl-C, display blank and beep */
;                if ( (isdigit(input))         &&                        /*C16*/
;                     (input <= (max_num+'0')) &&                        /*C16*/
;                     (input != c('0')) )                                /*C16*/
;                    clear_screen(u(23),u(0),u(23),u(79));               /*C16*/
;                else                                                    /*C16*/
;                    {                                                   /*C16*/
;                    if (isdigit(input))                                 /*C16*/
;                        {                                               /*C16*/
;                        /* Setup error message */                       /*C16*/
;                        insert[0] = input;                              /*C16*/
;                        insert[1] = c('1');                             /*C16*/
;                        insert[2] = c('-');                             /*C16*/
;                        insert[3] = max_num+'0';                        /*C16*/
;                        display(error_23);                              /*C16*/
;                        }                                               /*C16*/
;                    else                                                /*C16*/
;                        {                                               /*C16*/
;                        insert[0] = c('1');                             /*C16*/
;                        insert[1] = c('-');                             /*C16*/
;                        insert[2] = max_num+'0';                        /*C16*/
;                        display(error_31);                              /*C16*/
;                        }                                               /*C16*/
;                    input = c(' ');                                     /*C16*/
;                    }                                                   /*C16*/
;                VIOWRTCHARSTRATT(input_ptr,u(1),row,col,attribute_ptr,u(0)); /*C16*/
;                default_used = FALSE;
;                input_value = input;
;                break;
;                END
;            END
;        END
;     return(input);
;END

get_num_input:
	;char get_num_input(input_default,max_num,row,col)

	%define input_value	bp-16
	%define gni_attr_ptr	bp-14
	;%define gni_attr_ptr_2 bp-12
	%define default_used	bp-10
	%define gni_input_ptr	bp-8
	;%define gni_input_ptr_2 bp-6
	%define gni_attribute	bp-4
	%define gni_input	bp-2

	%define input_default	bp+4
	%define gni_max_num	bp+6
	%define gni_row		bp+8
	%define gni_column	bp+10

		push	bp
		mov	bp,sp
		sub	sp,16

		;/* Initialize this on entry */
		mov	byte [default_used],0
		
		lea	ax,[gni_attribute]
		mov	[gni_attr_ptr],ax
		;mov	[gni_attr_ptr_2],ss
		mov	[gni_attr_ptr+2],ss
		lea	cx,[gni_input]
		mov	[gni_input_ptr],cx
		;mov	[gni_input_ptr_2],ss
		mov	[gni_input_ptr+2],ss

		;if (mono_flag == TRUE)
		;       attribute = HIWHITE_ON_BLACK;
		;    else
		;       attribute = HIWHITE_ON_BLUE;

		cmp	byte [mono_flag],1
		jnz	short gni_1
		mov	byte [gni_attribute],0Fh ; HIWHITE_ON_BLACK
		jmp	short gni_2
gni_1:
		mov	byte [gni_attribute],1Fh ; HIWHITE_ON_BLUE
gni_2:
		;/* print default entry if there is one */
		;if (input_default != c(NUL))  

		cmp	byte [input_default],0
		je	short gni_3
		mov	byte [default_used],1

		;/* position the cursor */
		;VIOSETCURPOS(row,col,u(0));   

		;push	word [gni_row]
		;push	word [gni_column]
		;sub	ax,ax ; 0
		;push	ax
		; 09/12/2018
		mov	dh,[gni_row]
		mov	dl,[gni_column]
		call	VIOSETCURPOS

		;/* Display the default character */
		;input = c(input_default+'0');
		;VIOWRTCHARSTRATT(input_ptr,u(1),row,col,attribute_ptr,u(0));

		mov	al,[input_default]
		add	al,'0'
		mov	[gni_input],al
		;push	word [gni_input_ptr_2]
		push	word [gni_input_ptr+2]
		push	word [gni_input_ptr]
		mov	ax,1
		push	ax
		push	word [gni_row]
		push	word [gni_column]
		;push	word [gni_attr_ptr_2]
		push	word [gni_attr_ptr+2]
		push	word [gni_attr_ptr]
		; 09/12/2018
		;sub	ax,ax ; 0
		;push	ax
		call	VIOWRTCHARSTRATT
gni_3:
		;/* Assume bad input */
		; 15/12/2018
		mov	byte [valid_input],0
gni_4:
		;/* Loop until we get good stuff */
		;while (valid_input == FALSE)

		;/* position the cursor */
		;VIOSETCURPOS(row,col,u(0)); 

		;push	word [gni_row]
		;push	word [gni_column]
		;sub	ax,ax ; 0
		;push	ax
		; 09/12/2018
		mov	dh,[gni_row]
		mov	dl,[gni_column]
		call	VIOSETCURPOS

		;/* Flush the keyboard buffer and get the next pressed key */
		;input = get_char_input();
	
		call	get_char_input
		;mov	[gni_input],al
	
		;/* Do world trade get country information */
		;input = dos_upper(input);
		; 15/12/2018                      
		;push	ax
		call	dos_upper
		;pop	bx
		mov	[gni_input],al
switch_gni_input:
		;/* Go handle different inputs */	
		;switch(input)
		
		;cbw
		;sub	ax,0Dh  ; CR ?
		sub	al,0Dh
		jz	short case_gni_CR  ; yes
		;sub	ax,0Eh  ; 0Dh+0Eh = 1Bh  ; ESC ? 
		sub	al,0Eh
		jz	short case_gni_ESC ; yes

		; /* If Ctrl-C, display blank and beep */
		; if ((isdigit(input))  

		; 02/01/2019
		;mov	al,[gni_input]
		;cbw
		;mov	bx,ax
		xor	bh,bh
		mov	bl,[gni_input]
		test	byte [isdigit+bx],4
		;jz	short gni_not_digit
		jz	gni_12 ; 02/01/2019
		mov	al,[gni_max_num]
		cbw
		add	ax,'0'
		cmp	ax,bx
		jl	short gni_not_digit
		;cmp	byte [gni_input],'0'
		cmp	bl,'0' ; 02/01/2019
		jne	short gni_5
gni_not_digit:
		jmp	gni_11
gni_5:
		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	cx,cx
		push	cx
		push	ax
		call	clear_screen
		;add	sp,8
		jmp	gni_14
case_gni_ESC:
		mov	byte [valid_input],1
		;jmp	case_gni_break
		jmp	gni_15 ; 15/12/2018
case_gni_CR:
		;/* Set the input to the default if there is one there */
                ;if (default_used)
		
		cmp	byte [default_used],0
		je	short gni_7

		;if (input_default != c(NUL))

		cmp	byte [input_default],0
		je	short gni_6

		;input_value = input_default+'0';
		mov	al,[input_default]
		add	al,'0'
		mov	[input_value],al
		jmp	short gni_7
gni_6:
		;/* Make the enter look like a blank for error message */
		;input_value = c(' '); 
		mov	byte [input_value],' '
gni_7:
		;/* See if it is digit and less or equal to max */
                ;if ( (isdigit(input_value))         &&
                ;     (input_value <= (max_num+'0')) &&
                ;     (input_value != c('0')) )

		; 02/01/2019
		;mov	al,[input_value]
		;cbw
		;mov	bx,ax
		sub	bh,bh
		mov	bl,[input_value]
		test	byte [isdigit+bx],4
		;jz	short gni_8
		jz	short gni_9

		mov	al,[gni_max_num]
		cbw
		add	ax,'0'
		cmp	ax,bx
		jl	short gni_8
		;cmp	byte [input_value],'0'
		cmp	bl,'0' ; 02/01/2019
		je	short gni_8

		;valid_input = TRUE;
		;input = input_value;

		mov	byte [valid_input],1
		;mov	al,[input_value]
		mov	al,bl ; 02/01/2019
		;mov	[gni_input],al
		;jmp	case_gni_break
		jmp	gni_16 ; 15/12/2018
gni_8:
		;if (isdigit(input_value))

		; 02/01/2019
		;mov	al,[input_value]
		;cbw
		;mov	bx,ax
		;test	byte [isdigit+bx],4
		;jz	short gni_9

		;/* Setup error message */
		;insert[0] = input;
		;insert[1] = c('1');
		;insert[2] = c('-');
		;insert[3] = max_num+'0';
		;display(error_23);      
		
		;mov	[insert],al
		mov	[insert],bl ; 02/01/2019
		mov	byte [insert+1],'1'
		mov	byte [insert+2],'-'
		mov	al,[gni_max_num]
		add	al,'0'
		mov	[insert+3],al
		;push	word [error_23_seg]
		push	ds
		push	word [error_23_off]
		jmp	short gni_10
gni_9:
		;else 
		 ;insert[0] = c('1');
		 ;insert[1] = c('-');
		 ;insert[2] = max_num+'0';
		 ;display(error_31);
		
		mov	byte [insert],'1'
		mov	byte [insert+1],'-'
		mov	al,[gni_max_num]
		add	al,'0'
		mov	byte [insert+2],al
		;push	word [error_31_seg]
		push	ds
		push	word [error_31_off]
gni_10:
		call	display
		;pop	bx
		;pop	bx
		;jmp	short case_gni_break
		jmp	gni_4 ; 15/12/2018
gni_11:
		;else
		; insert[0] = c('1');
		; insert[1] = c('-');
		; insert[2] = max_num+'0';
		; display(error_31);

		; 02/01/2019
		;mov	al,[gni_input]
		;cbw
		;mov	bx,ax
		;test	byte [isdigit+bx],4
		;jz	short gni_12

		;mov	[insert],al
		mov	[insert],bl ; 02/01/2019
		mov	byte [insert+1],'1'
		mov	byte [insert+2],'-'
		mov	al,[gni_max_num]
		add	al,'0'
		mov	[insert+3],al
		;push	word [error_23_seg]
		push	ds
		push	word [error_23_off]
		jmp	short gni_13
gni_12:
		mov	byte [insert],'1'
		mov	byte [insert+1],'-'
		mov	al,[gni_max_num]
		add	al,'0'
		mov	[insert+2],al
		;push	word [error_31_seg]
		push	ds
		push	word [error_31_off]
gni_13:
		call	display
		;pop	bx
		;pop	bx

		;input = c(' ');  
		mov	byte [gni_input],' '
gni_14:
		;push	word [gni_input_ptr_2]
		push	word [gni_input_ptr+2]
		push	word [gni_input_ptr]
		mov	ax,1
		push	ax
		push	word [gni_row]
		push	word [gni_column]
		;push	word [gni_attr_ptr_2]
		push	word [gni_attr_ptr+2]
		push	word [gni_attr_ptr]
		; 09/12/2018
		;sub	ax,ax ; 0
		;push	ax
		call	VIOWRTCHARSTRATT
		mov	byte [default_used],0
		mov	al,[gni_input]
		mov	[input_value],al
		; 15/12/2018
;case_gni_break:
;		cmp	byte [valid_input],0
;		jne	short gni_15
		jmp	gni_4
gni_15:
		mov	al,[gni_input]
gni_16:			; 15/12/2018
		mov	sp,bp
		pop	bp
		;retn
		retn	8 ; 15/12/2018

; input.c - get_char_input
; ----------------------------------------------------------------------------

;/*  */
;char    get_char_input()
;
;BEGIN
;    regs.h.ah = uc(0x0C);                                           /* AC000 */
;    regs.h.al = uc(0x07);                                           /* AC000 */
;    intdos(&regs,&regs);
;    if (regs.h.al == uc(0))                                         /* AC000 */
;        BEGIN
;        DOSBEEP(u(900),u(400));                                     /* AC000 */
;        END
;    return(((char)(regs.h.al)));
;
;END

; 09/12/2018

get_char_input:
		; Flush STDIN (keyboard) buffer 
		; and then, read character from STDIN (without ECHO)

		;mov	byte [regs_x_ax+1],0Ch  ;ah = 0Ch
		;mov	byte [regs_x_ax],7 ; al = 7

		;mov	ax,regs_x_ax
		;push	ax
		;push	ax
		;call	intdos
		;pop	bx
		;pop	bx

		;cmp	byte [regs_x_ax],0
		;jne	short gci_1

		mov	ax,0C07h    ; **2018**	
		int	21h	    ; **2018**	

		or	al,al	    ; **2018**
		jnz	short gci_1 ; **2018**	

		; 01/01/2019
		;mov	ax,900
		;push	ax
		;mov	ax,400
		;push	ax
		call	DOSBEEP
		; 01/01/2019
		;xor	ax,ax ; 15/12/2018
gci_1:
		;mov	al,[regs_x_ax]
		retn

; video.asm (MSDOS 6.0, 1991)
; ----------------------------------------------------------------------------
; 09/12/2018 - Modified for NASM syntax & FDISK subroutines (by Erdogan Tan)

;========================================================
; Modify current cursor position.
;========================================================

VideoSetRowCol:
VIOSETCURPOS:

; IBM PC-DOS FDISK.COM Segment 3, Offset 0009h

	;;%define cpos_column bp+8   ; Far Call
	;;%define cpos_row    bp+10

	;%define cpos_column bp+6   ; Near Call
	;%define cpos_row    bp+8

		; 09/12/2018
		; DH = Row
		; DL = Column

		;push	bp
		;mov	bp,sp
		;push	bx
		;push	cx
		;push	dx
		;push	si
		;push	di
		;push	ds
		;push	es
		;push	ss
		;push	bp
		
		mov	bh,0 ; ScreenPage ; Video Page 0

		;mov	ax,[cpos_row]
		;cmp	al,25
		;jg	short viosetcpos_0
		;mov	dh,al
		;mov	ax,[cpos_column]
		;cmp	al,80
		;jg	short viosetcpos_0
		;mov	dl,al

		cmp	dh,25
		jg	short viosetcpos_0
		cmp	dl,80
		jg	short viosetcpos_0
		
		mov	ah,2 ; SET_CURS_POS

		;push	bx
		;push	cx
		;push	dx
		;push	si
		;push	di
		;push	ds
		;push	es
		;push	ss
		;push	bp
		
		int	10h	; - VIDEO - SET	CURSOR POSITION
				; DH,DL	= row, column (0,0 = upper left)
				; BH = page number
		;pop	bp
		;pop	ss
		;pop	es
		;pop	ds
		;pop	di
		;pop	si
		;pop	dx
		;pop	cx
		;pop	bx

		sub	ax,ax
		jmp	short viosetcpos_1

		;nop
viosetcpos_0:
		mov	ax,2
viosetcpos_1:
		;pop	bp
		;pop	ss
		;pop	es
		;pop	ds
		;pop	di
		;pop	si
		;pop	dx
		;pop	cx
		;pop	bx
		;mov	sp,bp
		;pop	bp
		;retf	6 ; return from far call
		;retn 	6 ; return from near call
		retn ; 10/12/2018

; ----------------------------------------------------------------------------
; convert.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 09/12/2018)

;/*  */
;/***************************************************************************/
;/*Routine name:  DOS_UPPER                                                 */
;/***************************************************************************/
;/*                                                                         */
;/*Description:   This routine will uppcase a character using get country   */
;/*               information (65H) with the capitalize single character    */
;/*               call (20H).                                               */
;/*                                                                         */
;/*Called Procedures:                                                       */
;/*                                                                         */
;/*                                                                         */
;/*                                                                         */
;/*Change History: Updated        5/31/87         DRM                       */
;/*                                                                         */
;/*Input: drive_value                                                       */
;/*                                                                         */
;/*Output: input_value                                                      */
;/*                                                                         */
;/***************************************************************************/

;char dos_upper(drive_value)
;
;char drive_value;
;
;BEGIN
;
;   char output;
;
;   regs.x.ax = (unsigned)CAPCHAR;   /* Get extended country information */
;   regs.h.dl = (unsigned char)drive_value; /* Move input_value to register DL */
;   int86((int)INT21,&regs,&regs);
;   output  = (char)regs.h.dl;
;
;#ifdef DEBUG
;           output = toupper(drive_value);
;#endif
;           return(output);
;END

;dos_upper:
	%define upcase_input bp+4

		;push	bp
		;mov	bp,sp
		;;sub	sp,2
		
		;country dependant character capitalization
		
		;mov	[regs_x_ax],6520h
		;mov	al,[upcase_input]
		;mov	[regs_x_dx],al
		;mov	ax,[regs_x_ax]
		;push	ax
		;push	ax
		;mov	ax,21h
		;push	ax
		;call	int86
		;mov	al,[regs_x_dx] ; capitalize character
		;mov	sp,bp
		;pop	bp
		;retn
dos_upper:
		; 09/12/2018
		;country dependant character capitalization
		
		;push	dx
		mov	dl,al
		mov	ax,6520h
		int	21h
		mov	al,dl
		;pop	dx
		
		retn


; WRITE.ASM (VCCRT1.ZIP) - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; Modified and simplified for NASM syntax by Erdogan Tan (10/12/2018)

;***
;int _write(fh, buf, cnt) - write bytes to a file handle
;
;Purpose:
;	Writes count bytes from the buffer to the handle specified.
;	If the file was opened in text mode, each LF is translated to
;	CR-LF.	This does not affect the return value.	In text
;	mode ^Z indicates end of file.
;
;	Multi-thread notes:
;	(1) write() - Locks/unlocks file handle
;	    _write_lk() - Does NOT lock/unlock file handle
;	(2) It is assumed in this source that MTHREAD can only be
;	true under OS/2.  Thus, conditional code is contained within
;	MTHREAD conditionals without additional OS2 conditionals.
;
;Entry:
;	int fh - file handle to write to
;	char *buf - buffer to write from
;	unsigned int cnt - number of bytes to write
;
;Exit:
;	returns number of bytes actually written.
;	This may be less than cnt, for example, if out of disk space.
;	returns -1 (and set errno) if fails.
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************


; 14/12/2018 (no need to _write for FDISK2.COM)

;;--- Non-multithread version of write
;
;_write:
;
;	;%define oldsp	bp-8
;	%define oldsp	bp-6
;	%define lfcnt	bp-4
;	%define outcnt	bp-2
;
;	%define fhndl	bp+4  ; fh
;	%define buf	bp+6
;	%define cnt	bp+8
;
;		push	bp
;		mov	bp,sp
;		;sub	sp,8
;		sub	sp,6		
;
;		; make sure handle is in range
;
;		mov	bx,[fhndl]	; get file handle
;
;		cmp	bx,[_nfile]	; handle in range ?
;		jb	short handle_okay ; yes, continue
;
;		;mov	ax,EBADF shl 8 + 0 ; file handle is out of range
;		mov	ax,900h
;		stc
;to_dosretax:
;		jmp	_dosretax	; error on lseek (invalid file handle)
;		;jmp	DOSerror
;handle_okay:
;		;cmp	_aDBswpflg,_aDBdoswp	; See if we should screen swap
;		cmp	word [_aDBswpflg],0D6D6h
;		jne	short chk_append ; No -- skip over call
;		call	_aDBswpchk	; Yes -- try to do the check
;chk_append:
;		;test	__osfile[bx],FAPPEND ; check for append
;		test    byte [_osfile+bx],20h
;		jz	short noseek1	; not appending, continue
;
;;Append mode - seek to end of file
;
;		;mov	ax,DOS_lseek shl 8 + 2 ; appending, lseek to end
;		mov	ax,4202h
;		xor	cx,cx
;		mov	dx,cx		; 0L
;		;callos
;		int	21h	; DOS - 2+ - MOVE FILE READ/WRITE POINTER (LSEEK)                                       ; AL = method: offset from end of file
;				; AL = method: offset from end of file
;		jc	short to_dosretax ; if no error, continue
;noseek1:
;		;test	__osfile[bx],FTEXT ; check for text (DOS finds err)
;		test	byte [_osfile+bx],80h
;		jz	short writebin0	; do it without translation
;		;fall thru		; do the cr/lf translation
;
;; --- Translate LF => CR/LF ---
;; We get here if we have to translate LF's to CR/LF's on output
;
;translate:
;
;;put input buffer address in es:si
;
;		mov	dx,[buf]	; get buffer address
;		push	ds
;		pop	es		; es = ds
;
;		xor	ax,ax
;		mov	[outcnt],ax	;zero out char counter
;		mov	[lfcnt],ax	;zero out lf counter, too
;
;		cld
;		push	di		; save di
;		push	si		; save si
;		mov	di,dx		; es:di = start of search
;		mov	si,dx		; ds:si = start of search, too
;
;;Scan for LFs in the user's buffer.
;;(1) If none, write the buffer out in one shot.
;;(2) If there is an LF, buffer the output doing translation.
;
;lfscan:
;		mov	[oldsp],sp	;save sp
;		mov	cx,[cnt]	;get char move count
;		jcxz	j_writedone	;done if count = 0
;
;		;mov	al,C_LF		;set up for scan
;		mov	al,0Ah
;		repnz	scasb		;scan for LF
;		jnz	short writebin1	;no LFs - write out in binary mode
;		;fall thru		;LFs - use the internal buffer
;
;;Move chars from input buffer to LF buffer doing translation as needed.
;;ds:si = start of input buffer
;
;		call	_stackavail	;ax = # bytes on stack
;		;cmp	ax,LFBUFFMIN+STACKSAVE ;is there enough room on stack?
;		cmp	ax,168
;		jbe	short stackerr	;nope - return an error
;	
;		sub	sp,2		;move sp to first free word
;		mov	bx,sp		;bx = end of LF buffer
;		;mov	dx,LFBUFFMAX	;assume max LF buff size
;		mov	dx,512	
;		;cmp	ax,LFBUFFMAX+STACKSAVE ;stack space > max LF buff size ??
;		cmp     ax,552
;		jae	short lfbuff	;yes, use the max LF buff size
;		;mov	dx,LFBUFFMIN	;no, use the min LF buff size
;		mov	dx,128
;lfbuff:
;		sub	sp,dx		;move sp past LF buffer
;		mov	dx,sp		;dx = start of LF buffer
;		mov	di,dx		;di = start of LF buffer also
;
;		push	ss		;es gets LF buffer segment
;		pop	es
;
;		mov	cx,[cnt]	;cx = # of chars to move
;
;;Main body of loop
;;	al = reserved for current character
;;	bx = end of LF buffer
;;	cx = count of chars left to write
;;	dx = beginning of LF buffer
;;	ds:si = curr position in input buffer
;;	es:di = curr position in LFBUFF
;
;lfloop:
;		lodsb			;al = next byte from input
;		;cmp	al,C_LF		;curr char == LF ?
;		cmp	al,0Ah
;		je	short foundlf 	;yes - do the translation
;lfloop1:
;		cmp	di,bx		;is LF buffer full ?
;		je	short wrlfbuff1	;if so, write it out
;storechr:
;		stosb			;al ->	LFBUFF and bump di
;		loop	lfloop		;do next char
;		;fall thru		;no more input (cx = 0)
;
;;No more input - write out anything that's in the LF buffer
;
;		call	wrlfbuff	;write out the buffer
;j_writedone:
;		jmp	short writedone ;all done!
;
;;Found an LF - do the translation
;
;foundlf:
;		;mov	al,C_CR		;put a CR in the buffer
;		mov	al,0Dh
;		cmp	di,bx		;LF buffer full ?
;		jne	short foundlf1	;nope - store the CR
;		call	wrlfbuff	;write out the LF buffer
;foundlf1:
;		stosb			;CR -> LFBUFF and bump di
;		;mov	al,C_LF		;get LF back
;		mov	al,0Ah
;		inc	word [lfcnt] 	;bump LF count
;		jmp	short lfloop1	;store the LF
;
;;Call to wrlfbuff used by the lfloop
;
;wrlfbuff1:
;		call	wrlfbuff	;write out the buffer
;		jmp	short storechr	;back into loop
;;Bridges
;
;writebin1:
;		pop	si		;restore si/di
;		pop	di
;writebin0:
;		jmp	short writebin	;binary write code
;
;;Error - could not get enough stack space
;
;stackerr:
;	; call _chkstk with a value guaranteed to give an error
;
;		mov	ax,0FFFCh ; -4
;		call	_chkstk 	;give stack overflow and die
;		;never returns

; ----------------------------------------------------------------------------

;***
;wrlfbuff - Write out the lfbuffer
;
;Purpose:
;	This routine writes out the lf buffer and resets appropriate
;	registers.
;Entry:
;	Registers still setup from LF/CR translation loop.
;	Pertinent values for wrlfbuff() are:
;		dx = beginning of LF buffer
;		di = current position in LF buffer
;Exit:
;	Resets di to the beginning of the LF buffer.
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************

; 14/12/2018 (no need to _wrlfbuff for FDISK2.COM)

;wrlfbuff:
;		push	ax		;save current char
;		push	bx		;save end of buffer pointer
;		push	cx		;save cx
;	
;		;calculate the # of chars to write out
;
;		mov	cx,di		;cx = calc # of bytes to write
;		sub	cx,dx
;		jcxz	wrlfdone	;if cx == 0, we're done
;
;		push	cx		;save char count
;
;		;do the write
;
;		mov	bx,[fhndl]		;bx = file handle
;		;mov	ah,DOS_write	;write call
;		;callos			;do the write
;		mov	ah,40h
;		int	21h	; DOS - 2+ - WRITE TO FILE WITH HANDLE
;				; BX = file handle, CX = number of bytes to write,
;				; DS:DX -> buffer
;		pop	cx		;restore chars written
;		jc	short wrlferror	;error
;
;		add	[outcnt],ax	;add chars written to total
;		cmp	cx,ax		;did we write less than we wanted
;		ja	short wrlferror	;yes - return error, if we jump, CF=0
;
;	;--- no error on the write ---
;	;Restore/re-initialize registers and return.
;
;wrlfdone:
;		pop	cx		;restore register
;		pop	bx
;		pop	ax
;		mov	di,dx		;make di = beginning of LF buffer
;		retn			;return to caller
;
;;--- error on the write ---
;;Either the write returned an explicit error or we wrote less than requested.
;;Either way, we are not returning to the caller.
;
;wrlferror:
;		lahf			;save carry for a sec...
;		;add	sp,8		;clean off stack (don't change ax)
;		add	sp,6		;cleans off return address, too
;		
;		cmp	word [outcnt],0	;have we written something?
;		jne	short writedone	;yes, return how much
;
;		sahf			;restore carry
;
;		jnc	short wrote0	;carry set ?
;		;mov	ah,EBADF	;yes - error on write
;		mov	ah,9
;		jmp	short writeerror ;error return
;
;; The write did not return an error but we didn't write anything.
;; if dev and first byte ^z, just return 0. else return end of media error.
;; (AX=0)
;
;wrote0:
;		;test	__osfile[bx],FDEV ; device ?
;		test	byte [_osfile+bx],40h
;		jz	short wrlferr1	; no, error
;	
;		mov	bx,[buf]
;		;cmp	byte ptr [bx],C_SUB ; ^z ?
;		cmp	byte [bx],1Ah
;		jne	short wrlferr1	; no
;
;		clc			; no error
;		jmp	short writeerror ; don't overwrite ax (ax=0)
;
;wrlferr1:				; return an error
;		stc			; carry set for error
;		;mov	ax,ENOSPC shl 8 + 0 ; return no more disk space error
;		mov	ax,1C00h
;		jmp	short writeerror ; return the error
;
;writedone:				; good return
;		mov	ax,[outcnt]	; total # chars written
;		sub	ax,[lfcnt]	; subtract the # of LFs translated
;					; clears carry, too
;writeerror:				; error return
;		mov	sp,[oldsp]	; restore sp
;		pop	si		; restore si
;		pop	di		; restore di
;justret:
;		jmp	_dosretax	; return AX if successful
;
;;--- Untranslated Writes ---
;; Just shove the entire buffer out there as fast as possible
;; ds = dgroup
;
;writebin:
;		mov	cx,[cnt]	; number of bytes to write
;		or	cx,cx		; are we supposed to write 0 bytes?
;		jnz	short writegoon	; nope, continue
;		mov	ax,cx		; yes, ax = byte count = 0
;		;jmp	__dosretax	; good return
;		jmp	DOSnoerror ; 10/12/2018
;writegoon:
;		mov	dx,[buf]	; buffer address
;		;callos	write
;		mov	ah,40h
;		int	21h	; DOS - 2+ - WRITE TO FILE WITH HANDLE
;				; BX = file handle, CX = number of bytes to write,
;				; DS:DX -> buffer
;		jnc	short writeok4
;
;		;mov	ah,EBADF
;		mov	ah,9
;		jmp	short justret
;
;writeok4:				;no write error  (ax = # bytes written)
;		or	ax,ax		;did we write 0 bytes ?
;		jnz	short justret 	;no, just return
;
;; Requested non-zero number of bytes to be written and 0 were written.
;; If device and 1st byte was ^z, just return 0. else end of media
;
;		;test	__osfile[bx],FDEV ; device?
;		test	byte [_osfile+bx],40h
;		jz	short notdev	; no
;
;		mov	bx,dx
;		;cmp	byte ptr [bx],C_SUB ; ^z ?
;		cmp	byte [bx],1Ah
;		jne	short notdev
;
;		clc
;		jmp	short justret	; good return
;notdev:
;		stc			; set carry flag to mark error
;		;mov	ax,ENOSPC shl 8 + 0 ; return no more disk space error
;		mov     ax,1C00h
;		jmp	short justret	; return AX

; STACKAVA.ASM (VCCRT1.ZIP) - Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; 10/12/2018

; 14/12/2018 (no need to _stackavail for FDISK2.COM)

;_stackavail:
;		pop	cx		; return offset
;		;mov	ax,[_STKHQQ]	; bottom of stack
;		mov	ax,[end_of_bss]
;
;		cmp	ax,sp
;		jae	short stkavl_1
;
;		sub	ax,sp
;		neg	ax
;stkavl_0:
;		jmp	cx		;; return to cx
;stkavl_1:
;		xor	ax,ax
;		jmp	short stkavl_0

; ----------------------------------------------------------------------------
; int13.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 15/12/2018)

;/*  */
;char write_boot_record(cylinder,which_disk)
;
;unsigned    cylinder;
;unsigned char   which_disk;
;
;BEGIN
;
;/*C00    char i;  */
;/*C00    char j;  */
;    char far *buffer_pointer = boot_record;
;
;    /* Setup read, always on a cylinder boundary */
;    regs.h.ah = uc(WRITE_DISK);                           /* AC000 */
;    regs.h.al = uc(1);                                    /* AC000 */
;    regs.h.dh = uc(0);                                    /* AC000 */
;    regs.h.cl = uc(0x01);                                 /* AC000 */
;
;    /* Specify the disk */
;    regs.h.dl = which_disk + 0x80;
;
;    /* Need to scramble CX so that sectors and cyl's are in INT 13 format */
;
;    if (cylinder > u(255))                                /* AC000 */
;       BEGIN
;        regs.h.cl = regs.h.cl | ((unsigned char)((cylinder /256) << 6));
;       END
;    regs.h.ch = (unsigned char)(cylinder & 0xFF);
;
;    /* Point at the place to read the boot record */
;    regs.x.bx = FP_OFF(buffer_pointer);
;    segregs.es = FP_SEG(buffer_pointer);
;
;    /* write the boot record */
;    DiskIo(&regs,&regs,&segregs);                         /* AC000 */
;
;    /* Check for error reading it */
;    if ((regs.x.cflag & 1) != u(1))                       /* AC000 */
;       BEGIN
;        return(TRUE);
;       END
;    else
;       BEGIN
;        /* Tell user there was an error */
;        clear_screen(u(0),u(0),u(24),u(79));              /* AC000 */
;        display(error_2);
;        no_fatal_error = FALSE;
;        return(FALSE);
;       END
;END

write_boot_record:

	;%define w_buf_pointer	bp-4  ; far ptr, dword

	%define w_cylinder	bp+4  ; unsigned int, word
	%define w_which_disk	bp+6  ; unsigned char, byte	

		push	bp
		mov	bp,sp
		;sub	sp,4 ; 04/01/2019
		
		;mov	word [w_buf_pointer],boot_record
		;mov	[w_buf_pointer2],ds

		mov	bx,boot_record
		;push	ds
		;pop	es
		
		;mov	byte [regs_x_ax+1],3 ; write
		;mov	byte [regs_x_ax],1   ; 1 sector	

		;mov	byte [regs_x_dx+1],0
		;mov	byte [regs_x_cx],1

		sub	dh,dh	; Head 0
		mov	cl,1	; Sector 1

		;mov	al,[w_which_disk]
		;add	al,80h
		;mov	byte [regs_x_dx],al

		mov	dl,[w_which_disk]
		add	dl,80h

		mov	ax,[w_cylinder]
		mov	ch,al

		;cmp	word [w_cylinder],255
		;cmp	ax,255
		;jbe	short write_bs_1
		or	ah,ah
		jz	short write_bs_1

		;mov	ax,[w_cylinder]
		shr	ax,1
		shr	ax,1
		and	al,0C0h
		;or	byte [regs_x_cx],al
		or	cl,al
write_bs_1:
		;mov	al,[w_cylinder]
		;mov	byte [regs_x_cx+1],al

		;mov	ax,[w_buf_pointer]
		;mov	[regs_x_bx],ax
		;mov	ax,[w_buf_pointer2]
		;mov	[segregs_es],ax
		;mov	ax,segregs_es

		;push	ax
		;mov	ax,regs_x_ax
		;push	ax
		;push	ax
		;call	DiskIo
		;add	sp,6
		;mov	al,[regs_x_cflag]
		;and	al,1
		;cmp	al,1
		;je	short write_bs_2
		;mov	al,1
		;jmp	short write_bs_3

		mov	ax,0301h ; write 1 sector (CHS write)
		int	13h
		jc	short write_bs_2

		mov	al,1 ; TRUE
		jmp	short write_bs_3
write_bs_2:
		;mov	ax,79
		;push	ax	 ; Bottom Rigth Column (79)  
		;mov	ax,24
		;push	ax	 ; Bottom Row (24)
		;sub	ax,ax ; 0
		;push	ax	 ; Top Left Column (0)	
		;push	ax	 ; Top Row (0)
		;
		;call	clear_screen
		;add	sp,8

		; Clear screen (clear whole video page)
		call	CLS

		sub	al,al ; FALSE
		stc	; cf = 1  (error!)

		;;push	word [error_2_seg] ; read error
		;push	word [error_3_seg] ; write error
		push	ds
		;push	word [error_2_off]
		push	word [error_3_off]
		call	display
		;pop	bx
		;pop	bx

		sub	al,al ; FALSE
		mov	[no_fatal_error],al ; 0
		stc	; cf = 1  (error!)
write_bs_3:
		;mov	sp,bp ; 04/01/2019
		pop	bp
		;retn
		retn	4 ; 22/12/2018

; ============================================================================
;  MAIN MENU
; ============================================================================
; 15/12/2018

; fdisk.msg (MSDOS 6.0)
;/*************************************************************************************************/
;/* Screen for DO_MAIN_MENU                                                                       */
;/*                                                                                               */
;/*      |00000000001111111111222222222233333333334444444444555555555566666666667777777777|       */
;/*      |01234567890123456789012345678901234567890123456789012345678901234567890123456789|       */
;/*    --|--------------------------------------------------------------------------------|       */
;/*    00|                               MS-DOS Version 6                                 |menu_1 */
;/*    01|                            Fixed Disk Setup Program                            |menu_1 */
;/*    02|                    (C)Copyright Microsoft Corp. 1983 - 1993                    |menu_1 */
;/*    03|                                                                                |       */
;/*    04|                                 FDISK Options                                  |menu_2 */
;/*    05|                                                                                |       */
;/*    06|    Current fixed disk drive: #                                                 |menu_5 */
;/*    07|                                                                                |       */
;/*    08|    Choose one of the following:                                                |menu_3 */
;/*    09|                                                                                |       */
;/*    10|    1.  Create DOS Partition or Logical DOS Drive                               |menu_2 */
;/*    11|    2.  Set active partition                                                    |menu_2 */
;/*    12|    3.  Delete DOS Partition or Logical DOS Drive                               |menu_2 */
;/*    13|    4.  Display partition information                                           |menu_2 */
;/*    14|    5.  Change current fixed disk drive                                         |menu_4 */
;/*    15|                                                                                |       */
;/*    16|                                                                                |       */
;/*    17|    Enter choice: [#]                                                           |menu_7 */
;/*    18|                                                                                |       */
;/*    19|                                                                                |       */
;/*    20|    Warning! No partitions are set active - disk 1 is not startable unless      |menu_6 */
;/*    21|    a partition is set active.                                                  |       */
;/*    22|                                                                                |       */
;/*    23|                                                                                |       */
;/*    24|    Press ESC to exit FDISK                                                     |menu_2 */
;/*    ------------------------------------------------------------------------------------       */
;/*                                                                                               */
;/*************************************************************************************************/

; ----------------------------------------------------------------------------
; mainmenu.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 15/12/2018)

;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: DO_MAIN_MENU                               */
;/*                                                             */
;/* DESCRIPTIVE NAME: Main menu display and input routine       */
;/*                                                             */
;/* FUNCTION:                                                   */
;/*    Displays the main FDISK menu, accepts and validates      */
;/*    input from menu and passes control to requested function */
;/*                                                             */
;/* NOTES: The following screen is managed by this routine:     */
;/*                                                             */
;/*       |0000000000111111111122222222223333333333|            */
;/*       |0123456789012345678901234567890123456789|            */
;/*     --|----------------------------------------|            */
;/*     00|                                        |            */
;/*     01|                                        |            */
;/*     02|                                        |            */
;/*     03|                                        |            */
;/*     04|FDISK Options                           |            */
;/*     05|                                        |            */
;/*     06|Current Fixed Disk Drive: #             |            */
;/*     07|                                        |            */
;/*     08|Choose one of the following:            |            */
;/*     09|                                        |            */
;/*     10|    1.  Create DOS partition            |            */
;/*     11|    2.  Change Active Partition         |            */
;/*     12|    3.  Delete DOS Partition            |            */
;/*     13|    4.  Display Partition Data          |            */
;/*     14|    5.  Select Next Fixed Disk Drive    |            */
;/*     15|                                        |            */
;/*     16|                                        |            */
;/*     17|                                        |            */
;/*     18|Enter choice: [#]                       |            */
;/*     19|                                        |            */
;/*     20|                                        |            */
;/*     21|WARNING! No partitions marked active    |            */
;/*     22|                                        |            */
;/*     23|Press ESC to return to DOS              |            */
;/*     --------------------------------------------            */
;/*                                                             */
;/* ENTRY POINTS: do_main_menu                                  */
;/*      LINKAGE: do_main_menu();                               */
;/*               NEAR CALL                                     */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if case statement   */
;/*             failure when branching to requested function    */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      display                                                */
;/*      get_num_input                                          */
;/*      create_partition                                       */
;/*      change_active_partition                                */
;/*      delete_partition                                       */
;/*      display_partition_information                          */
;/*      find_active_partition                                  */
;/*      change_drive                                           */
;/*      internal_program_error                                 */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void do_main_menu()
;
;BEGIN
;
;char   input;
;char   max_input;
;
;FLAG	error_switch;
;
;unsigned    temp;
;unsigned    i;
;
;   input = c(NUL);
;   PercentFlag = (FLAG)FALSE;
;   /* Initialize cur_disk indicator. It is 0 based for array usage */
;   /* See if first disk readable */
;   cur_disk = c(0);
;   if (!good_disk[0])
;      BEGIN
;       cur_disk++;
;      END
;
;   temp = u(0);
;   for (i=u(0);i<u(number_of_drives);i++)
;       if (good_disk[i])
;           temp = u(1);
;   if (temp == u(1))
;
;      BEGIN
;       clear_screen(u(0),u(0),u(24),u(79));
;       /* Display the copyright */
;       display(menu_1);
;
;       /* See if we couldn't access drive 1 */
;		for (i = 0; i < number_of_drives; i++)
;			BEGIN
;			 if (!good_disk[i] && (error_switch == FALSE))
;				{
;          	insert[0] = c(i+'1');
;           	display(error_30);
;			 	error_switch = TRUE;
;			   }
;      END
;
;      /* Display the menu every time this routine is returned to until ESC */
;      input = c(NUL);
;      while (input !=c(ESC))
;         BEGIN
;            /* Put up most of the menu */
;            display(menu_2);
;            display(menu_3);
;            display(menu_7);
;
;            /* Put correct disk in current disk message */
;            insert[0]=cur_disk+1+'0';
;            display(menu_5);
;
;            /* Display warning prompt if no active partitions */
;            /* check to see if there is an avail partition */
;            temp = u(0);
;            for (i = u(0); i < u(4);i++)
;               BEGIN
;
;               /* See if any non - zero system id bytes */
;               temp = temp | part_table[cur_disk][i].sys_id ;
;              END
;           /* Any entry that isn't zero means */
;           if (temp != u(0))
;              BEGIN
;               /* If there isn't an active partition and this is disk 1, then yell) */
;               if ((!find_active_partition()) && (cur_disk == c(0)))
;                  display(menu_6);
;              END
;
;           /* Get the menu input */
;
;           /* See if more than one fixed disk */
;           if (number_of_drives > uc(1))
;             BEGIN
;              display(menu_4);
;              max_input = c(5);
;             END
;           else     /* only 4 options */
;               max_input = c(4);
;           /* Setup default and go get input */
;           input = get_num_input(c(1),max_input,input_row,input_col);
;           switch(input)
;              BEGIN
;               case  '1': create_partition();
;                          break;
;
;               case  '2': change_active_partition();
;                          break;
;
;               case  '3': delete_partition();
;                          break;
;
;               case  '4': display_partition_information();
;                          break;
; 
;               case  '5': change_current_drive();
;                          break;
;
;               case  ESC: break;  /* ESC case */
;
;               default:   internal_program_error();
;              END
;           END
;       END
;   else
;       BEGIN
;        /* Can't read any drive, so quit */
;        no_fatal_error = c(FALSE);
;        display(error_2);
;       END
;   return;
;END

do_main_menu:

	%define mm_err_switch bp-8 ; bp-10
	%define mm_i	      bp-6 ; bp-8
	;%define mm_temp      bp-6
	%define mm_max_input  bp-4
	%define mm_input      bp-2

		push	bp
		mov	bp,sp
		;sub	sp,10
		sub	sp,8
		;sub	al,al ; 0
		sub	ax,ax
		mov	[mm_input],al
		mov	[PercentFlag],al
		mov	[cur_disk],al
		mov	[mm_err_switch],al ; 0
		;cmp	byte [gooddisk+0],0
		cmp	[good_disk],al ; 0
		jne	short mainmenu_01
		mov	byte [cur_disk],1
mainmenu_01:
		sub	ax,ax ; 0
		;mov	[mm_temp],ax ; FALSE
		mov	[mm_i],ax
		jmp	short mainmenu_04
mainmenu_02:
		mov	bx,[mm_i]
		cmp	byte [good_disk+bx],0
		je	short mainmenu_03
		;mov	byte [mm_temp],1 ; TRUE
		inc	ah ; [mm_temp] = 1
mainmenu_03:
		inc	byte [mm_i]
mainmenu_04:
		mov	al,[number_of_drives]
		;sub	ah,ah
		;cmp	ax,[mm_i]
		cmp	al,[mm_i]
		ja	short mainmenu_02
		;cmp	byte [mm_temp],1
		;je	short mainmenu_05
		or	ah,ah ; [mm_temp]
		jnz	short mainmenu_05
		jmp	mainmenu_27
mainmenu_05:
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;push	word [menu_1_segment]
		push	ds
		push	word [menu_1_offset]
		call	display
		;pop	bx
		;pop	bx
		mov	byte [mm_i],0
		jmp	short mainmenu_08
mainmenu_06:
		mov	bx,[mm_i]
		cmp	byte [good_disk+bx],0
		ja	short mainmenu_07
		cmp	byte [mm_err_switch],0
		ja	short mainmenu_07
		lea	ax,[bx+'1']
		mov	[insert],al
		;push	word [error_30_seg]
		push	ds
		push	word [error_30_off]
		call	display
		;pop	bx
		;pop	bx
		mov	byte [mm_err_switch],1
mainmenu_07:
		inc	byte [mm_i]
mainmenu_08:
		mov	al,[number_of_drives]
		sub	ah,ah
		;cmp	ax,[mm_i]
		cmp	al,[mm_i]
		ja	short mainmenu_06
		mov	byte [mm_input],ah ; 0
mainmenu_10:
		cmp	byte [mm_input],1Bh ; ESC key
		jne	short mainmenu_11
		jmp	mainmenu_28
mainmenu_11:
		;push	word [menu_2_segment]
		push	ds
		push	word [menu_2_offset]
		call	display
		;pop	bx
		;pop	bx
		;push	word [menu_3_segment]
		push	ds
		push	word [menu_3_offset]
		call	display
		;pop	bx
		;pop	bx
		;push	word [menu_7_segment]
		push	ds
		push	word [menu_7_offset]
		call	display
		;pop	bx
		;pop	bx
mainmenu_12:
		;mov	al,[cur_disk]
		;add	al,'1'
		;mov	[insert],al
		;;push	word [menu_5_segment]
		;push	ds
		;push	word [menu_5_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_5 ; 31/12/2018
		
		;sub	ax,ax ; 0
		sub	al,al
		;mov	[mm_temp],ax
		;mov	[mm_temp],al ; 0
		;xor	ch,ch ; [mm_temp]
		mov	cx,46 ; *
		;mov	[mm_i],ax
		mov	[mm_i],al ; 0
		;jmp	short mainmenu_14
mainmenu_13:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;add	ax,[mm_i]
		add	al,[mm_i]
		;mov	cx,46
		;mul	cx
		;mov	cl,46 ; *
		mul	cl
		mov	bx,ax
		mov	al,[part_table_sys_id+bx]
		;sub	ah,ah
		;or	[mm_temp],ax
		;or	[mm_temp],al
		or	ch,al
		inc	byte [mm_i]
mainmenu_14:
		cmp	byte [mm_i],4
		jb	short mainmenu_13
		;cmp	byte [mm_temp],0
		;jna	short mainmenu_15
		or	ch,ch ; [mm_temp]
		jz	short mainmenu_15

		call	find_active_partition
		;or	al,al
		;jnz	short mainmenu_15
		jnz	short mainmenu_15
		; al = 0

		cmp	[cur_disk],al ; 0
		jne	short mainmenu_15
		;push	word [menu_6_segment]
		push	ds
		push	word [menu_6_offset]
		call	display
		;pop	bx
		;pop	bx
mainmenu_15:
		cmp	byte [number_of_drives],1
		jbe	short mainmenu_16
		;push	word [menu_4_segment]
		push	ds
		push	word [menu_4_offset]
		call	display
		;pop	bx
		;pop	bx
		mov	byte [mm_max_input],5
		jmp	short mainmenu_17
mainmenu_16:
		mov	byte [mm_max_input],4
mainmenu_17:
		push	word [input_col]
		push	word [input_row]
		mov	al,[mm_max_input]
		push	ax
		mov	al,1
		push	ax
		call	get_num_input
		;add	sp,8 ; 15/12/2018
switch_input1:
		mov	[mm_input],al
		;cbw
		;cmp	ax,'5'
		cmp	al,'5'
		je	short case_5
		ja	short case_DEF
		sub	al,1Bh  ; ESC key
		;jnz	short mainmenu_19
		;jmp	mainmenu_10
		jz	short mainmenu_28
mainmenu_19:
		sub	al,16h ; 1Bh+16h = 31h = '1'
		jz	short case_1 ; '1'
		dec	al
		jz	short case_2 ; '2'
		dec	al
		jz	short case_3 ; '3'
		dec	al
		jz	short case_4 ; '4'
case_DEF:
		call	internal_program_error
mainmenu_21:
		jmp	mainmenu_10
case_1:
		call	create_partition
		jmp	mainmenu_10
case_2:
		call	change_active_partition
		jmp	mainmenu_10
case_3:
		call	delete_partition
		jmp	mainmenu_10
case_4:
		call	display_partition_information
		jmp	mainmenu_10
case_5:
		call	change_current_drive
		jmp	mainmenu_10
mainmenu_27:
		mov	byte [no_fatal_error],0
		;push	word [error_2_seg]
		push	ds
		push	word [error_2_off]
		call	display
		;pop	bx
		;pop	bx
mainmenu_28:
		mov	sp,bp
		pop	bp
		retn

; ============================================================================
;  DISPLAY PARTITION INFORMATION
; ============================================================================
; 16/12/2018

; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/*  Screen for DISPLAY_PARTITION_INFORMATION                                                       */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                           Display Partition Information                        |menu_35   */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Partition Status   Type    Size in Mbytes   Percentage of Disk Used         |menu_14 # */
;/*   09|     ## #        #   #######       ####         ###%                            |menu_14 # */
;/*   10|     ## #        #   #######       ####         ###%                            |          */
;/*   11|     ## #        #   #######       ####         ###%                            |          */
;/*   12|     ## #        #   #######       ####         ###%                            |          */
;/*   13|                                                                                |          */
;/*   14|    Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes)                   |menu_15 # */
;/*   15|                                                                                |          */
;/*   16|                                                                                |          */
;/*   17|    The Extended DOS partition contains Logical DOS Drives.                     |menu_36   */
;/*   18|    Do you want to display the logical drive information (Y/N)......? [Y]       |menu_36   */
;/*   19|                                                                                |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */
;/*                                                                                                 */
;/***************************************************************************************************/

; ----------------------------------------------------------------------------
; fdisk.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 16/12/2018)

;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: DISPLAY_PARTITION_INFORMATION              */
;/*                                                             */
;/* DESCRIPTIVE NAME: Display partition information             */
;/*                                                             */
;/* FUNCTION: Displays defined partition information and prompt */
;/*           user to display disk volumes if they exist        */
;/*                                                             */
;/* NOTES:                                                      */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*     |0000000000111111111122222222223333333333|              */
;/*     |0123456789012345678901234567890123456789|              */
;/*   --|----------------------------------------|              */
;/*   00|                                        |              */
;/*   01|                                        |              */
;/*   02|                                        |              */
;/*   03|                                        |              */
;/*   04|Display Partition Information           |              */
;/*   05|                                        |              */
;/*   06|Current Fixed Disk Drive: #             |              */
;/*   07|                                        |              */
;/*   08|Partition Status   Type  Start  End Size|              */
;/*   09|    #        #   #######  #### #### ####|              */
;/*   10|                                        |              */
;/*   11|                                        |              */
;/*   12|                                        |              */
;/*   13|                                        |              */
;/*   14|Total disk space is #### cylinders.     |              */
;/*   15|                                        |              */
;/*   16|                                        |              */
;/*   17|                                        |              */
;/*   18|The EXTENDED DOS partition contains DOS |              */
;/*   19|disk volumes. Do you want to display    |              */
;/*   20|the volume information............? [Y] |              */
;/*   21|                                        |              */
;/*   22|                                        |              */
;/*   23|Press ESC to return to FDISK Options    |              */
;/*   --------------------------------------------              */
;/*                                                             */
;/* ENTRY POINTS: Display_Partition_Information                 */
;/*      LINKAGE: display_partition_information ()              */
;/*          NEAR CALL                                          */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if invalid input    */
;/*             returned to this routine                        */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      wait_for_ESC                                           */
;/*      display                                                */
;/*      table_display                                          */
;/*      get_yn_input                                           */
;/*      find_partition_type                                    */
;/*      display_volume_information                             */
;/*      internal_program_error                                 */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void display_partition_information()
;
;BEGIN
;
; char   input;
;
;    input = c(NUL);
;    /* Clear_screen */
;    clear_screen(u(0),u(0),u(24),u(79));
;
;    /* Display Header */
;    display(menu_35);
;
;    /* Setup and print current disk */
;    insert[0] = cur_disk+1+'0';
;    display(menu_5);
;
;    /* Display information */
;    if (table_display())
;       BEGIN
;
;	/* Setup and print disk space msg */
;	number_in_msg((XFLOAT)total_mbytes[cur_disk],u(0));
;	display(menu_15);
;
;	/* See if any logical drive stuff to display */
;	if (find_partition_type(uc(EXTENDED)))
;	   BEGIN
;	    /* See if any logical drives exist */
;	    if (find_logical_drive())
;	       BEGIN
;
;		/* print ESC prompt */
;		display(menu_11);
;
;		/* Prompt to see if they want to see EXTENDED info */
;		display(menu_36);
;
;		/* Get Y/N input, default is YES */
;		input = get_yn_input(c(Yes),input_row,input_col);
;		switch(input)
;		   BEGIN
;
;		    case 1:    display_volume_information();
;			       break;
;
;		    case 0:    break;
;
;		    case ESC:  break;
;
;		    default:   internal_program_error();
;			       break;
;		   END
;	       END
;	    else
;		input = wait_for_ESC();
;	   END
;	else
;	    input = wait_for_ESC();
;       END
;    else
;	input = wait_for_ESC();
;    /* clear the screen before going back to main menu */
;    clear_screen(u(0),u(0),u(24),u(79));
;    return;
;END

; IBM PC-DOS 7.0, FDISK.COM (unpacked) Segment 0, Offset 202Ch

display_partition_information:
		push	bp
		;mov	bp,sp
		;sub	sp,2
		
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;push	word [menu_35_segment]
		push	ds
		push	word [menu_35_offset]
		call	display
		;pop	bx
		;pop	bx

		;mov	al,[cur_disk]
		;add	al,'1'
		;mov	[insert],al
		;;push	word [menu_5_segment]
		;push	ds
		;push	word [menu_5_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_5 ; 31/12/2018

		call	table_display
		;or	al,al
		;jz	short disp_wait_for_esc
		jc	short disp_wait_for_esc
		
		sub	ax,ax ; 0
		push	ax
		mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;shl	bx,1
		shl	al,1
		mov	bx,ax
		push	word [total_mbytes+bx]
		call	number_in_msg
		;pop	bx
		;pop	bx

		;push	word [menu_15_segment]
		push	ds
		push	word [menu_15_offset]
		call	display
		;pop	bx
		;pop	bx
		
		mov	al,EXTENDED ; 5
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short disp_wait_for_esc
		jc	short disp_wait_for_esc

		call	find_logical_drive
		;or	al,al
		;jz	short disp_wait_for_esc
		jc	short disp_wait_for_esc

		;;push	word [menu_11_segment]
		;push	ds
		;push	word [menu_11_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_11 ; 31/12/2018
		
		;push	word [menu_36_segment]
		push	ds
		push	word [menu_36_offset]
		call	display
		;pop	bx
		;pop	bx
		
		push	word [input_col] ; Column for input
		push	word [input_row] ; Row for input
		mov	al,[Yes] ; 'Y'	; Default input value/char
		push	ax
		call	get_yn_input  ; Get YES ('Y'), NO ('N') input
		;add	sp,6
switch_input9:
		;cbw
		;cmp	ax,1Bh
		cmp	al,1Bh ; ESC key
		je	short case_disp_pinf_break
		ja	short case_disp_pinf_DEF
		or	al,al
		jz	short case_disp_pinf_break ; NO, 'N'
		dec	al
		jz	short case_disp_pinf_1 ; YES, 'Y'
case_disp_pinf_DEF:
		call	internal_program_error
		jmp	short case_disp_pinf_break
case_disp_pinf_1:
		call	display_volume_information
		jmp	short case_disp_pinf_break
disp_wait_for_esc:
		call	wait_for_ESC
case_disp_pinf_break:
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		
		call	CLS

		;mov	sp,bp
		pop	bp
		retn

display_menu_5:
		; 31/12/2018
		mov	al,[cur_disk]
		add	al,'1'
		mov	[insert],al
		;push	word [menu_5_segment]
		push	ds
		push	word [menu_5_offset]
		call	display
		;pop	bx
		;pop	bx
		retn

display_menu_11:
		; 31/12/2018
		;push	word [menu_11_segment]
		push	ds
		push	word [menu_11_offset]
		call	display
		;pop	bx
		;pop	bx
		retn

; ----------------------------------------------------------------------------
; tdisplay.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 16/12/2018)

;/*  */
;char table_display()
;
;BEGIN
;
;    unsigned    i;
;    unsigned    io;
;    char       *ThisPartitionType;
;    char        ThisPartitionLetter[3];
;    FLAG        partition_found;
;    char        partition_num;
;
;    memset(insert,c(' '),4*38);
;    io = u(0);
;
;    /* Get current drive letters */
;    get_letters();
;
;    /* Sort the partitions */
;    sort_part_table(c(4));
;
;    /* loop thru the partitions, only print stuff if it is there */
;    partition_found = FALSE;
;    partition_num = c(0);
;
;    for (i=u(0); i < u(4); i++)
;        BEGIN
;
;        if (part_table[cur_disk][sort[i]].sys_id != uc(0))
;            BEGIN
;
;            partition_found = TRUE;
;
;            strcpy(ThisPartitionLetter,"  ");
;            switch(part_table[cur_disk][sort[i]].sys_id)
;                BEGIN
;                case DOSNEW:
;                case DOS16:
;                case DOS12:
;                    ThisPartitionType = DOS_part;
;                    sprintf(ThisPartitionLetter,"%c%c",
;                            part_table[cur_disk][sort[i]].drive_letter,
;                            ( part_table[cur_disk][sort[i]].drive_letter == c(' ') ) ? ' ' : ':');
;                    break;
;                case EXTENDED:
;                    ThisPartitionType = EXTENDED_part;
;                    break;
;                case BAD_BLOCK:
;                    ThisPartitionType = BAD_BLOCK_part;
;                    break;
;                case XENIX1:
;                    ThisPartitionType = XENIX_part;
;                    break;
;                case XENIX2:
;                    ThisPartitionType = XENIX_part;
;                    break;
;                case PCIX:
;                    ThisPartitionType = PCIX_part;
;                    break;
;                case HPFS:
;                    ThisPartitionType = HPFS_part;
;                    break;
;                case NOVELL:
;                    ThisPartitionType = NOVELL_part
;                    break;
;                case CPM:
;                    ThisPartitionType = CPM_part;
;                    break;
;                default:
;                    ThisPartitionType = NON_DOS_part;
;                    break;
;                END
;
;            io += sprintf(&insert[io],"%-2.2s%c%c%-7.7s%-11.11s%4.0d%-8.8s%3.0d%%",
;                       ThisPartitionLetter,
;                       partition_num+'1',
;                       (part_table[cur_disk][sort[i]].boot_ind == uc(0x80)) ? 'A' : ' ',
;                       ThisPartitionType,
;                       part_table[cur_disk][sort[i]].vol_label,
;                       part_table[cur_disk][sort[i]].mbytes_used,
;                       part_table[cur_disk][sort[i]].system,
;                       part_table[cur_disk][sort[i]].percent_used);
;
;            partition_num++;
;
;            END
;
;        END
;
;    /* Do a clearscreen to erase previous data */
;    clear_screen(u(8),u(0),u(12),u(79));
;
;    if (partition_found) display(menu_14);
;        else display(status_8);
;
;    /* Return true if partitions exist, false otherwise */
;    if (partition_found) return(TRUE);
;
;    return(FALSE);
;
;END

; IBM PC-DOS 7.0, FDISK.COM (unpacked) Segment 0, Offset 3D20h

table_display:

%define td_i                bp-14 ; unsigned int, word
%define partition_num       bp-12 ; char, byte
%define td_io               bp-10 ; unsigned int, word		
%define partition_found	    bp-8  ; flag, byte
%define ThisPartitionType   bp-6  ; word, near pointer
%define ThisPartitionLetter bp-4  ; 4 chars (array), dword

		push	bp
		mov	bp,sp
		sub	sp,14
		;push	si

		;mov	ax,152 ; 4*38
		;push	ax
		;mov	ax,' '
		;push	ax
		;mov	ax,insert
		;push	ax
		;call	memset
		;add	sp,6

		;push	di
		mov	cx,152 ; 4*38
		mov	di,insert
		mov	al,' '
		rep 	stosb
		;pop	di
				
		call	get_letters

		;mov	al,4
		;push	ax

		mov	cl,4
		call	sort_part_table
		;pop	bx

		;sub	al,al ; 0
		sub	ax,ax
		mov	[partition_found],al
		mov	[partition_num],al
		;sub	ax,ax
		mov	[td_io],ax ; 0
		mov	[td_i],ax ; 0
		;jmp	td_16
		jmp	td_17
td_ptype_PRIDOS:
		mov	ax,[PRIDOS]
		mov	[ThisPartitionType],ax

		;;mov	al,[cur_disk]
		;;;cbw
		;;;shl	ax,1
		;;;shl	ax,1
		;;shl	al,1
		;;shl	al,1
		;mov	cl,[cur_disk]
		;shl	cl,1
		;shl	cl,1
		;mov	bx,[td_i]
		;;;mov	cx,ax
		;;mov	cl,al
		;mov	al,[sort+bx]
		;;cbw
		;;add	ax,cx
		;add	al,cl
		;;mov	cx,46
		;;imul	cx
		;mov	cl,46
		;mul	cl
		;;mov	bx,ax
		;
		;mov	si,ax ; *=*

		mov	si,bx ; *=*

		;cmp	byte [part_table_drive_letter+bx],' '
		cmp	byte [part_table_drive_letter+si],' '
		jne	short td_02
		mov	ax,' '
		jmp	short td_03
td_02:
		mov	ax,':'
td_03:
		push	ax
		mov	al,[part_table_drive_letter+bx]
		;cbw
		push	ax
		mov	ax,twochars ; "%c%c"
		push	ax
		lea	ax,[ThisPartitionLetter]
		push	ax
		call	sprintf
		add	sp,8
td_04:
		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;shl	al,1
		;shl	al,1
		;mov	bx,[td_i]
		;;mov	cx,ax
		;mov	cl,al
		;mov	al,[sort+bx]
		;;cbw
		;;add	ax,cx
		;add	al,cl
		;mov	cx,46
		;;imul	cx
		;mul	cl
		;;mov	bx,ax
		;mov	si,ax

		mov	bx,si ; *=*
td_05:
		push	word [part_table_percent_used+bx]
		add	bx,part_table_system
		push	bx
		;mov	bx,ax
		;push	word [part_table_mbytes_used+bx]
		push	word [part_table_mbytes_used+si]
		;add	ax,part_table_vol_label
		;push	ax
		mov	ax,si
		add	ax,part_table_vol_label
		push	ax
		push	word [ThisPartitionType]
		;cmp	byte [part_table_boot_ind+bx],80h
		cmp	byte [part_table_boot_ind+si],80h
		jne	short td_13
		mov	ax,'A'
		jmp	short td_14
td_ptype_EXTENDED:
		mov	ax,[EXTDOS]
td_06:
		mov	[ThisPartitionType],ax
		mov	si,bx ; *=* ; 16/12/2018
		;jmp	short td_04
		jmp	short td_05 ; 17/12/2018
td_ptype_TABLE:
		mov	ax,[TABLE]
		jmp	short td_06
td_ptype_XENIX:
		mov	ax,[XENIX]
		jmp	short td_06
td_ptype_PCIX:
		mov	ax,[PCIX]
		jmp	short td_06
;td_ptype_HPFS:
td_ptype_NTFS:
		;mov	ax,[HPFS]
		mov	ax,[NTFS] ; 16/12/2018
		jmp	short td_06
td_ptype_NOVELL:
		mov	ax,[NOVELL]
		jmp	short td_06
td_ptype_CPM:
		mov	ax,[CPM]
		jmp	short td_06
td_13:
		mov	ax,' '
td_14:
		push	ax
		mov	al,[partition_num]
		;cbw
		;add	ax,'1'
		add	al,'1'
		push	ax
		lea	ax,[ThisPartitionLetter]
		push	ax
		mov	ax,ptbl_row_format ; "%-2.2s%c%c%-7.7s%-11.11s%4.1d%-8.8s%3.1"...
		push	ax
		mov	ax,[td_io]
		add	ax,insert
		push	ax
		call	sprintf
		add	sp,20
		add	[td_io],ax

		inc	byte [partition_num]
td_15:
		inc	byte [td_i]
td_16:
		cmp	byte [td_i],4
		jb	short td_17
		jmp	td_29
td_17:
		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;shl	al,1
		;shl	al,1
		;mov	bx,[td_i]
		;;mov	cx,ax
		;mov	cl,al
		mov	cl,[cur_disk]
		shl	cl,1
		shl	cl,1
		mov	bx,[td_i]
		mov	al,[sort+bx]
		;cbw
		;add	ax,cx
		add	al,cl
		mov	cx,46
		;imul	cx
		mul	cl
		;mov	si,ax ; *=*
		;mov	bx,si ; *=*
		mov	bx,ax ; *=*

		;cmp	byte [part_table_sys_id+si],0
		cmp	byte [part_table_sys_id+bx],0
		je	short td_15

		mov	byte [partition_found],1
		
		;;mov	ax,twospace ; "	 "
		;;push	ax
		;;lea	ax,[ThisPartitionLetter]
		;;push	ax
		;;call	strcpy
		;;pop	bx
		;;pop	bx

		mov	si,twospace
		lea	di,[ThisPartitionLetter]
		call	strcpy

		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;shl	al,1
		;shl	al,1
		;mov	bx,[td_i]
		;;mov	cx,ax
		;mov	cl,al
		;mov	al,[sort+bx]
		;;cbw
		;;add	ax,cx
		;add	al,cl
		;mov	cx,46
		;;imul	cx
		;mul	cl
		;mov	bx,ax

		mov	al,[part_table_sys_id+bx]
		;sub	ah,ah
		;dec	ax
		dec	al
		jnz	short td_18	; > 01h
		jmp	td_ptype_PRIDOS
td_18:
		;dec	ax
		dec	al
		jnz	short td_19	; > 02h
		jmp	td_ptype_XENIX
td_19:
		;dec	ax
		dec	al
		jnz	short td_20	; > 03h
		jmp	td_ptype_XENIX
td_20:
		;dec	ax
		dec	al
		jnz	short td_21	; > 04h
		jmp	td_ptype_PRIDOS
td_21:
		;dec	ax
		dec	al
		jnz	short td_22	; > 05h
		jmp	td_ptype_EXTENDED
td_22:
		;dec	ax
		dec	al
		jnz	short td_23	; > 06h
		jmp	td_ptype_PRIDOS
td_23:
		;dec	ax
		dec	al
		jnz	short td_24	; > 07h
		;jmp	td_ptype_HPFS
		jmp	td_ptype_NTFS ; 16/12/2018
td_24:
		;sub	ax,5Dh
		sub	al,5Dh
		jnz	short td_25	; > 64h
		;jb	short td_28
		;ja	short td_25
		jmp	td_ptype_NOVELL
td_25:
		;sub	ax,11h
		sub	al,11h
		jnz	short td_26	; > 75h
		;jb	short td_28
		;ja	short td_26
		jmp	td_ptype_PCIX
td_26:
		;sub	ax,66h
		sub	al,66h
		jnz	short td_27	; > DBh
		;jb	short td_28
		;ja	short td_27
		jmp	td_ptype_CPM
td_27:
		;sub	ax,24h
		sub	al,24h
		jnz	short td_28	; <> FFh
		jmp	td_ptype_TABLE
td_28:
		mov	ax,[NONDOS]
		jmp	td_06
td_29:
		mov	ax,79
		push	ax
		mov	ax,12
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,8
		push	ax
		call	clear_screen
		;add	sp,8

		cmp	byte [partition_found],0
		je	short td_30
		
		;push	word [menu_14_segment]
		push	ds
		push	word [menu_14_offset]
		jmp	short td_31
td_30:
		;push	word [status_8_seg]
		push	ds
		push	word [status_8_off]
td_31:
		call	display
		;pop	bx
		;pop	bx

		;cmp	byte [partition_found],0
		;je	short td_32
		;mov	al,1
		;jmp	short td_33
;td_32:
		;sub	al,al ; 0

		mov	al,[partition_found]
		cmp	al,1	
;td_33:
		;pop	si
		mov	sp,bp
		pop	bp
		retn

; ----------------------------------------------------------------------------
; display.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 16/12/2018)

;void number_in_msg(number,start)
;
;XFLOAT      number;
;unsigned    start;
;
;BEGIN
;
;char    mbytes[32];
;
;        /* Divide the space down and get it into decimal */
;        sprintf(mbytes,"%4.0d",number);
;        insert[start+0] = mbytes[0];
;        insert[start+1] = mbytes[1];
;        insert[start+2] = mbytes[2];
;        insert[start+3] = mbytes[3];
;
;        return;
;
;END

number_in_msg:
		; 16/12/2018

	;%define numinmsg_mb	bp-32
	%define numinmsg_mb	bp-4	

	%define numinmsg_num	bp+4
	%define numinmsg_start	bp+6

		push	bp
		mov	bp,sp
		;sub	sp,32
		sub	sp,4

		push	word [numinmsg_num]
		mov	ax,numinmsg_format ; "%4.1d"
		push	ax
		lea	ax,[numinmsg_mb]
		push	ax
		call	sprintf
		;add	sp,6

		mov	bx,[numinmsg_start]

		;mov	al,[numinmsg_mb]
		;mov	[insert+bx],al
		;mov	al,[numinmsg_mb+1]
		;mov	[insert+1+bx],al
		;mov	al,[numinmsg_mb+2]
		;mov	[insert+2+bx],al
		;mov	al,[numinmsg_mb+3]
		;mov	[insert+3+bx],al

		mov	ax,[numinmsg_mb]
		mov	[bx+insert],ax
		mov	ax,[numinmsg_mb+2]
		mov	[bx+insert+2],ax

		mov	sp,bp
		pop	bp
		;retn
		retn	4 ; 17/12/2018

; ----------------------------------------------------------------------------
; partinfo.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 16/12/2018)

;char find_logical_drive()
;
;BEGIN
;
;unsigned  char  i;
;
;       /* See if there is a logical drive defined in Extended Partition */
;       for (i = uc(0); i < uc(23);i++)
;          BEGIN
;
;           /* See if we find a sys id that is not 0 */
;           if (ext_table[cur_disk][i].sys_id != uc(0))
;              BEGIN
;               return(TRUE);
;               break;
;              END
;          END
;        return(FALSE);
;END

find_logical_drive:
		; 16/12/2018

	;%define findlogdrv_i bp-2
	
		;push	bp
		;mov	bp,sp
		;sub	sp,2
		
		;mov	word [findlogdrv_i],0
		;jmp	short findlogdrv_2
		
		xor	dx,dx
		jmp	short findlogdrv_3		
findlogdrv_1:
		;inc	byte [findlogdrv_i]
		inc	dl
findlogdrv_2:
		;cmp	byte [findlogdrv_i],23
		cmp	dl,23
		jnb	short findlogdrv_4
findlogdrv_3:
		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]
		;mov	cl,[findlogdrv_i]
		;;sub	ch,ch
		;;add	ax,cx
		;add	al,cl
		
		add	al,dl
		
		;mov	cx,46
		;imul	cx
		
		mov	cl,46
		mul	cl
		mov	bx,ax
		cmp	byte [ext_table_sys_id+bx],0
		je	short findlogdrv_1
		mov	al,1
		jmp	short findlogdrv_5 ; cf = 0
findlogdrv_4:
		sub	al,al
		stc
findlogdrv_5:
		;mov	sp,bp
		;pop	bp
		retn

; ----------------------------------------------------------------------------
; input.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 16/12/2018)

;/*  */
;
;char get_yn_input(input_default,row,col)
;
;unsigned        row;
;unsigned        col;
;char            input_default;
;
;BEGIN
;
;    char   input;
;    char   default_used;
;    char   input_value;
;
;    char   attribute;
;    char far *attribute_ptr = &attribute;
;    char far *input_ptr = &input;

;    if (mono_flag == TRUE)
;/*C09   attribute = GRAY_ON_BLACK;  */
;        attribute = HIWHITE_ON_BLACK; /*C09*/
;    else
;/*C09   attribute = WHITE_ON_BLUE;  */
;        attribute = HIWHITE_ON_BLUE;  /*C09*/
;
;    /* print default entry if there is one */
;    if (input_default != c(NUL))
;
;        BEGIN
;        default_used = TRUE;
;        /* position the cursor */
;        VIOSETCURPOS(row,col,u(0));
;
;        /* Display the default character */
;		 input = input_default;
;		 VIOWRTCHARSTRATT(input_ptr,u(1),row,col,attribute_ptr,u(0));
;        END
;
;    /* Assume bad input */
;    valid_input = FALSE;
;
;    /* Loop until we get good stuff */
;    while (valid_input == FALSE)
;        BEGIN
;
;        /* position the cursor */
;        VIOSETCURPOS(row,col,u(0));
;
;        /* Flush the keyboard buffer and get the next pressed key */
;        input = get_char_input();
;        input = dos_upper(input);
;
;        /* Go handle different inputs */
;        switch(input)
;            BEGIN
;            case ESC:
;                BEGIN
;                valid_input = TRUE;
;                break;
;                END
;
;            case  CR:
;                BEGIN
;                /* Set the input to the default if there is one there */
;                if (default_used)
;                    BEGIN
;                    if (input_default != c(NUL))
;                        BEGIN
;                        input_value = input_default;
;                        END
;                    else
;                        BEGIN
;                        internal_program_error();
;                        END
;                    END
;
;                /* See if YES or NO */
;
;                /* Do world trade get country information */
;                input = check_yn_input(input_value);
;
;                if ((input == c(1)) || (input == c(0)))
;                    BEGIN
;                    valid_input = TRUE;
;                    END
;                else
;                    BEGIN
;                    /* Setup error message */
;                    insert[0] = c(Yes);
;                    insert[1] = c('-');
;                    insert[2] = c(No);
;                    display(error_31);
;                    END
;                break;
;                END
;
;            default:
;                BEGIN
;                if ((check_yn_input(input) == c(1)) ||             /*C16*/
;                    (check_yn_input(input) == c(0)))               /*C16*/
;                    clear_screen(u(23),u(0),u(23),u(79));          /*C16*/
;                else                                               /*C16*/
;                    {                                              /*C16*/
;                    /* Setup error message */                      /*C16*/
;                    insert[0] = c(Yes);                            /*C16*/
;                    insert[1] = c('-');                            /*C16*/
;                    insert[2] = c(No);                             /*C16*/
;                    display(error_31);                             /*C16*/
;                    input = c(' ');                                /*C16*/
;                    }                                              /*C16*/
;                VIOWRTCHARSTRATT(input_ptr,u(1),row,col,attribute_ptr,u(0)); /*C16*/
;                default_used = FALSE;
;                input_value = input;
;                break;
;                END
;            END
;         END
;     return(input);
;END

get_yn_input:
		; 16/12/2018

	%define gyn_input_val	bp-16 ; byte, char 
	%define gyn_attr_ptr	bp-14 ; dword, far ptr
	%define gyn_def_used	bp-10 ; byte, char
	%define gyn_input_ptr	bp-8  ; dword, far ptr
	%define gyn_attribute	bp-4  ; byte, char
	%define gyn_input	bp-2  ; byte, char
	%define gyn_input_def	bp+4  ; byte, char 
	%define gyn_row		bp+6  ; word, unsigned int
	%define gyn_column	bp+8  ; word, unsigned int

		push	bp
		mov	bp,sp
		sub	sp,16

		lea	ax,[gyn_attribute]
		mov	[gyn_attr_ptr],ax
		mov	[gyn_attr_ptr+2],ss
		lea	cx,[gyn_input]
		mov	[gyn_input_ptr],cx
		mov	[gyn_input_ptr+2],ss

		cmp	byte [mono_flag],1 ; TRUE
		jne	short gyni_1
		mov	byte[gyn_attribute],0Fh  ; HIWHITE_ON_BLACK
		jmp	short gyni_2
gyni_1:
		mov	byte [gyn_attribute],1Fh ; HIWHITE_ON_BLUE
gyni_2:
		cmp	byte [gyn_input_def],0
		je	short gyni_3

		;mov	[gyn_def_used],1

		;push	word [gyn_row]
		;push	word [gyn_column]
		;sub	ax,ax
		;push	ax
		mov	dh,[gyn_row]
		mov	dl,[gyn_column]
		call	VIOSETCURPOS

		mov	al,[gyn_input_def]
		mov	[gyn_input],al
		push	word [gyn_input_ptr+2]
		push	word [gyn_input_ptr]
		mov	ax,1
		push	ax
		push	word [gyn_row]
		push	word [gyn_column]
		push	word [gyn_attr_ptr+2]
		push	word [gyn_attr_ptr]
		;sub	ax,ax
		;push	ax
		call	VIOWRTCHARSTRATT
gyni_3:
		mov	byte [valid_input],0
gyni_4:
		;push	word [gyn_row]
		;push	word [gyn_column]
		;sub	ax,ax
		;push	ax
		mov	dh,[gyn_row]
		mov	dl,[gyn_column]
		call	VIOSETCURPOS

		call	get_char_input
		;mov	[gyn_input], al
		
		;push	ax
		call	dos_upper
		;pop	bx
		mov	[gyn_input],al
switch_input11:
		;cbw
		;sub	ax,0Dh
		sub	al,0Dh
		jz	short case_gyni_CR
		;sub	ax,0Eh
		sub	al,0Eh
		jz	short case_gyni_ESC
case_gyni_DEF:
		; Check if character represents country relative
		; Yes or No response 

		;mov	al,[gyn_input]
		;push	ax
		;call	check_yn_input
		;pop	bx
		;dec	al
		;jz	short gyni_7  ; al = 1 = YES

		;cmp	al,1
		;ja	short gyni_13 ; al = 2 = not a valid YES or NO character

		;mov	al,[gyn_input]
		;;push	ax
		;call	check_yn_input
		;;pop	bx
		;or	al,al
		;jnz	short gyni_13

		mov	dl,[gyn_input]
		call	check_yn_input
		jc	short gyni_13
gyni_7:
		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	cx,cx
		push	cx
		push	ax
		call	clear_screen
		;add	sp,8
		jmp	short gyni_14
case_gyni_CR:
		cmp	byte [gyn_def_used],0
		je	short gyni_10
		cmp	byte [gyn_input_def],0
		je	short gyni_9
		mov	al,[gyn_input_def]
		mov	[gyn_input_val],al
		jmp	short gyni_10
gyni_9:
		call	internal_program_error
gyni_10:
		;mov	al,[gyn_input_val]
		;push	ax
		;call	check_yn_input
		;pop	bx
		;mov	[gyn_input],al
		;cmp	al,1
		;je	short case_gyni_ESC
		;or	al,al
		;jnz	short gyni_12
		
		mov	dl,[gyn_input_val]
		call	check_yn_input
		jc	short gyni_12
		mov	[gyn_input],al
case_gyni_ESC:
		mov	byte [valid_input],1
		;jmp	short gyni_15
		jmp	short gyni_16
gyni_12:
		mov	al,[Yes]
		mov	[insert],al
		mov	byte [insert+1],'-'
		mov	al,[No]
		mov	[insert+2],al
		;push	word [error_31_seg]
		push	ds
		push	word [error_31_off]
		call	display
		;pop	bx
		;pop	bx
		
		;jmp	short gyni_15
		jmp	short gyni_4
gyni_13:
		mov	al,[Yes]
		mov	[insert],al
		mov	byte [insert+1],'-'
		mov	al,[No]
		mov	[insert+2],al
		;push	word [error_31_seg]
		push	ds
		push	word [error_31_off]
		call	display
		;pop	bx
		;pop	bx
		mov	byte [gyn_input],' ' ; 20h
gyni_14:
		push	word [gyn_input_ptr+2]
		push	word [gyn_input_ptr]
		mov	ax,1
		push	ax
		push	word [gyn_row]
		push	word [gyn_column]
		push	word [gyn_attr_ptr+2]
		push	word [gyn_attr_ptr]
		;sub	ax,ax
		;push	ax
		call	VIOWRTCHARSTRATT
		
		mov	byte [gyn_def_used],0
		mov	al,[gyn_input]
		mov	[gyn_input_val],al
gyni_15:
		cmp	byte [valid_input],0
		jne	short gyni_16
		jmp	gyni_4
gyni_16:
		mov	al,[gyn_input]
		mov	sp,bp
		pop	bp
		;retn
		retn	6 ; 17/12/2018

; input.c - wait_for_ESC
; ----------------------------------------------------------------------------

;char wait_for_ESC()
;
;BEGIN
;    char  input;
;
;    clear_screen(u(24),u(0),u(24),u(79));
;    display(menu_46);
;    while (input != c(ESC))
;        BEGIN
;        /* position the cursor at the end of the ESC prompt */
;        VIOSETCURPOS(input_row,input_col,u(0));
;
;        /* Get input */
;        input = get_char_input();
;        END
;    return(c(ESC));
;END

wait_for_ESC:
		; 16/12/2018

		;%define wfesc_input bp-2

		;push	bp
		;mov	bp,sp
		;sub	sp,2

		; 17/12/2018
		mov	ax,79
		push	ax	; Bottom Rigth Column (79)  
		mov	ax,24
		push	ax	; Bottom Row (24)
		sub	cx,cx
		push	cx	; Top Left Column (0)	
		push	ax	; Top Row (24)
		call	clear_screen  ;	clear row
		;add	sp,8

		;push	word [menu_46_segment]
		push	ds
		push	word [menu_46_offset]
		call	display
		;pop	bx
		;pop	bx
		jmp	short wfesc_2
wfesc_1:
		;push	word [input_row]
		;push	word [input_col]
		;sub	ax,ax
		;push	ax
		mov	dh,[input_row]
		mov	dl,[input_col]
		call	VIOSETCURPOS
		
		call	get_char_input
		;mov	[wfesc_input],al
wfesc_2:
		;cmp	[wfesc_input],1Bh ; ESC key
		;jne	short wfesc_1
		;mov	al,1Bh

		cmp	al,1Bh ; ESC key
		jne	short wfesc_1

		;mov	sp,bp
		;pop	bp
		
		retn

; ----------------------------------------------------------------------------
; convert.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 16/12/2018)

;/***************************************************************************/
;/*Routine name:  CHECK_YN_INPUT                                            */
;/***************************************************************************/
;/*                                                                         */
;/*Description:   Get single character input, which must be a country       */
;/*               dependent (Y/N). Will be verified using new uppercase     */
;/*               table function calls. Will accept default value.          */
;/*                                                                         */
;/*Called Procedures:                                                       */
;/*                                                                         */
;/*                                                                         */
;/*Change History: Updated        5/31/87         DRM                       */
;/*                                                                         */
;/*Input: input_value                                                       */
;/*                                                                         */
;/*Output: input                                                            */
;/*        valid_input                                                      */
;/*                                                                         */
;/***************************************************************************/

;char check_yn_input(input_value)
;
;        char   input_value;
;
;BEGIN
;        char   input;
;
;        /* Get extended country information */
;        regs.x.ax = (unsigned)CAP_YN;
;        /* Move input_value to register DL  */
;        regs.h.dl = (unsigned char)input_value;
;        int86((int)INT21,&regs,&regs);
;
;        /* check carry flag for error */
;        if ((regs.x.cflag & CARRY_FLAG) == CARRY_FLAG)
;        /* input will be 0 for NO and 1 for YES in AX */
;           input = c(NO_GOOD);    /* input will equal not 0 or 1 */
;        else
;           input = c(regs.x.ax);
;
;        return(input);
;END

check_yn_input:
		; 16/12/2018

	%define	yn_input bp-2
	%define yn_input_value bp+4

		;push	bp
		;mov	bp,sp
		;sub	sp,2

		;mov	[regs_x_ax],6523h
		;mov	al,[yn_input_value]
		;mov	[regs_x_dx],al
		;mov	ax,regs
		;push	ax
		;push	ax
		;mov	ax,21h
		;push	ax
		;call	int86
		;add	sp,6
		;mov	al,[regs_x_cflag]
		;and	al,1
		;cmp	al,1
		;jnz	short cyni_1
		;mov	byte [yn_input],2
		;jmp	short cyni_2
;cyni_1:
		;mov	al,[regs_x_ax]
		;mov	[yn_input],al
;cyni_2:	
		;mov	al,[yn_input]
		;mov	sp,bp
		;pop	bp
		;retn

		; INT 21h
		;   INPUT:
		;      AH = 65h 
		;	    Get Extended Country Information (DOS 3.3+)
		;      AL = 23h
		;	    Determine if character represents 
		;	    country relative Yes or No response (DOS 4+)
		;
		;      DL = Character to be tested
		;			
		;   OUTPUT:
		;      AX = error code if CF is set
	  	;	  = 00h : NO response
	   	;	  = 01h : YES response
	  	;	  = 02h : not a yes or no response

		;mov	dl,al

		mov	ax,6523h
		int	21h
		jc	short cyni_1
		or	al,al
		jz	short cyni_1
		cmp	al,2
		cmc	
cyni_1:
		retn

; ============================================================================
;  DISPLAY VOLUME INFORMATION
; ============================================================================
; 16/12/2018

; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/*  Screen for DISPLAY_VOLUME_INFORMATION                                                          */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                     Display Logical DOS Drive Information                      |menu_37   */
;/*   02|                                                                                |          */
;/*   03|Drv Volume Label  Mbytes  System  Usage  Drv Volume Label  Mbytes  System  Usage|menu_19/20*/
;/*   04|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   05|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   16|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   17|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   18|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   19|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   10|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   11|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   12|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   13|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   14|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|          */
;/*   15|##  #############  ####  ########  ###%                                         |          */
;/*   16|                                                                                |          */
;/*   17|    Total Extended DOS partition size is #### Mbytes (1 Mbyte = 1048576 bytes)  |menu_17   */
;/*   18|                                                                                |          */
;/*   19|                                                                                |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */
;/*                                                                                                 */
;/***************************************************************************************************/

; ----------------------------------------------------------------------------
; fdisk.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 17/12/2018)

;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: DISPLAY_VOLUME_INFORMATION                 */
;/*                                                             */
;/* DESCRIPTIVE NAME: Display DOS disk Volume Information       */
;/*                                                             */
;/* FUNCTION: Displays disk volume size and existence           */
;/*                                                             */
;/* NOTES:                                                      */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*     |0000000000111111111122222222223333333333|              */
;/*     |0123456789012345678901234567890123456789|              */
;/*   --|----------------------------------------|              */
;/*   01|Display DOS Disk Volume Information     |              */
;/*   02|                                        |              */
;/*   03|Vol Start End  Size  Vol Start End  Size|              */
;/*   04| #  ####  #### ####   #  ####  #### ####|              */
;/*   05|                                        |              */
;/*   06|                                        |              */
;/*   07|                                        |              */
;/*   08|                                        |              */
;/*   09|                                        |              */
;/*   10|                                        |              */
;/*   11|                                        |              */
;/*   12|                                        |              */
;/*   13|                                        |              */
;/*   14|                                        |              */
;/*   15|                                        |              */
;/*   16|                                        |              */
;/*   17|                                        |              */
;/*   18|                                        |              */
;/*   19|                                        |              */
;/*   20|                                        |              */
;/*   21|                                        |              */
;/*   22|                                        |              */
;/*   23|Press ESC to return to FDISK Options    |              */
;/*   --------------------------------------------              */
;/*                                                             */
;/* ENTRY POINTS: Display_Volume_Information                    */
;/*      LINKAGE: display_volume_information ()                 */
;/*          NEAR CALL                                          */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      wait_for_ESC                                           */
;/*      display                                                */
;/*      volume_display                                         */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;void display_volume_information()
;
;BEGIN
;
;    char   input;
;    char    temp;
;
;    input = c(NUL);
;    /* clear the screen */
;    clear_screen(u(0),u(0),u(24),u(79));
;
;    /* Display Header */
;    display(menu_37);
;
;    /* Display information */
;    temp = volume_display();
;
;    /* Set up partition size message */
;    sprintf(insert,"%4.0d",get_partition_size( uc(EXTENDED) ) );
;    display(menu_21);
;
;    /* print ESC prompt */
;    display(menu_11);
;
;    /* Wait to exit */
;    input = wait_for_ESC();
;    return;
;END

; IBM PC-DOS 7.0 FDISK.COM (unpacked) /// Segment 0, Offset 20FCh 

display_volume_information:
		; 17/12/2018	
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS ; 18/02/2018

		;push	word [menu_37_segment]
		push	ds
		push    word [menu_37_offset]
		call    display
		;pop	bx
		;pop	bx

		call    volume_display

		;;mov	al,5
		;;push	ax
		;mov	dh,5
		;call	get_partition_size
		;;pop	bx
		;push 	ax
		;mov	ax,p_size_format ; "%4.1d"
		;push	ax
		;mov     ax,insert
		;push    ax
		;call    sprintf
		;add	sp,6
		;
		;;push	word [menu_21_segment]
		;push	ds
		;push	word [menu_21_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_ext_partition_size ; 31/12/2018

		;;push	word [menu_11_segment]
		;push	ds
		;push	word [menu_11_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_11 ; 31/12/2018

		jmp     wait_for_ESC

; 31/12/2018
display_ext_partition_size:
		;mov	al,5
		;push	ax
		mov	dh,5
		call	get_partition_size
		;pop	bx
		push    ax
		mov	ax,p_size_format ; "%4.1d"
		push	ax
		mov     ax,insert
		push    ax
		call    sprintf
		add	sp,6

		;push	word [menu_21_segment]
		push	ds
		push	word [menu_21_offset]
		call	display
		;pop	bx
		;pop	bx

		retn

; ----------------------------------------------------------------------------
; vdisplay.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 18/12/2018)

;/*  */
;char volume_display()
;
;BEGIN
;
;    unsigned    i;
;
;    char        drive_found;
;    char        drive_letter;
;    char        drive_num;
;
;    char        first_display;
;    char        second_display;
;    char        third_display;
;    char        fourth_display;
;    unsigned    insert_offset;
;
;    first_display = FALSE;
;
;    /* get the current drive letters */
;    get_letters();
;
;    /* loop thru the partitions, only print stuff if it is there */
;
;    /* Get the drives in order by location on disk */
;    sort_ext_table(c(23));
;
;    /* initialize all the inserts to blanks */
;    memset(insert,c(' '),(24*29));
;
;    drive_num = c(0);
;    drive_found = FALSE;
;    first_display = TRUE;
;    insert_offset = 0;
;
;    for (i=u(0); i < u(23); i++)
;       BEGIN
;
;        /* See if entry exists */
;        if ( (ext_table[cur_disk][sort[i]].sys_id == uc(DOS12)) ||
;             (ext_table[cur_disk][sort[i]].sys_id == uc(DOS16)) ||
;             (ext_table[cur_disk][sort[i]].sys_id == uc(DOSNEW)) )
;           BEGIN
;
;            /* We found one, now get the info */
;            drive_found = TRUE;
;
;            insert_offset += sprintf(&insert[insert_offset],"%c%c%-11.11s%4.0d%-8.8s%3.0d%%",
;                    ext_table[cur_disk][sort[i]].drive_letter,
;                    ( ext_table[cur_disk][sort[i]].drive_letter == c(' ') ) ? ' ' : ':',
;                    ext_table[cur_disk][sort[i]].vol_label,
;                    ext_table[cur_disk][sort[i]].mbytes_used,
;                    ext_table[cur_disk][sort[i]].system,
;                    ext_table[cur_disk][sort[i]].percent_used );
;
;            drive_letter = ext_table[cur_disk][sort[i]].drive_letter;
;            drive_num++;
;
;           END
;       END
;
;    /* Display the column of drives */
;    if (drive_found)
;       BEGIN
;
;        clear_screen(u(2),u(0),u(15),u(79));
;
;        if ( drive_num > 0 )
;            BEGIN
;            pinsert = &insert[0];
;            display(menu_19);
;            END
;
;        if ( drive_num > 6 )
;            BEGIN
;            pinsert = &insert[6*29];
;            display(menu_43);
;            END
;
;        if ( drive_num > 12 )
;            BEGIN
;            pinsert = &insert[12*29];
;            display(menu_20);
;            END
;
;        if ( drive_num > 18 )
;            BEGIN
;            pinsert = &insert[18*29];
;            display(menu_44);
;            END
;        pinsert = &insert[0];
;        END
;    else
;       BEGIN
;        /* Didn't find any */
;        if (first_display)
;           BEGIN
;            /* Wipe out display and put up message */
;            clear_screen(u(2),u(0),u(15),u(79));
;            display(status_9);
;           END
;       END
;    /* Return the highest drive letter found */
;    return(drive_letter);
;END

volume_display:
		; 18/12/2018

	;%define vd_first_display bp-18
	;%define vd_insert_offset bp-14
	;%define vd_i		  bp-12
	;%define vd_drive_letter  bp-10
	;%define vd_drive_num	  bp-8
	;%define vd_drive_found	  bp-6

	%define vd_drive_letter   bp-12 ; 25/12/2018
	%define vd_first_display  bp-10
	%define vd_insert_offset  bp-8
	%define vd_i		  bp-6
	%define vd_drive_num	  bp-4
	%define vd_drive_found	  bp-2

		push	bp
		mov	bp,sp
		;sub	sp,18
		sub	sp,12 ; 02/01/2019
		push	si ; *

		call	get_letters

		;mov	al,23
		;push	ax
		mov	cl,23
		call	sort_ext_table
		;pop	bx

		;mov	ax,696 ; 24*29
		;push	ax
		;mov	ax,' '
		;push	ax
		;mov	ax,insert
		;push	ax
		;call	memset
		;add	sp,6

		mov	al,' '
		mov	cx,696 ; 24*29
		mov	di,insert
		;push	ds
		;pop	es
		rep	stosb

		;sub	al,al
		sub	ax,ax
		mov	[vd_drive_num],al ; 0
		mov	[vd_drive_found],al ; 0

		;mov	byte [vd_first_display],1 ; TRUE

		;sub	ax,ax ; 0
		mov	[vd_insert_offset],ax ; 0
		mov	[vd_i],ax ; 0
		jmp	short vd_05
vd_01:
		mov	ax,':'
vd_02:
		push	ax
		mov	al,[ext_table_drive_letter+si]
		;cbw
		push	ax
		mov	ax,eptbl_row_format ; "%c%c%-11.11s%4.1d%-8.8s%3.1d%%"
		push	ax
		mov	ax,[vd_insert_offset]
		add	ax,insert
		push	ax
		call	sprintf
		add	sp,16
		add	[vd_insert_offset],ax
		
		;mov	al,24
		;;imul	byte [cur_disk]
		;mul	byte [cur_disk]
		;mov	bx,[vd_i]
		;;mov	cx,ax
		;;mov	al,[sort+bx]
		;;cbw
		;mov	cl,[sort+bx]
		;add	al,cl
		;;mov	cx,46
		;;imul	cx
		;mov	cl,46
		;mul	cl
		;mov	bx,ax
		
		;mov	al,[ext_table_drive_letter+bx]
		mov	al,[ext_table_drive_letter+si]
vd_03:
		mov	[vd_drive_letter],al ; 25/12/2018
		inc	byte [vd_drive_num]
vd_04:
		inc	byte [vd_i]
;vd_05:
		cmp	byte [vd_i],23
		jnb	short vd_08
vd_05:
		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]
		mov	bx,[vd_i]
		;mov	cx,ax
		;mov	al,[sort+bx]
		;cbw
		;add	ax,cx
		;mov	cl,[sort+bx]
		;add	al,cl
		add	al,[sort+bx] ; 06/01/2019
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		cmp	byte [ext_table_sys_id+bx],1
		je	short vd_06
		cmp	byte [ext_table_sys_id+bx],4
		je	short vd_06
		cmp	byte [ext_table_sys_id+bx],6
		jne	short vd_04
vd_06:
		mov	byte [vd_drive_found],1
		
		;mov	al,24
		;imul	byte [cur_disk]
		;mov	bx,[vd_i]
		;;mov	cx,ax
		;;mov	al,[sort+bx]
		;;cbw
		;;add	ax,cx
		;mov	cl,[sort+bx]
		;add	al,cl
		;;mov	cx,46
		;;imul	cx
		;mov	cl,46
		;mul	cl
		;mov	si,ax ; -*-

		mov	si,bx ; -*-		

		;push	word [ext_table_percent_used+si]
		;add	si,ext_table_system
		;push	si
		;mov	si,ax
		push	word [ext_table_percent_used+bx]
		add	bx,ext_table_system
		push	bx
		;mov	bx,ax ; -*-
		mov	bx,si ; -*-
		;push	word [ext_table_mbytes_used+si]
		push	word [ext_table_mbytes_used+bx]
		;add	ax,ext_table_vol_label
		;push	ax
		add	bx,ext_table_vol_label
		push	bx
		cmp	byte [ext_table_drive_letter+si],' '
		;je	short vd_07
		;jmp	vd_01
		jne	short vd_01
vd_07:
		mov	ax,' '
		jmp	vd_02
vd_08:
		cmp	byte [vd_drive_found],0
		;jne	short vd_09
		;jmp	vd_14
		je	short vd_14
vd_09:
		mov	ax,79
		push	ax
		mov	ax,15
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,2
		push	ax
		call	clear_screen
		;add	sp,8
		
		cmp	byte [vd_drive_num],0
		;jle	short vd_10
		jna	short vd_13
		
		mov	word [pinsert],insert
		;push	word [menu_19_segment]
		push	ds
		push	word [menu_19_offset]
		call	display
		;pop	bx
		;pop	bx
vd_10:
		cmp	byte [vd_drive_num],6
		;jle	short vd_11
		jle	short vd_13

		mov	word [pinsert],insert+174 ; 6*29
		;push	word [menu_43_segment]
		push	ds
		push	word [menu_43_offset]
		call	display
		;pop	bx
		;pop	bx
vd_11:
		cmp	byte [vd_drive_num],12
		;jle	short vd_12
		jle	short vd_13

		mov	word [pinsert],insert+348 ; 12*129
		;push	word [menu_20_segment]
		push	ds
		push	word [menu_20_offset]
		call	display
		;pop	bx
		;pop	bx
vd_12:
		cmp	byte [vd_drive_num],18
		jle	short vd_13

		mov	word [pinsert],insert+522 ; 18*129
		;push	word [menu_44_segment]
		push	ds
		push	word [menu_44_offset]
		call	display
		;pop	bx
		;pop	bx
vd_13:
		mov	word [pinsert],insert
		jmp	short vd_15
vd_14:
		;cmp	[vd_first_display],0
		;je	short vd_15

		mov	ax,79
		push	ax
		mov	ax,15
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,2
		push	ax
		call	clear_screen
		;add	sp,8

		;push	word [status_9_seg]
		push	ds
		push	word [status_9_off]
		call	display
		;pop	bx
		;pop	bx
vd_15:
		mov	al,[vd_drive_letter] ; 25/12/2018
		
		pop	si ; *
		mov	sp,bp
		pop	bp
		retn

; ----------------------------------------------------------------------------
; fdisk.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 18/12/2018)

;/*  */
;void internal_program_error()
;
;BEGIN
;   display(internal_error);
;   DOSEXIT(u(0),u(0));
;   return;
;END

internal_program_error:

		; 18/12/2018

		;push	word [inter_err_seg]
		push	ds
		push	word [inter_err_off]
		call	display
		;pop	bx
		;pop	bx
		
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	DOSEXIT
		;retn

		sub	ax,ax
		jmp	DOSEXIT

; ----------------------------------------------------------------------------
; partinfo.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 17/12/2018)

;XFLOAT get_partition_size(type) 
;
;unsigned char type;
;
;BEGIN
; char  i;
;
; /*  Look at all four partition entries for system id byte that matches */
; for (i = c(0); i < c(4);i++)
;    BEGIN
;
;     /* if we find a match, get the size */
;     if (part_table[cur_disk][i].sys_id == type)
;        BEGIN
;         /* Get the size of the partition from the array */
;         return(part_table[cur_disk][i].mbytes_used);
;        END
;    END
; /* Did not find one, something bad wrong happened */
; internal_program_error();
;END

get_partition_size:
		; 17/12/2018

	;%define gpz_i	 bp-2
	;%define gpz_type bp+4

		; DH = [gpz_type]

		;push	bp
		;mov	bp,sp
		;;sub	sp,2
		;xor	ax,ax
		;mov	word [gpz_i],ax ; 0
		;push	ax
		;xor	dx,dx
		;xor	dl,dl
		;jmp	short gpz_2
		mov	dl,0FFh ; 19/12/2018
gpz_1:	
		;inc	byte [gpz_i]
		inc	dl
;gpz_2:
		;cmp	byte [gpz_i],4
		cmp	dl,4
		;jge	short gpz_3
		jge	short internal_program_error ; 19/12/2018
gpz_2:
		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	cx,ax

		;mov	cl,[cur_disk]
		;shl	cl,1
		;shl	cl,1
		
		;mov	al,[gpz_i]
		;;cbw
		;;add	ax,cx
		;add	al,cl		
		
		mov	al,[cur_disk]
		shl	al,1
		shl	al,1
		add	al,dl ; [gpz_i]		

		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax

		;mov	al,[gpz_type]
		;cmp	[part_table_sys_id+bx],al
		cmp	[part_table_sys_id+bx],dh ; [gpz_type]
		jne	short gpz_1
		mov	ax,[part_table_mbytes_used+bx]
		;jmp	short gpz_4
		retn	; 19/12/2018
;gpz_3:
		;;call	internal_program_error
		;jmp	internal_program_error ; 19/12/2018
;gpz_4:
		;mov	sp,bp
		;pop	bp
		;retn

; ----------------------------------------------------------------------------
; 18/12/2018

;char find_active_partition()
;
;BEGIN
;
;unsigned  char   i;
;
;       /* See if there is an active partition */
;       for (i = uc(0); i < uc(4);i++)
;         BEGIN
;          /* if we find an active one, TRUE return */
;          if (part_table[cur_disk][i].boot_ind == uc(ACTIVE))
;             BEGIN
;              return(TRUE);
;              break;
;             END
;         END
;       /* Did not find one, return FALSE */
;       return(FALSE);
;END

find_active_partition:
		; 18/12/2018

		;%define fap_i bp-2

		;push	bp
		;mov	bp,sp

		;sub	sp,2
		;mov	word [fap_i],0
		;xor	dx,dx
		;xor	dl,dl
		;jmp	short fap_2
		mov	dl,0FFh ; 19/12/2018
fap_1:
		;inc	byte [fap_i]
		inc	dl
fap_2:
		;cmp	byte [fap_i],4
		cmp	dl,4
		jnb	short fap_3
		
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;mov	cl,[fap_i]
		;;sub	ch,ch
		;;add	ax,cx
		;add	al,cl
		add	al,dl
		;mov	cx,46
		;imul	cx
		mov	cl,46		
		mul	cl
		mov	bx,ax

		cmp	byte [part_table_boot_ind+bx],80h
		jne	short fap_1
		;mov	al,1
		;jmp	short fap_4

		xor	al,al
		inc	al

		; DL = 0  to 3 (active partition number)
		; zf = 0
		; AL = 1

		retn
fap_3:
		sub	al,al

		; DL = 4
		; zf = 1
		; AL = 0
fap_4:
		;mov	sp,bp
		;pop	bp

		retn

; ============================================================================
;  CHANGE ACTIVE INFORMATION
; ============================================================================
; 19/12/2018

; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/*  Screen for CHANGE_ACTIVE_PARTITION                                                             */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                              Set Active Partition                              |menu_23   */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                                                                                |          */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Partition Status   Type    Size in Mbytes   Percentage of Disk Used         |menu_14 # */
;/*   09|     ## #        #   #######       ####         ###%                            |          */
;/*   10|     ## #        #   #######       ####         ###%                            |          */
;/*   11|     ## #        #   #######       ####         ###%                            |          */
;/*   12|     ## #        #   #######       ####         ###%                            |          */
;/*   13|                                                                                |          */
;/*   14|    Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes)                   |menu_15 # */
;/*   15|                                                                                |          */
;/*   16|    Enter the number of the partition you want to make active............:[#]   |menu_24   */
;/*   17|                                                                                |          */
;/*   18|                                                                                |          */
;/*   19|                                                                                |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */
;/*                                                                                                 */
;/***************************************************************************************************/

; ----------------------------------------------------------------------------
; fdisk.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 19/12/2018)

;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: CHANGE_ACTIVE_PARTITION                    */
;/*                                                             */
;/* DESCRIPTIVE NAME: Change bootable partition                 */
;/*                                                             */
;/* FUNCTION: Will allow user to select the partition that will */
;/*           recieve control when system is IPL'd. This is     */
;/*           only for the first hardfile as far as booting is  */
;/*           concerned, although partitions can be set active  */
;/*           the second. There are reserved partitions that may*/
;/*           not be set active and this routine will enforce   */
;/*           that.                                             */
;/*                                                             */
;/* NOTES: If no valid partition is specified, then the active  */
;/*        partition setting is left unchanged. Screen can be   */
;/*        exited via the ESC command before active partition   */
;/*        is changed and no action will take place             */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*     |0000000000111111111122222222223333333333|              */
;/*     |0123456789012345678901234567890123456789|              */
;/*   --|----------------------------------------|              */
;/*   00|                                        |              */
;/*   01|                                        |              */
;/*   02|                                        |              */
;/*   03|                                        |              */
;/*   04|Change Active Partition                 |              */
;/*   05|                                        |              */
;/*   06|Current Fixed Disk Drive: #             |              */
;/*   07|                                        |              */
;/*   08|Partition Status   Type  Start  End Size|              */
;/*   09|    #        #   #######  #### #### ####|              */
;/*   10|                                        |              */
;/*   11|                                        |              */
;/*   12|                                        |              */
;/*   13|                                        |              */
;/*   14|Total disk space is #### cylinders.     |              */
;/*   15|                                        |              */
;/*   16|                                        |              */
;/*   17|                                        |              */
;/*   18|Enter the number of the partition you   |              */
;/*   19|want to make active...............: [#] |              */
;/*   20|                                        |              */
;/*   21|                                        |              */
;/*   22|                                        |              */
;/*   23|Press ESC to return to FDISK Options    |              */
;/*   --------------------------------------------              */
;/*                                                             */
;/* ENTRY POINTS: Change_Active_Partition                       */
;/*      LINKAGE: change_active_partition ()                    */
;/*           NEAR CALL                                         */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if invalid num      */
;/*             input is returned to this level                 */
;/*                                                             */
;/* EFFECTS: Display prompts needed to guide user input, and    */
;/*          gets input from user.                              */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      display                                                */
;/*      get_num_input                                          */
;/*      table_display                                          */
;/*      wait_for_ESC                                           */
;/*      internal_program_error                                 */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;void change_active_partition()
;
;BEGIN
;
;    char   input;
;    unsigned i;
;    unsigned x;
;    char   num_partitions;
;    char   valid_partitions;
;    char   num_of_bootable_partitions;
;    char   valid_input;
;    char   input_default;
;
;    input = c(NUL);
;    /* Clear screen */
;    clear_screen(u(0),u(0),u(24),u(79));
;
;    /* Display header */
;    display(menu_23);
;
;    /* Setup and print current disk */
;    insert[0] = cur_disk+1+'0';
;    display(menu_5);
;
;    /* Only allow active partitions on the first (and bootable) disk */
;    if (cur_disk == c(0))
;
;       BEGIN
;	/* Display partition info and see if any partitions exist*/
;	if (table_display())
;
;	   BEGIN
;	    /* See if active partition is bootable */
;	    for (i=u(0); i < u(4); i++)
;	       BEGIN
;		if (part_table[cur_disk][i].sys_id != uc(0) &&
;		    part_table[cur_disk][i].boot_ind == uc(0x80))
;		   BEGIN
;		    if ((part_table[cur_disk][i].sys_id == uc(BAD_BLOCK)) ||
;			(part_table[cur_disk][i].sys_id==uc(EXTENDED)))
;		       BEGIN
;			/* The active partition is not bootable, so warn user */
;			display(error_24);
;		       END
;		   END
;	       END
;
;	    /* Check to see if only one partition */
;	    num_partitions = c(0) ;
;	    num_of_bootable_partitions = c(0);
;	    for (i=u(0); i < u(4); i++)
;
;	       BEGIN
;		if (part_table[cur_disk][i].sys_id != uc(0))
;		   BEGIN
;		    /* Get a count of partitions */
;		    num_partitions++;
;
;		    /* Get a count of the number of defined partitions but don't*/
;		    /* count those we know aren't bootable */
;		    if ((part_table[cur_disk][i].sys_id != uc(BAD_BLOCK)) &&
;			(part_table[cur_disk][i].sys_id != uc(EXTENDED)))
;		       BEGIN
;			num_of_bootable_partitions++;
;		       END
;		   END
;	       END
;	    /* If only one partition found, see if it is active already */
;	    if (num_of_bootable_partitions == c(1))
;	       BEGIN
;
;		/* Find the partition and see if it is already active */
;		for (i=u(0); i < u(4); i++)
;
;		   BEGIN
;		    if (part_table[cur_disk][i].sys_id !=uc(0) &&
;			part_table[cur_disk][i].boot_ind == uc(0x80))
;
;		       BEGIN
;			/* Make sure it is not unbootable partition again*/
;			if ((part_table[cur_disk][i].sys_id != uc(BAD_BLOCK)) &&
;			    (part_table[cur_disk][i].sys_id!=uc(EXTENDED)))
;
;			   BEGIN
;			    /* Once it is found, put out the message */
;			    display(error_15);
;
;			    /* Wait for ESC, then get out */
;			    wait_for_ESC();
;
;			    /* clear the screen before going back to main menu*/
;			    clear_screen(u(0),u(0),u(24),u(79));
;			    return;
;			   END
;		       END
;		   END
;	       END
;	    /* See if any bootable partitions exist */
;	    if (num_of_bootable_partitions == c(0))
;	       BEGIN
;		/* At this point, we know at least one partition does exist due to*/
;		/* getting past the table_display call, so the only ones around   */
;		/* must be unbootable  */
;
;		/* Display this fact then get out of here */
;		display(error_25);
;	       END
;	    else
;	       BEGIN
;		/* All is okay to go and set one, do display prompts */
;		number_in_msg((XFLOAT)total_mbytes[cur_disk],u(0));
;		display(menu_15);
;
;		/* print ESC prompt */
;		display(menu_11);
;
;		/* Put up input prompt */
;		display(menu_24);
;
;		/* Assume bad input until proven otherwise */
;		valid_input = FALSE;
;		valid_partitions = num_partitions;
;		input_default = c(NUL);
;
;		while (!valid_input)
;		   BEGIN
;		    /* Go get partition to make active */
;		    input = get_num_input(input_default,num_partitions,input_row,input_col);
;
;		    /* Save the input for next time in case CR pressed */
;		    input_default = input-'0';
;
;		    clear_screen(u(18),u(0),u(23),u(79));
;
;		    if (input != c(ESC))
;		       BEGIN
;			/* See if known unbootable partition */
;			/* Set the new one */
;			valid_partitions = c(0);
;
;			/* Make sure the partitions are in physical order */
;			sort_part_table(c(4));
;
;			/* Go find existing partitions */
;			for (i=u(0);i < u(4); i++)
;			   BEGIN
;			    /* First we have to find it */
;			    if (part_table[cur_disk][sort[i]].sys_id != uc(0))
;			       BEGIN
;				/* If this is the 'input'th one, then we got it */
;				if (valid_partitions == (input-'1'))
;				   BEGIN
;				    /* See if it is an unbootable partition */
;				    if ((part_table[cur_disk][sort[i]].sys_id != uc(BAD_BLOCK)) &&
;				     (part_table[cur_disk][sort[i]].sys_id !=  uc(EXTENDED)))
;
;				       BEGIN
;					/* Its bootable, so we have good input */
;					valid_input = c(TRUE);
;
;					/* Remove the active indicator from the old partition */
;					for (x=u(0); x < u(4); x++)
;					   BEGIN
;
;					    if (part_table[cur_disk][x].boot_ind == uc(0x80))
;					       BEGIN
;						part_table[cur_disk][x].changed = TRUE;
;						part_table[cur_disk][x].boot_ind = uc(0);
;					       END
;					   END
;
;					/* Put in new active indicator */
;					part_table[cur_disk][sort[i]].boot_ind = uc(0x80);
;
;					/* Indicate that it is changed */
;					part_table[cur_disk][sort[i]].changed = TRUE;
;
;					/* Set the reboot flag */
;					reboot_flag = (FLAG)TRUE;
;
;					/* Update the partition info display */
;					table_display();
;
;					/* Clear off the old prompts */
;					clear_screen(u(16),u(0),u(21),u(79));
;
;					/* Say you did it */
;					insert[0] = input;
;					display(status_4);
;					break;
;				       END
;				    else
;				       BEGIN
;					/* It is, so setup message and tell user */
;					insert[0] = input;
;					display(error_17);
;					break;
;				       END
;				   END
;				else
;				   BEGIN
;				    /* Indicate we found one but keep going */
;				    valid_partitions++;
;				   END
;			       END
;			   END
;		       END
;		    else
;		       BEGIN
;			/* Mark ESC as ok input so we can get out of here */
;			valid_input = c(TRUE);
;		       END
;		   END /* While loop */
;	       END
;	   END /* table display test endif */
;	else
;	   BEGIN
;	    /* No partitions to make active */
;	    display(error_16);
;	   END
;       END
;    else
;       BEGIN
;	display(error_26);
;       END
;    /* clear the screen before going back to main menu */
;    if (input != c(ESC))
;       BEGIN
;	wait_for_ESC();
;       END
;    clear_screen(u(0),u(0),u(24),u(79));
;    return;
;END

change_active_partition:
		; 19/12/2018

	%define cap_valid_input		bp-16
	%define cap_num_partitions	bp-14
	%define cap_valid_partitions	bp-12
	%define cap_i			bp-10
	%define cap_x			bp-8
	%define cap_num_boot_partitions bp-6
	%define cap_input_default	bp-4
	%define cap_input		bp-2

		push	bp
		mov	bp,sp
		sub	sp,16
		
		mov	byte [cap_input],0
		
		;/* Clear screen */

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;/* Display header */

		;push	word [menu_23_segment]
		push	ds
		push	word [menu_23_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup and print current disk */	
		
		;mov	al,[cur_disk]
		;add	al,'1'
		;mov	[insert],al
		;
		;;push	word [menu_5_segment]
		;push	ds
		;push	word [menu_5_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_5 ; 31/12/2018

	;/* Only allow active partitions on the first (and bootable) disk */
cap_if1:
		cmp	byte [cur_disk],0
		je	short cap_01_if2
		jmp	cap_29

	;/* Display partition info and see if any partitions exist*/
cap_01_if2:
		call	table_display
		;or	al,al
		;jnz	short cap_02_for1
		jnc	short cap_02_for1
		jmp	cap_28

		;/* See if active partition is bootable */	
cap_02_for1:
		mov	word [cap_i],0
cap_03_for1_next2:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,[cap_i]
		shl	al,1
		shl	al,1
		add	al,[cap_i]
		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
cap_if3:
		cmp	byte [part_table_sys_id+bx],0
		je	short cap_05_for1_next1
		cmp	byte [part_table_boot_ind+bx],80h ; Active  partition indicator
		jne	short cap_05_for1_next1
cap_if4:
		cmp	byte [part_table_sys_id+bx],0FFh ; (xenix) Bad Block TABLE
		je	short cap_04
		cmp	byte [part_table_sys_id+bx],5 ; EXTENDED DOS partition
		jne	short cap_05_for1_next1

	;/* The active partition is not bootable, so warn user */	
cap_04:
		;push	word [error_24_seg]
		push	ds
		push	word [error_24_off]
		call	display
		;pop	bx
		;pop	bx
cap_05_for1_next1:
		inc	byte [cap_i]
		cmp	byte [cap_i],4
		jb	short cap_03_for1_next2

		;/* Check to see if only one partition */
		sub	al,al ; 0
		mov	[cap_num_partitions],al	; reset
		mov	[cap_num_boot_partitions],al ; reset
cap_for2:
		mov	byte [cap_i],0
cap_06_for2_next2:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,[cap_i]
		;mov	cx,46
		;mul	cx
		shl	al,1
		shl	al,1
		add	al,[cap_i]
		mov	cl,46
		mul	cl
		mov	bx,ax
cap_if5:
		cmp	byte [part_table_sys_id+bx],0 ; Partition ID (0 = Empty)	
		je	short cap_07_for2_next1

		;/* Get a count of partitions */
		inc	byte [cap_num_partitions]  ; number of partitions (in PT)
cap_if6:
	;/* Get a count of the number of defined partitions but don't*/
	;/* count those we know aren't bootable */
		cmp	byte [part_table_sys_id+bx],0FFh ; (xenix) Bad Block TABLE
		je	short cap_07_for2_next1
		cmp	byte [part_table_sys_id+bx],5  ; EXTENDED DOS partition
		je	short cap_07_for2_next1
		inc	byte [cap_num_boot_partitions] ; num of bootable partitions
cap_07_for2_next1:
		inc	byte [cap_i]
		cmp	byte [cap_i],4
		jb	short cap_06_for2_next2

	;/* If only one partition found, see if it is active already *
cap_if7:
		cmp	byte [cap_num_boot_partitions],1
		jne	short cap_12_if10

	;/* Find the partition and see if it is already active */
cap_for3:
		mov	byte [cap_i],0
		jmp	short cap_09_for3_next1
cap_08_for3_next2:
		inc	byte [cap_i]
;cap_09_for3_next1:
		cmp	byte [cap_i],4
		jnb	short cap_12_if10
cap_09_for3_next1:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,[cap_i]
		;mul	cx
		shl	al,1
		shl	al,1
		add	al,[cap_i]
		mul	cl	
		mov	bx,ax
cap_if8:
		cmp	byte [part_table_sys_id+bx],0 ; empty pt entry
		je	short cap_08_for3_next2
		cmp	byte [part_table_boot_ind+bx],80h ; Active partition
		jne	short cap_08_for3_next2

	;/* Make sure it is not unbootable partition again*/
cap_if9:
		cmp	byte [part_table_sys_id+bx],0FFh ; (xenix) Bad Block TABLE
		je	short cap_08_for3_next2
		cmp	byte [part_table_sys_id+bx],5  ; EXTENDED DOS partition	
		je	short cap_08_for3_next2

		;/* Once it is found, put out the message */	

		;push	word [error_15_seg]
		push	ds
		push	word [error_15_off]
		call	display
		;pop	bx
		;pop	bx

		jmp	short cap_10 ; 19/12/2018

		;/* No partitions to make active */
cap_28:
		;push	word [error_16_seg]
		push	ds
		push	word [error_16_off]
		jmp	short cap_30
cap_29:
		;push	word [error_26_seg]
		push	ds
		push	word [error_26_off]
cap_30:
		call	display
		;pop	bx
		;pop	bx

		;jmp	cap_31 ; 19/12/2018

		;/* clear the screen before going back to main menu */
cap_31:
		cmp	byte [cap_input],1Bh  ; ESC key
		;jne	short cap_32
		;jmp	cap_11
		je	short cap_11
;cap_32:
		;jmp	cap_10

		;/* Wait for ESC, then get out */
cap_10:
		call	wait_for_ESC

	 ;/* clear the screen before going back to main menu*/
cap_11:
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;jmp	cap_33
cap_33:
		mov	sp,bp
		pop	bp
		retn

	;/* See if any bootable partitions exist */
cap_12_if10:
		cmp	byte [cap_num_boot_partitions],0
		jne	short cap_13_if10_else

	;/* At this point, we know at least one partition does exist due to*/
	;/* getting past the table_display call, so the only ones around   */
	;/* must be unbootable  */
cap_12:
		;/* Display this fact then get out of here */

		;push	word [error_25_seg]
		push	ds
		push	word [error_25_off]
		jmp	cap_30

	;/* All is okay to go and set one, do display prompts */	
cap_13_if10_else:
		sub	ax,ax
		push	ax
		mov	al,[cur_disk]
		;cbw
		mov	bx,ax
		;shl	bx,1
		shl	bl,1
		push	word [total_mbytes+bx]
		call	number_in_msg
		;pop	bx
		;pop	bx

		;push	word [menu_15_segment]
		push	ds
		push	word [menu_15_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* print ESC prompt */

		;;push	word [menu_11_segment]
		;push	ds
		;push	word [menu_11_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_11 ; 31/12/2018

		;/* Put up input prompt */

		;push	word [menu_24_segment]
		push	ds
		push	word [menu_24_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Assume bad input until proven otherwise */

		mov	al,[cap_num_partitions]
		mov	[cap_valid_partitions],al
		sub	al,al ; 0
		mov	[cap_valid_input],al
		mov	[cap_input_default],al
		;jmp	cap_26_while

cap_26_while:
		cmp	byte [cap_valid_input],0 ; FALSE ?
		;;jne	short cap_27
		;jne	short cap_31
		;jmp	cap_14
		jne	short cap_31

		;/* Go get partition to make active */
cap_14:
		push	word [input_col]
		push	word [input_row]
		mov	al,[cap_num_partitions]
		push	ax
		mov	al,[cap_input_default]
		push	ax
		call	get_num_input
		;add	sp,8
		mov	[cap_input],al

	;/* Save the input for next time in case CR pressed */

		sub	al,'0'
		mov	[cap_input_default],al

		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	cx,18
		push	cx
		call	clear_screen
		;add	sp,8
cap_if11:
		cmp	byte [cap_input],1Bh ; ESC key
		jne	short cap_15
		jmp	cap_25_if11_else

		;/* See if known unbootable partition */
		;/* Set the new one */
cap_15:
		mov	byte [cap_valid_partitions],0

		;/* Make sure the partitions are in physical order */

		;mov	al,4
		;push	ax
		mov	cl,4
		call	sort_part_table
		;pop	bx

		;/* Go find existing partitions */
cap_15_for4:
		mov	byte [cap_i],0
		;jmp	short cap_20_for4_next1
		jmp	short cap_21_for4_next2

		;/* It is, so setup message and tell user */
cap_16_if14_else:
		mov	al,[cap_input]
		mov	[insert],al
		;push	word [error_17_seg]
		push	ds
		push	word [error_17_off]
cap_17:
		call	display
		;pop	bx
		;pop	bx
		jmp	short cap_26_while  ; /* While loop */

		;/* Indicate we found one but keep going */
cap_18:
		inc	byte [cap_valid_partitions]
cap_19:
		inc	byte [cap_i]
cap_20_for4_next1:
		cmp	byte [cap_i],4
		jb	short cap_21_for4_next2
		jmp	short cap_26_while  ; /* While loop */
cap_21_for4_next2:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		mov	bx,[cap_i]
		;mov	cx,ax
		;mov	al,[sort+bx]
		;cbw
		;add	ax,cx
		mov	cl,[sort+bx]
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax

		;/* First we have to find it */	
cap_if12:
		cmp	byte [part_table_sys_id+bx],0  ; Partition ID (0 = empty)
		je	short cap_19

		;/* If this is the 'input'th one, then we got it */
cap_if13:
		;mov	al,[cap_valid_partitions]
		;cbw
		;mov	cx,ax
		mov	cl,[cap_valid_partitions]
		mov	al,[cap_input]
		;cbw
		;sub	ax,cx
		sub	al,cl
		;cmp	ax,'1'
		cmp	al,'1'
		jne	short cap_18

		;/* See if it is an unbootable partition */
cap_if14:
		cmp	byte [part_table_sys_id+bx],0FFh ; (xenix) Bad Block TABLE
		je	short cap_16_if14_else
		cmp	byte [part_table_sys_id+bx],5  ; EXTENDED DOS partition	
		je	short cap_16_if14_else

		;/* Its bootable, so we have good input */
		
		mov	byte [cap_valid_input],1 ; TRUE

	;/* Remove the active indicator from the old partition */
cap_for5:
		mov	byte [cap_x],0
cap_22_for5_next2:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;add	ax,[cap_x]
		add	al,[cap_x]
		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
cap_if15:
		cmp	byte [part_table_boot_ind+bx],80h ; Active partition indicator
		jne	short cap_24_for5_next1
		mov	byte [part_table_changed+bx],1  ; Partion table changed flag
		mov	byte [part_table_boot_ind+bx],0 ; non-active partition
cap_24_for5_next1:
		inc	byte [cap_x]
		cmp	byte [cap_x],4
		jb	short cap_22_for5_next2
		
		;/* Put in new active indicator */

		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		mov	bx,[cap_i]
		;mov	cx,ax
		;mov	al,[sort+bx]
		;cbw
		;add	ax,cx
		mov	cl,[sort+bx]
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		mov	byte [part_table_boot_ind+bx],80h  ; Set as Active partition
		
		;/* Indicate that it is changed */

		mov	al,1
		mov	[part_table_changed+bx],al ;  TRUE

		;/* Set the reboot flag */

		mov	[reboot_flag],al ; TRUE

		;/* Update the partition info display */

		call	table_display

		;/* Clear off the old prompts */

		mov	ax,79
		push	ax
		mov	ax,21
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,16
		push	ax
		call	clear_screen
		;add	sp,8

		;/* Say you did it */

		mov	al,[cap_input]
		mov	[insert],al
		;push	word [status_4_seg]
		push	ds
		push	word [status_4_off]

		jmp	cap_17

	;/* Mark ESC as ok input so we can get out of here */
cap_25_if11_else:
		mov	byte [cap_valid_input],1 ; TRUE
		jmp	cap_11 ; 19/12/2018

;cap_26_while:
;		cmp	byte [cap_valid_input],0 ; FALSE ?
;		;jne	short cap_27
;		jne	short cap_31
;		jmp	cap_14
;cap_27:
		;jmp	short cap_31

;		;/* No partitions to make active */
;cap_28:
;		;push	word [error_16_seg]
;		push	ds
;		push	word [error_16_off]
;		jmp	short cap_30
;cap_29:
;		;push	word [error_26_seg]
;		push	ds
;		push	word [error_26_off]
;cap_30:
;		call	display
;		;pop	bx
;		;pop	bx
;
;		jmp	cap_31 ; 19/12/2018

;		;/* clear the screen before going back to main menu */
;cap_31:
;		cmp	byte [cap_input],1Bh  ; ESC key
;		;jne	short cap_32
;		;jmp	cap_11
;		je	cap_11
;cap_32:
;		jmp	cap_10
;cap_33:
;		mov	sp,bp
;		pop	bp
;		retn

; ----------------------------------------------------------------------------
; fdisk.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 19/12/2018)

;/*  */
;void reboot_system()
;BEGIN
;
;    char far *boot_drive;
;    char     boot_letter;
;    char     i,j;
;    FLAG     boot_changed;
;
;    clear_screen(u(0),u(0),u(24),u(79));
;    if (quiet_flag == FALSE)
;	BEGIN
;	regs.h.ah = 0x52;
;	intdosx(&regs,&regs,&segregs);
;	FP_SEG(boot_drive) = segregs.es;
;	FP_OFF(boot_drive) = regs.x.bx + u(0x43);
;	boot_letter = *boot_drive + c(0x40);
;	if (boot_letter != 'A')
;	    {
;	    boot_changed = TRUE;
;	    for (i=0; i<number_of_drives; i++)
;		for (j=0; j<4; j++)
;		    if (part_table[i][j].drive_letter == boot_letter)
;			boot_changed = part_table[i][j].changed;
;	    if (boot_changed == FALSE)
;		display(menu_60);
;	    else
;		display(menu_38);
;	    } 
;	else/
;	    display(menu_38);
;	getch();
;	reboot();
;	END
;   else
;	BEGIN
;	cur_disk = c(0);
;	reset_video_information();
;	if ( (find_partition_type(uc(DOS12))) ||
;	     (find_partition_type(uc(DOS16))) ||
;	     (find_partition_type(uc(DOSNEW))) )
;	    exit(ERR_LEVEL_0);
;	else
;	    exit(ERR_LEVEL_1);
;	END
;END

reboot_system:
		; 19/12/2018

	%define r_boot_drive	bp-12 ; far ptr, dword
	%define r_boot_changed	bp-8  ; flag, byte
	%define r_i		bp-6  ; char, byte	
	%define r_j		bp-4  ; char, byte
	%define r_boot_letter	bp-2  ; char, byte 

		;push	bp
		mov	bp,sp
		sub	sp,12

		mov	ax,79
		push	ax
		mov	ax,24
		push	ax
		sub	ax,ax
		push	ax
		push	ax
		call	clear_screen
		add	sp,8
		cmp	byte [quiet_flag],0
		je	short rebootsys_0
		jmp	rebootsys_8
rebootsys_0:
		;Get Pointer to DOS SYSVARS
		push	es
		mov	ah,52h
		int	21h
			; ES:BX = pointer to DOS "sysvars", 
			;	  a table of pointers used by DOS
		mov	al,[es:bx]
		pop	es
		add	al,40h
		mov	[r_boot_letter],al
		cmp	al,'A'
		je	short rebootsys_6
		mov	byte [r_boot_changed],1
		mov	byte [r_j],0
		jmp	short rebootsys_4
rebootsys_1:
		inc	byte [r_i]
rebootsys_2:
		cmp	byte [r_i],4
		jge	short rebootsys_3
		mov	al,[r_j]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;mov	cx,ax
		;mov	al,[r_i]
		;cbw
		;add	ax,cx
		add	al,[r_i]
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		mov	al,[r_boot_letter]
		cmp	byte [part_table_drive_letter+bx],al
		jne	short rebootsys_1
		mov	al,[part_table_changed+bx]
		mov	[r_boot_changed],al
		jmp	short rebootsys_1
rebootsys_3:
		inc	byte [r_j]
rebootsys_4:
		mov	al,[r_j]
		;cbw
		mov	cl,[number_of_drives]
		;sub	ch,ch
		;cmp	ax,cx
		cmp	al,cl
		jge	short rebootsys_5
		;mov	[r_i],ch
		mov	byte [r_i],0
		jmp	short rebootsys_2
rebootsys_5:
		cmp	byte [r_boot_changed],0
		jne	short rebootsys_6
		;push	word [menu_60_segment]
		push	ds
		push	word [menu_60_offset]
		jmp	short rebootsys_7
rebootsys_6:
		;push	word [menu_38_segment]
		push	ds
		push	word [menu_38_offset]
rebootsys_7:
		call	display
		;pop	bx
		;pop	bx
		call	getch
		;call	reboot
		;jmp	short rebootsys_12
		; 19/12/2018
		;mov	sp,bp
		;pop	bp
		jmp	short reboot
rebootsys_8:
		mov	byte [cur_disk],0
		call	reset_video_information
		mov	al,1
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short rebootsys_9
		jnc	short rebootsys_9
		mov	al,4
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short rebootsys_9
		jnc	short rebootsys_9
		mov	al,6
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short rebootsys_10
		jc	short rebootsys_10
rebootsys_9:
		sub	ax,ax
		jmp	short rebootsys_11
rebootsys_10:
		mov	ax,1
rebootsys_11:
		;push	ax
		;call	_exit
		;pop	bx
		jmp	_exit
;rebootsys_12:
;		mov	sp,bp
;		pop	bp
;		retn

; getch
; ----------------------------------------------------------------------------
; 19/12/2018

getch:
		xor	ah,ah
		int	16h
		retn

; reboot (MSDOS 6.0, reboot.asm)
; ----------------------------------------------------------------------------
; IBM PC-DOS FDISK.COM (unpacked) /// Segment 0, Offset 2E0Ah [ 19/12/2018 ]

reboot:
		mov	ax,40h ; BIOS DATA segment
		mov	ds,ax
		mov	word [72h],1234h ; mov word [WarmBootFlag],WARM_BOOT_CODE
		mov	ax,3515h
		int	21h	; DOS -	2+ - GET INTERRUPT VECTOR
				; AL = interrupt number
				; Return: ES:BX	= value	of interrupt vector
		mov	ax,es
		or	ax,bx
		jz	short reboot_0

		;mov	ax,40h
		;mov	ds,ax

		mov	byte [17h],0Ch ; mov byte [KB_FLAG],ALT_SHIFT|SHIFT
		mov	ax,4F53h ; (KB_INTERCEPT SHL 8) OR DEL_KEY
		int	15h	; OS HOOK - KEYBOARD INTERCEPT
				;	 (AT model 3x9,XT2,XT286,CONV,PS)
				; AL = scan code, CF set
				; Return: CF set - AL =	scan code
				; CF clear - scan code should be ignored

reboot_0:	; Jump to the processor power-on address FFFF:0000h
		jmp	0FFFFh:0

; ----------------------------------------------------------------------------
; diskout.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 20/12/2018)

;/*  */
;void write_info_to_disk()
;
;BEGIN
;
;    char     i;
;    unsigned char j;
;    unsigned extended_location;
;    char     extended_index;
;    char     temp;
;    char     changed_flag;
;    char     temp_disk;
;
;    /* Change invalid value for temp to 0xff. NUL is a valid value for
;       the index and cannot be used */
;
;    temp = 0xff;
;    temp_disk = cur_disk;
;    /* See if need to update the master boot record */
;    for (j = uc(0); j < number_of_drives; j++)
;       BEGIN
;
;        /* Save disk number */
;        cur_disk = ((char)(j));
;
;        /* See if there were any errors on that drive */
;        if (good_disk[j])
;           BEGIN
;            for (i=c(0); i < c(4); i++)
;               BEGIN
;                if (part_table[j][i].changed)
;                   BEGIN
;                    write_master_boot_to_disk(j);
;                    break;
;                   END
;               END
;            /* See if the extended partition exists - if not, don't fool with the logical */
;            /* drives - there is nothing to point to their structures. Otherwise you get into */
;            /* a chicken and the egg situation, where you are trying to write out 'deletes' of */
;            /* the logical drive based on the start of the extended partition, but there isn't one */
;            /* because it has already been deleted already. Bad things happen - PTM P941 */
;
;            /* SR; 9/26/89; Removed semi-colon at the end of the if
;               statement that caused the block of code to always execute */
;
;            if (find_partition_type(uc(EXTENDED)))
;               BEGIN
;                /* See if any extended partitions need to be updated */
;                changed_flag = FALSE;
;
;                for (i=c(0);i < c(23); i++)
;                   BEGIN
;                    if (ext_table[j][i].changed)
;                       BEGIN
;                        changed_flag = TRUE;
;                        break;
;                       END
;                   END
;                if (changed_flag)
;                   BEGIN
;                    /* First,get them in order - drive letters are assigned in the order */
;                    /* that they exist on the disk */
;                    sort_ext_table(c(23));
;
;                    for (i=c(0);i < c(23); i++)
;
;                       BEGIN
;                        /* If there is a valid drive existing, write it out */
;                        if (ext_table[j][sort[i]].sys_id != uc(0))
;                           BEGIN
;                            write_ext_boot_to_disk(i,j);
;                           END
;                       END
;
;                    /* Find start of extended partition */
;                    extended_index = find_partition_location(uc(EXTENDED));
;                    extended_location = part_table[j][extended_index].start_cyl;
;
;                    /* See if the first entry in EXTENDED DOS partition will be written out */
;                    /* Need to find the first drive in the sorted list */
;                    for (i=c(0);i < c(23); i++)
;                       BEGIN
;                        if (ext_table[j][sort[i]].sys_id != uc(0))
;                           BEGIN
;                            temp = sort[i];
;                            break;
;                           END
;                       END
;                    /* See if drive written out */
;                    /* SR; 9/28/89; Check for the special case when the
;                       volume is deleted and write out only a pointer
;                       for it */
;
;                    if ((temp == c(0xff)) ||
;                        (extended_location != ext_table[j][temp].start_cyl))
;                       BEGIN
;                        /* If not, make a special case and go do it */
;                        /* Use the 24 entry in the array to set up a dummy entry */
;                        /* This one isn't used for anything else */
;                        /* Indicate this is special by passing along a deleted entry - the subroutine will catch it and handle correctly */
;                        ext_table[j][23].sys_id = uc(0);
;                        ext_table[j][23].start_cyl = part_table[j][extended_index].start_cyl;
;                        ext_table[j][23].start_head = uc(0);
;                        ext_table[j][23].start_sector = uc(1);
;
;                        /* Write out our modified first location - only pointer info will be sent to the disk */
;                        write_ext_boot_to_disk(c(23),j);
;                       END
;                   END
;               END
;           END
;       END
;    cur_disk = temp_disk;
;    return;
;END

write_info_to_disk:
		; 04/01/2019
		; 20/12/2018
	
	%define witd_j		   bp-10 ; bp-14
	%define witd_i		   bp-8  ; bp-12
	%define witd_extd_location bp-6	 ; bp-10
	%define witd_extd_index    bp-4	 ; bp-8
	%define witd_temp	   bp-12 ; bp-6
	;%define witd_changed_flag       ; bp-4
	%define witd_temp_disk	   bp-2  ; bp-2

		;push	bp
		mov	bp,sp
		;;sub	sp,14
		;sub	sp,10
		sub	sp,12 ; 04/01/2019

		;push	si

		mov	byte [witd_temp],0FFh ; 04/01/2019

		mov	al,[cur_disk]
		mov	[witd_temp_disk],al
		mov	word [witd_j],0
		jmp	witd_16
witd_1:
		inc	byte [witd_i]
;witd_2:
		cmp	byte [witd_i],4
		jge	short witd_3
witd_2:
		mov	al,[witd_i] ; Partition number
		;cbw
		mov	cl,[witd_j] ; Disk number
		;sub	ch,ch
		;shl	cx,1
		;shl	cx,1
		shl	cl,1
		shl	cl,1
		;add	ax,cx
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		cmp	byte [part_table_changed+bx],0
		je	short witd_1
		mov	al,[witd_j]
		push	ax
		call	write_master_boot_to_disk
		;pop	bx

		;/* See if the extended partition exists - if not, 
		;   don't fool with the logical drives */
witd_3:
		mov	al,5 ; EXTENDED
		;push	ax
		call	find_partition_type
			 ; CL = Partition number if CF = 0
		;pop	bx
		;or	al, al
		;jnz	short witd_4
		jnc	short witd_4
		jmp	witd_15
witd_4:
		mov	[witd_extd_index],cl ; *==

 		;/* See if any extended partitions need to be updated */

		;sub	al,al
		;sub	ax,ax
		;mov	[witd_changed_flag],al ; 0  ; FALSE
		;;mov	[witd_i],al ; reset
		;mov	[witd_i],ax ; 0
		mov	word [witd_i],0
		jmp	short witd_6
witd_5:
		inc	byte [witd_i]
;witd_6:
		cmp	byte [witd_i],23
		;jge	short witd_7
		jge	witd_15
witd_6:
		;mov	al,[witd_i]
		;cbw
		;mov	cx,ax
		mov	cl,[witd_i]
		mov	al,24
		mul	byte [witd_j]
		;add	ax,cx
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		cmp	byte [ext_table_changed+bx],0
		je	short witd_5

		;mov	byte [witd_changed_flag],1 ; TRUE
;witd_7:
;		cmp	byte [witd_changed_flag],0
;		jne	short witd_8
;		jmp	witd_15

 	;/* First,get them in order - drive letters are assigned in the order */
	;/* that they exist on the disk */
witd_8:
		;mov	al,23
		;push	ax
		mov	cl,23
		call	sort_ext_table
		;pop	bx
		
		mov	byte [witd_i],0
witd_9:
		mov	al,24
		mul	byte [witd_j] ; Disk (0 to 7)
		;mov	cx,ax
		;mov	al,[witd_i]
		;cbw
		;mov	bx,ax
		mov	bx,[witd_i] ; Logical drive (0 to 22)	
		;mov	al,[sort+bx]
		;cbw
		;add	ax,cx
		add	al,[sort+bx]	
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax

		cmp	byte [ext_table_sys_id+bx],0
		je	short witd_10 ; Empty partition

		mov	al,[witd_j]
		push	ax
		mov	al,[witd_i]
		push	ax
		call	write_ext_boot_to_disk
		;pop	bx
		;pop	bx
witd_10:
		inc	byte [witd_i]
		cmp	byte [witd_i],23
		jb	short witd_9 ; 04/01/2019

		;/* Find start of extended partition */

		;mov	al,5
		;push	ax
		;call	find_partition_location
		;pop	bx
		;mov	[witd_extd_index],al ; *==
		
		;cbw
		;mov	cl,[witd_j]
		;sub	ch,ch
		;shl	cx,1
		;shl	cx,1
		;add	ax,cx

		mov	al,[witd_j]
		shl	al,1
		shl	al,1
		add	al,[witd_extd_index] ; *==		

		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl		
		mov	bx,ax

		mov	ax,[part_table_start_cyl+bx]
		mov	[witd_extd_location],ax

	;/* See if the first entry in EXTENDED DOS partition will be written out */
	;/* Need to find the first drive in the sorted list */

		mov	byte [witd_i],0
		jmp	short witd_12
witd_11:
		inc	byte [witd_i]
;witd_12:
		cmp	byte [witd_i],23
		jge	short witd_13 ; 04/01/2019
witd_12:
		mov	al,24
		mul	byte [witd_j]
		;mov	cx,ax
		;mov	al,[witd_i]
		;cbw
		mov	bx,[witd_i]
		;mov	al,[sort+bx]
		mov	dl,[sort+bx] ; 04/01/2019
		;mov	dx,ax
		;cbw
		;add	ax,cx
		add	al,dl ; 04/01/2019	

		;mov	cx,46
		;mov	bx,dx
		;imul	cx
		;mov	cl,46
		mul	cl
		;mov	si,ax
		mov	bx,ax
		;cmp	byte [ext_table_sys_id+si],0
		cmp	byte [ext_table_sys_id+bx],0
		je	short witd_11

		; 04/01/2019	
		;mov	[witd_temp],bl
		mov	[witd_temp],dl

		jmp	short witd_18 ; 20/12/2018

		;/* See if drive written out */

		;/* Check for the special case when the
                ;   volume is deleted and write out only a pointer for it */

		; 21/12/2018
witd_13:	; 04/01/2019	
		cmp	byte [witd_temp],0FFh ; 255
		je	short witd_14

		;;mov	al,[witd_temp]
		;;cbw
		;;mov	cx,ax
		;mov	dl,[witd_temp]	
;witd_18:	
		; 04/01/2019	
		mov	al,24
		mul	byte [witd_j]
		;;add	ax,cx
		;add	al,dl
		add	al,[witd_temp]
		;;mov	cx,46
		;;imul	cx
		;mov	cl,46
		mul	cl
		mov	bx,ax

witd_18:	; 04/01/2019
		mov	ax,[witd_extd_location]
		cmp	[ext_table_start_cyl+bx],ax
		je	short witd_15
witd_14:
		mov	al,[witd_j]
		sub	ah,ah ; 04/01/2019
		mov	cx,1104 ; 46*24
		;mov	bx,ax
		mov	bl,al
		;imul	cx
		mul	cx
		mov	si,ax
		mov	byte [ep0_lp23_sys_id+si],0
		mov	al,[witd_extd_index]
		;cbw
		;shl	bx,1
		;shl	bx,1
		shl	bl,1
		shl	bl,1
		;add	ax,bx
		add	al,bl
		mov	cx,46
		;imul	cx
		mul	cl
		mov	bx,ax

		;/* If not, make a special case and go do it */
		;/* Use the 24 entry in the array to set up a dummy entry */
		;/* This one isn't used for anything else */

		mov	ax,[part_table_start_cyl+bx]
		mov	[ep0_lp23_start_cyl+si],ax
		mov	byte [ep0_lp23_start_head+si],0
		mov	byte [ep0_lp23_start_sector+si],1
		
 		;/* Write out our modified first location -
		;   only pointer info will be sent to the disk */

		mov	al,[witd_j] ; 04/01/2019
		push	ax
		mov	al,23	; Logical drive	(23)
		push	ax
		call	write_ext_boot_to_disk
		;pop	bx
		;pop	bx
witd_15:
		inc	byte [witd_j]  ; next disk
;witd_16:
		;/* See if need to update the master boot record */

		mov	al,[number_of_drives]
		cmp	byte [witd_j],al
		jnb	short witd_17
witd_16:
		;mov	al,[witd_j]
		;mov	[cur_disk],al
		;mov	bl,al
		;sub	bh,bh
		mov	bx,[witd_j]
		mov	[cur_disk],bl		

		;/* See if there were any errors on that drive */

		cmp	byte [good_disk+bx],bh ; 0
		je	short witd_15
		mov	[witd_i],bh ; 0
		jmp	witd_2
witd_17:
		mov	al,[witd_temp_disk]
		mov	[cur_disk],al

		;pop	si
		
		mov	sp,bp
		;pop	bp
		retn

; ----------------------------------------------------------------------------

;/*  */
;char write_master_boot_to_disk(disk)
;
;unsigned char   disk;
;
;BEGIN
;
;    unsigned char i;
;    unsigned j;
;    unsigned long long_temp;
;    unsigned index;
;
;    /* Clean out the boot_record */
;    for (j=u(0);j < u(BYTES_PER_SECTOR); j++)
;       BEGIN
;        boot_record[j] = uc(0);
;       END
;
;    /* Copy the master boot record to boot_record */
;    for (j=u(0); j < u(BYTES_PER_SECTOR); j++)
;       BEGIN
;        boot_record[j] = master_boot_record[disk][j];
;       END
;
;    /* Copy the partition tables over - only bother with the changed ones */
;    for (i=uc(0); i < uc(4); i++)
;       BEGIN
;        index = ((unsigned)i)*16;
;        if (part_table[disk][i].changed)
;           BEGIN
;            /* Get boot ind */
;            boot_record[0x1BE+(index)] = part_table[disk][i].boot_ind;
;
;            /* Start head */
;            boot_record[0x1BF+(index)] = part_table[disk][i].start_head;
;
;            /* Start sector - scramble it to INT 13 format*/
;            boot_record[0x1C0+(index)] = (part_table[disk][i].start_sector & 0x3F)  |
;                                           ((unsigned char)((part_table[disk][i].start_cyl/256) << 6));
;
;            /* Start cyl - scramble it to INT 13 format */
;            boot_record[0x1C1+(index)] = ((unsigned char)(part_table[disk][i].start_cyl%256));
;
;            /* System id */
;            boot_record[0x1C2+(index)] = part_table[disk][i].sys_id;
;
;            /* End head */
;            boot_record[0x1C3+(index)] = part_table[disk][i].end_head;
;
;            /* End sector - scramble it to INT 13 format*/
;            boot_record[0x1C4+(index)] = (part_table[disk][i].end_sector & 0x3F)  |
;                                            ((unsigned char)((part_table[disk][i].end_cyl/256) << 6));
;
;            /* End cyl - scramble it to INT 13 format*/
;            boot_record[0x1C5+(index)] = ((unsigned char)(part_table[disk][i].end_cyl%256));
;
;            /* Relative sectors */
;            long_temp = part_table[disk][i].rel_sec;
;            boot_record[0x1C9+(index)] = uc((long_temp >> 24));
;            boot_record[0x1C8+(index)] = uc(((long_temp & 0x00FF0000l) >> 16));
;            boot_record[0x1C7+(index)] = uc(((long_temp & 0x0000FF00l) >> 8));
;            boot_record[0x1C6+(index)] = uc((long_temp & 0x000000FFl));
;
;
;            /* Number of sectors */
;            long_temp = part_table[disk][i].num_sec;
;            boot_record[0x1CD+(index)] = uc(long_temp >> 24);
;            boot_record[0x1CC+(index)] = uc((long_temp & 0x00FF0000l) >> 16);
;            boot_record[0x1CB+(index)] = uc((long_temp & 0x0000FF00l) >> 8);
;            boot_record[0x1CA+(index)] = uc(long_temp & 0x000000FFl);
;          END
;       END
;    boot_record[510] = uc(0x55);
;    boot_record[511] = uc(0xAA);
;
;    return(write_boot_record(u(0),disk));
;END

write_master_boot_to_disk:
		; 21/12/2018

	;%define wmbr_long_temp	bp-12 ; bp-14
	%define wmbr_j		bp-8  ; bp-10	
	%define wmbr_i		bp-6  ; bp-8
	%define wmbr_index	bp-4  ; bp-6
	
	%define wmbr_disk	bp+4

		push	bp
		mov	bp,sp
		;;sub	sp,14
		;sub	sp,12
		sub	sp,8

		;push	di
		;push	si

		mov	word [wmbr_j],0

		;/* Clean out the boot_record */
;wmbr_0:
		;;mov	bx,[wmbr_j]
		;;mov	byte [boot_record+bx],0
		;;inc	word [wmbr_j]
		;;cmp	word [wmbr_j],512
		;;jb	short wmbr_0
		;;mov	word [wmbr_j],0
		
		;xor	ax,ax
		;mov	di,boot_record
		;mov	cx,256
		;;push	ds
		;;pop	es
		;rep	stosw

		;/* Copy the master boot record to boot_record */
wmbr_1:
		;mov	cl,9
		;mov	al,[wmbr_disk]
		;sub	ah,ah
		;mov	si,ax
		;shl	si,cl
		;mov	bx,[wmbr_j]
		;mov	al,[master_boot_record+bx+si]
		;mov	[boot_record+bx],al
		;inc	word [wmbr_j]
		;cmp	word [wmbr_j],512
		;jb	short wmbr_1

		mov	al,[wmbr_disk]
		xor	ah,ah
		mov	si,ax
		mov	cl,9
		shl	si,cl ; * 512
		add	si,master_boot_record
		mov	di,boot_record		
		mov	cx,256
		rep	movsw

	;/* Copy the partition tables over - only bother with the changed ones */

		;mov	byte [wmbr_i],ah ; 0
		mov	word [wmbr_i],cx ; 0
wmbr_2:
		mov	cl,4
		;mov	al,[wmbr_i]
		;sub	ah,ah
		;mov	dx,ax
		;shl	ax,cl
		
		;mov	ax,[wmbr_i]
		;mov	bx,ax
		mov	bx,[wmbr_i]
		mov	al,bl
		;shl	bx,cl ; * 16
		shl	bl,cl
		;mov	[wmbr_index],ax
		mov	[wmbr_index],bx ; Partition table entry offset
		;mov	al,[wmbr_disk]
		;sub	ah,ah
		;shl	ax,1
		;shl	ax,1
		;add	ax,dx
		mov	cl,[wmbr_disk]
		shl	cl,1
		shl	cl,1
		add	al,cl	; FDISK Partititon data index	
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax	; FDISK Partition data offset
		cmp	byte [part_table_changed+bx],0
		;jne	short wmbr_3
		;jmp	wmbr_4
		je	short wmbr_4
wmbr_3:
		;mov	al,[part_table_boot_ind+bx]
		;mov	si,[wmbr_index]
		;mov	[boot_record+1BEh+si],al
		;mov	al,[part_table_start_head+bx]
		;mov	[boot_record+1BFh+si],al
		;mov	ax,[part_table_start_cyl+bx]
		;;mov	cx,ax
		;mov	ch,al
		;shr	ax,1
		;shr	ax,1
		;;mov	dx,ax
		;and	al,0C0h
		;;xor	al,[part_table_start_sector+bx]
		;;and	al,3Fh
		;;xor	dl,al
		;;mov	[boot_record+1C0h+si],dl
		;;mov	[boot_record+1C1h+si],cl  ; Start cylinder
		;mov	cl,[part_table_start_sector+bx]
		;;and	cl,3Fh
		;or	cl,al
		;mov	[boot_record+1C0h+si],cl  ; Start sector
		;mov	[boot_record+1C1h+si],ch  ; Start cylinder		
		;
		;mov	al,[part_table_sys_id+bx]
		;mov	[boot_record+1C2h+si],al
		;mov	al,[part_table_end_head+bx]
		;mov	[boot_record+1C3h+si],al
		;mov	ax,[part_table_end_cyl+bx]
		;;mov	cx,ax
		;shr	ax,1
		;shr	ax,1
		;;mov	dx,ax
		;and	al,0C0h
		;;xor	al,[part_table_end_sector+bx]
		;;and	al,3Fh
		;;xor	dl,al
		;;mov	[boot_record+1C4h+si],dl
		;;mov	[boot_record+1C5h+si],cl
		;mov	cl,[part_table_end_sector+bx]
		;;and	cl,3Fh
		;or	cl,al		
		;mov	[boot_record+1C4h+si],cl  ; End sector
		;mov	[boot_record+1C5h+si],ch  ; End cylinder

		lea	si,[part_table_boot_ind+bx]
		;es = ds = cs = ss
		mov	di,[wmbr_index]
		add	di,boot_record+1BEh
		
		movsw	; boot indicator & start head
		
		lodsb
		mov	cl,al ; start sector
		lodsw	; start cylinder
		mov	ch,al ; 04/01/2019
		shr	ax,1
		shr	ax,1
		and	al,0C0h
		or	al,cl ; sector bits 0 to 5, cylinder bits 8 & 9 (6 and 7)
		mov	ah,ch
		stosw	; start sector & start cylinder

		movsw	; system ID & end head

		lodsb
		mov	cl,al ; end sector
		lodsw	; end cylinder
		mov	ch,al ; 04/01/2019
		shr	ax,1
		shr	ax,1
		and	al,0C0h
		or	al,cl ; sector bits 0 to 5, cylinder bits 8 & 9 (6 and 7)
		mov	ah,ch
		stosw	; end sector & end cylinder
 		
		;; Microsoft C compiler code/output for
		;; /* Relative sectors */
		;;long_temp = part_table[disk][i].rel_sec;
		;;boot_record[0x1C9+(index)] = uc((long_temp >> 24));
		;;boot_record[0x1C8+(index)] = uc(((long_temp & 0x00FF0000l) >> 16));
		;;boot_record[0x1C7+(index)] = uc(((long_temp & 0x0000FF00l) >> 8));
		;;boot_record[0x1C6+(index)] = uc((long_temp & 0x000000FFl));

		;;mov	ax,[part_table_rec_sec_lw+bx]
		;;mov	dx,[part_table_rel_sec_hw+bx]
		;;mov	cx,ax
		;;mov	di,dx
		;;mov	dl,dh
		;;sub	dh,dh
		;;mov	[boot_record+1C9h+si],dl
		;;mov	si,di
		;;mov	ax,si
		;;mov	di,[wmbr_index]
		;;mov	[boot_record+1C8h+di],al
		;;mov	ax,cx
		;;mov	dx,si
		;;mov	cl,8
		;;mov	si,bx
		;;mov	[wmbr_long_temp],ax
		;;call	shr32
		;;mov	bx,[wmbr_index]
		;;mov	[boot_record+1C7h+bx],al
		;;mov	al,[wmbr_long_temp]
		;;mov	[boot_record+1C6h+bx],al

		; 21/12/2018
		; Direct assembly language code for
		; /* Relative sectors */
		
		;mov	ax,[part_table_rec_sec_lw+bx]
		;mov	dx,[part_table_rel_sec_hw+bx]
		;mov	[boot_record+1C6h+di],ax		
		;mov	[boot_record+1C8h+di],dx

		;; Microsoft C compiler code/output for
		;; /* Number of sectors */
		;;long_temp = part_table[disk][i].num_sec;
		;;boot_record[0x1CD+(index)] = uc(long_temp >> 24);
		;;boot_record[0x1CC+(index)] = uc((long_temp & 0x00FF0000l) >> 16);
		;;boot_record[0x1CB+(index)] = uc((long_temp & 0x0000FF00l) >> 8);
		;;boot_record[0x1CA+(index)] = uc(long_temp & 0x000000FFl);

		;;mov	ax,[part_table_num_sec_lw+si]
		;;mov	dx,[part_table_num_sec_hw+si]
		;;mov	cx,ax
		;;mov	si,dx
		;;mov	dl,dh
		;;sub	dh,dh
		;;mov	[boot_record+1CDh+bx],dl
		;;mov	di,si
		;;mov	ax,di
		;;mov	[boot_record+1CCh+bx],al
		;;mov	ax,cx
		;;mov	dx,si
		;;mov	cl,8
		;;mov	si,ax
		;;call	shr32
		;;mov	bx,[wmbr_index]
		;;mov	[boot_record+1CBh+bx],al
		;;mov	ax,si
		;;mov	[boot_record+1CAh+bx],al

		; 21/12/2018
		; Direct assembly language code for
		; /* Number of sectors */
		
		;mov	ax,[part_table_num_sec_lw+si]
		;mov	dx,[part_table_num_sec_hw+si]
		;mov	[boot_record+1CAh+bx],ax
		;mov	[boot_record+1CCh+bx],dx

		mov	cx,4
		rep	movsw
wmbr_4:
		inc	byte [wmbr_i]
		cmp	byte [wmbr_i],4
		;jnb	short wmbr_5
		;jmp	wmbr_2
		jb	short wmbr_2
wmbr_5:
		;mov	byte [boot_record+1FEh],55h
		;mov	byte [boot_record+1FFh],0AAh
		mov	word [boot_record+1FEh],0AA55h

		mov	al,[wmbr_disk] ; disk (0 to 7)
		push	ax
		sub	ax,ax  ; cylinder = 0
		push	ax
		call	write_boot_record
		;pop	bx
		;pop	bx ; 22/12/2018

		;pop	si
		;pop	di
		
		mov	sp,bp
		pop	bp
		;retn
		retn	2 ; 21/12/2018

; ----------------------------------------------------------------------------

;/*  */
;char write_ext_boot_to_disk(entry,disk)
;
;char entry;
;unsigned char disk;
;BEGIN
;
;    char            i;
;    unsigned        j;
;    unsigned long   long_temp;
;    char            location;
;    char            next_drive;
;    char            pointer;
;    char            write;
;
;    /* Clean out the boot_record */
;    for (j=u(0);j < u(BYTES_PER_SECTOR); j++)
;       BEGIN
;        boot_record[j] = uc(0);
;       END
;
;    /* First - setup the logical devices */
;    /* See if it has been deleted - if so, leave entries as zero */
;    /* Otherwise - go unscramble everything out of the arrays */
;
;    /* SR; 9/28/89; If entry=23, then sort[entry] is undefined and we
;       can have unpredictable results. Check for this special case */
;
;    if (entry != 23 && ext_table[disk][sort[entry]].sys_id != uc(0))
;       BEGIN
;        /* Get boot ind */
;        boot_record[0x1BE] = ext_table[disk][sort[entry]].boot_ind;
;
;        /* Start head */
;        boot_record[0x1BF] = ext_table[disk][sort[entry]].start_head;
;
;        /* Start sector - scramble it to INT 13 format */
;        boot_record[0x1C0] = (ext_table[disk][sort[entry]].start_sector & 0x3F) |
;                ((ext_table[disk][sort[entry]].start_cyl/256) << 6);
;
;        /* Start cyl - scramble it to INT 13 format*/
;        boot_record[0x1C1] = ((unsigned char)(ext_table[disk][sort[entry]].start_cyl%256));
;
;        /* System id */
;        boot_record[0x1C2]= ext_table[disk][sort[entry]].sys_id;
;
;        /* End head */
;        boot_record[0x1C3] = ext_table[disk][sort[entry]].end_head;
;
;        /* End sector - scramble it to INT 13 format */
;        boot_record[0x1C4] = (ext_table[disk][sort[entry]].end_sector & 0x3F) |
;             ((ext_table[disk][sort[entry]].end_cyl/256) << 6);
;
;        /* End cyl - scramble it to INT 13 format*/
;        boot_record[0x1C5] = ((unsigned char)(ext_table[disk][sort[entry]].end_cyl%256));
;
;        /* Relative sectors */
;        long_temp = ext_table[disk][sort[entry]].rel_sec;
;        boot_record[0x1C9] = uc((long_temp >> 24));
;        boot_record[0x1C8] = uc(((long_temp & 0x00FF0000l) >> 16));
;        boot_record[0x1C7] = uc(((long_temp & 0x0000FF00l) >> 8));
;        boot_record[0x1C6] = uc((long_temp & 0x000000FFl));
;
;        /* Number of sectors */
;        long_temp = ext_table[disk][sort[entry]].num_sec;
;        boot_record[0x1CD] = uc((long_temp >> 24));
;        boot_record[0x1CC] = uc(((long_temp & 0x00FF0000l) >> 16));
;        boot_record[0x1CB] = uc(((long_temp & 0x0000FF00l) >> 8));
;        boot_record[0x1CA] = uc((long_temp & 0x000000FFl));
;       END
;
;    /* set up pointer to next logical drive unless this is # 23 */
;    if (entry != c(22))
;       BEGIN
;        /* Find the drive to be pointed to */
;        pointer = entry+1;
;
;        /* Handle the special case of a deleted or empty first entry in partition */
;        if (entry == c(23))
;           BEGIN
;            pointer = c(0);
;           END
;        for (i = pointer; i <c(23); i++)
;           BEGIN
;            next_drive = ((char)(INVALID));
;
;            /* Go look for the next valid drive */
;            if (ext_table[disk][sort[i]].sys_id != uc(0))
;               BEGIN
;                next_drive = sort[i];
;                break;
;               END
;           END
;        if (next_drive != ((char)(INVALID)))
;           BEGIN
;            /* Get boot ind */
;            boot_record[0x1CE] = uc(0);
;
;            /* Start head */
;            boot_record[0x1CF] = uc(0);
;
;            /* Start sector - scramble it to INT 13 format*/
;            boot_record[0x1D0] = uc(0x01) | ((ext_table[disk][next_drive].start_cyl/256) << 6);
;
;            /* System id */
;            boot_record[0x1D2]= uc(EXTENDED);
;
;            /* End head */
;            boot_record[0x1D3] = uc(max_head[disk] -1);
;
;            /* End sector - scramble it to INT 13 format*/
;            boot_record[0x1D4] =(max_sector[disk] & 0x3F) | ((ext_table[disk][next_drive].end_cyl/256) << 6);
;
;            /* Start cyl - scramble it to INT 13 format*/
;            boot_record[0x1D1] = ((unsigned char)(ext_table[disk][next_drive].start_cyl%256));
;
;            /* End cyl - scramble it to INT 13 format*/
;            boot_record[0x1D5] = ((unsigned char)(ext_table[disk][next_drive].end_cyl%256));
;
;            /* Relative sectors - this is from the front of the extended volume */
;            /* Find the extended partition */
;            location = find_partition_location(uc(EXTENDED));
;            long_temp = ((unsigned long)(ext_table[disk][next_drive].start_cyl - part_table[disk][location].start_cyl))
;                          * max_head[disk] *  max_sector[disk];
;            boot_record[0x1D9] = uc((long_temp >> 24));
;            boot_record[0x1D8] = uc(((long_temp & 0x00FF0000l) >> 16));
;            boot_record[0x1D7] = uc(((long_temp & 0x0000FF00l) >> 8));
;            boot_record[0x1D6] = uc((long_temp & 0x000000FFl));
;
;            /* Number of sectors in the next volume*/
;            long_temp = ((unsigned long)(ext_table[disk][next_drive].end_cyl - ext_table[disk][next_drive].start_cyl+1))
;                        * max_head[disk] * max_sector[disk];
;            boot_record[0x1DD] = uc((long_temp >> 24));
;            boot_record[0x1DC] = uc(((long_temp & 0x00FF0000l) >> 16));
;            boot_record[0x1DB] = uc(((long_temp & 0x0000FF00l) >> 8));
;            boot_record[0x1DA] = uc((long_temp & 0x000000FFl));
;           END
;       END
;    boot_record[510] = uc(0x55);
;    boot_record[511] = uc(0xAA);
;
;    /* Write the boot record out */
;    if (entry != c(23))
;       BEGIN
;        write = write_boot_record(ext_table[disk][sort[entry]].start_cyl,disk);
;       END
;    else
;       BEGIN
;        /* Write the special case of the first entry only having a pointer */
;        write = write_boot_record(ext_table[disk][23].start_cyl,disk);
;       END
;    return(write);
;END

write_ext_boot_to_disk:

%define webr_temp3	bp-22h
%define webr_multiplicand_lw bp-1Eh
%define webr_multiplicand_hw bp-1Ch
%define webr_multiplier_lw bp-1Ah
%define webr_multiplier_hw bp-18h
%define webr_temp2	bp-16h
%define webr_temp1	bp-14h
%define webr_j		bp-0Eh
%define webr_i		bp-0Ch
%define webr_location	bp-0Ah
%define webr_next_drive	bp-8
%define webr_longtemp	bp-6
%define webr_longtemp_2	bp-4
%define webr_pointer	bp-2
%define webr_entry	bp+4
%define webr_disk	bp+6

		push	bp
		mov	bp, sp
		sub	sp, 34
		push	di
		push	si
		mov	word [webr_j], 0
webr_1:
		;/* Clean out the boot_record */

		;mov	bx,[webr_j]
		;mov	byte [boot_record+bx],0
		;inc	word [webr_j]
		;cmp	word [webr_j],512
		;jb	short webr_1

		xor	ax,ax
		mov	di,boot_record
		mov	cx,256
		;push	ds
		;pop	es
		rep	stosw

	; /* First - setup the logical devices */
	; /* See if it has been deleted - if so, leave entries as zero */
	; /* Otherwise - go unscramble everything out of the arrays */
	;
	; /* SR; 9/28/89; If entry=23, then sort[entry] is undefined and we
	;    can have unpredictable results. Check for this special case */

		cmp	byte [webr_entry],23
		;jne	short webr_2
		;jmp	webr_4
		je	short webr_4 ; 22/12/2018
webr_2:
		mov	al,24
		mul	byte [webr_disk]
		;mov	cx,ax
		;mov	al,[webr_entry]
		;cbw
		;mov	bx,ax
		mov	bl,[webr_entry]
		xor	bh,bh
		;mov	al,[sort+bx]
		;cbw
		;add	ax,cx
		add	al,[sort+bx]
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl ; 06/01/2019
		mov	bx,ax
		cmp	byte [ext_table_sys_id+bx],0
		;jne	short webr_3
		;jmp	webr_4
		je	short webr_4 ; 22/12/2018
webr_3:
		;/* Get boot ind */
		;mov	al,[ext_table_boot_ind+bx]
		;mov	[boot_record+1BEh],al  ; boot indicator
		;/* Start head */
		;mov	al,[ext_table_start_head+bx]
		;mov	[boot_record+1BFh],al  ;start head
		;/* Start sector - scramble it to INT 13 format */
		;/* Start cyl - scramble it to INT 13 format*/
		;mov	ax,[ext_table_start_cyl+bx]
		;mov	cx,ax
		;shr	ax,1
		;shr	ax,1
		;mov	dx,ax
		;xor	al,[ext_table_start_sector+bx]
		;and	al,3Fh
		;xor	dl,al
		;mov	[boot_record+1C0h],dl ; start sector
		;mov	[boot_record+1C1h],cl ; start cylinder
	
		lea	si,[ext_table_boot_ind+bx]
		;es = ds = cs = ss
		mov	di,boot_record+1BEh
		movsw	; boot indicator & start head
		
		lodsb
		mov	cl,al ; start sector
		lodsw	; start cylinder
		mov	ch,al ; 04/01/2019
		shr	ax,1
		shr	ax,1
		and	al,0C0h
		or	al,cl ; sector bits 0 to 5, cylinder bits 8 & 9 (6 and 7)
		mov	ah,ch
		stosw	; start sector & start cylinder

		movsw	; system ID & end head

		;/* System id */
		;mov	al,[ext_table_sys_id+bx]
		;mov	[boot_record+1C2h],al ; system ID
		;/* End head */
		;mov	al,[ext_table_end_head+bx]  ;end head
		;mov	[boot_record+1C3h],al ; end head
		;/* End sector - scramble it to INT 13 format */
		;/* End cyl - scramble it to INT 13 format*/
		;mov	ax,[ext_table_end_cyl+bx]
		;mov	cx,ax
		;shr	ax,1
		;shr	ax,1
		;mov	dx,ax
		;xor	al,[ext_table_end_sector+bx]
		;and	al,3Fh
		;xor	dl,al
		;mov	[boot_record+1C4h],dl ; end sector
		;mov	[boot_record+1C5h],cl ; end cylinder

		lodsb
		mov	cl,al ; end sector
		lodsw	; end cylinder
		mov	ch,al ; 04/01/2019
		shr	ax,1
		shr	ax,1
		and	al,0C0h
		or	al,cl ; sector bits 0 to 5, cylinder bits 8 & 9 (6 and 7)
		mov	ah,ch
		stosw	; end sector & end cylinder

 		;;/* Relative sectors */
		;;mov	ax,[ext_table_rel_sec_lw+bx]
		;;mov	dx,[ext_table_rel_sec_hw+bx]
		;;mov	cx,ax
		;;mov	si,dx
		;;mov	dl,dh
		;;sub	dh,dh
		;;mov	[boot_record+1C9h],dl
		;;mov	di,si
		;;mov	ax,si
		;;mov	[boot_record+1C8h],al
		;;mov	ax,cx
		;;mov	dx,di
		;;mov	cl,8
		;;mov	si,bx
		;;mov	[webr_temp],ax
		;;call	shr32
		;;mov	[boot_record+1C7h],al
		;;mov	al,[webr_temp]
		;;mov	[boot_record+1C6h],al

		;mov	ax,[ext_table_rec_sec_lw+bx]
		;mov	dx,[ext_table_rel_sec_hw+bx]
		;mov	[boot_record+1C6h+di],ax		
		;mov	[boot_record+1C8h+di],dx

		;;/* Number of sectors */
		;;mov	ax,[ext_table_num_sec_lw+si]
		;;mov	dx,[ext_table_num_sec_hw+si]
		;;mov	[webr_longtemp],ax
		;;mov	[webr_longtemp+2],dx
		;;mov	cx,ax
		;;mov	bx,dx
		;;mov	dl,dh
		;;sub	dh,dh
		;;mov	[boot_record+1CDh],dl
		;;mov	si,bx
		;;mov	[boot_record+1CCh],bl
		;;mov	dx,bx
		;;mov	cl,8
		;;mov	di,ax
		;;call	shr32
		;;mov	[boot_record+1CBh],al
		;;mov	ax,di
		;;mov	[boot_record+1CAh],al

		;mov	ax,[ext_table_num_sec_lw+si]
		;mov	dx,[ext_table_num_sec_hw+si]
		;mov	[boot_record+1CAh+bx],ax
		;mov	[boot_record+1CCh+bx],dx

		mov	cx,4
		rep	movsw

	;/* set up pointer to next logical drive unless this is # 23 */
webr_4:
		mov	al,[webr_entry] ; 21/12/2018

		;cmp	byte [webr_entry],22
		cmp	al,22
		jne	short webr_5
		jmp	webr_11

	;/* Find the drive to be pointed to */	
webr_5:
		; 21/12/2018
		cmp	al,23
		je	short webr_14

		;mov	al,[webr_entry]
		inc	al
		mov	[webr_pointer],al
		jmp	short webr_6

	;/* Handle the special case of a deleted or empty first entry in partition */

		;cmp	[webr_entry],23
		;jne	short webr_6
webr_14:
		sub	al,al ; 0 ; 21/12/2018
		;mov	byte [webr_pointer],0

		mov	[webr_pointer],al ; 0
;webr_6:
		;mov	al,[webr_pointer]

		;for (i = pointer; i < c(23); i++)
webr_6:
		mov	[webr_i],al ; al = [webr_pointer]
		;jmp	short webr_8
		jmp	short webr_15
webr_7:
		inc	byte [webr_i] ; i++

webr_8:
		cmp	byte [webr_i],23 ; i < c(23)
		;jge	short webr_9
		jge	webr_11
webr_15:
		; next_drive = ((char)(INVALID));

		;mov	byte [webr_next_drive],0FFh ; 255

	;/* Go look for the next valid drive */

		mov	al,24
		mul	byte [webr_disk]
		;mov	cx,ax
		;mov	al,[webr_i]
		;cbw
		;mov	bx,ax
		mov	bl,[webr_i]
		xor	bh,bh
		;mov	al,[sort+bx]
		;mov	dx,ax
		mov	dl,[sort+bx]
		;cbw
		;add	ax,cx
		add	al,dl
		;mov	cx,46
		;mov	bx,dx
		;imul	cx
		mov	cl,46
		mul	cl
		mov	si,ax

		;if (ext_table[disk][sort[i]].sys_id != uc(0))

		cmp	byte [ext_table_sys_id+si],0
		je	short webr_7 ; next for

		; next_drive = sort[i];

		;;mov	[webr_next_drive],bl
		;mov	[webr_next_drive],dl

		; break;   ; exit for
webr_9:
		; condition check inside 'for'

		; if (next_drive != ((char)(INVALID)))

;		cmp	byte [webr_next_drive],0FFh ; 255
;		jne	short webr_10
;		jmp	webr_11  ; next_drive = 0FFh ; exit from 'for'

webr_10:	; next_drive != 0FFh

		;sub	al,al
		;mov	[boot_record+1CEh],al ; boot (active) indicator
		;mov	[boot_record+1CFh],al ; start head (= 0)

		sub	ax,ax
		mov	[boot_record+1CEh],ax ; 0 

		;mov	al,[webr_next_drive]
		;cbw
		;mov	cx,24
		mov	cl,24
		;mov	dx,ax
		mov	al,[webr_disk]
		;sub	ah,ah
		;mov	bx,dx
		;mov	si,46
		mov	di,ax ; *!*!"
		;imul	cx
		mul	cl ; [webr_disk]*24
		;add	ax,bx
		;add	al,[webr_next_drive] ; 06/01/2019
		add	al,dl  ; add al,[webr_next_drive]
		;imul	si
		mov	cl,46
		mul	cl
		mov	bx,ax ; **

		mov	ax,[ext_table_start_cyl+bx]
		mov	ch,al ; 04/01/2019
		shr	ax,1
		shr	ax,1
		;and	al,0C1h
		and	al,0C0h
		or	al,1
		mov	ah,ch
		;mov	[boot_record+1D0h],al ; start sector (= 1) 
					      ;	and cylinders bits 8 and 9
		;mov	[boot_record+1D1h],ch ; start cylinder (bits 0 to 7)
		mov	[boot_record+1D0h],ax ; start sector & start cylinder
		mov	byte [boot_record+1D2h],5 ; EXTENDED  ; system ID
		
		;mov	ax,di ;disk (0 to 7)
		mov	si,di ; *!*!
		shl	di,1
		mov	dl,[max_head+di] ;*!*!*
		dec	dl
		mov	[boot_record+1D3h],dl ; end head

		mov	dx,[ext_table_end_cyl+bx]
		mov	ch,dl ; end cylinder, low 8 bits
		shr	dx,1
		shr	dx,1
		and	dl,0C0h
		mov	[webr_temp1],bx ; **
		;mov	bx,ax
		;mov	[webr_temp2],dx
		;xor	dl,[max_sector+bx]
		;and	dl,3Fh
		;xor	dl,[webr_temp2]
		mov	cl,[max_sector+si] ; *!*!
		;and	cl,3Fh
		or	cl,dl ; scramble end sector (bit 0 to bit 5) to 
			      ; end cylinder bits 8 & 9 (end sector bits 6 & 7)
		
		;mov	[boot_record+1D4h],dl ; end sector
		;mov	[boot_record+1D1h],cl
		;mov	cx,si
		;mov	[boot_record+1D5h],cl ; end cylinder
		;mov	cl,5
		;mov	[boot_record+1D2h],cl

		mov	[boot_record+1D4h],cx ; end sector & end cylinder	

		;/* Find the extended partition */

		;push	cx
		
		;mov	si,bx
		;call	find_partition_location
		;pop	bx
		;mov	[webr_location],al

		;mov	al,5  ; EXTENDED
		;mov	[boot_record+1D2h],al

		mov	al,5 ; EXTENDED
		;push	ax
		call	find_partition_type
			 ; CH = 0 ; *
			 ; CL = Partition number if CF = 0
		;pop	bx

		mov	[webr_location],cl

	;/* Relative sectors - this is from the front of the extended volume */

		mov	ax,[max_head+di] ; *!*!* (di = disk number * 2)
		;sub	dx,dx
		;push	dx ; 0		     ; dx_h	
		;push	ax ; max_head[disk]  ; ax_h	
		mov	cl,[max_sector+si] ; *!*! (si = disk number)
		;;sub	ch,ch ; *
		;sub	bx,bx
		;push	bx ; 0
		;push	cx ; max_sector[disk]
		mov	di,46
		shl	si,1
		shl	si,1 ; disk number * 4
		
		; 22/12/2018
		mul	cx ; mx_sector[disk]*max_head[disk]
		
		mov	[webr_multiplier_lw],ax
		mov	[webr_multiplier_hw],dx

		; 22/12/2018
		push	dx ; DX_h*s
		push	ax ; AX_h*s

		mov	al,[webr_location]
		cbw
		add	ax,si
		;imul	di
		mul	di ; * 46
		mov	si,ax ; [disk][location]

		mov	di,[webr_temp1] ; ** ; [disk][next_drive]

		mov	ax,[ext_table_start_cyl+di]

		;mov	dx,ax
		mov	di,ax ; ext_table[disk][next_drive].start_cyl ; ***

		sub	ax,[part_table_start_cyl+si]

	; ax = ext_table[disk][next_drive].start_cyl - part_table[disk][location].start_cyl

		;mov	si,dx  
		;sub	dx,dx
		
		push	dx ; 0
		push	ax
		
		;mov	di,cx
		;mov	[webr_multiplicand_lw],di
		;mov	[webr_multiplicand_hw],bx

		;; stack: ; Microsoft C compiler's multiplication code
		;	;sp+5 -> dx_head = 0
		;	;sp+4 -> ax_head = max_head[disk]
		;	;sp+3 -> bx = 0
		;	;sp+2 -> cx = max_sector[disk]
		;	;sp+1 -> dx = 0
		;	;sp -> ax = next_drive's start cyl - extended partition's start cyl
		;call	mul_32 ; [bx:cx]*[dx:ax]
		;	; result:
		;	;   dx:ax = start cylinder difference * max_sector[disk]
		;push	dx
		;push	ax
		;	;sp+3 -> dx_head = 0
		;	;sp+2 -> ax_head = max_head[disk]
		;	;sp+1 -> dx = high word of previous multiplication result
		;	;sp -> ax = low word of previous multiplication result
		;call	mul32
		;	; result:
		;	;   dx:ax = start cyl diff. * max_sector[disk] * max_head[disk]
			;         = relative start sector of next logical drv in ext part.
		
		; stack: ; Erdogan Tan - 22/12/2018
		;	;sp+3 -> DX_h*s = high word of max_sector[disk]*max_head[disk]
		;	;sp+2 -> AX_h*s = low word of max_sector[disk]*max_head[disk]
		;	;sp+1 -> DX = 0
		;	;sp -> AX = next_drive's start cyl - extended partition's start cyl
		call	mul32
			; result:
			;   dx:ax = relative start sector of next logical drive in ext part.

		;mov	cx,ax
		;mov	bx,dx
		;mov	dl,dh
		;sub	dh,dh
		;mov	[boot_record+1D9h],dl
		;mov	di,bx
		;mov	[boot_record+1D8h],bl
		;mov	dx,di
		;mov	cl,8
		;mov	[webr_temp3],ax
		;call	shr32
		;mov	[boot_record+1D7h],al
		;mov	al,[webr_temp3]
		;mov	[boot_record+1D6h],al

		; 22/12/2018
		mov	[boot_record+1D6h],ax
		mov	[boot_record+1D8h],dx

	;/* Number of sectors in the next volume */

		;push	word [webr_multiplier_hw]   ; 0	
		;push	word [webr_multiplier_lw]   ; max_head[disk] 	
		;push	word [webr_multiplicand_hw] ; 0
		;push	word [webr_multiplicand_lw] ; max_sector[disk]
		;mov	bx,[webr_temp]
		;sub	si,[ext_table_end_cyl+bx]
		;neg	si
		;inc	si
		;sub	cx,cx
		;push	cx ; 0
		;push	si ; cylinder count of the next logical drive
		;call	mul32
		;push	dx ;high word of cylinders * sectors (per track)	
		;push	ax ;low word of cylinders * sectors (per track)
		;call	mul32
		
		; 22/12/2018
		push	word [webr_multiplier_hw] ; hw of mx_sector[disk]*max_head[disk]
		push	word [webr_multiplier_lw] ; lw of mx_sector[disk]*max_head[disk]
		
		; di = ext_table[disk][next_drive].start_cyl ; ***

		mov	bx,[webr_temp1]
		sub	di,[ext_table_end_cyl+bx]
		neg	di
		inc	di
		xor	bx,bx
		push	bx ; 0
		push	di ; cylinder count of the next logical drive
		call	mul32
			; result:
			;   dx:ax = number of sectors in the next logical drive	

		;mov	[webr_longtemp],ax
		;mov	[webr_longtemp+2],dx
		;mov	dl,dh
		;sub	dh,dh
		;mov	[boot_record+1DDh],dl
		;mov	al,[webr_longtemp_2]
		;mov	[boot_record+1DCh],al
		;mov	ax,[webr_longtemp]
		;mov	dx,[webr_longtemp+2]
		;mov	cl,8
		;call	shr32
		;mov	[boot_record+1DBh],al
		;mov	al,[webr_longtemp]
		;mov	[boot_record+1DAh],al

		; 22/12/2018
		mov	[boot_record+1DAh],ax
		mov	[boot_record+1DCh],dx
webr_11:
		;mov	byte [boot_record+1FEh],55h
		;mov	byte [boot_record+1FFh],0AAh
		mov	word [boot_record+1FEh],0AA55h

		cmp	byte [webr_entry],23
		je	short webr_12

		;/* Write the boot record out */

		mov	al,[webr_disk]
		push	ax
		mov	cl,24
		mul	cl
		;mov	cx,ax
		;mov	al,[webr_entry]
		;cbw
		;mov	bx,ax

		mov	bl,[webr_entry]
		xor	bh,bh
		;;mov	al,[sort+bx]
		;mov	cl,[sort+bx]
		;;cbw
		;;add	ax,cx
		;add	al,cl
		add	al,[sort+bx]
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		push	word [ext_table_start_cyl+bx]
		jmp	short webr_13

	;/* Write the special case of the first entry only having a pointer */
webr_12:
		mov	al,[webr_disk]
		sub	ah,ah
		push	ax	; Disk (0 to 7)
		mov	cx,1104 ; 24*46
		;imul	cx
		mul	cx
		mov	bx,ax
		push	word [ep0_lp23_start_cyl+bx]  ; Cylinder
webr_13:
		call	write_boot_record
		;pop	bx
		;pop	bx ; 22/12/2018

		;pop	si
		;pop	di

		mov	sp,bp
		pop	bp
		
		;retn
		retn	4 ; 05/01/2019

; ============================================================================
;  DELETE PARTITION
; ============================================================================
; 23/12/2018

; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/*  Screen for DELETE_PARTITION                                                                    */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                   Delete DOS Partition or Logical DOS Drive                    |menu_25   */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Choose one of the following:                                                |menu_3 #  */
;/*   09|                                                                                |          */
;/*   10|    1.  Delete Primary DOS Partition                                            |menu_26   */
;/*   11|    2.  Delete Extended DOS Partition                                           |menu_26   */
;/*   12|    3.  Delete Logical DOS Drive(s) in the Extended DOS Partition               |menu_27   */
;/*   13|    4.  Delete Non-DOS Partition                                                |menu_57   */
;/*   14|                                                                                |          */
;/*   15|                                                                                |          */
;/*   16|                                                                                |          */
;/*   17|    Enter choice: [ ]                                                           |menu_7 #  */
;/*   18|                                                                                |          */
;/*   19|                                                                                |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */
;/*                                                                                                 */
;/***************************************************************************************************/
; ----------------------------------------------------------------------------
; d_menus.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 23/12/2018)

;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: DELETE_PARTITION                           */
;/*                                                             */
;/* DESCRIPTIVE NAME: Delete partition selection menu           */
;/*                                                             */
;/* FUNCTION: User is prompted as to what type of DOS partition */
;/*           he wishes to delete.                              */
;/*                                                             */
;/* NOTES: The delete volume option is only displayed if some   */
;/*        disk volumes exist                                   */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*     |0000000000111111111122222222223333333333|              */
;/*     |0123456789012345678901234567890123456789|              */
;/*   --|----------------------------------------|              */
;/*   00|                                        |              */
;/*   01|                                        |              */
;/*   02|                                        |              */
;/*   03|                                        |              */
;/*   04|Delete DOS Partition                    |              */
;/*   05|                                        |              */
;/*   06|Current Fixed Disk Drive: #             |              */
;/*   07|                                        |              */
;/*   08|Enter the type of DOS partition you     |              */
;/*   09|wish to delete..............?           |              */
;/*   10|                                        |              */
;/*   11|    1.  Normal DOS partition            |              */
;/*   12|    2.  EXTENDED DOS Partition          |              */
;/*   13|    3.  Disk volume in the EXTENDED     |              */
;/*   14|        DOS Partition                   |              */
;/*   15|                                        |              */
;/*   16|                                        |              */
;/*   17|                                        |              */
;/*   18|Enter choice: [#]                       |              */
;/*   19|                                        |              */
;/*   20|                                        |              */
;/*   21|                                        |              */
;/*   22|                                        |              */
;/*   23|Press ESC to return to FDISK Options    |              */
;/*   --------------------------------------------              */
;/*                                                             */
;/* ENTRY POINTS: Delete_Partition                              */
;/*      LINKAGE: delete_partition()                            */
;/*           NEAR CALL                                         */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if case statement   */
;/*             failure when branching to requested function    */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      wait_for_ESC                                           */
;/*      get_num_input                                          */
;/*      internal_program_error                                 */
;/*      dos_delete                                             */
;/*      ext_delete                                             */
;/*      vol_delete                                             */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void delete_partition()
;
;BEGIN
;
;    unsigned i;
;    char input;
;    char temp;
;    char max_input;
;
;    input = c(NUL);
;    /* clear_screen */
;    clear_screen(u(0),u(0),u(24),u(79));
;
;    /* Display header */
;    display(menu_25);
;
;    /* Setup and print current disk */
;    insert[0] = cur_disk+1+'0';
;    display(menu_5);
;
;    /* check to see if there is an avail partition */
;    temp = c(0);
;    for (i = u(0); i < u(4);i++)
;       BEGIN
;
;        /* See if any non - zero system id bytes */
;        temp = temp | part_table[cur_disk][i].sys_id ;
;       END
;    /* Any entry that isn't zero means */
;    if (temp != c(0))
;       BEGIN
;
;        /* Display enter prompts */
;        /* display dos delete menu without input prompt */
;        display(menu_3);
;        display(menu_25);
;        display(menu_26);
;        display(menu_7);
;
;        /* print ESC prompt */
;        display(menu_11);
;
;        display(menu_27);
;        display(menu_57);
;        max_input = c(4);
;
;        input = get_num_input(c(NUL),max_input,input_row,input_col);
;        /* Go branch to the requested function */
;        switch(input)
;           BEGIN
;            case '1':
;                if (find_partition_type(uc(DOS12)) ||
;                    find_partition_type(uc(DOS16)) ||
;                    find_partition_type(uc(DOSNEW)))
;                    dos_delete();
;                else
;                    BEGIN
;                    /* No Pri partition to delete */
;                    clear_screen(u(17),u(0),u(17),u(79));
;                    display(error_6);
;                    wait_for_ESC();
;                    END
;                break;
;
;            case '2':
;                if (find_partition_type(uc(EXTENDED)))
;                    ext_delete();
;                else
;                    BEGIN
;                    /* No Ext partition to delete */
;                    clear_screen(u(17),u(0),u(17),u(79));
;                    display(error_7);
;                    wait_for_ESC();
;                    END
;                break;
;
;            case '3':
;                if ((find_partition_type(uc(EXTENDED))) && (find_logical_drive()))
;                    volume_delete();
;                else
;                    BEGIN
;                    clear_screen(u(17),u(0),u(17),u(79));
;                    display(error_36);
;                    wait_for_ESC();
;                    END
;                break;
;
;            case '4':
;                if (find_non_dos_partition())
;                    non_dos_delete();
;                else
;                    BEGIN
;                    clear_screen(u(17),u(0),u(17),u(79));
;                    display(error_38);
;                    wait_for_ESC();
;                    END
;                break;
;
;            case ESC:
;                break;
;
;            default :
;                internal_program_error();
;                 break;
;           END
;       END
;    else
;       BEGIN
;        display(error_14);
;        wait_for_ESC();
;       END
;    /* clear the screen before going back to main menu */
;    clear_screen(u(0),u(0),u(24),u(79));
;    return;
;END

delete_partition:
		; 23/12/2018

	%define dp_i	bp-4
	%define dp_temp	bp-2

		push	bp
		mov	bp,sp
		sub	sp,4

		;/* clear_screen */

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;/* Display header */

		;push	word [menu_25_segment]
		push	ds
		push	word [menu_25_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup and print current disk */

		;mov	al,[cur_disk]
		;add	al,'1'
		;mov	[insert],al
		;;push	word [menu_5_segment]
		;push	ds
		;push	word [menu_5_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_5 ; 31/12/2018

		;/* check to see if there is an avail partition */
		
		sub	al,al ; 0
		mov	[dp_temp],al
		mov	[dp_i],al ; 0
dp_1:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;add	ax,[dp_i]
		add	al,[dp_i]
		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax

		;/* See if any non-zero system id bytes */
		
		mov	al,[part_table_sys_id+bx]
		or	[dp_temp],al
		inc	byte [dp_i]
		cmp	byte [dp_i],4
		jb	short dp_1

		;/* Any entry that isn't zero means */

		cmp	byte [dp_temp],0
		jne	short dp_2
		jmp	dp_16
dp_2:
		;/* Display enter prompts */
		;/* display dos delete menu without input prompt */

		;push	word [menu_3_segment]
		push	ds
		push	word [menu_3_offset]
		call	display
		;pop	bx
		;pop	bx
		
		;;push	word [menu_25_segment]
		;push	ds
		;push	word [menu_25_offset]
		;call	display
		;;pop	bx
		;;pop	bx
		
		;push	word [menu_26_segment]
		push	ds
		push	word [menu_26_offset]
		call	display
		;pop	bx
		;pop	bx
		
		;push	word [menu_7_segment]
		push	ds
		push	word [menu_7_offset]
		call	display
		;pop	bx
		;pop	bx
		
		;/* print ESC prompt */

		;;push	word [menu_11_segment]
		;push	ds
		;push	word [menu_11_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_11 ; 31/12/2018
		
		;push	word [menu_27_segment]
		push	ds
		push	word [menu_27_offset]
		call	display
		;pop	bx
		;pop	bx

		;push	word [menu_57_segment]
		push	ds
		push	word [menu_57_offset]
		call	display
		;pop	bx
		;pop	bx

		push	word [input_col]
		push	word [input_row]
		mov	al,4  ; Maximum input = 4	
		push	ax
		sub	al,al ; Default input = 0
		push	ax
		call	get_num_input
		;add	sp,8

		;/* Go branch to the requested function */
switch_input2:
		;cbw
		;cmp	ax,'4'
		cmp	al,'4'
		jne	short dp_4
		jmp	case_delete_4
dp_4:
		ja	short dp_6
		sub	al,1Bh  ; ESC key
		jnz	short dp_5
		jmp	case_delete_ESC
dp_5:
		sub	al,16h  ; 1Bh+16h = 31h = '1'
		jz	short case_delete_1
		dec	al		  ; 32h = '2'
		jz	short case_delete_2
		dec	al		  ; 33h = '3'	
		jz	short case_delete_3
dp_6:
		call	internal_program_error
		jmp	case_delete_ESC
case_delete_1:
		mov	al,1  ; DOS12 (FAT12)
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short dp_8
		jnc	short dp_8

		mov	al,4  ; DOS16 (FAT16)
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short dp_8
		jnc	short dp_8
		
		mov	al,6  ; DOSNEW (FAT16 big)
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short dp_9
		jc	short dp_9
dp_8:
		call	dos_delete
		jmp	case_delete_ESC
dp_9:
		;mov	ax,79
		;push	ax
		;mov	ax,17
		;push	ax
		;sub	cx,cx
		;push	cx
		;push	ax
		;call	clear_screen
		;;add	sp,8

		call	CLS_R17 ; 23/12/2018

		;push	word [error_6_seg]
		push	ds
		push	word [error_6_off]
		jmp	dp_17
case_delete_2:
		mov	al,5 ; EXTENDED partition
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short dp_11
		jc	short dp_11

		call	ext_delete
		jmp	case_delete_ESC
dp_11:
		;mov	ax,79
		;push	ax
		;mov	ax,17
		;push	ax
		;sub	cx,cx
		;push	cx
		;push	ax
		;call	clear_screen
		;;add	sp,8

		call	CLS_R17 ; 23/12/2018

		;push	word [error_7_seg]
		push	ds
		push	word [error_7_off]
		jmp	short dp_17
case_delete_3:
		mov	al,5
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al, al
		;jz	short dp_13
		jc	short dp_13
		call	find_logical_drive
		;or	al,al
		;jz	short dp_13
		jc	short dp_13
		call	volume_delete
		jmp	short case_delete_ESC
dp_13:
		;mov	ax,79
		;push	ax
		;mov	ax,17
		;push	ax
		;sub	cx,cx
		;push	cx
		;push	ax
		;call	clear_screen
		;;add	sp,8

		call	CLS_R17 ; 23/12/2018

		;push	word [error_36_seg]
		push	ds
		push	word [error_36_off]
		jmp	short dp_17
case_delete_4:
		call	find_non_dos_partition
		;or	al,al
		;jz	short dp_15
		jc	short dp_15
		call	non_dos_delete
		jmp	short case_delete_ESC
dp_15:
		;mov	ax,79
		;push	ax
		;mov	ax,17
		;push	ax
		;sub	cx,cx
		;push	cx
		;push	ax
		;call	clear_screen
		;;add	sp,8

		call	CLS_R17 ; 23/12/2018

		;push	word [error_38_seg]
		push	ds
		push	word [error_38_off]
		jmp	short dp_17
dp_16:
		;push	word [error_14_seg]
		push	ds
		push	word [error_14_off]
dp_17:
		call	display
		;pop	bx
		;pop	bx

		call	wait_for_ESC
case_delete_ESC:
		;/* clear the screen before going back to main menu */

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen

		call	CLS
		
		mov	sp,bp
		pop	bp
		retn

CLS_R17:
		; 23/12/2018 (Clear row 17)
		mov	ax,79
		push	ax
		mov	ax,17
		push	ax
		sub	cx,cx
		push	cx
		push	ax
		call	clear_screen
		;add	sp,8
		retn

; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/*  Screen for DOS_DELETE                                                                          */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                           Delete Primary DOS Partition                         |menu_28   */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Partition Status   Type    Size in Mbytes   Percentage of Disk Used         |menu_14 # */
;/*   09|     ## #        #   #######       ####         ###%                            |menu_14 # */
;/*   10|     ## #        #   #######       ####         ###%                            |          */
;/*   11|     ## #        #   #######       ####         ###%                            |          */
;/*   12|     ## #        #   #######       ####         ###%                            |          */
;/*   13|                                                                                |          */
;/*   14|    Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes)                   |menu_15 # */
;/*   15|                                                                                |          */
;/*   16|    Warning! Data in the deleted Primary DOS Partition will be lost.            |menu_29   */
;/*   17|    What Primary DOS Partition do you want to delete? [ ]                       |          */
;/*   18|                                                                                |          */
;/*   19|    Do you wish to continue (Y/N).................? [N]                         |menu_56   */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */ 
;/*                                                                                                 */
;/***************************************************************************************************/

; d_menus.c (MSDOS 6.0)
;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: DOS_DELETE                                 */
;/*                                                             */
;/* DESCRIPTIVE NAME: Delete DOS partition                      */
;/*                                                             */
;/* FUNCTION: Delete the DOS partition. Prompt user with dire   */
;/*           warning first. Default entry on prompt is (N)     */
;/*                                                             */
;/* NOTES: Screen can be exited via the ESC command before      */
;/*        partition is deleted and nothing will change         */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*     |0000000000111111111122222222223333333333|              */
;/*     |0123456789012345678901234567890123456789|              */
;/*   --|----------------------------------------|              */
;/*   00|                                        |              */
;/*   01|                                        |              */
;/*   02|                                        |              */
;/*   03|                                        |              */
;/*   04|Delete DOS Partition                    |              */
;/*   05|                                        |              */
;/*   06|Current Fixed Disk Drive: #             |              */
;/*   07|                                        |              */
;/*   08|Partition Status   Type  Start  End Size|              */
;/*   09|    #        #   #######  #### #### ####|              */
;/*   10|                                        |              */
;/*   11|                                        |              */
;/*   12|                                        |              */
;/*   13|                                        |              */
;/*   14|Total disk space is #### cylinders.     |              */
;/*   15|                                        |              */
;/*   16|                                        |              */
;/*   17|                                        |              */
;/*   18|Warning! Data in the DOS partition      |              */
;/*   19|will be lost. Do you wish to            |              */
;/*   20|continue..........................? [N] |              */
;/*   21|                                        |              */
;/*   22|                                        |              */
;/*   23|Press ESC to return to FDISK Options    |              */
;/*   --------------------------------------------              */
;/*                                                             */
;/* ENTRY POINTS: DOS_Delete                                    */
;/*      LINKAGE: dos_delete                                    */
;/*          NEAR CALL                                          */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if invalid input    */
;/*             returned to this level                          */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES                                                  */
;/*      table_display                                          */
;/*      clear_screen                                           */
;/*      wait_for_ESC                                           */
;/*      get_yn_input                                           */
;/*      display                                                */
;/*      Write_Boot_Record                                      */
;/*      find_part_free_space                                   */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void dos_delete()
;
;BEGIN
;
;    char input;
;    unsigned i;
;    unsigned char string_input[12];
;
;    int     j;
;    int     pri;
;    int     ext;
;    int     cnt;
;    int     pnum;
;
;    input = c(NUL);
;    /* clear screen */
;    clear_screen(u(0),u(0),u(24),u(79));
;
;    /* Display header */
;    display(menu_28);
;
;    /* Setup and print current disk */
;    insert[0] = cur_disk+1+'0';
;    display(menu_5);
;
;    /* print ESC prompt */
;    display(menu_11);
;
;    /* Display partition data and double check if partition exists*/
;    if (table_display())
;       BEGIN
;
;        sprintf(insert,"%4.0d",total_mbytes[cur_disk]);
;        display(menu_15);
;
;        /* See if drive 1 and extended partition exists */
;
;        cnt = 0;
;        pri = 0;
;        ext = 0;
;
;        /* Find the total number of partitions, the number of normal
;        /* partitions, and whether there is an extended partition on the
;        /* current hard disk
;
;        for (i = u(0); i < u(4); i++)
;            if (part_table[cur_disk][i].sys_id != uc(0))
;               {
;                cnt++;
;                if ((part_table[cur_disk][i].sys_id == uc(DOS12)) ||
;                    (part_table[cur_disk][i].sys_id == uc(DOS16)) ||
;                    (part_table[cur_disk][i].sys_id == uc(DOSNEW))  )
;                   {
;                    pri++;
;                   }
;                else if (part_table[cur_disk][i].sys_id == uc(LOGICAL))
;                   {
;                    ext = 1;
;                   }
;               }
;
;        /* The partition can be deleted if the the number of normal          */
;        /* partitions is greater than one or if there is only one but it is  */
;        /* not the first hard disk or if there is only one normal partition  */
;        /* on the first hard disk but no extended partition.                 */
;
;        if ((pri > 1) ||
;            (pri == 1 && cur_disk != c(0)) ||
;            (pri == 1 && cur_disk == c(0) && !ext))
;           BEGIN
;            /* Display partition number prompt */
;            display(menu_55);
;
;            /* Get the partition number from the user */
;            input = get_num_input(c(1),c(cnt),input_row,input_col);
;
;            if (input != ESC)
;               {
;                pnum = (int)input - '0';
;
;                /* The number that the user has entered is the sorted numbering  */
;                /* of the partition table. We have to retrieve the actual        */
;                /* position of this partition in the partition table             */
;
;                j = 0;
;                for (i = 0; i < 4; i++)
;                   {
;                    if (part_table[cur_disk][sort[i]].sys_id != 0)
;                       {
;                        j++;
;                        if (j == pnum)
;                            break;
;                       }
;                   };
;                i = sort[i];
;
;                /* Verify selected partition is a primary partition */
;
;                if ((part_table[cur_disk][i].sys_id==uc(DOS12)) ||
;                    (part_table[cur_disk][i].sys_id==uc(DOS16)) ||
;                    (part_table[cur_disk][i].sys_id==uc(DOSNEW)) )
;                   {
;                    /* delete previous volume mismatch message */
;                    string_input[0] = uc(NUL);
;
;                    /* Get input volume label */
;                    display(menu_41);
;                    get_string_input(input_row,input_col,string_input);
;                    if (string_input[0] != uc(ESC))
;                       {
;                        /* See if the volume id matches the drive */
;                        if (strcmp(part_table[cur_disk][i].vol_label,
;                            string_input) == (int)ZERO)
;                           {
;                            /* Display Y/N prompt */
;                            display(menu_34);
;
;                            /* Get yes/no prompt */
;                            input = get_yn_input(c(No),input_row,input_col);
;                            switch(input)
;                               BEGIN
;                                case 1:
;                                   BEGIN
;                                    /* Set Partition entry to zero */
;                                    remove_partition(cur_disk,i);
;
;                                    /* Redisplay the partition info */
;                                    table_display();
;
;                                    /* clear the prompt off */
;                                    clear_screen(u(16),u(0),u(23),u(79));
;
;                                    /* Set the reboot flag */
;                                    reboot_flag = (FLAG)TRUE;
;
;                                    /* Say that you deleted it */
;                                    display(status_1);
;
;                                    wait_for_ESC();
;                                    break;
;                                   END
;
;                                case 0:
;                                    break;
;
;                                case ESC:
;                                    break;
;
;                                default:
;                                   BEGIN
;                                    internal_program_error();
;                                    break;
;                                   END
;                               END
;                           }
;                        else
;                           {
;                            /* Tell user volume name was incorrect */
;                            display(error_34);
;                            wait_for_ESC();
;                           }
;                       }
;                   }
;                else
;                   {
;                    /* Tell user he can only delete primary partition */
;                    display(error_37);
;                    wait_for_ESC();
;                   }
;               }
;           END
;        else
;           BEGIN
;            /* Tell user he can't do it while extended exists on drive 1 */
;            display(error_32);
;            wait_for_ESC();
;           END
;       END
;
;    else
;       BEGIN
;        internal_program_error();
;       END
;    clear_screen(u(0),u(0),u(24),u(79));
;    return;
;END

dos_delete:
		; 23/12/2018

	%define ddp_pri	      bp-24 ;bp-26
	%define ddp_j	      bp-22 ;bp-24
	%define ddp_i	      bp-20 ;bp-22
	%define ddp_str_input bp-18 ;bp-20
	%define ddp_cnt	      bp-6  ;bp-8
	%define ddp_ext	      bp-4  ;bp-6
	%define ddp_input     	    ;bp-4
	%define ddp_pnum      bp-2  ;bp-2

		push	bp
		mov	bp,sp
		;sub	sp,26
		sub	sp,24 ; 24/12/2018

		;mov	word [ddp_input],0
		
		;/* clear screen */

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;/* Display header */

		;push	word [menu_28_segment]
		push	ds
		push	word [menu_28_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup and print current disk */

		;mov	al,[cur_disk]
		;add	al,'1'
		;mov	[insert],al
		;;push	word [menu_5_segment]
		;push	ds
		;push	word [menu_5_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_5 ; 31/12/2018
		
		;/* print ESC prompt */

		;;push	word [menu_11_segment]
		;push	ds
		;push	word [menu_11_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_11 ; 31/12/2018

	;/* Display partition data and double check if partition exists */

		call	table_display
		;or	al,al
		;jnz	short ddp_1
		jnc	short ddp_1
		jmp	case_dos_del_DEF
ddp_1:
		;;mov	al,[cur_disk]
		;;cbw
		;;mov	bx,ax
		;mov	bl,[cur_disk]
		;xor	bh,bh
		;shl	bx,1
		;push	word [total_mbytes+bx]
		;mov	ax,disk_size_format ; "%4.1d"
		;push	ax
		;mov	ax,insert
		;push	ax
		;call	sprintf
		;add	sp,6

		call	sprintf_total_mbytes ; 24/12/2018

		;push	word [menu_15_segment]
		push	ds
		push	word [menu_15_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* See if drive 1 and extended partition exists */

		sub	ax,ax
		mov	[ddp_cnt],al ; 0
		mov	[ddp_pri],al ; 0
		mov	[ddp_ext],al ; 0

	;/* Find the total number of partitions, the number of normal */
	;/* partitions, and whether there is an extended partition on the */
	;/* current hard disk */

		mov	[ddp_i],ax ; 0
		jmp	short ddp_4
ddp_2:
		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;;add	ax,[ddp_i]
		;shl	al,1
		;shl	al,1
		;add	al,[ddp_i]
		;;mul	cx
		;mul	cl
		;;mov	bx,ax
		
		;mov	al,[part_table_sys_id+bx]
		;cmp	byte [part_table_sys_id+bx],5 ; EXTENTED
		cmp	al,5
		jne	short ddp_3 
		mov	byte [ddp_ext],1 ;  TRUE
ddp_3:
		inc	byte [ddp_i]
;ddp_4:
		cmp	byte [ddp_i],4
		jnb	short ddp_6
ddp_4:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;add	ax,[ddp_i]
		add	al,[ddp_i]
		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		
		mov	al,[part_table_sys_id+bx]
		;cmp	byte [part_table_sys_id+bx],0
		;je	short ddp_3
		and	al,al
		jz	short ddp_3
		inc	byte [ddp_cnt]
		;cmp	byte [part_table_sys_id+bx],1
		cmp	al,1
		je	short ddp_5
		;cmp	byte [part_table_sys_id+bx],4
		cmp	al,4
		je	short ddp_5
		;cmp	byte [part_table_sys_id+bx],6
		cmp	al,6
		jne	short ddp_2
ddp_5:
		inc	byte [ddp_pri]
		jmp	short ddp_3
ddp_6:
	;/* The partition can be deleted if the the number of normal */
	;/* partitions is greater than one or if there is only one but it is */
	;/* not the first hard disk or if there is only one normal partition */
	;/* on the first hard disk but no extended partition. */

		cmp	byte [ddp_pri],1
		jg	short ddp_10
		;jne	short ddp_7
		jne	ddp_21
		cmp	byte [cur_disk],0
		jne	short ddp_10
;ddp_7:
		;cmp	byte [ddp_pri],1
		;;je	short ddp_8
		;;jmp	short ddp_21
		;jne	short ddp_21
;ddp_8:
		;cmp	byte [cur_disk],0
		;;jne	short ddp_9
		;jne	short ddp_21
		cmp	byte [ddp_ext],0
		;je	short ddp_10
		jne	short ddp_21
;ddp_9:
		;jmp	short ddp_21
ddp_10:
		;/* Display partition number prompt */

		;push	word [menu_55_segment]
		push	ds
		push	word [menu_55_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Get the partition number from the user */

		push	word [input_col]
		push	word [input_row]
		mov	al,[ddp_cnt] ; Maximum input number
		push	ax
		mov	al,1	; Default input number	
		push	ax
		call	get_num_input
		;add	sp,8
		;mov	[ddp_input],al

		cmp	al,1Bh	; ESCape key
		jne	short ddp_11
		jmp	dos_del_break
ddp_11:
		;cbw
		;sub	ax,'0'
		sub	al,'0'
		;mov	[ddp_pnum],ax
		mov	[ddp_pnum],al

	;/* The number that the user has entered is the sorted numbering */
	;/* of the partition table. We have to retrieve the actual */
	;/* position of this partition in the partition table */

		mov	byte [ddp_j],0
		mov	byte [ddp_i],0
		mov	cl,46 ; 24/12/2018
		jmp	short ddp_13
ddp_12:
		inc	byte [ddp_i]
;ddp_13:
		cmp	byte [ddp_i],4
		;jnb	short ddp_14
		jnb	ddp_20 ; 24/12/2018 
ddp_13:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		mov	bx,[ddp_i]
		;mov	cx,ax
		;mov	al,[sort+bx]
		;cbw
		mov	dl,[sort+bx]  ; *--*
		;add	ax,cx
		add	al,dl
		;mov	cx,46
		;mul	cx
		;mov	cl,46
		mul	cl
		mov	bx,ax

		cmp	byte [part_table_sys_id+bx],0
		je	short ddp_12
		;mov	ax,[ddp_pnum]
		mov	al,[ddp_pnum]
		inc	byte [ddp_j]
		;cmp	[ddp_j],ax
		cmp	[ddp_j],al
		jne	short ddp_12
;ddp_14:
		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;shl	al,1
		;shl	al,1
		;mov	bx,[ddp_i]
		;;mov	cx,ax
		;;mov	al,[sort+bx]
		;;cbw
		;;mov	[ddp_i],ax
		;;add	ax,cx
		;mov	dl,[sort+bx]
		;add	al,dl
		;;mov	cx,46
		;;mul	cx
		;mov	cl,46
		;mul	cl
		;mov	bx,ax
		
		; i = sort[i]
		mov	[ddp_i],dl ; *--*

		;/* Verify selected partition is a primary partition */

		mov	al,[part_table_sys_id+bx]
		;cmp	byte [part_table_sys_id+bx],1
		cmp	al,1 ; DOS12
		je	short ddp_15
		;cmp	byte [part_table_sys_id+bx],4
		cmp	al,4 ; DOS16
		je	short ddp_15
		;cmp	byte [part_table_sys_id+bx],6
		cmp	al,6 ; DOSNEW
		je	short ddp_15
		jmp	ddp_20
ddp_21:
		;/* Tell user he can't do it while extended exists on drive 1 */

		;push	word [error_32_seg]
		push	ds
		push	word [error_32_off]
		jmp	ddp_18
ddp_15:
		;/* delete privious volume mismatch message */

		mov	byte [ddp_str_input],0

		;/* Get input volume label */

		;push	word [menu_41_segment]
		push	ds
		push	word [menu_41_offset]
		call	display
		;pop	bx
		;pop	bx
		
		lea	ax,[ddp_str_input]
		push	ss
		push	ax
		push	word [input_col]
		push	word [input_row]
		call	get_string_input
		;add	sp,8
		cmp	byte [ddp_str_input],1Bh ; ESC key
		jne	short ddp_16
		jmp	dos_del_break
ddp_16:
		;/* See if the volume id matches the drive */

		;lea	ax,[ddp_str_input]
		;push	ax
	
		lea	di,[ddp_str_input] ; dst

		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;add	ax,[ddp_i]
		add	al,[ddp_i]
		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	si,ax

		;add	ax,part_table_vol_label
		;push	ax
		add	si,part_table_vol_label ; src

		call	strcmp
		;pop	bx
		;pop	bx
		or	ax,ax
		jnz	short ddp_19
		
		;/* Display Y/N prompt */

		;push	word [menu_34_segment]
		push	ds
		push	word [menu_34_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Get yes/no prompt */

		push	word [input_col]
		push	word [input_row]
		mov	al,[No] ; 'N'	; Default input value/char
		push	ax
		call	get_yn_input	; Get YES ('Y'), NO ('N') input
		;add	sp,6
ddp_17:
		;mov	[ddp_input],al  ; 1 = Yes, 0 = No
		;cbw
		;cmp	ax,1Bh  ; ESC key
		cmp	al,1Bh
		je	short dos_del_break
		ja	short case_dos_del_DEF
		or	al,al
		jz	short dos_del_break ; 'N'
		dec	al
		jnz	short case_dos_del_DEF ; neither 'Y' or 'N'
		; 'Y'
case_dos_del_1:
		;/* Set Partition entry to zero */

		;push	word [ddp_i]
		; 02/01/2019
		mov	ah,[ddp_i] ; Partition entry number
		mov	al,[cur_disk]
		;push	ax
		call	remove_partition
		;pop	bx
		;pop	bx

		;/* Redisplay the partition info */

		call	table_display
		
		;/* clear the prompt off */

		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,16
		push	ax
		call	clear_screen
		;add	sp,8

		;/* Set the reboot flag */

		mov	byte [reboot_flag],1  ; TRUE

		;/* Say that you deleted it */

		;push	word [status_1_seg]
		push	ds
		push	word [status_1_off]
ddp_18:
		call	display
		;pop	bx
		;pop	bx
		call	wait_for_ESC
		jmp	short dos_del_break
ddp_19:
		;/* Tell user volume name was incorrect */

		;push	word [error_34_seg]
		push	ds
		push	word [error_34_off]
		jmp	short ddp_18
ddp_20:
		;/* Tell user he can only delete primary partition */
	
		;push	word [error_37_seg]
		push	ds
		push	word [error_37_off]
		jmp	short ddp_18
;ddp_21:
;		;push	word [error_32_seg]
;		push	ds
;		push	word [error_32_off]
;		jmp	short ddp_18
case_dos_del_DEF:
		call	internal_program_error
dos_del_break:
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen

		call	CLS

		mov	sp,bp
		pop	bp
		retn

sprintf_total_mbytes:
		; 24/12/2018

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		mov	bl,[cur_disk]
		xor	bh,bh
		shl	bx,1
		push	word [total_mbytes+bx]
		mov	ax,disk_size_format ; "%4.1d"
		push	ax
		mov	ax,insert
		push	ax
		call	sprintf
		add	sp,6
		retn

; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/*  Screen for EXT_DELETE                                                                          */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                           Delete Extended DOS Partition                        |menu_30   */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Partition Status   Type    Size in Mbytes   Percentage of Disk Used         |menu_14 # */
;/*   09|     ## #        #   #######       ####         ###%                            |menu_14 # */
;/*   10|     ## #        #   #######       ####         ###%                            |          */
;/*   11|     ## #        #   #######       ####         ###%                            |          */
;/*   12|     ## #        #   #######       ####         ###%                            |          */
;/*   13|                                                                                |          */
;/*   14|    Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes)                   |menu_15 # */
;/*   15|                                                                                |          */
;/*   16|    Warning! Data in the deleted Extended DOS partition will be lost.           |menu_31   */
;/*   17|    Do you wish to continue (Y/N).................? [N]                         |menu_31   */
;/*   18|                                                                                |          */
;/*   19|                                                                                |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */ 
;/*                                                                                                 */
;/***************************************************************************************************/

; d_menus.c (MSDOS 6.0)
;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: EXT_DELETE                                 */
;/*                                                             */
;/* DESCRIPTIVE NAME: Delete EXTENDED DOS partition             */
;/*                                                             */
;/* FUNCTION: Delete the EXTENDED DOS partition. Prompt with    */
;/*           warning first. Default entry on prompt is (N)     */
;/*                                                             */
;/* NOTES: Screen can be exited via the ESC command before      */
;/*        partition is deleted and nothing will change         */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*     |0000000000111111111122222222223333333333|              */
;/*     |0123456789012345678901234567890123456789|              */
;/*   --|----------------------------------------|              */
;/*   00|                                        |              */
;/*   01|                                        |              */
;/*   02|                                        |              */
;/*   03|                                        |              */
;/*   04|Delete EXTENDED DOS Partition           |              */
;/*   05|                                        |              */
;/*   06|Current Fixed Disk Drive: #             |              */
;/*   07|                                        |              */
;/*   08|Partition Status   Type  Start  End Size|              */
;/*   09|    #        #   #######  #### #### ####|              */
;/*   10|                                        |              */
;/*   11|                                        |              */
;/*   12|                                        |              */
;/*   13|                                        |              */
;/*   14|Total disk space is #### cylinders.     |              */
;/*   15|                                        |              */
;/*   16|                                        |              */
;/*   17|                                        |              */
;/*   18|Warning! Data in the EXTENDED DOS       |              */
;/*   19|partition will be lost. Do you wish     |              */
;/*   20|to continue.......................? [N] |              */
;/*   21|                                        |              */
;/*   22|                                        |              */
;/*   23|Press ESC to return to FDISK Options    |              */
;/*   --------------------------------------------              */
;/*                                                             */
;/* ENTRY POINTS: Ext_Delete                                    */
;/*      LINKAGE: ext_delete ()                                 */
;/*          NEAR CALL                                          */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if invalid input    */
;/*             returned to this routine                        */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      table_display                                          */
;/*      clear_screen                                           */
;/*      wait_for_ESC                                           */
;/*      get_yn_input                                           */
;/*      display                                                */
;/*      Write_Boot_Record                                      */
;/*      Internal_Program_Error                                 */
;/*      Find_Free_Space                                        */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void ext_delete()
;
;BEGIN
;
;    char   input;
;    unsigned i;
;
;    input = c(NUL);
;    /* Clear the screen */
;    clear_screen(u(0),u(0),u(24),u(79));
;
;    /* Display header */
;    display(menu_30);
;
;    /* Setup and print current disk */
;    insert[0] = cur_disk+1+'0';
;    display(menu_5);
;
;    /* print ESC prompt */
;    display(menu_11);
;
;    /* Display partition data and double check if partition exists*/
;    table_display();
;    sprintf(insert,"%4.0d",total_mbytes[cur_disk]);
;    display(menu_15);
;
;       BEGIN
;        /* See if there are still volumes */
;        if (!find_logical_drive())
;           BEGIN
;            /* Display Y/N prompt */
;            display(menu_31);
;
;            /* Get yes/no prompt */
;            input = get_yn_input(c(No),input_row,input_col);
;            switch(input)
;               BEGIN
;                case 1:
;                   BEGIN
;                    for (i=u(0); i < u(4); i++)
;                    /* Note: This will delete all occurances of EXTENDED DOS partitions found */
;                       BEGIN
;                        if (part_table[cur_disk][i].sys_id == uc(EXTENDED))
;                           BEGIN
;                            /* Set Partition entry to zero */
;                            remove_partition(cur_disk,i);
;
;                            /* Redisplay the partition info */
;                            table_display();
;
;                            /* clear the prompt off */
;                            clear_screen(u(17),u(0),u(23),u(79));
;
;                            /* Say that you deleted it */
;                            display(status_2);
;
;                            /* Set the reboot flag */
;                            reboot_flag = (FLAG)TRUE;
;                           END
;                       END
;                    wait_for_ESC();
;                    break;
;                   END
;
;                case 0:
;                    break;
;
;                case ESC:
;
;                     break;
;
;                default:
;                     internal_program_error();
;                     break;
;               END
;           END
;        else
;           BEGIN
;            /* Logical drives still exist, can't delete partition */
;            display(error_21);
;            wait_for_ESC();
;           END
;       END
;    clear_screen(u(0),u(0),u(24),u(79));
;    return;
;END

ext_delete:
		; 24/12/2018

	;%define ed_i	bp-2 ;bp-4

		push	bp
		;mov	bp,sp
		;;sub	sp,4
		;sub	sp,2

		;/* Clear the screen */

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;/* Display header */

		;push	word [menu_30_segment]
		push	ds
		push	word [menu_30_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup and print current disk */

		;mov	al,[cur_disk]
		;add	al,'1'
		;mov	[insert],al
		;;push	word [menu_5_segment]
		;push	ds
		;push	word [menu_5_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_5 ; 31/12/2018

		;/* print ESC prompt */

		;;push	word [menu_11_segment]
		;push	ds
		;push	word [menu_11_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_11 ; 31/12/2018

	;/* Display partition data and double check if partition exists*/
		
		call	table_display
		
		;;mov	al,[cur_disk]
		;;cbw
		;;mov	bx,ax
		;mov	bl,[cur_disk]
		;xor	bh,bh
		;shl	bx,1
		;push	word [total_mbytes+bx]
		;mov	ax,disk_size_format ; "%4.1d"
		;push	ax
		;mov	ax,insert
		;push	ax
		;call	sprintf
		;add	sp,6

		call	sprintf_total_mbytes ; 24/12/2018
		
		;push	word [menu_15_segment]
		push	ds
		push	word [menu_15_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* See if there are still volumes */

		call	find_logical_drive
		;or	al,al
		;jz	short ed_1
		jc	short ed_1
		;jmp	ed_7
;ed_7:
	;/* Logical drives still exist, can't delete partition */

		;push	word [error_21_seg]
		push	ds
		push	word [error_21_off]
		call	display
		;pop	bx
		;pop	bx
		jmp	short ed_8
ed_1:
		;/* Display Y/N prompt */

		;push	word [menu_31_segment]
		push	ds
		push	word [menu_31_offset]
		call	display
		;pop	bx
		;pop	bx
		
		;/* Get yes/no prompt */

		push	word [input_col]
		push	word [input_row]
		mov	al,[No] ; 'N' ; Default input
		push	ax
		call	get_yn_input
		;add	sp,6
switch_input4:
		;cbw
		;cmp	ax,1Bh
		cmp	al,1Bh ; ESCape key
		je	short case_ext_del_break
		ja	short ed_3
		or	al,al
		jz	short case_ext_del_break  ; 'N'
		dec	al
		jz	short case_ext_del_1 ; 'Y'
ed_3:
		call	internal_program_error
		jmp	short case_ext_del_break
case_ext_del_1:
		;mov	byte [ed_i],0
		xor	bp,bp ; 01/01/2019
ed_5:

	;/* Note: This will delete all occurances of EXTENDED DOS partitions found */

		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;;add	ax,[ed_i]
		;add	al,[ed_i]
		add	ax,bp ; 01/01/2019
		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax

		cmp	byte [part_table_sys_id+bx],5  ; EXTENDED partition
		jne	short ed_6

		;/* Set Partition entry to zero */

		;push	word [ed_i]
		;push	bp ; 01/01/2019
		mov	ax,bp ; 02/01/2019
		;mov	al,[cur_disk]
		;push	ax
		mov	ah,[cur_disk]
		xchg	al,ah
		call	remove_partition
		;pop	bx
		;pop	bx

		;/* Redisplay the partition info */

		call	table_display

		;/* clear the prompt off */
		
		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,17
		push	ax
		call	clear_screen
		;add	sp,8

		;/* Say that you deleted it */

		;push	word [status_2_seg]
		push	ds
		push	word [status_2_off]
		call	display
		;pop	bx
		;pop	bx

		;/* Set the reboot flag */

		mov	byte [reboot_flag],1 ; TRUE
ed_6:
		;inc	byte [ed_i]
		inc	bp ; 01/01/2019
		;cmp	byte [ed_i],4
		cmp	bp,4
		jb	short ed_5
		;jmp	short ed_8
;ed_7:
;		;push	word [error_21_seg]
;		push	ds
;		push	word [error_21_off]
;		call	display
;		;pop	bx
;		;pop	bx
ed_8:
		call	wait_for_ESC

case_ext_del_break:
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen

		call	CLS		

		;mov	sp,bp
		pop	bp
		retn

; fdisk.msg (MSDOS 6.0)
;/******************************************************************************************************/
;/*  Screen for VOL_DELETE                                                                             */
;/*                                                                                                    */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|             */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|             */
;/*   --|--------------------------------------------------------------------------------|             */
;/*   00|                                                                                |             */
;/*   01|            Delete Logical DOS Drive(s) in the Extended DOS Partition           |menu_32      */
;/*   02|                                                                                |             */
;/*   03|Drv Volume Label  MBytes  System  Usage  Drv Volume Label  MBytes  System  Usage|menu_19/20 # */
;/*   04|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   05|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   06|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   07|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   08|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   09|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   10|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   11|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   12|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   13|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   14|##  #############  ####  ########  ###%  ##  #############  ####  ########  ###%|             */
;/*   15|##  #############  ####  ########  ###%                                         |             */
;/*   16|                                                                                |             */
;/*   17|    Total Extended DOS Partition size is #### Mbytes (1 Mbyte = 1048576 bytes)  |menu_21      */
;/*   18|                                                                                |             */
;/*   19|    Warning! Data in a deleted Logical DOS Drive will be lost.                  |menu_33      */
;/*   20|    What drive do you want to delete...........................? [ ]            |menu_33      */
;/*   21|    Enter Volume Label.............................? [             ]            |menu_41      */
;/*   22|    Are you sure (Y/N).............................? [N]                        |menu_34      */
;/*   23|                                                                                |             */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11      */
;/*   ------------------------------------------------------------------------------------             */
;/*                                                                                                    */
;/******************************************************************************************************/

; d_menus.c (MSDOS 6.0)
;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: VOL_DELETE                                 */
;/*                                                             */
;/* DESCRIPTIVE NAME: Delete DOS disk Volume                    */
;/*                                                             */
;/* FUNCTION: Prompts user to delete a DOS disk volume          */
;/*                                                             */
;/* NOTES: Screen can be exited via the ESC command before      */
;/*        partition is deleted and nothing will change         */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*     |0000000000111111111122222222223333333333|              */
;/*     |0123456789012345678901234567890123456789|              */
;/*   --|----------------------------------------|              */
;/*   00|Delete DOS Disk Volume                  |              */
;/*   01|                                        |              */
;/*   02|Vol Start End  Size                     |              */
;/*   03| #  ####  #### ####                     |              */
;/*   04|                                        |              */
;/*   05|                                        |              */
;/*   06|                                        |              */
;/*   07|                                        |              */
;/*   08|                                        |              */
;/*   09|                                        |              */
;/*   10|                                        |              */
;/*   11|                                        |              */
;/*   12|                                        |              */
;/*   13|                                        |              */
;/*   14|                                        |              */
;/*   15|                                        |              */
;/*   16|Total partition size is #### cylinders. |              */
;/*   17|                                        |              */
;/*   18|Warning! Data in the DOS disk volume    |              */
;/*   19|will be lost. What volume do you wish   |              */
;/*   20|to delete.........................? [#] |              */
;/*   21|                                        |              */
;/*   22|Are you sure......................? [N] |              */
;/*   23|Press ESC to return to FDISK Options    |              */
;/*   --------------------------------------------              */
;/*                                                             */
;/* ENTRY POINTS: Vol_Delete                                    */
;/*      LINKAGE: vol_delete ()                                 */
;/*          NEAR CALL                                          */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if invalid input    */
;/*             returned to this routine                        */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      display                                                */
;/*      volume_display                                         */
;/*      get_num_input                                          */
;/*      wait_for_ESC                                           */
;/*      get_yn_input                                           */
;/*      Write_Boot_Record                                      */
;/*      Find_Free_Space                                        */
;/*      Internal_Program_Error                                 */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void volume_delete()
;
;BEGIN
;
;    char   input;
;    char   drive_input;
;    char   high_drive;
;    char   low_drive;
;    char   error_low_drive;
;    char   error_high_drive;
;    char   drives_reassigned;
;    int    list_index;
;    int    i;
;    int    j;
;    int    point;
;    FLAG   delete_drive;
;    unsigned char   drive_list[23][2];
;    int    column;
;    int    row;
;    FLAG   drives_exist;
;    FLAG   vol_matches;
;    char   temp;
;    unsigned char drive_temp;
;    char far *s;
;    unsigned char   string_input[12];
;
;    input = c(NUL);
;    string_input[0] = uc(NUL);
;
;    /* Clear screen */
;    clear_screen(u(0),u(0),u(24),u(79));
;
;    /* Display header */
;    display(menu_32);
;
;    /* print ESC prompt */
;    display(menu_11);
;
;    /* Display logical drives and get the highest drive letter assigned*/
;    high_drive = volume_display();
;
;    /* Get the first avail drive letter to be deleted */
;    low_drive = (high_drive - get_num_logical_dos_drives()+1);
;
;    if (low_drive <= c('Z'))
;    {
;    if (high_drive > c('Z'))
;        high_drive = c('Z');
;
;    temp = low_drive;
;
;    /* Initialize array of drive letters that exist at this point */
;    for (i=(int)0; i < (int)23; i++)
;        BEGIN
;        /* See if we've exceeded the drive letter range */
;        if (temp <= high_drive)
;            BEGIN
;            /* Put in drive letter */
;            drive_list[i][0] = ((unsigned char)(temp));
;            /* Initialize the offsets into the array to something harmless */
;            drive_list[i][1] = uc(INVALID);
;            END
;        else
;            BEGIN
;            /* No drive there, put in NUL */
;            drive_list[i][0] = uc(NUL);
;            drive_list[i][1] = uc(INVALID);
;            END
;
;        /* Check for next drive */
;        temp++;
;        END
;
;    /* Set up partition size message */
;    sprintf(insert,"%4.0d",get_partition_size( uc(EXTENDED) ) );
;    display(menu_21);
;
;    /* Assume no drives deleted */
;    drives_reassigned = (FLAG)FALSE;
;
;    /* Loop until ESC or all deleted */
;    while (input != c(ESC))
;        BEGIN
;
;        /* Are there any drives left?*/
;        drives_exist = (FLAG)FALSE;
;        error_low_drive = ((char)(NUL));
;        error_high_drive = ((char)(NUL));
;
;        for (i=(int)0;i < (int)23; i++)
;            BEGIN
;            drive_temp = drive_list[i][0];
;            if ((drive_temp != uc(NUL)) && (drive_list[i][1] != uc(DELETED)))
;                BEGIN
;                drives_exist = (FLAG)TRUE;
;
;                /* Find last existing drive letter */
;                error_high_drive = ((char)(drive_temp));
;
;                /* See if we've found the first drive yet */
;                if (error_low_drive == ((char)(NUL)))
;                    error_low_drive = ((char)(drive_temp));
;                END
;            END
;
;        /* If there are drives, go let user try to delete them */
;        if (drives_exist)
;            BEGIN
;
;            /* Get input until given a correct drive */
;            valid_input = (FLAG)FALSE;
;            while ( (!valid_input) && (input != c(ESC)) )
;                BEGIN
;
;                /* Prompt for input */
;                display(menu_33);
;
;                /* Get input between first and highest drive letters */
;                clear_screen( u(21), u(0), u(21), u(79) );
;                input = get_alpha_input(low_drive,high_drive,input_row,input_col,error_low_drive,error_high_drive);
;                drive_input = input;
;
;                /* See if it has been deleted already or ESC pressed */
;                drives_exist = FALSE;
;                for (i=(int)0;i < (int)23; i++) 
;                    BEGIN
;                    if (drive_list[i][0] == ((unsigned char)(drive_input)) &&
;                       (drive_list[i][1] != ((unsigned char) DELETED)))
;                        BEGIN
;                        drives_exist = TRUE;
;                        list_index = i;
;                        END
;                    if (ext_table[cur_disk][i].drive_letter == c(drive_input) )
;                        point = i;
;                    END
;                END
;
;            /* Input volume string to confirm delete */
;            vol_matches = FALSE;
;            if (input != c(ESC))
;                BEGIN
;                if (drives_exist)
;                    BEGIN
;                    /* delete privious volume mismatch message */
;                    string_input[0] = uc(NUL);
;                    clear_screen( u(22), u(0), u(23), u(79) );
;                    /* Get input volume label */
;                    display(menu_41);
;                    get_string_input(input_row,input_col,string_input);
;                    if (string_input[0] == uc(ESC)) input = c(ESC);
;
;                    /* See if the volume id matches the selected drive */
;                    if (strcmp(ext_table[cur_disk][point].vol_label,string_input) == (int)ZERO)
;                           vol_matches = TRUE;
;                    else if (input != c(ESC)) display(error_34);
;                    END
;                 else
;                    BEGIN
;                    /* Tell user the drive has already been deleted */
;                    insert[0] = dos_upper(drive_input);
;                    insert[1] = c(DRIVE_INDICATOR);
;                    clear_screen( u(21), u(0), u(22), u(79) );
;                    display(error_29);
;                    END
;                END
;
;                /* If it is a valid drive indicate that the input was ok */
;                if ( (input != c(ESC)) && (drives_exist) && (vol_matches) )
;                    BEGIN
;                    valid_input = TRUE;
;
;                    /* At this point we have a valid drive letter to delete */
;
;                    /* Get the offset into the array for the drive to be deleted */
;                    delete_drive = find_ext_drive(drive_input - low_drive);
;
;                    /* Got a drive letter - prompt are you sure */
;                    display(menu_34);
;
;                    /* Get Y/N input, default is NO */
;                    input = get_yn_input(c(No),input_row,input_col);
;
;                    /* Clear everything out on screen in prompt area */
;                    clear_screen(u(23),u(0),u(23),u(79));
;
;                    /* Go handle the delete */
;                    switch(input)
;                        BEGIN
;                        case 1:
;                            BEGIN
;                            /* Go ahead and mark it deleted in list array */
;
;                            /* Throw up a flag to indicate we need to delete this one for real later */
;                            /* This is because if we change the ext_table array now, we lose the ability */
;                            /* to match up drive letters with locations, or at least it become more */
;                            /* complicated than I felt like figuring out, so mark it now and do it later */
;                            drive_list[list_index][1] = (unsigned char)DELETED;
;
;                            drives_reassigned = TRUE;
;
;                            /* Put prompt up on screen */
;                            for (i=(int)0; i < (int)23; i++)
;                                BEGIN
;                                /* See if drive deleted */
;                                if (drive_list[i][1] == uc(DELETED))
;                                    BEGIN
;                                    /* Wipe out the drive info and print deleted message */
;                                    /* See what column it is in */
;                                    if (i < (int)12)
;                                        BEGIN
;                                        column = (int)4;
;                                        row = (int)(4 + i - (int)0);
;                                        clear_screen( (unsigned)row, (unsigned)column,
;                                                      (unsigned)row, (unsigned)39 );
;                                        END
;                                    else
;                                        BEGIN
;                                        column = (int)45;
;                                        row = (int)(4 + i - (int)12);
;                                        clear_screen( (unsigned)row, (unsigned)column,
;                                                      (unsigned)row, (unsigned)79 );
;                                        END
;
;                                    /* Put the start row,col of message in the message string */
;                                    s=status_3;
;                                    s++;
;                                    *s++ = ((char)(row/10))+'0';
;                                    *s++ = ((char)(row%10))+'0';
;                                    *s++ = ((char)(column/10))+'0';
;                                    *s = ((char)(column%10))+'0';
;                                    display(status_3);
;                                    END
;                                END
;                            /* Set the reboot flag */
;                            reboot_flag = TRUE;
;                            clear_screen( u(21), u(0), u(23), u(79) );
;                            break;
;                            END
;
;                        case ESC:
;                        case 0:
;                            clear_screen( u(21), u(0), u(23), u(79) );
;                            break;
;
;                        default:
;                            internal_program_error();
;                            break;
;                        END
;                    END
;            END
;         else     /* drives do not exist! */
;            BEGIN
;            /* No more logical drives to delete */
;            clear_screen(u(16),u(0),u(21),u(79));
;            display(error_22);
;            input = wait_for_ESC();
;            END
;        END /* while input != esc */
;
;    if (drives_reassigned)
;        BEGIN
;        /* If anything got deleted, lets go do it for real */
;        for (i=(int)0; i < (int)23;i++)
;            BEGIN
;            if (drive_list[i][1] == uc(DELETED))
;                BEGIN
;                for (j=(int)0; j < (int)23;j++)
;                    BEGIN
;                    if (drive_list[i][0] == ext_table[cur_disk][j].drive_letter)
;                        BEGIN
;                        /* Zero sys id and show it changed */
;                        remove_volume(cur_disk,i);
;                        END
;                    END
;                END
;            END
;
;        /* Show new drive letters */
;        volume_display();
;
;        /* Say that drive letters changed */
;        clear_screen(u(16),u(0),u(23),u(79));
;        display(status_10);
;        wait_for_ESC();
;        END
;    }
;    else     /* drives do not exist! */
;    {
;        /* No more logical drives to delete */
;        clear_screen(u(16),u(0),u(21),u(79));
;        display(error_36);
;        wait_for_ESC();
;    }
;    clear_screen(u(0),u(0),u(24),u(79));
;
;    return;
;
;END

volume_delete:
		; 04/01/2018
		; 03/01/2019
		; 24/12/2018

	%define vdel_drv_temp	  bp-92 ;bp-94	;bp-98
	;%define vdel_column	  bp-92	;bp-96
	%define vdel_del_drive	  bp-90	;bp-94
	%define vdel_low_drive	  bp-88	;bp-92
	%define vdel_j		  bp-86	;bp-90
	%define vdel_point	  bp-84	;bp-88
	%define vdel_drive_input  bp-82	;bp-86
	%define vdel_high_drive	  bp-80	;bp-84
	%define vdel_i		  bp-78	;bp-82
	%define vdel_drives_exist bp-76	;bp-80
	%define vdel_row	  bp-74	;bp-78
	;%define vdel_temp	  bp-72	;bp-76
	%define vdel_column	  bp-72	;bp-96
	%define vdel_string_input bp-70	;bp-74
	%define vdel_drive_list	  bp-58	;bp-62
	;%define vdel_drive_list1 bp-57	;bp-61
	%define vdel_vol_matches  bp-12	;bp-16
	%define error_low_drive	  bp-10	;bp-14
	%define vdel_list_index	  bp-8	;bp-12
	;%define vdel_s		        ;bp-10
	%define error_high_drive  bp-6	;bp-6
	%define drives_reassigned bp-4	;bp-4
	%define vdel_input	  bp-2	;bp-2

		push	bp
		mov	bp,sp
		;sub	sp,98
		;sub	sp,94 ; 31/12/2018
		sub	sp,92 ; 04/01/2019

		;push	si ;*

		mov	byte [vdel_input],0
		mov	byte [vdel_string_input],0

		;/* Clear screen */
		
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS ; 03/01/2019

		;/* Display header */

		;push	word [menu_32_segment]
		push	ds ; 02/01/2019
		push	word [menu_32_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* print ESC prompt */

		;;push	word [menu_11_segment]
		;push	ds
		;push	word [menu_11_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_11 ; 31/12/2018

	;/* Display logical drives and get the highest drive letter assigned */

		call	volume_display
		mov	[vdel_high_drive],al

		;/* Get the first avail drive letter to be deleted */

		call	get_num_logical_dos_drives
		sub	al,[vdel_high_drive]
		neg	al
		inc	al
		mov	[vdel_low_drive],al

		cmp	al,'Z'
		jle	short vdel_1
		jmp	vdel_47
vdel_1:
		cmp	byte [vdel_high_drive],'Z'
		jle	short vdel_2
		mov	byte [vdel_high_drive],'Z'
vdel_2:
		;mov	al,[vdel_low_drive] ; 31/12/2018
		;mov	[vdel_temp],al ; 03/01/2019

	;/* Initialize array of drive letters that exist at this point */

		;mov	word [vdel_i],0
		; 03/01/2019
		xor	si,si ; 0
		mov	[vdel_i],si ; 0
		jmp	short vdel_5
vdel_3:
		;/* No drive there, put in NUL */

		;mov	si,[vdel_i] ; 31/12/2018
		;shl	si,1
		mov	byte [si+vdel_drive_list],0
vdel_4:
	;/* Initialize the offsets into the array to something harmless */

		mov	byte [si+vdel_drive_list+1],0FFh ; INVALID

		;/* Check for next drive */

		;inc	byte [vdel_temp] ; 03/01/2019
		inc	al ; 03/01/2019
		
		inc	byte [vdel_i]
;vdel_5:
		cmp	byte [vdel_i],23
		jnb	short vdel_6

		;/* See if we've exceeded the drive letter range */

		;mov	al,[vdel_temp] ; 03/01/2019

		; 31/12/2018
		mov	si,[vdel_i]
		shl	si,1

vdel_5: 	; 03/01/2019
		cmp	[vdel_high_drive],al ; [vdel_temp]
		jb	short vdel_3
		
		;/* Put in drive letter */

		;mov	si,[vdel_i]
		;shl	si,1

		mov	[si+vdel_drive_list],al
		jmp	short vdel_4
vdel_6:
		;/* Set up partition size message */

		;mov	al,5
		;;push	ax
		;mov	dh,5
		;call	get_partition_size
		;;pop	bx
		;push	ax
		;mov	ax,ld_p_size_format ; "%4.1d"
		;push	ax
		;mov	ax,insert
		;push	ax
		;call	sprintf
		;add	sp,6
		;	
		;;push	word [menu_21_segment]
		;push	ds
		;push	word [menu_21_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_ext_partition_size ; 31/12/2018

		;/* Assume no drives deleted */

		mov	byte [drives_reassigned],0 ; FALSE
		;jmp	vdel_39 ; 03/01/2019

		;/* while input != esc */
vdel_7:		
		;/* Are there any drives left?*/
	
		sub	al,al ; 0
		mov	[vdel_drives_exist],al ; 0
		mov	[error_low_drive],al ; 0
		mov	[error_high_drive],al ; 0
		mov	[vdel_i],al ; 0
vdel_8:
		mov	si,[vdel_i]
		shl	si,1
		mov	al,[si+vdel_drive_list]
		mov	[vdel_drv_temp],al

		or	al,al
		jz	short vdel_9
		cmp	byte [si+vdel_drive_list+1],0FEh ; DELETED
		je	short vdel_9
		mov	byte [vdel_drives_exist],1 ; TRUE

		;/* Find last existing drive letter */

		mov	[error_high_drive],al

		;/* See if we've found the first drive yet */

		cmp	byte [error_low_drive],0
		jne	short vdel_9
		mov	[error_low_drive],al
vdel_9:
		inc	byte [vdel_i]
		cmp	byte [vdel_i],23
		jb	short vdel_8

		;/* If there are drives, go let user try to delete them */

		cmp	byte [vdel_drives_exist],0
		jne	short vdel_10
		jmp	vdel_38

		;/* Get input until given a correct drive */
vdel_10:
		mov	byte [valid_input],0
vdel_11:
		cmp	byte [vdel_input],1Bh ; ESCape
		jne	short vdel_12
		jmp	vdel_16
	
		;/* Prompt for input */
vdel_12:
		;push	word [menu_33_segment]
		push	ds
		push	word [menu_33_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Get input between first and highest drive letters */

		mov	ax,79
		push	ax
		mov	ax,21
		push	ax
		sub	cx,cx
		push	cx
		push	ax
		call	clear_screen
		;add	sp,8

		mov	al,[error_high_drive]
		push	ax
		mov	al,[error_low_drive]
		push	ax
		push	word [input_col]
		push	word [input_row]
		mov	al,[vdel_high_drive]
		push	ax
		mov	al,[vdel_low_drive]
		push	ax
		call	get_alpha_input
		;add	sp,12

		mov	[vdel_input],al
		mov	[vdel_drive_input],al
		
		;/* See if it has been deleted already or ESC pressed */

		;mov	byte [vdel_drives_exist],0
		;mov	byte [vdel_i],0

		xor	al,al ; 0
		mov	[vdel_drives_exist],al
		mov	[vdel_i],al
vdel_13:
		mov	al,[vdel_drive_input]
		mov	si,[vdel_i]
		mov	dx,si ; 03/01/2019
		shl	si,1
		cmp	[si+vdel_drive_list],al
		jne	short vdel_14
		cmp	byte [si+vdel_drive_list+1],0FEh ; DELETED
		je	short vdel_14
		mov	byte [vdel_drives_exist],1 ; TRUE
		;mov	ax,[vdel_i]
		;mov	[vdel_list_index],ax
		;mov	dx,[vdel_i]
		mov	[vdel_list_index],dx
vdel_14:
		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]
		;add	ax,[vdel_i]
		;add	al,[vdel_i]
		add	al,dl ; 03/01/2019
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		mov	al,[vdel_drive_input]
		cmp	byte [ext_table_drive_letter+bx],al
		jne	short vdel_15
		;mov	ax,[vdel_i]
		;mov	[vdel_point],ax
		mov	[vdel_point],dx ; [vdel_i]
vdel_15:
		inc	byte [vdel_i]
		cmp	byte [vdel_i],23
		jl	short vdel_13
		cmp	byte [valid_input],0
		jne	short vdel_16
		jmp	vdel_11

		;/* Input volume string to confirm delete */
vdel_16:
		mov	byte [vdel_vol_matches],0 ; FALSE
		cmp	byte [vdel_input],1Bh ; ESC
		jne	short vdel_17
		;jmp	vdel_22
		jmp	vdel_40 ; 31/12/2018
vdel_17:
		cmp	byte [vdel_drives_exist],0
		je	short vdel_20

		;/* delete previous volume mismatch message */

		mov	byte [vdel_string_input],0
		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,22
		push	ax
		call	clear_screen
		;add	sp,8

		;/* Get input volume label */

		;push	word [menu_41_segment]
		push	ds
		push	word [menu_41_offset]
		call	display
		;pop	bx
		;pop	bx
		
		lea	ax,[vdel_string_input]
		push	ss
		push	ax
		push	word [input_col]
		push	word [input_row]
		call	get_string_input
		;add	sp,8
		cmp	byte [vdel_string_input],1Bh ; ESC
		jne	short vdel_18  ; [vdel_drives_exist] > 0

		;mov	byte [vdel_input],1Bh
		; 31/12/2018 (modification)
		jmp	vdel_40

		;/* See if the volume id matches the selected drive */
vdel_18:
		;lea	ax,[vdel_string_input]
		;push	ax

		lea	di,[vdel_string_input] ; dst

		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]
		;add	ax,[vdel_point]
		add	al,[vdel_point]
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		add	ax,ext_table_vol_label
		;push	ax

		mov	si,ax  ;src

		call	strcmp
		;pop	bx
		;pop	bx
		or	ax,ax
		jnz	short vdel_19

		mov	byte [vdel_vol_matches],1
		;jmp	short vdel_22

		; [vdel_drives_exist] > 0
		;jmp	short vdel_23 ; 31/12/2018
		jmp	short vdel_25
vdel_19:
		;cmp	byte [vdel_input],1Bh
		;je	short vdel_22

		;push	word [error_34_seg]
		push	ds
		push	word [error_34_off]
		;jmp	short vdel_21

		; 31/12/2018
		call	display
		;pop	bx
		;pop	bx
		jmp	vdel_7

vdel_20:
		;/* Tell user the drive has already been deleted */

		mov	al,[vdel_drive_input]
		;push	ax
		call	dos_upper
		;pop	bx
		mov	[insert],al
		mov	byte [insert+1],':' ; 3Ah
		
		mov	ax,79
		push	ax
		mov	ax,22
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,21
		push	ax
		call	clear_screen
		;add	sp,8

		;push	word [error_29_seg]
		push	ds
		push	word [error_29_off]
vdel_21:
		call	display
		;pop	bx
		;pop	bx
vdel_22:
		;cmp	[vdel_input],1Bh ; ESC
		;jne	short vdel_23
		
		;;jmp	vdel_39
		;jmp	vdel_40
vdel_23:
		;cmp	[vdel_drives_exist], 0
		;je	short vdel_24
		;cmp	[vdel_vol_matches], 0
		;jne	short vdel_25
vdel_24:
		;jmp	vdel_39
		jmp	vdel_7

	;/* At this point we have a valid drive letter to delete */

	;/* Get the offset into the array for the drive to be deleted */
vdel_25:
		mov	byte [valid_input],1 ; TRUE
		;mov	al,[vdel_drive_input]
		;sub	al,[vdel_low_drive]
		mov	dl,[vdel_drive_input]
		sub	dl,[vdel_low_drive]
		;push	ax
		call	find_ext_drive
		;pop	bx
		;mov	[vdel_del_drive],al
		mov	[vdel_del_drive],cl

		;/* Got a drive letter - prompt are you sure */

		;push	word [menu_34_segment]
		push	ds
		push	word [menu_34_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Get Y/N input, default is NO */

		push	word [input_col]
		push	word [input_row]
		mov	al,[No]
		push	ax
		call	get_yn_input
		;add	sp,6
		mov	[vdel_input],al
	
		;/* Clear everything out on screen in prompt area */

		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	cx,cx
		push	cx
		push	ax
		call	clear_screen
		;add	sp,8
switch_input5:
		;/* Go handle the delete */

		mov	al,[vdel_input]
		;cbw
		;cmp	ax,1Bh
		cmp	al,1Bh ; ESC key
		jne	short vdel_27
		jmp	case_vol_del_break ; case ESC
vdel_27:
		ja	short case_vol_del_DEF
		or	al,al
		jnz	short vdel_28
		jmp	case_vol_del_break ; Case 0
vdel_28:
		dec	al
		jz	short case_vol_del_1 ; 'Y'
case_vol_del_DEF:
		call	internal_program_error
		;jmp	vdel_39
		jmp	vdel_7 ; 02/01/2019

		;/* Go ahead and mark it deleted in list array */

	;/* Throw up a flag to indicate we need to delete this one for real later */
	;/* This is because if we change the ext_table array now, we lose the ability */
	;/* to match up drive letters with locations, or at least it become more */
	;/* complicated than I felt like figuring out, so mark it now and do it later */

case_vol_del_1:
		mov	si,[vdel_list_index]
		shl	si,1
		mov	byte [si+vdel_drive_list+1],0FEh ; DELETED
		mov	byte [drives_reassigned],1 ; TRUE
		mov	byte [vdel_i],0
		jmp	short vdel_34
vdel_31:
		mov	word [vdel_column],45
		mov	ax,[vdel_i]
		;sub	ax,8
		sub	al,8 ; 12-4 ; 04/01/2019
		mov	[vdel_row],ax
		mov	cx,79
		push	cx
		push	ax
		mov	cx,45
vdel_32:
		push	cx
		push	ax
		call	clear_screen
		;add	sp,8

		;/* Put the start row,col of message in the message string */

		;mov	ax,[vdel_row]
		;mov	cx,10
		;cwd
		;idiv	cx
		;add	al,'0'
		;les	bx,[status_3_off]
		;inc	bx
		;mov	[vdel_s],bx
		;mov	[vdel_s+2],es
		;mov	[es:bx],al

		; 26/12/2018
		mov	bx,[status_3_off]
		inc	bx
		mov	ax,[vdel_row]
		mov	cl,10
		div	cl
		add	ax,'00'
		mov	[bx],ax
		inc	bx		

		;mov	ax,[vdel_row]
		;cwd
		;;idiv	cx
		;div	cx
		;add	dl,'0'
		;inc	word [vdel_s]
		;;les	bx,[vdel_s]
		;mov	bx,[vdel_s]
		;;mov	es:[bx],dl
		;mov	[bx],dl

		;mov	ax,[vdel_column]
		;cwd
		;idiv	cx
		;add	al,'0'
		;inc	bx
		;mov	[vdel_s],bx
		;mov	[vdel_s+2],es
		;mov	[es:bx],al
		
		; 26/12/2018
		mov	ax,[vdel_column]
		div	cl ; 10
		add	ax,'00'
		inc	bx
		mov	[bx],ax

		;mov	ax,[vdel_column]
		;cwd
		;idiv	cx
		;add	dl,'0'
		;inc	bx
		;mov	[vdel_s],bx
		;mov	[vdel_s+2],es
		;mov	[es:bx],dl
		
		;push	word [status_3_seg]
		push	ds
		push	word [status_3_off]
		call	display
		;pop	bx
		;pop	bx
vdel_33:
		inc	byte [vdel_i]

		;/* Put prompt up on screen */
;vdel_34:
		cmp	byte [vdel_i],23
		jge	short vdel_36
vdel_34:
		mov	si,[vdel_i]
		shl	si,1
		cmp	byte [si+vdel_drive_list+1],0FEh ; DELETED
		jne	short vdel_33

		;/* Wipe out the drive info and print deleted message */
		;/* See what column it is in */

		cmp	byte [vdel_i],12
		;jl	short vdel_35
		;jmp	short vdel_31
		jnb	short vdel_31	
vdel_35:
		mov	word [vdel_column],4
		mov	ax,[vdel_i]
		;add	ax,4
		add	al,4
		mov	[vdel_row],ax
		mov	cx,39
		push	cx
		push	ax
		;mov	cx,4
		mov	cl,4
		jmp	short vdel_32

		;/* Set the reboot flag */
vdel_36:
		mov	byte [reboot_flag],1

case_vol_del_break:
		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,21
		push	ax
		call	clear_screen
		;add	sp,8
		jmp	short vdel_39

		;/* No more logical drives to delete */
vdel_38:
		mov	ax,79
		push	ax
		mov	ax,21
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,16
		push	ax
		call	clear_screen
		;add	sp,8
		
		;push	word [error_22_seg]
		push	ds
		push	word [error_22_off]
		call	display
		;pop	bx
		;pop	bx

		call	wait_for_ESC
		mov	[vdel_input],al

		;/* Loop until ESC or all deleted */
vdel_39:
		cmp	byte [vdel_input],1Bh  ; ESC
		je	short vdel_40
		jmp	vdel_7
vdel_40:
		cmp	byte [drives_reassigned],0
		jne	short vol_del_for_1
		
		;/* drives do not exist! */		
		
		jmp	vdel_49
vol_del_for_1:
		;/* If anything got deleted, lets go do it for real */
		
		mov	byte [vdel_i],0

vol_del_for_1_next:
		mov	si,[vdel_i]
		shl	si,1
		cmp	byte [si+vdel_drive_list+1],0FEh ; DELETED
		jne	short vol_del_for_1_condition

vol_del_for_2:
		mov	byte [vdel_j],0
vol_del_for_2_next:
		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]
		;add	ax,[vdel_j]
		add	al,[vdel_j] ; 04/01/2019
		;mov	cx,46
		mov	cl,46
		;imul	cx
		mul	cl
		mov	bx,ax
		mov	al,[ext_table_drive_letter+bx]
		;cbw
		mov	si,[vdel_i]
		shl	si,1
		mov	cl,[si+vdel_drive_list]
		;sub	ch,ch
		;cmp	ax,cx
		cmp	al,cl
		jne	short vol_del_for_2_condition
		
		;/* Zero sys id and show it changed */

		;push	word [vdel_i]
		mov	cl,[vdel_i] ; Partition entry number
		mov	al,[cur_disk]
		;push	ax
		call	remove_volume
		;pop	bx
		;pop	bx

vol_del_for_2_condition:
		inc	byte [vdel_j]

		cmp	byte [vdel_j],23
		jl	short vol_del_for_2_next
vol_del_for_1_condition:
		inc	byte [vdel_i]
		cmp	byte [vdel_i],23
		jl	short vol_del_for_1_next

		;/* Show new drive letters */

		call	volume_display

		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,16
		push	ax
		call	clear_screen
		;add	sp,8

		;/* Say that drive letters changed */

		; 04/01/2019

		;push	word [status_10_seg]
		push	ds
		push	word [status_10_off]
		jmp	short vdel_48
vdel_47:
		mov	ax,79
		push	ax
		mov	ax,21
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,16
		push	ax
		call	clear_screen
		;add	sp,8

		;push	word [error_36_seg]
		push	ds
		push	word [error_36_off]
vdel_48:
		call	display
		;pop	bx
		;pop	bx
		
		call	wait_for_ESC
vdel_49:
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;pop	si *

		mov	sp,bp
		pop	bp
		retn

; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/*  Screen for NON_DOS_DELETE                                                                      */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                            Delete Non-DOS Partition                            |menu_58   */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Partition Status   Type    Size in Mbytes   Percentage of Disk Used         |menu_14 # */
;/*   09|     ## #        #   #######       ####         ###%                            |menu_14 # */
;/*   10|     ## #        #   #######       ####         ###%                            |          */
;/*   11|     ## #        #   #######       ####         ###%                            |          */
;/*   12|     ## #        #   #######       ####         ###%                            |          */
;/*   13|                                                                                |          */
;/*   14|    Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes)                   |menu_15 # */
;/*   15|                                                                                |          */
;/*   16|    Warning! Data in the deleted Non-DOS Partition will be lost.                |menu_59   */
;/*   17|    What Non-DOS partition do you want to delete..? [ ]                         |          */
;/*   18|                                                                                |          */
;/*   19|    Do you wish to continue (Y/N).................? [N]                         |menu_56   */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */
;/*                                                                                                 */
;/***************************************************************************************************/

; d_menus.c (MSDOS 6.0)
;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: NON_DOS_DELETE                             */
;/*                                                             */
;/* DESCRIPTIVE NAME: Delete Non-DOS partition                  */
;/*                                                             */
;/* FUNCTION: Delete the Non-DOS partition. Prompt user with    */
;/*           warning first. Default entry on prompt is (N)     */
;/*                                                             */
;/* NOTES: Screen can be exited via the ESC command before      */
;/*        partition is deleted and nothing will change         */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*     |0000000000111111111122222222223333333333|              */
;/*     |0123456789012345678901234567890123456789|              */
;/*   --|----------------------------------------|              */
;/*   00|                                        |              */
;/*   01|                                        |              */
;/*   02|                                        |              */
;/*   03|                                        |              */
;/*   04|Delete Non-DOS Partition                |              */
;/*   05|                                        |              */
;/*   06|Current Fixed Disk Drive: #             |              */
;/*   07|                                        |              */
;/*   08|Partition Status   Type  Start  End Size|              */
;/*   09|    #        #   #######  #### #### ####|              */
;/*   10|                                        |              */
;/*   11|                                        |              */
;/*   12|                                        |              */
;/*   13|                                        |              */
;/*   14|Total disk space is #### cylinders.     |              */
;/*   15|                                        |              */
;/*   16|                                        |              */
;/*   17|                                        |              */
;/*   18|Warning! Data in the Non-DOS partition  |              */
;/*   19|will be lost. Do you wish to            |              */
;/*   20|continue..........................? [N] |              */
;/*   21|                                        |              */
;/*   22|                                        |              */
;/*   23|Press ESC to return to FDISK Options    |              */
;/*   --------------------------------------------              */
;/*                                                             */
;/* ENTRY POINTS: Non_DOS_Delete                                */
;/*      LINKAGE: non_dos_delete                                */
;/*          NEAR CALL                                          */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if invalid input    */
;/*             returned to this level                          */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES                                                  */
;/*      table_display                                          */
;/*      clear_screen                                           */
;/*      wait_for_ESC                                           */
;/*      get_yn_input                                           */
;/*      display                                                */
;/*      Write_Boot_Record                                      */
;/*      find_part_free_space                                   */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/
                                                                   
;/*  */                                                              
;void non_dos_delete()                                                
;                                                                     
;BEGIN                                                                
;                                                                     
;    char input;                                                      
;    unsigned i;                                                      
;    int     j;                                                       
;    int     cnt;                                                     
;    int     pnum;                                                    
;                                                                     
;    input = c(NUL);                                                  
;    /* clear screen */                                               
;    clear_screen(u(0),u(0),u(24),u(79));                             
;                                                                     
;    /* Display header */                                             
;    display(menu_58);                                                
;                                                                     
;    /* Setup and print current disk */                               
;    insert[0] = cur_disk+1+'0';                                      
;    display(menu_5);                                                 
;                                                                     
;    /* print ESC prompt */                                           
;    display(menu_11);                                                
;                                                                     
;    /* Display partition data and double check if partition exists*/ 
;    if (table_display())                                             
;       BEGIN                                                         
;                                                                     
;        sprintf(insert,"%4.0d",total_mbytes[cur_disk]);              
;        display(menu_15);                                            
;                                                                     
;        /* count the number of partitions */                         
;        cnt = 0;                                                     
;        for (i = u(0); i < u(4); i++)                                
;            if (part_table[cur_disk][i].sys_id != uc(0))             
;                cnt++;                                               
;                                                                     
;        /* Display partition number prompt */                        
;        display(menu_59);                                            
;                                                                     
;        /* Get the partition number from the user */                 
;        input = get_num_input(c(1),c(cnt),input_row,input_col);      
;                                                                     
;        if (input != ESC)                                            
;           BEGIN                                                     
;            pnum = (int)input - '0';                                 
;                                                                     
;            /* The number that the user has entered is the sorted */ 
;            /* numbering of the partition table.  We have to      */ 
;            /* retrieve the actual position of this partition in  */ 
;            /* the partition table.                               */ 
;                                                                     
;            j = 0;                                                   
;            for (i = 0; i < 4; i++)                                  
;               BEGIN                                                 
;                if (part_table[cur_disk][sort[i]].sys_id != 0)       
;                   BEGIN                                             
;                    j++;                                             
;                    if (j == pnum)                                   
;                        break;                                       
;                   END                                               
;               END                                                   
;            i = sort[i];                                             
;                                                                     
;            /* Verify selected partition is a non-DOS partition */   
;                                                                     
;            if ((part_table[cur_disk][i].sys_id!=uc(DOS12))  &&      
;                (part_table[cur_disk][i].sys_id!=uc(DOS16))  &&      
;                (part_table[cur_disk][i].sys_id!=uc(DOSNEW)) &&      
;                (part_table[cur_disk][i].sys_id!=uc(EXTENDED)) )     
;               BEGIN                                                 
;                /* Display Y/N prompt */                             
;                display(menu_56);                                    
;                                                                     
;                /* Get yes/no prompt */                              
;                input = get_yn_input(c(No),input_row,input_col);     
;                switch(input)                                        
;                   BEGIN                                             
;                    case 1:                                          
;                       BEGIN                                         
;                        /* Set Partition entry to zero */            
;                        remove_partition(cur_disk,i);
;                                                                  
;                        /* Redisplay the partition info */           
;                        table_display();                             
;                                                                     
;                        /* clear the prompt off */                   
;                        clear_screen(u(16),u(0),u(23),u(79));        
;                                                                     
;                        /* Set the reboot flag */                    
;                        reboot_flag = (FLAG)TRUE;                    
;                                                                     
;                        /* Say that you deleted it */                
;                        display(status_13);                          
;                                                                     
;                        wait_for_ESC();                              
;                        break;                                       
;                       END                                           
;                                                                     
;                    case 0:                                          
;                        break;                                       
;                                                                     
;                    case ESC:                                        
;                        break;                                       
;                                                                     
;                    default:                                         
;                       BEGIN                                         
;                        internal_program_error();                    
;                        break;                                       
;                       END                                           
;                   END                                               
;               END                                                   
;            else                                                     
;               BEGIN                                                 
;                /* Tell user he can only delete non-DOS partition */ 
;                display(error_39);                                   
;                wait_for_ESC();                                      
;               END                                                   
;           END                                                       
;       END                                                           
;    else                                                             
;       BEGIN                                                         
;        internal_program_error();                                    
;       END                                                           
;    clear_screen(u(0),u(0),u(24),u(79));                             
;    return;                                                          
;END 

non_dos_delete:
		; 31/12/2018

	%define ndd_j	 bp-10
	%define ndd_i	 bp-8
	%define ndd_cnt	 bp-6
	%define ndd_pnum bp-2

		push	bp
		mov	bp,sp
		sub	sp,10

		;/* clear screen */

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;/* Display header */

		;push	word [menu_58_segment]
		push	ds
		push	word [menu_58_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup and print current disk */
		
		;mov	al,[cur_disk]
		;add	al,'1'
		;mov	[insert],al
		;;push	word [menu_5_segment]
		;push	ds
		;push	word [menu_5_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_5 ; 31/12/2018

		;/* print ESC prompt */   

		;;push	word [menu_11_segment]
		;push	ds
		;push	word [menu_11_offset]
		;call	display
		;;pop	bx
		;;pop	bx

		call	display_menu_11 ; 31/12/2018

		;/* Display partition data and double check if partition exists*/ 

		call	table_display
		;or	al, al
		;jnz	short ndd_1
		jnc	short ndd_1
		jmp	case_nondos_del_DEF
ndd_1:
		mov	al,[cur_disk]
		cbw
		mov	bx,ax
		shl	bx,1
		push	word [total_mbytes+bx]
		mov	ax,nd_p_size_format ; "%4.1d"
		push	ax
		mov	ax,insert
		push	ax
		call	sprintf
		add	sp,6

		;push	word [menu_15_segment]
		push	ds
		push	word [menu_15_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* count the number of partitions */   

		xor	dx,dx
		mov	[ndd_cnt],dx ; 0
		mov	[ndd_i],dx ;0
ndd_2:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,[ndd_i]
		shl	al,1
		shl	al,1
		add	al,[ndd_i]		
		;mov	cx,46
		;mul	cx
		mov	bx,ax
		cmp	byte [part_table_sys_id+bx],0
		je	short ndd_3
		inc	byte [ndd_cnt]
ndd_3:
		inc	byte [ndd_i]
		cmp	byte [ndd_i],4
		jb	short ndd_2

		;/* Display partition number prompt */  

		;push	word [menu_59_segment]
		push	ds
		push	word [menu_59_offset]
		call	display
		;pop	bx
		;pop	bx
		push	word [input_col]
		push	word [input_row]
		mov	al,[ndd_cnt]  ; maximum
		push	ax
		mov	al,1  ; default
		push	ax
		call	get_num_input
		;add	sp,8

		cmp	al,1Bh
		jne	short ndd_4
		jmp	case_nondos_del_break
ndd_4:
		cbw
		;sub	ax,'0'
		sub	al,'0'
		mov	[ndd_pnum],ax

	;/* The number that the user has entered is the sorted */ 
        ;/* numbering of the partition table.  We have to      */ 
        ;/* retrieve the actual position of this partition in  */ 
        ;/* the partition table.                               */ 

		mov	byte [ndd_j],0
		mov	byte [ndd_i],0
		jmp	short ndd_6
ndd_5:
		inc	byte [ndd_i]
ndd_6:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		mov	bx,[ndd_i]
		;mov	cx,ax
		;mov	al,[sort+bx]
		mov	dl,[sort+bx] ; *=*
		;cbw
		;add	ax,cx
		add	al,dl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax

		cmp	byte [ndd_i],4
		jnb	short ndd_7

		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;shl	al,1
		;shl	al,1
		;mov	bx,[ndd_i]
		;;mov	cx,ax
		;;mov	al,[sort+bx]
		;mov	cl,[sort+bx]
		;;cbw
		;;add	ax,cx
		;add	al,cl
		;;mov	cx,46
		;;imul	cx
		;mov	cl,46
		;mul	cl
		;mov	bx,ax

		mov	dh,[part_table_sys_id+bx]  ; *==*

		;cmp	byte [part_table_sys_id+bx],0
		;je	short ndd_5

		or	dh,dh
		jz	short ndd_5

		;mov	ax,[ndd_pnum]
		mov	al,[ndd_pnum]
		inc	byte [ndd_j]
		;cmp	[ndd_j],ax
		cmp	[ndd_j],al
		jne	short ndd_5
ndd_7:
		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	bx,[ndd_i]
		;mov	cx,ax
		;mov	al,[sort+bx]
		;cbw
		;mov	[ndd_i],ax

		mov	[ndd_i],dl ; *=*

		;add	ax,cx
		;mov	cx,46
		;mul	cx
		;mov	bx,ax

		;/* Verify selected partition is a non-DOS partition */  
		
		; dh = [part_table_sys_id+bx] ; *==*

		;cmp	byte [part_table_sys_id+bx],1
		cmp	dh,1
		je	short ndd_11
		;cmp	byte [part_table_sys_id+bx],4
		cmp	dh,4
		je	short ndd_11
		;cmp	byte [part_table_sys_id+bx],6
		cmp	dh,6
		je	short ndd_11
		;cmp	byte [part_table_sys_id+bx],5
		cmp	dh,5
		je	short ndd_11

		;/* Display Y/N prompt */

		;push	word [menu_56_segment]
		push	ds
		push	word [menu_56_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Get yes/no prompt */ 
		
		push	word [input_col]
		push	word [input_row]
		mov	al,[No] ; default input, 'N'
		push	ax
		call	get_yn_input
		;add	sp,6
switch_input6:
		;cbw
		;cmp	ax,1Bh
		cmp	al,1Bh
		je	short case_nondos_del_break
		ja	short case_nondos_del_DEF
		or	al,al
		jz	short case_nondos_del_break
		dec	al
		jnz	short case_nondos_del_DEF

case_nondos_del_1:
		;/* Set Partition entry to zero */

		;push	word [ndd_i]
		mov	ah,[ndd_i] ; 02/01/2019
		mov	al,[cur_disk]
		;push	ax
		call	remove_partition
		;pop	bx
		;pop	bx

		;/* Redisplay the partition info */ 
		
		call	table_display

		;/* clear the prompt off */    
		
		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,16
		push	ax
		call	clear_screen
		;add	sp,8

		;/* Set the reboot flag */ 

		mov	byte [reboot_flag],1

		;/* Say that you deleted it */

		;push	word [status_13_seg]
		push	ds
		push	word [status_13_off]
ndd_10:
		call	display
		;pop	bx
		;pop	bx
		call	wait_for_ESC
		jmp	short case_nondos_del_break
ndd_11:
		;/* Tell user he can only delete non-DOS partition */ 

		;push	word [error_39_seg]
		push	ds
		push	word [error_39_off]
		jmp	short ndd_10
case_nondos_del_DEF:
		call	internal_program_error
case_nondos_del_break:
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		
		call	CLS

		mov	sp,bp
		pop	bp
		retn

; ----------------------------------------------------------------------------
; partinfo.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 23/12/2018)

;char find_non_dos_partition()
;
;BEGIN
; char  i;
;
; /* Look at all four partition entries for system id byte that is */
; /* not NUL, DOS12, DOS16, DOSNEW, or EXTENDED. */
; for (i = c(0); i < c(4);i++)
;    BEGIN
;
;     /* if we find a match, do a TRUE return */
;     if ((part_table[cur_disk][i].sys_id != NUL)    &&
;         (part_table[cur_disk][i].sys_id != DOS12)  &&
;         (part_table[cur_disk][i].sys_id != DOS16)  &&
;         (part_table[cur_disk][i].sys_id != DOSNEW) &&
;         (part_table[cur_disk][i].sys_id != EXTENDED))
;        BEGIN
;         return(TRUE);
;         break;
;        END
;    END
; /* Did not find one, return FALSE */
; return(FALSE);
;END

find_non_dos_partition:
		; 23/12/2018

	;%define fndp_i	bp-2

		;push	bp
		;mov	bp,sp
		;sub	sp,2
		
		;mov	byte [fndp_i],0
		xor	dl,dl
		jmp	short fndp_2
fndp_1:
		;inc	byte [fndp_i]
		inc	dl
;fndp_2:
		;cmp	byte [fndp_i],4
		cmp	dl,4
		jge	short fndp_3
fndp_2:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;mov	cx,ax
		;mov	al,[fndp_i]
		;cbw
		;add	ax,cx
		add	al,dl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		
		mov	cl,[part_table_sys_id+bx]
		
		;cmp	byte [part_table_sys_id+bx],0
		;je	short fndp_1
		or	cl,cl
		jz	short fndp_1

		;cmp	byte [part_table_sys_id+bx],1
		;je	short fndp_1
		cmp	cl,1
		je	short fndp_1

		;cmp	byte [part_table_sys_id+bx],4
		;je	short fndp_1
		cmp	cl,4
		je	short fndp_1
		
		;cmp	byte [part_table_sys_id+bx],6
		;je	short fndp_1
		cmp	cl,6
		je	short fndp_1		

		;cmp	byte [part_table_sys_id+bx],5
		;je	short fndp_1
		cmp	cl,5
		je	short fndp_1

		mov	al,1
		jmp	short fndp_4
fndp_3:
		sub	al,al
fndp_4:
		cmp	al,1

		;mov	sp,bp
		;pop	bp

		retn

; ----------------------------------------------------------------------------

;char find_ext_drive(offset)
;
;char offset;
;
;BEGIN
;
;char number_found;
;char i;
;
;    number_found = c(0);
;
;    /* Go look for the nth extended drive */
;    for (i=c(0); i < c(23); i++)
;      BEGIN
;       /* See if there is a drive we know about */
;       if ((ext_table[cur_disk][i].sys_id == uc(DOS12)) || (ext_table[cur_disk][i].sys_id == uc(DOS16)) ||
;          (ext_table[cur_disk][i].sys_id == uc(DOSNEW)))
;          BEGIN
;           /* Is this the one we were looking for ? */
;           if (number_found == offset)
;              BEGIN
;               /* Yes it is, return where we found it */
;               return(i);
;               break;
;              END
;              /* Show we found one and go look for the next */
;              number_found++;
;          END
;      END
;      /* We should never get here */
;      internal_program_error();
;      return(c(INVALID));
;END

find_ext_drive:
		; 26/12/2018
	;%define fed_number_found bp-4
	;%define fed_i		 bp-2
	;%define fed_offset	 bp+4

		;push	bp
		;mov	bp,sp
		;sub	sp,4

		; INPUT: DL = Logical dos drive offset/index
		; 06/01/2019
		; OUTPUT: CL = Extended drive index of (that) logical DOS drive 
		;	      (including count of non-dos drives before it) 
		;	  CL = 0FFh -> invalid (not found)		

		;/* Go look for the nth extended drive */

		;sub	al,al ; 0
		;mov	[fed_i],al ; 0
		;mov	[fed_number_found],al ; 0
		xor	cx,cx
		;mov	[fed_i],cl
		;mov	[fed_number_found],cl
		jmp	short fed_3
fed_1:
		;inc	byte [fed_i]
		inc	ch
fed_2:
		;/* Show we found one and go look for the next */

		;inc	byte [fed_number_found]
		inc	cl
;fed_3:
		;cmp	byte [fed_number_found],23
		cmp	cl,23	
		jge	short fed_5
		;mov	al,[fed_number_found]
		;mov	cl,[fed_number_found]
fed_3:
		;/* See if there is a drive we know about */

		;cbw
		;mov	cx,ax
		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]
		;add	ax,cx
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	bl,46
		mul	bl
		mov	bx,ax

		mov	al,[ext_table_sys_id+bx]
		;cmp	byte [ext_table_sys_id+bx],1
		cmp	al,1
		je	short fed_4
		;cmp	byte [ext_table_sys_id+bx],4
		cmp	al,4
		je	short fed_4
		;cmp	byte [ext_table_sys_id+bx],6
		cmp	al,6
		jne	short fed_2
fed_4:		
		;/* Is this the one we were looking for ? */

		;mov	al,[fed_offset]
		;cmp	[fed_i],al
		cmp	ch,dl
		jne	short fed_1

		;/* Yes it is, return where we found it */

		;mov	al,[fed_number_found]
		;jmp	short fed_6
		;mov	al,cl
		;xor	ch,ch
		; cl = Extended drive index number
		retn
fed_5:
		;/* We should never get here */

		call	internal_program_error
		;mov	al,0FFh
		;mov	cx,0FFh
		;stc
		mov	cl,0FFh
fed_6:
		;mov	sp,bp
		;pop	bp
		retn


; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/*  Screen for SYSTEM_REBOOT                                                                       */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                                                                                |          */
;/*   05|                                                                                |          */
;/*   06|                                                                                |          */
;/*   07|                                                                                |          */
;/*   08|                                                                                |          */
;/*   09|                                                                                |          */
;/*   10|                                                                                |          */
;/*   11|                                                                                |          */
;/*   12|                                                                                |          */
;/*   13|    System will now restart                                                     |menu_38   */
;/*   14|                                                                                |          */
;/*   15|    Insert DOS diskette in drive A:                                             |menu_38   */
;/*   16|    Press any key when ready . . .                                              |menu_38   */
;/*   17|                                                                                |          */
;/*   18|                                                                                |          */
;/*   19|                                                                                |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|                                                                                |          */
;/*   ------------------------------------------------------------------------------------          */
;/*                                                                                                 */
;/***************************************************************************************************/

; strcmp (Microsoft C 6.0 runtime library, MSDOS 6.0, 1991)	
; ============================================================================
; Modified and simplified for Assembly language (by Erdogan Tan, 23/12/2018)

; STRCMP.ASM
;*************
;strcmp - compare two strings, returning less than, equal to, or greater than
;
;Purpose:
;	Compares two string, determining their lexical order.  Unsigned
;	comparison is used.
;
;	Algorithm:
;	   int strcmp ( src , dst )
;		   unsigned char *src;
;		   unsigned char *dst;
;	   {
;		   int ret = 0 ;
;
;		   while( ! (ret = *src - *dst) && *dst)
;			   ++src, ++dst;
;
;		   if ( ret < 0 )
;			   ret = -1 ;
;		   else if ( ret > 0 )
;			   ret = 1 ;
;
;		   return( ret );
;	   }
;
;Entry:
;	const char * src - string for left-hand side of comparison
;	const char * dst - string for right-hand side of comparison
;
;Exit:
;	AX < 0, 0, or >0, indicating whether the first string is
;	Less than, Equal to, or Greater than the second string.
;
;Uses:
;	BX, CX, DX
;
;Exceptions:
;
;*******************************************************************************

; IBM PC-DOS FDISK.COM (upacked) - Segment 0, Offset 6FA4h

strcmp:
		; 23/12/2018

	%define strcmp_src bp+4
	%define strcmp_dst bp+6

		;push	bp
		;mov	bp,sp
	
		;mov	dx,di	; preserve SI and DI
		;mov	bx,si
	
		;mov	ax,ds
		;mov	es,ax	; ES = DS = DGROUP
		;mov	si,[strcmp_src]	; DS:SI = src
		;mov	di,[strcmp_dst]	; ES:DI = dst

		xor	ax,ax
		mov	cx,-1
		repne	scasb	; compute length of "dst"
		not	cx	; CX = strlen(dst)+1
		sub	di,cx	; restore ES:DI = dst
		repe	cmpsb	; compare while equal, at most length of "dst"
		je	short toend ; dst == src?  (AX = 0)
				; dst < src	dst > src
		sbb	ax,ax	; AX=-1, CY=1	AX=0, CY=0
		sbb	ax,-1	; AX=-1		AX=1
toend:
		;mov	si,bx		; restore SI and DI
		;mov	di,dx

		;pop	bp
		retn

; ----------------------------------------------------------------------------
; input.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 01/01/2019)

;/*  */ 
;
;void get_string_input(StartRow,StartCol,string_ptr)
;                                  
;unsigned        StartRow;                                         /* AN000 */
;unsigned        StartCol;                                         /* AN000 */
;char far        *string_ptr;                                      /* AN000 */
;                                                                  /* AN000 */
;BEGIN                                                             /* AN000 */
;
;    #define MAX_STRING_INPUT_LENGTH 11
;                                                                  /* AN000 */
;    unsigned char   input;                                        /* AN000 */
;    char   far *WorkingPtr;                                       /* AN000 */
;    char   far *DeletePtr;                                        /* AN000 */
;    char   Done;                                                  /* AN000 */
;    unsigned        Row;                                          /* AN000 */
;    unsigned        Col;                                          /* AN000 */
;
;    char            attribute;
;    char far        *attribute_ptr = &attribute;
;    char far *input_ptr = &input;
;
;    if (mono_flag == TRUE)
;        attribute = HIWHITE_ON_BLACK; /*C09*/
;    else
;        attribute = HIWHITE_ON_BLUE;  /*C09*/
;
;    WorkingPtr = string_ptr;                                      /* AN000 */
;
;    Row = StartRow;                                               /* AN000 */
;    Col = StartCol;                                               /* AN000 */
;    VIOSETCURPOS(Row,Col,u(0));                                   /* AN000 */
;
;    while(*WorkingPtr != c(NUL))                                  /* AN000 */
;        BEGIN                                                     /* AN000 */
;        VIOWRTCHARSTRATT(WorkingPtr,u(1),Row,Col,attribute_ptr,u(0));
;        WorkingPtr++;
;        Col++;                                                    /* AN000 */
;        VIOSETCURPOS(Row,Col,u(0));                               /* AN000 */
;        END                                                       /* AN000 */
;
;    regs.h.ah = uc(12);                                           /* AN000 */
;    regs.h.al = uc(7); /*C03*/
;    intdos(&regs,&regs);                                          /* AN000 */
;    input = regs.h.al;                                            /* AN000 */
;
;    /* Loop until we get good stuff */                            /* AN000 */
;    Done = FALSE;                                                 /* AN000 */
;    while (!Done)                                                 /* AN000 */
;        BEGIN                                                     /* AN000 */
;
;        /* Go handle different inputs */
;
;        if (input < 32)                                           /* AN000 */
;            BEGIN                                                 /* AN000 */
;            switch(input)                                         /* AN000 */
;                BEGIN                                             /* AN000 */
;                case ESC:                                         /* AN000 */
;                    Done=TRUE;                                    /* AN000 */
;                    *string_ptr++ = c(ESC);                       /* AN000 */
;                    *string_ptr++ = c('\0');                      /* AN000 */
;                   break;                                         /* AN000 */
;
;                case  CR:                                         /* AN000 */
;                    Done=TRUE;                                    /* AN000 */
;                    break;                                        /* AN000 */
;
;                case 8: /* backspace */                           /* AN000 */
;                    if (Col > StartCol)                           /* AN000 */
;                        BEGIN                                     /* AN000 */
;                        WorkingPtr--;                             /* AN000 */
;                        Col--;                                    /* AN000 */
;                        VIOSETCURPOS(Row,Col,u(0));               /* AN000 */
;			  input = c(' ');
;                        VIOWRTCHARSTRATT(input_ptr,u(1),Row,Col,attribute_ptr,u(0));
;                        VIOSETCURPOS(Row,Col,u(0));               /* AN000 */
;                        DeletePtr = WorkingPtr;                   /* AN000 */
;                        while ( *(DeletePtr+1) != c('\0')  )      /* AN000 */
;                            BEGIN                                 /* AN000 */
;                            *DeletePtr = *(DeletePtr+1);          /* AN000 */
;                            VIOWRTCHARSTRATT(DeletePtr,u(1),Row,Col,attribute_ptr,u(0));
;                            DeletePtr++;                          /* AN000 */
;                            END                                   /* AN000 */
;                        *DeletePtr = c('\0');                     /* AN000 */
;			  input = c(' ');
;                        VIOWRTCHARSTRATT(input_ptr,u(1),Row,Col+1,attribute_ptr,u(0));
;                        VIOSETCURPOS(Row,Col,u(0));               /* AN000 */
;                        END                                       /* AN000 */
;                    else DOSBEEP(u(900),u(400));                  /* AN000 */
;                break;                                            /* AN000 */
;
;                case  0:                                          /* AN000 */
;                    regs.h.ah = uc(0x07); /*C03*/
;                    intdos(&regs,&regs);                          /* AN000 */
;                    input = regs.h.al;                            /* AN000 */
;                    switch(input)                                 /* AN000 */
;                        BEGIN                                     /* AN000 */
;                        case 71: /* HOME */                       /* AN000 */
;                            WorkingPtr = string_ptr;              /* AN000 */
;                            Row = StartRow;                       /* AN000 */
;                            Col = StartCol;                       /* AN000 */
;                            VIOSETCURPOS(Row,Col,u(0));           /* AN000 */
;                            break;                                /* AN000 */
;
;                        case 79: /* END  */                       /* AN000 */
;                            while (*WorkingPtr != c('\0') )       /* AN000 */
;                                BEGIN                             /* AN000 */
;                                WorkingPtr++;                     /* AN000 */
;                                Col++;                            /* AN000 */
;                                VIOSETCURPOS(Row,Col,u(0));       /* AN000 */
;                                END                               /* AN000 */
;                            break;                                /* AN000 */
;
;                        case 75: /* Cursor Left */                /* AN000 */
;                            if (Col > StartCol)                   /* AN000 */
;                                BEGIN                             /* AN000 */
;                                WorkingPtr--;                     /* AN000 */
;                                Col--;                            /* AN000 */
;                                VIOSETCURPOS(Row,Col,u(0));       /* AN000 */
;                                END                               /* AN000 */
;                            else DOSBEEP(u(900),u(400));          /* AN000 */
;                            break;                                /* AN000 */
;
;                        case 77: /* Cursor Right */               /* AN000 */
;                            if ( *WorkingPtr != c('\0') )         /* AN000 */
;                                BEGIN                             /* AN000 */
;                                WorkingPtr++;                     /* AN000 */
;                                Col++;                            /* AN000 */
;                                VIOSETCURPOS(Row,Col,u(0));       /* AN000 */
;                                END                               /* AN000 */
;                            else DOSBEEP(u(900),u(400));          /* AN000 */
;                            break;                                /* AN000 */
;
;                        default:                                  /* AN000 */
;                            DOSBEEP(u(900),u(400));               /* AN000 */
;                            break;                                /* AN000 */
;
;                        END                                       /* AN000 */
;                    break;                                        /* AN000 */
;
;                default:                                          /* AN000 */
;                        DOSBEEP(u(900),u(400));                   /* AN000 */
;                        break;                                    /* AN000 */
;                END                                               /* AN000 */
;
;            END                                                   /* AN000 */
;         else     /* input is >= 32 */                            /* AN000 */
;            BEGIN                                                 /* AN000 */
;            input = dos_upper(input);                             /* AN000 */
;            if ( (strchr(".\"/\\[]:|<>+=;,",input) == NULL) &&
;                 (Col < StartCol + MAX_STRING_INPUT_LENGTH)    )  /* AN000 */
;                BEGIN                                             /* AN000 */
;                /* SR; 10/2/89; If Ctrl-C, display blank and beep */
;                if ( input != 0x03 )
;                    VIOWRTCHARSTRATT(input_ptr,u(1),Row,Col,attribute_ptr,u(0));
;                else
;                    {
;                    DOSBEEP( 900, 400 );
;                    input = c(' ');
;                    VIOWRTCHARSTRATT(input_ptr,u(1),Row,Col,attribute_ptr,u(0));
;                    }
;                *WorkingPtr = input;                              /* AN000 */
;                *(WorkingPtr+1) = c('\0');                        /* AN000 */
;                if (Col < (StartCol + MAX_STRING_INPUT_LENGTH - 1)) /* AN000 */
;                    BEGIN                                         /* AN000 */
;                    Col++;                                        /* AN000 */
;                    WorkingPtr++;                                 /* AN000 */
;                    END                                           /* AN000 */
;                VIOSETCURPOS(Row,Col,u(0));                       /* AN000 */
;                END                                               /* AN000 */
;            else DOSBEEP(u(900),u(400));                          /* AN000 */
;            END                                                   /* AN000 */
;
;        if (!Done)                                                /* AN000 */
;            BEGIN                                                 /* AN000 */
;            /* Get a character */                                 /* AN000 */
;            regs.h.ah = uc(0x07); /*C03*/
;            intdos(&regs,&regs);                                  /* AN000 */
;            input = regs.h.al;                                    /* AN000 */
;            END                                                   /* AN000 */
;        END                                                       /* AN000 */
;
;    return;                                                       /* AN000 */
;END                                                                 

get_string_input:

		; 01/01/2019

	%define gsi_endcol	bp-28 ; modification 

	%define gsi_col		bp-26
	%define gsi_deleteptr	bp-24
	%define gsi_attribute_ptr bp-20
	;%define gsi_attribute_ptr2 bp-18
	%define gsi_row		bp-16
	%define gsi_workingptr	bp-14
	%define gsi_done	bp-10
	%define gsi_input_ptr	bp-8
	;%define gsi_input_ptr2	bp-6
	%define gsi_attribute	bp-4
	%define gsi_input	bp-2

	%define gs_i_startrow	bp+4
	%define gs_i_startcol	bp+6
	%define gs_i_stringptr	bp+8

		push	bp
		mov	bp,sp
		;sub	sp,26
		sub	sp,28

		lea	ax,[gsi_attribute]
		mov	[gsi_attribute_ptr],ax
		mov	[gsi_attribute_ptr+2],ss
		lea	cx,[gsi_input]
		mov	[gsi_input_ptr],cx
		mov	[gsi_input_ptr+2],ss
		
		cmp	byte [mono_flag],1
		jne	short gsi_1
		mov	byte [gsi_attribute],0Fh ;HIWHITE_ON_BLACK
		jmp	short gsi_2
gsi_1:
		mov	byte [gsi_attribute],1Fh ;HIWHITE_ON_BLUE
gsi_2:
		mov	ax,[gs_i_stringptr]
		mov	dx,[gs_i_stringptr+2]
		mov	[gsi_workingptr],ax
		mov	[gsi_workingptr+2],dx
		mov	ax,[gs_i_startrow]
		mov	[gsi_row],ax
		mov	cx,[gs_i_startcol]
		mov	[gsi_col],cx

		; modification
		add	cx,11 ; MAX_STRING_INPUT_LENGTH = 11
		mov	[gsi_endcol],cx
		
		;push	ax
		;push	cx
		jmp	short gsi_4
gsi_3:
		;VIOWRTCHARSTRATT(WorkingPtr,u(1),Row,Col,attribute_ptr,u(0));

		push	es
		push	bx
		mov	ax,1
		push	ax
		push	word [gsi_row]
		push	word [gsi_col]
		push	word [gsi_attribute_ptr+2]
		push	word [gsi_attribute_ptr]
		;sub	cx,cx
		;push	cx
		call	VIOWRTCHARSTRATT
		
		;WorkingPtr++;
		;Col++;
		
		;VIOSETCURPOS(Row,Col,u(0));         

		inc	word [gsi_workingptr]
		;push	word [gsi_row]
		inc	byte [gsi_col]
		;push	word [gsi_col]
gsi_4:
		;sub	ax,ax
		;push	ax

		mov	dh,[gsi_row]
		mov	dl,[gsi_col]

		call	VIOSETCURPOS
		
		;while(*WorkingPtr != c(NUL))     	

		les	bx,[gsi_workingptr]
		cmp	byte [es:bx],0
		jne	short gsi_3

		;mov	byte [regs_x_ax+1],0Ch
		;mov	byte [regs_x_ax],7
		;mov	ax,regs_x_ax
		;push	ax
		;push	ax
		;call	intdos
		;pop	bx
		;pop	bx
		;mov	al,[regs_x_ax]

		;DOS function
		;FLUSH BUFFER AND READ STANDARD INPUT		
		;mov	ah,0Ch
		;mov	al,7  ; DIRECT CHARACTER INPUT, WITHOUT ECHO
		mov	ax,0C07h
		int	21h

		mov	byte [gsi_input],al

		;/* Loop until we get good stuff */ 

		mov	byte [gsi_done],0  ; Done = FALSE;
gsi_5:
		;/* Go handle different inputs */

		;if (input < 32)
		cmp	byte [gsi_input],20h ; 32 ; SPACE character
		jb	short gsi_6 ; one of control characters
		jmp	gsi_26	; TEXT character
gsi_6:
		;switch(input)  

		mov	al,[gsi_input]
		;sub	ah,ah
		;cmp	ax,1Bh
		cmp	al,1Bh ; ESCape key
		je	short gsi_9
		jb	short gsi_7
		jmp	gsi_29
gsi_7:
		or	al,al
		jnz	short gsi_8
		jmp	gsi_15
gsi_8:
		sub	al,8
		jz	short gsi_11  ; 8, /* backspace */
		sub	al,5
		jz	short gsi_10  ; 13, CR
		jmp	gsi_29 ; one of other (control) keys, invalid
gsi_9:
		;case ESC:
		mov	byte [gsi_done],1 ; Done = TRUE
		les	bx,[gs_i_stringptr]
		inc	word [gs_i_stringptr]
		;mov	byte [es:bx],1Bh
		mov	[es:bx],al ; 1Bh
		;les	bx,[gs_i_stringptr]
		inc	bx
		inc	word [gs_i_stringptr]
		mov	byte [es:bx],0
		jmp	gsi_30
gsi_10:	
		;case CR: ; 0Dh ; ENTER (Carriage Return) key
		mov	byte [gsi_done],1 ; TRUE
		jmp	gsi_30 ; break;
gsi_11:
		; case 8: ; /* backspace */ 
		mov	ax,[gs_i_startcol]
		cmp	[gsi_col],ax
		ja	short gsi_12 ; if (Col > StartCol) 
		jmp	gsi_29 ; beep!
gsi_12:
		;push	word [gsi_row]
		dec	byte [gsi_col]
		;mov	ax,[gsi_col]
		;push	ax
		;sub	cx,cx
		;push	cx
		mov	dh,[gsi_row]
		mov	dl,[gsi_col]
		call	VIOSETCURPOS
		mov	byte [gsi_input],' '
		push	word [gsi_input_ptr+2]
		push	word [gsi_input_ptr]
		mov	ax,1
		push	ax
		push	word [gsi_row]
		push	word [gsi_col]
		push	word [gsi_attribute_ptr+2]
		push	word [gsi_attribute_ptr]
		;sub	ax,ax
		;push	ax
		call	VIOWRTCHARSTRATT
		;push	[gsi_row]
		;push	[gsi_col]
		;sub	ax,ax
		;push	ax
		mov	dh,[gsi_row]
		mov	dl,[gsi_col]
		call	VIOSETCURPOS
		dec	word [gsi_workingptr]
		mov	ax,[gsi_workingptr]
		mov	dx,[gsi_workingptr+2]
		mov	[gsi_deleteptr],ax
		mov	[gsi_deleteptr+2],dx
		jmp	short gsi_14
gsi_13:	
		mov	al,[es:bx+1]
		mov	[es:bx],al
		push	es
		push	bx
		mov	ax,1
		push	ax
		push	word [gsi_row]
		push	word [gsi_col]
		push	word [gsi_attribute_ptr+2]
		push	word [gsi_attribute_ptr]
		;sub	ax,ax
		;push	ax
		call	VIOWRTCHARSTRATT
		mov	ax,[gsi_deleteptr]
		mov	dx,[gsi_deleteptr+2]
		inc	ax
		mov	[gsi_deleteptr],ax

gsi_14:
		;while ( *(DeletePtr+1) != c('\0')  ) 

		les	bx,[gsi_deleteptr]
		cmp	byte [es:bx+1],0
		jne	short gsi_13
	
		mov	byte [es:bx],0
		mov	byte [gsi_input],' '
		push	word [gsi_input_ptr+2]
		push	word [gsi_input_ptr]
		mov	ax,1
		push	ax
		push	word [gsi_row]
		add	ax,[gsi_col]
		push	ax
		push	word [gsi_attribute_ptr+2]
		push	word [gsi_attribute_ptr]
		;sub	ax,ax
		;push	ax
		call	VIOWRTCHARSTRATT
		jmp	gsi_28
gsi_15:		
		;case  0: 
 
		;mov	byte [regs_x_ax+1],7
		;mov	ax,regs_x_ax
		;push	ax
		;push	ax
		;call	intdos
		;pop	bx
		;pop	bx
		;mov	al,[regs_x_ax]

		;DOS function
		;DIRECT CHARACTER INPUT, WITHOUT ECHO
		mov	ah,07h
		int	21h
		mov	byte [gsi_input],al

		;switch(input)

		;sub	ah,ah
		cmp	ax,79  
		je	short gsi_19  ; /* END */
		jb	short gsi_16
		jmp	gsi_29
gsi_16:
		sub	al,71
		je	short gsi_17 ; /* HOME */    
		sub	al,4
		je	short gsi_21 ; 75, /* Cursor Left */	
		sub	al,2
		je	short gsi_23 ; 77, /* Cursor Right */ 
		jmp	gsi_29	; one of other (control) keys, invalid
gsi_17:
		;case 71: /* HOME */    

		mov	ax,[gs_i_stringptr]
		mov	dx,[gs_i_stringptr+2]
		mov	[gsi_workingptr],ax
		mov	[gsi_workingptr+2],dx
		
		mov	ax,[gs_i_startrow]
		mov	[gsi_row],ax
		mov	cx,[gs_i_startcol]
		mov	[gsi_col],cx
		;push	ax
		;push	cx
gsi_18:
		;sub	ax,ax
		;push	ax
		mov	dh,[gsi_row]
		mov	dl,[gsi_col]
		call	VIOSETCURPOS
		jmp	gsi_30
gsi_19:
		;case 79: ; /* END */   
		
		;while (*WorkingPtr != c('\0') ) 
		les	bx,[gsi_workingptr]
		cmp	byte [es:bx],0
		jne	short gsi_20
		jmp	gsi_30
gsi_20:	
		inc	word [gsi_workingptr]
		;push	word [gsi_row]
		inc	byte [gsi_col]
		;push	word [gsi_col]
		;sub	ax,ax
		;push	ax
		mov	dh,[gsi_row]
		mov	dl,[gsi_col]
		call	VIOSETCURPOS
		jmp	short gsi_19
gsi_21:
		;case 75: ; /* Cursor Left */

		mov	ax,[gs_i_startcol]
		cmp	[gsi_col],ax
		ja	short gsi_22  ; if (Col > StartCol)
		jmp	gsi_29
gsi_22:	
		dec	word [gsi_workingptr]
		push	word [gsi_row]
		dec	byte [gsi_col]
		;jmp	short gsi_25
		jmp	short gsi_18 ; 02/01/2019
gsi_23:
		;case 77: ; /* Cursor Right */ 

		les	bx,[gsi_workingptr]
		cmp	byte [es:bx],0
		jne	short gsi_24 ; if ( *WorkingPtr != c('\0') )
		jmp	gsi_29
gsi_24:
		inc	word [gsi_workingptr]
		push	word [gsi_row]
		inc	byte [gsi_col]
;gsi_25:
		;push	word [gsi_col]
		jmp	short gsi_18
gsi_26:
		;else	/* input is >= 32 */

		;input = dos_upper(input);
		mov	al,[gsi_input]
		;push	ax
		call	dos_upper
		;pop	bx
		mov	[gsi_input],al
	
		;if ( (strchr(".\"/\\[]:|<>+=;,",input) == NULL) &&
		;   (Col < StartCol + MAX_STRING_INPUT_LENGTH))

		;sub	ah,ah
		;push	ax
		;mov	ax,invstrchars ; ".\"/\\[]:|<>+=;,"
		;push	ax
		;call	strchr
		;pop	bx
		;pop	bx

		; 01/01/2019
		mov	si,invstrchars ; ".\"/\\[]:|<>+=;,"
		;al = character to be searched in invstrchars		
		call	strchr

		or	ax,ax
		jnz	short gsi_29

		;mov	ax,[gs_i_startcol]
		;add	ax,11	; MAX_STRING_INPUT_LENGTH = 11
		mov	ax,[gsi_endcol]
		cmp	ax,[gsi_col]		
		jbe	short gsi_29

		cmp	byte [gsi_input],3
		jne	short gsi_27
		
		;mov	ax,900
		;push	ax
		;mov	ax,400
		;push	ax
		call	DOSBEEP  ; 01/01/2019

		mov	byte [gsi_input],' '
gsi_27:
		;VIOWRTCHARSTRATT(input_ptr,u(1),Row,Col,attribute_ptr,u(0));

		push	word [gsi_input_ptr+2]
		push	word [gsi_input_ptr]
		mov	ax,1
		push	ax
		push	word [gsi_row]
		push	word [gsi_col]
		push	word [gsi_attribute_ptr+2]
		push	word [gsi_attribute_ptr]
		;sub	ax,ax
		;push	ax
		call	VIOWRTCHARSTRATT

		mov	al,[gsi_input]
		les	bx,[gsi_workingptr]
		mov	[es:bx],al
		mov	byte [es:bx+1],0
		;mov	ax,[gs_i_startcol]
		;add	ax,10
		mov	ax,[gsi_endcol]  ; modification
		dec	ax
		cmp	ax,[gsi_col]
		jbe	short gsi_28
		inc	byte [gsi_col]
		lea	ax,[bx+1]
		mov	[gsi_workingptr],ax
		mov	[gsi_workingptr+2],es
gsi_28:
		;push	word [gsi_row]
		;jmp	gsi_25
		jmp	gsi_18
gsi_29:
		;mov	ax,900
		;push	ax
		;mov	ax,400
		;push	ax
		call	DOSBEEP  ; 01/01/2019
gsi_30:
		;if (!Done) 
		cmp	byte [gsi_done],0
		;jne	short gsi_31
		jne	short gsi_32

		;/* Get a character */
		;regs.h.ah = uc(0x07);
		;intdos(&regs,&regs);
		;input = regs.h.al;       

		;mov	byte [regs_x_ax+1],7
		;mov	ax,regs_x_ax
		;push	ax
		;push	ax
		;call	intdos
		;pop	bx
		;pop	bx
		;mov	al,[regs_x_ax]

		;DOS function
		;DIRECT CHARACTER INPUT, WITHOUT ECHO
		mov	ah,07h
		int	21h		

		mov	[gsi_input],al
;gsi_31:
		;while (!Done)
		;cmp	[gsi_done],0
		;jne	short gsi_32
	
		;/* Go handle different inputs */
		jmp	gsi_5
gsi_32:
		mov	sp,bp
		pop	bp
		;retn
		retn	8

; STRCHR.ASM (VCCRT2.ZIP) - Microsoft Visual C++ 1.0 Run-Time Library Sources
; ----------------------------------------------------------------------------
; Modified and simplified for NASM syntax by Erdogan Tan (01/01/2019)

;********
;char *strchr(string, c) - search a string for a character
;
;Purpose:
;	Searches a string for a given character, which may be the
;	null character '\0'.
;
;	Algorithm:
;	char *
;	strchr (string, ch)
;	      char *string, ch;
;	      {
;	      while (*string && *string != ch)
;		      string++;
;	      if (*string == ch)
;		      return(string);
;	      return((char *)0);
;	      }
;
;Entry:
;	char *string - string to search in
;	char c - character to search for
;
;Exit:
;	returns pointer to the first occurence of c in string
;	returns NULL if c does not occur in string
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************

; IBM PC-DOS 7.0 FDISDK.COM (unpacked) - Segfment 0, Offset 7264h

strchr:
;	%define strchr_string bp+4
;	%define strchr_chr    bp+6	
;
;		push	bp
;		mov	bp,sp
;		;push	di 
;
;		mov	di,[strchr_string] ; di=pointer to string
;		push	ds	; fix es for small/middle model
;		pop	es
;	
;		mov	bx,di	; bx saves string pointer
;		xor	ax,ax	; null byte to search for
;		mov	cx,-1	; count bytes negatively in cx
;		repne	scasb	; find string length by scanning for null
;		not	cx	; cx=strlen+1
;		mov	al,[str_chr] ; al=byte to search for
;		mov	di,bx	; restore from saved string pointer
;		repne	scasb	; find that byte (if it exists)!
;
;; if the repne scasb above terminates with the zero flag set, a match has
;; been found and di points to the byte FOLLOWING the matching byte. if
;; the zero flag is NOT set and the character being scanned for was NOT
;; a null ('\0'), then the scan has failed. in the remaining case, which
;; can only occur in large data models, the string must be exactly 0x10000
;; bytes long (counting the terminal null character) and the very last byte
;; is the match.
;
;		je	short retsuccess ; have a match, go do the return
;
;		xor	ax,ax	; no match, return NULL
;		jmp	short toend
;retsuccess:
;		lea	ax,[di-1] ; ret value: pointer to matching byte
;toend:
;		;pop	di
;		pop	bp
;		retn

		; INPUT:
		;   ds:si = address of string to search in 
		;   al = character to search for
		; OUTPUT:
		;   ax = pointer to the first occurence of chr in string
		;      = 0 if character does not occur in string	 	

		;push	si

		mov	ah,al
strchr_0:
		lodsb
		cmp	al,ah
		je	short strchr_2
		and	al,al
		jnz	short strchr_0
		xor	ah,ah
strchr_1:
		;pop	si
		retn
strchr_2:
		lea	ax,[si-1]
		;jmp	shott shrchr_1
		retn

; ----------------------------------------------------------------------------
; input.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 02/01/2019)

;/*  */
;char get_alpha_input(low_letter,high_letter,row,col,error_low_letter,error_high_letter)
;
;unsigned     row;
;unsigned     col;
;char         low_letter;
;char         high_letter;
;char         error_low_letter;
;char         error_high_letter;
;
;BEGIN
;
;    char   input;
;    char   default_used;
;    char   input_value;
;
;    char            attribute;
;    char far        *attribute_ptr = &attribute;
;    char far *input_ptr = &input;
;
;    if (mono_flag == TRUE)
;        attribute = HIWHITE_ON_BLACK; /*C09*/
;    else
;        attribute = HIWHITE_ON_BLUE;  /*C09*/
;
;    /* Assume bad input */
;    valid_input = FALSE;
;
;    /* Init input_value to something non-alpha */
;    input_value = c(0);                                              /* AC000 */
;
;    /* Loop until we get good stuff */
;    while (valid_input == FALSE)
;        BEGIN
;
;        /* position the cursor */
;        VIOSETCURPOS(row,col,u(0));                                  /* AC000 */
;
;        /* Flush the keyboard buffer and get the next pressed key */
;        input = get_char_input();
;        input = dos_upper(input);
;
;        /* Go handle different inputs */
;        switch(input)
;            BEGIN
;            case ESC:
;                BEGIN
;                valid_input = TRUE;
;                break;
;                END
;
;            case  CR:
;                BEGIN
;                /* See if it is digit and between given letters*/
;                /* Do world trade get country information */
;                input = dos_upper(input_value);                      /* AN000 */
;                if ((isalpha(input))       &&
;                    (input >= low_letter)  &&
;                    (input <= high_letter) &&
;                    (isalpha(input_value)))
;                    BEGIN
;                    valid_input = TRUE;
;                    END
;                else
;                    BEGIN
;                    if (isalpha(input_value))
;                        BEGIN
;                        /* Setup error message */
;                        insert[0] = input;
;                        insert[1] = error_low_letter;
;                        insert[2] = c('-');                          /* AC000 */
;                        insert[3] = error_high_letter;
;                        display(error_23);
;                        END
;                    else
;                        BEGIN
;                        insert[0] = error_low_letter;
;                        insert[1] = c('-');                          /* AC000 */
;                        insert[2] = error_high_letter;
;                        display(error_31);
;                        END
;                    END
;                break;
;                END
;
;            default:
;                BEGIN
;
;                if ((isalpha(input))       &&                           /*C16*/
;                    (dos_upper(input) >= low_letter)  &&                /*C16*/
;                    (dos_upper(input) <= high_letter))                  /*C16*/
;                    clear_screen(u(23),u(0),u(23),u(79));               /*C16*/
;                else                                                    /*C16*/
;                    {                                                   /*C16*/
;                    if (isalpha(input))                                 /*C16*/
;                        {                                               /*C16*/
;                        /* Setup error message */                       /*C16*/
;                        insert[0] = input;                              /*C16*/
;                        insert[1] = error_low_letter;                   /*C16*/
;                        insert[2] = c('-');                             /*C16*/
;                        insert[3] = error_high_letter;                  /*C16*/
;                        display(error_23);                              /*C16*/
;                        }                                               /*C16*/
;                    else                                                /*C16*/
;                        {                                               /*C16*/
;                        insert[0] = error_low_letter;                   /*C16*/
;                        insert[1] = c('-');                             /*C16*/
;                        insert[2] = error_high_letter;                  /*C16*/
;                        display(error_31);                              /*C16*/
;                        }                                               /*C16*/
;                    input = c(' ');                                     /*C16*/
;                    }                                                   /*C16*/
;                VIOWRTCHARSTRATT(input_ptr,u(1),row,col,attribute_ptr,u(0)); /*C16*/
;                default_used = FALSE;
;                input_value = input;
;                break;
;                END
;            END
;        END
;    return(input);
;END
		
get_alpha_input:
		; 02/01/2019

	;%define gai_input_value   bp-16
	%define gai_attributeptr   bp-14
	;%define gai_attributeptr2 bp-12
	%define gai_input_value    bp-10
	;%define gai_default_used  bp-10
	%define gai_input_ptr	   bp-8
	;%define gai_input_ptr2	   bp-6
	%define gai_attribute	   bp-4
	%define gai_input	   bp-2

	%define ga_i_low_letter	   bp+4
	%define ga_i_high_letter   bp+6
	%define ga_i_row	   bp+8
	%define ga_i_col	   bp+10
	%define ga_i_err_low_lett  bp+12
	%define ga_i_err_high_lett bp+14

		push	bp
		mov	bp,sp
		;sub	sp,16
		sub	sp,14

		lea	ax,[gai_attribute]
		mov	[gai_attributeptr],ax
		mov	[gai_attributeptr+2],ss
		lea	cx,[gai_input]
		mov	[gai_input_ptr],cx
		mov	[gai_input_ptr+2],ss
		
		cmp	byte [mono_flag],1 ; TRUE
		jne	short gai_1
		mov	byte [gai_attribute],0Fh ;HIWHITE_ON_BLACK
		jmp	short gai_2
gai_1:
		mov	byte [gai_attribute],1Fh ;HIWHITE_ON_BLUE
gai_2:
		sub	al,al  ;0

		;/* Assume bad input */

		mov	[valid_input],al ; 0
gai_3:
		;/* Init input_value to something non-alpha */

		mov	[gai_input_value],al ; 0
gai_4:
		;/* Loop until we get good stuff */

		cmp	byte [valid_input],0 ; FALSE
		;je	short gai_5
		;jmp	gai_17 
		jne	short gai_17 ; 03/01/2019
gai_5:
		;/* position the cursor */

		;push	word [ga_i_row]
		;push	word [ga_i_col]
		;sub	ax,ax
		;push	ax

		mov	dh,[ga_i_row]
		mov	dl,[ga_i_col]

		call	VIOSETCURPOS

	;/* Flush the keyboard buffer and get the next pressed key */

		call	get_char_input
		;mov	[gai_input],al
		;push	ax
		call	dos_upper ; ***
		;pop	bx
		mov	[gai_input],al
		
		;/* Go handle different inputs */

		cbw
		mov	bx,ax ; bl = [gai_input]

		;switch(input)

		;cbw
		;sub	ax,0Dh
		sub	al,0Dh ; sub al,13
		jz	short gai_9 ; 13, CR
		;sub	ax,0Eh
		sub	al,0Eh ; sub al,14
		jz	short gai_8 ; 27, ESC 

		;mov	al,[gai_input]
		;cbw
		;mov	bx,ax

		test	byte [isdigit+bx],3
		;jz	short gai_6
		jz	gai_14

		;;push	ax
		;call	dos_upper
		;;pop	bx
		
		;cmp	al,[ga_i_low_letter]
		cmp	bl,[ga_i_low_letter]
		jl	short gai_6
		;;mov	al,[gai_input]
		;;push	ax
		;call	dos_upper
		;;pop	bx
		;cmp	al,[ga_i_high_letter]
		cmp	bl,[ga_i_high_letter]
		jle	short gai_7
gai_6:
		jmp	gai_13
gai_7:
		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	cx,cx
		push	cx
		push	ax
		call	clear_screen
		;add	sp,8
		
		jmp	gai_16
		
		; 03/01/2019
gai_17:
		;mov	al,[gai_input]
		mov	sp,bp
		pop	bp
		;retn
		retn	12

;gai_8:
;		mov	byte [valid_input],1
;		;jmp	short gai_4
;		mov	al,bl ; mov al,[gai_input]
;		jmp	short gai_17
gai_9:
		;/* See if it is digit and between given letters*/
		;/* Do world trade get country information */

		mov	al,[gai_input_value]

		; (AL has already uppercase character) ; ***
		; (gai_5 -> gai_7 -> gai_16 -> gai_3 -> gai_5 -> gai_9)
		;;push	ax
		;call	dos_upper
		;;pop	bx

		;if (isalpha(input))

		mov	[gai_input],al ; the char just prior to CR
		cbw
		mov	bx,ax
		test	byte [isdigit+bx],3
		;jz	short gai_10
		jz	short gai_11

		mov	al,[ga_i_low_letter]
		;cmp	[gai_input],al
		cmp	bl,al
		jl	short gai_10
		mov	al,[ga_i_high_letter]
		;cmp	[gai_input],al	
		cmp	bl,al
		jg	short gai_10
		
		;mov	al,[gai_input_value]
		;cbw
		;mov	bx,ax
		;test	[isdigit+bx],3
		;jnz	short gai_8

		;jmp	short gai_8
gai_8:
		mov	byte [valid_input],1 ; TRUE
		;jmp	short gai_4
		mov	al,bl ; mov al,[gai_input]
		jmp	short gai_17 ; 03/01/2019
gai_10:
		;/* Setup error message */    

		;mov	al,[gai_input_value]
		;cbw
		;mov	bx,ax
		;test	[isdigit+bx],3
		;jz	short gai_11
		
		mov	al,[gai_input]
		mov	[insert],al
		mov	al,[ga_i_err_low_lett]
		mov	[insert+1],al
		mov	byte [insert+2],'-'
		mov	al, [ga_i_err_high_lett]
		mov	[insert+3],al
		;push	word [error_23_seg]
		push	ds
		push	word [error_23_off]
		jmp	short gai_12
gai_11:
		mov	al,[ga_i_err_low_lett]
		mov	[insert],al
		mov	byte [insert+1],'-'
		mov	al,[ga_i_err_high_lett]
		mov	[insert+2],al
		;push	word [error_31_seg]
		push	ds
		push	word [error_31_off]
gai_12:
		call	display
		;pop	bx
		;pop	bx
		; 03/01/2019
		;jmp	gai_4
		jmp	gai_5 ; [valid_input] = 0
gai_13:
		;;mov	al,[gai_input]
		;;cbw
		;;mov	bx,ax
		;mov	bl,[gai_input]
		;xor	bh,bh
		;test	byte [isdigit+bx],3
		;jz	short gai_14

		;/* Setup error message */        

		;mov	[insert],al
		mov	[insert],bl
		mov	al,[ga_i_err_low_lett]
		mov	[insert+1],al
		mov	byte [insert+2],'-'
		mov	al,[ga_i_err_high_lett]
		mov	[insert+3],al
		;push	word [error_23_seg]
		push	ds
		push	word [error_23_off]
		jmp	short gai_15
gai_14:
		mov	al,[ga_i_err_low_lett]
		mov	[insert],al
		mov	byte [insert+1],'-'
		mov	al,[ga_i_err_high_lett]
		mov	[insert+2],al
		;push	word [error_31_seg]
		push	ds
		push	word [error_31_off]
gai_15:
		call	display
		;pop	bx
		;pop	bx
		mov	byte [gai_input],' '
gai_16:
	;VIOWRTCHARSTRATT(input_ptr,u(1),row,col,attribute_ptr,u(0));

		push	word [gai_input_ptr+2]
		push	word [gai_input_ptr]
		mov	ax,1
		push	ax
		push	word [ga_i_row]
		push	word [ga_i_col]
		push	word [gai_attributeptr+2]
		push	word [gai_attributeptr]
		;sub	ax,ax
		;push	ax
		call	VIOWRTCHARSTRATT
		;mov	byte [gai_default_used],0  ;FALSE
		mov	al,[gai_input]
		jmp	gai_3
;gai_17:
;		;mov	al,[gai_input]
;		mov	sp,bp
;		pop	bp
;		;retn
;		retn	12

; ----------------------------------------------------------------------------
; rempart.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 02/01/2019)

;void remove_partition(drive,entry)
;
;char        drive;
;unsigned    entry;
;
;BEGIN
;
;    /* Set Partition entry to zero */
;    part_table[drive][entry].boot_ind = uc(0);
;    part_table[drive][entry].start_head = uc(0);
;    part_table[drive][entry].start_sector = uc(0);
;    part_table[drive][entry].start_cyl = u(0);
;    part_table[drive][entry].sys_id = uc(0);
;    part_table[drive][entry].end_head = uc(0);
;    part_table[drive][entry].end_sector = uc(0);
;    part_table[drive][entry].end_cyl = u(0);
;    part_table[drive][entry].rel_sec = ul(0);
;    part_table[drive][entry].num_sec = ul(0);
;    part_table[drive][entry].changed = (FLAG)TRUE;
;    part_table[drive][entry].mbytes_used = f(0);
;    part_table[drive][entry].percent_used = u(0);
;
;    strcpy(part_table[drive][entry].system,c(NUL));
;    strcpy(part_table[drive][entry].vol_label,c(NUL));
;
;    return;
;END

remove_partition:
		; 02/01/2019

	;%define rmp_drive bp+4
	;%define rmp_entry bp+6

		;push	bp
		;mov	bp,sp
		;push	si

		; INPUT:
		;   AL = Disk number (0 to 7)
		;   AH = Partition entry number (0 to 3)

		;mov	al,[rmp_drive]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,[rmp_entry]

		shl	al,1
		shl	al,1
		add	al,ah

		;mov	cx,46
		;mul	cx

		mov	cl,46
		mul	cl		
		mov	bx,ax
		;sub	al,al
		sub	ax,ax
		mov	[part_table_boot_ind+bx],al
		mov	[part_table_start_head+bx],al
		mov	[part_table_start_sector+bx],al
		mov	[part_table_start_cyl+bx],ax ; 0
		mov	[part_table_sys_id+bx],al
		mov	[part_table_end_head+bx],al
		mov	[part_table_end_sector+bx],al
		mov	[part_table_end_cyl+bx],ax ; 0
		;sub	ax,ax
		mov	[part_table_rel_sec_hw+bx],ax
		mov	[part_table_rel_sec_lw+bx],ax
		mov	[part_table_num_sec_hw+bx],ax
		mov	[part_table_num_sec_lw+bx],ax
		mov	byte [part_table_changed+bx],1
		mov	[part_table_mbytes_used+bx],ax
		mov	[part_table_percent_used+bx],ax

		;push	ax
		;mov	cx,bx
		;add	bx,part_table_system
		;push	bx
		;mov	si,cx
		;call	strcpy
		;pop	bx
		;pop	bx

		;sub	ax,ax
		;push	ax
		;add	si,part_table_vol_label
		;push	si
		;call	strcpy
		;pop	bx
		;pop	bx

		; 02/01/2019
		;xor	al,al
		;push	ds
		;pop	es
		mov	di,part_table_vol_label
		add	di,bx
		mov	cx,12+9 ; 21
		rep	stosb
		retn		

		;pop	si
		;mov	sp,bp
		;pop	bp
		;retn
		;retn	4

; ----------------------------------------------------------------------------
		
;void remove_volume(drive,entry)
;
;char        drive;
;unsigned    entry;
;
;BEGIN
;
;    /* Set volume entry to zero */
;    ext_table[drive][entry].boot_ind = uc(0);
;    ext_table[drive][entry].start_head = uc(0);
;    ext_table[drive][entry].start_sector = uc(0);
;    ext_table[drive][entry].start_cyl = u(0);
;    ext_table[drive][entry].sys_id = uc(0);
;    ext_table[drive][entry].end_head = uc(0);
;    ext_table[drive][entry].end_sector = uc(0);
;    ext_table[drive][entry].end_cyl = u(0);
;    ext_table[drive][entry].rel_sec = ul(0);
;    ext_table[drive][entry].num_sec = ul(0);
;    ext_table[drive][entry].mbytes_used = f(0);
;    ext_table[drive][entry].percent_used = u(0);
;    ext_table[drive][entry].changed = TRUE;
;    ext_table[drive][entry].drive_letter = NUL;
;
;    strcpy(ext_table[drive][entry].system,c(NUL));
;    strcpy(ext_table[drive][entry].vol_label,c(NUL));
;
;    return;
;END

remove_volume:
		; 02/01/2019

	;%define rmv_drive bp+4
	;%define rmv_entry bp+6

		;push	bp
		;mov	bp,sp
		;push	si

		; INPUT:
		;   AL = Disk number (0 to 7)
		;   CL = Partition entry number (0 to 3)

		;mov	al,24
		;imul	byte [rmv_drive]

		mov	ah,24
		mul	ah
		add	al,cl
		
		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		;sub	al,al
		sub	ax,ax
		mov	[ext_table_boot_ind+bx],al
		mov	[ext_table_start_head+bx],al
		mov	[ext_table_start_sector+bx],al
		mov	[ext_table_start_cyl+bx],ax ; 0
		mov	[ext_table_sys_id+bx],al
		mov	[ext_table_end_head+bx],al
		mov	[ext_table_end_sector+bx],al
		mov	[ext_table_end_cyl+bx],ax ; 0
		;sub	ax,ax
		mov	[ext_table_rel_sec_hw+bx],ax
		mov	[ext_table_rel_sec_lw+bx],ax
		mov	[ext_table_num_sec_hw+bx],ax
		mov	[ext_table_num_sec_lw+bx],ax
		mov	[ext_table_mbytes_used+bx],ax
		mov	[ext_table_percent_used+bx],ax
		mov	byte [ext_table_changed+bx],1
		mov	[ext_table_drive_letter+bx],ax ; 0
		
		;push	ax
		;mov	cx,bx
		;add	bx,ext_table_system
		;push	bx
		;mov	si,cx
		;call	strcpy
		;pop	bx
		;pop	bx

		;sub	ax,ax
		;push	ax
		;add	si,ext_table_vol_label
		;push	si
		;call	strcpy
		;pop	bx
		;pop	bx

		; 02/01/2019
		;xor	al,al
		;push	ds
		;pop	es
		mov	di,ext_table_vol_label
		add	di,bx
		mov	cx,12+9 ; 21
		rep	stosb
		retn		

		;pop	si
		;mov	sp,bp
		;pop	bp
		;retn
		;retn	4

; ----------------------------------------------------------------------------
; partinfo.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 02/01/2019)

;char get_num_logical_dos_drives()
;BEGIN
;
;char   i;
;char number;
;
;   number = c(0);
;   /* See if there is a logical drive defined in Extended Partition */
;   for (i = c(0); i < c(23);i++)
;      BEGIN
;        /* See if we find a sys id that is DOS */
;       if ((ext_table[cur_disk][i].sys_id == uc(DOS12)) || (ext_table[cur_disk][i].sys_id == uc(DOS16)) ||
;          (ext_table[cur_disk][i].sys_id == uc(DOSNEW))) 
;          BEGIN
;           number++;
;          END
;      END
;    return(number);
;END

get_num_logical_dos_drives:
		
		; 02/01/2019

	;%define gnldd_i      bp-4
	;%define gnldd_number bp-2

		;push	bp
		;mov	bp,sp
		;sub	sp,4

		;sub	al,al
		;mov	[gnldd_number],al
		;mov	[gnldd_i], al
		
		xor	dx,dx  ; 0
		;jmp	short gnldd_4
gnldd_1:
		;mov	al,[gnldd_i]
;gnldd_4:
		;cbw
		;mov	cx,ax
		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]
		;add	ax,cx
		add	al,dl ; [gnldd_i]
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		mov	al,[ext_table_sys_id+bx]
		;cmp	byte [ext_table_sys_id+bx],1 ; DOS12
		cmp	al,1
		je	short gnldd_2
		;cmp	byte [ext_table_sys_id+bx],4 ; DOS16
		cmp	al,4
		je	short gnldd_2
		;cmp	byte [ext_table_sys_id+bx],6 ; DOSNEW (FAT16 big)
		cmp	al,6
		jne	short gnldd_3
gnldd_2:
		;inc	byte [gnldd_number]
		inc	dh
gnldd_3:
		;inc	byte [gnldd_i]
		inc	dl
;gnldd_4:
		;cmp	byte [gnldd_i],23
		cmp	dl,23
		jl	short gnldd_1

		;mov	al,[gnldd_number]

		mov	al,dh ; [gnldd_number]

		;xor	dx,dx

		;mov	sp,bp
		;pop	bp

		retn

; ============================================================================
;  CREATE PARTITION
; ============================================================================
; 13/01/2019

; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/* Screen for CREATE_PARTITION                                                                     */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                  Create DOS Partition or Logical DOS Drive                     |menu_8    */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Choose one of the following:                                                |menu_3 #  */
;/*   09|                                                                                |          */
;/*   10|    1.  Create Primary DOS Partition                                            |menu_9    */
;/*   11|    2.  Create Extended DOS Partition                                           |menu_9    */
;/*   12|    3.  Create logical DOS Drive(s) in the Extended DOS Partition               |menu_10   */
;/*   13|                                                                                |          */
;/*   14|                                                                                |          */
;/*   15|                                                                                |          */
;/*   16|                                                                                |          */
;/*   17|    Enter choice: [ ]                                                           |menu_7 #  */
;/*   18|                                                                                |          */
;/*   19|                                                                                |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */
;/*                                                                                                 */
;/***************************************************************************************************/

; ----------------------------------------------------------------------------
; c_menus.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 13/01/2019)

;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: CREATE_PARTITION                           */
;/*                                                             */
;/* DESCRIPTIVE NAME: Create DOS related partition(s)           */
;/*                                                             */
;/* FUNCTION:                                                   */
;/*      This routine verifies if there are free partitions,    */
;/*      posts an status message if there is not, otherwise     */
;/*      prints a screen asking what type of partition to       */
;/*      be created, and passes control to the requested        */
;/*      function.                                              */
;/*                                                             */
;/* NOTES: This is a screen control module only, no data is     */
;/*        modified. Routine also will only allow 1 DOS and     */
;/*        1 Ext DOS partitions per disk, if one already exists,*/
;/*        then status message is displayed when the create     */
;/*        option for that type partition is selected           */
;/*                                                             */
;/*        The following screen in managed                      */
;/*                                                             */
;/*       |0000000000111111111122222222223333333333|            */
;/*       |0123456789012345678901234567890123456789|            */
;/*     --|----------------------------------------|            */
;/*     00|                                        |            */
;/*     01|                                        |            */
;/*     02|                                        |            */
;/*     03|                                        |            */
;/*     04|Create DOS Partition                    |            */
;/*     05|                                        |            */
;/*     06|Current Fixed Disk Drive: #             |            */
;/*     07|                                        |            */
;/*     08|Choose one of the following:            |            */
;/*     09|                                        |            */
;/*     10|    1.  Create Primary DOS partition    |            */
;/*     11|    2.  Create EXTENDED DOS partition   |            */
;/*     12|    3.  Create logical DOS drive(s) in  |            */
;/*     13|        the EXTENDED DOS partition      |            */
;/*     14|                                        |            */
;/*     15|                                        |            */
;/*     16|                                        |            */
;/*     17|                                        |            */
;/*     18|Enter choice: [ ]                       |            */
;/*     19|                                        |            */
;/*     20|                                        |            */
;/*     21|                                        |            */
;/*     22|                                        |            */
;/*     23|Press ESC to return to FDISK Options    |            */
;/*     --------------------------------------------            */
;/*                                                             */
;/* ENTRY POINTS: create_partition                              */
;/*      LINKAGE: create_partition();                           */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if case statement   */
;/*             failure when branching to requested function    */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      find_free_partition                                    */
;/*      dos_create_partition                                   */
;/*      ext_create_partition                                   */
;/*      volume_create                                          */
;/*      internal_program_error                                 */
;/*      find_partition_type                                    */
;/*      get_num_input                                          */
;/*      display                                                */
;/*      wait_for_ESC                                           */
;/*      clear_screen                                           */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void create_partition()
;
;BEGIN
;
;char   input;
;char   default_value;
;char   max_input;
;
;    input = c(NUL);                                                    /* AC000 */
;    clear_screen(u(0),u(0),u(24),u(79));                               /* AC000 */
;    /* put up heading and ESC */
;    display(menu_8);
;    display(menu_11);
;
;    /* Setup current drive msg */
;    insert[0]=cur_disk+1+'0';
;    display(menu_5);
;
;    /* See if there are free partitions */
;    /* SR; 9/26/89; This check should be done only if the user asks to
;       create a primary or extended partition and not for logical volumes */
;
;        /* display menu */
;        display(menu_3);                                               /* AN000 */
;        display(menu_9);
;
;        /* ############# ADD CODE HERE FOR THIS FUNCTION ############## */
;        /* Do something about highlighting the available options and    */
;        /* setting up defaults                                          */
;        default_value = c(1);                                          /* AC000 */
;        /* ############################################################ */
;        /* setup default for prompt */
;        insert[0] = c('1');                                            /* AC000 */
;        display(menu_7);
;        display(menu_10);
;
;        max_input = c(3);                                              /* AC000 */
;
;        input = get_num_input(default_value,max_input,input_row,input_col);
;
;        /* SR; 9/26/89; We check here for the extended volume creation case
;           and remove it from the switch statement */
;
;        if (input == '3')
;           {       /* Create a volume */
;            if (find_partition_type(uc(EXTENDED)))
;                volume_create();
;            else
;               {
;                display(error_35);
;                clear_screen(u(17),u(0),u(17),u(79));
;                wait_for_ESC();
;               }
;           }
;        else if (find_free_partition() != ((char)(NOT_FOUND)))
;           {
;            /* Go branch to the requested function */
;            switch(input)
;               BEGIN
;                case '1':
;                    dos_create_partition();
;                    break;
;
;            	case '2':
;                    if ((cur_disk >= c(1)) || (find_partition_type(uc(DOS12))) || (find_partition_type(uc(DOS16))) ||
;                        (find_partition_type(uc(DOSNEW))))                   /* AN000 */             /* AC000 */
;                    	ext_create_partition();
;                    else
;                       BEGIN                                               /* AN000 */
;                    	/* don't have a primary partition yet, can't create an ext */
;                    	display(error_19);                                  /* AN000 */
;                    	clear_screen(u(17),u(0),u(17),u(79));               /* AN000 */
;                    	wait_for_ESC();                                     /* AN000 */
;                       END                                                 /* AN000 */
;                    break;
;
;                case ESC:
;                    break;
;
;                default:
;                    internal_program_error();
;                    break;
;
;               END
;           }
;        else
;           {
;            /* Display prompt telling there is no avail partition */
;            display(error_10);
;            input = wait_for_ESC();
;           }
;    /* clear the screen before going back to main menu */
;    clear_screen(u(0),u(0),u(24),u(79));                               /* AC000 */
;    return;
;END

create_partition:
		; 13/01/2019

		;push	bp
		;mov	bp,sp
		;sub	sp,6

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;/* put up heading and ESC */
		
		;push	word [menu_8_segment]
		push	ds
		push	word [menu_8_offset]
		call	display
		;pop	bx
		;pop	bx

		;push	word [menu_11_segment]
		push	ds
		push	word [menu_11_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup current drive msg */

		mov	al,[cur_disk]
		add	al,'1'
		mov	byte [insert],al
		
		;push	word [menu_5_segment]
		push	ds
		push	word [menu_5_offset]
		call	display
		;pop	bx
		;pop	bx

		;push	word [menu_3_segment]
		push	ds
		push	word [menu_3_offset]
		call	display
		;pop	bx
		;pop	bx
		
		;push	word [menu_9_segment]
		push	ds
		push	word [menu_9_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* setup default for prompt */

		mov	byte [insert],'1'
		
		;push	word [menu_7_segment]
		push	ds
		push	word [menu_7_offset]
		call	display
		;pop	bx
		;pop	bx

		;push	word [menu_10_segment]
		push	ds
		push	word [menu_10_offset]
		call	display
		;pop	bx
		;pop	bx

	;input = get_num_input(default_value,max_input,input_row,input_col);

		push	word [input_col]
		push	word [input_row]
		mov	al,3
		push	ax
		mov	al,1
		push	ax
		call	get_num_input
		;add	sp,8
		;mov	[cp_input],al
		
		mov	[_input],al

		;if (input == '3')

		cmp	al,'3'
		jne	short cp_2

		;/* Create a volume */

		mov	al,5 ; EXTENDED
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al, al
		;jz	short cp_1
		jc	short cp_1		

		call	volume_create
		jmp	case_crea_part_break
cp_1:
		;push	word [error_35_seg]
		push	ds
		push	word [error_35_off]
		jmp	short cp_9

	;else if (find_free_partition() != ((char)(NOT_FOUND)))
cp_2:
		call	find_free_partition
		inc	al
		jz	short cp_10 ; NOT FOUND

		;/* Go branch to the requested function */
switch_input7:
		;mov	al,[cp_input]
		mov	al,[_input]
		;cbw
		;cmp	ax,'2'
		cmp	al,'2'
		je	short case_crea_part_2 ; Create EXTENDED DOS partition
		ja	short case_crea_part_DEF

		sub	al,1Bh ; ESC
		jz	short case_crea_part_break ; ESCape key

		sub	al,16h ; '1'
		jz	short case_crea_part_1 ; Create primary DOS partition
case_crea_part_DEF:
		call	internal_program_error
		jmp	short case_crea_part_break
case_crea_part_1:
		call	dos_create_partition
		jmp	short case_crea_part_break
case_crea_part_2:
cp_6:  ; 25/01/2019
		cmp	byte [cur_disk],1
		;jge	short cp_7
		jnb	short cp_7
		
		mov	al,1 ; DOS12  ; FAT 12
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short cp_7
		jnc	short cp_7		

		mov	al,4 ; DOS16  ; FAT 16
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short cp_7
		jnc	short cp_7		
 
		mov	al,6 ; DOSNEW  ; FAT 16 big
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al, al
		;jz	short cp_8
		jc	short cp_8
cp_7:
		call	ext_create_partition
		jmp	short case_crea_part_break
cp_8:
	;/* don't have a primary partition yet, can't create an ext */	
		;push	word [error_19_seg]
		push	ds
		push	word [error_19_off]
cp_9:
		call	display
		;pop	bx
		;pop	bx

		mov	ax,79
		push	ax
		mov	ax,17
		push	ax
		sub	cx,cx
		push	cx
		push	ax
		call	clear_screen
		;add	sp,8

		jmp	short cp_11
cp_10:
	;/* Display prompt telling there is no avail partition */

		;push	word [error_10_seg]
		push	ds
		push	word [error_10_off]
		call	display
		;pop	bx
		;pop	bx
cp_11:
		call	wait_for_ESC

case_crea_part_break:
	;/* clear the screen before going back to main menu */

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen

		;call	CLS

		;mov	sp,bp
		;pop	bp
		;retn

		jmp	CLS

;/***************************************************************************************************/
;/*  Screen for DOS_CREATE_PARTITION                                                                */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                           Create Primary DOS Partition                         |menu_12   */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Do you wish to use the maximum available size for a Primary DOS Partition   |menu_13   */
;/*   09|    and make the partition active (Y/N).....................? [Y]               |menu_13   */
;/*   10|                                                                                |          */
;/*   11|                                                                                |          */
;/*   12|                                                                                |          */
;/*   13|                                                                                |          */
;/*   14|                                                                                |          */
;/*   15|                                                                                |          */
;/*   16|                                                                                |          */
;/*   17|                                                                                |          */
;/*   18|                                                                                |          */
;/*   19|                                                                                |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */
;/*                                                                                                 */
;/***************************************************************************************************/

; c_menus.c (MSDOS 6.0)
;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: DOS_CREATE_PARTITION                       */
;/*                                                             */
;/* DESCRIPTIVE NAME: Create default DOS partition on disk      */
;/*                                                             */
;/* FUNCTION: User is prompted to see if he wishes to use to    */
;/*           set up a DOS partition in the maximum available   */
;/*           size (limited to 32mb). If option is selected     */
;/*           than partition is created and marked active. The  */
;/*           partition is scanned to insure there are enough   */
;/*           contiguous good sectors for DOS.                  */
;/*                                                             */
;/* NOTES: Screen can be exited via the ESC command before      */
;/*        partition is created and nothing will change         */
;/*                                                             */
;/*        The following screen is managed:                     */
;/*                                                             */
;/*       |0000000000111111111122222222223333333333|            */
;/*       |0123456789012345678901234567890123456789|            */
;/*     --|----------------------------------------|            */
;/*     00|                                        |            */
;/*     01|                                        |            */
;/*     02|                                        |            */
;/*     03|                                        |            */
;/*     04|Create DOS Partition                    |            */
;/*     05|                                        |            */
;/*     06|Current Fixed Disk Drive: #             |            */
;/*     07|                                        |            */
;/*     08|Do you wish to use the maximum size     |            */
;/*     09|for a DOS partition and make the DOS    |            */
;/*     10|partition active (Y/N).........? [Y]    |            */
;/*     11|                                        |            */
;/*     12|                                        |            */
;/*     13|                                        |            */
;/*     14|                                        |            */
;/*     15|                                        |            */
;/*     16|                                        |            */
;/*     17|                                        |            */
;/*     18|                                        |            */
;/*     19|                                        |            */
;/*     20|                                        |            */
;/*     21|                                        |            */
;/*     22|                                        |            */
;/*     23|Press ESC to return to FDISK Options    |            */
;/*     --------------------------------------------            */
;/*                                                             */
;/* ENTRY POINTS: dos_create_partition                          */
;/*      LINKAGE: dos_create_partition();                       */
;/*               NEAR CALL                                     */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if case statement   */
;/*             failure when branching to requested function    */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      display                                                */
;/*      get_yn_input                                           */
;/*      wait_for_ESC                                           */
;/*      input_dos_create                                       */
;/*      make_partition                                         */
;/*      check_bad_tracks                                       */
;/*                                                             */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void dos_create_partition()
;
;BEGIN
;
;    char   input;
;    char   temp;
;    char   second_disk_flag;                                            /* AN000 */
;
;    /* SR; 9/26/89; These variables are added for the various fixes */
;
;    unsigned long total_sectors;
;    unsigned char  i;
;    char  defined_drives;
;    char  temp_cur_disk;
;
;    second_disk_flag = (FLAG)FALSE;                                     /* AN000 */
;    input = c(NUL);                                                     /* AC000 */
;    /* clear off screen */
;    clear_screen(u(0),u(0),u(24),u(79));                                /* AC000 */
;
;    /* Put up header */
;    display(menu_12);
;
;    /* Set up current disk message */
;    insert[0] = cur_disk+1+'0';
;    display(menu_5);
;
;    /* Display ESC prompt */
;    display(menu_11);
;
;    /* See if already exists */
;    if ((!find_partition_type(uc(DOS12))) && (!find_partition_type(uc(DOS16))) && (!find_partition_type(uc(DOSNEW))))  /* AC000 */
;
;       BEGIN
;
;        /* SR; 9/26/89; Ported from Olivetti fix. The min. no. of sectors
;           in a partition must be >64 for BIOS to recognize the drive */
;
;       temp = find_part_free_space(c(PRIMARY));
;       total_sectors = (long)free_space[temp].space * max_sector[cur_disk] * max_head[cur_disk];
;       if (total_sectors < 64)
;          {
;           display(error_10);      /**** No room on disk */
;           input = wait_for_ESC();
;           return;  /*C06*/
;          }
;        /* SR; 9/26/89; We do not allow creation of a drive on the second
;           hard disk if there are already 23 drives on the 1st hard disk */
;        else                   /*C07*/
;           {
;            defined_drives = c(0);
;            temp_cur_disk = cur_disk;
;
;            /* Search both drives for defined drives */
;            for (i = 0; i < number_of_drives; i++)
;               {
;                cur_disk = (c(i));
;
;                /* See if there is a primary drive letter */
;                if ((find_partition_type(uc(DOS12))) ||
;                    (find_partition_type(uc(DOS16))) ||
;                    (find_partition_type(uc(DOSNEW))))
;                    defined_drives++;
;
;                /* See if extended partition on disk */
;                if (find_partition_type(uc(EXTENDED)))
;                    /* Get number of logical drives */
;                    defined_drives += get_num_logical_dos_drives();
;               }
;            /* Restore cur_disk to original */
;            cur_disk = temp_cur_disk;
;
;            /* See if 26 or less drives total */
;            if (defined_drives > c(23))
;               /* Reached the maximum */
;               {
;                clear_screen(u(16),u(0),u(23),u(79));
;                display(error_27);
;                input = wait_for_ESC();
;                return;
;               }
;           }
;
;        /* Display prompt, depending on what disk */
;        if (cur_disk == c(0))                                           /* AC000 */
;            /* Put up make active partition message */
;            display(menu_13);
;        else
;            BEGIN
;            /* Second disk, so dont put up prompt mentioning active partition */
;            second_disk_flag = (FLAG)TRUE;                              /* AN000 */
;            display(menu_45);                                           /* AC000 */
;            END
;        /* Get Y/N input */
;        input = get_yn_input(c(Yes),input_row,input_col);               /* AC000 AC011 */
;
;        /* Go handle input */
;        switch(input)
;            BEGIN
;            case 1:                                                     /* AC000 */
;                if ( second_disk_flag == (FLAG)FALSE)
;                    BEGIN
;                    /* Go get the biggest area left */
;                    temp = find_part_free_space(c(PRIMARY));            /* AC000 */
;                    make_partition(free_space[temp].space,temp,uc(ACTIVE),c(PRIMARY)); /* AC000 */
;                    reboot_flag = (FLAG)TRUE;                           /* AC000 */
;                    if (number_of_drives == uc(1))                      /* AN000 */
;                        BEGIN                                           /* AN000 */
;                        write_info_to_disk();
;                        reboot_system();                                /* AC000 */
;                        END                                             /* AN000 */
;                    clear_screen(u(16),u(0),u(23),u(79));               /* AN000 */
;
;                    display(status_12);                                 /* AN000 */
;                    wait_for_ESC();
;                    break;
;                    END
;                else
;                    BEGIN                                               /* AN000 */
;                    /* Go get the biggest area left */                  /* AN000 */
;                    temp = find_part_free_space(c(PRIMARY));            /* AN000 */
;                    make_partition(free_space[temp].space,temp,uc(NUL),c(PRIMARY)); /* AN000 */
;                    reboot_flag = (FLAG)TRUE;                           /* AN000 */
;                    clear_screen(u(16),u(0),u(23),u(79));               /* AN000 */
;
;                    display(status_12);                                 /* AN000 */
;                    wait_for_ESC();
;                    break;
;                    END
;
;            case  0:
;                input_dos_create();                               /* AC000 */
;                break;
;
;            case ESC:
;                break;   /* take no action */
;
;            default:
;                internal_program_error();
;            END
;        END
;    else
;        BEGIN
;        /* Display partition table-it will return if no partitions there */
;        table_display();
;
;        /* Primary partition already exists message */
;        display(error_8);
;        wait_for_ESC();
;        END
;   return;
;END

; 13/01/2019
struc f
.space: resw 1
.start: resw 1
.end:   resw 1
endstruc

dos_create_partition:
		; 13/01/2019

	%define second_disk_flag bp-16
	%define defined_drives	 bp-14
	%define cdp_i		 bp-12
	%define temp_cur_disk	 bp-10
	%define cdp_temp	 bp-8

		push	bp
		mov	bp,sp
		sub	sp,16
		push	si
		sub	al,al
		mov	[second_disk_flag],al

		;/* clear off screen */		

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;/* Put up header */

		;push	word [menu_12_segment]
		push	ds
		push	word [menu_12_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Set up current disk message */

		mov	al,[cur_disk]
		add	al,'1'
		mov	[insert],al

		;push	word [menu_5_segment]
		push	ds
		push	word [menu_5_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Display ESC prompt */

		;push	word [menu_11_segment]
		push	ds
		push	word [menu_11_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* See if already exists */

		mov	al,1 ; DOS12 ; FAT12
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short cdp_1
		jnc	short cdp_1

		mov	al,4 ; DOS16 ; FAT16
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short cdp_1
		jnc	short cdp_1

		mov	al,6 ; DOSNEW ; FAT16 big
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short cdp_2
		jc	short cdp_2
cdp_1:
		jmp	cdp_19
cdp_2:
;	temp = find_part_free_space(c(PRIMARY));
;       total_sectors = (long)free_space[temp].space * max_sector[cur_disk] * max_head[cur_disk];

		xor	al,al ; 14/01/2019
		;push	ax
		call	find_part_free_space
		;pop	bx
		mov	[cdp_temp],al

		mov	al,[cur_disk]
		cbw
		mov	bx,ax
		mov	al,[max_sector+bx]
		sub	ah,ah
		sub	dx,dx
		push	dx  ; multiplier_hw	
		push	ax  ; multiplier_lw
		;mov	al,22
		mov	al,10 ; 14/01/2019
		;imul	byte [cdp_temp]
		mul	byte [cdp_temp]
		mov	si,ax
		mov	ax,[free_space.space+si]
		shl	bx,1
		mul	word [max_head+bx]
		push	dx ; multiplicand_hw
		push	ax ; multiplicand_lw
		call	mul32
			; DX:AX =  Total (available partition) sectors (of free space)

		; if (total_sectors < 64)

		or	dx,dx
		jnz	short cdp_3

		cmp	ax,64
		jnb	short cdp_3

		;/**** No room on disk */

		;push	word [error_10_seg]
		push	ds
		push	word [error_10_off]
		jmp	cdp_20
cdp_3:
		mov	byte [defined_drives],0
		mov	al,[cur_disk]
		mov	[temp_cur_disk],al
		mov	byte [cdp_i],0
		jmp	short cdp_8
cdp_4:
		;/* See if there is a primary drive letter */

		mov	al,[cdp_i]
		mov	[cur_disk],al
		mov	al,1 ; DOS12
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al, al
		;jnz	short cdp_5
		jnc	short cdp_5

		mov	al, 4 ; DOS16
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al, al
		;jnz	short cdp_5
		jnc	short cdp_5
		
		mov	al,6
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al, al
		;jz	short cdp_6
		jc	short cdp_6
cdp_5:
		inc	byte [defined_drives]
cdp_6:
		; /* See if extended partition on disk */

		mov	al,5 ; EXTENDED
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al, al
		;jz	short cdp_7
		jc	short cdp_7

		call	get_num_logical_dos_drives
		add	[defined_drives],al
cdp_7:
		inc	byte [cdp_i]
cdp_8:
		;/* Search both drives for defined drives */

		mov	al,[number_of_drives]
		cmp	[cdp_i],al
		jb	short cdp_4

		;/* Restore cur_disk  to original */

		mov	al,[temp_cur_disk]
		mov	[cur_disk],al

	; We do not allow creation of a drive on the second
	; hard disk if there are already 23 drives on the 1st hard disk */

  		;/* See if 26 or less drives total */
            	; if (defined_drives > c(23))

		cmp	byte [defined_drives],23
		jle	short cdp_9

		;/* Reached the maximum */

		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,16
		push	ax
		call	clear_screen
		;add	sp,8

		;push	word [error_27_seg]
		push	ds
		push	word [error_27_off]
		jmp	cdp_20
cdp_9:
		;/* Display prompt, depending on what disk */

		cmp	byte [cur_disk],0
		jne	short cdp_10
		;push	word [menu_13_segment]
		push	ds
		push	word [menu_13_offset]
		jmp	short cdp_11
cdp_10:
		; /* Second disk, so dont put up prompt mentioning active partition */

		mov	byte [second_disk_flag],1
		;push	word [menu_45_segment]
		push	ds
		push	word [menu_45_offset]
cdp_11:
		call	display
		;pop	bx
		;pop	bx

		;/* Get Y/N input */
 	; input = get_yn_input(c(Yes),input_row,input_col); 

		push	word [input_col]
		push	word [input_row]
		mov	al,[Yes]
		push	ax
		call	get_yn_input
		;add	sp,6
switch_input8:
		;/* Go handle input */

		;cbw
		;cmp	ax,1Bh
		cmp	al,1Bh ; ESCape key
		jne	short cdp_13
		jmp	case_dos_create_break  ; /* take no action */
cdp_13:
		ja	short case_dos_create_DEF
		or	al,al
		jnz	short cdp_14 ; 'Y'es or invalid
		jmp	case_dos_create_0 ; 'N'o
cdp_14:
		dec	al
		jz	short case_dos_create_1 ; 'Y'es
case_dos_create_DEF:
		call	internal_program_error
		jmp	case_dos_create_break
case_dos_create_1:
		; /* Go get the biggest area left */

		sub	al,al
		;push	ax
		call	find_part_free_space
		;pop	bx
		;mov	[cdp_temp],al
		mov	dl,al
		
		sub	al,al   ; PRIMARY
		push	ax	; mp_type (byte) - PRIMARY -

		;mov	al,[cdp_temp]
		;mov	dl,al		
		;mov	cl,22
		mov	cl,10 ; 14/01/2019
		mul	cl
		mov	bx,ax
		mov	cx,[free_space.space+bx]

		cmp	byte [second_disk_flag],0
		jne	short cdp_17

		;sub	al,al
		;push	ax
		;call	find_part_free_space
		;pop	bx
		;mov	[cdp_temp],al
		;sub	al,al
		;push	ax

		mov	al,80h  ; BOOTABLE
		push	ax	; mp_bootable (byte) - BOOTABLE -

		;mov	al,[cdp_temp]
		;push	ax
		;mov	cl,22
		;imul	cl
		;mov	bx,ax
		;push	word [free_space.space+bx]

		push	dx  ; dl = [cdp_temp]  ; mp_free_ptr (byte)
		push	cx  ; cx = [free_space.space+bx] ; mp_size (word)			

		call	make_partition
		;add	sp,8

		mov	byte [reboot_flag],1
		cmp	byte [number_of_drives],1
		jne	short cdp_18
		call	write_info_to_disk
		call	reboot_system
		jmp	short cdp_18
cdp_17:
		;sub	al,al
		;push	ax
		;call	find_part_free_space
		;pop	bx
		;mov	[cdp_temp],al
		;sub	al,al
		;push	ax

		push	ax  ; al = 0 ; mp_bootable - not bootable -
 		
		;mov	al,[cdp_temp]
		;push	ax
		;mov	cl,22
		;imul	cl
		;mov	bx,ax
		;push	word [free_space.space+bx]

		push	dx  ; dl = [cdp_temp]  ; mp_free_ptr
		push	cx  ; cx = [free_space.space+bx] ; mp_size		

		call	make_partition
		;add	sp,8

		mov	byte [reboot_flag],1
cdp_18:
		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,16
		push	ax
		call	clear_screen
		;add	sp,8
		
		;push	word [status_12_seg]
		push	ds
		push	word [status_12_off]
		jmp	short cdp_20

case_dos_create_0:
		call	input_dos_create
		jmp	short case_dos_create_break
cdp_19:
	;/* Display partition table - it will return if no partitions there */

		call	table_display

		;/* Primary partition already exists message */

		;push	word [error_8_seg]
		push	ds
		push	word [error_8_off]
cdp_20:
		call	display
		;pop	bx
		;pop	bx

		call	wait_for_ESC

case_dos_create_break:
		pop	si
		mov	sp,bp
		pop	bp
		retn

; fdisk.msg (MSDOS 6.0)
;/***************************************************************************************************/
;/*  Screen for INPUT_DOS_CREATE                                                                    */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                           Create Primary DOS Partition                         |menu_12 # */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Partition Status   Type    Size in Mbytes   Percentage of Disk Used         |menu_14   */
;/*   09|     ## #        #    #######       ####        ###%                            |          */
;/*   10|     ## #        #    #######       ####        ###%                            |          */
;/*   11|     ## #        #    #######       ####        ###%                            |          */
;/*   12|     ## #        #    #######       ####        ###%                            |          */
;/*   13|                                                                                |          */
;/*   14|    Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes)                   |menu_15   */
;/*   15|    Maximum space available for partition is #### Mbytes (###%)                 |menu_16   */
;/*   16|                                                                                |          */
;/*   17|                                                                                |          */
;/*   18|    Enter partition size in Mbytes or percent of disk space (%) to              |menu_39   */
;/*   19|    create a Primary DOS Partition..................................[####]      |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to return to FDISK Options                                        |menu_11   */
;/*   ------------------------------------------------------------------------------------          */ 
;/*                                                                                                 */
;/***************************************************************************************************/

; c_menus.c (MSDOS 6.0)
;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: INPUT_DOS_CREATE                           */
;/*                                                             */
;/* DESCRIPTIVE NAME: Create DOS partition on disk              */
;/*                                                             */
;/* FUNCTION: Gets user specified size for partition (maximum   */
;/*           is 32mb or largest contiguous freespace, which-   */
;/*           ever is smaller). Default is largest avail free   */
;/*           space. Partition is created to default size,unless*/
;/*           user enters different size, but is not marked     */
;/*           active. User specified size must be smaller or    */
;/*           equal to the default size                         */
;/*                                                             */
;/* NOTES: Screen can be exited via the ESC command before      */
;/*        partition is created and nothing will change         */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*       |0000000000111111111122222222223333333333|            */
;/*       |0123456789012345678901234567890123456789|            */
;/*     --|----------------------------------------|            */
;/*     00|                                        |            */
;/*     01|                                        |            */
;/*     02|                                        |            */
;/*     03|                                        |            */
;/*     04|Create DOS partition                    |            */
;/*     05|                                        |            */
;/*     06|Current Fixed Disk Drive: #             |            */
;/*     07|                                        |            */
;/*     08|Partition Status   Type  Start  End Size|            */
;/*     09|                                        |            */
;/*     10|                                        |            */
;/*     11|                                        |            */
;/*     12|                                        |            */
;/*     13|                                        |            */
;/*     14|Total disk space is #### cylinders.     |            */
;/*     15|Maximum space available for partition   |            */
;/*     16|is #### cylinders.                      |            */
;/*     17|                                        |            */
;/*     18|Enter partition size............: [####]|            */
;/*     19|                                        |            */
;/*     20|                                        |            */
;/*     21|                                        |            */
;/*     22|                                        |            */
;/*     23|Press ESC to return to FDISK Options    |            */
;/*     --------------------------------------------            */
;/*                                                             */
;/* ENTRY POINTS: input_dos_create                              */
;/*      LINKAGE: input_dos_create();                           */
;/*               NEAR CALL                                     */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if case statement   */
;/*             failure when branching to requested function    */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      table_display                                          */
;/*      get_num_input                                          */
;/*      display                                                */
;/*      wait_for_ESC                                           */
;/*      make_partition                                         */
;/*      check_bad_tracks                                       */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void input_dos_create()
;
;BEGIN
;
;    unsigned  input;
;    unsigned  default_entry;
;    char      temp;
;
;    input = u(NUL);                                                    /* AC000 */
;    /* clear off screen */
;    clear_screen(u(0),u(0),u(24),u(79));                               /* AC000 */
;
;    /* Put up heading */
;    display(menu_12);
;
;    /* Setup and print current disk */
;    insert[0] = cur_disk+1+'0';
;    display(menu_5);
;
;    /* Print ESC prompt */
;    display(menu_11);
;
;    /* Display partition table-it will return if no partitions there */
;    table_display();
;
;    sprintf(insert,"%4.0d",total_mbytes[cur_disk]);
;    display(menu_15);
;
;    /* Get the free space */
;    temp = find_part_free_space(c(PRIMARY));                           /* AC000 */
;
;    /* Is there any ?*/
;    if (free_space[temp].mbytes_unused != u(0))                        /* AC000 */
;
;        BEGIN
;        /* Display disk space */
;        sprintf(insert,"%4.0d",total_mbytes[cur_disk]);
;        display(menu_15);
;
;        /* Setup and print max partition size */
;
;        sprintf(insert,"%4.0d%3.0d%%",
;                free_space[temp].mbytes_unused,
;                free_space[temp].percent_unused);
;        display(menu_16);
;
;        /* Force repeats on the input until something valid (Non-Zero return) */
;        default_entry = (unsigned)free_space[temp].mbytes_unused;      /* AC000 */
;        valid_input = (FLAG)FALSE;                                     /* AC000 */
;
;        while (!valid_input)
;
;            BEGIN
;            /* Display prompt */
;            sprintf(insert,"%4.0d",default_entry);
;            display(menu_39);
;
;            input = get_large_num_input(default_entry,free_space[temp].mbytes_unused,free_space[temp].percent_unused,menu_39,u(0),error_13);       /* AC000 */
;
;            /* Update default in case of error, so it gets displayed and used */
;            /* if user presses CR only */
;
;            default_entry = input;
;            clear_screen(u(19),u(0),u(23),u(79));                     /* AC000 */
;            END
;
;        if (input != ((unsigned)(ESC_FLAG)))                          /* AC000 */
;
;            BEGIN
;            /* Change input to cylinders */
;            /* check to see if input was in percent or mbytes */
;
;            if (PercentFlag)                                          /* AN000 */
;                BEGIN                                                 /* AN000 */
;                if (input == free_space[temp].percent_unused)
;                    input = free_space[temp].space;                   /* AN000 */
;                else                                                  /* AN000 */
;                    input = percent_to_cylinders(input,total_disk[cur_disk]);
;                END                                                   /* AN000 */
;            else                                                      /* AN000 */
;                BEGIN                                                 /* AN000 */
;                if (input == free_space[temp].mbytes_unused)
;                    input = free_space[temp].space;                   /* AN000 */
;                else                                                  /* AN000 */
;                    input = (unsigned)mbytes_to_cylinders(input,
;                                                          cur_disk);  /* AN004 */
;                END                                                   /* AN000 */
;
;            /* Initialize PecentFlag back to FALSE */
;            PercentFlag = (FLAG)FALSE;                                /* AN000 */
;
;            /* SR; 9/26/89; Display error message if input value = 0 */
;
;            if (input == 0)
;               {
;                display(error_28);
;                wait_for_ESC();
;               }
;            else
;               {
;            	/* Go create the partition */
;            	make_partition(input,temp,uc(NUL),c(PRIMARY));         /* AC000 */
;
;            	/* clear off the old prompt */
;            	clear_screen(u(13),u(0),u(19),u(79));                  /* AC000 */
;
;            	/* Reissue the partition info */
;            	table_display();
;
;            	/* display the "okay, we did it" msg */
;            	if (number_of_drives == uc(1))                         /* AN000 */
;                	display(status_5);
;            	else
;                    BEGIN                                             /* AN000 */
;                    clear_screen(u(16),u(0),u(23),u(79));             /* AN000 */
;                    display(status_12);                               /* AN000 */
;                    END                                               /* AN000 */
;
;            	wait_for_ESC();
;
;            	reboot_flag = TRUE;
;               }
;
;            END
;        END
;    /* SR; 9/26/89; Display error if insufficient space for partition */
;    else
;        {
;        display(error_10);
;        wait_for_ESC();
;        }
;    return;
;END

input_dos_create:
		; 14/01/2019

	%define idc_def_entry	bp-6
	%define	idc_temp	bp-4
	%define idc_input	bp-2

		push	bp
		mov	bp,sp
		sub	sp,6

		;push	si

		;/* clear off screen */
		
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;mov	[idc_input],ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		mov	word [idc_input],0

		;/* Put up heading */

		;push	word [menu_12_segment]
		push	ds
		push	word [menu_12_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup and print current disk */

		mov	al,[cur_disk]
		add	al,'1'
		mov	[insert],al
		;push	word [menu_5_segment]
		push	ds
		push	word [menu_5_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Print ESC prompt */

		;push	word [menu_11_segment]
		push	ds
		push	word [menu_11_offset]
		call	display
		;pop	bx
		;pop	bx

	;/* Display partition table - it will return if no partitions there */

		call	table_display

		mov	al,[cur_disk]
		cbw
		mov	bx,ax
		shl	bx,1
		push	word [total_mbytes+bx]
		mov	ax,idc_tot_mb_format ; "%4.1d"
		push	ax
		mov	ax,insert
		push	ax
		call	sprintf
		add	sp,6

		;push	word [menu_15_segment]
		push	ds
		push	word [menu_15_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Get the free space */

		sub	al,al ; 0
		;push	ax
		call	find_part_free_space
		;pop	bx
		mov	[idc_temp],al

		;mov	cl,22
		mov	cl,10 ; 14/01/2019
		;imul	cl
		mul	cl
		mov	bx,ax

		;/* Is there any ?*/

		cmp	word [free_space.mbytes_unused+bx],0
		jne	short idc_1
		jmp	idc_12
idc_1:
		; /* Display disk space */

		mov	al,[cur_disk]
		cbw
		mov	si,ax
		shl	si,1
		push	word [total_mbytes+si]
		mov	ax,idc_tot_mb_format ; "%4.1d"
		push	ax
		mov	ax,insert
		push	ax
		mov	si,bx
		call	sprintf
		add	sp,6

		;push	word [menu_15_segment]
		push	ds
		push	word [menu_15_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup and print max partition size */

		push	word [free_space.percent_unused+si]
		push	word [free_space.mbytes_unused+si]
		mov	ax,idc_mb_pcent_format ; "%4.1d%3.1d%%"
		push	ax
		mov	ax, insert
		push	ax
		call	sprintf
		add	sp,8

		;push	word [menu_16_segment]
		push	ds
		push	word [menu_16_offset]
		call	display
		;pop	bx
		;pop	bx

		mov	ax,[free_space.mbytes_unused+si]
		mov	[idc_def_entry],ax
		mov	byte  [valid_input],0
idc_2:
		;/* Display prompt */

		push	word [idc_def_entry]
		mov	ax,idc_def_entry_format ; "%4.1d"
		push	ax
		mov	ax,insert
		push	ax
		call	sprintf
		add	sp,6

		;push	word [menu_39_segment]
		push	ds
		push	word [menu_39_offset]
		call	display
		;pop	bx
		;pop	bx

		;push	word [error_13_seg]   	
		push	ds		       ; glni_err_msg_seg	
		push	word [error_13_off]    ; glni_err_msg
		sub	ax,ax
		push	ax		       ; glni_prompt_loc	
		;push	word [menu_39_segment]
		push	ds		       ; glni_input_msg_seg	
		push	word [menu_39_offset]  ; glni_input_msg
		;mov	al,22
		mov	al,10 ; 14/01/2019
		;imul	byte [idc_temp]
		mul	byte [idc_temp]
		mov	bx,ax
		push	word [free_space.percent_unused+bx] ; glni_max_pc
		push	word [free_space.mbytes_unused+bx]  ; glni_max_num
		push	word [idc_def_entry]	; glni_input_def
		call	get_large_num_input
		;add	sp,16

	;/* Update default in case of error, so it gets displayed and used */
	;/* if user presses CR only */

		mov	[idc_input],ax
		mov	[idc_def_entry],ax

		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,19
		push	ax
		call	clear_screen
		;add	sp,8

	;/* Force repeats on the input until something valid (Non-Zero return) */

		cmp	byte [valid_input],0
		je	short idc_2

		cmp	word [idc_input],0FFFEh ; -2 ; ESC flag?
		jne	short idc_3
		jmp	idc_14

idc_3:
		;/* Change input to cylinders */
		;/* check to see if input was in percent or mbytes */

		;mov	al,22
		mov	al,10 ; 14/01/2019
		;imul	byte [idc_temp]
		mul	byte [idc_temp]
		mov	bx,ax
		mov	ax,[idc_input]

		cmp	byte [PercentFlag],0
		je	short idc_6

		;mov	al,22
		;;imul	byte [idc_temp]
		;mul	byte [idc_temp]
		;mov	bx,ax
		;mov	ax,[idc_input]

		cmp	[free_space.percent_unused+bx],ax
		jne	short idc_5 ; < 100
idc_4:
		mov	ax,[free_space.space+bx]
		jmp	short idc_8
idc_5:
		; 19/01/2019

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;shl	bx,1
		
		mov	bl,[cur_disk]
		;xor	bh,bh ; bh = 0
		shl	bl,1

		; ax = [idc_input]  ; percent in
		
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx] ; total cylinders
		;push	word [idc_input]
		;mov	ax,[idc_input] ; < 100
		call	percent_to_cylinders
		jmp	short idc_7
idc_6:
		;mov	al,22
		;imul	byte [idc_temp]
		;mul	byte [idc_temp]
		;mov	bx,ax
		;mov	ax,[idc_input]

		cmp	[free_space.mbytes_unused+bx],ax
		jz	short idc_4

		mov	al,[cur_disk]
		push	ax
		push	word [idc_input]
		call	mbytes_to_cylinders
idc_7:
		;pop	bx
		;pop	bx
idc_8:
		mov	[idc_input],ax

		;/* Initialize PecentFlag back to FALSE */

		mov	byte [PercentFlag],0

		; Display error message if input value = 0 */

		or	ax,ax
		jnz	short idc_9
		
		;push	word [error_28_seg]
		push	ds
		push	word [error_28_off]
		jmp	short idc_13
idc_9:
		;/* Go create the partition */
		;make_partition(input,temp,uc(NUL),c(PRIMARY));

		sub	al,al ; 0
		push	ax		 ; mp_type - PRIMARY -  
		push	ax		 ; mp_bootable - not bootable - 
		mov	al,[idc_temp]
		push	ax		 ; mp_free_ptr 
		push	word [idc_input] ; mp_size
		call	make_partition
		;add	sp,8

		;/* clear off the old prompt */

		mov	ax,79
		push	ax
		mov	ax,19
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,13
		push	ax
		call	clear_screen
		;add	sp,8

		;/* Reissue the partition info */
		
		call	table_display

		;/* display the "okay, we did it" msg */
		
		cmp	byte [number_of_drives],1
		jne	short idc_10
		
		;push	word [status_5_seg]
		push	ds
		push	word [status_5_off]
		jmp	short idc_11
idc_10:
		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,16
		push	ax
		call	clear_screen
		;add	sp,8

		;push	word [status_12_seg]
		push	ds
		push	word [status_12_off]
idc_11:
		call	display
		;pop	bx
		;pop	bx

		call	wait_for_ESC

		mov	byte [reboot_flag],1 ; TRUE
		jmp	short idc_14
idc_12:
		; Display error if insufficient space for partition */

		;push	word [error_10_seg]
		push	ds
		push	word [error_10_off]
idc_13:
		call	display
		;pop	bx
		;pop	bx

		call	wait_for_ESC
idc_14:
		;pop	si

		mov	sp, bp
		pop	bp
		retn

;/***************************************************************************************************/
;/*  Screen for EXT_CREATE_PARTITION                                                                */
;/*                                                                                                 */
;/*     |00000000001111111111222222222233333333334444444444555555555566666666667777777777|          */
;/*     |01234567890123456789012345678901234567890123456789012345678901234567890123456789|          */
;/*   --|--------------------------------------------------------------------------------|          */
;/*   00|                                                                                |          */
;/*   01|                                                                                |          */
;/*   02|                                                                                |          */
;/*   03|                                                                                |          */
;/*   04|                           Create Extended DOS Partition                        |menu_17   */
;/*   05|                                                                                |          */
;/*   06|    Current fixed disk drive: #                                                 |menu_5 #  */
;/*   07|                                                                                |          */
;/*   08|    Partition Status   Type    Size in Mbytes   Percentage of Disk Used         |menu_14 # */
;/*   09|     ##  #       #   #######       ####                   ###%                  |          */
;/*   10|     ##  #       #   #######       ####                   ###%                  |          */
;/*   11|     ##  #       #   #######       ####                   ###%                  |          */
;/*   12|     ##  #       #   #######       ####                   ###%                  |          */
;/*   13|                                                                                |          */
;/*   14|    Total disk space is #### Mbytes (1 Mbyte = 1048576 bytes)                   |menu_15 # */
;/*   15|    Maximum space available for partition is #### Mbytes (##%)                  |menu_16 # */
;/*   16|                                                                                |          */
;/*   17|                                                                                |          */
;/*   18|    Enter partition size in Mbytes or percent of disk space (%) to              |menu_42 # */
;/*   19|    create an Extended DOS Partition................................[####]      |          */
;/*   20|                                                                                |          */
;/*   21|                                                                                |          */
;/*   22|                                                                                |          */
;/*   23|                                                                                |          */
;/*   24|    Press ESC to continue                                                       |menu_46   */
;/*   ------------------------------------------------------------------------------------          */ 
;/*                                                                                                 */
;/***************************************************************************************************/

; c_menus.c (MSDOS 6.0)
;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: EXT_CREATE_PARTITION                       */
;/*                                                             */
;/* DESCRIPTIVE NAME: Create EXTENDED DOS partition             */
;/*                                                             */
;/* FUNCTION: Gets user specified size for EXTENDED partition   */
;/*           (Maximum is largest contiguous freespace). The    */
;/*           default is the largest available freespace.       */
;/*           space. Partition is created to default size,      */
;/*           unless user enters different size, but is not     */
;/*           marked as active. User specified size must be     */
;/*           smaller or equal to default size                  */
;/*                                                             */
;/* NOTES: Screen can be exited via the ESC command before      */
;/*        partition is created and nothing will change         */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*       |0000000000111111111122222222223333333333|            */
;/*       |0123456789012345678901234567890123456789|            */
;/*     --|----------------------------------------|            */
;/*     00|                                        |            */
;/*     01|                                        |            */
;/*     02|                                        |            */
;/*     03|                                        |            */
;/*     04|Create EXTENDED DOS partition           |            */
;/*     05|                                        |            */
;/*     06|Current Fixed Disk Drive: #             |            */
;/*     07|                                        |            */
;/*     08|Partition Status   Type  Start  End Size|            */
;/*     09|                                        |            */
;/*     10|                                        |            */
;/*     11|                                        |            */
;/*     12|                                        |            */
;/*     13|                                        |            */
;/*     14|Total disk space is  #### cylinders.    |            */
;/*     15|Maximum space available for partition   |            */
;/*     16|is #### cylinders.                      |            */
;/*     17|                                        |            */
;/*     18|Enter partition size............: [####]|            */
;/*     19|                                        |            */
;/*     20|                                        |            */
;/*     21|                                        |            */
;/*     22|                                        |            */
;/*     23|Press ESC to return to FDISK Options    |            */
;/*     --------------------------------------------            */
;/*                                                             */
;/* ENTRY POINTS: EXTENDED_create_partition                     */
;/*      LINKAGE: EXTENDED_create_partition();                  */
;/*               NEAR CALL                                     */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if case statement   */
;/*             failure when branching to requested function    */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      table_display                                          */
;/*      get_num_input                                          */
;/*      display                                                */
;/*      find_partition_type                                    */
;/*      wait_for_ESC                                           */
;/*      make_partition                                         */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void ext_create_partition()
;
;BEGIN
;
;    unsigned  input;
;    unsigned  default_entry;
;    char      temp;
;
;    input = u(NUL);                                                    /* AC000 */
;    /* clear off screen */
;    clear_screen(u(0),u(0),u(24),u(79));                               /* AC000 */
;
;    /* Put up heading */
;    display(menu_17);
;
;    /* Setup and print current disk */
;    insert[0] = cur_disk+1+'0';
;    display(menu_5);
;
;    /* print ESC prompt */
;    display(menu_11);
;
;    /* Display partition table-it will return if no partitions there */
;        table_display();
;
;    /* Go see if primary already exists and ext doesn't */
;    if ((cur_disk >= c(1)) || (find_partition_type(uc(DOS12))) || (find_partition_type(uc(DOS16))) ||
;        (find_partition_type(uc(DOSNEW))))                                            /* AC000 */
;        BEGIN
;        if (!find_partition_type(uc(EXTENDED)))                         /* AC000 */
;            /* We can go create one now */
;            BEGIN
;
;            /* Get the free space */
;            temp = find_part_free_space(c(EXTENDED));                   /* AC000 */
;
;            /* Is there any ?*/
;            /* SR; 9/26/89; Instead of checking only the percentage which
;               could be off because of rounding errors, we also check the
;               mbytes available */
;
;            if (free_space[temp].space != u(0) &&                       /* AC000 */
;                (free_space[temp].percent_unused != u(0) ||
;                 free_space[temp].mbytes_unused != u(0)))
;                BEGIN
;
;                /* Display disk space */
;                sprintf(insert,"%4.0d",total_mbytes[cur_disk]);
;                display(menu_15);
;
;                /* Setup and print max partition size */
;
;                sprintf(insert,"%4.0d%3.0d%%",
;                        free_space[temp].mbytes_unused,
;                        free_space[temp].percent_unused);
;                display(menu_16);
;
;                /* Force repeats on the input until something valid (Non-Zero return) */
;                /* Display MBytes unless MBytes == 0, then display percent */
;                if (free_space[temp].mbytes_unused == u(0))             /* AN000 */
;                    BEGIN                                               /* AN000 */
;                    default_entry = (unsigned)free_space[temp].percent_unused; /* AC000 */
;                    PercentFlag = (FLAG)TRUE;                           /* AN000 */
;                    END                                                 /* AN000 */
;                else                                                    /* AN000 */
;                    BEGIN
;                    default_entry = (unsigned)free_space[temp].mbytes_unused; /* AC000 */
;                    PercentFlag = (FLAG)FALSE;                          /* AN000 */
;                    END
;
;                valid_input = (FLAG)FALSE;                              /* AC000 */
;
;                while (!valid_input)
;                    BEGIN
;                    /* Display prompt */
;                    if (!PercentFlag)                                   /* AN000 */
;                        sprintf(insert,"%4.0d",default_entry);
;                    else                                                /* AN000 */
;                        sprintf(insert,"%3.0d%%",default_entry);        /* AN000 */
;                    display(menu_42);                                   /* AC000 */
;
;                    input = get_large_num_input(default_entry,free_space[temp].mbytes_unused,free_space[temp].percent_unused,menu_42,u(0),error_13);   /*  AC000 */
;
;                    /* Update default in case of error, so it gets displayed and used */
;                    /* if user presses CR only */
;
;                    default_entry = input;
;                    clear_screen(u(19),u(0),u(23),u(79));                /* AC000 */
;                    END
;
;                if (input != ((unsigned)(ESC_FLAG)))                          /* AC000 */
;                    BEGIN
;
;                    /* Change input to cylinders */
;                    if (PercentFlag)                                          /* AN000 */
;                        BEGIN                                                 /* AN000 */
;                        if (input == free_space[temp].percent_unused)
;                            input = free_space[temp].space;                   /* AN000 */
;                        else                                                  /* AN000 */
;                            input = percent_to_cylinders(input,total_disk[cur_disk]);
;                        END                                                   /* AN000 */
;                    else                                                      /* AN000 */
;                        BEGIN                                                 /* AN000 */
;                        if (input == free_space[temp].mbytes_unused)
;                            input = free_space[temp].space;                   /* AN000 */
;                        else                                                  /* AN000 */
;                            input = (unsigned)mbytes_to_cylinders(input,
;                                                                  cur_disk);  /* AN004 */
;                        END                                                   /* AN000 */
;
;
;                    /* Initialize PecentFlag back to FALSE */
;                    PercentFlag = (FLAG)FALSE;                                /* AN000 */
;
;                    /* SR; 9/26/89; Display error message if input value = 0 */
;
;                    if (input == 0)
;                       {
;                        display(error_28);
;                        wait_for_ESC();
;                       }
;                    else
;                       {
;
;                    	/* Go create the partition */
;                    	make_partition(input,temp,uc(NUL),c(EXTENDED));     /* AC000 */
;
;                    	/* clear off the old prompt */
;                    	clear_screen(u(13),u(0),u(19),u(79));               /* AC000 */
;
;                    	/* Display the updated partition information */
;                    	table_display();
;
;                    	/* Tell user we created it */
;                    	display(status_6);
;                    	wait_for_ESC();
;
;                    	reboot_flag = (FLAG)TRUE;                           /* AC000 */
;
;                    	/* Go allow him to create disk volumes */
;                    	volume_create();
;                       }
;                    END
;                END
;            else
;                BEGIN
;                /* No room */
;                display(error_10);
;                wait_for_ESC();
;                END
;            END
;        else
;            BEGIN
;            /* Already have ext partition, tell user and bow out */
;            display(error_9);
;            wait_for_ESC();
;            END
;        END
;    else
;        BEGIN
;        /* don't have a primary partition yet, can't create an ext */
;        display(error_19);
;        wait_for_ESC();
;        END
;
;    return;
;END

ext_create_partition:
		; 25/01/2019

	%define ecp_default_entry bp-6
	%define ecp_temp	  bp-4
	%define ecp_input	  bp-2

		push	bp
		mov	bp,sp
		sub	sp,6

		;push	si
		
		;/* clear off screen */

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;mov	[ecp_input],ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8
		
		call	CLS

		mov	word [ecp_input],0

		;/* Put up heading */

		;push	word [menu_17_segment]
		push	ds
		push	word [menu_17_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup and print current disk */

		mov	al,[cur_disk]
		add	al,'1'
		mov	[insert],al

		;push	word [menu_5_segment]
		push	ds
		push	word [menu_5_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* print ESC prompt */

		;push	word [menu_11_segment]
		push	ds
		push	word [menu_11_offset]
		call	display
		;pop	bx
		;pop	bx

	;/* Display partition table-it will return if no partitions there */

		call	table_display

	;/* Go see if primary already exists and ext doesn't */

; *** ('create_partition', 'cp_6:') ***
;
;		cmp	bytew [cur_disk],1
;		;jge	short ecp_1
;		jnb	short ecp_1
;
;		mov	al,1 ; DOS12
;		;push	ax
;		call	find_partition_type
;		;pop	bx
;		;or	al,al
;		;jnz	short ecp_1
;		jnc	short ecp_1
;		
;		mov	al,4 ; DOS16
;		;push	ax
;		call	find_partition_type
;		;pop	bx
;		;or	al, al
;		;jnz	short ecp_1
;		jnc	short ecp_1
;		
;		mov	al,6  ; DOSNEW
;		;push	ax
;		call	find_partition_type
;		;pop	bx
;		;or	al,al
;		;jnz	short ecp_1
;		jnc	short ecp_1
;
;	;/* don't have a primary partition yet, can't create an ext */
;
;		jmp	ecp_19

ecp_1:
		mov	al,5 ; EXTENDED
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short ecp_2
		jc	short ecp_2
		jmp	ecp_18

		;/* We can go create one now */
ecp_2:
		;/* Get the free space */

		; temp = find_part_free_space(c(EXTENDED));    

		mov	al,5
		;push	ax
		call	find_part_free_space
		;pop	bx
		mov	[ecp_temp],al

		;/* Is there any ?*/
	
	;Instead of checking only the percentage which
	;could be off because of rounding errors, we also check the
	;mbytes available */

		;mov	cl,22
		;imul	cl
		mov	cl,10
		mul	cl
		;mov	bx,ax
		mov	si,ax ; /***/
		xor	ax,ax ; 0
		;cmp	word [free_space.space+bx],0
		cmp	[free_space.space+si],ax ; 0
		jne	short ecp_3
		jmp	ecp_17
ecp_3:
		;cmp	word [free_space.percent_unused+bx],0
		cmp	[free_space.percent_unused+si],ax ; 0
		jne	short ecp_4
		;cmp	word [free_space.mbytes_unused+bx],0
		cmp	[free_space.mbytes_unused+bx],ax ; 0
		jne	short ecp_4
		jmp	ecp_17
ecp_4:
		;/* Display disk space */
		;sprintf(insert,"%4.0d",total_mbytes[cur_disk]);
		;display(menu_15);

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		mov	bl,[cur_disk]
		xor	bh,bh
		;shl	bx,1
		shl	bl,1
		push	word [total_mbytes+bx]
		mov	ax,ecp_size_format ; "%4.1d"
		push	ax
		mov	ax,insert
		push	ax
		call	sprintf
		add	sp,6

		;push	word [menu_15_segment]
		push	ds
		push	word [menu_15_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Setup and print max partition size */
		;sprintf(insert,"%4.0d%3.0d%%",
		;	free_space[temp].mbytes_unused,
		;	free_space[temp].percent_unused);
		;display(menu_16);

		;;mov	al,22
		;;imul	byte [ecp_temp]
		;mov	al,10
		;mul	byte [ecp_temp]
		;;mov	bx,ax
		;mov	si,ax ; /***/
		
		;push	word [free_space.percent_unused+bx]
		push	word [free_space.percent_unused+si] ; /***/
		;push	word [free_space.mbytes_unused+bx]
		push	word [free_space.mbytes_unused+si] ; /***/
		mov	ax,ecp_mb_pcent_format ; "%4.1d%3.1d%%"
		push	ax
		mov	ax,insert
		push	ax
		;mov	si,bx
		call	sprintf
		add	sp,8

		;push	word [menu_16_segment]
		push	ds
		push	word [menu_16_offset]
		call	display
		;pop	bx
		;pop	bx

	;/* Force repeats on the input until something valid (Non-Zero return) */
	;/* Display MBytes unless MBytes == 0, then display percent */

		cmp	word [free_space.mbytes_unused+si],0
		jne	short ecp_5
		mov	ax,[free_space.percent_unused+si]
		mov	[ecp_default_entry],ax
		mov	byte [PercentFlag],1  ; PercentFlag = (FLAG)TRUE;    
		jmp	short ecp_6
ecp_5:
		;;mov	al,22
		;mov	al,10
		;;imul	byte [ecp_temp]
		;mul	byte [ecp_temp]
		;;mov	bx,ax
		;mov	si,ax ; /***/
		
		;mov	ax,[free_space.mbytes_unused+bx]
		mov	ax,[free_space.mbytes_unused+si] ; /***/
		mov	[ecp_default_entry],ax
		mov	byte [PercentFlag],0  ; PercentFlag = (FLAG)FALSE;     
ecp_6:
		mov	byte [valid_input],0  ; valid_input = (FLAG)FALSE; 
ecp_7:
		push	word [ecp_default_entry] ; 25/01/2019

		cmp	byte [PercentFlag],0
		jne	short ecp_8

		;/* Display prompt */
		;if (!PercentFlag)
		;   sprintf(insert,"%4.0d",default_entry);
		;else
		;   sprintf(insert,"%3.0d%%",default_entry);
		;display(menu_42);     

		;push	word [ecp_default_entry]
		mov	ax,ecp_mb_format ; "%4.1d"
		jmp	short ecp_9
ecp_8:
		;push	word [ecp_default_entry]
		mov	ax,ecp_pcent_format ; "%3.1d%%"
ecp_9:
		push	ax
		mov	ax,insert
		push	ax
		call	sprintf
		add	sp,6

		;push	word [menu_42_segment]
		push	ds
		push	word [menu_42_offset]
		call	display
		;pop	bx
		;pop	bx

	;input = get_large_num_input(default_entry,free_space[temp].mbytes_unused,
	;		free_space[temp].percent_unused,menu_42,u(0),error_13);

		;push	word [error_13_seg]
		push	ds
		push	word [error_13_off]
		sub	ax,ax ; 0
		push	ax

		;push	word [menu_42_segment]
		push	ds
		push	word [menu_42_offset]
		
		;;mov	al,22
		;mov	al,10
		;;imul	byte [ecp_temp]
		;mul	byte [ecp_temp]
		;;mov	bx,ax
		;mov	si,ax ; /***/

		;push	word [free_space.percent_unused+bx]
		;push	word [free_space.mbytes_unused+bx]
		push	word [free_space.percent_unused+si] ; /***/
		push	word [free_space.mbytes_unused+si] ; /***/
		push	word [ecp_default_entry]
		call	get_large_num_input
		;add	sp,16

		mov	[ecp_input],ax

	;/* Update default in case of error, so it gets displayed and used */
	;/* if user presses CR only */

		mov	[ecp_default_entry],ax

		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,19
		push	ax
		call	clear_screen
		;add	sp,8

		;while (!valid_input)

		cmp	byte [valid_input],0
		je	short ecp_7

		; if (input != ((unsigned)(ESC_FLAG)))  

		cmp	word [ecp_input],0FFFEh ; ESC_FLAG
		jne	short ecp_10
		jmp	ecp_21
ecp_10:
		;/* Change input to cylinders */

		;;mov	al,22
		;mov	al,10
		;;imul	byte [ecp_temp]
		;mul	byte [ecp_temp]
		;;mov	bx,ax
		;mov	si,ax ; /***/

		; if (PercentFlag) 

		mov	ax,[ecp_input] ; **   

		cmp	byte [PercentFlag],0
		je	short ecp_13  ; else
		
		;;mov	al,22
		;mov	al,10
		;;imul	byte [ecp_temp]
		;mul	byte [ecp_temp]
		;;mov	bx,ax
		;mov	si,ax ; /***/

		; if (input == free_space[temp].percent_unused)

		;mov	ax,[ecp_input] ; **
		;cmp	[free_space.percent_unused+bx],ax
		cmp	[free_space.percent_unused+si],ax ; /***/
		jne	short ecp_12  ; else
ecp_11:
		;input = free_space[temp].space;
		
		;mov	ax,[free_space.space+bx]
		mov	ax,[free_space.space+si] ; /***/
		jmp	short ecp_15
ecp_12:	
	;input = percent_to_cylinders(input,total_disk[cur_disk]);

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;shl	bx,1
		mov	bl,[cur_disk]
		sub	bh,bh
		shl	bl,1	
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx]  ;total cylinders
		;;push	word [ecp_input]
		;mov	ax,[ecp_input]
			; cx = total cylinders (of the disk)
			; ax = percent in (word, <= 100)
		call	percent_to_cylinders
		jmp	short ecp_14
ecp_13:
		;;mov	al,22
		;mov	al,10
		;;imul	byte [ecp_temp]
		;mul	byte [ecp_temp]
		;;mov	bx,ax
		;mov	si,ax ; /***/

		;if (input == free_space[temp].mbytes_unused)
		;   input = free_space[temp].space; 

		;mov	ax,[ecp_input] ; **
		;cmp	[free_space.mbytes_unused+bx],ax
		cmp	[free_space.mbytes_unused+si],ax ; /***/
		je	short ecp_11

		;else

	; input = (unsigned)mbytes_to_cylinders(input,cur_disk); 

		;mov	al,[cur_disk]
		;push	ax
		push	word [cur_disk] ; 25/01/2019
		;push	word [ecp_input]
		push	ax ; **
		call	mbytes_to_cylinders
ecp_14:
		;pop	bx
		;pop	bx
ecp_15:	
		;mov	[ecp_input],ax ; *

		;/* Initialize PecentFlag back to FALSE */

		mov	byte [PercentFlag],0 ; PercentFlag = (FLAG)FALSE;   

		; Display error message if input value = 0 */

		or	ax,ax
		jnz	short ecp_16

		;push	word [error_28_seg]
		push	ds
		push	word [error_28_off]
		jmp	short ecp_20
ecp_16:
		;/* Go create the partition */

		mov	cx,ax ; *

		mov	al,5 ; EXTENDED
		push	ax		 ; mp_type (byte) - EXTENDED -
		sub	al,al ; 0
		push	ax		 ; mp_bootable (byte) - not bootable -
		mov	al,[ecp_temp]
		push	ax		 ; mp_free_ptr (byte)
		;push	word [ecp_input] ; mp_size (word)
		push	cx  ; *
		call	make_partition
		;add	sp,8

		;* clear off the old prompt */

		mov	ax,79
		push	ax
		mov	ax,19
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,13
		push	ax
		call	clear_screen
		;add	sp,8

		;/* Display the updated partition information */

		call	table_display

		;/* Tell user we created it */

		;push	word [status_6_seg]
		push	ds
		push	word [status_6_off]
		call	display
		;pop	bx
		;pop	bx
		
		call	wait_for_ESC

		mov	byte [reboot_flag],1  ;reboot_flag = (FLAG)TRUE; 

		;/* Go allow him to create disk volumes */

		call	volume_create
		jmp	short ecp_21
ecp_17:		
		;/* No room */
		
		;display(error_10);

		;push	word [error_10_seg]
		push	ds
		push	word [error_10_off]
		jmp	short ecp_20
ecp_18:
	;/* Already have ext partition, tell user and bow out */
		
		;display(error_9);

		;push	word [error_9_seg]
		push	ds
		push	word [error_9_off]
;		jmp	short ecp_20
;ecp_19:
;	;/* don't have a primary partition yet, can't create an ext */
;
;		;display(error_19);
;
;		;push	word [error_19_seg]
;		push	ds
;		push	word [error_19_off]
ecp_20:
		call	display
		;pop	bx
		;pop	bx

		call	wait_for_ESC  ; wait_for_ESC();
ecp_21:
		;pop	si

		mov	sp,bp
		pop	bp
		retn

;/*  */
;/******************* START OF SPECIFICATIONS *******************/
;/*                                                             */
;/* SUBROUTINE NAME: VOLUME_CREATE                              */
;/*                                                             */
;/* DESCRIPTIVE NAME: Create DOS disk volumes                   */
;/*                                                             */
;/* FUNCTION: Create the boot record/partition table structure  */
;/*           needed to support the DOS disk volume arch in     */
;/*           the EXTENDED partition. Volume is created to the  */
;/*           the default size (largest contiguous freespace or */
;/*           32mb, whichever smaller) or to the user specified */
;/*           size (must be smaller or equal to default size).  */
;/*           The volume boot record is created, and the appro- */
;/*           priate pointers in other volume partition tables  */
;/*           are generated.                                    */
;/*                                                             */
;/*                                                             */
;/* NOTES: Screen can be exited via the ESC command before      */
;/*        partition is created and nothing will change         */
;/*                                                             */
;/*        The following screen is managed                      */
;/*                                                             */
;/*       |0000000000111111111122222222223333333333|            */
;/*       |0123456789012345678901234567890123456789|            */
;/*     --|----------------------------------------|            */
;/*     00|Create DOS Disk Volume                  |            */
;/*     01|                                        |            */
;/*     02|Vol Start End  Size                     |            */
;/*     03| #  ####  #### ####                     |            */
;/*     04|                                        |            */
;/*     05|                                        |            */
;/*     06|                                        |            */
;/*     07|                                        |            */
;/*     08|                                        |            */
;/*     09|                                        |            */
;/*     10|                                        |            */
;/*     11|                                        |            */
;/*     12|                                        |            */
;/*     13|                                        |            */
;/*     14|                                        |            */
;/*     15|                                        |            */
;/*     16|Total partition size is #### cylinders. |            */
;/*     17|Maximum space available for disk        |            */
;/*     18|volume is #### cylinders.               |            */
;/*     19|                                        |            */
;/*     20|Enter disk volume size..........: [####]|            */
;/*     21|                                        |            */
;/*     22|                                        |            */
;/*     23|Press ESC to return to FDISK Options    |            */
;/*     --------------------------------------------            */
;/*                                                             */
;/* ENTRY POINTS: Volume_Create                                 */
;/*      LINKAGE: Volume_Create ()                              */
;/*           NEAR CALL                                         */
;/*                                                             */
;/* INPUT: None                                                 */
;/*                                                             */
;/* EXIT-NORMAL: ERROR=FALSE                                    */
;/*                                                             */
;/* EXIT-ERROR: ERROR=TRUE                                      */
;/*             GOTO internal_program_error if case statement   */
;/*             failure when branching to requested function    */
;/*                                                             */
;/* EFFECTS: No data directly modified by this routine, but     */
;/*          child routines will modify data.                   */
;/*                                                             */
;/* INTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*      clear_screen                                           */
;/*      display                                                */
;/*      volume_display                                         */
;/*      get_num_input                                          */
;/*      wait_for_ESC                                           */
;/*      make_partition                                         */
;/*                                                             */
;/* EXTERNAL REFERENCES:                                        */
;/*   ROUTINES:                                                 */
;/*                                                             */
;/******************** END OF SPECIFICATIONS ********************/

;/*  */
;void volume_create()
;
;BEGIN
;
;    unsigned  input;
;    unsigned  default_entry;
;    char  drive_letter;
;    char  location;
;    char  ext_location;
;    unsigned char  i;
;    char  defined_drives;
;    char  temp_cur_disk;
;    unsigned ext_part_percent_unused;                           /* AN000 */
;    unsigned ext_part_num;                                      /* AN000 */
;
;    input = u(NUL);                                             /* AC000 */
;
;    /* clear off screen */
;    clear_screen(u(0),u(0),u(24),u(79));                        /* AC000 */
;
;    /* Display header */
;    display (menu_18);
;
;    /* print ESC prompt */
;    display(menu_11);
;
;    /* Display volume info */
;    drive_letter = volume_display();
;
;    /* Loop until done */
;    input = u(NUL);                                             /* AC000 */
;    while (input != ((unsigned)(ESC_FLAG)))                     /* AC000 */
;
;        BEGIN
;        /* See if we have hit the max number of drives */
;        defined_drives = c(0);                                  /* AC000 */
;        temp_cur_disk = cur_disk;
;
;        /* Search both drives for defined drives */
;        for (i = uc(0); i < number_of_drives; i++)              /* AC000 */
;
;            BEGIN
;            cur_disk = ((char)(i));
;
;            /* See if there is a primary drive letter */
;            if ((find_partition_type(uc(DOS12))) || (find_partition_type(uc(DOS16))) || (find_partition_type(uc(DOSNEW)))) /*AC000*/
;                defined_drives++;
;
;            /* See if extended partition on disk */
;            if (find_partition_type(uc(EXTENDED)))              /* AC000 */
;                BEGIN
;                /* Get number of logical drives */
;                defined_drives = defined_drives + get_num_logical_dos_drives();
;                END
;            END
;        /* Restore cur_disk to original */
;        cur_disk = temp_cur_disk;
;
;        /* See if 26 or less drives total */
;        if ((defined_drives < c(24)) &&             /*C07*/
;            (get_num_logical_dos_drives() < c(23))) /*C07*/
;            BEGIN
;            location = find_ext_free_space();
;
;            /* find the number of the extended partiton to figure out percent */
;            ext_part_num = find_partition_location(uc(EXTENDED));       /* AN000 */
;
;            /* Set the percent used */
;            ext_part_percent_unused =
;                cylinders_to_percent(free_space[location].space,
;                ((part_table[cur_disk][ext_part_num].end_cyl-part_table[cur_disk][ext_part_num].start_cyl)+1));
;
;            /* Is there any ?*/
;
;            /* SR; 9/26/89; Instead of checking only the percentage which
;               could be off because of rounding errors, we also check the
;               mbytes available */
;
;            if (free_space[location].space != u(0) &&
;                (free_space[location].percent_unused != u(0) ||
;                 free_space[location].mbytes_unused != u(0)))    /*C02*/
;                BEGIN
;
;                /* Display disk space */
;                sprintf(insert,"%4.0d",get_partition_size(uc(EXTENDED)) );
;                display(menu_21);
;
;                /* Setup and print max partition size */
;
;                sprintf(insert,"%4.0d%3.0d%%",
;                        free_space[location].mbytes_unused,
;                        ext_part_percent_unused);
;                display(menu_22);
;
;                /* Force repeats on the input until something valid (Non-Zero return) */
;                /* If MBytes unused  is equel to zero, display percent unused */
;                if (free_space[location].mbytes_unused == u(0))         /* AN000 */
;                    BEGIN                                               /* AN000 */
;                    default_entry = (unsigned)ext_part_percent_unused;     /* AN000 */
;                    PercentFlag = (FLAG)TRUE;                           /* AN000 */
;                    END                                                 /* AN000 */
;                else                                                    /* AN000 */
;                    BEGIN                                               /* AN000 */
;                    default_entry = (unsigned)free_space[location].mbytes_unused;   /* AC000 */
;                    PercentFlag = (FLAG)FALSE;                          /* AN000 */
;                    END                                                 /* AN000 */
;
;                valid_input = (FLAG)FALSE;                              /* AC000 */
;
;                while (!valid_input)
;                    BEGIN
;                    /* Display prompt */
;                    if (!PercentFlag)                                   /* AN000 */
;                        sprintf(insert,"%4.0d",default_entry);
;                    else                                                /* AN000 */
;                        sprintf(insert,"%3.0d%%",default_entry);        /* AN000 */
;
;                    display(menu_40);
;
;                    input = get_large_num_input(default_entry,free_space[location].mbytes_unused,ext_part_percent_unused,menu_40,u(0),error_12); /* AC000*/
;
;                    /* Update default in case of error, so it gets displayed and used */
;                    /* if user presses CR only */
;
;                    default_entry = input;
;                    clear_screen(u(19),u(0),u(23),u(79));               /* AC000 */
;                    END
;
;                if (input != ((unsigned)(ESC_FLAG)))                    /* AC000 */
;                    BEGIN
;
;                    /* Change input to cylinders */
;                    if (PercentFlag)                                          /* AN000 */
;                        BEGIN                                                 /* AN000 */
;                        if (input == ext_part_percent_unused)
;                            input = free_space[location].space;               /* AN000 */
;                        else                                                  /* AN000 */
;                            input = percent_to_cylinders(input,((part_table[cur_disk][ext_part_num].end_cyl-part_table[cur_disk][ext_part_num].start_cyl)+1));
;                        END                                                   /* AN000 */
;                    else                                                      /* AN000 */
;                        BEGIN                                                 /* AN000 */
;                        if (input == free_space[location].mbytes_unused)
;                            input = free_space[location].space;                   /* AN000 */
;                        else                                                  /* AN000 */
;                            input = (unsigned)mbytes_to_cylinders(input,
;                                                                  cur_disk);  /* AN004 */
;                        END                                                   /* AN000 */
;
;                    /* Initialize PecentFlag back to FALSE */
;                    PercentFlag = (FLAG)FALSE;                                  /* AN000 */
;
;                    /* SR; 9/26/89; Display error message if input value = 0 */
;
;                    if (input == 0)
;                       {
;                        display(error_28);
;                        wait_for_ESC();
;                       }
;                    else
;                       {
;                    	/* go create the entry and find out where it put it */
;                    	ext_location = make_volume(input,location);
;
;                    	/* clear off the old prompt */
;                    	clear_screen(u(15),u(0),u(19),u(79));               /* AC000 */
;
;                    	reboot_flag = (FLAG)TRUE;                           /* AC000 */
;
;                    	/* Display the updated partition information */
;                    	drive_letter = volume_display();
;
;                    	/* Tell user we created it */
;                    	display(status_7);
;                       }
;                    END
;                END
;            else
;                BEGIN
;                /* No space left or already max'd on the devices */
;                /* Get rid of the size prompts */
;                clear_screen(u(17),u(0),u(21),u(79));                   /* AC000 */
;                display(error_20);
;                volume_display();
;                wait_for_ESC();                         /* KWC, 11-01-87 */
;                input = u(ESC_FLAG);                    /* KWC, 11-01-87 */
;                END
;            END
;        else
;            BEGIN
;            /* Reached the maximum */
;            /* Get rid of the size prompts */
;            clear_screen(u(17),u(0),u(21),u(79));                       /* AC000 */
;            display(error_27);
;            /* Force an exit with ESC */
;            wait_for_ESC();                         /* KWC, 11-01-87 */
;            input = u(ESC_FLAG);                    /* KWC, 11-01-87 */
;            END
;        END
;    clear_screen(u(0),u(0),u(24),u(79));                               /* AC000 */
;    return;
;END

volume_create:
		; 23/01/2019

	%define vc_defined_drives	 bp-14 	;bp-16
	%define vc_ext_part_pcent_unused bp-12 	;bp-14
	%define vc_location		 bp-10	;bp-12
	%define vc_i		 	 bp-8	;bp-10
	%define vc_temp_cur_disk 	 bp-6	;bp-8
	%define vc_default_entry 	 bp-4	;bp-6
	;%define vc_ext_part_num  	 	;bp-4
	%define vc_input	 	 bp-2	;bp-2

		push	bp
		mov	bp,sp
		sub	sp,14

		;/* clear off screen */

		;push	si
		
		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8

		call	CLS

		;/* Display header */

		;push	word [menu_18_segment]
		push	ds
		push	word [menu_18_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* print ESC prompt */
		
		;push	word [menu_11_segment]
		push	ds
		push	word [menu_11_offset]
		call	display
		;pop	bx
		;pop	bx

		;/* Display volume info */

		call	volume_display

		;/* Loop until done */

		mov	word [vc_input],0
vc_1:
		;/* See if we have hit the max number of drives */

		mov	byte [vc_defined_drives],0
		mov	al,[cur_disk]
		mov	[vc_temp_cur_disk],al
		mov	byte [vc_i],0
		jmp	short vc_6
vc_2:
		mov	al,[vc_i]
		mov	[cur_disk],al

		mov	al,1 ; DOS12
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short vc_3
		jnc	short vc_3

		mov	al,4  ; DOS16
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jnz	short vc_3
		jnc	short vc_3

		mov	al,6 ; DOSNEW
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short vc_4
		jc	short vc_4
vc_3:
		inc	byte [vc_defined_drives]
vc_4:
		mov	al,5 ; EXTENDED
		;push	ax
		call	find_partition_type
		;pop	bx
		;or	al,al
		;jz	short vc_5
		jc	short vc_5

		call	get_num_logical_dos_drives
		add	[vc_defined_drives],al
vc_5:
		inc	byte [vc_i]
vc_6:
		;/* Search both drives for defined drives */
		;for (i = uc(0); i < number_of_drives; i++)  

		mov	al,[number_of_drives]
		cmp	[vc_i],al
		jb	short vc_2

		;/* Restore cur_disk to original */
		mov	al,[vc_temp_cur_disk]
		mov	[cur_disk],al

		;/* See if 26 or less drives total */

		cmp	byte [vc_defined_drives],24
		;jge	short vc_7
		jnb	short vc_7

		call	get_num_logical_dos_drives
		cmp	al,23
		;jl	short vc_8
		jb	short vc_8
vc_7:
		jmp	vc_24
vc_8:
		call	find_ext_free_space
		mov	[vc_location],al

	;/* find the number of the extended partiton to figure out percent */
	;ext_part_num = find_partition_location(uc(EXTENDED));

		;mov	al,5
		;push	ax
		;call	find_partition_location
		;pop	bx
		;cbw
		;mov	[vc_ext_part_num],ax
		
		mov	al,5 ; EXTENDED
		call	find_partition_type
		;mov	[vc_ext_part_num],cl

		;/* Set the percent used */

		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,[vc_ext_part_num]
		shl	al,1
		shl	al,1
		;add	al,[vc_ext_part_num]
		add	al,cl

		;mov	cx,46
		;mul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax

		;mov	ax,[part_table_end_cyl+bx]
		;sub	ax,[part_table_start_cyl+bx]
		;inc	ax
		;push	ax

		mov	cx,[part_table_end_cyl+bx]
		sub	cx,[part_table_start_cyl+bx]
		inc	cx ; extended dos partition cylinders - divisor -

		mov	di,cx ; ***--

		;mov	al,22
		mov	al,10
		;imul	byte [vc_location]
		mul	byte [vc_location]
		;mov	bx,ax
		;push	word [free_space.space+bx]
		mov	si,ax ; **--
		mov	bx,[free_space.space+si]  ; volume cylinders - dividend -
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[vc_ext_part_pcent_unused],ax

		;/* Is there any ?*/

	;Instead of checking only the percentage which
	;could be off because of rounding errors, we also check the
	; mbytes available */

	;if (free_space[location].space != u(0) &&
	;   (free_space[location].percent_unused != u(0) ||
	;    free_space[location].mbytes_unused != u(0)))

		xor	ax,ax
		;cmp	word free_space.space+si],0
		cmp	[free_space.space+si],ax ; 0
		jne	short vc_9
		jmp	vc_23
vc_9:
		;cmp	word [free_space.percent_unused+si],0
		cmp	[free_space.percent_unused+si],ax; 0
		jne	short vc_10
		;cmp	word [free_space.mbytes_unused+si],0
		cmp	[free_space.mbytes_unused+si],ax ; 0
		jne	short vc_10
		jmp	vc_23
vc_10:
		;/* Display disk space */
		;sprintf(insert,"%4.0d",get_partition_size(uc(EXTENDED)) );
		;display(menu_21);

		;mov	al,5
		;push	ax
		mov	dh,5
		call	get_partition_size
		;pop	bx

		; ax = extended dos partition size (in megabytes)

		push	ax
		mov	ax,v_psize_format ; "%4.1d"
		push	ax
		mov	ax,insert
		push	ax
		call	sprintf
		add	sp,6

		;push	word [menu_21_segment]
		push	ds
		push	word [menu_21_offset]
		call	display
		;pop	bx
		;pop	bx

	;/* Setup and print max partition size */
	;
	;	sprintf(insert,"%4.0d%3.0d%%",
	;	free_space[location].mbytes_unused,
	;	ext_part_percent_unused);
	;	display(menu_22);,

		push	word [vc_ext_part_pcent_unused]

		;;mov	al,22
		;mov	al,10
		;;imul	byte [vc_location]
		;mul	byte [vc_location]
		;mov	bx,ax

		;push	word [free_space.mbytes_unused+bx]
		push	word [free_space.mbytes_unused+si] ; **--
		mov	ax,v_mb_percent_format ; "%4.1d%3.1d%%"
		push	ax
		mov	ax,insert
		push	ax
		;mov	si,bx ; **--
		call	sprintf
		add	sp,8

		;push	word [menu_22_segment]
		push	ds
		push	word [menu_22_offset]
		call	display
		;pop	bx
		;pop	bx

	;/* Force repeats on the input until something valid (Non-Zero return) */
	;/* If MBytes unused is equal to zero, display percent unused */
	;if (free_space[location].mbytes_unused == u(0))  

		cmp	word [free_space.mbytes_unused+si],0 ;**--
		jne	short vc_11

		;default_entry = (unsigned)ext_part_percent_unused;

		mov	ax,[vc_ext_part_pcent_unused]
		mov	[vc_default_entry],ax
		mov	byte [PercentFlag],1 ; PercentFlag = (FLAG)TRUE;
		jmp	short vc_12
vc_11: 
	;default_entry = (unsigned)free_space[location].mbytes_unused;   

		;;mov	al,22
		;mov	al,10
		;;imul	byte [vc_location]
		;mul	byte [vc_location]
		;mov	bx,ax

		;mov	ax,[free_space.mbytes_unused+bx]
		mov	ax,[free_space.mbytes_unused+si] ; **--
		mov	[vc_default_entry],ax
		mov	byte [PercentFlag],0 ; PercentFlag = (FLAG)FALSE;   
vc_12:	
		mov	byte [valid_input],0 ; valid_input = (FLAG)FALSE; 
vc_13:	
		;/* Display prompt */

	;if (!PercentFlag)
	;    sprintf(insert,"%4.0d",default_entry);
	;else
	;    sprintf(insert,"%3.0d%%",default_entry);

		push	word [vc_default_entry]

		cmp	byte [PercentFlag],0
		jne	short vc_14

		;push	word [vc_default_entry]
		mov	ax,v_mbytes_format ; "%4.1d"
		jmp	short vc_15
vc_14:
		;push	word [vc_default_entry]
		mov	ax,v_percent_format ; "%3.1d%%"
vc_15:
		push	ax
		mov	ax,insert
		push	ax
		call	sprintf
		add	sp,6

		;display(menu_40);

		;push	word [menu_40_segment]
		push	ds
		push	word [menu_40_offset]
		call	display
		;pop	bx
		;pop	bx

;input = get_large_num_input(default_entry,free_space[location].mbytes_unused,ext_part_percent_unused,menu_40,u(0),error_12)

		;push	word [error_12_seg]
		push	ds			; glni_err_msg_seg	
		push	word [error_12_off]	; glni_err_msg
		sub	ax,ax
		push	ax			; glni_prompt_loc
		;push	word [menu_40_segment]	
		push	ds			; glni_input_msg_seg
		push	word [menu_40_offset]	; glni_input_msg
		push	word [vc_ext_part_pcent_unused] ; glni_max_pc

		;;mov	al,22
		;mov	al,10
		;;imul	byte [vc_location]
		;mul	byte [vc_location]
		;mov	bx,ax

		;push	word [free_space.mbytes_unused+bx] ; glni_max_num
		push	word [free_space.mbytes_unused+si] ; **--
		push	word [vc_default_entry]	; glni_input_def
		call	get_large_num_input
		;add	sp,16
		mov	[vc_input],ax

	;/* Update default in case of error, so it gets displayed and used */
	;/* if user presses CR only */
	;
	;	default_entry = input;

		mov	[vc_default_entry],ax

		mov	ax,79
		push	ax
		mov	ax,23
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,19
		push	ax
		call	clear_screen
		;add	sp,8

		;while (!valid_input)

		cmp	byte [valid_input],0
		je	short vc_13

		;if (input != ((unsigned)(ESC_FLAG)))  

		cmp	word [vc_input],0FFFEh
		jne	short vc_16
		;jmp	vc_26
		jmp	vc_27
vc_16:
		; /* Change input to cylinders */

		;;mov	al,22
		;mov	al,10
		;;imul	byte [vc_location]
		;mul	byte [vc_location]
		;mov	bx,ax

		mov	ax,[vc_input]

		cmp	byte [PercentFlag],0
		je	short vc_19

;if (input == ext_part_percent_unused)
;   input = free_space[location].space;
;else
;   input = percent_to_cylinders(input,((part_table[cur_disk][ext_part_num].end_cyl-
;           part_table[cur_disk][ext_part_num].start_cyl)+1));

		;mov	ax,[vc_input]

		cmp	[vc_ext_part_pcent_unused],ax
		jne	short vc_18

		;;mov	al,22
		;mov	al,10
		;;imul	byte [vc_location]
		;mul	byte [vc_location]
		;mov	bx,ax
vc_17:
		;mov	ax,[free_space.space+bx]
		mov	ax,[free_space.space+si]
		jmp	short vc_21
vc_18:
		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;;add	ax,[vc_ext_part_num]
		;shl	al,1
		;shl	al,1
		;add	al,[vc_ext_part_num]
		;;mov	cx,46
		;;mul	cx
		;mov	cl,46
		;mul	cl
		;mov	bx,ax

		;mov	ax,[part_table_end_cyl+bx]
		;sub	ax,[part_table_start_cyl+bx]
		;inc	ax
		;push	ax

		;mov	cx,[part_table_end_cyl+bx]
		;sub	cx,[part_table_start_cyl+bx]
		;inc	cx ; available volume size in cylinders

		mov	cx,di ; ***--
		
		;push	word [vc_input]
		;mov	ax,[vc_input]  ; percentage input
		call	percent_to_cylinders  ; convert percent to cylinders

		mov	byte [PercentFlag],0

		jmp	short vc_20
vc_19:
		;;mov	al,22
		;mov	al,10
		;;imul	byte [vc_location]
		;mul	byte [vc_location]
		;mov	bx,ax

	;if (input == free_space[location].mbytes_unused)
	;    input = free_space[location].space;
	;else
	;    input = (unsigned)mbytes_to_cylinders(input,cur_disk); 

		;mov	ax,[vc_input]

		;cmp	[free_space.mbytes_unused+bx],ax
		cmp	[free_space.mbytes_unused+si],ax
		je	short vc_17

		;mov	al,[cur_disk]
		;push	ax		; mtc_which_disk
		push	word [cur_disk]
		push	word [vc_input] ; mtc_mbytes_in
		call	mbytes_to_cylinders
vc_20:
		;pop	bx
		;pop	bx
vc_21:
		;mov	[vc_input],ax

		;/* Initialize PecentFlag back to FALSE */
		; PercentFlag = (FLAG)FALSE;   

		;mov	byte [PercentFlag],0

		;Display error message if input value = 0 */

		or	ax,ax ; cylinders
		jnz	short vc_22

		;push	word [error_28_seg]
		push	ds
		push	word [error_28_off]
		call	display
		;pop	bx
		;pop	bx

		call	wait_for_ESC
		;jmp	vc_26
		jmp	vc_1
vc_22:
		;/* go create the entry and find out where it put it */
		;ext_location = make_volume(input,location);

		;mov	al,[vc_location]
		;push	ax
		push	word [vc_location] ; mv_free_ptr
		;push	word [vc_input]
		;mov	ax,[vc_input]
		push	ax ; volume size, mv_size
		call	make_volume
		;pop	bx
		;pop	bx

		;/* clear off the old prompt */
		
		mov	ax,79
		push	ax
		mov	ax,19
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,15
		push	ax
		call	clear_screen
		;add	sp,8

		mov	byte [reboot_flag],1 ; reboot_flag = (FLAG)TRUE;  

		;/* Display the updated partition information */ 
   
		call	volume_display

		;/* Tell user we created it */

		;push	word [status_7_seg]
		push	ds
		push	word [status_7_off]
		call	display
		;pop	bx
		;pop	bx
		;jmp	short vc_26
		jmp	vc_1
vc_23:
		;/* No space left or already max'd on the devices */
		;/* Get rid of the size prompts */
		;clear_screen(u(17),u(0),u(21),u(79));
		;display(error_20);
		;volume_display();
		;wait_for_ESC();
		;input = u(ESC_FLAG);

		mov	ax,79
		push	ax
		mov	ax,21
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,17
		push	ax
		call	clear_screen
		;add	sp,8

		;push	word [error_20_seg]
		push	ds
		push	word [error_20_off]
		call	display
		;pop	bx
		;pop	bx
		call	volume_display
		jmp	short vc_25
vc_24:	 
		;/* Reached the maximum */
		;/* Get rid of the size prompts */
		;clear_screen(u(17),u(0),u(21),u(79));
		;display(error_27);

		mov	ax,79
		push	ax
		mov	ax,21
		push	ax
		sub	ax,ax
		push	ax
		mov	ax,17
		push	ax
		call	clear_screen
		;add	sp,8

		;push	word [error_27_seg]
		push	ds
		push	word [error_27_off]
		call	display
		;pop	bx
		;pop	bx
vc_25:		
		;/* Force an exit with ESC */

		call	wait_for_ESC ; wait_for_ESC();    
		;mov	word [vc_input],0FFFEh ; input = u(ESC_FLAG);  
;		jmp	short vc_27
;
;		;while (input != ((unsigned)(ESC_FLAG)))
;vc_26:
;		cmp	word [vc_input],0FFFEh
;		je	short vc_27
;		jmp	vc_1
vc_27:
		;clear_screen(u(0),u(0),u(24),u(79));      

		;mov	ax,79
		;push	ax
		;mov	ax,24
		;push	ax
		;sub	ax,ax
		;push	ax
		;push	ax
		;call	clear_screen
		;add	sp,8
		
		call	CLS

		;pop	si

		mov	sp,bp
		pop	bp

		;return;
		retn

; ----------------------------------------------------------------------------
; space.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 14/01/2019)

;char find_part_free_space(type)
;
;char   type;
;
;BEGIN
;
;char        i;
;char        partition_count;
;char        last_found_partition;
;unsigned    temp;
;char        freespace_count;
;char        any_partition;
;unsigned    temp_size;
;
;        /* Sort the partition table */
;        sort_part_table(c(4));                                          /* AC000 */
;
;        /* Intialize free space to zero */
;        for (i = c(0); i < c(5); i++)                                   /* AC000 */
;           BEGIN
;            free_space[i].space = u(0);                                 /* AC000 */
;            free_space[i].start = u(0);                                 /* AC000 */
;            free_space[i].end = u(0);                                   /* AC000 */
;            free_space[i].mbytes_unused = f(0);                         /* AC000 */  /* AN000 */
;            free_space[i].percent_unused = u(0);                        /* AC000 */  /* AN000 */
;           END
;
;        /* Find space between start of disk and first partition */
;        partition_count = c(0);                                         /* AC000 */
;
;        any_partition = FALSE;
;        for (i = c(0); i < c(4); i++)                                   /* AC000 */
;           BEGIN
;            if (part_table[cur_disk][sort[i]].sys_id != uc(0))          /* AC000 */
;               BEGIN
;                /* Found a partition, get the space */
;
;                free_space[0].start = u(0);                             /* AC000 */
;
;                /* This is a special case - the extended partition can not start */
;                /* on cylinder 0 due too its archetecture. Protect against that here */
;                if (type == c(EXTENDED))                                /* AC000 */
;                   BEGIN
;                    free_space[0].start = u(1);                         /* AC000 */
;                  END
;
;                /* free space ends before start of next valid partition */
;                if (part_table[cur_disk][sort[i]].start_cyl > u(0))     /* AC000 */
;                   BEGIN
;                    free_space[0].end = part_table[cur_disk][sort[i]].start_cyl-1;
;                    free_space[0].space = part_table[cur_disk][sort[i]].start_cyl-free_space[0].start; /*C04*/
;                   END
;
;                free_space[0].mbytes_unused =
;                    cylinders_to_mbytes(free_space[0].space,cur_disk);  /* AN004 */
;                free_space[0].percent_unused = (unsigned)cylinders_to_percent(free_space[0].space,total_disk[cur_disk]); /* AN000 */
;
;                partition_count = i;
;                last_found_partition = sort[i];
;                any_partition = TRUE;
;                break;
;               END
;           END
;        /* See if any partitions were there */
;        if (any_partition)
;           BEGIN
;            /* Look for space between the rest of the partitions */
;            freespace_count = c(1);                                     /* AC000 */
;            for (i = partition_count+1; i < c(4); i++)                  /* AC000 */
;               BEGIN
;                if (part_table[cur_disk][sort[i]].sys_id != uc(0))      /* AC000 */
;                   BEGIN
;                    /* Check to see if more than one partition on a cylinder (i.e. XENIX bad block)  */
;                    /* If so, leave the space at zero */
;
;                    if (part_table[cur_disk][sort[i]].start_cyl != part_table[cur_disk][last_found_partition].end_cyl)
;                       BEGIN
;                        /* No, things are normal */
;                        /* Get space between the end of the last one and the start of the next one */
;                        free_space[freespace_count].space = part_table[cur_disk][sort[i]].start_cyl
;                           - (part_table[cur_disk][last_found_partition].end_cyl+1);
;
;                        temp_size = (part_table[cur_disk][sort[i]].start_cyl -
;                             part_table[cur_disk][last_found_partition].end_cyl);
;
;                        if (temp_size != u(0) )                         /* AC000 */
;                           BEGIN
;                            free_space[freespace_count].space = temp_size - u(1);  /* AC000 */
;                           END
;                       END
;
;                    free_space[freespace_count].start = part_table[cur_disk][last_found_partition].end_cyl+1;
;                    free_space[freespace_count].end = part_table[cur_disk][sort[i]].start_cyl -1;
;                    free_space[freespace_count].mbytes_unused =
;                         cylinders_to_mbytes(free_space[freespace_count].space,cur_disk); /* AN004 */
;                    free_space[freespace_count].percent_unused = (unsigned)
;                         cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]);  /* AN000 */
;
;                    /* update the last found partition */
;                    last_found_partition = sort[i];
;                    freespace_count++;
;                   END
;               END
;            /* Find the space between the last partition and the end of the disk */
;            /* SR; 10/10/89; Make sure that freespace cannot become negative */
;
;            if ( total_disk[cur_disk] >
;                 part_table[cur_disk][last_found_partition].end_cyl )
;               {
;            	free_space[freespace_count].space = (total_disk[cur_disk]
;                                     	-  part_table[cur_disk][last_found_partition].end_cyl)-1;
;            	free_space[freespace_count].start = part_table[cur_disk][last_found_partition].end_cyl+1;
;            	free_space[freespace_count].end = total_disk[cur_disk]-1;
;            	free_space[freespace_count].mbytes_unused =
;                 	cylinders_to_mbytes(free_space[freespace_count].space,cur_disk);    /* AN004 */
;            	free_space[freespace_count].percent_unused =
;                 	cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]); /* AN000 */
;               }
;            END
;         else
;           BEGIN
;            /* No partitions found, show entire space as free */
;            free_space[0].start = u(0);                                 /* AC000 */
;
;            /* This is a special case - the extended partition can not start */
;            /* on cylinder 0 due too its architecture. Protect against that here */
;            if (type == c(EXTENDED))                                    /* AC000 */
;               BEGIN
;                free_space[0].start = u(1);                             /* AC000 */
;               END
;            free_space[0].end = total_disk[cur_disk]-1;
;            free_space[0].space = (free_space[0].end - free_space[0].start)+1;
;            free_space[0].mbytes_unused =
;                 cylinders_to_mbytes(free_space[0].space,cur_disk);    /* AN004 */
;            free_space[0].percent_unused =
;                 cylinders_to_percent(free_space[0].space,total_disk[cur_disk]); /* AN000 */
;           END
;
;         /* Find largest free space, and verify the golden tracks while we are at it */
;         do
;            BEGIN
;             temp = u(0);                                               /* AC000 */
;
;             /* Zip thru the table */
;             for (i = c(0); i < c(5); i++)                              /* AC000 */
;                BEGIN
;                 /* Is this one bigger ? */
;                 if (free_space[i].space > temp)
;                    BEGIN
;                     temp = free_space[i].space;
;                     last_found_partition = i;
;                    END
;                END
;
;             /* If there is any free space, go verify it */
;             temp = u(0);
;             if (free_space[last_found_partition].space != u(0))        /* AC000 */
;               BEGIN
;                /* Go verify the tracks */
;                temp = verify_tracks(last_found_partition,c(PRIMARY));  /* AC000 */
;               END
;             /* Move up to next golden track */
;             free_space[last_found_partition].start = free_space[last_found_partition].start+temp;
;             free_space[last_found_partition].space = free_space[last_found_partition].space-temp;
;             free_space[last_found_partition].mbytes_unused =
;                  cylinders_to_mbytes(free_space[last_found_partition].space,cur_disk);    /* AN004 */
;             free_space[last_found_partition].percent_unused = (unsigned)
;                  cylinders_to_percent(free_space[last_found_partition].space,total_disk[cur_disk]);                      /* AN000 */
;             END
;
;            /* Repeat the loop if the start was moved due to bad tracks */
;            /* Unless we're past the end of the free space */
;            while ((temp != u(0)) && (free_space[last_found_partition].space != u(0)));    /* AC000 */
;
;        /* Don't create a partition larger than DOS can handle */                                       /*C05*/
;        if((type == c(PRIMARY)) && (free_space[last_found_partition].mbytes_unused > u(MAX_PART_SIZE))) /*C05*/
;          BEGIN                                                                                         /*C05*/
;          free_space[last_found_partition].space =                                                      /*C05*/
;           mbytes_to_cylinders(f(MAX_PART_SIZE),cur_disk) - 1;                                          /*C05*/
;          free_space[last_found_partition].end =                                                        /*C05*/
;           free_space[last_found_partition].start+free_space[last_found_partition].space-1;             /*C05*/
;          free_space[last_found_partition].mbytes_unused =                                              /*C05*/
;           cylinders_to_mbytes(free_space[last_found_partition].space,cur_disk);                        /*C05*/
;          free_space[last_found_partition].percent_unused = (unsigned)                                  /*C05*/
;           cylinders_to_percent(free_space[last_found_partition].space,total_disk[cur_disk]);           /*C05*/
;          END                                                                                           /*C05*/
;
;        /* Return with the pointer to the largest free space */
;        return(last_found_partition);
;END

find_part_free_space:
		; 17/01/2019
		; 14/01/2019

	%define fpfs_type	bp-12 ; 25/01/2019

	%define fpfs_i			bp-10	;bp-14
	%define last_found_partition	bp-8	;bp-12
	%define fpfs_temp		bp-6	;bp-10
	%define freespace_count		bp-4	;bp-8
	%define fpfs_partition_count	bp-2	;bp-6
	;%define fpfs_anypartition		;bp-4

	;%define fpfs_type	bp+4

		push	bp
		mov	bp,sp
		;;sub	sp,14
		;sub	sp,10  ; 20/01/2019
		sub	sp,12  ; 25/01/2019

		;push	di
		;push	si

  		;/* Sort the partition table */

		;mov	al,4
		;push	ax
		mov	cl,4
		call	sort_part_table
		;pop	bx

		;/* Initialize free space to zero */

		;mov	byte [fpfs_i],0
fpfs_1:
		;mov	al,22
		;;imul	byte [fpfs_i]
		;mul	byte [fpfs_i]
		;mov	bx,ax
		;sub	ax,ax ; 0
		;mov	[free_space.space+bx],ax
		;mov	[free_space.start+bx],ax
		;mov	[free_space.end+bx],ax
		;mov	[free_space.mbytes_unused+bx],ax
		;mov	[free_space.percent_unused+bx],ax
		;inc	byte [fpfs_i]
		;cmp	byte [fpfs_i],5
		;jl	short fpfs_1
		
		;push	cs
		;pop	es
		mov	di,fspc ; free_space.space
		mov	cx,5*5 ; (5*10/2) ; 17/01/2019
		xor	ax,ax ; 0
		rep	stosw

		;sub	al,al
		mov	[fpfs_partition_count],al ; 0
		;mov	[fpfs_anypartition],al ; 0
		mov	[fpfs_i],al ; 0
		jmp	short fpfs_3
fpfs_2:	
		inc	byte [fpfs_i]
;fpfs_3:
		cmp	byte [fpfs_i],4
		jb	short fpfs_4
		;jmp	fpfs_7
		jmp	fpfs_16
fpfs_4:
	; /* Find space between start of disk and first partition */

		; 17/01/2019
		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;;mov	cx,ax
		;shl	al,1
		;shl	al,1
		;mov	cl,al

		mov	al,[fpfs_i]
		;cbw
		xor	ah,ah
fpfs_3:
		; 17/01/2019
		mov	cl,[cur_disk]
		shl	cl,1
		shl	cl,1

		mov	bx,ax

		mov	al,[sort+bx]
		;cbw
		;add	ax,cx
		add	al,cl

		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax

		cmp	byte [part_table_sys_id+bx],0
		je	short fpfs_2

		xor	ax,ax

		;free_space[0].start = u(0);  

		;mov	word [free_space.start],0
		cmp	byte [fpfs_type],5  ; EXTENDED
		jne	short fpfs_5

	;/* This is a special case - the extended partition can not start */
	;/* on cylinder 0 due too its architecture. Protect against that here */

		;free_space[0].start = u(1);  

		;mov	word [free_space_start],1

		inc	al  ; ax = 1
fpfs_5:
		;/* Found a partition, get the space */	

		mov	[free_space.start],ax ; 0 or 1

		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;;mov	cx,ax
		;mov	cl,al
		;mov	al,[fpfs_i]
		;;cbw
		;; ah = 0
		;mov	bx,ax
		;mov	al,[sort+bx]
		;;cbw
		;;add	ax,cx
		;add	al,cl
		;;mov	cx,46
		;;imul	cx
		;mov	cl,46
		;mul	cl	
		;mov	bx,ax

		;/* free space ends before start of next valid partition */
		
		;cmp	word [part_table_start_cyl+bx],0
		;je	short fpfs_6
		;mov	ax,[part_table_start_cyl+bx]
		
		mov	ax,[part_table_start_cyl+bx]
		or	ax,ax
		jz	short fpfs_6

	;free_space[0].end = part_table[cur_disk][sort[i]].start_cyl-1;
	;free_space[0].space = part_table[cur_disk][sort[i]].start_cyl-free_space[0].start;

		mov	cx,ax
		dec	ax 
		mov	[free_space.end],ax
		sub	cx,[free_space.start]
		mov	[free_space.space],cx
fpfs_6:	
	;free_space[0].mbytes_unused = cylinders_to_mbytes(free_space[0].space,cur_disk);

		;mov	al,[cur_disk]
		;push	ax
		;push	word [free_space.space]

		mov	bl,[cur_disk]
		xor	bh,bh

		mov	ax,[free_space.space]

		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx

		mov	[free_space.mbytes_unused],ax

;free_space[0].percent_unused = cylinders_to_percent(free_space[0].space,total_disk[cur_disk]);

		mov	al,[cur_disk]
		cbw
		mov	bx,ax
		shl	bx,1
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx]	; Total (disk) cylinders -divisor-
		;push	word [free_space.space]
		mov	bx,[free_space.space]	; Partition cylinders -dividend-

		call	cylinders_to_percent
		;pop	bx
		;pop	bx

		mov	[free_space.percent_unused],ax

		;partition_count = i;
		;last_found_partition = sort[i];
		;any_partition = TRUE;

		mov	al,[fpfs_i]
		mov	[fpfs_partition_count],al
		cbw
		mov	bx,ax
		mov	al,[sort+bx]
		mov	[last_found_partition],al
		;mov	byte [fpfs_anypartition],1
;fpfs_7:	
;		;/* See if any partitions were there */
;		cmp	byte [fpfs_anypartition],0
;		jne	short fpfs_8
;		jmp	fpfs_16
fpfs_8:	
		;/* Look for space between the rest of the partitions */

		mov	byte [freespace_count],1
		mov	al,[fpfs_partition_count]
		inc	al
		mov	[fpfs_i],al
		jmp	fpfs_13
fpfs_9:
		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	cx,ax
		mov	cl,[cur_disk]
		shl	cl,1
		shl	cl,1   ; =**=
		mov	al,[fpfs_i]
		cbw
		mov	bx,ax
		mov	al,[sort+bx]
		;cbw
		;add	ax,cx
		add	al,cl  ; =**=
		;mov	bx,46
		;imul	bx
		mov	bl,46
		mul	bl
		mov	si,ax  ; ****
	
	;if (part_table[cur_disk][sort[i]].sys_id != uc(0))

		cmp	byte [part_table_sys_id+si],0 ;****
		;jne	short fpfs_10
		;jmp	fpfs_12
		je	short fpfs_12 ; 17/01/2019
fpfs_10:
	;/* Check to see if more than one partition on a cylinder (i.e. XENIX bad block)  */
	;/* If so, leave the space at zero */

;if (part_table[cur_disk][sort[i]].start_cyl != part_table[cur_disk][last_found_partition].end_cyl)

		mov	al,[last_found_partition]
		;cbw
		;add	ax,cx
		add	al,cl ; =**=
		;imul	bx
		mul	bl
		mov	bx,ax
		;mov	ax,[part_table_end_cyl+bx]
		mov	dx,[part_table_end_cyl+bx] ;****	
		;cmp	[part_table_start_cyl+si],ax
		;je	short fpfs_11

		mov	al,10
		mul	byte [freespace_count]
		mov	di,ax  ;***

		cmp	[part_table_start_cyl+si],dx  ;****
		je	short fpfs_11
		
	;/* No, things are normal */
	;/* Get space between the end of the last one and the start of the next one */

	; free_space[freespace_count].space = part_table[cur_disk][sort[i]].start_cyl
	;                           - (part_table[cur_disk][last_found_partition].end_cyl+1);

		;sub	ax,[part_table_start_cyl+si]
		;neg	ax
		;dec	ax
		;mov	dx,ax
		
		;;mov	al,22
		;mov	al,10
		;;imul	byte [freespace_count]
		;mul	byte [freespace_count]
		;mov	bx,ax

		;mov	[free_space.space+bx],dx  ; free_space[freespace_count].space

		mov	ax,dx  ; part_table[cur_disk][last_found_partition].end_cyl
		sub	ax,[part_table_start_cyl+si] ; part_table[cur_disk][sort[i]].start_cyl
		neg	ax
		dec	ax  ; - 1		

		mov	[free_space.space+di],ax  ; free_space[freespace_count].space
fpfs_11:
	;free_space[freespace_count].start = part_table[cur_disk][last_found_partition].end_cyl+1;
        ;free_space[freespace_count].end = part_table[cur_disk][sort[i]].start_cyl-1;
        ;free_space[freespace_count].mbytes_unused =
        ;	cylinders_to_mbytes(free_space[freespace_count].space,cur_disk);
        ;free_space[freespace_count].percent_unused = (unsigned)
        ;       cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]);

		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	cx,ax
		;mov	al,[last_found_partition]
		;cbw
		;add	ax,cx
		;mov	bx,46
		;imul	bx
		;mov	si,ax
		;mov	ax,[part_table_end_cyl+si]
		;inc	ax
		;mov	dx,ax
		
		inc	dx ;  part_table[cur_disk][last_found_partition].end_cyl+1

		;mov	al,22
		;imul	byte [freespace_count]
		;mov	si,ax
		;mov	[free_space.start+si],dx
		
		mov	[free_space.start+di],dx ; ***
		
		mov	al,[fpfs_i]
		cbw
		;mov	di,ax
		;mov	al,[sort+di]
		mov	bx,ax
		mov	al,[sort+bx]		

		;cbw
		;add	ax,cx
		add	al,cl ; =**=
		
		;mov	cl,[cur_disk]
		;imul	bx
		;mov	bx,ax

		; 17/01/2019
		mov	cl,46
		mul	cl
		mov	si,ax
		
		;mov	ax,[part_table_start_cyl+bx]
		mov	ax,[part_table_start_cyl+si] ;****
		dec	ax
		;mov	[free_space.end+si],ax
		mov	[free_space.end+di],ax ;***

		;mov	al,[cur_disk]
		;push	ax
		;push	word [free_space.space+si]
		
		mov	bl,[cur_disk]
		; bh = 0
		mov	ax,[free_space.space+di] ;***
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		;mov	[free_space.mbytes_unused+si],ax
		
		mov	[free_space.mbytes_unused+di],ax ;***

		mov	al,[cur_disk]
		cbw
		mov	bx,ax
		shl	bx,1
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx] ; -divisor-
		;push	word [free_space.space+si]
		mov	bx,[free_space.space+di] ;*** -dividend-
		call	cylinders_to_percent
		;pop	bx
		;pop	bx

		;mov	[free_space.percent_unused+si],ax
		mov	[free_space.percent_unused+di],ax ;***

		; 17/01/2019
		;mov	al,[sort+di]

		mov	bl,[fpfs_i]
		xor	bh,bh
		mov	al,[sort+bx]
		
		mov	[last_found_partition],al

		inc	byte [freespace_count]
fpfs_12:
		inc	byte [fpfs_i]
fpfs_13:
	;  for (i = partition_count+1; i < c(4); i++)

		cmp	byte [fpfs_i],4
		jge	short fpfs_14
		jmp	fpfs_9
fpfs_14:
	;/* Find the space between the last partition and the end of the disk */
	;/* Make sure that freespace cannot become negative */
	;
	;  if ( total_disk[cur_disk] >
	;     part_table[cur_disk][last_found_partition].end_cyl )

		mov	al,[cur_disk]
		cbw
		;mov	bx,ax
		;mov	al,[last_found_partition]
		;cbw
		;mov	cx,bx
		;shl	bx,1
		;shl	bx,1
		;add	ax,bx
		shl	al,1
		mov	si,ax
		shl	al,1
		add	al,[last_found_partition]
		;mov	bx,46
		;imul	bx
		;mov	bx,ax
		;mov	si,cx
		;shl	si,1
		mov	cl,46
		mul	cl
		mov	bx,ax
		mov	ax,[total_disk+si]
		cmp	[part_table_end_cyl+bx],ax
		jb	short fpfs_15
		jmp	fpfs_18
fpfs_15:
	;free_space[freespace_count].space = (total_disk[cur_disk]
	;      	-  part_table[cur_disk][last_found_partition].end_cyl)-1;
	;free_space[freespace_count].start = part_table[cur_disk][last_found_partition].end_cyl+1;
	;free_space[freespace_count].end = total_disk[cur_disk]-1;
	;free_space[freespace_count].mbytes_unused =
	;      	cylinders_to_mbytes(free_space[freespace_count].space,cur_disk);
	;free_space[freespace_count].percent_unused =
	;      	cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]);

		mov	cx,ax
		sub	ax,[part_table_end_cyl+bx]
		dec	ax
		mov	dx,ax
		;mov	al,22
		mov	al,10
		;imul	byte [freespace_count]
		mul	byte [freespace_count]
		mov	si,ax
		mov	[free_space.space+si],dx
		mov	ax,[part_table_end_cyl+bx]
		inc	ax
		mov	[free_space.start+si],ax
		dec	cx
		mov	[free_space.end+si],cx
		
		;mov	al,[cur_disk]
		;push	ax
		mov	bl,[cur_disk]
		xor	bh,bh
		;push	word [free_space.space+si]
		mov	ax,[free_space.space+si]
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		mov	[free_space.mbytes_unused+si],ax
		mov	al,[cur_disk]
		cbw
		mov	bx,ax
		shl	bx,1
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx]
		;push	word [free_space.space+si]
		mov	bx,[free_space.space+si]
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[free_space.percent_unused+si],ax
		jmp	short fpfs_18
fpfs_16:
		;/* No partitions found, show entire space as free */

		;free_space[0].start = u(0);

		sub	ax,ax
		;mov	word [free_space.start],0

	;/* This is a special case - the extended partition can not start */
	;/* on cylinder 0 due too its architecture. Protect against that here */
	;if (type == c(EXTENDED))
	;   BEGIN
	;      free_space[0].start = u(1);
	;   END
		cmp	byte [fpfs_type],5 ; EXTENDED
		jne	short fpfs_17
		
		;mov	word [free_space.start],1
		inc	al
fpfs_17:
		mov	[free_space.start],ax ; 0 or 1

	;free_space[0].end = total_disk[cur_disk]-1;
	;free_space[0].space = (free_space[0].end - free_space[0].start)+1;
	;free_space[0].mbytes_unused =
	;     cylinders_to_mbytes(free_space[0].space,cur_disk);
	;free_space[0].percent_unused =
	;     cylinders_to_percent(free_space[0].space,total_disk[cur_disk]);

		mov	al,[cur_disk]
		cbw
		;mov	bx,ax
		;shl	bx,1
		;mov	ax,[total_disk+bx]
		shl	al,1
		mov	si,ax
		mov	ax,[total_disk+si] 
		dec	ax
		mov	[free_space.end],ax
		sub	ax,[free_space.start]
		inc	ax
		mov	[free_space.space],ax
		;mov	cl,[cur_disk]
		;push	cx
		;push	ax
		xor	bh,bh
		mov	bl,[cur_disk]
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		mov	[free_space.mbytes_unused],ax
		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;shl	bx,1
		;push	word [total_disk+bx]
		mov	cx,[total_disk+si] 
		;push	word [free_space.space]
		mov	bx,[free_space.space]
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[free_space.percent_unused],ax
fpfs_18:
	;/* Find largest free space, and verify the golden tracks while we are at it */
	;         do
	;            BEGIN
	;             temp = u(0);
	;
	;             /* Zip thru the table */
	;             for (i = c(0); i < c(5); i++)
	;                BEGIN
	;                 /* Is this one bigger ? */
	;                 if (free_space[i].space > temp)
	;                    BEGIN
	;                     temp = free_space[i].space;
	;                     last_found_partition = i;
	;                    END
	;                END

		sub	ax,ax
		mov	[fpfs_temp],ax ; 0
		mov	[fpfs_i],al ; 0
fpfs_19:
		;mov	al,22
		mov	al,10
		;imul	byte [fpfs_i]
		mul	byte [fpfs_i]
		mov	bx,ax
		; 17/01/2019
		;mov	ax,[fpfs_temp]
		;cmp	[free_space.space+bx],ax
		;jbe	short fpfs_20
		mov	ax,[free_space.space+bx] 
		cmp	ax,[fpfs_temp]
		jbe	short fpfs_20
		;mov	ax,[free_space.space+bx]
		mov	[fpfs_temp],ax
		mov	al,[fpfs_i]
		mov	[last_found_partition],al
fpfs_20:
		inc	byte [fpfs_i]

		cmp	byte [fpfs_i],5
		jb	short fpfs_19

		;/* If there is any free space, go verify it */

		mov	word [fpfs_temp],0

		;mov	al,22
		;imul	byte [last_found_partition]
		mov	al,10
		mul	byte [last_found_partition]
		mov	bx,ax

	;if (free_space[last_found_partition].space != u(0))
	;   BEGIN
	;     /* Go verify the tracks */
	;    temp = verify_tracks(last_found_partition,c(PRIMARY));
	;  END
		cmp	word [free_space.space+bx],0
		je	short fpfs_21

		sub	al,al ; 0 ; type = PRIMARY
		push	ax
		mov	al,[last_found_partition] ; pointer
		push	ax
		call	verify_tracks
		;pop	bx
		;pop	bx
		mov	[fpfs_temp],ax	; offset from original cylinder number
fpfs_21:

; /* Move up to next golden track */
;free_space[last_found_partition].start = free_space[last_found_partition].start+temp;
;free_space[last_found_partition].space = free_space[last_found_partition].space-temp;
;free_space[last_found_partition].mbytes_unused =
;        cylinders_to_mbytes(free_space[last_found_partition].space,cur_disk);
;free_space[last_found_partition].percent_unused = (unsigned)
;        cylinders_to_percent(free_space[last_found_partition].space,total_disk[cur_disk]);

		;mov	al,22
		mov	al,10
		;imul	byte [last_found_partition]
		mul	byte [last_found_partition] 
		mov	bx,ax
		mov	ax,[fpfs_temp]
		add	[free_space.start+bx],ax
		;mov	cl,[cur_disk]
		;push	cx
		sub	[free_space.space+bx],ax
		;push	word [free_space.space+bx]
		mov	ax,[free_space.space+bx]
		mov	si,bx ; *
		mov	bl,[cur_disk]
		; bh = 0
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		mov	[free_space.mbytes_unused+si],ax ; *
		
		mov	al,[cur_disk]
		cbw
		mov	bx,ax
		shl	bx,1
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx]
		;push	word [free_space.space+si]
		mov	bx,[free_space.space+si] ; *
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[free_space.percent_unused+si],ax ; *

	;/* Repeat the loop if the start was moved due to bad tracks */
	;/* Unless we're past the end of the free space */
	; while ((temp != u(0)) && (free_space[last_found_partition].space != u(0))); 

		sub	ax,ax ; 17/01/2019

		;cmp	word [fpfs_temp],0
		cmp	[fpfs_temp],ax ; 0
		je	short fpfs_22

		;;mov	al,22
		;mov	al,10
		;;imul	byte [last_found_partition]
		;mul	byte [last_found_partition]
		;mov	bx,ax
		;cmp	word [free_space.space+bx],0
		;je	short fpfs_22
		;jmp	fpfs_18

		; 17/01/2019
		;cmp	word [free_space.space+si],0 ; *
		cmp	[free_space.space+si],ax ; 0
		je	short short fpfs_22
		jmp	fpfs_18
fpfs_22:
;if((type == c(PRIMARY)) && (free_space[last_found_partition].mbytes_unused > u(MAX_PART_SIZE)))

		;cmp	byte [fpfs_type],0 ; 0 for primary dos partition
		cmp	[fpfs_type],al ; 0
		jne	short fpfs_23	   ; 5 for extended partition	
		
		; 17/01/2019

		;;mov	al,22
		;mov	al,10
		;;imul	byte [last_found_partition]
		;mul	byte [last_found_partition]
		;mov	bx,ax

	;/* Don't create a partition larger than DOS can handle */

fefs_18: ; 20/01/2019
		;cmp	word [free_space.mbytes_unused+bx],2048 ; 2GB limit
		cmp	word [free_space.mbytes_unused+si],2048 ; 17/01/2019
		jbe	short fpfs_23

		mov	al,[cur_disk]
		;xor	ah,ah ; ah = 0
		;mov	di,ax ; *

		push	ax ; * ; 19/01/2019

		push	ax
		mov	ax,2048
		push	ax
		;mov	si,bx
		call	mbytes_to_cylinders
		;pop	bx
		;pop	bx

		pop	di ; * ; 20/01/2019

		dec	ax  ; max. available cylinders (for DOS partition)

		mov	[free_space.space+si],ax
		
		;mov	ax,[free_space.start+si]
		;add	ax,[free_space.space+si]

		add	ax,[free_space.start+si]
 
		dec	ax
		mov	[free_space.end+si],ax

		;mov	al,[cur_disk]
		;push	ax
		;push	word [free_space.space+si]
		mov	ax,[free_space.space+si]
		mov	bx,di ; *
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx

		mov	[free_space.mbytes_unused+si],ax

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;mov	bx,di ; *
		;shl	bl,1
		;;push	word [total_disk+bx]
		;mov	cx,[total_disk+bx]
		shl	di,1 ; *
		mov	cx,[total_disk+di] ; 20/01/2019 
		;push	word [free_space.space+si]
		mov	bx,[free_space.space+si]
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[free_space.percent_unused+si],ax
fpfs_23:
	; /* Return with the pointer to the largest free space */

		mov	al,[last_found_partition] ; mov al,[bp-8]

		;pop	si
		;pop	di

		mov	sp,bp
		pop	bp
		retn

; ----------------------------------------------------------------------------
; input.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 17/01/2019)

;XFLOAT get_large_num_input(input_default,max_num,max_percent,input_message,prompt_location,error_message)
;
;unsigned    input_default;                                          /* AC000 */
;unsigned    max_num;
;unsigned    max_percent;
;char far   *input_message;
;char far   *error_message;
;unsigned   prompt_location;
;
;BEGIN
;
;    char           input;
;    XFLOAT         large_input;                                     /* AC000 */
;    char           default_used;
;    FLAG           enter_flag;                                       /*C12*/
;
;    /* Assume bad input */
;    valid_input = FALSE;
;
;    /* Assume no input, and use default */
;    default_used = TRUE;
;
;    /* Assume ENTER key not pressed yet */                           /*C12*/
;    enter_flag = FALSE;                                              /*C12*/
;
;    /* Initialize the input value */
;    large_input = u(0);                                             /* AC000 */
;
;    /* Loop until we get good stuff */
;    while (valid_input == FALSE)
;
;        BEGIN
;        /* position the cursor */
;        VIOSETCURPOS(input_row,input_col,u(0));                     /* AC000 */
;
;        /* Flush the keyboard buffer and get the next pressed key */
;
;        input = get_char_input();
;
;        /* Go handle different inputs */
;        switch(input)
;            BEGIN
;            case ESC:
;                valid_input = TRUE;
;                large_input = ((unsigned)(ESC_FLAG));
;                break;
;
;            case CR:
;                BEGIN
;                if (PercentFlag)
;                    BEGIN
;                    /* Set the input to the default if there is one there and nothing else entered */
;                    if ((input_default != u(NUL)) && (default_used))  /* AC000 */
;                        large_input = input_default;
;                    /* See if input is less or equal to max_value */
;                    if (large_input <= max_percent)
;                        BEGIN
;                        if (large_input != u(0))
;                            valid_input = TRUE;
;                        else
;                            display(error_28);
;                        END
;                    else
;                        display(error_message);
;                    END
;                else
;                    BEGIN
;                    /* Set the input to the default if there is one there and nothing else entered */
;                    if ((input_default != u(NUL)) && (default_used))  /* AC000 */
;                        large_input = input_default;
;                    /* See if input is less or equal to max_value */
;                    if (large_input <= max_num)
;                        BEGIN
;                        if (large_input != u(0))
;                            valid_input = TRUE;
;                        else
;                            display(error_28);
;                        END
;                    else
;                        display(error_message);
;                    END
;                enter_flag = TRUE;                                      /*C12*/
;                break;
;                END
;
;            case BACKSPACE:
;                if (PercentFlag)
;                    PercentFlag = (FLAG)FALSE;                      /* AN000 */
;                else
;                    large_input = large_input / 10;
;
;                /* Indicate that we are not using the default */
;                default_used = FALSE;
;                sprintf(&insert[prompt_location],"%4.0d",large_input);  /* AN000 */
;                display(input_message);
;                break;
;
;            case PERCENT:                                           /* AN000 */
;
;                if (PercentFlag == (FLAG)FALSE)
;                    BEGIN                                           /* AN000 */
;                    PercentFlag = (FLAG)TRUE;                       /* AN000 */
;                    /* Round down if > 999.9 */
;                    if (large_input > u(999))                       /* AN000 */
;                        large_input = (large_input%1000);           /* AN000 */
;                    sprintf(&insert[prompt_location],"%3.0d%%",large_input);  /* AN000 */
;                    /* Indicate that we are not using the default */
;                    default_used = FALSE;                           /* AN000 */
;                    display(input_message);                         /* AN000 */
;                    END                                             /* AN000 */
;                else
;                    display(error_33);                              /* AN000 */
;
;                break;                                              /* AN000 */
;
;            case '0':                                                   /*C12*/
;            case '1':                                                   /*C12*/
;            case '2':                                                   /*C12*/
;            case '3':                                                   /*C12*/
;            case '4':                                                   /*C12*/
;            case '5':                                                   /*C12*/
;            case '6':                                                   /*C12*/
;            case '7':                                                   /*C12*/
;            case '8':                                                   /*C12*/
;            case '9':                                                   /*C12*/
;                if (enter_flag == TRUE)                                 /*C12*/
;                    BEGIN                                               /*C12*/
;                    large_input = u(0);                                 /*C12*/
;                    default_used = FALSE;                               /*C12*/
;                    PercentFlag = FALSE;                                /*C12*/
;                    enter_flag = FALSE;                                 /*C12*/
;                    END                                                 /*C12*/
;                if ((PercentFlag == FALSE) && (large_input < 1000))     /*C12*/
;                    BEGIN                                               /*C12*/
;                    /* Add this digit in */                             /*C12*/
;                    large_input = (large_input * 10) +                  /*C12*/
;                                  (XFLOAT)(input - '0');                /*C12*/
;                                                                        /*C12*/
;                    /* Put it in the message */                         /*C12*/
;                    number_in_msg((XFLOAT)large_input,prompt_location); /*C12*/
;                    display(input_message);                             /*C12*/
;                                                                        /*C12*/
;                    /* Indicate that we are not using the default */    /*C12*/
;                    default_used = FALSE;                               /*C12*/
;                    PercentFlag = (FLAG)FALSE;                          /*C12*/
;                    END                                                 /*C12*/
;                else                                                    /*C12*/
;                    display(error_33);                                  /*C12*/
;                break;                                                  /*C12*/
;                                                                        /*C12*/
;            default:                                                    /*C12*/
;                if ((PercentFlag == FALSE) && (large_input < 1000))     /*C12*/
;                    BEGIN                                               /*C12*/
;                    /* Setup error message */                           /*C12*/
;                    insert[0] = c('0');                                 /*C12*/
;                    insert[1] = c('-');                                 /*C12*/
;                    insert[2] = c('9');                                 /*C12*/
;                    display(error_31);                                  /*C12*/
;                    END                                                 /*C12*/
;                else                                                    /*C12*/
;                    display(error_33);                                  /*C12*/
;            END
;        END
;
;    return(large_input);
;END

get_large_num_input:
		; 17/01/2019

	%define large_input	   bp-8
	%define glni_enter_flag	   bp-6
	%define glni_def_used	   bp-4
	%define glni_input	   bp-2
	%define glni_input_def	   bp+4
	%define glni_max_num	   bp+6
	%define glni_max_pc	   bp+8
	%define glni_input_msg	   bp+10
	%define glni_input_msg_seg bp+12
	%define glni_prompt_loc	   bp+14
	%define glni_err_msg	   bp+16
	%define glni_err_msg_seg   bp+18

		push	bp
		mov	bp,sp
		sub	sp,8
		
		;/* Assume no input, and use default */
		mov	byte [glni_def_used],1 ; default_used = TRUE;

		sub	al,al ; 0

		;/* Assume bad input */
		mov	[valid_input],al ; valid_input = FALSE;

		;/* Assume ENTER key not pressed yet */  
		mov	[glni_enter_flag],al  ; enter_flag = FALSE;   

		;/* Initialize the input value */
		mov	word [large_input],0 ; large_input = u(0);      
		jmp	glni_29
glni_1:
		;/* Loop until we get good stuff */
		;while (valid_input == FALSE)

		;/* position the cursor */
		
		;push	word [input_row]
		;push	word [input_col]
		;sub	ax,ax
		;push	ax
		mov	dh,[input_row]
		mov	dl,[input_col]
		call	VIOSETCURPOS

	;/* Flush the keyboard buffer and get the next pressed key */

		call	get_char_input  ; input = get_char_input();
		mov	[glni_input],al

	; /* Go handle different inputs */
		 ; switch(input)
switch_input12:
		;cbw
		;sub	ax,8
		sub	al,8  ; 08h (8)  - BACKSPACE key
		jnz	short glni_3
		jmp	case_gln_backspace
glni_3:
		;sub	ax,5  ; 0Dh (13) - ENTER/CR key
		sub	al,5
		jz	short case_gln_CR
		;sub	ax,14 ; 1Bh (27) - ESC key
		sub	al,14
		jz	short case_gln_ESC
		;sub	ax,10 ; 25h (37) - '%' character/key
		sub	al,10
		jnz	short glni_4
		jmp	case_gln_percent
glni_4:
		;sub	ax,11 ; 30h (48) - '0' character/key
		sub	al,11 
		jb	short case_gln_default
		;sub	ax,9  ; 39h (57) - '9' character/key
		sub	al,9
		ja	short case_gln_default
		jmp	case_gln_dec_digits ; one of decimal digits
case_gln_default:
		; default:
	;if ((PercentFlag == FALSE) && (large_input < 1000))  
    		cmp	byte [PercentFlag],0
		jne	short glni_6
		cmp	word [large_input], 1000
		jb	short glni_7
glni_6:
		jmp	glni_27  ; else 
				 ;       display(error_33); 
glni_7:
		;/* Setup error message */
		;insert[0] = c('0');
     		;insert[1] = c('-');
                ;insert[2] = c('9');       
		;display(error_31);   
		mov	byte [insert],'0'
		mov	byte [insert+1],'-'
		mov	byte [insert+2],'9'
		;push	word [error_31_seg]
		push	ds
		push	word [error_31_off]
		jmp	glni_28
case_gln_ESC:
		;case ESC:
		mov	byte [valid_input],1  ; valid_input = TRUE;
		;large_input = ((unsigned)(ESC_FLAG));
		mov	word [large_input],0FFFEh
		jmp	glni_29  ; break;
case_gln_CR:
		cmp	byte [PercentFlag],0  ; if (PercentFlag)
		je	short glni_15
	;/* Set the input to the default if there is one there and nothing else entered */
	;if ((input_default != u(NUL)) && (default_used)) 
		cmp	word [glni_input_def],0
		je	short glini_10
		cmp	byte [glni_def_used],0
		je	short glini_10
		mov	ax,[glni_input_def]
		mov	[large_input],ax  ; large_input = input_default;
glini_10:
		;if (large_input <= max_percent)
		mov	ax,[glni_max_pc]
		cmp	[large_input],ax
		ja	short glni_12 ; display(error_message);
		;if (large_input != u(0))
		cmp	word [large_input],0
		je	short glni_17  ; display(error_28);
glni_11:
		mov	byte [valid_input],1  ; valid_input = TRUE;
		jmp	short glni_14
glni_12:
		;display(error_message);
		push	word [glni_err_msg_seg]
		push	word [glni_err_msg]
glni_13:
		call	display
		;pop	bx
		;pop	bx
glni_14:
		mov	byte [glni_enter_flag],1  ; enter_flag = TRUE;
		jmp	glni_29  ; break;
glni_15:
		; else
 	;/* Set the input to the default if there is one there and nothing else entered */
	;if ((input_default != u(NUL)) && (default_used))
		cmp	word [glni_input_def],0
		je	short glni_16
		cmp	byte [glni_def_used],0
		je	short glni_16
		mov	ax,[glni_input_def]
		mov	[large_input],ax ;  large_input = input_default;
glni_16:
		;/* See if input is less or equal to max_value */
		;if (large_input <= max_num)
		mov	ax,[glni_max_num]
		cmp	[large_input],ax
		ja	short glni_12
		;if (large_input != u(0))
		cmp	word [large_input],0
		jne	short glni_11
glni_17:
		;display(error_28);
		;push	word [error_28_seg]
		push	ds
		push	word [error_28_off]
		jmp	short glni_13
case_gln_backspace:
		;case BACKSPACE:
		cmp	byte [PercentFlag],0
		je	short glni_19
		mov	byte [PercentFlag],0  ; PercentFlag = (FLAG)FALSE;   
		jmp	short glni_20
glni_19:
		;large_input = large_input / 10;
		mov	cx,10
		mov	ax,[large_input]
		sub	dx,dx
		div	cx
		mov	[large_input],ax
glni_20:
		;/* Indicate that we are not using the default */
		mov	byte [glni_def_used],0 ; default_used = FALSE;

	;sprintf(&insert[prompt_location],"%4.1d",large_input);

		push	word [large_input]
		mov	ax,glni_num_format ; "%4.1d"
		push	ax
		mov	ax,[glni_prompt_loc]
		add	ax,insert
		push	ax
		call	sprintf
		add	sp,6
		jmp	short glni_24
case_gln_percent:
		;case PERCENT:    
		cmp	byte [PercentFlag],0
		je	short glni_22
		jmp	glni_27
glni_22:
		mov	byte [PercentFlag],1  ; PercentFlag = (FLAG)TRUE;   
		;/* Round down if > 999.9 */
		cmp	word [large_input],999
		jbe	short glni_23
		mov	cx,1000
		mov	ax,[large_input]
		sub	dx,dx
		div	cx
		mov	[large_input],dx
glni_23:
		push	word [large_input]
		mov	ax,percent_format ; "%3.1d%%"
		push	ax
		mov	ax,[glni_prompt_loc]
		add	ax,insert
		push	ax
		call	sprintf
		add	sp,6
		;/* Indicate that we are not using the default */
		mov	byte [glni_def_used],0 ; default_used = FALSE;
glni_24:
		; display(input_message);
		push	word [glni_input_msg_seg]
		push	word [glni_input_msg]
		jmp	short glni_28
case_gln_dec_digits:
		;case '0': 
		;...
            	;case '9':  
		;if (enter_flag == TRUE) 
		cmp	byte [glni_enter_flag],1
		jne	short glni_26
		sub	ax,ax
		;mov	word [large_input],0  ; large_input = u(0);
		mov	[large_input],ax ; 0
		;sub	al,al
		mov	[glni_def_used],al ; default_used = FALSE; 
		mov	[PercentFlag],al ; PercentFlag = FALSE
		mov	[glni_enter_flag],al ; enter_flag = FALSE; 
		jmp	short glni_31  ; 17/01/2019
glni_26:
		;if ((PercentFlag == FALSE) && (large_input < 1000))  
		cmp	byte [PercentFlag],0
		jne	short glni_27
		cmp	word [large_input],1000
		jnb	short glni_27
glni_31:
		;/* Add this digit in */ 
		
	;large_input = (large_input * 10) + (XFLOAT)(input - '0');  

	; /* Put it in the message */
        ;    number_in_msg((XFLOAT)large_input,prompt_location)

		push	word [glni_prompt_loc] ; numinmsg_start, start address 
		mov	al,[glni_input]
		cbw
		mov	cx,ax
		mov	ax,10
		mul	word [large_input]
		add	ax,cx
		sub	ax,'0'
		mov	[large_input],ax
		push	ax	; numinmsg_num, number
		call	number_in_msg
		;pop	bx
		;pop	bx
		
		;display(input_message);  
		push	word [glni_input_msg_seg]
		push	word [glni_input_msg]
		call	display
		;pop	bx
		;pop	bx
		
		;/* Indicate that we are not using the default */
		sub	al,al ; 0
		mov	[glni_def_used],al  ; default_used = FALSE; 
		mov	[PercentFlag],al ; PercentFlag = (FLAG)FALSE;   
		jmp	short glni_29
glni_27:
		;display(error_33); 
		;push	word [error_33_seg]
		push	ds
		push	word [error_33_off]
glni_28:
		call	display
		;pop	bx
		;pop	bx
glni_29:
		;/* Loop until we get good stuff */
    		;while (valid_input == FALSE)
		cmp	byte [valid_input],0
		jne	short glni_30
		jmp	glni_1
glni_30:
		;return(large_input);
		mov	ax,[large_input]
		
		mov	sp,bp
		pop	bp
		;retn
		retn	16

; ----------------------------------------------------------------------------
; makepart.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 19/01/2019)

;void make_partition(size,free_pointer,bootable,type)
;
;unsigned        size;
;char            free_pointer;
;unsigned char   bootable;
;char            type;
;
;BEGIN
;
;    char table_pointer;
;    unsigned i;
;    unsigned char   temp;
;    unsigned long   total_sectors;
;
;    /* Find a free spot to put it in */
;    table_pointer = find_free_partition();
;
;    if (table_pointer != ((char)(NOT_FOUND)))
;        BEGIN
;        /* found a free partition, now lets go fill it up */
;
;        /* Do we need to make it active? */
;        if (bootable == ((unsigned char)(ACTIVE)))
;            BEGIN
;
;            /* Go clear out a previously active one */
;            for (i=u(0); i <u(4); i++) 			/* AC000 */
;                BEGIN
;                if (part_table[cur_disk][i].boot_ind == uc(0x80))	/* AC000 */
;                    BEGIN
;                    part_table[cur_disk][i].changed = TRUE;
;                    part_table[cur_disk][i].boot_ind = uc(0);	/* AC000 */
;                    END
;                END
;
;                /* Now mark the new one active */
;                part_table[cur_disk][table_pointer].boot_ind = uc(0x80); /* AC000 */
;            END
;        else
;            BEGIN
;            /* Mark it as not active, leaving the others alone */
;            part_table[cur_disk][table_pointer].boot_ind = uc(0);	/* AC000 */
;            END
;
;            /* Go get the start cylinder */
;            part_table[cur_disk][table_pointer].start_cyl = free_space[free_pointer].start;
;
;            /* Setup end cylinder */
;            part_table[cur_disk][table_pointer].end_cyl = part_table[cur_disk][table_pointer].start_cyl + size - 1;
;
;            /* Start sector is always 1 */
;            part_table[cur_disk][table_pointer].start_sector = uc(1);	/* AC000 */
;
;            /* End sector is always the last sector */
;            part_table[cur_disk][table_pointer].end_sector = max_sector[cur_disk];
;
;            /* End head is always the last head */
;            part_table[cur_disk][table_pointer].end_head = uc(max_head[cur_disk] -1); /* AC004 */
;
;            /* Start head is always 0 unless this is track 0 - then it is 1 */
;            temp = uc(0);						/* AC000 */
;            if (part_table[cur_disk][table_pointer].start_cyl == u(0))	/* AC000 */
;                BEGIN
;                temp = uc(1);						/* AC000 */
;                END
;            part_table[cur_disk][table_pointer].start_head = temp;
;
;            /* Figure out the total number of sectors */
;            /* Total sectors in partition =                    */
;            /* [(end_cyl - start_cyl)*(max_sector)*(max_head)] */
;            /* - [start_head * max_sector]                     */
;            /* Note: This is assuming a track or cylinder aligned partition */
;
;            /* First - get the total size in Cylinders assuming head 0 start*/
;            total_sectors = ((unsigned long)(part_table[cur_disk][table_pointer].end_cyl -
;                             part_table[cur_disk][table_pointer].start_cyl+1));
;
;            /* Now multiply it by the number of sectors and heads per track */
;            total_sectors = total_sectors * max_sector[cur_disk] * max_head[cur_disk];
;
;            /* This will give us the total of sectors if it is cyl aligned */
;            /* Now, if it isn't aligned on head 0, we need to subtract off */
;            /* the skipped tracks in the first cylinder  */
;
;            /* Because the head is zero based, we can get the total number of */
;            /* skipped sectors by multipling the head number by sectors per track */
;            total_sectors = total_sectors - ((unsigned long)part_table[cur_disk][table_pointer].start_head) *
;                             max_sector[cur_disk];
;            part_table[cur_disk][table_pointer].num_sec = total_sectors;
;
;            /* Get the relative sector */
;            /* Figure out the total number of sectors	*/
;            /* Total sectors before partition =  	*/
;            /* (start_cyl)*(max_sector)*(max_head)]	*/
;            /* + [start_head * max_sector]		*/
;            /* Note: This is assuming a track or cylinder aligned partition */
;
;            /* Start cyl will work because it is zero based */
;            total_sectors = ((unsigned long)part_table[cur_disk][table_pointer].start_cyl);
;
;            /* Get sectors up to head 0 of the partition */
;            total_sectors = total_sectors * max_sector[cur_disk] * max_head[cur_disk];
;
;            /* Because the head is zero based, we can get the total number of */
;            /* skipped sectors by multipling the head number by sectors per track */
;            total_sectors = total_sectors + ((unsigned long)part_table[cur_disk][table_pointer].start_head) *
;                              max_sector[cur_disk];
;            /* Save it! */
;            part_table[cur_disk][table_pointer].rel_sec = total_sectors;
;
;            /* Setup the system id byte */
;            if (type == ((char)(EXTENDED)))
;                BEGIN
;                temp = uc(EXTENDED);					/* AC000 */
;                END
;            else
;                BEGIN
;                if (type == ((char)(PRIMARY)))
;                    BEGIN
;                    /* Always set to 06h - let format worry about setting to correct value */
;                    /* SR; 9/30/89; We fix up the size ourselves here. The
;                       calculation is simple. If total_sectors > 65536 then
;                       type = 06 else if total_sectors > 32680 then type = 04
;                       else type = 01 */
;
;                    /* SR; 9/30/89; Calculate total_sectors from start
;                       including the hidden sectors */
;
;                    total_sectors += part_table[cur_disk][table_pointer].num_sec;
;
;                    if ( (total_sectors >> 16) > 0 )
;                        temp = uc(DOSNEW); /* Partition extends beyond the 32M boundary */
;                    else if (part_table[cur_disk][table_pointer].num_sec > ul( FAT16_SIZE ))
;                        temp = uc(DOS16);
;                    else
;                        temp = uc(DOS12);				/* AC000 */
;                    END
;                else
;                    BEGIN
;                    internal_program_error();
;                    END
;                END
;
;            /* We got the sys id, now put it in */
;            part_table[cur_disk][table_pointer].sys_id = temp;
;
;            /* Set the changed flag */
;            part_table[cur_disk][table_pointer].changed = TRUE;
;
;            /* Set the mbytes used */
;            part_table[cur_disk][table_pointer].mbytes_used =
;                cylinders_to_mbytes(size,cur_disk);			- /* AN004 */
;
;            /* Set the percent used */
;            part_table[cur_disk][table_pointer].percent_used =
;                cylinders_to_percent(((part_table[cur_disk][table_pointer].end_cyl-part_table[cur_disk][table_pointer].start_cyl)+1),
;                total_disk[cur_disk]);                                  /* AN000 */
;
;            /* set the system to unknown and volume label to blanks */  /*C21*/
;            strcpy(part_table[cur_disk][table_pointer].system,NOFORMAT); /*C21*/
;            strcpy(part_table[cur_disk][table_pointer].vol_label,NOVOLUME); /*C21*/
;        END
;    else
;        BEGIN
;        /* This should not have happened */
;        internal_program_error();
;        return;
;        END
;
;    return;
;END

make_partition:
		; 19/01/2019

	;%define mp_temp4_lw	    bp-26
	;%define mp_temp4_hw	    bp-24
	;%define mp_temp3_lw	    bp-22
	;%define mp_temp3_hw	    bp-20
	;%define mp_temp2_lw	    bp-18
	;%define mp_temp2_hw	    bp-16
	;%define mp_temp1_lw	    bp-14
	;%define mp_temp1_hw	    bp-12
	
	%define mp_i		    bp-10
	%define mp_table_ptr	    bp-8
	%define mp_temp		    bp-6
	%define mp_total_sectors_lw bp-4
	%define mp_total_sectors_hw bp-2

	%define mp_size		    bp+4
	%define mp_free_ptr	    bp+6
	%define mp_bootable	    bp+8
	%define mp_type		    bp+10

		push	bp
		mov	bp,sp
		;sub	sp,26
		sub	sp,10 ; 19/01/2019
		
		;push	di
		;push	si

		;/* Find a free spot to put it in */
		call	find_free_partition
		mov	[mp_table_ptr],al
		;if (table_pointer != ((char)(NOT_FOUND)))
		inc	al
		jnz	short mp_1 
		jmp	mp_13
mp_1:
		;/* found a free partition, now lets go fill it up */

		mov	cx,46 ; *- ; 19/01/2019

		;/* Do we need to make it active? */
		cmp	byte [mp_bootable],80h
		jne	short mp_4
		
		;/* Go clear out a previously active one */
		mov	byte [mp_i],0
mp_2:
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,[mp_i]
		shl	al,1
		shl	al,1
		add	al,[mp_i]
		
		;mov	cx,46
		;mul	cx
		;mov	cl,46
		mul	cl
		mov	bx,ax

		cmp	byte [part_table_boot_ind+bx],80h
		jne	short mp_3
		;part_table[cur_disk][i].changed = TRUE;
		mov	byte [part_table_changed+bx],1
		mov	byte [part_table_boot_ind+bx],0
mp_3:
		inc	byte [mp_i]
		cmp	byte [mp_i],4
		jb	short mp_2

		;/* Now mark the new one active */
		;part_table[cur_disk][table_pointer].boot_ind = uc(0x80);

		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax, 1
		;;shl	ax, 1
		;;mov	cx, ax
		;;mov	al,[mp_table_ptr]
		;;cbw
		;;add	ax,cx
		;shl	al,1
		;shl	al,1
		;add	al,[mp_table_ptr]
		;;mov	cx,46
		;;imul	cx
		;;mov	cl,46
		;mul	cl
		;mov	bx,ax
		;mov	[part_table_boot_ind+bx],80h
		;jmp	short mp_5,

		mov	ch,80h ; *- ; 19/01/2019
mp_4:
		;/* Mark it as not active, leaving the others alone */
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	cx,ax
		;mov	al,[mp_table_ptr]
		;cbw
		;add	ax,cx
		;mov	cx,46
		;imul	cx

		shl	al,1
		shl	al,1
		add	al,[mp_table_ptr]
		;mov	cl,46
		mul	cl
		mov	bx,ax

		;mov	byte [part_table_boot_ind+bx],0
		mov	[part_table_boot_ind+bx],ch ; *- ; 19/01/2019
mp_5:
		;/* Go get the start cylinder */
		mov	al,22
		;imul	byte [mp_free_ptr]
		mul	byte [mp_free_ptr]
		mov	bx,ax
		;mov	ax,[free_space.start+bx]
		;mov	cx,ax
		mov	cx,[free_space.start+bx]
		mov	al,[cur_disk]
		;cbw
		;ah = 0
		;mov	dx,ax ; *-**
		mov	si,ax ; **-	
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;mov	bx,ax
		;mov	al,[mp_table_ptr]
		;cbw
		;add	ax,bx
		add	al,[mp_table_ptr]
		;mov	bx,46
		mov	bl,46
		;mov	si,dx ; *-**
		;imul	bx
		mul	bl
		mov	bx,ax
		mov	[part_table_start_cyl+bx],cx
		;/* Setup end cylinder */
		;part_table[cur_disk][table_pointer].end_cyl =
		add	cx,[mp_size]
		dec	cx  ; part_table[cur_disk][table_pointer].start_cyl + size - 1
		mov	[part_table_end_cyl+bx],cx
		;/* Start sector is always 1 */
		mov	byte [part_table_start_sector+bx],1
		;/* End sector is always the last sector */
		mov	al,[max_sector+si] ; **-
		mov	[part_table_end_sector+bx],al
		;/* End head is always the last head */
		shl	si,1  ;**-
		mov	al,[max_head+si] ; **-
		dec	al
		mov	[part_table_end_head+bx],al
		;/* Start head is always 0 unless this is track 0 - then it is 1 */
		;mov	byte [mp_temp],0 ; temp = uc(0);         
		sub	dx,dx ; 0
		;cmp	word [part_table_start_cyl+bx],0
		cmp	[part_table_start_cyl+bx],dx ; 0
		jne	short mp_6
		;mov	byte [mp_temp],1 ; temp = uc(1);     
		inc	dl  ; dl = 1 = [mp_temp]
mp_6:
		;mov	al,[cur_disk]
		;cbw
		;mov	cx,ax
		;shl	ax,1
		;shl	ax,1
		;mov	dx,ax
		;mov	al,[mp_table_ptr]
		;cbw
		;add	ax,dx
		;mov	bx,46
		;imul	bx
		;mov	bx,ax
		;mov	al,[mp_temp]

		; part_table[cur_disk][table_pointer].start_head = temp;
		;mov	[part_table_start_head+bx],al ; 0 or 1
		mov	[part_table_start_head+bx],dl ; 0 or 1

		;/* Figure out the total number of sectors */
            	;/* Total sectors in partition =                    */
            	;/* [(end_cyl - start_cyl)*(max_sector)*(max_head)] */
            	;/* - [start_head * max_sector]                     */
            	;/* Note: This is assuming a track or cylinder aligned partition */

		; dl = 0 or 1
		; dh = 0

		sub	ah,ah ; 0

		; AX = start head (0 or 1)

		;sub	dx,dx ; 0

		;push	dx	; multiplier_hw = 0
		;push	ax	; multiplier_lw  (0 or 1)
		;;mov	si,cx
		;shr	si,1 ; **-
		;mov	al,[max_sector+si] ; **-
		;push	dx	; multiplicand_hw
		;push	ax	; multiplicand_lw
		;mov	di,ax
		;mov	[mp_temp1_lw],di ; max_sector lw
		;mov	[mp_temp1_hw],dx ; max_sector hw
		;mov	di,bx
		;call	mul32
		;	; dx:ax = [start_head * max_sector] 

		; **** modification by Erdogan Tan

		shr	si,1
		mov	al,[max_sector+si]

		or	dl,dl ; dh = 0 , dl = start head (0 or 1)
		jz	short mp_15

		mov	dl,al	
mp_15:
		mov	[mp_temp],dx ; **** ; 19/01/2019
	
		; ****

		;push	word [mp_temp1_hw] ; multiplier_hw
		;push	word [mp_temp1_lw] ; multiplier_lw
		
		shl	si,1
		mov	cx,[max_head+si]
		;sub	bx,bx
		;push	bx  ; multiplicand_hw	
		;push	cx  ; multiplicand_lw
			; dx:ax = [start_head * max_sector] 	
		;mov	si,ax
		;mov	[mp_temp2_lw],si
		;mov	[mp_temp2_hw],dx
		;call	mul32
		;	; dx:ax = (max_sector)*(max_head)

		; **** modification by Erdogan Tan ; 19/01/2019

		; ax = max_sector (ah = 0)
		; cx = max_head   

		mul	cx
			; dx:ax = (max_sector)*(max_head)
		; ****

		push	dx  ; multiplier_hw
		push	ax  ; multiplier_lw	

	;/* First - get the total size in Cylinders assuming head 0 start*/
	;total_sectors = ((unsigned long)(part_table[cur_disk][table_pointer].end_cyl -
        ;                    part_table[cur_disk][table_pointer].start_cyl+1));

		;mov	cx,[part_table_end_cyl+di]
		mov	cx,[part_table_end_cyl+bx] ; ****
		;sub	cx,[part_table_start_cyl+di]
		sub	cx,[part_table_start_cyl+bx] ; ****
		inc	cx
			; cx = (end_cyl - start_cyl) + 1

	;/* Now multiply it by the number of sectors and heads per track */
	;total_sectors = total_sectors * max_sector[cur_disk] * max_head[cur_disk];

		;sub	bx,bx ; 0
		;push	bx 	; multiplicand_hw = 0	
		;push	cx	; multiplicand_lw
		;	; dx:ax = (max_sector)*(max_head)
		;	; (dx = 0)
		;mov	si,ax
		;mov	[mp_temp3_lw],si
		;mov	[mp_temp3_hw],dx
		;call	mul32
		;	; dx:ax = ((end_cyl - start_cyl) + 1) * (max_sector)*(max_head)
		;	; dx:ax = cylinders * (sectors per track * heads)
		;	; dx:ax = (cylinders*heads) * sectors per track

		
		; **** modification by Erdogan Tan ; 19/01/2019

		; ax = (max_sector)*(max_head) ; <= 16065 (max_head <= 255, max_sector <= 63)
		; dx = 0
		; cx = (end_cyl - start_cyl) + 1 = cylinders 

		mov	di,ax ; ***** (max_sector)*(max_head) 

		mul	cx
			; dx:ax = (cylinders*heads) * sectors per track

		; ****

	;/* This will give us the total of sectors if it is cyl aligned */
	;/* Now, if it isn't aligned on head 0, we need to subtract off */
	;/* the skipped tracks in the first cylinder  */

	;/* Because the head is zero based, we can get the total number of */
	;/* skipped sectors by multipling the head number by sectors per track */
	;total_sectors = 
	;	total_sectors - ((unsigned long)part_table[cur_disk][table_pointer].start_head) *
	;                       max_sector[cur_disk];

		;sub	ax,[mp_temp2_lw] ; total_sectors = 
		;sbb	dx,[mp_temp2_hw] ; 	total_sectors - [start_head * max_sector] 

		; **** modification by Erdogan Tan ; 19/01/2019

		mov	cx,[mp_temp] ; **** ; [start_head * max_sector] = 0 or max_sector
		jcxz	mp_16

		sub	ax,cx ; cx = max_sector
		sbb	dx,0
	
		; ****
mp_16:		
	;part_table[cur_disk][table_pointer].num_sec = total_sectors;	

		;mov	[part_table_num_sec_lw+di],ax
		;mov	[part_table_num_sec_hw+di],dx

		mov	[part_table_num_sec_lw+bx],ax ; ****
		mov	[part_table_num_sec_hw+bx],dx ; ****

		;/* Get the relative sector */
            	;/* Figure out the total number of sectors */
            	;/* Total sectors before partition =       */
		;/* (start_cyl)*(max_sector)*(max_head)    */
		;/* + [start_head * max_sector]            */
		;/* Note: This is assuming a track or cylinder aligned partition */

		;push	word [mp_temp1_hw]
		;push	word [mp_temp1_lw]
		;mov	al,[part_table_start_head+di]
		;sub	ah,ah
		;sub	dx,dx
		;push	dx
		;push	ax
		;call	mul32
		;	 ; dx:ax = [start_head * max_sector]  

	;/* Start cyl will work because it is zero based */
	;total_sectors = ((unsigned long)part_table[cur_disk][table_pointer].start_cyl);

	;/* Get sectors up to head 0 of the partition */
        ;total_sectors = total_sectors * max_sector[cur_disk] * max_head[cur_disk];

		;mov	cx,[part_table_start_cyl+di]
		;sub	bx,bx
		;push	bx
		;push	cx
		;push	word [mp_temp3_hw] ; (max_sector)*(max_head)
		;push	word [mp_temp3_lw]
		;mov	si, ax
		;mov	[mp_temp4_lw],si ; [start_head * max_sector]
		;mov	[mp_temp4_hw],dx
		;call	mul32
		;add	ax,[mp_temp4_lw] 
		;adc	dx,[mp_temp4_hw]
			
		; **** modification by Erdogan Tan ; 19/01/2019

		; cx = (start_head * max_sector) = max_sector or cx = 0
		; di = (max_sector * max_head) 

		mov	ax,[part_table_start_cyl+bx]
		mul	di ; *****
			; dx:ax = part_table[cur_disk][table_pointer].start_cyl *
			;	  max_sector[cur_disk] * max_head[cur_disk]

		add	ax,cx
		adc	dx,0
			; dx:ax =  Total sectors before partition = 
			;	   (start_cyl)*(max_sector * max_head)
			;	   + (start_head * max_sector)

		; ****		  

	;/* Because the head is zero based, we can get the total number of */
	;/* skipped sectors by multipling the head number by sectors per track */
	;total_sectors = 
	;	total_sectors + ((unsigned long)part_table[cur_disk][table_pointer].start_head) *
	;		max_sector[cur_disk];

		mov	[mp_total_sectors_lw],ax  ; -**-
		mov	[mp_total_sectors_hw],dx  ; -**-	

		;* Save it! */
		;part_table[cur_disk][table_pointer].rel_sec = total_sectors;

		;mov	[part_table_rel_sec_lw+di],ax
		;mov	[part_table_rel_sec_hw+di],dx

		mov	[part_table_rel_sec_lw+bx],ax
		mov	[part_table_rel_sec_hw+bx],dx

		;/* Setup the system id byte */

		cmp	byte [mp_type],5 ; EXTENDED
		jne	short mp_7
		;mov	byte [mp_temp],5
		mov	al,5 ; EXTENDED
		jmp	short mp_12
mp_7:
		;NOTE: If [mp_type] <> 5, it is 0 (there is not another possibility)
		
		;cmp	byte [mp_type],0 ; PRIMARY
		;jne	short mp_11  ; not possible !
		
		;mov	al,[cur_disk]
		;;cbw
		;;shl	ax,1
		;;shl	ax,1
		;;mov	cx,ax
		;;mov	al,[mp_table_ptr]
		;;cbw
		;;add	ax,cx
		;shl	al,1
		;shl	al,1
		;add	al,[mp_table_ptr]
		;;mov	cx,46
		;;imul	cx
		;mov	cl,46
		;mul	cl
		;mov	bx,ax

	;/* Always set to 06h - let format worry about setting to correct value */
        ;/* SR; 9/30/89; We fix up the size ourselves here. The
        ;	calculation is simple. If total_sectors > 65536 then
        ;	type = 06 else if total_sectors > 32680 then type = 04
        ;       else type = 01 */

        ;/* SR; 9/30/89; Calculate total_sectors from start
        ; including the hidden sectors */

	; total_sectors += part_table[cur_disk][table_pointer].num_sec;

		;mov	ax,[part_table_num_sec_lw+bx]
		;mov	dx,[part_table_num_sec_hw+bx]
		;add	[mp_total_sectors_lw],ax
		;adc	[mp_total_sectors_hw],dx

		; ax = [mp_total_sectors_lw] ; -**-
		; dx = [mp_total_sectors_hw] ; -**-

		add	ax,[part_table_num_sec_lw+bx]  ; -**-
		adc	dx,[part_table_num_sec_hw+bx]  ; -**-	
		
	; if ( (total_sectors >> 16) > 0 )
		jz	short mp_8 ; [mp_total_sectors_hw] = 0
	; temp = uc(DOSNEW); /* Partition extends beyond the 32M boundary */
		;mov	byte [mp_temp],6
		mov	al,6 ; DOSNEW
		jmp	short mp_12
;mp_8:
		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	cx,ax
		;mov	al,[mp_table_ptr]
		;cbw
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax
		
		;cmp	word [part_table_num_sec_hw+bx],0
		;jne	short mp_9
mp_8:
	;if (part_table[cur_disk][table_pointer].num_sec > ul( FAT16_SIZE ))

		cmp	word [part_table_num_sec_lw+bx],32680 ; FAT16_SIZE = 32680
		jbe	short mp_10 ;  if sectors <= 32680, it must be a FAT12 file system 
mp_9:
		;mov	byte [mp_temp],4 ; temp = uc(DOS16);
		mov	al,4
		jmp	short mp_12
;mp_11:
;		call	internal_program_error
;		jmp	short mp_12
mp_10:
		;mov	byte [mp_temp],1 ; temp = uc(DOS12); 
		mov	al,1
;;		jmp	short mp_12
;;mp_11:
;;		call	internal_program_error
mp_12:
		;mov	al,[mp_table_ptr]
		;cbw
		;mov	cx,ax
		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,cx
		;mov	bx,46
		;imul	bx
		;mov	si,ax

		; /* We got the sys id, now put it in */
            	;part_table[cur_disk][table_pointer].sys_id = temp;

		;mov	al,[mp_temp]

		;mov	[part_table_sys_id+si],al
		;mov	byte [part_table_changed+si],1
		mov	[part_table_sys_id+bx],al ; al = [mp_temp]

		;/* Set the changed flag */
            	;part_table[cur_disk][table_pointer].changed = TRUE;

		mov	byte [part_table_changed+bx],1
		
		mov	si,bx ; *

		;mov	al,[cur_disk]
		;push	ax
		mov	bl,[cur_disk]
		xor	bh,bh
		mov	di,bx ; **

		;/* Set the mbytes used */

		;push	word [mp_size]
		mov	ax,[mp_size]
		;mov	di,cx
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		mov	[part_table_mbytes_used+si],ax  ; *
		
		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;;shl	bx,1
		;shl	bl,1
		;push	word [total_disk+bx]
		
		;;shl	ax,1
		;;shl	ax,1
		;shl	al,1
		;shl	al,1
		;;add	ax,di
		;add	al,[mp_table_ptr]
		;;mov	cx,46
		;;imul	cx
		;mov	cl,46
		;mul	cl
		;mov	bx,ax
		
		;mov	ax,[part_table_end_cyl+bx]
		;sub	ax,[part_table_start_cyl+bx]
		;inc	ax
		;push	ax

		;mov	si,bx

		;/* Set the percent used */

		shl	di,1 ; **
		mov	cx,[total_disk+di] ; **
			; cx = total cylinders (of the disk)
		mov	bx,[part_table_end_cyl+si]
		sub	bx,[part_table_start_cyl+si]		
		inc	bx
			; bx = number of cylinders (of the partition)
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[part_table_percent_used+si],ax ; percent (<=100)

	;/* set the system to unknown and volume label to blanks */
        ;strcpy(part_table[cur_disk][table_pointer].system,NOFORMAT)
        ;strcpy(part_table[cur_disk][table_pointer].vol_label,NOVOLUME)

		;mov	ax,NO_FORMAT ; "UNKNOWN	"
		;push	ax
		mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,di
		;mov	cx,46
		;imul	cx
		;add	ax,part_table_system
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx

		mov	bx,si
		mov	si,NO_FORMAT
		mov	di,bx
		add	di,part_table_system
		call	strcpy
		

		;mov	ax,NO_VOLUME
		;push	ax
		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;add	ax,di
		;mov	cx,46
		;imul	cx
		;add	ax,part_table_vol_label
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx

		;mov	si,NO_VOLUME ; [NO_VOLUME] = 0
		;mov	di,bx
		;add	di,part_table_vol_label
		;call	strcpy
		mov	byte [part_table_vol_label+bx],0 ; NOVOLUME

		;jmp	short mp_14
;mp_13:
;		call	internal_program_error
mp_14:
		;pop	si
		;pop	di

		mov	sp,bp
		pop	bp
		;retn
		retn	8
mp_13:
		call	internal_program_error
		jmp	short mp_14

; ----------------------------------------------------------------------------
; convert.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 19/01/2019)

;/***************************************************************************/
;/*Routine name:  MBYTES_TO_CYLINDERS                                       */
;/***************************************************************************/
;/*                                                                         */
;/*Description:   This routine will take input of MBtes and                 */
;/*               convert it to cylinders rounding up to the next largest   */
;/*               cylinder boundry.  Rounding up is done to make sure the   */
;/*               requester is getting at least what he asked for to the    */
;/*               next cylinder boundry.                                    */
;/*                                                                         */
;/*Called Procedures:    none                                               */
;/*                                                                         */
;/*                                                                         */
;/*Change History: Created	5/30/87	DRM                                 */
;/*                                                                         */
;/*Input: Input                                                             */
;/*                                                                         */
;/*Output: Cylinders_out                                                    */
;/*                                                                         */
;/***************************************************************************/

;unsigned mbytes_to_cylinders(mbytes_in,which_disk)
;
;XFLOAT	mbytes_in;
;char	which_disk;
;
;BEGIN
;
;unsigned	cylinders_out;
;unsigned long	cylinders_out1;
;unsigned long	number_of_sectors;
;unsigned long	number_of_tracks;
;unsigned long	divide_by;
;
;      /* If trying to create a 3.30 compatible 32 MB partition */
;      /* Set the 32mb limit - round down                       */
;      if (mbytes_in == (XFLOAT)32)
;          BEGIN
;          cylinders_out1 = ul(DOS_MAX);
;          divide_by = ul((max_head[which_disk]) * ul(max_sector[which_disk]));
;          cylinders_out = u(cylinders_out1 / divide_by);
;          END
;      else
;          BEGIN
;	   /* SR; 9/26/89; Long calculation incorrect */
;	   number_of_sectors = ((ul(mbytes_in) * ul(ONE_MEG))/BYTES_PER_SECTOR);
;
;          /* SR; 9/26/89; Incorrect cast to int. Actually this modulo is */
;          /* always 0 because ONE_MEG mod BYTES_PER_SECTOR = 0 */
;	   if (((mbytes_in * ONE_MEG) % BYTES_PER_SECTOR) != (int)0)
;	       number_of_sectors++;
;	       number_of_tracks = ul((number_of_sectors / max_sector[which_disk]));
;
;          /* SR; 9/26/89; Changed int cast to unsigned */
;	   if (((unsigned)number_of_sectors % max_sector[which_disk]) != 0)
;	       number_of_tracks++;
;	       cylinders_out = u((number_of_tracks / max_head[which_disk]));
;
;	   /* SR; 9/26/89; Changed int cast to unsigned */
;	   if (((unsigned)number_of_tracks % max_head[which_disk]) != 0)
;	       cylinders_out++;
;          END
;
;      return(cylinders_out);
;END

mbytes_to_cylinders:
		; 19/01/2019

	;%define mtc_num_sectors_lw bp-18
	;%define mtc_num_sectors_hw bp-16
	;%define mtc_cylinders_out  bp-6
	;%define mtc_num_tracks_lw  bp-4
	;%define mtc_num_tracks_hw  bp-2
	
	%define mtc_mbytes_in	bp+4
	%define mtc_which_disk	bp+6

		push	bp
		mov	bp,sp

		;sub	sp,18
		
		;push	di
		;push	si

	;/* If trying to create a 3.30 compatible 32 MB partition */
	;/* Set the 32mb limit - round down  
		
		mov	al,[mtc_which_disk]
		cbw	; ah = 0
		mov	bx,ax
		mov	al,[max_sector+bx]
		mov	si,ax ; *+* ; 19/01/2019
		shl	bl,1
		mov	di,[max_head+bx] ; *++* ; 19/01/2019

		mov	ax,[mtc_mbytes_in] ; 19/01/2019

		;cmp	word [mtc_mbytes_in],32
		cmp	ax,32
		jne	short mbtocyl_1

		;mov	al,[mtc_which_disk]
		;cbw
		;mov	bx,ax
		;mov	al,[max_sector+bx]
		;;sub	ah,ah
		;mov	si,ax ; *+* ; 19/01/2019
		
		;;shl	bx,1
		;shl	bl,1
		;mul	word [max_head+bx]

		mul	di ; *++* ; 19/01/2019

		;push	dx  ; divisor hw = 0
		;push	ax  ; divisor lw <= 16065 (255*63)
		mov	cx,ax ; 19/01/2019
		mov	ax,0FFFFh ; 65535 sectors
		;sub	dx,dx ; dx = 0
		;push	dx ; dividend hw
		;push	ax ; dividend lw
			; dx:ax = dividend (32 bit)
			; cx = divisor (16 bit)
		call	div32
			; dx:ax = quotient
			; bx = remainder
		jmp	short mbtocyl_4
mbtocyl_1:
	;number_of_sectors = ((ul(mbytes_in) * ul(ONE_MEG))/BYTES_PER_SECTOR);
		mov	cl,4
		;mov	ax,[mtc_mbytes_in]
		sub	dx,dx
		;mov	bx,ax
		;mov	si,dx
		shl	ax,cl ; 16
		mov	dx,ax ; 16*65536
		sub	ax,ax
		mov	cl,9  ; bytes / 512
		;mov	di,bx
		call	shr32
			; dx:ax = sectors
		;mov	[mtc_num_sectors_lw],ax
		;mov	[mtc_num_sectors_hw],dx
		
	;Actually this modulo is always 0 because ONE_MEG mod BYTES_PER_SECTOR = 0
	
	;if (((mbytes_in * ONE_MEG) % BYTES_PER_SECTOR) != (int)0)
	;       number_of_sectors++;

		;mov	cx,512
		;sub	bx,bx
		;push	bx
		;push	cx
		;mov	cl,4
		;shl	di,cl
		;sub	cx,cx
		;push	di
		;push	cx
		;call	_mod32
		;or	dx,ax
		;jz	short mbtocyl_2  ; always 0
		
		;mov	ax,[bp+mtc_num_sectors_lw]
		;mov	dx,[bp+mtc_num_sectors_hw]
		;add	ax,1
		;adc	dx,si
		;mov	[mtc_num_sectors_lw],ax
		;mov	[mtc_num_sectors_hw],dx
mbtocyl_2:
	;number_of_tracks = ul((number_of_sectors / max_sector[which_disk]));	

		;mov	al,[mtc_which_disk]
		;cbw
		;mov	bx,ax
		;mov	al,[max_sector+bx]
		;sub	ah,ah

		;mov	cx,ax
		mov	cx,si ; *+* ; 19/01/2019
			; cl = [max_sector+bx]
			; ch = 0
		;sub	dx,dx
		;push	dx ; divisor hw = 0
		;push	ax ; divisor lw = sectors per track
		;push	word [mtc_num_sectors_hw] ; dividend hw
		;push	word [mtc_num_sectors_lw] ; dividend lw
		;mov	si,cx
		;call	div32
		
		;mov	dx,[mtc_num_sectors_hw]
		;mov	ax,[mtc_num_sectors_lw]	

			; dx:ax = number of sectors (dividend)
			; cx = sectors per track (divisor)
		call	div32
			; dx:ax = quotient, number of tracks (cylinders*heads)
			; bx = remainder, sectors (less than spt)

		;mov	[mtc_num_tracks_lw],ax
		;mov	[mtc_num_tracks_hw],dx
		
	;if (((unsigned)number_of_sectors % max_sector[which_disk]) != 0)
	;      number_of_tracks++;

		;mov	ax,[mtc_num_sectors_lw]
		;sub	dx,dx
		;div	si
		;or	dx,dx
		;jz	short mbtocyl_3
		
		;mov	ax,[mtc_num_tracks_lw]
		;mov	dx,[mtc_num_tracks_hw]
		;add	ax,1
		;adc	dx,0
		;mov	[mtc_num_tracks_lw],ax
		;mov	[mtc_num_tracks_hw],dx

		or	bx,bx
		jz	short  mbtocyl_3

		; round up
		add	ax,1 ; number_of_tracks++;
		adc	dx,0
mbtocyl_3:
		;mov	[mtc_num_tracks_lw],ax
		;mov	[mtc_num_tracks_hw],dx

	;cylinders_out = u((number_of_tracks / max_head[which_disk]));

		;mov	al,[mtc_which_disk]
		;cbw
		;mov	bx,ax
		;shl	bx,1
		;mov	ax,[max_head+bx]

		;mov	cx,ax
		mov	cx,di ; *++* ; 19/01/2019
			; cx = [max_head+bx]
		;sub	dx,dx
		;push	dx
		;push	ax
		;push	word [mtc_num_tracks_hw]
		;push	word [mtc_num_tracks_lw]
		;mov	si,ax
		;call	div32

		;mov	ax,[mtc_num_tracks_lw]
		;mov	dx,[[mtc_num_tracks_hw]
			; dx:ax = number of tracks (dividend)	
			; cx = heads (divisor)
		call	div32
			 ; dx:ax = quotient, cylinders  ; dx = 0
			 ; bx = remainder, head 	

		;mov	[mtc_cylinders_out],ax

	;if (((unsigned)number_of_tracks % max_head[which_disk]) != 0)
	;      cylinders_out++;

		;mov	ax,[mtc_num_tracks_lw]
		;sub	dx,dx
		;div	si
		;or	dx,dx
		;jz	short mbtocyl_5

		and	bx,bx
		jnz	short mbtocyl_5
		
		;mov	ax,[mtc_cylinders_out]
		inc	ax  ; round up ; cylinders_out++
mbtocyl_4:
		;mov	[mtc_cylinders_out],ax
mbtocyl_5:
		;mov	ax,[mtc_cylinders_out]

		; ax = cylinders
		
		;pop	si
		;pop	di
		
		mov	sp,bp
		pop	bp
		;retn

		retn	4

;/***************************************************************************/
;/*Routine name:  PERCENT_TO_CYLINDERS                                      */
;/***************************************************************************/
;/*                                                                         */
;/*Description:   This routine will take input of percentage and            */
;/*               convert it to cylinders rounding up to the next largest   */
;/*               cylinder boundry.  Rounding up is done to make sure the   */
;/*               requester is getting at least what he asked for to the    */
;/*               next cylinder boundry.                                    */
;/*                                                                         */
;/*Called Procedures:    none                                               */
;/*                                                                         */
;/*                                                                         */
;/*Change History: Created	5/30/87	DRM				    */
;/*                                                                         */
;/*Input: Input                                                             */
;/*                                                                         */
;/*Output: Cylinders_out                                                    */
;/*                                                                         */
;/***************************************************************************/

;XFLOAT percent_to_cylinders(percent_in,total_cylinders)
;
;unsigned percent_in;
;unsigned total_cylinders;
;
;BEGIN
;	XFLOAT	cylinders_out;
;        cylinders_out = (unsigned)((ul(percent_in) * ul(total_cylinders)) / 100);
;		 /* SR; 9/26/89; Typecast to long needed */
;	if (((ul(percent_in) * ul(total_cylinders)) % 100) != u(0))
;	   cylinders_out++;
;	return(cylinders_out);
;END

percent_to_cylinders:
		; 19/01/2019

	;%define ptc_cylinders_out   bp-2
	;%define ptc_percent_in	     bp+4
	;%define ptc_total_cylinders bp+6

		; INPUT:
		;	CX = total cylinders (of the disk)
		;	AX = percent in (word, <= 100)
		; OUTPUT:
		;	AX = cylinders (of the partition)
		;
 		; (modified registers: bx,cx,dx)

		;push	bp
		;mov	bp,sp
		;sub	sp,2
		
		;push	di
		;push	si
		
		;;mov	ax,100
		;;cwd
		;;push	dx  ; divisor hw
		;;push	ax  ; divisor lw
		;;mov	ax,[ptc_total_cylinders]
		;;mul	word [ptc_percent_in]
		;;push	dx  ; dividend hw
		;;push	ax  ; dividend lw
		;;mov	si,ax
		;;mov	di,dx
		;;call	div32

	;cylinders_out = (unsigned)((ul(percent_in) * ul(total_cylinders)) / 100);

		;mov	ax,[ptc_total_cylinders]
		;mul	word [ptc_percent_in]

		mul	cx ; total cylinders * percent in

			; dx:ax = (100*cylinders/totalcylinders) * total cylinders 

		mov	cx,100
					
			; dx:ax = Dividend
			; cx = divisor (16 bit)

		call	div32 ; ((100*cylinders/totalcylinders) * total cylinders) / 100 
			
			; DX:AX = Quotient 
			; BX = Remainder

		;mov	[ptc_cylinders_out],ax  ; dx = 0

		;mov	cx,100
		;sub	dx,dx
		;push	dx
		;push	cx
		;push	di
		;push	si
		;call	mod32

		;or	dx,ax
		;jz	short pctocyl_1

	;if (((ul(percent_in) * ul(total_cylinders)) % 100) != u(0))
	;   cylinders_out++;

		or	bx,bx
		jz	short pctocyl_1 ; remainder = 0

		;mov	ax,[ptc_cylinders_out]
		inc	ax  ; round up
		;mov	[ptc_cylinders_out],ax
pctocyl_1:
		;mov	ax,[ptc_cylinders_out]
		
		;pop	si
		;pop	di
		
		;mov	sp,bp
		;pop	bp

		retn

; ----------------------------------------------------------------------------
; partinfo.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 19/01/2019)

;char find_free_partition()
;
;BEGIN
; char  i;
;
;    /* Look at all four partition entries for empty partition */
;    for (i = c(0); i < c(4);i++)                             /* AC000 */
;       BEGIN
;
;       /* if we find an empty one, return which one */
;        if (part_table[cur_disk][i].num_sec == ul(0))        /* AC000 */
;           BEGIN
;            return(i);
;            break;
;           END
;       END
;    /* Did not find one, return NOT_FOUND */
;    return(c(NOT_FOUND));                                    /* AC000 */
;END

find_free_partition:
		; 19/01/2019

	%define	ffp_i	bp-2

		;push	bp
		;mov	bp,sp
		;sub	sp,2

	;/* Look at all four partition entries for empty partition */
	
		; for (i = c(0); i < c(4);i++)	
	
		;mov	byte [ffp_i],0
		xor	cx,cx ; 0
		jmp	short ffp_2
ffp_1:
		;inc	byte [ffp_i]
		inc	cl
;ffp_2:
		;cmp	byte [ffp_i],4
		;jge	short ffp_3
		cmp	cl,4
		jnb	short ffp_3
ffp_2:		
		;/* if we find an empty one, return which one */
		
		;mov	al,[cur_disk]
		;cbw
		;shl	ax,1
		;shl	ax,1
		;mov	cx,ax
		
		mov	bl,[cur_disk]
		shl	bl,1
		shl	bl,1		

		;mov	al,[ffp_i]
		;cbw
		;add	ax,cx

		add	bl,cl ; cl = [ffp_i]
		
		;mov	cx,46
		;imul	cx
		mov	al,46
		mul	bl		

		mov	bx,ax

		;if (part_table[cur_disk][i].num_sec == ul(0)) 

		mov	ax,[part_table_num_sec_hw+bx]
		or	ax,[part_table_num_sec_lw+bx]
		jnz	short ffp_1

		;mov	al,[ffp_i]
		mov	al,cl  ; return(i);
		;jmp	short ffp_4
		retn
ffp_3:
		;/* Did not find one, return NOT_FOUND */

		mov	al,0FFh ; -1 ; return(c(NOT_FOUND)); 
ffp_4:
		;mov	sp,bp
		;pop	bp
		retn

; ----------------------------------------------------------------------------
; space.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 20/01/2019)

;char find_ext_free_space()
;
;BEGIN
;
;char   i;
;char   partition_count;
;char   last_found_partition;
;unsigned    temp;
;char   freespace_count;
;char   any_partition;
;char   ext_location;
;
;        /* Sort the partition table */
;        sort_ext_table(c(23));                                          /* AC000 */
;
;        /* Initialize free space to zero */
;        for (i = c(0); i < c(24); i++)                                  /* AC000 */
;           BEGIN
;            free_space[i].space = u(0);                                 /* AC000 */
;            free_space[i].start = u(0);
;            free_space[i].end = u(0);                                   /* AC000 */
;            free_space[i].mbytes_unused = f(0);                         /* AN000 */
;            free_space[i].percent_unused = u(0);                        /* AN000 */
;           END
;
;        /* Find space between start of Extended partition and first volume */
;        ext_location = find_partition_location(uc(EXTENDED));           /* AC000 */
;
;        partition_count = c(0);                                         /* AC000 */
;
;        any_partition = FALSE;
;        for (i = c(0); i < c(23); i++)                                  /* AC000 */
;           BEGIN
;            if (ext_table[cur_disk][sort[i]].sys_id != uc(0))           /* AC000 */
;               BEGIN
;                /* Found a partition, get the space */
;                free_space[0].space = ext_table[cur_disk][sort[i]].start_cyl - part_table[cur_disk][ext_location].start_cyl;
;                free_space[0].start = part_table[cur_disk][ext_location].start_cyl;
;                free_space[0].end = ext_table[cur_disk][sort[i]].start_cyl-1;
;                free_space[0].mbytes_unused =
;                     cylinders_to_mbytes(free_space[0].space,cur_disk); /* AN004 */
;                free_space[0].percent_unused = (unsigned)cylinders_to_percent(free_space[0].space,total_disk[cur_disk]); /* AN000 */
;
;                partition_count = i;
;                last_found_partition = sort[i];
;                any_partition = TRUE;
;                break;
;               END
;           END
;        /* See if any partitions were there */
;        if (any_partition)
;           BEGIN
;            /* Look for space between the rest of the partitions */
;            freespace_count = c(1);                                     /* AC000 */
;            for (i = partition_count+1; i < c(23); i++)                 /* AC000 */
;               BEGIN
;                if (ext_table[cur_disk][sort[i]].sys_id != uc(0))       /* AC000 */
;                   BEGIN
;
;                    /* Get space between the end of the last one and the start of the next one */
;                    temp = ext_table[cur_disk][sort[i]].start_cyl - (ext_table[cur_disk][last_found_partition].end_cyl+1);
;                    free_space[freespace_count].space = temp;
;                    free_space[freespace_count].start = ext_table[cur_disk][last_found_partition].end_cyl+1;
;                    free_space[freespace_count].end = ext_table[cur_disk][sort[i]].start_cyl -1;
;                    free_space[freespace_count].mbytes_unused =
;                         cylinders_to_mbytes(free_space[freespace_count].space,cur_disk);   /* AN004 */
;                    free_space[freespace_count].percent_unused = (unsigned)
;                         cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]); /* AN000 */
;
;                    /* update the last found partition */
;                    last_found_partition = sort[i];
;                    freespace_count++;
;                   END
;               END
;            /* Find the space between the last partition and the end of the extended partition */
;            temp = part_table[cur_disk][ext_location].end_cyl -  ext_table[cur_disk][last_found_partition].end_cyl;
;            free_space[freespace_count].space = temp;
;            free_space[freespace_count].start = ext_table[cur_disk][last_found_partition].end_cyl+1;
;            free_space[freespace_count].end = part_table[cur_disk][ext_location].end_cyl;
;            free_space[freespace_count].mbytes_unused =
;                 cylinders_to_mbytes(free_space[freespace_count].space,cur_disk);    /* AN004 */
;            free_space[freespace_count].percent_unused = (unsigned)
;                 cylinders_to_percent(free_space[freespace_count].space,total_disk[cur_disk]);  /* AN000 */
;           END
;        else
;           BEGIN
;            /* No partitions found, show entire space as free */
;            free_space[0].space = (part_table[cur_disk][ext_location].end_cyl - part_table[cur_disk][ext_location].start_cyl) + 1;
;            free_space[0].start = part_table[cur_disk][ext_location].start_cyl;
;            free_space[0].end = part_table[cur_disk][ext_location].end_cyl;
;            free_space[0].mbytes_unused =
;                 cylinders_to_mbytes(free_space[0].space,cur_disk);  /* AN004 */
;            free_space[0].percent_unused = (unsigned)cylinders_to_percent(free_space[0].space,total_disk[cur_disk]); /* AN000 */
;           END
;
;         /* Find largest free space */
;         temp = u(0);                                                   /* AC000 */
;
;         /* Find largest free space, and verify the golden tracks while we are at it */
;         do
;            BEGIN
;             temp = u(0);                                               /* AC000 */
;
;             /* Zip thru the table */
;             for (i = c(0); i < c(24); i++)                             /* AC000 */
;                BEGIN
;                 /* Is this one bigger ? */
;                 if (free_space[i].space > temp)
;                    BEGIN
;                     temp = free_space[i].space;
;                     last_found_partition = i;
;                    END
;                END
;             /* If there is any free space, go verify it */
;             temp = u(0);
;             if (free_space[last_found_partition].space != u(0))       /* AC000 */
;                BEGIN
;
;                 /* Go verify the tracks */
;                 temp = verify_tracks(last_found_partition,c(EXTENDED)); /* AC000 */
;                END
;             /* Move up to next golden track */
;             free_space[last_found_partition].start = free_space[last_found_partition].start+temp;
;             free_space[last_found_partition].space = free_space[last_found_partition].space-temp;
;             free_space[last_found_partition].mbytes_unused =
;                  cylinders_to_mbytes(free_space[last_found_partition].space,cur_disk);    /* AN004 */
;             free_space[last_found_partition].percent_unused =
;                  cylinders_to_percent(free_space[last_found_partition].space,total_disk[cur_disk]); /* AN000 */
;             END
;             /* Repeat the loop if the start was moved due to bad tracks */
;            /* Unless we're past the end of the free space */
;            while ((temp !=u(0)) && (free_space[last_found_partition].space!= u(0)));  /* AC000 */
;
;        /* Don't create a partition larger than DOS can handle */                              /*C05*/
;        if(free_space[last_found_partition].mbytes_unused > u(MAX_PART_SIZE))                  /*C05*/
;          BEGIN                                                                                /*C05*/
;          free_space[last_found_partition].space =                                             /*C05*/
;           mbytes_to_cylinders(f(MAX_PART_SIZE),cur_disk) - 1;                                 /*C05*/
;          free_space[last_found_partition].end =                                               /*C05*/
;           free_space[last_found_partition].start+free_space[last_found_partition].space-1;    /*C05*/
;          free_space[last_found_partition].mbytes_unused =                                     /*C05*/
;           cylinders_to_mbytes(free_space[last_found_partition].space,cur_disk);               /*C05*/
;          free_space[last_found_partition].percent_unused = (unsigned)                         /*C05*/
;           cylinders_to_percent(free_space[last_found_partition].space,total_disk[cur_disk]);  /*C05*/
;          END                                                                                  /*C05*/
;
;        /* Return with the pointer to the largest free space */
;        return(last_found_partition);
;END

find_ext_free_space:
		; 21/01/2019
		; 20/01/2019

	%define fefs_i		     	bp-12	;bp-14
	%define fefs_ext_location    	bp-10	;bp-12
	%define fefs_last_found_part 	bp-8	;bp-10
	%define fefs_temp	     	bp-6	;bp-8
	%define fefs_freespace_count 	bp-4	;bp-6
	%define fefs_partition_count 	bp-2	;bp-4
	%define fefs_any_partition   		;bp-2

		push	bp
		mov	bp,sp
		;sub	sp,14
		sub	sp,12

		;push	di
		;push	si

		;/* Sort the partition table */

		;mov	al,23
		;push	ax
		mov	cl,23
		call	sort_ext_table
		;pop	bx

		;/* Initialize free space to zero */

		xor	ax,ax ; 21/01/2019

		;mov	word [fefs_i],0
		mov	[fefs_i],ax ; 0
fefs_1:
		;;mov	al,22
		;mov	al,10
		;;imul	byte [fefs_i]
		;mul	byte [fefs_i]
		;mov	bx,ax
		;sub	ax,ax
		;mov	[free_space.space+bx],ax
		;mov	[free_space.start+bx],ax
		;mov	[free_space.end+bx],ax
		;mov	[free_space.mbytes_unused+bx],ax
		;mov	[free_space.percent_unused+bx],ax
		;inc	byte [fefs_i]
		;cmp	byte [fefs_i],24
		;jl	short fefs_1

		;push	cs
		;pop	es
		mov	di,fspc ; free_space.space
		mov	cx,24*5 ; (24*10/2) ; 20/01/2019
		;xor	ax,ax ; 0
		rep	stosw

	;/* Find space between start of Extended partition and first volume */

		;mov	al,5
		;push	ax
		;call	find_partition_location
		;pop	bx

		;mov	[fefs_ext_location],al
		
		; 20/01/2019
		; get partition entry number of extended dos partion
 		; 	(on current disk/drive)
		mov	al,5  ; EXTENDED partition ID
		call	find_partition_type
		; CL = partition number (index), 0 to 3 or 4 (not found)

		mov	[fefs_ext_location],cl

		sub	al,al ; 0
		mov	[fefs_partition_count],al ; 0
		;mov	[fefs_any_partition],al ; 0
		;mov	[fefs_i],al ; 0
		;jmp	short fefs_3
		jmp	short fefs_4
fefs_2:
		inc	byte [fefs_i]
fefs_3:
		cmp	byte [fefs_i],23
		jb	short fefs_4
		;jmp	fefs_5
		;jnb	short fefs_5  ; [fefs_any_partition] = 0
		jmp	fefs_11 ; [fefs_any_partition] = 0
fefs_4:
		mov	al,[cur_disk]
		;cbw
		mov	cx,24
		;mov	bx,ax
		mov	bl,al
		;imul	cx
		mul	cl
		;mov	cx,ax ; ah = 0
		;mov	al,[fefs_i]
		;cbw
		;mov	si,ax
		mov	si,[fefs_i] ; =**=
		;mov	al,[sort+si]
		mov	cl,[sort+si]
		;cbw
		;add	ax,cx
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	di,ax
	
		cmp	byte [ext_table_sys_id+di],0
		je	short fefs_2

		;shl	bx,1
		;shl	bx,1
		shl	bl,1
		shl	bl,1
		mov	al,[fefs_ext_location]
		;cbw
		;add	ax,bx
		add	al,bl
		;imul	cx
		mul	cl
		mov	bx,ax
		;mov	ax,[part_table_start_cyl+bx]
		;mov	[free_space.start],ax
		mov	dx,[part_table_start_cyl+bx]
		mov	[free_space.start],dx
		mov	cx,[ext_table_start_cyl+di]
		;mov	dx,cx
		mov	ax,cx
		dec	cx
		mov	[free_space.end],cx
		;mov	cl,[cur_disk]
		;push	cx
		mov	bl,[cur_disk]	      ; BX = Drive number	
		xor	bh,bh
		push	bx ; *
		;sub	dx,ax
		sub	ax,dx
		;mov	[free_space.space],dx
		mov	[free_space.space],ax ; AX = CYLINDERS
		;push	dx
			; BX = drive number (0 to 7)
			; AX = cylinders
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		mov	[free_space.mbytes_unused],ax

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		pop	bx ; *
		;shl	bx,1
		shl	bl,1
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx]  ; total (disk) cylinders -divisor-
		;push	word [free_space.space]
		mov	bx,[free_space.space] ; num of cylinders (of partition) -dividend-
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[free_space.percent_unused],ax
		mov	al,[fefs_i]
		mov	[fefs_partition_count],al
		mov	al,[sort+si] ; =**=
		mov	[fefs_last_found_part],al
		;mov	[fefs_any_partition],1

		;/* See if any partitions were there */
;fefs_5:
;		cmp	byte [fefs_any_partition],0
;		jne	short fefs_6
;		jmp	fefs_11
fefs_6:
		;/* Look for space between the rest of the partitions */

		mov	byte [fefs_freespace_count],1
		;mov	al,[fefs_partition_count]
		;inc	al
		;mov	[fefs_i],al
		;jmp	fefs_9
		; 21/01/2019
		jmp	short fefs_8 ; inc byte [fefs_i]
fefs_7:
		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]
		;mov	cx,ax ; ah = 0
		mov	bl,al ; ==*
		;mov	al,[fefs_i]
		;cbw
		;;mov	bx,ax
		mov	si,[fefs_i]  ; *==*
		;mov	al,[sort+bx]
		;cbw
		;add	ax,cx
		mov	cl,[sort+si] ; *==*
		add	al,cl	
	
		;mov	si,46
		;imul	si
		mov	cl,46
		mul	cl

		mov	di,ax
		
		cmp	byte [ext_table_sys_id+di],0
		je	short fefs_8

	;/* Get space between the end of the last one and the start of the next one */

		mov	al,[fefs_last_found_part]
		;cbw
		;add	ax,cx
		add	al,bl ; ==*
		;imul	si
		mul	cl ; * 46
		;mov	si,ax
		mov	bx,ax ; ++=

		; 21/01/2019
		;mov	ax,[ext_table_start_cyl+di]
		;mov	cx,ax
		mov	dx,[ext_table_start_cyl+di]
		mov	cx,dx
		;;sub	ax,[ext_table_end_cyl+si]
		;sub	ax,[ext_table_end_cyl+bx] ; ++=
		;dec	ax
		;mov	[fefs_temp],ax
		;mov	dx,ax
		sub	dx,[ext_table_end_cyl+bx] ; ++=
		dec	dx
		;mov	[fefs_temp],dx

		;mov	al,22
		mov	al,10
		;imul	byte [fefs_freespace_count]
		mul	byte [fefs_freespace_count]
		mov	di,ax
		mov	[free_space.space+di],dx
		;mov	ax,[ext_table_end_cyl+si]
		mov	ax,[ext_table_end_cyl+bx] ; ++=
		inc	ax
		mov	[free_space.start+di],ax
		dec	cx
		mov	[free_space.end+di],cx

		;mov	al,[cur_disk]
		;push	ax
		;push	word [free_space.space+di]
		;mov	si,bx
		
		sub	bh,bh
		mov	bl,[cur_disk]
		push	bx ; *!*

		;mov	ax,[free_space.space+di]
		mov	ax,dx 
			; bx = drive number (0 to 7)
			; ax = cylinders
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx

		mov	[free_space.mbytes_unused+di],ax

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		
		pop	bx ;*!*

		;shl	bx,1
		shl	bl,1
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx]
		;push	word [free_space.space+di]
		mov	bx,[free_space.space+di] 
			; cx = total (disk) cylinders -divisor-
			; bx = num of cylinders (of partition) -dividend-
		call	cylinders_to_percent
		;pop	bx
		;pop	bx

		mov	[free_space.percent_unused+di],ax

		;/* update the last found partition */

		mov	al,[sort+si] ; *==*
		mov	[fefs_last_found_part],al
		inc	byte [fefs_freespace_count]
fefs_8:

		inc	byte [fefs_i]
fefs_9:
		cmp	byte [fefs_i],23
		;jge	short fefs_10
		jnb	short fefs_10
		jmp	fefs_7
fefs_10:
	;/* Find the space between the last partition and the end of the extended partition */

		;mov	al,[fefs_last_found_part]
		mov	dl,[fefs_last_found_part] ; -*-
		;cbw
		;mov	cx,24
		mov	cl,24
		;mov	dx,ax
		mov	al,[cur_disk] ; *-*-
		;cbw
		;mov	bx,dx
		;mov	si,ax
		mov	bl,al ; *-*-
		;imul	cx
		mul	cl
		;add	ax,bx ; ah = 0
		add	al,dl ; -*-
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		;mov	bx,ax
		mov	si,ax ; -**-
		mov	al,[fefs_ext_location]
		;cbw
		;shl	si,1
		;shl	si,1
		shl	bl,1 ; *-*-
		shl	bl,1
		;add	ax,si
		add	al,bl ; *-*-
		;imul	cx
		mul	cl
		;mov	si,ax
		mov	bx,ax ; -***-
		;mov	ax,[part_table_end_cyl+si]
		mov	cx,[part_table_end_cyl+bx] ; -***-
		;mov	cx,ax
		mov	dx,cx ; ++
		;sub	ax,[ext_table_end_cyl+bx]
		sub	cx,[ext_table_end_cyl+si] ; -**-
		;;mov	[fefs_temp],ax
		;mov	[fefs_temp],cx ; *+
		;mov	dx,ax
		;mov	al,22
		mov	al,10
		;imul	byte [fefs_freespace_count]
		mul	byte [fefs_freespace_count]
		;mov	si,ax
		mov	di,ax ; -****-
		;mov	[free_space.space+si],dx
		mov	[free_space.space+di],cx ; -****- ; *+

		;mov	ax,[ext_table_end_cyl+bx]
		mov	ax,[ext_table_end_cyl+si] ; -**-
		inc	ax
		;mov	[free_space.start+si],ax
		mov	[free_space.start+di],ax ; -****-
		;mov	[free_space.end+si],cx
		mov	[free_space.end+di],dx ; -****- ; ++
		
		;mov	al,[cur_disk]
		;push	ax
		sub	bh,bh
		mov	bl,[cur_disk]
		push	bx ; +**
		;push	word [free_space.space+si]
		;mov	ax,[free_space.space+di] ; *+
		mov	ax,cx ; *+ ; 21/01/2019
			; bx = drive number (0 to 7)
			; ax = cylinders	
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		;mov	[free_space.mbytes_unused+si],ax
		mov	[free_space.mbytes_unused+di],ax

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		
		pop	bx ; +**

		;shl	bx,1
		shl	bl,1	
		
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx]
		;push	word [free_space.space+si]
		mov	bx,[free_space.space+di] 
			; cx = total (disk) cylinders -divisor-
			; bx = num of cylinders (of partition) -dividend-
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		;mov	[free_space.percent_unused+si],ax
		mov	[free_space.percent_unused+di],ax
		jmp	short fefs_12
fefs_11:
	;/* No partitions found, show entire space as free */

		mov	al,[cur_disk]
		cbw

		push	ax ; **

		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1
		;mov	cx,ax
		;mov	al,[fefs_ext_location]
		;cbw
		;add	ax,cx
		add	al,[fefs_ext_location]
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl
		mov	bx,ax
		; 21/01/2019
		mov	ax,[part_table_end_cyl+bx]
		;mov	cx,ax
		mov	[free_space.end],ax
		sub	ax,[part_table_start_cyl+bx]
		inc	ax
		mov	[free_space.space],ax
		mov	dx,[part_table_start_cyl+bx]
		mov	[free_space.start],dx
		;mov	[free_space.end],cx
		;mov	cl,[cur_disk]
		;push	cx
		;push	ax
		pop	bx ; **
		mov	si,bx ; **
			; bx = drive number (0 to 7)
			; ax = cylinders
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		mov	[free_space.mbytes_unused],ax
		
		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;shl	bx,1
		shl	si,1 ; **
		;push	word [total_disk+bx]
		mov	cx,[total_disk+si]
		;push	word [free_space.space]
		mov	bx,[free_space.space] 	
			; cx = total (disk) cylinders -divisor-
			; bx = num of cylinders (of partition) -dividend-
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[free_space.percent_unused],ax
fefs_12:
		;mov	word [fefs_temp],0
fefs_13:
	;/* Find largest free space, and verify the golden tracks while we are at it */

		mov	word [fefs_temp],0

		; /* Zip thru the table */

		mov	byte [fefs_i],0
fefs_14:
		;mov	al,22
		mov	al,10
		;imul	byte [fefs_i]
		mul	byte [fefs_i]
		mov	bx,ax
		;mov	ax,[fefs_temp]
		mov	ax,[free_space.space+bx]
		;cmp	[free_space.space+bx],ax
		cmp	ax,[fefs_temp]
		jbe	short fefs_15
		;mov	ax,[free_space.space+bx]
		mov	[fefs_temp],ax
		mov	al,[fefs_i]
		mov	[fefs_last_found_part],al
fefs_15:
		inc	byte [fefs_i]
		cmp	byte [fefs_i],24
		jb	short fefs_14

		;/* If there is any free space, go verify it */

		mov	word [fefs_temp],0

		;mov	al,22
		mov	al,10
		;imul	byte [fefs_last_found_part]
		mul	byte [fefs_last_found_part]
		mov	bx,ax

		cmp	word [free_space.space+bx],0
		je	short fefs_16

		;/* Go verify the tracks */

		mov	al,5 ; EXTENDED  ; type
		push	ax
		mov	al,[fefs_last_found_part] ; pointer
		push	ax
		call	verify_tracks
		;pop	bx
		;pop	bx
		mov	[fefs_temp],ax
fefs_16:
		;/* Move up to next golden track */

		;mov	al,22
		mov	al,10
		;imul	byte [fefs_last_found_part]
		mul	byte [fefs_last_found_part]
		;mov	bx,ax
		mov	si,ax
		mov	ax,[fefs_temp]
		;add	[free_space.start+bx],ax
		add	[free_space.start+si],ax

		;mov	cl,[cur_disk]
		;push	cx
		;sub	[free_space.space+bx],ax
		;push	word [free_space.space+bx]
		;mov	si,bx
		xor	bh,bh
		mov	bl,[cur_disk]
		push	bx ; --*
		sub	[free_space.space+si],ax
		mov	ax,[free_space.space+si]
			; bx = drive number (0 to 7)
			; ax = cylinders
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		mov	[free_space.mbytes_unused+si],ax

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		pop	bx; --*
		;shl	bx,1
		shl	bl,1
		;push	word [total_disk+bx]
		mov	cx,[total_disk+bx]
		;push	word [free_space.space+si]
		mov	bx,[free_space.space+si]
			; cx = total (disk) cylinders -divisor-
			; bx = num of cylinders (of partition) -dividend-
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[free_space.percent_unused+si],ax

	;/* Repeat the loop if the start was moved due to bad tracks */
        ;/* Unless we're past the end of the free space */

		xor	ax,ax ; 20/01/2019

		;cmp	word [fefs_temp],0
		cmp	[fefs_temp],ax ; 0
		je	short fefs_17

		;;mov	al,22
		;mov	al,10
		;;imul	byte [fefs_last_found_part]
		;mul	byte [fefs_last_found_part]
		;mov	bx,ax
		;;cmp	word [free_space.space+bx],0
		;cmp	word [free_space.space+si],0
		cmp	[free_space.space+si],ax ; 0
		je	short fefs_17
		jmp	fefs_13
fefs_17:
	;/* Don't create a partition larger than DOS can handle */ 

		jmp	fefs_18  ; 20/01/2019

;		;;mov	al,22
;		;mov	al,10
;		;;imul	byte [fefs_last_found_part]
;		;mul	byte [fefs_last_found_part]
;		;mov	bx,ax
;
;		;cmp	[free_space.mbytes_unused+bx],2048
;		cmp	[free_space.mbytes_unused+si],2048  ; 2 GB limit
;		jbe	short fefs_18
;
;		mov	al,[cur_disk]
;		; ah = 0
;
;		push	ax ; *
;		
;		push	ax
;		mov	ax,2048
;		push	ax
;		mov	si,bx
;		call	mbytes_to_cylinders
;		;pop	bx
;		;pop	bx
;
;		pop	di ; *
;
;		dec	ax
;
;		mov	[free_space.space+si],ax
;
;		;mov	ax,[free_space.start+si]
;		;add	ax,[free_space.space+si]
;
;		add	ax,[free_space.start+si]
;
;		dec	ax
;		mov	[free_space.end+si],ax
;
;		;mov	al,[cur_disk]
;		;push	ax
;		;push	word [free_space.space+si]
;		mov	ax,[free_space.space+si]
;		mov	bx,di ; *
;		call	cylinders_to_mbytes
;		;pop	bx
;		;pop	bx
;
;		mov	[free_space.mbytes_unused+si],ax
;
;		;mov	al,[cur_disk]
;		;cbw
;		;mov	bx,ax
;		;shl	bx,1
;		;push	word [total_disk+bx]
;		shl	di,1 ; *
;		mov	cx,[total_disk+di]
;		;push	word [free_space.space+si]
;		mov	bx,[free_space.space+si]
;		call	cylinders_to_percent
;		;pop	bx
;		;pop	bx
;		mov	[free_space.percent_unused+si],ax
;fefs_18:
;		mov	al,[fefs_last_found_part] ; mov al,[bp-8]
;
;		;pop	si
;		;pop	di
;
;		mov	sp,bp
;		pop	bp
;		retn

; ----------------------------------------------------------------------------
; makepart.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 21/01/2019)

;char make_volume(size,free_pointer)
;
;unsigned    size;
;char   free_pointer;
;
;BEGIN
;
;    char table_pointer;
;    unsigned ext_part_num;                                        /* AN000 */
;    unsigned char   temp;
;    unsigned long   total_sectors;
;
;    /* Find a free spot to put it in */
;    table_pointer = find_free_ext();
;
;    if (table_pointer != ((char)(NOT_FOUND)))
;       BEGIN
;        /* found a free partition, now lets go fill it up */
;
;        /* This can never be marked active */
;        ext_table[cur_disk][table_pointer].boot_ind = uc(0);     /* AC000 */
;
;        /* Go get the start cylinder */
;        ext_table[cur_disk][table_pointer].start_cyl = free_space[free_pointer].start;
;
;        /* Setup end cylinder */
;        ext_table[cur_disk][table_pointer].end_cyl = ext_table[cur_disk][table_pointer].start_cyl + size - 1;
;
;        /* Start sector is always 1 */
;        ext_table[cur_disk][table_pointer].start_sector = uc(1);  /* AC000 */
;
;        /* End sector is always the last sector */
;        ext_table[cur_disk][table_pointer].end_sector = max_sector[cur_disk];
;
;        /* End head is always the last head */
;        ext_table[cur_disk][table_pointer].end_head = uc(max_head[cur_disk]-1);  /* AC004 */
;
;        /* Start head is always 1 - NOTE: This is a shortcut for PC-DOS */
;        /* If this is being modified for IFS drivers this may not be the */
;        /* the case - use caution */
;        ext_table[cur_disk][table_pointer].start_head = uc(1);   /* AC000 */
;
;        /* Figure out the total number of sectors */
;        /* Total sectors in partition =                    */
;        /* [(end_cyl - start_cyl)*(max_sector)*(max_head)] */
;        /* - [start_head * max_sector]                     */
;        /* Note: This is assuming a track or cylinder aligned partition */
;
;        /* First - get the total size in Cylinders assuming head 0 start*/
;        total_sectors = ((unsigned long)(ext_table[cur_disk][table_pointer].end_cyl -
;          ext_table[cur_disk][table_pointer].start_cyl+1));
;
;        /* Now multiply it by the number of sectors and heads per track */
;        total_sectors = total_sectors * max_sector[cur_disk] * max_head[cur_disk];
;
;        /* This will give us the total of sectors if it is cyl aligned */
;        /* Now, if it isn't aligned on head 0, we need to subtract off */
;        /* the skipped tracks in the first cylinder  */
;
;        /* Because the head is zero based, we can get the total number of */
;        /* skipped sectors by multipling the head number by sectors per track */
;        total_sectors = total_sectors - ((unsigned long)(ext_table[cur_disk][table_pointer].start_head *
;                           max_sector[cur_disk]));
;
;        ext_table[cur_disk][table_pointer].num_sec = total_sectors;
;
;        /* Get the relative sector */
;        /* Figure out the total number of sectors */
;        /* Total sectors before partition = max_sector     */
;        /* NOTE: Again, this is a PC-DOS 3.30 shortcut - by definition */
;        /* a logical drive always starts on head 1, so there is always */
;        /* one tracks worth of sectors before it. Hence, max_sector */
;
;        /* Save it! */
;        ext_table[cur_disk][table_pointer].rel_sec = ((unsigned long)(max_sector[cur_disk]));
;
;        /* Setup the system id byte */
;        /* Set to 06h - format will fix later on */
;        /* EGH; 7/03/90; We fix up the size ourselves here. The
;           calculation is simple. If total_sectors > 65536 then
;           type = 06 else if total_sectors > 32680 then type = 04
;           else type = 01 */
;
;        if (ext_table[cur_disk][table_pointer].num_sec > ul(65536))     /*C23*/
;            temp = uc(DOSNEW);                                         /* AC000 */                                    /*  AN000  */
;        else if (ext_table[cur_disk][table_pointer].num_sec > ul(FAT16_SIZE)) /*C23*/
;            temp = uc(DOS16);                                           /*C23*/
;        else                                                            /*C23*/
;            temp = uc(DOS12);                                           /*C23*/
;
;        /* We got the sys id, now put it in */
;        ext_table[cur_disk][table_pointer].sys_id = temp;
;
;        /* Set the changed flag */
;        ext_table[cur_disk][table_pointer].changed = TRUE;
;
;        /* Set the mbytes used */
;        ext_table[cur_disk][table_pointer].mbytes_used =
;            cylinders_to_mbytes(size,cur_disk);                   /* AN004 */
;
;        /* find the number of the extended partition to figure out percent */
;        ext_part_num = find_partition_location(uc(EXTENDED));              /* AN000 */
;
;        /* Set the percent used */
;        ext_table[cur_disk][table_pointer].percent_used =
;            cylinders_to_percent(((ext_table[cur_disk][table_pointer].end_cyl-ext_table[cur_disk][table_pointer].start_cyl)+1),
;            ((part_table[cur_disk][ext_part_num].end_cyl-part_table[cur_disk][ext_part_num].start_cyl)+1)); /* AN000 */
;
;        /* set the system to unknown and volume label to blanks */
;        strcpy(ext_table[cur_disk][table_pointer].system,NOFORMAT);     /* AN000 */
;        strcpy(ext_table[cur_disk][table_pointer].vol_label,NOVOLUME);  /* AN000 */
;
;       END
;    else
;
;       BEGIN
;        /* This should not have happened */
;        internal_program_error();
;       END
;
;    return(table_pointer);
;END

make_volume:
		; 21/01/2019

	;%define mv_total_secs_lw 	;bp-10	;bp-14
	;%define mv_total_secs_hw 	;bp-8	;bp-12
	%define mv_table_ptr	bp-2 	;bp-6	;bp-10
	;%define mv_ext_part_num 	;bp-4	;bp-8
	;%define mv_temp	 	;bp-2	;bp-6

	%define mv_size		bp+4
	%define mv_free_ptr	bp+6

		push	bp
		mov	bp,sp

		;;;sub	sp,14
		;;sub	sp,10
		;sub	sp,2

		;xor	ax,ax
		push	ax ; sub sp,2

		;push	di
		;push	si

		;/* Find a free spot to put it in */
		
		call	find_free_ext
		mov	[mv_table_ptr],al
		inc	al
		jnz	short mv_1
		jmp	mv_8
mv_1:
	;/* found a free partition, now lets go fill it up */

		mov	al,[cur_disk]
		cbw
		;mov	cx,24
		mov	cl,24
		mov	bx,ax  ; *****
		;imul	cx
		mul	cl
		;mov	cx,ax

		;mov	al,[mv_table_ptr]
		;cbw
		;add	ax,cx

		; ah = 0
		add	al,[mv_table_ptr]
		
		;mov	cx,46
		;imul	cx
		mov	cl,46
		mul	cl

		mov	si,ax ; *-+*

		;/* This can never be marked active */
		mov	byte [ext_table_boot_ind+si],0

		;/* Go get the start cylinder */

		;mov	al,22
		mov	al,10
		;imul	byte [mv_free_ptr]
		mul	byte [mv_free_ptr]
		mov	di,ax

		mov	ax,[free_space.start+di]
		mov	[ext_table_start_cyl+si],ax

		;/* Setup end cylinder */

		add	ax,[mv_size]
		dec	ax
		mov	[ext_table_end_cyl+si],ax

		;/* Start sector is always 1 */

		mov	byte [ext_table_start_sector+si],1

		;/* End sector is always the last sector */

		mov	al,[max_sector+bx]
		
		sub	ah,ah
		mov	di,ax ; -**- ; [start_head * max_sector]  

		mov	[ext_table_end_sector+si],al
		
		;/* End head is always the last head */

		shl	bx,1  ; *****
		mov	cl,[max_head+bx] ; num of (disk) heads
		mov	ah,cl ; 21/01/2019
		dec	cl
		mov	[ext_table_end_head+si],cl

	;/* Start head is always 1 - NOTE: This is a shortcut for PC-DOS */
	;/* If this is being modified for IFS drivers this may not be the */
	;/* the case - use caution */

		mov	byte [ext_table_start_head+si],1 ; start_head = 1

	;/* Figure out the total number of sectors */
	;/* Total sectors in partition =                    */
	;/* [(end_cyl - start_cyl)*(max_sector)*(max_head)] */
	;/* - [start_head * max_sector]                     */
	;/* Note: This is assuming a track or cylinder aligned partition */
	;
	;/* First - get the total size in Cylinders assuming head 0 start*/
	;total_sectors = ((unsigned long)(ext_table[cur_disk][table_pointer].end_cyl -
	;          ext_table[cur_disk][table_pointer].start_cyl+1));
		
		;sub	ah,ah
		;mov	cx,ax
		;sub	dx,dx
		;push	dx
		;push	ax
		;mov	di,cx
		;mov	ax,[ext_table_end_cyl+si]
		;sub	ax,[ext_table_start_cyl+si]
		;inc	ax
		;mov	[mv_total_secs_lw],di
		;mov	[mv_total_secs_hw],dx

	;/* Now multiply it by the number of sectors and heads per track */
	;total_sectors = total_sectors * max_sector[cur_disk] * max_head[cur_disk];
	;
	;/* This will give us the total of sectors if it is cyl aligned */


		;mul	word [max_head+bx]
		;push	dx
		;push	ax
		;call	mul32

		; al = max_sector (sectors per track) <= 63
		; ah = max_head (heads) - 2 to 255

		mul	ah
			 ; ax <= 16065

		mov	cx,[ext_table_end_cyl+si]
		sub	cx,[ext_table_start_cyl+si]
		inc	cx
 
		mul	cx
			 ; dx:ax = cylinders*heads*spt 

	;/* Now, if it isn't aligned on head 0, we need to subtract off */
	;/* the skipped tracks in the first cylinder */

	;/* Because the head is zero based, we can get the total number of */
	;/* skipped sectors by multipling the head number by sectors per track */
	;total_sectors = total_sectors - ((unsigned long)(ext_table[cur_disk][table_pointer].start_head *
	;                max_sector[cur_disk]));

		xor	cx,cx

		sub	ax,di  ; -**-  ; - [start_head * max_sector]  
		;sbb	dx,0
		sbb	dx,cx

		;mov	cx,ax
		;mov	ax,di
		;mov	bx,dx
		;cwd
		;sub	cx,ax
		;sbb	bx,dx
		;mov	ax,cx
		;mov	dx,bx
		
		mov	[ext_table_num_sec_lw+si],ax
		mov	[ext_table_num_sec_hw+si],dx

	;/* Get the relative sector */
	;/* Figure out the total number of sectors */
	;/* Total sectors before partition = max_sector */
	;/* NOTE: Again, this is a PC-DOS 3.30 shortcut - by definition */
	;/* a logical drive always starts on head 1, so there is always */
	;/* one tracks worth of sectors before it. Hence, max_sector */
		
		;mov	ax,[mv_total_secs_lw]
		;mov	dx,[mv_total_secs_hw]
		;mov	[ext_table_rel_sec_lw+si],ax
		;mov	[ext_table_rel_sec_hw+si],dx

		;/* Save it! */

		mov	[ext_table_rel_sec_lw+si],di ; -**- ; max_sector
		;mov	word [ext_table_rel_sec_hw+si],0
		mov	[ext_table_rel_sec_hw+si],cx ; 0

mkvol_chk_fat16_limit:
		;/* Setup the system id byte */
		;/* Set to 06h - format will fix later on */
		;/* EGH; 7/03/90; We fix up the size ourselves here.
		; The calculation is simple. If total_sectors > 65536 then
		; type = 06 else if total_sectors > 32680 then type = 04
		; else type = 01 */

		;cmp	word [ext_table_num_sec_hw+si],1
		cmp	dx,1
		;jb	short mkvol_chk_fat12_limit
		jb	short mv_10
		ja	short mkvol_fat16big
		;cmp	word [ext_table_num_sec_lw+si],0
		;je	short mkvol_chk_fat12_limit
		
		and	ax,ax
		;jz	short mkvol_chk_fat12_limit
	 	jz	short mkvol_fat16 ; partition size: 65536 sectors
mkvol_fat16big:
		;mov	byte [mv_temp],6  ; DOSNEW
		mov	al,6
		jmp	short mv_7
mkvol_chk_fat12_limit:
		;mov	al,[mv_table_ptr]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;;imul	byte [cur_disk]
		;mul	byte [cur_disk]
		;add	ax,cx
		;mov	cx,46
		;imul	cx
		;mov	bx,ax

		;;cmp	word [ext_table_num_sec_hw+bx],0
		;cmp	word [ext_table_num_sec_hw+si],0
		;jne	short mkvol_fat16

		;and	dx,dx
		;jnz	short mkvol_fat16
mv_10:
		;;cmp	word [ext_table_num_sec_lw+bx],32680 ; FAT12 upper limit
		;cmp	word [ext_table_num_sec_lw+si],32680
		;jbe	short mkvol_fat12
		cmp	ax,32680
		jbe	short mkvol_fat12
mkvol_fat16:
		;mov	byte [mv_temp],4 ; DOS16
		mov	al,4
		jmp	short mv_7
mkvol_fat12:
		;mov	byte [mv_temp],1 ; DOS12
		mov	al,1
mv_7:
		;mov	al,[mv_table_ptr]
		;cbw
		;mov	cx,ax
		;mov	al,24
		;;imul	byte [cur_disk]
		;mul	byte [cur_disk]
		;add	ax,cx
		;;mov	bx,46
		;mov	bl,46
		;;imul	bx
		;mul	bl
		;mov	si,ax

		;/* We got the sys id, now put it in */

		;mov	al,[mv_temp]
		mov	[ext_table_sys_id+si],al

		;/* Set the changed flag */

		mov	byte [ext_table_changed+si],1

		;/* Set the mbytes used */

		;mov	al,[cur_disk]
		;push	ax
		; bh = 0
		;mov	bl,[cur_disk]
		;;xor	bh,bh

		shr	bl,1 ; ***** 
			; bl = [cur_disk]
			; bh = 0 

		;push	word [mv_size]
		;mov	di,cx
		mov	ax,[mv_size]
		call	cylinders_to_mbytes
		;pop	bx
		;pop	bx
		mov	[ext_table_mbytes_used+si],ax

	;/* find the number of the extended partition to figure out percent */

		;mov	al,5 ; EXTENDED
		;push	ax
		;call	find_partition_location
		;pop	bx
		;cbw
		;mov	[mv_ext_part_num],ax

		; get partition entry number of extended dos partion
 		; 	(on current disk/drive)
		mov	al,5  ; EXTENDED partition ID
		call	find_partition_type
		; cl = partition number (index), 0 to 3 or 4 (not found)

		;mov	[mv_ext_part_num],cl ; ***

		;/* Set the percent used */

		mov	al,[cur_disk]
		;cbw
		;mov	cx,ax
		
		;shl	ax,1
		;shl	ax,1
		shl	al,1
		shl	al,1		

		;add	ax,[mv_ext_part_num]
		add	al,cl ; ***		

		;mov	bx,46
		;mul	bx
		mov	cl,46
		mul	cl
		mov	bx,ax

		;mov	ax,[part_table_end_cyl+bx]
		;sub	ax,[part_table_start_cyl+bx]
		;inc	ax
		;push	ax

		mov	cx,[part_table_end_cyl+bx]
		sub	cx,[part_table_start_cyl+bx]
		inc	cx  ; extended dos partition cylinders

		;;mov	bx,24
		;mov	al,24
		;;mov	ax,cx
		;;imul	bx
		;mul	byte [cur_disk]
		;;add	ax,di
		;add	al,[mv_table_ptr]
		;;mov	cx,46
		;;imul	cx
		;mov	cl,46
		;mul	cl
		;mov	si,ax

		;mov	ax,[ext_table_end_cyl+si]
		;sub	ax,[ext_table_start_cyl+si]
		;inc	ax
		;push	ax

		mov	bx,[ext_table_end_cyl+si]
		sub	bx,[ext_table_start_cyl+si]
		inc	bx  ; dos volume cylinders
		call	cylinders_to_percent
		;pop	bx
		;pop	bx
		mov	[ext_table_percent_used+si],ax

	;/* set the system to unknown and volume label to blanks */
		
		;mov	ax,_NOFORMAT ; "UNKNOWN	"
		;push	ax
		
		;mov	al,24
		;;imul	byte [cur_disk]
		;mul	byte [cur_disk]
		;add	ax,di
		;;mov	cx,46
		;mov	cl,46
		;;imul	cx
		;mul	cl

		;add	ax,ext_table_system
		;push	ax
		
		mov	bx,si ; *

		mov	si,NO_FORMAT ; 'UNKNOWN ' ; source 
		mov	di,bx ; *
		add	di,ext_table_system ; destination 

		call	strcpy
		;pop	bx
		;pop	bx

		;mov	ax,NOVOLUME
		;push	ax

		;mov	al,24
		;;imul	byte [cur_disk]
		;mul	byte [cur_disk]
		;add	ax,di
		;mov	cx,46
		;imul	cx

		;add	ax,ext_table_vol_label
		;push	ax
		;call	strcpy
		;pop	bx
		;pop	bx
		
		;mov	di,bx ; *
		;mov	byte [di+ext_table_vol_label],0 ; NOVOLUME
		mov	byte [bx+ext_table_vol_label],0

		jmp	short mv_9
mv_8:
		;/* This should not have happened */
		call	internal_program_error
mv_9:
		;mov	al,[mv_table_ptr]
		
		;pop	si
		;pop	di
			   ; sp = bp-2	
		pop	ax ; mov al,[mv_table_ptr] ; mov al,[bp-2]
			   ; mov sp,bp	
		
		;mov	sp,bp
		pop	bp
		;retn
		retn	4

; ----------------------------------------------------------------------------
; partinfo.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 21/01/2019)

;char find_free_ext()
;
;BEGIN
;
; char   i;
;
;    /* Look at all 23 extended entries for empty partition */
;    for (i = c(0); i < c(23);i++) 				/* AC000 */
;       BEGIN
;        /* if we find an empty one, return which one */
;        if (ext_table[cur_disk][i].sys_id == uc(0))		/* AC000 */
;           BEGIN
;            return(i);
;            break;
;           END
;       END
;    return(c(NOT_FOUND));					/* AC000 */
;END

find_free_ext:
		; 21/01/2019

	;%define ffe_i bp-2

		;push	bp
		;mov	bp,sp
		;sub	sp,2

		;mov	byte [ffe_i],0
		;xor	cx,cx
		xor	cl,cl
		jmp	short ffe_2
ffe_1:
		;inc	byte [ffe_i]
		inc	cl
;ffe_2:
		;cmp	byte [ffe_i],23
		;jge	short ffe_3
		cmp	cl,23
		jnb	short ffe_3
ffe_2:
		;mov	al,[ffe_i]
		;cbw
		;mov	cx,ax
		mov	al,24
		;imul	byte [cur_disk]
		mul	byte [cur_disk]
		;add	ax,cx
		add	al,cl
		;mov	cx,46
		;imul	cx
		mov	bl,46
		mul	bl
		mov	bx,ax
		cmp	byte [ext_table_sys_id+bx],0
		jne	short ffe_1
		;mov	al,[ffe_i]
		mov	al,cl
		;jmp	short ffe_4
		retn
ffe_3:
		mov	al,0FFh	; NOT_FOUND
ffe_4:
		;mov	sp,bp
		;pop	bp
		
		retn

; ----------------------------------------------------------------------------
; int13.c (FDISK, MSDOS 6.0, 1991)	
; ----------------------------------------------------------------------------
; Modified and simplified for Assembly language (by Erdogan Tan, 26/01/2019)

; 28/01/2019

;/*  */
;unsigned verify_tracks(pointer,type)
;
;char pointer;
;char type;
;
;BEGIN
;  unsigned	i;
;
;  /* SR; 9/29/89; Temp store */
;  unsigned	j;
;  unsigned	sectors_per_fat;
;  unsigned	cur_cyl;
;  unsigned	verify_cyl;
;  unsigned	num_tracks;
;  unsigned	retry_flg;
;  unsigned	long   total_sectors;
;  char	golden_tracks;
;  char	retry;
;  unsigned char cur_head;					     /* AC004 */
;
;  char far *buffer_pointer = boot_record;
;
;  for (i=u(0); i< u(BYTES_PER_SECTOR);i++)                        /* AC000 */
;     BEGIN
;      /* Put something other then 0's so that unformatted FAT looks full */
;
;      boot_record[i] = uc(0xF6);                                /* AC000 */
;     END
;
;  /* Get the start cylinder for the sweep */
;  cur_cyl = free_space[pointer].start;
;
;  /* Also keep track of what it is */
;  verify_cyl = cur_cyl;
;
;  /* Initialize the start head -assume 0*/
;  cur_head = uc(0);                                             /* AC004 */
;
;  /* SR; 9/29/89; cur_head should be 1 for extended partitions too */
;  if (((type == c(PRIMARY)) && (cur_cyl == u(0))) || type == c(EXTENDED))  /* AC000 */
;    BEGIN
;
;     /* It's head 1 - NOTE: This is convience for PC-DOS because it is */
;     /* always this way - This may have to be beefed up for IFS  */
;     cur_head = uc(1);                                          /* AC004 */
;    END
;
;  /* Now go figure out the number of golden sectors needed. Use the */
;  /* allocation equation in the fixed disk section of DOS Tech Ref. */
;  /*                                                                */
;  /*  TS = Free cyl's * sector/track * track/cyl                    */
;  /*  RS = 1                                                        */
;  /*  D  = 512                                                      */
;  /*  BPD = 32                                                      */
;  /*  BPS = BYTES_PER_SECTOR                                        */
;  /*  CF = 2                                                        */
;  /*  SPF = Solve                                                   */
;  /*  SPC = 4 or 8                                                  */
;  /*  BPC = 1.5 or 2                                                */
;  /*                                                                */
;  /*  Golden Sectors = RS + 2(SPF) + BPD(D)  + (DOSFILES)           */
;  /*                                 ------   if bootable           */
;  /*                                  BPS                           */
;
;  total_sectors = ((unsigned long)free_space[pointer].space) * max_head[cur_disk] * max_sector[cur_disk];
;
;  /* Chop off one track if it starts on head 1 */
;  if (cur_head == uc(1))                                          /* AC004 */
;     BEGIN
;      total_sectors = total_sectors - max_sector[cur_disk];
;     END
;
;  /* See if 12 or 16 bit fat */
;  if (total_sectors > (unsigned long)FAT16_SIZE)
;     BEGIN
;      /* SR; 9/30/89; We have to round up the sectors_per_fat.
;         Calculate the denominator first */
;
;      j = 2 + (BYTES_PER_SECTOR * 2);
;      /* 16 bit */
;      /* SR; 9/30/89; To round up add j-1 and divide by j */
;      sectors_per_fat = u(((total_sectors - 33) + j - 1) / j);      /*C00*/
;     END
;  else
;     BEGIN
;      /* SR; 9/30/89; We have to round up the sectors_per_fat.
;      Calculate the denominator first. We have to round up the
;      denominator too. The multiplying factor 16 = SPC * 2 */
;
;      j = 2 + (( BYTES_PER_SECTOR * 16 ) + 2 ) / 3;
;      /* 12 bit */
;      sectors_per_fat = u(((total_sectors - 33) + j - 1) / j);      /*C00*/
;     END
;
;  /* Round up one just to handle any rounding errors */
;  /* SR; 9/30/89; We have taken care of the rounding */
;  /***SR; 9/30/89; sectors_per_fat++;   ***/
;
;  /* Now see how many tracks */
;  num_tracks = (sectors_per_fat*2) + 33;
;
;  /* If primary and drive 0, add in enough for system files */
;  if ((type == c(PRIMARY)) && (cur_disk == c(0)))                 /* AC000 */
;     BEGIN
;      num_tracks = num_tracks + SYSTEM_FILE_SECTORS;
;     END
;
;   /* Handle upward rounding */         /* The problem with the IBM code is */
;   if (num_tracks%max_sector[cur_disk] != u(0)) /* that if num_tracks is < max_sector[cur_disk] */
;       BEGIN                           /* the num_tracks becomes 0 due to the integer  */
;       num_tracks = num_tracks + max_sector[cur_disk]; /* division and num_tracks will not be inc'd .  */
;       END                             /* This section of code overcomes that. */
;
;   /* Now convert to tracks */
;   num_tracks = num_tracks/max_sector[cur_disk];
;
;   /* SR; 9/30/89; The number of tracks above does not take into
;      account the wasted track 0 which contains the partition info.
;      If cur_head = 0, then the above calculation would cause the
;      last track in the partition to be not verified */
;
;   if ( cur_head == 0 )
;           num_tracks++;
;
;   golden_tracks = FALSE;
;
;   while (!golden_tracks)
;       {                               /* this allows resetting the starting cyl of the golden tracks */
;       for (i = u(0);i < num_tracks; i++)
;           {               /* this for loop is to write the number of golden tracks  AC000 */
;           retry = c(0);                         /* AC000 */
;           do
;               {                                       /* this do loop is for retries */
;               retry++;
;               regs.h.ah = uc(VERIFY_DISK);          /* BC001 */ /* Specify the operation */
;               regs.h.al = (unsigned char)max_sector[cur_disk]; /* Specify number of sectors */
;               regs.h.cl = 1;  /* Specify the start sectors */
;				 /* AC000 BC001 Scramble CX so that sectors and cyl's are in INT 13 format*/
;               if (cur_cyl > u(255))                                 /* AC000 */
;                   regs.h.cl = regs.h.cl | ((unsigned char)((cur_cyl/256) << 6));
;               regs.h.ch = ((unsigned char)cur_cyl) & 0xFF;
;               regs.h.dl = ((unsigned char)cur_disk) + 0x80; /* Specify the disk */
;               regs.h.dh = cur_head;                       /* Specify the head */ /* AC004 */
;               int86((int)DISK, &regs, &regs);   /* BC001 */ /* verify the track */
;                   retry_flg = regs.x.cflag & 1; /* BN001 */
;               }
;           while ((retry_flg) && (retry != c(3))); /* BN001 */ /* retry loop */
;
;           /************************************************************/
;           /* Check to see if cylinder was verified w/o errors.        */
;           /************************************************************/
;
;           if (!retry_flg)
;               {                                               /* BN001 */
;           /*********************************************************/
;           /* Cylinder verified correctly. So write boot sector     */
;           /* and bump cylinder count, then go verify that cylinder.*/
;           /* Do not pass the end of the partition free space.      */
;           /*********************************************************/
;               retry = 0;
;               do
;                   {
;                   retry++;
;                   regs.h.ah = uc(WRITE_DISK);          /* BN001 */ /* Specify the operation */
;                   regs.h.al = 1;                       /* BN001 */ /* Write one sector only */
;                   regs.h.cl = 1;                       /* BN001 */ /* Specify the start sectors */ /* AC000 BC001 Need to scramble CX for INT 13 format */
;                   if (cur_cyl > u(255))                  /* BN001 */
;                   regs.h.cl = regs.h.cl | ((unsigned char)((cur_cyl/256) << 6)); /* BN001 */
;                   regs.h.ch = ((unsigned char)cur_cyl) & 0xFF;  /* BN001 */
;                   regs.h.dl = ((unsigned char)cur_disk) + 0x80; /* BN001 */ /* Specify the disk */
;                   regs.h.dh = cur_head;                       /* BN001 */ /* Specify the head */   /* AC004 */
;                   regs.x.bx = FP_OFF(buffer_pointer);         /* BN001 */ /* Point at the place to write */
;                   segregs.es = FP_SEG(buffer_pointer);        /* BN001 */
;                   DiskIo(&regs,&regs,&segregs);               /* BN001 */ /* write the track */
;                   retry_flg = regs.x.cflag & 1;               /* BN001 */
;                   }
;               while ((retry_flg) && (retry != c(3)));         /* BN001 */ /* retry loop */
;               }
;
;           /* See if we had a good read */
;           if (!retry_flg)                        /* AC000 */
;               BEGIN
;               golden_tracks = TRUE;
;               /* Get the next head */
;               cur_head++;
;
;               /* SR; 9/29/89; Head no. is pre-incremented and cannot
;                  subtract 1 from max_head[cur_disk] */
;               if (cur_head == (uc(max_head[cur_disk] )))       /* AC004 */
;                   BEGIN
;                   /* Up to the next cylinder */
;                   cur_head = uc(0);                          /* AC004 */
;                   cur_cyl++;
;
;                   /* Check to see if we've reached the end of the free_space*/
;                   if (cur_cyl > free_space[pointer].end)
;                       BEGIN
;                       /* It is, so return with the cyl offset equal to the freespace */
;                       return(free_space[pointer].space);
;                       END
;                   END
;               END
;           else
;               BEGIN
;               /* Get out of the for loop, with a false flag */
;               golden_tracks = FALSE;
;
;               /* Bump up to the next cylinder boundary */
;               cur_cyl++;
;
;               /* SR; 9/29/89; To get out of the loop we have to
;                  check if there have been enough golden tracks or
;                  not. The setting of the flag as above will not
;                  get us out of the loop. We return with the cyl
;                  offset equal to the freespace to indicate that
;                  this freespace cannot be used */
;
;               if ( cur_cyl > free_space[pointer].end )
;                   return( free_space[pointer].space );
;
;               cur_head = uc(0);                             /* AC004 */
;
;               /* Save the new verify start point */
;               verify_cyl = cur_cyl;
;
;               break;
;               END
;           END  /* for num_tracks */
;       } /*while !golden_tracks */
;
;  /* All done, return the offset from original cyl to the new one */
;  return(verify_cyl - free_space[pointer].start);
;END

verify_tracks:
		; 26/01/2019

	%define verify_cyl 	bp-14	;bp-22	;bp-26
	%define	cur_head   	bp-12	;bp-20	;bp-24
	;%define buffer_pointer_off 	;bp-18	;bp-20
	;%define buffer_pointer_seg 	;bp-16	;bp-18
	%define vt_i		bp-10	;bp-14	;bp-16
	%define num_tracks	bp-8	;bp-12	;bp-14
	;%define vt_total_secs_lw 	;bp-10	;bp-12
	;%define vt_total_secs_hw 	;bp-8	;bp-10
	%define vt_retry	bp-6		;bp-8
	%define cur_cyl		bp-4
	%define golden_tracks	bp-2

	%define vt_pointer	bp+4
	%define vt_type		bp+6

		push	bp
		mov	bp,sp
		;;sub	sp,28
		;sub	sp,22
		sub	sp,14

		;push	di
		;push	si

		;char far *buffer_pointer = boot_record;
		
		;mov	word [buffer_pointer_off],boot_record
		;mov	[buffer_pointer_seg],ds

		;for (i=u(0); i< u(BYTES_PER_SECTOR);i++)    

		;mov	word [vt_i],0

	;/* Put something other then 0's so that unformatted FAT looks full */
vt_01:
		;mov	bx,[vt_i]
		;mov	byte [boot_record+bx],0F6h  ; boot_record[i] = uc(0xF6);  
		;inc	word [vt_i]
		;cmp	[vt_i],512
		;jb	short vt_01

		;push	cs
		;pop	es

		mov	cx,256
		mov	di,boot_record
		mov	ax,0F6F6h
		rep	stosw
		
		;mov	al,22
		mov	al,10
		;imul	byte [vt_pointer]
		mul	byte [vt_pointer]
		;mov	bx,ax
		mov	si,ax ; ***

		;/* Get the start cylinder for the sweep */
		;cur_cyl = free_space[pointer].start;
		;
		;/* Also keep track of what it is */
		;verify_cyl = cur_cyl;

		;mov	ax,[free_space.start+bx]
		mov	ax,[free_space.start+si] ; ***
		mov	[cur_cyl],ax
		mov	[verify_cyl],ax

		;/* Initialize the start head - assume 0*/

		mov	byte [cur_head],0

		;cur_head should be 1 for extended partitions too */
	;  if (((type == c(PRIMARY)) && (cur_cyl == u(0))) || type == c(EXTENDED))
	
		cmp	byte [vt_type],0 ; PRIMARY
		jne	short vt_02
		or	ax,ax
		jz	short vt_03
vt_02:
		cmp	byte [vt_type],5 ; EXTENDED
		jne	short vt_04
vt_03:
	;/* It's head 1 - NOTE: This is convience for PC-DOS because it is */
	;/* always this way - This may have to be beefed up for IFS */

		;mov	byte [cur_head],1
		inc	byte [cur_head] ; [cur_head] = 1

;  /* Now go figure out the number of golden sectors needed. Use the */
;  /* allocation equation in the fixed disk section of DOS Tech Ref. */
;  /*                                                                */
;  /*  TS = Free cyl's * sector/track * track/cyl                    */
;  /*  RS = 1                                                        */
;  /*  D  = 512                                                      */
;  /*  BPD = 32                                                      */
;  /*  BPS = BYTES_PER_SECTOR                                        */
;  /*  CF = 2                                                        */
;  /*  SPF = Solve                                                   */
;  /*  SPC = 4 or 8                                                  */
;  /*  BPC = 1.5 or 2                                                */
;  /*                                                                */
;  /*  Golden Sectors = RS + 2(SPF) + BPD(D)  + (DOSFILES)           */
;  /*                                 ------   if bootable           */
;  /*                                  BPS                           */

vt_04:

;total_sectors = ((unsigned long)free_space[pointer].space) * max_head[cur_disk] 
;		* max_sector[cur_disk];

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;mov	al,[max_sector+bx]
		;sub	ah,ah
		;sub	dx,dx
		;push	dx
		;push	ax
		;mov	cx,ax

		mov	al,[cur_disk]
		cbw
		mov	bx,ax
		mov	al,[max_sector+bx] ; <= 63
		mov	cx,ax

		;;mov	al,22
		;mov	al,10
		;;imul	byte [vt_pointer]
		;mul	byte [vt_pointer]
		;mov	si,ax ; ***

		;shl	bx,1
		shl	bl,1
		mov	ax,[max_head+bx] ; <= 255
		;mov	bx,dx
		
		;mul	word [free_space.space+si]
		;push	dx
		;push	ax
		;mov	si,cx
		;mov	di,bx
		;call	mul32

		mul	cx ; [max_sector] 
			;ax = [max_sector] * [max_head] <= 16065
			;dx = 0

		mul	word [free_space.space+si]

		;mov	[vt_total_secs_lw],ax
		;mov	[vt_total_secs_hw],dx

		;/* Chop off one track if it starts on head 1 */

	;if (cur_head == uc(1))
	;  BEGIN
	;    total_sectors = total_sectors - max_sector[cur_disk];
	;  END
		cmp	byte [cur_head],1
		jne	short vt_05

		;sub	ax,si
		;sbb	dx,di

		xor	di,di ; 0

		sub	ax,cx	; cx = max_sector[cur_disk]
		;sbb	dx,0
		sbb	dx,di ; sbb dx,0

		;;mov	[vt_total_secs_lw],ax
		;;mov	[vt_total_secs_hw],dx
vt_05:
		;mov	[vt_total_secs_lw],ax
		;mov	[vt_total_secs_hw],dx

		;cmp	dx,di
		;jne	short vt_06

		;/* See if 12 or 16 bit fat */
		; if (total_sectors > (unsigned long)FAT16_SIZE)

		and	dx,dx
		jnz	short vt_06

		cmp	ax,32680  ; FAT16_SIZE (FAT 12 size limit)
		jbe	short vt_07 ; FAT 12
vt_06:
		;/* We have to round up the sectors_per_fat.
		;   Calculate the denominator first */

		;j = 2 + (BYTES_PER_SECTOR * 2);

		;mov	ax,1026 ; j
		;cwd

		mov	cx,1026 ; j  ; divisor

		;/* 16 bit */
		;To round up add j-1 and divide by j */
		;sectors_per_fat = u(((total_sectors - 33) + j - 1) / j); 

		;push	dx
		;push	ax
		;mov	ax,[vt_total_secs_lw]
		;mov	dx,[vt_total_secs_hw]

		add	ax,992 ; 1026-33-1
		;adc	dx,0
		adc	dx,di ; adc dx,0
		jmp	short vt_08
vt_07:
		;We have to round up the sectors_per_fat.
		;Calculate the denominator first. We have to round up the
		;denominator too. The multiplying factor 16 = SPC * 2 */

		;j = 2 + (( BYTES_PER_SECTOR * 16 ) + 2 ) / 3;
		
		;mov	ax,2733	; j (= 2731+2)
		;cwd

		mov	cx,2733	; j

		;/* 12 bit */
		;sectors_per_fat = u(((total_sectors - 33) + j - 1) / j);

		;push	dx
		;push	ax
		;mov	ax,[vt_total_secs_lw]
		;mov	dx,[vt_total_secs_hw]
		
		add	ax,2699 ; 2733-33-1  
			 ;ax <= 32680+2699
			 ;dx = 0
;vt_08:
		;adc	dx,di
vt_08:
		;push	dx
		;push	ax
			; dx:ax = dividend (32 bit)
			; cx = divisor (16 bit)

		call	div32
			; ax = sectors per fat

		;/* Round up one just to handle any rounding errors */
		;/* We have taken care of the rounding */

		;/* Now see how many tracks */
		;num_tracks = (sectors_per_fat*2) + 33;

		shl	ax,1
		add	ax,33
		mov	[num_tracks],ax

	;/* If primary and drive 0, add in enough for system files */

		;if ((type == c(PRIMARY)) && (cur_disk == c(0)))
		;   BEGIN
		;     num_tracks = num_tracks + SYSTEM_FILE_SECTORS;
		;   END

		cmp	byte [vt_type],0 ; PRIMARY
		jne	short vt_09
		cmp	byte [cur_disk],0
		jne	short vt_09
		add	ax,250 ; SYSTEM_FILE_SECTORS
		mov	[num_tracks],ax
vt_09:
		;/* Handle upward rounding */         
	
		;/* The problem with the IBM code is */
		;/* that if num_tracks is < max_sector[cur_disk] */
		;/* the num_tracks becomes 0 due to the integer */
		;/* division and num_tracks will not be inc'd. */
		;/* This section of code overcomes that. */

		;if (num_tracks%max_sector[cur_disk] != u(0)) 
		;   BEGIN                          
		;     num_tracks = num_tracks + max_sector[cur_disk];
		;   END

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		mov	bl,[cur_disk]
		sub	bh,bh		
		mov	cl,[max_sector+bx]
		sub	ch,ch ; 0
		mov	ax,[num_tracks]
		sub	dx,dx ; 0
		div	cx
		or	dx,dx
		jz	short vt_10
		add	[num_tracks],cx

		xor	dx,dx ; **
vt_10:
		;/* Now convert to tracks */
		;   num_tracks = num_tracks/max_sector[cur_disk];

		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;mov	cl,[max_sector+bx]
		;sub	ch,ch
		;mov	ax,[num_tracks]
		;sub	dx,dx ; **

		mov	ax,[num_tracks]

		div	cx
		mov	[num_tracks],ax

	;/* The number of tracks above does not take into
	;account the wasted track 0 which contains the partition info.
	;If cur_head = 0, then the above calculation would cause the
	;last track in the partition to be not verified */

		;   if ( cur_head == 0 )
		;           num_tracks++;

		cmp	[cur_head],ch ; 0
		jne	short vt_11
		inc	word [num_tracks]
vt_11:
		mov	byte [golden_tracks],0 ; golden_tracks = FALSE;
vt_12:
	;/* this allows resetting the starting cyl of the golden tracks */	

		;for (i = u(0);i < num_tracks; i++)

		mov	word [vt_i],0
		jmp	short vt_14
vt_13:
		inc	word [vt_i]
vt_14:
	;/* this for loop is to write the number of golden tracks */

		mov	ax,[vt_i]
		cmp	[num_tracks],ax
		ja	short vt_15

		jmp	vt_25
vt_15:
	;/* this for loop is to write the number of golden tracks */		

		mov	byte [vt_retry],0
vt_16:
		; /* this do loop is for retries */

		inc	byte [vt_retry]

		;mov	byte [regs_x_ax+1],4 ; verify
		;mov	al,[cur_disk]
		;cbw
		;mov	bx,ax
		;mov	al,[max_sector+bx]
		;mov	[regs_x_ax],al
		;mov	byte [regs_x_cx],1

		mov	cl,1 	  ; /* Specify the start sectors */

		;cmp	word [cur_cyl],255
		;jbe	short vt_17

		mov	dx,[cur_cyl]
		cmp	dx,255
		jbe	short vt_17

		;mov	ax,[cur_cyl]
		;shr	ax,1
		;shr	ax,1
		;and	al,0C1h
		;or	al,1
		;mov	byte [regs_x_cx],al

		shl	dh,6
		or	cl,dh  ; high two bits of cylinder in bits 7-6
vt_17:
		;mov	al,[cur_cyl]
		;mov	[regs_x_cx+1],al
		;mov	al,[cur_disk]
		;add	al,80h
		;mov	[regs_x_dx],al
		;mov	al,[cur_head]
		;mov	[regs_x_dx+1],al
		;mov	ax,regs_x_ax
		;push	ax
		;push	ax
		;mov	ax,13h
		;push	ax
		;call	int86
		;add	sp,6

		mov	ch,dl  ; byte [cur_cyl], low 8 bits of cylinder
		mov	dh,[cur_head] ; /* Specify the head */
		mov	dl,[cur_disk] 
		mov	bl,dl
		add	dl,80h 	      ; /* Specify the disk */	
 
		;regs.h.al = (unsigned char)max_sector[cur_disk];

		;mov	bl,[cur_disk]
		sub	bh,bh
		mov	al,[max_sector+bx]  ; /* Specify number of sectors */

		; regs.h.ah = uc(VERIFY_DISK);
		mov	ah,04h  ; verify disk sectors
		int	13h

		; retry_flg = regs.x.cflag & 1;

		;mov	al,[regs_x_cflag]
		;and	ax,1
		;jz	short vt_18

		jnc	short vt_18

		;while ((retry_flg) && (retry != c(3))); /* retry loop */

		cmp	byte [vt_retry],3
		;jnz	short vt_16
		jb	short vt_16

		jmp	short vt_24
;vt_18:
	;/************************************************************/
	;/* Check to see if cylinder was verified w/o errors.        */
	;/************************************************************/
	
	;if (!retry_flg)
	;   {                 
		;or	ax,ax
		;jnz	short vt_21
vt_18:
	;/*********************************************************/
	;/* Cylinder verified correctly. So write boot sector     */
	;/* and bump cylinder count, then go verify that cylinder.*/
	;/* Do not pass the end of the partition free space.      */
	;/*********************************************************/

		mov	byte [vt_retry],0
	;do
	;	{
vt_19:
		inc	byte [vt_retry]

		;mov	byte ptr [regs_x_ax+1],3  ; WRITE_DISK
		;mov	al,1	; /* Write one sector only */
		;mov	[regs_x_ax],al
		;mov	[regs_x_cx],al ; /* Specify the start sectors */

		;if (cur_cyl > u(255)) 

		mov	cl,1 	  ; start sector	

		;cmp	word [cur_cyl],255
		;jbe	short vt_20

		mov	dx,[cur_cyl]
		cmp	dx,255
		jbe	short vt_20

		;regs.h.cl = regs.h.cl | ((unsigned char)((cur_cyl/256) << 6));

		;mov	ax,[cur_cyl]
		;shr	ax,1
		;shr	ax,1
		;and	al,0C1h
		;or	al,1
		;mov	[regs_x_cx],al

		shl	dh,6
		or	cl,dh  ; high two bits of cylinder in bits 7-6
vt_20:
		;mov	al,[cur_cyl]
		;mov	[regs_x_cx+1],al
		;mov	al,[cur_disk]
		;add	al,80h
		;mov	[regs_x_dx],al	 ; /* Specify the disk */
		;mov	al,[cur_head]
		;mov	[regs_x_dx+1],al ; /* Specify the head */ 
		;mov	ax,[buffer_pointer_off]
		;mov	[regs_x_bx],ax
		;mov	ax,[buffer_pointer_seg]
		;mov	[segregs_es],ax
		;mov	ax,segregs_es
		;push	ax
		;mov	ax,regs_x_ax
		;push	ax
		;push	ax
		;call	DiskIo
		;add	sp,6

		mov	ch,dl  ; byte [cur_cyl], low 8 bits of cylinder
		mov	dh,[cur_head]
		mov	dl,[cur_disk]
		add	dl,80h 
		;push	cs
		;pop	es
		mov	bx,boot_record
		mov	ax,0301h  ; write disk sectors 
				  ; (al = sector count = 1)
		int	13h

		;/* See if we had a good read */

		;retry_flg = regs.x.cflag & 1;  

		;mov	al,[regs_x_cflag]
		;and	ax,1
		;jz	short vt_21

		jnc	short vt_21

		;while ((retry_flg) && (retry != c(3)));  
		
		cmp	byte [vt_retry],3
		jb	short vt_19

		jmp	short vt_24
;vt_21:
		;or	ax,ax
		;jnz	short vt_24
vt_21:
		; if (!retry_flg)

		mov	byte [golden_tracks],1  ; golden_tracks = TRUE;
		
		;mov	al,[cur_disk] 
		;cbw
		;mov	bx,ax
		;shl	bx,1
		sub	bh,bh
		mov	bl,[cur_disk]
		shl	bl,1
		
		;/* Get the next head */
		inc	byte [cur_head]  ; cur_head++;
		mov	al,[cur_head]

		;/* Head no. is pre-incremented and cannot
		;   subtract 1 from max_head[cur_disk] */

		;if (cur_head == (uc(max_head[cur_disk] )))
		;   BEGIN
		; /* Up to the next cylinder */
		;      cur_head = uc(0);
		;      cur_cyl++;

		cmp	[max_head+bx],al
		jne	short vt_22
		mov	byte [cur_head],0
		
		;;mov	al,22
		;mov	al,10
		;;imul	byte [vt_pointer]
		;mul	byte [vt_pointer]
		;mov	bx,ax
		inc	word [cur_cyl]

	;/* Check to see if we've reached the end of the free_space*/

		;if (cur_cyl > free_space[pointer].end)
		;   BEGIN
	; /* It is, so return with the cyl offset equal to the freespace */
		;    return(free_space[pointer].space);
		;   END

		mov	ax,[cur_cyl]
		;cmp	[free_space.end+bx],ax
		cmp	[free_space.end+si],ax ; ***
		jb	short vt_23
vt_22:
		jmp	vt_13
vt_23:
		; return( free_space[pointer].space );
		;mov	ax,[free_space.space+bx]
		mov	ax,[free_space.space+si] ; ***
		jmp	short vt_27
	; else	
vt_24:
	;/* Get out of the for loop, with a false flag */
	
		;golden_tracks = FALSE;
		mov	byte [golden_tracks],0
		
		;;mov	al,22
		;mov	al,10
		;;imul	byte [vt_pointer]
		;mul	byte [vt_pointer]
		;mov	bx,ax

		;/* Bump up to the next cylinder boundary */
		
		;cur_cyl++;
		
		inc	word [cur_cyl]

		;/* To get out of the loop we have to check if 
		;there have been enough golden tracks or not.
		;The setting of the flag as above will not get us 
		;out of the loop. We return with the cyl offset 
		;equal to the freespace to indicate that
		;this freespace cannot be used */

		mov	ax,[cur_cyl]

		;if ( cur_cyl > free_space[pointer].end )
		;     return( free_space[pointer].space );

		;cmp	[free_space.end+bx],ax
		cmp	[free_space.end+si],ax ; ***
		jb	short vt_23

		mov	byte [cur_head],0  ; cur_head = uc(0);   

		;/* Save the new verify start point */

		mov	[verify_cyl],ax
vt_25:
		;while (!golden_tracks)
	
		cmp	byte [golden_tracks],0
		jne	short vt_26

	;/* this allows resetting the starting cyl of the golden tracks */

		jmp	vt_12  ; /*while !golden_tracks */
vt_26:
	;/* All done, return the offset from original cyl to the new one */
	
		; return(verify_cyl - free_space[pointer].start);

		;;mov	al,22
		;mov	al,10
		;;imul	byte [vt_pointer]
		;mul	byte [vt_pointer]
		;mov	bx,ax
		mov	ax,[verify_cyl]
		;sub	ax,[free_space.start+bx]
		sub	ax,[free_space.start+si] ; ***
vt_27:
		;pop	si
		;pop	di
		
		mov	sp,bp
		pop	bp
		;retn
		retn	4

;=============================================================================
;        	TEMPORARY
;=============================================================================
; 10/11/2018

;print_parse_error_msg:
;		;and	al,al
;		;jnz	short ppe
;		;retn
;;ppe:
;		push	ax
;		mov	si,beep_next_line
;		call	print_msg
;		pop	bx
;		dec	bx
;		shl	bx,1
;		add	bx,parse_error_tbl
;
;		mov	si,[bx]
;		call	print_msg
;		mov	si,next_line
;		jmp	print_msg
;
;parse_error_tbl:
;		;dw	_No_Error
;		dw	_Too_Many	; 1
;		dw	_Op_Missing	; 2
;		dw	_Not_In_Sw	; 3
;		dw	_Not_In_Key	; 4
;		dw	_unused_err_no	;(5)
;		dw	_Out_Of_Range	; 6
;		dw	_Not_In_Val	; 7
;		dw	_Not_In_Str	; 8
;		dw	_Syntax		; 9
;		; TEMPORARY!
;		dw	_Invalid

print_msg:
		mov	ah,0Eh
		mov	bx,07h
pmsg_1:
		lodsb
		and	al,al
		jz	short pmsg_2
		int	10h
		jmp	short pmsg_1
pmsg_2:
		retn	

beep_next_line:
		db	07h
next_line:
		db	0Dh,0Ah,0

;		; Note: Same error message order in COMMAND.COM 6.22 (*)
;		;	offset 0A41h - INT 2Fh MULTDOS,MSG_RETRIEVAL ; 11/11/2018
;_Too_Many:	;db	'Too many operands!',0
;		db	'Too many parameters!',0 ; (*)
;_Op_Missing:	;db	'Required operand missing!',0
;		db	'Required parameter missing!',0 ; (*)
;_Not_In_Sw:	;db	'Not in switch list provided!',0
;		db	'Invalid switch!',0 ; (*)		
;_Not_In_Key:	;db	'Not in keyword list provided!',0
;		db	'Invalid keyword!',0 ; (*)
;_unused_err_no: db	' ',0 ; (*)
;_Out_Of_Range:	;db	'Out of range specified!',0
;		;db	'Out of range!',0
;		db	'Parameter value not in allowed range!',0 ; (*)	
;_Not_In_Val:	;db	'Not in value list provided!',0
;		;db	'Invalid size!',0
;		db	'Parameter value not allowed!',0 ; (*)	
;_Not_In_Str:	;db	'Not in string list provided!',0
;		;db	'Invalid string!',0
;		db	'Parameter value not allowed',0 ; (*)
;_Syntax:	;db	'Syntax error!',0
;		db	'Parameter format not correct!',0 ; (*)
;_Invalid:	db	'Invalid command parameter(s)!',0 ; TEMPORARY!

incorrect_dos_version:
		db	0Dh,0Ah
		db	'Incorrect DOS version!'
		db	0Dh,0Ah,0

; ----------------------------------------------------------------------------

; TEMPORARY SUBROUTINES - 10/11/2018 

fdisk_program_msg:
		db	0Dh,0Ah
		;db	'FDISK utility (v2) by Erdogan Tan - 2019'
		; 22/12/2022
		db	'FDISK utility (v2) by Erdogan Tan [2019-2022]'
		db	0Dh,0Ah,0

print_fdisk_program_msg:
		mov	si,fdisk_program_msg
		jmp	print_msg

;=============================================================================
;        	initialized data
;=============================================================================

; 13/11/2018

align 2

$M_EXT_ERR_ADDRS: dd 0	
$M_EXT_FILE:	dd 0
$M_EXT_COMMAND:	dd 0
$M_EXT_TERM:	dd 0FFFFFFFFh
$M_PARSE_COMMAND: dd 0
$M_PARSE_ADDRS:	dd 0
$M_PARSE_TERM:	dd 0FFFFFFFFh
$M_CRIT_ADDRS:	dd 0
$M_CRIT_COMMAND: dd 0
$M_CRIT_TERM:	dd 0FFFFFFFFh
$M_DISK_PROC_ADDR: dd 0FFFFFFFFh
$M_CLASS_A_ADDRS: dd 0
$M_CLASS_B_ADDRS: dd 0
$M_CLS_TERM:	dd 0FFFFFFFFh
$M_DBCS_VEC:	dd 0
$M_HANDLE:	dw 0
$M_SIZE:	db 0
$M_CRLF:	dw 0A0Dh
$M_CLASS:	db 0
$M_RETURN_ADDR:	dw 0
$M_MSG_NUM:	dw 0
$M_DIVISOR:	dw 10
$M_TEMP_BUF:	db '$$$$$$$'
$M_THOU_SEPARA:	times 57 db '$' ; db 39h dup('$')
$M_BUF_TERM:	db '$'

		;db 0
align 2

;	; MSDOS 6.0 (1991) FDISK.SKL file (content):
;	
;	:util FDISK                ;utility name
;	:class A                   ;system messages
;	;
;	:use 1 COMMON1             ;"Incorrect DOS version"
;	:use 2 COMMON2             ;"Insufficient Memory"
;	:use 3 COMMON3             ;"Internal error loading messages"
;	:use 8 EXTEND87            ;"Invalid parameter"
;	:def 9  "Y",0              ;"Y"
;	:def 10 "N",0              ;"N"
;
;	;    Options help messages (all class A) 300-399 RESERVED
;	:def 300 FDISK /?
;	:def 301 FDISK /?
;
;	;
;	:class B
;	:def 4 "Cannot FDISK with network loaded",CR,LF
;	:def 5 "No fixed disks present",CR,LF
;	:def 6 "Error reading fixed disk",CR,LF
;	:def 7 "Error writing fixed disk",CR,LF
;	:def 11 "The Master boot code has NOT been updated.",CR,LF 

	; PC-DOS 7.0 FDISK.COM (unpacked & disassembled Offset: DGROUP:2262h)

CLASS_A_msg_tbl:
		db 0FFh	; Class identifer : UTILITY_MSG_CLASS
		dw 7	; COMMAND.COM version check : 7.0 (PC-DOS 7.0)
		db 9	; Total number of messages in class
		dw 1	; Message number: 1
		dw 24h	; Message offset from previous word. / Addr: 2266h+24h
		dw 2	; Message number: 2
		dw 38h	; Message offset from previous word. / Addr: 226Ah+38h
		dw 3	; $M_NUM
		dw 4Bh	; $M_TXT_PTR
		dw 8
		dw 64h
		dw 9	; Message number: 9
		dw 74h
		dw 10
		dw 73h
		dw 300	; Message number: 300
		dw 72h	; Message offset from previous word. / Addr: 227Eh+72h
		dw 301
		dw 9Eh
		dw 302
		dw 0AEh
		db 17h,'Incorrect DOS version',0Dh,0Ah
		db 16h,'%1 already installed',0Dh,0Ah
		db 1Ch,'%1 bytes available on disk',0Dh,0Ah
		db 13h,'Invalid parameter',0Dh,0Ah
		db 2
_yes:		db 'Y',0
		db 2
_no:		db 'N',0
options_msg:	db 2Fh
		db 'Configures a hard disk for use with PC DOS.',0Dh,0Ah
		db 0Dh,0Ah
_fdisk_st_row:	db 13h
		db 'FDISK [/STATUS]'
		db 0Dh,0Ah
		db 0Dh,	0Ah
stats_desc_row:	db 3Dh
		db '    /STATUS     Displays the status of the fixed disk drive',0Dh,0Ah

		;db 0
align 2

	; PC-DOS 7.0 FDISK.COM (unpacked & disassembled Offset: DGROUP:237Dh)

CLASS_B_msg_tbl:
		db 0FFh	; Class identifer : UTILITY_MSG_CLASS
		dw 7	; COMMAND.COM version check : 7.0 (PC-DOS 7.0)
		db 5	; Total number of messages in class
		dw 4	; $M_NUM
		dw 14h	; $M_TXT_PTR
		dw 5	; Message number: 5
		dw 33h	; Message offset from previous word. / Addr: 2285h+33h
		dw 6
		dw 48h
		dw 7
		dw 5Fh
		dw 11	; Message number: 11
		dw 76h	; Message offset from previous word. / Addr: 2291h+76h
		db 22h
		db 'Cannot FDISK with network loaded',0Dh,0Ah
		db 18h
		db 'No fixed disks present',0Dh,0Ah
		db 1Ah
		db 'Error reading fixed disk',0Dh,0Ah
		db 1Ah
		db 'Error writing fixed disk',0Dh,0Ah
		db 2Ch
		db 'The master boot code has NOT been updated.',0Dh,0Ah

		;db 0
align 2

CLASS_1_msg_tbl:
		db 1	; Class identifier : EXT_ERR_CLASS
		dw 7	; COMMAND.COM version check : 7.0 (PC-DOS 7.0)
		db 1	; Total number of messages in class
		dw 0FFFFh ; $M_NUM = -1
		dw 4	; $M_TXT_PTR
_EXT_ERR_CLASS:	db 17	; Msg length
		db 'Extended Error %1'

		;db 0

CLASS_2_msg_tbl:
		db 2	; Class identifier : PARSE_ERR_CLASS
		dw 7	; COMMAND.COM version check : 7.0 (PC-DOS 7.0)
		db 1	; Total number of messages in class
		dw 0FFFFh ; $M_NUM = -1
		dw 4	; $M_TXT_PTR
_PARSE_ERR_CLASSS: db 14 ; Msg length
		db 'Parse Error %1'

		;db 0

; 24/11/2018
extFAT16:
FAT16:		db 'FAT16   ',0
extFAT12:
FAT12:		db 'FAT12   ',0
extNOVOLUME:
NOVOLUME:	db 0
extUNKNOWN:
UNKNOWN:	db 'UNKNOWN ',0

; 26/11/2018
;extFAT16:	db 'FAT16   ',0 
;extFAT12:	db 'FAT12   ',0
;extNOVOLUME:	db 0
;extUNKNOWN:	db 'UNKNOWN ',0

align 2

master_boot_record:
	db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 00h, 7Ch, 8Bh, 0F4h, 50h, 07h, 50h, 1Fh, 0FBh, 0FCh
	db 0BFh, 00h, 06h, 0B9h, 00h, 01h, 0F2h, 0A5h, 0EAh, 1Dh, 06h, 00h, 00h, 0BEh, 0BEh, 07h
	db 0B3h, 04h, 80h, 3Ch,	80h, 74h, 0Eh, 80h, 3Ch, 00h, 75h, 1Ch,	83h, 0C6h, 10h,	0FEh
	db 0CBh, 75h, 0EFh, 0CDh, 18h, 8Bh, 14h, 8Bh, 4Ch, 02h,	8Bh, 0EEh, 83h,	0C6h, 10h, 0FEh
	db 0CBh, 74h, 1Ah, 80h,	3Ch, 00h, 74h, 0F4h, 0BEh, 8Bh,	06h, 0ACh, 3Ch,	00h, 74h, 0Bh
	db 56h,	0BBh, 07h, 00h,	0B4h, 0Eh, 0CDh, 10h, 5Eh, 0EBh, 0F0h, 0EBh, 0FEh, 0BFh, 05h, 00h
	db 0BBh, 00h, 7Ch, 0B8h, 01h, 02h, 57h,	0CDh, 13h, 5Fh,	73h, 0Ch, 33h, 0C0h, 0CDh, 13h
	db 4Fh,	75h, 0EDh, 0BEh, 0A3h, 06h, 0EBh, 0D3h,	0BEh, 0C2h, 06h, 0BFh, 0FEh, 7Dh, 81h, 3Dh
	db 55h,	0AAh, 75h, 0C7h, 8Bh, 0F5h, 0EAh, 00h, 7Ch, 00h, 00h, 49h, 6Eh,	76h, 61h, 6Ch
	db 69h,	64h, 20h, 70h, 61h, 72h, 74h, 69h, 74h,	69h, 6Fh, 6Eh, 20h, 74h, 61h, 62h
	db 6Ch,	65h, 00h, 45h, 72h, 72h, 6Fh, 72h, 20h,	6Ch, 6Fh, 61h, 64h, 69h, 6Eh, 67h
	db 20h,	6Fh, 70h, 65h, 72h, 61h, 74h, 69h, 6Eh,	67h, 20h, 73h, 79h, 73h, 74h, 65h
	db 6Dh,	00h, 4Dh, 69h, 73h, 73h, 69h, 6Eh, 67h,	20h, 6Fh, 70h, 65h, 72h, 61h, 74h
	db 69h,	6Eh, 67h, 20h, 73h, 79h, 73h, 74h, 65h,	6Dh, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 55h, 0AAh
mbr_hd1:
	db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 00h, 7Ch, 8Bh, 0F4h, 50h, 07h, 50h, 1Fh, 0FBh, 0FCh
	db 0BFh, 00h, 06h, 0B9h, 00h, 01h, 0F2h, 0A5h, 0EAh, 1Dh, 06h, 00h, 00h, 0BEh, 0BEh, 07h
	db 0B3h, 04h, 80h, 3Ch,	80h, 74h, 0Eh, 80h, 3Ch, 00h, 75h, 1Ch,	83h, 0C6h, 10h,	0FEh
	db 0CBh, 75h, 0EFh, 0CDh, 18h, 8Bh, 14h, 8Bh, 4Ch, 02h,	8Bh, 0EEh, 83h,	0C6h, 10h, 0FEh
	db 0CBh, 74h, 1Ah, 80h,	3Ch, 00h, 74h, 0F4h, 0BEh, 8Bh,	06h, 0ACh, 3Ch,	00h, 74h, 0Bh
	db 56h,	0BBh, 07h, 00h,	0B4h, 0Eh, 0CDh, 10h, 5Eh, 0EBh, 0F0h, 0EBh, 0FEh, 0BFh, 05h, 00h
	db 0BBh, 00h, 7Ch, 0B8h, 01h, 02h, 57h,	0CDh, 13h, 5Fh,	73h, 0Ch, 33h, 0C0h, 0CDh, 13h
	db 4Fh,	75h, 0EDh, 0BEh, 0A3h, 06h, 0EBh, 0D3h,	0BEh, 0C2h, 06h, 0BFh, 0FEh, 7Dh, 81h, 3Dh
	db 55h,	0AAh, 75h, 0C7h, 8Bh, 0F5h, 0EAh, 00h, 7Ch, 00h, 00h, 49h, 6Eh,	76h, 61h, 6Ch
	db 69h,	64h, 20h, 70h, 61h, 72h, 74h, 69h, 74h,	69h, 6Fh, 6Eh, 20h, 74h, 61h, 62h
	db 6Ch,	65h, 00h, 45h, 72h, 72h, 6Fh, 72h, 20h,	6Ch, 6Fh, 61h, 64h, 69h, 6Eh, 67h
	db 20h,	6Fh, 70h, 65h, 72h, 61h, 74h, 69h, 6Eh,	67h, 20h, 73h, 79h, 73h, 74h, 65h
	db 6Dh,	00h, 4Dh, 69h, 73h, 73h, 69h, 6Eh, 67h,	20h, 6Fh, 70h, 65h, 72h, 61h, 74h
	db 69h,	6Eh, 67h, 20h, 73h, 79h, 73h, 74h, 65h,	6Dh, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 55h, 0AAh
mbr_hd2:
	db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 00h, 7Ch, 8Bh, 0F4h, 50h, 07h, 50h, 1Fh, 0FBh, 0FCh
	db 0BFh, 00h, 06h, 0B9h, 00h, 01h, 0F2h, 0A5h, 0EAh, 1Dh, 06h, 00h, 00h, 0BEh, 0BEh, 07h
	db 0B3h, 04h, 80h, 3Ch,	80h, 74h, 0Eh, 80h, 3Ch, 00h, 75h, 1Ch,	83h, 0C6h, 10h,	0FEh
	db 0CBh, 75h, 0EFh, 0CDh, 18h, 8Bh, 14h, 8Bh, 4Ch, 02h,	8Bh, 0EEh, 83h,	0C6h, 10h, 0FEh
	db 0CBh, 74h, 1Ah, 80h,	3Ch, 00h, 74h, 0F4h, 0BEh, 8Bh,	06h, 0ACh, 3Ch,	00h, 74h, 0Bh
	db 56h,	0BBh, 07h, 00h,	0B4h, 0Eh, 0CDh, 10h, 5Eh, 0EBh, 0F0h, 0EBh, 0FEh, 0BFh, 05h, 00h
	db 0BBh, 00h, 7Ch, 0B8h, 01h, 02h, 57h,	0CDh, 13h, 5Fh,	73h, 0Ch, 33h, 0C0h, 0CDh, 13h
	db 4Fh,	75h, 0EDh, 0BEh, 0A3h, 06h, 0EBh, 0D3h,	0BEh, 0C2h, 06h, 0BFh, 0FEh, 7Dh, 81h, 3Dh
	db 55h,	0AAh, 75h, 0C7h, 8Bh, 0F5h, 0EAh, 00h, 7Ch, 00h, 00h, 49h, 6Eh,	76h, 61h, 6Ch
	db 69h,	64h, 20h, 70h, 61h, 72h, 74h, 69h, 74h,	69h, 6Fh, 6Eh, 20h, 74h, 61h, 62h
	db 6Ch,	65h, 00h, 45h, 72h, 72h, 6Fh, 72h, 20h,	6Ch, 6Fh, 61h, 64h, 69h, 6Eh, 67h
	db 20h,	6Fh, 70h, 65h, 72h, 61h, 74h, 69h, 6Eh,	67h, 20h, 73h, 79h, 73h, 74h, 65h
	db 6Dh,	00h, 4Dh, 69h, 73h, 73h, 69h, 6Eh, 67h,	20h, 6Fh, 70h, 65h, 72h, 61h, 74h
	db 69h,	6Eh, 67h, 20h, 73h, 79h, 73h, 74h, 65h,	6Dh, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 55h, 0AAh
mbr_hd3:
	db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 00h, 7Ch, 8Bh, 0F4h, 50h, 07h, 50h, 1Fh, 0FBh, 0FCh
	db 0BFh, 00h, 06h, 0B9h, 00h, 01h, 0F2h, 0A5h, 0EAh, 1Dh, 06h, 00h, 00h, 0BEh, 0BEh, 07h
	db 0B3h, 04h, 80h, 3Ch,	80h, 74h, 0Eh, 80h, 3Ch, 00h, 75h, 1Ch,	83h, 0C6h, 10h,	0FEh
	db 0CBh, 75h, 0EFh, 0CDh, 18h, 8Bh, 14h, 8Bh, 4Ch, 02h,	8Bh, 0EEh, 83h,	0C6h, 10h, 0FEh
	db 0CBh, 74h, 1Ah, 80h,	3Ch, 00h, 74h, 0F4h, 0BEh, 8Bh,	06h, 0ACh, 3Ch,	00h, 74h, 0Bh
	db 56h,	0BBh, 07h, 00h,	0B4h, 0Eh, 0CDh, 10h, 5Eh, 0EBh, 0F0h, 0EBh, 0FEh, 0BFh, 05h, 00h
	db 0BBh, 00h, 7Ch, 0B8h, 01h, 02h, 57h,	0CDh, 13h, 5Fh,	73h, 0Ch, 33h, 0C0h, 0CDh, 13h
	db 4Fh,	75h, 0EDh, 0BEh, 0A3h, 06h, 0EBh, 0D3h,	0BEh, 0C2h, 06h, 0BFh, 0FEh, 7Dh, 81h, 3Dh
	db 55h,	0AAh, 75h, 0C7h, 8Bh, 0F5h, 0EAh, 00h, 7Ch, 00h, 00h, 49h, 6Eh,	76h, 61h, 6Ch
	db 69h,	64h, 20h, 70h, 61h, 72h, 74h, 69h, 74h,	69h, 6Fh, 6Eh, 20h, 74h, 61h, 62h
	db 6Ch,	65h, 00h, 45h, 72h, 72h, 6Fh, 72h, 20h,	6Ch, 6Fh, 61h, 64h, 69h, 6Eh, 67h
	db 20h,	6Fh, 70h, 65h, 72h, 61h, 74h, 69h, 6Eh,	67h, 20h, 73h, 79h, 73h, 74h, 65h
	db 6Dh,	00h, 4Dh, 69h, 73h, 73h, 69h, 6Eh, 67h,	20h, 6Fh, 70h, 65h, 72h, 61h, 74h
	db 69h,	6Eh, 67h, 20h, 73h, 79h, 73h, 74h, 65h,	6Dh, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 55h, 0AAh
mbr_5:
	db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 00h, 7Ch, 8Bh, 0F4h, 50h, 07h, 50h, 1Fh, 0FBh, 0FCh
	db 0BFh, 00h, 06h, 0B9h, 00h, 01h, 0F2h, 0A5h, 0EAh, 1Dh, 06h, 00h, 00h, 0BEh, 0BEh, 07h
	db 0B3h, 04h, 80h, 3Ch,	80h, 74h, 0Eh, 80h, 3Ch, 00h, 75h, 1Ch,	83h, 0C6h, 10h,	0FEh
	db 0CBh, 75h, 0EFh, 0CDh, 18h, 8Bh, 14h, 8Bh, 4Ch, 02h,	8Bh, 0EEh, 83h,	0C6h, 10h, 0FEh
	db 0CBh, 74h, 1Ah, 80h,	3Ch, 00h, 74h, 0F4h, 0BEh, 8Bh,	06h, 0ACh, 3Ch,	00h, 74h, 0Bh
	db 56h,	0BBh, 07h, 00h,	0B4h, 0Eh, 0CDh, 10h, 5Eh, 0EBh, 0F0h, 0EBh, 0FEh, 0BFh, 05h, 00h
	db 0BBh, 00h, 7Ch, 0B8h, 01h, 02h, 57h,	0CDh, 13h, 5Fh,	73h, 0Ch, 33h, 0C0h, 0CDh, 13h
	db 4Fh,	75h, 0EDh, 0BEh, 0A3h, 06h, 0EBh, 0D3h,	0BEh, 0C2h, 06h, 0BFh, 0FEh, 7Dh, 81h, 3Dh
	db 55h,	0AAh, 75h, 0C7h, 8Bh, 0F5h, 0EAh, 00h, 7Ch, 00h, 00h, 49h, 6Eh,	76h, 61h, 6Ch
	db 69h,	64h, 20h, 70h, 61h, 72h, 74h, 69h, 74h,	69h, 6Fh, 6Eh, 20h, 74h, 61h, 62h
	db 6Ch,	65h, 00h, 45h, 72h, 72h, 6Fh, 72h, 20h,	6Ch, 6Fh, 61h, 64h, 69h, 6Eh, 67h
	db 20h,	6Fh, 70h, 65h, 72h, 61h, 74h, 69h, 6Eh,	67h, 20h, 73h, 79h, 73h, 74h, 65h
	db 6Dh,	00h, 4Dh, 69h, 73h, 73h, 69h, 6Eh, 67h,	20h, 6Fh, 70h, 65h, 72h, 61h, 74h
	db 69h,	6Eh, 67h, 20h, 73h, 79h, 73h, 74h, 65h,	6Dh, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 55h, 0AAh
mbr_6:
	db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 00h, 7Ch, 8Bh, 0F4h, 50h, 07h, 50h, 1Fh, 0FBh, 0FCh
	db 0BFh, 00h, 06h, 0B9h, 00h, 01h, 0F2h, 0A5h, 0EAh, 1Dh, 06h, 00h, 00h, 0BEh, 0BEh, 07h
	db 0B3h, 04h, 80h, 3Ch,	80h, 74h, 0Eh, 80h, 3Ch, 00h, 75h, 1Ch,	83h, 0C6h, 10h,	0FEh
	db 0CBh, 75h, 0EFh, 0CDh, 18h, 8Bh, 14h, 8Bh, 4Ch, 02h,	8Bh, 0EEh, 83h,	0C6h, 10h, 0FEh
	db 0CBh, 74h, 1Ah, 80h,	3Ch, 00h, 74h, 0F4h, 0BEh, 8Bh,	06h, 0ACh, 3Ch,	00h, 74h, 0Bh
	db 56h,	0BBh, 07h, 00h,	0B4h, 0Eh, 0CDh, 10h, 5Eh, 0EBh, 0F0h, 0EBh, 0FEh, 0BFh, 05h, 00h
	db 0BBh, 00h, 7Ch, 0B8h, 01h, 02h, 57h,	0CDh, 13h, 5Fh,	73h, 0Ch, 33h, 0C0h, 0CDh, 13h
	db 4Fh,	75h, 0EDh, 0BEh, 0A3h, 06h, 0EBh, 0D3h,	0BEh, 0C2h, 06h, 0BFh, 0FEh, 7Dh, 81h, 3Dh
	db 55h,	0AAh, 75h, 0C7h, 8Bh, 0F5h, 0EAh, 00h, 7Ch, 00h, 00h, 49h, 6Eh,	76h, 61h, 6Ch
	db 69h,	64h, 20h, 70h, 61h, 72h, 74h, 69h, 74h,	69h, 6Fh, 6Eh, 20h, 74h, 61h, 62h
	db 6Ch,	65h, 00h, 45h, 72h, 72h, 6Fh, 72h, 20h,	6Ch, 6Fh, 61h, 64h, 69h, 6Eh, 67h
	db 20h,	6Fh, 70h, 65h, 72h, 61h, 74h, 69h, 6Eh,	67h, 20h, 73h, 79h, 73h, 74h, 65h
	db 6Dh,	00h, 4Dh, 69h, 73h, 73h, 69h, 6Eh, 67h,	20h, 6Fh, 70h, 65h, 72h, 61h, 74h
	db 69h,	6Eh, 67h, 20h, 73h, 79h, 73h, 74h, 65h,	6Dh, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 55h, 0AAh
mbr_7:
	db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 00h, 7Ch, 8Bh, 0F4h, 50h, 07h, 50h, 1Fh, 0FBh, 0FCh
	db 0BFh, 00h, 06h, 0B9h, 00h, 01h, 0F2h, 0A5h, 0EAh, 1Dh, 06h, 00h, 00h, 0BEh, 0BEh, 07h
	db 0B3h, 04h, 80h, 3Ch,	80h, 74h, 0Eh, 80h, 3Ch, 00h, 75h, 1Ch,	83h, 0C6h, 10h,	0FEh
	db 0CBh, 75h, 0EFh, 0CDh, 18h, 8Bh, 14h, 8Bh, 4Ch, 02h,	8Bh, 0EEh, 83h,	0C6h, 10h, 0FEh
	db 0CBh, 74h, 1Ah, 80h,	3Ch, 00h, 74h, 0F4h, 0BEh, 8Bh,	06h, 0ACh, 3Ch,	00h, 74h, 0Bh
	db 56h,	0BBh, 07h, 00h,	0B4h, 0Eh, 0CDh, 10h, 5Eh, 0EBh, 0F0h, 0EBh, 0FEh, 0BFh, 05h, 00h
	db 0BBh, 00h, 7Ch, 0B8h, 01h, 02h, 57h,	0CDh, 13h, 5Fh,	73h, 0Ch, 33h, 0C0h, 0CDh, 13h
	db 4Fh,	75h, 0EDh, 0BEh, 0A3h, 06h, 0EBh, 0D3h,	0BEh, 0C2h, 06h, 0BFh, 0FEh, 7Dh, 81h, 3Dh
	db 55h,	0AAh, 75h, 0C7h, 8Bh, 0F5h, 0EAh, 00h, 7Ch, 00h, 00h, 49h, 6Eh,	76h, 61h, 6Ch
	db 69h,	64h, 20h, 70h, 61h, 72h, 74h, 69h, 74h,	69h, 6Fh, 6Eh, 20h, 74h, 61h, 62h
	db 6Ch,	65h, 00h, 45h, 72h, 72h, 6Fh, 72h, 20h,	6Ch, 6Fh, 61h, 64h, 69h, 6Eh, 67h
	db 20h,	6Fh, 70h, 65h, 72h, 61h, 74h, 69h, 6Eh,	67h, 20h, 73h, 79h, 73h, 74h, 65h
	db 6Dh,	00h, 4Dh, 69h, 73h, 73h, 69h, 6Eh, 67h,	20h, 6Fh, 70h, 65h, 72h, 61h, 74h
	db 69h,	6Eh, 67h, 20h, 73h, 79h, 73h, 74h, 65h,	6Dh, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 55h, 0AAh

mbr_8:
	db 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 00h, 7Ch, 8Bh, 0F4h, 50h, 07h, 50h, 1Fh, 0FBh, 0FCh
	db 0BFh, 00h, 06h, 0B9h, 00h, 01h, 0F2h, 0A5h, 0EAh, 1Dh, 06h, 00h, 00h, 0BEh, 0BEh, 07h
	db 0B3h, 04h, 80h, 3Ch,	80h, 74h, 0Eh, 80h, 3Ch, 00h, 75h, 1Ch,	83h, 0C6h, 10h,	0FEh
	db 0CBh, 75h, 0EFh, 0CDh, 18h, 8Bh, 14h, 8Bh, 4Ch, 02h,	8Bh, 0EEh, 83h,	0C6h, 10h, 0FEh
	db 0CBh, 74h, 1Ah, 80h,	3Ch, 00h, 74h, 0F4h, 0BEh, 8Bh,	06h, 0ACh, 3Ch,	00h, 74h, 0Bh
	db 56h,	0BBh, 07h, 00h,	0B4h, 0Eh, 0CDh, 10h, 5Eh, 0EBh, 0F0h, 0EBh, 0FEh, 0BFh, 05h, 00h
	db 0BBh, 00h, 7Ch, 0B8h, 01h, 02h, 57h,	0CDh, 13h, 5Fh,	73h, 0Ch, 33h, 0C0h, 0CDh, 13h
	db 4Fh,	75h, 0EDh, 0BEh, 0A3h, 06h, 0EBh, 0D3h,	0BEh, 0C2h, 06h, 0BFh, 0FEh, 7Dh, 81h, 3Dh
	db 55h,	0AAh, 75h, 0C7h, 8Bh, 0F5h, 0EAh, 00h, 7Ch, 00h, 00h, 49h, 6Eh,	76h, 61h, 6Ch
	db 69h,	64h, 20h, 70h, 61h, 72h, 74h, 69h, 74h,	69h, 6Fh, 6Eh, 20h, 74h, 61h, 62h
	db 6Ch,	65h, 00h, 45h, 72h, 72h, 6Fh, 72h, 20h,	6Ch, 6Fh, 61h, 64h, 69h, 6Eh, 67h
	db 20h,	6Fh, 70h, 65h, 72h, 61h, 74h, 69h, 6Eh,	67h, 20h, 73h, 79h, 73h, 74h, 65h
	db 6Dh,	00h, 4Dh, 69h, 73h, 73h, 69h, 6Eh, 67h,	20h, 6Fh, 70h, 65h, 72h, 61h, 74h
	db 69h,	6Eh, 67h, 20h, 73h, 79h, 73h, 74h, 65h,	6Dh, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 55h, 0AAh

numinmsg_format:
		;db '%4.1d',0
glni_num_format:      ; 17/01/2019		
idc_tot_mb_format:
idc_def_entry_format: ; 14/01/2019
ld_p_size_format:
nd_p_size_format:
disk_size_format:
v_psize_format:	; 23/01/2019
v_mbytes_format:
ecp_size_format: ; 25/01/2019
ecp_mb_format:
p_size_format:	db '%4.1d',0
v_mb_percent_format: ; 23/01/2019
ecp_mb_pcent_format: ; 25/01/2019
idc_mb_pcent_format:
		db '%4.1d%3.1d%%',0
v_percent_format:
ecp_pcent_format:
percent_format:	db '%3.1d%%',0
;v_percent_format:db '%3.1d%%',0
invstrchars:	db '."/\[]:|<>+=;,',0
		db 0
twospace:	db '  ',0
twochars:	db '%c%c',0
ptbl_row_format:
		db '%-2.2s%c%c%-7.7s%-11.11s%4.1d%-8.8s%3.1d%%',0
align 2
eptbl_row_format:  db '%c%c%-11.11s%4.1d%-8.8s%3.1d%%',0
cd_pt_row_format:  db '%1.0d%c%c%4.1d%4.1d%3.1d%%',0
drv_mb_row_format: db '%c%c%c%4.1d%8c',0
cdrv_mb_format:	   db '%c%c%c%4.1d%8c',0
cdrive_format:	   db '%1.0d%1.0d',0

NO_FORMAT:	db 'UNKNOWN ',0
NO_VOLUME:	db 0
_NOFORMAT:	db 'UNKNOWN ',0
_NOVOLUME:	db 0
PRI:		db '/PRI',0
EXT:		db '/EXT',0
LOG:		db '/LOG',0
QUIET:		db '/Q',0
STATUS:		db '/STATUS',0
OPTIONS:	db '/?',0
MBR:		db '/MBR',0
FILE_NAME:	db ':\????????.???',0

align 2

pinsert:	dw insert
NOVAL:		dd 0

_$P_ordinal:	dw 0
_$P_RC:		dw 0
_$P_SI_Save:	dw 0
_$P_DX:		dw 0
_$P_Terminator:	db 0
_$P_DBCSEV_OFF:	dw 0
_$P_DBCSEV_SEG:	dw 0
_$P_Flags:
_$P_Flags1:	db 0
_$P_Flags2:	db 0
_$P_SaveSI_Cmpx: dw 0
_$P_KEYorSW_Ptr: dw 0
_$P_Save_EOB:	dw 0
_$P_Found_SYNONYM: dw 0
_$P_STRING_BUF:	times 128 db 0		; Pick a operand from command line
_$P_Got_Time:	db 0
_$P_Country_Info: dw _$P_NeedToBeRead ; 0FFFFh
		;times 32 db 0
		times _$P_CDI.size - 2 db 0
_$P_1st_Val:	dw 0
_$P_2nd_Val:	dw 0
_$P_3rd_Val:	dw 0
_$P_4th_Val:	dw 0
_$P_Char_CAP_Ptr: db 0FFh
		dw 0
		dw 0
_$P_err_flag:	db 0

; 15/12/2018

;/************************************************************************/
;/*  FDISK MESSAGES                                                      */
;/*                                                                      */
;/* Portions of the screen that are handled in the msg are indicated on  */
;/* the listing of the screen with the message name given. If the text   */
;/* message is defined in another screen, then the name is followed by   */
;/* a "#" character                                                      */
;/*                                                                      */
;/* NOTE TO TRANSLATORS                                                  */
;/* The characters inside the <> and the  are control characters and   */
;/* should not be translated. The Control characters are defined as      */
;/* follows:                                                             */
;/*                                                                      */
;/* <H> - Highlight the following text                                   */
;/* <R> - Regular text                                                   */
;/* <U> - Underline the following text                                   */
;/* <B> - Blink the following text                                       */
;/* <O> - Turn off Blink                                                 */
;/* <Y> - Print YES character, as set by define                          */
;/* <N> - Print NO character, as set by define                           */
;/* <W> - Sound the beep                                                 */
;/* <S> - Save cursor position for later use                             */
;/* <G> - Cursor position left justified and regular proceed to right    */
;/* <C> - Clear the screen out from control char to end of line          */
;/* <I> - Insert character from Insert[] string. This string must be set */
;/*       up prior to displaying the message. The first <I> will insert  */
;/*       Insert[0], the second Insert[1], etc....This will move the     */
;/*       cursor one postition. The Insert%% string will be initialized  */
;/*                                                                      */
;/*  Multiple control characters can be between the <>.                  */
;/*                                                                      */
;/*  The  indicates Row and column for the text and has the format of  */
;/*  rrcc where the numbers are decimal and zero based .first row/col  */
;/*  is 00. The numbers are in decimal, and must be 2 characters, which  */
;/*  means rows/cols 0-9 should be listed as 00-09. For example, the 5th */
;/*  row, 3rd column on the screen would be listed as 0402.            */
;/*                                                                      */
;/*  The column number is always the column desired. The row number is   */
;/*  an offset from the previous row. For example, if the text just      */
;/*  printed is on row 6, and the next text should be printed 2 rows     */
;/*  down in column 0, then the control strin would be 0201. The first */
;/*  row specified in the message is assumed to be based off of row 0,   */
;/*  it would actually specify the actual row for the start of the msg   */
;/*  to be printed.                                                      */
;/*                                                                      */
;/************************************************************************/

; 01/12/2018
; FORMATTED MENU TEXT

menu_1:		db 6,'0004',6
		db '<R>                           PC DOS Version 7.0 '
		db 6,'0104',6
		db '<R>                         Fixed Disk Setup Program '
		db 6,'0104',6
		db '<R>                Copyright (c) IBM Corporation 1983 - 1994',0
menu_2:		db 6,'0404',6
		db '<H>                             FDISK Options '
		db 6,'0604',6
		db '<H>1. <R>Create DOS partition or Logical DOS Drive '
		db 6,'0104',6
		db '<H>2. <R>Set active partition '
		db 6,'0104',6
		db '<H>3. <R>Delete partition or Logical DOS Drive '
		db 6,'0104',6
		db '<H>4. <R>Display partition information '
		db 6,'1104',6
		db '<R>Press <H>Esc<R> to exit FDISK',0
menu_3:		db 6,'0804',6
		db '<R>Choose one of the following:',0
menu_4:		db 6,'1404',6
		db '<H>5. <R>Change current fixed disk drive',0
menu_5:		db 6,'0604',6
		db '<R>Current fixed disk drive: <H><I>',0
menu_6:		db 6,'2004',6
		db '<H>WARNING! <R>No partitions are set active - disk 1 is not startable unless '
		db 6,'0104',6
		db '<R>a partition is set active',0
menu_7:		db 6,'1704',6
		db '<R>Enter choice: <H>[<S> ]',0
menu_8:		db 6,'0404',6
		db '<H>                Create DOS Partition or Logical DOS Drive',0
menu_9:		db 6,'1004',6
		db '<H>1. <R>Create Primary DOS Partition '
		db 6,'0104',6
		db '<H>2. <R>Create Extended DOS Partition',0
menu_10:	db 6,'1204',6
		db '<H>3. <R>Create Logical DOS Drive(s) in the Extended DOS Partition',0
menu_11:	db 6,'2404',6
		db '<R>Press <H>Esc<R> to return to FDISK Options',0
menu_12:	db 6,'0404',6
		db '<H>                      Create Primary DOS Partition',0
menu_13:	db 6,'0804',6
		db '<R>Do you wish to use the maximum available size for a Primary DOS Partition '
		db 6,'0104',6
		db '<R>and make the partition active (<Y>/<N>).....................? <H>[<S> ]',0
menu_45:	db 6,'0804',6
		db '<R>Do you wish to use the maximum available size for a Primary DOS Partition '
		db 6,'0104',6
		db '<R>(<Y>/<N>)...................................................? '
		db '<H>[<S> ]',0
menu_14:	db 6,'0804',6
		db '<R>Partition  Status   Type    Volume Label  Mbytes   System   Usage '
		db 6,'0104',6
		db '<R> <II> <HI>         <RI>    <IIIIIII>   <IIIIIIIIIII>   <IIII> '
		db '  <IIIIIIII>   <IIII> '
		db 6,'0104',6
		db '<R> <II> <HI>         <RI>    <IIIIIII>   <IIIIIIIIIII>   <IIII> '
		db '  <IIIIIIII>   <IIII> '
		db 6,'0104',6
		db '<R> <II> <HI>         <RI>    <IIIIIII>   <IIIIIIIIIII>   <IIII> '
		db '  <IIIIIIII>   <IIII> '
		db 6,'0104',6
		db '<R> <II> <HI>         <RI>    <IIIIIII>   <IIIIIIIIIII>   <IIII> '
		db '  <IIIIIIII>   <IIII>'
		db 0
menu_15:	db 6,'1404',6
		db '<R>Total disk space is <HIIIIR> Mbytes (1 Mbyte = 1048576 bytes)',0
menu_16:	db 6,'1504',6
		db '<RC>Maximum space available for partition is <HIIIIR> Mbytes (<HIIIIR>)',0
menu_39:	db 6,'1804',6
		db '<RC>Enter partition size in Mbytes or percent of disk space (%) to '
		db 6,'0104',6
		db '<RC>create a Primary DOS Partition...............................'
		db '..: <H>[<IIISI>]',0
menu_17:	db 6,'0404',6
		db '<H>                      Create Extended DOS Partition',0
menu_42:	db 6,'1804',6
		db '<RC>Enter partition size in Mbytes or percent of disk space (%) to '
		db 6,'0104',6
		db '<RC>create an Extended DOS Partition..............................: <H>[<IIISI>]',0
menu_46:	db 6,'2404',6
		db '<R>Press <H>Esc<R> to continue<S>',0
menu_18:	db 6,'0104',6
		db '<HC>       Create Logical DOS Drive(s) in the Extended DOS Partition',0
menu_19:	db 6,'0300',6
		db '<R>Drv Volume Label  Mbytes  System  Usage'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>',0
menu_43:	db 6,'1000',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0100',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>',0
menu_20:	db 6,'0341',6
		db '<R>Drv Volume Label  Mbytes  System  Usage'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>',0
menu_44:	db 6,'1041',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>'
		db 6,'0141',6
		db '<H><II>  <RIIIIIIIIIII>    <IIII>  <IIIIIIII>  <IIII>',0
menu_21:	db 6,'1704',6
		db '<RC>Total Extended DOS Partition size is <HIIIIR> Mbytes (1 MByte'
		db ' = 1048576 bytes)',0
menu_22:	db 6,'1804',6
		db '<RC>Maximum space available for logical drive is <HIIIIR> Mbytes '
		db '<H>(<IIII>)',0
menu_40:	db 6,'2004',6
		db '<RC>Enter logical drive size in Mbytes or percent of disk space (%)'
		db '...<H>[<IIISI>]',0
menu_23:	db 6,'0404',6
		db '<H>                          Set Active Partition',0
menu_24:	db 6,'1604',6
		db '<R>Enter the number of the partition you want to make active.....'
		db '......: <H>[<S> ]',0
menu_25:	db 6,'0404',6
		db '<H>                Delete DOS Partition or Logical DOS Drive',0
menu_26:	db 6,'1004',6
		db '<HC>1.  <R>Delete Primary DOS Partition '
		db 6,'0104',6
		db '<HC>2.  <R>Delete Extended DOS Partition',0
menu_27:	db 6,'1204',6
		db '<HC>3.  <R>Delete Logical DOS Drive(s) in the Extended DOS Partition',0
menu_57:	db 6,'1304',6
		db '<HC>4.  <R>Delete Non-DOS Partition',0
menu_28:	db 6,'0404',6
		db '<H>                      Delete Primary DOS Partition',0
menu_55:	db 6,'1904',6
		db '<HBC>WARNING! <OR>Data in the deleted Primary DOS Partition will be lost. '
		db 6,'0104',6
		db '<R>What primary partition do you want to delete..? <H>[<S> ]<R>',0
menu_56:	db 6,'2204',6
		db '<RC>Do you wish to continue (<Y>/<N>).................? <H>[<S> ]',0
menu_30:	db 6,'0404',6
		db '<H>                      Delete Extended DOS Partition',0
menu_31:	db 6,'1604',6
		db '<HBC>WARNING! <OR>Data in the deleted Extended DOS Partition will be lost. '
		db 6,'0104',6
		db '<RC>Do you wish to continue (<Y>/<N>).................? <H>[<S> ]',0
menu_32:	db 6,'0104',6
		db '<H>        Delete Logical DOS Drive(s) in the Extended DOS Partition',0
menu_33:	db 6,'1904',6
		db '<HBC>WARNING! <OR>Data in a deleted Logical DOS Drive will be lost. '
		db 6,'0104',6
		db '<RC>What drive do you want to delete...............................? <H>[<S> ]',0
menu_34:	db 6,'2204',6
		db '<R>Are you sure (<Y>/<N>)..............................? <H>[<S> ]',0
menu_41:	db 6,'2104',6
		db '<R>Enter Volume Label..............................? <H>[<S>           ]',0
menu_58:	db 6,'0404',6
		db '<H>                        Delete Non-DOS Partition',0
menu_59:	db 6,'1604',6
		db '<HBC>WARNING! <OR>Data in the deleted Non-DOS Partition will be lost. '
		db 6,'0104',6
		db '<RC>What Non-DOS partition do you want to delete..? <H>[<S> ]<R>',0
menu_35:	db 6,'0404',6
		db '<H>                      Display Partition Information',0
menu_36:	db 6,'1704',6
		db '<RC>The Extended DOS Partition contains Logical DOS Drives. '
		db 6,'0104',6
		db '<RC>Do you want to display the logical drive information (<Y>/<N>)'
		db '......?<H>[<S> ]',0
menu_37:	db 6,'0104',6
		db '<H>                  Display Logical DOS Drive Information',0
menu_47:	db 6,'0004',6
		db '<H>                     Change Current Fixed Disk Drive',0
menu_48:	db 6,'0200',6
		db '<R>  Disk   Drv   Mbytes   Free   Usage'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>',0
menu_49:	db 6,'1104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0104',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>',0
menu_50:	db 6,'0241',6
		db '<R>  Disk   Drv   Mbytes   Free   Usage'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>',0
menu_51:	db 6,'1145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>'
		db 6,'0145',6
		db '<HI>     <RII>    <IIII>    <IIII>    <IIII>',0
menu_52:	db 6,'2004',6
		db '<R>(1 MByte = 1048576 bytes)',0
menu_53:	db 6,'2104',6
		db '<R>Enter Fixed Disk Drive Number (1-<I>).......................<H>[<SI>]',0
menu_54:	db 6,'0104',6
		db '<H>                         Fixed Disk Drive Status',0
menu_38:	db 6,'1304',6
		db '<H>System will now restart '
		db 6,'0204',6
		db '<R>Insert DOS system diskette in drive A: '
		db 6,'0104',6
		db '<R>Press any key when ready . . .<S>',0
menu_60:	db 6
		db '1304'
		db 6
		db '<H>System will now restart '
		db 6
		db '0304'
		db 6
		db '<R>Press any key when ready . . .<S>',0

; STATUS MESSAGES
; 01/12/2018
status_1:	db 6,'2104',6
		db '<CH>Primary DOS Partition deleted '
		db 6,'0100',6
		db '<CW>',0
status_2:	db 6,'2104',6
		db '<CH>Extended DOS Partition deleted '
		db 6,'0100',6
		db '<CW>',0
status_3:	db 6,'0004',6
		db '<H>Drive deleted',0
status_4:	db 6,'2104',6
		db '<CH>Partition <I> made active '
		db 6,'0100',6
		db '<CW>',0
status_5:	db 6,'2104',6
		db '<CH>Primary DOS Partition created '
		db 6,'0100',6
		db '<CW>',0
status_6:	db 6,'2104',6
		db '<CH>Extended DOS Partition created '
		db 6,'0100',6
		db '<CW>',0
status_7:	db 6,'2204',6
		db '<CH>Logical DOS Drive created, drive letters changed or added<W>',0
status_8:	db 6,'2104',6
		db '<CH>No partitions defined '
		db 6,'0100',6
		db '<C>',0
status_9:	db 6,'1004',6
		db '<CH>No logical drives defined '
		db 6,'0100',6
		db '<C>',0
status_10:	db 6,'1804',6
		db '<CH>Drive letters have been changed or deleted<W>',0
status_11:	db 6,'0004',6
		db '<H>Drive redirected',0
status_12:	db 6,'2104',6
		db '<CH>Primary DOS Partition created, drive letters changed or added '
		db 6,'0100',6
		db '<CW>',0
status_13:	db 6,'2104',6
		db '<CH>Non-DOS Partition deleted '
		db 6,'0100',6
		db '<CW>',0

; ERROR MESSAGES
; 17/11/2018

;-- FDISK.MSG (MSDOS 6.0, FDISK) --
;/*                                                                      */
;/* The following character strings are required to display the          */
;/* error messages. These have form: error_xx                            */
;/*                                                                      */
;/* Note: In order to overlay any previous message on the screen, these  */
;/*       messages are all 2 lines long. The second line may only be     */
;/*       a blank line. If 2 lines are needed for translation, use the   */
;/*       second line for text.  Exceptions are those msgs on line 0.    */
;/*       and those messages that start on line 23                       */
;/*                                                                      */

error_1:	
		db 6,'0004',6
		db '<CH>No fixed disks present. '
		db 6,'0100',6
		db '<CW>',0
error_2:	
		db 6,'2204',6
		db '<CH>Error reading fixed disk. '
		db 6,'0100',6
		db '<CW>',0
error_3:		
		db 6,'2204',6
		db '<CH>Error writing fixed disk. '
		db 6,'0100',6
		db '<CW>',0
error_4:
		db 6,'0004',6
		db '<CHW>Incorrect DOS version.',0
error_5:
		db 6,'0004',6
		db '<CHW>Cannot FDISK with network loaded.',0
error_6:
		db 6,'2204',6
		db '<CH>No Primary DOS Partition to delete. '
		db 6,'0100',6
		db '<CW>',0
error_7:
		db 6,'2204',6
		db '<CH>No Extended DOS Partition to delete. '
		db 6,'0100',6
		db '<CW>',0
error_8:
		db 6,'2204',6
		db '<CH>Primary DOS Partition already exists. '
		db 6,'0100',6
		db '<CW>',0
error_9:
		db 6,'2204',6
		db '<CH>Extended DOS Partition already exists. '
		db 6,'0100',6
		db '<CW>',0
error_10:
		db 6,'2204',6
		db '<CH>No space to create a DOS partition. '
		db 6,'0100',6
		db '<CW>',0

error_12:	db 6,'2204',6
		db '<CH>Requested logical drive size exceeds the maximum available sp'
		db 'ace.<W> '
		db 6,'0100',6
		db '<CW>',0
error_13:	db 6,'2204',6
		db '<CH>Requested partition size exceeds the maximum available space.'
		db '<W> '
		db 6,'0100',6
		db '<CW>',0
error_14:	db 6,'2204',6
		db '<CH>No partitions to delete. '
		db 6,'0100',6
		db '<CW>',0
error_15:	db 6,'2204',6
		db '<CH>The only startable partition on Drive 1 is already set active'
		db '.<W> '
		db 6,'0100',6
		db '<CW>',0
error_16:	db 6,'2204',6
		db '<CH>No partitions to make active. '
		db 6,'0100',6
		db '<CW>',0
error_17:	db 6,'2204',6
		db '<CH>Partition selected (<I>) is not startable, active partition not '
		db 'changed.<W>',0
error_19:	db 6,'2204',6
		db '<CH>Cannot create Extended DOS Partition without '
		db 6,'0104',6
		db '<CH>Primary DOS Partition on disk 1.<W>',0
error_20:	db 6,'2204',6
		db '<CH>All available space in the Extended DOS Partition '
		db 6,'0104',6
		db '<CH>is assigned to logical drives.<W>',0
error_21:	db 6,'2204',6
		db '<CH>Cannot delete Extended DOS Partition while logical drives exist.<W>',0
error_22:	db 6,'2204',6
		db '<CH>All logical drives deleted in the Extended DOS Partition.<W>',0
error_23:	db 6,'2204',6
		db '<C> '
		db 6,'0104',6
		db '<CHI> is not a choice. Please enter <III>.<W>',0
error_24:	db 6,'2204',6
		db '<CH>WARNING! The partition set active is not startable.<W>',0
error_25:	db 6,'2204',6
		db '<CH> Only non-startable partitions exist. '
		db 6,'0100',6
		db '<CW>',0
error_26:	db 6,'2204',6
		db '<CH>Only partitions on Drive 1 can be made active.<W>',0
error_27:	db 6,'2204',6
		db '<CH>Maximum number of Logical DOS Drives installed.<W>',0
error_28:	db 6,'2204',6
		db '<CH>Cannot create a zero size partition. '
		db 6,'0100',6
		db '<CW>',0
error_29:	db 6,'2204',6
		db '<CH>Drive <II> already deleted. '
		db 6,'0100',6
		db '<CW>',0
error_30:	db 6,'2204',6
		db '<CHB>Unable to access Drive <I>.<OW>',0
error_31:	db 6,'2304',6
		db '<CH>Invalid entry, please enter <III>.<W>',0
error_32:	db 6,'2204',6
		db '<CH>Cannot delete Primary DOS Partition on drive 1  '
		db 6,'0104',6
		db '<CH>when an Extended DOS Partition exists.<W>',0
error_33:	db 6,'2200',6
		db '<C> '
		db 6,'0104',6
		db '<CH>Invalid entry.<W>',0
error_34:	db 6,'2204',6
		db '<CH>Volume label does not match.<W>',0
error_35:	db 6,'2204',6
		db '<CH>Cannot create Logical DOS Drive without '
		db 6,'0104',6
		db '<CH>an Extended DOS Partition on the current drive.<W>',0
error_36:	db 6,'2204',6
		db '<CH>No Logical DOS Drive(s) to delete. '
		db 6,'0100',6
		db '<CW>',0
error_37:	db 6,'2204',6
		db '<CH>Partition selected is not a Primary DOS Partition '
		db 6,'0100',6
		db '<CW>',0
error_38:	db 6,'2204',6
		db '<CH>No Non-DOS Partition to delete. '
		db 6,'0100',6
		db '<CW>',0
error_39:	db 6,'2204',6
		db '<CH>Partition selected is not a Non-DOS Partition '
		db 6,'0100',6
		db '<CW>',0

;-- FDISK.MSG (MSDOS 6.0, FDISK) --
;/*                                                                      */
;/* The following message is only included as an aide to debug message   */
;/* strings during translations. The FDISK message formatter will attempt*/
;/* to the best of its ability to catch invalid message strings and      */
;/* print the error. This message should NEVER appear for a user, so it  */
;/* is not neccessary to translate this message                          */
;/*                                                                      */

debug_msg:
		db 6,'2200',6
		db '<HWB>Message string error <I>. See header of FDISKC.MSG for error'
		db ' definition',0

internal_error:
		db 6,'2204',6
		db '<HBW>Internal error',0
; 14/12/2018
stack_error:
		db 6,'2204',6
		db '<HBW>Stack overflow',0
fp_error:
		db 6,'2204',6
		db '<HBW>Floating-point support not loaded',0

;-- FDISK.MSG (MSDOS 6.0, FDISK) --
;/*                                                                      */
;/* The following are not translatable. They are the partition names     */
;/*                                                                      */

txtRemote:	db '* Remote * ',0
txtPriDos:	db 'PRI DOS',0
txtXenix:	db ' XENIX ',0
txtExtDos:	db 'EXT DOS',0
txtTable:	db ' Table ',0
txtPcIx:	db ' PC/IX ',0
;txtHpFs	db ' HPFS  ',0
txtNTFS:	db ' NTFS  ',0 ; 17/11/2018	
txtNovell:	db 'NOVELL ',0
txtCpM:		db ' CP/M  ',0
txtNonDos:	db 'Non-DOS',0

; MENU (FORMATTED) TEXT ADDRESS POINTERS
; 01/12/2018

menu_1_offset:	dw menu_1
;menu_1_segment: dw DGROUP
menu_2_offset: dw menu_2
;menu_2_segment: dw DGROUP
menu_3_offset: dw menu_3
;menu_3_segment: dw DGROUP
menu_4_offset: dw menu_4
;menu_4_segment: dw DGROUP
menu_5_offset: dw menu_5
;menu_5_segment: dw DGROUP
menu_6_offset: dw menu_6
;menu_6_segment: dw DGROUP
menu_7_offset: dw menu_7
;menu_7_segment: dw DGROUP
menu_8_offset: dw menu_8
;menu_8_segment: dw DGROUP
menu_9_offset: dw menu_9
;menu_9_segment: dw DGROUP
menu_10_offset: dw menu_10
;menu_10_segment: dw DGROUP
menu_11_offset: dw menu_11
;menu_11_segment: dw DGROUP
menu_12_offset: dw menu_12
;menu_12_segment: dw DGROUP
menu_13_offset: dw menu_13
;menu_13_segment: dw DGROUP
menu_45_offset: dw menu_45
;menu_45_segment: dw DGROUP
menu_14_offset: dw menu_14
;menu_14_segment: dw DGROUP
menu_15_offset: dw menu_15
;menu_15_segment: dw DGROUP
menu_16_offset: dw menu_16
;menu_16_segment: dw DGROUP
menu_39_offset: dw menu_39
;menu_39_segment: dw DGROUP
menu_17_offset: dw menu_17
;menu_17_segment: dw DGROUP
menu_42_offset: dw menu_42
;menu_42_segment: dw DGROUP
menu_46_offset: dw menu_46
;menu_46_segment: dw DGROUP
menu_18_offset: dw menu_18
;menu_18_segment: dw DGROUP
menu_19_offset: dw menu_19
;menu_19_segment: dw DGROUP
menu_43_offset: dw menu_43
;menu_43_segment: dw DGROUP
menu_20_offset: dw menu_20
;menu_20_segment: dw DGROUP
menu_44_offset: dw menu_44
;menu_44_segment: dw DGROUP
menu_21_offset: dw menu_21
;menu_21_segment: dw DGROUP
menu_22_offset: dw menu_22
;menu_22_segment: dw DGROUP
menu_40_offset: dw menu_40
;menu_40_segment: dw DGROUP
menu_23_offset: dw menu_23
;menu_23_segment: dw DGROUP
menu_24_offset: dw menu_24
;menu_24_segment: dw DGROUP
menu_25_offset: dw menu_25
;menu_25_segment: dw DGROUP
menu_26_offset: dw menu_26
;menu_26_segment: dw DGROUP
menu_27_offset: dw menu_27
;menu_27_segment: dw DGROUP
menu_57_offset: dw menu_57
;menu_57_segment: dw DGROUP
menu_28_offset: dw menu_28
;menu_28_segment: dw DGROUP
menu_55_offset: dw menu_55
;menu_55_segment: dw DGROUP
menu_56_offset: dw menu_56
;menu_56_segment: dw DGROUP
menu_30_offset: dw menu_30
;menu_30_segment: dw DGROUP
menu_31_offset: dw menu_31
;menu_31_segment: dw DGROUP
menu_32_offset: dw menu_32
;menu_32_segment: dw DGROUP
menu_33_offset: dw menu_33
;menu_33_segment: dw DGROUP
menu_34_offset: dw menu_34
;menu_34_segment: dw DGROUP
menu_41_offset: dw menu_41
;menu_41_segment: dw DGROUP
menu_58_offset: dw menu_58
;menu_58_segment: dw DGROUP
menu_59_offset: dw menu_59
;menu_59_segment: dw DGROUP
menu_35_offset: dw menu_35
;menu_35_segment: dw DGROUP
menu_36_offset: dw menu_36
;menu_36_segment: dw DGROUP
menu_37_offset: dw menu_37
;menu_37_segment: dw DGROUP
menu_47_offset: dw menu_47
;menu_47_segment: dw DGROUP
menu_48_offset: dw menu_48
;menu_48_segment: dw DGROUP
menu_49_offset: dw menu_49
;menu_49_segment: dw DGROUP
menu_50_offset: dw menu_50
;menu_50_segment: dw DGROUP
menu_51_offset: dw menu_51
;menu_51_segment: dw DGROUP
menu_52_offset: dw menu_52
;menu_52_segment: dw DGROUP
menu_53_offset: dw menu_53
;menu_53_segment: dw DGROUP
menu_54_offset: dw menu_54
;menu_54_segment: dw DGROUP
menu_38_offset: dw menu_38
;menu_38_segment: dw DGROUP
menu_60_offset: dw menu_60
;menu_60_segment: dw DGROUP

; STATUS MESSAGE ADDRESS POINTERS
; 01/12/2018

status_1_off:	dw status_1
;status_1_seg:	dw DGROUP
status_2_off:	dw status_2
;status_2_seg:	dw DGROUP
status_3_off:	dw status_3
;status_3_seg:	dw DGROUP
status_4_off:	dw status_4
;status_4_seg:	dw DGROUP
status_5_off:	dw status_5
;status_5_seg:	dw DGROUP
status_6_off:	dw status_6
;status_6_seg:	dw DGROUP
status_7_off:	dw status_7
;status_7_seg:	dw DGROUP
status_8_off:	dw status_8
;status_8_seg:	dw DGROUP
status_9_off:	dw status_9
;status_9_seg:	dw DGROUP
status_10_off:	dw status_10
;status_10_seg:	dw DGROUP
;status_11_off:	dw status_11
;status_11_seg:	dw DGROUP
status_12_off:	dw status_12
;status_12_seg:	dw DGROUP
status_13_off:	dw status_13
;status_13_seg:	dw DGROUP

; ERROR MESSAGE ADDRESS POINTERS
; 17/11/2018

align 2

error_1_off:	dw error_1
;error_1_seg:	dw DGROUP
error_2_off:	dw error_2
;error_2_seg:	dw DGROUP
error_3_off:	dw error_3
;error_3_seg:	dw DGROUP
error_4_off:	dw error_4
;error_4_seg:	dw DGROUP
error_5_off:	dw error_5
;error_5_seg:	dw DGROUP
error_6_off:	dw error_6
;error_6_seg:	dw DGROUP
error_7_off:	dw error_7
;error_7_seg:	dw DGROUP
error_8_off:	dw error_8
;error_8_seg:	dw DGROUP
error_9_off:	dw error_9
;error_9_seg:	dw DGROUP
error_10_off:	dw error_10
;error_10_seg:	dw DGROUP
error_12_off:	dw error_12
;error_12_seg:	dw DGROUP
error_13_off:	dw error_13
;error_13_seg:	dw DGROUP
error_14_off:	dw error_14
;error_14_seg:	dw DGROUP
error_15_off:	dw error_15
;error_15_seg:	dw DGROUP
error_16_off:	dw error_16
;error_16_seg:	dw DGROUP
error_17_off:	dw error_17
;error_17_seg:	dw DGROUP
error_19_off:	dw error_19
;error_19_seg:	dw DGROUP
error_20_off:	dw error_20
;error_20_seg:	dw DGROUP
error_21_off:	dw error_21
;error_21_seg:	dw DGROUP
error_22_off:	dw error_22
;error_22_seg:	dw DGROUP
error_23_off:	dw error_23
;error_23_seg:	dw DGROUP
error_24_off:	dw error_24
;error_24_seg:	dw DGROUP
error_25_off:	dw error_25
;error_25_seg:	dw DGROUP
error_26_off:	dw error_26
;error_26_seg:	dw DGROUP
error_27_off:	dw error_27
;error_27_seg:	dw DGROUP
error_28_off:	dw error_28
;error_28_seg:	dw DGROUP
error_29_off:	dw error_29
;error_29_seg:	dw DGROUP
error_30_off:	dw error_30
;error_30_seg:	dw DGROUP
error_31_off:	dw error_31
;error_31_seg:	dw DGROUP
error_32_off:	dw error_32
;error_32_seg:	dw DGROUP
error_33_off:	dw error_33
;error_33_seg:	dw DGROUP
error_34_off:	dw error_34
;error_34_seg:	dw DGROUP
error_35_off:	dw error_35
;error_35_seg:	dw DGROUP
error_36_off:	dw error_36
;error_36_seg:	dw DGROUP
error_37_off:	dw error_37
;error_37_seg:	dw DGROUP
error_38_off:	dw error_38
;error_38_seg:	dw DGROUP
error_39_off:	dw error_39
;error_39_seg:	dw DGROUP

debug_msg_off:	dw debug_msg
;debug_msg_seg:	dw DGROUP

; 18/12/2018
inter_err_off:	dw internal_error
;inter_err_seg:	dw DGROUP

; 14/12/2018
stackerror_msg_off:
		dw stack_error
;stackerror_msg_seg:
;		dw DGROUP		 

fperror_msg_off:
		dw fp_error
;fperror_msg_seg:
;		de DGROUP

; 26/11/2018
REMOTE:		dw txtRemote
PRIDOS:		dw txtPriDos
XENIX:		dw txtXenix
EXTDOS:		dw txtExtDos
TABLE:		dw txtTable
PCIX:		dw txtPcIx
;HPFS:		dw txtHpFs
NTFS:		dw txtNTFS
NOVELL:		dw txtNovell
CPM:		dw txtCpM
NONDOS:		dw txtNonDos

; 07/12/2018
;_atopsp:	dw 0
;_aexit_rtn:	dw _exit_
;_asizds:	dw 0

; 14/12/2018 (no need to  _nheap_desc)
; 09/12/2018
_nheap_desc:	db 0, 0, 5, 0, 0, 0, 0,	0
		db 0, 0, 0, 0, 0, 0, 0,	0
		db 0, 0, 0, 0, 0, 0, 0,	0

errno:		dw 0

;umaskval:	dw 0
;_pspadr:	dw 0
_psp:		dw 0

_dosvermajor:	db 0
_dosverminor:	db 0

; 14/12/2018 (cleaning)

;;_osmode	db 0

;_doserrno:	dw 0
;_nfile		dw 20
;
;_osfile:	db 81h,81h,81h
;		db 01h,01h
;		times 15 db 0	

; 17/11/2018

; ctype.h (MSDOS 6.0)

;/* set bit masks for the possible character types */

;#define _UPPER        0x1       /* upper case letter */
;#define _LOWER        0x2       /* lower case letter */
;#define _DIGIT        0x4       /* digit[0-9] */
;#define _SPACE        0x8       /* tab, carriage return, newline, */
;                                /* vertical tab or form feed */
;#define _PUNCT       0x10       /* punctuation character */
;#define _CONTROL     0x20       /* control character */
;#define _BLANK       0x40       /* space char */
;#define _HEX         0x80       /* hexadecimal digit */

;/* the character classification macro definitions */

;#define isalpha(c)      ( (_ctype+1)[c] & (_UPPER|_LOWER) )
;#define isupper(c)      ( (_ctype+1)[c] & _UPPER )
;#define islower(c)      ( (_ctype+1)[c] & _LOWER )
;#define isdigit(c)      ( (_ctype+1)[c] & _DIGIT )
;#define isxdigit(c)     ( (_ctype+1)[c] & _HEX )
;#define isspace(c)      ( (_ctype+1)[c] & _SPACE )
;#define ispunct(c)      ( (_ctype+1)[c] & _PUNCT )
;#define isalnum(c)      ( (_ctype+1)[c] & (_UPPER|_LOWER|_DIGIT) )
;#define isprint(c)      ( (_ctype+1)[c] & (_BLANK|_PUNCT|_UPPER|_LOWER|_DIGIT) )
;#define isgraph(c)      ( (_ctype+1)[c] & (_PUNCT|_UPPER|_LOWER|_DIGIT) )
;#define iscntrl(c)      ( (_ctype+1)[c] & _CONTROL )
;
;#define toupper(c)      ( (islower(c)) ? _toupper(c) : (c) )
;#define tolower(c)      ( (isupper(c)) ? _tolower(c) : (c) )
;
;#define _tolower(c)     ( (c)-'A'+'a' )
;#define _toupper(c)     ( (c)-'a'+'A' )
;
;#define isascii(c)      ( (unsigned)(c) < 0x80 )
;#define toascii(c)      ( (c) & 0x7f )

align 2
	db 0

;isdigit(*s) -c-
;[isdigit+bx] -asm-

_ctype:		; (PC-DOS 7.0 FDISK.COM - segment 4, offset 543Eh)
	db 0
isdigit: ; Table for numeric character check	; _ctype+1
	db 20h,	20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h, 28h, 28h, 28h, 28h, 28h, 20h, 20h
	db 20h,	20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h,	20h, 20h, 20h, 20h, 20h, 20h, 20h
	db 48h,	10h, 10h, 10h, 10h, 10h, 10h, 10h, 10h,	10h, 10h, 10h, 10h, 10h, 10h, 10h
	db 84h,	84h, 84h, 84h, 84h, 84h, 84h, 84h, 84h,	84h, 10h, 10h, 10h, 10h, 10h, 10h
	db 10h,	81h, 81h, 81h, 81h, 81h, 81h, 01h, 01h,	01h, 01h, 01h, 01h, 01h, 01h, 01h
	db 01h,	01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h,	01h, 01h, 10h, 10h, 10h, 10h, 10h
	db 10h,	82h, 82h, 82h, 82h, 82h, 82h, 02h, 02h,	02h, 02h, 02h, 02h, 02h, 02h, 02h
	db 02h,	02h, 02h, 02h, 02h, 02h, 02h, 02h, 02h,	02h, 02h, 10h, 10h, 10h, 10h, 20h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h
	db 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h,	00h, 00h, 00h, 00h, 00h, 00h, 00h

; 26/11/2018

;align 2
;_cpush:	dw 0FFFFh
;retadr:	dw 0

; 14/12/2018 (no need to err_conv_tbl)
;err_conv_tbl:
;		db 00h,	16h, 02h, 02h, 18h, 0Dh, 09h, 0Ch, 0Ch,	0Ch
;		db 07h,	08h, 16h, 16h, 0FFh, 02h, 0Dh, 12h, 02h, 0FFh

; 06/12/2018
	; The following defines the lookup table for changing states
	; This is actually two table combined into one.
	; The lower nybble of each byte gives the character
	; class of any character -- i.e.
	;   charclass = lookuptable[char-' '] & 0xF;
	; The upper nybble of each byte gives the next state to enter -- i.e.
	;   newstate = looptable[charclass][oldstate] >> 4;

	; The table below is generated by maketab.c -- use this program
	; to make changes.

lookuptable:	db 06h, 00h, 00h, 06h, 00h, 01h, 00h, 00h
		db 10h, 00h, 03h, 06h, 00h, 06h, 02h, 10h
		db 04h, 45h, 45h, 45h, 05h, 05h, 05h, 05h
		db 05h, 35h, 30h, 00h, 50h, 00h, 00h, 00h
		db 00h, 20h, 20h, 30h, 50h, 58h, 07h, 08h
		db 00h, 30h, 30h, 30h, 57h, 50h, 07h, 00h
		db 00h, 20h, 20h, 00h, 00h, 00h, 00h, 00h
		db 08h, 60h, 60h, 60h, 60h, 60h, 60h, 00h
		db 00h, 70h, 70h, 78h, 78h, 78h, 78h, 08h
		db 07h, 08h, 00h, 00h, 07h, 00h, 08h, 08h
		db 08h, 00h, 00h, 08h, 00h, 08h, 00h, 00h
		db 08h

nullstring:	db '(null)'
nullstrlen:	dw 6	; string to print when null string passed

		align 2
		dw 0FFFFh
end_of_bss:	
		;dw 8B10h   ; File Size + BSS
		dw end_of_file ; 10/12/2018

; 14/12/2018 (cleaning)

; 07/12/2018
;_iob:
;STDIN:		dw _bufin
;STDIN_cnt:	dw 0
;STDIN_base:	dw _bufin
;STDIN_flag:	db 1
;STDIN_file:	db 0
;
;STDOUT:	dw 0
;STDOUT_cnt:	dw 0
;STDOUT_base:	dw 0
;STDOUT_flag:	db 2
;STDOUT_file:	db 1
;
;STDERR:	dw 0
;STDERR_cnt:	dw 0
;STDERR_base:	dw 0
;STDERR_flag:	db 2
;STDERR_file:	db 2
;
;STDAUX:	dw 0
;STDAUX_cnt:	dw 0
;STDAUX_base:	dw 0
;STDAUX_flag:	db 84h
;STDAUX_file:	db 3
;
;STDPRN:	dw 0
;STDPRN_cnt:	dw 0
;STDPRN_base:	dw 0
;STDPRN_flag:	db 2
;STDPRN_file:	db 4
;
;	times 120 db 0
;
;_iob2:
;_iob2_flag2:	db 1
;_iob2_charbuf:	db 0
;_iob2_bufsiz:	dw 512
;_iob2_tmpnum:	dw 0
;_iob2_padding:	dw 0
;		
;	times 152 db 0

; CMISTDAT.ASM ; miscellaneous C run-time data
; MSDOS Visual C++ 1.0

;_cfltcvt_tab:
_cfltcvt:	dw _fptrap
_cropzeros	dw _fptrap
;		dw _fptrap
_forcdecpt	dw _fptrap
;		dw _fptrap
_cldcvt:	dw _fptrap
;	
;	times 8 db 0
;_amblksiz:	dw 2000h ; 09/12/2018
;_aDBswpflg:	dw 0
;_aDBswpchk:	dw _aDBretaddr
;_aDBrterr:	dw _aDBretaddr
;_aDBexit:	dw _aDBretaddr
;	
;	times 4 db 0
; 
; 13/12/2018
;strbuf:	; Stream Buffer (for sprintf)
;_strbuf_ptr:	dw 7E7Eh
;_strbuf_cnt:	dw 7E7Eh
;_strbuf_base:	dw 7E7Eh
;_strbuf_flag:	db 7Eh
;_strbuf_file:	db 7Eh
;
;xontab:	db 7Eh
;		db 7Eh

;=============================================================================
;        	uninitialized data
;=============================================================================

bss_start:

ABSOLUTE bss_start

alignb 2

; SEGMENT 4 - DGROUP ---------------------------------------------------------

reboot_flag:	resb 1
dx_buff:	resb 17
dx_buff_file_system: resb 8
video_mode:	resb 1
		resb 1
p_px:					; PARMSX block structure
p_px_p_minp:	 resb 1			; Minimum positional number
p_px_p_maxp:	 resb 1			; Maximum positional number
p_px_p_con1_ptr: resw 1			; Address of the 1st CONTROL block
p_px_p_maxs:	 resb 1			; # OF SWITCHES
p_px_p_swi1_ptr: resw 1			; DESCRIPTION OF SWITCH 1
p_px_p_swi2_ptr: resw 1			; REPEATS maxs-1 TIMES
p_px_p_swi3_ptr: resw 1
p_px_p_swi4_ptr: resw 1
p_px_p_swi5_ptr: resw 1
p_px_p_maxk:	 resb 1			; # OF KEYWORDS

disk_flag:	 resb 1
p_p:					; PARMS block structure
p_p_p_parmxs_ptr:      resw 1		; Address of PARMSX		
p_p_p_num_extra:       resb 1		; Number of extra stuff
p_p_p_len_extra_delim: resb 1		; Length of extra delimiter
p_p_p_extra_delim:     resb 1		; Extra delimiter

input_col:	resw 1
No:		resb 1
		resb 1

max_sector:	resb 8
max_head:	resw 8
total_disk:	resw 8
total_mbytes:	resw 8

		resw 2
;regs:
;regs_x_ax:	resw 1
;regs_x_bx:	resw 1
;regs_x_cx:	resw 1
;regs_x_dx:	resw 1
;regs_x_si:	resw 1
;regs_x_di:	resw 1
;regs_x_cflag:	resb 1
;		resb 1

sublistp_size:	    resb 1
sublistp_res:	    resb 1
sublistp_value:	    resw 1
sublistp_value_seg: resw 1
sublistp_id:	    resb 1
sublistp_flags:	    resb 1
sublistp_max_width: resb 1
sublistp_min_width: resb 1
sublistp_pad_char:  resb 1
		resb 1
p_swi1:
p_swi1_sp_match_flag:	 resw 1
p_swi1_sp_function_flag: resw 1
p_swi1_sp_buff1_ptr:	 resw 1
p_swi1_sp_val1_ptr:	 resw 1
p_swi1_sp_nid:		 resb 1
p_swi1_sp_switch1:	 resb 5
p_swi1_sp_switch2:	 resb 5
p_swi1_sp_switch3:	 resb 5
primary_flag:	resb 1
		resb 1

p_swi2:
p_swi2_sp_match_flag:	 resw 1
p_swi2_sp_function_flag: resw 1
p_swi2_sp_buff1_ptr:	 resw 1
p_swi2_sp_val1_ptr:	 resw 1
p_swi2_sp_nid:		 resb 1
p_swi2_sp_switch4:	 resb 3

p_swi3:
p_swi3_sp_match_flag:	 resw 1
p_swi3_sp_function_flag: resw 1
p_swi3_sp_buff1_ptr:	 resw 1
p_swi3_sp_val1_ptr:	 resw 1
p_swi3_sp_nid:		 resb 1
p_swi3_sp_switch5:	 resb 8

next_letter:	resb 1
display_page:	resb 1
		resb 1
p_swi4:
p_swi4_sp_match_flag:	 resw 1
p_swi4_sp_function_flag: resw 1
p_swi4_sp_buff1_ptr:	 resw 1
p_swi4_sp_val1_ptr:	 resw 1
p_swi4_sp_nid:		 resb 1
p_swi4_sp_switch6:	 resb 3

mbr_flag:	resb 1
		resb 1

; 14/12/2018 (no need to _bufin for FDISK2.COM) 

;_bufin:	resb 512

p_swi5:
p_swi5_sp_match_flag:	 resw 1
p_swi5_sp_function_flag: resw 1
p_swi5_sp_buff1_ptr:	 resw 1
p_swi5_sp_val1_ptr:	 resw 1
p_swi5_sp_nid:	 	 resb 1
p_swi5_sp_switch7:	 resb 5

input_row:	resw 1
quiet_flag:	resb 1
		resb 1

good_disk:	resb 8

; LOGICAL PARTITION DATA STRUCTURE
; (for logical paritions in extended paritions)
; 23/11/2018
; 8 extended partitions (on 8 hard disks -8 physical drives-)
; 24 logical drives (46 bytes) per extended partition
; 8832 bytes (8*24*46)

ext_table_boot_ind:	resb 1
ext_table_start_head:	resb 1
ext_table_start_sector: resb 1
ext_table_start_cyl:	resw 1
ext_table_sys_id:	resb 1
ext_table_end_head:	resb 1
ext_table_end_sector:	resb 1
ext_table_end_cyl:	resw 1
ext_table_rel_sec_lw:	resw 1
ext_table_rel_sec_hw:	resw 1
ext_table_num_sec_lw:	resw 1
ext_table_num_sec_hw:	resw 1
			resb 1
ext_table_changed:	resb 1
ext_table_mbytes_used:	resw 1
ext_table_percent_used:	resw 1
ext_table_vol_label:	resb 12
ext_table_system:	resb 9
ext_table_drive_letter:	resb 1
		resb 1012 ; 46*22
ep0_lp23_boot_ind:	resb 1
ep0_lp23_start_head:	resb 1
ep0_lp23_start_sector:	resb 1
ep0_lp23_start_cyl:	resw 1 ; 06/01/2019
ep0_lp23_sys_id:	resb 1
ep0_lp23_end_head:	resb 1
ep0_lp23_end_sector:	resb 1
ep0_lp23_end_cyl:	resw 1 ; 06/01/2019
ep0_lp23_rel_sec_lw:	resw 1
ep0_lp23_rel_sec_hw:	resw 1
ep0_lp23_num_sec_lw:	resw 1
ep0_lp23_num_sec_hw:	resw 1
			resb 1 ; 06/01/2019
ep0_lp23_changed: 	resb 1
ep0_lp23_mbytes_used:	resw 1
ep0_lp23_percent_used:	resw 1
ep0_lp23_vol_label:	resb 12
ep0_lp23_system:	resb 9
ep0_lp23_drive_letter:	resb 1
		resb 7728 ; 7*46*24

mono_flag:	resb 1
Yes:		resb 1
;segregs:
;segregs_es:	resw 1
;segregs_cs:	resw 1
;segregs_ss:	resw 1
;segregs_ds:	resw 1
extended_buff:	resw 1

;total_disk:	resw 8

primary_partition_count: resb 1
		resb 1
primary_buff:	resw 1
PercentFlag:	resb 1
logical_flag:	resb 1
status_flag:	resb 1
number_of_drives: resb 1
extended_flag:	resb 1

sp_val:
sp_val_p_values:	resb 1
sp_val_p_range:		resb 1
sp_val_p_range_one: 	resb 1
sp_val_p_low_range: 	resd 1
sp_val_p_high_range:   	resw 1
sp_val_p_high_range_2: 	resb 1

sort_1:			resb 1
sort:			resb 24

p_val:
p_val_p_values		resb 1
p_val_p_range:		resb 1
p_val_p_range_one:	resb 1
p_val_p_low_range:	resd 1
p_val_p_high_range:	resd 1
no_fatal_error:	resb 1
p_con:
p_con_p_match_flag:	resw 1
p_con_p_function_flag:	resw 1
p_con_p_buff1_ptr:	resw 1
p_con_p_val1_ptr:	resw 1
p_con_nid:		resb 1
cur_disk_buff:		resb 1

; 13/12/2018
video_attribute: resb 1
		 resb 1

; PARTITION DATA STRUCTURE
; 32 (4*8) partitions (on 8 hard disks -8 physical drives-)
; 46 byte partition data structure per partition
; (4*46 bytes per disk)

part_table_boot_ind:	 resb 1
part_table_start_head:	 resb 1
part_table_start_sector: resb 1
part_table_start_cyl:	 resw 1
part_table_sys_id:	 resb 1
part_table_end_head:	 resb 1
part_table_end_sector:	 resb 1
part_table_end_cyl:	 resw 1
part_table_rel_sec_lw:	 resw 1
part_table_rel_sec_hw:	 resw 1
part_table_num_sec_lw:	 resw 1
part_table_num_sec_hw:	 resw 1
			 resb 1
part_table_changed:	 resb 1
part_table_mbytes_used:  resw 1
part_table_percent_used: resw 1
part_table_vol_label:	 resb 12
part_table_system:	 resb 9
part_table_drive_letter: resb 1
		       resb 20
pt_part2_mbytes_used:  resw 1
pt_part2_percent_used: resw 1
		       resb 22
		       resb 20
pt_part3_mbytes_used:  resw 1
pt_part3_percent_used: resw 1
		       resb 22
		       resb 20
pt_part4_mbytes_used:  resw 1
pt_part4_percent_used: resw 1
		       resb 22
		resb 1288 ; 22/11/2018 (4*46*7 = 1288)

;max_sector:	resb 8
boot_record:	resb 512
logical_buff:	resw 1
cur_disk:	resb 1
		resb 1
p_buff:		   resb 1
p_buff_p_item_tag: resb 1
p_buff_p_synonym:  resw 1
p_buff_p_value:	   resd 1
valid_input:	resb 1
		resb 1
Parse_Ptr:	resw 1

; 14/11/2019
fspc:		; 5*10 words (for free space calculations)

; Space 1 - unused cylinders before partition 0
; Space 2 - unused cylinders between partition 0 & 1 
; Space 3 - unused cylinders between partition 1 & 2 
; Space 5 - unused cylinders between partition 2 & 3 
; Space 5 - unused cylinders after partition 3

; 13/01/2019
free_space.space:   	   resw 1
free_space.start:   	   resw 1
free_space.end:	   	   resw 1
free_space.mbytes_unused:  resw 1
free_space.percent_unused: resw 1
		;resb 520
		;resw 4*5  ; 17/01/2019
		resw  23*5 ; 20/01/2019		 	

disk_access:	 resb 1
dac_access_flag: resb 1
sp_buff:	    resb 1
sp_buff_p_item_tag: resb 1
sp_buff_p_synonym:  resw 1
sp_buff_p_value:    resb 10

; 13/12/2018
outbuf_ptr:	resw 1 ; offset insert (insert+)
outbuf_cnt:	resw 1 ; 800

insert:		resb 800

dataoffset_end_2: resw 1

; 10/11/2018
_argc:  resw 1
_argv:	resw 1
retadr:	resw 1
_temp:	resw 1
_input: resw 1
_pgmptr: resd 1
		
; SEGMENT 5 - Uninitialized --------------------------------------------------

;resb 2048

alignb 2

end_of_file: 