;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; TERMINAL ; ; Compile with FASM for Menuet ; use32 org 0x0 db 'MENUET01' ; header dd 0x01 ; header version dd START ; entry point dd I_END ; image size dd I_END+0x10000 ; required memory dd I_END+0x10000 ; esp dd 0x0 , 0x0 ; I_Param , I_Path include 'lang.inc' include 'macros.inc' START: ; start of execution ; Clear the screen memory mov eax, ' ' mov edi,text mov ecx,80*30 /4 cld rep stosd call draw_window still: ; check connection status mov eax,53 mov ebx,6 mov ecx,[socket] mcall mov ebx, [socket_status] mov [socket_status], eax cmp eax, ebx je waitev red: call draw_window waitev: mov eax,23 ; wait here for event mov ebx,20 mcall cmp eax,1 ; redraw request ? je red cmp eax,2 ; key in buffer ? je key cmp eax,3 ; button in buffer ? je button ; any data from the socket? mov eax, 53 mov ebx, 2 mov ecx, [socket] mcall cmp eax, 0 jne read_input jmp still read_input: push ecx mov eax, 53 mov ebx, 3 mov ecx, [socket] mcall pop ecx call handle_data push ecx mov eax, 53 mov ebx, 2 mov ecx, [socket] mcall pop ecx cmp eax, 0 jne read_input call draw_text jmp still handle_data: ; Telnet servers will want to negotiate options about our terminal window ; just reject them all. ; Telnet options start with the byte 0xff and are 3 bytes long. mov al, [telnetstate] cmp al, 0 je state0 cmp al, 1 je state1 cmp al, 2 je state2 jmp hd001 state0: cmp bl, 255 jne hd001 mov al, 1 mov [telnetstate], al ret state1: mov al, 2 mov [telnetstate], al ret state2: mov al, 0 mov [telnetstate], al mov [telnetrep+2], bl mov edx, 3 mov eax,53 mov ebx,7 mov ecx,[socket] mov esi, telnetrep mcall ret hd001: cmp bl,13 ; BEGINNING OF LINE jne nobol mov ecx,[pos] add ecx,1 boll1: sub ecx,1 mov eax,ecx xor edx,edx mov ebx,80 div ebx cmp edx,0 jne boll1 mov [pos],ecx jmp newdata nobol: cmp bl,10 ; LINE DOWN jne nolf addx1: add [pos],dword 1 mov eax,[pos] xor edx,edx mov ecx,80 div ecx cmp edx,0 jnz addx1 mov eax,[pos] jmp cm1 nolf: cmp bl,8 ; BACKSPACE jne nobasp mov eax,[pos] dec eax mov [pos],eax mov [eax+text],byte 32 mov [eax+text+60*80],byte 0 jmp newdata nobasp: cmp bl,15 ; CHARACTER jbe newdata mov eax,[pos] mov [eax+text],bl mov eax,[pos] add eax,1 cm1: mov ebx,[scroll+4] imul ebx,80 cmp eax,ebx jb noeaxz mov esi,text+80 mov edi,text mov ecx,ebx cld rep movsb mov eax,ebx sub eax,80 noeaxz: mov [pos],eax newdata: ret key: ; KEY mov eax,2 ; send to modem mcall mov ebx, [socket_status] cmp ebx, 4 ; connection open? jne still ; no, so ignore key shr eax,8 cmp eax,178 ; ARROW KEYS jne noaup mov al,'A' call arrow jmp still noaup: cmp eax,177 jne noadown mov al,'B' call arrow jmp still noadown: cmp eax,179 jne noaright mov al,'C' call arrow jmp still noaright: cmp eax,176 jne noaleft mov al,'D' call arrow jmp still noaleft: modem_out: call to_modem jmp still button: ; BUTTON mov eax,17 mcall cmp ah,1 ; CLOSE PROGRAM jne noclose mov eax,53 mov ebx,8 mov ecx,[socket] mcall or eax,-1 mcall noclose: cmp ah, 2 ; Set IP jne notip mov [string_x], dword 78 mov [string_y], dword 276 mov [string_length], dword 15 call read_string mov esi,string-1 mov edi,ip_address xor eax,eax ip1: inc esi cmp [esi],byte '0' jb ip2 cmp [esi],byte '9' jg ip2 imul eax,10 movzx ebx,byte [esi] sub ebx,48 add eax,ebx jmp ip1 ip2: mov [edi],al xor eax,eax inc edi cmp edi,ip_address+3 jbe ip1 call draw_window jmp still notip: cmp ah, 3 ; set port jne notport mov [string_x], dword 215 mov [string_y], dword 276 mov [string_length], dword 4 call read_string mov esi,string-1 mov edi,port xor eax,eax ip11: inc esi cmp [esi],byte '0' jb ip21 cmp [esi],byte '9' jg ip21 imul eax,10 movzx ebx,byte [esi] sub ebx,48 add eax,ebx jmp ip11 ip21: mov [edi],al inc edi mov [edi],ah call draw_window jmp still notport: cmp ah, 4 ; connect jne notcon mov eax, [socket_status] cmp eax, 4 je still call connect jmp still notcon: cmp ah,5 ; disconnect jne notdiscon call disconnect jmp still notdiscon: ; Echo Toggle cmp ah, 6 jne still mov al, [echo] not al mov [echo], al call draw_window jmp still arrow: push eax mov al,27 call to_modem mov al,'[' call to_modem pop eax call to_modem ret to_modem: pusha push ax mov [tx_buff], al mov edx, 1 cmp al, 13 jne tm_000 mov edx, 2 tm_000: mov eax,53 mov ebx,7 mov ecx,[socket] mov esi, tx_buff mcall pop bx mov al, [echo] cmp al, 0 je tm_001 push bx call handle_data pop bx cmp bl, 13 jne tm_002 mov bl, 10 call handle_data tm_002: call draw_text tm_001: popa ret disconnect: mov eax,53 mov ebx,8 mov ecx,[socket] mcall ret connect: pusha mov ecx, 1000 ; local port starting at 1000 getlp: inc ecx push ecx mov eax, 53 mov ebx, 9 mcall pop ecx cmp eax, 0 ; is this local port in use? jz getlp ; yes - so try next mov eax,53 mov ebx,5 mov dl, [ip_address + 3] shl edx, 8 mov dl, [ip_address + 2] shl edx, 8 mov dl, [ip_address + 1] shl edx, 8 mov dl, [ip_address] mov esi, edx movzx edx, word [port] ; telnet port id mov edi,1 ; active open mcall mov [socket], eax popa ret ; ********************************************* ; ******* WINDOW DEFINITIONS AND DRAW ******** ; ********************************************* draw_window: pusha mov eax,12 mov ebx,1 mcall xor eax,eax ; DRAW WINDOW mov ebx,100*65536+491 + 8 +15 mov ecx,100*65536+270 + 20 ; 20 for status bar mov edx,0x14000000 mov edi,title mcall ; draw status bar mov eax, 13 mov ebx, 4*65536+484 + 8 +15 mov ecx, 270*65536 + 3 mov edx, 0x00557799 mcall mov eax,8 ; BUTTON 2: SET IP mov ebx,4*65536+70 mov ecx,273*65536+12 mov esi, 0x00557799 mov edx,2 mcall mov eax,4 ; Button text mov ebx,6*65536+276 mov ecx,0x00ffffff mov edx,setipt mov esi,setiplen-setipt mcall mov eax,47 mov edi,ip_address ; display IP address mov edx,78*65536+276 mov esi,0x00ffffff mov ebx,3*65536 ipdisplay: movzx ecx,byte [edi] mcall add edx,6*4*65536 inc edi cmp edi,ip_address+4 jb ipdisplay mov eax,8 ; BUTTON 3: SET PORT mov ebx,173*65536+38 mov ecx,273*65536+12 mov edx,3 mov esi, 0x00557799 mcall mov eax,4 ; Button text mov ebx,178*65536+276 mov ecx,0x00ffffff mov edx,setportt mov esi,setportlen-setportt mcall mov edx,216*65536+276 ; display port mov esi,0x00ffffff mov ebx,4*65536 mov eax,47 movzx ecx,word [port] mcall mov eax,8 ; BUTTON 4: Connect mov ebx,250*65536+50 mov ecx,273*65536+12 mov esi, 0x00557799 mov edx,4 mcall mov eax,4 ; Button text mov ebx,255*65536+276 mov ecx,0x00ffffff mov edx,cont mov esi,conlen-cont mcall mov eax,8 ; BUTTON 5: disconnect mov ebx,303*65536+70 mov ecx,273*65536+12 mov edx,5 mov esi, 0x00557799 mcall mov eax,4 ; Button text mov ebx,307*65536+276 mov ecx,0x00ffffff mov edx,dist mov esi,dislen-dist mcall mov esi,contlen-contt ; display connected status mov edx, contt mov eax, [socket_status] cmp eax, 4 ; 4 is connected je pcon mov esi,discontlen-discontt mov edx, discontt pcon: mov eax,4 ; status text mov ebx,380*65536+276 mov ecx,0x00ffffff mcall mov eax,8 ; BUTTON 6: echo mov ebx,460*65536+50 mov ecx,273*65536+12 mov edx,6 mov esi, 0x00557799 mcall mov edx,echot mov esi,echolen-echot mov al, [echo] cmp al, 0 jne peo mov edx,echoot mov esi,echoolen-echoot peo: mov eax,4 ; Button text mov ebx,463*65536+276 mov ecx,0x00ffffff mcall xor eax,eax mov edi,text+80*30 mov ecx,80*30 /4 cld rep stosd call draw_text mov eax,12 mov ebx,2 mcall popa ret draw_text: pusha mov esi,text mov eax,0 mov ebx,0 newletter: mov cl,[esi] cmp cl,[esi+30*80] jne yesletter jmp noletter yesletter: mov [esi+30*80],cl ; erase character pusha mov edx, 0 ; bg colour mov ecx, ebx add ecx, 26 shl ecx, 16 mov cx, 9 mov ebx, eax add ebx, 6 shl ebx, 16 mov bx, 6 mov eax, 13 mcall popa ; draw character pusha mov ecx, 0x00ffffff push bx mov ebx,eax add ebx,6 shl ebx,16 pop bx add bx,26 mov eax,4 mov edx,esi mov esi,1 mcall popa noletter: add esi,1 add eax,6 cmp eax,80*6 jb newletter mov eax,0 add ebx,10 cmp ebx,24*10 jb newletter popa ret read_string: mov edi,string mov eax,'_' mov ecx,[string_length] inc ecx cld rep stosb call print_text mov edi,string f11: mov eax,10 mcall cmp eax,2 jne read_done mov eax,2 mcall shr eax,8 cmp eax,13 je read_done cmp eax,8 jnz nobsl cmp edi,string jz f11 sub edi,1 mov [edi],byte '_' call print_text jmp f11 nobsl: cmp eax,dword 31 jbe f11 cmp eax,dword 95 jb keyok sub eax,32 keyok: mov [edi],al call print_text inc edi mov esi,string add esi,[string_length] cmp esi,edi jnz f11 read_done: call print_text ret print_text: pusha mov eax,13 mov ebx,[string_x] shl ebx,16 add ebx,[string_length] imul bx,6 mov ecx,[string_y] shl ecx,16 mov cx,8 mov edx,0x00000000 mcall mov eax,4 mov ebx,[string_x] shl ebx,16 add ebx,[string_y] mov ecx,0x00ffffff mov edx,string mov esi,[string_length] mcall popa ret ; DATA AREA telnetrep db 0xff,0xfc,0x00 telnetstate db 0 string_length dd 16 string_x dd 200 string_y dd 60 string db '________________' tx_buff db 0, 10 ip_address db 001,002,003,004 port db 0,0 echo db 0 socket dd 0x0 socket_status dd 0x0 pos dd 80 * 1 scroll dd 1 dd 24 wcolor dd 0x000000 title db 'Telnet v0.1',0 setipt db 'IP Address: . . .' setiplen: setportt db 'Port:' setportlen: cont db 'Connect' conlen: dist db 'Disconnect' dislen: contt db 'Connected' contlen: discontt db 'Disconnected' discontlen: echot db 'Echo On' echolen: echoot db 'Echo Off' echoolen: text: I_END: