Last active
March 4, 2019 21:36
-
-
Save neuro-sys/52204b23c6cd7017d1eba2f8f70bdccc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BDOS EQU &5 | |
C_WRITESTR EQU &9 | |
; Structs and the member sizes | |
edge_status equ 1 ; 0 negative, 1 positive | |
edge_node equ 2 ; pointer to node this edge connects to | |
edge_next equ 2 ; pointer to next edge | |
edge_s_offset equ edge_status + edge_node + edge_next | |
node_name equ 64 ; name | |
node_edges equ 2 ; pointer to edge vector | |
node_next equ 2 ; pointer to next node | |
node_s_offset equ node_name + node_edges + node_next | |
org &100 | |
di ; Disable interrupts | |
call clear_data_area ; Clear data area | |
call initgraph ; Initialize graph with relationships | |
call isstable ; Check if graph is stable | |
ei ; Enable interrupts and return | |
rst 0 ; Return to CCP | |
initgraph: ld hl, input ; Load input list | |
initgraph_l3: call getline ; Read only one line into inputbuffer | |
cp 1 ; Check end of input flag | |
jp nz, initgraph_l4 ; If the end, exit | |
ret | |
initgraph_l4: push hl ; Save new input list pointer | |
ld hl, inputbuffer ; load input address | |
call parseinput ; Parse line into first, second and status | |
ld hl, first ; Load first name | |
push hl | |
call node_findbyname ; Search for first name | |
pop de | |
ld a, l | |
cp h | |
jp nz, initgraph_l1 | |
ex de, hl | |
call node_append | |
initgraph_l1: ex de, hl | |
ld hl, primary | |
ld (hl), e | |
inc hl | |
ld (hl), d ; primary = first | |
ld hl, second | |
push hl | |
call node_findbyname ; Search for second name | |
pop de | |
ld a, l | |
cp h | |
jp nz, initgraph_l2 | |
ex de, hl | |
call node_append | |
initgraph_l2: ex de, hl | |
ld hl, secondary | |
ld (hl), e | |
inc hl | |
ld (hl), d ; secondary = second | |
ld hl, primary | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; | |
ld de, 64 ; edges offset | |
add hl, de ; | |
ex de, hl ; DE = primary node edges | |
ld hl, secondary | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = secondary node | |
ld bc, curstatus | |
ld a, (bc) ; A = status | |
call edge_append | |
ld hl, secondary | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ld de, 64 | |
add hl, de | |
ex de, hl | |
ld hl, primary | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ld bc, curstatus | |
ld a, (bc) | |
call edge_append | |
pop hl ; Restore input address | |
jp initgraph_l3 ; Repeat | |
inputended: ret | |
; no input, using the graph in node_head | |
; determines if the graph is balanced or not | |
; by printing a message to terminal | |
isstable: ld hl, node_head | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl ; HL = *node_head | |
isstable_l2: ex de, hl | |
ld hl, node1 | |
ld (hl), e | |
inc hl | |
ld (hl), d ; node1 = *node_head | |
ex de, hl | |
ld a, l | |
cp h | |
cp 0 | |
jp nz, isstable_l3 ; if node1 == NULL | |
ld de, msg_balanced | |
ld c, C_WRITESTR | |
call BDOS | |
ret ; print and return | |
isstable_l3: call isstable2 | |
cp 1 | |
jp nz, isstable_l4 ; Exit if unbalanced | |
ret | |
isstable_l4: ld hl, node1 | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl ; HL = *node1 | |
ld de, 66 | |
add hl, de ; HL = node1->next | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl | |
jp isstable_l2 | |
; Inner iteration for isstable routine | |
; Returns 1 in A if unbalanced condition is found | |
; Otherwise 0 | |
isstable2: ld hl, node_head | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl ; HL = *node_head | |
isstable2_l2: ex de, hl | |
ld hl, node2 | |
ld (hl), e | |
inc hl | |
ld (hl), d ; node2 = *node_head | |
ex de, hl | |
ld a, l | |
cp h | |
jp nz, isstable2_l3 ; if node2 == NULL | |
xor a | |
ret ; End of iteration, return | |
isstable2_l3: ld hl, node1 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ex de, hl ; DE = *node1 | |
ld hl, node2 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = *node2 | |
call strcmp | |
cp 0 | |
jp z, isstable2_l5 ; If node1->name == node2->name, skip | |
call isstable3 | |
cp 1 | |
jp nz, isstable2_l5 | |
ret | |
isstable2_l5: ld hl, node2 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = *node2 | |
ld de, 66 | |
add hl, de ; HL = node2->next | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl | |
jp isstable2_l2 | |
; second level inner loop of isstable | |
; Print unbalanced if an unbalanced condition is met | |
; And returns 1 in A | |
; Otherwise 0 | |
isstable3: ld hl, node_head | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl ; HL = *node_head | |
isstable3_l2: ex de, hl | |
ld hl, node3 | |
ld (hl), e | |
inc hl | |
ld (hl), d ; node3 = *node_head | |
ex de, hl | |
ld a, l | |
cp h | |
jp nz, isstable3_l3 ; if node3 == NULL, then end of iteration | |
xor a | |
ret | |
isstable3_l3: ld hl, node1 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ex de, hl ; DE = *node1 | |
ld hl, node3 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = *node3 | |
call strcmp | |
cp 0 | |
jp z, isstable3_l4 ; If node1->name == node3->name, skip | |
ld hl, node2 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ex de, hl ; DE = *node2 | |
ld hl, node3 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL *node3 | |
call strcmp | |
cp 0 | |
jp z, isstable3_l4 ; If node2->name == node3->name, skip | |
; Do body | |
call is_all_friends | |
push af | |
call common_enemy | |
pop hl | |
or h ; if is_all_friends || common_enemy | |
jp nz, isstable3_l4 ; continue searching, otherwise | |
ld c, C_WRITESTR | |
ld de, msg_unbalanced | |
call BDOS | |
ld a, 1 ; print message, and return with 1 | |
ret | |
isstable3_l4: ld hl, node3 | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl ; HL = node3 | |
ld de, 66 | |
add hl, de ; HL = node3->next | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl | |
jp isstable3_l2 | |
; A = 1 if node1, node2, node3 are all friends | |
is_all_friends: ld hl, node1 | |
ld e, (hl) | |
inc hl | |
ld d, (hl) ; DE = *node1 | |
ld hl, node2 | |
ld c, (hl) | |
inc hl | |
ld b, (hl) ; BC = *node2 | |
ex de, hl ; HL = *node1 | |
push hl | |
call node_friends ; node1 and node2 | |
pop de | |
cp 0 | |
ret z | |
ld hl, node3 | |
ld c, (hl) | |
inc hl | |
ld b, (hl) ; BC = *node3 | |
ex de, hl ; HL = *node1 | |
push bc | |
call node_friends ; node1 and node3 | |
pop de | |
cp 0 | |
ret z | |
ld hl, node2 | |
ld c, (hl) | |
inc hl | |
ld b, (hl) ; BC = *node2 | |
ex de, hl ; HL = *node3 | |
call node_friends ; node2 and node3 | |
cp 0 | |
ret z | |
ret | |
; A = 1 if among node1, node2, and node3, a pair considers the other an enemy | |
common_enemy: ld hl, node3 | |
ld c, (hl) | |
inc hl | |
ld b, (hl) ; BC = node3 | |
ld hl, node2 | |
ld e, (hl) | |
inc hl | |
ld d, (hl) ; DE = node2 | |
ld hl, node1 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = node1 | |
push hl | |
call node_enemy | |
pop de | |
cp 1 | |
ret z | |
common_enem1: ld hl, node2 | |
ld c, (hl) | |
inc hl | |
ld b, (hl) ; BC = node2, DE = node1 | |
ld hl, node3 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = node3 | |
push de | |
call node_enemy | |
pop bc | |
cp 1 | |
ret z | |
ld hl, node3 | |
ld e, (hl) | |
inc hl | |
ld d, (hl) ; DE = node3, BC = node1 | |
ld hl, node2 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
call node_enemy | |
cp 1 | |
ret z | |
ret | |
; HL = input | |
; inputbuffer will have zero terminated string | |
; HL will have next input pointer after it's advanced | |
; A = 1 if finished | |
getline: ld de, inputbuffer ; Load dest buffer | |
ld a, (hl) ; Check first char | |
cp &13 ; Is it end? | |
jp nz, getline_l1 ; If not, continue | |
ld a, 1 ; otherwise, set end flag, return | |
ret | |
getline_l1: cp 0 | |
jp nz, getline_l2 | |
halt | |
getline_l2: call strcpy | |
ld a, 0 | |
ret | |
; HL = input buffer | |
; first, second, and status fields are set via inputbuffer | |
parseinput: ld a, (hl) ; check cur char | |
cp '+' ; Is it '+'? | |
jp z, hitmarker | |
cp '-' ; Is it '-'? | |
jp z, hitmarker | |
inc hl ; next char | |
jp parseinput ; loop | |
hitmarker: cp '+' ; Is it '+'? | |
ex de, hl ; DE = cur input ptr | |
ld hl, curstatus ; HL = cur status | |
jp nz, hitpositive ; If not positive | |
ld (hl), 1 ; otherwise set cur status as 1 | |
jp markerdone | |
hitpositive: ld (hl), 0 ; if positive, set as 0 | |
markerdone: ex de, hl ; HL = cur input ptr | |
push hl ; Save cur input ptr | |
dec hl ; One before the marker | |
or a | |
ld de, inputbuffer ; Load beginning of input buffer | |
sbc hl, de ; size = cur input ptr - input begin | |
ld c, l | |
ld b, h ; bc = size | |
ex de, hl ; hl = input begin | |
ld de, first ; de = first buffer | |
ldir ; copy | |
ex de, hl ; hl = last char | |
ld (hl), 0 ; put string terminator | |
pop hl ; Restore last cur input ptr | |
inc hl ; skip the second marker | |
inc hl ; skip white space | |
inc hl ; Second name | |
push hl ; Save second name begin | |
parseinput2: ld a, (hl) ; Load char | |
cp 0 ; Is it string terminator? | |
jp z, second_done | |
inc hl ; otherwise, next char | |
jp parseinput2 ; loop | |
second_done: pop de ; Restore second name begin | |
or a | |
sbc hl, de ; cur ptr - begin | |
ld c, l | |
ld b, h ; bc = size | |
ex de, hl ; hl = second name begin | |
ld de, second ; second buffer | |
ldir ; copy | |
ex de, hl ; hl = last char | |
ld (hl), 0 ; put string terminator | |
ret | |
; HL = node1 | |
; DE = node2 | |
; BC = enemy | |
; out A = 1 if BC is a common enemy of node1 and node2 | |
; 0 otherwise | |
node_enemy: push bc | |
push de | |
ld de, 64 ; offset to edges list | |
add hl, de | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ex de, hl ; DE = node1->edges | |
ld hl, edge1 | |
ld (hl), e | |
inc hl | |
ld (hl), d ; edge1 = node1->edges | |
pop hl ; HL = node2 | |
ld de, 64 ; offset to edges list | |
add hl, de | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ex de, hl ; DE = node2->edges | |
ld hl, edge2_begin | |
ld (hl), e | |
inc hl | |
ld (hl), d ; edge2_begin = node2->edges | |
pop de ; DE = enemy | |
ld hl, enemy | |
ld (hl), e | |
inc hl | |
ld (hl), d ; enemy = BC | |
call node_enem1 ; now &edge1, &edge2_begin, enemy set | |
ret | |
; inner loop of node_enemy, works on edge1, edge2 and enemy objects | |
node_enem1: ld hl, edge1 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = *edge1 | |
node_enem1_l3: ld a, l | |
cp h | |
jp nz, node_enem1_l2 ; if *edge1 == NULL | |
xor a ; not found, return | |
ret | |
node_enem1_l2: ld hl, edge2_begin | |
ld e, (hl) | |
inc hl | |
ld d, (hl) ; DE = *edge2_begin | |
ld hl, edge2 | |
ld (hl), e | |
inc hl | |
ld (hl), d ; edge2 = DE | |
call node_enem2 | |
cp 0 | |
jp z, node_enem1_l4 | |
ret | |
node_enem1_l4: ld hl, edge1 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
inc hl | |
inc hl | |
inc hl ; edge next offset | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ex de, hl | |
ld hl, edge1 | |
ld (hl), e | |
inc hl | |
ld (hl), d ; edge1 = &edge1->next | |
ex de, hl | |
jp node_enem1_l3 | |
; second inner loop of node_enemy, works on edge1, edge2 and enemy objects | |
; returns 1 in A if conditions are met, 0 otherwise | |
node_enem2: ld hl, edge2 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = *edge2 | |
node_enem2_l3: ld a, l | |
cp h | |
jp nz, node_enem2_l2 ; if *edge2 == NULL | |
xor a ; not found, return | |
ret | |
node_enem2_l2: ld hl, edge1 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = *edge1 | |
ld a, (hl) ; Load status | |
cp 1 ; Is it a friend of edge1? | |
jp z, node_enem2_l4 ; if yes, then skip | |
ld hl, edge2 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = *edge2 | |
ld a, (hl) ; Load status | |
cp 1 ; Is it a friend of edge2? | |
jp z, node_enem2_l4 ; if yes, then skip | |
ld hl, edge1 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
inc hl ; edge1->node offset | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = *edge1->node | |
push hl | |
ld hl, edge2 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
inc hl ; edge2->node offset | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = edge2->node | |
pop de ; DE = edge1->node | |
push de | |
call strcmp | |
pop de | |
cp 0 | |
jp nz, node_enem2_l4 ; if not shared then skip | |
ld hl, enemy | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = enemy | |
call strcmp | |
cp 0 | |
jp nz, node_enem2_l4 ; if not enemy, then skip | |
ld a, 1 | |
ret | |
node_enem2_l4: ld hl, edge2 | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
inc hl | |
inc hl | |
inc hl ; edge next offset | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
ex de, hl | |
ld hl, edge2 | |
ld (hl), e | |
inc hl | |
ld (hl), d ; edge2 = &edge2->next | |
ex de, hl | |
jp node_enem2_l3 | |
; HL = node1 | |
; BC = node2 | |
; out A = 1 if friends | |
; 0 if not | |
node_friends: ld de, 64 ; edges offset | |
add hl, de ; HL = node1->edges | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl ; HL = *node1->edges | |
nodefri_l2: ld a, l | |
cp h | |
jp nz, nodefri_l3 ; if *node1->edges == NULL | |
ld a, 0 ; no friends found | |
ret | |
nodefri_l3: push hl | |
push bc | |
inc hl ; node offset | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl ; HL = edge->node | |
ld e, c | |
ld d, b ; BC = node2 | |
call strcmp | |
pop bc | |
pop hl | |
jp nz, nodefri_l4 | |
ld a, 1 | |
ret | |
nodefri_l4: inc hl | |
inc hl | |
inc hl ; next offset | |
ld e, (hl) | |
inc hl | |
ld d, (hl) | |
ex de, hl ; edge = edge->next | |
jp nodefri_l2 | |
; HL returns free slot for node | |
; @TODO if implement node_free, `node_cur_free` should be changed | |
; To point to the new free slot | |
node_new: ld hl, node_cur_free ; load next free slot address | |
ld a, (hl) | |
cp 0 ; Is it empty? | |
jp nz, node_new_l2 ; If not zero, find an empty one | |
inc hl | |
ld a, (hl) | |
dec hl | |
cp 0 | |
jp nz, node_new_l2 ; Check hibyte too | |
ld de, node_heap ; Otherwise, initialize node_cur_free | |
ld (hl), e ; with first block in node_heap | |
inc hl | |
ld (hl), d ; *node_cur_free = node_heap | |
ex de, hl ; HL = *node_cur_free | |
ret | |
node_new_l2: inc hl | |
ld h, (hl) | |
ld l, a ; HL = *node_cur_free | |
ld de, node_s_offset ; load the size of node entry | |
node_new_l1: add hl, de ; find next slot | |
ld a, 0 ; Is it empty? | |
cp (hl) | |
jp nz, node_new_l1 ; If not, then keep searching | |
inc hl | |
cp (hl) | |
dec hl | |
jp nz, node_new_l1 ; If not, then keep searching | |
node_new_l3: ex de, hl ; Empty found, DE = empty slot in heap | |
ld hl, node_cur_free | |
ld (hl), e | |
inc hl | |
ld (hl), d ; *node_cur_free = empty slot | |
dec hl | |
ex de, hl ; HL = empty slot | |
ret | |
; HL returns free slot for edge | |
; @TODO if implement edge_free, `edge_cur_free` should be changed | |
; To point to the new free slot | |
edge_new: ld hl, edge_cur_free ; load next free slot address | |
ld a, (hl) | |
cp 0 ; Is it empty? | |
jp nz, edge_new_l2 ; If not zero, find an empty one | |
inc hl | |
ld a, (hl) | |
dec hl | |
cp 0 | |
jp nz, edge_new_l2 ; check hibyte | |
ld de, edge_heap ; Otherwise, initialize edge_cur_free | |
ld (hl), e ; with first block in edge_heap | |
inc hl | |
ld (hl), d ; *edge_cur_free = edge_heap | |
ex de, hl ; HL = *edge_cur_free | |
ret | |
edge_new_l2: inc hl | |
ld h, (hl) | |
ld l, a ; HL = *edge_cur_free | |
ld de, edge_s_offset ; load the size of edge entry | |
edge_new_l1: add hl, de ; find next slot | |
ld a, 0 ; Is it empty? | |
cp (hl) | |
jp nz, edge_new_l1 ; If not, then keep searching | |
inc hl | |
cp (hl) | |
dec hl | |
jp nz, edge_new_l1 ; check hibyte | |
edge_new_l3: ex de, hl ; Empty found, DE = empty slot in heap | |
ld hl, edge_cur_free | |
ld (hl), e | |
inc hl | |
ld (hl), d ; *edge_cur_free = empty slot | |
dec hl | |
ex de, hl ; HL = empty slot | |
ret | |
; in HL = name | |
; out HL = new node address | |
node_append: push hl ; Save name address | |
call node_new | |
ex de, hl ; DE = new node entry | |
pop hl ; HL = name (first entry) | |
push de ; Save node address | |
call strcpy ; Copy name to node.name | |
node_appendl1: ld hl, node_head ; Load node_head pointer to pointer | |
ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = *node_head | |
ld a, 0 | |
cp l ; Is the pointer null? | |
jp nz, node_appendl5 ; Then initialize node_head | |
cp h | |
jp nz, node_appendl5 ; check hibyte | |
ld hl, node_head ; Load node_head pointer to pointer | |
pop de ; DE = node address | |
ld (hl), e | |
inc hl | |
ld (hl), d ; *node_head = node_entry | |
ex de, hl ; HL = node_entry, and return | |
ret | |
; Otherwise, find tail via next ptr | |
node_appendl5: ld de, 66 ; offset to next ptr in struct | |
add hl, de ; Find address of next ptr | |
ld a, (hl) ; Load ptr low byte | |
cp 0 ; Is it null? | |
jp nz, node_appendl4 ; next is null, so it's tail | |
inc hl | |
ld a, (hl) ; check upper byte as well | |
dec hl | |
jp nz, node_appendl4 | |
pop de ; DE = node address | |
ld (hl), e | |
inc hl | |
ld (hl), d ; it->next = node | |
ex de, hl ; Return new node address | |
ret | |
node_appendl4: inc hl | |
ld h, (hl) | |
ld l, a ; HL = next ptr | |
jp node_appendl5 ; keep searching | |
; A = status | |
; HL = node | |
; DE = head edge | |
; out HL = new edge | |
edge_append: push af | |
push hl | |
push de | |
call edge_new | |
ld c, l | |
ld b, h ; BC = new edge | |
pop de ; DE = head | |
pop hl ; HL = node | |
pop af ; A = status | |
ld (bc), a ; Set status on edge | |
inc bc ; edge->node | |
ld a, l | |
ld (bc), a | |
inc bc | |
ld a, h | |
ld (bc), a ; edge->node = node | |
dec bc | |
dec bc ; BC = edge | |
ex de, hl ; HL = head | |
ld a, (hl) | |
cp 0 | |
jp nz, edge_app1 | |
inc hl | |
ld a, (hl) | |
dec hl | |
cp 0 | |
jp nz, edge_app1 ; init head and return | |
ld (hl), c | |
inc hl | |
ld (hl), b ; *head = edge | |
ld l, c | |
ld h, b ; HL = edge | |
ret | |
edge_app1: ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a ; HL = cur edge | |
ld a, l | |
cp h | |
jp nz, edge_app3 ; if not null then continue | |
edge_app2: ld (hl), c | |
inc hl | |
ld (hl), b ; edge->next = edge | |
ld l, c | |
ld h, b ; HL = edge | |
ret | |
edge_app3: inc hl | |
inc hl | |
inc hl ; edge->next | |
ld a, (hl) | |
cp 0 | |
jp nz, edge_app4 | |
inc hl | |
ld a, (hl) | |
dec hl | |
cp 0 | |
jp nz, edge_app4 ; Loop until edge->next is NULL | |
jp edge_app2 ; Found empty next, set it and return | |
edge_app4: ld a, (hl) | |
inc hl | |
ld h, (hl) | |
ld l, a | |
jp edge_app3 | |
; HL = name | |
node_findbyname:ex de, hl | |
ld hl, node_head | |
ld a, (hl) | |
cp 0 | |
jp nz, node_findby1 ; head is not initialized | |
inc hl | |
ld a, (hl) | |
dec hl | |
cp 0 | |
jp nz, node_findby1 ; check hibyte | |
ld hl, 0 | |
ret | |
node_findby1: inc hl | |
ld h, (hl) | |
ld l, a ; HL = first node | |
node_findby3: push hl | |
push de | |
call strcmp ; Compare node->name to searched name | |
pop de | |
pop hl | |
jp nz, node_findby2 | |
ret ; Return cur node | |
node_findby2: ld bc, 66 | |
add hl, bc | |
ld a, (hl) | |
cp 0 | |
jp nz, node_findby4 ; next ptr is NULL | |
ld hl, 0 | |
ret | |
node_findby4: inc hl | |
ld h, (hl) | |
ld l, a ; HL = next node | |
jp node_findby3 | |
; HL = src, null terminated string | |
; DE = dest | |
strcpy: ld a, (hl) | |
ld (de), a | |
or a | |
inc hl | |
inc de | |
jp nz, strcpy | |
ret | |
; HL = src, null terminated string | |
; DE = dest | |
; A = 0 if equal | |
strcmp: | |
ld b, (hl) ; Load source char | |
ld a, (de) ; Load dest char | |
cp b ; compare both chars | |
jp nz, strcmp2 ; If not equal | |
xor a | |
cp b | |
jp z, strcmp3 | |
inc hl ; Next src char | |
inc de ; Next dst char | |
jp strcmp | |
strcmp2: ld a, 1 ; return 1 | |
ret | |
strcmp3: ld a, 0 | |
ret | |
clear_data_area:ld hl, data_area_begin | |
ld bc, data_area_end | |
xor a | |
clear_data_are1:ld (hl), a | |
inc hl | |
or a | |
sbc hl, bc | |
add hl, bc | |
jp nz, clear_data_are1 | |
ret | |
data_area_begin equ $ | |
first: ds 64 ; first name in input line parsed | |
second: ds 64 ; second name | |
curstatus: ds 1 ; 1 if inputline has '++', 0 if '--' | |
primary: ds 2 ; Primary node | |
secondary: ds 2 ; Secondary node | |
edge_heap: ds 128*edge_s_offset; Edge objects heap | |
edge_cur_free: ds 2 ; Points to the next free block | |
node_heap: ds 32*node_s_offset; | |
node_cur_free: ds 2 ; The last free node | |
node_head: ds 2 ; holds node list head | |
node1: ds 2 | |
node2: ds 2 | |
node3: ds 2 | |
edge2_begin: ds 2 ; needed to reset iterator | |
edge1: ds 2 ; used by iterators | |
edge2: ds 2 | |
enemy: ds 2 | |
inputbuffer: ds 256 ; Holds a single inputline | |
data_area_end equ $ | |
input: | |
db "Superman ++ Green Lantern", 0 | |
db "Superman ++ Wonder Woman", 0 | |
db "Superman -- Sinestro", 0 | |
db "Superman -- Cheetah", 0 | |
db "Superman -- Lex Luthor", 0 | |
db "Green Lantern ++ Wonder Woman", 0 | |
db "Green Lantern -- Sinestro", 0 | |
db "Green Lantern -- Cheetah", 0 | |
db "Green Lantern -- Lex Luthor", 0 | |
db "Wonder Woman -- Sinestro", 0 | |
db "Wonder Woman -- Cheetah", 0 | |
db "Wonder Woman -- Lex Luthor", 0 | |
db "Sinestro ++ Cheetah", 0 | |
db "Sinestro ++ Lex Luthor", 0 | |
db "Cheetah ++ Lex Luthor", 0 | |
db &13 | |
msg_balanced: db "balanced", &d, &a, '$' | |
msg_unbalanced: db "unbalanced", &d, &a, '$' | |
ds &100 ; Extra space for disk image |
Author
neuro-sys
commented
Mar 3, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment