changeset 33:28a84507a829

Decoded much of the scheduling code and scheduled events The timer ticks and various scheduling has been decoded. Also, the main input processing loop has been decoded.
author William Astle <lost@l-w.ca>
date Fri, 26 Dec 2014 21:20:45 -0700
parents 8a94218c2a4c
children acf702e04bdf
files dod.s
diffstat 1 files changed, 322 insertions(+), 289 deletions(-) [+]
line wrap: on
line diff
--- a/dod.s	Fri Dec 26 19:20:30 2014 -0700
+++ b/dod.s	Fri Dec 26 21:20:45 2014 -0700
@@ -116,6 +116,11 @@
 clearcommand	macro noexpand
 		dod S0B
 		endm
+; check for death, fainting, or recovery, and calculate how long before next
+; damage reduction tick
+checkdamage	macro noexpand
+		dod S0C
+		endm
 ; update the inventory on the status line
 updatestatus	macro noexpand
 		dod S0D
@@ -314,16 +319,23 @@
 V291		rmb 1				; for iterating over object list, zero means start, nonzero means underway
 V292		rmb 2				; current object pointer for iteration
 V294		rmb 1				; nonzero means to show creatures when displaying a scroll
-V295		rmb 2
-V297		rmb 3
+V295		rmb 1				; 10Hz timer counter
+		rmb 1				; 1Hz timer counter
+V297		rmb 1				; 1 min timer counter
+		rmb 1				; 1 hour timer counter
+		rmb 1				; 1 day timer counter
 V29A		rmb 1
-V29B		rmb 1
+disablesched	rmb 1				; set to nonzero to disable timer handling
 V29C		rmb 1
 V29D		rmb 1
 V29E		rmb 1
 V29F		rmb 2
-V2A1		rmb 10
-V2AB		rmb 2
+V2A1		rmb 2				; 60Hz tick event list
+		rmb 2				; 10Hz tick event list
+		rmb 2				; 1Hz tick event list
+		rmb 2				; 1 minute tick event list
+		rmb 2				; 1 hour tick event list
+V2AB		rmb 2				; the "ready" list (also 1 day tick event list)
 V2AD		rmb 1
 V2AE		rmb 1
 V2AF		rmb 1
@@ -428,20 +440,20 @@
 LC05A		clr ,x+				; clear a byte
 		cmpx #V2AD			; are we finished clearing things?
 		blo LC05A			; brif not
-		ldx #V9FD
-		stx V2B9
+		ldx #V9FD			; start of the sceduling list
+		stx V2B9			; mark that as the end of it
 LC066		clr ,x+				; clear more data
 		cmpx #emptyhand			; end of area to clear?
 		blo LC066			; brif not
-		ldy #LD7DC
+		ldy #LD7DC			; point to list of entries to schedule
 		dec V2BB
-		ldd #12
-LC076		ldx ,y++
-		beq LC084
-		jsr LC25C
-		stx 3,u
-		jsr LC21D
-		bra LC076
+		ldd #12				; set tick count to 0 and list to "ready" list
+LC076		ldx ,y++			; get routine address
+		beq LC084			; brif end of list
+		jsr LC25C			; create scheduler entry
+		stx 3,u				; save routine address in scheduling entry
+		jsr LC21D			; add to "ready" list
+		bra LC076			; go look for another routine
 LC084		puls cc,a,b,x,y,u,pc
 LC086		bsr LC053			; initialize new level data
 		ldu #LDA91			; point to objects to create for game
@@ -532,14 +544,14 @@
 		bra LC139			; go look for another object to create
 LC14F		tst waitnewgame			; are we doing a demo game?
 		beq LC166			; brif not
-		dec V29B
+		dec disablesched		; disable scheduling events
 		ldx #displayscroll		; set to scroll display
 		stx displayptr
 		dec V294			; set to show creatures on map
 		dod S0E				; show the dungeon map
 		delay				; delay for about 2.5 seconds
 		delay
-		clr V29B
+		clr disablesched		; enable scheduling events
 		sync				; wait a couple of ticks
 		sync
 LC166		dod S19				; clear command and status areas and show the dungeon
@@ -602,62 +614,62 @@
 		clr V2B8			; flag regular operations
 		dod S19				; clear command and status areas, update appropriately
 		showprompt			; show command prompt
