Author Topic: sine generator in TASM  (Read 219 times)

0 Members and 1 Guest are viewing this topic.

boogop

• C= 64
• Posts: 57
• Karma: 22
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 /tcseg    segmentassume cs:csegorg 0100h.286start:    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,sisin1:       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 BXmain:;------- 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               Y_LOOP:    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 timesX_LOOP:    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,63cseg endsEnd Start`
Challenge Trophies Won:

boogop

• C= 64
• Posts: 57
• Karma: 22
Re: sine generator in TASM
« Reply #1 on: August 14, 2018 »
nvm the color banding. That's caused by the counter value in ah. duh

Code: [Select]
`push axxor ah,ahstoswpop ax`
Challenge Trophies Won:

Rbz

• Founder Member
• Posts: 2689
• Karma: 483
Re: sine generator in TASM
« Reply #2 on: August 19, 2018 »
And here is the Freebasic port for the sine generator part, for anyone who wants to investigate how it works.

Keep in mind that this generator was done for old computers without FPU (old PC 286 computers I believe), but it's an interesting piece of code that shows how those old coders did their stuff, might be useful for someone making demos for other kinds of old school  computers ofcourse.

Code: [Select]
`' CALCULATE SINE/COS - VALUES (Wally/Rage)    dim shared bx(16384) as short    dim as short cx = &h783F    dim as byte ch = 0    dim as short si = 0    dim as short ax = 0    dim as short dx = 0    dim as short b = 0    width 80, 25    cls    dim as integer i = 0    for i = 0 to 16383         ax = -39  '65497      dx = (cx * ax) shr 16      si += dx      cx += si      ch = (cx shr 8 ) and &hFF      bx( i ) = ch      b = bx( i )      bx( i ) = b shr 1      print bx( i ); "  ";         next      print   print   print "press any key to exit..."   sleep   dim as string clearkey = inkey   `
Challenge Trophies Won:

boogop

• C= 64
• Posts: 57
• Karma: 22
Re: sine generator in TASM
« Reply #3 on: August 21, 2018 »
Cool stuff, Rbz!

I probably have all the effect source from Hornet Archive and I've never seen a sine generator like that one. Mostly people seemed to be generating them externally and using a list of constants. There are a few that use fi[blah] commands to produce one.

Starport II (1993) had an interesting one but didn't create a table, it calculated it on the fly. SHRD was a 386 instruction, not sure it was available on the 286?

Code: [Select]
`;北北北北北北北北 sin/cos 北北北北北北北北;entry: ax=angle (0..65535); exit: ax=muller (-127..127)addwcos:add ax,ds:[bx] ;optimized entry for wavesets mov ds:[bx],axcos: add ax,16384sin: mov bx,ax mov cx,bx and cx,1023 neg cx add cx,1023 shr bx,10 mov ah,ds:sintable[bx] xor al,al imul cx push ax push dx mov ah,ds:sintable[bx+1] xor al,al neg cx add cx,1023 imul cx pop bx pop cx add ax,cx adc dx,bx shrd ax,dx,11 ret`
but SPII also included a sine table, so further investigation is needed

Code: [Select]
`sintable LABEL BYTE ;sine table (circle is 64 units)db 0,12,24,36,48,59,70,80,89,98,105,112,117,121,124,126,127,126db 124,121,117,112,105,98,89,80,70,59,48,36,24,12,0,-12,-24,-36db -48,-59,-70,-80,-89,-98,-105,-112,-117,-121,-124,-126,-127db -126,-124,-121,-117,-112,-105,-98,-89,-80,-70,-59,-48,-36db -24,-12,0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54db 57,59,62,65,67,70`
Challenge Trophies Won: