Files
Sprinter-SDCC/docs/samples/flames/flames.z80
T
snark13 c71e249a4e Add full compiler toolchain, libc, examples and reference docs
First substantive commit: the entire Sprinter C compiler tree on top of
the bare README+gitignore initial commit.

What's in here:
  bin/sprinter-cc        — driver script invoking SDCC + linker + mkexe
  libc/                  — Sprinter-specific libc layer over ESTEX/BIOS
                           (conio, gfx, io, mem, stdio + headers)
  runtime/               — crt0 variants (default/small/banked/minimal)
                           + heap + bank trampolines
  toolchain/             — mkexe (SprintEXE packer, C + tests)
  examples/              — 30 demo programs (gfx, file I/O, env, time, …)
  lib/Makefile           — builds the libc archive (sprinter.lib)
  docs/                  — converted Sprinter manuals + asm reference samples
  third_party/           — solid-c reference compiler dump + sdcc setup script
  release_docs/          — packaging / release notes

gitignore overhaul:
  • Drop dangerous blanket patterns: *.asm (would hide docs/samples/*.asm)
    and *.exe (case-insensitive match was hiding third_party/solid-c/*.EXE
    on macOS APFS).  Replaced with examples/*/*.{asm,exe,…} and lib/*.lib.
  • Restore tracking of toolchain/mkexe/tests/{one,big}.bin — those are
    INPUT fixtures, not build outputs.
  • Collapse the duplicated SDCC/C/Sdcc sections into one section per
    concern (build outputs / vendored / OS-junk).
  • Add .sprinter-cc-*/, build/ (catches lib/build/ too), .claude/.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 16:13:21 +03:00

448 lines
8.5 KiB
Z80 Assembly

;[]=======================================================================[]
;
; flames.z80 -- mini demo for Sprinter
;
; Created by Anton Enin 21-April-1999
;
; Last update 18-July-2002
;
; Copyright (C) 2002 R-lab
;
; This program should be compiled using z80asm
; http://www.zxasm.narod.ru/
;
; z80asm.exe -f bin flames.z80 -o flames.exe
;
;[]=======================================================================[]
; sprinter constants -- see sprinter docs
VPAGE equ 0x50 ; video memory page
YPORT equ 0x89 ; y pos for write to the vram
PAGE0 equ 0x82 ; memory page ports
PAGE1 equ 0xA2 ;
PAGE2 equ 0xC2 ;
PAGE3 equ 0xE2 ;
; os constants -- see os docs
struc HeaderStruct ; Estex Exe Header
id: resb 3 ; exe file Id (must be 'EXE')
version: resb 1 ; exe file version
code_offeset: resd 1 ; offset to start code (header size)
loader_size: resw 1 ; first loader size
reserved1: resw 3 ; reserved
start_address: resw 1 ; program org
entry_point: resw 1 ; program entry point
stack_point: resw 1 ; program stack point
endstruc
; my constants -- see ...? :)
PALETTE_BASE equ 0x8000
FLAMES_FRAME1 equ 0x8000
FLAMES_FRAME2 equ 0x8800
;[]=======================================================================[]
section .text
org 0x8FEA
;[]=======================================================================[]
; EXE header
ExeHeader: istruc HeaderStruct ; initialized structure
at id, db 'EXE'
at version, db 0
at code_offeset, dd CodeStart - ExeHeader
at loader_size, dw 0
at start_address, dw 0x9000
at entry_point, dw EntryPoint
at stack_point, dw 0xBFFF
iend
CodeStart: ; start address is 0x9000
;[]=======================================================================[]
EntryPoint: ; org = 0x9000
ld hl, HelpString
ld c, 0x5C ; print text
rst 0x10
call SetVideoMode
call SetPalette
call CrearVideoRam
ld hl, FLAMES_FRAME1 ; clear 2 frame buffer
ld de, FLAMES_FRAME1+1
ld bc, 0x0FFF
ld (hl), l
ldir
in a, (YPORT) ; save inflective ports
ld c, a
in a, (PAGE1)
ld b, a
push bc
ld a, VPAGE ; set video page to 0x4000-0x7FFF
out (PAGE1), a
.main_loop:
; now scroll frame up to 1 line
ld hl, FLAMES_FRAME1+0x40
ld de, FLAMES_FRAME1+0x20
ld bc, 62*0x20
call AccelCopy
; now add 4 new random pixel
; to the bottom of the flame
; hl - last line of frame + 3
ex de, hl
ld c, 0x06
add hl, bc
ld b, 0x04
.next_pixel:
push hl
ld a, 24 ; random 0 - 23
push hl ; for pixel x position
call GetRandom
pop hl
add a, l
ld l, a
ld a, 180 ; pixel intensity 0 - 189
push hl
call GetRandom
pop hl
ld (hl), a ; pixel size 2x1
inc l
ld (hl), a
pop hl
djnz .next_pixel
; now blur the frame
; this is not optimized code ;)
; better blur for each pixel
; xxx
; xox
; x x
ld ix, FLAMES_FRAME1+0x20
ld de, FLAMES_FRAME2+0x20
ld h, b
ld yh, 0x3F
.blur_line:
ld yl, 0x1F
inc ix
inc de
.blur_pixel:
ld l, (ix-0x21)
ld c, (ix-0x20)
add hl, bc
ld c, (ix-0x1F)
add hl, bc
ld c, (ix-0x01)
add hl, bc
ld c, (ix+0x01)
add hl, bc
ld c, (ix+0x1F)
add hl, bc
ld c, (ix+0x21)
add hl, bc
ld c, (ix+0x21) ; this equal two pixel deflect
add hl, bc ; the flame to left
ld a, l
srl h
rra
srl h
rra
srl h
rra
ld (de), a
inc de
inc ix
dec yl
jr nz, .blur_pixel
dec yh
jr nz, .blur_line
halt ; v'sync, maybe :)
; now copy frame to
; the vram
; 60 lines from top
ld hl, FLAMES_FRAME2
ld de, 0x4080
ld b, 62
di
ld d, d ; set accel count
ld a, 0x20
ld b, b
ld a, b
.out_loop:
out (YPORT), a
ld l, l ; accel copy
ld a, (hl)
ld (de), a
ld b, b
ld a, l
add a, 0x20
ld l, a
adc a, h
sub l
ld h, a ; next line in frame buffer
inc b
ld a, b ; next y line in vram
cp 62+60
jr nz, .out_loop
ei
ld hl, FLAMES_FRAME2 ; duplicate frame buffers
ld de, FLAMES_FRAME1
ld bc, 0x0800
call AccelCopy
ld c, 0x31 ; test keypress
rst 0x10
jp z, .main_loop
sub 0x1B ; ESC is pressed?
jp nz, .main_loop
pop bc
ld a, b
out (PAGE1), a
ld a, c
out (YPORT), a ; restore ports
call CrearVideoRam
call ResVideoMode
ld bc, 0x0041
rst 0x10 ; exit to OS...
;[]=======================================================================[]
; Simple random numbers generator
; Input:
; a - random number limit
; Output:
; a - random number
GetRandom:
ld c, a
.seed: ld de, 0x4664
ld h, e
ld l, 0xFD
ld a, d
and a
sbc hl, de
and a
sbc hl, de
ld e, a
ld d, 0x00
and a
sbc hl, de
jr nc, .next
inc hl
.next: ld (.seed + 1), hl
; now c - limit
; l - random 0.0 - 1.0
ld e, l
ld d, 0x00
ld l, d
ld h, c ; random * limit = number 8.8
%rep 8
add hl, hl
jr nc, $+3
add hl, de
%endrep
ld a, h ; return rnd (0 < x < limit)
ret
;[]=======================================================================[]
; set requist video mode 640x256x16
SetVideoMode:
ld c, 0x51 ; save previos vmode
rst 0x10
ld (vmode + 1), a
ld a, b
ld (vscrn + 1), a
sub a
call CrearVideoRam
ld bc, 0x0050 ; set 320x256x256
ld a, 0x81
rst 0x10
ret
;[]=======================================================================[]
; restore previos video mode
ResVideoMode:
sub a
call CrearVideoRam
vscrn: ld b, 0x00
vmode: ld a, 0x00
ld c, 0x50
rst 0x10 ; set previos vmode
ret
;[]=======================================================================[]
SetPalette:
ld hl, PALETTE_BASE ; generate palette
ld bc, 0x0800
.loop1: ld a, 0x10 ; gradien of red color
sub b
add a, a
add a, a
add a, a
add a, a
add a, a
ld (hl), c
inc hl
ld (hl), c
inc hl
ld (hl), a
inc hl
ld (hl), c
inc hl
djnz .loop1
ld b, 0x10
.loop2: ld (hl), c ; gradien of yellow color
inc hl
ld a, 0x10
sub b
add a, a
add a, a
add a, a
add a, a
ld (hl), a
inc hl
ld (hl), 240
inc hl
ld (hl), c
inc hl
djnz .loop2
ld b, 0x10
.loop3: ld a, 0x10 ; gradien of white color
sub b
add a, a
add a, a
add a, a
add a, a
ld (hl), a
inc hl
ld (hl), 240
inc hl
ld (hl), 240
inc hl
ld (hl), c
inc hl
djnz .loop3
ld b, 208
ld a, 252
InPal4 ld (hl), a ; gradien of :) super white color
inc hl
ld (hl), a
inc hl
ld (hl), a
inc hl
ld (hl), c
inc hl
djnz InPal4
ld hl, PALETTE_BASE
ld de, 0x0000
ld bc, 0xFFA4
sub a
rst 0x08 ; load palette by BIOS
ret
;[]=======================================================================[]
; Clear video memory (first screen)
CrearVideoRam:
in a, (YPORT) ; store modify ports
ld c, a
in a, (PAGE1)
ld b, a
push bc
ld a, VPAGE
out (PAGE1), a
ld hl, 0x4000
ld bc, 320 ; screen x size in bytes
ld e, l
di
ld d, d
ld a, 0x00 ; set accel lenght to 256 bytes
.loop: ld e, e ; fill vertical lines
ld (hl), e
ld b, b
inc hl
dec bc
ld a, b
or c
jr nz, .loop
ei
pop bc
ld a, b
out (PAGE1), a
ld a, c
out (YPORT), a ; restore modify ports
ret
;[]=======================================================================[]
; Copy memory with sprinter accel
; Input:
; hl - from
; de - to
; bc - size
; Output:
; hl - hl + size
; de - de + size
AccelCopy:
ld a, b
or a
jr z, .next
di
ld d, d ; set accel count to 256
ld a, 0x00
.loop1: ld l, l
ld a, (hl)
ld (de), a
ld b, b
inc h
inc d
djnz .loop1
ei
.next:
ld a, c
or a
ret z
ld (.count + 1), a
di
ld d, d
.count: ld a, 0x00
ld l, l
ld a, (hl)
ld (de), a
ld b, b
ei
ld a, c
add a, l
ld l, a
ld a, h
adc a, l
sub l
ld h, a ; update hl
ld a, c
add a, e
ld e, a
ret nc
inc d ; update de
ret
;[]=======================================================================[]
HelpString:
db 0x0D, 0x0A
db "The Flames! Mini demo for Sprinter.", 0x0D, 0x0A
db "Created by Enin Anton.", 0x0D, 0x0A, 0x00