Login

Subversion Repositories NedoOS

Rev

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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;Extended operations
;
MAXEXT  EQU     0Fh     ;Maximum extended opcode.
;
ext_high:
        scf             ;Extended operations 128-255.
        ret             ;Entered with (inst+1) = opcode
;
ext_ops:        ;0       1        2       3      4      5        6        7
        defw    d_save,  d_restr, z_srl,  z_sra, sfont, drawpic, picdata, erapic
        defw    smargin, u_save,  u_restr,pruni, ckuni, fail,    fail,    fail
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
flags2: defb    0
;
save_magic:     ;1...5...10..14  15 16
        defb    'ZXZVM savefile',1Ah,2  ;(version 2)

save_hdr:
        defs    16      ;Magic number
save_zpc:
        defw    0,0     ;Program counter
save_mlen:
        defw    0       ;DRAM length
save_slen:
        defw    0       ;Z-stack length
save_rlen:
        defw    0       ;Routine stack length
        defs    102     ;Takes it up to 128 bytes

                        ;<< v1.01
filever:
        defb    0       ;Savefile version - 1 if the Z-stack has not been
                        ;manipulated due to bug in v1.00, else 2
                        ;>> v1.01

d_save: ld      a,1     ;<< v0.02 >> Flag "Save as"
        call    ZXNAME
        ex      de,hl   ;DE = filename parameter
        call    ilprint
        defb    13,10,'$'
        ld      hl,abandoned ;<< v1.01 >>
        ccf               ;<< v0.02 >> Carry-reset return here means "cancel"
        jp      c,badsave ;<< v1.01 >> Don't RET, it will send the Z-machine
                          ;           into hyperspace!
        ex      de,hl   ;Restore filename parameter
        ld      b,1     ;CREATE
        call    ZXOPEN  ;CREATE savefile
        jp      nc,badsave
        ld      a,(v_argc)      ;<< v1.00  Nasty SAVE bug in v3 games
        cp      1               ;         (and maybe others) - the base
        jr      nc,d_sav0       ;         address was not being set to 0
        ld      hl,0            ;         so save was from random address
        ld      (v_arg1),hl
d_sav0: ld      a,(v_argc)      ;>> v1.00
        cp      2
        jr      nc,d_sav1
        ld      hl,0eh
        ld      e,0     ;Address of DRAM length
        call    ZXPKWI  ;BC = DRAM length
        ld      (v_arg2),bc
d_sav1: ld      hl,save_magic
        ld      de,save_hdr
        ld      bc,16
        ldir            ;Copy magic number into header
        ld      hl,(zpc)
        ld      (save_zpc),hl
        ld      hl,(zpc+2)
        ld      (save_zpc + 2),hl
        ld      hl,(zstop)      ;Top of Z-stack
        ld      de,(zsp)        ;Bottom of Z-stack
        and     a
        sbc     hl,de           ;HL = Z-stack length
        ld      (save_slen),hl
        ld      hl,(rstop)
        ld      de,(rsp)        ;Routine stack length
        and     a
        sbc     hl,de
        ld      (save_rlen),hl
        ld      hl,(v_arg2)
        ld      (save_mlen),hl
;
;Write out the header
;
        ld      hl,save_hdr
        ld      bc,128
        call    ZXWRIT
        jp      nc,badsave
;
;Write out the memory
;
        ld      bc,(save_mlen)
        ld      hl,(v_arg1)     ;Base
        call    ZXWMEM          ;Write z-machine memory
        jr      nc,badsave
;
        call    fixup_stack     ;Write call stack.
        ld      bc,(save_slen)
        ld      hl,(zsp)
        call    ZXWRIT
        call    fixup_stack
        jr      nc,badsave      ;Write routine stack
        ld      bc,(save_rlen)
        ld      hl,(rsp)
        call    ZXWRIT
;
        ld      b,1
        call    ZXCLSE

        ld      a,(zver)        ;<< v0.04  Early versions branch if OK
        cp      4
        jp      c,branch        ;>> v0.04
        scf
        ld      hl,1
        jp      ret_hl
