Login

Subversion Repositories NedoOS

Rev

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

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

bigmem=1
atm=1
p3dos=0
USE_STDIO=0

STACK=0x4000

BANKN_TERMINATOR=0xff

        macro SELMEM
        ld b,tpgs/256
        ld c,a
        ld a,(bc)
       ;or a
       ;jr z,$
        SETPGC000
        endm

        org PROGSTART
begin
        ld sp,STACK
       if USE_STDIO
        call initstdio
       else
        OS_HIDEFROMPARENT
        ld e,3+0x80 ;6912 + keep gfx pages
        OS_SETGFX ;e=0:EGA, e=2:MC, e=3:6912, e=6:text ;+SET FOCUS ;e=-1: disable gfx (out: e=old gfxmode)
       endif
       
        if 1
        OS_GETMAINPAGES
       push hl
;dehl=номера страниц в 0000,4000,8000,c000
        ld hl,tpgs
        ld b,64;32
getpgs0
        push bc
        push hl
        OS_NEWPAGE
       ;ld a,e
       ;SETPGC000
       ;push de
       ;ld hl,0xc000
       ;ld de,0xc001
       ;ld bc,0x3fff
       ;ld (hl),l
       ;ldir
       ;pop de
        pop hl
        ld (hl),e
        inc hl
        pop bc
        djnz getpgs0
       LD A,pg1
       CALL selmem
       ld a,5 ;z-machine version
       ld (0xc000),a
       pop hl
       ld a,l ;как было
       SETPGC000
        endif
       
        ;ld de,path
        ;OS_CHDIR

        ld hl,COMMANDLINE ;command line
;command line = "zxzvm <file>"
        call skipword
        ld a,(hl)
        or a
        jr z,nofilename
        call skipspaces
        ld de,tfilename
        call getword
        ;call untr_load
nofilename
        ld hl,tfilename
        ld de,0x705C
copyfilename0
        ld a,(hl)
        ldi
        or a
        jr nz,copyfilename0
        dec de
        dec a ;0xff
        ld (de),a
        inc de
        ld a,'$' ;на всякий случай
        ld (de),a
       
        call main
        ld hl,0
        QUIT

path
        db "zxzvm",0

        align 256
tpgs
        ds 256

tfilename
        db "zxzvm/heroes.z5",0
        ds tfilename+DIRMAXFILENAME64-$

getword
;hl=string
;de=wordbuf
;out: hl=terminator/space addr
getword0
        ld a,(hl)
        or a
        jr z,getwordq
        sub ' '
        jr z,getwordq
        ldi
        jp getword0
getwordq
        ;xor a
        ld (de),a
        ret

skipword
;hl=string
;out: hl=terminator/space addr
skipword0
        ld a,(hl)
        or a
        ret z
        sub ' '
        ret z
        inc hl
        jp skipword0

skipspaces
;hl=string
;out: hl=after last space
        ld a,(hl)
        cp ' '
        ret nz
        inc hl
        jr skipspaces
       
       if USE_STDIO
        include "../_sdk/stdio.asm"
       endif

        ds #4000-$

       IF atm
MAXMEM  EQU #0E ;ATM-Turbo 2+ = #E0000
;BANKIO  EQU #FFF7
PGBUF=6;#7F^6
pg1=1;#7F^8 ;header
pg3=3;#7F^3
pg6=6;#7F^6 ;buf
;pg7=#7F^7 ;scr
       ELSE
MAXMEM  EQU #07 ;Пентагон 512 = #70000
;BANKIO  EQU #7FFD
PGBUF=#1E
pg1=1
pg3=3
pg6=6
;pg7=7
       ENDIF
;USED    EQU #38 ;число которое будет накладываться по AND
;и т.о. гасить биты
;отвечающие за страницы и не изменять другие
;GASIM   EQU #C7 ;если поступила в A не
;только информация о номере (физическом)
;страницы, то лишнюю информацию надо
;уничтожить. Уничтожаем с помощью AND GASIM

TABLE1  EQU #9E ;верхняя часть адреса
;где располагается таблица для перекл.
;нижних 64K
TABLE2  EQU #9F ;верхняя часть адреса
;где располагается таблица для переключения памяти >64K

        INCLUDE "in_zxzvm.asm" ;header с EQU #4000+3*N

ONERR   EQU #5B3A ;Memory paging subroutine used in reporting
;errors
BANKM   EQU #5B5C ;Memory paging latch
OLDSP   EQU #5B6A ;Saved stack pointer used while BASIC is
;calling +3DOS
SYNRET  EQU #5B6C ;Return address for ONERR
ERRNO   EQU #5C3A ;Spectrum BASIC error number
BORDCR  EQU #5C48 ;Border colour
ATTR_P  EQU #5C8D ;Current screen colours set by BASIC
RAMTOP  EQU #5CB2 ;Top of BASIC's memory (bottom of ZXZVM)
PRAMT   EQU #5CB4 ;Top of physical memory

;Graphics characters used by the 64-column printing system
GTLC    EQU 142     ;Top left corner
GTRC    EQU 130     ;Top right corner
GBLC    EQU 133     ;Bottom left corner
GBRC    EQU 134     ;Bottom right corner
GTL     EQU 129     ;Top line
GBL     EQU 135     ;Bottom line
GLL     EQU 131     ;Left side
GRL     EQU 132     ;Right side
GLJ     EQU 136     ;Left side /internal line junction
GRJ     EQU 137     ;Right side/internal line junction
GIL     EQU 138     ;Internal line

;Cursor keys
LA      EQU 8       ;<-
RA      EQU 9       ;->
UA      EQU 11      ;^
DA      EQU 10      ;DOWN ARROW

CR      EQU #0D
LF      EQU #0A

        JP init1   ;Initialise, load story file
        JP exit1   ;Deinitialise
        JP cls1    ;Clear screen
        JP peek1   ;Read byte from Z-machine memory
        JP poke1   ;Write byte to Z-machine memory
        JP peek64  ;Read byte from low 64k
        JP peekw   ;Read word from Z-machine memory
        JP ipeekw  ;Read word with auto increment
        JP fdos1   ;CP/M-like I/O functions
        JP ihdr1   ;Initialise the header
        JP tmem1   ;Get top of available host memory
        JP eraw1   ;Erase window
        JP zchr1   ;Output a ZSCII letter in HL.
        JP swnd1   ;Split window
        JP swnd2   ;Select window
        JP styl1   ;SET text style
        JP scur1   ;SET cursor position
        JP LINEINP ;Line input
        JP RCHAR   ;Read character
        JP scol1   ;SET colours
        JP sfnt1   ;SET font
        JP rndi1 ;Get randomish number (eg,the computer's clock)
        JP getx1   ;Get cursor X position
        JP gety1   ;Get cursor Y position
        JP strm1   ;Open or close stream in A
        JP eral1   ;Erase to EOL
        JP snd1    ;MAKE a sound
        JP rst1    ;Restart
        JP GNAME   ;Get filename
        JP p3opn   ;Open file
        JP p3clse  ;Close file
        JP p3read  ;Read bytes
        JP p3write ;Write bytes
        JP p3rmem  ;Read z-machine memory
        JP p3wmem  ;Write z-machine memory
        JP p3vrfy  ;Verify the game file
                        ;<< v0.02
        JP bfit1   ;Check if word in buffer will fit on screen.
        RET
        NOP
        NOP             ;Relinquish the CPU, or rather don't.
        JP yes_i_live
        LD A,VMVER ;Return version
        RET
        RET             ;Update the screen. Not necessary.
        NOP
        NOP
                        ;>> v0.02

oldHL_
       DW 0
;;;
init1
        LD (story),DE
       IF atm
        ;LD A,#18
        ;LD BC,#7FFD
        ;OUT (C),A
        ;CALL ATMON
        LD HL,TABLE1*256
        LD A,8;#7F^8 ;FIXME
MKTAB10 LD (HL),A
        inc a;DEC A
        INC L
        jr NZ,MKTAB10
        LD HL,TABLE2*256
        LD A,8;#7F^8
MKTAB20 LD (HL),A
        add a,4;SUB 4
        INC L
        jr NZ,MKTAB20
       ELSE
        CALL vers
       ENDIF
       ;EXX
       ;LD (oldHL_),HL
       ;EXX
        JR init2
        ;ld de,0100h
;0201 => +3 with Amstrad ROMs
;0100 => Sinclair 128
        ;and a
        ;sbc hl,de
        ;jr z,init2
        ;ld hl,reqp3
        ;xor a
        ;ret

init2
        CALL ZXCLS           ;Clear the shadow screen
       ld e,1
       OS_SETSCREEN
        LD A,1
        LD (cfont),A       ;SET current font
       IF atm
        LD A,pg6
       ELSE
        LD A,(BANKM)
        AND USED           ;Switch to bank 6 at the same time...
        OR #0E              ;Activate the shadow screen
         ;DI
       ENDIF
        LD (BANKM),A
        call selmem
        ;LD BC,BANKIO
        ;OUT (C),A
         ;EI
        CALL dosinit    ;!
;Initialise +3DOS
        RET NC
        LD DE,signon
        CALL PRINT           ;Sign on
        ;ld de,copyright
        ;call PRINT
        LD HL,(story)
pslp
        LD E,(HL)
        INC E               ;Print story name (FF-terminated)
        JR Z,pslend
        DEC E
        CALL OPCHAR
        INC HL
        JR pslp

;pslend ld de,sign1        ;Second part of sign-on message
        ;call PRINT
pslend
        LD HL,(story)
        CALL st_open ;!
;Load the story file
        RET NC
        CALL ZXCLS
        LD A,pg6
        CALL selmem
        SCF
        RET

;Restart
rst1
        LD HL,#10  ;Flags 2 is preserved through a restart
        CALL ZXPK64
        LD B,A
        INC HL
        CALL ZXPK64
        LD C,A
        PUSH BC
        LD DE,rest_
        CALL PRINT
        CALL st_reload
        POP BC
        RET NC
        LD HL,#10
        LD A,B     ;Restore Flags 2
        CALL ZXPOKE
        INC HL
        LD A,C
        CALL ZXPOKE
        CALL ZXCLS
        LD A,1
        LD (cfont),A
        SCF
        RET

;;;
exit1
        PUSH AF
        PUSH HL
      if 0
       EXX
       LD HL,(oldHL_)
       EXX
      endif
        CALL st_close
        CALL dosunit ;Undo anything we did to +3DOS
      if 1
        POP HL
        POP AF
        RET C               ;IF Carry was set, return (zmexit)
        ;ld hl,(ERRNO)
        ;ld h,0
       pop hl ;error=return addr
        QUIT
      else
         DI              ;Switch back to the conventional screen
        LD A,(BANKM)
        AND #F0
         DI
        LD (BANKM),A
        LD BC,BANKIO
        OUT (C),A
         EI
        POP HL
        POP AF
        RET C               ;IF Carry was set, return
        EX DE,HL
        LD A,(ERRNO)       ;Error number has been set elsewhere.
        INC A               ;Don't try to guess it.
        JP NZ,ZXERR
        LD A,(DE)         ;1st byte of return string could be an
                                ;ASCII error number
        CP "0"
        JP C,ZXERR
        CP "9"+1
        JR C,setnum
        CP "A"
        JP C,ZXERR
        CP "Z"+1
        JP NC,ZXERR
;setlet
        SUB 7
setnum
        SUB "1"
        LD (ERRNO),A
        JP ZXERR
      endif

;;;
cls1
        ;LD A,pg7
        CALL selmemscr
        LD HL,#C000 ;Clear the screen bitmap
        LD D,H
        LD E,L
        INC DE
        LD BC,#17FF
        LD (HL),L
        LDIR
        INC HL
        INC DE
        JR clattr1

;Clear colours only
clattr
        ;LD A,pg7
        CALL selmemscr
        LD HL,#D800
        LD D,H
        LD E,L
        INC DE
clattr1
        LD BC,#2FF
        LD A,7;(ATTR_P)
        LD (HL),A
        LDIR
        LD A,0;(BORDCR)
        RRCA
        RRCA
        RRCA
        AND 7
        OUT (254),A
        RET

;;;
HL_     DB #00,#00 ;Дабы не мучаться со стеком (записывается в getbyte)

TEMP    DB #00 ; Надо для исп. команды RRD

;;;
        IF bigmem == 0
getbyte ;128K
        LD A,(BANKM) ;Запоминаем банку
        LD (TEMPBANKA),A ;для последующего (в конце)
;к ней возврата
        LD (HL_),HL
        PUSH BC

        LD B,#06 ;Переключение на буфер
        LD A,(BANKM) ;(страница 6)
        AND USED
        OR B
        LD BC,BANKIO
        OUT (C),A

        LD A,E  ;склеиваем правую поло-
        LD B,H  ;винку E и левую H
        LD HL,TEMP ;подробнее смотри в
        LD (HL),B  ;tr-dos+.zsm
        RRD
        LD A,(HL)
        AND #FC ;гасим два бита 0-ой 1-й
        LD H,A
        LD A,(BUFMEM)
        SUB H ;не содержится ли требуемый адрес
;уже в буфере? Если нет, то вызов процедуры st_peek

        LD HL,(HL_)
        CALL NZ,st_peek
;Вызов процедуры загрузки 16K
;буфера содержащего запрашиваемый адрес

        LD A,#C0 ;Ложим байт в A из нуж-
        OR H     ;ной страницы по нужно-
        LD H,A   ;му адресу
        LD A,(HL)

        LD L,A
        LD A,(TEMPBANKA) ;Переключаемся
        LD BC,BANKIO ;обратно банку
        OUT (C),A ;бывшую до getbyte
        LD A,L

        POP BC
        LD HL,(HL_)
        SCF
        EI
        RET

peek1 ;128K
        DI
        LD A,E
;First 64k? IF not, access file on disc
        AND A
        JR NZ,getbyte

peek64 ;128K
        DI
        PUSH BC
        LD (HL_),HL
        LD A,(BANKM)
        LD (TEMPBANKA),A

        AND USED ;Only change the memory banking settings
        LD C,A
        LD A,H
        RLCA
        RLCA
        AND 3    ;A = Z-machine bank, 0-3

        LD L,A
        LD H,TABLE1
        LD A,(HL)
        OR C
        LD BC,BANKIO
        OUT (C),A

        LD HL,(HL_)
        LD A,#C0
        OR H
        LD H,A     ;HL |= #C000
        LD A,(HL)

        LD L,A
        LD A,(TEMPBANKA)
        LD BC,BANKIO
        OUT (C),A
        LD A,L

        POP BC
        LD HL,(HL_)
        SCF
        EI
        RET
        ENDIF ;128K




        IF bigmem
peek1
        DI ;FIXME
        LD A,E
       IF atm == 0
;First 64k? IF not, access file on disc
        AND A
        JR Z,peek64nDI
       CP MAXMEM ;addr>=#70000?
       JR NC,BANKA6
       ENDIF
       EXX
       LD L,A
       EXX

       ;LD A,(BANKM) ;Запоминаем банку
       ;LD (TEMPBANKA),A ;для последующего (в конце)
;к ней возврата

       ;LD (HL_),HL
       ;PUSH BC

       ;LD A,E
       ;CP MAXMEM ;Пентагон 512 может
;содержать в памяти адреса от #00000 до #6ffff
       ;JR NC,BANKA6

        LD A,H
       EXX
        RLCA
        RLCA
        AND %00000011

        LD H,TABLE2
       ;LD L,E
       IF atm
        XOR (HL)
       ELSE
        OR (HL)
       ENDIF

;Получаем банку, которую нужно включить
       ;LD B,A ;Включаем банку
       ;LD A,(BANKM) ;расширенной
       ;AND USED      ;памяти
       ;OR B
        ;LD BC,BANKIO
        ;OUT (C),A
        SELMEM
       EXX
       ;LD HL,(HL_)
CONT
       PUSH HL
        LD A,#C0 ;Ложим байт в A из нуж-
        OR H     ;ной страницы по нужно-
        LD H,A   ;му адресу
       ;LD A,(HL)
       ;LD L,A
       LD L,(HL)
       ;LD A,(TEMPBANKA) ;Переключаемся
       LD A,(BANKM)
       EXX
        ;LD BC,BANKIO ;обратно банку
        ;OUT (C),A ;бывшую до getbyte
        SELMEM
       EXX
        LD A,L

       ;POP BC
       ;LD HL,(HL_)
       POP HL
        SCF
        EI
        RET

       IF atm == 0
BANKA6
;Переключение на буфер-страницу
       PUSH HL
       ;LD B,#06
       ;LD A,(BANKM)
       ;AND USED
       ;OR B
       LD A,PGBUF
       EXX
        ;LD BC,BANKIO
        ;OUT (C),A
        SELMEM
       EXX

       ;LD A,E
       ;LD B,H
       LD A,H
        LD HL,TEMP
       ;LD (HL),B
       LD (HL),A
       LD A,E
        RRD
        LD A,(HL)
        AND #FC ;гасим два бита 0-ой 1-й
        LD H,A

        LD A,(BUFMEM)
        SUB H ;не содержится ли требуемый адрес
;уже в буфере? Если нет, то вызов процедуры st_peek

       ;LD HL,(HL_)
       POP HL
        CALL NZ,st_peek
;Вызов процедуры загрузки 16K
;буфера содержащего запрашиваемый адрес

        JP CONT
       ENDIF

peek64
        DI
peek64nDI ;
       ;PUSH BC
       ;LD (HL_),HL
       ;LD A,(BANKM)
       ;LD (TEMPBANKA),A
       ;AND USED ;Only change the memory banking settings
       ;LD C,A
        LD A,H
        RLCA
        RLCA
        AND 3  ;A = Z-machine bank, 0-3
       EXX

        LD L,A
        LD H,TABLE1
        LD A,(HL)
       ;OR C
        ;LD BC,BANKIO
        ;OUT (C),A
        SELMEM

       EXX
       ;LD HL,(HL_)
        JP CONT

        ENDIF

;
btrace
        CALL PUSHA
        OUT (254),A
yil11
        CALL CON6
        OR A
        JR Z,yil11
        JP POPA
;
slowpw
        CALL peek1
        DI
        LD B,A
        INC HL
        LD A,H
        OR L
        JR NZ,slowp1
        INC E
slowp1
        CALL peek1
        DI
        INC HL
        LD C,A
        LD A,H
        OR L
        JR NZ,slowp2
        INC E
slowp2
       ;POP AF
       EX AF,AF' ;'
        SCF
        EI
        RET
;
peekw
        PUSH HL
        PUSH DE
        CALL ipeekw
        POP DE
        POP HL
        RET
;
ipeekw
        DI
       ;PUSH AF
       EX AF,AF' ;'
        LD A,E
        OR A       ;Is the word in RAM?
        JR NZ,slowpw
        LD A,L
       ;CP #FF
       INC A ;Is there a chance the word might go across 2 pgs?
        JR Z,slowpw

;Read a word from the low 64k
;we know it does not extend over a page boundary
        PUSH HL
       ;PUSH DE

       ;LD A,(BANKM)
       ;LD (TEMPBANKA),A
       ;AND USED ;Only change the memory banking settings
       ;LD C,A
        LD A,H
        RLCA
        RLCA
        AND 3       ;A = Z-machine bank, 0-3

       ;PUSH HL
       EXX
        LD L,A
        LD H,TABLE1
        LD A,(HL)
       ;OR C
        ;LD BC,BANKIO
        ;OUT (C),A
        SELMEM
       ;POP HL
       EXX

        LD A,#C0
        OR H
        LD H,A     ;HL |= #C000
       ;LD D,(HL)
       LD B,(HL)
        INC HL
       ;LD E,(HL)
       LD C,(HL)

       ;LD L,A
       ;LD A,(TEMPBANKA)
       LD A,(BANKM)
       EXX
        ;LD BC,BANKIO
        ;OUT (C),A
        SELMEM
       EXX
       ;LD A,L

       ;LD B,D
       ;LD C,E
       ;POP DE
        POP HL
        INC HL
        INC HL
        LD A,H     ;<< v1.03 Check for rollover at FFFE ->>10000
        OR L
       ;JR NZ,fpw1
       JR Z,fpwinc
       EX AF,AF' ;'
       SCF
       EI
       RET
fpwinc
        INC E
fpw1
                                ;>> v1.03
       ;POP AF
       EX AF,AF' ;'
        SCF
        EI
        RET

;;;
poke1
        DI
        PUSH HL
       ;PUSH DE
       ;PUSH BC
       ;LD D,A
       EX AF,AF' ;'

       ;LD A,(BANKM)
       ;LD (TEMPBANKA),A
       ;AND USED
       ;LD C,A
        LD A,H
        RLCA
        RLCA
        AND 3

       ;PUSH HL
       EXX
        LD L,A
        LD H,TABLE1
        LD A,(HL)
       ;OR C
        ;LD BC,BANKIO
        ;OUT (C),A
        SELMEM
       ;POP HL
       EXX

        LD A,#C0
        OR H
        LD H,A     ;HL|=#C000
       ;LD (HL),D
       EX AF,AF' ;'
       LD (HL),A

       ;LD L,A
       ;LD A,(TEMPBANKA)
       LD A,(BANKM)
       EXX
        ;LD BC,BANKIO
        ;OUT (C),A
        SELMEM
       EXX
       ;LD A,L

       ;POP BC
       ;POP DE
        POP HL
        SCF
        EI
        RET

;;;
;SET screen colours

;Since this I/O model does not support colour (Spectrum colour
;clash means the lines of text don't match the colours) this is
;disabled pro tem. What it would normally do is set colours for
;the whole screen...

scol1
        SCF
        RET

;Colour map. ibm2zx[ibm_col] = zx_col
ibm2zx
        DEFB 0,2,4,6,1,3,5,7
zx2ibm
        DEFB 0,4,1,6,2,3,5,7
def_fg
        DEFB 0       ;Default FG
def_bg
        DEFB 0       ;Default BG

;;;
;<< v0.02
;Work out whether a word will fit on the line. Since the +3 uses
;a fixed-pitch font, we don't need to bother with what the text
;actually says, only with its length. B=no. of letters and C=no.
;of spaces.Return 0 to print everything,1 to print letters only,
;2 to print carriage return and then everything.
bfit1
        DI
        CALL getx1  ;H = amount of space on the line
        LD D,0     ;D = value to return.
        LD A,C
        ADD A,B     ;A = total chars in line
        CP H
        LD A,D
        RET C       ;The whole lot will fit.

;See if the word will fit.
        INC D
        LD A,B
        CP H
        LD A,D
        RET C       ;Letters only will fit
        INC A       ;Nothing will fit, return 2.
        SCF
        RET

;>> v0.02
;;;
;Get X position in L, chars left in H, total screen width in A
getx1
        LD HL,(uwx)        ;<< v0.04 use UWX/LWX, not XPOS.
        LD A,(cwin)
        OR A
        JR Z,getx2
        LD HL,(lwx)
getx2
        LD A,64            ;>> v0.04
        SUB L
        LD H,A
        LD A,64
        SCF
        RET

;Get Y position in L
gety1
        LD HL,(uwx)
        LD A,(cwin)
        OR A
        JR Z,gety2
        LD HL,(lwx)
gety2
        LD L,H
        LD H,0
        SCF
        RET

;;;
eral1
        DI
        LD HL,(XPOS)
        PUSH HL
        LD A,(HVF)
        PUSH AF
        LD A,(ulf)
        PUSH AF
        XOR A
        LD (HVF),A
        LD HL,(uwx)
        LD A,(cwin)
        OR A
        JR Z,eral2
        LD HL,(lwx)
eral2
        LD (XPOS),HL
        LD A,63
        SUB L
        JR Z,eral9
        LD B,A
eral3
        LD E," "
        CALL OPCHAR
        DJNZ eral3
eral9
        POP AF
        LD (ulf),A
        POP AF
        LD (HVF),A
        POP HL
        LD (XPOS),HL
        SCF
        EI
        RET

;;;
;SET font.
;The Spectrum uses only one font, but it serves as no.1
;or no. 4
sfnt1
        CP 1               ;Font is not valid
        JR Z,sfnt2
        CP 3
        JR Z,sfnt2
        CP 4
        JR Z,sfnt2
        XOR A
        RET

sfnt2
        LD HL,(cfont)      ;Font is valid
        LD (cfont),A
        LD A,L
        RET

cfont
        DEFB 0

;;;
;SET output stream
strm1
        CP 2       ;Open a transcript
        JP Z,ts_open
        CP #FE     ;Close a transcript
        JP Z,ts_close
        SCF
        RET

;;;
;A Spectrum clone of CP/M's BDOS functions dealing with console
;I/O
;These functions are mainly intended for diagnostic code
fdos1
        LD A,C
        CP 1
        JR Z,ichr1
        CP 2
        JR Z,opc1
        CP 6
        JR Z,dcio1
        CP 9
        JR Z,print1
        LD A,C
        LD DE,badfun
        CALL sphex2  ;Write function number into error message
        LD HL,unimpl
        XOR A
        RET

ichr1
        CALL CON6    ;1. Input character with echo
        OR A
        JR Z,ichr1
        LD E,A
opc1
        CALL OPCHAR  ;2. Output character
        SCF
        RET

dcio1
        LD A,E     ;6. Direct console input/output
        CP #FD
        JR C,opc1
        JR Z,ichr2 ;6/FD: Input character, no echo
        CP #FE
        JR Z,pkbd1 ;6/FE: Poll keyboard,return 1 if char waiting
        CALL CON6
        SCF    ;6/FF: Poll keyboard, return char if char waiting
        RET

pkbd1
        CALL CON6    ;6/FE
        OR A
        SCF
        RET Z
        LD A,1
        RET

ichr2
        CALL CON6    ;6.FD
        OR A
        JR Z,ichr2
        SCF
        RET

print1
        LD A,1
        LD (WRAP),A
print2
        LD A,(DE)
        CP "$"
        JR Z,endpr
        LD L,A
        LD H,0
        PUSH DE
        CP #0A
        CALL NZ,out1
        POP DE
        INC DE
        JR print2

;call print   ;9. Print $-terminated string
endpr
        XOR A
        LD (WRAP),A
        SCF
        RET

;;;
ihdr1
;The header is at 1:C000. So page it in and access it directly.
        LD A,pg1
        CALL selmem
        LD A,(#C000)      ;Z-machine version
        LD (zver),A
        LD DE,zvbuf
        LD L,A
        LD H,0             ;CREATE the "invalid version" error
        CALL spdec3
        EX DE,HL
        DEC HL
        SET 7,(HL)       ;Fatal error, so set bit 7 of last char
        LD HL,zvbad
        LD A,(zver)
        CP 3               ;<< v0.04 allow v3 games
        JR Z,okver         ;<< v0.04
        CP 4               ;<< v1.10 allow v4 games
        JR Z,okver         ;>> v1.10
        CP 8
        JR Z,okver
        CP 5
        JR NZ,ihdr8
;Version is acceptable
;nb: the Z-machine is big-endian, but the Spectrum is
;little-endian. So the LSB of a word will be in H.
okver
        CP 4               ;v3 flags or v4 flags?
        LD HL,(#C001)     ;Flags 1
        LD A,L
        JR NC,v4flag
        AND #9F           ;Reset bits 5,6
        JR cflag

v4flag
        AND #B8            ;Reset bits 0,1,2,5
        OR #98             ;SET bits 7,3 & 4
cflag
        LD L,A
        LD (#C001),HL
        LD HL,(#C010)     ;Flags 2
        LD A,H
        AND #43        ;No pictures, no mouse, no UNDO, no sound
        LD H,A
        RES 0,L             ;"Menus" bit
        LD (#C010),HL
        LD HL,scrset5
        LD DE,#C020
        LD BC,8
        LDIR

        LD A,(ATTR_P)
        PUSH AF
        AND 7       ;Current ink
        LD HL,zx2ibm
        CALL xlat
        LD A,(HL)
        LD (#C02D),A
        LD (def_fg),A
        POP AF
        RRCA
        RRCA
        RRCA            ;Current paper
        AND 7
        LD HL,zx2ibm
        CALL xlat
        LD (#C02C),A
        LD (def_bg),A

        SCF
        DEFB #0E     ;LD C, which will swallow the AND A
ihdr8
        AND A
ihdr9
        PUSH AF
        LD A,pg6
        CALL selmem
        POP AF
        RET

;Screen settings for a v5 game
scrset5
        DEFB 32,64,1,0,0,192,4,6     ;32x64 chars 192x256 pels

;Translate A -> HL[A]
xlat
        PUSH HL
xlat1
        OR A
        JR Z,xlat2
        INC HL
        DEC A
        JR xlat1

xlat2
        LD A,(HL)
        POP HL
        RET

;;;
tmem1
        LD HL,#BFFF ;Top of memory. The top16k is a
        RET         ;disk cache; we may have to shrink this.

;;;
rndi1
        ;LD DE,(FRAMES)
       push af
       push bc
       push hl
       OS_GETTIMER ;dehl
       ex de,hl
       pop hl
       pop bc
       pop af
       
        RET

;;;
eraw1
        CP #FF            ;Erase screen?
        JR Z,erall
        CP #FE
        JP Z,cls1
        OR A
        JR Z,erabot
        DEC A
        JR Z,eratop
erawi
        LD HL,badera
        XOR A
        RET

eratop
        ;LD A,pg7     ;<< v1.02
        ;CALL selmem  ;>> v1.02
        CALL selmemscr
        LD A,(lwtop)
        LD C,A
        LD B,0
        JR erablk

erabot
        ;LD A,pg7     ;<< v1.02
        ;CALL selmem  ;>> v1.02
        CALL selmemscr
        LD A,(lwtop)
        LD B,A
        LD C,32
        JR erablk

erall
        CALL ZXCLS
        LD A,pg6
        CALL selmem
        LD A,31
        LD (scrls),A
        XOR A
        LD (lwtop),A
        LD (lwx),A
        LD (lwy),A
        LD (uwx),A
        LD (uwy),A
        LD A,1
        LD (cwin),A
        LD A,(zver)
        CP 5
        JR NC,erall1
        LD A,31
        LD (lwy),A
erall1
        SCF
        RET

erablk
        CALL ZAPLN
        INC B
        LD A,B
        CP C
        JR C,erablk
        LD A,pg6             ;<< v1.02
        CALL selmem          ;>> v1.02
        SCF
        RET

;;;
scrls
        DEFB 31      ;Number of scrolls to [MORE] prompt
lwtop
        DEFB 0       ;Top line of lower window
lwx
        DEFB 0       ;Lower window X,Y
lwy
        DEFB 0
uwx
        DEFB 0       ;Upper window X,Y
uwy
        DEFB 0
cwin
        DEFB 1       ;1 = lower

;;;
zchr1
        DI
        CP 1
        JR Z,out1
        CP 2
        JP Z,ts_char       ;Output to transcript
        SCF
        EI
        RET

out1
        LD A,L     ;Output to stream 1 (screen)
        CP #0D
        JR NZ,zchr2
        LD A,(cwin)
        OR A
        JR Z,ulf
        JR llf

zchr2
        DI
        LD A,(cwin)
        OR A
        LD DE,(uwx)
        JR Z,pchr1
        LD DE,(lwx)
pchr1
        CALL PRINAT
        LD E,L
        CALL OPCHAR
        LD A,(cwin)
        OR A
        JR Z,stepcu
        LD A,(lwx)
        INC A
        LD (lwx),A
        CP 64
        RET C
llf
        XOR A
        LD (lwx),A
        LD A,(lwy)
        INC A
        LD (lwy),A
        PUSH AF
        LD A,(scrls)
        OR A
        CALL Z,MORE
        DEC A
        LD (scrls),A
        POP AF
        CP 32
        RET C
        LD A,31
        LD (lwy),A
        LD A,(lwtop)
        CALL SCRL_N
        SCF
        EI
        RET

stepcu
        DI
        LD A,(uwx)
        INC A
        LD (uwx),A
        CP 64
        RET C
ulf
        XOR A
        LD (uwx),A
        LD A,(uwy)
        INC A       ; <<v0.03>> LWTOP check removed
                 ;it was causing trouble in the Curses help menu
        LD (uwy),A
        SCF
        EI
        RET

;;;
;Split_window...
swnd1
        LD (lwtop),A
        LD B,A
        CALL RES_MORE
        LD A,(lwy) ;Ensure lower window y >= lwtop
        CP B
        JR NC,swnd1a
        LD A,B
        LD (lwy),A
swnd1a
        LD A,(uwy)
        CP B
        RET C       ;Ensure upper window y < lwtop
        LD HL,0
        LD (uwx),HL
        SCF
        RET

;;;
;Set_window...
swnd2
        AND 1
        XOR 1 ;set_window opcode uses 0 to mean lower window
        LD (cwin),A
        SCF
        RET NZ
        LD HL,0
        LD (uwx),HL
        SCF
        RET

;;;
;Set_text_style
styl1
        LD C,A
        AND 1       ;Reverse video?
        LD (HVF),A
        LD A,C
        AND 4       ;Italic?
        LD (ITF),A
        SCF
        RET

;;;
;set_cursor_position
scur1
        DI
        BIT 7,C             ;Negative => set cursor on/off
        JR NZ,cursw
        DEC B
        DEC C               ;0-based
        LD A,C
        CP 64
        JR C,scur1a
        LD C,63
scur1a
        LD A,(cwin)
        OR A
        JR Z,scur2
        LD A,(lwtop)
        ADD A,B
        CP 32
        JR C,scur1b
        LD A,31
scur1b
        LD B,A
        LD A,31    ;Reset the scroll counter
        SUB B
        LD (scrls),A
        LD (lwx),BC
        SCF
        EI
        RET

scur2
        LD A,B            ; << v0.02  Don't bother to check if
        CP 32                     ;this takes the cursor outside
        JR C,scur2b               ;the upper window.
        LD B,31
scur2b
        LD (uwx),BC        ; >> v0.02
        SCF
        EI
        RET

cursw
        CP #FF
        CALL Z,CUROFF
        CALL NZ,CURON
        SCF
        EI
        RET

;;;
snd1
        LD E,7   ;Beep!
        CALL OPCHAR
        SCF
        RET

;;;
;Select memory bank in A
selmem
        ;DI
        PUSH AF
        PUSH BC
       if 1
        SELMEM
       else
       IF atm == 0
        AND GASIM
        LD B,A
        LD A,(BANKM)
        AND USED
;Only change the bits we want to
        OR B
       ENDIF
        LD BC,BANKIO
        OUT (C),A
       endif
        POP BC
        POP AF
        ;EI
        RET
       
selmemscr
        push bc
        ld a,(user_scr1_high)
        SETPGC000
        pop bc
        ret

;;;
TEMPBANKA   DB pg6;#00 ;Временное хранение
;информации о банке и режимах

;;;
;Messages
badera
       ;DEFB "A Bad ERASE_WINDO"
       DB "BEW"
        DEFB "W"+#80
unimpl
       ;DEFB "A No ZXFDOS function "
       DB "NZF "
badfun
        DEFB "00"
        DEFB "h"+#80
zvbad
       ;DEFB "A Story format "
       DB "SF "
zvbuf
        DEFB "000"
reqp3
       ;DEFB "A Spectrum +3 require'
       DB "SR"
        DEFB "d"+#80

signon
        INCLUDE "in_ver.asm"
        DEFB CR,LF,"$"

;defb CR,LF,' +3 Copyright 1998-9 by John Elliott','$'

;defb CR,LF,'TR-DOS version by CATAHUCTb|, 2001'
;defb CR,LF,LF
;defb 'Story file: $'

;sign1: defb CR,LF,'The story is loading...',CR,LF,'$'
rest_
        DEFB CR,LF,"ZXZVM is restarting...",CR,LF,"$"

;;;
;Numeric data
story
        DEFW tfilename;0  ;Address of story filename
zver
        DEFB 0  ;Z-machine version no.

;;;
;Банки для загрузки (BANKN_TERMINATOR;#02 - нет банки для такого адреса, конец списка)

BankN
        IF bigmem
       IF atm
_=8;#7F^8
        DUP 56
        DB _
_=_+1;-1
        EDUP
;#E0000
       ELSE
        DB #01,#03,#04,#00
        DB #40,#41,#42,#43,#44,#45,#46,#47
        DB #80,#81,#82,#83,#84,#85,#86,#87
        DB #C0,#C1,#C2,#C3,#C4,#C5,#C6,#C7
;#70000
       ENDIF
        ELSE ;~bigmem
        DB #01,#03,#04,#00
;#10000
        ENDIF
        DB BANKN_TERMINATOR;#02

;;;
;Other source files
        ;INCLUDE "zxp3dos2.asm" ;+3DOS specific functions
p3vrfy
        SCF
        RET  
       
        INCLUDE "trdos.asm" ;TR-DOS специфические функции
        ;INCLUDE "zxvers.asm" ;Get Spectrum version
        INCLUDE "zxchime.asm" ;Sound a chime on the 8912 chip
        ;INCLUDE "zxerr.asm" ;Return a BASIC error
        INCLUDE "zx64_1.asm" ;64-column printing
        INCLUDE "in_wrhex.asm" ;Render numbers into hex or dec

       IF 0;atm
ATMON
        LD BC,#BD77
        LD A,%10101011 ;6912,turbo
       ;LD A,%10101110 ;text,turbo
        CALL OUT_DOS
        LD A,#03 ;48K
        LD BC,#3FF7
        OUT (C),A
        RET
ATMOFF
        LD A,#83 ;48K/DOS
        LD BC,#3FF7
        OUT (C),A
        LD BC,#FF77
        LD A,%10101011 ;6912,turbo
        OUT (C),A
        RET
OUT_DOS
        LD HL,#2A53
        PUSH HL
        JP #3D2F
       ENDIF

        ;ENT
       
        ds 0x7000-$
main
        incbin "vm.bin"
       
end
;GO
        ;RET
        savebin "zxzvm.com",begin,end-begin

        LABELSLIST "../../us/user.l",1