6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 12:33 pm

All times are UTC




Post new topic Reply to topic  [ 48 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
PostPosted: Tue Dec 26, 2023 5:58 pm 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
dmsc wrote:
Hi!

I also used a table, but "compressed" it to 5 bytes, of which 3 bytes also are the last bytes of the code :-P

This is for the Atari XL / XE 8-bit computers, calling the put-char ROM routine and directly writing to the screen, 31 bytes total.
Code:
   org   256-E+S
S  ldy   #1
C  lda   #10
   ldx   T,y
   stx   T+6,y
R  cpx   T+4
   bne   K
   sta   (94),y
K  iny
   cpy   #20
   bne   C
   lda   #$9B
   jsr   $F2B0
T  inc   R+1
   bne   S
   rts
   .byte $FC-T+S,$D0
E  =  *+16


For the C64, the code is about 5 bytes shorter.

Have Fun!


I see some problems with assembling this.

First, the org cannot be defined since E is not defined. And E cannot be defined since it uses the *, which indicates a present location, but since org has not been defined yet without the E, the * cannot have a memory address, which means E cannot be defined. I don't get this.
Second, I don't see how $94.95 gets set up with the screen address. That takes up 8 bytes to set up.
Third, some remarks would be nice to indicate what the #10 and #$9B actually print out on the screen. Those are not normal ascii chars and therefore must be special chars. If they are special, then all computers usually have to switch that character set in. Again, don't see that in the code.

Please explain.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 26, 2023 8:50 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
If you look at my screenshot, you may notice an "extra" blank line below the object. The rules do not prohibit that so I made no effort to get rid of it.

But it provides a clue for further optimization. What if we mark the beginning of each line instead of the end? And do so without having to add another byte?

If $80 indicates the end of the image, we can detect it by decrementing, then checking for sign flag clear. The decrementation serves a second purpose in removing a by-one offset in the space count.
An actual space-star at the beginning of a line is denoted by the space count plus $81.

Doing this saves six bytes in the table, but some of them will be given back in the code to process this change.

The net gain for the 6800 version is two bytes - six bytes of data saved and four additional bytes taken by new code.

Code:
                          00031 * $81+n spaces denotes the beginning of the line.
                          00032 * $80 spaces denotes the end of the image.
                          00033 *
                          00034 * The rows of diamonds repeat three times.
                          00035 *
                          00036 * Because the line containing the three narrowly spaced stars are not
                          00037 * repeated between rows of diamonds, a row of diamonds does not include
                          00038 * the top row; the bottom of the previous row provides those.
                          00039 *
                          00040 * That means we must begin by emitting that "bottom" row as the very top row.
                          00041 *
                          00042
 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 2B 11 (003A)    [4] 00074          bmi    Special
                          00075
 0029                     00076 DoCouplet
 0029 27 08 (0033)    [4] 00077          beq    NoSpaces
                          00078
 002B 86 20           [2] 00079          ldaa   #' '      ; Emit spaces
                          00080
 002D                     00081 SpaceLoop
 002D BD AD18         [9] 00082          jsr    PUTCHR
                          00083
 0030 5A              [2] 00084          decb
 0031 26 FA (002D)    [4] 00085          bne    SpaceLoop
                          00086
 0033                     00087 NoSpaces
 0033 86 2A           [2] 00088          ldaa   #'*'      ; Emit star
                          00089
 0035 BD AD18         [9] 00090          jsr    PUTCHR
                          00091
 0038 20 EA (0024)    [4] 00092          bra    LineLoop
                          00093
 003A                     00094 Special
 003A 5A              [2] 00095          decb
 003B 2A 09 (0046)    [4] 00096          bpl    EndImage
                          00097
 003D 37              [4] 00098          pshb             ; Save couplet
 003E BD AD24         [9] 00099          jsr    PCRLF     ; Start a new line
 0041 33              [4] 00100          pulb             ; Recover couplet
                          00101
 0042 C4 7F           [2] 00102          andb   #$7F      ; Isolate space count
                          00103
 0044 20 E3 (0029)    [4] 00104          bra    DoCouplet
                          00105
 0046                     00106 EndImage
 0046 CE 0000         [3] 00107          ldx    #Image-1  ; Point to before start of the image
                          00108
 0049 7A 0000         [6] 00109          dec    Count     ; Do it again?
 004C 26 D6 (0024)    [4] 00110          bne    LineLoop
                          00111
 004E 7E AD03         [3] 00112          jmp    WARMS     ; Back to FLEX
                          00113
 0021                     00114          end    Start


The 6809 cannot do this because the instructions to push or pull a single register is two bytes each - no gain. But the 6809 can index with a negative offset, something the 6800 cannot do.

Code:
                                  00031 * $81+n spaces denotes the beginning of the line.
                                  00032 * $80 spaces denotes the end of the image.
                                  00033 *
                                  00034 * The rows of diamonds repeat three times.
                                  00035 *
                                  00036 * Because the line containing the three narrowly spaced stars are not
                                  00037 * repeated between rows of diamonds, a row of diamonds does not include
                                  00038 * the top row; the bottom of the previous row provides those.
                                  00039 *
                                  00040 * That means we must begin by emitting that "bottom" row as the very top row.
                                  00041 *
                                  00042
 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 2B 11 (0039)            [3] 00073          bmi    Special
                                  00074
 0028                             00075 DoCouplet
 0028 27 08 (0032)            [3] 00076          beq    NoSpaces
                                  00077
 002A 86 20                   [2] 00078          lda    #' '      ; Emit spaces
                                  00079
 002C                             00080 SpaceLoop
 002C BD CD18                 [8] 00081          jsr    PUTCHR
                                  00082
 002F 5A                      [2] 00083          decb
 0030 26 FA (002C)            [3] 00084          bne    SpaceLoop
                                  00085
 0032                             00086 NoSpaces
 0032 86 2A                   [2] 00087          lda    #'*'      ; Emit star
                                  00088
 0034 BD CD18                 [8] 00089          jsr    PUTCHR
                                  00090
 0037 20 EB (0024)            [3] 00091          bra    LineLoop
                                  00092
 0039                             00093 Special
 0039 5A                      [2] 00094          decb
 003A 2A 09 (0045)            [3] 00095          bpl    EndImage
                                  00096
 003C BD CD24                 [8] 00097          jsr    PCRLF     ; Start a new line
                                  00098
 003F E6 1F                   [5] 00099          ldb    -1,X      ; Recover couplet
                                  00100
 0041 C4 7F                   [2] 00101          andb   #$7F      ; Isolate space count
                                  00102
 0043 20 E3 (0028)            [3] 00103          bra    DoCouplet
                                  00104
 0045                             00105 EndImage
 0045 8E 0001                 [3] 00106          ldx    #Image    ; Point back to start of the image
                                  00107
 0048 0A 00                   [6] 00108          dec    Count     ; Do it again?
 004A 26 D8 (0024)            [3] 00109          bne    LineLoop
                                  00110
 004C 7E CD03                 [4] 00111          jmp    WARMS     ; Back to FLEX
                                  00112
 0021                             00113          end    Start


Unfortunately, the 6502 cannot benefit from this trick because I cannot and Y with $7F or add or subtract $80.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 27, 2023 1:10 am 
Offline

Joined: Mon Sep 17, 2018 2:39 am
Posts: 138
Hi!

IamRob wrote:
I see some problems with assembling this.

First, the org cannot be defined since E is not defined. And E cannot be defined since it uses the *, which indicates a present location, but since org has not been defined yet without the E, the * cannot have a memory address, which means E cannot be defined. I don't get this.


The code can be assembled with the MADS assembler ( https://github.com/tebe6502/Mad-Assembler ), it is a multi-pass assembler so it has no problem resolving the forward references. For old assemblers, you can simply fix the ORG at address $D1, this is the resulting listing:

Code:
00D1 A001       S   LDY #1
00D3 A90A       C   LDA #10
00D5 B6E9           LDX T,Y
00D7 96EF           STX T+6,Y
00D9 E4ED       R   CPX T+4
00DB D002           BNE K
00DD 915E           STA (94),Y
00DF C8         K   INY
00E0 C014           CPY #20
00E2 D0EF           BNE C
00E4 A99B           LDA #$9B
00E6 20B0F2         JSR $F2B0
00E9 E6DA       T   INC R+1
00EB D0E4           BNE S
00ED 60             RTS
00EE E4D0           .BYTE $FC-T+S,$D0
    =0100       E   =   *+16


Quote:
Second, I don't see how $94.95 gets set up with the screen address. That takes up 8 bytes to set up.
Third, some remarks would be nice to indicate what the #10 and #$9B actually print out on the screen. Those are not normal ascii chars and therefore must be special chars. If they are special, then all computers usually have to switch that character set in. Again, don't see that in the code.

Please explain.


The Atari 8bit computers don't use ASCII, instead use the "ATASCII" character set. There, $9B is the end-of-line (named "RETURN"), this is like $0A in ASCII. So, the LDA $$9B / JSR $F2B0 simply advances one line in the display.

The "10" ($0A) is the code for the asterix character "*".

The 94/95 ($5E/$5F) locations always contains the address of the cursor in the screen - this is the address on which the next character will be printed. In the Atari computers the screen memory is not at a fixed address - it depends on the amount of memory and graphics mode, so you must use the ZP locations to access the pointer to the memory.

Have Fun!


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 27, 2023 1:20 am 
Offline

Joined: Mon Sep 17, 2018 2:39 am
Posts: 138
Hi!

barrym95838 wrote:
dmsc wrote:
I also used a table, but "compressed" it to 5 bytes, of which 3 bytes also are the last bytes of the code :-P

This is for the Atari XL / XE 8-bit computers, calling the put-char ROM routine and directly writing to the screen, 31 bytes total.
[...]
For the C64, the code is about 5 bytes shorter.

I haven't quite finished my first cup of coffee, but I don't think any amount of coffee could allow me to understand how you did either of those very impressive feats without a much more detailed description. If you find the time and generosity, could you please try to enlighten me/us?


This is the code with comments:
Code:
; Setup ORG so that the end of the table is at address $FF
        org     $100 - (endtab - start)
;       Draw one row, avoiding drawing over the cursor
start   ldy     #1
;       Draw one column
column  lda     #10             ; Star symbol
        ldx     tab-1,y         ; Load table for X coordinate, and
        stx     tab-1+6,y       ; expand the table to the rest of the diamonds
row     =       *+1
        cpx     tab+3           ; Compare with table for Y coordinate.
        bne     skip            ; Skip drawing this star
        sta     (94),y
skip    iny                     ; Go to next column
        cpy     #20
        bne     column

        lda     #$9B            ; Advance the cursor one line
        jsr     $F2B0
; Last 4 bytes of the code are the first elements of the table:
tab     =       *+1
        inc     row             ; Increment row and repeat
        bne     start
        rts
; This is the assembly for "BNE line" above, the last 2 elements of the table
        .byte   $FD - (tab - start), $D0
endtab  =       *+16


The table is setup as:
table = A B C D C B A B C D C B A B C D C B A B C D

Then, you need to draw a star in coordinates with "table[column] == table[row+3]"

As the table repeats, the code only stores the first 6 elements of the table, using the last 6 bytes of the program.

Have Fun!


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 27, 2023 1:14 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
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


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 27, 2023 2:30 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
BillG wrote:
In 2021, there was another active venue discussing entries. I cannot find it now.


We had an active discussion here on 6502, also one over on retrocomputing forum, and another on stardot. I imagine there were others too.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 27, 2023 2:55 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
retrocomputing has little activity and none of it recent (after the deadline.)

search on stardot is fubar, but I managed to find the thread: https://stardot.org.uk/forums/viewtopic.php?t=28096


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 27, 2023 3:03 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Oh, I was talking about the 2021 contest, which you mentioned. Indeed, for 2023, there isn't (yet?) much conversation about the 2023 contest over on retrocomputing.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 27, 2023 3:09 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
stardot is no fun.

They decided to shush until the video presentation is released, not the submission deadline.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 27, 2023 3:16 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
I think last year that was part of the VC3 challenge rules, but I don't see it this year. Nonetheless, as you say, as a group of peers the people on that thread have chosen to reveal by stages. Very civilised.


Top
 Profile  
Reply with quote  
PostPosted: Thu Dec 28, 2023 10:28 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
From https://logiker.com/Vintage-Computing-C ... lenge-2023

Quote:
The presentation of the results will be a few days later, planed on the Saturday, 30th of December 2023 19:00 CET.

That is 18:00 GMT or high noon CST.

This will also be a test of who is using ad block and who is ad block blocked and which countermeasures can get around it...


Top
 Profile  
Reply with quote  
PostPosted: Fri Dec 29, 2023 11:09 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
Looking at some of the other entries gave me an impression that challenges like these are biased in favor of machines with direct access to video memory. Instead of emitting spaces, memory locations can simply be skipped over, often with a single add instruction.

So to test that theory, I coded up a version of the "line drawing" algorithm for the IBM PC. After a bit of code golf, it comes in one byte smaller than the best 6809 version.

Code:
     25       =0002                  Cell    equ     2               ; Number of bytes in a display position
     26       =00A0                  Row     equ     80*Cell         ; Number of bytes on a display row
     27
     28       =01E0                  Origin  equ     3*Row           ; Start on fourth row
     29
     30 0000                         CODE    segment byte public 'CODE'
     31                                      assume  CS:CODE,DS:CODE,SS:CODE
     32
     33                                      org     100h            ; It runs as a .COM file (Tiny model)
     34
     35 0100                         Start:
     36 0100  B8 0003                        mov     AX,3            ; Clear screen
     37 0103  CD 10                          int     10h
     38
     39 0105  B8 B800                        mov     AX,0B800h       ; Point ES to display buffer
     40                              ;       mov     AX,0B000h       ;   for MDA
     41 0108  8E C0                          mov     ES,AX
     42
     43 010A  BA 0C06                        mov     DX,0C06h        ; Twelve runs with six of positive slope
     44 010D  BB 009D                        mov     BX,Row-Cell-Cell/2      ; Load the increment to next row
     45
     46 0110  BE 0134r                       mov     SI,offset Runs  ; Point to list of runs
     47
     48 0113                         RunLoop:
     49
     50                              ; The address consists of three nybbles N2N1N0
     51                              ; The run length - 1 is one nybble RL
     52                              ;
     53                              ; They are stored in the form RLN2N1N0
     54
     55 0113  AD                             lodsw                   ; Load address
     56
     57 0114  8A EC                          mov     CH,AH           ; Extract run length
     58 0116  B1 04                          mov     CL,4
     59 0118  D2 ED                          shr     CH,CL
     60
     61 011A  80 E4 0F                       and     AH,0Fh          ; Isolate upper nybble of address
     62 011D  8B F8                          mov     DI,AX           ; Use it for stosb
     63
     64 011F  B0 2A                          mov     AL,'*'          ; Load the star
     65
     66 0121                         PutStar:
     67 0121  AA                             stosb                   ; Emit a star
     68 0122  03 FB                          add     DI,BX           ; Increment to the next row
     69
     70 0124  FE CD                          dec     CH              ; Another star?
     71 0126  79 F9                          jns     PutStar         ; Yes if still positive
     72
     73 0128  FE CA                          dec     DL              ; Change slope?
     74 012A  75 02                          jnz     SameSlope               ; Not yet
     75
     76 012C  B3 A1                          mov     BL,Row+Cell-Cell/2      ; Load the new increment to next row
     77
     78 012E                         SameSlope:
     79 012E  FE CE                          dec     DH              ; More runs?
     80 0130  75 E1                          jnz     RunLoop         ; Yes
     81
     82 0132                         Exit:
     83 0132  CD 20                          int     20h             ; Back to DOS
     84
     85
     86                              ; The address consists of three nybbles N2N1N0
     87                              ; The run length - 1 is one nybble RL
     88                              ;
     89                              ; They are stored in the form RLN2N1N0
     90
     91 0134                         Runs:
     92 0134  31E6                           dw      ((4-1) shl 12) + (Origin+3*Cell)
     93
     94 0136  91F2                           dw      ((10-1) shl 12) + (Origin+9*Cell)
     95
     96 0138  F1FE                           dw      ((16-1) shl 12) + (Origin+15*Cell)
     97
     98 013A  F3E4                           dw      ((16-1) shl 12) + (Origin+3*Row+18*Cell)
     99
    100 013C  97A4                           dw      ((10-1) shl 12) + (Origin+9*Row+18*Cell)
    101
    102 013E  3B64                           dw      ((4-1) shl 12) + (Origin+15*Row+18*Cell)
    103
    104
    105 0140  31FE                           dw      ((4-1) shl 12) + (Origin+15*Cell)
    106
    107 0142  91F2                           dw      ((10-1) shl 12) + (Origin+9*Cell)
    108
    109 0144  F1E6                           dw      ((16-1) shl 12) + (Origin+3*Cell)
    110
    111 0146  F3C0                           dw      ((16-1) shl 12) + (Origin+3*Row)
    112
    113 0148  9780                           dw      ((10-1) shl 12) + (Origin+9*Row)
    114
    115 014A  3B40                           dw      ((4-1) shl 12) + (Origin+15*Row)
    116
    117 014C                         CODE    ends
    118
    119                                      end     Start


I also coded up a version using the original run length table. It is smaller than the 8080 version, but larger than the 6xxx ones.

Code:
     25       =0002                  Cell    equ     2               ; Number of bytes in a display position
     26       =00A0                  Row     equ     80*Cell         ; Number of bytes on a display row
     27
     28       =01E0                  Origin  equ     3*Row           ; Start on fourth row
     29
     30       =0080                  EndOfLine equ 80h
     31       =007F                  EndOfImage equ 7Fh
     32
     33 0000                         CODE    segment byte public 'CODE'
     34                                      assume  CS:CODE,DS:CODE,SS:CODE
     35
     36                                      org     100h            ; It runs as a .COM file (Tiny model)
     37
     38 0100                         Start:
     39 0100  B8 0003                        mov     AX,3            ; Clear screen
     40 0103  CD 10                          int     10h
     41
     42 0105  B8 B800                        mov     AX,0B800h       ; Point ES to display buffer
     43                              ;       mov     AX,0B000h       ;   for MDA
     44 0108  8E C0                          mov     ES,AX
     45
     46 010A  BE 014Er                       mov     SI,offset Top   ; Point to top row
     47
     48 010D  BA 01DF                        mov     DX,Origin-1     ; Point to before start of object in display
     49                                                              ;   buffer - this is because storing a star
     50                                                              ;   with stosb leaves DI one byte before the
     51                                                              ;   next character cell
     52
     53 0110  B9 0004                        mov     CX,4            ; Do it three times plus the top line
     54
     55 0113                         LineLoop:
     56 0113  AC                             lodsb                   ; Get the couplet
     57
     58 0114  3C 7F                          cmp     AL,EndOfImage   ; End of image?
     59 0116  74 13                          jz      EndImage
     60 0118  72 08                          jb      DoCouplet
     61
     62 011A  81 C2 00A0                     add     DX,Row          ; Point to the next row in the display buffer
     63 011E  8B FA                          mov     DI,DX
     64
     65 0120  24 7F                          and     AL,7Fh          ; Isolate space count
     66
     67 0122                         DoCouplet:
     68 0122  32 E4                          xor     AH,AH
     69
     70 0124  03 F8                          add     DI,AX           ; "Space" over to the star
     71
     72 0126  B0 2A                          mov     AL,'*'          ; Load star
     73 0128  AA                             stosb                   ; Store it
     74
     75 0129  EB E8                          jmp     LineLoop
     76
     77 012B                         EndImage:
     78 012B  BE 0132r                       mov     SI,offset Image ; Point back to start of image
     79
     80 012E  E2 E3                          loop    LineLoop
     81
     82 0130  CD 20                          int     20h             ; Back to DOS
     83
     84 0132                         Image:
     85 0132  85 03 07 03 07 03              db      EndOfLine+2*2+1,1*2+1,3*2+1,1*2+1,3*2+1,1*2+1
     86 0138  83 07 03 07 03 07              db      EndOfLine+1*2+1,3*2+1,1*2+1,3*2+1,1*2+1,3*2+1
     87 013E  81 0B 0B 0B                    db      EndOfLine+0*2+1,5*2+1,5*2+1,5*2+1
     88 0142  83 07 03 07 03 07              db      EndOfLine+1*2+1,3*2+1,1*2+1,3*2+1,1*2+1,3*2+1
     89 0148  85 03 07 03 07 03              db      EndOfLine+2*2+1,1*2+1,3*2+1,1*2+1,3*2+1,1*2+1
     90
     91 014E                         Top:
     92 014E  87 0B 0B                       db      EndOfLine+3*2+1,5*2+1,5*2+1
     93
     94 0151  7F                             db      EndOfImage
     95
     96 0152                         CODE    ends
     97
     98                                      end     Start


Top
 Profile  
Reply with quote  
PostPosted: Fri Dec 29, 2023 8:17 pm 
Offline

Joined: Fri Dec 29, 2023 8:11 pm
Posts: 1
My official C64 entry came to 26 bytes. But subsequent to the deadline I came up with this 25-byte version:
Code:
    CRLF = $AAD7
    PNT = $d1
*=$80d

start
    bcc right
    dey
    bne skip
    jsr CRLF
right
    iny
    cpy #19
skip
    inx
    xaa #$0f
    bne start
    lax #'*'
    sta (PNT),y
    inc $65   
    bpl start
    rts
end


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 01, 2024 10:52 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
I have yet to figure out the trickier approaches, but one method discussed on stardot is treating each row of diamonds as a pair of triangle waves. I decided to try that...

61 bytes of code, no data storage, beating the "line drawing" one by 15 bytes.
Code:
     24                              ; Each row of diamonds can be treated as a pair of triangle waves, one
     25                              ; starting with a positive slope and the other with a negative slope.
     26                              ;
     27
     28       =0002                  Cell    equ     2               ; Number of bytes in a display position
     29       =00A0                  Row     equ     80*Cell         ; Number of bytes on a display row
     30
     31       =01E0                  Origin  equ     3*Row           ; Start on fourth row
     32
     33 0000                         CODE    segment byte public 'CODE'
     34                                      assume  CS:CODE,DS:CODE,SS:CODE
     35
     36                                      org     100h            ; It runs as a .COM file (Tiny model)
     37
     38 0100                         Start:
     39 0100  B8 0003                        mov     AX,3            ; Clear screen
     40 0103  CD 10                          int     10h
     41
     42 0105  B8 B800                        mov     AX,0B800h       ; Point ES to display buffer
     43                              ;       mov     AX,0B000h       ;   for MDA
     44 0108  8E C0                          mov     ES,AX
     45
     46 010A  B8 2A2A                        mov     AX,101010b*100h+'*' ; Six rows of half-diamonds plus the star
     47                                                              ; These bits are shifted to also track odd
     48                                                              ;   versus even rows
     49
     50 010D  BE 03C0                        mov     SI,Origin+3*Row ; Address left vertex of first diamond row
     51
     52 0110  BD FF61                        mov     BP,Cell-Row-1   ; Load increment for positive slope
     53 0113  BB 00A1                        mov     BX,Cell+Row-1   ; Set up to toggle between them
     54 0116  33 DD                          xor     BX,BP
     55
     56 0118                         RowLoop:
     57 0118  B9 0603                        mov     CX,603h         ; Six half-cycles on a row and
     58                                                              ;   three stars in a half-cycle
     59 011B  8B FE                          mov     DI,SI           ; Point to beginning of the row
     60
     61 011D                         StarLoop:
     62 011D  AA                             stosb                   ; Emit a star
     63
     64 011E  03 FD                          add     DI,BP           ; Increment to the next star
     65
     66 0120  FE C9                          dec     CL
     67 0122  75 F9                          jnz     StarLoop
     68
     69 0124  B1 03                          mov     CL,3            ; Reload three stars per half-cycle
     70
     71 0126  FE CD                          dec     CH              ; More half-cycles?
     72 0128  74 04                          jz      EndRow
     73
     74 012A  33 EB                          xor     BP,BX           ; Toggle slope
     75
     76 012C  EB EF                          jmp     StarLoop
     77
     78 012E                         EndRow:
     79 012E  AA                             stosb                   ; Emit final star on row
     80
     81 012F  D0 EC                          shr     AH,1            ; More rows?
     82 0131  74 08                          jz      Exit
     83
     84 0133  73 E3                          jnc     RowLoop         ; Odd row?
     85
     86 0135  81 C6 03C0                     add     SI,6*Row        ; Move to next row of diamonds after even row
     87
     88 0139  EB DD                          jmp     RowLoop
     89
     90 013B                         Exit:
     91 013B  CD 20                          int     20h             ; Back to DOS
     92
     93 013D                         CODE    ends
     94
     95                                      end     Start


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 02, 2024 10:30 pm 
Offline

Joined: Sat Sep 05, 2020 3:12 pm
Posts: 22
I decided to try my hand at some C for my cc64 compiler. I was too late to submit anything, though, only noticed the challenge just after the deadline, on Dec 26th.
In the first version I did some sort of overlay of vertical and horizontal triangular oscillations. Next I noticed the modulo-6 aspect (version 2), and then tried to shorten the source using more modulo and ternary operators (versions 3 and 4). Interestingly, the shortest executable was version 2 with 764 bytes on the Commander X16, 492 bytes of which are the runtime library.

Version 1
Code:
#include <rt-x16-08-9e.h>
extern _fastcall putchar() *= 0xffd2 ;

int main() {
  static int i, j, x, y, dx, dy;
  for (i=0, y=3, dy=1; i<19; ++i, y+=dy) {
    dy=(y==0?1:y==3?-1:dy);
    for (j=0, x=0, dx=1; j<19; ++j, x+=dx) {
      dx=(x==0?1:x==3?-1:dx);
      putchar(x==y?'*':' ');
    }
    putchar('\n');
  }
}

Version 2
Code:
#include <rt-x16-08-9e.h>
extern _fastcall putchar() *= 0xffd2 ;

int main() {
  static int i, j;
  for (i=3;i<22;++i) {
    for (j=0;j<19;++j) {
      putchar((i+j)%6&&(i-j)%6?' ':'*');
    }
    putchar('\n');
  }
}

Version 3
Code:
#include <rt-x16-08-9e.h>
extern _fastcall putchar() *= 0xffd2 ;

int main() {
  static int i, j;
  for (i=3;i<22;++i)
    for (j=0;j<20;++j)
      putchar(j%20-19?(i+j)%6&&(i-j)%6?' ':'*':'\n');
}

Version 4
Code:
#include <rt-x16-08-9e.h>
extern _fastcall putchar() *= 0xffd2 ;

int main() {
  static int j;
  for (j=0;j<380;++j)
    putchar(j%20-19?(j/20+j%20+3)%6&&(j/20-j%20+3)%6?' ':'*':'\n');
}


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 48 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 15 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron