;*************************************************************************

; GPL3+

; Copyright 2023 by Sean Conner.

; Draws a maze on a Color Computer.

;

;NOTE: This program has a bug for instructional purposes. See

; https://boston.conman.org/2023/11/27.1 for more information.

;*************************************************************************

	include	"Coco-DP.i"

	include	"Coco-video.i"

VIDEO equ $0E00

NORTH equ 8

EAST equ 4

WEST equ 2

SOUTH equ 1

EXPLORE equ 2

BACKTRACK equ 3

BG equ 0

xpos equ U76 ; these are unused locations

ypos equ U77 ; in the direct page of the Coco

xstart equ UF4

ystart equ UF5

lfsr equ UF6

color equ UF7

rnd4.cache equ UF8

rnd4.cnt equ UF9

;*************************************************************************

	org	$4000

start lda $FF22 ; set G1C mode-64x64 4-colors

	anda	#$07

	ora	#G1C.PIA

	sta	$FF22

	sta	$FFC4 + (G1C.MODE & 4 <> 0)

	sta	$FFC2 + (G1C.MODE & 2 <> 0)

	sta	$FFC0 + (G1C.MODE & 1 <> 0)

	ldx	#$FFD2		; point to frame buffer address bits

	lda	ECB.grpram	; get MSB of frame buffer

.mapframebuf clrb ; isolate next bit of address

	lsla

	rolb

	sta	b,x		; inform hardware of bit value

	leax	-2,x		; point to next "bit address"

	cmpx	#$FFC4		; 7-bits of address required

	bne	.mapframebuf

.clear_screen ldx ECB.beggrp ; address of frame buffer

	clra

	clrb

.cls_loop std ,x++ ; clear frame buffer

	cmpx	ECB.endgrp	; are we done with the clearing?

	bne	.cls_loop	; keep going if not.

	ldd	#32 * 256 + 32	; starting position

	std	xpos

	std	xstart

.reseed lda $112 ; read timer value

	beq	.reseed		; if zero, read again

	sta	lfsr		; seed our random number generator

	clr	rnd4.cnt	; and clear the rnd cache count

;*************************************************************************

explore lda #EXPLORE ; exploring free territory

	sta	color

.loop bsr boxed_in ; can we move?

	beq	backtrack	; if not, start backtracking

	lbsr	rnd4		; pick a random direction

	lslb

	leax	movetab,pc

	jsr	b,x		; call drawing function

	bra	.loop

;*************************************************************************

backtrack lda #BACKTRACK

	sta	color

.loop ldd xpos ; check to see if we're back

	cmpd	xstart		; at the starting point,

	beq	done		; and if so, we're done

	ldd	xpos		; can we backtrack NORTH?

	decb

	lbsr	getpixel

	cmpb	#EXPLORE

	bne	.check_east

	lbsr	move_north.now	; if so, move NORTH and see if

	bra	.probe		; we have to keep backtracking

.check_east ldd xpos ; east ...

	inca

	lbsr	getpixel

	cmpb	#EXPLORE

	bne	.check_west

	lbsr	move_east.now

	bra	.probe

.check_west ldd xpos ; yada yada ...

	deca

	lbsr	getpixel

	cmpb	#EXPLORE

	bne	.check_south

	lbsr	move_west.now

	bra	.probe

.check_south ldd xpos

	incb

	lbsr	getpixel

	cmpb	#EXPLORE

	bne	.probe

	lbsr	move_south.now

.probe bsr boxed_in ; can we stop backtracking?

	bne	explore		; if so, go back to exploring

	bra	.loop		; else backtrack some more

;*************************************************************************

done jsr [$A000]

	beq	done

	cmpa	#32

	lbeq	start.clear_screen

	jmp	[$FFFE]

;*************************************************************************

; BOXED_IN Are we boxed in?

;Entry: none

;Exit: A - direction flag

;*************************************************************************

boxed_in clr ,-s ; clear direction flags

	ldb	ypos

	beq	.check_east

	subb	#2		; look up two pixels

	lda	xpos

	lbsr	getpixel	; get the color there

	tstb			; 0?

	bne	.check_east	; if not, look towards the east

	lda	,s		; set NORTH flag

	ora	#NORTH

	sta	,s

.check_east lda xpos ; now look east

	cmpa	#62

	beq	.check_west

	adda	#2

	ldb	ypos

	lbsr	getpixel

	tstb

	bne	.check_west

	lda	,s

	ora	#EAST

	sta	,s

.check_west lda xpos ; and so on ...

	beq	.check_south

	suba	#2

	ldb	ypos

	bsr	getpixel

	tstb

	bne	.check_south

	lda	,s

	ora	#WEST

	sta	,s

.check_south ldb ypos

	cmpb	#62

	beq	.done

	addb	#2

	lda	xpos

	bsr	getpixel

	tstb

	bne	.done

	lda	,s

	ora	#SOUTH

	sta	,s

.done lda ,s+ ; set flags

	rts

;*************************************************************************

movetab bra move_north

	bra	move_east

	bra	move_west

	bra	move_south

;*************************************************************************

; MOVE_* Move (draw) along the maze

;Entry: A - dir

;Exit: A - trashed

; B - trashed

; X - trashed

;*************************************************************************

no_movement rts

move_north anda #NORTH

	beq	no_movement

.now bsr setpixel

	dec	ypos

	bsr	setpixel

	dec	ypos

	bra	setpixel

move_east anda #EAST

	beq	no_movement

.now bsr setpixel

	inc	xpos

	bsr	setpixel

	inc	xpos

	bra	setpixel

move_west anda #WEST

	beq	no_movement

.now bsr setpixel

	dec	xpos

	bsr	setpixel

	dec	xpos

	bra	setpixel

move_south anda #SOUTH

	beq	no_movement

.now bsr setpixel

	inc	ypos

	bsr	setpixel

	inc	ypos

;*************************************************************************

; SETPIXEL Set a pixel

;Uses: xpos

; ypos

;Exit: X - video address

; D - trashed

;*************************************************************************

setpixel ldd xpos

	bsr	point_addr	; get video address

	stb	,-s		; save mask

	ldb	color		; get color to use

	tsta			; any shift?

	beq	.setit		; if not, skip

.rotate lslb ; shift color bits

	deca

	bne	.rotate

.setit lda ,x ; get screen data

	anda	,s		; mask screen data

	sta	,s

	orb	,s+		; add in color

	stb	,x		; save back to video screen

	rts

;*************************************************************************

; GETPIXEL Get the color of a given pixel

;Entry: A - x pos

; B - y pos

;Exit: X - video address

; A - 0

; B - color

;*************************************************************************

getpixel bsr point_addr ; get video address

	comb			; reverse mask (since we're reading

	stb	,-s		; the screen, not writing it)

	ldb	,x		; get video data

	andb	,s+		; mask off the pixel

.rotate lsrb ; shift color bits

	deca

	bne	.rotate

.done rts ; return color in B

;*************************************************************************

; POINT_ADDR calculate the address of a pixel

;Entry: A - xpos

; B - ypos

;Exit: X - video address

; A - shift value

; B - mask

;*************************************************************************

point_addr.bits fcb %00111111,%11001111,%11110011,%11111100 ; masks

	fcb	6,4,2,0	; bit shift counts

point_addr pshs u,a ; save U and xpos

	lda	#16		; # byte per line

	mul			; calculate offset to line

	addd	ECB.beggrp	; add in start of video buffer

	tfr	d,x

	ldb	,s		; get xpos

	lsrb			; xpos /= 4

	lsrb

	abx			; add x offset into video address

	lda	,s+		; get xpos

	anda	#3		; xpos %= 4

	leau	.bits,pc	; point to mask bits table

	ldb	a,u		; get mask

	leau	4,u		; point to shift value table

	lda	a,u		; get shift value

	puls	u,pc		; restore U and return

;***********************************************************************

; RND4 Generate a random number 0 .. 3

;Entry: none

;Exit: B - random number

;***********************************************************************

rnd4 dec rnd4.cnt ; any more cached random #s?

	bpl	.cached		; yes, get next cached number

	ldb	#3		; else reset count

	stb	rnd4.cnt

	bsr	random		; get random number

	stb	rnd4.cache	; save in the cache

	bra	.ret		; and return the first number

.cached ldb rnd4.cache ; get cached value

	lsrb			; get next 2-bit random number

	lsrb

	stb	rnd4.cache	; save ermaining bits

.ret andb #3 ; mask off our result

	rts

;***********************************************************************

; RANDOM Generate a random number

;Entry: none

;Exit: B - random number (1 - 255)

;***********************************************************************

random ldb lfsr

	andb	#1

	negb

	andb	#$B4

	stb	,-s		; lsb = -(lfsr & 1) & taps

	ldb	lfsr

	lsrb			; lfsr >>= 1

	eorb	,s+		; lfsr ^=  lsb

	stb	lfsr

	rts

;*************************************************************************

	end	start

Proxy Information
Original URL
gemini://gemini.conman.org/boston/2023/11/27/maze-bug.asm
Status Code
Success (20)
Meta
text/plain; charset=us-ascii
Capsule Response Time
871.813895 milliseconds
Gemini-to-HTML Time
3.003639 milliseconds

This content has been proxied by September (ba2dc).