- 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:
Simon Owen 2008-09-05 10:58:10 +00:00
parent 64db2eff61
commit c571f7dd59
4 changed files with 85 additions and 44 deletions

View File

@ -1,6 +1,6 @@
; 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/
@ -21,8 +21,6 @@ low_page: equ 3 ; LMPR during emulation
screen_page: equ 5 ; SAM display
file_page: equ 6 ; File import text page
bord_invalid: equ 2 ; Invalid instruction (red)
m6502_nmi: equ &fffa ; nmi vector address
m6502_reset: equ &fffc ; reset vector address
m6502_int: equ &fffe ; int vector address (also for BRK)
@ -139,19 +137,16 @@ back_chr: ld a,l
jr no_wrap
; Map display character from SAM to Apple 1
map_chr: cp &20
jr c,invalid_chr
and %10111111
xor %01100000
ret
invalid_chr: xor a
map_chr: sub &20
ret nc
xor a
ret
; Display character in A at current cursor position
display_chr: add a,a ; * 2
add a,a ; * 4
ld l,a
ld h,0
add hl,hl ; * 4
add hl,hl ; * 8
ld de,font_data
add hl,de
@ -359,7 +354,7 @@ no_key:
call display_chr ; show it
pop af
done_draw2: call advance_chr ; advance the cursor position
ld a,&3f ; cursor block
ld a,&5f ; cursor block
call display_chr ; show cursor
done_draw:
no_char:
@ -442,16 +437,13 @@ execute: ld a,&1a ; LD A,(DE)
i_undoc_3: inc de ; 3-byte NOP
i_undoc_2: inc de ; 2-byte NOP
i_undoc_1:
; ld a,bord_invalid
; out (border),a
jp (ix)
i_undoc_1: jp (ix) ; NOP
read_write_loop:
write_loop: ld a,h
cp &d0 ; I/O area?
jr z,write_trap
cp base/256 ; emulator or ROMs above?
jr nc,write_trap
zwrite_loop:
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!
; = 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?
jr z,chr_write
jp (ix)
chr_write: set 7,(hl) ; display busy
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
cp &d0
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
; !"#$%&1()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]`abcdefghijklmnopqrstuvwxyz{|}~
font_data:
MDAT "font.bin"
MDAT "font.bin"
mask_data: defb %00000011,%11111111
defb %11000000,%11111111
@ -613,18 +612,47 @@ length: equ end-start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Instruction implementations
INC "opimpl.inc"
; Instruction implementations
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
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
dump &ff00
MDAT "apple1.rom"
; Test program to output the character set (5000-500B)
; LDX $00 ; loop: TXA ; JSR echo ; INX ; BRA loop
dump low_page,&5000
defb &a2, &00, &8a, &20, &ef, &ff, &e8, &80, &f9

View File

@ -1,6 +1,6 @@
; Opcode table positions (auto-generated by opdefs.pl)
op_00: equ &b000 ; +38
op_00: equ &b000 ; +42
op_01: equ &b401 ; +18
op_02: equ &ba02 ; +3
op_03: equ &b103 ; +3

View File

@ -2,12 +2,15 @@
#
# 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/
$source = 'apple1emu.asm';
$codeend = 0xc000;
# 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
my $outfile = 'opdefs.inc';
@ -19,9 +22,10 @@ if ($?)
{
# Create dummy offset list to allow lengths to be calculated
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;
}
@ -68,8 +72,8 @@ MSB:
}
}
# Position base so code finishes just before &c000
$base = 0xc000 - (($size + 0xff) & ~0xff);
# Position base so code finishes at the required point
$base = $codeend - (($size + 0xff) & ~0xff);
print "Size = $size, used = $used, slack = ", $size-$used, "\n";

View File

@ -1,10 +1,20 @@
; 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"
org op_00
dump $
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
exx
ld (hl),a ; push return PCH
@ -14,22 +24,21 @@ i_brk: inc de ; return to BRK+2
exx
ld (hl),a ; push return PCL
dec l ; S--
ex af,af' ; carry
inc c
dec c ; set N Z
push af ; save flags
ex af,af' ; save carry
pop bc
pop bc ; Z80 flags in C
ld a,c
and %10000001 ; keep N and C
bit 6,c ; check Z
and %10000001 ; keep Z80 N and C
bit 6,c ; check Z80 Z
jr z,brk_nz
or %00000010 ; set Z
brk_nz: or e ; merge V
or d ; merge T D I
or %00010000 ; set B
or d ; merge T B D I
or %00010000 ; set B (stack value only)
ld (hl),a ; push P
dec l ; S--
res 3,d ; clear D [65C02]
set 2,d ; set I (disable interrupts)
exx
ld de,(m6502_int) ; fetch interrupt handler
jp (ix) ; main_loop