raycast: dos whitespace undamage

This commit is contained in:
Vince Weaver 2021-06-02 01:59:32 -04:00
parent a04725449e
commit 613df3f4e4

View File

@ -1,464 +1,464 @@
;--------------------------------------- ;---------------------------------------
; based on 1bir - 1 block interactive raycaster ; based on 1bir - 1 block interactive raycaster
; coded by huseyin kilic (wisdom) ; coded by huseyin kilic (wisdom)
; copyright (c) 2009-2013 crescent ; copyright (c) 2009-2013 crescent
.include "hardware.inc" .include "hardware.inc"
; zero page ; zero page
V2 = $2D V2 = $2D
COLOR = $30 COLOR = $30
RAYPOSX = $61 RAYPOSX = $61
RAYPOSXH = $62 RAYPOSXH = $62
RAYPOSY = $63 RAYPOSY = $63
RAYPOSYH = $64 RAYPOSYH = $64
STEPX = $66 ; leave 1 byte between x and y STEPX = $66 ; leave 1 byte between x and y
STEPY = $68 STEPY = $68
PLAYERX = $69 PLAYERX = $69
PLAYERXH = $6a PLAYERXH = $6a
PLAYERY = $6b PLAYERY = $6b
PLAYERYH = $6c PLAYERYH = $6c
DISTANCE = $70 ; reset in $bc00 and $bc0f calls DISTANCE = $70 ; reset in $bc00 and $bc0f calls
ROWPTR = $d1 ROWPTR = $d1
ROWPTRH = $d2 ROWPTRH = $d2
LINEH_T = $d9 LINEH_T = $d9
WALL_HEIGHT = $f8 WALL_HEIGHT = $f8
FLOOR_SKY_HEIGHT= $f9 FLOOR_SKY_HEIGHT= $f9
; external value dependencies ; external value dependencies
HEADING = $81 HEADING = $81
SINADD = $9a SINADD = $9a
COLORS = $b1 ; 3 bytes consecutively COLORS = $b1 ; 3 bytes consecutively
; temp ; temp
CURRENTROW = $ff CURRENTROW = $ff
; constants ; constants
sin_t = $1000 sin_t = $1000
blocksize = $28 blocksize = $28
;--------------------------------------- ;---------------------------------------
; main ; main
;--------------------------------------- ;---------------------------------------
main: main:
jsr SETGR jsr SETGR
bit FULLGR bit FULLGR
lda #$20 lda #$20
sta HEADING sta HEADING
;--------------------------------------- ;---------------------------------------
; sin/cos table generator ; sin/cos table generator
;--------------------------------------- ;---------------------------------------
; first generate sine for 0..63 (0..90 degrees) ; first generate sine for 0..63 (0..90 degrees)
lda #3 lda #3
sta SINADD sta SINADD
lda #$00 lda #$00
tay tay
gensin_loop: gensin_loop:
sta sin_t,Y sta sin_t,Y
iny iny
clc clc
] adc SINADD ] adc SINADD
ldx SINADD ldx SINADD
dec sincount_t,X dec sincount_t,X
bne gensin_loop bne gensin_loop
dec SINADD dec SINADD
bpl gensin_loop bpl gensin_loop
; x = $00 ; x = $00
; y = $40 ; y = $40
; next generate ; next generate
gensin_loop2: gensin_loop2:
lda sin_t,X lda sin_t,X
sta sin_t+$0100,X ; copy at $100 so cosine easier sta sin_t+$0100,X ; copy at $100 so cosine easier
sta sin_t-1+$40,Y ; store 90-180 degrees sta sin_t-1+$40,Y ; store 90-180 degrees
eor #$ff ; invert eor #$ff ; invert
sta sin_t+$80,X ; store for 180-270 degrees sta sin_t+$80,X ; store for 180-270 degrees
sta sin_t-1+$c0,Y ; store for 270-360 degrees sta sin_t-1+$c0,Y ; store for 270-360 degrees
inx inx
dey dey
bpl gensin_loop2 bpl gensin_loop2
;--------------------------------------- ;---------------------------------------
; raycaster ; raycaster
;--------------------------------------- ;---------------------------------------
loop_main: loop_main:
; cast 40 rays for each screen column ; cast 40 rays for each screen column
; starting with rightmost one ; starting with rightmost one
; Y is used as global column index ; Y is used as global column index
; throughout the rest of the program ; throughout the rest of the program
ldy #39 ldy #39
loop_ray: loop_ray:
; determine current ray's direction ; determine current ray's direction
; by taking player's current direction ; by taking player's current direction
; and fov into account ; and fov into account
; fov is 40 b-rads out of 256 b-rads ; fov is 40 b-rads out of 256 b-rads
tya tya
clc clc
adc HEADING adc HEADING
;sec ;sec
sbc #19+1 ; half of the fov (+1 because of sec) sbc #19+1 ; half of the fov (+1 because of sec)
tax tax
; get sin/cos values accordingly ; get sin/cos values accordingly
; and copy player position to current ray position ; and copy player position to current ray position
; distance is reset on return from this call ; distance is reset on return from this call
jsr getsincos_copyplr2ray jsr getsincos_copyplr2ray
; reset line row before each column gets drawn ; reset line row before each column gets drawn
; (needed in vertical line section) ; (needed in vertical line section)
; X is 0 here? ; X is 0 here?
stx CURRENTROW stx CURRENTROW
loop_dist: loop_dist:
; step along current ray's path and find distance ; step along current ray's path and find distance
inc DISTANCE inc DISTANCE
; limit distance when it is needed in larger maps ; limit distance when it is needed in larger maps
; or open (wrapped) maps ; or open (wrapped) maps
; max distance = $29 ; max distance = $29
; lda DISTANCE ; lda DISTANCE
; cmp #$29 ; cmp #$29
; bcs skip_dist ; bcs skip_dist
; max distance = $40 (make sure ar is always 0 here) ; max distance = $40 (make sure ar is always 0 here)
; bit DISTANCE ; bit DISTANCE
; bvs skip_dist ; bvs skip_dist
; max DISTANCE = $80 ; max DISTANCE = $80
bmi skip_dist bmi skip_dist
jsr addsteptopos jsr addsteptopos
; on return from last call, A is cell (block) value ; on return from last call, A is cell (block) value
; A == 0 means empty cell, so continue tracing ; A == 0 means empty cell, so continue tracing
beq loop_dist beq loop_dist
skip_dist: skip_dist:
; now A contains the value in reached map position ; now A contains the value in reached map position
; (or last cell value fetched if max distance is reached) ; (or last cell value fetched if max distance is reached)
; use A or X to colorize the block ; use A or X to colorize the block
; and #$07 ; and #$07
; ora #$03 ; ora #$03
sta COLORS+1 sta COLORS+1
; find out visible block height ; find out visible block height
; according to distance ; according to distance
ldx #$ff ldx #$ff
; calculate visible block height through simple division ; calculate visible block height through simple division
lda #<blocksize lda #<blocksize
loop_div: loop_div:
inx inx
; sec ; sec
sbc DISTANCE sbc DISTANCE
bcs loop_div bcs loop_div
; X = half of visible block height ; X = half of visible block height
txa txa
;--------------------------------------- ;---------------------------------------
; vertical line ; vertical line
;--------------------------------------- ;---------------------------------------
; Y = x position (screen column) ; Y = x position (screen column)
; A = half height (zero height is ok) ; A = half height (zero height is ok)
cmp #24 ; height > 24? cmp #24 ; height > 24?
bcc vline_validheight bcc vline_validheight
lda #23 ; make sure max height = 24 lda #23 ; make sure max height = 24
vline_validheight: vline_validheight:
asl ; calculate full height asl ; calculate full height
sta WALL_HEIGHT ; store for looping below sta WALL_HEIGHT ; store for looping below
eor #$ff ; subtract full height from screen height eor #$ff ; subtract full height from screen height
; sec ; (48 rows) ; sec ; (48 rows)
adc #48+1 ; +1 because of sec adc #48+1 ; +1 because of sec
lsr ; sky/floor heights are equal to each other lsr ; sky/floor heights are equal to each other
sta FLOOR_SKY_HEIGHT sta FLOOR_SKY_HEIGHT
; loop through 3 sections of one screen column ; loop through 3 sections of one screen column
; i.e. sky - wall - floor ; i.e. sky - wall - floor
vline_loop: vline_loop:
;========== ;==========
; vline sky, 0 to FLOOR_SKY_HEIGHT ; vline sky, 0 to FLOOR_SKY_HEIGHT
; load color ; load color
lda #$77 ; sky blue lda #$77 ; sky blue
sta COLOR sta COLOR
lda FLOOR_SKY_HEIGHT lda FLOOR_SKY_HEIGHT
sta V2 sta V2
lda #0 lda #0
jsr VLINE ; VLINE A,$2D at Y (Y preserved, A=V2) jsr VLINE ; VLINE A,$2D at Y (Y preserved, A=V2)
;================= ;=================
; vline wall, FLOOR_SKY_HEIGHT to FLOOR_SKY_HEIGHT+WALL_HEIGHT ; vline wall, FLOOR_SKY_HEIGHT to FLOOR_SKY_HEIGHT+WALL_HEIGHT
ldx COLORS+1 ldx COLORS+1
stx COLOR stx COLOR
; A already FLOOR_SKY_HEIGHT ; A already FLOOR_SKY_HEIGHT
clc clc
adc WALL_HEIGHT adc WALL_HEIGHT
sta V2 sta V2
lda FLOOR_SKY_HEIGHT lda FLOOR_SKY_HEIGHT
jsr VLINE ; VLINE A,$2D at Y jsr VLINE ; VLINE A,$2D at Y
;============= ;=============
; vline floor, WALL_HEIGHT+FLOOR_SKY_HEIGHT to 47 ; vline floor, WALL_HEIGHT+FLOOR_SKY_HEIGHT to 47
ldx #$88 ldx #$88
stx COLOR stx COLOR
; A already WALL_HEIGHT+FLOOR_SKY_HEIGHT ; A already WALL_HEIGHT+FLOOR_SKY_HEIGHT
ldx #47 ldx #47
stx V2 stx V2
jsr VLINE ; VLINE A,$2D at Y jsr VLINE ; VLINE A,$2D at Y
;--------------------------------------- ;---------------------------------------
; advance to next ray/column ; advance to next ray/column
dey dey
bpl loop_ray bpl loop_ray
;--------------------------------------- ;---------------------------------------
; user input ; user input
;--------------------------------------- ;---------------------------------------
; common preparation code to set up sin/cos and ; common preparation code to set up sin/cos and
; to copy player position to ray position to trace movement ; to copy player position to ray position to trace movement
; direction to determine if player hits a block ; direction to determine if player hits a block
; in case player actually tries to move forward or backwards ; in case player actually tries to move forward or backwards
ldx HEADING ldx HEADING
jsr getsincos_copyplr2ray jsr getsincos_copyplr2ray
; get joystick 2 status (lowest 4 bits) ; get joystick 2 status (lowest 4 bits)
; and check each bit to determine action ; and check each bit to determine action
lda KEYPRESS lda KEYPRESS
beq done_user_input beq done_user_input
cmp #'W'+$80 cmp #'W'+$80
bne skip_j1 bne skip_j1
; try to move forward ; try to move forward
pha pha
jsr stepandcopy jsr stepandcopy
pla pla
skip_j1: skip_j1:
cmp #'S'+$80 cmp #'S'+$80
bne skip_j2 bne skip_j2
; try to move backward ; try to move backward
pha pha
jsr invertstepandcopy jsr invertstepandcopy
pla pla
skip_j2: skip_j2:
cmp #'A'+$80 cmp #'A'+$80
bne skip_j3 bne skip_j3
; turn right ; turn right
dec HEADING dec HEADING
dec HEADING dec HEADING
skip_j3: skip_j3:
cmp #'D'+$80 cmp #'D'+$80
bne done_user_input bne done_user_input
; turn left ; turn left
inc HEADING inc HEADING
inc HEADING inc HEADING
done_user_input: done_user_input:
bit KEYRESET ; clear keyboard buffer bit KEYRESET ; clear keyboard buffer
; absolute jump, as carry is always 0 here ; absolute jump, as carry is always 0 here
jmp loop_main jmp loop_main
;--------------------------------------- ;---------------------------------------
; ray tracing subroutines ; ray tracing subroutines
;--------------------------------------- ;---------------------------------------
; heart of tracing, very slow, because of looping ; heart of tracing, very slow, because of looping
; for x and y components and also because of ; for x and y components and also because of
; brute force approach ; brute force approach
addsteptopos: addsteptopos:
ldx #$02 ldx #$02
loop_stepadd: loop_stepadd:
lda STEPX,X ; & y lda STEPX,X ; & y
ora #$7f ; sign extend 8 bit step value to 16 bit ora #$7f ; sign extend 8 bit step value to 16 bit
bmi was_neg ; was negative *+4 bmi was_neg ; was negative *+4
lda #$00 lda #$00
was_neg: was_neg:
pha pha
;clc ;clc
lda STEPX,x ; & y lda STEPX,x ; & y
adc RAYPOSX,x ; & y adc RAYPOSX,x ; & y
sta RAYPOSX,x ; & y sta RAYPOSX,x ; & y
pla pla
adc RAYPOSXH,x ; & y adc RAYPOSXH,x ; & y
sta RAYPOSXH,x ; & y sta RAYPOSXH,x ; & y
dex dex
dex dex
bpl loop_stepadd bpl loop_stepadd
; A = RAYPOSXH ; A = RAYPOSXH
; calculate index to look up the map cell ; calculate index to look up the map cell
; the map area is 8x8 bytes ; the map area is 8x8 bytes
; + instead of the usual y * 8 + x ; + instead of the usual y * 8 + x
; x * 8 + y done here, to save some bytes ; x * 8 + y done here, to save some bytes
; (just causing a flip of the map as a side effect) ; (just causing a flip of the map as a side effect)
asl asl
asl asl
asl asl
asl asl
; by doing ora instead of adc, it is possible to have ; by doing ora instead of adc, it is possible to have
; a closed area map in $ecb9 ; a closed area map in $ecb9
adc RAYPOSYH adc RAYPOSYH
tax tax
lda map_t,X lda map_t,X
step_exit: step_exit:
rts rts
;--------------------------------------- ;---------------------------------------
; getsincos_copyplr2ray ; getsincos_copyplr2ray
;--------------------------------------- ;---------------------------------------
getsincos_copyplr2ray: getsincos_copyplr2ray:
lda sin_t,X ; sin(x) lda sin_t,X ; sin(x)
sta STEPX sta STEPX
lda sin_t+$40,X ; cos(x) lda sin_t+$40,X ; cos(x)
sta STEPY sta STEPY
; copy player position to ray position for a start ; copy player position to ray position for a start
; through the basic rom ; through the basic rom
copyplr2ray: ; $bc00 in c64 kernel? copyplr2ray: ; $bc00 in c64 kernel?
ldx #$05 ; copy 5 bytes, from 69..6D to 61..65 ldx #$05 ; copy 5 bytes, from 69..6D to 61..65
copyloop: copyloop:
lda $68,X lda $68,X
sta $60,X sta $60,X
dex dex
bne copyloop bne copyloop
stx DISTANCE ; side effect, needed? stx DISTANCE ; side effect, needed?
rts rts
;====================================== ;======================================
; invert step and copy ; invert step and copy
;====================================== ;======================================
invertstepandcopy: invertstepandcopy:
; invert step variables for backward motion ; invert step variables for backward motion
invertstepx: ; from BFB8 in C64 ROM invertstepx: ; from BFB8 in C64 ROM
lda $66 lda $66
eor #$ff eor #$ff
sta $66 sta $66
invertstepy: invertstepy:
lda STEPY lda STEPY
eor #$ff eor #$ff
sta STEPY sta STEPY
;======================================= ;=======================================
; stepandcopy ; stepandcopy
;======================================= ;=======================================
stepandcopy: stepandcopy:
; see if player can move to the direction desired ; see if player can move to the direction desired
jsr addsteptopos jsr addsteptopos
bne step_exit ; no, return without doing anything bne step_exit ; no, return without doing anything
; yes, move player by ; yes, move player by
; copying ray position to player position ; copying ray position to player position
; through the basic rom ; through the basic rom
copyray2plr: ; BC0f in c64 ROM copyray2plr: ; BC0f in c64 ROM
ldx #$6 ldx #$6
r2_loop: r2_loop:
lda $60,X lda $60,X
sta $68,X sta $68,X
dex dex
bne r2_loop bne r2_loop
stx DISTANCE stx DISTANCE
rts rts
;--------------------------------------- ;---------------------------------------
; data ; data
;--------------------------------------- ;---------------------------------------
; number of sin additions (backwards) ; number of sin additions (backwards)
sincount_t: sincount_t:
.byte 6,14,19,25 .byte 6,14,19,25
;--------------------------------------- ;---------------------------------------
.if 0 .if 0
map_t: map_t:
.byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
.byte $55,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$44,$00,$00,$00,$00,$55 .byte $55,$00,$44,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$11,$00,$55 .byte $55,$00,$00,$00,$00,$11,$00,$55
.byte $55,$22,$00,$00,$00,$00,$00,$55 .byte $55,$22,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$99,$00,$00,$00,$55 .byte $55,$00,$00,$99,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$55
.byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
.endif .endif
map_t: map_t:
.byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
.byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$11,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$11,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$22,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$22,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$22,$22,$22,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$22,$22,$22,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$22,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$22,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$33,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$33,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$99,$99,$11,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$99,$99,$11,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55 .byte $55,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55
.byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff