Sunday, January 17, 2021

How to Build Vice 3.5 (x64sc, etc.) on Raspberry Pi 400

Raspberry Pi 400

The Raspberry Pi 400 invokes a sense of nostalgia back to the all-in-one systems of the past, such as those commonly available in the 80's (about 40 years ago!) of having the keyboard and computer all in one, with connections at the back of the enclosure, and expansion at the back of the enclosure.

My favorite system released January 1982 was the Commodore 64.

So why not have both?  With emulation, let the Raspberry Pi 400 become a Commodore 64 as well.

Vice 3.5 built, running on Raspian

One way to do this, is using Vice (the Versatile Commodore emulator).  Of course you can use a prepackaged solution like Retropie and Emulation Station.  But since it is open source, you can also just download and build the source yourself.

As vice 3.5 was just released Christmas Eve, 2020, it makes a lot of sense to build yourself, so you can have the latest build relatively easily.  Just think of all those new features!!!

I've attempted this myself on my Raspberry Pi 400 (and expect should work on others fine too) with Raspian.  I've tested with both the latest 32-bit ARM, and beta 64-bit ARM builds.

Following are the steps I took to accomplish building the default configuration.  I followed the basic instructions, and when configuration or build failed due to a dependency, researched the dependencies necessary (thanks Google and all those who have built before me and posted their solutions).  

Grab yourself your favorite beverage, power up your Pi, and get building!   And once you're done, feel free to test my hires.d64 image.  Maybe even pick up some keyboard stickers.   And also can run Pet, Vic-20, Commodore 128, etc.


  1. Install dependency packages
  2. Download three archives from web: vice 3.5, SDL2, SDL2_image
  3. extract the archives to their respective directories
  4. configure, build, and install each iteratively in the order: SDL2, SDL2_image, vice 3.5
Full Steps (note versions may change, these were the ones available January 2021):

  • sudo apt-get install flex bison xa65 libgtk2.0-dev texinfo libxxf86vm-dev dos2unix libpulse-dev libasound2-dev
  • sudo apt-get install texlive-latex-base texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra 

Thursday, August 6, 2020

Commodore 64 BASIC CRUNCH Routine Commented

The disassembled code here is from
Commodore 64 ROM.

The comments and intermediate labels
are mine.

Together they are useful.

Placing this here as is for reference.
I found this exercise necessary when
implementing my hires extensions for C64
including a patch of this routine.

        ; C64 crunch is A57C-A612
        ; C64 tokens are A09E-A19D
crunch ; from C64 ROM
       ; INPUT: PETASCII of entered line is at buffer $0200, ending with #$00 null character
       ; OUTPUT: tokenizes in place entire line, ending line with #$00 null character
       ; HINT: because of tokens, result is smaller than original so can modify in place
         LDX $7A        ; source buffer index
         LDY #$04       ; storage index starts at 4 (4+$1FB+1 = $200)
         STY $0F        ; set not DATA flag (4=NOT, 0=DATA)
.go      LDA $0200,X    ; retrieve next character from input buffer
         BPL .lowch     ; branch if 00-7F
         CMP #$FF       ; PI?
         BEQ .store     ; branch if PI, already tokenized
         INX            ; advance source index
         BNE .go        ; always skip initial character 80-FE, as X shouldn't ever wrap to 0
.lowch   CMP #$20       ; compare to ASCII space
         BEQ .store     ; branch if space, store literal
         STA $08        ; no, store character, non-zero = not REMark
         CMP #$22       ; compare to ASCII quote
         BEQ .literal   ; branch if string, store literal characters instead of matchng tokens
         BIT $0F        ; test if in DATA statement
         BVS .store     ; branch if in DATA statement, store literal characters instead of matching tokens
         CMP #$3F       ; compare to ASCII question mark
         BNE .chkzero   ; no, skip next part
         LDA #$99       ; replace question mark with token PRINT
         BNE .store     ; unconditional branch, store token
