; LAST UPDATE: 21.03.2025 savelij
 
 
 
; ((out&0ffff)==37f7)&&((val&0ff)==1)
 
; ((out&0ffff)==77f7)&&((val&0ff)==1)
 
; ((out&0ffff)==0b7f7)&&((val&0ff)==1)
 
; ((out&0ffff)==0f7f7)&&((val&0ff)==1)
 
; ((M(5CF4)==2)&&(M(5CF5)==1B))
 
; (((M(5CF4)==2)&&(M(5CF5)==1B))&&(SP<4000))
 
; ((OUT&0FFFF)==1F)|((OUT&0FFFF)==3F)|((OUT&0FFFF)==7F)
 
 
 
                include macros.a80
 
                include global_vars.a80
 
                include define.a80
 
                include evodos_vars.a80
 
                include version.a80
 
 
 
STACK           EQU 0x0DFF
 
 
 
OLD_IF          EQU STACK - WORD * 2
 
OLD_AF          EQU STACK - WORD
 
 
 
 BITMASK RDWR,          7                       ; 1-запись, 0-чтение
 
 
 
; команда выхода и переход на обработчик
 
JP_EMU          MACRO ADDRESS
 
                DB ADDRESS-$ DUP 0
 
                OUT (EXIT_PORT),A
 
                JP ADR_ADDRESS
 
                ENDM
 
 
 
; генерация адресов для таблицы
 
LABEL_GEN       MACRO ADDRESS
 
_ADDRESS        EQU ($ - TABLE_VIRT) / 4
 
                DW ADDRESS,ADR_ADDRESS.WORK
 
                ENDM
 
 
 
; переход на обработчик с кодом адреса
 
EMU_JUMP        MACRO ADDRESS
 
ADR_ADDRESS     EQU $
 
                LD (OLD_AF + 1),A
 
                LD A,_ADDRESS
 
                JP WORKER
 
 
 
.WORK           EQU $
 
                ENDM
 
 
 
                ORG 0
 
                DB "Emu TR-DOS v",VERS_DOS,"Build: "
 
                TEXTTIME
 
                DB " "
 
                TEXTDATE
 
 
 
                DB 0x0038 - $ DUP 0
 
                EI
 
                RET
 
 
 
                DB 0x006F - $ DUP 0
 
                JP (HL)
 
 
 
        JP_EMU 0x02BE                           ; OUT      (0xFF), A
 
 
 
                DB 0x0801 - $ DUP 0
 
;таблица адресов перехвата и вызыватора обработчиков
 
TABLE_VIRT
 
        LABEL_GEN 0x02BE                        ; OUT      (0xFF), A
 
        LABEL_GEN 0x1E3A                        ; OUT      (0x3F), A
 
        LABEL_GEN 0x1FDD                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x1FF3                        ; OUT      (0xFF), A
 
        LABEL_GEN 0x2000                        ; OUT      (0x1F), A
 
        LABEL_GEN 0x2076                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x2085                        ; OUT      (0x3F), A
 
        LABEL_GEN 0x208D                        ; OUT      (0x5F), A
 
        LABEL_GEN 0x2093                        ; OUT      (0x1F), A
 
        LABEL_GEN 0x2099                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x20B1                        ; IN    A, (0xFF)
 
        LABEL_GEN 0x20B8                        ; OUT      (C),    D
 
        LABEL_GEN 0x2740                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x2748                        ; OUT      (0x7F), A
 
        LABEL_GEN 0x2A53                        ; OUT      (C),    A
 
        LABEL_GEN 0x2A71                        ; OUT      (0xFF), A MAGIC
 
        LABEL_GEN 0x2A77                        ; IN    A, (0x1F)    MAGIC
 
        LABEL_GEN 0x2AD9                        ; OUT      (OxFF), A MAGIC
 
        LABEL_GEN 0x2B25                        ; IN    A, (0x5F)    MAGIC
 
        LABEL_GEN 0x2C07                        ; IN    A, (0x5F)    MAGIC
 
        LABEL_GEN 0x2CD8                        ; IN    A, (0x5F)    MAGIC
 
        LABEL_GEN 0x2D75                        ; OUT      (0x5F), A MAGIC
 
        LABEL_GEN 0x2D80                        ; OUT      (0x1F), A MAGIC
 
        LABEL_GEN 0x2D87                        ; IN    A, (0x1F)    MAGIC
 
        LABEL_GEN 0x2F0C                        ; OUT      (0xFF), A MAGIC
 
        LABEL_GEN 0x2F1D                        ; OUT      (0x5F), A MAGIC
 
        LABEL_GEN 0x2F28                        ; OUT      (0x1F), A MAGIC
 
        LABEL_GEN 0x2F2F                        ; IN    A, (0x1F)    MAGIC
 
        LABEL_GEN 0x2F3C                        ; OUT      (0xFF), A MAGIC
 
        LABEL_GEN 0x2F4D                        ; OUT      (0xFF), A MAGIC
 
        LABEL_GEN 0x2F50                        ; OUT      (0x7F), A MAGIC
 
        LABEL_GEN 0x2F57                        ; OUT      (0x1F), A MAGIC
 
        LABEL_GEN 0x2F59                        ; IN    A, (0xFF)
 
        LABEL_GEN 0x2FB1                        ; OUT      (0xFF), A
 
        LABEL_GEN 0x2FC3                        ; OUT      (0x1F), A
 
        LABEL_GEN 0x3C30                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x3D4D                        ; OUT      (0xFF), A
 
        LABEL_GEN 0x3D9A                        ; OUT      (0x1F), A
 
        LABEL_GEN 0x3DA6                        ; IN    A, (0xFF)
 
        LABEL_GEN 0x3DB5                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x3DBA                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x3DD5                        ; OUT      (0xFF), A
 
        LABEL_GEN 0x3E30                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x3E3A                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x3E44                        ; OUT      (0x7F), A
 
        LABEL_GEN 0x3E4C                        ; OUT      (0x7F), A
 
        LABEL_GEN 0x3E50                        ; IN    A, (0x3F)
 
        LABEL_GEN 0x3E78                        ; IN    A, (0x3F)
 
        LABEL_GEN 0x3E7E                        ; OUT      (0x3F), A
 
        LABEL_GEN 0x3E87                        ; IN    A, (0x3F)
 
        LABEL_GEN 0x3E95                        ; OUT      (0x3F), A
 
        LABEL_GEN 0x3EB5                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x3EBC                        ; IN    A, (0x3F)
 
        LABEL_GEN 0x3EC9                        ; OUT      (0x1F), A
 
        LABEL_GEN 0x3ECE                        ; IN    A, (0xFF)
 
        LABEL_GEN 0x3EDF                        ; OUT      (0x1F), A
 
        LABEL_GEN 0x3EF3                        ; IN    H, (C)
 
        LABEL_GEN 0x3EF5                        ; IN    A, (0xFF)
 
        LABEL_GEN 0x3EFE                        ; IN    A, (0x7F)
 
        LABEL_GEN 0x3F1B                        ; OUT      (0x5F), A
 
        LABEL_GEN 0x3F25                        ; OUT      (0x1F), A
 
        LABEL_GEN 0x3F33                        ; IN    A, (0x1F)
 
        LABEL_GEN 0x3F4D                        ; OUT      (0x1F), A
 
        LABEL_GEN 0x3F55                        ; IN    A, (0x3F)
 
        LABEL_GEN 0x3F5A                        ; Ix    A, (0x5F)
 
        LABEL_GEN 0x3F69                        ; IN    A, (0x3F)
 
        LABEL_GEN 0x3F72                        ; IN    A, (0x5F)
 
        LABEL_GEN 0x3FBC                        ; IN    A, (0xFF)
 
        LABEL_GEN 0x3FCA                        ; IN    A, (0xFF)
 
        LABEL_GEN 0x3FD1                        ; OUTI
 
        LABEL_GEN 0x3FD7                        ; IN    A, (0xFF)
 
        LABEL_GEN 0x3FE5                        ; IN    A, (0xFF)
 
        LABEL_GEN 0x3FEC                        ; INI
 
        LABEL_GEN 0x3FF0                        ; OUT      (C),    A
 
        LABEL_GEN 0x3FF3                        ; IN    A, (C)
 
 
 
