serial.asm 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. Serial::
  2. push af
  3. push bc
  4. push de
  5. push hl
  6. ld a, [hSerialConnectionStatus]
  7. inc a
  8. jr z, .connectionNotYetEstablished
  9. ld a, [rSB]
  10. ld [hSerialReceiveData], a
  11. ld a, [hSerialSendData]
  12. ld [rSB], a
  13. ld a, [hSerialConnectionStatus]
  14. cp USING_INTERNAL_CLOCK
  15. jr z, .done
  16. ; using external clock
  17. ld a, START_TRANSFER_EXTERNAL_CLOCK
  18. ld [rSC], a
  19. jr .done
  20. .connectionNotYetEstablished
  21. ld a, [rSB]
  22. ld [hSerialReceiveData], a
  23. ld [hSerialConnectionStatus], a
  24. cp USING_INTERNAL_CLOCK
  25. jr z, .usingInternalClock
  26. ; using external clock
  27. xor a
  28. ld [rSB], a
  29. ld a, $3
  30. ld [rDIV], a
  31. .waitLoop
  32. ld a, [rDIV]
  33. bit 7, a
  34. jr nz, .waitLoop
  35. ld a, START_TRANSFER_EXTERNAL_CLOCK
  36. ld [rSC], a
  37. jr .done
  38. .usingInternalClock
  39. xor a
  40. ld [rSB], a
  41. .done
  42. ld a, $1
  43. ld [hSerialReceivedNewData], a
  44. ld a, SERIAL_NO_DATA_BYTE
  45. ld [hSerialSendData], a
  46. pop hl
  47. pop de
  48. pop bc
  49. pop af
  50. reti
  51. ; hl = send data
  52. ; de = receive data
  53. ; bc = length of data
  54. Serial_ExchangeBytes::
  55. ld a, 1
  56. ld [hSerialIgnoringInitialData], a
  57. .loop
  58. ld a, [hl]
  59. ld [hSerialSendData], a
  60. call Serial_ExchangeByte
  61. push bc
  62. ld b, a
  63. inc hl
  64. ld a, 48
  65. .waitLoop
  66. dec a
  67. jr nz, .waitLoop
  68. ld a, [hSerialIgnoringInitialData]
  69. and a
  70. ld a, b
  71. pop bc
  72. jr z, .storeReceivedByte
  73. dec hl
  74. cp SERIAL_PREAMBLE_BYTE
  75. jr nz, .loop
  76. xor a
  77. ld [hSerialIgnoringInitialData], a
  78. jr .loop
  79. .storeReceivedByte
  80. ld [de], a
  81. inc de
  82. dec bc
  83. ld a, b
  84. or c
  85. jr nz, .loop
  86. ret
  87. Serial_ExchangeByte::
  88. xor a
  89. ld [hSerialReceivedNewData], a
  90. ld a, [hSerialConnectionStatus]
  91. cp USING_INTERNAL_CLOCK
  92. jr nz, .loop
  93. ld a, START_TRANSFER_INTERNAL_CLOCK
  94. ld [rSC], a
  95. .loop
  96. ld a, [hSerialReceivedNewData]
  97. and a
  98. jr nz, .ok
  99. ld a, [hSerialConnectionStatus]
  100. cp USING_EXTERNAL_CLOCK
  101. jr nz, .doNotIncrementUnknownCounter
  102. call IsUnknownCounterZero
  103. jr z, .doNotIncrementUnknownCounter
  104. call WaitLoop_15Iterations
  105. push hl
  106. ld hl, wUnknownSerialCounter + 1
  107. inc [hl]
  108. jr nz, .noCarry
  109. dec hl
  110. inc [hl]
  111. .noCarry
  112. pop hl
  113. call IsUnknownCounterZero
  114. jr nz, .loop
  115. jp SetUnknownCounterToFFFF
  116. .doNotIncrementUnknownCounter
  117. ld a, [rIE]
  118. and (1 << SERIAL) | (1 << TIMER) | (1 << LCD_STAT) | (1 << VBLANK)
  119. cp (1 << SERIAL)
  120. jr nz, .loop
  121. ld a, [wUnknownSerialCounter2]
  122. dec a
  123. ld [wUnknownSerialCounter2], a
  124. jr nz, .loop
  125. ld a, [wUnknownSerialCounter2 + 1]
  126. dec a
  127. ld [wUnknownSerialCounter2 + 1], a
  128. jr nz, .loop
  129. ld a, [hSerialConnectionStatus]
  130. cp USING_EXTERNAL_CLOCK
  131. jr z, .ok
  132. ld a, 255
  133. .waitLoop
  134. dec a
  135. jr nz, .waitLoop
  136. .ok
  137. xor a
  138. ld [hSerialReceivedNewData], a
  139. ld a, [rIE]
  140. and (1 << SERIAL) | (1 << TIMER) | (1 << LCD_STAT) | (1 << VBLANK)
  141. sub (1 << SERIAL)
  142. jr nz, .skipReloadingUnknownCounter2
  143. ld [wUnknownSerialCounter2], a
  144. ld a, $50
  145. ld [wUnknownSerialCounter2 + 1], a
  146. .skipReloadingUnknownCounter2
  147. ld a, [hSerialReceiveData]
  148. cp SERIAL_NO_DATA_BYTE
  149. ret nz
  150. call IsUnknownCounterZero
  151. jr z, .done
  152. push hl
  153. ld hl, wUnknownSerialCounter + 1
  154. ld a, [hl]
  155. dec a
  156. ld [hld], a
  157. inc a
  158. jr nz, .noBorrow
  159. dec [hl]
  160. .noBorrow
  161. pop hl
  162. call IsUnknownCounterZero
  163. jr z, SetUnknownCounterToFFFF
  164. .done
  165. ld a, [rIE]
  166. and (1 << SERIAL) | (1 << TIMER) | (1 << LCD_STAT) | (1 << VBLANK)
  167. cp (1 << SERIAL)
  168. ld a, SERIAL_NO_DATA_BYTE
  169. ret z
  170. ld a, [hl]
  171. ld [hSerialSendData], a
  172. call DelayFrame
  173. jp Serial_ExchangeByte
  174. WaitLoop_15Iterations::
  175. ld a, 15
  176. .waitLoop
  177. dec a
  178. jr nz, .waitLoop
  179. ret
  180. IsUnknownCounterZero::
  181. push hl
  182. ld hl, wUnknownSerialCounter
  183. ld a, [hli]
  184. or [hl]
  185. pop hl
  186. ret
  187. ; a is always 0 when this is called
  188. SetUnknownCounterToFFFF::
  189. dec a
  190. ld [wUnknownSerialCounter], a
  191. ld [wUnknownSerialCounter + 1], a
  192. ret
  193. ; This is used to exchange the button press and selected menu item on the link menu.
  194. ; The data is sent thrice and read twice to increase reliability.
  195. Serial_ExchangeLinkMenuSelection::
  196. ld hl, wLinkMenuSelectionSendBuffer
  197. ld de, wLinkMenuSelectionReceiveBuffer
  198. ld c, 2 ; number of bytes to save
  199. ld a, 1
  200. ld [hSerialIgnoringInitialData], a
  201. .loop
  202. call DelayFrame
  203. ld a, [hl]
  204. ld [hSerialSendData], a
  205. call Serial_ExchangeByte
  206. ld b, a
  207. inc hl
  208. ld a, [hSerialIgnoringInitialData]
  209. and a
  210. ld a, 0
  211. ld [hSerialIgnoringInitialData], a
  212. jr nz, .loop
  213. ld a, b
  214. ld [de], a
  215. inc de
  216. dec c
  217. jr nz, .loop
  218. ret
  219. Serial_PrintWaitingTextAndSyncAndExchangeNybble::
  220. call SaveScreenTilesToBuffer1
  221. callab PrintWaitingText
  222. call Serial_SyncAndExchangeNybble
  223. jp LoadScreenTilesFromBuffer1
  224. Serial_SyncAndExchangeNybble::
  225. ld a, $ff
  226. ld [wSerialExchangeNybbleReceiveData], a
  227. .loop1
  228. call Serial_ExchangeNybble
  229. call DelayFrame
  230. call IsUnknownCounterZero
  231. jr z, .next1
  232. push hl
  233. ld hl, wUnknownSerialCounter + 1
  234. dec [hl]
  235. jr nz, .next2
  236. dec hl
  237. dec [hl]
  238. jr nz, .next2
  239. pop hl
  240. xor a
  241. jp SetUnknownCounterToFFFF
  242. .next2
  243. pop hl
  244. .next1
  245. ld a, [wSerialExchangeNybbleReceiveData]
  246. inc a
  247. jr z, .loop1
  248. ld b, 10
  249. .loop2
  250. call DelayFrame
  251. call Serial_ExchangeNybble
  252. dec b
  253. jr nz, .loop2
  254. ld b, 10
  255. .loop3
  256. call DelayFrame
  257. call Serial_SendZeroByte
  258. dec b
  259. jr nz, .loop3
  260. ld a, [wSerialExchangeNybbleReceiveData]
  261. ld [wSerialSyncAndExchangeNybbleReceiveData], a
  262. ret
  263. Serial_ExchangeNybble::
  264. call .doExchange
  265. ld a, [wSerialExchangeNybbleSendData]
  266. add $60
  267. ld [hSerialSendData], a
  268. ld a, [hSerialConnectionStatus]
  269. cp USING_INTERNAL_CLOCK
  270. jr nz, .doExchange
  271. ld a, START_TRANSFER_INTERNAL_CLOCK
  272. ld [rSC], a
  273. .doExchange
  274. ld a, [hSerialReceiveData]
  275. ld [wSerialExchangeNybbleTempReceiveData], a
  276. and $f0
  277. cp $60
  278. ret nz
  279. xor a
  280. ld [hSerialReceiveData], a
  281. ld a, [wSerialExchangeNybbleTempReceiveData]
  282. and $f
  283. ld [wSerialExchangeNybbleReceiveData], a
  284. ret
  285. Serial_SendZeroByte::
  286. xor a
  287. ld [hSerialSendData], a
  288. ld a, [hSerialConnectionStatus]
  289. cp USING_INTERNAL_CLOCK
  290. ret nz
  291. ld a, START_TRANSFER_INTERNAL_CLOCK
  292. ld [rSC], a
  293. ret
  294. Serial_TryEstablishingExternallyClockedConnection::
  295. ld a, ESTABLISH_CONNECTION_WITH_EXTERNAL_CLOCK
  296. ld [rSB], a
  297. xor a
  298. ld [hSerialReceiveData], a
  299. ld a, START_TRANSFER_EXTERNAL_CLOCK
  300. ld [rSC], a
  301. ret