From 51aec75ce7ac5ab81c04d327b844e6891531c02d Mon Sep 17 00:00:00 2001 From: "Marc A. Golombeck" Date: Sun, 26 May 2019 23:20:31 +0200 Subject: [PATCH] Create hw-detect.s --- hw-detect.s | 860 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 860 insertions(+) create mode 100644 hw-detect.s diff --git a/hw-detect.s b/hw-detect.s new file mode 100644 index 0000000..8475588 --- /dev/null +++ b/hw-detect.s @@ -0,0 +1,860 @@ +******************************** +* * +* Machine Detection * +* * +* Routines * +* * +* BY MARC GOLOMBECK * +* * +* VERSION 1.00 / 26.04.2019 * +******************************** +* + DSK detect + MX %11 + ORG $901 ; routine starts at $0901 +* +HOME EQU $FC58 ; CLEAR SCREEN +COUT EQU $FDED ; PRINT CHARACTER +KYBD EQU $C000 ; READ KEYBOARD +STROBE EQU $C010 ; CLEAR KEYBOARD +BELL EQU $FBDD ; RING BELL +WAIT EQU $FCA8 ; WAIT A BIT +PREAD EQU $FB1E ; switch to LORES +VERTBLANK EQU $C019 ; vertical blanking -> available only IIe and above +MEMCOPY EQU $FE2C ; monitor routine for copying RAM +WRITERAM EQU $C081 ; read ROM write RAM - toggle 2 times +READROM EQU $C082 ; read ROM no write - toggle 1 time +READWRITE EQU $C083 ; read & write RAM - toggle 2 times +READRAM EQU $C080 ; read RAM no write - toggle 1 time +* +bMB EQU $2078 ; MockingBoard available? ($00/No | $01 Yes) +bMachine EQU $2079 ; auto detect Apple II machine type +bMem EQU $207A ; 128k? ($00 No | $78 Yes) +bZC EQU $207B ; ZIPchip installed? ($00/No | $01 Yes) +bFC EQU $207C ; FastChip installed? ($00/No | $01 Yes) +bLC EQU $207D ; Language Card available? ($00/No | $01 Yes) +bMBSlot EQU $207E ; slot of MockingBoard ($01..$07) +bRefresh EQU $207F ; byte REFRESH RATE ($00/50Hz | $01/60Hz) +b65C02 EQU $20F8 ; byte CPU ($00/6502 | $01/65C02 | $FF/65816) +bEmu EQU $20F9 ; emulator detection ($00/No | $01 Yes) +* +chkMEM EQU $0100 ; adress of AUX mem checking routine +dest EQU $F8 ; + $F9 +MB_ADDRL EQU $06 +MB_ADDRH EQU $07 +TICKS EQU $09 +charFLAG EQU $FF ; only uppercase letters? +* +* +* FastChip constants +* +FC_UNLOCK EQU $6A ; FastChip unlock value +FC_LOCK EQU $A6 ; FastChip lock value +FC_LOCK_REG EQU $C06A ; FastChip lock register +FC_EN_REG EQU $C06B ; FastChip enable register +FC_SPD_REG EQU $C06D ; FastChip speed register +* +INIT SEI ; just to be sure... + JSR DETECTA2 ; get machine type + STA $C000 ; 80STOREOFF + STA $C008 ; zero Page = Main (+ $FXXX MAIN) +* + JSR COPYAUX ; copy main program to AUX-memory + JSR COPYROM ; copy MONITOR to language card + JMP chkMEM ; jump to short routine in Stack for checking AUX MEM size + JSR DETECTCPU + JSR DETECTREFRESH +* + JSR DETECTZIP ; detect and disable a ZIPchip + JSR DETECTFC ; detect FastChip and set to 1 MHz + JSR DETECTEMU ; detect possible emulator first + JSR DETECTLC ; can we also detect a language card? + JSR MB_DETECT ; detect MB-slot + JSR HOME ; clear screen + JSR PRTRES ; print detection results on screen +* + RTS + +* +* +************************************************* +* COPY PROGRAM TO AUX MEMORY * +************************************************* +* +COPYAUX + STA $C002 ; read MAIN + STA $C005 ; write AUX + LDA #$09 ; set start adress HI-byte + STA dest+1 ; for page copy + LDA #0 + STA dest ; LO-byte +* +cpAUXlp2 LDY #0 ; loop over Y +cpAUXlp1 LDA (dest),Y ; read from MAIN memory + STA (dest),Y ; store to AUX memory at same address! + INY + BNE cpAUXlp1 + INC dest+1 ; increase HI-byte +1 + LDA dest+1 ; must include the MB-playing routine in code copy! + CMP #$0d ; HI-Byte = $14? Copy until reaching $13FF! + BNE cpAUXlp2 ; no, copy next page + STA $C004 ; write MAIN + + LDA #>CODE + STA dest+1 + LDA # copy MEM chk routine to Stack area + STA dest + LDY #0 + STY bMem ; init result byte +cpSTACK LDA (dest),Y + STA chkMEM,Y + INY + CPY #15 + BNE cpSTACK +* + RTS +* +* +* copy monitor ROM +* +COPYROM LDY #$F8 ; copy Monitor-ROM to Language Card + STY $3D + STY $43 + LDY #$FF + STY $3E + STY $3F + INY + STY $3C + STY $42 + LDA WRITERAM ; toggle Language Card RAM for writing + LDA WRITERAM + JSR MEMCOPY + LDA READROM ; toggle Language Card off + RTS + +*============================================================================= +* +* detect slot with MockingBoard +* +MB_DETECT LDA #0 + STA MB_ADDRL +* +MB_DET_lp LDA #$07 ; we start in slot 7 ($C7) and go down to 0 ($C0) + STA bMBSlot ; slot with MB + ORA #$C0 ; make it start with C + STA MB_ADDRH + LDY #04 ; $CX04 + LDX #02 ; 2 tries? +MB_CHK_CYC LDA (MB_ADDRL),Y ; timer 6522 (Low Order Counter) +* ; count down + STA TICKS ; 3 cycles + LDA (MB_ADDRL),Y ; + 5 cycles EQU 8 cycles +* ; between the two accesses to the timer + SEC + SBC TICKS ; subtract to see if we had 8 cycles (accepted range 7-9) + CMP #$f8 ; -8 + BEQ DEC_X + CMP #$F9 ; -7 - range is necessary if FastChip is installed + BEQ DEC_X + CMP #$F7 ; -9 + BNE MB_NOT_SLOT +DEC_X DEX ; decrement, try one more time + BNE MB_CHK_CYC ; loop detection + INX ; Mockingboard found (XEQU1) +DONE_DET STX bMB ; store result to bMB + RTS ; return +* +MB_NOT_SLOT DEC MB_DET_lp+1 ; decrement the "slot" (self_modify) + BNE MB_DET_lp ; loop down to one + LDX #00 + BEQ DONE_DET + +*============================================================================= +* +* detect type of Apple 2 computer +* +DETECTA2 + LDA #$FF + STA charFLAG ; allow lower case output + LDA $FBB3 + CMP #$06 ; IIe/IIc/IIGS = 06 + BEQ checkII ; if not II ($38) or II+ ($EA) +_G22PLUS STA bMachine ; save $38 or $EA as machine byte + LDA #%11011111 ; convert lowercase chars to uppercase + STA charFLAG + RTS +* +checkII LDA $FBC0 ; detect IIc + BEQ _G2C ; 0 = IIc / Other = no IIc +* + SEC ; IIgs or IIe ? + JSR $FE1F ; test for GS + BCS _G2E ; if carry flag is set -> IIE +* + LDA #$FF ; IIGS -> $FF + STA bMachine +*============================================================================= +* +* condition some IIgs settings +* + LDA $C036 ; put IIgs in 8-bit-mode + AND #$7F + STA $C036 ; slow speed +* + LDA $C034 ; + AND #$F0 + STA $C034 ; black border +* + LDA $C022 + AND #$F0 ; bit 0-3 at 0 = background black + ORA #$F0 ; bit 7-4 at 1 = text white + STA $C022 ; background black/text white + RTS +* +_G2E LDA #$7F ; IIE -> $7F + STA bMachine + RTS +* +_G2C STA bMachine ; IIc -> $00 + RTS +*============================================================================= +* +* detect CPU type +* +DETECTCPU + LDA #00 + BRA _is65C02 ; results in a BRA +4 if 65C02/65816 or NOPs if 6502 + BEQ _contD ; a 6502 drops through directly to the BEQ here +_is65C02 INC A ; 65C02/65816 arrives here +* ; some 65816 code here + XBA ; .byte $eb, put $01 in B accu -> equals a NOP for 65C02 + DEC A ; .byte $3a, A=$00 if 65C02 + XBA ; .byte $eb, get $01 back if 65816 + INC A ; .byte $1a, make $01/$02 +_contD STA b65C02 + RTS + +*============================================================================= +* +* detect and disable a ZIPchip +* +DETECTZIP + LDA #$5A ; unlock ZC + STA $C05A + STA $C05A + STA $C05A + STA $C05A + + LDX #$00 +CACHE LDA ALTER,X ; put altering part of the code in the cache! + INX + BNE CACHE + +ALTER LDA $C05C ; Get the slot delay status + EOR #$FF ; Flip it + STA $C05C ; Save it + CMP $C05C ; Correct? + BNE NOZIP ; No, ZIP CHIP not found. + + EOR #$FF ; Get back old status + STA $C05C ; Save it + CMP $C05C ; Correct? + BNE NOZIP ; No, ZIP CHIP not found. + + LDA #$00 ; other value as $5A or $A5 + STA $C05A ; will disable ZC + LDA #$A5 ; lock ZC + STA $C05A + LDA #01 + STA bZC + RTS + +NOZIP LDA #00 + STA bZC + RTS +*============================================================================= +* +* detect a FastChip and set speed to 1 MHz +* +DETECTFC LDA bMachine ; get machine type byte + LDX #$00 + CMP #$7F ; Apple IIe + BEQ chk_slot + BNE not_found +chk_slot LDY #$04 ; loop 4 times + LDA #FC_UNLOCK ; load the unlock value +unlock_lp STA FC_LOCK_REG ; store in lock register + DEY + BNE unlock_lp + LDA #$00 ; MegaAudio check + STA FC_EN_REG ; enable the Fast Chip + LDY FC_EN_REG ; bit 7 will be high when enabled + CPY #$80 + BNE not_found +found LDA #$80 ; reset speed register + STA FC_SPD_REG + LDA #$09 ; set FC speed to 1.10 MHz + STA FC_SPD_REG ; necessary for correct MB-detection! + LDA #FC_LOCK + STA FC_LOCK_REG ; lock the registers again + LDA #$01 + STA bFC + RTS +not_found TXA + STA bFC + RTS +*============================================================================= +* +* detect Language Card +* +DETECTEMU + LDA #0 + STA bEmu ; set value to "real wood" + LDX #0 ; read PDL(0) + JSR PREAD + STY PDL0 ; store value + LDX #1 ; read PDL(0) + JSR PREAD + STY PDL1 ; store value + LDX #2 ; read PDL(0) + JSR PREAD + STY PDL2 ; store value + LDX #3 ; read PDL(0) + JSR PREAD + STY PDL3 ; store value +* + LDA #0 + STA PDL0+1 + STA PDL1+1 + STA PDL2+1 + STA PDL3+1 + + CLC + LDA PDL0 ; adding all read PDL values + ADC PDL1 ; emulators mainly return #127 for PDL-read + STA PDLsum ; real wood returns 255 if no paddle is connected + LDA PDL0+1 ; or anything else (but mostly not 127 for all values) + ADC PDL1+1 + STA PDLsum+1 + CLC + LDA PDLsum ; adding all read PDL values + ADC PDL2 ; emulators mainly return #127 for PDL-read + STA PDLsum + LDA PDLsum+1 + ADC PDL2+1 + STA PDLsum+1 + CLC + LDA PDLsum ; adding all read PDL values + ADC PDL3 ; emulators mainly return #127 for PDL-read + STA PDLsum + LDA PDLsum+1 + ADC PDL3+1 + STA PDLsum+1 + + LDA PDLsum+1 + CMP #1 + BEQ Pchk1 ; check for 508 as magic number = 4*127 + JMP Pchk3 +Pchk1 LDA PDLsum + CMP #252 + BEQ Pchk2 + JMP Pchk3 +Pchk2 ; magic number found + INC bEmu ; bEmu = 1 + RTS +* +Pchk3 LDA PDL0 ; second check if first check fails + CMP PDL1 ; PDL(0) = PDL(1)? + BEQ Pchk3a ; yes -> check for other two values + RTS ; values are different, likely real wood +Pchk3a LDA PDL0 ; open gate? (=255) is likely to be real wood here with no joystick connected + CMP #255 + BNE Pchk3b + RTS +Pchk3b LDA PDL2 + CMP PDL3 + BEQ Pchk2 ; assume emulator + RTS + +PDL0 DS 2 ; paddle read values +PDL1 DS 2 +PDL2 DS 2 +PDL3 DS 2 +PDLsum DS 2 +*============================================================================= +* +* detect Emulator +* +DETECTLC + LDA $C083 ; turn on LC + LDA $C083 + LDA $D000 + INC $D000 + + CMP $D000 + BEQ noLCARD + DEC $D000 + LDA #1 ; language card positive + STA bLC ; -> might be an emulator! + JMP exitEMU +noLCARD LDA #0 + STA bLC + LDA bEmu ; emulator detected? + BNE exitEMU + LDA #2 ; can't tell if running in an emulator -> sorry! + STA bEmu +exitEMU LDA $C081 ; turn off LC + RTS +*============================================================================= +* +* detect screen refresh rate +* +DETECTREFRESH + LDA bMachine + BEQ Refresh_IIC ; IIc -> another refresh detection method is necessary + CMP #$EA + BEQ _badguy ; II+ -> no detection possible + CMP #$38 + BEQ _badguy ; II -> no detection possible + +_L1 CMP VERTBLANK ; works with IIGS/IIE + BPL _L1 ; wait until the end of the vertical blank + +_L2 CMP VERTBLANK ; synchronizing counting algorithm + BMI _L2 ; wait until the end of the complete display -> start of vertical blanking +_BP3 INC COUNTREF ; 6 increment counter + + LDX #$09 ; wait for a certain number of cycles +_WL3 DEX ; + BNE _WL3 ; = 46 cycles + ; + 6 + 3 + 3 + 4 + 3 = 65 ! + LDA bMachine ; 3 + LDA bMachine ; 3 + CMP VERTBLANK ; 4 + Bpl _BP3 ; 3 -> repeat and increment counter until VBL is done + + LDA COUNTREF + CMP #72 ; >= 72 equals 50 HZ (120*65 cycles of VBL) + BCS _GO3 + LDA #01 ; 60HZ (VBL = 70x65 cycles) + JMP _GO4 +_GO3 LDA #00 ; 50HZ (VBL = 120x65 cycles) +_GO4 STA bRefresh + RTS +* +_badguy LDA #$FF ; system without VBL-signal is a bad guy + STA bRefresh + RTS +* +Refresh_IIC ; specific treatment for Apple IIc + STA $C070 + STA $C07F + STA $C05B +_l1 LDA $C019 ; preparation for the beginning of VBL + bpl _l1 + STA $C070 + STA $C07F + STA $C05B ; enable VBL interrupt + +_BP2 INC COUNTREF ; 6 increment counter + + LDX #$09 ; +_WL1 DEX ; + BNE _WL1 ; = 46 cycles + ; + 6 + 6 + 4 + 3 = 65 ! + NOP + NOP + NOP ; 3*2 = 6 additional cycles + + LDA $C019 ; waiting for the next VBL to begin + bpl _BP2 ; 3 -> wait for vblflag = 1 + + STA $C058+2 ; disable VBL int. Contains a complete VBL + one display. Exit on the beginning of + LDA COUNTREF ; the next VBL gives = 192+70+(50) = $138 or ($106) hence $38 or $06 + CMP #$10 ; >= 16 hence 50 HZ + BCS _GO1 + LDA #01 ; 60HZ + JMP _GO2 +_GO1 LDA #00 ; 50HZ +_GO2 STA bRefresh + RTS +COUNTREF DS 1 + + +*============================================================== +* +* print detection results on screen +* +PRTRES LDA #0 ; set cursor position + STA $25 + JSR LFEED + + LDA #6 ; HTAB 6 + STA $24 + LDX #T_APPLE + JSR PRINT + JSR LFEED + JSR LFEED + LDA #7 ; HTAB 7 + STA $24 + + LDX #T_MACH + JSR PRINT + + LDA bMachine + BNE comp1 ; //c = $00? + LDX #T_COMP3 + JSR PRINT + JMP NEXT1 + +comp1 CMP #$7F ; //e? + BNE comp2 + LDX #T_COMP1 + JSR PRINT + JMP NEXT1 + +comp2 CMP #$FF ; IIgs? + BNE comp3 + LDX #T_COMP2 + JSR PRINT + JMP NEXT1 + +comp3 CMP #$38 ; II? + BNE comp4 + LDX #T_COMP4 + JSR PRINT + JMP NEXT1 + +comp4 CMP #$EA ; II? + BNE comp5 + LDX #T_COMP5 + JSR PRINT + JMP NEXT1 + +comp5 LDX #T_COMP6 + JSR PRINT + +NEXT1 + JSR LFEED ; print CPU type + LDA #7 ; HTAB 7 + STA $24 + LDX #T_CPU + JSR PRINT + + LDA b65C02 + CMP #2 ; 65816 in any machine setting! + BEQ _s2_cpu + LDA b65C02 + BEQ _s1_cpu ; 0 (6502) + BMI _s2_cpu ; >$7F (65816 or 65C802) + LDX #T_CPU2 + JSR PRINT + JMP NEXT1a +_s1_cpu + LDX #T_CPU1 + JSR PRINT + JMP NEXT1a +_s2_cpu ; CPU is 65816 or 65C802 + LDA bMachine + CMP #$FF + BEQ cpu816 ; is 65816 + LDX #T_CPU4 + JSR PRINT + JMP NEXT1a +cpu816 + LDX #T_CPU3 + JSR PRINT + +NEXT1a JSR LFEED ; output RAM + LDA #7 ; HTAB 7 + STA $24 + LDX #T_RAM + JSR PRINT + + LDA bMem + CMP #$78 ; $78 is flag byte for 128k! + BNE not128 ; 64 or 48k + LDA bMachine ; check for Apple ][ and ][+ -> no 128k supported + CMP #$38 + BEQ not128 + CMP #$EA + BEQ not128 + + LDX #T_128 + JSR PRINT + JMP NEXT1b + +not128 LDA bLC + BEQ only48 + LDX #T_64 + JSR PRINT + JMP NEXT1b + +only48 LDX #T_48 + JSR PRINT + +NEXT1b JSR LFEED ; output Language Card + LDA #7 ; HTAB 7 + STA $24 + LDX #T_LANG + JSR PRINT + + LDA bLC + BEQ noLC + LDX #T_YES + JSR PRINT + JMP NEXT2 + +noLC LDX #T_NO + JSR PRINT + + + +NEXT2 JSR LFEED ; print refresh rate + LDA #7 ; HTAB 7 + STA $24 + LDX #T_REFRESH + JSR PRINT + LDA bRefresh + BMI _s2_rate + BEQ _s1_rate + LDX #T_RATE2 + JSR PRINT + JMP NEXT3 +_s1_rate + LDX #T_RATE1 + JSR PRINT + JMP NEXT3 +_s2_rate + LDX #T_RATE3 + JSR PRINT + +NEXT3 JSR LFEED ; output MockingBoard detection results + LDA #7 ; HTAB 7 + STA $24 + LDX #T_MOCK + JSR PRINT + + LDA bMB + BEQ noMB ; no MB detected + LDX #T_SLOT + JSR PRINT + LDA bMBSlot ; get slot no and convewrt to ASCII-value + CLC + ADC #$B0 + JSR COUT ; output ASCII-value! + JMP NEXT4 + +noMB LDX #T_NONE + JSR PRINT + +NEXT4 JSR LFEED ; output FastChip detection + LDA #7 ; HTAB 7 + STA $24 + LDX #T_FC + JSR PRINT + + LDA bFC + BEQ noFC ; no FC detected + + LDX #T_YES + JSR PRINT + JMP NEXT5 + +noFC LDX #T_NO + JSR PRINT + +NEXT5 JSR LFEED ; output ZipChip detection result + LDA #7 ; HTAB 7 + STA $24 + LDX #T_ZC + JSR PRINT + + LDA bZC + BEQ noZC ; no ZC detected + + LDX #T_YES + JSR PRINT + JMP NEXT6 + +noZC LDX #T_NO + JSR PRINT + +NEXT6 JSR LFEED ; output Emulator detection + JSR LFEED + LDA #7 ; HTAB 7 + STA $24 + LDX #T_EMU + JSR PRINT + + LDA bEmu + BEQ pnoEmu + + CMP #1 + BEQ pyesEmu + + LDX #T_UNCLEAR + JSR PRINT + JMP prtSHK + +pnoEmu LDX #T_RATE3 + JSR PRINT + JMP prtSHK + +pyesEmu LDX #T_POS + JSR PRINT + + +prtSHK JSR LFEED ; output copyright notice + JSR LFEED + JSR LFEED + LDA #4 ; HTAB 4 + STA $24 + LDX #T_SHACK + JSR PRINT + + +resRTS RTS +* +* +* text output routines +* +LFEED LDA #$8D ; print a line feed + JSR COUT + RTS +* +PRINT ; x = LO-Byte Text, y = HI-Byte Text +!zone + STX ba+1 + STY ba+2 + + LDX #00 +ba LDA $1000,X + BEQ rtsPRINT + CMP #$E1 ; "a" char in lower case range? + BCC doCOUT ; no -> direct output + CMP #$FB ; "z" + BCS doCOUT ; no -> direct output + AND charFLAG ; lowercase conversion if necessary +doCOUT JSR COUT ; output ASCII on screen + INX + BNE ba +rtsPRINT RTS + +*============================================================================= +* +* AUX-memory detection code +* +CODE HEX 8D03C0AD01098D02 + HEX C08D7A204C1409 +* +* +* text output data +* +T_APPLE ASC "* Hardware Autodetection *" + HEX 00 +T_SHACK ASC "* V.1.00 by 8-BIT-SHACK 2019 *" + HEX 00 +T_MACH ASC "Machine: " + HEX 00 +T_COMP1 ASC "Apple //e" + HEX 00 +T_COMP2 ASC "Apple IIgs" + HEX 00 +T_COMP3 ASC "Apple //c" + HEX 00 +T_COMP4 ASC "Apple ][" + HEX 00 +T_COMP5 ASC "Apple ][+" + HEX 00 +T_COMP6 ASC "Other" + HEX 00 +T_RAM ASC "RAM: " + HEX 00 +T_48 ASC "48kB " + HEX 00 +T_64 ASC "64kB (LC) " + HEX 00 +T_128 ASC ">= 128kB " + HEX 00 +T_MOCK ASC "MockingBoard: " + HEX 00 +T_NONE ASC "None " + HEX 00 +T_SLOT ASC "Slot #" + HEX 00 +T_FC ASC "FastChip: " + HEX 00 +T_YES ASC "Yes" + HEX 00 +T_ZC ASC "ZIPChip: " + HEX 00 +T_NO ASC "No" + HEX 00 +T_CPU ASC "CPU-Type: " + HEX 00 +T_REFRESH ASC "Refresh Rate: " + HEX 00 +T_LANG ASC "Language Card: " + HEX 00 +T_EMU ASC "Emulator: " + HEX 00 +T_CPU1 ASC "6502" + HEX 00 +T_CPU2 ASC "65C02" + HEX 00 +T_CPU3 ASC "65816" + HEX 00 +T_CPU4 ASC "65C802" + HEX 00 +T_RATE1 ASC "50Hz" + HEX 00 +T_RATE2 ASC "60Hz" + HEX 00 +T_RATE3 ASC "Not detected!" + HEX 00 +T_POS ASC "Detected!" + HEX 00 +T_UNCLEAR ASC "Unclear..." + HEX 00 +* +* end of file +*