Compact 64 column print routine

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
utz
Microbot
Posts: 114
Joined: Wed Nov 15, 2017 9:04 am
Contact:

Re: Compact 64 column print routine

Post by utz »

Not the most pretty, but it's a Q I'd say:

Code: Select all

 * 
* *
* *
* *
**
 **
User avatar
utz
Microbot
Posts: 114
Joined: Wed Nov 15, 2017 9:04 am
Contact:

Re: Compact 64 column print routine

Post by utz »

Made a little font that fits completely in 6x3, just in case ;)

Image
User avatar
Alessandro
Dynamite Dan
Posts: 1908
Joined: Wed Nov 15, 2017 11:10 am
Location: Messina, Italy
Contact:

Re: Compact 64 column print routine

Post by Alessandro »

This is the font I designed for the copyright messages of the loading screens for my games. Feel free to employ it if you think it could be useful to you.

Image
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 »

Thanks guys, both those fonts look very nice. I did try making versions of the routine using CP and CPIR so that I could keep the longer tails of some of the letters, but they turned out pretty badly. They both total at 69 bytes, almost twice the size of the original routine, and still only end up saving 13 bytes overall with 96 chars.

Using CPIR:

Code: Select all

charloop:
    push hl         ; save screen pos

    dec ix          ; read string backwards
    ld a, (ix+0)    ; get char

    ld d, c         ; save length temporarily
    ld e, 6         ; assume char is 6px initially

    ld hl, check_table
    ld bc, 2        ; compare two chars
    cpir            ; check if char is Q or j

    jr nz, skip_inc_e
    inc e

skip_inc_e:
    ld l, check_table+2
    ld c, 5         ; compare five chars
    cpir            ; check if char is g p q y ,

    pop hl          ; restore screen pos
    push hl         ; save it again

    jr nz, skip_inc_h
    inc h

skip_inc_h:
    ld b, e         ; load counter for height
    ld c, d         ; restore length
    ld d, font_hi
    ld e, a         ; put character into e

    ; ... rest of code ...

check_table:
    db 'Q', 'j', 'g', 'p', 'q', 'y', ','
Using CP:

Code: Select all

charloop:
    ld d, font_hi
    push hl         ; save screen pos

    dec ix          ; read string backwards
    ld a, (ix+0)    ; get char

    ld b, 6         ; assume char is 6px initially

    cp 'g'
    jr z, inc_h
    cp 'p'
    jr z, inc_h
    cp 'q'
    jr z, inc_h
    cp 'y'
    jr z, inc_h
    cp ','
    jr z, inc_h

    cp 'Q'
    jr z, inc_b
    cp 'j'
    jr nz, skip_inc

inc_b:
    inc b
    jr skip_inc

inc_h:
    inc h

skip_inc:

    ; ... rest of code ...
I think that going 6x3 is the right option to choose here, might not be as readable but you can save up to 48 bytes. I wonder if anything could be done about the wasted zero bits in between the letters...
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 »

About wasted bits in the font data, what about sticking in a RES 4, (HL) at nextrow just after the font row has been written to the screen? This would ensure that only the first three bits of each character are printed, allowing for the spare bits to be used as flags for other code.
User avatar
utz
Microbot
Posts: 114
Joined: Wed Nov 15, 2017 9:04 am
Contact:

Re: Compact 64 column print routine

Post by utz »

djnzx48 wrote: Fri Feb 23, 2018 4:41 am About wasted bits in the font data, what about sticking in a RES 4, (HL) at nextrow just after the font row has been written to the screen? This would ensure that only the first three bits of each character are printed, allowing for the spare bits to be used as flags for other code.
That sounds like an excellent idea, though I don't have any great ideas on what to use those bits for, other than signaling vertical displacement.

Btw [mention]Alessandro[/mention] Man, that is a stylish font! Never noticed it before, but it's a very solid design.
User avatar
Alessandro
Dynamite Dan
Posts: 1908
Joined: Wed Nov 15, 2017 11:10 am
Location: Messina, Italy
Contact:

Re: Compact 64 column print routine

Post by Alessandro »

Thanks a lot [mention]utz[/mention], but your font is great too, and more flexible than mine - it's got lower case characters ;)

I also employ it for the language selection screen for the disk multi-language edition of several of my games. Here is the one from Sophia (notice my attempt at a Cyrillic variant):

Image
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Compact 64 column print routine

Post by RMartins »

Alessandro wrote: Mon Feb 26, 2018 1:56 pm Thanks a lot @utz, but your font is great too, and more flexible than mine - it's got lower case characters ;)

I also employ it for the language selection screen for the disk multi-language edition of several of my games. Here is the one from Sophia (notice my attempt at a Cyrillic variant):

Image
Nice language selection screen.
Is it really Portuguese, or Brasilian Portuguese ?

Is it just me, or the two top corners sprites, are not correctly aligned ?
I mean in the sense that the bottom ones, have the curly parts in an exact diagonal to each other.
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 »

That language selection screen looks good [mention]Alessandro[/mention]. I like the colour scheme; yellow and cyan are a combination that you don't see too often.

[mention]utz[/mention] I was thinking along the lines of using those spare bits whenever I needed a flag or something in another part of the code, not specifically the font routine. Although this does seem like a recipe for unmaintainable spaghetti code before long :)

I've discovered another few optimisations that can be made in the routine to get the size down. The first one is that the two decrements of the counter variable (DEC A & DEC C) can be combined into one, saving a byte, while the sign flag is used to check if there's any more to print. A side effect of this method is that you can't print more than 128 chars at a time, but the routine can't cope with screen thirds anyway so it's no major loss. Also if you call it with the counter set to 0, it exits without printing anything.

Code: Select all

charloop:
    ld d, font_hi   ; construct font address
    push hl         ; save screen pos

    dec c           ; any more chars?
    ret m           ; done
    ld a, c         ; number of chars left to print
    or a            ; clear carry for scroll
    rra             ; divide by two (64 chars to 32)
    add a, l        ; calculate new screen address
    ld l, a

    ld b, 6         ; loop 6 rows

    dec ix          ; read string backwards

if 1
    ld e, (ix+0)    ; get character
    srl e           ; check value of LSB
else
    db $DD, $CB, $00, $3B   ; ld e, srl (ix+0)
                    ; saves one byte and 4 Ts
                    ; Only use for temporary strings
                    ; (string becomes corrupted)
endif

rowloop:
    inc h           ; next screen line (skipping first row)
    ld a, (de)      ; get graphic
    rrd             ; rotate onto screen
    jr c, nextrow   ; done printing?
    rrd             ; rotate again into A
    ld (hl), a      ; display on screen
nextrow:
    inc d           ; next graphic
    djnz rowloop    ; loop for all rows

nextchar:
    pop hl          ; restore screen pos
    jr charloop     ; loop back round
Also, I realised that if the string buffer is aligned on a 256-byte boundary, the low byte of the string address will be equal to the number of bytes to print, since the string is being printed backwards. This allows the two registers to be combined so that BC is used for the address of the string, which eliminates the need for IX. However, BC must still be saved and restored before and after the inner printing loop, since B is also being used as the row counter. SRL A now appears twice, wasting two bytes, but if RRA was used the high bit would be corrupted by the carry flag. Because there is no LD E, (BC) instruction so the character has to be loaded into A first and then into E. So this optimisation ends up saving only one byte overall but it's still better than nothing.

Code: Select all

charloop:
    ld d, font_hi   ; construct font address
    push hl         ; save screen pos

    dec c           ; any more chars?
    ret m           ; done
    ld a, c         ; number of chars left to print
    srl a           ; divide by two (64 chars to 32)
    add a, l        ; calculate new screen address
    ld l, a

    ld a, (bc)      ; read string backwards
    ld e, a         ; get character
    srl e           ; check value of LSB

    push bc         ; save message address
    ld b, 6         ; loop 6 rows

rowloop:
    inc h           ; next screen line (skipping first row)
    ld a, (de)      ; get graphic
    rrd             ; rotate onto screen
    jr c, nextrow   ; done printing?
    rrd             ; rotate again into A
    ld (hl), a      ; display on screen
nextrow:
    inc d           ; next graphic
    djnz rowloop    ; loop for all rows

