; _____________________________________________ ; | | ; | Project: APPLER | ; | File: EMULATE.ASM | ; | Compiler: 16-bit TASM (2.5) | ; | | ; | Subject: I/O Switches Emulation | ; | | ; | Authors: Alexander & Emil | ; |_____________________________________________| include GLOBALS.INC include INTERFAC.INC ReadAllFreeSpace Emulate segment common assume CS:Emulate,DS:Apple,ES:Video,SS:Data UseNextFreeSpace AppleFlags db 00110000b even AppleSP dw StackPage*100h + 0FFh SaveStack dw 0 ResetFlag db 0 C000 db 0 C050 db 0000b C080 db 1000b HGRcolor db 07h even Port3?4h dw 3D4h CheckAddress UseNextFreeSpace SetScrEntry Proc far ; Set Screen mode. mov si,ax ; AL - mode. xor al,1b mov ah,C050 ror ax,1 rol ah,1 mov C050,ah mov dx,50h SetScrEntry10: shr si,1 mov bx,dx adc bl,0 shl bx,1 mov di,offset SetScrEntry20 jmp SS:C0XXRead[bx] SetScrEntry20: add dl,2 cmp dl,58h jb SetScrEntry10 ret SetScrEntry Endp CheckAddress UseNextFreeSpace PowerON Proc far ; Initial Test entry point mov ax,Apple mov bx,Video mov ds,ax mov es,bx mov al,0 call SetScrEntry jmp RESET PowerON Endp CheckAddress UseNextFreeSpace RESET Proc far ; Reset Pressed entry point xor eax,eax push ax popf mov ax,Data mov ss,ax mov sp,CS:[SaveStack] call SystemRESET RESET_Wait: sti test CS:[ResetFlag],00000001b jnz RESET_Wait mov ax,Apple mov bx,Video mov ds,ax mov es,bx xor ax,ax mov bx,ax mov cx,ax mov dx,ax mov di,ax mov bp,ax sahf mov si,DS:[RESETvector] DoNext RESET Endp CheckAddress UseNextFreeSpace ChangeTEXTcolor Proc far Save ax cx di es mov di,ss mov es,di mov di,offset TEXTchars + 1 mov cx,40h mov ah,al shl al,4 cld TC_Loop1: stosb inc di loop TC_Loop1 or al,10000000b mov cx,40h TC_Loop2: stosb inc di loop TC_Loop2 mov cx,80h mov al,ah TC_Loop3: stosb inc di loop TC_Loop3 Restore ax cx di es ret ChangeTEXTcolor Endp CheckAddress ;-------------- Keyboard emulation entries & subroutines ----------------------- UseNextFreeSpace C000r: call key_taken call synchronize mov al,C000 mov bl,ch jmp di C000w: call synchronize sahf DoNext C010r: call synchronize and byte ptr C000,01111111b call GetBuffer mov bl,ch jmp di C010w: call synchronize and byte ptr C000,01111111b call GetBuffer sahf DoNext ResetKeyboard Proc far mov C000,0 call ClearBuffer ret ResetKeyboard Endp CheckAddress ;-------------- Speaker emulation entries & subroutines ------------------------ UseNextFreeSpace C030r: call synchronize in al,61h xor al,00000010b out 61h,al mov bl,ch jmp di C030w: call synchronize in al,61h xor al,00000010b out 61h,al sahf DoNext C020r: call synchronize mov al,cs:C020bit xor al,80h mov cs:C020bit,al push dx mov dx,378h out dx,al pop dx mov bl,ch jmp di C020w: call synchronize mov al,cs:C020bit xor al,80h mov cs:C020bit,al push dx mov dx,378h out dx,al pop dx sahf DoNext C020bit db 0 ResetSpeaker Proc far in al,61h and al,11111100b out 61h,al mov cs:C020bit,0 ret ResetSpeaker Endp CheckAddress ;-------------- Digital Outputs emulation entries & subroutines ---------------- UseNextFreeSpace C05Or: call synchronize mov bl,al and bx,111b mov al,PPortBuffer and al,DOmasks[bx] or al,DOvalues[bx] mov PPortBuffer,al mov bx,dx mov dx,PPortBase out dx,al mov dx,bx mov bl,ch jmp di C05Ow: call synchronize mov bl,al and bx,111b mov al,PPortBuffer and al,DOmasks[bx] or al,DOvalues[bx] mov PPortBuffer,al mov bx,dx mov dx,PPortBase out dx,al mov dx,bx mov bl,ch sahf DoNext DOmasks db 11111110b,11111110b,11111101b,11111101b db 11111011b,11111011b,11110111b,11110111b DOvalues db 0000b,0001b,0000b,0010b,0000b,0100b,0000b,1000b ResetDigOutputs Proc far mov al,PPortBuffer and al,11110000b mov PPortBuffer,al mov dx,PPortBase out dx,al ret ResetDigOutputs Endp even PPortBase dw 3BCh PPortBuffer db 00001111b ; 0 - Inputs, 1 - Outputs CheckAddress ;-------------- Joystick emulation entries & subroutines ----------------------- UseNextFreeSpace C061r: mov al,cs:JoyButton1 mov bl,ch jmp di C062r: mov al,cs:JoyButton2 mov bl,ch jmp di JoyButton1 db 7Fh JoyButton2 db 7Fh joy_pos1 dw 0 joy_pos2 dw 0 JoyStick db 0 JoyEnd label word JoyEx db 0 JoyEy db 0 Joy_Table dw 1400,0,2800,1400 C064r: mov ebx,eax sub ebx,cs:C07X_eax shr ebx,16 cmp bx,cs:joy_pos1 mov al,0FEh rcr al,1 xchg al,cs:JoyEx or al,cs:JoyEx mov bl,ch jmp di C065r: mov ebx,eax sub ebx,cs:C07X_eax shr ebx,16 cmp bx,cs:joy_pos2 mov al,0FEh rcr al,1 xchg al,cs:JoyEy or al,cs:JoyEy mov bl,ch jmp di CheckAddress UseNextFreeSpace C07Xr: mov cs:C07X_eax,eax xor bx,bx mov cs:JoyEnd,bx mov bl,cs:JoyStick shl bl,1 and bl,6 mov ax,cs:Joy_Table[bx] mov cs:joy_pos1,ax mov bl,cs:JoyStick shr bl,1 and bl,6 mov ax,cs:Joy_Table[bx] mov cs:joy_pos2,ax mov al,0FFh mov bl,ch jmp di C0612r: mov al,7Fh mov bl,ch jmp di C0645r: mov al,0FFh mov bl,ch jmp di C07X_eax dd 0 C061w: C062w: C07Xw: sahf DoNext CheckAddress ;-------------- N/A entries & subroutines -------------------------------------- UseNextFreeSpace C0NAr: mov bl,ch jmp di C0NAw: sahf DoNext CheckAddress ;-------------- Synchronization Subroutines ------------- MacroSoft & IvoSoft--- UseNextFreeSpace ; Entry: ; EAH - 65C02 clocks sinse last call to synchronize synchronize proc near synchro_push_ax label byte cli push ax bx cx dx lahf push ax mov ebx,eax sub eax,cs:old_eax mov al,00000100b ; 00000110b out 43h,al jmp $+2 shr eax,16 ; 10 mul cs:O75 shr eax,6 ; 12 mov bx,ax ; 65C02 clocks in timer ticks in al,40h jmp $+2 jmp $+2 jmp $+2 mov ah,al in al,40h jmp $+2 jmp $+2 jmp $+2 xchg al,ah mov cx,cs:old_timer sub cx,ax ; cx-time passed since last call sub bx,cx ; bx-time to wait jbe synch_xit ; don't wait sub cx,bx synch_loop: mov cx,ax mov al,00000100b cli out 43h,al jmp $+2 jmp $+2 jmp $+2 in al,40h jmp $+2 jmp $+2 jmp $+2 mov ah,al in al,40h sti xchg al,ah sub cx,ax sub bx,cx jnb synch_loop cli synch_xit: mov cs:old_timer,ax mov cs:old_eax,ebx mov eax,ebx pop ax sahf pop dx cx bx ax sti ret old_timer dw 0 O75 dd 75 old_eax dd 0 synchronize endp CheckAddress ;-------------- Include peripheral devices emulation files --------------------- include Video.ASM include DRAM.INC include Floppy.INC include PhisFlop.INC Emulate ends ;------------------------------------------------------------------------------- Peripher segment public assume CS:Peripher,DS:Nothing,ES:Nothing OldTimer dd 0 TimerINIT Proc near mov ax,3508h int 21h mov word ptr OldTimer,bx mov word ptr OldTimer+2,es push cs pop ds mov dx,offset TimerCntr mov ax,2508h int 21h ret TimerINIT Endp TimerTINI Proc near lds dx,OldTimer mov ax,2508h int 21h ret TimerTINI Endp even Tcounters dw Tlen dup (0) Tadrs dd Tlen dup (0) TimerReq Proc far ; CX:DX-Proc address, AX-Count Save bx pushf cli xor bx,bx TimerReq10: cmp word ptr Tadrs[BX],dx jne TimerReq20 cmp word ptr Tadrs[BX]+2,cx je TimerReq50 TimerReq20: add bx,4 cmp bx,Tlen*4 jb TimerReq10 xor bx,bx TimerReq30: cmp Tcounters[BX],0 je TimerReq40 add bx,2 cmp bx,Tlen*2 jb TimerReq30 jmp TimerReqExit ; ERROR: Tlen must be increased TimerReq40: shl bx,1 mov word ptr Tadrs[BX],dx mov word ptr Tadrs[BX]+2,cx TimerReq50: shr bx,1 mov Tcounters[BX],ax TimerReqExit: popf Restore bx ret TimerReq Endp TimerCntr Proc far Save ax bx cli xor ax,ax mov bx,ax TimerCntr10: cmp Tcounters[bx],0 je TimerCntr20 inc ax dec Tcounters[bx] jnz TimerCntr20 SaveAll shl bx,1 call Tadrs[bx] RestoreAll TimerCntr20: add bx,2 cmp bx,Tlen*2 jb TimerCntr10 or ax,ax comment % mov al,20h out 20h,al % jnz TimerCntr30 comment % in al,21h or al,00000001b out 21h,al % TimerCntr30: xchg bp,sp xor ax,ax xchg ax,cs:TimerFlags or [bp+8],ax xchg sp,bp Restore ax bx jmp cs:[OldTimer] ; iret TimerFlags dw 0 TimerCntr Endp SystemINIT Proc far mov al,00001100b mov dx,3F2h out dx,al mov al,IRQmasks out 21h,al call TimerINIT call FloppyINIT call PhisFloppyINIT ret SystemINIT Endp SystemTINI Proc far call PhisFloppyTINI call FloppyTINI call TimerTINI mov al,0 out 21h,al ret SystemTINI Endp SystemRESET Proc far ; Registers state: call ResetDRAM ; SS -> Data call ResetKeyboard ; IF = 0 call ResetSpeaker ; All others are unknown call ResetDigOutputs ; and may be modified. call ResetVideo call ResetFloppy call ResetPhisFloppy ret SystemRESET Endp Peripher ends ;=============================================================================== Data segment stack 'stack' even C0xxRead dw 10h dup ( C000r ) dw 10h dup ( C010r ) dw 10h dup ( C020r ) ; C020 dw 10h dup ( C030r ) dw 10h dup ( C0NAr ) ; C040 dw C050r, C051r dw C052r, C053r dw C054r, C055r dw C056r, C057r dw 8 dup ( C05Or ) dw C0NAr,C0612r,C0612r,C0NAr ; C060 dw C0645r,C0645r dw 2 dup ( C0NAr ) dw 4 dup ( C0NAr ) dw 4 dup ( C0NAr ) dw 10h dup ( C07Xr ) ; C070 dw 10h dup ( C08Xr ) dw 10h dup ( C0NAr ) ; C090 dw 10h dup ( C0NAr ) ; C0A0 dw 10h dup ( C0NAr ) ; C0B0 dw 10h dup ( C0NAr ) ; C0C0 dw 10h dup ( C0NAr ) ; C0D0 dw C0E0r,C0E1r,C0E2r,C0E3r,C0E4r,C0E5r,C0E6r,C0E7r dw C0E8r,C0E9r,C0EAr,C0EBr,C0ECr,C0EDr,C0EEr,C0EFr dw 10h dup ( C0NAr ) ; C0F0 C0xxWrite dw 10h dup ( C000w ) dw 10h dup ( C010w ) dw 10h dup ( C020w ) ; C020 dw 10h dup ( C030w ) dw 10h dup ( C0NAw ) ; C040 dw C050w, C051w ; C050 dw C052w, C053w dw C054w, C055w dw C056w, C057w dw 8 dup ( C05Ow ) dw C0NAw,C061w,C062w,C0NAw ; C060 dw 4 dup ( C0NAw ) dw 4 dup ( C0NAw ) dw 4 dup ( C0NAw ) dw 10h dup ( C07Xw ) ; C070 dw 10h dup ( C08Xw ) ; C080 dw 10h dup ( C0NAw ) ; C090 dw 10h dup ( C0NAw ) ; C0A0 dw 10h dup ( C0NAw ) ; C0B0 dw 10h dup ( C0NAw ) ; C0C0 dw 10h dup ( C0NAw ) ; C0D0 dw C0E0w,C0E1w,C0E2w,C0E3w,C0E4w,C0E5w,C0E6w,C0E7w dw C0E8w,C0E9w,C0EAw,C0EBw,C0ECw,C0EDw,C0EEw,C0EFw dw 10h dup ( C0NAw ) ; C0F0 Data ends End