Welcome, Guest. Please Login or Register
 
The Purple Parade is marching in full stride to the beat of that 'other' drum we all hear, but generally ignore. Wink
Home Help Search Login Register


Pages: 1 2 3 
Send Topic Print
Project - nuVWF (formerly Nightcrawler's VWF) (Read 38188 times)
Nightcrawler
YaBB Administrator
*****
Offline


The Dark Angel of Romhacking

Posts: 3292
USA
Gender: male
Re: Project - nuVWF (formerly Nightcrawler's VWF)
Reply #30 - Oct 13th, 2015 at 12:28pm
 
*NuVWF Update*

Overview:

I set out to create a solution that would be able to convert static and dynamic text engines of any type (any bitplane depth, size etc), in any code variety possible on the SNES, into a VWF renderer. That's a tall order, but let's rearrange the problem. We don't really want to convert all of these possibilities to be VWF.  Rather, we want to design a way to be able to easily replace all types of existing text engines with a single VWF rendering engine. Approaching it from that angle was the key for me. This approach means we can abstract ourselves from the countless possibilities and game specific details to the fullest possible extent. It means we can focus only on the common elements that every text engine will have. If we break our system down into modules that address common elements, the result is a drop-in solution that can be hooked into any text engine at common points with minimal work. The devil is in the details of course. What are some of these common elements to think about?

Loading an input character of some bitplane depth, size, and font.
Rendering an output character.
- Rendering for static engines is simply an entry in the tilemap mapping to a static font character in VRAM.
- Rendering for dynamic engines dynamically renders characters to RAM in some output format and quantity.
Transferring rendered characters to VRAM.
- static engines do not to do this, however we will always need to do this for our VWF as it is always dynamic.

At it's core, NuVWF is an input/output VWF rendering engine coupled with an optional transfer subsystem. It renders up to 8 pixel wide characters at 8 or 16 pixel height (Linear tile ordered font chars only!). The input and output can independently be set to 1bpp, 2bpp, or 4bpp. A bit depth auto up-convert will happen when the output bpp exceeds the input. Rendering can be set to use a new internal managed ring buffer, or existing game's buffer.

Rendering Anywhere:

Easily overlooked is the fact that the system needs to be flexible enough to take input from, and render output to, any address on the system dynamically. This is a requirement to work for any game, and/or multiple text engines per game. This is tough to pull off on the SNES. Having such dynamic 24-bit and bank independence forces you to forgo most typical optimizations. You can't rely on having any memory in direct page, or any common banks between font, text, and output locations. As a result, there is significantly more overhead, and a large speed penalty. Speed while maintaining dynamic flexibility is probably the single biggest challenge. It could have been much faster if setup required you to customize various code routines, or if I set up several variations of the same routines to choose from. However, I wanted this to be a drop-in library with one set of routines, that you don't have to touch, that really does work everywhere. That was worth more to me than anything. I'd never have to write another VWF, or deal associated details of those routines again! I have attempted to mitigate the speed and overhead issue by taking a minimalist approach to the whole thing and keeping features limited, but functional enough to accomplish the goal. Some requirements on font have also been imposed to reduce complexity. It is English/Latin font centric, so supporting non-English/Latin fonts was not a consideration. I think it came out fast enough to be used in most circumstances. Certainly this can be revisited in the future. Further refinements and optimizations can surely be made!


Public Interface:

I've written up a few notes on the current public interface.

Code:
;**********************************************************************************************************
;* Settings - These need to be set here in this file by the user!
;**********************************************************************************************************
membase             = $XXXXXX   ;base offset for all nuvwf variables. Allocate $40 bytes starting here!
dmaqueue            = $XXXXXX   ;dma transfer queue offset. Each slot is 8 bytes - 0 is debug number, 1 is source bank, 2+3 is 16-bit source, 4+5 is VRAM destination, 6+7 is bytes to transfer.
!dmaqueuesize       = 0         ;size in slots (8bytes each) of dmaqueue. If limit reached, DMA will refuse to add more. Set to 0 if using external transfer method.
!dmachannel         = 0         ;dma channel to use for all dma transfers.
!blankmask          = $00       ;backsplash color - $ff (11=blank (2bpp font) or 1=blank (1bpp font)) or $00 (00=blank (2bpp font) or 0=blank (1bpp font)) .

;**********************************************************************************************************
;* Public external variables that should be set or read via user application.
;**********************************************************************************************************
rendermode          = membase       ;Can be changed at any time. -8
    !VWFMode     = 0                ;Normal VWF Rendering Mode
    !TileMapMode = 1                ;TileMapMode. Run of the mill tilemap output only. No rendering, tile counting, transfers etc.
    !StaticMode  = 2                ;No tile rendering, but positions, tile counting, and index updates. This mode assumes static data is in VRAM already by external means.
    !RenderOff   = 3                ;All output off. Rendering, positions, tiles, etc. do not update.
flag                = membase+$2    ;status flag - Bits 1,2,3 can be written. All others should be readonly -8
                                    ;Bit 7 - Last Rendered Character caused tile advance (spillover), tileindex updated for mapping.
                                    ;Bit 4 - vwfbuffer buffer full
                                    ;Bit 3 - DMA NMI mode Enable
                                    ;Bit 2 - DMA Tile/Dialog mode Enable
                                    ;Bit 1 - DMA Enable
                                    ;Bit 0 - Data Ready to Transfer (Cleared on transfer)
fontoffset          = membase+$4    ;currently used font offset -16
fontoffsetbank      = membase+$6    ;currently used font offset bank -8
vwftableoffset      = membase+$8    ;currently used vwf table offset -16
vwftableoffsetbank  = membase+$a    ;currently used vwf table offset bank -8
vwfbufferbase       = membase+$c    ;currently used vwf output ring buffer offset to be loaded for VWF RAM Output location calculation -16
vwfbufferbasebank   = membase+$e    ;currently used vwf output ring buffer offset bank -8
vrambase            = membase+$10   ;VRAM base offset for tilemap based VWF routines. -16
tilebase            = membase+$12   ;tile number base for tilemap based VWF routines. Should correspond to vram base above.-16
tileindex           = membase+$14   ;tile index for tilemap use in for tilemap based VWF routines. 0-1024 -16
vwfbuffersize       = membase+$16   ;size in bytes for vwfbuffer. Note last tile space is reserved for spillover tile. Minimum of 3 tiles space for proper ring/rollover operation.


;**********************************************************************************************************
;* Public Functions
;**********************************************************************************************************    
;nuvwf_Init - Must be called on Initialization before doing anything. Call this ASAP after game start if you added the NMI hook to DMATiles.
;nuvwf_SetInputFormat  - Must be called on init and any time you change the current input font to another format.
;nuvwf_SetOutputFormat - Must be called on init and any time you wish to change the output character format.
;nuvwf_FreshTile - Can be called any time to end the current tile and move to a new tile for VWFMode. Line breaks, string ends etc.
;nuvwf_AddToDMAQueue - Call when ready to add DMA Queue slot for all currently available new tile data to transfer. String Ends, Menus Ends, etc.
;nuvwf_DMATiles - Put in NMI hook and call to transfer and flush DMA Queue. Or, you may call it manually.
;nuvwf_Render - Will Render the current character based on the rendering mode and formats. Should be called once per character.
;nuvwf_ResetBuffer - Resets renderer including vwfbuffer, transfer location, bitpos etc. If in NMI mode, will queue and flush data before reusing buffer.
;nuvwf_RingBufferRollover - Rolls over spillover to beginning of buffer and resets buffer (but NOT bitpos/bitmask). Clears buffer full.
;nuvwf_AdvanceTile  - Advances render buffer positions by x tiles/characters.

;**********************************************************************************************************
;* General Expected Usage
;**********************************************************************************************************    
;set variable locations.
;include vwftable
;include font
;hook to initialize. Call to nuvwf_Init() and set all necessary variables (locations, modes, bases). Call to nuvwf_SetOutputFormat() and nuvwf_SetInputFormat()
;find font routine. Add hook to nuvwf_Render() after load character.
;application may grab resulting stored tilemap index and make sure you write that value to tilemap (as well as next value for spillover if needed).
;application may transfer VRAM buffered data. Could be NMI, could be forced transfer when buffer is full etc.
;hook for end of string, new tile/position reset etc. Call to FreshTile().
 

Back to top
 

ROMhacking.net - The central hub of the ROM hacking community.
WWW  
IP Logged
 
Pages: 1 2 3 
Send Topic Print
(Moderator: Nightcrawler)