Login

Subversion Repositories NedoOS

Rev

Rev 1408 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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

PROFI=512;1024
PENT512=1;0 ;если включить, то может неправильно работать память Profi
        if PROFI=512
PGATTR0=0x18
PGATTR1=0x1a
        else
PGATTR0=0x38
PGATTR1=0x3a
        endif

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

STACK=0x4000

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

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

extpg5=1 ;1=перехват экрана

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

        MACRO OUTPG
        SETPGC000
        ENDM

       if margins
        MACRO OUTPGCOM
        SETPG4000
        ENDM
       endif

        MACRO OUTPG4000
        SETPG4000
        ENDM

        MACRO _Loop_
       ;OUTcom
        JP (IY) ;EMULOOP
        ENDM

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

;если вместо стр.команд включили др.стр. и до этого момента не трогали флаги
        MACRO _LoopCimmediately
        OUTcomCY15
        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 (могла измениться конфигурация памяти - но внутри out7ffd уже есть CALCpgcom)
        MACRO _LoopSWI
        JP (IY)
        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
        ;OS_GETMAINPAGES ;out: d,e,h,l=pages in 0000,4000,8000,c000, c=flags, b=id
       pop hl
        ld a,h
        ld (temulpgs+2),a
        ld a,l
        ld (temulpgs+0),a

        ld a,(user_scr0_low) ;ok
        call clearpg
        ld a,(user_scr1_low) ;ok
        call clearpg

       if extpg5
        OS_NEWPAGE
        ld a,e
       else
        ld a,(user_scr0_high) ;ok
       endif
        ld (temulpgs+5),a
       if extpg5
        OS_NEWPAGE
        ld a,e
       else
        ld a,(user_scr1_high) ;ok
       endif
        ld (temulpgs+7),a

        OS_NEWPAGE
        ld a,e
        ld (temulpgs+1),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+PGATTR0),a;0x38
        OS_NEWPAGE
        ld a,e
        ld (temulpgs+PGATTR1),a;0x3a

        OS_NEWPAGE
        ld a,e
        ld (temulpgs+3),a
        OS_NEWPAGE
        ld a,e
        ld (temulpgs+8),a
        OS_NEWPAGE
        ld a,e
        ld (temulpgs+9),a
        OS_NEWPAGE
        ld a,e
        ld (temulpgs+10),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 (pgrom48_im1check),a
        ld de,trom48
;de=имя файла
;a=в какой странице
        call loadfile_in_ahl

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

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

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

        call swapimer

Reset
        ld sp,STACK

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

       if 0;extpg5
        xor a
        ld (screenin4000_flag),a
        ld a,0xc9
        ld (screenin0000_flag),a
        ld (screenin8000_flag),a
        ld (screeninc000_flag),a
       endif

        ;ld a,5
        ;ld (_logicpg4000),a
        ;ld a,(temulpgs+5)
        ;ld (emulcurpg4000),a
        ;SETPG4000 ;TODO убрать
        ;ld a,2
        ;ld (_logicpg8000),a
        ;ld a,(temulpgs+2)
        ;ld (emulcurpg8000),a
        ;SETPG8000

        ld a,-1 ;impossible value
        ld (oldcurvideomode),a
        ld (oldcurscr7ffd),a

       ;ld a,-1
       ;ld (doson0),a ;for basic48
        xor a
        ld (doson0),a
        ;ld a,0x10 ;for basic48
        ld (_fd),a
        ;xor a
        ld (_dffd),a
        CALL eoutDFFD;дальше идёт на 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

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

        ld a,0xdd
        ld (oldprefix),a ;ix содержит ix

        xor a
        ld (immode),a

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

Quit
        call swapimer
        QUIT