; вызываторы перехвата
 
        EMU_JUMP 0x02BE                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x1E3A                         ; OUT (0x3F),A
 
                JP OUT_3F
 
 
 
        EMU_JUMP 0x1FDD                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x1FF3                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x2000                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x2076                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x2085                         ; OUT (0x3F),A
 
                JP OUT_3F
 
 
 
        EMU_JUMP 0x208D                         ; OUT (0x5F),A
 
                JP OUT_5F
 
 
 
        EMU_JUMP 0x2093                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x2099                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x20B1                         ; IN A,(0xFF)
 
                JP IN_FF
 
 
 
        EMU_JUMP 0x20B8                         ; OUT (C),D
 
                JP OUT_C_D
 
 
 
        EMU_JUMP 0x2740                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x2748                         ; OUT (0x7F),A
 
                JP OUT_7F
 
 
 
        EMU_JUMP 0x2A53                         ; OUT (C),A
 
                JP OUT_C_A
 
 
 
        EMU_JUMP 0x2A71                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x2A77                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x2AD9                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x2B25                         ; IN A,(0x5F)
 
                JP IN_5F
 
 
 
                DB 0x09FF - $ DUP 0
 
                DW 0xFFFF
 
 
 
        EMU_JUMP 0x2C07                         ;IN A,(0x5F)
 
                JP IN_5F
 
 
 
        EMU_JUMP 0x2CD8                         ; IN A,(0x5F)
 
                JP IN_5F
 
 
 
        EMU_JUMP 0x2D75                         ; OUT (0x5F),A
 
                JP OUT_5F
 
 
 
        EMU_JUMP 0x2D80                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x2D87                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x2F0C                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x2F1D                         ; OUT (0x5F),A
 
                JP OUT_5F
 
 
 
        EMU_JUMP 0x2F28                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x2F2F                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x2F3C                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x2F4D                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x2F50                         ; OUT (0x7F),A
 
                JP OUT_7F
 
 
 
        EMU_JUMP 0x2F57                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x2F59                         ; IN A,(0xFF)
 
                CALL IN_FF
 
                LD HL,EXIT_0x2F59
 
                LD (ADR_EXIT),HL
 
                JP UPDATE_AF
 
 
 
        EMU_JUMP 0x2FB1                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x2FC3                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x3C30                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x3D4D                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x3D9A                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x3DA6                         ; IN A,(0xFF)
 
                JP IN_FF
 
 
 
        EMU_JUMP 0x3DB5                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x3DBA                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x3DD5                         ; OUT (0xFF),A
 
                JP OUT_FF
 
 
 
        EMU_JUMP 0x3E30                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x3E3A                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x3E44                         ; OUT (0x7F),A
 
                JP OUT_7F
 
 
 
        EMU_JUMP 0x3E4C                         ; OUT (0x7F),A
 
                JP OUT_7F
 
 
 
        EMU_JUMP 0x3E50                         ; IN A,(0x3F)
 
                JP IN_3F
 
 
 
        EMU_JUMP 0x3E78                         ; IN A,(0x3F)
 
                JP IN_3F
 
 
 
        EMU_JUMP 0x3E7E                         ; OUT (0x3F),A
 
                JP OUT_3F
 
 
 
        EMU_JUMP 0x3E87                         ; IN A,(0x3F)
 
                JP IN_3F
 
 
 
        EMU_JUMP 0x3E95                         ; OUT (0x3F),A
 
                JP OUT_3F
 
 
 
        EMU_JUMP 0x3EB5                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x3EBC                         ; IN A,(0x3F)
 
                JP IN_3F
 
 
 
        EMU_JUMP 0x3EC9                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x3ECE                         ; IN A,(0xFF)
 
                JP IN_FF
 
 
 
        EMU_JUMP 0x3EDF                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x3EF3                         ; IN H,(C)
 
                JP IN_H_C
 
 
 
        EMU_JUMP 0x3EF5                         ; IN A,(0xFF)
 
                CALL IN_FF
 
                LD HL,EXIT_0x3EF5
 
                LD (ADR_EXIT),HL
 
UPDATE_AF       LD A,(OLD_AF + 1)
 
                AND 0xC0
 
                PUSH AF
 
                POP HL
 
                LD (OLD_AF),HL
 
                RET
 
 
 
        EMU_JUMP 0x3EFE                         ; IN A,(0x7F)
 
                CALL OUT_1F.INFF_BIT6
 
                JP IN_7F
 
 
 
        EMU_JUMP 0x3F1B                         ; OUT (0x5F),A
 
                JP OUT_5F
 
 
 
        EMU_JUMP 0x3F25                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x3F33                         ; IN A,(0x1F)
 
                JP IN_1F
 
 
 
        EMU_JUMP 0x3F4D                         ; OUT (0x1F),A
 
                JP OUT_1F
 
 
 
        EMU_JUMP 0x3F55                         ; IN A,(0x3F)
 
                JP IN_3F
 
 
 
        EMU_JUMP 0x3F5A                         ; IN A,(0x5F)
 
                JP IN_5F
 
 
 
        EMU_JUMP 0x3F69                         ; IN A,(0x3F)
 
                JP IN_3F
 
 
 
        EMU_JUMP 0x3F72                         ; IN A,(0x5F)
 
                JP IN_5F
 
 
 
        EMU_JUMP 0x3FBC                         ; IN A,(0xFF)   ; запись сектора
 
                JP WRITE_SECTOR
 
 
 
        EMU_JUMP 0x3FCA                         ; IN A,(0xFF)   ; запись сектора
 
                JP WRITE_SECTOR
 
 
 
        EMU_JUMP 0x3FD1                         ; OUTI          ; запись сектора
 
                JP WRITE_SECTOR
 
 
 
        EMU_JUMP 0x3FD7                         ; IN A,(0xFF)   ; чтение сектора
 
                JP READ_SECTOR
 
;       EMU_JUMP 0x3FD7                         ; ожидание готовности чтения
 
;               JP WAIT_READ
 
 
 
        EMU_JUMP 0x3FE5                         ; IN A,(0xFF)   ; чтение сектора
 
                JP READ_SECTOR
 
 
 
        EMU_JUMP 0x3FEC                         ; INI           ; чтение сектора
 
                JP IN_INI
 
 
 
        EMU_JUMP 0x3FF0                         ; OUT (C),A
 
                LD BC,(OLD_BC)
 
                LD A,(OLD_AF+1)
 
                LD D,A
 
                JP WR_C_D
 
 
 
        EMU_JUMP 0x3FF3                         ; IN A,(C)
 
                LD BC,(OLD_BC)
 
                IN A,(C)
 
                PUSH AF
 
                POP HL
 
                LD (OLD_AF),HL
 
                RET
 
 
 
; стек и обработчики
 
                DB STACK - $ DUP 0
 
                DW INT_BREAK
 
 
 
INT_BREAK       PUSH AF
 
                PUSH HL
 
                PUSH DE
 
                LD A,(FLAG_RW_BREAK)
 
                AND A
 
                JR NZ,.L1
 
                LD HL,(OLD_IF)
 
                LD L,0xFF
 
                LD E,(HL)
 
                INC HL
 
                LD D,(HL)
 
                LD HL,(OLD_SP)
 
                DEC HL
 
                LD (HL),D
 
                DEC HL
 
                LD (HL),E
 
                LD (OLD_SP),HL
 
                POP DE
 
                POP HL
 
                POP AF
 
                EI
 
                RET
 
 
 
.L1             PUSH BC
 
                LD (INT_SP),SP
 
                CALL READ_TMP_CPU12
 
                CALL WRITE_CPU12
 
                LD A,(OLD_PORT_BF)
 
                OUT (PEVO_CONF),A
 
                LD A,(OLD_IF + 1)
 
                LD I,A
 
                LD HL,(OLD_AF)
 
                PUSH HL
 
                POP AF
 
                LD HL,(OLD_SP)
 
                LD DE,0x2A71                    ; адрес возврата из обработчика прерывания внешней проги через OUT (0xFF),A
 
                DEC HL
 
                LD (HL),D
 
                DEC HL
 
                LD (HL),E
 
                DEC HL
 
                EX DE,HL
 
                LD HL,OLD_IF + 1
 
                LD H,(HL)
 
                LD L,0xFF
 
                LD C,(HL)
 
                INC HL
 
                LD B,(HL)
 
                EX DE,HL
 
                LD (HL),B
 
                DEC HL
 
                LD (HL),C
 
                LD SP,HL
 
                LD HL,(OLD_HL)
 
                LD DE,(OLD_DE)
 
                LD BC,(OLD_BC)
 
                LD A,(WR_FF)                    ; байтик для возврата через команду OUT (0xFF),A
 
                EI
 
                JP 0x2A53
 
 
 
INT_RET         LD SP,0
 
INT_SP          EQU $-2
 
                IN A,(PEVO_CONF)
 
                LD (OLD_PORT_BF),A
 
                OR 1
 
                OUT (PEVO_CONF),A
 
                LD A,HIGH (STACK)
 
                LD I,A
 
                CALL WRITE_TMP_CPU12
 
                POP BC
 
                POP DE
 
                POP HL
 
                POP AF
 
                RET
 
 
 
; выход из обработчика
 
EXIT_PAGE_FE    LD A,(OLD_PORT_BF)
 
                OUT (PEVO_CONF),A               ; восстановление порта 0xBF
 
                LD A,(OLD_IF + 1)
 
                LD I,A
 
                LD HL,(OLD_AF)
 
                PUSH HL
 
                POP AF
 
                LD HL,0                         ; восстановление HL
 
OLD_HL          EQU $-2
 
                LD DE,0                         ; восстановление DE
 
OLD_DE          EQU $-2
 
                LD BC,0                         ; восстановление BC
 
OLD_BC          EQU $-2
 
                LD SP,0                         ; восстановление SP
 
OLD_SP          EQU $-2
 
                JP 0
 
ADR_EXIT        EQU $-2         
 
 
 
; вход в обработчик
 
WORKER          LD (NUM_ADR),A
 
                LD (OLD_SP),SP
 
                LD SP,STACK - WORD
 
                PUSH AF
 
                EX (SP),HL
 
                LD A,L
 
                LD (OLD_AF),A
 
                POP HL
 
                LD A,I
 
                JP PE,.L1
 
                LD A,I
 
.L1             PUSH AF                         ; IF
 
                IN A,(PEVO_CONF)
 
                LD (OLD_PORT_BF),A              ; порт BF
 
                OR 1
 
                OUT (PEVO_CONF),A
 
                LD A,HIGH (STACK)
 
                LD I,A
 
                LD (OLD_HL),HL
 
                LD (OLD_DE),DE
 
                LD (OLD_BC),BC
 
                LD HL,0
 
NUM_ADR         EQU $-2
 
                ADD HL,HL
 
                ADD HL,HL
 
                LD DE,TABLE_VIRT
 
                ADD HL,DE
 
                LD E,(HL)
 
                INC HL
 
                LD D,(HL)                       ; DE-адрес возврата из обработчика
 
                INC HL
 
                LD (ADR_EXIT),DE
 
                LD E,(HL)
 
                INC HL
 
                LD D,(HL)                       ; DE-адрес обработчика
 
                PUSH DE
 
                LD HL,EXIT_PAGE_FE              ; код выхода из обработчика
 
                EX (SP),HL
 
                JP (HL)
 
 
 
; чтение/запись примонтированного диска
 
MOUNT_RW        DI
 
                LD A,(RDWR_MODE)
 
                AND M_RDWR
 
                LD L,A
 
                LD A,(WR_FF)
 
                AND 3
 
                OR L
 
                BIT B_RDWR,A
 
                PUSH AF                         ; флаг чтения/записи на стек
 
                LD HL,0x2A77
 
                PUSH HL                         ; адрес возврата на стек
 
                LD HL,MNT_RW + CPU1
 
                PUSH HL                         ; адрес вызова RST 8 для чтения/записи на стек
 
                JR Z,.L1
 
; запись, копируем в буфер сектор который будем записывать на смонтированный образ
 
                LD HL,(OLD_HL)
 
                LD DE,MNT_SECTOR
 
                CALL COPY_BLOCK
 
                LD (OLD_HL),HL
 
; переключаем паги для работы с маунтом
 
.L1             PUSH AF
 
                LD BC,WIN_A1
 
                LD A,0x40
 
                OUT (C),A
 
                LD B,HIGH (WIN_P1)
 
                LD A,RAM_EVODOS
 
                OUT (C),A
 
                POP AF
 
; переставляем стек
 
                LD HL,CPU1
 
                ADD HL,SP
 
                LD SP,HL
 
                JP 0x2A53
 
 
 
; чтение/запись сектора в образе
 
MNT_RW          LD L,A
 
                LD A,(PORT_3F + CPU1)           ; взяли номер трека
 
                ADD A,A                         ; сторон 2
 
                LD D,A
 
                LD A,(WR_FF + CPU1)
 
                AND 0x10                        ; проверка какая сторона диска
 
                JR NZ,.L1
 
                INC D                           ; для стороны 1
 
.L1             LD A,(PORT_5F + CPU1)           ; взяли номер сектора
 
                LD E,A                          ; D-трек, E-сектор
 
                LD A,L
 
                LD HL,MNT_SECTOR + CPU1
 
        RST8 _MOUNTER,_RDWR_MOUNT
 
                JP 0x3D2F
 
 
 
; возврат после чтения/записи в образе
 
RET_MNT_RW      LD HL,-CPU1
 
                ADD HL,SP
 
                LD SP,HL
 
                CALL WRITE_CPU12
 
                POP AF
 
                RET NZ                          ; для записи выходим
 
; для чтения переносим сектор в указанный адрес
 
                LD HL,MNT_SECTOR                ; буфер откуда переносить
 
                LD DE,(OLD_HL)                  ; адрес куда переносить
 
                LD A,D
 
                CP 0x40                         ; чтение в адреса 0x0000...0x3FFF?
 
                JR NC,.L5
 
                CP 0x3F
 
                JR NZ,.L3                       ; если не 0x3Fxx, пропускаем
 
                LD A,E
 
                AND A
 
                JR Z,.L3                        ; для адрес 0x3F00 просто пропуск
 
; для смещения в адресе 0x3Fxx
 
                NEG
 
                LD C,A
 
                LD B,0
 
                ADD HL,BC                       ; сколько пропустить от начала буфера
 
                PUSH DE
 
                LD C,E                          ; сколько копировать
 
                LD DE,CPU1
 
                LDIR
 
                POP DE
 
                JR .L3
 
 
 
; проверка для адресов чтения 0xFFxx
 
.L5             INC A
 
                JR NZ,.L1
 
; проверка на адрес 0xFF00
 
                LD A,E
 
                AND A
 
                JR Z,.L1
 
; для загрузки в адрес выше 0xFF00 переносим только до адреса 0, остальное в игнор
 
.L4             PUSH DE
 
                NEG
 
                LD C,A
 
                LD B,0
 
                LDIR
 
                POP DE
 
.L3             INC D
 
                LD (OLD_HL),DE
 
                RET
 
 
 
.L1             CALL COPY_BLOCK
 
                LD (OLD_HL),DE
 
                RET
 
 
 
; инфа для создания 9 сектора нового диска
 
DSKINFO         DB 0                            ; + 0xE1 - номер первого свободного сектора
 
                DB 1                            ; + 0xE2 - номер первого свободного трека
 
                DB 0x16                         ; + 0xE3 - тип дискеты
 
                DB 0                            ; + 0xE4 - количество файлов на дискете
 
SECFREE         DW 2544                         ; + 0xE5 - количество свободных секторов
 
                DB 0x10                         ; + 0xE7 - идентификационный код TRDOS
 
                DW 0                            ; + 0xE8 - 2 байта 0
 
                DB 9 DUP " "                    ; + 0xEA - 9 байт 0x20
 
                DB 0                            ; + 0xF3 - 1 байт 0
 
                DB 0                            ; + 0xF4 - количество удаленных файлов
 
                DB "RAMDISKO"                   ; + 0xF5 - имя дискеты
 
DSK_END
 
 
 
                DB LOW (-$) DUP 0
 
MNT_SECTOR
 
 
 
; адреса перехвата
 
        JP_EMU 0x1E3A                           ; OUT      (0x3F), A
 
        JP_EMU 0x1FDD                           ; IN    A, (0x1F)
 
        JP_EMU 0x1FF3                           ; OUT      (0xFF), A
 
        JP_EMU 0x2000                           ; OUT      (0x1F), A
 
        JP_EMU 0x2076                           ; IN    A, (0x1F)
 
        JP_EMU 0x2085                           ; OUT      (0x3F), A
 
        JP_EMU 0x208D                           ; OUT      (0x5F), A
 
        JP_EMU 0x2093                           ; OUT      (0x1F), A
 
        JP_EMU 0x2099                           ; IN    A, (0x1F)
 
        JP_EMU 0x20B1                           ; IN    A, (0xFF)
 
        JP_EMU 0x20B8                           ; OUT      (C),    D
 
        JP_EMU 0x2740                           ; IN    A, (0x1F)
 
        JP_EMU 0x2748                           ; OUT      (0x7F), A
 
        JP_EMU 0x2A53                           ; OUT      (C),    A
 
 
 
; первая команда в обработчике MAGIC для возврата в пагу FE
 
;       JP_EMU 0x2A71                           ; OUT      (0xFF), A
 
                DB 0x2A71 - $ DUP 0
 
                OUT (EXIT_PORT),A
 
                JP INT_RET                      ; возвращение из обработчика INT
 
 
 
;       JP_EMU 0x2A77                           ; IN    A, (0x1F)
 
                DB 0x2A77 - $ DUP 0
 
                OUT (EXIT_PORT),A
 
                JP RET_MNT_RW                   ; возвращение после вызова RST 8
 
 
 
        JP_EMU 0x2AD9                           ; OUT      (0xFF), A
 
        JP_EMU 0x2B25                           ; IN    A, (0x5F)
 
        JP_EMU 0x2C07                           ; IN    A, (0x5F)
 
        JP_EMU 0x2CD8                           ; IN    A, (0x5F)
 
        JP_EMU 0x2D75                           ; OUT      (0x5F), A
 
        JP_EMU 0x2D80                           ; OUT      (0x1F), A
 
        JP_EMU 0x2D87                           ; IN    A, (0x1F)
 
        JP_EMU 0x2F0C                           ; OUT      (0xFF), A
 
        JP_EMU 0x2F1D                           ; OUT      (0x5F), A
 
 
 
                DB 0x2F24 - $ DUP 0             ; для адреса 0x2F4D
 
                JP ADR_0x2F4D
 
 
 
        JP_EMU 0x2F28                           ; OUT      (0x1F), A
 
        JP_EMU 0x2F2F                           ; IN    A, (0x1F)
 
        JP_EMU 0x2F3C                           ; OUT      (0xFF), A
 
 
 
                DB 0x2F4D - $ DUP 0             ; OUT      (0xFF), A
 
                OUT (EXIT_PORT),A
 
                DB 0x18                         ; JR 0x2F24
 
 
 
        JP_EMU 0x2F50                           ; OUT      (0x7F), A
 
 
 
                DB 0x2F57 - $ DUP 0             ; OUT      (0x1F), A
 
                OUT (EXIT_PORT),A
 
                JR JUMP_0x2F57
 
 
 
                JR JUMP_0x2F59                  ; IN    A, (0xFF)
 
 
 
EXIT_0x2F59     OUT (EXIT_PORT),A
 
JUMP_0x2F59     JP ADR_0x2F59
 
 
 
JUMP_0x2F57     JP ADR_0x2F57
 
 
 
        JP_EMU 0x2FB1                           ; OUT      (0xFF), A
 
        JP_EMU 0x2FC3                           ; OUT      (0x1F), A
 
 
 
                DB 0x32A2 - $ DUP 0
 
; обработчики чтения/записи портов
 
; запись "A" в порт 0x1F
 
OUT_1F          LD A,(OLD_AF + 1)
 
                LD (WR_1F),A
 
                AND %11110000
 
                RRCA
 
                RRCA
 
                RRCA
 
                ADD A,LOW (.TABL_CMD)
 
                LD L,A
 
                ADC A,HIGH (.TABL_CMD)
 
                SUB L
 
                LD H,A
 
                LD A,(HL)
 
                INC HL
 
                LD H,(HL)
 
                LD L,A
 
                JP (HL)
 
 
 
.TABL_CMD       DW .CMD_00
 
                DW .CMD_10
 
                DW .CMD_20
 
                DW .CMD_30
 
                DW .CMD_40
 
                DW .CMD_50
 
                DW .CMD_60
 
                DW .CMD_70
 
                DW .CMD_80
 
                DW .CMD_90
 
                DW .CMD_A0
 
                DW .CMD_B0
 
                DW .CMD_C0
 
                DW .CMD_D0
 
                DW .CMD_E0
 
                DW .CMD_F0
 
 
 
; 00-0F команда восстановления
 
.CMD_00         XOR A
 
                LD (PORT_3F),A
 
                JR .INFF_BIT6
 
 
 
; 10-1F команда поиска
 
.CMD_10         LD A,(PORT_7F)
 
                LD (PORT_3F),A
 
                CALL DISK_NONE
 
                LD A,0x80
 
                JR C,.INFF_BIT6_1
 
.INFF_BIT6      XOR A
 
.INFF_BIT6_1    LD (RD_1F),A
 
                LD A,0xBF
 
                LD (RD_FF),A
 
                RET
 
 
 
; 20-3F команда шаг в предыдущем направлении
 
.CMD_20
 
.CMD_30         LD A,(PORT_3F)
 
.NAPRAVL        INC A
 
                LD (PORT_3F),A
 
                JR .INFF_BIT6
 
 
 
; 40-5F команда шаг вперед
 
.CMD_40
 
.CMD_50         LD A,(PORT_3F)
 
                INC A
 
                LD (PORT_3F),A
 
                LD A,0x3C                       ; INC A
 
                LD (.NAPRAVL),A
 
                JR .INFF_BIT6
 
 
 
; 60-7F команда шаг назад
 
.CMD_60
 
.CMD_70         LD A,(PORT_3F)
 
                DEC A
 
                LD (PORT_3F),A
 
                LD A,0x3D                       ; DEC A
 
                LD (.NAPRAVL),A
 
 
 
; 80-9F команда чтение сектора
 
.CMD_80
 
.CMD_90
 
 
 
; A0-BF команда запись сектора
 
.CMD_A0
 
.CMD_B0
 
 
 
; C0-CF чтение адреса
 
.CMD_C0         JR .INFF_BIT6
 
 
 
; D0-DF принудительное прерывание
 
.CMD_D0         LD A,0xBF
 
                LD (RD_FF),A
 
                RET
 
 
 
; E0-EF чтение дорожки
 
.CMD_E0
 
.CMD_F0         JR .INFF_BIT6
 
 
 
; запись "A" в порт 0x3F
 
OUT_3F          LD A,(OLD_AF + 1)
 
                LD (PORT_3F),A
 
                RET
 
 
 
; запись "A" в порт 0x5F
 
OUT_5F          LD A,(OLD_AF + 1)
 
                LD (PORT_5F),A
 
                RET
 
 
 
; запись "A" в порт 0x7F
 
OUT_7F          LD A,(OLD_AF + 1)
 
                LD (PORT_7F),A
 
                RET
 
 
 
; запись "A" в порт 0xFF
 
OUT_FF          LD A,(OLD_AF + 1)
 
                LD (WR_FF),A
 
                LD D,A
 
                LD BC,0x00FF
 
                JR WR_C_D
 
 
 
; запись "A" в порт (C)
 
OUT_C_A         LD A,(OLD_AF + 1)
 
WRCA1           LD D,A
 
                LD BC,(OLD_BC)                  ; если порт не TR-DOS
 
                LD A,C
 
; определение в какой порт запись       
 
                CP 0x1F
 
                JP Z,OUT_1F
 
                CP 0x3F
 
                JR Z,OUT_3F
 
                CP 0x5F
 
                JR Z,OUT_5F
 
                CP 0x7F
 
                JR Z,OUT_7F
 
                CP 0xFF
 
                JR Z,OUT_FF
 
                CP LOW (WIN_A0)
 
                JR Z,WRCA3
 
WR_C_D          PUSH BC
 
                LD BC,FDD_EMU_PORT
 
                IN E,(C)
 
                XOR A
 
                OUT (C),A
 
                POP BC
 
                OUT (C),D
 
                LD BC,FDD_EMU_PORT
 
                OUT (C),E
 
                RET
 
 
 
; запись в порты ATM/PENTEVO
 
WRCA3           LD A,B
 
                LD HL,BB_CPU1
 
                CP HIGH (WIN_A1)
 
                JR Z,.L1
 
                CP HIGH (WIN_P2)
 
                JR Z,.L1
 
                LD HL,BB_CPU2
 
                CP HIGH (WIN_A2)
 
                JR Z,.L1
 
                CP HIGH (WIN_P2)
 
                JR NZ,WR_C_D
 
.L1             LD E,B
 
                PUSH DE
 
                PUSH HL
 
                CALL READ_CPU12
 
                POP HL
 
                POP DE
 
                LD (HL),D
 
                INC HL
 
                LD (HL),E
 
                JP WRITE_CPU12
 
 
 
; запись "D" в порт (C)
 
OUT_C_D         LD A,(OLD_DE + 1)
 
                JR WRCA1
 
 
 
; передача байта, команда OUTI
 
OUT_OUTI        LD HL,(BUFF_SECT)
 
                EXX
 
                LD A,(HL)
 
                INC HL
 
                EXX
 
                LD (HL),A
 
                INC HL
 
                LD (BUFF_SECT),HL
 
                RET
 
 
 
; чтение порта 0x1F
 
IN_1F           LD A,(WR_1F)
 
                AND %11110000
 
                CP 0x10
 
                JR C,.L1                        ; 00-0F команды восстановления
 
                CP 0x20
 
                JR C,.L3                        ; 10-1F команды поиска
 
                CP 0x80
 
                JR C,.L5                        ; 20-7F команды шагания головки
 
                CP 0xC0
 
                JR C,.L8                        ; 80-BF команды чтения/записи
 
                CP 0xD0
 
                JR Z,.L1                        ; D0-DF команды принудительного прерывания
 
                XOR A
 
                JR .L2
 
 
 
; проверка выхода за 80 дорожку
 
.L8             LD A,(PORT_3F)
 
                CP 80
 
                LD A,0
 
                JR C,.L2
 
                LD A,%00010000                  ; при уходе за 80 дорожку выдача ошибки "массив не найден"
 
                JR .L2
 
 
 
.L5             LD A,(PORT_3F)
 
                AND A
 
                JR NZ,.L1
 
                LD A,%00100100
 
                JR .L6
 
 
 
.L3             LD A,(.INDEX)
 
                XOR %00000100
 
                JR .L4
 
 
 
.L1             LD A,%00100100
 
.INDEX          EQU $-1
 
.L4             XOR %00000010
 
.L6             LD (.INDEX),A
 
.L2             LD (RD_1F),A
 
                LD (OLD_AF + 1),A
 
                RET
 
 
 
; чтение порта 0x3F
 
IN_3F           LD A,(PORT_3F)
 
                LD (OLD_AF + 1),A
 
                RET
 
 
 
; чтение порта 0x5F
 
IN_5F           LD A,(PORT_5F)
 
                LD (OLD_AF + 1),A
 
                RET
 
 
 
; чтение порта 0x7F
 
IN_7F           LD A,(PORT_7F)
 
                LD (OLD_AF + 1),A
 
                RET
 
 
 
; чтение порта 0xFF
 
IN_FF           LD A,(RD_FF)
 
                LD (OLD_AF + 1),A
 
                RET
 
 
 
; чтение в "H" из (С)
 
IN_H_C          LD A,(OLD_BC)
 
; определение из какого порта чтение
 
                CP 0x1F
 
                JR NZ,.L2
 
                LD A,(RD_1F)
 
                LD (OLD_HL + 1),A
 
                RET
 
 
 
.L2             CP 0x3F
 
                JR NZ,.L3
 
                LD A,(PORT_3F)
 
                LD (OLD_HL + 1),A
 
                RET
 
 
 
.L3             CP 0x5F
 
                JR NZ,.L4
 
                LD A,(PORT_5F)
 
                LD (OLD_HL + 1),A
 
                RET
 
 
 
.L4             CP 0x7F
 
                JR NZ,.L5
 
                LD A,(PORT_7F)
 
                LD (OLD_HL+1),A
 
                RET
 
 
 
.L5             CP 0xFF
 
                JR NZ,.L6
 
                LD A,(RD_FF)
 
                LD (OLD_HL + 1),A
 
                RET
 
 
 
.L6             LD BC,(OLD_BC)
 
                IN A,(C)
 
                LD (OLD_HL + 1),A
 
                RET
 
 
 
; чтение INI
 
IN_INI          LD HL,(OLD_HL)
 
                LD A,H
 
                CP 0x40
 
                JR C,.L1
 
                DEC HL
 
                LD A,(RD_1F)
 
                LD (HL),A
 
; временно, для анрыла
 
;               LD A,0xD3
 
;               LD (0x3FD7),A
 
; временно, для анрыла
 
.L1             LD HL,0x2A53
 
                LD (ADR_EXIT),HL
 
                JP OUT_1F.INFF_BIT6
 
 
 
WAIT_READ       LD A,(WR_1F)
 
                AND 0xF0
 
                CP 0x80
 
                JP C,OUT_1F.INFF_BIT6
 
                CP 0xC0
 
                JR NC,READ_SECTOR.L1
 
                CALL READ_CPU12                 ; сохранение текущей конфигурации окон проецирования 1,2
 
                CALL FIND_SECTOR                ; проверяем наличие сектора
 
                PUSH AF
 
                CALL WRITE_CPU12                ; восстановление конфигурации окон проецирования 1,2
 
                POP AF
 
                JR NC,READ_SECTOR_1
 
; сектора нет, не дождетесь
 
                LD A,0x3C
 
                JP OUT_1F.INFF_BIT6_1
 
 
 
; чтение сектора или портов
 
READ_SECTOR     LD A,(WR_1F)
 
                AND 0xF0
 
                CP 0x80
 
                JP C,OUT_1F.INFF_BIT6
 
                CP 0xC0
 
                JR C,READ_SECTOR_1
 
.L1             CALL READ_CPU12                 ; чтение текущей конфы
 
                LD BC,WIN_A1
 
                LD A,0x40
 
                OUT (C),A
 
                LD B,HIGH (WIN_P1)
 
                LD A,RAM_RAMDISK
 
                OUT (C),A                       ; страница заголовков рамдиска
 
                LD A,(PORT_3F)                  ; взяли номер трека
 
                ADD A,A                         ; сторон 2
 
                LD C,A
 
                LD A,(WR_FF)
 
                AND 0x10                        ; проверка какая сторона диска
 
                JR NZ,.L2
 
                INC C                           ; для стороны 1
 
.L2             LD B,HIGH (CPU1) + 2            ; адрес начала инфы о секторах на дорожке
 
                LD A,0                          ; текущий номер сектора
 
.CURR_SEC       EQU $-1
 
                INC A
 
                AND %00001111
 
                LD (.CURR_SEC),A
 
                ADD A,A
 
                ADD A,HIGH (CPU1) + 2
 
                LD B,A
 
                LD A,(PORT_3F)                  ; номер дорожки
 
                LD C,A
 
                LD A,(BC)                       ; проичтали номер сектора
 
                PUSH AF
 
                CALL WRITE_CPU12                ; восстановление конфы
 
                LD A,(PORT_3F)
 
                LD HL,(OLD_HL)
 
                LD (HL),A                       ; номер дорожки
 
                INC HL
 
                LD (HL),0                       ; номер стороны
 
                INC HL
 
                POP AF
 
                LD (HL),A                       ; номер сектора
 
                INC HL
 
                LD (HL),0                       ; размер сектора
 
                INC HL
 
                LD (HL),0                       ; байт CRC
 
                INC HL
 
                LD (HL),0                       ; байт CRC
 
                INC HL
 
                LD (OLD_HL),HL
 
                LD HL,OLD_BC + 1
 
                LD A,(HL)
 
                SUB 6                           ; REG B - 6
 
                LD (HL),A
 
                LD HL,0x2A53
 
                LD (ADR_EXIT),HL
 
                JP OUT_1F.INFF_BIT6
 
 
 
; чтение сектора
 
READ_SECTOR_1   XOR A
 
                JR WRITE_SECTOR.L1
 
 
 
; запись сектора
 
WRITE_SECTOR    LD A,0xFF
 
.L1             LD (RDWR_MODE),A
 
                LD A,1
 
                LD (FLAG_RW_BREAK),A
 
                LD HL,(OLD_IF)
 
                PUSH HL
 
                POP AF
 
                JP PO,.DI_MODE                  ; прерывания разрешены?
 
                CP 0x3F
 
                JR Z,.DI_MODE
 
                HALT                            ; разрешены, ждем обработчик прерывания
 
.DI_MODE        CALL READ_CPU12                 ; сохранение текущей конфигурации окон проецирования 1,2
 
                CALL W_WR_RD_SECT
 
                XOR A
 
                LD (FLAG_RW_BREAK),A
 
                LD HL,0x8090
 
                LD (OLD_AF),HL                  ; эмуляция флага успешного чтения/записи сектора
 
                LD HL,0x2A53
 
                LD (ADR_EXIT),HL
 
                JP WRITE_CPU12                  ; восстановление конфигурации окон проецирования 1,2
 
 
 
; поиск сектора в таблице
 
FIND_SECTOR     LD BC,WIN_A1
 
                LD A,0x40
 
                OUT (C),A
 
                LD B,HIGH (WIN_P1)
 
                LD A,RAM_RAMDISK
 
                OUT (C),A                       ; страница заголовков рамдиска
 
                LD A,(PORT_3F)                  ; взяли номер трека
 
                ADD A,A                         ; сторон 2
 
                LD C,A
 
                LD A,(WR_FF)
 
                AND 0x10                        ; проверка какая сторона диска
 
                JR NZ,.L2
 
                INC C                           ; для стороны 1
 
.L2             LD B,HIGH (CPU1) + 2            ; адрес начала инфы о секторах на дорожке
 
                LD HL,(PORT_5F)                 ; взяли номер сектора
 
                LD H,0
 
.L1             LD A,(BC)
 
                LD D,A                          ; взяли номер сектора
 
                INC B
 
                LD A,(BC)
 
                LD E,A                          ; взяли размер сектора
 
                INC B
 
;               LD A,D
 
                AND A
 
                SCF
 
                RET Z                           ; ошибка, сектор не найден
 
                LD A,L
 
                CP D
 
                RET Z                           ; сектор найден
 
                LD A,E
 
                ADD A,H
 
                LD H,A
 
                JR .L1
 
 
 
; чтение или запись сектора рамдиска
 
W_WR_RD_SECT    LD A,(WR_FF)
 
                AND 3
 
                INC A
 
                LD B,A
 
                LD A,%10000000
 
.L1             RLCA
 
                DJNZ .L1
 
                LD B,A
 
                LD A,(COPY_VIRT_BITS)
 
                AND B
 
                JP NZ,MOUNT_RW                  ; работа с примонтированным образом
 
                CALL FIND_SECTOR
 
                JR NC,.L2
 
; сектор не найден, на выход
 
                LD A,0x10
 
                JP IN_1F.L2
 
 
 
; сектор найден, читаем/пишем
 
.L2             LD A,E
 
                RRCA
 
                LD (SECTOR_SIZE),A              ; размер найденного сектора
 
                LD L,0
 
                LD E,L
 
                SRL H
 
                RR L                            ; HL = смещение в блоках до найденного сектора
 
                LD B,HIGH (CPU1)
 
                LD A,(BC)
 
                LD D,A
 
                ADD HL,DE                       ; HL = смещение от начала страницы в блоках
 
                INC B
 
                LD A,(BC)
 
                LD C,A                          ; смещение в страницах от начала рамдиска
 
                LD A,H
 
                CP HIGH (CPU1)
 
                JR C,.L5
 
                SUB 0x40
 
                LD H,A
 
                INC C
 
; HL = смещение в странице до начала сектора
 
.L5             LD A,C                          ; смещение до номера страницы, где указанный сектор начинается
 
                ADD A,RAM_DATARAMD              ; прибавили номер начала рамдиск и +1. в 0 странице рамдиска описатели секторов
 
                LD (RDWR_PAGE),A                ; сохранили номер вычисленной страницы
 
                LD DE,(OLD_HL)                  ; адрес куда/откуда копировать
 
                LD BC,(BB_CPU1)
 
                LD A,C
 
                LD C,LOW (WIN_A0)
 
                OUT (C),A                       ; вернули стандартную 5 страницу
 
.S9             LD A,D                          ; проверка границы откуда/куда копировать
 
                CP HIGH (CPU2)
 
                PUSH DE
 
                LD DE,CPU1 + HIGH (WIN_P1)
 
                LD BC,WIN_A1                    ; если верхние 32кб озу, то нужно включить в 1 окне проецирования
 
                JR NC,.S1
 
                LD DE,CPU2 + HIGH (WIN_P2)
 
                LD B,HIGH (WIN_A2)              ; если нижние 32кб озу, то нужно включить во 2 окне проецирования
 
.S1             LD A,0x40
 
                OUT (C),A
 
                LD B,E
 
                LD A,(RDWR_PAGE)                ; номер вычисленной страницы озу
 
                OUT (C),A                       ; включили вычисленную страницу
 
                LD B,D                          ; старший байт адреса начала включенной страницы
 
                POP DE
 
                LD A,B
 
                ADD A,H
 
                LD H,A
 
                LD A,(RDWR_MODE)
 
                AND A
 
                JR NZ,.I1
 
                LD A,D
 
                INC A
 
                JR NZ,.I1
 
                LD A,E
 
                AND A
 
                JR Z,.I1
 
                NEG
 
                LD C,A
 
                LD B,0
 
                LDIR
 
                NEG
 
                LD C,A
 
.I2             EX DE,HL
 
                ADD HL,BC
 
                EX DE,HL
 
                ADD HL,BC
 
                LD A,(SECTOR_SIZE)
 
                JP .S8_
 
 
 
.I1             LD A,D
 
                CP HIGH (CPU1)
 
                JR NC,.I3
 
                LD A,(SECTOR_SIZE)
 
                AND A
 
                LD BC,0x80
 
                JR Z,.I2
 
                LD BC,0x100
 
                JR .I2
 
 
 
.I3             CP HIGH (CPU2)                  ; проверка перехода границы страниц
 
                JP NC,.S3                       ; если выше то сразу копируем
 
                CP HIGH (CPU2) - 1
 
                JP C,.S3                        ; если ниже так же сразу копируем
 
                LD A,E
 
                AND A                           ; если сектор полностью укладывется до границы, то сразу копируем
 
                JR Z,.S3                        ; иначе принудительно копируем в два приема
 
                LD A,(RDWR_MODE)                ; чтение или запись?
 
                AND A
 
                LD A,E                          ; младший байт адрес в блоке
 
                JR Z,.S4
 
                EX DE,HL                        ; для записи меняем направление
 
.S4             NEG
 
                LD C,A                          ; копируем остаток до конца блока
 
                LD B,0
 
                LDIR
 
                NEG
 
                PUSH AF                         ; спрятали сколько осталось копировать из начала следующего блока
 
                LD BC,(BB_CPU2)
 
                LD A,C
 
                LD C,LOW (WIN_A0)
 
                OUT (C),A
 
                LD B,HIGH (WIN_A1)
 
                LD A,0x40
 
                OUT (C),A
 
                LD B,HIGH (WIN_P1)
 
                LD A,(RDWR_PAGE)
 
                OUT (C),A                       ; вычисленную страницу включаем в 1 окне проецирования
 
                LD A,(RDWR_MODE)                ; чтение или запись
 
                AND A
 
                JR Z,.S5
 
                LD A,D                          ; для записи
 
                SUB 0x40                        ; изменили адрес куда копировать на другое окно проецирования
 
                LD D,A
 
                JR .S6
 
 
 
.S5             LD A,H                          ; для чтения
 
                SUB 0x40                        ; изменили адрес куда копировать на другое окно проецирования 
 
                LD H,A
 
.S6             POP AF
 
                LD C,A                          ; сколько осталось скопировать байт
 
                LD B,0
 
                LDIR
 
                LD A,(SECTOR_SIZE)
 
                JR .S8_
 
 
 
.S3             LD A,(RDWR_MODE)                ; чтение или запись
 
                AND A
 
                JR Z,.S7
 
                EX DE,HL                        ; для записи меняем направление
 
.S7             LD A,(SECTOR_SIZE)
 
                AND A
 
                JR NZ,.S8
 
                CALL COPYHBLOCK                 ; для сектора размером 128 байт копируем половину и выходим
 
.ECOPY_BLOCK    LD A,(RDWR_MODE)
 
                AND A
 
                JR Z,.ECOPY_BLOCK1
 
                EX DE,HL
 
.ECOPY_BLOCK1   LD (OLD_HL),DE
 
                RET
 
 
 
.S8             CALL COPY_BLOCK                 ; для сектора 256 байт копируем весь и выходим
 
.S8_            DEC A
 
                JR Z,.ECOPY_BLOCK
 
                LD (SECTOR_SIZE),A
 
                LD A,(RDWR_MODE)
 
                AND A
 
                JR Z,.S0
 
                EX DE,HL
 
.S0             LD A,0x3F
 
                AND H
 
                LD H,A
 
                JP .S9
 
 
 
COPY_BLOCK
 
        REPT 128
 
                LDI
 
        ENDM
 
COPYHBLOCK
 
        REPT 128
 
                LDI
 
        ENDM
 
                RET
 
 
 
; проверка наличия маркера рамдиска
 
CMP_RAM_DISK    CALL READ_CPU12
 
                LD BC,WIN_P1
 
                LD A,RAM_RAMDISK
 
                OUT (C),A
 
                LD HL,CPU1 + 0x3FFF
 
                LD D,(HL)
 
                DEC H
 
                LD E,(HL)                       ; взяли байты для проверки маркера
 
                CALL WRITE_CPU12
 
                LD HL,"RD"
 
                AND A
 
                SBC HL,DE
 
                RET Z                           ; если маркер на месте, то рамдиска не создаем
 
; создание чистого рамдиска
 
CREATE_TRDTABL  LD BC,WIN_P1
 
                LD A,RAM_RAMDISK                ; нужна страница начала рамдиска, где будет таблица описателей
 
                OUT (C),A
 
                LD HL,CPU1
 
                PUSH HL
 
                LD DE,CPU1 + 1
 
                LD BC,0x3FFF
 
                LD (HL),L
 
                LDIR                            ; очистили страницу
 
                POP DE                          ; адрес начала страницы
 
                LD HL,0                         ; смещение в блоках и страницах
 
                LD A,0xA0
 
.L1             PUSH AF
 
                LD BC,0x1000                    ; счетчик номеров секторов и их номера
 
                LD A,L
 
                RRCA
 
                RRCA
 
                LD (DE),A                       ; смещение в блоках дорожки в странице
 
                INC D
 
                LD A,H
 
                LD (DE),A                       ; смещение в страницах до дорожки
 
                INC D
 
.L2             INC C
 
                LD A,C
 
                LD (DE),A                       ; номер сектора
 
                INC D
 
                LD A,2
 
                LD (DE),A                       ; размер сектора
 
                INC D
 
                DJNZ .L2                        ; вносим в таблицу все номера секторов с размерами
 
                LD D,HIGH (CPU1)                ; вернули указатель в начало
 
                INC E                           ; для следующей дорожки
 
                LD BC,0x40
 
                ADD HL,BC                       ; переход к следующей дорожке
 
                POP AF
 
                DEC A
 
                JR NZ,.L1                       ; повторяем для всех дорожек
 
                LD HL,CPU1 + 0x3FFF
 
                LD (HL),"R"                     ; вносим маркер рамдиска
 
                DEC H
 
                LD (HL),"D"
 
                LD BC,WIN_P1
 
                LD A,RAM_DATARAMD
 
                OUT (C),A
 
                LD HL,CPU1
 
                LD DE,CPU1 + 1
 
                LD BC,0x0FFF
 
                LD (HL),L
 
                LDIR
 
                LD HL,DSKINFO
 
                LD DE,CPU1 + 0x08E1
 
                LD BC,DSK_END - DSKINFO
 
                LDIR
 
; восстановление конфигурации окон проецирования 1,2
 
WRITE_CPU12     LD BC,(BB_CPU1)
 
                LD A,C
 
                LD C,LOW (WIN_A0)
 
                OUT (C),A
 
                LD BC,(BB_CPU2)
 
                LD A,C
 
                LD C,LOW (WIN_A0)
 
                OUT (C),A
 
                RET
 
 
 
; чтение текущего конфига страниц проецирования 1,2
 
READ_TMP_CPU12  LD HL,(BB_CPU1)
 
                PUSH HL
 
                LD HL,(BB_CPU2)
 
                PUSH HL
 
                CALL READ_CPU12
 
                LD HL,(BB_CPU1)
 
                LD (TMP_BB_CPU1),HL
 
                LD HL,(BB_CPU2)
 
                LD (TMP_BB_CPU2),HL
 
                POP HL
 
                LD (BB_CPU2),HL
 
                POP HL
 
                LD (BB_CPU1),HL
 
                JR WRITE_CPU12
 
 
 
; восстановление текущей конфигурации страниц проецирования 1,2
 
WRITE_TMP_CPU12 LD BC,0
 
