Page 1 of 2

Help wanted with 8×8 VWF algorithm

Posted: Sun Jun 28, 2015 11:13 am
by Ramsis
So I've been trying and trying to implement a VWF for the dialogue in Furry RPG, but without success so far. :(

Image

Note that I spent the last two weeks studying VWF source examples on RHDN (including this one) -- most of which are a pain to even read, or simply incomplete. Also, I stumbled across Stealth Translation's doc, and couldn't help but notice that it too is more than incomplete. Also, I looked at both tepples' Action menu and bisqwit's Chronotools 8×8 VWF engine, both of which only managed to confuse me even more. :?

Please note that the bit-shifting apparently works correctly -- the left half of the "2" appears shifted to the right just fine (albeit on the wrong tile), whereas the right half appears unnecessarily shifted, and shows up as garbage in an unwanted place. :|

Here's the code I came up with after studying all those other documents. Code executes during Vblank, variables starting with DP_ are direct page, vars starting with ARRAY_ are in the range of $0200-$1FFF (minus stack pointer) in WRAM:

Code: Select all

ProcessVWFTiles:
	A16

	lda DP_TextASCIIChar			; ASCII char no. --> font tile no.
	asl a					; value * 16 as 1 font tile = 16 bytes
	asl a
	asl a
	asl a
	tax

	A8

	lda DP_VWFBitsRemaining
	and #$07
	sta DP_VWFBitsRemaining
	bne __UseOldVWFTile

	A16

	lda DP_VWFTileNew			; new tile no. --> VWF buffer index
	bra +

__UseOldVWFTile:
	A16

	lda DP_VWFTileOld			; old tile no. --> VWF buffer index
+	asl a
	asl a
	asl a
	asl a
	tay

	A8

	lda #16					; loop through 16 bytes per tile
	sta DP_VWFLoop

-	lda.l GFX_FontMode5, x
	xba					; move to high byte

	lda #$00

	jsr __VWFShiftBits			; shift tile data if necessary

	ora ARRAY_VWFTileBuffer1+1, y
	sta ARRAY_VWFTileBuffer1+1, y

	xba

	ora ARRAY_VWFTileBuffer1, y
	sta ARRAY_VWFTileBuffer1, y

	iny
	inx

	dec DP_VWFLoop
	bne -

	ldx DP_TextASCIIChar			; ASCII char no. --> font width table index

	lda DP_VWFBitsRemaining			; adjust pixels remaining for shifting
	bne +

	inc DP_VWFTileOld
	inc DP_VWFTileNew
	inc DP_VWFTileNew
	lda #8					; 8 = max. no. of bits

+	sec
	sbc.l SRC_FWTDialogue, x
	bpl +
	
	eor #$FF				; handle overflow
	inc a
	sta DP_VWFBitsRemaining

	inc DP_VWFTileOld
	inc DP_VWFTileNew
	inc DP_VWFTileNew

	lda #8
	sec
	sbc DP_VWFBitsRemaining

+	sta DP_VWFBitsRemaining

rts
	

	
__VWFShiftBits:
	phx
	
	A16

	pha

	lda DP_VWFBitsRemaining
	bne +

	pla

	bra __VWFShiftBitsDone

+	dec a
	asl a
	tax

	pla

	jmp (__VWFShiftAmount, x)



__VWFShiftAmount:
	.DW _R1, _R2, _R3, _R4, _R5, _R6, _R7

_R1:
	lsr a

_R2:
	lsr a

_R3:
	lsr a

_R4:
	lsr a

_R5:
	lsr a

_R6:
	lsr a

_R7:
	lsr a



__VWFShiftBitsDone:

	A8

	plx
rts
Download:
http://manuloewe.de/snestuff/projects/f ... d_00224.7z

Any substantial help is very much appreciated. Thanks! :)
Ramsis

Re: Help wanted with 8×8 VWF algorithm

Posted: Sun Jun 28, 2015 11:46 am
by Sik
I'm getting the impression the problem is calculating which byte to write into (note how the right half of the digits is shifted down by 1 pixel as well).

Also consider testing with letters, numbers are probably the one thing you want to keep fixed width (yes, this means extra spacing around the 1).

Re: Help wanted with 8×8 VWF algorithm

Posted: Sun Jun 28, 2015 11:57 am
by lidnariq
<tangent> Bring back text figures! (It turns out that monospaced numerals are a modern invention, to accommodate computers not needing to know the difference between tabular data and mid-text data)

Re: Help wanted with 8×8 VWF algorithm

Posted: Sun Jun 28, 2015 12:27 pm
by Sik
It's more to do with the fact that if you have variable-width digits then use that font in a counter, the width of the number will go all over the place as the number changes - especially annoying when the value is changing constantly like with timers and such.

