snescic-lock.asm 14 KB

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