Nice text

Basic and Machine Language

Moderator: Moderators

Kakemoms
Vic 20 Nerd
Posts: 740
Joined: Sun Feb 15, 2015 8:45 am

Nice text

Post by Kakemoms »

Nice text for me is when it is readable and not too blocky. It may be a subjective thing.

What I am trying to do is to make 5-bit wide characters. "T" and other elements look ugly in 4-bit, so I want something that is symmetric. 3-bit won't do for "M". I may consider to do variable width later, but for now I want 5-bit. One needs 1 bit of space, so it means 6-bits characters. Its easy to get them from character ROM:

POKE B,(PEEK(A) AND 112)*2 OR (PEEK(A) AND 14)*4

Or something like it. You get the idea. 4 "new" 6-bit characters will go into 3 "old" 8-bit. In total 29 columns.

Now, to print those 6 bits I will simply fill the screen with the character set 22*5=110 and use an interrupt to shift the character ROM between 4 locations on the screen. The last lines of the screen will be left open (I know I can use the cassette buffer to utilize some of it, but I leave that for later).

I can't do everything in assembler (I will only make an INITALIZE and a new PRINT command there), so I also want the BASIC available. I have a 32K expansion, so memory is no problem. I will use the RS232 port.

The question is: were is the best place to put the CHAR maps?
Kakemoms
Vic 20 Nerd
Posts: 740
Joined: Sun Feb 15, 2015 8:45 am

Re: Nice text

Post by Kakemoms »

Ok, no reply yet so I will try to elaborate:

I can put the CHAR maps at 4096, 5120, 6144 and 7168 which is the most obvious:

127 characters in each map.

Fill first 5 lines with 22 characters each, e.g. 110 characters.

The 6th line will have 17 characters, so the last 5 will be A,B,C,D,E. In order for that to work, I will put up an interrupt that fills char 1-5 while the display shows line 2-5 (e.g. location is 4096-4135, 40 bytes). It will take 1000/50th*4*8/321=1.99ms. At 1MHz that is about 2000 clock cycles, so if I do it with:

STX #0
loop:
LDA 4096,x
STA 828,x
LDA (828+40),x
STA 4096,x
INX
CPX #39
BNE loop

Cycles according to http://6502.org/tutorials/6502opcodes.html:
LDA (5 cycles) + STA (5 cycles) + LDA (5 cycles) + STA (5 cycles) + INX (2 cycles) + CPX(2 cycles) + BNE (3 cycles) = 27 cycles * 40 bytes =1080 cycles.

For the next char map (5120) I will need to do the same while copying back the bytes in 4096-4135, so that would be 2160 cycles which is too slow. A less memory-preserving way is to only copy the bytes TO the chars and manipulate them in the 828-1023 area:

STX #0
loop:
LDA 828,x
STA 4096,x
INX
CPX #39
BNE loop

LDA (5 cycles) + STA (5 cycles) + INX (2 cycles) + CPX(2 cycles) + BNE (3 cycles) = 17 cycles * 40 bytes =680 cycles.

Which will execute in 1360 cycles during the 5120 char map display.

For each char map we will need 80 bytes to store the CHAR1-5 twice. The cassette buffer 828-1019 contains 192 bytes which is enough for 2 CHAR maps. The third will go elsewere.

Now we also need the screen memory somewhere, so I will need to put it to 7680. I only need 6 lines of CHARS (22*6=132 bytes) as I can move the screen position around during update. That leaves 7168-7679 and 7812-8191 for CHAR mem (64 + 47 characters) . We can use this for 5 lines (110 chars).

In total this gives 6+6+6+5=23 lines on the screen and 29 columns. And some time to BASIC execution as well.

Comments?
User avatar
majikeyric
Vic 20 Afficionado
Posts: 349
Joined: Fri Oct 24, 2014 2:08 pm
Website: http://majikeyric.free.fr
Location: France

Re: Nice text

Post by majikeyric »

Kakemoms wrote:STX #0
You mean : LDX #0

STX #immediate doesn't exist.
User avatar
tokra
Vic 20 Scientist
Posts: 1120
Joined: Tue Apr 27, 2010 5:32 pm
Location: Scheessel, Germany

Re: Nice text

Post by tokra »

Kakemoms wrote:Now we also need the screen memory somewhere, so I will need to put it to 7680. I only need 6 lines of CHARS (22*6=132 bytes) as I can move the screen position around during update. That leaves 7168-7679 and 7812-8191 for CHAR mem
Just giving this a quick glance, but what you try here won't work. If you move the screen position down during updates video-RAM will still be read continously. So if you want 22*23 video-RAM positions for your 6 bit-wide 29 columns of 23 chars you will still need 506 bytes in video-RAM.

