Compact 64 column print routine

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Compact 64 column print routine

Post by Seven.FFF »

I love it when you get your teeth into a project :)
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Compact 64 column print routine

Post by Nomad »

It is compact code porn. :lol:
User avatar
utz
Microbot
Posts: 113
Joined: Wed Nov 15, 2017 9:04 am
Contact:

Re: Compact 64 column print routine

Post by utz »

Not that I have anything useful to say, but I do want to join the choir of appreciation. This is a piece of art.
User avatar
djnzx48
Manic Miner
Posts: 729
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Compact 64 column print routine

Post by djnzx48 »

(Sorry, I should've replied to this sooner but I've been sick the last few days.)

99 bytes, now that's impressive! My first attempt at a text routine was 89 bytes for the code alone! :lol: At first I couldn't figure out how you were getting five graphic rows from two bytes but then I realised that you're only shifting three bits at a time into A, that's quite clever. I take it that the routine doesn't work properly if the screen isn't blank? Probably not a major problem. And it's a shame that lowercase letters are gone, but at 100 bytes you can't really complain ;)

About the size issue, perhaps the last part that increments the screen pointer could be made smaller somehow? Maybe changing the routine to print the string backwards and using a counter, say in A', instead of the 'end of string' marker would simplify it a bit? Then you could use (initial screen position) + counter/2 to get the screen position of the next character. I don't know if this would make the routine any smaller though.

How did you decide on the character ordering so that adjacent font rows can be merged; was it just manual trial and error? I came up with an algorithm for the last version that got optimal or close to optimal results most of the time - for a small amount of characters. I don't think you could ensure the results were optimal without brute-forcing it, which would take far too long to compute if you had a lot of characters. The time can be reduced by only considering the characters with overlapping parts, so if there aren't many, it might be a feasible solution.

For this version of the code, it doesn't look like you could get much more optimal than this, since each character is only 2 bytes.

Although I just remembered that changing the character set from the default won't work too well if it needs to be used with key redefine or keyboard input routines, since it'll require a 40 byte table mapping the keys to the new character values. And if lower case letters are needed then that's another 26 bytes for an uppercase->lowercase table. Still, there's always RST 16 if you're really desperate.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

Many different methods were tried before I decided to go with the 15 bit (2 byte) data format. Even now, I'm mortified that it wastes a whole BIT per character, though in a few instances, its worked to my advantage, where that trailing unused BIT can be any value in order to allow if to be shared as the first byte of the next Character.

I've tried all sorts to get the screen address to increment. In the previous routine I did, It does an SRL L to effectively /2, but that only leaves it possible to print on the upper 4 lines of each screen 3rd, maybe ok in some cases, but for the sake of 2 bytes, I thought it better to give full access to the screen area.

I have 2 further formats to try out, and though the actual routine will be a bit larger, hopefully a few more bytes might get shaved off.

The reason I use an end marker in the text string is the avoid having to specify the length before the routine is called. At the moment, with an initial address of BC (message) given, we only need specify the new screen address in DE before each CALL to the print routine. If we were to put a few extra decoding bytes in the routine, its possible to make the string contain the screen address too, with separate line end and message end markers.

The advantage of trying out these encoding methods on a minimal character set is that it can be done quicker to test.

I do intend to do a full CHR set with lower case and all the other characters. Maybe not the full 96 characters, but perhaps 75-80-ish.

When it became apparent that sub 100 bytes was possible, it became a sort of crusade to achieve it with the 37 characters needed for most text.

I also have a bit based format that if I can get the CHR data to sub 32 bytes (half its current size), 32 bytes=256 bits, then if the routine allows, we might go sub 90 bytes.
User avatar
utz
Microbot
Posts: 113
Joined: Wed Nov 15, 2017 9:04 am
Contact:

Re: Compact 64 column print routine

Post by utz »

Soooo... how many bytes in the print routine code are actually usable as character data? :twisted:
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

Believe me, I've looked at that soooooooo many times!

There might be possibly one or two characters if the code structure would allow, but its very tricky!