.chkzero CMP #$30       ; compare to ASCII zero digit
         BCC .scantbl   ; branch if less
         CMP #$3C       ; compare to ASCII less than
         BCC .store     ; branch if less, so branch if numeric or colon or semi-colon, store literal character
.scantbl STY $71        ; save storage offset index
         LDY #$00       ; initialize token table byte index to zero
         STY $0B        ; initialize token number to zero
         DEY            ; cancel out the next increment for loop beginning with decrement
         STX $7A        ; save source index
         DEX            ; cancel out the next increment for loop beginning with decrement
.advance INY            ; advance token table index
         INX            ; advance source index
.scanch  LDA $0200,X    ; retrieve character from buffer
         SEC            ; prepare for subtraction
         SBC $A09E,Y    ; compare to Commodore token table
         BEQ .advance   ; branch if character match, look for more matches
         CMP #$80       ; end of token?
         BNE .scannxt   ; branch if not end of token, mismatch, so get ready to check next token
         ORA $0B        ; match! combine zero based token number with $80 high bit set for storage
.storaty LDY $71        ; retrive storage offset index
.store   INX            ; advance input index
         INY            ; advance output index
         STA $01FB,Y    ; store token or character
         LDA $01FB,Y    ; set Z flag if end of line
         BEQ .endline   ; branch if end of line, finish up
         SEC            ; prepare for subtraction
         SBC #$3A       ; subtract ASCII colon
         BEQ .setf      ; branch if colon
         CMP #$49       ; DATA?
         BNE .skipset   ; skip setting flag if not DATA
.setf    STA $0F        ; $49 if DATA, or $00 if colon
.skipset SEC            ; prepare for subtraction
         SBC #$55       ; REM?
         BNE .go        ; branch if not REM to get next character
         STA $08        ; store flag zero = REM
.litloop LDA $0200,X    ; retrieve next character from input
         BEQ .store     ; branch if end of line
         CMP $08        ; compare to token that got us in this loop (e.g. 0x22 quote), or 0x00 (REM)
         BEQ .store     ; branch if REMark end of line
.literal INY            ; advance destination index
         STA $01FB,Y    ; store in buffer
         INX            ; advance source index
         BNE .litloop   ; repeat getting next character
.scannxt LDX $7A        ; retrieve source index
         INC $0B        ; advance token number
.endtok  INY            ; advance destination index
         LDA $A09D,Y    ; retrieve character from token table
         BPL .endtok    ; loop until find end of token
         LDA $A09E,Y    ; retrieve next character from token table
         BNE .scanch    ; branch if not end of token table
         LDA $0200,X    ; re-retrieve character from input buffer
         BPL .storaty   ; branch if character 00-7F, should be if got here, no token match
.endline STA $01FD,Y    ; store end of line nul character $00
         DEC $7B        ; update TXTPTR
         LDA #$FF       ;  to point to
         STA $7A        ;  $01FF
         RTS            ; done

Monday, July 13, 2020

Commodore 64 running in web browser

Open full size window:

  • Coded in TypeScript(/JavaScript) with some HTML of course
  • Portable (got a web browser right?)
  • Keyboard driver works best with Firefox
  • Works on Mobile and TV too (click on screen for configuration, help)
  • F9 to toggle Help
  • Recommend use wired or bluetooth keyboard instead of onscreen keyboard
  • This is based on my earlier efforts (see previous posts)
I coded this as a learning experience with TypeScript.  Go ahead and try it out!

Included features:
6502 Emulation, machine code
 Commodore 64 Text Screen
 Commodore Fonts: Uppercase/Graphics, Lowercase/Uppercase
 Commodore Colors: Foreground, Background, Border
 Commodore BASIC v2 (Microsoft)
 64K RAM
 20K ROM
 Attach D64 image
 Load directory from D64
 Restart with PRG image
 JavaScript speedloader to bypass slow C64 disk access
 Save/Download PRG
 Great wired/wireless keyboard support
 Keyboard scan code support - press/release, multiple keys support, separate left/right Shift
 Standard to Commodore keyboard symbolic mapping, add/remove Shift
 Special key mappings: Stop, Home, Restore, F1-F8, Ctrl, Commodore
 Mobile/TV browser keyboard support (but minimal)
 Clipboard paste support
 IRQ 60 times per second
 NMI on Restore key
 Works best with Firefox

Missing features or limitations:
6502 undocumented instructions
 Accurate, regulated instruction timing
 6502 emulation battery drain (one thread always running 100%, no idle sleep)
 VIC-II register support
 Device register support
 Programmable timers
 Serial Port - User Port
 High Resolution 320x200 and 160x200 graphics
 Multi-color text mode
 Programmable characters
 Joysticks, Paddles
 Cassette Tape
 Save to D64
 SEQ, RND, etc. files
 LOAD PRG from running program
 Positional keyboard mapping
 On-screen keyboard
 Clipboard copy
 A few graphic character key strokes (punctuation keys) may not be mapped yet
 Known issues with Google Chrome

Sunday, April 12, 2020

Commodore 64 for STM32F429 Discovery board

So here is a Commodore 64 emulator I built for STM32F429 Discovery board:

Yeah, the LCD is tiny at 2.4", and the emulation runs about 15% slower than an NTSC C64.  But it's running on a small embedded board that's available for under $30 US (DigiKey, Mouser, ...) including mounted LCD display and USB OTG jack.  Just add keyboard, OTG USB adapter, and power supply.

This is a port of my portable C64/6502 emulator for terminal console, which was a port of my Commodore/6502 emulator for Windows Console.   But this time, I dropped the console part, and went for real video (LCD) and USB keyboard support.   Hello PETSCII!

Keyboard mapping (showing my Dell keyboard):
   STOP(ESC) F1 F2 F3 F4 F5 F6 F7 F8            Restore(PrtScr/SysRq) Run/Stop(Pause/Break)
             1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ += Del/Ins(Back)    Ins Hme/Clr     / * -
   Ctrl(Tab) Q  W  E  R  T  Y  U  I  O  P  [  ]  £ (\)            Del           7 8 9 +
             A  S  D  F  G  H  J  K  L  ;: '" Return(ENTER)                     4 5 6
   LShift    Z  X  C  V  B  N  M  ,< .> /?  RShift                     Up       1 2 3
   C=(Ctrl)           SPACEBAR              C=(Ctrl)              Lft Down Rt   0 .   Enter

  • 320x200 text screen on graphics LCD, with top/bottom border.
  • USB Keyboard (e.g. PC-103) support (symbolic, not positional)
    • Tab maps to C64 Ctrl key
    • Ctlr maps to C64 Commodore key
    • Esc key maps to C64 RUN/STOP key
    • PrtScr/SysRq maps to C64 RESTORE key (supports STOP+RESTORE)
    • PgUp also maps to C64 RESTORE key
  • Full 6502 emulation.  Go ahead, run some machine language on it.
  • Commodore character set
  • Text video at $0400 (address 1024)
  • Text color at $D800 (address 55296)
  • Keyboard scan by writing to $DC00, reading from $DC01
  • Full 64K RAM.  Update 2020-04-14: RAM/ROM/IO/Charset banking is implemented!  And 1K color nybbles
  • 1/60 second IRQ.  So we've got the software clock: TI, TI$
  • Upper/lower case switch ($D018), and reverse characters.
  • Border color ($D020) and background color ($D021).
  • Approximately 85% cpu speed of a real C64
  • No NMI.  No Restore key.  Update 2020-04-15: implemented, see keyboard above.
  • No other device support.  No tape, no disk, no serial, no cartridges, no joysticks, no printer.
  • VIC-II support is limited to getting system booted.
    • No full register support.
    • Text address can't be moved.
    • No graphics support.
    • No programmable characters.
    • No raster interrupts.
    • No sprites.
    • No left/right side border displayed.  Ran out of pixels.
  • No CIA1/CIA2 (except for keyboard data ports, but no data direction registers)
  • No SID.
  • In progress.  There are bugs lurking (for example, the IRQ and USB keyboard stops working exactly at 35 minutes, 38 seconds from start, maybe a resource leak in third party libraries, so we'll call that time limited I guess)
  • Keyboard support may need tweaks for more complete PETSCII key support
  • No CAPS LOCK or SHIFT LOCK supported
  • Doesn't utilize full capabilities of the STM32F429 MCU and discovery board components including 2.0MB of Flash (uses 110KB), 256KB of RAM (uses 83KB), 8MB SDRAM, motion sensor, user leds, user button, or other expansion capabilities.  Opportunity awaits!

Monday, March 30, 2020

6502 emulator for terminal, Commodore Edition

(Update: Commodore 64, VIC-20, PET, Commodore 16, Plus/4 aka TED series)

This is a simple 6502 emulator.  And a very simple Commodore emulator.  If you like console windows and command lines, this may be your emulator, especially if you like both 6502 and BASIC.  And if you prefer C#, check out the emulator sources (link at end).


How simple is it?  It is so simple!  It turns out you can craft a 6502 emulator, hook just the character in/out routines, do a little memory management, feed it Commodore ROMs, and you've got a retro computer in a terminal (Windows Console in this case).  If you implement the 6502 accurate enough, it just works.

Commodore 64 and VIC-20 ROMs don't really care if there is any real hardware I/O available or not.  All memory is zeroed to begin with, and I've treated the I/O areas as RAM so the I/O values can be retrieved.  And it seems to work for booting the system.

The only two kernel JMP table entries patches are CHRIN ($FFCF) and CHROUT ($FFD2).  By intercepting CHRIN completely, the screen editor is bypassed, but by allowing the CHROUT to continue, screen memory is updated simultaneously to the Windows console.  Note that this emulation has lazily not implemented hooks to writes to screen memory, though you are free to implement this as you desire adding code to the SetMemory() method within the C64Emu, Vic20Emu, or other appropriate class.

The goal was to access the BASIC command line.  And using the Windows Console ReadLine(), we now get those history and editing features instead:  Home, End, Del, Backspace, Cursor Up/Down/Left/Right, etc.

If you're itching for some simple BASIC command line, including entering programs line by line, you are all set.  Until you want to SAVE, LOAD, VERIFY.  Sorry, not implemented (yet?  use the Windows clipboard for now).   Full LOAD/SAVE implementation exercise left to the reader.  ;-)   Yet, since it is a faithful 6502 emulator, if you can get your own machine code loaded, you can run that too.

Commodore PET 2001 series, Commodore 16 and Plus/4 (TED) emulators are available too, required some additional changes including RAM banking for the TED series.

I suspect additional emulation will be necessary for the Commodore 128, like the MMU, and the 8502 memory mapping, and hopefully can do without a Z80.

Want to work with another system like an Atari 400/800 series, Apple II, BBC Micro, Atari 2600 cartridge, or NES ROM?  I'm not going to stop you.  The 6502 emulation is here to use.  Though the video game systems probably won't work well in a console.  Not sure what the minimal emulation is required to get BASIC working on the others.


  • Only keyboard/console I/O.  No text pokes, no graphics.  Just stdio.  No asynchronous input (GET K$), but INPUT S$ works.  No special Commodore keys, e.g. function keys, cursor keys, color keys, STOP/RESTORE, etc.  (Could improve this.)
  • No keyboard color switching.  No border or border color.  Text and background colors are implemented, but disabled by default because mapping to the standard console colors results in some fairly horrible color combinations.
  • No screen editing (gasp!) Just short and sweet for running C64 BASIC in terminal/console window via 6502 chip emulation in software
  • No PETSCII graphic characters, only supports printables CHR$(32) to CHR$(126).  But does support CHR$(147) for clear screen.  Now also supports Home/Left/Right/Up/Down output characters (not input).
  • No memory management or banking.  Not full 64K RAM despite what the startup screen says.  C64 has just 44K RAM, 16K ROM, 1K VIC-II color RAM nybbles.   VIC-20 has just 5K RAM including screen memory (you can add more memory at the command line).
  • No timers.  No interrupts except BRK.  No NMI/RESTORE key.  No STOP key.
  • No loading or saving of files implemented (but Windows clipboard works!)
  • No cartridges.
  • No joysticks.
  • No sprites.
  • No graphics (you know this is a terminal/console window right?)
  • Yikes, that's a lot of no.  Seriously, it is a simple emulator.  Emphasis on simple.
  • Lightly tested.  Bugs are lurking! 

Trace Execution:

It is possible to trace some or all of execution by setting the Emu6502.trace to true, and it will produce debug output (see in your IDE, or capture with DebugView).  Note that this slows down the emulation significantly, but provides very good insight.   Registers and flags are shown to the left of the statement's disassembly, in their states prior to executing the statement.  Currently, referenced memory is not shown, that would be a good enhancement for the future.

Walk a ROM:

Another feature is the ability to walk a ROM method without actually executing anything.  It traverses all subroutines, and both cases of branches (not taking the branch first, then when exhausted, taking the branch).  Each statement is disassembled exactly once.  Note that JMP($00FE) or similar will probably disassemble as BRK, unless you specifically code loading memory (see C64Emu for an example).   Pushing values to the stack (say from a table) and using RTS is not supported, as the walk isn't executing anything or remembering variable assignment, so dynamically pulling values from specific entries in a table is not supported directly (but see C64Emu.Walk() that implements a workaround).

If you initialize enough low memory, and walk all the entry points including addresses from tables, then the disassembly should be a view to the complete code coverage possible (and some impossible branches and paths too).  Note it is recommended to pass the output to sort (shown below) so the code is organized in memory order.  You could effectively get a ROM disassembly (without data tables).  More work could be done to show the data tables and/or unreferenced code/bytes.

simple-emu-c64 c64 walk | sort | more
simple-emu-c64 c64 walk FF3D
simple-emu-c64 vic20 walk FFCF FFD2

Development Environment:

Developed in beautiful C# using Microsoft .NET Framework 4 in Microsoft Visual Studio 2017.  Should be portable to other languages without much difficulty (it really is a simple implementation).  And should be able to recompile on Mac or Linux with a minimum of changes if any.  Submit your pull requests if you do something cool that would be generally useful.  Or just fork your own version. 


So in the process of my retro binge session the last year or so, I did come across another BASIC for the console.  I remember at least reading it, maybe even trying it out.  But time passed.  And I was recently puzzled on how it actually worked.  Problem was, I couldn't find it, which caused me to be even more puzzled.  I googled and googled, but the keywords are so common, it is hard to sift through the results to find exactly the solution I was searching for.   So I pieced together memories and thoughts of how one would approach a solution.  I wrote down steps.
  1. Use C64 BASIC in existing VICE emulator to test tokenizing, and execution - validate entry points, memory usage, define API subset
  2. Emulate 6502 code on Windows
  3. Graphing techniques - capture code paths, variables used
  4. Convert 6502 machine code to C or other using graphing information
  5. Add optimization techniques
I used Compute!'s Mapping the Commodore 64 and VICE to find and test the code to tokenize a statement: $A579, code for adding/replacing a line of a program: $A49C, and to execute a statement: $A7E4.  And I made notes about more Commodore 64 memory map entries.

I also found an Internet archived copy of the 6502 (65XX) Microprocessor Instant Reference Card (that I probably have filed away somewhere in a box in my garage) and I was itching real bad to implement the emulator.  Now, I've implemented the 6502 emulator before, but if memory serves correctly, it was a long time ago, and the moment I was ready to test it, I kinda gave up on it.  I was ready to return to this challenge.  I needed to get over that hill.  I was determined.  I was obsessed.

And then I happened to search for the original solution on github.  Huh, yeah, I should have thought of that first.  Brain fart!  I found mist64/cbmbasic.   The statically recompiled BASIC console program and loader.  Works great!

But my obsession was in full gear, so I wrote the disassembler Thursday night, March 26, 2020, and wrote the emulator Friday all day, March 27, 2020.  I had a miscommunication with other members of my family -- they thought I was working.  But I was on PTO.   Guess I forgot to tell them.  I was present for the family -- working at the dining room table -- but my mind was full bore into my laptop getting this emulator going.  And sure enough, I was able to post a screen shot to Twitter after midnight, barely into Saturday, March 28, 2020, just over 28 hours start to finish, including some sleep.  I am so lucky to get a successful result after such a short time.

Did it actually work first time?  Definitely not.  I had to fix my implementation of the BIT statement, somehow some opcodes got deleted, had to fix some instruction modes, and continuously fixing the flag assignments.  The challenge was fun.

Put in a bit more polish, separate out the Commodore 64 code from the 6502, and I was able to post the source to Github Saturday night, March 28.

Sunday I was able to test the VIC-20 ROMs, and wow, those work too.  Posted additional changes to formally support those, and have command line arguments checked in Sunday, March 29.

Then checked in backspace support early Monday, March 30 before heading to my real world job of working at home (how convenient!).  Yeah Coronavirus going on and all that.  All the more reason to keep my head low and focus on something else.

Monday night March 30 I created this blog entry.  Okay, time to get more sleep.

Sleep, maybe some, but TED was bothering me.  Turns out it needed memory banking (damn you TED!) so there you go, revised the memory scheme from an array, to a C# class that each machine type can handle those accesses including banking support.  Watch out 128, I'm going to get you next.

Saturday April 4 I was able to fix some I/O issues, and check in TED (C16, Plus/4) and PET 2001 support.

What's next?  I'm toying with replicating the static recompilation, to C would work best for me.  Then I could test on various or select embedded hardware platforms I have in my possession (or did I say obsession?).  

And maybe even use one with an LCD, and modify the emulation to support the screen editor and hi-res graphics support, either hooked or emulated, and support file loading from SD.  

Then probably on to something else newly retro and exiting.  Have fun!

[Update: ported to C, and tested on ARM boards with MBED and Arduino.  Skipped the static recompilation, because easier not to, and keeps all the machine code 6502 compatibility.]


Inspired by mist64/cbmbasic and RetroShield 6502
Compute!'s Mapping the VIC
VICE - the Versatile Commodore Emulator

External Links:

Open Source! (C#, follow links for C version)

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!

70 X=R*COS(A)+160
80 Y=-R*SIN(A)+100
86 C=C+1:IF C=16 THEN C=1

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:

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 1K 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?



Tuesday, June 4, 2019

Computer Graphics Final Project 1989 Detailed

My graphics final project included a demonstration to the professor.  The demo went well as I remember, involving hefting my C128D including monitor up to the second floor of the UCSC Applied Sciences Room 215 computer lab.  The date is March 16, 1989.

Then I either didn't have documentation or otherwise couldn't show the work how I got to that point, and I was stunned, all I can remember is the professor walking off and leaving me without a way to recover, and even dropping off the description of the project to the proctor during my final exam didn't satisfy that section of my grade, and my evaluation (no grades at UCSC then) was very clear I had failed or underachieved in the project yet passed the class.

Evidently I missed something in the requirements and focused too much on the demonstration.  Documentation was the farthest thing from my mind while the demo was everything.  Lesson learned the hard way -- always cross all your i's and dot all your t's or something like that.

Well here's the project fully documented now.  Only it's 30 years late.  This is the best, or one of my best, failures to date!  Hope you enjoy.

Okay, so what is all this?  The course I took was an undergraduate computer graphics class.  We quickly got into 3D projection graphics.  The mathematics was covered in our course textbook and also in class.  Our assignments were to take templates of code provided by the teaching assistant, fill in missing portions, and turn in the final code.  Our target system (from memory) was either a SCO UNIX or Microsoft Xenix 386 system (I think it was Xenix) with separately attached graphics display (graphics library was ig, can't remember what that stands for).  It did color of course, and had a resolution in the neighborhood of 512x512.   The system did not have a concept of quick animation to my recollection.

My project took our 3D graphics primitives built in my assignments, and built around them a scripting language to describe the scene and move through it, or move the objects, rotate the objects, or scale the objects, or a combination of all of these.  Most of my demonstrations set up the object and rotate it around in 360 degrees.   So I built on my compiler experience (lex/yacc) to build a reusable mini-language to do simple computer animation.

Now this is 30 years ago.  Now we take 3D graphics for granted.  We have software libraries and graphics hardware acceleration that can do polygons in the thousands, millions, billions.  And all this code is doing is wire frame animation, not solid objects.  Whoop de doo!   Yeah, but it's doing it from scratch.   And I built up my own graphics workstation software to replicate the lab experience, albeit in black and white and lower res (320x200).   Hello Commodore 128!   And Commodore 512KB RAM Expansion Unit (REU) for animation!

Most of these animations are 60 frames total (1 to 4 seconds), where the code was run on a UNIX system, converted to line graphics, downloaded to the Commodore 128 and rendered.  I wrote the Commdore 128 software to render the graphics, and swap in/out of the REU for animation.  Because the REU does DMA, the transfer is fast.  Yeah, it's only 8Kbytes, but we're still talking a 1MHz or 2MHz 6502 based system, and with 60 frames, thats 480Kbytes total, more than the 128Kbytes on board.

We start by defining an object.  A simple one is 3dbox.obj

-100 -100 -100 100 -100 -100
100 -100 -100 100 100 -100
100 100 -100 -100 100 -100
-100 100 -100 -100 -100 -100
-100 -100 100 100 -100 100
100 -100 100 100 100 100
100 100 100 -100 100 100
-100 100 100 -100 -100 100
-100 -100 -100 -100 -100 100
100 -100 -100 100 -100 100
100 100 -100 100 100 100
-100 100 -100 -100 100 100

This is a 200 unit cube defined in 3D space with x,y,z coordinates space separated, one line of the box defined on each line of the file

scripts/06_box that animates this box looks like this

output bin
object "objects/box.obj"
translate z 0 y 0
eye 0 0 -500 0 0 0 0
window -200 200 -200 200 -200 200
viewport 0 511 0 511
repeat 60
   rotate y 6

Now looking at this, I see I could have "cheated" and only rotated it 90 degrees, because the cube is the same on all sides.  I proceeded to use this cheat in creating the gif with online tools.  I leave it as an exercise to the user, hint: rotate at a finer pitch to get a finer animation.  Note that the numbers are floats, so decimals are allowed.

And here is more description for the animation scripting mini-language

CIS 160 Project
David R. VanWagner

My project includes an enhancement of assignment 5.  I changed it to use
a language with which most commands require a single statement, and
a repeat statement is used to generate animation.  The instructions are
as follows:

help                            list commands
device, output                  change device type (ig,c128,bin)
eye                             set eye from,to,tilt
window                          set window extents xmin,xmax ... zmax
viewport                        set viewport xmin,xmax,ymin,ymax (0-511)
display                         turn c128 graphics display off,on
clear, cls, frame               clear screen, next frame
draw                            draw on screen using current settings
quit, exit, done                quit
set                             set current settings as default
reset                           reset to default settings
rotate                          rotate in x, y, and/or z
                                        as in  rotate x 30 y -20
scale                           scale in x, y, and/or z
translate, move                 translate in x, y, and/or z
bezier                          load bezier curve data, filename in quotes
repeat                          specify a number of times to repeat
loop                              until loop statement
                                (repeat/loop-s may be nested!)
object                          load object line data
input                           input commands from file
perspective                     turn perspective off,on
                                        ( perspective on is default )

The code is done in C with a lot of help from lex and yacc because of
the repeat/loop statements -> parses the code before it is executed, and
in the case of repeat/loop, lists of psuedo-code are made that are executed.

To allow me to do the majority of my work at home, most of my preliminary
work was done specific to my home computer.  I wrote my own ADM-31 (not
3A!) terminal emulator some time ago, and added to it to turn it into a
graphics work station.  Since the Commodore 128 has seperate RGB and composite
outputs, the setup is very similar to AS215 with text terminals and attached
graphics displays.  I also added code to allow for saving video display
coordinate lines ( what is normally sent to the graphics display ) to a
file in a compressed format ( 34 bits per point: 9 bits each x, 8 bits each
y ) and then using a combination of BASIC and 8502 Assembly on the
Commodore, each frame is drawn and stashed in external DMA memory, then
fetched in sequence for the fast animation.

There's another piece missing.  The c128 output device is actually when running in my own custom terminal emulator, to render in real-time to the secondary graphics screen (320x200 monochrome) while commanding UNIX over my 2400 baud modem in 80x50 text from the RGBI screen.

What I found out was that once you write your own terminal emulator, adding additional emulation sequences to do other stuff is a breeze.  And there weren't that many new ones to add for graphics.  My graphics terminal was running in no time!  But in retrospect, I should have added flow control to slow down the UNIX system.  It probably would have been as easy as a ^S when receiving a graphics command, and ^Q when finished rendering it.

Having the real-time graphics allowed me to render a single frame on the screen to make sure I was doing the right thing.  Then I would switch to bin format to output to a file on the UNIX system, and then file transfer to my floppy drive (can you remember those!!!) and then run other programs to render to the DMA memory and replay quickly for animation.

Disclaimers to folks.  Except for the first 5 input files (mostly the MIG-25 planes), the other renders I did now in the present in reconnecting with this project.  And I ran all my recent tests and development with Vice 3.3 on Windows 10 using both cygwin and Ubuntu as my "UNIX" systems.  Also there's a bug somewhere in my code!  It craps out on the 64th frame.  Probably something stupid.  Anyways 60 is a more round number for 360 degrees anyways.  Also I haven't matched loadbin.src to the machine language version in animate.bas.  I suspect they are the same, just trusting 30 year old bits.

Another tip is that I created an AWK script for combining named points and named lines into a 2D object.  Add another AWK line, and you can place it in 3D.   Here's an example:

File abc.v defines the points

a1 -40 -30 -100
a2 -35 0 -100
a3 -30 30 -100
a4 -25 0 -100
a5 -20 -30 -100
b1 -10 0 -100
b2 -10 30 -100
b3 5 30 -100
b4 10 25 -100
b5 10 5 -100
b6 5 0 -100
b7 10 -5 -100
b8 10 -25 -100
b9 5 -30 -100
b10 -10 -30 -100
c1 40 30 -100
c2 25 30 -100
c3 20 25 -100
c4 20 -25 -100
c5 25 -30 -100
c6 40 -30 -100

File abc.l defines the lines (between the points)

a1 a2
a2 a3
a2 a4
a3 a4
a4 a5
b1 b2
b2 b3
b3 b4
b4 b5
b5 b6
b6 b1
b6 b7
b7 b8
b8 b9
b9 b10
b10 b1
c1 c2
c2 c3
c3 c4
c4 c5
c5 c6

Then use objects/draw.awk to combine all these

cat abc.v abc.l | awk -f draw.awk > abc.obj

Then abc3d.v and abc3d.l were created from the previous files, resulting in abc3d.obj

There is also a commodore.awk and circle.awk to generate 2D objects, be sure to append a Z value and you can place them in 3D space.  Also check out commodore.obj, and yes it is designed to the 1965 specifications, except for some aspect ratio stuff (if you're running in emulation, just resize the window until the slants are at right angles).  Then again, the scale command could be used to help adjust the aspect ratio.  Again, left to the student.

All the C128, UNIX, source, and animation files used in this project are provided at this link here, and be sure to check out the node-m terminal emulator with its graphics capabilities as well.  There are also 7 more sample animations on the disk not displayed here.