If you want 6 bit-wide chars I would suggest mapping a full bitmap screen with 480 bytes at 192x160 pixels (=24*20=480 VIC-chars) for 32 characters (6-bit) per line and 20 lines. No interrupts and on-the-fly shifting necessary if you use double-height chars. You can put 240 8x16 chars at $1000 and have room for the 240 8x16 char-rom from $1100-$1fff.

If you want to retain BASIC-interoperability to some degree, some years back Mike and I got a 208x208 pixel-mode to work with on-the-fly updates:

http://sleepingelephant.com/ipw-web/bul ... php?t=4532
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Nice text

Post by Mike »

Kakemoms wrote:Comments?
Kakemoms,

It might just be appropriate to point you to a number of threads, that should give you a good read over this weekend. Especially when it comes to the basics of putting a bitmapped screen on display with the VIC-20:

o 'MINIGRAFIK batch processing suite',

o 'A round-up of all known VIC-I display modes', and

o 'New Frontiers in VIC-Hires-Graphics Series'.

Taking those for granted, for text display applications I once wrote this set of routines ...

o 'MG BROWSE, a 40 column ASCII text viewer'

... using this 4x8 pixel ASCII character set I designed myself:

Image

As you see, I had no issues providing a 'M' with this font. If anything, today I'd re-think the design of the letter 'r', and there's simply no good way to draw the letter 'z' in this typeface: I reduced the height of the capital letters to 6 pixels for a better line spacing, and the lower case letters are 4 pixels, save for ascenders and descenders. I just had to compromise on 'g', 'p', 'q' and 'y'.

But overall, I'm quite happy with this font. As for readability, just judge for yourself from this number of applications, where the font was used as main font in a program, within READ MEs on disk, and showing large excerpts of The Bible:

o 'MINIPAINT 1.2',

o 'Happy Easter from Mike and Orion! Here's our gift...',

o 'WIP: Vic GUI',

o 'MAXIGRAFIK: 208 x 256 true, high-resolution graphics!',

o 'Merry Christmas from Mike and Orion! Here's a gift for you.',

o 'MG Text Edit', and

o 'New Release: Mike's unexpanded type-in collection'.


That being said, you first should implement a working bitmap mode, maybe 192x160 as tokra suggested; then design a nice 6 pixel wide font; and finally write the code to display this font on screen.
Kakemoms
Vic 20 Nerd
Posts: 740
Joined: Sun Feb 15, 2015 8:45 am

Re: Nice text

Post by Kakemoms »

tokra wrote:
Kakemoms wrote:Now we also need the screen memory somewhere, so I will need to put it to 7680. I only need 6 lines of CHARS (22*6=132 bytes) as I can move the screen position around during update. That leaves 7168-7679 and 7812-8191 for CHAR mem
Just giving this a quick glance, but what you try here won't work. If you move the screen position down during updates video-RAM will still be read continously. So if you want 22*23 video-RAM positions for your 6 bit-wide 29 columns of 23 chars you will still need 506 bytes in video-RAM.

If you want 6 bit-wide chars I would suggest mapping a full bitmap screen with 480 bytes at 192x160 pixels (=24*20=480 VIC-chars) for 32 characters (6-bit) per line and 20 lines. No interrupts and on-the-fly shifting necessary if you use double-height chars. You can put 240 8x16 chars at $1000 and have room for the 240 8x16 char-rom from $1100-$1fff.

If you want to retain BASIC-interoperability to some degree, some years back Mike and I got a 208x208 pixel-mode to work with on-the-fly updates:

http://sleepingelephant.com/ipw-web/bul ... php?t=4532
Very interesting. I took your advice and implemented double height char with screen map at 4096. The idea was 22 columns and 22 lines, which means that I have 2048-484=1564bytes (=97 16-bit "chars") which is 4 lines of double height characters + 6144-8191 which is 6 lines of double height characters. I miss 4 char for that last line, so I copy them into "@ABC" characters before they get displayed. That gives me 160 pixel-lines and I can stop the interrupt about half way down the screen. As you point out, I could contine to copy data into the other characters to add more pixel-lines, but that would reduce time for BASIC programs. I might use the extra two columns (which there is enough space for in first char set) and add 12 more chars to be copied. That gives the 192*160 bitmap with an acceptable speed for BASIC. The cassette buffer have space for another 8 pixel-lines, but it will slow the BASIC (and give me a non-contineous bitmap).

It was nice to implement this myself in order to understand the different aspects of the mapping method. I have worked with programming for 34 years now, and I am astonished with how much fun 8-bit programming still is. My other side-project is on the Amiga and 680x0 emulation in FPGA, so I am wondering how small the FPGA code would be if one implemented a full Vic-20. It is still the largest sales/(no of logic gates) computer ever made, which is very interesting.

