Category : Assembly Language Source Code
Archive   : APL2EM.ZIP
Filename : APPLE.ASM
Title APPLE.ASM Apple Emulator (65C02 Processor)
;******************************************************************************
;
; Name: APPLE.ASM Apple Emulator (65C02 Processor)
;
; Group: Emulator
;
; Revision: 1.00
;
; Date: January 30, 1988
;
; Author: Randy W. Spurlock
;
;******************************************************************************
;
; Module Functional Description:
;
; This module contains all the code for the Apple
; specific part of the Apple emulator.
;
;******************************************************************************
;
; Changes:
;
; DATE REVISION DESCRIPTION
; -------- -------- -------------------------------------------------------
; 1/30/88 1.00 Original
;
;******************************************************************************
Page
;
; Public Declarations
;
Public Initialize ; Apple emulator initialization routine
Public Read_Memory ; Read 65C02 Apple memory routine
Public Write_Memory ; Write 65C02 Apple memory routine
Public System_Reset ; Apple system reset routine (Interrupt)
Public System_Request ; System request routine (Interrupt)
Public Reset_System ; Apple reset system routine
Public Request_System ; Apple request system routine
Public Error ; Apple emulator error routine
Public Exit ; Apple emulator exit routine
;
; External Declarations
;
Extrn Memory_Init:Near ; Memory initialization routine(MEMORY)
Extrn Device_Init:Near ; Device initialization routine(DEVICE)
Extrn Video_Init:Near ; Video initialization routine (VIDEO)
Extrn Video_Reset:Near ; Video reset routine (VIDEO)
Extrn Int_Init:Near ; Interrupt initialization (INT)
Extrn Int_Reset:Near ; Interrupt reset routine (INT)
Extrn TTY_Init:Near ; Initialize TTY mode routine (TTY)
Extrn TTY_Reset:Near ; Reset TTY mode routine (TTY)
Extrn Write_TTY:Near ; Write TTY routine (TTY)
Extrn Set_Position:Near ; Set current position routine (TTY)
Extrn Set_Row:Near ; Set current row routine (TTY)
Extrn Set_Column:Near ; Set current column routine (TTY)
Extrn Set_Attribute:Near ; Set current attribute routine (TTY)
Extrn Set_Foreground:Near ; Set current foreground routine (TTY)
Extrn Set_Background:Near ; Set current background routine (TTY)
Extrn Set_Cursor:Near ; Set cursor position routine (TTY)
Extrn Set_Type:Near ; Set cursor type routine (TTY)
Extrn Get_Position:Near ; Get current position routine (TTY)
Extrn Get_Row:Near ; Get current row routine (TTY)
Extrn Get_Column:Near ; Get current column routine (TTY)
Extrn Get_Attribute:Near ; Get current attribute routine (TTY)
Extrn Get_Foreground:Near ; Get current foreground routine (TTY)
Extrn Get_Background:Near ; Get current background routine (TTY)
Extrn Get_Cursor:Near ; Get cursor position routine (TTY)
Extrn Get_Type:Near ; Get cursor type routine (TTY)
Extrn Clear_Screen:Near ; Clear screen routine (TTY)
Extrn Scroll_Up:Near ; Scroll window up routine (WINDOW)
Extrn Scroll_Down:Near ; Scroll window down routine (WINDOW)
Extrn Clear_Window:Near ; Clear window routine (WINDOW)
Extrn Save_Window:Near ; Save window routine (WINDOW)
Extrn Restore_Window:Near ; Restore window routine (WINDOW)
Extrn Flush_Keyboard:Near ; Flush keyboard routine (KEYBOARD)
Extrn Get_Key:Near ; Get keyboard code routine (KEYBOARD)
Extrn Printf:Near ; Generic Printf routine (PRINTF)
Extrn Set_LED:Near ; Set keyboard LED routine (KEYBOARD)
Extrn Key_Reset:Near ; Keyboard reset routine (KEYBOARD)
Extrn Key_Status:Byte ; Keyboard status byte (KEYBOARD)
Extrn Last_Key:Byte ; Last keyboard scan code (KEYBOARD)
Extrn Error_Table:Word ; Error string table (DATA)
Extrn System_ROM:Word ; Apple system ROM file name (DATA)
Extrn Read_Table:Word ; Read memory page table (DATA)
Extrn Write_Table:Word ; Write memory page table (DATA)
Extrn System_Flag:Byte ; Apple emulator system flag byte(DATA)
Extrn Emulate_Flag:Byte ; Emulator system flag byte (DATA)
Extrn RAM_Space:Word ; RAM space segment value (DATA)
Extrn ALT_Space:Word ; Alternate RAM space segment (DATA)
Extrn ERR_NO_MEMORY:Abs ; Not enough memory error code (DATA)
Extrn ERR_NO_SYSTEM_FILE:Abs ; No system ROM file error code (DATA)
Extrn ERR_BAD_SYSTEM_FILE:Abs ; Bad system ROM file error code (DATA)
Extrn ERR_BAD_SYSTEM_IMAGE:abs; Bad system ROM image error code(DATA)
;
; LOCAL Equates
;
SYSTEM_ADDRESS Equ 0D000h ; Apple system ROM load address
SYSTEM_SIZE Equ 3000h ; Apple system ROM size (Bytes)
OP_SIZE Equ 80h ; Op-code work area size (128 Bytes)
OP_BASE Equ 07h ; Op-code work area base (Op_Size Log 2)
;
; Define any include files needed
;
Include Macros.inc ; Include the macro definitions
Include Equates.inc ; Include the equate definitions
.286c ; Include 80286 instructions
Page
;
; Define the emulator code segment
;
Emulate Segment Word Public 'EMULATE' ; Emulator code segment
Assume cs:Emulate, ds:Nothing, es:Nothing
Subttl Initialize Initialize the Apple Emulator
Page +
;******************************************************************************
;
; Initialize()
;
; Clear direction flag (All moves are forward)
; Try to allocate the 65C02 RAM space (64k)
; If able to allocate the RAM space
; Call routine to initialize memory
; Call routine to load the Apple system ROM
; Call routine to initialize expansion slot devices
; Call routine to initialize interrupts
; Call routine to initialize video system
; Call routine to initilize keyboard LED's
; Try to allocate the alternate 65C02 RAM space (64k)
; If able to allocate the RAM space
; Save the alternate RAM space segment
; Call routine to initialize memory
; Call routine to setup 65C02 registers (Reset)
; Else unable to allocate the needed RAM space
; Set error code to not enough memory
; Call the error routine
; Call routine to exit the emulator
; Endif
; Else unable to allocate the needed RAM space
; Set error code to not enough memory
; Call the error routine
; Call routine to exit the emulator
; Endif
; Return to the caller
;
; Registers on Entry:
;
; None
;
; Registers on Exit:
;
; DL - Accumulator initialized (0h)
; DH - 65C02 flags initialized (0h)
; CL - Y index register initialized (0h)
; CH - X index register initialized (0h)
; BX - Stack pointer initialized (1FFh)
; SI - Program counter initialized (FFFCh)
; DS - 65C02 RAM space
; ES - Video RAM segment
;
;******************************************************************************
Even ; Force procedure to even address
Initialize Proc Near ; Emulator initialization procedure
cld ; Clear direction flag (All forward)
mov ah,ALLOCATE_MEMORY ; Get the allocate memory function code
mov bx,RAM_SIZE ; Get number of paragraphs to allocate
int DOS ; Try to allocate the 65C02 RAM space
jnc Continue ; Jump if no errors allocating space
Memory_Error:
mov al,ERR_NO_MEMORY ; Get not enough memory error code
call Error ; Call routine to print the error
call Exit ; Call routine to exit the emulator
Continue:
mov ds,ax ; Setup RAM space segment address
mov cs:[RAM_Space],ax ; Save the RAM space segment address
call Memory_Init ; Call routine to initialize memory
call Load_System ; Call routine to load system ROM
call Device_Init ; Call routine to initialize devices
call Int_Init ; Call routine to initialize interrupts
call Video_Init ; Call routine to initialize video
call Set_LED ; Call routine to initialize LED's
mov ah,ALLOCATE_MEMORY ; Get the allocate memory function code
mov bx,RAM_SIZE ; Get number of paragraphs to allocate
int DOS ; Try to allocate the 65C02 RAM space
jc Memory_Error ; Jump if errors allocating space
mov cs:[ALT_Space],ax ; Save alternate RAM space segment
mov ds,ax ; Setup RAM space segment address
call Memory_Init ; Call routine to initialize memory
mov ds,cs:[RAM_Space] ; Setup the 65C02 RAM space segment
call CPU_Init ; Call CPU initialize routine
ret ; Return to the caller
Initialize Endp ; End of the Initialize procedure
Subttl Load_System Load the Apple System ROM
Page +
;******************************************************************************
;
; Load_System(RAM_Space)
;
; Try to open the Apple System ROM data file
; If no errors opening the System ROM file
; Try to read in the System ROM image
; If errors reading the System ROM
; Set error code to bad System ROM file
; Call the error routine
; Call routine to exit the emulator
; Endif
; Close the System ROM file
; Else errors opening the System ROM file
; Set error code to no System ROM file
; Call the error routine
; Call routine to exit the emulator
; Endif
; Return to the caller
;
; Registers on Entry:
;
; DS - 65C02 RAM space
;
; Registers on Exit:
;
; AX-DX - Destroyed
; SI-DI - Destroyed
;
;******************************************************************************
Even ; Force procedure to even address
Load_System Proc Near ; Load System ROM procedure
mov ax,cs ; Get the current code segment value
mov bx,ds ; Save 65C02 RAM space segment value
mov ds,ax ; Setup to open the system ROM file
mov ah,OPEN_FILE ; Get the open file function code
mov al,READ_ONLY ; Get the read file access code
lea dx,cs:[System_ROM] ; Get pointer to system ROM file name
int DOS ; Try to open the system ROM file
jnc Read_System_ROM ; Jump if no errors opening file
mov al,ERR_NO_SYSTEM_FILE ; Get no system ROM file error code
System_ROM_Error:
call Error ; Call routine to print the error
call Exit ; Call routine to exit emulator
Read_System_ROM:
mov ds,bx ; Restore 65C02 RAM space segment value
mov bx,ax ; Move file handle to BX register
mov ah,READ_FILE ; Get read file function code
mov dx,SYSTEM_ADDRESS ; Setup the data buffer address
mov cx,SYSTEM_SIZE ; Get the system ROM image size (12k)
int DOS ; Try to read the system ROM image
mov cx,ax ; Save ROM image size in CX register
mov al,ERR_BAD_SYSTEM_FILE ; Get bad system ROM file error code
jc System_ROM_Error ; Jump if error trying to read the file
cmp cx,SYSTEM_SIZE ; Check for all of image read in
mov al,ERR_BAD_SYSTEM_IMAGE ; Get bad system ROM image error code
jne System_ROM_Error ; Jump if part of image missing
mov ah,CLOSE_FILE ; Get close file function code
int DOS ; Close the system ROM file
ret ; Return to the caller
Load_System Endp ; End of the Load_System procedure
Subttl CPU_Init Initialize the 65C02 CPU Registers
Page +
;******************************************************************************
;
; CPU_Init()
;
; Initialize the accumulator register (0h)
; Initialize the X index register (0h)
; Initialize the Y index register (0h)
; Initialize the stack pointer register (1FFh)
; Initialize the program counter register (FFFCh)
; Initialize the 65C02 processor status register (0h)
; Return to the caller
;
; Registers on Entry:
;
; DS - 65C02 RAM space
;
; Registers on Exit:
;
; DL - Accumulator initialized (0h)
; DH - 65C02 flags initialized (0h)
; CL - Y index register initialized (0h)
; CH - X index register initialized (0h)
; BX - Stack pointer initialized (1FFh)
; SI - PC initialized (Reset Vector)
;
;******************************************************************************
Even ; Force procedure to even address
CPU_Init Proc Near ; Initialize CPU registers procedure
xor dl,dl ; Initialize the accumualtor register
xor ch,ch ; Initialize the X index register
xor cl,cl ; Initialize the Y index register
mov bx,STACK_TOP ; Initialize the stack pointer
mov si,ds:[RST_VECTOR] ; Initialize the program counter
xor dh,dh ; Initialize 65C02 processor flags
ret ; Return to the caller
CPU_Init Endp ; End of the CPU_Init procedure
Subttl Error Emulator Error Routine
Page +
;******************************************************************************
;
; Error(Error_Code)
;
; Save the required registers
; Print the correct error message
; Restore the required registers
; Return to the caller
;
; Registers on Entry:
;
; AL - Error code
;
; Registers on Exit:
;
; AX-DX - Destroyed
;
;******************************************************************************
Even ; Force procedure to even address
Error Proc Near ; Emulator error procedure
Save ds ; Save the required registers
xor ah,ah ; Convert error code to full word
shl ax,1 ; Convert error code to table index
mov bx,ax ; Move table index into BX register
mov si,cs:[bx+Error_Table] ; Get the error string address
mov ax,cs ; Get current CS register value
mov ds,ax ; Setup to access the error string
mov ah,WRITE_FILE ; Get write file function code
mov bx,STD_ERROR ; Get the standard error handle
lodsb ; Get the length of the error string
mov cl,al ; Move string length into CL register
xor ch,ch ; Convert string length into full word
mov dx,si ; Setup error string address
int DOS ; Print the error string to handle
Restore ds ; Restore the required registers
ret ; Return to the caller
Error Endp ; End of the Error procedure
Subttl Exit Emulator Exit Routine
Page +
;******************************************************************************
;
; Exit()
;
; Call routine to reset interrupt vectors
; Call routine to reset video
; Call routine to reset keyboard
; Zero the return code
; Exit to DOS
;
; Registers on Entry:
;
; None
;
; Registers on Exit:
;
; None
;
;******************************************************************************
Even ; Force procedure to even address
Exit Proc Near ; Emulator exit procedure
call Int_Reset ; Call the interrupt reset routine
call Video_Reset ; Call the video reset routine
call Key_Reset ; Call the keyboard reset routine
mov ah,TERMINATE ; Get the terminate function code
xor al,al ; Zero the return code
int DOS ; Return control to MS-DOS
ret ; Return to the caller (Never executed)
Exit Endp ; End of the Exit procedure
Subttl Read_Memory Read 65C02 Apple Memory Routine
Page +
;******************************************************************************
;
; Read_Memory(Effective_Address)
;
; Get the memory page from effective address
; Jump to correct routine to process read
;
; Registers on Entry:
;
; DS:DI - 65C02 Effective address
;
; Registers on Exit:
;
; AL - 65C02 Memory value
; BP - Destroyed
;
;******************************************************************************
Even ; Force procedure to even address
Read_Memory Proc Near ; Read 65C02 Apple memory procedure
mov bp,di ; Get the effective address
shr bp,8 ; Get page number into BP register
shl bp,1 ; Convert page number to table index
jmp cs:[bp + Read_Table] ; Jump to correct routine to read
ret ; Return to the caller (Never executed)
Read_Memory Endp ; End of the Read_Memory procedure
Subttl Write_Memory Write 65C02 Apple Memory Routine
Page +
;******************************************************************************
;
; Write_Memory(Effective_Address, Data_Value)
;
; Get the memory page from effective address
; Jump to correct routine to process write
;
; Registers on Entry:
;
; DS:DI - 65C02 Effective address
; AL - 65C02 Memory value
;
; Registers on Exit:
;
; AX - Destroyed
; DI - Destroyed
; BP - Destroyed
;
;******************************************************************************
Even ; Force procedure to even address
Write_Memory Proc Near ; Write 65C02 Apple memory procedure
mov bp,ax ; Save memory value in BP register
mov ax,di ; Get the effective address
shr ax,8 ; Get page number into AX register
shl ax,1 ; Convert page number to table index
xchg bp,ax ; Setup to jump to correct routine
jmp cs:[bp + Write_Table] ; Jump to correct routine to write
ret ; Return to the caller (Never executed)
Write_Memory Endp ; End of the Write_Memory procedure
Subttl System_Reset Apple System Reset Routine
Page +
;******************************************************************************
;
; System_Reset(Scan_Code)
;
; If the last scan code does NOT match (NOT a repeat)
; If this is a make code
; Set system reset interrupt type
; Endif this is a break code
; Endif this key is repeating
; Return control to the caller
;
; Registers on Entry:
;
; None
;
; Registers on Exit:
;
; None
;
;******************************************************************************
Even ; Force procedure to even address
System_Reset Proc Near ; Apple system reset procedure
cmp ah,cs:[Last_Key] ; Check for a repeat scan code
je Reset_Done ; Jump if this key is repeating
or ah,ah ; Check for a make or break code
js Reset_Done ; Jump if this is a break code
or cs:[Emulate_Flag],SYS_RESET
Reset_Done:
ret ; Return to the caller
System_Reset Endp ; End of the System_Reset procedure
Subttl System_Request Emulator System Request Routine
Page +
;******************************************************************************
;
; System_Request()
;
; If this is a make code
; Set system request interrupt type
; Endif this is a break code
; Return control to the caller
;
; Registers on Entry:
;
; None
;
; Registers on Exit:
;
; None
;
;******************************************************************************
Even ; Force procedure to even address
System_Request Proc Near ; Emulator system request procedure
or ah,ah ; Check for a make or break code
js Request_Done ; Jump if this is a break code
test cs:[Emulate_Flag],SYS_REQUEST
jnz Request_Done ; Jump if already in system procedure
or cs:[Emulate_Flag],SYS_REQUEST
Request_Done:
ret ; Return to the caller
System_Request Endp ; End of the System_Request procedure
Subttl Reset_System Reset System Routine
Page +
;******************************************************************************
;
; Reset_System(Interrupt_Number, RAM_Space, Registers, Address)
;
; Clear the system reset interrupt bit
; Call routine to reset the processor registers
; Setup to execute the next opcode (No interrupt check)
; Go process the next opcode
;
; Registers on Entry:
;
; DL - 65C02 Accumulator
; DH - 65C02 processor flags
; CL - 65C02 Y index register
; CH - 65C02 X index register
; BX - 65C02 Stack pointer
; SI - 65C02 Program counter
; AX - Interrupt number (Doubled)
; DI - Current opcode address
; DS - 65C02 RAM space
;
; Registers on Exit:
;
; DL - Accumulator initialized (0h)
; DH - 65C02 flags initialized (0h)
; CL - Y index register initialized (0h)
; CH - X index register initialized (0h)
; BX - Stack pointer initialized (1FFh)
; SI - Program counter initialized (FFFCh)
; DI - Set to new opcode address
;
;******************************************************************************
Even ; Force procedure to even address
Reset_System Proc Near ; Reset system procedure
and cs:[Emulate_Flag],Not SYS_RESET
call CPU_Init ; Call routine to initialize registers
Setup ; Setup the new opcode address
jmp di ; Go process the new opcode
Reset_System Endp ; End of the Reset_System procedure
Subttl Request_System Request System Routine
Page +
;******************************************************************************
;
; Request_System(Interrupt_Number, RAM_Space, Registers, Address)
;
;
;
; Registers on Entry:
;
; DL - 65C02 Accumulator
; DH - 65C02 processor flags
; CL - 65C02 Y index register
; CH - 65C02 X index register
; BX - 65C02 Stack pointer
; SI - 65C02 Program counter
; AX - Interrupt number (Doubled)
; DI - Current opcode address
; DS - 65C02 RAM space
;
; Registers on Exit:
;
; None
;
;******************************************************************************
Even ; Force procedure to even address
Request_System Proc Near ; Request system procedure
or cs:[System_Flag],INPUT ; Put keyboard into input mode
call Flush_Keyboard ; Call routine to flush the keyboard
call TTY_Init ; Call routine to initialize TTY console
call Clear_Screen ; Call routine to clear the screen
Request_Exit:
and cs:[System_Flag],Not INPUT
and cs:[Emulate_Flag],Not SYS_REQUEST
call Exit ; Call routine to exit the emulator
ret ; Return control to the caller
Request_System Endp ; End of the Request_System procedure
;******************************************************************************
;
; Define the end of the Emulator Code Segment
;
;******************************************************************************
Emulate Ends
End ; End of the Apple module
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/