Stack tricks

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
presh
Manic Miner
Posts: 237
Joined: Tue Feb 25, 2020 8:52 pm
Location: York, UK

Stack tricks

Post by presh »

My confidence with manipulating SP is growing, having successfully implemented my first stack-based screen blitter with Display and Attribute rows interleaved.

It got me thinking - what else can we do faster utilising the stack pointer?

I discovered a "clear memory" routine in my code which I figured could go faster:

Code: Select all

  ; clear 256 byte heap
  LD HL, heap_addr  ; divisible by $100 [10]
  XOR A             ; [4]
REPT 256
  LD (HL), A        ; [7] x256
  INC L             ; [4] x256
ENDM
Total: 2830 Ts in 516 bytes

Using SP:

Code: Select all

  ; clear 256 byte heap
  LD (sp_store), SP       ; [20]
  LD SP, heap_addr + $100 ; [10]
  LD HL, 0                ; [10]
REPT 128
  PUSH HL                 ; [11] x128
ENDM
  LD SP, (sp_store)       ; [20]
Total: 1468 Ts in 142 bytes - nearly half the time, and nearly 1/4 of the memory! :shock: :)


I've also manipulated SP in a look-up table when drawing sprites; after each row, I simply POP the screen address at which the next pixel row starts, and then just add the sprite's x position... much quicker than the arithmetic & logic required to determine and adjust for the cell / block boundaries (at least within my implementation!) but also much simpler-looking code, cleaner and easier to understand without all those extra logical caveats.

I'm sure none of this is anything new, so my question is: which other cool SP-based tricks can you think of?
User avatar
cmal
Manic Miner
Posts: 630
Joined: Fri Jun 05, 2020 1:05 am
Location: California

Re: Stack tricks

Post by cmal »

Nice clearing trick!
Similar to what you've done, I've used the stack to load sprite data to the screen instead of loading the screen address. It's not new or groundbreaking. I think quite a lot of games do this. That way you can pop two sprite bytes from the stack at once.

Something like this:

Code: Select all

pop de
ld (hl),e
inc l
ld (hl),d
For the screen address, you can fairly quickly look it up:

Code: Select all

;L = Y coordinate
;E = X coordinate
ld h,HIGH ScreenAdrTable (address is divisable by 256)
ld a,(hl)	;get display address low byte
inc h
ld h,(hl)	;get display address high byte
add a,e
ld l,a
presh
Manic Miner
Posts: 237
Joined: Tue Feb 25, 2020 8:52 pm
Location: York, UK

Re: Stack tricks

Post by presh »

cmal wrote: Tue Dec 29, 2020 5:53 pm I've used the stack to load sprite data to the screen instead of loading the screen address.
[...]

Code: Select all

pop de
ld (hl),e
inc l
ld (hl),d
Nice, exactly the kind of thing I'm after! And I guess you could modify this to work with interleaved mask/graphic data...

Code: Select all

POP DE
LD A, (HL)
AND E       ; mask
OR D        ; graphic
LD (HL), A
User avatar
cmal
Manic Miner
Posts: 630
Joined: Fri Jun 05, 2020 1:05 am
Location: California

Re: Stack tricks

Post by cmal »

You can use the stack to simplify code to some extent, I guess. For example writing strings, you can have the string following right after the call:

Code: Select all

		call	write_string
		DEFM "This sentence will prin", "t"+128
		ld	c,2
		...


write_string:
                di
		ex	(sp),hl	;HL points to start of string
		...
		...		;Code to print the string
		...
		ex	(sp),hl	;before this point, HL must point to the location right after the last character in the string
		ei
		ret
presh
Manic Miner
Posts: 237
Joined: Tue Feb 25, 2020 8:52 pm
Location: York, UK

Re: Stack tricks

Post by presh »

Found another one!

The final chunk of code on this page shows how to quickly print repeated background tiles to screen:

"ZX Spectrum Ghost 'n Goblins: graphics routines"
http://www.emix8.org/ggdisasm/

Image

I'm assuming a similar method is/could be used to generate tiled parallax backgrounds such as those in Rastan - just shift the tile graphics first, then POP the data and PUSH to screen en-masse.

In fact there are repeating tiles everywhere you look in this one. Hmm!

https://www.youtube.com/watch?v=QDzrkndlnWk
User avatar
cmal
Manic Miner
Posts: 630
Joined: Fri Jun 05, 2020 1:05 am
Location: California

Re: Stack tricks

Post by cmal »

That was an interesting read on Ghosts 'n Goblins. I always liked how smooth the scrolling was in that game. Only now that I realize that the two right-most columns are attributed out for clipping reasons :o . I just assumed that was the black border.
presh
Manic Miner
Posts: 237
Joined: Tue Feb 25, 2020 8:52 pm
Location: York, UK

Re: Stack tricks

Post by presh »

You can do arithmetic on the stack pointer - in Hell Yeah!'s sprite engine, I need to skip a precalculated number of data bytes after each row if the sprite has its width cropped. Turn's out, that's dead easy!

Code: Select all

    ; Get the byte offset
    ; (this value was self-modified by the code earlier for speed)
    LD HL, 8    
    ; Add the current SP value (sprite data pointer)
    ADD HL, SP
    ; Set the new SP value
    LD SP, HL
Or if you just want HL = SP

Code: Select all

    LD HL,0
    ADD HL, SP
(HL can be substituted for IX or IY in all of the above)
Post Reply