Edit: I forgot that using double height characters means that I only need 10 lines for the full screen. With 24 columns (192 bit wide) it gives me another 256 bytes of CHAR mem after 4335. I will need 24 of those for the extra screen line, so 232 bytes are left. That is 14 double-height characters. By copying the remaining 10 characters (as done in the lower part of the screen) I can get this to 192*176 without consuming more CPU cycles. Now, to make the bitmap contineous, I can instead copy the 160 bytes of the lower part of the screen at the start of the interrupt, once the first two lines have been displayed (4096-4120). E.g. it will give me a contineous bitmap from 4176 to 8383 outside of the screen interrupt. That should make character drawing fast.

Edit2: I can use a 4096-8320 bitmap instead. It will only require copying of screen map & move its location + few bytes. E.g. 24*11= 264 bytes (for 192*176) + remap 8*16 bytes (128 bytes). Total manipulation is then 392 bytes (twice). The shortest time to do this is (but not very memory conserving):

2 LDX #0
4 LDA 7680
4 STA stor0+1
4 STX 7680
2 INX
4 LDA 7681
4 STA stor1+1
4 STX 7681
... and so on

2 stor1 LDA #00
4 STA 7680
2 stor2 LDA #00
4 STA 7681
... and so on

E.g. 20 cycles/byte * 264 bytes = 5280 cycles.

The remap requires LDA & STA both ways, so 22 cycles/byte * 128 bytes = 2816 cycles

That leaves 63% of the CPU time for other things and gives a continuous bitmap for fast drawing of characters.
Last edited by Kakemoms on Sat Aug 01, 2015 3:12 pm, edited 4 times in total.
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Nice text

Post by Mike »

You just *don't* need any interrupts to implement the resolution of 192x160 pixels!

All that needs to be done is:

- set the display window to 24 columns and 10 rows of double-height characters,
- set both text screen and character base to $1000, and
- fill the text screen with all characters 16 .. 255.

This way, the text screen only needs 240 bytes from $1000 to $10EF, and the bitmap starts at $1100 and ends at $1FFF.

...

The bitmap of MINIGRAFIK is implemented exactly the same way, using 20 columns and 12 rows instead.

...

Please take the time to read the threads I suggested, before you continue to propose techniques that might well work on other machines, but aren't usable or at least rather inconvenient, when there exist easier and - especially! - working solutions for the VIC-20.
Kakemoms
Vic 20 Nerd
Posts: 740
Joined: Sun Feb 15, 2015 8:45 am

Re: Nice text

Post by Kakemoms »

Mike wrote:You just *don't* need any interrupts to implement the resolution of 192x160 pixels!
Please take the time to read the threads I suggested, before you continue to propose techniques that might well work on other machines, but aren't usable or at least rather inconvenient, when there exist easier and - especially! - working solutions for the VIC-20.
You probably miss the point here. Interaction is the way to learn and see things differently, so even if I mostly do it the same way you have done it, there might be point at which I do things differently. If you find my solutions inconvenient, that is your problem not mine.
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Nice text

Post by Mike »

Then, go ahead! :lol:

Ultimately, it's your own program running on the VIC-20 which will prove or disprove your ideas.
Kakemoms
Vic 20 Nerd
Posts: 740
Joined: Sun Feb 15, 2015 8:45 am

Re: Nice text

Post by Kakemoms »

Mike wrote:Then, go ahead! :lol:

Ultimately, it's your own program running on the VIC-20 which will prove or disprove your ideas.
Oh, I already tested it. Works but needs optimization. I will post a link to the program once I finish it.
Kakemoms
Vic 20 Nerd
Posts: 740
Joined: Sun Feb 15, 2015 8:45 am

Re: Nice text

Post by Kakemoms »

Well, if any of you are interested (probably not), I am finished with the IRQ routine and it works as such:

I have 25 columns (8 bit)* 11 lines (16-bit), so 200x176 pixel resolution.

The"bitmap" memory for the screen is from 4096-8495. Writing to it requires timing routines in the interrupt, so I am implementing them now.

To get a contineous bitmap from 4096-8495 without sacrificing kernal & basic I move the character (CHAR) map:

1) Start by putting CHAR map to 7680
2) Store 7680-7729 bytes (two lines) into LDA statements
3) Write CHAR map data to 7680-7729
4) Store 4121-4370 bytes (10 lines) into LDA statements
5) Write CHAR map data to 4121-4370 AFTER pixelline 16 has finished
6) Move CHAR map to 4096 at pixelline 30-31. The second line will start to display (I have one line overlap between the two CHAR maps to prevent flicker - can probably be removed, but is still there)
7) Restore 7680-7729 bytes
8 ) The last line of the screen contains 19 doubleheight characters which are the same as start of line two of the screen (4496-4799), so store these into LDA statements
9) Copy bytes 8192-8495 into 4496-4799
10) After the CHAR map has been drawn; restore 4121-4370 and 4496-4799

