home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / misc_programming / tplas.asm < prev    next >
Assembly Source File  |  1994-03-20  |  29KB  |  995 lines

  1. ;************************************************************************
  2. ;*                                                                      *
  3. ;*    TPLAS.ASM - Generate a Plasma fractal of 320x200 dimensions       *
  4. ;*       and display on screen.                                         *
  5. ;*                                                                      *
  6. ;*    This is a working prototype of what will become TomsPlas.  At     *
  7. ;*       that point, the fractal will be twice the size of the screen   *
  8. ;*       (640x480), allowing greater movement in the window, and the    *
  9. ;*       window will be expanded to much more of the screen (perhaps    *
  10. ;*       all?).  Controls will be added to vary the speed (1-9 the      *
  11. ;*       number of frames to skip to speed it up, +/- a delay factor.)  *
  12. ;*       The code itself will be optimized to eliminate repetitive      *
  13. ;*       code, such as a push right before a pop, from the macros.      *
  14. ;*       Also, the movement and palette generation routines should      *
  15. ;*       be moved into the function itself rather than in the data      *
  16. ;*       file.  This would shrink the data file to exactly 65,536       *
  17. ;*       bytes, all of which would be numbers for the random series.    *
  18. ;*                                                                      *
  19. ;*          All code and original algorithms expressed herein,          *
  20. ;*                Copyright (C) 1994 by Tom Dibble                      *
  21. ;************************************************************************
  22.  
  23.  
  24. .MODEL TINY    ; always must be TINY model for .COM ...
  25.  
  26. LOCALS
  27.  
  28.     ;<<Macros>>
  29.  
  30. Screen_MaxX    equ   320
  31. Screen_MaxY    equ   240
  32.  
  33.  
  34. ; PrintNum(n)
  35. ;        Print a decimal number to the screen using DBuf and INT 21h:09h
  36. ;        Prints number up to 1000
  37. PrintNum    MACRO    n
  38.     LOCAL @@PosNum
  39.             push     ax
  40.             push    bx
  41.             push    cx
  42.             push    dx
  43.             push    di
  44.  
  45.             xor    bx,bx
  46.             mov    di,offset DBuf
  47.  
  48.             mov    ax,n
  49.             cmp    ax,0
  50.             jg        @@PosNum
  51.             neg    ax
  52.             mov    [di+0], BYTE PTR '-'
  53.             inc    bx
  54.  
  55.         @@PosNum:
  56.             xor    dx,dx
  57.             mov    cx,1000
  58.             div    cx
  59.             add    ax,48                ; convert whole # to ASCII
  60.             mov    [di+bx],al
  61.             inc    bx
  62.             mov    ax,dx                ; put remainder in ax
  63.  
  64.             xor    dx,dx
  65.             mov    cx,100
  66.             div    cx
  67.             add    ax,48                ; convert whole # to ASCII
  68.             mov    [di+bx],al
  69.             inc    bx
  70.             mov    ax,dx                ; put remainder in ax
  71.  
  72.             xor    dx,dx
  73.             mov    cx,10
  74.             div    cx
  75.             add    ax,48                ; convert whole # to ASCII
  76.             mov    [di+bx],al
  77.             inc    bx
  78.             mov    ax,dx                ; put remainder in ax
  79.             add    ax,48                ; convert whole # to ASCII
  80.             mov    [di+bx],al
  81.             inc    bx
  82.             mov    ax,dx                ; put remainder in ax
  83.             inc    bx
  84.             mov    [di+bx], BYTE PTR 10        ; CR
  85.             inc    bx
  86.             mov    [di+bx], BYTE PTR 13        ; LF
  87.             inc    bx
  88.             mov    [di+bx], BYTE PTR '$'        ; terminate string
  89.  
  90.             mov   ah,09h
  91.             mov   dx,offset DBuf
  92.             int   21h
  93.             pop    di
  94.             pop    dx
  95.             pop    bx
  96.             pop    cx
  97.             pop    ax
  98.             endm
  99.  
  100.  
  101. ;  GetPoint(x,y)
  102. ;     Get the point in DS:[plasma] and place it in AL
  103. ;        x and y can not be any of the following:  AX, BX, CX
  104. GetPoint MACRO    x,y
  105.             push  bx       ; So we have some regs to play with
  106.             push  cx       ;
  107.             push  ds
  108.  
  109.          mov   bx, y
  110.          mov   cx, bx      ; multiply by (320) [256+64 == <<8 + <<6]
  111.             xchg  bh, bl      ;
  112.          shl   cx, 6       ;
  113.          add   bx, cx      ;
  114.          add   bx, x
  115.          mov   ds, [Plasma]   ; DS -->  (0,0) in Plasma mem block
  116.          mov   al, [bx]    ; Get the damned byte
  117.  
  118.             pop   ds
  119.          pop   cx
  120.          pop   bx
  121.             endm
  122.  
  123.  
  124. ;  SetPoint(x,y)
  125. ;     Set the point in DS:[plasma] to value in AL
  126. SetPoint MACRO    x,y
  127.          push  bx       ; So we have some regs to play with
  128.          push  cx       ;
  129.          push  ds
  130.  
  131.             mov   bx, y
  132.          mov   cx, bx      ; multiply by (320) [256+64 == <<8 + <<6]
  133.          xchg  bh, bl      ;  (mov low into high, same as shl bx, 8)
  134.             shl   cx, 6       ;
  135.             add   bx, cx      ;
  136.          add   bx, x
  137.             mov   ds, [Plasma]   ; DS -->  (0,0) in Plasma mem block
  138.          mov   [bx], al    ; Set the damned byte
  139.          pop   ds          ; DS -->  Data
  140.          push  ds
  141.          mov   ds, [Video] ; DS -->  Video mem block
  142.          mov   [bx], al    ; Put this bitch on screen!
  143.  
  144.             pop   ds
  145.             pop   cx
  146.             pop   bx
  147.             endm
  148.  
  149.  
  150. ;  SubDivide x1, y1, x2, y2
  151. ;  Subdivide a Plasma rectangle defined by given coordinates and recurse.
  152. SubDivide   MACRO    x1,y1,x2,y2
  153.             mov   ax,y2
  154.             push  ax
  155.             mov   ax,x2
  156.             push  ax
  157.             mov   ax,y1
  158.             push  ax
  159.             mov   ax,x1
  160.             push  ax
  161.             call SubDiv
  162.             endm
  163.  
  164. ;  Adjust x1, y1, x2, y2, xm, ym
  165. ;  Adjust point (x,ym) to average of (x,y1) and (x,y2) plus a random val.
  166. ;
  167. Adjust   MACRO x1, y1, x2, y2, xm, ym
  168.             mov   ax, ym
  169.             push  ax
  170.             mov   ax, xm
  171.             push  ax
  172.             mov   ax, y2
  173.             push  ax
  174.             mov   ax, x2
  175.             push  ax
  176.             mov   ax, y1
  177.             push  ax
  178.             mov   ax, x1
  179.             push  ax
  180.  
  181.             call  Adj
  182.  
  183.             endm
  184.  
  185.  
  186. ;  Rand8
  187. ;  Get the next 8-bit random value from Rand_Series.  Put it into AL.
  188. Rand8    MACRO
  189.          push  ds
  190.             mov   bx, Rand_Ptr
  191.          mov   ds, [Rand_Series]
  192.             mov   al, [bx]
  193.          pop   ds
  194.          inc   Rand_Ptr
  195.          endm
  196.  
  197. ;  Rand16
  198. ;  Get the next 16-bit random value from Rand_Series.  Put it into AX.
  199. Rand16   MACRO
  200.             push  ds
  201.          mov   bx, Rand_Ptr
  202.          mov   ds, [Rand_Series]
  203.             mov   ax, [bx]
  204.          pop   ds
  205.          inc   Rand_Ptr
  206.             inc   Rand_Ptr
  207.          endm
  208.  
  209.  
  210. ;  GetTRand
  211. ;  Get System-Time 'seconds' and '1/100 seconds' into DH and DL, respectively
  212. ;  'hour' and 'minute' into CH and CL, respectively
  213. GetTRand MACRO
  214.          push  ax
  215.          mov   ah, 2Ch     ;  DOS Interrupt Fn:  'Get System Time'
  216.             int   21h
  217.          pop   ax
  218.          endm
  219.  
  220.  
  221. ; malloc:  allocate memory to program in 16-byte chunks
  222. ;  'amount' is the number of 'paragraphs' to allocate
  223. ;  (a paragraph being 16 bytes).
  224. ;  CF set on error, AX is 09h, BX is size of largest block
  225. ;  The segment address is left in AX if successful
  226. malloc   MACRO    amount
  227.          mov     ah,48h
  228.          mov     bx,amount
  229.             int     21h
  230.          endm
  231.  
  232. ; mfree:  frees malloc'd memory.
  233. mfree    MACRO    where
  234.             mov     ah,49h
  235.             mov     es,where
  236.          int     21h
  237.          endm
  238.  
  239.  
  240. ; keyp:  check for key press
  241. ;  CF set if key is present.
  242. keyp     MACRO
  243.          mov     ah,0bh
  244.          int     21h
  245.          or      al,al
  246.          endm
  247.  
  248. ; kwait:  wait for key-press
  249. kwait    MACRO
  250.          push     ax
  251.          mov      ah, 08h
  252.             int      21h
  253.          pop      ax
  254.          endm
  255.  
  256. ; exit:  exit with error code
  257. exit     MACRO    return_code
  258.          mov     al,return_code
  259.          mov     ah,4ch
  260.          int     21h
  261.             endm
  262.  
  263. ;  prints:  print a string to text screen
  264. prints   MACRO    str
  265.             mov     ah,09h
  266.             mov     dx,offset str
  267.             int     21h
  268.             endm
  269.  
  270.  
  271. ; fopen:  open a file for read (0) or write (1) or both (2)
  272. ;  CF set on error, AX holds error code.
  273. ;  file handle left in AX if successful.
  274. fopen   macro   file,attrib
  275.         mov     ah,3dh
  276.           mov     al,attrib
  277.         mov     dx,offset file
  278.           int     21h
  279.         endm
  280.  
  281.  
  282. ; fread:  read information from file opened by fopen.
  283. ;  Data read into (AX:00h).
  284. ;  CF set on error.
  285. ;  AX return (number of bytes read) is nuked.
  286. fread   macro   handle,bytes
  287.           push    ax
  288.         push    ds
  289.         push    ax
  290.           mov     ah,3fh
  291.           mov     bx,[handle]
  292.         mov     cx,bytes
  293.         xor     dx,dx      ;  Segment is (00h)
  294.           pop     ds         ;  this used to be AX!
  295.         int     21h
  296.         pop     ds
  297.         pop     ax
  298.         endm
  299.  
  300.  
  301.  
  302.  
  303. ;**************************** << CODE SEGMENT >> ****************************;
  304.  
  305. .CODE
  306.  
  307. org 100h
  308. start:  jmp begin
  309.  
  310.     ;  Variables
  311.             ;  Strings
  312.         CopyRight   db    "Tom's Plasma (C) 1994 by Tom Dibble",10,13,"$"
  313.         TPVersion    db        "Revision 1.1, March 19, 1994",10,13,"$"
  314.         NoMemory    db    "Out of Base Memory!",10,13,"$"
  315.         NoFile      db    10,13,\
  316.                                 "ERROR:  Couldn't open TomsPlas.DAT!",10,13,\
  317.                                 "   Change to the directory containing",10,13,\
  318.                                 "   TomsPlas.DAT and restart the program!",10,13,"$"
  319.         DebugPoint  db    "Debug Point!",10,13,"$"
  320.         DataFile    db    "TOMSPLASM.DAT",0
  321.         DBuf            db    80 dup (?)
  322.  
  323.             ;  General Variables
  324.         OrigVMode    db        03h    ; Mode the video card was in when we got here!
  325.         recadj      db    11111111B   ; last 8 bits set (255)
  326.         count       dw    0        ; loop counter while swimmin' and cyclin'
  327.         DATHandle   dw    ?        ; Handle to Data File
  328.         Rand_Ptr    dw    ?     ; Pointer to next random value in [Rand_Series]
  329.         WinHide        db        0        ; Is the swim-window hidden?
  330.  
  331.             ;  Segment Addresses
  332.         Plasma      dw    0     ; Segment beginning for Plasma Bitmap
  333.         Video       dw    0     ; Segment beginning for Video Memory
  334.         Color       dw    0     ; Segment for Color-Palette Data
  335.         Movement    dw    0     ; Movement data
  336.         Rand_Series dw    0     ; 64k of random values
  337.  
  338. ASSUME   CS:@code,DS:@code,ES:@code
  339.  
  340. .386           ; select the processor
  341.  
  342. begin:      ; from here on in is executable stuffs ...
  343.  
  344.             mov     sp,offset stacktop       ; set new stack
  345.  
  346.             mov     bx,last_inst-start+100h  ; (size of prog. + 100h header)
  347.             shr     bx,4            ; shrink memory usage to program size
  348.             inc     bx              ; in pages (16 bytes)
  349.             mov     ah,4ah
  350.             int     21h                ; ES segment is resized.  ES is set to @code
  351.  
  352.             prints  CopyRight       ; display header message
  353.             prints  TPVersion       ; display header message, part 2
  354.  
  355.  
  356.         ; InitProgram sets video mode, allocates memory, seeds 'Random'
  357.             CALL  InitProgram
  358.  
  359.         ; GenPlasma does all the work
  360.             mov    [recadj], 11111111B    ; last eight bits default ('Rough')
  361.             CALL        ClearPlasma
  362.     NewPlasma:
  363.             CALL        ShowPlasma
  364.             CALL        ClearPlasma
  365.             CALL      GenPlasma
  366.  
  367.         ; Cycle the colors and swim the image
  368.     ContinueCycle:
  369.             cmp    [WinHide],0
  370.             jne    NoWindow
  371.             CALL  CycleSwim
  372.             jmp    KeyDecipher
  373.         NoWindow:
  374.             CALL    ShowPlasma
  375.             CALL    CycleNoSwim
  376.  
  377.     KeyDecipher:
  378.         ; Wait for a key to be pressed (if none has already)
  379.             mov   ah, 08h
  380.             int   21h
  381.         ; Process that key!
  382.             cmp    al, 13        ; Return --> New Plasma!
  383.             je        NewPlasma
  384.             cmp    al, ' '        ; Space --> Hide Window!
  385.             je        ToggleWindow
  386.             cmp    al, '1'        ; New Plasma, recadj of 255
  387.             je        RoughPlasma
  388.             cmp    al, '2'        ; New Plasma, recadj of 127
  389.             je        MedPlasma
  390.             cmp    al, '3'        ; New Plasma, recadj of 63
  391.             je        SmoothPlasma
  392.             cmp    al,27            ; <Esc> --> Get outta here!
  393.             je    LeaveProg
  394.  
  395.             jmp    ContinueCycle
  396.  
  397.     ToggleWindow:
  398.             not    [WinHide]
  399.             jmp    ContinueCycle    ; any key puts the window back!
  400.  
  401.     RoughPlasma:
  402.             mov    recadj, 11111111B
  403.             jmp    NewPlasma
  404.  
  405.     MedPlasma:
  406.             mov    recadj, 01111111B
  407.             jmp    NewPlasma
  408.  
  409.     SmoothPlasma:
  410.             mov    recadj, 00111111B
  411.             jmp    NewPlasma
  412.  
  413.     LeaveProg:
  414.  
  415.         ; Clean out memory allocated, return to right video mode
  416.             CALL  CleanUp
  417.  
  418.         ;Now exit to DOS
  419.             mov   ah,4Ch
  420.             int   21h
  421.             ret
  422.  
  423. ;************************************************************************
  424. ;*                                                                      *
  425. ;*    InitProgram                                                       *
  426. ;*                                                                      *
  427. ;*             Allocate memory to Plasma, clear it out                  *
  428. ;*             Open Data File                                           *
  429. ;*             Allocate memory to Movement, read                        *
  430. ;*             Allocate memory to Color, read                           *
  431. ;*             Allocate memory to Rand_Series, read                     *
  432. ;*             Get Rand_Ptr from system time function                   *
  433. ;*             Set Video Mode to 13                                     *
  434. ;*                                                                      *
  435. ;************************************************************************
  436.  
  437. InitProgram PROC NEAR
  438.             malloc   4000+1         ; allocate memory for plasma buffer + 1 para.
  439.             jc       nomem          ; break if not enough memory
  440.             mov      [Plasma],ax    ; store address
  441.  
  442.             malloc   2500+1            ; allocate memory for movement buffer + 1
  443.             jc       nomem             ; as above...
  444.             mov      [Movement],ax
  445.             malloc   192+1            ; allocate memory for color buffer + 1
  446.             jc       nomem
  447.             mov      [Color],ax
  448.             malloc   1000h             ; allocate memory for random buffer + 1
  449.             jc       nomem
  450.             mov      [Rand_Series],ax
  451.             jmp      allocok           ; skip the following
  452.  
  453. allocok: fopen    DataFile,0        ; open TomsPlas.DAT read only
  454.             jnc      loadok            ;
  455.             prints   NoFile            ; You schmuck!  It's not here!
  456.             mfree    [Plasma]
  457.             mfree    [Movement]
  458.             mfree    [Color]
  459.             mfree    [Rand_Series]
  460.             exit     254               ; so quit
  461. loadok:  mov      [DATHandle],ax    ; store handle
  462.  
  463.             mov      ax,[Movement]     ; read movement data
  464.             fread    DATHandle,40000
  465.             mov      ax,[Color]        ; color data
  466.             fread    DATHandle,3072
  467.             mov      ax,[Rand_Series]  ; and random series
  468.             fread    DATHandle,0ffffh
  469.  
  470.             GetTRand                   ; get 'time' values into CX and DX
  471.             add      cx, dx            ; accumulate values
  472.             mov      Rand_Ptr, cx      ; put Rand_Ptr as a random place in series
  473.  
  474.             mov        ax,0F00h          ; get the video mode now
  475.             int        10h               ;
  476.             mov        [OrigVMode], al
  477.             mov      ax,0013h          ; set video mode 13
  478.             int      10h
  479.             mov      [Video],0a000h    ; Start segment for Video Mem
  480.  
  481.             mov      si, 0
  482.             mov      cx, 3*255         ; Set Color Palette!
  483.             push     ds                ;
  484.             mov      ds, [Color]
  485.             cld
  486.             mov      dx, 03C8h         ;
  487.             mov      al, 1             ; start with color '1'
  488.             out      dx, al            ;
  489.             inc      dx
  490.             rep      outsb
  491.             pop      ds
  492.  
  493.             ret
  494.  
  495.     nomem:
  496.             prints   NoMemory
  497.          exit     -1
  498.  
  499. InitProgram ENDP
  500.  
  501. ClearPlasma    PROC    NEAR
  502.             push        eax                    ;
  503.             push        cx                ;
  504.             push        es                ;    Clear out the memory devoted to
  505.             push        di                ;        the Plasma buffer so that
  506.                                                 ;        we can create a new Plasma!
  507.             mov        ax, 0             ;
  508.             shl        eax, 16           ;
  509.             mov        ax,0              ;
  510.             mov        cx, [Plasma]      ;
  511.             mov        es, cx            ;
  512.             mov        di, 0             ;
  513.             mov        cx, 64000/4       ;
  514.             rep        stosd                    ; put eax into es:di
  515.                                                 ;
  516.             pop        di                ;
  517.             pop        es                ;
  518.             pop        cx                ;
  519.             pop        eax               ;
  520.             ret
  521. ClearPlasma    ENDP
  522.  
  523.  
  524. ShowPlasma    PROC    NEAR
  525.             push        ax
  526.             push        cx
  527.             push        es
  528.             push        ds
  529.             push        si
  530.             push        di
  531.  
  532.             mov        si,0
  533.             mov        di,0
  534.             mov        ax,[Video]
  535.             mov        es,ax
  536.             mov        ds,[Plasma]
  537.             mov        cx, 320*200/4
  538.             rep        movsd
  539.  
  540.             pop        di
  541.             pop        si
  542.             pop        ds
  543.             pop        es
  544.             pop        cx
  545.             pop        ax
  546.             ret
  547. ShowPlasma    ENDP
  548.  
  549.  
  550. CleanUp  PROC  NEAR
  551.             push     ax
  552.  
  553.             mfree    [Plasma]
  554.             mfree    [Movement]
  555.             mfree    [Color]
  556.             mfree    [Rand_Series]
  557.  
  558.             mov        ah,00h
  559.             mov      al,[OrigVMode]              ; set video mode back to what it was
  560.             int      10h
  561.  
  562.             prints   CopyRight                ; Tell 'em this again!
  563.  
  564.             pop      ax
  565.             ret
  566.  
  567. CleanUp  ENDP
  568.  
  569.  
  570. GenPlasma   PROC NEAR
  571.  
  572.             Rand8
  573.             SetPoint 0,0
  574.             Rand8
  575.             SetPoint 319, 199
  576.             Rand8
  577.             SetPoint 0, 199
  578.             Rand8
  579.             SetPoint 319, 0
  580.  
  581.             SubDivide 0,0,319,199
  582.             ret
  583. GenPlasma   ENDP
  584.  
  585. ;************************************************************************
  586. ;*                                                                      *
  587. ;*    SubDiv      x1, y1, x2, y2                                        *
  588. ;*                                                                      *
  589. ;*             Corners have already been set to proper values.          *
  590. ;*             Check each side if it has been set yet, and if not,      *
  591. ;*                   set it to the average of associated corners plus   *
  592. ;*                   a random value based on Code:recadj.               *
  593. ;*             Set middle to average of four sides.                     *
  594. ;*             Recurse for each of four sectors in lt,rt,rb,lb order.   *
  595. ;*             Free up our memory and get the hell outta here!          *
  596. ;*                                                                      *
  597. ;*       18 bytes on stack per recursion, times 7 recursions.  Stack     *
  598. ;*                        size must be large enough to handle this load!        *
  599. ;*                                                                      *
  600. ;************************************************************************
  601.  
  602.  
  603. SubDiv   PROC
  604.     ARG x1:word, y1:word, x2:word, y2:word
  605.     LOCAL    x:word, y:word=LocalStk
  606.             push     bp
  607.             mov      bp,sp
  608.             sub    sp,LocalStk        ; Set-up local stack
  609.             push  cx
  610.             push  dx
  611.  
  612.                         ;  First, check for recursion halts.
  613.                         ;     < if(xhalt && yhalt) return >
  614.  
  615.             mov   ax,[x1]
  616.             add   ax,[x2]
  617.             shr   ax,1        ;  divide by two for average of x1,x2
  618.             mov    [x],ax      ; now 'x' is on stack!
  619.  
  620.                         ;  Find the 'y' value now!
  621.             mov   cx,[y1]
  622.             add   cx,[y2]
  623.             shr   cx,1        ;  divide by two for average of y1,y2
  624.             mov    [y],cx      ; now 'y' is on stack!
  625.  
  626.             cmp   ax,[x1]
  627.             jg xchecks        ;  if x1 != x, keep on going
  628.                         ;  x does not check.
  629.                         ;  Check for 'y' value recursion halt.
  630.             cmp   cx,[y1]
  631.             jg ychecks        ;  y checks.  Jump out.
  632.  
  633.                 pop   dx          ;  Cleanup:  return DX, to it's place
  634.                 pop   cx          ;      and same with CX, SP and BP ...
  635.                 mov   sp,bp       ;
  636.                 pop   bp          ;
  637.                 ret   8
  638.  
  639.         xchecks:
  640.         ychecks:
  641.  
  642.                         ;  Okay!  We have checked for recursion halt
  643.                         ;  and have calculated x and y.
  644.                         ;  Next, check each of the four sides for empty
  645.                         ;  and call 'Adjust' if so.  Meanwhile, keep
  646.                         ;  a running total of all the four sides so we
  647.                         ;  can do a quick average of them in the next
  648.                         ;  step.
  649.  
  650.             GetPoint [x],[y1]
  651.             cmp   al,0
  652.             jne topgood
  653.             Adjust [x1],[y1],[x2],[y1],[x],[y1]
  654.         topgood:
  655.             mov   ah,0
  656.             push  ax
  657.  
  658.             GetPoint [x2],[y]
  659.             cmp   al,0
  660.             jne rightgood
  661.             Adjust [x2],[y1],[x2],[y2],[x2],[y]
  662.         rightgood:
  663.             mov   ah,0
  664.             pop   bx
  665.             add   ax,bx
  666.             push  ax
  667.  
  668.             GetPoint [x],[y2]
  669.             cmp   al,0
  670.             jne bottomgood
  671.             Adjust [x1],[y2],[x2],[y2],[x],[y2]
  672.         bottomgood:
  673.             mov   ah,0
  674.             pop   bx
  675.             add   ax,bx
  676.             push  ax
  677.  
  678.             GetPoint [x1],[y]
  679.             cmp   al,0
  680.             jne leftgood
  681.             Adjust [x1],[y1],[x1],[y2],[x1],[y]
  682.         leftgood:
  683.             mov   ah,0
  684.             pop   cx
  685.             add   cx,ax
  686.             ;  No push of AX here!
  687.  
  688.                         ;  Okay.  All four side pixels have been computed
  689.                         ;  and plotted on the screen and in memory.  AX
  690.                         ;  holds the sum of all four pixels.  Divide by four
  691.                         ;  and set x,y to the resulting value.
  692.             shr   cx,2
  693.  
  694.             mov    al,cl
  695.             SetPoint    [x],[y]
  696.  
  697.                         ;  Finally.  All the real work is done.  Now, decrease
  698.                         ;  the recurse-level adjustment and recurse down
  699.                         ;  to the next level for each of the four quads
  700.  
  701.             mov   al, recadj
  702.             push  ax
  703.             shr   al, 1
  704.             mov   recadj, al
  705.  
  706.             SubDivide [x1], [y1], [x],  [y]
  707.             SubDivide [x],  [y1], [x2], [y]
  708.             SubDivide [x],  [y],  [x2], [y2]
  709.             SubDivide [x1], [y],  [x],  [y2]
  710.  
  711.             pop   ax
  712.             mov   recadj, al  ; return it to what it was before we got here.
  713.  
  714.             pop   dx          ;  Cleanup:  return DX, to it's place
  715.             pop   cx          ;      and same with CX, SP and BP ...
  716.             mov   sp,bp       ;
  717.             pop   bp          ;
  718.             ret   8
  719. SubDiv   ENDP
  720.  
  721.  
  722. ;************************************************************************
  723. ;*                                                                      *
  724. ;*    Adj         x1, y1, x2, y2, x, y                                  *
  725. ;*                                                                      *
  726. ;*          Sets the point at (x,y) to be the average of points (x1,y1) *
  727. ;*                and (x2,y2), plus a random factor based on recval.    *
  728. ;*                                                                      *
  729. ;*          Get points (1) and (2) into AH, AL.                         *
  730. ;*          Average the values into AL.                                 *
  731. ;*          CBW AL, move into BX.                                       *
  732. ;*          Get a random 16-bit number into AX                          *
  733. ;*          Multiply AX and recval.                                     *
  734. ;*          Shift DX to the right 2 bits (same as shifting 32-bit 18)   *
  735. ;*          Move DX into AX                                             *
  736. ;*          Add BX into AX                                              *
  737. ;*          if AX < 1, AX = 1.                                          *
  738. ;*          if AH != 0, AL = 255                                        *
  739. ;*          Set point (x,y) to value in AL.                             *
  740. ;*                                                                      *
  741. ;************************************************************************
  742.  
  743. Adj      PROC  NEAR
  744.     ARG x1:word, y1:word, x2:word, y2:word, xm:word, ym:word
  745.             push  bp
  746.             mov   bp, sp
  747.             push  bx
  748.             push  cx
  749.             push  dx
  750.  
  751.             mov    ah,0
  752.  
  753.             GetPoint [x1], [y1]     ;  Sets 'AL'
  754.             mov   cl, al            ;  Put it into 'CL'
  755.  
  756.             GetPoint [x2], [y2]     ;  Sets 'AL'
  757.             add   cx, ax            ;  Add this guy to the first.
  758.  
  759.             shr   cx, 1             ;  Divide by two (to make average)
  760.  
  761.             Rand8                ; random byte in al
  762.             mov   bl, recadj
  763.             and   al, bl            ; restrict the rand #
  764.             shr   bl, 1          ; div by 2
  765.             sub   al, bl         ; subtract 1/2 (so low # neg, high pos)
  766.             cbw
  767.             add    ax, cx            ; cx is pos.  ax may be + or -
  768.                                         ; If the sum exceeded 255, ah will
  769.                                         ;         have a positive number in it.
  770.                                         ; If the sum was less than zero, ax
  771.                                         ;         will be negative.
  772.  
  773.             cmp    ax,0
  774.             jg        AdjLowCheck
  775.             mov    ax,1                ; ax < 0, force it to lower bound!
  776.             jmp    AdjSetPoint
  777.  
  778.         AdjLowCheck:
  779.             cmp    ax,256
  780.             jl        AdjSetPoint
  781.             mov    ax,255            ; ax > 255, force it to upper bound!
  782.  
  783.         AdjSetPoint:
  784.             SetPoint [xm], [ym];  Set (x,y) to 'AL'
  785.  
  786.             pop   dx
  787.             pop   cx
  788.             pop   bx
  789.             pop   bp
  790.  
  791.             ret   12                ; 6*2 parameters
  792.  
  793. Adj      ENDP
  794.  
  795.  
  796.  
  797.  
  798. ;************************************************************************
  799. ;*                                                                      *
  800. ;*    CycleSwim                                                         *
  801. ;*                                                                      *
  802. ;*          Cycle the color palette and swim a middle window of plasma. *
  803. ;*                                                                      *
  804. ;*          'Swimming' is the process of adding two sections of the     *
  805. ;*                plasma fractal together, then moving the pointers     *
  806. ;*                to each of those sections in a loop so as to create   *
  807. ;*                a composite, changing fractal.                        *
  808. ;*                                                                      *
  809. ;************************************************************************
  810.  
  811.  
  812. CycleSwim    PROC  NEAR
  813.  
  814.             mov      ax, [Video]    ; Put the video segment address in es
  815.             mov      es, ax         ;   for stosd loop below.
  816.  
  817.         mainloop:
  818.                         ; We'll do all this setup stuff *BEFORE* we wait for VRT.
  819.                         ; This sets things up for :setpl: loop below ...
  820.  
  821.                         ; Rotate the palette!
  822.             push     ds
  823.             push     es
  824.             cld
  825.             mov      es, [Color]
  826.             mov      ds, [Color]
  827.             mov      bx, 0
  828.  
  829.             mov      ax, [bx]            ; r,g of color[0]
  830.             mov      dl, [bx+2]        ; b of color[0]
  831.  
  832.             mov      cx, 256*3      ; loop 256*4*3/4 times
  833.             mov      si, 3
  834.             mov      di, 0
  835.             rep      movsd          ; move bytes from ds:si to es:di
  836.  
  837.             mov      bx, 256*4*3-3     ; copy saved rgb to end of current pal.
  838.             mov      [bx],ax
  839.             mov      [bx+2],dl
  840.  
  841.             pop      es
  842.             pop      ds
  843.  
  844.             mov      si,0
  845.             mov      cx,255*3       ; loop 255 times (for 255 DAC's)
  846.             push     ds
  847.             mov      ds,[Color]     ; address segment
  848.             cld                     ; ensure SI is incremented
  849.  
  850.         VSync:
  851.             mov      dx,03dah       ; VGA input status register 1
  852.             in       al,dx          ; load value
  853.             test     al,08          ; vertical retrace??
  854.             je       VSync                ; if not, try again...
  855.  
  856.                         ;  Load all the info from the colour segment
  857.                         ;  into the DAC's ...
  858.  
  859.                         ; NOW do the final prep for color loading
  860.             mov      dx,3c8h        ; DAC index register
  861.             mov      al,1           ; start with color 1
  862.             out      dx,al          ; and load
  863.             inc      dx             ; DAC read/write register
  864.             rep         outsb
  865.  
  866.             pop      ds             ; and restore DS back to code segment
  867.  
  868.             mov      di,[count]     ; source = count * 4
  869.             shl      di,2           ;
  870.             push     ds
  871.             mov      ds,[Movement]  ; get segment address of movement data
  872.             mov      si,[di]        ; load point 1, start of reading x-data
  873.             mov      bx,[di+2]      ; load point 2, start of added x-data
  874.             pop      ds             ; and restore DS back to code segment
  875.             push     ds
  876.             mov      ds,[Plasma]    ; get segment of start of plasma
  877.             mov      di,320*50+90   ; put window in the center of the screen.
  878.  
  879.             mov      ch,100         ; y loop = 100 pixels
  880.     pl1:  mov      cl,40          ; x loop = 40 * 4 = 160 pixels
  881.     pl2:  lodsd                   ; get 4 source pixels from ds:si, inc si
  882.             add      eax,[si+bx]    ; add 4 source pixels from ds:(si+bx)
  883.             stosd                   ; and store them on screen to es:di, inc di
  884.             dec      cl             ; dec  x-counter
  885.             jnz      pl2            ; and loop..
  886.  
  887.             sub      si,160         ; reset source to beg. of :pl1:
  888.             mov      dx,ds          ; add 20 to DS :
  889.             add      dx,20          ; move 20*16 = 320 bytes down in source mem
  890.             mov      ds,dx
  891.             add      di,160         ; add 160 to vid ptr (to beg of next line)
  892.             dec      ch             ; dec y-counter
  893.             jnz      pl1            ; and loop..
  894.  
  895.             pop      ds                ; and restore DS back to code segment
  896.             inc      word ptr [count]  ; increase counter
  897.             cmp      word ptr [count],10000  ; reset it at end of cycle
  898.             jne      noreset
  899.             mov      word ptr [count],0
  900.  
  901.         noreset:
  902.             keyp                       ; keypressed??
  903.             jnz      closedown         ; if yes then quit..
  904.             jmp      mainloop
  905.  
  906.         closedown:
  907.             ret
  908.  
  909. CycleSwim    ENDP
  910.  
  911.  
  912. ;************************************************************************
  913. ;*                                                                      *
  914. ;*    CycleNoSwim                                                       *
  915. ;*                                                                      *
  916. ;*          Just cycle the color palette.                                         *
  917. ;*                                                                      *
  918. ;************************************************************************
  919.  
  920.  
  921. CycleNoSwim    PROC  NEAR
  922.  
  923.             mov      ax, [Video]    ; Put the video segment address in es
  924.             mov      es, ax         ;   for stosd loop below.
  925.  
  926.         CNSmainloop:
  927.                         ; We'll do all this setup stuff *BEFORE* we wait for VRT.
  928.                         ; This sets things up for :setpl: loop below ...
  929.  
  930.                         ; Rotate the palette!
  931.             push     ds
  932.             push     es
  933.             cld
  934.             mov      es, [Color]
  935.             mov      ds, [Color]
  936.             mov      bx, 0
  937.  
  938.             mov      ax, [bx]            ; r,g of color[0]
  939.             mov      dl, [bx+2]        ; b of color[0]
  940.  
  941.             mov      cx, 256*3      ; loop 256*4*3/4 times
  942.             mov      si, 3
  943.             mov      di, 0
  944.             rep      movsd          ; move bytes from ds:si to es:di
  945.  
  946.             mov      bx, 256*4*3-3     ; copy saved rgb to end of current pal.
  947.             mov      [bx],ax
  948.             mov      [bx+2],dl
  949.  
  950.             pop      es
  951.             pop      ds
  952.             push     ds
  953.  
  954.             mov      si,0
  955.             mov      cx,255*3       ; loop 255 times (for 255 DAC's)
  956.             mov      ds,[Color]     ; address segment
  957.             cld                     ; ensure SI is incremented
  958.  
  959.         CNSVSync:
  960.             mov      dx,03dah       ; VGA input status register 1
  961.             in       al,dx          ; load value
  962.             test     al,08          ; vertical retrace??
  963.             je       CNSVSync          ; if not, try again...
  964.  
  965.                         ;  Load all the info from the colour segment
  966.                         ;  into the DAC's ...
  967.  
  968.                         ; NOW do the final prep for color loading
  969.             mov      dx,3c8h        ; DAC index register
  970.             mov      al,1           ; start with color 1
  971.             out      dx,al          ; and load
  972.             inc      dx             ; DAC read/write register
  973.             rep         outsb
  974.  
  975.             pop      ds             ; and restore DS back to code segment
  976.  
  977.             keyp                      ; keypressed??
  978.             jnz      leaveCNS       ; if yes then quit..
  979.             jmp      CNSmainloop
  980.  
  981.         leaveCNS:
  982.             ret
  983.  
  984. CycleNoSwim    ENDP
  985.  
  986.  
  987. mystack    db      8192 dup (?)  ; my stack:  room for lots o' recursion
  988. stacktop   equ     $             ; top of my stack.
  989.  
  990. last_inst:                       ; the end of the program!
  991.  
  992. END     start
  993.  
  994.  
  995.