Friday, March 13, 2020

New Hi-res Graphics for Commodore 64

[Author's Note: There is text to this blog post.  Be sure to also scroll down]
 
[Author's Note: There is text to this blog post.  Be sure to also scroll down]
Dust off that Commodore 64.  It's time to play with graphics old school. In the highest resolution available to your Commodore 64 -- 320x200 in beautiful monochrome and up to 16 colors (limited to two per 8x8 cell -- foreground and background).   That's more than twice the resolution of your first generation Palm Pilot, and more colors, so cool!


So what shall we draw first on our Commodore 64?  I vote for a circle.  Since I'm running the show here, I get to pick my favorite one sided two dimensional object.  Just a little trigonometry in play here.  Ah, takes me back to high school in 1982.  Good times!

10 REM HI-RES CIRCLE, DAVEVW.COM
20 COLOR 1, 15, 0, 14: REM GRAPHICS COLORS: LT GRAY ON BLACK, LT BLUE BORDER
30 HIRES 1 CLR: REM SWITCH TO GRAPHICS AND CLEAR
40 PI=3.1416: REM OR USE PI CHARACTER
50 R=90: REM RADIUS
55 C=1: REM COLOR
60 FOR A=0 TO 2*PI+PI/30 STEP PI/15: REM LOOP THROUGH ALL THE ANGLES AND MORE
70 X=R*COS(A)+160
80 Y=-R*SIN(A)+100
85 PLOT COLOR C
86 C=C+1:IF C=16 THEN C=1
90 IF A=0 THEN:PLOT 1,X,Y: REM PLOT POINT FIRST
100 IF A<>0 THEN:PLOT 1 TO X,Y: REM ALL OTHERS ARE LINES

110 NEXT


Pretty cool.  The code fakes a circle with 30 lines (see the different colors!) using SIN/COS to get the coordinates. (Hint: to get out blind type HIRES 0 and RETURN, or just make a syntax error and that will return to text as well.  Or use STOP+RESTORE, or power cycle as a last resort).

But what?  You don't have the COLOR, HIRES, PLOT keywords in your Commodore 64 BASIC?  Shucks, time to install HI-RES FOR C64.  Better yet, let's just dive in to learning the new keywords by launching LOADHIRES.

Insert your HI-RES FOR C64 disk.   I wish I had a time machine.  We could dial back to 1982 and look for it in your favorite computer retailer shop, or mail order house.  If it only existed then.  I probably could have sold this for something.

Except we are in the 21st century now.  We have Internet and everything.  You're not reading this on a BBS are you?   Just download the HI-RES FOR C64 disk image (open source!) and run in your favorite C64 emulator (VICE 3.3 r35872 or later recommended as that's what I'm running).  Or just copy to a floppy or such (SD for use with SD2IEC, pi1541, etc.) and run in your real C64 or C128.  (I personally use ZoomFloppy to transfer to my 1581 on 3 1/2" floppy to run on my C128[DCR].)


Hi-res is a software extension to Commodore I wrote over the course of about a year (June 2019 - March 2020) to continue my retro vibe, and close the loop on a project I had embarked on in the early 1980s.  I realized my dream!  Achievement completed.  Okay that is pretty priceless.

The keyword commands that you can learn about in the interactive documentation shown above, include:
HIRES
COLOR
PLOT
RECT
PATTERN
SHAPE


I'm not going to explain how to use them here.  Run the interactive documentation and learn there.  Move the cursor up and down, and press return for a demo or more information.  The demos show the capabilities of this hi-res system and utilize its keywords.

Now I'm going to use this remaining blog space to continue to rant about my Commodore programming memories...

Now I started on a PET at high school school.  And soon afterwards bought a VIC-20 for home with my own money.  I didn't get a Commodore 64 until about 1986, and a Commodore 128(DCR) in 1987.  With limited funds available prior to the C128, my only graphics capabilities was from purchasing a Super Expander with 3K RAM for my VIC-20.  While I was underwhelmed by some specifics of the Super Expander product (after shelling out about $60), having access to graphics was way cool and I did use it along with my math studies.  But then I outgrew BASIC programming in 1982 and branched into 6502 assembly.  I used HESMON to code 6502 machine language to develop a graphics package I could call into from BASIC using SYS commands.  I remember adding ability to parse commas and numbers to get arguments to my hi-res routines.

And since this was a VIC-20 and not a C64, there were no sprites to speak of.  So I wrote my own shape routines to copy portions of screen to and from memory.   And wrote my own character editor, and wrote my own routines for 40 columns text.  Unfortunately I haven't recovered any of those programs for tape and disk yet.  Here's hoping!  Finishing this project has been in the back of my mind for more than 35 years.

But I did one better.  I rewrote the high resolution package from scratch.  Well, actually I had some help starting out, so can't take all the credit (more on that later).  And this time targeted the C64 instead of the VIC-20.  Modern equipment and upgrades, you know!  Well, the C64 is a better more popular target for now, and has pretty good resources available (64K vs. 5K), except my VIC-20 Golden RAM 24K expansion board is laying around here somewhere.  But the VIC-20 isn't running.  So yeah, back to the C128 in 64 mode or more technically, the VICE emulator.

Okay, so Paul Soper posted on Reddit a link to his blog post of plotting a math function.  And I was in the retro mood so I ported the BASIC code he posted directly to machine code.  So I could pretty much replace the BASIC GOSUB routines with SYS commands.   The result was a little messy for passing values in A,X,Y registers, but it worked, and the graphics init and clear were much faster.  I posted the response to a comment in Reddit and on his blog.  Thanks again Paul!   And Paul credits the book The Graphics Book for the Commodore 64 as a source for his program, so thanks also to Abacus Software!

So to make a long story longer, I patched BASIC vectors to add the keywords.  This is not something I had accomplished in the 80s.  But with PDFs of Commodore manuals accessible at my fingertips to search and reference at whim, and more determination, and more senior engineering experience and confidence, I was able to accomplish the complete task in a professional and ideal manner.

Here are the successes of hi-res summarized:
  • supports graphics screens across the memory map (except zero page, and not where character rom gets in the way)
  • can switch between multiple graphics screens.  Supporting both hardware screens, and software swapped color tables, depending on addresses used.
  • default graphics screen is under KERNAL ROM
  • alternate graphics screen and color table is under BASIC ROM and I/O
  • So two screens without taking away any BASIC RAM!!!
  • machine code is from $C000-D423 (or thereabouts).  Utilizes more than 5K of RAM under I/O using banking, so not taking away any BASIC RAM.
  • Shape routines can copy any size portion of hi-res screen to/from RAM, and combine using GET/PUT/AND/OR/NOT/XOR.  This is leveraged to also support filling rectangular area with 8x8 pixel pattern, and plotting character strings to hi-res screen.
  • Hi-res patches SCRLEDIT in RAM so it will list the new tokens correctly.  Scroll up and down through your BASIC programs with F1/F7 using software I published in Compute!'s Gazzette.
  • assembly compiled using ACME.  Developing 6502 Assembly using Microsoft Visual Code editor, and builds into a running VICE instance.   And vice has built in machine language monitor with symbol table loaded built by ACME.   Very nice edit+build+test+debug cycle for development!!!  So glad not developing in the 80s anymore.
  • Machine language interface is also there.   Load up A/X/Y with correct values and JSR to $C000 as entry point for all the routines.  See source for details.
  • There are actual comments in the source code!  Gasp!  Don't worry, the BASIC interactive demo source is almost indecipherable in comparison.
  • Writing the assembly code was fun!
  • Writing the BASIC code to drive the demo was so much of a chore it wore on and dragged on for months.  Finally it is done.  I'm done with it too.  I'm sure it's done with me too.
Finally there is a joke screen (easter egg?) at the end of the interactive demo.   Cursor down to my website name, and press RETURN.  You will get a fun prompt.


It's up to you to find out what happens if you brave disagreeing with this statement.  Press y or n, it's up to you!

So what do you think of this?   What would you do different or add?  Having any troubles with it?  Do you want to know more of a particular aspect of this software?   Do you have a Commodore computer to dust off and get running again?  What was your favorite vintage computer?

Enjoy!

Links:

21 comments:

  1. Hi, this is very well done! I'm trying to figure out if this could be used as an extension to XC=BASIC (a BASIC cross compiler: https://xc-basic.net) and since you write it has an ML interface, I think it's very much possible. Now twe questions is what license is your work under, is it allowed to be reused in another open source project. Thanks

    ReplyDelete
  2. Sorry, now I see it's under the MIT license. My question is answered.

    ReplyDelete
    Replies
    1. Cool neils. I'm glad a couple of ya'll have checked out my github page. My blog post was a bit of a ramble, so to get as far down as the comments is quite an accomplishment!!! Congrats for your perseverance. I'll have to check out XC=BASIC too.

      Delete
  3. Thinking of some applications for this. Beautiful work, Dave.

    ReplyDelete
  4. It is really nice work, Dave.
    BUT: why reinventing the wheel? AND: How about more compatibility (of) standards? SYNERGY effect?
    Please, do consider convert it, making it compatible with DotBasic+.

    Because:
    1) Powerful DB+ is designed to be extended through extensions like yours, by using "modules" (it is how it works anyway). See page 72 of DB+ manual.
    2) HIRES, COLOR, PLOT or equivalents are already implemented there, in common with very interesting e.g. LINE, FILL, CLIP, OFFSET, that you did not provide (yet). There is much more,
    for example, mixing with loaded bitmaps in background, use parts of it at multicolor mode etc.
    (see "SOUND & GRAPHICS", "Grafstar", page 33 of DB+ manual).

    At least, I hope it could be used as extension for XC=BASIC (greetz to neils).

    There is only one possible problem and it is about licencing:
    Although DB+ is freeware + abandonware, it is not open sourced.
    However, I think it could be managed - authors (and possible copyright holders) are all nice chaps afaik.
    Worth a try.

    ReplyDelete
    Replies
    1. Thanks Crispin for your feedback. I've been out of the Commodore community for 28 years, just back a year and getting my feet wet. Thanks for the introduction to DotBASIC Plus, I hadn't heard of it yet.

      Here's the point of my whole project -- accomplish with some professional looking polish what I wanted to accomplish 38 years ago. Reinvent the wheel? Well, it's my wheel, I get to decide.

      I ran out of room in my memory map, and probably my steam, to do the FILL/PAINT command, but it would be great to do with patterns with the multiple/alternate buffer support so it's in the back of my mind if I figure out how to fit in more code without taking more from BASIC. PAINT or FILL will probably be the next command if I continue the project.

      As for LINE... there's PLOT TO equivalent already.

      More and more commands? Nah, that's not the point. I will probably post HOW to build in more commands. I am most interested in supporting the machine language programmer. BASIC programmers can definitely get a better package elsewhere.

      I am open to my work being encapsulated into something else or whatever. If I'm part of that, who knows? Things could change. Decisions and ideas can be dynamic.

      Actually I do like your response. I love having responses. And being challenged to think and communicate.

      Hopefully you've enjoyed the exchange and learned something in the process too. What's your favorite thing to create? What's your favorite language?

      Mine are utilities... tools... solving a problem, even if they're just my problems I'm making, or I'm the only customer. I like C# and next 6502 Assembly. Learning ACME assembler (at least enough to do the job) was way cool.

      Cheers!

      Delete
    2. Thank you for your quick replay.
      It is same here, almost 3 decades out of it, TheC64 Mini pull me back.

      > "I ran out of room in my memory map, and probably my steam, to do the FILL/PAINT command ..."
      You see, this is the point where DB+ differs from similar extensions: unlike Simons', yours and every other I am known of (aka "bunch of all" solutions), DB+ is cleverly designed in a way that you load only those modules (aka asm routines, commands, tokens) that you really need.
      Not just that: you can swap parts of memory from inside of your dBASIC program. It means that you can swap your actual routine to the other part of memory, to provide more space for something else. Of course, if your routine is coded to allow it.
      It is the smartest way to use that kind of extension, IMHO.
      It is still not full dynamic: you can't just "unload" modules, DB program has to be "compiled" already (preprocessed before), but it is the best we have, ever imo (...as pure BASIC v2 extension).
      Very smart, powerful, never seen elsewhere.
      This is why I fall in love with.
      Unfortunately, it is forgotten magic, mostly.
      This is why I am passioned to make it "rediscovered".

      Just to answer your question, I am not a coder at all, just a hobbyist and retro enthusiast. I do have knowledge of c64 asm, but not a practical one.
      Same stands for e.g. Python. I just can't catch enough time to learn it properly.
      My favourite language is - Forth, although I am far, far away to make something real useful from it.
      But I really like the concept: Forth is (or should be) the most natural way to join high level programming with bare metal / asm (aside of DB+ LOL).

      Right now, I am fiddling with smart "drawstring" coding (aka old vector type graphics) for DAAD/Illustrator. I think it is one of the most underrated technologies ever.
      Right now, I'm trying to implement "traveling salesman problem" aka TSP graphics, instead of very slow FILL routine. Same for some basic fractals. Very interesting, but it is too much complex to explain it here.

      It is nice to find some clever, open minded soul as you are, species that is under extinction.
      It was really nice to hear you.
      If you like, I am ready to share my peculiar projects and visions with you.

      ~All the best~

      Delete
    3. Dave, if you like challenges, imagine this tsp art as hires at C64 ;)
      https://wiki.evilmadscientist.com/TSP_art
      Actually, my idea is to replace fill / pattern fill with tsp art & simple fractal fill and/or peano curve, e.g. like this
      http://teachout1.net/village/fill.html
      https://en.wikipedia.org/wiki/Space-filling_curve

      Delete
    4. I kind of feel like this is cheating a little bit. The line may be a single line, but the stroke gets thicker and thinner throughout instead of just making a tighter pattern to make a darker image...

      Delete
    5. No, not with variable thickness of line: look at Evil Mad Scientist 1st example (Mona Lisa).
      Eve better one is zebra at
      "Generating TSP art from a stippled image"
      http://shop.emscdn.com/wiki/eggbot/tspart/zebras-svg.png
      Left pic is just one closed line, right is the same pic but with filled space.
      I already made some test conversions, it works and it looks great as C64 hires. ;)

      Delete
  5. Cool! I wrote my Down & Dirty Graphics Wedge for the C64 from the same inspiration. Yours graphic package looks fancier than mine.

    http://www.defiancestudios.com/2019/10/12/down-dirty-graphics-wedge/

    ReplyDelete
    Replies
    1. Ooo. I can appreciate the simplicity in parsing of your wedge. (As for fancy, I just got carried away -- I really tried to stop, but it was an obsession.) Thanks for sharing your project!

      Delete
    2. I was the same way... I just eventually ran out of memory for where I wanted the program to live.

      Delete
  6. Hi Dave!

    First of all I'd like to congratulate you for this great utility/hi-res BASIC add-on. I'd love to see some documentation or a simple reference manual of the included commands, as it would be great to have something that you can refer to at any moment when using the hi-res commands, instead of having to see the video once again!

    One other thing that concerns me is the amount of free memory left after the program is run. PRINT FRE(0)+65536 gives more than 70KB (!) of free RAM! How can one check how much memory is available?

    ReplyDelete
    Replies
    1. Thanks for the inquiry! Syntax documentation is on github, there's a quick link hidden at the end of the blog too. No BASIC RAM was sacrificed for this extension. I stole high RAM from $C000 (49152) onward, available RAM after ROM, RAM under I/O and RAM under the ROMs. So FRE(0) just works as FRE(0) does. Let me know if the syntax doc need any work.

      https://github.com/davervw/hires-c64/raw/master/docs/hi-res%20syntax.pdf

      Delete
    2. But SCRLEDIT grabs 1280 bytes, and the demos grab RAM for extra buffers too, so look out for that. To retrieve high BASIC memory claimed for buffers do POKE 56, 160: CLR

      Delete
    3. Thank you very much, Dave. Oh and congratulations for your highly interesting blog too!

      Delete
    4. Thanks Dony! And I forgot one more thing. The demos change the alternate hi-res screen's color table to use BASIC RAM, so that needs to be reset too. I will fix-up the demo soon, in the meanwhile:
      hires 1,57344,56320 swap 40960,55296
      or reset HI-RES use of addresses:
      poke 780,0:sys 49152
      (use either of these from a text screen, e.g. HIRES 0)

      Delete
  7. Interesting work, I'm studying it.
    I see your Plot code, and you could make it faster like this:

    ldy #0 ; 2 ; comput. dY
    sty ptrl ; 3 ; reset lobyte
    lda _Y ; 3 ; Y
    lsr ; 2 ; int(Y/2)
    lsr ; 2 ; int(Y/4)
    lsr ; 2 ; int(Y/8)
    sta ptrh ; 3 ; 256*int(Y/8) hibyte (lobyte=0)
    lsr ; 2 ; 128*int(Y/8) hibyte
    ror ptrl ; 5 ; 128*int(Y/8) lobyte
    lsr ; 2 ; 64*int(Y/8) hibyte
    ror ptrl ; 5 ; 64*int(Y/8) lobyte (= 320*int(Y/8) lobyte)
    adc ptrh ; 3 ; 256*int(Y/8) + 64*int(Y/8) hibyte
    sta ptrh ; 3 ; =320*int(Y/8) hibyte

    lda _Y ; 3 ; add (Y and 7)
    and #7 ; 2
    ora ptrl ; 3 ; lobyte [xx000xxx]
    sta ptrl ; 3 48

    lda _Xlo ; 3 ; dX + dY + BaseAddr
    and #248 ; 2
    adc ptrl ; 3
    sta ptrl ; 3
    lda ptrh ; 3
    adc _Xhi ; 3
    adc #>_VidMem ; 2
    sta ptrh ; 3 22

    Shorter and without loops.
    You could be even faster using a table for the Y offset.

    ReplyDelete