-LC1F5		ldu #V2AB
-		clr V2BB
-LC1FA		tfr u,y
+LC1F5		ldu #V2AB			; point to ready list head
+		clr V2BB			; mark ready list restart not needed
+LC1FA		tfr u,y				; save ready list pointer
 LC1FC		tst V2B8			; are we loading or saving?
 		bgt LC192			; brif saving
 		bmi LC1C1			; brif loading
-		ldu ,u
-		beq LC1F5
-		pshs y,u
-		jsr [3,u]
-		puls y,u
-		tst V2BB
-		bne LC1F5
-		cmpb #12
-		beq LC1FA
-		bsr LC238
-		bsr LC21D
-		tfr y,u
-		bra LC1FC
-LC21D		pshs cc,a,b,x
-		orcc #$10
-		sta 2,u
-		ldx #V29F
-		abx
-		clra
+		ldu ,u				; are we at the end of the ready list?
+		beq LC1F5			; brif so
+		pshs y,u			; save registers
+		jsr [3,u]			; call the registered routine
+		puls y,u			; restore registers
+		tst V2BB			; do we need to restart the ready list processing?
+		bne LC1F5			; brif so
+		cmpb #12			; are we leaving the routine in the ready list?
+		beq LC1FA			; brif so - check next entry
+		bsr LC238			; remove this event from the ready list
+		bsr LC21D			; reschedule in requested queue for requested number of ticks
+		tfr y,u				; move current pointer to previous pointer
+		bra LC1FC			; go check next entry
+LC21D		pshs cc,a,b,x			; save flags and registers
+		orcc #$10			; disable IRQ
+		sta 2,u				; reset tick count
+		ldx #V29F			; pointer to routine base
+		abx				; add offset
+		clra				; NULL pointer
 		clrb
-		std ,u
-LC22B		cmpd ,x
-		beq LC234
-		ldx ,x
-		bra LC22B
-LC234		stu ,x
-		puls cc,a,b,x,pc
-LC238		pshs cc,x
-		orcc #$10
-		ldx ,u
-		stx ,y
-		puls cc,x,pc
-LC242		pshs b,x,y,u
-		tst V29B
-		bne LC25A
-LC248		tfr u,y
-		ldu ,u
-		beq LC25A
-		dec 2,u
-		bne LC248
-		bsr LC238
-		ldb #12
-		bsr LC21D
-		bra LC248
-LC25A		puls b,x,y,u,pc
-LC25C		pshs x
-		ldu V2B9
-		leax 7,u
-		stx V2B9
-		puls x,pc
+		std ,u				; mark this timer unused
+LC22B		cmpd ,x				; are we at a NULL pointer (end of list)?
+		beq LC234			; brif so
+		ldx ,x				; point to next entry
+		bra LC22B			; go check if we're at the end yet
+LC234		stu ,x				; move this timer entry to the end of the list
+		puls cc,a,b,x,pc		; restore registers, interrupt status,  and return
+LC238		pshs cc,x			; save interrupt status and registers
+		orcc #$10			; disable IRQ
+		ldx ,u				; get next pointer from this entry
+		stx ,y				; save it in previous entry
+		puls cc,x,pc			; restore interrupts, registers, and return
+LC242		pshs b,x,y,u			; save registers
+		tst disablesched		; are we handling timers?
+		bne LC25A			; brif not
+LC248		tfr u,y				; save timer pointer
+		ldu ,u				; get pointer to timer info
+		beq LC25A			; brif nothing doing for timer
+		dec 2,u				; has this timer record expired?
+		bne LC248			; brif not - check next one
+		bsr LC238			; go process timer record
+		ldb #12				; offset to "ready" list
+		bsr LC21D			; go move event entry to "ready" list
+		bra LC248			; go process next timer record
+LC25A		puls b,x,y,u,pc			; restore registers and return
+LC25C		pshs x				; save registers
+		ldu V2B9			; get open slot for scheduling
+		leax 7,u			; point to next open slot
+		stx V2B9			; save new open slot for scheduling
+		puls x,pc			; restore registers and return
 ; Set the SAM video mode and display offset register to the value in D. Starting at the lsb of
 ; D, the SAM bits are programmed from FFC0 upward. This sets bits 9-0 of the SAM register
 ; to match the value in D.
@@ -719,20 +731,20 @@
 		inca
 		jsr LCA17
 		stx 4,u
-LC2DC		ldu #V2A1
-		jsr LC242
-		ldx #V295
-		ldy #LC324
-LC2E9		inc ,x
-		cmpx #V29A
-		beq LC2FF
-		lda ,x
-		cmpa ,y+
-		blt LC2FF
-		clr ,x+
-		leau 2,u
-		jsr LC242
-		bra LC2E9
+LC2DC		ldu #V2A1			; point to timer lists
+		jsr LC242			; check if any records expired at 60Hz
+		ldx #V295			; point to timer records
+		ldy #LC324			; point to timer max values
+LC2E9		inc ,x				; bump timer value
+		cmpx #V29A			; end of timer record?
+		beq LC2FF			; brif so
+		lda ,x				; fetch new value
+		cmpa ,y+			; has timer maxed out?
+		blt LC2FF			; brif not
+		clr ,x+				; reset timer record
+		leau 2,u			; move to next timer list
+		jsr LC242			; see if any events have expired
+		bra LC2E9			; go handle next timer
 LC2FF		tst nokeyboard			; are we polling the keyboard?
 		bne LC320			; brif not
 		tst waitnewgame			; are we running a demo/waiting for keypress for game start?
@@ -750,7 +762,13 @@
 		bsr writekeybuf			; go process keyboard input
 LC320		lda PIA0+2			; clear interrupt status
 		rti
-LC324		fcb $06,$0a,$3c,$3c,$18
+; These are the rollover points for the timers. Each timer only ticks if the previous
+; timer has rolled over.
+LC324		fcb 6				; tick 10 times per second
+		fcb 10				; tick 1 time per second
+		fcb 60				; tick 1 time per minute
+		fcb 60				; tick 1 time per hour
+		fcb 24				; tick 1 time per day
 readkeybuf	pshs cc,b,x			; save registers and interrupt status
 		orcc #$10			; disable IRQ
 		clra				; flag no key pressed
@@ -1095,81 +1113,83 @@
 		bne LC520			; brif not
 		puls a,b,x,y,u,pc		; restore registers and return
 ; swi 12 routine
-LC529		clr V2C1
-		ldd powerlevel
-		std V2C2
-		lda #6
-LC531		lsl V2C3
-		rol V2C2
-		rol V2C1
-		deca
-		bne LC531
-		clr V2C4
-		ldd damagelevel
-		std V2C5
-		lsl V2C6
-		rol V2C5
-		rol V2C4
-		ldd powerlevel
-		addd V2C5
-		std V2C5
-		ldb V2C4
-		adcb #0
-		stb V2C4
-		clr V2C7
-LC554		ldd V2C2
-		subd V2C5
-		std V2C2
-		lda V2C1
-		sbca V2C4
-		sta V2C1
-		inc V2C7
-		bcc LC554
-		lda V2C7
-		suba #19
-		sta V2AF
-		tst nokeyboard
-		bne LC595
-		cmpa #3
-		bgt LC5AE
-		clearcommand
-		lda effectivelight
-		sta V270
-LC578		dec V26F
+; Check for fainting or recovery from damage and handle the fading out and fading in as a result.
+; Also check for death due to damage level exceeding power level.
+LC529		clr V2C1			; mark high bits of 24 bit accumulator
+		ldd powerlevel			; get current power level
+		std V2C2			; save it in accumulator
+		lda #6				; shift left 6 bits (times 64)
+LC531		lsl V2C3			;* do one left shift
+		rol V2C2			;*
+		rol V2C1			;*
+		deca				; done enough shifts?
+		bne LC531			; brif not
+		clr V2C4			; clear high bits of 24 bit accumulator
+		ldd damagelevel			; get damage level
+		std V2C5			; stow in accumulator
+		lsl V2C6			;* shift left (times 2)
+		rol V2C5			;*
+		rol V2C4			;*
+		ldd powerlevel			; get current power level
+		addd V2C5			; add in half damage level
+		std V2C5			; save low word
+		ldb V2C4			;* propagate carry
+		adcb #0				;*
+		stb V2C4			;*
+		clr V2C7			; clear high bits of 24 bit accumulator
+LC554		ldd V2C2			; get low bits of powerlevel/64
+		subd V2C5			; subtract (powerlevel + damagelevel * 2)
+		std V2C2			; save low word
+		lda V2C1			; fetch msb of powerlevel/64
+		sbca V2C4			; finish subtracting with msb of (powerlevel + damagelevel * 2)
+		sta V2C1			; save it in msb of result
+		inc V2C7			; bump lsb of result
+		bcc LC554			; brif no carry from addition
+		lda V2C7			; get low bits
+		suba #19			; subtract 19
+		sta V2AF			; save number of ticks before redoing the calculation
+		tst nokeyboard			; are we blocking the keyboard?
+		bne LC595			; brif so
+		cmpa #3				; is number of ticks > 3?
+		bgt LC5AE			; brif so
+		clearcommand			; clear the command area
+		lda effectivelight		; fetch the effective light level
+		sta V270			; save it
+LC578		dec V26F			; mark us as passed out
 		jsr [displayptr]		; update the main display area
 		dec pageswap			; set graphics swap required
 		sync				; wait for swap to happen
-		dec effectivelight
-		lda effectivelight
-		cmpa #$f8
-		bgt LC578
-		cleargfx2
+		dec effectivelight		; reduce effective light level
+		lda effectivelight		; fetch new light level
+		cmpa #$f8			; have we reached a minimum?
+		bgt LC578			; brif not
+		cleargfx2			; clear graphics
 		dec pageswap			; set graphics swap required
-		dec nokeyboard
-		clr keybufread			;* reset keyboard buffer
+		dec nokeyboard			; disable keyboard
+		clr keybufread			;* reset keyboard buffer - we passed out so clear any commands
 		clr keybufwrite			;*
-		bra LC5AE
-LC595		cmpa #4
-		ble LC5AE
+		bra LC5AE			; get on with things
+LC595		cmpa #4				; have we recovered enough to wake up?
+		ble LC5AE			; brif not
 LC599		jsr [displayptr]		; update the main display area
 		dec pageswap			; set graphics swap required
 		sync				; wait for swap to happen
-		inc V26F
-		inc effectivelight
-		lda effectivelight
-		cmpa V270
-		ble LC599
-		clr nokeyboard
-		showprompt
-LC5AE		ldx powerlevel
-		cmpx damagelevel
-		blo LC5B5
-		rts
+		inc V26F			; mark as not passed out
+		inc effectivelight		; bump effective light level
+		lda effectivelight		; fetch new light level
+		cmpa V270			; are we at old intensity?
+		ble LC599			; brif not
+		clr nokeyboard			; re-enable keyboard
+		showprompt			; show the prompt
+LC5AE		ldx powerlevel			; get current power level
+		cmpx damagelevel		; is it less than damage level?
+		blo LC5B5			; brif so - we're dead!
+		rts				; returnt o caller
 ; This routine handles player death
-LC5B5		ldx #img_wizard			
+LC5B5		ldx #img_wizard			; point to wizard image
 		dec V29E
-		fadeinclrst
-		renderstrimmp
+		fadeinclrst			; fade in the wizard
+		renderstrimmp			; display "YET ANOTHER DOES NOT RETURN..."
 		fcb $ff,$c1,$92,$d0		; packed "YET ANOTHER DOES NOT RETURN..." string
 		fcb $01,$73,$e8,$82
 		fcb $c8,$04,$79,$66
@@ -1388,17 +1408,17 @@
 		sta 8,u
 LC742		rts				; return to caller
 ; swi 25 routine
-LC743		clearstatus
-		clearcommand
-		dod S0C
+LC743		clearstatus			; clear the status line
+		clearcommand			; clear the command area
+		checkdamage			; update damage information
 		inc V2AE
 		dec V2AD
 		dec V2B1
-		updatestatus
-cmd_look	ldx #LCE66
-		stx displayptr
-		dod S0E
-		rts
+		updatestatus			; update status line to current information
+cmd_look	ldx #LCE66			; standard dungeon view routine
+		stx displayptr			; restore display to standard dungeon view
+		dod S0E				; update display
+		rts				; return to caller
 ; swi 26 routine
 LC759		sta currentlevel		; save current dungeon level
 		ldb #12				; number of entries in creature count table
@@ -2272,7 +2292,7 @@
 LCD60		bsr LCD6D			; go create a door
 		decb				; done yet?
 		bne LCD60			; brif not
-		ldb V297			; get number of times to spin the random number generator
+		ldb V297			; get number of times to spin the random number generator (cycles once/minute)
 LCD67		getrandom			; fetch a random number
 		decb				; have we done enough randoms?
 		bne LCD67			; brif not, do another
@@ -2612,20 +2632,27 @@
 		fcb 0,31,16
 		fcb $80				; marker for end of level 4-5
 		fcb $80				; marker for end of level 5-6
-LD027		ldx creaturecountptr
-		ldb #11
-		clra
-LD02C		adda b,x
-		decb
-		bpl LD02C
-		cmpa #$20
-		bhs LD03D
-		getrandom
-		anda #7
-		adda #2
-		inc a,x
-LD03D		ldd #$0508
-		rts
+; This is the routine that adjusts the creature counts for handling retreats. It is called every
+; five minutes. If there are less than 32 creatures on the current level, it will pick a random
+; creature (club giants through galdrogs) and bump the count that will be spawned the next time
+; the level is entered. This *only* applies to the level currently being played.
+;
+; It's worth noting that this can ONLY affect levels 1, 2, and 3 because there is no way to return
+; to levels 4 (no holes up from 5) which means  level 5 can only be entered once.
+LD027		ldx creaturecountptr		; point to creature counts for this level
+		ldb #11				; maximum creature number
+		clra				; initialize count
+LD02C		adda b,x			; add the number of this creature
+		decb				; at end of creature list?
+		bpl LD02C			; brif not
+		cmpa #32			; do we have the maximum number of creatures yet?
+		bhs LD03D			; brif so
+		getrandom			; get a random value
+		anda #7				; only interested in spawning one of 8 creatures
+		adda #2				; offset above vipers
+		inc a,x				; bump creature count for that type
+LD03D		ldd #$0508			; reschedule for 5 minutes
+		rts				; return to caller
 LD041		ldy 5,u
 		tst creaturefreeze
 		bne LD06A
@@ -2666,7 +2693,7 @@
 		bmi LD099
 		playsoundimm $13
 		jsr LD40C
-LD099		dod S0C
+LD099		checkdamage
 		jmp LD10F
 LD09E		pshs a,b,x
 		beq LD0B0
@@ -2796,73 +2823,79 @@
 LD196		dec V2B5
 LD198		clra
 LD199		puls a,b,x,pc
-LD19B		ldu curtorch
-		beq LD1BC
-		lda 6,u
-		beq LD1BC
-		deca
-		sta 6,u
-		cmpa #5
-		bgt LD1B0
-		ldb #$18
-		stb 9,u
-		clr 11,u
-LD1B0		cmpa 7,u
-		bge LD1B6
-		sta 7,u
-LD1B6		cmpa 8,u
-		bge LD1BC
-		sta 8,u
-LD1BC		dec V2B5
-		ldd #$0108
-		rts
-LD1C2		tst V2B5
-		bne LD1CD
-		ldx #displayscroll
+; This is the routine that ticks down the torch.
+LD19B		ldu curtorch			; get currently burning torch
+		beq LD1BC			; brif no torch in use
+		lda 6,u				; get remaining torch life
+		beq LD1BC			; brif already empty
+		deca				; reduce time remaining
+		sta 6,u				; update object data
+		cmpa #5				; is it 5 minutes left?
+		bgt LD1B0			; brif more
+		ldb #$18			; object type "DEAD TORCH"
+		stb 9,u				; set torch to DEAD TORCH
+		clr 11,u			; mark as fully revealed
+LD1B0		cmpa 7,u			; is time remaining less than physical light strength?
+		bge LD1B6			; brif not
+		sta 7,u				; tick down physical light strength
+LD1B6		cmpa 8,u			; is time remaining less than magical light strength?
+		bge LD1BC			; brif not
+		sta 8,u				; tick down magical light strength
+LD1BC		dec V2B5			; mark update to dungeon required
+		ldd #$0108			; reschedule for one minute
+		rts				; return to caller
+; This is the routine that periodically updates the dungeon display (or scroll). It does not update
+; unless something has marked the display changed OR a scroll is being displayed. It is called twice
+; per second.
+LD1C2		tst V2B5			; check if we need to update dungeon display
+		bne LD1CD			; brif so
+		ldx #displayscroll		; are we displaying a scroll?
 		cmpx displayptr
