spx_snes.asm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. ;------------------------------------------------------------------------------------------------------------------------
  2. ; Copyright (c) 2007, Mukunda Johnson
  3. ;
  4. ; All rights reserved.
  5. ;
  6. ; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  7. ;
  8. ; * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  9. ; * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  10. ; * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
  11. ;
  12. ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  13. ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  14. ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  15. ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  16. ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  17. ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  18. ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  19. ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  20. ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  21. ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. ;-----------------------------------------------------------------------------------
  24. .equ REG_APUI00 $2140
  25. .equ REG_APUI01 $2141
  26. .equ REG_APUI02 $2142
  27. .equ REG_APUI03 $2143
  28. .include "memmap.inc" ; replace with your memory definitions
  29. .MACRO SPX_RECEIVE_MESSAGE
  30. sta spx_message
  31. and #15
  32. jsl MessageReceived ; SET THIS TO YOUR MESSAGE HANDLER
  33. .ENDM
  34. .define SPX_STACK_SIZE $10 ; increase stack size if neccesary
  35. .define SPX_XMSOFFSET $2100
  36. .MACRO SPX_SYNC
  37. lda spx_validation ; load validation
  38. - cmp REG_APUI03 ; sync
  39. bne -
  40. .ENDM
  41. .ramsection "spx_var" BANK 0 SLOT 1
  42. spx_spvar: db
  43. spx_validation: db
  44. spx_package_adr: dsb 3
  45. spx_stack: dsb SPX_STACK_SIZE*4 ; FIFO stack
  46. spx_stack_r: dw ; stack read position
  47. spx_stack_w: dw ; stack write position
  48. spx_var1: dw
  49. spx_var2: dw
  50. spx_var3: dw
  51. spx_var4: dw
  52. spx_message: db
  53. ddd: db
  54. .ends
  55. .bank 0
  56. .SECTION "SPX_SNES"
  57. spx_binary:
  58. .incbin "spx_binaries\spx_core.bin"
  59. spx_lft:
  60. .incbin "spx_binaries\spx_lft.bin"
  61. spx_aft:
  62. .incbin "spx_binaries\spx_aft.bin"
  63. spx_aftf:
  64. .incbin "spx_binaries\spx_aftf.bin"
  65. .INDEX 16
  66. ;----------------------------------------------------------------------------------------------------
  67. BootSPC:
  68. ldx #spx_binary
  69. lda #:spx_binary
  70. ; x = source address (word) 16-BIT INDEX
  71. ; a = bank (byte) 8-BIT AKKU
  72. sei ; disable interrupts during upload
  73. stx spx_var1 ; store source address in var1
  74. sta spx_var1+2 ; store bank
  75. REP #$20 ; 16-bit akku
  76. lda #$BBAA ; Check if SPC is ready
  77. - cmp REG_APUI00 ;
  78. bne - ;
  79. SEP #$20 ; 8-bit akku
  80. ldy #0 ; reset data counter
  81. lda #0 ; reset port0 data (for protocol)
  82. xba ; swap out
  83. ; load first block
  84. lda #$01 ; port1 = NOT 0
  85. sta REG_APUI01 ;
  86. REP #$20 ; 16-bit akku
  87. lda [spx_var1], y ; load data transfer address
  88. iny ; increase data pointer
  89. iny ;
  90. sta REG_APUI02 ; ports2/3 = TRANSFER ADDRESS
  91. SEP #$20 ; 8-bit akku
  92. lda #$CC ; port0 = $CC (protocol)
  93. sta REG_APUI00 ;
  94. - cmp REG_APUI00 ; wait for SPC reply
  95. bne - ;
  96. REP #$20 ; 16-bit akku
  97. lda [spx_var1], y ; load data LENGTH
  98. tax ; transfer to X
  99. SEP #$20 ; 8-bit akku
  100. iny ; increase data pointer
  101. iny ;
  102. lda [spx_var1], y ; load first byte (real data)
  103. iny ; increase pointer
  104. sta REG_APUI01 ; port1 = data
  105. lda #0 ; port0 = 0 (start sending data)
  106. sta REG_APUI00 ;
  107. - cmp REG_APUI00 ; wait for SPC reply
  108. bne - ;
  109. dex ; prepare loop
  110. xba ; swap counter/data
  111. scr_data_loop:
  112. lda [spx_var1], y ; load byte
  113. iny ; inc pointer
  114. xba ; swap to counter
  115. - cmp REG_APUI00 ; check/wait for SPC reply
  116. bne - ;
  117. ina ; increase counter
  118. REP #$20 ; port1 = data
  119. sta REG_APUI00 ; port0 = counter
  120. SEP #$20 ;
  121. xba ; swap to data
  122. dex ; decrease loop counter
  123. bne scr_data_loop ; loop
  124. xba ; swap to counter
  125. - cmp REG_APUI00 ; check/wait for SPC reply
  126. bne - ;
  127. xba ; swap to data
  128. REP #$20 ; 16-bit akku
  129. pha ; preserve
  130. lda [spx_var1], y ; load next block size
  131. tax ; transfer to X
  132. pla ; restore
  133. SEP #$20 ; 8-bit akku
  134. iny ; increase data pointer
  135. iny ;
  136. cpx #0 ; load another block? (if block size is 0, then no)
  137. beq scr_terminate ; ...
  138. REP #$20 ; yes..
  139. pha ; preserve
  140. lda [spx_var1], y ; load something
  141. tax ; transfer to X
  142. pla ; restore
  143. SEP #$20 ; 8-bit akku
  144. iny ; increase pointer
  145. iny ;
  146. lda #1 ; port1 = NOT 0
  147. sta REG_APUI01 ;
  148. stx REG_APUI02 ; port2/3 = transfer address
  149. xba ; swap to counter
  150. ina ; counter += 2, != 0
  151. - ina ;
  152. beq - ;
  153. sta REG_APUI00 ; store in port0
  154. - cmp REG_APUI00 ; wait for SPC reply
  155. bne - ;
  156. bra scr_data_loop ; jump to data loop
  157. scr_terminate: ; no...
  158. stz REG_APUI01 ; port1 = 0
  159. REP #$20 ; 16-bit akku
  160. pha ; preserve
  161. lda [spx_var1], y ; load program start address
  162. tax ; transfer to X
  163. pla ; restore
  164. SEP #$20 ; 8-bit akku
  165. stx REG_APUI02 ; port2/3 = program start address
  166. xba ; swap to counter
  167. ina ; counter += 2, != 0
  168. - ina ;
  169. beq - ;
  170. sta REG_APUI00 ; port0 = counter
  171. - cmp REG_APUI00 ; wait for SPC reply
  172. bne - ;
  173. ; TRANSFER COMPLETE.
  174. cli ; enable interrupts
  175. jmp SPX_Init ; Initialize
  176. ;-----------------------------------------------------------------------------------------------------
  177. SPX_Init:
  178. lda #0 ; reset validation
  179. sta spx_validation
  180. sta spx_stack_w ; reset stack read/write
  181. sta spx_stack_r
  182. REP #$20
  183. lda #$FEED ; initial sync
  184. - cmp REG_APUI00 ;
  185. bne -
  186. SEP #$20
  187. RTL
  188. ;-----------------------------------------------------------------------------------------------------
  189. SPX_Transfer_XMS:
  190. ; ayy = 24-bit address
  191. sty spx_var1 ; save address
  192. sta spx_var2
  193. rep #$20 ; 16bit everything
  194. rep #$10
  195. lda [spx_var1] ; load length
  196. tax ; x = length/3
  197. ldy #SPX_XMSOFFSET
  198. lda spx_var1
  199. pha
  200. sep #$20
  201. lda spx_var2
  202. jsl SPX_Transfer
  203. ply
  204. rtl
  205. ;-----------------------------------------------------------------------------------------------------
  206. .accu 8
  207. SPX_Transfer_LFT:
  208. sep #$20 ; 8-bit akku
  209. rep #$10 ; 16-bit index
  210. ldx #(768/3) ; set transfer length (bytes/3)
  211. ldy #(spx_lft & 65535) ; load snes offset
  212. phy ; push
  213. ldy #$300 ; $300-$5FF = linear frequency LUT
  214. lda #:spx_lft ; get bank#
  215. JSL SPX_Transfer ; transfer data
  216. ply ; free stack
  217. lda.b #$1C ; set table
  218. sta REG_APUI02 ;
  219. stz REG_APUI01 ;
  220. JSL SPX_SEND ;
  221. RTL ; return
  222. ;-----------------------------------------------------------------------------------------------------
  223. SPX_Transfer_AFT:
  224. sep #$20 ; 8-bit akku
  225. rep #$10 ; 16-bit index
  226. ldx #(768/3) ; set transfer length (bytes/3)
  227. ldy #(spx_aft & 65535) ; load snes offset
  228. phy ; push
  229. ldy #$300 ; $300-$5FF = amiga period LUT
  230. lda #:spx_aft ; get bank#
  231. JSL SPX_Transfer ; transfer data
  232. ply ; free stack
  233. ldx #1365 ; 4096/3, rounded down
  234. ldy #(spx_aftf & 65535) ; load snes offset
  235. phy ; push
  236. ldy #$F000 ; $F000-$FFFF = amiga->freq LUT
  237. lda #:spx_aftf ; get bank#
  238. JSL SPX_Transfer ; transfer data
  239. ply ; free stack
  240. lda #$1C ; set table
  241. sta REG_APUI02 ;
  242. lda #$01 ;
  243. sta REG_APUI01 ;
  244. JSL SPX_SEND ;
  245. RTL ; return
  246. ;-----------------------------------------------------------------------------------------------------
  247. .INDEX 16
  248. .ACCU 8
  249. .MACRO SPX_TRANSFER_INCPOINTER
  250. iny ; increase pointer
  251. iny ;
  252. bpl ++ ; check for overflow
  253. cpy #$8001 ; check for an overflow reading
  254. bne + ; fix data if so
  255. dey ;
  256. dey ;
  257. lda [spx_var1], y ; read low byte
  258. sta REG_APUI00 ; store
  259. ldy #$0000 ; read high byte
  260. inc spx_var1+2 ; next bank
  261. lda [spx_var1], y ;
  262. sta REG_APUI01 ;
  263. iny ;
  264. lda spx_validation ;
  265. xba ;
  266. bra ++ ;
  267. + ; if not just increase bank#
  268. inc spx_var1+2 ; increase bank#
  269. ldy #$0000 ; reset counter
  270. ++
  271. .ENDM
  272. SPX_Transfer_SAMP:
  273. sei ; $14 = SAMPLE TRANSFER
  274. sta spx_var1+2 ;
  275. SPX_SYNC ;
  276. lda #$14 ;
  277. jmp SPX_TRANSFER_MOD;
  278. SPX_Transfer:
  279. ; SPX_Transfer
  280. ; parameters:
  281. ; a = file bank :8
  282. ; x = length/4 :16
  283. ; y = spc offset :16
  284. ; stack:1 = snes_offset :16
  285. ; types
  286. ; 0 = xms
  287. ; 1 = freq table
  288. sei ; disable interrupts
  289. sta spx_var1+2 ; store bank#
  290. SPX_SYNC ; sync with spc
  291. lda #$1A ; $1A = GENERIC TRANSFER
  292. SPX_TRANSFER_MOD:
  293. sta REG_APUI02 ; set message type
  294. REP #$20 ; set spc write position
  295. tya ;
  296. SEP #$20 ;
  297. sta REG_APUI00 ;
  298. xba ;
  299. sta REG_APUI01 ;
  300. lda spx_validation ; validate data
  301. eor #128 ;
  302. ora #1
  303. sta REG_APUI03 ;
  304. - cmp REG_APUI03 ; wait for spc to respond
  305. bne -
  306. ; eor #128 ; prepare transfer mode
  307. sta spx_validation ; save
  308. REP #$20 ; 16-bit akku
  309. lda 4, S ; load file offset sp+4
  310. sec ; set carry
  311. sbc #$8000 ; subtract
  312. tay ; transfer to y
  313. SEP #$20 ; 8-bit akku
  314. lda #$80 ; set offset in var1
  315. stz spx_var1 ; reset mem pointers
  316. sta spx_var1+1 ;
  317. REP #$20 ; 16-bit akku
  318. _stf_start: ; loop:
  319. lda [spx_var1], y ; load data
  320. sta spx_var3 ; save
  321. SPX_TRANSFER_INCPOINTER
  322. sep #$20
  323. lda [spx_var1], y ; get third byte
  324. iny ; increase pointer
  325. bpl +
  326. ldy #$0000
  327. inc spx_var1+2
  328. +
  329. sta spx_spvar ; store
  330. lda spx_validation ; get validation
  331. eor #128 ;
  332. sta spx_validation ; update
  333. eor #128 ; reverse
  334. phx ; preserve
  335. ldx spx_spvar ; get ready
  336. - cmp REG_APUI03 ; sync with spc
  337. bne - ;
  338. lda spx_var3 ; load byte1
  339. sta REG_APUI00 ; store byte1
  340. lda spx_var3+1 ; load byte2
  341. sta REG_APUI01 ; store byte2
  342. stx REG_APUI02 ; store byte3/validation
  343. plx ; restore
  344. rep #$20
  345. dex ; decrease counter
  346. bne _stf_start ; loop until finished
  347. sep #$20
  348. stz REG_APUI03 ; send 0
  349. stz spx_validation
  350. lda #0
  351. - cmp REG_APUI03 ; wait for reply
  352. bne -
  353. cli ; enable interrupts
  354. RTL ; return --make sure higher function frees stack space
  355. ;--------------------------------------------------------------------------------------------------------
  356. .index 16
  357. SPX_Queue:
  358. ; a = $00/$01 message
  359. ; x = $02/$03 params
  360. ; accumulator can be 8 or 16 bit, do not read anything with it
  361. ldy spx_stack_w ; load stack position
  362. sta spx_stack, y ; store bytes0/1
  363. iny ; increase pointer
  364. iny
  365. txa ; get high word
  366. sta spx_stack, y ; store bytes 2/3
  367. iny ; increase pointer
  368. iny
  369. cpy #SPX_STACK_SIZE*4 ; wrap to stack size
  370. bcc +
  371. ldy #0
  372. +
  373. sty spx_stack_w ; save stack position
  374. rtl
  375. ;---------------------------------------------------------------------------------------------------------
  376. .accu 8
  377. SPX_Routine:
  378. ; get messages
  379. lda REG_APUI00 ; check if port0 is different
  380. cmp spx_message
  381. beq +
  382. SPX_RECEIVE_MESSAGE ; if so then a message was received
  383. +
  384. lda spx_validation ; check if spc has processed last message
  385. cmp REG_APUI03
  386. beq +
  387. rtl ; not ready
  388. +
  389. ldy spx_stack_r ; load stack read position
  390. cpy spx_stack_w ; exit function if it equals write position (no messages)
  391. bne +
  392. rtl
  393. +
  394. lda spx_stack, y ; load byte0
  395. sta REG_APUI00 ; store
  396. iny
  397. lda spx_stack, y ; load byte1
  398. sta REG_APUI01 ; store
  399. iny
  400. lda spx_stack, y ; load byte2
  401. sta REG_APUI02 ; store
  402. iny
  403. lda spx_stack, y ; load byte3
  404. lda spx_validation ; add validation
  405. and #128
  406. eor #128
  407. ora spx_stack, y ; store
  408. sta REG_APUI03 ; message dispatched
  409. sta spx_validation ; save validation
  410. iny
  411. cpy #SPX_STACK_SIZE*4 ; wrap read counter to stack size
  412. bcc +
  413. ldy #0
  414. +
  415. sty spx_stack_r ; save
  416. rtl
  417. SPX_Flush: ; flushes queue
  418. jsl SPX_Routine ; call routine
  419. ldy spx_stack_r ; check for more messages
  420. cpy spx_stack_w
  421. bne SPX_Flush ; loop
  422. rtl ; exit
  423. SPXM_Play:
  424. ldx #$1E ; $1E = play message
  425. jmp SPX_Queue
  426. SPXM_BuildDir:
  427. ldx #$1B ; $1B = build directory
  428. jmp SPX_Queue
  429. SPXM_Reset: ; blocking function
  430. ldx #$1D ; $1D = RESET XMS
  431. jmp SPX_Queue
  432. SPXM_SetVol:
  433. ; a = volume
  434. ldx #$18 ; $18 = set XM playback volume
  435. jmp SPX_Queue
  436. SPX_SetVol:
  437. ; a = volume L } 16bit akku
  438. ; b = volume R } resets afterwards
  439. ldx #$19 ; $19 = change main volume
  440. jmp SPX_Queue
  441. .accu 8
  442. .index 16
  443. SPXS_Play:
  444. ; a = volume [llllrrrr]
  445. ; x = sample#/priority/frequency [0ccfffffssssssss]
  446. pha ; rearrange data
  447. rep #$20
  448. txa
  449. sep #$20
  450. pha
  451. rep #$20
  452. and #$FF00
  453. ora #$20 ; $20 = play sample
  454. tax
  455. sep #$20
  456. pla
  457. xba
  458. pla
  459. rep #$20
  460. jsl SPX_Queue
  461. sep #$20
  462. rtl
  463. SPXS_SetParam:
  464. ; a = index
  465. ; x = param
  466. xba ; rearrange data
  467. tax
  468. xba
  469. rep #$20
  470. ldx #$21 ; $21 = message
  471. jsl SPX_Queue ; queue
  472. sep #$20
  473. rtl
  474. SPX_SEND: ; blocking send
  475. lda spx_validation ; get validation
  476. eor #128 ; change
  477. sta REG_APUI03 ; set port data
  478. sta spx_validation ; save validation
  479. - cmp REG_APUI03 ; wait for spc reply
  480. bne -
  481. RTL ; exit
  482. SPXP_InstallPackage:
  483. ; x = address (16-bit) ;
  484. ; a = bank#
  485. stx spx_package_adr ; store offset
  486. sta spx_package_adr+2 ; store bank
  487. rtl
  488. SPXP_LoadSong:
  489. ; x = index (16-bit)
  490. sep #$20 ; 8bit akku
  491. txa ; a=x
  492. sta $4202 ; multiply a*3
  493. lda #3 ;
  494. sta $4203 ; 8 cycles... ; ...
  495. ; setup send
  496. rep #$20 ; read package address
  497. lda #$10
  498. nop
  499. nop
  500. nop ; small delay
  501. clc
  502. adc $4216 ; add multiplication result
  503. tay ; y=result
  504. lda spx_package_adr ; read package address
  505. adc [spx_package_adr], y ; add song offset
  506. ora #$8000 ;
  507. pha ; save result
  508. sep #$20 ; 8bit akku
  509. lda spx_package_adr+2 ; load bank#
  510. iny
  511. iny
  512. adc [spx_package_adr], y ; add song offset
  513. ply ; restore address
  514. jsl SPX_Transfer_XMS ; transfer song
  515. ; transfer samples
  516. SPX_SYNC
  517. lda #$17 ; ask for sample requests
  518. sta REG_APUI02
  519. jsl SPX_SEND
  520. --
  521. ; message received
  522. lda REG_APUI02 ; satisfy request
  523. cmp #$9C ; 9c = no more samples
  524. beq +
  525. ldx REG_APUI00
  526. ldy #0
  527. jsl SPXP_LoadSample ; send sample
  528. jsl SPX_SEND ; sync
  529. jmp --
  530. +
  531. rtl
  532. SPXP_LoadSample:
  533. ; x = index (16-bit)
  534. ; y = spc address, 0=use next available
  535. rep #$20 ; 16-bit akku
  536. txa ; a=x
  537. sta spx_var1 ; save
  538. asl ; shift
  539. adc spx_var1 ; add (a = index*3 now)
  540. phy
  541. ldy #4
  542. adc [spx_package_adr],y ; add sample table offset
  543. tay
  544. clc
  545. lda spx_package_adr
  546. adc [spx_package_adr], y
  547. ora #$8000 ; wrap around ROM area if overflow
  548. sta spx_var1
  549. sep #$20
  550. lda spx_package_adr+2
  551. iny
  552. iny
  553. adc [spx_package_adr], y
  554. adc #0 ; increase on overflow
  555. sta spx_var2
  556. rep #$20
  557. lda [spx_var1] ; load sample size/3
  558. tax ; transfer to x
  559. lda spx_var1 ; load snes address
  560. ply
  561. pha
  562. sep #$20 ; 8-bit akku
  563. lda spx_var2 ; load bank#
  564. jsl SPX_Transfer_SAMP ; transfer data
  565. ply ; restore stack
  566. lda spx_validation ; get sample #
  567. eor #128
  568. sta REG_APUI03
  569. - cmp REG_APUI03
  570. bne -
  571. sta spx_validation
  572. lda REG_APUI00
  573. rtl ; return
  574. .ENDS