; virtual processor, emulator for FIFTH ; registers usage: ; edi - data stack pointer ; esi - instruction pointer ; es = 0 ; cs - emulator program code segment ; ds = cs org 100h call system_init ; init system, allocate XMS call KB_init ; init keyoard push 0 ; initialize segments pop es push cs pop ds sub ebx, ebx ; initialize pointers mov bx, cs shl ebx, 4 add ebx, buf add ebx, 20000 mov edi, ebx ; data stack add ebx, 10000 mov [resp], ebx ; return stack mov esi, [xms_addr] ; instruction pointer mov ah, 3dh ; open diskfile mov al, 2 mov dx, infile int 21h mov word [fileh], ax mov ax, 4F02h ; set VESA 640*480 8 bit mov bx, 101h int 10h mov ecx, 0 ; load boot block (first 1024 bytes) mov ebx, [xms_addr] call diskload jmp emu xmemtot dw 0 ; amount of accessible XMS infile db 'disk.raw', 0 ; virtual disk file name fileh dw 0 ; it's handle coresiz dw 4096 ; core size gran dw 0 ; VESA granule size quit: mov ax, 3 ; restore text mode int 10h mov ah, 3eh ; close diskfile mov bx, word [fileh] int 21h call KB_restore jmp system_exit ; terminate program resp dd 0 ; return stack pointer emu: ; pick instruction movzx bx, byte [es:esi] inc esi shl bx, 1 add bx, table jmp word [cs:bx] table dw emu ; 0 dw quit dw xkbd@ dw xnum dw xjmp dw xcall ; 5 dw xinc dw xdec dw xdup dw xdrop dw xif ; 10 dw xret dw xc@ dw xc! dw xpush dw xpop ; 15 dw 0 dw xrot dw xdisk@ dw xdisk! dw x@ ; 20 dw x! dw xover dw xswap dw xplus dw xminus ; 25 dw xmul dw xdiv dw xgreat dw xless dw xnot ; 30 dw xi dw xcprt@ dw xcprt! dw xi2 dw xi3 ; 35 dw xshl dw xshr dw lor dw lxor dw xvidmap ; 40 dw xmouse@ dw xvidput dw xcmove dw xcfill dw xtvidput ; 45 dw xdep dw xcharput xkbd@: call KB_read sub edi, 4 mov [es:edi], dl mov ah, 0bh ; check for key in keyboard buffer int 21h cmp al, 0h je emu mov ah, 0 ; read key int 16h jmp emu xnum: mov edx, dword [es:esi] sub edi, 4 mov [es:edi], edx add esi, 4 jmp emu xjmp: mov esi, dword [es:esi] add esi, [xms_addr] jmp emu xcall: mov edx, dword [es:esi] mov eax, [resp] sub eax, 4 mov ebx, esi add ebx, 4 sub ebx, [xms_addr] mov [es:eax], ebx mov [resp], eax mov esi, edx add esi, [xms_addr] jmp emu xinc: inc dword [es:edi] jmp emu xdec: dec dword [es:edi] jmp emu xdup: mov eax, [es:edi] sub edi, 4 mov [es:edi], eax jmp emu xdrop: add edi, 4 jmp emu xif: mov eax, [es:edi] add edi, 4 cmp eax, 0 jne l2 mov esi, [es:esi] add esi, [xms_addr] jmp emu l2: add esi, 4 jmp emu xret: mov eax, [resp] mov esi, [es:eax] add esi, [xms_addr] add eax, 4 mov [resp], eax jmp emu xc@: mov eax, [es:edi] add eax, [xms_addr] sub ecx, ecx mov cl, [es:eax] mov [es:edi], ecx jmp emu xc!: ;( n addr -- ) mov ebx, [es:edi] add edi, 4 mov ecx, [es:edi] add edi, 4 add ebx, [xms_addr] mov [es:ebx], cl jmp emu xpush: mov ebx, [es:edi] add edi, 4 mov eax, [resp] sub eax, 4 mov [es:eax], ebx mov [resp], eax jmp emu xpop: mov eax, [resp] mov ebx, [es:eax] add eax, 4 mov [resp], eax sub edi, 4 mov [es:edi], ebx jmp emu xrot: mov ebx, [es:edi] mov ecx, [es:edi+4] mov edx, [es:edi+8] mov [es:edi+8], ecx mov [es:edi+4], ebx mov [es:edi], edx jmp emu xdisk@: mov ebx, [es:edi] add ebx, [xms_addr] mov ecx, [es:edi+4] add edi, 8 call diskload ; ecx-fromdisk ebx-tomem jmp emu xdisk!: mov ecx, [es:edi] call file_seek mov ecx, 1024 mov ebx, [es:edi+4] add edi, 8 add ebx, [xms_addr] sub edx, edx mov dx, cs shl edx, 4 add edx, buf call memmove ; ebx - from, edx - to, ecx - amount mov ah, 40h mov bx, [fileh] mov cx, 1024 mov dx, buf int 21h jmp emu x@: mov eax, [es:edi] add eax, [xms_addr] mov eax, [es:eax] mov [es:edi], eax jmp emu x!: ;( n addr -- ) mov eax, [es:edi] add eax, [xms_addr] mov ecx, [es:edi+4] add edi, 8 mov [es:eax], ecx jmp emu xover: mov ebx, [es:edi+4] sub edi, 4 mov [es:edi], ebx jmp emu xswap: mov ebx, [es:edi] xchg ebx, [es:edi+4] mov [es:edi], ebx jmp emu xplus: mov ebx, [es:edi] add edi, 4 add [es:edi], ebx jmp emu xminus: mov ebx, [es:edi] add edi, 4 sub [es:edi], ebx jmp emu xmul: mov eax, [es:edi] add edi, 4 sub edx, edx imul dword [es:edi] mov [es:edi], eax jmp emu xdiv: add edi, 4 mov eax, [es:edi] cdq idiv dword [es:edi-4] mov [es:edi], eax jmp emu xgreat: mov eax, [es:edi] add edi, 4 mov edx, 0 cmp [es:edi], eax jng l3 dec edx l3: mov [es:edi], edx jmp emu xless: mov eax, [es:edi] add edi, 4 mov edx, 0 cmp [es:edi], eax jnl l4 dec edx l4: mov [es:edi], edx jmp emu file_seek: ; ( ecx - pointer to seek ) mov eax, 1024 mul ecx mov ecx, eax mov dx, cx shr ecx, 16 mov ah, 42h mov al, 0 mov bx, [ds:fileh] int 21h ret xnot: not dword [es:edi] jmp emu xi: mov ebx, [resp] mov eax, [es:ebx] sub edi, 4 mov [es:edi], eax jmp emu xcprt@: mov dx, [es:edi] in al, dx sub ecx, ecx mov cl, al mov [es:edi], ecx jmp emu xcprt!: mov dx, [es:edi] mov al, [es:edi+4] add edi, 8 out dx, al jmp emu xi2: mov ebx, [resp] mov eax, [es:ebx+4] sub edi, 4 mov [es:edi], eax jmp emu xi3: mov ebx, [resp] mov eax, [es:ebx+8] sub edi, 4 mov [es:edi], eax jmp emu xshl: mov cl, [es:edi] add edi, 4 shl dword [es:edi], cl jmp emu xshr: mov cl, [es:edi] add edi, 4 shr dword [es:edi], cl jmp emu lor: mov eax, [es:edi] add edi, 4 or [es:edi], eax jmp emu lxor: mov eax, [es:edi] add edi, 4 xor [es:edi], eax jmp emu xvidmap: mov edx, [es:edi] add edx, [xms_addr] add edi, 4 push edi push esi push 0a000h pop es mov word [ds:gra], 0 push 0 pop ds mov esi, edx mapl1: mov dx, [cs:gra] xor bx, bx mov ax, 4f05h int 10h mov edi, 0 mov cx, 4096 ; mov cx, 16384 mapl2: mov eax, [ds:esi] add esi, 4 stosd loop mapl2 inc word [cs:gra] ; cmp word [cs:gra], 5 cmp word [cs:gra], 19 jne mapl1 push 0 pop es push cs pop ds pop esi pop edi jmp emu gra dw 0 xmouse@: mov ax, 0bh ; read motion counter int 33h push dx sub eax, eax mov ax, cx cwd shl edx, 16 add edx, eax mov [es:edi-4], edx pop ax cwd shl edx, 16 add edx, eax mov [es:edi-8], edx mov ax, 3 ; read buttons int 33h sub eax, eax mov ax, bx sub edi, 12 mov [es:edi], eax jmp emu memmove: ; ebx - from, edx - to, ecx - amount cmp ecx, 0 je l11 mov al, [es:ebx] mov [es:edx], al inc ebx inc edx dec ecx jmp memmove l11: ret memmove2: ; ebx - from, edx - to, ecx - amount add ebx, ecx add edx, ecx l7: cmp ecx, 0 je l12 dec ebx dec edx mov al, [es:ebx] mov [es:edx], al dec ecx jmp l7 l12: ret xcmove: mov ecx, [es:edi] add edi, 12 mov edx, [es:edi-8] add edx, [xms_addr] mov ebx, [es:edi-4] add ebx, [xms_addr] cmp ecx, 0 je emu cmp ebx, edx ja l8 call memmove2 jmp emu l8: call memmove jmp emu xcfill: mov ecx, [es:edi] mov edx, [es:edi+4] add edx, [xms_addr] mov eax, [es:edi+8] add edi, 12 l9: cmp ecx, 0 je emu mov [es:edx], al inc edx dec ecx jmp l9 diskload: ; ecx-fromdisk ebx-tomem push ebx call file_seek mov cx, 1024 mov ah, 3fh mov bx, [fileh] mov dx, buf int 21h sub ebx, ebx ; move it to XMS mov bx, cs shl ebx, 4 add ebx, buf pop edx mov ecx, 1024 call memmove ; ebx - from, edx - to, ecx - amount ret xdep: sub eax, eax mov ax, cs shl eax, 4 add eax, buf add eax, 20000 sub eax, edi shr eax, 2 sub edi, 4 mov [es:edi], eax jmp emu include 'vidput.inc' include 'tvidput.inc' include 'charput.inc' include 'system.inc' include 'kbdrive.inc' buf: ; pointer to end of the code