diff --git a/SIM8800-instructions.pdf b/SIM8800-instructions.pdf new file mode 100644 index 0000000..c068694 Binary files /dev/null and b/SIM8800-instructions.pdf differ diff --git a/SIM8800.2mg.zip b/SIM8800.2mg.zip new file mode 100644 index 0000000..91dcb52 Binary files /dev/null and b/SIM8800.2mg.zip differ diff --git a/SIM8800.s b/SIM8800.s new file mode 100644 index 0000000..7dc1d16 --- /dev/null +++ b/SIM8800.s @@ -0,0 +1,3248 @@ +; SIM8800 +; Altair 8800 simulator by Charles Mangin, 2019 +;8080 emulator code: +; APPLE-80 - an 8080 simulator-debug package Copyright (c) 1979 by Dann Mccreary + + DSK SIM8800 + ORG $9000 + +; ---------------------------------------------------------------------------- +; TODO: +; port to 65816 - 24bit addresses, 16 bit registers, 64k contiguous AUX, 2.8mhz +; +; ---------------------------------------------------------------------------- + +ZERO EQU $00 +SPEED EQU $02 ; ??? +INTE EQU $03 ; INTERRUPT ENABLE - 00 == interrupts enabled, 01 == no interrupts +PSW EQU $04 ; PROCESSOR STATUS +SIMA EQU $05 ; ACCUMULATOR +SIMM EQU $06 ; DUMMY MEMORY REGISTER +SIML EQU $07 ; HL REG PAIR +SIMH EQU $08 ; HL REG PAIR +SIME EQU $09 ; DE REG PAIR +SIMD EQU $0A ; DE REG PAIR +SIMC EQU $0B ; BC REG PAIR +SIMB EQU $0C ; BC REG PAIR +SPL EQU $0D ; STACK POINTER L +SPH EQU $0E ; STACK POINTER H +PCL EQU $0F ; 8080 PROGRAM COUNTER L +PCH EQU $10 ; 8080 PROGRAM COUNTER H +DECIT EQU $11 ; DOUBLE PRECISION -1 +INCIT EQU $13 ; DOUBLE PRECISION 0001 +FLAG EQU $15 ; USED BY SIMULATOR +DESTDA EQU $16 ; DESTINATION DATA +DEST EQU $17 ; DESTINATION INDEX +SRC EQU $18 ; SOURCE INDEX + +OPCODE EQU $1A ; CURRENT OPCODE +;PSPEED EQU $1B ; TRACE SPEED FROM PADDLE0 +PNT EQU $1C ; DATA POINTER +SCR EQU $1E ; SCRATCHPAD REGISTER + +TEXTTOP EQU $22 ; text window top edge + +HPOS EQU $24 ; HORIZONTAL CURSOR POSITION +VPOS EQU $25 ; VERTICAL CURSOR POSITION +CURPOS EQU $28 ; CURSOR POSITION ADDRESS +KSWL EQU $38 ; keyboard input routine +KSWH EQU $39 ; normally $FD1B + +HIPCH EQU $FE ; is the PC above 32k limit? + +KBDBUF EQU $C000 ; KEYBOARD BUFFER +KBDSTROBE EQU $C010 ; KEYBOARD STROBE +SPKR EQU $C030 ; CLICK +LORES EQU $C050 +TXTSET EQU $C051 +MIXCLR EQU $C052 +MIXSET EQU $C053 + +TXTPAGE1 EQU $C054 +TXTPAGE2 EQU $C055 + +RAMRDOFF EQU $C002 ; Read enable main memory from $0200-$BFFF +RAMRDON EQU $C003 ; Read enable aux memory from $0200-$BFFF +RAMWRTOFF EQU $C004 ; Write enable main memory from $0200-$BFFF +RAMWRTON EQU $C005 ; Write enable aux memory from $0200-$BFFF +ALZTPOFF EQU $C008 ; Enable main memory from $0000-$01FF & avl BSR +ALTZPON EQU $C009 ; Enable aux memory from $0000-$01FF & avl BSR + +; READ HIGH BIT: +RAMRD EQU $C013 ; 0=main $0200-$BFFF active reads 1=aux active +RAMWRT EQU $C014 ; 0=main $0200-$BFFF active writes 1=aux writes +ALTZP EQU $C016 ; 1=aux $0000-$1FF+auxBSR 0=main available + +AUXMOVE EQU $C311 ; +; The beginning address of the block to be moved must be stored at locations A1L ($3C) and A1H ($3D) and the ending address at +; A2L ($3E) and A2H ($3F). Finally, the destination address must be stored at A4L ($42) and A4H ($43). +; If the carry flag is set, then the move will be performed from main memory to auxiliary memory. +; If it is clear, the move will take place in the opposite direction. + + +CLRLORES EQU $F832 ; clear low res screen +PREAD EQU $FB1E ; PREAD returns a number that represents the position of a hand control. +SETTXT EQU $FB39 ; Set Text Mode +SETGR EQU $FB40 ; mixed text/graphics Mode +BASCALC EQU $FBC1 ; calculate base address +BELL2 EQU $FBE4 ; 60hz bell +VTAB EQU $FC22 ; Sets the cursor vertical position (from CV) +HOME EQU $FC58 ; HOME +CLREOL EQU $FC9C ; say end of line +WAIT EQU $FCA8 ; simple delay +KEYIN EQU $FD1B +RDKEY EQU $FD0C ; read keyboard input + +CROUT EQU $FD8E ; Print CR +PRBYTE EQU $FDDA ; Prints byte as 2 hex digits +COUT EQU $FDED ; character output +BELL EQU $FF3A ; outputs ^G +OLDRST EQU $FF59 ; set screen mode and init + +MLI EQU $BF00 ; ProDOS system call +OPENCMD EQU $C8 ; OPEN command index +READCMD EQU $CA ; READ command index +SET_MARKCMD EQU $CE ; SET_MARK index +CLOSECMD EQU $CC ; CLOSE command index +WRITECMD EQU $CB ; HERE THERE BE DRAGONS +; ---------------------------------------------------------------------------- + +; DO AUXMOVE from $9000 to $B000 -> aux $9000 + LDA #$00 + STA $3C + STA $3E + STA $42 + LDA #$90 + STA $3D + STA $43 + LDA #$B0 + STA $3F + SEC + JSR AUXMOVE +; magic done. + + + + JSR HOME + JSR CHOOSER ; determine what program/basic/bootloader to load + + JSR LOADPROGRAM ; load it, based on ACC value + + JSR HOME + JSR INSTRUCTIONS ; copyright and instructions + + JSR ALTAIRSCREEN ; Draw GR screen + +; INIT +INIT JMP SETUP + +; ---------------------------------------------------------------------------- +; MAIN +MNSTRT JMP DISPLAYLOOP ; setup and display first frame + +; ---------------------------------------------------------------------------- + +SIM80 LDA #$00 + STA HIPCH ; reset HIPCH for each go-round + ; **** add $10 to PCH + LDA PCH + STA DISPLAYBYTES ; high byte to first bank of LEDs. + CMP #$7F ; above 32k limit? + BCC ADC10 + ROL HIPCH ; carry into HIPCH indicates we schlepped above 32K + SEC ; gotta set carry again. + SBC #$80 ; subtract #$80 - probably could do AND 7F + CLC + +ADC10 ADC #$10 + STA PCH + ; **** + + JSR MAIN ; execute OPCODE + + ; **** subtract $10 from PCH + SEC + LDA PCH + SBC #$10 + + LDX HIPCH ; were we reading PC from AUX? + BEQ SBC10 ; nope, skip + CLC + ADC #$80 + ROR HIPCH ; HIPCH 1 into carry, leaving 00 +SBC10 STA PCH ; store resulting PCH + ;**** + + LDA PSW ; processor status + AND #$D7 ; AND 1101 0111 - clear MI and HLTA bits + ORA #$02 ; OR 0000 0010 - set WO bit + STA PSW ; + CLI ; clear interrupts + + JSR SIMDSK ; operate virtual disk drive + + RTS ; return + +; ---------------------------------------------------------------------------- +; EXECUTE ONE 8080 OPCODE +MAIN SEI ; DON'T ALLOW INTERRUPTS + CLD ; CLEAR DECIMAL MODE + LDX #$00 ; LOAD INDEX + ; **** add $10 to SIMH + CLC + LDA SIMH + +; compare to 8f, subtract 80 + + CMP #$7F ; if it's >=32K boundary after add $10, get from AUX + BCC STASIMM2 + STA RAMRDON ; set AUX READ + + SBC #$80 ; subtract #$80 + CLC ; read from AUX, still write to MAIN + ; add #$80 + ; set MAIN READ +STASIMM2 ADC #$10 + STA SIMH + + + +STASIMM LDA (SIML,X) ; FETCH MEMORY *** from (HL) register pair *** + STA SIMM ; crashes II if SIMH is C0 softswitch area + + ; **** subtract $10 from SIMH +DECSIMH SEC ; then subtract #$10... oof. + LDA SIMH + SBC #$10 + STA SIMH + ;**** + + LDA RAMRD ; if RAMRD high bit + BPL CHECKPCH ; low = RAMRDOFF + STA RAMRDOFF ; high = turn it off, etc + CLC ; add #$80 to SIMH again + LDA SIMH + + ADC #$80 + STA SIMH + +CHECKPCH ; is PC looking above #$8FFF? + LDA HIPCH + BEQ LDAPC ; nope, skip + STA RAMRDON ; read from AUX + +LDAPC LDA (PCL,X) ; FETCH INSTRUCTION **** this should come from real $1000-$8fff + + PHA ; opcode to stack + LDA RAMRD ; if RAMRD high bit + BPL STAOPCODE + STA RAMRDOFF ; high = turn it off, etc + + +STAOPCODE PLA ; get the opcode back + + STA OPCODE ; + EOR #$76 ; + TAX ; + LDY #$01 ; + LDA PNT ; + AND INTE ; IS THIS A HALT? + BPL CKINT ; + STY INTE ; + STY PNT ; + ORA #$C7 ; + STA OPCODE ; + DEY ; +; CHECK FOR INTERRUPT +CKINT LDA INTE ; + BNE NINT ; + DEC INTE ; +; ENABLE INTERRUPT +NINT TXA ; + BNE NOHLT ; + DEY ; +; HALT? +NOHLT TYA ; + BEQ ITR ; + JSR INCPC ; +; SET COUNTER/INDEX +ITR LDX #$02 ; + LDA OPCODE ; +DIV PHA ; + AND #$07 ; + EOR #$07 ; + STA ZERO,X ; + PLA ; + LSR A ; + LSR A ; + LSR A ; + DEX ; + BNE DIV ; + STX FLAG ; + LSR A ; + BCS IMI ; + BEQ FIRST ; +IMARL LDA #$11 ; no, arilog + ADC ZERO+$01 ; SIMA + TAX ; + LDA #$00 ; set dest=A + STA ZERO+$01 ; SIMA +IMI BEQ MOVE ; +SECOND LDA #$07 ; offset for 2nd (page?) +FIRST ADC SPEED ; + TAX ; Transfer to Index + INX ; + + +MOVE TXA ; SET HIGH ADDRESS + ASL A ; + TAX ; + LDA XFERTBL,X ; GET LO ADOR + INX ; + PHA ; SET LO ADDRESS + LDA XFERTBL,X ; + PHA ; + LDX SPEED ; GET SOURCE INDEX + +NOFETCH LDY SIMA,X ; GET SOURCE DATA IN Y *** + + LDX ZERO+$01 ; GET DEST INDEX + LDA SIMA,X ; + STA ZERO ; SAVE DESTINATION DATA + LDA #$44 ; SET 6502 STATUS + PHA ; + TXA ; DEST IND, IN A & X + RTI ; GO INTERPRET + ; RTS to stack pointer instruction + +; ---------------------------------------------------------------------------- +IN LSR A ; + BEQ XCHG ; + BCC INPUT ; + TAY ; + JSR CALL65 ; + STA SIMA ; + RTS ; + +; ---------------------------------------------------------------------------- +; CALL 6502 SUBROUTINE +CALL65 LDA (PCL),Y ; + PHA ; + DEY ; + BPL CALL65 ; + JSR DBLINC ; + LDA #$00 ; + PHA ; + LDA SIMA ; + RTI ; + +; ---------------------------------------------------------------------------- +XCHG JSR RPSCR ; + LDX #$04 + LDY #$02 + JSR RPRP ; + LDX #$04 + JMP SCRRP ; + +; ---------------------------------------------------------------------------- +XTHL JSR RPSCR ; + JSR SPPNT ; + LDX #$02 + JSR MEMRP ; + LDX #$13 + BNE RPMEM ; +; ---------------------------------------------------------------------------- + +IO LSR A ; which inst? + BNE LBL ; + STX INTE ; set/clear INTE + RTS ; + +; ---------------------------------------------------------------------------- +LBL LDX #$02 ; point to HL + BCC IN ; is it input + LSR A ; no, is it xthl? + BEQ XTHL ; yes + BCS JMPJUMPUN ; is it jump? +OUTPUT DEC FLAG ; no, flag an output +INPUT JSR IMM ; get port # + LDA SRC ; SRC = port number + AND #$0F ; clear high bits (FF => 0F) because why keep up with 256 ports when we only need 16? + ASL A ; double index for hi/lo byte in table + TAX ; port table offset in X + LDY #$02 ; +IOPLP LDA IOTBLOUT,X ; get IO address + STA FLAG,Y ; store in pointer + INX ; bump index + DEY ; decrement counter + BNE IOPLP ; + INY ; point to data dir, reg +PNTPRT DEY ; point to port + LSR FLAG ; FLAG is FF on OUTPUT, 00 on INPUT + BCC IOIN ; do input if carry clear. + LDA SIMA ; - if carry set, OUTPUT +IOOUT + STA (DESTDA),Y ; OUTPUT TO PORT + JSR SIOOUT ; TELL SIO I HAVE PUT A BYTE TO SEND + BCS IOEX ; should return with Carry set??? + +IOIN + INC DESTDA ; switch from PORT-OUT to PORT-IN + TYA + PHA + JSR SIOIN ; TELL SIO I WANT A BYTE - Y=PORT + PLA + TAY + LDA (DESTDA),Y ; input from port + STA SIMA ; store in SIMA + +IOEX RTS ; + +JMPJUMPUN JMP JUMPUN ; spaghetti +; ---------------------------------------------------------------------------- +ARIM JSR IMM ; + CLC ; + JMP IMARL ; + +JMPCALLUN JMP CALLUN ; spaghetti +; ---------------------------------------------------------------------------- +PUSH LSR A ; IS THIS A PUSH? + BCS SKP ; YES, GO PUSH + CMP #$03 ; NO, IS THIS A CALL? + BEQ JMPCALLUN ; YES, GO CALL + JMP UNDEF ; NO, UNDEFINED + +SKP ASL A ;MAKE AN INDEX + TAX ;IS IT PUSH PSW? + BNE PUSHT ; NO, KEEP INDEX + DEX ;YES, ADJUST INDEX + +PUSHT TXA ; TEMP SAVE - x=0A on set return, gets PCL/H + PHA ; + JSR DECSP ; DECREMENT STACK POINTER + JSR SPPNT ; IT BECOMES POINTER + PLA ; RECOVER TEMP SAVE + TAX ; + + + +RPMEM LDY #$01 ; CLEAR INDEX + + ; compare to 8f, THEN add 10 if necessary + + ;CLC + LDA DESTDA,Y ; $04 + $12 = $16 DESTDA + STA DISPLAYBYTES ; high byte to first bank of LEDs. + CMP #$7F ; over 9000? + BCC RPMEM2 ; nope, skip math + + SBC #$80 ; off by $10 ??? *** + STA RAMWRTON ; write to AUX + STA DESTDA,Y + +RPMEM2 CPX #$02 ; **** + BNE RPLP ; **** add $10 to SRC+1 ON SHLD, X=2 + ; E5 PUSH H AXY=02/02/01 + ; 22 SHLD AXY=02/01/01 + LDA OPCODE ; is it PUSH H or SHLD? <-- corner case! + CMP #$22 + BNE STADESTDA + LDA DESTDA,Y + CLC ; ADD 10 to destination on SHLD + ADC #$10 + STA DESTDA,Y ; **** + +STADESTDA LDA RAMWRT ; if writing to aux, add 80 back and write to main + BPL RPLP + CLC + LDA DESTDA,Y + ADC #$80 + STA DESTDA,Y + STA RAMWRTOFF ; write to MAIN + +RPLP LDA SIMM,X ;GET NEXT RP DATA + PHA ; hang onto it + LDA DESTDA+1 + STA DISPLAYBYTES ; high byte to first bank of LEDs. + + CMP #$8F ; over 9000 or under 1000? + BCS STADESTDA3 ; over 9000 + CMP #$10 + BCS STADESTDA2 ; Over 1000, skip + +STADESTDA3 SEC + + SBC #$80 + STA RAMWRTON + STA DESTDA+1 + +STADESTDA2 PLA ; get RP data back + STA (DESTDA),Y ;STORE IN MEMORY + + LDA RAMWRT ; if writing to aux, add 80 back and write to main + BPL RPLP2 + CLC + LDA DESTDA+1 + + ADC #$80 + STA DESTDA+1 + STA RAMWRTOFF ; write to MAIN + +RPLP2 DEX ; + DEY ; + BEQ RPLP ; + + CPX #$00 ; **** + BNE RTS ; **** reset SRC+1 ON SHLD, X=2 + INY + INY + SEC + LDA DESTDA,Y ; $04 + $12 = $16 DESTDA + SBC #$10 + PHA ; hold that thought... + LDA RAMWRT ; writing to AUX? turn that off. + BPL RPLP3 + CLC + LDA DESTDA,Y + ADC #$80 +RPLP3 STA RAMWRTOFF + PLA ; and we're back. + STA DESTDA,Y ; **** + + +RTS RTS ; +; ---------------------------------------------------------------------------- +JMP CLV ; INDICATE A JUMP + +CALL JSR CONDIT ; TEST CONDITION + BEQ CALLUN ; MET + JMP DBLINC ; NOT MET, increment PC + +; ---------------------------------------------------------------------------- +JUMPUN CLV ; INDICATE A JUMP +CALLUN PHP ; preserve overflow, etc + +CALLUN3 JSR PCPNT ; GET NEXT 2 BYTES + + +CALLUN4 LDX #$13 ; INTO SCRATCH + JSR MEMRP ; + + ; **** add $10 to SRC+1 + CLC + LDA SRC+1 + PHA + STA DISPLAYBYTES ; high byte to first bank of LEDs. + CMP #$7F ; is above 32k? + BCC CALLUN5 + LDA #$01 + STA HIPCH ; if destination PCH is above 32k? +CALLUN5 PLA + CLC + ADC #$10 ; CLEARS OVERFLOW? + STA SRC+1 + ;**** + + PLP ; get overflow, etc. + +CALLUN2 BVC JM ; JUMP on overflow clear + JSR DBLINC ; otherwise? BUMP PC twice + +SVR LDX #$0A ; SAVE RETURN for RST + + LDA HIPCH ; return address should be HIPCH as well + BEQ SVR1 + LDA PCH + CLC + ADC #$80 + STA PCH + + ; **** subtract 10 before setting return point +SVR1 SEC + LDA PCH + SBC #$10 + STA PCH + ;**** + + JSR PUSHT ; ON STACK **** <--- and if SP is >9000? + + ; **** add 10 after setting return point ??? + CLC + LDA PCH + ADC #$10 + STA PCH + ;**** + +JM LDX #$0A ; POINT TO PC + + ; **** doing a JUMP or CALL - reset HIPCH + LDA #$00 + STA HIPCH + ; **** doing a JUMP or CALL - reset HIPCH + + JMP SCRRP ; GIVE IT NEW ADDRESS + +JMPSVR JMP SVR ; SPAGHETTI! + +; ---------------------------------------------------------------------------- +RETURN JSR CONDIT ; TEST CONDITION + BNE RTS ; NOT MET +RETUN + ; if SPH > 8F or < 10, subtract 80, read from AUX, write to AUX !!! + ; **** doing a JUMP or CALL - reset HIPCH + LDA #$00 + STA HIPCH + + ; **** doing a JUMP or CALL - reset HIPCH + + LDA SPH + STA DISPLAYBYTES ; high byte to first bank of LEDs. + + CMP #$8F + BCS RETUN1 + CMP #$10 + BCS RETUN2 + SEC +RETUN1 + SBC #$80 ; *** SPH off by $10? + STA RAMRDON + STA RAMWRTON + STA SPH + + + + ; **** add $10 to (SP) before grabbing return point +RETUN2 CLC + LDY #$01 + LDA (SPL),Y ; get byte at (SPL/H) + ADC #$10 + STA (SPL),Y + ;**** + + LDA RAMRD ; if reading/writing AUX, switch back to MAIN + BPL RETUN3 + LDA SPH ; return SPH to high value + CLC + ADC #$80 ; *** SPH off by $10? + STA SPH + STA RAMRDOFF + STA RAMWRTOFF + +RETUN3 LDX #$0A ; POP RETURN OFF + BNE POPIT ; STACK INTO PC + +RST LDA OPCODE ; CONVERT INSTRUCTION + AND #$38 ; TO RESET VECTOR + STA SRC ; STORE IT IN SCRATCH + LDA #$00 + STA HIPCH ; no longer need to inc the PCH if we're resetting to 0038 + LDA #$10 ; HIGH RESET VECTOR + STA SRC+1 ; ??? SCR+1 ??? + BCC JMPSVR ; +; ---------------------------------------------------------------------------- +POP LSR A ; POP? + BCC OTH ; NO + ASL A ; + TAX ; POP PSW? + BNE POPIT ; NO, KEEP INDEX + DEX ; YES, ADJUST INDEX + +POPIT TXA ; TEMP SAVE INDEX + PHA ; + + + JSR SPPNT ; PULL OUT STACK DATA + PLA ; BUMP SP + TAX ; + JSR MEMRP ; SP IS POINTER +ICISP JSR ISP ; RECOVER TEMP +ISP LDX #$08 ; + JMP INC ; + +; ---------------------------------------------------------------------------- +OTH LDX #$02 ; POINT TO HL + LDY #$08 ; ASSUME SPHL + ASL A ; IS IT SPHL? + BEQ SPHL ; YES, GO DO IT + CMP #$04 ; NO, WHAT IS IT? + BEQ UNDEF ; UNDEFINED + BPL RETUN ; RETURN + LDY #$0A ; PCHL + +; **** ; if it's a PCHL, add $10 to SIMH to offset subtracting after the operation. + + LDA SIMH ; **** + CLC ; **** + ADC #$10 ; **** + STA SIMH ; **** + +SPHL JMP RPRP ; + +; ---------------------------------------------------------------------------- +CONDIT + LSR A ; MAKE INDEX TO MASK. TABLE + TAX ; + LDA MSKTBL,X ; GET CONDITION FLAG MASK + AND PSW ; IS CONDITION SET* + BCS RTN ; LEAVE Z FLAG SET + EOR MSKTBL,X ; OR REVERSE IT +RTN RTS ; + +; ---------------------------------------------------------------------------- +NOP LDA OPCODE ; CHECK INSTRUCTION + BEQ RTN ; Pointer says 00 == NOP +UNDEF ;LDY #$0C ; ILLEGAL OPCODE, UNDEFINED + ;LDX #$0A ; + ;JSR INCDEC ; + ;JMP MNSTRT ; ignore and move on. + ;JSR BELL ; Beep, then RTS + RTS ; RTS on illegal/undefined opcode ? + +; ---------------------------------------------------------------------------- +DADLXI LSR A ; DROP LSB + ASL A ; + BNE NSP ; USE SP? + LDA #$08 ; YES, POINT TO IT + + +NSP PHA ; SAVE POINTER a=8 + TXA ; GET DESTINATION INDEX + LSR A ; DAD? + BCS LXI ; NO, GO DO LXI +DAD PLA ; YES, RECOVER POINTER a=8 + TAY ; + LDX #$02 ; SET HL AS DESTINATION + + LDA OPCODE ; **** subtract 10 from SPH before working with it / DAD SP + CMP #$39 ; if we're working with stack pointer + BNE DAD2 + LDA SPH + SEC + SBC #$10 + STA SPH ; **** subtract 10 from SPH before working with it + +DAD2 JSR INCDEC ; GO ADD RP & HL + + PHA ; **** if we're working with DAD SP + PHP ; preserve carry set, etc + LDA OPCODE + CMP #$39 + BNE CARRY2 + LDA SPH ; **** add 10 to SPH after working with it + CLC + ADC #$10 + STA SPH +CARRY2 PLP ; reset carry, etc + PLA ; **** add 10 to SPH after working with it + +CARRY TAY ; SAVE RESULT + ROL A ; BRING IN CARRY + EOR FLAG ; CHG TO BORROW IF SUBTRACT + LSR PSW ; + LSR A ; RESTORE CARRY(BORROW) + ROL PSW ; + TYA ; RECOVER RESULT + + + RTS + +; ---------------------------------------------------------------------------- +LXI JSR PCPNT ; PC INTO PNT + PLA ; RECOVER POINTER + TAX ; USE TO INDEX DESTINATION RP + JSR MEMRP ; MOVE IMMEDIATE DATA TO RP +; if RP is SP, add 10 to SPH + ; **** + LDA OPCODE + CMP #$31 + BNE LXI2 + CLC + LDA SPH + ADC #$10 + STA SPH + ; **** +LXI2 JMP DBLINC ; BUMP PROGRAM COUNTER + +; ---------------------------------------------------------------------------- +LDSTR BIT FOUR ; INDIRECT? + BEQ DIRECT ; NO + LSR A ; STAX? + BCC LDAX ; NO +STAX + INX ; **** add 10 to DESTDA + CLC + LDA PSW,X + STA DISPLAYBYTES ; high byte to first bank of LEDs. + CMP #$7F ; over 9000? + BCC STAX1 ; nope, carry on + SBC #$80 ; yep, subtract 80 + STA RAMWRTON ; write AUX + CLC +STAX1 ADC #$10 + + +STAX2 STA PSW,X ; store updated destination address + DEX ; **** + LDA SIMA ; YES,STORE A + STA (PSW,X) ; PSW = 04 + 12 = 16 = destDA + INX ; **** reset DESTDA + SEC + LDA PSW,X + SBC #$10 + LDY RAMWRT ; load Y? Y not!? + BPL STAX3 + CLC + ADC #$80 + STA RAMWRTOFF ; back to MAIN +STAX3 STA PSW,X + DEX ; **** + + + RTS ; + +; ---------------------------------------------------------------------------- +DIRECT PHA ; TEMP SAVE + JSR PCPNT ; PC TO POINTER + JSR DBLINC ; + LDX #$13 ; + JSR MEMRP ; + +; **** if LHLD, add 10 to SRC before grabbing memory contents + LDA OPCODE + CMP #$2A + BNE DIRECT2 + LDA SRC+1 + CLC + ADC #$10 + STA SRC+1 +; **** if LHLD, add 10 to SRC before grabbing memory contents + +DIRECT2 LDX #$11 ; + JSR SCRRP ; + PLA ; RECOVER TEMP + LSR A ; LOAD? + BCS STORE ; NO, STORE + ASL A ; + TAX ; + BEQ LDAD ; + JMP MEMRP ; + +; ---------------------------------------------------------------------------- +LDAD LDX #$11 ; + +LDAX CLC ; **** + INX + LDA SIMA,X + + STA DISPLAYBYTES ; high byte to first bank of LEDs. + + CMP #$7F ; over 9000? + BCC LDAX1 + SBC #$80 + STA RAMRDON + + CLC +LDAX1 ADC #$10 + STA SIMA,X + + +LDAX2 DEX ; **** + + LDA (SIMA,X) ; + STA SIMA ; + + SEC ; **** + INX + LDA SIMA,X + SBC #$10 + STA SIMA,X + + LDA RAMRD + BPL LDAX3 + STA RAMRDOFF ; back to MAIN + LDA SIMA,X + CLC + ADC #$80 + STA SIMA,X + +LDAX3 DEX ; **** + + RTS ; + +; ---------------------------------------------------------------------------- +STORE ASL A ; MAKE INDEX + TAX ; + BEQ STAD ; STORE A DIRECT? + + JMP RPMEM ; NO, STORE HL DIRECT SHLD + +STAD LDX #$12 ; POINT TO POINTER + JMP STAX ; jump to STAX + +; ---------------------------------------------------------------------------- + +INXDCX LDY #$0C ; SET FOR DECREMENT + LSR A ; + BCC DRP ; YES + LDY #$0E ; NO, SET FOR INCR +DRP ASL A ; DROP LSB + BNE NOR ; FOR SP? + LDA #$08 ; YES, POINT TO SP +NOR TAX ; USE AS INDEX + JMP INCDEC ; + +; ---------------------------------------------------------------------------- +DCR SEC ; SET FOR DECREMENT + DEC FLAG ; +INR LDY #$01 ; SET FOR INCREMENT +BTH JSR ADDR ; GO ADD + JMP STATUS2 ; SET STATUS, NOT CARRY + + + +; ---------------------------------------------------------------------------- +MVI JSR IMM ; GET IMMEDIATE BYTE + JMP MOVE ; MOVE IT TO DESTINATION + +; ---------------------------------------------------------------------------- +MOVIT TYA ; GET SOURCE DATA +MVIT1 DEX ; IS DEST MEMORY? + BNE NMEM ; NO + + INX ; **** + PHA ; **** + LDA SIML,X ; **** SIMH + STA DISPLAYBYTES ; high byte to first bank of LEDs. + CMP #$7F ; above 8000? + ; above 9000 after adding $10 !!! + BCC MVIT2 + STA RAMWRTON ; set AUX WRITE + SBC #$80 ; SBC #$80 + CLC ; **** + +MVIT2 ADC #$10 ; add #$10 + + ; store in AUX + ; add #$80 + ; set MAIN WRITE + + + +STASIMH STA SIML,X ; **** + PLA ; **** + DEX ; **** + + STA (SIML,X) ; YES STORE IN MEMORY + INX ; **** + PHA ; **** byte into stack + + LDA RAMWRT + BPL STASIMH2 + LDA SIML,X + STA RAMWRTOFF ; AUX OFF, write to MAIN + CLC + ADC #$80 + STA SIML,X + +STASIMH2 SEC ; **** + LDA SIML,X ; **** + SBC #$10 ; **** subtract 10 + STA SIML,X ; **** + +NOMOV PLA ; **** + DEX ; **** + +NMEM STA SIMM,X ; STORE IN DEST REGISTER + RTS ; + +; ---------------------------------------------------------------------------- +ADC CLV ; FLAG W/CARRY + BVC ADD ; + +CMP LDX #$13 ; CHG DEST TO SCR + BNE SUB ; SO ONLY PSW IS AFFECTED + +SBB CLV ; FLAG W/BORROW +SUB DEC FLAG ; F L A G = FF FOR SUBTRACT + SEC ; + +ADD JMP ADCRY ; + +; ---------------------------------------------------------------------------- +ORA TYA ; GET SOURCE DATA + ORA SIMA ; LOGICAL OR + BCC SOM ; SET FOR A CLEAR AUX CRY + +XRA TYA ; G E T SOURCE DA T A + EOR SIMA ; LOGICAL EXCLUSIVE OR +SOM LDY #$00 ; 00 WON'T SET ANY FLAGS + BEQ ALL ; GO SAVE RESULT + +ANA TYA ; G E T SOURCE DA T A + PHA ; SAVE IT + ORA SIMA ; LOGICAL OR OF BIT + ASL A ; T H R E E BECOMES AUX CARRY + AND #$10 ; + TAY ; + PLA ; GET SOURCE DATA + AND SIMA ; LOGICAL AND + +ALL STY SRC+1 ; SAVE FLAG SETTING DATA + STA SIMA ; LOGICAL RESULT INTO A + JSR STATUS2 ; SET STATUS + LDA #$EE ; SELECT STATUS BITS TO CLEAR +CYAC AND PSW ; CLEAR SELECTED BITS + ORA SRC+1 ; SET SELECTED BITS +STPSW STA PSW ; SAVE NEW PSW + RTS ; + + + + + + +; ---------------------------------------------------------------------------- +ROTATE LDY SIMA ; GET ACCUMULATOR + LSR A ; IS THIS CMC OR 8TC? + BNE ROCOMP ; NO, IT IS A ROTATE .OR CMA + LDA PSW ; YES, CHANGE CARRY + EOR #$01 ; CMC + BCC STPS ; + ORA #$01 ; STC +STPS BVS STPSW ; +; ---------------------------------------------------------------------------- + +ROCOMP BCS LEFT ; LEFT OR RIGHT? + LSR A ; CMA? + BNE ROT ; NO, ROTATE + TYA ; YES, COMMPLEMFNT A + EOR #$FF ; + STA SIMA ; DOESN* T SET STATUS + RTS ; + +; ---------------------------------------------------------------------------- +ROT TYA ; GET ACCUMULATOR + BCS RRC ; + LDA PSW ; GET 8080 CARRY +RRC LSR A ; + TYA ; GET ACCUMULATOR + ROR A ; ROTATE RIGHT + BVS JCRY ; GO STORE&SET CARRY +; ---------------------------------------------------------------------------- +LEFT LSR A ; DECIMAL ADJUST? IYES# GO 00 IT + BEQ DAA ; N 0 , GET ACCUMULATOR + TYA ; JRLC? + BCS RLC ; NO#GET 8080 CARRY + LDA PSW ; MOVE IT INTO MSNIB + ROR A ; + ROR A ; +RLC ASL A ; MOVE IT INTO CARRY + TYA ; G E T ACCUMULATOR + ROL A ; MOVE IT LEFT +JCRY STA SIMA ; SAVE IT + JMP CARRY ; GO SET STATUS + +; ---------------------------------------------------------------------------- +DAA CLC ; + PHP ;PRE3ERVE STATUS | + TYA ;GET SOURCE DATA + STA ZERO ; PREP FOR ADD + AND #$0F ;LOOK AT LSNI8 + ADC #$06 ;IF *0A WILL CAUSE AUX CRY + ORA PSW ;OR I F AC I S ALREADY SET + AND #$10 ; EITHER SET? + BEQ NOSIX ;NO, DON T ADJUST LSNIB + LDA #$06 ; YES# ADJUST IT +NOSIX TAY ; + ADC ZERO ; G E T SOURCE + BCS SXTY ; + ADC #$60 ;113 MSNIB NOW > A0T IIF SO* CARRY IS SET + ROL A ;G E T CARRY + ORA PSW ;OR WITH 8080 CARRY + LSR A ;I S EITHER SETT + BCC DA ;NO# DON'T ADJUST MSNIB l +SXTY TYA ;YES* ADJUST MSN!B I + ADC #$5F ;(5F + CARRY = 60) + TAY ; +DA LDX #$00 ;DESTINATION IS A + PLP ;RESTQRE STATUS +ADCRY JSR ADDR ; + JSR CARRY ; + + +STATUS2 + TAY ; SAVE RESULT + ROL PSW ; CLEAR P3W SIGN BIT + ASL A ; PUT NEW SIGN IN CARRY + STA FLAG ; C L E A R L S B OF F L A G + LDA PSW ; PUT NEW SIGN IN P3N + ROR A ; +SGN ORA #$46 ; PRESET Z*P 8 PRESET + TAX ; 3AVE IN X + TYA ; RECOVER WORD + BEQ DONE ; I F ZERO*ALL DONE +FLIP INC FLAG ; IFLIP FLAG | +PAR LSR A ; TEST EACH BIT I + BEQ ALL2 ; NO MORE BITS + BCC PAR ; +ALL2 BCS FLIP ; + LSR FLAG ; TEST FLAG + TXA ; RECOVER P3w + AND #$BF ; CLEAR Z + BCS REC ; PARITY EVENT + AND #$FB ; N0* CLEAR P +REC TAX ; BACK TO X +DONE STX PSW ; STORE AS PSW + RTS ; + +; ---------------------------------------------------------------------------- + +PCPNT LDX #$0A ; **** 0A + 05/06 = 0F = PCL/PCH +RPPNT LDY #$11 ; 05 + 11 = 16 = store at DESTDA + BNE RPRP ; never zero, branch always +RPSCR LDY #$13 ; store at SRC instead + +; moves scratchpad or other RP bytes to PC, vice versa +RPRP + + LDA SIMA,X ; load SOURCE BYTE L + STA SIMA,Y ; store at DESTINATION L + LDA SIMM,X ; load SOURCE BYTE H + + CPY #$08 ; **** if SPHL + BNE RPRP4 ; **** + CLC ; **** + ADC #$10 ; **** + JMP RPRP2 + +RPRP4 CPX #$0A ; X=0A, PC IS POINTER. + BNE RPRP2 + LDA HIPCH ; HIPCH = 1, inc resulting pointer by 70 + BEQ RPRP3 + CLC + LDA SIMM,X + ADC #$80 ; 70 or 80? oof... + JMP RPRP2 + +RPRP3 LDA SIMM,X + +RPRP2 STA SIMM,Y ; store at DESTINATION H + +RPRTS RTS ; + +; ---------------------------------------------------------------------------- +SCRRP TXA ; RP is destination (RP is a Register Pair) + TAY ; 0A on CALL (for return address???) + LDX #$13 ; SCR is source + BNE RPRP ; never zero, branch always + +SPPNT LDX #$08 ; SP is Source + BNE RPPNT ; jump RPPNT + +DBLINC JSR INCPC ; Increments PC twice +; ADVANCE COUNTER + +INCPC LDX #$0A ; INC PC - $0A + $05 = $0F = PCL +INC LDY #$0E ; point to INC data - $0E + $05 = $13 = INCIT (0001) +INCDEC CLC ; + +INDE LDA SIMA,X ; get register/PC value + ADC SIMA,Y ; add value from + STA SIMA,X ; save + INY ; bump indexes + INX ; + TYA ; check index 0E->0F + AND #$01 ; last pass? - increment HI byte + BNE INDE ; not done, loop + + RTS ; yes + +; ---------------------------------------------------------------------------- +DECSP JSR DSP ; DEC SP twice +DSP LDX #$08 ; DEC SP +DEC LDY #$0C ; point to DEC data + BNE INCDEC ; go do it +; ---------------------------------------------------------------------------- +MEMRP TYA ; grab source pointer offset + + + LDA DESTDA+1 + + STA DISPLAYBYTES ; high byte to first bank of LEDs. + + CMP #$8F ; *** off by $10 *** WTF *** + BCS AUXMEMRP + CMP #$10 ; less than $10, rolled over from $F0 + BCS MRLP1 +AUXMEMRP STA RAMRDON ; read from AUX + SEC + SBC #$80 + STA DESTDA+1 + +MRLP1 LDY #$01 ; move data in memory + +MRLP LDA (DESTDA),Y ; get next byte + STA SIMM,X ; store in destination + DEX ; bump indices + DEY ; + BEQ MRLP ; + + LDA RAMRD ; if we're still reading from AUX, add 80 back + BPL MRLPRTS + STA RAMRDOFF ; read from MAIN + LDA DESTDA+1 + CLC + ADC #$80 + STA DESTDA+1 + + + +MRLPRTS RTS ; + +; ---------------------------------------------------------------------------- +IMM LDX #$00 ; GET BYTE POINTED AT + ; BY PROGRAM COUNTER + LDA HIPCH ; if HIPCH, get it from AUX + BEQ IMM2 + STA RAMRDON ; AUX on + +IMM2 LDA (PCL,X) + STA SRC ; SAVE IT IN SCR + LDA #$13 ; MAKE SCR THE SOURCE INDEX + STA SPEED ; ??? should SPEED be SCR? + STA RAMRDOFF ; back to main + JSR INCPC ; BUMP PC + LDX #$00 ; POINT TO INTERP PAGE 2 + RTS ; + +; ---------------------------------------------------------------------------- +ADDR TYA ; + EOR FLAG ; + TAY ; + AND #$0F ; + STA SRC ; + ROL A ; + BVS WOCRY ; + EOR PSW ; +WOCRY PHA ; + LSR A ; + LDA ZERO ; + AND #$0F ; + ADC SRC ; + AND #$10 ; + STA SRC+1 + LDA #$EF ; + JSR CYAC ; + PLA ; + LSR A ; + TYA ; + ADC ZERO ; + JMP MVIT1 ; + +; ---------------------------------------------------------------------------- +; TABLE OF PSW MASKS +MSKTBL DB $80 ; SIGN BIT MASK +FOUR DB $04,$01,$40 ; PARITY BIT MASK, CARRY BIT MASK, ZERO BIT MASK + +; XFER TABLE +XFERTBL + DB >MOVIT,ROTATE,MVI,DCR,INR,INXDCX,LDSTR,DADLXI,NOP,RST,ARIM,PUSH,CALL,IO,JMP,POP,RETURN,CMP,ORA,XRA,ANA,SBB,SUB,ADC,ADD, current HPOS, + BCS INCHPOS ; increment HPOS and start over + LDA #$FF ; otherwise, + STA HPOS ; set HPOS to FF + BNE INCHPOS ; then increment to 00 + + + +; ---------------------------------------------------------------------------- +; I/O TABLE +; 0/10 = SIO STATUS = for left bank of switches +; 1/11 = SIO DATA = to put a byte at lower left of screen + +; 08 = Disk Enable/Status channel +; 09 = Disk control/sector position channel +; 0A = Disk data channel + +; FF/0F = panel switches + +IOTBLOUT DB >SIOSTATUSOUT,SIODATAOUT,DSKSELECT,DSKCONTROL,DSKWRITE,DISPLAYBYTES,SIOSTATUSIN,SIODATAIN,DSKSTATUS,DSKSECTORIN,DSKREAD,SWITCHBYTES, ignore for now + + AND #$0F ; 1x => 0x + CMP #$01 ; is it on port 1 or 11? + BNE DSKOUT ; if not, is it output to DSK? + + ; LOAD BYTE FROM SIODATA + LDA SIODATAOUT ; load SIO DATA + + ; translate CR/LF into newline. + ; CR = 0D + ; LF = 0A + CMP #$0A + BEQ SIORTS ; ignore LF, just do CR. + + ORA #$80 ; add the high bit? + + + ; OUTPUT TO SCREEN + JSR COUT ; output char + +SIORTS SEC + RTS + +SIOIN ; SIGNALLED FROM IOIN THAT SIM80 LOOKING FOR A BYTE. + ; looking for a byte from IN 1 or 0? + LDX #$00 + LDA SRC ; if input is 00, checking SIO status. + + CMP #$ff ; sense switches. + BEQ SENSEIN + + CMP #$0A ; looking for DISK DATA + BEQ DSKIN + + CMP #$09 ; looking for DISK SECTOR + BEQ DSKSPIN ; "spin" the disk + + CMP #$10 ; SIO2 on port 10/11. SIO1 on port 0/1 + BCC SIO1IN + INX + INX ; use SIO2 status bytes instead of SIO1 + JMP SIO2IN + +SIO1IN ;AND #$0F ; kill hi nibble so 10==00 + BNE SIOKEY ; 00? status check. Otherwise, expects a byte. + STA SIODATAIN ; clear the pipes on status check, 00 to data + JMP SIOREADY ; set status to ready for I/O + + ; CHECK KEYBOARD +SIOKEY LDA KBDBUF ; read keyboard + STA KBDSTROBE ; clear strobe + + ; IF KEY WAITING, LOAD IT IN SIODATA + BPL SIORTS ; no key. RTS. +; BPL CHECKKSW ; if bit8/carry, has keyboard input. else check for BASIC LOAD + STA SIODATAIN ; put ascii in DATA + + ; SET SIOSTATUS TO 00 = HAVE DATA + LDA SIOSTATUSBYTES,X ; set STATUS to 00 - HAVE DATA/READY FOR OUTPUT + STA SIOSTATUSIN + RTS + + ; NO KEY WAITING + ; SET SIOSTATUS 01 = STILL WAITING INPUT +;CHECKKSW JSR KSW ; CHECK FOR KSW INPUT FROM BASIC LOAD +; ; should only run on input and if src = 1? +; BPL SIORESET ; if high bit set, have a byte from BASIC LOAD. otherwise, return + +SIOREADY ; SET SIOSTATUS TO 00 = HAVE DATA + LDA SIOSTATUSBYTES,X ; set STATUS to 00 - HAVE DATA/READY FOR OUTPUT + STA SIOSTATUSIN + RTS + +SIORESET INX + LDA SIOSTATUSBYTES,X ; 01 = WAITING FOR INPUT/READY FOR OUTPUT + STA SIOSTATUSIN ; + RTS + +SENSEIN AND #$0F + CLC + ROL + TAY + LDA IOTBLIN,Y ; sense switches up/down don't have an IN/OUT version + STA DESTDA+1 + INY + LDA IOTBLIN,Y + STA DESTDA + RTS + + +SIO2IN AND #$0F ; #$10 -> #$00 + BEQ SIO2STATUS + ; SIO2 data input + LDA KBDBUF ; get the key + STA KBDSTROBE ; clear the strobe + STA SIODATAIN ; store it in datain buffer + JMP SIORESET ; input done. set status to waiting for next check. + + +SIO2STATUS ; looking for status of SIO2 - have a byte, byte sent, or 00 waiting + LDA KBDBUF ; if KBDBUF bit 8 hi, have a byte + BPL SIORESET ; bit8 lo, set status to byte sent/waiting + JMP SIOREADY ; bit 8 hi, has keyboard input. + +DSKOUT CMP #$0A ; port 0A -> output to DSK + BNE SIORTS ; not 0A? -> ignore + + LDY SECTOROFFSET ; which byte of the current sector to push to + LDA TRACKPOINTER ; offset within track ($89xSECTOR) + STA $0 + LDA TRACKPOINTER+1 + STA $1 + LDA DSKWRITE ; load the byte + STA ($0),Y ; set byte at track pointer + offset + INC SECTOROFFSET ; ready for next read + RTS + + +; ---------------------------------------------------------------------------- + + +FULLSCREEN ASC " FULL SCREEN MODE: CONTROL-C TO EXIT ",00 +LASTLINEBUF DS 41,$00 ; 40 bytes to store last line of split screen text. followed by zero to stop. + +CTRLF LDA TEXTTOP ; control-F for full-screen terminal + BEQ CTRLFRTS ; already in full-screen. ignore. + + LDX #$27 ; copy last line of text from $7d0 +BUFFERLINE LDA $7D0,X + STA LASTLINEBUF,X + DEX + BPL BUFFERLINE + + BIT TXTSET ; set text Mode + LDA #$00 + STA TEXTTOP ; to make scroll full screen. + JSR HOME ; clear low res screen + +; Ask for 80 columns? + JSR ASK80 ; Returns with ZERO on YES + BNE CTRLFGO + LDA #$00 ; clears out the Y/N from accumulator + JSR $C300 + +CTRLFGO LDY #$3F + JSR $FE86 + + LDA #$00 + STA $F3 ; no blinking text? + + LDY #>FULLSCREEN + LDA #LASTLINEBUF + LDA #ASK80STRING + LDA #/= 8, and we do SWITCHBYTES+0 carry set + LDA #$00 ; A < 8, and we do SWITCHBYTES+1 carry clear + + ADC #$00 ; if carry, 0. If not, 1 + EOR #$01 ; flip bit 1 + + CMP #$01 ; carry set, >7, so needs an extra loop + BCS SETBANK ; carry clear, 0-7 + + INX +SETBANK TAY ; bank 0 or 1 + + SEC ; set carry bit to rotate into accumulator + LDA #$00 +ROTATEIN ROL ; rotate the bit into + DEX + BNE ROTATEIN + + EOR SWITCHBYTES,Y + STA SWITCHBYTES,Y + + JSR UPDATESWITCHES ; update the display + + RTS + +; --------------------------------------------------------------------------- + +; Display bytes as sWITCHES +UPDATESWITCHES + BIT SPKR ; click + + LDA #$06 ; down row to use COUT + JSR BASCALC + LDA #$06 ; over for COUT + STA HPOS + LDX #$00 ; PC HI + JSR SWITCHLOOP + + LDA #$06 ; down row to use COUT + JSR BASCALC + + LDX #$01 ; PC LO + JSR SWITCHLOOP + RTS + + +SWITCHLOOP LDY #$08 ; do a byte's worth + LDA SWITCHBYTES,X ; put the switch status into scratch + STA SWITCHSCRATCH,X +SWLOOP LDA #$AA ; gray + JSR COUT ; output gray between switches + LDA #$25 ; switch DOWN + CLC ; clear carry + ROL SWITCHSCRATCH,X ; rotate opcode, hi bit into carry + BCC SETSW ; if Carry clear, skip + LDA #$26 ; switch UP +SETSW JSR COUT ; output to screen + DEY ; done all 8 bits? + BNE SWLOOP + ; bottom pixels + + LDA SWITCHBYTES,X ; put the switch status into scratch + STA SWITCHSCRATCH,X + + LDA #$07 ; down row to use COUT + JSR BASCALC + LDA HPOS ; over for COUT + SEC + SBC #$10 + STA HPOS + +SWITCHLOOP2 LDY #$08 ; do a byte's worth + LDA SWITCHBYTES,X ; put the switch status into scratch + STA SWITCHSCRATCH,X +SWLOOP2 LDA #$AA ; gray + JSR COUT ; output gray between switches + LDA #$A6 ; switch DOWN + CLC ; clear carry + ROL SWITCHSCRATCH,X ; rotate opcode, hi bit into carry + BCC SETSW2 ; if Carry clear, skip + LDA #$A5 ; switch UP +SETSW2 JSR COUT ; output to screen + DEY ; done all 8 bits? + BNE SWLOOP2 + BIT SPKR ; click + + RTS + + + + +; --------------------------------------------------------------------------- +BYTELOOP LDY #$08 ; do a byte's worth +BITLOOP LDA #$AA ; gray + JSR COUT ; output gray between lights + LDA #$A8 ; LED OFF + CLC ; clear carry + ROL DISPLAYBYTES,X ; rotate opcode, hi bit into carry + BCC SETLED ; if Carry clear, skip + LDA #$A1 ; LED ON +SETLED JSR COUT ; output to screen + DEY ; done all 8 bits? + BNE BITLOOP + RTS + + +WAITLED LDY #$A8 ; light off + BCC SETWAIT ; Carry clear, lamp off + LDY #$A1 ; Carry set, light on +SETWAIT LDA #$03 ; down one row to use COUT + JSR BASCALC + LDA #$02 ; over 22 for COUT + STA HPOS + TYA + JSR COUT ; output to screen + RTS + + + +; ---------------------------------------------------------------------------- +BOTTOMROW ; flip switches + + ; six switches X = number of loops + ; Y =1 for up, =0 for down. + BIT SPKR ; click + LDA #$04 ; start at column 4 + STA HPOS +BRSWLOOP ; bottom row switch loop. + INC HPOS + INC HPOS ; over two spaces + INC HPOS ; over two spaces + DEX ; loop X times + BNE BRSWLOOP ; switch last one up/down + + LDA #$0A ; row 10 + JSR BASCALC + LDA #$55 ; #$55 is down + CPY #$0 ; is Y 0 or 1? + BEQ SWDOWN1 + LDA #$52 ; #$52 is up + +SWDOWN1 JSR COUT ; put switch pixels + + LDA #$0B ; Down to row 11 + JSR BASCALC + DEC HPOS ; back over 1 px + LDA #$A2 ; #$A2 is down + CPY #$0 ; is Y 0 or 1? + BEQ SWDOWN2 + LDA #$A5 ; #$A5 is up/center +SWDOWN2 JSR COUT ; put switch pixels + + BIT SPKR ; click + LDA #$80 + JSR WAIT ; delay to show switch action. + RTS + + + +BOTTOMROWRST + LDX #$04 ; four of six switches X = number of loops + LDA #$05 ; start at column 4 + STA HPOS +BRRSLOOP + LDA #$0A ; row 10 + JSR BASCALC + + INC HPOS + INC HPOS ; over two spaces + + LDA #$25 ; #$25 is centered + JSR COUT ; put switch pixels + + LDA #$0B ; Down to row 11 + JSR BASCALC + DEC HPOS ; back over 1 px + + LDA #$A5 ; #$A5 is center + JSR COUT ; put switch pixels + + DEX ; loop X times + BNE BRRSLOOP ; switch last one up/down + + + RTS + + + +; --------------------------------------------------------------------------- +PRLOHI JSR PRBYTE ; prints a pair of registers + TXA ; +PRREG JSR PRBYTE ; print hex of one register, followed by space (#$A0) + LDA #$A0 ; + JMP $FDED ; JMP to COUT with RTS ? + +MOVETXT ; move the current text page to alt text page + LDA #$00 ; Setup pointers to move memory + STA $3C ; $3C and $3D for source start + LDA #$04 + STA $3D + + LDA #$FF + STA $3E ; $3E and $3F for source end + LDA #$07 + STA $3F ; + + LDA #$00 + STA $42 ; $42 and $43 for destination + LDA #$08 ; $1000 == destination + STA $43 + LDA #$00 ; Clear ACC, X,Y for smooth operation + TAX + TAY + JSR $FE2C ; F8ROM:MOVE ; Do the memory move + RTS + +ALTAIRSCREEN + ; move graphic data to $4000 + + LDA ALTAIRLO ; Setup pointers to move memory + STA $3C ; $3C and $3D for source start + LDA ALTAIRHI + STA $3D + + LDA ALTAIRLO + STA $3E ; $3E and $3F for source end + LDA ALTAIRHI + CLC + ADC #$04 ; add $400 to start == end of graphic + STA $3F ; + + LDA #$00 + STA $42 ; $42 and $43 for destination + LDA #$50 ; $4000 == destination + STA $43 + LDA #$00 ; Clear ACC, X,Y for smooth operation + TAX + TAY + JSR $FE2C ; F8ROM:MOVE ; Do the memory move + + + + LDA #$15 ; Kill 80-Column mode whether active or not + JSR $FDED ; F8ROM:COUT + + STA $C050 ; rw:TXTCLR ; Set Lo-res page 1, mixed graphics + text + STA $C053 ; rw:MIXSET + STA $C054 ; rw:TXTPAGE1 + STA $C056 ; rw:LORES + + ; display the data from $4000 at $400 +RESETVPTR LDA #$00 ; Move titlepage from $4000 to $400 (screen) + STA $FE ; pointer for where we are at vertically on screen + TAY ; Y-Reg used for indexing across (horiz) screen +VERTICALPTR LDA $FE ; pointer for where we are at vertically on screen + JSR $F847 ; F8ROM:GBASCALC + + LDA $26 + STA $FA ; $FA is our offset GBASL Byte (Source data titlepage) + + LDA $27 ; Add 04 w/ Carry to get to $4000 where graphic data is + ADC #$4C + STA $FB ; $FB is our offset GBASH Byte (Source data titlepage) + +GRABSTORAGE LDA ($FA),Y ; Grab from storage + STA ($26),Y ; Put to screen + INY + CPY #$28 ; #$28 past the width of screen? + BNE GRABSTORAGE ; No? Back for another round + LDA #$00 + TAX + TAY + + + INC $FE ; Next line down vertically + LDA #$00 + TAX + TAY + LDA $FE + CMP #$15 ; #$18 bottom of screen - go to line 21 for legend + BNE VERTICALPTR ; No? Go back and do next line down + + + LDA #$00 + STA KBDSTROBE ; r:KBDSTRB ; Clear keyboard strobe + + ; LOOP HERE TO WAIT FOR KEYPRESS ??? + + RTS ; We now return you to your regular programming + +;/ALTAIRSCREEN + + + +************************************************** +* writes instructiONS +************************************************** + +COPYRIGHT ASC "APPLE-80 COPYRIGHT 1979 BY DANN MCCREARY",00 ; ascii copyright info +LINE1 ASC " SIM8800 BY CHARLES MANGIN, 2019", 00 + +LINE2 ASC "KEYBOARD COMMANDS:",00 + +LINE3 ASC " " + INV '0-9' + ASC ", " + INV 'A-F' + ASC " TOGGLES SWITCHES 0-15",00 + +LINE4 ASC " " + INV 'X' + ASC " TO EXAMINE MEMORY",00 + +LINE5 ASC " " + INV 'N' + ASC " FOR NEXT ADDRESS, " + INV '^' + ASC " FOR PREVIOUS",00 + +LINE6 ASC " " + INV 'P' + ASC " TO DEPOSIT BYTE INTO MEMORY",00 + +LINE6A ASC " " + INV 'O' + ASC " TO DEPOSIT NEXT BYTE",00 + +LINE7 ASC " " + INV 'SPACE' + ASC " OR " + INV 'S' + ASC " TO EXECUTE 1 STEP",00 + +LINE8 ASC " " + INV 'T' + ASC " TO START INTERACTIVE TRACE",00 + +LINE9 ASC " " + INV 'G' + ASC " TO RUN PROGRAM",00 + +LINE9A ASC " " + INV 'CTRL-C' + ASC " TO STOP RUN/TRACE",00 + +LINE9B ASC " " + INV 'CTRL-F' + ASC " TO RUN FULL SCREEN",00 + + +LINE10 ASC " " + INV 'K' + ASC " TO SET BREAKPOINTS",00 + +LINE11 ASC " " + INV 'R' + ASC " TO EDIT REGISTERS",00 + +LINE12 ASC " " + INV 'I' + ASC " FOR THESE INSTRUCTIONS",00 + +ANYKEY ASC " PRESS SPACE TO CONTINUE",00 + + +INSTRUCTIONSTBL DB #>LINE2,#LINE3,#LINE4,#LINE5,#LINE6,#LINE6A,#LINE7,#LINE8,#LINE9,#LINE9B,#LINE9A,#LINE10,#LINE11,#LINE12,#CHOOSER1,CHOOSER2,CHOOSER3,CHOOSER4,CHOOSER5,CHOOSER6, 0x + TAX + RTS + + + +SHOWINST + STA TXTPAGE2 ; alternate page + JSR SETTXT ; sets text mode + +INSTLOOP LDA KBDBUF ; check for keydown + CMP #$A0 + BEQ RETURNSIM ; + JMP INSTLOOP ; got a key? + +RETURNSIM STA KBDSTROBE ; clear key + STA LORES + STA MIXSET + STA TXTPAGE1 ; main text/gr page + JMP DISPLAYLOOP ; back to it. + + +INSTRUCTIONS LDA #$00 + STA VPOS + JSR VTAB + + LDY #>COPYRIGHT + LDA #LINE1 + LDA #ANYKEY + LDA #PAPERTAPE,>FILENAME1,>FILENAME2,>FILENAME3,>FILENAME4,>FILENAME5 + +READLOCLO DB BASICBUFFER,$10,$10,$10,$10,$10 ; remember to add $10 + + +************************************************** +LOADPROGRAM BEQ NOPROGRAM ; x=0, no program to load. + JSR BLOAD ; loads BASIC + + LDA BASICBUFFERLO ; locate BASICBUFFERLO + CLC + ADC TRANSFERRED ; ADD TRANSFERRED + STA $00 ; put BASICBUFFERLO,$00 + LDA BASICBUFFERHI ; add BASICBUFFERHI + TRANSFERRED+1 + ADC TRANSFERRED+1 ; put BASICBUFFERHI,$01 + STA $01 + LDY #$00 ; Y=0 + TYA + STA ($00),Y ; put #$00 ($0),Y + +NOPROGRAM RTS ; Otherwise done + +************************************************** + +BLOAD ; file gets chosen by LDX before JSR BLOAD + LDA FILENAMESLO,X + STA OPENFILENAME + LDA FILENAMESHI,X + STA OPENFILENAME+1 + + LDA READLOCLO,X + STA READLOC + LDA READLOCHI,X + STA READLOC+1 + + JSR OPEN ;open "DATA" + JSR READ + BNE ERROR ; error if return !=0 + JSR CLOSE + BNE ERROR ; error if return !=0 + + RTS + +OPEN JSR MLI ;Perform call + DB OPENCMD ;CREATE command number + DW OPENLIST ;Pointer to parameter list + BNE ERROR ;If error, display it + LDA REFERENCE + STA READLIST+1 + STA CLOSELIST+1 + RTS + +READ JSR MLI + DB READCMD + DW READLIST + RTS + +CLOSE JSR MLI + DB CLOSECMD + DW CLOSELIST + RTS + +OPENLIST DB $03 ; parameter list for OPEN command +OPENFILENAME DB $00,$00 + DA MLI-$400 ; buffer snuggled up tight with PRODOS +REFERENCE DB $00 ; reference to opened file + +READLIST DB $04 + DB $00 ; REFERENCE written here after OPEN +READLOC DB $00,$00 ; write to end of sim8800 + DB $FF,$FF ; read as much as $FFFF - should error out with EOF before that. +TRANSFERRED DB $00,$00 + +CLOSELIST DB $01 + DB $00 + +ERROR JSR PRBYTE ;Print error code + JSR CROUT ;Print a carriage return + JSR BELL + RTS + +************************************************** + +DSKLOAD + JSR DSKOPEN ; open dsk file + JSR SETDSKOFFSET ; SET_MARK + JSR READDSK + BNE ERROR ; error if return !=0 + JSR CLOSE + BNE ERROR ; error if return !=0 + + RTS + +DSKOPEN JSR MLI ;Perform call + DB OPENCMD ;CREATE command number + DW DSKOPENLIST ;Pointer to parameter list + BNE ERROR ;If error, display it + LDA DSKREFERENCE + STA DSKREADLIST+1 + STA CLOSELIST+1 + STA MARKLIST+1 + RTS + +SETDSKOFFSET ;LDA DSKTRACK ; get track number + ;BEQ RESETOFFSET ; if zero, rezero MARK and move along + LDA #$00 +RESETOFFSET STA DSKOFFSET ; rezero the offset + STA DSKOFFSET+1 + STA DSKOFFSET+2 + LDX DSKTRACK ; how many loops to INC offset by? + BEQ SET_MARK ; zero = skippity + +MARKLOOP LDA DSKOFFSET ; should be zero to start *** magic happens *** + CLC + ADC #$20 ; multiply $1120 by track number + STA DSKOFFSET + LDA DSKOFFSET+1 ; store result in DSKOFFSET + ADC #$11 + STA DSKOFFSET+1 + BCC MARKLOOP2 + INC DSKOFFSET+2 +MARKLOOP2 DEX ;*** magic happens *** + BNE MARKLOOP + +SET_MARK JSR MLI + DB SET_MARKCMD + DW MARKLIST + BNE ERROR + RTS + + +READDSK JSR MLI + DB READCMD + DW DSKREADLIST + RTS + +OUTTODSK JSR DSKOPEN ; open dsk file + JSR SETDSKOFFSET ; SET_MARK + JSR WRITEDSK + BNE ERROR ; error if return !=0 + JSR CLOSE + BNE ERROR ; error if return !=0 + + RTS + + + + +DSKOPENLIST DB $03 ; parameter list for OPEN command +DSKOPENFILENAME DB DSKFILE + DA MLI-$400 ; buffer snuggled up tight with PRODOS +DSKREFERENCE DB $00 ; reference to opened file + +MARKLIST DB $02 ; 2 parameters for set_mark + DB $00 ; mark REFERENCE +DSKOFFSET DB $00,$00,$00 ; 3 bytes, lo to hi + +DSKREADLIST DB $04 + DB $00 ; REFERENCE written here after OPEN +DSKREADLOC DB BASICBUFFER ; write to end of sim8800 + DB $20,$11 ; read $1120 bytes at a time (137*32) +DSKTRANSFERRED DB $00,$00 + +DSKFILE DB ENDDSKNAME-DSKNAME ;Length of name +DSKNAME ASC '/SIM8800/ZORK.DSK' ;followed by the name +ENDDSKNAME EQU * + +WRITEDSK JSR MLI + DB WRITECMD + DW DSKREADLIST ; same parameters for read/write + RTS + +************************************************** +; Defaults: +; DSKTRACK == 0 +; set DSKSTATUS = A5 : *** 1 == FALSE, 0 == TRUE *** +; bit 0 = not ready to write 1 +; bit 1 = head move allowed 0 +; bit 2 = head status not on 1 +; bit 5 = interrupt disabled = 1 +; bit 6 = 0 - on track 0 +; bit 7 = 1 - data not ready yet +; +; set DSKSECTORIN = 0 +; +; on DSKCONTROL out - if bit 2 = 1, then load 137 bytes from DSKTRACK. +; +; OPEN DISKBASIC41, SET_MARK = DSKTRACK, READ 32*137 bytes into BASICBUFFER +; +; +************************************************** + +DSKSELECT DB $00 ; port 08 out - latches and enables drive - ignored for now, only enabling 1 drive (0) +DSKSTATUS DB $A5 ; port 08 in - indicates drive status 1010 0101 *** 0=TRUE, 1=FALSE *** + ; not ready to write, move enable, head off, n/a, n/a, interrupt disable, on track 0, no data +DSKCONTROL DB $00 ; port 09 out - controls drive functions *** 1=TRUE, 0=FALSE *** +DSKSECTORIN DB $00 ; port 09 in - indicates disk sector position - start at 00 + ; 0-31 offset by 1 bit, bit 0=0 when on sector 0, 1 otherwise. + +DSKWRITE EQU $FA ; port 0A out - data to write +DSKREAD EQU $FB ; port 0A in - data to read + +DSKTRACK DB $00 ; 32 sectors ($20) per track. Start at track 00 (4K=$1120 per track) +DSKSECTOR DB $00 ; 137 bytes ($89) per sector. Start at sector 00 + ; *** use this for math, DSKSECTORIN for comms. +SECTOROFFSET DB $00 ; how far into the sector to grab bytes +TRACKPOINTER DB $00,$00 ; how far into the track to look for sector start + +************************************************** + +SIMDSK LDA DSKCONTROL ; see what the last operation wants from the drive + BEQ DSKRTS ; ZERO? Do nothing. + TAX ; hang onto DSKCONTROL byte + + AND #$03 ; one/two LO bits set? 00000011 + BNE MOVEHEAD ; moving head in/out + + TXA ; get DSKCONTROL back + CMP #$08 ; bits 2/3 set, load/unload head 00001000 + BEQ UNLOADHEAD + + CMP #$80 + BEQ WRITESEQUENCE ; == #$80 for DSK write??? + + AND #$04 ; == 04 TRUE = load HEAD + BEQ DSKRTS ; anything else? + +LOADHEAD LDA DSKSTATUS ; if bit 0=0 then, yes. Write was initiated at least. + TAX + AND #$01 ; if it's 1, no need to write + BNE LOADHEAD2 + + TXA ; otherwise, write the track to DSK file + ORA #$01 + STA DSKSTATUS ; set bit 0 to disable write for next pass + + JSR OUTTODSK ; write the track with MLI + +LOADHEAD2 JSR DSKLOAD ; LOAD TRACK TO BUFFER AFTER WRITING CURRENT TRACK BACK TO DISK + + LDA DSKSTATUS ; DSKCONTROL == #$04 + AND #$7B ; 0111 1011B .....0.. = head on, data waiting +; ORA #$02 ; 0000 0010B head not movable - unnecessary + STA DSKSTATUS ; move off, head on, + + JMP DSKRTS + +UNLOADHEAD LDA DSKSTATUS ; DSKCONTROL == #$08 + ORA #$04 ; 00000100B .....10. = move on, head off + AND #$FD ; 11111101B + STA DSKSTATUS + +DSKRTS LDA #$00 + STA DSKCONTROL ; reset DKSCONTROL to prevent loopity + RTS + +WRITESEQUENCE + + LDA DSKSTATUS ; unset bit 0 to enable write + AND #$FC ; set head loaded true. STATUS bit 2 = 0 + STA DSKSTATUS ; 11111100 + + ; set sector status true. SECTOR bit 0 = 0 + + ; bytes OUT on 0A + + JMP DSKRTS + +MOVEHEAD ; DID WE WRITE TO THIS TRACK? + LDA DSKSTATUS ; if bit 0=0 then, yes. Write was initiated at least. + TAX + AND #$01 ; if it's 1, no need to write + BNE MOVEHEAD2 + + TXA ; otherwise, write the track to DSK file + ORA #$01 + STA DSKSTATUS ; set bit 0 to disable write for next pass + + JSR OUTTODSK ; write the track with MLI + +MOVEHEAD2 LDA DSKCONTROL ; move which way? + ROR ; bit 0 into carry + BCS STEPIN ; bit 0 set, move to HIGHER track # + +STEPOUT LDA DSKTRACK ; if already on track 0, ignore. + BEQ SETTRACK0 ; make sure TRACK0 bit is set? + DEC DSKTRACK ; otherwise next lower track + BEQ SETTRACK0 ; + JSR DSKLOAD ; LOAD TRACK N TO BUFFER + JMP DSKRTS + +SETTRACK0 LDA DSKSTATUS ; + AND #$BF ; 10111111 unset bit 6 (track 0=TRUE) + STA DSKSTATUS + JSR DSKLOAD ; LOAD TRACK 0 TO BUFFER + JMP DSKRTS + +STEPIN LDA DSKTRACK + CMP #$4D ; can't go higher than 77 + BEQ DSKRTS + INC DSKTRACK + LDA DSKSTATUS + ORA #$40 ;01000000 - sets bit 6, not on TRACK0 + STA DSKSTATUS + JSR DSKLOAD ; LOAD TRACK N TO BUFFER + JMP DSKRTS + + + + + +************************************************** + + + + +ALTAIRLO DB ALTAIRSCREENDATA + +ALTAIRTABLE DA ALTAIRLO,ALTAIRHI + +ALTAIRSCREENDATA + HEX 66,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,A6,66 + HEX 66,AA,AA,AA,AA,AA,AF,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,AA,66 + HEX 66,FF,F5,FF,F5,FF,F5,F5,F5,FF,F5,FF,FF,F5,FF,F5,FF,F5,FF,F5,FF,F5,FF,FF,F5,FF,FF,FF,F5,FF,FF,FF,F5,FF,FF,FF,F5,FF,FF,66 + HEX 00,00,00,00,00,00,00,00,66,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1 + HEX AA,A1,AA,A1,AA,A1,AA,66,66,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA + HEX AA,AA,AA,AA,AA,AA,AA,66,66,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A,6A + HEX 6A,6A,6A,6A,6A,6A,6A,66,00,00,00,00,00,00,00,00 + + HEX 66,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,66 + HEX 66,AA,25,AA,AA,AA,AA,25,AA,AA,25,AA,AA,25,AA,AA,25,AA,AA,25,AA,AA,25,AA,AA,AA,AA,25,AA,AA,AA,25,AA,AA,AA,AA,AA,AA,AA,66 + HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + HEX 00,00,00,00,00,00,00,00,66,AA,A8,AA,A8,AA,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1,AA,A1 + HEX AA,A1,AA,A1,AA,A1,AA,66,66,AA,A6,AA,AA,AA,AA,A5,AA,AA,A5,AA,AA,A5,AA,AA,A5,AA,AA,A5,AA,AA,A5,AA,AA,AA,AA,A5,AA,AA,AA,A5 + HEX AA,AA,AA,AA,AA,AA,AA,66,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + + HEX 66,AA,AA,AA,AA,AA,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,66 + HEX 66,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,FA,66 + HEX D0,D3,A0,C1,C3,A0,C2,A0,C3,A0,A0,C4,A0,C5,A0,A0,C8,A0,CC,A0,A0,A0,D3,D0,A0,A0,A0,D0,C3,A0,A0,CF,D0,A0,C9,D4,A0,C2,CB,A0 + HEX 00,00,00,00,00,00,00,00,66,AA,AA,AA,AA,AA,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF,AA,AF + HEX AA,AF,AA,AF,AA,AF,AA,66,66,FF,FF,55,FF,FF,55,FF,FF,55,55,55,FF,FF,55,FF,FF,55,FF,55,F5,5F,FF,FF,5F,FF,FF,FF,5F,FF,FF,FF + HEX 5F,FF,FF,FF,5F,FF,FF,66,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + + HEX 66,AA,AA,AA,AA,AA,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,26,AA,66 + HEX 66,FF,55,FF,55,FF,55,FF,FF,FF,55,FF,FF,55,FF,55,FF,55,FF,55,FF,55,FF,F5,5F,F5,FF,F5,5F,F5,FF,55,FF,55,FF,55,FF,55,FF,66 + HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + HEX 00,00,00,00,00,00,00,00,66,AA,AF,AF,AF,FA,AA,A5,AA,A5,AA,A5,AA,A5,AA,A5,AA,A5,AA,A5,AA,A5,AA,A5,AA,A5,AA,A5,AA,A5,AA,A5 + HEX AA,A5,AA,A5,AA,A5,AA,66,66,FF,55,F5,55,FF,55,5F,5F,FF,55,FF,FF,55,F5,55,FF,55,FF,55,F5,5F,FF,55,FF,55,FF,55,FF,55,FF,55 + HEX FF,55,FF,55,FF,55,FF,66,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + HEX 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + + +DISPLAYBYTES DB $00,$00,$00 ; for the "graphical" display + ; PCH/REGD PCL OPCODE +SWITCHBYTES DB $00,$00 + +SWITCHSCRATCH DB $00,$00 ; state of switches. Should all be OFF to start + +SIOSTATUSOUT DB $00 ; probably unnecessary +SIOSTATUSIN DB $81 ; not ready for IO + +SIODATAOUT DB $00 ; Virtual Serial Interface, status buffer, DATA buffer +SIODATAIN DB $00 ; Virtual Serial Interface, status buffer, DATA buffer + +SIOBUFFER DB $00 ; TEMP data + +SIOSTATUSBYTES DB $00,$01 ; status settings for "Have data" and "waiting data" +SIO2STATUSBYTES DB $01,$02 ; has a byte, last byte sent + +; SIO2 +;Receive Data Register Full (RDRF), Bit 0 - Receive Data Register Full indicates +;that received data has been transferred to the Receive Data Reqister. RDRF is +;cleared after a read of the Receive Data Register or by a maiter reset. +;The cleared or empty state indicates that the contents of the Receive Data Register are not current. + +;Transmit Data Register Empty (TDRE), Bit 1 - The Transmit Data Register Empty bit being set high +;indicates that the Transmit Data Register contents have been transferred and that new data may be entered. +;The low state indicates that the register is full and that transm'ission of a new character has not begun +;since the last write data command. + + + + +; PS AC... +LEGEND DB $D0,$D3,$A0,$C1,$C3,$A0,$C2 + DB $A0,$C3,$A0,$A0,$C4,$A0,$C5,$A0 + DB $A0,$C8,$A0,$CC,$A0,$A0,$A0,$D3 + DB $D0,$A0,$A0,$A0,$D0,$C3,$A0,$A0 + DB $CF,$D0,$A0,$C9,$D4,$A0,$C2,$CB +; APPLE 80...MCCREARY +TITLEBAR DB $A0,$C1,$D0,$D0,$CC,$C5,$AD,$B8 + DB $B0,$A0,$C3,$CF,$D0,$D9,$D2,$C9 + DB $C7,$C8,$D4,$A0,$B1,$B9,$B7,$B9 + DB $A0,$C2,$D9,$A0,$C4,$C1,$CE,$CE + DB $A0,$CD,$C3,$C3,$D2,$C5,$C1,$D2,$00 +; "BREAKPOINTS" (BACKWARDS) +BREAKPOINTS DB $D9,$D3,$D4,$CE,$C9,$CF,$D0,$CB + DB $C1,$C5,$D2,$C2 + +BASICBUFFERLO DB BASICBUFFER +BASBUFPNT DB 00 00 +BASICBUFFER DB 00