Login

Subversion Repositories NedoOS

Rev

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

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

;emul=в 0000
;основной набор регистров=в альтернативном наборе
;PC=в DE
;текущий индексный=в IX
;не текущий индексный=в _IZ
;SP=в _SP (todo в (SP)? но там сейчас jpiyer для выхода из DOSER. сделать в DOSER 2-байтный патч?)

STACK=0x4000

stats=0 ;статистика по опкодам

margins=1 ;1=хранить в de уже пересчитанный PC
MEM48C0=1 ;8000,c000 - всегда замапленные страницы ;4000 - страница ПЗУ или текущая 4000 (каждый раз включать)

extpg5=0 ;1=стр5 лежит в pg5,иначе в #4000(без перехвата экрана)
        ;экран надо строить редко, в scr2

skipIM1=1 ;1=вместо трассировки #38 вызываем ее (если IY=23610)

        MACRO OUTPG
        SETPGC000
        ENDM

       if margins
        MACRO OUTPGCOM
        SETPG4000
        ENDM
       endif

        MACRO OUTPG4000
        SETPG4000
        ENDM

        MACRO _Loop_
        JP (IY) ;EMULOOP
        ENDM

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

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

;если эмулятор щёлкал страницу и резко сменился PC (полный DE)
        MACRO _LoopC_JP
        CALCiypgcom
        jp DOSER
        ENDM
        MACRO _LoopC_JP_NODOS
        CALCiypgcom
        JP (IY)
        ENDM

;если IN/OUT (могла измениться конфигурация памяти - но там внутри уже CALCpgcom)
        MACRO _LoopSWI
        ;CALCpgcom
        JP (IY)
        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 margins
        include "mem_marg.asm"
       else
       if MEM48C0
        include "mem_48c0.asm"
       else
        include "mem_c000.asm"
       endif
       endif

        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 ;color byte
        ;OS_CLS

        OS_GETMAINPAGES ;out: d,e,h,l=pages in 0000,4000,8000,c000, c=flags, b=id
       push hl
        ld hl,temulpgs
        ld a,d
        ld (deadpg),a
        ld (hl),d
        ld d,h
        ld e,l
        inc de
        ld bc,64-1
        ldir

        ld a,(user_scr0_high) ;ok
        ld (curpg5),a
        ld (temulpgs+5),a
        SETPG4000
        ld a,(user_scr1_high) ;ok
        ld (temulpgs+7),a

        ;OS_GETMAINPAGES ;out: d,e,h,l=pages in 0000,4000,8000,c000, c=flags, b=id
       pop hl
        ld a,h
        ld (curpg2),a
        ld (temulpgs+2),a
        ld a,l
        ld (temulpgs+0),a

        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

        ;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

        call swapimer

;хотя бы одно прерывание, чтобы захватить матрицу клавиатуры
        ld b,25
waitstart0
        halt ;не YIELD, иначе наш обработчик не вызовется!
        djnz waitstart0

       ;ld a,-1
       ;ld (doson0),a
        xor a
        ld (doson0),a
        ld (_dffd),a
       ;ld a,0x10
        ld (_fd),a
        ;LD A,(_fd)
        CALL eout7FFD

       if 0
        LD HL,0
        ld d,h
        ld e,l
        ld b,h
        ld c,l
        PUSH HL
        POP AF
        ld (immode),a
        PUSH HL
        POP ix
        ld (_IZ),hl
        ld (_AF),hl
        ld (_BC),hl
        ld (_DE),hl
        ld (_HL),hl
        EXX
        EXA
       endif

      IF margins
       LD HL,currom
       LD (curquart),HL
        LD A,(HL)
        OUTPGCOM
        ld de,0x4000 ;пересчитанный PC
      else
        LD DE,0x0000 ;=PC
      endif

        LD IY,EMUCHECKQ
       ;EMUDATABUS ;ШД0..2 на бордюр
       ;EMUADDRBUS ;ША8..10 ма бордюр
       ;EMUCHECKPOINT ;проверка адреса или условия
                      ;проверка числа тактов до INT?
jpiyer
        ld hl,jpiyer
        push hl
        jp (iy)

;oldpc
;        dw 0

EMUCHECKQ
       ;ld a,(0x4000)
       ;or a
       ;jr z,$
       ;ld (oldpc),de
        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=код команды, если надо ;но надо менять обработчики, они сейчас ждут код в A!
;или ld l,a:ld h,NN:ld h,(hl):jp (hl)
;или ld l,a:or 0xc0:ld h,a:jp (hl)

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)
       OUT (-2),A
        JP EMUCHECKQ

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

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

;OUTA
;        PUSH BC
;        OUTPG
;        POP BC
;        RET

EMUOUT
;BC=port, A=value
       BIT 0,C
       jp 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
       BIT 5,B
       jr z,eoutDFFD
        LD BC,#FFFD
        OUT (C),A
        RET
eoutDFFD
        ld (_dffd),a
        ld a,(_fd)
eout7FFD
        LD (_fd),A
        LD C,A
        AND #C7
        and 7
        ld l,a
       ld a,(_dffd)
       and 3 ;Profi 512K
       add a,a
       add a,a
       add a,a
       add a,l
       ld l,a
        ld h,temulpgs/256
        ld a,(hl)
deadpg=$+1
        cp 0
        jr nz,eout7FFDOK
       push bc
       push de
       push hl
       exx
       push bc
       push de
       push hl
       push ix
       push iy
       exa
       push af
       OS_NEWPAGE ;мегабайт захватывать динамически постранично
       pop af
       exa
        ld a,e
       pop iy
       pop ix
       pop hl
       pop de
       pop bc
       exx
       pop hl
       pop de
       pop bc      
        ld (hl),a
eout7FFDOK
        LD (curpghi),A
       if MEM48C0
        push bc
        OUTPG
        pop bc
       endif

       LD A,(doson0) ;DOS ports on ;TODO separate flag for DOS ROM select ;TODO RAM in 0000
       OR A
       jr Z,eo7FFDdos
        BIT 4,C ;номер ПЗУ
        ld b,DOSSTATE_FROM48
        LD A,(pgrom48)
        jr NZ,eo7FFDo
        ld b,DOSSTATE_FROM128
        LD A,(pgrom128)
        JR eo7FFDo
eo7FFDdos
        BIT 4,C ;номер ПЗУ
        ld b,DOSSTATE_FROMDOS
        LD A,(pgromDOS)
        jr NZ,eo7FFDo
        LD A,(pgromSYS)
        ;JR eo7FFDo
eo7FFDo
        LD (currom),A
        ld a,b
        ld (DOSER_state),a

        LD A,C
        AND 8 ;номер экрана
        LD (curscr),A
oldcurscr7ffd=$+1
        cp 0
        jr z,eo7FFDnoscr
        ld (oldcurscr7ffd),a
       ;push bc
       push de
       ;push hl
       exx
       push bc
       push de
       push hl
       push ix
       push iy
        rrca
        rrca
        rrca
        ld e,a
       exa
       push af
       OS_SETSCREEN
       pop af
       exa
       pop iy
       pop ix
       pop hl
       pop de
       pop bc
       exx
       ;pop hl
       pop de
       ;pop bc
eo7FFDnoscr
      if MEM48C0
       if margins
        CALCpgcom
       else
enable0000
        ld a,0x3e;3a
        ld (setrom),a
        ld (getde0000ret),a
       endif
      endif
        RET
eoutFE
        LD (_fe),A
outFE
        OUT (#FE),A
        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 0xfd
       jr z,einAY
       CP #DF
       jr Z,einMOUSE
       CP #1F
       jr Z,einKEMPSTON
        LD A,#FF
        RET
einAY
        ld bc,0xfffd
        in a,(c)
        ret
einMOUSE
       LD A,B
       CP #FA
       jr Z,einFADF
       CP #FB
       jr Z,einFBDF
       CP #FF
       jr Z,einFFDF
        LD A,#FF
        RET
einFADF
        ;LD BC,#FADF
        ;IN A,(C)
mousebuttons=$+1
        ld a,0xff
        RET
einFBDF
        ;LD BC,#FBDF
        ;IN A,(C)
mousex=$+1
        ld a,0
        RET
einFFDF
        ;LD BC,#FFDF
        ;IN A,(C)
mousey=$+1
        ld a,0
        RET
einKEMPSTON
        ;IN A,(#1f)
kempston=$+1
        ld a,0
        RET
einFE
        ;LD C,#FE
        ;IN A,(C)
        ;ld a,b
        ;or a
        ;jr z,$
       push hl
       ld hl,keymatrix
       ld a,0xff
       dup 8
       rlc b
       jr c,$+3
       and (hl)
       inc hl
       edup
       pop hl
       and a
        ;LD C,#FE
        ;IN A,(C)
        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
        ld a,r
        rla
        and 0xc0 ;D6=DRQ, D7=INTRQ
        RET
eid1F
        ;LD A,#80 ;команда выполнена ok, диск вставлен
        ld a,r
fddstatemask=$+1
        and 3
        or 0x80
        RET
eid3F
        LD A,(dos3F) ;trk
        RET
eid5F
        LD A,(dos5F) ;sec
        RET

keymatrix
        ds 8,0xff

       if 0
imitret
        LD HL,(_SP)
        getmemBC
        LD (_SP),HL
        ld d,b
        ld e,c
       _LoopC_JP
       endif

DOSrdindex
        LD A,E
        cp #08
        jr z,DOSsetheadwait
        CP #b2 ;#3eb2
        jr nz,jpiy;ret nz
;Адрес #3EB2. Проверка индексной области дорожки. Установите #5CD1 и поместите в B время перемещения головки дисковода. Выбирается верхняя сторона и при ошибке в #5D17 помещается #FF. В регистр H помещается номер текущей дорожки. Используется также с адреса: #3EE7 (обработка ошибки NO DISC).
       ld a,(dos3F) ;trk
       exx
       ld h,a
       exx
        jp imitret
DOSsetheadwait
        ld a,3
        ld (fddstatemask),a ;костыль!!!
        jp imitret

DOSER
;после каждой команды, меняющей PC ;выход по jp (iy)
;если мы не в досе, то проверяем, что D=#3D
;если мы в досе, то проверяем, что D<=#40
;если мы в 128K (TODO или в ОЗУ 0000), то ничего не делаем
DOSSTATE_FROM48=0x18 ;jr DOSERny
DOSSTATE_FROMDOS=0x3e ;ld a,N (skip jr)
DOSSTATE_FROM128=0xc9 ;ret
        ;LD A,(doson0)
        ;OR A
        ;jr NZ,DOSERny
DOSER_state=$
        jr DOSERny
       if margins
        ld a,(curquart)
        cp 3 ;0000?
        jr z,DOSDOS ;DOS -> DOS
       else
        LD A,D
        CP #40
        jr C,DOSDOS ;DOS -> DOS
       endif
;DOS -> неDOS
;выкл. стр. доса
        LD A,-1
        LD (doson0),A ;DOS ports off
        ld a,DOSSTATE_FROM48
        ld (DOSER_state),a
        LD A,(_fd)
        call eout7FFD
jpiy
        jp (iy)
DOSDOS
  ;для SYS не перехватываем!
        LD A,(_fd)
        AND 16
        jr z,jpiy;RET Z
        ld a,d
;перехваты процедур доса
       if margins
        cp 0x3e+0x40
       else
        cp 0x3e
       endif
        jr z,DOSrdindex
       if margins
        cp 0x3f+0x40
       else
        cp 0x3f
       endif
        jr nz,jpiy;RET NZ ;не перехватываем
;имитировать RET после неё
        LD A,E
        CP #D5 ;#3fd5
        jr Z,DOSRD
        CP #E5 ;#3fe5
        jr Z,DOSRD
        CP #BA ;#3fba
        jr z,DOSWR
        jp (iy) ;RET NZ
DOSRD
        xor a
        ld (fddstatemask),a ;костыль!!! иначе читает через раз
     PUSH DE,IX,IY
        EXX
        PUSH HL
        INC H
        EXX
        POP HL
        LD C,5
        LD A,(dos3F) ;trk
        ADD A,A
        LD D,A
        LD A,(dosFF)
        BIT 4,A
        jr nz,$+3
        INC D
        LD A,(dos5F) ;sec
        DEC A
        LD E,A
        CALL DOSrdsec
     POP IY,IX,DE
DOSWR
;TODO
        jp imitret

DOSERny
;from 48/RAM
       if margins
        ld a,d
        cp 0x3d+0x40
        jr nz,jpiy;RET NZ
        ld a,(curquart)
        cp 3 ;0000?
        jr nz,jpiy;RET NZ
       else
        LD A,D
        CP #3D
        jr nz,jpiy;RET NZ
       endif
  ;для 128 васика запрещено! иначе глючит калькулятор
        ;LD A,(_fd)
        ;AND 16
        ;RET Z
;неDOS -> DOS
       LD A,E
       CP #13
       jr Z,DOS3D13 ;если убрать, будет значительно медленнее
DOSSWON
;вкл. стр. доса
;имитация RET не катит для точки #3D2F
        XOR A
        LD (doson0),A ;DOS ports on
        ld a,DOSSTATE_FROMDOS
        ld (DOSER_state),a
        LD A,(_fd)
        call eout7FFD
        jp (iy)
DOS3D13
        exx
        ld a,c
        exx
        cp 6
        jr z,DOSWRSEC
        cp 5
        jr nz,DOSSWON ;(for other functions)
DOSRDSEC
DOSWRSEC
        exx
D3D5S0
        CALL DOSrdsec ;c=5(read)/6(write)
        inc h
        inc e
        bit 4,e
        jr z,$+5
        inc d
        ld e,0
        DJNZ D3D5S0
;write de to virtual 23796:
        ld hl,23796
        ld b,d
        ld c,e
        putmemBC
        exx
       jp imitret ;имитировать 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 in file
diskhandle=$+1
        ld b,0
       push bc ;c=5/6
        OS_SEEKHANDLE
       pop bc ;c=5/6, b=handle
        pop hl ;addr
       bit 0,c
       jr nz,DOSrdsec5
        ld de,secbuf
        push bc
        push de
        ld b,0
DOSwrseccopy0
        push bc
        push hl
        getmem
        ld (de),a
        pop hl
        pop bc
        inc hl
        inc de
        djnz DOSwrseccopy0
        pop de ;secbuf
        pop bc ;b=handle
        ld hl,256 ;de=phys addr ;hl=size
        OS_WRITEHANDLE
       jr DOSrdsec5ok
DOSrdsec5
         push hl ;addr
         ld de,secbuf
         push de
        ld hl,256 ;size
        OS_READHANDLE
         pop hl ;secbuf
         pop de ;addr
        ex de,hl ;de->hl
        ld b,0
DOSrdseccopy0
        push bc
        push hl
        ld a,(de)
        putmem
        pop hl
        pop bc
        inc hl
        inc de
        djnz DOSrdseccopy0
DOSrdsec5ok
       exx
       EXA
        pop iy,ix
        pop hl,de,bc
        pop af
       EXA
       EXX
        pop hl,de,bc    
        ret

        INCLUDE "disasm.asm"

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

        include "rst38.asm"

on_int
        ;jp IMER
;IMER
        PUSH AF,HL
        push bc,de
        exx
        push bc
        push de
        push hl
        push ix
        push iy
        ex af,af' ;'
        push af

        ld a,(curscr)
oldcurscr=$+1
        cp 0
        jr z,IMERnoscr
        ld (oldcurscr),a
        rrca
        rrca
        rrca
        ld e,a
        OS_SETSCREEN
IMERnoscr

        ld a,(_fe)
        and 7
oldcurborder=$+1
        cp 0
        jr z,IMERnoborder
        ld (oldcurborder),a
        ld e,a
        OS_SETBORDER
IMERnoborder
        call oldimer

       if 0
        ld bc,0x7ffe
        in a,(c)
        ld lx,a  ;lx=%???bnmS_
        ld b,0xbf
        in a,(c)
        ld hx,a  ;hx=%???hjklE
        ld b,0xdf
        in l,(c)  ;l=%???yuiop
        ld b,0xef
        in h,(c)  ;h=%???67890
        ld b,0xf7
        in e,(c)  ;e=%???54321
        ld b,0xfb
        in d,(c)  ;d=%???trewq
        ld a,0xfd
        in a,(0xfe);c=%???gfdsa
        ld b,c;0xfe
        in b,(c)  ;b=%???vcxzC
        ld c,a
       else
        OS_GETKEYMATRIX ;out: bcdehlix = halfrows cs...space
       endif
        ld (keymatrix),ix
        ld (keymatrix+2),hl
        ld (keymatrix+4),de
        ld (keymatrix+6),bc
        OS_GETKEY
;        A - код символа(кнопки). Допустимые коды смотри в 'sysdefs.asm' секция 'Usable key codes'
;        C - код символа(кнопки) без учета текущего языкового модификатора. Как правило, используется дляи обработки "горячих кнопок"
;        DE - позиция мыши (y,x) (возвращает 0 при отсутствии фокуса)
;        L - кнопки мыши (bits 0(LMB),1(RMB),2(MMB): 0=pressed; bits 7..4=положение колёсика)
;        LX - Kempston joystick (0bP2JFUDLR): 1=pressed, - при отсутствии джойстика 0 (а не 0xff)
;        Флаг Z - если 0(NZ), то отсутствует фокус.
        jr nz,IMERnofocus
        ld a,e
        ld (mousex),a
        ld a,d
        ld (mousey),a
        ld a,l
        ld (mousebuttons),a
        ld a,lx
        ld (kempston),a
IMERnofocus

;TODO здесь опрос клавиш эмулятора

        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)
        LD (keepemuchecker),IY
        LD IY,IMINT
        POP HL,AF
        RET  ;di!
IMINT
keepemuchecker=$+2
        LD IY,0
       LD (retfromim),DE ;для индикации времени обработки прерыв
       LD A,(immode)
       CP #18 ;IM2
        LD HL,#38 ;new PC
       jr NZ,IMERIM1
        LD HL,(_I-1)
        LD L,#FF ;состояние пассивной ШД
        getmemBC
        ld h,b
        ld l,c
        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
     if MEM48C0
        call set4000
     endif
      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
;hl=new PC
        EI
       CALCpc ;de=old PC
        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

       if MEM48C0      
setmem00004000forwrite
;NC, keep CY (keep A for rra:ld h,a)
;если 0000 (p) и включено ПЗУ, то должен ld h,secbuf/256
;иначе setmem00004000
ROMSTATE_ON=0xf2 ;jp p
ROMSTATE_OFF=0xda ;jp c
romstate=$
        jp p,setmem00004000forwrite_skip
setmem00004000
        jp m,set4000forwrite
        set 6,h
setrom
       if !margins
        ld a,0xc9 ;/RET
        ld (setrom),a
        ld (getde0000ret),a
        ld a,0x3e;3a
        ld (set4000),a
        ld (set4000forwrite),a
       endif
        ld a,(currom) ;0000
       push bc
        OUTPG4000
       pop bc
       ld a,h
       sub 64
       add a,a
        ret
setmem00004000forwrite_skip
        ld h,secbuf/256
        ret

set4000forwrite
       if !margins
        ld a,0xc9 ;/RET
        ld (set4000),a
        ld (set4000forwrite),a
        ld a,0x3e;3a
        ld (setrom),a
        ld (getde0000ret),a
       endif
        ld a,(curpg5) ;4000
       push bc
        OUTPG4000
       pop bc
       ld a,h
       add a,a
        ret

set4000
       if !margins
        ld a,0xc9 ;/RET
        ld (set4000),a
        ld (set4000forwrite),a
        ld a,0x3e;3a
        ld (setrom),a
        ld (getde0000ret),a
       endif
        ld a,(curpg5) ;4000
       push bc
        OUTPG4000
       pop bc
         ld a,(de) ;for getde00004000
        ret

getde0000l_getde00004000
        call getde0000
        ld l,a
       inc de
        ld a,d
        add a,a ;check 3fff->4000
getde00004000
        jp m,set4000
getde0000
       if !margins
        set 6,d
        ld a,(de)
        res 6,d ;fastest branch! no extra commands!
getde0000ret
        ld a,0xc9 ;/RET
        ld (setrom),a
        ld (getde0000ret),a
        ld a,0x3e;3a
        ld (set4000),a
        ld (set4000forwrite),a
       endif
        ld a,(currom) ;0000
        OUTPG4000
        set 6,d
        ld a,(de)
        res 6,d
        ret
       
       endif

       if margins
next_incd
        inc d
        ret nz
        ld d,0xc0
        ld hl,(curquart)
        inc l
        res 2,l
        ld (curquart),hl
        ld a,(hl)
        OUTPGCOM
        ret
       endif

        align 256
temulpgs
        ds 64 ;пока используем 8

pgrom48
        db 0
pgrom128
        db 0
pgromDOS
        db 0
pgromSYS
        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 ;с точки зрения эмулимой проги
_dffd   db 0
_fe     DB 0
dos3F   DB 0
dos5F   DB 0
dosFF   DB 0

       if margins
curquart
        DW currom
        align 256
       endif

;реальные банки (лежат подряд для margins)
curpg5  DB 0 ;for 4000
curpg2  DB 0 ;for 8000
curpghi DB 0 ;for c000
currom  DB 0 ;for 0000

curscr  DB 0 ;0/8

;romon0  DB 0 ;#C0=ОЗУ, 0=ПЗУ в нижних 16k ;теперь в romstate
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

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

        if 0
sysvars
        incbin "goodsysv"
sz_sysvars=$-sysvars
        endif

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

end

        align 256 ;for setmem00004000forwrite
rrdbuf  ;DB 0
secbuf
        ds 256
        display secbuf+256

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

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