mirror of
https://github.com/michaelcmartin/Ophis.git
synced 2024-10-31 14:09:43 +00:00
233 lines
5.6 KiB
Plaintext
233 lines
5.6 KiB
Plaintext
|
.include "../platform/c64_0.oph"
|
||
|
.require "../platform/c64kernal.oph"
|
||
|
.outfile "structuredemo.prg"
|
||
|
|
||
|
jsr print'unsorted
|
||
|
jsr insertion'sort
|
||
|
jsr print'list
|
||
|
rts
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
; Linked list data: head, next, lb, hb.
|
||
|
; lb/hb: Low/high bytes of the data array. These are immutable and
|
||
|
; kept with the program text.
|
||
|
; head: Array index of the first element in the list, or #$FF if the
|
||
|
; list is empty
|
||
|
; next: Array of successor indices. If you've just read element X,
|
||
|
; the value of memory location next+X is the index of the
|
||
|
; next element. If next is #$FF, you've reached the end of
|
||
|
; the list.
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
.data
|
||
|
.org $C000
|
||
|
.space head 1
|
||
|
.space next 16
|
||
|
|
||
|
.text
|
||
|
lb: .byte <$838,<$618,<$205,<$984,<$724,<$301,<$249,<$946
|
||
|
.byte <$925,<$043,<$114,<$697,<$985,<$633,<$312,<$086
|
||
|
hb: .byte >$838,>$618,>$205,>$984,>$724,>$301,>$249,>$946
|
||
|
.byte >$925,>$043,>$114,>$697,>$985,>$633,>$312,>$086
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
; insertion'sort: Sorts the list defined by head, next, hb, lb.
|
||
|
; Arguments: None.
|
||
|
; Modifies: All registers destroyed, head and next array sorted.
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
insertion'sort:
|
||
|
lda #$FF ; Clear list by storing the terminator in 'head'
|
||
|
sta head
|
||
|
ldx #$0 ; Loop through the lb/hb array, adding each
|
||
|
insertion'sort'loop: ; element one at a time
|
||
|
txa
|
||
|
pha
|
||
|
jsr insert_elt
|
||
|
pla
|
||
|
tax
|
||
|
inx
|
||
|
cpx #$10
|
||
|
bne insertion'sort'loop
|
||
|
rts
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
; insert_elt: Insert an element into the linked list. Maintains the
|
||
|
; list in sorted, ascending order. Used by
|
||
|
; insertion'sort.
|
||
|
; Arguments: X register holds the index of the element to add.
|
||
|
; Modifies: All registers destroyed; head and next arrays updated
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
.data
|
||
|
.space lbtoinsert 1
|
||
|
.space hbtoinsert 1
|
||
|
.space indextoinsert 1
|
||
|
|
||
|
.text
|
||
|
|
||
|
insert_elt:
|
||
|
ldy head ; If the list is empty, make
|
||
|
cpy #$FF ; head point at it, and return.
|
||
|
bne insert_elt'list'not'empty
|
||
|
stx head
|
||
|
tya
|
||
|
sta next,x
|
||
|
rts
|
||
|
insert_elt'list'not'empty:
|
||
|
lda lb,x ; Cache the data we're inserting
|
||
|
sta lbtoinsert
|
||
|
lda hb,x
|
||
|
sta hbtoinsert
|
||
|
stx indextoinsert
|
||
|
ldy head ; Compare the first value with
|
||
|
sec ; the data. If the data must
|
||
|
lda lb,y ; be inserted at the front...
|
||
|
sbc lbtoinsert
|
||
|
lda hb,y
|
||
|
sbc hbtoinsert
|
||
|
bmi insert_elt'not'smallest
|
||
|
tya ; Set its next pointer to the
|
||
|
sta next,x ; old head, update the head
|
||
|
stx head ; pointer, and return.
|
||
|
rts
|
||
|
insert_elt'not'smallest:
|
||
|
ldx head
|
||
|
insert_elt'loop: ; At this point, we know that
|
||
|
lda next,x ; argument > data[X].
|
||
|
tay
|
||
|
cpy #$FF ; if next[X] = #$FF, insert arg at end.
|
||
|
beq insert_elt'insert'after'current
|
||
|
lda lb,y ; Otherwise, compare arg to
|
||
|
sec ; data[next[X]]. If we insert
|
||
|
sbc lbtoinsert ; before that...
|
||
|
lda hb,y
|
||
|
sbc hbtoinsert
|
||
|
bmi insert_elt'goto'next
|
||
|
insert_elt'insert'after'current: ; Fix up all the next links
|
||
|
tya
|
||
|
ldy indextoinsert
|
||
|
sta next,y
|
||
|
tya
|
||
|
sta next,x
|
||
|
rts ; and return.
|
||
|
insert_elt'goto'next: ; Otherwise, let X = next[X]
|
||
|
tya ; and go looping again.
|
||
|
tax
|
||
|
jmp insert_elt'loop
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
; print'unsorted: Steps through the data array and prints each value.
|
||
|
; Standalone procedure.
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
print'unsorted:
|
||
|
lda #<unsorted'hdr
|
||
|
ldx #>unsorted'hdr
|
||
|
jsr put'string
|
||
|
ldy #$00
|
||
|
print'unsorted'loop:
|
||
|
lda hb, Y
|
||
|
jsr print'hex
|
||
|
lda lb, y
|
||
|
jsr print'hex
|
||
|
lda #$20
|
||
|
jsr chrout
|
||
|
iny
|
||
|
cpy #$10
|
||
|
bne print'unsorted'loop
|
||
|
lda #$0D
|
||
|
jsr chrout
|
||
|
rts
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
; print'list: Starts at head, and prints out every value in the
|
||
|
; linked list.
|
||
|
; Standalone procedure.
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
print'list:
|
||
|
lda #<sorted'hdr
|
||
|
ldx #>sorted'hdr
|
||
|
jsr put'string
|
||
|
ldy head
|
||
|
print'list'loop:
|
||
|
cpy #$FF
|
||
|
beq print'list'done
|
||
|
lda hb, y
|
||
|
jsr print'hex
|
||
|
lda lb, y
|
||
|
jsr print'hex
|
||
|
lda #$20
|
||
|
jsr chrout
|
||
|
lda next, Y
|
||
|
tay
|
||
|
jmp print'list'loop
|
||
|
print'list'done:
|
||
|
lda #$0d
|
||
|
jsr chrout
|
||
|
rts
|
||
|
|
||
|
;; String data for the above routines.
|
||
|
|
||
|
unsorted'hdr:
|
||
|
.byte 147 ; Clear screen first!
|
||
|
.byte "UNSORTED DATA:",13,0
|
||
|
|
||
|
sorted'hdr:
|
||
|
.byte "SORTED DATA:",13,0
|
||
|
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
; print'hex: outputs a two-character hex representation of a one-
|
||
|
; byte value.
|
||
|
; Arguments: Byte to print in accumulator
|
||
|
; Modifies: .A and .X
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
print'hex:
|
||
|
pha
|
||
|
clc
|
||
|
lsr
|
||
|
lsr
|
||
|
lsr
|
||
|
lsr
|
||
|
tax
|
||
|
lda hexstr,x
|
||
|
jsr chrout
|
||
|
pla
|
||
|
and #$0F
|
||
|
tax
|
||
|
lda hexstr,X
|
||
|
jsr chrout
|
||
|
rts
|
||
|
|
||
|
; Character data array for print'hex.
|
||
|
hexstr: .byte "0123456789ABCDEF"
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
; put'string: outputs a C-style null terminated string with length
|
||
|
; less than 256 to the screen. If 256 bytes are written
|
||
|
; without finding a terminator, the routine ends quietly.
|
||
|
; Arguments: Low byte of string address in .A, high byte in .X
|
||
|
; Modifies: .A and .Y
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
.data zp
|
||
|
.space put'string'addr 2
|
||
|
|
||
|
.text
|
||
|
put'string:
|
||
|
sta put'string'addr
|
||
|
stx put'string'addr+1
|
||
|
ldy #$00
|
||
|
put'string'loop:
|
||
|
lda (put'string'addr),y
|
||
|
beq put'string'done
|
||
|
jsr chrout
|
||
|
iny
|
||
|
bne put'string'loop
|
||
|
put'string'done:
|
||
|
rts
|
||
|
|