snescic-key.asm 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. #include <p12f629.inc>
  2. processor p12f629
  3. ; ---------------------------------------------------------------------
  4. ; SNES CIC clone for PIC Microcontroller (key mode only)
  5. ;
  6. ; Copyright (C) 2010 by Maximilian Rehkopf (ikari_01) <otakon@gmx.net>
  7. ; This software is part of the sd2snes project.
  8. ;
  9. ; This program is free software; you can redistribute it and/or modify
  10. ; it under the terms of the GNU General Public License as published by
  11. ; the Free Software Foundation; version 2 of the License only.
  12. ;
  13. ; This program is distributed in the hope that it will be useful,
  14. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ; GNU General Public License for more details.
  17. ;
  18. ; You should have received a copy of the GNU General Public License
  19. ; along with this program; if not, write to the Free Software
  20. ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. ;
  22. ; ---------------------------------------------------------------------
  23. ;
  24. ; pin configuration: (cartridge pin) [key CIC pin]
  25. ;
  26. ; ,---_---.
  27. ; +5V (27,58) [16] |1 8| GND (5,36) [8]
  28. ; CIC clk (56) [6] |2 7| CIC data i/o 0 (55) [2]
  29. ; status out |3 6| CIC data i/o 1 (24) [1]
  30. ; nc |4 5| CIC slave reset (25) [7]
  31. ; `-------'
  32. ;
  33. ;
  34. ; Status out can be connected to a LED. It indicates:
  35. ;
  36. ; state | output
  37. ; -------------------------+--------------------
  38. ; OK (normal operation) | high
  39. ; error (unlock failed) | alternating @~2.5Hz
  40. ; no CIC (modded SNES) | low
  41. ;
  42. ; In case lockout fails, the region is switched automatically and
  43. ; will be used after the next reset.
  44. ;
  45. ; memory usage:
  46. ;
  47. ; 0x20 buffer for seed calc and transfer
  48. ; 0x21 - 0x2f seed area (lock seed)
  49. ; 0x30 buffer for seed calc
  50. ; 0x31 - 0x3f seed area (key seed; 0x31 filled in by lock)
  51. ; 0x40 - 0x41 buffer for seed calc
  52. ; 0x4d buffer for eeprom access
  53. ; 0x4e loop variable for longwait
  54. ; 0x4f loop variable for wait
  55. ;
  56. ; ---------------------------------------------------------------------
  57. ; -----------------------------------------------------------------------
  58. __CONFIG _EC_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF
  59. ; -----------------------------------------------------------------------
  60. ; code memory
  61. org 0x0000
  62. nop
  63. nop
  64. nop
  65. goto init
  66. isr
  67. org 0x0004
  68. bcf INTCON, 1 ; clear interrupt cause
  69. bcf GPIO, 0
  70. bcf GPIO, 1
  71. bsf GPIO, 4 ; LED on
  72. nop
  73. nop
  74. nop
  75. nop
  76. nop
  77. nop
  78. bsf INTCON, 7 ; re-enable interrupts (ISR will continue as main)
  79. goto main
  80. init
  81. org 0x0010
  82. banksel GPIO
  83. clrf GPIO
  84. movlw 0x07 ; GPIO2..0 are digital I/O (not connected to comparator)
  85. movwf CMCON
  86. movlw 0x90 ; global enable interrupts + enable external interrupt
  87. movwf INTCON
  88. banksel TRISIO
  89. movlw 0x2d ; in out in in out in
  90. movwf TRISIO
  91. movlw 0x24 ; pullups for reset+clk to avoid errors when no CIC in host
  92. movwf WPU
  93. movlw 0x00 ; 0x80 for global pullup disable
  94. movwf OPTION_REG
  95. banksel GPIO
  96. bcf GPIO, 4 ; LED off
  97. idle
  98. goto idle ; wait for interrupt from lock
  99. main
  100. banksel TRISIO
  101. bsf TRISIO, 0
  102. bcf TRISIO, 1
  103. banksel GPIO
  104. ; --------INIT LOCK SEED (what the lock sends)--------
  105. movlw 0xb
  106. movwf 0x21
  107. movlw 0x1
  108. movwf 0x22
  109. movlw 0x4
  110. movwf 0x23
  111. movlw 0xf
  112. movwf 0x24
  113. movlw 0x4
  114. movwf 0x25
  115. movlw 0xb
  116. movwf 0x26
  117. movlw 0x5
  118. movwf 0x27
  119. movlw 0x7
  120. movwf 0x28
  121. movlw 0xf
  122. movwf 0x29
  123. movlw 0xd
  124. movwf 0x2a
  125. movlw 0x6
  126. movwf 0x2b
  127. movlw 0x1
  128. movwf 0x2c
  129. movlw 0xe
  130. movwf 0x2d
  131. movlw 0x9
  132. movwf 0x2e
  133. movlw 0x8
  134. movwf 0x2f
  135. ; --------INIT KEY SEED (what we must send)--------
  136. banksel EEADR ; D/F411 and D/F413
  137. clrf EEADR ; differ in 2nd seed nibble
  138. bsf EECON1, RD ; of key stream,
  139. movf EEDAT, w ; restore saved nibble from EEPROM
  140. banksel GPIO
  141. movwf 0x32
  142. movlw 0xa
  143. movwf 0x33
  144. movlw 0x1
  145. movwf 0x34
  146. movlw 0x8
  147. movwf 0x35
  148. movlw 0x5
  149. movwf 0x36
  150. movlw 0xf
  151. movwf 0x37
  152. movlw 0x1
  153. movwf 0x38
  154. movwf 0x39
  155. movlw 0xe
  156. movwf 0x3a
  157. movlw 0x1
  158. movwf 0x3b
  159. movlw 0x0
  160. movwf 0x3c
  161. movlw 0xd
  162. movwf 0x3d
  163. movlw 0xe
  164. movwf 0x3e
  165. movlw 0xc
  166. movwf 0x3f
  167. ; --------wait for stream ID--------
  168. movlw 0xb5
  169. call wait
  170. clrf 0x31 ; clear lock stream ID
  171. ; --------lock sends stream ID. 15 cycles per bit--------
  172. ; bsf GPIO, 0 ; (debug marker)
  173. ; bcf GPIO, 0 ;
  174. btfsc GPIO, 0 ; check stream ID bit
  175. bsf 0x31, 3 ; copy to lock seed
  176. movlw 0x2 ; wait=3*W+5
  177. call wait ; burn 11 cycles
  178. nop
  179. nop
  180. ; bsf GPIO, 0
  181. ; bcf GPIO, 0
  182. btfsc GPIO, 0 ; check stream ID bit
  183. bsf 0x31, 0 ; copy to lock seed
  184. movlw 0x2 ;
  185. call wait ; burn 11 cycles
  186. nop
  187. nop
  188. ; bsf GPIO, 0
  189. ; bcf GPIO, 0
  190. btfsc GPIO, 0 ; check stream ID bit
  191. bsf 0x31, 1 ; copy to lock seed
  192. movlw 0x2 ;
  193. call wait ; burn 11 cycles
  194. nop
  195. nop
  196. ; bsf GPIO, 0
  197. ; bcf GPIO, 0
  198. btfsc GPIO, 0 ; check stream ID bit
  199. bsf 0x31, 2 ; copy to lock seed
  200. banksel TRISIO
  201. bcf TRISIO, 0
  202. bsf TRISIO, 1
  203. banksel GPIO
  204. nop
  205. movlw 0x27 ; "wait" 1
  206. call wait ; wait 121
  207. nop
  208. nop
  209. ; --------main loop--------
  210. loop
  211. movlw 0x1
  212. loop0
  213. addlw 0x30 ; key stream
  214. movwf FSR ; store in index reg
  215. loop1
  216. movf INDF, w ; load seed value
  217. movwf 0x20
  218. bcf 0x20, 1 ; clear bit 1
  219. btfsc 0x20, 0 ; copy from bit 0
  220. bsf 0x20, 1 ; (if set)
  221. bsf 0x20, 4 ; LED on
  222. movf 0x20, w
  223. movwf GPIO
  224. nop
  225. movlw 0x10
  226. movwf GPIO ; reset GPIO
  227. movlw 0x16
  228. call wait
  229. nop
  230. btfsc GPIO, 0 ; both pins must be low...
  231. goto die
  232. btfsc GPIO, 1 ; ...when no bit transfer takes place
  233. goto die ; if not -> lock cic error state -> die
  234. incf FSR, f ; next one
  235. movlw 0xf
  236. andwf FSR, w
  237. btfss STATUS, Z
  238. goto loop1
  239. movlw 0x2 ; wait 10
  240. call wait ;
  241. nop
  242. nop
  243. call mangle
  244. call mangle
  245. call mangle
  246. btfsc 0x37, 0
  247. goto swap
  248. banksel TRISIO
  249. bcf TRISIO, 0
  250. bsf TRISIO, 1
  251. goto swapskip
  252. swap
  253. banksel TRISIO
  254. bsf TRISIO, 0
  255. bcf TRISIO, 1
  256. nop
  257. swapskip
  258. banksel GPIO
  259. movf 0x37, w
  260. andlw 0xf
  261. btfss STATUS, Z
  262. goto loop0
  263. goto loop
  264. ; --------calculate new seeds--------
  265. ; had to be unrolled because PIC has an inefficient way of handling
  266. ; indirect access, no post increment, etc.
  267. mangle
  268. call mangle_lock
  269. nop
  270. nop
  271. mangle_key
  272. movf 0x2f, w
  273. movwf 0x20
  274. mangle_key_loop
  275. addlw 0x1
  276. addwf 0x21, f
  277. movf 0x22, w
  278. movwf 0x40
  279. movf 0x21, w
  280. addwf 0x22, f
  281. incf 0x22, f
  282. comf 0x22, f
  283. movf 0x23, w
  284. movwf 0x41 ; store 23 to 41
  285. movlw 0xf
  286. andwf 0x23, f
  287. movf 0x40, w ; add 40(22 old)+23+#1 and skip if carry
  288. andlw 0xf
  289. addwf 0x23, f
  290. incf 0x23, f
  291. btfsc 0x23, 4
  292. goto mangle_key_withskip
  293. mangle_key_withoutskip
  294. movf 0x41, w ; restore 23
  295. addwf 0x24, f ; add to 24
  296. movf 0x25, w
  297. movwf 0x40 ; save 25 to 40
  298. movf 0x24, w
  299. addwf 0x25, f
  300. movf 0x26, w
  301. movwf 0x41 ; save 26 to 41
  302. movf 0x40, w ; restore 25
  303. andlw 0xf ; mask nibble
  304. addlw 0x8 ; add #8 to HIGH nibble
  305. movwf 0x40
  306. btfss 0x40, 4 ; skip if carry to 5th bit
  307. addwf 0x26, w
  308. movwf 0x26
  309. movf 0x41, w ; restore 26
  310. addlw 0x1 ; inc
  311. addwf 0x27, f ; add to 27
  312. movf 0x27, w ;
  313. addlw 0x1 ; inc
  314. addwf 0x28, f ; add to 28
  315. movf 0x28, w ;
  316. addlw 0x1 ; inc
  317. addwf 0x29, f ; add to 29
  318. movf 0x29, w ;
  319. addlw 0x1 ; inc
  320. addwf 0x2a, f ; add to 2a
  321. movf 0x2a, w ;
  322. addlw 0x1 ; inc
  323. addwf 0x2b, f ; add to 2b
  324. movf 0x2b, w ;
  325. addlw 0x1 ; inc
  326. addwf 0x2c, f ; add to 2c
  327. movf 0x2c, w ;
  328. addlw 0x1 ; inc
  329. addwf 0x2d, f ; add to 2d
  330. movf 0x2d, w ;
  331. addlw 0x1 ; inc
  332. addwf 0x2e, f ; add to 2e
  333. movf 0x2e, w ;
  334. addlw 0x1 ; inc
  335. addwf 0x2f, f ; add to 2f
  336. movf 0x20, w ; restore original 0xf
  337. andlw 0xf
  338. addlw 0xf
  339. movwf 0x20
  340. nop
  341. nop
  342. nop
  343. nop
  344. nop
  345. nop
  346. nop
  347. nop
  348. nop
  349. btfss 0x20, 4 ; skip if half-byte carry
  350. goto mangle_return ; +2 cycles in return
  351. nop
  352. goto mangle_key_loop
  353. ; 69 when goto, 69 when return
  354. ; CIC has 78 -> 9 nops
  355. mangle_key_withskip
  356. movf 0x41, w ; restore 23
  357. addwf 0x23, f ; add to 23
  358. movf 0x24, w
  359. movwf 0x40 ; save 24 to 40
  360. movf 0x23, w
  361. addwf 0x24, f
  362. movf 0x25, w
  363. movwf 0x41 ; save 25 to 41
  364. movf 0x40, w ; restore 24
  365. andlw 0xf ; mask nibble
  366. addlw 0x8 ; add #8 to HIGH nibble
  367. movwf 0x40
  368. btfss 0x40, 4 ; skip if carry to 5th bit
  369. addwf 0x25, w
  370. movwf 0x25
  371. movf 0x41, w ; restore 25
  372. addlw 0x1 ; inc
  373. addwf 0x26, f ; add to 26
  374. movf 0x26, w ;
  375. addlw 0x1 ; inc
  376. addwf 0x27, f ; add to 27
  377. movf 0x27, w ;
  378. addlw 0x1 ; inc
  379. addwf 0x28, f ; add to 28
  380. movf 0x28, w ;
  381. addlw 0x1 ; inc
  382. addwf 0x29, f ; add to 29
  383. movf 0x29, w ;
  384. addlw 0x1 ; inc
  385. addwf 0x2a, f ; add to 2a
  386. movf 0x2a, w ;
  387. addlw 0x1 ; inc
  388. addwf 0x2b, f ; add to 2b
  389. movf 0x2b, w ;
  390. addlw 0x1 ; inc
  391. addwf 0x2c, f ; add to 2c
  392. movf 0x2c, w ;
  393. addlw 0x1 ; inc
  394. addwf 0x2d, f ; add to 2d
  395. movf 0x2d, w ;
  396. addlw 0x1 ; inc
  397. addwf 0x2e, f ; add to 2e
  398. movf 0x2e, w ;
  399. addlw 0x1 ; inc
  400. addwf 0x2f, f ; add to 2f
  401. movf 0x20, w ; restore original 0xf
  402. andlw 0xf
  403. addlw 0xf
  404. movwf 0x20
  405. nop
  406. nop
  407. nop
  408. nop
  409. nop
  410. nop
  411. nop
  412. nop
  413. nop
  414. nop
  415. nop
  416. btfss 0x20, 4 ; skip if half-byte carry
  417. goto mangle_return ; +2 cycles in return
  418. nop
  419. goto mangle_key_loop
  420. mangle_return
  421. return
  422. ; 73 when goto, 73 when return
  423. ; CIC has 84 -> 11 nops
  424. mangle_lock
  425. movf 0x3f, w
  426. movwf 0x30
  427. mangle_lock_loop
  428. addlw 0x1
  429. addwf 0x31, f
  430. movf 0x32, w
  431. movwf 0x40
  432. movf 0x31, w
  433. addwf 0x32, f
  434. incf 0x32, f
  435. comf 0x32, f
  436. movf 0x33, w
  437. movwf 0x41 ; store 33 to 41
  438. movlw 0xf
  439. andwf 0x33, f
  440. movf 0x40, w ; add 40(32 old)+33+#1 and skip if carry
  441. andlw 0xf
  442. addwf 0x33, f
  443. incf 0x33, f
  444. btfsc 0x33, 4
  445. goto mangle_lock_withskip
  446. mangle_lock_withoutskip
  447. movf 0x41, w ; restore 33
  448. addwf 0x34, f ; add to 34
  449. movf 0x35, w
  450. movwf 0x40 ; save 35 to 40
  451. movf 0x34, w
  452. addwf 0x35, f
  453. movf 0x36, w
  454. movwf 0x41 ; save 36 to 41
  455. movf 0x40, w ; restore 35
  456. andlw 0xf ; mask nibble
  457. addlw 0x8 ; add #8 to HIGH nibble
  458. movwf 0x40
  459. btfss 0x40, 4 ; skip if carry to 5th bit
  460. addwf 0x36, w
  461. movwf 0x36
  462. movf 0x41, w ; restore 36
  463. addlw 0x1 ; inc
  464. addwf 0x37, f ; add to 37
  465. movf 0x37, w ;
  466. addlw 0x1 ; inc
  467. addwf 0x38, f ; add to 38
  468. movf 0x38, w ;
  469. addlw 0x1 ; inc
  470. addwf 0x39, f ; add to 39
  471. movf 0x39, w ;
  472. addlw 0x1 ; inc
  473. addwf 0x3a, f ; add to 3a
  474. movf 0x3a, w ;
  475. addlw 0x1 ; inc
  476. addwf 0x3b, f ; add to 3b
  477. movf 0x3b, w ;
  478. addlw 0x1 ; inc
  479. addwf 0x3c, f ; add to 3c
  480. movf 0x3c, w ;
  481. addlw 0x1 ; inc
  482. addwf 0x3d, f ; add to 3d
  483. movf 0x3d, w ;
  484. addlw 0x1 ; inc
  485. addwf 0x3e, f ; add to 3e
  486. movf 0x3e, w ;
  487. addlw 0x1 ; inc
  488. addwf 0x3f, f ; add to 3f
  489. movf 0x30, w ; restore original 0xf
  490. andlw 0xf
  491. addlw 0xf
  492. movwf 0x30
  493. nop
  494. nop
  495. nop
  496. nop
  497. nop
  498. nop
  499. nop
  500. nop
  501. nop
  502. btfss 0x30, 4 ; skip if half-byte carry
  503. goto mangle_return
  504. nop
  505. goto mangle_lock_loop
  506. ; 69 when goto, 69 when return
  507. ; CIC has 78 -> 9 nops
  508. mangle_lock_withskip
  509. movf 0x41, w ; restore 33
  510. addwf 0x33, f ; add to 33
  511. movf 0x34, w
  512. movwf 0x40 ; save 34 to 40
  513. movf 0x33, w
  514. addwf 0x34, f
  515. movf 0x35, w
  516. movwf 0x41 ; save 35 to 41
  517. movf 0x40, w ; restore 34
  518. andlw 0xf ; mask nibble
  519. addlw 0x8 ; add #8 to HIGH nibble
  520. movwf 0x40
  521. btfss 0x40, 4 ; skip if carry to 5th bit
  522. addwf 0x35, w
  523. movwf 0x35
  524. movf 0x41, w ; restore 35
  525. addlw 0x1 ; inc
  526. addwf 0x36, f ; add to 36
  527. movf 0x36, w ;
  528. addlw 0x1 ; inc
  529. addwf 0x37, f ; add to 37
  530. movf 0x37, w ;
  531. addlw 0x1 ; inc
  532. addwf 0x38, f ; add to 38
  533. movf 0x38, w ;
  534. addlw 0x1 ; inc
  535. addwf 0x39, f ; add to 39
  536. movf 0x39, w ;
  537. addlw 0x1 ; inc
  538. addwf 0x3a, f ; add to 3a
  539. movf 0x3a, w ;
  540. addlw 0x1 ; inc
  541. addwf 0x3b, f ; add to 3b
  542. movf 0x3b, w ;
  543. addlw 0x1 ; inc
  544. addwf 0x3c, f ; add to 3c
  545. movf 0x3c, w ;
  546. addlw 0x1 ; inc
  547. addwf 0x3d, f ; add to 3d
  548. movf 0x3d, w ;
  549. addlw 0x1 ; inc
  550. addwf 0x3e, f ; add to 3e
  551. movf 0x3e, w ;
  552. addlw 0x1 ; inc
  553. addwf 0x3f, f ; add to 3f
  554. movf 0x30, w ; restore original 0xf
  555. andlw 0xf
  556. addlw 0xf
  557. movwf 0x30
  558. nop
  559. nop
  560. nop
  561. nop
  562. nop
  563. nop
  564. nop
  565. nop
  566. nop
  567. nop
  568. nop
  569. btfss 0x30, 4 ; skip if half-byte carry
  570. goto mangle_return
  571. nop
  572. goto mangle_lock_loop
  573. ; 73 when goto, 73 when return
  574. ; CIC has 84 -> 11 nops
  575. ; --------wait: 3*(W-1)+7 cycles (including call+return). W=0 -> 256!--------
  576. wait
  577. movwf 0x4f
  578. wait0 decfsz 0x4f, f
  579. goto wait0
  580. return
  581. ; --------wait long: 8+(3*(w-1))+(772*w). W=0 -> 256!--------
  582. longwait
  583. movwf 0x4e
  584. clrw
  585. longwait0
  586. call wait
  587. decfsz 0x4e, f
  588. goto longwait0
  589. return
  590. ; --------change region in eeprom and die--------
  591. die
  592. banksel EEADR
  593. clrw
  594. movwf EEADR
  595. bsf EECON1, RD
  596. movf EEDAT, w
  597. banksel GPIO
  598. movwf 0x4d
  599. btfsc 0x4d, 0
  600. goto die_reg_6
  601. die_reg_9
  602. movlw 0x9 ; died with PAL, fall back to NTSC
  603. goto die_reg_cont
  604. die_reg_6
  605. movlw 0x6 ; died with NTSC, fall back to PAL
  606. die_reg_cont
  607. banksel EEADR
  608. movwf EEDAT
  609. bsf EECON1, WREN
  610. die_intloop
  611. bcf INTCON, GIE
  612. btfsc INTCON, GIE
  613. goto die_intloop
  614. movlw 0x55
  615. movwf EECON2
  616. movlw 0xaa
  617. movwf EECON2
  618. bsf EECON1, WR
  619. bsf INTCON, GIE
  620. banksel GPIO
  621. ; --------forever: blink status pin--------
  622. die_blink
  623. clrw
  624. call longwait
  625. bcf GPIO, 4
  626. call longwait
  627. bsf GPIO, 4
  628. goto die_blink
  629. ; -----------------------------------------------------------------------
  630. ; eeprom memory
  631. DEEPROM CODE
  632. de 0x09 ; D411 (NTSC)
  633. end