This is my third attempt at a 256 bytes twister effect, in hires (mode 2 - 640×200), fullscreen and twisting at fullframe rate. I wanted to do a great looking lighting/dithering effect applied to the twister but I failed to squeeze it into 256 bytes. So I ended up with a much simpler and not so good looking dithering effect, but it fits the size limitation. It was released at Forever Next 2009 (and was unfortunately the only CPC entry, thus the CPC compo was canceled). » Twither (DSK and sources included). |
The twister is 256 pixels wide with 256 twisting-steps. It requires 64Kb RAM and should work on CRTC type 0,1 or 3 (probably 4 too). CRTC type 2 is not supported. See readme.txt
to hack the intro and play with the colors.
“Twither (Arkos).asm”
in the Assembler window.; _____ __ ; / _ \_______| | ______ ______ ; / /_\ \_ __ \ |/ / _ \/ ___/ ; / | \ | \/ < <_> )___ \ ; \____|__ /__| |__|_ \____/____ > ; \/ \/ \/ ; Twither, a 256 bytes intro presented at Forever 2009. ; (252 bytes exactly =) ; ; Hires(640x200) and fullscreen twister bar with some sort ; of dithering effet (not exactly what I planned first but ; I miserably failed to squeeze it all in 256 bytes =). ; ; The twister is 256 (mode 2) pixels wide with 256 steps. ; ; It works on CRTC type 0, 1 and 3. ; It should work on CRTC type 4 (not tested) ; It simply can't work on CRTC type 2. ; ; Grim/Arkos^Semilanceata ; ; NOTES ; - content at &0Cxx corrupted by the fx 64us innerloop, DO NOT USE! ;*** Configuration ************************************************************ ; Compile a small build test-code and debug stuff rubberbar_debug equ 1 ; Configure CRTC synchronization ; &E0 - Type 0. ; &F0 - Type 1, 3 (probably 4). rubberbar_cnf_crtcsync equ &F0 ; Sinus lookup tables addresses rubberbar_data_lut_sinus1024 equ &8800 rubberbar_data_lut_sinus256 equ &0900 ; opt - hibyte used as CRTC Select reg 9 ;****************************************************************************** if rubberbar_debug org &9F00 run $ ; clear screen ld a,2 call &BC0E jp rubberbar_exec else run rubberbar_exec endif org &A000 ; Dithering patterns rubberbar_data_dither_seq db 1,17,21,85,87,119,127,255 ;rubberbar_data_dither_seq db 255,127,119,87,85,21,17,1 rubberbar_exec: ; disable 300Hz interrupts di ; select screen mode 2 ld bc,&7F8E out (c),c ; set ink 1 color to red (&4C) ld de,&014C out (c),d out (c),e ; Wild CRTC 6845 initialization ld hl,&0701 ;ld de,&0100+16 ld e,16 call rubberbar_crtset ;*** Generate a 1024 bytes sinus (8bits unsigned) lookup table ***************** cnf_math_singen_sizeopt_store equ rubberbar_data_lut_sinus1024 cnf_math_singen_inline equ 1 cnf_math_singen_unsigned equ 1 read "math.singen.sizeopt.lib.asm" ; Output ; HL=0 ; DE=0 ; BC=1 ; save HL=&0000 (used as VRAM pointer later) push hl ; clear vram inc e ld (hl),l ld bc,&87FF ldir ;*** Generate a 256 bytes sinus (8bits unsigned) lookup table ****************** ; 256 bytes sinus ;ld h,rubberbar_data_lut_sinus1024/256 inc hl ld d,rubberbar_data_lut_sinus256/256 ld c,4 _rubberbar_256b_singen_loop ld a,(hl) add a,e ld (de),a add hl,bc inc e jr nz,_rubberbar_256b_singen_loop ;*** Generate the twisterbar graphic ******************************************* ld hl,rubberbar_data_lut_sinus1024 + &180 ; pi/2+pi/4 exx pop hl ;ld hl,&0000 call rubberbar_generator call rubberbar_generator ;*** 50Hz Twister display loop ************************************************* ; *** 50Hz loop *** rubberbar_sync ld b,&F5 in a,(c) rra jr nc,rubberbar_sync+2 ; On first frame, VCC will overflow, and the ; display will be fucked up. No space to waste ; for a clean first 20ms frame =) ; CRTC0 => Wait VCC=2 & VLC=7 (last scanline) ; CRTC1 => Wait VCC=0 & VLC=0 (new screen) ld b,rubberbar_cnf_crtcsync djnz $ ; setup CRTC for rubberbar fx ld hl,&0400 ld de,&0900 ; doube usage, &0900 => CRTCReg9=0 & 256bytes sinus LUT address call rubberbar_crtset ; update twister-sin pointers ld hl,&0131 _rubberbar_var_sinptr equ $-2 ld bc,&FD04 add hl,bc ld (_rubberbar_var_sinptr),hl ld e,h ld h,d ;ld h,rubberbar_data_lut_sinus256/256 ;ld d,h ; rubberbar height (rasterlines) ld bc,287 ; *** 64us innerloop *** _rubberbar_fx_loop ; A=(sin(DE)+sin(HL)) AND 255 ld a,(de) inc e add a,(hl) inc l exx ; convert A into screen offset ld h,&0C ld (hl),a xor a rld ld d,a ld e,(hl) ; AE=%xxxxPPLL.LLLL0000 and h ;%1100 = &C add a,a add a,a or d ; AE=%xxPPxxLL.LLLL0000 ld l,a ld d,&0D call rubberbar_crtset exx ; 64us rasterline loop dec bc ld a,b or c jr nz,_rubberbar_fx_loop ; *** end of splitscreen *** ;ld hl,&0907 ld l,7 ld de,&0402 call rubberbar_crtset ; loop forever jr rubberbar_sync ;*** Subroutines *************************************************************** rubberbar_crtset: ; write two CRTC registers ld b,&BC out (c),h ; select register inc b out (c),l ; write register dec b out (c),d ; select register inc b out (c),e ; write register ret rubberbar_generator: ; draw 64 lines of the twister per 16k page. ; there's 4 pages => 256 lines. Only the firsts ; &800 bytes of each pages is used. ld b,64 _rubberbar_generator_16k ;save vram pointer push hl dec l exx ; save sin pointer push hl ; read x1 = cos(a+45) ld a,(hl) ld c,a ; set the plotter to the x1 position exx inc a ld c,%0000001 _rubberbar_generator_locate rrc c jr nc,$+2+1 inc l dec a jr nz,_rubberbar_generator_locate exx ; read x2 = cos(a-45) dec h ;res 2,h ld a,(hl) sub c ; x2-x1 = Line lenght ld b,a _rubberbar_generator_plot ; 8bits dither level ld a,(hl) ;res 2,h ; 3bits dither index rlca rlca rlca and %111 ; 8bits dither value ld e,a ld d,rubberbar_data_dither_seq/256 ld a,(de) ; read dithering byte ; plot pixel exx and c ; apply bitmask or (hl) ; merge with vram ld (hl),a rrc c ; next pixel, rotate bitmask jr nc,$+3 inc hl ; move to next byte exx jr nc,$+3 inc hl ; repeat for line-lenght pixels djnz _rubberbar_generator_plot _rubberbar_generator_plot_skip ; restore sin pointer pop hl ; move to next angle (0, 511) inc hl ;res 2,h exx ; move to the next line pop hl ld de,32 add hl,de djnz _rubberbar_generator_16k ; move to the next 16k page ld de,&3800 add hl,de jr nc,rubberbar_generator ; exit after 4x16k pages processed ret