if 0
TEMP_SEC EQU #5CF4
SEC_LEN EQU #5CEA
SECTOR EQU #5CEB
TRACK EQU #5CEC
FILENAME EQU #5CDD
FILEEXT EQU #5CE5
FREE EQU #E5 ;смещение в секторе 9, где
;находится количество свободных секторов
FREESECT EQU #E1; смещение в секторе 9,
;где находится первый свободный трек и
;сектор
endif
if 0
IF atm
TRDOS
PUSH AF
PUSH BC
PUSH HL
CALL ATMOFF
POP HL
POP BC
POP AF
CALL #3D13
PUSH AF
PUSH BC
PUSH HL
CALL ATMON
POP HL
POP BC
POP AF
RET
ELSE
TRDOS EQU #3D13
ENDIF
endif
dosunit
SCF
RET
st_close
LD A,(tsflag)
AND A
CALL NZ,ts_close
SCF
RET
dosinit
;0x705C содержит имя файла с точкой, в конце 0xff,'$'
;хэндл файла надо сохранить в STORY
;потом переделать имя файла в 8.3 с точкой, в конце 0xff,'$'
if 1
else
LD B,8 ;Заполняем восмью
LD HL,FILENAME ;пробелами
MET7 LD (HL),#20 ;имя файла
INC HL
DJNZ MET7
;Перенос информации в область
;переменных DOS'а
LD BC,FILENAME ;Нормально рабо-
LD HL,#705C ;тающий, безглючный
MET6 LD A,(HL) ;определитель имени
CP #FF
JP Z,END1 ;Точка должна быть
CP "." ;только одна
JP NZ,MET5
LD BC,FILEEXT
INC HL
LD A,(HL)
MET5 LD (BC),A
INC BC
INC HL
JP MET6
END1
AND A
PUSH BC
POP HL
LD BC,FILENAME
SBC HL,BC
LD A,L ;количество байтов маски
;Поиск файла в каталоге по
;маске "имя.ext"
LD C,#0A
LD (23814),A
CALL TRDOS
;Чтение полного заголовка файла
LD A,C
LD (STORY),A
LD C,#08
CALL TRDOS
;Перенос из дескриптора в #705c
;Нужно для нормального вывода на экран
;имени файла, а не его огрызка
LD HL,#705C
LD C,#14
CALL TRDOS
LD A,(#7065)
LD (#7066),A
LD A,(#7064)
LD (#7065),A
LD HL,#7064
LD (HL),"."
LD HL,#7067
LD (HL),#FF ;Такие требования
INC HL ;идут в ZXZVM +3
LD (HL),"$"
endif
SCF
RET
st_reload
;???
XOR A ; в 6-й банке (буфер) ничего
LD (BUFMEM),A ;нет
LD HL,(REAL_LEN2) ;восстанавливаем
LD (REAL_LEN),HL ;реальную длину
if 1
else
LD A,(STORY) ;считывание заголовка
LD C,#08
CALL TRDOS
endif
CALL RRR ;считываем первые 64 Кб
;z-памяти (динамическая память)
SCF
RET
st_open
MET4 LD A,(BANKM) ;На всякий случай
LD (TEMPBANKA),A ;запоминаем какая
;банка и в каком режиме была включена
if 1
ld hl,0x705C
ld d,h
ld e,l
ld a,0xff
ld b,1
cpir
dec hl
push hl
inc (hl);0x00 для ASCIIZ
OS_OPENHANDLE
ld a,b
ld (STORY),a
OS_GETFILESIZE ;dehl=file size
ld l,h
ld h,e
LD (REAL_LEN),HL
LD (REAL_LEN2),HL
pop hl
dec (hl);0xff как было
else
LD A,(STORY)
LD C,#08
CALL TRDOS
LD A,(SEC_LEN)
CP #FF ;Сравниваем, а не нужна ли
;проверка на наличие дополнительных
;файлов к основному (ext = 0,1,2,...)
LD E,A
LD D,#00
LD (REAL_LEN),DE
LD (REAL_LEN2),DE
CALL Z,real_len
LD A,(STORY) ;Т.к. после вызова
LD C,#08 ;real_len дескриптор мог
CALL TRDOS ;измениться восстанав-
;ливаем дескриптор основного файла
LD HL,(SECTOR) ;трек и сектор
LD (FILE_BEGIN),HL ;начала файла
endif
RRR LD HL,BankN
LD (WHERE),HL
;сюда переходим при рестарте
MET3
;LD DE,(SECTOR) ;FIXME?
;помещаем информацию о треке и
;секторе файла
LD HL,(WHERE)
LD A,(HL)
CP BANKN_TERMINATOR;#02
JR Z,LOADED64K ;Загружены все
;банки (не только 64к), переход на конец
;загрузки файла
CALL selmem; Переключаем страницу
;для загрузки в нее данных
INC HL
LD (WHERE),HL
LD HL,(REAL_LEN)
LD BC,#0040
; #40 = 64 сектора = страница
;количество секторов файла
AND A
SBC HL,BC
JR Z,MET2
JR C,MET2
LD (REAL_LEN),HL
if 1
ld hl,0x4000
ld de,0xc000
ld a,(STORY)
ld b,a
OS_READHANDLE
else
LD B,64
LD A,(TRACK)
ADD A,#04
LD (TRACK),A
CALL READ ;DE брали из переменной TR-DOS, т.е. продолжаем читать файл
endif
JP MET3
MET2 LD A,(REAL_LEN) ;Все влезло в
;доступные банки, посему загружаем
;остаток и спокойно идем дальше
if 1
ld hl,0x4000
ld de,0xc000
ld a,(STORY)
ld b,a
OS_READHANDLE
else
LD B,A
CALL READ
endif
LOADED64K LD A,(TEMPBANKA)
CALL selmem
LD A,BANKN_TERMINATOR;#02 ;для возможности
LD (BankN+4),A ;restart'а
SCF
RET
if 0
READ LD HL,#C000 ;Чтение группы
LD C,#05 ;секторов
CALL TRDOS
RET
endif
if 0
real_len
LD A,#30 ;Загоняем начальное
LD (EXT),A ;расширение '0'
LD HL,#705C ;переносим инфор-
LD C,#14 ;мацию из дескриптора
;файла в адрес #705c
CALL TRDOS
LD A,(STORY)
LD (TEMPSTORY),A
CYCLE3 LD A,(TEMPSTORY)
INC A
LD (TEMPSTORY),A
LD C,#08 ;Считываем следущий
CALL TRDOS;за игровым файл
;для дальнейщей его проверки
LD HL,#705C
LD DE,FILENAME
LD B,8
CYCLE2 LD C,(HL) ;Цикл проверки
LD A,(DE) ;Сравниваем имена
SUB C
RET NZ
INC HL
INC DE
DJNZ CYCLE2
LD A,(DE) ;Проверяем правиль-
LD C,A ;ность расширения
LD A,(EXT)
SUB C
RET NZ
LD A,(EXT)
INC A
LD (EXT),A
LD DE,(SEC_LEN)
LD D,#00
LD HL,(REAL_LEN)
ADD HL,DE
LD (REAL_LEN),HL
LD (REAL_LEN2),HL
JR CYCLE3
endif
if 0
st_peek
IF bigmem
PUSH HL
ENDIF
PUSH BC
PUSH DE
PUSH IX
;Вставить проверку на ошибку
LD A,H
LD HL,TEMP
LD (HL),A
LD A,E
RRD
LD A,(HL)
AND #FC
;#x0,#x1,#x2,#x3 -> #x0
;#x4,#x5,#x6,#x7 -> #x4
;#x8,#x9,#xA,#xB -> #x8
;#xC,#xD,#xE,#xF -> #xC
LD (BUFMEM),A
LD DE,(FILE_BEGIN)
ADD A,D
LD D,A
LD B,64 ;Загрузка в буфер
LD HL,#C000 ;нужной части памя-
LD C,#05 ;ти
CALL TRDOS
DI
LD HL,(HL_)
POP IX
POP DE
POP BC
IF bigmem
POP HL
ELSE
LD HL,(HL_)
ENDIF
RET
endif
;;;;;;
; Открытие и закрытие файла-отгрузки
;
if 0
init_name
;hl=name
LD C,#13 ;Переносим имя из
CALL TRDOS ;HL в системную
;область TR-DOS'а
LD A,#FF ;Находим конец имени
LD HL,FILENAME
LD BC,#0009
CPIR
LD B,C
INC B
DEC HL
CYCLE4 LD A,#20 ;и забиваем #FF и
LD (HL),A ;далее пробелами
INC HL
DEC B
JR NZ,CYCLE4
LD A,"!" ;устанавливаем рас-
LD (FILEEXT),A ;ширение '!'
RET
endif
;;;;;
;;;;;;;
p3read
PUSH AF
PUSH HL
PUSH BC
PUSH DE
PUSH IX
XOR A
LD (WHAT),A
CALL driver
POP IX
POP DE
POP BC
POP HL
POP AF
SCF
RET
;;;;;;
p3write
PUSH AF
PUSH HL
PUSH BC
PUSH DE
PUSH IX
LD A,#01
LD (WHAT),A
CALL driver
POP IX
POP DE
POP BC
POP HL
POP AF
SCF
RET
;;;;;;
p3rmem
PUSH AF
PUSH HL
PUSH BC
PUSH DE
PUSH IX
LD A,#02
LD (WHAT),A
CALL driver
POP IX
POP DE
POP BC
POP HL
POP AF
SCF
RET
;;;;;;;
p3wmem
PUSH AF
PUSH HL
PUSH BC
PUSH DE
PUSH IX
LD A,#03
LD (WHAT),A
CALL driver
POP IX
POP DE
POP BC
POP HL
POP AF
SCF
RET
;;;;;;;;;;
p3opn
PUSH AF ;сохраняем все регистры
PUSH HL ; (на всякий случай)
PUSH BC
PUSH DE
PUSH IX
if 0
LD A,#09 ;маска в 9 символов
LD (23814),A
endif
LD A,B ;b=0 - открыть файл
AND A ;b=1 - создать файл
JR NZ,createe
read ;для отгрузок
;hl=name
if 1
ld d,h
ld e,l
ld a,0xff
ld b,1
cpir
dec hl
push hl
inc (hl) ;0x00 для ASCIIZ
OS_OPENHANDLE
pop hl
dec (hl) ;0xff как было
or a
JR nz,NO_FILE
LD A,b ;запоминаем
LD (OPENFILE),A ;его
ld hl,0
ld (SECT),hl ;запоминаем начало файла
else
CALL init_name
LD C,#0A ;получаем номер файла
CALL TRDOS
LD A,C ;запоминаем
LD (OPENFILE),A ;его
CP #FF
JR Z,NO_FILE
LD C,#08 ;считываем полную
CALL TRDOS ;информацию о нем
LD HL,(SECTOR) ;запоминаем
LD (SECT),HL ;начало файла
endif
XOR A ;устанавливаем естественно
LD (SMESH),A ;смещение (внутри сектора) в ноль
POP IX
POP DE
POP BC
POP HL
POP AF
SCF
RET
NO_FILE POP IX
POP DE
POP BC
POP HL
POP AF
AND A
RET
createe ;для отгрузок
LD A,(tsflag)
AND A
CALL NZ,ts_close
if 1
;jr $
ld d,h
ld e,l
ld a,0xff
ld b,1
cpir
dec hl
push hl
inc (hl) ;0x00 для ASCIIZ
OS_CREATEHANDLE
pop hl
dec (hl) ;0xff как было
;or a
;JR nz,NO_FILE
LD A,b ;запоминаем
LD (OPENFILE),A ;его
ld hl,0
ld (SECT),hl ;запоминаем начало файла
else
CALL init_name
LD C,#12
CALL TRDOS
LD HL,#0000 ;создание заголовка
LD DE,#0001 ;файла
LD C,#0B
CALL TRDOS
LD HL,(SECTOR) ;запоминание на-
LD (FILEBEG),HL ;начального
LD (SECT),HL ;сектора
LD A,#09 ;установление маски
LD (23814),A ;длиной в 9 байт
LD C,#0A ;получение номера файла
CALL TRDOS ;в каталоге
LD A,C
LD (OPENFILE),A
endif
XOR A ;установление смещения в
LD (SMESH),A ;ноль
POP IX
POP DE
POP BC
POP HL
POP AF
SCF
RET
;;;;;;
if 0
NO17SEC LD A,L ;дабы не было 17-го
CP 16 ;сектора
RET C
SUB 16
LD L,A
INC H
RET
endif
;;;;
;Close file
;
p3clse
PUSH AF
PUSH HL
PUSH BC
PUSH DE
PUSH IX
LD A,(WHAT);если для открытия
AND A ;файла, то сразу переход
JR Z,FOR_OPEN ;на конец
if 1
ld a,(OPENFILE)
ld b,a
OS_CLOSEHANDLE
else
LD HL,(SECT) ;получаем информа-
INC HL ;цию о следущем свободном
;секторе
CALL NO17SEC
LD (SECT),HL
LD DE,#0008 ;считываем
LD BC,#0105 ;9-й (системный)
LD HL,BUFFER ;сектор
CALL TRDOS
LD HL,(SECT)
LD (BUFFER+FREESECT),HL
;записываем первый свободный трек
;и сектор
LD DE,(FILEBEG)
LD A,H ;длина файла в треках
SUB D ;без секторов
;!!!
SLA A ;получаем количество
SLA A ;секторов
SLA A
SLA A
SUB E ;получаем полное
ADD A,L;количество секторов
DEC A
PUSH AF
LD B,#00 ;вычисляем количество
LD C,A ;свободных секторов
LD HL,(BUFFER+FREE)
AND A
SBC HL,BC
LD (BUFFER+FREE),HL
LD HL,BUFFER ;сохраняем измене-
LD BC,#0106 ;ный 9-й сектор
LD DE,#0008
CALL TRDOS
LD A,(OPENFILE) ;получаем
LD C,#08 ;полную информацию о
CALL TRDOS ;открытом файле
POP AF
INC A ;сохраняем длину файла
LD (SEC_LEN),A ;в секторах
LD A,(OPENFILE) ;записываем
LD C,#09 ;измененный дескриптор
CALL TRDOS ;файла
endif
FOR_OPEN XOR A ;на всякий случай
LD (OPENFILE),A
POP IX
POP DE
POP BC
POP HL
POP AF
SCF
RET
;;;;;;
SMESH_ADD
LD B,#00
LD A,(SMESH)
LD C,A
ADD HL,BC
RET
;;;;;;;;;
load1
;переносим из
LD HL,BUFFER ;буфера нужную
CALL SMESH_ADD
LD DE,(ADRESS) ;нам информацию
LD BC,(BUFLEN)
LDIR
JP CONTINUE
load2
LD HL,BUFFER ;переносим из
CALL SMESH_ADD ;буфера нужную
LD DE,(ADRESS) ;нам информацию
LD BC,(BUFLEN)
LD A,C ;а не ноль ли в BC
OR B
JR Z,MMM
CYCLE1 LD A,(HL) ;этот цикл является
EX DE,HL ;фактически ldir'ом,
CALL poke1 ;только для z-memory
EX DE,HL
INC HL
INC DE
DEC BC
LD A,C
OR B
JR NZ,CYCLE1
MMM JP CONTINUE
save1
;переносим информацию из памяти
LD DE,BUFFER ;в буфер
EX DE,HL
CALL SMESH_ADD
EX DE,HL
LD BC,(BUFLEN)
LD HL,(ADRESS)
LDIR
if 1
ld hl,(SECT)
ld d,0
ld e,h
ld h,l
ld l,d;0
ld a,(OPENFILE)
ld b,a
OS_SEEKHANDLE
ld de,BUFFER
ld hl,0x0100
ld a,(OPENFILE)
ld b,a
OS_READHANDLE
else
LD BC,#0106 ;записываем сектор
LD DE,(SECT)
LD HL,BUFFER
CALL TRDOS
endif
JP CONTINUE
save2
;переносим информацию из памяти
LD DE,BUFFER ;в буфер
EX DE,HL
CALL SMESH_ADD
EX DE,HL
LD HL,(ADRESS)
LD BC,(BUFLEN)
LD A,C
OR B
JR Z,MMM1
CYCLE5 CALL peek64 ;этот цикл
EX DE,HL ;фактически является
LD (HL),A ;ldir'ом
EX DE,HL
INC HL
INC DE
DEC BC
LD A,B
OR C
JR NZ,CYCLE5
if 1
ld hl,(SECT)
ld d,0
ld e,h
ld h,l
ld l,d;0
ld a,(OPENFILE)
ld b,a
OS_SEEKHANDLE
ld de,BUFFER
ld hl,0x0100
ld a,(OPENFILE)
ld b,a
OS_READHANDLE
else
LD BC,#0106 ;записываем сектор
LD DE,(SECT)
LD HL,BUFFER
CALL TRDOS
endif
MMM1 JP CONTINUE
;;;;;;;;;;;;;;;;;;;;
;
;Read/write savefile
;
driver
LD A,B ;если передали
OR C ;длину = 0, то сразу
SCF ;выход
RET Z
LD (ADRESS),HL ;сохраняем нужную
;для считывания адрес (куда считывать)
LD (LENGTH),BC ; и длину
;(сколько)
next
LD HL,#0100 ;получаем в HL
LD A,(SMESH)
LD B,#00
LD C,A ;количество байт до
AND A ;конца сектора
SBC HL,BC
LD (BUFLEN),HL
LD BC,(LENGTH)
AND A
SBC HL,BC ;сколько байт нужно
JR C,metka ;считать?
LD (BUFLEN),BC
metka
if 1
ld hl,(SECT)
ld d,0
ld e,h
ld h,l
ld l,d;0
ld a,(OPENFILE)
ld b,a
OS_SEEKHANDLE
ld de,BUFFER
ld hl,0x0100
ld a,(OPENFILE)
ld b,a
OS_READHANDLE
else
LD BC,#0105 ;считываем один сектор
LD HL,BUFFER ;в нужный буфер
LD DE,(SECT)
CALL TRDOS
endif
LD A,(WHAT)
CP #00
JP Z,load1; чтение в память из файла
CP #01
JP Z,save1; запись из памяти в файл
CP #02
JP Z,load2; чтение в Z-памяти в файл
CP #03
JP Z,save2; запись из Z-памяти в файл
CONTINUE LD HL,(ADRESS) ;устанавливаем
LD BC,(BUFLEN) ;следущий адрес
ADD HL,BC ;считывания
LD (ADRESS),HL
LD A,(SMESH) ;а также другое
LD H,#00
LD L,A
ADD HL,BC ;смещение в секторе
LD A,L
LD (SMESH),A
LD A,H ;и другой номер сектора
LD H,#00
LD L,A
LD BC,(SECT)
ADD HL,BC
;CALL NO17SEC
LD (SECT),HL
LD BC,(BUFLEN) ;и уменьшаем
LD HL,(LENGTH) ;общую длину
AND A ;считывания
SBC HL,BC
LD (LENGTH),HL
LD A,H ;а не равна ли длина
OR L ;нулю
SCF
RET Z ;если она равна нулю, то
;возврат
jp next
;
;;;;;;;;;;;;;;;;;;;;;
;
;Transcript functions (отгрузки)
;
ts_open
CALL ZXNAME
LD A,H
OR L
SCF
RET Z
LD B,#01
CALL p3opn
RET NC
LD A,#01
LD (tsflag),A
SCF
RET
;;;
ts_close
LD A,(tsflag)
OR A
SCF
RET Z
PUSH HL ;Т.к. участвует и при
PUSH BC ;создании файла
PUSH DE
LD HL,#0003
CALL ts_char
RET NC
LD A,(SMESH)
LD C,A
LD B,#00
LD HL,BUFFER
ADD HL,BC
CYCLE9 LD A,#20 ;' '
LD (HL),A
INC HL
INC C
JR NZ,CYCLE9
CALL full_buffer
LD A,#01
LD (WHAT),A
LD HL,(SECT)
DEC HL
LD (SECT),HL
CALL p3clse
RET NC
XOR A
LD (tsflag),A
POP DE
POP BC
POP HL
SCF
RET
;;;
ts_char
LD A,(tsflag)
OR A
SCF
RET Z
LD A,(cwin)
OR A
SCF
RET Z
LD A,L
PUSH AF
LD HL,BUFFER
LD B,#00
LD A,(SMESH); В SMESH в данном
LD C,A ;случае хранится смещение
ADD HL,BC ;в BUFFER (от 0 до FF)
POP AF
LD (HL),A
INC C
CALL Z,full_buffer
LD A,(SMESH)
INC A
LD (SMESH),A
SCF
RET
full_buffer
if 1
ld a,(OPENFILE)
ld b,a
ld hl,(SECT)
ld d,0
ld e,h
ld h,l
ld l,d;0
OS_SEEKHANDLE ;dehl=shift
ld a,(OPENFILE)
ld b,a
ld hl,0x0100
ld de,BUFFER
OS_WRITEHANDLE
LD HL,(SECT)
inc hl
LD (SECT),HL
else
LD BC,#0106
LD DE,(SECT)
LD HL,BUFFER
CALL TRDOS
LD HL,(TEMP_SEC)
LD (SECT),HL
endif
RET
OPENFILE DB #00 ;Номер открываемого
;файла
LENGTH DB #00,#00
;Длина какую надо считать/записать
ADRESS DB #00,#00
;Куда надо записывать/откуда считывать
SECT DB #00,#00
;Номер трека и сектора последовательного файла (или номер сектора в файле)
BUFFER DB #00
DUP 255
DB #00
EDUP
;Буфер для Save/Load
BUFLEN DB #00,#00
;Длина из буфера, которую надо перенести
SMESH DB #00
;Смещение внутри сектора (от 0 до FF)
WHAT DB #00 ; для чтения или для
;записи нужно это? 0=чтение; 1=запись
;FILEBEG DB #00,#00 ;начало файла-отгрузки
;;;;;;;;;;;;;;;;;;
if 0
EXT DB #30; проверочное расширение
; сначала равно '0'
endif
WHERE DB #00,#00; используется при
;начальной загрузке и рестарте (адрес в BankN+)
STORY DB #00 ;Номер игрового файла (хэндл)
BUFMEM DB #00 ; А для какого адреса
;Z-machine забита 6-я банка :
;содержится младшая часть E и старшая H
REAL_LEN DB #00, #00 ; действительная
;длина в секторах
if 0
TEMPSTORY DB #00 ;номер файла для прове-
;рки: не является ли он продолжением
;игрового
FILE_BEGIN DB #00,#00 ;трек и сектор
;начала игрового файла. Используется для
;подсчета длины файла при закрытии
;потока
endif
; ИСПОЛЬЗУЕТСЯ ДЛЯ RESTART'А
REAL_LEN2 DB #00,#00
tsflag
DEFB 0
;Transcripting on or off?