org $4000 ; ; Print control codes cDel equ $08 ; cCret equ $0D ; cCls equ $0C ; cClr equ $1B ; cHome equ $0E ; ; Print colour select characters cBlack equ $00 ; cBlue equ $01 ; cRed equ $02 ; cMagenta equ $03 ; cGreen equ $04 ; cCyan equ $05 ; cYellow equ $06 ; cWhite equ $07 ; zeusemulate "48K" output_szx "linked.szx",0,Start ; Generate code to test org $8000 ; Somewhere safe ; Select which example we want to assemble (the option will appear after you assemble this file on the Options tab ; Select the options tab (up there ^ between the "Zeus(assembler)" and the "Zeus Code" tabs. ; Then select the version you want from the drop-down list and reassemble to build that option. ; optionsize 0 ; Comment this line out to put the option on the "Options" tab optWhichExample optionlist 10,50,"Which example?","Forwards link","Backwards multiple","Backwards single" ; Use a switch statement to select the appropriate example code switch optWhichExample case 0 ; Example for forwards linked lists zeusprint "Generating multiple forward linked lists..." Start di ; Make sure we're not interrupted ld sp,0 ; Set the stack to the top of memory ld a,cCls ; Clear the screen call Print ; ld a,cBlue ; Show the first in blue call Print ; ld hl,StartLink1 ; Point at the first entry in linked list1 call PrintStringsInList ; And print the strings in the list ld a,cCret ; Line-feed call Print ; ld a,cCyan ; Show the second in cyan call Print ; ld hl,StartLink2 ; Point at the first entry in linked list1 call PrintStringsInList ; And print the strings in the list Stop jr Stop ; Done ; A macro to overwrite words in memory at a given address mPokeWord macro(addr,data) ; Write a word into memory at a given address This equ * ; Remember where we are now org addr ; Move to the address dw data ; Write the word org This ; Move back to where we were mend ; Done ; A macro to plant the link as a word mPlantForwardsLink macro(first,last) ; This equ * ; Where this pointer is in memory ; Now, if the global last pointer is not zero, we need to point it at us. if ::last <> 0 mPokeWord(last,This) ; Link the old one to us else ::first = This ; This is the first entry, remember where we are. endif dw 0 ; Assume this is the last and plant a zero ::last = This ; Point at our link mend ; ; Plant a linked list of strings. The first ones will be first in the lists. mPlantForwardsLink(StartLink1,LastLink1) ; Plant Link and store db "Hello ",0 mPlantForwardsLink(StartLink1,LastLink1) ; Plant Link and store db "there",0 ; And another list mPlantForwardsLink(StartLink2,LastLink2) ; Plant Link and store db "This ",0 mPlantForwardsLink(StartLink2,LastLink2) ; Plant Link and store db "is ",0 mPlantForwardsLink(StartLink2,LastLink2) ; Plant Link and store db "list ",0 mPlantForwardsLink(StartLink2,LastLink2) ; Plant Link and store db "2",0 endcase case 1 ; Example for a mutiple backwards linked lists zeusprint "Generating more than one backwards linked lists..." Start di ; Make sure we're not interrupted ld sp,0 ; Set the stack to the top of memory ld a,cCls ; Clear the screen call Print ; ld a,cBlue ; Show the first in blue call Print ; ld hl,Link1 ; Point at the first entry in linked list1 call PrintStringsInList ; And print the strings in the list ld a,cCret ; Line-feed call Print ; ld a,cCyan ; Show the second in cyan call Print ; ld hl,Link2 ; Point at the first entry in linked list1 call PrintStringsInList ; And print the strings in the list Stop jr Stop ; Done Link1 = 0 ; This declares Link1 as a variable and inits it to 0 Link2 = 0 ; This declares Link2 as a variable and inits it to 0 ; A macro to plant the link as a word mPlantForwardLink macro(ptr) ; This dw ::ptr ; Store the (global) link pointer value ::ptr = This ; And update it to point at this instance mend ; Note! MUST have "::" in front of it to update the global variable! ; Plant two linked lists of strings. The last ones will be first in the lists. mPlantForwardLink(Link1) ; Plant Link and store db "backwards!",0 mPlantForwardLink(Link2) ; Plant Link and store db "backwards!",0 ; You can interleave the lists or not, they're independent mPlantForwardLink(Link1) db "it is ",0 mPlantForwardLink(Link2) db "it is ",0 mPlantForwardLink(Link1) db "well ",0 mPlantForwardLink(Link2) db "well ",0 mPlantForwardLink(Link1) db "List 1: ",0 mPlantForwardLink(Link2) db "List 2: ",0 endcase case 2 ; Example for a mutiple single linked list zeusprint "Generating a single backwards linked list..." Start di ; Make sure we're not interrupted ld sp,0 ; Set the stack to the top of memory ld a,cCls ; Clear the screen call Print ; ld a,cWhite ; Show in white call Print ; ld hl,Link ; Point at the first entry in the list call PrintStringsInList ; And print the strings in the list Stop jr Stop ; Done Link = 0 ; This declares Link as a variable and inits it to 0 ; A macro to plant the link as a word mPlantForwardLink macro() ; This dw ::Link ; Store the (global) link pointer value ::Link = This ; And update it to point at this instance mend ; Note! MUST have "::" in front of it to update the global variable! ; Plant a linked list of strings. The last one will be first in the list. mPlantForwardLink() ; Plant Link and store db "last...",cCret,0 mPlantForwardLink() db "third ",0 mPlantForwardLink() db "second ",0 mPlantForwardLink() db "First ",0 endcase endswitch ; Below here is just the print routine code. ; Follow a linked list of strings (pointed at by HL) and print the strings in each list entry PrintStringsInList proc ; ; Is HL zero? NextString ld a,l ; Do we have a string? or h ; ret z ; We are done if it is ld e,(hl) ; Get the pointer to the next entry inc hl ; ld d,(hl) ; inc hl ; push de ; Save the pointer call PrintStr ; Print the string we're now pointing at pop hl ; Restore the pointer to the next jr NextString ; And loop pend ; ; Print the zero-terminated string pointed to by HL PrintStr proc ; push hl,af ; Loop ld a,(hl) ; inc hl ; or a ; jr z,Exit ; call Print ; jr Loop ; Exit pop af,hl ; retp ; (RET) ; Print the string following the call in memory PrintStrFollow proc ; ex (sp),hl ; push af ; Loop ld a,(hl) ; inc hl ; or a ; jr z,Exit ; call Print ; jr Loop ; Exit pop af ; ex (sp),hl ; retp ; (RET) ; Print the contents of HL in hex PrintHex_HL ld a,h ; call PrintHex_A ; ld a,l ; ; Print the contents of A in hex PrintHex_A call PH2 ; PH2 rrca ; rrca ; rrca ; rrca ; push af ; and $0F ; add a,"0" ; cp "9"+1 ; jr c,PH3 ; add a,"A"-("9"+1) ; PH3 call Print ; pop af ; ret ; ; Print a space Print_Sp push af ; Save ld a,' ' ; Print a space call Print ; pop af ; Done ret ; ; A print character routine. Proportionally spaced characters Print push ix,hl,de,bc,af ; Save them cp cWhite+1 ; jr c,PrintColour ; cp cCls ; jr z,PrintCls ; cp cCret ; jr z,PrintCret ; cp cHome ; jr z,PrintHome ; ld h,PrintWidths/256 ; ld l,a ; ld a,(pCurX) ; add a,(hl) ; call c,PrintCret ; call PrintOutChar ; ld a,(pCurX) ; add a,(hl) ; ld (pCurX),a ; PrintExit pop af,bc,de,hl,ix ; ret ; ; Set a colour PrintColour cp 4 ; Above green don't make them bright jr nc,PrintCol1 ; or $40 ; Bright PrintCol1 ld (CurCol),a ; jr PrintExit ; ; Carriage return PrintCret call PrintDoCret ; jr PrintExit ; ; Clear screen - this clears it slowly with a fade effect PrintCls ld e,$00 ; ld hl,$5800 ; ld bc,$02FF ; pC1 ld a,(hl) ; and $07 ; jr z,pC2 ; set 0,e ; dec (hl) ; pC2 cpi ; jp pe,pC1 ; call Delay ; bit 0,e ; jr nz,PrintCls ; ld hl,$4000 ; ld de,$4001 ; ld bc,$1800 ; xor a ; ld (hl),a ; ldir ; ld a,(CurCol) ; ld (hl),a ; ld bc,$02FF ; ldir ; xor a ; out ($FE),a ; PrintHome xor a ; ld (pCurX),a ; ld (ppCurY),a ; ld a,cWhite ; ld (CurCol),a ; ld hl,$4000 ; ld (pCurY),hl ; jr PrintExit ; ; A suitable delay for the fade Delay push bc ; ld bc,1000 ; Del1 cpi ; dec hl ; jp pe,Del1 ; pop bc ; ret ; ; Do the carriage return PrintDoCret ld a,(ppCurY) ; inc a ; PrintSetUpY ld (ppCurY),a ; and $1F ; push hl ; ld l,a ; ld h,$00 ; add hl,hl ; ld de,YTable ; add hl,de ; ld a,(hl) ; inc hl ; ld h,(hl) ; ld l,a ; ld (pCurY),hl ; xor a ; ld (pCurX),a ; pop hl ; ret ; ; Output the character PrintOutChar bit 7,l ; characters $00..$7F only ret nz ; push hl ; ld h,0 ; add hl,hl ; add hl,hl ; add hl,hl ; ld de,PrintChars-256 ; add hl,de ; push hl ; pop ix ; ld a,(pCurX) ; rrca ; rrca ; rrca ; and $1F ; ld de,(pCurY) ; or e ; ld e,a ; push de ; ld a,d ; rrca ; rrca ; rrca ; and $03 ; or $58 ; ld d,a ; ld a,(CurCol) ; ld (de),a ; inc de ; ld (de),a ; pop de ; ld a,(pCurX) ; and $07 ; ld c,a ; ld b,$08 ; OutCharL ld h,(ix) ; ld l,$00 ; ld a,c ; or a ; jr z,OCL1 ; OCL2 srl h ; rr l ; dec a ; jr nz,OCL2 ; OCL1 ld a,(de) ; xor h ; ld (de),a ; inc e ; ld a,(de) ; xor l ; ld (de),a ; dec e ; inc ix ; inc d ; djnz OutCharL ; pop hl ; ret ; ; Screen addresses for the character rows YTable defw $4000,$4020,$4040,$4060 ; defw $4080,$40A0,$40C0,$40E0 ; defw $4800,$4820,$4840,$4860 ; defw $4880,$48A0,$48C0,$48E0 ; defw $5000,$5020,$5040,$5060 ; defw $5080,$50A0,$50C0,$50E0 ; defw 0,0,0,0,0,0,0,0 ; So running off the end isn't fatal ; Declare the macros NegHL_A macro() ; No parameters supported (yet) ld a,l ; Code to negate HL cpl ; ld l,a ; ld a,h ; cpl ; ld h,a ; inc hl ; mend ; Macro end InvL_A macro() ; No parameters supported (yet) ld a,l ; Code to invert L cpl ; ld l,a ; mend ; Macro end InvH_A macro() ; No parameters supported (yet) ld a,h ; Code to invert H cpl ; ld h,a ; mend ; Macro end ; This macro includes other macros NestedNegHL_A macro() ; No parameters supported (yet) InvL_A() ; Invert L InvH_A() ; Invert H inc hl ; +1 mend ; Macro end ; Character set graphics align 256 ; Put these on page boundaries PrintChars defb $00,$00,$00,$00,$00,$00,$00,$00 defb $80,$80,$80,$80,$80,$00,$80,$00 defb $A0,$A0,$A0,$00,$00,$00,$00,$00 defb $50,$50,$F8,$50,$F8,$50,$50,$00 defb $20,$78,$A0,$70,$28,$F0,$20,$00 defb $C0,$C8,$10,$20,$40,$98,$18,$00 defb $40,$A0,$A0,$40,$A8,$90,$68,$00 defb $80,$80,$80,$00,$00,$00,$00,$00 defb $20,$40,$80,$80,$80,$40,$20,$00 defb $80,$40,$20,$20,$20,$40,$80,$00 defb $20,$A8,$70,$20,$70,$A8,$20,$00 defb $00,$20,$20,$F8,$20,$20,$00,$00 defb $00,$00,$00,$00,$40,$40,$80,$00 defb $00,$00,$00,$F8,$00,$00,$00,$00 defb $00,$00,$00,$00,$00,$00,$80,$00 defb $00,$08,$10,$20,$40,$80,$00,$00 defb $70,$88,$98,$A8,$C8,$88,$70,$00 defb $20,$60,$20,$20,$20,$20,$70,$00 defb $70,$88,$08,$30,$40,$80,$F8,$00 defb $F8,$08,$10,$30,$08,$88,$70,$00 defb $10,$30,$50,$90,$F8,$10,$10,$00 defb $F8,$80,$F0,$08,$08,$88,$70,$00 defb $38,$40,$80,$F0,$88,$88,$70,$00 defb $F8,$08,$10,$20,$40,$40,$40,$00 defb $70,$88,$88,$70,$88,$88,$70,$00 defb $70,$88,$88,$78,$08,$10,$E0,$00 defb $00,$00,$80,$00,$80,$00,$00,$00 defb $00,$00,$40,$00,$40,$40,$80,$00 defb $10,$20,$40,$80,$40,$20,$10,$00 defb $00,$00,$F8,$00,$F8,$00,$00,$00 defb $80,$40,$20,$10,$20,$40,$80,$00 defb $70,$88,$10,$20,$20,$00,$20,$00 defb $70,$88,$A8,$B8,$B0,$80,$78,$00 defb $20,$50,$88,$88,$F8,$88,$88,$00 defb $F0,$88,$88,$F0,$88,$88,$F0,$00 defb $70,$88,$80,$80,$80,$88,$70,$00 defb $F0,$88,$88,$88,$88,$88,$F0,$00 defb $F8,$80,$80,$F0,$80,$80,$F8,$00 defb $F8,$80,$80,$F0,$80,$80,$80,$00 defb $78,$80,$80,$80,$98,$88,$78,$00 defb $88,$88,$88,$F8,$88,$88,$88,$00 defb $E0,$40,$40,$40,$40,$40,$E0,$00 defb $08,$08,$08,$08,$08,$88,$70,$00 defb $88,$90,$A0,$C0,$A0,$90,$88,$00 defb $80,$80,$80,$80,$80,$80,$F8,$00 defb $88,$D8,$A8,$A8,$88,$88,$88,$00 defb $88,$88,$C8,$A8,$98,$88,$88,$00 defb $70,$88,$88,$88,$88,$88,$70,$00 defb $F0,$88,$88,$F0,$80,$80,$80,$00 defb $70,$88,$88,$88,$A8,$90,$68,$00 defb $F0,$88,$88,$F0,$A0,$90,$88,$00 defb $70,$88,$80,$70,$08,$88,$70,$00 defb $F8,$20,$20,$20,$20,$20,$20,$00 defb $88,$88,$88,$88,$88,$88,$70,$00 defb $88,$88,$88,$88,$88,$50,$20,$00 defb $88,$88,$88,$A8,$A8,$D8,$88,$00 defb $88,$88,$50,$20,$50,$88,$88,$00 defb $88,$88,$50,$20,$20,$20,$20,$00 defb $F8,$08,$10,$20,$40,$80,$F8,$00 defb $F8,$C0,$C0,$C0,$C0,$C0,$F8,$00 defb $00,$80,$40,$20,$10,$08,$00,$00 defb $F8,$18,$18,$18,$18,$18,$F8,$00 defb $20,$70,$A8,$20,$20,$20,$00,$00 defb $00,$00,$00,$00,$00,$00,$F8,$00 defb $00,$00,$00,$00,$00,$00,$00,$00 defb $00,$00,$68,$98,$88,$98,$68,$00 defb $80,$80,$B0,$C8,$88,$C8,$B0,$00 defb $00,$00,$78,$80,$80,$80,$78,$00 defb $08,$08,$68,$98,$88,$98,$68,$00 defb $00,$00,$70,$88,$F8,$80,$70,$00 defb $20,$40,$40,$E0,$40,$40,$40,$00 defb $00,$00,$78,$88,$98,$68,$08,$70 defb $80,$80,$F0,$88,$88,$88,$88,$00 defb $80,$00,$80,$80,$80,$80,$80,$00 defb $00,$20,$00,$20,$20,$20,$20,$C0 defb $80,$80,$90,$A0,$E0,$90,$88,$00 defb $C0,$40,$40,$40,$40,$40,$E0,$00 defb $00,$00,$D0,$A8,$A8,$A8,$A8,$00 defb $00,$00,$F0,$88,$88,$88,$88,$00 defb $00,$00,$70,$88,$88,$88,$70,$00 defb $00,$00,$F0,$88,$88,$F0,$80,$80 defb $00,$00,$78,$88,$88,$78,$08,$08 defb $00,$00,$B0,$C0,$80,$80,$80,$00 defb $00,$00,$78,$80,$70,$08,$F0,$00 defb $00,$20,$F8,$20,$20,$20,$18,$00 defb $00,$00,$88,$88,$88,$88,$78,$00 defb $00,$00,$88,$88,$50,$50,$20,$00 defb $00,$00,$88,$88,$88,$A8,$50,$00 defb $00,$00,$88,$50,$20,$50,$88,$00 defb $00,$00,$90,$90,$90,$F0,$10,$E0 defb $00,$00,$F8,$10,$20,$40,$F8,$00 defb $30,$40,$40,$80,$40,$40,$30,$00 defb $00,$80,$80,$00,$00,$80,$80,$00 defb $C0,$20,$20,$10,$20,$20,$C0,$00 defb $50,$00,$70,$88,$F8,$80,$70,$00 defb $00,$00,$08,$70,$80,$00,$00,$00 ; Character widths PrintWidths defb $07,$09,$09,$09,$09,$09,$09,$03 defb $05,$05,$05,$05,$03,$05,$05,$05 defb $05,$03,$05,$05,$05,$05,$09,$09 ; " " .. defb $07,$09,$07,$02,$05,$09,$07,$09 defb $06,$02,$04,$06,$06,$06,$06,$02 defb $04,$04,$06,$06,$03,$06,$02,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$02,$03,$05,$06,$05,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$04,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$04,$06 defb $06,$02,$04,$06,$04,$06,$06,$06 defb $06,$06,$05,$06,$06,$06,$06,$06 defb $06,$05,$06,$05,$02,$05,$06,$06 defb $03,$06,$0C,$12,$18,$1E,$24,$2A ; Wide spaces $80..? defb $30,$36,$3C,$42,$48,$06,$06,$06 defb $01,$02,$03,$04,$05,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 defb $06,$06,$06,$06,$06,$06,$06,$06 ; Variables pCurX db 0 ; A logical X position ppCurY db 0 ; A logical Y position pCurY dw 0 ; The actual address CurCol db 0 ; The cursor colour