Loadsnapshot
       ld a,55 ;scf
       ld (debugon),a
        ld sp,STACK

        ld de,snapshotram3name
        ld a,(temulpgs+3)
        call loadfile_in_ahl
        ld de,snapshotram5name
        ld a,(temulpgs+5)
        call loadfile_in_ahl
        ld de,snapshotram8name
        ld a,(temulpgs+8)
        call loadfile_in_ahl
        ld de,snapshotram9name
        ld a,(temulpgs+9)
        call loadfile_in_ahl
        ld de,snapshotramaname
        ld a,(temulpgs+10)
        call loadfile_in_ahl

        ld de,snapshotscrname
        ld a,(temulpgs+6)
        call loadfile_in_ahl
        ld de,snapshotattrname
        ld a,(temulpgs+PGATTR1);0x3a
        call loadfile_in_ahl

        ld de,snapshotname
        OS_OPENHANDLE
        ld a,(temulpgs+0)
        call loadsnappg
        ld a,(temulpgs+1)
        call loadsnappg
        ld a,(temulpgs+2)
        call loadsnappg
        ld a,(temulpgs+7)
        call loadsnappg
        OS_CLOSEHANDLE

       if 0;extpg5
        ld a,0xc9
        ld (screenin4000_flag),a
        ld a,0xc9
        ld (screenin0000_flag),a
        ld a,0xc9
        ld (screenin8000_flag),a
        ld a,0xc9
        ld (screeninc000_flag),a
       endif

        ;ld a,(temulpgs+1)
        ;ld (emulcurpg4000),a
        ;SETPG4000 ;TODO убрать
        ;ld a,(temulpgs+2)
        ;ld (emulcurpg8000),a
        ;SETPG8000

        ld hl,0xe6fb
        ld (_SP),hl

        ld a,-1 ;impossible value
        ld (oldcurvideomode),a
        ld (oldcurscr7ffd),a

       ;ld a,-1
       ;ld (doson0),a
        xor a
        ld (doson0),a
        ld a,0x09 ;screen 1
        ld (_fd),a
        ld a,0xb8
        CALL eoutDFFD;дальше идёт на eout7FFD
       
        ld a,0xff
        ex af,af' ;'
        ld bc,0xff00
        ld de,0x321f ;важно!!!
        ld hl,0xffff
        ld ix,0x001d ;?0038?
        exx
       
        ld de,0x07a2
    if 0;1 ;debug
      IF margins
        CALCiypgcom
      endif
        ld a,0xdd
        ld (oldprefix),a ;ix содержит ix
        xor a
        ld (immode),a
        ld hl,EMUCHECKQ
        LD (keepemuchecker),hl;IY
       ;jr $
       jp IMDEBUG
    else
        jp Jumpin
    endif

;oldpc
;        dw 0

EMUCHECKQ
       ;ld a,(0x4000)
       ;or a
       ;jr z,$
       ;ld a,d
       ;sub 0x7c
       ;cp 2
       ;jr nc,$
       ;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

clearpg
        OUTPG4000
        ld hl,0x4000
        ld de,0x4001
        ld bc,0x3fff
        ld (hl),l
        ldir
        ret

keymatrix
        ds 8,0xff

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?
       ;cpl
       ;and 3
        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?
       ;cpl
       ;and 3
        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 "debugsrv.asm"
        include "debugger.asm"
        include "disasm.asm"

        include "asmsrv.asm"
        include "asmsubr.asm"
        include "asm.asm"

        include "editline.asm"

        include "ports.asm"

        include "z80cmd.asm"

        include "rst38.asm"

on_int
        PUSH AF,HL

        ex af,af' ;'
        push af

        push bc,de
        exx
        push bc
        push de
        push hl
        push ix
        push iy

        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

        pop iy
        pop ix
        pop hl
        pop de
        pop bc
        exx
        pop de,bc      

        pop af
        ex af,af' ;'

debugon=$
        scf;or a ;для нормального старта пока пропускаем все активности до JumpIn
        jr c,imerskipdebug

;здесь опрос клавиш эмулятора
       ld a,0xef
       in a,(0xfe)
       and 0b10101 ;6+8+0
       jp z,Reset
       ld a,0xf7
       in a,(0xfe)
       push af
       and 0b10101 ;1+3+5
       jp z,Quit
       pop af
       push af
       and 0b10011 ;1+2+5
       jp z,Loadsnapshot
       pop af
       and 0b11000 ;4+5
       jp z,GotoDebugger

       LD A,(iff1)
       OR A
       jr NZ,IMEREI
imerskipdebug
        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!