Re: Help wanted with 8×8 VWF algorithm

Posted: Sun Jun 28, 2015 12:59 pm
by tepples
What's the first thing that confuses you about the VWF engine in the Action 53 menu? I'm willing to document everything more thoroughly.

Agreed about digit width, which is why the font shipped with my own VWF engine leaves an extra pixel of space on the sides of the glyph for '1'.
See the extra pixel of space on left and right sides of '1' glyph
See the extra pixel of space on left and right sides of '1' glyph
vwf7_digits.png (462 Bytes) Viewed 5843 times
In any case, text figures (digit glyphs with descenders) and a narrow advance width for '1' are orthogonal, meaning each can be used without the other. Here are some fixed-width text figures that I designed for another project.
See descenders on '3', '4', '5', '7', and '9' and ascenders only on '6' and '8'
See descenders on '3', '4', '5', '7', and '9' and ascenders only on '6' and '8'
text_figures.png (636 Bytes) Viewed 5845 times

Re: Help wanted with 8×8 VWF algorithm

Posted: Sun Jun 28, 2015 3:36 pm
by Myask
That ascent/descent is very subtle, tepples.
Sik wrote:It's more to do with the fact that if you have variable-width digits then use that font in a counter, the width of the number will go all over the place as the number changes - especially annoying when the value is changing constantly like with timers and such.
This is alleviated somewhat when the number is justified to the most-significant digit rather than the least...but still a problem. (And if you do that, then you get a confusing change when a digit is added, if you weren't using leading zeros.)

Re: Help wanted with 8×8 VWF algorithm

Posted: Mon Jun 29, 2015 5:30 am
by Ramsis
Sik wrote:I'm getting the impression the problem is calculating which byte to write into (note how the right half of the digits is shifted down by 1 pixel as well).
Thanks. Indeed, I'm not quite sure if I'm getting the correct Y index value at all. And since I don't really know what to take into account for that, I can only hope someone will point me in the right direction. :)
Sik wrote:Also consider testing with letters, numbers are probably the one thing you want to keep fixed width (yes, this means extra spacing around the 1).
The dialogue, where numbers barely ever appear anyway, will be an all-VWF. The menu, on the other hand, will employ fixed-width fonts for numbers etc., and possibly a VWF for descriptions and such.
tepples wrote:What's the first thing that confuses you about the VWF engine in the Action 53 menu?
Nothing in particular, really. I've just been a bit frustrated about all that time spent on staring at other peoples' code examples without ever fully grasping the essence of how and why those work. :?

Re: Help wanted with 8×8 VWF algorithm

Posted: Mon Jun 29, 2015 5:57 am
by tepples
Ramsis wrote:
tepples wrote:What's the first thing that confuses you about the VWF engine in the Action 53 menu?
Nothing in particular, really. I've just been a bit frustrated about all that time spent on staring at other peoples' code examples without ever fully grasping the essence of how and why those work. :?
Do you use IRC or AIM or Skype or Hangouts? I'm willing to explain how it works in real time text chat.

Re: Help wanted with 8×8 VWF algorithm

Posted: Mon Jun 29, 2015 11:16 am
by Ramsis
Today's progress:

Image

I rewrote/simplified the routine quite significantly, which now looks like this:

Code: Select all

ProcessVWFTiles:
	A16

	lda DP_TextASCIIChar			; ASCII char no. --> font tile no.
	asl a					; value * 16 as 1 font tile = 16 bytes
	asl a
	asl a
	asl a
	tax

	A8

	ldy DP_VWFBufferIndex

	lda #16					; loop through 16 bytes per tile
	sta DP_VWFLoop

-	lda.l GFX_FontMode5, x
	xba					; move to high byte

	lda #$00

	jsr __VWFShiftBits			; shift tile data if necessary

	A16

	xba

	ora ARRAY_VWFTileBuffer1, y
	sta ARRAY_VWFTileBuffer1, y

	A8

	iny
	inx

	dec DP_VWFLoop
	bne -

	ldx DP_TextASCIIChar			; ASCII char no. --> font width table index

	lda.l SRC_FWTDialogue, x
	clc
	adc DP_VWFBitsUsed
	cmp #8
	bcs +
	sta DP_VWFBitsUsed

	A16

	tya
	sec
	sbc #16
	sta DP_VWFBufferIndex

	A8

	bra ++

+	sec
	sbc #8
	sta DP_VWFBitsUsed
	sty DP_VWFBufferIndex
++
rts



__VWFShiftBits:
	phx
	phy

	A16

	pha

	lda DP_VWFBitsUsed
	bne +
	
	pla

	bra __VWFShiftBitsDone

+	tay

	pla

-	lsr a
	dey
	bne -

__VWFShiftBitsDone:

	A8

	ply
	plx
rts
Still, when characters have a width of other than 8 or 4 pixels, it freaks out (this should read "bc", both of which are 7-pixel-wide characters):

Image

Anyone spot the error in my code? Please? :lol:
tepples wrote:Do you use IRC or AIM or Skype or Hangouts? I'm willing to explain how it works in real time text chat.
Thanks, I might actually come back to you some time. :)

Re: Help wanted with 8×8 VWF algorithm

Posted: Mon Jun 29, 2015 4:20 pm
by Near
When you are building your proportional text string in RAM, you need to store the other half of the tiledata that shifts off of your original tile.

Let's say you are drawing 'bc', and each is six pixels long.

The first one is easy, it fits cleanly onto one tile. But the second one splits two pixels of 'c' onto the first tile, and four onto the next tile.

The way to do this is to use a 16-bit accumulator and xba.

Keep a bit-position for where you are at on the screen. This value lsr #3 (divided by 8) is the tile# you are on, and this value and #7 (low three bits) is the bit position on said tile.

In our case with 'bc', you've drawn 'b', so now you're on tile# 0, bit position #6.

Load up a horizontal line of 'c', and #$ff, and now use xba on it.

Thus we go from:
jjjjjjjj cccccc00 (j = junk, c = c, 0 = padding)
and #$ff
00000000 cccccc00
xba
cccccc00 00000000

Now remember our tile/bit position and #7 is 6. So we right shift A six times (lsr #6)

lsr #6
000000cc cccc0000

Or the way I like to do it:
pha; lda bitpos; and #7; tax; pla ;get the bitpos into X
-; beq +; lsr; dex; bra -; + ;shift right and decrement X until zero

(you can get this faster with a jmp (table,x) into a block of lsr's, but this is for demonstration.)

We first need to OR the upper 8-bits with the existing tile# 0 in RAM, and then store the remaining four bits of 'c' into the next tile. This usually goes something like this:

xba
sep #$20
ora tiledata,x
sta tiledata,x
xba
sta tiledata+16,x ;16 for 2bpp tiles
inx #2 ;one horizontal line
<repeat for all lines>

(the above can be optimized by doing it in the reverse order, this is for demonstration though.)

Now when you're done, add the length of 'c' (6) to your tile/bit-pos. It was 6 from 'b', now we add 6 from 'c' and it's 12. Or tile#1, bit-position #4. And repeat for the rest of the string.

When you're done building your string, the total # of tiles you need has to be incremented by one if bitpos&7 != 0. Say you only drew 'bc', since we're at 12, we have -two- tiles we need to transfer data for, and two tilemap entries need to be valid for that.

Simple method:
lda bitpos
clc; adc #7
lsr #3

Have fun ;)

Re: Help wanted with 8×8 VWF algorithm

Posted: Tue Jun 30, 2015 10:06 am
by Ramsis
1000 kudos to you, byuu. ^^ That 16 for 2bpp tiles clue of yours helped me make my algorithm work almost instantly. :D :D :D

Of course, it still took a lot more changes to my text engine, as well as an all-new buffer management/VRAM transfer routine, in order to get the desired result.

Which currently looks like this:

Image

To do:
  • move the buffer-building routine to the active display period (this should avoid gfx glitches)
  • rework carriage returns / maybe even implement automatic line-wrapping?!
  • track down and fix all buffer-related bugs (of which there are many :P )
Download:
http://manuloewe.de/snestuff/projects/f ... d_00226.7z
(Please be warned -- this build is buggy!)

Re: Help wanted with 8×8 VWF algorithm

Posted: Tue Jun 30, 2015 10:57 am
by Sik
Now nitpicking on the font: how does it look on TV? (or at least with a NTSC filter) Because I have the feeling that font must be awful to read since it's so thin.

Re: Help wanted with 8×8 VWF algorithm

Posted: Tue Jun 30, 2015 12:16 pm
by Ramsis
Sik wrote:Now nitpicking on the font: how does it look on TV? (or at least with a NTSC filter) Because I have the feeling that font must be awful to read since it's so thin.
Rest assured that FURRY RPG will be designed with modern 40"+ TV sets in mind -- though not with all-anamorph tiles for 16:9, despite this actually being a short-listed (i.e., early on discarded) design question. :wink:

Re: Help wanted with 8×8 VWF algorithm

Posted: Tue Jun 30, 2015 1:13 pm
by Sik
I was talking about the SDTV ones =S (i.e. the ones the SNES was originally intended for... maybe over composite instead of RF though)

Re: Help wanted with 8×8 VWF algorithm

Posted: Tue Jun 30, 2015 2:34 pm
by tepples
Plenty of SDTVs take an S-Video signal. I may take a photo of S-Video displayed on an SDTV tonight.