Login

Subversion Repositories NedoOS

Rev

Rev 997 | Rev 1012 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

        DEVICE ZXSPECTRUM1024
        include "../_sdk/sys_h.asm"

;STACK=0x4000
atm=1
;emul=в 0 [#8000..#BFFF]
;основной набор регистров=в альтернативном наборе
;PC=в DE
;текущий индексный=в IX
;не текущий индексный=в _IZ
;SP=в _SP (todo в (SP)?)

;брякпойнты для скорости можно ставить на обработчиках
;КОНКРЕТНОЙ команды

STACK=#BB00
D1SBUF=#BB00
;IMTAB=#BC00
;IMER=#BDBD

stats=0 ;статистика по опкодам
margins=0
fullmem=1 ;0=16k mem (fast, don't work without ROM), 1=48/128/512k mem (slow)
extpg5=0 ;1=стр5 лежит в pg5,иначе в #4000(без перехвата экрана)
         ;для 16k нельзя
        ;экран надо строить редко, в scr2

skipIM1=1 ;1=вместо трассировки #38 вызываем ее (если IY=23610)
showimtime=0 ;на бордюре

        MACRO OUTPG
        SETPGC000
        ENDM

        MACRO getmem
        mem
        LD A,(HL)
        ENDM

        MACRO _Loop_
        JP (IY) ;EMULOOP (нужный marg или нужный обработчик b/p)
        ENDM

;если вместо стр.команд включили др.стр.
        MACRO _LoopC
        OUTcom
        JP (IY)
        ENDM

;если резко сменился PC (полный DE)
        MACRO _LoopJP
        CALCiypgcom
        JP (IY)
        ENDM

;если выключили др.стр. и резко сменился PC (полный DE)
        MACRO _LoopC_JP
        CALCiypgcom
        JP (IY)
        ENDM

;если IN/OUT (могла измениться конфигурация памяти)
        MACRO _LoopSWI
        CALCpgcom
        JP (IY)
        ENDM

        MACRO next
        INC DE
        ENDM

;BC,DE,HL,AF -> BC
;rp=A&#30
        MACRO rptoBC
        AND #30
        OR #C5 ;PUSH rp
        LD ($+5),A
        EXX
        EXA
        PUSH BC ;DE;HL;AF
        EXX
        EXA
        POP BC
        ENDM

;BC,DE,HL,AF <- BC
;rp=A&#30
        MACRO BCtorp
        AND #30
        OR #C1 ;POP rp
        PUSH BC
        LD ($+5),A
        EXX
        EXA
        POP BC ;DE;HL;AF
        EXX
        EXA
        ENDM

;берем смещение d
;результат HL=IX+d
        MACRO getdIXtoHL
        get
        next
        LD L,A
        RLA
        SBC A,A
        LD H,A
        PUSH IX
        POP BC
        ADD HL,BC
        ENDM

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       IF fullmem
;портит HL,BC!
;оптимизен slow (там в 95% случаев стек)
        MACRO mem
        ;LOCAL
        LD A,H
        ADD A,A
        jr NC,4f;lo
          JP M,3f;pg
            SET 6,H
            LD A,(curpg2)
           JP 5f;o
3;pg
           LD A,(curpghi)
           JP 5f;o
4;lo
            JP M,6f;sl
            LD A,H
            OR #C0
            LD H,A
            LD A,(currom)
       IF extpg5
           JP 5f;o
6;sl
            LD A,(curpg5)
            SET 7,H
       ENDIF
5;o
        OUTPG
       IF extpg5==0
6;sl
       ENDIF
        ;ENDL
        ENDM

;портит HL,A!
      IF 1
        MACRO getmemBC
        ;LOCAL
       PUSH HL
        mem
        LD C,(HL)
        INC L
        JP NZ,1f;q
       POP HL
       PUSH BC
        INC HL
        mem
       POP BC
        JP $+4
1;q
       POP AF ;просто скипаем
        LD B,(HL)
        ;ENDL
        ENDM
      ELSE
        MACRO getmemBC
        ;LOCAL
       PUSH HL
        INC HL
        getmem
       POP HL
       PUSH AF
        getmem
       POP BC
        LD C,A
        ;ENDL
        ENDM
      ENDIF

;портит BC,HL!
        MACRO putmem
        ;LOCAL
        ;module lcl
        ;LD (aa),A
        ld ($+0x28),a
        LD A,H
        ADD A,A
        jr NC,4f;lo
          JP M,3f;pg
            SET 6,H
            LD A,(@curpg2)
           JP 5f;o
3;pg
           LD A,(@curpghi)
       IF @extpg5
            CP @pg5
           JP NZ,5f;o
            RES 7,H
           JP 6f;sl
       ELSE
           JP 5f;o
       ENDIF
4;lo
          JP M,6f;sl
            LD A,(@romon0) ;0=ПЗУ, #C0=ОЗУ
            OR H
           JP P,1f;q ;невозможно putmem в ПЗУ
            LD H,A
            LD A,(@currom)
       IF extpg5
           JP 5f;o
6;sl
        BIT 5,H
        jr NZ,7f;ns
        LD A,L
        AND #1F
        CP 24
        jr NC,ns
         LD A,(aa)
         LD (HL),A ;экран
7;ns
        SET 7,H
        LD A,@pg5
       ENDIF
5;o
        OUTPG
       IF @extpg5==0
6;sl
       ENDIF
;aa=$+1
        LD (HL),0
1;q
        ;ENDL
        ;endmodule
        ENDM

;портит HL,A,BC!
;нельзя ускорить, иначе не перехватить экран
;сделать ветку?
;вообще не перехватывать экран?
        MACRO putmemBC
        ;LOCAL
       PUSH HL
       PUSH BC
        LD A,C
        putmem
       POP AF
       POP HL
        INC HL
        putmem
        ;ENDL
        ENDM
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       IF margins
        MACRO get
        LD A,(DE)
        ENDM

        MACRO getHL
        get
        next
        LD L,A
        get
        next
        LD H,A
        ENDM

        MACRO OUTcom
        LD A,(curpgcom)
        OUTPG
        ENDM

        MACRO CALCpgcom
        LD HL,(curquart)
        LD A,(HL)
        LD (curpgcom),A
        OUTPG
        ENDM

     ;перед JR/CALL/RST
        MACRO CALCpc
        LD A,(curquart)
        SUB currom
        RRCA
        RRCA
        XOR D
        AND #C0
        XOR D
        LD D,A
        ENDM

     ;после JR/JP/CALL/RST/RET (на входе - полный DE)
        MACRO CALCiypgcom
        LOCAL
        LD A,D
        ADD A,A
        jr NC,lo
          JP M,pg
            SET 6,D
            LD HL,curpg2
            LD IY,marg2
           JP o
pg          LD HL,curpghi
            LD IY,marg3
           JP o
lo        JP M,sl
            LD A,D
            OR #C0
            LD D,A
            LD HL,currom
            LD IY,marg0
           JP o
sl          LD HL,curpg5
            LD IY,marg1
            SET 7,D
o
        ENDL
        LD (curquart),HL
        LD A,(HL)
        LD (curpgcom),A
        OUTPG
        ENDM
;########################################
      ELSE
;без ускорения через margins
        MACRO OUTcom
        ENDM
        MACRO CALCpgcom
        ENDM
        MACRO CALCpc
        ENDM
        MACRO CALCiypgcom
        ENDM

;оптимизено ПЗУ и pg2
;портит BC!
        MACRO getnp
        ;LOCAL
        LD A,D
        ADD A,A
        jr NC,4f;lo
          JP M,3f;pg
            SET 6,D
            LD A,(curpg2)
           JP 5f;o
3;pg
           LD A,(curpghi)
           JP 5f;o
4;lo
       IF extpg5
          JP P,8f;r
            LD A,(curpg5)
            SET 7,D
           JP 5f;o
       ELSE
          JP M,9f;q
       ENDIF
8;r
            LD A,D
            OR #C0
            LD D,A
            LD A,(currom)
5;o
        OUTPG
9;q
        LD A,(DE)
        ;ENDL
        ENDM

        MACRO get
        PUSH DE
        getnp
        POP DE
        ENDM

;портит BC!
     IF 1
        MACRO getHL
        ;LOCAL
       PUSH DE
        getnp
        LD L,A
        INC E
        JP NZ,2f;x
       POP DE
       PUSH BC
        next
        get
       POP BC
        JP $+6
2;x
       LD A,(DE)
       POP DE
       INC DE
        next
        LD H,A
        ;ENDL
        ENDM
     ELSE
        MACRO getHL
        get
        next
        LD L,A
        get
        next
        LD H,A
        ENDM
     ENDIF
       ENDIF
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       ELSE ;16k mem

        MACRO OUTcom
        ENDM

        MACRO mem
        ENDM

        MACRO getmemBC
        LD C,(HL)
        INC HL
        LD B,(HL)
        ENDM

        MACRO putmem
        BIT 7,H
        jr NZ,$+3
        LD (HL),A
        ENDM

        MACRO putmemBC
        BIT 7,H
        jr NZ,$+3
        LD (HL),C
        INC HL
        BIT 7,H
        jr NZ,$+3
        LD (HL),B
        ENDM

        MACRO get
        LD A,(DE)
        ENDM

        MACRO getHL
        get
        next
        LD L,A
        get
        next
        LD H,A
        ENDM

        MACRO CALCpgcom
        ENDM

     ;перед JR/CALL/RST
        MACRO CALCpc
        ENDM

     ;после JR/JP/CALL/RST/RET (на входе - полный DE)
        MACRO CALCiypgcom
        ENDM
       ENDIF ;16k mem

;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

        ;ORG #8000
        org PROGSTART
begin
        ld sp,STACK
        OS_HIDEFROMPARENT
        ld e,3+0x80 ;keep
        OS_SETGFX ;e=0:EGA, e=2:MC, e=3:6912, e=6:text ;+SET FOCUS ;e=-1: disable gfx (out: e=old gfxmode)
        ld e,0
        OS_SETSCREEN
        ld e,0 ;color byte
        OS_CLS
        ;ld e,1
        ;OS_SETSCREEN
        ;ld e,0 ;color byte
        ;OS_CLS

        ld a,(user_scr0_high) ;ok
        ld (curpg5),a
        SETPG4000

        OS_GETMAINPAGES ;out: d,e,h,l=pages in 0000,4000,8000,c000, c=flags, b=id

        ld a,h
        ld (curpg2),a
        ld a,l
        ld (temulpgs+0),a

        ld b,25
waitstart0
        push bc
        YIELD
        pop bc
        djnz waitstart0

       if 1
        OS_NEWPAGE
        ld a,e
        ld (temulpgs+1),a
        OS_NEWPAGE
        ld a,e
        ld (temulpgs+3),a
        OS_NEWPAGE
        ld a,e
        ld (temulpgs+4),a
        OS_NEWPAGE
        ld a,e
        ld (temulpgs+6),a
        OS_NEWPAGE
        ld a,e
        ld (temulpgs+7),a
       endif

        ld de,path
        OS_CHDIR      

        ld de,diskname
        OS_OPENHANDLE
        ld a,b
        ld (diskhandle),a
       
        OS_NEWPAGE
        ld a,e
        LD (pgrom48),a
        ld de,trom48
        ld hl,0xc000
;de=имя файла
;hl=куда грузим (0xc000)
;a=в какой странице
        call loadfile_in_ahl

        OS_NEWPAGE
        ld a,e
        LD (pgrom128),a
        ld de,trom128
        ld hl,0xc000
;de=имя файла
;hl=куда грузим (0xc000)
;a=в какой странице
        call loadfile_in_ahl

        OS_NEWPAGE
        ld a,e
        LD (pgromDOS),a
        ld de,tromDOS
        ld hl,0xc000
;de=имя файла
;hl=куда грузим (0xc000)
;a=в какой странице
        call loadfile_in_ahl

        OS_NEWPAGE
        ld a,e
        LD (pgromSYS),a
        ld de,tromSYS
        ld hl,0xc000
;de=имя файла
;hl=куда грузим (0xc000)
;a=в какой странице
        call loadfile_in_ahl

        JP GO

        align 256
temulpgs
        ds 8

diskname
        db "SYS.TRD",0
       
pgrom48
        db 0
pgrom128
        db 0
pgromDOS
        db 0
pgromSYS
        db 0
       
rrdbuf  DB 0

_AF     DW 0 ;AF'
_BC     DW 0 ;BC'
_DE     DW 0 ;DE'
_HL     DW 0 ;HL'
_SP     DW 0
_IZ     DW 0
_R      DB 0
_I      DB 0
iff1    DB 0
iff2    DB 0
immode  DB 0 ;#18=IM2, иначе IM1
_fd     DB 0;#10 ;с точки зрения эмулимой проги
_fe     DB 0
dos3F   DB 0
dos5F   DB 0
dosFF   DB 0

;реальные банки
currom  DB 0;rom48;0
curpg5  DB 0;pg5
curpg2  DB 0;pg2
curpghi DB 0;pg0;#10
curscr  DB 0 ;0/8

romon0  DB 0 ;#C0=ОЗУ, 0=ПЗУ в нижних 16k
doson0  DB 0;-1 ;0=SYS/DOS, -1=48/128

loadfile_in_ahl
;de=имя файла
;hl=куда грузим (0xc000)
;a=в какой странице
        SETPGC000 ;включили страницу A в 0xc000
        push hl ;куда грузим
        OS_OPENHANDLE
        pop de ;куда грузим
        push bc ;b=handle
        ld hl,0x4000 ;столько грузим (если столько есть в файле)
        OS_READHANDLE
        pop bc ;b=handle
        OS_CLOSEHANDLE
        ret;jp setpgmainc000 ;включили страницу программы в c000, как было

path
        db "z80",0

trom48
        ;DB "2006.ROM",0
        ;DB "1982.ROM",0
        DB "48for128.rom",0
trom128
        DB "128tr.rom",0
tromSYS
        DB "GLUKPEN.ROM",0
tromDOS
        DB "DOS6_10E.ROM",0

sysvars
        incbin "goodsysv"
sz_sysvars=$-sysvars

swapimer
        di
        ld de,0x0038
        ld hl,oldimer
        ld bc,3
swapimer0
        ld a,(de)
        ldi ;[oldimer] -> [0x0038]
        dec hl
        ld (hl),a ;[0x0038] -> [oldimer]
        inc hl
        jp pe,swapimer0
        ei
        ret
oldimer
        jp on_int
        jp 0x0038+3

on_int
        jp IMER

GO
        LD SP,STACK

        ld hl,sysvars
        ld de,0x5b00
        ld bc,sz_sysvars
        ldir

        LD A,(curpg5);pg5
        CALL OUTA
        LD HL,#C000
        LD DE,#4000
        LD BC,#4000
        LDIR
       IF 0
       LD A,#10
       CALL CLPG
       LD A,#11
       CALL CLPG
       LD A,#13
       CALL CLPG
       LD A,#14
       CALL CLPG
       LD A,#16
       CALL CLPG
       LD A,#17
       CALL CLPG
       ENDIF

       if 1
        call swapimer
       else
        LD HL,IMTAB
        LD BC,256
        LD D,H
        ld E,B
        LD (HL),IMER&0xff
        LD A,H
        LDIR
        LD I,A
        IM 2
       endif

        LD A,(_fd)
        CALL eout7FFD

        LD BC,0
        LD DE,0
        LD HL,0
        PUSH HL
        POP AF
        EXX
        EXA
        LD IX,0
        LD DE,#0000 ;=PC
        EI

      IF margins
       LD HL,currom
       LD (curquart),HL
        LD A,(HL)
       LD (curpgcom),A
        OUTPG
        LD D,#C0
        LD IY,marg0 ;или адрес обработчика b/p, идущего туда
        JP (IY)

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

curquart
        DW currom
curpgcom
        DB 0;pg0;#10
marg0
        LD A,(DE) ;уже ORed #C000
        INC E
        JZ marg0i ;проигрыш 5 тактов
marg0iq LD L,A
        ld H,MAINCOMS/256
        LD C,(HL)
        INC H
        LD H,(HL)
        ld L,C
        JP (HL) ;след. байт команды - в (DE)
marg0i  INC D
        JP NZ,marg0iq
       LD HL,curpg5
       LD (curquart),HL
        LD A,(HL)
       LD (curpgcom),A
        OUTPG
        LD D,#C0
marg1adr=$+2
        LD IY,marg1 ;или адрес обработчика b/p, идущего туда
        JP marg1iq
marg1
        LD A,(DE) ;уже ORed #C000
        INC E
        jr Z,marg1i ;проигрыш 5 тактов
marg1iq LD L,A
        ld H,MAINCOMS/256
        LD C,(HL)
        INC H
        LD H,(HL)
        ld L,C
        JP (HL) ;след. байт команды - в (DE)
marg1i  INC D
        JP NZ,marg1iq
       LD HL,curpg2
       LD (curquart),HL
        LD A,(HL)
       LD (curpgcom),A
        OUTPG
        LD D,#C0
marg2adr=$+2
        LD IY,marg2 ;или адрес обработчика b/p, идущего туда
        JP marg2iq
marg2
        LD A,(DE) ;уже ORed #C000
        INC E
        jr Z,marg2i ;проигрыш 5 тактов
marg2iq LD L,A
        ld H,MAINCOMS/256
        LD C,(HL)
        INC H
        LD H,(HL)
        ld L,C
        JP (HL) ;след. байт команды - в (DE)
marg2i  INC D
        JP NZ,marg2iq
       LD HL,curpghi
       LD (curquart),HL
        LD A,(HL)
       LD (curpgcom),A
        OUTPG
        LD D,#C0
marg3adr=$+2
        LD IY,marg3 ;или адрес обработчика b/p, идущего туда
        JP marg2iq
marg3
        LD A,(DE)
        INC E
        jr Z,marg3i ;проигрыш 5 тактов
marg3iq LD L,A
        ld H,MAINCOMS/256
        LD C,(HL)
        INC H
        LD H,(HL)
        ld L,C
        JP (HL) ;след. байт команды - в (DE)
marg3i  INC D
        JP NZ,marg3iq
       LD HL,currom
       LD (curquart),HL
        LD A,(HL)
       LD (curpgcom),A
        OUTPG
        LD D,#C0
marg0adr=$+2
        LD IY,marg0 ;или адрес обработчика b/p, идущего туда
        JP marg0iq

      ENDIF ;margins
;---------------------------
       IF showimtime
        LD IY,EMUSHOWIMTIME
       ELSE
        LD IY,EMUCHECKQ
       ENDIF
       ;EMUDATABUS ;ШД0..2 на бордюр
       ;EMUADDRBUS ;ША8..10 ма бордюр
       ;EMUCHECKPOINT ;проверка адреса или условия
                      ;проверка числа тактов до INT?
EMUCHECKQ
        get
        next
       IF stats
       PUSH HL
        LD L,A
        LD H,comstats/256-1
        INC H
        INC (HL)
        jr Z,$-2
       POP HL
       ENDIF
        LD L,A
        ld H,MAINCOMS/256
        LD C,(HL)
        INC H
        LD H,(HL)
        ld L,C
        JP (HL)
;можно выиграть 11(-JP=1) тактов:
       ;LD L,A
       ;AND 3 ;3 для JP, а можно(?) целые п/п: 7/15/31
       ;ADD A,'MAINCOMS
       ;LD H,A
       ;JP (HL) ;L=код команды, если надо

CBPREFIX
        get
        next
        LD L,A
        ld H,CBCOMS/256
        LD C,(HL)
        INC H
        LD H,(HL)
        ld L,C
        JP (HL)

EDPREFIX
        get
        next
        LD L,A
        ld H,EDCOMS/256
        LD C,(HL)
        INC H
        LD H,(HL)
        ld L,C
        JP (HL)

FDPREFIX
DDPREFIX
oldprefix=$+1
        CP #DD
        jr Z,DDFDOLD
        LD (oldprefix),A
;сменили префикс! меняем местами IX и _IZ
        LD HL,(_IZ)
        LD (_IZ),IX
        PUSH HL
        POP IX
DDFDOLD get
        next
        LD L,A
        ld H,DDCOMS/256
        LD C,(HL)
        INC H
        LD H,(HL)
        ld L,C
        JP (HL)

DDCBPREFIX
        getdIXtoHL
       PUSH HL
        get
        next
        LD L,A
        ld H,DDCBCOMS/256
        LD C,(HL)
        INC H
        LD H,(HL)
        ld L,C
       EX (SP),HL
       RET

EMUDATABUS
        LD A,(DE)
       call outFE;OUT (-2),A
        JP EMUCHECKQ

EMUADDRBUS
        LD A,D
       call outFE;OUT (-2),A
        JP EMUCHECKQ

EMUCHECKPOINT
retfromim=$+1
        LD HL,0
        XOR A
        SBC HL,DE
        JP NZ,EMUCHECKQ
        LD A,(_fe)
       call outFE;OUT (-2),A
        JP EMUCHECKQ

OUTA
        PUSH BC
       ;LD BC,32765
       ;OUT (C),A
        OUTPG
        POP BC
        RET

EMUOUT
;BC=port, A=value
       BIT 0,C
       jr Z,eoutFE
       BIT 1,C
       jr Z,eoutFD
        PUSH AF
        LD A,(doson0)
        OR A
        jp Z,EMUOUTDOS
        POP AF
        RET
eoutFD
       BIT 7,B
       jr Z,eout7FFD
       BIT 6,B
       jr NZ,eoutFFFD
        LD BC,#BFFD
        OUT (C),A
        RET
eoutFFFD
        LD BC,#FFFD
        OUT (C),A
        RET
eout7FFD
        LD (_fd),A
        LD C,A
     ;пересчитываем номер банки (A=C -> A)
        AND #C7
        CP 5
        JR NZ,$+7
        LD A,(curpg5)
        JR eout7FFDOK
        CP 2
        JR NZ,$+7
        LD A,(curpg2)
        JR eout7FFDOK
     ;
       IF 0;atm
;%bb000bbb
        RRCA
        RRCA
        RRCA
        XOR C
        AND %11000
        XOR C
        AND %11111
        XOR #7F
       else
        and 7 ;TODO мегабайт захватывать динамически постранично
        ld l,a
        ld h,temulpgs/256
        ld a,(hl)
       ENDIF
eout7FFDOK
        LD (curpghi),A

        LD A,C
        AND 8 ;номер экрана
        LD B,A
        LD (curscr),A

       LD A,(doson0)
       OR A
       jr Z,eo7FFDdos
        BIT 4,C ;номер ПЗУ
        LD A,(pgrom48)
        jr NZ,$+5
        LD A,(pgrom128)
        JR eo7FFDo
eo7FFDdos
        BIT 4,C ;номер ПЗУ
        LD A,(pgromDOS)
        jr NZ,$+4
        LD A,(pgromSYS)
        JR eo7FFDo
eo7FFDo
       IF atm
        LD (currom),A
       ELSE
        LD C,#F7
        AND C
        OR B
        LD (currom),A
        LD HL,curpg5
        LD A,(HL)
        AND C
        OR B
        LD (HL),A
        LD HL,curpg2
        LD A,(HL)
        AND C
        OR B
        LD (HL),A
        LD HL,curpghi
        LD A,(HL)
        AND C
        OR B
        LD (HL),A
       ENDIF
        RET
eoutFE
        LD (_fe),A
        ;OUT (#FE),A
outFE
        OUT (#FE),A
       push af
       push bc
       push de
       push hl
       push ix
       push iy
       exx
       push bc
       push de
       push hl
       and 7
       ld e,a
       ex af,af' ;'
       push af
       OS_SETBORDER
       pop af
       ex af,af' ;'
       pop hl
       pop de
       pop bc
       exx
       pop iy
       pop ix
       pop hl
       pop de
       pop bc
       pop af
        RET
EMUOUTDOS
        LD A,C
        CP #3F
        jr Z,eod3F
        CP #5F
        jr Z,eod5F
        CP #FF
        jr Z,eodFF
        POP AF
        RET
eod3F
        POP AF
        LD (dos3F),A
        RET
eod5F
        POP AF
        LD (dos5F),A
        RET
eodFF
        POP AF
        LD (dosFF),A
        RET

EMUIN
;BC=port
;return A=value
       BIT 0,C
       jr Z,einFE
        LD A,(doson0)
        OR A
        jr Z,EMUINDOS
       LD A,C
       CP #DF
       jr Z,einMOUSE
        LD A,#FF
        RET
einMOUSE
       LD A,B
       CP #FA
       jr Z,einFADF
       CP #FB
       jr Z,einFBDF
       CP #FF
       jr Z,einFFDF
        LD A,#FF
        RET
;TODO from OS
einFADF
        LD BC,#FADF
        IN A,(C)
        RET
einFBDF
        LD BC,#FBDF
        IN A,(C)
        RET
einFFDF
        LD BC,#FFDF
        IN A,(C)
        RET
einFE
        ;LD C,#FE
        ;IN A,(C)
       push hl
       ld hl,keymatrix
       ld a,0xff
       dup 8
       rlc b
       jr c,$+3
       and (hl)
       inc hl
       edup
       pop hl
       and a
        RET
EMUINDOS
        LD A,C
        CP #1F
        jr Z,eid1F
        CP #3F
        jr Z,eid3F
        CP #5F
        jr Z,eid5F
        CP #5F
        jr Z,eidFF
        LD A,#FF
        RET
eidFF
        LD A,#80 ;INTRQ=команда выполнена ok
        RET
eid1F
        LD A,#80 ;команда выполнена ok, диск вставлен
        RET
eid3F
        LD A,(dos3F)
        RET
eid5F
        LD A,(dos5F)
        RET

keymatrix
        ds 8,0xff

imitret
        LD HL,(_SP)
        ex de,hl
        getHL
        ex de,hl
        LD (_SP),HL
        ret

DOSER
;подпрограмма
        LD A,(doson0)
        OR A
        jr NZ,DOSERny
        LD A,D
        CP #40
        jr C,DOSDOS ;DOS -> DOS
;DOS -> неDOS
;выкл. стр. доса
        LD A,-1
        LD (doson0),A
        LD A,(_fd)
        JP eout7FFD
DOSDOS
  ;для SYS не перехватываем!
        LD A,(_fd)
        AND 16
        RET Z
;TODO имитировать RET после неё
      ld hl,imitret
      push hl
;перехваты процедур доса
        CP #3F
        RET NZ
        LD A,E
        CP #D5 ;#3fd5
        jr Z,DOSWR
        CP #E5 ;#3fe5
        jr Z,DOSRD
        CP #BA ;#3fba
        RET NZ
DOSRD
     PUSH DE,IX,IY
     LD IY,23610
        EXX
        PUSH HL
        INC H
        EXX
        POP HL
        LD C,5
        LD A,(dos3F) ;trk
        DEC A
        ADD A,A
        LD D,A
        LD A,(dosFF)
        BIT 4,A
        jr Z,$+3
        INC D
        LD A,(dos5F) ;sec
        DEC A
        LD E,A
        CALL DOSrdsec
     POP IY,IX,DE
DOSWR
        RET

DOSERny
        LD A,D
        CP #3D
        RET NZ
  ;для 128 васика запрещено! иначе глючит калькулятор
        LD A,(_fd)
        AND 16
        RET Z
;неDOS -> DOS
;имитировать RET после неё
      ld hl,imitret
      push hl
       LD A,E
       CP #13
       jr Z,DOS3D13
DOSSWON
;вкл. стр. доса
;имитация RET не катит для точки #3D2F
        XOR A
        LD (doson0),A
        LD A,(_fd)
        JP eout7FFD
DOS3D13
       if 1
        exx
        ld a,c
        exx
        cp 6
        jr z,DOSWRSEC
        cp 5
        jr nz,DOSSWON ;(for other functions)
DOSRDSEC
DOSWRSEC
        exx
D3D5S0
        CALL DOSrdsec
        call DOSnextsec
        DJNZ D3D5S0
DOS3D13q
;write de to virtual 23796:
        ld hl,23796
        ld b,d
        ld c,e
        putmemBC
        exx
        ret
       if 0
DOSWRSEC
        exx
D3D6S0
        CALL DOSrdsec
        call DOSnextsec
        DJNZ D3D6S0
        jr DOS3D13
       endif
DOSnextsec
        inc h
        inc e
        bit 4,e
        ret z
        inc d
        ld e,0
        ret

DOSrdsec
;hl=addr
;d=track
;e=sector
;c=5(read)/6(write)
       PUSH BC
       PUSH de
       PUSH HL
       EXX
       EXA
        PUSH AF
        PUSH BC,DE,HL
        push ix,iy
       EXA
       EXX
        push hl ;addr
        ld a,e ;de=trsec
        add a,a
        add a,a
        add a,a
        add a,a
        ld l,d ;track
        ld h,0 ;0la=trsec*16
        dup 4
        add a,a
        adc hl,hl
        edup ;hl0=trsec*256
        ld d,a;0
        ld e,h
        ld h,l
        ld l,a;0
        ;dehl=shift
diskhandle=$+1
        ld b,0
       push bc ;c=5/6
        OS_SEEKHANDLE
       pop bc ;c=5/6, b=handle
        pop hl ;addr
       push bc
        mem ;paging
       pop bc
        ex de,hl ;de=phys addr      
        ld hl,256
       ld a,c
       cp 5
       jr z,DOSrdsec5
        OS_WRITEHANDLE
       jr DOSrdsec5ok
DOSrdsec5
        OS_READHANDLE
DOSrdsec5ok
       exx
       EXA
        pop iy,ix
        pop hl,de,bc
        pop af
       EXA
       EXX
        pop hl,de,bc    
        ret
       else
        EXX
        LD A,C
        EXX
        CP 1
        jr Z,DOS3D131
        CP 5
        jr Z,DOS3D135
        CP 6
        jr Z,DOS3D136
        JP DOSSWON
DOS3D136
DOS3D135
     PUSH DE,IX,IY
     LD IY,23610
        EXX
        PUSH BC,HL
        LD (23796),DE
        EXX
       IM 1
        POP HL,BC
D3D5S0
        LD DE,(23796)
        CALL DOSrdsec
        DJNZ D3D5S0
       IM 2
       ;POP
       ;EXX
     POP IY,IX,DE
DOS3D131
DOSRET
        POP AF
        JP RETER
DOSrdsec
       PUSH BC
       PUSH HL
        LD HL,D1SBUF
        PUSH HL
        LD B,1
       EXX
       EXA
        PUSH AF
        PUSH BC,DE,HL
       EXA
       EXX
        CALL #3D13
       EXX
       EXA
        POP HL,DE,BC
        POP AF
       EXA
       EXX
        POP DE
       POP HL
D3D50   LD A,(DE)
        putmem
        INC HL
        INC E
        jr NZ,D3D50
       POP BC
        RET
       endif

CLPG
        CALL OUTA
        LD HL,#C000
        LD DE,#C001
        LD B,#40
        LD (HL),L
        LDIR
        RET

        INCLUDE "z80cmd.asm"
        align 256
        INCLUDE "z80table.asm"
        DISPLAY $
       IF stats
        align 256
comstats
        DISPLAY "comstats=",$
        DS #400
       ENDIF


        include "rst38.asm"

        ;ds 0x3f00-$

        ;ORG IMER
IMER
        PUSH AF,HL
;здесь опрос клавиш эмулятора
        call oldimer
        push bc,de
        exx
        push bc
        push de
        push hl
        push ix
        push iy
        ex af,af' ;'
        push af
        OS_GETKEYMATRIX ;out: bcdehlix = halfrows cs...space
        ld (keymatrix),ix
        ld (keymatrix+2),hl
        ld (keymatrix+4),de
        ld (keymatrix+6),bc
        pop af
        ex af,af' ;'
        pop iy
        pop ix
        pop hl
        pop de
        pop bc
        exx
        pop de,bc
       
;
       LD A,(iff1)
       OR A
       jr NZ,IMEREI
        POP HL,AF
        EI
        RET
IMEREI
        XOR A
        LD (iff1),A
        LD (iff2),A ;для NMI надо только iff1!
;перед эмуляцией INT завершаем тек.команду (перехват на EMULOOP)
       IF margins==0
        LD (keepemuchecker),IY
        LD IY,IMINT
       ELSE
        LD HL,marg0
        LD (HL),205
        INC HL
        LD (HL),IMINT&0xff
        INC HL
        LD (HL),IMINT/256
        LD HL,marg1
        LD (HL),205
        INC HL
        LD (HL),IMINT&0xff
        INC HL
        LD (HL),IMINT/256
        LD HL,marg2
        LD (HL),205
        INC HL
        LD (HL),IMINT&0xff
        INC HL
        LD (HL),IMINT/256
        LD HL,marg3
        LD (HL),205
        INC HL
        LD (HL),IMINT&0xff
        INC HL
        LD (HL),IMINT/256
       ENDIF
        POP HL,AF
        RET  ;di!
IMINT
       IF margins==0
keepemuchecker=$+2
        LD IY,0
       ELSE
        POP HL
        DEC HL,HL,HL ;здесь мы должны быть
        PUSH HL
        LD HL,marg0
        LD (HL),26 ;ld a,(de)
        INC HL
        LD (HL),28 ;inc e
        INC HL
        LD (HL),40 ;jz
        LD HL,marg1
        LD (HL),26 ;ld a,(de)
        INC HL
        LD (HL),28 ;inc e
        INC HL
        LD (HL),40 ;jz
        LD HL,marg2
        LD (HL),26 ;ld a,(de)
        INC HL
        LD (HL),28 ;inc e
        INC HL
        LD (HL),40 ;jz
        LD HL,marg3
        LD (HL),26 ;ld a,(de)
        INC HL
        LD (HL),28 ;inc e
        INC HL
        LD (HL),40 ;jz
       ENDIF
       LD (retfromim),DE ;для индикации времени обработки прерыв
       LD A,(immode)
       CP #18 ;IM2
        LD HL,#38 ;new PC
       jr NZ,IMERIM1
        LD HL,(_I-1)
        LD L,#FF ;состояние пассивной ШД
        LD A,(HL)
        INC HL
        LD H,(HL)
        ld L,A
        JR IMERIM
GETIY
        LD HL,(_IZ)
        LD A,(oldprefix)
        CP #DD
        RET Z
        PUSH IX
        POP HL
        RET
IMERIM1
     IF skipIM1
       PUSH HL
        CALL GETIY
        LD BC,23610
        OR A
        SBC HL,BC
       POP HL
        JR NZ,IMERIM
;вообще-то надо и SP проверить...
    IF extpg5
        PUSH DE
        LD A,(curpg5)
        CALL OUTA
        LD DE,#5C00
        LD HL,#DC00
        LD BC,146
        LDIR
    ENDIF
      push ix
      PUSH IY
      LD IY,23610
      call L0038;basicrst38
      LD A,-1
      LD (iff1),A
      LD (iff2),A
      POP IY
      pop ix
    IF extpg5
        LD HL,#5C00
        LD DE,#DC00
        LD BC,146
        LDIR
        POP DE
    ENDIF
     _LoopC ;RET уже был (адрес со стека снят)
     ENDIF
IMERIM
       IF showimtime
       LD A,1
       call outFE;OUT (-2),A
       ENDIF
        EI
       CALCpc
        EX de,hl
                   ;DE=new PC
        LD B,H
        ld C,L ;BC=old PC
        LD HL,(_SP)
        DEC HL,HL
        LD (_SP),HL
        putmemBC
       _LoopC_JP



end

        savebin "z80.com",begin,end-begin

        LABELSLIST "../../us/user.l"