;
ts_err:
        ld      a,(hl)
        push    hl
        push    af
        and     7fh
        ld      l,a
        ld      h,0
        ld      a,1
        call    ZXZCHR
        pop     af
        pop     hl
        inc     hl
        bit     7,a
        jr      z,ts_err
        ld      hl,0dh
        ld      a,1
        call    ZXZCHR
        scf
        ret

badsave:
        call    ts_err
        ld      b,1
        call    ZXCLSE
;
        ld      a,(zver)        ;<< v0.04 Early versions branch not store
        cp      4
        jp      c,nbranch       ;>> v0.04

        scf
        ld      hl,0
        jp      ret_hl
;
d_restr: ;"restore"
        ld      hl,10h
        call    peek64
        ld      (flags2),a
        xor     a               ;<< v0.02 >> "Load" rather than "Save"
        call    ZXNAME
        ex      de,hl           ;DE = "name" parameter
        call    ilprint
        defb    13,10,'$'
        ld      hl,abandoned    ;<< v1.01 >>
        ccf                     ;<< v0.02 >> Carry reset here does not abort
        jr      c,badsave       ;<< v1.01 >> nor send Z-machine into hyperspace
        ld      b,0     ;Open to read
        ex      de,hl           ;HL = "name" parameter
        ;jr $
        call    ZXOPEN  ;
        jp      nc,badsave
        ld      a,(v_argc)      ;<< v1.00 v3 'save' bug fix
        cp      1
        jr      nc,d_rstr0
        ld      hl,0            ;Start restoring at byte 0
        ld      (v_arg1),hl
d_rstr0:                        ;>> v1.00
        ld      a,(v_argc)
        cp      2
        jr      nc,d_rstr1
        ld      hl,0eh
        ld      e,0     ;Address of DRAM length
        call    ZXPKWI  ;BC = DRAM length
        ld      (v_arg2),bc
d_rstr1:
        ld      hl,save_hdr
        ld      bc,128
        call    ZXREAD
        jp      nc,badsave
        ld      hl,save_hdr
        ld      de,save_magic
        ld      b,15            ;<< v1.01 >> Can be v1 or v2
d_rstr2:
        ld      a,(de)
        cp      (hl)
        inc     hl
        inc     de
        jp      nz,d_rstr3
        djnz    d_rstr2
        ld      a,(hl)          ;<< v1.01 Special check on savefile version
        ld      (filever),a
        or      a               ;== 0
        jp      z,d_rstr3
        cp      3               ;>= 3
        jp      nc,d_rstr3      ;Savefile versions 1 and 2 are acceptable
                                ;>> v1.01
;
;Header recognised. Load Z-memory & stacks
;
        ld      a,(v_argc)
        or      a
        jr      nz,rstr_tab
        ld      bc,(save_mlen)  ;Load memory
        ld      hl,0            ;Base
        call    ZXRMEM          ;Read z-machine memory
        jp      nc,badsave
;
        ld      hl,(zstop)
        ld      de,(save_slen)
        and     a
        sbc     hl,de
        ld      (zsp),hl        ;We have now passed the point of no return!
                                ;Errors now result in game abort!
        ld      hl,(rstop)
        ld      de,(save_rlen)
        and     a
        sbc     hl,de
        ld      (rsp),hl
                                ;<< v1.01 don't fixup stack for v1 savefile
        push    af
        ld      a,(filever)
        cp      1
        call    nz,fixup_stack
        pop     af              ;>> v1.01 Read call stack
        ld      bc,(save_slen)
        ld      hl,(zsp)
        call    ZXREAD
        push    af              ;<< v1.01
        ld      a,(filever)     ;Don't fixup stack for v1 savefile
        cp      1
        call    nz,fixup_stack
        pop     af              ;>> v1.01
        ret     nc
        ld      bc,(save_rlen)
        ld      hl,(rsp)
        call    ZXREAD
        ret     nc
        call    ZXCLSE
        ld      hl,(save_zpc)   ;Returning from a successful restore.
        ld      (zpc),hl
        ld      hl,(save_zpc+2)
        ld      (zpc+2),hl
        ld      hl,2
        ld      a,(zver)        ;<< v0.04 Branch if successful
        cp      4
        jp      c,branch        ;>> v0.04
        scf
        jp      ret_hl
