full screen demo concept

This commit is contained in:
2026-07-13 16:06:51 +02:00
parent 44265afe59
commit e068a41c6d
2 changed files with 252 additions and 95 deletions
+27 -63
View File
@@ -1,6 +1,12 @@
# C64 Demo — `main.asm` # C64 Demo — `main.asm`
A minimal Commodore 64 demo written in 6502 assembly (compiled with the ACME assembler). The program prints two lines of text on the screen, then enters an infinite loop that cycles the border color. A Commodore 64 intro written in 6502 assembly (compiled with the ACME assembler). The screen shows:
- giant **TTG** letters in the top half (built from 8×8 bitmaps, drawn with solid block characters),
- **TELETYPE GAMES** centered below,
- a horizontally scrolling credits line (`MR.ZERO - TASNADI ZSOLT / MR.ONE - TARI BALAZS / MR.TWO - TIMAR ZOLTAN / MR.THREE - MEZO BELA`),
- **WWW.TELETYPEGAMES.ORG**,
- **SZEGED, 2026**.
## Build and run ## Build and run
@@ -22,80 +28,38 @@ RUN
### 1. BASIC stub (from `$0801`) ### 1. BASIC stub (from `$0801`)
The C64 looks for programs at the start of the BASIC memory area (`$0801`). We place a one-line BASIC program here: A hand-encoded one-line BASIC program (`10 SYS 2064`) so the user only has to type `RUN`; it jumps to the machine-code entry point at `$0810`.
``` ### 2. Initialization
10 SYS 2064
```
This lets the user just type `RUN` — the BASIC interpreter then transfers control to the machine-code entry point at address `2064` ($0810). The `!byte` directives hand-encode the BASIC line: link pointer, line number, `SYS` token (`$9e`), the `" 2064"` ASCII digits, end-of-line zero, and end-of-program marker. Border and background are set to black, then screen RAM (`$0400`) is filled with spaces and color RAM (`$D800`) with white. Everything is drawn by writing to screen RAM directly — the KERNAL `CHROUT` routine is not used.
### 2. Entry point (`$0810` = 2064) ### 3. Giant letters
```asm Each big letter is an 8×8 bitmap (`bigfont`, one byte per row, MSB = left pixel). The drawing loop walks the three letters, shifts each bitmap row out bit by bit, and writes an inverse-space block (`$A0`) plus yellow into color RAM for every set bit. Letters are 8 columns wide with a 2-column gap, so the 28-column logo is centered starting at column 6, row 2.
* = $0810
```
Machine code starts here. ### 4. Static texts
### 3. KERNAL and VIC-II addresses Null-loop copies place the screen-code strings (`!scr`) at fixed, centered screen offsets:
| Symbol | Address| Meaning | | Text | Row | Color |
|-----------|--------|----------------------------------| |-------------------------|-----|-------------|
| `CHROUT` | `$FFD2`| KERNAL character output routine | | `TELETYPE GAMES` | 12 | white |
| `BORDER` | `$D020`| VIC-II border color register | | scroller line | 14 | cyan |
| `BG` | `$D021`| VIC-II background color register | | `WWW.TELETYPEGAMES.ORG` | 17 | light green |
| `SZEGED, 2026` | 19 | light grey |
### 4. `start` — initialization ### 5. Scroller (main loop)
- **Background:** light blue (`14`) into `$D021`. The main loop synchronizes to the display by waiting for raster line `$FE` (`$D012`), giving one iteration per frame. Every `SCROLL_SPEED` (4) frames it shifts row 14 one character to the left and feeds the next character of `scrolltext` into the rightmost column; the index wraps at the end of the text, so the credits loop forever.
- **Border:** dark blue (`6`) into `$D020`.
- **Clear screen:** PETSCII control code `$93` sent to `CHROUT`.
- **Text color:** white (`$05`).
### 5. `print_loop` — printing the text
Classic null-terminated string output:
```asm
ldx #0
print_loop:
lda message,x ; load character using X as index
beq color_loop ; if 0 → done
jsr CHROUT ; otherwise print it
inx
jmp print_loop
```
At the `message` label there is PETSCII text separated by line breaks (`13`), terminated with a `0` byte.
### 6. `color_loop` — infinite border flashing
```asm
color_loop:
inc BORDER ; border color +1
; two nested delay loops (256*256 iterations)
jmp color_loop
```
`inc $D020` increments the lower 4 bits of the border color on every iteration (the VIC-II only uses those anyway), cycling through all 16 colors. The nested `dex`/`dey` loop is pure busy-wait so the eye can perceive the change — the C64 runs at ~1 MHz, and without the delay the flashing would be invisibly fast.
### 7. `message` — data
```asm
message:
!text "HELLO, COMMODORE 64!"
!byte 13, 13 ; two line breaks
!text "TELETYPE GAMES DEMO"
!byte 13, 0 ; line break + end-of-string
```
## Memory map ## Memory map
``` ```
$0801 .. $080F BASIC stub (10 SYS 2064) $0801 .. $080F BASIC stub (10 SYS 2064)
$0810 .. ... machine code (start, print_loop, color_loop, message) $0810 .. ... machine code + font bitmaps + texts + variables
$D020 border color (visible while being written) $0400 .. $07E7 screen RAM (written directly)
$D021 background color $D800 .. color RAM
$FFD2 KERNAL CHROUT $D012 raster line (frame sync)
$D020 / $D021 border / background color
``` ```
+225 -32
View File
@@ -1,5 +1,5 @@
; ----------------------------------------------------------- ; -----------------------------------------------------------
; main.asm - C64 demo: text output + border flashing ; main.asm - C64 demo: giant TTG logo + credits scroller
; Build: acme -f cbm -o main.prg main.asm ; Build: acme -f cbm -o main.prg main.asm
; ----------------------------------------------------------- ; -----------------------------------------------------------
@@ -18,45 +18,238 @@
* = $0810 ; = 2064 in decimal * = $0810 ; = 2064 in decimal
; ---- KERNAL routines ---- ; ---- hardware registers ----
CHROUT = $ffd2 ; character output
BORDER = $d020 ; border color register BORDER = $d020 ; border color register
BG = $d021 ; background color register BG = $d021 ; background color register
RASTER = $d012 ; current raster line
SCREEN = $0400 ; screen RAM (40x25 chars)
COLRAM = $d800 ; color RAM
; ---- colors ----
BLACK = 0
WHITE = 1
CYAN = 3
YELLOW = 7
LGREEN = 13
LGREY = 15
; ---- screen layout ----
BIGROW = 2 ; top row of the giant letters
BIGCOL = 6 ; left column (3*8 + 2*2 = 28 wide, centered)
TITLE_POS = 12*40 + 13 ; "TELETYPE GAMES" (14 chars, centered)
SCROLLROW = 14 ; scroller row
WWW_POS = 17*40 + 9 ; "WWW.TELETYPEGAMES.ORG" (21 chars)
CITY_POS = 19*40 + 14 ; "SZEGED, 2026" (12 chars)
SCROLL_SPEED = 4 ; frames per scroll step
; ---- zero page pointers ----
scrlo = $fb
scrhi = $fc
collo = $fd
colhi = $fe
start: start:
lda #14 ; light blue background lda #BLACK
sta BG
lda #6 ; dark blue border
sta BORDER sta BORDER
sta BG
lda #$93 ; CLR/HOME - clear screen ; clear screen RAM, fill color RAM with white
jsr CHROUT
lda #$05 ; white text color
jsr CHROUT
ldx #0 ldx #0
print_loop: clear_loop:
lda message,x lda #$20 ; space
beq color_loop ; if 0 -> text done sta SCREEN,x
jsr CHROUT sta SCREEN+$100,x
sta SCREEN+$200,x
sta SCREEN+$2e8,x
lda #WHITE
sta COLRAM,x
sta COLRAM+$100,x
sta COLRAM+$200,x
sta COLRAM+$2e8,x
inx inx
jmp print_loop bne clear_loop
; infinite color flasher ; ---- draw the giant TTG letters from 8x8 bitmaps ----
color_loop: lda #0
inc BORDER ; increment border color sta letter
letter_loop:
ldx letter
lda letter_off,x
clc
adc #<(SCREEN + BIGROW*40 + BIGCOL)
sta scrlo
lda #>(SCREEN + BIGROW*40 + BIGCOL)
adc #0
sta scrhi
lda letter_off,x
clc
adc #<(COLRAM + BIGROW*40 + BIGCOL)
sta collo
lda #>(COLRAM + BIGROW*40 + BIGCOL)
adc #0
sta colhi
lda letter ; bitmap index = letter * 8
asl
asl
asl
tax
lda #8
sta rowcount
row_loop:
lda bigfont,x
sta curbits
ldy #0 ldy #0
delay_outer: bit_loop:
ldx #0 asl curbits ; leftmost pixel first
delay_inner: bcc no_plot
dex lda #$a0 ; inverse space = solid block
bne delay_inner sta (scrlo),y
dey lda #YELLOW
bne delay_outer sta (collo),y
jmp color_loop no_plot:
iny
cpy #8
bne bit_loop
lda scrlo ; advance both pointers one screen row
clc
adc #40
sta scrlo
bcc scr_nocarry
inc scrhi
scr_nocarry:
lda collo
clc
adc #40
sta collo
bcc col_nocarry
inc colhi
col_nocarry:
inx
dec rowcount
bne row_loop
message: inc letter
!text "HELLO, COMMODORE 64!" lda letter
!byte 13, 13 cmp #3
!text "TELETYPE GAMES DEMO" bne letter_loop
!byte 13, 0
; ---- static texts ----
ldx #0
title_loop:
lda txt_title,x
sta SCREEN+TITLE_POS,x
lda #WHITE
sta COLRAM+TITLE_POS,x
inx
cpx #txt_title_end - txt_title
bne title_loop
ldx #0
www_loop:
lda txt_www,x
sta SCREEN+WWW_POS,x
lda #LGREEN
sta COLRAM+WWW_POS,x
inx
cpx #txt_www_end - txt_www
bne www_loop
ldx #0
city_loop:
lda txt_city,x
sta SCREEN+CITY_POS,x
lda #LGREY
sta COLRAM+CITY_POS,x
inx
cpx #txt_city_end - txt_city
bne city_loop
; scroller row color
ldx #39
lda #CYAN
scrollcol_loop:
sta COLRAM+SCROLLROW*40,x
dex
bpl scrollcol_loop
lda #SCROLL_SPEED
sta framecnt
lda #0
sta scrollidx
; ---- main loop: scroll the credits line ----
main:
wait_raster: ; wait for raster line $fe (bottom of screen)
lda RASTER
cmp #$fe
bne wait_raster
wait_raster2: ; ...and wait until it passes -> exactly one frame
lda RASTER
cmp #$fe
beq wait_raster2
dec framecnt
bne main
lda #SCROLL_SPEED
sta framecnt
; shift scroller row one char to the left
ldx #0
shift_loop:
lda SCREEN+SCROLLROW*40+1,x
sta SCREEN+SCROLLROW*40,x
inx
cpx #39
bne shift_loop
; fetch next char of the scrolltext into the rightmost column
ldx scrollidx
lda scrolltext,x
sta SCREEN+SCROLLROW*40+39
inx
cpx #scrolltext_end - scrolltext
bne no_wrap
ldx #0
no_wrap:
stx scrollidx
jmp main
; ---- data ----
; 8x8 bitmaps of the giant letters (one byte per row, MSB = left pixel)
bigfont:
; T
!byte $ff, $ff, $3c, $3c, $3c, $3c, $3c, $3c
; T
!byte $ff, $ff, $3c, $3c, $3c, $3c, $3c, $3c
; G
!byte $7e, $c3, $c0, $c0, $cf, $c3, $c3, $7e
letter_off: ; column offset of each letter (8 wide + 2 gap)
!byte 0, 10, 20
; texts in screen codes (!scr); lowercase source shows as uppercase on C64
txt_title:
!scr "teletype games"
txt_title_end:
txt_www:
!scr "www.teletypegames.org"
txt_www_end:
txt_city:
!scr "szeged, 2026"
txt_city_end:
scrolltext:
!scr "mr.zero - tasnadi zsolt / mr.one - tari balazs / "
!scr "mr.two - timar zoltan / mr.three - mezo bela / "
scrolltext_end:
; ---- variables ----
letter: !byte 0
rowcount: !byte 0
curbits: !byte 0
framecnt: !byte 0
scrollidx: !byte 0