New format currently underway. The routine looks like maybe 36-37 bytes, and the data maybe 62, so perhaps smaller!! ;)
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: Compact 64 column print routine

Post by Einar Saukas »

Instead of this:

Code: Select all

          ld a,(bc)
          ld l,a
          add a,a
          ret c
          ld h,0fah
          push de
          ld a,(hl)
          inc l
          ld l,(hl)
          ld h,a
Perhaps you can use this:

Code: Select all

          ld a,(bc)
          ld (label+1),a
          add a,a
          ret c
          push de
label:
          ld hl,(0fa00h)
Except you will need to swap the order you are storing each pair of bytes, or store everything backwards.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

Oh yes! Very good Mr S!!

Theres a bit more to it than just swapping the Hi/Lo byte order, as some rely upon shared bytes, however I will re-align them all to save a byte!!

Thankyou!! :P
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

With Einars clever self modifying trick, and by hiding the 'E' character in the routine to make the jump vector at the end the value of 'DCh', therefore sharing the D Character first byte with the jump at the end, I've saved 2 more bytes.

Now down to 97 bytes!

Code: Select all

;15 bit 64 column format
;
;super compact 5 byte high characters
;
;DE holds screen address
;BC is message address
;End of Message byte is any value with BIT 7 set
;message must be an even number of characters long (padded with space if reqd.)
;Call routine at 0FA00h (64000d)
;
;99 bytes if we include the trailing 00h,00h (space CHR)
;97 bytes otherwise
;
;Characters A-Z...0-9..spc.
;
;Arkannoyed March 2018
;
;Special Thanks to Einar!

org 0f9fah

          ld bc,example_message
          ld de,4300h

start:
          ld a,(bc)
          ld (get_bytes+1),a
          inc bc
          add a,a
          ret c
          push de
get_bytes:
          ld hl,(0fa00h)
lp0:
          ld a,(de)
          or 10h

          add a,a
lp1:
          add hl,hl
          rla
          jr nc,lp1
          
          ld (de),a
          inc d
          ld a,d
          and 07h
          jr nz,lp0
          
          pop de
          ld a,c
          and 01h
          add a,e
          ld e,a
          ;db %11000110,%01110011        ;E code 20h      ;0c6h,73h
          add a,73h     ;code for CHR E ..doesn't affect anything being here.
          db 18h        ;jr start vector DCh which is the first byte of CHR D

          db %11011100,%11010110        ;D code 23h      ;0dch,0d6h
          db %11011010,%01010111        ;A code 25h      ;0dah,57h
          db %01011100,%11010111        ;B code 27h      ;5ch,0d7h
          db %01000110,%01110010        ;C code 29h      ;46h,72h
          db %00100100,%01001001        ;I code 2bh *    ;24h,49h
          db %01110011                  ;F code 2ch      ;49h,73h
          db %11010100,%01010110        ;O code 2eh *    ;0d4h,56h
          db %01110010                  ;G code 2fh      ;56h,72h
          db %11011010,%10110111        ;H code 31h      ;0dah,0b7h
          db %00100100,%11101001        ;T code 33h *    ;24h,0e9h
          db %10110110                  ;V code 34h      ;0e9h,0b6h
          db %11011100,%11100100        ;J code 36h      ;0dch,0e4h
          db %01011010,%10110111        ;K code 38h      ;5ah,0b7h
          db %01001110,%10010010        ;L code 3ah      ;4eh,92h
          db %11011010,%10111111        ;M code 3ch      ;0dah,0bfh
          db %01001000,%11010111        ;P code 3eh      ;48h,0d7h
          db %01011010,%11010111        ;R code 40h *    ;5ah,0d7h
          db %01010110                  ;Q code 41h      ;0d7h,56h
          db %00011100,%01110001        ;S code 43h      ;1ch,71h
          db %11010100,%10110110        ;U code 45h      ;0d4h,0b6h
          db %11111010,%10110111        ;W code 47h      ;0fah,0b7h
          db %01011010,%10110101        ;X code 49h      ;5ah,0b5h
          db %00100100,%10110101        ;Y code 4bh      ;24h,0b5h
          db %01001110,%11100101        ;Z code 4dh      ;4eh,0e5h
          db %11011010,%11010110        ;N code 4fh *    ;0dah,0d6h
          db %11010110                  ;0 code 50h      ;0d6h,0d6h
          db %00101110,%01011001        ;1 code 52h      ;2eh,59h
          db %01001110,%11000101        ;2 code 54h      ;4eh,0c5h
          db %10011100,%11000101        ;3 code 56h      ;9ch,0c5h
          db %00011100,%11110011        ;5 code 58h *    ;1ch,0f3h
          db %10010010                  ;4 code 59h      ;0f3h,92h
          db %10100100,%11100100        ;7 code 5bh      ;0a4h,0e4h
          db %10010100,%01010101        ;9 code 5dh *    ;9ch,55h
          db %01010101                  ;8 code 5eh *    ;55h,55h
          db %01010011                  ;6 code 5fh *    ;55h,53h
          db %00000000,%00000000        ;spc cd 61h      ;00h,00h


example_message:
          db 25h,27h,29h,23h,20h,2ch,2fh,31h,2bh,36h,38h,3ah,3ch,4fh,2eh,3eh,41h,40h,43h,33h,45h,34h,47h,49h,4bh,4dh,50h,52h,54h,56h,59h,58h,5fh,5bh,5eh,5dh,61h,0ffh
I'll see if I can lose any more bytes! :D
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

Don't you just hate it when you find another place to save a byte...but it means reorganizing code for about an hour!

Oh, and how fortunate that the change to the routine and swapping a few registers around lets me hide the '3' character in there too, thus saving another byte!

Now fully working and down to 95 bytes! :lol:

I really need to comment the source, which I promise I'll do and tidy it up a bit.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

And heres the code, actually commented this time! Well, I suppose theres always a first time for everything! :lol:

Code: Select all

;15 bit 64 column format
;
;super compact 5 byte high characters
;
;BC holds screen address, HI-byte -1
;DE is message address
;End of Message byte is any value with BIT 7 set
;message must be an even number of characters long (padded with space if reqd.)
;Call routine at 0FA00h (64000d)
;
;97 bytes if we include the trailing 00h,00h (space CHR)
;95 bytes otherwise
;
;Characters A-Z...0-9..spc.
;
;Arkannoyed March 2018
;
;Special Thanks to Einar!

org 0f9fah

          ld de,example_message
          ld bc,3f00h       ;screen address hi-byte must start -1

start:
          ld a,(de)         ;CHR byte into A
          ld (get_bytes+1),a;write it to direct input (HL) load
          inc de            ;next CHR
          add a,a           ;test bit 7 for end marker
          ret c             ;RET if end of message

          sbc a,h           ;useless instruction!!
          push bc           ;together these 2 instructions create CHR 3 (9Ch,C5h)
                            ;db %10011100,%11000101        ;3 code 56h      ;9ch,0c5h
                            ;3 = code 07h
get_bytes:
          ld hl,(0fa00h)    ;get 2 data bytes
lp0:
          inc b             ;down 1 screen line
          ld a,(bc)         ;SCReen byte into A
          or 10h            ;set the marker for 4 bits

          add a,a           ;add the space between chars