GotoDebugger
;перед входом в отладчик завершаем тек.команду (перехват на EMULOOP)
        LD (keepemuchecker),IY
        LD IY,IMDEBUG
        POP HL,AF
        EI
        RET
IMDEBUG
       ld a,55 ;scf
       ld (debugon),a

;запоминаем регистры в переменные
       CALCpc ;de=old PC
       ld (curpc),de
       exx
       ld (curbc),bc
       ld (curde),de
       ld (curhl),hl
       ex af,af' ;'
       push af
       pop hl
       ld (curaf),hl
;ставим, что был префикс #dd, кладём curix,curiy
        ld a,(oldprefix)
        CP #DD
        jr Z,IMDEBUGwasdd
;был префикс #fd, ix содержит "iy"
        ld a,#dd
        LD (oldprefix),A
        LD HL,(_IZ) ;=curiy
        ld (curiy),ix ;=_IZ
        ld (curix),hl
        jr IMDEBUGwasddq
IMDEBUGwasdd
        ld (curix),ix
        ;ld (curiy),hl ;=_IZ
IMDEBUGwasddq

        call Debugger
        ld a,(oldcurvideomode)
        call setvideomode
        ld a,(oldcurscr7ffd)
        call setscreen

;берём регистры из переменных (уже установлено "был префикс #dd")
        ld ix,(curix)
        ;ld hl,(curiy) ;=_IZ
        ;ld (_IZ),hl
       ld hl,(curaf)
       push hl
       pop af
       ex af,af' ;'
       ld hl,(curhl)
       ld de,(curde)
       ld bc,(curbc)
       exx
       
       ld a,55+128 ;or a
       ld (debugon),a
        ld iy,(keepemuchecker)
       ld de,(curpc)
       _LoopC_JP
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
        ;ld a,(romstate_flag)
        ;cp ROMSTATE_ON
        ld a,(emulcurpg0000)
pgrom48_im1check=$+1
        cp 0
        jr nz,IMERIM
       PUSH HL
        CALL GETIY
        LD BC,23610
        OR A
        SBC HL,BC
       POP HL
        JR NZ,IMERIM
;вообще-то надо и SP проверить...
      push ix
      PUSH IY
     if margins;MEM48C0
        call setmem4000
     endif
      LD IY,23610
      call L0038;basicrst38
      LD A,-1
      LD (iff1),A
      LD (iff2),A
      POP IY
      pop ix
     _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

writescreen_6912
        bit 1,a
        ld a,(user_scr0_high) ;ok
        jr z,$+5
        ld a,(user_scr1_high) ;ok
;curscreenc000pgaddr=$+1
        ;ld a,(user_scr1_high) ;ok
       push bc
        OUTPG4000
       pop bc
       ld (hl),c
        ret

writescreen_profi
;hl=0x4000+ (keep)
;c=data (keep bc)
;a=logicpg
      push hl
       push bc
;y=%TTYYYyyy
;hl=%010TTyyy YYYxxxxx
       push af
        ld a,h
        xor l
        and 0x1f
        xor l
       ld c,l
        ld l,a
       ld a,c
       and 0x1f
       ld b,0
       bit 5,h
       jr nz,$+4
       ld b,0x20
        ld h,tprofiy/256
        ld c,(hl)
        inc h
        ld h,(hl)
        ld l,a
        add hl,bc
;addr=0x4000+(half*0x2000)+y*40+x
       pop af
       bit 4,a
       jr z,writescreen_profi_outpg_pix
        bit 1,a
        ld a,(user_scr0_low) ;ok
        jr z,writescreen_profi_outpg
        ld a,(user_scr1_low) ;ok
        jr writescreen_profi_outpg
writescreen_profi_outpg_pix
        bit 1,a
        ld a,(user_scr0_high) ;ok
        jr z,writescreen_profi_outpg
        ld a,(user_scr1_high) ;ok
writescreen_profi_outpg
        OUTPG4000
       pop bc
       ld (hl),c
      pop hl
        ret

       if margins;MEM48C0    

       if extpg5
setmem8000c000writec
;CY=1, keep CY (keep A for rra:ld h,a)
        jp m,setmemc000writec
        ld (hl),c
screenin8000_flag=$
        ret ;/nop for screen in 8000
       ld a,(_logicpg8000)
SCREEN8000_VIDEOMODE_6912=0x30 ;jr nc
SCREEN8000_VIDEOMODE_PROFI=0x38 ;jr c
screen8000_videomode=$
        jr nc,screen8000_profi
        bit 5,h
        jr nz,setmem8000writec_skip
        res 7,h
        set 6,h
        call writescreen_6912
       push bc
        LD bc,(curquart)
        LD A,(bc)
        OUTPGCOM ;надо именно тут, т.к. OUTcomCY15 работает только после обращения к <0x8000
       pop bc
        set 7,h
        res 6,h
setmem8000writec_skip
       ld a,h
       add a,a
        ret
screen8000_profi
        res 7,h
        set 6,h
        call writescreen_profi
       push bc
        LD bc,(curquart)
        LD A,(bc)
        OUTPGCOM ;надо именно тут, т.к. OUTcomCY15 работает только после обращения к <0x8000
       pop bc
        set 7,h
        res 6,h
       ld a,h
       add a,a
        ret
setmemc000writec
        ld (hl),c
screeninc000_flag=$
        ret ;/nop for screen in c000
       ld a,(_logicpgc000)
;screenc000_branchvideomode
SCREENC000_VIDEOMODE_6912=0x30 ;jr nc
SCREENC000_VIDEOMODE_PROFI=0x38 ;jr c
screenc000_videomode=$
        jr nc,screenc000_profi
        bit 5,h
        jr nz,setmemc000writec_skip
        res 7,h
        call writescreen_6912
       push bc
        LD bc,(curquart)
        LD A,(bc)
        OUTPGCOM ;надо именно тут, т.к. OUTcomCY15 работает только после обращения к <0x8000
       pop bc
        set 7,h
setmemc000writec_skip
       ld a,h
       add a,a
        ret
screenc000_profi
        res 7,h
        call writescreen_profi
       push bc
        LD bc,(curquart)
        LD A,(bc)
        OUTPGCOM ;надо именно тут, т.к. OUTcomCY15 работает только после обращения к <0x8000
       pop bc
        set 7,h
       ld a,h
       add a,a
        ret
       endif
       
setmem00004000writec
;NC, keep CY (keep A for rra:ld h,a)
       if !extpg5
ROMSTATE_ON=0xf2 ;jp p
ROMSTATE_OFF=0xda ;jp c
       else
ROMSTATE_ON=0xf0 ;ret p
ROMSTATE_OFF=0xd8 ;ret c
       endif
        jp m,setmem4000writec
       if !extpg5
romstate_flag=$
       jp p,setmem00004000writec_skip
       else
romstate_flag=$
        ret p
       endif
        set 6,h
        ld a,0x3e
        ld (set4000com),a
        ld a,(emulcurpg0000) ;0000
       push bc
        OUTPG4000
       pop bc
       if extpg5
       ld (hl),c
       endif
       ld a,h
       sub 64
       add a,a
screenin0000_flag=$
        ret ;/nop for screen in 0000
;TODO write C to screen if screen in 0000
       if extpg5
       
        ret
       endif
setmem4000writec
        ld a,0x3e
        ld (set4000com),a
        ld a,(emulcurpg4000) ;4000
       push bc
        OUTPG4000
       pop bc
       if extpg5
       ld (hl),c
       endif
       ld a,h
       add a,a
screenin4000_flag=$
        ret ;/nop for screen in 4000
;CY=0
       if extpg5
       ld a,(_logicpg4000)
screen4000_branchvideomode
SCREEN4000_VIDEOMODE_6912=0x38 ;jr c
SCREEN4000_VIDEOMODE_PROFI=0x30 ;jr nc
screen4000_videomode=$
        jr c,screen4000_profi
        bit 5,h
        call z,writescreen_6912
setmem4000writec_skip
       ld a,h
       add a,a
        ret
screen4000_profi
        call writescreen_profi
       ld a,h
       add a,a
        ret
       endif

       if !extpg5
setmem00004000writec_skip
        ld h,secbuf/256
        ret
       endif

;for read
setmem00004000
        jp m,setmem4000
        set 6,h
        ld a,0x3e
        ld (set4000com),a
        ld a,(emulcurpg0000) ;0000
       push bc
        OUTPG4000
       pop bc
       ld a,h
       sub 64
       add a,a
        ret
setmem4000
        ld a,0x3e
        ld (set4000com),a
        ld a,(emulcurpg4000) ;4000
       push bc
        OUTPG4000
       pop bc
       ld a,h
       add a,a
        ret

;for PC
set4000com
        ld a,0xc9 ;/RET
        ld (set4000com),a
        LD HL,(curquart)
        LD A,(HL)
        OUTPGCOM
        ret
       
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

pgrom48
        db 0
pgrom128
        db 0
pgromDOS
        db 0
pgromSYS
        db 0

curregs ;for debugger
curaf   dw 0 ;for debugger
curbc   dw 0 ;for debugger
curde   dw 0 ;for debugger
curhl   dw 0 ;for debugger
_AF     DW 0 ;AF'
_BC     DW 0 ;BC'
_DE     DW 0 ;DE'
_HL     DW 0 ;HL'
_SP     DW 0
curpc   dw 0 ;for debugger
curix   dw 0 ;for debugger
;curiy   dw 0 ;for debugger
curiy ;for debugger
_IZ     DW 0
_R      DB 0
_I      DB 0
_fd     DB 0;#10 ;с точки зрения эмулимой проги
_dffd   db 0

iff1    DB 0
iff2    DB 0
immode  DB 0 ;#18=IM2, иначе IM1
_logicpg0000 db 0 ;TODO
_logicpg4000 db 0
_logicpg8000 db 0
_logicpgc000 db 0
_fe     DB 0
dos3F   DB 0
dos5F   DB 0
dosFF   DB 0

       if margins
curquart
        DW emulcurpg0000
       endif

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
        call loadpg
        OS_CLOSEHANDLE
        ret;jp setpgmainc000 ;включили страницу программы в c000, как было

loadsnappg
;b=handle
        push bc
        SETPGC000 ;включили страницу A в 0xc000
        pop bc
loadpg
        ld de,0xc000 ;куда грузим
        ld hl,0x4000 ;столько грузим (если столько есть в файле)
        push bc ;b=handle
        OS_READHANDLE
        pop bc ;b=handle
        ret

path
        db "z80",0

diskname
        db "SYS.TRD",0
snapshotname
        db "SOLI",0
snapshotscrname
        db "ram6",0
snapshotattrname
        db "ram3a",0
snapshotram3name
        db "ram3",0
snapshotram5name
        db "ram5",0
snapshotram8name
        db "ram8",0
snapshotram9name
        db "ram9",0
snapshotramaname
        db "rama",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

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

        align 256
        include "z80table.asm"
        align 256
       if margins
        align 256 ;почему не работает 8? TODO
       endif
;реальные банки (лежат подряд с адреса, делящегося на 8, для margins)
emulcurpg4000=$  ;DB 0 ;for 4000
emulcurpg8000=$+1  ;DB 0 ;for 8000
emulcurpgc000=$+2  ;DB 0 ;for c000
emulcurpg0000=$+3  ;DB 0 ;for 0000
        ;ds 4
t866toatm
        incbin "../_sdk/codepage/866toatm"
       IF stats
        align 256
comstats
        DISPLAY "comstats=",$
        DS #400
       ENDIF
        align 256 ;for setmem00004000forwrite
secbuf
        ds 256
        align 256
tprofiy
_chr=0
        dup 32
;_chr=%000YYYTT
_Y=((_chr*8)&0x18)+((_chr/4)&0x07) ;_Y=%000TTYYY
        ;db 200 ;invisible line
_egay=_Y*8;7 ;- 4
        dup 8;7
       if (_egay >= 200) || (_egay < 0)
        ;db 200 ;invisible line
        DCOM (0x4000+4+(200*40))
       else
        ;db _egay
        DCOM (0x4000+4+(_egay*40))
       endif
_egay=_egay+1
        edup
_chr=_chr+1
        edup
        ;ds (-$)&0xff,200 ;invisible line
        org $+256
        align 256
temulpgs
        ds 64 ;пока используем 8

        display $
end

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

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