; Перед таблицей диска вывести строку о размере своб. системной памяти ; DEFINE App_EXE_Version 1 INCLUDE 'shared_includes/constants/sp2000.inc' INCLUDE 'shared_includes/constants/BIOS_equ.inc' INCLUDE 'shared_includes/constants/DSS_EQU.inc' INCLUDE 'shared_includes/macroses/macros.z80' ; Версия программы major_version equ 1 minor_version equ 12 org_addr EQU SLOT1.MEM_ADDR + #100 + CLP_Buffer code_addr EQU ramdrv program_start EQU ramdrv stack_point EQU #C000 Loader_length EQU 0 ; org 4100h ; db "EX" ; exe ID ; db "E" ; exe тип ; db 0 ; exe версия ; dw 512 ; мл. смещ. кода ; dw 0 ; ст. смещ. кода ; dw 0 ; end-beg, первичный загрузчик ; dw 0,0 ; резерв ; dw 0 ; ; dw start ; адрес загрузки кода ; dw start ; адрес передачи управления ; dw 0C000h ; адрес стека ; ds 490 ; резерв EXE_ORG org_addr ramdrv: ; парсинг ком-строки push ix ld hl,title ; титл программы ld c,5Ch ; вывести строку rst 10h ; очистить буфер клавы ld bc,3135h rst 10h pop de ld hl,help ; вывод помощи ld a,(de) or a jr z,.error inc de ; перейти на ком-строку ld a,(de) cp " " jr z,$-4 ld a,(de) ; цифра or a jr z,.bad_option call dec_to_word ; char -> int ld (.kbytes+1),hl ; размер диска в kB jr nc,.ok_option .bad_option: ld hl,err_value ; "Invalid value" jr .error ; .ok_option: ld hl,(.kbytes+1) ; размер диска в kB ld de,64 ; мин. размер диска в kB sbc hl,de jr nc,$+5 ld (.kbytes+1),de ; создать серийный номер диска ld c,21h ; получить время rst 10h ; hl=часы/минуты, b=секунды ld a,r ; динамич. счетчик долей секунды cp 99+1 jr c,.rand ld a,99 .rand: ld c,a ; доли секунды ld de,07C7h add hl,de ld (msdos+39),hl ; sn_low ld hl,0707h add hl,bc ld (msdos+41),hl ; sn_high ; получить идентиф. блока, назначенного на RAM-диск di ld bc,00CEh ; с=номер функции .loop: ld a,b ; номер RAM-диска 0..15, (от E: до T:) push bc rst 08h pop bc or a jr z,.free ; блок не назначен inc b ld a,b cp 15+1 ; номер RAM-диска jr nz,.loop ; выход за пределы 0..15 диапазона ld hl,no_free_ramdisk ; "No free RAM-DISK" .error: ld c,5Ch ; вывод строки rst 10h ld b,1 ; код ошибки jp .abort ; выход в ДОС .free: ld a,b ld (.ram+1),a ; номер ram-диска .kbytes: ld hl,0 ; размер в kB call get_sect_fat ; расчитать число секторов на FAT ld (msdos+22),hl ; ячейка "секторов на FAT" ld hl,not_enough ; "No enough memory for create RAM-DISK" jr c,.error ; слишком большой объем (> 3984 kB) ; .hsize: ld hl,0 ; ст.разряд .lsize: ld bc,0 call get_mem_pages ; выделить память ld hl,not_enough ; "No enough memory for create RAM-DISK" jr c,.error ; нет памяти ld (.id+1),a ; идентиф. блока ; создать список страниц ld hl,list_pages ; буфер списка ld c,0C5h rst 08h ; назначить блок памяти RAM-диску .ram: ld a,0 ; номер RAM-диска 0..15 (от E: до T:) .id: ld b,-1 ; идентиф. блока ld c,0C9h rst 08h ; in a,(0C2h) ld (.port2+1),a ; сохр. порт Page2 in a,(0E2h) ld (.port3+1),a ; сохр. порт Page3 ; вкл. начальные 2 стр. блока в #8000..#FFFF ld hl,list_pages ; список страниц блока ld a,(hl) inc hl out (0C2h),a ; 1-я стр. блока ld a,(hl) out (0E2h),a ; 2-я стр. блока ; очистить Boot+FAT+RootDir ld hl,8000h ; начало 2-й страницы ld e,l ld d,h inc de ld bc,8000h-1 ; размер области ld (hl),l ldir ; перебросить BPB в 1-й сектор (boot) ld hl,msdos ; откуда ld de,8000h ; куда ld bc,len_BPB ldir dec c ld hl,8000h+510 ld (hl),55h ; сигнатура inc hl ld (hl),0AAh ; inc hl ; FAT ld (hl),0FAh ; эл. диск inc hl ld (hl),c ; FF inc hl ld (hl),c ; FF ; .port2: ld a,-1 out (0C2h),a ; восст. порт Page2 .port3: ld a,-1 out (0E2h),a ; восст. порт Page3 ; call environment ; поиск переменной окружения ; размер своб. сист. памяти ld c,3Ch ; инфа о памяти rst 10h ; bc=число своб. банок ld l,c ld h,b inc hl ; + банка, занимаемая самой RAMDRV add hl,hl ;1+1=2 add hl,hl ;2+2=4 add hl,hl ;4+4=8 add hl,hl ;8+8=16 ld de,freemem ; куда call decim ;--------------------------- ; весь объем диска ld hl,(.kbytes+1) ; размер в kB ld de,total_size ; куда call decim ; заполнение инфо-таблицы ; вычислить доступный размер диска ld hl,(msdos+19) ; всех секторов на диске ld de,(msdos+22) ; секторов на FAT ld bc,33 ; 1+32 (Boot + RootDirSect) and a sbc hl,bc and a sbc hl,de ; hl=число дост. секторов ; CountSect * 512 = SizeBytes push hl pop ix ld b,9 ld hl,0 .calc: add ix,ix ; мл.разряд adc hl,hl ; ст.разряд djnz .calc push ix pop bc ld de,1024 ; делитель call divide ; hl=число kB ld de,avail_size ; буфер call decim ; заполнение инфо-таблицы ; узнать версию ДОС ld c,0 rst 10h ld hl,013Ch ; 1.60 and a sbc hl,de jr nc,.old_ver ; =< 1.60 ; перескан. девайсы системы ld c,8 rst 10h xor a ld (mess_),a ; не выводить "Now reboot, ..." ; вывод инфы по созданному диску ld hl,ram_created ; info-таблица ld c,5Ch ; вывод строки rst 10h jr .backcode ; вывод инфы по созданному диску .old_ver: ld hl,ram_created ; info-таблица ld c,5Ch ; вывод строки rst 10h ; задержка в 4 секунды ei ld b,4 ; 4 секунды .wait: push bc ld c,31h ; код клавиши без ожидания rst 10h pop bc jr nz,.exit ld a,49 ; 1/50 секунды halt dec a jr nz,$-2 djnz .wait ; софтовый ребут xor a ld bc,02FDh rst 08h .exit: ld hl,aborting ld c,5Ch ; вывод строки rst 10h .backcode: ld b,0 ; возвр. код .abort: ei push bc ; очистить буфер клавы ld bc,3135h rst 10h pop bc ; выход в ДОС ld c,41h rst 10h di halt ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Расчитать и выделить необходимое число страниц ; ; вход: hl=ст.разряд байтов ; bc=мл.разряд ; выход: CF-ошибка выделения памяти ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_mem_pages: ld de,4000h ; делитель (размер страницы) xor a scf .loc1: rr d rr e jr c,.loc2 rr h rr l rr b rr c jr nc,.loc1 ld a,1 jr .loc1 ; .loc2: or a jr z,.loc3 inc bc .loc3: xor a cp b scf ret nz ; выделить блок памяти ld b,c ; b=число страниц ld c,0C2h ; выделить блок памяти rst 08h ret ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Расчитать число секторов для FAT ; ; вход: hl=число килобайт ; выход: hl=число секторов ; CF - ошибка ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_sect_fat: push hl ld bc,3984+1 ; Max kB для 31-го сектора FAT + 1 and a sbc hl,bc pop ix ccf ret c ; SizeKBytes * 1024 = SizeBytes ld b,10 ld hl,0 .loop: add ix,ix ; мл.разряд adc hl,hl ; ст.разряд djnz .loop push ix pop bc ld (ramdrv.hsize+1),hl ld (ramdrv.lsize+1),bc ; вычислить размер FAT в секторах call get_num_sectors ; SizeBytes / 512 = Total sectors ld (msdos+19),hl ; всех секторов на диске ld bc,33 ; 1+32 (Boot + RootDirSect) sbc hl,bc add hl,hl ld c,l ld b,h ld hl,0 ;jr get_num_sectors ; / 512 = Sectors per FAT ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Расчитать число секторов ; вход: hl=ст.разряд байтов ; bc=мл.разряд ; выход: hl=число секторов ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ get_num_sectors:ld de,512 ; делитель (размер сектора) divide: xor a scf .loc1: rr d rr e jr c,.loc2 rr h rr l rr b rr c jr nc,.loc1 ld a,1 jr .loc1 ; .loc2: or a jr z,.loc3 inc bc .loc3: ld l,c ld h,b ret ;----------------------------------------------------------- ; Конвертировать десят. число (макс. 4 цифры) в слово. ; вход: de=буфер ; выход: hl=число ; "Carry" - ошибка ;----------------------------------------------------------- dec_to_word: ld hl,0 ld b,4 ; макс. 4 цифры .loop: ld a,(de) ; цифра or a ret z call .isdigit ret c ; ошибка push bc call .dec_digit pop bc inc de djnz .loop ld a,(de) or a ; был один параметр ? ret z ld a,-1 scf ret ; конверт. цифру .dec_digit: ld c,l ld b,h add hl,hl ;1+1=2 add hl,hl ;2+2=4 add hl,bc ;4+1=5 add hl,hl ;5+5=10 sub "0" ld c,a ld b,0 add hl,bc ret ; Тест на цифру ; вых: Carry - не цифра .isdigit: cp "0" ret c cp "9"+1 ccf ret ;------------------------------------------------- ; Работа с переменной окружения программы ; и отслеживание буквы диска. ;------------------------------------------------- environment: ld bc,0146h ; получить переменную окружения ld hl,name ; имя переменной ld de,title ; буфер для значения переменной rst 10h ret c ; ошибка or a jr z,.not_found ; переменная не найдена ld a,(title) cp "Z" ret z inc a ; ++буква диска jr .next_letter ; .not_found: ld c,2 ; получить текущий номер диска rst 10h ld c,1 ; смена диска rst 10h add a,"A" .next_letter: ld (disk),a ; "lastdrive" ld (disk1),a ; ld bc,0246h ; уст. переменную окружения ld hl,name1 ; имя переменная=значение rst 10h ret ;------------------------------------------------- ; Перевод числа в символьный десятичный формат ; вход: hl=число ; de=буфер числа ;------------------------------------------------- decim: ld iy,.tmp res 7,(iy+0) ld bc,1000 ;1.000 (макс. 9999) call .getN16 ld bc,100 ;100 call .getN16 ld bc,10 ;10 call .getN16 ld a,l add a,"0" ld (de),a ret ; .tmp: db 0 .getN16: ld a,2Fh or a inc a sbc hl,bc jr nc,$-3 add hl,bc cp "0" jr z,$+6 set 7,(iy+0) bit 7,(iy+0) jr nz,$+4 ld a," " ; вед. пробелы ld (de),a inc de ret name: db "LASTDRV",0 ; имя переменной name1: db "LASTDRV=" disk: db "C",0 title: db 0Dh,0Ah,"RAMdrive Version ",major_version + "0","." db (minor_version / 10) + "0",(minor_version % 10) + "0" db ", Copyright (c) 2005-2007 by Vasil Ivanov." db 0Dh,0Ah,0Ah,0 ram_created: db "RAM-disk " disk1: db "C: successfully created",0Dh,0Ah db "Free system memory: " freemem: db "#### kB",0Dh,0Ah,0Ah ; db "Disk size: " total_size: db "#### kB",0Dh,0Ah ; размер диска db "Available space: " avail_size: db "#### kB",0Dh,0Ah ; размер диска db "Directory entries: 512",0Dh,0Ah ; записей в корне db "Sector size: 512 bytes",0Dh,0Ah ; байт на сектор db "Allocation unit: 1 sector",0Dh,0Ah,0Ah ; секторов на кластер mess_: db "Now reboot, please wait (4 sec.) ...",0 aborting: db " Aborting",0Dh,0Ah,0Ah db "Press ",34,"Ctrl+Alt+Del",34," for rebooting computer..." db 0Dh,0Ah,0Ah,0Ah,0 no_free_ramdisk:db "No free RAM-DISK !",0Dh,0Ah,0Ah,0 not_enough: db "Insufficient memory for create RAM-DISK !",0Dh,0Ah,0Ah,0 ; не верное значение err_value: db "Invalid value",0Dh,0Ah,0Ah,0 help: db "Syntax: ramdrv.exe ##",0Dh,0Ah,0Ah db "where: ## - disk size in kB (64 minimum).",0Dh,0Ah,0Ah,0 ; MS-DOS данные msdos: db 0EBh,3Ch,90h ; 3 байта, код перехода на загрузчик db "RDV 1.21" ; 8 байт, OEM ID ; BPB, 17 байт dw 512 ;+11 ; байтов на сектор db 1 ; 1, секторов на кластер dw 1 ; зарезерв. секторов db 1 ; число копий FAT-ов dw 512 ; записей в корне dw 34 ;+19 ; # всех секторов на диске db 0FAh ; байт формата dw 1 ;+22 ; # секторов на FAT dw 1 ; секторов на сторону dw 1 ; кол-во сторон диска ; Extended boot-record dw 0,0 ; скрытых секторов dw 0,0 ; всех секторов на диске dw 80h ; 0x00 физ. номер диска db 29h ; сигнатура расш. boot-записи dw 96C2h,2D3Ah ;+39..+41 ; серийный номер диска 2D3A:96C2 db "NO NAME " ;+43 ; 11 байт, метка ram-диска db "FAT12 " ;+54 ; 8 байт, ID файловой системы len_BPB equ $ - msdos ; буфер списка страниц выдел. блока list_pages: