draw2_arm.S 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. /*
  2. * assembly optimized versions of most funtions from draw2.c
  3. * (C) notaz, 2006-2008
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. *
  8. * this is highly specialized, be careful if changing related C code!
  9. */
  10. #include "pico_int_offs.h"
  11. @ define these constants in your include file:
  12. @ .equiv START_ROW, 1
  13. @ .equiv END_ROW, 27
  14. @ one row means 8 pixels. If above example was used, (27-1)*8=208 lines would be rendered.
  15. #ifndef START_ROW
  16. #define START_ROW 0
  17. #endif
  18. #ifndef END_ROW
  19. #define END_ROW 28
  20. #endif
  21. .text
  22. .align 2
  23. @ void BackFillFull(void *dst, int reg7)
  24. .global BackFillFull
  25. BackFillFull:
  26. stmfd sp!, {r4-r9,lr}
  27. add lr, r0, #328*8
  28. mov r0, r1, lsl #26
  29. mov r0, r0, lsr #26
  30. orr r0, r0, r0, lsl #8
  31. orr r0, r0, r0, lsl #16
  32. mov r1, r0 @ 25 opcodes wasted?
  33. mov r2, r0
  34. mov r3, r0
  35. mov r4, r0
  36. mov r5, r0
  37. mov r6, r0
  38. mov r7, r0
  39. mov r8, r0
  40. mov r9, r0
  41. mov r12, #(END_ROW-START_ROW)*8
  42. @ go go go!
  43. .bff_loop:
  44. add lr, lr, #8
  45. subs r12, r12, #1
  46. stmia lr!, {r0-r9} @ 10*4*8
  47. stmia lr!, {r0-r9}
  48. stmia lr!, {r0-r9}
  49. stmia lr!, {r0-r9}
  50. stmia lr!, {r0-r9}
  51. stmia lr!, {r0-r9}
  52. stmia lr!, {r0-r9}
  53. stmia lr!, {r0-r9}
  54. bne .bff_loop
  55. ldmfd sp!, {r4-r9,lr}
  56. bx lr
  57. .pool
  58. @ -------- some macros --------
  59. @ helpers
  60. .macro add_c24 d s c
  61. add \d, \s, #(\c & 0x00ff00)
  62. .if \c & 0x0000ff
  63. add \d, \d, #(\c & 0x0000ff)
  64. .endif
  65. .if \c & 0xff0000
  66. add \d, \d, #(\c & 0xff0000)
  67. .endif
  68. .endm
  69. @ TileLineSinglecol (r1=pdest, r2=pixels8, r3=pal) r4: scratch, r0: pixels8_old
  70. .macro TileLineSinglecol notsinglecol=0
  71. and r2, r2, #0xf @ #0x0000000f
  72. .if !\notsinglecol
  73. cmp r2, r0, lsr #28 @ if these don't match,
  74. bicne r9, r9, #2 @ it is a sign that whole tile is not singlecolor (only it's lines may be)
  75. .endif
  76. orr r4, r3, r2
  77. orr r4, r4, r4, lsl #8
  78. tst r1, #1 @ not aligned?
  79. strneb r4, [r1], #1
  80. streqh r4, [r1], #2
  81. strh r4, [r1], #2
  82. strh r4, [r1], #2
  83. strh r4, [r1], #2
  84. strneb r4, [r1], #1 @ have a remaining unaligned pixel?
  85. sub r1, r1, #8
  86. .if !\notsinglecol
  87. mov r0, #0xf
  88. orr r0, r0, r2, lsl #28 @ we will need the old palindex later
  89. .endif
  90. .endm
  91. @ TileNorm (r1=pdest, r2=pixels8, r3=pal) r0,r4: scratch
  92. .macro TileLineNorm
  93. ands r4, r0, r2, lsr #12 @ #0x0000f000
  94. orrne r4, r3, r4
  95. strneb r4, [r1]
  96. ands r4, r0, r2, lsr #8 @ #0x00000f00
  97. orrne r4, r3, r4
  98. strneb r4, [r1,#1]
  99. ands r4, r0, r2, lsr #4 @ #0x000000f0
  100. orrne r4, r3, r4
  101. strneb r4, [r1,#2]
  102. ands r4, r0, r2 @ #0x0000000f
  103. orrne r4, r3, r4
  104. strneb r4, [r1,#3]
  105. ands r4, r0, r2, lsr #28 @ #0xf0000000
  106. orrne r4, r3, r4
  107. strneb r4, [r1,#4]
  108. ands r4, r0, r2, lsr #24 @ #0x0f000000
  109. orrne r4, r3, r4
  110. strneb r4, [r1,#5]
  111. ands r4, r0, r2, lsr #20 @ #0x00f00000
  112. orrne r4, r3, r4
  113. strneb r4, [r1,#6]
  114. ands r4, r0, r2, lsr #16 @ #0x000f0000
  115. orrne r4, r3, r4
  116. strneb r4, [r1,#7]
  117. .endm
  118. @ TileFlip (r1=pdest, r2=pixels8, r3=pal) r0,r4: scratch
  119. .macro TileLineFlip
  120. ands r4, r0, r2, lsr #16 @ #0x000f0000
  121. orrne r4, r3, r4
  122. strneb r4, [r1]
  123. ands r4, r0, r2, lsr #20 @ #0x00f00000
  124. orrne r4, r3, r4
  125. strneb r4, [r1,#1]
  126. ands r4, r0, r2, lsr #24 @ #0x0f000000
  127. orrne r4, r3, r4
  128. strneb r4, [r1,#2]
  129. ands r4, r0, r2, lsr #28 @ #0xf0000000
  130. orrne r4, r3, r4
  131. strneb r4, [r1,#3]
  132. ands r4, r0, r2 @ #0x0000000f
  133. orrne r4, r3, r4
  134. strneb r4, [r1,#4]
  135. ands r4, r0, r2, lsr #4 @ #0x000000f0
  136. orrne r4, r3, r4
  137. strneb r4, [r1,#5]
  138. ands r4, r0, r2, lsr #8 @ #0x00000f00
  139. orrne r4, r3, r4
  140. strneb r4, [r1,#6]
  141. ands r4, r0, r2, lsr #12 @ #0x0000f000
  142. orrne r4, r3, r4
  143. strneb r4, [r1,#7]
  144. .endm
  145. @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=Pico.vram) r2,r4,r7: scratch, r0=0xf
  146. .macro Tile hflip vflip
  147. mov r7, r9, lsl #13 @ r9=code<<8; addr=(code&0x7ff)<<4;
  148. add r7, r10, r7, lsr #16
  149. orr r9, r9, #3 @ emptytile=singlecolor=1, r9 must be <code_16> 00000xxx
  150. .if \vflip
  151. @ we read tilecodes in reverse order if we have vflip
  152. add r7, r7, #8*4
  153. .endif
  154. @ loop through 8 lines
  155. orr r9, r9, #(7<<24)
  156. b 1f @ loop_enter
  157. 0: @ singlecol_loop
  158. subs r9, r9, #(1<<24)
  159. add r1, r1, #328 @ set pointer to next line
  160. bmi 8f @ loop_exit with r0 restore
  161. 1:
  162. .if \vflip
  163. ldr r2, [r7, #-4]! @ pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels
  164. .else
  165. ldr r2, [r7], #4
  166. .endif
  167. tst r2, r2
  168. beq 2f @ empty line
  169. bic r9, r9, #1
  170. cmp r2, r2, ror #4
  171. bne 3f @ not singlecolor
  172. TileLineSinglecol
  173. b 0b
  174. 2:
  175. bic r9, r9, #2
  176. 2: @ empty_loop
  177. subs r9, r9, #(1<<24)
  178. add r1, r1, #328 @ set pointer to next line
  179. bmi 8f @ loop_exit with r0 restore
  180. .if \vflip
  181. ldr r2, [r7, #-4]! @ next pack
  182. .else
  183. ldr r2, [r7], #4
  184. .endif
  185. mov r0, #0xf @ singlecol_loop might have messed r0
  186. tst r2, r2
  187. beq 2b
  188. bic r9, r9, #3 @ if we are here, it means we have empty and not empty line
  189. b 5f
  190. 3: @ not empty, not singlecol
  191. mov r0, #0xf
  192. bic r9, r9, #3
  193. b 6f
  194. 4: @ not empty, not singlecol loop
  195. subs r9, r9, #(1<<24)
  196. add r1, r1, #328 @ set pointer to next line
  197. bmi 9f @ loop_exit
  198. .if \vflip
  199. ldr r2, [r7, #-4]! @ next pack
  200. .else
  201. ldr r2, [r7], #4
  202. .endif
  203. tst r2, r2
  204. beq 4b @ empty line
  205. 5:
  206. cmp r2, r2, ror #4
  207. beq 7f @ singlecolor line
  208. 6:
  209. .if \hflip
  210. TileLineFlip
  211. .else
  212. TileLineNorm
  213. .endif
  214. b 4b
  215. 7:
  216. TileLineSinglecol 1
  217. b 4b
  218. 8:
  219. mov r0, #0xf
  220. 9: @ loop_exit
  221. add r9, r9, #(1<<24) @ fix r9
  222. sub r1, r1, #328*8 @ restore pdest pointer
  223. .endm
  224. @ TileLineSinglecolAl (r1=pdest, r4,r7=color)
  225. .macro TileLineSinglecolAl0
  226. stmia r1!, {r4,r7}
  227. add r1, r1, #320
  228. .endm
  229. .macro TileLineSinglecolAl1
  230. strb r4, [r1], #1
  231. strh r4, [r1], #2
  232. str r4, [r1], #4
  233. strb r4, [r1], #1+320
  234. @ add r1, r1, #320
  235. .endm
  236. .macro TileLineSinglecolAl2
  237. strh r4, [r1], #2
  238. str r4, [r1], #4
  239. strh r4, [r1], #2
  240. add r1, r1, #320
  241. .endm
  242. .macro TileLineSinglecolAl3
  243. strb r4, [r1], #1
  244. str r4, [r1], #4
  245. strh r4, [r1], #2
  246. strb r4, [r1], #1+320
  247. @ add r1, r1, #320
  248. .endm
  249. @ TileSinglecol (r1=pdest, r2=pixels8, r3=pal) r4,r7: scratch, r0=0xf
  250. @ kaligned==1, if dest is always aligned
  251. .macro TileSinglecol kaligned=0
  252. and r4, r2, #0xf @ we assume we have good r2 from previous time
  253. orr r4, r4, r3
  254. orr r4, r4, r4, lsl #8
  255. orr r4, r4, r4, lsl #16
  256. mov r7, r4
  257. .if !\kaligned
  258. tst r1, #2 @ not aligned?
  259. bne 2f
  260. tst r1, #1
  261. bne 1f
  262. .endif
  263. TileLineSinglecolAl0
  264. TileLineSinglecolAl0
  265. TileLineSinglecolAl0
  266. TileLineSinglecolAl0
  267. TileLineSinglecolAl0
  268. TileLineSinglecolAl0
  269. TileLineSinglecolAl0
  270. TileLineSinglecolAl0
  271. .if !\kaligned
  272. b 4f
  273. 1:
  274. TileLineSinglecolAl1
  275. TileLineSinglecolAl1
  276. TileLineSinglecolAl1
  277. TileLineSinglecolAl1
  278. TileLineSinglecolAl1
  279. TileLineSinglecolAl1
  280. TileLineSinglecolAl1
  281. TileLineSinglecolAl1
  282. b 4f
  283. 2:
  284. tst r1, #1
  285. bne 3f
  286. TileLineSinglecolAl2
  287. TileLineSinglecolAl2
  288. TileLineSinglecolAl2
  289. TileLineSinglecolAl2
  290. TileLineSinglecolAl2
  291. TileLineSinglecolAl2
  292. TileLineSinglecolAl2
  293. TileLineSinglecolAl2
  294. b 4f
  295. 3:
  296. TileLineSinglecolAl3
  297. TileLineSinglecolAl3
  298. TileLineSinglecolAl3
  299. TileLineSinglecolAl3
  300. TileLineSinglecolAl3
  301. TileLineSinglecolAl3
  302. TileLineSinglecolAl3
  303. TileLineSinglecolAl3
  304. 4:
  305. .endif
  306. sub r1, r1, #328*8 @ restore pdest pointer
  307. .endm
  308. @ DrawLayerTiles(*hcache, *scrpos, (cells<<24)|(nametab<<9)|(vscroll&0x3ff)<<11|(shift[width]<<8)|planeend, (ymask<<24)|(planestart<<16)|[htab||hscroll]
  309. @ void DrawLayerFull(int plane, int *hcache, int planestart, int planeend,
  310. @ struct PicoEState *est)
  311. .global DrawLayerFull
  312. DrawLayerFull:
  313. ldr r12,[sp] @ est
  314. stmfd sp!, {r4-r11,lr}
  315. mov r6, r1 @ hcache
  316. ldr r11, [r12, #OFS_EST_Pico]
  317. ldr r10, [r12, #OFS_EST_PicoMem_vram]
  318. ldrb r5, [r11, #OFS_Pico_video_reg+13] @ pvid->reg[13]
  319. ldrb r7, [r11, #OFS_Pico_video_reg+11]
  320. sub lr, r3, r2
  321. and lr, lr, #0x00ff0000 @ lr=cells
  322. mov r5, r5, lsl #10 @ htab=pvid->reg[13]<<9; (halfwords)
  323. add r5, r5, r0, lsl #1 @ htab+=plane
  324. bic r5, r5, #0x00ff0000 @ just in case
  325. tst r7, #3 @ full screen scroll? (if ==0)
  326. ldrb r7, [r11, #OFS_Pico_video_reg+16] @ ??hh??ww
  327. ldreqh r5, [r10, r5]
  328. biceq r5, r5, #0x0000fc00 @ r5=hscroll (0-0x3ff)
  329. movne r5, r5, lsr #1
  330. orrne r5, r5, #0x8000 @ this marks that we have htab pointer, not hscroll here
  331. and r8, r7, #3
  332. orr r5, r5, r7, lsl #1+24
  333. orr r5, r5, #0x1f000000
  334. cmp r8, #1
  335. biclt r5, r5, #0x80000000
  336. biceq r5, r5, #0xc0000000
  337. bicgt r5, r5, #0xe0000000
  338. mov r9, r2, lsl #24
  339. orr r5, r5, r9, lsr #8 @ r5=(ymask<<24)|(trow<<16)|[htab||hscroll]
  340. add r4, r8, #5
  341. cmp r4, #7
  342. subge r4, r4, #1 @ r4=shift[width] (5,6,6,7)
  343. orr lr, lr, r4
  344. orr lr, lr, r3, lsl #24 @ lr=(planeend<<24)|(cells<<16)|shift[width]
  345. @ calculate xmask:
  346. mov r8, r8, lsl #24+5
  347. orr r8, r8, #0x1f000000
  348. @ Find name table:
  349. tst r0, r0
  350. ldreqb r4, [r11, #OFS_Pico_video_reg+2]
  351. moveq r4, r4, lsr #3
  352. ldrneb r4, [r11, #OFS_Pico_video_reg+4]
  353. and r4, r4, #7
  354. orr lr, lr, r4, lsl #13 @ lr|=nametab_bits{3}<<13
  355. ldr r11,[sp, #9*4] @ est
  356. sub r4, r9, #(START_ROW<<24)
  357. ldr r11, [r11, #OFS_EST_Draw2FB]
  358. mov r4, r4, asr #24
  359. mov r7, #328*8
  360. mla r11, r4, r7, r11 @ scrpos+=8*328*(planestart-START_ROW);
  361. @ Get vertical scroll value:
  362. add_c24 r7, r10, (OFS_PMEM_vsram-OFS_PMEM_vram)
  363. ldr r7, [r7]
  364. tst r0, r0
  365. moveq r7, r7, lsl #22
  366. movne r7, r7, lsl #6
  367. mov r7, r7, lsr #22 @ r7=vscroll (10 bits)
  368. orr lr, lr, r7, lsl #3
  369. mov lr, lr, ror #24 @ packed: cccccccc nnnvvvvv vvvvvsss pppppppp: cells, nametab, vscroll, shift[width], planeend
  370. ands r7, r7, #7
  371. addne lr, lr, #1 @ we have vertically clipped tiles due to vscroll, so we need 1 more row
  372. rsb r7, r7, #8
  373. str r7, [r6], #4 @ push y-offset to tilecache
  374. mov r4, #328
  375. mla r11, r4, r7, r11 @ scrpos+=(8-(vscroll&7))*328;
  376. mov r9, #0xff000000 @ r9=(prevcode<<8)|flags: 1~tile empty, 2~tile singlecolor
  377. .rtrloop_outer:
  378. mov r4, lr, lsl #11
  379. mov r4, r4, lsr #25 @ r4=vscroll>>3 (7 bits)
  380. add r4, r4, r5, lsr #16 @ +trow
  381. and r4, r4, r5, lsr #24 @ &=ymask
  382. mov r7, lr, lsr #8
  383. and r7, r7, #7 @ shift[width]
  384. mov r0, lr, lsr #9
  385. and r0, r0, #0x7000 @ nametab
  386. add r12,r0, r4, lsl r7 @ nametab_row = nametab + (((trow+(vscroll>>3))&ymask)<<shift[width]);
  387. mov r4, lr, lsr #24
  388. orr r12,r12,r4, lsl #23
  389. mov r12,r12,lsl #1 @ (nametab_row|(cells<<24)) (halfword compliant)
  390. @ htab?
  391. tst r5, #0x8000
  392. moveq r7, r5, lsl #22 @ hscroll (0-3FFh)
  393. moveq r7, r7, lsr #22
  394. beq .rtr_hscroll_done
  395. @ get hscroll from htab
  396. mov r7, r5, lsl #17
  397. ands r4, r5, #0x00ff0000
  398. add r7, r7, r4, lsl #5 @ +=trow<<4
  399. andne r4, lr, #0x3800
  400. subne r7, r7, r4, lsl #7 @ if(trow) htaddr-=(vscroll&7)<<1;
  401. mov r7, r7, lsr #16 @ halfwords
  402. ldrh r7, [r10, r7]
  403. .rtr_hscroll_done:
  404. and r8, r8, #0xff000000
  405. rsb r4, r7, #0 @ r4=tilex=(-ts->hscroll)>>3
  406. mov r4, r4, asr #3
  407. and r4, r4, #0xff
  408. orr r8, r8, r4 @ r8=(xmask<<24)|tilex
  409. sub r7, r7, #1
  410. and r7, r7, #7
  411. add r7, r7, #1 @ r7=dx=((ts->hscroll-1)&7)+1
  412. cmp r7, #8
  413. subeq r12,r12, #0x01000000 @ we will loop cells+1 times, so loop less when there is no hscroll
  414. add r1, r11, r7 @ r1=pdest
  415. mov r0, #0xf
  416. b .rtrloop_enter
  417. @ r4 & r7 are scratch in this loop
  418. .rtrloop: @ 40-41 times
  419. add r1, r1, #8
  420. subs r12,r12, #0x01000000
  421. add r8, r8, #1
  422. bmi .rtrloop_exit
  423. .rtrloop_enter:
  424. and r7, r8, r8, lsr #24
  425. add r7, r10, r7, lsl #1
  426. bic r4, r12, #0xff000000 @ Pico.vram[nametab_row+(tilex&xmask)];
  427. ldrh r7, [r7, r4] @ r7=code (int, but from unsigned, no sign extend)
  428. tst r7, #0x8000
  429. bne .rtr_hiprio
  430. cmp r7, r9, lsr #8
  431. bne .rtr_notsamecode
  432. @ we know stuff about this tile already
  433. tst r9, #1
  434. bne .rtrloop @ empty tile
  435. tst r9, #2
  436. bne .rtr_singlecolor @ singlecolor tile
  437. b .rtr_samecode
  438. .rtr_notsamecode:
  439. and r4, r9, #0x600000
  440. mov r9, r7, lsl #8 @ remember new code
  441. @ update cram
  442. and r7, r7, #0x6000
  443. mov r3, r7, asr #9 @ r3=pal=((code&0x6000)>>9);
  444. .rtr_samecode:
  445. tst r9, #0x100000 @ vflip?
  446. bne .rtr_vflip
  447. tst r9, #0x080000 @ hflip?
  448. bne .rtr_hflip
  449. @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=Pico.vram) r2,r4,r7: scratch, r0=0xf
  450. Tile 0, 0
  451. b .rtrloop
  452. .rtr_hflip:
  453. Tile 1, 0
  454. b .rtrloop
  455. .rtr_vflip:
  456. tst r9, #0x080000 @ hflip?
  457. bne .rtr_vflip_hflip
  458. Tile 0, 1
  459. b .rtrloop
  460. .rtr_vflip_hflip:
  461. Tile 1, 1
  462. b .rtrloop
  463. .rtr_singlecolor:
  464. TileSinglecol
  465. b .rtrloop
  466. .rtr_hiprio:
  467. @ *(*hcache)++ = code|(dx<<16)|(trow<<27);
  468. sub r4, r1, r11
  469. orr r7, r7, r4, lsl #16
  470. and r4, r5, #0x00ff0000
  471. orr r7, r7, r4, lsl #11 @ (trow<<27)
  472. str r7, [r6], #4 @ cache hi priority tile
  473. b .rtrloop
  474. .rtrloop_exit:
  475. add r5, r5, #0x00010000
  476. mov r4, r5, lsl #8
  477. cmp r4, lr, lsl #24
  478. bge .rtrloop_outer_exit
  479. add r11, r11, #328*8
  480. b .rtrloop_outer
  481. .rtrloop_outer_exit:
  482. @ terminate cache list
  483. mov r0, #0
  484. str r0, [r6] @ save cache pointer
  485. ldmfd sp!, {r4-r11,lr}
  486. bx lr
  487. .pool
  488. @ void DrawTilesFromCacheF(int *hc, struct PicoEState *est)
  489. .global DrawTilesFromCacheF
  490. DrawTilesFromCacheF:
  491. stmfd sp!, {r4-r10,lr}
  492. mov r9, #0xff000000 @ r9=prevcode=-1
  493. mvn r6, #0 @ r6=prevy=-1
  494. ldr r4, [r1, #OFS_EST_Draw2FB]
  495. ldr r2, [r0], #4 @ read y offset
  496. mov r7, #328
  497. mla r2, r7, r2, r4
  498. sub r12, r2, #(328*8*START_ROW) @ r12=scrpos
  499. ldr r10, [r1, #OFS_EST_PicoMem_vram]
  500. mov r8, r0 @ hc
  501. mov r0, #0xf
  502. @ scratch: r4, r7
  503. @ *hcache++ = code|(dx<<16)|(trow<<27); // cache it
  504. .dtfcf_loop:
  505. ldr r7, [r8], #4 @ read code
  506. movs r1, r7, lsr #16 @ r1=dx;
  507. ldmeqfd sp!, {r4-r10,pc} @ dx is never zero, this must be a terminator, return
  508. @ row changed?
  509. cmp r6, r7, lsr #27
  510. movne r6, r7, lsr #27
  511. movne r4, #328*8
  512. mlane r5, r4, r6, r12 @ r5=pd = scrpos + prevy*328*8
  513. bic r1, r1, #0xf800
  514. add r1, r5, r1 @ r1=pdest (halfwords)
  515. mov r7, r7, lsl #16
  516. mov r7, r7, lsr #16
  517. cmp r7, r9, lsr #8
  518. bne .dtfcf_notsamecode
  519. @ we know stuff about this tile already
  520. tst r9, #1
  521. bne .dtfcf_loop @ empty tile
  522. tst r9, #2
  523. bne .dtfcf_singlecolor @ singlecolor tile
  524. b .dtfcf_samecode
  525. .dtfcf_notsamecode:
  526. and r4, r9, #0x600000
  527. mov r9, r7, lsl #8 @ remember new code
  528. @ update cram val
  529. and r7, r7, #0x6000
  530. mov r3, r7, asr #9 @ r3=pal=((code&0x6000)>>9);
  531. .dtfcf_samecode:
  532. tst r9, #0x100000 @ vflip?
  533. bne .dtfcf_vflip
  534. tst r9, #0x080000 @ hflip?
  535. bne .dtfcf_hflip
  536. @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=Pico.vram) r2,r4,r7: scratch, r0=0xf
  537. Tile 0, 0
  538. b .dtfcf_loop
  539. .dtfcf_hflip:
  540. Tile 1, 0
  541. b .dtfcf_loop
  542. .dtfcf_vflip:
  543. tst r9, #0x080000 @ hflip?
  544. bne .dtfcf_vflip_hflip
  545. Tile 0, 1
  546. b .dtfcf_loop
  547. .dtfcf_vflip_hflip:
  548. Tile 1, 1
  549. b .dtfcf_loop
  550. .dtfcf_singlecolor:
  551. TileSinglecol
  552. b .dtfcf_loop
  553. .pool
  554. @ @@@@@@@@@@@@@@@
  555. @ (tile_start<<16)|row_start
  556. @ void DrawWindowFull(int start, int end, int prio, struct PicoEState *est)
  557. .global DrawWindowFull
  558. DrawWindowFull:
  559. stmfd sp!, {r4-r11,lr}
  560. ldr r11, [r3, #OFS_EST_Pico]
  561. ldrb r12, [r11, #OFS_Pico_video_reg+3] @ pvid->reg[3]
  562. mov r12, r12, lsl #10
  563. ldr r4, [r11, #OFS_Pico_video_reg+12]
  564. mov r5, #1 @ nametab_step
  565. tst r4, #1 @ 40 cell mode?
  566. andne r12, r12, #0xf000 @ 0x3c<<10
  567. andeq r12, r12, #0xf800
  568. movne r5, r5, lsl #7
  569. moveq r5, r5, lsl #6 @ nametab_step
  570. and r4, r0, #0xff
  571. mla r12, r5, r4, r12 @ nametab += nametab_step*start;
  572. ldr r10, [r3, #OFS_EST_PicoMem_vram]
  573. mov r4, r0, lsr #16 @ r4=start_cell_h
  574. add r7, r12, r4, lsl #1
  575. @ fetch the first code now
  576. ldrh r7, [r10, r7]
  577. cmp r2, r7, lsr #15
  578. ldmnefd sp!, {r4-r11,pc} @ hack: simply assume that whole window uses same priority
  579. rsb r8, r4, r1, lsr #16 @ cells (h)
  580. orr r8, r8, r4, lsl #8
  581. mov r4, r1, lsl #24
  582. sub r4, r4, r0, lsl #24
  583. orr r8, r8, r4, lsr #8 @ r8=cells_h|(start_cell_h<<8)|(cells_v<<16)
  584. sub r8, r8, #0x010000 @ adjust for algo
  585. mov r9, #0xff000000 @ r9=prevcode=-1
  586. ldr r11, [r3, #OFS_EST_Draw2FB]
  587. and r4, r0, #0xff
  588. add r11, r11, #328*8
  589. sub r4, r4, #START_ROW
  590. add r11, r11, #8
  591. mov r7, #328*8
  592. mla r11, r7, r4, r11 @ scrpos+=8*328*(start-START_ROW);
  593. mov r0, #0xf
  594. .dwfloop_outer:
  595. and r6, r8, #0xff00 @ r6=tilex
  596. add r1, r11, r6, lsr #5 @ r1=pdest
  597. add r6, r12, r6, lsr #7
  598. add r6, r10, r6 @ r6=Pico.vram+nametab+tilex
  599. orr r8, r8, r8, lsl #24
  600. sub r8, r8, #0x01000000 @ cell loop counter
  601. b .dwfloop_enter
  602. @ r4 & r7 are scratch in this loop
  603. .dwfloop:
  604. add r1, r1, #8
  605. subs r8, r8, #0x01000000
  606. bmi .dwfloop_exit
  607. .dwfloop_enter:
  608. ldrh r7, [r6], #2 @ r7=code
  609. cmp r7, r9, lsr #8
  610. bne .dwf_notsamecode
  611. @ we know stuff about this tile already
  612. tst r9, #1
  613. bne .dwfloop @ empty tile
  614. tst r9, #2
  615. bne .dwf_singlecolor @ singlecolor tile
  616. b .dwf_samecode
  617. .dwf_notsamecode:
  618. and r4, r9, #0x600000
  619. mov r9, r7, lsl #8 @ remember new code
  620. @ update cram val
  621. and r7, r7, #0x6000
  622. mov r3, r7, asr #9 @ r3=pal=((code&0x6000)>>9);
  623. .dwf_samecode:
  624. tst r9, #0x100000 @ vflip?
  625. bne .dwf_vflip
  626. tst r9, #0x080000 @ hflip?
  627. bne .dwf_hflip
  628. @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=PicoMem.vram)
  629. @ r2,r4,r7: scratch, r0=0xf
  630. Tile 0, 0
  631. b .dwfloop
  632. .dwf_hflip:
  633. Tile 1, 0
  634. b .dwfloop
  635. .dwf_vflip:
  636. tst r9, #0x080000 @ hflip?
  637. bne .dwf_vflip_hflip
  638. Tile 0, 1
  639. b .dwfloop
  640. .dwf_vflip_hflip:
  641. Tile 1, 1
  642. b .dwfloop
  643. .dwf_singlecolor:
  644. TileSinglecol 1
  645. b .dwfloop
  646. .dwfloop_exit:
  647. bic r8, r8, #0xff000000 @ fix r8
  648. subs r8, r8, #0x010000
  649. ldmmifd sp!, {r4-r11,pc}
  650. add r11, r11, #328*8
  651. add r12, r12, r5 @ nametab+=nametab_step
  652. b .dwfloop_outer
  653. .pool
  654. @ ---------------- sprites ---------------
  655. .macro SpriteLoop hflip vflip
  656. .if \vflip
  657. mov r1, r5, lsr #24 @ height
  658. mov r0, #328*8
  659. mla r11, r1, r0, r11 @ scrpos+=height*328*8;
  660. add r12, r12, r1, lsl #3 @ sy+=height*8
  661. .endif
  662. mov r0, #0xf
  663. .if \hflip
  664. and r1, r5, #0xff
  665. add r8, r8, r1, lsl #3 @ sx+=width*8
  666. 58:
  667. cmp r8, #336
  668. blt 51f
  669. add r9, r9, r5, lsr #16
  670. sub r5, r5, #1 @ sub width
  671. sub r8, r8, #8
  672. b 58b
  673. .else
  674. cmp r8, #0 @ skip tiles hidden on the left of screen
  675. bgt 51f
  676. 58:
  677. add r9, r9, r5, lsr #16
  678. sub r5, r5, #1
  679. adds r8, r8, #8
  680. ble 58b
  681. b 51f
  682. .endif
  683. 50: @ outer
  684. .if !\hflip
  685. add r8, r8, #8 @ sx+=8
  686. .endif
  687. bic r5, r5, #0xff000000 @ fix height
  688. orr r5, r5, r5, lsl #16
  689. 51: @ outer_enter
  690. sub r5, r5, #1 @ width--
  691. movs r1, r5, lsl #24
  692. ldmmifd sp!, {r4-r11,pc} @ end of tile
  693. .if \hflip
  694. subs r8, r8, #8 @ sx-=8
  695. ldmlefd sp!, {r4-r11,pc} @ tile offscreen
  696. .else
  697. cmp r8, #328
  698. ldmgefd sp!, {r4-r11,pc} @ tile offscreen
  699. .endif
  700. mov r6, r12 @ r6=sy
  701. add r1, r11, r8 @ pdest=scrpos+sx
  702. b 53f
  703. 52: @ inner
  704. add r9, r9, #1<<8 @ tile++
  705. .if !\vflip
  706. add r6, r6, #8 @ sy+=8
  707. add r1, r1, #328*8
  708. .endif
  709. 53: @ inner_enter
  710. @ end of sprite?
  711. subs r5, r5, #0x01000000
  712. bmi 50b @ ->outer
  713. .if \vflip
  714. sub r6, r6, #8 @ sy-=8
  715. sub r1, r1, #328*8
  716. .endif
  717. @ offscreen?
  718. cmp r6, #(START_ROW*8)
  719. ble 52b
  720. cmp r6, #(END_ROW*8+8)
  721. bge 52b
  722. @ Tile (r1=pdest, r3=pal, r9=prevcode, r10=PicoMem.vram)
  723. @ r2,r4,r7: scratch, r0=0xf
  724. Tile \hflip, \vflip
  725. b 52b
  726. .endm
  727. @ void DrawSpriteFull(unsigned int *sprite, struct PicoEState *est)
  728. .global DrawSpriteFull
  729. DrawSpriteFull:
  730. stmfd sp!, {r4-r11,lr}
  731. ldr r3, [r0] @ sprite[0]
  732. mov r5, r3, lsl #4
  733. mov r6, r5, lsr #30
  734. add r6, r6, #1 @ r6=width
  735. mov r5, r5, lsl #2
  736. mov r5, r5, lsr #30
  737. add r5, r5, #1 @ r5=height
  738. mov r12, r3, lsl #23
  739. mov r12, r12, lsr #23
  740. ldr lr, [r0, #4] @ lr=code
  741. sub r12, r12, #0x78 @ r12=sy
  742. mov r8, lr, lsl #7
  743. mov r8, r8, lsr #23
  744. sub r8, r8, #0x78 @ r8=sx
  745. mov r9, lr, lsl #21
  746. mov r9, r9, lsr #13 @ r9=tile<<8
  747. and r3, lr, #0x6000
  748. mov r3, r3, lsr #9 @ r3=pal=((code>>9)&0x30);
  749. ldr r11, [r1, #OFS_EST_Draw2FB]
  750. ldr r10, [r1, #OFS_EST_PicoMem_vram]
  751. sub r1, r12, #(START_ROW*8)
  752. mov r0, #328
  753. mla r11, r1, r0, r11 @ scrpos+=(sy-START_ROW*8)*328;
  754. orr r5, r5, r5, lsl #16 @
  755. orr r5, r6, r5, lsl #8 @ r5=width|(height<<8)|(height<<24)
  756. tst lr, #0x1000 @ vflip?
  757. bne .dsf_vflip
  758. tst lr, #0x0800 @ hflip?
  759. bne .dsf_hflip
  760. SpriteLoop 0, 0
  761. .dsf_hflip:
  762. SpriteLoop 1, 0
  763. .dsf_vflip:
  764. tst lr, #0x0800 @ hflip?
  765. bne .dsf_vflip_hflip
  766. SpriteLoop 0, 1
  767. .dsf_vflip_hflip:
  768. SpriteLoop 1, 1
  769. .pool
  770. @ vim:filetype=armasm