snes-igr.asm 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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. ; In SuperCIC mode this actually issues a reset
  71. ; "doubleclick" to trigger the SuperCIC's long reset
  72. ; function.
  73. ;
  74. ; Region 50Hz/PAL overrides the region to 50Hz/PAL.
  75. ; Region 60Hz/NTSC overrides the region to 60Hz/NTSC.
  76. ; Region from SuperCIC sets the region according to the input level of
  77. ; pin 4 (+5V = 50Hz, 0V = 60Hz). In this mode the
  78. ; region is updated constantly.
  79. ; This function is only available in SuperCIC mode
  80. ; (pin 8 = 5V).
  81. ;
  82. ; -----------------------------------------------------------------------
  83. ; Configuration bits: adapt to your setup and needs
  84. __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _BODEN & _CP_OFF & _CPD_OFF
  85. ; -----------------------------------------------------------------------
  86. ; relocatable code
  87. PROG CODE
  88. start
  89. banksel PORTA
  90. clrf PORTA
  91. movlw 0x07 ; PORTA2..0 are digital I/O (not connected to comparator)
  92. movwf CMCON
  93. movlw 0x00 ; disable all interrupts
  94. movwf INTCON
  95. banksel TRISA
  96. movlw 0x2f ; in out in in in in
  97. movwf TRISA
  98. movlw 0x0f ; out out in in in in
  99. movwf TRISC
  100. movlw 0x00 ; no pullups
  101. movwf WPUA
  102. movlw 0x80 ; global pullup disable
  103. movwf OPTION_REG
  104. banksel PORTA
  105. bsf PORTA, 5
  106. ; tits GTFO
  107. clrf 0x24
  108. btfsc PORTC, 2
  109. bsf 0x24, 1
  110. clrf 0x23
  111. btfss 0x24, 1 ; SuperCIC absent?
  112. goto doregion_60 ; then set defaults
  113. bsf 0x23, 1 ; else enable passthru
  114. idle
  115. ; check region passthru
  116. btfss 0x23, 1 ; passthru enabled?
  117. goto waitforlatch_h ;
  118. btfsc PORTA, 3
  119. bsf PORTA, 4
  120. btfss PORTA, 3
  121. bcf PORTA, 4
  122. call setleds_passthru
  123. waitforlatch_h ; wait for "latch" to become high
  124. btfss PORTA, 1
  125. goto idle
  126. waitforlatch_l ; wait for "latch" to become low
  127. btfsc PORTA, 1
  128. goto waitforlatch_l
  129. clrf 0x20
  130. clrf 0x21
  131. clrf 0x22
  132. bcf STATUS, C ; clear carry
  133. dl1
  134. movf PORTA, w ;read data bit
  135. rlf 0x20, f ;shift
  136. andlw 0x1
  137. iorwf 0x20, f ;put in data reg
  138. incf 0x22, f ;inc bit count
  139. dl1_wait
  140. btfss PORTA, 2 ;wait for clk=h
  141. goto dl1_wait
  142. btfss 0x22, 3 ;first byte done?
  143. goto dl1
  144. clrf 0x22
  145. dl2
  146. movf PORTA, w ;read data bit
  147. rlf 0x21, f ;shift
  148. andlw 0x1
  149. iorwf 0x21, f ;put in data reg
  150. incf 0x22, f ;inc bit count
  151. dl2_wait
  152. btfss PORTA, 2 ;wait for clk=h
  153. goto dl2_wait
  154. btfss 0x22, 2 ; read only 4 bits
  155. goto dl2
  156. checkkeys
  157. ; we now have the first 8 bits in 0x20 and the second 4 bits in 0x21
  158. ; 00011111 00011111 = ABXY, Select, L
  159. movlw 0x04
  160. xorwf 0x21, w
  161. btfsc STATUS, Z
  162. goto group04
  163. movlw 0x08
  164. xorwf 0x21, w
  165. btfsc STATUS, Z
  166. goto group08
  167. movlw 0x0c
  168. xorwf 0x21, w
  169. btfsc STATUS, Z
  170. goto group0c
  171. goto idle
  172. group04
  173. movlw 0xdf
  174. xorwf 0x20, w
  175. btfss STATUS, Z
  176. goto idle
  177. goto doregion_60
  178. group08
  179. movlw 0xdf
  180. xorwf 0x20, w
  181. btfss STATUS, Z
  182. goto idle
  183. btfss 0x24, 1 ; SuperCIC absent?
  184. goto doreset_long ; then do long reset
  185. goto doreset_dbl ; else do dbl reset
  186. group0c
  187. movlw 0x5f
  188. xorwf 0x20, w
  189. btfsc STATUS, Z
  190. goto doregion_passthru
  191. movlw 0x9f
  192. xorwf 0x20, w
  193. btfsc STATUS, Z
  194. goto doregion_50
  195. movlw 0xcf
  196. xorwf 0x20, w
  197. btfsc STATUS, Z
  198. goto doreset_normal
  199. goto idle
  200. doreset_normal
  201. banksel TRISA
  202. bcf TRISA, 5
  203. banksel PORTA
  204. bsf PORTA, 5
  205. movlw 0x15
  206. call longwait
  207. banksel TRISA
  208. bsf TRISA, 5
  209. banksel PORTA
  210. goto idle
  211. doreset_dbl
  212. banksel TRISA
  213. bcf TRISA, 5
  214. banksel PORTA
  215. bsf PORTA, 5
  216. movlw 0x15
  217. call longwait
  218. banksel TRISA
  219. bsf TRISA, 5
  220. clrw
  221. call longwait
  222. bcf TRISA, 5
  223. movlw 0x15
  224. call longwait
  225. banksel TRISA
  226. bsf TRISA, 5
  227. banksel PORTA
  228. goto idle
  229. doreset_long
  230. banksel TRISA
  231. bcf TRISA, 5
  232. banksel PORTA
  233. bsf PORTA, 5
  234. movlw 0x1e
  235. call superlongwait
  236. banksel TRISA
  237. bsf TRISA, 5
  238. banksel PORTA
  239. goto idle
  240. doregion_50
  241. bsf PORTA, 4
  242. clrf 0x23
  243. call setleds_own
  244. goto idle
  245. doregion_60
  246. bcf PORTA, 4
  247. clrf 0x23
  248. call setleds_own
  249. goto idle
  250. doregion_passthru
  251. clrf 0x23
  252. btfsc 0x24, 1 ; SuperCIC present?
  253. bsf 0x23, 1 ; then enable passthru
  254. goto idle
  255. ; --------wait: 3*(W-1)+7 cycles (including call+return). W=0 -> 256!--------
  256. wait
  257. movwf 0x2f
  258. wait0 decfsz 0x2f, f
  259. goto wait0
  260. goto longwait1
  261. ; --------wait long: 8+(3*(w-1))+(772*w). W=0 -> 256!--------
  262. longwait
  263. movwf 0x2e
  264. clrw
  265. longwait0
  266. goto wait
  267. longwait1
  268. decfsz 0x2e, f
  269. goto longwait0
  270. return
  271. ; --------wait extra long: 8+(3*(w-1))+(198405*w).
  272. superlongwait
  273. movwf 0x2d
  274. clrw
  275. superlongwait0
  276. call longwait
  277. decfsz 0x2d, f
  278. goto superlongwait0
  279. return
  280. setleds
  281. btfss 0x24, 1
  282. goto setleds_own
  283. setleds_passthru
  284. clrw
  285. btfsc PORTC, 0 ; green LED
  286. iorlw 0x20
  287. btfsc PORTC, 1 ; red LED
  288. iorlw 0x10
  289. movwf PORTC
  290. return
  291. setleds_own
  292. movlw 0x20 ; assume green LED
  293. btfss PORTA, 4
  294. movlw 0x10 ; if PORTA.4 is low -> red LED
  295. btfsc PORTC, 3 ; if common anode:
  296. xorlw 0x30 ; invert output
  297. movwf PORTC
  298. return
  299. END