vwf.asm 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483
  1. ; SPDX-License-Identifier: MIT
  2. ;
  3. ; MIT License
  4. ;
  5. ; Copyright (c) 2018-2020 Eldred Habert
  6. ;
  7. ; Permission is hereby granted, free of charge, to any person obtaining a copy
  8. ; of this software and associated documentation files (the "Software"), to deal
  9. ; in the Software without restriction, including without limitation the rights
  10. ; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. ; copies of the Software, and to permit persons to whom the Software is
  12. ; furnished to do so, subject to the following conditions:
  13. ;
  14. ; The above copyright notice and this permission notice shall be included in all
  15. ; copies or substantial portions of the Software.
  16. ;
  17. ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. ; SOFTWARE.
  24. ; Number of elements the text stack has room for
  25. ; Having more will cause a soft crash
  26. ; This must not exceeed $7F, as the return logic discards bit 7 when checking for zero
  27. IF !DEF(TEXT_STACK_CAPACITY)
  28. TEXT_STACK_CAPACITY equ 8
  29. ENDC
  30. ; IMPORTANT NOTE REGARDING NEWLINES!!!
  31. ; DO NOT PRINT MORE THAN THIS NEWLINES AT ONCE
  32. ; THIS **WILL** CAUSE A BUFFER OVERFLOW
  33. IF !DEF(TEXT_NEWLINE_CAPACITY)
  34. TEXT_NEWLINE_CAPACITY equ 10
  35. ENDC
  36. ; `wTextFlags` bits
  37. rsset 6
  38. MACRO text_flag
  39. TEXTB_\1 rb 1
  40. TEXTF_\1 equ 1 << TEXTB_\1
  41. EXPORT TEXTB_\1, TEXTF_\1
  42. ENDM
  43. text_flag WAITBUTTON
  44. text_flag SYNC
  45. CHARACTER_HEIGHT equ 8
  46. CHARACTER_SIZE equ CHARACTER_HEIGHT + 1
  47. SECTION "VWF engine", ROM0
  48. CTRL_CHAR_PTRS equs ""
  49. rsreset
  50. MACRO control_char
  51. IF DEF(PRINT_CHARMAP)
  52. PRINT "charmap \"<\1>\", {d:_RS}\n"
  53. ENDC
  54. TEXT_\1 rb 1
  55. IF DEF(EXPORT_CONTROL_CHARS)
  56. EXPORT TEXT_\1
  57. ENDC
  58. IF _NARG > 1
  59. dw \2
  60. TMP equs "{CTRL_CHAR_PTRS}\ndw \3"
  61. PURGE CTRL_CHAR_PTRS
  62. CTRL_CHAR_PTRS equs "{TMP}"
  63. PURGE TMP
  64. ENDC
  65. ENDM
  66. ;;;;;;;;;;;;;;;;;;;;; "Regular" control chars ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  67. control_char END
  68. RefillerControlChars:
  69. control_char SET_FONT, ReaderSetFont, TextSetFont
  70. control_char RESTORE_FONT, ReaderRestoreFont, TextRestoreFont
  71. control_char SET_VARIANT, ReaderSetVariant, TextSetVariant
  72. control_char RESTORE_VARIAN, ReaderRestoreVariant, TextRestoreVariant
  73. control_char SET_COLOR, Reader2ByteNop, TextSetColor
  74. control_char BLANKS, ReaderPrintBlank, TextPrintBlank
  75. control_char DELAY, Reader2ByteNop, TextDelay
  76. control_char WAITBTN, ReaderWaitButton, TextWaitButton
  77. control_char CLEAR, ReaderClear, TextClear
  78. control_char NEWLINE, ReaderNewline, TextNewline
  79. control_char SYNC, Reader1ByteNop, TextSync
  80. control_char SCROLL, ReaderScroll, TextScroll
  81. control_char WAITBTN_SCROLL, ReaderWaitButtonScroll, TextWaitButtonScroll
  82. control_char ZWS, _RefillCharBuffer.canNewline, PrintNextCharInstant
  83. TEXT_BAD_CTRL_CHAR rb 0
  84. assert TEXT_NEWLINE == "\n"
  85. PTRS equs ""
  86. rsset 256
  87. MACRO reader_only_control_char
  88. _RS = _RS - 1
  89. IF DEF(PRINT_CHARMAP)
  90. PRINT "charmap \"<\1>\", {d:_RS}\n"
  91. ENDC
  92. TEXT_\1 equ _RS
  93. IF DEF(EXPORT_CONTROL_CHARS)
  94. EXPORT TEXT_\1
  95. ENDC
  96. TMP equs "dw \2\n{PTRS}"
  97. PURGE PTRS
  98. PTRS equs "{TMP}"
  99. PURGE TMP
  100. ENDM
  101. ;;;;;;;;;;;;;;;;;;;; Reader-only control chars ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  102. reader_only_control_char CALL, ReaderCall
  103. reader_only_control_char JUMP, ReaderJumpTo
  104. reader_only_control_char SOFT_HYPHEN, ReaderSoftHyphen
  105. ;; custom
  106. reader_only_control_char CG, SetCGOKFlag
  107. ; The base of the table is located at its end
  108. ; Unusual, I know, but it works better!
  109. PTRS
  110. RefillerOnlyControlChars:
  111. FIRST_READER_ONLY_CONTROL_CHAR rb 0
  112. NB_FONT_CHARACTERS equ FIRST_READER_ONLY_CONTROL_CHAR - " "
  113. ; Sets the pen's position somewhere in memory
  114. ; The code is designed for a pen in VRAM, but it can be anywhere
  115. ; Please call this after PrintVWFText, so wTextCurTile is properly updated
  116. ; @param hl The address to print to (usually in the tilemap)
  117. SetPenPosition::
  118. ; Note: relied upon preserving HL
  119. ld a, l
  120. ld [wPenPosition], a
  121. ld [wPenStartingPosition], a
  122. ld a, h
  123. ld [wPenPosition + 1], a
  124. ld [wPenStartingPosition + 1], a
  125. ld a, [wTextCurTile]
  126. ld [wPenCurTile], a
  127. ret
  128. DrawVWFChars::
  129. ld hl, wPenPosition
  130. ld a, [hli]
  131. ld e, a
  132. ld a, [hli]
  133. ld d, a
  134. assert wPenPosition + 2 == wPenCurTile
  135. ld c, [hl]
  136. ld hl, wNewlineTiles
  137. ld a, [wFlushedTiles]
  138. and a
  139. jr z, .noNewTiles
  140. ld b, a
  141. xor a
  142. ld [wFlushedTiles], a
  143. .writeNewTile
  144. ; Check if current tile is subject to a newline
  145. ld a, [wNbNewlines]
  146. and a
  147. jr z, .writeTile
  148. ld a, c
  149. cp [hl]
  150. jr z, .newline
  151. .writeTile
  152. ldh a, [rSTAT]
  153. and STATF_BUSY
  154. jr nz, .writeTile
  155. ld a, c
  156. ld [de], a
  157. ld a, [wLastTextTile]
  158. scf
  159. sbc c
  160. jr nc, .nowrap
  161. ld a, [wWrapTileID]
  162. ld c, a
  163. db $FE ; cp imm8
  164. .nowrap
  165. inc c
  166. inc de
  167. dec b
  168. jr nz, .writeNewTile
  169. .noNewTiles
  170. .tryAgain
  171. ld a, [wNbNewlines]
  172. and a
  173. jr z, .noFinalNewline
  174. ld a, c
  175. cp [hl]
  176. jr z, .finalNewline
  177. .noFinalNewline
  178. xor a
  179. ld [wNbNewlines], a
  180. ld hl, wPenCurTile
  181. ld a, c
  182. ld [hld], a
  183. assert wPenCurTile - 1 == wPenPosition + 1
  184. ld a, d
  185. ld [hld], a
  186. ld [hl], e
  187. ; If the current tile is empty (1 px == 1 space)
  188. ld a, [wTextCurPixel]
  189. cp 2
  190. ret c
  191. .waitFinalTile
  192. ldh a, [rSTAT]
  193. and STATF_BUSY
  194. jr nz, .waitFinalTile
  195. ld a, c
  196. ld [de], a
  197. ret
  198. .newline
  199. ld a, [wNbNewlines]
  200. dec a
  201. ld [wNbNewlines], a
  202. ld a, [wPenStartingPosition]
  203. and SCRN_VX_B - 1
  204. ld c, a ; Get offset from column 0
  205. ld a, e
  206. and -SCRN_VX_B ; Get to column 0
  207. add a, c ; Get to starting column
  208. add a, SCRN_VX_B ; Go to next row (this might overflow)
  209. ld e, a
  210. jr nc, .nocarry
  211. inc d
  212. .nocarry
  213. ld c, [hl] ; Get back tile ID
  214. xor a ; Clear this newline tile
  215. ld [hli], a ; Go to the next newline (if any)
  216. jr .writeNewTile
  217. .finalNewline
  218. ld a, [wNbNewlines]
  219. dec a
  220. ld [wNbNewlines], a
  221. xor a
  222. ld [hli], a ; Clear that
  223. ld a, [wPenStartingPosition]
  224. and SCRN_VX_B - 1
  225. ld b, a
  226. ld a, e
  227. and -SCRN_VX_B
  228. add a, b
  229. add a, SCRN_VX_B
  230. ld e, a
  231. jr nc, .tryAgain ; noCarry
  232. inc d
  233. jr .tryAgain
  234. TEXT_CONT_STR equ 0
  235. TEXT_NEW_STR equ 1
  236. EXPORT TEXT_CONT_STR
  237. EXPORT TEXT_NEW_STR
  238. ; Sets up the VWF engine to start printing text
  239. ; WARNING: If flushing the string, the auto-wordwrapper assumes that a new line is started
  240. ; (You might get odd gfx otherwise if the text ended close enough to the tile border)
  241. ; If needed, manually modify `wLineRemainingPixels` after calling this
  242. ; WARNING: If you want to print to a specific tile ID, set wTextCurTile *after* calling this
  243. ; (Obviously, don't do this if you're not flushing the string)
  244. ; WARNING: Variant is reset when calling this, but the language is preserved
  245. ; WARNING: Source data located between $FF00 and $FFFF will probably cause some malfunctioning
  246. ; NOTICE: Source data outside of ROM banks is fine, but banking won't be performed.
  247. ; Any ROM bank number is thus fine, but avoid 0 or values too high as this triggers spurious warnings in BGB
  248. ; @param hl Pointer to the string to be displayed
  249. ; @param b Bank containing the string
  250. ; @param a Non-zero to flush the current string (use zero if you want to keep printing the same string)
  251. ; @return a 0
  252. ; @return hl wTextCharset
  253. ; @return f NC and Z
  254. ; @destroy bc de
  255. PrintVWFText::
  256. and a ; Set Z flag for test below
  257. ; Write src ptr
  258. ld a, b
  259. ld [wTextSrcBank], a
  260. ld a, l
  261. ld [wTextSrcPtr], a
  262. ld a, h
  263. ld [wTextSrcPtr + 1], a
  264. ; Flag preserved from `and a`
  265. jr z, .dontFlush
  266. ; Reset auto line-wrapper (assuming we're starting a new line)
  267. ld a, [wTextLineLength]
  268. ld [wLineRemainingPixels], a
  269. ; Don't flush if current tile is empty
  270. ld a, [wTextCurPixel]
  271. cp 2 ; Again, last pixel of all tiles is empty
  272. call nc, FlushVWFBuffer
  273. ; Reset position always, though
  274. xor a
  275. ld [wTextCurPixel], a
  276. ld [wNbNewlines], a
  277. .dontFlush
  278. ; Force buffer refill by making these two identical
  279. ; wTextReadPtrLow needs to be this to refill the full buffer
  280. ld a, LOW(wTextCharBufferEnd)
  281. ld [wTextFillPtrEnd], a
  282. ld [wTextReadPtrEnd], a
  283. ld [wTextReadPtrLow], a
  284. ; Use black color by default (which is normally loaded into color #3)
  285. ld a, 3
  286. ld [wTextColorID], a
  287. ; Preserve the language but reset the decoration
  288. ld hl, wTextCharset
  289. ld a, [hl]
  290. and $F0
  291. ld [hl], a
  292. ; Set initial letter delay to 0, to start printing directly
  293. xor a
  294. ld [wTextNextLetterDelay], a
  295. ret
  296. FlushVWFBuffer::
  297. push hl
  298. ; Calculate ptr to next tile
  299. ld a, [wTextTileBlock]
  300. ld h, a
  301. ld a, [wTextCurTile]
  302. swap a ; Multiply by 16
  303. ld d, a
  304. and $F0
  305. ld e, a
  306. xor d
  307. add a, h
  308. ld d, a
  309. ; Copy buffer 1 to VRAM, buffer 2 to buffer 1, and clear buffer 2
  310. ld hl, wTextTileBuffer
  311. ld bc, wTextTileBuffer + $10
  312. .copyByte
  313. ldh a, [rSTAT]
  314. and STATF_BUSY
  315. jr nz, .copyByte
  316. ; Write tile buf to VRAM
  317. ld a, [hl]
  318. ld [de], a
  319. inc e ; Faster than inc de, guaranteed thanks to ALIGN[4]
  320. ; Copy second tile to first one
  321. ld a, [bc]
  322. ld [hli], a
  323. ; Clear second tile
  324. xor a
  325. ld [bc], a
  326. inc c
  327. ld a, l
  328. cp LOW(wTextTileBuffer + $10)
  329. jr nz, .copyByte
  330. ; Go to next tile
  331. ld hl, wLastTextTile
  332. ld a, [hld]
  333. ld c, a
  334. assert wLastTextTile - 1 == wTextCurTile
  335. ld a, [hl]
  336. cp c
  337. inc a
  338. jr c, .noWrap
  339. ld a, [wWrapTileID]
  340. .noWrap
  341. ld [hl], a
  342. ld hl, wFlushedTiles
  343. inc [hl]
  344. pop hl
  345. ret
  346. ; Prints a VWF char (or more), applying delay if necessary
  347. ; Might print more than 1 char, eg. if wTextLetterDelay is zero
  348. ; Sets the high byte of the source pointer to $FF when finished
  349. ; **DO NOT CALL WITH SOURCE DATA IN FF00-FFFF, THIS WILL CAUSE AN EARLY RETURN!!
  350. ; Number of tiles to write to the tilemap is written in wFlushedTiles
  351. PrintVWFChar::
  352. ld hl, wTextNextLetterDelay
  353. ld a, [hl]
  354. and a
  355. jr nz, .delay
  356. ; xor a
  357. ld [wFlushedTiles], a
  358. ldh a, [hCurROMBank]
  359. push af
  360. ld a, BANK(_PrintVWFChar)
  361. ldh [hCurROMBank], a
  362. ld [rROMB0], a
  363. call _PrintVWFChar
  364. pop af
  365. ldh [hCurROMBank], a
  366. ld [rROMB0], a
  367. ret
  368. .delay
  369. dec a
  370. ld [hl], a
  371. ret
  372. RefillerOnlyControlChar:
  373. ld bc, _RefillCharBuffer
  374. push bc
  375. push hl
  376. add a, a
  377. add a, LOW(RefillerOnlyControlChars)
  378. ld l, a
  379. ld a, $FF ; If we're here, the value in A is negative
  380. adc a, HIGH(RefillerOnlyControlChars)
  381. jr RefillerJumpControlChar
  382. RefillerControlChar:
  383. add a, " " ; Restore the original value
  384. add a, a ; Double for pointer calculation, and check for 0
  385. jr z, RefillerTryReturning
  386. ld bc, _RefillCharBuffer.afterControlChar
  387. push bc
  388. inc e ; Otherwise the char isn't counted to be written!
  389. push hl
  390. add a, LOW(RefillerControlChars - 2)
  391. ld l, a
  392. adc a, HIGH(RefillerControlChars - 2)
  393. sub l
  394. RefillerJumpControlChar:
  395. ld h, a
  396. ld a, [hli]
  397. ld b, [hl]
  398. ld c, a
  399. pop hl
  400. push bc
  401. ret
  402. RefillerTryReturning:
  403. ld hl, wTextStackSize
  404. ld a, [hl]
  405. ld b, a
  406. add a, a
  407. ld [de], a ; If we're returning, we will need to write that $00; otherwise, it'll be overwritten
  408. jp z, _RefillCharBuffer.done ; Too far to `jr`
  409. dec b
  410. ld [hl], b
  411. add a, b ; a = stack size * 3 + 2
  412. add a, LOW(wTextStack)
  413. ld l, a
  414. adc a, HIGH(wTextStack)
  415. sub l
  416. ld h, a
  417. jr RestartCharBufRefill
  418. ; Refills the char buffer, assuming at least half of it has been read
  419. ; Newlines are injected into the buffer to implement auto line-wrapping
  420. ; @param hl The current read ptr into the buffer
  421. RefillCharBuffer:
  422. ld de, wTextCharBuffer
  423. ; First, copy remaining chars into the buffer
  424. ld a, [wTextFillPtrEnd]
  425. sub l
  426. ld c, a
  427. jr z, .charBufferEmpty
  428. .copyLeftovers
  429. ld a, [hli]
  430. ld [de], a
  431. inc e
  432. dec c
  433. jr nz, .copyLeftovers
  434. .charBufferEmpty
  435. ; Cache charset ptr to speed up calculations
  436. ld a, [wTextCharset]
  437. ld [wRefillerCharset], a
  438. add a, LOW(CharsetPtrs)
  439. ld l, a
  440. adc a, HIGH(CharsetPtrs)
  441. sub l
  442. ld h, a
  443. ld a, [hli]
  444. add a, 8 ; Code later on will want a +8 offset
  445. ld [wCurCharsetPtr], a
  446. ld a, 0 ; If you try to optimize this to `xor a` I will kick you in the nuts
  447. adc a, [hl]
  448. ld [wCurCharsetPtr+1], a
  449. ; Set a position to insert a newline at if the first word overflows
  450. xor a
  451. ld [wNewlinePtrLow], a
  452. ; Get ready to read chars into the buffer
  453. ld hl, wTextSrcBank
  454. RestartCharBufRefill:
  455. ld a, [hld]
  456. ldh [hCurROMBank], a
  457. ld [rROMB0], a
  458. assert wTextSrcBank - 1 == wTextSrcPtr + 1
  459. ld a, [hld]
  460. ld l, [hl]
  461. ld h, a
  462. _RefillCharBuffer:
  463. ld a, [hli]
  464. cp FIRST_READER_ONLY_CONTROL_CHAR
  465. jr nc, RefillerOnlyControlChar
  466. ld [de], a
  467. sub " "
  468. jr c, RefillerControlChar ; The refiller needs to be aware of some control chars
  469. ; Add char length to accumulated one
  470. push hl
  471. ld hl, wCurCharsetPtr
  472. ld c, [hl]
  473. inc hl
  474. ld b, [hl]
  475. ld l, a
  476. ld h, 0
  477. add hl, hl
  478. add hl, hl
  479. add hl, hl
  480. add hl, bc ; Char * 8 + base + 8
  481. ld c, a ; Stash this for later
  482. ld b, 0
  483. add hl, bc ; Char * 9 + base + 8
  484. ld a, [wLineRemainingPixels]
  485. sub a, [hl]
  486. .insertCustomSize
  487. jr nc, .noNewline
  488. ld b, a ; Stash this for later
  489. ; Line length was overflowed, inject newline into buffer
  490. ; Get ptr to newline injection point
  491. ld h, d ; ld h, HIGH(wTextCharBuffer)
  492. ld a, [wNewlinePtrLow]
  493. ld l, a
  494. ld d, "\n"
  495. ld a, [wTextRemainingLines]
  496. dec a
  497. jr nz, .linesRemain
  498. inc a
  499. ld d, TEXT_SCROLL
  500. .linesRemain
  501. ld [wTextRemainingLines], a
  502. ld a, [wNewlinesUntilFull]
  503. dec a
  504. jr nz, .dontPause
  505. ld d, TEXT_WAITBTN_SCROLL
  506. ld a, [wTextNbLines]
  507. .dontPause
  508. ld [wNewlinesUntilFull], a
  509. ; Dashes aren't overwritten on newlines, instead the newline is inserted right after
  510. ld a, [hl]
  511. cp " "
  512. jr z, .overwritingNewline
  513. cp TEXT_ZWS
  514. jr nz, .noSoftHyphen
  515. ; A soft hyphen causes a hyphen to be placed over it, after which the newline is inserted
  516. ld a, "-"
  517. ld [hli], a
  518. .noSoftHyphen
  519. ; We're going to shift the entire buffer right, so count an extra char...
  520. ; ...unless doing so would overflow the buffer.
  521. ld a, e
  522. cp LOW(wTextCharBufferEnd - 1)
  523. jr z, .bufferFull
  524. inc e
  525. .bufferFull
  526. ; Swap characters between `d` and `[hl]` (we already have the char to be inserted in `d`)
  527. .copyNewlinedChars
  528. ld a, d
  529. ld d, [hl]
  530. ld [hli], a
  531. ld a, e ; Stop when we're about to write the last char
  532. cp l
  533. jr nz, .copyNewlinedChars
  534. ; But write it, of course!
  535. .overwritingNewline
  536. ld [hl], d
  537. ; Restore dest ptr high byte
  538. ld d, h ; ld d, HIGH(wTextCharBuffer)
  539. ; Compute the amount of pixels remaining after inserting the newline
  540. ; pixels now = pixels before word - word length ⇒ word length = pixels before word - pixels now
  541. ld a, [wPixelsRemainingAtNewline]
  542. sub b
  543. ld b, a
  544. ; new line's pixels = line length - word length
  545. ld a, [wTextLineLength]
  546. sub b
  547. .noNewline
  548. ld [wLineRemainingPixels], a
  549. pop hl
  550. ld a, c
  551. ; If the character is a dash or a space, a newline can be inserted
  552. and a ; cp " " - " "
  553. jr z, .canNewline
  554. inc e ; This increment is also shared by the main loop
  555. cp "-" - " " ; Dashes aren't *overwritten* by the newline, instead it's inserted after
  556. ld a, e ; The increment has to be placed in an awkward way because it alters flags
  557. jr z, .canNewlineAfter
  558. .afterControlChar
  559. ld a, e
  560. cp LOW(wTextCharBufferEnd - 2) ; Give ourselves some margin due to multi-byte control chars
  561. jr c, _RefillCharBuffer
  562. dec e ; Compensate for what's below
  563. .done
  564. inc e ; If we jumped to .done, we have written a terminator, account for it
  565. ; Write src ptr for later
  566. ld a, l
  567. ld [wTextSrcPtr], a
  568. ld a, h
  569. ld [wTextSrcPtr+1], a
  570. ldh a, [hCurROMBank]
  571. ld [wTextSrcBank], a
  572. ; End the buffer refill at newlineable chars only
  573. ld a, [wNewlinePtrLow]
  574. cp 2
  575. jr nc, .foundNewlineableChar
  576. ld a, e
  577. .foundNewlineableChar
  578. ld [wTextReadPtrEnd], a
  579. ld a, e
  580. ld [wTextFillPtrEnd], a
  581. ld a, BANK(_PrintVWFChar)
  582. ldh [hCurROMBank], a
  583. ld [rROMB0], a
  584. ; Restart printer's reading
  585. ld hl, wTextCharBuffer
  586. ret
  587. .canNewline
  588. ld a, e
  589. inc e
  590. .canNewlineAfter
  591. ld [wNewlinePtrLow], a
  592. ld a, [wLineRemainingPixels]
  593. ld [wPixelsRemainingAtNewline], a
  594. jr .afterControlChar
  595. Reader2ByteNop:
  596. ld a, [hli]
  597. ld [de], a
  598. inc e
  599. Reader1ByteNop:
  600. ret
  601. ReaderSoftHyphen:
  602. ; TODO: the added hyphen might overflow the line when wrapping occurs
  603. pop bc ; We will take a detour instead of returning
  604. ld a, TEXT_ZWS
  605. ld [de], a
  606. jr _RefillCharBuffer.canNewline
  607. ReaderSetFont:
  608. ld a, [wRefillerCharset]
  609. ld c, a
  610. ld [wRefillerPrevFont], a
  611. ld a, [hli]
  612. ld [de], a
  613. inc e
  614. xor c
  615. and $F0
  616. jr ReaderUpdateCharset
  617. ReaderRestoreFont:
  618. ld a, [wRefillerCharset]
  619. and $0F
  620. ld c, a
  621. ld a, [wRefillerPrevFont]
  622. and $F0
  623. jr ReaderUpdateCharset
  624. ReaderSetVariant:
  625. ld a, [wRefillerCharset]
  626. ld c, a
  627. ld [wRefillerPrevVariant], a
  628. ld a, [hli]
  629. ld [de], a
  630. inc e
  631. xor c
  632. and $0F
  633. jr ReaderUpdateCharset
  634. ReaderRestoreVariant:
  635. ld a, [wRefillerCharset]
  636. and $F0
  637. ld c, a
  638. ld a, [wRefillerPrevVariant]
  639. and $0F
  640. ; Fall through
  641. ReaderUpdateCharset:
  642. xor c
  643. ld [wRefillerCharset], a
  644. add a, LOW(CharsetPtrs)
  645. ld c, a
  646. adc a, HIGH(CharsetPtrs)
  647. sub c
  648. ld b, a
  649. ld a, [bc]
  650. add a, 8 ; Add the offset to the character widths
  651. ld [wCurCharsetPtr], a
  652. inc bc
  653. ld a, [bc]
  654. adc a, 0
  655. ld [wCurCharsetPtr+1], a
  656. ret
  657. ReaderPrintBlank:
  658. pop bc ; We're not gonna return because we're gonna insert a custom size instead
  659. ld a, [hli] ; Read number of blanks
  660. ld [de], a
  661. ; inc e ; Don't increment dest ptr because the code path we'll jump into will do it
  662. ld c, a
  663. ld a, [wLineRemainingPixels]
  664. sub c
  665. ; We'll be jumping straight in the middle of some code path, make sure not to break it
  666. push hl
  667. ld c, "A" ; Make sure we won't get a newline
  668. jp _RefillCharBuffer.insertCustomSize ; Too far to `jr`
  669. ReaderWaitButton:
  670. ; Don't auto-wait for user input until the textbox has been entirely freshened
  671. ld a, [wTextNbLines]
  672. inc a ; The next newline will actually start introducing new text
  673. ld [wNewlinesUntilFull], a
  674. ret
  675. ; For the purpose of line length counting, newline, clearing and scrolling are the same
  676. ; For height counting, however...
  677. ReaderNewline:
  678. ld a, [wTextRemainingLines]
  679. dec a
  680. ld [wTextRemainingLines], a
  681. jr nz, ReaderScroll.checkFullBox
  682. dec e ; dec de
  683. ld a, TEXT_SCROLL
  684. ld [de], a
  685. inc e ; inc de
  686. ReaderScroll:
  687. ld a, [wTextRemainingLines]
  688. inc a
  689. ld [wTextRemainingLines], a
  690. .checkFullBox
  691. ld a, [wNewlinesUntilFull]
  692. dec a
  693. jr nz, StartNewLine
  694. dec e ; dec de
  695. ld a, TEXT_WAITBTN_SCROLL
  696. ld [de], a
  697. inc e ; inc de
  698. ReaderWaitButtonScroll:
  699. ld a, [wTextRemainingLines]
  700. inc a
  701. ld [wTextRemainingLines], a
  702. ld a, [wTextNbLines]
  703. jr StartNewLine
  704. ReaderClear:
  705. ld a, [wTextNbLines]
  706. ld [wTextRemainingLines], a
  707. StartNewLine:
  708. ld [wNewlinesUntilFull], a
  709. ; Reset line length, since we're forcing a newline
  710. ld a, [wTextLineLength]
  711. ld [wLineRemainingPixels], a
  712. ret
  713. ; Sets text ptr to given location
  714. ReaderJumpTo:
  715. ld a, [hli]
  716. ld b, a
  717. ld a, [hli]
  718. ld h, [hl]
  719. ld l, a
  720. ld a, b
  721. ldh [hCurROMBank], a
  722. ld [rROMB0], a
  723. ret
  724. ; Start printing a new string, then keep writing this one
  725. ; NOTE: avoids corruption by preventing too much recursion, but this shouldn't happen at all
  726. ReaderCall:
  727. ld a, [wTextStackSize]
  728. IF DEF(STACK_OVERFLOW_HANDLER)
  729. cp TEXT_STACK_CAPACITY
  730. call nc, STACK_OVERFLOW_HANDLER
  731. ENDC
  732. ; Read target ptr
  733. inc a ; Increase stack size
  734. ld [wTextStackSize], a
  735. ; Get ptr to end of 1st empty entry
  736. ld b, a
  737. add a, a
  738. add a, b
  739. add a, LOW(wTextStack - 1)
  740. ld c, a
  741. adc a, HIGH(wTextStack - 1)
  742. sub c
  743. ld b, a
  744. ; Save ROM bank immediately, as we're gonna bankswitch
  745. ldh a, [hCurROMBank]
  746. ld [bc], a
  747. dec bc
  748. ; Swap src ptrs
  749. ld a, [hli]
  750. ld [de], a ; Use current byte in char buffer as scratch
  751. ; Save src ptr now
  752. inc hl
  753. inc hl
  754. ld a, h
  755. ld [bc], a
  756. dec bc
  757. ld a, l
  758. ld [bc], a
  759. ; Read new src ptr
  760. dec hl
  761. ld a, [hld]
  762. ld l, [hl]
  763. ld h, a
  764. ; Perform bankswitch now that all bytecode has been read
  765. ld a, [de]
  766. ldh [hCurROMBank], a
  767. ld [rROMB0], a
  768. ret
  769. SECTION "VWF ROMX functions + data", ROMX
  770. PrintVWFControlChar:
  771. IF DEF(BAD_CTRL_CHAR_HANDLER)
  772. ; Check if ctrl char is valid
  773. cp TEXT_BAD_CTRL_CHAR
  774. call nc, BAD_CTRL_CHAR_HANDLER
  775. ENDC
  776. ; Control char, run the associated function
  777. ld de, _PrintVWFChar.charPrinted
  778. push de
  779. ; Push the func's addr (so we can preserve hl when calling)
  780. add a, a
  781. add a, LOW(ControlCharFuncs - 2)
  782. ld e, a
  783. adc a, HIGH(ControlCharFuncs - 2)
  784. sub e
  785. ld d, a
  786. ld a, [de]
  787. ld c, a
  788. inc de
  789. ld a, [de]
  790. ld b, a
  791. push bc
  792. ret ; Actually jump to the function, passing `hl` as a parameter for it to read (and advance)
  793. _PrintVWFChar:
  794. ld h, HIGH(wTextCharBuffer)
  795. ld a, [wTextReadPtrLow]
  796. ld l, a
  797. .setDelayAndNextChar
  798. ; Reload delay
  799. ld a, [wTextLetterDelay]
  800. ld [wTextNextLetterDelay], a
  801. .nextChar
  802. ; First, check if the buffer is sufficiently full
  803. ; Making the buffer wrap would be costly, so we're keeping a safety margin
  804. ; Especially since control codes are multi-byte
  805. ld a, [wTextReadPtrEnd]
  806. cp l
  807. IF DEF(OVERREAD_HANDLER)
  808. call c, OVERREAD_HANDLER ; This needs to be first as it's a no-return
  809. ENDC
  810. call z, RefillCharBuffer ; If it was second this function could destroy carry and trigger it
  811. ; Read byte from string stream
  812. ld a, [hli]
  813. and a ; Check for terminator
  814. jr z, .return
  815. cp " "
  816. jr c, PrintVWFControlChar
  817. ; Print char
  818. ; Save src ptr & letter ID
  819. push hl
  820. sub " "
  821. ld e, a
  822. ; Get ptr to charset table
  823. ld a, [wTextCharset]
  824. add a, LOW(CharsetPtrs)
  825. ld l, a
  826. adc a, HIGH(CharsetPtrs)
  827. sub l
  828. ld h, a
  829. ld a, [hli]
  830. ld b, [hl]
  831. ld c, a
  832. ; Get ptr to letter
  833. ld d, 0
  834. ld l, e
  835. ld h, d ; ld h, 0
  836. add hl, hl
  837. add hl, hl
  838. add hl, hl
  839. add hl, de ; * 9
  840. add hl, bc
  841. ld d, h
  842. ld e, l
  843. ; Get dest buffer ptr
  844. ld hl, wTextTileBuffer
  845. ld a, 8
  846. .printOneLine
  847. ldh [hVWFRowCount], a
  848. ld a, [wTextCurPixel]
  849. ld b, a
  850. and a ; Check now if shifting needs to happen
  851. ld a, [de]
  852. inc de
  853. ld c, 0
  854. jr z, .doneShifting
  855. .shiftRight
  856. rra ; Actually `srl a`, since a 0 bit is always shifted in
  857. rr c
  858. dec b
  859. jr nz, .shiftRight
  860. .doneShifting
  861. ld b, a
  862. ld a, [wTextColorID]
  863. rra
  864. jr nc, .noLSB
  865. ld a, b
  866. or [hl]
  867. ld [hl], a
  868. set 4, l
  869. ld a, c
  870. or [hl]
  871. ld [hl], a
  872. res 4, l
  873. ld a, [wTextColorID]
  874. rra
  875. .noLSB
  876. inc l
  877. rra
  878. jr nc, .noMSB
  879. ld a, b
  880. or [hl]
  881. ld [hl], a
  882. set 4, l
  883. ld a, c
  884. or [hl]
  885. ld [hl], a
  886. res 4, l
  887. .noMSB
  888. inc l
  889. ldh a, [hVWFRowCount]
  890. dec a
  891. jr nz, .printOneLine
  892. ; Advance read by size
  893. ld hl, wTextCurPixel
  894. ld a, [de]
  895. add a, [hl]
  896. ld [hl], a
  897. ; Restore src ptr
  898. pop hl
  899. .charPrinted
  900. ; Check if flushing needs to be done
  901. ld a, [wTextCurPixel]
  902. sub 8
  903. jr c, .noTilesToFlush
  904. ; Move back by 8 pixels
  905. ld [wTextCurPixel], a
  906. ; Flush them to VRAM
  907. call FlushVWFBuffer
  908. ; Try flushing again (happens with characters 9 pixels wide)
  909. ; We might never use 9-px chars, but if we do, there'll be support for them ^^
  910. jr .charPrinted
  911. ; This block of code is only here to avoid turning a `jp` into a `jr`
  912. .return
  913. ; Tell caller we're done (if we're not, this'll be overwritten)
  914. ld a, $FF
  915. ld [wTextSrcPtr + 1], a
  916. jr .flushAndFinish
  917. .noTilesToFlush
  918. ; If not printing next char immediately, force to flush
  919. ld a, [wTextNextLetterDelay]
  920. and a
  921. jp z, .setDelayAndNextChar
  922. dec a
  923. ld [wTextNextLetterDelay], a
  924. ; Write back new read ptr into buffer for next iteration
  925. ld a, l
  926. ld [wTextReadPtrLow], a
  927. .flushAndFinish
  928. ; Check if flushing is necessary
  929. ld a, [wTextCurPixel]
  930. cp 2
  931. ret c
  932. ; We're not using FlushVWFBuffer because we don't want to advance the tile
  933. ld a, [wTextTileBlock]
  934. ld d, a
  935. ld a, [wTextCurTile]
  936. swap a
  937. ld h, a
  938. and $F0
  939. ld l, a
  940. xor h
  941. add a, d
  942. ld h, a
  943. ld de, wTextTileBuffer
  944. .copyTile
  945. ldh a, [rSTAT]
  946. and STATF_BUSY
  947. jr nz, .copyTile
  948. ld a, [de]
  949. ld [hli], a
  950. inc e ; inc de
  951. ld a, [de]
  952. ld [hli], a
  953. inc e ; inc de
  954. bit 4, e
  955. jr z, .copyTile
  956. ret
  957. ControlCharFuncs:
  958. CTRL_CHAR_PTRS
  959. TextDelay:
  960. ld a, [hli]
  961. ld [wTextNextLetterDelay], a
  962. ret
  963. TextRestoreFont:
  964. ld de, wTextCharset
  965. ld a, [de]
  966. and $0F
  967. ld b, a
  968. ld a, [wPreviousFont]
  969. and $F0
  970. jr _TextSetCharset
  971. TextRestoreVariant:
  972. ld de, wTextCharset
  973. ld a, [de]
  974. and $F0
  975. ld b, a
  976. ld a, [wPreviousVariant]
  977. and $0F
  978. jr _TextSetCharset
  979. TextSetVariant:
  980. ld de, wTextCharset
  981. ld a, [de]
  982. ld [wPreviousVariant], a
  983. and $F0
  984. ld b, a
  985. ld a, [hli]
  986. and $0F
  987. jr _TextSetCharset
  988. TextSetFont:
  989. ld de, wTextCharset
  990. ld a, [de]
  991. ld [wPreviousFont], a
  992. and $0F
  993. ld b, a
  994. ld a, [hli]
  995. and $F0
  996. _TextSetCharset:
  997. or b
  998. ld [de], a
  999. jr PrintNextCharInstant
  1000. TextSetColor:
  1001. ld a, [hli]
  1002. and 3
  1003. ld [wTextColorID], a
  1004. jr PrintNextCharInstant
  1005. MACRO skip_key
  1006. IF \1 == 1
  1007. rra
  1008. jr c, \2
  1009. ELIF \1 == 1 << 7
  1010. add a, a
  1011. jr c, \2
  1012. ELSE
  1013. and \1
  1014. jr nz, \2
  1015. ENDC
  1016. ENDM
  1017. TextWaitButton:
  1018. xor a ; FIXME: if other bits than 7 and 6 get used, this is gonna be problematic
  1019. ld [wTextFlags], a
  1020. ; End this char if suitable user input is found
  1021. ldh a, [hHeldKeys]
  1022. skip_key SKIP_HELD_KEYS, PrintNextCharInstant
  1023. ldh a, [hPressedKeys]
  1024. skip_key SKIP_PRESSED_KEYS, PrintNextCharInstant
  1025. ; If no button has been pressed, keep reading this char
  1026. ; Ensure the engine reacts on the very next frame to avoid swallowing buttons
  1027. ld a, 1
  1028. ld [wTextNextLetterDelay], a
  1029. ; We know that text is running, so it's fine to overwrite bit 7
  1030. ld a, $40
  1031. ld [wTextFlags], a
  1032. ; Decrement src ptr so this char keeps getting read
  1033. dec hl
  1034. ret
  1035. TextPrintBlank:
  1036. ld a, [hli]
  1037. ld c, a
  1038. ld a, [wTextCurPixel]
  1039. add a, c
  1040. ld c, a
  1041. and $F8
  1042. jr z, .noNewTiles
  1043. rrca
  1044. rrca
  1045. rrca
  1046. ld b, a
  1047. .printNewTile
  1048. push bc
  1049. call FlushVWFBuffer ; Preserves HL
  1050. pop bc
  1051. dec b
  1052. jr nz, .printNewTile
  1053. .noNewTiles
  1054. ld a, c
  1055. and 7
  1056. ld [wTextCurPixel], a
  1057. ; Fall through
  1058. PrintNextCharInstant:
  1059. xor a
  1060. ld [wTextNextLetterDelay], a
  1061. ret
  1062. TextWaitButtonScroll:
  1063. call TextWaitButton
  1064. ; The function returns with a = 0 iff the user has input something
  1065. and a
  1066. ret nz
  1067. ; fallthrough
  1068. TextScroll:
  1069. push hl
  1070. ld b, b ; You'll have to write your own code here
  1071. ld hl, IMPRINT_STARTING_POINT
  1072. ld de, IMPRINT_STARTING_POINT + SCRN_VX_B
  1073. ld b, TEXT_HEIGHT_TILES - 1
  1074. .shiftTilemapRows
  1075. ld c, TEXT_WIDTH_TILES
  1076. .shiftRow
  1077. ldh a, [rSTAT]
  1078. and STATF_BUSY
  1079. jr nz, .shiftRow
  1080. ld a, [de]
  1081. ld [hli], a
  1082. inc e
  1083. dec c
  1084. jr nz, .shiftRow
  1085. ld a, e
  1086. add a, SCRN_VX_B - TEXT_WIDTH_TILES
  1087. ld e, a
  1088. adc a, d
  1089. sub e
  1090. ld d, a
  1091. ld hl, -SCRN_VX_B
  1092. add hl, de
  1093. dec b
  1094. jr nz, .shiftTilemapRows
  1095. lb bc, 0, TEXT_WIDTH_TILES
  1096. call LCDMemsetSmallFromB
  1097. ld hl, wPenPosition
  1098. ld a, [hl]
  1099. sub SCRN_VX_B
  1100. ld [hli], a
  1101. jr nc, .noCarry
  1102. dec [hl]
  1103. .noCarry
  1104. pop hl
  1105. ; fallthrough
  1106. TextNewline:
  1107. ; Flush the current tile if non-blank
  1108. ld a, [wTextCurPixel]
  1109. cp 2
  1110. call nc, FlushVWFBuffer
  1111. ; Reset position
  1112. xor a
  1113. ld [wTextCurPixel], a
  1114. ld de, wNbNewlines
  1115. ld a, [de]
  1116. inc a
  1117. ld [de], a
  1118. dec a
  1119. add a, LOW(wNewlineTiles)
  1120. ld e, a
  1121. adc a, HIGH(wNewlineTiles)
  1122. sub e
  1123. ld d, a
  1124. ld a, [wTextCurTile]
  1125. ld [de], a
  1126. jr PrintNextCharInstant
  1127. TextSync:
  1128. ld a, [wTextFlags]
  1129. set 7, a
  1130. ld [wTextFlags], a
  1131. ret
  1132. TextClear:
  1133. push hl
  1134. ;;;; You'll probably want to clear some tilemap here ;;;;
  1135. ld b, b
  1136. ld hl, IMPRINT_STARTING_POINT
  1137. ld e, TEXT_HEIGHT_TILES
  1138. .clearTilemap
  1139. lb bc, 0, TEXT_WIDTH_TILES
  1140. call LCDMemsetSmallFromB
  1141. ld a, l
  1142. add a, SCRN_VX_B - TEXT_WIDTH_TILES
  1143. ld l, a
  1144. adc a, h
  1145. sub l
  1146. ld h, a
  1147. dec e
  1148. jr nz, .clearTilemap
  1149. ; Reset text printing
  1150. ; Don't flush if current tile is empty
  1151. ld a, [wTextCurPixel]
  1152. cp 2
  1153. ; Flush buffer to VRAM
  1154. call nc, FlushVWFBuffer
  1155. ; Reset position always, though
  1156. xor a
  1157. ld [wTextCurPixel], a
  1158. ; The pen should not advance, should we have flushed a tile
  1159. ld [wFlushedTiles], a
  1160. ld [wNbNewlines], a
  1161. ;;;; You will probably want to reset the pen position, too ;;;;
  1162. ld b, b
  1163. ld hl, IMPRINT_STARTING_POINT
  1164. call SetPenPosition
  1165. pop hl
  1166. ret
  1167. SECTION "Charset data", ROM0
  1168. IF !DEF(NB_CHARSETS)
  1169. FAIL "Please define NB_CHARSETS!"
  1170. ENDC
  1171. CharsetPtrs::
  1172. rsreset
  1173. REPT NB_CHARSETS
  1174. CHARSET equs "CHARSET_{d:_RS}"
  1175. CHARSET_DEFINED equs "DEF({CHARSET})"
  1176. IF CHARSET_DEFINED
  1177. CHARSET_LABEL equs "Charset{d:_RS}"
  1178. dw CHARSET_LABEL
  1179. PUSHS
  1180. SECTION "Charset {d:_RS}", ROM0
  1181. CHARSET_LABEL:
  1182. INCBIN "{{CHARSET}}"
  1183. IF @ - CHARSET_LABEL > CHARACTER_SIZE * NB_FONT_CHARACTERS
  1184. WARN "Charset {d:_RS} is larger than expected; keep in mind they can only contain {d:NB_FONT_CHARACTERS} characters"
  1185. ENDC
  1186. POPS
  1187. PURGE CHARSET_LABEL
  1188. ELSE
  1189. dw 0
  1190. ENDC
  1191. PURGE CHARSET_DEFINED
  1192. PURGE CHARSET
  1193. rsset _RS + 2
  1194. ENDR
  1195. SECTION "VWF engine memory", WRAM0,ALIGN[7]
  1196. wTextCharBuffer::
  1197. ds 64
  1198. wTextCharBufferEnd:: ; We need this not to be on a 256-byte boundary
  1199. assert HIGH(wTextCharBuffer) == HIGH(wTextCharBufferEnd)
  1200. assert @ & -(1 << 6)
  1201. wTextTileBuffer::
  1202. ds $10 * 3
  1203. assert @ & -(1 << 5)
  1204. ; Format of entries: ptr(16bit LE), bank
  1205. wTextStack::
  1206. ds TEXT_STACK_CAPACITY * 3
  1207. ; Number of entries in the stack
  1208. wTextStackSize::
  1209. db
  1210. wTextCurPixel::
  1211. db
  1212. wTextCurTile::
  1213. db
  1214. ; ID of the last tile the VWF engine is allowed to write to
  1215. wLastTextTile::
  1216. db
  1217. ; Tells which tile to wrap to when going past the above
  1218. wWrapTileID::
  1219. db
  1220. ; This allows selecting the "tile block" to use
  1221. ; Write $80 for tiles in $8000-8FFF
  1222. ; Write $90 for tiles in $9000-97FF
  1223. ; Other values are not officially supported, experiment yourself
  1224. wTextTileBlock::
  1225. db
  1226. ; Tells which color to use in the palette for the text (in range 0-3)
  1227. wTextColorID::
  1228. db
  1229. ; Defines which character table to use
  1230. ; Upper nibble is language-defined, lower nibble is decoration
  1231. wTextCharset::
  1232. db
  1233. wPreviousFont::
  1234. db
  1235. wPreviousVariant::
  1236. db
  1237. wTextSrcPtr::
  1238. dw
  1239. wTextSrcBank:
  1240. db
  1241. ; Number of frames between each character
  1242. wTextLetterDelay::
  1243. db
  1244. ; Number of frames till next character
  1245. wTextNextLetterDelay::
  1246. db
  1247. ; Bit 6 - Whether the text engine is currently waiting for a button press
  1248. ; Bit 7 - Whether the text engine is halted, for syncing (can be reset)
  1249. wTextFlags::
  1250. db
  1251. ; Number of tiles flushed, used to know how many tiles should be written to the tilemap
  1252. wFlushedTiles::
  1253. db
  1254. ; Number of newlines that occurred during this print
  1255. wNbNewlines::
  1256. db
  1257. ; ID of the tiles during which newlines occurred (NOTE: there can be duplicates due to empty lines!!)
  1258. wNewlineTiles::
  1259. ds TEXT_NEWLINE_CAPACITY
  1260. wPenStartingPosition::
  1261. dw
  1262. wPenPosition::
  1263. dw
  1264. wPenCurTile::
  1265. db
  1266. ; Low byte of the read ptr into wTextCharBuffer
  1267. wTextReadPtrLow::
  1268. db
  1269. ; Where the refiller ended, i.e. where the printer needs to stop
  1270. wTextReadPtrEnd::
  1271. db
  1272. ; Where the refiller's read ended; characters between the above and this may be candidate for an
  1273. ; auto linebreak, so they shouldn't be passed to the printer yet
  1274. wTextFillPtrEnd::
  1275. db
  1276. ; Number of lines of the current text area
  1277. wTextNbLines::
  1278. db
  1279. ; How many newlines remain before the text box is full
  1280. wTextRemainingLines::
  1281. db
  1282. ; How many newlines remain until the text box has been filled with fresh text
  1283. wNewlinesUntilFull::
  1284. db
  1285. ; Length, in pixels, of the current text line
  1286. wTextLineLength::
  1287. db
  1288. wLineRemainingPixels::
  1289. db
  1290. ; Ptr to last newlineable location
  1291. wNewlinePtrLow::
  1292. db
  1293. ; wLineRemainingPixels at the time wNewlinePtrLow is updated
  1294. wPixelsRemainingAtNewline::
  1295. db
  1296. ; Charset ptr is cached by refiller to speed up reads
  1297. wCurCharsetPtr::
  1298. dw
  1299. wRefillerCharset::
  1300. db
  1301. wRefillerPrevFont::
  1302. db
  1303. wRefillerPrevVariant::
  1304. db
  1305. SECTION "VWF engine fast memory", HRAM
  1306. ; How many rows are left to be drawn in the current tile
  1307. hVWFRowCount::
  1308. db