lp1:
          add hl,hl         ;propagate the data into the Carry
          rla               ;and then the result into A
          jr nc,lp1         ;repeat if we've not put the marker into the Carry
          
          ld (bc),a         ;replace the SCReen byte
          bit 2,b           ;test if we've done 5 bytes
          jr z,lp0          ;repeat if not

          pop bc            ;restore SCReen address
          ld a,e            ;message address LO byte into A
          and 01h           ;test if odd or even
          add a,c           ;add the result to A
          ld c,a            ;update the SCReen address

                            ;db %11000110,%01110011        ;E code 20h      ;0c6h,73h
          add a,73h         ;code for CHR E = doesn't do anything to affect the routine

          db 18h            ;jr start vector DCh which is the first byte of CHR D

          db %11011100,%11010110        ;D code 23h      ;0dch,0d6h
          db %11011010,%01010111        ;A code 25h      ;0dah,57h
          db %01011100,%11010111        ;B code 27h      ;5ch,0d7h
          db %01000110,%01110010        ;C code 29h      ;46h,72h
          db %00100100,%01001001        ;I code 2bh *    ;24h,49h
          db %01110011                  ;F code 2ch      ;49h,73h
          db %11010100,%01010110        ;O code 2eh *    ;0d4h,56h
          db %01110010                  ;G code 2fh      ;56h,72h
          db %11011010,%10110111        ;H code 31h      ;0dah,0b7h
          db %00100100,%11101001        ;T code 33h *    ;24h,0e9h
          db %10110110                  ;V code 34h      ;0e9h,0b6h
          db %11011100,%11100100        ;J code 36h      ;0dch,0e4h
          db %01011010,%10110111        ;K code 38h      ;5ah,0b7h
          db %01001110,%10010010        ;L code 3ah      ;4eh,92h
          db %11011010,%10111111        ;M code 3ch      ;0dah,0bfh
          db %01001000,%11010111        ;P code 3eh      ;48h,0d7h
          db %01011010,%11010111        ;R code 40h *    ;5ah,0d7h
          db %01010110                  ;Q code 41h      ;0d7h,56h
          db %00011100,%01110001        ;S code 43h      ;1ch,71h
          db %11010100,%10110110        ;U code 45h      ;0d4h,0b6h
          db %11111010,%10110111        ;W code 47h      ;0fah,0b7h
          db %01011010,%10110101        ;X code 49h      ;5ah,0b5h
          db %00100100,%10110101        ;Y code 4bh      ;24h,0b5h
          db %01001110,%11100101        ;Z code 4dh      ;4eh,0e5h
          db %11011010,%11010110        ;N code 4fh *    ;0dah,0d6h
          db %11010110                  ;0 code 50h      ;0d6h,0d6h
          db %00101110,%01011001        ;1 code 52h      ;2eh,59h
          db %01001110,%11000101        ;2 code 54h      ;4eh,0c5h
          db %00011100,%11110011        ;5 code 56h *    ;1ch,0f3h
          db %10010010                  ;4 code 57h      ;0f3h,92h
          db %10100100,%11100100        ;7 code 59h      ;0a4h,0e4h
          db %10010100,%01010101        ;9 code 5bh *    ;9ch,55h
          db %01010101                  ;8 code 5ch *    ;55h,55h
          db %01010011                  ;6 code 5dh *    ;55h,53h
          db %00000000,%00000000        ;spc cd 5fh      ;00h,00h


example_message:
          db 25h,27h,29h,23h,20h,2ch,2fh,31h,2bh,36h,38h,3ah,3ch,4fh,2eh,3eh,41h,40h,43h,33h,45h,34h,47h,49h,4bh,4dh,50h,52h,54h,07h,57h,56h,5dh,59h,5ch,5bh,5fh,0ffh
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

..And probably the final one today, saving another byte by changing the shape of the '9' to share it with 'L'

94 bytes!

Code: Select all

