I searched around for a compact routine for calculating the VIC-II byte address of a point, given its (x, y) coordinates. As you know, the VIC-II has a weird addressing, i.e. the bitmap addressing in 320x200 graphic mode is not linear: the very first 8 addresses refer to the 8x8-pixel block at top left of the screen, the 2nd ones to the next right block, and so on; so the mapping (x,y) -> address is given by this function:
address(x,y) = 320*row + 8*col + line, where row=int(y/8), col=int(x/col), line=y AND 7.
Most of the routines I found make use of huge tables to precalculate the address; I wrote the routine below, which doesn't waste a lot of space, but is not very fast.
I'll be glad if someone posts a better code, many thanks!
Code: Select all
;Calculate address and mask for a given 320x200-hires point
;address= Base + 320*r + 8*c + l, r=int(y/8), c=int(x/8), l=y&$07
; = Base + 320*(y>>3) + 8*(x>>3) + y&$07
; = Base + 256*(y>>3) + 64*(y>>3) + 256*(>x) + x&$F8 + y&$07
; = Base + 256*(y>>3) + (y>>3:$00)>>2 + 256*(>x) + x&$F8 + y&$07
;so we can access that memory address by a 16-bit pointer as below:
;ptr_h = >Base + y>>3 + >x + >((y>>3:$00)>>2)
;ptr_l = <((y>>3:$00)>>2) + y&$07
;Y = x&$F8
; IN: X:<x, C:>x, Y:y, .baseh:>Base, .ptr:pointer
; OUT: .ptr+Y:address, X:bitmask offset, A:X, C:0, N:0, Z:?, V:?
!macro COORD .ptr, .baseh {
TYA ;2
AND #$07 ;2 ;A = y & 7
ROL ;2 ;save C in bit0 of .ptr, then move it
ASL ;2 ;in bit1 (it'll be RORed out later)
STA .ptr ;3 ;.ptr = 0 0 0 y2 y1 y0 >x 0
TYA ;2
LSR ;2
LSR ;2
LSR ;2
STA .ptr + 1 ;3 ;.ptr+1 = y>>3 = 0 0 0 y7 y6 y5 y4 y3
LSR ;2
ROR .ptr ;5
LSR ;2 ;A= >((y>>3:$00)>>2)=0 0 0 0 0 y7 y6 y5
ROR .ptr ;5 ;.ptr = <((y>>3:$00)>>2) + y&7, C = >x
ADC .ptr + 1 ;3 ;A = A + y>>3 + >x
;CLC ;C already clear
ADC #.baseh ;2 ;A = A + >Base
STA .ptr + 1 ;3 ;.ptr+1= >Base+y>>3+>x+>((y>>3:$00)>>2)
TXA ;2
AND #$F8 ;2
TAY ;2 ;Y = x&$F8, (.ptr),Y = address
;52 TOT
;; calculate bitmasks offset
TXA ;2
AND #$07 ;2
TAX ;2 ;X = mask offset
} ;58 TOT
; Bitmasks
setmsk !byte $80, $40, $20, $10, $08, $04, $02, $01
clrmsk !byte $7F, $BF, $DF, $EF, $F7, $FB, $FD, $FE