mirror of
https://github.com/simonowen/apple1emu.git
synced 2024-05-31 12:41:31 +00:00
- Fixed BRK flags (clear D, set I, N/Z set from wrong EXX set)
- Added Applesoft BASIC [Lite] and Lee Davidson's Enhanced BASIC - First byte of emulator at &9000 appears to be ROM (for Applesoft BASIC) - Terminal output now supports lower-case characters (for Enhanced BASIC) - Updated Ken Wessen's BASIC+Krusader assembler to v1.3
This commit is contained in:
parent
64db2eff61
commit
c571f7dd59
|
@ -1,6 +1,6 @@
|
||||||
; Apple 1 emulator for SAM Coupe, by Simon Owen
|
; Apple 1 emulator for SAM Coupe, by Simon Owen
|
||||||
;
|
;
|
||||||
; Version 1.1 (27/8/2008)
|
; Version 1.2 (5/9/2008)
|
||||||
;
|
;
|
||||||
; WWW: http://simonowen.com/sam/apple1emu/
|
; WWW: http://simonowen.com/sam/apple1emu/
|
||||||
|
|
||||||
|
@ -21,8 +21,6 @@ low_page: equ 3 ; LMPR during emulation
|
||||||
screen_page: equ 5 ; SAM display
|
screen_page: equ 5 ; SAM display
|
||||||
file_page: equ 6 ; File import text page
|
file_page: equ 6 ; File import text page
|
||||||
|
|
||||||
bord_invalid: equ 2 ; Invalid instruction (red)
|
|
||||||
|
|
||||||
m6502_nmi: equ &fffa ; nmi vector address
|
m6502_nmi: equ &fffa ; nmi vector address
|
||||||
m6502_reset: equ &fffc ; reset vector address
|
m6502_reset: equ &fffc ; reset vector address
|
||||||
m6502_int: equ &fffe ; int vector address (also for BRK)
|
m6502_int: equ &fffe ; int vector address (also for BRK)
|
||||||
|
@ -139,19 +137,16 @@ back_chr: ld a,l
|
||||||
jr no_wrap
|
jr no_wrap
|
||||||
|
|
||||||
; Map display character from SAM to Apple 1
|
; Map display character from SAM to Apple 1
|
||||||
map_chr: cp &20
|
map_chr: sub &20
|
||||||
jr c,invalid_chr
|
ret nc
|
||||||
and %10111111
|
xor a
|
||||||
xor %01100000
|
|
||||||
ret
|
|
||||||
invalid_chr: xor a
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Display character in A at current cursor position
|
; Display character in A at current cursor position
|
||||||
display_chr: add a,a ; * 2
|
display_chr: add a,a ; * 2
|
||||||
add a,a ; * 4
|
|
||||||
ld l,a
|
ld l,a
|
||||||
ld h,0
|
ld h,0
|
||||||
|
add hl,hl ; * 4
|
||||||
add hl,hl ; * 8
|
add hl,hl ; * 8
|
||||||
ld de,font_data
|
ld de,font_data
|
||||||
add hl,de
|
add hl,de
|
||||||
|
@ -359,7 +354,7 @@ no_key:
|
||||||
call display_chr ; show it
|
call display_chr ; show it
|
||||||
pop af
|
pop af
|
||||||
done_draw2: call advance_chr ; advance the cursor position
|
done_draw2: call advance_chr ; advance the cursor position
|
||||||
ld a,&3f ; cursor block
|
ld a,&5f ; cursor block
|
||||||
call display_chr ; show cursor
|
call display_chr ; show cursor
|
||||||
done_draw:
|
done_draw:
|
||||||
no_char:
|
no_char:
|
||||||
|
@ -442,16 +437,13 @@ execute: ld a,&1a ; LD A,(DE)
|
||||||
|
|
||||||
i_undoc_3: inc de ; 3-byte NOP
|
i_undoc_3: inc de ; 3-byte NOP
|
||||||
i_undoc_2: inc de ; 2-byte NOP
|
i_undoc_2: inc de ; 2-byte NOP
|
||||||
i_undoc_1:
|
i_undoc_1: jp (ix) ; NOP
|
||||||
; ld a,bord_invalid
|
|
||||||
; out (border),a
|
|
||||||
jp (ix)
|
|
||||||
|
|
||||||
|
|
||||||
read_write_loop:
|
read_write_loop:
|
||||||
write_loop: ld a,h
|
write_loop: ld a,h
|
||||||
cp &d0 ; I/O area?
|
cp base/256 ; emulator or ROMs above?
|
||||||
jr z,write_trap
|
jr nc,write_trap
|
||||||
|
|
||||||
zwrite_loop:
|
zwrite_loop:
|
||||||
main_loop: ld a,(de) ; 7/7/15 - fetch opcode
|
main_loop: ld a,(de) ; 7/7/15 - fetch opcode
|
||||||
|
@ -462,13 +454,19 @@ main_loop: ld a,(de) ; 7/7/15 - fetch opcode
|
||||||
jp (hl) ; 4/5/9 - execute!
|
jp (hl) ; 4/5/9 - execute!
|
||||||
; = 35T (official) / 40T (off-screen) / 72T (on-screen)
|
; = 35T (official) / 40T (off-screen) / 72T (on-screen)
|
||||||
|
|
||||||
write_trap: ld a,l
|
write_trap: cp &d0
|
||||||
|
jr nz,write_rom
|
||||||
|
ld a,l
|
||||||
cp &12 ; display char?
|
cp &12 ; display char?
|
||||||
jr z,chr_write
|
jr z,chr_write
|
||||||
jp (ix)
|
jp (ix)
|
||||||
chr_write: set 7,(hl) ; display busy
|
chr_write: set 7,(hl) ; display busy
|
||||||
jp (ix)
|
jp (ix)
|
||||||
|
|
||||||
|
write_rom: ld a,&f3 ; Z80 DI opcode
|
||||||
|
ld (base),a ; emulator appears to be in ROM for RAM tests
|
||||||
|
jp (ix)
|
||||||
|
|
||||||
read_loop: ld a,h
|
read_loop: ld a,h
|
||||||
cp &d0
|
cp &d0
|
||||||
jr z,read_trap
|
jr z,read_trap
|
||||||
|
@ -598,8 +596,9 @@ msb_table: defb op_00>>8, op_01>>8, op_02>>8, op_03>>8, op_04>>8, op_05>>8,
|
||||||
|
|
||||||
defs -$\256 ; align to 256-byte boundary
|
defs -$\256 ; align to 256-byte boundary
|
||||||
|
|
||||||
|
; !"#$%&1()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]`abcdefghijklmnopqrstuvwxyz{|}~
|
||||||
font_data:
|
font_data:
|
||||||
MDAT "font.bin"
|
MDAT "font.bin"
|
||||||
|
|
||||||
mask_data: defb %00000011,%11111111
|
mask_data: defb %00000011,%11111111
|
||||||
defb %11000000,%11111111
|
defb %11000000,%11111111
|
||||||
|
@ -613,18 +612,47 @@ length: equ end-start
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
; Instruction implementations
|
; Instruction implementations
|
||||||
INC "opimpl.inc"
|
INC "opimpl.inc"
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
; Woz Monitor ROM (&ff00-&ffff)
|
||||||
|
; May be overwritten by includes below
|
||||||
|
dump &ff00
|
||||||
|
MDAT "apple1.rom"
|
||||||
|
|
||||||
; Ken Wessen's custom BASIC+Krusader+Monitor ROM (&e000-&ffff)
|
|
||||||
; BRK handler points to mini-monitor in this version
|
; Use RAM-based Applesoft BASIC by default
|
||||||
|
IF 1
|
||||||
|
; Applesoft BASIC [Lite] (6000-7FFF)
|
||||||
|
; http://cowgod.org/replica1/applesoft/
|
||||||
|
dump low_page,&6000
|
||||||
|
MDAT "applesoft-lite-0.4-ram.bin"
|
||||||
|
ELSE
|
||||||
|
; Lee Davidson's Enhanced BASIC (5800-77CE)
|
||||||
|
; http://members.lycos.co.uk/leeedavison/6502/ehbasic/
|
||||||
|
dump low_page,&5800
|
||||||
|
MDAT "ehbasic.bin"
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
|
||||||
|
; Use Ken Wessen's BASIC+assembler by default
|
||||||
|
IF 1
|
||||||
|
; Ken Wessen's custom BASIC + Krusader assembler + enhanced monitor (E000-FFFF)
|
||||||
|
; BRK handler points to mini-monitor in this version
|
||||||
|
; http://school.anhb.uwa.edu.au/personalpages/kwessen/apple1/Krusader.htm
|
||||||
dump &e000
|
dump &e000
|
||||||
MDAT "65C02.rom.bin"
|
MDAT "65C02.rom.bin"
|
||||||
|
ELSE
|
||||||
|
; Applesoft BASIC [Lite] + Woz monitor (E000-FFFF)
|
||||||
|
; http://cowgod.org/replica1/applesoft/
|
||||||
|
dump &e000
|
||||||
|
MDAT "applesoft-lite-0.4.bin"
|
||||||
|
ENDIF
|
||||||
|
|
||||||
; Original Monitor ROM (&ff00-&ffff)
|
|
||||||
; If uncommented, this will replace the monitor ROM section from above
|
; Test program to output the character set (5000-500B)
|
||||||
dump &ff00
|
; LDX $00 ; loop: TXA ; JSR echo ; INX ; BRA loop
|
||||||
MDAT "apple1.rom"
|
dump low_page,&5000
|
||||||
|
defb &a2, &00, &8a, &20, &ef, &ff, &e8, &80, &f9
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
; Opcode table positions (auto-generated by opdefs.pl)
|
; Opcode table positions (auto-generated by opdefs.pl)
|
||||||
|
|
||||||
op_00: equ &b000 ; +38
|
op_00: equ &b000 ; +42
|
||||||
op_01: equ &b401 ; +18
|
op_01: equ &b401 ; +18
|
||||||
op_02: equ &ba02 ; +3
|
op_02: equ &ba02 ; +3
|
||||||
op_03: equ &b103 ; +3
|
op_03: equ &b103 ; +3
|
||||||
|
|
14
opdefs.pl
14
opdefs.pl
|
@ -2,12 +2,15 @@
|
||||||
#
|
#
|
||||||
# Calculates opcode addresses for the inline instruction decoding table
|
# Calculates opcode addresses for the inline instruction decoding table
|
||||||
#
|
#
|
||||||
# Used by the VIC-20 emulator, available from:
|
# Used by the Apple 1 emulator, available from:
|
||||||
#
|
#
|
||||||
# http://simonowen.com/sam/apple1emu/
|
# http://simonowen.com/sam/apple1emu/
|
||||||
|
|
||||||
|
$source = 'apple1emu.asm';
|
||||||
|
$codeend = 0xc000;
|
||||||
|
|
||||||
# Assemble, outputting the symbols containing opcode implementation lengths
|
# Assemble, outputting the symbols containing opcode implementation lengths
|
||||||
$_ = `pyz80.py -s op_.*_len apple1emu.asm`;
|
$_ = `pyz80.py -s op_.*_len $source`;
|
||||||
|
|
||||||
# Create include file for definitions
|
# Create include file for definitions
|
||||||
my $outfile = 'opdefs.inc';
|
my $outfile = 'opdefs.inc';
|
||||||
|
@ -19,9 +22,10 @@ if ($?)
|
||||||
{
|
{
|
||||||
# Create dummy offset list to allow lengths to be calculated
|
# Create dummy offset list to allow lengths to be calculated
|
||||||
for (0..255) {
|
for (0..255) {
|
||||||
printf FILE "op_%02x: equ &b000\n", $_;
|
printf FILE "op_%02x: equ &%04x\n", $_, $codeend-0x1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print "Assembly error, creating dummy definitions!\n";
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,8 +72,8 @@ MSB:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Position base so code finishes just before &c000
|
# Position base so code finishes at the required point
|
||||||
$base = 0xc000 - (($size + 0xff) & ~0xff);
|
$base = $codeend - (($size + 0xff) & ~0xff);
|
||||||
|
|
||||||
print "Size = $size, used = $used, slack = ", $size-$used, "\n";
|
print "Size = $size, used = $used, slack = ", $size-$used, "\n";
|
||||||
|
|
||||||
|
|
29
opimpl.inc
29
opimpl.inc
|
@ -1,10 +1,20 @@
|
||||||
; 65C02 instruction implementations
|
; 65C02 instruction implementations
|
||||||
|
;
|
||||||
|
; NOTE: If you change this file, opdefs.inc must be rebuilt by running
|
||||||
|
; opdefs.pl (requires the pyz80 assembler)
|
||||||
|
|
||||||
INC "opdefs.inc"
|
INC "opdefs.inc"
|
||||||
|
|
||||||
org op_00
|
org op_00
|
||||||
dump $
|
dump $
|
||||||
i_brk: inc de ; return to BRK+2
|
i_brk: inc de ; return to BRK+2
|
||||||
|
|
||||||
|
ex af,af' ; get C
|
||||||
|
inc c
|
||||||
|
dec c ; set N Z
|
||||||
|
push af ; save flags for below
|
||||||
|
ex af,af' ; save C
|
||||||
|
|
||||||
ld a,d ; PCH
|
ld a,d ; PCH
|
||||||
exx
|
exx
|
||||||
ld (hl),a ; push return PCH
|
ld (hl),a ; push return PCH
|
||||||
|
@ -14,22 +24,21 @@ i_brk: inc de ; return to BRK+2
|
||||||
exx
|
exx
|
||||||
ld (hl),a ; push return PCL
|
ld (hl),a ; push return PCL
|
||||||
dec l ; S--
|
dec l ; S--
|
||||||
ex af,af' ; carry
|
|
||||||
inc c
|
pop bc ; Z80 flags in C
|
||||||
dec c ; set N Z
|
|
||||||
push af ; save flags
|
|
||||||
ex af,af' ; save carry
|
|
||||||
pop bc
|
|
||||||
ld a,c
|
ld a,c
|
||||||
and %10000001 ; keep N and C
|
and %10000001 ; keep Z80 N and C
|
||||||
bit 6,c ; check Z
|
bit 6,c ; check Z80 Z
|
||||||
jr z,brk_nz
|
jr z,brk_nz
|
||||||
or %00000010 ; set Z
|
or %00000010 ; set Z
|
||||||
brk_nz: or e ; merge V
|
brk_nz: or e ; merge V
|
||||||
or d ; merge T D I
|
or d ; merge T B D I
|
||||||
or %00010000 ; set B
|
or %00010000 ; set B (stack value only)
|
||||||
ld (hl),a ; push P
|
ld (hl),a ; push P
|
||||||
dec l ; S--
|
dec l ; S--
|
||||||
|
|
||||||
|
res 3,d ; clear D [65C02]
|
||||||
|
set 2,d ; set I (disable interrupts)
|
||||||
exx
|
exx
|
||||||
ld de,(m6502_int) ; fetch interrupt handler
|
ld de,(m6502_int) ; fetch interrupt handler
|
||||||
jp (ix) ; main_loop
|
jp (ix) ; main_loop
|
||||||
|
|
Loading…
Reference in New Issue
Block a user