;[]=======================================================================[] ; ; 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