nextchar:
    pop bc          ; restore message address
    pop hl          ; restore screen pos
    jr charloop     ; loop back round
If the routine needs to be made even smaller, the print buffer can be arranged so that its address has the same high byte as the font address, with the font data placed after the print buffer in memory. This means that the PUSH/POP BC can be removed, and replaced with a LD B, D instruction just after LD D, FONT_HI. Using all these optimisations together, the routine can fit in only 32 bytes.
User avatar
Alessandro
Dynamite Dan
Posts: 1908
Joined: Wed Nov 15, 2017 11:10 am
Location: Messina, Italy
Contact:

Re: Compact 64 column print routine

Post by Alessandro »

Thanks for liking the screen fellas.
RMartins wrote: Mon Feb 26, 2018 9:54 pm Is it really Portuguese, or Brasilian Portuguese ?
Cannot really say, I am unable to distinguish between them because my knowledge of the language is basic to say the least. However, since the initial translations were kindly provided by Brazilian native speakers (Einar, Marcus Garrett Chiado), I guess it's closer to Brazilian, although I suppose the reforms and agreements achieved since 1990 made the two variants more similar than in the past.

But may I ask: why don't you read the documentation and play the games (Sophia, Al's Double Bill, Seto Taisho etc.)? This way you can discover it by yourself - and I hope you like them too ;)
RMartins wrote: Mon Feb 26, 2018 9:54 pm Is it just me, or the two top corners sprites, are not correctly aligned ?
I mean in the sense that the bottom ones, have the curly parts in an exact diagonal to each other.
The picture does not have 4:3 proportions, hence the slight misalignment, which is more evident here; when you watch it on a monitor/TV full screen, it's less noticeable.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Compact 64 column print routine

Post by RMartins »

Alessandro wrote: Tue Feb 27, 2018 8:06 am ...
RMartins wrote: Mon Feb 26, 2018 9:54 pm Is it just me, or the two top corners sprites, are not correctly aligned ?
I mean in the sense that the bottom ones, have the curly parts in an exact diagonal to each other.
The picture does not have 4:3 proportions, hence the slight misalignment, which is more evident here; when you watch it on a monitor/TV full screen, it's less noticeable.
I may have not explained myself well enough.
The top corner sprites, do not appear to be vertical flips of the bottom ones, hence the curly things, seem different.
User avatar
Alessandro
Dynamite Dan
Posts: 1908
Joined: Wed Nov 15, 2017 11:10 am
Location: Messina, Italy
Contact:

Re: Compact 64 column print routine

Post by Alessandro »

Now I understand what you mean. Mind you, I had not noticed that myself.

If you look again at the picture, I revised the "frame", also by adding an inner black line to make it stand out even more. (You might need to erase your browser cache before reloading the page to see the new picture.)

However I won't be adding it to my already existing multi-language files, that would mean uploading them again, then updating the SC database, and it's not worth the hassle. I will use the new "frame" with the next releases and updates.

Now, will you actually play the games? ;)
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Compact 64 column print routine

Post by RMartins »

Alessandro wrote: Tue Feb 27, 2018 4:37 pm ...

Now, will you actually play the games? ;)
Nice ...

Fixing that, was not a pre condition for me playing the game :)

I usually keep a list of recently released games, so that when I have some free play time, I can try them.
It's always good to see what others have come up with, either to improve our own game design skills, or learn new tricks, while enjoying playing Spectrum :)
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 »

I like the creative use of RRD/RLD. I just wish they were faster instructions!

Anyway, I thought I'd throw my hat into the ring sort of thing.

I use a method of encoding the characters that stores vertical lines, then adding a vertical 'space' between each character.

Its a similar way to how I store the font in my proportional scroller.

So, routine needs HL with screen address and BC with the message address when CALLed.

the combined print routine and 74 character 'font' based upon the one posted earlier here, is 210 bytes currently, but could be optimised probably a little more.

Certainly slower though.

Image

Code: Select all

org 0fa00h

direct_dat:
          db 19h,25h,3fh,25h,19h,25h,19h,7dh,19h,7dh,51h,41h,79h,05h,7dh,11h
          db 7dh,31h,7dh,25h,19h,25h,3dh,51h,3dh,31h,3dh,21h,1dh,7dh,55h,29h
          db 55h,29h,29h,29h,39h,45h,45h,79h,05h,79h,7dh,45h,39h,45h,5dh,7dh
          db 55h,45h,7dh,45h,7dh,05h,05h,7dh,11h,6dh,11h,6dh,7dh,41h,3dh,0dh
          db 3dh,43h,01h,43h,3dh,39h,45h,39h,05h,3dh,7dh,51h,21h,55h,39h,05h
          db 39h,55h,39h,55h,09h,39h,4dh,35h,7dh,51h,2dh,11h,2dh,35h,25h,55h
          db 49h,41h,7dh,41h,55h,21h,61h,1dh,61h,01h,61h,4dh,55h,65h,19h,25h
          db 25h,19h,2dh,35h,01h,3dh,51h,1bh,2bh,3dh,19h,25h,7dh,21h,1dh,01h
          db 5dh,01h,1dh,21h,13h,5dh,01h,79h,25h,15h,35h,29h,3bh,0bh,3dh,4dh
          db 55h,25h,45h,55h,29h,71h,11h,3dh,75h,55h,49h,4dh,51h,61h,01h,75h
          db 01h,05h,01h,25h,01h,01h,01h,03h,05h,11h,11h,11h,39h,11h,7dh,11h,2dh

          ;177 bytes CHR set

          ;A=16,B=1d,C=24,D=2a,E=2f,F=09,G=2c,H=0e,I=31,J=25,K=37,L=34,M=10,N=3c,O=45,P=4a,Q=55,R=58,S=5e,T=61,U=0c,V=27,W=07,X=39,Y=66,Z=6b
          ;a=14,b=12,c=6e,d=7a,e=71,f=74,g=77,h=7c,i=7f,j=84,k=b0,l=0b,m=18,n=1a,o=04,p=02,q=00,r=81,s=89,t=86,u=47,v=4e,w=3e,x=5a,y=8c,z=5c
          ;0=50,1=33,2=8f,3=92,4=95,5=98,6=52,7=9b,8=1f,9=4c
          ;!=9e,"=68,.=a0,,=a6,:=a2,+=ab,-=a9,(=40,)=42,==21,?=63,SPC=a4

start:
          ld d,0fah             ;Hi-byte of CHR set+ EOM marker
s_rpt:
          ld a,(bc)             ;get CHR code
          ld e,a                ;CHR code is x3 to save having to do it in routine
          cp d                  ;SUB 0FAh, use D reg value to mark the string end
          ret nc                ;RET if 0FAh detected
          push bc               ;save MSG position
          ld b,04h              ;counter

          ld a,01h              ;set space line with end marker
pr_lp0:
          and a                 ;clear Carry
          ld c,h                ;save SCReen position
init0:
          inc h
          rl (hl)               ;bit into (HL)
          add a,a               ;next data BIT
          jr nz,init0           ;repeat if not 00

          ld h,c                ;restore SCReen address
          ld a,(de)             ;get data byte
          inc e                 ;next
          djnz pr_lp0           ;next line

          pop bc                ;restore MGS address
          inc bc                ;next CHR byte
          ld a,c                ;check
          and 01h               ;mask BIT 0
          add a,l               ;add result to L
          ld l,a                ;INC 1 or 0
          jr s_rpt              ;next CHR rpt.
          
target:
          ld hl,3f00h           ;SCReen address
          ld bc,message         ;MSG address
          call start
          ret
          
message:  ;example message 'Hi To All At Spectrum Computing'
          db 0eh,7fh,0a4h,61h,04h,0a4h,16h,0bh,0bh,0a4h,16h,86h,0a4h,5eh,02h,71h,6eh,86h,81h,47h,18h,0a4h,24h,04h,18h,02h,47h,86h,7fh,1ah,77h,0fah
I'll have a further faff around with the character map and see if I can gain a few more bytes 8-)
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Compact 64 column print routine

Post by Nomad »

That is all kinds of awesome. :lol:
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 »

Ah nice, so you basically store the font 'sideways' and draw it column by column. Solves the problem of wasted gaps in between letters, and a simple AND could be used to mask off the unused top and bottom pixels to use them for other stuff. Having to preprocess the text before printing is a downside but at least it gives you an easy way of checking whether L needs to be incremented or not. I'll definitely be giving your routine a closer look.
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 »

Bit 0 of each data byte is set as and end market for the print loop. Whereas we could use 3 bytes for each character, there are some that can be found within the data as a sort of bonus. As we’re only addressing the data within a 256 byte area, there’s the possibility to use direct address lo-bytes as the character codes. With some additional manual rearrangement of the data, I managed to save 45 bytes. I’m sure with some more tweaking I could more efficiently pack the data and find a few more matches within it, saving even more.

The way it decides when to inc to the next screen byte is a bit crude. We check the message position and inc to the next right byte when it’s on an even byte. There might be a better way to do it, I haven’t found one....yet.

So the main routine is 33 bytes and can manage to print within screen thirds, so could potentially do 512 characters at once.
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 »

I knew there was a better way of deciding when to increment the screen address. Really its obvious!!

If we just /2 (SRA L) the screen address, then we divide the Lo-byte by 2, as we've 2 characters per byte printed.

The only downside is that we can now only print 256 characters in a single string, but thats still 4 lines of continuous text, so probably not much of a problem.

So now down to 31 bytes! :D

Code: Select all

start:
          ld d,0fah             ;Hi-byte of CHR set+ EOM marker
s_rpt:
          ld a,(bc)             ;get CHR code
          ld e,a                ;CHR code is x3 to save having to do it in routine
          cp d                  ;SUB 0FAh, use D reg value to mark the string end
          ret z                ;RET if 0FAh detected
          push bc               ;save MSG position
          ld b,04h              ;counter

          ld a,01h              ;set space line with end marker
pr_lp0:
          push hl
          sra l
          and a                  ;clear Carry
init0:
          inc h
          rl (hl)               ;bit into (HL)
          add a,a               ;next data BIT
          jr nz,init0           ;repeat if not 00

          pop hl                ;restore SCReen address
          ld a,(de)             ;get data byte
          inc e                 ;next
          djnz pr_lp0           ;next line

          pop bc                ;restore MGS address
          inc bc                ;next CHR byte
          inc l                 ;next SCR addr
          jr s_rpt              ;next CHR rpt.
Bizzley
Microbot
Posts: 124
Joined: Thu Nov 16, 2017 10:47 am

Re: Compact 64 column print routine

Post by Bizzley »

Copied and Pasted your latest change and with a message string that is an odd length in size (like the example message used previously) the last character is printed in the wrong place. This might be down to my bad typing but can you check it out? Ta.
"He made eloquent speeches to an audience consisting of a few depressed daffodil roots, and sometimes the cat from next door."
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 »

Yes, in cases where the last character gets spaced apart from the rest of the text, then add a space at the end (code A4h in this case), before the terminating code (FAh)

Sorry, should've mentioned that! :o
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 »

Should also mention that you can of course change the address where the code is, and as long as the CHR set is within a 256 byte window, it doesn't even have to start at xx00.

The D register holds the CHR set Hi-byte and is also the message end marker. So any messages must end with whatever value D holds.
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..30 bytes!

If we replace the B,04 loop, therefore getting rid of the need for Push/Pop BC, we can rather cheekily use the top line of the character square, as its not printed on, to temporarily store the counter, just doing a DEC (HL) with each pass.

I do however now need to refactor the CHR set, and move everything left one BIT to make it work, but thats not too much hassle.

Code: Select all

start:
          ld d,0fah             ;Hi-byte of CHR set+ EOM marker
s_rpt:
          ld a,(bc)             ;get CHR code
          ld e,a                ;CHR code is x3 to save having to do it in routine
          cp d                  ;SUB 0FAh, use D reg value to mark the string end
          ret z                 ;RET if 0FAh detected
          ld (hl),04h

          ld a,01h              ;set space line with end marker
pr_lp0:
          push hl               ;save HL  SCReen address
          sra l                 ;/2 L
          and a                 ;clear Carry
init0:
          inc h
          rl (hl)               ;bit into (HL)
          add a,a               ;next data BIT
          jr nz,init0           ;repeat if not 00

          pop hl                ;restore SCReen address
          ld a,(de)             ;get data byte
          inc e                 ;next
          dec (hl)
          jr nz,pr_lp0

          inc bc                ;next CHR byte
          inc l                 ;next SCR addr
          jr s_rpt              ;next CHR rpt.
Might struggle to save any more bytes! :cry:
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 updates CHR set code

Code: Select all

direct_dat:
          db 31h,49h,7dh,49h,31h,49h,31h,0f9h,31h,0f9h,0a1h,81h,0f1h,09h,0f9h,21h
          db 0f9h,61h,0f9h,49h,31h,49h,79h,0a1h,79h,61h,79h,41h,39h,0f9h,0a9h,51h
          db 0a9h,51h,51h,51h,71h,89h,89h,0f1h,09h,0f1h,0f9h,89h,71h,89h,0b9h,0f9h
          db 0a9h,89h,0f9h,89h,0f9h,09h,09h,0f9h,21h,0d9h,21h,0d9h,0f9h,81h,79h,19h
          db 79h,85h,01h,85h,79h,71h,89h,71h,09h,79h,0f9h,0a1h,41h,0a9h,71h,09h
          db 71h,0a9h,71h,0a9h,11h,71h,99h,69h,0f9h,0a1h,59h,21h,59h,69h,49h,0a9h
          db 91h,81h,0f9h,81h,0a9h,41h,0c1h,39h,0c1h,01h,0c1h,99h,0a9h,0c9h,31h,49h
          db 49h,31h,59h,69h,01h,79h,0a1h,35h,55h,79h,31h,49h,0f9h,41h,39h,01h
          db 0b9h,01h,39h,41h,25h,0b9h,01h,0f1h,49h,29h,69h,51h,75h,15h,79h,99h
          db 0a9h,49h,89h,0a9h,51h,0e1h,21h,79h,0e9h,0a9h,91h,99h,0a1h,0c1h,01h,0e9h
          db 01h,09h,01h,49h,01h,01h,01h,05h,09h,21h,21h,21h,71h,21h,0f9h,21h,59h

          ;177 bytes CHR set

          ;A=16,B=1d,C=24,D=2a,E=2f,F=09,G=2c,H=0e,I=31,J=25,K=37,L=34,M=10,N=3c,O=45,P=4a,Q=55,R=58,S=5e,T=61,U=0c,V=27,W=07,X=39,Y=66,Z=6b
          ;a=14,b=12,c=6e,d=7a,e=71,f=74,g=77,h=7c,i=7f,j=84,k=b0,l=0b,m=18,n=1a,o=04,p=02,q=00,r=81,s=89,t=86,u=47,v=4e,w=3e,x=5a,y=8c,z=5c
          ;0=50,1=33,2=8f,3=92,4=95,5=98,6=52,7=9b,8=1f,9=4c
          ;!=9e,"=68,.=a0,,=a6,:=a2,+=ab,-=a9,(=40,)=42,==21,?=63,SPC=a4
30 bytes +177 = 207 bytes

Enjoy
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 »

Well, looks like my routine's become obsolete already! :lol: That's some impressive stuff there; I didn't realise at first glance that you were interleaving the font bytes of the characters together to save space. One thing though, since L is being divided by two won't that affect both the X and Y coordinates of the screen address, causing the text to be drawn in the wrong place? Additionally the counter looks like it corrupts random parts of the screen as it's using the normal value of L, not the halved value that is being drawn to. Maybe an additional PUSH/POP HL and a SLA L on entry could be added to compensate?
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 »

As far as I can see, there isn't any screen corruption, but you may have tested it more fully than I have.

The screen address Lo-byte is halved for printing the actual characters, but restored afterwards.

You are right though, in the 30 byte version, it may cause corruption elsewhere, so probably in most cases, using B as the counter is safer, therefore 31 bytes.

There may yet be a way to achieve a smaller routine, as I've another data structure to investigate.

The CHR data is treated sort of as a 'pool' to dip into at any point. With no spaces to worry about, as they're added by the routine, it gives rise to that flexibility.
Post Reply