diff --git a/apple1emu.asm b/apple1emu.asm index 7df2622..43dda9d 100644 --- a/apple1emu.asm +++ b/apple1emu.asm @@ -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 diff --git a/opdefs.inc b/opdefs.inc index 7022dcb..ac5580c 100644 --- a/opdefs.inc +++ b/opdefs.inc @@ -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 diff --git a/opdefs.pl b/opdefs.pl index cf30f30..12509b6 100644 --- a/opdefs.pl +++ b/opdefs.pl @@ -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"; diff --git a/opimpl.inc b/opimpl.inc index fc7a6e3..041e592 100644 --- a/opimpl.inc +++ b/opimpl.inc @@ -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