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

0 Members and 1 Guest are viewing this topic.

Online boogop

  • C= 64
  • **
  • Posts: 57
  • Karma: 22
    • View Profile
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
.286

start:
    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
sin1:   
    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:

;------- 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 times
X_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,63


cseg ends

End Start
Challenge Trophies Won:

Online boogop

  • C= 64
  • **
  • Posts: 57
  • Karma: 22
    • View Profile
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 ax
xor ah,ah
stosw
pop ax
Challenge Trophies Won:

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2689
  • Karma: 483
    • View Profile
    • http://www.rbraz.com/
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:

Online boogop

  • C= 64
  • **
  • Posts: 57
  • Karma: 22
    • View Profile
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],ax
cos: add ax,16384
sin: 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,126
db 124,121,117,112,105,98,89,80,70,59,48,36,24,12,0,-12,-24,-36
db -48,-59,-70,-80,-89,-98,-105,-112,-117,-121,-124,-126,-127
db -126,-124,-121,-117,-112,-105,-98,-89,-80,-70,-59,-48,-36
db -24,-12,0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54
db 57,59,62,65,67,70

Challenge Trophies Won: