     1                                  ; ****************************************************************************
     2                                  ; piano2.s (TRDOS 386, TRDOS v2.0 - sample binary file, 'piano2.prg')
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; PIANO2.PRG ! TEST program !  INT 34h (IOCTL functions) test !
     5                                  ;
     6                                  ; 21/06/2016
     7                                  ;
     8                                  ; [ Last Modification: 22/06/2016 ]
     9                                  ;
    10                                  ; ****************************************************************************
    11                                  
    12                                  ; 29/04/2016
    13                                  ; TRDOS 386 system calls (temporary list!)
    14                                  _ver 	equ 0
    15                                  _exit 	equ 1
    16                                  _fork 	equ 2
    17                                  _read 	equ 3
    18                                  _write	equ 4
    19                                  _open	equ 5
    20                                  _close 	equ 6
    21                                  _wait 	equ 7
    22                                  _creat 	equ 8
    23                                  _link 	equ 9
    24                                  _unlink	equ 10
    25                                  _exec	equ 11
    26                                  _chdir	equ 12
    27                                  _time 	equ 13
    28                                  _mkdir 	equ 14
    29                                  _chmod	equ 15
    30                                  _chown	equ 16
    31                                  _break	equ 17
    32                                  _stat	equ 18
    33                                  _seek	equ 19
    34                                  _tell 	equ 20
    35                                  _mount	equ 21
    36                                  _umount	equ 22
    37                                  _setuid	equ 23
    38                                  _getuid	equ 24
    39                                  _stime	equ 25
    40                                  _quit	equ 26	
    41                                  _intr	equ 27
    42                                  _fstat	equ 28
    43                                  _emt 	equ 29
    44                                  _mdate 	equ 30
    45                                  _stty 	equ 31
    46                                  _gtty	equ 32
    47                                  _ilgins	equ 33
    48                                  _sleep	equ 34
    49                                  _msg    equ 35
    50                                  
    51                                  %macro sys 1-4
    52                                      ; 29/04/2016 - TRDOS 386 (TRDOS v2.0)	
    53                                      ; 03/09/2015	
    54                                      ; 13/04/2015
    55                                      ; Retro UNIX 386 v1 system call.	
    56                                      %if %0 >= 2   
    57                                          mov ebx, %2
    58                                          %if %0 >= 3    
    59                                              mov ecx, %3
    60                                              %if %0 = 4
    61                                                 mov edx, %4   
    62                                              %endif
    63                                          %endif
    64                                      %endif
    65                                      mov eax, %1
    66                                      ;int 30h
    67                                      int 40h ; TRDOS 386 (TRDOS v2.0)	   
    68                                  %endmacro
    69                                  
    70                                  ; TRDOS 386 (and Retro UNIX 386 v1) system call format:
    71                                  ; sys systemcall (eax) <arg1 (ebx)>, <arg2 (ecx)>, <arg3 (edx)>
    72                                  
    73                                  [BITS 32] ; We need 32-bit intructions for protected mode
    74                                  
    75                                  [ORG 0] 
    76                                  
    77                                  start: 
    78 00000000 E80E020000              	call	clrscr 
    79 00000005 E8EB010000              	call	toneon
    80                                  start1: 
    81 0000000A E823000000              	call	show_panio 
    82 0000000F E868010000              	call	sound 
    83 00000014 E85D000000              	call	show_dot 
    84 00000019 B401                    	mov	ah, 1   ; check keyboard buffer
    85 0000001B CD32                    	int	32h	; TRDOS 386 Keyboard Interrupt
    86 0000001D 74EB                    	jz	short start1 
    87                                  	;
    88 0000001F E8E0010000              	call	toneoff 
    89 00000024 E8EA010000              	call	clrscr
    90                                   
    91                                  terminate:
    92                                  	sys 	_exit			   ; INT 40h
    92                              <1> 
    92                              <1> 
    92                              <1> 
    92                              <1> 
    92                              <1>  %if %0 >= 2
    92                              <1>  mov ebx, %2
    92                              <1>  %if %0 >= 3
    92                              <1>  mov ecx, %3
    92                              <1>  %if %0 = 4
    92                              <1>  mov edx, %4
    92                              <1>  %endif
    92                              <1>  %endif
    92                              <1>  %endif
    92 00000029 B801000000          <1>  mov eax, %1
    92                              <1> 
    92 0000002E CD40                <1>  int 40h
    93                                  here:
    94 00000030 EBFE                    	jmp	short here
    95                                   
    96                                  show_panio:
    97 00000032 FE0D[47020000]          	dec	byte [delay]
    98 00000038 753B                    	jnz	short msg1 
    99 0000003A C605[47020000]40        	mov	byte [delay], 64 
   100 00000041 C605[48020000]04        	mov	byte [fig_r], 4
   101 00000048 C605[49020000]00        	mov	byte [fig_c], 0 
   102 0000004F B909000000              	mov	ecx, 9
   103 00000054 BE[4E020000]            	mov	esi, msg 
   104 00000059 E800010000              	call	set_wp 
   105 0000005E E892000000              	call	bitmap_char
   106                                  
   107 00000063 E8CB010000              	call	video_page_update
   108                                   
   109 00000068 FE05[4A020000]                  inc     byte [msgptr]
   110 0000006E 8025[4A020000]1F        	and	byte [msgptr], 011111b 
   111                                  msg1:
   112 00000075 C3                      	retn 
   113                                  
   114                                  show_dot: 
   115 00000076 8B1D[D0020000]           	mov	ebx, [counter]
   116 0000007C 3B1D[CC020000]          	cmp	ebx, [lastdot]
   117 00000082 7470                    	je	short dot1 
   118                                   
   119 00000084 8B1D[CC020000]          	mov	ebx, [lastdot] 
   120 0000008A 8A83[B3020000]          	mov	al, [ebx+melody]	 ; get code for nth of 
   121 00000090 FEC8                    	dec	al 
   122 00000092 C0E003                  	shl	al, 3 
   123 00000095 A2[49020000]            	mov 	[fig_c], al 
   124 0000009A C605[48020000]0E                mov     byte [fig_r], 14 
   125                                   
   126 000000A1 31C9                    	xor	ecx, ecx
   127 000000A3 FEC1                    	inc	cl	; mov ecx, 1
   128 000000A5 BE[59020000]            	mov	esi, blnk 
   129 000000AA E8AF000000              	call	set_wp
   130 000000AF E841000000              	call	bitmap_char
   131                                  
   132 000000B4 E87A010000              	call	video_page_update 
   133                                   
   134 000000B9 BB[D0020000]            	mov	ebx, counter 
   135 000000BE 891D[CC020000]          	mov	[lastdot], ebx 
   136 000000C4 8A83[B3020000]          	mov	al, [ebx+melody]	; get code for nth of 
   137 000000CA FEC8                    	dec	al
   138 000000CC C0E003                  	shl	al, 3
   139 000000CF A2[49020000]                    mov     [fig_c], al 
   140 000000D4 C605[48020000]0E                mov     byte [fig_r], 14 
   141                                   
   142 000000DB B901000000              	mov	ecx, 1 
   143 000000E0 BE[58020000]            	mov	esi, dot 
   144 000000E5 E874000000              	call	set_wp 
   145 000000EA E806000000              	call	bitmap_char 
   146                                  
   147 000000EF E83F010000              	call	video_page_update 
   148                                  dot1:
   149 000000F4 C3                      	retn 
   150                                  
   151                                  bitmap_char: 
   152                                  each_character: 
   153 000000F5 51                      	push	ecx 
   154 000000F6 0FB61E                  	movzx	ebx, byte [esi] ; BL is the character's ASCII code 
   155 000000F9 46                      	inc	esi 
   156 000000FA 66C1E303                	shl	bx, 3	; ebx = ebx * 8, because each 
   157                                  			; character's dot pattern occupys 8 bytes 
   158 000000FE 81C3[5A020000]          	add	ebx, pattern 
   159 00000104 B208                    	mov	dl, 8   ; ROW_LEN ;The dot pattern is 8 bytes (row) 
   160                                  each_row:
   161 00000106 8A23                    	mov	ah, [ebx] ; Get the byte which refers immediate row 
   162 00000108 43                      	inc	ebx	; Pointer to next byte 
   163 00000109 B108                    	mov	cl, 8   ; COL_LEN ;each row is 8 dots 
   164                                  each_dot:
   165 0000010B D0C4                    	rol	ah, 1	; Bit 0 is the next bit we want 
   166 0000010D 88E0                    	mov	al, ah 
   167 0000010F 2401                    	and	al, 1   ; Mask other bits 
   168 00000111 F6D8                    	neg 	al	; If Bit 0 = 1 then AL = 0FFh 
   169 00000113 24DB                    	and	al, 0DBh ; If AL = 0FFh then AL = 0DBh else space 
   170 00000115 AA                      	stosb		; Display AL = char 
   171 00000116 B006                    	mov	al, 6 
   172 00000118 AA                      	stosb		; Display AL = attribute 
   173                                  end_e_dot:
   174 00000119 E2F0                    	loop	each_dot
   175 0000011B 57                      	push	edi 
   176 0000011C 83EF02                  	sub	edi, 2 
   177 0000011F FD                      	std 
   178 00000120 B108                    	mov	cl, 8 
   179                                  shadow:
   180 00000122 66B80006                	mov	ax, 0600h 
   181 00000126 F366AF                  	repe	scasw 
   182 00000129 67E31C                          jcxz    no_shadow 
   183 0000012C 83C704                  	add	edi, 4
   184 0000012F 66B8B205                	mov	ax, 05B2h 
   185 00000133 66AB                    	stosw 
   186 00000135 83EF02                  	sub	edi, 2 
   187 00000138 66B8DB06                	mov	ax, 06DBh 
   188 0000013C F366AF                  	repe	scasw 
   189 0000013F 7407                    	jz	short no_shadow 
   190 00000141 FEC1                    	inc	cl
   191 00000143 83C702                  	add	edi, 2 
   192 00000146 EBDA                    	jmp	shadow 
   193                                  no_shadow:
   194 00000148 5F                      	pop	edi 
   195 00000149 81C790000000            	add	edi, 144 ; Pointer to next line on screen 
   196 0000014F FC                      	cld 
   197 00000150 FECA                    	dec	dl 
   198                                  end_e_row:
   199 00000152 75B2                    	jnz	short each_row 
   200 00000154 81EFF0040000            	sub	edi, 1264 
   201 0000015A 59                      	pop	ecx 
   202                                  end_e_char: 
   203 0000015B E298                    	loop	each_character 
   204 0000015D C3                      	retn 
   205                                  
   206                                  set_wp:
   207 0000015E B050                    	mov 	al, 80 ; number of columns * 2
   208 00000160 F625[48020000]          	mul	byte [fig_r]
   209 00000166 0205[49020000]          	add	al, [fig_c] 
   210 0000016C 80D400                  	adc	ah, 0 
   211 0000016F 66D1E0                  	shl	ax, 1 
   212 00000172 0FB7F8                  	movzx	edi, ax
   213 00000175 81C7[FC020000]          	add	edi, video_buffer ; video page 0 
   214 0000017B C3                      	retn
   215                                   
   216                                  sound:
   217 0000017C 50                      	push	eax
   218 0000017D 53                      	push	ebx
   219 0000017E 51                      	push	ecx
   220 0000017F 52                      	push	edx
   221 00000180 56                      	push	esi
   222 00000181 57                      	push	edi 
   223 00000182 8B35[D0020000]          	mov	esi, [counter] ; initialize ptr to 
   224                                  		               ; melody/beat strings 
   225                                  	; check delay loop 
   226 00000188 BB[8A020000]            	mov	ebx, beat      ; get offset of beat 
   227                                  		       	       ; string 
   228 0000018D 0FB60C33                	movzx	ecx, byte [ebx+esi] ; get beat value for 
   229                                  		       	       ; note number ESI 
   230                                  	
   231 00000191 8B1D[D4020000]          	mov	ebx, [ticks]   ; get timer tick count 
   232 00000197 01CB                    	add	ebx, ecx       ; add beat count to 
   233                                  		       	       ; current tick count 
   234 00000199 B400                    	mov	ah, 0	       ; function to get 
   235                                  		               ; time-of-day count 
   236 0000019B CD35                    	int	35h	       ; TRDOS 386 Date&Time Interrupt
   237 0000019D 39D9                    	cmp	ecx, ebx       ; cmp count with 
   238                                  		       	       ; end-of-note count 
   239 0000019F 7641                    	jbe	short finish   ; if not equal, continue 
   240                                  		       	       ; sound 
   241 000001A1 46                       	inc	esi	       ; else, point to next 
   242                                  		       	       ; note 
   243 000001A2 FF05[D0020000]          	inc	dword [counter] ; go get the next note 
   244                                  
   245                                  	;mov	ah, 0	       ; function to get 
   246                                  		               ; time-of-day count 
   247 000001A8 CD35                    	int	35h	       ; TRDOS 386 Date&Time Interrupt
   248                                  
   249 000001AA 890D[D4020000]          	mov	[ticks], ecx
   250                                   
   251 000001B0 B401                     	mov	ah, 1		; out
   252 000001B2 B0B6                    	mov	al, 0B6h        ; initialize channel 2 
   253                                  		      	 	; for mode 3 
   254 000001B4 66BA4300                	mov	dx, 43h		; port address/number	
   255 000001B8 CD34                    	int	34h		; TRDOS 386 IOCTL Interrupt
   256                                  
   257                                  	; Look up a note, get it's frequeny, place in channel 2 
   258                                  next_note:
   259 000001BA BB[B3020000]            	mov	ebx, melody     ; get offset of melody 
   260                                  		       		; string 
   261 000001BF 0FB60433                	movzx	eax, byte [ebx+esi] ; get code for nth of 
   262                                  		       		; the string 
   263 000001C3 3CFF                    	cmp	al, 0FFh	; is it FF? (end of 
   264                                                                  ; string marker) 
   265 000001C5 7422                    	je	short no_more   ; if so,jump to end of 
   266                                  		       		; routine 
   267                                  	; get the frequency 
   268 000001C7 BB[A3020000]            	mov	ebx, frequency  ; get offset of the 
   269                                  		                ; frequency table 
   270 000001CC FEC8                    	dec 	al		; EAX-1 so that counting 
   271                                  		       		; start from 0 
   272 000001CE D0E0                    	shl	al, 1	        ; double AX,since word- 
   273                                  		       		; length table 
   274 000001D0 89C7                    	mov	edi, eax	; mov to EDI for 
   275                                  		       		; addressing 
   276 000001D2 668B0C3B                	mov	cx, [ebx+edi]   ; get the frequency 
   277                                  		       		; from the table 
   278                                  	; start the note playing
   279 000001D6 B401                    	mov	ah, 1		; out
   280 000001D8 88C8                    	mov	al, cl		; prepare to send low 
   281                                  		       		; byte of frequency
   282                                  	;mov	dx, 42h 	; send to latch 
   283                                  		       		; register (via I/O reg) 
   284 000001DA 664A                    	dec	dx
   285 000001DC CD34                    	int	34h		; TRDOS 386 IOCTL Interrupt
   286                                  
   287 000001DE 88E8                    	mov	al, ch		; prepare high byte 
   288                                  	;mov	dx, 42h 	; send high byte 
   289 000001E0 CD34                    	int	34h		; TRDOS 386 IOCTL Interrupt
   290                                  finish: 
   291 000001E2 5F                      	pop	edi
   292 000001E3 5E                      	pop	esi
   293 000001E4 5A                      	pop	edx
   294 000001E5 59                      	pop	ecx
   295 000001E6 5B                      	pop	ebx
   296 000001E7 58                      	pop	eax
   297 000001E8 C3                      	retn
   298                                  
   299                                  no_more:
   300 000001E9 C705[D0020000]0000-     	mov	dword [counter], 0
   300 000001F1 0000               
   301 000001F3 EBED                    	jmp	short finish
   302                                  
   303                                  toneon:
   304                                  	; Turn speaker and timer on 
   305 000001F5 B400                    	mov	ah, 0 	; in
   306 000001F7 66BA6100                	mov	dx, 61h	; get current status of Port B
   307 000001FB CD34                    	int	34h	; TRDOS 386 IOCTL Interrupt
   308 000001FD 0C03                    	or	al, 3	; enable the speaker and timer channel2 
   309                                  	;mov	ah, 1	; out
   310 000001FF FEC4                    	inc	ah	; replace the byte 
   311 00000201 CD34                    	int	34h	; TRDOS 386 IOCTL Interrupt
   312 00000203 C3                      	retn
   313                                  
   314                                  toneoff:
   315                                  	; Turn off timer 2
   316 00000204 B400                    	mov	ah, 0 	; in
   317 00000206 66BA6100                	mov	dx, 61h	; get the byte in Port_B 
   318 0000020A CD34                    	int	34h	; TRDOS 386 IOCTL Interrupt
   319 0000020C 24FC                    	and	al, 0FCh ; turn off the speaker bits 
   320                                  	;mov	ah, 1	; out
   321 0000020E FEC4                    	inc	ah	; replace the byte in Port_B 
   322 00000210 CD34                    	int	34h	; TRDOS 386 IOCTL Interrupt
   323 00000212 C3                      	retn
   324                                  
   325                                  clrscr:
   326 00000213 BF[FC020000]            	mov	edi, video_buffer
   327 00000218 B9D0070000              	mov	ecx, 80*25
   328 0000021D 66B82007                        mov     ax, 0720h ; light gray char space (blank)
   329 00000221 F366AB                  	rep	stosw
   330                                  
   331 00000224 E80A000000              	call	video_page_update
   332                                  
   333 00000229 6631D2                          xor     dx, dx    ; column 0, row 0
   334                                  
   335                                  	; DX = cursor position
   336 0000022C B402                    	mov	ah, 2		; Set cursor position
   337 0000022E 30FF                    	xor	bh, bh		; for video page 0
   338 00000230 CD31                    	int	31h		; TRDOS 386 video interrupt
   339 00000232 C3                      	retn
   340                                  
   341                                  video_page_update:
   342                                  	; copy video buffer content to video page 0
   343 00000233 BB01000000              	mov	ebx, 1	; BL = 1 = user to system
   344 00000238 B200                    	mov	dl, 0	; video page 0
   345 0000023A B9[FC020000]            	mov	ecx, video_buffer
   346 0000023F B81F000000              	mov	eax, 31 ; 'sysvideo'
   347 00000244 CD40                    	int	40h	; TRDOS 386 system call	
   348 00000246 C3                      	retn
   349                                  
   350                                  ; Data
   351                                  
   352 00000247 01                      delay:	db 1
   353 00000248 00                      fig_r:	db 0
   354 00000249 00                      fig_c:	db 0
   355 0000024A 00000000                msgptr: dd 0
   356 0000024E 000102000102000102-     msg:	db 0,1,2,0,1,2,0,1,2,0 
   356 00000257 00                 
   357 00000258 03                      dot	db 3 
   358 00000259 04                      blnk	db 4
   359 0000025A FEFEFEFEFEFEFEFE        pattern: db	0FEh, 0FEh, 0FEh, 0FEh, 0FEh, 0FEh, 0FEh, 0FEh 
   360 00000262 E0E0E0E0FEFEFEFE        	 db	0E0h, 0E0h, 0E0h, 0E0h, 0FEh, 0FEh, 0FEh, 0FEh 
   361 0000026A 0E0E0E0EFEFEFEFE        	 db	00Eh, 00Eh, 00Eh, 00Eh, 0FEh, 0FEh, 0FEh, 0FEh 
   362 00000272 1814121070906000        	 db	018h, 014h, 012h, 010h, 070h, 090h, 060h, 0000 
   363 0000027A 0000000000000000        	 db	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000 
   364 00000282 183C7EC3C37E3C18        	 db	018h, 03Ch, 07Eh, 0C3h, 0C3h, 07Eh, 03Ch, 018h 
   365                                  
   366 0000028A 06060C                  beat:	db   6,6,12	;duration of each 
   367 0000028D 06060C                  	db   6,6,12 
   368 00000290 0606060606060C          	db   6,6,6,6,6,6,12 
   369 00000297 06060C                  	db   6,6,12 
   370 0000029A 06060C                  	db   6,6,12 
   371 0000029D 060606061800            	db   6,6,6,6,24,0 
   372                                  			;note 
   373                                  frequency:
   374 000002A3 E808EF071107AD06        	dw   2280,2031,1809,1709 ;table of 
   375 000002AB F1054B05B7047304        	dw   1521,1355,1207,1139 ;frequencies 
   376                                  
   377                                  melody:
   378 000002B3 050303                  	db   5,3,3	 ;,0FFH;frequency code 
   379 000002B6 040202                  	db   4,2,2 
   380 000002B9 01020304050505          	db   1,2,3,4,5,5,5 
   381 000002C0 050303                  	db   5,3,3 
   382 000002C3 040202                  	db   4,2,2 
   383 000002C6 0103050501FF            	db   1,3,5,5,1,0FFh 
   384                                  			 ;of each note
   385 000002CC 00000000                lastdot: dd 0
   386 000002D0 00000000                counter: dd 0 
   387 000002D4 00000000                ticks:	 dd 0
   388                                  
   389 000002D8 4572646F67616E2054-     db	'Erdogan Tan - TRDOS 386 '
   389 000002E1 616E202D205452444F-
   389 000002EA 532033383620       
   390 000002F0 32322F30362F323031-     db	'22/06/2016'
   390 000002F9 36                 
   391 000002FA 00                      db 	0 
   392                                  
   393                                  bss_start:
   394                                  
   395                                  ABSOLUTE bss_start
   396                                  
   397 000002FB <res 00000001>          alignb 2
   398                                  
   399                                  video_buffer:
   400 000002FC <res 00000FA0>          	resb	4000 ; 80*25*2
   401                                  
   402                                  ;bss_end:
