A huge thank you to all who rose to the challenge and posted their code here.
In 2021, there was another active venue discussing entries. I cannot find it now.
I found one more minor restructuring to save yet another relative branch.
It turns out that negative indexing is not needed on the 6800 and 6502 because the index register had to be incremented before reading an entry from the table so that the condition code flags are correct. The index register points to the current entry instead of the next as on the 6809.
I tend to believe that these are close to if not the smallest versions of my approach.
The smallest one is for the 6809. It has 44 bytes of code and 33 bytes of data.
Code:
0081 00043 EndOfLine equ $80+1
0080 00044 EndOfImage equ $80
00045
00046 *
00047 * FLEX operating system definitions
00048 *
CD00 00049 OSBase equ $CD00 ; For 6809, $AD00 for 6800
CD03 00050 WARMS equ OSBase+$03 ; Warmstart Entry Point
CD18 00051 PUTCHR equ OSBase+$18 ; Put Character
CD24 00052 PCRLF equ OSBase+$24 ; Print Carriage Return and Line Feed
00053
0000 04 00054 Count fcb 4 ; Repeat three times plus top row
00055
0001 00056 Image
0001 83 01 03 01 00057 fcb EndOfLine+2,1,3,1,3,1
0005 03 01
0007 82 03 01 03 00058 fcb EndOfLine+1,3,1,3,1,3
000B 01 03
000D 81 05 05 05 00059 fcb EndOfLine+0,5,5,5
0011 82 03 01 03 00060 fcb EndOfLine+1,3,1,3,1,3
0015 01 03
0017 83 01 03 01 00061 fcb EndOfLine+2,1,3,1,3,1
001B 03 01
00062
001D 00063 Top
001D 84 05 05 00064 fcb EndOfLine+3,5,5
00065
0020 80 00066 fcb EndOfImage
00067
0021 00068 Start
0021 8E 001D [3] 00069 ldx #Top ; Point to top row
00070
0024 00071 LineLoop
0024 E6 80 [6] 00072 ldb ,X+ ; Get the couplet
0026 2A 0A (0032) [3] 00073 bpl DoCouplet
00074
0028 5A [2] 00075 decb
0029 2A 18 (0043) [3] 00076 bpl EndImage
00077
002B BD CD24 [8] 00078 jsr PCRLF ; Start a new line
00079
002E E6 1F [5] 00080 ldb -1,X ; Recover couplet
00081
0030 C4 7F [2] 00082 andb #$7F ; Isolate space count
00083
0032 00084 DoCouplet
0032 27 08 (003C) [3] 00085 beq NoSpaces
00086
0034 86 20 [2] 00087 lda #' ' ; Emit spaces
00088
0036 00089 SpaceLoop
0036 BD CD18 [8] 00090 jsr PUTCHR
00091
0039 5A [2] 00092 decb
003A 26 FA (0036) [3] 00093 bne SpaceLoop
00094
003C 00095 NoSpaces
003C 86 2A [2] 00096 lda #'*' ; Emit star
00097
003E BD CD18 [8] 00098 jsr PUTCHR
00099
0041 20 E1 (0024) [3] 00100 bra LineLoop
00101
0043 00102 EndImage
0043 8E 0001 [3] 00103 ldx #Image ; Point back to start of the image
00104
0046 0A 00 [6] 00105 dec Count ; Do it again?
0048 26 DA (0024) [3] 00106 bne LineLoop
00107
004A 7E CD03 [4] 00108 jmp WARMS ; Back to FLEX
Then comes the version for the 6800. It has 46 bytes of code and 33 bytes of data.
Code:
0081 00043 EndOfLine equ $80+1
0080 00044 EndOfImage equ $80
00045
00046 *
00047 * FLEX operating system definitions
00048 *
AD00 00049 OSBase equ $AD00 ; For 6800, $CD00 for 6809
AD03 00050 WARMS equ OSBase+$03 ; Warmstart Entry Point
AD18 00051 PUTCHR equ OSBase+$18 ; Put Character
AD24 00052 PCRLF equ OSBase+$24 ; Print Carriage Return and Line Feed
00053
0000 04 00054 Count fcb 4 ; Repeat three times plus top row
00055
0001 00056 Image
0001 83 01 03 01 00057 fcb EndOfLine+2,1,3,1,3,1
0005 03 01
0007 82 03 01 03 00058 fcb EndOfLine+1,3,1,3,1,3
000B 01 03
000D 81 05 05 05 00059 fcb EndOfLine+0,5,5,5
0011 82 03 01 03 00060 fcb EndOfLine+1,3,1,3,1,3
0015 01 03
0017 83 01 03 01 00061 fcb EndOfLine+2,1,3,1,3,1
001B 03 01
00062
001D 00063 Top
001D 84 05 05 00064 fcb EndOfLine+3,5,5
00065
0020 80 00066 fcb EndOfImage
00067
0021 00068 Start
0021 CE 001C [3] 00069 ldx #Top-1 ; Point to before the top row
00070
0024 00071 LineLoop
0024 08 [4] 00072 inx ; Point to the next couplet
0025 E6 00 [5] 00073 ldab 0,X ; Get the couplet
0027 2A 0A (0033) [4] 00074 bpl DoCouplet
00075
0029 5A [2] 00076 decb
002A 2A 18 (0044) [4] 00077 bpl EndImage
00078
002C BD AD24 [9] 00079 jsr PCRLF ; Start a new line
00080
002F E6 00 [5] 00081 ldab 0,X ; Recover the couplet
00082
0031 C4 7F [2] 00083 andb #$7F ; Isolate space count
00084
0033 00085 DoCouplet
0033 27 08 (003D) [4] 00086 beq NoSpaces
00087
0035 86 20 [2] 00088 ldaa #' ' ; Emit spaces
00089
0037 00090 SpaceLoop
0037 BD AD18 [9] 00091 jsr PUTCHR
00092
003A 5A [2] 00093 decb
003B 26 FA (0037) [4] 00094 bne SpaceLoop
00095
003D 00096 NoSpaces
003D 86 2A [2] 00097 ldaa #'*' ; Emit star
00098
003F BD AD18 [9] 00099 jsr PUTCHR
00100
0042 20 E0 (0024) [4] 00101 bra LineLoop
00102
0044 00103 EndImage
0044 CE 0000 [3] 00104 ldx #Image-1 ; Point to before start of the image
00105
0047 7A 0000 [6] 00106 dec Count ; Do it again?
004A 26 D8 (0024) [4] 00107 bne LineLoop
00108
004C 7E AD03 [3] 00109 jmp WARMS ; Back to FLEX
The 6502 version also managed to benefited from the latest transformations. It has 48 bytes of code and 33 bytes of data.
Code:
0081 00043 EndOfLine equ $80+1
0080 00044 EndOfImage equ $80
00045
00046 *
00047 * FLEX operating system definitions
00048 *
1000 00049 DOSBase equ $1000
1003 00050 WARMS equ DOSBase+$03 ; Warmstart Entry Point
1018 00051 PUTCHR equ DOSBase+$18 ; Put Character
1024 00052 PCRLF equ DOSBase+$24 ; Print Carriage Return and Line Feed
00053
0000 04 00054 Count fcb 4 ; Repeat three times plus top row
00055
0001 00056 Image:
0001 83 01 03 01 03 01 00057 fcb EndOfLine+2,1,3,1,3,1
0007 82 03 01 03 01 03 00058 fcb EndOfLine+1,3,1,3,1,3
000D 81 05 05 05 00059 fcb EndOfLine+0,5,5,5
0011 82 03 01 03 01 03 00060 fcb EndOfLine+1,3,1,3,1,3
0017 83 01 03 01 03 01 00061 fcb EndOfLine+2,1,3,1,3,1
00062
001D 00063 Top
001D 84 05 05 00064 fcb EndOfLine+3,5,5
00065
0020 80 00066 fcb EndOfImage
00067
0021 00068 Start:
0021 20 1024 [6] 00069 jsr PCRLF ; FLEX does not do CRLF from prompt
00070
0024 A2 1C [2] 00071 ldx #Top-1 ; Point to before the top row
00072
0026 00073 LineLoop:
0026 E8 [2] 00074 inx ; Point to the next couplet
0027 B4 00 [4] 00075 ldy 0,X ; Get the couplet
0029 10 0B (0036) [2/3] 00076 bpl DoCouplet
00077
002B 88 [2] 00078 dey
002C 10 1A (0048) [2/3] 00079 bpl EndImage
00080
002E 20 1024 [6] 00081 jsr PCRLF ; Start a new line
00082
0031 B5 00 [4] 00083 lda 0,X ; Recover the couplet
0033 29 7F [2] 00084 and #$7F
0035 A8 [2] 00085 tay
00086
0036 00087 DoCouplet:
0036 F0 08 (0040) [2/3] 00088 beq NoSpaces
00089
0038 A9 20 [2] 00090 lda #' ' ; Emit spaces
00091
003A 00092 SpaceLoop:
003A 20 1018 [6] 00093 jsr PUTCHR
00094
003D 88 [2] 00095 dey
003E D0 FA (003A) [2/3] 00096 bne SpaceLoop
00097
0040 00098 NoSpaces:
0040 A9 2A [2] 00099 lda #'*' ; Emit star
00100
0042 20 1018 [6] 00101 jsr PUTCHR
00102
0045 4C 0026 [3] 00103 jmp LineLoop
00104
0048 00105 EndImage:
0048 A2 00 [2] 00106 ldx #Image-1 ; Point to before the image
00107
004A C6 00 [5] 00108 dec Count ; Do it again?
004C D0 D8 (0026) [2/3] 00109 bne LineLoop
00110
004E 4C 1003 [3] 00111 jmp WARMS ; Back to FLEX
The version for the 8080 benefited as well. It has 66 bytes of code and 32 bytes of data. I used an old trick to return to the CCP instead of making a CP/M system call to exit. If I rewrite it for the Z80, use of relative branches save another four bytes of code.
Code:
0081 00043 EndLine equ 80h+1
0080 00044 EndOfImage equ 80h
00045
0005 00046 BDOS equ 5
00047
0100 00048 org 100h
00049
0100 00050 Start:
0100 0E 04 [7] 00051 mvi C,4 ; Repeat three times plus the top row
00052
0102 21 015E [10] 00053 lxi H,Top ; Point to the top line
00054
0105 00055 LineLoop:
0105 7E [7] 00056 mov A,M ; Get the couplet
0106 23 [5] 00057 inx H ; Point to the next couplet
0107 B7 [4] 00058 ora A
0108 F2 0114 [10] 00059 jp DoCouplet
00060
010B 3D [5] 00061 dcr A
010C F2 0128 [10] 00062 jp EndImage
00063
010F CD 012F [17] 00064 call PCRLF ; Start a new line
00065
0112 E6 7F [7] 00066 ani 7Fh ; Isolate space count
00067
0114 00068 DoCouplet:
0114 CA 0120 [10] 00069 jz NoSpaces
00070
0117 1E 20 [7] 00071 mvi E,' ' ; Emit spaces
00072
0119 00073 SpaceLoop:
0119 CD 0136 [17] 00074 call PUTCHR
00075
011C 3D [5] 00076 dcr A
011D C2 0119 [10] 00077 jnz SpaceLoop
00078
0120 00079 NoSpaces:
0120 1E 2A [7] 00080 mvi E,'*' ; Emit star
00081
0122 CD 0136 [17] 00082 call PUTCHR
00083
0125 C3 0105 [10] 00084 jmp LineLoop
00085
0128 00086 EndImage:
0128 21 0142 [10] 00087 lxi H,Image ; Point to the image
00088
012B 0D [5] 00089 dcr C ; Do it again?
012C C2 0105 [10] 00090 jnz LineLoop
00091
00092 ; Fall through to PCRLF which 'returns' to the CCP
00093
012F 00094 PCRLF:
012F 1E 0D [7] 00095 mvi E,0Dh ; Print CR
0131 CD 0136 [17] 00096 call PUTCHR
00097
0134 1E 0A [7] 00098 mvi E,0Ah ; Now LF
00099
0136 00100 PUTCHR:
0136 F5 [11] 00101 push PSW
0137 C5 [11] 00102 push B
0138 E5 [11] 00103 push H
00104
0139 0E 02 [7] 00105 mvi C,2
013B CD 0005 [17] 00106 call BDOS
00107
013E E1 [10] 00108 pop H
013F C1 [10] 00109 pop B
0140 F1 [10] 00110 pop PSW
00111
0141 C9 [10] 00112 ret
00113
0142 00114 Image:
0142 83 01 03 01 03 01 00115 db EndLine+2,1,3,1,3,1
0148 82 03 01 03 01 03 00116 db EndLine+1,3,1,3,1,3
014E 81 05 05 05 00117 db EndLine+0,5,5,5
0152 82 03 01 03 01 03 00118 db EndLine+1,3,1,3,1,3
0158 83 01 03 01 03 01 00119 db EndLine+2,1,3,1,3,1
00120
015E 00121 Top:
015E 84 05 05 00122 db EndLine+3,5,5
00123
0161 80 00124 db EndOfImage