TMP_BB_CPU1     EQU $-2
 
                LD A,C
 
                LD C,LOW (WIN_A0)
 
                OUT (C),A
 
                LD BC,0
 
TMP_BB_CPU2     EQU $-2
 
                LD A,C
 
                LD C,LOW (WIN_A0)
 
                OUT (C),A
 
                RET
 
 
 
; чтение конфигурации окон проецирования 1,2
 
READ_CPU12      LD BC,RD_RAMNROM
 
                IN L,(C)                        ; биты RAM & ROM
 
                INC B
 
                IN H,(C)                        ; биты DOS & 7FFD
 
                ADD HL,HL
 
                LD B,HIGH (RD_1WINA1)
 
                IN A,(C)
 
                CP 0xC0
 
                JR NC,.L1
 
                LD E,A
 
                LD D,HIGH (WIN_P1)
 
                JR .L2
 
 
 
.L1             RLCA
 
                RLCA
 
                SLA L
 
                RRA
 
                SLA H
 
                RRA
 
                LD E,A
 
                LD D,HIGH (WIN_A1)
 
.L2             LD (BB_CPU1),DE
 
                INC B
 
                IN A,(C)
 
                CP 0xC0
 
                JR NC,.L3
 
                LD E,A
 
                LD D,HIGH (WIN_P2)
 
                JR .L4
 
 
 
.L3             RLCA
 
                RLCA
 
                SLA L
 
                RRA
 
                SLA H
 
                RRA
 
                LD E,A
 
                LD D,HIGH (WIN_A2)
 
.L4             LD (BB_CPU2),DE
 
                RET
 
 
 
; проверка наличия виртуального диска
 
DISK_NONE       PUSH HL
 
                PUSH BC
 
                CALL READ_CPU12
 
                LD BC,WIN_A1
 
                LD A,0x40
 
                OUT (C),A
 
                LD B,HIGH (WIN_P1)
 
                LD A,RAM_RAMDISK
 
                OUT (C),A
 
                LD HL,CPU1 + 0x3FFF
 
                LD A,(HL)
 
                DEC H
 
                CP "R"
 
                SCF
 
                JR NZ,.L1
 
                LD A,(HL)
 
                CP "D"
 
                SCF
 
                JR NZ,.L1
 
                XOR A
 
.L1             PUSH AF
 
                CALL WRITE_CPU12
 
                POP AF
 
                POP BC
 
                POP HL
 
                RET
 
 
 
; на входе: H-адрес ячейки
 
;           L-прочитанное значение
 
READCMOS        PUSH BC
 
                LD BC,CMOSD_SET_ADR
 
                OUT (C),H
 
                LD B,HIGH (CMOSD_RD_WR)
 
                IN L,(C)
 
                POP BC
 
                LD A,L
 
                AND A
 
                RET
 
 
 
        JP_EMU 0x3C30                           ; IN    A, (0x1F)
 
 
 
                DB 0x3D2F - $ DUP 0
 
                NOP
 
                RET
 
 
 
        JP_EMU 0x3D4D                           ; OUT      (0xFF), A
 
        JP_EMU 0x3D9A                           ; OUT      (0x1F), A
 
        JP_EMU 0x3DA6                           ; IN    A, (0xFF)
 
        JP_EMU 0x3DB5                           ; IN    A, (0x1F)
 
        JP_EMU 0x3DBA                           ; IN    A, (0x1F)
 
        JP_EMU 0x3DD5                           ; OUT      (0xFF), A
 
        JP_EMU 0x3E30                           ; IN    A, (0x1F)
 
        JP_EMU 0x3E3A                           ; IN    A, (0x1F)
 
        JP_EMU 0x3E44                           ; OUT      (0x7F), A
 
 
 
                DB 0x3E49 - $ DUP 0
 
                JP ADR_0x3E4C                   ; для адреса 0x3E4C
 
 
 
;               JP_EMU 0x3E4C                   ; OUT      (0x7F), A
 
                DB 0x3E4C - $ DUP 0
 
                OUT (EXIT_PORT),A
 
                JR 0x3E49
 
 
 
        JP_EMU 0x3E50                           ; IN    A, (0x3F)
 
        JP_EMU 0x3E78                           ; IN    A, (0x3F)
 
        JP_EMU 0x3E7E                           ; OUT      (0x3F), A
 
        JP_EMU 0x3E87                           ; IN    A, (0x3F)
 
        JP_EMU 0x3E95                           ; OUT      (0x3F), A
 
        JP_EMU 0x3EB5                           ; IN    A, (0x1F)
 
        JP_EMU 0x3EBC                           ; IN    A, (0x3F)
 
        JP_EMU 0x3EC9                           ; OUT      (0x1F), A
 
        JP_EMU 0x3ECE                           ; IN    A, (0xFF)
 
        JP_EMU 0x3EDF                           ; OUT      (0x1F), A
 
 
 
                DB 0x3EF3 - $ DUP 0             ; IN    H, (C)
 
                OUT (EXIT_PORT),A
 
                JR JUMP_0x3EF3
 
 
 
                JR JUMP_0x3EF5                  ; IN    A, (0xFF)
 
 
 
EXIT_0x3EF5     OUT (EXIT_PORT),A
 
JUMP_0x3EF5     JP ADR_0x3EF5
 
 
 
;       JP_EMU 0x3EF5                           ; IN    A, (0xFF)
 
        JP_EMU 0x3EFE                           ; IN    A, (0x7F)
 
 
 
JUMP_0x3EF3     JP ADR_0x3EF3
 
 
 
                JP_EMU 0x3F1B                   ; OUT      (0x5F), A
 
                JP_EMU 0x3F25                   ; OUT      (0x1F), A
 
                JP_EMU 0x3F33                   ; IN    A, (0x1F)
 
 
 
                DB 0x3F40 - $ DUP 0             ; для адреса 0x3EF3
 
                JP ADR_0x3EF3
 
 
 
        JP_EMU 0x3F4D                           ; OUT      (0x1F), A
 
        JP_EMU 0x3F55                           ; IN    A, (0x3F)
 
        JP_EMU 0x3F5A                           ; IN    A, (0x5F)
 
        JP_EMU 0x3F69                           ; IN    A, (0x3F)
 
        JP_EMU 0x3F72                           ; IN    A, (0x5F)
 
 
 
        JP_EMU 0x3FBC                           ; IN    A, (0xFF)       ;запись сектора
 
 
 
                DB 0x3FC7 - $ DUP 0
 
JUMP_0x3FF0     JP ADR_0x3FF0
 
 
 
        JP_EMU 0x3FCA                           ; IN    A, (0xFF)       ;запись сектора
 
        JP_EMU 0x3FD1                           ; OUTI                  ;запись сектора
 
 
 
        JP_EMU 0x3FD7                           ; IN    A, (0xFF)       ;чтение сектора
 
 
 
JUMP_0x3FEC     JP ADR_0x3FEC
 
JUMP_0x3FF3     JP ADR_0x3FF3
 
 
 
        JP_EMU 0x3FE5                           ; IN    A, (0xFF)       ;чтение сектора
 
 
 
;       JP_EMU 0x3FEC                           ; INI                   ;чтение сектора
 
                DB 0x3FEC - $ DUP 0
 
                OUT (EXIT_PORT),A
 
                JR JUMP_0x3FEC
 
 
 
;               DB 0x3FF0 - $ DUP 0             ; OUT      (C), A
 
                OUT (EXIT_PORT),A
 
                DB 0x18                         ; JR 0x3FC7
 
 
 
;               DB 0x3FF5 - $ DUP 0             ; IN    A, (C)
 
                OUT (EXIT_PORT),A
 
                JP JUMP_0x3FF3
 
 
 
                DB 0x3FF8 - $ DUP 0
 
                DB "EVOSFE"
 
                DW DATA_VERS