-		bne LD1D1
-LD1CD		clr V2B5
-		dod S0E
-LD1D1		ldd #$0304
-		rts
-LD1D5		clra
+		bne LD1D1			; brif not
+LD1CD		clr V2B5			; mark update not required
+		dod S0E				; update dungeon display
+LD1D1		ldd #$0304			; reschedule check for 0.5 seconds
+		rts				; return to caller
+
+LD1D5		clra				; set NULL value
 		clrb
-		subd damagelevel
-		jsr LD379
-		addd damagelevel
-		bgt LD1E2
-		clra
+		subd damagelevel		; subtract it from the current damage level
+		jsr LD379			; shift right 6 bits (divide by 64)
+		addd damagelevel		; reduce damage level by 1/64 of original damage level
+		bgt LD1E2			; brif new damage level > 0
+		clra				; minimize damage level at 0
 		clrb
-LD1E2		std damagelevel
-		dod S0C
-		lda V2AF
-		ldb #2
-		rts
-LD1EB		tst waitnewgame
-		bne LD21B
-LD1EF		jsr readkeybuf
-		tsta
-		beq LD248
-		tst nokeyboard
-		bne LD1EF
-		cmpa #$20
-		beq LD215
-		ldb #$1f
-		cmpa #$0d
-		beq LD212
-		ldb #$24
-		cmpa #8
-		beq LD212
-		clrb
-		cmpa #$41
-		blo LD212
-		cmpa #$5a
-		bls LD215
-LD212		tfr b,a
-		skip2
-LD215		anda #$1f
-		bsr LD24C
-		bra LD1EF
+LD1E2		std damagelevel			; save new damage level
+		checkdamage			; check damage level and calculate ticks until next recovery run
+		lda V2AF			; get ticks to reduce damage
+		ldb #2				; requeue in the 60Hz ticker
+		rts				; return to caller
+; This routine handles the keyboard input.
+LD1EB		tst waitnewgame			; are we waiting for a new game?
+		bne LD21B			; brif so
+LD1EF		jsr readkeybuf			; get a key from buffer
+		tsta				; did we get something?
+		beq LD248			; brif not
+		tst nokeyboard			; is keyboard disabled?
+		bne LD1EF			; brif so - keep draining buffer
+		cmpa #$20			; is it a space?
+		beq LD215			; brif so
+		ldb #$1f			; value for CR
+		cmpa #$0d			; is it CR?
+		beq LD212			; brif so
+		ldb #$24			; value for BS
+		cmpa #8				; is it BS?
+		beq LD212			; brif so
+		clrb				; value for nothing (space)
+		cmpa #$41			; is it a letter?
+		blo LD212			; brif below uppercase alpha
+		cmpa #$5a			; is it still a letter?
+		bls LD215			; brif uppercase alpha
+LD212		tfr b,a				; save calculated code
+		skip2				; skip instruction
+LD215		anda #$1f			; normalize down to 0...31
+		bsr LD24C			
+		bra LD1EF			; go handle another character
 LD21B		ldy V20D			; fetch pointer to command sequence
 		ldb ,y+				; do we have a command to do?
 		bpl LD229			; brif so
@@ -2883,58 +2916,57 @@
 		decb				; have we consumed all the words in this command?
 		bne LD229			; brif not - get another
 		lda #$1f			; code for carriage return
-		bsr LD24C
+		bsr LD24C			; add character to buffer and process if needed
 		sty V20D			; save new command stream pointer
-LD248		ldd #$0102
-		rts
-LD24C		pshs a,b,x,y,u
+LD248		ldd #$0102			; reschedule for next tick
+		rts				; return to caller
+LD24C		pshs a,b,x,y,u			; save registers
 		tst V2AD
 		bne LD256
-		dod S19
-		showprompt
-LD256		ldu V211
-		cmpa #$1f
-		beq LD26F
-		cmpa #$24
-		beq LD27D
-		renderchar
-		sta ,u+
-		ldx #LC67C
-		renderstr
-		cmpu #V311
-		bne LD2B4
-LD26F		clra
-		renderchar
-		ldd allones
-		std ,u++
-		ldu #V2F1
-		stu V211
-		bra LD292
-LD27D		cmpu #V2F1
-		beq LD2B4
-		leau -1,u
-		ldx #LD28C
-		renderstr
-		bra LD2B4
-LD28C		fcb $00,$24,$24,$1c
-		fcb $24,$ff
-LD292		ldx #kwlist_cmd
-		jsr LCBEC
-		beq LD2A7
-		bpl LD2A1
-		jsr badcommand
-		bra LD2A7
-LD2A1		lsla
-		ldx #LD9D0
-		jsr [a,x]
-LD2A7		ldu #V2F1
+		dod S19				; clear command area, reset status, and redisplay dungeon
+		showprompt			; show the prompt
+LD256		ldu V211			; get input buffer pointer
+		cmpa #$1f			; end of line?
+		beq LD26F			; brif so
+		cmpa #$24			; BS?
+		beq LD27D			; brif so
+		renderchar			; render the character
+		sta ,u+				; save in buffer
+		ldx #LC67C			; point to cursor string
+		renderstr			; go render the cursor
+		cmpu #V311			; is the buffer full?
+		bne LD2B4			; brif not
+LD26F		clra				; make a space
+		renderchar			; render it
+		ldd allones			; get end of string marker
+		std ,u++			; save in buffer
+		ldu #V2F1			; reset buffer pointer to start of line
+		stu V211			; save new buffer pointer
+		bra LD292			; go process command
+LD27D		cmpu #V2F1			; are we at the start of the line?
+		beq LD2B4			; brif so - BS does nothing
+		leau -1,u			; move buffer pointer back
+		ldx #LD28C			; pointer to SPACE BS BS _ BS
+		renderstr			; display the backspace string
+		bra LD2B4			; get on with things
+LD28C		fcb $00,$24,$24,$1c,$24,$ff	; unpacked SPACE BS BS _ BS string
+LD292		ldx #kwlist_cmd			; point to command list
+		jsr LCBEC			; look up word in command list
+		beq LD2A7			; brif nothing to match
+		bpl LD2A1			; brif found
+		jsr badcommand			; show bad command string
+		bra LD2A7			; go on with new command
+LD2A1		lsla				; two bytes per jump table entry
+		ldx #LD9D0			; point to command jump table
+		jsr [a,x]			; go handle command
+LD2A7		ldu #V2F1			; start of command buffer
 		tst V2AD
 		beq LD2B4
-		tst nokeyboard
-		bne LD2B4
-		showprompt
-LD2B4		stu V211
-		puls a,b,x,y,u,pc
+		tst nokeyboard			; is keyboard disabled?
+		bne LD2B4			; brif so
+		showprompt			; show a new prompt
+LD2B4		stu V211			; save new buffer pointer
+		puls a,b,x,y,u,pc		; restore registers and return
 cmd_attack	jsr LCC31			; get pointer to specified hand
 		ldu ,u				; fetch item in specified hand
 		bne LD2C2			; brif item there
@@ -3024,7 +3056,7 @@
 		std righthand			; mark right hand empty
 		std lefthand			; mark left hand empty
 		dod S19
-LD375		dod S0C
+LD375		checkdamage
 LD377		asra
 		rorb
 LD379		asra
@@ -3272,7 +3304,7 @@
 		sex
 LD56B		addd carryweight
 		std carryweight
-		dod S0C
+		checkdamage
 		bra LD5B7
 LD573		jmp badcommand
 LD576		jmp LCC31
@@ -3470,7 +3502,7 @@
 		addd #3
 		addd damagelevel
 		std damagelevel
-		dod S0C
+		checkdamage
 		dec pageswap			; set graphics swap required
 		sync				; wait for swap to happen
 		rts
@@ -3535,8 +3567,8 @@
 		clr 11,u
 		playsoundimm $0c		; play the flask sound
 		updatestatus			; update status line to reflect changed flask state
-		dod S0C
-		rts
+		checkdamage			; check the damage level and recovery interval
+		rts				; return to caller
 LD7A0		clra				; flag for not showing creatures
 		skip2				; skip over next instruction
 LD7A2		lda #$ff			; flag for do show creatures
@@ -3571,6 +3603,7 @@
 startobj	fcb 17				; wooden sword
 		fcb 15				; pine torch
 		fcb $ff				; end of list
+; This is the list of routines that get scheduling entries by default.
 LD7DC		fdb LD1EB
 		fdb LD1C2
 		fdb LD1D5