Skip to content

Instantly share code, notes, and snippets.

@ped7g
Created April 8, 2021 06:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ped7g/b33111b1d91dc4441b8579831da507bc to your computer and use it in GitHub Desktop.
Save ped7g/b33111b1d91dc4441b8579831da507bc to your computer and use it in GitHub Desktop.
ZX Spectrum Next - size optimised setup of larger block of next-registers
; Author: Ped7g ; (C) 2021 ; license: https://opensource.org/licenses/MIT
; Z80N (ZX Next) assembly, sjasmplus syntax: https://github.com/z00m128/sjasmplus
;
; code-size optimisation for larger next-reg init block, where `nextreg r,v` ED91rrvv
; opcode takes four bytes for every next-reg set, so a block of 20 pair values takes
; 80 bytes (with the "setup_next_regs_v2" approach such block will take only 58 bytes)
;----------------------------------------------------------------------------------------
; variant 1, reads next-reg pairs from particular memory address
; this will break-even at 8 value pairs, every one more pair is two byte less
; compared to block of four byte opcodes `nextreg r,v`
setup_next_regs_v1: ; 16 bytes long code
ld hl,nr_values ; source address of next-reg value pairs
ld bc,$243B + $0100 ; TBBLUE_REGISTER_SELECT_P_243B with ++B
xor a
.set_loop:
outi ; adjust BC to $243B and out *HL++ (register num)
inc b ; bc = TBBLUE_REGISTER_ACCESS_P_253B
outinb ; out *HL++ (value)
cp (hl)
jr nz,.set_loop ; loop until zero-terminator is reached
ret
;----------------------------------------------------------------------------------------
; variant 2, reads next-reg pairs from machine code following the caller's `call`
; instruction. This will break-even at 7 value pairs.
; The routine technically returns at wrong address into data, but at the zero-terminator
; which means a harmless `nop` is executed.
setup_next_regs_v2: ; 14 bytes long code
pop hl ; read values from return address
ld bc,$243B + $0100 ; TBBLUE_REGISTER_SELECT_P_243B with ++B
xor a
.set_loop:
outi ; adjust BC to $243B and out *HL++ (register num)
inc b ; bc = TBBLUE_REGISTER_ACCESS_P_253B
outinb ; out *HL++ (value)
cp (hl)
jr nz,.set_loop ; loop until zero-terminator is reached
; return back [almost] beyond the data (jumps at the zero-terminator == `nop`)
jp (hl)
;----------------------------------------------------------------------------------------
; both variants save extra bytes for second+ call starting from 3+ reg-value pairs.
;----------------------------------------------------------------------------------------
; example of v2 usage
call setup_next_regs_v2
; |
; data to set up follow the `call` instruction
; |
; v
;----------------------------------------------------------------------------------------
; example of init value pairs
nr_values: ; example of tilemode init with ULA display OFF
db $64,33 ; VIDEO_LINE_OFFSET_NR_64
; set other NextRegs to default settings of 80x42 tilemode component
db $6B,%11000001 ; Tilemap control
;= +enable +80col -noAttr -palNum -textMode .r -512tile +forceTmOverUla
db $6E,high $4000 ; Tile map base address
db $6F,high $6000 ; Tiles gfx base address
db $4C,$0f ; Transparency colour (last item)
db $68,%10000000 ; Disable ULA output
;*; +disableUla-blending-r-r-r-r-r-stencil
db $1C,$08 ; reset tilemap clip window index to 0
db $1B,0 ; reset clip window to 640x256
db $1B,159
db $1B,0
db $1B,255
db 0 ; init list terminator (and `nop` for v2 return)
; here is the code where the setup_next_regs_v2 will return to (end of v2 usage example)
jr $
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment