0,0 → 1,755 |
; |
; TFTP Wave Player |
; |
; Compile with FASM for Menuet |
; |
; |
; 12.7.2002 - Audio system calls by VT |
; |
|
use32 |
|
org 0x0 |
|
db 'MENUET00' ; 8 byte id |
dd 38 ; required os |
dd START ; program start |
dd I_END ; program image size |
dd 0x100000 ; required amount of memory |
dd 0x00000000 ; reserved=no extended header |
|
include 'lang.inc' |
include 'macros.inc' |
|
delay dd 145 |
wait_for dd 0x0 |
|
START: ; start of execution |
|
mov dword [prompt], p9 |
mov dword [promptlen], p9len - p9 |
|
call draw_window ; at first, draw the window |
|
still: |
|
mov eax,10 ; wait here for event |
int 0x40 |
|
cmp eax,1 ; redraw request ? |
jz red |
cmp eax,2 ; key in buffer ? |
jz key |
cmp eax,3 ; button in buffer ? |
jz button |
|
jmp still |
|
red: ; redraw |
call draw_window |
jmp still |
|
key: ; Keys are not valid at this part of the |
mov eax,2 ; loop. Just read it and ignore |
int 0x40 |
jmp still |
|
button: ; button |
mov eax,17 ; get id |
int 0x40 |
|
cmp ah,1 ; button id=1 ? |
jnz noclose |
|
|
; close socket before exiting |
mov eax, 53 |
mov ebx, 1 |
mov ecx, [socketNum] |
int 0x40 |
|
mov [socketNum], dword 0 |
|
|
mov eax,0xffffffff ; close this program |
int 0x40 |
|
noclose: |
cmp ah,2 ; copy file to local machine? |
jnz nocopyl |
|
mov dword [prompt], p5 |
mov dword [promptlen], p5len - p5 |
call draw_window ; |
|
; Copy File from Remote Host to this machine |
call translateData ; Convert Filename & IP address |
mov edi, tftp_filename + 1 |
mov [edi], byte 0x01 ; setup tftp msg |
call copyFromRemote |
|
jmp still |
|
nocopyl: |
|
|
cmp ah,4 |
jz f1 |
cmp ah,5 |
jz f2 |
jmp nof12 |
|
f1: |
mov [addr],dword source |
mov [ya],dword 35 |
jmp rk |
|
f2: |
mov [addr],dword destination |
mov [ya],dword 35+16 |
|
rk: |
mov ecx,15 |
mov edi,[addr] |
mov al,' ' |
rep stosb |
|
call print_text |
|
mov edi,[addr] |
|
f11: |
mov eax,10 |
int 0x40 |
cmp eax,2 |
jz fbu |
jmp still |
fbu: |
mov eax,2 |
int 0x40 ; get key |
shr eax,8 |
cmp eax,8 |
jnz nobs |
cmp edi,[addr] |
jz f11 |
sub edi,1 |
mov [edi],byte ' ' |
call print_text |
jmp f11 |
nobs: |
cmp eax,dword 31 |
jbe f11 |
cmp eax,dword 95 |
jb keyok |
sub eax,32 |
keyok: |
mov [edi],al |
|
call print_text |
|
add edi,1 |
mov esi,[addr] |
add esi,15 |
cmp esi,edi |
jnz f11 |
|
jmp still |
|
print_text: |
|
mov eax,13 |
mov ebx,103*65536+15*6 |
mov ecx,[ya] |
shl ecx,16 |
mov cx,8 |
mov edx,0x224466 |
int 0x40 |
|
mov eax,4 |
mov ebx,103*65536 |
add ebx,[ya] |
mov ecx,0xffffff |
mov edx,[addr] |
mov esi,15 |
int 0x40 |
|
ret |
|
|
nof12: |
jmp still |
|
|
;*************************************************************************** |
; Function |
; translateData |
; |
; Description |
; Coverts the filename and IP address typed in by the user into |
; a format suitable for the IP layer. |
; |
; The filename, in source, is converted and stored in tftp_filename |
; The host ip, in destination, is converted and stored in tftp_IP |
; |
;*************************************************************************** |
translateData: |
|
; first, build up the tftp command string. This includes the filename |
; and the transfer protocol |
|
|
; First, write 0,0 |
mov al, 0 |
mov edi, tftp_filename |
mov [edi], al |
inc edi |
mov [edi], al |
inc edi |
|
; Now, write the file name itself, and null terminate it |
mov ecx, 15 |
mov ah, ' ' |
mov esi, source |
|
td001: |
lodsb |
stosb |
cmp al, ah |
loopnz td001 |
|
cmp al,ah ; Was the entire buffer full of characters? |
jne td002 |
dec edi ; No - so remove ' ' character |
|
td002: |
mov [edi], byte 0 |
inc edi |
mov [edi], byte 'O' |
inc edi |
mov [edi], byte 'C' |
inc edi |
mov [edi], byte 'T' |
inc edi |
mov [edi], byte 'E' |
inc edi |
mov [edi], byte 'T' |
inc edi |
mov [edi], byte 0 |
|
mov esi, tftp_filename |
sub edi, esi |
mov [tftp_len], edi |
|
|
; Now, convert the typed IP address into a real address |
; No validation is done on the number entered |
; ip addresses must be typed in normally, eg |
; 192.1.45.24 |
|
xor eax, eax |
mov dh, 10 |
mov dl, al |
mov [tftp_IP], eax |
|
; 192.168.24.1 1.1.1.1 1. 9.2.3. |
|
mov esi, destination |
mov edi, tftp_IP |
|
mov ecx, 4 |
|
td003: |
lodsb |
sub al, '0' |
add dl, al |
lodsb |
cmp al, '.' |
je ipNext |
cmp al, ' ' |
je ipNext |
mov dh, al |
sub dh, '0' |
mov al, 10 |
mul dl |
add al, dh |
mov dl, al |
lodsb |
cmp al, '.' |
je ipNext |
cmp al, ' ' |
je ipNext |
mov dh, al |
sub dh, '0' |
mov al, 10 |
mul dl |
add al, dh |
mov dl, al |
lodsb |
|
ipNext: |
mov [edi], dl |
inc edi |
mov dl, 0 |
loop td003 |
|
ret |
|
|
|
;*************************************************************************** |
; Function |
; copyFromRemote |
; |
; Description |
; |
;*************************************************************************** |
copyFromRemote: |
|
mov eax,0x20000-512 |
mov [fileposition], eax |
|
; Get a random # for the local socket port # |
mov eax, 3 |
int 0x40 |
mov ecx, eax |
shr ecx, 8 ; Set up the local port # with a random # |
|
; open socket |
mov eax, 53 |
mov ebx, 0 |
mov edx, 69 ; remote port |
mov esi, [tftp_IP] ; remote IP ( in intenet format ) |
int 0x40 |
|
mov [socketNum], eax |
|
; make sure there is no data in the socket - there shouldn't be.. |
|
cfr001: |
mov eax, 53 |
mov ebx, 3 |
mov ecx, [socketNum] |
int 0x40 ; read byte |
|
mov eax, 53 |
mov ebx, 2 |
mov ecx, [socketNum] |
int 0x40 ; any more data? |
|
cmp eax, 0 |
jne cfr001 ; yes, so get it |
|
; Now, request the file |
mov eax, 53 |
mov ebx, 4 |
mov ecx, [socketNum] |
mov edx, [tftp_len] |
mov esi, tftp_filename |
int 0x40 |
|
cfr002: |
|
mov eax,23 ; wait here for event |
mov ebx,1 ; Time out after 10ms |
int 0x40 |
|
cmp eax,1 ; redraw request ? |
je cfr003 |
cmp eax,2 ; key in buffer ? |
je cfr004 |
cmp eax,3 ; button in buffer ? |
je cfr005 |
|
; Any data to fetch? |
mov eax, 53 |
mov ebx, 2 |
mov ecx, [socketNum] |
int 0x40 |
|
cmp eax, 0 |
je cfr002 |
|
push eax ; eax holds # chars |
|
; Update the text on the display - once |
mov eax, [prompt] |
cmp eax, p3 |
je cfr008 |
mov dword [prompt], p3 |
mov dword [promptlen], p3len - p3 |
call draw_window ; |
|
cfr008: |
; we have data - this will be a tftp frame |
|
; read first two bytes - opcode |
mov eax, 53 |
mov ebx, 3 |
mov ecx, [socketNum] |
int 0x40 ; read byte |
|
mov eax, 53 |
mov ebx, 3 |
mov ecx, [socketNum] |
int 0x40 ; read byte |
|
pop eax |
; bl holds tftp opcode. Can only be 3 (data) or 5 ( error ) |
|
cmp bl, 3 |
jne cfrerr |
|
push eax |
|
; do data stuff. Read block #. Read data. Send Ack. |
mov eax, 53 |
mov ebx, 3 |
mov ecx, [socketNum] |
int 0x40 ; read byte |
|
mov [blockNumber], bl |
|
mov eax, 53 |
mov ebx, 3 |
mov ecx, [socketNum] |
int 0x40 ; read byte |
|
mov [blockNumber+1], bl |
|
cfr007: |
mov eax, 53 |
mov ebx, 3 |
mov ecx, [socketNum] |
int 0x40 ; read byte |
|
mov esi, [fileposition] |
mov [esi], bl |
mov [esi+1],bl |
add dword [fileposition],2 |
|
mov eax, 53 |
mov ebx, 2 |
mov ecx, [socketNum] |
int 0x40 ; any more data? |
|
cmp eax, 0 |
jne cfr007 ; yes, so get it |
|
cmp [fileposition],0x20000+0xffff |
jb get_more_stream |
|
wait_more: |
|
mov eax,5 ; wait for correct timer position |
; to trigger new play block |
mov ebx,1 |
int 0x40 |
|
mov eax,26 |
mov ebx,9 |
int 0x40 |
|
cmp eax,[wait_for] |
jb wait_more |
|
add eax,[delay] |
mov [wait_for],eax |
|
mov esi,0x20000 |
mov edi,0x10000 |
mov ecx,65536 |
cld |
rep movsb |
|
mov eax,55 |
mov ebx,0 |
mov ecx,0x10000 |
int 0x40 |
|
mov eax,55 |
mov ebx,1 |
int 0x40 |
|
mov [fileposition],0x20000 |
|
get_more_stream: |
|
; write the block number into the ack |
mov al, [blockNumber] |
mov [ack + 2], al |
|
mov al, [blockNumber+1] |
mov [ack + 3], al |
|
; send an 'ack' |
mov eax, 53 |
mov ebx, 4 |
mov ecx, [socketNum] |
mov edx, ackLen - ack |
mov esi, ack |
int 0x40 |
|
; If # of chars in the frame is less that 516, |
; this frame is the last |
pop eax |
cmp eax, 516 |
je cfr002 |
|
; Write the file |
mov eax, 33 |
mov ebx, source |
mov edx, [filesize] |
mov ecx, I_END + 512 |
mov esi, 0 |
int 0x40 |
|
jmp cfrexit |
|
cfrerr: |
; simple implementation on error - just read all data, and return |
mov eax, 53 |
mov ebx, 3 |
mov ecx, [socketNum] |
int 0x40 ; read byte |
|
mov eax, 53 |
mov ebx, 2 |
mov ecx, [socketNum] |
int 0x40 ; any more data? |
|
cmp eax, 0 |
jne cfrerr ; yes, so get it |
|
jmp cfr006 ; close socket and close app |
|
cfr003: ; redraw request |
call draw_window |
jmp cfr002 |
|
cfr004: ; key pressed |
mov eax,2 ; just read it and ignore |
int 0x40 |
jmp cfr002 |
|
cfr005: ; button |
mov eax,17 ; get id |
int 0x40 |
|
cmp ah,1 ; button id=1 ? |
jne cfr002 ; If not, ignore. |
|
cfr006: |
; close socket |
mov eax, 53 |
mov ebx, 1 |
mov ecx, [socketNum] |
int 0x40 |
|
mov [socketNum], dword 0 |
|
mov eax,-1 ; close this program |
int 0x40 |
|
jmp $ |
|
cfrexit: |
; close socket |
mov eax, 53 |
mov ebx, 1 |
mov ecx, [socketNum] |
int 0x40 |
|
mov [socketNum], dword 0 |
|
mov dword [prompt], p4 |
mov dword [promptlen], p4len - p4 |
call draw_window ; |
|
ret |
|
|
|
|
; ********************************************* |
; ******* WINDOW DEFINITIONS AND DRAW ******** |
; ********************************************* |
|
|
draw_window: |
|
mov eax,12 ; function 12:tell os about windowdraw |
mov ebx,1 ; 1, start of draw |
int 0x40 |
|
; DRAW WINDOW |
mov eax,0 ; function 0 : define and draw window |
mov ebx,100*65536+230 ; [x start] *65536 + [x size] |
mov ecx,100*65536+170 ; [y start] *65536 + [y size] |
mov edx,0x03224466 ; color of work area RRGGBB |
mov esi,0x00334455 ; color of grab bar RRGGBB,8->color gl |
mov edi,0x00ddeeff ; color of frames RRGGBB |
int 0x40 |
|
; WINDOW LABEL |
mov eax,4 ; function 4 : write text to window |
mov ebx,8*65536+8 ; [x start] *65536 + [y start] |
mov ecx,0x00ffffff ; color of text RRGGBB |
mov edx,labelt ; pointer to text beginning |
mov esi,labellen-labelt ; text length |
int 0x40 |
|
|
mov eax,8 ; COPY BUTTON |
mov ebx,20*65536+190 |
mov ecx,79*65536+15 |
mov edx,3 |
mov esi,0x557799 |
; int 0x40 |
|
mov eax,8 ; DELETE BUTTON |
mov ebx,20*65536+190 |
mov ecx,111*65536+15 |
mov edx,2 |
mov esi,0x557799 |
int 0x40 |
|
mov eax,8 |
mov ebx,200*65536+10 |
mov ecx,34*65536+10 |
mov edx,4 |
mov esi,0x557799 |
int 0x40 |
|
mov eax,8 |
mov ebx,200*65536+10 |
mov ecx,50*65536+10 |
mov edx,5 |
mov esi,0x557799 |
int 0x40 |
|
|
; Copy the file name to the screen buffer |
; file name is same length as IP address, to |
; make the math easier later. |
cld |
mov esi,source |
mov edi,text+13 |
mov ecx,15 |
rep movsb |
|
|
; copy the IP address to the screen buffer |
mov esi,destination |
mov edi,text+40+13 |
mov ecx,15 |
rep movsb |
|
; copy the prompt to the screen buffer |
mov esi,[prompt] |
mov edi,text+280 |
mov ecx,[promptlen] |
rep movsb |
|
; Re-draw the screen text |
cld |
mov ebx,25*65536+35 ; draw info text with function 4 |
mov ecx,0xffffff |
mov edx,text |
mov esi,40 |
newline: |
mov eax,4 |
int 0x40 |
add ebx,16 |
add edx,40 |
cmp [edx],byte 'x' |
jnz newline |
|
|
mov eax,12 ; function 12:tell os about windowdraw |
mov ebx,2 ; 2, end of draw |
int 0x40 |
|
ret |
|
|
; DATA AREA |
|
source db 'HEAT8M22.WAV ' |
destination db '192.168.1.24 ' |
|
|
tftp_filename: times 15 + 9 db 0 |
tftp_IP: dd 0 |
tftp_len: dd 0 |
|
addr dd 0x0 |
ya dd 0x0 |
|
fileposition dd 0 ; Points to the current point in the file |
filesize dd 0 ; The number of bytes written / left to write |
fileblocksize dw 0 ; The number of bytes to send in this frame |
|
text: |
db 'SOURCE FILE: xxxxxxxxxxxxxxx ' |
db 'HOST IP ADD: xxx.xxx.xxx.xxx ' |
db ' ' |
db 'WAVE FORMAT: 8 BIT,MONO,22050HZ ' |
db ' ' |
db ' SERVER -> PLAY FILE ' |
db ' ' |
db ' ' |
db 'x <- END MARKER, DONT DELETE ' |
|
|
labelt: |
db 'TFTP Wave Player' |
labellen: |
|
|
prompt: dd 0 |
promptlen: dd 0 |
|
|
p1: db 'Waiting for Command ' |
p1len: |
|
p9: db 'Define SB with setup' |
p9len: |
|
p2: db 'Sending File ' |
p2len: |
|
p3: db 'Playing File ' |
p3len: |
|
p4: db 'Complete ' |
p4len: |
|
p5: db 'Contacting Host... ' |
p5len: |
|
p6: db 'File not found. ' |
p6len: |
|
ack: |
db 00,04,0,1 |
ackLen: |
|
socketNum: |
dd 0 |
|
blockNumber: |
dw 0 |
|
; This must be the last part of the file, because the blockBuffer |
; continues at I_END. |
blockBuffer: |
db 00, 03, 00, 01 |
I_END: |
|
|
|
|
|
|
|
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |