Turbo Assembler	 Version 4.1	    03/29/24 08:17:56	    Page 1
vlf.ASM



      1					 ;vlf.asm
      2					 ;Very,	Little Fugue
      3					 ;Fugue	in G Minor by Johann Sebastian Bach
      4					 ;The recursive	spiral was inspired by this:
      5					 ;https://pythonturtle.academy/spiral-of-spirals-fractals-2-with-python-turtle-source-code/
      6					 ;Assemble with: tasm; tlink /t
      7					 ;This runs under DOSBox; not under pure DOS.
      8
      9	    0000				 .model	 tiny
     10	    0000				 .code
     11						 .486
     12						 org	 100h
     13					 ;ax=0,	bx=0, cx=00FFh,	dx=cs, si=0100h, di=-2,	bp=09xx, sp=-2
     14					 ;high 16 bits of esp =	0000h
     15
     16		  =0000			 debug	 equ	 0		 ;set to 0 for compo version
     17		  =0400			 ScrW	 equ	 1024		 ;screen dimensions (pixels)
     18		  =0300			 ScrH	 equ	 768
     19
     20	    0100			 start:
     21					 ;	 push	 ax		 ;access absolute memory addresses
     22					 ;	 pop	 fs		 ;unnecessary with DOSBox
     23					 ;	 fninit			 ;unnecessary with DOSBox
     24
     25	    0100  B8 4F02			 mov	 ax, 4F02h	 ;1024x768x8 graphics
     26	    0103  BB 0105			 mov	 bx, 0105h
     27	    0106  CD 10				 int	 10h
     28		  =DGROUP:0107		 ticks	 equ	 $-1		 ;tick counter for note	duration, initially 1 sec
     29
     30					 ;Use our routine for the system timer interrupt (1Ch).
     31					 ;The routine is called	about 18.2 times per second.
     32	    0108  68 01D5r			 push	 offset	score
     33	    010B  07				 pop	 es
     34
     35	    010C  B8 251C			 mov	 ax, 251Ch	 ;point	interrupt vector to our	routine
     36	    010F  BA 01A0r			 mov	 dx, offset inthan ; ds=cs
     37	    0112  CD 21				 int	 21h		 ;(music will start playing)
     38
     39					 ;DrawSpiral(770, 600, 135, -1.6)
     40	    0114  DF 44	2A			 fild	 word ptr [si+d770-start]	 ;FPU: X
     41	    0117  DF 44	2E			 fild	 word ptr [si+d600-start]	 ;FPU: X Y
     42	    011A  DF 44	30			 fild	 word ptr [si+d135-start]	 ;FPU: X Y Len
     43	    011D  D9 44	32			 fld	dword ptr [si+d_1_6-start]	 ;FPU: X Y Len Dir
     44	    0120  E8 001D			 call	 Spiral
     45
     46	    0123  E5 60			 wait10: in	 ax, 60h			 ;wait for Esc key
     47	    0125  FE C8				 dec	 al
     48	    0127  75 FA				 jne	 wait10
     49	    0129  C3			 return: ret
     50
     51	    012A  0302			 d770	 dw	 770		 ;02 03
     52		  =DGROUP:012B		 d3	 equ	 $-1		 ;03 00
     53	    012C  0400			 dScrW	 dw	 ScrW		 ;00 04
     54	    012E  0258			 d600	 dw	 600
     55	    0130  0087			 d135	 dw	 135
     56	    0132  BFCCCCCD		 d_1_6	 dd	 -1.6
     57	    0136  3E99999A		 d0_3	 dd	 0.3
     58	    013A  0004			 d4	 dw	 4
     59	    013C  3F70A3D7		 d0_94	 dd	 0.94
     60
     61					 ;-------------------------------------------------------------------------------
     62					 ;proc DrawSpiral(X, Y,	Len, Dir)
     63
     64	    0140			 Spiral:
     65					 ;while	Len > 0.3 do
     66	    0140  D9 44	36		 spi00:	 fld	 dword ptr [si+d0_3-start]	 ;FPU: X Y Len Dir 0.3
     67	    0143  D8 DA				 fcomp	 st(2)				 ;FPU: X Y Len Dir
     68	    0145  DF E0				 fnstsw	 ax
     69	    0147  9E				 sahf
     70	    0148  73 DF				 jae	 short return			 ;exit if Len <= 0.3
     71
     72					 ;if Len > 1 then
     73	    014A  D9 E8				 fld1					 ;FPU: X Y Len Dir 1
     74	    014C  D8 DA				 fcomp	 st(2)				 ;FPU: X Y Len Dir
     75	    014E  DF E0				 fnstsw	 ax
     76	    0150  9E				 sahf
     77	    0151  73 1D				 jae	 short spi20			 ;skip if Len <= 1
     78
     79					 ;DrawSpiral(X,	Y, Len/4, Dir-3)
     80	    0153  2B E6				 sub	 sp, si				 ;at least 108 bytes of	stack
     81	    0155  67| DD 34 24			 fnsave	 [esp]				 ;FPU: also does finit
     82	    0159  67| DD 24 24			 fnrstor [esp]				 ;FPU: X Y Len Dir
     83
     84	    015D  DF 44	3A			 fild	 word ptr [si+d4-start]		 ;FPU: X Y Len Dir 4
     85	    0160  DE FA				 fdivp	 st(2)
     86	    0162  DE 64	2B			 fisub	 word ptr [si+d3-start]		 ;FPU: X Y Len/4 Dir-3
     87
     88	    0165  E8 FFD8			 call	 spiral				 ;recurse
     89
     90	    0168  67| DD 24 24			 fnrstor [esp]				 ;FPU: X Y Len Dir
     91	    016C  03 E6				 add	 sp, si				 ;release reserved stack space
     92
     93	    016E  E2 FE				 loop	 $				 ;delay	for effect
     94	    0170			 spi20:
     95					 ;X:= X	+ Len*Cos(Dir)
     96	    0170  D9 C0				 fld	 st				 ;FPU: X Y Len Dir Dir
     97	    0172  D9 FB				 fsincos				 ;FPU: X Y Len Dir sin cos
     98	    0174  D8 CB				 fmul	 st, st(3)			 ;FPU: X Y Len Dir sin Lencos
     99	    0176  DE C5				 faddp	 st(5),	st			 ;FPU: X Y Len Dir sin
    100
    101					 ;Y:= Y	+ Len*Sin(Dir)
    102	    0178  D8 CA				 fmul	 st, st(2)
    103	    017A  DE C3				 faddp	 st(3),	st			 ;FPU: X Y Len Dir
    104
    105					 ;Point(fix(X),	fix(Y),	$0F)
    106	    017C  D9 C2				 fld	 st(2)				 ;FPU: X Y Len Dir Y
    107	    017E  D9 FC				 frndint
    108	    0180  DE 4C	2C			 fimul	 word ptr [si+dScrW-start]	 ;FPU: X Y Len Dir Y*ScrW
    109	    0183  D8 C4				 fadd	 st, st(4)			 ;FPU: X Y Len Dir Y*ScrW+X
    110	    0185  DB 1C				 fistp	 dword ptr [si]			 ;FPU: X Y Len Dir
    111	    0187  66| 8B 1C			 mov	 ebx, dword ptr	[si]
    112	    018A  8B C4				 mov	 ax, sp				 ;color	it beautiful!
    113	    018C  04 10				 add	 al, 16
    114	    018E  64: 67| 88 83	      +		 mov	 byte ptr fs:[ebx+0C0000000h], al
    115		  C0000000
    116
    117					 ;Len:=	Len * 0.94
    118	    0196  D9 44	3C			 fld	 dword ptr [si+d0_94-start]	 ;FPU: X Y Len Dir 0.94
    119	    0199  DE CA				 fmulp	 st(2),	st			 ;FPU: X Y Len Dir
    120
    121					 ;Dir:=	Dir - 0.30
    122	    019B  D8 64	36			 fsub	 dword ptr [si+d0_3-start]	 ;FPU: X Y Len Dir
    123	    019E  EB A0				 jmp	 spi00
    124
    125					 ;-------------------------------------------------------------------------------
    126		  =002B			 base	 equ	 43		 ;base offset for packed notes format
    127
    128	    01A0  60			 inthan: pusha
    129
    130	    01A1  FE 4C	07			 dec	 byte ptr [si+ticks-start]
    131	    01A4  75 2D				 jne	 ih90
    132
    133	    01A6  BA 0330			 mov	 dx, 330h	 ;set MPU-401 into UART	mode and
    134	    01A9  B8 3FC0			 mov	 ax, 3FC0h	 ; set instrument on channel 0 to:
    135	    01AC  EF				 out	 dx, ax
    136	    01AD  B0 0B				 mov	 al, 12-1	 ; vibraphone
    137	    01AF  EE				 out	 dx, al
    138
    139	    01B0  B0 90				 mov	 al, 90h	 ;turn on note for channel 0
    140	    01B2  EE				 out	 dx, al
    141
    142	    01B3  8C C6				 mov	 si, es		 ;fetch	note
    143	    01B5  AC				 lodsb			 ;al:= ds:[si++]
    144	    01B6  8E C6				 mov	 es, si
    145
    146	    01B8  3C 00				 cmp	 al, 0		 ;end of score?
    147	    01BA  75 06				 jne	 ih10		 ;skip if not
    148	    01BC  68 01D5r			  push	 offset	score	 ;restart music
    149	    01BF  07				  pop	 es
    150	    01C0  EB 11				  jmp	 ih90
    151	    01C2			 ih10:				 ;unpack note byte into	pitch and duration
    152	    01C2  D4 06				 aam	 6		 ;ah:= al/6; al:= remainder
    153	    01C4  40				 inc	 ax		 ;1..6
    154	    01C5  C0 E0	02			 shl	 al, 2		 ;*4: 4, 8, 12,	16, 20,	24
    155	    01C8  A2 0107r			 mov	 byte ptr ticks, al ;note duration (ticks); 1/4	note = 16/18.2
    156
    157	    01CB  8A C4				 mov	 al, ah		 ;play note's pitch
    158	    01CD  04 2B				 add	 al, base
    159	    01CF  EE				 out	 dx, al
    160
    161	    01D0  B0 7F				 mov	 al, 7Fh	 ;full volume
    162	    01D2  EE				 out	 dx, al
    163	    01D3			 ih90:
    164	    01D3  61				 popa
    165	    01D4  CF				 iret
    166
    167	    01D5  93			 score	 db	 (67-base)*6+4-1 ;quarter note
    168	    01D6  BD				 db	 (74-base)*6+4-1
    169	    01D7  A7				 db	 (70-base)*6+6-1 ;dotted quarter note
    170	    01D8  9D				 db	 (69-base)*6+2-1 ;eigth	note
    171
    172	    01D9  91				 db	 (67-base)*6+2-1
    173	    01DA  A3				 db	 (70-base)*6+2-1
    174	    01DB  9D				 db	 (69-base)*6+2-1
    175	    01DC  91				 db	 (67-base)*6+2-1
    176	    01DD  8B				 db	 (66-base)*6+2-1
    177	    01DE  9D				 db	 (69-base)*6+2-1
    178	    01DF  75				 db	 (62-base)*6+4-1
    179
    180	    01E0  91				 db	 (67-base)*6+2-1
    181	    01E1  73				 db	 (62-base)*6+2-1
    182	    01E2  9D				 db	 (69-base)*6+2-1
    183	    01E3  73				 db	 (62-base)*6+2-1
    184	    01E4  A3				 db	 (70-base)*6+2-1
    185	    01E5  9C				 db	 (69-base)*6+1-1 ;sixteenth note
    186	    01E6  90				 db	 (67-base)*6+1-1
    187	    01E7  9D				 db	 (69-base)*6+2-1
    188	    01E8  73				 db	 (62-base)*6+2-1
    189
    190	    01E9  91				 db	 (67-base)*6+2-1
    191	    01EA  72				 db	 (62-base)*6+1-1
    192	    01EB  90				 db	 (67-base)*6+1-1
    193	    01EC  9D				 db	 (69-base)*6+2-1
    194	    01ED  72				 db	 (62-base)*6+1-1
    195	    01EE  9C				 db	 (69-base)*6+1-1
    196	    01EF  A3				 db	 (70-base)*6+2-1
    197	    01F0  9C				 db	 (69-base)*6+1-1
    198	    01F1  90				 db	 (67-base)*6+1-1
    199	    01F2  9C				 db	 (69-base)*6+1-1
    200	    01F3  72				 db	 (62-base)*6+1-1
    201
    202	    01F4  BA				 db	 (74-base)*6+1-1
    203	    01F5  AE				 db	 (72-base)*6+1-1
    204	    01F6  A2				 db	 (70-base)*6+1-1
    205	    01F7  9C				 db	 (69-base)*6+1-1
    206	    01F8  90				 db	 (67-base)*6+1-1
    207	    01F9  A2				 db	 (70-base)*6+1-1
    208	    01FA  9C				 db	 (69-base)*6+1-1
    209	    01FB  90				 db	 (67-base)*6+1-1
    210	    01FC  8A				 db	 (66-base)*6+1-1
    211	    01FD  9C				 db	 (69-base)*6+1-1
    212
    213	    01FE  90				 db	 (67-base)*6+1-1
    214	    01FF  00				 db	 0
    215
    216	    0200  ???? ????		 oldint	 dw	 ?, ?		 ;original interrupt handler vector
    217						 end	 start
Turbo Assembler	 Version 4.1	    03/29/24 08:17:56	    Page 2
Symbol Table




Symbol Name			  Type	 Value

??DATE				  Text	 "03/29/24"
??FILENAME			  Text	 "vlf	  "
??TIME				  Text	 "08:17:56"
??VERSION			  Number 040A
@32BIT				  Text	 0
@CODE				  Text	 DGROUP
@CODESIZE			  Text	 0
@CPU				  Text	 1F1FH
@CURSEG				  Text	 _TEXT
@DATA				  Text	 DGROUP
@DATASIZE			  Text	 0
@FILENAME			  Text	 VLF
@INTERFACE			  Text	 000H
@MODEL				  Text	 1
@STACK				  Text	 DGROUP
@WORDSIZE			  Text	 4
BASE				  Number 002B
D0_3				  Dword	 DGROUP:0136
D0_94				  Dword	 DGROUP:013C
D135				  Word	 DGROUP:0130
D3				  Number DGROUP:012B
D4				  Word	 DGROUP:013A
D600				  Word	 DGROUP:012E
D770				  Word	 DGROUP:012A
DEBUG				  Number 0000
DSCRW				  Word	 DGROUP:012C
D_1_6				  Dword	 DGROUP:0132
IH10				  Near	 DGROUP:01C2
IH90				  Near	 DGROUP:01D3
INTHAN				  Near	 DGROUP:01A0
OLDINT				  Word	 DGROUP:0200
RETURN				  Near	 DGROUP:0129
SCORE				  Byte	 DGROUP:01D5
SCRH				  Number 0300
SCRW				  Number 0400
SPI00				  Near	 DGROUP:0140
SPI20				  Near	 DGROUP:0170
SPIRAL				  Near	 DGROUP:0140
START				  Near	 DGROUP:0100
TICKS				  Number DGROUP:0107
WAIT10				  Near	 DGROUP:0123

Groups & Segments		  Bit Size Align  Combine Class

DGROUP				  Group
  _DATA				  16  0000 Word	  Public  DATA
  _TEXT				  16  0204 Word	  Public  CODE