;
rstr_tab:
;
;Only load memory
;
        ld      hl,(v_arg1)
        ld      bc,(v_arg2)
        call    ZXRMEM
        jp      nc,badsave
        ld      hl,(v_arg2)
        scf
        jp      ret_hl
;
d_rstr3:
        ld      hl,badfrm
        jp      badsave
;
fixup_stack:
        push    af      ;For each entry in the Z-stack, replace its RSP
        push    bc      ;entry with (RSPTOP - RSP). This operation is
        push    de      ;self-inverse.
        push    hl      ;Doing it like this means the stack in the savefile
        push    ix      ;does not depend on the local ZXZVM's setting of
        ld      ix,(zsp) ;RSPTOP.
fixup_s1:
        ld      de,(zstop)
        push    ix
        pop     bc
        call    cpdebc
        jr      z,fixend
        ld      e,(ix+36)
        ld      d,(ix+37)       ;DE = associated RSP
        ld      hl,(rstop)
        and     a
        sbc     hl,de           ;HL = RSP offset
        ld      (ix+36),l       ;<< v1.01 - write back the RESULT, not
        ld      (ix+37),h       ;>> v1.01   the parameter!
        ld      bc,38
        add     ix,bc
        jr      fixup_s1
;
fixend: pop     ix
        jp      popd
;
badfrm: defb    'Not a ZXZVM savefile'
        defb    0AEh                    ;'.'+80h
;
abandoned:
        defb    'Operation abandoned'
        defb    0AEh                    ;'.'+80h
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;ZXZVM does not support Undo in this incarnation. We can't guarantee
;enough memory in the target computer to hold the RAMsaved undo image.
;
;Possibly in the future this could be implemented (some PCWs have enough
;memory) but the speed hit might be too much for a 3.5MHz Z80 to take.
;
u_save: ld      hl,0ffffh       ;RAMsave failed
        scf
        jp      ret_hl
;
u_restr:
        ld      hl,0            ;RAM restore failed
        scf
        jp      ret_hl
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
z_srl:  ld      hl,(v_arg1)     ;logical shift
        ld      bc,(v_arg2)
        bit     7,b
        jr      nz,z_srlr
z_srll: add     hl,hl
        dec     c
        jr      nz,z_srll
z_srlm: scf
        jp      ret_hl
;
z_srlr: res     7,h
        call    absbc
z_srlt: srl     h
        rr      l
        dec     c
        jr      nz,z_srlt
        jr      z_srlm
;
;Arithmetic shift
;
z_sra:  ld      hl,(v_arg1)
        ld      bc,(v_arg2)
        bit     7,b
        jr      z,z_srll
        call    absbc
z_srar: srl     h
        rr      l
        bit     6,h
        jr      nz,z_srat
        set     7,h
z_srat: dec     c
        jr      nz,z_srar
        scf
        jp      ret_hl
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;set_font
;
sfont:  call    flush_buf       ;<< v1.02 >> Flush buffers before
        ld      a,(v_arg1)      ;changing fonts
        call    ZXSFNT
        ld      l,a
        ld      h,0
        scf
        jp      ret_hl
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;v6 routines (no-ops)
;
erapic:
drawpic:
smargin:
        scf
        ret
picdata:
        jp      nbranch
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;Unicode routines
;
pruni:  ld      hl,(v_arg1)
        ld      a,h
        or      a
        scf
        ret     nz      ;Only allow ASCII characters to print
        jp      prchar
;
ckuni:  ld      de,(v_arg1)
        ld      hl,0
        ld      a,d
        or      a
        jr      nz,ckunie
        set     0,l
        ld      a,e
        cp      128
        jr      nc,ckunie
        set     1,l
ckunie: scf
        jp      ret_hl