snes-igr.asm 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include <p16f630.inc>
  2. ; -----------------------------------------------------------------------
  3. ; SNES "In-game reset" (IGR) controller
  4. ;
  5. ; Copyright (C) 2010 by Maximilian Rehkopf <otakon@gmx.net>
  6. ;
  7. ; This program is free software; you can redistribute it and/or modify
  8. ; it under the terms of the GNU General Public License as published by
  9. ; the Free Software Foundation; version 2 of the License only.
  10. ;
  11. ; This program is distributed in the hope that it will be useful,
  12. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ; GNU General Public License for more details.
  15. ;
  16. ; You should have received a copy of the GNU General Public License
  17. ; along with this program; if not, write to the Free Software
  18. ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. ;
  20. ; -----------------------------------------------------------------------
  21. ;
  22. ; This program is designed to run on a PIC 16F630 microcontroller connected
  23. ; to the controller port and SNES main board. It allows an SNES to be reset
  24. ; and region switched via a standard controller.
  25. ;
  26. ; pin configuration: (controller port pin) [other connection]
  27. ; ,-----_-----.
  28. ; +5V (1) |1 14| GND (7)
  29. ; Reset out [to CIC pin 8 / SuperCIC pin 13] |2 A5 A0 13| serial data in(4)
  30. ; 50/60Hz out [to PPUs] |3 A4 A1 12| latch in(3)
  31. ; 50/60Hz in [from SuperCIC pin 12] |4 A3 A2 11| clk in(2)
  32. ; LED out - grn |5 C5 C0 10| LED in - grn [from SuperCIC pin 5]
  33. ; LED out - red |6 C4 C1 9| LED in - red [from SuperCIC pin 6]
  34. ; LED_TYPE in |7 C3 C2 8| SuperCIC present
  35. ; `-----------'
  36. ;
  37. ; Pin 4 should be connected to SuperCIC pin 12 if a SuperCIC is used.
  38. ;
  39. ; Pin 7 (LED_TYPE) sets the output mode for the LED pins
  40. ; (must be tied to either level):
  41. ; low = common cathode
  42. ; high = common anode (output inverted)
  43. ;
  44. ; Pin 8 should be connected as follows:
  45. ; low = no SuperCIC present
  46. ; high = SuperCIC present
  47. ;
  48. ; controller pin numbering
  49. ; ========================
  50. ; _______________________________
  51. ; | | \
  52. ; | (1) (2) (3) (4) | (5) (6) (7) )
  53. ; |_________________|_____________/
  54. ;
  55. ;
  56. ; key mapping: L + R + Select + (stream data)
  57. ; =============================
  58. ; Start Reset (normal) 0xcf 0xcf
  59. ; X Reset (6s) 0xdf 0x8f
  60. ;
  61. ; Y Region 50Hz/PAL 0x9f 0xcf
  62. ; A Region 60Hz/NTSC 0xdf 0x4f
  63. ; B Region from SuperCIC (SuperCIC only) 0x5f 0xcf
  64. ;
  65. ; functional description:
  66. ; =======================
  67. ; Reset (normal): simply resets the console.
  68. ; Reset (6s): resets the console for >5s to enter main menu on
  69. ; PowerPak and sd2snes.
  70. ;
  71. ; Region 50Hz/PAL overrides the region to 50Hz/PAL.
  72. ; Region 60Hz/NTSC overrides the region to 60Hz/NTSC.
  73. ; Region from SuperCIC sets the region according to the input level of
  74. ; pin 4 (+5V = 50Hz, 0V = 60Hz). In this mode the
  75. ; region is updated constantly.
  76. ; This function is only available in SuperCIC mode
  77. ; (pin 8 = 5V).
  78. ;
  79. ; -----------------------------------------------------------------------
  80. ; Configuration bits: adapt to your setup and needs
  81. __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _BODEN & _CP_OFF & _CPD_OFF
  82. ; -----------------------------------------------------------------------
  83. ; relocatable code
  84. PROG CODE
  85. start
  86. banksel PORTA
  87. clrf PORTA
  88. movlw 0x07 ; PORTA2..0 are digital I/O (not connected to comparator)
  89. movwf CMCON
  90. movlw 0x00 ; disable all interrupts
  91. movwf INTCON
  92. banksel TRISA
  93. movlw 0x2f ; in out in in in in
  94. movwf TRISA
  95. movlw 0x0f ; out out in in in in
  96. movwf TRISC
  97. movlw 0x00 ; no pullups
  98. movwf WPUA
  99. movlw 0x80 ; global pullup disable
  100. movwf OPTION_REG
  101. banksel PORTA
  102. bsf PORTA, 5
  103. ; tits GTFO
  104. clrf 0x24
  105. btfsc PORTC, 2
  106. bsf 0x24, 1
  107. clrf 0x23
  108. btfss 0x24, 1 ; SuperCIC absent?
  109. goto doregion_60 ; then set defaults
  110. bsf 0x23, 1 ; else enable passthru
  111. idle
  112. ; check region passthru
  113. btfss 0x23, 1 ; passthru enabled?
  114. goto waitforlatch_h ;
  115. btfsc PORTA, 3
  116. bsf PORTA, 4
  117. btfss PORTA, 3
  118. bcf PORTA, 4
  119. call setleds_passthru
  120. waitforlatch_h ; wait for "latch" to become high
  121. btfss PORTA, 1
  122. goto idle
  123. waitforlatch_l ; wait for "latch" to become low
  124. btfsc PORTA, 1
  125. goto waitforlatch_l
  126. clrf 0x20
  127. clrf 0x21
  128. clrf 0x22
  129. bcf STATUS, C ; clear carry
  130. dl1
  131. movf PORTA, w ;read data bit
  132. rlf 0x20, f ;shift
  133. andlw 0x1
  134. iorwf 0x20, f ;put in data reg
  135. incf 0x22, f ;inc bit count
  136. dl1_wait
  137. btfss PORTA, 2 ;wait for clk=h
  138. goto dl1_wait
  139. btfss 0x22, 3 ;first byte done?
  140. goto dl1
  141. clrf 0x22
  142. dl2
  143. movf PORTA, w ;read data bit
  144. rlf 0x21, f ;shift
  145. andlw 0x1
  146. iorwf 0x21, f ;put in data reg
  147. incf 0x22, f ;inc bit count
  148. dl2_wait
  149. btfss PORTA, 2 ;wait for clk=h
  150. goto dl2_wait
  151. btfss 0x22, 2 ; read only 4 bits
  152. goto dl2
  153. checkkeys
  154. ; we now have the first 8 bits in 0x20 and the second 4 bits in 0x21
  155. ; 00011111 00011111 = ABXY, Select, L
  156. movlw 0x04
  157. xorwf 0x21, w
  158. btfsc STATUS, Z
  159. goto group04
  160. movlw 0x08
  161. xorwf 0x21, w
  162. btfsc STATUS, Z
  163. goto group08
  164. movlw 0x0c
  165. xorwf 0x21, w
  166. btfsc STATUS, Z
  167. goto group0c
  168. goto idle
  169. group04
  170. movlw 0xdf
  171. xorwf 0x20, w
  172. btfss STATUS, Z
  173. goto idle
  174. goto doregion_60
  175. group08
  176. movlw 0xdf
  177. xorwf 0x20, w
  178. btfss STATUS, Z
  179. goto idle
  180. btfss 0x24, 1 ; SuperCIC absent?
  181. goto doreset_long ; then do long reset
  182. goto doreset_dbl ; else do dbl reset
  183. group0c
  184. movlw 0x5f
  185. xorwf 0x20, w
  186. btfsc STATUS, Z
  187. goto doregion_passthru
  188. movlw 0x9f
  189. xorwf 0x20, w
  190. btfsc STATUS, Z
  191. goto doregion_50
  192. movlw 0xcf
  193. xorwf 0x20, w
  194. btfsc STATUS, Z
  195. goto doreset_normal
  196. goto idle
  197. doreset_normal
  198. banksel TRISA
  199. bcf TRISA, 5
  200. banksel PORTA
  201. bsf PORTA, 5
  202. movlw 0x15
  203. call longwait
  204. banksel TRISA
  205. bsf TRISA, 5
  206. banksel PORTA
  207. goto idle
  208. doreset_dbl
  209. banksel TRISA
  210. bcf TRISA, 5
  211. banksel PORTA
  212. bsf PORTA, 5
  213. movlw 0x15
  214. call longwait
  215. banksel TRISA
  216. bsf TRISA, 5
  217. clrw
  218. call longwait
  219. bcf TRISA, 5
  220. movlw 0x15
  221. call longwait
  222. banksel TRISA
  223. bsf TRISA, 5
  224. banksel PORTA
  225. goto idle
  226. doreset_long
  227. banksel TRISA
  228. bcf TRISA, 5
  229. banksel PORTA
  230. bsf PORTA, 5
  231. movlw 0x1e
  232. call superlongwait
  233. banksel TRISA
  234. bsf TRISA, 5
  235. banksel PORTA
  236. goto idle
  237. doregion_50
  238. bsf PORTA, 4
  239. clrf 0x23
  240. call setleds_own
  241. goto idle
  242. doregion_60
  243. bcf PORTA, 4
  244. clrf 0x23
  245. call setleds_own
  246. goto idle
  247. doregion_passthru
  248. clrf 0x23
  249. btfsc 0x24, 1 ; SuperCIC present?
  250. bsf 0x23, 1 ; then enable passthru
  251. goto idle
  252. ; --------wait: 3*(W-1)+7 cycles (including call+return). W=0 -> 256!--------
  253. wait
  254. movwf 0x2f
  255. wait0 decfsz 0x2f, f
  256. goto wait0
  257. goto longwait1
  258. ; --------wait long: 8+(3*(w-1))+(772*w). W=0 -> 256!--------
  259. longwait
  260. movwf 0x2e
  261. clrw
  262. longwait0
  263. goto wait
  264. longwait1
  265. decfsz 0x2e, f
  266. goto longwait0
  267. return
  268. ; --------wait extra long: 8+(3*(w-1))+(198405*w).
  269. superlongwait
  270. movwf 0x2d
  271. clrw
  272. superlongwait0
  273. call longwait
  274. decfsz 0x2d, f
  275. goto superlongwait0
  276. return
  277. setleds
  278. btfss 0x24, 1
  279. goto setleds_own
  280. setleds_passthru
  281. clrw
  282. btfsc PORTC, 0 ; green LED
  283. iorlw 0x20
  284. btfsc PORTC, 1 ; red LED
  285. iorlw 0x10
  286. movwf PORTC
  287. return
  288. setleds_own
  289. movlw 0x20 ; assume green LED
  290. btfss PORTA, 4
  291. movlw 0x10 ; if PORTA.4 is low -> red LED
  292. btfsc PORTC, 3 ; if common anode:
  293. xorlw 0x30 ; invert output
  294. movwf PORTC
  295. return
  296. END