db %11011100,%11010110        ;D code 23h      ;0dch,0d6h
          db %11011010,%01010111        ;A code 25h      ;0dah,57h
          db %01011100,%11010111        ;B code 27h      ;5ch,0d7h
          db %01000110,%01110010        ;C code 29h      ;46h,72h
          db %00100100,%01001001        ;I code 2bh *    ;24h,49h
          db %01110011                  ;F code 2ch      ;49h,73h
          db %11010100,%01010110        ;O code 2eh *    ;0d4h,56h
          db %01110010                  ;G code 2fh      ;56h,72h
          db %11011010,%10110111        ;H code 31h      ;0dah,0b7h
          db %00100100,%11101001        ;T code 33h *    ;24h,0e9h
          db %10110110                  ;V code 34h      ;0e9h,0b6h
          db %11011100,%11100100        ;J code 36h      ;0dch,0e4h
          db %01011010,%10110111        ;K code 38h      ;5ah,0b7h
          db %01001110,%10010010        ;L code 3ah      ;4eh,92h
          db %01010101                  ;9 code 3bh *    ;92h,55h
          db %01010101                  ;8 code 3ch *    ;55h,55h
          db %01010011                  ;6 code 3dh *    ;55h,53h
          db %11011010,%10111111        ;M code 3fh      ;0dah,0bfh
          db %01001000,%11010111        ;P code 41h      ;48h,0d7h
          db %01011010,%11010111        ;R code 43h *    ;5ah,0d7h
          db %01010110                  ;Q code 44h      ;0d7h,56h
          db %00011100,%01110001        ;S code 46h      ;1ch,71h
          db %11010100,%10110110        ;U code 48h      ;0d4h,0b6h
          db %11111010,%10110111        ;W code 4ah      ;0fah,0b7h
          db %01011010,%10110101        ;X code 4ch      ;5ah,0b5h
          db %00100100,%10110101        ;Y code 4eh      ;24h,0b5h
          db %01001110,%11100101        ;Z code 50h      ;4eh,0e5h
          db %11011010,%11010110        ;N code 52h *    ;0dah,0d6h
          db %11010110                  ;0 code 53h      ;0d6h,0d6h
          db %00101110,%01011001        ;1 code 55h      ;2eh,59h
          db %01001110,%11000101        ;2 code 57h      ;4eh,0c5h
          db %00011100,%11110011        ;5 code 59h *    ;1ch,0f3h
          db %10010010                  ;4 code 5ah      ;0f3h,92h
          db %10100100,%11100100        ;7 code 5ch      ;0a4h,0e4h
          db %00000000,%00000000        ;spc cd 5eh      ;00h,00h


example_message:
          db 25h,27h,29h,23h,20h,2ch,2fh,31h,2bh,36h,38h,3ah,3fh,52h,2eh,41h,44h,43h,46h,33h,48h,34h,4ah,4ch,4eh,50h,53h,55h,57h,07h,5ah,59h,3dh,5ch,3ch,3bh,5eh,0ffh
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

Oh well! Never say never!

by sharing A and B, a slight modification to B, but it still looks like B!

93 bytes. :shock:

Code: Select all

db %11011100,%11010110        ;D code 23h      ;0dch,0d6h
          db %11011010,%01010111        ;A code 25h      ;0dah,57h
          db %11010111                  ;B code 26h      ;57h,0d7h
          db %01000110,%01110010        ;C code 28h      ;46h,72h
          db %00100100,%01001001        ;I code 2ah *    ;24h,49h
          db %01110011                  ;F code 2bh      ;49h,73h
          db %11010100,%01010110        ;O code 2dh *    ;0d4h,56h
          db %01110010                  ;G code 2eh      ;56h,72h
          db %11011010,%10110111        ;H code 30h      ;0dah,0b7h
          db %00100100,%11101001        ;T code 32h *    ;24h,0e9h
          db %10110110                  ;V code 33h      ;0e9h,0b6h
          db %11011100,%11100100        ;J code 35h      ;0dch,0e4h
          db %01011010,%10110111        ;K code 37h      ;5ah,0b7h
          db %01001110,%10010010        ;L code 39h      ;4eh,92h
          db %01010101                  ;9 code 3ah *    ;92h,55h
          db %01010101                  ;8 code 3bh *    ;55h,55h
          db %01010011                  ;6 code 3ch *    ;55h,53h
          db %11011010,%10111111        ;M code 3eh      ;0dah,0bfh
          db %01001000,%11010111        ;P code 40h      ;48h,0d7h
          db %01011010,%11010111        ;R code 42h *    ;5ah,0d7h
          db %01010110                  ;Q code 43h      ;0d7h,56h
          db %00011100,%01110001        ;S code 45h      ;1ch,71h
          db %11010100,%10110110        ;U code 47h      ;0d4h,0b6h
          db %11111010,%10110111        ;W code 49h      ;0fah,0b7h
          db %01011010,%10110101        ;X code 4bh      ;5ah,0b5h
          db %00100100,%10110101        ;Y code 4dh      ;24h,0b5h
          db %01001110,%11100101        ;Z code 4fh      ;4eh,0e5h
          db %11011010,%11010110        ;N code 51h *    ;0dah,0d6h
          db %11010110                  ;0 code 52h      ;0d6h,0d6h
          db %00101110,%01011001        ;1 code 54h      ;2eh,59h
          db %01001110,%11000101        ;2 code 56h      ;4eh,0c5h
          db %00011100,%11110011        ;5 code 58h *    ;1ch,0f3h
          db %10010010                  ;4 code 59h      ;0f3h,92h
          db %10100100,%11100100        ;7 code 5bh      ;0a4h,0e4h
          db %00000000,%00000000        ;spc cd 5dh      ;00h,00h


