A83: Re: LDIR/CPIR clock timing, AND sprite routine


[Prev][Next][Index][Thread]

A83: Re: LDIR/CPIR clock timing, AND sprite routine




> - What is the clock timing for LDIR and CPIR? I've read in ASM GURU that
> LDIR takes 21/1 clocks, does this mean it takes 21+1*(number of bytes to
> copy) clocks, or is it just 21? (same questions for CPIR - 21/1 clocks)

Asm Guru is wrong, as were earlier versions of the Assemby Studio help file.
This is due, most likely, to the z80time.txt file having incorrect (or at
least mis-interpreted) fall-through timings for some instructions.  In the
case of the repeat instructions, fall through is not quite the proper term.
First, you need to understand how the repeat instructions work.  You may
have noticed, for example, that LDIR and LDI are very similiar.  This is
because an LDIR is a Repeated LDI.  Everytime the instruction copies data,
it takes 21 clock cycles.  So the timing is 21 times BC (or in the case of
CPIR, it can early out if A = (HL)).  When the instruction ends, you have
the fall through time.  This is not 1 (the same as it is not 1 for a JP),
but I don't remember what the proper timing would be (7 seems right).

Because the processor treats it as executing multiple LDI or CPI
instructions, interrupts can occur in the middle of the operation.  Now that
I think about it, I can't remember how the processor retains the internal
registers when this occurs.  My guess is that it pushes the return address
as the start of the repeat instruction, and assumes that the interrupt
handler preserves the state of the registers.  This should be fairly easy to
test, although I do not know if every z80 emulates it properly (though I
would think it should).  I don't have time at the moment to research this
further.  The z80 core from MAME would be a good place to check (it is the
one used in VTI and afaik is completely acurate).

> - Is there any decent AND sprite routine available? I've tried modifying
> MOVAX' XOR sprite routine (e.g.: change all 'xor (hl)' commands into 'and
> (hl)'. This does not seem to be working OK. The aligned sprite blitting is
> OK, but the non-aligned blitting screws up. Does anybody know why?

This is off the top of my head (not tested), but should work.  As with most
sprite routines, aligned blitting is not optimized as a special case (this
makes it smaller).  If you want the sprite to be passed in HL, add a "push
hl \ pop ix" at the beginning.  I leave adding extras such as masks as an
excericise to the reader  :)

; ix = sprite (8x8), bc = x,y coords
PutSprite:
 call FindAddress
 ld de,VideoBuffer         ; this is the graph screen or wherever to draw
the sprite
 add hl,de
 ld c,a
 ld b,8
RenderSprite:
 ld d,(ix+0)
 ld e,0
 inc ix
 ld a,c
 or a
 jr z,ShiftDone
Shift:
 srl d
 rr e
 dec a
 jr nz,Shift
ShiftDone:
 ld a,(hl)
 and d            ; this is where the AND takes place, this can be OR or
probably XOR
 ld (hl),a
 inc hl
 ld a,(hl)
 and e            ; AND here as well
 ld (hl),a
 ld de,11
 add hl,de
 djnz RenderSprite
 ret

; bc = x,y coords
; returns: hl = offset in video buffer (96x64), a = number of times to shift
FindAddress:
 ld a,c                 ; this part is not optimized
 add a,a
 add a,a
 ld e,a
 ld h,0
 ld d,h
 ld l,a
 add hl,hl
 add hl,de
 ld a,b
 rra
 rra
 rra
 and %00011111
 ld e,a
 add hl,de
 ld a,b
 and %00000111
 ret





References: