Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - boogop

Pages: [1]
ASM / Plasma in 128b FASM source
« on: October 31, 2018 »
Because the world needs more cruddy asm lol. At one point I had this down to like 106b but I was losing quality, it looked less plasma-y and more like some weird sinusoidal blob. This captures some of the feel of Argon by Matrix which I really like

Code: [Select]
;▒ 10/2018 by Boogop
;▒  Plasma in 128 bytes
;▒      FASM source
;▒ Acknowledgements:
;▒ - wally/rage for the sin generator and rbz for
;▒   the analysis thereof
org 100h

mov     al,13h              ; set mode 13
int     10h
push    0a000h              ; stick video segment in es
pop     es

;------- set palette ---------
xor     ax,ax
mov     dx, 3c9h            ; who needs 3c8h!
@redup:                     ; red-blue palette
out     dx,al
xchg    al,ah
out     dx,al
out     dx,al
xchg    al,ah
inc     al
cmp     al,127
jne     @redup
xchg    al,ah
out     dx,al
out     dx,al
xchg    al,ah
out     dx,al
dec     al
jnz     @bluedn

mov     cx,783Fh            ; harmonic oscillator by wally/rage
xor     si,si
mov     ax,65497
imul    cx
add     si,dx
add     cx,si
mov     [bx],ch
sar     byte [bx],1
dec     bx
cmp     bx,16383
jne     sin1
mov     si,bx

xor     di,di               ; Reset vga position
mov     cx,[p_pos1]         ; stick position val into cx
mov     ax,255              ; magic number. imul leaves result
imul    cx                  ; in dx:ax which will do for dx vals
mov     ah,160              ; X counter. since we're using stosw
                            ; we only have to loop 320/2 times
push    ax
                            ; plasma calcs
mov     bl,dl
add     ax,[si+bx]
mov     bl,dh
add     bl,cl
add     ax,[si+bx]
mov     bl,cl
add     ax,[si+bx]
mov     bl,ch
sub     bl,dl
add     ax,[si+bx]
pop     ax
add     dx,0102h            ; add movement
dec     ah                  ; decrement the x counter
jnz     @x_loop             ; test for 0
add     cx,0102h            ; add movement
cmp     di,320*200          ; use di for the y_loop counter
jb      @y_loop             ; test for 0
inc     [p_pos1]
nop                         ; pad to 128 bytes lol
jmp      @main

p_pos1      dw 0


ASM / Fire in 159b FASM source
« on: October 25, 2018 »
Started this in TASM but switched to FASM because I really should make some kind of attempt to update myself. Originally 170-something bytes, took some work getting it down to 159. Remove the text, pallete rot and exit logic and it should be 97 bytes.

boogop greets: ralf brown's interrupt list lol

Code: [Select]

;▒ 10/2018 by Boogop
;▒  Boring Old Fire in 159 bytes
;▒ Acknowledgements:
;▒ - raven/tektonic,preacher/traction and others for
;▒   the adc idea, really makes it look demo-y
;▒ requirements
;▒ - must have a halloween message referencing dbf
;▒ - fire must not look like suck
;▒ - text shouldn't be white
;▒ - must have appropriate exit logic

org 100h

; in we trust
; assume ax = 0, if not we're in trouble ;)
mov     al,13h                  ; enter classic demo world
int     10h

xchg    al,ah                   ; al=13h,ah=0 after setting video mode. Switch those
                                ; to get the draw string function in ah and save 2 bytes
                                ; setting al=0 uses color attributes in bl
; draw text
mov     bl,128                  ; color index, we'll rotate it later
mov     cl,24                   ; string length
mov     dx,0107h                ; dl=7 dh=1 column 7 row 1
mov     bp,foo
int     10h

; set palette
xor     ax,ax
mov     dx, 3c9h                ; who needs 3c8h!

@redup:                         ; Set colors 0-64, ramp up red
out     dx,al                   ; set red to value in al
xchg    al,ah                   ; green & blue get 0
out     dx,al                   ; the xchg commands seem unavoidable
out     dx,al
xchg    al,ah
inc     ax                      ; 1 byte smaller than inc al
cmp     al,64
jne     @redup

@yellowdn:                      ; we'll add some yellow for the lols
out     dx,al
out     dx,al
xchg    al,ah
out     dx,al
xchg    al,ah
dec     ax
jnz     @yellowdn               ; don't need cmp al,0

push    0a000h                  ; ds:si is smaller than es:di
pop     ds                      ; by about 6 bytes it seems (why??)


; fire
mov     si,(199*320)            ; bottom line, y * xres
mov     cx,320                  ; screen_w
in      al,40h                  ; the better looking prods tend to use
                                ; rng's, but for my purposes 40h does
mov     [ds:si],al              ; just fine
inc     si ; using the ds: prefix isn't necessary
loop    @randline ; but makes things a little clearer
mov     si,(320*20)             ; we're moving forwards through video
                                ; memory, some move backwards. Skip the
                                ; first 20 lines for the text so it doesn't
@draw:                          ; melt
mov     al,[ds:si]              ; add the surrounding pixels
shl     ax,2                    ;
add     al,[ds:si+1]            ;
adc     ah,0                    ; if the carry flag is set, add 1 to ah
add     al,[ds:si+320]          ;
adc     ah,0                    ;
add     al,[ds:si-1]            ;
adc     ah,0
add     al,[ds:si+640]          ; add the pixel 2 rows above for higher flame
adc     ah,0                    ; ah += 0 + cf
shr     ax,3
;or ax,00111101b                ; uncomment for weird effect lol

                                ; don't let al wrap, you get lots of
jz      @nozero                 ; noise on the screen
dec     ax
mov     [ds:si-320],al          ; put the pixel back on the row below
inc     si
jnz     @draw                   ; if it's wrapped to 0 we've reached the end of the screen

inc     bh
mov     dx,3C8h
mov     al,128                  ; rotate palette index 128
out     dx,al
inc     dx
mov     al,bh                   ; increment red & green together
out     dx,al
out     dx,al
sub     al,32                   ; stick blue 32 behind them for great justice
out     dx,al                   ; we could save 2 bytes by making it white but
                                ; that looks like crap

in      al,60h                  ; check keypress
dec     ax                      ; escape key = 01h, dec 01h = 0
jnz     @main                   ; dex ax one byte smaller than dec al

; exit stuff
mov al,03h
int 10h


foo db 'Halloween greets to DBF!'

Only barely has something to do with Halloween!

Written in FASM, includes text, palette rotation and exit logic. Without those it's 97b. I'll put the source up on \asm because why not. Works in DOSBox but that's about all I tried. I'm going on some assumptions about initial register states that may cause it to blow up elsewhere lol

ASM / How to preserve the background color?
« on: September 25, 2018 »

So there I was doing some copper(-ish) bars using the tried and true method of 'draw lines and rotate the palette.' How to I preserve the background color? Pic should be attached. It rotates along with everything else  :telloff:

Code: [Select]

; tasm [blah]
; tlink [blah]

MODEL SMALL             
.STACK 200H   


palindex    db 0
upperstop   dw 320*50
lowerstart  dw 320*150
endscreen   dw 320*200

Palette     LABEL BYTE
        REPT 42
            db i/2,i,i/3     

        REPT 42
            db i/2,i,i/3   

        REPT 52 ; make the reds a little more coppery
            db i,i/2,i/3     

        REPT 52
            db i,i/2,i/3   

        REPT 32 ; less avail for blue but that's okay
            db i/2,i/3,i   

        REPT 32
            db i/2,i/3,i   


Set_Palette PROC
        mov     ax,SEG Palette       
        mov     ds,ax
        mov     si,OFFSET Palette
        mov     dx,3C8h
        xor     al,al
        out     dx,al
        inc     dx
        mov     cx,(256*3)
        rep     outsb


mov     ax,13h              ; set mode 13
int     10h
push    0a000h              ; stick video segment in es
pop     es

;------- set palette ---------   

call Set_Palette

; ------ main loop ----------


mov     di,lowerstart ; draw some lines along the bottom of the screen


mov     ax,di
sub     ax,lowerstart
shr     ax,1
shl     ax,3
cmp     di,endscreen
jb      lower

xor     di,di

upper:              ; xor the colors and draw along the top

mov     ax,di
shr       ax,1
shl       ax,3
xor       al, 11111000b
cmp     di,upperstop
jb        upper

; ------ rotate ----------
; michael abrash this isn't

inc       palindex

mov     si,OFFSET Palette
mov     dx, 3C8h
mov     al, palindex
out      dx, al
inc       dx
mov     cx, (256*3)
rep      outsb

in        al, 60h             
cmp     al, 01h             
jnz      main               

;------- exit stuff ---------
mov     ax,3               
int       10h

mov     ah,4CH             
mov     al,00H
int       21H

END Start 

ASM / sine generator in TASM
« on: August 14, 2018 »

I'm working on a small plasma in TASM. It's very vanilla and not very interesting except for the sine generator. I was struggling with a big list of sine constants (originally I'd exported them from c#, double d = 32 + 32 * Math.Cos((i * 6.28) / 256)) when I came upon this generator in a prod by insomniac/matrix. But I'm not good enough at asm to tell exactly how it's working, except that wally/rage (??) was pretty darn clever. 188 bytes but I'm also getting some annoying color banding from stosw

Code: [Select]
; tasm /m2
; tlink /t

cseg    segment
assume cs:cseg
org 0100h

    mov     ax,13h              ; set mode 13
    int       10h
    push    0a000h              ; stick video segment in es
    pop      es
    mov     dx,3c8h             ; set color index port
    xor       ax,ax
    out       dx,al                ; output color index 0
    inc       dx                    ; inc dx = 3C9h, color write port
@redup:                          ; Set colors 0-62, ramp up red
    out      dx,al                  ; set red to value in al
    xchg    al,ah                 ; ah is 0, so exchange it with al
    out      dx,al                  ; set green and blue = 0
    out      dx,al
    xchg    al,ah               ; swap ah/al so al is again non-zero
    inc      al                     ; al +=1
    cmp     al,63
    jne     @redup
@reddn:                         ;set colors 63-127, ramp down red
    out     dx,al
    xchg    al,ah
    out     dx,al
    out     dx,al
    xchg    al,ah
    dec     al
    jnz     @reddn
@blueup:                        ;set colors 127-194, ramp up blue
    xchg    al,ah
    out     dx,al
    out     dx,al
    xchg    al,ah
    out     dx,al
    inc     al
    cmp     al,63
    jne     @blueup
@bluedn:                        ;set 194-256, ramp down blue
    xchg    al,ah
    out     dx,al
    out     dx,al
    xchg    al,ah
    out     dx,al
    dec     al
    jnz     @bluedn
                                ; sin generator from argon by insomnia/matrix
                                ; who got it from Wally/Rage, but I'm not sure
                                ; who that was. There was a Rage demogroup
                                ; in the amiga scene. Anyway, credit to the
                                ; original author. My big list of sin constants
                                ; was taking up ~200 bytes

    mov     cx,783Fh            ; [30783]
    xor     si,si
    mov     ax,65497
    imul    cx                  ;[2016194151]
    add     si,dx               ; results of imul are stored in dx:ax [782C AE67, si+=30764]
    add     cx,si               ; [783F + 782C,cx=30783+30764=61547=F06B]
    mov     [bx],ch             ; [[bx]=F0=240]
    sar     byte ptr [bx],1     ; divide the value by 2, only store a byte [bx=120?]
    dec     bx                 
    cmp     bx,16383           
    jne     sin1

   ; inc     bx                  ; BX points to the sine/cos-values [comment by insomnia but this step isn't needed and saves a byte]
    mov     si,bx               ; move it to SI since I need BX


;------- main program ------------
    xor     di,di               ; Reset vga position

    mov     cl,[p_pos1]         ; stick plasma position values into ch,cl
    mov     ch,[p_pos2]

    mov     ah,200              ; 200 rows in mode 13               
    push    ax                  ; ax is also our x counter, so save
                                    ; the y vals to test later
    mov     dl,[p_pos3]         ; the other position values in dh,dl
    mov     dh,[p_pos4]         ; now the plasma position vals are in cx/dx

    mov     ah,160              ; X counter. since we're using stosw we only have to loop 320/2 times
    xor     al,al               ; al holds the color, so clear it

                                ; x = SinTable[p_pos1] + SinTable[p_pos2] + SinTable[p_pos3] + SinTable[p_pos4]
    mov     bl,dl               ; mov p_pos3 into bl   
    add     al,si[bx]           ; x += Sin[p_pos3]
    mov     bl,dh               ; mov p_pos4 into bl   
    add     al,si[bx]           ; x += Sin[p_pos4]
    mov     bl,cl               ; mov p_pos1 into bl   
    add     al,si[bx]           ; x += Sin[p_pos1]
    mov     bl,ch               ; mov p_pos2 into bl   
    add     al,si[bx]           ; x += Sin[p_pos2]

    ; push    cx                ; save the position vals
    ; mov     cx,4              ; write 4 pixels at a time
    ; rep     stosb             ; put pixel cx times in es:di, advancing the screen pointer
    ; pop     cx                ; restore position vals
    stosw                       ; stosw is smaller than that noise

    add     dl,2                ; add movement var to p_pos3
    add     dh,1                ; add movement var to p_pos4

    dec     ah                  ; decrement the x counter
    jnz     X_LOOP              ; test for 0

    add     cl,2                ; add movement var to p_pos1
    add     ch,3                ; add movement var to p_pos2

    pop     ax                  ; restore the y counter
    dec     ah                  ; Next vertical line
    jnz     Y_LOOP              ; test for 0

    add     [p_pos1],2          ; add some vals to the position vars
    add     [p_pos2],3          ; speed up/slow down the plasma
    sub     [p_pos3],1
    add     [p_pos4],4

    jmp     main                ; do it all again
    p_pos1   db 0
    p_pos2   db 0
    p_pos3   db 0
    p_pos4   db 0

    ; SinTable  db 64,63,63,63,63,63,63,63,63,63
    ; db 63,62,62,62,62,61,61,61,60,60
    ; db 60,59,59,59,58,58,57,57,56,56
    ; db 55,55,54,54,53,52,52,51,51,50
    ; db 49,49,48,47,47,46,45,44,44,43
    ; db 42,42,41,40,39,39,38,37,36,35
    ; db 35,34,33,32,32,31,30,29,28,28
    ; db 27,26,25,25,24,23,22,21,21,20
    ; db 19,19,18,17,16,16,15,14,14,13
    ; db 12,12,11,11,10,9,9,8,8,7
    ; db 7,6,6,5,5,4,4,4,3,3
    ; db 3,2,2,2,1,1,1,1,0,0
    ; db 0,0,0,0,0,0,0,0,0,0
    ; db 0,0,0,0,0,0,0,0,0,1
    ; db 1,1,1,2,2,2,3,3,3,4
    ; db 4,4,5,5,6,6,7,7,8,8
    ; db 9,9,10,11,11,12,12,13,14,14
    ; db 15,16,16,17,18,18,19,20,21,21
    ; db 22,23,24,24,25,26,27,28,28,29
    ; db 30,31,31,32,33,34,35,35,36,37
    ; db 38,38,39,40,41,41,42,43,44,44
    ; db 45,46,47,47,48,49,49,50,50,51
    ; db 52,52,53,54,54,55,55,56,56,57
    ; db 57,58,58,58,59,59,60,60,60,61
    ; db 61,61,62,62,62,62,63,63,63,63
    ; db 63,63,63,63,63,63

cseg ends

End Start

General coding questions / voxel waves
« on: April 04, 2018 »
Does anyone know of or have an example of this effect, the one that future crew had in second reality? The only example I've been able to find is by Insolit Dust who used to post here, but it's difficult to read and has enough hardcoded values that I can't really tell what it's trying to do. Any language should be okay, but it's more difficult for me to deconstruct an xy location if the video is addressed like unsigned char *b = DBuf + (a << 8) + (a << 6) + i;

snippet from insolit dust, he posted a link to his site here so I hope this is okay!

Code: [Select]
void Line(int x0, int y0, int x1, int y1, int hy, int s)
register int i;
     int sx, sy;
     int c,y,h,u0,v0,u1,v1,a,b,h0,h1,h2,h3;
     sx = (x1 - x0) / 320;
     sy = (y1 - y0) / 320;
     for (i = 0; i < 320; i++)
         u0 = (x0 >> 16) & 0xFF;
         a = (x0 >> 8) & 255;
         v0 = ((y0 >> 8) & 0xFF00);
         b = (y0 >> 8) & 255;
         u1 = (u0 + 1) & 0xFF;
         v1 = (v0 + 256) & 0xFF00;
         h0 = HMap[u0 + v0];
         h2 = HMap[u0 + v1];
         h1 = HMap[u1 + v0];
         h3 = HMap[u1 + v1];
         h0 = (h0 << 8) + a * (h1 - h0);
         h2 = (h2 << 8) + a * (h3 - h2);
         h = ((h0 << 8) + b * (h2 - h0)) >> 16;
         h0 = CMap[u0 + v0];
         h2 = CMap[u0 + v1];
         h1 = CMap[u1 + v0];
         h3 = CMap[u1 + v1];
         h0 = (h0 << 8) + a * (h1 - h0);
         h2 = (h2 << 8) + a * (h3 - h2);
         c = ((h0 << 8) + b * (h2 - h0));
         y = (((h - hy) * s) >> 11) + (240 / 2);
         if (y < (a = LastY[i]))
                unsigned char *b = DBuf + (a << 8) + (a << 6) + i;
                int sc,cc;
                if (LastC[i] == -1)
                   LastC[i] = c;
                sc = (c - LastC[i]) / (a - y);
                cc = LastC[i];
                if (a > 240 - 1)
                      b -= (a - (240 - 1)) * 320;
                      cc += (a - (240 - 1)) * sc;
                      a = 240 - 1;
                if (y < 0)
                   y = 0;
                while (y < a)
                      *b = cc >> 18;
                      cc += sc;
                      b -= 320;
                LastY[i] = y;
         LastC[i] = c;
         x0 += sx;
         y0 += sy;

Boogop's amazing summer demo! Loaded with ancient crusty effects you've seen a gorillion times before! Absolutely no new ground broken whatsoever!

Kludged up in Freebasic, Tinyptc_ext by RBZ, FMod for music (could have used Tinyptc_ext++ herp derp), FPS limiter by RBRAZ, FFNT_Lib by Deleter. Music is d3.mod by Necros. Is there anything in here by me?!

Freebasic / Dot Tunnel
« on: November 17, 2016 »
Dot tunnels gave me fits trying to figure out. So here's one for the lulz, maybe it will help (or hinder) someone else!

Code: [Select]
' by boogop
' The c# logic from my entry for the Amiga
' demo a year or so ago
' - now in glorious lo-res!
' For me, dot tunnels were the hardest effect
' to figure out. There didn't seem to be many
' examples (before I found dbfinteractive, on
' which there are several) and the ones I could
' find on the intarnets or hornet archive were
' frequently not very good. Some of them
' weren't tunnels at all, they were tubes with the
' rings fixed in place. The best one I ever saw
' was Crystal2 BBS addy by Xography but they never
' released the source, and I haven't been able to
' figure out how they were handling the movement path

#include ""

' screen dimensions & put_pixel routine
const screenWidth = 320
const screenHeight = 200
const SCR_SIZE as integer = screenWidth*screenHeight

dim shared buffer( 0 to SCR_SIZE-1 ) as integer
dim shared as uinteger ptr pntr
dim shared as integer ptr p

declare sub put_pixel(buffer() as integer, byval x as integer, byval y as integer, byval col as integer)

' this may be Shockwave's routine!
sub put_pixel(buffer() as integer, byval x as integer, byval y as integer, byval col as integer)

    if(y < screenHeight -1 and y > 1) then
        if( x < screenWidth-1 and x > 1 ) then
            PNTR = @buffer(y * screenWidth + x)   
                mov eax, dword ptr[col]
                mov edi, [pntr]               
            end asm           
        end if
    end if

end sub

' declare variables
type colors
    dim as integer r,g,b
end type

dim shared as colors colArray(256)

const _pointsPerCircle = 20
const _numCircles = 35
dim shared as double zDistance = 8

' named star because I lifted it from my 3d starfield code :)
type star
    dim as double xpos, ypos, speed, zpos
    dim as double origX, origY, origZ
    dim as integer oldx,oldy
end type

dim shared as star circles(_numCircles, _pointsPerCircle)

dim shared as double maxZ = 0
dim shared as double diam = 50
dim shared as double xp,yp,zp,increment, px, py, skew, skewCount
dim shared as integer angle = 0
dim shared as double zPos = 1
dim shared as integer angleAdder = int(360 / _pointsPerCircle)     
dim shared as double zPosAdder
dim shared as double midWidth = screenWidth / 2
dim shared as double midHeight = screenHeight / 2
dim as integer i,j, xpathcount
dim as double rad = 3.1416 / 180.0

' set initial values
skewCount = .0001
zPosAdder = zDistance / _numCircles

for  j = 0 to  _numCircles
    for  i = 0 to _pointsPerCircle
      dim as double Y =  diam * Sin(angle * rad)
      dim as double X = 2 * diam * Cos(angle * rad) ' make it oval shaped for the lulz
      circles(j, i).xpos = X
      circles(j, i).ypos = Y
      circles(j, i).speed = .0025
      circles(j, i).zpos = zPos
      circles(j, i).origX = X
      circles(j, i).origY = Y     
      circles(j, i).oldx = 0
      circles(j, i).oldy = 0
      angle += angleAdder
    next i
zPos += zPosAdder
next j

maxZ = 0

' figure out the largest z value
for  j = 0 to _numCircles
    for i = 0 to _pointsPerCircle     
        if circles(j, i).zpos > maxZ then
            maxZ = circles(j, i).zpos
        end if   
    next i
next j

increment = 0

' fill color array     
i = 0
while i < 256     
    dim as single red = 1 + Cos(i * 3.14 / 128)
    dim as single grn = 1 + Cos((i - 85) * 3.14 / 128)
    dim as single blu = 1 + Cos((i + 85) * 3.14 / 128)
    colArray(i).r = int(red * 127) mod 256
    colArray(i).g = int(grn * 127) mod 256
    colArray(i).b = int(blu * 127) mod 256
    i = i+1

' run the thing

if( ptc_open( "freeBASIC - tinyPTC Dot Tunnel", screenWidth, screenHeight ) = 0 ) then
    end -1
end if

while inkey() <> chr(27)   
    if skew <= 1 then
        skew = skew + skewcount
    end if
    for  i = 0 to _numCircles
        for  j = 0 to _pointsPerCircle
           ' erase the last point
            put_pixel Buffer(),circles(i, j).oldx,circles(i, j).oldy,0
            put_pixel Buffer(),circles(i, j).oldx+1,circles(i, j).oldy,0
            ' bring each circle towards the viewer
            circles(i, j).zpos -= circles(i, j).speed
            ' if a circle is close enough to the viewer, send it to the back
            ' using the maximum z value
            if circles(i, j).zpos < 2 then           
                circles(i, j).xpos = circles(i, j).origX
                circles(i, j).ypos = circles(i, j).origY
                circles(i, j).zpos = maxZ
            end if
            ' most compilers will perform some kind of bounds checks, and those
            ' will really bog an app down. Cast the array to vars so any bounds
            ' checking only has to happen once
            xp = circles(i, j).xpos
            yp = circles(i, j).ypos
            zp = circles(i, j).zpos
            ' kludgey color fader lol
            dim as double cc = 1 - Abs(zp / (maxZ * .8))
            if (cc < 0) then
                cc = 0
            end if
            if (cc > 1) then
                cc = 1
            end if
            dim as integer c = int(300 * cc)
            if c > 255 then
                c = 255
            end if
            dim as integer co = rgb(colArray(c).b,colArray(c).r,colArray(c).g)
            if zp > int(maxZ * .6) then
                co = rgb(colArray(c).b/2,c,c)
            end if       
           ' zpos isn't quite right and doesn't bring the circles as close
           ' as it should but I don't feel like fixing it!
            dim as double z = zp - 1.5
            ' path of the tunnel
            px = 50 * Sin(z * skew * sin(increment))
            py = 40 * Cos(z * skew * cos(increment))           
            ' calculate perspective, add path, align to center screen
            dim as double sx = (xp / z) + px + midWidth
            dim as double sy = (yp / z) - py + midHeight
            dim as integer ix = int(sx)
            dim as integer iy = int(sy)
            put_pixel Buffer(),ix,iy,co
            put_pixel Buffer(),ix+1,iy,co           
            ' save the current pos so we can erase it in the next iteration
            circles(i, j).oldx = ix
            circles(i, j).oldy = iy
        next j
    next i   
    increment +=.0005   
    ptc_update @buffer(0)


Freebasic / Fractal Zoomer
« on: November 09, 2016 »
Here's a version of the fractal zoomer from R.I.P. Boogop converted to freeBasic/ASM. I'd love to figure out a way around having to iterate over each pixel 300 times because that's where all your performance goes. It drives me nuts. This seems about as optimized as I know how to make it; if you focus optimizing anywhere else but the iteration loop it's a red herring, that loop is the killer. There are ideas around to split the screen in half and render each half in a separate thread, but that's still working around the central problem of the inability to determine if an equation is going to go to infinity without doing it 300 times.

On my work PC (LoMem Kludge-0-Matic 100) I get to the lose-resolution point in about 22 seconds. If you want to go deeper you'll need to tweak horizPosAdjust and vertPosAdjust to position yourself where you want to be

Code: [Select]
' by boogop
' this may be a little faster than the FB version
' but I'm sure I've done lots of stuff wrong or fb
' is just smarter than I am lol
' Where this loses resolution is about the limit
' of a single data type. Converting to double will
' zoom farther in but also take longer

#include ""

' 350 x 325 to size it the same as the c# effect
dim shared as integer screenWidth = 320
dim shared as integer screenHeight = 200
const SCR_SIZE as integer = 320*200

dim shared as integer ptr p

dim shared buffer( 0 to SCR_SIZE-1 ) as integer
dim shared as uinteger ptr pntr

dim shared as integer w, h, h2

' initial vals
dim shared as single a1 = -2.5
dim shared as single b1 = -1.5
dim shared as single ax1 = -2.5
dim shared as single ax2 = 1.5
dim shared as single bx1 = -1.5
dim shared as single bx2 = 1.6

dim shared as single bailnum = 2.0
dim shared as single bailGT1 = 1.3
dim shared as single bailLT1 = -1.3

dim shared as single z1, z2, z3, dx, dy, crx, yy, cr, ci', dydx
dim shared as integer k = 0   

dim shared as single ww
dim shared as single hh
dim shared as single a1w, b1h
dim shared as single aw
dim shared as single bh

dim shared as single zoom = 1

dim shared as uinteger colSingle(300)

declare sub init
declare sub DrawMandelbrot
declare sub CreateMandelbrot(a1 as single, a2 as single, b1 as single, b2 as single)
declare sub put_pixel(buffer() as integer, byval x as integer, byval y as integer, byval col as integer)

sub init   
    w = screenWidth
    h = screenHeight   
    h2 = h / 2     
    ' these coords put us in scepter valley
    a1 = 153.41801 
    b1 = h2 - 8.650006   
    ' if you change the size of the window you have to figure out where in the
    ' mandelbrot set you are - not easy! >:(
    dim as single horizPosAdjust = 13.24
    dim as single vertPosAdjust = 1.5
    a1 = a1 - horizPosAdjust
    b1 = b1 - vertPosAdjust
    ww = ax2 - ax1
    hh = bx2 - bx1
    a1w = a1 * ww
    b1h = b1 * hh
    aw = a1w / w
    bh = b1h / h
    dim i as integer = 0
    ' usually the array would be dimensioned to 256 but if we set it to the
    ' number of iterations we can skip a mod operation
    while i < 300     
        dim as single red = 1 + Cos(i * 3.14 / 128)
        dim as single grn = 1 + Cos((i - 85) * 3.14 / 128)
        dim as single blu = 1 + Cos((i + 85) * 3.14 / 128)       
        dim as integer r = int(red * 127) mod 256
        dim as integer g = int(grn * 127) mod 256
        dim as integer b = int(blu * 127) mod 256
        colSingle(i) = rgb(r,g,b)     
        i = i+1
end sub

sub DrawMandelbrot   
    zoom = zoom + (zoom * .05)
    dim as single d = zoom + zoom
    dim as single wax = ww / d
    dim as single wah = hh / d   
    dim as single newleft = aw + ax1 - wax
    dim as single newright = aw + ax1 + wax
    dim as single newtop = bh + bx1 - wah
    dim as single newbottom = bh + bx1 + wah
    CreateMandelbrot(newleft, newright, newtop, newbottom)
end sub

sub CreateMandelbrot(a1 as single, a2 as single, b1 as single, b2 as single)
    p = @buffer(0)
    dim as single dr = (a2 - a1) / w
    dim as single di = (b2 - b1) / h
    dim as integer j = 0
    dim as integer i = 0
    dim as single temp, q, a, b
    dim as single dx1, dy1
    dim as single ptr t
    'dim as string key
    for j = 1 to h
        ci = b1 + j * di 
        for i = 0 to w-1
            cr = a1 + i * dr
            dx1 = 0.0
            dy1 = 0.0         
            ' PERIOD CHECKING
            ' if we can tell we're inside the cardiod or period-2 bulb we can skip the iterations.
            ' period checks make the routine blaze until we're past them but the iteration loop is
            ' the big problem
            crx = cr + 1.0
            yy = ci * ci
            if ((crx * crx) + yy < .0625) then
                ' checks for a point inside the period-2 bulb
                ' but once you're past that it does nothing
                *p = 0
                goto bail
            end if
            ' check for cardiod bulb
            temp = cr - .25
            t = @temp
           ' q = temp * temp + yy
            q = (*t) * (*t) + yy
            a = q * (q + *t)
            b = .25 * yy
            if (a < b) then
                *p = 0
                goto bail
            end if
            ' SSE ITERATION LOOP
            k = 0   
            ' 32 bit singles are only taking up 1/4 of these registers
                mov cx, 0
                movss xmm2, [ci]
                movss xmm3, [cr]
                movss xmm0, [dx1]
                mulss xmm0, xmm0
                movss [z1], xmm0        'z1 =  dx1 * dx1
                movss xmm1, [dy1] 
                mulss xmm1, xmm1   
                movss [z2], xmm1        'z2 =  dy1 * dy1               
                addss xmm0, xmm1        ' z1 + z2     
                comiss xmm0,[bailnum]   ' if z1 + z2 > 2.0
                ja @asmdone                 
                inc cx                  ' handle the iterations counter
                cmp cx, 300
                je @asmdone
                movss xmm0, [dx1]
                movss xmm1, [dy1]
                mulss xmm0, xmm1        ' dy1 * dx1               
                addss xmm0, xmm0        ' (dy1 * dx1) + (dy1 * dx1)               
                addss xmm0, xmm2        ' + ci
                movss [dy1],xmm0        'dy1 = (dy1 * dx1) + (dy1 * dx1) + ci               
                movss xmm0, [z1]
                movss xmm1, [z2]
                subps xmm0, xmm1        ' z1 - z2               
                addss xmm0, xmm3        ' + cr
                movss [dx1],xmm0        'dx1 = z1 - z2 + cr   
                jmp @starter           
                mov [k],cx
            end asm
            if k = 300 then
                *p = 0
                *p = colSingle(k)
            end if
            ' print k, z3, dx1, dy1
            ' key = INKEY
            ' WHILE key = "": key = INKEY: WEND
            p = p + 1
        next i
    next j
end sub

ptc_open( "tinyPTC Mandelbrot test", screenWidth, screenHeight )

'dim as string key
'print "Press to start"
'WHILE key = "": key = INKEY: WEND


dim as single t1,t2

t2 = timer
while inkey() <> chr(27)
    t1 = timer
    ptc_update @buffer(0)
    print t1 - t2

R.I.P BOOGOP (getting some halloween correlation is really reaching!)

C#, .NET 4, VS2015, SharpMod for music, hopefully most folks will be able to run it without having to install a bunch of cruddy .NET which you probably wouldn't do anyway! No frameworks, only GDI with getpixel/putpixel [pointer] routines and bmp.drawstring. The drawback to doing things that 'oldskool' way is I have to limit the form size to get acceptable performance (particularly for the fractal zoomer), do my own sucky 3D, load my own textures [into int arrays] blahblah.

optimizing assumptions
- must have a doevents each time through the demo loop for the app to behave while rendering
- add is faster than mult (old assumption that may no longer be valid)
- bounds checking gets exponentially worse with 2-dim arrays so use multiples of 1 whenever possible
- switch is faster than if due to jumptable opcodes
- C# is optimized for doubles
- using pointers anywhere but the actual drawing would p-r-o-b-a-b-l-y be slower (much discussion on this exists)
- use bitwise ops whenever possible (&=, >>, <<)

Notes on some of the FX (I really need to get out of the early 90's, man)

- my two problems with fractal zooming is the thing wants to spend longer and longer in the escape-time loop to get resolution at depth, and eventually you run into the limits of a double variable type. After I'd gotten the thing working I dug around in the IL and optimized it based on what I saw the compiler emitting, though I'm guessing on some of the commands (just for kicks I rewrote this in freebasic with ASM for the inner loop, SSE instruction set, and it was slow as crap. But it may be my retarded asm too)
- these are lulzy and look really oldskool if you live in the past like I do
- there's a few of these in here for ball-0-ween lolz
- I'm really pleased with this, I worked the problems out of the one I used in my last demo and tweaked it until it looks close to 'fake demo' by Pelusa which I love
- The problem with these is whatever I do with them they usually end up looking like Tumblin's 94 demo unless you just bounce them around like Scoopex, but that was less interesting
- I liked Argon by Matrix (1997), however this ain't that. I draw three plasmas on top of each other and skip the black values in the color array. What I've done is probably not a true tri-plasma and Argon seems to be doing some blending that eludes me. But even if I translated it directly it wouldn't look the same. STOSW in c# --> lololol
- a modification of the effect I used last time which drew the plasma then rotated the palette. This one attempts to do it in realtime by using values in arrays to redraw the map instead of getPixel each time which is a killer. For some reason this wants to migrate to the bottom right. Meh, palette rotation actually looks better.

skull graphic, palm tree and a few others from some public domain clipart collection I can't remember, openclipart maybe
Music is starlitdeception.mod by Necros. Dude was one of the best trackers ever
Font is some free thing but I call bmp.SetResolution(320, 200) which doesn't affect the actual drawing but causes the font to be rendered in glorious lo-res lol

I work in vs2015 c#,  which is a beautiful language,  but when you're stuck in the late 80s and early 90's and stupidly insist on doing everything yourself without frameworks it chafes. There is no getting away from GDI. Is it even possible to access the graphics hardware directly anymore without resorting to a framework?  I see a lot of acronyms going around,  which have you had experience with? Any support asm? Basically I'm feeling the itch for something lower level than current Microsoft technologies.

(and if there was any way it could resemble 'work' that would be a plus lol)

Here's my contribution to the Amiga anniversary compo!

Written in C#, .NET4, GDI+ only. No OpenGL, no DirectX. Just what I could do with getpixel/putpixel routines. Seemed fitting!

Back in the day some of the old demos required a pretty good PC to run. Now that PCs are blazingly fast it's brutally ironic that since I'm using just GDI SO DOES MINE!!! lol  :-[

It's a sad state of affairs that those old Amiga guys wrote their intros and cracktros in asm on primitive computers and what they did STILL LOOKS BETTER THAN MINE!  :clap: Respect!

Projects / App store approved my demo!
« on: April 07, 2011 »
(or demo-ish app) --> IntroFX

If you've got an iPhoan, go to the app store and it's under 'Entertainment.' Or search on 'IntroFX.' The app was originally titled 'DemoFX' but I scrubbed all references to 'Demo' due to Apple's cryptic guidelines against the word.

- Scrolling checkerboard/floor: totally cheating. I use textures instead of calculating.
- Dot sphere: there's a perspective problem. Damned if I can figure it out
- Twisty bars: slower than hell due to iOS's miserable implementation of GL_POINTS, much worse on an iPad. I should have just taken it out.
- Plasma square: clipping problem I forgot to fix
- iPad: touches only work in the upper left quadrant, again due to retarded programmer :whack:

A word on the greets

va!n staticgerbil xalthorn dr.death - they responded to my original thread!
FC - though Future Crew hasn't been around for years, same with Kefrens, 2nd Reality and Desert Dream are still my favorite demos
Jare, Raphius,Denthor for their tutorials back in the day
Jeff Molofee because a lot of folks who code in openGL owe as much to him as the old scene owed to Michael Abrash
dbfinteractive - so you guys get blamed!  O0

So...some parts are a little glitchy but most work, and with the music and greets it should get the idea across.

General coding questions / iPhone Demo
« on: December 17, 2010 »
Longtime lurker here. I thought you guys might be interested in this--I'm finishing up a retro demo for the iPhone. To my knowlege this hasn't been done before, at least I've never seen a real demo in the app store. There are a couple showing demo type effects, but no real oldschool demo.

I'm doing this in Objective-C on a Mac mini. Obj-C is basically a wrapper for C, but contains enough Mac weirdness to make it a challenge. It takes a subset of OpenGL that doesn't offer quads or the predefined shapes in GLUT, so you have to do everything with lines, points or triangles. There are some good gaming libraries available like CocoaGL, but for me it's been easier to just write it using OpenGL directly.

I'm doing the music in Garageband, which ships with MacOS. It's pretty good and has a huge variety of samples and loops. Found something interesting though when I dragged one of my ancient MIDI compositions into it. Garageband understands MIDI and lets you redefine the voices for each track.

I'm including some of my favorite oldskool effects:
- parallax stars
- sphere
- free-direction dot tube
- dot tunnel
- texture-mapped tunnel
- plasma mapped onto a pyramid
- blobs mapped onto a cube
- dot grid
- terrain
- copper bars

The dot tunnel has actually been the biggest b*tch to figure out. I'm not including a lens effect or 3D starfield because those have been really overdone. I'd post this on the Obj-C sub-board but there isn't one! lol


Pages: [1]