소스 검색

SuperCIC pair mode. TODO: disable pair mode (key)

ikari 14 년 전
부모
커밋
14b82b8808
2개의 변경된 파일779개의 추가작업 그리고 14개의 파일을 삭제
  1. 715 0
      cic/supercic/supercic-key.asm
  2. 64 14
      cic/supercic/supercic-lock.asm

+ 715 - 0
cic/supercic/supercic-key.asm

@@ -0,0 +1,715 @@
+    #include <p12f629.inc>
+processor p12f629
+
+; ---------------------------------------------------------------------
+;   SNES CIC clone for PIC Microcontroller (key mode only)
+;
+;   Copyright (C) 2010 by Maximilian Rehkopf (ikari_01) <otakon@gmx.net>
+;   This software is part of the sd2snes project.
+;
+;   This program is free software; you can redistribute it and/or modify
+;   it under the terms of the GNU General Public License as published by
+;   the Free Software Foundation; version 2 of the License only.
+;
+;   This program is distributed in the hope that it will be useful,
+;   but WITHOUT ANY WARRANTY; without even the implied warranty of
+;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;   GNU General Public License for more details.
+;
+;   You should have received a copy of the GNU General Public License
+;   along with this program; if not, write to the Free Software
+;   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+;
+; ---------------------------------------------------------------------
+;
+;   pin configuration: (cartridge pin) [key CIC pin]
+;
+;                       ,---_---.
+;      +5V (27,58) [16] |1     8| GND (5,36) [8]
+;      CIC clk (56) [6] |2     7| CIC data i/o 0 (55) [2]
+;            status out |3     6| CIC data i/o 1 (24) [1]
+;                    nc |4     5| CIC slave reset (25) [7]
+;                       `-------'
+;
+;
+;   Status out can be connected to a LED. It indicates:
+;
+;   state                   | output
+;  -------------------------+----------------------------
+;   OK or no lock CIC       | high
+;   error                   | low
+;   SuperCIC pair mode      | high-low alternating @1kHz
+;
+;   In case lockout fails, the region is switched automatically and
+;   will be used after the next reset.
+;
+;   memory usage:
+;
+;   0x20		buffer for seed calc and transfer
+;   0x21 - 0x2f		seed area (lock seed)
+;   0x30		buffer for seed calc
+;   0x31 - 0x3f		seed area (key seed; 0x31 filled in by lock)
+;   0x40 - 0x41		buffer for seed calc
+;   0x4d		buffer for eeprom access
+;   0x4e		loop variable for longwait
+;   0x4f		loop variable for wait
+;
+; ---------------------------------------------------------------------
+
+
+; -----------------------------------------------------------------------
+    __CONFIG _EC_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF
+
+; -----------------------------------------------------------------------
+; code memory
+	org	0x0000
+	nop
+	nop
+	nop
+	goto	init
+isr
+	org	0x0004
+	bcf	INTCON, 1	; clear interrupt cause
+	bcf	GPIO, 0
+	bcf	GPIO, 1
+	bsf	GPIO, 4		; LED on
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	bsf	INTCON, 7	; re-enable interrupts (ISR will continue as main)
+	goto	main
+init
+	org 0x0010
+	banksel GPIO
+	clrf	GPIO
+	movlw	0x07	; GPIO2..0 are digital I/O (not connected to comparator)
+	movwf	CMCON
+	movlw	0x90	; global enable interrupts + enable external interrupt
+	movwf	INTCON
+	banksel	TRISIO
+	movlw	0x2d	; in out in in out in
+	movwf	TRISIO
+	movlw	0x24	; pullups for reset+clk to avoid errors when no CIC in host 
+	movwf	WPU
+	movlw	0x00	; 0x80 for global pullup disable
+	movwf	OPTION_REG
+	
+	banksel GPIO
+	bsf 	GPIO, 4	; LED on
+idle
+	goto	idle	; wait for interrupt from lock
+
+main
+	banksel	TRISIO
+	bsf	TRISIO, 0
+	bcf	TRISIO, 1
+	banksel	GPIO
+; --------INIT LOCK SEED (what the lock sends)--------
+	movlw	0xb
+	movwf	0x21
+	movlw	0x1
+	movwf	0x22
+	movlw	0x4
+	movwf	0x23
+	movlw	0xf
+	movwf	0x24
+	movlw	0x4
+	movwf 	0x25
+	movlw	0xb
+	movwf 	0x26
+	movlw	0x5
+	movwf 	0x27
+	movlw	0x7
+	movwf 	0x28
+	movlw	0xf
+	movwf 	0x29
+	movlw	0xd
+	movwf 	0x2a
+	movlw	0x6
+	movwf 	0x2b
+	movlw	0x1
+	movwf 	0x2c
+	movlw	0xe
+	movwf 	0x2d
+	movlw	0x9
+	movwf 	0x2e
+	movlw	0x8
+	movwf 	0x2f
+	
+; --------INIT KEY SEED (what we must send)--------
+	banksel	EEADR		; D/F411 and D/F413
+	clrf	EEADR		; differ in 2nd seed nibble
+	bsf	EECON1, RD	; of key stream,
+	movf	EEDAT, w	; restore saved nibble from EEPROM
+	banksel GPIO
+	movwf	0x32
+	movlw	0xa
+	movwf	0x33
+	movlw	0x1
+	movwf	0x34
+	movlw	0x8
+	movwf 	0x35
+	movlw	0x5
+	movwf 	0x36
+	movlw	0xf
+	movwf 	0x37
+	movlw	0x1
+	movwf 	0x38
+	movwf 	0x39
+	movlw	0xe
+	movwf 	0x3a
+	movlw	0x1
+	movwf 	0x3b
+	movlw	0x0
+	movwf 	0x3c
+	movlw	0xd
+	movwf 	0x3d
+	movlw	0xe
+	movwf 	0x3e
+	movlw	0xc
+	movwf 	0x3f
+	
+; --------wait for stream ID--------
+	movlw	0xb5
+	call	wait
+	clrf	0x31		; clear lock stream ID
+
+; --------lock sends stream ID. 15 cycles per bit--------
+;	bsf	GPIO, 0		; (debug marker)
+;	bcf	GPIO, 0		; 
+	btfsc	GPIO, 0		; check stream ID bit
+	bsf	0x31, 3		; copy to lock seed
+	movlw	0x2		; wait=3*W+5
+	call	wait		; burn 11 cycles
+	nop
+	nop
+
+;	bsf	GPIO, 0
+;	bcf	GPIO, 0
+	btfsc	GPIO, 0		; check stream ID bit
+	bsf	0x31, 0		; copy to lock seed
+	movlw	0x2		;
+	call	wait		; burn 11 cycles
+	nop
+	nop
+
+;	bsf	GPIO, 0
+;	bcf	GPIO, 0
+	btfsc	GPIO, 0		; check stream ID bit
+	bsf	0x31, 1		; copy to lock seed
+	movlw	0x2		;
+	call	wait		; burn 11 cycles
+	nop
+	nop
+
+;	bsf	GPIO, 0
+;	bcf	GPIO, 0
+	btfsc	GPIO, 0		; check stream ID bit
+	bsf	0x31, 2		; copy to lock seed
+	banksel	TRISIO
+	bcf	TRISIO, 0
+	bsf	TRISIO, 1
+	banksel	GPIO
+	nop
+	movlw	0x27		; "wait" 1
+	call	wait		; wait 121
+; --------main loop--------
+loop	
+	movlw	0x1
+loop0
+	addlw	0x30	; key stream
+	movwf	FSR	; store in index reg
+loop1
+	nop
+	nop
+	movf	INDF, w ; load seed value
+	movwf	0x20
+	bcf	0x20, 1	; clear bit 1 
+	btfsc	0x20, 0 ; copy from bit 0
+	bsf	0x20, 1 ; (if set)
+	bsf	0x20, 4 ; LED on
+	movf	0x20, w
+	movwf	GPIO
+	nop
+	movlw	0x10
+	movwf	GPIO	; reset GPIO
+	movlw	0x14
+	call	wait
+	nop
+	nop
+	nop
+	nop
+	nop
+	btfsc	GPIO, 0 ; both pins must be low...
+	goto	die
+	btfsc	GPIO, 1 ; ...when no bit transfer takes place
+	goto	die	; if not -> lock cic error state -> die
+	incf	FSR, f	; next one
+	movlw	0xf
+	andwf	FSR, w
+	btfss	STATUS, Z	
+	goto	loop1
+	call	mangle
+	call	mangle
+	call	mangle
+	movlw	0x2	; wait 10
+	call	wait	;
+	nop
+	nop
+	btfsc	0x37, 0
+	goto	swap
+	banksel	TRISIO
+	bcf	TRISIO, 0
+	bsf	TRISIO, 1
+	goto	swapskip
+swap
+	banksel	TRISIO
+	bsf	TRISIO, 0
+	bcf	TRISIO, 1
+	nop
+swapskip
+	banksel GPIO
+	movf	0x37, w
+	andlw	0xf
+	btfss	STATUS, Z
+	goto	loop0
+	goto	loop
+
+; --------calculate new seeds--------
+; had to be unrolled because PIC has an inefficient way of handling
+; indirect access, no post increment, etc.
+mangle
+	call	mangle_lock
+	nop
+	nop
+mangle_key
+	movf	0x2f, w
+	movwf	0x20	
+mangle_key_loop
+	addlw	0x1
+	addwf	0x21, f
+	movf	0x22, w
+	movwf	0x40
+	movf	0x21, w
+	addwf	0x22, f
+	incf	0x22, f
+	comf	0x22, f
+	movf	0x23, w
+	movwf	0x41	; store 23 to 41
+	movlw	0xf
+	andwf	0x23, f
+	movf	0x40, w ; add 40(22 old)+23+#1 and skip if carry
+	andlw	0xf
+	addwf	0x23, f
+	incf	0x23, f
+	btfsc	0x23, 4
+	goto	mangle_key_withskip
+mangle_key_withoutskip
+	movf	0x41, w ; restore 23
+	addwf	0x24, f ; add to 24
+	movf	0x25, w
+	movwf	0x40	; save 25 to 40
+	movf	0x24, w
+	addwf	0x25, f
+	movf	0x26, w
+	movwf	0x41	; save 26 to 41
+	movf	0x40, w ; restore 25
+	andlw	0xf	; mask nibble
+	addlw	0x8	; add #8 to HIGH nibble
+	movwf	0x40
+	btfss	0x40, 4 ; skip if carry to 5th bit
+	addwf	0x26, w
+	movwf	0x26
+
+	movf	0x41, w ; restore 26
+	addlw	0x1	; inc
+	addwf	0x27, f	; add to 27
+
+	movf	0x27, w ;
+	addlw	0x1	; inc
+	addwf	0x28, f ; add to 28
+
+	movf	0x28, w ;
+	addlw	0x1	; inc
+	addwf	0x29, f ; add to 29
+
+	movf	0x29, w ;
+	addlw	0x1	; inc
+	addwf	0x2a, f ; add to 2a
+
+	movf	0x2a, w ;
+	addlw	0x1	; inc
+	addwf	0x2b, f ; add to 2b
+
+	movf	0x2b, w ;
+	addlw	0x1	; inc
+	addwf	0x2c, f ; add to 2c
+
+	movf	0x2c, w ;
+	addlw	0x1	; inc
+	addwf	0x2d, f ; add to 2d
+
+	movf	0x2d, w ;
+	addlw	0x1	; inc
+	addwf	0x2e, f ; add to 2e
+
+	movf	0x2e, w ;
+	addlw	0x1	; inc
+	addwf	0x2f, f ; add to 2f
+
+	movf	0x20, w ; restore original 0xf
+	andlw	0xf
+	addlw	0xf
+	movwf	0x20
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	btfss	0x20, 4 ; skip if half-byte carry
+	goto mangle_return ; +2 cycles in return
+	nop
+	goto mangle_key_loop
+; 69 when goto, 69 when return
+; CIC has 78 -> 9 nops
+
+mangle_key_withskip
+	movf	0x41, w ; restore 23
+	addwf	0x23, f ; add to 23
+	movf	0x24, w
+	movwf	0x40	; save 24 to 40
+	movf	0x23, w
+	addwf	0x24, f
+	movf	0x25, w
+	movwf	0x41	; save 25 to 41
+	movf	0x40, w ; restore 24
+	andlw	0xf	; mask nibble
+	addlw	0x8	; add #8 to HIGH nibble
+	movwf	0x40
+	btfss	0x40, 4 ; skip if carry to 5th bit
+	addwf	0x25, w
+	movwf	0x25
+
+	movf	0x41, w ; restore 25
+	addlw	0x1	; inc
+	addwf	0x26, f	; add to 26
+
+	movf	0x26, w ;
+	addlw	0x1	; inc
+	addwf	0x27, f ; add to 27
+
+	movf	0x27, w ;
+	addlw	0x1	; inc
+	addwf	0x28, f ; add to 28
+
+	movf	0x28, w ;
+	addlw	0x1	; inc
+	addwf	0x29, f ; add to 29
+
+	movf	0x29, w ;
+	addlw	0x1	; inc
+	addwf	0x2a, f ; add to 2a
+
+	movf	0x2a, w ;
+	addlw	0x1	; inc
+	addwf	0x2b, f ; add to 2b
+
+	movf	0x2b, w ;
+	addlw	0x1	; inc
+	addwf	0x2c, f ; add to 2c
+
+	movf	0x2c, w ;
+	addlw	0x1	; inc
+	addwf	0x2d, f ; add to 2d
+
+	movf	0x2d, w ;
+	addlw	0x1	; inc
+	addwf	0x2e, f ; add to 2e
+
+	movf	0x2e, w ;
+	addlw	0x1	; inc
+	addwf	0x2f, f ; add to 2f
+
+	movf	0x20, w ; restore original 0xf
+	andlw	0xf
+	addlw	0xf
+	movwf	0x20
+	bcf	GPIO, 0
+	movf	GPIO, w
+	movwf	0x5e
+	bsf	GPIO, 0
+	movf	GPIO, w
+	movwf	0x5f
+	bcf	GPIO, 0
+	nop
+	nop
+	nop
+	nop
+	btfss	0x20, 4 ; skip if half-byte carry
+	goto mangle_return ; +2 cycles in return
+	movf	0x20, w		; restore w (previously destroyed)
+	goto mangle_key_loop
+mangle_return
+	return
+; 73 when goto, 73 when return
+; CIC has 84 -> 11 nops
+
+mangle_lock
+	movf	0x3f, w
+	movwf	0x30	
+mangle_lock_loop
+	addlw	0x1
+	addwf	0x31, f
+	movf	0x32, w
+	movwf	0x40
+	movf	0x31, w
+	addwf	0x32, f
+	incf	0x32, f
+	comf	0x32, f
+	movf	0x33, w
+	movwf	0x41	; store 33 to 41
+	movlw	0xf
+	andwf	0x33, f
+	movf	0x40, w ; add 40(32 old)+33+#1 and skip if carry
+	andlw	0xf
+	addwf	0x33, f
+	incf	0x33, f
+	btfsc	0x33, 4
+	goto	mangle_lock_withskip
+mangle_lock_withoutskip
+	movf	0x41, w ; restore 33
+	addwf	0x34, f ; add to 34
+	movf	0x35, w
+	movwf	0x40	; save 35 to 40
+	movf	0x34, w
+	addwf	0x35, f
+	movf	0x36, w
+	movwf	0x41	; save 36 to 41
+	movf	0x40, w ; restore 35
+	andlw	0xf	; mask nibble
+	addlw	0x8	; add #8 to HIGH nibble
+	movwf	0x40
+	btfss	0x40, 4 ; skip if carry to 5th bit
+	addwf	0x36, w
+	movwf	0x36
+
+	movf	0x41, w ; restore 36
+	addlw	0x1	; inc
+	addwf	0x37, f	; add to 37
+
+	movf	0x37, w ;
+	addlw	0x1	; inc
+	addwf	0x38, f ; add to 38
+
+	movf	0x38, w ;
+	addlw	0x1	; inc
+	addwf	0x39, f ; add to 39
+
+	movf	0x39, w ;
+	addlw	0x1	; inc
+	addwf	0x3a, f ; add to 3a
+
+	movf	0x3a, w ;
+	addlw	0x1	; inc
+	addwf	0x3b, f ; add to 3b
+
+	movf	0x3b, w ;
+	addlw	0x1	; inc
+	addwf	0x3c, f ; add to 3c
+
+	movf	0x3c, w ;
+	addlw	0x1	; inc
+	addwf	0x3d, f ; add to 3d
+
+	movf	0x3d, w ;
+	addlw	0x1	; inc
+	addwf	0x3e, f ; add to 3e
+
+	movf	0x3e, w ;
+	addlw	0x1	; inc
+	addwf	0x3f, f ; add to 3f
+
+	movf	0x30, w ; restore original 0xf
+	andlw	0xf
+	addlw	0xf
+	movwf	0x30
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	btfss	0x30, 4 ; skip if half-byte carry
+	goto mangle_return
+	nop
+	goto mangle_lock_loop
+; 69 when goto, 69 when return
+; CIC has 78 -> 9 nops
+	
+mangle_lock_withskip
+	movf	0x41, w ; restore 33
+	addwf	0x33, f ; add to 33
+	movf	0x34, w
+	movwf	0x40	; save 34 to 40
+	movf	0x33, w
+	addwf	0x34, f
+	movf	0x35, w
+	movwf	0x41	; save 35 to 41
+	movf	0x40, w ; restore 34
+	andlw	0xf	; mask nibble
+	addlw	0x8	; add #8 to HIGH nibble
+	movwf	0x40
+	btfss	0x40, 4 ; skip if carry to 5th bit
+	addwf	0x35, w
+	movwf	0x35
+
+	movf	0x41, w ; restore 35
+	addlw	0x1	; inc
+	addwf	0x36, f	; add to 36
+
+	movf	0x36, w ;
+	addlw	0x1	; inc
+	addwf	0x37, f ; add to 37
+
+	movf	0x37, w ;
+	addlw	0x1	; inc
+	addwf	0x38, f ; add to 38
+
+	movf	0x38, w ;
+	addlw	0x1	; inc
+	addwf	0x39, f ; add to 39
+
+	movf	0x39, w ;
+	addlw	0x1	; inc
+	addwf	0x3a, f ; add to 3a
+
+	movf	0x3a, w ;
+	addlw	0x1	; inc
+	addwf	0x3b, f ; add to 3b
+
+	movf	0x3b, w ;
+	addlw	0x1	; inc
+	addwf	0x3c, f ; add to 3c
+
+	movf	0x3c, w ;
+	addlw	0x1	; inc
+	addwf	0x3d, f ; add to 3d
+
+	movf	0x3d, w ;
+	addlw	0x1	; inc
+	addwf	0x3e, f ; add to 3e
+
+	movf	0x3e, w ;
+	addlw	0x1	; inc
+	addwf	0x3f, f ; add to 3f
+
+	movf	0x30, w ; restore original 0xf
+	andlw	0xf
+	addlw	0xf
+	movwf	0x30
+
+	btfss	0x5e, 1
+	goto	scic_pair_skip1
+	btfsc	0x5f, 1
+	goto	scic_pair_skip2
+	goto	supercic_pairmode
+scic_pair_skip1
+	nop
+	nop
+scic_pair_skip2
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	btfss	0x30, 4 ; skip if half-byte carry
+	goto mangle_return
+	nop
+	goto mangle_lock_loop
+; 73 when goto, 73 when return
+; CIC has 84 -> 11 nops
+
+; --------wait: 3*(W-1)+7 cycles (including call+return). W=0 -> 256!--------
+wait	
+	movwf	0x4f
+wait0	decfsz	0x4f, f
+	goto	wait0
+	return	
+
+; --------wait long: 8+(3*(w-1))+(772*w). W=0 -> 256!--------
+longwait
+	movwf	0x4e
+	clrw
+longwait0
+	call	wait
+	decfsz	0x4e, f
+	goto	longwait0
+	return
+
+; --------change region in eeprom and die--------
+die
+	banksel	EEADR
+	clrw
+	movwf	EEADR
+	bsf	EECON1, RD
+	movf	EEDAT, w
+	banksel	GPIO
+	movwf	0x4d
+	btfsc	0x4d, 0
+	goto	die_reg_6
+die_reg_9
+	movlw	0x9	; died with PAL, fall back to NTSC
+	goto	die_reg_cont
+die_reg_6
+	movlw	0x6	; died with NTSC, fall back to PAL
+die_reg_cont
+	banksel	EEADR
+	movwf	EEDAT
+	bsf	EECON1, WREN
+
+die_intloop
+	bcf	INTCON, GIE
+	btfsc	INTCON, GIE
+	goto	die_intloop
+	
+	movlw	0x55
+	movwf	EECON2
+	movlw	0xaa
+	movwf	EECON2
+	bsf	EECON1, WR
+	bsf	INTCON, GIE
+
+	banksel	GPIO
+	bcf	GPIO, 4
+; --------forever: blink status pin--------
+die_trap
+	goto	die_trap
+; -----------------------------------------------------------------------
+supercic_pairmode
+	banksel	TRISIO
+	bsf	TRISIO, 0
+	bsf	TRISIO, 1
+	banksel	GPIO
+supercic_pairmode_loop
+	bsf	GPIO, 4
+	nop
+	nop
+	bcf	GPIO, 4
+	goto supercic_pairmode_loop
+
+; eeprom memory
+DEEPROM	CODE
+	de      0x09	; D411 (NTSC)
+end

+ 64 - 14
cic/supercic/supercic-lock.asm

@@ -29,7 +29,7 @@ processor p16f630
 ;                       ,-----_-----.
 ;      +5V (27,58) [18] |1        14| GND (5,36) [9]
 ;      CIC clk (56) [7] |2  A5 A0 13| CIC lock reset in [8]
-;                       |3  A4 A1 12| 50/60Hz out
+;                D4 out |3  A4 A1 12| 50/60Hz out
 ;                       |4  A3 A2 11| host reset out [10]
 ;         LED out (grn) |5  C5 C0 10| CIC data i/o 0 (55) [1]
 ;         LED out (red) |6  C4 C1  9| CIC data i/o 1 (24) [2]
@@ -43,6 +43,11 @@ processor p16f630
 ;   pin 12 connected to PPU1 pin 24 and PPU2 pin 30 (both isolated from mainboard)
 ;   pin 13 connected to reset button
 ;
+;   D4 out is always switched to the autodetected region and is not user
+;   overridable. It can be used, by adding an address decoder and a latch,
+;   to override bit 4 of the $213f register (used by games to detect the
+;   console region).
+;
 ;   Host reset out behaves as follows:
 ;   After powerup it is held low for a couple of ms to allow the components
 ;   to power-up properly.
@@ -74,6 +79,14 @@ processor p16f630
 ;   In case no CIC is present in the game cartridge the user setting is applied
 ;   immediately.
 ;
+;   SuperCIC pair mode: when a SuperCIC lock and SuperCIC key detect each other
+;   they both switch both of the data pins to inputs. The lock then passes through
+;   data i/o 0 to SNES 50/60Hz and data i/o 1 to an optional D4 output (for
+;   overriding the 213f register using additional hardware). This makes it
+;   possible to switch 50/60Hz and D4 from the cartridge slot, e.g. by connecting
+;   an additional MCU to the CIC data lines. Of course, they have to be tristated
+;   for normal (non-passthrough) operation first.
+;
 ;   Table 1. 50/60Hz output behavior according to user setting and key CIC type.
 ;   SuperCIC	key CIC		"region"
 ;   ------------------------------------------------------
@@ -123,6 +136,9 @@ processor p16f630
 ;   0x56		temp LED state
 ;   0x57		detected region (0: 60Hz, 2: 50Hz)
 ;   0x58		forced region (0: 60Hz, 2: 50Hz)
+;   0x59		detected D4 (0: 60Hz, 16: 50Hz)
+;   0x5e		SuperCIC pair mode detect (phase 1)
+;   0x5f		SuperCIC pair mode detect (phase 2)
 ;
 ; ---------------------------------------------------------------------
 
@@ -158,6 +174,9 @@ rst_loop
 	clrf	0x53
 	clrf	0x54		; clear user mode
 	clrf	0x57		; clear key mode
+	clrf	0x59		; clear D4
+	clrf	0x5e		;
+	clrf	0x5f		;
         banksel EEADR		; fetch current mode from EEPROM
         clrf    EEADR		; address 0
         bsf     EECON1, RD	; 
@@ -166,7 +185,6 @@ rst_loop
 	movwf	0x55		; store saved mode in mode var
 	movwf	0x56		; and temp LED
 	movwf	0x58
-
 	movwf	0x50		; and final LED	
 	movlw	0x3		; mask
 	andwf	0x50, f		;
@@ -181,7 +199,7 @@ rst_loop
 	bsf	T1CON, 0	; start the timer	
 	goto	main		; go go go
 init
-;	PORTA:  in  in  in out out  in
+;	PORTA:  in out  in out out  in
 ;	PORTC: out out  in out out  in
 	banksel PORTA
 	clrf	PORTA
@@ -190,7 +208,7 @@ init
 	movlw	0x00		; disable all interrupts
 	movwf	INTCON
 	banksel	TRISA
-	movlw	0x39		; in in in out out in
+	movlw	0x29		; in out in out out in
 	movwf	TRISA
 	movlw	0x09		; out out in out out in
 	movwf	TRISC
@@ -352,7 +370,6 @@ loop1
 	movwf	0x42		; store input
 	movf	0x50, w		; get LED state
 	movwf	PORTC		; reset GPIO
-	nop
 
 	call	checkkey
 
@@ -388,7 +405,6 @@ loop1
 	nop
 	nop
 	nop
-	nop
 	btfsc	0x37, 0
 	goto	swap
 	banksel	TRISC
@@ -404,6 +420,7 @@ swapskip
 	banksel PORTA
 	bsf	0x54, 2		; run the console
 	movf	0x54, w		; read resolved mode
+	iorwf	0x59, w		; get D4 value
 	movwf	PORTA
 	bcf	0x43, 0		; don't check key region anymore
 	movf	0x37, w
@@ -576,10 +593,10 @@ mangle_key_withskip
 	addlw	0xf
 	movwf	0x20
 	bsf	PORTC, 1
-	movlw	PORTC
+	movf	PORTC, w
 	movwf	0x5e
 	bcf	PORTC, 1
-	movlw	PORTC
+	movf	PORTC, w
 	movwf	0x5f
 	nop
 	nop
@@ -751,17 +768,23 @@ mangle_lock_withskip
 	andlw	0xf
 	addlw	0xf
 	movwf	0x30
+	
+	btfsc	0x5e, 0
+	goto	scic_pair_skip1
+	btfss	0x5f, 0
+	goto	scic_pair_skip2
+	goto	supercic_pairmode
+scic_pair_skip1
 	nop
 	nop
+scic_pair_skip2	
 	nop
 	nop
 	nop
 	nop
 	nop
 	nop
-	nop
-	nop
-	nop
+
 	btfss	0x30, 4 	; skip if half-byte carry
 	goto mangle_return
 	nop
@@ -793,7 +816,7 @@ die
 	goto	die
 
 ; --------check the key input and change "region" when appropriate--------
-; --------requires 19 cycles (incl. call+return)
+; --------requires 20 cycles (incl. call+return)
 checkkey
 	btfss	0x43, 0		; first time?
 	goto 	checkkey_nocheck; if not, just burn some cycles
@@ -807,11 +830,13 @@ checkkey
 checkkey_411
 	nop			; to compensate for untaken branch
 	bcf	0x57, 1		; set detected mode (60Hz)
+	bcf	0x59, 4		; set detected D4 mode (60Hz)
 	bcf	0x54, 1		; set output mode (60Hz)
 	movlw	0x9
 	goto	checkkey_save
 checkkey_413
 	bsf	0x57, 1		; set detected mode (50Hz)
+	bsf	0x59, 4		; set detected D4 mode (50Hz)
 	bsf	0x54, 1		; set output mode (50Hz)
 	movlw	0x6
 	goto	checkkey_save
@@ -828,6 +853,7 @@ checkkey_nocheck2
 	nop
 	nop
 	nop
+	nop
 	goto checkkey_done
 checkkey_save
 	movwf	0x32
@@ -974,8 +1000,32 @@ checkrst_0_0_setregion_plus5
 	nop
 	goto	checkrst_0_0_setregion
 
-checktmr	; TODO
-	return
+supercic_pairmode
+	banksel	TRISC
+	bsf	TRISC, 0	; tristate both
+	bsf	TRISC, 1	; data lines
+	banksel	PORTC
+supercic_pairmode_loop
+	clrf	0x5d
+	bsf	0x5d, 2
+	btfsc	PORTC, 0
+	bsf	0x5d, 1
+	btfsc	PORTC, 1
+	bsf	0x5d, 4
+	btfsc	PORTA, 0
+	bcf	0x5d, 2
+	movf	0x5d, w
+	movwf	PORTA
+	btfss	PORTC, 0
+	goto	supercic_pairmode_led_60
+supercic_pairmode_led_50
+	bcf	PORTC, 4
+	bsf	PORTC, 5
+	goto	supercic_pairmode_loop
+supercic_pairmode_led_60
+	bsf	PORTC, 4
+	bcf	PORTC, 5
+	goto	supercic_pairmode_loop
 ; -----------------------------------------------------------------------
 ; eeprom data
 DEEPROM	CODE