Close

Serial port printing on a commodore

A project log for Unlimited tile world on a Commodore 64

Unfinished childhood project

lion-mclionheadlion mclionhead 06/06/2024 at 19:080 Comments

What's really needed is hello world for the serial port, since you can't debug graphics by printing on the screen.

Lions kind of dread having to get too involved in the specifics of C64 programming.  It's kind of expected nowadays to have libraries abstract all that.

For its fame in retro computing, there's hardly any developer documentation.  chatgpt can produce very little useful assembly output.  There's no stack overflow for it, very few programming examples. The glxgears demo was possible because internet examples for graphics abound, but not for I/O.

CC65 has a graphics library tgi.h but it just draws text, polygons in high res bitmap mode.  There's a device library dio.h which allows random sector access.  There are standard C functions in stdio.h for accessing files.  There's a debug library dbg.h which just dumps RAM.  There's a decompression library lz4.h.  There's a serial port library serial.h which supports single character I/O.  Don't think these are all implemented for every target.   The only real magic seems to be in cbm.h

cbm.h has C64 functions for file I/O: cbm_open, cbm_load, cbm_save but no seek.  It has a few kernal functions: cbm_k_ckout, cbm_k_bsout, cbm_k_chrout, cbm_k_getin, cbm_k_load, cbm_k_open, cbm_k_talk.  It looks like you have to make some chrout calls to seek.  It doesn't really abstract anything.

The addresses of the kernal routines are abstracted to names in cbm_kernal.inc

There are some hits for printing the serial port output on the host: https://vice-emu.pokefinder.org/wiki/RS232#connecting_to_local_modem_simulator

The kernal used a device number to select the serial port for character output:  https://www.c64-wiki.com/wiki/Device_number

There's a better reference for the kernal: https://sta.c64.org/cbm64krnfunc.html

Maybe it would revive a positive memory to have the original reference manual, smell the glossy paper while cleaning up the hanging chads created by the plastic binder.

http://cini.classiccmp.org/pdf/Commodore/C64%20Programmer%27s%20Reference%20Guide.pdf

 A PDF of it is easy to obtain nowadays but not searchable.

https://archive.org/details/c64-programmer-ref/mode/2up

A hideous javascript viewer with limited searching exists.

The mane things not in it were always subroutines in BASIC & KERNAL routines, a map of memory below byte 1024.  Young lion only ever read the beginning of the manual which covered graphics.   Old lion now focused on the end of the manual which covered I/O.

Sadly, getting serial port text out of VICE proved intractable.  There seemed to be a mismatch in baud rate or a missing step.  It might be easier to have a physical commodore with logic signals that could be probed.  The RS232 signals were made with shift registers on the CIA chips.  Waveforms from physical hardware would allow an animal to make a custom serial driver or use bit banging, but it's not possible with emulation.

After much browsing of the reference manual, VICE was able to print hello world to the console through printer emulation.

.autoimport    on              ; imports C library functions
.forceimport    __STARTUP__ ; imports STARTUP, INIT, ONCE
.export        _main           ; expose mane to the C library
.include        "zeropage.inc"
.include        "cbm_kernal.inc"


.segment    "CODE"
.proc    _main: near

; open the printer page 338
    lda #1 ; logical number
    ldx #4 ; device number
    ldy #7 ; secondary address
    jsr SETLFS

    jsr OPEN

; direct CHROUT to the printer
    ldx #1 ; logical number
    jsr CHKOUT

; print something
    ldx #$00          ; initialize X register for indexing
LOOP:
    lda MESSAGE,x     ; load the character from the message
    beq DONE          ; if character is zero, we are done
    jsr CHROUT         ; call CHROUT routine to send the character to the serial port
    inx               ; increment X register
    jmp LOOP          ; repeat the loop

DONE:
; direct CHROUT to the screen to print ready on the screen
    ldx #0 ; logical number
    jsr CHKOUT
    rts               ; return from subroutine


MESSAGE:
    .byte "hello world"
    .byte $0a
    .byte 0           ; null terminator for the message


.endproc

Getting VICE to print hello world on the console required editing ~/.vice/vicerc.  The key options were

PrinterTextDevice1="/dev/stdout"

Printer4=1

PrinterUserport=1

The text needs to end in $0a to get the buffer to flush.  The assembler converts the text to PETSCII. Then the emulator converts the printer output to ASCII.

It seems the printer was the mane way an ordinary consumer would have debugged graphics programs in the old days.  Berkeley Softworks actually cross compiled on UNIX workstations.

---------------------------------------------------------------------------------------------------

Kind of impressive what kinds of 2D tile worlds were created back in the day with just character sets, character objects, & the available RAM.  Seeing the caliber of 2D worlds that were created kind of defeats the appeal of making yet another one.

Always wondering if a disk mechanism is necessary to achieve the desired map.

Discussions