This uses about 60% of the CPU in addition to the VIC, so rather CPU intensive. I divided the screen into 3 irq timings, e.g the interrupt kicks in three times per screen update which I call IRQ1, IRQ2 and IRQ3.

After 10) I can handle the 4096-8495 area as a contineous bitmap (end of IRQ3)
There is some time between 7) & 8 ) (end of IRQ1) in which I can handle bytes in the 4096-4121, 4371-8495 area.
There is also some time between 9) & 10) (end of IRQ2) in which I can handle bytes in the 4096-4121, 4371-4495 and 4800-8495 area.

So for copying bytes around the screen I call an external routine who sets parameters (from, to, number of bytes). The copying is in the IRQ routine and it takes about 24 rasterlines to copy 100 bytes, so I can get about 500 bytes/screen update or around 25KB/second. Copying things in the 4496-4799 and especially 4121-4370 is slower due to the limitations.

I hope to improve it further. It retains one contineous bitmap and does not break Basic/kernal, but requires 5K+ of memory for the program & storage. The next step is to replace the PRINT command.
Kakemoms
Vic 20 Nerd
Posts: 740
Joined: Sun Feb 15, 2015 8:45 am

Re: Nice text

Post by Kakemoms »

A little update:

The bitmap implementation of dual heigh characters gave me a little headache as I needed to implement a special copy routine for moving single textlines (e.g. 8-bit high characters). I have implemented this in the following way:

copybytes from, to, length, step, blocklength

I pass the parameters to the routine via the stack and it gets from address, to address and length as you would for any routine to copy bytes from one location to another. The two other parameters "step" and "blocklength" are what makes it possible to copy selected bytes from one place to another. The routine will copy "blocklength" number of bytes, then jump over "step" number of bytes and copy next "blocklength" number of bytes.. and so on.. until length has been reached.

In that way I can scroll the whole screen with two variations on the call to the copy command. For example scroll one line up will be:

Copybytes 4096+8,4096,16*25,8,8 (move second line up to top line)
Copybytes 4096+16*25,4096+8,16*25,8,8 (move third line up to second line)
and so on...

As for previous copycommand, the actual copying is called in cycles from the IRQ routine so that it does not interfere with the display. I had to slow down the copy routine a little to allow for the step-vise copy, but it still performs with about 350-450 bytes per screen update. Thus it takes less than half a second to scroll all lines up or down. That should be useable for a text editor, but I hope to optimize it later (once everything is finished).

The actual code is less than 2K byte, but the screen buffer currently takes more than 8K byte due to the LDA+STA implementation of rewriting different areas. This can be reduced quite alot if I make a version that allow slightly more time for the screen. E.g. instead of a contineous:

LDA $1000
STA $4000
LDA $1001
STA $4001
and so on... which is 8 cycles/byte, but also 6 bytes per store byte.
For manipulating the 574 bytes that my screen currently needs, this routine takes over 3K byte of memory!

One can use
LDA $1000,X
STA $4000,X
LDA $1001,X
STA $4001,X
and so on... which is 10 cycles/byte + increment and branch loop code:
DEX
DEX (or a SBC if we have many lines)
BNE top

More lines in the lower code segment will get us closer to the 10 cycles/byte speed.
FD22
Vic 20 Hobbyist
Posts: 148
Joined: Mon Feb 15, 2010 12:31 pm

Re: Nice text

Post by FD22 »

You should definitely do some background reading on this topic - others here have done or are doing similar things.

Keep plugging away - maybe you'll surprise everyone with something that hasn't been seen before.
User avatar
tokra
Vic 20 Scientist
Posts: 1120
Joined: Tue Apr 27, 2010 5:32 pm
Location: Scheessel, Germany

Re: Nice text

Post by tokra »

FD22 wrote:You should definitely do some background reading on this topic - others here have done or are doing similar things.
Is your VIC++ or FAST-40 still being developed? Updates were kind of sparse recently. I can understand Kakemoms and you wanting to learn and experience the ins-and-outs of VIC-graphics for yourselves without too much outside influence, even while I enjoy reading the in-between-posts. But be prepared for constructive criticism :-)
FD22
Vic 20 Hobbyist
Posts: 148
Joined: Mon Feb 15, 2010 12:31 pm

Re: Nice text

Post by FD22 »

I went into 'bunker mode' regarding updates on FAST-40 - but silence doesn't mean inactivity! :D 2014/15 have been tough years (due to a bereavement) and I haven't had as much time to work on stuff at home as I did a year or two before that. I promise to post an update soon though.

VIC++ is a much more complex project than FAST-40 and I'm unlikely to return to it in the foreseeable future. Maybe once I've completed my Mathematics degree I'll have enough time and mental capacity to resurrect it - provided I stick to the OU timetable I should graduate in 2018, roughly on my 50th birthday!
Post Reply