** Helper functions (that is, the emulator would work without them, ** but you wouldn't want to be without them). ** ====================================================================== IFD VERBOSE LIST ** Compiling the helpfuncts.i file. NOLIST ENDC ** This subroutine makes the emulator update the private fields of the ** control structure when changes to any of the public fields have taken ** place, for instance if the Z80_Memory field is changed. Do not call ** this routine while the emulator is running. ** Call Z80_Exitreq and make sure the emulator has stopped before ** reallocating memory (remember to copy the old memory contents to the ** new areas), then update the corresponding entries in the control ** structure (Z80_Memory, Z80_Cachemem and Z80_Flagmem). Calling ** Z80_NewSettings will then make sure that Z80_Continue will properly ** resume the emulation from the new addresses. ** a0 must point to the control structure. ** The return value in d0 is nonzero if an error occurred, and zero ** otherwise. Z80_NewSettings ;(a0) (ctrl) move.l Z80_Memory(a0),d0 add.l #Z80_0_OFFSET,d0 move.l d0,Z80_Z0(a0) move.l d0,Z80_zero(a0) move.l Z80_Cachemem(a0),d0 add.l #CACHE_0_OFFSET,d0 move.l d0,Z80_CacheB(a0) move.l d0,Z80_cachezero(a0) IFD Z80_MEMCHECK move.l Z80_Flagmem(a0),d0 add.l #FLAGS_0_OFFSET,d0 move.l d0,Z80_FlagsB(a0) move.l d0,Z80_flagzero(a0) ENDC moveq #0,d0 rts ;return zero (No Error) ** ---------------------------------------------------------------------- ** These routines access the Z80 address space, mirroring any changes ** in the cache and handling the wraparound of addresses transparently. ** They do *not* respect any memory protection flags - a write always ** takes effect. ** I recommend that they are used rathed than writing directly into ** the Z80 address space. ** ** Z80_SetByte (a0,d0,d1) (ctrl, addr, BYTE val) ** Z80_SetWordLH (a0,d0,d1) (ctrl, addr, WORD val) ** Z80_GetByte (a0,d0) (ctrl, addr) ** Z80_GetWordLH (a0,d0) (ctrl, addr) ** Z80_SetBlock (a0,d0,d1,d2) (ctrl, start_addr, size, BYTE val) ** Z80_ReadBlock (a0,a1,d0,d1) (ctrl, buf, start_addr, size) ** Z80_WriteBlock (a0,a1,d0,d1) (ctrl, buf, start_addr, size) ** ** All need a pointer to the control structure in a0. The Z80 address ** (word-sized) is passed in d0 (for block functions this is the ** block start address). ** Z80_SetByte is passed a byte value to be written in d1. It returns ** nothing. ** Z80_SetWordLH is passed a (high-end first) word value to be written ** in d1 and writes it low-end first. It returns nothing. ** Z80_GetByte returns the byte value in d0. ** Z80_GetWordLH reads a (low-end first) word value and returns it ** high-end first in d0. ** All block functions are passed the block size (an unsigned longword) ** in d1. They return nothing. ** Z80_SetBlock is passed the byte value to be written in d2. ** Z80_ReadBlock and Z80_WriteBlock are passed the buffer address ** (in the 680x0 address space) in a1. ** All Z80 address arithmetic is word-sized. For instance, calling ** Z80_SetWordLH(ctrl, $ffff, $1234) will set address $ffff to $34 and ** address $0000 to $12. The block functions will also wrap at $ffff. Z80_SetByte ;(a0,d0,d1) (ctrl, addr, BYTE val) move.l a1,-(a7) move.l Z80_zero(a0),a1 move.b d1,(a1,d0.w) move.l Z80_cachezero(a0),a1 add.w d0,a1 clr.w (a1,d0.w) move.l (a7)+,a1 rts ;return nothing ** ------------ Z80_SetWordLH ;(a0,d0,d1) (ctrl, addr, WORD val) move.l a1,-(a7) movea.l Z80_zero(a0),a1 move.b d1,(a1,d0.w) lsr.w #8,d1 addq.w #1,d0 ;second byte move.b d1,(a1,d0.w) move.l Z80_cachezero(a0),a1 movea.l a1,a0 ;keep cachezero add.w d0,a1 clr.w (a1,d0.w) ;mark cache subq.w #1,d0 ;first byte movea.l a0,a1 ;get cachezero add.w d0,a1 clr.w (a1,d0.w) ;mark cache move.l (a7)+,a1 rts ;return nothing ** ------------ Z80_GetByte ;(a0,d0) (ctrl, addr) movea.l Z80_zero(a0),a0 move.b (a0,d0.w),d0 ext.w d0 ;sign extend ext.l d0 rts ;return (signed) byte in d0 ** ------------ Z80_GetWordLH ;(a0,d0) (ctrl, addr) movea.l Z80_zero(a0),a0 move.w d0,-(sp) ;create word on stack move.b (a0,d0.w),1(sp) ;low byte addq.w #1,d0 move.b (a0,d0.w),(sp) ;high byte move.w (sp)+,d0 ext.l d0 ;sign extend rts ;return (signed) word in d0 ** ------------ Z80_SetBlock ;(a0,d0,d1,d2) (ctrl, start_addr, size, BYTE val) movem.l a1/a2,-(a7) movea.l Z80_zero(a0),a1 movea.l Z80_cachezero(a0),a2 .loop move.b d2,(a1,d0.w) movea.l a2,a0 adda.w d0,a0 clr.w (a0,d0.w) ;mark cache addq.w #1,d0 subq.l #1,d1 bne.s .loop movem.l (a7)+,a1/a2 rts ;return nothing ** ------------ Z80_ReadBlock ;(a0,a1,d0,d1) (ctrl, buf, start_addr, size) movea.l Z80_zero(a0),a0 .loop move.b (a0,d0.w),(a1)+ addq.w #1,d0 subq.l #1,d1 bne.s .loop rts ;return nothing ** ------------ Z80_WriteBlock ;(a0,a1,d0,d1) (ctrl, buf, start_addr, size) movem.l a2/a3,-(a7) movea.l Z80_zero(a0),a2 movea.l Z80_cachezero(a0),a3 .loop move.b (a1)+,(a2,d0.w) movea.l a3,a0 adda.w d0,a0 clr.l (a0,d0.w) ;mark cache addq.w #1,d0 subq.l #1,d1 bne.s .loop movem.l (a7)+,a2/a3 rts ;return nothing ** ------------------------------------------------------------------------ ** This routine sets Z80 memory control flags. If the Z80_Flagmem field ** in the control structure is zero, the function has no effect. ** Z80_SetMemFlag (a0,d0,d1,d2) (ctrl, start_addr, size, flag) ** ** As for the memory access functions, the Z80 address is word-sized and ** passed in d0, and the size is an unsigned longword. The flag is a ** byte-sized value, and its possible meanings are defined in Z80.i. ** Nothing is returned. Z80_SetMemFlag ;(a0,d0,d1,d2) (ctrl, start_addr, size, flag) tst.l Z80_Flagmem(a0) beq.s .end move.l Z80_flagzero(a0),a0 .loop move.b d2,(a0,d0.w) addq.w #1,d0 subq.l #1,d1 bne.s .loop .end rts ;return nothing ** This routine returns the memory control flag for an address, in case ** you should forget it. If the Z80_Flagmem field in the control ** structure is zero, the function has no effect, and returns zero (RAM). ** Z80_GetMemFlag (a0,d0) (ctrl, addr) ** ** The Z80 address is word-sized and passed in d0. The flag value is ** returned in (the whole of) d0, and has the range -128 to +127. Z80_GetMemFlag ;(a0,d0) (ctrl, addr) tst.l Z80_Flagmem(a0) beq.s .end move.l Z80_flagzero(a0),d1 move.b (a0,d0.w),d0 ext.w d0 ext.l d0 .end rts ;return flag in d0 ** =====================================================================