You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

440 line
9.9KB

  1. ; vml.s - machine code helpers for the c64 vim clone (called from power c).
  2. ;
  3. ; Assembled for $C000. vml.c holds the bytes; mlinit() calls highmem($C000)
  4. ; so power c keeps its heap and stack below, then copies the code up here.
  5. ; Parameters are written by C into a block at $C400 (PB) before each call;
  6. ; entry addresses come from the ld65 label file (see build-ml.ps1).
  7. ;
  8. ; Zero page: 34-42 ($22-$2A), 75-96 ($4B-$60) and 251-252 ($FB-$FC) are the
  9. ; temporaries power c leaves to machine language - but sys() itself is using
  10. ; some of them while our code runs (it keeps where to store A/X/Y back), so
  11. ; every entry that touches zero page saves all three ranges first (zsave) and
  12. ; puts them back before it returns (zrest). Without that, sys() wrote X/Y
  13. ; through our screen pointer and then jumped into zero page.
  14. ;
  15. ; Entries
  16. ; scrn paint screen rows r0..r1 straight from the buffer and line index
  17. ; row paint one row from a byte string (the status row)
  18. ; bmove overlapping block move (memmove)
  19. ; ladj add a 16 bit delta to n consecutive words (line index fix-up)
  20. ; kpop take one key from the kernal keyboard buffer, irqs masked: A = key or 0
  21. SAVE = $C410 ; zsave's copy of the zero page we use
  22. PB = $C400 ; above the code; NOT $CF00 - power c's stack lives under $D000
  23. ; paint's inputs
  24. src = $22 ; 2 text to show (petscii)
  25. len = $24 ; 1 bytes of it, 0..40
  26. dst = $25 ; 2 screen address of the row
  27. cur = $27 ; 1 column to invert, $FF = none
  28. rev = $28 ; 1 $00 normal, $80 whole row reverse
  29. endp = $29 ; 2 scrn: end offset of the line
  30. ; scrn's copy of its parameter block: PB+0..PB+15 -> $4B..$5A
  31. bfr = $4B ; 2 buffer address
  32. lptr = $4D ; 2 address of lptr[0]
  33. nl = $4F ; 2 number of lines
  34. top = $51 ; 2 first line on screen
  35. blen = $53 ; 2 bytes in buffer
  36. lcol = $55 ; 2 horizontal scroll
  37. crow = $57 ; 1 screen row of the cursor ($FF none)
  38. ccol = $58 ; 1 screen column of the cursor
  39. r0 = $59 ; 1 first row to paint
  40. r1 = $5A ; 1 last row to paint (inclusive)
  41. ln = $5B ; 2 line being painted
  42. lp = $5D ; 2 -> lptr[ln]
  43. rowc = $5F ; 1 screen row being painted
  44. st = $FB ; 2 start offset of the visible text
  45. .segment "CODE"
  46. ; ---------------------------------------------------------------- scrn
  47. scrn: jsr zsave
  48. ldx #15
  49. @cp: lda PB,x
  50. sta bfr,x
  51. dex
  52. bpl @cp
  53. clc ; ln = top + r0
  54. lda top
  55. adc r0
  56. sta ln
  57. lda top+1
  58. adc #0
  59. sta ln+1
  60. lda ln ; lp = lptr + 2*ln
  61. asl a
  62. sta lp
  63. lda ln+1
  64. rol a
  65. sta lp+1
  66. clc
  67. lda lp
  68. adc lptr
  69. sta lp
  70. lda lp+1
  71. adc lptr+1
  72. sta lp+1
  73. lda #0 ; dst = $0400 + 40*r0
  74. sta dst
  75. lda #4
  76. sta dst+1
  77. ldx r0
  78. beq @d1
  79. @dl: clc
  80. lda dst
  81. adc #40
  82. sta dst
  83. bcc @dn
  84. inc dst+1
  85. @dn: dex
  86. bne @dl
  87. @d1: lda r0
  88. sta rowc
  89. @row: lda #0
  90. sta rev
  91. sta len
  92. lda #$FF
  93. sta cur
  94. lda ln ; past the last line: a blank row
  95. cmp nl
  96. lda ln+1
  97. sbc nl+1
  98. bcs @paint
  99. ldy #0 ; st = lptr[ln]
  100. lda (lp),y
  101. sta st
  102. iny
  103. lda (lp),y
  104. sta st+1
  105. clc ; is ln the last line?
  106. lda ln
  107. adc #1
  108. tax
  109. lda ln+1
  110. adc #0
  111. cpx nl
  112. bne @mid
  113. cmp nl+1
  114. bne @mid
  115. lda blen ; last line ends at blen
  116. sta endp
  117. lda blen+1
  118. sta endp+1
  119. jmp @gotend
  120. @mid: ldy #2 ; else at lptr[ln+1] - 1 (before the $0d)
  121. lda (lp),y
  122. sec
  123. sbc #1
  124. sta endp
  125. iny
  126. lda (lp),y
  127. sbc #0
  128. sta endp+1
  129. @gotend:
  130. clc ; st += lcol
  131. lda st
  132. adc lcol
  133. sta st
  134. lda st+1
  135. adc lcol+1
  136. sta st+1
  137. sec ; len = min(40, end - st), 0 if negative
  138. lda endp
  139. sbc st
  140. tax
  141. lda endp+1
  142. sbc st+1
  143. bcc @src ; scrolled past the end of this line
  144. bne @full
  145. cpx #41
  146. bcc @setn
  147. @full: ldx #40
  148. @setn: stx len
  149. @src: clc ; src = bfr + st
  150. lda bfr
  151. adc st
  152. sta src
  153. lda bfr+1
  154. adc st+1
  155. sta src+1
  156. lda rowc ; the cursor row?
  157. cmp crow
  158. bne @paint
  159. lda ccol
  160. sta cur
  161. @paint: jsr paint
  162. lda rowc ; next row, until r1 is done
  163. cmp r1
  164. bcs @done
  165. inc rowc
  166. inc ln
  167. bne @l1
  168. inc ln+1
  169. @l1: clc
  170. lda lp
  171. adc #2
  172. sta lp
  173. bcc @l2
  174. inc lp+1
  175. @l2: clc
  176. lda dst
  177. adc #40
  178. sta dst
  179. bcc @l3
  180. inc dst+1
  181. @l3: jmp @row
  182. @done: jmp zrest
  183. ; ---------------------------------------------------------------- row
  184. ; PB+0 src, PB+2 len, PB+3 dst, PB+5 cur, PB+6 rev
  185. row: jsr zsave
  186. ldx #6
  187. @cp: lda PB,x
  188. sta src,x
  189. dex
  190. bpl @cp
  191. jsr paint
  192. jmp zrest
  193. ; ---------------------------------------------------------------- paint
  194. ; clear the row to blanks, copy len bytes converted petscii -> screen code,
  195. ; then invert the cursor cell
  196. paint: lda rev
  197. ora #$20
  198. ldy #39
  199. @clr: sta (dst),y
  200. dey
  201. bpl @clr
  202. ldy #0
  203. @cp: cpy len
  204. beq @cur
  205. lda (src),y
  206. cmp #$20
  207. bcs @ok
  208. lda #$20 ; control codes show as a blank
  209. @ok: cmp #$C0
  210. bcc @l1
  211. sbc #$80
  212. bcs @st
  213. @l1: cmp #$A0
  214. bcc @l2
  215. sbc #$40
  216. bcs @st
  217. @l2: cmp #$60
  218. bcc @l3
  219. sbc #$20
  220. bcs @st
  221. @l3: cmp #$40
  222. bcc @st
  223. sbc #$40
  224. @st: ora rev
  225. sta (dst),y
  226. iny
  227. bne @cp
  228. @cur: lda cur
  229. cmp #40
  230. bcs @fin ; $FF (none) or off screen
  231. tay
  232. lda (dst),y
  233. eor #$80
  234. sta (dst),y
  235. @fin: rts
  236. ; ---------------------------------------------------------------- bmove
  237. ; PB+0 from, PB+2 to, PB+4 count. Overlap safe.
  238. mfrom = $22
  239. mto = $25
  240. mcnt = $4B
  241. bmove: jsr zsave
  242. lda PB
  243. sta mfrom
  244. lda PB+1
  245. sta mfrom+1
  246. lda PB+2
  247. sta mto
  248. lda PB+3
  249. sta mto+1
  250. lda PB+4
  251. sta mcnt
  252. lda PB+5
  253. sta mcnt+1
  254. lda mto ; to < from: copy upwards from the start
  255. cmp mfrom
  256. lda mto+1
  257. sbc mfrom+1
  258. bcc @fwd
  259. ; to >= from: copy downwards from the end
  260. clc ; point both at their last whole page
  261. lda mfrom+1
  262. adc mcnt+1
  263. sta mfrom+1
  264. clc
  265. lda mto+1
  266. adc mcnt+1
  267. sta mto+1
  268. ldy mcnt ; the odd bytes at the top first
  269. beq @bpg
  270. @bodd: dey
  271. lda (mfrom),y
  272. sta (mto),y
  273. cpy #0
  274. bne @bodd
  275. @bpg: ldx mcnt+1 ; then whole pages, highest first
  276. beq @out
  277. @bnext: dec mfrom+1
  278. dec mto+1
  279. ldy #0
  280. @bpl: dey
  281. lda (mfrom),y
  282. sta (mto),y
  283. cpy #0
  284. bne @bpl
  285. dex
  286. bne @bnext
  287. @out: jmp zrest
  288. @fwd: ldy #0
  289. ldx mcnt+1 ; whole pages
  290. beq @fodd
  291. @fpg: lda (mfrom),y
  292. sta (mto),y
  293. iny
  294. bne @fpg
  295. inc mfrom+1
  296. inc mto+1
  297. dex
  298. bne @fpg
  299. @fodd: ldx mcnt ; then the rest
  300. beq @out
  301. @fo: lda (mfrom),y
  302. sta (mto),y
  303. iny
  304. dex
  305. bne @fo
  306. jmp zrest
  307. ; ---------------------------------------------------------------- ladj
  308. ; PB+0 address of the first word, PB+2 how many, PB+4 delta
  309. aptr = $22
  310. acnt = $4B
  311. adel = $4D
  312. ladj: jsr zsave
  313. ldx #5
  314. @cp: lda PB,x
  315. sta $4B,x
  316. dex
  317. bpl @cp
  318. lda $4B ; the address goes to $22 for (zp),y
  319. sta aptr
  320. lda $4C
  321. sta aptr+1
  322. lda $4D ; count to acnt, delta to adel
  323. sta acnt
  324. lda $4E
  325. sta acnt+1
  326. lda $4F
  327. sta adel
  328. lda $50
  329. sta adel+1
  330. @lp: lda acnt
  331. ora acnt+1
  332. beq @done
  333. ldy #0
  334. clc
  335. lda (aptr),y
  336. adc adel
  337. sta (aptr),y
  338. iny
  339. lda (aptr),y
  340. adc adel+1
  341. sta (aptr),y
  342. clc
  343. lda aptr
  344. adc #2
  345. sta aptr
  346. bcc @nc
  347. inc aptr+1
  348. @nc: lda acnt
  349. bne @dc
  350. dec acnt+1
  351. @dc: dec acnt
  352. jmp @lp
  353. @done: jmp zrest
  354. ; ---------------------------------------------------------------- kpop
  355. kpop: sei
  356. lda $C6
  357. beq @none
  358. ldx #0
  359. lda $0277
  360. pha
  361. @sh: lda $0278,x
  362. sta $0277,x
  363. inx
  364. cpx #9
  365. bne @sh
  366. dec $C6
  367. pla
  368. cli
  369. rts
  370. @none: cli
  371. lda #0
  372. rts
  373. ; ---------------------------------------------------------------- zsave / zrest
  374. ; $22-$2A -> SAVE+0..8, $4B-$60 -> SAVE+9..30, $FB-$FC -> SAVE+31..32
  375. zsave: ldx #8
  376. @a: lda $22,x
  377. sta SAVE,x
  378. dex
  379. bpl @a
  380. ldx #21
  381. @b: lda $4B,x
  382. sta SAVE+9,x
  383. dex
  384. bpl @b
  385. lda $FB
  386. sta SAVE+31
  387. lda $FC
  388. sta SAVE+32
  389. rts
  390. zrest: ldx #8
  391. @a: lda SAVE,x
  392. sta $22,x
  393. dex
  394. bpl @a
  395. ldx #21
  396. @b: lda SAVE+9,x
  397. sta $4B,x
  398. dex
  399. bpl @b
  400. lda SAVE+31
  401. sta $FB
  402. lda SAVE+32
  403. sta $FC
  404. rts
  405. .export scrn, row, bmove, ladj, kpop

Powered by TurnKey Linux.