diff --git a/.gitignore b/.gitignore index 16572a0..4b26227 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.o *.kate-swp *.prg +main diff --git a/Makefile b/Makefile index c9beb47..bb698f1 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ LD = ld65 SP = sp65 all: main.c - $(CL) -t c64 -O -o 64fetch.prg main.c detect.s + $(CL) -t c64 -O -o 64fetch.prg main.c detect.c detectasm.s clean: rm *.o diff --git a/detect.c b/detect.c new file mode 100644 index 0000000..2266bbb --- /dev/null +++ b/detect.c @@ -0,0 +1,219 @@ +#include <6502.h> +#include + +#include "detect.h" +// shoutouts to chironb on github, who i """"borrowed"""" this code from, because i sure as hell wouldn't have been able to do this wizardry, especially not the device section +unsigned char detect_sid(void) { + + // ********** + // DETECT SID + // ********** + + // Taken from the work published here: + + // https://codebase64.org/doku.php?id=base:detecting_sid_type_-_safe_method + + // ;SID DETECTION ROUTINE + + // ;By SounDemon - Based on a tip from Dag Lem. + // ;Put together by FTC after SounDemons instructions + // ;...and tested by Rambones and Jeff. + + // ; - Don't run this routine on a badline + // ; - Won't work in VICE (always detects 6581) unless resid-fp emulation is enabled + + // sei ;No disturbing interrupts + // lda #$ff + // cmp $d012 ;Don't run it on a badline. + // bne *-3 + + // ;Detection itself starts here + // lda #$ff ;Set frequency in voice 3 to $ffff + // sta $d412 ;...and set testbit (other bits doesn't matter) in $d012 to disable oscillator + // sta $d40e + // sta $d40f + // lda #$20 ;Sawtooth wave and gatebit OFF to start oscillator again. + // sta $d412 + // lda $d41b ;Accu now has different value depending on sid model (6581=3/8580=2) + // lsr ;...that is: Carry flag is set for 6581, and clear for 8580. + // bcc model_8580 + // model_6581: + // [...] + + // model_8580: + // [...] + + unsigned char i = 0; // For looping + + unsigned char D41B_before = 0; + unsigned char D41B_after = 0; + + unsigned char one_D41B_after_value = 0; + unsigned char one_D41B_after_frequency = 0; + unsigned char two_D41B_after_value = 0; + unsigned char two_D41B_after_frequency = 0; + unsigned char three_D41B_after_value = 0; + unsigned char three_D41B_after_frequency = 0; + + unsigned char likely_8580 = 0; + unsigned char likely_6581 = 0; + + D41B_before = PEEK(0xD41B); // Record iniital value + + for (i = 0 ; i < 255 ; ++i) { + + POKE(0xD011, 0x0B); // Load 0x0B into 0xD011(53265) - Disable VIC-II + POKE(0xD412, 0xFF); // Load 0xFF into 0xD412 - Set frequency in voice 3 to $ffff + POKE(0xD40E, 0xFF); // Load 0xFF into 0xD40E - ...and set testbit (other bits doesn't matter) in $d012 to disable oscillator + POKE(0xD40F, 0xFF); // Load 0xFF into 0xD40F + POKE(0xD412, 0x20); // Load 0x20 into 0xD412 - Sawtooth wave and gatebit OFF to start oscillator again. + POKE(0xD011, 0x1B); // Load 0x1B into 0xD011(53265) - Enable VIC-II + D41B_after = PEEK(0xD41B); // Record current value + + // check curent value to see if it's sotred + if ( D41B_after == one_D41B_after_value ) { // does the current value equal slot one's value + ++one_D41B_after_frequency; // if so, update the count for this slot + + } else if ( D41B_after == two_D41B_after_value ) { // does the current value equal slot two's value + ++two_D41B_after_frequency; // if so, update the count for this slot + + } else if ( D41B_after == three_D41B_after_value ) { // does the current value equal slot three's value + ++three_D41B_after_frequency; // if so, update the count for this slot + + // if it doesn't match any slots, try to allocate one + } else if ( one_D41B_after_frequency == 0 ) { // if this slot one empty? + one_D41B_after_value = D41B_after; // if so, update the value for this slot and... + ++one_D41B_after_frequency; // ...update the count for this slot + + } else if ( two_D41B_after_frequency == 0 ) { // if this slot one empty? + two_D41B_after_value = D41B_after; // if so, update the value for this slot and... + ++two_D41B_after_frequency; // ...update the count for this slot + + } else if ( three_D41B_after_frequency == 0 ) { // if this slot one empty? + three_D41B_after_value = D41B_after; // if so, update the value for this slot and... + ++three_D41B_after_frequency; // ...update the count for this slot + + } else { + D41B_after = 0; + one_D41B_after_value = 0; + one_D41B_after_frequency = 0; + two_D41B_after_value = 0; + two_D41B_after_frequency = 0; + three_D41B_after_value = 0; + three_D41B_after_frequency = 0; + + }; + + }; + + // Scan for 8580 --> 0x08 & any of 0x33 0x32 + if (one_D41B_after_value == 0x08 || two_D41B_after_value == 0x08 || three_D41B_after_value == 0x08) { + ++likely_8580; + }; + + if (one_D41B_after_value == 0x32 || two_D41B_after_value == 0x32 || three_D41B_after_value == 0x32) { + ++likely_8580; + }; + + // Scan for 6581 --> 0x09 & any of 0x34 0x33 + if (one_D41B_after_value == 0x09 || two_D41B_after_value == 0x09 || three_D41B_after_value == 0x09) { + ++likely_6581; + }; + + if (one_D41B_after_value == 0x34 || two_D41B_after_value == 0x34 || three_D41B_after_value == 0x34) { + ++likely_6581; + }; + + // Codes: + // 1 - 6581 + // 2 - 8580 + // 0 - Undetermined + if (likely_6581 > likely_8580) { + return(1); + } else if (likely_8580 > likely_6581) { + return(2); + } else { + return(0); + }; + + };//end func + + unsigned char detect_cpu(void) { + + unsigned char gotten_cpu = 0; + unsigned char sid_detected = 0; + + // cc65 has a getcpu() function that only tells you if it's a 6502 or others, but not the Commodore specific ones. + // The cc65 online documentation is super old. The GitHub has more up-to-date information. + // https://github.com/cc65/cc65/blob/master/include/6502.h + // + // /* Possible returns of getcpu() */ + // #define CPU_6502 0 + // #define CPU_65C02 1 + // #define CPU_65816 2 + // #define CPU_4510 3 + // #define CPU_65SC02 4 + // #define CPU_65CE02 5 + // #define CPU_HUC6280 6 + // #define CPU_2A0x 7 + // #define CPU_45GS02 8 + + // Detect 6510/8500/8502 --> Address 0x00 should be 47, whereas regular 6502's seem to have 76 there. + // Detect SID to guess that it's a Commodore 64C or not. + // Detect a Commodore 128 --> Address 0xD030 (53296) is always 255 on a non-Commodore 128 6502 CPU. + + gotten_cpu = getcpu(); + sid_detected = detect_sid(); + + if ( getcpu() == 0 ) { + if (PEEK(0) == 47 && PEEK(0xD030) != 255) { return(9 ); // 9 MOS 8502 (Commodore 128) + } else if (PEEK(0) == 47 && sid_detected == 2 ) { return(10); // 10 MOS 8500 (Commodore 64C) + } else if (PEEK(0) == 47 && sid_detected == 1 ) { return(11); // 11 MOS 6510 (Commodore 64) + } else { return(0); // 0 MOS 6502 ??? + }; + } else { return(gotten_cpu); // 255 Unknown + }; + + };//end func + + unsigned char detect_kernal(void) { + // I have discovered a *NEW* byte to look at in any kernal and figure out what it is. I need to re-write this to use this, becuase it'll save a bunch of code! + + // REVIEW - E4AC (58540) - Each Kernal: + // - 901227-01 --> 0x2B + // - 901227-02 --> 0x5C + // - 901227-03 --> 0x81 + // - 251104-01 --> 0x00 + // - 251104-04 --> 0xB3 + // - 901246-01 --> 0x63 + + // C64 R3 58497 _77_ && 58498 79 && 58677 14 + // SX R3 58497 _83_ && 58498 88 && 58677 6 + // J64 R3 58497 _68_ && 58498 79 && 58677 14 + // JSX R3 58497 _68_ && 58498 79 && 58677 6 + + unsigned char kernal_value = 0; + kernal_value = PEEK(0xE4AC); + + switch (kernal_value) { + case 0x2B : return(1); break; // 901227-01 - R1 C64 First Kernal + case 0x5C : return(2); break; // 901227-02 - R2 C64 Early Kernal + case 0x81 : + switch ( PEEK(58497L) ) { + case 68 : + switch (PEEK(58677L)) { + case 14 : return(10); break; // R3 C64 JiffyDOS + case 6 : return(11); break; // R3 SX-64 JiffyDOS + };//end-switch + break; + };//end-switch + return(3); // 901227-03 - R3 C64 Kernal + break; + case 0xB3 : return(4); break; // 251104-04 - R4 SX-64 Common Latest Kernal + case 0x00 : return(5); break; // 251104-01 - R1 SX-64 Rare First Kernal + case 0x63 : return(6); break; // 901246-01 - 4064 Educator 64 --> ? Fair to say this is most similar to a stock R3 901227-03 kernal. From here: "Note that some patches of 901227-03 are included." http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/c64/revisions.txt + default : return(0); break; // Default Unknown Kernal + };//end switch + + }; // end func + diff --git a/detect.h b/detect.h index 154c5de..e69de29 100644 --- a/detect.h +++ b/detect.h @@ -1,2 +0,0 @@ -extern char detectregion(); -extern char detectsid(); diff --git a/detect.s b/detect.s deleted file mode 100644 index 040fd07..0000000 --- a/detect.s +++ /dev/null @@ -1,48 +0,0 @@ -.include "zeropage.inc" - -.global _detectsid -.global _detectregion -.importzp ptr1 - -.code - -; methods grabbed from -_detectsid: - SEI ;No disturbing interrupts - LDX #$00 - LDA #$FF - CMP $D012 ;Don't run it on a badline. - BNE *-3 - ;Detection itself starts here - LDA #$FF ;Set frequency in voice 3 to $ffff - STA $D412 ;...and set testbit (other bits don't matter) in VCREG3 ($d412) to disable oscillator - STA $D40E - STA $D40F - LDA #$20 ;Sawtooth wave and gatebit OFF to start oscillator again. - STA $D412 - LDA $D41B ;Accu now has different value depending on sid model (6581=3/8580=2) - RTS - -_detectregion: - LDX #$00 - SEI -w0: LDA $D012 -w1: CMP $D012 - BEQ w1 - BMI w0 - AND #$03 - CMP #$03 - BNE detectionDone ; done for NTSC - TAY -countCycles: - INX - LDA $D012 - BPL countCycles - CPX #$5E ; VICE values: PAL-N=$6C PAL=$50 - ; so choose middle value $5E for check - BCC isPAL - INY ; is PAL-N -isPAL: - TYA -detectionDone: - RTS diff --git a/detectasm.s b/detectasm.s new file mode 100644 index 0000000..a48f793 --- /dev/null +++ b/detectasm.s @@ -0,0 +1,29 @@ +; TODO: Convert to C + +.global _detect_region + +.code + +_detect_region: + SEI + LDX #$00 +w0: LDA $D012 +w1: CMP $D012 + BEQ w1 + BMI w0 + AND #$03 + CMP #$03 + BNE detectionDone ; done for NTSC + TAY +countCycles: + INX + LDA $D012 + BPL countCycles + CPX #$5E ; VICE values: PAL-N=$6C PAL=$50 + ; so choose middle value $5E for check + BCC isPAL + INY ; is PAL-N +isPAL: + TYA +detectionDone: + RTS diff --git a/main.c b/main.c index d64d6bb..d81be8a 100644 --- a/main.c +++ b/main.c @@ -3,26 +3,30 @@ #include #include #include -#include "detect.h" +#include "main.h" + void main() { - char sidmodel[5]; - char region[14]; + char cpu[11]; + char kernal[10]; char key; - char revision[11]; + char region[14]; + char sidmodel[5]; + char prev289 = PEEK(0x289); + char prev28A = PEEK(0x28A); POKE(0x289,1); - POKE(0x28a,127); + POKE(0x28A,0x7F); clrscr(); - switch (detectsid()) { - case 2: - strcpy(sidmodel, "6581"); + switch (detect_sid()) { + case 1: + strcpy(sidmodel, "MOS 6581"); break; - case 3: - strcpy(sidmodel, "8580"); + case 2: + strcpy(sidmodel, "MOS 8580"); break; default: strcpy(sidmodel, "????"); } - switch (detectregion()) { + switch (detect_region()) { case 1: strcpy(region, "Old NTSC"); break; @@ -38,32 +42,55 @@ void main() { default: strcpy(region, "????"); } - switch (PEEK(65408L)) { - case 170: - strcpy(revision, "Revision 1"); + switch (detect_kernal()) { + case 1: + strcpy(kernal, "901227-01"); break; - case 0: - strcpy(revision, "Revision 2"); + case 2: + strcpy(kernal, "901227-02"); break; case 3: - strcpy(revision, "Revision 3"); + strcpy(kernal, "901227-03"); + break; + case 4: + strcpy(kernal, "251104-04"); + break; + case 5: + strcpy(kernal, "251104-01"); + break; + case 6: + strcpy(kernal, "901246-01"); + break; + case 10: + case 11: + strcpy(kernal, "JiffyDOS"); + break; + default: + strcpy(kernal, "Unknown"); + } + switch (detect_cpu()) { + case 0: + strcpy(cpu, "MOS 6502!?"); + break; + case 9: + strcpy(cpu, "MOS 8502"); break; - case 67: - strcpy(revision, "SX-64"); + case 10: + strcpy(cpu, "MOS 8500"); break; - case 100: - strcpy(revision, "4064"); + case 11: + strcpy(cpu, "MOS 6510"); break; default: - strcpy(revision, "Unknown"); + strcpy(cpu, "????"); } printf("\n \x9A \xAC\x12\xBE \xBC\x92\x05 64Fetch\n"); printf(" \x9A \x12\xBE \x92\x05 By Korbo\n"); printf(" \x9A \x12\xBE \x92\n"); printf(" \xAC\x12 \xA2\x92 \xBC\xA2\xA2\xA2\xA2\xA2\x05 SID: %s\n", sidmodel); printf(" \x9A\x12\xBE \x92\xA1 \x12 \x92\xBE\x05 VIC: %s\n", region); - printf(" \x9A\x12 \x92 \x12 \x92\xBE\x05 KERNAL: %s\n", revision); - printf(" \x9A\x12 \x92 \x81\xA2\xA2\xA2\n"); + printf(" \x9A\x12 \x92 \x12 \x92\xBE\x05 KERNAL: %s\n", kernal); + printf(" \x9A\x12 \x92 \x81\xA2\xA2\xA2\x05 CPU: %s\n", cpu); printf(" \x9A\x12 \x92\xBB \x81\x12 \xBC\x92\n"); printf(" \x9A\x12\xE1 \xBC\x92 \x81\x12 \xBC\x92\n"); printf(" \x9A \x12 \x92\xA2\xA2\x12\xBE\x92\n"); @@ -79,7 +106,7 @@ void main() { while(key != 0x0D) { key = cgetc(); } - POKE(0x289,10); - POKE(0x28a,0); + POKE(0x289,prev289); + POKE(0x28a,prev28A); } diff --git a/main.h b/main.h new file mode 100644 index 0000000..452fd01 --- /dev/null +++ b/main.h @@ -0,0 +1,4 @@ +extern unsigned char detect_cpu(); +extern unsigned char detect_region(); +extern unsigned char detect_kernal(); +extern unsigned char detect_sid();