From 43e1495d761f0278e52d05ea62bbae08a810b6a6 Mon Sep 17 00:00:00 2001 From: Simon Owen Date: Mon, 2 Apr 2007 13:21:49 +0000 Subject: [PATCH] apple1emu v1.0 --- 65C02.rom.bin | Bin 0 -> 8192 bytes ReadMe.txt | 32 + apple1.rom | Bin 0 -> 256 bytes apple1emu-master.dsk | Bin 0 -> 17152 bytes apple1emu.asm | 2104 ++++++++++++++++++++++++++++++++++++++++++ apple1emu.dsk | Bin 0 -> 17696 bytes font.bin | Bin 0 -> 512 bytes m.bat | 2 + samdos2 | Bin 0 -> 10000 bytes 9 files changed, 2138 insertions(+) create mode 100644 65C02.rom.bin create mode 100644 ReadMe.txt create mode 100644 apple1.rom create mode 100644 apple1emu-master.dsk create mode 100644 apple1emu.asm create mode 100644 apple1emu.dsk create mode 100644 font.bin create mode 100644 m.bat create mode 100644 samdos2 diff --git a/65C02.rom.bin b/65C02.rom.bin new file mode 100644 index 0000000000000000000000000000000000000000..407d9b73b72713797ba5d23cde9a29e7e79f5d57 GIT binary patch literal 8192 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 +http://simonowen.com/sam/apple1emu/ diff --git a/apple1.rom b/apple1.rom new file mode 100644 index 0000000000000000000000000000000000000000..7280907226f38c9243aa42bcba245bf5824b764e GIT binary patch literal 256 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 literal 0 HcmV?d00001 diff --git a/apple1emu.asm b/apple1emu.asm new file mode 100644 index 0000000..ea7bb05 --- /dev/null +++ b/apple1emu.asm @@ -0,0 +1,2104 @@ +; Apple 1 emulator for SAM Coupe, by Simon Owen (v1.0) +; +; WWW: http://simonowen.com/sam/apple1emu/ + +base: equ &b000 ; Spare-ish Apple 1 space + +status: equ 249 ; Status and extended keyboard port +lmpr: equ 250 ; Low Memory Page Register +hmpr: equ 251 ; High Memory Page Register +vmpr: equ 252 ; Video Memory Page Register +keyboard: equ 254 ; Keyboard port +border: equ 254 ; Border port +rom0_off: equ %00100000 ; LMPR bit to disable ROM0 +rom1_on: equ %01000000 ; LMPR bit to enable ROM1 +vmpr_mode2: equ %00100000 ; Mode 2 select for VMPR + +low_page: equ 3 ; LMPR during emulation +screen_page: equ 5 ; SAM display +file_page: equ 6 ; File import text page + +bord_stp: equ 2 ; STP instruction halted CPU (red) +bord_wai: equ 6 ; WAI instruction waiting for interrupt (yellow) + +m6502_nmi: equ &fffa ; nmi vector address +m6502_reset: equ &fffc ; reset vector address +m6502_int: equ &fffe ; int vector address (also for BRK) + +getkey: equ &1cab ; SAM ROM key reading (NZ=got key in A, A=0 for no key) + + +; Apple 1 keyboard and display I/O locations + +kbd_data: equ &d010 ; keyboard data +kbd_ctrl: equ &d011 ; keyboard control +dsp_data: equ &d012 ; display data +dsp_ctrl: equ &d013 ; display control + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + org base + dump $ + autoexec + +start: di + + ld a,low_page+rom0_off + out (lmpr),a + ld a,vmpr_mode2+screen_page + out (vmpr),a + ld sp,stack_top + + call reorder_decode ; optimise instruction decode table + call set_sam_attrs ; set the mode 2 attrs so the screen is visible + call setup_im2 ; enable IM 2 + +reset_loop: ld hl,0 + ld (dsp_data),hl ; display ready + ld (kbd_ctrl),hl ; no key available + + ld hl,(m6502_reset) ; start from reset vector + ld (reg_pc),hl + + ei + call execute ; GO! + jr reset_loop + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Utility functions + +; Fill SAM mode 2 display attributes to make the screen visible +set_sam_attrs: ld a,screen_page+rom0_off + out (lmpr),a + + ld hl,&2000 + ld bc,&1844 ; 24 blocks of bright green on black +clear_lp: ld (hl),c + inc l + jr nz,clear_lp + inc h + djnz clear_lp + + ld a,low_page+rom0_off + out (lmpr),a + ret + +; Scroll the screen up 1 row and clear the bottom line +scroll_screen: ld hl,0 + ld d,h + ld e,l + inc h + ld bc,&1700 +scroll_lp: FOR 32, ldi ; 32 * LDI + jp pe,scroll_lp + dec h +scroll_clr: ld (hl),0 + inc l + jp nz,scroll_clr + ret + +; Advance the cursor 1 character, wrapping and scrolling if necessary +advance_chr: ld hl,(cursor_xy) + cp &5f + jr z,back_chr + cp &0a + jr z,advance_line + cp &0d + jr z,advance_line + ld a,l + add a,6 + ld l,a + cp &f0 + jr c,no_wrap +advance_line: ld l,0 + inc h + ld a,h + cp &18 + jr nz,no_wrap + dec h + exx + call scroll_screen + exx +no_wrap: ld (cursor_xy),hl + ret +back_chr: ld a,l + sub 6 + ld l,a + jr nc,no_wrap + ld l,39*6 + ld a,h + sub 1 + adc a,0 + ld h,a + 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 + 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 ; * 8 + ld de,font_data + add hl,de + ld d,mask_data/256 + exx + ld hl,(cursor_xy) + ld a,l + and %00000111 + srl l + srl l + srl l + inc l + exx + ld e,a + exx + ld de,&0020 + ld b,8 +draw_lp: exx + ld c,(hl) + inc l + xor a + cp e + jr z,no_rot + ld b,e +rot_lp: srl c + rra + djnz rot_lp +no_rot: ld b,a + ld a,(de) + inc e + exx + and (hl) + inc l + exx + or c + ex af,af' + ld a,(de) + dec e + exx + and (hl) + exx + or b + exx + ld (hl),a + dec l + ex af,af' + ld (hl),a + add hl,de + djnz draw_lp + ret + +; LSB=pixel position (0-240), MSB=display row (0-23) +cursor_xy: defw 0 + +; Map key symbols from SAM to Apple 1 +map_key: cp &0c + jr z,del_key + cp &fc + jr z,tab_key + cp &80 + jr nc,ignore_key + cp &61 ; 'a' + ret c + cp &7b ; 'z'+1 + ret nc + and %11011111 + ret +del_key: ld a,&5f ; Delete -> _ + ret +tab_key: ld a,&09 ; standard tab + ret +invalid_key: ld a,&20 ; space for invalid + ret +ignore_key: xor a ; ignore + ret + +; Get a type-in key from the imported file +get_filekey: ld a,file_page+rom0_off + out (lmpr),a + + ld hl,(filepos) + ld a,h + or l + or (hl) + jr z,file_done ; jump if no file + +file_skip: ld a,(hl) ; fetch next file character + inc hl + and a + jr z,clear_file2 ; clear file at end + cp &0d ; CR? + jr z,file_skip ; ignore CR in file + cp &0a ; LF? + jr nz,file_done + ld a,&0d ; convert LF to CR +file_done: ld (filepos),hl + ex af,af' + ld a,screen_page+rom0_off + out (lmpr),a + ex af,af' + and a + ret +filepos: defw 0 + +; Clear the file area to disable type-in +clear_file: ld a,file_page+rom0_off + out (lmpr),a +clear_file2: ld hl,0 + ld c,l +clr_file_lp: ld (hl),c + inc l + jr nz,clr_file_lp + inc h + bit 7,h + jr nz,clr_file_lp + ld h,l + xor a ; no file character + jr file_done + +update_io: + ld a,&f7 + in a,(status) + and %00100000 + jr nz,not_esc ; jump if Esc not pressed +still_esc: ld a,&f7 + in a,(status) + and %00100000 + jr z,still_esc ; wait until Esc released + + call clear_file ; Esc cancels type-in mode + + ld a,&fe + in a,(keyboard) + rra + ld a,&1b ; Esc character + jr c,got_key ; unshifted gives chr + + ld a,&c9 ; RET + ld (main_loop),a ; exit to reset at next instruction + jr no_key +not_esc: + ld a,&7f + in a,(keyboard) + bit 1,a + jr nz,not_sym + + ld a,&f7 + in a,(keyboard) + rra + ld c,&ff ; line interrupt disable + jr nc,got_line + rra + ld c,88 ; centre of display (312/2-68=88) + jr c,not_sym +got_line: ld a,c + out (status),a ; set or disable line interrupt +not_sym: + ld hl,kbd_ctrl + bit 7,(hl) ; key available? + jr nz,no_key ; no need to read more yet + + call get_filekey ; got a type-in key from file? + jr nz,got_key ; jump if we have + +skip_key: ld a,&1f+rom1_on + out (lmpr),a + call getkey + ex af,af' + ld a,screen_page+rom0_off + out (lmpr),a + ex af,af' + jr z,no_key + call map_key + and a + jr z,skip_key +got_key: + ld hl,kbd_data + ld (hl),a + set 7,(hl) ; bit 7 always set + inc l + set 7,(hl) ; key available +no_key: + ld hl,dsp_data + bit 7,(hl) ; display char available? + jr z,no_char + res 7,(hl) ; display ready + ld a,(hl) ; fetch character to display + and a + jr z,done_draw + cp &7f + jr z,done_draw + push af + ld a,&00 ; space + call display_chr ; erase cursor + pop af + cp &5f ; backspace? (underscore) + jr z,done_draw2 ; if so, no need to process further + + push af + call map_chr ; map output from SAM->Apple 1 + call display_chr ; show it + pop af +done_draw2: call advance_chr ; advance the cursor position + ld a,&3f ; cursor block + call display_chr ; show cursor +done_draw: +no_char: + ret + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Interrupt handling + +setup_im2: ld hl,im2_table + ld a,im2_jp/256 +im2_fill: ld (hl),a + inc l + jr nz,im2_fill + inc h + ld (hl),a ; complete the final entry + ld a,im2_table/256 + ld i,a + im 2 ; set interrupt mode 2 + ret + +im2_handler: push af + push bc + push de + push hl + ex af,af' + exx + push af + push bc + push de + push hl + push ix + push iy + + in a,(lmpr) + push af + ld a,screen_page+rom0_off + out (lmpr),a + + call update_io + + pop af + out (lmpr),a + + pop iy + pop ix + pop hl + pop de + pop bc + pop af + exx + ex af,af' + pop hl + pop de + pop bc + pop af + ei + reti +end_1: + +; IM 2 table must be aligned to 256-byte boundary + defs -$\256 +im2_table: defs 257 + +; IM 2 vector must have LSB==MSB + defs $/256-1 +stack_top: ; stack fits nicely in the slack space +im2_jp: jp im2_handler + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; 65C02 emulation + +execute: ld a,&1a ; LD A,(DE) + ld (main_loop),a + call load_state + jr main_loop + +read_write_loop: +write_loop: ld a,h + cp &d0 + jr z,io_write + +zwrite_loop: +zread_write_loop: +main_loop: ld a,(de) ; fetch opcode + inc de ; PC=PC+1 + ld l,a + ld h,decode_table/256 + ld a,(hl) ; handler low + inc h + ld h,(hl) ; handler high + ld l,a + jp (hl) ; execute! + + ; I/O write +io_write: ld a,l + cp &12 ; display char? + jr nz,main_loop + set 7,(hl) ; display busy + jp main_loop + +read_loop: +zread_loop: ld a,h + cp &d0 + jr z,io_read + + ld a,(de) ; fetch opcode + inc de ; PC=PC+1 + ld l,a + ld h,decode_table/256 + ld a,(hl) ; handler low + inc h + ld h,(hl) ; handler high + ld l,a + jp (hl) ; execute! + +io_read: ld a,l + cp &10 ; key read? + jr nz,main_loop + inc l + res 7,(hl) ; key not available + jp main_loop + + +; 6502 addressing modes, shared by logical and arithmetic +; instructions, but inlined into the load and store. + +a_indirect_x: ld a,(de) ; indirect pre-indexed with X + inc de + defb &fd + add a,h ; add X (may wrap in zero page) + ld l,a + ld h,0 + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + jp (ix) + +a_zero_page: ld a,(de) ; zero-page + inc de + ld l,a + ld h,0 + jp (ix) + +a_absolute: ex de,hl ; absolute (2-bytes) + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ex de,hl + jp (ix) + +a_indirect_y: ld a,(de) ; indirect post-indexed with Y + inc de + ld l,a + ld h,0 + defb &fd + ld a,l ; Y + add a,(hl) + inc l ; (may wrap in zero page) + ld h,(hl) + ld l,a + ld a,0 + adc a,h + ld h,a + jp (ix) + +a_zero_page_x: ld a,(de) ; zero-page indexed with X + inc de + defb &fd + add a,h ; add X (may wrap in zero page) + ld l,a + ld h,0 + jp (ix) + +a_zero_page_y: ld a,(de) ; zero-page indexed with Y + inc de + defb &fd + add a,l ; add Y (may wrap in zero page) + ld l,a + ld h,0 + jp (ix) + +a_absolute_y: ex de,hl ; absolute indexed with Y + defb &fd + ld a,l ; Y + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) + ld d,a + inc hl + ex de,hl + jp (ix) + +a_absolute_x: ex de,hl ; absolute indexed with X + defb &fd + ld a,h ; X + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) + ld d,a + inc hl + ex de,hl + jp (ix) + +a_indirect_z: ld a,(de) ; indirect zero-page [65C02] + inc de + ld l,a + ld h,0 + ld a,(hl) + inc l ; (may wrap in zero page) + ld h,(hl) + ld l,a + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + jp (ix) + +; Instruction implementations + +i_nop: equ main_loop +i_undoc_1: equ main_loop +i_undoc_3: inc de ; 3-byte NOP +i_undoc_2: inc de ; 2-byte NOP + jp main_loop + +i_clc: exx ; clear carry + ld c,0 + exx + jp main_loop +i_sec: exx ; set carry + ld c,1 + exx + jp main_loop +i_cli: exx ; clear interrupt disable + res 2,d + exx + jp main_loop +i_sei: exx ; set interrupt disable + set 2,d + exx + jp main_loop +i_clv: exx ; clear overflow + ld b,0 + exx + jp main_loop +i_cld: exx ; clear decimal mode + res 3,d + exx + xor a ; NOP + ld (adc_daa),a ; use binary mode for adc + ld (sbc_daa),a ; use binary mode for sbc + jp main_loop +i_sed: exx + set 3,d + exx + ld a,&27 ; DAA + ld (adc_daa),a ; use decimal mode for adc + ld (sbc_daa),a ; use decimal mode for sbc + jp main_loop + +i_bpl: ld a,(de) + inc de + ex af,af' + ld l,a ; copy N + ex af,af' + bit 7,l ; test N + jr z,i_branch ; branch if plus + jp main_loop +i_bmi: ld a,(de) + inc de + ex af,af' + ld l,a ; copy N + ex af,af' + bit 7,l ; test N + jr nz,i_branch ; branch if minus + jp main_loop +i_bvc: ld a,(de) ; V in bit 6 + inc de ; V set if non-zero + exx + bit 6,b + exx + jr z,i_branch ; branch if V clear + jp main_loop +i_bvs: ld a,(de) ; V in bit 6 + inc de + exx + bit 6,b + exx + jr nz,i_branch ; branch if V set + jp main_loop +i_bcc: ld a,(de) ; C in bit 1 + inc de + exx + bit 0,c + exx + jr z,i_branch ; branch if C clear + jp main_loop +i_bcs: ld a,(de) + inc de + exx + bit 0,c + exx + jr nz,i_branch ; branch if C set + jp main_loop +i_beq: ld a,(de) + inc de + inc c + dec c ; zero? + jr z,i_branch ; branch if zero + jp main_loop +i_bne: ld a,(de) + inc de + inc c + dec c ; zero? + jp z,main_loop ; no branch if not zero +i_branch: ld l,a ; offset low + rla ; set carry with sign + sbc a,a ; form high byte for offset + ld h,a + add hl,de ; PC=PC+e + ex de,hl + jp main_loop +i_bra: ld a,(de) ; unconditional branch [65C02] + inc de + jr i_branch + +i_bbr_0: ld a,%00000001 ; BBRn [65C02] + jp i_bbs +i_bbr_1: ld a,%00000010 + jp i_bbs +i_bbr_2: ld a,%00000100 + jp i_bbs +i_bbr_3: ld a,%00001000 + jp i_bbs +i_bbr_4: ld a,%00010000 + jp i_bbs +i_bbr_5: ld a,%00100000 + jp i_bbs +i_bbr_6: ld a,%01000000 + jp i_bbs +i_bbr_7: ld a,%10000000 +i_bbr: ex de,hl + ld e,(hl) + inc hl + ld d,0 + ex de,hl + and (hl) + ld a,(de) + inc de + jr z,i_branch ; ToDo: read_loop after branch + jp read_loop + +i_bbs_0: ld a,%00000001 ; BBSn [65C02] + jp i_bbs +i_bbs_1: ld a,%00000010 + jp i_bbs +i_bbs_2: ld a,%00000100 + jp i_bbs +i_bbs_3: ld a,%00001000 + jp i_bbs +i_bbs_4: ld a,%00010000 + jp i_bbs +i_bbs_5: ld a,%00100000 + jp i_bbs +i_bbs_6: ld a,%01000000 + jp i_bbs +i_bbs_7: ld a,%10000000 +i_bbs: ex de,hl + ld e,(hl) + inc hl + ld d,0 + ex de,hl + and (hl) + ld a,(de) + inc de + jr nz,i_branch ; ToDo: read_loop after branch + jp read_loop + +i_jmp_a: ex de,hl ; JMP nn + ld e,(hl) + inc hl + ld d,(hl) + inc hl + jp main_loop + +i_jmp_i: ex de,hl ; JMP (nn) + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ex de,hl + ld e,(hl) +; inc l ; 6502 bug wraps within page, *OR* + inc hl ; 65C02 spans pages correctly + ld d,(hl) + jp main_loop + +i_jmp_ax: ex de,hl ; JMP (nn,X) [65C02] + defb &fd + ld a,h ; X + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) ; carry spans page + ld d,a + inc hl + ex de,hl + ld e,(hl) + inc hl + ld d,(hl) + jp main_loop + +i_jsr: ex de,hl ; JSR nn + ld e,(hl) ; subroutine low + inc hl ; only 1 inc - we push ret-1 + ld d,(hl) ; subroutine high + ld a,h ; PCh + exx + ld (hl),a ; push ret-1 high byte + dec l ; S-- + exx + ld a,l ; PCl + exx + ld (hl),a ; push ret-1 low byte + dec l ; S-- + exx + jp main_loop + +i_brk: inc de ; return to BRK+2 + ld a,d + exx + ld (hl),a ; push return MSB + dec l ; S-- + exx + ld a,e + exx + ld (hl),a ; push return LSB + dec l ; S-- + ld a,d + or %00010000 ; set B flag (temp) + ld (hl),a ; push flags with B set + dec l ; S-- + set 2,d ; set I flag + exx + ld de,(m6502_int) ; fetch interrupt handler + jp main_loop + +i_rts: exx ; RTS + inc l ; S++ + ld a,(hl) ; PC LSB + exx + ld e,a + exx + inc l ; S++ + ld a,(hl) ; PC MSB + exx + ld d,a + inc de ; PC++ (strange but true) + jp main_loop + +i_rti: exx ; RTI + inc l ; S++ + ld a,(hl) ; pop P + or %00110000 ; set T and B flags + call split_p_exx ; split P into status+flags (already exx) + exx + inc l ; S++ + ld a,(hl) ; pop return LSB + exx + ld e,a + exx + inc l ; S++ + ld a,(hl) ; pop return MSB + exx + ld d,a + jp main_loop + +i_php: call make_p ; make P from status+flags + or %00010000 ; B always pushed as 1 + exx + ld (hl),a + dec l ; S-- + exx + jp main_loop +i_plp: exx ; PLP + inc l ; S++ + ld a,(hl) ; P + or %00110000 ; set T and B flags + exx + call split_p ; split P into status+flags + jp main_loop +i_pha: ld a,b ; PHA + exx + ld (hl),a + dec l ; S-- + exx + jp main_loop +i_pla: exx ; PLA + inc l ; S++ + ld a,(hl) + exx + ld b,a ; set A + ld c,b ; set Z + ex af,af' ; set N + jp main_loop +i_phx: defb &fd ; PHX [65C02] + ld a,h ; X + exx + ld (hl),a + dec l ; S-- + exx + jp main_loop +i_plx: exx ; PLX [65C02] + inc l ; S++ + ld a,(hl) + exx + defb &fd + ld h,a ; set X + ld c,a ; set Z + ex af,af' ; set N + jp main_loop +i_phy: defb &fd ; PHY [65C02] + ld a,l ; Y + exx + ld (hl),a + dec l ; S-- + exx + jp main_loop +i_ply: exx ; PLY [65C02] + inc l ; S++ + ld a,(hl) + exx + defb &fd + ld l,a ; set Y + ld c,a ; set Z + ex af,af' ; set N + jp main_loop + +i_dex: defb &fd ; DEX + dec h ; X-- + defb &fd + ld a,h ; X + ld c,a ; set Z + ex af,af' ; set N + jp main_loop +i_dey: defb &fd ; DEY + dec l ; Y-- + defb &fd + ld a,l ; Y + ld c,a ; set Z + ex af,af' ; set N + jp main_loop +i_inx: defb &fd ; INX + inc h ; X++ + defb &fd + ld a,h ; X + ld c,a ; set Z + ex af,af' ; set N + jp main_loop +i_iny: defb &fd ; INY + inc l ; Y++ + defb &fd + ld a,l ; Y + ld c,a ; set Z + ex af,af' ; set N + jp main_loop + +i_txa: defb &fd ; TXA + ld a,h ; X + ld b,a ; A=X + ld c,b ; set Z + ex af,af' ; set N + jp main_loop +i_tya: defb &fd ; TYA + ld a,l ; Y + ld b,a ; A=Y + ld c,b ; set Z + ex af,af' ; set N + jp main_loop +i_tax: defb &fd ; TAX + ld h,b ; X=A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp main_loop +i_tay: defb &fd ; TAY + ld l,b ; Y=A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp main_loop +i_txs: defb &fd ; TXS + ld a,h ; X + exx + ld l,a ; set S (no flags set) + exx + jp main_loop +i_tsx: exx ; TSX + ld a,l ; fetch S + exx + defb &fd + ld h,a ; X=S + ld c,a ; set Z + ex af,af' ; set N + jp main_loop + + +; For speed, LDA/LDX/LDY instructions have addressing inlined + +i_lda_ix: ld a,(de) ; LDA ($nn,X) + inc de + defb &fd + add a,h ; add X (may wrap in zero page) + ld l,a + ld h,0 + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + ld b,(hl) ; set A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp zread_loop +i_lda_z: ld a,(de) ; LDA $nn + inc de + ld l,a + ld h,0 + ld b,(hl) ; set A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp zread_loop +i_lda_a: ex de,hl ; LDA $nnnn + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ex de,hl + ld b,(hl) ; set A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp read_loop +i_lda_iy: ld a,(de) ; LDA ($nn),Y + inc de + ld l,a + ld h,0 + defb &fd + ld a,l ; Y + add a,(hl) + inc l ; (may wrap in zero page) + ld h,(hl) + ld l,a + ld a,0 + adc a,h + ld h,a + ld b,(hl) ; set A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp read_loop +i_lda_zx: ld a,(de) ; LDA $nn,X + inc de + defb &fd + add a,h ; add X (may wrap in zero page) + ld l,a + ld h,0 + ld b,(hl) ; set A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp zread_loop +i_lda_ay: ex de,hl ; LDA $nnnn,Y + defb &fd + ld a,l ; Y + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) + ld d,a + inc hl + ex de,hl + ld b,(hl) ; set A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp read_loop +i_lda_ax: ex de,hl ; LDA $nnnn,X + defb &fd + ld a,h ; X + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) + ld d,a + inc hl + ex de,hl + ld b,(hl) ; set A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp read_loop +i_lda_i: ld a,(de) ; LDA #$nn + inc de + ld b,a ; set A + ld c,b ; set Z + ex af,af' ; set N + jp main_loop +i_lda_iz: ld a,(de) ; LDA ($nn) [65C02] + inc de + ld l,a + ld h,0 + ld a,(hl) + inc l ; (may wrap in zero page) + ld h,(hl) + ld l,a + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + ld b,(hl) ; set A + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp read_loop + +i_ldx_z: ld a,(de) ; LDX $nn + inc de + ld l,a + ld h,0 + ld a,(hl) + defb &fd + ld h,a ; set X + ld c,a ; set Z + ex af,af' ; set N + jp zread_loop +i_ldx_a: ex de,hl ; LDX $nnnn + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ex de,hl + ld a,(hl) + defb &fd + ld h,a ; set X + ld c,a ; set Z + ex af,af' ; set N + jp read_loop +i_ldx_zy: ld a,(de) ; LDX $nn,Y + inc de + defb &fd + add a,l ; add Y (may wrap in zero page) + ld l,a + ld h,0 + ld a,(hl) + defb &fd + ld h,a ; set X + ld c,a ; set Z + ex af,af' ; set N + jp zread_loop +i_ldx_ay: ex de,hl ; LDX $nnnn,Y + defb &fd + ld a,l ; Y + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) + ld d,a + inc hl + ex de,hl + ld a,(hl) + defb &fd + ld h,a ; set X + ld c,a ; set Z + ex af,af' ; set N + jp read_loop +i_ldx_i: ld a,(de) ; LDX #$nn + inc de + defb &fd + ld h,a ; set X + ld c,a ; set Z + ex af,af' ; set N + jp main_loop + +i_ldy_z: ld a,(de) ; LDY $nn + inc de + ld l,a + ld h,0 + ld a,(hl) + defb &fd + ld l,a ; set Y + ld c,a ; set Z + ex af,af' ; set N + jp zread_loop +i_ldy_a: ex de,hl ; LDY $nnnn + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ex de,hl + ld a,(hl) + defb &fd + ld l,a ; set Y + ld c,a ; set Z + ex af,af' ; set N + jp read_loop +i_ldy_zx: ld a,(de) ; LDY $nn,X + inc de + defb &fd + add a,h ; add X (may wrap in zero page) + ld l,a + ld h,0 + ld a,(hl) + defb &fd + ld l,a ; set Y + ld c,a ; set Z + ex af,af' ; set N + jp zread_loop +i_ldy_ax: ex de,hl ; LDY $nnnn,X + defb &fd + ld a,h ; X + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) + ld d,a + inc hl + ex de,hl + ld a,(hl) + defb &fd + ld l,a ; set Y + ld c,a ; set Z + ex af,af' ; set N + jp read_loop +i_ldy_i: ld a,(de) ; LDY #$nn + inc de + defb &fd + ld l,a ; set Y + ld c,a ; set Z + ex af,af' ; set N + jp main_loop + + +; For speed, STA/STX/STY instructions have addressing inlined + +i_sta_ix: ld a,(de) ; STA ($xx,X) + inc de + defb &fd + add a,h ; add X (may wrap in zero page) + ld l,a + ld h,0 + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + ld (hl),b + jp zwrite_loop +i_sta_z: ld a,(de) ; STA $nn + inc de + ld l,a + ld h,0 + ld (hl),b + jp zwrite_loop +i_sta_iy: ld a,(de) + inc de + ld l,a + ld h,0 + defb &fd + ld a,l ; Y + add a,(hl) + inc l + ld h,(hl) + ld l,a + ld a,0 + adc a,h + ld h,a + ld (hl),b + jp write_loop +i_sta_zx: ld a,(de) + inc de + defb &fd + add a,h ; add X (may wrap in zero page) + ld l,a + ld h,0 + ld (hl),b + jp zwrite_loop +i_sta_ay: ex de,hl + defb &fd + ld a,l ; Y + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) + ld d,a + inc hl + ex de,hl + ld (hl),b + jp write_loop + +i_sta_ax: ex de,hl + defb &fd + ld a,h ; X + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) + ld d,a + inc hl + ex de,hl + ld (hl),b + jp write_loop +i_sta_a: ex de,hl + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ex de,hl + ld (hl),b + jp write_loop +i_sta_iz: ld a,(de) ; STA ($nn) [65C02] + inc de + ld l,a + ld h,0 + ld a,(hl) + inc l ; (may wrap in zero page) + ld h,(hl) + ld l,a + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + ld (hl),b ; store A + jp write_loop + +i_stx_z: ld a,(de) + inc de + ld l,a + ld h,0 + defb &fd + ld a,h ; X + ld (hl),a + jp zwrite_loop +i_stx_zy: ld a,(de) + inc de + defb &fd + add a,l ; add Y (may wrap in zero page) + ld l,a + ld h,0 + defb &fd + ld a,h ; X + ld (hl),a + jp zwrite_loop +i_stx_a: ex de,hl + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ex de,hl + defb &fd + ld a,h ; X + ld (hl),a + jp write_loop + +i_sty_z: ld a,(de) + inc de + ld l,a + ld h,0 + defb &fd + ld a,l ; Y + ld (hl),a + jp zwrite_loop +i_sty_zx: ld a,(de) + inc de + defb &fd + add a,h ; add X (may wrap in zero page) + ld l,a + ld h,0 + defb &fd + ld a,l ; Y + ld (hl),a + jp zwrite_loop +i_sty_a: ex de,hl + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ex de,hl + defb &fd + ld a,l ; Y + ld (hl),a + jp write_loop + +i_stz_z: ld a,(de) ; STZ $nn [65C02] + inc de + ld l,a + ld h,0 + ld (hl),h + jp zwrite_loop +i_stz_zx: ld a,(de) + inc de + defb &fd + add a,h ; add X (may wrap in zero page) + ld l,a + ld h,0 + ld (hl),h + jp zwrite_loop +i_stz_ax: ex de,hl + defb &fd + ld a,h ; X + add a,(hl) + ld e,a + inc hl + ld a,0 + adc a,(hl) + ld d,a + inc hl + ex de,hl + ld (hl),0 + jp write_loop +i_stz_a: ex de,hl + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ex de,hl + ld (hl),0 + jp write_loop + +i_adc_ix: ld ix,i_adc + jp a_indirect_x +i_adc_z: ld ix,i_adc + jp a_zero_page +i_adc_a: ld ix,i_adc + jp a_absolute +i_adc_zx: ld ix,i_adc + jp a_zero_page_x +i_adc_ay: ld ix,i_adc + jp a_absolute_y +i_adc_ax: ld ix,i_adc + jp a_absolute_x +i_adc_iy: ld ix,i_adc + jp a_indirect_y +i_adc_iz: ld ix,i_adc ; [65C02] + jp a_indirect_z +i_adc_i: ld h,d + ld l,e + inc de +i_adc: exx + ld a,c ; C + exx + rra ; set up carry + ld a,b ; A + adc a,(hl) ; A+M+C +adc_daa: nop + ld b,a ; set A +; jp set_nvzc + ; fall through to set_nvzc... + +set_nvzc: ld c,a ; set Z + rla ; C in bit 0, no effect on V + exx + ld c,a ; set C + jp pe,set_v + ld b,%00000000 ; V clear + exx + ld a,c + ex af,af' ; set N + jp read_loop +set_v: ld b,%01000000 ; V set + exx + ld a,c + ex af,af' ; set N + jp read_loop + +i_sbc_ix: ld ix,i_sbc + jp a_indirect_x +i_sbc_z: ld ix,i_sbc + jp a_zero_page +i_sbc_a: ld ix,i_sbc + jp a_absolute +i_sbc_zx: ld ix,i_sbc + jp a_zero_page_x +i_sbc_ay: ld ix,i_sbc + jp a_absolute_y +i_sbc_ax: ld ix,i_sbc + jp a_absolute_x +i_sbc_iy: ld ix,i_sbc + jp a_indirect_y +i_sbc_iz: ld ix,i_sbc ; [65C02] + jp a_indirect_z +i_sbc_i: ld h,d + ld l,e + inc de +i_sbc: exx + ld a,c ; C + exx + rra ; set up carry + ld a,b ; A + ccf ; uses inverted carry + sbc a,(hl) ; A-M-(1-C) +sbc_daa: nop + ccf ; no carry for overflow + ld b,a ; set A + jp set_nvzc + +i_and_ix: ld ix,i_and + jp a_indirect_x +i_and_z: ld ix,i_and + jp a_zero_page +i_and_a: ld ix,i_and + jp a_absolute +i_and_zx: ld ix,i_and + jp a_zero_page_x +i_and_ay: ld ix,i_and + jp a_absolute_y +i_and_ax: ld ix,i_and + jp a_absolute_x +i_and_iy: ld ix,i_and + jp a_indirect_y +i_and_iz: ld ix,i_and ; [65C02] + jp a_indirect_z +i_and_i: ld h,d + ld l,e + inc de +i_and: ld a,b ; A + and (hl) ; A&x + ld b,a ; set A + ld c,b ; set Z + ex af,af' ; set N + jp read_loop + +i_eor_ix: ld ix,i_eor + jp a_indirect_x +i_eor_z: ld ix,i_eor + jp a_zero_page +i_eor_a: ld ix,i_eor + jp a_absolute +i_eor_zx: ld ix,i_eor + jp a_zero_page_x +i_eor_ay: ld ix,i_eor + jp a_absolute_y +i_eor_ax: ld ix,i_eor + jp a_absolute_x +i_eor_iy: ld ix,i_eor + jp a_indirect_y +i_eor_iz: ld ix,i_eor ; [65C02] + jp a_indirect_z +i_eor_i: ld h,d + ld l,e + inc de +i_eor: ld a,b ; A + xor (hl) ; A^x + ld b,a ; set A + ld c,b ; set Z + ex af,af' ; set N + jp read_loop + +i_ora_ix: ld ix,i_ora + jp a_indirect_x +i_ora_z: ld ix,i_ora + jp a_zero_page +i_ora_a: ld ix,i_ora + jp a_absolute +i_ora_zx: ld ix,i_ora + jp a_zero_page_x +i_ora_ay: ld ix,i_ora + jp a_absolute_y +i_ora_ax: ld ix,i_ora + jp a_absolute_x +i_ora_iy: ld ix,i_ora + jp a_indirect_y +i_ora_iz: ld ix,i_ora ; [65C02] + jp a_indirect_z +i_ora_i: ld h,d + ld l,e + inc de +i_ora: ld a,b ; A + or (hl) ; A|x + ld b,a ; set A + ld c,b ; set Z + ex af,af' ; set N + jp read_loop + +i_cmp_ix: ld ix,i_cmp + jp a_indirect_x +i_cmp_z: ld ix,i_cmp + jp a_zero_page +i_cmp_a: ld ix,i_cmp + jp a_absolute +i_cmp_zx: ld ix,i_cmp + jp a_zero_page_x +i_cmp_ay: ld ix,i_cmp + jp a_absolute_y +i_cmp_ax: ld ix,i_cmp + jp a_absolute_x +i_cmp_iy: ld ix,i_cmp + jp a_indirect_y +i_cmp_iz: ld ix,i_cmp ; [65C02] + jp a_indirect_z +i_cmp_i: ld h,d + ld l,e + inc de +i_cmp: ld a,b ; A + sub (hl) ; A-x (result discarded) + ccf + exx + rl c ; retrieve carry + exx + ld c,a ; set Z + ex af,af' ; set N + jp read_loop + +i_cpx_z: ld ix,i_cpx + jp a_zero_page +i_cpx_a: ld ix,i_cpx + jp a_absolute +i_cpx_i: ld h,d + ld l,e + inc de +i_cpx: defb &fd + ld a,h ; X + sub (hl) ; X-x (result discarded) + ccf + exx + rl c ; retrieve carry + exx + ld c,a ; set Z + ex af,af' ; set N + jp read_loop + +i_cpy_z: ld ix,i_cpy + jp a_zero_page +i_cpy_a: ld ix,i_cpy + jp a_absolute +i_cpy_i: ld h,d + ld l,e + inc de +i_cpy: defb &fd + ld a,l ; Y + sub (hl) ; Y-x (result discarded) + ccf + exx + rl c ; retrieve carry + exx + ld c,a ; set Z + ex af,af' ; set N + jp read_loop + + +i_dec_z: ld ix,i_dec_zp + jp a_zero_page +i_dec_zx: ld ix,i_dec_zp + jp a_zero_page_x +i_dec_a: ld ix,i_dec + jp a_absolute +i_dec_ax: ld ix,i_dec + jp a_absolute_x +i_dec: dec (hl) ; mem-- + ld c,(hl) ; set Z + ld a,c + ex af,af' ; set N + jp read_write_loop +i_dec_zp: dec (hl) ; zero-page-- + ld c,(hl) ; set Z + ld a,c + ex af,af' ; set N + jp zread_write_loop +i_dec_ac: dec b ; A-- [65C02] + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp main_loop + +i_inc_z: ld ix,i_inc_zp + jp a_zero_page +i_inc_zx: ld ix,i_inc_zp + jp a_zero_page_x +i_inc_a: ld ix,i_inc + jp a_absolute +i_inc_ax: ld ix,i_inc + jp a_absolute_x +i_inc: inc (hl) ; mem++ + ld c,(hl) ; set Z + ld a,c + ex af,af' ; set N + jp read_write_loop +i_inc_zp: inc (hl) ; zero-page++ + ld c,(hl) ; set Z + ld a,c + ex af,af' ; set N + jp zread_write_loop +i_inc_ac: inc b ; A++ [65C02] + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp main_loop + +i_asl_z: ld ix,i_asl + jp a_zero_page +i_asl_zx: ld ix,i_asl + jp a_zero_page_x +i_asl_a: ld ix,i_asl + jp a_absolute +i_asl_ax: ld ix,i_asl + jp a_absolute_x +i_asl_acc: sla b ; A << 1 + exx + rl c ; retrieve carry + exx + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp main_loop +i_asl: ld a,(hl) ; x + add a,a ; x << 1 + ld (hl),a ; set memory + exx + rl c ; retrieve carry + exx + ld c,a ; set Z + ex af,af' ; set N + jp write_loop + +i_lsr_z: ld ix,i_lsr + jp a_zero_page +i_lsr_zx: ld ix,i_lsr + jp a_zero_page_x +i_lsr_a: ld ix,i_lsr + jp a_absolute +i_lsr_ax: ld ix,i_lsr + jp a_absolute_x +i_lsr_acc: srl b ; A >> 1 + exx + rl c ; retrieve carry + exx + ld c,b ; set Z + ld a,b + ex af,af' ; set N + jp main_loop +i_lsr: ld a,(hl) ; x + srl a ; x >> 1 + ld (hl),a ; set memory + exx + rl c ; retrieve carry + exx + ld c,a ; set Z + ex af,af' ; set N + jp write_loop + +i_rol_z: ld ix,i_rol + jp a_zero_page +i_rol_zx: ld ix,i_rol + jp a_zero_page_x +i_rol_a: ld ix,i_rol + jp a_absolute +i_rol_ax: ld ix,i_rol + jp a_absolute_x +i_rol_acc: ld a,b + exx + rr c ; set up carry + rla ; A << 1 + rl c ; retrieve carry + exx + ld b,a ; set A + ld c,b ; set Z + ex af,af' ; set N + jp main_loop +i_rol: ld a,(hl) ; x + exx + rr c ; set up carry + rla ; x << 1 + rl c ; retrieve carry + exx + ld (hl),a ; set memory + ld c,a ; set Z + ex af,af' ; set N + jp write_loop + +i_ror_z: ld ix,i_ror + jp a_zero_page +i_ror_zx: ld ix,i_ror + jp a_zero_page_x +i_ror_a: ld ix,i_ror + jp a_absolute +i_ror_ax: ld ix,i_ror + jp a_absolute_x +i_ror_acc: ld a,b + exx + rr c ; set up carry + rra ; A >> 1 + rl c ; retrieve carry + exx + ld b,a ; set A + ld c,b ; set Z + ex af,af' ; set N + jp main_loop +i_ror: ld a,(hl) ; x + exx + rr c ; set up carry + rra ; x >> 1 + rl c ; retrieve carry + exx + ld (hl),a ; set memory + ld c,a ; set Z + ex af,af' ; set N + jp write_loop + + +i_bit_z: ld ix,i_bit + jp a_zero_page +i_bit_zx: ld ix,i_bit + jp a_zero_page_x +i_bit_a: ld ix,i_bit + jp a_absolute +i_bit_ax: ld ix,i_bit + jp a_absolute_x +i_bit_i: ld h,d ; BIT #$nn + ld l,e + inc de +i_bit: ld c,(hl) ; x + ld a,c + ex af,af' ; set N + ld a,c + and %01000000 ; V flag set from bit 6 + exx + ld b,a ; set V + exx + ld a,b ; A + and c ; perform BIT test + ld c,a ; set Z + jp read_loop + +i_tsb_z: ld ix,i_tsb ; TSB [65C02] + jp a_zero_page +i_tsb_a: ld ix,i_tsb + jp a_absolute +i_tsb: ld c,(hl) ; x + ld a,c + or b ; set bits from A + ld (hl),a + ld a,c + and b ; test bits against A + ld c,a ; set Z + jp write_loop + +i_trb_z: ld ix,i_trb ; TRB [65C02] + jp a_zero_page +i_trb_a: ld ix,i_trb + jp a_absolute +i_trb: ld c,(hl) ; x + ld a,b ; A + cpl ; ~A + and c ; reset bits from A + ld (hl),a + ld a,c + and b ; test bits against A + ld c,a ; set Z + jp write_loop + +i_smb_0: ld a,%00000001 ; SMBn [65C02] + jp i_smb +i_smb_1: ld a,%00000010 + jp i_smb +i_smb_2: ld a,%00000100 + jp i_smb +i_smb_3: ld a,%00001000 + jp i_smb +i_smb_4: ld a,%00010000 + jp i_smb +i_smb_5: ld a,%00100000 + jp i_smb +i_smb_6: ld a,%01000000 + jp i_smb +i_smb_7: ld a,%10000000 +i_smb: ex de,hl + ld e,(hl) + inc hl + ld d,0 + ex de,hl + or (hl) + ld (hl),a + jp zwrite_loop + +i_rmb_0: ld a,%11111110 ; RMBn [65C02] + jp i_smb +i_rmb_1: ld a,%11111101 + jp i_smb +i_rmb_2: ld a,%11111011 + jp i_smb +i_rmb_3: ld a,%11110111 + jp i_smb +i_rmb_4: ld a,%11101111 + jp i_smb +i_rmb_5: ld a,%11011111 + jp i_smb +i_rmb_6: ld a,%10111111 + jp i_smb +i_rmb_7: ld a,%01111111 +i_rmb: ex de,hl + ld e,(hl) + inc hl + ld d,0 + ex de,hl + and (hl) + ld (hl),a + jp zwrite_loop + +i_stp: dec de ; STP [65C02] + ld a,bord_stp + out (border),a + jp main_loop + +i_wai: dec de ; WAI [65C02] + ld a,bord_wai + out (border),a + jp main_loop + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +make_p: ex af,af' + and %10000000 ; keep N + ld l,a ; N + ex af,af' + ld a,c ; Z + sub 1 ; set carry if zero + rla + rla + and %00000010 ; keep 6510 Z bit + or l ; N+Z + exx + or b ; N+V+Z + ld e,a + ld a,c + and %00000001 ; keep C + or e ; N+V+Z+C + exx + ret + +split_p: exx +split_p_exx: ld e,a ; save P + and %00111100 ; keep CPU bits + ld d,a ; set status + ld a,e + ex af,af' ; set N + ld a,e + and %01000000 ; keep V + ld b,a ; set V + ld a,e + and %00000001 ; keep C + ld c,a ; set C + ld a,e + cpl + and %00000010 ; Z=0 NZ=2 + exx + ld c,a ; set NZ + ret + +load_state: ld a,(reg_a) + ld b,a ; set A + ld a,(reg_x) + defb &fd + ld h,a ; set X to IYh + ld a,(reg_y) + defb &fd + ld l,a ; set Y to IYl + exx + ld a,(reg_s) + ld l,a ; set S + ld h,&01 ; MSB for stack pointer + exx + ld a,(reg_p) + call split_p ; set P and flags + ld de,(reg_pc) ; set PC + ret + +save_state: ld a,b ; get A + ld (reg_a),a + defb &fd + ld a,h ; get X from IYh + ld (reg_x),a + defb &fd + ld a,l ; get Y from IYl + ld (reg_y),a + exx + ld a,l ; get S + ld (reg_s),a + exx + call make_p ; get P + ld (reg_pc),de + ret + +; While running we have the 6502 registers in Z80 registers +; These are used only to hold the state before/afterwards +reg_a: defb 0 +reg_p: defb 0 +reg_x: defb 0 +reg_y: defb 0 +reg_s: defb 0 +reg_pc: defw 0 + + +; Reordering the decode table to group low and high bytes means +; we avoid any 16-bit arithmetic for the decode stage, saving +; 12T on the old method (cool tip from Dave Laundon) + +reorder_256: equ im2_table + +reorder_decode:ld hl,decode_table + ld d,h + ld e,l + ld bc,reorder_256 ; 256-byte temporary store +reorder_lp: ld a,(hl) ; low byte + ld (de),a + inc l + inc e + ld a,(hl) ; high byte + ld (bc),a + inc hl + inc c + jr nz,reorder_lp + dec h ; back to 2nd half (high bytes) +reorder_lp2: ld a,(bc) + ld (hl),a + inc c + inc l + jr nz,reorder_lp2 + ld a,&c9 ; RET + ld (reorder_decode),A + ret + + defs -$\256 ; align table to 256-byte boundary + +decode_table: DEFW i_brk,i_ora_ix,i_undoc_1,i_undoc_2 ; 00 + DEFW i_tsb_z,i_ora_z,i_asl_z,i_rmb_0 ; 04 + DEFW i_php,i_ora_i,i_asl_acc,i_undoc_2 ; 08 + DEFW i_tsb_a,i_ora_a,i_asl_a,i_bbr_0 ; 0C + + DEFW i_bpl,i_ora_iy,i_ora_iz,i_undoc_2 ; 10 + DEFW i_trb_z,i_ora_zx,i_asl_zx,i_rmb_1 ; 14 + DEFW i_clc,i_ora_ay,i_inc_ac,i_undoc_3 ; 18 + DEFW i_trb_a,i_ora_ax,i_asl_ax,i_bbr_1 ; 1C + + DEFW i_jsr,i_and_ix,i_undoc_1,i_undoc_2 ; 20 + DEFW i_bit_z,i_and_z,i_rol_z,i_rmb_2 ; 24 + DEFW i_plp,i_and_i,i_rol_acc,i_undoc_2 ; 28 + DEFW i_bit_a,i_and_a,i_rol_a,i_bbr_2 ; 2C + + DEFW i_bmi,i_and_iy,i_and_iz,i_undoc_2 ; 30 + DEFW i_bit_zx,i_and_zx,i_rol_zx,i_rmb_3 ; 34 + DEFW i_sec,i_and_ay,i_dec_ac,i_undoc_3 ; 38 + DEFW i_bit_ax,i_and_ax,i_rol_ax,i_bbr_3 ; 3C + + DEFW i_rti,i_eor_ix,i_undoc_1,i_undoc_2 ; 40 + DEFW i_undoc_2,i_eor_z,i_lsr_z,i_rmb_4 ; 44 + DEFW i_pha,i_eor_i,i_lsr_acc,i_undoc_2 ; 48 + DEFW i_jmp_a,i_eor_a,i_lsr_a,i_bbr_4 ; 4C + + DEFW i_bvc,i_eor_iy,i_eor_iz,i_undoc_2 ; 50 + DEFW i_undoc_2,i_eor_zx,i_lsr_zx,i_rmb_5 ; 54 + DEFW i_cli,i_eor_ay,i_phy,i_undoc_3 ; 58 + DEFW i_undoc_3,i_eor_ax,i_lsr_ax,i_bbr_5 ; 5C + + DEFW i_rts,i_adc_ix,i_undoc_1,i_undoc_2 ; 60 + DEFW i_stz_z,i_adc_z,i_ror_z,i_rmb_6 ; 64 + DEFW i_pla,i_adc_i,i_ror_acc,i_undoc_2 ; 68 + DEFW i_jmp_i,i_adc_a,i_ror_a,i_bbr_6 ; 6C + + DEFW i_bvs,i_adc_iy,i_adc_iz,i_undoc_2 ; 70 + DEFW i_stz_zx,i_adc_zx,i_ror_zx,i_rmb_7 ; 74 + DEFW i_sei,i_adc_ay,i_ply,i_undoc_3 ; 78 + DEFW i_jmp_ax,i_adc_ax,i_ror_ax,i_bbr_7 ; 7C + + DEFW i_bra,i_sta_ix,i_undoc_2,i_undoc_2 ; 80 + DEFW i_sty_z,i_sta_z,i_stx_z,i_smb_0 ; 84 + DEFW i_dey,i_bit_i,i_txa,i_undoc_2 ; 88 + DEFW i_sty_a,i_sta_a,i_stx_a,i_bbs_0 ; 8C + + DEFW i_bcc,i_sta_iy,i_sta_iz,i_undoc_2 ; 90 + DEFW i_sty_zx,i_sta_zx,i_stx_zy,i_smb_1 ; 94 + DEFW i_tya,i_sta_ay,i_txs,i_undoc_2 ; 98 + DEFW i_stz_a,i_sta_ax,i_stz_ax,i_bbs_1 ; 9C + + DEFW i_ldy_i,i_lda_ix,i_ldx_i,i_undoc_2 ; A0 + DEFW i_ldy_z,i_lda_z,i_ldx_z,i_smb_2 ; A4 + DEFW i_tay,i_lda_i,i_tax,i_undoc_2 ; A8 + DEFW i_ldy_a,i_lda_a,i_ldx_a,i_bbs_2 ; AC + + DEFW i_bcs,i_lda_iy,i_lda_iz,i_undoc_2 ; B0 + DEFW i_ldy_zx,i_lda_zx,i_ldx_zy,i_smb_3 ; B4 + DEFW i_clv,i_lda_ay,i_tsx,i_undoc_3 ; B8 + DEFW i_ldy_ax,i_lda_ax,i_ldx_ay,i_bbs_3 ; BC + + DEFW i_cpy_i,i_cmp_ix,i_undoc_2,i_undoc_2 ; C0 + DEFW i_cpy_z,i_cmp_z,i_dec_z,i_smb_4 ; C4 + DEFW i_iny,i_cmp_i,i_dex,i_wai ; C8 + DEFW i_cpy_a,i_cmp_a,i_dec_a,i_bbs_4 ; CC + + DEFW i_bne,i_cmp_iy,i_cmp_iz,i_undoc_2 ; D0 + DEFW i_undoc_2,i_cmp_zx,i_dec_zx,i_smb_5 ; D4 + DEFW i_cld,i_cmp_ay,i_phx,i_stp ; D8 + DEFW i_undoc_3,i_cmp_ax,i_dec_ax,i_bbs_5 ; DC + + DEFW i_cpx_i,i_sbc_ix,i_undoc_2,i_undoc_2 ; E0 + DEFW i_cpx_z,i_sbc_z,i_inc_z,i_smb_6 ; E4 + DEFW i_inx,i_sbc_i,i_nop,i_undoc_2 ; E8 + DEFW i_cpx_a,i_sbc_a,i_inc_a,i_bbs_6 ; EC + + DEFW i_beq,i_sbc_iy,i_sbc_iz,i_undoc_2 ; F0 + DEFW i_undoc_2,i_sbc_zx,i_inc_zx,i_smb_7 ; F4 + DEFW i_sed,i_sbc_ay,i_plx,i_undoc_3 ; F8 + DEFW i_undoc_3,i_sbc_ax,i_inc_ax,i_bbs_7 ; FC + +font_data: +MDAT "font.bin" + +mask_data: defb %00000011,%11111111 + defb %11000000,%11111111 + defb %11110000,%00111111 + defb %11111100,%00001111 + +end: equ $ +length: equ end-start + + +; Ken Wessen's custom BASIC+Krusader+Monitor ROM (&e000-&ffff) +; BRK handler points to mini-monitor in this version + dump &e000 +MDAT "65C02.rom.bin" + +; Original Monitor ROM (&ff00-&ffff) +; If uncommented, this will replace the monitor ROM section from above + dump &ff00 +MDAT "apple1.rom" diff --git a/apple1emu.dsk b/apple1emu.dsk new file mode 100644 index 0000000000000000000000000000000000000000..e07879b16a17bd55f7c94920857fadeb6cda56f9 GIT binary patch literal 17696 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 N5jf|XoCQbm0RJxns>uKV literal 0 HcmV?d00001 diff --git a/m.bat b/m.bat new file mode 100644 index 0000000..45a5fdc --- /dev/null +++ b/m.bat @@ -0,0 +1,2 @@ +pyz80.py -I samdos2 -s length apple1emu.asm +@if %errorlevel%==0 start apple1emu.dsk diff --git a/samdos2 b/samdos2 new file mode 100644 index 0000000000000000000000000000000000000000..21ef3d8aa1cf27209d6bb451dc1a8fa3d892b466 GIT binary patch literal 10000 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 literal 0 HcmV?d00001