example_message:
          db 25h,26h,28h,23h,20h,2bh,2eh,30h,2ah,35h,37h,39h,3eh,51h,2dh,40h,43h,42h,45h,32h,47h,33h,49h,4bh,4dh,4fh,52h,54h,56h,07h,59h,58h,3ch,5bh,3bh,3ah,5dh,0ffh
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

Now 92 bytes. Getting closer to Djnz48’s initial attempt of 89. Only 3 to go, though Im out of ideas as to where to save any more at the moment.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Compact 64 column print routine

Post by RMartins »

You can probably shave off 2 more bytes by changing your ORG address, so that 'get_bytes+1' matches the definition of a letter. Maybe W?

You can also reduce the overal footprint by using the 7th bit of the last char in message instead of adding an entire byte to end the message.
This will improve the footprint for each added message.

Alternatively you can concat messages and mark the first character 7th bit as terminator of previous message, if the test is not done on first char or is only done after processing increment.
NOTE :This obviously precludes single char messages.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

Altering the way the message terminates is possible but not without making the routine larger. Nice idea regarding the address being substituted for a character data set, however it does seriously restrict the number of locations that the routine can be located at. Currently it can go pretty much anywhere. Even hidden in 3 attr blanked lines of the screen maybe at the bottom! We could cheat a little and use ‘S’ and ‘5’ A’s the same character, also ‘0’ and ‘O’, but I don’t like doing that. That would though take it under 90 bytes! I think 92 might just be about the best I can do. Maybe time to add in the lower case characters and see how it grows in size.
User avatar
djnzx48
Manic Miner
Posts: 729
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Compact 64 column print routine

Post by djnzx48 »

Have you considered using delta encoding to reduce the size of the font? In this modified font, each row only has up to four possible rows that can follow it. That means that you can store the first row using 3 bits, then use 2 bits each for the remaining four rows, giving 11 bits overall per character. It's still not a particularly nice size to work with, but it might be possible to find more characters that can be merged together with this method.

Image
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

Ahhh, yes, I like that. I have been considering some sort of compression, and I'd struggled to manage an overall improvement over the whole font. Although this makes a few changes that are less than ideal, its certainly a possibility. I've adapted a data structure from my 3D Chess engine, where the routine reads just 1 bit per byte. It relies upon being able to address only up to 32 bytes with interleaved data.

I've managed to encode 31 of 37 characters to fit within the allowed size so far. The routine to display them is currently 50 bytes.

Do, its incomplete, but a total of 50 bytes prog and 40 bytes data, making 90. The '5' and '0' could use 'S' and 'O' instead I suppose, and maybe even 'I' could be '1', which would save a bit more, but still fall just short.

I could encode this CHR set with its in line compression and see what I get.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Compact 64 column print routine

Post by RMartins »

arkannoyed wrote: Sun Mar 18, 2018 5:21 pm Altering the way the message terminates is possible but not without making the routine larger. ...
Eventually, but it shouldn't be very different, since we just need to test after processing the char.
Probably just need to move a few instructions, and not much else (assuming we do not lose the contents of the string char).
If it's the test flag we need, a simple pair of EX.AF,AF' might do the trick.
The savings will come one byte for each extra message.

Making the code really dense, does not help you much if you have a lot more data than code. It's a balance, between the too.
User avatar
djnzx48
Manic Miner
Posts: 729
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Compact 64 column print routine

Post by djnzx48 »

If you want to go even more extreme, you can design a font so that each row has only two possible rows that can follow it. This way each successive row can be stored in only one bit, giving a total of 7 bits per character. OK, so it might be a little hard to read, but just imagine the byte savings :)

Image
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Compact 64 column print routine

Post by Nomad »

If you want to move away from a direct representation of an alphabet..

Why not abstract it a level and use a visual representation of Morse.. that would dramatically reduce the code size.

Image

super compact method... :lol:

Be really cold war 80s and use a combination of Morse, + one time number pad to generate your message thereby only needing the characters 0-9... Assuming you did it like a number station you would only need a few blocks of 5 digits. Very compact message encoding that way. But of course suffers from readability issues. :lol:
User avatar
Kweepa
Manic Miner
Posts: 311
Joined: Sat Feb 03, 2018 6:14 pm
Location: Albuquerque, New Mexico

Re: Compact 64 column print routine

Post by Kweepa »

I see another crap game entry!
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

Isn't it annoying when you find a way of storing data in an even more efficient and compact way, but then can't get the routine to decode it small enough to make a difference! Grrrrrr!!!!!!!!

The data is now 41 bytes for the 37 characters, but the best I can do with the print routine is 54 bytes, giving a total of 95. :x
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Compact 64 column print routine

Post by arkannoyed »

So, having failed so far to get any smaller than 92 bytes, though I do have some investigating to do in terms of decoding the data format, so I might still achieve a smaller size, I thought I'd do the obvious and alter the routine to actually manage without any CHR set data.

The Character codes are actually the bitmap for each character, so 32768 possible characters! :D

The only downside is that each character code is 2 bytes. This is fine if you've only a few lines of text to display perhaps.

Now the terminating character at the end of the message just has BIT 0 set to 1.

The print routine is now 31 bytes, CALLed with BC=message address, and DE= SCReen address (-1 from the Hi-byte)

Image

Code: Select all

;interleaved 3 bit data format for 64 column text
;using the actual data for the character instead
;of the character code
;BC=message address
;DE=SCReen address -1 from the Hi-byte
;messages terminate with BIT 0 of the second byte set
;all other letters MUST have BIT 0 as 0
;
;Arkannoyed March 2018
;
;31 bytes
;
org 0fa00h

          ld bc,msg
          ld de,3f00h
start:
          ld a,(bc)            ;get msg chr byte
          ld h,a
          inc bc
          ld a,(bc)
          ld l,a
          inc bc

          push de
lp0:
          inc d
          ld a,(de)
          or 10h
          add a,a
lp1:
          add hl,hl
          adc a,a
          jr nc,lp1
          
          ld (de),a

          bit 2,d
          jr z,lp0
          
          pop de
          
          add hl,hl
          ret c

          bit 1,c
          jr nz,start
          inc e
          jr start

msg:
        db %10110111,%11011010,%11110011,%01001110,%10010010,%01001110,%10010010,%01001110 ;HELL
        db %01110110,%11011100,%00000000,%00000000,%11101001,%00100100,%01110110,%11011100 ;O TO
        db %00000000,%00000000,%01110111,%11011010,%10010010,%01001110,%10010010,%01001110 ; ALL
        db %00000000,%00000000,%01110111,%11011010,%11101001,%00100100,%00000000,%00000000 ; AT
        db %01110001,%00011100,%11010111,%01001000,%11110011,%01001110,%01110010,%01000110 ;SPEC
        db %11101001,%00100100,%11010111,%01011010,%10110110,%11011100,%10111111,%11011010 ;TRUM
        db %00000000,%00000000,%01110010,%01000110,%01110110,%11011100,%10111111,%11011010 ; COM
        db %11010111,%01001000,%10110110,%11011100,%11101001,%00100100,%11101001,%00101110 ;PUTI
        db %11010110,%11011010,%01110010,%01010110,%01001001,%00000100,%00000000,%00000001 ;NG! 
        
Post Reply