329 lines
8.1 KiB
NASM
329 lines
8.1 KiB
NASM
#include <p16f630.inc>
|
|
|
|
; -----------------------------------------------------------------------
|
|
; SNES "In-game reset" (IGR) controller
|
|
;
|
|
; Copyright (C) 2010 by Maximilian Rehkopf <otakon@gmx.net>
|
|
;
|
|
; 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
|
|
;
|
|
; -----------------------------------------------------------------------
|
|
;
|
|
; This program is designed to run on a PIC 16F630 microcontroller connected
|
|
; to the controller port and SNES main board. It allows an SNES to be reset
|
|
; and region switched via a standard controller.
|
|
;
|
|
; pin configuration: (controller port pin) [other connection]
|
|
; ,-----_-----.
|
|
; +5V (1) |1 14| GND (7)
|
|
; Reset out [to CIC pin 8 / SuperCIC pin 13] |2 A5 A0 13| serial data in(4)
|
|
; 50/60Hz out [to PPUs] |3 A4 A1 12| latch in(3)
|
|
; 50/60Hz in [from SuperCIC pin 12] |4 A3 A2 11| clk in(2)
|
|
; LED out - grn |5 C5 C0 10| LED in - grn [from SuperCIC pin 5]
|
|
; LED out - red |6 C4 C1 9| LED in - red [from SuperCIC pin 6]
|
|
; LED_TYPE in |7 C3 C2 8| SuperCIC present
|
|
; `-----------'
|
|
;
|
|
; Pin 4 should be connected to SuperCIC pin 12 if a SuperCIC is used.
|
|
;
|
|
; Pin 7 (LED_TYPE) sets the output mode for the LED pins
|
|
; (must be tied to either level):
|
|
; low = common cathode
|
|
; high = common anode (output inverted)
|
|
;
|
|
; Pin 8 should be connected as follows:
|
|
; low = no SuperCIC present
|
|
; high = SuperCIC present
|
|
;
|
|
; controller pin numbering
|
|
; ========================
|
|
; _______________________________
|
|
; | | \
|
|
; | (1) (2) (3) (4) | (5) (6) (7) )
|
|
; |_________________|_____________/
|
|
;
|
|
;
|
|
; key mapping: L + R + Select + (stream data)
|
|
; =============================
|
|
; Start Reset (normal) 0xcf 0xcf
|
|
; X Reset (6s) 0xdf 0x8f
|
|
;
|
|
; Y Region 50Hz/PAL 0x9f 0xcf
|
|
; A Region 60Hz/NTSC 0xdf 0x4f
|
|
; B Region from SuperCIC (SuperCIC only) 0x5f 0xcf
|
|
;
|
|
; functional description:
|
|
; =======================
|
|
; Reset (normal): simply resets the console.
|
|
; Reset (6s): resets the console for >5s to enter main menu on
|
|
; PowerPak and sd2snes.
|
|
; In SuperCIC mode this actually issues a reset
|
|
; "doubleclick" to trigger the SuperCIC's long reset
|
|
; function.
|
|
;
|
|
; Region 50Hz/PAL overrides the region to 50Hz/PAL.
|
|
; Region 60Hz/NTSC overrides the region to 60Hz/NTSC.
|
|
; Region from SuperCIC sets the region according to the input level of
|
|
; pin 4 (+5V = 50Hz, 0V = 60Hz). In this mode the
|
|
; region is updated constantly.
|
|
; This function is only available in SuperCIC mode
|
|
; (pin 8 = 5V).
|
|
;
|
|
; -----------------------------------------------------------------------
|
|
; Configuration bits: adapt to your setup and needs
|
|
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _BODEN & _CP_OFF & _CPD_OFF
|
|
|
|
; -----------------------------------------------------------------------
|
|
; relocatable code
|
|
PROG CODE
|
|
start
|
|
banksel PORTA
|
|
clrf PORTA
|
|
movlw 0x07 ; PORTA2..0 are digital I/O (not connected to comparator)
|
|
movwf CMCON
|
|
movlw 0x00 ; disable all interrupts
|
|
movwf INTCON
|
|
banksel TRISA
|
|
movlw 0x2f ; in out in in in in
|
|
movwf TRISA
|
|
movlw 0x0f ; out out in in in in
|
|
movwf TRISC
|
|
movlw 0x00 ; no pullups
|
|
movwf WPUA
|
|
movlw 0x80 ; global pullup disable
|
|
movwf OPTION_REG
|
|
banksel PORTA
|
|
bsf PORTA, 5
|
|
|
|
; tits GTFO
|
|
|
|
clrf 0x24
|
|
btfsc PORTC, 2
|
|
bsf 0x24, 1
|
|
|
|
clrf 0x23
|
|
btfss 0x24, 1 ; SuperCIC absent?
|
|
goto doregion_60 ; then set defaults
|
|
|
|
bsf 0x23, 1 ; else enable passthru
|
|
|
|
idle
|
|
; check region passthru
|
|
btfss 0x23, 1 ; passthru enabled?
|
|
goto waitforlatch_h ;
|
|
btfsc PORTA, 3
|
|
bsf PORTA, 4
|
|
btfss PORTA, 3
|
|
bcf PORTA, 4
|
|
call setleds_passthru
|
|
waitforlatch_h ; wait for "latch" to become high
|
|
btfss PORTA, 1
|
|
goto idle
|
|
|
|
|
|
waitforlatch_l ; wait for "latch" to become low
|
|
btfsc PORTA, 1
|
|
goto waitforlatch_l
|
|
|
|
|
|
clrf 0x20
|
|
clrf 0x21
|
|
clrf 0x22
|
|
bcf STATUS, C ; clear carry
|
|
dl1
|
|
movf PORTA, w ;read data bit
|
|
rlf 0x20, f ;shift
|
|
andlw 0x1
|
|
iorwf 0x20, f ;put in data reg
|
|
incf 0x22, f ;inc bit count
|
|
dl1_wait
|
|
btfss PORTA, 2 ;wait for clk=h
|
|
goto dl1_wait
|
|
btfss 0x22, 3 ;first byte done?
|
|
goto dl1
|
|
clrf 0x22
|
|
dl2
|
|
movf PORTA, w ;read data bit
|
|
rlf 0x21, f ;shift
|
|
andlw 0x1
|
|
iorwf 0x21, f ;put in data reg
|
|
incf 0x22, f ;inc bit count
|
|
dl2_wait
|
|
btfss PORTA, 2 ;wait for clk=h
|
|
goto dl2_wait
|
|
btfss 0x22, 2 ; read only 4 bits
|
|
goto dl2
|
|
|
|
|
|
|
|
|
|
checkkeys
|
|
; we now have the first 8 bits in 0x20 and the second 4 bits in 0x21
|
|
; 00011111 00011111 = ABXY, Select, L
|
|
movlw 0x04
|
|
xorwf 0x21, w
|
|
btfsc STATUS, Z
|
|
goto group04
|
|
movlw 0x08
|
|
xorwf 0x21, w
|
|
btfsc STATUS, Z
|
|
goto group08
|
|
movlw 0x0c
|
|
xorwf 0x21, w
|
|
btfsc STATUS, Z
|
|
goto group0c
|
|
goto idle
|
|
|
|
group04
|
|
movlw 0xdf
|
|
xorwf 0x20, w
|
|
btfss STATUS, Z
|
|
goto idle
|
|
goto doregion_60
|
|
|
|
group08
|
|
movlw 0xdf
|
|
xorwf 0x20, w
|
|
btfss STATUS, Z
|
|
goto idle
|
|
btfss 0x24, 1 ; SuperCIC absent?
|
|
goto doreset_long ; then do long reset
|
|
goto doreset_dbl ; else do dbl reset
|
|
|
|
group0c
|
|
movlw 0x5f
|
|
xorwf 0x20, w
|
|
btfsc STATUS, Z
|
|
goto doregion_passthru
|
|
movlw 0x9f
|
|
xorwf 0x20, w
|
|
btfsc STATUS, Z
|
|
goto doregion_50
|
|
movlw 0xcf
|
|
xorwf 0x20, w
|
|
btfsc STATUS, Z
|
|
goto doreset_normal
|
|
goto idle
|
|
|
|
doreset_normal
|
|
banksel TRISA
|
|
bcf TRISA, 5
|
|
banksel PORTA
|
|
bsf PORTA, 5
|
|
movlw 0x15
|
|
call longwait
|
|
banksel TRISA
|
|
bsf TRISA, 5
|
|
banksel PORTA
|
|
goto idle
|
|
|
|
doreset_dbl
|
|
banksel TRISA
|
|
bcf TRISA, 5
|
|
banksel PORTA
|
|
bsf PORTA, 5
|
|
movlw 0x15
|
|
call longwait
|
|
banksel TRISA
|
|
bsf TRISA, 5
|
|
clrw
|
|
call longwait
|
|
bcf TRISA, 5
|
|
movlw 0x15
|
|
call longwait
|
|
banksel TRISA
|
|
bsf TRISA, 5
|
|
banksel PORTA
|
|
goto idle
|
|
|
|
doreset_long
|
|
banksel TRISA
|
|
bcf TRISA, 5
|
|
banksel PORTA
|
|
bsf PORTA, 5
|
|
movlw 0x1e
|
|
call superlongwait
|
|
banksel TRISA
|
|
bsf TRISA, 5
|
|
banksel PORTA
|
|
goto idle
|
|
|
|
doregion_50
|
|
bsf PORTA, 4
|
|
clrf 0x23
|
|
call setleds_own
|
|
goto idle
|
|
|
|
doregion_60
|
|
bcf PORTA, 4
|
|
clrf 0x23
|
|
call setleds_own
|
|
goto idle
|
|
|
|
doregion_passthru
|
|
clrf 0x23
|
|
btfsc 0x24, 1 ; SuperCIC present?
|
|
bsf 0x23, 1 ; then enable passthru
|
|
goto idle
|
|
|
|
; --------wait: 3*(W-1)+7 cycles (including call+return). W=0 -> 256!--------
|
|
wait
|
|
movwf 0x2f
|
|
wait0 decfsz 0x2f, f
|
|
goto wait0
|
|
goto longwait1
|
|
|
|
; --------wait long: 8+(3*(w-1))+(772*w). W=0 -> 256!--------
|
|
longwait
|
|
movwf 0x2e
|
|
clrw
|
|
longwait0
|
|
goto wait
|
|
longwait1
|
|
decfsz 0x2e, f
|
|
goto longwait0
|
|
return
|
|
|
|
; --------wait extra long: 8+(3*(w-1))+(198405*w).
|
|
superlongwait
|
|
movwf 0x2d
|
|
clrw
|
|
superlongwait0
|
|
call longwait
|
|
decfsz 0x2d, f
|
|
goto superlongwait0
|
|
return
|
|
|
|
setleds
|
|
btfss 0x24, 1
|
|
goto setleds_own
|
|
setleds_passthru
|
|
clrw
|
|
btfsc PORTC, 0 ; green LED
|
|
iorlw 0x20
|
|
btfsc PORTC, 1 ; red LED
|
|
iorlw 0x10
|
|
movwf PORTC
|
|
return
|
|
|
|
setleds_own
|
|
movlw 0x20 ; assume green LED
|
|
btfss PORTA, 4
|
|
movlw 0x10 ; if PORTA.4 is low -> red LED
|
|
btfsc PORTC, 3 ; if common anode:
|
|
xorlw 0x30 ; invert output
|
|
movwf PORTC
|
|
return
|
|
END
|