Code: Select all
; Хамелеон-ДОС, версия 7.7
; (c) Алексей Мамонтов, 1994
.Z80
aseg
ORG 100H
MCONIN EQU 0F803H
MF806 EQU 0F806H ; ввод байта
MCOUT EQU 0F809H
YFCA6 EQU 0FCA6H ; ???
YE043 EQU 0E043H ; ROM бейсика (похоже это вход в ROM-бейсик)
YE14A EQU 0E14AH ; ROM бейсика
TRANS EQU 0E11FH ; ROM бейсика (блок (DE) -> (HL) длиной BC)
FILL_E EQU 0E12AH ; ROM бейсика (FILL блока длиной BC байтом из E)
YE260 EQU 0E260H ; ROM бейсика (возможно это пауза)
CMPDH EQU 0E425H ; ROM бейсика
MSSG EQU 0E4A4H ; ROM бейсика
PAUS_A EQU 0E5FBH ; ROM бейсика
YE627 EQU 0E627H ; ROM бейсика
YE6AA EQU 0E6AAH ; ROM бейсика
YE6A3 EQU 0E6A3H ; ROM бейсика
YEBD0 EQU 0EBD0H ; ROM бейсика
YDD31 EQU 0DD31H ; ROM бейсика (запись файла на МГ-ленту)
YDD94 EQU 0DD94H ; ROM бейсика (загрузка МГ-файла)
VG93 EQU 0E0H
RG_UPR EQU 0E4H
RGCOM EQU VG93 ; регистр команд
RGTRK EQU VG93+1 ; регистр дорожки
RGSEC EQU VG93+2 ; регистр сектора
RGDATA EQU VG93+3 ; регистр данных
CMDBUF EQU 0BE00H ; буфер ввода команд
NAME1 EQU 0BE8CH ; входное имя для МГ-файла (всего 6 букв)
NAME2 EQU 0BE92H ; похоже, что это имя МГ-файла считанное с ленты
BEGADR EQU 0BEA4H ; адрес начала МГ-файла (ROM-BIOS)
ENDADR EQU 0BEA6H ; адрес конца МГ-файла (ROM-BIOS)
YBEA9 EQU 0BEA9H ; адрес старта загруженного МГ-файла
D_PARM EQU 0BED0H ; область загрузки параметров всего диска
; далее следуют параметры диска:
DSKNAM EQU 0BED0H ; имя дискеты 10 символов (не 11)
FR_SEC EQU 0BEDBH ; номер сектора первого свободного сектора на диске
FR_TRK EQU 0BEDCH ; номер трека первого свободного сектора на диске
CLOSED EQU 0BEDEH ; флаг зпрета DIR
DISKRO EQU 0BEDFH ; флаг диск R/O
DIRBUF EQU 0BD00H ; буфер для работы с каталогом диска (256 байт)
YBE1E EQU 0BE1EH ; какой-то, похоже, неиспользуемый флаг
RECORD EQU 0BE1FH ; сюда грузится каталоговая запись файла:
FNAME EQU 0BE1FH ; имя файла, 8 символов
F_EXT EQU 0BE26H ; расширение, 3 символа
F_ATTR EQU 0BE2AH ; атрибут файла: 0 - R/W, 1 - R/O, 2- SYS & R/O
FF_SEC EQU 0BE2BH ; номер сектора на дорожке занимаемый первым сектором файла
FF_TRK EQU 0BE2CH ; номер дорожки, где находится первый сектор файла
F_BEGA EQU 0BE2DH ; начальный адрес файла в ОЗУ = адрес запуска
F_NSEC EQU 0BE2FH ; длина файла в секторах
YB880 EQU 0B880H
YBE38 EQU 0BE38H ; похоже флаг горячего старта
YBE3A EQU 0BE3AH
YBE40 EQU 0BE40H
STACK EQU 0BE80H
TRACK EQU 0BFB0H ; логический номер текущего трека (0...164)
SECTOR EQU 0BFB1H ; номер текущего сектора (1-9)
SIDE EQU 0BFB2H ; текущая сторона диска (0/1)
FIZTRK EQU 0BFB3H ; физический номер дорожки для контроллера
DISK EQU 0BFB4H ; номер текущего дисковода (1,2,3,4)
EXEFLG EQU 0BFB5H ; если >0 запуск файлa, =0 нет запускa
LENGTH EQU 0BFB6H ; число читаемых секторов (1-255)
CURDSK EQU 0BFB7H ; используется при работе (диск к которому лезем)
YBFB8 EQU 0BFB8H ; возможно это число секторов в треке (заготовка для DD)
JBFE8 EQU 0BFE8H ; здесь код C3 (команда JMP)
YBFE9 EQU 0BFE9H ; здесь в ДОС адрес ABORT
JBFEB EQU 0BFEBH ; здесь код C3 (команда JMP)
YBFEC EQU 0BFECH ; здесь AC6CD
JERROR EQU 0BEF0H ; здесь код C3 (сюда переход при ошибках дисковых операций)
YBEF1 EQU 0BEF1H ; здесь в ДОС адрес ABORT
; ----------------------------------------------
.msg MACRO ADDR
LD HL,ADDR
CALL MSSG
ENDM
; ----------------------------------------------
.msg_B MACRO SIZE
LD B,SIZE
CALL MSSG_B
ENDM
; ----------------------------------------------
.emit MACRO SYM
LD C,SYM
CALL MCOUT
ENDM
; ----------------------------------------------
.home MACRO ; процедура HOME
XOR A ; она исп-ся 4 раза, лучше сделать п/п-му HOME
LD (TRACK),A
INC A
LD (SECTOR),A
ENDM
; ----------------------------------------------
INCLOC MACRO LOC
LD A,(LOC)
INC A
LD (LOC),A
ENDM
; ----------------------------------------------
.phase 0C000H
JP START
; ----------------------------------------------
SREAD: LD B,32 ; число попыток чтения сектора каталога
AC005: DI
PUSH HL
CALL SREAD1
POP HL
IN A,(RGCOM)
AND 00011100B
EI
RET Z
DEC B ; DJNZ
JP NZ,AC005
JP ERROR
; ----------------------------------------------
SREAD1: LD A,(SECTOR)
OUT (RGSEC),A
JP SREAD2
; ----------------------------------------------
JP CMPDH ; для совместимости с прежними версиями
; ----------------------------------------------
SREAD2: LD C,0C0H
LD A,(SIDE)
OR A
LD A,82H
JP Z,JJJ_01
LD A,8AH
JJJ_01: CALL EXEC
JP RD_LOO ; && перенести сюда процедуру RD_LOO
; ----------------------------------------------
defb 255,255,255,255
; ----------------------------------------------
SWRITE: LD B,32 ; число попыток записи
AC03C: DI
PUSH HL
CALL SWRIT1
POP HL
IN A,(RGCOM)
AND 01111100B
EI
RET Z
JP AC105
; ----------------------------------------------
SWRIT1: LD A,(SECTOR)
OUT (RGSEC),A
LD C,0C0H
LD A,(SIDE)
OR A
LD A,0A2H
JP Z,AC05D
LD A,0AAH
AC05D: ; физическая запись сектора
CALL EXEC
WR_LOO: IN A,(RG_UPR)
AND C
JP Z,WR_LOO
LD A,(HL)
OUT (RGDATA),A
INC HL
JP P,WR_LOO
RET
; ----------------------------------------------
PODGOT: ; подготовка дисковых операций
PUSH HL ; установка головки на требуемую дорожку
PUSH BC ; в HL куда грузить
LD C,10
LD HL,CURDSK
LD A,(DISK)
CP (HL)
JP Z,AC080
LD (HL),A
AC07D: CALL SELDSK
AC080: LD A,(TRACK)
OR A ; CY=0
RRA
LD (FIZTRK),A
LD A,0
RLA
LD (SIDE),A
OR A
LD A,(HL)
LD B,00001100B
JP NZ,AC097 ; если сторона 1
LD B,00011100B ; бит стороны в контроллере инвертированный
AC097: OR B
LD B,A
INC HL
INC HL
LD A,(HL)
OR A
JP Z,AC63D
AC0A0: LD A,B
XOR 01000000B
CALL AC656
JP AC632 ; && перенести сюда процедуру AC632
; ----------------------------------------------
defb 0
; ----------------------------------------------
LDNSEC: CALL PODGOT ; загрузить LENGTH секторов на
AC0AD: CALL SREAD
LD A,(LENGTH)
DEC A
RET Z
LD (LENGTH),A
CALL AC0C1
JP C,AC0AD
JP LDNSEC
; ----------------------------------------------
AC0C1: LD BC,100H ; Выход: CY
ADD HL,BC
PUSH HL
LD HL,SECTOR
LD A,(YBFB8)
INC (HL)
CP (HL)
JP NC,AC0F7
LD (HL),1 ; первый сектор трека: SECTOR= 1
DEC HL ; теперь HL указывет на TRACK
LD A,(HL)
CP 164 ; превышен последний трек ?
JP AC0F3 ; && перенести сюда процедуру AC0F3
; ----------------------------------------------
defb 255,255
; ----------------------------------------------
WRNSEC: CALL PODGOT
AC0DF: CALL SWRITE
LD A,(LENGTH)
DEC A
RET Z
LD (LENGTH),A
CALL AC0C1
JP C,AC0DF
JP WRNSEC
; ----------------------------------------------
AC0F3: JP NC,ERROR
INC (HL)
AC0F7: CCF
POP HL
RET
; ----------------------------------------------
AC0FA: CALL EXEC
CALL READY
IN A,(RGCOM)
AND 00011000B
RET
; ----------------------------------------------
AC105: DEC B
JP NZ,AC03C ; DJNZ
JP ERROR
; ----------------------------------------------
defb 255,255
; ----------------------------------------------
RD_DIR: CALL PODGOT ; читаем сектор каталога
AC111: PUSH HL
LD HL,DIRBUF
CALL SREAD
POP HL
RET
; ----------------------------------------------
WR_DIR: PUSH HL ; запись сектора каталога
LD HL,DIRBUF
CALL PODGOT
CALL SWRITE
POP HL
RET
; ----------------------------------------------
FIND: ; поиск файла в каталоге
.home ; если файл найден, то загрузка пар-ров файла в область RECORD
FNLOO1: CALL RD_DIR
LD HL,DIRBUF
FNLOO2: PUSH HL
PUSH DE
CALL CMPSTR
POP DE
POP HL
OR A
RET Z
CP 1 ; имена были равны?
JP Z,AC17F ; если равны, на загрузку пар-ров файла в область RECORD
LD BC,17 ; шаг каталоговых записей
ADD HL,BC ; к следующей каталоговой записи в DIR-буфере
LD A,L
CP 0FFH ; была последняя запись сектора ? (кстати, короче INC A)
JP NZ,FNLOO2
INCLOC SECTOR ; на следующий сектор
CP 10 ; был последний сектор трека ?
JP C,FNLOO1 ; если был не последний сектор
RET_A2: LD A,2
RET
; ----------------------------------------------
CMPSTR: LD A,(HL) ; Сравнение двух имён длиной 11 символов (всез значащие)
OR A ; Выход: A=1, если строки сравнились O'KAY
RET Z ; A=2, если строки неодинаковые
LD C,11
CMPLOO: LD A,(DE) ; сравнение строк по (HL) и (DE) длиной из C
CP (HL)
JP NZ,RET_A2
INC HL
INC DE
DEC C
JP RETZA1 ; && перенести сюда процедуру RETZA1
; ----------------------------------------------
defb 0
; ----------------------------------------------
LD A,E ; ?? бредятина
CP 0FFH
JP Z,65CH
CP B
JP C,0F065H
JP 0F168H
; ----------------------------------------------
RETZA1: JP NZ,CMPLOO
LD A,1
RET
; ----------------------------------------------
AC17F: EX DE,HL ; DE= откуда
LD HL,RECORD ; куда
LD BC,17 ; сколько (это длина каталоговой записи)
CALL TRANS
LD A,1
RET
; ----------------------------------------------
LOAD: LD DE,FNAME
AC18F: CALL FIND
CP 1
RET NZ ; если такого файла нет
CALL PODG_W ; на выходе HL= адрес начала блока
CALL LDNSEC
LD HL,(F_BEGA)
CALL CHKEXE ; проверить атрибут запуска файла
RET Z
POP AF
JP (HL)
; ----------------------------------------------
PODG_W: LD A,(FF_SEC) ; подготовка к записи файла
LD (SECTOR),A
LD A,(FF_TRK)
LD (TRACK),A
LD A,(F_NSEC)
LD (LENGTH),A
LD HL,(F_BEGA)
RET
; ----------------------------------------------
@C1BA:
RDDPRM: ; считать параметры всего диска в область D_PARM
.home
CALL RD_DIR
LD HL,D_PARM ; куда
LD DE,DIRBUF ; откуда
LD BC,16 ; сколько
JP TRANS
; ----------------------------------------------
SAVE: ; запись целого файла
CALL RDDPRM ; читаем общие параметры диска в D_PARM
LD A,(DISKRO)
OR A
RET NZ ; если диск R/O
LD DE,FNAME ; проверяем есть ли уже такой файл
CALL FIND ; на выходе HL указывает на запись в DIRBUF
OR A
RET NZ ; если такой файл уже есть
; HL указывает на конец списка файлов в DIRBUF
LD A,(FR_SEC)
LD (FF_SEC),A ; пишем файл на DISK TOP
LD A,(FR_TRK)
LD (FF_TRK),A
XOR A
LD (F_ATTR),A ; атрибут файла R/W
; HL откуда, указывает на конец списка файлов в DIRBUF
LD DE,FNAME ; куда
LD BC,17 ; сколько (длина каталоговой записи)
CALL TRANS ; копирует из FNAME в DIRBUF на место записи
CALL WR_DIR ; обновляем сектор каталога (куда добавлена нов.запись)
CALL PODG_W
CALL WRNSEC ; пишем сам файл
LD A,(SECTOR)
INC A
CP 10 ; был последний сектор ?
JP Z,AC231 ; если ДА
LD (FR_SEC),A ; ставим новый DISK TOP
LD A,(TRACK)
AC212: LD (FR_TRK),A ; ставим новый DISK TOP
.home ; читаем первый сектор и пишем его с новыми параметрами
CALL RD_DIR
LD HL,DIRBUF ; куда
LD DE,D_PARM ; откуда
LD BC,16 ; сколько
CALL TRANS
CALL WR_DIR ; пишем обновлённый первый сектор
XOR A
RET
; ----------------------------------------------
AC231: LD A,1 ; переход на следующий трек при записи
LD (FR_SEC),A
LD A,(TRACK)
CP 164 ; последний трек ?
CALL Z,WRFSEC ; если ДА, то на запись N сектора указателя DISK TOP и RET
INC A
JP AC212 ; на чтение первого сектора и запись его с новыми параметрами
; ----------------------------------------------
MSSG_B: .emit (HL) ; вывод Z-строки длиной в B-символов
INC HL
DEC B ; поменяв на JP NZ можно использовать DJNZ
RET Z
JP MSSG_B
; ----------------------------------------------
TDNAME: defb 'ИМЯ ДИСКА: ',0
; ----------------------------------------------
XDIR: ; вывод каталога диска
CALL RDDPRM ; читаем общие параметры диска в D_PARM
LD A,(CLOSED)
OR A
RET NZ
.msg TDNAME ; выводим текст 'ИМЯ ДИСКА: '
LD HL,DSKNAM ; выводим само имя дискеты
.msg_B 10
CALL CR ; на начало следующей строки
LD HL,DIRBUF +17 ; начало списка файлов в 1-м секторе (первые 17 байт - пар-ры диска)
DIRLOO: LD A,(HL)
OR A
RET Z
CALL AC2BF
CP 0FFH
CALL Z,AC2AE
CP 10
RET Z
LD A,E
CP 1
JP Z,DIRLOO
CALL SPACE
.emit ':'
CALL SPACE
AC294: LD A,(HL)
OR A
RET Z
CALL AC2BF
CP 0FFH
CALL Z,AC2AE
CP 10
RET Z
LD A,E
CP 1
JP Z,AC294
CALL CR
JP DIRLOO
; ----------------------------------------------
AC2AE: INCLOC SECTOR
CP 10 ; был последний сектор трека ?
RET Z
CALL AC111
LD HL,DIRBUF
RET
; ----------------------------------------------
AC2BF: LD A,(HL)
CP 1
JP Z,AC2EA
PUSH HL
LD BC,11
ADD HL,BC
LD A,(HL)
POP HL
CP 2
JP NC,AC2EA
PUSH HL
.msg_B 8
.emit '.'
.msg_B 3
POP HL
LD E,0
HLADD17: ; переходим к следующей записи в каталоге
LD BC,17 ; шаг каталоговых записей
ADD HL,BC
LD A,L
RET
; ----------------------------------------------
AC2EA: LD E,1
JP HLADD17
; ----------------------------------------------
SEL_A: XOR A
LD (DISK),A
LD (CURDSK),A
SELDSK: XOR A ; установка диска CURDSK и проверка готовности
OUT (RG_UPR),A
LD A,(CURDSK)
LD B,00011100B ; не понял, зачем грузить маску в рег.B
OR B
OUT (RG_UPR),A
LD A,0D8H
CALL EXEC
AC306: IN A,(RGCOM)
RRA
JP C,AC306
LD A,8
CALL EXEC
CALL READY
CALL YE260
JP YE260
; ----------------------------------------------
READY: IN A,(RGCOM) ; ждём готовности
RLA
JP C,READY
READY1: IN A,(RGCOM)
RRA
JP C,READY1
RET
; ----------------------------------------------
AC327: LD DE,TCMND
LD A,D ; A= 0C3H
LD (EXEFLG),A ; не 0, запуск файлa разрешён
JP AC18F
; ----------------------------------------------
TCMND: defb 'COMMAND COM' ; имя автостартующего при старте DOS файла
TITR: defb 'CHAMELEON-DOS 7.7',13
defb '(C)MASKSOFT&144KБ',13,0
; ----------------------------------------------
AC361: XOR A
LD (YBE38),A ; похоже флаг горячего старта
CALL YEBD0 ; возможно инициализация чего-то
CCP: ; вход в командный процессор DOS
LD SP,STACK
.msg TITR
CALL SEL_A
CALL V_INIT ; инициализация векторов ошибок
CALL RDDPRM ; читаем общие параметры диска в D_PARM
CALL AC327
ABORT:
LD SP,STACK
CALL V_INIT ; инициализация векторов ошибок
CALL RDDPRM ; читаем общие параметры диска в D_PARM
CALL CR ; на начало следующей строки
LD A,(DISK)
ADD A,'A'
.emit A
.emit ':'
.emit '>'
LD HL,CMDBUF ; буфер ввода команд
PUSH HL
LD BC,15 ; длина блока (здесь длина ком.строки)
LD E,20H ; чем заполнять
CALL FILL_E
POP HL
; HL буфер ввода команд
CALL MF806 ; первое слово можно ввести ключевой клавишей
CP 7 ; клавиша <F0>
JP Z,ZDIR
CP 12H
JP Z,ZSAVE
CP 15H ; клавиша <F1>
JP Z,BLOAD
CP 16H ; клавиша <F3>
JP Z,RENAME
CP 14H ; клавиша <F4>
JP Z,ERA
CP 13H ; клавиша <F5>
JP Z,TYPE
CP 6 ; клавиша <П/Д>
JP Z,RUNCPM
CP 0BH
JP Z,YE14A
CP 0CH
JP Z,CMD_0C
LD (HL),A
CALL COUTA
INC HL
AC3DE: CALL MCONIN
CP 7FH
JP Z,ZABOJ
CP 13
JP Z,AC40A
LD (HL),A
CALL COUTA
LD A,L
CP 15 + low CMDBUF
JP NC,AC3DE
INC HL
JP AC3DE
; ----------------------------------------------
ZABOJ: LD A,L
OR A
JP Z,AC3DE
DEC HL
.emit 7FH
LD A,20H
LD (HL),A
JP AC3DE
; ----------------------------------------------
AC40A: DEC HL
LD A,(HL)
CP ':'
JP NZ,AC420
DEC HL
LD A,(HL)
SUB 'A'
CP 4
JP NC,ABORT
LD (DISK),A
JP ABORT
; ----------------------------------------------
AC420: LD HL,FNAME ; куда
LD DE,CMDBUF ; откуда
LD BC,8 ; сколько
CALL TRANS
LD (HL),'C' ; короче на 5 байтов CALL MOVCOM
INC HL
LD (HL),'O'
INC HL
LD (HL),'M'
LD A,1
LD (EXEFLG),A
CALL LOAD
JP NO_FND ; && перенести сюда процедуру NO_FND
; ----------------------------------------------
ZDIR: .msg TDIR
CALL WAITWK ; ждём нажатия <ВК>
CALL XDIR
JP JBFE8
; ----------------------------------------------
WAITWK: CALL MCONIN
CP 13
JP Z,CR ; если <ВК>, то на начало следующей строки
JP WAITWK
; ----------------------------------------------
BLOAD: .msg TLOAD
CALL WAITWK
LD HL,NAME1
LD BC,6 ; длина заполняемого блока
LD E,20H ; чем заполнять
CALL FILL_E
CALL YDD94 ; загрузка МГ-файла
LD HL,(YBEA9)
JP (HL)
; ----------------------------------------------
ASCHEX: SUB 30H ; из ASCII получить HEX-число
CP 10H
RET C
SUB 7
RET
; ----------------------------------------------
IS_HEX: CP 30H
JP C,RETCY1
CP 3AH
JP C,RETCY0
CP 'A'
JP C,RETCY1
CP 'G'
JP NC,RETCY1
RETCY0:
OR A
RET
; ----------------------------------------------
RETCY1: SCF
RET
; ----------------------------------------------
GETHEX: PUSH HL ; считывает из F806 и выводит HEX-число
CALL MF806
CALL IS_HEX
JP C,SYNTAX
LD H,A
CALL COUTA
CALL MF806
CALL IS_HEX
JP C,SYNTAX
LD L,A
CALL COUTA
LD A,L
CALL ASCHEX
LD B,A
LD A,H
CALL ASCHEX
RLCA
RLCA
RLCA
RLCA
OR B
POP HL
RET
; ----------------------------------------------
GET_HL: CALL GETHEX
LD H,A
CALL GETHEX
LD L,A
RET
; ----------------------------------------------
COUTA: LD C,A
JP MCOUT
; ----------------------------------------------
GETNAM: LD HL,FNAME ; считывает имя файла из п/п-ммы F806 на FNAME
AC4CF: CALL MF806
CP 13H
JP Z,SYNTAX
LD (HL),A
CALL COUTA
LD A,L
CP (low FNAME) +7 ; 26H
INC HL
JP C,AC4CF ; если введено не более 8 символов
.emit '.'
AC4E7: CALL MF806
CP 13H
JP Z,SYNTAX
LD (HL),A
CALL COUTA
INC HL
LD A,L
CP (low FNAME) +11 ; 2AH
RET NC ; если был последний 12-тый символ в имени
JP AC4E7
; ----------------------------------------------
SPACE: LD C,20H
JP MCOUT
; ----------------------------------------------
CR: LD C,13 ; на начало следующей строки
JP MCOUT
; ----------------------------------------------
ZSAVE: .msg TSAVE
CALL GETNAM ; считывает имя файла из п/п-ммы F806
CALL SPACE
CALL GET_HL
PUSH HL
LD (F_BEGA),HL
CALL SPACE
CALL GET_HL
EX DE,HL
POP HL
CALL GET_NS ; расчёт длины файла в секторах. Блок: HL...DE
CALL WAITWK
CALL SAVE
OR A
JP NZ,NOSAVE
JP JBFE8
; ----------------------------------------------
ERROR: .msg TEROR
JP JERROR
; ----------------------------------------------
NO_FND: LD HL,TNOFIL
MSGEXI: CALL MSSG
JP JBFE8
; ----------------------------------------------
NOSAVE: LD HL,TNOSAV
JP MSGEXI
; ----------------------------------------------
SYNTAX: LD HL,TSNERR ; синтаксическая ошибка в команде
JP MSGEXI
; ----------------------------------------------
TEROR: defb 13,'*ERORR I/O*',13,0
TDIR: defb 'DIR',0
TLOAD: defb 'LOAD ',0
TSAVE: defb 'SAVE ',0
TERA: defb 'ERA ',0
TREN: defb 'REN ',0
TNOFIL: defb 13,'*NO FILE*',0
TNOSAV: defb 13,'*NO SAVE*',0
TTYPE: defb 'TYPE ',0
TSNERR: defb 13,'*SN.ERROR*',0
; ----------------------------------------------
ERA: .msg TERA
CALL GETNAM ; считывает имя файла из п/п-ммы F806
CALL WAITWK
LD DE,FNAME
CALL FIND
CP 1 ; короче DEC A
JP NZ,NO_FND
EX DE,HL ; DE указывает на следующую запись файла в DIRBUF
LD BC,17 ; шаг каталоговых записей
CALL DSUB_B
PUSH HL ; HL указывает на начало каталоговой записи
LD BC,11 ; смещение в каталоговой записи до атрибута
ADD HL,BC
LD A,(HL) ; A= атрибут файла
POP HL ; HL указывает на начало каталоговой записи
CP 1
JP NC,NO_FND ; если файл R/O
LD A,1 ; короче LD (HL),1
LD (HL),A ; удаляем файл, записав 1 первым символом имени
CALL WR_DIR ; пишем обновлённый первый сектор
JP JBFE8
; ----------------------------------------------
RENAME: .msg TREN
CALL GETNAM ; считывает имя файла из п/п-ммы F806
LD HL,CMDBUF
LD DE,FNAME
LD BC,11
CALL TRANS
.emit '='
CALL GETNAM ; считывает имя файла из п/п-ммы F806
LD DE,FNAME
CALL FIND
CP 1
JP NZ,NO_FND
EX DE,HL
LD BC,17 ; шаг каталоговых записей
CALL DSUB_B ; вернём указатель HL на найденный файл в DIRBUF
LD DE,CMDBUF ; откуда
LD BC,11 ; сколько
CALL TRANS ; скопируем новое имя в каталоговую запись в DIRBUF
CALL WR_DIR ; обновляем сектор каталога
JP JBFE8
; ----------------------------------------------
@C60F:
DSUB_B: LD A,L ; вычитание HL минус BC
SUB C
LD L,A
LD A,H
SBC A,B
LD H,A
RET
; ----------------------------------------------
TYPE: .msg TTYPE
LD (EXEFLG),A ; A=0 запуск файлa запрещён
CALL GETNAM ; считывает имя файла из п/п-ммы F806
CALL WAITWK
CALL LOAD
DEC A
JP NZ,NO_FND
LD HL,(F_BEGA)
JP MSGEXI
; ----------------------------------------------
AC632: LD (HL),1
JP NZ,AC64C
DEC HL ; HL указывает на SECTOR
LD (HL),9
POP BC
POP HL ; в HL куда грузить
RET
; ----------------------------------------------
AC63D: LD A,B
CALL AC656
JP NZ,AC0A0
LD (HL),0
DEC HL
LD (HL),10H
POP BC
POP HL
RET
; ----------------------------------------------
AC64C: DEC (HL)
DEC HL
DEC HL
DEC C
JP NZ,AC07D
JP ERROR
; ----------------------------------------------
AC656: OUT (RG_UPR),A
CALL PAUS15
LD A,(FIZTRK)
OUT (RGDATA),A ; ?? а не должно тут быть RGTRK
LD A,1CH ; команда для ВГ93
JP AC0FA ; && перенести сюда процедуру AC0FA
; ----------------------------------------------
START: OUT (0),A
LD SP,0BF99H ; начальный стек
LD A,88H
OUT (0C3H),A
LD A,8AH
OUT (0D3H),A
LD A,2
OUT (0C2H),A
LD A,8FH
OUT (0C1H),A
LD A,0BFH
OUT (0D0H),A
IN A,(0D1H)
CP 0FBH
JP NZ,AC696
LD HL,0000
AC688: LD A,(HL)
CPL
LD (HL),A
CP (HL)
JP NZ,YE043
INC HL
LD A,H
CP 0C0H
JP NZ,AC688
AC696: CALL AC786
LD A,0DFH
OUT (0D0H),A
IN A,(0D1H)
CP 7FH
JP Z,AC6AA
LD HL,AC6CD
LD (YBFEC),HL
AC6AA: LD A,0C3H
LD (JBFEB),A
LD HL,0B000H
LD BC,0EEFH
LD E,0
CALL FILL_E
LD HL,YB880
LD (YBE40),HL
LD A,1
LD (YBE3A),A
LD A,255
LD (YBE1E),A
JP 0E0F5H
; ----------------------------------------------
AC6CD: LD HL,DIRBUF ; откуда
LD DE,80C0H ; куда
LD BC,100H ; сколько
PUSH HL
PUSH DE
PUSH BC
CALL TRANS
CALL AC777
POP BC
POP HL
POP DE
CALL TRANS
JP AC361
; ----------------------------------------------
defb 0
; ----------------------------------------------
@C6E9:
GET_NS: PUSH HL ; расчёт длины файла в секторах. Блок: HL...DE
PUSH DE ; заносит рассчитанную длину в RECORD
LD A,1
LD (F_NSEC),A ; начиная с одного сектора
CALL GNSLOO ; здесь п/п-мма не нужна (теряем байт)
POP DE
POP HL
RET
; ----------------------------------------------
GNSLOO: LD BC,256
ADD HL,BC
CALL CMPDH ; сравнение HL и DE (CMPDH)
RET NC ; если достигнут или превышен конечный адрес
LD A,(F_NSEC)
INC A
LD (F_NSEC),A
JP GNSLOO
; ----------------------------------------------
@C708:
RUNCPM: .home
LD A,31 ; длина файла в секторах
LD (LENGTH),A
LD HL,9000H ; куда грузим
CALL LDNSEC
JP 0A600H
; ----------------------------------------------
AC71E: ; формирование имени DOS-файла из имени МГ-файла
LD DE,NAME1 ; откуда
JP FNFORM
; ----------------------------------------------
LD DE,NAME2 ; откуда
FNFORM: LD HL,FNAME ; куда
LD BC,6 ; сколько
CALL TRANS
LD (HL),20H
INC HL
LD (HL),20H
INC HL
MOVCOM: LD (HL),'C'
INC HL
LD (HL),'O'
INC HL
LD (HL),'M'
RET
; ----------------------------------------------
AC73F:
CALL AC71E ; формирование имени DOS-файла из имени МГ-файла
LD HL,(ENDADR)
EX DE,HL
LD HL,(BEGADR) ; адреса начала и конца блока в HL,DE
LD (F_BEGA),HL ; готовим каталоговую запись в RECORD
CALL GET_NS ; расчёт длины файла в секторах. Блок: HL...DE
JP SAVE ; && перенести сюда процедуру SAVE
; ----------------------------------------------
AC752: ; загрузка и запуск COM-файла
CALL AC71E ; формирование имени DOS-файла из имени МГ-файла
XOR A
LD (EXEFLG),A ; =0 запуск файлa запрещён
JP LOAD
; ----------------------------------------------
V_INIT: LD A,0C3H ; инициализация векторов ошибок
LD (JBFE8),A
LD (JERROR),A
LD (JBFEB),A
LD HL,ABORT
LD (YBEF1),HL
LD (YBFE9),HL
LD HL,CCP
LD (YBFEC),HL
RET
; ----------------------------------------------
AC777: LD HL,80C0H ; запуск
LD DE,YFCA6
LD BC,0EAH ; 234 дес
CALL TRANS
JP 80D4H
; ----------------------------------------------
AC786: CP 0F7H
RET NZ
LD HL,YB880
LD (YBE40),HL
LD C,33H
CALL YE6AA
LD C,17H
CALL YE6A3
JP YE627
; ----------------------------------------------
defb 80H
; ----------------------------------------------
; Входы в функции ДОС
@C79D: JP PODGOT ; подготовка
@C7A0: JP SREAD ; читать сетор
@C7A3: JP SWRITE ; запись сектора
@C7A6: JP LDNSEC ; считать LENGTH секторов
@C7A9: JP WRNSEC ; записать LENGTH секторов
@C7AC: JP FIND ; поиск файла и чтение его каталоговой записи
@C7AF: JP LOAD ; загрузка файла
@C7B2: JP SAVE ; запись файла
@C7B5: JP XDIR ; вывод каталога диска
@C7B8: JP ERA ; удаление файла
@C7BB: JP RENAME ; переименование файла
@C7BE: JP TYPE ; вывод текстового файла на экран
@C7C1: JP ZSAVE ; запись файла с вводом командной строки
@C7C4: JP GETHEX ; считать однобайтовое HEX-число
@C7C7: JP GETNAM ; считывает имя файла из п/п-ммы F806
@C7CA: JP GET_HL ; считать двухбайтовое HEX-число
@C7CD: JP AC752
@C7D0: JP AC73F
; ----------------------------------------------
CMD_0C: LD A,165
LD (TRACK),A
CALL PODGOT
JP AC361 ; && перенести сюда процедуру AC361
; ----------------------------------------------
CHKEXE: LD A,(EXEFLG) ; проверить атрибут запуска файла
OR A ; Выход: флаг Z=1, если запуск файлa запрещён
LD A,1
RET Z
RET
; ----------------------------------------------
RD_LOO: IN A,(RG_UPR) ; физическое чтение сектора
AND C
JP Z,RD_LOO
IN A,(RGDATA)
RET M
LD (HL),A
INC HL
JP RD_LOO
; ----------------------------------------------
EXEC: OUT (RGCOM),A
PAUS15: LD A,15
JP PAUS_A
; ----------------------------------------------
defb 0
; ----------------------------------------------
WRFSEC: LD (FR_SEC),A ; записать N сектора указателя DISK TOP
RET
; ----------------------------------------------
.dephase
END